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()
.