4記事にわたり、複数の古典的ngram言語モデルについて試しに実装してきました。
torchtextのデータセットを使ってきたので、pytorchで簡単な言語モデルを作ってみます。
元となる論文があるわけではないですが、ネット上に多数実装が多数あるので、それらを参考にしました。
実装コードは gist を参照してください。一番下に埋め込んでます。
参考資料について軽くまとめます。
アーキテクチャ
NgramModel( (embedding): Embedding(28782, 100) (linear1): Linear(in_features=200, out_features=128, bias=True) (linear2): Linear(in_features=128, out_features=28782, bias=True) )
- 入力単語を語彙数×次元数で表現する Embedding
- 活性化関数 Relu
- 線形変換1 Linear
- 線形変換2 Linear
- 確率値として出力 log_softmax
という比較的簡単な構造。
Embedding層はいわゆるword2vecとして単語特徴量を学習する。 Mikolovの論文 (https://arxiv.org/abs/1301.3781) におけるSkipgramやCBOWとは厳密には異なる。
アーキテクチャ参考
- Word Embeddings: Encoding Lexical Semantics — PyTorch Tutorials 1.11.0+cu102 documentation
- pytorch-beginner/N-Gram.py at master · L1aoXingyu/pytorch-beginner · GitHub
- pytorch-word-embedding/NNLM.py at master · jeffchy/pytorch-word-embedding · GitHub
- PyTorch DL for NLP -単語埋め込み、n-gram、CBOW- - fukuの犬小屋
DatasetとDataloader
上記アーキテクチャにおいて参考にしたコードたちはデータを直接コード上に書いてバッチサイズも設定していないことがある。なので実践向き (大きいデータ向き) ではない。
Dataloaderを設定して、ngramをバッチサイズごとイテレートした。
今回使っている torchtext.datasets.WikiText2
はすでにイテレーターなのでDatasetとDataloaderどっちも使う必要があるのかわからなかったが、仕組みを理解したいので使うことにした。
- Datasetではvocabの設定をし、単語を数値に変換したngram単語列と正解単語を返す
- Dataloaderはバッチサイズを設定し、concatしたデータを返す
drop_last=True
でバッチサイズより小さいデータは学習に使わない
Text classification with the torchtext library — PyTorch Tutorials 1.11.0+cu102 documentation (テキスト分類タスク向け)の実装に従ったので、もしかしたら別の方法もあるかもしれない。
学習・評価
今回10epochで実験。
WikiText2の場合テストデータのエントロピーは 4.1636 、 PentTreeDatasetの場合は 4.1657 と小さくなった。 今まで実装してきたモデルでエントロピーが5を切っているモデルはなかったのでかなり良いスコアといえる。
さいごに
公式のtutorial (Welcome to PyTorch Tutorials — PyTorch Tutorials 1.11.0+cu102 documentation) で改めてpytorchを勉強したが、モデルの実装よりデータの扱いについての情報が少なくて結構困った。
日本語ngramデータは公開がされているので頻度ベースのモデルは実装できそうだ。今後試したい。