自動要約API「summpy」を使って、いろんな文章を要約してみた

# summpyとは
リクルートテクノロジーズさんが公開している文章の自動要約APIです。
入力した文章を指定した行数で要約してくれます。

公開されているGitHub
https://github.com/recruit-tech/summpy

今回は、こちらのAPIに色々な文章を投入し、
結果がどうなるかを検証してみました。

# 検証環境
EC2(Amazon Linux release 2)
python2.7

# インストール
pip, summpy, mecab-python3をインストールします

mecab-python3については、バージョン0.996.5を指定しないと、
「no such file or directory: /usr/local/etc/mecabrc」エラーが出てしまうため、バージョン指定しています。

```
$ sudo easy_install pip
$ sudo pip install summpy
$ sudo pip install mecab-python3==0.996.5
```

併せて、networkxのバージョンを1.11にします。
これをしないと、実行時に「"error": "add_edge() takes exactly 3 arguments (4 given)"」エラーが発生します。

```
$ sudo pip install multiqc==1.2
$ sudo pip install networkx==1.11
```

# サーバ実行
8080番ポートで起動します。
バックグラウンドで実行させるために、nohupをつけています。

```
nohup python -m summpy.server -h 127.0.0.1 -p 8080 &
```

# ソースコード

```python:summpy_test.py
#!/usr/bin/env python2
# coding:utf-8
import requests

limit = 3 # ここで、要約したい行数を指定
text = 'ここに、要約したい文章を入れます。'

p = {'sent_limit':limit, 'text':text}

r = requests.get('http://localhost:8080/summarize', params=p)

print(r.text)
```

# 実行 & 結果
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "ここに、要約したい文章を入れます。"
  ]
}
```

text の文章が1行なので、結果も1行になっています。
ここの文章を色々と変えてみたいと思います。

# 色々な文章で試してみた

では、ここからは、各テーマに沿って、色々な文章を要約してみます。
要約に使った文章は、以下記事の内容を使っています。
※ 筆者が過去に書いた記事で、最も文章が長い記事です

> 『アドラー心理学』をエンジニアの目線で解釈すると？
https://qiita.com/keki/items/0542d9d121cf89d6154e


## まずは、特に何も考えずに要約
まずは、以下の文章を要約してみます。
尚、改行は削除してから要約APIに投入しています。

### 原文
```
この年齢になってくると、人の気持ちとか感情、考え方というところに興味がわいてくるんですね。

そんな中、数年前に出会ったのが今回のタイトルにもある『アドラー心理学』です。

エンジニアはプログラミングという専門的な業務に専念することもあり、人とのコミュニケーションが苦手だ、チームの輪に加わるのが下手だと言われることがあると思います。

また、人間関係に悩んだり、うつ病を煩ってしまったり...というケースも多い職種だと思います。

『アドラー心理学』は、そんな人間関係の悩みを解決する為の考え方、思想そのものだと、私自身感じています。

今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線で解釈すると、どういうことになるのかを記事にしたいと思います。

ちなみにかなりの長文となります。
ちょっとした書籍を読むつもりで見てもらえると嬉しいです。
```

### ソースコード
```python:summpy_test.py
#!/usr/bin/env python2
# coding:utf-8
import requests

limit = 3 # ここで、要約したい行数を指定
text = 'この年齢になってくると、人の気持ちとか感情、考え方というところに興味がわいてくるんですね。そんな中、数年前に出会ったのが今回のタイトルにもある『アドラー心理学』です。エンジニアはプログラミングとい
う専門的な業務に専念することもあり、人とのコミュニケーションが苦手だ、チームの輪に加わるのが下手だと言われることがあると思います。また、人間関係に悩んだり、うつ病を煩ってしまったり...というケースも多い職>種だと思います。『アドラー心理学』は、そんな人間関係の悩みを解決する為の考え方、思想そのものだと、私自身感じています。今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線
で解釈すると、どういうことになるのかを記事にしたいと思います。ちなみにかなりの長文となります。ちょっとした書籍を読むつもりで見てもらえると嬉しいです。'

p = {'sent_limit':limit, 'text':text}

r = requests.get('http://localhost:8080/summarize', params=p)

print(r.text)
```

### 実行結果
```
$ python summpy_test.py
{
  "debug_info": {},
  "summary": [
    "この年齢になってくると、人の気持ちとか感情、考え方というところに興味がわいてくるんですね。",
    "『アドラー心理学』は、そんな人間関係の悩みを解決する為の考え方、思想そのものだと、私自身感じています。",
    "今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線で解釈すると、どういうことになるのかを記事にしたいと思います。"
  ]
}
```

うーん。1行目と2行目の繋がりがわかりづらい要約結果になっていますが、3行に要約されてはいます。
また、原文の加工は行わず、単に文章の抜き出しと選択を行っているだけのようです。

## 句読点を削除してみる
summpyにおいて、句読点がどんな意味を持つのかを調査するため、あえて全ての句読点を削ってみます。
※ ソースコードは先ほどとほぼ同様（変数textの値が変わるだけ）なので、割愛します。

### 原文
```
この年齢になってくると人の気持ちとか感情考え方というところに興味がわいてくるんですね

