我尝试使用Redis和Python来实现协同过滤(推荐)功能

这次制作的东西

让我们尝试创建类似亚马逊的「购买了该商品的人也购买了这些商品」功能。

スクリーンショット 2015-04-23 5.53.32.png

要素技术和实施方法 sù hé

一般而言,所谓的推荐功能(推荐功能)。推荐的实现方法主要有两种,分别是“协同过滤”和“内容基准过滤”。

コンテンツベースフィルタリングは、例えば上記例の『老人と海(ヘミングウェイ)』のお勧め商品をコンテンツベースで実装する場合は、事前に商品に属性のタグを打っておく。例えば作者という属性でタグを打っておけば、同じヘミングウェイが記した本をお勧めとして表示する。

協調過濾是指顯示其他購買了此商品的人的購買推薦。

这次我们要实现”协同过滤”。

我们会使用Redis和Python。

Redis是一个键值存储系统(KVS)。
使用Redis的SortedSet结构。

Redis安装步骤

MacPorts: http://blog.katsuma.tv/2010/03/start_redis.html
HomeBrew: http://qiita.com/items/3d2a2fc683ae19302071

MacPorts: http://blog.katsuma.tv/2010/03/start_redis.html
HomeBrew: http://qiita.com/items/3d2a2fc683ae19302071

使用Redis的原因

由于从计算量的角度来看,每次计算推荐商品并不现实,因此需要事先计算并以便于获取和记录的形式进行存储。(只要能够方便取出和记录,除了Redis之外的其他工具也可以使用)

SortedSet是一种数据结构

将数据放入,并由Redis自动重新排序的列表。

スクリーンショット 2015-04-23 4.26.57.png

协调过滤算法的实现

只要能够获取对商品X的每个商品的相似度值,就可以进行实现。

スクリーンショット 2015-04-23 4.29.36.png

相似度的计算公式

有各种方法,但通常使用Jaccard指数(ジャッカールしすう)。
在下面的样本数据中,商品A的计算公式为1÷5。
1表示同时购买商品X和商品A的客户数量为1,即交集。
5表示购买商品X和商品A中任意一个的客户总数,即并集。

スクリーンショット 2015-04-23 4.36.07.png

使用本次的样本数据

スクリーンショット 2015-04-23 5.23.01.png

实施

# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals


def jaccard(e1, e2):
    """
    ジャッカード指数を計算する
    :param e1: list of int
    :param e2: list of int
    :rtype: float
    """
    set_e1 = set(e1)
    set_e2 = set(e2)
    return float(len(set_e1 & set_e2)) / float(len(set_e1 | set_e2))


def get_key(k):
    return 'JACCARD:PRODUCT:{}'.format(k)

# 商品Xを購入した顧客IDが1,3,5ということ
product_x = [1, 3, 5]
product_a = [2, 4, 5]
product_b = [1, 2, 3]
product_c = [2, 3, 4, 7]
product_d = [3]
product_e = [4, 6, 7]

# 商品データ
products = {
    'X': product_x,
    'A': product_a,
    'B': product_b,
    'C': product_c,
    'D': product_d,
    'E': product_e,
}

# redis
import redis
r = redis.Redis(host='localhost', port=6379, db=10)

# ジャッカード指数を計算して商品毎にredisのSortedSetに記録する
for key in products:
    base_customers = products[key]
    for key2 in products:
        if key == key2:
            continue
        target_customers = products[key2]
        # ジャッカード指数を計算
        j = jaccard(base_customers, target_customers)
        # redisのSortedSetに記録する
        r.zadd(get_key(key), key2, j)

# 例1 商品Xを買った人はこんな商品も買っています。
print r.zrevrange(get_key('X'), 0, 2)
# > ['B', 'D', 'A']

# 例2 商品Eを買った人はこんな商品も買っています。
print r.zrevrange(get_key('E'), 0, 2)
# > ['C', 'A', 'X']

让我们来查看一下Redis中存储的值。

r.png

让我们来做个验证

购买商品X的人向他们推荐了商品B,D,A。根据校验结果,它们分别具有0.5,0.33和0.2的相似度,所以可以说它们被适当地推荐了。

スクリーンショット 2015-04-23 5.21.23.png

这种方法的问题所在

当顾客数量和商品数量增加时,计算量会急剧增加并导致系统崩溃。

解决方案 (jiě jué àn)

Amazon希望与您一同创建倒排索引。请访问http://www.cs.umd.edu/~samir/498/Amazon-Recommendations.pdf。

广告
将在 10 秒后关闭
bannerAds