数据驱动业务的艺术(一)

原文:annas-archive.org/md5/42d9640be578d0082a7e1589f07dd9bf

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

数据科学最有价值的贡献之一就是帮助企业做出正确的决策。理解这两个截然不同的领域及其与激烈竞争市场的交汇,要求你获取尽可能多的指导。

数据驱动商业的艺术是你获得数据驱动视角的宝贵指南,同时也是利用机器学习ML)的力量来指导你商业决策的工具书。本书为公司内部多个角色提供了共同的讨论基础。

你将首先学习如何使用 Python 及其众多库进行机器学习(ML)。有经验的数据科学家可能会想跳过这个简短的介绍,但很快你就会进入书籍的核心内容,探索 Python 在机器学习中的多种应用方式,特别是如何通过现实世界中的商业问题,独立解决它们,从而将 ML 应用于商业决策领域。随着进展,你将获得实践性洞察,了解机器学习对你的业务能提供的价值,并掌握应用各种经过验证的机器学习方法的技术能力。

在本书结束时,你将学会如何基于数据驱动的方法制定商业决策,并掌握应用这些知识于现实世界的 Python 技能。

本书的目标读者

本书适用于数据科学家、机器学习工程师与开发者、数据工程师以及商业决策者,他们希望将数据科学应用于业务流程优化,并开发出能够在市场营销、销售、定价、客户成功、广告技术等领域实施数据科学项目所需的技能。其他希望探索数据科学如何改善商业运作的专业人士,以及那些希望通过强有力的商业案例支持技术提案的技术人员,也将从本书中受益。

本书内容

第一章使用 Python 分析与可视化数据,作为使用 pandas 和 Seaborn 进行数据分析的入门。你将学习如何转换、可视化和分析数据,这些都是本书贯穿始终的基础工具。你将通过基于现实生活应用的实例,接触到这些库的使用。

第二章在商业运营中使用机器学习,介绍了 scikit-learn,这是使用 Python 应用机器学习算法最受欢迎的框架。你将学习机器学习的基本概念,如何进行训练以及监督式和无监督式算法的推理。这些概念将通过练习得到巩固,并在后续章节中应用到优化各种商业应用的实际案例中。

第三章通过市场洞察寻找商业机会,聚焦于使用 Python 和搜索趋势分析来从搜索引擎数据中获取有价值的信息。你将学习如何使用 Python 获取搜索引擎趋势信息,构建并可视化结果以验证假设,扩展查询并分析结果内容,使用 NLP 和 scikit-learn 分析结果。

第四章通过联合分析了解客户偏好,将向你介绍联合分析方法,分析用户偏好调查数据,应用方法确定用户如何权衡每个属性,并预测新组合的排名。

第五章通过价格需求弹性选择最佳价格,将向你介绍价格弹性概念,并利用该概念通过销售数据找到不同产品的最佳价格。在本章结束时,你将能够找到最大化收入的价格,并理解需求曲线。

第六章产品推荐,展示了创建产品推荐和执行市场篮子分析的两种方法。你将了解协同过滤和先验算法,并学习如何实现它们,以使用销售数据创建产品推荐。

第七章预测客户流失,将展示如何使用 Python 和 scikit-learn 预测消费者行为中的微妙变化。

第八章通过客户细分进行用户分组,将帮助你了解和实践可以应用于建模数据的方法,以及哪些无监督机器学习方法可以用来发现这些群体,并找出它们的关键特征。最后,你将学习如何通过销售分析这些细分群体,如何通过使用 Seaborn 在清晰定义的仪表板中传达这些发现。

第九章利用历史 Markdown 数据预测销售额,将指导你使用 pandas 和 Seaborn 分析促销活动对历史时间序列销售数据的影响,并使用 scikit-learn 优化库存和存储,以分析促销活动的影响并优化存储成本。

第十章网站分析优化,将向你展示如何使用 Python 分析数字营销数据,通过分析数字广告活动的结果,基于客户生命周期价值预测计算投资回报,并优化程序化广告平台上的投资。

第十一章在商业中创建数据驱动的文化,与商业领袖沟通,了解他们如何应用数据科学和分析来改进业务运营。我们将与多位首席数据官和首席数据科学家进行交流,收集他们在多个公司中应用这些方法的具体实例。

为了充分利用本书

本书涵盖的软件/硬件操作系统要求
Python 3.xWindows、macOS 或 Linux

如果您使用的是本书的数字版,我们建议您亲自输入代码,或从本书的 GitHub 仓库中获取代码(相关链接在下一节提供)。这样做可以帮助您避免因复制粘贴代码而导致的潜在错误。

下载示例代码文件

您可以从 GitHub 上下载本书的示例代码文件,网址为 github.com/PacktPublishing/The-Art-of-Data-Driven-Business-Decisions。如果代码有更新,将会在 GitHub 仓库中进行更新。

我们还提供了其他代码包,您可以在我们的书籍和视频丰富目录中找到,网址为 github.com/PacktPublishing/。快去看看吧!

使用的约定

本书中使用了一些文本约定。

文本中的代码:表示文本中的代码词汇、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 账号。例如:“将下载的 WebStorm-10*.dmg 磁盘映像文件挂载为系统中的另一个磁盘。”

代码块的格式如下:

results_df = pd.DataFrame(results).dropna()
results_df.columns = ['client','slope','std']
results_df.index = results_df.client
results_df = results_df.drop(['client'],axis=1)
results_df.head()

当我们希望引起您对代码块中特定部分的注意时,相关的行或项会以粗体显示:

df.columns.tolist()
>>> ['period', 'sub_market', 'client_class', 'division', 'brand','cat', 'product', 'client_code', 'client_name', 'kgs_sold']

任何命令行输入或输出将如下所示:

!pip install --upgrade openpyxl scikit-surprise

粗体:表示新术语、重要单词或您在屏幕上看到的词汇。例如,菜单或对话框中的单词通常以粗体显示。举个例子:“从管理面板中选择系统信息。”

提示或重要说明

如下所示。

联系我们

我们非常欢迎读者的反馈。

一般反馈:如果您对本书的任何内容有疑问,请通过电子邮件联系我们,邮箱地址为 customercare@packtpub.com,并在邮件主题中注明书名。

勘误:尽管我们已经尽力确保内容的准确性,但仍难免会出现错误。如果您发现本书中的错误,我们非常感谢您报告给我们。请访问 www.packtpub.com/support/errata 并填写表单。

盗版: 如果您在互联网上发现我们作品的任何形式的非法复制,请告知我们其位置或网站名称。请通过 copyright@packt.com

如果您有兴趣成为作者:如果您在某一主题上有专业知识,并且有意撰写或为书籍做出贡献,请访问 authors.packtpub.com

分享您的想法

一旦您阅读了《数据驱动业务的艺术》,我们很乐意听取您的想法!请点击此处直接转到亚马逊评论页面 并分享您的反馈。

您的评价对我们和技术社区至关重要,将帮助我们确保我们提供的内容质量卓越。

下载本书的免费 PDF 版本

感谢您购买本书!

您喜欢随时随地阅读,但不能随身携带印刷书籍吗?

您购买的电子书是否与您选择的设备不兼容?

别担心,现在您每购买一本 Packt 书籍,都可以免费获得该书的无 DRM PDF 版本。

可在任何设备上的任何地方阅读。直接从您喜爱的技术书籍中搜索、复制和粘贴代码到您的应用程序中。

福利不止如此,您还可以独享折扣、新闻通讯和每日优质免费内容

按照以下简单步骤获取这些好处:

  1. 扫描下方的 QR 码或访问以下链接

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_QR_Free_PDF.jpg

packt.link/free-ebook/9781804611036

  1. 提交您的购书证明

  2. 就这样!我们将直接将您的免费 PDF 和其他好处发送至您的电子邮件

第一部分:使用 Python 进行数据分析与预测

第一部分将介绍主要工具,使用 Python 分析、预测和可视化数据。核心框架如 Pandas、Scikit-learn 和 Seaborn 将被介绍,确保您学会如何正确探索和操作数据,了解机器学习算法的基础以预测和聚类数据,并进行有效的数据可视化来讲述数据故事。

本部分涵盖以下章节:

  • 第一章使用 Python 分析和可视化数据

  • 第二章在业务运营中使用机器学习

第一章:使用 Python 进行数据分析和可视化

高级分析和数据科学如今在大多数企业中发挥着重要作用。它帮助组织跟踪、管理和收集绩效指标,从而改善组织决策。企业经理可以利用创新的分析和机器学习技术帮助他们决定如何最佳地与客户互动、提升企业绩效并增加销售额。数据科学和分析可以用于创建以用户为中心的产品,并做出明智的决策。通过比较不同的产品特性、研究消费者反馈和市场趋势,企业能够开发能够吸引客户并保持长期吸引力的商品和服务。

本书面向所有希望了解数据科学、高级分析和机器学习技术的方法的人,特别是针对那些研究由这些方法影响的商业案例的人。这些案例大多基于真实的应用案例,并展示了这些方法在不同行业的公司中产生的积极影响。因此,无论是那些希望通过数据科学提升技能的资深商业分析师,还是希望找到可以应用于最大化特定操作的管理者,都会从本书中讨论的示例中受益。

在本章中,我们将介绍本书中将用来管理数据、操作数据和可视化数据的初步组件。具体来说,我们将讨论以下内容:

  • 数据科学在商业中的应用及其与业务分析师或数据分析师等角色的主要区别

  • 使用诸如 NumPy 等统计编程库来应用矩阵代数和统计方法

  • 使用 pandas 存储数据,pandas 是一个广泛用于数据科学领域的数据分析和处理库

  • 使用 Seaborn 进行可视化,并了解不同类型的图表如何在不同场景下使用

接下来,我们将讨论您需要满足的技术要求,以便能够跟随本章中的示例。

技术要求

要能够跟随本章的步骤,您需要满足以下要求:

  • 一个运行 Python 3.7 及以上版本的 Jupyter notebook 实例。如果您有 Google Drive 帐户,也可以使用 Google Colab notebook 来运行这些步骤。

  • 基本的数学和统计学概念理解。

在商业中使用数据科学和高级分析

大多数时候,关于数据科学家与商业分析师之间的区别会引发讨论,因为这两个角色都专注于从数据中获取洞察。从某种角度看,数据科学可以被视为通过分析原始数据背后的模式来进行预测。商业智能是回顾性的,发现过去和当前的趋势,而数据科学则是前瞻性的,预测未来的趋势。

商业决策在很大程度上依赖于数据科学和先进的分析方法,因为这些方法帮助管理者理解决策如何影响结果。因此,数据科学家越来越需要将常见的机器学习技术与对潜在因果关系的了解结合起来。这些发展催生了“决策科学家”这一职位,这是一位专注于利用技术支持业务和决策的技术专家。然而,与“数据科学家”或“大数据科学家”这一职位相比,“决策科学家”这一职位的含义则更加深刻。

很多时候,商业分析师、数据科学家和数据分析师的角色容易混淆。商业分析师更可能解决业务问题并提出解决方案,而数据分析师通常更多地直接与数据本身打交道。虽然这两个职位都需求量大且通常薪酬丰厚,但数据科学更注重预测,因为它分析的是原始数据中隐藏的模式。

使用 NumPy 进行统计学和代数运算

NumPy 是一个用于处理数组的 Python 库。此外,它还提供了处理矩阵、傅里叶变换和线性代数领域的函数。NumPy 现在支持大规模、多维数组和矩阵,并且提供了一系列复杂的数学操作,可以在这些数组上执行。这些操作使用大量复杂的数学函数来处理庞大的多维数组和矩阵,并进行机器学习中的基本科学计算,因此非常有用。它提供了 n 维数组,这是一个简单而有效的数据结构。学习 NumPy 是每个 Python 数据科学家入门的第一步,因为它构成了几乎所有工具包功能的基础。

数组是一个由所有相同类型的值组成的网格,通过一个非负整数元组来索引,这是 NumPy 使用的基本构建块。类似于代数中矩阵的维度定义,数组的秩由其维度的数量决定。一个数字元组,表示数组在每个维度上的大小,构成了数组的形状:

import numpy as np
arr = np.array([1, 2, 3, 4, 5])
print(arr)
print(type(arr))

NumPy 数组是一个容器,可以容纳一定数量的元素,这些元素必须是相同类型的,正如之前所指定的那样。大多数数据结构都使用数组来执行其算法。就像你可以切片一个列表一样,你也可以切片一个 NumPy 数组,但它支持多维切片。与索引类似,切片 NumPy 数组会返回一个原始数组的视图。

在 Python 中,切片意味着从一个给定的索引到另一个给定的索引选择元素。我们可以通过使用 [start:end] 对数组进行切片,选择数组中的某些元素,其中 start 表示开始的元素位置,end 表示结束的位置。我们还可以使用 [start:end:step] 来定义步长:

print('select elements by index:',arr[0])
print('slice elements of the array:',arr[1:5])
print('ending point of the array:',arr[4:])
print('ending point of the array:',arr[:4])

有三种不同的索引技术:字段访问、基本切片和高级索引。基本切片是 Python 基本切片概念的 n 维扩展。通过传递 startstopstep 参数给内建的 slice 函数,可以创建一个 Python 切片对象。切片使得编写清晰、简洁的代码成为可能。当一个可迭代元素按位置被“索引”时,它指的是该元素在可迭代对象中的位置。根据元素的索引,从一个可迭代对象中获取元素子集被称为“切片”。

要合并(拼接)两个数组,我们必须通过使用 np.concatenate() 函数将两个数组中的每个元素复制到 result 中:

arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.concatenate((arr1, arr2))
print(arr)

数组也可以使用 NumPy 的堆叠方法进行连接。我们可以沿第二个轴将两个 1D 数组合并,堆叠在一起,这个过程称为堆叠。stack() 方法接收一个我们希望连接的数组列表,并指定轴:

arr = np.stack((arr1, arr2), axis=1)
print(arr)

axis 参数可以用来引用我们想要进行拼接的轴:

arr = np.stack((arr1, arr2), axis=0)
print(arr)

NumPy 的 mean() 函数用于计算指定轴上的算术平均值:

np.mean(arr,axis=1)

你需要使用 NumPy 的 mean() 函数并设置 axis=0 来计算按列的平均值。要按行计算平均值,应该使用 axis=1

np.mean(arr,axis=0)

在接下来的章节中,我们将介绍 pandas,一个用于数据分析和操作的库。pandas 就像 NumPy 一样,是数据科学中最广泛使用的 Python 库之一。它提供了高性能、易于使用的数据分析工具。与 NumPy 提供的多维数组对象不同,pandas 提供了一种称为 DataFrame 的内存中的二维表对象。

使用 pandas 存储和操作数据

