Python 关于Sklearn管道的困惑&;特征联合在一起

Python 关于Sklearn管道的困惑&;特征联合在一起,python,scikit-learn,Python,Scikit Learn,我试着用一个玩具的例子来说明我的困惑。我意识到这是一个关于iris数据集的愚蠢的例子 from sklearn.pipeline import Pipeline, FeatureUnion from sklearn.model_selection import GridSearchCV from sklearn.svm import SVC from sklearn.datasets import load_iris import pandas as pd from sklearn.base i

我试着用一个玩具的例子来说明我的困惑。我意识到这是一个关于iris数据集的愚蠢的例子

from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
from sklearn.datasets import load_iris
import pandas as pd
from sklearn.base import BaseEstimator, TransformerMixin


class ItemSelector(BaseEstimator, TransformerMixin):
    """For data grouped by feature, select subset of data at a provided key.

    The data is expected to be stored in a 2D data structure, where the first
    index is over features and the second is over samples.  i.e.

    >> len(data[key]) == n_samples

    Please note that this is the opposite convention to scikit-learn feature
    matrixes (where the first index corresponds to sample).

    ItemSelector only requires that the collection implement getitem
    (data[key]).  Examples include: a dict of lists, 2D numpy array, Pandas
    DataFrame, numpy record array, etc.

    >> data = {'a': [1, 5, 2, 5, 2, 8],
               'b': [9, 4, 1, 4, 1, 3]}
    >> ds = ItemSelector(key='a')
    >> data['a'] == ds.transform(data)

    ItemSelector is not designed to handle data grouped by sample.  (e.g. a
    list of dicts).  If your data is structured this way, consider a
    transformer along the lines of `sklearn.feature_extraction.DictVectorizer`.

    Parameters
    ----------
    key : hashable, required
        The key corresponding to the desired value in a mappable.
    """
    def __init__(self, key):
        self.key = key

    def fit(self, x, y=None):
        return self

    def transform(self, data_dict):
        return data_dict[self.key]

# 150 examples, 4 features, labels in {0, 1, 2}
iris = load_iris()
y = iris.target
dfX = pd.DataFrame(iris.data, columns=iris.feature_names)

# feature union transformer list 
transformer_list = [
    ('sepal length (cm)', Pipeline([
        ('selector', ItemSelector(key='sepal length (cm)')),
    ])),

    ('sepal width (cm)', Pipeline([
        ('selector', ItemSelector(key='sepal width (cm)')),
    ])),

    ('petal length (cm)', Pipeline([
        ('selector', ItemSelector(key='petal length (cm)')),
    ])),

    ('petal width (cm)', Pipeline([
        ('selector', ItemSelector(key='petal width (cm)')),
    ])),
]

# create pipeline
pipeline = Pipeline([
    ("union", FeatureUnion(transformer_list=transformer_list)),
    ("svm", SVC(kernel="linear")),
])

# train model
param_grid = dict({})
search = GridSearchCV(estimator=pipeline, param_grid=param_grid, n_jobs=1)
search.fit(dfX, y)
print(search.best_estimator_)
它在以下方面出错:

/Users/me/.virtualenvs/myenv/lib/python2.7/site-packages/sklearn/utils/validation.pyc in check_consistent_length(*arrays)
    179     if len(uniques) > 1:
    180         raise ValueError("Found input variables with inconsistent numbers of"
--> 181                          " samples: %r" % [int(l) for l in lengths])
    182
    183

ValueError: Found input variables with inconsistent numbers of samples: [1, 99]
我的想法是功能联合是并行的,管道是串行的


我怎么会认为这是错误的?混合到两个的正确方法是什么,以获得特定功能类型的丰富流,并能够分段添加变换器,但仍然与最终预测器的功能联合在一起?

是的,您的想法是正确的:

我的想法是功能联合是并行的,管道是串行的

但是这里的问题是,您的
ItemSelector
返回了一个带有shape
(150,)
的numpy数组。在FeatureUnion的最后一步中,来自不同变换器的特性连接完成,使用水平堆叠阵列的
numpy.hstack()
。请注意,输出中不存在第二个维度。因此,当对所有变压器进行并集时,将生成一个形状为
(600,)
的数组。这就是为什么在
fit
方法中出现错误的原因

返回数组的正确形状应为
(150,4)
。必须向以正确形状返回数据的管道中再添加一个转换器(或使用
numpy.asmatrix()
transpose()
手动更改返回数据的形状)

请看一下的文档示例。在本例中,
ItemSelector
的输出被传递到其他转换器,如
TfidfVectorizer()
DictVectorizer()
,后者返回2d数组中的数据,然后在
FeatureUnion
中正确合并。 希望能有帮助