NLP-fastai-lesson4-detailed note (1)

我们今天将进一步深入研究NLP迁移学习。然后我们将看看表格数据和协同过滤,它们都是非常有用的应用程序。
我们将采用该协作过滤示例并深入研究它,以便在数学上准确理解发生了什么 - 确切地说是计算机中发生了什么。我们将使用它再次以相反的顺序通过应用程序再次返回,以便准确了解所有这些应用程序的幕后发生了什么。

自然语言处理(NLP)

我想回过头来了解NLP,真正理解那里发生了什么。

快速回顾

首先,快速回顾一下。记住NLP是自然语言处理。这是关于拿文本来做一些事情。文本分类特别有用 - 实用的应用。这是我们开始关注的重点。因为对文本进行分类或对文档进行分类可以用于以下任何事情:

  • 垃圾邮件预防
  • 鉴别假新闻
  • 从医疗报告中寻找诊断
  • Finding mentions of your product in Twitter

您在这里看到的这一系列三个步骤(我确信您认识到这个分类矩阵)是我们将要从挖掘开始的。


image.png

我们将开始像这样的电影评论,并决定它是否对电影有正面或负面的看法。那就是问题所在。在训练集中,我们有25,000个电影评论,每个我们都有一些信息:他们喜欢它,或者他们不喜欢它。这就是我们今天和当前课程中将要详细研究的内容。我们的神经网络(记住,它们只是一堆矩阵乘法和简单的非线性 - 特别是用零替换负数),这些权重矩阵随机开始。因此,如果你从一些随机参数开始并尝试训练这些参数来学习如何识别正面和负面的电影评论,你实际上有25,000个1和0实际告诉你我喜欢这个我不喜欢那个。这显然是不足以学习的信息,基本上,如何说英语 - 如何说得好英语,以便认识到他们喜欢这个,或者他们不喜欢这样。有时这可能非常微妙。特别是对于电影评论,因为这些像IMDB上的在线电影评论,人们经常可以使用讽刺。这可能真的很棘手。

直到最近,事实上,今年神经网并没有在所有这类分类问题上做得很好。这就是为什么 - 没有足够的信息可用。因此,希望你能猜到的诀窍是使用学习迁移。这总是诀窍。

去年在这个课程中,我尝试了一些疯狂的东西,如果我尝试转换学习以证明它也适用于NLP,我想到了什么。我尝试了它,它工作得非常好。所以我们在一年之后,在NLP转学是绝对受欢迎的事情。我将向你描述会发生什么。

在NLP中迁移学习

关键是我们将开始使用我们用于计算机视觉的同类事物 - 一种经过预训练的模型,该模型经过培训可以做一些与我们正在做的事情不同的事情。对于ImageNet,它最初是作为模型建立的,用于预测每张照片属于千种类别中的哪一类。然后人们会对你所看到的各种不同的东西进行微调。因此,我们将从一个预先训练好的模型开始,这个模型将会做其他事情。不是电影评论分类。我们将从一个被称为语言模型*的预训练模型开始。

语言模型在NLP中具有非常特定的含义,就是这样。语言模型是学习预测句子的下一个单词的模型。要预测句子的下一个单词,你实际上必须非常了解英语(假设你用英语做)和相当多的世界知识。根据世界的知识,我会给你一个例子。

这是您的语言模型,它已阅读:

  • "I'd like to eat a hot ___": Obviously, "dog", right?
  • "It was a hot ___": Probably "day"
    现在以前的NLP方法主要使用一种叫做n-gram的东西,这基本上说这些词对或词组往往彼此相邻。n-gram在这种事情上表现很糟糕。正如您所看到的,这里没有足够的信息来决定下一个词可能是什么。但是使用神经网络,你绝对可以。

所以这是件妙事。如果你训练神经网络来预测句子的下一个单词,那么你实际上有很多信息。而不是每2000字的电影评论只有一点:“喜欢它”或“不喜欢它”,每一个单词,你都可以尝试预测下一个单词。因此,在2000字的电影评论中,有1,999个机会可以预测下一个字。更好的是,你不仅要看电影评论。因为真正困难的不是“这个人喜欢电影吗?”但“你怎么说英语?”。所以你可以学习“你怎么说英语?”(粗略地)来自一些更大的文件。所以我们做的是我们从维基百科开始。

