TensorFlow はまだほとんど分かっていないので、線形回帰と同様、まだまだ見よう見まねです。
今回は簡単なニューラルネットなので、MNISTのtutorialを参考にしました。
mnist_softmax.py から今回使う部分を抜き出してみました。
import tensorflow as tf
# Create the model
x = tf.placeholder(tf.float32, [None, 784])
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))
y = tf.matmul(x, W) + b
# Define loss and optimizer
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
# Train
for _ in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
# Test trained model
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: mnist.test.images,
y_: mnist.test.labels}))
4.1 学習データの準備
scikit-learn、spark.ml との違いは、label として数値ではなく、出力ノード数分の配列を用意し、対応するインデックスの値を 1、それ以外を 0 にすることです。
つまり、label が 0 or 1 の場合、scikit-learn、spark.ml では y = 0 or 1 と、y という変数を一つ用意しておけば良かったのですが、TensorFlow では、1 * 2 の行列を用意し、y=0 の時は [1, 0]、y=1 の時は [0, 1] という具合に値を設定しておく必要があります。
# read train data
import csv
def readArrayWithCSV(dataFile):
features = []
labels = []
f = open(dataFile, 'r')
reader = csv.reader(f)
for row in reader:
features.append([float(row[0]), float(row[1])])
# row[2]==0 の時 [1,0]、row[2]==1 の時 [0,1] とする
l = [0.0] * 2
i = int(float(row[2]))
l[i] = 1.0
labels.append(l)
return features,labels
trainFile = 'trainPC.csv'
train_features,train_labels = readArrayWithCSV(trainFile)
4.2 モデルの作成
ここは mint_softmax の入力ノード数と出力ノード数の変更のみです。
y_ はわかりにくくなりそうだったので、labに名前を変更しました。
import tensorflow as tf
# Create the model
input_layer = 2
output_layer = 2
x = tf.placeholder(tf.float32, [None, input_layer])
W = tf.Variable(tf.zeros([input_layer, output_layer]))
b = tf.Variable(tf.zeros([output_layer]))
y = tf.matmul(x, W) + b
# Define loss and optimizer
lab = tf.placeholder(tf.float32, [None, output_layer])
cross_entropy = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=lab, logits=y))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
sessionを開始して、学習させます。データは csv から読み込んだ値を numpy.array に変換してそのまま feed_dict で与えています。
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
# Train
maxIter = 1000
for _ in range(maxIter):
batch_xs = np.array(train_features)
batch_labs = np.array(train_labels)
sess.run(train_step, feed_dict={x: batch_xs, lab: batch_labs})
4.3 モデルを用いた予測
評価は、scikit-learn、spark.ml 同様、(0,0)〜(10,5)の 0.1単位のマトリックスに対する予測です。テストデータと共に正解データも作っておきます。
# (0, 0)-(10, 5)の範囲で 0.1 単位のマトリックスを作る
npax = np.arange(0.0, 10.0, 0.1)
npay = np.arange(0.0, 5.0, 0.1)
npx, npy = np.meshgrid(npax, npay)
npxy = np.c_[npx.ravel(), npy.ravel()]
# eval
a = 0.4
b = 0.8
# a * npx + b < npy の時 [0,1]、そうでない時 [1,0] の配列=npz を作る
np1 = a * npx + b < npy
np0 = -np1
npz = np.c_[np0.ravel(), np1.ravel()].astype(np.float32)
mnistのサンプルでは出力が正解率のみですが、予測値も取得したいので、予測値の部分を predict = tf.argmax(y, 1) とし、run の第1引数を[predict, accuracy]のリストにして、リターン値をリストで取得するとうまく取れたようです。
predict = tf.argmax(y, 1)
correct_prediction = tf.equal(predict, tf.argmax(lab, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
npp, ac = sess.run([predict, accuracy], feed_dict={x: npxy, lab: npz})
npz = npp.reshape(npx.shape)
from plotPC import plotPC
title = "predPC_with_tensorflow"
plotPC(title, npx, npy, npz, a, b, maxIter, ac)
- argmax() は numpy.array.argmax() と同じく、行列の最大値のindexを取得します。学習データで y=0 → [1,0]、y=1 → [0,1] としましたが、逆をやってくれる関数になります。
>>> import numpy as np
>>> a = np.array([1,0])
>>> a.argmax()
0
>>> b = np.array([0,1])
>>> b.argmax()
1
>>> c = np.array([0,0,0,1])
>>> c.argmax()
3
繰り返し 100回と1000回の出力結果は以下です。100だとあまりいい結果にはなっていません。
最後にプログラムの全体です。plotPCは、scikit-learn編を参照ください。
import tensorflow as tf
import numpy as np
# read train data
import csv
def readArrayWithCSV(dataFile):
features = []
labels = []
f = open(dataFile, 'r')
reader = csv.reader(f)
for row in reader:
features.append([float(row[0]), float(row[1])])
# row[2]==0 の時 [1,0]、row[2]==1 の時 [0,1] とする
l = [0.0] * 2
i = int(float(row[2]))
l[i] = 1.0
labels.append(l)
return features,labels
trainFile = 'trainPC.csv'
train_features,train_labels = readArrayWithCSV(trainFile)
# Create the model
input_layer = 2
output_layer = 2
x = tf.placeholder(tf.float32, [None, input_layer])
W = tf.Variable(tf.zeros([input_layer, output_layer]))
b = tf.Variable(tf.zeros([output_layer]))
y = tf.matmul(x, W) + b
# Define loss and optimizer
lab = tf.placeholder(tf.float32, [None, output_layer])
cross_entropy = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=lab, logits=y))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
# Train
maxIter = 1000
for _ in range(maxIter):
batch_xs = np.array(train_features)
batch_labs = np.array(train_labels)
sess.run(train_step, feed_dict={x: batch_xs, lab: batch_labs})
# (0, 0)-(10, 5)の範囲で 0.1 単位のマトリックスを作る
npax = np.arange(0.0, 10.0, 0.1)
npay = np.arange(0.0, 5.0, 0.1)
npx, npy = np.meshgrid(npax, npay)
npxy = np.c_[npx.ravel(), npy.ravel()]
# eval
a = 0.4
b = 0.8
# a * npx + b < npy の時 [0,1]、そうでない時 [1,0] の配列=npz を作る
np1 = a * npx + b < npy
np0 = -np1
npz = np.c_[np0.ravel(), np1.ravel()].astype(np.float32)
predict = tf.argmax(y, 1)
correct_prediction = tf.equal(predict, tf.argmax(lab, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
npp, ac = sess.run([predict, accuracy], feed_dict={x: npxy, lab: npz})
npz = npp.reshape(npx.shape)
from plotPC import plotPC
title = "predPC_with_tensorflow"
plotPC(title, npx, npy, npz, a, b, maxIter, ac)