2018 年 12 月

第 33 卷,第 12 期

人工智能 - 市场篮分析

作者 Frank La La

Frank La Vigne毫无疑问,你多少接触过人工智能 (AI),即推荐购买,特别是在节假日购物季来临时。几乎每个联机零售商都会显示其他产品推荐,有时是在“经常一起购买”下,有时是在“购买了 X 的顾客也购买了 Y”标题下。 根据麦肯锡公司于 2013 年进行的一项调查 (bit.ly/2yK3Bu8),消费者在 Amazon 上完成的购买中有 35% 来自产品推荐算法。此外,不再只有零售商使用这种策略,联机流媒体服务(如 Netflix 和 YouTube)也使用复杂的推荐算法来延长观众关注流媒体的时间。

很显然,推荐系统影响着我们的日常生活。可以认为,这是消费者接触到的最普遍 AI 形式。在本专栏中,我将探讨基本形式的推荐系统(称为“市场篮分析”)。

市场篮分析

市场篮分析亦称为“关联分析”,这是一种基于以下理论的建模技术:如果你购买一组特定的商品,就更有可能购买另一组商品。例如,如果某人购买花生酱和面包,那么他/她极有可能想要购买果冻。不过,并非所有关系都一目了然。预知消费者行为不仅可以提高销售额,还能让零售商在与竞争对手的比拼中占据显著优势。严格来说,市场篮分析就是关联分析技术的一种应用,尽管许多联机文章和教程可能会将两者混为一谈。从我以前撰写过的其他机器学习技术的角度来看,市场篮分析是一款不受监督的学习工具,它几乎不需要执行功能设计工作,数据清理和准备的工作量也有限。实际上,可使用其他 AI 或数据科学工具,进一步探索通过市场篮分析慢慢收集到的见解。

尽管市场篮分析能够发掘隐藏的模式,但它解释起来相对容易,且无需掌握高等统计学或微积分学知识。不过,有几个术语和常规表示法需要了解一下。首先,“原因”和“结果”这两个概念称为“前因”和“后果”。在我前面提到的示例中,花生酱和面包是前因,果冻是后果。这种关系的正式表示法为,{花生酱,面包} -> {果冻},指明这些商品相关。另请注意,前因和后果都可以由多个商品组成。

执行市场篮分析时,必须使用三个重要的数学度量值:支持、提升和置信度。支持表示前因和后果一起在数据中出现的次数。为了简化此示例,假设关系如下:{花生酱} -> {葡萄果冻}。如果有 100 名顾客(每名顾客一次交易),假设场景如下:

  • 15 名顾客购买了花生酱
  • 13 名顾客购买了葡萄果冻
  • 11 名顾客购买了花生酱和葡萄果冻

支持表示商品一起在交易中出现的次数,在此示例中为 11/100(或 0.11)。若要用统计术语来解释,就是说任何给定交易同时包含花生酱和葡萄果冻的概率为 11%。置信度的计算方法为,用支持值 (0.11) 除以顾客单独购买葡萄果冻的交易概率,计算结果等于值 0.846。也就是说,顾客在购买葡萄果冻时一起购买了花生酱的概率为 85%。最后要说的是提升。它的计算方法为,用置信度值 (0.846) 除以顾客购买花生酱的概率。计算结果等于 5.64(四舍五入到小数点后两位)。

用一个简单的图表就可以更清楚地说明这一切,如图 1 所示。

图 1:支持值、置信度值和提升值

度量值 Formula
支持 P(花生酱和葡萄果冻) 0.11
置信度 支持/P(葡萄果冻) 0.846
提升 置信度/P(花生酱) 5.64(四舍五入)

 

市场篮分析实际效果

请记住上述这些指标,是时候尝试对实际数据集执行市场篮分析了。第一步是获取要分析的零售数据。幸运的是,加利福尼亚州大学欧文分校提供了数据集,其中包含一家总部位于英国的网站的交易数据。若要详细了解此数据集,请访问 bit.ly/2DgATFl。在首选平台上创建 Python 3 笔记本(我在以前的专栏 (msdn.com/magazine/mt829269) 中介绍过 Jupyter 笔记本)。创建空单元格,输入以下用于下载示例数据的代码,再执行单元格:

