ロジスティック回帰 + TF-IDFによる感情分析
感情分析のためのモデルを作成していきます。
まずはベンチマークとして、単純なモデルと、単純な特徴量の組み合わせのモデルを作成します。
具体的には、分類器にはロジスティック回帰を、特徴量はTF-IDFによって作成します。
TF-IDFは、Bag of Wordsと同様に、文書データを数値的に表現するための技術の一つです。
目次
TF-IDFとは
TF-IDFは、文書データを数値的に表現するための技術の一つです。Bag of Wordsとの違いは、データセットの文書全体における単語の出現頻度を考慮して、重み付けをしている点です。
文書データを解析すると、すべての文書で頻繁に登場する単語があります。そういった頻繁に登場する単語は、意味のある情報を持たないことが多いです。たとえば、「を」や「です」などの単語は、どんな文書でも出現するが、それ自体は分類に対して意味を持ちません。
TF-IDFは各単語の「各文書での出現頻度」に「全文書での出現頻度の逆数の対数」をかけることによって、意味を持たない単語の重みを減らします。
TF-IDFの計算式
TF-IDFは、以下の式で計算されます。
TFIDF(t,d,D)=TF(t,d)×IDF(t,D)
TFとIDFは、それぞれ以下のように計算されます。
1.TF (単語の出現頻度):各文書内の特定の単語の出現頻度。具体的には、その単語の出現回数を各文書の全単語数で割ったものです。
TF(t,d)= 単語tの文書dにおける出現回数文書dにおける全単語の出現回数 単語tの文書dにおける出現回数文書dにおける全単語の出現回数
2.IDF (逆文書頻度):単語がデータセット全体でどれくらい希少か(または一般的か)を示す値。具体的には、全文書数をその単語が出現する文書の数で割ったものの対数をとった値を示します。
IDF(t,D)=log データセットDの文書数 1+単語tを含む文書数
実装
TF-IDFを使って、精度が上がるかを検証してみます。
データの読み込み
前回の記事で作成した、前処理済みのデータセットを使用します。
■python
import pandas as pd import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score import ast
■python
# データの読み込み
df = pd.read_csv('../data/interim/chabsa-sentiment-analysis-with-kfold-preprocessed.csv')
# tokens列のデータ型をstrからlistに変換
df['tokens'] = df['tokens'].apply(lambda x: ast.literal_eval(x))
df.head()
TF-IDF特徴量を使った精度の計算
■python
# foldごとに以下の処理を行う
# 1. 学習用データと検証用データに分割する
# 2. TF-IDF特徴量を作成する
# 3. モデルを学習する
# 4. 正解率を計算する
for fold_ in range(5):
# 学習用データと検証用データに分割する
df_train = df[df.kfold != fold_].reset_index(drop=True)
df_valid = df[df.kfold == fold_].reset_index(drop=True)
# TFIDFインスタンスを作成する
tfidf_vec = TfidfVectorizer(
tokenizer=lambda x: x,
token_pattern=None,
lowercase=False
)
# 学習用データのtokens列を使ってBoW特徴量を作成する
tfidf_vec.fit(df_train.tokens)
# 正解ラベルと特徴量を作成する
# 特徴量は、学習用データ文章にfitしたTfidfVectorizerを使って、学習用データと検証用データのBoW特徴量を作成する
y_train = df_train.rating
y_valid = df_valid.rating
X_train = tfidf_vec.transform(df_train.tokens)
X_valid = tfidf_vec.transform(df_valid.tokens)
# ロジスティック回帰のインスタンスを作成する
lr = LogisticRegression(penalty='l1', solver='liblinear')
# ロジスティック回帰のモデルを学習する
lr.fit(X_train, y_train)
# 検証用データに対する予測を行う
preds = lr.predict(X_valid)
# 正解率(Accuracy)を計算する
accuracy = accuracy_score(
y_valid,
preds
)
# 予測結果をdfに追加する
df.loc[df.kfold == fold_, 'preds'] = preds
# 正解率を出力する
print(f'Fold={fold_} 検証用データに対する正解率: {accuracy:.4f}')
# トータルの正解率を出力する
accuracy = accuracy_score(
df.rating,
df.preds
)
print(f'トータルの正解率: {accuracy:.4f}')
Fold=0 検証用データに対する正解率: 0.8934 Fold=1 検証用データに対する正解率: 0.9165 Fold=2 検証用データに対する正解率: 0.9183 Fold=3 検証用データに対する正解率: 0.8879 Fold=4 検証用データに対する正解率: 0.8861 トータルの正解率: 0.9005
まとめ
TF-IDFを使った結果、Bag of Wordsを使った場合と比べて、正解率は、89.05% → 90.05%に上がりました。TF-IDFによって、それぞれの文章を特徴づけるような単語を際立たせる事ができた事が示唆されます。
