ワードウルフのお題を自動で作る(Googleトレンド/ Word2vec / MeCab)
10/8~10/10の3連休で1日はデイキャンプに行く予定でしたが、初日の朝に腰をずらしてしまい、ほぼ寝たきりでラジオやYouTubeを楽しむだけの3日間になりました。そんな中でYouTubeで見ていたのが「おぎやはぎのハピキャン」。デイキャンプに行った気分を味わうにはちょうどよかったのです。
この放送のなかで「ワードウルフ」という単語を使った人狼ゲームを遊んでおり、これが非常に面白そうでした。内容は村人(多数派)のワードと人狼(少数派)のワードを用意し、制限時間の中で会話をしながら人狼を特定していくゲームです。カードゲーム版、スマホ版がありますが、スマホ版は司会者(ゲーム進行役)を必要としないので手軽だと思います。
また、これをきっかけにワードウルフのお題を話題になっているキーワードから自動的に作ることができないかと、やることがなさすぎて考え始めたのでプログラムを書いてその結果を確認しました。結論からいいますと、お題として面白いかな思えたのは全体の2%くらいでしょうか。
(1) 設計を考える
話題になっている出来事を「Googleで高い頻度で検索されているキーワード」と決めました。このキーワードと類似度の高い言葉を何個か出力し、この中から文法的に近い言葉を出力するという流れで作ります。
1. Googleで高い頻度で検索されているキーワード
Pythonライブラリとしてpytrendsがあり、こちらを使ってGoogleトレンドの情報を入手します。
2. 類似性の高いキーワードの検索
今回は言葉をベクトル(数値)に変換することで言葉を類似度を求めたり、加減算できるようにします。Pythonでは言葉をベクトル(数値)化するライブラリとしてGensimがあります。またアルゴリズムにはWord2vecを使います。Word2vecで使う学習済みの日本語モデルはfastTextを使います。
3. キーワードの文法解析
今回は形態素解析により文章の文法構成を言葉単位で分類します。解析エンジンにはMeCabを使います。それはmecab-ipadic-NEologdというMeCab用のシステム辞書を使うことで形態素解析の精度が飛躍的に向上するからです。
(2) 開発環境を作る
設計に基づいたソフトを動かすためにはパソコンに以下の設定が必要となります。本記事ではWindows10 、11での開発を想定しています。
Python実行環境
プログラム・エディター
fastTextの学習済みモデル
Mecab / mecab-ipadic-NEologd作成環境(WSL2にUbuntuを導入し、この環境でコンパイルします)
1. Python実行環境
Python言語で書かれたプログラムを動作するときに必要な環境です。
2022/10/13時点の最新版はv3.10.8です。自身はPython v3.9.8を使っています。
ダウンロードしたインストーラーをダブルクリックしてInstall Nowを押せば良いのですが、以下の部分だけチェックを入れて環境変数PATHを自動登録しておきます。
今回のプログラムでは以下のPythonライブラリーを追加で導入します。Python実行環境をインストールした後にコマンドプロンプトかWindows Power Shellから以下のコマンドを順番に実行してください。
pip install pytrends
pip install gensim
pip install MeCab
2. プログラム・エディター
プログラムの記述はメモ帳で行えますが、動作確認することを考えますとプログラム・エディターを使用した方が良いと思います。PythonであればPyScripter / Visual Studio / Visual Studio Code / Atomがあります。自身は使い慣れているPyScripterを使っています。
3. fastTextの学習済みモデル
fastTextとは異なりますが、chiVeという学習モデルを使用した言語を数値化する環境の作り方は別記事にまとめております。
今回はfastTextの学習済みモデルを使いますが、以下でサイトで配布いただいているモデルをダウンロードし、chiVeと差し替えれば使うことができます。
4. Mecab / mecab-ipadic-NEologd作成環境
Mecabで文章を言葉に分類する環境の作り方は別記事にまとめました。WSL2を使いますので、Windows10/11パソコン用の内容です。
(3) プログラムを実装する
開発環境が完成しましたら、設計に沿って機能を作っていきたいと思います。
1. Googleトレンドからキーワードを検索する
Pythonライブラリのpytrendsを使って検索されている上位20個のキーワードを検索します。検索する前にTrendReq命令でgoogleトレンドに接続します。引数の「hl」は検索言語、「tz」は検索地域の標準時間からの時差です。日本のトレンドを検索したいため、hl=’ja-JP’(日本語)、tz=-540(標準時間から540分の時差)を指定します。
この戻り値(trends)をtrending_searches命令でトレンドを20個検索します。引数のpnはトレンド対象の国を指定します。trending_searchesで求めたトレンドはDataFrame型で求められます。
from pytrends.request import TrendReq
trends = TrendReq(hl='ja-jp', tz=540)
trending_result = trends.trending_searches(pn='japan')
print(trending_result)
Googleトレンドの検索結果を表示すると以下のようにDataFrame型となっています。
0
0 バロンドール
1 MAP
2 日経平均
3 BTS 兵役
4 日経平均株価
5 みずほ銀行
6 インフルエンザ予防接種
7 SDGs
8 矢吹奈子
9 のん
10 インボイス制度
11 Teams
12 うまゆる
13 アトムの童
14 ヴァンフォーレ甲府
15 地震
16 菊花賞
17 霊媒探偵
18 日本シリーズ
19 男闘呼組
2. Mecabで言葉を分類する
検索したGoogleトレンドをMecabで形態素解析します。以下のPythonコードではmecab-ipadic-NEologdの辞書ファイルはCドライブのdicフォルダに配置しています。Mecabで解析した結果は後ほど使いやすいようにタブとカンマ区切りでリスト化します。
import MeCab
import re
from pprint import pprint
tagger = MeCab.Tagger('-d C:\dic')
result = tagger.parse('日本シリーズ')
result = [re.split('[,\t]',x) for x in result.splitlines()]
pprint(result)
形態素解析した結果は以下のようになります。Mecabの公式サイトによりますと「表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音」で出力されます。
[['日本シリーズ','名詞','固有名詞','一般','*','*','*','日本シリーズ','ニッポンシリーズ','ニッポンシリーズ'],
['EOS']]
3. Word2vecで類似語を探す
形態素解析した言葉のなかで品詞が名詞のものを対象にその類似語をWord2vecで検索します。
import gensim
kw = '日本シリーズ'
vectors = gensim.models.KeyedVectors.load_word2vec_format('model.vec', binary=False)
if kw in vectors:
item = vectors.most_similar(kw, topn=10)
else:
print(kw + 'は登録されていません')
以下のように類似語が出力されました。
[('クライマックスシリーズ', 0.7961986064910889),
('ゴルフ日本シリーズ', 0.7557626962661743),
('ワールドシリーズMVP', 0.7224666476249695),
('日本選手権シリーズ', 0.7204544544219971),
('ファーム日本選手権', 0.7164201736450195),
('セ・リーグ', 0.7157709002494812),
('パ・リーグ', 0.7123793959617615),
('韓国シリーズ', 0.7100515961647034),
('ポストシーズン', 0.7071235775947571),
('パシフィック・リーグ', 0.7027769088745117)]
4. Mecabで類似語を分類する
先ほどはGoogleトレンドの結果を形態素解析しましたが、今回はWord2vecで取得した類似語を形態素解析して両者を比較します。例えばGoogleトレンドから取得した「日本シリーズ」はMecabで「名詞」、「固有名詞」、「一般」に分類されていますので、Word2vecで取得した類似語も同じようにMecabで分類して文法的に同じ言葉のみを選びます。
5. 完成したコード
これまでの機能をまとめたPythonコードを紹介します。Word2vecの処理が非常に時間を要するので気長に実行してください。
from pytrends.request import TrendReq
import MeCab
import re
import gensim
# Googleトレンドから上位20キーワードをDataFrame型で取得する
trends = TrendReq(hl='ja-jp', tz=540)
trending_result = trends.trending_searches(pn='japan')
# MecabでGoogleトレンドのキーワードを解析する
for i in range(len(trending_result)):
tagger = MeCab.Tagger('-d C:\dic')
result = tagger.parse(trending_result[0][i])
result = [re.split('[,\t]',x) for x in result.splitlines()]
# Googleトレンドのキーワードの類似語をWord2vecで取得する
for j in range(len(result)-1):
if result[j][1] == '名詞':
vectors = gensim.models.KeyedVectors.load_word2vec_format('model.vec', binary=False)
if result[j][0] in vectors:
item = vectors.most_similar(result[j][0], topn=10)
# Word2vecで取得した類似語をMecabで解析する
for k in range(len(item)):
result_sim = tagger.parse(item[k][0])
result_sim = [re.split('[,\t]',x) for x in result_sim.splitlines()]
# Mecabが出力したGoogleトレンドと類似語の品詞、品詞細分類1、品詞細分類2、品詞細分類3を比較して同じものだけを抜き出す
if result[j][1] == result_sim[0][1] and \
result[j][2] == result_sim[0][2] and \
result[j][3] == result_sim[0][3] and \
result[j][4] == result_sim[0][4]:
print ('「' + result[j][0] + '」' + 'と' + '「' + result_sim[0][0] + '」' + 'の類似値は' + str(round(item[k][1]*100,2)) + '%です')
else:
print('「' + result[j][0] + '」' + 'は登録されていません')
結果は以下のように表示されます。面白そうなキーワードは「だんじり」と「神輿」くらいかなという感じですが、実行する日によっては面白いお題が出てくるかもしれません。
「ヘルプマーク」は登録されていません
「バロンドール」と「フリスト・ストイチコフ」の類似値は67.06%です
「バロンドール」と「ローター・マテウス」の類似値は66.12%です
「藤原さくら」は登録されていません
「株」と「株式」の類似値は66.82%です
「株」と「株数」の類似値は62.7%です
「株」と「持株」の類似値は57.41%です
「株」と「持ち株」の類似値は56.89%です
「株」と「株価」の類似値は54.86%です
「対応」と「対処」の類似値は55.82%です
「MAP」と「MAPK」の類似値は58.42%です
「MAP」と「MAPI」の類似値は53.35%です
「MAP」と「マップ」の類似値は52.7%です
「MAP」と「MAPS」の類似値は49.93%です
「MAP」と「PLA」の類似値は45.56%です
「MAP」と「OMAP」の類似値は45.49%です
「MAP」と「SVF」の類似値は45.23%です
「MAP」と「DMAP」の類似値は44.8%です
「日経平均」と「日経平均株価」の類似値は84.47%です
「日経平均」と「日経225」の類似値は71.5%です
「日経平均」と「TOPIX」の類似値は70.37%です
「日経平均」と「東証株価指数」の類似値は69.93%です
「日経平均」と「日経225先物取引」の類似値は69.14%です
「日経平均」と「株価指数」の類似値は63.26%です
「日経平均」と「原資産」の類似値は61.17%です
「日経平均」と「時間外取引」の類似値は60.74%です
「日経平均株価」と「日経平均」の類似値は84.47%です
「日経平均株価」と「ダウ平均株価」の類似値は74.56%です
「日経平均株価」と「東証株価指数」の類似値は71.39%です
「日経平均株価」と「TOPIX」の類似値は70.21%です
「日経平均株価」と「日経225」の類似値は64.63%です
「日経平均株価」と「前日比」の類似値は64.02%です
「日経平均株価」と「時価総額加重平均型株価指数」の類似値は63.67%です
「日経平均株価」と「株価指数」の類似値は62.93%です
「みずほ銀行」と「三井住友銀行」の類似値は79.86%です
「みずほ銀行」と「りそな銀行」の類似値は75.19%です
「みずほ銀行」と「第一勧業銀行」の類似値は73.07%です
「みずほ銀行」と「東日本銀行」の類似値は73.04%です
「みずほ銀行」と「UFJ銀行」の類似値は72.68%です
「インフルエンザ予防接種」は登録されていません
「SDGs」は登録されていません
「だんじり」と「山車」の類似値は66.71%です
「だんじり」と「神輿」の類似値は63.19%です
「だんじり」と「しゃぎり」の類似値は57.99%です
「インボイス」と「楽天」の類似値は48.52%です
「インボイス」と「アグリーメント」の類似値は48.35%です
「制度」と「法制」の類似値は60.4%です
「制度」と「税制」の類似値は55.45%です
「Teams」と「teams」の類似値は81.66%です
「Teams」と「Team」の類似値は71.02%です
「Teams」と「Clubs」の類似値は61.1%です
「Teams」と「Racing」の類似値は61.02%です
「Teams」と「Supporting」の類似値は60.67%です
「Teams」と「Steamship」の類似値は60.54%です
「Teams」と「Cycling」の類似値は59.74%です
「Teams」と「Compatibility」の類似値は59.59%です
「うま」と「いぬ」の類似値は46.84%です
「うま」と「いのこ」の類似値は46.09%です
「うま」と「きんぱ」の類似値は45.48%です
「アトム」と「複合項」の類似値は44.12%です
「童」と「舞」の類似値は49.05%です
「童」と「童子」の類似値は48.21%です
「童」と「児」の類似値は48.18%です
「童」と「喜」の類似値は47.99%です
「地震」と「余震」の類似値は79.97%です
「地震」と「震源」の類似値は78.57%です
「地震」と「本震」の類似値は76.94%です
「菊花賞」と「皐月賞」の類似値は89.24%です
「菊花賞」と「天皇賞(春)」の類似値は87.94%です
「菊花賞」と「桜花賞」の類似値は87.23%です
「菊花賞」と「宝塚記念」の類似値は86.32%です
「菊花賞」と「天皇賞(秋)」の類似値は86.09%です
「菊花賞」と「東京優駿」の類似値は85.72%です
「菊花賞」と「日本ダービー」の類似値は85.62%です
「菊花賞」と「有馬記念」の類似値は85.23%です
「菊花賞」と「天皇賞」の類似値は84.87%です
「菊花賞」と「エリザベス女王杯」の類似値は84.43%です
「霊媒」と「心霊」の類似値は53.9%です
「探偵」と「推理」の類似値は65.35%です
話題になっている言葉でワードウルフをやってみたい方は試してみてはいかがでしょうか。