我有成对的列表,每对大小相等。我想通过从每个索引中选择一个随机元素来“合并”每个对象,但是我当前的实现非常慢-在进行多处理时 even 。 (FWIW,我的代码确实需要可线程化的。)
def rand_merge(l1, l2):
newl = []
for i in range(len(l1)):
q = random.choice([l1, l2])
newl.append(q[i])
return newl
非常基本,但是要在20k大小约为5-25的列表上运行,则要花很长时间-我认为它是随机的。但是我还尝试了其他版本的random,例如创建一个字符串0和1来引用,这是不行的。
编辑: 更清晰:这是一种遗传算法,旨在通过匹配语料库来编写句子。有问题的列表是按单词拆分的句子。遗传算法将获胜的健身“父母”“合并”到孩子中,每个孩子都是两个父句的“基因”的合并。 这意味着“列表”确实需要匹配,并且不能从更大的列表列表中提取(我不认为)。
这里有一些代码...
from multiprocessing import Pool as ThreadPool
import random
def offspring(parents):
child = []
p1 = parents[0].split(' ')
p2 = parents[1].split(' ')
for i in range(min(len(p1), len(p2))):
q = random.choice([p1, p2])
child.append(q[i])
child = ' '.join([g for g in child]).strip()
return child
def nextgen(l): #l is two lists of previous generation and grammar seed
oldgen = l[0][:pop] # Population's worth of previous generation
gramsent = l[1] # this is the grammar seed
newgen = []
newgen.append(tuple([oldgen[0][0], oldgen[0][0]])) # Keep the winner!
for i in range(len(oldgen) - len(oldgen)//4):
ind1 = oldgen[0][0] # paired off against the winner - for larger pools, this is a random.sample/"tournament"
ind2 = oldgen[i][0]
newgen.append(tuple([ind1, ind2]))
pool = ThreadPool(processes=8)
newgen = pool.map(offspring, newgen)
pool.close()
pool.join()
人口和世代可以一起大量进入,并且每个句子都贯穿其中。自从最初发布问题以来,我就担心每一代人都需要花费很长时间才能解决问题,所以我发现(对于我来说,是头上的挠头)长的处理时间实际上(几乎)与“人口”规模或人数无关列表。变异每一代大约需要15秒。我将人口从50增加到50000,并将世代从15秒增加到17左右。因此,速度缓慢显然隐藏在其他地方。
答案 0 :(得分:1)
尝试一次合并所有20,000个列表,而不是一次合并两个。
from itertools import zip_longest
from functools import partial
import random
lists = [l1, l2, ...]
idxvals = map(partial(filter, None), itertools.zip_longest(*lists))
newl = [random.choice([*i]) for i in idxvals]
由于要在每个索引中选择一个随机元素,因此一次选择所有20k列表而不是一次选择2个是有意义的。
>>> lists = [[1, 2, 3], [10], [20, 30, 40, 5]]
zip_longest
将压缩到最长列表,并用None
填充缺少的值。
>>> list(itertools.zip_longest(*lists))
[(1, 10, 20), (2, None, 30), (3, None, 40), (None, None, 5)]
这些“无”将需要在选择步骤之前过滤掉。 filter
将对此有所帮助。
>>> f = partial(filter, None)
>>> list(map(list, map(f, itertools.zip_longest(*lists))))
[[1, 10, 20], [2, 30], [3, 40], [5]]
应该清楚我要做什么。输出的ith索引包含l[i]
中每个l
出现在lists
上的那些元素。
现在,遍历idxvals
并选择:
>>> idxvals = map(f, itertools.zip_longest(*lists))
>>> [random.choice([*i]) for i in idxvals]
[10, 30, 3, 5]