Numpy Array - Drop дубликаты - PullRequest
       4

Numpy Array - Drop дубликаты

0 голосов
/ 28 октября 2018

Я пытаюсь удалить дубликаты элементов из массива numpy.

Eg:
a = np.array([[0.03,0.32],[0.09,0.26],[0.03,0.32]])
a = np.unique(a,axis=0)

Это прекрасно работает.Но проблема в том, что этот код является частью функции.И я запускаю функцию, скажем, 10 раз.При любом запуске система зависает именно на этой линии.Я заметил, что массив будет иметь максимальный размер 3500, а каждый элемент (внутренний массив) будет иметь длину 60. Почему это происходит или любым другим эффективным способом?

1 Ответ

0 голосов
/ 28 октября 2018

Есть довольно много проблем с тем, что вы делаете.

Во-первых, обратите внимание, что np.unique не работает хорошо для арифметики с плавающей запятой и не будет в целом отфильтровать "уникальные" массивы с плавающей точкой:

In [16]: a = np.array([[2.1*3, .123], [6.3, 2.05*.06]])

In [17]: a
Out[17]: 
array([[6.3  , 0.123],
       [6.3  , 0.123]])

In [18]: np.unique(a, axis=0)
Out[18]: 
array([[6.3  , 0.123],
       [6.3  , 0.123]])

Обратите внимание, что дубликаты все еще находятся в результате после вызова np.unique.Причина этого в том, что np.unique сравнивается с равенство , что означает, что числа с плавающей запятой должны совпадать бит за битом.Однако арифметика с плавающей запятой не является точной, поэтому вы не гарантированно правильно отфильтруете дубликаты.

Во-вторых, с точки зрения производительности вы можете добиться большего успеха, чем np.unique с типом hashable. np.unique всегда будет работать в O (n log n), так как он выполняет сортировку.Вы можете проверить это в исходном коде:

if optional_indices:
    perm = ar.argsort(kind='mergesort' if return_index else 'quicksort')
    aux = ar[perm]
else:
    ar.sort()
    aux = ar

Таким образом, независимо от того, как условная оценка оценивается, сортировка выполняется по ar (который является входным массивом, см. Здесь для получения более подробной информации: https://github.com/numpy/numpy/blob/v1.15.0/numpy/lib/arraysetops.py#L277). Причина этого в том, что np.unique поддерживает богатый набор функций (например, получение индексов дуплей, возвращение количества дуплей и т. Д.).

Вам не нужно сортировать пополучить уникальные элементы. Если вы превратите свой тип в тип с хэшем (например, tuple), то вы можете отфильтровать дубликаты по O (n), линейному времени. Вот пример:

In [37]: b
Out[37]: 
[(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)]

In [39]: np.unique(b, axis=0)
Out[39]: array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])

In [40]: set(b)
Out[40]: {(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)}

In [41]: %timeit np.unique(b, axis=0)
21.9 µs ± 132 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [42]: %timeit set(b)
627 ns ± 5.09 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Итак,Как вы можете видеть, просто использование встроенного set работает примерно в 30 раз быстрее, чем np.unique. Обратите внимание, что это не будет работать правильно для массивов с плавающей запятой, но я просто хотел показать, что np.unique не особенно эффективен изАлгоритмическая перспектива.

Наконец, 3500x60 не так уж и велик. Вы можете легко пройти через это, даже с алгоритмом низкого уровня, и он не должен зависать на любом современном оборудовании. Этоsон должен работать довольно быстро:

In [43]: np.random.seed(0)

In [46]: x = np.random.random((3500, 60))

In [49]: %timeit np.unique(x, axis=0)
2.57 ms ± 17.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Так что на моем MacBook Pro уходит 2,57 миллисекунды, что не совсем удобно с точки зрения аппаратного обеспечения (2,3 ГГц i5, 8 ГБ ОЗУ). Убедитесь, что вы профилируете свой код, и убедитесь, что строка в этом вопросе на самом деле строка с ошибкой.

HTH.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...