Pytorch:テキストの前処理(torchtext)④
はじめに
torchtextの使い方に関するメモ。
入力の素性をカスタマイズしたい場合について
例えば、各系列に付与したカラムを入力に含めたい場合
(0,1は系列の何らかの情報)
a 1 b 0 c 1 d 0 e 1 f 0
これをどうハンドリングするかについて少し考えた。
簡単な方法
多分、一番簡単な方法は以下のように系列カラムと同じように処理するだけ。
TEXT = data.Field() LABEL = data.Field() train = datasets.SequenceTaggingDataset( path=data_dir, fields=[('text', TEXT), ('label', LABEL)]) TEXT.build_vocab(train) LABEL.build_vocab(train)
これだけで基本的には問題ない。
ただ、思ったのは素性が数値の場合、わざわざ「辞書作り」する必要があるのかってこと。
別に辞書作りをしても全く問題ないが、個人的にはそのまま入力できないかなって思った。
で、どうするのが良いか考えてみた。
そのまま処理する方法
1.入力の数値変換
結論としては、そのまま処理できないので、工夫が必要。
まず、初めにデータをDatasetで読み込んだ場合、全ての入力は「文字列」として扱われる。
train.examples[0].label # ['1', '0', '1']
そして、辞書を作らずにそのまま処理した場合、バッチ化のところで「文字は扱えないよ」って怒られる。
なので、まずはここで入力を数値変換する必要がある。
Datasetでハンドリングできるかもしれないが、ここでは Fieldのpreprocessing
で変換させる。
def to_int(x): return list(map(int, x)) LABEL = data.Field(use_vocab=False, preprocessing=to_int)
これで、入力情報を数値変換できる。
train.examples[0].label # [1, 0, 1]
2.pad値の指定
続いて、バッチのpadding時の値を指定する。
これはデフォルトの場合、<unk>
となっているので、このままではまたも怒られる。
そこで、paddingの値をpad_token
で明示する。
LABEL = data.Field(sequential=True, use_vocab=False, preprocessing=to_int, pad_token=-1)
※指定する値は入力で使用しない値をしておくのが無難。
バッチ処理までをまとめて書くとこんな感じ。
from torchtext import data, datasets data_dir = 'test_ner.txt' def to_int(x): return list(map(int, x)) TEXT = data.Field() LABEL = data.Field(sequential=True, use_vocab=False, preprocessing=to_int, pad_token=-1) train = datasets.SequenceTaggingDataset( path=data_dir, fields=[('text', TEXT), ('label', LABEL)]) TEXT.build_vocab(train) rain_iter = data.BucketIterator(dataset=train, batch_size=2, device=-1, repeat=False) for i, train_batch in enumerate(train_iter): print('text : \n', train_batch.text) print('label : \n', train_batch.label) """ text : tensor([[7]]) label : tensor([[0]]) text : tensor([[5, 2], [6, 3], [1, 4]]) label : tensor([[0, 1], [1, 0], [9, 1]]) """
全く持って自己満足に過ぎないが、備忘録として残しておく。