こんにちは。
本日whotwiに、ツイートを分析し、よく使うことばを分析・グラフィカルに表示する機能をリリースしました。
こんな感じでツイートによく含まれるワードをワードクラウド風に表示します。
試しに企業のTwitterアカウントの中の人運営で有名なタニタさんのアカウントの結果で表示してみましょう。
こんな感じになります。
タニタさんのアカウントの特徴的な言葉が大きく表示され、数回しか言っていないようなものも小さな文字で周囲に表示されています。また「おはよう」などの回数は多いが一般的な語はやや小さめに表示されています。
whotwiは、アカウントの特徴を調べるツールなので、このようにできるだけ人と違う部分が際立って見えるように、また、意味のある語だけが出るように微調整を行いました。
使ったもの
ワードクラウドの処理としては、形態素解析でテキストを単語に分けて、出現回数の多いものから表示すればOKですね。
- MeCab 最も有名な形態素解析エンジン 文章を単語ごとに分割します
- mecab-ipadic-neologd mecabで使う辞書です。新語に弱いIPA辞書の弱点を克服するため、wikipediaやはてなキーワードから不足部分を補った辞書です
- php-mecab mecabのPHPバインディングです
- d3-cloud D3.jsのワードクラウドがかけるプラグインです。
- D3.js
上記を入れると、ワードクラウドが作れます。
ワードクラウドの課題
ただ、回数順で多いものから表示するだけだと、以下のような問題が起きてしまい、つまらない結果になってしまいます。
- 動詞「する」など、一般的すぎる語が大量に発生してしまう
- 特徴的なワードでも、出現回数だけだと上位に来ないので表示されない
- 意味のない単語が多数出現してしまう(特に非自立語)
- 形態素単位で分解すると、接尾語・接頭語も切り離されてしまい、意味不明になる
そこで、表示にあたっていくつかの工夫を行い、いい感じの表示になったのでその方法をかいてみます。
新語が正しく処理できるようにする
mecabの辞書としてはIPA辞書などが一般的ですが、これだと新語が入っておらず、「Apple Watch」などが正しく処理できません。 「Apple」と「Watch」が別々になってしまいます。分けてしまうと意味が変わってしまうので、わけずに処理したいわけです。
新語などのデータとしては、Wikipediaやはてなキーワードなどが使えそうですが、データを取ってきてmecab用の辞書を作りなおして、とかなり面倒です。
そこで、この課題を解決するべく、@overlastさんが公開されたmecab-ipadic-neologdという辞書を使うことにしました。
これで、たいていの語は分割されずに済むようになりました。
単語の細かい表記の違いで集計がずれないようにする
生のテキストで集計すると、全角半角の違い(「Apple」と「APPLE」)や、長音の連続(「スーパー」と「ス~パー」)などの微妙な違いで、同じ単語が別々にカウントされてしまいます。
そこで、解析前に事前に前処理しておきます。 前処理の方法は、上の@overlastさんが辞書を作る際に書かれたドキュメントが大変参考になります。
Regexp.ja · neologd/mecab-ipadic-neologd Wiki · GitHub
品詞ごとに重みをつける
品詞ごとにも、表示する大きさを変えたり、表示しなくしたりします。 例えば助詞、記号、また非自立の動詞・名刺、接尾の動詞、助動詞はそれ単体では意味がわからないので、削除します。
また、場所や人の名前が入りがちな固有名詞の重みを高めにします。
例えば、「東京に行きたい」であれば、以下のように分解されます。
東京 名詞,固有名詞,地域,一般,*,*,東京,トウキョウ,トーキョー に 助詞,格助詞,一般,*,*,*,に,ニ,ニ 行き 動詞,自立,*,*,五段・カ行促音便,連用形,行く,イキ,イキ たい 助動詞,*,*,*,特殊・タイ,基本形,たい,タイ,タイ 。 記号,句点,*,*,*,*,。,。,。
「東京」は固有名詞なので高めにします。助詞「に」、助動詞「たい」などは今回は必要ないので捨てます。
単語ごとの特徴量で重みをつける
また、単語の中でも特徴っぽいものと、そうでないものがあります。 ここでの「特徴」は、全体で見たときに出現頻度が低いという意味です。
今回のワードクラウドでは、できるだけ他の人との違いを可視化させたいので、ツイート一般であまり出現しない単語を大きく表示させたいです。
ちょうどmecabでは、「単語生起コスト」というのがあります。mecabの形態素解析の過程で使われる辞書に含まれるパラメータの一つです。単語の出現頻度が高いほど、「単語生起コスト」は低くなります。実際にはこれと「連接コスト」を合計し、合計コストの低い組み合わせが選択されます。
今回は、あまり出現しない単語を強調したいので、単語生起コストの高いものが出やすいようにします。
接尾語・接頭語をくっつける
形態素的には、「山手線」は、「山手/線」になってしまいます。
山手 名詞,固有名詞,地域,一般,*,*,山手,ヤマテ,ヤマテ 線 名詞,接尾,一般,*,*,*,線,セン,セン に 助詞,格助詞,一般,*,*,*,に,ニ,ニ 乗り 動詞,自立,*,*,五段・ラ行,連用形,乗る,ノリ,ノリ たい 助動詞,*,*,*,特殊・タイ,基本形,たい,タイ,タイ 。 記号,句点,*,*,*,*,。,。,。
意味的に「山手線」を一つとして扱いたいので、接尾の名詞である「線」は前とくっつけます。 同様に、接頭語も合体させます。
- (接頭語)+(あとの形態素)
- (あとの形態素)+(接尾語)
mecabのサイトに品詞ID(pos_id)の定義があるので、それを参考に結合します。
ワードクラウドの見た目の調整
今回、ワードの表示にはD3.jsのd3-cloudを使いました。
サーバーサイドで画像を合成する方法だとそこそこのリソースが必要なこと、それぞれの語をクリックできるようにしたかったことが理由です。
実装はサンプルを見ながらやればさくっとできます。
フォントはデフォルトだと細めのフォントになるのですが、太めのフォントの方が見栄えがいいので、ヒラギノProN W6の指定にしました。
文字のフォントを変える場合、実際に描画する要素への指定のほか、d3.layout.cloud
のオプションとしても渡す必要があるので注意が必要です。
これがずれると、位置の計算は別のフォントで計算されてしまい、表示が少しずれてしまいます。
d3.layout.cloud() .font(function (d) { return 'Impact, HiraKakuProN-W6, sans-serif'; })
他サイトの事例
実はこれ作り終わるまであまり他サイトの事例を見ていませんでした。 二番煎じどころか何番煎じなんだっていうw
テキストマイニングツール(UserLocal)
Twitterのツイートか、自由入力テキストからワードクラウドを作れるサービス。
こちらはwhotwiと同じでd3-cloudでの実装でした。 単語の抽出はおそらく重み付けなしで名詞と動詞のみ表示というシンプルな実装(ぽい)です。
「シロクモ」(白ヤギコーポレーション)
プレスリリースによると2014年10月20日にリニューアル版がリリースされた、白ヤギコーポレーションさんの「シロくも」ですが、現在はつながるURLが見つけられませんでした。
自分のワードクラウドが作れる「シロくも」がパワーアップ! 「シロクモ」「ラブクモ」「マイクモ」の3種類をリリース - 株式会社白ヤギコーポレーションのプレスリリース
「クロクモ」(@lightnet328さん)
丸ゴシック体でかわいいですね。 このワードクラウドはブラウザではなくサーバーでPNG画像として生成しているものでした。
ソースコードを公開されています。
ワードクラウド画像の生成には、Pythonのamueller/word_cloudを使っているようです。
シロクモと名前似てるし、フォントも似てるので同じ方が作ったのかも(未検証)
あなたが Twitter で、よく使っている言葉は?(vonvon)
こちらは、単語がTwitter Birdの形になってますね、かわいい。
小さめの文字だけ傾けて、読みやすいようにしてますね。 あと色合いがとてもお洒落!
生成はjpgでサーバーサイドでした。関係ないけど、vonvon、GCP使ってるんですね!今風。