Wikitext 103

Stephen Merity和他的一些同事构建了一个名为Wikitext 103数据集的东西,它只是维基百科大多数最大文章的一个子集,有一些可供下载的预处理。所以你基本上抓住了维基百科,然后我在所有维基百科上建立了一个语言模型。所以我构建了一个神经网络,它可以预测每篇重要大小的维基百科文章中的下一个单词。这是很多信息。如果我没记错的话,就像十亿token一样。所以我们要预测十亿个不同的东西。每次我们在其中一个预测中犯了错误,我们就会得到损失,我们会从中获得gradients渐变,我们可以更新我们的权重,他们可以越来越好,直到我们能够很好地预测维*基百科的下一个单词。为什么这有用?因为在那一点上,我有一个模型,它可能知道如何完成这样的句子,因此它对英语有很多了解,而且对于世界的运作方式有很多了解 - 在不同的情况下,什么样的东西往往很热, 例如。理想情况下,它会学习诸如“1996年在联合国演讲中,美国总统_____所说”......现在这将是一个非常好的语言模型,因为它实际上必须知道这位美国总统是谁在那年。因此,真正擅长培训语言模型是一种很好的方式来教神经网络,了解我们的世界是什么,我们的世界是什么,我们的世界是如何运作的。这是一个非常引人入胜的话题,它实际上是哲学家数百年来一直在研究的话题。实际上,整个哲学理论都是关于单独学习语言可以学到什么。事实证明,显然,相当多。

所以这是有趣的事情。您可以从维基百科上的所有语言模型开始,然后我们就可以向所有人提供。就像预先训练的ImageNet视觉模型一样,我们现在已经为NLP提供了预训练的Wikitext模型,不是因为它对自身特别有用(预测句子的下一个单词有些用处,但通常不是我们想要的那种),但它是一个能够理解很多关于语言的模型以及很多关于语言描述的模型。那么,我们可以采取这种方式,我们可以进行迁移学习创建一种新的语言模型,特别擅长预测电影评论的下一个词

微调Wikitext以创建新的语言模型

如果我们能够建立一个擅长预测下一个使用Wikitext模型预训练的电影评论的语言模型,那么就会对“我最喜欢的演员是Tom____”有很多了解。或者“我认为摄像很精彩但我对_____(导演)并不是那么高兴。“它将特别了解电影评论的编写方式。它甚至可以学习一些流行电影的名称。

这意味着我们仍然可以使用大量的电影评论,即使我们不知道他们是积极的还是消极的,以了解电影评论的写作方式。因此,对于所有这些预训练和所有这种语言模型的微调,我们根本不需要任何标签。这是研究人员Yann LeCun所说的自我监督式学习。换句话说,它是一个经典的监督模型 - 我们有标签,但标签不是别人创造的东西。它们内置于数据集本身。所以这真的很整洁。因为在这一点上,我们现在已经有了一些擅长理解电影评论的东西,我们可以通过转移学习对我们想要做的事情进行微调,在这种情况下,将电影评论分类为正面或负面。所以我的希望是(当我去年尝试这个时),那时,25,000个1和0将足以反馈微调该模型,结果证明它绝对是。

问题:语言模型方法是否适用于非正式英语,拼写错误的单词或俚语或短语(如s6而非Samsung S 6)的论坛中的文本?

是的,绝对是的。特别是如果你从你的wikitext模型开始,然后用你的“目标”语料库进行微调。语料库只是一堆文件(电子邮件,推文,医学报告或其他)。您可以对其进行微调,以便它可以了解俚语,缩写或任何未出现在完整语料库中的细节。有趣的是,这是人们在去年进行这项研究时感到惊讶的一件大事。人们认为从维基百科这样的东西中学习并不是那么有用,因为它并不能代表人们的写作方式。但事实证明它非常有用,因为维基百科和随机词之间存在很大差异,而维基百科和reddit之间存在很大差异。所以它可以让你99%的方式。

