深度学习:不调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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值