更多实时更新的个人学习笔记分享,请关注:
知乎:https://www.zhihu.com/people/yuquanle/columns
微信订阅号:AI小白入门
ID: StudyForAI
Flair工具使用教程之如何优化自己的模型
教程地址:https://github.com/zalandoresearch/flair/blob/master/resources/docs/TUTORIAL_8_MODEL_OPTIMIZATION.md
本教程我们通过选择正确的模型和超参数集来研究如何提高模型的质量。
选择超参数
Flair包含用于众所周知的超参数选择工具hyperopt的包装器。
首先,您需要加载语料库:
from flair.data import TaggedCorpus
from flair.data_fetcher import NLPTaskDataFetcher, NLPTask
# load your corpus
corpus: TaggedCorpus = NLPTaskDataFetcher.load_corpus(NLPTask.AG_NEWS)
- 其次,您需要定义参数的搜索空间。 因此,您可以使用hyperopt定义的所有参数表达式。
from hyperopt import hp
from flair.hyperparameter.param_selection import SearchSpace, Parameter
# define your search space
search_space = SearchSpace()
search_space.add(Parameter.EMBEDDINGS, hp.choice, options=[
[ WordEmbeddings('en') ],
[ CharLMEmbeddings('news-forward'), CharLMEmbeddings('news-backward') ]
])
search_space.add(Parameter.HIDDEN_SIZE, hp.choice, options=[32, 64, 128])
search_space.add(Parameter.RNN_LAYERS, hp.choice, options=[1, 2])
search_space.add(Parameter.DROPOUT, hp.uniform, low=0.0, high=0.5)
search_space.add(Parameter.LEARNING_RATE, hp.choice, options=[0.05, 0.1, 0.15, 0.2])
search_space.add(Parameter.MINI_BATCH_SIZE, hp.choice, options=[8, 16, 32])
注意:您应始终将嵌入添加到搜索空间(如上所示)。 如果您不想测试不同类型的嵌入,只需将一个嵌入选项传递给搜索空间,这将在每次测试运行中使用。 例如:
search_space.add(Parameter.EMBEDDINGS, hp.choice, options=[
[ CharLMEmbeddings('news-forward'), CharLMEmbeddings('news-backward') ]
])
- 在最后一步中,您必须创建实际的参数选择器。 根据您需要定义TextClassifierParamSelector或SequenceTaggerParamSelector并启动优化。 您可以定义hyperopt应执行的最大评估运行次数(max_evals)。 评估运行执行指定数量的历元(max_epochs)。 为了克服噪声评估分数的问题,我们从评估运行中获取最后三个评估分数(dev_score或dev_loss)的平均值,它代表最终分数并将传递给hyperopt。 此外,您可以指定每次评估运行的次数(training_runs)。 如果指定多个训练运行,则将执行一次评估运行指定的次数。 最终评估分数将是所有这些运行的平均值。
from flair.hyperparameter.param_selection import TextClassifierParamSelector, OptimizationValue
# create the parameter selector
param_selector = TextClassifierParamSelector(
corpus,
False,
'resources/results',
'lstm',
max_epochs=50,
training_runs=3,
optimization_value=OptimizationValue.DEV_SCORE
)
# start the optimization
param_selector.optimize(search_space, max_evals=100)
参数设置和评估分数将写入结果目录中的param_selection.txt。 在选择最佳参数组合时,我们不会将任何模型存储到磁盘。 我们也不会在训练期间执行测试运行,我们只是在针对测井集进行训练后对模型进行一次评估。
搜索最佳学习率
学习率是最重要的超级参数之一,最佳学习将提高您的训练速度,并希望提供更高性能的模型。
通过绘制相对于学习率的损失,我们通常会观察三个不同的阶段:对于低学习率,损失不会改善,最佳学习率范围,其中损失下降最陡,最后阶段,损失随着学习而爆炸率变得太大了。通过这样的图,最佳学习速率选择就像从最佳阶段中选择最高学习速率一样容易。
为了运行这样的实验,请从初始化的ModelTrainer开始,并使用base_path和文件名调用find_learning_rate(),以记录学习率和损失。然后通过绘图仪的plot_learning_rate()函数绘制生成的结果,并查看learning_rate.png图像以选择最佳学习率:
from flair.data import TaggedCorpus
from flair.data_fetcher import NLPTaskDataFetcher, NLPTask
from flair.embeddings import TokenEmbeddings, WordEmbeddings, StackedEmbeddings
from flair.trainers import ModelTrainer
from typing import List
# 1. get the corpus
corpus: TaggedCorpus = NLPTaskDataFetcher.load_corpus(NLPTask.CONLL_03).downsample(0.1)
print(corpus)
# 2. what tag do we want to predict?
tag_type = 'ner'
# 3. make the tag dictionary from the corpus
tag_dictionary = corpus.make_tag_dictionary(tag_type=tag_type)
print(tag_dictionary.idx2item)
# 4. initialize embeddings
embedding_types: List[TokenEmbeddings] = [
WordEmbeddings('glove'),
]
embeddings: StackedEmbeddings = StackedEmbeddings(embeddings=embedding_types)
# 5. initialize sequence tagger
from flair.models import SequenceTagger
tagger: SequenceTagger = SequenceTagger(hidden_size=256,
embeddings=embeddings,
tag_dictionary=tag_dictionary,
tag_type=tag_type,
use_crf=True)
# 6. initialize trainer
trainer: ModelTrainer = ModelTrainer(tagger, corpus)
# 7. find learning rate
learning_rate_tsv = ModelTrainer.find_learning_rate('resources/taggers/example-ner',
'learning_rate.tsv')
# 8. plot the learning rate finder curve
plotter = Plotter()
plotter.plot_learning_rate(learning_rate_tsv)
自定义优化工具
- 现在,您可以在初始化ModelTrainer时使用任何PyTorch的优化器进行训练。 要为优化器提供任何额外选项,只需使用weight_decay示例指定它:
from torch.optim.adam import Adam
trainer: ModelTrainer = ModelTrainer(tagger, corpus,
optimizer=Adam, weight_decay=1e-4)
权重衰减通常由优化方法使用以减少过度拟合,并且它基本上通过优化器的weight_decay参数向损失函数添加权重正则化器。在PyTorch中实现它的方式,这个因素与learning_rate混淆,实质上是实现L2正则化。在亚当的Ilya Loshchilov和Frank Hutter Fixing Weight Decayrization的论文中,作者建议实际上做重量衰减而不是L2正则化,并且他们将他们的方法AdamW和SGDW称为相应的Adam和SGD版本。根据经验,通过这些优化器的结果优于它们相应的L2正则化版本。然而,由于学习速率和权重衰减在这些方法中是分离的,因此任何学习速率调度都必须改变这两个术语。不用担心,我们会在使用这些优化器时自动切换执行此操作的调度程序。
要使用这些优化器,只需使用AdamW或SGDW创建ModelTrainer以及任何其他选项,如下所示:
from flair.optim import SGDW
trainer: ModelTrainer = ModelTrainer(tagger, corpus,
optimizer=SGDW, momentum=0.9)