3、深度神经网络(DNN)

1 DNN基本结构

​ 深度神经网络是基于上述MLP感知机的扩展,DNN可以理解为有很多隐藏层的神经网络。MLP可以视为DNN的前身,大致可以分为三层:输入层,隐藏层,输出层,MLP通常很浅,隐藏层就一二层。DNN一般隐藏层大于二,而且激活函数的种类更多。

在这里插入图片描述

2 DNN训练过程

在这里插入图片描述

​ 如图所示,我们在这里将DNN训练划分为4个过程,分别为前向传播(Forward-Propogation, FP), 反向传播(Backward-Propogation, BP ), 权重梯度计算(Weight Gradient, WG), (为了表述方便,后面会将BP和WG统称为反向过程) 和权重更新(Weight Update, WU)。

​ 首先将训练数据分批送入网络中,逐层进行前向计算,直至输出层,然后将当前网络输出与真实标签比较,并利用损失函数(Loss function)计算出损失,常见的损失函数包括均方误差损失 (Mean square error, MSE), 交叉熵损失(Cross Entropy)等;以典型的分类任务,Cross Entropy损失函数为例,前向计算如下:

y ^ ( i ) = f [ L ] ( . . . f f [ 2 ] ( f f [ 1 ] ( x ( i ) ) ) ) , y ^ ( i ) ∈ R 1 × C p i = s o f t m a x ( y ^ ( i ) ) L o s s = − 1 m ∑ i m ∑ c C y i c log ⁡ ( p i c ) \hat{y}^{(i)}=f^{[L]}(...ff^{[2]}(ff^{[1]}(x^{(i)}))) ,\hat{y}^{(i)} \in \R^{1 \times C}\\ p_i=softmax(\hat{y}^{(i)}) \\ Loss=-\frac{1}{m} \sum_i^m \sum_c^Cy_{ic}\log(p_{ic}) y^(i)=f[L](...ff[2](ff[1](x(i)))),y^(i)R1×Cpi=softmax(y^(i))Loss=m1imcCyiclog(pic)
其中 m m m 表示样本数目, C C C 表示类别数目,即 n y n_y ny

​ 反向过程则是根据链式法则,逐层计算出损失函数关于各层 W [ l ] , b [ l ] W^{[l]},b^{[l]} W[l],b[l]的梯度,BP和WG是反向过程的两条计算支路,分别用于计算损失函数对于激活值的梯度(文献中通常称之为error,也就是图中的 σ 1 \sigma _1 σ1 σ 2 \sigma _2 σ2 σ 3 \sigma _3 σ3 ,和对于权重的梯度 W g 0 , W g 1 , W g 2 W_{g0},W_{g1},W_{g2} Wg0,Wg1,Wg2 )。他们的计算原理分别如下面的公式:

σ 1 = ∂ L ∂ α 1 = ∂ L ∂ α 2 ∂ α 2 ∂ α 1 = σ 2 W 1 T W g 1 = ∂ L ∂ W 1 = ∂ L ∂ α 2 ∂ α 2 ∂ W 1 = σ 2 α 1 \sigma _1=\frac{\partial L}{\partial \alpha_1}=\frac{\partial L}{\partial \alpha_2}\frac{\partial \alpha_2}{\partial \alpha_1}=\sigma_2 W_1^T \\ W _{g1}=\frac{\partial L}{\partial W_1}=\frac{\partial L}{\partial \alpha_2}\frac{\partial \alpha_2}{\partial W_1} =\sigma_2 \alpha_1 \\ σ1=α1L=α2Lα1α2=σ2W1TWg1=W1L=α2LW1α2=σ2α1
pytorch中,反向过程是通过 l o s s . b a c k w a r d ( ) loss.backward() loss.backward()内部直接完成

最后,根据反向过程中得到的权重梯度,来对权重进行更新。基本的随机梯度下降算法(SGD): W 1 ′ {W_1}′ W1= W 1 − η W g 1 W_1−ηW_{g1} W1ηWg1

补充说明:(此处 W W W 应为 W T W^T WT,为方便省去了转置符号)

1)DNN前向传播算法:针对一个样本描述

利用和感知机一样的思路,我们可以利用上一层的输出计算下一层的输出

在这里插入图片描述

