
本記事ではLightGBMとtf-idfを使って自然言語処理モデルを作る方法を解説します。
意外と簡単に実装できるのでおススメです!

文字データの機械学習ってどうしたらいいんだろう。
なんか難しくて自分にはできなさそう。
こんな方のために簡単に実装できる自然言語処理モデルを紹介します。
現在有力なモデルはBERTですが、ちょっと計算が重くGPUが欲しいアルゴリズムです。
CPUで計算できるような簡単なモデルを作りたい場合は、LightGBMとtf-idfを使いましょう。
fetch_20newsgroups
モデルを作るために文字データが必要なので、scikit-learnにあるデータセットを使います。
from sklearn.datasets import fetch_20newsgroups
train_data = fetch_20newsgroups(subset = 'train')
valid_data = fetch_20newsgroups(subset = 'test')
“fetch_20newsgroups”は20グループに分けられた文字データセットです。
引数”subset”を”train”にすると学習データ、”valid”にすると評価データが得られます。
import pandas as pd
train = pd.DataFrame({"text" : train_data["data"], "target" : train_data["target"]})
valid = pd.DataFrame({"text" : valid_data["data"], "target" : valid_data["target"]})
print(train.shape, valid.shape)
train.head()

このように文字データとラベルが入った表ができるはずです。
文字を取り出してみましょう。↓
print(train["text"].values[0])

メールの文面みたいですね。
ラベルは“target”の列に入っており、7番です。
print(train_data.target_names)
print(train_data.target_names[7])
“target_names”にラベル名が入っています。合計で20クラスです。
7番目は”rec.autos”つまり車関係ということですね。
今回は“text”の文字データから”target”のラベルを予測しましょう。
tf-idf
機械学習モデルは文字をそのまま受け取ることはできません。
必ず数値にする必要があります。
なので文字を数値に置き換える変換をしましょう。
ここで有効な変換方法がtf-idfです。
tf-idfの数学的な説明は私にはできませんのでぜひ調べてみてください。
私は、単語の出現頻度とレア度をうまくベクトル化する手法程度に理解しています。

文章の特徴を数値化するってくらいに思っとけばOK。
from sklearn.feature_extraction.text import TfidfVectorizer
sklearnの”feature_extraction”に“TfidfVectorizer”があります。
vectorizer = TfidfVectorizer(max_features = 1000)
X_train = vectorizer.fit_transform(train["text"].values)
X_valid = vectorizer.transform(valid["text"].values)
TfidfVectorizerの”fit_transform”で学習データ(train)に対応させます。
評価データ(valid)は本来未知のデータなのでtransformだけで変換してください。
“max_features”はデータの次元数です。列方向のデータサイズに関係します。
大きければ大きいほどデータの表現力が上がりますが、計算が重くなるので注意。
print(X_train.shape, X_valid.shape)
shapeで変換後のデータサイズを見てみましょう。
行方向はもともとのデータの行数のままで、列方向が”max_features”の数値と同じはずです。
以上で文字⇒数値の変換が完了しました。モデルに入れてみましょう。
モデル作成(LightGBM)
今回はLightGBMの多クラス分類モデルを作ります。
モデル作成手順は以下の通り。
②パラメータ設定
③学習
import lightgbm as lgb
“lightgbm”をインポートします。よくlgbと略されます。
train_set = lgb.Dataset(X_train, train["target"].values)
valid_set = lgb.Dataset(X_valid, valid["target"].values)
データをDataset形式に変換しました。
特徴量としてif-idf変換した数値ベクトルを、目的変数として”target”を渡してください。
次にパラメータを設定します。
params = {
"objective" : "multiclass",
"metric" : "multi_logloss",
"num_class" : 20
}
metric:評価指標。多クラスならmulti_logloss。
num_class:クラス数。今回は20。
最後にtrainで学習します。
model = lgb.train(
params = params,
train_set = train_set,
valid_sets = [train_set, valid_set],
num_boost_round = 300,
early_stopping_rounds = 10,
verbose_eval = 20,
)
early_stopping_rounds:指定した回数だけ性能が改善しないとストップ。
verbose_eval:結果を表示する頻度。

このように学習結果が出力されます。
lossが下がっているのでうまく学習が進んでいるとわかりますね。
予測結果
predictで予測できます。評価データを渡しましょう。
preds = model.predict(X_valid)
print(preds.shape)
予測値は各ラベルに該当する確率となっています。
なのでデータサイズは(元データの行数, ラベル数)にです。
preds = preds.argmax(axis = 1)
print(preds)
print("=" * 50)
print(valid["target"].values)

argmaxを列方向(axis = 1)に実行すると最も値が大きい列番号が出力されます。
つまり最も予測確率の大きいラベルを予測結果にするということです。
実際の正解データと比較すると同じ数値になっていますね。
正解率を計算してみましょう。↓
from sklearn.metrics import accuracy_score
acc = accuracy_score(valid["target"].values, preds)
print(acc)
“accuracy_score”をインポートします。
正解データと予測値を入れると正解率を計算してくれます。
だいたい60%強くらいかと思います。
max_featuresと予測精度
TfidfVectorizerの変換時に”max_features”を1000に設定しました。
この値を小さくすると列数が減り、学習が早くなる一方でデータの表現力が落ちます。
MAX_FEATURES = 100
vectorizer = TfidfVectorizer(max_features = MAX_FEATURES)
X_train = vectorizer.fit_transform(train["text"].values)
X_valid = vectorizer.transform(valid["text"].values)
train_set = lgb.Dataset(X_train, train["target"].values)
valid_set = lgb.Dataset(X_valid, valid["target"].values)
model = lgb.train(
params = params,
train_set = train_set,
valid_sets = [train_set, valid_set],
num_boost_round = 300,
early_stopping_rounds = 10,
verbose_eval = 20,
)
preds = model.predict(X_valid).argmax(axis = 1)
acc = accuracy_score(valid["target"].values, preds)
print(MAX_FEATURES, acc)
“max_features”を100にしました。
実行すると学習が早く終わり、正解率が30%くらいに下がっているかと思います。
一方で5000にすると正解率75%を超えました。
このように学習時間と性能との兼ね合いになりますね。
ちなみに”max_features”を設定しないデフォルトだと、列数は130107で正解率77%くらいです。

あんまり大きくしすぎても、
時間が長くなるだけで性能の見返りが小さかったりする。
まとめ:自然言語処理モデルを作ってみよう
今回はtf-idfとLightGBMで自然言語処理モデルを作る方法を解説しました。
CPUで手軽に実装できる方法なのでぜひ試してみてください!
コメント