Pytorch:テキストの前処理(torchtext)②
前回のtorchtextの使い方の続き。
今回、実際の処理でどうすれば良いんだってなったところを確認する。
訓練用と検証用
訓練用と検証用のデータを取り込む。
Datasetクラスのsplitsメソッドが使用できる。
使い方は以下の通り
TEXT = data.Field() train, dev = data.TabularDataset.splits(path=base_path, train='train.tsv', validation='dev.tsv', format='tsv', fields=[('text', TEXT)])
- train.tsv
This movie was awesome The dog was too big to have in my house My mother is good at cooking We like chatting
- dev.tsv
This banana was made in Philippines I like small dog
辞書作成
TEXT.build_vocab(train) print(TEXT.vocab.freqs.keys()) [u'house', u'awesome', u'at', u'have', u'in', u'We', u'movie', u'cooking', u'to', u'too', u'was', u'is', u'good', u'chatting', u'This', u'big', u'The', u'My', u'like', u'dog', u'mother', u'my']
データセットにtrain
を指定すると、当然訓練用の単語のみの辞書となる。(検証用にのみ存在するPhilippines
などは含まれていない)
検証用の単語も含めたい場合、
TEXT.build_vocab(train, dev) TEXT.vocab.freqs [u'house', u'awesome', u'at', u'have', u'in', u'We', u'movie', u'cooking', u'to', u'too', u'was', u'is', u'good', u'chatting', u'This', u'big', u'Philippines', u'The', u'My', u'made', u'I', u'like', u'dog', u'banana', u'mother', u'small', u'my']
とする必要がある。
また、バッチ化する時も同様にsplitsメソッドが使える。
訓練用の場合は下記のようにしたが
train_iter = data.BucketIterator(dataset=train, batch_size=train_batch_size)
2つのIteratorを作る場合は以下のように指定する。
train_iter, val_iter = data.BucketIterator.splits(
(train, val, test), batch_sizes=(train_batch_size, len(dev)))
テストデータの予測
文章の極性分類問題を考える。
テストデータの極性を予測したい場合、どのように前処理を行うべきか。
例えば、以下をどのようにて処理すべきか。
test_sent = 'I like watching movie'
まずは文章を単語に分割する。
今回のようにスペースで区切られている場合、デフォルトのFieldクラスのpreprocessメソッドで問題ない。
test_sent = TEXT.preprocess(test_sent) [u'I', u'like', u'watching', u'movie']
次に単語を辞書に基づきインデックスに変換する。
test_idx = [[TEXT.vocab.stoi[x] for x in test_sent]] [[7, 6, 0, 24]]
watching
は未知語なので、0に変換されている。
次にテンソル型に変換する。
TEXT.tensor_type(test_idx) 7 6 0 24 [torch.LongTensor of size 1x4]
最後にautogradでラップする。
test_idx = torch.autograd.Variable(test_idx, volatile=True) Variable containing: 7 6 0 24 [torch.LongTensor of size 1x4]
予測時は重みの更新をしないので、微分計算も不要。
その場合、volatile
を指定することで、メモリの節約が可能。
これで
model(test_idx)
などでモデルの入力として扱えるようになる。
最後に、予測結果をラベルに再度変換する場合の注意。
一般的にはこのようにして
out = model(x) _, predicted = torch.max(out, 1)
ラベルの予測結果を取得する場合が多い。
例えば、2値分類の場合、0,1の何れかかが返ってくる。
それをラベルに戻す場合、以下のようにしてはいけない。
LABEL.vocab.itos[predicted.data[0]]
なぜなら、
LABEL.vocab.itos ['<unk>', u'1', u'-1']
で分かるように先頭は<unk>
だからである。
なので、以下のように正しいラベルを取得する場合は「+1」する必要がある。
LABEL.vocab.itos[predicted.data[0]+1]