python-机器学习-手写数字识别

机器学习简单的来说,分为监督式学习无监督式学习
对于监督式学习就是需要人为的来告诉计算机这是什么,需要我们给他一个标签(答案)。
无监督式学习就是不需要我们给出标签(答案)。

图像识别(Image Recognition)是指利用计算机对图像进行处理、分析、计算以识别各种不同模式的目标和对像的技术。

手写数字识别是机器学习以及学习CNN的一个入门案例,计算机通过手写体写出来的数字来识别出图片中的字;但是与印刷字体不同的是,印刷体的字体规则整齐,而不同人的手写体风格迥异,大小不一, 造成了计算机对手写识别任务的一些困难。所以就需要寻找大量的数据集来供应计算机学习。

数字手写体识别由于其有限的类别(0~9共10个数字)成为了相对简单 的手写识别任务。MNIST是常用的数字手写识别数据集
手写数字识别

一、下载数据集
TensorFlow所用版本为1.14版本的

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets("MNIST_data",one_hot=True)

数据集根据MNIST函数调用下载,并且转换为onehot编码;
所谓onehot编码就是由01做组成的一组数,例如0100000000,000010000等字样的数据,他们分别代表了数14,根据0123456789他们所在的位置来表示数的。
python-机器学习-手写数字识别_第1张图片
本次手写数字识别train是55000个训练数据,测试是10000个测试集;大小都为28*28的手写图片。

#列出(图片个数,像素点个数)
print("'trainimg' 的shape是:{}".format(mnist.train.images.shape)) 
print("'trainlabel' 的shape是: {}".format(mnist.train.labels.shape)) 
print("'testing' 的shape是: {}" .format(mnist.test.images.shape)) 
print("'testlabel' 的shape是:{} ".format(mnist.test.labels.shape))


'trainimg' 的shape是:(55000, 784)
'trainlabel' 的shape是: (55000, 10)
'testing' 的shape是: (10000, 784)
'testlabel' 的shape是:(10000, 10)

二、构建神经网络

#神经网络构成
n_hidden_1 = 256
n_hidden_2 = 128
n_input = 784
n_classes = 10

#输入与输出
x = tf.placeholder("float", [None, n_input])
y = tf.placeholder("float", [None, n_classes])

#神经网络初始化参数 
stddev = 0.1 

#权重选择高斯初始化,关键在于out权重矩阵
weights = { 
        'w1': tf.Variable(tf.random_normal([n_input, n_hidden_1],stddev=stddev)), 
        'w2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2], stddev=stddev)), 
        'out': tf.Variable(tf.random_normal([n_hidden_2, n_classes], stddev=stddev)) 
}

#偏置可以选择0值或者也采用高斯初始化 
biases = { 
        'b1': tf.Variable(tf.random_normal([n_hidden_1])), 
        'b2': tf.Variable(tf.random_normal([n_hidden_2])), 
        'out': tf.Variable(tf.random_normal([n_classes])) 
} 


三、构建优化函数和损失函数

#前向传播,返回10个类别的输出,所有的输出不是神经网络的层,直接返回即可 
def multilayer_perceptron(_X, _weights, _biases): 
    layer_1 = tf.nn.relu6(tf.add(tf.matmul(_X, _weights['w1']), _biases['b1'])) 
    layer_2 = tf.nn.relu6(tf.add(tf.matmul(layer_1, _weights['w2']), _biases['b2'])) 
    return(tf.matmul(layer_2, _weights['out']) + _biases['out'])

#Prediction,定义预测值
pred = multilayer_perceptron(x, weights, biases)

#反向传播 
#损失函数采用 交叉熵函数softmax_cross_entropy_with_logits(pred,y) 输入:第一参数:预测值,即一次前向传播的结果;第二参数实际的label值 
#平均的loss reduce_mean 表示最后的结果除以n 
#tf.nn.softmax_cross_entropy_with_logits()函数参数要设置更新! 

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=pred, labels=y)) 

