Stanford Politeness APIの環境構築

# 概要
 Politenessは文章の礼儀正しさの指標を表す数値です。詳しい定義は[提唱者の論文](https://www.amazon.co.jp/%E3%83%9D%E3%83%A9%E3%82%A4%E3%83%88%E3%83%8D%E3%82%B9-%E8%A8%80%E8%AA%9E%E4%BD%BF%E7%94%A8%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%80%81%E3%81%82%E3%82%8B%E6%99%AE%E9%81%8D%E7%8F%BE%E8%B1%A1-Politeness%EF%BC%9ASome-Universals-Language/dp/4327378208)を参照してもらうとして、とりあえず高いほど礼儀正しい文ということになります。その英文におけるPoliteness値を判定する[「Stanford Politeness API」](https://github.com/sudhof/politeness)というPythonソフトウェアを使用するまでのインストール手順です。判定方法はSupport Vector Machineによるものとのこと。

# 環境
- Ubuntu 16.04.4 LTS (Xenial Xerus)
- anyenv

# 手順
## 1. Python（2系）のインストール
 Pythonで書かれているのでまずはPythonをインストールします。以下は[anyenv](https://qiita.com/zaburo/items/8ac16133c3823c6e6ad6)の上のpyenvにインストールする手順ですがPythonがあればとりあえず何でも良いです。ただし後ほど各種ライブラリインストールのところでnumpyのバージョンを指定してインストールしてしまったりするのでその辺が変わるのが嫌な場合はpyenv等の管理ツールを使ったほうが良いかもしれません。以上で何いってるかわからない場合はとりあえず心配はないと思うので普通にインストールされているPythonをそのまま使ってください。

### 事前のライブラリインストール
```bash
sudo apt install curl llvm sqlite3 libssl-dev libbz2-dev libreadline-dev libsqlite3-dev libncurses5-dev libncursesw5-dev python-tk python3-tk tk-dev aria2
```
このあたりが足りないと途中で変なエラーが出る原因になるのでとりあえずインストールしておきましょう。

### pyenvとpython本体のインストール
```
anyenv install pyenv
pyenv install 2.7.14
pyenv global 2.7.14
```

## 2. 訓練済みモデルその他のダウンロード
GitHubからクローンするだけです。

```bash
git clone https://github.com/sudhof/politeness.git
```

## 3. 各種ライブラリのインストール
　基本的には README.md に書かれている通りにライブラリをインストールします。
　ただし一部追加で初理をしないと動かない部分があります。

### 要求ライブラリのインストール
　何が入るのかは requirement.txt を見れば割とそのまま書いてあります。

```bash
pip install -r requirement.txt
```

### scikit-learnの整合性確保
READMEによると次のステップはtokenizers/punkt/english.pickle nltkリソースのダウンロードですが、普通にやろうとすると以下のようなエラーが発生します。

```python
python
>>> import nltk
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/nltk/__init__.py", line 117, in <module>
    from nltk.align import *
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/nltk/align/__init__.py", line 15, in <module>
    from nltk.align.ibm1 import IBMModel1
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/nltk/align/ibm1.py", line 18, in <module>
    from nltk.corpus import comtrans
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/nltk/corpus/__init__.py", line 66, in <module>
    from nltk.corpus.reader import *
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/nltk/corpus/reader/__init__.py", line 59, in <module>
    from nltk.corpus.reader.tagged import *
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/nltk/corpus/reader/tagged.py", line 17, in <module>
    from nltk.tag import str2tuple, map_tag
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/nltk/tag/__init__.py", line 65, in <module>
    from nltk.tag.sequential    import (SequentialBackoffTagger, ContextTagger,
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/nltk/tag/sequential.py", line 25, in <module>
    from nltk.classify.naivebayes import NaiveBayesClassifier
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/nltk/classify/__init__.py", line 93, in <module>
    from nltk.classify.scikitlearn import SklearnClassifier
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/nltk/classify/scikitlearn.py", line 41, in <module>
    from sklearn.feature_extraction import DictVectorizer
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/sklearn/feature_extraction/__init__.py", line 7, in <module>
    from .dict_vectorizer import DictVectorizer
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/sklearn/feature_extraction/dict_vectorizer.py", line 14, in <module>
    from ..utils import atleast2d_or_csr, tosequence
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/sklearn/utils/__init__.py", line 10, in <module>
    from .murmurhash import murmurhash3_32
  File "numpy.pxd", line 155, in init sklearn.utils.murmurhash (sklearn/utils/murmurhash.c:5029)
ValueError: numpy.dtype has the wrong size, try recompiling
```
どうやらnumpyとscikit-learnの整合性が取れていないという話のようで、なんとなく requirements.txt で scikit-learn → numpy の順にインストールしてるのが悪いような気がするのですが、まあそんなことをいっていても仕方がないのでこちらを手動で修正します。

```bash
pip uninstall scikit-learn
pip install scikit-learn==0.15.1
```
再インストールすれば整合性は直してくれるとのこと。

### nltkリソースのダウンロード
　テキストのトークン化のためにnltk.word_tokenizeを使用しているので tokenizers/punkt/english.pickle をダウンロードする必要があるとのことなのですが、よくわからないのでnltkリソースを全部ダウンロードします。全部ダウンロードする場合はREADMEの記載とちょっと変わって以下の通り。

```python
python
>>>import nltk
>>>nltk.download('all')
>>>exit()
```
nltk.downloadはたまにタイムアウトしますが、何度でも```nltk.download('all')```を呼び出し続ければいずれ終わります。ちなみにREADMEのように```nltk.download()```とallを抜かすとダウンロードする対象を選ばせるGUIが出ます。わかる方はそちらでやると良いでしょう。GUIでタイムアウトするとやり直しのときに再度立ち上げないといけないみたいですが……。

### 必要ライブラリの追加インストール
　READMEによると環境構築はこれで完了とのことなのですが、サンプルを試そうとすると

```python
Traceback (most recent call last):
  File "model.py", line 63, in <module>
    clf = cPickle.load(open(MODEL_FILENAME))
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/sklearn/svm/__init__.py", line 13, in <module>
    from .classes import SVC, NuSVC, SVR, NuSVR, OneClassSVM, LinearSVC
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/sklearn/svm/classes.py", line 1, in <module>
    from .base import BaseLibLinear, BaseSVC, BaseLibSVM
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/sklearn/svm/base.py", line 9, in <module>
    from . import libsvm_sparse
  File "libsvm_sparse.pyx", line 5, in init sklearn.svm.libsvm_sparse (sklearn/svm/libsvm_sparse.c:6773)
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/sklearn/utils/__init__.py", line 11, in <module>
    from .validation import (as_float_array, check_arrays, safe_asarray,
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/sklearn/utils/validation.py", line 17, in <module>
    from .fixes import safe_copy
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/sklearn/utils/fixes.py", line 18, in <module>
    from .testing import ignore_warnings
  File "/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/sklearn/utils/testing.py", line 36, in <module>
    from nose.tools import assert_equal
ImportError: No module named nose.tools
```
こうなります。No module named nose.toolsとのことなので、入れましょう。

```bash
pip install nose
```

## 4. 動作確認
### 入力
```bash
python model.py
```

### 出力
```text
/home/【ユーザー名】/.anyenv/envs/pyenv/versions/2.7.14/lib/python2.7/site-packages/numpy/core/fromnumeric.py:2499: VisibleDeprecationWarning: `rank` is deprecated; use the `ndim` attribute or function instead. To find the rank of a matrix see `numpy.linalg.matrix_rank`.
  VisibleDeprecationWarning)
====================
Text:  Have you found the answer for your question? If yes would you please share it?
	P(polite) = 0.719
	P(impolite) = 0.281


====================
Text:  Sorry :) I dont want to hack the system!! :) is there another way?
	P(polite) = 0.640
	P(impolite) = 0.360


====================
Text:  What are you trying to do?  Why can't you just store the "Range"?
	P(polite) = 0.034
	P(impolite) = 0.966


====================
Text:  This was supposed to have been moved to &lt;url&gt; per the cfd. why wasn't it moved?
	P(polite) = 0.068
	P(impolite) = 0.932
```
警告は出ますが無事動作しました。

# 参考文献
- [pyenvまとめ](https://qiita.com/SUZUKI_Masaya/items/7ba3fef9eb7c9603762a)
- [pythonのモジュールについてのエラー](https://teratail.com/questions/48486)
- [NLTK data out of date - Python 3.4](https://stackoverflow.com/questions/33183618/nltk-data-out-of-date-python-3-4)
- [Python error in SVM classifier.predict()](https://stackoverflow.com/questions/29773574/python-error-in-svm-classifier-predict)
- [ImportError: No module named nose.tools](https://stackoverflow.com/questions/25398915/importerror-no-module-named-nose-tools)