今度は、パーセプトロンを使って線形分離をしてみます。
適当に線形分離できそうなデータを以下のように作ってみました。
データは2次元平面上の点の座標(x, y)とそれぞれの正解ラベル1 or -1をつけています。
10, 20, 1
11, 30, 1
15, 30, 1
17, 35, 1
5, 25, 1
25, 35, 1
50, 40, 1
44, 38, 1
33, 30, 1
35, 35, 1
15, 8, -1
20, 2, -1
23, 11, -1
31, 22, -1
40, 35, -1
42, 29, -1
45, 39, -1
47, 37, -1
50, 39, -1
35, 20, -1
これを、テキストファイルとして読み込んで教師データとしています。
r = (x, y), 正解 t = 1or -1として、2入力、1出力のパーセプトロンをつくります。
重みw = (w0, w1)に対して、
出力層への入力は u = dot(w, r)となります。
識別関数fは
f = 1 ( if u >= 0)
f = -1 ( if u< 0)
とします。
教師データと出力が一致しない場合は
w := w + r* t
として重みw を更新します。
コードは以下のようになりました。
学習は120エポックとしました。
############### # パーセプトロンの実装 ############### import numpy as np import matplotlib.pyplot as plt ### (1) データ読み込み ### trainData = np.loadtxt('linerSeparateData.txt', delimiter=',', skiprows=0) trainDataX = trainData[:, 0:2] # (x, y) trainDataY = trainData[:, 2] # 正解ラベル # 重みwの初期化 w = np.random.rand(2) # activation function def f(x): if np.dot(w, x) >= 0: return 1 else: return -1 num_epoch = 120 #エポック数 countNum = 0 #カウンター ### 学習 ### for _ in range(num_epoch): for x, y in zip(trainDataX, trainDataY): if f(x) != y: # 予想が間違えたとき w = w + y*x # 重みを更新 # print result countNum+=1 print('{}: w = {}' .format(countNum, w)) # 結果の表示 x0 = np.arange(0, 50) plt.plot(trainDataX[trainDataY == 1, 0], trainDataX[trainDataY == 1, 1], 'o') plt.plot(trainDataX[trainDataY == -1, 0], trainDataX[trainDataY == -1, 1], 'x') plt.plot(x0, -w[0]/w[1] * x0) plt.show()
見た感じはうまく分離できているように見えます。