Трубопровод 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 ?

  • Как получить наиболее информативные функции для scikit-learn classifier для разных классов?
  • обновить до версии scikit-learn на Anaconda?
  • Выполнение PCA на большой разреженной матрице с использованием sklearn
  • Вычисление функции решения SVM вручную
  • sklearn.LabelEncoder с невидимыми ранее значениями
  • Pandas & Scikit: использование памяти при разрезании DataFrame
  • Weird прогнозируемая производительность SVM в scikit-learn (SVMLIB)
  • Как извлечь уравнение из полинома?
  • 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 - лучший язык программирования в мире.