http://pkolt.ru/pages/168/
Определить на сколько отличаются(похожи) объекты
Практическое применение:
Рассмотрим 2 алгоритма для определения похожести Эвклидово расстояние и коэффициент корреляции Пирсона.
Результат работы функции число от 0 до 1, чем больше число тем больше общего между Гвидо и Ларри.
- списки продуктов, каталоги товаров(поиск схожих товаров)
- профили пользователей, сайты знакомств(поиск близких по критериям людей)
Рассмотрим 2 алгоритма для определения похожести Эвклидово расстояние и коэффициент корреляции Пирсона.
Эвклидово расстояние
В примере дается список людей и их оценки разным языкам программирования, по шкале от 0 до 5. Причем понятно что Гвидо больше нравится Python, а Ларри - Perl. Просто потому что каждый из них автор этого языка.Результат работы функции число от 0 до 1, чем больше число тем больше общего между Гвидо и Ларри.
01 | from math import sqrt |
02 |
03 | values = { |
04 | 'Guido van Rossum' : { 'python' : 5.0 , 'php' : 1.2 , 'ruby' : 4.0 , 'perl' : 2.8 }, |
05 | 'Larry Wall' : { 'python' : 5.0 , 'php' : 1.2 , 'ruby' : 4.0 , 'perl' : 5.0 }, |
06 | } |
07 |
08 |
09 | def euclidean_distance(values, obj1, obj2): |
10 | """ |
11 | Эвклидово расстояние, |
12 | дианазон значений результата от 0 до 1 |
13 | """ |
14 | if isinstance (values, dict ) and values.has_key(obj1) and values.has_key(obj2): |
15 | signs = {} # признаки оценки |
16 | # отбор признаков, присутствующих у обоих |
17 | for key, value in values[obj1].items(): |
18 | if key in values[obj2]: |
19 | signs[key] = (values[obj1][key], values[obj2][key]) |
20 | # если признаков нет, вернуть 0 |
21 | return 0 if not signs else 1 / ( 1 + sqrt( sum ([ pow (v1 - v2, 2 ) for (v1,v2) in signs.values()]))) |
22 | else : |
23 | raise ValueError |
24 |
25 | print euclidean_distance(values, 'Guido van Rossum' , 'Larry Wall' ) |
26 | # 0.3125 |
Коэффициент корреляции Пирсона
01 | from math import sqrt |
02 |
03 | values = { |
04 | 'Guido van Rossum' : { 'python' : 5.0 , 'php' : 1.2 , 'ruby' : 4.0 , 'perl' : 2.8 }, |
05 | 'Larry Wall' : { 'python' : 5.0 , 'php' : 1.2 , 'ruby' : 4.0 , 'perl' : 5.0 }, |
06 | } |
07 |
08 | def pearsons_correlation_coefficient(values, obj1, obj2): |
09 | """ |
10 | Коэффициент корреляции Пирсона |
11 | диапазон значений результата от -1 до 1 |
12 | """ |
13 | if isinstance (values, dict ) and values.has_key(obj1) and values.has_key(obj2): |
14 | signs = [] # признаки оценки |
15 | # отбор признаков, присутствующих у обоих |
16 | for key, value in values[obj1].items(): |
17 | if key in values[obj2]: |
18 | signs.append(key) |
19 | # если признаков нет, вернуть 0 |
20 | if not signs: return 0 |
21 | # количество признаков |
22 | n = len (signs) |
23 | # сумма знач.всех признаков |
24 | sum1 = sum ([values[obj1][s] for s in signs]) |
25 | sum2 = sum ([values[obj2][s] for s in signs]) |
26 | # сумма квадратов знач.всех признаков |
27 | sum1Sq = sum ([ pow (values[obj1][s], 2 ) for s in signs]) |
28 | sum2Sq = sum ([ pow (values[obj2][s], 2 ) for s in signs]) |
29 | # сумма произведений знач.всех признаков |
30 | pSum = sum ([values[obj1][s] * values[obj2][s] for s in signs]) |
31 | # Коэффициент Пирсона |
32 | num = pSum - (sum1 * sum2 / n) |
33 | den = sqrt((sum1Sq - pow (sum1, 2 ) / n) * (sum2Sq - pow (sum2, 2 ) / n)) |
34 | if den = = 0 : return 0 |
35 | r = num / den |
36 | return r |
37 | else : |
38 | raise ValueError |
39 |
40 | print pearsons_correlation_coefficient(values, 'Guido van Rossum' , 'Larry Wall' ) |
41 | # 0.79850420561 |
Как видно из примера коэффициент Пирсона дает более объективный результат, но существуют и другие математические формулы.
No comments:
Post a Comment