ValueError: Значение истинности массива с более чем одним элементом неоднозначно. Используйте a.any() или a.all(): алгоритм производительности Silhouette
Я реализовал алгоритм kmeans в python и пытался вычислить силуэтную производительность кластера для различных значений k. Вот несколько переменных для небольшой части набора данных.
def avgdist(pt, clust):
dists = []
for elem in clust:
dists.append(np.linalg.norm(pt-elem))
return np.mean(dists)
def silhouette(data, clusts):
s = []
print("data-")
print(data)
for i in range(len(clusts)):
for j in range(len(clusts[i])):
clusts[i][j] = clusts[i][j].tolist()
print("Clusters")
print(clusts)
for elem in data:
a = []
b = []
print(elem)
for clust in clusts:
print(clust)
if elem in clust: #Error in this line
b.append(avgdist(elem, clust))
else:
a.append(avgdist(elem, clust))
s.append((min(b)-min(a)/(max(min(b), min(a)))))
return np.mean(s)
Выход на терминале получается следующим образом:
data-
[[ 0. 0. 5.]
[ 0. 0. 0.]
[ 0. 0. 0.]
[ 0. 0. 7.]
[ 0. 0. 0.]
[ 0. 0. 12.]
[ 0. 0. 0.]
[ 0. 0. 7.]
[ 0. 0. 9.]
[ 0. 0. 11.]]
Clusters
[[array([ 0., 0., 5.]), array([ 0., 0., 0.]), array([ 0., 0., 0.]), array([ 0., 0., 0.]), array([ 0., 0., 0.])], [array([ 0., 0., 7.]), array([ 0., 0., 12.]), array([ 0., 0., 7.]), array([ 0., 0., 9.]), array([ 0., 0., 11.])]]
[ 0. 0. 5.]
[[0.0, 0.0, 5.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]
Это получается вместе с ошибкой в закомментированной строке
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Пожалуйста, помогите, поскольку я не уверен, что означает эта ошибка в моем контексте. Подобные вопросы дали мне некоторое представление о природе ошибки, но я считаю, что здесь это не применимо.
Изменить - я решил этот вопрос, изменив строку ошибки как
.....
if elem.tolist() in clust: #Error in this line
.....
2 ответа
Ваша проблема в том, что вы пытаетесь оценить в рассматриваемой строке, содержит ли список списков (clust) другой список (elem), что приводит к созданию списка / массива значений Truth/False, поскольку оценка выполняется поэлементно: линия будет оцениваться в соответствии с
if [True, False, ...]: #<- error here
code
который выдаст ошибку
вместо хранения списков списков преобразуйте / упакуйте ваши данные и элементы кластера в списки кортежей, и эта оценка будет работать.
Скажи у тебя
import numpy as np
data = np.array([[ 0., 0., 5.],
[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 7.],
[ 0., 0., 0.],
[ 0., 0., 12.],
[ 0., 0., 0.],
[ 0., 0., 7.],
[ 0., 0., 9.],
[ 0., 0., 11.]])
clusts = [[np.array([ 0., 0., 5.]), np.array([ 0., 0., 0.]), np.array([ 0., 0., 0.]), np.array([ 0., 0., 0.]), np.array([ 0., 0., 0.])], [np.array([ 0., 0., 7.]), np.array([ 0., 0., 12.]), np.array([ 0., 0., 7.]), np.array([ 0., 0., 9.]), np.array([ 0., 0., 11.])]]
Как насчет замены
[...]
if elem in clust: #Error in this line
[...]
от
[...]
if any([compa.all() for compa in elem == clust]):
[...]
который проверяет наличие одного массива в списке таких массивов.
Протестировано под Python3.6
В итоге
def silhouette(data, clusts):
s = []
print("data-")
print(data)
for i in range(len(clusts)):
for j in range(len(clusts[i])):
clusts[i][j] = clusts[i][j].tolist()
print("Clusters")
print(clusts)
for elem in data:
a = []
b = []
print(elem)
for clust in clusts:
print(clust)
condition = any([compa.all() for compa in elem == clust])
print(condition)
if condition: #No error anymore in this line
b.append(avgdist(elem, clust))
else:
a.append(avgdist(elem, clust))
s.append((min(b)-min(a)/(max(min(b), min(a)))))
return np.mean(s)
распечатает (сообщается только одно сравнение)
[...]
[ 0. 0. 5.]
[[0.0, 0.0, 5.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]
True
[[0.0, 0.0, 7.0], [0.0, 0.0, 12.0], [0.0, 0.0, 7.0], [0.0, 0.0, 9.0], [0.0, 0.0, 11.0]]
False