[趣味研究]Youtubeコメント分析#1:Word2Vec
背景
Smile-up(旧:ジャニーズ事務所)に関するこのようなツイートを見かけました。
陰謀論の研究では、近年、陰謀論そのもののの性質よりも、陰謀論を信じやすい人の傾向に関心が集まっています(conspiracy mindset)。その要因の一つに「党派性(右か左か)」の強さがあげられます。これはいわゆる「動機付けられた推論」といって、自分が信じたいものを信じちゃう傾向です。例えば、トランプさんが何かやらしたらディープステートに嵌められた!と考えたりとか。
まあsmile upでもこうした傾向はありそうなので、Word2Vecの練習もかねて分析したいと思います。
予想
探索的にやる予定ですが、
・擁護vs批判で意見が極化してる
・ホモフィリーで擁護派ばかり?
データ
ソースコードは教えられないのですが、"ジャニーズ 当事者の会の検索クエリでかかった500件くらいの動画から関係なさそうなものを排除して、残った動画についているコメントを集めました(9万件くらい)。表だけ示しておきます(idは何のため消します)。
メソッド
import MeCab
import neologdn
import unicodedata
import pandas as pd
import json
import re
import pandas as pd
import gensim
from gensim.models import Word2Vec
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn.datasets import load_digits
from scipy.sparse.csgraph import connected_components
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from sklearn.manifold import TSNE
import umap
import time
import pickle
import os
分かち書き
mecabはneologd辞書じゃないと、「ジャニーズ」が登録されていないのでこれを採用します。
def tokenize(s):
s = unicodedata.normalize('NFKC', s) # NFKC: Normalization Form Compatibility Composition
s = neologdn.normalize(s) # 正規化
s = s.replace('\r\n', '').replace('\t', '').replace('\n', '').replace('\r', '') # 改行文字を取り除く # 改行文字とタブ文字を取り除く
tagger = MeCab.Tagger('-d ' + neologd_path)
words = []
for line in tagger.parse(s).splitlines()[:-1]:
surface, feature = line.split('\t')
pos_info = feature.split(',')[0] # 品詞情報のみを取得
if pos_info in ['名詞', '動詞'] and ',非自立,' not in feature:
if pos_info == '動詞':
feature_detail = feature.split(',')
lemma = feature_detail[-3] if len(feature_detail) >= 7 else surface
if lemma not in ['する', 'ある', 'いる']:
words.append(lemma)
else:
words.append(surface)
return words
# 分かち書きを実行
count = 0
tokenized_texts = []
for text in texts:
print(count)
count += 1
tokens = tokenize(text)
if tokens:
tokenized_texts.append(tokens)
単語埋め込み
Word2Vecに埋め込みます。
# Word2Vecモデルの学習
model = Word2Vec(sentences=tokenized_texts, vector_size=100, window=5, min_count=1)
# テキストデータをベクトル化
vectorized_texts = []
for text in tokenized_texts:
text_vector = sum([model.wv[word] for word in text]) / len(text)
vectorized_texts.append(text_vector)
リストを保存するライブラリーpickleで
・分かち書きのリスト
・ベクトル化した単語のリスト
# # Define the file path in your Google Drive where you want to save the vectorized texts
file_path = '*/tokenized_texts.pkl'
# # Save the vectorized_texts to a file
with open(file_path, 'wb') as f:
pickle.dump(tokenized_texts, f)
# # Define the file path in your Google Drive where you want to save the vectorized texts
file_path = '*/vectorized_texts.pkl'
# # Save the vectorized_texts to a file
with open(file_path, 'wb') as f:
pickle.dump(vectorized_texts, f)
リザルト
類似度
まずはベクトル化がちゃんと機能しているかを確認します
「当事者の会」が「当事者」・「会」に分かれたせいで少し当事者の制度が低いですね。また、最初の動画のクリーニングが甘かったのか、他のニュースと思われる話題も混ざってしまっています。ただ、概ねいい感じの精度ではないかと思います。
分布の確認
# UMAPによる次元削減(3次元)
reducer = umap.UMAP(n_components=3)
embedding = reducer.fit_transform(vectorized_texts)
# 可視化
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(embedding[:, 0], embedding[:, 1], embedding[:, 2], c=kmeans.labels_, cmap='viridis', s=5)
ax.set_title('UMAP Visualization in 3D')
ax.set_xlabel('UMAP 1')
ax.set_ylabel('UMAP 2')
ax.set_zlabel('UMAP 3')
# クラスターの番号をlegendに追加
legend1 = ax.legend(*scatter.legend_elements(), title="Clusters")
ax.add_artist(legend1)
plt.show()
適当に3つぐらいにクラスタリングしてみた結果
全然、分かれてないですね。
ディスカッション
単語ベクトル自体に問題はなさそうですが、文書の分類はうまくいきませんでした。いくつか考えられることを挙げます。
・擁護派も批判派も結局何かを攻撃しているから語彙が似ている
・そもそもコメントがほとんど擁護派?
今後
・道徳基盤辞書を使ってみる
・共起語をみる
・極性分析をする
・なんかクリーニングしてネットワークをみる
そもそもWord2Vecで何ができるかよくわかっていないので教えてほしい、、、