基于Tensorflow的MINIST手写体识别

MINIS手写体识别相当于机器学习中的Hello world,作为深度学习领域的入门任务是初学者的首选。

数据集下载 download.py

1. MINIST数据集

MINIST数据集是一个图片压缩包,包含大量手写数字图片;
其中一个数据样本有两部分构成:手写图片和label;
基于Tensorflow的MINIST手写体识别_第1张图片
数据集每个样本都是(1,784)维度的图片,为了方便展示就像下图一样画成二维矩阵,实际上后面要将向量转换为28*28的二维矩阵;
基于Tensorflow的MINIST手写体识别_第2张图片基于Tensorflow的MINIST手写体识别_第3张图片

2. 读取数据

TensorFlow为了教学MNIST而提前编制了程序,所以只需两行代码就可自动下载数据集文件

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
# 从MNIST_data/中读取MNIST数据,这条语句在数据不存在时,会自动执行下载

运行后可以在相应目录下查看到如下数据压缩包
在这里插入图片描述

3. 打印数据集基本信息

数据集可分为:

训练集 测试集 验证集
minist.train minist.test minist.validation
55,000 10,000 5,000
训练模型 多次使用调参 评估模型

将MINIST保存为图片 save_pic.py

1. 创建文件夹保存原始图片

save_dir = 'MNIST_data/raw/'
if os.path.exists(save_dir) is False:  # 判断save_dir文件是否存在
    os.makedirs(save_dir) # os.makedirs()方法用于递归创建目录

2. reshape图片

 # 注意:mnist.train.images[i, :]就表示第i张图片(序号从0开始)
    image_array = mnist.train.images[i, :]
    # TensorFlow中的MNIST图片是一个784维的向量,我们重新把它还原为28x28维的图像
    image_array = image_array.reshape(28, 28)

3. 文件命名

# 保存文件的格式为 mnist_train_0.jpg, mnist_train_1.jpg, ... ,mnist_train_19.jpg
    filename = save_dir + 'mnist_train_%d.jpg' % i

4.转换为图片存储

    # 将image_array保存为图片:array - > image
    #scipy.misc.toimage(image_array, cmin=0.0, cmax=1.0).save(filename)
    # AttributeError: module 'scipy.misc' has no attribute 'toimage'

    Image.fromarray((image_array * 255).astype('uint8'), mode='L').convert('RGB').save(filename)

运行后可以在相应目录下看到存储下来的如下图片:
基于Tensorflow的MINIST手写体识别_第4张图片

打印MINIST数据集图片的标签 label.py

1. 独热编码

one - hot读热编码是一种稀疏向量,其中:一个向量设为1,其他元素均设为0;独热编码常用于表示拥有有限个可能值的字符串或标识符;

2. argmax(array, axis)

numpy.argmax(array, axis) 函数:
array是矩阵,axis是0或者1;axis默认为0
其中,0表示的是按行比较返回最大值的索引,1表示按列比较返回最大值的索引
eg: one_dim_array = np.array([1, 4, 5, 3, 7, 2, 6])
print(np.argmax(one_dim_array)) # 4

3. 打印label

MINIST数据集每个样本的label是(1*10)维的数组,采用独热编码表示,形如(0, 1, 0, 0, 0, 0, 0, 0, 0, 0)

# 看前20张训练图片的label
for i in range(20):
    one_hot_label = mnist.train.labels[i, :]
    # 通过np.argmax我们可以直接获得原始的label
    label = np.argmax(one_hot_label)
    print(f'mnist_train_{i}.jpg label: {label}')
    # mnist_train_18.jpg label: 6

Softmax回Softmax_regression.py

1. Softmax回归模型

Softmax回归是一个线性的多类分类模型,我们期望对输入的图片计算出它属于某个类别的概率,比如90%的概率是2,5%的概率是5,那么最终会输出这张图片的标签为5;因此,一张图片对于每一个数字的吻合度可以被softmax函数转换成为一个概率值。softmax函数可以定义为:
基于Tensorflow的MINIST手写体识别_第5张图片
由下图所示,对于输入Xi加权求和,再分别加上一个偏置量,最后输入到Softmax函数中:
基于Tensorflow的MINIST手写体识别_第6张图片
其矩阵表现形式如下:
在这里插入图片描述
基于Tensorflow的MINIST手写体识别_第7张图片
下面举一个例子理解:
假设我们现在需要预估房价。输出y是房子价格,输入Xi就是多种影响因素,可能是大小,距离,教育资源等等,类比MINIST问题就是输入图片的像素值;W为各影响因素的权,b为偏移量;

2. 设置占位符

  1. tf.placeholder( dtype, shape=None, name )
    dtype是数据类型;shape是数据形状,默认一维,也可二维;name可有可无
  2. palceholder只暂时存储变量,传值过程在sess.run()中进行
x = tf.placeholder(tf.float32, [None, 784])
# 用于得到传递进来的待识别的训练图片
W = tf.Variable(tf.zeros([784, 10])) 
# 相当于一层神经网络上的参数
b = tf.Variable(tf.zeros([10]))
# 偏置向量

2. 预测函数

y是模型的输出,y_是实际的图像标签,用one-hot表示

# y=softmax(Wx + b),y表示模型的输出
y = tf.nn.softmax(tf.matmul(x, W) + b)  
# tf.matmual()表示两个矩阵相乘

# y_是实际的图像标签,同样以占位符表示
y_ = tf.placeholder(tf.float32, [None, 10])

3. 损失函数

根据y和y_来构造交叉熵损失函数

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y)))  

4. 梯度下降

使用梯度下降的方式去迭代使得损失函数达到最小;
GradientDescentOptimizer(0.01)是梯度下降的封装函数,设置0.01的初始学习速率;
minimize(cross_entropy)表示最小化损失函数;

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

5. 定义会话Session

上面所有的步骤只是定义了一个框架,Tensorflow中要求所有的数据计算都要在定义的会话中进行;

with tf.Session() as sess:
	tf.global_variables_initializer().run()
	# 初始化所有变量
	for _ in range(1000):
	# 迭代1000次
		batch_xs, batch_ys = mnist.train.next_batch(100)
		sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})  # feed_dict给使用placeholder创建出来的tensor赋值

6. 查看准确率

  1. equal()函数:逐元素比较是否相等,返回结一个比较结果(Ture/False)

  2. reduce_mean()函数:计算张量的各个维度上的元素的平均值

  3. cast()函数:张量数据类型转换,将布尔型转换为float32
    例如:
    [True,False,True,True]可以用[1,0,1,1]表示,精度 为0.75
    0.75 = 3/4

correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})) 
# 用测试集的数据去得到准确率

源代码

github源代码

你可能感兴趣的:(Deep,Learning,深度学习,tensorflow)