cs231n之Assignment2全连接网络上

  • 2019 年 10 月 6 日
  • 筆記

cs231n之Assignment2全连接网络上

——光城

0.说在前面

在上次作业中,已经实现了两层神经网络,但是有些问题,比如程序不够模块化,耦合度不高等问题,所以本节引出神经网络的层与层结构。本节主要实现一种模块化的神经网络架构,将各个功能封装为一个对象,包括全连接层对象,仿射层,Relu层等,在各层对象的前向传播函数中,将由上一层传来的数据和本层的相关参数,经过本层的激活函数,生成输出值,并将在后面反向传播需要的额外参数,进行缓存处理,将根据后面层次的提取与缓存值计算本层各参数的梯度,从而实现反向传播。

1.仿射层

仿射层前向传播

目标:

– 计算实现一个仿射层的前向传播

输入:

– x: (N, d_1, …, d_k)

– w: (D, M)

– b: (M,)

返回:

– out: (N, M)

– cache: (x, w, b)

实现

仿射层反向传播

目标:

计算仿射层的后向传播

输入:

– dout: (N, M)

– cache:

x: (N, d_1, … d_k)

w: (D, M)

b: (M,)

返回:

– dx: (N, d1, …, d_k)

– dw: (D, M)

– db: (M,)

实现:

首先获得上面前向传播的输出值与cache,紧接着计算反向传播。

cache解开得到前面仿射层的前向传播参数,接着计算梯度即可!

实现

2.RELU层

Relu层前向传播

目标:

计算Relu的前向传播

输入:

– x: 任意shape的输入

返回:

– out: 输出同x一样的shape

– cache: x

实现:

上面目标很明确,这里直接来实现,不多解释,这里用到了一个布尔矩阵运算,如果觉得疑惑,请看作业详解knn中的解释!

实现

Relu层后向传播

目标:

计算Relu的后向传播

输入:

– dout: 任何shape的前向输出(这里疑惑的看英文原文)

– cache:同dout相同shape的x

返回:

– dx: x的梯度

实现:

Relu只有矩阵中大于0的数有效,所以x>0筛选得出一个布尔矩阵,直接相乘就是最后的结果。因为如果x<0,求导肯定为0,所以有效值,就是x>0的结果!

实现

3.两层组合

组合前向传播

目标:

完成仿射层与Relu层组合

输入:

– x: 仿射层的输入

– w, b: 仿射层的权重

返回:

– out: ReLU层输出

– cache: 后向传播的缓存

实现

组合反向传播

目标:

实现反向传播

输入:

– dout

– cache

返回:

– dx: x梯度

– dw: w梯度

– db: b梯度

实现:

直接调用刚才的方法。

4.两层神经网络

类封装

目标:

实现affine – relu – affine – softmax架构

输入:

– input_dim: 输入层尺寸

– hidden_dim: 隐藏层尺寸

– num_classes: 类别数

– dropout: 随机失活强度 0~1

– weight_scale: 权重范围

– reg: 正规化

实现:

封装全局参数

实现

损失函数

输入:

– X: (N, d_1, …, d_k)

– y: (N,)

返回:

If y is None

test-time forward

– scores: (N, C)

If y is not None,

training-time forward

backward pass

– loss

– grads

实现

5.Solver训练

概要

使用这个训练之前,需要补充optim.py!

此文件实现了常用的各种一阶更新规则用于训练神经网络。每个更新规则接受当前权重和相对于那些权重的损失梯度并产生下一组权重!

SGD

SGD公式

这个被称为朴素sgd(Vanilla SGD)

公式中四个参数分别对应为:下一次的权重w,当前权重w,学习率,当前权重的梯度!

实现

Momentum

Momentum公式

这个被称为结合动量的sgd(最常用)。

阿尔法代表学习率!

实现

RMSProp

RMSProp公式

实现

Adam

Adam公式

实现

训练

实现

训练结果