! curl http://archive.ics.uci.edu/ml/machine-learning-databases/00352/Online%20Retail.xlsx -o retail.xlsx

完成此操作后,在新单元格中输入下面的代码,以将 Excel 电子表格加载到 Pandas DataFrame,并打印出数据集中的列:

import pandas as pd
df = pd.read_excel('retail.xlsx')
print( df.columns)
The output will look something like this:
Index(['InvoiceNo', 'StockCode', 'Description', 'Quantity', 'InvoiceDate',
       'UnitPrice', 'CustomerID', 'Country'],
      dtype='object')

尽管市场篮分析不要求进行严格的数据处理,但最好删除无关记录(如包含空发票号和已取消订单的记录)。此外,还可以删除产品说明中不必要的空格,并将所有发票号都转换为字符串,这些做法也是有裨益的。为此,可以运行下面的代码:

df['Description'] = df['Description'].str.strip()
df.dropna(axis = 0, subset=['InvoiceNo'], inplace = True)
df['InvoiceNo'] = df['InvoiceNo'].astype('str')
df = df[~df['InvoiceNo'].str.contains('C')]

现在,输入下面的代码,以聚合数据并从国家/地区级别来查看数据:

df.groupby('Country').count().reset_index().sort_values(
  'InvoiceNo', ascending = False).head()

接下来,我将重新排列数据,即对每个产品进行独热编码,且每行一个交易。独热编码是一种数据转换技术,用于将分类值转换为列,并在有分类值的位置输入值 1。此外,我还将把数据集的范围限制为一个国家/地区(在此示例中为法国),以便在单独市场中比较消费者行为。为此,请输入并运行下面的代码(请注意单元格输出中 basket_uk 数据帧的形状;独热编码将列数从 8 列扩展为 4175 列):

basket_fr = (df[df['Country']=="France"]
          .groupby(['InvoiceNo', 'Description'])['Quantity']
          .sum().unstack().reset_index().fillna(0)
          .set_index('InvoiceNo'))
basket_fr.head(10)

快速浏览结果后发现我的独热编码存在问题。往下看,第六个商品在第二列中的值为 24.0。我是要在数据中显示 1 或 0,而不是数量。因此,我需要找到所有非零值,并将它们转换为 1。若要解决此问题,请运行下面的代码(注意到,24.0 已转换为 1):

def sum_to_boolean(x):
  if x<=0:
    return 0
  else:
    return 1
basket_fr_final = basket_fr.applymap(sum_to_boolean)
basket_fr_final.head(10)

我将使用 MLXTEND (rasbt.github.io/mlxtend) 进一步分析数据。MLXTEND 是实用工具的 Python 库,用于执行常见数据科学任务,其中包括市场篮分析。若要在笔记本中安装此库,请运行下面的代码:

! pip install mlxtend

安装 MLXTEND 包后,是时候从 MLXTEND 中导入相关库了,如下所示:

from mlxtend.frequent_patterns import association_rules
from mlxtend.frequent_patterns import apriori

在新单元格中,输入下面的代码,以查看支持值至少为 6% 的商品集:

frequent_itemsets_fr = apriori(basket_fr_final, min_support = 0.06,
  use_colnames = True)
frequent_itemsets_fr.sort_values('support', ascending = False).head()

确定关键商品集后,我现在可以应用关联规则库,以发现顾客的购买行为。输入并运行下面的代码:

a_rules = association_rules(frequent_itemsets_fr, metric = "lift",
  min_threshold = 1)
a_rules.sort_values('lift',ascending = False)

按提升值排序的结果应如图 2**** 所示,揭示了法国顾客在此网站上的购买模式。快速浏览结果后发现,购买了儿童餐具 SPACEBOY 的顾客也购买了儿童餐具 DOLLY GIRL,购买了一种颜色闹钟的顾客也购买了另一种颜色闹钟。至于可操作见解,我可以建议网站所有者提供针对不同性别的餐具的捆绑优惠,以及多色闹钟的捆绑优惠。

