Pull to refresh

Использование коэффициента Танимото для поиска людей с одинаковыми предпочтениями

Algorithms *
Sandbox
Решая упражнения к книге «Программируем коллективный разум», я решил поделиться реализацией одного из алгоритмов упомянутого в этой книге (Глава 2 — Упражнение 1).

Исходные условия следующие: пусть мы имеем словарь с оценками критиков:

critics={'Lisa Rose'{'Superman Returns'3.5'You, Me and Dupree'2.5'The Night Listener'3.0}
           'Gene Seymour'
{'Superman Returns'5.0'The Night Listener'3.5'You, Me and Dupree'3.5}}

Чем выше оценка, тем больше нравится фильм.
Надо вычислить: насколько схожи интересы критиков для того, например, чтобы можно было на основе оценок одного рекомендовать фильмы другому?



Коэффициент Танимото – описывает степень схожести двух множеств. В интернете я нашел несколько вариантов формулы для его вычисления. И решил остановиться на следующем:

, где k — коэффициент Танимото (число от 0 до 1), чем он ближе к 1, тем более схожи множества;
a — количество элементов в первом множестве;
b — количество элементов во втором множестве;
c — количество общих элементов в двух множествах;
Теперь нам надо сравнить оценки двух критиков.
Сразу хочу прояснить один момент. Что следует считать общим элементом в двух наших множествах? Понятно, что представление оценки в текущем виде не позволит достаточно точно определить людей со схожими интересами. Ведь, по сути своей, одинаковые оценки 3,5 и 4.0 для этого алгоритма — совершенно разные цифры. Поэтому коэффициент Танимото, на мой взгляд, стоит использовать, если количество вариантов оценок не больше 2-3 (например, «понравилось-не понравилось» или «рекомендую-не смотрел-не рекомендую») Я решил немного изменить словарь для более удобной работы и применил к оценкам следующее преобразование: Если оценка меньше 3, значит фильм не понравился (оценка становится — 0), иначе – понравился (оценка становится — 1). Данные в таком виде являются более подходящими для нашего эксперимента.
def prepare_for_tanimoto(critics_arr):
    arr = critics_arr.copy()
    for critic in arr:
        for film in arr[critic]:
            if arr[critic][film] < 3:
                arr[critic][film] = 0
            else:
                arr[critic][film] = 1
    return arr

На выходе мы получим следующий словарь:

critics={'Lisa Rose'{'Superman Returns'1'You, Me and Dupree'0'The Night Listener'1}
           'Gene Seymour'
{'Superman Returns'1'The Night Listener'1'You, Me and Dupree'1}}

А затем мы напишем функцию, которая вычисляет коэффициент сходства оценок двух критиков.

def tanimoto(critics_arr, critic1, critic2):
    arr = prepare_for_tanimoto(critics_arr)
 
    a = len(arr[critic1])
    b = len(arr[critic2])
    c = 0.0
 
    for film in arr[critic1]:
        if arr[critic1][film] == arr[critic2][film]:
            c = c + 1
 
    koef = c / (a + b - c)
    return koef


Проверим работоспособность функции tanimoto.

>>>print tanimoto(critics, 'Gene Seymour', 'Lisa Rose')
>>>0.5

По моему, результат верен. Надо заметить, что при увеличении количества оценок у каждого критика, увеличится и точность подсчета коэффициента сходства.

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

Скачать текст примера можно тут.
Скачать полный текст всех примеров из книги можно на сайте автора. Там же можно найти более полный массив с оценками критиков.
Tags:
Hubs:
Total votes 109: ↑100 and ↓9 +91
Views 10K
Comments Comments 22