もっと単純なところへ
昨日書いた記事はまあ、クラスタリングできるのスゲーってなったけど、でも、肝心の部分はブラックボックスだった。
肝心な部分というのは、どうやって重みを更新してるんだろう、という部分だ。
ということで、もっともっと原始的になってみよう。
そこで、Deep Learningの前世であるパーセプトロンを実装してみた。
アルゴリズムが単純だったので、以外と苦にならずに実装できた。
データとラベルはこんな感じに書いた。
ANDの場合
datas_and_labels = [ [np.array([0, 0]),np.array([-1])], [np.array([0, 1]),np.array([-1])], [np.array([1, 0]),np.array([-1])], [np.array([1, 1]),np.array([1])], ]
線形分離可能なデータの場合
datas_and_labels = [ [np.array([-1, 0.8]), np.array([-1])], [np.array([-1.2, 0.5]),np.array([-1])], [np.array([-0.7, 0.2]),np.array([-1])], [np.array([0.2, -1]), np.array([-1])], [np.array([0.3, -0.8]),np.array([-1])], [np.array([-0.3, 1]), np.array([1])], [np.array([-0.2, 0.9]) ,np.array([1])], [np.array([0.5, 0.6]), np.array([1])], [np.array([0.7, -0.1]), np.array([1])], [np.array([1, -0.4]), np.array([1])], ]
前回は0と1でラベルづけしたが、今回は-1と1でラベルづけした。
この-1と1は逆でもよい(はず)。
肝要なのは次の部分だろう。
def train(d, l, w): rho = 0.5 f = np.sign(function(w, d))# -1/1の2値で関数を判定 j = True if f != l: # 重み更新 w += l*rho*d j = False return f, w
どういうルールに基づいて重みを変えていくか。
元のラベルと予測のラベルが一致しなければ、重みを変更する。
係数rhoと、そのときのデータを掛けた量=デルタ分だけ。
そのデルタを、今の重みから引くのか、足すのかは、ラベルしだい。
やってみると、こんな感じになる
---epoch 9--- source label:-1, data:[-1. 0.8] predoct label:-1, weight:[ 0.15456065 0.74428118 0.52686861] OK source label:-1, data:[-1.2 0.5] predoct label:-1, weight:[ 0.15456065 0.74428118 0.52686861] OK source label:-1, data:[-0.7 0.2] predoct label:-1, weight:[ 0.15456065 0.74428118 0.52686861] OK source label:-1, data:[ 0.2 -1. ] predoct label:-1, weight:[ 0.15456065 0.74428118 0.52686861] OK source label:-1, data:[ 0.3 -0.8] predoct label:-1, weight:[ 0.15456065 0.74428118 0.52686861] OK source label:1, data:[-0.3 1. ] predoct label:1, weight:[ 0.15456065 0.74428118 0.52686861] OK source label:1, data:[-0.2 0.9] predoct label:1, weight:[ 0.15456065 0.74428118 0.52686861] OK source label:1, data:[ 0.5 0.6] predoct label:1, weight:[ 0.15456065 0.74428118 0.52686861] OK source label:1, data:[ 0.7 -0.1] predoct label:1, weight:[ 0.15456065 0.74428118 0.52686861] OK source label:1, data:[ 1. -0.4] predoct label:1, weight:[ 0.15456065 0.74428118 0.52686861] OK
おお!ちゃんと分類してる!!
ただし、XORなどの線形分離不可能なデータは分離できない。やったらめちゃくちゃになる。
参考にした「フリーソフトでつくる音声認識システム」って本では、このつぎにSVMの話になる。
んだけど、昨日作った多層パーセプトロンの話にもっていきたい。