Подтвердить что ты не робот

Способы расчета подобия

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

возраст, тип кожи (маслянистый, сухой), тип волос (длинный, короткий, средний), образ жизни (активный наружный любовник, телевизионный junky) и другие.

Может ли кто-нибудь сказать мне, как решить эту проблему или указать мне на некоторые ресурсы?

4b9b3361

Ответ 1

Другой способ вычисления (в R) всех попарных различий (расстояний) между наблюдениями в наборе данных. Исходные переменные могут иметь смешанные типы. Обработка номинальных, порядковых и (а) симметричных двоичных данных достигается за счет использования общего коэффициента несходства Gower (Gower, J. C. (1971) Общий коэффициент подобия и некоторые его свойства, Biometrics 27, 857-874). Подробнее см. на странице 47. Если x содержит любые столбцы этих типов данных, коэффициент Gower будет использоваться как метрика.

Например

x1 <- factor(c(10, 12, 25, 14, 29))
x2 <- factor(c("oily", "dry", "dry", "dry", "oily"))
x3 <- factor(c("medium", "short", "medium", "medium", "long"))
x4 <- factor(c("active outdoor lover", "TV junky", "TV junky", "active outdoor lover", "TV junky"))
x <- cbind(x1,x2,x3,x4)

library(cluster)
daisy(x, metric = "euclidean")

вы получите:

Dissimilarities :
         1        2        3        4
2 2.000000                           
3 3.316625 2.236068                  
4 2.236068 1.732051 1.414214         
5 4.242641 3.741657 1.732051 2.645751

Если вас интересует метод уменьшения размерности для категориальных данных (также способ упорядочивания переменных в однородные кластеры), проверьте this

Ответ 2

Дайте каждому атрибуту соответствующий вес и добавьте различия между значениями.

enum SkinType
    Dry, Medium, Oily

enum HairLength
    Bald, Short, Medium, Long

UserDifference(user1, user2)
    total := 0
    total += abs(user1.Age - user2.Age) * 0.1
    total += abs((int)user1.Skin - (int)user2.Skin) * 0.5
    total += abs((int)user1.Hair - (int)user2.Hair) * 0.8
    # etc...
    return total

Если вам действительно нужно подобие вместо разницы, используйте 1 / UserDifference(a, b)

Ответ 3

Вероятно, вам стоит взглянуть на

Эти темы позволят вашей программе распознавать сходства и кластеры в вашей коллекции пользователей и попытаться адаптироваться к ним...

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

Как совет, попробуйте использовать готовые реализованные инструменты для этой функции, а не для ее реализации самостоятельно...
Взгляните на Открыть проекты разработки данных каталога

Ответ 4

Три шага для достижения простой субъективной метрики для разницы между двумя точками данных, которые могут нормально работать в вашем случае:

  • Захватите все свои переменные в числовой переменной, например: тип кожи (масляный = -1, сухой = 1), тип волос (длинный = 2, короткий = 0, средний = 1), образ жизни (активный наружный любовник = 1, TV junky = -1), возраст - это число.
  • Масштабируйте все числовые диапазоны, чтобы они соответствовали относительной важности, которую вы им даете для указания разницы. Например: Разница в возрасте 10 лет примерно такая же разная, как разница между длинными и средними волосами, а также разница между жирной и сухой кожей. Таким образом, 10 по возрастной шкале отличаются друг от друга, так как 1 по шкале волос отличается от 2 по шкале кожи, поэтому уменьшите разницу в возрасте на 0,1, что в волосах на 1, а на коже - на 0,5.
  • Используйте соответствующий показатель расстояния, чтобы сочетать различия между двумя людьми в разных масштабах с одной разницей. Чем меньше это число, тем они более похожи. Я бы предложил простое квадратичное различие в качестве первой попытки вашей дистанционной функции.

Тогда разница между двумя людьми может быть рассчитана с помощью (Я предполагаю, что Person.age,.skin,.hair и т.д. уже прошли шаг 1 и являются числовыми):

double Difference(Person p1, Person p2) {

    double agescale=0.1;
    double skinscale=0.5;
    double hairscale=1;
    double lifestylescale=1;

    double agediff = (p1.age-p2.age)*agescale;
    double skindiff = (p1.skin-p2.skin)*skinscale;
    double hairdiff = (p1.hair-p2.hair)*hairscale;
    double lifestylediff = (p1.lifestyle-p2.lifestyle)*lifestylescale;

    double diff = sqrt(agediff^2 + skindiff^2 + hairdiff^2 + lifestylediff^2);
    return diff;
}

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

Ответ 5

Посмотрите на алгоритмы вычисления разности srting. Это очень похоже на то, что вам нужно. Храните свои атрибуты в виде битовой строки и вычисляйте расстояние между строками