FeatureUnion和Pipeline用于选择矩阵

时间:2017-06-08 15:56:30

标签: python scikit-learn

这是你的男孩。

我目前正在与scikit-learn FeatureUnion和Pipeline组合中的一些诡计苦苦挣扎。

1)我有功能和目标

的.csv数据

2)另外,我有已加载并转换为np.arrays的np.array的图像数据

3)我已将它拆分为train(train_idx和img_train)并使用StratifiedShuffleSplit测试(test_idx和img_test)。

要调用.csv数据的列车特征,我输入train_idx [0],其形状为(792,192)。

要调用图像数据的列车特征,我输入img_train [0],其形状为(792,4816)。

作为目标的train_idx [1]和img_train [1]的相应形状是(792,)和(792,)

这里的任务是将PCA()应用于img_train并保留train_idx,然后将它们传递给RandomForestClassifier。首先,它们应该存储在np.matrix中。我的代码如下:

# define functions that pass columns of matrix to FeatureUnion
def select_col_idx(matrix, cols):
      return X_train[:, cols]
def select_col_img(matrix, cols):
      return X_train[:, cols]

A_train = np.matrix((train_idx[0].T, train_idx[1], img_train[0].T, img_train[1]))

A_train的形状为(1,4)。这很奇怪吗?

无论如何,下面的代码显示了我的管道:

subpipe = Pipeline([('caller', FunctionTransformer(select_col_img, validate=False, kw_args={'cols': [2, 3]})),
                ('pca', PCA(n_components=4, random_state=RANDOM_SEED))])


subpipe_2 = Pipeline([('caller', FunctionTransformer(select_col_idx, validate=False, kw_args={'cols': [0, 1]})),
                 ('none', None)])

features = FeatureUnion([('subpipe', subpipe), ('subpipe2', subpipe_2)])

pipe = Pipeline([('features_union', features), ('rf', rf)])

然后,我尝试pipe.fit(A_train)这不起作用。 说实话,我甚至不能适应subpipe.fit(A_train)因为我收到'设置一个带序列的数组元素'错误。

我知道数据提取存在问题,但我花了好几个小时试图解决它。我甚至尝试在简单的np.array上执行相同的操作,而不是np.matrix,但仍然没有运气。

我感到筋疲力尽......

提前感谢您所有事情Q(^,^ Q)

P.S。我们真的需要python Class来提取列吗?

发表编辑:

正如我已经写过的那样,subpipe.fit(A_train)不起作用。错误的完整回溯如下:

Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/home/komplett/.local/lib/python3.6/site-
packages/sklearn/pipeline.py", line 270, in fit
self._final_estimator.fit(Xt, y, **fit_params)
File "/home/komplett/.local/lib/python3.6/site-
packages/sklearn/decomposition/pca.py", line 307, in fit
self._fit(X)
File "/home/komplett/.local/lib/python3.6/site-
packages/sklearn/decomposition/pca.py", line 346, in _fit
copy=self.copy)
File "/home/komplett/.local/lib/python3.6/site-
packages/sklearn/utils/validation.py", line 382, in check_array
array = np.array(array, dtype=dtype, order=order, copy=copy)
ValueError: setting an array element with a sequence.

但是,我可以将第二个子管道设为subpipe_2.fit(A_train),这样可以完全正常拟合:

 Pipeline(steps=[('caller', FunctionTransformer(accept_sparse=False,
      func=<function select_col_idx at 0x7fc954345b70>,
      inv_kw_args=None, inverse_func=None, kw_args={'cols': [0, 1]},
      pass_y=False, validate=False)), ('none', None)])

后后编辑

好的,如果我执行X = select_col_idx(A_train, cols=[0, 1]),它将返回两个矩阵的矩阵,其中X[:, 0]是要素(train_idx [0] .T),X[:, 1]是目标(train_idx [ 1])。请注意,[X.dtype == object][true]

尽管如此,如果我尝试按下面提到的那样调整FunctionTransformer,我会收到上面的回溯错误,即带有'设置带序列的数组元素'的错误:

X = FunctionTransformer(select_col_img, kw_args={'cols': [2, 3]})
X.fit_transform(A_train)
# output is the traceback error

我使用'select_col_idx'函数收到同样的错误。

所以,我在想的是我需要修复提取方法。它应该将矩阵矩阵划分为两个不同的变量,它们作为 X y 以任意方式传递给任何.fit,因为简单.fit( X)不起作用并返回'设置数组...'错误。对我来说似乎是'好'的逻辑,但它很麻烦。