对于第二层的输出 a 1 [ 2 ] , a 2 [ 2 ] , a 3 [ 2 ] a_1^{[2]},a_2^{[2]},a_3^{[2]} a1[2],a2[2],a3[2],我们有:
a 1 [ 2 ] = σ ( z 1 [ 2 ] ) = σ ( w 11 [ 2 ] x 1 + w 12 [ 2 ] x 2 + w 13 [ 2 ] x 3 + b 1 [ 2 ] ) a 2 [ 2 ] = σ ( z 2 [ 2 ] ) = σ ( w 21 [ 2 ] x 1 + w 22 [ 2 ] x 2 + w 23 [ 2 ] x 3 + b 2 [ 2 ] ) a 3 [ 2 ] = σ ( z 3 [ 2 ] ) = σ ( w 31 [ 2 ] x 1 + w 32 [ 2 ] x 2 + w 33 [ 2 ] x 3 + b 3 [ 2 ] ) a_1^{[2]} = \sigma(z_1^{[2]})=\sigma(w_{11}^{[2]} x_1+w_{12}^{[2]} x_2+w_{13}^{[2]} x_3+b_1^{[2]}) \\a_2^{[2]} = \sigma(z_2^{[2]})=\sigma(w_{21}^{[2]} x_1+w_{22}^{[2]} x_2+w_{23}^{[2]} x_3+b_2^{[2]}) \\a_3^{[2]} = \sigma(z_3^{[2]})=\sigma(w_{31}^{[2]} x_1+w_{32}^{[2]} x_2+w_{33}^{[2]} x_3+b_3^{[2]}) a1[2]=σ(z1[2])=σ(w11[2]x1+w12[2]x2+w13[2]x3+b1[2])a2[2]=σ(z2[2])=σ(w21[2]x1+w22[2]x2+w23[2]x3+b2[2])a3[2]=σ(z3[2])=σ(w31[2]x1+w32[2]x2+w33[2]x3+b3[2])
对于第三层的输出 a 1 [ 3 ] a_1^{[3]} a1[3],我们有:
a 1 [ 3 ] = σ ( z 1 [ 3 ] ) = σ ( w 11 [ 3 ] a 1 [ 2 ] + w 12 [ 3 ] a 2 [ 2 ] + w 13 [ 3 ] a 3 [ 2 ] + b 1 [ 3 ] ) a_1^{[3]}= \sigma(z_1^{[3]})=\sigma(w_{11}^{[3]} a_1^{[2]}+w_{12}^{[3]} a_2^{[2]}+w_{13}^{[3]} a_3^{[2]}+b_1^{[3]}) a1[3]=σ(z1[3])=σ(w11[3]a1[2]+w12[3]a2[2]+w13[3]a3[2]+b1[3])
将上面的例子一般化,假设第 l − 1 l-1 l1层共有 n h [ l − 1 ] n^{[l-1]}_h nh[l1]个神经元,则对于第 l l l层的第 j j j个神经元的输出 a j [ l ] a_j^{[l]} aj[l],我们有:
a j [ l ] = σ ( z j [ l ] ) = σ ( ∑ k = 1 n h [ l − 1 ] w j k [ l ] a k [ l − 1 ] + b j [ l ] ) a_j^{[l]}=\sigma(z_j^{[l]})=\sigma(\sum_{k=1}^{n^{[l-1]}_h}w_{jk}^{[l]}a_k^{[l-1]}+b_j^{[l]}) aj[l]=σ(zj[l])=σ(k=1nh[l1]wjk[l]ak[l1]+bj[l])
其中,如果 l = 2 l=2 l=2,则对于 a k [ l ] a_k^{[l]} ak[l],即为输入层的 x k x_k xk

2)DNN反向传播算法损失以 m m m个样本的平均损失计算,反向梯度公式按单个样本进行推导

​ 假设我们有 m m m个训练样本 ( x ( 1 ) , y ( 1 ) ) , ( x ( 2 ) , y ( 2 ) ) , . . . , ( x ( m ) , y ( m ) ) {(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),...,(x^{(m)},y^{(m)})} (x(1),y(1)),(x(2),y(2)),...,(x(m),y(m)) ,其中 x ( i ) x^{(i)} x(i)为输入向量,特征维度为 n i n n_{in} nin,而 y ( i ) y^{(i)} y(i)为输出向量,特征维度为 n o u t n_{out} nout。我们需要利用这 m m m个样本训练出一个模型,当有一个新的测试样本 ( x t e s t , ? ) (x_{test},?) (xtest,?) 时,可以预测 y t e s t y_{test} ytest 向量的输出。

