版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
神经网络大脑内部
在通常情况下,我们馈送给已受训练的神经网络一个问题,神经网络弹出出个答案。在我们的例子中,这个问题是人类的手写数字图像。答案是表示数字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()