GiNZA 5 (=SudachiPy >= 0.6)で49149 bytes以上のテキストをTokenizeする


1. GiNZA(というかSudachiPy)でデカ目のテキストファイルがTokenizeできなかった話

講談社サイエンティフィク 実践Data ScienceシリーズPythonではじめるテキストアナリティクス入門を勉強中。
(この本、雑に理解していた GiNZA、spaCy、Sudachi の処理が体系的に理解出来てとてもありがたい)。

サンプルコードはGiNZA==4.0.6SudachiPy==0.5.4環境での利用が推奨されている。

GiNZA のバージョン上げたら、スピードアップするかしら? と思い試しに、サンプルコードを GiNZA 5.1 環境で実行したところ、江戸川乱歩作「影男」のテキストを Tokenize するコードで下記のエラー。

Exception: Tokenization error: Input is too long, it can't be more than 49149 bytes, was 464332

2. 原因

Sudachi の Slack 検索させていただいたところ、内部のコスト計算でオーバフローが起こるため、入力サイズに制限を掛けているとの説明あり。
どのバージョンからの変更なのかは不明だが、 GiNZA==5.1 + SudachiPy==0.6.3の環境では上記エラー発生。
GiNZA==4.0.6SudachiPy==0.5.4環境の環境ではエラーおきず。

3. 一時的解決策

入力ファイルの分割が推奨とのことだったので、text を.readlinesで一行ずつ読み込み list に格納。適当な単位(今回は 100 要素)でテキストを塊(Chunk)に分割して list に格納。chunk から要素を取り出して、tokenize 処理してみた。

import spacy

input_fn = 'text/kageotoko.corpus.txt'

nlp = spacy.load("ja_ginza")

with open(input_fn) as f:
    lines = f.readlines()

chunks = [' '.join(lines[i:i+100]) for i in range(0, len(lines), 100)]

for chunk in chunks:
    doc = nlp(chunk)
    for ## 以下処理省略

4. 将来の課題

分割して tokenize した後の Doc オブジェクトをまとめておける DocBin というオブジェクトもあるようなので、今後必要になったら、使ってみよう。

https://spacy.io/api/docbin#_title