TypeError: разреженная длина матрицы неоднозначна; используйте getnnz() или shape[0] при использовании RF-классификатора?

Я изучаю случайные леса в scikit learn, и в качестве примера я хотел бы использовать случайный классификатор леса для классификации текста с моим собственным набором данных. Поэтому сначала я векторизировал текст с помощью tfidf и для классификации:

from sklearn.ensemble import RandomForestClassifier
classifier=RandomForestClassifier(n_estimators=10) 
classifier.fit(X_train, y_train)           
prediction = classifier.predict(X_test)

когда я запускаю классификацию, я получил это:

TypeError: A sparse matrix was passed, but dense data is required. Use X.toarray() to convert to a dense numpy array.

тогда я использовал .toarray() на X_train и я получил следующее:

TypeError: sparse matrix length is ambiguous; use getnnz() or shape[0]

из вопрос как я понял мне нужно чтобы уменьшить размерность массива numpy, я делаю то же самое:

from sklearn.decomposition.truncated_svd import TruncatedSVD        
pca = TruncatedSVD(n_components=300)                                
X_reduced_train = pca.fit_transform(X_train)               

from sklearn.ensemble import RandomForestClassifier                 
classifier=RandomForestClassifier(n_estimators=10)                  
classifier.fit(X_reduced_train, y_train)                            
prediction = classifier.predict(X_testing) 

тогда я получил это исключение:

  File "/usr/local/lib/python2.7/site-packages/sklearn/ensemble/forest.py", line 419, in predict
    n_samples = len(X)
  File "/usr/local/lib/python2.7/site-packages/scipy/sparse/base.py", line 192, in __len__
    raise TypeError("sparse matrix length is ambiguous; use getnnz()"
TypeError: sparse matrix length is ambiguous; use getnnz() or shape[0]

я попробовал следующий:

prediction = classifier.predict(X_train.getnnz()) 

и получил это:

  File "/usr/local/lib/python2.7/site-packages/sklearn/ensemble/forest.py", line 419, in predict
    n_samples = len(X)
TypeError: object of type 'int' has no len()

из этого были подняты два вопроса: Как я могу использовать случайные леса для правильной классификации? и что происходит с X_train?.

затем я попробовал следующий:

df = pd.read_csv('/path/file.csv',
header=0, sep=',', names=['id', 'text', 'label'])



X = tfidf_vect.fit_transform(df['text'].values)
y = df['label'].values



from sklearn.decomposition.truncated_svd import TruncatedSVD
pca = TruncatedSVD(n_components=2)
X = pca.fit_transform(X)

a_train, a_test, b_train, b_test = train_test_split(X, y, test_size=0.33, random_state=42)

from sklearn.ensemble import RandomForestClassifier

classifier=RandomForestClassifier(n_estimators=10)
classifier.fit(a_train, b_train)
prediction = classifier.predict(a_test)

from sklearn.metrics.metrics import precision_score, recall_score, confusion_matrix, classification_report
print 'nscore:', classifier.score(a_train, b_test)
print 'nprecision:', precision_score(b_test, prediction)
print 'nrecall:', recall_score(b_test, prediction)
print 'n confussion matrix:n',confusion_matrix(b_test, prediction)
print 'n clasification report:n', classification_report(b_test, prediction)

2 ответов


немного неясно, передаете ли вы одну и ту же структуру данных (тип и форму) в fit способ и predict способ классификатора. Случайные леса займут много времени, чтобы работать с большим количеством функций, поэтому предложение уменьшить размерность в сообщении, на которое вы ссылаетесь.

вы должны применить SVD как к тренировочным, так и к тестовым данным, чтобы классификатор обучался на том же фасонном входе, что и данные, которые вы хотите предсказать. Регистрация вход fit и входные данные для метода predict имеют одинаковое количество функций и являются массивами, а не разреженными матрицами.

обновление с Пример: обновлено для использования dataframe

from sklearn.feature_extraction.text import TfidfVectorizer
tfidf_vect= TfidfVectorizer(  use_idf=True, smooth_idf=True, sublinear_tf=False)
from sklearn.cross_validation import train_test_split

df= pd.DataFrame({'text':['cat on the','angel eyes has','blue red angel','one two blue','blue whales eat','hot tin roof','angel eyes has','have a cat']\
              ,'class': [0,0,0,1,1,1,0,3]})



X = tfidf_vect.fit_transform(df['text'].values)
y = df['class'].values

from sklearn.decomposition.truncated_svd import TruncatedSVD        
pca = TruncatedSVD(n_components=2)                                
X_reduced_train = pca.fit_transform(X)  

a_train, a_test, b_train, b_test = train_test_split(X, y, test_size=0.33, random_state=42)

from sklearn.ensemble import RandomForestClassifier 

classifier=RandomForestClassifier(n_estimators=10)                  
classifier.fit(a_train.toarray(), b_train)                            
prediction = classifier.predict(a_test.toarray()) 

обратите внимание, что SVD происходит до разделения на учебные и тестовые наборы, так что массив, переданный предиктору, имеет то же самое n как массив fit метод вызывается.


Я мало знаю о sklearn, хотя я смутно припоминаю некоторые более ранние проблемы, вызванные переключением на использование разреженных матриц. Внутри некоторые матрицы пришлось заменить на m.toarray() или m.todense().

но чтобы дать вам представление о том, что сообщение об ошибке о том, считать

In [907]: A=np.array([[0,1],[3,4]])
In [908]: M=sparse.coo_matrix(A)
In [909]: len(A)
Out[909]: 2
In [910]: len(M)
...
TypeError: sparse matrix length is ambiguous; use getnnz() or shape[0]

In [911]: A.shape[0]
Out[911]: 2
In [912]: M.shape[0]
Out[912]: 2

len() обычно используется в Python для подсчета количества терминов 1-го уровня списка. При применении к 2d-массиву это количество строк. Но!--5--> лучший способ подсчета рядов. И M.shape[0] то же самое. В этом случае вас не интересует .getnnz, что является числом ненулевых членов разреженной матрицы. A не имеет этого метода, хотя может быть получен из A.nonzero().