pandas 是一个开源工具包,建立在 NumPy 之上,为 Python 程序员提供高性能、易用的数据结构和数据分析能力。它使得快速分析、数据准备和清洗成为可能。它在性能和产出上都表现卓越。

pandas 是一个数据分析的包,因其包含许多内置的辅助功能,通常用于金融时间序列数据、经济数据以及任何形式的表格数据。对于科学计算,NumPy 是管理大型多维数组的快速方法,且可与 SciPy 和 pandas 包一起使用。

通过将字典传递给DataFrame构造函数,可以从字典构建一个 DataFrame:

import pandas as pd
d = {'col1': [1,5,8, 2], 'col2': [3,3,7, 4]}
df = pd.DataFrame(data=d)
df

pandas 的groupby函数是一个强大而多功能的函数,允许我们将数据拆分成单独的组,以便进行计算和更好的分析:

df = pd.DataFrame({'Animal': ['Dog', 'Dog',
                              'Rat', 'Rat','Rat'],
                   'Max Speed': [380., 370., 24., 26.,25.],
                   'Max Weight': [10., 8.1, .1, .12,.09]})
df

“拆分”、“应用”和“合并”这三步让我们最容易记住“groupby”操作的功能。拆分是指根据特定的列将数据分成不同的组。举例来说,我们可以将销售数据按月分组:

df.groupby(['Animal']).mean()

pandas 的groupby技术非常强大。通过值计数,你可以根据某一列进行分组,并按该列的值对另一列进行计数。我们可以使用groupbyvalue_counts来统计每个人完成的活动次数:

df.value_counts()

我们还可以使用aggregate()方法对行进行聚合,这允许你对 DataFrame 的某一轴应用一个或多个函数名称。默认值是 0,即索引(行)轴。需要注意的是,agg()方法是aggregate()方法的别名:

df.agg("mean", axis="rows",numeric_only=True)

我们还可以传递多个函数用于每一列的选择:

df.agg({'Max Speed' : ['sum', 'min'], 'Max Weight' : ['mean', 'max']})

在给定轴上的分位数是通过quantile()方法确定的。默认情况下是按行轴来计算。当指定列轴(axis='columns')时,quantile()方法会按列计算分位数,并返回每行的均值。以下代码将为我们提供整个 DataFrame 的 10%分位数:

df.quantile(.1)

我们还可以传递一个分位数组:

df.quantile([.1, .5])

pivot()函数用于根据提供的索引或列值重塑给定的 DataFrame,并且是我们可以用来改变数据的不同类型函数之一。此函数不支持数据聚合;多个值会在列中产生MultiIndex

df = pd.DataFrame(
{'type': ['one', 'one', 'one', 'two', 'two',  'two'],
 'cat': ['A', 'B', 'C', 'A', 'B', 'C'],
'val': [1, 2, 3, 4, 5, 6],
'letter': ['x', 'y', 'z', 'q', 'w', 't']})
df.pivot(index='type', columns='cat', values='val')

数据透视表是 pandas 最强大的功能之一。数据透视表让我们从数据中提取洞见。pandas 提供了一个类似的功能,叫做pivot_table()。它是一个简单的函数,但能非常快速地产生强大的分析结果。

接下来的步骤是学习如何可视化数据,以便进行恰当的故事讲述和解释。

使用 Seaborn 可视化模式

Seaborn 是一个基于 Matplotlib 的 Python 数据可视化库。它提供了一个精致的绘图工具,用于创建引人注目且具有教育意义的统计图形。

Seaborn 和 Matplotlib 的主要区别在于 Seaborn 如何处理 pandas DataFrame。使用简单的函数集,Python 可以提供美丽的图形。当处理 DataFrame 和数组时,Matplotlib 表现出色,它将坐标轴和图形视为对象,并提供了几种有状态的绘图 API。

在这里,我们将开始使用“tips”数据集进行示例,该数据集包含数字和分类变量的混合:

import seaborn as sns
import matplotlib.pyplot as plt
tips = sns.load_dataset("tips")
f, ax = plt.subplots(figsize=(12, 6))
sns.scatterplot(data=tips, x="total_bill", y="tip", hue="time")

在前面的代码片段中,我们导入了 Seaborn 和 Matplotlib;后者允许用户控制图表创建的某些方面,例如图形大小,我们将其定义为 12x6 英寸。这创建了 Seaborn 将放置可视化内容的布局。

我们使用scatterplot()函数来创建一个点的可视化,其中X轴表示total_bill变量,Y轴表示tip变量。在这里,我们使用hue参数根据time分类变量为不同的点上色,从而允许我们用分类维度绘制数值数据:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_1.jpg

图 1.1:Seaborn 散点图,颜色取决于分类变量

生成的图形显示了根据我们指定的颜色代码(在我们这种情况下是收到的小费、它们与总账单金额的关系以及是否为午餐或晚餐时段)分布的数据。

我们可以得出的解释是,总账单金额和收到的小费之间可能存在线性关系。但如果我们仔细观察,会发现最高的账单总额出现在晚餐时段,同时也导致了最高的小费值。

在商业领域,这些信息可能非常有用,但首先需要通过适当的假设检验方法进行验证,可以使用 t 检验来验证这些假设,再加上线性回归分析来得出总金额与小费分布之间存在关系的结论,同时考虑到发生这一过程的时间差异。我们将在下一章中探讨这些分析。

我们现在可以看到,简单的探索图如何帮助我们构建假设,并在此基础上做出决策,从而更好地改进商业产品或服务。

我们还可以将色调和样式分配给不同的变量,这样就能独立地改变颜色和标记。这使我们可以在同一个图表中引入另一个分类维度,在 Seaborn 中可以使用style参数,根据我们参考的分类变量分配不同类型的标记:

f, ax = plt.subplots(figsize=(12, 6))
sns.scatterplot(data=tips, x="total_bill", y="tip", hue="day", style="time")

前面的代码片段将创建一个 12x6 英寸的布局,并添加关于time分类变量的信息,如下图所示:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_2.jpg

图 1.2:Seaborn 散点图,颜色和形状依赖于分类变量

这种类型的图表允许我们将大量信息集成到单个图中,这可能是有益的,但也可能导致信息过载,一次难以消化。重要的是始终考虑我们想要展示的信息的理解,使利益相关者能够一目了然地看到关系。

在这里,一开始很难看出任何对一周中哪些天进行解释的信息。这是因为已经显示了大量信息。通过其他类型的分析,如统计测试、相关性和因果关系,可以获得不能仅通过观察图表获得的这些差异。

另一种通过 Seaborn 创建的图形添加更多维度的方式是将数值变量表示为散点图中点的大小。可以将数值变量分配给 size,以对点的面积应用语义映射。

我们可以通过大小控制标记区域的范围,并将 legend 参数设置为 full,以强制每个唯一值都出现在图例中:

f, ax = plt.subplots(figsize=(12, 6))
sns.scatterplot(
    data=tips, x="total_bill", y="tip", hue="size", 
    size="size", sizes=(20, 200), legend="full"
)

上述代码片段创建了一个散点图,其中点的大小和颜色取决于 size 变量。这对于在这类图中再添加另一个数值维度非常有用:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_3.jpg

图 1.3:Seaborn 散点图,大小依赖于第三变量

表示数据的另一重要方式是查看时间序列信息。我们可以使用 Seaborn 包显示时间序列数据,无需对数据进行任何特殊处理。

在下面的示例中,我们正在创建一个带有日期的 pandas DataFrame,使用 Matplotlib 创建一个 15 x 8 英寸的图形,然后使用 Seaborn 的 lineplot 函数显示信息:

df = pd.DataFrame({"Dates":
['01/01/2019','01/02/2019','01/03/2019','01/04/2019',
'01/05/2019','01/06/2019','01/07/2019','01/08/2019'],
"Count": [727,716,668,710,718,732,694,755]})
plt.figure(figsize = (15,8))
sns.lineplot(x = 'Dates', y = 'Count',data = df)

上述示例创建了一个将日期放在 x 轴上,count 变量放在 y 轴上的精彩图表:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_4.jpg

图 1.4:Seaborn 时间轴线图

在下面的示例中,我们将加载一个称为 FMRI 数据集的预定义数据集,其中包含时间序列数据。

首先,我们将加载一个包含长格式数据的示例数据集,然后绘制不同事件和地区的响应。为此,我们将创建一个 15 x 8 英寸的 Matplotlib 图形,并使用 lineplot 函数显示信息,使用 hue 参数显示关于地区的分类信息,并使用 style 参数显示关于事件类型的分类信息:

fmri = sns.load_dataset("fmri")
f, ax = plt.subplots(figsize=(15, 8))
sns.lineplot(x="timepoint", y="signal", hue="region", style="event",data=fmri)

上述代码片段创建了一个展示信息的图表,允许我们研究变量随时间变化的情况,依据数据的不同类别特征:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_5.jpg

图 1.5:Seaborn 线图与置信区间

Seaborn lineplot 函数的一个特点是它展示了在 95% 置信区间内所有数据点的置信区间;实线表示均值。这种方式在展示包含多个数据点的时间序列数据时非常有用。趋势可以通过均值来可视化,同时也能让我们感知数据的分散程度,这在分析行为模式时是非常重要的。

我们可以通过条形图来可视化数据。Seaborn 使用 barplot 函数来创建条形图:

f, ax = plt.subplots(figsize=(12, 6))
ax = sns.barplot(x="day", y="total_bill", data=tips,ci=.9)

上述代码使用 Matplotlib 创建了一个 12 x 6 英寸的图形,其中生成了 Seaborn 条形图。在这里,我们将在 x 轴上显示日期,在 y 轴上显示总账单,显示置信区间作为触须出现在条形上方。上面的代码生成了以下图表:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_6.jpg

图 1.6:Seaborn 条形图

在上述图表中,我们无法详细看到触须,因为数据的分散程度非常小。我们可以通过绘制一组垂直条形图并按两个变量进行分组,来更好地查看这一点:

f, ax = plt.subplots(figsize=(12, 6))
ax = sns.barplot(x="day", y="total_bill", hue="sex", data=tips)

上述代码片段在 12 x 6 英寸的 Matplotlib 图形上创建了一个条形图。不同之处在于我们使用 hue 参数来显示性别差异:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_7.jpg

图 1.7:Seaborn 条形图与类别数据

从这张图中可以得出的一个结论是,女性的总账单通常低于男性,只有星期六是均值存在差异的那一天,尽管在分散程度上有一个更低的基准点。

我们可以通过使用 catplot 向可视化中添加另一个类别维度,将 barplot 与 FacetGrid 结合来创建多个图表。这允许我们在额外的类别变量中进行分组。使用 catplot 比使用 FacetGrid 创建多个图表更安全,因为它确保了不同小面板之间变量顺序的同步:

sns.catplot(x="sex", y="total_bill",hue="smoker", col="time",data=tips, kind="bar",height=6, aspect=.7)

上述代码片段生成了一个包含不同条形图的类别图。注意,图表的大小是通过 heightaspect 变量来控制的,而不是通过 Matplotlib 图形:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_8.jpg

图 1.8:Seaborn 条形图与两个类别变量

在这里,我们可以看到在午餐时间,男性吸烟者的平均值低于非吸烟者,而女性吸烟者的平均值高于非吸烟者。这种趋势在晚餐时反转,晚餐时男性吸烟者的平均值高于女性吸烟者。

在分析模式时使用直方图分析趋势是一种很好的工具。我们可以使用 Seaborn 的hisplot函数。在这里,我们将使用penguins数据集,并创建一个 Matplotlib 图形,大小为 12 x 6 英寸:

penguins = sns.load_dataset("penguins")
f, ax = plt.subplots(figsize=(12, 6))
sns.histplot(data=penguins, x="flipper_length_mm", bins=30)

前面的代码创建了一个分组数据中翻转长度的直方图,分为 30 个箱子:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_9.jpg

图 1.9: Seaborn 直方图绘图

在这里,我们可以添加一个核密度线估计,软化直方图,提供关于数据分布形状的更多信息。

以下代码添加了kde参数,设为True以显示此行:

f, ax = plt.subplots(figsize=(12, 6))
sns.histplot(data=penguins, x="flipper_length_mm", kde=True)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_10.jpg

图 1.10: 使用 KDE 估计密度的 Seaborn 直方图绘图

在这里,我们可以看到数据接近一些叠加的标准分布,这可能意味着我们正在观察不同类型的数据。

我们还可以通过在分类变量species上使用hue参数向图形添加更多维度:

f, ax = plt.subplots(figsize=(12, 6))
sns.histplot(data=penguins, x="flipper_length_mm", hue="species")

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_11.jpg

图 1.11: 使用分类数据的 Seaborn 直方图绘图

正如我们所怀疑的那样,我们正在观察企鹅的不同物种的叠加,每种物种都具有正态分布,尽管有些比其他物种更倾斜。

pairplot函数可用于绘制数据集中的多个成对的双变量分布。对角线图是单变量图,显示了 DataFrame 中变量(n, 2)组合的关系作为一组图。pairplot用于确定最显著的集群或最佳的特征组合以解释两个变量之间的关系。在我们的数据集中构建线性分离或一些简单的线条也有助于创建一些基本的分类模型:

sns.pairplot(penguins,height=3)

前面的代码创建了一个数据的pairplot,其中每个框的高度为 3 英寸:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_12.jpg

图 1.12: 变量关系和选择特征的直方图

变量名称显示在矩阵的外部边界上,使其易于理解。每个变量的密度图显示在对角线上的框中。每个变量之间的散点图显示在左下角的框中。

我们还可以使用hue参数将分类维度添加到可视化中:

sns.pairplot(penguins, hue="species", diag_kind="hist",height=3)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_13.jpg

图 1.13: 带分类标签的变量关系和直方图

尽管非常有用,但这个图表可能计算开销很大,这个问题可以通过仅查看部分变量而非整个数据集来解决。

我们可以通过减少显示的图形数量来缩短渲染可视化所需的时间。我们可以通过指定每个轴上要显示的变量类型来实现这一点,如下代码块所示:

sns.pairplot(
    penguins,
    x_vars=["bill_length_mm", "bill_depth_mm", 
           "flipper_length_mm"],
    y_vars=["bill_length_mm", "bill_depth_mm"],
    height=3
)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_14.jpg

图 1.14: 选定特征的变量关系和直方图

箱型图,有时也被称为描述性统计中的箱线图,是一种在解释性数据分析中常用的图表类型。箱型图使用数据的四分位数(或百分位数)和均值,直观地描述数值数据的分布情况及偏斜度。

我们可以通过 Seaborn 的boxplot函数来使用这些功能,如下所示:

f, ax = plt.subplots(figsize=(12, 6))
ax = sns.boxplot(x="day", y="total_bill", data=tips)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_15.jpg

