Как стандартно масштабировать 3D матрицу? - PullRequest
0 голосов
/ 02 мая 2018

Я работаю над проблемой классификации сигналов и хотел бы сначала масштабировать матрицу набора данных, но мои данные представлены в формате 3D (партия, длина, каналы).
Я пытался использовать Scikit-learn Standard Scaler:

from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

Но у меня есть это сообщение об ошибке:

Найден массив с dim 3. Ожидается StandardScaler <= 2 </p>

Я думаю, что одним из решений было бы разделить матрицу по каждому каналу на несколько двумерных матриц, масштабировать их по отдельности и затем вернуть обратно в формат 3D, но мне интересно, есть ли лучшее решение.
Большое спасибо.

Ответы [ 3 ]

0 голосов
/ 09 ноября 2018

Если вы хотите масштабировать каждую функцию по-разному, как StandardScaler, вы можете использовать это:

import numpy as np
from sklearn.base import TransformerMixin
from sklearn.preprocessing import StandardScaler


class NDStandardScaler(TransformerMixin):
    def __init__(self, **kwargs):
        self._scaler = StandardScaler(copy=True, **kwargs)
        self._orig_shape = None

    def fit(self, X, **kwargs):
        X = np.array(X)
        # Save the original shape to reshape the flattened X later
        # back to its original shape
        if len(X.shape) > 1:
            self._orig_shape = X.shape[1:]
        X = self._flatten(X)
        self._scaler.fit(X, **kwargs)
        return self

    def transform(self, X, **kwargs):
        X = np.array(X)
        X = self._flatten(X)
        X = self._scaler.transform(X, **kwargs)
        X = self._reshape(X)
        return X

    def _flatten(self, X):
        # Reshape X to <= 2 dimensions
        if len(X.shape) > 2:
            n_dims = np.prod(self._orig_shape)
            X = X.reshape(-1, n_dims)
        return X

    def _reshape(self, X):
        # Reshape X back to it's original shape
        if len(X.shape) >= 2:
            X = X.reshape(-1, *self._orig_shape)
        return X

Он просто сглаживает особенности ввода перед передачей его в StandardScaler. Затем он меняет их обратно. Использование такое же, как для StandardScaler:

data = [[[0, 1], [2, 3]], [[1, 5], [2, 9]]]
scaler = NDStandardScaler()
print(scaler.fit_transform(data))

печать

[[[-1. -1.]
  [ 0. -1.]]

 [[ 1.  1.]
  [ 0.  1.]]]

Аргументы with_mean и with_std непосредственно передаются StandardScaler и, таким образом, работают, как ожидается. copy=False не сработает, поскольку изменение формы не происходит на месте. Для 2-D входов NDStandardScaler работает как StandardScaler:

data = [[0, 0], [0, 0], [1, 1], [1, 1]]
scaler = NDStandardScaler()
scaler.fit(data)
print(scaler.transform(data))
print(scaler.transform([[2, 2]]))

печать

[[-1. -1.]
 [-1. -1.]
 [ 1.  1.]
 [ 1.  1.]]
[[3. 3.]]

как в примере с sklearn для StandardScaler.

0 голосов
/ 30 января 2019
s0, s1, s2 = y_train.shape[0], y_train.shape[1], y_train.shape[2]
y_train = y_train.reshape(s0 * s1, s2)
y_train = minMaxScaler.fit_transform(y_train)
y_train = y_train.reshape(s0, s1, s2)

s0, s1, s2 = y_test.shape[0], y_test.shape[1], y_test.shape[2]
y_test = y_test.reshape(s0 * s1, s2)
y_test = minMaxScaler.transform(y_test)
y_test = y_test.reshape(s0, s1, s2)

Просто изменил данные так. Для дополнения нулями используйте аналогичные:

s0, s1, s2 = x_train.shape[0], x_train.shape[1], x_train.shape[2]
x_train = x_train.reshape(s0 * s1, s2)
minMaxScaler.fit(x_train[0::s1])
x_train = minMaxScaler.transform(x_train)
x_train = x_train.reshape(s0, s1, s2)

s0, s1, s2 = x_test.shape[0], x_test.shape[1], x_test.shape[2]
x_test = x_test.reshape(s0 * s1, s2)
x_test = minMaxScaler.transform(x_test)
x_test = x_test.reshape(s0, s1, s2)
0 голосов
/ 02 мая 2018

Вам нужно будет установить и сохранить скейлер для каждого канала

from sklearn.preprocessing import StandardScaler

scalers = {}
for i in range(X_train.shape[1]):
    scalers[i] = StandardScaler()
    X_train[:, i, :] = scalers[i].fit_transform(X_train[:, i, :]) 

for i in range(X_test.shape[1]):
    X_test[:, i, :] = scalers[i].transform(X_test[:, i, :]) 
...