#python #numpy
#python #numpy
Вопрос:
data_xy = tuple([x, y])
x и y — это массивы numpy с размерами:
x.shape = (56567, 128, 16) и
y.shape = (56567, 1)
Ошибка типа возникает в следующей строке:
for data_class in sorted(set(data_xy[1])):
Ошибка типа: не хэшируемый тип: ‘numpy.ndarray’
Комментарии:
1. наборы не могут содержать изменяемые типы. См . learnpython.dev/02-введение в python/…
2. @balderman. Наборы могут содержать изменяемые типы просто отлично. Они не могут содержать нехешируемые типы.
Ответ №1:
Вы не можете хэшировать массив numpy, потому что он изменяемый. Наборы — это хэш-таблицы, которые требуют, чтобы все их элементы были хэшируемыми.
Поскольку вы не можете применить set
к строкам массива, я предлагаю np.unique
вместо этого использовать:
s = np.unique(data_xy[1], axis=0)
s.sort()
for data_class in s:
В общем, выполнение for
цикла над массивами numpy — это то, что вы должны стремиться обойти, поскольку это часто не нужно и замедляет работу.
Альтернативным решением было бы создать хешируемый тип оболочки для строк, чтобы вы могли использовать их в set
. Это будет довольно медленно и не рекомендуется, но служит для иллюстрации концепции:
class RowView:
def __init__(self, row):
self.hash = hash(tuple(row))
self.data = row
def __hash__(self):
return self.hash
def __lt__(self, other):
return np.argmax(np.less(self.data, other.data)) < np.argmax(np.less(other.data, self.data))
for data_class in (x.data for x in sorted(set(RowView(r) for r in data_xy[1]))):
Немного более быстрое решение, которое лучше демонстрирует пользовательское хеширование, — это расширение np.ndarray
с помощью пользовательского хэша. Затем вы можете использовать объекты просмотра напрямую, не копируя данные вперед и назад:
class HashableArray(np.ndarray):
def __hash__(self):
return hash(tuple(self))
def __lt__(self, other):
return np.argmax(np.less(self, other)) < np.argmax(np.less(other, self))
for data_class in sorted(set(x.view(HashableArray) for x in data_xy[1]))):