TensorFlow学习实战(一):通过CNN实现Mnist

	本次通过CNN来实现Mnist
	该模型在可以识别原数据集的前提下,加入了可以识别艺术体数字的功能。
	先给出未经训练的模型的程序,你可以自己设定训练次数并将参数数据保存到自己想要保存的位置:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)


# 识别准确度
def compute_accuracy(v_xs, v_ys):
    global prediction
    y_pre = sess.run(prediction, feed_dict={xs: v_xs, keep_prob: 1})# 根据测试集中的图片预测数值
    correct_prediction = tf.equal(tf.argmax(y_pre, 1), tf.argmax(v_ys, 1))# 预测值与测试集中的正确数值相比较,相同为True,不同为False
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))# 将布尔类型转化为单精度浮点类型
    result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys, keep_prob: 1})# 运行accuracy,得到识别准确度
    return result# 返回识别准确度


# 定义权重
def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)  # 生成随机数
    return tf.Variable(initial)


# 定义偏值
def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)  # biases最好定义为正数
    return tf.Variable(initial)


# 定义卷积层
def conv2d(x, W):  # 其中的x即为输入数据(例如RGB图片,W即为上面定义的权重)
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
    # tensorflow中有定义好的卷积层,直接调用即可
    # 其中,strides([1,x_movements,y_movements,1])为卷积核滑动步长,padding为补零方法


# 定义池化层
def max_pool_2x2(x):  # 其中的x为convd2中运算完毕的x
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
    # 此处调用的是tensorflow中定义好的最大池化层
    # 其中,ksize为池化核的大小,strides([1,x_movements,y_movements,1])为卷积核滑动步长,padding为补零方法


# 定义神经网络的placeholder
xs = tf.placeholder(tf.float32, [None, 784])  # 因为输入数据是28*28的矩阵(包括了所有的输入图片)
ys = tf.placeholder(tf.float32, [None, 10])   # 其中的10是因为有0—9十个数字
keep_prob = tf.placeholder(tf.float32)

x_image = tf.reshape(xs, [-1, 28, 28, 1])  # 其中的-1代表着一共输入了多少数据,两个28即为输入数据矩阵的大小,1为输入图片的通道数(因为是灰色照片)

# 定义conv1 layer
W_conv1 = weight_variable([5, 5, 1, 32])  # 其中的两个5代表卷积核的大小,1代表输入的一张图片(包含许多特征)的通道数,32代表经过这一神经层处理后生成的通道数(特征数)
b_conv1 = bias_variable([32])  # 因为生成了32个通道
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)  # 经过卷积运算和激活函数运算得到的数据,尺寸:28*28*32
h_pool1 = max_pool_2x2(h_conv1)  # 经过最大池化运算得到的数据,尺寸:14*14*32(池化不改变通道数只改变大小)

# 定义conv2 layer
W_conv2 = weight_variable([5, 5, 32, 64])  # 其中的两个5代表卷积核的大小,32代表输入图片(包含许多特征)经过conv1 layer处理后的通道数,64代表经过这一神经层处理后生成的通道数(特征数)
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)  # 经过卷积运算和激励函数运算得到的数据,尺寸:14*14*64
h_pool2 = max_pool_2x2(h_conv2)  # 经过最大池化运算得到的数据,尺寸:7*7*64(池化不改变通道数只改变大小)

# 定义func1 layer
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_falt = tf.reshape(h_pool2, [-1, 7 * 7 * 64])  # 将h_pool2的形状改为[-1,7*7*64]
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_falt, W_fc1) + b_fc1)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)  # 防止过拟合

# 定义func2 layer
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)  # 进行分类,计算概率

# 定义交叉熵损失函数(分类问题常用交叉熵损失函数)
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), reduction_indices=[1]))
# 定义训练函数
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

with tf.Session() as sess:
    sess.run(tf.initialize_all_variables())  # 激活神经网络
    counter = 10

    # 训练过程
    for step in range(10000):
        batch_xs, batch_ys = mnist.train.next_batch(100)  # 从训练集中一次提取100张图片进行训练
        sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys, keep_prob: 0.5})
        if step % 1000 == 0:
            counter -= 1
            print('the remaining times trained is ', counter * 1000, '.')
            print('the current accuracy is ', compute_accuracy(mnist.test.images, mnist.test.labels), '.')
            print()

    # 保存神经网络中的参数
    saver = tf.train.Saver()
    save_path = saver.save(sess, 'Mnist_parameter_CNN/save_parameter.ckpt')

    # 提示神经网络已经完成训练
    print('The training has been end!')

	接下来给出已经训练好的模型的程序,你可以通过绝对路径或相对路径来上传你想要识别的艺术体数字的图片:
import tensorflow as tf
import numpy as np
from PIL import Image
import random

from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

# 加载图片
def get_picture(img_path):
    img = Image.open(img_path)# 加载RGB图片或灰度图片
    img = img.resize((28, 28), Image.ANTIALIAS).convert('L')# 将图片重置为28*28*1
    img = np.array(img.getdata()).reshape((1, 784))# 将图片的像素矩阵转化为一个向量
    img = [10*(255-x)*1.0/255.0 for x in img]# 将图片的像素值缩小到0-1之间
    return img[0]# 转化为向量

# 识别准确度
def compute_accuracy(v_xs, v_ys):
    global prediction
    y_pre = sess.run(prediction, feed_dict={xs: v_xs, keep_prob: 1})# 根据测试集中的图片预测数值
    correct_prediction = tf.equal(tf.argmax(y_pre, 1), tf.argmax(v_ys, 1))# 预测值与测试集中的正确数值相比较,相同为True,不同为False
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))# 将布尔类型转化为单精度浮点类型
    result = sess.run(accuracy, feed_dict={xs: v_xs, ys: v_ys, keep_prob: 1})# 运行accuracy,得到识别准确度
    return result# 返回识别准确度

