edo1z blog

プログラミングなどに関するブログです

協調フィルタリング(ピアソン相関)

from operator import itemgetter
from math import sqrt

data = {
    'A': {'あ': 10, 'い': 5, 'う': 3, 'え': 4, 'お': 9, 'か': 6},
    'B': {'あ': 3, 'い': 3, 'う': 3, 'え': 4, 'お': 3, 'か': 4},
    'C': {'あ': 2, 'い': 10, 'う': 4, 'え': 2, 'お': 4},
    'D': {'あ': 6, 'い': 3, 'う': 5, 'え': 2, 'お': 5},
    'E': {'あ': 8, 'い': 4, 'う': 3, 'え': 2, 'お': 9},
    'F': {'あ': 1, 'い': 2, 'う': 9, 'え': 3, 'お': 8},
    'G': {'あ': 9, 'い': 4, 'う': 3, 'え': 4, 'お': 9, 'か': 5},
    'H': {'あ': 10, 'い': 0, 'う': 1, 'え': 2, 'お': 5},
    'I': {'あ': 9, 'い': 10, 'う': 10, 'え': 5, 'お': 3},
    'J': {'あ': 3, 'い': 8, 'う': 8, 'え': 1, 'お': 5},
    'K': {'あ': 7, 'い': 4, 'う': 1, 'え': 2, 'お': 9},
    'L': {'あ': 8, 'い': 3, 'う': 1, 'え': 4, 'お': 1},
    'M': {'あ': 1, 'い': 5, 'う': 4, 'え': 5, 'お': 5},
    'N': {'あ': 1, 'い': 5, 'う': 4, 'え': 6, 'お': 3},
    'O': {'あ': 10, 'い':4}
}

def get_pearson(data, person1, person2):
    item_list = []
    [item_list.append(item) for item in data[person1] if item in data[person2]]
    n = len(item_list)
    if n < 1: return 0

    ave_1 = sum([data[person1][item] for item in item_list]) / n
    ave_2 = sum([data[person2][item] for item in item_list]) / n

    top = sum([(data[person1][item] - ave_1) * (data[person2][item] - ave_2) for item in item_list])
    under = sqrt(sum([pow(data[person1][item] - ave_1, 2)for item in item_list])) * sqrt(sum([pow(data[person2][item] - ave_2, 2)for item in item_list]))
    if under == 0: return 0
    return top / under

#meに嗜好が似ている人順に並んだリストを返す
def get_similar_list(data, me):
    person_list = {}
    for person in data:
        if person == me: continue
        person_list[person] = get_pearson(data, me, person)

    return sorted(person_list.items(), key = itemgetter(1), reverse = True)

a_sim = get_similar_list(data, 'A')
for person in a_sim:
    print(person[0], person[1])

結果は、下記のように表示される。

O 1.0 G 0.9808680821138367 E 0.9484536082474225 K 0.9408299662818367 H 0.8827613485576769 D 0.6252910738779192 L 0.49037436997675116 C -0.2540244987629046 F -0.2553208668685789 I -0.3101395942331776 J -0.31251695558993137 B -0.3242687382284557 M -0.5561279983200484 N -0.8262633124961081