そんな中数年前に出会ったのが今回のタイトルにもある『アドラー心理学』です

エンジニアはプログラミングという専門的な業務に専念することもあり人とのコミュニケーションが苦手だチームの輪に加わるのが下手だと言われることがあると思います

また人間関係に悩んだりうつ病を煩ってしまったり...というケースも多い職種だと思います

『アドラー心理学』はそんな人間関係の悩みを解決する為の考え方思想そのものだと私自身感じています

今回そんな『アドラー心理学』を実際現場でエンジニアをやってる私がエンジニアの目線で解釈するとどういうことになるのかを記事にしたいと思います

ちなみにかなりの長文となります
ちょっとした書籍を読むつもりで見てもらえると嬉しいです
```

### 実行結果
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "この年齢になってくると人の気持ちとか感情考え方というところに興味がわいてくるんですねそんな中数年前に出会ったのが今回のタイトルにもある『アドラー心理学』ですエンジニアはプログラミングという専門的な業務に専念することもあり人とのコミュニケーションが苦手だチームの輪に加わるのが下手だと言われることがあると思いますまた人間関係に悩んだりうつ病を煩ってしまったり...というケースも多い職種だと思います『アドラー心理学』はそんな人間関係の悩みを解決する為の考え方思想そのものだと私自身感じています今回そんな『アドラー心理学』を実際現場でエンジニアをやってる私がエンジニアの目線で解釈するとどういうことになるのかを記事にしたいと思いますちなみにかなりの長文となりますちょっとした書籍を読むつもりで見てもらえると嬉しいです"
  ]
}
```
1行で要約されてしまいました。
どうやら、句読点を文章の区切りとみなしているようです。

## 要約行数を調整する
続いて、要約する行数を増やすとどうなるでしょうか？
上記の文章を100行で要約してみました。
※ 句読点は元に戻しています。

### 実行結果
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "この年齢になってくると、人の気持ちとか感情、考え方というところに興味がわいてくるんですね。",
    "そんな中、数年前に出会ったのが今回のタイトルにもある『アドラー心理学』です。",
    "エンジニアはプログラミングという専門的な業務に専念することもあり、人とのコミュニケーションが苦手だ、チームの輪に加わるのが下手だと言われることがあると思います。",
    "また、人間関係に悩んだり、うつ病を煩ってしまったり...というケースも多い職種だと思います。",
    "『アドラー心理学』は、そんな人間関係の悩みを解決する為の考え方、思想そのものだと、私自身感じています。",
    "今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線で解釈すると、どういうことになるのかを記事にしたいと思います。",
    "ちなみにかなりの長文となります。",
    "ちょっとした書籍を読むつもりで見てもらえると嬉しいです。"
  ]
}
```

原文そのままですね。
読点（、）は文章の区切りとしては使われておらず、
あくまで句点（。）で区切られていることがわかります。
他にも、ドット（．）、クエッションマーク（？）、エクスクラメーションマーク（！）でも区切られそうですね。

では、行数を徐々に減らしていきます。

### 実行結果（7行）
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "この年齢になってくると、人の気持ちとか感情、考え方というところに興味がわいてくるんですね。",
    "そんな中、数年前に出会ったのが今回のタイトルにもある『アドラー心理学』です。",
    "エンジニアはプログラミングという専門的な業務に専念することもあり、人とのコミュニケーションが苦手だ、チームの輪に加わるのが下手だと言われることがあると思います。",
    "また、人間関係に悩んだり、うつ病を煩ってしまったり...というケースも多い職種だと思います。",
    "『アドラー心理学』は、そんな人間関係の悩みを解決する為の考え方、思想そのものだと、私自身感じています。",
    "今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線で解釈すると、どういうことになるのかを記事にしたいと思います。",
    "ちなみにかなりの長文となります。"
  ]
}
```

### 実行結果（6行）
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "この年齢になってくると、人の気持ちとか感情、考え方というところに興味がわいてくるんですね。",
    "そんな中、数年前に出会ったのが今回のタイトルにもある『アドラー心理学』です。",
    "また、人間関係に悩んだり、うつ病を煩ってしまったり...というケースも多い職種だと思います。",
    "『アドラー心理学』は、そんな人間関係の悩みを解決する為の考え方、思想そのものだと、私自身感じています。",
    "今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線で解釈すると、どういうことになるのかを記事にしたいと思います。",
    "ちなみにかなりの長文となります。"
  ]
}
```

### 実行結果（5行）
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "この年齢になってくると、人の気持ちとか感情、考え方というところに興味がわいてくるんですね。",
    "そんな中、数年前に出会ったのが今回のタイトルにもある『アドラー心理学』です。",
    "『アドラー心理学』は、そんな人間関係の悩みを解決する為の考え方、思想そのものだと、私自身感じています。",
    "今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線で解釈すると、どういうことになるのかを記事にしたいと思います。",
    "ちなみにかなりの長文となります。"
  ]
}
```

