[bigdata-126] 一般形式的反向传导算法BP最简推导-3
发布时间:2020-12-14 04:57:56 所属栏目:大数据 来源:网络整理
导读:前述两篇推导还是太繁琐了,有一种更简单的方式。因为排版的问题,直接贴图。 根据上述公式,可以实现一个简单的验证性python代码 #!/usr/bin/env python#!-*- coding:utf-8 -*-#bp alogrithmimport mathimport numpy as np#active functiondef f(x): return
前述两篇推导还是太繁琐了,有一种更简单的方式。因为排版的问题,直接贴图。 根据上述公式,可以实现一个简单的验证性python代码 #!/usr/bin/env python #!-*- coding:utf-8 -*- #bp alogrithm import math import numpy as np #active function def f(x): return 1.0/(1+math.exp(-x)) #应激函数的一阶导数 def d_f(x): return f(x)*(1-f(x)) #神经网络层数 p=3 #神经网络每层的神经元数量,第一个值是None,是为了脚标从1开始 d = [None,2,3,1] #有一个None,是为了脚标从1开始 #权重矩阵 W = [None] #bias b = [None] #z^l_{j,i} z = [None] #a^l_{j,i} a = [None] #a一阶偏导 del_a = [None] for i in range(1,p): #随机初始化权重矩阵 W.append(np.array(0.01*np.random.rand(d[i+1],d[i]))) #随机初始化bias b.append(np.array(0.01*np.random.rand(1,1))) for i in range(1,p+1): #初始化z值 z.append(np.zeros((d[i],1),np.float64)) #初始化a值 a.append(np.zeros((d[i],np.float64)) #初始化a的一阶偏导 del_a.append(np.zeros((d[i],np.float64)) #样本 x = np.array([0.0,1.0],np.float64).reshape((2,1)) y = np.array([1.0],np.float64) #学习速率 eta = 0.1; ###开始计算 n = 1 #最大迭代次数 max_iter = 200 #将输入层设置为样本x a[1]=x #循环计算 while n <= max_iter: print('第'+str(n)+'迭代'+'-'*20) #计算z^l_{j,i}和z^l_{j,i} for l in range(2,p+1): print('*'*5) print(' ' * 2,'计算z[' + str(l) + ']') print(' ' * 4,'a['+str(l-1)+']=',a[l-1]) print(' ' * 4,'W['+str(l-1)+']=',W[l-1]) print(' ' * 4,'b['+str(l-1)+']=',b[l-1]) z[l] = np.dot(W[l-1],a[l-1])+b[l-1] print(' ' * 4,'z['+str(l)+']=',z[l]) print(' '*2,'计算a['+str(l)+']') for i in range(d[l]): a[l][i,0] = f(z[l][i,0]) print(' ' * 4,'a['+str(l)+']=',a[l]) print(' ' * 2,'计算a和z结束') #计算frac{partial J}{partial a^l_{j,i}} print('*'*5) print(' '*2,'计算del_a') #第p层需要单独计算 for i in range(d[p]): del_a[p][i] = -(y[i]-a[p][i,0]) print(' '*4,'del_a['+str(p)+']=',del_a[p]) #第i层 print(' '*4,'**') for i in range(p-1,-1): #第i层的第j个神经元 for j in range(d[i]): #先将其值置0 del_a[i][j,0] = 0 #然后求和 for k in range(d[i+1]): del_a[i][j,0] += W[i][k,j]*d_f(z[i+1][k,0])*del_a[i+1][k][0] print(' ' * 4,'del_a[' + str(i) + ']=',del_a[i]) #计算新的W_l_{j,i} #第l层 for l in range(p-1,-1): #第l层第i个神经元 print('W['+str(l)+']=',W[l]) print('b['+str(l)+']=',b[l]) for i in range(d[l]): for j in range(d[l+1]): W[l][j,i] -= eta*del_a[l+1][j]*d_f(z[l+1][j,0])*a[l][i,0] b[l] -= eta*del_a[l+1][j]*d_f(z[l+1][j,0]) print('new W[' + str(l) + ']=',W[l]) print('new b[' + str(l) + ']=',b[l]) n += 1 latex的文档 documentclass[a4paper,12pt]{article} usepackage{CJK} %define the tile title{BackPropagation Alogrithom} usepackage{graphicx} usepackage{pythonhighlight} begin{document} begin{CJK}{UTF8}{gkai} %generates the title maketitle section{前馈神经网络} 前馈神经网络:设神经网络的层数是$p$,各层分别记为$L^1,L^2,...,L^p$,每层的神经元数量记为$d^1,d^2,d^p$,每个神经元的应激函数记为$f(x)$。 训练集是${(mathbf{x}^k,mathbf{y}^k) } k=1,m$,显而易见,$mathbf{x^k} in R^{d^1times 1}$,$mathbf{y^k} in R^{d^ptimes 1}$,$mathbf{x}^k$是一维列向量且元素个数跟神经网络输入层的神经元数量相同,同理$mathbf{y}^k$是一维列向量且元素个数跟神经网络输出层神经元数量相同。 为推导方便,设$(mathbf{x},mathbf{y})$是一组样本。根据神经网络的定义,在第$l$层,第$i$个神经元的输入值记为$z^l_i$,输出值记为$a^l_i$,有如下关系: begin{eqnarray*} a^l_i &=& f(z^l_i) z^{l+1}_j &=& sum_{i=1}^{d^l}mathbf{W}^{l}_{j,i}a^l_i+ mathbf b^l end{eqnarray*} 上述两式,定义了神经网络的计算方式。其中,$mathbf{W}^l$是第$l$层和第$l+1$层之间的权重矩阵,$mathbf{W}^l_{j,i}$是第$l$层的第$i$个神经元的与第$l+1$层的第$j$个神经元的权重系数,$mathbf b^l$是第$l$层的bias。对于输入层,可以视为$a^1_i=mathbf{x}_i$,也就是说,输入层的第$i$个输出值是样本$mathbf x$的第$i$个元素。 神经网络对$(mathbf{x},mathbf{y})$拟合误差的代价函数如下: begin{eqnarray*} J(mathbf{W},mathbf{b};mathbf{x},mathbf{y})&=&frac{1}{2}sum_{q=1}^{d^p}(mathbf{y}_q-a^p_q)^2 &=&frac{1}{2}sum_{q=1}^{D}(mathbf{y}_q-a^p_q)^2 &=&frac{1}{2}sum_{q=1}^{D}(mathbf{y}_q-f(z^p_q))^2 end{eqnarray*} 其中,$D=d^p$,代价函数的形式在求解中不会变动,因此用$D$以避免计算中的误解,$mathbf{y}_q$是$mathbf{y}$的第$q$个元素,后文$J(mathbf{W},mathbf{y})$将简写为$J$。 section{权重系数和偏差的一阶偏导求解} 前馈神经网络的输出,是样本值进入输入层,从前向后,逐层计算。BP算法求解优化问题,让拟合误差从后向前,从输出层逐层传递到隐层和输入层,由此优化所有权重系数,由此得名BackPropagation反向传播。BP算法的求解推导,本质就是推导相邻两层之间的关系。 $J$对$mathbf b^l$的一阶偏导通式: begin{eqnarray*} frac{partial J}{partial mathbf b^l} &=& sum_{j=1}^{d^{l+1}} frac{partial{J}}{partial a^{l+1}_j}frac{partial a^{l+1}_j}{partial z^{l+1}_j}frac{partial z^{l+1}_j}{partial mathbf b^l} &=& sum_{j=1}^{d^{l+1}} frac{partial{J}}{partial a^{l+1}_j}frac{partial a^{l+1}_j}{partial z^{l+1}_j} &=& sum_{j=1}^{d^{l+1}} frac{partial{J}}{partial a^{l+1}_j}f^{'}(z^{l+1}_j) end{eqnarray*} $J$对$mathbf{W}^l_{j,i}$的一阶偏导通式: begin{eqnarray*} frac{partial{J}}{partial mathbf{W}^l_{j,i}} &=&frac{partial{J}}{partial a^{l+1}_j}frac{partial a^{l+1}_j}{partial z^{l+1}_j}frac{partial z^{l+1}_j}{partial mathbf{W}^{l}_{j,i}} &=&frac{partial{J}}{partial a^{l+1}_j}frac{partial a^{l+1}_j}{partial z^{l+1}_j}a^{l}_{j,i} &=&frac{partial{J}}{partial a^{l+1}_j}f^{'}(z^{l+1}_j)a^{l}_{i} end{eqnarray*} 上式的$frac{partial{J}}{partial a^{l+1}_j}$,也可以通过反向传播的方式求解,其通式$frac{partial{J}}{partial a^{l}_j}(l< p)$求解如下: begin{eqnarray*} frac{partial{J}}{partial {a}^l_{j}} &=&sum_{r=1}^{d^{l+1}}frac{partial J}{partial a^{l+1}_r} frac{partial a^{l+1}_r}{partial z^{l+1}_r}frac{partial z^{l+1}_r}{partial a^l_j} &=& sum_{r=1}^{d^{l+1}} frac{partial J}{partial a^{l+1}_r} frac{partial a^{l+1}_r}{partial z^{l+1}_r}mathbf{W}^{l}_{r,j} &=& sum_{r=1}^{d^{l+1}} frac{partial J}{partial a^{l+1}_r} f^{'}(z^{l+1}_r)mathbf{W}^{l}_{r,j} end{eqnarray*} newpage 以梯度下降法优化$mathbf{W}^l_{j,i}$和$mathbf b^l$,$eta$是学习速率,公式如下: begin{eqnarray*} mathbf{W}^l_{j,i} &=& mathbf{W}^l_{j,i} - eta frac{partial J}{partial mathbf{W}^l_{j,i}} mathbf{b}^l &=& mathbf{b}^l - eta frac{partial J}{partial mathbf{b}^l} end{eqnarray*} section{反向传播计算步骤} 步骤如下: 1.以极小随机值对$mathbf W$和$mathbf b$进行初始化。 2.样本$(mathbf x,mathbf y)$前向传播计算输出值。 3.计算$frac{partial J}{partial a^p_{r}}$,也就是$frac{partial J}{partial a^p_{r}}=-(y_r-a^p_r)$。 4.根据上面推导的公式,从后往前计算所有的$frac{partial{J}}{partial a^{l}_j}$。 5.根据上面推导的公式,从后往前计算所有的$frac{partial{J}}{partial mathbf{W}^l_{j,i}}$。 6.根据上面推导的公式,从后往前计算所有的$frac{partial{J}}{partial mathbf{b}^l}$。 7.更新所有的$mathbf W^l_{j,i}$和$mathbf b^l$。 8.重复步骤2至7,直至终止条件达成。 section{推广到多样本和正则化情况} 对样本集而言,考虑正则化,代价函数如下: begin{eqnarray*} mathbf J(mathbf{W},mathbf{b};mathbf{X},mathbf{Y}) &=&sum_{k=1}^{m}J(mathbf{W},mathbf{b}; mathbf x_k,mathbf y_k)+ frac{lambda}{2} sum_{l=1}^{p-1} sum_{j=1}^{d^{l+1}} sum_{i=1}^{d^{l}} (W^l_{j,i})^2 end{eqnarray*} 对$W^l_{j,i}$求一阶偏导: begin{eqnarray*} frac{mathbf J(mathbf{W},mathbf{Y})}{partial W^l_{j,i}} &=&sum_{k=1}^{m}frac{partial J_k}{partial W^l_{j,i}}+ lambda W^l_{j,i} end{eqnarray*} 从本质上来说,等价于所有样本的一阶偏导之和再加上一个系数。 end{CJK} end{document} grid (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |