请选择 进入手机版 | 继续访问电脑版

Hello Mat

 找回密码
 立即注册
查看: 4280|回复: 0

基于BP神经网络的手写数字识别

[复制链接]

1064

主题

1239

帖子

13

金钱

管理员

Rank: 9Rank: 9Rank: 9

积分
21393
发表于 2018-5-27 22:08:09 | 显示全部楼层 |阅读模式
基于BP神经网络的手写数字识别
运行结果视频:https://pan.baidu.com/s/1x2wGGBZ8iBIEYU2IZRv0OQ
  1. """
  2. Created on Sun May 20 21:38:45 2018

  3. @author: ysw
  4. """
  5. #-*- coding: utf-8 -*-
  6. #from PIL import Image
  7. import numpy as np
  8. from scipy import io as spio
  9. from scipy import optimize
  10. from matplotlib import pyplot as plt
  11. #from sklearn import datasets
  12. #from sklearn.preprocessing import StandardScaler
  13. import time
  14.                
  15. # BP
  16. def BPneuralNetwork(X, y, input_layer_size,hidden_layer_size,out_put_layer):
  17.     m,n = X.shape
  18.     ## 随机显示几行数据
  19.     rand_indices = [t for t in [np.random.randint(x-x, m) for x in range(100)]]  # 生成100个0-m的随机数
  20.     display_data(X[rand_indices,:])     # 显示100个数字   
  21.    
  22.     Lambda = 1
  23.     initial_Theta1 = randInitializeWeights(input_layer_size,hidden_layer_size);
  24.     initial_Theta2 = randInitializeWeights(hidden_layer_size,out_put_layer)
  25.     initial_nn_params = np.vstack((initial_Theta1.reshape(-1,1),initial_Theta2.reshape(-1,1)))  #展开theta   
  26.     result = optimize.fmin_cg(nnCostFunction, initial_nn_params, fprime=nnGradient, args=(input_layer_size,hidden_layer_size,out_put_layer,X,y,Lambda), maxiter=100)
  27.     '''可视化 Theta1'''
  28.     length = result.shape[0]
  29.     Theta1 = result[0:hidden_layer_size*(input_layer_size+1)].reshape(hidden_layer_size,input_layer_size+1)
  30.     Theta2 = result[hidden_layer_size*(input_layer_size+1):length].reshape(out_put_layer,hidden_layer_size+1)   
  31.     return Theta1, Theta2

  32. # 显示100个数字
  33. def display_data(imgData):
  34.     sum = 0
  35.     '''
  36.     显示100个数(若是一个一个绘制将会非常慢,可以将要画的数字整理好,放到一个矩阵中,显示这个矩阵即可)
  37.     - 初始化一个二维数组
  38.     - 将每行的数据调整成图像的矩阵,放进二维数组
  39.     - 显示即可
  40.     '''
  41.     m,n = imgData.shape
  42.     width = np.int32(np.round(np.sqrt(n)))
  43.     height = np.int32(n/width);
  44.     rows_count = np.int32(np.floor(np.sqrt(m)))
  45.     cols_count = np.int32(np.ceil(m/rows_count))
  46.     pad = 1
  47.     display_array = -np.ones((pad+rows_count*(height+pad),pad+cols_count*(width+pad)))
  48.     for i in range(rows_count):
  49.         for j in range(cols_count):
  50.             if sum >= m: #超过了行数,退出当前循环
  51.                 break;
  52.             display_array[pad+i*(height+pad):pad+i*(height+pad)+height,pad+j*(width+pad):pad+j*(width+pad)+width] = imgData[sum,:].reshape(height,width,order="F")    # order=F指定以列优先,在matlab中是这样的,python中需要指定,默认以行
  53.             sum += 1
  54.         if sum >= m:  #超过了行数,退出当前循环
  55.             break;
  56.             
  57. #    plt.imshow(np.transpose(display_array),cmap='gray')   #显示灰度图像
  58.     plt.imshow(display_array, cmap='gray')   #显示灰度图像
  59.     plt.axis('off')
  60.     plt.show()

  61. # 代价函数
  62. def nnCostFunction(nn_params,input_layer_size,hidden_layer_size,num_labels,X,y,Lambda):
  63.     length = nn_params.shape[0] # theta的中长度
  64.     # 还原theta1和theta2
  65.     Theta1 = nn_params[0:hidden_layer_size*(input_layer_size+1)].reshape(hidden_layer_size,input_layer_size+1)
  66.     Theta2 = nn_params[hidden_layer_size*(input_layer_size+1):length].reshape(num_labels,hidden_layer_size+1)
  67.    
  68.     m = X.shape[0]
  69.     class_y = np.zeros((m,num_labels))      # 数据的y对应0-9,需要映射为0/1的关系
  70.     # 映射y
  71.     for i in range(num_labels):
  72.         class_y[:,i] = np.int32(y==i).reshape(1,-1) # 注意reshape(1,-1)才可以赋值
  73.      
  74.     '''去掉theta1和theta2的第一列,因为正则化时从1开始'''   
  75.     Theta1_colCount = Theta1.shape[1]   
  76.     Theta1_x = Theta1[:,1:Theta1_colCount]
  77.     Theta2_colCount = Theta2.shape[1]   
  78.     Theta2_x = Theta2[:,1:Theta2_colCount]
  79.     # 正则化向theta^2
  80.     term = np.dot(np.transpose(np.vstack((Theta1_x.reshape(-1,1),Theta2_x.reshape(-1,1)))),np.vstack((Theta1_x.reshape(-1,1),Theta2_x.reshape(-1,1))))
  81.    
  82.     '''正向传播,每次需要补上一列1的偏置bias'''
  83.     a1 = np.hstack((np.ones((m,1)),X))      
  84.     z2 = np.dot(a1,np.transpose(Theta1))   
  85.     a2 = sigmoid(z2)
  86.     a2 = np.hstack((np.ones((m,1)),a2))
  87.     z3 = np.dot(a2,np.transpose(Theta2))
  88.     h  = sigmoid(z3)   
  89.     '''代价'''   
  90.     J = -(np.dot(np.transpose(class_y.reshape(-1,1)),np.log(h.reshape(-1,1)))+np.dot(np.transpose(1-class_y.reshape(-1,1)),np.log(1-h.reshape(-1,1)))-Lambda*term/2)/m   
  91.     #temp1 = (h.reshape(-1,1)-class_y.reshape(-1,1))
  92.     #temp2 = (temp1**2).sum()
  93.     #J = 1/(2*m)*temp2
  94.     return np.ravel(J)

  95. # 梯度
  96. def nnGradient(nn_params,input_layer_size,hidden_layer_size,num_labels,X,y,Lambda):
  97.     length = nn_params.shape[0]
  98.     Theta1 = nn_params[0:hidden_layer_size*(input_layer_size+1)].reshape(hidden_layer_size,input_layer_size+1).copy()   # 这里使用copy函数,否则下面修改Theta的值,nn_params也会一起修改
  99.     Theta2 = nn_params[hidden_layer_size*(input_layer_size+1):length].reshape(num_labels,hidden_layer_size+1).copy()
  100.     m = X.shape[0]
  101.     class_y = np.zeros((m,num_labels))      # 数据的y对应0-9,需要映射为0/1的关系   
  102.     # 映射y
  103.     for i in range(num_labels):
  104.         class_y[:,i] = np.int32(y==i).reshape(1,-1) # 注意reshape(1,-1)才可以赋值
  105.      
  106.     '''去掉theta1和theta2的第一列,因为正则化时从1开始'''
  107.     Theta1_colCount = Theta1.shape[1]   
  108.     Theta1_x = Theta1[:,1:Theta1_colCount]
  109.     Theta2_colCount = Theta2.shape[1]   
  110.     Theta2_x = Theta2[:,1:Theta2_colCount]
  111.    
  112.     Theta1_grad = np.zeros((Theta1.shape))  #第一层到第二层的权重
  113.     Theta2_grad = np.zeros((Theta2.shape))  #第二层到第三层的权重
  114.       
  115.     '''正向传播,每次需要补上一列1的偏置bias'''
  116.     a1 = np.hstack((np.ones((m,1)),X))
  117.     z2 = np.dot(a1,np.transpose(Theta1))
  118.     a2 = sigmoid(z2)
  119.     a2 = np.hstack((np.ones((m,1)),a2))
  120.     z3 = np.dot(a2,np.transpose(Theta2))
  121.     h  = sigmoid(z3)
  122.    
  123.     '''反向传播,delta为误差,'''
  124.     delta3 = np.zeros((m,num_labels))
  125.     delta2 = np.zeros((m,hidden_layer_size))
  126.     for i in range(m):
  127.         #delta3[i,:] = (h[i,:]-class_y[i,:])*sigmoidGradient(z3[i,:])  # 均方误差的误差率
  128.         delta3[i,:] = h[i,:]-class_y[i,:]                              # 交叉熵误差率
  129.         Theta2_grad = Theta2_grad+np.dot(np.transpose(delta3[i,:].reshape(1,-1)),a2[i,:].reshape(1,-1))
  130.         delta2[i,:] = np.dot(delta3[i,:].reshape(1,-1),Theta2_x)*sigmoidGradient(z2[i,:])
  131.         Theta1_grad = Theta1_grad+np.dot(np.transpose(delta2[i,:].reshape(1,-1)),a1[i,:].reshape(1,-1))
  132.    
  133.     Theta1[:,0] = 0
  134.     Theta2[:,0] = 0         
  135.     '''梯度'''
  136.     grad = (np.vstack((Theta1_grad.reshape(-1,1),Theta2_grad.reshape(-1,1)))+Lambda*np.vstack((Theta1.reshape(-1,1),Theta2.reshape(-1,1))))/m
  137.     return np.ravel(grad)

  138. # S型函数   
  139. def sigmoid(z):
  140.     h = np.zeros((len(z),1))    # 初始化,与z的长度一致
  141.     h = 1.0/(1.0+np.exp(-z))
  142.     return h

  143. # S型函数导数
  144. def sigmoidGradient(z):
  145.     g = sigmoid(z)*(1-sigmoid(z))
  146.     return g

  147. # 随机初始化权重theta
  148. def randInitializeWeights(L_in,L_out):
  149.     W = np.zeros((L_out,1+L_in))    # 对应theta的权重
  150.     epsilon_init = (6.0/(L_out+L_in))**0.5
  151.     W = np.random.rand(L_out,1+L_in)*2*epsilon_init-epsilon_init # np.random.rand(L_out,1+L_in)产生L_out*(1+L_in)大小的随机矩阵
  152.     return W

  153. # 预测
  154. def predict(Theta1, Theta2, X):
  155.     m = X.shape[0]
  156.     num_labels = Theta2.shape[0]
  157.     #p = np.zeros((m,1))
  158.     '''正向传播,预测结果'''
  159.     X = np.hstack((np.ones((m,1)),X))
  160.     h1 = sigmoid(np.dot(X,np.transpose(Theta1)))
  161.     h1 = np.hstack((np.ones((m,1)),h1))
  162.     h2 = sigmoid(np.dot(h1,np.transpose(Theta2)))
  163.    
  164.     '''
  165.     返回h中每一行最大值所在的列号
  166.     - np.max(h, axis=1)返回h中每一行的最大值(是某个数字的最大概率)
  167.     - 最后where找到的最大概率所在的列号(列号即是对应的数字)
  168.     '''
  169.     #np.savetxt("h2.csv",h2,delimiter=',')
  170.     p = np.array(np.where(h2[0,:] == np.max(h2, axis=1)[0]))  
  171.     for i in np.arange(1, m):
  172.         t = np.array(np.where(h2[i,:] == np.max(h2, axis=1)[i]))
  173.         p = np.vstack((p,t))
  174.     return p   

  175. # 加载mat文件
  176. def loadmat_data(fileName):
  177.     return spio.loadmat(fileName)

  178. if __name__ == "__main__":
  179.     # 加载数据
  180.     data_img = loadmat_data("data_digits.mat")
  181.     X = data_img['X']
  182.     y = data_img['y']   
  183.     input_layer_size = 400;
  184.     hidden_layer_size = 25;
  185.     out_put_layer = 10;
  186.     start = time.time()
  187.     Theta1, Theta2 = BPneuralNetwork(X, y, input_layer_size, hidden_layer_size, out_put_layer)
  188.     print ('\n')
  189.     print ('\n')
  190.     print ( '执行时间:' )
  191.     print ( time.time()-start )
  192.     '''预测'''
  193.     p = predict(Theta1,Theta2,X)
  194.     print ('预测准确度为:')
  195.     print ( np.mean(np.float64(p == y.reshape(-1,1))*100) )   
  196.     res = np.hstack((p,y.reshape(-1,1)))
  197.     np.savetxt("predict.csv", res, delimiter=',')
复制代码
百度网盘链接:链接:https://pan.baidu.com/s/1wyldRyUqMasP2uGfQ402Eg 密码:uidi






算法QQ  3283892722
群智能算法链接http://halcom.cn/forum.php?mod=forumdisplay&fid=73
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Python|Opencv|MATLAB|Halcom.cn

GMT+8, 2022-7-3 10:44 , Processed in 0.187381 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表