機械学習・自然言語処理の勉強メモ

学んだことのメモやまとめ

Pytorch:テキストの前処理(torchtext)②

前回のtorchtextの使い方の続き。

kento1109.hatenablog.com

今回、実際の処理でどうすれば良いんだってなったところを確認する。

訓練用と検証用



訓練用と検証用のデータを取り込む。
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]