亀岡的プログラマ日記

京都のベッドタウン、亀岡よりだらだらとお送りいたします。

irofさんってどういう人なのか客観的に分析してみる[追記あり]

この記事は、irof Advent Calander 1日目の記事です。

irofさんってどんな人なの?

irofさん、irofさんとみんな言いますが、一体どんな人なんでしょうか?インスタンスが複数ある、VMである、Vagrant-irofができるらしい、など様々な憶測が飛び交っています。 では、ふさわしい方法で分析してみましょう。

irofさんを分析する

irofさんの生態を知る一番の方法は、やはりTwitterでしょう。では、Twitterでの発言内容を分析し、irofさんを特徴付けるキーワードを求めてみたいと思います。 方法は、形態素解析器 + TF-IDFを用いてます。具体的には、irofさんの発言内容のうちから形態素解析器により名詞を抽出して、各名詞のTF-IDFスコアを求め、そのランクが高い言葉を指標として採用しようと思います。

TF-IDF

TF-IDFですが、ざっくり言うと「ある属性を持ったドキュメントと、それを含む全体のドキュメントが与えられた時に、ある属性を持ったドキュメントに特異的に含まれている言葉」を抽出するための評価関数です。実装はとても単純で、評価したい単語をWとし、

  • TF: ある属性を持ったドキュメント群全体に含まれているWの数
  • DF: ドキュメント群全体のうち、Wを含むドキュメント数
  • N : ドキュメント群全体の総数

と定義した場合に、

TF-IDF = TF * log(N / DF)

となります。

詳しくは以下に。

分析する準備

必要となるツールは2つです。まずはTwitterの発言内容を取得するライブラリ、それから形態素解析器です。

まずTwitterライブラリですが、やはりirofさんといえばJVMの方ですから、Twitter4Jを採用しましょう。もちろんC#から呼び出します。

次に構文解析器ですが、やはり更新が頻繁なJVM系のライブラリということで、Kuromojiを採用します。呼び出し側のコードは当然C#です。

使用準備

しかし、なぜか上記2つのライブラリはC#から直接参照できませんでした。...おかしいですね。 まぁ、仕方がありません。天の導きに従ってIKVM.netを速やかにダウンロードしましょう。

さらに、jar2ikvmcという素敵ツールが公開されているではありませんか。これを使うと、jarファイルからdllファイルに変換するスクリプトを、jarファイルの依存関係を考慮した上で作成してくれます。素晴らしいですね。

例えば、Twitter4Jだと以下の様なスクリプトを、生成してくれます。

ikvmc twitter4j-core-3.0.5.jar -target:library
ikvmc twitter4j-async-3.0.5.jar -target:library -r:twitter4j-core-3.0.5.dll
ikvmc twitter4j-stream-3.0.5.jar -target:library -r:twitter4j-core-3.0.5.dll -r:twitter4j-async-3.0.5.dll
ikvmc twitter4j-media-support-3.0.5.jar -target:library -r:twitter4j-core-3.0.5.dll -r:twitter4j-async-3.0.5.dll

では、早速この2つのライブラリを使うために、必要なライブラリをusingしておきます

using java.util;
using org.atilika.kuromoji;
using twitter4j;

また、以下の様な拡張メソッドを作っておくと、何かと便利です。

    public static class JavaListExtention
    {
        public static System.Collections.Generic.IEnumerable<T> 
            ToEnumerable<T>(this java.util.List jList)
        {
            var iterator = jList.iterator();

            while (iterator.hasNext())
            {
                yield return (T) iterator.next();
            }
        }
    }

Tweetを取得し、格納

まず、Tweetの取得です。今回はHomeTimelineを取得しましょう。Retweetは省きたいところですね。 というわけで、こんなかんじになります。

    var twitter = new TwitterFactory().getInstance();
    timeline = twitter.getHomeTimeline(new Paging(1, 200))
        .ToEnumerable<Status>().Where(status => !status.isRetweet())
        .Select(status =>
            new Tweet(
                status.getUser().getScreenName(),
                status.getText(),
                status.getId()))
        .ToList();

そして、上記取得したTimelineをKuromojiを使って品詞分解します。TF-IDFの計算の都合上

  • 各ドキュメントが持つ全名詞のリスト
  • irofさんが発言した全名詞のリスト

の2つが必要ですので、それを計算しています。

    var tokenizer = Tokenizer.builder().build();
    
    //各ドキュメントが持つ全名詞リスト
    var wordsFromAllTweets = new Dictionary<long, List<string>>();
    //irofさんの全発言リスト 
    var wordsFromAllIrof = new List<string>();
  
    foreach (var tweet in timeLine.Distinct())
    {
       var tokens = ExtractNoun(tokenizer.tokenize(tweet.Text)).ToArray();
       var nouns = tokens.Select(token => token.getSurfaceForm()).ToList();
       if (!wordsFromAllTweets.ContainsKey(tweet.Id))
       {
           wordsFromAllTweets.Add(tweet.Id,nouns);
       }
   
       if (tweet.User == "irof")
       {
           wordsFromAllIrof.AddRange(tokens.Select(token => token.getSurfaceForm()));
       }
    }

結果

では、上記データを使って、TLから600件ほどTweetを取り出し、調べてみました。ランク上位5つを、上から見て行きましょう!!

  • 1位: @
    • → まぁこれは誤差というかノイズですね。無視。まぁmention言及が他の人と比べて多い、とも言えますが。
  • 2位: 新幹線
    • → さすが多態性をもついろふさん。主たる移動手段の言及は欠かさないわけですね?
  • 3位: _
    • → ???なんで、あんだーばーを??
  • 4位: kazuhito
    • → かずひと・・・?
  • 5位: 三浦
    • → あっ・・・(察し)

(番外)

  • 8位: m
    • → kazuhito(4位) + _(3位) + m(8位) = ・・・?

結論

irofさんはみうみうと仲良し

裏話

Twitter APIがこれほど過去のツイート取りにくいと思っておらず、想定よりもかなり少ない数での解析となったので、残念だなーと思いましたが、結果を見た瞬間に勝ったと思いました(小学生並みの感想)

追記

ご本人からツッコミが。

確かに、ツイートは半日分くらいしか取れていなかったので、残念ながらかなり偏ったデータとなってしまった模様。残念(´・ω・`)

次は

@kawakawa さんです!!