先生、旧姓で呼んでもいいですか?

雑記です。勉強したことなど

もっと単純なところへ

昨日書いた記事はまあ、クラスタリングできるのスゲーってなったけど、でも、肝心の部分はブラックボックスだった。
肝心な部分というのは、どうやって重みを更新してるんだろう、という部分だ。
ということで、もっともっと原始的になってみよう。
そこで、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

f:id:joumyakun:20160225155525p:plain

おお!ちゃんと分類してる!!

ただし、XORなどの線形分離不可能なデータは分離できない。やったらめちゃくちゃになる。
参考にした「フリーソフトでつくる音声認識システム」って本では、このつぎにSVMの話になる。
んだけど、昨日作った多層パーセプトロンの話にもっていきたい。