LoginSignup
25

More than 5 years have passed since last update.

TensorFlowチュートリアルやってみた CNN 第4回

Last updated at Posted at 2017-08-21

TensorFlowの公式チュートリアルをやってみました
前回までのNNでは結果がまだ悪い。
CNNを利用するとさらに精度が向上する。

CNN

CNNは画像認識や音声認識などでよく使われている。
「畳み込み層(Convolutionレイヤ)」,「プーリング層(Poolingレイヤ)」を組み合わせて作ることができる。

畳み込み処理

①3*3の正方形の畳み込みフィルタ-を入力データにかけていく。
畳み込みフィルターはストライドで移動距離を定める。1ピクセルの指定だと1ピクセルずつずらす。
28×28のデータに5×5のフ畳み込みィルターをかけると、24×24となって小さくなってしまう。←これに対応するためにゼロパディングがある。
ゼロパディングは入力のデータの周囲を0で囲む処理である。
②フィルター1回ので得られた計算の総和を求める。

プーリング処理

畳み込み処理の結果の次元を削減する処理。
例 2×2のプーリングフィルターがあるとする
maxプーリングは2×2のプーリングフィルターを畳み込み結果にかけて、その2×2の中の最大値を取得する。

活性化関数

今回使用するのはReLu関数
ReLu関数は以下のような関数
y = max(x, 0)
0以下の時は0
0以上の時はx
を返す関数

プログラムの流れ

データの読み込み

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot = True)

tensorflowのインポート

import tensorflow as tf

Sessionを立てる

今回はInteractiveSession()を使う

sess = tf.InteractiveSession()

入力xと正解ラベルy_の入れ物を作成する

placeholderで作成。ついでに、重みとバイアスも作成。

x = tf.placeholder(tf.float32, shape=[None, 784])
y_ = tf.placeholder(tf.float32, shape=[None,10])

W = tf.Variable(tf.zeros([783, 10]))
b = tf.Variable(tf.zeros([10]))

重みやバイアスの計算をする関数を作成

重みのinitial = tf.truncated_normal(shape, stddev=0.1)は初期値を与えている。正規分布の左右を切り取った形をしていて、stddevで標準偏差でデーターの散らばりを指定する。

バイアスのinitial = tf.constant(0.1, shape=shape)は値が0だと計算が進まないので'0.1'をバイアスで与える。

def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

畳み込み処理・畳み込み層

入力データとお耳を引数する。
strides=[1,1,1,1]は1ピクセルずつずらして適応するという意味。
padding='SAME'は左右に0をつけたようなデータに変換する(出力が入力と同じサイズになるように0で埋める)。

def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding='SAME')

プーリング層

サイズを小さくするために特徴量を抽出する層
ksize=[1,2,2,1] 2*2のブロックを適応する。
strides=[1,2,2,1]は2ピクセルずつずらして適応するという意味。
padding='SAME'は左右に0をつけたようなデータに変換する(出力が入力と同じサイズになるように0で埋める)。

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

第1畳込み層の設定

5*5の重みパッチを32個用意する。[パッチサイズ,入力チャンネル数,出力チャンネル数]。
バイアスは出力チャンネル数と同じだけ用意。

W_conv1 = weight_variable([5,5,1,32])
b_conv1 = bias_variable([32])

xの値を与える

レイヤーを適用するには、最初xに、画像の幅と高さに対応する第2および第3の次元、およびカラーチャネルの数に対応する最終次元で4dテンソルに変形する。tf.reshape(x, [-1, 28, 28, 1])は行列の形を変換している。最後の'1'は濃淡画像であることを示す。

x_image = tf.reshape(x, [-1, 28, 28, 1])

第1層の畳み込んだ結果

x_image、重みテンソルと畳み込み、バイアスを加え、ReLU関数を適用し、最後に最大プールを適用する。このmax_pool_2x2方法では、画像サイズを14x14に縮小する。

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

第2畳込み層の設定と畳み込んだ結果

W_conv2 = weight_variable([5,5,32,64])は5*5パッチが32種類の64個ある

2層目なので、h_pool1W_conv2の畳み込み計算

W_conv2 = weight_variable([5,5,32,64])
b_conv2 = bias_variable([64])

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

結合層

W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

Dropout

オーバーフィット(過学習)を減らすために、読み出しレイヤの前にドロップアウトを適用する。我々placeholderは、ドロップアウト中にニューロンの出力が保持される確率についてa を作成する。これにより、トレーニング中にドロップアウトをオンにし、テスト中にオフにすることができる。

keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

読み出し層

W_fc2 = weight_variable([1024,10])1024行×10列(0~9の数字の確立)

W_fc2 = weight_variable([1024,10])
b_fc2 = bias_variable([10])

y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2

モデルのトレーニングと評価

cross_entropy = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))

reduce_mean()は平均値を取る
tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv)は正解ラベル(y_)と推定値(y_conv)を比べる

tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)で学習の仕方を設定今回はAdamOptimizer

cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  for i in range(20000):
    batch = mnist.train.next_batch(50)
    if i % 100 == 0:
      train_accuracy = accuracy.eval(feed_dict={
          x: batch[0], y_: batch[1], keep_prob: 1.0})
      print('step %d, training accuracy %g' % (i, train_accuracy))
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

  print('test accuracy %g' % accuracy.eval(feed_dict={
      x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

完全なプログラム

上記の流れをまとめたものがこちら

mnist_cnn.py
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot = True)

import tensorflow as tf
sess = tf.InteractiveSession()

x = tf.placeholder(tf.float32, shape=[None, 784])
y_ = tf.placeholder(tf.float32, shape=[None,10])

W = tf.Variable(tf.zeros([783, 10]))
b = tf.Variable(tf.zeros([10]))

def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding='SAME')

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')

W_conv1 = weight_variable([5,5,1,32])
b_conv1 = bias_variable([32])

x_image = tf.reshape(x, [-1, 28, 28, 1])

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

W_conv2 = weight_variable([5,5,32,64])
b_conv2 = bias_variable([64])

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

W_fc2 = weight_variable([1024,10])
b_fc2 = bias_variable([10])

y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2

cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  for i in range(20000):
    batch = mnist.train.next_batch(50)
    if i % 100 == 0:
      train_accuracy = accuracy.eval(feed_dict={
          x: batch[0], y_: batch[1], keep_prob: 1.0})
      print('step %d, training accuracy %g' % (i, train_accuracy))
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

  print('test accuracy %g' % accuracy.eval(feed_dict={
      x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
出力
step 0, training accuracy 0
step 100, training accuracy 0.9
step 200, training accuracy 0.9
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
step 19900, training accuracy 1
test accuracy 0.9916

99%!! 前回は92%だったので精度が向上している。

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
25