Pythoni c Вложено для - циклы в Python - PullRequest
2 голосов
/ 24 февраля 2020

Я работаю над этим кодом, где я вложил в циклы. a_list и b_list - это список кортежей, где каждый кортеж состоит из двух тензоров [(tens1, tens2), ...]. Я пытаюсь вычислить сходство каждого tens1 в a_list с каждым tens1 в b_list. Ниже приведен код, который у меня есть. И вложенное l oop кажется узким местом. Есть ли лучший способ (pythoni c), чтобы я мог переписать циклы?

a2b= defaultdict(dict)
b2a= defaultdict(dict)
ab_sim = []

for a, vec_a in a_list:
    for b, vec_b in b_list:
        # Ignore combination if the first element in both a and b are same
        if a[0] == b[0]:
            continue
        # Calculate cosine similarity of combination
        sim = self.calculate_similarity(vec_a, vec_b )
        a2b[a][b] = sim
        b2a[b][a] = sim
        ab_sim.append(sim)

calculate_similarity - это просто метод вычисления косинусного сходства. a_list и b_list могут быть любого размера. У меня есть b2a и a2b, потому что они нужны мне для других вычислений.

Ответы [ 3 ]

2 голосов
/ 24 февраля 2020

Вы можете использовать словарь понимания:

a2b = {a: {b: self.calculate_similarity(vec_a, vec_b )
       for (b, vec_b) in b_list if a[0] != b[0]} for (a, vec_a) in a_list}
0 голосов
/ 24 февраля 2020

Я думаю, что наиболее естественным способом хранения этой информации является Матрица

from random import random
import numpy as np
n=3
a=[ (n*np.random.rand(n)//1, n*np.random.rand(n)//1) for _ in range(3) ]
b=[ (n*np.random.rand(n)//1, n*np.random.rand(n)//1) for _ in range(3) ]


similarity = lambda x,y: np.dot(x, y)/(np.linalg.norm(x)*np.linalg.norm(y))

sim_matrix = [[ similarity(x,y) if x[0]!=y[0] else np.inf for y,_ in b  ] for x,_ in a]

print(*sim_matrix, sep="\n")

Полный код. enter image description here

0 голосов
/ 24 февраля 2020

Вы также можете использовать product из itertools:

from itertools import product
result = {(a,b): self.calculate_similarity(vec_a, vec_b) 
          if a[0] != b[0] else 1 
          for ((a, vec_a) ,(b, vec_b)) in product(a_list, b_list)}

Обратите внимание, что вы получаете один словарь с индексом кортежей вместо двух избыточных словарей.

РЕДАКТИРОВАНИЕ: чтобы вернуть эти два словаря, вы можете использовать dict compethsion:

a2b = {a: {_b:v for (_a,_b), v in result.items() if _a==a} for (a,b) in result.keys()}
b2a = {b: {_a:v for (_a,_b), v in result.items() if _b==b} for (a,b) in result.keys()}

, чтобы получить список значений сходства, вы можете использовать ab_sim = list(result.values())

...