基于Levenberg-Marquardt训练算法的BP网络Python实现

来源:互联网 发布:mac ps cs6 编辑:程序博客网 时间:2024/05/14 10:09
 

基于Levenberg-Marquardt训练算法的BP网络Python实现

分类: 统计机器学习算法理论 430人阅读 评论(0) 收藏 举报

经过一个多月的努力,终于完成了BP网络,参考的资料为:

1、Training feed-forward networks with the Marquardt algorithm

2、The Levenberg-Marquardt method for nonlinear least squares curve-fitting problems

3、Neural Network Design

4、http://deeplearning.stanford.edu/wiki/index.php/UFLDL%E6%95%99%E7%A8%8B 中介绍的神经网络部分




以下给出Python脚本:

[python] view plaincopy在CODE上查看代码片派生到我的代码片
  1. import numpy as np  
  2. from math import exp, pow  
  3. from mpl_toolkits.mplot3d import Axes3D  
  4. import matplotlib.pyplot as plt  
  5. import sys  
  6. import copy  
  7. from scipy.linalg import norm, pinv  
  8. class Layer:  
  9.     def __init__(self,w, b, neure_number, transfer_function, layer_index):  
  10.         self.transfer_function = transfer_function  
  11.         self.neure_number = neure_number  
  12.         self.layer_index = layer_index  
  13.         self.w = w  
  14.         self.b = b  
  15.           
  16. class NetStruct:  
  17.     def __init__(self, x, y, hidden_layers, activ_fun_list, performance_function = 'mse'):  
  18.         if len(hidden_layers) == len(activ_fun_list):  
  19.             activ_fun_list.append('line')  
  20.         self.active_fun_list = activ_fun_list  
  21.         self.performance_function = performance_function  
  22.         x = np.array(x)  
  23.         y = np.array(y)  
  24.         if(x.shape[1] != y.shape[1]):  
  25.             print 'The dimension of x and y are not same.'  
  26.             sys.exit()  
  27.         self.x = x  
  28.         self.y = y  
  29.         input_eles = self.x.shape[0]  
  30.         output_eles = self.y.shape[0]  
  31.         tmp = []  
  32.         tmp.append(input_eles)  
  33.         tmp.extend(hidden_layers)  
  34.         tmp.append(output_eles)  
  35.         self.hidden_layers = np.array(tmp)  
  36.         self.layer_num = len(self.hidden_layers)  
  37.         self.layers = []  
  38.         for i in range(0, len(self.hidden_layers)):  
  39.               
  40.             if i == 0:  
  41.                 self.layers.append(Layer([],[],\  
  42.                                         self.hidden_layers[i], 'none', i))   
  43.                 continue  
  44.             f = self.hidden_layers[i - 1]  
  45.             s = self.hidden_layers[i]   
  46.             self.layers.append(Layer(np.random.randn(s, f),np.random.randn(s, 1),\  
  47.                                         self.hidden_layers[i], activ_fun_list[i-1], i))   
  48.       
  49. class Train:  
  50.     def __init__(self, net_struct, mu = 1e-3, beta = 10, iteration = 100, tol = 0.1):  
  51.         self.net_struct = net_struct  
  52.         self.mu = mu  
  53.         self.beta = beta  
  54.         self.iteration = iteration  
  55.         self.tol = tol  
  56.     def train(self, method = 'lm'):  
  57.         if(method == 'lm'):  
  58.             self.lm()  
  59.     def sim(self, x):  
  60.         self.net_struct.x = x  
  61.         self.forward()  
  62.         layer_num = len(self.net_struct.layers)  
  63.         predict = self.net_struct.layers[layer_num - 1].output_val  
  64.         return predict  
  65.     def actFun(self, z, activ_type = 'sigm'):  
  66.         if activ_type == 'sigm':              
  67.             f = 1.0 / (1.0 + np.exp(-z))  
  68.         elif activ_type == 'tanh':  
  69.             f = (np.exp(z) + np.exp(-z)) / (np.exp(z) + np.exp(-z))  
  70.         elif activ_type == 'radb':  
  71.             f = np.exp(-z * z)  
  72.         elif activ_type == 'line':  
  73.             f = z  
  74.         return f  
  75.     def actFunGrad(self, z, activ_type = 'sigm'):  
  76.         if activ_type == 'sigm':  
  77.             grad = self.actFun(z, activ_type) * (1.0 - self.actFun(z, activ_type))  
  78.         elif activ_type == 'tanh':  
  79.             grad = 1.0 - self.actFun(z, activ_type) * self.actFun(z, activ_type)  
  80.         elif activ_type == 'radb':  
  81.             grad = -2.0 * z * self.actFun(z, activ_type)  
  82.         elif activ_type == 'line':  
  83.             m = z.shape[0]  
  84.             n = z.shape[1]  
  85.             grad = np.ones((m, n))  
  86.         return grad  
  87.     def forward(self):  
  88.         layer_num = len(self.net_struct.layers)  
  89.         for i in range(0, layer_num):  
  90.             if i == 0:  
  91.                 curr_layer = self.net_struct.layers[i]  
  92.                 curr_layer.input_val = self.net_struct.x  
  93.                 curr_layer.output_val = self.net_struct.x  
  94.                 continue  
  95.             before_layer = self.net_struct.layers[i - 1]  
  96.             curr_layer = self.net_struct.layers[i]  
  97.             curr_layer.input_val = curr_layer.w.dot(before_layer.output_val) + curr_layer.b  
  98.             curr_layer.output_val = self.actFun(curr_layer.input_val,   
  99.                                                 self.net_struct.active_fun_list[i - 1])  
  100.     def backward(self):  
  101.         layer_num = len(self.net_struct.layers)  
  102.         last_layer = self.net_struct.layers[layer_num - 1]  
  103.         last_layer.error = -self.actFunGrad(last_layer.input_val,  
  104.                                             self.net_struct.active_fun_list[layer_num - 2])  
  105.         layer_index = range(1, layer_num - 1)  
  106.         layer_index.reverse()  
  107.         for i in layer_index:  
  108.             curr_layer = self.net_struct.layers[i]  
  109.             curr_layer.error = (last_layer.w.transpose().dot(last_layer.error)) \  
  110.                       * self.actFunGrad(curr_layer.input_val,self.net_struct.active_fun_list[i - 1])  
  111.             last_layer = curr_layer  
  112.     def parDeriv(self):  
  113.         layer_num = len(self.net_struct.layers)  
  114.         for i in range(1, layer_num):  
  115.             befor_layer = self.net_struct.layers[i - 1]  
  116.             befor_input_val = befor_layer.output_val.transpose()  
  117.             curr_layer = self.net_struct.layers[i]  
  118.             curr_error = curr_layer.error  
  119.             curr_error = curr_error.reshape(curr_error.shape[0]*curr_error.shape[1], 1, order='F')  
  120.             row =  curr_error.shape[0]  
  121.             col = befor_input_val.shape[1]  
  122.             a = np.zeros((row, col))  
  123.             num = befor_input_val.shape[0]  
  124.             neure_number = curr_layer.neure_number  
  125.             for i in range(0, num):  
  126.                 a[neure_number*i:neure_number*i + neure_number,:] = \  
  127.                  np.repeat([befor_input_val[i,:]],neure_number,axis = 0)  
  128.             tmp_w_par_deriv = curr_error * a  
  129.             curr_layer.w_par_deriv = np.zeros((num, befor_layer.neure_number * curr_layer.neure_number))  
  130.             for i in range(0, num):  
  131.                 tmp = tmp_w_par_deriv[neure_number*i:neure_number*i + neure_number,:]  
  132.                 tmp = tmp.reshape(tmp.shape[0] * tmp.shape[1], order='C')  
  133.                 curr_layer.w_par_deriv[i, :] = tmp  
  134.             curr_layer.b_par_deriv = curr_layer.error.transpose()  
  135.     def jacobian(self):  
  136.         layers = self.net_struct.hidden_layers  
  137.         row = self.net_struct.x.shape[1]  
  138.         col = 0  
  139.         for i in range(0, len(layers) - 1):  
  140.             col = col + layers[i] * layers[i + 1] + layers[i + 1]  
  141.         j = np.zeros((row, col))  
  142.         layer_num = len(self.net_struct.layers)  
  143.         index = 0  
  144.         for i in range(1, layer_num):  
  145.             curr_layer = self.net_struct.layers[i]  
  146.             w_col = curr_layer.w_par_deriv.shape[1]  
  147.             b_col = curr_layer.b_par_deriv.shape[1]  
  148.             j[:, index : index + w_col] = curr_layer.w_par_deriv  
  149.             index = index + w_col  
  150.             j[:, index : index + b_col] = curr_layer.b_par_deriv  
  151.             index = index + b_col  
  152.         return j  
  153.     def gradCheck(self):  
  154.         W1 = self.net_struct.layers[1].w  
  155.         b1 = self.net_struct.layers[1].b  
  156.         n = self.net_struct.layers[1].neure_number  
  157.         W2 = self.net_struct.layers[2].w  
  158.         b2 = self.net_struct.layers[2].b  
  159.         x = self.net_struct.x  
  160.         p = []  
  161.         p.extend(W1.reshape(1,W1.shape[0]*W1.shape[1],order = 'C')[0])  
  162.         p.extend(b1.reshape(1,b1.shape[0]*b1.shape[1],order = 'C')[0])  
  163.         p.extend(W2.reshape(1,W2.shape[0]*W2.shape[1],order = 'C')[0])  
  164.         p.extend(b2.reshape(1,b2.shape[0]*b2.shape[1],order = 'C')[0])  
  165.         old_p = p  
  166.         jac = []  
  167.         for i in range(0, x.shape[1]):  
  168.             xi = np.array([x[:,i]])  
  169.             xi = xi.transpose()  
  170.             ji = []  
  171.             for j in range(0, len(p)):  
  172.                 W1 = np.array(p[0:2*n]).reshape(n,2,order='C')  
  173.                 b1 = np.array(p[2*n:2*n+n]).reshape(n,1,order='C')  
  174.                 W2 = np.array(p[3*n:4*n]).reshape(1,n,order='C')  
  175.                 b2 = np.array(p[4*n:4*n+1]).reshape(1,1,order='C')  
  176.                   
  177.                 z2 = W1.dot(xi) + b1  
  178.                 a2 = self.actFun(z2)  
  179.                 z3 = W2.dot(a2) + b2  
  180.                 h1 = self.actFun(z3)  
  181.                 p[j] = p[j] + 0.00001  
  182.                 W1 = np.array(p[0:2*n]).reshape(n,2,order='C')  
  183.                 b1 = np.array(p[2*n:2*n+n]).reshape(n,1,order='C')  
  184.                 W2 = np.array(p[3*n:4*n]).reshape(1,n,order='C')  
  185.                 b2 = np.array(p[4*n:4*n+1]).reshape(1,1,order='C')  
  186.                   
  187.                 z2 = W1.dot(xi) + b1  
  188.                 a2 = self.actFun(z2)  
  189.                 z3 = W2.dot(a2) + b2  
  190.                 h = self.actFun(z3)  
  191.                 g = (h[0][0]-h1[0][0])/0.00001  
  192.                 ji.append(g)  
  193.             jac.append(ji)  
  194.             p = old_p  
  195.         return jac  
  196.     def jjje(self):  
  197.         layer_number = self.net_struct.layer_num  
  198.         e = self.net_struct.y - \  
  199.           self.net_struct.layers[layer_number - 1].output_val  
  200.         e = e.transpose()  
  201.         j = self.jacobian()  
  202.         #check gradient  
  203.         #j1 = -np.array(self.gradCheck())  
  204.         #jk = j.reshape(1,j.shape[0]*j.shape[1])  
  205.         #jk1 = j1.reshape(1,j1.shape[0]*j1.shape[1])  
  206.         #plt.plot(jk[0])  
  207.         #plt.plot(jk1[0],'.')  
  208.         #plt.show()  
  209.         jj = j.transpose().dot(j)  
  210.         je = -j.transpose().dot(e)  
  211.         return[jj, je]  
  212.     def lm(self):  
  213.         mu = self.mu  
  214.         beta = self.beta  
  215.         iteration = self.iteration  
  216.         tol = self.tol  
  217.         y = self.net_struct.y  
  218.         self.forward()  
  219.         pred =  self.net_struct.layers[self.net_struct.layer_num - 1].output_val  
  220.         pref = self.perfermance(y, pred)  
  221.         for i in range(0, iteration):  
  222.             print 'iter:',i, 'error:', pref  
  223.             #1) step 1:   
  224.             if(pref < tol):  
  225.                 break  
  226.             #2) step 2:  
  227.             self.backward()  
  228.             self.parDeriv()  
  229.             [jj, je] = self.jjje()  
  230.             while(1):  
  231.                 #3) step 3:   
  232.                 A = jj + mu * np.diag(np.ones(jj.shape[0]))  
  233.                 delta_w_b = pinv(A).dot(je)  
  234.                 #4) step 4:  
  235.                 old_net_struct = copy.deepcopy(self.net_struct)  
  236.                 self.updataNetStruct(delta_w_b)  
  237.                 self.forward()  
  238.                 pred1 =  self.net_struct.layers[self.net_struct.layer_num - 1].output_val  
  239.                 pref1 = self.perfermance(y, pred1)  
  240.                 if (pref1 < pref):  
  241.                     mu = mu / beta  
  242.                     pref = pref1  
  243.                     break  
  244.                 mu = mu * beta  
  245.                 self.net_struct = copy.deepcopy(old_net_struct)  
  246.     def updataNetStruct(self, delta_w_b):  
  247.         layer_number = self.net_struct.layer_num  
  248.         index = 0  
  249.         for i in range(1, layer_number):  
  250.             before_layer = self.net_struct.layers[i - 1]  
  251.             curr_layer = self.net_struct.layers[i]  
  252.             w_num = before_layer.neure_number * curr_layer.neure_number  
  253.             b_num = curr_layer.neure_number  
  254.             w = delta_w_b[index : index + w_num]  
  255.             w = w.reshape(curr_layer.neure_number, before_layer.neure_number, order='C')  
  256.             index = index + w_num  
  257.             b = delta_w_b[index : index + b_num]  
  258.             index = index + b_num  
  259.             curr_layer.w += w  
  260.             curr_layer.b += b  
  261.     def perfermance(self, y, pred):  
  262.         error = y - pred  
  263.         return norm(error) / len(y)    
  264.     def plotSamples(self, n = 40):  
  265.         x = np.array([np.linspace(03, n)])  
  266.         x = x.repeat(n, axis = 0)  
  267.         y = x.transpose()  
  268.         z = np.zeros((n, n))  
  269.         for i in range(0, x.shape[0]):  
  270.             for j in range(0, x.shape[1]):  
  271.                 z[i][j] = self.sampleFun(x[i][j], y[i][j])  
  272.         fig = plt.figure()  
  273.         ax = fig.gca(projection='3d')  
  274.         surf = ax.plot_surface(x, y, z, cmap='autumn', cstride=2, rstride=2)  
  275.         ax.set_xlabel("X-Label")  
  276.         ax.set_ylabel("Y-Label")  
  277.         ax.set_zlabel("Z-Label")  
  278.         plt.show()  
  279. def sinSamples(n):  
  280.         x = np.array([np.linspace(-0.50.5, n)])  
  281.         #x = x.repeat(n, axis = 0)  
  282.         y = x + 0.2  
  283.         z = np.zeros((n, 1))  
  284.         for i in range(0, x.shape[1]):  
  285.             z[i] = np.sin(x[0][i] * y[0][i])  
  286.         X = np.zeros((n, 2))  
  287.         n = 0  
  288.         for xi, yi in zip(x.transpose(), y.transpose()):  
  289.             X[n][0] = xi  
  290.             X[n][1] = yi  
  291.             n = n + 1  
  292.         return X,z  
  293. def peaksSamples(n):  
  294.     x = np.array([np.linspace(-33, n)])  
  295.     x = x.repeat(n, axis = 0)  
  296.     y = x.transpose()  
  297.     z = np.zeros((n, n))  
  298.     for i in range(0, x.shape[0]):  
  299.         for j in range(0, x.shape[1]):  
  300.             z[i][j] = sampleFun(x[i][j], y[i][j])  
  301.     X = np.zeros((n*n, 2))  
  302.     x_list = x.reshape(n*n,1 )  
  303.     y_list = y.reshape(n*n,1)  
  304.     z_list = z.reshape(n*n,1)  
  305.     n = 0  
  306.     for xi, yi in zip(x_list, y_list):  
  307.         X[n][0] = xi  
  308.         X[n][1] = yi  
  309.         n = n + 1  
  310.       
  311.     return X,z_list.transpose()  
  312. def sampleFun(x, y):  
  313.     z =  3*pow((1-x),2) * exp(-(pow(x,2)) - pow((y+1),2)) \  
  314.    - 10*(x/5 - pow(x, 3) - pow(y, 5)) * exp(-pow(x, 2) - pow(y, 2)) \  
  315.    - 1/3*exp(-pow((x+1), 2) - pow(y, 2))   
  316.     return z  
  317. if __name__ == '__main__':  
  318.       
  319.     hidden_layers = [10,10#设置网络层数,共两层,每层10个神经元  
  320.     activ_fun_list = ['sigm','sigm']#设置隐层的激活函数类型,可以设置为<span style="font-family: Arial, Helvetica, sans-serif;">tanh,radb,tanh,line类型,如果不显式的设置最后一层为line </span>  
  321.   
  322.     [X, z] = peaksSamples(20#产生训练数据点  
  323.     X = X.transpose()  
  324.     bp = NetStruct(X, z, hidden_layers, activ_fun_list) #初始化网络信息  
  325.     tr = Train(bp) #初始化训练网络的类  
  326.     tr.train() #训练  
  327.     [XX, z0] = peaksSamples(40#产生测试数据  
  328.     XX = XX.transpose()  
  329.     z1 = tr.sim(XX) #用训练好的神经网络预测数据,z1为预测结果  
  330.       
  331.     fig  = plt.figure()  
  332.     ax = fig.add_subplot(111)  
  333.     ax.plot(z0[0]) #真值  
  334.     ax.plot(z1[0],'r.'#预测值  
  335.     plt.legend((r'real data', r'predict data'))  
  336.     plt.show()  

以上代码计算的结果如下图,由于初始值等原因的影响偶尔收敛效果会变差,不过大多数时候都可以收敛到下图的结果,以后再改进,欢迎指正。



1 0
原创粉丝点击