1. 程式人生 > >北大人工智慧網課攻略[2]:mnist手寫數字分類,並測試自己的手寫體

北大人工智慧網課攻略[2]:mnist手寫數字分類,並測試自己的手寫體


個人程式如下:
連結: https://pan.baidu.com/s/1Yy0Dg9AOGntDIdb4VGle4A 提取碼: zwv4


北大人工智慧網課考試一是手寫數字體識別,與常見的入門題目唯一的區別是我們需要再讀入老師手寫的圖片進行識別。編寫一下讀取普通圖片的程式帶入模型即可。
由於老師的程式學習率給的很低,所以執行老師的程式你會發現速度非常慢。我將學習率提高了十倍,也能在幾分鐘內達到94%識別率,所以我認為這類簡單識別可以使用千分之一的學習率,當然變學習率也是可行的。
之後把模型從一般的CNN變成lenet5準確度下降到了83%,果然卷積核個數與大小確實對系統影響很大。
使用儲存模型加呼叫模型編寫程式。
程式如下:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import matplotlib.pyplot as plt
import os
from PIL import Image

BATCH_SIZE = 50
learning_rate = 0.001       

def get_real_test():
    file_dir = '/home/emin/Temp/Tensorflow/num1'
    image_list = []
    label_list =
[] for file in os.listdir(file_dir): image_list.append(file_dir + '/' +file) label_list.append(int(file[0])) for i in range(0,10): image1 = Image.open(image_list[i]) image1 = image1.resize([28, 28]) plt.imshow(image1) images1 = np.array(image1)[:,
:,0] images1=images1.astype(float) img = images1.reshape(1,784) if i==0: img_last=img else: img_last=np.vstack((img_last,img)) print(label_list, 'real number') return img_last def train(): mnist = input_data.read_data_sets('/home/emin/Temp/Tensorflow/Me/lenet5/data', one_hot=True) # they has been normalized to range (0,1) test_x = mnist.test.images[:2000] test_y = mnist.test.labels[:2000] tf_x = tf.placeholder(tf.float32, [None, 28*28]) / 255. image = tf.reshape(tf_x, [-1, 28, 28, 1]) tf_y = tf.placeholder(tf.int32, [None, 10]) conv1 = tf.layers.conv2d(image, 32, 5, 1, 'same', activation=tf.nn.relu) pool1 = tf.layers.max_pooling2d(conv1, 2, 2) conv2 = tf.layers.conv2d(pool1, 64, 5, 1, 'same', activation=tf.nn.relu) pool2 = tf.layers.max_pooling2d(conv2, 2, 2) flat = tf.reshape(pool2, [-1, 7*7*64]) output = tf.layers.dense(flat, 10) loss = tf.losses.softmax_cross_entropy(onehot_labels=tf_y, logits=output) # compute cost train_op = tf.train.AdamOptimizer(learning_rate).minimize(loss) accuracy = tf.metrics.accuracy( # return (acc, update_op), and create 2 local variables labels=tf.argmax(tf_y, axis=1), predictions=tf.argmax(output, axis=1),)[1] sess = tf.Session() init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer()) # the local var is for accuracy_op sess.run(init_op) # initialize var in graph saver = tf.train.Saver() for step in range(1000): b_x, b_y = mnist.train.next_batch(BATCH_SIZE) _, loss_ = sess.run([train_op, loss], {tf_x: b_x, tf_y: b_y}) if step % 50 == 0: accuracy_, flat_representation = sess.run([accuracy, flat], {tf_x: test_x, tf_y: test_y}) print('Step:', step, '| train loss: %.4f' % loss_, '| test accuracy: %.2f' % accuracy_) saver.save(sess, "my_net/save_net.ckpt") def test(): tf_x = tf.placeholder(tf.float32, [None, 28*28]) / 255. image = tf.reshape(tf_x, [-1, 28, 28, 1]) conv1 = tf.layers.conv2d(image, 32, 5, 1, 'same', activation=tf.nn.relu) pool1 = tf.layers.max_pooling2d(conv1, 2, 2) conv2 = tf.layers.conv2d(pool1, 64, 5, 1, 'same', activation=tf.nn.relu) pool2 = tf.layers.max_pooling2d(conv2, 2, 2) flat = tf.reshape(pool2, [-1, 7*7*64]) output = tf.layers.dense(flat, 10) sess = tf.Session() saver = tf.train.Saver() saver.restore(sess, "my_net/save_net.ckpt") test_output = sess.run(output, {tf_x: get_real_test()}) pred_y = np.argmax(test_output, 1) print(pred_y, 'prediction number') def main(): # first train then restart your program and test train() # test() if __name__ == '__main__': main()

主要就是三個方面,一是提取老師手寫圖片的子函式,二是使用訓練和測試集進行訓練,並將網路結構儲存的函式,三是呼叫儲存的網路結構,進行老師的手寫體識別。
然而對於老師的手寫體識別準確度極低:
在這裡插入圖片描述在這裡插入圖片描述
就對了兩個,然而對於手寫體自己的訓練集和測試集,準確度倒是非常高。
在這裡插入圖片描述
所以我決定自己寫一些相對字型較粗的數字進行測試。

在這裡插入圖片描述在這裡插入圖片描述
稍微好一點。但是這個準確度還是太慘了。所以問題出在程式呢?還是影象壓縮的處理呢?
我決定先從影象壓縮的處理開始。使用了各種濾波方法:
https://blog.csdn.net/guduruyu/article/details/71404941
加上以前經驗,決定還是中值濾波好。然而對準確率沒有什麼用。

然後我進行了在測試集準確度為90%時的實驗,很遺憾,我手寫的數字識別準確度也只有10%,很神奇,測試集準確度差了5%,我手寫數字識別的準確度竟然從50%下降到10%。

同時如果影象集中只有3, 2, 5, 3, 1這五張及其複製,無論如何準確度都是百分之百,說明影響準確度的變數是圖片本身問題。

之後我看了一下訓練集的影象(把一組784個元素提出來,之後reshape一下),我恍然大悟。
在這裡插入圖片描述
我們的字型色黑和背景色白,而訓練和測試集剛好相反!
好的,我們反色一下。由於老師的影象是四通道的png影象,所以無法直接用PIL.ImageOps反色,要先儲存成jpg然後反色。

import os
from PIL import Image
import PIL.ImageOps
file_dir = '/home/emin/Temp/Tensorflow/num' 
image_list = []
label_list = []
for file in os.listdir(file_dir):
    image_list.append(file_dir + '/' +file)
    label_list.append((file[0]))
for i in range(0,10):
    image1 = Image.open(image_list[i])
    image1.save('/home/emin/Temp/Tensorflow/num1/' + label_list[i]+ '.jpg')    
file_dir1 = '/home/emin/Temp/Tensorflow/num1' 
image_list1 = []
label_list1 = []
for file in os.listdir(file_dir1):
    image_list1.append(file_dir1 + '/' +file)
    label_list1.append((file[0]))    
for i in range(0,10):
    image1 = Image.open(image_list1[i])
    inverted_image = PIL.ImageOps.invert(image1)
    inverted_image.save('/home/emin/Temp/Tensorflow/num1/' + label_list1[i]+ '.jpg')

先實我的手寫體。

在這裡插入圖片描述
我手寫的準確度還是那樣。
再看老師的。
在這裡插入圖片描述
老師手寫的反色後,準確度百分之百,這驗證了對於簡單的影象識別,神經網路任然是靠顏色對圖片進行識別,相反的顏色同樣的形狀可能是0%與100%準確度的差距。