​ 如果我们采用DNN的模型,即我们使输入层 n x n_{x} nx个神经元,而输出层有 n y n_{y} ny个神经元。再加上一些含有若干神经元的隐藏层。此时需要找到合适的所有隐藏层和输出层对应的线性系数矩阵 W W W ,偏倚向量 b b b ,让所有的训练样本输入计算出的输出尽可能的等于或很接近样本输出。怎么找到合适的参数呢?

​ 可以用一个合适的损失函数来度量训练样本的输出损失,接着对这个损失函数进行优化求最小化的极值,对应的一系列线性系数矩阵 W W W,偏倚向量 b b b即为我们的最终结果。在DNN中,损失函数优化极值求解的过程最常见的一般是通过梯度下降法来一步步迭代完成的,也可以是其他的迭代方法比如牛顿法与拟牛顿法。

​ 在进行DNN反向传播算法前,我们需要选择一个损失函数,来度量训练样本计算出的输出和真实的训练样本输出之间的损失。DNN可选择的损失函数有不少,为了专注算法,这里使用最常见的均方差来度量损失。即对于每个样本,我们期望最小化下式:
J ( W , b , x , y ) = 1 2 ∣ ∣ a [ L ] − y ∣ ∣ 2 2 J(W,b,x,y)=\frac{1}{2}||a^{[L]}-y||_2^2 J(W,b,x,y)=21∣∣a[L]y22
其中, a [ L ] a^{[L]} a[L] y y y为特征维度为 n o u t n_{out} nout的向量,而 ∣ ∣ S ∣ ∣ 2 ||S||_2 ∣∣S2 S S S L 2 L2 L2范数

最终损失为所有样本损失的平均值,损失函数有了,用梯度下降法迭代求解每一层的 W [ l ] , b [ l ] W^{[l]},b^{[l]} W[l],b[l]

(1)首先求输出层第 L L L 层的 W [ L ] , b [ L ] W^{[L]},b^{[L]} W[L],b[L]的梯度:

将第 L L L层式子 a [ L ] = σ ( z [ L ] ) = σ ( W [ L ] a [ L − 1 ] + b [ L ] ) a^{[L]}=\sigma(z^{[L]})=\sigma(W^{[L]}a^{[L-1]}+b^{[L]}) a[L]=σ(z[L])=σ(W[L]a[L1]+b[L])代入到损失函数中,损失函数变为:
J ( W , b , x , y ) = 1 2 ∣ ∣ a [ L ] − y ∣ ∣ 2 2 = 1 2 ∣ ∣ σ ( z [ L ] ) − y ∣ ∣ 2 2 = 1 2 ∣ ∣ σ ( W [ L ] a [ L − 1 ] + b [ L ] ) − y ∣ ∣ 2 2 J(W,b,x,y)=\frac{1}{2}||a^{[L]}-y||_2^2=\frac{1}{2}||\sigma(z^{[L]})-y||_2^2=\frac{1}{2}||\sigma(W^{[L]}a^{[L-1]}+b^{[L]})-y||_2^2 J(W,b,x,y)=21∣∣a[L]y22=21∣∣σ(z[L])y22=21∣∣σ(W[L]a[L1]+b[L])y22
求解 W [ L ] , b [ L ] W^{[L]},b^{[L]} W[L],b[L]的梯度有:
∂ J ( W , b , x , y ) ∂ W [ L ] = ∂ J ( W , b , x , y ) ∂ z [ L ] ∂ z [ L ] ∂ W [ L ] ∂ J ( W , b , x , y ) ∂ b [ L ] = ∂ J ( W , b , x , y ) ∂ z [ L ] ∂ z [ L ] ∂ b [ L ] \frac{\partial J(W,b,x,y)}{\partial W ^{[L]}}=\frac{\partial J(W,b,x,y)}{\partial z ^{[L]}}\frac{\partial z ^{[L]}}{\partial W ^{[L]}}\\ \frac{\partial J(W,b,x,y)}{\partial b ^{[L]}}=\frac{\partial J(W,b,x,y)}{\partial z ^{[L]}}\frac{\partial z ^{[L]}}{\partial b ^{[L]}} W[L]J(W,b,x,y)=z[L]J(W,b,x,y)W[L]z[L]b[L]J(W,b,x,y)=z[L]J(W,b,x,y)b[L]z[L]
其中,记 σ [ L ] = ∂ J ( W , b , x , y ) ∂ z [ L ] \sigma^{[L]}=\frac{\partial J(W,b,x,y)}{\partial z ^{[L]}} σ[L]=z[L]J(W,b,x,y),由 J ( W , b , x , y ) = 1 2 ∣ ∣ σ ( z [ L ] ) − y ∣ ∣ 2 2 J(W,b,x,y)=\frac{1}{2}||\sigma(z^{[L]})-y||_2^2 J(W,b,x,y)=21∣∣σ(z[L])y22 z [ L ] = W [ L ] a [ L − 1 ] + b [ L ] z^{[L]}=W^{[L]}a^{[L-1]}+b^{[L]} z[L]=W[L]a[L1]+b[L]分别得
σ [ L ] = ∂ J ( W , b , x , y ) ∂ z [ L ] = ( a [ L ] − y ) ⊙ σ ′ ( z [ L ] ) ∂ z [ L ] ∂ W [ L ] = ( a [ L − 1 ] ) T ∂ z [ L ] ∂ b [ L ] = 1 \sigma^{[L]}=\frac{\partial J(W,b,x,y)}{\partial z ^{[L]}}=(a^{[L]}-y)\odot \sigma'(z^{[L]})\\ \frac{\partial z ^{[L]}}{\partial W ^{[L]}}=(a^{[L-1]})^T\\ \frac{\partial z ^{[L]}}{\partial b ^{[L]}}=1 \\ σ[L]=z[L]J(W,b,x,y)=(a[L]y)σ(z[L])W[L]z[L]=(a[L1])Tb[L]z[L]=1
式中 ⊙ \odot 表示Hadamard积,对于两个维度相同的向量 A = ( a 1 , a 2 , . . . , a n ) T A=(a_1,a_2,...,a_n)^T A=(a1,a2,...,an)T B = ( b 1 , b 2 , . . . , b n ) T B=(b_1,b_2,...,b_n)^T B=(b1,b2,...,bn)T,有 A ⊙ B = ( a 1 b 1 , a 2 b 2 , . . . , a n b n ) T A\odot B=(a_1b_1,a_2b_2,...,a_nb_n)^T AB=(a1b1,a2b2,...,anbn)T。因此,将上式代入到 W [ L ] , b [ L ] W^{[L]},b^{[L]} W[L],b[L]的梯度求解式子中可得:
∂ J ( W , b , x , y ) ∂ W [ L ] = ∂ J ( W , b , x , y ) ∂ z [ L ] ∂ z [ L ] ∂ W [ L ] = ( a [ L ] − y ) ( a [ L − 1 ] ) T ⊙ σ ′ ( z [ L ] ) ∂ J ( W , b , x , y ) ∂ b [ L ] = ∂ J ( W , b , x , y ) ∂ z [ L ] ∂ z [ L ] ∂ b [ L ] = ( a [ L ] − y ) ⊙ σ ′ ( z [ L ] ) \frac{\partial J(W,b,x,y)}{\partial W ^{[L]}}=\frac{\partial J(W,b,x,y)}{\partial z ^{[L]}}\frac{\partial z ^{[L]}}{\partial W ^{[L]}}=(a^{[L]}-y)(a^{[L-1]})^T\odot \sigma'(z^{[L]})\\ \frac{\partial J(W,b,x,y)}{\partial b ^{[L]}}=\frac{\partial J(W,b,x,y)}{\partial z ^{[L]}}\frac{\partial z ^{[L]}}{\partial b ^{[L]}}=(a^{[L]}-y)\odot \sigma'(z^{[L]}) W[L]J(W,b,x,y)=z[L]J(W,b,x,y)W[L]z[L]=(a[L]y)(a[L1])Tσ(z[L])b[L]J(W,b,x,y)=z[L]J(W,b,x,y)b[L]z[L]=(a[L]y)σ(z[L])
(2)求第 l l l 层的 W [ l ] , b [ l ] W^{[l]},b^{[l]} W[l],b[l]的梯度:

计算完输出层 W [ L ] , b [ L ] W^{[L]},b^{[L]} W[L],b[L]的梯度后,可以依次计算每一层 W [ l ] , b [ l ] W^{[l]},b^{[l]} W[l],b[l]的梯度。第 l l l层的未激活输出 z [ l ] z^{[l]} z[l]的梯度为:
σ [ l ] = ∂ J ( W , b , x , y ) ∂ z [ l ] \sigma^{[l]}=\frac{\partial J(W,b,x,y)}{\partial z ^{[l]}} σ[l]=z[l]J(W,b,x,y)
根据前向传播算法, z [ l ] = W [ l ] a [ l − 1 ] + b [ l ] z^{[l]}=W^{[l]}a^{[l-1]}+b^{[l]} z[l]=W[l]a[l1]+b[l],计算第 l l l W [ l ] , b [ l ] W^{[l]},b^{[l]} W[l],b[l]的梯度如下:
∂ J ( W , b , x , y ) ∂ W [ l ] = ∂ J ( W , b , x , y ) ∂ z [ l ] ∂ z [ l ] ∂ W [ l ] = σ [ l ] ( a [ l − 1 ] ) T ∂ J ( W , b , x , y ) ∂ b [ l ] = ∂ J ( W , b , x , y ) ∂ z [ l ] ∂ z [ l ] ∂ b [ l ] = σ [ l ] \frac{\partial J(W,b,x,y)}{\partial W ^{[l]}}=\frac{\partial J(W,b,x,y)}{\partial z ^{[l]}}\frac{\partial z ^{[l]}}{\partial W ^{[l]}}=\sigma^{[l]}(a^{[l-1]})^T\\ \frac{\partial J(W,b,x,y)}{\partial b ^{[l]}}=\frac{\partial J(W,b,x,y)}{\partial z ^{[l]}}\frac{\partial z ^{[l]}}{\partial b ^{[l]}}=\sigma^{[l]}\\ W[l]J(W,b,x,y)=z[l]J(W,b,x,y)W[l]z[l]=σ[l](a[l1])Tb[l]J(W,b,x,y)=z[l]J(W,b,x,y)b[l]z[l]=σ[l]
对于第 l l l层的未激活输出 z [ l ] z^{[l]} z[l]的梯度 σ [ l ] \sigma^{[l]} σ[l],它还可以表示为:
σ [ l ] = ∂ J ( W , b , x , y ) ∂ z [ l ] = ∂ J ( W , b , x , y ) ∂ z [ L ] ∂ z [ L ] ∂ z [ L − 1 ] ∂ z [ L − 1 ] ∂ z [ L − 2 ] . . . ∂ z [ l + 1 ] ∂ z [ l ] = ∂ J ( W , b , x , y ) ∂ z [ l + 1 ] ∂ z [ l + 1 ] ∂ z [ l ] = σ [ l + 1 ] ∂ z [ l + 1 ] ∂ z [ l ] \sigma^{[l]}=\frac{\partial J(W,b,x,y)}{\partial z ^{[l]}}=\frac{\partial J(W,b,x,y)}{\partial z ^{[L]}}\frac{\partial z ^{[L]}}{\partial z ^{[L-1]}}\frac{\partial z ^{[L-1]}}{\partial z ^{[L-2]}}...\frac{\partial z ^{[l+1]}}{\partial z ^{[l]}}=\frac{\partial J(W,b,x,y)}{\partial z ^{[l+1]}}\frac{\partial z ^{[l+1]}}{\partial z ^{[l]}}=\sigma^{[l+1]}\frac{\partial z ^{[l+1]}}{\partial z ^{[l]}} σ[l]=z[l]J(W,b,x,y)=z[L]J(W,b,x,y)z[L1]z[L]z[L2]z[L1]...z[l]z[l+1]=z[l+1]J(W,b,x,y)z[l]z[l+1]=σ[l+1]z[l]z[l+1]
对于 ∂ z [ l + 1 ] ∂ z [ l ] \frac{\partial z ^{[l+1]}}{\partial z ^{[l]}} z[l]z[l+1],由 z [ l + 1 ] z^{[l+1]} z[l+1] z [ l + 1 ] z^{[l+1]} z[l+1]的关系: z [ l + 1 ] = W [ l + 1 ] a [ l ] + b [ l + 1 ] = W [ l + 1 ] σ ( z [ l ] ) + b [ l + 1 ] z^{[l+1]}=W^{[l+1]}a^{[l]}+b^{[l+1]}=W^{[l+1]}\sigma (z^{[l]})+b^{[l+1]} z[l+1]=W[l+1]a[l]+b[l+1]=W[l+1]σ(z[l])+b[l+1],得到:
∂ z [ l + 1 ] ∂ z [ l ] = ( W [ l + 1 ] ) T ⊙ σ ′ ( z [ l ] ) \frac{\partial z ^{[l+1]}}{\partial z ^{[l]}}=( W ^{[l+1]})^T \odot \sigma '(z^{[l]}) z[l]z[l+1]=(W[l+1])Tσ(z[l])
代入上面 σ [ l ] \sigma^{[l]} σ[l] σ [ l + 1 ] \sigma^{[l+1]} σ[l+1]的关系式中得到:
σ [ l ] = σ [ l + 1 ] ∂ z [ l + 1 ] ∂ z [ l ] = ( W [ l + 1 ] ) T σ [ l + 1 ] ⊙ σ ′ ( z [ l ] ) \sigma^{[l]}=\sigma^{[l+1]}\frac{\partial z ^{[l+1]}}{\partial z ^{[l]}}=( W ^{[l+1]})^T \sigma^{[l+1]} \odot \sigma '(z^{[l]}) σ[l]=σ[l+1]z[l]z[l+1]=(W[l+1])Tσ[l+1]σ(z[l])
得到 σ [ l ] \sigma^{[l]} σ[l]递推关系式后,通过第 L L L层的未激活输出 z [ L ] z^{[L]} z[L]的梯度 σ [ L ] = ( a [ L ] − y ) ⊙ σ ′ ( z [ L ] ) \sigma^{[L]}=(a^{[L]}-y)\odot \sigma'(z^{[L]}) σ[L]=(a[L]y)σ(z[L]),依次求出每一层的 σ [ l ] \sigma^{[l]} σ[l],代入 W [ l ] , b [ l ] W^{[l]},b^{[l]} W[l],b[l]的梯度求解式子中即可。

