【GiNZA】GoogleColabで日本語NLPライブラリGiNZAがloadできない

2019/10/11

Python 自然言語処理

t f B! P L
GiNZAという神・日本語NLPライブラリがあります。

  • 分かち書き/品詞タグ付け/固有表現認識/係り受け解析などがワンストップでできる
  • pip1行でインストール可能
という特徴があります。
特にColabでは2行目が重要です。

分かち書きはMeCab、Janome、Sudachiなど、インストールも容易なツールが整っている状況にあります。

一方の係り受け解析は、Cobocha(南瓜)やKNPが有名ですが、前回も記事にしたように環境構築がややめんどうで時間がかかります。

通常環境では一度インストールしてしまえばよいので、たいした問題にはならないのですが、Colabでは毎度インストールする必要があるため(ファイル群はドライブに保存しておくとしても)、これが結構ネックになります。

なのでpip1行でインストールというのは魅力です。
!pip install "https://github.com/megagonlabs/ginza/releases/download/latest/ginza-latest.tar.gz"


※何度も使う場合はファイルを落としておきましょう。

しかし問題がおきる…

エラー

GiNZAはフルスタックNLPライブラリspacyのAPIから使用します。

pip1行&日本語の係り受け解析も可能なStanfordNLPというライブラリもあるのですが、APIの機能性やドキュメントの充実度ではspacyが上回っているように感じます(StanfordNLPにも大変お世話になっております)。

さて、ginzaは以下のようにして利用可能です。

import spacy
nlp = spacy.load('ja_ginza')

---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-3-68155cf1a72c> in <module>()
----> 1 nlp = spacy.load('ja_ginza')

1 frames
/usr/local/lib/python3.6/dist-packages/spacy/util.py in load_model(name, **overrides)
    169     elif hasattr(name, "exists"):  # Path or Path-like to model data
    170         return load_model_from_path(name, **overrides)
--> 171     raise IOError(Errors.E050.format(name=name))
    172 
    173 

OSError: [E050] Can't find model 'ja_ginza'. It doesn't seem to be a shortcut link, a Python package or a valid path to a data directory.
</module></ipython-input-3-68155cf1a72c>



GiNZAが認識できていないようです。


再起動すれば直る

このエラー、Colabのメニューから「ランタイム」>「ランタイムを再起動」をすると何事もなかったかのうように直ります。
spacy.load("ja_ginza")でふつうに利用可能になります。

間違って「すべてのランタイムをリセット」を選択しないでください。
インストールしたGiNZAも消えてしまいます。

でも毎回再起動するのも面倒なので原因を調べました。


pkg_resourcesに読み込まれていない

まずspacy.loadについて調べるとドキュメントに以下のようにあります。

spaCy will assume it’s a Python package and import it and call the model’s own load() method.
https://spacy.io/api/top-level#spacy.load

ショートカットリンク、パッケージ、モデルへのpathの3つに対応していて、引数によって”よしな”にしてくれるみたいです。

ginzaはginzaとしてパッケージ(Pythonライブラリ)でインストールされているので、パッケージ呼び出しになります。

で、こちらのis_packageというメソッドで、ja_ginzaがパッケージとして存在しているかを判定する処理になっているのですが
https://github.com/explosion/spaCy/blob/master/spacy/util.py#L294


_人人人人_
> ない <
 ̄Y^Y^Y ̄


具体的には以下の2行でパッケージ一覧を取得して、その中にja_ginzaがあるかチェックしているのですが、colab環境ではja_ginzaをインストールしただけでは、こちらのパッケージ一覧に含まれていないことが判明しました。


import pkg_resources
packages = pkg_resources.working_set.by_key.keys()


Colabのセルでこちらを実行してみるとたしかにpackagesの中にja_ginzaがないので、これがエラーの原因とわかります。

ちなみに再起動するとja_ginza(正確にはja-ginza)がちゃんと入ってます。

さらにちなみにimport ja_ginza自体は最初から(インストール直後から)動くんですよね。
import文がインストール直後から使えるのは、(当たり前ですが)他のパッケージと一緒です。

これはGiNZA側の問題ではなく、Colabの仕様でpkg_resourcesに新しくインストールしたライブラリが反映されないことが原因みたいです。

他のライブラリはimportから使うので、上述の通り問題なく使えるわけです。
一方のGiNZAはspacyからの呼び出しという変則的な使い方をするので、この問題が発生します。

pkg_resourcesをリロードする

impというpythonのimport文をなんやかんやするライブラリがあります。
標準ライブラリなので特に心配せず使えます。
これでpkg_resourcesをリロードします。

import pkg_resources, imp
imp.reload(pkg_resources)


あっけないですが、これで完了です。
再起動する必要はありません!


全体としては

!pip install "https://github.com/megagonlabs/ginza/releases/download/latest/ginza-latest.tar.gz"

import pkg_resources, imp
imp.reload(pkg_resources)

import spacy
nlp = spacy.load('ja_ginza')


でOKです。

今日のベストプラクティス

昔プログラミングできるお友達からよく「ソース嫁」と言われましたが、今考えると大事なアドバイスでした。

ラベル

QooQ