sklearn конвейер ValueError: все размеры входного массива, кроме оси конкатенации, должны точно совпадать - PullRequest
1 голос
/ 23 октября 2019

У меня есть 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())
            ])),

        ])),
    ])

Учитывая, что функции A и B каждая возвращает массив dim (# of records, 10, 20), в то время как Z возвращает (# of records, 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). Я хочу получить массив измерений (количество записей, 10, 40), в котором процесс конкатенации применяется к axis=2.

. Как получить то, что я хочу, используя Pipeline и безредактировать исходный код библиотеки?

Редактировать: Я упоминал, что объединение A и B создает массив (# записей, 10, 40) DIM. Это не правильно;он производит массив DIM (количество записей 20, 20). Я отредактирую вопрос.

1 Ответ

0 голосов
/ 24 октября 2019

Я решил проблему, создав преобразователь, который обрабатывает процесс конкатенации.

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')),
    ])

То, что я сделал в этом преобразователе,следующее: Например, имеющаяся у меня функция A, B и Z возвращает следующие массивы:

  • A: (# записей, 10, 20)
  • B: (количество записей 10, 20)
  • Z: (количество записей 10, 15)

Вmode='append', я добавляю все массивы с дополнительными фиксированными значениями максимальной длины 50 (в качестве примера), чтобы иметь одинаковое значение axis=2 dim и позволить функции Xs = np.hstack(Xs) работать.

Таким образом, в результате конвейер вернет массив: (# of records, 30, 50)

Затем, в mode=split', я добавляю его в конце конвейера, я разделяю окончательный массив на их добавленныйформа: (# of records, 30, 50) до 3 элементов массива dim (# of records, 10, 50)

Затем я удаляю дополнительное фиксированное значение и применяю конкатенацию к последнему dim.

Dim финального массива: (# of records, 10, 55). 55 - объединение 3-го измерения массивов (20 + 20 + 15), что я и хочу.

...