00:00
呃,大家好,今天这期视频是给大家讲一下ccf这个比赛,呃,以及。呃,就是如何去使用嗯,Transformers它的预训练模型,然后去定义自己的一个呃模型,就是加载它的预训练模型,然后啊,去用在自己的一个下游任务。啊,重点是讲这一块这一部分。好,那我们先看一下这个比赛吧,呃,这个比赛是这样的。呃,它是一个分类任务,就是说。就是他训练你是这样子的ID,然后class label,就是说呃,这个content就是就是这个文本内容它的类别,那么类别有几个呢。呃,训练里面类别一共有七个啊,就是这个。然后呢,他还给了一个未标注的数据,呃,我个人感觉他的意思可能是这样子的,就是说让你通过这个已标注的数据啊,训练出一个模型,然后呢,去呃预测这个呃就是去标记这个没有标记的数据,那么这两个加在一起,总共呃就会有4万个样本。
01:07
啊,4万篇文档,然后再用4万篇文档啊,再去训练一个模型,然后再来去就最后进行一个测试啊,去测试这个2万篇文档是这样的一个,呃情况。嗯。但是呢,呃,这个就是大家很明显可以看到,就是说你的训练数据有七类,但是呢,它的测试数据,也就是最终要提交的这个数据,这个是最终要提交的,呃,这个数据它有十个类别,所以说有三个类别是没有的,也就是最后这三个,呃,这个东西怎么做,我现在其实还不太知道,呃,当然我想的话就是说。呃,你去,呃,就是呃,这个怎么怎么做,我其实还没有想好,所以说我就简单的就分了个七类,然后剩下这三个我就没有管它,当然这个不是我们的重点啊,重点是如何去用这个transformers啊,所以我就先简单介绍一下这个数据,大家到时候自己去看一下可以了。
02:05
好的,我就直接讲一下代码吧。呃,这个地方我写了两两个版本的代码,一个是呃,用的什么呢?用的哈工大的一个,呃,预训练模型,比方说我用的是X,因为因为这个数据啊,呃,这个比赛它的数据是中文的,就是文本内容啊,这些都是中文的,而这个transformers transformers,它这里面中文的预训练模型非常的少,只有一个,呃。啊,这里。只有一个,而且这个呃,还是一个贝。啊,这里bird base,它就只有这一个预习类的模型。呃,所以说如果说你想要有啊更好的模型使用的话,可以用这个哈工大的他们预训练的一个XRNE,还有还有这个,呃,还有这些什么之类的。所以我这里也写了两版,一版是呃,用的这个哈工大的,一版是用的这个transformers,那我先讲一下transformers吧,呃,这个transformers啊,我用的它的什么呢?非常简单,我用的它的一个。
03:13
啊,算了,我先讲一下这个哈根大的吧,因为哈大这个比较通用。呃。好,那么大家可以看一下它这个read me啊。其实前面都我没有什么说的,后面的话也没有,它这里有个最重要是这个这个地方,他说快速加载,如何去使用transformers去调用这个模型呢?那你就只需要去,呃,首先你要有一个to和一个model,呃,这个这个to和model啊,这个其实我在这个。这个LNE文本关系抽取这个视频里面讲过,呃,当时那个视频讲的非常的清楚,大家如果没有看过的话,就先去看一下那个视频才会懂啊,这个讲的是什么东西?好,呃,这个talk其实就是说呃,你把一个文本传进去之后,它就会自动给你分词,然后并且给你传出来一个ids,也就是呃分词后,然后那个词所对应的那个呃,Index。
04:07
然后这个model就是啊,就是model对吧,好,那你就去加载这两个,加加载这两个东西,那这个model name是什么呢?就是这里这两个东西。啊,就把这个copy过去就可以了,看你要用哪个,那么它这个模型的名字啊,有不同的效果,比方说它这个X me。它有什么效果呢啊,他这里就写了什么什么效果,然后比方说base,它的效果是什么样子的,当然我的呃,我的实验室的呃,一个GPU是是11G的,所以说呃,我当时试了一下,11个G用这个密的这个模型是跑不了的,会扩大out of memory,那只能用这个base。嗯,好,那就啊,那我们来看一下代码吧。啊,首先这里面包括一些呃,数据处理的部分,呃,这个地方我想一下,还是给大家讲一下吧。
05:04
啊,首先给大家看一下数据,比方说这个,呃,这个地方label的贝塔,也就是训练集。看一下什么样子的。呃,它就是有一个ID,然后class label,然后content对吧,然后ID0,然后时政,然后后面是这个五,呃内容,然后ID是一,然后它是房产类别的,然后后面有个内容。然后ID2也是房产这样子好看了这个数据之后呢,因为我们就这一个数据,然后我也没有去,呃,远程就是去标注这个未标注的数据,所以说其实我用到的呃数据啊,就这一个。我就只训练这一个数据集,然后呢去呃,预测这个东西就完了,所以我根本就没有用到这个未标准数据,当然用到的话肯定会更好,但是我还不知道怎么去用啊,当然这个不是重点啊,重点是如何使用这个预训练模型。呃,首先设置一个随机种子啊,这个都非常好说了,都没什么说了,直接直接就是我从百呃百度上copy一个代码就可以了。
06:04
不用管他啊。然后后面呢,这个是呃,Process data啊,Label的data,也就是呃,标注了的数据,然后传入一个class to I DX,呃,True这个表示什么意思呢?请看一下吧。大家可以看一下,这里有一个class to idx,就是我把这个呃类别转换成一个呃数字,然后还有一个数字再转成类别啊,这样的一个互利的一个东西字典。然后这里是process data对吧,把这个你的file name传进来,然后把这个传进来,为什么传这个呢?呃,因为我想让他就是说。因为我想让他就是把这个呃实证啊,还有房产这些的都换成数字,我不需要它的中文,所以说呃代码的话就非常简单,你就要把这个用一个panda啊瑞CSV把这个读进来,然后呢,如果说你有呃。
07:00
就是你有标签的话,呃,什么叫标签呢?标签就是这个。标签就是这个实证啊,房产啊等等。因为后面是有的,是没有标签的,比方说像这个,呃,你的测试数据就是你要提交的这个数据集啊,它就是没有标签,它只有内容。怎么卡住了?啊,这里它就只有内容,它没有标签,它没有标签的话,那你就没有办法处理这个表,没有办法去用呃index去转换。啊,所以说这里。就设置,呃,设置一下,判断一下,如果说有标签,那你再去转换,怎么转换呢?就用点replace这个字典的方式去把这个class label这个列。啊,大家可以看到这里有个class label这个列,也就是这个之类的,把它转换成用这个class to index这个字典去换好,那么最后那这个data它返回出来这个data frame。
08:03
啊,就对,我也标注了,就是然后后面下划线表示它的一个数据的格式,它是个frame,呃,它的内容现在变成什么呢?ID还是一样的,Class就变成数字了。然后content content。呃,之后呢,我去,呃去在这个训练就是这个标注了的数据上。去拆分一下训练级和验证级。啊,然后这里呢,我是自己写的一个函数,因为这是个data frame嘛,然后但是呢,呃,S里面是有这个test SP,但是S里面的那个不支持对data frame进行操作,就就直接去做了一个data data frame进行操作的一个函数,非常的短啊这么一点,所以你把这个data frame传进来,然后你要划分你的呃,验证级的一个。啊,比例啊20%,然后是否要瞎吼。Shuffle就是在在在划分之前先去一个shuffle啊,Random等等,好,那就是首先如果是shuffle的话,那你就先shuffle消完了之后再去划分一下,呃。
09:05
嗯。训练级和验验证级,但是验证级的话,我就用test来表示,那就很简单,你只要把这个呃。按一个比例去划分就可以了,前这么多份给到这个train,后面这么多份给到这个test就可以了。好,那么它最终返回出来是这个啊,它也是个data frame。啊,Data frame和validation data frame也就是一个训练的,呃,训练集和验证集。然后呢,我现在去处理一个训练集,要处理什么什么样呢,我需要把这个训练集啊。首先要给它转换成一个呃拍的data size,然后把这个data size传到这个data load里面啊,这已经是非常常见的一个操作了,就是自定义数据集的方式,好,那我就看一下这个怎么去实现自己的一个,首先你要去继承这个,呃。的size。
10:01
啊u t.data里面的data set这个类要的,然后你们要实现两个函数一呃。在这之前呢,呃,我先说一点,就是说我之前做这个,呃,比赛的时候呢,就是之前这个视频啊,呃,我当时做了一个方法是说就是将这个。啊,数据传过来之后,直接一股脑先全部呃。转换成ids,也就是通过一个预训练的一个方法,然后转换成ids,而这里呢是说就是嗯,当你要用到这个数据集,数据集的时候,也就是在data load里面,它返回出来,呃数据的时候,它才会转换成ids。呃,这是两种不同的方法,但是这种方法其实是更好一些的,因为我看网上几乎所有人都是用的这种方法,没有人用我这种之前这种一次性先全部转换成ids,这个是不太好的,而且会非常的慢啊。
11:03
这样子的,呃,用这种接待的方法就好一些。好,那我看一下吧,首先在这个initial函数里面啊,我先啊把这个它是个data frame类型的,我这里注释了。然后呢,你这里要去,呃,用一个,那这里其实有很多种。我可以看一下这里。啊,它这里to其实有非常注重啊,比方说你用的是Albert的话,那就会那就那那它的名字就是Albert,那如果你用的是birdt的话,那就是bet to,那这里我用的是一个auto talk,就是说它自动的去,呃,根据你这个模型的名字来去选择你的呃,Talk,那这个是啊自动的选择一个方式,然后这里我使用的是就是我的默认的这个参数啊,是base Chinese。但实际上我在这个方法当中用到什么呢?就是我用到前面提到的哈工大的一个。呃,预训练的一个,呃,XL net,那么它这个模型的名字啊,HFL,然后Chinese XL net base,把这copy过来放在这里,等会传进去就可以了,好,那这个啊头就实例化好了。
12:11
然后你的这个文本最长要设置为多长的啊,这个地方你要去自己统计一下,就是大部分的文本都是多长的,然后with labels,就是说它是否呃含有label啊,如果含有label,那么也要对label去进行进行处理啊,Label就是你的target,也就是这里的这个啊,是呃这些东西。好,那我们看一下这个learn啊,非常简单,就反回它的元素个数就可以了,那么get item在这个里面去进行一个,呃。呃,去进行一个token的一个呃使用,那首先你要去把这个呃文本处理出来,对吧,那就是呃,因为这个这个data是个data frame data frame的lock方法,然后index传进来,然后把这个content这个列。
13:01
啊传进来,那么此时它就会返回什么呢?返回你就给定的index。给定的行所对应的content。的内容,并且它是string类型的。然后呢,我先要把这个呃句子啊。分词,分词之后呢,再通过index。呃,就是去查它的index啊,然后获取它的attention mask token type,呃,Index等等等等去获取出来,那么首先要经过一个token,然后把这个句子传进去,然后Ding等于ma,就是说啊,你是否要进行Ding呢?是的,那么你Ding的长度是多少呢?使ma,那就是说它会自动去获取你这个maence的长度,那这个ma的长度是多少呢?我这里设定是self啊,Ma对,我设定好的,然后呢,呃,Return。就是返回,它的返回类型是个CH类型的。呃,那么这个是表示什么呢?就是说如果你超过这个max论啊,就给它截断。
14:00
所以说这个地方就既考虑到了,呃不够长就要加派的,呃够长就要截断好。那么下面就是呃就不说了,就是它,它是个字典类型的,字典类型里面input ids,也就是这个文本啊,它的一个分词,以后呃,各个词它的索引。啊,它并且是拍attention attention类型的,然后这个Co PI里面的attention mask啊,就是mask啊。然后这个是token type ideas,也就是说如果你有呃一句话的话,那么他们都是零,如果是两句话的话,它就是呃,零和一啊,这里我再说一点,假如说你这个是个句子对的任务,那你这儿有一个句子一,然后你这还有个句子二。那你在这里再加上一个二就可,呃,哪个逗号就可以了,不用管它。但是我都是一个句子的任务。
15:00
好,那么with labels,如果是他有label呢,那你们那你这个label也要去返回出来。啊,如果没有label的话呢,那你就直接把这三个东西返回出来就可以了,那什么情况下会有label呢?就是当你在训练的时候或者验证的时候会用到,那什么情况下会返回这个呢?就当你在进行最终啊测试的时候会用到,因为你测试的时候是没有呃,Label的。啊,那么这个就是一个自定义的这个一个data size,然后把这个data size呢,啊封装好,然后传到这个data漏洞里面去。啊啊,这里。Train size,然后by size啊呃,线程数还有shuffle等于什么都设置一下好,那么这个train data load就是就完了,那么这个validation data也是一样的,Validation data的话。传入的就是validation data frame。那么这个地方也非常简单啊,这是一样的。然后呢,最后就是说你去定一个模型了,模型的话,刚才我前面已经,呃。
16:00
啊,模型化还没讲过。呃,这里模型首先你要呃这个参数不是必须的,这是我自己去设置的,比方说呃,万一真的有用户有需求,就是说呃,他这个预训练的模型啊,他并不想去,呃就是反向传播的时候,他并不想去更新这个预训练模型的一个参数,他只想更新后面这个,呃。一些参数,那么它就会我就会设置这个free等于false,就是如果说你的这个参数是true的话,它就会将这个预训练的模型啊。的里面的这个梯度全部设置为false,那么它在反向传播的时候就不会去更新它,而是会去更新这一块。啊,这个model name也是一样的,呃,He size就是说当你最后返回,返回出来,这个是非常重要的,因为你之后,呃,你这个N n.Li啊,它这个模型的大小到底是呃。呃,这个size到底是多少,这里要设计好,那怎么知道这个size呢?其实很多地方都会有写,比方说我这里用的这个吧,它这个XNE它就会提到啊,他最后返回的是一个768维的一个,呃呃,一个东西七百68维,那你就写上768,但我这里默认是768,其实你这里是可以传入的。
17:13
你就可以入1024啊,768等等都可以。然后number of classes,我这里默认是二,就是个二分类问题,但其实我这是个七分类问题,因为它这里有七个类别,所以说呃,在这里。嗯,后面的话就会传出个七啊,就是传入个嫩。那么这个棱的长度其实就是七。好,那么最后下面就是主要这一块。呃,Auto auto model,呃呃,Model它会它会自动去加载,你这个根据你这个model内去自动加载,你到底有没有什么模型,因为我这里是用的XNE吗。他就会去,呃,给我一个XL model,那其实它这个auto model等价于什么呢?等价于在这里写上。呃,稍等等价于在这里写上。
18:02
因为它这个大小写我不我记得不是很清楚X。啊,等价于在这写上XL model其实等价的,因为它会自动去啊,嗯,变化。然后呢,你这里有一个output hidden states等于true,因为它这里那可以指呃,它这个API写的很清楚,它这里有个返回值对吧,反正是这里有last hidden states,还有像这个东西,当然我需要的是hidden states隐藏的变量,那么它这个地方你要获取的话,它必须要设置output hidden state等于true啊,所以说我在这里要设置了。然后呢,返回的类型是torch的,呃类型。好,那么这个模型就定义完了啊,Self的self点等于啊这一块后面呢,呃,因为我这是一个分类问题嘛,所以我获得它的隐藏变量之后呢,我要把这个隐藏变量啊,不管你是通过一个比方说LSTM啊CN,然后再接一个呃,Linear,或者是你直接像我这样接一个linear做一个分类啊,也是一样的,那么你就要首先。
19:14
啊,你会获得一个output对吧,这个output它里面就会有这些东西。然后我需要的什么呢?我需要是hidden states,所以我就用什么的,我就用outputs.hidden states去获取它,然后呢,我这里做的一个呃东西,就是说把这个呃,Output。我把他的这个,呃,最后呃。就是负1234给它拼接起来,那么啊,作为一个hidden space,然后呢,我要的是第零个单词的space。首先它拼接之后,它的he s变成四倍了,因为它是呃后面四个都拼接起来了嘛,所以它变成四倍了,呃四倍中后呢,这个零,为什么我要取零呢?因为呃之类的,他们第一个单词基本上都是什么。
20:02
基本上其实都是cos,比方说cos,然后I啊什么什么,然后SE之类的这样,所以我要的是它这个第一单词啊,第一个单词,所以说呃,就把这个零取出来就可以了,那么它的维度就少了一位,就只有by hidden dimension以四,然后呢,我要传入这个FC,因此我现在其实就知道这个的维度是多少,就是乘四,然后最后输出的维度什么呢?Number of classes就可以了。要。啊,把这船那么啊返回出来一个log就可以了。因此这个预训练的模型啊就做完了。呃,这个模型定义完之后呢,然后下面就是损失函数,损失函数和优化器,优化器我这里用的是transformers的IW。或者你直接用呃。torch.op.I也是可以的,呃,感觉其实优化器嗯也不是,也没有那么的重要,因为我看很多论文啊,虽然很非常多的论文他们都呃提出来各种各样的优化器。
21:10
但是好像大家用的还是I比较多啊,这个其实也不是那么重要了,其实就用IW吧,然后这个model.paras传进来,然后learning rate,还有呃,DK就是learning rate它的。呃,衰减系数。呃,最后就开始训练就行了,好,那么训练的时候我要传入model,然后传入这个损失函数,传入优化器啊,传入纯load,传入啊validation load,还有它的IPO。因为我是在呃训练的过程当中去穿插的进行一个验证,所以说这里呃validation也要传进来。那么在这个函数里面,Train和validation,首先这个model它要to device。这个我是设置了一个全局变量在这里。
22:03
后面就开始练了。首先然后。然后你打印,现在已经到第几个I了。然后去,呃,把这些数据都放到device上。然后再传入model。啊,这里model传入的参数啊,我这里讲一下inputds attention mask token typebd,这都是,呃,T类模型,像X net等等他们都需要的。呃,这个地方我就不讲了吧,其实这个都没什么好说的了,因为我在前面这个视频已经讲过了,就是X net这个地方我已经讲过了。嗯,好,那我们下面继续看,然后返回一个log,然后把这个呃,Log和这个LABEL2个人去做一个损失函数,然后打印一下这个损失函数。后面三件套,然后下面去做一个呃验证,验证的时候把这个模型传进来,然后把这个optimizer,还有呃这个也传进来,呃验证的时候首先进入验证模式,然后下面也是一样的,其实就是和X那个视频讲的一样,大家去看一下,这里我就不多赘述了,也就是说我先把我要记录一下它的最好的分数,然后呢,呃,我去保保存一下当前,如果说当前这个最好的分数被刷新了。
23:19
那我就去保存这个模型,然后我自己写了一个,写了一个函数,这里保存模型,保存模型同时呢,我其实还保存了这个optimize。我把优化器保存了啊,然后打印一下model has saved。啊,那么整个这个就是呃,训练和验证的部分。然后下面呢。呃,训练和验证完了之后呢。把它注释掉。就去开始做,呃,就是去开始做测试了,测试的话就是。对于这个test。那test data也是一样的,首先process data对吧,后面的话,然后这个都是一样的,这个。都是一模一样的,然后去test,呃,Test过程其实也和呃,Validation也很像,首先你去加载这个模型啊。
24:07
加载这个模型,把这个模型放到CPU上,然后再去load load完了之后再去to device。因为这个地方呃,验证的话,它又不需要去优化,所以说根本不需要用optimize,因此我就呃没有去获取optimize。然后开始测试啊,测试的话也是一样的,这里然后后面就是对数据的一些处理了啊,这个就没什么好讲的,这个就是对数据处理,这就已经不算是模型的呃一些部分了,这样大家自己看一下就可以了。好,那么这个就是一个呃,完整非常完整的一个翻tu的教程,包括这个模型,就是当你用了这个呃,Hoggey face的transfers的预训练模型之后,你怎么去保存,其实当时这个问题也是我困扰了我很久,因为我当时认为,呃,我认为就是我自己自是制定了一个模型,然后这个里面是别人的一个模型,我觉得应该不能像torch.safe,这样非常简单的去保存,但是其实是是可以的,因为how face transform的预训列模型,它也是用torch实现的,所以说你这里直接用C,它这个地方也是直接保存了,呃,我一开始还以为我先单独去保存这个,然后再单独保存我自己的,呃里面的一个呃拍拓式的模型。
25:19
但是其实不用就只需要啊。呃,直接保存就可以了,然后漏也是,呃,加载也也是一样的,好,那么这个就是一个非常完整的一个啊。翻,然后运,运用在自己下游任务的一个方法。包括这里,大家后面想去改成呃,LSTM啊等等,你也知道怎么改了,因为你只要知道数据的维度,其实一切都好,一切都好说。那么这个呃,首先第一呃第一个部分就讲完了,就是说用呃。哈工大的一个预训练模型,那么第二个部分就是说我我如果是用的一个,呃,我是第二个模型。就是我在这里用for sequence classification,这个其实和我之前讲的这个XLNE非常像,因为我当时用的也是XL。
26:07
For classification这里,但是呢,我这里还是包在了我自己的一个模型里面,呃。这样子。呃,其实其他地方都是一样的,我就主要是给大家介绍一下它这个呃参数就是大家如果呃用的时候其实都不知道它会返回什么东西,你就仔细去看这个API。Burnt。然后for classification。那它这里会问什么呢?它它可以传入呃。它可以传入label。啊,如果你传入label的话,它就会返回这个loss,那如果你不传入label,呃,它也会返回,它也它也会返回这个logs,因此我这里就啊没有传入,直接让它返回一个逻辑,我自己来呃去计算损失函数,我没有让它去呃自动返回损失函数。
27:07
这里是一样的。啊,后面是一样的,其实就没什么多说了,最主要还是这个吧,这个怎么去做一个预训练。呃呃,不是怎么是使用一个预训练,然后完整的去。用在自己的下游任务上。嗯。大概就这么多吧,好吧,那么本期视频就到这儿,谢谢大家。
我来说两句