TorchTextとRandom Forestで文書分類


はじめに

 PyTorchのtochtextで文書分類の続きです。前回はtorchtextのチュートリアルに沿って実装を解説しました。今回はtorchtextのデータを使ってrandom forestでの学習を行う方法を解説します。

復習

 今回はtf-idf形式にデータを加工した上でrandom forestfitさせます。普通にsklearnTfidfVectorizerを使えばいいように思えますが、torchtextのデータをそのままTfidfVectorizerに放り込むことはできません。理由はtorchtextから取り出せるデータの構造がTfidfVectorizerの入力として可能なものではないからです。torchtextではN-gram形式でデータを保持しています。一方TfidfVectorizerにはraw textつまり原文を入力する必要があります。実装においてはこのギャップを最初に埋めます。

開発環境

Google Colab

実装

0. pip install, importなど

 前回と同様にimport等を行います。mountする理由は後述します。

# mount
from google.colab import drive
drive.mount('/content/gdrive/')
%cd 'gdrive/My Drive/Colab Notebooks/'
%ls

#install PyTorch
!pip install torch 
!pip install torchtext==0.5
%matplotlib inline

#import modules
from torchtext.datasets import text_classification
import csv
import os
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import GridSearchCV

1. データの用意

 データを用意していきます。今回自前で処理を書く必要があるのがtrain_corpus変数の定義以降の部分です。なおGoogle Colabの場合、csvファイルからデータを直接得るためにmountが必要です。 


if not os.path.isdir('./.data'):
  os.mkdir('./.data')
SAMPLE_NUMBER = 100
K = 5
train_dataset, test_dataset = text_classification.DATASETS['AG_NEWS'](
    root='./.data', ngrams=NGRAMS, vocab=None
)

train_corpus = []
train_labels = []
with open('./.data/ag_news_csv/train.csv', 'r') as f:
  train_csv = csv.reader(f)
  for row in train_csv:
    train_labels.append(row[0])
    train_corpus.append(row[-1])

test_corpus = []
test_labels = []
with open('./.data/ag_news_csv/test.csv', 'r') as f:
  train_csv = csv.reader(f)
  for row in train_csv:
    test_labels.append(row[0])
    test_corpus.append(row[-1])

2. tf-idf作成

 traintestで使用する関数が違うので注意してください。fit_transformを使用するとvectorizerで保持している行列が変更されます。使用するデータが異なる場合、新規で作成したtf-idf matrixは異なります。従って、fit_transformを再度使用するとscore計算においてエラーが発生します。そのため、既存の行列構造を保持しながら変換を行うtransform関数をtestデータに対して適応しています。

# create tf-idf
vectorizer = TfidfVectorizer()
train_matrix = vectorizer.fit_transform(train_corpus)
test_matrix = vectorizer.transform(test_corpus)

3. Random Forest

 tf-idfを用意できたので実際にfitさせます。そのままでもいいですが、せっかくなのでgrid-searchを使ってモデルを選択します。ちなみに今回は処理時間削減のために一部のみをfitに利用しています。学習用サンプル数1万程度でも0.8以上の精度は出るようです。

# randomforest
forest = RandomForestClassifier()

# grid-searchをしないならそのままfit
# forest.fit(train_matrix[:SAMPLE_NUMBER], train_labels[:SAMPLE_NUMBER])

# grid-search
param_grid = {"n_estimators":[10,20,30,40,50,60,70,80,90,100]}
tree_grid = GridSearchCV(
    estimator=forest,
    param_grid=param_grid,
    scoring='accuracy',
    cv=K
)
tree_grid.fit(train_matrix[:SAMPLE_NUMBER], train_labels[:SAMPLE_NUMBER])
tree_grid_best = tree_grid.best_estimator_
# check classifier's performance
print("Best Model Parameter: ",tree_grid.best_params_)
print("Best Model Score    : ",tree_grid.best_score_)

終わりに

 今後もtorchtext.text_classification関係で実装を公開していこうと思います。