Google ColabとTensorFlowで感情分析を実装しよう!
今回は、Google ColabとTensorFlowを使って、文章の感情(ポジティブ/ネガティブ)を自動判定する感情分析を実装しました。しかし、結果は期待通りにはいきませんでした。この記事では、試行錯誤のプロセスを共有し、なぜうまくいかなかったのか、そしてどうすれば改善できるのかを解説します。
感情分析とは?
感情分析とは、SNSの投稿やレビューなどのテキストデータを解析し、「肯定的」「否定的」といった感情を分類する技術です。
例えば、商品レビューの「とても便利で満足!」はポジティブ、「全然使えない。最悪。」はネガティブと判定されます。
Google Colabの準備
Google Colabは、Googleが提供する無料のクラウドベースのノートブック環境です。インストール不要でブラウザからすぐに利用できるため、今回の感情分析も手軽に試せます。
試行①:シンプルなモデルと最初の誤判定
まずは、最低限のデータでシンプルなモデルを構築しました。しかし、学習データが非常に少ないために、テスト文の「ひどい内容だった。」がポジティブと誤判定されました。
実行コード
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import numpy as np
# サンプルデータ(日本語の簡易感情データセット)
texts = [
"この商品はとても素晴らしい!",
"買ってよかった。満足です。",
"使いにくいし二度と買わない。",
"最悪の体験だった。",
"コスパが良くて最高!"
]
labels = [1, 1, 0, 0, 1] # 1=ポジティブ, 0=ネガティブ
# 単語を数値に変換する「トークナイザー」を準備
tokenizer = Tokenizer(num_words=1000, oov_token="[UNK]") # 未知語(OOV)対策
tokenizer.fit_on_texts(texts)
# 文章を単語IDのリストに変換し、長さを揃える
# maxlenは、各シーケンス(文章)の最大長を定義
padded = pad_sequences(tokenizer.texts_to_sequences(texts), maxlen=12)
# モデル構築
# 感情分析に適したシンプルなニューラルネットワークモデルを定義します
model = tf.keras.models.Sequential([
layers.Input(shape=(10,)),
layers.Embedding(1000, 16),
layers.GlobalAveragePooling1D(),
layers.Dense(16, activation='relu'),
layers.Dense(1, activation='sigmoid')
])
# モデルのコンパイル
model.compile(
loss='binary_crossentropy', # 2値分類に適した損失関数
optimizer='adam', # 最適化アルゴリズム
metrics=['accuracy'] # 評価指標
)
# モデルの学習
model.fit(padded, np.array(labels).astype('float32'), epochs=30, verbose=0)
# 推論の実行
test_texts = ["すごく面白い!", "ひどい内容だった。"]
test_seq = tokenizer.texts_to_sequences(test_texts)
test_pad = pad_sequences(test_seq, maxlen=12)
predictions = model.predict(test_pad)
# 結果の表示
for text, pred in zip(test_texts, predictions):
print(text, "→", "ポジティブ" if pred > 0.5 else "ネガティブ")
実行結果と考察
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 215ms/step
すごく面白い! → ポジティブ
ひどい内容だった。 → ポジティブ
ご覧の通り、「ひどい内容だった。」がポジティブと誤判定されました。これは、与えた学習データが少なく、モデルが文脈を十分に学習できていないためです。
試行②:データ増強とバランス調整で挑むも、再び誤判定
次に、ネガティブな文章を増やし、学習データのバランスを改善しました。さらに、モデルの入力設定を修正し、エポック数も調整しました。
実行コード
# データを増やす
aug_texts = texts + [
"ひどい出来だった。", "酷い表現が多い。", "面白くなかった。", "期待外れで残念。",
"良くない部分が目立つ。", "全然おすすめできない。", "退屈だった。"
]
aug_labels = labels + [0,0,0,0,0,0,0]
# トークナイザーの再定義
tokenizer = Tokenizer(num_words=2000, oov_token="[UNK]")
tokenizer.fit_on_texts(aug_texts)
padded = pad_sequences(tokenizer.texts_to_sequences(aug_texts), maxlen=16)
# モデルの再定義
model = tf.keras.Sequential([
layers.Input(shape=(16,)),
layers.Embedding(2000, 32),
layers.GlobalAveragePooling1D(),
layers.Dense(32, activation="relu"),
layers.Dense(1, activation="sigmoid")
])
model.compile(loss="binary_crossentropy", optimizer="adam", metrics=["accuracy"])
model.fit(padded, np.array(aug_labels, dtype="float32"), epochs=40, verbose=0)
# 推論関数を定義し、しきい値を調整可能にする
def predict_with_threshold(texts, th=0.55): # 変更: しきい値を柔軟に
pad = pad_sequences(tokenizer.texts_to_sequences(texts), maxlen=16)
p = model.predict(pad)
out = []
for t, prob in zip(texts, p):
label = "ポジティブ" if prob[0] >= th else "ネガティブ"
out.append((t, float(prob[0]), label))
return out
# 検証
for t, prob, label in predict_with_threshold(["すごく面白い!", "ひどい内容だった。"], th=0.55):
print(f"{t} → prob={prob:.3f}, label={label}")
実行結果と考察
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 301ms/step
すごく面白い! → prob=0.297, label=ネガティブ
ひどい内容だった。 → prob=0.297, label=ネガティブ
今度は、「すごく面白い!」がネガティブと誤判定されました。さらに、両方の文章が同じ確率値でネガティブと判定され、モデルは感情の区別を全く行えていないことがわかります。
結論:なぜ、うまく学習できなかったのか?
一連の試行錯誤から、モデルがうまく学習できなかった根本的な原因は、学習データの圧倒的な不足にありました。
1. データ不足が最大の課題
最終的に用意した学習データは、ポジティブ・ネガティブ合わせてわずか20件程度でした。人間であればわずかな例で学習できますが、機械学習モデルは大量のデータからパターンを学ぶ必要があります。たった20件のデータでは、モデルは個々の単語や表現の感情的なニュアンスを十分に学習できず、新しい文章を正しく分類することができません。
2. 過学習と汎化能力の欠如
データが少ない状態で学習を繰り返すと、モデルは汎用的なパターンではなく、与えられたわずかな文章を「暗記」してしまいます。これを過学習と呼びます。過学習が起きると、学習データにない新しい文章に対して、正確な予測ができなくなります。
まとめ:感情分析成功への道
今回の挑戦は、失敗という結果に終わりましたが、機械学習の本質を理解する上で非常に重要な教訓を得ることができました。感情分析を成功させるための鍵は、以下の2点に集約されます。
1. 大規模なデータセットの用意
感情分析の精度は、何よりも学習データの量と質に依存します。実用的なシステムを構築するには、ポジティブ・ネガティブそれぞれ数千〜数万件の学習データが必要になります。
2. 事前学習済みモデルの活用
もし自分で大量のデータを集めるのが難しい場合は、事前学習済みモデルの活用を検討しましょう。例えば、Hugging Faceなどで公開されている日本語のBERTモデルなどは、すでに膨大なテキストで学習されているため、少ないデータでファインチューニングするだけで高い精度を出すことができます。これは、ゼロからモデルを訓練するよりもはるかに効率的で効果的なアプローチです。
今回の失敗は、機械学習が単なるコードではなく、良質なデータがあって初めて機能することを教えてくれました。もしこれから感情分析に挑戦する方がいれば、まずは大規模なデータセットの用意から始めることをお勧めします。
0 件のコメント:
コメントを投稿