图 1.15: Seaborn 箱型图

Seaborn 箱型图结构非常简单。分布情况通过箱型图可视化。当你想比较两个组之间的数据时,它们非常有用。箱型图也可以称为箱线图。每个箱子显示数据集的四分位数,而须线则延伸以展示其余的分布。

在这里,我们可以使用hue参数来指定我们想要展示的某种类别变量类型,同时指定我们想使用的 Seaborn 默认颜色调色板:

f, ax = plt.subplots(figsize=(12, 6))
ax = sns.boxplot(x="day", y="total_bill", hue="smoker",data=tips, palette="Set3")

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_01_16.jpg

图 1.16: 带有分类数据的 Seaborn 箱型图

总是会有一个问题:何时使用箱型图。箱型图用于显示数值数据的分布,尤其是在跨多个组进行比较时。它们旨在通过一瞥提供高层次信息,并提供诸如对称性、偏斜度、方差和异常值等数据集的详细信息。

总结

在本章中,我们介绍了如何使用 pandas 和 NumPy 存储和操作数据,以及如何使用 Seaborn 可视化数据模式的初步概念。这些元素不仅用于探索数据,还用于创建可视化叙事,让我们能够理解数据中的模式,并以简单而实用的方式进行沟通。

在下一章中,我们将基于此了解如何利用机器学习和描述性统计来验证假设、研究相关性与因果关系,并且构建预测模型。

第二章:在业务操作中使用机器学习

机器学习是一个研究领域,专注于理解和开发“学习”过程,或使用数据来提高在特定任务集上的表现。它被认为是人工智能的一个组成部分。其中,机器学习是一项技术,使企业能够高效地从非结构化数据中提取知识。在几乎不需要编程的情况下,机器学习——更准确地说,机器学习算法——可以用来从给定的数据集进行迭代学习,理解模式、行为等。

在本章中,我们将学习如何做到以下几点:

  • 使用统计分析验证观察到的效果差异

  • 分析变量之间的相关性和因果关系,并建立模型

  • 为聚类和机器学习模型准备数据

  • 开发用于回归和分类的机器学习模型

技术要求

为了能够跟随本章的步骤,你需要满足以下要求:

  • 运行 Python 3.7 及以上版本的 Jupyter Notebook 实例。如果你有 Google Drive 账户,也可以使用 Google Colab Notebook 运行这些步骤。

  • 具备基本的数学和统计概念知识。

  • 下载书中 GitHub 页面提供的示例数据集,原始来源是python.cogsci.nl/numerical/statistics/

使用 t 检验验证变化的效果

当衡量某些操作对特定用户群体的影响时,我们需要验证这些操作是否已经显著影响了目标群体。为了做到这一点,我们可以使用 t 检验。

t 检验是一种统计检验,用于比较两组的均值,以确定某种方法或治疗是否对感兴趣的人群产生影响,或者两个组是否存在差异;它通常用于假设检验。

当两个组中的数据集不涉及相同的值时,独立地选择不同的 t 检验样本。这些样本可能包括两组随机选择的、不相关的患者群体,用来研究药物的效果。例如,其中一组接受处方治疗,另一组则作为对照组,接受安慰剂。这会产生两个独立的、无关的样本集。简单来说,t 检验用于比较两组的均值。它通常用于假设检验,以确定一个方法或治疗是否真正影响了感兴趣的人群,或者两个组之间是否存在差异。

t 检验在商业背景下用于比较两个不同的均值,并确定它们是否代表相同的总体,尤其在验证促销活动对销售提升的影响时非常有用。此外,它还使企业能够理解其结果是否为偶然现象的概率。

我们将学习如何使用 SciPy 包和 Matzke 等人(2015)数据集进行独立样本 t 检验。该数据集中的参与者经历了一项记忆挑战,需回忆出一组单词。在保持间隔期间,一组参与者专注于显示屏上的中央固定点,而另一组志愿者则不断地水平移动眼睛,有些人认为这有助于记忆。

为了判断横向眼动组的记忆表现(CriticalRecall)是否优于注视组,我们可以使用 SciPy 库中的 ttest_ind 函数:

from scipy.stats import ttest_ind
import pandas as pd
dm = pd.read_csv('matzke_et_al.csv')
dm_horizontal = dm[dm.Condition=='Horizontal']
dm_fixation = dm[dm.Condition=='Fixation']
t, p = ttest_ind(dm_horizontal.CriticalRecall, dm_fixation.CriticalRecall)
print('t = {:.3f}, p = {:.3f}'.format(t, p))

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_1.jpg

图 2.1:T 检验结果

t 检验的 p 值可以在输出结果中找到,它是你评估 t 检验结果所需的全部信息。只需将输出的 p 值与所选的 alpha 水平进行比较,即可在所需的 alpha(显著性)水平上进行假设检验:

import seaborn as sns
import matplotlib.pyplot as plt # visualization
sns.barplot(x='Condition', y='CriticalRecall', data=dm)
plt.xlabel('Condition')
plt.ylabel('Memory performance')
plt.show()

如果 p 值小于设定的显著性阈值(例如 0.05),你可以拒绝原假设。两个均值之间的差异在统计上具有显著性。你的样本数据足够有说服力,支持两个总体均值不相等的结论:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_2.jpg

图 2.2:总体分布

高 t 值(也称为 t 值)表示组间差异明显,而低 t 值则表示组间相似。自由度,或研究中可能变化的值,对于确定原假设的显著性和真实性至关重要。

在我们的例子中,结果表明存在显著差异(p = 0.0066)。然而,固定注视组表现优于其他组,且其效果与预期方向相反。

另一种测试两个总体差异的方法是配对样本 t 检验,它比较同一组的两个变量均值。为确定平均值是否偏离 0,该过程计算每次出现时两个变量之间的差异。独立或不相关组的均值使用非配对 t 检验进行比较。非配对 t 检验假设组间的方差相等,而配对 t 检验则不要求方差相等。该过程还自动计算 t 检验的效应量。配对 t 检验用于数据为匹配对的情况,而两样本 t 检验用于两个样本在统计上独立的数据。

让我们使用 Moore、McCabe 和 Craig 的数据集。在这里,评估了痴呆症患者在满月和其他月相期间的攻击行为。这是一个被试内设计,因为在两个时间点对每位参与者进行了测量。

你可以使用 ttest_rel SciPy 函数来检验攻击性在满月和其他月相之间是否有所不同:

from scipy.stats import ttest_rel
dm = pd.read_csv('moon-aggression.csv')
t, p = ttest_rel(dm.Moon, dm.Other)
print('t = {:.3f}, p = {:.3f}'.format(t, p))

如下图所示,有一个有趣且显著的效应,因为 p 值从不为 0,正如输出所示。这一效应表明,人们确实在满月期间最为暴力:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_3.jpg

图 2.3:攻击性数据集的 T 检验结果

另一种比较两个组之间差异的方法是统计方法方差分析ANOVA),该方法用于检查不同均值之间的差异。罗纳德·费舍尔于 1918 年创立了这一统计检验方法,并一直沿用至今。简而言之,ANOVA 分析可以确定三个或更多独立组的均值是否在统计上存在差异。那么,ANOVA 会取代 t 检验吗?其实不会。ANOVA 用于比较三个或更多组之间的均值,而 t 检验则用于比较两个组之间的均值。

在商业环境中,ANOVA 可以用于预算管理,例如,将预算与成本进行比较,以管理收入和库存。ANOVA 还可以用于通过比较预算与成本来管理收入和库存。例如,为了更好地了解未来的销售表现,ANOVA 还可以用于通过检查数据模式来预测趋势。在评估市场研究中经常使用的多项量表时,ANOVA 尤其有用。使用 ANOVA 可能会帮助你作为市场研究员理解不同群体的反应。你可以通过接受零假设开始测试,即观察到的所有组的均值是相等的。

在下一个示例中,让我们重新审视 Moore、McCabe 和 Craig 提供的心率信息。性别和组别是该数据集中两个与主题相关的因素,还有一个因变量(心率)。你需要以下代码来检查性别、组别或它们的交互作用是否对心率产生影响。

我们将使用 anova_lm 的组合,这并不是非常优雅,但关键部分是公式:

from statsmodels.stats.anova import anova_lm
dm = pd.read_csv('heartrate.csv')
dm = dm.rename({'Heart Rate':'HeartRate'},axis=1)  # statsmodels doesn't like spaces
df = anova_lm(ols('HeartRate ~ Gender * Group', data=dm).fit())
print(df)

结果显示心率与所有因素相关:性别(F = 185.980,p < .001)、组别(F = 695.647,p < .001)以及性别与组别的交互作用(F = 7.409,p = .006)。

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_4.jpg

图 2.4:ANOVA 检验结果

现在我们已经验证了多个组之间确实存在差异,接下来可以开始对这些关系进行建模。

使用多元线性回归建模关系

被称为多元线性回归的统计方法利用两个或更多的自变量来预测因变量的结果。通过这种方法,分析师可以计算模型的方差以及每个自变量对整体方差的相对贡献。涉及多个解释变量的回归,无论是线性还是非线性的,都属于多元回归范畴。

多元回归分析的目的是让研究人员能够评估结果(因变量)与多个预测变量之间关系的强度,以及每个预测变量在关系中的重要性,通常是通过消除其他预测变量的统计效应来实现。

多元回归包含多个自变量,而线性回归只考虑一个自变量来影响关系的斜率。

企业可以使用线性回归分析趋势并生成估算或预测。例如,如果一家公司的销售额在过去几年中每月逐渐上升,该公司可以通过对销售数据和每月销售额进行线性分析,预测未来几个月的销售额。

让我们使用 Moore、McCabe 和 Craig 的数据集,其中包含高中生的平均绩点(GPA)和数学及语言知识的 SAT 成绩。我们可以使用以下代码来测试satmsatv是否与gpa(独立)相关。

我们将使用OLS的 SciPy 函数来评估这个关系,该关系作为相关变量的组合传递,然后拟合到数据上:

from statsmodels.formula.api import ols
dm = pd.read_csv('gpa.csv')
model = ols('gpa ~ satm + satv', data=dm).fit()
print(model.summary())

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_5.jpg

图 2.5:OLS 结果

结果显示,仅数学科目的 SAT 成绩与平均绩点(GPA)有独特的关系,而语言科目的 SAT 成绩则没有。

在下一节中,我们将探讨相关性的概念,即当变量以相似的方式变化时,称为相关;而因果关系则是指一个变量影响另一个变量。

建立相关性和因果关系

被称为相关性的统计量表示了两个变量之间线性关系的紧密程度,可以通过图形方式理解为两个曲线重叠的程度。这是一种描述简单关系的典型方法,而不明确指出因果关系。

相关矩阵显示了相关值,用于量化每一对变量之间的线性关系的紧密程度。相关系数的范围是-1 到+1。如果两个变量有相似的上升和下降趋势,相关值为正。

统计中通常测量的四种相关性类型是斯皮尔曼相关系数、皮尔逊相关系数、肯达尔秩相关系数和点二列相关系数。

为了使组织能够根据预测事件结果做出数据驱动的决策,通常使用相关性和回归分析来预测未来的结果。相关性分析的两个主要优点是它能够快速进行假设检验,并帮助企业决定要进一步探究哪些变量。为了确定两个变量之间线性关系的强度,相关性分析的主要方法是应用 Pearson 的 r 公式。

使用 pandas 数据框中的 corr 方法,我们可以计算列的成对相关性,并删除 NA/null 值。该技术可以作为参数传递,pearsonkendall 为标准相关系数,spearman 为斯皮尔曼等级相关性,或者 kendall 为 Kendall Tau 相关系数。

pandas 数据框中的 corr 方法返回一个浮动矩阵,对角线上为 1,并且无论调用函数的行为如何,都是对称的:

import numpy as np
import pandas as pd
df = pd.DataFrame([(.2, .3,.8), (.0, .6,.9), (.6, .0,.4), (.2, .1,.9),(.1, .3,.7), (.1, .5,.6), (.7, .1,.5), (.3, .0,.8),],columns=['dogs', 'cats','birds'])
corr_mat = df.corr()

我们可以使用 seaborn 热图来绘制结果的相关性矩阵:

import seaborn as sn
sn.heatmap(corr_mat, annot=True)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_6.jpg

图 2.6: 相关性矩阵

利用成对相关性进行特征选择的主要目标是找到高度相关的特征组,并仅保留其中一个,这样可以通过尽可能少的特征来最大化模型的预测值。

成对相关性是在 DataFrame 的行或列与 Series 或 DataFrame 的行或列之间计算的。相关性是在对齐了 DataFrame 的两个轴之后计算的。接下来,我们可以看到一个例子,可能会更清楚一些:

df1=pd.DataFrame( np.random.randn(3,2), columns=['a','b'] )
df2=pd.DataFrame( np.random.randn(3,2), columns=['a','b'] )

使用 corr 来比较同一数据框内的数值型列。非数值型列将自动被跳过:

corr_mat = df1.corr()
sn.heatmap(corr_mat, annot=True)
plt.show()

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_7.jpg

图 2.7: 相关性矩阵

我们还可以使用 corrwith 比较 df1df2 的列。请注意,只有具有相同名称的列才会被比较:

df1.corrwith(df2)

为了简化操作,如果我们希望 pandas 忽略列名并仅比较 df1 的第一行与 df2 的第一行,可以将 df2 的列名重命名为与 df1 匹配:

df1.corrwith(df2.set_axis( df1.columns, axis='columns', inplace=False))

需要注意的是,在这种情况下,df1df2 必须具有相同的列数。

最后,你也可以将这两个数据集水平合并,并使用 corr。其优点在于,它基本上独立于列的数量和命名规则,但缺点是你可能会得到超出需要或想要的输出:

corr_mat = pd.concat([df1,df2],axis=1).corr()
sn.heatmap(corr_mat, annot=True)
plt.show()

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_8.jpg

图 2.8: 相关性热图

现在我们已经确认了通过相关性分析可以找出两个变量之间的相关性,我们可以尝试通过因果分析验证这些变量是否真正相互影响。

一个变量对另一个变量的影响能力被称为因果关系。第一个变量可能会产生第二个变量,或者可能会改变第二个变量的发生频率。

因果关系是一个事件、过程、状态或对象影响另一个事件、过程、条件或对象发展的过程,其中原因和结果是相互依赖的。那么,相关性与因果关系有什么区别呢?相关性并不自动意味着因果关系,即使因果关系和相关性可能同时存在。在 A 行动导致 B 结果的情况下,因果关系明确适用。另一方面,相关性只是两者之间的关系。

我们可以使用以下数据集来研究变量之间的因果关系:

import numpy as np
import pandas as pd
import random
ds = pd.DataFrame(columns = ['x','y'])
ds['x'] = [int(n>500) for n in random.sample(range(0, 1000), 
      100)]
ds['y'] = [int(n>500) for n in random.sample(range(0, 1000), 
      100)]
ds.head()

为了研究因果关系,我们可以尝试估算两组之间的均值差异。两组之间均值的绝对差异被称为均值差异,通常称为均值之差。它让你了解在临床研究中,实验组和对照组的平均值有多大差异。

在下一个示例中,我们将估算提升量作为均值差异的量化值,并计算确定的标准误差。我们将使用 90 作为正态分布范围内的置信区间,这将得到一个 z 值为 1.96:

base,var  = ds[ds.x == 0], ds[ds.x == 1]
delta = var.y.mean() - base.y.mean()
delta_dev = 1.96 * np.sqrt(var.y.var() / var.shape[0] 
      +base.y.var() / base.shape[0])
print("estimated_effect":,delta, "standard_error": delta_dev)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_9.jpg

图 2.9: 人群之间的估计差异

我们还可以使用列联 卡方 检验来比较具有二分依赖变量的两组。例如,我们可以使用是/否响应尺度对男性和女性进行对比。列联卡方检验基于与简单卡方分析相同的原理,该分析比较预期结果与实际结果。

这种统计技术用于将实际结果与预测结果进行比较。此测试的目的是确定观察到的数据与预期数据之间的差异是否是偶然的,还是研究变量之间的相关性。结果会生成一个列联矩阵,从中我们可以推断,如果 C 接近零(或等于零),则变量之间相互独立且没有关联。如果 C 不为零,则存在某种关系;C 只能取正值:

from scipy.stats import chi2_contingency
contingency_table = (
         ds 
         .assign(placeholder=1) 
         .pivot_table(index="x", columns="y", 
              values="placeholder", aggfunc="sum") 
         .values)
_, p, _, _ = chi2_contingency(contingency_table, 
     lambda_="log-likelihood")

在这里,我们将仅尝试解释 p 值:

print("P-value:",p)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_10.jpg

图 2.10: 结果 p 值

现在我们将使用一组合成生成的数据集:

data_1 = pd.read_csv('observed_data_1.csv' )
data_1.plot.scatter(x="z", y="y", c="x", cmap="rainbow", colorbar=False)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_11.jpg

图 2.11: 数据分布图

连续随机变量的概率密度函数可以通过 核密度估计KDE)seaborn 方法来估计。图中曲线下方的区域代表了数据值的概率分布:

import seaborn as sns
sns.kdeplot(data_1.loc[lambda df: df.x == 0].y, label="untreated")
sns.kdeplot(data_1.loc[lambda df: df.x == 1].y, label="treated")

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_12.jpg

图 2.12:密度图

为了研究因果关系,研究人员必须建立一个模型,以描述在因果建模中与特定现象相关的思想之间的联系。

多重因果性——即任何给定结果可能有多个原因——被纳入因果模型。例如,社会地位、年龄、性别、种族和其他因素可能会影响一个人的投票行为。此外,一些独立或解释变量可能是相互关联的。

外部效度可以通过因果模型来解决(即一个研究的结果是否适用于未研究的群体)。在某些情况下,因果模型可以结合数据提供一些单一数据集无法解决的问题的答案。

我们可以使用causalinference包中的est_via_ols函数,通过最小二乘法估计平均处理效应。

这里,y是处理后的潜在结果,D 是处理状态,X 是协变量或个体特征的向量。

控制的参数是adj,一个整数,可以是 0、1 或 2。该参数指示如何执行协变量调整。将adj设置为 0 时,将不包括任何协变量。将adj设置为 1 时,分别包括处理指示变量 D 和协变量 X,或者将adj设置为 2 时,还包括 D 与 X 之间的交互项。默认值是 2。

!pip install causalinference
from causalinference import CausalModel
cm = CausalModel(
    Y=data_1.y.values,
    D=data_1.x.values,
    X=data_1.z.values)
cm.est_via_ols(adj=1)
print(cm.estimates)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_13.jpg

图 2.13:因果模型结果

估计结果显示,变量之间存在负相关关系。负估计可能表明,D 的应用使 Y 的概率降低了 48%。观察所有估计分布以得出结论非常重要。

假设或反事实现实的分析是因果分析,因为我们必须对我们没有目睹的反事实结果做出假设,以评估处理效应:

data_2 = pd.read_csv('observed_data_2.csv')
data_2.plot.scatter(x="z", y="y", c="x", cmap="rainbow", colorbar=False)

之前加载的数据将向我们展示因果模型中的不同值:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_14.jpg

图 2.14:数据分布

我们将使用新加载的值构建新的因果模型:

cm = CausalModel(
    Y=data_2 .y.values,
    D=data_2 .x.values,
    X=data_2 .z.values)
cm.est_via_ols(adj=1)

我们可以打印处理效应估计值,以验证我们的因果模型是否有效:

print(cm.estimates)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_15.jpg

图 2.15:使用新数据的因果模型结果

估计结果告诉我们,关系已经变为正相关。

因果模型是验证数据中变量关系建模和方向的好方法。

在下一节中,我们将深入探讨如何使用缩放方法准备我们的数据,以适应机器学习,具体取决于数据的分布情况。

特征缩放到一个范围

在使用机器学习模型时,数据预处理非常重要,以便解决诸如梯度爆炸或分布不均等问题。

为了将原始特征向量转换为更适合下游估算器的表示,sklearn.preprocessing包提供了多个常用的实用函数和转换器类。

许多在scikit-learn中使用的机器学习估算器通常需要数据集标准化;如果单个特征不大致符合标准正态分布,它们的表现可能很差:均值为 0,方差为 1 的高斯分布。

通常,标准化数据集对学习算法是有利的。如果数据集中存在异常值,建议使用鲁棒的缩放器或转换器。在包含边际异常值的数据集上,分析不同缩放器对包含异常值的数据影响时,突出显示了多个缩放器、转换器和归一化器的作用。

实际上,我们通常忽略分布的形状,简单地通过将非恒定特征除以其标准差并通过减去每个特征的均值来使数据适应缩放。

例如,学习算法的目标函数的多个组件(如支持向量机的 RBF 核函数或线性模型的 l1 和 l2 正则化项)可能假设所有特征都围绕零居中,或者它们的方差在相同数量级上。如果一个特征的方差比其他特征大几个数量级,它可能主导目标函数,阻止估算器根据其他特征进行正确推断。

StandardScaler实用程序类,作为预处理模块的一部分,能够快速简单地对类数组数据集执行以下操作:

from sklearn import preprocessing
x_train = pd.DataFrame([[ 1., -1.,  2.],
                    [ 2.,  0.,  0.],
                    [ 0.,  1., -1.]],columns=['x','y','z'])
scaler = preprocessing.StandardScaler().fit(x_train)

以下代码将拟合缩放器到数据,假设我们的分布是标准的:

scaler.mean_

现在我们可以可视化数据的均值:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_16.jpg

图 2.16:数据的均值

我们也可以可视化缩放:

scaler.scale_

数据显示为一组值:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_17.jpg

图 2.17:列的缩放

最后,我们可以使用transform方法来缩放数据:

x_scaled = scaler.transform(x_train)

另一种标准化方法是将每个特征的最大绝对值缩放到单位一,或缩放到一个预定的最小值和最大值之间,通常是零和一。可以使用MaxAbsScalerMinMaxScaler来实现这一点。

对非常小的特征标准差的鲁棒性以及在稀疏数据中保留零值是使用这种缩放的两个原因。

要将一个玩具数据矩阵缩放到[0, 1]范围,请参考以下示例:

min_max_scaler = preprocessing.MinMaxScaler()
x_train_minmax = min_max_scaler.fit_transform(x_train)

如果我们的分布与标准高斯分布不同,可以使用非线性变换。变换有两种不同的类型:幂变换和分位数变换。分位数和幂变换都通过单调变换保持每个特征的值的秩,因此它们可以保留特征的秩。

基于公式,它是特征的累积分布函数与所需输出分布的分位数函数,分位数变换将所有特征转换为相同的目标分布。这两个事实被应用于该公式:如果是具有连续累积分布函数的随机变量,则均匀分布;如果是具有均匀分布的随机变量,则具有分布。分位数变换通过排名变换平滑掉不典型的分布,相比缩放技术,它对异常值的敏感性较低。然而,它会扭曲特征内部和特征之间的相关性和距离。

Sklearn 提供了一系列称为幂变换的参数变换,旨在将数据从任何分布转换为尽可能接近高斯分布的分布。

我们可以使用 QuantileTransformer 将数据映射到均匀分布,它提供了一种非参数变换,将数据映射到一个值介于 0 和 1 之间的均匀分布:

from sklearn.datasets import load_iris
data = load_iris()
x, y = data['data'],data['target']
quantile_transformer = preprocessing.QuantileTransformer(
n_quantiles=5)
x_train_qt = quantile_transformer.fit_transform(x)
x_train_qt[:5]

我们可以看到得到的数组:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_18.jpg

图 2.18:转换后的数据

也可以通过设置 output_distribution='normal',使用 QuantileTransformer 将数据映射到正态分布。以下示例使用了之前的 iris 数据集:

quantile_transformer = preprocessing.QuantileTransformer(
n_quantiles=5,output_distribution='normal')
x_trans_qt = quantile_transformer.fit_transform(x)
quantile_transformer.quantiles_

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_19.jpg

图 2.19:通过分位数方法转换的数据

上述代码将使用分位数变换对数据进行缩放,定义五个分位数,并期望输出具有正态分布。

为了确定要使用的适当分布,我们需要深入分析我们变量的分布,因为错误的变换可能会导致我们丧失可能需要考虑的重要细节。

在下一节中,我们将通过使用 scikit-learn 的聚类算法深入探讨无监督学习。

聚类数据与降维

聚类过程涉及将总体或数据点分成若干组,使得每组内的数据点彼此之间比其他组的数据点更相似。简单来说,目标是将具有相似特征的人群排序成簇。它在商业分析中常常被使用。如何将大量可用数据整理成有用的结构,是当前组织面临的一个问题。

图像分割、网页分组、市场细分和信息检索是聚类如何帮助企业更好地管理数据的四个例子。数据聚类对于零售公司非常有益,因为它影响销售努力、客户保持和客户购物行为。

向量量化技术“K-means 聚类”的目标,起源于信号处理,是将 n 个观测值划分为 k 个簇,每个簇的原型是与其均值最接近的观测值。K-means 聚类是一种无监督的技术,它使用输入数据本身,并且不需要标签化的响应。K-means 聚类是一种流行的聚类方法。通常,实践者首先研究数据集的结构。数据点被 K-means 分为不同的、不重叠的组。

在下一个代码中,我们可以使用KMeans来拟合数据,以便将每个数据点标记为某个给定的簇:

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=len(set(y)), random_state=0).fit(x)
kmeans.labels_

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_20.jpg

图 2.20:聚类数据

我们可以预测每个新的数据实例属于哪个聚类:

kmeans.predict(x[0].reshape(1,-1))

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_21.jpg

图 2.21:预测数据

我们还可以可视化聚类中心:

kmeans.cluster_centers_

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_22.jpg

图 2.22:聚类中心

KMeans 使我们能够在变量过多时找到共同数据的特征,并且对分割很有帮助。但有时需要将维度减少到一组具有共同特征的变量。

为了将数据投影到一个低维环境中,我们可以使用TruncatedSVD类。

接下来,我们将数据拟合到两个组件中,以减少维度:

from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca.fit(x)

我们应该努力解释尽可能多的方差,简单来说,就是我们模型能够解释整个数据集的程度:

print(pca.explained_variance_ratio_)
print(pca.singular_values_)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_23.jpg

图 2.23:PCA 奇异值

在我们对数据进行预处理、减少维度并进行聚类之后,现在可以构建机器学习模型,预测未来的行为。

在接下来的章节中,我们将构建机器学习模型,用于预测回归和分类任务中的新数据标签。

构建机器学习模型

我们可以构建的最简单的机器学习模型之一是线性回归,它通过最小化数据集中观察到的目标与线性近似预测目标之间的残差平方和,拟合一个线性模型,并使用系数。

从实现角度来看,这实际上是普通最小二乘法或非负最小二乘法,通过预测器对象进行封装。

我们可以通过使用 Sklearn 中的LinearRegression类来非常简单地实现这一点:

from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_diabetes
data_reg = load_diabetes()
x,y = data_reg['data'],data_reg['target']
reg = LinearRegression().fit(x, y)
reg.score(x, y)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_24.jpg

图 2.24:模型回归得分

前面的代码将为我们的数据拟合一个线性回归模型,并打印出数据的得分。

我们还可以打印出系数,这可以很好地估计每个变量对解释我们要预测的变量的贡献:

reg.coef_

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_25.jpg

图 2.25:回归系数

我们还可以打印截距变量:

reg.intercept_

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_26.jpg

图 2.26:回归截距

最后,我们可以使用模型进行预测:

print('Predicted:',reg.predict(x[10].reshape(
1,-1)),'Actual:',y[10])

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_27.jpg

图 2.27:预测的回归值

在这里,我们预测的是一个连续变量,但我们也可以使用分类器而非回归来预测分类变量。

Sklearn 让我们可以选择使用逻辑回归(logitMaxEnt)分类器,在多类情况下,如果将 'multi_class' 选项设置为 ‘ovr’,训练算法会使用一对多(OvR)方案;如果将 'multi_class' 选项设置为 'multinomial',则会使用交叉熵损失。该类使用 'liblinear' 库,'newton-cg''sag''saga''lbfgs' 求解器来实现正则化逻辑回归。请记住,正则化是默认启用的。它可以处理稠密和稀疏输入。为了获得最佳速度,仅使用 64 位浮动矩阵;所有其他输入格式将会转换。

"newton-cg""sag""lbfgs" 求解器唯一支持的正则化是具有原始公式的 L2 正则化。"liblinear" 求解器支持 L1 和 L2 正则化,但只有 L2 惩罚项具有对偶公式。唯一支持弹性网正则化的求解器是 "saga" 求解器。

在拟合模型时,底层的 C 程序通过随机数生成器选择特征。因此,对于相同的输入数据,稍有不同的输出是常见的。如果发生这种情况,可以尝试使用较小的 tol 参数:

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_digits
data_class = load_digits()
x,y = data_class['data'],data_class['target']
clf = make_pipeline(StandardScaler(), 
      LogisticRegression(penalty='l2',C=.1))
clf.fit(x, y)
clf.predict(x[:2, :])

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_28.jpg

图 2.28:逻辑回归结果

我们还可以对模型进行评分,以评估预测的精度:

