Update from Sync Service
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
|
||||
## 一、GRU模型的关键参数
|
||||
|
||||
1. input_size:输入的特征数,代表输入序列数据中每个值由多少个特征表示,比如NLP中,每个单次由几维的词向量表示;
|
||||
|
||||
> 个人经验:在氢燃料电池系统性能均值预测模型中,input_size代表了输入序列中每个值有多少个特征维度;
|
||||
|
||||
2. hidden_size:隐藏层特征数;
|
||||
3. num_layers:代表GRU的层数;
|
||||
4. bias:是否带有偏置, False则没有偏置,即$b_{ih}=0, b_{hh}=0$. 默认为True
|
||||
5. batch_first:输入序列中,第一个维度是否为batch. 默认为False;
|
||||
6. dropout:除最后一层,每一层的输出都进行dropout,默认为: 0
|
||||
7. bidirectional:是否为双向GRU,默认为False;
|
||||
|
||||
## 二、GRU模型的输入和输出及维度
|
||||
|
||||
### 2.1 输入
|
||||
|
||||
1. GRU模型的输入为input和$h_0$,其中input是输入的序列数据,$h_0$是第一个GRU cell的隐藏层在每个batch中的初始值,$h_0$可以不提供,系统会默认生成一个符合维度要求的全零tensor。
|
||||
2. 输入维度:
|
||||
1. input,当参数batch_first为False时,input的维度为(seq_size, batch_size, feature_size),当batch_first为True时,input的维度为(batch_size, seq_size, feature_size);
|
||||
2. $h_0$的维度为(num_layers×GRU方向数,batch_size,hidden_size);
|
||||
|
||||
### 2.2 输出
|
||||
|
||||
1. GRU模型的输出为output和$h_n$,其中output为模型输出值,$h_n$为模型最后一个GRU cell的隐藏层状态;
|
||||
2. 输出维度:
|
||||
1. output的维度为(seq_size,batch_size,num_layers×GRU方向数)
|
||||
2. $h_n$的维度为(num_layers×GRU方向数,batch_size,hidden_size)
|
||||
|
||||
> 1. GRU方向数:当bidirectional为True时,GRU方向数为2,当bidirectional为False时,GRU方向数为1;
|
||||
> 2. seq_size为输入的单个序列长度,对于NLP代表了每个句子的长度,对于氢燃料电池系统性能均值预测模型中,seq_size代表了序列的时间窗口长度;
|
||||
|
||||
## 三、对应关系
|
||||
|
||||
1. GRU设置参数中input_size与输入序列input的最后一个维度即feature_size对应;
|
||||
2. GRU设置参数中hidden_size与输入$h_0$、输出output和$h_n$的最后一个维度对应;
|
||||
3. GRU设置参数中num_layers与输入$h_0$、输出$h_n$的第一个维度中num_layers对应;
|
||||
4. GRU设置参数中bidirectional与输入$h_0$、输出output和$h_n$的第一个维度中GRU方向数对应;
|
||||
5. GRU输入和输出中seq_size、batch_size不变,但是最后一个维度由输入的feature_size变为输出的hidden_size;
|
||||
|
||||
> 由于上述对应关系,在encoder-decoder架构中,decoder和encoder的hidden_size必须保持一致,否则会出现维度不匹配的问题;
|
||||
|
||||
## 参考文献
|
||||
|
||||
1. [循环神经网络 - torch.nn.GRU()参数详解](https://blog.51cto.com/u_11299290/4727876)
|
||||
2. [RNN, LSTM, GRU中输入输出维度](https://blog.csdn.net/sophicchen/article/details/108005115)
|
||||
@@ -0,0 +1,6 @@
|
||||
1. 位置编码
|
||||
2. 自注意力
|
||||
3. 多头自注意力
|
||||
4. 全连接网络
|
||||
5. 残差连接
|
||||
6.
|
||||
+34
@@ -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=x−lr∗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()之前,不要忘记使用,否则之前的梯度将会累积,这通常不是我们所期望的( 也不排除也有人需要利用这个功能)。
|
||||
|
||||
Reference in New Issue
Block a user