深度学习:不调TensorFlow,自己写神经网络学习MNIST数据集(2)—旋转图像继续强化模型(正确率达98%+)

本文在之前神经网络模型基础上,通过旋转MNIST数据集图像增强模型能力,最高正确率提升至98%以上。同时,通过反向查询了解神经网络学习内容,实现从输出端输入数据逆向生成图像。
摘要由CSDN通过智能技术生成
之前手写神经网络学习效果已经很不错了,最高正确率略微超越97%。本文文章中我们对数据做进一步处理,从而继续强化模型的能力。同时我们也将进行反向查询,看看神经网络到底学到了什么

之前一篇https://blog.csdn.net/CxsGhost/article/details/104794125

——————————————————————————————————————————————————

我们知道MNIST数据集是“手写体数字”,那么既然是手写,就难免会有歪歪扭扭的可能,而这样的数据输入到我们的神经网络中,往往并不会有很好的效果,于是我们可以考虑:用一组“歪歪扭扭”的图像,继续训练强化我们的网络

旋转图像:

看下面的示例,第一张图是原始数据,后两张图像分别是,逆时针和顺时针旋转10度后得到的图像,将这些作为新的数据用来训练,会大大提高模型的能力。
但是一定注意旋转角度不能太大,否则整个数据即将变得混乱不堪,一般±10度足可以了
在这里插入图片描述

如何旋转:

scipy库中为我们提供了这样的函数,可以很简单做到import scipy.ndimage.interpolation.rotate()

scipy.ndimage.interpolation.rotate(each_input.reshape(28, 28), 10, cval=0.01, reshape=False).reshape(1, -1)

上面的代码是把图像顺时针旋转10度,实际上我们是对构成图像的矩阵进行偏转
参数介绍

  • 第一个位置参数,是我们要操作的矩阵,因为在进行训练时数据是784个数字的一行矩阵,这里要先重新排列为28 * 28再转,转完再reshape回来。
  • 第二个位置参数angle,代表旋转的角度,这里我们设为10度
  • 第三个命名参数cval,简单说就是旋转后边缘部分难免会有空缺,这个固定值用来填充,设置0.01即可
  • 第四个命名参数reshape,这里的reshape不同于numpy中对数组的操作,指定为False可以更“柔和的旋转”,或者说防止图像出现看起来“断层”“被截断”的感觉

更多参数详细和标准的解释参见官方文档scipy.ndimage.interpolation.rotate()


代码
下面的代码直接替换之前基础版网络的训练部分即可,就是在原始数据输入训练完成后,紧接着旋转然后再次训练

while True:
    # 对原始数据,旋转后的数据依次进行训练
    for each_train_data in zip(train_data_inputs, train_data_targets):
        each_input = each_train_data[0]
        each_target = each_train_data[1]
        DNN.train(each_input, each_target)
        # 把图像旋转后再次进行训练
        each_input_plus10 = scipy.ndimage.interpolation.rotate(each_input.reshape(28, 28),
                                                               10, cval=0.01, reshape=False).reshape(1, -1)
        DNN.train(each_input_plus10, each_target)
        each_input_minus10 = scipy.ndimage.interpolation.rotate(each_input.reshape(28, 28),
                                                                -10, cval=0.01, reshape=False).reshape(1, -1)
        DNN.train(each_input_minus10, each_target)

——————————————————————————————————————————————————

反向查询:

当训练完成后,正常的思路就是正向输入一个图片,然后神经网络将会告诉你是几。但是如果我们从输出端输入一组数据,然后让神经网络进行逆向输出,是否也能得到一组合适的图形呢

代码:
  • 和正向输入的计算思路一样,只需要把矩阵和输入的位置重新调整一下即可
  • 不同之处在于,我们要调整每个节点的激活函数。也就是把sigmoid函数x和y的关系颠倒一下,如下图的推导
    这个函数称为:logit,在scipy中也有提供。下面的代码加在__init__()中
self.inverse_activation_function = lambda y: scipy.special.logit(y)

推导过程

  • 下面的代码添加了一个实例方法,用来反向查询
    可以看到在每次从反向激活函数输出后,都进行数据处理,1.归一化 2. 保底处理
    首先进行归一化是没什么问题的。因为数据可能存在极小的值导致出现inf,所以要加0.01保底
    但是只单纯加上0.01又有超出1的可能,所以先乘0.98,再加0.01无论如何不会超出1,还能保底
    “保底”如果不做的话,会导致反向查询输出结果无法绘制图像
    def back_query(self, back_inputs_list):
        back_inputs = np.array(back_inputs_list, ndmin=2)

        # 计算输出层的反向输出,以及隐藏层的反向输入,并缩放范围至sigmoid函数的范围内!!!
        back_output = self.inverse_activation_function(back_inputs)
        back_hidden_inputs = np.dot(back_output, self.who)
        back_hidden_inputs -= np.min(back_hidden_inputs)
        back_hidden_inputs /= np.max(back_hidden_inputs) - np.min(back_hidden_inputs)
        # 防止从反向激活函数输出为-inf
        back_hidden_inputs = back_hidden_inputs * 0.98 + 0.01

        # 计算隐藏层的反向输出,及输入层的反向输入,最终反向输出
        back_hidden_outputs = self.inverse_activation_function(back_hidden_inputs)
        back_final_outputs = np.dot(back_hidden_outputs, self.wih)
        back_final_outputs -= np.min
利用tensorflow实现的卷积神经网络来进行MNIST数字图像的分类。 #导入numpy模块 import numpy as np #导入tensorflow模块,程序使用tensorflow来实现卷积神经网络 import tensorflow as tf #下载mnist数据集,并从mnist_data目录中读取数据 from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets('mnist_data',one_hot=True) #(1)这里的“mnist_data” 是和当前文件相同目录下的一个文件夹。自己先手工建立这个文件夹,然后从https://yann.lecun.com/exdb/mnist/ 下载所需的4个文件(即该网址中第三段“Four files are available on this site:”后面的四个文件),并放到目录MNIST_data下即可。 #(2)MNIST数据集是手数字字符的数据集。每个样本都是一张28*28像素的灰度手数字图片。 #(3)one_hot表示独热编码,其值被设为true。在分类问题的数据集标注时,如何不采用独热编码的方式, 类别通常就是一个符号而已,比如说是9。但如果采用独热编码的方式,则每个类表示为一个列表list,共计有10个数值,但只有一个为1,其余均为0。例如,“9”的独热编码可以为[00000 00001]. #定义输入数据x和输出y的形状。函数tf.placeholder的目的是定义输入,可以理解为采用占位符进行占位。 #None这个位置的参数在这里被用于表示样本的个数,而由于样本个数此时具体是多少还无法确定,所以这设为None。而每个输入样本的特征数目是确定的,即为28*28。 input_x = tf.placeholder(tf.float32,[None,28*28])/255 #因为每个像素的取值范围是 0~255 output_y = tf.placeholder(tf.int32,[None,10]) #10表示10个类别 #输入层的输入数据input_x被reshape成四维数据,其中第一维的数据代表了图片数量 input_x_images = tf.reshape(input_x,[-1,28,28,1]) test_x = mnist.test.images[:3000] #读取测试集图片的特征,读取3000个图片 test_y = mnist.test.labels[:3000] #读取测试集图片的标签。就是这3000个图片所对应的标签
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值