三层神经网络识别手写体数字(自己制作训练集)
整个部分分为训练集制作和运行网络两个部分
一、首先制作训练集
目录分布如下:分为data、test、手写数字数据集和两个脚本
步骤一: 自己手写几张数字,用手机拍照放在“手写数字数据集”,为了避免麻烦,每个图片对应的标签直接将照片命名为相应的数字,有重复的数字依次保存即可(只要第一个数字正确即可),例如数字“7”拍了很多张,保存成“7.jpg、7(1).jpg、7(2).jpg…”
如图所示:
步骤二:data里面放训练集,考虑到自己手机照的像素不一致,需要将照片全部改为28*28像素大小,运行“改变像素.py”,注意:手机照的图片放在“手写数字数据集”。
下面展示 改变像素.py
// 改变像素后存入到data文件夹下,原始手机图片放在“手写数字数据集”
import os
from PIL import Image
def image_processing():
# 待处理图片路径下的所有文件名字
all_file_names = os.listdir('手写数字数据集')
for file_name in all_file_names:
print(file_name)
# 待处理图片路径
img_path = Image.open(f'手写数字数据集\\{file_name}')
# resize图片大小,入口参数为一个tuple,新的图片的大小
img_size = img_path.resize((28, 28))
# 处理图片后存储路径,以及存储格式
img_size.save(f'data\\{file_name}', 'JPEG')
if __name__ == '__main__':
image_processing()
运行结束后data文件就出现制作好的训练集~
步骤三:测试集放入想要测试的图片,注意:像素也改成28*28,且命名方式和训练集一致,只需要把上述脚本其中两行做相应的改动即可,在运行一下,test就出现了制作好的测试集~
img_path = Image.open(f'手写数字数据集\\{file_name}')
img_size.save(f'data\\{file_name}', 'JPEG')
改为:
img_path = Image.open(f'XXXXX\\{file_name}')#XXXXX是用来测试的文件夹,存放没有拿来训练的原始手机照片
img_size.save(f'test\\{file_name}', 'JPEG')
步骤四:运行“神经网络(第三版).py”脚本即可出现结果:
下面展示 神经网络(第三版).py
import numpy
import scipy.special
import os
import re
import imageio
class neuraNetwork:
#初始化神经网络
#输入层节点、隐藏层节点、输出层节点数量
def __init__(self,inputnodes,hiddennodes,outputnodes,learningrate):
self.inodes = inputnodes #定义输入节点数
self.hondes = hiddennodes#定义隐藏层节点数
self.onodes = outputnodes#定义输出层节点数
self.lr = learningrate#定义学习率
self.wih = numpy.random.normal(0.0,pow(self.inodes,-0.5),(self.hondes,self.inodes))#定义输入层到隐藏层的权重矩阵
self.who = numpy.random.normal(0.0,pow(self.hondes,-0.5),(self.onodes,self.hondes))#定义隐藏层到输出层的权重矩阵
self.activation_function = lambda x: scipy.special.expit(x)
#训练神经网络
def train(self,inputs_list,targets_list):
inputs = numpy.array(inputs_list,ndmin=2).T
targets = numpy.array(targets_list,ndmin=2).T
hidden_inputs = numpy.dot(self.wih,inputs)
hidden_outputs = self.activation_function(hidden_inputs)#隐藏层输出
final_inputs = numpy.dot(self.who,hidden_outputs)
final_outputs = self.activation_function(final_inputs)#输出层输出
#计算误差
output_errors = targets - final_outputs #计算目标标记值-计算的输出值的误差
hidden_errors = numpy.dot(self.who.T,output_errors) #根据权重分割误差
#更新两层权重
self.who += self.lr * numpy.dot((output_errors * final_outputs) * (1.0 - final_outputs),numpy.transpose(hidden_outputs))
self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs) * (1.0 - hidden_outputs),numpy.transpose(inputs))
#梯度下降法更新权重
#预测
def query(self, inputs_list):
inputs = numpy.array(inputs_list, ndmin=2).T
hidden_inputs = numpy.dot(self.wih, inputs)
hidden_outputs = self.activation_function(hidden_inputs)
final_inputs = numpy.dot(self.who, hidden_outputs)
final_outputs = self.activation_function(final_inputs)
return final_outputs
#*****************************************************************************************************************
#训练part
def train_first():
inputs = []
global epochs
all_file_names = os.listdir('data')
while epochs:
for file_name in all_file_names:
img_array = imageio.imread(f'data\\{file_name}', as_gray=True)
image_data = 255.0 - img_array.reshape(784)
# print(image_data)
image_data = (image_data / 255.0 * 0.99) + 0.01
inputs.append(image_data)
targets = numpy.zeros(outputs_nodes) + 0.01
num = re.findall("\d+",file_name)
num_ = num[0]
targets[int(num_)] = 0.99
n_train.train(image_data, targets)
print(f'训练了{n-epochs+1}次')
epochs -= 1
print('训练完成!')
#*****************************************************************************************************************
#测试part
def perdict():
files = os.listdir('test')
add = []
for file in files:
img_array = imageio.imread(f'test\\{file}', as_gray=True)
image_data = 255.0-img_array.reshape(784)
image_data = (image_data/255.0*0.99)+0.01
outputs = n_train.query(image_data)
num = re.findall("\d+", file)#图片名字
num_ = int(num[0])
label = numpy.argmax(outputs) #网络的预测结果值
print(num_,label,'真实值:预测值')
if num_ == label:
add.append(1)
else:
add.append(0)
scorecard_array = numpy.asanyarray(add)
print('预测完成!')
print("准确率==", scorecard_array.sum() / scorecard_array.size)
#***********************************************************************************************************
if __name__ == '__main__':
input_nodes = 784 #输入节点数(像素:28*28=784)
hidden_nodes = 100 #隐藏层节点数
outputs_nodes = 10 #输出节点数(预测0~9)
learning_rate = 0.1 #学习率
epochs = n = 300 #训练样本循环次数
n_train = neuraNetwork(input_nodes,hidden_nodes,outputs_nodes,learning_rate)
train_first()
perdict()
结果: