Быстрый синтаксис NumPy / Torch для объединения строк с одинаковым значением столбца - PullRequest
0 голосов
/ 04 февраля 2020

Я дал массив / тензор из n значений, каждое из которых состоит из вектора признаков (в примере это первые 4 значения) и позиционного вектора (в примере 5-е значение). Таким образом, весь массив здесь имеет форму (n, 5).

[ 1 2 3 4 *0* ]
[ 5 1 0 1 *1* ]
[ 0 1 0 1 *1* ]
[ 1 0 3 0 *2* ]
[ 1 1 2 6 *2* ]
[ 0 1 0 2 *2* ]

Моя цель - объединить (max или sum или avg) значения по первому измерению в соответствии с их позиционным вектором. Т.е. все строки с одинаковым позиционным вектором (здесь 5-е значение) должны быть объединены с учетом некоторой функции симметрии c (скажем, sum ()) при сохранении указанного 5-го значения постоянным. В результате получается новый массив формы (n ', 5)

[ 1 2 3 4 *0* ]
[ 5 2 0 2 *1* ]
[ 2 2 5 8 *2* ]

Естественно, это может быть достигнуто с помощью циклического перемещения по массиву и сохранения всех их в dict с помощью key, value = positional_vector, sum(feature_vector, dict[positional_vector]), а затем преобразования его обратно в массив.

К сожалению, этот метод кажется довольно медленным, и, поскольку я планирую использовать его при обучении нейронного net, представляется более разумным использовать некоторые магические умножения на тензор / матрицу c.

Я очень ценю любые полезные комментарии:)

[В противоположность данному примеру, позиционный вектор может быть n-мерным и не упорядоченным.]

1 Ответ

1 голос
/ 04 февраля 2020

Так что это грубый ответ, основанный на методе diff, который я упоминал в комментариях. Обратите внимание, что, поскольку вам нужна операция agg, основанная на группах, нет верного способа действительно векторизовать ее эффективным образом. Кроме того, в этом примере предполагается, что ваши данные отсортированы, мы вернемся к нему позже.

def reduce(x): return np.r_[x[:,:-1].sum(axis=0), x[0,-1]]
x = np.array([[ 1, 2, 3, 4, 0 ],
              [ 5, 1, 0, 1, 1 ],
              [ 0, 1, 0, 1, 1 ],
              [ 1, 0, 3, 0, 2 ],
              [ 1, 1, 2, 6, 2 ],
              [ 0, 1, 0, 2, 2 ] ])
ind = np.where(np.diff(x[:,-1], prepend=x[0,-1]))[0]
x_agg = np.array([reduce(i) for i in np.split(x, ind)])

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

Теперь, если данные не отсортированы в последней строке, возникают два случая:

  1. Элементы с одинаковым целевым значением рядом друг с другом. Это должно быть хорошо, так как поведение diff будет таким же (возможно, придется добавить условие, например np.where(np.diff(...)!=0)
  2. Те же значения цели разбросаны, тогда порядок не должен иметь значения, так как нет логического способа сопоставления их после агломерации.

Надеюсь, это поможет.

...