1

以下问题:通过填写表明个性、生活方式、兴趣等的个人资料提供的数据,根据兼容性分数匹配用户。

每个属性都是真 (1) 或假 (0) 的标签(例如,性格冷静的属性)。假设我们想要找到两个用户的兼容性。

从 panda DataFrame 中提取个性

从用户 3 中减去用户 2,对差异进行平方,然后将差异的总和与最大可能偏差(一个类别的属性数量等个性)相关联。倒数是相似度的分数。所有类别(例如生活方式)都是如此

def similarityScore (pandaFrame, name1, name2):

    profile1 = pandaToArray(pandaFrame, name1)#function changing DataFrane to array
    profile2 = pandaToArray(pandaFrame, name2)

    newArray = profile1 - profile2
    differences = 0
    for element in newArray:
        element = (element)**2
        differences += element
    maxDifference = len(profile1)
    similarity = 1 - (differences/maxDifference)
    return similarity

每个用户都与 DataFrame 中的所有其他用户进行比较:

def scorecalc(fileName):
    data = csvToPanda(fileName)
    scorePanda = pd.DataFrame([], columns=userList, index=userList)
    for user1 in userList:
        firstUser = user1

        for user2 in userList:
            secondUser = user2
            score = similarityScore(data, firstUser, secondUser)
            scorePanda.iloc[[userList.index(firstUser)],[userList.index(secondUser)]] = score
    return(scorePanda)

根据特定类别的相似性对用户的重要性,通过将相似性分数乘以偏好数据框来加权相似性分数:

def weightedScore (personality, lifestyle,preferences):

    personality = personality.multiply(preferences['personality'])
    lifestyle = lifestyle.multiply(preferences['lifestyle'])

    weightscore = (personality + lifestyle) 
    return(weightscore)

结果将是从 0 到 1 的兼容性分数。

它工作得很好,但是运行它需要相当多的时间,特别是如果比较的用户数量(100+)增加了。有什么建议可以加快速度,使代码更容易吗?

4

2 回答 2

0

希望我的问题陈述正确:

我有二进制指标变量的 DataFrame X。(0,1) 对于 X 的每一行(代表不同的用户),我想在其他用户/行中找到最相似的用户/行。

我将使用 sklearn 中的 NearestNeighbors 类,从这里开始

import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
from sklearn.neighbors import NearestNeighbors
X = np.array([[0,0,0,0,1],
              [0,0,0,0,1],
              [1,1,1,0,0],
              [1,0,0,1,1]])

查看 X,我们可以看到 idx = 1 和 idx = 2 是最相似的。他们完美匹配。它们应该相互匹配为“最相似”。

# two nbrs since first match is self match
nbrs = NearestNeighbors(n_neighbors=2, metric='dice').fit(X)
distances, indices = nbrs.kneighbors(X) 
print(indices) 

#remember first val in this array per line is self match
[[0 1]
[0 1]
[2 3]
[3 1]]

要合并您的加权分数,我不太确定。我的第一个想法是获取您的二进制数据数组,乘以“这对我来说有多重要”,然后在最近的邻居搜索中使用不同的指标,比如"euclidean"或其他。它需要更多关于这些其他数据帧中包含的具体内容的信息。

因此,假设用户 1 和 2(通过他们的索引位置)表示第三列非常重要(0-10 上的“10”),并且第三列在此处填写如下:

X = np.array([[0,0,0,0,1],
             [0,0,1,0,1],
             [1,1,1,0,0],
             [1,0,0,1,1]])
# notice they match now on that 3rd col, but disagree elsewhere

#ugly hack for replacing two vals
np.put(X[1], [2], [10]) # grab second row, third col, place [10]
np.put(X[2], [2], [10])

print(X)

[[ 0  0  0  0  1]
[ 0  0 10  0  1]
[ 1  1 10  0  0]
[ 1  0  0  1  1]]

现在他们都同意这个问题非常重要。现在尝试使用不同的度量来计算邻居:

nbrs = NearestNeighbors(n_neighbors=2, metric='euclidean').fit(X)

d, i = nbrs.kneighbors(X)
print(d)
print(i)

[[0.         1.41421356]
 [0.         1.73205081]
 [0.         1.73205081]
 [0.         1.41421356]]
[[0 3]
 [1 2]
 [2 1]
 [3 0]]

[1,2]and[2,1]表示第二行和第三行现在彼此最接近。(记住数组中的第一个 vali是自匹配)

这里有一些我正在掩饰的细节,这可能会使最近的邻居不合适,但你可以在其他不同的地方阅读它们

于 2019-01-23T21:16:29.353 回答
0

@Dylan 我对 NearestNeighbours 的唯一问题是它会为我所采取的方法带来不同的结果。一个例子:

from sklearn.neighbors import NearestNeighbors
import numpy as np

X = np.array([[0,0,0,0,1],
             [0,0,1,1,0]])

nbrs = NearestNeighbors(n_neighbors=2, metric = 'euclidean').fit(X)
distances, indices = nbrs.kneighbors(X)
print(distances)
print(1/ (1+distances)) # returns a similarity score between 0 and 1

相似度得分为 0.366,而应该为 40%,因为它们的绝对偏差是 5 个变量中的 3 个 --> 60%

于 2019-02-04T10:11:42.890 回答