Tensorflow入门——单层神经网络识别MNIST手写数字

作者: Hongtao洪滔 | 来源:发表于2019-03-30 01:22 被阅读14次

    手写数字识别是一个非常经典的机器学习项目,这篇文章,我们就通过Kaggle上这个经典项目,学习如何用Tensorflow和Keras用最简单的单层神经网络,来识别手写数字。

    同样的,为了方便与读者交流,所有的代码都放在了这里:

    Repository:

    https://github.com/zht007/tensorflow-practice

    1. 数据下载和预处理

    Kaggle的项目页面可以下载两个csv文件,"train.csv"包含数据和标签,"test.csv"仅包含带验证数据。你可以用train.csv训练自己的模型,然后再用这个模型识别test.csv中的手写数字,并将其分类,最后将结果上传至Kaggle的项目,查看正确率和全球排名。

    通过pands的read_csv方法读取csv文件,分离数据和标签,并分用scikit-learn 中的train_test_split,分出训练集和验证集。

    labeled_images = pd.read_csv('train.csv')
    images = labeled_images.iloc[:,1:]
    labels = labeled_images.iloc[:,:1]
    train_images, test_images,train_labels, test_labels = train_test_split(images, labels, test_size=0.01)
    

    2. Batch training 的帮助函数

    这个部分虽然比较难,但是不是这篇文章的重点,就此略过,主要作用是从训练数据集中顺序取出指定数量的batch,在Session中给模型训练。帮助函数处理之后数据的shape为[batch_size, 28,28,1]

    帮助函数还有一个作用,就是将标签onehot encode。onehot-encoded 的标签shape为[batch_size, 10]。

    3. 创建模型

    单层神经网络,神经元个数就等于输出的类别的个数,手写数字分成0到9,一共10个类别,神经元个数就是10。

    神经网络是全链接的,我们需要把输入的28*28个像素的二维图片,拆解拼凑成一个784个像素点的一维向量。此时输入的feature数就是784。

    输入的feature数和输出的类别数共同决定了权重W和偏移b的shape

    初始化权重W1和偏移B1:

    W1 = tf.Variable(tf.truncated_normal([784, 10], stddev=0.1))  # 784 = 28 * 28
    B1 = tf.Variable(tf.ones([10])/10)
    

    单层神经网络通过softmax的激活,就能得到最终的结果

    XX = tf.reshape(X,[-1,784])
    Ylogits = tf.matmul(XX, W1) + B1
    Y = tf.nn.softmax(Ylogits)
    

    Cross_entropy 可以直接通过公式计算

    cross_entropy = -tf.reduce_mean(Y_true * tf.log(Y)) * 1000.0 
    

    也可以用tensorflow中自带的,如何选择我在前面的文章中已经介绍过了。

    cross_entropy = tf.losses.softmax_cross_entropy(onehot_labels = Y_true, logits = Ylogits)
    

    Optimizer 可以选择基本的GradientDescent也可以选择Adam

    optimizer = tf.train.AdamOptimizer(learning_rate=0.001)
    train = optimizer.minimize(cross_entropy)
    

    4. 模型训练

    将batch中的数据通过Feed_dict载入数据,剩下的就交给Tensorflow吧,注意,为了记录loss 和 Accuracy的变化,我创建了history这个字典,记录每100个Iteration它们的数字变化。

    history = {'acc_train':list(),'acc_val':list(),
               'loss_train':list(),'loss_val':list()}
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        
        for i in range(30000):
            batch = ch.next_batch(100)
            sess.run(train, feed_dict={X: batch[0], Y_true: batch[1]})
            
            # PRINT OUT A MESSAGE EVERY 100 STEPS
            if i%100 == 0:
                
                # Test the Train Model
                feed_dict_train = {X: batch[0], Y_true: batch[1]}
                feed_dict_val = {X:ch.test_images, Y_true:ch.test_labels}
    
                matches = tf.equal(tf.argmax(Y,1),tf.argmax(Y_true,1))
                acc = tf.reduce_mean(tf.cast(matches,tf.float32))
                history['acc_train'].append(sess.run(acc, feed_dict = feed_dict_train))
                history['acc_val'].append(sess.run(acc, feed_dict = feed_dict_val))
    
                history['loss_train'].append(sess.run(cross_entropy, feed_dict = feed_dict_train))
                history['loss_val'].append(sess.run(cross_entropy, feed_dict = feed_dict_val))
                
                print("Iteration {}:\tloss_train={:.6f}:\tloss_val={:.6f}:\tacc_train={:.6f}:\tacc_val={:.6f}"
                      .format(i,history['loss_train'][-1],history['loss_val'][-1],history['acc_train'][-1],history['acc_val'][-1]))
                
                print('\n')
    

    4.查看训练结果

    可以看到,即便只有一层神经网络,我们也达到了将近90%的Accuracy.

    image-20190329150857000

    5. 用Keras试试看

    Keras就更加简单了,Model两行代码搞定了。

    model = models.Sequential()
    model.add(layers.Dense(units=10, activation='softmax',input_shape=(784,)))
    

    6.预测测试集数据并上传Kaggle

    我们在训练的最后已经将tensorflow的模型保存起来了

     saver.save(sess,'models_saving/my_model.ckpt')
    

    预测的时候取出来就行了

    unlabeled_images_test = pd.read_csv('test.csv')
    
    with tf.Session() as sess:
        
        # Restore the model
        saver.restore(sess, 'models_saving/my_model.ckpt')
        # Fetch Back Results
        label = sess.run(Y, feed_dict={X:X_unlabeled})
    

    最后,按照Kanggle提供模板格式,将结果转换成csv文件,上传服务器,就可以看到训练成果啦。

    详细过程请参见jupyter notbook中的代码和注释。


    参考资料

    https://www.kaggle.com/c/digit-recognizer/data

    https://codelabs.developers.google.com/codelabs/cloud-tensorflow-mnist/#0

    https://www.tensorflow.org/api_docs/


    同步到我的Steemit

    https://steemit.com/@hongtao

    相关文章

      网友评论

        本文标题:Tensorflow入门——单层神经网络识别MNIST手写数字

        本文链接:https://www.haomeiwen.com/subject/pxwdbqtx.html