#优化器选择:梯度下降 
#optm = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost)
optm = tf.train.AdamOptimizer(learning_rate=0.001).minimize(cost)

#定义精度值,tf.cast()将True和False转换为1和0
corr = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))
accr = tf.reduce_mean(tf.cast(corr, 'float'))

#变量初始化
init = tf.global_variables_initializer()

四、训练模型

#超参数定义
training_epochs = 40
batch_size = 100
display_step = 2
#加载计算图
sess = tf.Session()
sess.run(init)
#optimize

print("开始训练:")

for epoch in range(training_epochs): 
    avg_cost = 0 
    total_batch = int(mnist.train.num_examples/batch_size) 
    #Iteraton 
    for i in range(total_batch): 
        batch_xs, batch_ys = mnist.train.next_batch(batch_size) 
        feeds = {x: batch_xs, y: batch_ys} 
        sess.run(optm, feed_dict=feeds) 
        avg_cost += sess.run(cost, feed_dict=feeds) 
    avg_cost = avg_cost/total_batch 
    #display 
    if (epoch) % display_step == 0: 
        print("循环次数: %03d/%03d 损失: %.9f" % (epoch, training_epochs, avg_cost)) 
        feeds = {x: batch_xs, y: batch_ys} 
        train_acc = sess.run(accr, feed_dict=feeds) 
        print("训练集正确率: %.3f" % (train_acc)) 

模型在训练几轮之后,训练集正确率就会达到97%,之后就会出现模型过拟合。大家可以通过调参,优化函数等方法来改进,使模型能够更近一步;

五、验证结果

预测错误

print('现在随机显示25个错误的预测:')
randidx = np.random.randint(incorrectImages.shape[0],size = 25)
plt.figure(figsize=(8,8))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(True)
    curr_img = np.reshape(incorrectImages[randidx[i],:],(28,28)) 
    rightLabel=np.argmax(incorrectLabels[randidx[i],:]) #label 
    predictedLabel=np.argmax(incorrectPredications[randidx[i],:])
    curr_label = '{}: {}(v) -> {}(x)'.format(randidx[i],rightLabel,predictedLabel)
    plt.imshow(curr_img,cmap=plt.cm.binary) 
    plt.xlabel(curr_label)
    #plt.imshow(mnist.test.images[i], cmap=plt.cm.binary)
    #plt.xlabel(mnist.test.labels[i])

python-机器学习-手写数字识别_第2张图片
预测正确

correctGuesses=sess.run(corr, feed_dict=\
                        {x: mnist.test.images, \
                         y: mnist.test.labels})
incorrectImages=mnist.test.images[correctGuesses]
incorrectLabels=mnist.test.labels[correctGuesses]
incorrectPredications=sess.run(pred, feed_dict={x:incorrectImages})
print('测试集中有{}个预测正确'.format(incorrectImages.shape[0]))
print('现在随机显示25个正确的预测:')
randidx = np.random.randint(incorrectImages.shape[0],size = 25)
plt.figure(figsize=(8,8))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(True)
    curr_img = np.reshape(incorrectImages[randidx[i],:],(28,28)) 
    rightLabel=np.argmax(incorrectLabels[randidx[i],:]) #label 
    predictedLabel=np.argmax(incorrectPredications[randidx[i],:])
    curr_label = '{}: {}(v) -> {}(x)'.format(randidx[i],rightLabel,predictedLabel)
    plt.imshow(curr_img,cmap=plt.cm.binary) 
    plt.xlabel(curr_label)
    #plt.imshow(mnist.test.images[i], cmap=plt.cm.binary)
    #plt.xlabel(mnist.test.labels[i])

python-机器学习-手写数字识别_第3张图片
结论:
手写数字来说,神经网络是一个很好的,并且非常好的一个方法。

谢谢点赞评论!

你可能感兴趣的:(机器学习,深度学习,机器学习,tensorflow,神经网络,python)