3 DNN优缺点

①DNN优点

​ 由于DNN几乎可以拟合任何函数,所以DNN的非线性拟合能力非常强。

②DNN缺点

  • 参数数量膨胀。由于DNN采用的是全连接的形式,结构中的连接带来了数量级的权值参数,这不仅容易导致过拟合,也容易造成陷入局部最优。

  • 局部最优。随着神经网络的加深,优化函数更容易陷入局部最优,且偏离真正的全局最优,对于有限的训练数据,性能甚至不如浅层网络。

  • 梯度消失。使用 s i g m o i d sigmoid sigmoid激活函数(传递函数),在BP反向传播梯度时,梯度会衰减,随着神经网络层数的增加,衰减累积下,到底层时梯度基本为0。

  • 无法对时间序列上的变化进行建模。对于样本的时间顺序对于自然语言处理、语音识别、手写体识别等应用非常重要。

4 DNN代码实现(手写数字识别)

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets,transforms
from torch.autograd import Variable

#training setting
batch_size = 16
# MNIST Dataset
train_dataset = datasets.MNIST(root='./mnist_data/',
                               train = True ,
                               transform = transforms.ToTensor(),
                               download=True)

test_dataset = datasets.MNIST(root='./mnist_data/',
                              train=False,
                              transform=transforms.ToTensor())

# Data Loader (Input Pipeline)

train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
                                           batch_size=batch_size,
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
                                           batch_size=batch_size,
                                           shuffle=False)

class Net(nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.l1 = nn.Linear(784,520)
        self.l2 = nn.Linear(520, 320)
        self.l3 = nn.Linear(320, 240)
        self.l4 = nn.Linear(240, 120)
        self.l5 = nn.Linear(120, 10)

    def forward(self, x):
        x = x.view(-1,784) # Flattern the (n,1,28,28) to (n,784)
        x = F.relu(self.l1(x))
        x = F.relu(self.l2(x))
        x = F.relu(self.l3(x))
        x = F.relu(self.l4(x))

        return self.l5(x)
model = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(),lr= 0.01 , momentum= 0.5)

def train(epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        print(len(train_loader))
        data,target = Variable(data), Variable(target)
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output,target)
        loss.backward()
        optimizer.step()
        if batch_idx % 10 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                       100. * batch_idx / len(train_loader), loss.item()))


def test():
    model.eval()
    test_loss = 0
    correct = 0
    for data, target in test_loader:
        data, target = Variable(data,volatile=True),Variable(target)
        output = model(data)
        # sum up batch loss
        test_loss += criterion(output, target).data.item()
        # get the index of the max
        pred = output.data.max(1, keepdim=True)[1]
        correct += pred.eq(target.data.view_as(pred)).cpu().sum()
    test_loss /= len(test_loader.dataset)
    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

for epoch in range(1, 10):
    train(epoch)
    test()

  • 3
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

healed萌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值