所以语言模型本身可以非常强大。例如,有一篇来自SwiftKey的博客文章(那些使用移动电话预测文本键盘的人),他们描述了他们如何重写他们的基础模型以使用神经网络。这是一两年前。现在大多数手机键盘似乎都是这样做的。你将在手机上打字,在预测中会有一些东西告诉你接下来你想要的是什么词。这是手机中的语言模型。

另一个例子是研究员Andrej Karpathy现在在特斯拉运行所有这些东西,当他还是博士生时,他在LaTeX文档中创建了一个文本语言模型,并创建了这些自动生成的LaTeX文档,然后成为这些自动生成的文档。那太可爱了。

我们自己并不真正对语言模型的输出感兴趣。我们只对它感兴趣,因为它对这个过程很有帮助。

回顾基本过程[15:14]

我们上周简要介绍了这个过程。基本过程是,我们将从某种格式的数据开始。例如,我们准备了一个可以使用的小型IMDB示例,该示例位于CSV文件中。您可以使用Pandas阅读它,并且每个电影评论的文本都是负面或正面的,布尔值是在验证集或训练集中。

path = untar_data(URLs.IMDB_SAMPLE)
path.ls()
[PosixPath('/home/jhoward/.fastai/data/imdb_sample/texts.csv'),
 PosixPath('/home/jhoward/.fastai/data/imdb_sample/models')]
df = pd.read_csv(path/'texts.csv')
df.head()
image.png

所以有一个电影评论的例子:

df['text'][1]
'This is a extremely well-made film. The acting, script and camera-work are all first-rate. The music is good, too, though it is mostly early in the film, when things are still relatively cheery. There are no really superstars in the cast, though several faces will be familiar. The entire cast does an excellent job with the script.

But it is hard to watch, because there is no good end to a situation like the one presented. It is now fashionable to blame the British for setting Hindus and Muslims against each other, and then cruelly separating them into two countries. There is some merit in this view, but it\'s also true that no one forced Hindus and Muslims in the region to mistreat each other as they did around the time of partition. It seems more likely that the British simply saw the tensions between the religions and were clever enough to exploit them to their own ends.

The result is that there is much cruelty and inhumanity in the situation and this is very unpleasant to remember and to see on the screen. But it is never painted as a black-and-white case. There is baseness and nobility on both sides, and also the hope for change in the younger generation.

There is redemption of a sort, in the end, when Puro has to make a hard choice between a man who has ruined her life, but also truly loved her, and her family which has disowned her, then later come looking for her. But by that point, she has no option that is without great pain for her.

This film carries the message that both Muslims and Hindus have their grave faults, and also that both can be dignified and caring people. The reality of partition makes that realisation all the more wrenching, since there can never be real reconciliation across the India/Pakistan border. In that sense, it is similar to "Mr & Mrs Iyer".

In the end, we were glad to have seen the film, even though the resolution was heartbreaking. If the UK and US could deal with their own histories of racism with this kind of frankness, they would certainly be better off.'

所以你可以去TextDataBunch.from_csv来获取特定于语言模型的数据:

data_lm = TextDataBunch.from_csv(path, 'texts.csv')

然后你可以用通常的方式创建一个learner(学习器)并fit(拟合)它。

data_lm.save()

您可以保存数据束(data bunch),这意味着已完成的预处理,您不必再次执行此操作。你可以加载它。

data = TextDataBunch.load(path)

如果我们现在将它作为分类数据加载(这将允许我们看到标签),幕后会发生什么?

data = TextClasDataBunch.load(path)
data.show_batch()
image.png

如我们所描述的,它基本上为单词的每个单独部分创建单独的单元(即“标记”)。所以他们中的大多数只是用于单词,但有时如果像it’s中的‘s,它会得到自己的标记。标点符号的每一点都倾向于获得自己的标记(逗号,句号,等等)。

接下来我们要做的是数值化,在这里我们可以找到这里出现的所有唯一token,并创建一个大的列表。这是频率顺序的前十个:

data.vocab.itos[:10]
['xxunk', 'xxpad', 'the', ',', '.', 'and', 'a', 'of', 'to', 'is']

那个独特的可能令牌的大列表被称为词汇表,我们称之为“vocab”。那么我们接下来要做的是用vocab中的token ID替换token:

