Tensorflow MNIST CNN 手写数字识别

觉得有用的话,欢迎一起讨论相互学习~

参考文献

Tensorflow机器学习实战指南

源代码请点击下方链接

Tesorflow实现基于MNIST数据集上简单CNN

少说废话多写代码

下载并读取MNIST数据集

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow.contrib.learn.python.learn.datasets.mnist import read_data_sets
from tensorflow.python.framework import ops ops.reset_default_graph() # Start a graph session
sess = tf.Session() # 下载并读取数据集
# 如果本地没有temp文件夹需要从Tensorflow官网下载
data_dir = 'temp'
mnist = read_data_sets(data_dir) # 把mnist.train.images中的数据集变换成(28*28)的数据格式,原文件中以784维向量的形式保存
train_xdata = np.array([np.reshape(x, (28, 28)) for x in mnist.train.images])
test_xdata = np.array([np.reshape(x, (28, 28)) for x in mnist.test.images])
# print(train_xdata.shape) # 输出格式是numpy.ndarray的形式
# print(test_xdata.shape)
# (55000, 28, 28)
# (10000, 28, 28) train_labels = mnist.train.labels
test_labels = mnist.test.labels
# print(train_labels.shape) # (55000,)
# print(train_labels[0:10]) # [7 3 4 6 1 8 1 0 9 8]

构造模型

