У меня есть два двоичных списка, которые я пытаюсь сравнить. Чтобы сравнить, я суммирую, где каждое соответствующее значение равно и преобразовать это в процент:
import numpy as np
l1 = [1,0,1]
l2 = [1,1,1]
print(np.dot(l1 , l2) / len(l1) * 100)
Печатает 66.666
Таким образом, в этом случае l1 и l2 составляют 61,666 с точки зрения близости. Поскольку каждый список менее похож, значение близости уменьшается.
Например, используя значения:
l1 = [1,0,1]
l2 = [0,1,0]
Возвращает 0.0
Как построить l1
и l2
, которые описывают отношения между l1
и l2
? Есть ли имя для использования этого метода для измерения сходства между двоичными значениями?
Используя скаттер:
import matplotlib.pyplot as plt
plt.scatter( 'x', 'y', data=pd.DataFrame({'x': l1, 'y': l2 }))
Производит:
Но это не имеет смысла?
Обновить :
«если обе записи равны 0, это не повлияет на ваше« сходство »
Используя обновленный код ниже для вычисления подобия, эта обновленная мера сходства включает в себя соответствующие 0 значений при вычислении итоговой оценки.
import numpy as np
l1 = [0,0,0]
l2 = [0,1,0]
print(len([a for a in np.isclose(l1 , l2) if(a)]) / len(l1) * 100)
Который возвращает:
66.66666666666666
В качестве альтернативы, использование приведенного ниже кода с мерой normalized_mutual_info_score
возвращает 1,0 для списков, которые являются одинаковыми или разными, поэтому normalized_mutual_info_score
не является подходящей мерой сходства?
from sklearn.metrics.cluster import normalized_mutual_info_score
l1 = [1,0,1]
l2 = [0,1,0]
print(normalized_mutual_info_score(l1 , l2))
l1 = [0,0,0]
l2 = [0,0,0]
print(normalized_mutual_info_score(l1 , l2))
Печать:
1.0
1.0
2 ответа
Нет, сюжет не имеет смысла. То, что вы делаете, по сути является внутренним продуктом между векторами. Согласно этой метрике l1
и l2
должны быть векторами в трехмерном (в данном случае) пространстве, и это измеряет, обращены ли они к одному и тому же направлению и имеют одинаковую длину. Выводом является скалярное значение , поэтому нечего строить.
Если вы хотите показать индивидуальный вклад каждого компонента, вы могли бы сделать что-то вроде
contributions = [a==b for a, b in zip(l1, l2)]
plt.plot(list(range(len(contributions)), contributions)
Но я все еще не уверен, что это имеет смысл.
import numpy as np
import matplotlib.pyplot as plt
def unpackbits(a, n):
''' Unpacks an integer `a` to n-length binary list. '''
return [a >> i & 1 for i in range(n-1,-1,-1)]
def similarity(a, b, n):
''' Similarity between n-length binary lists obtained from unpacking
the integers a and b. '''
a_unpacked = unpackbits(a, n)
b_unpacked = unpackbits(b, n)
return np.sum(np.isclose(a_unpacked, b_unpacked))/n
# Plot
n = 3
x = np.arange(2**n+1)
y = np.arange(2**n+1)
xx, yy = np.meshgrid(x, x)
z = np.vectorize(similarity)(yy[:-1,:-1], xx[:-1,:-1], n)
labels = [unpackbits(i, n) for i in x]
cmap = plt.cm.get_cmap('binary', n+1)
fig, ax = plt.subplots()
pc = ax.pcolor(x, y, z, cmap=cmap, edgecolor='k', vmin = 0, vmax=1)
ax.set_xticks(x + 0.5)
ax.set_yticks(y + 0.5)
ax.set_xlim(0, 2**n)
ax.set_ylim(0, 2**n)
ax.set_xticklabels(labels, rotation=45)
ax.set_yticklabels(labels)
cbar = fig.colorbar(pc, ax=ax, ticks=[i/n for i in range(n+1)])
cbar.ax.set_ylabel('similarity', fontsize=14)
ax.set_aspect('equal', adjustable='box')
plt.tight_layout()
plt.show()
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.