data.train_ds[0][0]
Text xxbos xxfld 1 he now has a name , an identity , some memories and a a lost girlfriend . all he wanted was to disappear , but still , they xxunk him and destroyed the world he hardly built . now he wants some explanation , and to get ride of the people how made him what he is . yeah , jason bourne is back , and this time , he 's here with a vengeance .

data.train_ds[0][0].data[:10]

array([ 43,  44,  40,  34, 171,  62,   6, 352,   3,  47])

这是数字化。不过这是件事。正如您将要了解的那样,我们词汇表中的每个单词都需要在我们的神经网络中的权重矩阵中单独排一行。因此,为了避免权重矩阵变得太大,我们将词汇限制为不超过(默认情况下)60,000个单词。如果一个单词出现的次数不超过两次,我们也不会把它放在词汇中。因此,我们以这种方式将词汇保持在合理的大小。当你看到这些xxunk时,那是一个未知的令牌。这只是意味着这是一个在我们的词汇中出现的不常用词。

我们还有一些其他特殊token(请参阅fastai.text.transform.py以获取最新信息):

  • xxfld:这是一个特殊的事情,如果你有标题,摘要,摘要,正文,(即文档的单独部分),每个将获得一个单独的字段,因此它们将被编号(例如xxfld 2)。
  • xxup:如果有些词是全大写,那么它会变成小写,并且会添加一个名为xxup的标记。

使用数据块API(data block API)

就个人而言,我更经常使用数据块API,因为不用记住确切地使用什么数据束、参数等等,并且它可以更灵活一点。

data = (TextList.from_csv(path, 'texts.csv', cols='text')
                .split_from_df(col=2)
                .label_from_df(cols=0)
                .databunch())

所以这样做的另一种方法是决定:

  • 你正在创建什么样的列表(即你的自变量是什么)?所以在这种情况下,我的自变量是文本。
  • 它是什么格式?CSV。
  • 您想如何将其分为验证集与训练集?所以在这种情况下,第二列是is_valid标志。
  • 你想如何标记它?例如,有积极或消极的情绪。因此第0列就是这样。
  • 然后把它变成一个数据束。

这将做同样的事情。

path = untar_data(URLs.IMDB)
path.ls()
[PosixPath('/home/jhoward/.fastai/data/imdb/imdb.vocab'),
 PosixPath('/home/jhoward/.fastai/data/imdb/models'),
 PosixPath('/home/jhoward/.fastai/data/imdb/tmp_lm'),
 PosixPath('/home/jhoward/.fastai/data/imdb/train'),
 PosixPath('/home/jhoward/.fastai/data/imdb/test'),
 PosixPath('/home/jhoward/.fastai/data/imdb/README'),
 PosixPath('/home/jhoward/.fastai/data/imdb/tmp_clas')]
(path/'train').ls()
[PosixPath('/home/jhoward/.fastai/data/imdb/train/pos'),
 PosixPath('/home/jhoward/.fastai/data/imdb/train/unsup'),
 PosixPath('/home/jhoward/.fastai/data/imdb/train/unsupBow.feat'),
 PosixPath('/home/jhoward/.fastai/data/imdb/train/labeledBow.feat'),
 PosixPath('/home/jhoward/.fastai/data/imdb/train/neg')]

现在让我们抓住整个数据集:

  • 25,000条训练评论
  • 25,000条验证评论
  • 50,000个无人监督的电影评论(50,000个电影评论根本没有评分)

语言模型

我们将从语言模型开始。现在好消息是,我们不需要训练Wikitext 103语言模型。这并不困难 - 您只需下载wikitext 103语料库,然后运行相同的代码即可。但是在一个体面的GPU上需要两到三天,所以你没有多大意义。你也可以从我们的开始。即使你有大量类似医疗文件或法律文件的语料库,你仍然应该从Wikitext 103开始。没有理由从随机权重开始。如果可以的话,使用迁移学习总是好的。
所以我们将开始微调我们的IMDB语言模型。

bs=48
data_lm = (TextList.from_folder(path)
           #Inputs: all the text files in path
            .filter_by_folder(include=['train', 'test']) 
           #We may have other temp folders that contain text files so we only keep what's in train and test
            .random_split_by_pct(0.1)
           #We randomly split and keep 10% (10,000 reviews) for validation
            .label_for_lm()           
           #We want to do a language model so we label accordingly
            .databunch(bs=bs))
