多クラス分類にone_hot関数を使う

2016-09-03

ニューラルネットワークで多クラス分類をする場合、出力層として分類したいクラスの数と同じ次元のベクトルを出力する。訓練時にはその出力に対して、教師ラベルに対応する要素だけが1で他は0であるOne hotベクトルを教師データとすることで学習させることができる。

TensorflowのMNISTチュートリアルではデータの読み込み時にnumpyの関数を使ってラベルからOne hotベクトルをあらかじめ作成しているが、Tensforflowのone_hot関数を使えばラベルを直接入力することができる(one_hot後からAPIに追加された模様)。

使い方

import tensorflow as tf

labels = tf.placeholder(tf.int64, [None])
y_ = tf.one_hot(labels, depth=3, dtype=tf.float32)
  • 教師ラベルを入力するプレースホルダーlabelsを作り、それをtf.one_hotに渡せばよい。
  • depthに分類するクラスの数を指定する。

動かしてみる

with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
teacher = [1, 2, 0]
print sess.run(y_, feed_dict={labels: teacher})
# [[ 0. 1. 0.]
# [ 0. 0. 1.]
# [ 1. 0. 0.]]
  • 試しに[1, 2, 0]を教師ラベルとしてlabelsに与えてやると、One hotベクトル化されたテンソル[[ 0. 1. 0.], [ 0. 0. 1.], [ 1. 0. 0.]]が出力される。

訓練で使用

  • 出力されたy_を使えば後はチュートリアルと同様に、NNの出力結果yを使って二乗誤差やクロスエントロピーでコストを計算してやれば訓練できる。
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

判定で使用

  • 認識率をNNの出力結果の一番大きな要素が教師ラベルと等しいかどうかで計算するが、その際tf.argmaxint64型で出力するので、教師ラベルのプレースホルダーlabelsint64で作成しておくと都合がいい。
  • tf.argmax(y_, 1)で教師ラベルを復元する必要はなく、直接labelsequalで比較すればよい
# yはNNの出力
correct_prediction = tf.equal(tf.argmax(y, 1), labels)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))