clf.score(x, y)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_29.jpg

图 2.29:用户数据

为了验证模型,我们可以使用交叉验证,这允许我们评估估算器的性能。这是学习预测函数参数并在同一数据集上评估它的一个方法学错误。一个仅仅重复它刚刚看到的样本标签的模型会得分较高,但无法对尚未见过的数据做出预测。过拟合是这种情况的术语。为了避免这个问题,在进行(有监督的)机器学习实验时,通常会预留一部分可用数据作为测试集(x 测试,y 测试)。

需要注意的是,“实验”一词不仅仅指学术目的,因为机器学习实验有时也始于商业环境。网格搜索方法可用于寻找最优参数。

scikit-learn中,可以使用train_test_split辅助函数快速将数据随机划分为训练集和测试集。我们加载iris数据集,并在其上训练一个线性支持向量机:

x, y = load_iris(return_X_y=True)
x.shape, y.shape

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_30.jpg

图 2.30:数据形状

现在,我们可以快速采样一个训练集,同时保留 40%的数据用于测试(评估)我们的分类器:

from sklearn.model_selection import train_test_split
from sklearn import svm
x_train, x_test, y_train, y_test = train_test_split(x, y, 
test_size=0.4, random_state=0)

我们可以通过查看numpy数组的形状来验证生成的训练数据集的形状:

x_train.shape, y_train.shape

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_31.jpg

图 2.31:训练数据形状

我们可以对test数据集执行相同操作:

x_test.shape, y_test.shape

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_32.jpg

图 2.32:测试数据形状

最后,我们可以在训练数据上训练我们的机器学习模型,并使用test数据集对其进行评分,该数据集包含模型在训练过程中未见过的数据点:

clf = svm.SVC(kernel='linear', C=.7).fit(x_train, y_train)
clf.score(x_test, y_test)

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_33.jpg

图 2.33:逻辑回归评分

在比较不同超参数设置时,仍然有可能出现过拟合现象,例如 SVM 中必须手动选择的 C 参数。这是因为参数可以调整直到估计器的表现最佳。在这种方法中,模型可能会“泄漏”测试集的信息,从而导致评估度量无法准确反映泛化性能。这个问题可以通过进一步从数据集中留出一部分作为“验证集”来解决:首先在训练集上进行训练,然后在验证集上进行评估,当实验成功时,最后可以在测试集上进行最终评估。

然而,通过将可用数据划分为三组,我们大幅减少了可用于训练模型的样本数量,且根据训练集和验证集的随机化,结果可能有所不同。

交叉验证(简称 CV)是一种可以用来解决这个问题的方法。在进行交叉验证时,不再需要验证集,但仍应保留一个测试集以供最终评估。其基本策略,称为 k 折交叉验证,将训练集划分为 k 个较小的子集(其他方法见下文,但通常遵循相同的原则)。每一个 k 个“折”操作如下进行:

各个折叠被用作模型的训练数据,随后使用剩余的部分数据进行验证(即,用作测试集来计算准确度等性能指标)。

在循环中计算的数字的平均值就是由 k 折交叉验证提供的性能指标。尽管这种方法计算开销较大,但它不会浪费大量数据(不像固定一个任意的验证集),这是在样本较少的应用中,如逆推断,的一个显著优势。

我们可以通过在估计器上调用cross_val得分帮助函数来计算交叉验证指标,并且该数据集是应用交叉验证的最简单方法。以下示例展示了如何拆分数据,开发模型,并连续五次计算得分(每次使用不同的拆分)以衡量线性核支持向量机在iris数据集上的准确性:

from sklearn.model_selection import cross_val_score
scores = cross_val_score(clf, x, y, cv=5)

因此,平均得分和标准差由以下公式给出:

print('Mean:',scores.mean(),'Standard Deviation:', 
scores.std())

估计器的评分技术默认用于计算每次 CV 迭代时的得分:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_34.jpg

图 2.34:CV 平均得分

通过应用scoring参数可以更改此设置:

from sklearn import metrics
scores = cross_val_score(clf, x, y, cv=5, scoring='f1_macro')
scores

由于iris数据集中的样本在目标类别中均匀分布,准确率和 F1 分数几乎相等:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_35.jpg

图 2.35:交叉验证(CV)得分

cv参数是整数时,CV 得分默认使用KFoldStratifiedKFold策略,如果估计器来自ClassifierMixin,则使用后者。

也可以通过传递一个使用ShuffleSplit Sklearn 类的 CV 迭代器来使用其他 CV 策略:

from sklearn.model_selection import ShuffleSplit
n_samples = x.shape[0]
cv = ShuffleSplit(n_splits=5, test_size=0.3, random_state=0)
cross_val_score(clf, x, y, cv=cv)

上述代码将向我们展示在多个测试样本折叠上的 CV 得分,这可以用来防止过拟合问题:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_02_36.jpg

图 2.36:使用洗牌拆分的结果

上述结果向我们展示了 CV 得分的结果。

概述

在本章中,我们学习了如何使用描述性统计和机器学习模型量化群体之间的差异,这些差异可以用来验证商业假设以及评估某些营销活动的效果提升。我们还学习了如何通过相关性和因果分析研究变量之间的关系,并如何使用线性模型对这些关系进行建模。最后,我们构建了机器学习模型来预测和分类变量。

在下一章中,我们将学习如何利用网络搜索结果,并将其应用于市场研究的背景下。

第二部分:市场与客户洞察

在本部分,您将学习如何通过利用某些工具获取并分析市场数据。本部分将教您如何获取搜索趋势,使用相似查询丰富趋势,使用抓取工具获取数据,并通过有效的可视化监控关键业务绩效 KPI 来构建结果,从而做出更好的决策。

本部分涵盖以下章节:

  • 第三章通过市场洞察寻找商业机会

  • 第四章通过联合分析理解客户偏好

  • 第五章通过价格需求弹性选择最优价格

  • 第六章产品推荐

第三章:利用市场洞察发现商业机会

近年来,"洞察"一词在创新市场测试者中使用得越来越频繁。大多数时候,它没有明确的定义,有时暗示在使用的数据中存在隐藏的模式,或者它可以在商业环境中用于创造新的收入来源,更清晰地定义特定市场的条件和偏好,或了解不同地理区域或群体中不同的客户偏好。

在本章中,我们将使用搜索引擎趋势分析不同金融资产在多个市场中的表现。总体来说,我们将关注以下内容:

  • 使用 Pytrends 包通过 Google Trends 数据收集不同术语的相对表现信息

  • 查找这些洞察模式的变化,以识别消费者偏好的转变

  • 使用关于相似查询的信息,理解与我们研究的每个金融产品相关的搜索模式

之后,我们将逐步进行分析,在本章结束时,你将能够做到以下几点:

  • 利用搜索引擎趋势识别可能对某一产品或服务感兴趣/购买/订阅的地区

  • 理解这些关系的行为正在发生变化,并适应这些变化

  • 扩展搜索空间分析,使用与原始查询相关的术语,以更好地理解潜在的市场需求

本章包含以下内容:

  • 使用 Pytrends 理解搜索趋势

  • 安装 Pytrends 和市场排名

  • 查找搜索趋势模式的变化

  • 使用相似的查询来获取关于新趋势的洞察

  • 分析相似查询在时间上的表现

让我们开始使用 Google Trends API 分析趋势,通过一组例子和一些假设情境,许多公司和企业可能会面临这种情境。例如,收集有关特定市场的情报,以便广告宣传新产品和服务。

技术要求

为了能够跟随本章中的步骤,你需要满足以下要求:

  • 一个运行 Python 3.7 及以上版本的 Jupyter Notebook 实例。如果你有 Google Drive 账户,你也可以使用 Google Colab Notebook 来运行步骤。

  • 理解基本的数学和统计概念。

使用 Pytrends 理解搜索趋势

在市场营销中,市场调研指的是寻找有关特定目标市场的相关、可操作且新颖的知识,这在规划商业策略时始终至关重要。这意味着目标是获取能够帮助我们更好了解特定市场需求以及企业如何通过其产品和服务满足这些需求的信息。我们通过数据分析来发现之前未见的模式,从而获取这些知识。这一新的洞察使得公司能够做到以下几点:

  • 通过实际满足需求来实现创新

  • 更好地理解特定市场中的客户

  • 监测品牌知名度等

在本章中,我们将分析一组金融资产及其在不同市场中的表现,以及人们在搜索这些资产时的搜索行为。我们特别跟踪的四种资产是比特币、房地产、债券和股票。这些资产是加密货币、房地产市场、债券(即贷款给某公司或政府)以及股票(代表公司部分所有权)的金融资产。在这种情况下,我们将模拟一个想要拥有特定资产组合并希望通过更好地满足目标市场的搜索模式来吸引特定市场的公司。

我们将使用 Pytrends 包,它通过 Google Trends API 访问数据,且该 API 在一些例外情况下是免费的。

Google Trends API 提供与任何浏览器界面上显示的信息相同的数据,但在处理大量数据时,通过 API 访问数据更加便捷。

这个数据存在一些需要仔细考虑的局限性,具体如下:

  • 该 API 对在给定时间内可以检索的响应数量有所限制。这意味着在短时间内不能发出大量请求。

  • 结果以相对的方式显示。所使用的查询如果移除其中一个并重新请求,将会得到不同的结果。这是因为结果是相对的。

  • 根据 Google 的定义,度量单位在 0 到 100 之间计算,考虑到特定地点某个查询的搜索总量的比例。

  • 请求在同一时间内可以提供的词语数量是有限制的。每次请求最多只能比较五个词语。这一限制不适用于结果,结果有时可能非常详细。

既然我们已经理解了我们在寻找什么,那么让我们开始分析吧。

安装 Pytrends 并对市场进行排名

作为第一步,我们需要安装一个包来分析网页搜索数据。我们将安装 Pytrends 包,它是 Google Trends API 的一个封装器。为此,打开一个运行 Python 3.7 的新 Jupyter Notebook,并在新单元格中运行以下命令来安装该包:

pip install pytrends

安装完包后,我们可以开始分析。我们可以向 API 发出几种类型的查询,如下所示:

  • 随时间变化的兴趣

  • 历史小时兴趣

  • 按地区的兴趣

  • 相关主题

  • 相关查询

  • 热搜

  • 实时搜索趋势

  • 热门榜单

  • 建议

在这种情况下,我们希望获得有关给定搜索词集在各地区的兴趣信息。我们将按照以下步骤进行:

  1. 导入pandas包来存储结果并绘制数据。

  2. 初始化 Pytrends API,我们将传入一组搜索词,并以过去 12 个月作为搜索的参数构建有效载荷。

  3. 最后,我们将把结果存储在一个名为regiondf_12mpandas DataFrame 中:

    import pandas as pd
    
    from pytrends.request import TrendReq
    
    pytrend = TrendReq()
    
    #provide your search terms
    
    kw_list=['bitcoin',
    
             'stocks',
    
             'real estate',
    
             'bonds']
    
    #search interest per region
    
    pytrend.build_payload(kw_list, timeframe='today 12-m')
    
    # Interest by Region
    
    regiondf_12m = pytrend.interest_by_region()
    

在结果中,可能会有一些地区没有我们所搜索的词的结果,因此我们可以通过对行求和并检查是否和为零来删除这些行。如果为零,我们将删除这一行。如果你在给定时间内发出过多请求,Google 会限制你进行新的查询,你将收到 429 错误代码,这表明你可能需要等待一段时间才能再次查询。

  1. 现在,我们可以利用这个逻辑创建一个括号中的掩码,传递给regiondf_12m DataFrame,以删除没有结果的行:

    # #looking at rows where all values are not equal to 0
    
    regiondf_12m = regiondf_12m[regiondf_12m.sum(axis=1)!=0]
    
  2. 最后,我们可以使用pandas DataFrame 的plot方法来可视化结果,绘制一个显示结果的柱状图:

    # visualize
    
    regiondf_12m.plot(figsize=(14, 8), y=kw_list, 
    
          kind ='bar')
    

执行前面的代码块将提示我们得到类似这样的结果:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_1.jpg

图 3.1:过去 12 个月各地区的相对搜索趋势重要性

在这里,重要的是要记住,搜索趋势是作为给定区域总搜索量的一个分数建模的,因此所有这些结果仅与它们所指示的地区相关。

仅从这个柱状图分析结果可能有点困难,因此我们将深入分析我们分析的每一个搜索词的具体情况。

  1. 现在,我们将绘制过去 12 个月里bitcoin搜索词表现较好的地区。为此,我们需要选择相应的列,对数值进行升序排序,并使用plot方法绘制柱状图,显示在这些地区搜索词相对于总区域搜索量的较大比例:

    regiondf_12m['bitcoin'].sort_values(ascending= False).plot(figsize=(14, 8),                              
    
    y=regiondf_12m['bitcoin'].index,kind ='bar')
    

这段代码生成以下结果:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_2.jpg

图 3.2:过去 12 个月比特币是热门搜索趋势的国家

这个图表显示了bitcoin在过去 12 个月里成为热门搜索趋势的国家。这可以作为市场中给定趋势成熟度的指标,因为这意味着在至少一年内,这些地区相对于其他搜索趋势的搜索量是持续存在的。

  1. 接下来,我们将对其余的搜索词执行相同的操作,并将比较各个市场之间的差异。

接下来的代码块以相同的方式过滤、排序并绘制数据,不过这次是针对 real estate 搜索词:

regiondf_12m['real estate'].sort_values(ascending= 
   False).plot(figsize=(14, 8),
      y=regiondf_12m['real estate'].index,kind ='bar')

这一代码块的结果是一个柱状图,显示了不同地区对这一术语的搜索结果:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_3.jpg

图 3.3:在过去 12 个月中,房地产是搜索趋势排名前列的国家

作为第一个区别,我们可以看到房地产的结果在结果分布上有所不同。虽然我们可以在 图 3.1 中看到结果在各个结果之间趋于更均匀分布,但在房地产结果中,数据显示只有少数国家对这一术语的搜索量较大。这可能表明这种类型的投资与当地的法规和条件更加紧密相关。我们可以看到,澳大利亚、新西兰、美国和加拿大是唯一搜索量超过 40 分的国家。

  1. 接下来的代码块将展示我们关于搜索词“股票”的表现:

    regiondf_12m['stocks'].sort_values(ascending= False).plot(figsize=(14, 8),
    
         y=regiondf_12m['stocks'].index,kind ='bar')
    

这显示了过去 12 个月中 stocks 搜索词的结果:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_4.jpg

图 3.4:在过去 12 个月中,股票是搜索趋势排名前列的国家

