[TensorFlow深度學習入門]實戰九·用CNN做科賽網TibetanMNIST藏文手寫數字資料集準確率98%+
阿新 • • 發佈:2018-12-22
[TensorFlow深度學習入門]實戰九·用CNN做科賽網TibetanMNIST藏文手寫數字資料集準確率98.8%+
我們在博文,使用CNN做Kaggle比賽手寫數字識別準確率99%+,在此基礎之上,我們進行對科賽網TibetanMNIST藏文手寫數字資料集訓練,來驗證網路的正確性。
- 問題描述
資料地址
背景描述
MNIST 資料集來自美國國家標準與技術研究所, National Institute of Standards and Technology (NIST). 訓練集由來自 250 個不同人手寫的數字構成, 其中 50% 是高中學生, 50% 來自人口普查局 (the Census Bureau) 的工作人員。自MNIST資料集建立以來,被廣泛地應用於檢驗各種機器學習演算法,測試各種模型,為機器學習的發展做出了不可磨滅的貢獻,其當之無愧為歷史上最偉大的資料集之一。在一次科研部門的會議上,我無意間看到了一位藏族夥伴的筆記本上寫著一些奇特的符號,好奇心驅使我去了解這些符號的意義,我的夥伴告訴我,這些是藏文當中的數字,這對於從小使用阿拉伯數字的我十分驚訝,這些奇特的符號竟有如此特殊的含義!我當即產生了一個想法,能不能讓計算機也能識別這些數字呢?這個想法得到了大家的一致認可,於是我們開始模仿MNIST來製作這些資料,由於對藏文的不熟悉,一開始的工作十分艱難,直到取得了藏學研究院同學的幫助,才使得製作工作順利完成。歷時1個月,超過300次反覆篩選,最終得到17768張高清藏文手寫體數字影象,形成了TibetanMNIST資料集。我和我的團隊為其而驕傲,因為它不僅僅是我們自行製作的第一個資料集,更是第一個藏文手寫數字的影象資料集!藏文手寫數字和阿拉伯數字一樣,在藏文中是一個獨立的個體,具有筆畫簡單,便於識別等優良特性。經過反覆地商議,我們決定將其完全開源,供所有的開發者自由使用,使其能發揮最大的價值!為了方便大家使用,我們將資料製作成了TFRecords以及npz檔案格式【檔案順序未打亂】,使其便於讀取,能很好地配合現有機器學習框架使用,當然,如果你覺得它還可以做的更好,你也可以自行DIY,我們將分割後的原始影象也上傳到了科賽平臺上,你可以將其做成你喜歡的任何資料格式,並建立各種有趣的專案。我和我的團隊衷心地希望你能在使用它的過程獲得樂趣!
最後,十分感謝科賽網提供的平臺,為資料的維護和推廣提供了極大的便利!能讓更多人看到藏文數字和原創資料的美,就是我們最大的收穫!
——袁明奇、才讓先木、湯吉安等
中央民族大學創業團隊巨神人工智慧科技
- 訓練程式碼
# coding: utf-8
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"
# In[1]:
import os
import numpy as np
import tensorflow as tf
from tensorflow.keras import utils
import pandas as pd
import matplotlib.pyplot as plt
excl = lambda x:os.popen( x).readlines()
# In[3]:
data_path = "./1CNN/TIbeiMNISTApp/TibetanMNIST/TibetanMNIST.npz"
data = np.load(data_path)
x_data = data['image'].reshape(17768, 784)
y_data = utils.to_categorical(data['label'], 10)
datas = []
for (x,y) in zip(x_data,y_data):
datas.append({"x":x/255,"y":y})
datas = np.array(datas)
np.random.shuffle(datas)
seq = 0.8
lens = len(datas)
trains = datas[0:int(seq*lens)]
tests = datas[int(seq*lens):]
x_train = []
y_train = []
x_test = []
y_test = []
for t in trains:
x_train.append(t["x"])
y_train.append(t["y"])
for t in tests:
x_test.append(t["x"])
y_test.append(t["y"])
x_train = np.array(x_train).astype(np.float32)
y_train = np.array(y_train).astype(np.float32)
x_test = np.array(x_test).astype(np.float32)
y_test = np.array(y_test).astype(np.float32)
lens_train,_=x_train.shape
lens_test,_=x_test.shape
lens_train,lens_test,x_train.shape,y_train.shape
# In[4]:
#訓練資料
x = tf.placeholder("float", shape=[None, 784],name="x")
#訓練標籤資料
y_ = tf.placeholder("float", shape=[None, 10],name="y_")
#把x更改為4維張量,第1維代表樣本數量,第2維和第3維代表影象長寬, 第4維代表影象通道數, 1表示灰度
x_image = tf.reshape(x, [-1,28,28,1])
#第一層:卷積層
conv1_weights = tf.get_variable("conv1_weights", [5, 5, 1, 32], initializer=tf.truncated_normal_initializer(stddev=0.1)) #過濾器大小為5*5, 當前層深度為1, 過濾器的深度為32
conv1_biases = tf.get_variable("conv1_biases", [32], initializer=tf.constant_initializer(0.0))
conv1 = tf.nn.conv2d(x_image, conv1_weights, strides=[1, 1, 1, 1], padding='SAME') #移動步長為1, 使用全0填充
relu1 = tf.nn.relu( tf.nn.bias_add(conv1, conv1_biases) ) #啟用函式Relu去線性化
#第二層:最大池化層
#池化層過濾器的大小為2*2, 移動步長為2,使用全0填充
pool1 = tf.nn.max_pool(relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
#第三層:卷積層
conv2_weights = tf.get_variable("conv2_weights", [5, 5, 32, 64], initializer=tf.truncated_normal_initializer(stddev=0.1)) #過濾器大小為5*5, 當前層深度為32, 過濾器的深度為64
conv2_biases = tf.get_variable("conv2_biases", [64], initializer=tf.constant_initializer(0.0))
conv2 = tf.nn.conv2d(pool1, conv2_weights, strides=[1, 1, 1, 1], padding='SAME') #移動步長為1, 使用全0填充
relu2 = tf.nn.relu( tf.nn.bias_add(conv2, conv2_biases) )
#第四層:最大池化層
#池化層過濾器的大小為2*2, 移動步長為2,使用全0填充
pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
#第五層:全連線層
fc1_weights = tf.get_variable("fc1_weights", [7 * 7 * 64, 1024], initializer=tf.truncated_normal_initializer(stddev=0.1)) #7*7*64=3136把前一層的輸出變成特徵向量
fc1_baises = tf.get_variable("fc1_baises", [1024], initializer=tf.constant_initializer(0.1))
pool2_vector = tf.reshape(pool2, [-1, 7 * 7 * 64])
fc1 = tf.nn.relu(tf.matmul(pool2_vector, fc1_weights) + fc1_baises)
#為了減少過擬合,加入Dropout層
keep_prob = tf.placeholder(tf.float32,name="keep_prob")
fc1_dropout = tf.nn.dropout(fc1, keep_prob)
#第六層:全連線層
fc2_weights = tf.get_variable("fc2_weights", [1024, 10], initializer=tf.truncated_normal_initializer(stddev=0.1)) #神經元節點數1024, 分類節點10
fc2_biases = tf.get_variable("fc2_biases", [10], initializer=tf.constant_initializer(0.1))
fc2 = tf.matmul(fc1_dropout, fc2_weights) + fc2_biases
#第七層:輸出層
# softmax
y_conv = tf.nn.softmax(fc2,name="y_conv")
y_conv_labels = tf.argmax(y_conv,1,name='y_conv_labels')
#定義交叉熵損失函式
y_conv = tf.clip_by_value(y_conv,1e-4,1.99)
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices=[1]))
#選擇優化器,並讓優化器最小化損失函式/收斂, 反向傳播
train_step = tf.train.AdamOptimizer(0.00008).minimize(cross_entropy)
# tf.argmax()返回的是某一維度上其資料最大所在的索引值,在這裡即代表預測值和真實值
# 判斷預測值y和真實值y_中最大數的索引是否一致,y的值為1-10概率
correct_prediction = tf.equal(y_conv_labels, tf.argmax(y_,1))
# 用平均值來統計測試準確率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32),name="accuracy")
# In[1]:
with tf.Session() as sess:
#開始訓練
srun = sess.run
srun(tf.global_variables_initializer())
saver = tf.train.Saver()
for i in range(4501):
start_step = i*100 % lens_train
stop_step = start_step+100
batch_x, batch_y = x_train[start_step:stop_astep,:], y_train[start_step:stop_step,:]
cross_entropy_val,_=srun([cross_entropy,train_step],feed_dict={x: batch_x, y_: batch_y, keep_prob: 0.5}) #訓練階段使用50%的Dropout
if i%100 == 0:
train_accuracy = srun(accuracy,feed_dict={x:x_test[:200], y_:y_test[:200], keep_prob: 1.0}) #評估階段不使用Dropout
print("step %d, loss %f test accuracy %f" % (i, cross_entropy_val, train_accuracy))
saver_path = saver.save(sess, "./1CNN/TIbeiMNISTApp/ckpt1/my_model.ckpt",global_step=i) # 將模型儲存到save/model.ckpt檔案
print("Model saved in file:", saver_path)
#在測試資料上測試準確率
print("final test accuracy %g" % srun(accuracy,feed_dict={x: x_test, y_: y_test, keep_prob: 1.0}))
- 執行結果
step 4100, loss 0.008919 test accuracy 0.985000
step 4200, loss 0.014542 test accuracy 0.980000
step 4300, loss 0.019433 test accuracy 0.985000
step 4400, loss 0.006040 test accuracy 0.985000
step 4500, loss 0.007214 test accuracy 0.990000
Model saved in file: /home/kesci/input/TibetanMNIST5610/ckpt1/my_model.ckpt-4500
final test accuracy 0.988745