logo资料库

两层神经网络全连接层.pdf

第1页 / 共35页
第2页 / 共35页
第3页 / 共35页
第4页 / 共35页
第5页 / 共35页
第6页 / 共35页
第7页 / 共35页
第8页 / 共35页
资料共35页,剩余部分请下载后查看
之前的作业中,我们已经完成了一个两层的全连接神经网络的设计,但是有些简单, 并且还没有模块化,因为那里的损失函数和梯度我们是用一个函数来计算出来的。因 此,我们希望可以设计更复杂的网络,以便于我们可以完成不同类型层的设计,然后 将它们集成到不同结构的模型中。 主要内容如下:   1 基础层  1.1 全连接层  1.1.1 前向传播  1.1.2 反向传播  1.2 Relu层  1.2.1 前向传播  1.2.2 反向传播  1.3 损失函数层  2 两层神经网络  3 Solver  4 多层神经网络  4.1 多层网络训练  5 更新规则  5.1 SGD+Momenrum  5.2 自适应优化器  5.2.1 RMSProp  5.2.3 Adam  5.3 四种优化器的比较  6 网络训练  7 预测  8 总结 注意,这里我们提到的层数,是不将输入层算入的。 1 基础层 在 layers.py 文件中,定义了我们接下来所需要的层,我们来逐个进行分析。 1.1 全连接层
1.1.1 前向传播 前向传播的计算类似这样: 1 2 3 4 5 def layer_forward(x,w):     z=   #中间值     out=  #输出值     cache=(x,w,z,out)  #反向传播计算梯度时需要的参数     return out cache 代码如下: 1 2 3 4 5 6 7 8 9 10 11 def affine_forward(x,w,b):     '''x:(N,d_1,…,d_k) x_rsp中我们会将x转化为(N,D),其中D=d_1*…*d_k;  w: (D,M);   b:(M,);   out:(N,M);    cache:(x,w,b)'''     out=None     N=x.shape[0]     x_rsp=x.reshape(N,‐1)     out=x_rsp.dot(w)+b     cache=(x,w,b)     return out,cache 我们可以检验下计算的误差,检验代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 num_inputs=2 input_shape=(4,5,6) output_dim=3 input_size=num_inputs*np.prod(input_shape) weight_size=output_dim*np.prod(input_shape) x=np.linspace(‐0.1,0.5,num=input_size).reshape(num_inputs,*input_shape) w=np.linspace(‐0.2,0.3,num=weight_size).reshape(np.prod(input_shape),outp ut_dim) b=np.linspace(‐0.3,0.1,num=output_dim) out,_=affine_forward(x,w,b) correct_out=np.array([[ 1.49834967,  1.70660132,  1.91485297],                         [ 3.25553199,  3.5141327,   3.77273342]]) print('testing affine_forward function:')
16 print('difference:',rel_error(out,correct_out)) 输出结果如下: 1 2 testing affine_forward function: difference: 9.76984772881e‐10 误差竟然达到e­10,还是挺不错的。接下来我们就继续计算反向传播。 1.1.2 反向传播 反向传播接收来自上一层输出的梯度值和 cache 值,返回输入和权重的梯度,形式如 下: 1 2 3 4 5 def layer_backward(dout,cache):     x,w,z,out=cache     dx=     dw=     return dx dw 实现代码如下: 1 2 3 4 5 6 7 8 9 10 11 def affine_backward(dout,cache):     '''dout:(N,M);   x:(N,d_1,…d_k) x_rsp中我们会将x转化为(N,D),其中 D=d_1*…*d_k;   w:(D,M);   dx:(D,d_1,…d_k);   dw:(D,M);   db:(M,)'''     x,w,b=cache     dx,dw,db=None,None,None     N=x.shape[0]     x_rsp=x.reshape(N,‐1)     dx=dout.dot(w.T)     dx=dx.reshape(*x.shape)     dw=x_rsp.T.dot(dout)     db=np.sum(dout,axis=0)     return dx,dw,db 注:如果不清楚反向传播过程中如何利用利用链式法则进行计算,可以参阅我们上一 次的作业   同样,下面我们来检验下: 1 x=np.random.randn(10,2,3)
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 w=np.random.randn(6,5) b=np.random.randn(5) dout=np.random.randn(10,5) dx_num=eval_numerical_gradient_array(lambda x:affine_forward(x,w,b) [0],x,dout) dw_num=eval_numerical_gradient_array(lambda w:affine_forward(x,w,b) [0],w,dout) db_num=eval_numerical_gradient_array(lambda b:affine_forward(x,w,b) [0],b,dout) _,cache=affine_forward(x,w,b) dx,dw,db=affine_backward(dout,cache) print('test affine_backward function:') print('dx error:',rel_error(dx_num,dx)) print('dw error:',rel_error(dw_num,dw)) print('db error:',rel_error(db_num,db)) 输出结果如下: 1 2 3 4 test affine_backward function: dx error: 2.50214010994e‐10 dw error: 9.11372672216e‐11 db error: 3.57180037616e‐11 bingo,误差还是很小的。这样我们就完成了一层映射层的前向和反向传播两个过程。 1.2 Relu层 1.2.1 前向传播 代码如下: 1 2 3 4 5 def relu_forward(x):     out=None     out=x*(x>=0)     cache=x     return out,cache 检验代码如下:
1 2 3 4 5 6 7 x=np.linspace(‐0.5,0.5,num=12).reshape(3,4) out,_=relu_forward(x) correct_out = np.array([[ 0.,          0.,          0.,          0.,         ],                         [ 0.,          0.,          0.04545455,   0.13636364,],                         [ 0.22727273,  0.31818182,  0.40909091,  0.5,        ]]) print('testing relu_forward function:') print('difference:',rel_error(out,correct_out)) 输出结果如下: 1 2 testing relu_forward function: difference: 4.99999979802e‐08 1.2.2 反向传播 代码如下: 1 2 3 4 def relu_backward(dout,cache):     dx,x=None,cache     dx=(x>=0)*dout     return dx 检验代码如下: 1 2 3 4 5 6 7 8 9 x=np.random.randn(10,10) dout=np.random.randn(*x.shape) dx_num=eval_numerical_gradient_array(lambda x:relu_forward(x)[0],x,dout) _,cache=relu_forward(x) dx=relu_backward(dout,cache) print('testing relu_backward functin:') print('dx error:',rel_error(dx_num,dx)) 输出结果如下: 1 testing relu_backward functin:
2 dx error: 3.27561649471e‐12 到现在,我们差不多已经完成了基础层的构建。但是,实践中,一般映射层后面会接 Relu层,我们这里把两层合为一层来看看: 1 2 3 4 5 6 7 8 9 10 11 def affine_relu_forward(x,w,b):     a,fc_cache=affine_forward(x,w,b)     out,relu_cache=relu_forward(a)     cache=(fc_cache,relu_cache)     return out,cache def affine_relu_backward(dout,cache):     fc_cache,relu_cache=cache     da=relu_backward(dout,relu_cache)     dx,dw,db=affine_backward(da,fc_cache)     return dx,dw,db 梯度检验代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 x=np.random.randn(2,3,4) w=np.random.randn(12,10) b=np.random.randn(10) dout=np.random.randn(2,10) out,cache=affine_relu_forward(x,w,b) dx,dw,db=affine_relu_backward(dout,cache) dx_num=eval_numerical_gradient_array(lambda x:affine_relu_forward(x,w,b) [0],x,dout) dw_num=eval_numerical_gradient_array(lambda w:affine_relu_forward(x,w,b) [0],w,dout) db_num=eval_numerical_gradient_array(lambda b:affine_relu_forward(x,w,b) [0],b,dout) print('testing affine_relu_forward:') print('dx_error:',rel_error(dx_num,dx)) print('dw error:',rel_error(dw_num,dw)) print('db error:',rel_error(db_num,db)) 运行结果如下: 1 testing affine_relu_forward:
2 3 4 dx_error: 1.58523685005e‐10 dw error: 3.68009862446e‐10 db error: 1.04868325611e‐10 1.3 损失函数层 在上一个作业中,我们已经实现了svm和softmax线性分类器,现在我们来实现了svm 和softmax层。 代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def svm_loss(x,y):     ''':param x: (N,C),x[i,j]表示第i个输入是第j个的分数   :param y:(N,),  x[i]的标签    :return:loss,dx'''     N=x.shape[0]     correct_class_scores=x[np.arange(N),y]     margins=np.maximum(0,x‐correct_class_scores[:,np.newaxis]+1.0)     margins[np.arange(N),y]=0     loss=np.sum(margins)/N     num_pos=np.sum(margins>0,axis=1)     dx=np.zeros_like(x)     dx[margins>0]=1     dx[np.arange(N),y]‐=num_pos     dx/=N     return loss,dx def softmax_loss(x,y):     probs=np.exp(x‐np.max(x,axis=1,keepdims=True))     probs/=np.sum(probs,axis=1,keepdims=True)     N=x.shape[0]     loss=‐np.sum(np.log(probs[np.arange(N),y]))/N     dx=probs.copy()     dx[np.arange(N),y]‐=1     dx/=N     return loss,dx 我们检验下我们做的是不是正确,代码如下: num_classes,num_inputs=10,50 x=0.001*np.random.randn(num_inputs,num_classes) y=np.random.randint(num_classes,size=num_inputs) 1 2 3 4
5 6 7 8 9 10 11 12 13 14 15 16 dx_num=eval_numerical_gradient(lambda x:svm_loss(x,y)[0],x,verbose=False) loss,dx=svm_loss(x,y) print('testing svm_loss:') print('loss:',loss) print('dx error:',rel_error(dx_num,dx)) dx_num=eval_numerical_gradient(lambda x:softmax_loss(x,y) [0],x,verbose=False) loss,dx=softmax_loss(x,y) print('\ntesting softmax_loss:') print('loss:',loss) print('dx error:',rel_error(dx_num,dx)) 运行结果如下: 1 2 3 4 5 6 7 testing svm_loss: loss: 9.00034570116 dx error: 1.40215660067e‐09 testing softmax_loss: loss: 2.30262010084 dx error: 8.19589239336e‐09 OK,现在我们已经完成了基础层的构建,下面我们就可以通过这些层的连接来组成我 们想要的结构。 2 两层神经网络 下面我们就使用我们原来构建的基础层来搭建一个两层的神经网络。   我们定义了一个 TwoLayerNet 代的类来实现一个两层神经网络的搭建,代码如下: 1 2 3 4 5 6 class TwoLayerNet(object):     def  __init__(self,input_dim=3*32*32,hidden_dim=100,num_classes=10,weight_scal e=1e‐3,reg=0.0):         self.params={}         self.reg=reg          self.params['W1']=weight_scale*np.random.rand(input_dim,hidden_dim)         self.params['b1']=np.zeros(hidden_dim)
分享到:
收藏