【TensorFlow】アヤメの分類をする

 

こんにちは。のっくん(@yamagablog)です。

 

今日の記事では、TensorFlowを使ったアヤメの分類にチャレンジしたいと思います。

 

「TensorFlowの使い方がよく分からない」

 

そんな方に読んでいただければと思います。

 

[toc]

 

使用するデータセット

 

以下のような花びらの長さとアヤメの種類が入ったcsv形式のデータを使用します。

 

 

表示は6個だけですが、全部で150個あります。

 

このデータは前回の記事でも使用していまして、ダウンロード方法は以下のページをみてください。

 

https://ymgsapo.com/classify-flower/

 

入力データとラベルの作成

 

入力データは花の種類を推測するのに使用するデータです。花びらやガクの長さを含めた4つです。

 

ラベルというのはアヤメの種類です。アヤメの種類は3種類でしたね。

 

pandasを使って、入力データとラベルの列を取り出してみます。

 

import pandas as pd

iris_data = pd.read_csv("iris.csv",encoding="utf-8")

y_labels = iris_data.loc[:,"Name"]

x_data = iris_data.loc[:,["SepalLength","SepalWidth","PetalLength","PetalWidth"]]

 

loc[:,”Name”]でアヤメの種類だけ取り出しています。第一引数に、「:」を指定することで全部の行を取り出しています。ちなみに、「:9」とかにすると9行だけ取り出せます。

 

ラベルをOne-Hotベクトルにする

 

One-Hotベクトルは1つだけ1であとは0のベクトルです。[0,0,1]とかですね。

 

TensorFlowを使う場合、ラベルをこの形式にしなければいけません。

 

変換用の辞書を作って、for文で回して変換します。

 

labels = {
    'Iris-setosa':[1,0,0],
    'Iris-versicolor':[0,1,0],
    'Iris-virginica':[0,0,1]
}

y_nums=[]
for v in y_labels:
    y_nums.append(labels[v])

pprint.pprint(y_nums)

 

実行してみると、、

 

[[1, 0, 0],
 [1, 0, 0],
 [1, 0, 0],
 [1, 0, 0],
 [1, 0, 0],
 [1, 0, 0],

 

変換できました。

 

学習用とテスト用に分離

 

入力データ(x)とラベル(y)を学習用に8割、テスト用に2割になるようにそれぞれ分割します。

 

from sklearn.model_selection import train_test_split

x_train,x_test,y_train,y_test = train_test_split(x_data,y_nums,train_size=0.8)

 

ちなみにこのコードを実行すると以下のようにワーニングが出ますが、x_trainをみてみるとちゃんと分割されてたので気にしないことにします。

 

/home/matsu/anaconda3/envs/digits/lib/python3.6/site-packages/sklearn/model_selection/_split.py:2026: 
FutureWarning: From version 0.21, test_size will always complement train_size unless both are specified.
  FutureWarning)

 

おそらく、「(test_sizeとtrain_size)が両方記述されていないと、test_sizeからtrain_sizeを補完するぞ」と言っているようです。

学習とテストの実行

 

学習アルゴリズムを記載して、学習とテストを実行してみます。

 

import tensorflow as tf

# あやめの四次元の入力値xと三次元の出力値y_
x = tf.placeholder(tf.float32,[None, 4])
y_ = tf.placeholder(tf.float32, [None,3])

# 重み xが4,yが3なので4*3にする
w = tf.Variable(tf.zeros([4,3]))

# バイアス yが3なので3にする
b = tf.Variable(tf.zeros([3]))

y = tf.nn.softmax(tf.matmul(x,w)+b)


cross_entropy = -tf.reduce_sum(y_ * tf.log(y))
optimizer = tf.train.AdamOptimizer(0.05)
train = optimizer.minimize(cross_entropy)

predict = tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(predict, tf.float32))


# セッションを開始して変数を初期化
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

# 学習を行う 300回繰り返すことで、変数wやbの値が調整されていく
train_feed_dict = {x: x_train,y_: y_train}
for step in range(300):
    sess.run(train, feed_dict=train_feed_dict)

# テストデータを使って、正解率を求める
acc = sess.run(accuracy, feed_dict={x:x_test,y_:y_test})
print("正解率=", acc)

 

いきなりコードが長くなってしまいました。

 

学習アルゴリズムは難しいので全て理解する必要はありません。

 

クロスエントロピーはクラス分類でよく使われる誤差関数の1つで、アダム方は確率的勾配降下法の1つです。

 

あまり深く考えずに、最初のx、y_、重み、バイアスの次元を設定できればそれで良いかと思います。

 

実行すると以下のような値が出ました。

 

正解率= 0.93333334

 

[speech_bubble type=”ln” subtype=”L1″ icon=”ilust/cat2_1_idea.png” name=”ネコ”]コードは複雑なのに、機械学習と精度ほとんど変わらないじゃん![/speech_bubble]

 

確かにそうですねw

 

ちなみに機械学習でやってみた記事は以下にありますので良かったらどうぞ。

 

https://ymgsapo.com/classify-flower/

 

プレースホルダーとか知りたい方は以下の記事もどうぞ。

 

https://ymgsapo.com/tensorflow-beginner/

 

以上です、お疲れ様でした。

 

参考

 

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog