Сравнение матрицы Python

У меня есть большие данные вроде:

{'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 проверит строки a (a_1, a_2, a_3) на строки b (b_1, b_2) друг друга. 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)

моя проблема заключается в том, что в особенности процесс построения в сочетании с более крупным comb_count занимает много времени. данные, конечно, намного больше. Он имеет около 231 ключ со списками каждая длиной ~ 60000. Кроме того, потребление ОЗУ слишком велико.

python,performance,numpy,matrix,comparison,

-1

Ответов: 1


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)
'''

EDIT * Я думаю, что этот код: найти местоположение (и значение) максимум между 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, чтобы начать и сохранить список высоких показателей, затем пройти через каждую из этих комбинаций против всех других записей в списке, чтобы выбрать самый высокий забив три пути и.

питон, производительность, NumPy, матрица, сравнение,
Похожие вопросы