1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Countvectorizerをしたら単語(1文字)が消える、不要後にされてしまう件について

Last updated at Posted at 2021-04-03

はじめに

日本語文章でBOWをするためにCountvectorizerを試していたのですが、どうもfitした単語とtransformしたあとのカラム(get_feature_names()で獲得が可能)が一致せず、fitに利用した単語が一部消えていることが判明しました。解決策を知らず、検索もなかなか時間がかかったため、まとめたいと思います。

環境

  • python3.8
  • Docker
  • docker_image : Datascience notebook
  • Jupyter Lab / jupyter notebook

追記

from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(tokenizer=lambda txt: txt.split())

こちらが一番良かったです。正規表現は「......」のようなものが消えてしまいました。

問題

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

# ベクトル化する文字列
sample = np.array(['今日 晴れ 明日 曇'])

# CountVectorizer
vec_count = CountVectorizer()
# ベクトル化
vec_count.fit(sample)
X = vec_count.transform(np.array(["今日 雨 明日 雨 会社 電車 晴れ 会社 歩く"]))

print('Vocabulary size: {}'.format(len(vec_count.vocabulary_)))
print('Vocabulary content: {}'.format(vec_count.vocabulary_))
pd.DataFrame(X.toarray(), columns=vec_count.get_feature_names()) 

結果がこのように出力される
bandicam 2021-04-03 23-33-49-114.jpg

本来であれば「」という単語もカラムになってほしいが、なぜか府用語とされてしまう。

調べてみると、すべての単一文字トークンは、デフォルトのトークナイザによって無視されるとのこと

英語が前提でできているため、「a」などは削除されるようにできているらしい。詳しくはこちらの記事を見ていただきたい。

解決策

こちらの記事を参考にしたところ解決した。
やったこととしては、Countvectorizer(token_pattern='(?u)\\b\\w+\\b')としただけ

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

# ベクトル化する文字列
sample = np.array(['今日 晴れ 明日 曇'])

# CountVectorizer
vec_count = CountVectorizer(token_pattern='(?u)\\b\\w+\\b')
# ベクトル化
vec_count.fit(sample)
X = vec_count.transform(np.array(["今日 雨 明日 雨 会社 電車 晴れ 会社 歩く"]))

print('Vocabulary size: {}'.format(len(vec_count.vocabulary_)))
print('Vocabulary content: {}'.format(vec_count.vocabulary_))
pd.DataFrame(X.toarray(), columns=vec_count.get_feature_names()) 

結果
bandicam 2021-04-03 23-47-05-916.jpg

うまくいきました!

余談

1つ目の記事には単一の文字トークンを語彙に含めたい場合は、衣装トークナイザーを使用する必要があります。

vectorizer = CountVectorizer(tokenizer=lambda txt: txt.split())

とあり、こちらで解決したのですが、別の状態(入力が単純なnumpy配列じゃない?)のときにうまくいかず、すべてのカラムに1以上の値が割り当てられているという謎の現象が起きました。こちらについては現在調査中ですので、わかり次第追記したいと思います。

今回のサンプルコードであれば問題なく動いています。

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

# ベクトル化する文字列
sample = np.array(['今日 晴れ 明日 曇'])

# CountVectorizer
vec_count = CountVectorizer(tokenizer= lambda sample: sample.split())
# ベクトル化
vec_count.fit(sample)
X = vec_count.transform(np.array(["今日 雨 明日 雨 会社 電車 晴れ 会社 歩く"]))

print('Vocabulary size: {}'.format(len(vec_count.vocabulary_)))
print('Vocabulary content: {}'.format(vec_count.vocabulary_))
pd.DataFrame(X.toarray(), columns=vec_count.get_feature_names()) 

結果
bandicam 2021-04-03 23-47-56-580.jpg

Warningはでていますが、1文字の単語も機能しています。

最後に

日本語文章をCountvectorizerすると疎のベクトルになりやすいので、やはり扱いは難しいなと感じました。1文字が消えてしまう問題に気付かないで行ってしまう人もいそうですね (私も今になって気づきました)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?