概要
本記事はfast.aiのwikiのTextページの要約となります。
筆者の理解した範囲内で記載します。
Text モデル、データ、トレーニング
fast.aiライブラリのText モジュールは、DatasetをNLP (Natural Language Processing)目的へ最適化するための関数を多数備えています。具体的には:
- text.transform にてデータの前処理実施し、テキストをidへと変換する
- text.data にて TextDataBunch を用いてNLPに必要なDatasetのクラスを規定する
- text.learner にて素早くlanguage model や RNN classifierを作成できる
上のリンクを辿って各モジュールのAPIを参考にしてみて下さい。
早速やってみる: ULMFiTIでimdbの感情modelを鍛える
早速fast.ai textモジュールを使ってみましょう。以下の例では名の知れたimdbデータを用いて、感情分類モデルを4ステップで鍛えていきます。
- Imdbデータを読み込み俯瞰する
- データをモデルに最適化する
- language modelをfine-tuneする
- 分類モデルを作成する
1) Imdbデータを読み込み俯瞰する
text に必要なパッケージを読み込みましょう。
from fastai.text import *
画像認識とは異なり、テキストは直接モデルに読み込むことができません。従って、最初にデータを前処理してテキストをトークンへと変換して(tokenization)それを数字へと変換する(numericalization)必要があります。これらの数字 embedding layer へと引き渡されることで浮動小数点の配列へと変換されます。
これらトークンを浮動小数点へと変換するWord Embeddingsはweb上で掲載されています。これらのWord Embeddingsはwikipediaなどの膨大なサイズのcorpusで鍛えられたものです。ULMFiTの手法を用いて、fast.aiライブラリはpre-trained Language Modelsを用いて、fine-tuneすることに焦点を絞っています。Word embeddingsとは、具体的に300から400の小数点を異なる単語を表すために鍛えられたもので、pre-trained language model はこれらの特性を備えているだけではなく、文や文章を表現する性質も備わっております。
注記: ライブラリは以下の3ステップで構成されています。
- データを最小限のコードで前処理を済ませる
- pre-trained された language model をベースに、データセットを用いてfine-tuneする
- 分類器などのモデルをlanguage modelの上に載せる。
1000レビューに抽出されたIMDBデータセットを用いる(陽性または陰性)
path = untar_data(URLs.IMDB_SAMPLE)
path
PosixPath('/home/ubuntu/.fastai/data/imdb_sample')
データセットをテキストから作成するには以下の方法がベストです
- ImageNet スタイルにフォルダへ整理されている
- csv ファイルへラベルの欄とテキスト欄へ整理されている
こちらの例ではimdbをtexts.csvファイルから読み込んで以下のようになっております。
df = pd.read_csv(path/'texts.csv')
df.head()
label | text | is_valid |
---|---|---|
0 | negative | Un-bleeping-believable! Meg Ryan doesn't even ... |
1 | positive | This is a extremely well-made film. The acting... |
2 | negative | Every once in a long while a movie will come a... |
3 | positive | Name just says it all. I watched this movie wi... |
4 | negative | This movie succeeds at being one of the most u... |
2) データをモデルに最適化する
DataBunchを準備するためには、複数のfactory methodsがデータの構成に応じて存在します。詳細はtext.data。こちらではfrom_csv
メソッドを用いてTextLMDataBunch(Language Modelのためのデータ処理)とTextClasDataBunch(Text Classifierのためのデータ処理)クラスを用います。
# Language model データ処理
data_lm = TextLMDataBunch.from_csv(path, 'texts.csv')
# Classifier model データ処理
data_clas = TextClasDataBunch.from_csv(path, 'texts.csv', vocab=data_lm.train_ds.vocab, bs=32)
これで必要なデータの前処理がなされます。分類器には、vocabulary(wordからidを引き渡す役目)を引き渡すことによって、data_clasがdata_lmと同じdictionaryを用いる点は注意して下さい。
この処理は時間がかかるため、結果を保存するために以下のコードを実行しましょう。
data_lm.save('data_lm_export.pkl')
data_clas.save('data_clas_export.pkl')
これで全ての結果を保存するためのtmp
directoryが作成されます。ロードするためには以下のコードを実行しましょう。
data_lm = load_data(path, fname='data_lm_export.pkl')
data_clas = load_data(path, fname='data_clas_export.pkl', bs=16)
注記:DataBunch
のパラメータを設定できます。(batch size
, bptt
,...)
3) language modelをfine-tuneする
data_lm
を用いてlanguage modelをfine-tuneしましょう。fast.ai は、AWD-LSTM architectureの英語モデルを用意してるので、それとpretrained weightsをダウンロードし、fine-tuneするためのlearner
オブジェクトを作成しましょう
learn = language_model_learner(data_lm, AWD_LSTM, drop_mult=0.5)
learn.fit_one_cycle(1, 1e-2)
Total time:00:13
epoch train_loss valid_loss accuracy 1 4.514897 3.974741 0.282455
画像認識モデルと同様に、モデルをunfreeze
することでさらにfine-tuneすることができます。
learn.unfreeze()
learn.fit_one_cycle(1, 1e-3)
Total time: 00:17
epoch train_loss valid_loss accuracy 1 4.159299 3.886238 0.289092
モデルを評価するために、以下のLearner.predict
を実行することで、単語とその数を指定し予測させることができます。
learn.predict("This is a review about", n_words=10)
'This is a review about dog - twist credited , and that , along with'
あまり意味は通じませんが(小さいvocabularyのため)ここでは基本的な文法をmodelが習得していることは驚愕すべきことです。(pretrained modelが可能にしたもの)
最後にencoderを保存して分類モデルに用いるようにできるようにしましょう。
learn.save_encoder('ft_enc')
4) 分類モデルを作成する
ここでは、先述して作成したdata_clas
オブジェクトを用いて、分類器をencoderを用いて新たに作成します。learner
オブジェクト自体はたった一行のコードで作成できます。
learn = text_classifier_learner(data_clas, AWD_LSTM, drop_mult=0.5)
learn.load_encoder('ft_enc')
data_clas.show_batch()
text target xxbos xxmaj raising xxmaj victor xxmaj vargas : a xxmaj review \n \n xxmaj you know , xxmaj raising xxmaj victor xxmaj vargas is like sticking your hands into a big , xxunk bowl of xxunk . xxmaj it 's warm and gooey , but you 're not sure if it feels right . xxmaj try as i might , no matter how warm and gooey xxmaj raising xxmaj negative xxbos xxmaj now that xxmaj che(2008 ) has finished its relatively short xxmaj australian cinema run ( extremely limited xxunk screen in xxmaj xxunk , after xxunk ) , i can xxunk join both xxunk of " xxmaj at xxmaj the xxmaj movies " in taking xxmaj steven xxmaj soderbergh to task . \n \n xxmaj it 's usually satisfying to watch a film director change his style / negative xxbos i really wanted to love this show . i truly , honestly did . \n \n xxmaj for the first time , gay viewers get their own version of the " xxmaj the xxmaj xxunk " . xxmaj with the help of his obligatory " hag " xxmaj xxunk , xxmaj james , a good looking , well - to - do thirty - something has the chance negative xxbos xxmaj to review this movie , i without any doubt would have to quote that memorable scene in xxmaj tarantino 's " xxmaj pulp xxmaj fiction " ( xxunk ) when xxmaj jules and xxmaj vincent are talking about xxmaj mia xxmaj wallace and what she does for a living . xxmaj jules tells xxmaj vincent that the " xxmaj only thing she did worthwhile was pilot " . negative xxbos xxmaj how viewers react to this new " adaption " of xxmaj shirley xxmaj jackson 's book , which was promoted as xxup not being a remake of the original 1963 movie ( true enough ) , will be based , i suspect , on the following : those who were big fans of either the book or original movie are not going to think much of this one negative
learn.fit_one_cycle(1, 1e-2)
Total time: 00:33
epoch train_loss valid_loss accuracy 1 0.650518 0.599687 0.691542
再度modelをunfreezeしてfine-tuneしましょう。
learn.freeze_to(-2)
learn.fit_one_cycle(1, slice(5e-3/2., 5e-3))
Total time: 00:38
epoch train_loss valid_loss accuracy 1 0.628320 0.563579 0.716418
learn.unfreeze()
learn.fit_one_cycle(1, slice(2e-3/100, 2e-3))
Total time: 00:56
epoch train_loss valid_loss accuracy 1 0.533411 0.539693 0.721393
そして、Learner.predict
を用いてテキストを予測してみましょう。
learn.predict("This was a great movie!")
(Category positive, tensor(1), tensor([0.0118, 0.9882]))