基于Apriori算法的杂货店推荐案例研究
如今,产品推荐已成为每一个电子商务的核心。大多数实时推荐引擎使用复杂的概念,如协同过滤,基于内容的过滤或混合推荐系统。每种类型都有其优点和缺点,但是当涉及到产品匹配或找到一起购买的产品集时,Apriori算法就发挥了作用。
使用这种推荐引擎有很多好处。即使您没有客户的各种数据,您仍然可以使用Apriori算法构建仅使用订单事务数据的引擎。
Apriori算法理论
Apriori算法有三个主要组成部分:
- 支持度
- 置信度
- 提升度
支持度
支持度基本上说明该项目的受欢迎程度。支持度是通过在总订单编号中包含物品B的交易来计算的。
Support(B) = (Transactions containing (B))/(Total Transactions)
置信度
置信度是指如果购买物品A,物品B也被购买的可能性。 可以通过查找A和B一起购买的交易数量除以购买A的交易总数来计算。在数学上,它可以表示为:
Confidence(A,B) = (Transactions containing both (A and B))/(Transactions containing A)
提升度
Lift(A,B)是指出售A时B的销售比率的增加。Lift(A,B)可以用Confidence(A,B)除以Support(B)来计算。。在数学上它可以表示为:
Lift(A→B) = (Confidence (A,B))/(Support (B))
您可以通过查看提升度得出一些结论。提升度1表示产品之间没有关联。提升度大于1意味着产品可能一起购买。假设两种产品A和B的提升度为5,这意味着产品A和B一起购买比单独购买产品B的可能性高5倍。提升度小于1表明产品不太可能一起购买。
Python的Apriori算法
我使用kaggle中提供的数据(https://www.kaggle.com/psparks/instacart-market-basket-analysis)实现该算法。数据来自一家杂货店。在本文中,我仅使用订单和产品数据来描述Apriori。订单日期包含大约13个缺失行。我对数据进行了一些过滤,以减少脚本所花费的时间。您可以在完整的机器学习数据集上运行。
导入必要的Python库
import pandas as pd import numpy as np
读取数据
order_product_df = pd.read_csv(‘data/order_products__train.csv’) product_df = pd.read_csv(‘data/products.csv’)
检查两个data frame的形状
print(“shape of order data = “, order_product_df.shape) print(“shape of product data = “, product_df.shape)
shape of order data = (1384617, 4)
shape of product data = (49688, 4)
检查订单数据
order_product_df.head()
在订单数据中,为简单起见,我只使用order_id和product_id。我只对重新排序的数据进行了分析。
过滤数据
#lets do analysis for only the order which is reordered.. reorder_product = order_product_df.loc[order_product_df.reordered == 1] print(“reorder shape = “, reorder_product.shape)
reorder shape = (555793, 4)
检查每个产品的订单数量
reorder_product_ids = pd.DataFrame({‘order_count’: reorder_product.groupby([‘product_id’])[‘order_id’].count()}) reorder_product_ids.reset_index(inplace = True) reorder_product_ids_sort = reorder_product_ids.sort_values(by = ‘order_count’, ascending= False) reorder_product_ids_sort['order_count'].describe()
我使用了根据订单数量排序的产品id列表中排名前1%的产品。order_count的截止值是370。
过滤产品
reorder_product_ids_sort.quantile(0.99)
reorder_product_top99pct = reorder_product_ids_sort.loc[reorder_product_ids_sort.order_count > 370] #print("product count for top 99% = ", reorder_product_top99pct.shape) product_list_99pct = reorder_product_top99pct.product_id.unique() reorder_product_99Pct = reorder_product.loc[reorder_product.product_id.isin(product_list_99pct)]
此数据集reorder_product_90Pct基本上包含产品位于前1%的所有订单。
为了分析数据,我将订单和产品组合排成行
使数据排成一行以便更好地理解。Python代码如下:
def make_dataSet_rowWise(reorder_product): print(“unique Product in dataset = “, len(reorder_product.product_id.unique())) print(“unique order_id in dataset = “, len(reorder_product.order_id.unique())) product_id_list = reorder_product.product_id.unique().tolist() product_id_list.append(‘order_id’) product_id_dict = {} i = 0 for prod_id in product_id_list: product_id_dict[prod_id] = i i = i+1 product_id_df = pd.DataFrame(columns = product_id_list) row_list_all = [] order_id_list = reorder_product.order_id.unique() i = 1 for id in order_id_list: #print(i) i = i+1 np_zeros = np.zeros(shape = [len(product_id_list)-1]) ordered_product_list = reorder_product.loc[reorder_product.order_id == id][‘product_id’].tolist() for order_prod in ordered_product_list: np_zeros[product_id_dict.get(order_prod)] = 1 row_list = np_zeros.tolist() row_list.append(id) row_list_all.append(row_list) return (row_list_all, product_id_list) df_row_wise = make_dataSet_rowWise(reorder_product_99Pct) product_id_df = pd.DataFrame(df_row_wise[0], columns = df_row_wise[1]) product_id_df.head()
上图显示了数据集的格式。这里每行代表一个order_id,每列代表一个product_id。如果特定订单包含product_id,则该行中该列的相应值将填充为1,否则为零。
现在在上面提到的数据集之上。我计算上面提到的三个参数,即每对产品的置信度,支持度,提升度。
计算每对产品的提升度。
上图基本上显示了产品数据之间的提升度数据。现在您可以看到产品24852和13176之间的提升度是0.007368。
将提升度数据与产品名称数据集合并。并按升序对数据进行排序。
product_A_name = lift_df.Product_A.apply(lambda x: product_df.loc[product_df.product_id == x].product_name.tolist()[0]) product_B_name = lift_df.Product_B.apply(lambda x: product_df.loc[product_df.product_id == x].product_name.tolist()[0]) lift_df[‘product_A_name’] = product_A_name lift_df[‘product_B_name’] = product_B_name lift_df_sorted = lift_df.sort_values(by = [‘Lift’], ascending= False) lift_df_sorted[[‘Lift’, ‘product_A_name’, ‘product_B_name’]].head()
在这里你可以看到Icelandic Style Skyr Blueberry Non-fat Yogurt和Non Fat Raspberry Yogurt,提升度值为69.09,非常高。这表明这两种产品之间的可能性非常高。
我们如何使用这种分析的结果?
现在你有了所有显示产品之间可能性的数据。现在,如果您想搜索某个特定产品的前5个推荐产品,只需使用product_id或名称过滤掉数据即可。您将看到那些特定产品中最常购买的产品。
这是一个例子,我过滤了产品 Icelandic Style Skyr Blueberry Non-fat Yogurt的数据,该列表显示了当一个人购买第一个产品时可以推荐的前5个其他产品。