在这里,趋势倾向于重复,但出现在不同的国家。在这种情况下,前五个国家是印度、美国、菲律宾、加拿大和沙特阿拉伯。这里的区别在于,印度是唯一一个超过 40 分的国家。这可能是推测这些地区人们在投资选择方面思考方式的一种方式。

  1. 最后,我们需要重复相同的过程,但对于 bonds 搜索词,通过更改之前代码中使用的列来实现:

    regiondf_12m['bonds'].sort_values(ascending= False).plot(figsize=(14, 8), 
    
         y=regiondf_12m['bonds'].index, kind ='bar')
    

执行这段代码将返回以下结果:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_5.jpg

图 3.5:在过去 12 个月中,债券是搜索趋势排名前列的国家

可以看出,债券似乎是用户在搜索投资选项时使用较少的选择。澳大利亚在债券搜索占比方面处于领先地位,同时房地产搜索也位列前茅,这表明债券和房地产似乎是澳大利亚比股票或比特币更具吸引力的选项。

现在我们已经确定了每个资产在受欢迎程度方面表现最好的地区,我们将研究这些趋势模式的变化。

寻找搜索趋势模式的变化

搜索趋势不是静态变量;事实上,它们会随时间变化。我们将获得过去 3 个月按地区划分的兴趣结果,然后与过去 12 个月的结果进行比较,看看结果的变化:

  1. 为了找出搜索趋势的变化模式,我们将在不同的时间框架内构建负载。

  2. 最后,我们将把结果存储在一个名为regiondf_3mpandas数据框中:

    #search interest per region
    
    pytrend = TrendReq()
    
    pytrend.build_payload(kw_list, timeframe='today 3-m')
    
    # Interest by Region
    
    regiondf_3m = pytrend.interest_by_region()
    
  3. 我们需要删除没有搜索词结果的行:

    # #looking at rows where all values are not equal to 0
    
    regiondf_3m = regiondf_3m[regiondf_3m.sum(axis=1)!=0]
    
  4. 现在,我们可以使用pandas数据框的plot方法来可视化结果:

    # visualize
    
    regiondf_3m.plot(figsize=(14, 8), y=kw_list, kind ='bar')
    

这段代码会生成下一个可视化结果:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_6.jpg

图 3.6:过去 3 个月的兴趣变化

一眼看去,要找到结果中可能的变化是非常复杂的,所以我们将以一种方式排列数据,只展示这些趋势的变化:

  1. 第一步是创建一个包含过去 12 个月和过去 3 个月信息的数据框:

    df = pd.DataFrame([regiondf_3m['stocks'],
    
                      regiondf_12m['stocks'],
    
                      regiondf_3m['bitcoin'],
    
                      regiondf_12m['bitcoin'],
    
                      regiondf_3m['real estate'],
    
                      regiondf_12m['real estate'],
    
                      regiondf_3m['bonds'],
    
                      regiondf_12m['bonds']
    
                      ]).T
    

在这里,数据框是通过连接不同搜索词的结果构建的。

  1. 接下来,我们需要重命名列并创建表示搜索词随时间变化的兴趣差异的列:

    cols = ['stocks_3m','stocks_12m','bitcoin_3m',
    
    'bitcoin_12m','real_estate_3m','real_estate_12m','bonds_3m','bonds_12m']
    
    df.columns = cols
    
    df['diff_stocks'] = df['stocks_12m'] - df['stocks_3m']
    
    df['diff_bitcoin'] = df['bitcoin_12m'] - df['bitcoin_3m']
    
    df['diff_real_estate'] = df['real_estate_12m'] - df['real_estate_3m']
    
    df['diff_bonds'] = df['bonds_12m'] - df['bonds_3m']
    
    # Inspect the new created columns
    
    df.head()
    
  2. 现在,我们可以限制新创建的列的值:

    n_cols = ['diff_stocks','diff_bitcoin',
    
          'diff_real_estate','diff_bonds']
    
    df = df[n_cols]
    
    df.head()
    

这将生成下一个结果,展示搜索趋势的相对变化:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_7.jpg

图 3.7:比较过去 3 个月与 12 个月之间的相对差异

  1. 有些国家没有变化,因此我们将通过沿着轴求和并将结果与零进行比较,来创建一个掩码,过滤掉这些情况:

    # Create a mask for of the null results
    
    mask = df.abs().sum(axis=1)!=0
    
    df = df[mask]
    
    df.head()
    

需要注意的是,这种比较仅在绝对值的基础上进行。

上述代码向我们展示了经过筛选的结果。

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_8.jpg

图 3.8:筛选后的相对差异结果

  1. 现在,我们可以展示所获得的结果。我们将首先查看那些搜索“股票”一词时发生变化的地区。

为此,我们将使用图 3.8中的结果,根据我们想要的列进行筛选,剔除没有变化的行,按升序排序,然后使用pandas数据框的plot方法可视化结果:

data = df['diff_stocks'][df['diff_stocks']!=0]
data = data.sort_values(ascending = False)
data.plot(figsize=(14, 8),y=data.index, kind ='bar')

这将生成下一个结果:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_9.jpg

图 3.9:过去 12 个月中,搜索词股票在不同国家的流行度变化

结果显示,与之相比,股票作为搜索趋势在阿联酋和美国的流行度有所巩固,而在巴基斯坦和俄罗斯的流行度则有所下降。这些结果不能直接解释为对资产本身价值认知的变化,而是流量变化的指示。流量的增加可能由正面或负面因素引起,因此深入分析总是很重要。

  1. 现在,我们将查看“比特币”搜索趋势变化的差异:

    df['diff_bitcoin'][df['diff_bitcoin']!=0
    
    ].sort_values(ascending = False).plot(figsize=(14, 8), y=df['diff_bitcoin'][df['diff_bitcoin']!=0].index,kind ='bar')
    

代码生成下一个图表:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_10.jpg

图 3.10:在过去 12 个月中,“比特币”这一搜索词的流行变化国家

关于这个图表,首先需要注意的是,最近几个月的大多数变化是积极的,而非负面的。这可能是过去几个月全球范围内更加广泛采纳的一个标志。

在增长方面,领先的国家是新西兰、巴基斯坦和南非,而阿联酋则处于下降的领先地位。

  1. 下一个代码块展示了“债券”这一搜索词的相同效果:

    df['diff_bonds'][df['diff_bonds']!=0
    
    ].sort_values(ascending = False).plot(figsize=(14, 8),y = df['diff_bonds'][df['diff_bonds']!=0].index,kind ='bar')
    

结果将在下一个图表中展示:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_11.jpg

图 3.11:在过去 12 个月中,“债券”这一搜索词的流行变化国家

可以看到一个有趣的趋势变化,现在大多数国家的搜索量都有所下降。这可能是全球投资模式一致变化的一个标志,某些国家受影响的程度较大。还可以注意到,新西兰现在在所分析的时期内是搜索趋势下降最多的国家,而在比特币的情况下,它曾是增长最快的国家。美国也是如此,虽然出现了下降趋势,但在“股票”这一搜索词的变化中却表现出正面的变化。

  1. 最后,下面的代码块显示了“房地产”搜索词的变化:

    df['diff_real_estate'][df['diff_real_estate']!=0].sort_values(ascending = False).plot(figsize=(14, 8),y=df['diff_real_estate'][df['diff_real_estate']!=0].index,kind ='bar')
    

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_12.jpg

图 3.12:在过去几个月中,“房地产”这一搜索词的流行变化国家

在这种情况下,变化也可以被视为全球范围内负面变化大于正面变化。虽然一些国家如越南和泰国经历了正向变化,但更多的国家在搜索词上出现了下降。这不仅可能由投资决策引起,还可能与搜索模式相关。根据地区的不同,在大多数情况下,房地产被视为一种投资,而在其他情况下,它仅仅是为了居住或商业目的。

在接下来的部分中,我们将深入探讨经历显著变化的国家,并尝试更详细地理解其原因。

使用相关查询获取有关新趋势的洞察

如果我们想要找到与我们正在搜索的搜索词最相关的术语的更多信息,可以使用相关查询获取与我们搜索的查询相似的查询。这是有用的,因为它不仅提供了背景信息,还提供了可以进一步分析的趋势信息。

在接下来的代码块中,我们将定义一系列区域,在给定的时间范围内查找相关查询。在这种情况下,我们将查看美国、加拿大、新西兰和澳大利亚。结果将被整理成一个单一的pandas数据框:

geo = ['US','CA','NZ','AU']
d_full = pd.DataFrame()
for g in geo:
  pytrend.build_payload(kw_list=['bitcoin','stocks'],
  geo=g,timeframe='today 3-m')
  #get related queries
  related_queries = pytrend.related_queries()
  # Bitcoin top
  d = related_queries['bitcoin']['top']
  d['source_query'] = 'bitcoin'
  d['type'] = 'top'
  d['geo'] = g
  d_full = pd.concat([d_full,d],axis=0)
  # Bitcoin rising
  d = related_queries['bitcoin']['rising']
  d['source_query'] = 'bitcoin'
  d['type'] = 'rising'
  d['geo'] = g
  d_full = pd.concat([d_full,d],axis=0)
  # stocks top
  d = related_queries['stocks']['top']
  d['source_query'] = 'stocks'
  d['type'] = 'top'
  d['geo'] = g
  d_full = pd.concat([d_full,d],axis=0)
  # stocks rising
  d = related_queries['stocks']['rising']
  d['source_query'] = 'stocks'
  d['type'] = 'rising'
  d['geo'] = g
  d_full = pd.concat([d_full,d],axis=0)

这段代码将遍历定义的区域,并合并相关查询的结果,这些查询是在给定时间范围内的顶级结果,以及在该地区上升的查询。

最后,我们重置索引并显示前 10 行:

d_full = d_full.reset_index(drop=True)
d_full.head(10)

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_13.jpg

图 3.13:美国地区与比特币相似的查询

我们可以利用相关查询的信息,对与原始搜索词相关的频率和术语进行分析。这将为我们提供更好的背景,以了解特定地区某一资产的相关因素。这意味着,在这种情况下,我们可以看到搜索比特币的人也在搜索以太坊,因此我们可以预期它们之间存在一定的相关性:

  1. 让我们使用一种简单的方法,通过使用词云来展示这些查询中最频繁的术语,从而展示最重要的术语。我们将使用wordcloudmatplotlib包:

    from wordcloud import WordCloud
    
    from wordcloud import ImageColorGenerator
    
    from wordcloud import STOPWORDS
    
    import matplotlib.pyplot as plt
    
  2. 我们将使用美国与“股票”相关的顶级相关查询作为数据:

    data = d_full[(d_full['source_query']=='stocks')&(
    
          d_full['type']=='top')&(d_full['geo']=='US')]
    
  3. 之后,我们将合并所有结果列,替换源查询以避免冗余,并去除停用词。最后,代码的最后部分将生成图形并显示结果:

    text = " ".join(i for i in data['query']).replace('stock','')
    
    stopwords = set(STOPWORDS)
    
    wordcloud = WordCloud(stopwords=stopwords, background_color="white").generate(text)
    
    plt.figure( figsize=(12,8))
    
    plt.imshow(wordcloud, interpolation='bilinear')
    
    plt.axis("off")
    
    plt.show()
    

这将生成下一个词云,大小适应术语的相对频率。请注意,我们始终需要至少一个词才能绘制,否则我们将收到一个错误,提示我们得到的词数为 0。

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_14.jpg

图 3.14:美国“股票”搜索词的频繁相关查询

结果显示,“股票”这个术语主要与以下术语相关:

  • penny:指的是便士股市场

  • nowtoday:对日常频繁更新的信息和实时更新的需求

  • dividend:偏好支付股息的股票

  • amazontesla:受欢迎的股票

  • redditnews:信息来源

  • 购买投资:用户的行为

当试图获取有关驱动用户的模式的信息时,这些信息可能非常有趣。

  1. 接下来是与之前相同的代码,但现在它引用了在美国与股票相关的上升搜索词:

    data = d_full[(d_full['source_query']=='stocks')&(
    
          d_full['type']=='rising')&(d_full['geo']=='US')]
    
    text = " ".join(i for i in data['query']).replace('stock','')
    
    stopwords = set(STOPWORDS)
    
    wordcloud = WordCloud(stopwords=stopwords, 
    
          background_color="white").generate(text)
    
    plt.figure( figsize=(12,8))
    
    plt.imshow(wordcloud, interpolation='bilinear')
    
    plt.axis("off")
    
    plt.show()
    

下一幅图将展示我们原始搜索词相关的上升查询中找到的术语。这些术语的大小根据它们的频率变化,提供了它们相对重要性的信息。

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_15.jpg

图 3.15:美国与搜索词股票相关的常见热门查询

它显示了不同层次的信息,正如我们所看到的,目前正在发生的事件,例如短期内对衰退的恐惧,表明市场看涨,还有一些新股票名称,如 Twitter、Disney 和 Haliburton。

  1. 我们通过查看与新西兰比特币搜索词相关的热门查询,重复相同的练习:

    data = d_full[(d_full['source_query']=='bitcoin')&(
    
          d_full['type']=='top')&(d_full['geo']=='NZ')]
    
    text = " ".join(i for i in data['query']).replace('bitcoin','')
    
    stopwords = set(STOPWORDS)
    
    wordcloud = WordCloud(stopwords=stopwords, 
    
          background_color="white").generate(text)
    
    plt.figure( figsize=(12,8))
    
    plt.imshow(wordcloud, interpolation='bilinear')
    
    plt.axis("off")
    
    plt.show()
    

这生成了下一个词云。

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_16.jpg

图 3.16:新西兰与搜索词比特币相关的常见热门查询

在这里,我们可以看到特斯拉与比特币以及道琼斯之间的关系。后者可能表明那些想要投资比特币的人,已经在股市中有投资,或者正在考虑投资其中之一。

  1. 下一个焦点是新西兰与比特币相关的上升术语:

    data = d_full[(d_full['source_query']=='bitcoin')&(
    
          d_full['type']=='rising')&(d_full['geo']=='NZ')]
    
    text = " ".join(i for i in data['query']).replace('bitcoin','')
    
    stopwords = set(STOPWORDS)
    
    wordcloud = WordCloud(stopwords=stopwords, 
    
          background_color="white").generate(text)
    
    plt.figure( figsize=(12,8))
    
    plt.imshow(wordcloud, interpolation='bilinear')
    
    plt.axis("off")
    
    plt.show()
    

结果展示在下一个词云中。

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_17.jpg

图 3.17:新西兰与搜索词比特币相关的常见热门查询

结果显示了其他加密货币的名称,如 Cardano 和 Luna,同时我们还可以看到“崩盘”这个词,可能与后者有关。

这些可视化图表能够帮助我们一眼就识别出一些越来越重要的术语,它们通过表示每个术语的流行趋势来使用大小来展示。人类一次性吸收大量详细信息的能力有限,因此我们需要提前思考数据的讲故事方式。

