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. 调试和开发npm模块的方式

    ln -s(软连接) 假设my-project是运行npm模块的项目,vue-router是我们需要调试的npm模块 将vue-router下载到与my-project同级目录中. git clone ...

  2. 后端编程语言PHP

    | 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.PHP 简介 PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言. PHP 脚本在服务器上执行. 什么是 PHP?(超文本预处理器 ...

  3. Kotlin 学习笔记(一)

    (Kotlin 学习笔记的文档结构基本按照 Java 核心技术一书的目录排列) 基本程序设计结构 数据类型 数字 类型 宽度 Double 64 Float 32 Long 64 Int 32 Sho ...

  4. 【每日scrum】NO.8

    (1) 在图的设计过程中掌握了图的基本运算函数的算法的理解和程序的有效吸收,包括图的深度和广度优先的遍历,对图的联通分量的求解,图的最小生成树,图的拓扑排序,图的关键路径, (2)在迪杰斯特拉算法的基 ...

  5. P4环境搭建

    P4环境搭建 执行仓库中所有脚本,即可即可安装所有依赖项. GitHub链接 脚本执行顺序:deps,p4c-bm,bmv2,p4c

  6. 中国剩余定理---FZU 1402 猪的安家

    J - 猪的安家 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Sta ...

  7. jQuery之元素查找

    在已经匹配出的元素集合中根据选择器查找孩子/父母/兄弟标签1. children(): 子标签中找2. find() : 后代标签中找3. parent() : 父标签4. prevAll() : 前 ...

  8. bond下改变网卡

    浪潮服务器打开控制台 用ip addr查看哪个网卡是绑定的,eth2和eth4是绑定状态 用mv命令,更改网卡名称 并将每个网卡里的信息更改 reboot,重启 ip addr查看,eth6和eth8 ...

  9. CCF——数位之和201512-1

    问题描述 给定一个十进制整数n,输出n的各位数字之和. 输入格式 输入一个整数n. 输出格式 输出一个整数,表示答案. 样例输入 20151220 样例输出 13 样例说明 20151220的各位数字 ...

  10. python/django将mysql查询结果转换为字典组

    使用python查询mysql数据库的时候,默认查询结果没有返回表字段名称,不方便使用.为了方便使用一般会选择将查询结果加上字段名称以字典组的方式返回查询结果. 实现如下: def dict_fetc ...