七月在线公开课笔记-二-
七月在线公开课笔记(二)
【七月】NLP高端就业小班10期 - P4:4.文本相似度计算与文本匹配模型_ev - 不看兵法的数据分析师 - BV1BC4y1C7E5
OK今天的话我们要给大家讲这个文本相似度啊,文本相似度,那在之前的一些啊,包括一些录播课里面啊,我们已经简单的去了解了,包括像啊文本分类对吧,那今天的话我们还会去作战的一个NLP当中。
会经常应用应用到的这样的一个模型啊,就是咱们的这个文本相似度的一个计算,那当然我们今天的这个课程呢,也会带着大家一起从这个理论层面,再到代码层面,一起去实现这个所谓文本相似度的一个计算。
好吧好,那我们就先来看一下,我们今天会讲的三部分内容啊,第一部分内容呢我们会先给大家简单介绍一下,到底什么是这个文本相似度,包括这个文本相似度啊,它有什么样的一个作用,那对于文本分类来说。
那他的这个作用大家都很清楚嘛对吧,它的应用场景也比较广泛,那对于文本相似度来说,它又有什么样的一个作用呢,它可以应用在什么样的一个场景下呢,好这是我们今天要第一块讲的内容,第二块的话我们会来看一下啊。
基于这个表示学习的一个,文本相似度的一个计算,也就是说文本像素计算啊,其实有两种方式,第一种的话是基于咱们这个表示学习,第二种的话是基于这样的一个匹配模型,匹配模型好,那匹配模型和这个表示学习模型。
它又有什么样的一个区别呢,这也是待会我们会详细说的点,好吧好,这是我们今天主要要讲的这个三块内容啊。
那我们接下来就进入到我们的第一部分内容啊,关于这个文本相似度好。
那这边开始之前呢,我也简单说一下啊,我们的这个课程上的这个代码呢,都会在这个啊GITHUB地址里啊,好给大家简单看一下,那啊大家上课之后,如果大家需要看这个代码,那就来到这边来到这个页面上。
然后如果你需要去获取这个代码该怎么去拿呢,啊有两种方法,第一种方法,你可以点击一下这里这个绿色的这个按钮啊,因为这里为什么要说这个事呢,因为有些同学可能还是啊正在大学期间啊。
可能对GITHUB这一块用的还不太熟练,所以这边简单说一下好吧,那就点击这边这个code啊,然后呢你可以使用这个git命令把它clone下来,你也可以呢在这边直接把这个下载下来,那下载下来的话。
它就是这样的一个压缩包好吧,然后解压缩之后呢,就可以看到这个代码了,好两种形式好吧,一个是使用这个git命令,一种是使用这个下载压缩包的形式,当然大家最好是使用这个git命令啊,那我这边代码更新的话。
大家如果使用git克隆下来的话,你也方便去更新你的代码好不好,这是啊关于代码这一块的一些东西啊,好提前说一下,OK那我们就接下来就来看这个文本相似度啊,那文本相似度说白了其实就是计算两个文本。
它的一个相似度对吧,就是字面意思啊,就是计算两条文本它的一个相似度,它的文本分类它最大的一个点在于是什么呢,文本分类我们是针对什么,我们针对的是单条文本,但是对于文本相似度来说。
假设我们要去计算A和B的一个相似度,那我们是需要两条文本的对吧,这是它最大的一个点啊,在我们训练阶段,它最大的一个点分类是针对于一条文本,我们的这个相似度啊,针对的是两条文本。
那待会大家也可以从模型的结构层面看到,如何去针对于两条文本去设计,这样的一个模型结构,那知道了什么是文本相似度之后呢,我们需要考虑一下,就这个文本相似度啊,它到底是有什么样的一个应用场景。
它其实文本相似度啊,和文本分类一样,它的这个应用场景是非常多的啊,例如咱们的这个文本的一个检索信息检索,还有咱们的这个问答好,我们先说先说这个检索啊,检索这个相信各位同学都非常好理解啊。
例如咱们的一个搜索引擎对吧,那你搜索引擎你输入了一个问题,那咱们这个搜索引擎要把这个答案进行返回,那通常呢把用户输入了一个这样的一个,question对吧,那它会返回很多的这样的一个啊document。
或者说他输入了一个query,我们要返回很多这样的一个document,可能有第一第二第三好,那如何去对这个D1D2D三进行一个排序呢,因为我们显示在页面上,那我们就需要对它进行一个排序对吧。
那其中一种方式啊,我们就可以根据我们的这个相似度来进行排序,那相似度越靠前的,我就把它往前面排,那假如A11它的相似度很高对吧,那我就把它排在第一位,第三它的相似度可能是第二,那我就把它排在第二位。
最后这个排在第三位,这是检索的这样的一个场景啊,那包括搜索引擎,它其实也会应用到这样的一个文本相似度计算,当然啊一些做的比较好的一些搜索引擎,除了去考虑咱们的这个文本相似度以外。
还会去考虑一些额外的一些特征,举个简单的例子啊,假设你用的这个是百度的一个搜索,那百度搜索的话,你可能会遇到很多的一些广告对吧,那它其实是会对针对于这些广告,也是采用一些加权的一些形式。
把这些广告呢排到前面去,其次啊啊其次的一些排序的一些结果,甚至会涉及到一些learning to rank,一些类似于推荐的这样的一些模式,把你感兴趣的内容往前面排,它也是有的,好不好,这是一个检索啊。
让我们再说一下问答,问答和检索呢其实是比较接近的啊,他的思路是比较接近的,举个例子啊,对于问答来说呢,首先呢我们需要有一个这样的一个,QA的一个库,也就是说我们有这样的一个数据库。
我的数据库里面存了很多的这样的一个QA对啊,QA对,这个时候呢用户输入输入了一个问题,好用户输入一个问题,那我们的这个可能有Q1Q二一直到QN,咱们的answer也是啊,从一一直到answer n。
这个时候呢用户输入进来的这个question,会和我们库里的这些question,去做一个相似度的一个计算,哎,这个时候可能算出来,我Q2它的相似度是最高的,那么我们就把Q2对应的answer2。
进行一个返回,进行一个返回,这就是一个非常简单的一个问答系统啊,问答系统,所以说可以看到啊,这个文本相似度的一个应用场景啊,实际上是非常多的非常多的,这边再说一个简单的一个场景啊,那这个简单的场景。
就是咱们的一个文本的一个聚类,假设你现在有非常多的这样的一个文本,你想把这个同义句给聚在一起,怎么做呢,这个时候您实际上也可以采用这个文本相似度,的一个方式来进行计算,那我们去两两进行相似度一个计算。
最后把相似度比较接近的就把它聚在一起,对吧好,这是第三个应用场景啊,聚类聚类,那目前文本相似度的主要是有两种方式啊,就基于这样的一个表示学习的,就是看咱们这个大纲里说的一个表示学习,还有一种呢。
就是基于咱们这的一个双塔模式的啊,双塔模式的,当然啊,现在其实对于双塔模式这样的一个结构来说呢,也会存在于一些啊单塔的一个结构,那具体是什么样子呢,待会我们来详细说好吧,推荐的双塔用于白领计算好。
这就是我们的一个文本相似度,它的一个应用场景,应用场景,好那咱们的这个文本相似度,通常啊不管你是用什么样的一个方式来做,不管是说这里的一个表示学习也好,还是这里这样的一个双塔结构的一个模型也好。
关键的有一个点啊,在我们去计算相似度的时候,我们是不是应该去确认一个这样的一个,度量的一个标准,我们到底应该是采用什么样的一个距离,来判断两条文本它的一个相思路呢,哎例如我们这里有很多距离对吧。
我们有欧式距离哎,有曼哈顿距离,有海明距离,有很多的一些距离都可以用来度量,两条两个向量它的一个距离对吧,那我们会去使用什么样的一个方式呢,那对于计算文本相似度来说啊,我们通常会采用这个余弦相似度。
那为什么都是建议采用这样的一个,余弦相似度呢,最主要的原因在于咱们的这个余弦相似度啊,它的一个值域在-11之间,那基本上啊对于文本来说,我们计算出来的这个相似度,大部分都是01之间。
很少会出现一个负数啊,很少会出现一个负数,那余弦相似度它又是怎么计算的呢,我们可以看一下下面这个公式啊,如果我们要求A这个向量和B这个向量,它的一个余弦相似度,实际上就是A向量乘以B向量。
再除以A的模和B的模,这就是两个向量它的一个余弦相似度啊,余弦相似度好,那了解了我们接下来要计算的这个相似度,用什么样的一个度量方式去计算之后呢,那接下来我们就可以进入到。
我们后面的一个内容了,好接下来我们来到我们第二块啊。
关于这个表示学习的一个相似度,那什么是一个表示学习的一个相似度的计算呢,其实表示学习啊,意思就是说我们需要通过一个模型,通过一个模型得到句子的embedding,这里大家需要注意一下啊。
是通过模型得到我们句子的embedding,那得到句子的embedding之后诶,那我们就可以把我们的这个embedding,根据我们这里提到的这个余弦相似度,来进行一个计算。
就可以最终得到我们想要的一个结果对吧,举个简单的例子,假设呢我们现在这里有A这条文本,B这条文本好,首先呢我们这里有一个这样的一个模型啊,我们先不考虑它到底是什么样子的一个模型啊。
我们先不考虑它是什么样的模型,总之我们这里有两条文本A和B,我们把这两条文本给到了我们的模型,我们的模型呢生成了两个向量,一个是VA,一个是vb,OK有了两个向量之后。
那我们是不是就可以去计算我们的余弦相似度,对吧,那就VA乘以为D除以V的模vb,怎么这样子的话,我们就可以计算出我们的文本相似度了对吧,OK那知道了这个流程,那接下来就有一点比较关键了。
这里这个模型该怎么得到呢,好这就是我们需要关注的一个点啊,关注的点那在我们之前的这个啊,包括录播课里面啊,我们实际上已经讲过这个word to vector对吧。
我们已经讲过这个word to vector好,那既然如此,我们是不是可以考虑采用word to vector的一个,形式呢,对吧,OK啊,那我们就采用这样的一个形式嘛,假设啊我现在A这个句子。
A这个句子它里面可能包含了很多的一个词,可能有A1A2A3A4好,那接下来呢,我们就可以采用我们这样的一个海量的数据,采用word to vector的一个形式,得到这样的一个模型。
word to vector的一个模型对吧,那有了这样的一个word to vector模型之后呢,当用户输入了这句话好,我们把就把这句话啊进行一个分词分词,这边的话就是分成了四个词啊,分成了四个词。
那有了这四个词之后呢,我们会把这四个词啊经过我们的word vector,这样的话,我们是不是就能得到这四个词对应的一个,embedding对吧,那我们这里就得到了VA1VA2。
VA3和我们的VA4对吧,同理同理,那对于B这个句子来说,我们也可以把它进行一个分词,再转换成对应的一个向量,对应对应的一个向量,这个时候我们是做了什么呢,我们是把句子分了词,转换成一个向量的形式。
但是但是我们这里的这个向量啊,我们可以看一下,这里是四个词,假设我们的向量它的维度是64,假设维度是64啊,那我们这边得到的实际上就是一个,4×64的这样的一个张量,或者说矩阵对吧。
我们得到的是这样的一个维度的一个数据,那对于这边来说,我们得到的就是啊啊假设我们的N是六好吧,我这里写个六好了,写个六好,那我们这边得到的这样的一个,就是一个6×64的这样的一个,矩阵或张量好。
那现在就有问题了,这两个矩阵我们该怎么去计算它的相似度呢,哎刚才我们说我们是两个向量对吧,两个向量才能去计算它的余弦相似度,那这个时候我们得到的这个内容到底是什么呢。
我们这里得到的这个矩阵到底是什么东西,有同学知道吗,或者说接下来我想去算这个余弦相似度,我该怎么做呢,来有同学知道吗,好我这边那我就解释了啊,我来解释好了,首先呢我们这边得到的实际上是什么。
是每一个词它对应的一个词的embedding,但是我们这里这个余弦相似的公式,我们使用的这个是什么,是使用的是句子的embedding,但我们这里是啥,我们这里是词的embedding对吧,假设啊。
假设我们最终得到的是一个一维的,也就是说它只是单纯的一个向量,它不是一个矩阵的形式,加上他这边得到了一个64位的一个向量,诶这边也得到了一个64位的一个向量,那这个时候我们是不是就可以进行一个计算。
对吧好,这里有一位同学说哎,是不是可以采用这个平均池化层嗯,差不多啊,思路差不多,OK那既然如此啊,我们这里得到的是一个词的embedding,那我们就应该想办法把它变成一个什么句子的。
一个embedding嘛,对吧,我们要从词的embedding转换到句子的embedding,那怎么转呢,其中一种方法啊,就是这里这位同学说的,我们可以采用一个平均池化层,平均池化层好,我们来看一下啊。
那通常呢我们要把我们的这个embedding啊,从词从咱们的这个词转换成这样的一个句子,从word转换成这样的一个sentence对吧,那最常用的一个方式呢,其实就是什么加权平均,加权平均。
也就是说我的这个vs实际上是等于,加上这是第一个词啊,这是第一个词它的一个embedding,这是第一个词的embedding对应的一个权重好,那假如我们有N个词,那接下来就是阿尔法二乘以W。
一直加加到我们的阿尔法三乘以我们的啊,这是N阿尔法N到我们的WN,这样子呢,我们就等于给我们每一个词加了一个权重对吧,最后再求和再求和,这就是咱们的加权平均的一个过程啊。
假如我们的阿尔法一一等于我们的阿尔法二,等于我们的阿尔法N,就每一个词啊它都是相等的,并且每一个词它的一个权重都是相等的,并且等于什么,等于N分之一的话,这是什么,这实际上就是去求平均嘛对吧。
就是这位同学说的,做了一个类似于平均池化层的处理对吧,好那这个时候也有同学会说了,哎那我这里这个权重,我这个阿尔法到底该怎么去求对吧,好这里呢就需要去做一些小的一些处理了,例如啊我们呢在分词之后呢。
我们可以去对每一个词,它的一个这个啊词性做一个标注,诶假设我这是一个名词,哎我这里是一个动词诶,那我就可能给它一个稍微大一点点的一个权重,那可能后面有些词诶它是一个副词对吧。
我就给他一个稍微小一点点的一个权重,以这样的一个形式啊,来确认它的一个阿尔法到底是多大,当然还有一些其他的一些方式,例如你可以采用这个TFIDF,你可以采用这个text rank去计算每一个词。
它的一个权重,再把这个权重啊,来作为他的这样的一个阿尔法的一个值,也是可以的啊,也是可以的,当然啊如果大家觉得这些啊有点麻烦对吧,没关系,我们就采用最简单的一个方式啊。
就采用这样的一个平均值化的一个形式,就直接取一个均值啊,直接取个均值,这样子的话,我们就可以把我们的这个词的一个白embedding,转换成一个句子的一个embedding,好我们回到刚才这个例子啊。
回到刚才这个例子,那对于A这个句子来说,我们是4×64的这样的一个矩阵对吧,OK那接下来呢我就对它求一个均值,求完均值之后呢,实际上就是让我们的这个V1加上我们的VA2,加上VA3,加上VA4。
最后再除以四对吧,所以这样呢我们就可以得到一个一维的,一个这样的一个向量对吧,得到一个向量,那对于B来说也是一样啊,我们把每一个词的embedding进行一个相加,进行一个相加,相加完之后呢。
再除以我们的六个词,也就是除以六对吧,就可以得到我们最终啊这64位的一个向量,接下来呢我们就可以把这两个向量拿去计算,我们的什么余弦相似度,余弦相似度啊,这就是我们整个表示学习的一个过程啊。
表示学习的一个过程,好再简单,我们梳理一遍啊,首先拿到一个句子,拿到一个sentence,我们要把sentence转换成什么,转换成词,再把每一个词转换成我们的什么embedding。
转换成我们的词的一个向量,再从这个词的一个向量,转换成我们这个句子的一个向量,句子的一个向量,那句子的向量怎么做呢,是进行我们的这样的一个啊,啊这里写VWVWI好,是进行我们的什么加权平均对吧。
这就是我们哦对还有一步啊,下一步就可以去计算我们的什么相似度了,就算我们的余弦相似度,计算我们预弦相似度,这就是整个表示学习的一个过程啊,好这个时候呢可能也有同学会说了,那有没有其他的一个方式。
我们这里只是一个采用want to vector的一个形式,对吧,有没有其他的一个形式呢,那其他形式怎么做呢,其他形式啊,实际上就是把咱们刚才说的这里这个模型啊,进行一个优化,进行一个修改。
我们从之前的word vector对吧,进行一个升级,升级成其他的一个模型,其他的一些语言模型,Language model,Language model,对其中一种方法就是BT啊。
其中一种方法就是BT,但是这个我们今天暂时不讲啊,今天暂时不讲,我们会放到后面来讲,因为BT这个模型来说相对会稍微复杂一点点啊,好这里我们稍微停一下啊,对于表示学习的这个整个流程。
各位同学有没有什么疑问,对就是给每一个词它一个权重,然后相加相加,就是这个意思啊,简单一点的话,那你就把这个权重啊,把它变成一个N分之一,这样的话实际上就是什么,就是求个均值嘛,求均值。
求均值就是咱们刚才这位同学说的平均值化层,好,各位同学还有疑问吗,这里,还有疑问吗,各位同学,啊这里也简单说一下啊,就咱们是直播课嘛,直播课的话,大家如果有什么疑问就及时提出来好吧。
我们尽量就是在这个课程当中啊,帮大家把所有的问题都给解决,大家不要带着疑问,带着疑问呢,那接下来我们直播的一些内容啊,你可能就会听不太明白好吧,因为每一环都是相辅相成的啊,前面的内容你听不明白。
后面的内容你可能就更听不明白了好吧,所以大家有疑问啊,一定要提出来,一定要提出来,我们就及时解决,及时解决,好那我们就继续往下啊,继续往下,那刚才说了啊,我们刚才使用的模型是这样的。
一个word vector的一个模型对吧,word vector一个模型,那我们把这个word max这个模型啊做一点点升级,我们要把这个word vector升级成什么呢,升级成另外一个语言模型。
Language model,或者说叫做预训练的语言模型,Patri language model,Portrait language model,预训练语言模型。
那我们今天要给大家介绍的这个语言模型呢,叫做arm,有些同学可能会比较熟悉啊,像BT这样的一个语言模型,那这样的一个语言模型呢,其中的一些结构啊会稍微复杂一点点,我们需要放到后面去讲。
那今天呢我们会给大家讲另外一个比较重要的,预训练的语言模型,而这个模型,那这个模型呢它是基于这样的一个LSTM的,那LSTM的话,相信各位同学在之前的一个录播课当中,已经了解过了对吧,已经学过了。
那我们今天的话就来详细看一下,这个基于LSTM得到的这样的一个语言模型,预训练,语言模型它到底是什么样子的啊,好它的一个结构整体来看其实并不复杂啊,我们可以看一下下面这个图,那arm这个模型呢。
实际上采用的就是一个双层双向的LSTM,注意啊,它是一个双层的,并且是双向的,并且是一个双向的,那他这个双向是什么意思呢,对于普通的一个RN的一个模型来说,咱们的一个结构是这个样子的对吧。
哎我们这里进行一个输入,第二个时间点,输入第三个时间点进行一个输入,它是一个从左到右的一个过程,那对于RN站的一个结构的一个模型来说啊,实际上我们还可以进行一个,从右到左的一个结构。
诶它可能是这个样子的,就从右到左,或者说从后往前的这样的一个结构,那这样的话,我们的模型除了可以看到我们的前文以外,我们还可以看到我们的后文对吧,那对于我们的第一种结构。
从前往后那模型其实这个能看到的是什么,看到的是前文的一些信息,那对于我们的第二种结构来说,那模型看到的实际上就是我们的后文的一些内,容对吧,那既然如此,我们把这两者结合一下对吧,结合一下,那结合之后呢。
我们当前的这个时间节点,就既能看到我们之前的一些内容,又能看到我们这之后的一些内容,也就是说我们能看到什么,能看到我们的上下文啊,上下文好,这就是一个双向的结构,双向的RN结构,那对于这个模型来说。
它是把RN这样的一个结构,换成了这个LSTMLSTM好,我们来看一下它的输入呢,就是我们对应的每一个词的这样的一个,Embedded,然后呢给到我们的一个前线的双层的,这是两层啊。
两层的LST那对于这边来说也是一样啊,它是一个反向的LISTM当然也是两层的,最后我们会把这个两层的,它对应位置的一个输出值会把它拼在一起,拼在一起好,我们可以看一下啊,啊这是一个前线的。
我们用F来表示啊,这是第一个位置,那啊这边的话我们也用这个B来表示,这是B1,所以说对于第一个embedding,它对应的就是前向的F1和反向的这个BE,它组成的一个结果组成,在他最终这里这个T1啊。
是咱们的F1和我们的B1进行了一个拼接,翻到了T1这个位置啊,那这个位置的一个输出值,代表的就是我们的这个embedding,经过了我们的模型提取了一定的一些特征之后。
得到的对应的一个词的embedding,假设这里是词是W1W1,那这里这个embedding,实际上是经过了我们这样的一个embedding matrix。
也就是类似于咱们的这个word to vector的,那样的一个矩阵,好得到了我们这里这个1111,经过我们的双向LSTM,分别得到我们的F1和B1,再把这两者进行一个拼接,得到我们的T1。
那T1表示的是什么呢,表示的就是我们W1这个词它的一个输出值,你也可以理解为W1对应的一个什么词的,Embedding,一个向量,一个向量好,这就是整个这样的一个ERO的一个模型,但是我刚刚有说啊。
ERO这个模型它是一个什么,它是一个预训练的模型,预训练模型又是什么意思呢,也就是说这个模型啊我们再去使用它的时候,它的一个权重啊并不是随机初始化的,而是它在海量的这样的一个文本数据上。
已经进行了一个训练,也就是说它自身已经具备了一定的收敛的,比较好的一些权重,那他这个群众是怎么得到的呢,或者说他这个预训练是怎么做的呢,其实很简单啊,举个简单的例子啊,假设这是我们的一个,那正常来说啊。
我们实际上是会有很多的这样的一些,文本数据的对吧,假设我这里有一条文本数据,哎我就以这条数据为例啊,AO采用的是双层的双向LST,那我就可以把这句话啊输入给我们的耳膜,我把这句话作为输入给到我们的耳膜。
然后呢,我们让我们arm这个模型来预测一下这句话,它的下一个字是什么,下一个字是什么,当然这个过程肯定是一个字一个字进行预测的,举个例子,假设我现在输入的是ERO采用的啊,我们就输前面这一段这里啊采用。
然后呢我们要让我们的ERO,也就是LSTM,它最后的一个位置输出D这个字输出的这个字,那输出完之后呢,我们再把D这个字啊再给到我们的耳膜,也就是给到我们这个双向的LSTM,再让他把士这个字进行一个输出。
哎这个时候各位同学可能就发现了啊,那这个过程它实际上是一个什么,是一个无监督的一个过程,只要你有文本,那你就可以来进行这样的一个训练对吧,有文本你就能训练,那它就是在海量的一个文本的基础上。
去做了这样的一个预训练的一个任务,那训练完成之后呢,它就会自身已经具备了一些权重了对吧,那当你去使用arm的时候,你只需要把这个权重给加载进来,加载进来,这个时候你就可以在这个已经训练过的一个。
模型的一个基础上再去做一些所谓的什么微调,就可以去适应你自己的一个任务,那对于我们的这个文本相似度来说啊,其实就是可以直接使用它的一个权重,那只要我们有了这样的一个权重。
那我们最终这里实际上就可以得到每一个词,它对应的一个embedding对吧,也就是这里这个所谓的T,那我们在对每一个T去求,刚才这里说的这样的一个加权平均的一个值,就可以得到我们最终的一个什么句子的。
embedding对吧,所以各位同学可以发现一个问题啊,我们刚才说我们的那个模型使用的是word vector,Word vector,这里换成了这样的一个,不管你使用什么样的一个模型啊。
我们最终的这个整个这样的一个流程啊,它是不会变的,它是不会变的,唯一改变的就是我们这里这个模型对吧,唯一改变的就是这个模型,包括我们最终生成的这个句子的一个embedding,对吧。
你这个句向量该怎么生成,哎也是和我们这里说的这个方式啊也是一样的,毕竟我们最终这里得到的也是一个一个的词的,一个embedding对吧,词的embedding好,这就是我们的这个ERO这个模型。
这个模型好,接下来呢我们再来看一下,如何去对我们的这个啊前向语言模型,和我们的反向语言模型去进行一个建模啊,好我们来看一下啊,这里呢假设啊我们现在有这样的一个句子,这个句子呢有N个词。
也就是说从T1到tn,那我们要对这个句子去进行建模的话,实际上就是求每一个词它的一个联合概率分布,也就是咱们的P从T1到TN对吧,最终我们会得到这样的一个内存的一个公式,为什么是这样的一个形式呢。
其实啊这个公式是怎么得到的呢,我们来看一下啊,那对于PT1到TN这N个词来说,那如何去得到这样的一个概率分布呢,实际上假如假如每一个词它是相互独立的,假如每一个词它是相互独立的,那它实际上就等于PT1。
一直乘乘到PTN对吧,但对于我们的文本来说,每一个词肯定不可能是相互独立的,对吧啊,例如像啊啊吃饭诶,这两个字可能会大概率在一起诶,蝙蝠这两个字可能大概率会在一起,你不可能说吃福诶,那这是啥东西对吧。
所以说词和词之间啊,或者说字和字之间它不可能是相互独立的好,那既然它不是相互独立的,那这个肯定是不对的对吧,那我们该怎么去求这个概率分布呢,那这个时候我们就可以这么求啊,首先呢我们先看前面的一些词好。
这时候实际上就等于PT1乘以P这个啊,T2给本T1好,那这两者进行相乘之后呢,我们得到的是什么,我们是不是得到的是PTTR对吧,我们得到的是这个东西,得到的这个东西,那我们可以继续再往下面乘啊。
那我们可以再乘这个P这个啊,这个这个T3T1T二好,那我们再把这一项和这一项进行一个相乘,那我们拿到的是什么,是不是PT1T二T三,所以啊只要我们一直沉下去,一直沉下去,那我们乘到最后一项对吧。
我们实际上整个的一个联合概率分布啊,就是这样的一个公式,就是这样的一个公式好,这是我们的一个前向语言模型,那对于反向语言模型来说其实就是一样的啊,我们就把我们的这个啊,从T1换成了咱们的一个TN对吧。
就重复从后往前来啊,从后往前来,那对于一个双向的语言模型,我们该怎么做呢,理论上来说,我们应该把这两者就前向和反向进行一个什么,进行个相乘对吧,进行一个相乘,但是嗯各位同学可以考虑一下啊,理论上来说。
这里这样的一个概率值,其实计算出来已经非常小了,这里这个概率值通常会怎么去求呢,你可以去采用一个词平的一个形式去求解,但是求解出来大家可以发现啊,这个概率值已经非常小了,你再采用一个相乘的一个形式的话。
那这个值就会变得更小了,所以呢我们通常会取一个log,取个log,取完log之后呢,我们就可以把我们相乘这个过程,变成一个相加的一个过程,相加的一个过程啊,然后我们这个累乘啊啊。
也变成了这样的一个累加累加啊,这就是一个双向语言模型啊,双向语言模型,OK那理解了这个建模的一个思路之后,我们再来回到我们的耳膜啊,回到我们的耳膜,那arm这样的一个模型呢。
其实啊他想去得到每一个词的这样的一个,向量表示的一个方式啊,是有很多种的,有很多种,那第一种形式呢,就是去取我们第二层的LISTM的输出,也就是咱们刚才说的,我我直接去取这里这个T,一直接去取这个T来。
作为我们最终的一个输出的一个结果,当然啊还有一些其他形式,也就是说我们给每一层它一个权重啊,去取它的一个加权的一个平均,什么意思呢,好我们还是回到这里啊,这里有我们的这个啊,有我们的一个一对吧。
这个是经过咱们这个embedding matrix,得到的这样的一个向量好,那对于第一层的ALSTM来说,我们实际上也可以得到这样的一个输出值,假设我用H来表示H1,它也可以得到这样的一个输出值。
那对于第二层来说,哎我们这里也可以得到HR,然后这里呢我们又得到了一个TT好,那这个时候我们就可以把这里这个T,这里这个H这是第一层的H,还有这里这个啊一进行一个加权加权,加权求和也是可以的啊。
也是可以的,哎,这个时候可能各位同学会发现诶,怎么好像和我们去求那个句子embedding,或者有点像对吧,所以说啊这些方式啊其实都是类似的,都是类似的,那这些呢其实都是他的一个paper当中说明的。
说明的好,这就是我们的这个arm啊,来得到这样的一个embedding的一个形式,那最终得到embedding之后呢,怎么做呢,就还是像刚才的对吧。
把它转换成一个句子的embedding就OK了就OK了,好这就是我们这个ERO这个模型,如何去得到它的一个embedding啊,得到embedding,好,这里呢啊也给大家提供了一下。
如何去使用这个ERO这个模型,当然啊你可以自己去做这样的一个预训练,是完全OK的,但是呢这边其实是有一些啊,别人已经训练好的这样的一个耳膜的一个模型,大家如果有足够的一个数据,你有足够的算力。
那你可以自己去预训练,这样的一个耳膜的一个模型,但是呢我还是建议大家去使用这样的一个,开源的啊,就足够了好吧,使用开源的就足够了,嗯这有点慢啊,有点慢好,大家都去这边来使用这样的一个开源的开源的。
包括他这里也提供了不同语言的一个版本,让大家来这里下载一个中文版就OK了啊,下载中文版,那这里下载下来呢是什么呢,是模型的权重,模型的权重,那如何去使用呢,使用的地方。
我们在这边已经给大家进行了一个说明啊,这里简单说一下啊,啊首先呢要有以下几步啊,第一步的话,肯定是要去安装我们的这个PYTORCH,Pytorch,这里也简单说一下啊,我们在之后的课程当中呢。
所涉及到的一些模型的一个开发啊,我们都会采用这个Python,只是个框架,好吧,都会使用Python是这个框架,然后呢我们需要去安装我们的这个康达康达,安装好之后呢,我们需要去安装一些这个啊。
刚才说的啊,这个arm这个我们要把这个arm这个啊,用这个PIP的一个形式啊去进行一个安装,或者说你直接把他的这个源码啊给克隆下来,也就是说大家只需要去执行这几行命令啊,这几行命令。
那它就会自动把我们的这个arm啊,安装在我们的这个本机里,本机里,当然啊大家记得要把这个权重下载下来,你如果不去进行一个下载,那你使用的这个权重就是随机初始化的,你随机初始化的一个权重。
那最终你得到的这个文本的一个embedding对吧,文本的embedding肯定就是效果不理想的啊,效果不理想的好,这边呢也有一个啊如何去使用啊。
如何去使用,大家到时候就自己来看,然后这边呢我给大家简单演示一下啊,啊其实在我们这个代码当中啊,我也把它放进来了。
大家如果不去,大家也不需要去clone它的这个代码啊,大家直接把我的这个克隆下来就OK了好吧。
或者说你去下载这个压缩包,那打开之后呢,大家会看到这里有这样的一个文件夹啊,会看到这里有这样的一个文件夹,好,那这样的话大家就可以去使用这样的一个模型。
大家需要注意一下啊,大家去下载这个权重之后啊,这边去进行一个权重的下载之后呢,需要把权重啊放在我这里。
这里有一个,有一个叫做pre model的一个目录啊,我会把这个模这个模型啊,这就是它的一个权重,还有一些他的一些配置文件啊,会把它放到这个文件夹下,大家去拉我的代码的时候,会发现没有这个文件夹啊。
你要去自己创建一个文件夹,然后把这个模型下载下来,放到这个文件夹下,然后呢你就可以去使用这个AO这个模型了,好我们来看一下啊,这边呢我已经就几行代码,就可以去调用这个ERO的一个模型,好我们简单看一下。
首先呢把arm这个进行一个import啊,然后呢我们导入一下结巴分词,好,第一步是我们的句子,然后把句子进行分词,然后初始化一下我们的AO这个模型。
然后调用一下他的这个sentence to arm这个方法,然后把我们的分词的结果传递进来,最终就可以得到我们这个句子的embedding,好,我们可以执行一下这个代码啊,好这边是一个分词的一个结果啊。
OK最终啊我们可以看到他输出了这样的一个啊,一个这样的一个张量啊,这样的一个张量诶,那为什么它输出的是这样的一个张量呢,因为他这里最终输出的是什么,是每一个词的一个embedding。
每一个词的embedding,我们还需要去求个均值好吧,要转换成句子的embedding的话。
你就需要去求均值好吧。
或者说你去做个加权平均都是可以的,就是咱们刚才说的好。
这就是如何使用咱们的这个ERO这个模型,来生成我们的embedding,好这里呢最后再额外说一点啊,额外说一点啊,对于这个sentence to oral这个方法来说啊。
它里面有一个参数叫做output layer,那这个参数是什么意思呢,我们来这边看一下啊,他有这样的一个解释,out the layer如果是零的话,它实际上输出的就是warning coder一个值。
也就是它经过咱们的这个embedding,matrix的一个结果,也就是这里这个图当中的这个黄色的,一一这样的一个结果啊,如果你输的是一一的话,它实际上得到的就是第一层的LISTM的。
一个hidden state,hidden layer的一个输出值啊,hidden layer的输出值如果是二,就是第二层的LSTM的一个,hidden layer的一个值,如果是一诶。
可以看到如果是一的话,输出的是这三层的一个什么一个均值啊,一个均值哦,对我刚才这里弄错了啊,啊这里这个T啊,实际上已经是我们第二层的LIS,TM的输出值啊,它表示的是第二层的输出值。
所以说这个T和这里这个hr是一样的,是一样的,只不过这里这个hr和T1唯一的区别在于,它没有进行一个拼接好吧,这里我纠正一下啊,最后如果你输的是二的话,他就会把这三层的一个结构啊都进行一个输出。
那如果三层结构都进行输出的话,你可能要做一些加权啊对吧,那你就自己按照你自己的想法来啊,就OK了,当然默认它是一啊,默认是一,也就是取决于三层的均值。
如果大家想更改的话,就是在这个方法当中啊,把这个参数进行一个修改就OK了,好吧好,这就是使用咱们的这个arm这个模型。
来生成我们的这个句子的embedding,好吧,生成句子的embedding好,这里我们再稍微停一下啊,看各位同学对于ERO这一块还有疑问吗,所以说最关键的点还是在于,如何去找到一个合适的一个模型对吧。
如何找到一个合适的一个模型,不管是咱们的word to vector,还是咱们那个AL,亦或者说我们今后会给大家讲的这样的一个BT,一个模型,其实都可以用来生成这样的一个句子,的一个embedding。
好,各位同学有疑问吗,看来是都没有欲望啊。
好OK那咱们就继续下面的内容了。
好吧好,那我们进入到我们的这个第三部分啊,关于这个匹配模型的一个相似度啊。
那刚才呢我们给大家聊的是,采用这个embedding的一个形式,也就是说哎我们把这个句子,提前转换成一个向量的形式,来计算这样的一个embedding,那接下来呢我们要给大家讲第二种方式啊。
就直接采用模型的形式,也就是说我这里有这样的一个模型,你直接把你的两个句子输入进来,比如咱们的A和咱们的BA输入给我们的模型,我们的模型呢最终输出一个值来决定,或者说来告诉你A和B这两个句子。
它到底是不是这样的一个同义句,或者说输出它最终的一个相似度,那对于这样的一个模型来说啊,我们通常会怎么做呢,实际上就是在我们的结尾啊,做了一个所谓的二分类,二分类,我要让它输出一个0~1之间的一个值。
01之间的一个值,那这个01之间的值越接近于一,就说明A和B这两个句子它越相似,大家也可以认为哎只要它大于0。5对吧,大于0。5,我就认为它是同一局,如果小于0。5,它就不是同一局。
就是以这样的一个思路啊来做好,那对于这样的一个模型来说,我们该怎么去构建它呢,好我们来看一下啊,啊文本相似度的一个模型的一个结构呢,通常都会采用一个孪生网络的一个结构,哎呦也就是咱们的一个双塔结构啊。
什么意思呢,就是说啊我们这个模型啊,它其实分成了两个部分,两个部分诶,这边一个部分,这边一个部分,这两个部分呢一边输入我们的A,一边输入我们的B两个模型,那这两个模型呢。
有时候呢他会去做这个所谓的权重共享,也就是说我们的模型一,它的一个权重和我们的模型二它是相等的,它是相等的,那有时候呢他也可以不相等,它也可以不相等,好当然啊这种结构他能做的一些事情呢。
更多是把我们的这边输出一个所谓的VA,这边输出一个所谓的vb,那最终再把这两个向量啊,去经过一些类似于我们的全连接层,或者说我们的SIGMOID的层,再来做一个所谓的二分类。
然后得到我们最终的这个零一之间的,这样的一个值,好,那除了这样的一个结构以外呢,其实啊我们可以还有一些其他的一些结构,还有什么结构呢,这就需要看到这里,我们的相似的模型可以分为两种情况,也就是这个图啊。
这个图也就是我们的第一种形式,第一种形式,那还有第二种形式啊,一个内交互的一个形式,那内交互的一个形式又是什么样子的呢,它也可以是一个这个啊双塔的一个结构,也就是说诶我这里输出之后。
我和我的M2这边的一些输出,做了一些这样的一些交互的一些处理,做了这样的一些交互处理,这个交互处理有什么呢,可能你去做了一些attention,然后可能你去做了一些磁化,你做了一些拼接。
总之你去做了一些相互的交互,然后呢,再给到我们接下来的一些其他的一些结构,例如LSTM,或者其他的一些类似的这样的一些结构,这是一个所谓的一个内交互的一个形式啊,甚至诶我这里这个模型就只有一个模型。
它不是一个双塔的一个结构,那我把A和B1起做了一个拼接对吧,做了一个拼接给到了我们的模型,我们的内部去做了一些交互,然后最后进行了一个二分类,这是我们的第二种结构,第二种结构内交互的一个形式。
当然啊也有外交互加内交互,也就是说哎我先去做一些内交互,我再去做一些外交互的形式,所以说啊文本相似的模型,它的一个结构是非常多的,非常多的,当然啊大家只需要注意到这里。
这个所谓的一个内交互和外交互就OK了,好吧,还有这里说的这样的一个双塔的一个结构啊,你可以让这两个模型它的一个权重不同,也可以相同,但是大部分的情况啊,双塔结构的模型它的权重都是相同的。
也就是说所谓的权重共享好吧,权重共享,而某英文模型的词典都是26字母啊,不是啊,不是英文的一个分词,它是怎么做的呢,第一种方式啊,它是就把这个分成一个一个的英文的一个词,分成英文的词,但是分成英文词。
它实际上也会存在于这个OV的问题,也会有OV的问题,OV什么意思呢,就是out of vocabulary,就是没有在我们的词典当中,所以说啊这个时候也会去做一些所谓的word piece。
这个东西我们之后放到BT再给大家讲好吧,所以说这里不是分字母啊,不是分字母,那对于中文来说,我们有两种方式,第一种方式呢我们可以分字分字,它的优势在于不容易出现OV的问题,因为常用的汉字也就那么多。
可能1万2万,基本上就覆盖了大部分的这个汉字了,就很难出现OV的问题了,第二种形式呢是分词,分词的话,你中文的词就非常多了,那这种时候的话就可以,就容易出现这个OV的问题,所以说啊分子和分子各有优缺。
各有优缺,还有一点啊,那对于分词来说,它能对语义表示的更合理一些,对于分子来说,那大家都知道吗,那对于中文来说,这个一个字它有很多个意思对吧,可能要和其他的字组合成一个词之后。
才能真正的知道他到底是什么意思,这就是字和词它各自的一个啊优缺好吧,好我也说明白吧,这位同学,OK行好,那我们回到我们的这个文本,相似度模型这一块啊,啊还是关键还是那两点啊,一个是内交互。
一个是外交互好吧,然后这边也大,还有这个双塔结构啊,大部分是这个所谓的权重共享,权重共享,权重共享的意思就是说模型结构是一样的,然后权重它是进行一个,你看着它好像是两个模型。
但实际上它结构和权重都是一样的,如果你的权重不共享,那它的结构也是一样的,只是说权重不一样,好吧好,然后呢,我这边呢有啊有这样的一篇博客啊,这个是我很久以前写的一篇博客啊,这边呢我整理了很多的一些这样。
文本相似度计算的一些小模型啊,然后这些啊这边有个表格,大家可以看一下啊,它的一个输入有字向量啊,有这个词向量,然后好像还有静态词向量和动态词向量,我觉得这个应该是在之前的那个录播课里面,讲过了对吧。
然后啊还有对应的一个论文的地址,那每一个模型呢,我这边也有博客去讲解,每个模型是什么样的一个结构,它是怎么用的,大家如果对这些模型想了解的更多,就一个一个来看好吧,一个一个来看,当然啊。
我们今天课堂上也会带着大家去看一些,比较重点的一些模型,好吧哦对还有一点啊,我这边也有对应的一个源码,也有对应的源码,但是这个源码呢它是这个啊,TENSORFLOW的版本好吧。
TENSORFLOW的版本大家也可以来自己看一下好吧,自己看一下,而某一般是直接用还是自己重新训练一个,如果你想用来生成这样的一个句子的embedding,那你就直接去加载它的权重,进行使用就可以了啊。
但是如果你想让这个生成的句子的embedding,效果更好,那可以怎么做呢,举个例子啊,假设你现在是一个这个医疗领域的一个场景,那可能而某它是一个在通用领域进行,预训练的一个模型。
那你就可以把你医疗领域的这个啊数据啊,你的文本数据拿过来去做一个预训练,预训练,预训练完之后呢,再直接用这个训练好的模型,来生成这样的一个embedding,好吧,当然你也可以啊,不进行预训练啊。
就直接去使用它的这个预训练,好的权重也是可以的好吧,这位同学两种方式啊,你想要效果更好,你就在你自己领域的数据再做一下预训练,当然啊这个通用领域的数据也是可以用的,只是说可能效果会稍微欠缺一点点好吧。
好啊,这边呢我们还有这样的一个图啊,讲解了,说明了一下咱们这个内交互和外外交互啊,我们来分别看一下这四个图啊,首先呢是第一个图啊,第一个图呢啊这边啊实际上它使用的是这样,BT这样的一个模型的一个结构。
而BT这个模型它结构到底是什么样子呢,没关系啊,这个没关系,我们主要是看一下它的这个叫做对于这个bird,它最原始的计算文本相似度的一个形式呢,实际上就是把两句话拼接在一起,黄色的是A,绿色的是B。
可以看一下啊,它中间会有很多的交互对吧,明显的它是一个内交互的形式,好我们再来看一下第二种形式啊,第二种形式A这边是A,这是B它有两个两个模型对吧,两个模型这两个模型呢还是像刚才说的,他可以做这个啊。
共享也可以不做共享,然后再把输出结果对吧,这里可能输出了一个VA这边输出了一个vb,然后计算了一个分数值,那这几个分数值你可以去算与选项速度,你可以去搞个全连接层,做个二分类对吧。
这就是典型的外交互嘛对吧,好我们再来看一下这个,那这个的话对于这篇模啊,对于这个模型结构来说啊,它是对于我们之前的这样的一个BT,一个模型做了一些改进啊,可以看到他这里有这样的一个啊内交互。
也有一个所谓的外交户对吧,对于最后这个结构来说也是啊,稍微做了一些改动,做了一些改动好,这就是我们的这个所谓的文本相似度,的一个模型啊,模型,通用领域的基础上进行训练,也可以也可以好吧也可以啊。
我这边再给大家总结一下啊,假设你现在是一个特定领域,你是特定领域,那你可以用特定领域的数据进行啊,通常叫做post train,进行post train,也就是做一个后后训练啊,那这样的话。
你特定领域的这个embedding效果就会提升,效果就会提升,当然你的这个post tra,EFEFA也可以使用通用领域的数据进行训练,好吧,两种形式都可以,但是我我想我的建议是通用领域。
实际上你没有必要了,你自己去你自己的领域上,用自己的数据进行post tree就可以了,好吧,这位同学,但是啊你还是需要去加载它的预训练权重好吧,就是说你在你自己的领域上去训练一个模型。
你还是需要去先把他的那个权重权重啊,给加载一下,你还是要把它的权重给加载一下,为什么呢,因为他这是在全领域进行训练的,它可能是一个泛化能力比较好的,但是对于你的领域,你想让你的领域效果更好。
但是你不能说唉,我只在我自己的领域上面效果好,你一些通用的一些场景,你效果就不好,那肯定是不行的对吧,所以呢你应该先加载它的权重,然后再在你特定领域的一个数据上,进行一个post train,好吧。
这位同学好,我有解释清你的问题吗,这位同学,OK啊,然后这位同学说这里这个EXP,你是指这里这个cl s吗,还是啥,这位同学是指这里这个CLS吗,还是啥,还是这里这个吗,E x p,这里这个EXP1。
这个我还真不太确定,这,这个我还真不太确定他这个exp是什么意思啊,但是我这里简单说明一下啊,首先呢这里这个cl s还有像这里这个SP啊,表示的是BT这个模型当中,带着这样的一个特定的一个标记位。
标记为那这些标记位有什么用呢,到时候讲BT的时候会去给大家去讲啊,那这里这个EXP啊,我这里也不太清楚啊,到这个可能需要去看一下这个PO这篇paper,它里面的一个应该也是一个特定的一个标记为。
需要去看一下这篇paper,他对这个EXP的一个解释好吧,啊这个东西我下来帮各位同学看一下啊,看完之后,到时候我在群里再同步,各位同步给这位同学好吧,好那我们继续啊,好啊。
刚才我们有说到这个啊啊文本相似度这一块啊,那文本相似度有内交互,有外交互,当然啊,我们还是得,虽然这里说了一些比较复杂的一些结构啊,但我们还是得那个从一些简单的模型来入手,毕竟只有简单的大家都弄清楚了。
你的这个复杂的模型你才能了解的更好,好吧好,那我们就先来看一下文本相似度,它的一个可以算是开山鼻祖的一个模型啊,咱们的DSS这个模型,它的一个结构其实是非常简单的啊,非常简单的。
首先呢输入的就是这样的一个,每一个这样的一个词的一个这个vector vector,然后呢他会去做一个所谓的word hash,这个可以不做可以不做,然后呢这边会有一些多层的非线性的一些变化。
简单点就是咱们的全连接层,加上我们的激活函数,最后啊再去进行我们的这个相似度的这个计算,哎你可以看到啊,他这里采用的也是这样的一个cosine similarity,对吧,Cos similarity。
最后呢再去做一个分类,做一个分类好,那我们诶这个是,啊这是它就是一个整体的一个结构啊,整体的一个结构,那这个结构我们先不看后面啊,我们不看后面这一块,我们就看前面这里这个Q和这里这个D。
从这里就可以看到啊,它实际上它是什么,它就是一个双塔的结构对吧,这就是双塔模型它的一个来源啊,它的一个来源就是来源于咱们的这个DSM,可以看到啊,这边有一个类似于塔的结构对吧。
这边也有一个类似于塔的结构,简单点看呢,就是说哎我这边生输入了一个句子的,这样的一个输入,一个句子经过了我们的这个embedding matrix,得到了我们的embedding。
然后经过我们的这群连接层,要经过我们的激活函数对吧,最后进行一个相似度计算,然后来进行所谓的一个二分类,这就是我们最原始的一个,双塔结构的一个模型啊,那后面为什么还有一些其他的塔呢,他的意思就是说。
哎我这里可能会有多个document对吧,多个document,然后我这个query,要和这些document都进行一个相似度的一个计算啊,所以看着好像有多个塔,那塔和塔之间呢。
大家可以去做一些所谓的权重的一些共享,权重共享,这样的话它的结构就是一样的,它的值也是一样的,我们就只需要一个模型,一个模型好,这就是我们的DSSM这个模型啊,整体来看模型结构非常简单对吧。
但是呢这样的一个模型啊,是我们的文本相似度,或者说相似度计算它的一个比较重要的一个,所谓的一个里程碑式的一个这样的一个模型啊,好,那接下来呢,我们就来看我们今天的一个重点模型啊。
重点模型叫做ESIM这个模型啊,那我们会一起带着大家从理论到实践的层面啊,把ESIM这个模型给实现一下,好吧嗯这样子啊我们刚好啊稍微休息一会好吧,我们休息5分钟,休息5分钟好,接下来的内容不多了啊。
主要就是对ESIM这个模型的一个讲解,包括如何去把ESIM这个模型进行一个复线啊,这是我们接下来下半节课,要给大家讲的一个内容,好吧好,那我们就啊稍微休息一会儿啊,我们休息5分钟。
当然啊对于我们上半节课讲的这些内容,大家如果有什么疑问,就把它打到公屏上好吧,打到公屏上,待会呢我们进行统一的一个解答啊,进行统一的解答好,我们稍微休息一会儿啊,好各位同学都回来了啊。
我们准备继续后面的内容了,好那接下来我们就来看这个ESIM这个模型啊,ESIM这个模型,那ESIM这个模型为什么要给大家讲这个模型呢,对于刚才说的这个DSSM这个模型,它是算是个开箱鼻祖。
那为什么要讲EC这个模型,首先呢ESIM这个模型啊,它是基于这个LSTM来的,那也顺便带着大家去复习一下这个LISTM,其次啊,ESIM这个模型相比于其他的文本,相似的计算模型来说呢。
它的效果和速度都还是不错的啊,都还是不错的好,那我们就一起来看一下啊,ESIM这个模型呢它有两种版本啊,一个呢是基于这个双向ISTM,就和刚才给大家讲的这个arm它的结构是一样啊,双向的AISTM。
第二种结构是基于这个TRISTM,就是基于一个树形结构的ASTM,如果要使用这个trail i s t m呢,首先呢需要去构建这样的一个啊预存数啊,去做所谓的语句法分析。
把转把句子转换成一个树形的一个结构,再给到我们的TRISTM,那这一步呢,首先啊就需要你的这个句法分析的这个过程,效果足够好,不然的话你可能会出现一些错误对吧,所以呢啊我们这边啊,主要还是给大家去讲解。
这个基于普通版本的这个LSTM,好吧好,那普通版本的这个LSTM呢,我们来看一下啊,它主要有四个部分,第一个部分的话是这个input encoding层,它其实就是这个LSTM的一个结构。
第二层呢是这个local influence model,那这一层呢它实际上是去做了一些好内交互啊,内交互,但是他这个内交互怎么做的呢,待会我们详细来看哈。
那最后一层是这个influence conversation啊,这一层可以看到啊,它也是一个LSTM对吧,然后最后呢就是做一些所谓的池化操作,咱们的平均池化层,最大池化层,最后再做个soft max。
也就是说你可以做个二分类对吧,这就是ESIM整个模型的一个结构啊,整体来看它其实就是我们的AISTM,加上这里的这个local influence,做了一些所谓的内交互对吧。
所以我们重点啊更多是放在这里,这个local inference modeling这一部分好吧,重点会放在这个部分好,那接下来呢,我们就来把这四个部分分别来看一下啊。
首先是我们的这个input encoding层,可以看到啊,他这就是一个LSTM层,这个LISTM层呢,大家可以看到它这里包含了两个部分啊,也就是包含他的这个ho size和他这个premise啊。
他这两个部分呢啊,大家可以简单的看成对应的,就是输入的两条文本,那对于ESIM这个模型来说,它实际上当时提出来的时候是去做什么呢,他做的是NLI,就自然语言推理啊,就我有一个啊有一个前提。
然后我要和他的一个假设,这两者之间到底是什么样的一个关系,他是作战的一个NLI的,他是一个矛盾的一个关系,还是能进行毫无关系,或者说他是一个能相互推出来的一个关系,所以它是一个啊,他这个H和P分别表示。
也是这个hle sites和咱们的premise,它的一个前提和他的一个假设啊,那我们还是可以利用它的一个,这样的一个结构啊,我们这边就输入A这条文本,然后这边输入B这个文本。
要进行一个相似度计算就OK了啊,所以他也是能达到这样的一个作用的好,那对于这里来说啊,我们可以看到我们不管是我们的H还是P,它实际上啊他这里都只有一个模型,都只有一个LST,这里大家需要注意一下啊。
他这里只有一个SLSTM,这里看似好像是两个对吧,但实际上它是一个,说白了它就是一个双塔的一个模型,他就是一个双塔的模型,并且它的这个模型的权重啊,它是进行了一个共享的,它是进行了一个共享的。
好共享之后呢,啊这边需要大家注意一点啊,他这里是一个双向的对吧,他这里是一个双向的双向的一个输出,结果我们刚才说过啊,我们会做什么处理呢,我们会把双向的结果进行一个拼接对吧,双向的结果进行拼接。
这里是最关键的点啊,最关键的点,那拼接之后好,我这里说一下啊,假设我的输入维度,那我这个LSTM的输出维度是64,因为是双向的对吧,我拼接之后维度就变成了128,这里大家需要注意一下好吧。
默认是拼接在一起的这个东西,待会也会在我们的代码当中有所体现,好,这是他的第一层input encoding,接下来我们来看第二层,第二层呢叫做local inference model。
那名字还挺长的,但实际上他实际上做了一个事情,叫做attention,Attention,什么是attention呢,attention啊,它实际上它不是所谓的一个结构啊。
它更适合叫做一种交互的一种方式,它不是一个模型,好吧,它不是一个模型,那attention是什么意思呢,好我们来看一下啊,首先呢他还是首先做了第一个事情啊,他把这里这个H和P做了一个相乘。
他把H和P做了一个相乘,K,H和P进行一个相乘,也就是说把两个向量进行了一个相乘,好我们提个问,两个向量相乘表示什么,它有什么样的一个意思,这里这个H也不能叫向量啊,应该叫做H这个代表的这个张量。
和P代表的这个张量,这两个张量进行一个相乘,它到底有什么样的作用,来各位同学,啊,我们把这里这个H和P的一个维度,进行考虑一下啊,这个H和P它的一个维度啊,实际上是三个部分。
第一个部分呢是我们的beach size,Batch size,第二个部分呢是我们的序列的长度,第三个部分呢是我们这个维度啊,eden size哦,我用size来表示吧。
size ok那H和P它的维度都是这个样子的,他的besides是一样的,他的这个size也是一样的,唯一可能是序列长度不一样,因为一个是我们的H,一个是P嘛,那对应到我们这边可能就是一个是A。
一个是B那它的长度可能不一样对吧,那这两者基因相乘表示的是什么呢,各位同学,你们觉得表示的是什么,来有同学知道吗,大家说一下自己的想法就可以了,并不是说一定是对的对吧,大家有什么想法,相似度。
其他同学觉得呢,这位同学觉得是什么,我看这位同学应该是有一定的一个基础的啊,这位同学觉得是什么,好那我来解释啊,这位同学说的基本上就是对的啊,基本上是对的,为什么可以说它是一个相似度呢,回忆一下啊。
刚才我们的这个余弦相似度是怎么做的,是不是A乘以B除以A的模,B的模除魔是在做什么呀,在做归一化嘛对吧,除以模我们的目的是在做归一化,那如果不做归一化,我们就是A乘以B,那这个东西是不是。
就可以看成一个所谓的一个相似度,只不过我们这里因为有一个序列长度,这个维度,也就是说哎我们这里实际上是有很多个词诶,这边是W1W2W三,然后这边可能是Z1Z2,哎这里得到的结果是Z1W1。
这里得到的是Z1W2,这里得到的是Z1W3,这里是ZRWEZRWRZRW3,那这里我们得到的这个东西,它是什么呢,它是每一个词和词之间它的一个相似度,大家也可以理解为它之间的一个权重,也就是说。
Z1这个词和W1这个词它的一个相关性好,Z1这个词和W2这个词它的一个相关性,Z1这个词和W3它的一个词的一个相关性,你也可以看出它的一个相似度,那相似度越高,那说明它们的相关性就越高对吧。
这就是这里这个矩阵它的一个实际的含义,说白了就是词和词之间,它的一个相似度或者相关性,我们得到这样的一个矩阵之后呢,我们把这个矩阵去做一个所谓的soft max,做完soft max之后呢。
说白了就是对这一行,我们去做了一个所谓的规划,那可能就是A这里是啊0。7,这里是0。2,这里是0。1,那这样的话就等于我们就得到了Z1这个词,相对于W1这个词来说,它的一个相关性是0。7。
Z1相比于W2来说,它的相关性是0。2,Z1相比于相对于W3来说,它的相关性是0。1,那有了这个权重之后呢,我们就可以做一个什么,做一个加权求和嘛,我们把这里这个0。7乘以我们W1,再加上0。2×2。
再加上0。1乘以我们的W3,那这个东西是啥,这个东西说白了就是用我们的W来表示,我们的Z也就是说我们用对应的这些词,它的一个加权求和的一个结果,来表示Z1这个词,这就是一个attention。
Attention attention,就是我先进行一个相乘,得到一个所谓的权重,得到权重,得到这个东西,它是一个权重,再把这个权重分别和我们的A和B再进行相乘,就可以得到加权之后的一个结果。
加权之后的一个结果好,这里呢我们就把我们的哦,我这里也写的是Q啊,我这里应该写H的好,我们这里把P和Q相乘之后,得到了我们的权重矩阵对吧,得到权重矩阵之后呢,我们再分别和原来的两个句子进行加权之后呢。
就可以得到加权之后的P和Q,也就是这里的P1撇和Q1撇好,这是原P,这是原Q和加权和我们的权重矩阵相乘之后,得到加权的P1撇和Q1撇,那这个时候实际上就是在做一些交互处理,交互处理。
最后我们把这里这个PP1撇,P减PP乘P1撇进行一个拼接啊,进行一个拼接,对于Q来说也是哎也是一样啊,进行一个拼接,进行一个拼接,拼接完之后再把整体啊,作为一个这样的一个输出值,输出值好。
这就是我们的这个啊local influence modern层好吧,local influence modern层好,这里我们停一下啊,我们停一下,因为这个东西是今天的一个重点啊。
重点看各位同学对于这一块还有没有什么疑问,再总结一下啊,A和B相乘,得到了这样的一个所谓的相似度,或者说相关性的一个矩阵,然后做所谓的soft max,soft max的目的在于让他变到一个零一之间。
做了一个所谓的归一化,那也做了归一化之后,再做一个加权求和的一个过程,这样的话我们就可以针对于Z1这个词,得到Z1的一个加一个替代品对吧,替代品也就是这里的P对应的P1撇,好这里我们稍微停一下啊。
各位同学有疑问吗,这里这个地方是ESIM模型的重重中之重,重中之重,后续当我们学到BT这个模型的时候,你会发现它里面的核心点也是TENTION,也是2TENTION,如果这里这个腾讯大家弄明白了。
到时候来学BERT的tension的时候,大家就会觉得哎和这个特征人差不多嘛,没什么区别,大家就会学起来就会很简单啊,就很简单,好还有疑问吗,各位同学,好如果都没有问题,我们就继续往下了好吧。
OK那我们上一步是把PP1撇,还有一些P减P1撇,P乘P1撇,拼接在了一起是吧,那拼接完之后呢,我们接下来啊就会给到我们的这个influence,conversation层,这一层也是一样啊。
就是我们的双向的LTM给进去就OK了,最后就是我们的输出层,输出层有这个最大池化层,平均池化层加上我们的soft max层,当然啊,这里这个平均池化层和最大池化层的输出,结果啊。
我们会进行这样的一个拼接,拼接,拼接完之后呢,再给到我们的这个分类层去做一个分类好吧,好,这就是整个我们的ESIM这个模型的一个结构啊,ESIM模型的结构好,那到这里之后呢,我们的模型结构也就讲完了啊。
那这里我们再给大家补充一个额外的知识点啊,好,那对于我们刚才提到的这个文本表示的,一个方式,和我们的这个基于模型来计算,相似度的一个方式,大家觉得这两种形式各有什么样的一个优缺呢,大家觉得各有什么优缺。
来各位同学,大家觉得刚刚说的,表示学习和我们基于模型来计算,相似度的一个方式,大家觉得各自有什么优缺,OK那还是我来说吧,其实最大的问题在于嗯啊,这位同学说表示更简单一些啊,也不能这么说啊。
其实表示学习也会很复杂,也可以很复杂,但是感觉信息不多,表示模型直接相加好,我来我来解释一下啊,其实对于表示学习的一个形式呢,只是说他使用的时候速度会更快一些,为什么这么说呢。
假设啊我们现在啊我们以检索场景为例,我们现在有很多这样的一个document,有DED2D三,一直到第N,如果是表示学习会怎么做呢,我们提前有一个离线的一个操作。
把每一个document转换成一个向量对吧,V d v d2 vd 3v d n,那当用户输入了一条query之后呢,我们只需要把用户的这一条query,转换成VTO。
然后再把这个VK和我们这边这个去计算,我们的什么余弦相似度,调一下速度,它的计算量非常小,我们只需要用模型,把用户的query生成一个向量,然后和这些存储起来的document的向量去计算。
计算余弦相似度就OK了,它最大的优势在于什么,在于速度快,速度快,耗时小,那如果是我们的基于模型的一个形式,你想啊我们这里有N个document,然后有一条用户的query。
那我们是不是需要把用户的query,还有第一先给到我们的模型对吧,哎计算一遍,得到了我们的一个相似度,得到了S1好,我们还需要把用户的问题和我们的第二个document,给到模型,得到SR。
那好我们一共有N个对吧,最后我们就会得有一个SN,那我们就等于,我们需要把这NN个结果都计算出来,也就是说我们需要用模型计算N次,计算N次,那这种情况下呢实际上是非常耗时的,非常耗时的。
但是基于模型的一个形式,它的效果肯定是好于基于表示学习的对吧,这是不用想的嘛,你用模型实时计算出来的,那它的效果肯定是会比这种,embedding的一个形式来得更好一些啊,更好一些。
所以说啊在这样的一个基础上呢,我们就引入了所谓的一个流程,叫做召回,然后排序REWR重排序,什么意思呢,我们可以使用我们的这种embedding的形式啊,也就是咱们这样的表示学习的形式。
embedding的形式,进行一个召回,我embedding的一个形式,每次只需要计算这一次imagine,然后算相似度就行了对吧,也就是说我的这个计算量非常小,所以啊我让他来做召回阶段。
那可能我一开始库里面有1万个document好,那我采用这样的一个表示学习的一个形式,然后我取出top20,Top20,我把top20最相似的20个document给取出来,D1到这个第20把它取出来。
然后我再进入到我的REWRONG阶段,我把这20个文档和用户的这个query,给到我们的这个排序模型,给到我们的相似度的模型,给到我们相似度模型,这样的话我们只需要计算20次。
最后再把相似度最高的这个结果啊排在第一位,或者说你就按相似度,从大到小进行一个排序对吧,按相似度进行一个salt就OK了就OK了,这样的话我们兼具了效果,那个时间的同时也兼具了一个效果。
也兼具了一个效果,这就是目前比较主流的一个,文本检索的一个流程,好吧,当然啊这里到底应该选择top几,就自己大家就自己来决定了好吧,你可以选top20,你可以选top5,top10都可以好吧。
当然你这里选的top的数量越少越越少,那你这里啊后续的这个rank的一个时间就越短,但是你这个召回的数量少了,那这边可能对最终的结果可能会有一些负面的,一些影响也是有可能的,好吧好。
这就是我们今天要给大家讲的,这个文本相似度了哈,文本相似度包括它的一个应用好吧,好这里我们稍微停一下啊,看对于这一块大家有没有什么疑问的,如果没有什么疑问的话,我们就要进入到我们今天的这个实战环节了啊。
实战环节有疑问吗,各位同学,OK行,那我们就进入到我们代码环节啊,进入到代码环节。
代码这一块的话,大家建议大家啊,自己下来一定要动手去写一遍啊,写一遍啊,这边我们,我们也重新写一个啊,我重新写一个,我们先把代码给删了啊,我们再来重新写一个,首先第一步呢。
肯定是要把我们这个PYTORCH给进行导入啊,啊我们在使用PYTORCH这个框架的时候,我们在之前的一个录播课有讲过啊,首先呢我们要使构建一个模型的时候,需要去继承一个类对吧,继承一个类啊。
这个你可以先自己去取个名字啊,这个类的名字你就自己取,我们就叫EZ好吧,EZ好,然后呢他需要继承这样的一个类,继承什么呢,nn module对吧,这是我们最关键的啊,最关键的。
然后呢我们需要去实现它的两个方法,一个是我们的这个啊构造方法,这是一个是我们的一个构造方法啊,那构造方法是用来干什么的呢,有同学还记得吗,构造方法是用来干嘛的,有同学还记得吗,构造方法是用来干嘛的。
对诶这位同学是新来的吗,好像一直没有看你说话,对构造方法啊,它就是用来初始化咱们的layer的,包括一些参数,初始化layer参数啊,好然后呢我们还需要重写一个方法,叫做咱们的这个方法对吧。
for的方法,然后是我们的一个输入值,输入值呢我们就按照我们的这个啊,这个和咱们之前的这个分类啊,还不太一样,分类我们刚才说了,他就一条文本,那对于我们的这个ESIM模型来说,我们是计算的是文本相似度。
那就需要两条文本对吧,两条文本啊,那我们就用我们的我们用PQ来表示啊,用我们的P和Q来表示好,OK这是我们的啊forward的方法,for word方法是做什么的,就是前向传播对吧,选项传播。
OK那接下来我们就来看一下啊,我们的这个构造方法需要用到哪些层。
需要用到哪些层,呃,我们来到来到这里啊,我们看一下啊,需要用到哪些层,首先呢这边有一个ASTM层,因为这边是咱们刚才说的attention,Attention,好像也没有什么额外的权重对吧。
只有一个权重矩阵,所以这里应该是local influence这一块的话,应该是用不到我们的一些额外的层的,然后这里也是我们的LISTM层,最后呢就是一个啊平均池化层和最大池化层,还有一个分类层。
对吧好。
当然啊,最开始这里输入啊,还有一个embedding层,embedding层,也就是把我们的一个一个的词,转换成对应的一个embedding对吧,好,那我们就首先来定义一下我们这个embedding层。
embedding呢它有两个参数,第一个参数是我们词典的大小,Vocab size,你的这个词典的这个大小呢,我们可以从外面传递进来啊,我们从外面传递进来好。
第二个维度呢是这个embedding size,也就是说你的这个embedding层啊,要输出到维的,如果你想输出100维的,那你这个参数就填100,好吧好,这是我们的embedding层。
embedding层完了之后呢。
我们看一下啊,是这个input encoding这一层是什么。
ASTM嘛对吧,ASTM好,那我们就来写一下我们的这个ASTM,我们叫做input encoding,Input a input encoding,LST好,那LSTM这个模型呢我们来看一下啊。
它有哪些参数,他这边有一些参数介绍啊,我们来看一下input啊,首先哦不是这个啊,应该是这个地方,首先呢有input size,有hidden size,有input size的话。
就是说你输入的这个数据啊,它的一个维度,hidden size的话就是hen size应该不用解释了吧,然后number layer的话,就是说你的这个LSTM是多少层的,然后还有一个参数叫BIOS。
也就是说你要不要添加这个偏移项,然后是这个beach first,beach first的话,意思就是说你要不要把你的beach size,放在第一个维度,通常是为了加速啊。
beatch size放在第二个维度速度会更快一些,但是我们默认喜欢把beside放在第一个维度啊,所以待会我们需要把这个参数改成这个true,然后还有一个常数参数呢是这个drop out。
就如果你给这个drop out一个值啊,它就会再做一些dropout,然后这里还有比较重要的参数啊,就是这个啊,By dictionary,如果你填为true的话,它就是一个双向的AISTM好吧。
所以说对于Python学框架来说,使用是非常简单的好,第一个为第一个参数是我们的input size,那对应的就是我们的bedding size对吧,上一层输出的维度是多少。
那我们这个input size的维度就是多少,然后呢我们需要给他一个hidden size,Hidden size,那个hidden size我们要从外面传递进来好吧,传递进来好。
然后我们有一个叫做number layer的啊,我们和论文当中保持一致啊,它是一层对吧,它是一层,那我们就写一层,然后呢它是一个双向的,那我们就有点理也改,也弄成双向的啊,也弄成双向的。
然后还有刚才说的一个比较重要的参数啊,first就是说我们的这个把ch size放在第一个维度啊,那我们就把这个参数设置为true好。
这是我们的这个input encoding层,那这里这个local influence modern层没有权重,那我们就不需要准备啥对吧。
接下来就是这个influence conversation层啊,我们再来定义一下这个,那这里其实是一样的对吧,首先是input size,那就是embedding size。
然后是这里这个hidden size,这个hidden size到底哦不对不对啊,啊我先这么写吧,这里其实有一个问题啊,我们待会再来说,我们待会再来聊,后面就保持一样啊,我们这里也是true。
然后beside beat first true,好啊,这里我先留一下啊,大家也可以考虑一下,这里只有input size到底应该填什么,这里这个input size填embedding size对吗。
到底应该填什么,这里大家考虑一下,考虑一下好。
我们先继续往后,我们继续往后啊,然后呢,我们是需要平均池化层和最大池化层对吧。
平均池化,这里我们采用两种方式,第一种方式呢我们先来搞个最大池化层啊,Max to,我们定义一个max to啊,然后呢他需要有一个序列的最大长度好,我们把它从外面传递进来啊。
那这个参数呢实际上就是它的一个kernel啊,它的一个kernel size,Kernel size,这是他的一个kernel size啊,啊这是我们的最大池化层好,然后是我们可以定义两个全连接层啊。
嗯电池吧,A,LI好,OK那这里又有一个问题了,我们这个linear的第一个维度到底应该填多少啊,我先写一个size,好吧好,我们的输出是resize,第二个B,好最后我们输出两个值啊,我们输出两个值。
两个值为什么输出两个值呢,这里因为我们需要用到的是交叉熵损失函数啊,所以我们这里输出两个值,那最后我们再加个drop po,给个0。2的主炮率,OK这样的话我们初始化的一些layer啊,就准备好了。
准备好了,那接下来我们来看一下我们的这个前向传播,前向传播这个首先第一步啊,啊我们去要得到我们的这个哎,等一下等一下这里忘记说了啊,我们这里初始化的这些layer有一个点啊。
有一个点我们实际上只出使了一套对吧。
在这个图当中它是有两个LST,但是在我们这里实际上就一个LST。
那一个LSTM怎么达到他两个的效果呢。
那就是说你调用两次,这样子的话,实际上就等于做了所谓的权重共享好,我们来看一下啊,首先呢我们得到P的embedding,那就self点embedding层,把P传递进来。
然后Q的embedding也是一样啊,我们把Q传递进来,这样我们就得到了P和Q,它对应的一个embedding,然后我们去调用我们的LSTM,叫做local influence是吧,还是叫啥好。
Input encoding,input encoding好,我们把我们的ping bedding放进来,这样的话我们就可以得到我们的LI,STM的输出值,但这个输出值好有点讲究,我们来看一下啊。
它的一个输出值包含了两个部分,一个是输出值,一个是这边一个元组,这个组里面放了hidden state和cal state,我们要的是输出值,这两者,He hidden sit,我们是不需要的啊。
不需要的,所以呢我们就可以啊,这么写啊,我们可以写叫做啊好我们就还剩个embedding,表示p embedding,然后下划线就等于等于这个,这样的话,我们就只拿到了我们的LSTM的一个输出值。
hidden state我们就不要了不要了,而对于Q来说也是一样啊,我们还是用这样的一个形式去拿,诶,这里我们换一种形式啊,上面是把它取出来对吧,那这里的话我们换一种形式,我们取零零是什么意思。
零的话就是取前面嘛,取前面对吧,所以说两种形式啊,两种形式都可以好,那接下来呢我们去这里做个drop吧,好吧,我们做个drop out啊,Q版好,这样的话我们的这个input encoding层啊。
就完成了完成了。
接下来我们来看我们的这个local influence这一层。
首先第一步还是做我们的什么相乘嘛,对吧,我们要把P和Q进行一个相乘好,我们来乘一下啊,touch the mam好,我们把这两个进行相乘啊,首先是我们的这个啊P的embedding。
p embedding好,再和q embedding进行相乘,那和Q的embedding进行相乘的时候,这里就需要做一个transl,Transport,这个transpose是什么意思呢,意思是说啊。
我们要对Q的embedding的第一个维度,和第二个维度去做一个转置,为什么要做一个转置呢,好我们来看一下啊,对于P的embedding来说,它的维度实际上是啥,它的一个维度是,Besides。
然后序列长度,然后是我们的这个hidden size对吧,Hidden size,那对于Q的维度来说,它其实也是这个,那这个张量和这个张量是没有办法去做乘法的,所以我们需要把这两个维度啊做一个调换。
调换之后呢,QE就变成了Q的embedding的维度啊,就变成了这个样子,变成了这个样子,这样子的话我们就可以进行相乘,因为这个维度等于这个维度对吧,所以呢我们Q和啊,这里写我们这个P啊。
和Q就可以进行一个这个相乘的一个处理了,好吧好。
乘完之后呢,我们再来做一个加权的一个处理啊。
加权的一个处理啊,好,那我们首先第一步还是需要先对这个一啊,做这个所谓的一个soft max,soft max呢我们需要有一个维度啊,我们对第二个维度进行SOFTMAX,然后还是一样啊。
我们还是去做这样的一个矩阵的一个,或者张亮的一个乘法,然后把这个QUEBE传递进来好,也就是说这个部分是得到我们加权。
并且规划的一个结果,也就是这里这个0。70。20。1,它的一个权重。
然后有了权重之后呢,再和Q进行一个加权啊。
这样的话就可以得到我们的PH,也就是我们这里的加权之后的结果好。
那对于我们的Q来说也是一样啊,我们去做一个处理啊,这里我们去做这个soft max的时候,这里大家需要注意一下啊,维度要改变一下,改变一下,其次呢我们需要对我们的soft max这个一啊,做一个转置。
因为它的维度不对啊,他没办法和我们接下来的这个啊,p p embedding进行一个矩阵乘法啊,所以我们要把这个也做一个转置,还是把第一个维度和第二个维度进行,交换一下啊。
OK这样的话我们就可以得到我们的Q,它加权之后的一个结果啊,P加权之后的一个Q。
好,那我们得到了就等于是得到了P1撇和撇一撇,接下来是什么,接下来就是拼接嘛,对吧。
接下来就是拼接好,那我们来把它做一个拼接啊,啊我们的key bedding,然后是我们的这个BEH,然后是p embedding,剪掉PH,p embedding乘以p heat对吧。
OK那对于Q来说也是一样啊,Quin bedding,Cue heat kin bedding,减掉cue heat lp embedding乘以我们的P是吧,OK这样的话我们就全部拼接在了一起啊。
当然这里还需要注意一下啊,我们是要以最后一个维度作为一个拼接对吧,这里大家需要注意一下,好拼接完之后呢,下一步是什么,是给到我们的influenced嘛对吧,Influenced。
OK我们把p cat给进来啊,这里我们直接取取零了啊,这里就是得到我们的P,然后Q也是一样啊,Q然后这里是q cat,OK这里我们稍微停一停啊,稍微停一停,刚才我们说这里这个influence。
这里这个东西是有问题的对吧,因为这个input size我们不知道是多少,那这个input size到底是多少呢,好我们来看一下这个input size应该是多少。
首先我们输入的是invoke ef size,然后得到embedding size,Embedding size,经过我们的LSTM,因为它是一个双向的,所以这里的LSTM的输出值。
也就是说这个地方它的输出值,它的维度啊已经变成了embedding size,乘以二吧,已经变成了乘以二,哦这里写错了啊,这里写错了,好检查一下啊,QQQQ好写错了啊,这个地方啊这边已经乘以二了对吧。
乘完了二之后呢,我们这边呢又去做了什么,做了四次的一个拼接,所以这个时候就又变成了embedding乘以二,再乘以什么,再乘以四,因为一共有四个嘛,所以啊这里这个influence层啊。
它的这个维度就应该是hidden,Hidden size,乘什么乘以8×8,好我们继续往下啊,我们的这个啊influence层完了之后是啥,这是我们的预测层了啊,预测层了,好那我们首先拿一下这个。
啊p max啊,我们就调调我们的最大池化层,把我们的这个P啊给传递进来,然后呢我们需要把中间的维度给去了啊,对于Q来说也是一样啊,好,这样的话,我们就可以得到我们最大池化层的一个结果。
然后呢我们再去做一下平均池化层,平均池化层的话好我们可以直接用touch命啊,直接用touch命,然后把我们的P传递进来,还是一样啊,我们这边啊这边需要注意一下。
这里是要根据我们的这个中间这个维度去取平,均好吧,这里大家不要弄错了,也就是这个序列长度的那个维度啊,好,这样的话我们就得到了最大池化层的结构,和平均池化层的一个结果,最后我们再做一个事情啊。
把它做一个什么,做一个拼接,也就是这里说的。
我们要把结果做个拼接,对吧好。
那我们把结果拼接一下,p Max-Q max还有P命Q命,好最后我们再调用一下这个dropout,好这里我们需要有一个输出值,啊啊我们用out,OK最后的话再给到我们的这个分类层。
分类层先给到dc1好out,然后我们可以加一个这个激活函数,激活函数啊,我们加个激活函数,好我们再经过一下我们的这个drop吧,我们最后再经过我们的这个啊dance啊,然后把结果进行返回。
OK整个模型啊我们就写完了,然后这里这个dance1大家需要注意一下啊,我们这里是不是就应该也是hidden size,hidden size再乘以多少呢,因为这里也是一个四部分进行一个拼接对吧。
然后包括刚才这里是一个双向的,所以我们这里应该也是乘以八,好这就是我们整个ESIM模型的一个结构了啊,结构接下来我们我们来跑一下啊,我们在我们的处理方法里啊,处理方法呢和我们之前的那个分类是一样的啊。
分类是一样的,然后我们这边改一下啊,我们从我们刚才写的这个里面进来ec to,然后我们看一下啊,work happy size是不是一样的,Embedding size。
hidden size maxine啊,都是一样的,好,OK我们把模型跑一下哈,啊我这里先取1000条数据好吧,我们速度快一点,不然比较耗时啊,数据量大的话比较耗时,我们来看一下会不会报错啊。
诶好像是报错了啊,啊这里必须是用一个long的类型啊,那我们在进行forward的时候啊,我们可以把它转换成一个long的一个形式,然后下面也是一样啊,我们做验证的时候也是一样。
那训练代码呢和我们之前讲的TX的一个,训练代码是一样的啊,我们就啊不再重复说了啊,简单看一眼啊,简单看一眼,这边呢去加载数据,加载数据也不说了啊,然后这边是我们的初始化我们的一个模型啊。
初始化我们的模型,然后放到我们的GPU上,然后优化器定义我们的cross entropy损失函数,然后这边是循环五个epoch,然后以bech size的形式去取数据对吧。
前向传播要计算loss梯度归一,反向传播更新权重好,这些都是我们之前说过的了啊,之前说过的啊,正常是跑起来了啊,因为我这里就取了1000条数据,就取了1000条数据啊,没有全部跑,所以效果可能不太好。
大家到时候就下来自己去跑这个好吧,我们先简单看一下第一个epoch呢,我们的训练集的准确率是57,验证机是49,然后变成了5964,然后6553,诶,这个法案效果是降低了一点点对吧。
不过这个大家可以把这行代码啊,把这个改了,让它去跑一个全量的一个数据啊,全量的数据整体来看模型是持续在收敛的啊,持续在收敛的,没有什么问题,没有什么问题,验证机的效果也是在持续提升的啊。
好那整体来看代码应该是没什么问题啊,没什么问题,那细节的话啊,各位同学就自己下来看了好吧,但整体和我们上节课那个录播课里的tag cn啊,他的这个流程是一样的一样的,关键还是在于模型的一个结构好吧。
模型结构一点是,这里的双向LISTM需要啊去乘以二,维度要乘以二,其次呢我们这里做了一个拼接对吧,有四次的拼接,所以呢二还要乘以四,所以我们第二个AISTM它的一个输入值啊。
就是hidden side乘以八,这里是非常重要的一个点啊,大家需要注意一下,包括这里的这个linear层也是一样的啊,因为我们这里也是做了这样的一个拼接对吧,也是做了这样的一个拼接。
所以这里也是要乘以8×8好,这就是我们整个ESIM这个模型啊,整个ESIM的一个模型,那训练细节的话,大家就自己下来去看代码了好吧,这种重复的代码我们就不带着大家去看了。
OK那咱们今天的一个课程内容啊,基本上就给大家讲到这里了好吧,什么时候需要drop out啊,dropout的用作用呢是用来防止模型过拟合的。
基本上呢你经过了一层全连接层,或者说经过了一层这样的一个STM层,你就可以去添加上这样的一个drop,好吧,我们可以看一下啊,啊我们这里embedding,然后AISTMASTM经过之后呢。
我做了个drop out,然后这里因为没有权重嘛对吧,没有权重,attention层是没有权重的啊,所以我没有做JPP,然后啊腾讯之后做了拼接,又给到了我们的这个啊LSTM层,然后做了石化和这个这个啊。
平均池化层和最大池化层,那这两个地方也是没有权重的对吧,然后我是拼接完之后又做了一个drop out,好,经过这第二个这第一个全连接层之后呢,我又做了一个抓party,所以你经过了有权重的层之后。
你就可以考虑去做一下drop,好吧,这位同学。
OK行,其他同学还有问题吗,如果没有什么问题的话,咱们今天的课程内容,基本上就给大家讲到这里了,好吧啊。
今天内容还是挺多的啊,总之大家下来要多花点时间去复习一下啊,包括这个表示学习和这里的这样的一个,匹配式的模型啊。
最重要的点在这里啊,在这个attention这一块,这个是非常重要的好吧,OK如果没有什么问题,那咱们今天的一个啊课程内容,咱们就到这边了好吧,各位同学下来就好好复习,然后下来之后呢。
自己要把这个ESIM这个模型做一个复线,然后ERO那一块要学会如何去使用好吧,OK那咱们今天的课程内容就到这边,大家有什么疑问的话。
就在群里,然后再沟通就OK了啊。
【七月在线】NLP高端就业训练营10期 - P1:1.循环神经网络与Pytorch框架_ev - IT自学网100 - BV1uxT5eEEr6
好OK那咱们就开始今天的一个课程内容啊,好咱们这次课的话,主要是要给大家讲这个关于神经网络这一块啊,神经网络这一块。
那我们先看一下今天要给大家讲的四块内容啊,首先呢我们会从这个基础的神经网络开始,给大家讲起啊,然后呢再给大家介绍关于啊,NIP当中用的比较多的这个循环神经网络,然后是卷积神经网络,那卷积神经网络呢。
可能更多会应用在这个图像处理,这个图像处理当中啊,但实际上啊在NLP当中也还是有蛮多啊,使用这个卷积神经网络来处理文本的,那最后一部分的话,我们会做这样的一个文本分类的,这样的一个实战啊。
实战还是先讲理论后进行实战,好吧好OK,那我们就先来看我们今天的第一块内容啊,关于这个神经网络,神经网络,那什么是神经网络呢,我们这边举个小例子啊,举个小的例子,假设呢我们现在想构建这样的一个模型啊。
这个模型的作用呢,是来预测我们这个深圳的这样的一个房价啊,深圳的这样的一个房价,那我们先从简单的开始考虑啊,假设啊,假设我们这个房屋的这个总价格额,只和我们的这个面积有关系啊,只和我们面积有关系。
那这样的话,那可能就是看面积的单价是多少就OK了对吧,既然如此啊,我们大概会得到这样的一个函数关系啊,那一开始可能啊我们是从零开始嘛对吧,那肯定没有说这个面积特别小的,这样的一些房子啊。
那这可能至少他也有一个压视平嘛对吧,好他大概可能就是这个样子啊,他的关系可能是这个样子这个样子,那这个是一个比较理想的一个状态啊,就说咱们的一个面积和咱们的这个价格啊,它是呈现这样的一个正相关的对吧。
当然啊真实的情况的话,可能咱们有些样本点啊,就可能会在啊咱们这个这条函数的两侧对吧,那在咱们这样的一个两侧,那咱们只是说构建出了这样的一个函数,本来拟合咱们这个面积和咱们价格,这之间的一个关系啊。
那假设我们的这个面积是,而价格是Y,那实际上我们是可以得到这样的一个,映射关系的对吧,也就是Y等于这样的1WX加B,我们是可以得到这样的一个映射关系的,这样的一个映射关系的好。
那这个呢是我们只考虑了这个面积的,一个情况啊,但实际上呢咱们这个价格啊,其实影响因素有很多对吧,除了咱们的这个面积以外,那还得还得考虑一些房屋的一些,周边的一些配套对吧,是否啊临近地铁啊。
或者说你这个住宅楼距离这个市区的距离,远不远对吧,还有他的一个什么像房屋的一些年限,那如果你说你这个房屋还是九几年的房,那你现在嘛肯定没有10年建的房,卖的这个价格高对吧。
那假设啊我们每一个这样的一个影响因素,它都有自己这样的一个权重,也就是说对于面积这个值啊,假设对于这个特征我们定义为X1,那它对应肯定会有相应的一个权重对吧,我们用A这个W1来表示。
就好比咱们刚才这样这个图对吧,我们的这个面积啊,会有对应这样的一个W的一个权重,那你就可以得到这样的一个价格,那假设我们在这里多个因素的情况下,我们面积这个特征的对应的权重是W1,那对于我们第二个特征。
我们假设是W2,第三个特征是W3,然后我们的房屋年限是第四个特征啊,我们假设是W4的这样的一个特征,那,有了这些特征之后呢,我们会认为啊我们可以根据这些特征,我们实际上是可以得到我们最终的这样的一个。
价格的对吧,最终的这样的一个价格的,也就是说,如果啊,我们把我们的这些每一个输入的一个特征啊,看成这样的一个向量,看成一个向量,那最终呢我们的这个价格Y啊,实际上就等于我们的X乘以我们的W的装置,对吧。
最后呢,我们可能还需要再加上这样的一个偏移下,那这个东西呢这个关系映射啊,大家就可以把它简单的看成一个,所谓的一个神经网络,只是说啊,咱们这样的一个关系映射,到底应该是什么样子的。
那就取决于你的这个神经网络,它是什么样子的了,好我们继续往下看啊,这里呢啊我给大家罗列了一个很普通的啊,一个最基础版本的一个神经网络,那他这里呢,首先呢就输入了这样的一个四个特征对吧,那这个神经网络呢。
它会对这四个特征去做一些这样的一些,交互的一些计算啊,交互的一些计算,那对于这里呢我们就可以发现啊,他其实有三个这样的一个节点,三个这样的一个节点,那这三个节点呢实际上就是我们前一层对吧。
我们前一层的这些值得到的这样的一个,交互之后的这样的一个结果,那通常啊对于一个普通的一个神经网络来说,例如这个地方的一个值啊,这里咱们可以我们用H来表示,实际上呢就等于咱们这里这个X1对吧。
这里会有个权重啊,这里会有个权重,那就是啊我们这里用啊we1表示啊,然后这里呢我们用W2表示,这里呢我们用W4表示,那对于这个节点的一个值呢,就等于W1X1加上W2X2,再加上我们的啊W4X4。
最后呢我们会有这样的一个偏移项对吧,我们会有这样的一个偏移项,通常啊经过了我们这样的一个计算之后呢,我们都会在外面啊,再进行一个所谓的,加上一个所谓的一个激活函数啊,加上一个激活函数。
那这个激活函数的作用是什么呢,通常呢是引入一些非线性的一些变化啊,引入一些非线性的变化,我举个例子啊,假设啊,我们如果没有这样的一个非线性的一个变化,那走到下一层的时候。
我们实际上假设啊这里我又成了这样的一个W,假设我这里是用W5来表示好,我把这个W5再和这个直接相乘,那相乘之后的结果是不是就是W1W5乘以哎,乘以X1对吧,后面我就不写了啊,就写不写了。
那最后一项的话就是W乘以B那可以发现啊,这个时候实际上啊这里这个W1,W5和这里这个W1,其实啊可以用同一个值来表示,所以说啊咱们这个神经网络,每一层最普最普通的神经网络啊。
每一层之间我们通常都会去加上这样的一个,所谓的一个激活函数,去做一些非线性的一些变化,不然你的这个两层的神经网络实际上和一层啊,它就关系不会很大好吧,他的关系不会很大,所以啊我们需要去加上这样的一些。
非线性的一些变化啊,非线性的变化,那这就是我们的一个最基本的,最基础的一个神经网络,那这个时候可能就会有同学说了呃,那我怎么知道这个X1X2X3X,我到底应该构建什么样的一个神经网络呢。
那这里这个神经网络对吧,我们啊这里有一个中间这一层啊,我们通常称为隐藏层,然后最后这一层呢我们称为输出层,那有的同学会说,那我这个隐隐藏隐藏层,我到底应该设置几个节点呢对吧。
或者说我这个隐藏层现在是一层,那我可不可以搞两层或者三层,那都是OK的啊,都是OK的,那到底应该设置几个节点呢,这就是一个所谓的一个超参数啊,超参数需要我们去自己进行这样的一个。
超参数的进行一个调整好吧,进行一个调整好,这就是我们的一个神经网络啊,然后我们这里来看一下这里这样的一个网站啊,啊这是一个神经网络可视化的这样的一个网站。
我们可以去看一下啊,我们可以随便选啊,啊这边是有一个数据的一个数据集啊,假设呢我们要分这样的一个数据集啊,可以看到中间是蓝色的点,然后外面这一圈的话是这样的一个橙色的点啊。
我们要把这个蓝色的点和这个橙色的点给啊,区分开啊,分成这个样子,然后这边呢我们会有一些这样的一个,输入的一些数据好,那我们可以给它添加一些这样的一些,输入的一些数据,而中间呢就是咱们的这个隐藏层啊。
这边是咱们的输入值,这边是咱们的一个输入值,然后这边呢是咱们的一个哦隐藏层啊,隐藏层现在的话是四个节点,对吧啊,我这边先去两个啊,我就用原始的X1和X2,这两个输入值作为我们的输入啊。
这边呢是四个这样的一个隐藏层的一个节点,然后这边的话就是咱们那个输出值,因为为什么这里是R呢,因为我们要做一个R分类对吧,我们要把它区分成蓝色节点和橙色节点,好,我们可以这边是可以调整一些超参数啊。
好OK我们执行一下,可以看到啊,这个时候呢模型就是正在收敛啊,正在收敛,那其中蓝色这一块的话,就是咱们的这个蓝色的点,而橙色这一块呢里面就是咱们橙色的点对吧,而这边呢我们还可以添加更多的这样的。
一些层啊,可以添加更多的一些层,而这边呢我们也可以去添加节点的一个数量啊,然后我们也可以再跑一下哎,他也是可以一样收敛的,这边我们也可以换一下啊,换成其他的,甚至你可以多加一些特征数据对吧。
OK我们再跑一下好,这边也是进行这样的一个收敛啊,这就是咱们的一个很普通的,这样的一个神经网络啊。
神经网络好,那除了这样的一个最基础版本的,神经网络以外呢,其实还有很多的一些其他的一些,神经网络的一些变体啊,啊例如咱们的这个卷积神经网络,卷积神经网络,还有咱们的这个循环神经网络。
那咱们今天除了给大家介绍这种最基本版本的,这个神经网络以外呢,我们也会给大家去介绍,这个所谓的卷积神经网络,还有循环神经网络,好吧,我们就分别来看啊,我们分别来看好,接下来呢我们来看一个概念啊。
就是说如果我现在有了这样的一个神经网络,对吧,我该怎么去把我神经网络当中,这些参数给求解出来,什么意思呢,就是说我这里的这些W啊,我这里不是有很多这样的一些W吗对吧,那这个W我该怎么求解出来呢。
如果我不知道这些W的话,那你最终你输入这个值对吧,我也拿不到我最终的一个结果,所以关键啊神经网络你除了要有结构之外,还要有咱们的这个参数对吧,还有咱还要有咱们的这样的一个参数啊,也就是咱们这里这个W。
OK那我们来看个例子啊,看个例子,假设呢我现在要输入一张图片,我要判断一下啊,我输入的这张图片它到底是个什么动物啊,是个什么动物,那这里呢,我们就把这个图片给到咱们的这样的一个模型。
那这个模型的话其实就是两部分组成,刚刚说的这个结构和咱们这个参数啊,结构的话就看你去是怎么构建了,你可以去构建一个啊,普通的这样的一个神经网络对吧,你也可以去构建这样的一个卷积神经网络好。
那当我们把我们张图片输入给我们的模型,的时候呢,我们的模型啊它会输出一个值,它会输出一个值,那这个值呢表示的是我们的图片的某个类别,某个类别好,这个输出值到底该怎么定义,我们待会再说啊,待会再说。
那有了输出值之后呢,实际上啊我们对于每一张图片,我们都是有真实的这样的一个标签的对吧,人工可以给这个图片打上标签,那对于模型的一个输出结果,和我们真实的这样的一个结果。
我们就可以去计算它之间的这样的一个差值,那这个值呢我们把它称之为loss,loss值啊,也就是说我们的预测值和我们的这个真实值之,间的这样的一个差距有多大,那我们的目标是什么。
我们的目标实际上就是要把这个差距缩小对吧,我们要把这个差距缩小好,那把这个差距缩小,我们就等于是在去,怎么才能把我们的差距缩小呢,说白了就是要去让我们的这个参数变得,越来越好对吧。
越来越适合我们这样的一个场景,我们可以回到刚才那个例子啊,假设我们要让我们的这个房价预测的特别准,那肯定也得保证我们的这个W对吧,我们这个W尽可能的让我们的这些样本点,和我们真实的这个结果。
他的这个差距最小,那才是最合适的对吧,所以说啊我们就需要不停的去把这个最合适的,或者说最优的这个W给求解出来啊,给求解出来,那这个求解的过程呢,我们通常采用的是梯度下降法,梯度下降法好。
那接下来的话我们就分别来看一下,我们的这个loss和我们的这个啊,梯度下降法到底是怎么个回事啊,怎么回事,嗯好等一下啊,我们在看这个loss和梯度之前呢,我们先把咱们这个前项的这个流程啊。
我们再简单梳理一下,我们刚才这里说到说哎,我们这里会输出一个这样的一个值对吧,我们这个这里的话是输出了一个零,那这里这个零表示的是什么意思,或者说我每次输出的时候,我到底应该输出什么东西。
好我们先看这个问题啊,我们先看输出,再看loss,再看我们的这个梯度下降法,好吧好,我们先看输出,首先呢我们这边会有张图片,我们把图片啊转换成这样的一个数字,那一张图片的话放到咱们的计算机当中。
它实际上就是一个0~255之间的,这样的一些啊,数字的组成的这样的一个张量对吧,OK那我们可以把咱们这些值啊,首先呢做一个这样的一个归一化的一个处理,很简单啊,就把每一个值都除以255就OK了。
然后呢我们把我们每个这样的一个输入值啊,给到我们这样的一个神经网络,神经网络,那这个神经网络网络呢你可以去设置多层,也可以设置为一层,你也可以用刚才说的卷积神经网络也好,或者其他神经网络都是OK的好。
那这里啊,假设我们中间已经经过了一系列的一,些神经网络,最后呢我们这边又经过了这样的一层,普通的一个神经网络,最后我们又加上了这样的一个激活函数啊,激活函数,那这里呢我们采用的是一个叫做SIGMOID。
激活函数,那这个激活函数它有什么作用呢,它是这样子啊,这个激活函数它是这个样子的,我们简单画一下啊,简单画一下,嗯这是咱们的一个0。5,0。5,他大概是这个样子啊,大概是这个样子。
也就是说如果你的这个值啊,他是就是我当我们把这个值啊,输入给咱们的这个激活函数的时候,它可以输出一个0~1之间的一个值啊,这个最大值是一,最大值是一,最小值的话就是咱们的一个零。
它可以输出一个0~1之间的一个值,那通常啊假设我们要去判断这张图片,它是不是猫,那我们就可以把我们神经网络的输出结果,给到这样的一个SIGMMOID的一个激活函数。
那这个激活函数如果它的一个输出值大于零,那这个输出值啊它大于零给到我们奇偶函数,他就会输出一个大于0。5的一个值对吧,那大于0。5我们就认为它属于猫,如果呢他这个神经网络它的一个输出值。
它小于零小于零的,那给到我们的激活函数,它输出的值就是一个小于0。5的,这个时候我们就认为它不是猫,那在我们这个场景当中啊,假设我们最终的结果是0。75,0。75哦,0。730。73的话,它是大于0。
5的对吧,所以最终呢我们就认为啊,这张图片它实际上就是一只猫,我们就以这样的一个模式啊,来得到我们的一个输出值好吧,输出值好,我们再简单总那个总结一下啊,输入一张图片给到我们的神经网络。
把神经网络的一个输出值给到我们的SIGMOID,激活函数,激活函数根据它的一个输出值是否大于0。5,来决定它是否是猫,如果大于0。5,我们认为它是锚,如果小于0。5,我们就认为它不是锚好。
这就是一个很简单的一个所谓的一个二分类啊,二分类判断一张图片是不是毛好,这个时候可能会有同学说,那假设我现在不是想去做阿凡雷,我并不是说我要去判断这张图片是不是猫,而是我想知道这张图片它是什么动物。
假设啊,假设呢我们这边嗯我们有这样几个类别啊,可能有啊,有狗有猫,还有咱们的这个啊长颈鹿,OK我想判断一下我当前这张图片,它到底是狗还是猫还是长颈鹿,那怎么办呢,有一种方案啊。
就是说我们可以把我们的这个数,这个神经网络啊,我们可以搞三个节点对吧,刚才的这个神经网络呢,我们这边实际上就一个节点对吧,那实际上呢我们可以搞三个节点啊,三个节点可以看到这里呢。
实际上就分别是三个节点啊,那每一个节点的一个值啊,我们都会经过这样的一个SIGMOID,都会经过这样的一个SIGMOID,那每一个SIGMOID呢,它都会输出一个0~1之间的这样的一个值,对吧好。
那么我们还是和刚才一样,假设对于第一个类别,哎他这里实际上想知道是是否是dog对吧,OK那他如果他输出一个0。12,它是小于0。5的,那我们就认为他不是狗这个类别,OK这边0。73他输出是大于0。5的。
那我们就认为它是猫的这个类别,那如果啊他是一个啊,他最后这个是0。04,它是小于0。5的,那我们就认为他不是这样的一个长颈鹿,那我们最终的结论就是A他是猫,他是猫,那这样的一个方法啊。
这样的一个输出的一个方法,还有一个优势啊,还有一个优势,假设你的这张图片里面既有猫又有狗对吧,那这个时候你去进行输出的时候,你就会发现诶,可能这里它输出的是一个0。6对吧,它是大于0。5的。
那这个时候啊,你就会也这张这张图片的一个输出值啊,实际上就也包含dog对吧,那这就是一种多分类的一种一种方法啊,多分类的方法,并且啊它还支持咱们所谓的一个多标签,也就是说我这张图片不单可以进行多分类。
还可以得到多个这样的一个输出的一个标签值,好吧,好嗯,刚才咱们这里只给了一个节点对吧,那如果我们想让我们的模型的这个,收敛能力更强一些啊,我们就可以去加一些所谓的hidden layer啊。
hidden layer在我们的这个节点之前呢,我们再去加一些其他的一些层对吧,可以加一个中间层啊,中间层,那这个中间层呢我们就可以继续啊,也是给他一些所谓的一些激活函数好吧。
例如你可以在这一层啊给他加上一个啊,ten h奇偶函数,或者是value的这样的一些奇偶函数,当然这里用SIGMOID的啊,也是可以的也是可以的好吧,好那如果啊我们这个hidden layer。
如果我们这个hidden layer啊很大,它可能等于很多层啊,很多层可能十层20层都是OK的啊,那当我们这个层数比较深的时候呢,我们又称我们的神经网络为深度神经网络,也就是咱们所谓的深度学习,好吧。
这就是我们的深度学习啊,深度学习深度神经网络,好那我们继续往下啊,继续往下嗯,这是咱们刚才看到的啊,整个这样的一个流程,咱们的一个猫对吧,给到了咱们这个单层的神经网络,然后经过了我们的SIGMOID。
最终做了这样的一个二分类啊,二分类好,那这个是我们的第一步啊,也就是拿到我们的一个输出结果对吧,拿到我们的输出结果,那接下来我们要考虑什么,刚才说的我们要去计算我们的这个loss对吧。
我们的这个输出结果,我们希望它和我们的真实的目标是,越接近越好啊,越接近越好,OK接下来的话我们就来考虑一下这个loss,Function loss function,好啊,我们考虑一个问题啊。
考虑一个问题,对于我们这里的这个嗯这个猫的这个小例子啊,我们实际上是什么,是一个二分类对吧,二分类好,那我们就以二分类来举例啊,我们以二分类来举例,假设啊,呃假设我们现在有这样的一个。
我们要求解这样的一个概率值啊,就PY等于1given x好,那假如这个值呢我们用啊y hat来表示,也就是说什么意思呢,就是说我给定我这张图片,X表示我们的图片,我给定我这张图片,那它是猫的一个概率。
我们用y hat来表示好,那对于它不是猫的一个概率,也就是PY等于零,Given x,那这种时候是不是就是咱们的一减掉y hat,对吧,这就是我们是猫的一个概率,和不是猫的一个概率,OK那这个东西啊。
实际上我们可以把它做一个这样的一个合并啊,简单做这样的一个合并,合并完之后呢,它实际上就是啊YH的Y次方,再乘以咱们的额一减y hat的一键Y次方,那为什么是这样的一个公式呢,我们可以这么看啊。
我们把这个公式给带进去看一下,假设我们Y等于一,Y等于一的话,我们看一下啊,哦Y等于一,Y等于一,那后面这一项实际上就是一减y hat的零次方,那就是一对吧,那我们最终的这个结果就是y hat。
那如果Y等于零,Y等于零,Y等于零的话,那前面这一项就是一对吧,那我们最终的结果就是一个啊一减掉y hat,那这边是零的话,那1-0的话就是一对吧,那这个东西和这个东西。
是不是就是咱们的前面的这个结果对吧,所以呢我们是可以把我们的这样的一个结果啊,用这样的就把这两个式子啊,用这样的一个式子来表示,那通常啊这个式子呢,实际上就是我们需要去求解的一个目标,那有这个式子呢。
也称为这个所谓的一个极大似然估计啊,极大似然估计,那通常呢我们会对这个式子啊去做一些处理,就取一个log,取个log,取log,它有什么优势呢,它可以让我们的这个乘法啊,变成这样的一个加法的一个形式。
那最终的话这里实际上就变成了一个Y乘以log,咱们的y hat要加上咱们的一减Y乘以,咱们的这个啊log1减y head对吧,这就是咱们的一个啊自然函数啊,自然函数,那我们的目的是什么呢。
我们肯定是希望我们的这个值它越大越好对吧,我们肯定是我们先看这里来啊,我们先看这里,我们肯定是希望对于这样的一个概率值,它越大越好嘛对吧,当然我Y输入X的时候,Y等于一的这个值我需要让它越大越好。
那X输入XY等于零的时候,这个概率值越大越好对吧,那所以啊,我们的目标就是让这个东西它越大越好,越大越好,我们要让他大啊,需要让它大,但是我们这里需要考虑一点啊,我们需要考虑一点。
如果我们要让它越大越好的话,实际上他是没有上限的对吧,他是没有上限的,那我们在反过来考虑这个问题,如果我们把它让它变得越越小呢,我们是不是就可以让它,尽可能的把这个值给减小到接近零,那如果它接近于零了。
我们就认为它是好的,所以啊我们就把我们的这个自然函数啊,进行了进一步的一个处理,也就是最终就得到了我们的这个loss function,那我们这个loss function呢,我们的y y head。
就等于啊在前面加上了这样的一个负号啊,在前面加上这样一个负号,就Y乘以log y hat,这里的话也是继续加上我们的一减Y乘以,咱们的log1减y at。
那这个就是我们最终的一个loss function,因为我们在前面加了一个负号,所以呢我们最终就变成了要让他越小越好,越小越好,那越小这个过程呢实际上就是要让它接近于零,接近于零好吧,接近于零好。
那这是我们这个啊,单条数据的一个情况我们考虑一下啊,那通常我们在训练的过程当中,我们肯定不可能就输入一条数据嘛对吧,我们肯定是要输入很多条这样的一个数据对吧,所以呢我们可以再把这里啊再展开一下啊。
所以我们最终啊最终的这个loss function,实际上啊就等于咱们的一个负的,M分之1summation,从I到M,咱们里面呢就是每一条这样的一个每一条,这样的一个每一条这样的一个值啊,一条一条的。
这里的话是咱们的IOK额,再加上咱们的一减YI和乘以咱们的log,一减y hi,这个啊就是咱们最终的哎这里漏了,最终的一个loss function啊,Loss function,这里这个M呢表示。
就是我们的一个数据的一个量啊,数据量,假设你这里有100条数据,那你应该考虑的是,把100条数据的这个loss function都要算出来对吧,loss function的指标给算出来。
但是我们肯定不能求和嘛,你肯定得取平均,因为求和的话,你100条的这个loss肯定是没有1000条的,这个loss多的,我们应该保证这个loss是在,同一个这样的一个级别的对吧,所以呢。
我们通常要是要取一个这样的一个均值啊,均值,这就是我们求解我们的这个loss的一个过程,好吧,二分类求解loss的一个过程啊,求解loss的一个过程好,那讲完了咱们这个loss的求解之后呢。
我们再来考虑一个问题啊,那接下来我们该怎么去更新我们的这个参数呢,嗯我们有哪些参数呢,哦我们再考虑一下啊,对于我们的这里这个Y啊,哎对于我们这里这个y hat,我们这里先用好,我们就用啊。
我用y hat表示吧,就啊我我就用Y表示,我就用Y表示,那我们这个Y它实际上就等于咱们的一个啊,SIGMOID也是咱们的一个激活函数对吧,然后里面就是咱们的这个权重和我们的输入的,这个特征。
加上我们的一个偏移项好,这是我们那个Y那对于我们的这个激活函数,激活函数啊,它实际上等于是的是1÷1,加上一的负的次方啊,负ZA次方好,这是我们的这个前向传播的一个过程啊。
那我们刚才也得到了我们这样的一个啊,loss function对吧,Loss function ok,那梯度下降它是在做什么呢,它实际上是这样子啊,假设我们现在的这个loss function。
它是这个样子的,假设它是这个样子的,那我们是不是希望让我们的这个loss,尽可能小对吧,尽可能小,那肯定希望诶我这个loss如果能到这个位置,那对于我们来说。
就等于是拿到了一个非常好的这样的一个loss,吧对吧,那这个时候的loss对应的这个权重啊,也就是W就是我们想要的这样的一个W,但是这样的一个值我们或者说这样的一个loss,我们整怎样才能得到呢。
这就是需要涉及到我们的这样的一个,梯度下降法啊,梯度下降法,也就是说在每一次去更新的一个过程中啊,我们首先会计算得到这样的一个loss的,这样的一个值对吧,那有了这样的一个呃,loss这样一个值之后呢。
我们呢就可以去根据我们的这个loss啊,去求解我们对应的权重的一个梯度,也就是说我们要去求解,我们的这个W的一个梯度,W的一个梯度,那这个梯度实际上就等于对我们的这个啊loss,去进行求导就OK了对吧。
进行对LOS进行求导好,那求出来我们的这个梯度之后,那那那梯度是什么呢,举个例子啊,假设我们要求的是这个点的一个梯度,它实际上表示的就是它距离,就是它的这个点的这样的一个切线对吧,它的这样的一个切线。
那这个切线的一个位置呢是距离啊,咱们最优点,它下降过程最快的一个方向,所以呢它实际上就是指引了,或者说告诉了我们的这个啊权重啊,你接下来应该往哪个方向走对吧,接下来要往哪个方向走。
那好你OK那接下来我告诉你要往这个方向走,那关键啊你要走多少,这个时候啊我们就需要引入另外一个概念,叫做学习率啊,学习率,那通常啊我们更新我们每一个权重的时候啊,W实际上是等于W乘以这样的一个啊。
贝塔再乘以咱们的这个W的一个权重啊,这是减号啊,减号啊,这里这个贝塔呢表示就是咱们的这个learning rate啊,学习率learning rate,学习力这个学习力就决定了你要走多少步。
就如果你这个学习率设置的比较大对吧,那他就可能往下面走很大一步,那如果你这个学习力设计设计的比较小,他可能就只会走一小步,走一小步啊,这个有什么区别呢,我们这边再画一个图啊,再画一个图。
如果你的学习率特别大,他可能最后变成什么情况呢,他可能就变成这样子情况,这样子的情况,他是这样子走的,那如果你的学习率比较小呢,他可能就是每次就只走一小步啊,每次就只走一小步,学习力比较大的话。
其实啊他不容易收敛到一个嗯比较合适的,或者说loss值比较小的一个点的一个情况,他可能收敛的没有,咱们这个学习力比较小的时候效果那么好,但是学习越大的话,能让我们收敛的速度变快啊。
能让我们的收敛的速度变快好,那这整个过程呢就是咱们的这个梯度下降法啊,梯度下降法好,我们再把整个流程梳理一遍啊,我们再把整个流程梳理一遍,首先呢第一步,我们是有咱们的这样的一个输入值对吧。
有这样的一个输入值,然后给到我们的模型model,model啊,给到我们的模型之后呢,我们拿到我们的这样的一个输出值对吧,out也就是咱们这样的一个结结果对吧,输入值给到我们的模型,拿到我们的输出值好。
有了我们的输出值之后呢,第二步我们就可以根据我们真实的label对吧,真实的label,真实的label,还有我们的这个输出值啊,还有我们的输出值,我这里用pd来表示这两个值。
我们就可以去计算我们的loss,计算我们的loss好,有了loss之后呢,我们可以采用我们的这个梯度下降法对吧,梯度下降法来得到我们的这样的一个梯度啊,来得到我们的一个梯度,来进行我们的反向传播。
反向传播,那反向传播的过程中呢,也就是咱们的这个执行梯度下降法的,这个过程啊,那最终呢我们就会去更新我们的这个参数啊,更新我们的参数好,那参数更新好了呢,我们要继续这个循环啊。
继续这个循环又继续走到第一步,好把X给到我们的模型,再得到输出值,好在有了输出值之后呢,再把我们的预测值和我们的标签源去计算loss,而再继续进行BP又更新我们的这样的一个权重。
那这个过程呢实际上就是一个持续循环的一个,递归的这样的一个过程对吧,直到啊,直到我们认为哎这个W已经收敛的不错了,或者说这个loss我们认为他已经足够小了,那我们就认为整个过训训练的过程啊。
我们就结束了好吧,这就是我们整个咱们的这个神经网络啊,神经网络在进行训练过程的一个流程啊,一个流程,好那说完了神经网络这一块呢,那咱们接下来的话,就来进入我们的这个第二部分啊。
我们要进入我们的这个第二部分,接下来我们来看一下,我们的这个循环神经网络啊,循环神经网络,啊我们在看循环神经网络呢之前呢,我们先来看一下,左边这个普通的一个神经网络啊。
左边这个呢是一个非常普通的一个神经网络啊,那我们先看一下啊,对于H来说,对于中间这个H啊,它实际上等于的是嗯,咱们的这个U我去先写个奇偶函数吧,我们用西格玛表示奇偶函数,然后U乘以X加上B对吧。
这是我们的一个XH的这样的一个值,那我们这里还有个输出值好,那这个输出值呢实际上也是咱们的sigma好,V乘以H加上咱们的B对吧,好,这是我们的这样的一个普通的一个神经网络啊,那循环神经网络是什么呢。
循环神经网络啊,实际上就是在中间这里啊,去加上了这样的一个环,加上了这样的一个环,可以看到啊,他这里额外多了一条路线,而这里有这样的一个W的一个权重,那有了这个W的权重之后呢,我们再来看一下这个H。
那这个H实际上啊除了咱们的这个U和X对吧,实际上还要再加上一下对吧,还要再加上一下,那这一项呢,哎这也是这一项是什么东西呢对吧,它好像还要和咱们这个W进行相乘对吧,然后和W进行相乘。
然后再最后再加上我们的偏移项,我们才能得到我们的H,OK那接下来我们就来看一下,这里到底应该输入的是什么,是什么,好我们来看一下我们呢在这里啊,把这个环给展开给展开,展开之后呢。
我们实际上会得到这样的一个图啊,OK接下来呢我们就要引入一个概念啊,一个概念叫做时间点,时间点我们用T来表示啊,用T来表示好,我们先看这里啊,这里是XTXT的意思,就是说在T时刻我输入的是XT。
那我上一个时时刻点我输入的是XT减一对吧,那下一个时刻点的话,我输入的就是XT加一,OK那对于我这里这个HT来说,它实际上就包含两个部分嘛,好我们在这里看一下啊,那这里这个HT。
它实际上就是咱们的这个U乘以XT,再加上咱们的这边过来的一个值对吧,这边过来的值,这边过来的值是什么,是HT减一乘以咱们的W,然后再加上我们的激活函数,还有我们的偏移项,就得到了我们HT的一个结果。
好那这个HT减一又是怎么得到的呢,那这里这个HT减一啊,实际上就等于U乘以XT减一,加上HT减二乘以W,加上B加上B也就是说这里这个HT减一啊,它实际上是根据是这个时刻的输入值。
还有上一个时刻的HT减二乘以W来得到的,来得到的,所以啊咱们这里的关键就在于这里的这个HT,和咱们的这个W,那大家可以发现一个问题啊,咱们这里所有的这个W啊,还有咱们这些UV,它其实权重都是共享的啊。
可以发现它其实都是同一个值对吧,它是同一个值,那这些权重啊它是共享的好吧,这些权重是共享的,它唯一的不同点就在于它输入不同,它输入不同,那为什么说RNN适合用在文本当中呢,大家考虑一下我们的文本对吧。
实际上它也是带有这个所谓的一个顺序属性的,或者说时间属性的,它是从左往右进行这样的一个输入的对吧,例如我爱自然语言处理,那它就是按顺序进行这样的一个输入的对吧,按顺序进行这样的一个输入的。
所以啊我们通常也会使用这个RN来处理文本,就是因为它自带的这个所谓的一个顺序的,一个属性,或者说位置的一个属性,也就是说它自带了个所谓的一个position,Position。
position的这样的一个属性啊,好那这个时候可能又有同学会问了,那既然如此,我一开始这个HT减一怎么办呢,是这样子啊,其实一开始啊,一开始的时候咱们这个HT减一呢。
你可以是随机给这样的一个值就OK了,好吧,随机给这样的一个值,好这就是我们的这个最基础的一个RN好吧,最基础的一个RN,但是呢其实大家也可以发现啊,现在RN其实用的并不多,更多的还是这个咱们的这个呃。
呃ISTM这一块啊啊我们先看这里吧,我们先看这里好,我们先看这里,那这里的话给大家介绍了这个RN,那RN的话,它其实会有很多种不同的一个输入和输出啊,我们先一个一个来看,那假设我们只有一个输入。
一个输出对吧,那这种情况,实际上就是我们普通的一个神经网络啊,它就是一个普通的神经网络,不同的一个神经网络好,那假如我们这个RN它有一个输入以多个输出呢,我们一个输入多个输出,那这种情况实际上是什么。
你可以简单的理解啊,它就类似于在做一些所谓的一个,续写的一个处理啊,就说哎我输入了某个这样的一个啊标题对吧,你去帮我把后文给续写出来,续写啊续写,然后我们再来看一下这个many to one。
就说我输入多个值,但是我只输出一个值,这种情况呢就是最典型的啊,就是咱们的一个文本分类对吧,我把我整段文本输入进去,你最终帮我输出这个文本,到底属于什么样的一个类别啊,文本分类好,我们再来看一下这个啊。
Many to many,那这种情况呢它其实是有一个错位的啊,他会有一个错位的,那这种情况大家可以看成A,类似于他做一些机器翻译,或者说文本摘要啊,文本摘要就说我这边输入的是一个中文对吧。
CHINESE这边输出的这样的一个ENGLISH,好翻译,那最终呢最后呢我们再来看一下这个啊,Many too many,这个many to many,和这边这个唯一的区别就在于。
它这个位置是一一对应的对吧,这边的话位置它是错开的,那这种一一对应的话,其实应用场景也很多啊,就是咱们的N1啊实体识别啊,实体识别或者说词性标注,甚至说分词对吧。
这都是一个many to many的一个结构啊,好,这就是我们RN经常遇到的一些不同的这种啊,输入输出的一些格式啊,大家其实也可以发现啊,这个RN他可以做的这样的一些,基于文本的任务很多对吧。
很多啊很多不同的一个输入输出的话,他做的这样的一个任务,他也是不一样的啊,不一样的,OK那接下来我们再来看一个概念啊,就大家其实也可以发现啊,我们其实RN用的并不多,用的多的其实还是RN的一些变体。
就像LSTM啊,或者说GRU啊这样的一些模型对吧,这些模型我们用的会更多一些,那为什么呢,就是因为啊RN它有一个非常大的一个缺点,就是它非常容易出现这个,所谓的一个梯度消失啊。
容易出现这个所谓的一个梯度消失,为什么会容易出现一个梯度消失呢,我们这边给大家详细解释一下啊,详细解释一下,当然啊这里这个问题啊,其实也是面试当中会经常问到的一个点啊,所以大家这里要哦注意听,好吧好。
那假设我们现在有啊三个时时间点啊,第一个时间点呃,第二个时间点,第三个时间点,那第一个时间点呢我们输入的是这个X1,第二个时间点输入的是X2,第三个时间点我们输入的是X3,好。
那这边呢会有输入一个H0啊,这边是咱们的一个W,而这里呢我们就可以得到我们的H1对吧,好然后进行一个输出输出的话,我们啊这里用用O1表示吧,好这是咱们的一个O1OK好,对于第二个节点。
我们可以等拿到hr,然后输出结果的话就是我们的OR,最后的话是我们的这个拿到我们的H3好,这边的话这个节点输出的是我们的O3O3呃,我们中间的权重呢我们用W表示啊,然后下面这一层呢我们用的权重。
我们用U来表示上面这层权重,我们用V来表示啊,这里大家我再重复说一遍啊,咱们这里这个UV还有W他对于每一个时刻点,他的这个权重啊,它是共享的好吧,权重是共享的,权重是共享的好。
那接下来呢我们先去看一下啊,他的一个啊求解loss的一个过程,它是什么样子的,也就是所谓的这个前向传播的一个过程,它是什么样子的,好我们先看我们一步一步来啊,我们先看这里这个H1,那这里这个H1。
实际上就等于咱们的这个啊激活函数对吧,哦还是用西格玛来表示啊,然后X1乘以我们的U加上我们的H0,乘以咱们的一个W,然后还有咱们这样的一个啊偏移项,偏移项我这里就不写了啊,我们就先啊简化一下。
我们就不写了,好这是我们的H1的一个值,然后我们再看一下O1,那我们的O1的值是不是也是一个这样的一个,激活函数对吧,然后H1乘以咱们的一个V好,这是我们的H1和O1,我们再来看一下我们的H2。
H2的话,实际上也是咱们的一个计划函数,X2U加上H1,然后W对吧,那对应的我们的O2,就等于西格玛H2乘以我们的V,然后是我们的H3H3还是一样啊,西格玛X3U加上哦H2W,然后这里是我们的O3对吧。
O3O3的话,西格玛H3乘以V2,这是我们的一个前向传播的一个值啊,前向传播的一个值,Ok,那最终的话啊假设我们这里是一个假设,我们是一个many too many的一个过程。
好吧哦many too many的一个过程,那对于也就是说假设我们现在在最后一个吧,我们以N12举例子好吧,我们以N12举例子好,那以N12举例子的话,那这里我们实际上可以得到L1,这样的一个loss。
这里也可以得到第二个loss,这里可以得到第三个loss对吧,第三个loss,那我们最终的这个loss呢实际上就是,啊咱们的这个13扫描神I从13对吧,I从13,然后LI好。
这就是我们最终的一个lost的一个值啊,最终的一个lost的一个值,OK那有了我们的loss之后呢,我们下一步是要去计算我们的这个梯度对吧,我们要去计算我们的梯度,好我们来看一下我们梯度啊。
我们呃我们取这个L3啊,我们来算L3的一个这个loss,它对应的咱们这个U和V的这样的一个梯度啊,这样的一个梯度为什么要取L3,不取L1和L2呢,大家看完就知道了,好吧好,我们fl3。
我们对咱们的这个我们先对V求导啊,我们先对V求导,也是对这个对V求导,那对V求导呢,首先第一步是不是要先对我们的O3求导对吧,YO3法O3求导,然后呢,我们的法O3再对我们的这个FV进行求导。
这样的话我们就可以拿到这里,这个V这里是U啊,好这里的都标一下,这里是V这里是U好WW好,这样的话我们就可以拿到我们这里,这个V的这样的一个啊梯度对吧,就是L3对应的这个V他的一个梯度啊,他的一个梯度。
OK这里很简单啊,这里很简单,就是一个非常简单的一个链式,求导的一个过程啊,非常简单好,那V求导简单,但是对于U求导来说,它就有点麻烦了,为什么这么说呢,我们来看一下啊。
我们five l3对于Y这个FU求导,它实际上首先是fl3对于FO3求导对吧,呃然后呢再加上我们的YO3,对我们的FH3进行求导对吧,那这里求解完之后呢,我们还得这个five h3。
对我们的five这个法U进行求导对吧,法U进行求导好,这样的话我们就把U的一个导数给求出来了,但实际上我们并没有求九啊,为什么呢,我们换个颜色啊,我们这里求出来的导数,只是这一条路径上的对吧。
只是这一条路径上的,但实际上啊我们这边还有一些U啊,我们这里也还有U对吧,这些U对我们最终的这个L3的一个结果,都有一定的一些影响,所以我们的我们在求解U的梯度的时候,还得去考虑这些路径上的一些优哎。
但是有同学就会说哎,那为什么我这里这个V就只求解这一个地方呢,因为这些地方的V,它只对这里的L1和L2造成影响,它并没有对这里的L23造成影响,所以我们求V的梯度的时候,只需要求解这个V的梯度就OK了。
好吧,所以啊当我们求U的梯度的时候呢,我们现在这里啊只是第一个U的一个梯度,我们还得去求第二个时刻和第一个时刻对应的,这个U的梯度好,那我们就继续加嘛,OK前面的话就还是fl3。
five o3还是一样啊,前面是一样的,这里是five o3,five h3好,到这里就会有点不一样了,那接下来的话我们实际上是要走,这边就要往回走一步了对吧,往回走的话。
那就是five h3对FH2进行求导,那到这里才是法H2对FU就行求导对吧好,这是第二个时刻的U的梯度,接下来我们看第一个时刻啊,第一个时刻其实也是一样啊,fl3FO3乘以FO3,Y h3,Y h3。
Y h2,最后这就是法H2对法H1进行求导,然后法H1再对我们的法U来进行求导啊,进行求导,那这到这里呢,我们整个求导的一个过程啊才结束了结束了,所以说啊对于咱们的这个过程,它其实还是挺复杂的。
挺麻烦的对吧好,那接下来我们把他的一些这一块啊,我们可以看一下,就这一块啊,这里它实际上会有一些这样的一个重复项对吧,这一项它是一个重复的,就这一项他也是这样的一个重复项,那这两项呢取决于什么。
取决于你的序列的一个长度对吧,假设你的序列长度越长,那你在求解这个U的梯度的时候,你中间的这一项它就越长对吧啊,那这里我们可以简单做一个合并啊,合并那合并完之后呢。
最终咱们的这个phi LT对FIU进行求导之后,他的一个梯度实际上就是法LT除以FUT,再乘以我们的five ut除以咱们的法,这个通过48小时核酸哎,等一下啊,这里写错了啊,这里不是U这里是啊。
我们的O啊,这是我们的OOT这是O写错了,反OT在对我们的这个啊HT进行求导对吧,HT求导进行求导啊,这是我们前面这一项嘛,这是我们的前面这一项对吧,那关键是中间这一项。
那中间这一项我们实际上啊就可以去对他这个,求基好,那这里的话我们用下标,用J来表示啊,我们从J道题那里面呢,实际上就是咱们的这个FHJ,再对我们的FHJ减一,进行这样的一个求导对吧。
这个呢就是我们中间这一块啊,中间这一块,但是啊这里大家需要考虑一下,我们这里实际上是什么,是有三个部分吗,是有三个部分对吧,我们这里是有三个部分的,那三个部分的话,那我们。
前面这里前面这一块我们是可以提取出来的嘛,对吧,前面这一块我们可以提取出来放到前面吧,所以呢后面这一块啊,我们实际上还有一个相加的一个过程对吧,所以我们这里还有个相加的一个过程啊。
所以这里啊我们还有这样的一个扫描声,这里还有个扫描声,然后我们这里用啊用K来表示啊,K从一到咱们的一个T,那这里这个J呢,实际上是从咱们的K加一开始啊,K加一开始,那这一项呢就是咱们对应的。
咱们蓝色框里的这一项对吧,然后最后是咱们的这个啊,最后这一项啊,最后这一项,那最后这一项呢实际上就是咱们的这个FHK,再对咱们的FU进行求导就OK了啊,就OK了,那这个过程就是我们最终的一个这个哎。
这里写错了啊,这里是怎么回事啊,这个地方写错了,这个地方就是FU对吧,我在我这写的啥,L对U求导,T对OO对HT好,这就是我们最终的一个梯度啊,这是我们最终的一个梯度,OK那看到这里之后呢。
我们来考虑一下,那为什么说RN容易梯出现梯度消失呢,我们看一下这里啊,我们看一下这一块,这一块是HJHJ对HJ减一求导,也就是说他是在对这个链路上进行一个求导,那这个链路他做了什么事情呢。
它其实就是一个激活函数对吧,是这样的,西格玛我们可以看到啊,他这里会有这样的一个西格玛,那在我们的RN或者说呃在我们RN当中啊,我们通常使用的一个激活函数,要么是这个SIGMOID。
要么是这个ten h啊,那这两个激活函数,它有它有什么样的一个问题呢,我们可以再简单回顾一下那个SIGMOID激活函数,它什么样子,他是大概这个样子的对吧,大概是这个样子的诶,画的不太好啊,这是0。
5这个奇偶函数,大家可以看一下啊,他的这个梯度啊,它是很容易就是说他这个梯度,它容易很容易出现一个比较小的这样一个值,对吧,他这个梯度也是一个0~1之间的,这样的一个值,它梯度很小。
梯度很小好OK那假设我现在这个梯度,我现在这个梯度假设啊求解出来它是0。1,0。1,那我们再假设我们这这个这里,这个T也就是说这里是个T啊,假设T等于一五十,T等于50的意思。
就是说我这个序列长度是50对吧,那我们这里这里就我们这里啊,这一块求解出来的梯度就是0。1的50次方,50次方这个东西是不是就趋近于零对吧,那你的梯度就会变得很小,你梯度变得很小,会出现什么问题呢。
梯度变得很小,你咱们刚才这里说的对吧,你每一次这个值都特别的小,特别小,特别现在已经接近于零了,对吧,那就等于你这个W就很难去更新,你每次虽然就算你更新100次,1000次。
但是你每一次的值基本上都是零,就等于你这个W没有怎么更新,所以你模型就会很难收敛啊,你的模型就会很难收敛好吧,这就是RNN当中的一个所谓的一个,梯度消失的一个问题啊,RN当中的梯度消失的一个问题。
那怎么解决这个问题呢,或者说怎么有没有什么办法能缓解这个问题呢,这就是我们接下来要给大家讲的这个LSTM,ASTMASTM呢,又被称为这个所谓的长短期记忆网络啊,它能有效地去学习一些长期依赖的关系啊。
也能有效的去啊缓解梯度消失的问题,这里不能说解决啊,这里我改一下,这里应该说缓解缓解梯度消失的问题好,那接下来我们就给大家介绍一下,这个LSTM啊,给大家介绍一下LSTM,啊第一个图呢是咱们的这个啊。
RN下面这个是我们的LSTM可以看到啊,RN的结构还是非常简单的,但是对于LSTM来说,里面其实有很多这样的一些计划函数对吧,这里有SABOID,有ten h,这里这个西格玛表示就是这样的一个西格玛啊。
西格玛id啊,这里我也简单说一下,哎,有同学会说这个torch,这个激活函数是什么东西啊,我这里也简单画个图啊,咱们SIGGMOID,它是,所以咱们SIGMOID是啊。
在这个都是大于零的一个这样的一个值对吧,但是tan值呢它其实是关于原点对称的啊,他是这样子的,它是这样子的,它是它是经过原点的啊,画的不太好,他是经过原点的,那C格MOID的话。
它是全都是这样的一个大于零的一个值啊,好那接下来的话我们就把这个LSTM啊,展开详细看一下啊,我们展开详细看一下,首先呢LSTM这个模型啊,它额外添加了一个叫做细胞状态的一个东西,它是用C来表示啊。
在我们的RN当中,我们只有一个H对吧,用H那我们通常称这个H叫做hidden state,隐藏状态啊,隐藏状态,那在我们的这个LSTM当中多加了一个cell state,细胞状态啊。
细胞状态我们这里用C来表示它,其实hidden state也有对吧,在下面这里啊,在下面这里,那这里这个cl state呢,就是这个图当中的上面这一条线啊,上面的向右的表示的就是sales state。
它传递的一个过程,那这个sales state什么东西呢,我们详细来看一下啊,详细来看一下好,我们先在先看这个sales state之前呢,我们先来了解几个概念啊。
几个概念叫做门LSTM一个比较关键的东西,就是它有一个所谓的一个门的一个机制啊,门的一个机制,这个机制是什么意思呢,我们来看一下啊,就是说LSTM啊,它能决定我当前哪些值需要保留,哪些值不需要保留。
我们可以先看一下下面这里这个例子啊,我们可以先看一个例子,就是说假如我现在有句话叫做他今天有事,所以我当处理到我这个字的时候,我们实际上希望看到的是说,我们这个模型能把我之前的这个主语。
它就是1万了就不要了对吧,1万了不要了,要保留我对吧对吧,这个时候我们应该更加关注的是我,而不是他那1万门,也是我们LSTM当中的第一步啊,也就是这一块它的作用就是把它这个字给忘了,他是怎么忘的呢。
我们看一下啊,首先呢这是我们的上一个时刻的hidden state HT,是我们当前时刻的一个输入值,我们把当前时刻的一个输入值,和我们上一时刻的这个hidden state啊,进行这样的一个拼接。
拼接完之后呢还是一样啊,会有这样的一个权重进行相乘,要加上我们的偏移项,然后经过SIGMOID的层,刚才说了SIGMMOID的层,他是输出一个零一之间的一个值对吧,它输出的是一个零一之间的一个值好。
说白了就是说我这里我这里啊,就是输出这样的一个零一之间的这个值,那如果这个值它接近于一,它接近于一,意思就是说我会把之前的内容保存下来,如果接近于零,就等于是把之前的内容完全就给遗弃了。
那如果他是一个0。20。6,意思就是说我之前的值要保保留20%,保留60%,就这样的一个思路,好这是我们的一个遗忘门啊,遗忘门,那接下来我们再来看我们的一个输入门,那刚才我们把一部分内容给遗忘了对吧。
但是上文的其他内容,我们还是得留一部分下来嘛对吧,我们要留,把留下来的内容作为我们的一个输入对吧,作为我们的一个输入好,那怎么作为输入呢,其实也很简单啊,还是把刚才的hidden state和当前时刻。
我们的这个输入值啊,先作为拼接,然后给到我们对应的一个权重,好这里大家可以发现诶,我好像计算了两个部分咳,第一个部分和刚才的一样,他也是一个门,因为他是一个SIGMMOID的。
他还是输出一个零一之间的一个值,那对于第二部分,我们经过的是ten h这样的一个激活函数,大家可以理解为,我把输入和上一时刻的hidden seat,去做了一些非线性的一些变换,然后呢我就得到了。
再把这两个部分啊,会去做一个所谓的一个相乘的一个操作,可以看到这里我做了一个相乘的一个操作,也就是这里啊IT乘以CT德尔塔,那这里这个相乘实际上表示的是什么,就是我ct是我当前时刻的一些输入值对吧。
我这里这个i it是这样的一个门,比如说当前这些东西,我哪些东西要保留下来对吧,这个就是我们当前要表保留下来的一些值啊,当前保留下来的一些值好,我们再看这一块,这里是FT乘以T减一。
CT减一是上一时刻的sale state,ft t是我们刚才这里说的1万门对吧,1万门,那这里的意思就是说,我要把我之前的这个ct减一保留下来,多少遗忘掉多少对吧,所以说啊这里我们进行相乘对吧。
就是这一块这里进行相加呢,就等于是把我们上一时刻经过遗忘门之后的,一个值,和当前时刻,经过了咱们门之后的这样的一个值,进行了一个融合,这样呢我们就得到了我们当前新的这个时刻的,Sales state。
好吧,好再说一遍啊,这个ft t,第一个ft t是我们的之前的一个,1万门的一个值,这里这个cat减也是我们上一个时刻的cell state相乘,表示。
就是说我要把之前的sales state遗忘掉多少,那后面这一块it是我们当前的这个输入的,这个值,我需要保留多少,那c ct t尔塔的话,是当前的输入值的一个非线性变化。
这两块相乘意思就是说我当前的输入值,我需要输入哪些内容,保留哪些内容,最后再把这两者进行相加,意思就是说,我要把之前的上一个时刻的剩余的内容,和我当前的输入的内容进行合并,在一起就是这样的一个意思啊。
这就是我们的一个输入门啊,那这样的话我们就可以得到当前时刻的一个,sales state啊,sales s那有了sales state的之后呢,我们还要考虑一下,我们也还有这样的一个当前时刻的HT。
我们还没有算吧对吧,所以接下来我们就来输出门,看一下我们当前时刻的这个HT唉,怎么进行计算,好我们看一下啊,他的他的这个思路,其实还是延续,咱们刚才这个门的这样的一个想法啊。
首先呢还是把我们上一时刻的hal hidden state,和当前时刻的一个输入啊进行拼接,进行非线性变换哦,不是非线性变化啊,经过我们的个SIG格MOID的,那。
这个时候实际上又是一个01之间的一个值,对吧,01之间的一个值好,然后呢我们会把刚才的这里这个值啊,这个这里我们是已经拿到了这个cell set对吧,当前时刻的cell set。
我们会把当前时刻的cell state经过这个ten h啊,经过ten h经过完twitch之后呢,说白了就是把cs state做了一个非线性的变换对吧,再和这样的一个门之后的一个结果进行相乘。
而作为当前时刻的一个hidden state,作为当前时刻的一个hidden state啊,这里的意思就是说我当前要进行输出了对吧,但是呢我现在有了我们啊,上一时刻的这些sales state,然后呢。
我是不是应该考虑一下我哪些应该输出对吧,我们这里也可以看一个例子啊,假设啊有这样的一个例子啊,the cat会说ready at was full,当处理到was的时候,由于前面获取的主语是cat对吧。
那我们这里肯定就要用was,那如果我们前面这里是cats呢对吧,如果是cats,那我们后面这里就应该用were,就这样的一个意思啊,就这样的一个意思,这就是我们的这个LISTM的一个输出门啊,输出门。
好最后呢我们再来简单看一下,关于为什么LSTM,它能解决这个所谓的一个梯度消失的,一个问题啊,那这里呢是我们的这个啊sales state,它求解这个梯度的过程的时候,它的一个公式啊,它的一个公式。
其实大家对比的时候就可以发现啊,我们这里这个sales state它其实它的一个梯度啊,它是一个相加的形式对吧,它是一个相加的一个形式,那我们这边的这个RN,它是一个纯相乘的一个形式对吧。
然后我们再再注意一点啊,他这里啊它有一个FT这一项,也就是说这里这个ft t是啥,这个ft t表示的是我们这里,这个这里这样的一个值啊,也就是说我们的这个遗忘门他的一个输出值。
那这个值它是个0~1之间的一个值,所以说啊就算你前面这些地方,你都是一些相乘的对吧,你这些前面这些地方就算乘,假设我你这三个部分假设是一个0。0,000001接近于零的一个值。
但我最终这个FT它是一个01之间的,一个值,是一个01之间的值,它可能是0。1,它可能是0。2对吧,当然他也有可能是0。01也是有可能的,但是啊就是因为它这里是一个相加的一项。
他就就算你前面这些全都是零,我也能保证你最后这个值,它是一个0~1之间的一个值,但是它不会特别接近于零,就以这样的一个形式啊,来缓解咱们的一个梯度消失的一个问题,注意这里是缓解啊,这里是缓解。
假设你最终这里这个ft t,你求解出来也是一个零,点000001的一个值对吧,非常接近于零的值,那其实他也没有办法完全解决,这个梯度消失的问题啊,所以说咱们说的是缓解,好吧啊,我这里这个标题也改一下。
缓解啊缓解好,这就到这里的话,我们就给大家嗯介绍完了这个LSTM啊,我们就介绍完了LSTM,那接下来的话我们再来看我们的啊,下一个部分啊,下一个部分咱们的这个卷积神经网络啊,卷积神经网络,那。
好我们来考虑一下啊,就对于RN这样的一个模型来说,那除了刚才说的这个,所谓的梯度消失的一个问题啊,他其实还有个问题啊,就是他时间复杂度,时间复杂度比较高啊,它的时间复杂度是ON。
因为它是一个创新的一个过程对吧,它是一个从左到右,它需要一个节点,一个节点的去进行这样的一个处理,它是一个创新的过程啊,创新的过程你序列长度越长,它处理的时间点就越多对吧,花费的时间就越多。
那对于我们的这个呃,文本分类的一个任务来说啊,我们其实刚才也说过啊,我们在这里的时候,我们通常如果要去做文本分类对吧,把每一个词进行一个输入,X 1x2,一直到XN进行输入。
然后要取的是最后一个时刻的一个这个值,用这个out值来进行我们的文本分类,所以说啊他很耗时,那既然如此,我们是有没有可能采用一些并行模型的,一些思路,例如像咱们的一个CNN模型对吧。
它其实就是一个并行的一个思想,咱们的我们来看一下啊,如何使用我们的这个卷积神经网络,来加速一下我们这个RN的一些缺点啊,大家可能都会觉得,这个卷积可能更适合去处理图像对吧。
但实际上啊在文本当中他处理的也非常的多啊,非常的多好,那我们来看一下,如果我们使用这个卷积神经网络,是怎么去处理文本的好,那我们这里假设有一句话啊,叫做他毕业于上海交通大学这样一句话。
那我们分词分完之后呢,它一共有六个词啊,六个词对于on n来说,它实际上每次处理的是一个字对吧,这样哎或者说一个词诶,先输入它,然后输入毕业,输入渝,再输入上海,ok now啊。
那个如果我们使用的是卷积神经网络,卷积神经网络,它就有一个优势啊,他可以干什么,他可以去处理你的这个所谓的更大力度的,这样的一些特征,例如我可以去处理,把这个他毕业于这三个词放在一起,一起去提取特征。
毕业于上海三个词放在一起去提取特征,还有最后这样的一个上海交通大学,我可以把把这三个词放在一起一起来提取特征,但是对于RN来说,他就没有办法做到这样的一个情况,那为什么卷积可以做到这个所谓的这种多词。
或者说短语级别的一个特征的一个提取呢,那接下来我们就来详细给大家介绍一下,卷积神经网络啊,我们就详细介绍一下,在介绍卷积神经网络之前呢,我们先了解一下什么是卷积,什么是卷积,通常啊我们就称为F乘以G。
就是对于F和G的一个卷积,好好像很难理解是吧,很难理解,好不着急,我们慢慢来看啊,如果我们现在这个是一个连续的啊,如果是一个连续的一个情况,它实际上就是求解积分的一个过程,那如果是一个离散的一个情况呢。
我们就是要去对我们所有的情况啊,去求和求和,但是看完这个公式,好像还是非常难理解这个卷积到底啥意思对吧,没关系,我们慢慢来,我们可以先看一个例子啊,假设我们令啊X等于啊掏,然后Y等于N卷套。
那么X加Y等于N啊,就是下面这条线可以看到啊,我们有这样的一条线,这条线那这一条线它实际上就好比什么呢,就好比我们把一条毛巾啊,沿着左下角的这样的一个角,就往右上角去卷去卷,那这个卷的过程呢。
我们把它称为这样的一个卷积的一个操作啊,这个过程我们把它称之为卷积的一个操作,我们再看一个离散的一个例子啊,我们看一个离散卷积的一个例子,这个例子看完,大家就能对卷积有一个更直观的一个理解了。
假设呢我们现在有两个啊,两个桃子啊,这两个桃子呢我们希望啊扔到的点数,它加起来是四的一个概率,就是我们要求解啊,加起来是四的这样的一个概率,那我们用F来表示第一个,用G来表示第二个。
那F1呢表示的是投出一的一个概率啊,F2F3的话就以此类推,G也是啊,G1的话就是表示我扔出就是第二个这个投资,扔出一的这样的一个概率值啊,好那我们啊就来计算一下啊,计算一下,OK那我们来看一下。
如果我们把所有的这个这个这个啊是就相加,他的这个概率是咱们的这个,四的这个投资的这个情况啊,给算一下啊,首先呢是咱们的第一个骰子,扔到一的一个概率值,要乘以咱们的第二个骰子扔到三的一个概率值。
然后再加上我们扔到二的一个概率,分别扔到二的对吧,还有情况呢是我第一个投资扔到三,第二个投资扔到的是一的一个概率值对吧,我们要进分别进行相乘再相加,那这个呢实际上就是我们两枚骰子。
点数加起来为四的这样的一个概率对吧好,那接下来呢我们把它改变一下啊,改变成我们卷积的一个定义,它实际上就是,表示为F4减M再乘以gm,然后前面是一个累加扫描ATION。
那这个啊实际上就是我们的一个卷积卷积,那再解释一下,说白了他就是先相乘再相加对吧,先相乘再相加,这就是我们的一个卷积啊,卷积我们也可以回到我们一开始的这样的一个,离散的一个公式,可以看一下对吧。
它实际上就是一个先相乘再相加的一个过程,这就是我们的一个卷积操作啊,卷积操作好,那有了这样的一个卷积计算的,这样的一个概念之后呢,我们再把这个卷积啊,拿到我们的图像上面来看一下啊,下面呢这里有一张啊。
噪点非常严重的一个图片啊,如果我们想去做一个所谓的去噪的一个处理,我们就可以把这个采用一个卷积的一个方式,我们可以把高频信号啊,以周围的一些数值去做一个,平均的一下的一个处理,怎么做呢,好举个例子啊。
假设这是我们的这样的一个图片啊,这是我们的一个图片啊,我们要去平滑这个A11这个点,它周围的这些加速点,OK那我们就把A11附近的这些像素点啊,全部给取出来,取出来取出来之后呢。
我们可以得到这样的一个矩阵F啊,我们的一个矩阵F,接下来我们去定义这样的一个啊卷积核,也就是用G也是我们的卷积卷积核啊,这个卷积核因为我们刚才说我们如果去造的话,就是取个均值对吧。
那我们就把所有的卷积核的每一个位置,都设置为1/9,然后呢我们再把这个这里这个F啊,和我们的这个G进行相乘再相加,也就是说A00乘以我们的19,加上A01乘以我们的19,再加上A02乘以我们的19。
就对位相乘再相加,最终啊我们对位相乘相加之后呢,我们就可以得到一个所谓的,卷积之后的一个结果啊,卷积之后的一个结果,这就是我们在图像当中去做的,这个所谓的卷积的一个处理啊,卷积的一个处理。
啊这就是我们可以看一下啊,这是我们的一个啊卷积的一个动图,左边呢是我们这样的一张图片啊,中间是我们的一个卷积核,那这个卷积核呢在这里啊,我们只是对我们图像的这一个部分,做了卷积处理对吧。
但是你对这一个部分做完卷积处理之后,其他地方你其实也需要做卷积处理,这个时候呢你就要需要去移动你的卷积核对吧,我们可以看一下啊,我们这个动图是啊,先向这边先向右移对吧,然后再向下移进行移动。
你看第一次卷积完了之后向右移一个单位,做一次卷积,再往右移一个单位,再做一次卷积对吧,直到移不动了,我们再往下进行移动,这就是我们完整的一个卷积的一个过程啊,卷积的一个过程,好那有了卷积这个概念之后呢。
我们来看一下卷积神经网络啊,那卷积神经网络,实际上呢就是在寻找最合适的一个卷积核,那刚才我们是要去造对吧,那去噪的卷积核就求均值就OK了,但是我们想一下哈,如果我们现在是在处理我们的图片。
或者说我们在处理我们的文本,我们想去做这个所谓的分类,或者说图片识别对吧,那我们就应该去找到最合适的一个卷积核对吧,那如何去找到最合适的一个卷积核呢,这个是不是就是我们刚才给大家介绍。
神经网络那个部分给大家提到的对吧,先计算我们的loss,要去求解我们的这个梯度,要进行反向反向传播,更新我们的权重对吧,那在我们这里其实也是一样嘛,我们的卷积核实际上就是我们的W。
我们只需要根据我们的目标得到我们的输出值,要求解我们的loss,再根据loss进行反向传播,就可以更新我们卷积核的一个值对吧,这样的话我们就可以得到我们最合适的卷积和,好我们可以看一下这里这个图片啊。
啊左边的话是我们的一个输入的图片,右边的话是我们的一个卷积核啊,啊右边的话是我们得到的一个结果啊,得到一个结果,然后红色的话啊,红色这里乘以1×0乘以一,就是我们对应的一个卷积核啊。
那右上角这一个卷积核和黄色这一块,进行卷积之后呢,得到的一个结果就是四啊,就是四对位相乘再相加啊,好这就是我们卷积神经网络好吧,卷积神经网络,那接下来呢我们再看一下啊,如何把这个卷积神经网络。
应用到我们的这个文本当中呢,好接下来而我们这边有这样的一句话啊,这句话我们做了一个分词,1234567好,我们分成了七个词啊,这句话我们分成了七个词,分成了七个词。
那每一个词呢它有对应的这样的一个embedding,就上节课我们去讲那个word vector的时候,给大家讲过吧对吧,就每一个词我们可以把它转换成这样的一个,embedding的一个形式,那在这里呢。
它每一个词的这个embedding是四维的啊,四维的,所以说我们的一个输入啊,就是一个7×4的输入,就是7×4的好吧,7×4的,接下来呢我们就会去定义一个这样,所谓的一个卷积核啊,卷积核。
那这个卷积核它需要有两个维度对吧,第一个维度的话是我们这个序列长度,这个方向的一个维度,第二个维度的话是他的这个embedding,这个维度对吧,这里大家就需要注意一下啊,对于他的第一个维度。
你是可以自定义的,你第一个维度你可以是二,你可以是三,你可以是四,但是对于第二个维度,你必须和文本的这个embedding,这个维度保持一致,也就是说你必须设置为四,为什么呢,假设你的这个维度小于四。
那你这个卷积核它可能是什么样子呢,就变成了这个样子,那你这样的一个卷积核,你卷积出来实际上是没有意义的,因为你这个词你没有把这个词,它完整的这个embedding给加进去,你没有加进去的话。
你这个词的这个语义可能会改变对吧,所以你在做卷积的时候啊,你要把当前这个文本的embedding,全部给包含进去,你才能拿到当前这个文字或者这个词,它完整的一个语义,好吧,这里是关键点啊。
大家必须注意一下,这个维度必须保持统一,第二个维度是多少,取决于你输入的文本的embedding的维度是多少,好吧,好我们再看我们的第一个维度啊,那对于第一个维度来说,就得看你想去取多大力度的一个特征。
就像我们刚才这里给大家举的那个例子,如果你每次想取得是一个字,一个字或者说一个词一个词的特征,那你就设置为一,那对于我们这里,我们这里取的这些是短语,它是三个词对吧,那你就把你的卷积核大小设置为三。
如果你想取两个词,那你卷积和大小就设置为二,所以啊,这就是得到了我们最终的这样的一个卷积核啊,那这个卷积核实际上就是一个3×4的啊,3×4的好,那我们就把这个卷积核在我们的这个文本上啊。
去做卷积的一个处理,最终呢我们就可以得到这样的一个输出值,这样的一个输出值,第一个输出值的话就是前面三个词,它的一个前面三个词啊,然后这这个值呢就是又是这三个词,这三个词,对于最后这个啊就是最后三个词。
他的一个卷积之后的一个结果啊,这就是咱们的一个卷积啊,卷积OK那了解了这个卷积的一个概念之后呢,我们再来看一个东西啊,对于我们这里来说,我们可以看到啊,我们做了卷积操作之后呢。
我们这个序列长度从七变成了五对吧,但是大家可以考虑一下啊,就有些情况,假设我现在是要做N12,我要做N12,我们的输入和输出必须长度保持一致对吧,那你这里缩短了不行啊,那如何才能保证这个长度不变呢。
我们就可以在头和尾啊去补充一个padding位,也是补零,只要你补零之后呢,我们这里一开始的这个长度啊,就由七变成了九,但是啊我们经过卷积操作之后呢,它的这个长度就还是七啊。
就和我们原来保持一样的保持一样,为什么它会一样呢,因为我们每次做卷积的时候,就是从这里开始了对吧,我们之前的话是从这里开始的好,这就是我们补padding啊,补padding。
那看完补padding之后呢,我们再来看一个概念啊,叫做mari china,在五处理图像的时候呢,图像它是一个RGB3原色的对吧,所以呢我们通常处理图像的时候,我们会有最少你得准备三个卷积核对吧。
分别处理RGBRGRGB的一个通道,那对于文本来说其实也是一样嘛,你可以多准备几个卷积核,你卷积核准备的越多,你提取的这个特征维度就越多对吧,那这里的话,我们就等于是准备了三个这样的一个卷积核啊。
三个卷集合,然后再加上我们的padding,那正常情况来说,我们只能得到一个啊啊77×1的对吧,7×1的这样一个矩阵,那三个矩那个卷积核的话,最终我们就可以得到7×3的这样的,一个特征啊。
7×3的这样的一个特征好,这是我们的一个多通道,多通道,好接下来我们再来看一个概念叫做池化操作啊,池化操作,那我们这里多个卷积核,我们能达到了一个7×3的这样的一个矩阵。
但如果我们要最后去做一个二分类对吧,假设我们要去做文本二分类,你肯定不能给我一个7×3的呀对吧,你肯定得给我一个啊7×1的,或者说七乘几的对吧,你不能,总之你不能给我一个多维的呀。
我你只能给我一个一维的一个向量,我能才能去作为一个分类吗,你不能给我这样的一个7×3的对吧,所以呢我们这边就会做一些所谓的池化操作啊,这里呢我们采用的是一个最大池化层,就说我们去吧。
当前这个里面啊它最大值给取出来,这一列里面最大值给取出来,这是0。3,然后这边取出来是1。6,这是1。4,所以最终我们就能得到了一个,一维的这样的一个向量啊,一维的一个向量,这是我们的最大池化层啊。
最大池化层,好那我们接下来来看一下啊,这个卷积的这个过程怎么去计算,我们输入的这个值,经过卷积之后,它输出值的一个维度呢,啊我们以图片举例啊,假设我们输入输入的图片大小是W乘以W。
我们卷积核的大小是F乘以F,那不长是S不长是什么意思呢,就是说你每次移动多少步,有的时候呢你可能会移动一步,但是有可能你也会移动两步三步对吧,然后还有一个是padding啊。
padding我们用P来表示,OK那假设我们现在不padding啊,如果我们不padding,那我们的这个输入和输出的一个这个维度,大小呢,这是win的话是我们的一个输入输入啊。
就是输入减掉我们卷积核的一个大小,再除以我们的S也是咱们那个步长,而加一就是我们输出解输出的这个啊长度啊,那如果我们要保持不变的话,那就是我们输入的一个维度,再加上二乘以padding。
因为padding你前面要补,后面也要补对吧,所以你要乘以二,然后再减掉我们的这个filter的一个大小,再除以我们的步长,再加上一,这是我们的输出的一个维度的一个大小啊,好到这里的话。
我们就给大家啊把这个卷积神经网络这一块啊,咱们就讲完了啊,讲完了,今天的话到这里的话,基本上就是要给大家讲的所有的啊,这个理论方面的一个内容啊,理论方面的一个内容,那接下来的话。
我们就进入到我们的这个实战环节啊,我们给大家介绍了这个卷积网络,又给大家介绍了这个啊循环神经网络对吧,那我们就来应用一下啊。
应用一下好,我们进入实战环节啊,实战环节。
额,接下来我们来看一个基于LST作战的一个,文本分类的这样的一个小例子啊,看个小例子好,我们把字体调大一点,OK好我们可以看一下啊,我们啊从TRA方法开始看吧,好这个处理方法当中呢,首先呢。
我们会去进行这样的一个数据的一个加载啊,我们会去加载一个数据加载数据,然后呢去啊拿我们的模型,我们先看我们的这个加载数据这一块吧好吧,我们一步一步来好,呃加载数据这边呢我们是从本地这边啊。
加载了一个这样的一个啊,情感分析的二分类的一个数据啊,我们可以简单看一下,蒙牛真果粒美丽有新意,这是一个正例啊,还有什么密密麻麻孩子不喜欢,这是一个复利啊,呃总之是个二分类啊。
咱们情感分析的二分类一的话是正理,零的话是咱们的一个负理啊,负理好,那我们就来看一下啊,我们看一下这个load date这个方法,先看一下load date这个方法,首先呢我们去把这个文件给读取出来啊。
然后循环每一行,循环读取每一行啊,今天的代码因为比较多啊,可能我就没有办法全部带着大家写了,好吧,我我们就把一些关键代码会,给大家详细讲一下啊,好这边循环每一行代码,那每一行代码呢。
我们这里是根据这个啊tab键啊,进行这样的一个区分,这样的话我们就可以拿到我们的这个标签,还有我们的文本啊,拿到我们的标签,拿到我们的标签和我们的文本好,那有了标签,有了文本之后呢,我们考虑一下啊。
我们上节课给大家讲这个word to vector那块的时候,说过啊,我们需要先构建一个词典对吧,我们需要有构建一个词典,那构建词典呢怎么构建呢,首先第一步肯定是需要进行分词嘛对吧。
那我们就去便利一下啊,我们所有的这样的一个文本,然后把便利出来的文本呢,去做这样的一个分词的一个处理啊,分词的一个这样的一个处理啊,我们这里可以看一下啊,这里是好token nice。
这个方法我们去看一下啊,可以看到啊,这个token ize呢,其实就是调用了一下结巴的这个分词啊,调用了一下结巴分词,结巴DOCUT就可以进行分词了啊,给你分词好,这边的话。
我们就拿到了我们所有的这个分词的,一个结果啊,这里大家需要注意一下,这个分词的结果是一个list,然后list里面呢又是list,那内部的这个list呢,就是一个一个的这样的一个分词好吧。
那接下来呢我们去定义这样的一个词典啊,定义一个词典,这边呢我们就开始对这个分出来的这个词啊,去进行一个遍列,然后呢我们去统计一下每一个词,它的一个词频,统计一下每一个词的一个词瓶啊,统计词频好。
统计完磁瓶之后呢,我们去根据这个词瓶去做这样的一个呃,降序的一个排序啊,因为我们说过啊,我们要把这个词平比较高的排在前面,词平比较低的排在后面啊,排在后面,这样的话我们就排好序了,排好排好序之后呢。
我们要来定义我们的一个词典,这个词典当中呢我们需要两个标记位啊,这个也是在我们上一节课给大家讲过的,一个呢是pad标记位,表示的是我们这个补零的对吧,一个是UNK标记位,UNK的话就是啊OV的一些词。
我们就用UNK来表示对吧,好这是我们前两个词啊,那后面的一些词呢,我们就去便利我们的这个排好序的一个,词典当中,排好序的这个词啊,把这些词加到我们的词典当中,这样的话我们就能拿到我们的一个词典,好。
我们这里可以给大家看一下,我们这个词典什么样子啊,好稍等一下啊,OK我们把这个词典展开看一下啊,它实际上就是这样的一个啊字典的一个格式,对吧啊,key的话就是我们对应的这个词。
value的话就是它的一个下标对吧,就是它的一个下标,那我们输入一个这样的一个词,就可以拿到它对应的一个下标的一个值啊,这就是我们的一个词典,这是我们的词典好,那有了词典之后呢。
那接下来的话我们就要去做什么事情呢,是不是要把我们的这个训练的一个数据,先转换成我们的一个下标对吧,我们就要便利便利我们每一条数据啊,把这个数据转换成一个下标,好,我们就来看一下这个文本转下标。
这个函数它是怎么写的啊,首先还是一样,我们先分词,分完词之后呢,我们去遍历每一个词对吧,然后根据我们的这个词典get的话,就是根据我们的key把value给取出来对吧,如果取不到。
那我就取一这个一为什么是一呢,因为我们UNK表示对应的是一,所以我们这里是一好吧,这样的话我们就把我们的这个下标啊,给取出来了,取出来之后呢,我们要去做一个padding的一个处理对吧。
padding的一个处理好,这里我们也看一下这个函数啊,也很简单啊,这边先去便利我们每一个句子啊,遍历每一个句子,那如果我们这个句子的长度,是小于我们最大长度的,我们这个最大长度测了个十啊。
如果我们这个句子的长度小于了最大长度,那我们就需要补零对吧,补零怎么补呢,那我们就去做contact at嘛,把我们的X和零进行一个拼接,拼接多少个零呢,拼接的是最大长度。
减掉我们当前文本长度的这个长度的零好,这样的话我们就可以把短的补偿对吧,那我们再看一下啊,如果我们这个长度它是大于这个最大长度的话,那我们就截取对吧,我们就截取,这样的话。
我们就做了这样的一个补偿的一个操作啊,这样的话我们所有的文本的长度就能保持一致,接下来呢我们再把我们的这个输入值,还有我们的标签给到我们这个啊,Tensor dataset。
这个DATASET是干什么的呢,大家可以把它看成他就是这个所谓的这样的,一个list的一个格式,只是说这个list当中啊,它包含了我们的训练数据,也包含了我们的label,好吧好。
那有了这个DATASET之后呢,我们接下来呢需要去定义一个data loader,这个data loader又是干什么的呢,因为我们每次在训练的时候啊,我们的这个GPU的一个显存。
是有一定大小的限制的对吧,或者说即使你用CPU跑也是一样啊,是有这个大小限制的,那如果你的这个数据量特别大,你有100万的一个数据量对吧,你没有办法,一次性把所有的数据都放到你的这个,显存或者内存里。
所以呢我们通常都会分批进行跑啊,采用这个besides的一个形式,就我们每次只计算一部分的这样的一个数据,那我们使用data loader呢,就可以生成一批一批的这样的一些数据。
那每一批的数据它的这个数量啊都是固定的,也就是data babech size条数哈,EXSIZE条数,当然它有个输出值啊,就是这个DATASET,这个DATASETS的话。
就是根据我们的tensordata set来得到的,那我们把这个东西呢还有我们big size啊,就给到我们的data loader,就能拿到我们的数据的这个data loadad。
当我们来便利这个data data loadad的时候呢,每次就可以取出有一个batch的一个数据啊,那接下来的话我们就把这个data loader,还有我们的这个vocab进行返回。
也就是我们的训练数据或我们的词典,我们就进行返回啊,返回,好我们再回到哎,我们再回到一开始的地方啊,啊这是我们加载数据的一个代码,这样的话我们就拿到了我们的训练数据,拿到了我们的词典对吧好。
接下来我们来看一下我们的模型啊,我们的模型我们的模型很简单啊,我们这里用了一个LSTM的一个模型,然后加了两个全连接层啊,全连接层是什么东西呢,就是我们的普通的一个神经网络,好吧好。
我们来看一下我们这个模型什么样子啊,其实内容都是我们今天学过的,首先呢我们需要定义这个embedding层,这个embedding层是什么东西呢。
就是我们上节课给大家讲的这个embedding matrix,就是我们输入一开始输入的是什么,我们输入的是文本的一个下标对吧,或者说一个one hot。
我们需要去经过这个embedding matrix,把这个embedding给映射出来对吧,所以呢我们是首先需要去定义这个embedding,层啊,embedding哦,这里忘记说了啊。
啊很多同学可能都没有接触过这个PYTORCH啊,可能没有接触过PYTORCH,那我这边先给大家简单介绍一下,这个PYTORCH啊,PYTORCH去定义一个模型呢,它非常简单啊,非常简单。
如何定义一个模型呢,首先呢你实现一个类,这个类呢需要继承自PYTORCH,这个touch到NN打module,继承完这个类之后呢,你需要重写两个方法,一个是构造方法,一个是for word方法。
构造方法他做的事情是什么呢,嗯准备我们需要用到的参数和layer,就是说我们需要用到哪些参数,你需要去做一些准备,有需要用到哪些层,你要用RN,你要用CN还是要用LSTM。
你就在我们构造方法当中去进行准备,这是我们第一个要写的方法啊,要重写的方法,第二个要重写的方法的话是我们的for2的方法,这个方法呢就是我们的前向传播,前向传播,这是在什么,在干什么呢。
就是把我们准备好的layer拼接在一起,拼接在一起,就你这里准备了这么多layer对吧,那每一层layer它这个数据是怎么传递的,你需要把它拼接在一起,你才能构建成一个神经网络对吧。
这就是我们的前向传播做的一个事情啊,做的一个事情就这么简单啊,PY套式构建模型就这么简单,就这么简单,好吧好,那我们回到刚才的内容啊,首先我们来看我们的构造方法,我们先构建我们的embedding层。
这个embedding层的话就是刚才说的,我们要把我们的下标转换成这个,embedding的一个形式对吧,那这个embedding呢这个embedding层啊,它有两个参数。
第一个参数的话是这个词典的一个大小,第二个参数的话就是embedding size,那分别对应的,实际上就是我们上节课给大家讲的,这个embedding matrix的一个维度嘛对吧。
一个是词典的大维度,一个是embedding的一个维度,所以这两个参数啊你需要传递进来,这样的话我们就构建好了我们的引白领层,然后呢我们这边使用的是LSTM好,我们就来构建我们的LSTM层,LSTM层。
首先的话是你的输入维度对吧。
你的这个X对吧,你的输入维度是什么,还有你的这个hidden hidden size,就是你的这个啊hidden state和咱们的这个sales state。
它的维度是多少,这个东西需要定义出来好,然后是这这里有个参数啊,叫做number layers,什么意思呢,就是说你要构建几层这样的LSTM。
正常的话就是一层嘛对吧,我们实际上可以这样子做啊,我们可以啊,诶稍等一下,哎,这是我们的一层AIST,我们可以在上面再叠加一层啊,再叠加一层LSTM,这样的话就是两层的LISTM啊。
那在我们这边代码当中也是一样啊,我们就设置两层两层,然后这里我们额外还有个参数啊,叫做best fast first,就是我们把第一个维度啊设置为这个啊,这个背驰的一个维度。
它默认第一个维度不是背驰的维度啊,所以我们这里把它设置为true,那这样的话,我们这个维度实际上就是第一个维度,是咱们的啊,BESIZE对吧,第二个维度的话是我们的序列的长度。
第三个维度的话就是我们的这个啊,输出的一个维度,也就是hidden size对吧,这就是我们最终AISTM的一个,输出值的一个维度啊,输出值的一个维度好,这是我们LSTM层,最后我们再构建两个全连接层。
第一个全连接层的话,你的输入维度,肯定和上一层的这个维度保持一致,你才能进行计算对吧,所以是这里是256,那这里就是256,然后接下来呢我们给这一层的一个输出维度啊,我们给个100。
然后最后的我们再给一个啊,再给一个linear层啊,输入为就是100,输出维度是二,为什么这里输出维度是二呢,因为我们接下来要去计算我们的那个and,cross entropy啊,交叉熵损失。
所以呢我们这里就输出两个值啊,输出两个值去计算我们的cross entrop好,这是我们的构造方法啊,接下来我们看我们的前向传播,那前向传播的话,就是把我们准备好的layer,去进行一些什么拼接对吧。
首先是embedding层,我们把我们的X给过来啊,这个X是什么呢,这个X就是我们刚才data load date的时候呢,我们把他做了转序列长度,然后补偿之后的这个X啊,我们进行了返回了。
只是封装成了loader的一个形式对吧,但实际上里面还是这样的一个下标,并且做了补偿对吧,所以这个东西呢,待会呢我们就会把它传递进来啊,传递进来就先给到我们embedding层。
拿到我们的embedding,再把embedding给到我们的LSTM好,这里是我们的重点啊,这里是我们重点,我们可以去看一下LSTM的代码的说明,额我们看一下它的output,output的话。
它包括两个部分啊,一个是输出值,还有一个是HN和这个CN,HN的话就是我们的hidden state cn的话,就是刚才说的这个sales state,那我们其实不需要后面这两个东西。
我们只需要output对吧,我们只需要他的输出值啊,输出值,所以呢啊我们这里就用这个用这个符号啊,就表示刚才这里的eden state,Sales state,我们不需要啊。
我们不需要只需要他的这个输出值好,那这个输出值的维度啊,就是这个h size序列长度,Een state。
那我们现在要做的是什么,做的是文本分类对吧,我们文本分类刚才我们有个这样的一个图,它是一个manning to one的一个形式。
并且我们取的是最后一个时刻点的一个输出值,对吧,所以啊。
我们这里应该取的是最后一个时刻的输出值,最后一个时刻怎么取呢,是不是就是一呃,这两个维度的话就是就全取,为什么是全曲呢,因为bech size你要全取吧,pen size你要全取,唯独序列长度对吧。
我们要取最后一个字,那就是一好,这样的话我们就可以把最后这个时刻的值啊,也就是这个值这个蓝色框的值就取出来了,我们就给到我们的全连接层,给完全连接层之后呢,我们再给到第二个全连接层。
然后再把结果进行输出,这就是我们构建的一个神经网络啊。
神经网络好,我们的模型就准备好了,我们再回过回到这边啊,有了数据,有了模型,那接下来就是开始进行训练了对吧,接下来开始训训练好,训练过程呢,我们这边啊首先去定义我们的这个优化器啊。
优化器这个优化器是什么东西呢,这个东西大家可以理解为。
就是我们在求解这个进行啊梯度下降的过程中,我们不是要用这个W减掉这个学习力,再乘以我们的这个梯度对吧,那这个东西呢就被这个过程啊。
我们就采用了这个所谓的一个优化器,但不同的一个优化器啊。
它会有针对于我们这个梯度下降,会有一些更多的一些优化方法。
那我们用的这里这种方法啊,被称为这个梯度下降,这是个随机梯度下降法啊,就是咱们有这个SGD,我们有可以给大家看一下啊,有这个touch点,用SGDSGD,SGD啊,SGD的话就是我们的随机梯度下降法。
就是我们对一个位置的数据啊,去采用我们的梯度下降法,那ADAM呢,就是在SGD的基础上,去做了进一步的一些优化啊,让它收敛的更好一些,或者说收敛的速度更快一些啊,更快一些。
那我们啊这里这个原理啊我们就不展开讲了,大家感大家感兴趣的话,可以再下来搜索一下相关的资料啊,好,那我们这里就去定义一个这样的一个优化器啊,这个优化器呢需要去优化,我们当前这个模型里的所有参数对吧。
并且学习率我们要设置一个啊,就设置为我们这里设置为0。01,接下来我们去定义我们的这个loss function。
Loss function,像我们这里这个例子对吧,这里这个例子啊,我们采用的是这个binary cross entrop,它是一个二分类的一个啊交叉熵损失对吧。
然后我们这里呢就采用普通的cross entrop啊,其实你用binary cross entrop也是一样的好吧,都是可以的,好优化器,有了loss function我们也定义好了。
那接下来呢我们就可以进行我们的训练了对吧,这边呢这个代码什么意思呢,就是说我们要把我们的模型啊,如果你的KDA是可用的,就把模型放到我们的GPU上,好,这边我们跑五个epoch啊。
好每个epoch的时候呢,我会去便利我这个data loader对吧,我们这个data loader,那便利data loadad的时候呢,我们就可以把每一个bech size的,一个数据给取出来。
取出来之后呢也是一样啊,要放到GPU上,对于我们的标签也是哈,我们把它放到这个啊GPU上面,OK那X呢我们就给到我们的模型,给到我们模型,给到我们模型呢,实际上就是去执行我们的for word方法。
就可以得到我们的输出值,好得到我们输出值之后呢,啊,我们就可以去取他的aug max,来得到我们真实的一个标签,让我们把真实的标签啊存到我们这个list当中,然后这是我们的label啊。
label我们也存到这个list当中,接下来呢我们把我们的输出值啊,和我们的这个真实的这个label啊,去算一下我们的这个loss loss值,算完这个loss值之后呢,我们就有了loss对吧。
有了LOS好,首先第一步,我们把我们优化器当中之前的梯度啊,先清零清零,因为在PYTORCH当中啊,这个优化其它会保留之前的一个梯度,你如果不清零的话,它这个梯度会累加,所以我们在进行更新梯度的时候啊。
要先把这个七梯度清零清零之后呢。
我们去进行反向传播,反向传播是在干什么,就是在去求解咱们的这个梯度啊。
就是在求解FW,在求解我们的梯度,那求解好梯度之后呢,我们再执行我们的这个optimizer的step方法,就可以去进行反向传播。
更新我们的这里的W好吧。
这里就是在更新我们W这是在求梯度,好吧好,这里可以给大家写一下啊,这里是在求解梯度,这里是在诶更新我们的权重好,这样的话我们这个就是在一个循环的一个过程,对吧,这就是我们循环的一个过程。
最后的话我们每跑完一个epoch,我们就去求解一下这个准确率啊,准确率,最后我们把代码执行一下啊,把代码执行一下,整个流程就是这个样子啊,整个流程就是这个样子,好稍等一下啊。
O这第一个apple是67的准确率啊,好我们跑了五个apple之后,准确率就很高了对吧,已经90多了啊,90多了,这个就是我们整个使用这个啊PYTORCH啊,构建这样的一个LSTM。
来做咱们的这个文本分类的,这样的一个小例子啊。
小例子好吧,好,最后的话我们再对今天的一个内容啊,建做一个简单的一个总结啊,今天的话,首先呢我们给大家介绍了这个神经网络对吧,包括什么是神经网络啊,神经网络啊是怎么去求解它的一个输出值的。
要怎么求解我们loss,那有了loss呢,又怎么去进行我们这个权重的一个优化和更新,对吧,那知道了这个什么是神经网络之后呢,我们又去进行了一些扩展,给大家介绍了文本当中用的比较多的,这个循环神经网络。
但循环神经网络的话,它容易出现这个所谓的梯度消失的问题对吧,所以呢我们引出了这个LSTM,那除了这个循环神经网络,它可以处理文本,其实呢卷积神经网络啊,它也可以处理这个文本。
那我们又从卷积的角度去给大家介绍了,如何去处理这样的一个文本对吧,包括卷积,什么是卷积,什么是这个卷积神经网络,再到我们如何在文本上去处理我们的啊,用卷积网络处理文本对吧,最后呢。
我们又给大家去取得这样的一个实战环节啊。
去构建了这样的一个基于LISTM的一个,文本分类模型啊,文本分类模型好的,那咱们今天的内容啊基本上就到这边了,到这边了,今天的内容还是蛮多的啊。
蛮多的啊,大家下来就多花点时间去啊复习一下啊,特别是这一块啊,就这个RN为什么会梯度消失,这一块,这一块是非常重要的啊,基本上面试的时候是绝对会问的好吧,绝对会问的,绝对会问的嗯好行。
那咱们今天的内容就给大家介绍到这边了,后续大家如果还有什么疑问的疑问的话。
欢迎在这个群里面找我进行啊咨询,好吧好,那咱们今天的课程就到这边好。
【七月在线】NLP高端就业训练营10期 - P2:2.基于RNN的文本分类与语言模型_ev - IT自学网100 - BV1uxT5eEEr6
我们今天这节课主要讲的内容,是关于语言模型和啊文本分类的一些问题,然后在PYTORCH这个方面呢,我们会主要主要介绍一下RNN相关的模型,就是recurrent neural network。
所以在课之前,我先啊我先把我的PPT给找出来,Power po,然后这节课内容其实还挺多,我们能讲多少,讲多少,如果讲不完的话,就明天继续讲,啊这是文本分类,然后,啊这节这是我们这节课的PPT。
然后我们就就可以开始讲今天的内容了,啊,首先我们这节课的内容,是关于语言模型和文本分类,然后这两个问题其实看起来没有那么相关,但是因为他们都涉及到呃,我们这节课要讲的关于PYTORCH的。
如何写一个循环神经网络的内容,所以我们就把它放到一起讨论,这是一个非常快速的review,因为大家可能都有一些相应相应的啊,关于关于关于这两个部分的经验,所以我们就不会详细的讲了。
那我们先开始进入到呃语言模型,什么是一个语言模型呢,简单的来说一个语言模型,我们要讨论的任务就是给你一句话,我要告诉你这句话它出现的概率有多大,那什么叫概率有多大呢,嗯这个概率其实是呃。
它它是一个人为定义的一个东西,就是我们我们想要知道这一句话,他一个人有多大的概率能够讲出这样一句话来,比如说下面有一个下面有一些例子说7月在线,7月在线是一所好学校,跟7月在线一是学好所效。
那第一句话就比第二句话,它出现的概率要更大一些,一般一个正常的人会讲第一句话,但是不太会讲出第二句话来,然后这个第二个还有一些选词也很重要,比如7月在线是一所好学校,就比7月在线是一所好教室。
出现的概率要大得多,它其实是衡量一句话他的啊,它的合理性有多高的一种一种表示,然后我们想象一下,如果你能够知道每句话,它出现的概率有多多大的话,那就可以,你就可以做很多事情,有有一个同学说他看不到画面。
别的同学可以看到吧,我继续讲这个,啊OK那可能是那位同学需要自己重新刷新一下,然后我们讲到说啊,如果你能够知道,如果你能够知道这个一句话出现的概率有多大,你就可以完成很多任务。
比如说啊你可以做一些完形填空的任务对吧,就是如果这个句子里少了一个单词,然后给你几个不同的选项,你就能够去填,你也可以去啊做一些文本的生成,就给你一句话,你可以继续往下写文章。
因为因为你能够知道哪些话的概率比较大啊,就是有一些很很多各种各样的功能,都可以靠着这个这样一套模型去实现它,然后当我们在做这个在做语言模型的时候,我们往往会遵从这样一个法则,就是一个链式的法则。
这个其实是conditional probability,条件概率是吧,每每后面一个单词出现的概率是,它是基于前面一个单词的,然后你这样就可以一条链式把它乘法乘起来,然后应用到这个语言模型当中呢。
你就会拿到最下面的这样一套一套公式,就是它是一个连续的,连续的乘法,能够帮你把这个概率给算出来,嗯然后我们我们在以往做传统的这个语,言模型的时候,往往会遵守一个叫做马克夫假设。
这个马克夫马尔科夫假设的意思是说,后面一个单词往往只基于前面的N个单词,至于前面的N加1N加二个单词,我们就忽略不计了,就这样的话呢,在做一些传统模型的时候,能够帮你帮你把这个模型的啊参数调小。
就是你不需要看太远的过去发生了什么事情,你只要知道目前当前这前N个单词,你说的什么话,你就遇到下一个单词说什么话,当然这个在我们这节课里面,会稍微有点不太一样,因为我们这个神经网络的模型。
其实可以再往前看的更多一点,嗯最后讲一下这个语言模型的评价,我知道我讲的有点快,所以同学们有什么问题,可以在那个留言的地方评论啊,因为因为我我我会稍微假设,大家对于这个方面有了一定的了解。
然后我们一般评价一个语言模型,是用一个一个东西叫做perplexity,perplexity是是什么呢,它其实就是把额就是把一句话出现的概率,取一个负的N分之一次方啊,群群里的PPT我会在之后更新一下。
没有问题,就perplexity是嗯,把把一个概率取了一个负的N分之一次方,为什么要取一个N分之一次,负的N分之一次方呢,啊首先他一个负的负的次方,是,因为这个条是这个概率非常的小,往往概率是一个0。
000几的东西,然后你看起来不太方便,然后你取一个负的什么次方呢,就可以把它变成一个比较大的数字,然后第二个为什么要取N分之一次方呢,是因为你的句子的长度实际上是不一样的,如果是一个太长的句子。
自然而然根据我们前面条件概率的定义,这个句子的出现概率就会非常的小,然后你你帮他做了一个N分之一次方之后,就可以normalize它,那就可以把这个单词,把这个语语句的长度的这个factor给它取消。
那这样你会拿到的是一个正的数字,如果perplexity越高呢,就表示你这个呃perplexity越高,就表示你这个语言语言越不好,perplex city d呢就表示你出现了这个语言啊。
比较符合你这个模型的预期,所以这个是对于语言模型的一套评价,就是我们往往会训练一套模型,然后在一些新的语句上面预,去计算一下你的perplexity,如果它越低呢,就表示你这个语言模型越好。
那基于神经网络的语言模型呢,其实跟刚刚是一样的,就也是一样的道理,它也是根据前面的若干个单词,来预测下一个单词啊,在这个在这个概率上面并没有任何的不同,但是唯一的区别呢是。
我们希望用用一个神经网络来拟合这个概率P,就这个P在我们传统的AGRAM当中呢,其实只计算一个频数的问题,就计算一个频率,你把它都数一数,然后除一数算个频率,就是这个这个前面若干个单词。
一共出现了多少次,然后你在基于前面若干个单词情况下出现,下一个单词出现了多少次,然后你把这个分子除以分母,你就能算出一个概率来啊,这是n gram,但神经网络呢。
就是我们的目标是要训练一个神经网络的模型,我们前面讲过这个feedforward network,这些模型来来拟合它,在特别特别的来说,在这个神经在语言模型当中呢,我们经常用一些循环神经网络来啊。
预测这个下一个出现的单词是什么,这个模型呢,它的基本架构就是给你一个单词的输入,我根据前面当前的hidden state HT减一,和我的上一个单词HTXT减一,我要能够啊做一些做一个神经网络的操作。
帮你生成一个hidden state,这个hidden state呢再下一步可以预测啊,我刚刚好像把它都调了一个,调了一个位置嗯,就是这是这是XXT减一这个单词,然后你把它传到他这里。
其实拿拿了上面一个HT减二这样一个hidden state,然后这样进来之后呢,生成HT减一这个hidden state,拿到这个hidden state之后,最后你再做一个这个线性的线性的变换。
可以把它map到一个输出的层,这个YT减一呢其实就是为了预测XT,然后当你拿到了XT跟HT减一之后呢,你又可以做一些神经网络的操作,拿到一个HT,然后用这个HT再预测下一个单词。
所以往往同学们经常会看到一些呃,一一般你能看到的图表是。
先把它放大一下,就是一般我们能够看到的图表,经常是有一个有一个这样的连接,就是这个YT跟YT跟YT减一,都是为了预测下面一个单词啊,当然这个地方也会预测下一个单词,就这是我们经常看到的一些啊。
很容易看到的一些定义,然后看到同学们这里有一个问题,他说第二次课word to vec,输入层到隐藏层,玩house到W矩阵,这个W矩阵,啊这有有一个同学提了一个上一节课的问题。
但我还是我还是回答一下吧,就是上一节课,我们在训练那个词向量矩阵的时候,其实我们训练了一个输出项,输出矩阵和输出矩阵啊,算是输入矩阵和输出矩阵,然后在一般大家是拿那个输入的矩阵作为。
我们的词向量输出的矩阵,你就扔掉不要了,就是这个是一个比较随意的决定,就是呃当年米克洛发那那篇文章的时候,他说他说他发现这个input,hidden input的那个embedding比较好。
比那个output的要好,所以我们大家就基本上都沿用了这个习惯,大家都都用这个input的这个embedding,来来训练我们的词向量好,那我们具体来看循环神经网络呢。
你会发现它其实就是一个简单的feed forward network,然后连续套了无限无限次,这样就达到了一个循环神经网络,你在计算每一个hidden state HT的时候呢。
其实都是拿上一个hidden state HT减一,做一个线性变换,然后再加一个啊,我们现在输入当前输入的单词XT,再做一个线性变换,这样你就可以拿到一个当前的hidden state HT。
然后再拿它来做一部这个做一步操作,把它map到你整个单词的这个空间上去,我们可以想象这个HT可能是一个,100维或者300维的hidden state,但是嗯你这个YT呢。
可能是要展现在整个vocabulary size上面的,所以也就是说嗯我们HT可能是一个,可能是一个300dimensional hi的state,然后但是我们的YT呢,YT这个hat我想说的是hat。
YT呢它应该是一个啊,比如说是5万维的hidden state,因为它要在整个单词的表上面做一个预测,所以这是一个把它把它展,这个WS呢就是一个啊,相当于是一个5万×300位的这样一个向量。
能够把它转回到你想要的单词表上面,这是一个recurrent neural network啊,然后H0呢一般就是一个全部为零的向量,这个是大家一般经常用的这个初始化的过程。
然后如果你要训练这样的一个循环神经网络呢,我们就一般会用一个cross entropy的损失函数,然后要注意的是,这个cross entropy它是在所有的啊,每一个你预测的单词上面。
都要做一个这个cross entropy的计算,因为我们我们如果回到前面这张图呢,你会看到我其实预测了YT减一,预测了YT预测了YT加一,就是你你一直在不停的预测下一个单词,所以假设如果说你一共有一共。
比如说有text,从一到,那我们想要预测的target呢其实是从二到N加一,就这是我们我我们要预测的东西,就是我每一步拿了上一个单词,我都可以预测下一个单词,当然你要注意这个循环神经网络。
它其实是从左往右走的,所以我们当我们在预测第二个单词的时候,我们没有看到后面的单词,就是你不希望先把后面的单词给看了,把答案揭晓了啊,这个是我们预测的这样一个任务。
所以当你预测出了第二到N减一个单词之后呢,你就可以用它来计算你的loss啊,这个loss在在我们这里讲,就是一个cross entropy的损失函数,然后那个嗯优化的方法呢就是SGD。
或者你也可以用ADAM,或者我们用rms prop,其实我最常用的就是ADD啊,就是ADAM这这样一个随机梯度下降的方法嗯,因为它的效果一般比较好,然后我们讲了这个perplexity。
其实是就是二的J次方,这个跟我们前面定义的那个cross entropy,应该是等价的,同学们可以自己思考一下,就是这个J是我们一个loss对吧,然后这个二的J次方呢。
实际上就是就是我们刚刚的那个这个语句,出现的概率,它啊取一个负的N分之一次方的这样一个结果,好但是呢呃人们发现训练RNA比较困难,因为他有一个梯度消失和梯度爆炸的问题,为什么呢。
因为我们这个循环神经网络,它是一路从左往右开始这样训练,然后当你每一次呃,当你计算gradient的时候,其实你是不断的不断的在啊求导求导,求导再求导,然后我们知道这个求导公式,如果你给它展开的话呢。
它是类似于下面的这样一种构造,就第一个你如果要这个E3是这里的一个loss,然后你希望用这个loss对S3求导的,那你是啊PARTIE3除以partial S3,然后当你再对S2求导的时候呢。
又要partial S3对par树S2求导,然后一直一直往前走,一直到这个爬树S1除以partial s0,然后现在如果我问你,这个E3对S0的导数是多少,那就是一个这就是一个连续点乘的一个过程呃。
连续相乘的过程,然后如果你把这四个东西都乘到一起,这个梯度很容易降到太低,所以啊我就不太具体讲述讲述这个理论的问题,因为只要大家知道这个训练案呢,一个容易梯度消失,一个容易梯度爆炸。
然后后来人们发明了什么办法呢,就有有一些有一些那个经验性的方法,一个是gradient clipping,就是当你每一步求导之后,你发现gradient词太大了,我都把你往下一卡。
卡到一个低于threshold的位置,再做这个再做这个更新啊,这个是解决梯度爆炸的问题,就是梯度太大了,你可以把它往下卡,但梯度如果太小怎么办呢,梯度太小的话,我们可以想象,如果你一个模型的梯度非常小。
你这个模型就几乎不会更新,你就一直等着他在那它都不会动,那怎么办呢,后来人们又发现了,又发明了几套模型,这个长短记忆网络,long short term memory啊。
讲完这个launshort time memory呃,大家应该知道,最近那个图灵奖颁给了三个做深度学习的人,做深度学习的一个是JOEFREYHINGTON,一个是呃yellow kn,一个是JOE。
JOE说uh ysa bengio,然后就有很多人说发明long shots and memory的,这个人也也应该能拿这个图灵奖,就他是一个叫什么史密特HUBER的一个人,忘了他的他的名字叫什么了啊。
但是就这个人非常可惜,他没有拿到图灵奖呃,一一部分原因是,因为他据说他在学术圈比较喜欢骂人,然后就呃大家都不太喜欢他,然后有同学问说这个perplexity是什么意思,就是你中文直接翻译一下。
Perplexity,其实是一个叫做困惑度的东西,就是当我拿到了一个模型,我们知道我我前面定义了一个语言模型,其实是为了计算一些句子的概率的,所以如果我现在手上有一个模型,我给你一个句子。
你这个模型应该能给我一个概率对吧,那我现在是希望啊,我希望那些好的句子,它出现的概率应该越大越好,而差的概率差的句子呢,你的模型应该告诉我它的概率比较小。
然后perplexity呢其实是我们知道是求了一个,求了一个inverse对吧,就是一个呃相反数是吗,就是一除以那个东西,然后再给他normalize了一下,所以他其实是啊,相当于你数字越大。
就表示你的困惑度越大,困惑度越大,就是说你这个模型有点问题,我明明这个句子挺好的,你怎么把这个困惑度调这么大,所以嗯一般是这个样子的,就是当我们一般在评估一个模型的时候,你是给它一些比较好的句子。
让他去计算一下概率,如果他给你算出来的这个困惑度特别大呢,就表示他这个模型看不懂你的句子,那就表示他这个模型有点问题,就是这样一个直观的解释呃,然后这个长度这个OSTM呢。
呃具体的这个模型我都不想再细讲了,但它这是这是一个RNA的一个记忆细胞,因为因为是船上一个hidden state,加一个当前的input,生成一个当前的output,当前的hidden state。
然后LSTM呢它里面就有很多个gate啊,有一个input gate,有一个output gate,有一个forget gate,有一个叫做啊,另外一个叫什么gate来着,反正他有四个gate啊。
我们这里后面后面会讲这个LSTM,它的这个细胞有有几个gate啊,一个是它有它有若干个门来控制这个输入,然后这个门呢有有一个这个叫做forget gate对吧,然后这个I呢叫做input gate。
然后这个C应该是一个sell gate对吧,然后最后一个啊,最后还有一个gate叫做output gate,就是这这几个门可以控制你这个输入输出,它看起来很复杂,然后这个呢其实是最经典的一个长短记忆。
记忆网络网,说to memory其实只有五个公式,但是如果同学们看这个公式了,就会发现它,那它比较好的解决了,我们刚刚讲的这个gradient消失的问题,因为当你用这个后面的后面的输出。
对前面求导的时候,你会发现他他的那个梯度,并没有被完全的消失掉,就但是我这里就就不讲了,但这个下面的这个长短记忆网络呢,其实是更常用的一个长短记忆网络,就它并不是它并它跟刚刚的其实有一些变化啊。
但这是一个更加popular的版本,也是我们在PYTORCH当中能够写到的一个版本,就你直接扣,你直接用PYTORCH里面的OSTM,它实现的就是这样的一个一套公式,这个是呃长短记忆网络。
然后还有一个非常常用的啊,网络叫做gated recurrent unit,它是2014年提出的一个比较新的网络,这个网络呢就比我们刚刚的LOSTM,又少了一个gate,它有一个啊。
有一个他把一个他把忘记门和这个就forget gate,和input gate拼成了一个叫做reset gate好的,然后这样呢啊,就能够相当于是拿了一个更加简单的公式,只有他只有ZT跟RT这两个部分。
然后用它来对我们的,用它来对我们前面的一些输入,对对于我们前面的hidden state和新的输入,做一个线性的变化和什么非线性的激活,但嗯总结一下我们关于语言模型。
主要就是有三三套模型是我们经常拿来用的,一个叫做一个是传统的recurrent neural network,一个是LOSTM,一个是group,在实际的大多数项目当中。
我们很少使用这个最原始的recurrent neural network,大部分时候我们使用的都是LSTM和啊group,然后注意这两个模型的一个区别。
就是LSTM它其实同时在传两个两个hidden state,就是我们同时要传这个ct和H,这两个都是沿着我们的这个轨道在往后传的,如果我们看这一张图,就会发现它其实都它其实上下有两条轨道在走。
这两条我们都要传,好然后然后还有一个呃总结一点,总结下来的一点,就是我们的模型的训练方法,是训练这个cross entropy loss,并且这个cross entropy loss。
是要定义在每一个你输出的啊,输出的这个单词上面,这个是想要提醒大家的一个点,然后我们就可以开始,代码的部分,那我把这个拿过来啊,我们我们这节课的学习目标,我们已经讲了,我们要学习语言模型。
然后呢我们会给大家介绍一个包,叫做torch text,它可以啊,帮我们处理很多自然语言中,经常要处理到的任务啊,我是一个比较方便的库,但它其实现在也在开发当中,很多API还不是很稳定嗯。
然后下面我们是要介绍如何写这个recurrent,Neural network,ISTM和group,然后我们讲怎么样训练它,就是一个一个最常用的技巧,是要做gradient clipping。
即使我们做LSTM,一般我们也经常会做gradient clipping,因为其实这一些循环神经网络,都很容易梯度爆炸,梯度爆炸之后你就会出现一堆MAM,就是整个啊gradient非常非常大。
然后我们会讲一些这个比小的细节问题,比如如何保存和读取一个模型好,那我们第一步就是要用啊,torch text来创建一个vocabulary,大家可以自己嗯打开torch text之后。
读他的这个read me,就这个这个这个库其实非常小,它都没有多少代码,就是只是帮我们实现了一些,最常用的文本处理的功能,那我们我们这节课就会快速过一下。
第一步还是我们把想要想要import的库都import,主要是torch,还有这个torch text,然后我们还是把这个random seed全都freeze掉啊。
这个use coa呢是看我有没有ka available,然后我们我们这里其实我这边是有哭的的,所以我待会很多可以用可以用GPU来帮忙训练,会快很多,然后下面有一些hyper parameter。
一个是batch size,就是整个啊每一句话有多啊,一个batch里面有多少个句子,然后这个embedding size是我们一会要用到的,这个啊,输输入的时候把这个单词embedded成多少维。
其实我们可以试一个稍微小一点的数字,就是我给大家提供,在提供在我们的那个呃,提供在群里面的那个课件,应该是650位的,是一个比较大的模型,但是我们现在课上可以用一个小一点的模型。
这样方便我一会儿训练的时候,可能速度会快一些,然后我们讲呃。
我要用一个什么训练的训练的数据呢,嗯我这边有,给大家看一下,我们还是用我之前经常用的text8点点train。
我们应该看点train对吧,我给大家先稍微熟悉一下,它其实是一个帮你处理好的一堆文字,我们看到他就是呃,他把那些标点符号全都去掉了,就是它都是一句一句完整的话,然后我们就直接用它来训练。
相当于是做一个demo的过程,因为我们知道其实标点符号也是挺重要的,但是我们这里就忽略不计了,然后就从直接用这个来训练,那嗯我们首先想到第一步,你得把这些把这些文本都读进来。
然后我们就用torch text来帮我们处理这个问题,我们可以用torch text点data点field来定义一个field,什么叫做field呢,field其实就是呃其实就是相当于告诉你。
我输入的东西是一些是一些什么,然后呢field你可以声明一些要求,就是因为他处理的全都是文本的东西,所以这些field全都是一个一个的单词,然后我们告诉他,我们想要把单词全都lower case。
然后下一步呢你就可以创建我们的数据集,然后torch text里面有一些啊,有一个DATASETS,点language model,这个language modeling dataset。
就是专门帮我们创建language modeling的这个DATASET,然后我们可以传给他这个splits,它的path就我们告诉他这些文件,这些文件都在当前的文件夹下,然后这个训练数据呢train。
我们告诉他这个train的文件等于text,八点train点TXT,然后我们要给他传三个文件,一个是train,一个是一个是validation,就是验证集,还有一个是测试集,就是test。
我们给他这三个集合,然后我们告诉他这个text field是text,也就是说我们我们这个这些文本都要被lower case,然后它是一个一个field。
这样呢你就可以拿到train value test这样三个部分,下一步呢啊这样我们就拿到了啊,这里出了什么问题,Has no attributes language,我可能打错了。
Model main dataset,这样你就拿到了train file test,这样三个DATASET嗯,它包含了什么东西呢,其实train val test,相当于他都把这些。
我们刚刚给大家看的那些文章,他都读进来了,读进来之后呢,第一步,我们要做的事情是要创建一个vocabulary,什么叫做vocabulary,那大家还记得我们上上一次训练词向量的时候。
我们就是把频率最高的那些单词留下来啊,作为我们的作为我们的单词表,然后PYTORCH啊,这个torch text直接帮我们做了这件事情,所以我们可以写text点build vocab train。
就是从训练数据里面去找,词频数最高的那些单词,当做你的vocabulary,然后呢我们还要指定一个max size,就是告诉我最终最大一共有多少个单词,然后可以用max for CAB size。
这样你就可以拿到啊,我们看到刚刚max for capsize是5万,所以我们想要构建一个5万个单词的单词表,至于5万个以上的单词呢,我们就留着,啊5万个以上的这个单词。
我们就把它全都定义成一个叫做UNK的东西,然后我们可以看一下,现在它build完vocab之后呢,所以你你如果看这个text for CAB,你就发现它一共有5万02个单词啊。
再给大家看一下这个vocab,它有一些什么重要的功能啊,这个vocab它有一个它里面包含一个一个函数,叫做ITOS,这个是index to to string啊,我们看一下它的,它是个什么样的东西呢。
首先它的type是这个i to os,它是一个list,然后我们看一下这个list它具体长什么样子,如果你看十的话呢,他就告诉你前十个单词是什么,他有unk pad,The of and one。
就这些都是出现频率非常高的单词,然后有两个特殊的字符,UNK叫UNK和pad,UNK表示的是unknown word,就是两个不一样的啊,on unknown是一个特殊字符,就表示任何你没见过的单词啊。
都是unknown pad呢,嗯是因为我们往往在传一个batch的text的时候,这个单词有长有短,然后这些太短的句子,我们就会给给它加上这个pad的字符在后面,然后帮帮你补全到一样长,这样可以传进来。
然后有同学问三个文件一样吗,三个文件是不一样的,就他是三个三个不同的不同的哦,Sorry,非常感谢同学们提醒我,就这里是我这个地方打错了,应该是应该是有三个不一样的文件是text8,这里三个文件对好。
非常感谢同学的提醒,然后我们在beautiful CAB,这样你就拿到了vocabulary,然后除了i to os呢,还有一个s two i这个是string to index。
然后我们看一下string to index呢,它其实是一个dictionary对吧,它其实是一个dictionary,所以我们可以把它把他的items全都拿出来,或者或者我可以给大家看一下。
如果你现在传一个UNK进去呢,那他就会告诉你是零,然后你如果你传一个apple进去,他告他就告诉你这个index是多少啊,就是你可以传各种不同的单词进去,他就给你给你返回一个index。
然后有了这个之后呢,下一步我们要做的事情就是训,就是把构建一个iterator,什么叫做iterator,就是你有这么多的,你在这个训练,训练验证和测试集上面有这么多的text。
你希望把它变成一个一个的batch,每一个batch里面包含了32个句子,然后你用这32个句子来做训练,因为我们刚刚定义了这个batch size是32对吧,所以呢现在我们要构建一个iterator。
这个iterator的构建方法就我们可以用train iter,因为我们一共有三个部分,有train iter,value iter和test eater,然后它可以被你一起构建出来。
我们用torch text点data点,同学们注意这些呃,这些很多就batch type batch啊,torch text的这些写法其实呃并不用背下来,我一般都是直接从他们的官网上面抄,他们的做法。
就因为这些库呢还没有特别稳定,所以没有必要把很多的时间花在记这些API上面,就是当你需要用的时候,直接去抄就行了,就是这是一个他们的,啊一一些一些做这个的,就他们他们目前还是比较随机的。
定义了一些做iteration的方法,然后我们看这些device等于一,然后这个BP t t length,BP t t length是什么呢,啊BP t length其实就是,啊这个device。
我应该应该给他写成一个torch device,你要想一下,我可以写torch点device,哭哭的呃,其实我应该先把device给定义下来,大家知道device是定义,你要不是一个CPU。
要不是一个GPU,所以我可以写torch点device,if use哭的我就写哭的,Else cpu,这样你就拿到了一个device,我们可以看一下device,现在是一个扩大的device。
然后他就在我的一张GPU上面,所以我这里device可以写device等于,device等于device,然后BP t d length是什么东西呢,就是我们知道,刚刚刚刚我们介绍语言模型的时候。
我讲到了啊,你这个recurrent neural network,它的梯度是一路不停的传回去的,所以这个啊这样的一种传梯度的方式,我们叫做back propagation through time。
就是他根据时间的这个维度上往回back propagate,所以这个BP t t length,就是表示你的往回传的长度要有多少,其实我们可以随便定义一个,我本来定义的是32。
但我现在想32跟那个batch size可能会搞混,所以我干脆写一个BP t size等于50,然后我们写repeat等于false,就是当你过完一个epoch之后,就训练完,走完一遍这个文件之后。
他不会再给你重复,然后我们写shuffle等于true,就是它能够帮你把,额把它杀后一下,然后这样你就拿到了一个一个E特几个iterator,然后我们看一下这些iterator,分别可以干什么事情。
如果你想要拿一个iterator呢,你可以写ITER,Train iter,这样你就拿到了一个training iterator,然后我们我们可以看下一个batch,等于batch。
等于next eer,这样你就拿到了一个batch,然后我们想要看这个batch,它里面有一些什么信息,你要怎么看呢,啊我先拿一个batch给大家看,然后我们看到如果你把batch打出来之后。
它有两个部分,一个是点text,一个是点target,我们分别看一下点text和点target是什么东西啊,字面上意思来看,点text就是你当前的文本,target是你需要你需要预测的这个文本。
然后我们看它的形状都是50×32,这个32是我们的batch size,50呢是句子的长度,所以我们可以看啊batch点text,看看他是个什么样,他就是一个这样的矩阵,然后你拿到这样一个矩阵之后呢。
我们可以把它用我们刚刚讲过的,我们刚刚讲过text点for CAB点,I two s,i two s是把我们的index换成单词,然后我们可以用for i in batch点text。
然后我们知道batch点text,它第二个维度是batch size,所以我们可以把第二个维度是,把第一个维度上面所有的单词全拿出来,第二个维度上面我们只拿一个一个sequence。
比如说第零个sequence,然后我们看他点贝塔,然后我们再用把它给join起来啊,我们看看这里点data还要还要做什么呢,点我们可以点data点CPU,然后现在再print出来。
Invalid syntax,Okay,这边然后我们看到这样,他就你就拿到第一个句子,他说anarchism originated是什么东西,然后呢我们还希望把target也一起打印,一起打印出来。
所以我们看到我们间隔开,第一句话是我们的我们的输入的这个文字,第二段话呢是我们输出的文字,我们发现其实它基本上是一样的,他们只是差了一个一个offset,就是他们差了一个位置,你用前面的这一句话。
当你读到anarchism的时候,我希望你预测originated,当你当你读到originate的时候,我希望你预测as,就是我希望你每次都预测下一个单词,这是我们的我们的一个任务对吧。
然后我们再看一看这些句子呢,啊我们可以再继续拿下一个batch,我们可以写for i in range5,然后我可以再继续拿batch等于next it,我们看它会发生什么,然后我们再print。
我只要把这些都拿下来就行,然后再print i,然后我们看到他就会告诉你啊,然后我我为什么要展示这个给大家来看呢,我就想我就希望大家知道,其实这些它是连续预测出来的。
就是destroy the organization,然后你看下面又是organization of society,It has also been taken up as positive。
然后这里又什么啊,你看这边最后是,Interpretation,然后下面一句话又是interpretation of what this means,就是它其实是连续的一些文字下来。
所以你是可以理论上来说,你可以一路训练一个循环神经网络,往下一直一直把这些参数都,把这些句子都传进去,这个也是我们一会要做的这样一件事情,就先给大家预告一下,好然后我们刚刚已经讲了。
这个为什么有5万02个单词,而不是5万个单词,因为有两个特别的字符,一个叫做UNK,一个叫做pad,它是会自动赠送给你的啊,然后我们说这个语言模型的任务是,根据之前的单词预测下一个单词,所以这是为什么。
我们输入是这个样子,那下面我就要开始写我们的这个模型了,为了定义一个模型呢,我们回顾一下,我们上节课讲讲,我们我们这个模型是要用torch,点NNSNN来定义一个模型对吧。
然后我们现在要写一个class anon model,这个anna model呢,我希望把它写成一个非常generic的model,但是在课上我可能就写的简单一点,我们我们这个群里面的那个模型。
它可以同时处理各种啊,可以可以同时处理recurrent neural network,可以处理group,可以处理LSTM,那我们现在就写啊,首先你要定义一个init function。
这个init function里面有一个i n type,但是我想呃and and type,就是说我希望知道这个recurrent,neural network是什么什么类型的。
它是一个嗯最简单的recursion,Ual natural,可能还是一个LSTM,还是一个group,然后我还想知道下一个是n token,其实是我们的vocabulary size。
或者我可以把这个名字改的更加好一点,我可以改成vocab size,然后嗯下面我们需要的是一个embedding size,Embedded size,然后我们还需要知道hidden size。
注意我稍微改了一下这些变量的名字,我感觉这样可能更加清晰的一些,这个n layers呢,是因为我们的recursion network,其实可以一层套一层套好几层,所以你可以声明一个有多少layer。
然后最后的是一个dropout等于propose,我都想先不加了,就是这个先不给大家讲,包括这个and layers c也不要了吧,就我们就训练一个最简单的模型。
然后呢我们先初始化super animmodel,self点image,这个其实就是,反正大家只要把这段背下来就行了,我们一般就是直接写一段初始化这个模型,它上面的那个internet。
然后我们现在要做的是self点encoder,等于NN点embedding,或者你也可以写embed点embedding,然后我们vocab size到n a capp size。
die到embed size,这个是一个啊embedding的层,相当于我给你一段话进来,每一个单词我先给你,embed成一个100维的向量或者300维的向量。
我们刚刚定义的embedded size是100,所以我们会拿到一个100维的向量啊,然后下一步呢我们就是要定义一个recurrent,neural network self点,我这边就写个LSTM吧。
同学们具体可以看就是别的几种应该要怎么写,可以去参照我们的啊,群里的那个已经上传的代码,那我们可以写LSTMNN点,L s t m,然后LSTM需要哪些参数呢,它需要的第一个是。
所以我把这个ann type也扔掉了,我们就只用了LSTM,然后呢,呃我们相当于是要告诉他,我们的embed size跟这个hidden size,这样这样就已经可以了,这样你就拿到一个LSTM。
然后最后我们再加个self点啊,Decoder layer,decoder是什么意思呢,就是我们这张slides里面啊,你最后输出的时候,这个YT减一,其实是一个5万5万02维的这样一个向量。
因为这样他要能够最终被你arg max回,我们的单词表,所以它是一个5万02维的向量,所以这个东西呢它是一个ANN点,linear hidden size到for CAB size,没有问题。
这样我们就拿到了我们想要拿的拿的东西,然后我们就可以定义一个forward函数,Self,呃self对,有同学问说这个super不写可以吗,就是在在这个模型里面是要写的。
因为它是继承继承自这个NN点module,所以你要先super tie,然后再做做下面的事情,就这是为了继承上面的一个类型,然后下一步我们需要呃forward,就是我们我们其实拿到的是两个部分内容。
一个是input,一个是hidden,就forward,还记得是是我们我们前面讲过的一个forward path,然后对于我们这个forward pass来说呢,其实我们就是拿到啊。
就是我们刚刚拿到的这个,batch点text是我们要处理的东西,所以我可以把input改成text,这样可能更统一一些,这样拿到text之后呢,我们要做什么事情呢。
首先我们要给它变成embedding self,点in bed text啊,我一般写这些代码的时候,我经常会把它的shape给写下来,我们知道这个text它应该是sequence length。
乘以batch size对吧,这里要稍微注意一点,就是torch它拍torch它默认做这一些呃,recurrent的处理的时候,他的第一个维度都是sequence length。
第二个维度是batch size,其实这个稍微有点不是特别直观,如果同学们看着不太爽的话呢,可以把它特别声明一个batch first等于true。
这样就可以让你的recurrent neural network,都改成处理bash,把batch放在第一个维度上,也就是给他转制一下,变成batch size乘以sequence land。
但是我们这里就先不做这个处理,先沿用它原始的这个习惯,然后这样你拿到了一个embedding,然后下一步呢,我们就是直接把embedding传进我们的。
传进我们的recurrent neural network,所以我们写self点LSTM in bed hidden,注意hidden是上一个hidden state,就是这个LSTM它究竟在做什么呢。
啊我先写,他会给你输出一个output跟hidden,等于,这个我应该把high torch的这个documentation给打开,然后跟大家一起看一下IOSTM,它具体是怎么怎么用的。
就LSTM这一个函数呢,那这一个这一个类这个class对吧,它实际上是啊,我们看到他的公式在这里,这个是我刚才给大家看过的这一套公式,就这是他要干的一件事情,然后呢它的输入是你当前的input。
然后我们看到这个input,它的shape是sequence length乘以batch乘以input size,也就是说它一共有多少个单词,这个batch有多少多大。
然后告诉你这个input size,这个其实就是你embedding的这个layer之类的,然后呢H0我们注意他这里还有number of flayers,就是你其实可以有若干层这个LOSTM。
但是很多我们在这里其实就直接写一层的,这个LSTM,然后number of directions,你还可以写双向LSTM,但我们这里是个单向,然后呢是batch跟hidden size这个batch啊。
这个H0呢就是告诉你你这个ISTM,因为我们一共有sequence length对吧,就你传进来的时候,其实传了sequence length这个token,它会一路把LSTM跑到底。
然后告诉你最后的时候啊,就这个H0是第一个hidden state,C0是第一个sales state,我们刚刚讲过LSTM,有个有个有两个有两个东西在往后传。
然后它的output呢其实是也是sequence,lance乘以batch乘以number of directions跟hidden size u,就是说一共一共输出了多少个呃。
就是把输出的每一个hidden state他都给你拿出来了,有一个有乘一个hidden size,然后这个HN呢就是当你跑到结尾的时候,那个hidden state这个CN是你跑到结尾的时候。
这个sell state我不知道同学们有没有被我搞混了,就是其实其实这个他完全处理的,就是我刚刚才在slides里面给大家看的这张图,就这张图里面他拿进来的这个input呢。
是相当于是你的这个XX0到XNX0到XT,然后呢,他的输出其实就是你输出的这个H0到HT,或者说是H就是当你X0到XT之后呢,它输入是H0到HT,或者我们说X1到XT输入是H1到XHT。
然后他还会帮你帮你把最后一个hidden state,也留下来,然后最后还有一个self state是LTM特有的,所以如果直接进入写代码的这个,我们再回到写代码这里,那下一步呢你这样就会拿到一个啊。
我们注意这个这个embedding呢,它其实是sequence stance乘以batch size,乘以embed size对吧,然后这里呢我们我们可以想一下output。
它究竟是一个什么样的shape,这个output它其实是我们看一下这个output,是它告诉你是一个sequence length乘以batch乘以。
它其实是一个sequence length乘以batch size,再乘以乘以什么呢,乘以hidden size,就这是你拿到的output,然后这个hidden是什么呢。
hidden其实就是最后一个hidden state,就当你sequence lent拿到底的时候,所以它其实就是一乘以它,其实这个hidden有两个部分对吧,它是一乘以batch size。
Chen hien,另外一个也是一乘以百,h six乘以七等,为什么有个一乘以南,因为它的LSTM其实可以是有若干层的,所以啊当你只有一层,只有一个方向的时候,它就是个就是一个定值一。
但我们可以暂时就这么记住它,这样你就拿到了奥特给hidden,然后下面下一步你要做的事情,你是要把它给decode,掉到这个vocabulary size上面,所以我们可以把output。
直接啊linear掉,但是这里要注意一个什么问题呢,因为我们的output是sequence length乘以batch size,它是一个三个维度的,但是实际上我们在啊。
就是当我们在做这个线性变化的时候,他必须他只能取一个两维的这个变量,所以我们常常做的一件事情是,我们会把output点,output变成output点,-1output点sheep2。
就这个是干什么事情呢,就是我们把前两个维度给拼到一起,就变成sequence length,Change in batch size,就这两个维度直接给你拼到一起,这样你就变成一个二维的啊。
这样这样一个向一个向量那一个tensor,只有两个dimension的一个tensor,然后这样拿到之后,你再把它把它啊抵扣的出来,然后我们往往会这么做,我就直接把它给传进去算了。
就这样这样传进去一个啊,你新的一般state我们把它叫做decoded,等于你decoded这个东这个部分,然后这样这样当你拿到decoded之后呢,我们我们再记一下。
decoded它是一个什么什么形状呢,decoded它其实也是sequence length乘以batch,再乘以一个vocab size对吧,但是我们注意我们又会,我们又会希望把这两个维度给拆开。
就是不要啊啊,有个同学问为什么decoder是个线性变换,其实这是一个好问题,因为decoder一般其实往往是,这这个名字确实不太好,我给我把它直接转成mini算了,我换一个名字叫做linear。
这样应该就没有没有歧义了,就decoder往往其实是个IN,所以这个同学其实说的说的很有道理,就是我可以把它啊叫做叫个什么名字呢,就叫out vocab。
然后这个out of a CAB最后要做的一件事情是return,我们是我们希望把out of a CAB,再变成我们本来的那个形状,所以我会用out of a CAB,等于out to a cap。
点view view什么呢,output点size啊,注意这个size跟shape其实是一样的,就是shape你只要写啊方括号,然后size你得写这个这种括号,然后我们再写个output size,一。
最后我们写啊,他应该是,其实它应该是vocabulary size,但是我们直接写out for CAB点size-1就可以了,这个是我们的啊,这个是我们最终返回的。
我们最终就希望返回这个out of the cat,因为我们我们要知道每一个每一个位置,是每一个位置是什么样的额,每一个位置分别预测了哪一个单词,然后另外一个我我想要输出的是。
我要把这个hidden也给输出出去,因为这个hidden呢,它是包含了到目前为止句子的信息,然后同学们后面就会知道,为什么我要把这个hidden给传出去,然后看同学这里有一个问题。
他说隐藏层到输出层没有SIGMOID或者RAU嘛,我记得呃我呃我assume同学们问的是,为什么这个output到这个out of a CAB之间,只有linear,没有一个LINI。
没有一个activation,就一般来说我们在做这种LSTM的时候,不太会再加一个activation,因为LSTM里面本身有很多的activation,就它每一个gate,每一个那些啊。
每一个那个unit里面都做了一些activation,所以一般我们不会在这里再加一个activation,但同学们如果感兴趣,也可以自己去加这些activation,看会不会有效果,相当于是个惯例吧。
大家一般不会加,然后呢,嗯另外我还要定义的一个函数是death in it hidden,我们刚刚讲过,我们一般一般hidden其实全都是全零的那个参数,所以我们就会嗯直接写一个。
直接初始化一个hidden state,然后写request grad等于true,怎么样怎么样产生一个hidden state呢,就这里这里有一个有一些比较呃,奇淫技巧的地方。
就是我们一般因为因为有一个问题啊,就是我我们我们这个init hidden呢,其实我们就希望直接return一个类似于这样的东西,类,类似于一个全零的这样一个一个hidden state。
但是这里有一个问题啊,是你其实不知道你的,你现在的模型是在coda上面,还是不在CUDA上面,就你是在用GPU还是在用CPU,然后我们一般这种时候,经常会直接把这个self点parameters啊。
self点parameters是一个iterator对吧,它相当于是所有的你模型里面所有的参数,然后我就随便拿一个参数,然后我用这个参数写一个点,New zeros,这个是什么意思呢。
其实就是你创建创建一些全名的啊,这个hidden创建一个全零的tensor,但是它的类型跟你的weight是一个类型,所以你就可以拿到一堆,如果这个如果你的模型在GPU上。
你就可以拿到GPU的全零的tensor,如果是在CPU上,你就可以拿到CPU上全零的tensor,让我们看一下,这个时候你需要拿到的这个tensor,应该是一乘以batch size乘以啊。
self点我想说的是hidden size,所以我要写self点,hidden size等于hidden size,这样你就可以拿到hidden size,然后最后我们再写一个request grad。
这个是表示你要不要做gradient,这个gradient它要不要back prop到这个地方啊,具体的含义我们一会儿一会儿同学们就会理解,所以我这里先不多讲这样,因为我们这是因为我们这是个LSTM。
所以它要返回两个hidden state,一个是真正的这个hidden state,另外一个叫做sell sell state,对吧,是我们的啊,LSTM里面特有的两个hidden state。
那这样这个模型基本上就写完了,就这个模型其实就这么简单,因为我稍微忽略掉了几个啊,忽略掉了几个部分,就是如何写gr入如何写啊,但基本上性质是一样的,然后有了这个模型之后呢,你就可以初始化一个模型。
初始化一个模型的方法是model,点r n RNN model,然后它有哪些参数,我们可以把这些参数都拿下来,有vocab size,我一般在写这个这些模型的时候,会把它的每一个参数都指定好。
他的vocab size应该是啊,是不是我们的我已经前面把它定下来了对吧,其实我们的vocab size应该是text点vocab,是不是没有把text of a CAB给拿下来,所以我们可以写啊。
我可以直接写length of text,点f CAB,这样是你当前的vocabulary size,然后它的embedding size应该是点in,我记得我前面有一个,Embedding size。
这应该是个global variable,然后这个hidden size呢,hien size又是什么啊,我就直接定义成,Sorry,外面外面很吵,我们再定义一个hidden size。
这个hidden size我们就写hidden size,等于我们也写100吧,因为这个模型小一点,训练要快一点,那我们就再把他的hidden size也拿下来,这样就拿到了一个hidden size。
这样就拿到了一个模型,然后呢如果如果我有KDA的话呢,If use coa,我希望把模型变成model点to device,这样就可以了,我们刚刚device其实是个库的。
所以我们现在可以看一下我的模型长什么样,他就告诉你这是个IN模型啊,然后我们可以看一下model,我们可以看一下刚刚我们做的这个model,next点parameters。
这样你相当于就拿到了一个parameter,然后你看到这个parameter,它其实是在KDA上面的,这样你就知道你的模型它都在KA0,这个device上面了,那下面呢我们就可以开始写这个模型了。
写这个模型啊,训练这个模型要怎么做呢,其实它的跟出,训练所有其他模型的套路都是一样的,我们就是做uh for epoch in range,Number of epox。
我忘了number of epox,我定了多少,number of epox等于咦,我是不是根本就没有定义number of epox,但是问题不大。
我们一会随便定义一个number of epox等于,我们可以写number of epox,等于两个epoch,然后下面我要做什么事情呢,你要写model点train。
因为因为模型我不知道上一节课有没有讲过,就是PYTORCH里面模型其实有两种不同的setting,一种是训练模型,训练模式,一种是测试模式,在训练的时候跟测试的时候,有很多地方是不一样的。
比如说这个draw pbh normalization,Sorry,外面外面警车太多了,就这个嗯有很多不同的不同的地方,所以同学们只要记住,你每次开始训练之前都写model点train。
然后我们把这个train的这个iterator给拿过来,然后我就可以开始循环了,然后我要做的一件事情,首先我要把当前的hidden state给拿出来,所以我写model点init hidden啊。
把我们的batch size传进去,下一步呢我就要写for i batch in enumerate,我们知道enumerate是可以帮你ENUMERRATE,Enumerate。
可以帮你循环这一个iterator,然后还可以帮你拿到这个index i,然后呢我们就可以用data target等于我们的batch,点text batch,点target,Um。
然后这样呢其实其实我有点好奇这一点啊,我们前面应该拿到过一个batch对吧,这是我们之前拿到的patch batch,然后你看到这个batch点data啊,batch点text。
你看到他其实已经在哭到零上面了,这个就非常方便,所以他已经在哭到零上面,那我们就不用把它转成哭的,然后下面一步我要做一个什么事情呢,呃这个稍微有一点tricky啊。
就是因为因为我刚刚我刚刚特别跟大家讲过,这个句子,它是一路往下连下去的,就是我这个这个地方,你发现它的句子其实是这个batch跟下一个batch,它的句子是连着走的。
所以理论上你这个hidden state可以一直往下传,就是当你这一句话跑了一个LSTM,最后拿到了一个hidden state,这个hidden state你其实可以再传到这个地方,再接着往下走。
又拿到一个hidden state,然后再接着往下走对吧,就是这个没有什么问题对吧,就是你这个hidden state其实你可以一路往下走,然后你这个文章如果一共有,比如说1万个单词。
你可以一路跑1万个这个这个back propagation,Through time,但是实际上呢在训练的时候,我们知道你的神经网络是不能太深的,当你的神经网络太深了之后。
一个是他back propagation会非常的慢,另外一个呢你的内存也也存不下,这么大的一个计算图,所以实际上我们经常在做的一件事情呢,是实际上我们经常在做的一件事情。
是我确实希望把hidden state往下传,就是我希望做,我希望做这样一件事情,就是output点,啊我希望做的是output hidden等于model,然后你写的是。
我觉得其实我都可以直接这么写啊,就你希望把data和hidden直接传进去,变成output,Hidden,就是我们看到这个hidden,他过了一个iteration。
过了一个iteration之后又是hidden,过了一个iteration之后又是hidden,等于说你这个hidden在不断的往下传,但这样有一个什么问题呢。
就是你会back prop propagate,Propagate through or iterations,就想你想象一下,如果这个循环它有它循环了1万次。
那我这个back propagation就要back prop,50×10000次,就这样就会非常的这个计算图非常的大,非常的深,然后你的内存很快就会爆掉,对这个同学说的没错。
只有训练语言模型的时候会这样穿hidden,因为你训练别的模型的时候,这个hidden跟前面的一个batch其实就没有关系了,就这个语言模型的时候才有关系,然后我们经常做的一件事情呢。
就是对这同学说的没错,就是翻译什么的,一般就不会这样做,因为你翻译的下一个batch跟上一个batch,其实基本上没什么关系,他就是只是一些很短的句子,但在语言模型的时候呢,训练一个语言模型的时候。
你往往会希望把这些信息能保存的都保存下来,但是所以为了做这一件事情呢,我们一般会定义一个function叫做repackage,这个是什么事情呢,就是当你给我一个hidden state的时候。
其实我想要返回的是这么一个东西,就是我想返回H点,detach detach干的是什么事情呢,detach就是说啊我这个hidden state还是在这没错。
但是我把这个hidden state跟之前所有的history,全部detach掉,就是这个H它其实是H表面上是一个tensor,但在PYTORCH里面,这个tensor其实是计算图里面的一个节点。
这个节点跟你计算图里面,之前所有的节点都是有联系的,但是你detach之后呢,你可以把它从前面的这张计算图里截断,等于说这个H它就是一个全新的开始了,它相当于是复制了一个新的这样同样的tensor。
它只是把这些值给复制下来,他没有把它的历史给背下来,那这样呢你就可以你做back propagation的时候,这个就是back propagation的起点,而不是前面就这个反向传播,从这里开始。
然后注意,因为我们的tensor啊,因为我们这个呃,我们我们现在在做的一件事情是,他有这个LOSTM,有两个hidden,所以我们就要特别处理一下its instance。
H如果它是torch点tensor的话呢,我就直接返回detach,然后else的话呢,因为我知道它它另外一种方法,其实它就是一个突破,就是两个突破,就是一个用逗号隔开的那个那个格式。
所以我可以repackage,对的就是我recursively call一下v for v in h,就是如果他有两它有若干个hidden state。
我就把每一个hidden state都重重新package一下,所以我这里要做的一件事情是啊,当我在传进这个模型之前,我要先做hidden,等于repackage hidden hidden。
这样我能确保这个hidden它是一个全新的hidden,而不是一个带着一大堆历史的hidden,下一步就是我们啊最基本的操作了,就是你其实就是做model点嗯,应该是什么,应该是optimizer点。
Zero grad,我我们要先算一个loss对吧,loss等于loss function of output,然后output跟target,注意这个target其实就是这个target。
然后我们我们记得这个,然后这里要稍微注意一下,就是我们啊这个loss function我都还没定义啊,我可以在这里定义一下,我们先把loss function跟这些optimizer什么的,全都定义了。
这个loss function是我们刚刚讲过,我们要用的是一个cross entropy loss,然后learning rate我调个0。001,然后我们的optimizer我写一个torch点。
OPTIM点,adam model点parameters,我把所有的参数都传进去优化,然后learning rate等于the learning rate,U这个就可以了。
这样你有了一个optimizer,然后我们可以optimizer zero grad,然后我们就可以做我们前面讲过的啊,啊,这里这里要刚刚,为什么我要刚刚我还要强调的一个点是什么呢。
就是这个loss function,这个loss function是一个呃,他希望你传进来,因为这个loss function它是cross entropy loss。
他希望你传进来的是batch size乘以number of targets,就targets dimension,然后呃第二个是,第二个参数,它希望你传进来的就是batch size。
因为它其实就只需要知道你正确的class是哪一类,然后这个是等于说target uh class dimension,然后有同学问题,touch的时候,grade会清零吗,其实这个问题我还真不知道。
我不知道他grad会不会清零,但是我我想他应该会帮你清零,就同学们可以自己看一下,你点detach时候,他的grad有没有清零,但是问题都不大,即使他没有清零,我这个地方还是会帮他把呃。
里面model里面所有的参数哦,gradual more清零,我我认为应该是清零了,就他他没有理由不清零,我觉得,但同学们可以自己检查一下,看一看他的grad。
就是其实你只要看这个hidden点grad,你就能知道了他有没有被清理好,那我们现在计算了一个loss之后,然后这个形状不对对吧,就是这个output,我们还记得他刚刚的形状其实是,它其实是一个啊。
如果我们还记得刚刚我模型定义的时候,他其实返回的是一个sequence,length乘以batch size乘以vocabulary size,它其实是有三个部分,那我现在想要把它变成两个部分。
那我可以做optimize啊,我可以写这个点,view-1vocab size,Vocab size,我其实应该把它写到外面去,就是vocab size,应该是,等于length of。
Text d m vocab,就这是我们的vocab size应该是5万02,那这样你就拿到vocabulary size,然后这个target呢你就给他view-1就行了。
然后后面我们是不是就要做loss点backward,再下一步我们是写optimizer点step对吧,但是这里注意有一个问题是什么,就是我们讲了你训练RN的时候需要gradient。
需要clip gradient,所以我们要做的一件事情,我们是torch点NN点,UTILS点clip grad nm,就是把它的NM给cut到model点parameters。
我们希望把model点parameters里面的parameter,全都cut到gradient clipse这个这个区间下面,所以我们要定义gradient clip啊,一般我们会定一个5。
0之类的数字,所以我们就用个5。0吧,然后有同学问就是拷贝data,对,其实那个规定,其实那个detach基本就是copy了这个它的data,但是没有copy他的history。
只copy这个当前的data,那这个这样现在就可以了,我们可以试一下啊,if i divided by100等于零,然后我就print loss loss,点item看一下这个模型可不可以训练起来。
然后你就看到这个loss,它已经开始了,你看到这个loss会降下来,然后我们边训练边说,我们还可以做一些什么事情,还可以做的一件事情呢,是啊,我们我们往往希望把你训练时候的一,些模型给存下来。
那我们怎么样存一个模型呢,我们一般做的方法就是,比如说你是希望每1万个iteration保存一次,那我可以每当每当过1万个iteration的时候,我可以写torch点。
safe model点state dict,State dict,就是model的那些state dicstate什么东西,然后你要把这个模型的名字告诉他,我可以写language model点啊。
Pytorch,这样你就把它存下来了,但是呢嗯我先把它断掉了,就是因为我们一会还会重新训练,但这里又有一个什么小问题要提醒大家,就是啊也没有,也不是一个小问题吧。
就先给大家看一下这个model sp stick,究竟是个什么东西,就model state dict呢,它其实就是一个order dictionary,他帮你把里面每一个模型的参数都存下来了。
其实这就是模型所有的参数,然后当你存下来之后呢,下次你又可以给它load回来,这个是PYTORCH推荐的一个保存的方法,就是你把他的state dict给保存下来,但是还有一个呃,我想讲的一个问题是。
我们一般不会把每个模型都保存下来,就是我们一般的常常用常用的做法是,我我先给它在validation set上面evaluate一下,因为我们有三个set,三个DATASET,一个叫training。
一个叫validation,一个叫test,然后我们会经常在validation上面evaluate一下,所以我现在定义一个evaluate这样一个function。
然后呢你把这个模型在while it上面,valization iteration上面啊,去给它evaluate一下,那如果我发现这个if well loss,比,比你最好的那个loss要要好的话。
我就给他存下来,所以我我会写一个while losses,等于等于一个一个一个list,然后如果他的我希望做的事情,就是如果现在是第一次做validation,BIOLOSSES等于零。
or vloss小于minimum of well,Losses,就是它比之前的每一次validation结果都好,我就把模型保存下来对吧,然后我可以做一个print啊,Best model。
啊来看一下,我可以写print best model safe to l m点PTH,这样就告诉你这个模型已经保存了,else else我要做什么事情呢,就是当你发现这个模型不太好的时候啊。
我们常常做的一件事情是直接schedule,我们常常这个时候我们常常做一件什么事情呢,就是发当你发现这个时候,模型的loss在validation上面的loss没有降下来。
这个就表示你现在的这个optimizer,已经心有余而力不足,就是这个它的模型已经loss降不下来了,这个时候我们常常会做的一件事情,叫做learning rate decay。
什么叫做learning rate decay,就是当你发现现在这个learning rate下面,模型的loss降不下来,你你把这个learning rate降一下,那另外降了之后。
这个模型调的就变得更精细一点,往往你会发现它又能够降下来,然后PYTORCH里面提供提供了一个降这个啊,降learning rate的方法,就是你可以定义一个schedule,一个schedule啊。
就是他可以帮你,它可以帮你调这个模型的learning rate,然后你就可以用torch点OPTIM,它也是一个optimizer点l r scare,JUE了点,Exponential。
Exponential l r,它其实就是呃你每你每call一次这个schedule,他都帮你把learning rate降一降一个一个点,我这0。5就表示它learning rate降一半。
然后这样你有了一个schedule之后呢,你就可以写schedule点step,这样他learning rate就降了,就有时候有时候这里还有很多啊,很多细节的地方。
有时候人们会说我如果连续三次learning rate不降呃,连续三次这个loss不降,我就降learning rate,我们这里是每一次loss不降,我就降一次learning rate。
就这个取决于大家同学们自己调模型的时候,看哪一个更有效果,然后我们唯一缺的一点就是,我们还没有写evaluate,这个这个function对吧。
下一步我要写的是写一个def evaluate model啊,这个其实是一个iterator,但我把它叫做data吧,就是我传了一个well well,那个iterator进来。
下面我们要做的一件事情是,我基本上其实只要把这个模型一抄就行了啊,就把这把这一段代码我一抄其实就可以了,就除了把最后这个optimizer之类的东西,不要剩下的东西我全部直接抄一遍就可以。
嗯还要注意一点什么呢,就这个地方不是model点train,而是model点evil,然后当你evil完之后,最后我还是希望我们还是需要把它改回,model点train。
就是你突然进了evaluate之后,你得把这个模型给evaluate1遍,然后还有一点我们希望保存什么呢,我希望把total loss给保存下来,所以total loss是零点。
然后我还希望把这个total count,就是我一共预测了多少个单词也保存下来,然后这个it应该是iterate data,然后hidden还是应该说来自hidden没有什么问题。
但是这里又要包一层特别的啊,因为我们现在是在做预测,是在做evaluation,而不是在做training,所以你要写model点NO grad,这样你就能确保这个context。
下面所有的东西都没有gradient,啊,然后我们看看还有没有这个,还还有没有什么问题,这里是init grade啊,然后这里的requires grad应该要等于false。
这样可以让他没有gradient进来啊,注意这个这个request grade是我之前写在这个,写在这个地方,request grade就是让他不要有gradient进来。
然后我们再看一下还有什么需要改的,这个hidden是repackage hidden,然后with NO啊,然后这里有output,然后这里要计算loss,然后下一步我们要做的是更新一下。
total loss等于loss,这里要注意什么呢,因为这个loss它其实是被平均过的,所以我希望把它lost总的加回来,所以我其实只要loss点item乘以啊,我希望把这个data的size给传进来。
因为他一共一共预测了这么多个这么多个位置,所以我们可以用N派点multiply,把这个data点size给拿拿出来,这个表示就是把因为data点size是一个突破,然后我这个就相当于把这个突破给拆开。
然后给它全都缠到一起,然后这个是total loss,另外一个要改的是total,这个total count也是lost啊,total count应该是什么呢,应该就是把lost点item给去掉。
这就是你的total count,然后我现在要返回的是return loss,然后希望把loss等于total loss除以total count,这样我们就拿到了evaluate。
然后我们不出意外的话,我们应该已经可以evaluate,我们我稍微把这个数字写小一点,这样1000个位置我们就evaluate一次,然后我们看看这个啊模型有没有什么问题,但愿能够一次通过,要不然的话。
要不然的话跑一下还是挺费时间的,然后看看同学们有没有什么问题想要问的,因为我觉得我一口气其实讲了很多,讲了不少内容呃,为什么为什么出现了两次best model shift,应该是出现了一个bug。
为什么会出现,一直一直在safe,同学们有没有看出来是,为什么一直在safe这个模型呢,有没有同学可以找出来我这个模型里啊,我这个代码里有什么bug,如果没有的话,我我可以直接啊看一下这里。
我怀疑我是不是一直在loss没有加进列表,对loss没有加进列表,所以我要把这是一个bug,但是这个VLOSSES点append will loss,但是这样也不应该出这个bug吧。
是不是我在哪个地方把I给改了三,可能这个100太慢了吧,嗯anyway,但这个模型基本上应该开始训练,我把这些数字再调小一点,我这里比如说三这边是五吧,然后我们看这样有没有什么问题。
我稍微多打一点信息啊,就是epoch,epoch是,Epoch,然后iteration,这样就可以了,我再把这个I给comm掉,应该应该没有什么问题,现在看起来if i哦,对,非常感谢。
就这个地方应该是等于零,就是非常感谢同学们告诉我这个bug,这个非常尴尬,那这样应该应该这个模型就到这里,没有什么问题了,然后你就看到会呃某一些位置要保存一下,就他有best model safe。
有的时候又没有safe,然后没有safe的话呢,它的learning rate应该就decay了,你甚至可以这里写一个print learning rate decay。
然后当你训练完这样一个模型之后呢,下面一步就是我们我们之前说的呃,啊我我我讲完了这个呃,讲完了保存模型,还没有讲怎么样把模型漏的回来,这个load模型的方法就是,load模型的方法是我们一般会这样做。
就是你首先建一个模型,best model等于ann model,看一下他一直没有learning with decay嘛,那说明validation loss可能还是在降吧。
其实我应该把这个validation loss给print出来,就是我们可以print啊,Validation loss,Validation loss,然后把这个VLOSS也给打出来。
这个well loss应该是一个数字,算了,我要重新训练一把,然后我我讲怎么样把一个模型读回来呢,就是如果要把一个模型的参数给load回来,你也是一样的,就是我们前面有这样一个model对吧。
我们前面做这个model的时候,是这样定义的一个模型,我现在可以新定义一个模型,叫做best model,就best model跟这个model基本上是一样的。
这个best model跟跟那个model几乎没有区别,它呃也是也是要use库的,但是我现在可以把它best model点load state dict,然后再把它从torch那边load回来。
把这个LM啊,我这个LM叫什么名字来着,叫做LM,我的模型叫做LM点PHPTH,你就可以把它再load回来,LOM点PTH,注意这个这个torch点load呢,我先把这个给拿出来。
给大家拿出来看一下这个torch点load,啊sorry,因为刚刚这个这里跑到一半,我发现其实validation loss没有怎么降下去,但我也先不管了,然后我们看这个torch点load呢。
它其实会帮你把这个order dict给load回来,你相当于可以把模型的参数全都拿回来,然后帮你模型的参数拿回来之后呢,你再可以把它load回这个best model里面去。
这样你就可以拿到这个best model,然后我们就可以用best model来做evaluation,然后这里我就不给大家展示,evaluate出来之后会什么样子了,因为这个其实我训练了挺挺长时间。
才训练出了这个140跟178,这两个perplexity,我现在呃给到evaluate出来的perplexity,肯定会非常的差,所以就啊就这样给大家看一下,然后训练好的这些模型呢。
你还可以用它来生成一些句子,我这里生成句子的方法是直接拿啊,就是你可以初始化一些HIIT,一个hidden state,就是直接拿一个batch size,是一的一个hidden state。
然后你再啊用它来传到你的这个best model里面,去拿这个best model呃,然后就是你你用它来生成之后,最后再一个一个生成,每生成一个hidden state之后。
你给他给他传到那个啊output的这个shape上面,就这是vocabulary size,然后你用multinomial sampling来sample1些单词,就相当于我如果给你一个vector。
告诉你这个单词有多大的概率,就其实这里你可以用MULTINOMIAL,你也可以用啊GRADY的方法,就GRADY的方法就是用arg max来卖,来sample那个啊,你你的sample。
你的那个logic最高的位置来预测下一个单词,然后就这样就可以产生一些啊,还算比较reasonable的句子,啊其实这节课讲的有点长,然后我后面其实还还还想再讲一些内容,我们要不简单的休息5分钟。
然后我回来再看20分钟,我们能讲多少,讲多少,perplexity是越小越好,嗯我就在这边跟大家一边答疑,一边说吧,我们休息,同学们可以简单休息五到10分钟,然后我们马上就呃休息休息5分钟。
我们就继续讲,有同学问这个BPTT是干什么用的,没有太懂,我给大家稍微解释一下,就是同学们如果看我这篇文章,我如果这里随便打一个,打开一个text8点def点TXT呢,你会看到这个文章其实很长对吧。
它其实只有一行,然后这一行到底有有很多单词,我们可以看一下word count,应该有我不知道这是100个,这是应该这是这么多个character,然后呢你有这么多单词,但是嗯但是我们自己在训练的时候。
我不能一把直接训练,比如一一起,比如100万个单词,我只能每一次只能拿50个单词,50个单词这样训练,所以这个BPTT就是拿50个单词出来,你每次训练这个语言模型的时候,只拿50个单词训练。
就这个是BP t t length干的事情,它的就英文名字叫做back propagation through time,这个time就是它每一个单词叫做一个time step。
所以才叫BPTT这个东西,对就是他给你切多长没有错,然后有同学说这个time step是可以自己设定的吗,嗯我不知道同学指的这个time step,是不是BP t t length。
如果你指的是BP t t length的话,就是他在拍torch啊,他在这个torch text里面,就你有一个参数是可以设定,这个BP t t length,但很多时候我自己写代码。
其实我不太用torch text,就是它并没有帮你完成太多的功能,而且没有特别flexible,所以有时候我会自己写,可能我们后面的这个项目也会里面会自己写。
就其实上面其实你自己构建一个dictionary,并不是很复杂,就是我们上一节课讲那个word embedding的时候,那个dictionary就是自己造的,其实你只需要很简单的几个功能,一个是嗯。
一个是build一个vocabulary,一个是把每一个单词变成变成一个index,对就很多时候自己手写一个data loader,可能也会更加flexible一点,OK有同学说想看一看这个生成句子。
这个地方我们可以一起简单的看一看,这里的模型在做什么事情啊,哦这里代代码在做什么事情,你看他呃,首先这个hidden是生成了一个零的hidden,然后这个他的第一个单词呢,它其实是random int。
就是他随随机拿到一个,先随机拿到一个呃数字作为你这个文章的开头,然后后面呢你就开始做传进这个模型,然后你把它放到这个best model,然后你注意你进去的是一个单词,所以它出来的也是一个单词。
然后这个单词呢再把它这个word weights,应该是一个5万02维的,这样的一个一个vector,然后这里有一个5万02维的这样的一个vector,之后呢。
然后你做一个MULTINOMIAL的sampling,拿到一个单词的index,然后你再把这个单词的index f到这个input里面去,这input是我们刚刚讲的这个,随机生成的一个东西。
然后这个input你拿回去之后呢,再把它变成我们的啊,再再回到这个循环里面去,再生成下一个单词,所以你其实是一个单词,一个单词都在生成,然后有同学问这个output点squeeze,Squeeze。
其实是把那些所有维度为一的维度全都给扔掉,就比如说你有一个100×1,乘以一的一个tensor,它就会变成一个100维的tensor,就把那个一跟一扔掉了,好我感觉我们就呃这个部分我们先讲到这里。
然后我接着往下讲后面的内容,后面我们是想给大家讲,啊文本分类的一些问题,然后我们先想一下呃,文本分类是个什么什么问题呢,有没有,我觉得这节课可能只能把这个slides,给过一遍了,就是文本分类。
它哎我我们可以可以有这样一些功能,就比如说啊识别垃圾邮件啊,比如说情感分类啊,给你一段文字,它是正向的情感还是负面的情感,额sorry,我看到同学们又有一个问题,我再回答一下,然后我最后再确认一下。
当然没有问题,我再说这里为什么要加EXP,这个是因为,呃其实同学们可以试一试,如果你不加EXP可不可以,因为我,我怀疑跟这个torch点MULTINOMIO有一定的关系。
我们看一下MULTINOMIAL具体干了一件什么事情,torch点MULTINOMIAL,他是告诉你说,Returns a tensor。
Where a roll contains number of samples from multinomial probability。
Distribution located in the corresponding role of,就我我我的我的猜想啊,就是这个我也我也不太确定,就是他这个位置可能必须要是,啊应该没有什么关系。
我觉得他这个EXP,只是为了让让一些LOGTS大的概率更大,让logic小的概率更小,就是让它整个分布更加极端一点嘛,我的我的感觉是这样的,因为比如说你是一和二的话。
那其实一和二相当于一个是1/3的概率,一个是1/2的概率,但如果是E和ex平方的话,可能概率的相差会选更悬殊一点,对就是同学说的没错,就跟soft max应该是一个一个道理。
然后range100中有同学问output是啥,这个output其实是啊,我们我们还记得刚刚我们定义这个模型的时候,这个hidden是当前的hidden state。
这个output是你输出的输出的单词,在vocabulary size上面的log,等于说它是一个5万02维的这样的一个向量,其实同学们可以呃,我还是自己print一下。
就print output点shape,同学们就知道了啊,这里为什么会不行呢,这是因为object of second CPU,But got back ka for argument index。
这是因为我的hidden没有,应该是有些东西没有哭的,我看一下,我是因为hidden点现在是一个cool的吗,应该是因为这个hidden没有变成哭的,但是为什么呢。
best model应该在KDA上才对啊,哦这里是因为我这里best model忘了放到best model,点code上去,这样就没有问题,然后我再把它拿过来。
然后就看到他其实就是一个5万02维的向量,然后他其实就是在5万5万02维的向量上面,拿那个啊,取这个取取这个multinomial sampling multinomio。
就是你有你这个logic越大的话,它被sample到的概率越大,就你可以把它改成一个arg max之类的,一样的东西,就你如果做这个arg max也会出现类似的效果。
当然这里的arg max其实是torch点max,还有没有什么问题啊,同学们就他的一个基本套路就是run forward pass,然后这个是相当于同学说的soft max。
就是把这个LOGI给它做一个EXP,然后这里是multinomial sampling,拿到你一个单词,然后这个是嗯fill in the current。
Predicted word to the current input,然后你用这个current input,再预测下一个input就可以了,那这样这样OK了吧,就是如果同学们没有什么问题。
我就接着讲后面的后面的slides,好那我们继续讲后面400就是这个文本分类,主要是有一些主主要的这个任务其实非常简单,就是给你一句话或者一段话,然后让你把它分个类,有一个同学呃算了。
我就还是有同学继续提问,我就继续把他再讲清楚一点,有同学说为什么这里要做MULTOMO,其实你不一定要做MULTINOMIAL,就是这个同学他的意思是说。
有一个同学说直接soft max换成生成的字不就行了,那同学这位同学问的问题是说,直接用它来生成字,那你还是有一个问题,你要生成哪个字呢,你是要生成arg max吗。
因为soft max给你的是一个概率分布对吧,那你返回的,你是不是想返回一个概率最大的那个单词呢,就这样,当然是可以的,就是你直接拿那个arg max也可以出一个结果。
但是大家有时候也经常会做个multinomial sampling,因为有时候阿格max给你返回的并不是最好的,那个句子,应该来说这个arg max的方法。
给你返回的是一个deterministic的句子,就是你生成的句子是每次生成的都是一样的,我如果这里用的是arg max的话呢,你每次生成的句子都是同一个句子,但是你用这个呃。
用我们的这个sampling的方法,你每次拿到的句子是不一样的,就这个是这个是为什么要用arg max,然后有同学说soft max以后不是要取最大值的吗,额这个其实是随便。
你的soft max跟arg max没有任何关系,就是soft max只是给了你一个概率分布而已,后面你想做什么事情是你自己决定的,就这个是呃这两个事情是独立的。
并不是说你soft max之后一定要带一个arg max,只是人们经常在后面做一个arg max,然后我们可以想象文本的生成,你其实是希望比较比较那个呃random一点,就是它能够随机帮你生成一些句子。
但是如果呃如果你是做翻译之类的任务,就经常容易用arg max或者beam search之类的方法,就是他是比较deterministic的,你不希望每次翻译出来的句子都不一样对吧,就是说给我一个句子。
我希望翻译出来就是一个相应的句子,所以这个是为什么,同学们可能会认为soft max,后面总是会跟一个arg max,因为我们经常会做这件事情好的,那这样我就继续回到这个呃文本分类的问题。
然后我们讲到这个文本分类,其实它本质上也是一个模型预测和学习的过程,就是我给你一个给你一个句子,给你一个句子,我我我的目标是啊,用这个分类器把它做一个分类,那在文本分类上面呢,我们介绍几个常用的模型嗯。
如果如果我给你一个句子,你要给它分成几个类,比如说是情感分类分成是正的还是负的,那有一个非常简单,但是非常robust的模型叫做word averaging。
这个这个模型不是不是最简单的word averaging,它是word averaging,后面加了两层神经网络,两层这个前向神经网络造的这个啊,文本分类器就是这个基本的思路。
其实就是把每个单词都变成一个词向量,就这里的每一个单词都变成了一个向量,然后给他求个平均,然后再过两层neural network,然后最后再比如说这是个二分类问题呢。
就是一个binary的cross entropy loss,训练出来的一个一个模型,就这个模型非常的简单,但是非常的高效啊,在情感分类里面,就是把每个单词拿到一个词向量,然后算一个平均。
然后你再用这个平均的向量来做后面的这个一,一个线性分类,做一个做一个分类的过程,这个是文本分类啊,这个是word average的模型,然后呢我我们已经知道,其实常用的做这个文本分类的套路啊。
都是你要想办法拿到一个句子的vector,就这个句子是由若干个单词组成的,然后如果你能把每个词向量有机地组合在一起,无论你是word averaging还是任何别的,你想你能想到的那些嗯函数。
把这些单词拼单词的词向量拼到一起,变成一个句子的向量,然后这个句子的向量你再做一个线性变换,你就可以做一做一个分类的问题,那我们刚刚学到了,你用一个神经网络啊。
用一个recurrent neural network,也可以很好的encode这个句子,然后我们常用的一些做法呢,就是比如说你可以把这个句子跑一个双向,神经网络。
其实我还没有讲过双向的recurrent neural network,但大家应该可以想象,就是你有一个前向的on呢,有一个反向的recurrent neural network。
然后你把这个前向的跟反向的拼到一起,然后这样你就可以拿到每一个单词的,Contextualized word embedding,就是它包括了他的context这样的一个embedding。
然后这个embedding你再想办法做一些啊,还有这个堆叠神经网络,其实就是跑若干层神经网络,也能拿到一个hidden state,然后这些hidden state呢。
你又可以把它当word averaging来处理,就当你拿到了Y1Y2Y三,一直到YT,你再套到这个模型里面去做一个word average,又可以拿到一个一个分类器啊。
当然人们之前也做过很多不同的实验,就是你可以跑一个单向的神经网络啊,你可以跑一个单向的这个recurrent neural network,然后拿最后一个hidden state。
YTY的大写的T来当做你这个句子的表示,然后你用这个vector来啊做预测,也能做出一个比较好的效果,因为这个YT你你你看这张图就会发现,它其实包含了从X1到XT所有的信息,它唯一的缺点就是。
它比较容易拿到XT附近单词的信息,前面的很多单词的信息他其实比较容易忘掉啊,因为因为隔得太远了,所以很多时候大家其实经常做的是跑一个双向,Recurrent neural network。
然后给他求个平均之类的,这个平均也叫做average pooling,对吧嗯,然后后面CNN的做文本分类,我先这节课先不讲,我们先快速稍微简单的讲一下。
这个sentiment analysis的这个代码,可能只能讲一讲这个预处理,然后在这节这节课里面呢,我们会讲呃,用这个IIMDB的数据集,就是IIMDB是一堆电影的评论,电影的评论有正的有负的。
然后我们就是把这个电影的评论拿出来,做一个文本分类的过程,然后为了准备这个数据呢,我们还是用啊,对,我们还是用这个torch text来帮我们做这个事情,这里唯一的区别是我现在的呃。
我要就是我对他的field传了一个token iser,相当于是个分词的过程,然后其实英文的分词是比较简单的,因为英文里面它空格就表示单词的分隔符,但是还是有一些比较tricky的地方。
就比如说一个单词跟最后的句号,往往是连在一起的,它们中间没有空格隔开,但是呃如果你只用空格当分隔符就分不出来,然后就有一些比较好的TOCONNIZER,比如说SPACY就是一个包啊。
同学们可以用配备install e spaces来装这个库,然后把这个ENGLISH的这个let model给装下来,然后就可以帮你做english organization。
然后还有一个特别的field叫做label field,就表示这个句子是哪一个类型啊,好然后我们拿进来之后呢,下一步是这个IIMDB的数据集,是由torch text直接提供的。
所以你其实只要用data size点IMDB点split,所以用torch text,很多时候可以比较简单的做这些事情,就是能够很迅速的拿到一些简单的数据集,来做实验,嗯然后后面我们是看一下。
一共有多少个training data,有多少个test data,然后我们可以看一个看一个training example,这里是之我之前跑出来的,就它其实大致就长这个样子。
我们看一下这个training example,他就告诉你什么brilliant adaptation of the novel that。
什么famous relatives of children prem,就其实你看了前几个单词,你就知道这个评论还是比较好的,他说brilliant adaptation。
所以后面他的label是一个positive的example,然后呃他这个数据集默认给你的是一个,training和test validation,然后我想把train再翻译一下。
分成这个train validation跟跟test,所以我再把它分分一个类,这个也是嗯你可以直接split,然后按照按照某一个呃racial i分类,它默认的分类方法是七三分,就是七十三十分。
然后我们可以看一下现在你能拿到多少东西,然后后面后面也是一样的啊,就非常抱歉这段代码跑的比较慢,因为他其实我也不知道他为什么跑的很慢,但就是就是有点慢,然后后面我们我们就还是迅速回顾啊。
就是上一段上半节课我们讲过,你要你要从这个training data里面去build,这个vocabulary,然后max size,我这里设2万5,然后这里还有一个特别的参数vectors。
我把它定成是glove,6b100 d,这是什么意思呢,就是glove是一个预训练的词向量,然后我现在等于说,我是要把这个单词的词向量也带进来,因为这个词向量在很多时候非常有用,就是预训练的这些词向量。
可以帮助你训练的速度收敛快很多,所以我才这里把它嗯,把GLO夫的这个100维的向量给拿进来,glove是一个比较好的词向量,然后我们就看到这里有2万5000多个单词啊。
好那现在这样数据都数据都漏的进来了,然后你有这个vocabulary,I two x i to s c u s two i,然后我们再把它全都变成iterator。
这里的iterator我们用一个什么什么iterator呢,用一个bucket iterator啊,这个bucket iterator可以把嗯,bucket iterator干的是什么事情呢。
它其实是把一些长度差不多的句子,都放到同一个batch当中,确保每一个batch不会出现太多的padding,什么意思呢,因为我这里有很多电影的评论,电影的评论有长有短。
然后我希望一个batch里面的句子尽量差不多长,就是太长的跟太短的句子不要在一起,因为我们知道最终你这个单词进来之后,而最终你这些text进来之后,它会变成一个sequence length。
乘以batch size的一个一一个tensor,然后如果你这个单,如果你这个句子有100个单词长度的,有1000个单词长度的,那对于那个100个单词的来说,它后面的900个单词全都是padding。
这样就会对你的模型的效果不太好,嗯所以我们希望这个padding越少越好,然后在写这个为了简单处理啊,我们这节课写这个模型的时候,我不会把这些padding处理掉,就是这些padding。
我也直接当做模型的输入给输入进去了,嗯然后我感觉时间可能有点不太够了,我想就基本上就在这里结束了,然后我把我会把这个,我会把这个notebook也传到群里面,然后同学们可以自己花点时间学习一下。
然后下一节课我们可能会非常快的讲一讲一遍,这个下面的这些模型,其实最关键的是最关键的是这个CNN模型,因为RNN跟这个word averaging,我相信同学们理解起来都不困难。
所以我们下节课主要是讲CNN模型,然后我们会开始跟大家讲一些图像的,图像的一些问题,然后有同学问说,用bucket的话会不会打乱顺序,就bucket确实打乱顺序了,就是但是同学们注意在我的这个任务里面。
顺序是不重要的,因为我只有我的,我的所有的数据都是一段电影评论加一个label,一段电影评论加一个label,就是这个顺序你打乱了,其实没有关系,就是本来是第一个出现的example。
你现在在第1000个位置出现,它还是出现了,那就没有关系,就这不是一个语言语言模型的训练问题,所以顺序是没有关系的,然后同学们还有什么问题,就我见我,我是想把这个传到群里面,然后同学们看一看呃。
用torch text load这些text,然后熟悉一下这个单词的熟悉,熟悉一下这些输入输出向量是长什么样子,然后下一节课我们再把模型给打一遍就可以了,好这个要不我们这节课就先到这里了。
然后同学们可以提几个问题,有同学说顺序重要的时候用CNN效果不好,不是的,就是呃同学们可能理解错我的意思了,这个bucket iterator,并不是说你把一句话里面的单词打乱了。
而是如果我现在有1000句话,并不是把并不是把一个一个instance,里面的任何句子给打乱了,他是一段评论里面,比如说有五个句子,然后我现在有1000段评论,我把这个1000段评论分成bucket。
每一段评论里面的句子,还是按照原来的顺序在排的,并没有打乱他的顺序,然后再有同学说,如果分类的时候除了文本,还有一个特征是数字,怎么将这个特征一起加进去,嗯这个我觉得有很多方法可以处理啊。
就是比如说我们我们刚刚讲的word averaging,是不是可以把一段文本给你一个向量,然后你如果还有一个数字的话,你完全可以把这个数字concatenate到你,你拿到的这个文本向量上面去。
就word average是一个向量,然后再加上你想要加的数字,你可以一起把它拼成一个向量,然后再做后面的这些线性分线性转换,然后有同学问word average,是将各个词向量对应维度相加平均吗。
没错就是这个同学说的没有错,就是把各个维度都做一个相加的平均,然后有同学问顺序,重要的时候用CNN效果不好啊,这个问题我想等下一节课再再回答,但我我认为你说的基本上是对的。
就是因为CNN很难capture到,很长的这个单词的关系,然后有同学说,word average是将词向量对应维度方式啊,这个这个已经回答过了,就不再继续回答,同学们还有什么问题吗,如果没有的话。
那我们这节课就讲到这里,然后我们有什么问题可以在群里面继续交流。
那就这样了。