web-dev-qa-db-ja.com

scikit-learnのTfidfVectorizer:ValueError:np.nanは無効なドキュメントです

テキストデータからいくつかの特徴抽出を行うためにscikit-learnのTfidfVectorizerを使用しています。スコア(+1または-1が可能)とレビュー(テキスト)を含むCSVファイルがあります。このデータをDataFrameにプルして、Vectorizerを実行できるようにしました。

これは私のコードです:

_import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer

df = pd.read_csv("train_new.csv",
             names = ['Score', 'Review'], sep=',')

# x = df['Review'] == np.nan
#
# print x.to_csv(path='FindNaN.csv', sep=',', na_rep = 'string', index=True)
#
# print df.isnull().values.any()

v = TfidfVectorizer(decode_error='replace', encoding='utf-8')
x = v.fit_transform(df['Review'])
_

これは私が得るエラーのトレースバックです:

_Traceback (most recent call last):
  File "/home/PycharmProjects/Review/src/feature_extraction.py", line 16, in <module>
x = v.fit_transform(df['Review'])
 File "/home/b/hw1/local/lib/python2.7/site-   packages/sklearn/feature_extraction/text.py", line 1305, in fit_transform
   X = super(TfidfVectorizer, self).fit_transform(raw_documents)
 File "/home/b/work/local/lib/python2.7/site-packages/sklearn/feature_extraction/text.py", line 817, in fit_transform
self.fixed_vocabulary_)
 File "/home/b/work/local/lib/python2.7/site- packages/sklearn/feature_extraction/text.py", line 752, in _count_vocab
   for feature in analyze(doc):
 File "/home/b/work/local/lib/python2.7/site-packages/sklearn/feature_extraction/text.py", line 238, in <lambda>
tokenize(preprocess(self.decode(doc))), stop_words)
 File "/home/b/work/local/lib/python2.7/site-packages/sklearn/feature_extraction/text.py", line 118, in decode
 raise ValueError("np.nan is an invalid document, expected byte or "
 ValueError: np.nan is an invalid document, expected byte or unicode string.
_

NaNとして読み取られているものについてCSVファイルとDataFrameをチェックしましたが、何も見つかりません。 18000行あり、isnanをTrueとして返す行はありません。

df['Review'].head()は次のようになります。

_  0    This book is such a life saver.  It has been s...
  1    I bought this a few times for my older son and...
  2    This is great for basics, but I wish the space...
  3    This book is perfect!  I'm a first time new mo...
  4    During your postpartum stay at the hospital th...
  Name: Review, dtype: object
_
34
boltthrower

トレースバックで明確に述べられているように、dtype objectunicode文字列に変換する必要があります。

x = v.fit_transform(df['Review'].values.astype('U'))  ## Even astype(str) would work

TFIDF VectorizerのDocページから:

fit_transform(raw_documents、y = None)

パラメーター:raw_documents:反復可能
strnicode、またはfile objectsのいずれかを生成するイテラブル

79
Nickil Maveli

この問題を解決するより効率的な方法を見つけました。

_x = v.fit_transform(df['Review'].apply(lambda x: np.str_(x)))
_

もちろん、df['Review'].values.astype('U')を使用して、シリーズ全体を変換できます。しかし、変換したいシリーズが非常に大きい場合、この関数を使用するとより多くのメモリが消費されることがわかりました。 (80w行のデータを含むシリーズでこれをテストし、これを行うとastype('U')は約96GBのメモリを消費します)

代わりに、ラムダ式を使用して、シリーズ内のデータをstrから_numpy.str__にのみ変換し、その結果が_fit_transform_関数でも受け入れられる場合、これはより高速になります。また、メモリ使用量は増加しません。

TFIDF VectorizerのDocページに次の理由があるので、これがなぜ機能するのかわかりません。

fit_transform(raw_documents、y = None)

パラメーター:raw_documents:反復可能

str、unicode、またはfileオブジェクトを生成するイテラブル

しかし実際には、この反復可能オブジェクトはstrではなく_np.str__を生成する必要があります。

3
Andy Ma