法国顾客的关联规则
图 2:法国顾客的关联规则

但请注意,此列表是按提升值(而不是发生次数)排序。如果产品不够受欢迎,引入新捆绑或产品优惠可能就没有意义。若要了解这些餐具商品的受欢迎程度,请输入以下 Python 代码:

print( basket_fr_final['CHILDRENS CUTLERY SPACEBOY'].sum())
print( basket_fr_final['CHILDRENS CUTLERY DOLLY GIRL'].sum())

结果并不令人满意;SPACEBOY 的结果仅为 27,而 DOLLY GIRL 的结果也仅为 28。略作探索后,我发现一条结果更令人满意一些的关联规则。其实,关联规则索引 50 (SET/20 RED RETROSPOT PAPER NAPKINS) 是红色纸杯和红色纸盘的前因。输入下面的代码,以查看卖出了多少商品:

basket_fr_final['SET/20 RED RETROSPOT PAPER NAPKINS'].sum()

虽然数字很低,但购买一次性杯子的顾客想要购买配套的纸盘和餐巾纸是理所当然的。有洞察力的零售商很有可能会将这些商品打包成捆绑优惠,以吸引顾客购买。

眼尖的读者会注意到,在生成的数据帧中还有两个指标:“利用”和“确信”。这些是在执行市场篮分析时要考虑的其他值。若要详细了解这方面的信息,可以浏览所谓的“备用兴趣度量值”。 可以先从便捷的维基百科入手 (bit.ly/2AECRNh)。

回想一下,当我聚合国家/地区级数据时,英国的发票数远远超过其他任何国家/地区。或许通过更多可用的原始数据来调查顾客行为,可以获取更多见解。接下来将探索此数据,具体方法是在新单元格中输入并运行下面的代码,如下所示:

basket_uk = (df[df['Country']=="United Kingdom"]
          .groupby(['InvoiceNo', 'Description'])['Quantity']
          .sum().unstack().reset_index().fillna(0)
          .set_index('InvoiceNo'))
basket_final_uk = basket_uk.applymap(sum_to_boolean)
frequent_itemsets_uk = apriori(basket_final_de, min_support = 0.06,
  use_colnames = True)
a_rules_uk = association_rules(frequent_itemsets_uk, metric = "lift",
  min_threshold = 1)
a_rules_uk.sort_values('lift',ascending = False).head()

对于英国,由于数据集更大,因此执行时间也更长。还注意到,结果大不相同。这是因为数据更多改变了分析,还只是因为顾客偏好因市场而异?或者是因为零售商在不同市场销售的产品不同?这些是在整个分析过程中必须要理解的各种变量。在此示例中,除了联机零售商的总部位于英国以外,几乎没有其他任何上下文。不过,在实际项目中,与企业的行业专家进行交互是数据分析项目取得成功的关键要素。

总结

在本文中,我探讨了如何使用市场篮分析来发掘消费者行为模式。市场篮分析属于范畴更大的关联分析,各大公司使用它来激励顾客购买更多商品,并延长观众在流媒体平台上观看流媒体的时间。

对于希望探索数据科学的个人和组织,市场篮分析是绝佳起点。就数学能力而言,它的入门门槛低。事实上,只需掌握简单除法和基础概率理论即可。对于初学者来说,它是一个容易探索的问题领域,并为开始向企业应用 AI 提供了绝佳契机。尽管如此,也别傻乎乎地认为它在执行数据科学任务或为公司领导力增值方面的作用不大。它可能会对企业盈亏产生重大影响。


Frank La Vigne 是 Microsoft 的 AI 技术解决方案专家,他通过充分利用分析后的数据和 AI 来帮助公司实现更大价值。他还共同主持 DataDriven 播客。他定期在 FranksWorld.com 上发表博客,你还可以在他的 YouTube 频道“Frank’s World TV”(FranksWorld.TV) 中看到他。

衷心感谢以下技术专家对本文的审阅:Andy Leonard (Enterprise Data & Analytics)


在 MSDN 杂志论坛讨论这篇文章