python - 优化矩阵遍历/通用代码优化

标签 python pandas numpy matrix scipy

我有两个矩阵。一个的大小为 (CxK),另一个的大小为 (SxK)(其中 S、C 和 K 都有可能非常大)。我想使用余弦相似度函数(大小为 [CxS])将这些输出矩阵组合起来。当我运行代码时,需要很长时间才能产生输出,我想知道是否有任何方法可以优化我当前拥有的内容。 [注意,两个输入矩阵通常非常稀疏]

我之前使用两个 for index,row 循环遍历每个矩阵,但后来我切换到 while 循环,这显着提高了我的运行时间。

A #this is one of my input matrices (pandas dataframe)
B #this is my second input matrix (pandas dataframe)
C = pd.DataFrame(columns = ['col_1'  ,'col_2'  ,'col_3'])

i=0
k=0
while i <= 5:
    col_1 = A.iloc[i].get('label_A')
    while k < 5:
        col_2 = B.iloc[k].get('label_B')
        propensity = cosine_similarity([A.drop('label_A', axis=1)\
            .iloc[i]], [B.drop('label_B',axis=1).iloc[k]])
        d = {'col_1':[col_1], 'col_2':[col_2], 'col_3':[propensity[0][0]]}
        to_append = pd.DataFrame(data=d)
        C = C.append(to_append)
        k += 1
    k = 0
    i += 1

现在我的循环只对每个矩阵中的 5 个项目运行,生成一个 5x5 矩阵,但我显然希望它适用于非常大的输入。这是我第一次做这样的事情,所以请让我知道代码的任何方面是否可以改进(用于保存矩阵的数据类型、如何遍历它们、更新输出矩阵等)。

提前谢谢您。

最佳答案

将标签移动到索引后,通过将整个数组传递给cosine_similarity,可以更轻松、更快地完成此操作:

import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
import time

c = 50
s = 50
k = 100

A = pd.DataFrame( np.random.rand(c,k))
B = pd.DataFrame( np.random.rand(s,k))
A['label_A'] = [f'A{i}' for i in range(c)]
B['label_B'] = [f'B{i}' for i in range(s)]
C = pd.DataFrame()

# your program
start = time.time()
i=0
k=0
while i < c:
    col_1 = A.iloc[i].get('label_A')
    while k < s:
        col_2 = B.iloc[k].get('label_B')
        propensity = cosine_similarity([A.drop('label_A', axis=1)\
            .iloc[i]], [B.drop('label_B',axis=1).iloc[k]])
        d = {'col_1':[col_1], 'col_2':[col_2], 'col_3':[propensity[0][0]]}
        to_append = pd.DataFrame(data=d)
        C = C.append(to_append)
        k += 1
    k = 0
    i += 1
print(f'elementwise: {time.time() - start:7.3f} s')

# my solution
start = time.time()
A = A.set_index('label_A')
B = B.set_index('label_B')
C1 = pd.DataFrame(cosine_similarity(A, B), index=A.index, columns=B.index).stack().rename('col_3')
C1.index.rename(['col_1','col_2'], inplace=True)
C1 = C1.reset_index()
print(f'whole array: {time.time() - start:7.3f} s')

# verification
assert(C[['col_1','col_2']].to_numpy()==C1[['col_1','col_2']].to_numpy()).all()\
       and np.allclose(C.col_3.to_numpy(), C1.col_3.to_numpy())

关于python - 优化矩阵遍历/通用代码优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57420245/

相关文章:

python - 在不违反类封装的情况下在两个窗口之间进行通信

python - Python中的匹配组

python - 数字系统转换器python

python - 在 numpy 中向量化简单的 for 循环

python - 将 pandas 数据框中的单个 header 转换为多个 header

python - 使用 numpy/python 从头开始​​进行多项式展开

python - 正则表达式模式仅用一项替换列值

python - 如何根据列值从 DataFrame 中选择行?

numpy - 从/向 Parquet 文件读取/写入 pyarrow 张量

python - 在一个 Pandas 系列中找到两个近似值。根据标准在另一个上创建一个标志