Подбор людей по интересам - PullRequest
0 голосов
/ 22 января 2019

следующая проблема: сопоставление пользователей на основе оценки совместимости на основе данных, предоставленных путем заполнения профиля с указанием личности, образа жизни, интересов и т. Д.

Каждый из атрибутов - это теги (например, атрибут спокойный для личности), которые имеют значение true (1) или false (0). Предположим, мы хотим найти совместимость двух пользователей.

Выписка из панды DataFrame для личности

Пользователь 2 вычитается из Пользователя 3, различия возводятся в квадрат, а сумма различий устанавливается в зависимости от максимально возможного отклонения (количество атрибутов для категории и т. Д. Личности). Тогда обратная оценка является результатом сходства. То же самое сделано для всех категорий (например, стиль жизни)

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

Каждый пользователь сравнивается с любым другим пользователем в кадре данных:

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). Любые предложения, чтобы ускорить это, сделать код проще?

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

@ 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

Коэффициент подобия Th равен 0,366, тогда как он должен составлять 40%, поскольку их абсолютное отклонение составляет 3 из 5 переменных -> 60%

0 голосов
/ 24 января 2019

Надеюсь, у меня правильная постановка задачи:

У меня есть DataFrame X, бинарных индикаторных переменных.(0,1) Для каждой строки X (которая представляет другого пользователя) я хотел бы найти наиболее похожих пользователей / строк среди других пользователей / строк.

Я буду использовать класс NearestNeighbors в sklearn, отсюда :

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 (по расположению их индексов) указали, что 3-й столбец был очень важным («10» на0-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] и [2,1], указывающими, что вторая строка и третья строка теперь находятся ближе всего друг к другу.(Помните, что первое значение в массиве i - это само совпадение)

Здесь есть тонкие детали, которые я подчеркиваю, которые могут сделать неподходящих соседей, но вы можете прочитать о их в другихразличные места

...