我可不向其他博主那样拖泥带水,我有代码就直接贴在文章里,或者放到gitee供你们参考下载,虽然写的不咋滴,废话少说,上代码。
gitee码云地址:
卢东艺/pytorch_cv_nlp - 码云 - 开源中国 (gitee.com)https://gitee.com/Ludongyi/pytorch_cv_nlp
一、情感分析
外卖评论(好评坏评)二分类
用线性模型来做比较简单,就是个简单的二分类,模型代码如下:
用RNN模型来做,可用RNN,GRU,LSTM模型,对于这种简单二分类模型,随便选一个都得,后面复杂的模型才考虑其他。
由图可以看出,训练20次,损失值一直在下降,然后开始震荡并逐渐收敛,训练的准确率一直在上升,当到达20次时,训练的准确率达到97%,进行模型测试,测试准确率只有86%,很明显的过拟合现象,不用慌,自己解决。
二、看图说话
Image Caption多模态任务,根据图片生成描述文字
数据集:
Flickr30k数据集是一个基于Flickr网站的数据集,它包括了31000张图像和每张图像准确的5个人工标注语句。该数据集的图像类型
非常丰富,从日常生活场景到复杂的社会场景都有涉及,本文只使用5条标注语句的第一条作为计算损失函数的输入。
下载地址:Flickr30k图像标注数据集下载及使用方法_flickr30k下载-****博客
网络模型结构:
编码器部分
vgg16的卷积模块进行提取特征:
解码器部分
模型的训练结果如下:
在英伟达P4000显卡的加持下,每轮训练需要7分钟,128批次, 21轮训练损失值才降到1 ,可见这个模型还是有些复杂的,没有好的显卡的人可以去AutoDL算力云 租算力来跑。
测试案例:
一只白色的狗一只狗站在他面前看着嘴里的棍子
从网上下载一张图片进行预测,从预测的结果可以看出,预测的描述有点错误,分析原因,可能是整个网络还不够复杂,vgg16网络没有很好提取狗的嘴巴特征,LSTM预测的词不是很好。额,什么狗屁预测。
改进模型:
增加注意力机制: 在LSTM中引入注意力机制,使模型能够动态地关注图像中不同区域的信息,从而改善生成描述的精度和连贯性......
避坑
建议训练和测试都放到一个程序里,也就是训练完毕接着测试显示结果。我的代码是训练和测试分开的,是不同的进程。然后我发现每次运行词典都不一样,每次都会有不一样的id和乱序,这会造成一个问题,训练一半保存参数,下次加载模型参数重新训练时导致损失值很高而难以下降,因为词典的序号都变了,上次训练的参数语义信息不适用当前。还有如果你训练和测试都效果不错,过几天后发现预测效果很差,可能是一不小心运行数据处理部分,生成了新的词典了。所以,需要保存词典,而且只保存一次,下次加载处理接着用该词典,固定住词典。
在词典里没有的词模型是预测不出来的,所以如果发现模型预测的效果差,可能是词典里的单词少了,可以到网上找常用的英语单词5万个,搞成一个大的词典 .pkl格式,保存起来,方便自然语言处理的学习使用。
统计正确率:
生成的文本与目标的文本如何才能判断是预测对的,太难判断了。就算计算两个文本的相似度,相似度大于0.5正确,小于则错误,但是,以上面的图片为例子,目标文本是两只小狗亲嘴,如果生成了草地的预测文本,相似度为0 ,但是你能说它预测不正确吗,草地也属于图片的潜在描述之一。
所以,这里不统计正确率。
深度学习之Image captioning的评分指标篇(BLEU、CIDEr)_bleu和cider-****博客
python中计算BLEU分数_python 计算blue分数-****博客
创新点:
1.动态调参技术
训练模型时参数是固定的,也就是一旦运行代码,就只能看着输出的结果,而不能手动改变里面的参数,如果在训练时发现损失值已经震荡收敛了,还继续训练这就造成资源的浪费,所以,这就要人为的进行控制调参,使程序能正常运行又不浪费资源。
本模型采用tkinter库进行GUI调参,控制模型的训练次数和学习率。
界面如图所示:
开一个线程,运行调参窗口,里面设置模型需要改变的重要参数。如学习率初始值为0.003,训练次数初始值为30。训练过程观测损失值的变化,如果损失值的改变量变小了,就把学习率调小为0.001甚至更小 ;如果损失值开始震荡收敛,就把训练次数改为当前轮的值,使训练完当前轮后就自然退出模型的训练,进行测试;如果训练了30次后损失值还有下降的趋势,就增大训练次数。
虽然GUI调参很方便,但多开一个线程也耗费了一定的资源,而且,这方法只适合有模型训练经验的人,有经验的调参大师。
2.训练过程提醒技术
有时候模型训练的时间需要很久,训练模型的人应该不会一直看着模型的训练过程,这时候需要需要一项提醒技术,每训练完一轮或者全部训练完毕,可以提醒训练者。
WxPusher微信消息推送服务介绍:WxPusher (微信推送服务)是一个使用微信公众号作为通道的,实时信息推送平台,你可以通过调用API的方式,把信息推送到微信上,无需安装额外的软件,即可做到信息实时通知。 你可以使用WxPusher来做服务器报警通知、抢课通知、抢票通知,信息更新提示等。 WxPusher微信推送服务
用户收到消息后,微信会响通知铃声,用户进入微信查看具体消息文字。
参考:shenxiaohai.me/pytorch-tutorial-advanced-04/
三、经验分享
数据处理类 继承 Dataset类,然后要写 def __len__() 和 def __getitem__(item)这两个特殊函数。def __len__()函数返回的是处理数据的大小,可以把它看成是循环调用def __getitem__(item)函数的次数,比如返回的是10,就调用10次__getitem__函数,__getitem__处理并返回了10个数据。
设计模型时先训练一批次的数据 (Dataset类里def __len__()返回batch_size大小,把模型设计好后,保证能正常运行出结果,再用全部数据。
策略:写代码时__len__()函数返回的大小分别采用一批次,一半,全部。
假如你一下子处理了全部数据,开始设计模型,运行,处理数据跑了一分钟,模型报了一个错,你修改模型代码,跑了一分钟,又报了一个错,又修改......等你能正确运行代码,浪费了很多时间。而刚开始就只处理一批数据,一下子就能出结果。所以我写代码刚开始只用一批次是验证代码能不能正常运行。
代码能正常运行了,我就把数据量增大到一半,用来验证模型的损失值和正确率是否正常,是否出现过拟合现象,模型是否需要改进......没问题后,我就处理完全部数据,继续增大训练,再观察效果,最后完工。
嫌数据集数量多,先不着急删除(万一突然想要用到),先只处理一部分数据训练看看效果,最后再决定删不删除。
要加检测损失值,连续2次震荡就停止训练,记得每隔几次保存一次模型参数,不然中途退出就白干。
训练集和验证集都计算损失值和准确率,观测数据之间的变化。
其他的经验自己多跑模型就能总结出来,跳过很多坑的过来人默默留下了眼泪(手动狗头)
未完待续......