概要
TfidfVectorizer.fitにおいてtokenizeとidf計算にどのくらい時間を要しているのか調べました。
背景
TfidfVectorizerのidf辞書のなるべく高速なマージ方法を検討したく、その事前準備として、TfidfVectorizer.fitのどの工程に時間がかかっているのかを調査しようと思いました。fitで時間がかかるのは、形態素解析(tokenize)とidfの計算なので、それら2つの時間を計りました。
実装
ライブラリをインストールします。
pip install scikit-learn datasets
大きな日本語のデータセットを用意します。
今回はmiracl-corpusを使います。700万件弱の文章です。
import time
import MeCab
from sklearn.feature_extraction.text import TfidfVectorizer
from datasets import load_dataset
import tqdm
dataset = load_dataset("miracl/miracl-corpus", "ja")["train"]
dataset = [d["text"] for d in dataset]
print(len(dataset))
6953614
datasetから適当な件数を取得して、tokenizeとidf計算にかかる時間を計測し出力します。tokenizerは使い慣れたmecabを使用しました。
# 形態素解析器の初期化(MeCab)
mecab = MeCab.Tagger("-Owakati")
# 形態素解析を行う関数
def tokenize(text):
return mecab.parse(text).split()
# 形態素解析の時間計測
for doc_num in [10**2, 10**3, 10**4, 10**5, 10**6]:
start_time = time.time()
tokenized_dataset = [tokenize(text) for text in dataset[:doc_num]]
tokenize_time = time.time() - start_time
# IDF計算の時間計測
tfidf_vectorizer = TfidfVectorizer(tokenizer=lambda text: text, preprocessor=lambda text: text)
start_time = time.time()
tfidf_vectorizer.fit(tokenized_dataset)
idf_time = time.time() - start_time
print(f"文書数: {doc_num}")
print(f"単語数: {sum([len(t) for t in tokenized_dataset])}")
print(f"単語種類数: {len(tfidf_vectorizer.get_feature_names_out())}")
print(f"形態素解析にかかった時間: {tokenize_time}")
print(f"IDF計算にかかった時間: {idf_time}")
print("")
結果
上記プログラムの実行結果は以下です。
文書数: 100
単語数: 6809
単語種類数: 1805
形態素解析にかかった時間: 0.07840418815612793
IDF計算にかかった時間: 0.003988027572631836
文書数: 1000
単語数: 75989
単語種類数: 9767
形態素解析にかかった時間: 0.03894186019897461
IDF計算にかかった時間: 0.021020174026489258
文書数: 10000
単語数: 652418
単語種類数: 38772
形態素解析にかかった時間: 0.3236968517303467
IDF計算にかかった時間: 0.15282797813415527
文書数: 100000
単語数: 7253378
単語種類数: 157076
形態素解析にかかった時間: 3.460052013397217
IDF計算にかかった時間: 1.8129661083221436
文書数: 1000000
単語数: 79557632
単語種類数: 538666
形態素解析にかかった時間: 48.29531979560852
IDF計算にかかった時間: 21.297609090805054
考察
以下の傾向が見て取れます。
- miracl-corpusの特徴
- 1件あたり平均して70-80単語
- 単語数が10倍になると単語の種類数は3-4倍
- 処理時間
- 形態素解析もIDF計算も処理時間は文書数(あるいは単語数)に概ね比例している
- 形態素解析はIDF計算の2倍くらい時間がかかっている。
制限事項
mecab以外のtokenizerを使ったらidf計算よりも高速になる可能性もあります。janomeやvibratoのほうがmecabより早いという記事もありました。