ツイートを要約してくれる執事を作りました【最大被覆モデル】

## はじめに
今回は最大被覆モデルを使ったツイートの要約APIを作りました。キーワードを指定すると直近の話題を要約して教えてくれる、まるで執事のようなAPIです。たとえば「気になっている製品の市場の声を知りたい」「自分の会社のニュースや評判を知りたい」「今流行しているFGO関連のネタツイートを知りたい」などの用途で使えます。

<img src="http://blog.apitore.com/wp-content/uploads/2017/01/amarec-20170111-055734.png" alt="" width="800" height="376" class="aligncenter size-full wp-image-735" />

## API公開しました
- [ツイート要約コンシェルジュ](https://apitore.com/store/apis/details?id=27)
- [使うまでの手順や解説はこちら](http://blog.apitore.com/2017/01/13/api-tweet-summarize-concierge/)
- [Javaサンプルコードはこちら](https://github.com/keigohtr/apitore-response-parent/tree/master/twitter-response)

```java
public class Api27TwitterSummarizeExample {

  static String ENDPOINT     = "https://api.apitore.com/api/27/twitter-summarize/get";
  static String ACCESS_TOKEN = "YOUR-ACCESS-TOKEN";

  public static void main(String[] args) {
    RestTemplate restTemplate = new RestTemplate();
    Map<String, String> params = new HashMap<String, String>();
    params.put("access_token", ACCESS_TOKEN);
    params.put("q", "Apitore");
    params.put("iter", "1");
    params.put("num", "3");
    String url = UrlFormatter.format(ENDPOINT, params);

    TwitterSummarizeResponseEntity response =
        restTemplate.getForObject(url, TwitterSummarizeResponseEntity.class, params);

    System.out.println(response.getLog());
    System.out.println(response.getTweets().get(0).getText());
    System.out.println(response.getTweets().get(0).getScore());
  }

}
```

## 文書要約とは
Wikipediaの[自動要約](https://ja.wikipedia.org/wiki/%E8%87%AA%E5%8B%95%E8%A6%81%E7%B4%84)のエントリーが参考になります。今回は「最大被覆モデルで重要文（ツイート）を任意の数だけ選択する」というアプローチを取りました。最大被覆モデルによる文選択型の文書要約をとてもざっくりと説明すると「全体の文字長が長さMを超えないように、重要な単語をたくさん含む文をN個選択する」というものです。通常は性能保証付き貪欲法で計算します。単語の重要度は、例えばTF-IDFのようなもので計算しても良いですし、独自に重要度辞書を作って参照する場合もあります。

## アルゴリズム
細かい工夫は省略しますが、おおまかには以下の流れになっています。

1. [簡単ツイート収集API](https://apitore.com/store/apis/details?id=23)で任意のキーワードを含むツイートをT件取得する
2. [kuromoji-ipadic-neologd](https://apitore.com/store/apis/details?id=7)で形態素解析し、内容語（名詞、動詞、形容詞、形容動詞）のみを対象とする
3. 内容語のbigramを計算する、内容語bigramのDocument Frequencyを重要度とする
4. 最大被覆モデル+性能保証付き貪欲法で重要文を抽出する

## 要約してみる
任意のキーワードを含むツイート100件を使って要約してみました。まずは「とある魔術の禁書目録」を入力してみます。どうやらディバインゲートというソシャゲでコラボ企画がやっているようですね。ファミ通でも特集が組まれているようです。

```json
  "tweets": [
    {
      "statusId": 819472977976660000,
      "text": "とある魔術の禁書目録コラボユニットの性能調整が行われました！！\n詳しくはこちら\nhttps://t.co/nCtI6L2lEB\n#ディバゲ https://t.co/euWj6SVOlU",
      "createdAt": 1484212557000,
      "userId": 1651752007,
      "userName": "ミスター☆ディバイン@ディバゲ公式",
      "userScreenName": "divine_gate",
      "userProfileImageURL": "http://pbs.twimg.com/profile_images/545168403653083137/tPjlbZBx_normal.png",
      "score": 15.556059143488126
    },
    {
      "statusId": 819379554334576600,
      "text": "【ディバゲ研究室】劇場版『とある魔術の禁書目録』コラボが1/13より復刻！新ユニットのステータス＆スキルも判明 - ファミ通App https://t.co/i8B6GkYabA https://t.co/mmNxqtB0RR",
      "createdAt": 1484190283000,
      "userId": 5921162,
      "userName": "ファミ通.com",
      "userScreenName": "famitsu",
      "userProfileImageURL": "http://pbs.twimg.com/profile_images/378800000675754960/d98b55583c072a904463b4a625655c70_normal.png",
      "score": 13.692591672735654
    },
```

続いて「ガチャ」。今はFGOのガチャが熱いようですね！

```json
  "tweets": [
    {
      "statusId": 819441067925782500,
      "text": "FGOはシステムから「こいつがいないとクリアできないよor他のプレイヤーに勝てないよ」って無言の圧力をかけられる事がないから本当に「ガチャは自己責任」っていう意味で良心的だと思う",
      "createdAt": 1484204949000,
      "userId": 113922292,
      "userName": "カボチャ@ティアマト鯖",
      "userScreenName": "Lantern_pumpkin",
      "userProfileImageURL": "http://pbs.twimg.com/profile_images/787644896349872128/67tAY3Cp_normal.jpg",
      "score": 21.51741612946915
    },
    {
      "statusId": 819164551534870500,
      "text": "ガチャ回すの悩んでる人向けにJust do itの嘘字幕でっち上げておいたんで置いておきますね https://t.co/YrKBV4CmQp",
      "createdAt": 1484139023000,
      "userId": 3002869106,
      "userName": "祢架丸(ねかまる)",
      "userScreenName": "NakedAmarl",
      "userProfileImageURL": "http://pbs.twimg.com/profile_images/732055255278452736/gFzwi9NU_normal.jpg",
      "score": 12.289830977543446
    },
```

最後は真面目なものを期待して「安倍首相」。蓮舫さんの発言やフィリピンでの1兆円支援が話題のようです。フィリピンに1兆円支援するのは知らなかったです。ふむふむ。

```json
  "tweets": [
    {
      "statusId": 819510275959181300,
      "text": "民進・蓮舫「安倍晋三首相と意識共有できていない」～ネットの反応「有権者と意識を共有できてない蓮舫さん大いに語る」「党内の意識統一できない人が言うと面白いよね」\nhttps://t.co/oBChp3nIzL",
      "createdAt": 1484221450000,
      "userId": 3147651630,
      "userName": "アノニマス ポスト",
      "userScreenName": "anonymous201504",
      "userProfileImageURL": "http://pbs.twimg.com/profile_images/713181990690775040/BWrea93U_normal.jpg",
      "score": 26.90972898141721
    },
    {
      "statusId": 819496986638315500,
      "text": "TBS◆日比首脳会談で安倍首相、１兆円規模の支援表明 https://t.co/eabtk7unzH 「フィリピンのさらなる発展のため、ＯＤＡと民間投資をあわせ、今後５年間で１兆円規模のビジネス、機会を創出します」（安倍首相）※今年もバラマキスタート。",
      "createdAt": 1484218281000,
      "userId": 57184966,
      "userName": "deepthroat",
      "userScreenName": "gloomynews",
      "userProfileImageURL": "http://pbs.twimg.com/profile_images/315728613/deepthroat_normal.gif",
      "score": 23.325985203733698
    },
```

## おわりに
ツイートの要約サービスはちょっと探しましたが見つかりませんでした。結構便利だと思います。[APIを公開](https://apitore.com/store/apis/details?id=27)したので使ってみて下さい。「新製品が出たとき」や「ソシャゲで新キャラが出たとき」「自社の評判を知りたい」「時事問題を知りたい」「加湿器のオススメを知りたい」などの用途で役に立つと思います。