[TensorFlow深度学习入门]实战九·用CNN做科赛网TibetanMNIST藏文手写数字数据集准确率98%+

[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

猜你喜欢

转载自blog.csdn.net/xiaosongshine/article/details/84780969
今日推荐