# 定义权重
def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)  # 生成随机数
    return tf.Variable(initial)


# 定义偏值
def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)  # biases最好定义为正数
    return tf.Variable(initial)


# 定义卷积层
def conv2d(x, W):  # 其中的x即为输入数据(例如RGB图片,W即为上面定义的权重)
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
    # tensorflow中有定义好的卷积层,直接调用即可
    # 其中,strides([1,x_movements,y_movements,1])为卷积核滑动步长,padding为补零方法


# 定义池化层
def max_pool_2x2(x):  # 其中的x为convd2中运算完毕的x
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
    # 此处调用的是tensorflow中定义好的最大池化层
    # 其中,ksize为池化核的大小,strides([1,x_movements,y_movements,1])为卷积核滑动步长,padding为补零方法

# 定义神经网络的placeholder
xs = tf.placeholder(tf.float32, [None, 784])  # 因为输入数据是28*28的矩阵(包括了所有的输入图片)
ys = tf.placeholder(tf.float32, [None, 10])   # 其中的10是因为有0—9十个数字
keep_prob = tf.placeholder(tf.float32)

x_image = tf.reshape(xs, [-1, 28, 28, 1])  # 其中的-1代表着一共输入了多少数据,两个28即为输入数据矩阵的大小,1为输入图片的通道数(因为是灰色照片)

# 定义conv1 layer
W_conv1 = weight_variable([5, 5, 1, 32])  # 其中的两个5代表卷积核的大小,1代表输入的一张图片(包含许多特征)的通道数,32代表经过这一神经层处理后生成的通道数(特征数)
b_conv1 = bias_variable([32])  # 因为生成了32个通道
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)  # 经过卷积运算和激活函数运算得到的数据,尺寸:28*28*32
h_pool1 = max_pool_2x2(h_conv1)  # 经过最大池化运算得到的数据,尺寸:14*14*32(池化不改变通道数只改变大小)

# 定义conv2 layer
W_conv2 = weight_variable([5, 5, 32, 64])  # 其中的两个5代表卷积核的大小,32代表输入图片(包含许多特征)经过conv1 layer处理后的通道数,64代表经过这一神经层处理后生成的通道数(特征数)
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)  # 经过卷积运算和激励函数运算得到的数据,尺寸:14*14*64
h_pool2 = max_pool_2x2(h_conv2)  # 经过最大池化运算得到的数据,尺寸:7*7*64(池化不改变通道数只改变大小)

# 定义func1 layer
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_falt = tf.reshape(h_pool2, [-1, 7 * 7 * 64])  # 将h_pool2的形状改为[-1,7*7*64]
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_falt, W_fc1) + b_fc1)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)  # 防止过拟合

# 定义func2 layer
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)  # 进行分类,计算概率

with tf.Session() as sess:

    sess.run(tf.initialize_all_variables())
    saver = tf.train.Saver()

    # 加载训练好的参数数据
    saver.restore(sess, 'Mnist_parameter_CNN/save_parameter.ckpt')

    # 通过随即数模块生成随机测试区间
    min = random.randint(0, len(mnist.test.labels))
    max = random.randint(0, len(mnist.test.labels))
    if min > max:
        min, max = max, min
    max += 1

    # 预测值与实际值的测试
    for i in range(min, max):
        # 预测值
        prediction_num = sess.run(prediction, feed_dict={xs: np.array([mnist.test.images[i]]), keep_prob: 1})
        prediction_number = np.argmax(prediction_num, axis=1)
        print('The predictive number is ', prediction_number[0], '.', end=' ')
        # 实际值
        ys_num = sess.run(ys, feed_dict={ys: np.array([mnist.test.labels[i]]), keep_prob: 1})
        ys_number = np.argmax(ys_num, axis=1)
        print('    The actual number is ', ys_number[0], '.')
        print()

    # 输出随机测试区间
    max -= 1
    print('The random test interval is [', min, ',', max, '].')
    print()

    # 输出该模型的识别准确度
    recognition_accuracy = compute_accuracy(mnist.test.images, mnist.test.labels)
    print('The current recognition accuracy is', recognition_accuracy, '.')
    print()

    # 加载自定义图片
    print('Loading image or not? Y/N')
    choice = input()

    # 确保输入的choice的值是Y或N
    while(choice != 'Y' and choice != 'N'):
        print('Warning! Please input Y or N rather than any other words!')
        choice = input()

    if choice == 'Y':
        while(1):
            print('You have chosen to load image, please input the path of the image and the model will recognize it.')

            # 加载图片并输出预测值
            path = input()
            path = 'number_picture/' + path
            number_picture = get_picture(path)# 加载图片
            prediction_num = sess.run(prediction, feed_dict={xs: np.array([number_picture]), keep_prob: 1})
            prediction_num = np.argmax(prediction_num, axis=1)# 得到预测值
            print('The predictive number is ', prediction_num[0], '.')# 输出预测值

            # 判断是否继续输入图片
            print('Continuing to input the image or not? Y/N')
            choice = input()

            # 确保输入的choice的值是Y或N
            while (choice != 'Y' and choice != 'N'):
                print('Warning! Please input Y or N rather than any other words!')
                choice = input()

            if choice == 'N':
                break

        print('The model is over.')

    elif choice == 'N':
        print('You have not chosen to load image and the model is over.')



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值