### 実行結果（4行）
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "この年齢になってくると、人の気持ちとか感情、考え方というところに興味がわいてくるんですね。",
    "『アドラー心理学』は、そんな人間関係の悩みを解決する為の考え方、思想そのものだと、私自身感じています。",
    "今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線で解釈すると、どういうことになるのかを記事にしたいと思います。",
    "ちなみにかなりの長文となります。"
  ]
}
```

### 実行結果（3行）
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "この年齢になってくると、人の気持ちとか感情、考え方というところに興味がわいてくるんですね。",
    "『アドラー心理学』は、そんな人間関係の悩みを解決する為の考え方、思想そのものだと、私自身感じています。",
    "今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線で解釈すると、どういうことになるのかを記事にしたいと思います。"
  ]
}
```

### 実行結果（2行）
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "『アドラー心理学』は、そんな人間関係の悩みを解決する為の考え方、思想そのものだと、私自身感じています。",
    "今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線で解釈すると、どういうことになるのかを記事にしたいと思います。"
  ]
}
```

### 実行結果（1行）
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "今回、そんな『アドラー心理学』を、実際現場でエンジニアをやってる私が、エンジニアの目線で解釈すると、どういうことになるのかを記事にしたいと思います。"
  ]
}
```

徐々に、重要ではないと判断された文章が、削られていますね。
どのような基準で判断されているかはわかりませんが、
やはり、挙動としては、

1. 文章を句読点で区切る
2. 文章のうち、重要度上位○行（指定行数分）を、結果として出力

という形で間違いなさそうです。

要約結果を見ると、個人的には3行要約が一番わかりやすく、的をついていると思います。
が、文章量が増えてくると、恐らく3行だけでは「何の話か分からない」となる気がします。
文章量に応じた、適切な行数設定を見つけることも必要だと感じます。

## まとまりのない文章を要約
繋がりのない文章を要約したらどうなるかを検証するために、
上記記事の「目次」を要約してみます。
※ 句点がないと、文章の区切ることができないのは、上記にて実証済みのため、
改行コードを全て句点「。」に変換して実行します。

### 原文
```
参考書籍
前提
1. 人は変われる
1-1. トラウマは存在しない
1-2. 傷つくことを恐れてはいけない
1-3. 劣等感が強くなりすぎると生まれる弊害
1-4. 自己を受容する
2. 課題の分離
2-1. 他者の期待を満たす必要はない
2-2. 他者の課題に土足で踏み込まない
2-3. 課題の分離について
3. 他者との関わり方
3-1. 他者との競争はしない
3-2. 非を認める＝負けではない
4. 人を育てることについて
4-1 叱ってはいけない、ほめてもいけない
4-2 評価ではなく、感謝をする
5. 共同体感覚
最後に
```

### 実行結果（3行）
```
$ python ./summpy_test.py
{
  "debug_info": {},
  "summary": [
    "2-1. 他者の期待を満たす必要はない。",
    "2-2. 他者の課題に土足で踏み込まない。",
    "3. 他者との関わり方。"
  ]
}
```
もともと、前後関係があまりない文章なので、要約結果にもまとまりがないのは当然ですが、
大分類ばかりが選ばれず、中分類（2-1, 2-2）まで選択されたのは興味深いです。

## ちょっとだけ、APIの中を見てみる
どんなロジックで要約されているのかが気になったので、
GitHubに公開されているAPIのソースコードを、少しだけ見て見ました。

おそらく、要約をしている部分（コアロジックにあたる部分）が以下かと思いますが、
https://github.com/recruit-tech/summpy/blob/master/summpy/lexrank.py

DictVectorizer と pairwise_distances を使っているので、
文章を区切ったのち、特徴抽出を行い、その特徴の距離行列を求めて、
その結果をスコアリングしている...ように見えます。
※ そこまでがっつりとソースを追ったわけではないので、
　詳しい方、コメントいただけると嬉しいです。


# まとめ
- summpy側で文章の加工は行わない。あくまで原文を句点等で区切り、重要度の高い文章を抽出する
- 文章量と行数のバランスさえ合えば、きちんと要約される（何言ってるか分からない。。とはならない）
- まとまりのない文章の要約はNG。例えば、文章内に「目次」等の箇条書き情報がある場合は、除いた方が良い要約がされそう。

# 終わりに
最後まで見ていただきありがとうございます。

「こんな文章要約するとどうなる？」
「この文章を要約してほしいよ！」

といったリクエストがあれば、コメントいただけると喜びます。
※ 可能な限り、試してみたいと思います。