Трубопровод Scikit-Learn's: решена малая матрица, но требуются плотные данные

Мне трудно понять, как исправить созданный мной конвейер (читайте: в значительной степени вставляйте из учебника). Это python 3.4.2:

df = pd.DataFrame df = DataFrame.from_records(train) test = [blah1, blah2, blah3] pipeline = Pipeline([('vectorizer', CountVectorizer()), ('classifier', RandomForestClassifier())]) pipeline.fit(numpy.asarray(df[0]), numpy.asarray(df[1])) predicted = pipeline.predict(test) 

Когда я запускаю его, я получаю:

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

Это для строки pipeline.fit(numpy.asarray(df[0]), numpy.asarray(df[1])) .

Я много экспериментировал с решениями через numpy, scipy и т. Д., Но я до сих пор не знаю, как это исправить. И да, подобные вопросы возникли раньше, но не внутри конвейера. Где я должен применять toarray или todense ?

4 Solutions collect form web for “Трубопровод Scikit-Learn's: решена малая матрица, но требуются плотные данные”

К сожалению, эти два несовместимы. CountVectorizer производит разреженную матрицу, а для RandomForestClassifier требуется плотная матрица. Конвертировать можно с помощью X.todense() . Это значительно увеличит ваш объем памяти.

Ниже приведен пример кода для этого, который я нашел по адресу http://zacstewart.com/2014/08/05/pipelines-of-featureunions-of-pipelines.html, который позволяет вам вызвать .todense () на стадии конвейера.

 class DenseTransformer(TransformerMixin): def transform(self, X, y=None, **fit_params): return X.todense() def fit_transform(self, X, y=None, **fit_params): self.fit(X, y, **fit_params) return self.transform(X) def fit(self, X, y=None, **fit_params): return self 

Когда у вас есть DenseTransformer , вы можете добавить его в качестве шага конвейера.

 pipeline = Pipeline([ ('vectorizer', CountVectorizer()), ('to_dense', DenseTransformer()), ('classifier', RandomForestClassifier()) ]) 

Другой вариант – использовать классификатор, предназначенный для разреженных данных, таких как LinearSVC .

 from sklearn.svm import LinearSVC pipeline = Pipeline([('vectorizer', CountVectorizer()), ('classifier', LinearSVC())]) 

Случайные леса в 0.16-dev теперь принимают разреженные данные.

Самое чистое решение – использовать FunctionTransformer для преобразования в плотный: это автоматически реализует методы fit , transform и fit_transform как в ответе Дэвида. Кроме того, если мне не нужны специальные имена для шагов моего конвейера, мне нравится использовать sklearn.pipeline.make_pipeline удобства sklearn.pipeline.make_pipeline чтобы включить более минималистический язык для описания модели:

 pipeline = make_pipeline( CountVectorizer(), FunctionTransformer(lambda x: x.todense(), accept_sparse=True), RandomForestClassifier() ) 

вы можете изменить Series pandas на массивы, используя метод .values .

 pipeline.fit(df[0].values, df[1].values) 

Однако я думаю, что проблема здесь возникает, потому что CountVectorizer() возвращает разреженную матрицу по умолчанию и не может быть передан в RF-классификатор. CountVectorizer() имеет параметр dtype для указания типа возвращаемого массива. Тем не менее, как правило, вам нужно сделать какое-то уменьшение размерности, чтобы использовать случайные леса для классификации текста, потому что мешок слов содержит векторы очень долго

Python - лучший язык программирования в мире.