2022Cs231n笔记-神经网络和反向传播

本文详细介绍了神经网络的结构和容量设定,重点解析了反向传播的计算思想,包括如何利用计算图和链式法则求解权重梯度。通过PyTorch的autograd机制,解释了如何在实践中实现反向传播,并探讨了向量反向传播中的雅克比矩阵应用。此外,文章还讨论了神经网络正则化对抗过拟合的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一切图片来自官方PPT网站Index of /slides/2022 

代码部分:双层网络(仿射层+ReLu层)_iwill323的博客-CSDN博客

目录

神经网络

神经网络结构​

 关于神经网络capacity的设定

反向传播

计算思想

例子

pytorch中的反向传播

向量的反向传播

引申


神经网络

神经网络结构

神经网络计算层数的时候是不带输入层的

 “3-layer Neural Net”, or “2-hidden-layer Neural Net”

# forward-pass of a 3-layer neural network:
f = lambda x: 1.0/(1.0 + np.exp(-x)) # activation function (use sigmoid)
x = np.random.randn(3, 1) # random input vector of three numbers (3x1)
h1 = f(np.dot(W1, x) + b1) # calculate first hidden layer activations (4x1)
h2 = f(np.dot(W2, h1) + b2) # calculate second hidden layer activations (4x1)
out = np.dot(W3, h2) + b3 # output neuron (1x1)

 关于神经网络capacity的设定

神经网络尺寸越大越容易过拟合

使用正则化可以抑制过拟合

官方笔记的建议:The regularization strength is the preferred way to control the overfitting of a neural network. The takeaway is that you should not be using smaller networks because you are afraid of overfitting. Instead, you should use as big of a neural network as your computational budget allows, and use other regularization techniques to control overfitting.

反向传播

计算思想

一般把输入输出当做给定的(也有例外,比如神经风格转化),于是计算的过程就是求解最优权重的过程。反向传播就是为了计算梯度、更新权重。方法是采用计算图分解复杂的计算过程,通过链式法则一步步计算中间变零的梯度,直至计算出所有权重的梯度。

每个节点计算自己的梯度的时候,不需要知道上游的梯度。这样每个节点只需要计算好自己的梯度就行了。

所有节点组成了一个电路。Every gate in a circuit diagram gets some inputs and can right away compute two things: 1. its output value and 2. the local gradient of its output with respect to its inputs.每个节点从上游接受传来的信号(梯度),然后和自己的自变量的梯度相乘,向下游传导。

PPT: backpropagation = recursive application of the chain rule along a computational graph to compute the gradients of all inputs/parameters/intermediates

 例子

计算图不是唯一的,可以把相近节点合成一个有意义的计算节点,比如sigmoid

 

pytorch中的反向传播

理解了上面的思想,再学习pytorch的autograd就更简单了。

如果想在反向传播过程中计算一个参数的梯度,那么就把它的requires_grad属性设置成True。只要对一个参数这么做了,那么由他计算出来的所有因变量requires_grad属性都是True。

pytorch中变量有一个grad_fn属性,用于梯度的计算和传播。用户直接创建的Tensor,其grad_fn是None,通过计算产生的tensor,它的grad_fn不是None(当然还要要求自变量至少有一个requires_grad=True.)。grad_fn指向一个Function对象,这个Function对象知道如何计算正向的函数,以及如何在反向传播步骤中计算导数。长这个样子

 一般不人为定义这个Function对象,因为pytorch直接帮我们定义好了。直接对loss执行loss.backward()就行了。这个操作将调用loss里面的grad_fn这个属性,通过Function对象执行求导的操作。每一个grad_fn有一个next_functions属性,指向下游(对反向传播而言)的Function对象,继续求导,于是梯度信息就不断向下传播,直至计算图的叶子节点。计算出结果以后,将结果保存到他们的 grad这个属性里面。求导结束,所有的叶节点的grad变量都得到了更新

a = torch.tensor([3.14], requires_grad = True)
b = torch.sin(a)
c = 2 * b 
d = c + 1
print(d.grad_fn)
# <AddBackward0 object at 0x7fabeda787d0>
print(d.grad_fn.next_functions)
# ((<MulBackward0 object at 0x7fabeda78ad0>, 0), (None, 0)) None对应的是常数
print(d.grad_fn.next_functions[0][0].next_functions)
# ((<SinBackward0 object at 0x7fabeda78ad0>, 0), (None, 0))
print(id(d.grad_fn.next_functions[0][0])==id(c.grad_fn))
# True  说明变量的grad_fn属性是相互连接的,就像电路图里的元器件一样

尤其要注意的是,上下游变量的grad_fn是连通的,这就是计算图的思想(猜的)

向量的反向传播

雅克比矩阵长这个样子(维度和下面的应用差一个转置)

注意,由于z是向量,所以local gradient这时候成了雅克比矩阵,更新下游梯度的时候采用的是矩阵乘积。并且变量关于loss的梯度和原变零的维度是一模一样的。

 

  官方PPT的例子:

 有了雅克比矩阵,就可以通过矩阵运算来计算下游梯度,但是这么做运算代价太大:

 根据乘法求导的特点,从某种程度上讲,权重和输入分别就是y关于输入和权重的导数。可以跳过雅克比矩阵,直接用上游梯度和权重矩阵来算:

 

代码来自官方网站 https://cs231n.github.io/optimization-2/

# forward pass
W = np.random.randn(5, 10)
X = np.random.randn(10, 3)
D = W.dot(X)
	 
# now suppose we had the gradient on D from above in the circuit
dD = np.random.randn(*D.shape) # same shape as D
dW = dD.dot(X.T) #.T gives the transpose of the matrix
dX = W.T.dot(dD)

dW和dX的计算公式不用记,因为通过维度匹配就能推出来。

引申

在这里,2022年的PPT比2021年的删去了下面这一部分,我倒是觉得原来的内容挺好的

 

拓展资料: http://cs231n.stanford.edu/handouts/linear-backprop.pdf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值