data_lm.save('tmp_lm')

我们可以称:

  • 这是一个文本文件列表 - 完整的IMDB实际上不是CSV格式。每个文档都是一个单独的文本文件。
  • 说出它在哪里 - 在这种情况下,我们必须确保我们只包括训练和测试文件夹。
  • 我们用0.1随机拆分文件。
    现在这很有趣 - 10%。为什么我们将它随机拆分10%而不是使用他们给我们的预定义训练和测试?这是迁移学习的一个很酷的事情。即使我们的验证集必须被搁置,实际上只有我们必须保留的标签。所以我们不允许在测试集中使用标签。如果你在Kaggle比赛中考虑,你当然不能使用标签,因为他们甚至不会给你。但你当然可以使用自变量。因此,在这种情况下,您绝对可以使用测试集中的文本来训练您的语言模型。这是一个很好的技巧 - 当您使用语言模型时,将训练和测试集连接在一起,然后只拆分一个较小的验证集,这样您就可以获得更多数据来训练您的语言模型。所以这是一个小技巧。

例如,如果您正在Kaggle上做NLP的事情,或者您只是获得了较小的标记数据子集,请确保使用您在语言模型中训练的所有文本,因为没有理由不这样做。

  • 我们如何标记它?请记住,语言模型有自己的标签。文本本身就是标签,因此语言模型(label_for_lm)的标签就是为我们做的。
  • 并创建数据并保存。这需要几分钟来标记化和数字化。

由于需要几分钟,我们保存它。稍后您可以加载它。无需再次运行它。

data_lm = TextLMDataBunch.load(path, 'tmp_lm', bs=bs)
data_lm.show_batch()
image.png

训练

在这一点上,事情看起来会非常熟悉。我们创造了一个学习器(learner):

learn = language_model_learner(data_lm, pretrained_model=URLs.WT103, drop_mult=0.3)

但是,我们不是创建CNN学习者,而是创建一个语言模型学习者。因此,在幕后,这实际上不会创建CNN(卷积神经网络),它将创建一个RNN(一个循环神经网络)。我们将要学习如何在即将到来的课程中建立它们,但简而言之,它们是相同的基本结构。输入进入权重矩阵(即矩阵乘法),然后用零替换负数,然后它进入另一个矩阵乘法,等等多次。所以它是相同的基本结构。
像往常一样,当我们创建一个学习者时,你必须传递两件事:

  • 数据:所以这是我们的语言模型数据
  • 用什么预训练模型:这里,预先训练的模型是Wikitext 103模型,如果您之前没有使用过它,将会从fastai下载,就像为您下载ImageNet预训练模型一样。

这里(drop_mult = 0.3)设置了丢失量。我们还没有谈到这一点。我们已经简要地谈过这个想法,即有一种称为正规化的东西,你可以减少正则化以避免欠拟合。所以现在,只要知道通过使用一个低于1的数字是因为当我第一次尝试运行这个时,我欠拟合。因此,如果你减少了这个数字,那么它将避免欠拟合。

好的。所以我们有一个学习者,我们可以lr_find,看起来非常标准:

learn.lr_find()
learn.recorder.plot(skip_end=15)
image.png

然后我们可以拟合一个循环(cycle)。

learn.fit_one_cycle(1, 1e-2, moms=(0.8,0.7))
Total time: 12:42
epoch  train_loss  valid_loss  accuracy
1      4.591534    4.429290    0.251909  (12:42)

这里发生的事情是我们只是微调最后一层。通常在我们对最后一层进行微调后,我们接下来要做的就是解冻并训练整个事物。所以这里是:

learn.unfreeze()
learn.fit_one_cycle(10, 1e-3, moms=(0.8,0.7))
Total time: 2:22:17
epoch  train_loss  valid_loss  accuracy
1      4.307920    4.245430    0.271067  (14:14)
2      4.253745    4.162714    0.281017  (14:13)
3      4.166390    4.114120    0.287092  (14:14)
4      4.099329    4.068735    0.292060  (14:10)
5      4.048801    4.035339    0.295645  (14:12)
6      3.980410    4.009860    0.298551  (14:12)
7      3.947437    3.991286    0.300850  (14:14)
8      3.897383    3.977569    0.302463  (14:15)
9      3.866736    3.972447    0.303147  (14:14)
10     3.847952    3.972852    0.303105  (14:15)