为什么有人会告诉我首先将数据存储在np.matrix中!无论如何,是否可以修复此方法?

修改后的帖子

train_idx看起来像这样:

[array([[ 0.001953,  0.      ,  0.      , ...,  0.010742,  0.      ,
     0.017578],
   [ 0.003906,  0.005859,  0.074219, ...,  0.02832 ,  0.      ,
     0.051758],
   [ 0.013672,  0.005859,  0.019531, ...,  0.      ,  0.024414,
     0.029297],
   ..., 
   [ 0.011719,  0.013672,  0.048828, ...,  0.017578,  0.      ,
     0.019531],
   [ 0.027344,  0.044922,  0.009766, ...,  0.      ,  0.024414,
     0.051758],
   [ 0.046875,  0.10742 ,  0.015625, ...,  0.008789,  0.006836,  0.      
   ]]), array([ 4,  6, 56, 29, 94, 22, 94, 16,  0, 53, 87, 67, 51, 97,  5, 98, 44,
   43, 66, 81, 80, 67, 42, 67, 40, 34, 91, 88,  0, 13, 53, 89, 32, 72,
   22, 79, 26, 84, 79,  3, 25, 19, 87, 18, 48,  5,  2, 28, 66,  2, 83,
   22, 10, 84, 58, 55, 76, 52,  3, 84, 44, 65,  9, 51,  9, 58, 52, 44, ...  6, 28, 25])]

img_train相同,但第一个数组如下所示:

[array([[255, 255, 255, ..., 255, 255, 255],
   [255, 255, 255, ..., 255, 255, 255],
   [255, 255, 255, ..., 255, 255, 255],
   ..., 
   [255, 255, 255, ..., 255, 255, 255],
   [255, 255, 255, ..., 255, 255, 255],
   [255, 255, 255, ..., 255, 255, 255]], dtype=uint8)

所以第一个train_idx数组是特征,第二个是目标。更确切地说,这些特征是树叶的宽度,边缘,长度等特征(据我所知)。目标是这种叶子的类别(它们的生物学名称)。 img_train的第一个数组是先前已经标准化的输入图像的像素。我已经加载了以下函数:

def load_img(path):
img_data = []
for i in range(1, 101):
    flist = glob.glob(path + str(i) + '.png')
    for j in flist:
        img_data.append(scipy.misc.imread(j))

return np.array(img_data)

然后,我在img_data上应用了StratifiedShuffle。

再次感谢您的回复,Vivek!

1 个答案:

答案 0 :(得分:0)

好。

在考虑了一些问题之后,我实际上想出了一个解决方案,但数据存储在np.array中,而不是必需的np.matrix格式。请注意rf = RandomForestClassifier()

A_train = np.array((train_idx[0].T, train_idx[1],
                    img_train[0].T, img_train[1]))

def select_train_cols(X_train, cols):
    return X_train[cols].T

def megapipe():
    subpipe = Pipeline(
        [('caller', FunctionTransformer(select_train_cols, validate=False, kw_args={'cols': 0})),
         ('none', None)])
    subpipe_2 = Pipeline(
        [('caller', FunctionTransformer(select_train_cols, validate=False, kw_args={'cols': 2})),
         ('pca', pca)])
    fu = FeatureUnion([('subpipe', subpipe),
                       ('subpipe_2', subpipe_2)])
    megapipe = Pipeline([('fu', fu),
                         ('rf', rf)])
    return megapipe

因此可以实现不会产生错误的megapipe.fit(A_train, train_idx[1])

似乎实施np.matrix方法只是不切实际和不合适......或者至少我希望如此。

感谢。

<强>被修改

因此,使用np.concatenate()实际上有一个解决方案:

A_train = np.concatenate((train_idx[0], img_train[0]), axis=1)
A_test = np.concatenate((test_idx[0], img_test[0]), axis=1)

def select_col_idx(X, col_idx=[1]):
return X[:, col_idx]

然后,您将致电FunctionTransformer以获取 train_idx 数据,如下所示:

FunctionTransformer(select_col_idx, kw_args={'col_idx': np.arange(0, 192)}

要将PCA()应用于 img_train ,您只需获取其余数据列,然后按照前面所述在管道中传递。

适合和预测适用于.fit(A_train, *labels).predict(A_test, *labels)

从现在开始,这个主题可能被认为是多余的。

谢谢。