Hello Wor.log

IT系大学生4人による備忘録のようなもの

tensorflow slimでxorを学習させる

CPPXのXです。

tensorflowのslimを使ってxorを学習させたいと思います。

以下のような事をslimを使ってやろうかなと思います。

gtech.hatenablog.com

環境

  • python 3.5.3
  • tensorflow 1.4.0

ソースコード

モデル

import tensorflow as tf
inputs = tf.placeholder("float", [None, 2], name="input") # 1層目 入力

x = tf.contrib.slim.fully_connected(inputs, 2, activation_fn=tf.nn.sigmoid, scope="fc1") # 2層目全結合 活性化関数:sigmoid
pred_value = tf.contrib.slim.fully_connected(x, 1, activation_fn=None, scope="fc2") # 3層目全結合 出力
outputs = tf.identity(pred_value, name="result") # 推論用

sess = tf.Session()
sess.run(tf.global_variables_initializer())


# 計算グラフの保存
saver = tf.train.Saver()
saver.save(sess, "defmodel/output")

全結合層は以下のもので定義できます。

tf.contrib.slim.fully_connected
  • inputs : 入力データ
  • num_outputs : 出力ノード数
  • activation_fn=relu : 活性化関数
  • normalizer_fn=None : 正規化関数
  • normalizer_params=None : 正規化関数に渡すパラメータ
  • weights_initializer=variance_scaling_initializer : 重みの初期化方法
  • weights_regularizer=None : 重みの正則化
  • biases_initializer=tensorflow.python.ops.init_ops.Zeros : バイアスの初期化方法
  • biases_regularizer=None : バイアスの正則化
  • reuse=None : 同じ変数スコープがある時につけとく
  • variables_collections=None
  • outputs_collections=None
  • trainable=True
  • scope=None : スコープの名前

tf.identityは引数をそのまま出力する関数です。

データ data.py

import numpy as np

train_input = np.array([
    [0, 0], [1, 1],
    [1, 0], [0, 1],
], dtype=np.float16) # 学習データ

train_label = np.array([
    [0], [0],
    [1], [1],
], dtype=np.float16) # ラベル

test_input = np.array([
    [1, 0], [0, 1], [1, 1], [0, 1],
    [0, 0], [1, 0], [1, 0], [1, 0],
    [1, 1], [0, 0], [1, 0], [1, 1],
    [0, 0], [1, 1], [0, 0], [0, 0],
    [0, 1], [0, 0], [0, 0], [0, 1],
    [0, 0], [1, 0], [0, 0], [1, 0],
    [0, 0], [1, 0], [1, 1], [1, 1],
    [0, 0], [0, 1], [1, 1], [0, 1],
    [0, 1], [0, 1], [1, 0], [0, 0],
    [0, 1], [0, 0], [1, 0], [1, 0],
], dtype=np.float16) # テストデータ

test_label = np.array([
    [1], [1], [0], [1],
    [0], [1], [1], [1],
    [0], [0], [1], [0],
    [0], [0], [0], [0],
    [1], [0], [0], [1],
    [0], [1], [0], [1],
    [0], [1], [0], [0],
    [0], [1], [0], [1],
    [1], [1], [1], [0],
    [1], [0], [1], [1],
]) # テストラベル

学習

import tensorflow as tf
from data import *
sess = tf.Session()

saver = tf.train.import_meta_graph("./defmodel/output.meta") # 計算グラフの読み込み

pred_value = sess.graph.get_tensor_by_name("fc2/BiasAdd:0") # 出力層

y = tf.placeholder("float", [None, 1])

with tf.name_scope("adam-optimizer"):
    loss = tf.losses.mean_squared_error(pred_value, y) # 平均二乗誤差
    optimizer = tf.train.AdamOptimizer().minimize(loss)

sess.run(tf.global_variables_initializer())

for i in range(10000):
    _, loss_val = sess.run([optimizer, loss], feed_dict={
        "input:0": train_input,
        y: train_label
    }) # 重みの更新
    if not i % 100:
        print("epoch: {}, loss_val: {}".format(i, loss_val))

# 重みを保存します。
saver = tf.train.Saver()
saver.save(sess, "./train/output")

学習用のデータは上の方で定義したものを用います。

計算グラフをはじめに読み込んで、それに対して学習に使うグラフを追加します。 以下の部分です。

with tf.name_scope("adam-optimizer"):
    loss = tf.losses.mean_squared_error(pred_value, y) # 平均二乗誤差
    optimizer = tf.train.AdamOptimizer().minimize(loss)

あとは、optimizerに対してrunすれば学習を勝手にやってくれます。

重みの統合

import tensorflow as tf

sess = tf.Session()
saver = tf.train.import_meta_graph("./defmodel/output.meta") # 計算グラフ
saver.restore(sess, tf.train.latest_checkpoint("./train")) # 学習した重み

saver.save(sess, "model/output")

推論部分の計算グラフと重みを別々に保存しているので、統合します。

学習部分のグラフも一緒に書いてしまって、そこから推論部分だけ保存する方法がよくわからなかったので今回のような形になってます。

確認

from data import *
import tensorflow as tf

sess = tf.Session()

# 計算グラフと重みの読み込み
saver = tf.train.import_meta_graph("./model/output.meta")
saver.restore(sess, tf.train.latest_checkpoint("./model"))

result = sess.run("result:0", {"input:0": test_input}) # 推論
print("accuracy:", np.sum(np.round(result) == test_label) / len(test_label)) # 精度確認