# 设置模型超参数
batch_size = 100 # 批处理数量
learning_rate = 0.005 # 学习率
evaluation_size = 500 # 测试批数量
image_width = train_xdata[0].shape[0]
image_height = train_xdata[0].shape[1]
target_size = max(train_labels) + 1
# print(target_size) # 10
num_channels = 1 # 通道数,灰度图片只有一个通道
generations = 500 # 迭代次数为500次
eval_every = 5 # 输出统计
conv1_features = 25 # 第一个卷积层特征个数
conv2_features = 50 # 第二个卷积层特征个数
max_pool_size1 = 2 # NxN window for 1st max pool layer
max_pool_size2 = 2 # NxN window for 2nd max pool layer
fully_connected_size1 = 100 # 全连接层神经元个数 # 声明模型占位符
# 训练数据集变量
x_input_shape = (batch_size, image_width, image_height, num_channels)
x_input = tf.placeholder(tf.float32, shape=x_input_shape)
y_target = tf.placeholder(tf.int32, shape=(batch_size))
# 测试数据集变量
eval_input_shape = (evaluation_size, image_width, image_height, num_channels)
eval_input = tf.placeholder(tf.float32, shape=eval_input_shape)
eval_target = tf.placeholder(tf.int32, shape=(evaluation_size)) # conv1_weight表示第一层的权重,即为第一层的卷积核[卷积核高,卷积核宽,输入通道数量,输出通道数量]
# 使用标准差为0.1的截断高斯分布进行变量初始化。注意通tf.Variable,此时的conv1_weight是一个变量。
conv1_weight = tf.Variable(tf.truncated_normal([4, 4, num_channels, conv1_features],
stddev=0.1, dtype=tf.float32))
# 第一个卷积层偏置
conv1_bias = tf.Variable(tf.zeros([conv1_features], dtype=tf.float32)) # 第二个卷积层权重即卷积核大小
conv2_weight = tf.Variable(tf.truncated_normal([4, 4, conv1_features, conv2_features], stddev=0.1, dtype=tf.float32))
# 第二个卷积层偏置
conv2_bias = tf.Variable(tf.zeros([conv2_features], dtype=tf.float32)) # 全连接层参数
# 因为卷积层设置padding mode 为'SAME',所以卷积过后每一个特征层的维度仍与原来保持相同
# 在池化层中步长和窗口的宽度和高度相同,则进行池化操作后的输出的高度和宽度只是原维度除以池化窗口的乘积
resulting_width = image_width//(max_pool_size1*max_pool_size2) # // 表示取整除法
resulting_height = image_height//(max_pool_size1*max_pool_size2)
full1_input_size = resulting_width*resulting_height*conv2_features
full1_weight = tf.Variable(tf.truncated_normal([full1_input_size, fully_connected_size1],
stddev=0.1, dtype=tf.float32))
full1_bias = tf.Variable(tf.truncated_normal([fully_connected_size1], stddev=0.1, dtype=tf.float32))
full2_weight = tf.Variable(tf.truncated_normal([fully_connected_size1, target_size],
stddev=0.1, dtype=tf.float32))
full2_bias = tf.Variable(tf.truncated_normal([target_size], stddev=0.1, dtype=tf.float32)) # 模型进行初始化操作
def my_conv_net(input_data):
# 第一个卷积-ReLU-池化层
conv1 = tf.nn.conv2d(input_data, conv1_weight, strides=[1, 1, 1, 1], padding='SAME')
relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_bias))
max_pool1 = tf.nn.max_pool(relu1, ksize=[1, max_pool_size1, max_pool_size1, 1],
strides=[1, max_pool_size1, max_pool_size1, 1], padding='SAME')
# 第二个卷积-ReLU-池化层
conv2 = tf.nn.conv2d(max_pool1, conv2_weight, strides=[1, 1, 1, 1], padding='SAME')
relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_bias))
max_pool2 = tf.nn.max_pool(relu2, ksize=[1, max_pool_size2, max_pool_size2, 1],
strides=[1, max_pool_size2, max_pool_size2, 1], padding='SAME') # 扁平化/光栅化处理
# 将max_pool2的输出形状转化成list格式,其中分别表示[batch_size,height,weight,channels]
final_conv_shape = max_pool2.get_shape().as_list()
final_shape = final_conv_shape[1]*final_conv_shape[2]*final_conv_shape[3]
flat_output = tf.reshape(max_pool2, [final_conv_shape[0], final_shape]) # 第一个全连接层
fully_connected1 = tf.nn.relu(tf.add(tf.matmul(flat_output, full1_weight), full1_bias)) # 第二个全连接层
final_model_output = tf.add(tf.matmul(fully_connected1, full2_weight), full2_bias) return (final_model_output) # 构造好模型后,使用时只需要传入数据集
model_output = my_conv_net(x_input)
test_model_output = my_conv_net(eval_input) # 定义损失函数(softmax 交叉熵函数)
loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=model_output, labels=y_target)) # 构造预测函数,通过输出预测是属于哪个数字分类
prediction = tf.nn.softmax(model_output)
test_prediction = tf.nn.softmax(test_model_output) # 设定精准度函数
# 传入logits为经过softmax函数one-hot标记的形状为[batch_size,10]的全连接层输出。
# 如果对于一张图片的输出如果和标签相等则输出为1,否则为0.然后除以这批处理数量为准确率。
def get_accuracy(logits, targets):
batch_predictions = np.argmax(logits, axis=1)
num_correct = np.sum(np.equal(batch_predictions, targets))
return (100.*num_correct/batch_predictions.shape[0]) # 创建一个优化器
my_optimizer = tf.train.MomentumOptimizer(learning_rate, 0.9) # 使用momentum优化方法,设定学习率
train_step = my_optimizer.minimize(loss)

训练模型

# 初始化变量
init = tf.global_variables_initializer()
sess.run(init) # 开始训练循环
train_loss = [] # 用于保存训练集下loss值
train_acc = [] # 用于保存训练集下准确率
test_acc = [] # 用于保存测试集下准确率 for i in range(generations): # 从0开始迭代
rand_index = np.random.choice(len(train_xdata), size=batch_size)
# 意为从(0~train_xdata-1)中挑选batch_size个数组成索引。
rand_x = train_xdata[rand_index] # 从train_xdata数据中取出[rand_index]索引的图片
rand_x = np.expand_dims(rand_x, 3) # 向图片数据中增加通道信息
rand_y = train_labels[rand_index] # 从train_xdata数据中取出[rand_index]索引的标签
train_dict = {x_input: rand_x, y_target: rand_y}
sess.run(train_step, feed_dict=train_dict)
temp_train_loss, temp_train_preds = sess.run([loss, prediction], feed_dict=train_dict)
# prediction 是通过softmax函数处理过的全连接层的输出shape为[batch_size,10]第二维中为one-hot稀疏张量 temp_train_acc = get_accuracy(temp_train_preds, rand_y) if (i + 1)%eval_every == 0:
eval_index = np.random.choice(len(test_xdata), size=evaluation_size) # 测试批处理数量
eval_x = test_xdata[eval_index]
eval_x = np.expand_dims(eval_x, 3) # 向图片数据增加通道信息
eval_y = test_labels[eval_index]
test_dict = {eval_input: eval_x, eval_target: eval_y}
test_preds = sess.run(test_prediction, feed_dict=test_dict) # 测试集预测结果
temp_test_acc = get_accuracy(test_preds, eval_y) # 测试集预测精度 # 记录和打印结果
train_loss.append(temp_train_loss) # 在迭代时,每经过eval_every此就将训练集上的loss function值记录到train_loss中
train_acc.append(temp_train_acc)
test_acc.append(temp_test_acc)
acc_and_loss = [(i + 1), temp_train_loss, temp_train_acc, temp_test_acc]
# i 从0开始,acc_and_loss是一个列表的形式(4,)
print('Generation # {}. Train Loss: {:.2f}. Train Acc (Test Acc): {:.2f} ({:.2f})'.format(*acc_and_loss))