正如您所看到的,即使在相当强大的GPU上也需要两到三个小时。事实上,我还是欠拟合,可能会训练一整夜,并尝试做得更好一点。我猜我可能会训练这个更长一点,因为你可以看到准确性还没有开始下降。所以我不介意尝试再训练一下。但准确性,这很有趣。0.3意味着我们在三分之一的时间里正确地猜测电影评论的下一个词。这听起来像一个非常高的数字 - 你可以实际猜测下一个单词的想法。所以这是一个很好的迹象,我的语言模型做得很好。对于更有限的域名文件(如医疗成绩单和法律成绩单),您经常会发现这种准确性要高得多。所以有时甚至可以达到50%或更多。但0.3或更高是相当不错的。

用语言模型预测

您现在可以运行learn.predict并传入一个句子的开头,它会尝试为您完成该句子。

learn.predict('I liked this movie because ', 100, temperature=1.1, min_p=0.001)

Total time: 00:10
'I liked this movie because  of course after yeah funny later that the world reason settings - the movie that perfect the kill of the same plot - a mention of the most of course . do xxup diamonds and the " xxup disappeared kill of course and the movie niece , from the care more the story of the let character , " i was a lot \'s the little performance is not only . the excellent for the most of course , with the minutes night on the into movies ( ! , in the movie its the first ever ! \n\n a'

现在我应该提一下,这不是一个好的文本生成系统。这更像是为了检查它是否正在创造一些模糊不清的东西。您可以使用很多技巧来生成更高质量的文本 - 我们在这里都没有使用这些技巧。但是你可以看到它产生的肯定不是随机的。听起来很模糊英语,尽管它没有任何意义。

现在,我们有一个电影评论模型。所以现在我们要保存它以便将它加载到我们的分类器中(即成为分类器的预训练模型)。但实际上我并不想保存全部。语言模型的后半部分很多都是关于预测下一个词而不是到目前为止理解句子。因此,到目前为止专门用于理解句子的位(bit)称为编码器,所以我只保存它(即理解句子的位而不是生成该单词的位)。??????

learn.save_encoder('fine_tuned_enc')    

分类器

现在我们准备创建我们的分类器了。按照惯例,第一步是创建一个数据集,我们基本上会做同样的事情:

data_clas = (TextList.from_folder(path, vocab=data_lm.vocab)
             #抓取路径中的所有文本文件
             .split_by_folder(valid='test')
             #按训练和验证文件夹拆分(只保留'训练'和'测试',所以不需要过滤)
             .label_from_folder(classes=['neg', 'pos'])
             #删除不在上面列表中的标签的文档(即'unsup')
             .filter_missing_y()
             #用文件夹标记它们
             .databunch(bs=50))
data_clas.save('tmp_clas')

但我们希望确保它使用与语言模型完全相同的词汇。如果单词编号10是语言模型,我们需要确保单词编号10在分类器中。因为否则,预训练的模型将完全没有意义。这就是为什么我们从语言模型中传递词汇以确保这些数据集具有完全相同的词汇。这是重要的一步。

split_by_folder-记住,我们最后一次随机分割,但这次我们需要确保不触及测试集的标签。所以我们按文件夹拆分。

然后这次我们将它标记为不是语言模型,而是标记这些类(['neg','pos'])。然后最终创建一个数据束。

有时您会发现GPU耗尽了内存。我在一台11G机器上运行它,所以如果你的内存不足,你应该确保这个数字(bs)稍微低一些。您可能还需要确保重新启动笔记本,并从此处启动它(分类器部分)。批量大小50与我在11G卡上获得的一样高。例如,如果您在亚马逊上使用p2或p3或在Google上使用K80,我认为您将获得16G,这样您就可以将此值提高到64,因此您可以找到任何批次尺寸适合您的卡。

所以这是我们的数据集:

