Как добавить маскирующий шум к двумерной матрице в векторной форме? - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть двумерный массив X с формой (n_samples, n_features).Я хочу применить маскирующий шум к каждому сэмплу, то есть к каждому ряду.По сути, для каждой записи строки я хочу случайным образом выбрать долю frac от общего числа n_features элементов и установить для них значение 0.

. Я до сих пор векторизовал внутреннюю часть цикла,но не могу избавиться от внешней i петли.

Мой текущий код приведен ниже.

def add_noise(X, frac):
    X_noise = X.copy()

    n_samples = X.shape[0]
    n_features = X.shape[1]

    for i in range(n_samples):
        mask = np.random.randint(0, n_features, int(frac * n_features))
        X_noise[i][mask] = 0

    return X_noise

Пример показан ниже.

test_arr = np.arange(1, 11)
test_arr = np.array([test_arr, test_arr])
print(test_arr)
print(add_noise(test_arr, 0.3))

[[ 1  2  3  4  5  6  7  8  9 10]
 [ 1  2  3  4  5  6  7  8  9 10]]
[[ 1  0  3  4  5  6  0  8  9  0]   # 0.3 * num_features = 3 random elements
 [ 0  2  3  4  5  6  7  0  0 10]]  # for each row set to 0

Какизбавиться от внешнего цикла?

Ответы [ 3 ]

0 голосов
/ 11 февраля 2019

попробуйте создать карту нулей и единиц и умножьте тестовый массив на карту:

zero_map = np.round(np.random.rand(*test_arr.shape) * (1-frac))
test_arr = test_arr * zero_map
0 голосов
/ 11 февраля 2019

вы можете использовать функцию numpy apply_along_axis.

def add_noise(X, frac):
    X_noise = X.copy()

    n_samples = X.shape[0]
    n_features = X.shape[1]

    mask = np.concatenate((np.ones((n_samples,int(frac * n_features)), dtype=np.bool),
                           np.zeros((n_samples, n_features - int(frac * n_features)), dtype=np.bool)),
                           axis=1)
    np.apply_along_axis(np.random.shuffle,1,mask)
    X_noise[mask] = 0
    return X_noise
0 голосов
/ 11 февраля 2019

Ничто не мешает вам использовать np.random.randint для генерации полной матрицы индексов, по одному элементу в строке:

k = int(frac * n_features)
indices = np.random.randint(0, n_features, size=(n_samples, k))
X_noise[np.arange(n_samples)[:, None], indices] = 0

Индекс np.arange(n_samples)[:, None] делает диапазон широковещательнымпридать форму n_samples, k.Этот подход имеет то преимущество, что не требует промежуточного шага с маской.

У этого подхода есть несколько потенциальных проблем:

  1. k = int(frac * n_features) не обязательно является ближайшим целым числомк фактической фракции, которую вы ищете.Нечто более похожее на k = math.round(frac * n_features).
  2. np.random.randint образцов с заменой.Это означает, что вы будете время от времени сталкиваться с одной и той же строкой в ​​индексе.Если вы в порядке с этим, это нормально.Если нет, вы можете взять образец без замены, используя np.random.choice(n_features, replace=False).Проблема в том, что тогда вам придется циклически проходить по каждой строке.

Более "честный" подход, на мой взгляд, состоит в том, чтобы генерировать последовательность случайных чисел и просто пороговать их вfrac, так что ваш общий шум приблизился к frac, но шум в каждой строке будет случайным.Числа могут быть сгенерированы с помощью чего-то вроде np.random.sample:

X_noise[np.random.sample(size=X_noise.shape) < frac] = 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...