Python矩阵比较

时间:2016-10-14 12:42:13

标签: python performance numpy matrix comparison

我有大数据:

{'a_1':0b110000,
 'a_2':0b001100,
 'a_3':0b000011,
 'b_1':0b100100,
 'b_2':0b000001,
 'c_1':0b100000,}

等等...数据的结构可以重新组织,更多的是展示,我想要实现的目标。 'a'的行将永远不会与其子行重叠。 在大多数匹配值方面,获得两个(ab,ac)或三个(abc)或更多行的最佳组合将是一种高效的方法? 希望,问题很明显,很难描述:/ 也许是numpy的一些矩阵运算?

更多信息: 两种可能的组合是ab,ac,bc。 ab会针对b(b_1,b_2)的行检查a(a_1,a_2,a_3)的行。 a_1& b_1表示0b110000& 0b100100并给出一个结果。 a_1& b_2表示0b110000& 0b000001并且不会给出任何结果。这将是循环解决方案的描述,但它非常慢,尤其是大约8的组合(未被示例数据覆盖)。

可能是一个更清晰的数据结构:

{'a': [0b110000,
       0b001100,
       0b000011],
 'b': [0b100100,
       0b000001],
 'c': [0b100000]}

让我说明一下,到目前为止我是如何进行这些计算的。数据结构有点不同,因为我试图以“我认为”更好的结构来启动这个问题......

data = {'a':[1,1,2,2,3,3],
        'b':[4,5,5,5,4,5],
        'c':[6,7,7,7,6,7]}    

combine_count = 3
for config in combinations(['a','b','c'],combine_count):
    ret = {}
    for index,combined in enumerate(zip(*tuple(data.get(k) for k in config))):
        ret.setdefault(combined, []).append(index)

for k,v in ret.items():
    score = len(v)
    if score >= 2:
        print(k,score)

我的问题是,特别是与更大的combine_count相结合的构建过程需要花费很多时间。 数据当然要大得多。它有大约231个键,每个列表的长度约为60000。此外,RAM消耗太高。

1 个答案:

答案 0 :(得分:1)

不确定您的三重评估*但您可以修改此功能以执行您想要的操作。我假设你将遍历a,b,c等的组合。

#!/usr/bin/python
import numpy as np
import random
import time

A = [np.random.randint(0, 2**15, random.randint(1, 5)) + 2**16 for i in range(231)]
best_score = 0
tm = time.time()
for i, a in enumerate(A):
  for j, b in enumerate(A[1:]):
    for k, c in enumerate(A[2:]):
      an, bn, cn = len(a), len(b), len(c) #some shortcuts

      a_block = np.broadcast_to(a.reshape(an, 1, 1), (an, bn, cn))
      b_block = np.broadcast_to(b.reshape(1, bn, 1), (an, bn, cn))
      c_block = np.broadcast_to(c.reshape(1, 1, cn), (an, bn, cn))

      all_and = c_block & b_block & a_block

      all_score = ((all_and & 1) + 
                   ((all_and >> 1) & 1) +
                   ((all_and >> 2) & 1) +
                   ((all_and >> 3) & 1) +
                   ((all_and >> 4) & 1) +
                   ((all_and >> 5) & 1))
      ix = np.unravel_index(np.argmax(all_score), (an, bn, cn))
      if all_score[ix] > best_score:
        print(i,j,k, ix, all_score[ix], a_block[ix], b_block[ix], c_block[ix])
        best_score = all_score[ix]
        best_abc = (i, j, k)
        best_ix = ix[:]

print(time.time() - tm)
print(best_score)
print(best_abc)
print(best_ix)
''' gives
0 0 0 (0, 2, 0) 2 95038 76894 78667
0 0 1 (0, 3, 1) 3 95038 70262 96242
0 0 2 (0, 2, 0) 4 95038 76894 96255
0 3 2 (0, 0, 0) 5 95038 96255 96255
4 3 2 (0, 0, 0) 6 96255 96255 96255
871.6093053817749
6
(4, 3, 2)
(0, 0, 0)
'''

编辑*我认为这段代码确实:找到a1& b1& c1,a2& b1& c1,a3& b1& c1,a1& b2& c1等之间可能不同的最大位置(和值)来自a1& b1& c1 | a2& b1& c1 | a3& b1& c1 | A1&安培; B2&安培; C1

EDIT2更明确地显示迭代伪数据集的过程。 a,b,c是长度为1到5的数组,但是numpy randint不能生成60000位长的随机数,我也没有尝试确保所有数字都是唯一的(这很容易做到)这台功能不太强大的笔记本电脑大约需要15米,因此可以为您提供比较的起点。

加速这个过程的一种方法可能是将比较仅限于两个,即a,b开始并保留一个高分的列表,然后通过这些组合中的每一个并且对抗所有其他条目。列表选择最高得分的三种方式和。