手写数字识别是一个非常经典的机器学习项目,这篇文章,我们就通过参加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文件,分离数据和标签,并分出训练集和验证集
1 | labeled_images = pd.read_csv('train.csv') |
2. Batch training 的帮助函数
这个部分虽然比较难,但是不是这篇文章的重点,就此略过,主要作用是从训练数据集中顺序取出指定数量的batch,在Session中给模型训练。帮助函数处理之后数据的shape为[batch_size, 28,28,1]
帮助函数还有一个作用就是讲标签onehot encoded。onehot encoded 的标签shape为[batch_size, 10]。
3. 创建模型
单层神经网络,神经元个数就是输出的个数,手写数字有0到9一共10个类别,所以输出是10个数,神经元个数就是10。因为是全连接的神经网络,我们需要把输入的28*28的二维图片拆解拼凑成一个784个像素点的一维向量。输入,输出的个数和纬度决定了权重W和偏移b的shape
初始化权重W1和偏移B1:
1 | W1 = tf.Variable(tf.truncated_normal([784, 10], stddev=0.1)) # 784 = 28 * 28 |
单层神经网络通过线性变换加softmax的激活函数就能得到最终的结果
1 | XX = tf.reshape(X,[-1,784]) |
Cross_entropy 可以直接通过公式计算
1 | cross_entropy = -tf.reduce_mean(Y_true * tf.log(Y)) * 1000.0 |
也可以用tensorflow中自带的,如何选择我在前面的文章中已经介绍过了。
1 | cross_entropy = tf.losses.softmax_cross_entropy(onehot_labels = Y_true, logits = Ylogits) |
Optimizer 可以选择基本的GradientDescent也可以选择Adam
1 | optimizer = tf.train.AdamOptimizer(learning_rate=0.001) |
4. 模型训练
将batch中的数据通过Feed_dict载入数据,剩下的就交给Tensorflow吧,注意,为了记录loss 和 Accuracy的变化,我创建了history这个字典,记录每100个Iteration它们的数字变化。
1 | history = {'acc_train':list(),'acc_val':list(), |
4.查看训练结果
可以看到,即便只有一层神经网络,我们也达到了将近90%的Accuracy.
5. 用Keras试试看
Keras就更加简单了,Model两行代码搞定了。
1 | model = models.Sequential() |
6.预测测试集数据并上传Kaggle
我们在训练的最后已经将tensorflow的模型保存起来了
1 | saver.save(sess,'models_saving/my_model.ckpt') |
预测的时候取出来就行了
1 | unlabeled_images_test = pd.read_csv('test.csv') |
最后根据Kanggle提供的后台上传转成csv文件,就可以检验模型的效果啦。
参考资料
https://www.kaggle.com/c/digit-recognizer/data
https://codelabs.developers.google.com/codelabs/cloud-tensorflow-mnist/#0
https://www.tensorflow.org/api_docs/
同步到我的简书