【问题标题】:ranking similarity of one vector with a very large dataframe of vectors in panda熊猫中一个向量与一个非常大的向量数据框的相似度排名
【发布时间】:2021-01-06 19:40:41
【问题描述】:

目标:我正在尝试创建一个有序的项目列表,这些项目根据它们与测试项目的接近程度进行排名。

我有 1 个具有 10 个属性的测试项目和 250,000 个具有 10 个属性的项目。我想要一个对 250,000 个项目进行排名的列表。例如,如果结果列表返回 [10,50,21,11,10000....] 比索引 10 的项目最接近我的测试项目,索引 50 是第二接近我的测试项目,等等。

我尝试过的方法适用于小数据帧,但不适用于较大的数据帧:

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

similarity_matrix = pd.np.random.rand(4,4) 

#4 items with the first being the test
#0.727048   0.113704    0.886672    0.0345438
#0.496636   0.678949    0.0627973   0.547752
#0.641021   0.498811    0.628728    0.575058
#0.760778   0.955595    0.646792    0.126714 

#creates the cosine similarity matrix 
winner = cosine_similarity(similarity_matrix) 

#I just need the first row, how similar each item is to the test, I'm excluding how similar the test is to the test 
winner = np.argsort(winner[0:1,1:])

#I want to reverse the order and add one so the list matches the original index    
winner = np.flip(winner) +1

不幸的是,250,000 我收到以下错误“MemoryError: Unable to allocate 339. GiB for an array with shape (250000, 250000) and data type float64”

我真的只需要第一行,而不是创建一个 250000X250000 矩阵。还有其他方法吗?

【问题讨论】:

    标签: python pandas numpy sklearn-pandas cosine-similarity


    【解决方案1】:

    逐行计算距离 例如。

    test = np.array([[1, 2, 3]])
    big_matrix = np.array([[1, 2, 3], [2, 3, 4]])
    
    #calculate and concat all of them into one
    result = np.array([cosine_similarity(test, row.reshape(1, -1)) for row in big_matrix]).reshape(-1, 1)
    winner = np.argsort(result)
    

    【讨论】:

    • 这看起来很有希望,但返回错误“ValueError: Expected 2D array, got 1D array instead: array=[1. 2. 3.].”
    • 这不起作用,结果是0 0,在这个例子中应该是1 0。我认为问题在于应该将测试数组附加到行中。我不知道如何在列表理解中做到这一点,但在多行中它看起来更接近这个array1 = np.array([[1, 2, 3]]) array2 = np.array([[1, 2, 3]]) array3 = np.append(array1,array2, axis=0) cosine_similarity(array3)[0,1]
    【解决方案2】:

    如果您使用第二个参数调用 cosine_similarity,它只会计算与第二个数组的距离。
    一个带有随机向量的例子

    x = np.random.rand(5,2)
    

    只有一个参数

    cosine_similarity(x)
    array([[1.        , 0.95278802, 0.93496787, 0.45860786, 0.62841819],
           [0.95278802, 1.        , 0.99853581, 0.70677904, 0.8349406 ],
           [0.93496787, 0.99853581, 1.        , 0.74401257, 0.86348853],
           [0.45860786, 0.70677904, 0.74401257, 1.        , 0.979448  ],
           [0.62841819, 0.8349406 , 0.86348853, 0.979448  , 1.        ]])
    

    将第一个向量作为第二个参数

    cosine_similarity(x, [x[0]])
    array([[1.        ],
           [0.95278802],
           [0.93496787],
           [0.45860786],
           [0.62841819]])
    

    如果你的内存仍然不足,你可以分块计算距离

    chunks = 4
    np.concatenate(
        [cosine_similarity(i, [x[0]]) for i in np.array_split(x, chunks)]
    )
    array([[1.        ],
           [0.95278802],
           [0.93496787],
           [0.45860786],
           [0.62841819]])
    

    【讨论】:

    • 当我将 df 设置为 np.array 时,您的答案有效。为了完整起见,之后导出列表需要进行以下更改:winner = cosine_similarity(np_array,[np_array[0]])[1:,:] #take all elements except the first winner = winner[:,0].argsort(axis=0) #sort the index of the array winner = np.flip(winner) +1 #flip the sort order and add one to match the index
    猜你喜欢
    • 2016-12-22
    • 2018-11-14
    • 2019-12-27
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2020-12-20
    相关资源
    最近更新 更多