列表的快速 Python 外部差异
Fast Python outer difference of list
我想计算 Python 等长列表中每个元素之间的 差异,并将其放入 Numpy 数组中。
当我说两个列表之间的差异时,我指的是两个列表之间相应元素之间的差异数。
这是一个使用列表理解的 difference 函数示例:
def list_difference(list_a, list_b):
len_lists = len(list_a)
assert len_lists == len(list_b), "Lists must be the same length."
return sum([list_a[i] != list_b[i] for i in range(len_lists)])
然后我对列表列表中的每一对调用 difference 函数并将其放入一个 numpy 数组中。
你可以称它为列表列表的外差,就像外积一样。
我在天真的循环中这样做:
import numpy as np
import time
sequences = [
["A", "A", "A", "B", "C"],
["B", "A", "B", "A", "B"],
["B", "A", "C", "C", "B"],
["B", "A", "C", "C", "C"],
]
start = time.time()
n_seq = len(sequences)
dists = np.zeros((n_seq, n_seq))
for row in range(n_seq):
for col in range(n_seq):
if row >= col:
continue
dists[row, col] = list_difference(sequences[row], sequences[col])
dists += dists.T
print(dists)
print(f"Time: {time.time() - start} seconds")
结果是
[[0. 4. 4. 3.]
[4. 0. 2. 3.]
[4. 2. 0. 1.]
[3. 3. 1. 0.]]
Time: 0.0003669261932373047 seconds
这个例子在我的电脑上已经足够快了(上面三个中的最佳时间)。
然而,运行 这在 64 个列表(序列)上每个长度为 1008 需要 293.572190 秒,这是一段时间。
有更快的方法吗?
尝试次数:
1 我尝试将内部 for 循环放入列表理解中:
dists = np.zeros((n_seq, n_seq))
for row in range(n_seq):
dist_row = [list_difference(sequences[row], sequences[col]) for col in range(n_seq) if row >= col]
dists[row, n_seq-row-1:] = dist_row
dists += dists.T
但它实际上使它变慢了,需要 0.000523 秒(快 0.70 倍)。
在我更大的数据集上,它需要 319.2168769 秒(快 0.92 倍)。
2 我想知道在本机中执行 for 循环 Python 然后在最后复制到 Numpy 是否会有帮助。
_dists = [ [0]*n_seq for i in range(n_seq)]
for row in range(n_seq):
for col in range(n_seq):
if col <= row:
continue
_dists[row][col] = list_difference(sequences[row], sequences[col])
dists = np.array(_dists)
dists += dists.T
这需要 0.0001862 秒,大约是原始代码的两倍。
在我较大的数据集上,加速并不显着,为 229.945951 秒(快 1.28 倍),但仍然有所提升。
3 只是想到可能有一种方法可以直接在 Numpy 中执行两个外部 for 循环。
一种更简洁、更简单、更快速的方法是使用 numpy 广播:
sequences = np.array(sequences)
dists = (sequences[:, None] != sequences).sum(axis=2)
输出:
>>> dists
array([[0, 4, 4, 3],
[4, 0, 2, 3],
[4, 2, 0, 1],
[3, 3, 1, 0]])
我想计算 Python 等长列表中每个元素之间的 差异,并将其放入 Numpy 数组中。
当我说两个列表之间的差异时,我指的是两个列表之间相应元素之间的差异数。 这是一个使用列表理解的 difference 函数示例:
def list_difference(list_a, list_b):
len_lists = len(list_a)
assert len_lists == len(list_b), "Lists must be the same length."
return sum([list_a[i] != list_b[i] for i in range(len_lists)])
然后我对列表列表中的每一对调用 difference 函数并将其放入一个 numpy 数组中。 你可以称它为列表列表的外差,就像外积一样。 我在天真的循环中这样做:
import numpy as np
import time
sequences = [
["A", "A", "A", "B", "C"],
["B", "A", "B", "A", "B"],
["B", "A", "C", "C", "B"],
["B", "A", "C", "C", "C"],
]
start = time.time()
n_seq = len(sequences)
dists = np.zeros((n_seq, n_seq))
for row in range(n_seq):
for col in range(n_seq):
if row >= col:
continue
dists[row, col] = list_difference(sequences[row], sequences[col])
dists += dists.T
print(dists)
print(f"Time: {time.time() - start} seconds")
结果是
[[0. 4. 4. 3.]
[4. 0. 2. 3.]
[4. 2. 0. 1.]
[3. 3. 1. 0.]]
Time: 0.0003669261932373047 seconds
这个例子在我的电脑上已经足够快了(上面三个中的最佳时间)。 然而,运行 这在 64 个列表(序列)上每个长度为 1008 需要 293.572190 秒,这是一段时间。 有更快的方法吗?
尝试次数:
1 我尝试将内部 for 循环放入列表理解中:
dists = np.zeros((n_seq, n_seq))
for row in range(n_seq):
dist_row = [list_difference(sequences[row], sequences[col]) for col in range(n_seq) if row >= col]
dists[row, n_seq-row-1:] = dist_row
dists += dists.T
但它实际上使它变慢了,需要 0.000523 秒(快 0.70 倍)。 在我更大的数据集上,它需要 319.2168769 秒(快 0.92 倍)。
2 我想知道在本机中执行 for 循环 Python 然后在最后复制到 Numpy 是否会有帮助。
_dists = [ [0]*n_seq for i in range(n_seq)]
for row in range(n_seq):
for col in range(n_seq):
if col <= row:
continue
_dists[row][col] = list_difference(sequences[row], sequences[col])
dists = np.array(_dists)
dists += dists.T
这需要 0.0001862 秒,大约是原始代码的两倍。 在我较大的数据集上,加速并不显着,为 229.945951 秒(快 1.28 倍),但仍然有所提升。
3 只是想到可能有一种方法可以直接在 Numpy 中执行两个外部 for 循环。
一种更简洁、更简单、更快速的方法是使用 numpy 广播:
sequences = np.array(sequences)
dists = (sequences[:, None] != sequences).sum(axis=2)
输出:
>>> dists
array([[0, 4, 4, 3],
[4, 0, 2, 3],
[4, 2, 0, 1],
[3, 3, 1, 0]])