data_clas = TextClasDataBunch.load(path, 'tmp_clas', bs=bs)
data_clas.show_batch()
image.png
learn = text_classifier_learner(data_clas, drop_mult=0.5)
learn.load_encoder('fine_tuned_enc')
learn.freeze()

这一次,我们创建的是文本分类器学习器,而不是创建语言模型学习器。但同样,同样的事情 - 传递我们想要的数据,弄清楚我们需要多少正规化。如果你过度拟合,那么你可以增加这个数字(drop_mult)。如果你欠拟合,你可以减少数量。最重要的是,加载我们的预训练模型。请记住,特别是它的一半模型称为编码器,它是我们要加载的位。

然后冻结,lr_find,找到学习率并适合一点点。

learn.lr_find()

learn.recorder.plot()
image.png
learn.fit_one_cycle(1, 2e-2, moms=(0.8,0.7))


Total time: 02:46
epoch  train_loss  valid_loss  accuracy
1      0.294225    0.210385    0.918960  (02:46)

经过不到3分钟的培训,我们已经达到了近92%的准确率。所以这是一件好事。在您的特定领域(无论是法律,医学,新闻,政府还是其他领域),您可能只需要训练一次域名的语言模型。这可能需要一夜之间才能很好地训练。但是一旦你得到它,你现在可以很快地创建各种不同的分类器和模型。在这种情况下,三分钟后已经是一个非常好的模型。所以当你第一次开始这样做时。您可能会觉得有点烦人的是,您的第一个模型需要四个小时或更长时间来创建该语言模型。但要记住的关键是你只需要为你感兴趣的整个领域做一次。然后你可以在几分钟内建立许多不同的分类器和其他模型。

learn.save('first')
learn.save('first')
learn.freeze_to(-2)
learn.fit_one_cycle(1, slice(1e-2/(2.6**4),1e-2), moms=(0.8,0.7))

我们可以保存它以确保我们不必再次运行它。

然后,这里有一些有趣的东西。我不会说解冻(unfreeze)。相反,我要说冻结(freeze_to)。这说的是解冻最后两层,不解冻整体。我们刚刚发现它真的有助于这些文本分类,不是解冻整个事物,而是一次解冻一层。

  • 解冻最后两层
  • 再训练一下
  • 再解冻下一层
  • 再训练一下
  • 解冻整个事情
  • 再训练一下

learn.save('second')

learn.load('second');

learn.freeze_to(-3)
learn.fit_one_cycle(1, slice(5e-3/(2.6**4),5e-3), moms=(0.8,0.7))

Total time: 04:06
epoch  train_loss  valid_loss  accuracy
1      0.211133    0.161494    0.941280  (04:06)

learn.save('third')

learn.load('third');

learn.unfreeze()
learn.fit_one_cycle(2, slice(1e-3/(2.6**4),1e-3), moms=(0.8,0.7))

Total time: 10:01
epoch  train_loss  valid_loss  accuracy
1      0.188145    0.155038    0.942480  (05:00)
2      0.159475    0.153531    0.944040  (05:01)

你也看到我传递了这个东西(moms=(0.8,0.7)) - 动量(momentums )等于0.8,0.7。我们将在下周准确地了解这意味着什么。我们甚至可以自动化它。所以也许当你观看视频时,这甚至不再是必要的了。基本上我们发现训练复发神经网络(RNNs),它确实有助于减少动量。这就是那个。

在大约半小时或更短的训练后,这使我们的准确率达到94.4%。训练实际分类器的次数要少得多。实际上,通过一些技巧,我们可以获得更好的效果。我不知道我们是否会学习这一部分的所有技巧。它可能是下一部分。但即便是这种非常简单的标准方法也非常棒。


image.png

如果我们将其与去年IMDb的最新技术水平进行比较,则来自McCann等人的The CoVe论文。在Salesforce Research。他们的论文准确率为91.8%。他们可以找到最好的论文,他们从2017年发现了一个相当特定领域的情绪分析论文,他们有94.1%。在这里,我们有94.4%。而我能够建立的最好的模型大约是95.1%。因此,如果您正在寻找文本分类,这种真正标准化的迁移学习方法非常有效。

你可能感兴趣的:(NLP-fastai-lesson4-detailed note (1))