Переворачивание numpy осей массива на основе значений во втором массиве - PullRequest
1 голос
/ 08 июля 2020

В настоящее время пишу собственный генератор данных для Keras, и я хочу случайным образом перевернуть входной массив numpy во время обучения для целей увеличения данных.

  • X: входной массив формы (batchsize, y_dim, x_dim)
  • to_flip: логический массив формы (batchsize, X_rank), который описывает, какие оси нужно переворачивать

Например:

X = [[[0, 1],
      [2, 3]],
     [[4, 5],
      [6, 7]]]

to_flip = [[0, 1],
           [1, 0]]

flipped_X = [[[1, 0],
              [3, 2]],
             [[6, 7],
              [4, 5]]]

или любую комбинацию оси (обе оси / оси не перевернуты). Я не мог понять, как использовать np.flip или расширенную индексацию (например, X[::-1]), чтобы получить этот эффект. В идеале я мог бы найти решение, которое можно было бы применить ко всей партии без явных циклов, потому что я считаю, что такое решение будет быстрее.

Лучшее решение, которое у меня есть на данный момент:

def flip_axes(an_input, axes_to_flip):
    axis_inds_to_flip = np.where(axes_to_flip.reshape(-1))[0]
    return np.flip(an_input, axis_inds_to_flip)[None, ...]

flipped_X = np.concatenate([flip_axes(an_input, axes_to_flip) 
                            for an_input, axes_to_flip 
                            in zip(X, to_flip)], axis=0)

У кого-нибудь есть мысли? Действительно ли это будет быстрее, чем то, что я написал здесь?

edit: Я изменил свое решение, чтобы оно работало, и добавил свою мотивацию для вопроса.

1 Ответ

0 голосов
/ 08 июля 2020

Вы можете сделать это, используя python индексацию следующим образом:

flipped_X = []
for sample, flip in zip(X, to_flip):
  flipped = [*sample]                          # Generate a copy of x
  if flip[0]:                                  # if flip[0] is 1
    flipped = flipped[::-1]                    # Flip matrix vertically
  if flip[1]:                                  # if flip[1] is 1
    flipped = [elem[::-1] for elem in flipped] # Flip elements to flip horizontally
  flipped_X.append(flipX)                      # Finally append to result
print(flipped_X)

Будет выводить:

[[[1, 0], [3, 2]], [[6, 7], [4, 5]]]

EDIT: Используя numpy, вы можете добиться того же результата с помощью np.flip(m, axis), где m будет каждой матрицей в X, а axis будет кортежем индексов, которые нужно переворачивать. Например:

to_flip = [[0,0], [1,0], [0,1], [1,1]]

, поэтому индексы будут

[[], [0], [1], [0,1]]

# Get indexes to flip at each sample
flip_idxes = map(lambda flip: [idx for idx, x in enumerate(flip) if x], to_flip)
# Flip samples
flipped_X = np.array([np.flip(sample, indexes) for sample, indexes in zip(X, flip_idxes)])
...