二.嚼烂python神经网络编程提高篇-探究神经网络内部的工作原理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_35289736/article/details/94144528

神经网络大脑内部

在通常情况下,我们馈送给已受训练的神经网络一个问题,神经网络弹出出个答案。在我们的例子中,这个问题是人类的手写数字图像。答案是表示数字0到9中的某个标签。
如果将这种方式反转,向后操作,会发生什么呢?如果馈送一个标签到输出节点,通过已受训练的网络反向输入信号,直到输入节点弹出一个图像,那会怎么样?下图显示了正常的正向查询和疯狂的反向向后查询的想法。
在这里插入图片描述
来看看如果我们使用标签“0”进行反向查询,会发生什么情况。也就是说,我们向输出节点展示了一些值,除了使用值0.99展示给第一个节点表示标签“0”,其余节点都展示了0.01。换句话说,也就是数组[0.99, 0.01,0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01,0.01]。
在这里插入图片描述
下图显示了其他数字向后查询的结果。
在这里插入图片描述
哇!同样是一些非常有趣的图像,就像使用超声波扫描神经网络的大脑一样。

可用于反向输出网络内部图像的代码:

import sys
import numpy as np
import matplotlib.pyplot as plt
import scipy.special as spp
import json
class Ann2020:
    # 初始化神经网络
    def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
        # 设置每个输入层、隐藏层和输出层的节点数
        self.inodes = inputnodes
        self.hnodes = hiddennodes
        self.onodes = outputnodes

        # 链接权重矩阵,wih和who
        # 数组中的权值为w_i_j,其中链接是从下一层的节点i到节点j
        # w11 w21
        # w12 w22 etc
        self.wih = np.random.normal(0.0, pow(self.inodes, -0.5), (self.hnodes, self.inodes))
        self.who = np.random.normal(0.0, pow(self.hnodes, -0.5), (self.onodes, self.hnodes))

        # 学习率
        self.lr = learningrate

        # 激活函数
        self.activation_function = lambda x: spp.expit(x)
        self.inverse_activation_function = lambda x: spp.logit(x)

        pass

    # 训练神经网络
    def train(self, inputs_list, targets_list):
        # convert inputs list to 2d array
        inputs = np.array(inputs_list, ndmin=2).T
        targets = np.array(targets_list, ndmin=2).T

        # 计算信号到隐藏层
        hidden_inputs = np.dot(self.wih, inputs)
        # 计算从隐层发出的信号
        hidden_outputs = self.activation_function(hidden_inputs)

        # 将信号计算到最终的输出层
        final_inputs = np.dot(self.who, hidden_outputs)
        # 计算最终输出层发出的信号
        final_outputs = self.activation_function(final_inputs)

        # 输出层误差为(目标-实际)
        output_errors = targets - final_outputs
        # 隐藏层错误是output_errors,按权重拆分,在隐藏节点上重新组合
        hidden_errors = np.dot(self.who.T, output_errors)

        # 更新隐藏层和输出层之间链接的权重
        self.who += self.lr * np.dot((output_errors * final_outputs * (1.0 - final_outputs)),
                                     np.transpose(hidden_outputs))

        # 更新输入层和隐藏层之间链接的权重
        self.wih += self.lr * np.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)),
                                     np.transpose(inputs))

        pass

    # 查询神经网络
    def query(self, inputs_list):
        # 将输入列表转换为2d数组
        inputs = np.array(inputs_list, ndmin=2).T

        # 计算信号到隐藏层
        hidden_inputs = np.dot(self.wih, inputs)
        # 计算从隐层发出的信号
        hidden_outputs = self.activation_function(hidden_inputs)

        # 将信号计算到最终的输出层
        final_inputs = np.dot(self.who, hidden_outputs)
        # 计算最终输出层发出的信号
        final_outputs = self.activation_function(final_inputs)

        return final_outputs

    def backquery(self, targets_list):
        # transpose the targets list to a vertical array
        final_outputs = np.array(targets_list, ndmin=2).T

        # calculate the signal into the final output layer
        final_inputs = self.inverse_activation_function(final_outputs)

        # calculate the signal out of the hidden layer
        hidden_outputs = np.dot(self.who.T, final_inputs)
        # scale them back to 0.01 to .99
        hidden_outputs -= np.min(hidden_outputs)
        hidden_outputs /= np.max(hidden_outputs)
        hidden_outputs *= 0.98
        hidden_outputs += 0.01

        # calculate the signal into the hidden layer
        hidden_inputs = self.inverse_activation_function(hidden_outputs)

        # calculate the signal out of the input layer
        inputs = np.dot(self.wih.T, hidden_inputs)
        # scale them back to 0.01 to .99
        inputs -= np.min(inputs)
        inputs /= np.max(inputs)
        inputs *= 0.98
        inputs += 0.01

        return inputs



# 输入、隐藏和输出节点的数量
input_nodes = 784
hidden_nodes = 200 #最佳可调整至500
output_nodes = 10
# 学习率为 0.3
learning_rate = 0.1
# 创建神经网络实例
n = Ann2020(input_nodes, hidden_nodes, output_nodes, learning_rate)
# 测试查询(目前还没有任何有用的含义)

f = np.load('mnist.npz')
x_train, y_train = f['x_train'], f['y_train']
x_test, y_test = f['x_test'], f['y_test']
f.close()
epochs = 1
for e in range(epochs):
    # 遍历所有数据
    for record,y_trainn in zip(x_train,y_train):
        # 缩放输入值
        inputs = (np.asfarray(record[:]).ravel() / 255.0 * 0.99) + 0.01
        # 创建目标输出值(除所需的标签为0.99外,其余均为0.01)
        targets = np.zeros(output_nodes) + 0.01
        # 记录标签
        targets[int(y_trainn)] = 0.99
        n.train(inputs, targets)
        pass
    pass

scorecard = []
for record,y_testn in zip(x_test,y_test):
    # 导入标签
    correct_label = int(y_testn)
    # 预处理输入
    inputs = (np.asfarray(record[:]).ravel() / 255.0 * 0.99) + 0.01
    # 查询神经网络
    outputs = n.query(inputs)
    # 将最大值的索引对应到标签
    label = np.argmax(outputs)
    # 将识别分数添加进列表
    if (label == correct_label):
        # 匹配   计1
        scorecard.append(1)
    else:
        # 不匹配 计0
        scorecard.append(0)
        pass

    pass

scorecard_array = np.asarray(scorecard)
print ("准确率 = ", scorecard_array.sum() / scorecard_array.size)

# 反向查询神经网络

# 测试标签
label = 0
# 创建输出信号,在标签上
targets = np.zeros(output_nodes) + 0.01
# 标签的数据值值
targets[label] = 0.99
print(targets)

# 获取图像数据
image_data = n.backquery(targets)

# 画出图像
plt.imshow(image_data.reshape(28,28), cmap='Greys', interpolation='None')
plt.show()

测试截图:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_35289736/article/details/94144528
今日推荐