【问题标题】:Optimize Dict values(List) Multiplication优化字典值(列表)乘法
【发布时间】:2018-11-04 00:41:04
【问题描述】:

我有两个字典元素如下:初始(25 个键值对)结果(100 个键值对)

Initial: {0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0],....... 24: [0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0]}

Results: {'0': [360, 0, 0, 0, 0, 1, 0, 0, 3, 3, 0, 0, 15, 0, 14, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 0, 3, 3, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 2, 0, 1, 0, 0, 3, 1, 0, 1, 0, 0, 0, 1, 2, 0, 2, 0, 0, 0, 137, 21, 78, 65, 241, 31, 30, 88, 152, 3, 13, 67, 31, 145, 132, 37, 1, 107, 120, 171, 39, 35, 31, 8, 24, 0, 0, 0, 0, 0],......'100': [183, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 2, 8, 1, 3, 1, 0, 3, 3, 0, 1, 1, 3, 2, 1, 1, 4, 0, 2, 1, 3, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 76, 10, 25, 33, 121, 14, 6, 40, 62, 2, 5, 34, 23, 66, 61, 28, 1, 56, 46, 69, 23, 10, 14, 1, 13, 1, 0, 0, 0, 0]}

在每次迭代中,我将 Results 字典的每个值与 Initial 字典中的一个值相乘,并调用一个函数来传递该产品,该产品将获取另一个值,然后我通过整个 Initial 字典值对其进行迭代。我正在使用以下代码执行此操作:

for z in Initial.keys():
        for i in sorted(Results.keys()):
            result = {i :[x*y for x, y in zip(Initial[z], Results[i])]}  

一个完整的循环大约需要 1 分钟,我需要执行至少 5000 个循环才能观察最终结果。任何有关提高代码性能/优化的建议将不胜感激。

【问题讨论】:

    标签: python dictionary optimization iteration matrix-multiplication


    【解决方案1】:

    您的值是列表,因此您必须一次乘以一个元素。您可以先将值(列表)转换为数组,然后使用向量化乘法,从而消除使用列表理解和元素乘法,如下所示

    # Converting the values to arrays once for all
    Initial = {k:np.array(v) for k,v in Initial.items()}
    Results = {k:np.array(v) for k,v in Results.items()}
    
    # Now just using vectorized multipliction
    for z in Initial.keys():
        for i in sorted(Results.keys()):
            result = {i :Initial[z] * Results[i]}  
    

    由于您没有提供完整的数据,我尝试了您的代码进行了大约 100 万次迭代,发现矢量化代码要快得多。在您的原始数据上尝试一下,看看您是否可以加快速度(应该这样做)。


    比较时间的测试用例

    您的列表理解版本耗时 1 分 6 秒

    for ii in range(500000):
        for z in Initial.keys():
            for i in sorted(Results.keys()):
                result = {i :[x*y for x, y in zip(Initial[z], Results[i])]}  
    

    以下矢量化操作耗时 2.9 秒

    for ii in range(500000):
        for z in Initial.keys():
            for i in sorted(Results.keys()):
                result = {i :Initial[z] * Results[i]}  
    

    【讨论】:

    • 我确实看到了改进,但我现在遇到了另一个问题。我正在使用 'i' 和 result[i] 传递给我的下一个函数,但我无法更改它们的生成格式。列表 result[i] 中的每个元素都包含在 array() 中,“i”列表中的每个元素都包含在 array() 中,并包含 dtype='|s10' 作为额外元素。关于如何解决这个问题的任何意见?
    • 您可以尝试使用 list(element) 将元素从数组转换回列表
    • 我们如何用 '.' 分割 np.array() 中的每个值?
    • 请在评论中添加一些您想要拆分的示例数组。我会在早上回复。
    • 好吧,假设x = np.array([[253, 0, 2, 0, 0, 0], [150, 0, 0, 0, 0, 0]] ),您可以使用x = [list(map(float, i)) for i in x]进行转换
    猜你喜欢
    • 2013-10-21
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 1970-01-01
    • 2018-11-23
    • 2020-02-05
    • 2015-12-25
    相关资源
    最近更新 更多