1+ #-*- coding: utf-8 -*-
2+ import numpy as np
3+ from scipy import io as spio
4+ from matplotlib import pyplot as plt
5+ from scipy import optimize
6+ from matplotlib .font_manager import FontProperties
7+ font = FontProperties (fname = r"c:\windows\fonts\simsun.ttc" , size = 14 ) # 解决windows环境下画图汉字乱码问题
8+
9+ from sklearn import datasets
10+ from sklearn .preprocessing import StandardScaler
11+
12+ def neuralNetwork (input_layer_size ,hidden_layer_size ,out_put_layer ):
13+ data_img = loadmat_data ("data_digits.mat" )
14+ #data_weights = loadmat_data("weights.mat")
15+ X = data_img ['X' ]
16+ y = data_img ['y' ]
17+ #Theta1 = data_weights['Theta1']
18+ #Theta2 = data_weights['Theta2']
19+
20+
21+ #y = np.ravel(y)
22+ m ,n = X .shape
23+ """digits = datasets.load_digits()
24+ X = digits.data
25+ y = digits.target
26+ m,n = X.shape
27+
28+ scaler = StandardScaler()
29+ scaler.fit(X)
30+ X = scaler.transform(X)"""
31+
32+ ## 随机显示几行数据
33+ rand_indices = [t for t in [np .random .randint (x - x , m ) for x in range (100 )]] # 生成100个0-m的随机数
34+ display_data (X [rand_indices ,:]) # 显示100个数字
35+
36+ #nn_params = np.vstack((Theta1.reshape(-1,1),Theta2.reshape(-1,1)))
37+
38+ Lambda = 1
39+
40+ initial_Theta1 = randInitializeWeights (input_layer_size ,hidden_layer_size );
41+ initial_Theta2 = randInitializeWeights (hidden_layer_size ,out_put_layer )
42+
43+ initial_nn_params = np .vstack ((initial_Theta1 .reshape (- 1 ,1 ),initial_Theta2 .reshape (- 1 ,1 ))) #展开theta
44+ result = optimize .fmin_cg (nnCostFunction , initial_nn_params , fprime = nnGradient , args = (input_layer_size ,hidden_layer_size ,out_put_layer ,X ,y ,Lambda ))
45+ print result
46+ '''可视化 Theta1'''
47+ length = result .shape [0 ]
48+ Theta1 = result [0 :hidden_layer_size * (input_layer_size + 1 )].reshape (hidden_layer_size ,input_layer_size + 1 )
49+ Theta2 = result [hidden_layer_size * (input_layer_size + 1 ):length ].reshape (out_put_layer ,hidden_layer_size + 1 )
50+ display_data (Theta1 [:,1 :length ])
51+ '''预测'''
52+ p = predict (Theta1 ,Theta2 ,X )
53+ print u"预测准确度为:%f%%" % np .mean (np .float64 (p == y .reshape (- 1 ,1 ))* 100 )
54+ res = np .hstack ((p ,y .reshape (- 1 ,1 )))
55+ np .savetxt ("predict.csv" , res , delimiter = ',' )
56+
57+
58+ # 加载mat文件
59+ def loadmat_data (fileName ):
60+ return spio .loadmat (fileName )
61+
62+ # 显示100个数字
63+ def display_data (imgData ):
64+ sum = 0
65+ '''
66+ 显示100个数(若是一个一个绘制将会非常慢,可以将要画的数字整理好,放到一个矩阵中,显示这个矩阵即可)
67+ - 初始化一个二维数组
68+ - 将每行的数据调整成图像的矩阵,放进二维数组
69+ - 显示即可
70+ '''
71+ m ,n = imgData .shape
72+ width = np .int32 (np .round (np .sqrt (n )))
73+ height = np .int32 (n / width );
74+ rows_count = np .int32 (np .floor (np .sqrt (m )))
75+ cols_count = np .int32 (np .ceil (m / rows_count ))
76+ pad = 1
77+ display_array = - np .ones ((pad + rows_count * (height + pad ),pad + cols_count * (width + pad )))
78+ for i in range (rows_count ):
79+ for j in range (cols_count ):
80+ 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中需要指定,默认以行
81+ sum += 1
82+
83+ plt .imshow (display_array ,cmap = 'gray' ) #显示灰度图像
84+ plt .axis ('off' )
85+ plt .show ()
86+
87+ # 代价函数
88+ def nnCostFunction (nn_params ,input_layer_size ,hidden_layer_size ,num_labels ,X ,y ,Lambda ):
89+ length = nn_params .shape [0 ]
90+ Theta1 = nn_params [0 :hidden_layer_size * (input_layer_size + 1 )].reshape (hidden_layer_size ,input_layer_size + 1 )
91+ Theta2 = nn_params [hidden_layer_size * (input_layer_size + 1 ):length ].reshape (num_labels ,hidden_layer_size + 1 )
92+
93+ # np.savetxt("Theta1.csv",Theta1,delimiter=',')
94+
95+ m = X .shape [0 ]
96+ class_y = np .zeros ((m ,num_labels )) # 数据的y对应0-9,需要映射为0/1的关系
97+ # 映射y
98+ for i in range (num_labels ):
99+ class_y [:,i ] = np .int32 (y == i ).reshape (1 ,- 1 ) # 注意reshape(1,-1)才可以赋值
100+
101+
102+ Theta1_colCount = Theta1 .shape [1 ]
103+ Theta1_x = Theta1 [:,1 :Theta1_colCount ]
104+ Theta2_colCount = Theta2 .shape [1 ]
105+ Theta2_x = Theta2 [:,1 :Theta2_colCount ]
106+
107+ 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 ))))
108+
109+ '''正向传播'''
110+ a1 = np .hstack ((np .ones ((m ,1 )),X ))
111+ z2 = np .dot (a1 ,np .transpose (Theta1 ))
112+ a2 = sigmoid (z2 )
113+ a2 = np .hstack ((np .ones ((m ,1 )),a2 ))
114+ z3 = np .dot (a2 ,np .transpose (Theta2 ))
115+ h = sigmoid (z3 )
116+ '''代价'''
117+ 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
118+
119+ return np .ravel (J )
120+
121+ # 梯度
122+ def nnGradient (nn_params ,input_layer_size ,hidden_layer_size ,num_labels ,X ,y ,Lambda ):
123+ length = nn_params .shape [0 ]
124+ Theta1 = nn_params [0 :hidden_layer_size * (input_layer_size + 1 )].reshape (hidden_layer_size ,input_layer_size + 1 )
125+ Theta2 = nn_params [hidden_layer_size * (input_layer_size + 1 ):length ].reshape (num_labels ,hidden_layer_size + 1 )
126+ m = X .shape [0 ]
127+ class_y = np .zeros ((m ,num_labels )) # 数据的y对应0-9,需要映射为0/1的关系
128+ # 映射y
129+ for i in range (num_labels ):
130+ class_y [:,i ] = np .int32 (y == i ).reshape (1 ,- 1 ) # 注意reshape(1,-1)才可以赋值
131+
132+
133+ Theta1_colCount = Theta1 .shape [1 ]
134+ Theta1_x = Theta1 [:,1 :Theta1_colCount ]
135+ Theta2_colCount = Theta2 .shape [1 ]
136+ Theta2_x = Theta2 [:,1 :Theta2_colCount ]
137+
138+ Theta1_grad = np .zeros ((Theta1 .shape ))
139+ Theta2_grad = np .zeros ((Theta2 .shape ))
140+
141+ Theta1 [:,0 ] = 0 ;
142+ Theta2 [:,0 ] = 0 ;
143+ '''正向传播'''
144+ a1 = np .hstack ((np .ones ((m ,1 )),X ))
145+ z2 = np .dot (a1 ,np .transpose (Theta1 ))
146+ a2 = sigmoid (z2 )
147+ a2 = np .hstack ((np .ones ((m ,1 )),a2 ))
148+ z3 = np .dot (a2 ,np .transpose (Theta2 ))
149+ h = sigmoid (z3 )
150+
151+ '''反向传播'''
152+ delta3 = np .zeros ((m ,num_labels ))
153+ delta2 = np .zeros ((m ,hidden_layer_size ))
154+ for i in range (m ):
155+ delta3 [i ,:] = h [i ,:]- class_y [i ,:]
156+ Theta2_grad = Theta2_grad + np .dot (np .transpose (delta3 [i ,:].reshape (1 ,- 1 )),a2 [i ,:].reshape (1 ,- 1 ))
157+ delta2 [i ,:] = np .dot (delta3 [i ,:].reshape (1 ,- 1 ),Theta2_x )* sigmoidGradient (z2 [i ,:])
158+ Theta1_grad = Theta1_grad + np .dot (np .transpose (delta2 [i ,:].reshape (1 ,- 1 )),a1 [i ,:].reshape (1 ,- 1 ))
159+
160+ '''梯度'''
161+ 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
162+ return np .ravel (grad )
163+
164+ # S型函数
165+ def sigmoid (z ):
166+ h = np .zeros ((len (z ),1 )) # 初始化,与z的长度一致
167+
168+ h = 1.0 / (1.0 + np .exp (- z ))
169+ return h
170+
171+ # S型函数导数
172+ def sigmoidGradient (z ):
173+ g = sigmoid (z )* (1 - sigmoid (z ))
174+ return g
175+
176+ # 随机初始化权重theta
177+ def randInitializeWeights (L_in ,L_out ):
178+ W = np .zeros ((L_out ,1 + L_in ))
179+ epsilon_init = (6 / (L_out + L_in ))** 0.5
180+ W = np .random .rand (L_out ,1 + L_in )* 2 * epsilon_init - epsilon_init
181+ return W
182+
183+ # 预测
184+ def predict (Theta1 ,Theta2 ,X ):
185+ m = X .shape [0 ]
186+ num_labels = Theta2 .shape [0 ]
187+ #p = np.zeros((m,1))
188+ X = np .hstack ((np .ones ((m ,1 )),X ))
189+ h1 = sigmoid (np .dot (X ,np .transpose (Theta1 )))
190+ h1 = np .hstack ((np .ones ((m ,1 )),h1 ))
191+ h2 = sigmoid (np .dot (h1 ,np .transpose (Theta2 )))
192+
193+
194+ '''
195+ 返回h中每一行最大值所在的列号
196+ - np.max(h, axis=1)返回h中每一行的最大值(是某个数字的最大概率)
197+ - 最后where找到的最大概率所在的列号(列号即是对应的数字)
198+ '''
199+ #np.savetxt("h2.csv",h2,delimiter=',')
200+ p = np .array (np .where (h2 [0 ,:] == np .max (h2 , axis = 1 )[0 ]))
201+ for i in np .arange (1 , m ):
202+ t = np .array (np .where (h2 [i ,:] == np .max (h2 , axis = 1 )[i ]))
203+ p = np .vstack ((p ,t ))
204+ return p
205+
206+ if __name__ == "__main__" :
207+ neuralNetwork (400 , 25 , 10 )
0 commit comments