自动驾驶—— Image Caption的学习笔记

1 前言

序列映射我们当前准备使用Transformer的结构;

2 致谢

感谢公众号《人工智能技术干货》提供的资料,《如何优雅的使用pytorch内置torch.nn.CTCLoss的方法》

让我收获了很棒的知识!

3 词表建立的规则

我们使用","作为统一的分隔符;

3.1 词典类——Vocab

我们使用set来作为词典的数据结构;

4 模型设计

3.1 backbone——rec_r34_vd

主干网络的设计我们是参考的PaddleOCR的识别模型,

代码的链接如下:

https://github.com/PaddlePaddle/PaddleOCR/blob/develop/ppocr/modeling/backbones/rec_resnet_vd.py

3.2 loss函数—— CTC Loss

关于 CTC Loss函数的数学推导:

https://zhuanlan.zhihu.com/p/43534801

关于 CTC Loss中CTC动态规划的计算过程,可以参考  Deep Systems的PPT文档:

https://docs.google.com/presentation/d/12gYcPft9_4cxk2AD6Z6ZlJNa3wvZCW1ms31nhq51vMk/pub?start=false&loop=false&delayms=3000#slide=id.g24e9f0de4f_0_332

3.2.1 代码写作——torch.nn.CTCLoss

我们使用PyTorch自带的CTCLoss;

CTCLoss的输入有两种方式:padded和un-padded;

这里我们是推荐un-padded方式,因为不用预先做padding的操作,会方便一些,也更好理解;


nn.CTCLoss()参数说明:

blank——空白标识:

类似于一种占位符,在CTC-Loss中用来分隔两种字符区间,例如“ap-ple”,可以使用blank来分隔字符串中相同的元素;

我们在词典中也会加入<blank>字符,并将词典中的ID闯入到这里的blank参数中;

ctc_loss()参数说明:

参考代码是

loss = ctc_loss(output.log_softmax(2), target, input_lengths, target_lengths)

input——预测数组:

input模型的预测值,在输入到loss之前需要log_softmax(2);

targets——目标数组的长数组:

称它为长数组,是因为它是由目标值拼接而成的,拼接的方法是使用了“long_array += array”;

形象化的解释可以参考我发的博文,这里粘贴一下,

5 模型调试

5.1 loss出现了“nan”——模型在计算时出现了数值溢出

5.1.1 由梯度爆炸引起的“nan”现象——而不是学习率lr过大引起的

梯度爆炸是会引起loss出现“nan”现象的,这是因为梯度在反向传播的过程中出现了“数值溢出”的问题,(这样的问题并不一定是代码的问题导致的)

观察点一:调小学习率之后,未出现梯度爆炸,说明不是loss计算的问题,而是梯度反向传播出现的问题;

观察点二:在使用最初大学习率时,会偶然出现“loss is nan”的情况,而不是每次训练都会出现,说明loss的前向计算不存在问题;

观察点三:使用最初大学习率时,模型有一定几率(例如50%)收敛的很好,说明学习率的设置不存在问题;

综上所述,这可能是由于模型存在大量的“全连接”结构,梯度在反向传递时,出现了多次的“乘法”运算而产生了梯度爆炸;

猜想:可以尝试使用梯度裁剪,来避免梯度回传时产生的数值溢出;

实验结果:使用梯度裁剪是可行的;

6 提问备忘

4.1 为什么Transformer不能指定输出encoding的大小呢?

今天在写作的时候,想到了这个问题,为什么Transformer不能指定输出encoding的大小呢?

我看了一下PyTorch的接口说明,的确是没有的,

然后请教了一下亮亮老师,老师说是因为PyTorch的实现版本没有提供这个功能,

他建议我看看OpenNMT-py,感谢亮亮老师!

猜你喜欢

转载自blog.csdn.net/songyuc/article/details/107460069