手把手教你为电商搭建购物车推荐系统!
对于企业来说,为客户持续创造价值是企业发展的灵魂,只有真正帮助客户取得成功,企业才能从激烈的市场竞争中脱颖而出,获得应有的利润和回报。然而,要想真正为客户创造价值,信息是基础。只有越了解客户,才越可能满足他们的真正需求,从而赢得他们的信任并成为其长期合作伙伴。
因此,对于电商来说,了解客户并为客户提供独一无二的购物体验是企业工作的必不可少的一个环节。本篇文章将利用机器学习技术,手把手教你如何通过分析顾客的购买行为并构建购物车推荐系统来为顾客提供量身定制的购物体验,从而提高顾客的参与度。
这种方法可能会给电商带来许多好处,例如:
1. 目标营销:通过分析客户在网站/应用程序上的虚拟足迹可以把你的目标营销提升到一个新的水平。比如,你可以根据用户的购买历史,向他们精准推送他们最喜欢的商品的特价活动。
2. 有策略地在一天中的特定时段向每个客户推送不同的营销活动,这个时间一般是客户最常购物或登录应用程序的时间。
3. 计算什么时候应该为商品补货,从而制定有效的库存周期。
4. 推荐顾客可能想要添加到购物车中的商品,并通过推送个性化的建议来吸引客户。
项目目的
我希望能够通过这个项目探索以下问题:
1. 通过分析客户的购买历史来进行行为分析,看看我是否能找到一些规律:比如顾客在一个时间段(例如一天或一周)内的不同时间点喜欢购买哪些商品,以及人们对购买过的产品的再次订购频率等。
2. 购物车推荐:利用客户的重新订购特征和余弦相似度(cosine similarity)构建一个推荐系统。
项目设计
1. 执行数据清理,将不同的表合并在一起,然后进行探索性数据分析(EDA)。
2. 分析客户行为,生成见解并进行数据可视化。
3. 定义模型评估的指标。
4. 最后,创建一个购物车推荐系统,根据顾客的购买历史向顾客推荐商品。
数据来源和工具
这个项目所使用的数据集是我在Instacart上找到的一个客户购买历史数据集,来源于Instacart于2017年在Kaggle平台上发布的一个挑战。
该数据集附带了6个不同的.csv文件,需要使用主键和外键将它们连接起来从而获得完整的信息并执行分析。
这个项目需要用到的数据分析工具有Python的numpy、pandas、matplotlib、seaborn以及来自sklearn的StandardScaler、OneHotEncoder和cosine_similarity。
数据清洗&探索性数据分析(EDA)
该数据集有200万个客户和超过300万个订单。它包含了哪天下单,几点下单,是否再次订购等特征项。此外,该数据集共有6张不同的表格:aisle,department,order_product_prior,order_product_train,products and orders。
购物者行为分析
我们需要了解以下几个问题的答案: 数据集中有多少个订单?我们有多少个不同的客户?客户多久购买一次?客户喜欢什么时候购买?客户在每个订单中购买多少个商品? 以上只是举例几个问题,还有许多其他的问题需要我们找到答案。接下来,我们就来一个一个问题地看!
1. 数据集有多少个订单?
在查看订单表时,我使用了以下代码来查找数据集中有多少个订单以及每个标签的订单数量:
print(orders.shape) print('there are', len(orders[orders.eval_set == 'prior']), 'entries for prior') print('there are', len(orders[orders.eval_set == 'train']), 'entries for train') print('there are', len(orders[orders.eval_set == 'test']), 'entries for test')
一共有3421083个订单。
其中有3214874个prior订单。
训练集中有131209个订单。
测试集中有75000个订单。
2. 数据集有多少不同的客户?
我使用了以下代码来找有多少个不同的客户:
print('there are', len(orders[orders.eval_set == 'prior'].user_id.unique()), 'unique customers in total') print('there are', len(orders[orders.eval_set == 'train'].user_id.unique()), 'unique customers in train set') print('there are', len(orders[orders.eval_set == 'test'].user_id.unique()), 'unique customers in test set')
总共有206209个不同的客户。
训练集中有131209个客户。
测试集中有75000个客户。
3. 订单的数量是如何分布的?
我使用了以下代码来生成订单数量分布图:
orders_amount_for_customer = orders.groupby('user_id')['order_number'].count().value_counts() plt.figure(figsize=(20,8)) sns.barplot(x=orders_amount_for_customer.index, y=orders_amount_for_customer.values, color='mediumseagreen') plt.title('Amount of Orders Distribution', fontsize=16) plt.ylabel('Number of Customers', fontsize=16) plt.xlabel('Amount of Orders', fontsize=16) plt.xticks(rotation='vertical');
每个客户的订单数量在4到100之间,其中大多数人购买了4到10次。
4. 客户最喜欢在一周的哪一天购物?
我使用了以下代码将订单按一周的不同日期分组:
plt.figure(figsize=(12,8)) sns.countplot(x=orders.order_dow, color='mediumseagreen') #plt.title("Order Amounts by Days", fontsize=16) plt.xlabel('', fontsize=16) plt.xticks(fontsize=15) plt.ylabel('Order Counts', fontsize=16) plt.yticks(fontsize=15) ;
0 (周日)和1 (周一)在一周内订单最多,4 (周四)订单最少。
5. 客户喜欢什么时候购物?
我使用了以下代码将订单按小时分组:
plt.figure(figsize=(12,8)) sns.countplot(x=orders.order_hour_of_day, color='mediumseagreen') #plt.title("Order Amounts by Hours", fontsize=16) plt.xlabel('Hour of Day', fontsize=16) plt.xticks(fontsize=15) plt.ylabel('Order Counts', fontsize=16) plt.yticks(fontsize=15) ;
看起来人们喜欢在早上8点到下午6点之间下单。
6. 客户多久购买一次?
我使用了以下代码将订单按上次购买发生的日期分组:
plt.figure(figsize=(12,8)) sns.countplot(x=orders.days_since_prior_order, color= 'mediumseagreen') #plt.title("Number of Orders per Days Since Last Purchase", fontsize=16) plt.xlabel('Days Since Last Purchase', fontsize=16) plt.xticks(np.arange(31), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], fontsize=15) plt.xticks(rotation='vertical') plt.ylabel('Order Counts', fontsize=16) plt.yticks(fontsize=15) ;
看起来大多数人一周购买一次,在0到7点之间。
有些人在30天内只购买一次。
7. 人们在一个订单中购买多少件商品?
为了回答这个问题,我们将把视线转移到另一组表:
order_product_prior,order_product_train。
以下是我使用到的代码:
# Concatenation of both tables. order_products_total = pd.concat([order_products_prior, order_products_train]) # Create amounts of item per order. frequency_per_number_of_order = order_products_total.groupby('order_id')['product_id'].count().value_counts() plt.figure(figsize=(20,8)) sns.barplot(x=frequency_per_number_of_order.index, y=frequency_per_number_of_order.values, color='mediumseagreen') plt.title('Amount of Items Per Order', fontsize=16) plt.ylabel('Order Counts', fontsize=16) plt.xlabel('Number of Items', fontsize=16) plt.xticks(rotation='vertical');
人们通常每次购买4件商品。
大多数人喜欢每次购买3到8件商品。
8. 这个数据集中有多少交易和不同的产品?
我们可以用以下代码来回答这个问题:
print('there are', order_products_total.shape[0], 'grocery products ordered') print('there are', len(order_products_total.order_id.unique()), 'order transactions') print('there are', len(order_products_total.product_id.unique()), 'unique products')
一共有33819106日用品订购。
3346083个订单交易。
49685种不同的产品。
9. 在所有订单中,有多少重复订单和非重复订单?比例是多少?
我们可以用以下代码来回答这个问题:
# Find out how many products have been reordered before. print(len(order_products_total[order_products_total.reordered == 1]), 'products have reordered before') print(len(order_products_total[order_products_total.reordered == 0]), 'products haven\'t reordered before') # Find out the ratio. print(len(order_products_total[order_products_total.reordered == 1])/order_products_total.shape[0], 'have reordered before') print(len(order_products_total[order_products_total.reordered == 0])/order_products_total.shape[0], 'haven\'t reordered before')
# Merging tables together. products_departments = products.merge(departments, left_on='department_id', right_on='department_id', how='left') products_departments_aisles = products_departments.merge(aisles, left_on='aisle_id', right_on='aisle_id', how='left') products_departments_aisles.head() # Counting how many items is in each product category. products_departments_aisles.groupby('department')['product_id'].count().reset_index().sort_values(by='product_id', ascending=False).head(10)
结果如下:
11. 人们买的最多的商品分别是什么?
为了回答这个问题,我们需要将products_departments_aisles,order_products_total表合并在一起。
# Merging products_departments_aisles and order_products_total. df = order_products_total.merge(products_departments_aisles, left_on='product_id', right_on='product_id', how='left') df.head() # Find out the top 15 items people purchased the most. top_15_products = df.product_name.value_counts(ascending=False).reset_index().head(15) top_15_products.columns = ['product_name', 'count'] top_15_products
以上为人们购买最多的15种商品
它们全部是水果/蔬菜
使用相同的逻辑,我们可以找出人们光顾最多的前15个货架和前15种商品类型。
# Finding top 15 aisles. top_15_aisles = df.aisle.value_counts(ascending=False).reset_index().head(15) top_15_aisles.columns = ['aisle_name', 'count'] top_15_aisles # Finding top 15 departments. top_15_department = df.department.value_counts(ascending=False).reset_index().head(15) top_15_department.columns = ['department_name', 'count'] top_15_department
12. 每件商品类型和货架的重复购买率是多少?
# Find out reorder ratio per department. reorder_ratio_per_dep = df.groupby('department')['reordered'].mean().reset_index() reorder_ratio_per_dep.columns = ['department', 'reorder_ratio'] reorder_ratio_per_dep.sort_values(by='reorder_ratio', ascending=False) # Find out reorder ration per aisle. reorder_ratio_per_aisle = df.groupby('aisle')['reordered'].mean().reset_index() reorder_ratio_per_aisle.columns = ['aisle', 'reorder_ratio'] reorder_ratio_per_aisle.sort_values(by='reorder_ratio', ascending=False)
蛋类在商品类型中的重复购买率最高
个人护理类在商品类型中的重复购买率最低
牛奶货架在货架分类中有最高的重复购买率
调味料货架在货架分类中有最低的重复购买率
接下来,我想为我的购物车推荐系统定义一个指标。人们通常喜欢将不同的通用指标用于评估。例如:
Precision
Recall
对于此项目,我决定使用Recall作为评估指标。这意味着客户购买的商品中有多少实际上是来自购物车推荐系统的?
例如,如果我向客户推荐5件商品,而他/她购买了4件,则意味着Recall= 0.80。换句话说,我推荐的商品中有80%出现在了客户的购物车中,而20%的商品是我向客户推荐的新商品。
购物车推荐系统
有多种构建推荐系统的方法,例如,基于内容的过滤和协作(基于项目或基于用户)过滤以及两者的结合。在这个项目中,我将探讨如何使用余弦相似度来构建购物车推荐系统,这是协同过滤下的一种方法。
推荐系统的设计是首先找出之前已重复消费的客户以及之前已被重复购买的商品。然后计算所有这些用户和产品之间的余弦相似度。然后生成5条建议的列表。
以下是如何查找之前已重复消费的客户并计算余弦相似度的代码:
# get the list of orders that have been reordered before reorders = order_products_total[order_products_total['reordered'] == 1] orders2 = orders[['order_id', 'user_id']] # merge to get user_id and product_id user_orders = reorders.merge(orders2, on='order_id') # filtering out the high volumn products that user reordered more than once user_orders['high_volume'] = (user_orders['product_id'].value_counts().sort_values(ascending=False)>1) high_volume = user_orders[user_orders['high_volume'] == True] # get a matrix of different high volume items that particular user purchased high_volume_users = high_volume.groupby(['user_id', 'product_name']).size().sort_values(ascending=False).unstack().fillna(0) # calculate similarity between each user cosine_dists = pd.DataFrame(cosine_similarity(high_volume_users),index=high_volume_users.index, columns=high_volume_users.index) cosine_dists.head()
这是为推荐系统定义功能。并尝试向与我们的目标客户具有相似购买历史的客户推荐5种商品。
def Recommender_System(user_id): ''' enter user_id and return a list of 5 recommendations. ''' u = high_volume.groupby(['user_id','product_name']).size().sort_values(ascending=False).unstack().fillna(0) u_sim = pd.DataFrame(cosine_similarity(u), index=u.index, columns=u.index) p = high_volume.groupby(['product_name','user_id']).size().sort_values(ascending=False).unstack().fillna(0) recommendations = pd.Series(np.dot(p.values,cosine_dists[user_id]), index=p.index) return recommendations.sort_values(ascending=False).head() # recommendation for customer id 175965. Recommender_System(175965)
以上为根据175965号客户的购买历史生成的五种推荐商品
评估
为了更好地解释,我以我自己的购买记录作为例子:
左侧是用户Ka之前购买的最多的前20个商品的列表。在右边,是我的推荐系统生成的5条推荐商品。如你所见,我推荐的5项中有4项符合Ka的前20条购买记录。也就是说我推荐的商品有80%的几率出现在该用户的前20个重复购买率最高的商品列表中。
使用与评估指标相同的逻辑。为了计算推荐系统的recall得分,我定义了一个功能来完成这项工作,以下是此功能的代码。数据框架太大,导致无法一次性处理,所以我将数据框架分成7个部分用于度量标准计算。
# filter 1000 users for calculation # because the dataframe is too large users = high_volume.user_id.unique().tolist() # calculate recall for the :1000 users def how_match(): res = [] for user in sorted(users)[:1000]: recommendations = Recommender_System(user) top_20_itmes = _[_.user_id == user].product_name.value_counts().head(20) recommendations_list = recommendations.index.tolist() top_20_items_list = top_20_itmes.index.tolist() res.append((len(set(recommendations_list) & set(top_20_items_list)))/5) return np.mean(res) # get metric for the :1000 users how_match() # calculate the mean of all the metric from all the Recommender notebooks. print('The Final Score for Metric is', (0.531 + 0.522 + 0.519 + 0.530 + 0.523 + 0.519 + 0.526)/7)
最终recall分数为0.524,这意味着我推荐的商品有52%的几率会进入用户的前20个重复购买率最高的商品列表中,这比从5万多种产品中随机猜测要好得多。大约一半的商品是我推荐给客户的新商品。
为了更好地了解推荐系统的效率和功能,我认为最好的方法是运行A / B测试实验。
我们能从这个项目中学到什么?
关于如何搭建推荐器的研究,类型和方式多种多样。你确实需要花费大量时间进行研究和学习。这没有捷径可走,你需要尝试不同的数据处理方法来对推荐系统进行比较。
为每个客户和商品创建虚拟特征后,你的数据框会变得很大。因此,你需要探索一些不同的方法,例如:矩阵,以使你的代码更易读或更省时,以便计算机进行计算。
如果你想系统的学习如何做数据驱动的电商增长、如何高效的利用大数据提高用户体验,为自己增添一段给美国电商公司做增长的工作经验,那么千万不要错过由MarTechApe与获得真格基金数千万投资的跨境电商赛客CIKERS官方合作的《电商增长企业实习计划》第4期!
戳下方图片👇,了解《电商增长企业实习计划》项目详情!
你将获得:
为知名电商“赛客CIKERS”(获真格基金数千万投资)拓展北美市场,积累跨境电商“出海”增长实战经验,增加相关工作经历,提升求职竞争力
跨境电商的一手实操经验、硅谷前沿的增长营销最佳战略
深度掌握北美各渠道广告投放,包括Facebook广告、Instagram购物广告、Google搜索/展示/购物广告、TikTok广告、Snapchat广告在内的广告投放策略
学会用Google Analytics进行电商网站的各类分析;学会使用电商必备工具Shopify来优化与客制化电商网站;学会利用A/B测试优化网页并提高转化率
学会通过分析增长营销的关键指标(CAC、LTV、弃购率等)获得商业洞察,优化电商业务广告回报率;学会通过CRM战略实现用户激活、留存、推荐等增长目标。
在项目期间,所有学员获得一对一简历修改服务及面试真题辅导,教你如何举一反三,将实习经验迁移到任何电商公司,并将实习项目加入简历,成为你的经历亮点与面试谈资,助你成功加盟你的电商Dream Company!
毕业学员均获得项目证书。优秀学员获得行业推荐信,并有机会获得赛客的全职或实习offer!
福利升级:训练营以往只内推成功从训练营中毕业的学生。但在疫情期间,所有电商增长实战训练营学员,均可获得全职或实习岗位的内推机会!
官方合作企业:
赛客科技CIKERS,世界一流球衣产品与功能完善的赛事管理平台。获真格基金数千万元估值的投资。项目借鉴了海外先进的校园体育文化(如美国 Intramural 和 NCAA 以及日本高中足球联赛),并结合了中国校园的特色,从美国常春藤起步,一直持之以恒改善技术和产品。CIKERS 作为经历了大浪淘沙成功壮大的创业公司,已经拓展了全国市场,并出海美国(www.XTeamwear.com)
产品理念:秉承Relentless Innovation to Enrich Sports理念,诚邀顶级运动品牌设计师参与设计,与 MIT 的材料科学家合作,走访上百足球专业人士,齐聚中、美、韩、西班牙、墨西哥、印尼等世界各地球衣发烧友,共同钻研赛客球衣的专业特性与实现方案,为发烧级产品注入高科技创新基因。矢志让每支热爱足球的球队都能穿上属于自己的专业装备。
在本次项目中,所有学员将直接上手使用赛客海外业务的电商平台、广告平台(包括官网、Shopify、Facebook、Google、Instagram、TikTok、Mailchimp等等),在导师的带领下,为赛客全力开启美国电商增长的战略之旅!
长按二维码,添加小助手为好友,回复“电商”,即可报名《电商增长企业实习计划》:
小助手(微信ID:yvonne91_wsn)