版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
“纸上得来终觉浅,绝知此事须躬行。”
1. 创建、训练和查询3层神经网络:
import numpy as np
import matplotlib.pyplot as plt
import scipy.special as spp
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)
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
# 输入、隐藏和输出节点的数量
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 = 5
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)
准确率高达98%
2. 自制自己的手写数字图像进行测试:
我所使用的手机拍摄图片:
自制图像的去噪与黑白转换代码:
# -*- coding: utf-8 -*-
# 图像去噪并转化为黑白图像
import os
from PIL import Image
curdir = "F:\\pyth\\shendu\\CNN2019\\image"
os.chdir(curdir)
def RGB2B(filename):
im = Image.open(filename)
print("image info,", im.format, im.mode, im.size)
(w, h) = im.size
R = 0
G = 0
B = 0
for x in range(w):
for y in range(h):
pos = (x, y)
rgb = im.getpixel(pos)
(r, g, b) = rgb
R = R + r
G = G + g
B = B + b
rate1 = R * 1000 / (R + G + B)
rate2 = G * 1000 / (R + G + B)
rate3 = B * 1000 / (R + G + B)
print("rate:", rate1, rate2, rate3)
for x in range(w):
for y in range(h):
pos = (x, y)
rgb = im.getpixel(pos)
(r, g, b) = rgb
n = r * rate1 / 1000 + g * rate2 / 1000 + b * rate3 / 1000
# print "n:",n
if n >= 155:
im.putpixel(pos, (255, 255, 255))
else:
im.putpixel(pos, (0, 0, 0))
im.save('my_image3_whiteb.png')
def saveAsBmp(fname):
pos1 = fname.rfind('.')
fname1 = fname[0:pos1]
fname1 = fname1 + '_hui.png'
im = Image.open(fname)
new_im = Image.new("RGB", im.size)
new_im.paste(im)
new_im.save(fname1)
return fname1
if __name__ == "__main__":
filename = saveAsBmp("my_image3.png")
RGB2B(filename)
将测试部分转换为自己的图像测试:
our_own_dataset = []
# 获得测试图像信息
for image_file_name in glob.glob('my_image?.png'):
# 使用倒数第五个字符作为正确标签
label = int(image_file_name[-5:-4])
# 获得图像
print("loading ... ", image_file_name)
img_array = imageio.imread(image_file_name, as_gray=True)
# 转化为一维数组 并反转
img_data = 255.0 - img_array.reshape(784)
# 把像素值转为到0.01到0.99之间
img_data = (img_data / 255.0 * 0.99) + 0.01
print(np.min(img_data))
print(np.max(img_data))
# 添加图像标签和信息到列表
record = np.append(label, img_data)
our_own_dataset.append(record)
pass
item = 3
# 画出图像
plt.imshow(our_own_dataset[item][1:].reshape(28,28), cmap='Greys', interpolation='None')
#拿到正确标签
correct_label = our_own_dataset[item][0]
# data is remaining values
inputs = our_own_dataset[item][1:]
# 查询神经网络
outputs = n.query(inputs)
print (outputs)
# 与输出最高的得分标签进行比较
label = np.argmax(outputs)
print("机器判断为:", label)
# 输出判断正误
if (label == correct_label):
print ("识别正确!")
else:
print ("识别错误!")
pass
plt.show()