分析相关查询随时间变化的表现

在获取更多关于背景信息后,我们可以追踪这些查询随时间的演变。这可以为我们提供关于在我们雷达下逐渐升温的本地趋势的有价值信息。我们将通过以下步骤进行:

  1. 我们将选择与美国比特币相关的上升查询:

    query_data = d_full[(d_full['source_query']=='bitcoin' )&(d_full['type']=='rising')&(d_full['geo']=='US')]
    
    query_data.head()
    

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_18.jpg

图 3.18:美国与比特币相关的上升查询

  1. 我们将使用排名前五的查询,追踪它们在过去 12 个月中的表现:

    kw_list = query_data.head()['query'].tolist() # list of keywords to get data
    
    # build payload
    
    pytrend.build_payload(kw_list, cat=0, timeframe='today 12-m')
    
    # Interest over Time
    
    data = pytrend.interest_over_time()
    
    data = data.reset_index()
    
  2. 最后,我们将使用 Plotly 库来展示结果,以便能够更互动地展示信息:

    import plotly.express as px
    
    fig = px.line(data, x="date", y=kw_list, title='Keyword Web Search Interest Over Time')
    
    fig.show()
    

这展示了以下图表,我们可以看到随时间推移,趋势的上升演变:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_03_19.jpg

图 3.19:查询性能随时间的变化

我们可以看到,查询在 2021 年 11 月左右达到了峰值,且表现不一。

总结

获取不同市场中特定实时趋势的信息可能会非常昂贵,但使用网页搜索引擎流量可以为我们提供有价值的工具,以分析不同地区。在本章中,我们主要关注了按国家级别进行的地区分析,但我们也可以使用不同的地区地理编码,例如 US-NY 代表纽约。

这些信息还可以与销售数据结合使用,以获得有价值的相关性,通过因果分析,能够生成一个变量,用于预测行为,正如我们将在接下来的章节中看到的那样。

接下来的章节将继续关注潜在价值的理解,但这次将聚焦于使用联合分析对产品特征进行评分的层面。

第四章:通过联合分析理解客户偏好

联合分析是用于产品和定价研究的知名方法,可以识别客户偏好,并利用这些知识选择产品特性、评估价格敏感性、预测市场份额以及预测消费者对新产品或服务的接受程度。

联合分析经常用于各种商品,包括消费品、电器、人寿保险政策、退休社区、奢侈品和航空旅行等多个领域。它可以应用于各种情境,旨在了解客户最可能购买的产品类型以及消费者在产品中最看重(和最不看重)的特性。因此,它在产品管理、市场营销和广告中被广泛使用。

联合分析对各种规模的企业都有益处,即使是小型的本地餐馆和杂货店。

在本章中,您将学习联合分析在市场研究中的应用及实验如何进行。然后,您将使用普通最小二乘OLS)模型进行联合分析,并使用不同的机器学习ML)模型预测新产品特性的表现。

本章包括以下主题:

  • 理解联合分析

  • 设计联合实验

  • 确定产品的相关属性

  • 使用 Python 和 Statsmodels 的 OLS

  • 使用更多产品特性

  • 预测新特性组合

让我们使用一些消费品零售产品的模拟数据来进行分析。

技术要求

为了能够按照本章的步骤操作,您需要满足以下要求:

  • 运行 Python 3.7 及以上版本的 Jupyter 笔记本实例。如果您有 Google Drive 帐户,也可以使用 Google Colab 笔记本运行这些步骤。

  • 对基本数学和统计概念的理解。

理解联合分析

联合分析是一种研究性统计方法,用于市场研究,以确定人们如何评估构成单一产品或服务的不同属性(特征、功能和好处)。

联合分析起源于数学心理学,其目标是确定有限数量属性的组合对受访者选择和决策的影响最大。受访者被呈现一组潜在产品或服务,并通过分析如何从这些产品中选择,隐含评估了产品或服务的每个组成部分。您可以决定使用这些隐含评分(效用或分数)创建估计市场份额、销量甚至新设计的盈利能力的市场模型。

可设计不同类型的联合研究:

  • 基于排名的联合

  • 基于评分的联合

  • 基于选择的联合

联合分析还广泛应用于社会科学和实际科学领域,包括运筹学、产品管理和营销。它通常用于服务设计、广告吸引力分析以及新产品设计的消费者接受度测试。尽管联合分析已被应用于产品布局,但也有一些人反对这种用法。

联合分析方法是系统决策分析工具中一类更广泛的权衡分析工具的子集,也被称为多属性组合建模、离散选择建模或表达偏好研究。联合分析将产品或服务拆解为其称为属性的组成部分,并测试这些组件的不同组合,以确定消费者的偏好。

在下一个图示中,我们可以看到产品是不同水平特征的组合——例如,一袋薯片可以通过品牌、口味、尺寸和价格等水平来表示:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_1.jpg

图 4.1:不同产品作为特征的独特组合

下面是这些属性和水平组合可能出现在联合选择任务中的选项方式:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_2.jpg

图 4.2:联合选择任务

联合分析采用了一种更加现实的方式,而不是仅仅询问你喜欢产品的哪些方面或哪些特征最重要。

在调查中,每个人被要求在具有相同属性水平但不同组合的产品之间做出选择。这个模型被称为基于选择的联合分析,在大多数情况下,由 8 到 12 个“对抗”产品组成。这个过程旨在模拟购买行为,越接近实际情况,效果越好。属性选择和对抗设置被设计为需要领域知识的实验。这些信息随后被用来衡量各个属性对用户购买模式的影响。

现在我们已经了解了联合分析是什么以及如何用它来衡量顾客对某些产品特征的看法,接下来我们将探讨如何设计这些实验。

设计联合实验

产品或服务领域描述为一组属性。例如,一台笔记本电脑可能具有屏幕尺寸、品牌和价格等特征。因此,每个属性可以划分为多个层级——例如,屏幕尺寸可以是 13、14 或 15 英寸。受访者将看到一组由所有或部分配置属性层级组合而成的产品、原型、模型或图片,以供选择、排序或展示进行评估。你将被要求进行排名。每个示例足够相似,消费者会认为它是一个不错的替代品,但又足够不同,使得受访者能够清晰地识别出他们的偏好。每个示例由独特的产品特征组合构成。数据可以包括单独的评分、排名,或从不同组合中进行选择。

联合设计包含四个不同的步骤:

  1. 确定研究类型

  2. 确定相关特征:

    • 与管理决策相关

    • 在现实中有不同的层级

    • 预计会影响偏好

    • 易于理解并清晰定义

    • 显示没有过度相关性(价格和品牌是例外)

    • 至少应存在两个层级

  3. 指定属性的层级:

    • 明确无误

    • 相互排斥

    • 现实的

  4. 设计问卷:随着属性和层级组合数量的增加,备选方案的数量呈指数增长。应对指数增长的方式之一是采用分数因子设计方法,这种方法通常用于减少需要检查的资料数,同时确保有足够的数据用于统计分析。这反过来会产生一组控制良好的“资料”供受访者考虑。

在设计联合实验时考虑这些要点,将使我们能够准确地建模并复制我们希望了解的消费者行为模式。我们必须时刻记住,这项分析的目的是通过尽可能模拟实际购买行为,揭示隐藏的模式。

确定产品相关的属性

如前所述,我们将进行联合分析,衡量一组用户对某个产品或服务特征的重视程度。为此,我们将进行多变量分析,确定最优的产品概念。通过评估整个产品(总体效用值),可以计算出各个元素对购买决策的影响程度(部分效用值)。例如,当用户购买 PC 时,可以确定哪些因素影响这一决策,以及影响的程度(重要性)。同样的方法也可以扩展到更多特征。

要使用的数据以不同的笔记本电脑特征组合形式呈现,涉及 RAM、存储和价格。不同的用户对这些组合进行排序。

我们将在下一个示例中使用以下 Python 模块:

  • Pandas:Python 包,用于数据分析和数据操作。

  • NumPy:Python 包,允许使用矩阵和数组,并可以使用数学和统计函数在这些矩阵上进行操作。

  • Statsmodels:Python 包,提供 SciPy 在统计计算方面的补充,包括描述性统计以及统计模型的估计和推断。它提供了用于估计多种不同统计模型的类和函数。

  • Seaborn 和 Matplotlib:Python 包,用于有效的数据可视化。

  1. 接下来的代码块将导入必要的包和函数,并创建一个带有模拟数据的示例 DataFrame:

    import numpy as np
    
    import pandas as pd
    
    import seaborn as sns
    
    import matplotlib.pyplot as plt
    
    import statsmodels.api as sm
    
    # data: Laptop spec data
    
    data = pd.DataFrame([[6000, '4GB', '128GB', 3],
    
                         [6000, '8GB', '512GB', 9],
    
                         [8000, '4GB', '512GB', 5],
    
                         [8000, '8GB', '128GB', 7],
    
                         [6000, '4GB', '128GB', 4]],
    
                        columns=['price', 'memory', 
    
                                'storage', 'score'])
    
    data.head()
    

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_3.jpg

图 4.3:产品特征及其评分

  1. 接下来的代码将把我们的数据分离成预测变量和目标变量:

    X = data[[col for col in data.columns if col != 'score']]
    
    y = data['score']
    
    X.head()
    

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_4.jpg

图 4.4:产品特征

  1. 以下代码行将使用编码的分类变量创建虚拟变量:

    X_dum = pd.get_dummies(X, columns=X.columns)
    
    X_dum.head()
    

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_5.jpg

图 4.5:产品及其特征的独热编码表示

现在,信息已经被正确编码,我们可以使用不同的预测模型来尝试预测,根据产品特征,判断每个产品的评分。在下一节中,我们可以使用 OLS 回归模型来确定变量的重要性,并推断出用户在选择购买产品时最看重的特征。

使用 Python 和 Statsmodels 的 OLS 方法

OLS,一种线性最小二乘法方法,在统计学中用于估计线性回归模型中未确定的参数。通过最小化因变量的观测值与通过自变量的线性函数预测的值之间的差异的平方和,OLS 根据最小二乘原则,从一组解释变量中推导出线性函数的参数。

提醒一下,线性回归模型建立了一个因变量(y)和至少一个自变量(x)之间的关系,公式如下:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/Formula_04_001.jpg

在 OLS 方法中,我们必须选择 https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/Formula_04_002.pnghttps://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/Formula_04_003.png 的值,使得计算值与观测值之间的差异平方和最小化。

OLS 可以用几何学的术语来描述,即所有数据点到回归面之间的平方距离之和。这个距离是平行于调整面轴线的,距离越小,面就越能更好地拟合数据。当误差是同方差且彼此不相关时,OLS 是一种特别有用的方法,当回归中使用的变量是外生的时,效果尤为显著。

当误差具有有限方差时,OLS 方法提供一个最小方差的无偏估计。OLS 在额外假设误差呈正态分布的前提下,是最大似然估计器。

我们将使用 Python 的 statsmodels 模块来实现 OLS 线性回归方法:

model = sm.OLS(y, sm.add_constant(X_dum))
result = model.fit()
result.summary()

OLS 回归过程用于估计多元数据中的线性关系,得到了一个 R 平方值为 0.978

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_6.jpg

图 4.6:OLS 模型摘要

结果摘要显示了我们一些基本信息,以及相关的指标。其中一些包括 R 平方值、用于训练模型的观测数、模型的自由度、协方差及其他信息。

在这个摘要中需要解释的一些最重要的方面是以下值:

  • 'score' 变量。由于模型的 R 平方值随着添加的变量不会下降,即使它们只贡献了很少的部分,模型也可能看起来更准确。这个属性在分析多个自变量对模型的有效性时非常重要。较低的调整 R 平方值可能表明某些变量没有充分地贡献到模型中,因为调整后的 R 平方会根据变量的数量惩罚 R 平方公式。

  • null 假设,或者说是否准确地表述变量的效应为零。你可以看到,这种情况的概率是 15.3%。

  • 截距:如果我们模型中的所有变量都设置为 0,那么截距就是结果。这是我们的 b,一个常数,用来声明经典线性方程“y = mx + b”中的起始值。这些是交点下的变量。系数是我们表格中的第一个有用列。它是我们部分的值,它衡量了每个变量变化对自变量的影响。“y = mx + b”中的“m”就是罪魁祸首,其中“m”是变量系数在自变量中的变化率,或者是因变量单位变化的结果。如果系数是负的,它们之间存在反向关系,这意味着一个变量上升时,另一个变量会下降。

  • std error:系数的标准差,或者说系数在数据点之间的变化程度,是通过 std error(或标准误差)变量来估计的,它衡量了系数测量的准确性,并与之相关。在 t 统计量较高的情况下,这意味着系数的重要性较高,这通常是由于标准误差相对较低而系数较高所产生的。

  • P>|t|:摘要中的一个最重要的统计量是 p 值。t 统计量用于生成 p 值,它表示在我们的模型中,系数由随机因素决定的可能性。一个低 p 值(如 0.278)表示有 27.8% 的概率表明所提供的变量对因变量没有影响,并且我们的结果是偶然的。p 值将与一个预先设定的 alpha 值(或阈值)进行比较,以便我们能够为我们的系数附加显著性,在适当的模型分析中进行检验。

  • [0.025 和 0.975]:是我们的系数值在 95% 数据范围内或两倍标准差范围内的测量值吗?超出这些范围的值通常可以视为离群值。数据是否包含在两个标准差之间,超出这个范围的数据可以被视为离群值?

  • Omnibus:使用偏度和峰度作为度量,Omnibus 描述了残差分布的正态性。0 表示完全正态。一个叫做 Prob (Omnibus) 的统计检验用于确定残差是否符合正态分布的可能性。1 表示完全正态的分布。偏度的范围是从 0 到完美对称,衡量数据的对称程度。峰度衡量数据的尖峭程度,或者它在正态曲线上的集中程度。较高的峰度意味着较少的离群值。

  • Durbin-Watson:数据中的同方差性,即误差的均匀分布,是通过 Durbin-Watson 统计量来衡量的。异方差性则表示不均匀分布,例如当数据点增多时,相对误差也增大。理想的同方差性应该在 1 和 2 之间。使用偏度和峰度来测量相同的 Omnibus 和 Prob (Omnibus) 值的替代方法是 Jarque-Bera (JB) 和 Prob。这些理想方法帮助我们相互验证。衡量我们的模型对所处理数据变化的敏感度的指标是条件数。许多不同的条件强烈暗示多重共线性,这是一个用来描述两个或多个自变量彼此强相关,并且通过冗余错误地影响我们预测变量的术语。

在我们的案例中,我们将使用数据的结果,并将变量名称、权重和 p 值存储在 DataFrame 中,稍后我们将用它来绘制数据:

data_res = pd.DataFrame({'name': result.params.keys(),
                         'weight': result.params.values,
                         'p_val': result.pvalues})
data_res = data_res[1:]
data_res

查看 p 值时,如果显著性水平低于 5%,这可能表明该变量在统计学上不显著:

data_res = data_res.sort_values(by='weight')
data_res

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_7.jpg

图 4.7:产品特征的权重和 p 值

虽然考虑 p 值以建立统计显著性水平很重要,但模型应该包含所有变量。在这里,我们可以使用 Prob (F 统计量),在我们的案例中该值大于 0.05,因此我们无法拒绝原假设。通过查看一个非常高的 R 平方值,我们可以看到模型存在过拟合。我们需要更多的数据来创建一个显著的模型,但这个挑战我会留给你。

下一个截图显示了按相对权重排序的产品特征。在这种情况下,用户对 8GB 内存的评价较高,其次是 128GB 存储:

sns.set()
xbar = np.arange(len(data_res['weight']))
plt.barh(xbar, data_res['weight'])
plt.yticks(xbar, labels=data_res['name'])
plt.xlabel('weight')
plt.show()

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_8.jpg

图 4.8:按权重排序的产品特征

可以看出,内存在评价中的贡献最大,其次是存储。

我们已经看到 OLS 如何作为一种手段来估计每个产品特征的重要性。在这种情况下,它被建模为对单一变量的回归,但我们可以包括有关响应者类型的信息,以发现不同的客户群体如何对产品特征做出反应。

在下一部分,我们评估一个具有更多特征的消费品案例。

使用更多的产品特征

在这个示例中,我们将使用一个包含比前一个示例更多特征的数据集。在这种情况下,我们将模拟来自一家脆片零售商的数据,该零售商已要求一些客户根据他们的偏好程度对其产品进行排名:

  1. 以下代码块将读取数据集,该数据集为 CSV 文件,并将提示我们显示结果:

    # Load data
    
    conjoint_dat = pd.read_csv('/content/conjoint_data.csv')
    
    conjoint_dat
    

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_9.jpg

图 4.9:脆片数据

  1. 我们可以看到数据仅包含分类值,因此需要使用get_dummies pandas 函数将这些分类数据转换为独热编码向量表示,这就是我们在下一个代码块中所做的:

    conjoint_dat_dum = pd.get_dummies(conjoint_dat.iloc[:,:-1], columns = conjoint_dat.iloc[:,:-1].columns)
    
    conjoint_dat_dum
    

我们可以看到现在我们已经创建了一组列,这些列用 1 和 0 描述了产品特征:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_10.jpg

图 4.10:脆片数据的独热编码表示

  1. 我们现在可以构建一个 OLS 模型,使用产品特征的独热编码向量表示,并将排名作为目标变量:

    main_effects_model_fit = sm.OLS(conjoint_dat['ranking'].astype(int), sm.add_constant(conjoint_dat_dum))
    
    result = main_effects_model_fit.fit()
    
    result.summary()
    

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_11.jpg

图 4.11:OLS 回归结果

模型摘要中的AICBIC术语,分别代表赤池信息准则贝叶斯信息准则,是模型选择标准中常用的术语;然而,它们是不可互换的。BIC 是一个从包含变量参数数量不等的参数模型类中选择模型的方法,而 AIC 可以被看作是估计统计模型拟合优度的度量。BIC 对额外参数的惩罚比 AIC 更大。BIC 对自由参数的惩罚比 AIC 更严厉。

AIC 通常会寻找未发现的具有高维实际情况的模型。这表明 AIC 模型并不准确。另一方面,BIC 仅会遇到True模型。此外,BIC 是一致的,尽管 AIC 可能不一致,可以这么说。BIC 会指示出可能的欠拟合风险,而 AIC 则更适合用来检查模型是否存在过度拟合的风险。尽管 BIC 比 AIC 更宽容,但随着数量的增加,它变得不那么宽容。通过 AIC,交叉验证可以渐近相等。另一方面,BIC 对于精确估计非常有用。

在比较 BIC 和 AIC 时,BIC 对额外参数的惩罚比 AIC 更高。AIC 通常会寻找一个具有高维实际情况的未识别模型。另一方面,BIC 仅会找到True模型。AIC 是不一致的,而 BIC 是一致的。尽管 BIC 比 AIC 更宽容,但随着数量的增加,它变得不那么宽容。BIC 对自由参数的惩罚比 AIC 更严厉。

  1. 接下来的代码将创建一个数据框,用于存储来自分析的最重要的值,在此情况下为权重和 p 值:

    data_res = pd.DataFrame({'name': result.params.keys(),
    
                             'weight': result.params.values,
    
                             'p_val': result.pvalues})
    
    data_res = data_res[1:]
    
    data_res
    

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_12.jpg

图 4.12:OLS 变量权重和 p 值

  1. 现在我们已经排列好了这些值,我们可以检查每一个关系的显著性,以检查假设的有效性并可视化权重:

    xbar = np.arange(len(data_res['weight']))
    
    plt.barh(xbar, data_res['weight'])
    
    plt.yticks(xbar, labels=data_res['name'])
    
    plt.xlabel('weight')
    
    plt.show()
    

这将产生以下输出

:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_8.jpg

图 4.13:按重要性排序的变量权重

在这种情况下,可以看出有一些因素是正相关的,比如 100 克的重量和产品为无脂肪的选项,而其他因素是负相关的,比如 400 克的重量,接着是产品不是无脂肪的。

可能出现的一个问题是:如果我们有一个回归模型来估计产品得分,能否使用同一个模型预测客户如何对新产品组合做出反应? 从理论上讲,我们可以,但在这种情况下,我们必须使用评分系统而非排名,并且需要更多更多的数据。为了演示的目的,我们将继续进行,因为这些数据难以获得,甚至更难披露。

预测新特征组合

现在我们已经正确训练了预测模型,除了捕获产品特征的重要性外,我们还可以利用它为我们提供关于新产品特征表现的信息:

  1. 在完成 EDA(探索性数据分析)之后,我们将开发一些预测模型并进行比较。我们将使用已创建虚拟变量的数据框架,并将所有变量缩放到 0 到 1 的范围内:

    from sklearn.preprocessing import StandardScaler
    
    X = conjoint_dat_dum
    
    y = conjoint_dat['ranking'].astype(int)
    
    # The target variable will be normalized from a ranking to a 1 to 10 score
    
    y = y.apply(lambda x: int(x/len(y)*10))
    
    features = X.columns.values
    
    scaler = StandardScaler()
    
    scaler.fit(X)
    
    X = pd.DataFrame(scaler.transform(X))
    
    X.columns = features
    

这将导致以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_14.jpg

图 4.14:标准化变量

最受欢迎的机器学习模型之一是逻辑回归,它是一种利用自变量进行预测的算法。该算法可以用于分类和回归任务。它是一种监督学习算法,需要数据标注。该算法利用示例答案来拟合模型,以达到目标变量,在我们这里就是产品排名。从数学角度来看,该模型旨在根据一组自变量 X 预测 Y。逻辑回归可以分为二元逻辑回归和多项式逻辑回归。这两者的特点可以描述如下:

  • 二元:所有类型的逻辑回归中使用最广泛的是二元逻辑回归,算法旨在区分 0 和 1,这一任务被视为分类问题。

  • 多项式:当目标或自变量具有三个或更多潜在值时,使用多项式逻辑回归。例如,利用胸部 X 光的特征可以指示三种可能的结果之一(无病、肺炎或纤维化)。在这种情况下,示例根据特征被排序成三种可能的结果之一,使用的是多项式逻辑回归。当然,目标变量可以有超过三个可能的值。

  • 有序逻辑回归:如果目标变量本质上是有序的,则使用有序逻辑回归。在这种类型中,每个类别都有定量意义,并且具有明显的顺序。此外,目标变量包含的不仅仅是两个类别。例如,考试结果根据定量标准进行分类和排序。简单来说,成绩可以是 A、B 或 C。

  1. 线性回归和逻辑回归的主要区别在于,逻辑回归用于解决分类问题,而线性回归用于解决回归问题。回归问题中的目标变量可能具有连续值,例如产品价格或参与者年龄,而分类问题则涉及预测仅具有离散值的目标变量,例如确定一个人的性别或肿瘤是良性还是恶性:

    # Logistic Regression
    
    from sklearn.model_selection import train_test_split
    
    from sklearn.linear_model import LogisticRegression
    
    from sklearn import metrics
    
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=101)
    
    # Running logistic regression model
    
    model = LogisticRegression()
    
    result = model.fit(X_train, y_train)
    

通过将训练集特征及其匹配的目标类别值输入模型,模型可以被训练。这将帮助模型学习如何对新案例进行分类。评估模型在尚未遇到的实例上的表现至关重要,因为只有当它能够准确分类那些不属于训练集的示例时,模型才会有用。

误差平方的平均值由真实值来衡量。

  1. MSE 始终为正,尽管如果预测完全准确,MSE 可以为 0。它包括估计器的方差(估计值的分布范围)和偏差(估计值与实际值之间的差异):

    prediction_test = model.predict(X_test)
    
    # Print the prediction accuracy
    
    print(metrics.mean_squared_error(y_test, prediction_test))
    

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_15.jpg

图 4.15:简单回归的 MSE

  1. MSE 始终为 0 或正值。如果 MSE 很大,这意味着线性回归模型预测不准确。重要的一点是,MSE 对异常值很敏感。这是因为每个数据点的误差是平均的。因此,如果异常值的误差很大,MSE 将被放大。MSE 没有“目标”值。然而,MSE 是衡量模型如何拟合数据的良好指标。它还可以帮助你判断是否更倾向于选择一个模型而非另一个:

    # To get the weights of all the variables
    
    weights = pd.Series(model.coef_[0],
    
                     index=X.columns.values)
    
    print(weights.sort_values(ascending = False)[:10].plot(kind='bar'))
    

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_16.jpg

图 4.16:线性回归顶级变量贡献

在这里,我们可以看到模型识别为与得分正相关的前 10 个变量。

  1. 接下来的代码将显示那些与结果负相关的变量:

    print(weights.sort_values(ascending = False)[-10:].plot(kind='bar'))
    

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_17.jpg

图 4.17:线性回归负向变量贡献

随机森林是一种监督学习SL)算法。它既可以用于分类,也可以用于回归。此外,它是最具适应性和用户友好的算法。森林中有很多树。森林中的树木越多,它应该越强大。在随机选择的数据样本上,随机森林生成决策树,从每棵树中获取预测结果,然后投票选出最佳选项。它们还提供了特征重要性的相当准确的指示。

随机森林的应用包括特征选择、图片分类和推荐引擎。它们可以用于分类可靠的贷款候选人、发现欺诈行为和预测疾病。

随机森林是一种元估计器,它通过采用均值来提高预测准确性并减少过拟合。它在多个数据集子样本上拟合多个决策树分类器。如果bootstrap = True(默认设置),子样本的大小由max_samples参数指定;否则,每棵树都是使用完整的数据集构建的。在随机森林中,集成中的每棵树都是使用从训练集中提取的样本(即,带有替代的样本)构建的。此外,在构建树时,每次拆分节点时,都会发现所有输入特征或任何max_features大小子集的最佳分割。

这两种随机源用于降低森林估计器的方差。实际上,单个决策树常常过拟合并具有较大的方差。通过将随机性引入森林,会生成具有部分不相关预测误差的决策树。通过对这些预测进行平均,可以帮助某些误差消失。通过合并多棵树,随机森林减少了方差,有时会稍微增加一些失真。实际上,方差减少通常较大,从而产生一个更强大的整体模型。

scikit-learn 的实现并不是让每个分类器选择单一类别,而是通过对其概率预测取平均来组合多个分类器:

from sklearn.ensemble import RandomForestClassifier
model_rf = RandomForestClassifier(n_estimators=1000 , oob_score = True, n_jobs = -1,random_state =50, max_features = "auto",max_leaf_nodes = 30)
model_rf.fit(X_train, y_train)
# Make predictions
prediction_test = model_rf.predict(X_test)
print(metrics.mean_squared_error(y_test, prediction_test))

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_18.jpg

图 4.18:随机森林均方误差

机器学习模型的一个可选算法是随机森林算法,该算法在 scikit-learn 包中实现,包括RandomForestRegressorRandomForestClassifier类。这些类可以被拟合到数据中,从而得到一个模型,该模型随后可以用来进行新预测或获取关于特征重要性的信息,这是联合分析的重要核心,如以下示例所示:

importances = model_rf.feature_importances_
weights = pd.Series(importances, index=X.columns.values)
weights.sort_values()[-10:].plot(kind = 'barh')

这将产生以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_19.jpg

图 4.19:随机森林特征重要性

XGBoost 库是一个高效、适应性强且便于分布式梯度增强的库。它在梯度提升框架内应用机器学习技术,并提供并行树增强(也称为 GBDT 和 GBM),能够快速准确地解决各种数据科学问题。相同的代码可以处理涉及超过万亿个样本的问题,并在大规模分布式环境中运行。

它是最近在多个机器学习竞赛中获胜算法的主要推动力。由于其无与伦比的速度和性能,它在监督学习任务中经常超过所有其他算法。

主要算法可以在 GPU 集群或甚至 PC 网络上运行,因为该库是可并行化的。这使得在数亿训练实例上进行训练并以高性能解决机器学习任务成为可能。

在赢得一项重要的物理学竞赛后,它迅速被机器学习社区所接受,尽管最初是用 C++编写的:

from xgboost import XGBClassifier
model = XGBClassifier()
model.fit(X_train, y_train)
preds = model.predict(X_test)
metrics.mean_squared_error(y_test, preds)

这产生了以下输出:

https://github.com/OpenDocCN/freelearn-ds-pt4-zh/raw/master/docs/art-dtdvn-biz/img/B19026_04_20.jpg

图 4.20:随机森林 MSE

我们可以看到,随机森林的均方误差(MSE)甚至大于线性回归。这是因为数据不足以获得更好的得分,所以在接下来的步骤中,我们需要考虑增加数据点的数量来进行分析。

摘要

在本章中,我们学习了如何进行联合分析,这是一种统计工具,可以帮助我们揭示消费者偏好,这些偏好通常难以确定。我们进行分析的方式是使用 OLS 估算不同特征组合的表现,并尝试隔离每个可能配置对客户总体感知的影响,以揭示消费者认为的价值所在。

这使我们能够创建一个概述,了解驱动用户购买产品的因素,甚至能够通过使用机器学习算法预测新特征组合的表现。

在下一章中,我们将通过研究价格变化与销售数量之间的关系,使用价格弹性来学习如何调整商品价格。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值