Contents
スポンサードリンク
ここではパーセプトロンについて実際のプログラムを、pythonの数理統計関数の説明していきながら述べていきます。
計算に用いたプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# -*- coding: utf-8 -*- # # Perceptronによる二項分類 # # 2015/04/24 ver1.0 # import numpy as np import matplotlib.pyplot as plt import pandas as pd from pandas import Series, DataFrame from numpy.random import multivariate_normal #------------# # Parameters # #------------# N1 = 20 # クラス t=+1 のデータ数 Mu1 = [15,10] # クラス t=+1 の中心座標 N2 = 30 # クラス t=-1 のデータ数 Mu2 = [0,0] # クラス t=-1 の中心座標 Variances = [15,30] # 両クラス共通の分散(2種類の分散で計算を実施) # データセット {x_n,y_n,type_n} を用意 def prepare_dataset(variance): cov1 = np.array([[variance,0],[0,variance]]) cov2 = np.array([[variance,0],[0,variance]]) df1 = DataFrame(multivariate_normal(Mu1,cov1,N1),columns=['x','y']) df1['type'] = 1 df2 = DataFrame(multivariate_normal(Mu2,cov2,N2),columns=['x','y']) df2['type'] = -1 df = pd.concat([df1,df2],ignore_index=True) df = df.reindex(np.random.permutation(df.index)).reset_index(drop=True) return df # Perceptronのアルゴリズム(確率的勾配降下法)を実行 def run_simulation(variance, data_graph, param_graph): train_set = prepare_dataset(variance) train_set1 = train_set[train_set['type']==1] train_set2 = train_set[train_set['type']==-1] ymin, ymax = train_set.y.min()-5, train_set.y.max()+10 xmin, xmax = train_set.x.min()-5, train_set.x.max()+10 data_graph.set_ylim([ymin-1, ymax+1]) data_graph.set_xlim([xmin-1, xmax+1]) data_graph.scatter(train_set1.x, train_set1.y, marker='o', label=None) data_graph.scatter(train_set2.x, train_set2.y, marker='x', label=None) # パラメータの初期値とbias項の設定 w0 = w1 = w2 = 0.0 bias = 0.5 * (train_set.x.mean() + train_set.y.mean()) # Iterationを30回実施 paramhist = DataFrame([[w0,w1,w2]], columns=['w0','w1','w2']) for i in range(30): for index, point in train_set.iterrows(): x, y, type = point.x, point.y, point.type if type * (w0*bias + w1*x + w2*y) <= 0: w0 += type * bias w1 += type * x w2 += type * y paramhist = paramhist.append( Series([w0,w1,w2], ['w0','w1','w2']), ignore_index=True) # 判定誤差の計算 err = 0 for index, point in train_set.iterrows(): x, y, type = point.x, point.y, point.type if type * (w0*bias + w1*x + w2*y) <= 0: err += 1 err_rate = err * 100 / len(train_set) # 結果の表示 linex = np.arange(xmin-5, xmax+5) liney = - linex * w1 / w2 - bias * w0 / w2 label = "ERR %.2f%%" % err_rate data_graph.plot(linex, liney, label=label, color='red') data_graph.legend(loc=1) paramhist.plot(ax=param_graph) param_graph.legend(loc=1) # Main if __name__ == '__main__': fig = plt.figure() # 2種類の分散で実行 for c, variance in enumerate(Variances): subplots1 = fig.add_subplot(2,2,c+1) subplots2 = fig.add_subplot(2,2,c+2+1) run_simulation(variance, subplots1, subplots2) fig.show() |
最初のパラメータのところは問題ないと思います。
Variancesdで2種類の分散を用意しているのは、分散が大きい時と小さい時で、分類結果を比較するためです。
分散が大きい時は、二つのデータ群が多かれ少なかれ、重なる領域が生じ、綺麗に二つのデータ群を直線で分割できなくなります。
前ページで言えば、総誤差ΣEは小さくすることはできるが、0にならないということになります。
分散が小さい時は二つのデータ群はそれぞれの中心座標からあまり離れることなく、データが分布するので、領域が明確になり、直線で二つのデータ群を分割できます。
前ページで言えば誤差関数=0の状態です。
データセットの用意に関して
1 2 3 4 5 6 7 8 9 10 11 12 |
# データセット {x_n,y_n,type_n} を用意 def prepare_dataset(variance): cov1 = np.array([[variance,0],[0,variance]]) cov2 = np.array([[variance,0],[0,variance]]) df1 = DataFrame(multivariate_normal(Mu1,cov1,N1),columns=['x','y']) df1['type'] = 1 df2 = DataFrame(multivariate_normal(Mu2,cov2,N2),columns=['x','y']) df2['type'] = -1 df = pd.concat([df1,df2],ignore_index=True) df = df.reindex(np.random.permutation(df.index)).reset_index(drop=True) return df |
- varianceは標本から分散を推定する場合に用いるコマンドです。
「分散」とはデータの中心からのバラツキの度合いです。
ここでは、関数の変数として使われていますので、注意してください。
1 |
cov1 = np.array([[variance,0],[0,variance]]) |
上記は二重にネストした配列を作成しています。
スポンサードリンク
- multivariate_normal
このコマンドは
1 |
multivariate_normal(平均,共分散行列,データ数) |
のように用いると多次元正規分布の乱数を生成してくれるみたいです。
よくわからないので、途中でreturnの前にprint df1を挟んで確認してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
x y type 0 13.548830 7.319199 1 1 10.341402 7.753353 1 2 14.192551 6.464979 1 3 16.868014 12.057804 1 4 19.064857 12.832494 1 5 10.961612 18.200402 1 6 9.159768 10.695429 1 7 18.179028 8.704171 1 8 17.499760 8.776130 1 9 3.024615 12.567991 1 10 11.423902 17.803245 1 11 13.909609 7.592572 1 12 10.484846 12.521170 1 13 20.650581 2.027669 1 14 16.820236 6.351919 1 15 22.500461 -0.589681 1 16 12.777110 3.223326 1 17 13.905127 10.789665 1 18 16.579758 5.997613 1 19 17.501150 10.310128 1 x y type 0 13.905825 11.098330 1 1 12.061756 12.014905 1 2 18.717352 7.898807 1 3 15.377015 -0.464237 1 4 10.934587 0.994783 1 5 13.515569 9.571461 1 6 4.823344 8.320701 1 7 11.675756 15.805615 1 8 17.041173 15.598456 1 9 15.099372 8.683218 1 10 10.843983 7.013562 1 11 17.368617 14.724556 1 12 16.922832 18.497884 1 13 16.789654 17.806064 1 14 11.519738 4.859890 1 15 16.890872 13.313301 1 16 23.901925 16.935261 1 17 18.856928 7.388827 1 18 9.189150 12.240367 1 19 18.495711 6.111069 1 |
Dateframeコマンドで、マトリクスを作成するみたいです。
columnsでインデックスの指定、さらにマトリクスに行とインデックスを追加する場合には別で
1 |
df1['type'] = 1 |
と書いていますね。
- pd.concat
よくわからないのでprint
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
x y type 0 7.914411 13.766897 1 1 12.421795 6.464875 1 2 12.533345 4.408905 1 3 21.651654 11.510633 1 4 9.024532 9.888576 1 5 13.050861 8.222459 1 6 16.797658 8.109874 1 7 14.129778 10.491189 1 8 12.621794 9.738241 1 9 16.947550 5.157104 1 10 19.978489 17.952185 1 11 17.457621 5.928273 1 12 13.354854 6.460380 1 13 14.297729 10.207718 1 14 18.983682 11.176899 1 15 6.632770 12.403663 1 16 15.067818 17.240273 1 17 15.165991 10.061345 1 18 17.576370 11.472352 1 19 18.691837 12.371169 1 20 -2.139159 -5.673129 -1 21 0.860456 8.090770 -1 22 -5.788432 -0.936744 -1 23 0.003875 5.616296 -1 24 -2.007876 -3.518680 -1 25 -6.597750 -5.073692 -1 26 -8.121631 -0.477203 -1 27 5.887535 -4.732506 -1 28 6.464496 -1.334255 -1 29 -2.903128 -5.044807 -1 30 10.253523 0.512712 -1 31 0.105470 -4.930637 -1 32 -0.714381 2.761888 -1 33 3.080850 0.623442 -1 34 1.912794 3.307122 -1 35 4.741883 -1.947296 -1 36 -1.050251 -0.054052 -1 37 1.192007 -5.993319 -1 38 4.953090 5.156868 -1 39 -1.945456 0.210915 -1 40 -2.795425 2.085100 -1 41 -3.311139 -5.233880 -1 42 3.239319 -3.939893 -1 43 4.185058 -6.196983 -1 44 1.422154 -2.202211 -1 45 -1.660466 -2.584244 -1 46 9.114114 0.187492 -1 47 -0.881801 -1.334942 -1 48 -3.071802 2.330590 -1 49 8.820899 0.254645 -1 |
linuxのcatコマンドからきているのでしょう。df1とdf2を縦に連結しています。
もう一つ下のdfも不明なので、これまたprint.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
x y type 0 17.390853 15.367978 1 1 17.990108 11.545457 1 2 1.155451 7.671224 -1 3 -6.259384 9.301330 -1 4 1.643164 -3.039337 -1 5 10.112192 -1.451187 -1 6 13.807407 7.913411 1 7 18.728826 11.482187 1 8 2.767394 0.334469 -1 9 8.751170 14.078460 1 10 -16.288021 -0.206298 -1 11 -8.232353 5.332661 -1 12 -2.121590 6.468324 -1 13 -0.901305 -2.544183 -1 14 1.207815 -4.698115 -1 15 8.524593 5.163455 1 16 -2.433254 -7.249434 -1 17 3.246779 -1.998557 -1 18 4.806579 1.077874 -1 19 18.386209 10.664266 1 20 12.735496 8.498020 1 21 -5.269391 3.545209 -1 22 8.310496 12.382170 1 23 -5.693958 -3.293665 -1 24 23.930117 12.191825 1 25 -1.509779 -1.376394 -1 26 14.271644 8.313317 1 27 3.709599 -1.454642 -1 28 7.624723 -4.033262 -1 29 18.071709 1.339816 1 30 7.830113 10.582230 1 31 13.194158 8.418753 1 32 -5.212267 0.775280 -1 33 -12.486186 -1.242689 -1 34 17.036860 9.470380 1 35 4.058375 9.532520 1 36 5.310115 2.355995 -1 37 -8.569930 -0.682856 -1 38 14.093141 13.021086 1 39 3.568152 2.386507 -1 40 -1.125541 7.764457 -1 41 -0.909560 1.406511 -1 42 -8.515567 1.929022 -1 43 11.491522 14.730818 1 44 5.812418 -5.219397 -1 45 10.450621 14.619904 1 46 -3.924372 -0.461741 -1 47 13.852815 3.554839 1 48 1.083237 2.846657 -1 49 -3.847790 9.437395 -1 |
df.reindex(np.random.permutationでランダムに並び替えています。
その次のreset_index(drop=True)で左端のインデックスのみ数字順に並び替えています。
以降ではパーセプトロンのアルゴリズムの部分と計算結果について述べていきます。
スポンサードリンク
「パーセプトロンのアルゴリズム(python編)」への2件のフィードバック