python2.7から3.5へのアップグレード(NLP風味)
研究で使っているコードを2.7から3.5へアップグレードした。
理由はpython3がいいらしいという話を前にカンファで聞いたからというだけ。具体的に何がいいかはよく覚えてないけどレガシーなものを使い続けるのは良くないと思うし、自分でもやるべきだと思ってやってみた。なお環境はubuntuとmac。どちらもほとんど同様の作業で出来るはず。
python3.5のインストール
pythonのバージョン管理をするpyenvを利用する
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
homebrewでもインストール出来るが3.5.0が入ってないようなのでgitでやったほうが良さそう。次にシェルの設定ファイルに以下のコードを追加する。参考URLではbashだが僕はzshを使っているので.zshrcを書き換えた。
export PYENV_ROOT="${HOME}/.pyenv" export PATH=${PYENV_ROOT}/bin:$PATH eval "$(pyenv init -)"
設定を以下のコマンドで反映。
$ source .zshrc
インストール可能なものの一覧の表示。3.5.0があることを確認する。
pyenv install -l
python3.5のインストール、利用バージョンの変更、更新をする。最後にpythonのバージョンを確認し、3.5.0になっていれば成功。
pyenv install 3.5.0 pyenv global 3.5.0 pyenv rehash python --version
参考URL
MacでPython使う時の最低限のメモ(pyenv編) - Qiita
pyenv + virtualenv (CentOS7) - Qiita
コードの修正
2to3を利用する。以下のコマンドで動作確認。成功すれば変更点がどこかが表示される。
$ 2to3 (ファイル名)
「-w」オプションを使うことでファイルを書き換えることができる。またディレクトリを指定することでディレクトリ内のコード全てに適用出来る。
$ 2to3 -w .
これでほとんど更新出来るが使用するライブラリによって問題が発生する場合がある。特に文字コード周りでの問題は多い。問題に関係する変数をtype()関数で型を確認しつつ修正する。以降は自然言語処理関係のライブラリについて書く。
参考URL
26.4. 2to3 - Python 2 から 3 への自動コード変換 — Python v2.6.2 documentation
MeCab
MeCabをインストールしなおす。pythonライブラリのバージョン管理をするpipが便利。
$ pip install mecab-python3
しかしpython3でMeCabを使うとsurfaceが読み取れなくなることがある。この問題は一度parseをすることで解決するようだ。
import MeCab tagger = MeCab.Tagger('') tagger.parse('') #これを挿入する text = u'MeCabで遊んでみよう!' node = tagger.parseToNode(text) while node: print(node.surface + '\t' + node.feature) node = node.next
これについては以下のリンク先が詳しい。
CaboCha
先にsubversionをインストールしてからpipを利用する。
$ brew install subversion $ pip install 'svn+http://cabocha.googlecode.com/svn/trunk/python@r99'
gensim
pipで非常に簡単に出来た。
$ pip install numpy $ pip install scipy $ pip install gensim
ライブラリが入ってるかどうかはpythonを起動しimportして確かめてみよう。
MeCabのsurface問題とCaboChaのインストールには結構手こずってしまい、今日の午後はずっとアップグレード作業になってしまった。裏を返せば今日だけで済んで良かったのかもしれない。明日以降はコードのリファクタリングをし、アルゴリズムの改良をするつもり。
追記(4/28)
MeCab周りが遅いとボヤいたところ、大学の先生から以下のページを教えてもらった。
PythonでのMeCabを速くするtips - Qiita
上記ではparseToNode()を使っているが、parse()の出力結果を使った方が速いという話である。なおparseToNode()の場合は形態素をオブジェクト型として出力するがparse()は形態素を文字列型として出力する。この点のみ注意すれば修正出来るだろう。