Update from Sync Service

This commit is contained in:
FNS Service
2026-07-31 15:28:08 +08:00
commit b8a78631a4
569 changed files with 193313 additions and 0 deletions
@@ -0,0 +1,34 @@
---
doc_type: hypothesis-highlights
url: 'https://blog.csdn.net/qq_38410428/article/details/101102075'
---
## Metadata
- Reference: https://blog.csdn.net/qq_38410428/article/details/101102075
## Highlights
## mode.train()和mode.eval()作用
### train
- 启用 Batch Normalization 和 Dropout,如果模型中有BN层(Batch Normalization)和 Dropout,需要在训练时添加model.train()
### eval
- 在这个特定的例子中,似乎每50次迭代就会降低准确度。 如果我们检查一下代码, 我们看到确实在train函数中设置了训练模式。
- 修复很简单,我们将model.train() 向下移动一行,让其在训练循环中。理想的模式设置是尽可能接近推理步骤,以避免忘记设置它。修正后,我们的训练过程看起来更合理,没有中间的峰值出现。
## mode.eval()和torch.no_grad()区别
- 主要用于通知dropout层和BN层在training和validation/test模式间切换: 在train模式下,dropout网络层会按照设定的参数p,设置保留激活单元的概率(保留概率=p)。BN层会继续计算数据的mean和var等参数并更新。在eval模式下,dropout层会让所有的激活单元都通过,而BN层会停止计算和更新mean和var,直接使用在训练阶段已经学出的mean和var值。
- 2.eval模式不会影响各层的gradient计算行为,即gradient计算和存储与training模式一样,只是不进行反向传播(back probagation)。
- 而with torch.no_grad()则主要是用于停止autograd模块的工作,以起到加速和节省显存的作用。它的作用是将该with语句包裹起来的部分停止梯度的更新,从而节省了GPU算力和显存,但是并不会影响dropout和BN层的行为。
- 如果不在意显存大小和计算时间的话,仅仅使用model.eval()已足够得到正确的validation/test的结果;而with torch.no_grad()则是更进一步加速和节省gpu空间(因为不用计算和存储梯度),从而可以更快计算,也可以跑更大的batch来测试。
@@ -0,0 +1,125 @@
最近被 [pytorch](https://so.csdn.net/so/search?q=pytorch&spm=1001.2101.3001.7020) 的几种 Tensor 维度转换方式搞得头大,故钻研了一下,将钻研历程和结果简述如下
_**注意:torch.__version__ == '1.2.0**_
## [torch](https://so.csdn.net/so/search?q=torch&spm=1001.2101.3001.7020).transpose() 和 torch.permute()
两者作用相似,都是用于交换不同维度的内容。但其中`torch.transpose()`是交换指定的两个维度的内容,`permute()`则可以一次性交换多个维度。具体情况如 code 所示:
**transpose()**: 两个维度的交换
```
>>> a = torch.Tensor([[[1,2,3,4,5], [6,7,8,9,10], [11,12,13,14,15]],
[[-1,-2,-3,-4,-5], [-6,-7,-8,-9,-10], [-11,-12,-13,-14,-15]]])
>>> a.shape
torch.Size([2, 3, 5])
>>> print(a)
tensor([[[ 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10.],
[ 11., 12., 13., 14., 15.]],
[[ -1., -2., -3., -4., -5.],
[ -6., -7., -8., -9., -10.],
[-11., -12., -13., -14., -15.]]])
>>> b = a.transpose(1,2) # 使用transpose,将维度1和2进行交换。这个很好理解。转换后tensor与其shape如下
>>> print(b, b.shape)
(tensor([[[ 1., 6., 11.],
[ 2., 7., 12.],
[ 3., 8., 13.],
[ 4., 9., 14.],
[ 5., 10., 15.]],
[[ -1., -6., -11.],
[ -2., -7., -12.],
[ -3., -8., -13.],
[ -4., -9., -14.],
[ -5., -10., -15.]]]),
torch.Size([2, 5, 3])))
```
**permute()**:一次性做任意维度的交换
```
>>> c = a.permute(2, 0, 1)
>>> print(c, c.shape) # 此举将原维度0,1,2的次序变为2,1,0,所以shape也发生了相应的变化。
(tensor([[[ 1., 6., 11.],
[ -1., -6., -11.]],
[[ 2., 7., 12.],
[ -2., -7., -12.]],
[[ 3., 8., 13.],
[ -3., -8., -13.]],
[[ 4., 9., 14.],
[ -4., -9., -14.]],
[[ 5., 10., 15.],
[ -5., -10., -15.]]]),
torch.Size([5, 2, 3]))
```
transpose() 和 permute() 之间的转化:
```
>>> b = a.permute(2,0,1)
>>> c = a.transpose(1,2).transpose(0,1)
>>> print(b == c, b.shape)
(tensor([[[True, True, True],
[True, True, True]],
[[True, True, True],
[True, True, True]],
[[True, True, True],
[True, True, True]],
[[True, True, True],
[True, True, True]],
[[True, True, True],
[True, True, True]]]),
torch.Size([5, 2, 3]))
```
如代码所示,先将 [Tensor](https://so.csdn.net/so/search?q=Tensor&spm=1001.2101.3001.7020) a 的 1,2 维度进行交换,再将得到的 Tensor 的 0,1 维度再交换,得到的结果和 permute 是一样的。
## transpose() 和 view()
`view()`是个在 pytorch 中很常见的函数。该函数也起到转换 Tensor 维度的作用,但它转换的方式和 transpose()/permute() 截然不同。如果说`tranpose()`是按照 Tensor 的原有维度忠实地进行交换,那么`view()`就直接而且简单的多——首先,view() 函数会将 Tensor 所有维度拉平成一维,然后再根据传入的的维度信息重构出一个 Tensor。code 如下:
```
# 还是上面的Tensor a
>>> print(a.shape)
torch.Size([2, 3, 5])
>>> print(a.view(2,5,3))
tensor([[[ 1., 2., 3.],
[ 4., 5., 6.],
[ 7., 8., 9.],
[ 10., 11., 12.],
[ 13., 14., 15.]],
[[ -1., -2., -3.],
[ -4., -5., -6.],
[ -7., -8., -9.],
[-10., -11., -12.],
[-13., -14., -15.]]])
>>> c = a.transpose(1,2)
>>> print(c, c.shape)
(tensor([[[ 1., 6., 11.],
[ 2., 7., 12.],
[ 3., 8., 13.],
[ 4., 9., 14.],
[ 5., 10., 15.]],
[[ -1., -6., -11.],
[ -2., -7., -12.],
[ -3., -8., -13.],
[ -4., -9., -14.],
[ -5., -10., -15.]]]),
torch.Size([2, 5, 3]))
```
如代码所示。即使`view()``transpose()`最终得到的 Tensor 的 shape 是一样的,但二者内容并不相同。view 函数只是按照给定的 (2,5,3) 的 Tensor 维度,将元素**按顺序**一个个填进去;而 transpose 函数,则的确是在进行第一个第二维度的**转置**。
此外,有些情况下转置 (transpose) 后的 Tensor 是无法被 **view** 的,原因在于,转置后的 Tensor 不是 “连续”(non-contiguous)的。关于 contiguous array 的问题 numpy 里也一样,在这里有个[很棒的解释](https://stackoverflow.com/questions/26998223/what-is-the-difference-between-contiguous-and-non-contiguous-arrays/26999092#26999092)
@@ -0,0 +1,36 @@
---
doc_type: hypothesis-highlights
url: 'https://zhuanlan.zhihu.com/p/445009191'
---
## Metadata
- Reference: https://zhuanlan.zhihu.com/p/445009191
- Tags:
## Highlights
- loss.backward()故名思义,就是将损失loss 向输入侧进行反向传播,同时对于需要进行梯度计算的所有变量 xxx (requires_grad=True),计算梯度 $\frac{d}{dx}loss$,并将其累积到梯度 $x.grad$ 中备用,即: $x.grad=x.grad+ddxlossx.grad =x.grad +\frac{d}{dx}lossx.grad =x.grad +\frac{d}{dx}loss$
- optimizer.step()是优化器对 xxx 的值进行更新,以随机梯度下降SGD为例:学习率(learning rate, lr)来控制步幅,即:$x=xlr∗x.gradx$,减号是由于要沿着梯度的反方向调整变量值以减少Cost。
```python
x = torch.tensor([1., 2.], requires_grad=True)
# x: tensor([1., 2.], requires_grad=True)
y = 100*x
# y: tensor([100., 200.], grad_fn=<MulBackward0>)
loss = y.sum(). # tensor(300., grad_fn=<SumBackward0>)
# Compute gradients of the parameters respect to the loss
print(x.grad) # None, 反向传播前,梯度不存在
loss.backward()
print(x.grad) # tensor([100., 100.]) loss对y的梯度为1 对x的梯度为100
optim = torch.optim.SGD([x], lr=0.001) # 随机梯度下降, 学习率0.001
print(x) # tensor([1., 2.], requires_grad=True)
optim.step() # 更新x
print(x) # tensor([0.9000, 1.9000], requires_grad=True) 变化量=梯度X学习率 0.1=100*0.001
```
- optimizer.zero_grad()清除了优化器中所有 xxx 的 $x.grad$ ,在每次loss.backward()之前,不要忘记使用,否则之前的梯度将会累积,这通常不是我们所期望的( 也不排除也有人需要利用这个功能)。