我有一个数据框df
包含二十万件物品的信息。现在我想测量它们的成对相似性,并选择最高n
对。这意味着,我应该计算近数十亿计算。鉴于巨大的计算成本,我选择通过多处理来运行它。这是我到目前为止编写的代码:
user_list = (list(range(1, 200001))
def gen_pair():
for u1 in reversed(user_list):
for u2 in reversed(list(range(1, u1))):
yield (u1, u2)
def cal_sim(u_pair):
u1, u2 = u_pair
# do sth quite complex...
sim = sim_f(df[u1], df[u2])
if sim < 0.5:
return None
else:
return (u1, u2, sim)
with multiprocessing.Pool(processes=3) as pool:
vals = pool.map(cal_sim, gen_pair())
for v in vals:
if v is not None:
with open('result.txt', 'a') as f:
f.write('{0}\t{1}\t{2}\n'.format(v[0], v[1], v[2]))
当我刚拿到前1000名用户时,它的效果非常好。但是,当我把它们全部拿走时,它在result.txt
中已经死了,没有一个单词。但是如果我添加进程的数量,它也会死掉。我想知道是什么原因,我该如何解决?提前谢谢。
编辑:
以下是我的sim_f
代码:
def sim_f(t1, t2):
def intersec_f(l1, l2):
return set(l1)&set(l2)
def union_f(l1, l2):
return set(l1)|set(l2)
a_arr1, a_arr2 = t1[0], t1[1]
b_arr1, b_arr2 = t2[0], t2[1]
sim = float(len(union_f(intersec_f(a_arr1, a_arr2), intersec_f(b_arr1, b_arr2))))\
/ float(len(union_f(union_f(a_arr1, a_arr2), union_f(b_arr1, b_arr2))))
return sim
答案 0 :(得分:2)
没什么可继续的,但请尝试:
vals = pool.imap(cal_sim, gen_pair())
^
相反:请注意我将“map”更改为“imap”。如上所述,map()
阻塞,直到整个计算完成,因此在完成所有工作之前,您永远不会进入for
循环。 imap
会立即“返回”。
如果您不关心交付结果的顺序,请改用imap_unordered()
。
关于评论中提出的问题:
with open('result.txt', 'w') as f:
for v in vals:
if v is not None:
f.write('{0}\t{1}\t{2}\n'.format(v[0], v[1], v[2]))
是打开文件一次的明显方法。但是如果它对你有所帮助我会感到惊讶 - 迄今为止的所有证据都表明cal_sim()
只是昂贵的。
正在进行大量冗余工作:
def sim_f(t1, t2):
def intersec_f(l1, l2):
return set(l1)&set(l2)
def union_f(l1, l2):
return set(l1)|set(l2)
a_arr1, a_arr2 = t1[0], t1[1]
b_arr1, b_arr2 = t2[0], t2[1]
sim = float(len(union_f(intersec_f(a_arr1, a_arr2), intersec_f(b_arr1, b_arr2))))\
/ float(len(union_f(union_f(a_arr1, a_arr2), union_f(b_arr1, b_arr2))))
return sim
完全未经测试,这是显而易见的;-)重写:
def sim_f(t1, t2):
a1, a2 = set(t1[0]), set(t1[1])
b1, b2 = set(t2[0]), set(t2[1])
sim = float(len((a1 & a2) | (b1 & b2))) \
/ len((a1 | a2) | (b1 | b2))
return sim
这更快,因为:
float()
的一次不必要的调用(或者,在Python 3中,剩余的float()
调用也可以被删除)。