LoginSignup
0
2

More than 5 years have passed since last update.

scikit-learn、Spark.ml、TensorFlow で Perceptron〜(4)TensorFlow

Posted at

TensorFlow はまだほとんど分かっていないので、線形回帰と同様、まだまだ見よう見まねです。
今回は簡単なニューラルネットなので、MNISTのtutorialを参考にしました。
mnist_softmax.py から今回使う部分を抜き出してみました。

mnnist_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] という具合に値を設定しておく必要があります。

tfPC.py
# 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に名前を変更しました。

tfPC.py
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 で与えています。

tfPC.py
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単位のマトリックスに対する予測です。テストデータと共に正解データも作っておきます。

tfPC.py
# (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]のリストにして、リターン値をリストで取得するとうまく取れたようです。

tfPC.py
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だとあまりいい結果にはなっていません。
predPC_with_tensorflow_100.png
predPC_with_tensorflow_1000.png

最後にプログラムの全体です。plotPCは、scikit-learn編を参照ください。

tfPC.py
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)
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2