sklearn管道ValueError:除连接轴外的所有输入数组维度必须完全匹配

Posted

技术标签:

【中文标题】sklearn管道ValueError:除连接轴外的所有输入数组维度必须完全匹配【英文标题】:sklearn pipeline ValueError: all the input array dimensions except for the concatenation axis must match exactly 【发布时间】:2020-02-19 23:49:48 【问题描述】:

我有一个sklearn 管道,它提取三个不同的特征。

manual_feats = Pipeline([
        ('FeatureUnion', FeatureUnion([
            ('segmenting_pip1', Pipeline([
                ('A_features', A_features()),
                ('segmentation', segmentation())
            ])),
            ('segmenting_pip2', Pipeline([
                ('B_features', B_features(),
                ('segmentation', segmentation())
            ])),
            ('segmenting_pip3', Pipeline([
                ('Z_features', Z_features()),
                ('segmentation', segmentation())
            ])),

        ])),
    ])

鉴于特征 AB 每个返回一个暗淡数组(记录数,10、20),而 Z 返回(记录数,10、15 )。

当我使用所有功能安装管道时,我收到此错误:

 File "C:\Python35\lib\site-packages\sklearn\pipeline.py", line 451, in _transform
    Xt = transform.transform(Xt)
  File "C:\Python35\lib\site-packages\sklearn\pipeline.py", line 829, in transform
    Xs = np.hstack(Xs)
  File "C:\Python35\lib\site-packages\numpy\core\shape_base.py", line 340, in hstack
    return _nx.concatenate(arrs, 1)
ValueError: all the input array dimensions except for the concatenation axis must match exactly

但是,如果我排除功能 Z,管道可以工作,但在轴上应用的串联 = 1 暗淡(记录数,20、20)。我想要的是获得一个 (# of records, 10, 40) 维度的数组,其中连接过程应用于axis=2

如何在不编辑库源代码的情况下使用Pipeline 获得我想要的内容?

编辑: 我提到AB 的串联会产生一个(记录数,10、40)DIM 数组。这不正确;它产生一个 DIM 数组(记录数,20、20)。我将编辑问题。

【问题讨论】:

查看Pipeline 代码,并尝试弄清楚您的输入是如何转换为XtXs 的。它必须假设Xs 是二维数组的列表或数组,应该在最后一个轴上连接。第一个轴必须匹配,但它不匹配(出于某种原因)。 谢谢@hpaulj,但我不想更改pipeline 代码中的某些内容,我可以用Xs = np.concatenate(Xs, axis=-1) 更改Xs = np.hstack(Xs) 行,它可以工作。我可以在那里更改连接过程的轴,但我想在我的代码中添加一些东西。 【参考方案1】:

我通过创建一个处理连接过程的转换器解决了这个问题。

class append_split_3D(BaseEstimator, TransformerMixin):
    def __init__(self, segments_number=20, max_len=50, mode='append'):
        self.segments_number = segments_number
        self.max_len = max_len
        self.mode = mode
        self.appending_value = -5.123

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

    def transform(self, data):
        if self.mode == 'append':
            self.max_len = self.max_len - data.shape[2]
            appending = np.full((data.shape[0], data.shape[1], self.max_len), self.appending_value)
            new = np.concatenate([data, appending], axis=2)
            return new
        elif self.mode == 'split':
            tmp = []
            for item in range(0, data.shape[1], self.segments_number):
                tmp.append(data[:, item:(item + self.segments_number), :])
            tmp = [item[item != self.appending_value].reshape(data.shape[0], self.segments_number, -1) for item in tmp]
            new = np.concatenate(tmp, axis=2)
            return new
        else:
            print('Error: Mode value is not defined')
            exit(1)

整个管道变成这样的地方:

manual_feats = Pipeline([
        ('FeatureUnion', FeatureUnion([
            ('segmenting_pip1', Pipeline([
                ('A_features', A_features()),
                ('segmentation', segmentation()),
                ('append', append_split_3D(max_len=50, mode='append')),
            ])),
            ('segmenting_pip2', Pipeline([
                ('B_features', B_features(),
                ('segmentation', segmentation())
                ('append', append_split_3D(max_len=50, mode='append')),
            ])),
            ('segmenting_pip3', Pipeline([
                ('Z_features', Z_features()),
                ('segmentation', segmentation())
                ('append', append_split_3D(max_len=50, mode='append')),
            ])),

        ])),
        ('split', append_split_3D(segments_number=10, mode='split')),
    ])

我在这个转换器中所做的如下: 例如,我拥有的功能 ABZ 返回以下数组:

A: (记录数, 10, 20) B: (记录数, 10, 20) Z:(记录数,10、15)

mode='append' 中,我将所有数组附加最大长度值为50 的额外固定值(作为示例)以具有相同的axis=2 暗淡并允许函数Xs = np.hstack(Xs) 工作。

因此,管道将返回一个数组:(# of records, 30, 50)

然后,在mode=split' 中,我将它添加到管道的末尾,我将最终数组拆分为它们附加的形状:(# of records, 30, 50) 到 3 个暗淡的特征数组(# of records, 10, 50)

然后我删除额外的固定值,并在最后一个暗淡上应用连接。

最终数组的暗度为:(# of records, 10, 55)。 55是数组第3维的串联(20+20+15),这就是我想要的。

【讨论】:

以上是关于sklearn管道ValueError:除连接轴外的所有输入数组维度必须完全匹配的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 sklearn 管道跟踪 catboost 的分类索引

ValueError:使用 GridSearch 参数时估计器 CountVectorizer 的参数模型无效

sklearn(错误的输入形状)ValueError

带有 SkLearn 管道的 GridSearch 无法正常工作

sklearn 的 PLSRegression:“ValueError:数组不得包含 infs 或 NaN”

Numpy、Pandas 和 Sklearn 中的多维缩放拟合(ValueError)