- 作者: 中井悦司
- 出版社/メーカー: 技術評論社
- 発売日: 2015/10/17
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
機械学習の次の分野として、分類アルゴリズムの勉強をしてみよう。分類アルゴリズムの中で、「パーセプトロン」は分類アルゴリズムの手法で、誤差関数を利用したアルゴリズムだ。
http://tensorflow.org/tutorials/pdes/index.md
今回は、上記の書籍の例を参考にして、2つのデータの分類から、それを分割する一次方程式を算出してみよう。 下記のように、
- データ1 : 20個 (中心 X=10, Y=25, データ範囲15)
- データ1 : 30個 (中心 X= 0, Y=15, データ範囲15)
分類アルゴリズムの定式化
まずは、パラメータを定義しよう。ここでは、上記の書籍に従って、一次方程式を定義する。W[0], W[1], W[2]を算出することになる。
分割する方程式に対して、
上側に分類されるデータ
- データが直線の上側に存在する(正解) : 0
- データが直線の下側に存在する(不正解) : 直線までの距離(正の数)
下側に分類されるデータ
- データが直線の下側に存在する(正解) : 0
- データが直線の上側に存在する(不正解) : 直線までの距離(正の数)
とする。この関数を誤差関数として、これを最小化(→0)とするように学習させれば良い訳だ。
誤差関数
ここで、上側に分類されるべきデータはt=1.0、下側に分類されるべきデータはt=-1.0とする。 すると、逆側にグループ化された場合(つまり負の数になる)と、正の数に変換して誤差とする。これを最小化する。
W = tf.Variable(tf.zeros([3])) X = tf.placeholder("float", [3]) t = tf.placeholder("float") y = tf.reduce_sum(tf.mul(W, X)) loss = tf.reduce_mean(tf.select(tf.greater(t*y, 0.0), 0.0, -t*y))
学習させる
まずは上側のデータを学習させ、下側のデータを学習させる。train_stepの引数として、
- W : 現在の学習中パラメータ(W[0],W[1],W[2])
- t : どちら側に分類されるべきか(t=1.0:上側、t=-1.0:下側)
とする。これを1000回繰替えして収束させていく。
for j in range(1000): for i in range(N1-1): next_grp = sess.run(grp0)[i] sess.run(train_step, feed_dict={X:next_grp, t: 1.0}) for i in range(N2-1): next_grp = sess.run(grp1)[i] sess.run(train_step, feed_dict={X:next_grp, t: -1.0})
学習結果から得られた直線のパラメータ
実行結果から、以下の結果が得られた。
$ python perceptron.py I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 1 I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 1 11.8301645736 33.7975375936 6.3721922867 20.0283013408 9.54279120396 20.5036238957 8.93012794294 25.4320740275 12.4558098147 24.1691295696 11.712123013 30.9916721474 7.96224594242 28.1186272312 -1.14441878366 20.1146535213 15.3815303446 16.3311509242 16.2858485809 28.276399798 11.318138601 32.5024510104 15.3145841787 33.169439917 9.86939868644 26.3050355861 5.65680444998 15.1521841596 8.99577395706 22.4053180223 1.27422690763 20.0788538154 16.2900669629 33.7956193422 6.34090862522 23.4361873553 8.274108156 24.7673157933 -1.03228478785 12.6707847273 -7.35302555303 10.0511432871 -13.0486602449 7.92992577728 -2.98514937222 1.52491558936 -2.96723904458 8.56845709249 0.947990357606 14.9240248797 1.42585958649 10.1330678777 2.23229826647 11.1247983005 3.02170577393 22.4440187862 3.22232243421 18.9654572865 -9.43096963229 5.17501555756 -7.87980106919 10.5603534195 -0.837600937693 -1.67276942188 -12.5366588778 3.34004169407 5.21500569061 20.765034053 0.675640920862 7.39868575156 -1.25457104952 9.37773237113 -1.66071067421 7.91445975321 -2.0735161238 7.17806619728 -4.44019379412 3.57946865387 -5.86664078923 16.1019402766 -0.454096769706 2.15289934949 -2.34753011619 1.2671985078 -1.55799390941 2.16329891383 7.21918787827 11.3084523064 -2.23623650298 18.1374053032 -12.6823310581 14.4050839961 7.3731135749 7.98695716502 4.1782871166 11.4991252024 answer = [ 0.51865494 0.15567437 -6.20004702]
得られたパラメータは、 - W[0] = 0.51865494 - W[1] = 0.15567437 - W[2] = -6.20004702
早速Excelに書いて表示させてみた。
お、色がちょっと薄くなっているが、ちゃんと分類できている!
ソースコード
import tensorflow as tf import numpy as np import random import math N1 = 20 Mu1 = [10,25] N2 = 30 Mu2 = [0, 10] Variances = 15 group0 = [] group1 = [] for idx in range(0, N1-1): radius = Variances * np.random.random() radian = np.random.uniform(0, 2*math.pi) x = radius * math.cos(radian) + Mu1[0] y = radius * math.sin(radian) + Mu1[1] group0.append([x, y, 1.0]) for idx in range(0, N2-1): radius = Variances * np.random.random() radian = np.random.uniform(0, 2*math.pi) x = radius * math.cos(radian) + Mu2[0] y = radius * math.sin(radian) + Mu2[1] group1.append([x, y, 1.0]) grp0 = tf.Variable(group0) grp1 = tf.Variable(group1) W = tf.Variable(tf.zeros([3])) X = tf.placeholder("float", [3]) t = tf.placeholder("float") y = tf.reduce_sum(tf.mul(W, X)) loss = tf.reduce_mean(tf.select(tf.greater(t*y, 0.0), 0.0, -t*y)) init = tf.initialize_all_variables() sess = tf.Session() sess.run(init) train_step = tf.train.GradientDescentOptimizer(0.01).minimize(loss) # print sess.run(loss, feed_dict={W:[3., 2., -10.], X:[5., 5., 1], t:-1.0}) # print sess.run(grp0)[0] for j in range(1000): for i in range(N1-1): next_grp = sess.run(grp0)[i] sess.run(train_step, feed_dict={X:next_grp, t: 1.0}) for i in range(N2-1): next_grp = sess.run(grp1)[i] sess.run(train_step, feed_dict={X:next_grp, t: -1.0}) for idx in range(0, N1-1): print group0[idx][0], group0[idx][1] print "" for idx in range(0, N2-1): print group1[idx][0], group1[idx][1] print "answer = " print sess.run(W)