はじめに
この半年間でデータ分析を学習しました。 そこで学んだ技術を使って、ツイッターアカウントが人間かボットかを分類するモデルを作成し、その分析結果をまとめてみました。
解決したい社会問題
近年、生成AIを利用した信憑性の低い情報が拡散されるという問題が深刻化しています。このような状況の中で、人間が執筆した記事とボットによって生成された記事を判別できるモデルを構築し、この問題の解決に貢献したいと考えました。
実行環境
パソコン:Windows 10 Home
開発環境:Google Coraboratory
言語:Python
ライブラリ:Matplotlib、pandas、numpy、seaborn
分析の流れ
1.ライブラリのインポート
2.データの確認
3.決定木分類器modelを構築する
4.テストデータに対する予測結果の評価指標を表示する
5.モデルの改善のため、ランダムフォレストmodelを構築する
6.テストデータに対する予測結果の評価指標を表示する
データの確認
# ライブラリ「pandas」をインポートし、pandasをpdという短い名前で呼び出せるようにする。
import pandas as pd
# 読み込んだデータをpandasのデータフレーム(df)として保持する。
# index_col=0: 読み込むファイルの最初の列(0番目の列)をデータフレームのインデックス(行ラベル)として使用する。
# sep='\t': ファイルがタブ区切り (\t) であることを指定する。通常の CSV(カンマ区切り)ではなく、TSV(タブ区切り)にする。
df = pd.read_csv('/content/train.tsv', index_col=0, sep='\t')
# デフォルトで先頭5行を表示。
df.head()
# タプル (行数, 列数) を確認する。
df.shape
# pandasデータフレーム(df)の概要情報を表示する。
df.info()
欠損値が無いことを確認した。
可視化したデータ
# pandasデータフレームdfの数値列(floatやint型の列)についてヒストグラム(度数分布図)を描画する。
df.hist(figsize=(20, 15), bins=30)
可視化したデータから得られた情報
ボット(1)のデータ数がボットでない(0)のデータ数に比べ、約6分の1しかない。
学習データとテストデータの準備
# pandasのデータフレームdfから特定の列(bot列)を削除し、残りのデータをNumPy配列に変換して変数Xに格納する。
X = df.drop(columns=['bot']).to_numpy()
# pandasデータフレームdfのbot列を抽出し、それをNumPy配列(numpy.ndarray型)に変換して、変数yに格納する。
y = df['bot'].to_numpy()
# scikit-learn(機械学習ライブラリ)のmodel_selectionモジュールからtrain_test_split関数をインポートする。
from sklearn.model_selection import train_test_split
# X(特徴量データ)とy(ラベルデータ)を訓練用データ(X_train, y_train)とテスト用データ(X_test, y_test)に分割する処理を行う。
# train.csv から 訓練用データ(X_train, y_train)とテスト用データ(X_test, y_test)を作成する。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
# 訓練用データおよびテスト用データの形状(shape)を表示する。
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
決定木モデルの作成
# scikit-learnライブラリのtreeモジュールからDecisionTreeClassifierクラスをインポートする。
from sklearn.tree import DecisionTreeClassifier
# DecisionTreeClassifierは、scikit-learnライブラリのtreeモジュールに含まれるクラスで、分類問題を解くための決定木アルゴリズムを実装している。
# random_state=0を指定すると、シード値として0を使うことになる。これにより、同じコードを実行するたびに同じ結果を得ることができる。
model = DecisionTreeClassifier(random_state=0)
# 決定木分類器(model)を訓練する処理を行う。訓練データX_trainとその対応するラベルy_trainを使って、モデルを学習させる。
model.fit(X_train, y_train)
# trainデータに対する予測結果の評価指標を表示する。
y_pred_train = model.predict(X_train)
# 分類問題のモデル評価を行う。
from sklearn.metrics import classification_report
# 訓練データ(y_train)に対する予測結果(y_pred_train)の評価を出力する。
print(classification_report(y_train, y_pred_train))
# 訓練されたモデル(model)を使って、テストデータ(X_test)に対する予測を行い、その結果をy_predに格納する。
y_pred = model.predict(X_test)
# テストデータ(X_test)に対するモデルの予測結果を表示。これらの予測結果は、モデルが学習したパターンに基づいて、各テストサンプルのクラスラベル(カテゴリ)を予測したものである。
y_pred
# テストデータにおける正解ラベル(またはクラスラベル)の配列。
# モデルが予測したクラスラベル(y_pred)と比較するために使用する。これにより、モデルの予測がどれだけ正確であるかを評価できる。
y_test
# 分類モデルの性能を評価するために、classification_report関数を使って、テストデータに対する予測結果の評価指標を表示する。
print(classification_report(y_test, y_pred))
ボット=1のF値は0.62と低い。また、正解率も0.87と低く過学習をしている。
モデルの改善1ランダムフォレスト
from sklearn.ensemble import RandomForestClassifier
model_rf = RandomForestClassifier(random_state=0)
# ランダムフォレスト分類器(model_rf)を訓練する処理を行う。具体的には、訓練データX_trainとその対応するラベルy_trainを使って、モデルを学習させる。
model_rf.fit(X_train, y_train)
# trainデータに対する予測結果の評価指標を表示する。
y_pred_train = model_rf.predict(X_train)
# モデルが訓練データに対してどの程度正確に予測できたかを示す。
print(classification_report(y_train, y_pred_train))
# 訓練されたモデル(model)を使って、テストデータ(X_test)に対する予測を行い、その結果をy_predに格納する。
y_pred = model_rf.predict(X_test)
ボット=1のF値は0.62と低い。また、正解率も0.90と決定木モデルに比べると少し改善されたが、学習データに比べると低く過学習をしている。
モデル改善2ランダムフォレスト
# RandomForestClassifier をハイパーパラメータを指定して機械学習モデルを訓練する。
# ランダムフォレストにおける決定木の数を指定する。ここでは 150 本の決定木を使用する。
# 各決定木の最大の深さを指定する。ここでは、各木の深さが最大 5 に制限されることを意味する。
# モデルの結果が再現可能になるように乱数の種(シード値)を設定する。
model_rf2 = RandomForestClassifier(n_estimators = 150, max_depth = 5,class_weight = "balanced", random_state = 0)
model_rf2.fit(X_train, y_train)
y_pred = model_rf2.predict(X_train)
# 分類モデルの性能を評価するために、classification_report関数を使って、学習データに対する予測結果の評価指標を表示する。
print(classification_report(y_train, y_pred))
y_pred = model_rf2.predict(X_test)
# 分類モデルの性能を評価するために、classification_report関数を使って、学習データに対する予測結果の評価指標を表示する。
print(classification_report(y_test, y_pred))
テストデータのボット=1のF値は0.68に改善されたが、依然として低い。今後改善する必要がある。
課題
(1) 今回、人間が執筆した記事とボットによって生成された記事を判別できるようにするために、決定木分類器modelの構築を試みた。決定木分類器modelではF値が低く、過学習が起こっていた。改善のため、ランダムフォレストmodelを構築したところ、決定木分類器modelよりもF値が改善された。しかし、依然としてボット=1のF値が低いため、今後さらに改善する必要がある。
(2) どのようなデータがボットなのかを今後分析する必要がある。
まとめ
今回使用したデータはボットのデータ数がボットでないデータ数に比べ、約6分の1しかなかった。偏りのあるデータをscikit-learnのランダムフォレストでクラス分類を行う際はclass weight を設定するなど、工夫する必要がある。