TwitterのAPIを使ってユーザーのTweetを取得し、オープンソース 形態素解析エンジン「Mecab」により形態素解析しています。
その際、予め形態素ごとに属性情報を付与した辞書を使う事でユーザーの属性を推定します。
Mecabの辞書は「mecab-ipadic-NEologd」をベースにしつつ「はてなキーワード」の情報も一部使った改造辞書を用いています。
面白いなと思っていただきたい部分は「全般」タブの所のユーザー属性です。「バズツイ」「フレンド」はそれらを処理する時の副産物で、おまけにすぎません。
サイトのフロントエンドはJavaScriptのお勉強も兼ねて「Node.JS」を使用しました。その際のフレームワークは「Express」です。
形態素解析周りは「Ruby」、データベースは「MySQL」を使用しています。
大量の日本語を取り扱う上で問題になるのが、全文検索が遅い点です。当サイトの場合、クラウド上でガッツリと日本語の分析を行いますが、お小遣いの関係上リソースがかなり限られておりこの速度がボトルネックになる事が分かっています。 レコード数も億単位になってしまうため高速で処理するのが難しいです。そこで、日本語の全文検索の速度をウリにしている「Mroonga」というストレージエンジンをMySQLで使用しています。
実際に使用した所、MySQL8の全文検索よりもかなり高速でレスポンスが大きく改善しました。
ただし、Mroongaを使用することでRDSが使えなくなってしまったので、EC2上にDBサーバーを立てておりそれがとても不便だなあと思っています
こういった解析サービスの常としてとにかく「レスポンスが遅い」という問題があります。
これはリアルタイムに解析する場合仕方の無い事なのですが、当サイトの場合は一時的にキャッシュする事でレスポンス良く閲覧出来る事を優先しました。
しかしデータを溜め込むディスク容量が必要になるため、私のお小遣いの状況によってはこのあたりは流動的になります。
以下に概要図を載せております。殆ど全ての処理はAWS上で行っていますが、Mecabの辞書を作成する時のみ、数十時間CPUをフルに使うためローカルのPCを利用しています。
Mroongaはえええええ!!!早いとは聞いてたけどこんなに早いのか。
— 安眠枕 (@makura) August 8, 2022
ベンチ取った訳じゃないけど手元の環境で20.84秒かかったクエリが0.06秒になったぞ。350倍?どうなってんだ。 pic.twitter.com/QoAiJE1HUy
下記のTweetの場合、後述するような属性情報となります
上記Tweetの場合、以下のようにキーワードが抽出され、それぞれ属性判定されました。なお1Tweetの中でキーワードが複数回出てくる場合は、全てカウントします。 また、ハッシュタグは別の所でも利用します。
「SLAM DUNK」 - アニメ0.5 漫画0.5
「One and Only」 - 音楽1.0
「桜木花道」 - 漫画1.0
「湘北高校 」 - 漫画1.0
この結果、上記Tweetは「漫画4.0、アニメ2.0、音楽1.0」という属性を持つと判定されます。
何となく、イメージと近いのでは無いでしょうか。
この処理を3200Tweet分行いその人の属性判定を行っています。
※なお「One and Only」という音楽グループが存在するため上記Tweetは「音楽1.0」となっていますが、この場合は誤判定です。
実装上の工夫で文脈と関係の無いキーワードを無視するような仕組みも考えられますが、上記の場合アニメと音楽という関係性のありそうなキーワード群なのでどちらにせよ誤判定となりそうです。
まず、属性の判定には「はてなキーワード」を利用しました。これは以前、ふりがなリストとして配布されていたものを利用しています。(現在は公開終了)
はてなキーワードは人手でメンテナンスされていたのが魅力ではありますが、随分昔にサービスが停止しているため情報が非常に古くなっています。この辞書だけでTwitterのように、新語・未知語が飛び交う サービスを解析するのは難しいため、これとは別にmecab-ipadic-NEologdも併用しています。
これらの情報を用いながら、直近3200Tweet(APIで呼び出せる上限)からそのユーザーの属性情報を推定しています。
これは自然言語処理を行う上で必ず問題になる事だと思いますが、新語への対応と属性の判定の精度向上の2点が課題です。
はてなキーワードは2019年10月にサービス終了していますし、mecab-ipadic-NEologdも更新が止まっており、最近の新語に対応出来ていません。
そこで、Wikipediaを利用して新たな辞書を作成し、未知語への対応とキーワードの属性の判定を行う事を考えています。
Wikipediaはキーワードに付随して説明文があるため、この説明文からキーワードの属性は多分推定可能です。多分そういった研究も進められているはずです。
実際に私がこの作業を行う場合は、仮に先行研究でいい感じのがあればそのままその手法を使わせてもらおうと思っています。今のところは、BERTの日本語版事前解析モデルが各所から出ていますので、それらを用いるか、もしくはDoc2Vec(Word2Vec)などで自前で学習させる事を考えています。仮に自前で学習させる場合は教師無しで学習させるか、それともはてなキーワードが過去には人手でメンテナンスされていた事を踏まえ、 教師データとして利用するのか(この場合Doc2Vecでは無いと思いますが)また、各パラメータの調整など、十分な精度を出すためには考慮すべき点が多そうだな、というのが今のところの感想です。
またデータセット自体も大きいので実装までには相当な時間がかかりそうです。
というかですね、研究室でn百万するグラボをp個使ってq週間かけてトレーニングしてる時代に、自宅PCでどうこうするような時代じゃない気がしますよね。そうこうしてるうちにいい感じの辞書が出てこないかと心待ちにしております。
API経由で3200Tweetを取得しそれらを解析するため、1ユーザーの解析に数秒~最大10秒程度の時間が必要です。
その殆どはAPIでデータを取得するのにかかる時間なので劇的な改善は難しいです。このためユーザーが多数アクセスして解析を行った場合、恐らく順番待ちが発生します。
仮に100人が同時に解析ボタンを押した場合、100人x10秒=1000秒≒17分。これを4並列で実行したとしても4分ほどかかります。
3秒レスポンスが返ってこないだけで半数以上の人がサイトを離脱すると言われてる時代に、カップラーメン出来るまで待つ人が居るんでしょうか?
プログラムそのものの高速化や並列処理を行うなどしてなるべく高速化しつつ、一方で待ち時間が発生してしまう事も前提に設計したつもりですが、どうなるか未知数です
サイト自体が重いのは個人的に許せないので、解析部分とWeb表示を担当するインスタンスは分けてますのでサイト自体は軽くなるようにしているつもりではあります。
ただしDBは予算の都合上共用なので、DBにかかる負荷によってはサイト表示も重くなりそうです。
殆ど全ての問題はEC2のスペックを上げれば解決しそうな気がしますが、趣味のサイトにどこまでお小遣いを投入するか、という問題はあります。
もしいいお仕事情報があれば教えてください。よろしくお願いします。Twitter:@makura