

「TensorFlow&Kerasプログラミング実装ハンドブック」を参考に、TensorFlowでmnistの手書き数字を用いてCNNによる文字認識を実装しようとしました。  
しかし、認識精度が何度やっても0.1になってしまいます。おそらく予測の値が全て同じ数字になってしまっている(全て1と予想したり、全て7と予想している)ことが原因だと思いますが、どうしてそうなってしまうのかが分かりません。  
以下コードです。

[code]

    #データフローグラフ
    #学習率とエポック数を設定
    learning_rate = 0.01  #学習率
    epochs = 1500         #学習を繰り返す回数
    batch_size = 50      #ミニバッチのサイズ
    dropout = 0.5         #非ドロップアウト率
    
    #MNISTからデータを取得
    mnist = tf.keras.datasets.mnist
    (train_images, train_labels), (test_images, test_labels) = mnist.load_data()
    train_images = train_images.reshape(60000, 784)/255
    test_images = test_images.reshape(10000, 784)/255
    to_categorical = tf.keras.utils.to_categorical
    train_labels = to_categorical(train_labels)
    test_labels = to_categorical(test_labels)
    
    #入力層
    x = tf.placeholder(tf.float32,[None, 784])
    #画像データの二次元配列[データ数×784]を
    #[データ数×28×28×1]の4次元配列に変換
    out_img = tf.reshape(x,[-1, 28, 28, 1])
    
    #第1層 : 畳み込み層
    #2次元フィルター(3×3を32枚)
    f1 = tf.Variable(
        tf.truncated_normal([3, 3, 1, 32],stddev = 0.1))
    #畳み込みを行うopノード
    conv1 = tf.nn.conv2d(out_img, f1, strides=[1,1,1,1],padding='SAME')
    #フィルターのバイアス
    b1 = tf.Variable(
        tf.constant(0.1,shape=[32]))
    #活性化関数はReLU
    #出力 : (画像の枚数, 28, 28, 32)
    out_conv1 = tf.nn.relu(conv1 + b1)
    
    #第2層 : プーリング層
    #最大プーリングを適用
    out_pool1 = tf.nn.max_pool(
        out_conv1,
        ksize=[1,2,2,1],
        strides=[1,2,2,1],
        padding='SAME')
    
    #第3層 : 畳み込み層
    f2 = tf.Variable(
        tf.truncated_normal([3, 3, 32, 64],stddev = 0.1))
    #畳み込みを行うopノード
    conv2 = tf.nn.conv2d(out_pool1, f2, strides=[1,1,1,1],padding='SAME')
    #フィルターのバイアス
    b2 = tf.Variable(
        tf.constant(0.1,shape=[64]))
    #活性化関数はReLU
    #出力 : (画像の枚数, 28, 28, 32)
    out_conv2 = tf.nn.relu(conv2 + b2)
    
    #第4層 : プーリング層
    #最大プーリングを適用
    out_pool2 = tf.nn.max_pool(
        out_conv2,
        ksize=[1,2,2,1],
        strides=[1,2,2,1],
        padding='SAME')
    
    #ドロップアウト
    #非ドロップアウト率を保持するプレースホルダー
    keep_prob = tf.placeholder(tf.float32)
    #ドロップアウトを行うopノード
    out_drop = tf.nn.dropout(out_pool2, 1-keep_prob)
    
    #Flatten
    out_flat = tf.reshape(out_drop,[-1, 7*7*64])
    
    #第5層 : 全結合層
    #重み
    w_comb1 = tf.Variable(tf.truncated_normal([7*7*64,1024],stddev=0.1))
    #バイアス
    b_comb1 = tf.Variable(tf.constant(0.1, shape=[1024]))
    #活性化関数
    out_comb1 = tf.nn.relu(tf.matmul(out_flat,w_comb1)+b_comb1)
    
    #第6層 : 出力層
    #重み
    w_comb2 = tf.Variable(tf.truncated_normal([1024, 10],stddev=0.1))
    #バイアス
    b_comb2 = tf.Variable(tf.constant(0.1, shape=[10]))
    #活性化関数
    out = tf.nn.softmax(tf.matmul(out_comb1,w_comb2)+b_comb2)
    
    #正解データの型を定義
    #誤差関数
    t = tf.placeholder(tf.float32, [None, 10])
    loss = tf.reduce_mean(-tf.reduce_sum(t*tf.log(out), axis=[1]))
    
    #ミニマイザー
    train_op = tf.train.GradientDescentOptimizer(
        learning_rate).minimize(loss)
    
    #評価
    correct = tf.equal(
        tf.argmax(out, 1),tf.argmax(t, 1)
        )
    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))
    
    #変数を初期化するノード
    init_op = tf.global_variables_initializer()
    
[/code]

[code]

    #セッション部分
    with tf.Session() as sess:
        sess.run(init_op)
        for i in range(epochs):
            #ミニバッチを抽出
            #オフセット=回数×バッチサイズを訓練データの行数で割った余り
            offset = (i * batch_size) % 60000
            #オフセットの位置からミニバッチを抽出
            batch_train_images = train_images[
                offset:(offset + batch_size), :]
            batch_train_labels= train_labels[
                offset:(offset + batch_size),:]
            sess.run(train_op,
                        feed_dict={x:batch_train_images,
                        t:batch_train_labels,
                        keep_prob:dropout})
                #100回ごとにテストデータを使用して精度を出力
            if (i+1) % 100 == 0:
                acc_val = sess.run(accuracy,
                                      feed_dict={x:test_images,
                                         t:test_labels,
                                         keep_prob:1})
                print('Step %d: accuracy = %.2f' % (i+1, acc_val))
    
[/code]

以下出力結果です

[code]

    Step 200: accuracy = 0.10
    Step 300: accuracy = 0.10
    Step 400: accuracy = 0.10
    Step 500: accuracy = 0.10
    Step 600: accuracy = 0.10
    Step 700: accuracy = 0.10
    Step 800: accuracy = 0.10
    Step 900: accuracy = 0.10
    Step 1000: accuracy = 0.10
    Step 1100: accuracy = 0.10
    Step 1200: accuracy = 0.10
    Step 1300: accuracy = 0.10
    Step 1400: accuracy = 0.10
    Step 1500: accuracy = 0.10
    
[/code]

古いバージョンのTensorFlowで申し訳ないのですが、よろしくお願いします。


CC BY-SA 4.0
2022-08-02T06:46:19.507
90331
2022-08-02T06:46:19.507
53809
question
tensorflow
TensorFlow ver1.x CNNによる文字認識について