汉明距离 python 改进
hamming distance python improvement
我正在尝试写汉明距离。
作为输入,我有两个矩阵 M1 和 M2,一个是 40x20,第二个是 50x20;它们包含 True/False。我需要计算每行之间的距离,因此 M1[0] 与 M2[0] 的距离,M1[0] 与 M2[1] 的距离 ... M1[39] 与 M2[49] 的距离。产生 40x50 结果矩阵。我的第一次尝试当然是像这样循环:
for x_i in range(X.shape[0]):
for x_train_j in range(X_train.shape[0]):
distance_results[x_i, x_train_j] = sum(np.logical_xor(x_array[x_i, :], x_train_array[x_train_j, :]))
它是正确的,但是,它对我的数据来说太慢了。我对乘法 M1.dot(M2.T)
有一些想法,它给出了正确的矩阵形状并一步求和,但是当需要乘法和求和 xor 时,所以:
1 * 1 = 1
(需要 0 - 不好)
1 * 0 = 0
(需要 1 - 不好)
0 * 1 = 0
(需要 1 - 不好)
0 * 0 = 0
(需要 0 - 即可)
你知道我怎样才能得到想要的结果吗?我想我想念一些数学来正确快速地完成它。
提前致谢。
M1.dot(M2.T)
在某种程度上可以被视为布尔逻辑的 AND
。对于二进制逻辑 A xor B
等价于 (A and not B) or (not A and B)
所以你可以做一件事 --
M1.dot(M2.T):
1 * 1 = 1
1 * 0 = 0
0 * 1 = 0
0 * 0 = 0
(not M1).dot(M2.T):
0 * 1 = 0
0 * 0 = 0
1 * 1 = 1
1 * 0 = 0
M1.dot(not M2.T):
1 * 0 = 0
1 * 1 = 1
0 * 0 = 0
0 * 1 = 0
(not M1).dot(M2.T) or M1.dot(not M2.T):
0 * 1 || 1 * 0 = 0
0 * 0 || 1 * 1 = 1
1 * 1 || 0 * 0 = 1
1 * 0 || 0 * 1 = 0
要对其进行编码,您需要注意在点之前抛出逻辑,以便计算总和。如果你点在 2 个逻辑数组上,你将不会得到你想要的结果。我只使用 -1 作为我的非运算符 ( True - 1 = 0, False - 1 = -1)
。此外,这里的 'or' 实际上是一个总和,因为您正在考虑多个布尔值。最后,您的距离为负值,很容易用绝对值修复。
_A = [[ True, True, False],
[ True, False, True]]
_B = [[ True, False, False],
[ False, False, False],
[ True, True, True ]]
预期输出:
[[ 1, 2, 1],
[ 1, 2, 1]]
A = numpy( _A, dtype=bool)
B = numpy( _B, dtype=bool)
numpy.absolute(numpy.dot(A,B.T-1) + numpy.dot(A-1, B.T))
>>>array([[1, 2, 1],
[1, 2, 1]])
我正在尝试写汉明距离。
作为输入,我有两个矩阵 M1 和 M2,一个是 40x20,第二个是 50x20;它们包含 True/False。我需要计算每行之间的距离,因此 M1[0] 与 M2[0] 的距离,M1[0] 与 M2[1] 的距离 ... M1[39] 与 M2[49] 的距离。产生 40x50 结果矩阵。我的第一次尝试当然是像这样循环:
for x_i in range(X.shape[0]):
for x_train_j in range(X_train.shape[0]):
distance_results[x_i, x_train_j] = sum(np.logical_xor(x_array[x_i, :], x_train_array[x_train_j, :]))
它是正确的,但是,它对我的数据来说太慢了。我对乘法 M1.dot(M2.T)
有一些想法,它给出了正确的矩阵形状并一步求和,但是当需要乘法和求和 xor 时,所以:
1 * 1 = 1
(需要 0 - 不好)
1 * 0 = 0
(需要 1 - 不好)
0 * 1 = 0
(需要 1 - 不好)
0 * 0 = 0
(需要 0 - 即可)
你知道我怎样才能得到想要的结果吗?我想我想念一些数学来正确快速地完成它。
提前致谢。
M1.dot(M2.T)
在某种程度上可以被视为布尔逻辑的 AND
。对于二进制逻辑 A xor B
等价于 (A and not B) or (not A and B)
所以你可以做一件事 --
M1.dot(M2.T):
1 * 1 = 1
1 * 0 = 0
0 * 1 = 0
0 * 0 = 0
(not M1).dot(M2.T):
0 * 1 = 0
0 * 0 = 0
1 * 1 = 1
1 * 0 = 0
M1.dot(not M2.T):
1 * 0 = 0
1 * 1 = 1
0 * 0 = 0
0 * 1 = 0
(not M1).dot(M2.T) or M1.dot(not M2.T):
0 * 1 || 1 * 0 = 0
0 * 0 || 1 * 1 = 1
1 * 1 || 0 * 0 = 1
1 * 0 || 0 * 1 = 0
要对其进行编码,您需要注意在点之前抛出逻辑,以便计算总和。如果你点在 2 个逻辑数组上,你将不会得到你想要的结果。我只使用 -1 作为我的非运算符 ( True - 1 = 0, False - 1 = -1)
。此外,这里的 'or' 实际上是一个总和,因为您正在考虑多个布尔值。最后,您的距离为负值,很容易用绝对值修复。
_A = [[ True, True, False],
[ True, False, True]]
_B = [[ True, False, False],
[ False, False, False],
[ True, True, True ]]
预期输出: [[ 1, 2, 1], [ 1, 2, 1]]
A = numpy( _A, dtype=bool)
B = numpy( _B, dtype=bool)
numpy.absolute(numpy.dot(A,B.T-1) + numpy.dot(A-1, B.T))
>>>array([[1, 2, 1],
[1, 2, 1]])