├── GUI.py ├── Neuron.py ├── Neuron运行截图.png ├── Readme.txt ├── Readme.txt~ ├── Train_data.txt ├── 方块图案.png ├── 燕子图案.png ├── 箭头图案.png ├── 迭代误差变化a.png └── 迭代误差变化b.png /GUI.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright © 2015-2016 Jay Sinco -v python2.6 3 | 4 | import pygame 5 | from pygame.locals import * 6 | import sys 7 | import pickle 8 | 9 | 10 | # 模块函数 11 | 12 | def fromIntToBinary(num, Max): 13 | if 0 <= num <= Max -1: 14 | mode = [0] * Max 15 | mode[num] = 1 16 | return mode 17 | else: 18 | return [] 19 | 20 | class Block: 21 | def __init__(self, px, py, color=[122,197,205]): 22 | self.color = color 23 | self.px = px 24 | self.py = py 25 | self.clicked = False 26 | 27 | def draw(self): 28 | offset = 1 29 | pygame.draw.rect(Screen,self.color,[self.px+offset,self.py+offset,Side_Length-offset*2, Side_Length-offset*2], 0) 30 | 31 | def isClicked(self, mx, my): 32 | if (self.px<=mx<=self.px+Side_Length) and (self.py<=my<=self.py+Side_Length): 33 | return True 34 | else: 35 | return False 36 | 37 | class BlockList: 38 | def __init__(self, Width_Num, Height_Num): 39 | self.blocks = [Block(w*Side_Length, H2+h*Side_Length) for w in range(Width_Num) for h in range(Height_Num)] 40 | 41 | def draw(self): 42 | for block in self.blocks: 43 | block.draw() 44 | 45 | def onMouseClick(self, mx, my, mouseState): 46 | for block in self.blocks: 47 | if block.isClicked(mx, my): 48 | if mouseState == (1,0,0): 49 | block.color = [255,0,0] # 鼠标划过后block的颜色 50 | block.clicked = True 51 | elif mouseState == (0,0,1): 52 | block.color = [122,197,205] # clear后block的颜色 53 | block.clicked = False 54 | 55 | def onClear(self): 56 | for block in self.blocks: 57 | block.color = [122,197,205] 58 | block.clicked = False 59 | 60 | def blockStatue(self): 61 | statue = [] 62 | for block in self.blocks: 63 | if block.clicked == True: 64 | statue.append(1) 65 | else: 66 | statue.append(0) 67 | return statue 68 | 69 | 70 | 71 | def draw_word(text, pos=(0,0), size=16, color=(0,0,0)): 72 | font = pygame.font.SysFont("Consolas", size) 73 | Screen.blit(font.render(text, True, color), pos) 74 | 75 | def draw_scene(): 76 | pygame.draw.line(Screen,[0,0,0],[0,H2],[W1,H2],1) 77 | pygame.draw.line(Screen,[0,0,0],[0,H2+H1],[W1,H2+H1],1) 78 | pygame.draw.rect(Screen,[0,0,0],[0,0,Window_Width, Window_Height], 1) 79 | draw_word("Number : %s"%(Character), [W1/100,H1+H2+H3/3], 16) 80 | draw_word("Character Recognition", [W1/15,H2/6], 30) 81 | Blocks.draw() 82 | 83 | 84 | 85 | # 参数 86 | Side_Length = 60 # 绘图区方格边长 87 | Height_Num = 5 # 绘图区宽处方格个数 88 | Width_Num = 5 # 绘图区横处方格个数 89 | H1 = Side_Length * Height_Num 90 | W1 = Side_Length * Width_Num 91 | H2 = H1/10 92 | H3 = H1/15 93 | Window_Height = H1+H2+H3 94 | Window_Width = W1 95 | MouseHold = False # 鼠标被按住 96 | Blocks = BlockList(Width_Num, Height_Num) # 构造block集 97 | Character = "" # 当前字符 98 | 99 | 100 | # pygame 初始化 101 | pygame.init() 102 | pygame.display.set_caption('Character Recognition') 103 | Screen = pygame.display.set_mode((Window_Width, Window_Height), 0, 32) 104 | print ''' 105 | ********** GUIDE ******************* 106 | * => Clear drawing all * 107 | * => Write mode file * 108 | * => Number for now * 109 | * => draw * 110 | * => undraw * 111 | ************************************ 112 | ''' 113 | 114 | # 事件循环 115 | 116 | Data_File = open('Train_data.txt', 'w') 117 | Character = "" 118 | Target = -1 119 | 120 | while True: 121 | for event in pygame.event.get(): 122 | if event.type == QUIT: 123 | sys.exit() 124 | if event.type == MOUSEBUTTONDOWN: 125 | MouseHold = True 126 | if event.type == MOUSEBUTTONUP: 127 | MouseHold = False 128 | if event.type == MOUSEMOTION: 129 | if MouseHold: 130 | Blocks.onMouseClick(event.pos[0], event.pos[1], pygame.mouse.get_pressed()) 131 | if event.type == KEYDOWN: 132 | if event.key == K_SPACE: 133 | Blocks.onClear() 134 | if 48 <= event.key <= 57: 135 | Target = event.key - 48 136 | Character = "%s" %(str(Target)) 137 | if event.key == K_RETURN: 138 | BsL = [] 139 | BsL.append(Blocks.blockStatue()) 140 | BsL.append(fromIntToBinary(Target, 3)) 141 | pickle.dump(BsL, Data_File, 0) 142 | print "Dump into file => ", BsL 143 | 144 | Screen.fill((255, 255, 255)) 145 | draw_scene() 146 | pygame.display.update() 147 | 148 | 149 | Data_File.close() 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /Neuron.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf8 -*- 2 | # Copyright © 2015-2016 Jay Sinco -v python2.6 3 | 4 | import random 5 | import math 6 | import matplotlib.pyplot as plt 7 | 8 | #import pickle 9 | 10 | def rand(a, b): 11 | ''' 生成[a,b)内的随机数 ''' 12 | return (b - a)*random.random() + a 13 | 14 | def makeMatrix(I, J, fill=0.0): 15 | ''' 生成 I*J 大小的矩阵 ''' 16 | return [[fill]*J for i in range(I)] 17 | 18 | def sigmoid(x): 19 | ''' 激活函数 ''' 20 | #return math.tanh(x) 21 | #return 1.0/(1 + math.exp(-x)) 22 | return 0.5 * (1 + math.tanh(0.5 * x)) 23 | 24 | class Neuron: 25 | def __init__(self, ni, nh, no, A = 0.5, B = 0.1): 26 | ''' 输入层,隐层,输出层的初始化 ''' 27 | # 网络学习率和动量因子设定 28 | self.A = A 29 | self.B = B 30 | # 考虑到神经元阈值,输入层+1,且应初始化为 1 31 | self.ni = ni + 1 32 | self.nh = nh 33 | self.no = no 34 | # 设置各层的存储向量 35 | self.ai = [1.0] * self.ni 36 | self.ah = [1.0] * self.nh 37 | self.ao = [1.0] * self.no 38 | # 最后建立动量因子矩阵 39 | self.ci = makeMatrix(self.ni, self.nh) 40 | self.co = makeMatrix(self.nh, self.no) 41 | # 设置权值矩阵 42 | self.wi = makeMatrix(self.ni, self.nh) 43 | self.wo = makeMatrix(self.nh, self.no) 44 | # 初始化权值矩阵 45 | for i in range(self.ni): 46 | for j in range(self.nh): 47 | for k in range(self.no): 48 | self.wi[i][j] = rand(-0.2, 0.2) 49 | self.wo[j][k] = rand(-2.0, 2.0) 50 | 51 | def runfront(self, inputs): 52 | ''' 正向传播,inputs为单个训练样本输入''' 53 | if len(inputs) != self.ni - 1: 54 | raise ValueError("输入节点数错误") 55 | # 计算输入层输出 56 | for i in range(self.ni - 1): 57 | self.ai[i] = inputs[i] 58 | # 计算隐层输出 59 | for j in range(self.nh): 60 | self.ah[j] = sigmoid(sum([self.ai[i]*self.wi[i][j] for i in range(self.ni)])) 61 | # 计算输入层输出 62 | for k in range(self.no): 63 | self.ao[k] = sigmoid(sum([self.ah[j]*self.wo[j][k] for j in range(self.nh)])) 64 | return self.ao 65 | 66 | def runback(self, outputs): 67 | ''' 反向传播, outputs为训练样本期望输出 ''' 68 | Error = 0.0 # 网络误差 69 | if len(outputs) != self.no: 70 | raise ValueError('输出节点数错误') 71 | # 计算输出层误差 72 | output_deltas = [0.0] * self.no 73 | for k in range(self.no): 74 | reo = self.ao[k] # 实际输出 75 | wano = outputs[k] # 期望输出 76 | output_deltas[k] = (wano - reo) * (1 - reo**2) 77 | Error += 0.5 * (wano - reo)**2 # 计算整体网络误差 78 | # 计算隐层误差 79 | hidden_deltas = [0.0] * self.nh 80 | for j in range(self.nh): 81 | reo = self.ah[j] 82 | error = 0.0 83 | for k in range(self.no): 84 | error += output_deltas[k] * self.wo[j][k] 85 | hidden_deltas[j] = (1 - reo**2) * error 86 | # 更新输出层权值 87 | for j in range(self.nh): 88 | for k in range(self.no): 89 | change = output_deltas[k] * self.ah[j] 90 | self.wo[j][k] += self.A * change + self.B * self.co[j][k] 91 | self.co[j][k] = change 92 | # 更新隐层权重 93 | for i in range(self.ni): 94 | for j in range(self.nh): 95 | change = hidden_deltas[j] * self.ai[i] 96 | self.wi[i][j] += self.A * change + self.B * self.ci[i][j] 97 | self.ci[i][j] = change 98 | return Error 99 | 100 | def train(self, dataSet, iteration): 101 | ''' 训练网络,打印训练样本的整体误差 ''' 102 | for i in range(iteration): 103 | All_Error = 0.0 104 | for data in dataSet: 105 | self.runfront(data[0]) 106 | All_Error += self.runback(data[1]) 107 | Logger.append(All_Error) 108 | if i%100 == 0: 109 | print i, "Iter's error: ", All_Error 110 | print "样本已完成%d次迭代训练"%iteration,"下面开始测试\n" 111 | 112 | 113 | 114 | # 构造神经网络 115 | N_In = 25 # 输入层神经元数量 116 | N_Out = 3 # 输出层神经元数量 117 | N_Hidden = 8 # 隐层神经元数量 118 | N_Train = 1000 # 训练次数 119 | Alpha = 0.8 # 学习常数 120 | Belta = 0.5 # 动量因子 121 | NN = Neuron(N_In, N_Hidden, N_Out, Alpha, Belta) 122 | 123 | Logger = [] # 记录迭代中的误差变化 124 | 125 | # 从文件中获取训练数据 126 | #Train_File = open('Train_data.txt', 'r') 127 | #Train_Set = [] 128 | #for i in range(N_Out): 129 | # Train_Set.append(pickle.load(Train_File)) 130 | #Train_File.close() 131 | #print Train_Set 132 | 133 | Train_Set = [ 134 | [[1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1], [1, 0, 0]], # 燕子图案 135 | [[1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1], [0, 1, 0]], # 箭头 136 | [[1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1], [0, 0, 1]] # 方块 137 | ] 138 | 139 | # 训练 140 | NN.train(Train_Set, N_Train) 141 | 142 | # 画误随迭代次数差变化图 143 | plt.plot(Logger) 144 | plt.xlim(0,150) 145 | plt.xlabel("Iteration-Count") 146 | plt.ylabel("Error") 147 | 148 | plt.show() 149 | 150 | # 测试 151 | def test(n, s): 152 | res = NN.runfront(Train_Set[n][0]) 153 | ide = Train_Set[n][1] 154 | print "** 测试 <%s> 图案"%(s) 155 | print " -实际输出 => [", ", ".join(["%.3f"%d for d in res ]), "]" 156 | print " -理想输出 => [", ", ".join(["%.3f"%d for d in ide ]), "]" 157 | print 158 | 159 | test(0, "燕子") 160 | test(1, "箭头") 161 | test(2, "方块") 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /Neuron运行截图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smilelhh/Neural_NetWork/ea32710b07daeb0090fff2dd495eaa5bc7404584/Neuron运行截图.png -------------------------------------------------------------------------------- /Readme.txt: -------------------------------------------------------------------------------- 1 | 【文件列表】 2 | 3 | -- GUI.py 模式识别的窗口界面文件 4 | -- Neuron.py 神经网络构造主程序 5 | -- Neuron运行截图.png Neuron.py运行后的结果屏幕截图 6 | -- **图案.png 需要识别的三种模式图像化表示,由GUI.py创建和生成 7 | -- 迭代误差变化*.png 迭代训练次数和网络整体误差间的变化关系(1000次整体图 200次局部图) 8 | -- Train_data.txt GUI.py运行时生成的临时文件,存储由GUI生成的训练样本 9 | -- Readme.txt 作解释用途 10 | 11 | 12 | 13 | 【源文件说明】 14 | 15 | -- Neuron.py 16 | -- 目标是构造一个神经网络,识别三种基于5*5方格的图像模式(即"**图案.png"文件序列所显示的"方块,箭头,燕子图案") 17 | -- 构造了一个Neuron类用来模拟多层前反馈型神经网络系统,含一个隐藏层 18 | -- 采用基于附加动量法的BP网络算法来调整权值矩阵 19 | -- 经过测试后决定采用25-8-3的三次网络结构,即25个输入,8个隐层,3个输出 20 | -- 反复实验,发现学习率取0.8,动量因子取0.5,学习效果较好 21 | 22 | 23 | -- GUI.py 24 | -- 目标是构造可视化截面,用来绘制需要识别的模式,并导出0-1形式的训练样本 25 | -- 使用方法: 鼠标左键选定方格,右键取消选定;空格键清除全部绘图;Enter键写入训练样本;数字键标识样本目标值; 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Readme.txt~: -------------------------------------------------------------------------------- 1 | 【文件列表】 2 | 3 | -- GUI.py 模式识别的窗口界面文件 4 | -- Neuron.py 神经网络构造主程序 5 | -- Neuron运行截图.png Neuron.py运行后的结果屏幕截图 6 | -- **图案.png 需要识别的三种模式图像化表示,由GUI.py创建和生成 7 | -- 迭代误差变化*.png 迭代训练次数和网络整体误差间的变化关系(1000次整体图 200次局部图) 8 | -- Train_data.txt GUI.py运行时生成的临时文件,存储由GUI生成的训练样本 9 | -- Readme.txt 做解释用途 10 | 11 | 12 | 13 | 【源文件说明】 14 | 15 | -- Neuron.py 16 | -- 目标是构造一个神经网络,识别三种基于5*5方格的图像模式(即"**图案.png"文件序列所显示的"方块,箭头,燕子图案") 17 | -- 构造了一个Neuron类用来模拟多层前反馈型神经网络系统,含一个隐藏层 18 | -- 采用基于附加动量法的BP网络算法来调整权值矩阵 19 | -- 经过测试后决定采用25-8-3的三次网络结构,即25个输入,8个隐层,3个输出 20 | -- 反复实验,发现学习率取0.8,动量因子取0.5,学习效果较好 21 | 22 | 23 | -- GUI.py 24 | -- 目标是构造可视化截面,用来绘制需要识别的模式,并导出0-1形式的训练样本 25 | -- 使用方法: 鼠标左键选定方格,右键取消选定;空格键清除全部绘图;Enter键写入训练样本;数字键标识样本目标值; 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Train_data.txt: -------------------------------------------------------------------------------- 1 | (lp0 2 | (lp1 3 | I1 4 | aI0 5 | aI1 6 | aI0 7 | aI0 8 | aI1 9 | aI0 10 | aI1 11 | aI0 12 | aI0 13 | aI1 14 | aI1 15 | aI1 16 | aI1 17 | aI1 18 | aI0 19 | aI1 20 | aI1 21 | aI0 22 | aI0 23 | aI1 24 | aI0 25 | aI1 26 | aI1 27 | aI1 28 | aa(lp2 29 | I1 30 | aI0 31 | aI0 32 | aa.(lp0 33 | (lp1 34 | I1 35 | aI1 36 | aI1 37 | aI1 38 | aI1 39 | aI0 40 | aI0 41 | aI0 42 | aI1 43 | aI1 44 | aI0 45 | aI0 46 | aI1 47 | aI0 48 | aI1 49 | aI0 50 | aI1 51 | aI0 52 | aI0 53 | aI1 54 | aI1 55 | aI0 56 | aI0 57 | aI0 58 | aI1 59 | aa(lp2 60 | I0 61 | aI1 62 | aI0 63 | aa.(lp0 64 | (lp1 65 | I1 66 | aI1 67 | aI0 68 | aI1 69 | aI1 70 | aI1 71 | aI1 72 | aI0 73 | aI1 74 | aI1 75 | aI0 76 | aI0 77 | aI1 78 | aI0 79 | aI0 80 | aI1 81 | aI1 82 | aI0 83 | aI1 84 | aI1 85 | aI1 86 | aI1 87 | aI0 88 | aI1 89 | aI1 90 | aa(lp2 91 | I0 92 | aI0 93 | aI1 94 | aa. -------------------------------------------------------------------------------- /方块图案.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smilelhh/Neural_NetWork/ea32710b07daeb0090fff2dd495eaa5bc7404584/方块图案.png -------------------------------------------------------------------------------- /燕子图案.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smilelhh/Neural_NetWork/ea32710b07daeb0090fff2dd495eaa5bc7404584/燕子图案.png -------------------------------------------------------------------------------- /箭头图案.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smilelhh/Neural_NetWork/ea32710b07daeb0090fff2dd495eaa5bc7404584/箭头图案.png -------------------------------------------------------------------------------- /迭代误差变化a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smilelhh/Neural_NetWork/ea32710b07daeb0090fff2dd495eaa5bc7404584/迭代误差变化a.png -------------------------------------------------------------------------------- /迭代误差变化b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smilelhh/Neural_NetWork/ea32710b07daeb0090fff2dd495eaa5bc7404584/迭代误差变化b.png --------------------------------------------------------------------------------