fastai v2による深層学習
深層学習ライブラリfastai
fastaiは最も簡単に深層学習を行うことができるPythonのパッケージです.毎年3月くらいに行われる講義を無料で公開してきましたが,2020年度はコロナの影響で(中心人物がマスクの普及に奔走していたために)8/22にやっと公開されました.2020年度版では本(の原稿のJupyter Notebook)も公開されています.
- fastaiの無料講義
- 本のgithubリポジトリ
- ドキュメント(マニュアル)
2020年度の講義で使うために,fastaiのバージョンも2にあがりました.簡単に使用法をご紹介していこうと思います.
インストール
GPU付きのlinuxにインストールします.最も簡単なのはGoogle Colab. です.このページから直接本の各章のノートをGoogle Colab.で開くことがでいます.
実は,Colab.からpublicに設定されたgithubのページは簡単に開けます.たとえば,第3章を開くには,
https://colab.research.google.com/github/fastai/fastbook/blob/master/03_ethics.ipynb
とします.
Google Colab.にはfastaiの元になるPyTorchがすでにインストールされているので,ランタイムをGPUに変更してから
!pip install -Uqq fastbook
import fastbook
fastbook.setup_book()
とすればインストール完了です.
最初の例題(犬猫の判別)
例として,犬と猫を判別してみましょう.まず,必要なモジュールをインポートします.
from fastbook import *
from fastai.vision.all import *
次にデータを読み込み,猫かどうかを返す関数is_catを準備します.PETSデータセットでは最初の文字が大文字なら猫です.
この関数を用いてデータローダーを生成し,34層のRESNETを用いた学習器を作り,転移学習データを用いて,転移学習用の最適化メソッド fine_tuneを用いて1エポックだけ訓練します.
path = untar_data(URLs.PETS)/’images’def is_cat(x): return x[0].isupper()
dls = ImageDataLoaders.from_name_func(
path, get_image_files(path), valid_pct=0.2, seed=42,
label_func=is_cat, item_tfms=Resize(224)learn = cnn_learner(dls, resnet34, metrics=error_rate)
learn.fine_tune(1)
これだけで,以下の結果が得られます.誤差率(1-正解率)は非常に小さいことが見てとれます.
epoch | train_loss | valid_loss | error_rate | time |
---|---|---|---|---|
0 | 0.144485 | 0.030431 | 0.008796 | 01:26 |
epoch | train_loss | valid_loss | error_rate | time |
---|---|---|---|---|
0 | 0.050339 | 0.011808 | 0.003383 | 02:01 |
上欄が最終層以外を固定して訓練した1エポック,下欄がすべての層を自由にして訓練した1エポックを表します.
1バッチ分の結果を表示させると以下のようになります.すべて正解になっていることが確認できます.
手書き文字認識
次に,深層学習の”Hello World”でもあるMNISTデータセットで手書き文字の分類をしてみましょう.データを読み込んで画像用のデータローダーを生成します.
path = untar_data(URLs.MNIST)
dls = ImageDataLoaders.from_folder(path,train=”training”,valid=”testing”)
次に,学習器learnを生成してから,学習率決定のためのlr_findメソッドを呼び出します.
learn = cnn_learner(dls, resnet34, metrics=[error_rate,accuracy],cbs=ShowGraphCallback())
lr_min, lr_steep = learn.lr_find()
print(lr_min, lr_steep)
>> 0.014454397559165954 0.005248074419796467
lr_findの返値は,損失関数が最小になる学習率の1/10 (lr_min) と,傾きが最大になる学習率 (lr_steep) のタプルです. この2つの値の間あたりが,良い学習率となるので,ここでは. base_lrを0.02に設定して訓練をしてみます.
learn.fine_tune(2, base_lr=0.02)
epoch | train_loss | valid_loss | error_rate | accuracy | time |
---|---|---|---|---|---|
0 | 0.255310 | 0.137086 | 0.038300 | 0.961700 | 01:16 |
epoch | train_loss | valid_loss | error_rate | accuracy | time |
---|---|---|---|---|---|
0 | 0.069197 | 0.053692 | 0.013500 | 0.986500 | 01:24 |
1 | 0.027597 | 0.019030 | 0.005200 | 0.994800 | 01:25 |
fine_tuneメソッドでは,最終層以外を固定して(既定値では1回)訓練を行い、その後、学習率と慣性項を変化させながら訓練を行う fit_one_cycleを用いて,指定したエポック数だけ訓練します。fiit_one_cycleは,学習率を小さな値から最大学習率まで増やし,その後徐々に減少させていくと同時に,慣性項を徐々に下げて,その後増加させていきます. これを使うと超収束すると言われています.
これによって,正解率は99.5%となりました.こちらのサイトよると,この数値は,数年前の世界記録です.
テキストデータ
画像だけでなく,テキストデータの処理でもfastaiは優秀です.キーになるのは,言語モデルに対する転移学習です.
言語モデルとは,文章を与えたとき,その後に続く文章を予測する訓練を行うことによって,単語を数値ベクトルで表すエンコーディングを行うものです. fastaiでは,Wikipediaの膨大なテキストデータを用いた学習済みのモデルであるAWD_LSTMを準備しています. 映画の批評データを例として,fastaiのテキストデータ処理を試してみましょう.
まず,映画批評のデータセットと学習済のパラメータAWD_LSTMを読み込んで言語モデルの学習器をつくります.
from fastai.text.all import *
path = untar_data(URLs.IMDB)
get_imdb = partial(get_text_files, folders=[‘train’, ‘test’, ‘unsup’])
dls_lm = DataBlock(
blocks=TextBlock.from_folder(path, is_lm=True),
get_items=get_imdb, splitter=RandomSplitter(0.1)
).dataloaders(path, path=path, bs=128, seq_len=80)
learn = language_model_learner(
dls_lm, AWD_LSTM, drop_mult=0.3,
metrics=[accuracy, Perplexity()]).to_fp16()
これによって,次の単語を出力(予測)することがでいます.試しに,ピコ太郎の歌の続きを作詞してもらいましょう.
TEXT = “This is a pen. That is an”
N_WORDS = 40
N_SENTENCES = 2
preds = [learn.predict(TEXT, N_WORDS, temperature=0.75)
for _ in range(N_SENTENCES)]
print(preds)
>>[“This is a pen . That is an allusion to what i ‘ ve known as The Radio Times . BBC Radio 1 ! is an example of how a different composer can work with an orchestra and which contains over half a”, ‘This is a pen . That is an especially unusual phrase for an artist who has been ascribed to the term , and is sometimes referred to as the ” Artist Generation ” . The term is sometimes defined as defining the evolution of the’]
今度は,この言語モデルを用いて,映画の批評のテキストが,ネガティブかパシティブかを判別する学習器をつくります.
dls = TextDataLoaders.from_folder(untar_data(URLs.IMDB), valid=’test’)
learn = text_classifier_learner(dls, AWD_LSTM, drop_mult=0.5, metrics=accuracy)
learn.fine_tune(4, 1e-2)
epoch | train_loss | valid_loss | accuracy | time |
---|---|---|---|---|
0 | 0.598281 | 0.404613 | 0.822120 | 04:11 |
epoch | train_loss | valid_loss | accuracy | time |
---|---|---|---|---|
0 | 0.318746 | 0.245778 | 0.898840 | 07:56 |
1 | 0.249433 | 0.221797 | 0.908000 | 08:07 |
2 | 0.183325 | 0.190910 | 0.926360 | 08:19 |
3 | 0.153639 | 0.194017 | 0.926240 | 08:11 |
言語モデルに対して訓練しなくても93%程度の正解率で,批評がポシティブか否かを当てられるようになりました.