显示图表

# 使用matplotlib显示loss和精确度
eval_indices = range(0, generations, eval_every) # x轴
# 虽迭代次数推移的loss值
plt.plot(eval_indices, train_loss, 'k-')
plt.title('Softmax Loss per Generation')
plt.xlabel('Generation')
plt.ylabel('Softmax Loss')
plt.show() # 显示训练集和测试集上的准确率
plt.plot(eval_indices, train_acc, 'k-', label='Train Set Accuracy')
plt.plot(eval_indices, test_acc, 'r--', label='Test Set Accuracy')
plt.title('Train and Test Accuracy')
plt.xlabel('Generation')
plt.ylabel('Accuracy')
plt.legend(loc='lower right') # 显示标题出现的位置在图片右下角,否则不会显示标题
plt.show() # 绘制样例图片
# 绘制最后一个batch中的6张图片
actuals = rand_y[0:6]
# print(actuals)[8 6 8 2 3 5]
predictions = np.argmax(temp_train_preds, axis=1)[0:6]
# 表示返回0~6个temp_train_preds中第一维数据中最大值所在位置
# print(predictions)[8 6 8 2 3 0]
images = np.squeeze(rand_x[0:6]) # 降维度,只保留有用的数据信息 Nrows = 2
Ncols = 3
fig = plt.figure() # 设置一个大的figure,向其中添加子图片
for i in range(6):
ax = fig.add_subplot(Nrows, Ncols, i + 1) # 设置当前图片所在位置
ax.imshow(np.reshape(images[i], [28, 28]), cmap='Greys_r') # 子块显示图片使用imshow语句
ax.set_title('Actual: ' + str(actuals[i]) + ' Pred: ' + str(predictions[i]), fontsize=10) # 设置子图标题
frame = plt.gca() # 去除图的边框
frame.axes.get_xaxis().set_visible(False) # 设置x坐标轴不可见
frame.axes.get_yaxis().set_visible(False) # 设置y坐标轴不可见
plt.show() # 显示figure sess.close()

