CountVectorizerで日本語を使う

語彙カウントしてますか?
自然言語処理の下準備でしょっちゅうお世話になるscikit-learnのCountVectorizerやTfidfVectorizerですが、実は分かち書きした日本語に対してそのまま使うと一文字の単語を認識しなかったり、結構癖があります。

詳しくは下記のナイスなブログ記事をどうぞ。
scikit-learnでテキストをBoWやtfidfに変換する時に一文字の単語も学習対象に含める
こちらのブログによると、

これ以外にも “-” (ハイフン) などが単語の境界として設定されていて想定外のところで切られたり、
デフォルトでアルファベットを小文字に統一する設定になっていたり(lowercase=True)と、注意する時に気をつけないといけないことが、結構あります。デフォルトでアルファベットを小文字に統一する設定になっていたり(lowercase=True)と、注意する時に気をつけないといけないことが、結構あります。

とあります。
そんなこともあるのか。CountVectorizerで試してみましょう(TfidfVectorizerもtokenの使い方は同じです)。

import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer

text_list = ["scikit-learn の Count Vectorizer を 使って みよう"]
vectorizer_count = CountVectorizer()
count = vectorizer_count.fit_transform(text_list)
vocab = vectorizer_count.get_feature_names()

df_count = pd.DataFrame(count.toarray(), columns=vocab)
print(df_count)
count learn scikit vectorizer みよう 使って
0 1 1 1 1 1 1

なってますね。これもデフォルトのtoken_patternが原因です(公式ドキュメント)。

token_patternstr, default=r”(?u)\b\w\w+\b”

この\b(単語の境界)や\w(アルファベット、アンダーバー、数字)が英語仕様なのが原因です(ちなみに (?u) はUnicode (UTF-8) を示す正規表現)。
ということでシンプルに区切り文字を使ってCountVectorizerを使ってみます。
やり方は、文末に区切り文字(半角スペース)を追加した後「(任意の1文字以上の文字列)+半角スペース」をtoken_patternとして設定します。
正規表現を上手く使えば他のやり方もある気がしますが、とりあえず。

text_list = ["scikit-learn の Count Vectorizer を 使って みよう"]
text_list[0] = text_list[0] + " "
print(text_list)

vectorizer_count = CountVectorizer(token_pattern='(?u)(.+?) ',
                                  lowercase=False)
count = vectorizer_count.fit_transform(text)
vocab = vectorizer_count.get_feature_names()

df_count = pd.DataFrame(count.toarray(), columns=vocab)
print(df_count)
['scikit-learn の Count Vectorizer 使って みよう ']
Count Vectorizer scikit-learn みよう 使って
0 1 1 1 1 1 1

これでよし。ついでにアルファベットを勝手に小文字にするお節介機能もオフにしておきました。
あらかじめ単語のリストを用意しておけば、スペース以外を区切り文字にすることもできます。これによってスペースを含めた単語も一単語としてカウントすることができますね。

text_list = [""]

word_list = ["scikit-learn", "の", "Count Vectorizer", "を", "使って", "みよう"]
delimiter = "///"
text = delimiter.join(word_list)
text_list[0] = text + delimiter
print(text_list)

vectorizer_count = CountVectorizer(token_pattern='(?u)(.+?){}'.format(delimiter),
                                  lowercase=False)
count = vectorizer_count.fit_transform(text_list)
vocab = vectorizer_count.get_feature_names()

df_count = pd.DataFrame(count.toarray(), columns=vocab)
print(df_count)
['scikit-learn///の///Count Vectorizer///を///使って///みよう///']
Count Vectorizer scikit-learn みよう 使って
0 1 1 1 1 1 1

いいね。素敵な前処理ライフを!