TersorflowTutorial_MNIST数据集上简单CNN实现的更多相关文章

  1. MNIST数据集上卷积神经网络的简单实现(使用PyTorch)

    设计的CNN模型包括一个输入层,输入的是MNIST数据集中28*28*1的灰度图 两个卷积层, 第一层卷积层使用6个3*3的kernel进行filter,步长为1,填充1.这样得到的尺寸是(28+1* ...

  2. BP算法在minist数据集上的简单实现

    BP算法在minist上的简单实现 数据:http://yann.lecun.com/exdb/mnist/ 参考:blog,blog2,blog3,tensorflow 推导:http://www. ...

  3. NASNet学习笔记——   核心一:延续NAS论文的核心机制使得能够自动产生网络结构;    核心二:采用resnet和Inception重复使用block结构思想;    核心三:利用迁移学习将生成的网络迁移到大数据集上提出一个new search space。

    from:https://blog.csdn.net/xjz18298268521/article/details/79079008 NASNet总结 论文:<Learning Transfer ...

  4. 用DELPHI的RTTI实现数据集的简单对象化

    在<强大的DELPHI RTTI--兼谈需要了解多种开发语言>一文中,我说了一下我用DELPHI的RTTI实现了数据集的简单对象化.本文将详细介绍一下我的实现方法.     首先从一个简单 ...

  5. Tensorflow简单CNN实现

    觉得有用的话,欢迎一起讨论相互学习~Follow Me 少说废话多写代码~ """转换图像数据格式时需要将它们的颜色空间变为灰度空间,将图像尺寸修改为同一尺寸,并将标签依 ...

  6. 【翻译】借助 NeoCPU 在 CPU 上进行 CNN 模型推理优化

    本文翻译自 Yizhi Liu, Yao Wang, Ruofei Yu.. 的  "Optimizing CNN Model Inference on CPUs" 原文链接: h ...

  7. pytorch实现MLP并在MNIST数据集上验证

    写在前面 由于MLP的实现框架已经非常完善,网上搜到的代码大都大同小异,而且MLP的实现是deeplearning学习过程中较为基础的一个实验.因此完全可以找一份源码以参考,重点在于照着源码手敲一遍, ...

  8. PyTorch迁移学习-私人数据集上的蚂蚁蜜蜂分类

    迁移学习的两个主要场景 微调CNN:使用预训练的网络来初始化自己的网络,而不是随机初始化,然后训练即可 将CNN看成固定的特征提取器:固定前面的层,重写最后的全连接层,只有这个新的层会被训练 下面修改 ...

  9. iOS上简单推送通知(Push Notification)的实现

    iOS上简单推送通知(Push Notification)的实现 根据这篇很好的教程(http://www.raywenderlich.com/3443/apple-push-notification ...

随机推荐

  1. VUE AXIOS 跨域问题

    背景: 后台跨域使用通配符:context.Response.Headers.Add("Access-Control-Allow-Origin", "*"); ...

  2. HDU 5862 Counting Intersections 扫描线+树状数组

    题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 Counting Intersections Time Limit: 12000/ ...

  3. oracle执行完shutdown immediate后登陆不上了怎么办

    在sqlplus 里登录后使用shutdown immediate 关闭数据库后若没有使用startup重启数据库就退出窗口则会出现下一次重启sqlplus窗口时无法登录的现象,解决方法如下 一.启动 ...

  4. CentOS 7 网卡命名修改为eth0格式

    Linux 操作系统的网卡设备的传统命名方式是 eth0.eth1.eth2等,而 CentOS7 提供了不同的命名规则,默认是基于固件.拓扑.位置信息来分配.这样做的优点是命名全自动的.可预知的,缺 ...

  5. jQuery表单验证组件BootstrapValidator

    github:https://github.com/nghuuphuoc/bootstrapvalidator 参考博客:JS组件系列——Form表单验证神器: BootstrapValidator ...

  6. 第95天:CSS3 边框、背景和文字效果

    1.CSS3边框: border-radius:CSS3圆角边框.在 CSS2 中添加圆角矩形需要技巧,我们必须为每个圆角使用不同的图片,在 CSS3 中,创建圆角是非常容易的,在 CSS3 中,bo ...

  7. ZOJ2725_Digital Deletions

    题意是这样的,一开始给你一串数字,两个人轮流操作,操作可以分为两种. 1.每次修改一个数字,使其变为一个小于当前的非负数. 2.移除中间的某一个0以及0右边的所有数字. 使得所有数字消失的游戏者获胜. ...

  8. Qt中父子widget的事件传递

    以前我一直以为:在父widget上摆一个子widget后,当click子widget时:只会进入到子widget的相关事件处理函数中,比如进入到mousePressEvent()中, 而不会进入到父w ...

  9. 创建Django工程-Day19

    1. 新建一个day19的工程和app01. 2. 新建templates和static的文件夹. 3. 去settings.py中去做配置. 1)注释掉csrf 2)配置模板路径 'DIRS': [ ...

  10. Spring Boot系列教程四:配置文件详解properties

    一.配置随机数,使用随机数 在application.properties文件添加配置信息 #32位随机数 woniu.secret=${random.value} #随机整数 woniu.numbe ...