为机器学习准备数据
当我去 Amazon.com 时,这家在线商店经常推荐我应该购买的产品。我知道我不是唯一一个认为这些推荐可能相当诡异的人——通常它们是我已经在其他地方购买过的产品,或者是我正在考虑购买的产品。亚马逊是如何做到的?就此而言,Facebook 和 LinkedIn 如何知道建议我与我已经认识但尚未在线联系的人建立联系?
简而言之,答案是“数据科学”,这是一个相对较新的领域,它结合了编程和统计学,以便理解我们在现代世界中创建的大量数据。在数据科学领域内,机器学习使用软件创建统计模型,以发现我们数据中的相关性。这些相关性可以帮助推荐产品、预测公路交通、个性化定价、展示适当的广告或识别图像。
因此,在本文中,我将着眼于机器学习及其可以完成的一些惊人事情。我越来越觉得机器学习有点像宇宙——已经很广阔并且一直在扩张。我的意思是,即使您认为自己错过了机器学习的浪潮,现在开始也永远不会晚。此外,其他所有人也都在努力跟上机器学习的所有技术、算法和应用。
在本文中,我着眼于分类和“监督学习”的简单应用,解决了一个多年来困扰科学家和研究人员的问题:究竟是什么造就了完美的墨西哥卷饼?在此过程中,您有望开始理解机器学习领域中的一些技术和思想。
问题如上所述,这个问题相对容易理解:墨西哥卷饼是一种受欢迎的食物,尤其是在南加州。您可以在许多地方买到墨西哥卷饼,通常包含肉、奶酪和蔬菜的组合。墨西哥卷饼的价格差异很大,其大小和质量也是如此。神经科学博士生斯科特·科尔与他的朋友们争论的不仅是哪里可以买到最好的墨西哥卷饼,还包括哪些因素导致墨西哥卷饼更好或更差。显然,解决这个问题的最佳方法是收集数据。
现在,您可以想象一个简单的墨西哥卷饼质量评级系统,就像亚马逊等服务使用的那样:要求人们在 1-5 分的范围内对墨西哥卷饼进行评分。如果有足够的评分,这将表明哪些墨西哥卷饼最好,哪些最差。
但是,科尔作为一名优秀的研究人员,明白简单的一维评级可能是不够的。多维评级系统将使评级更接近(因为它们将更集中),但它也让他能够理解墨西哥卷饼的哪些方面对其高质量最重要。
结果记录在 科尔的 GitHub 页面上,他在其中描述了他和他的研究伙伴所做的细致而令人印象深刻的工作,他们带着卷尺和秤去吃午餐(为了测量和称量墨西哥卷饼),并为了科学的进步而牺牲自己。
除了娱乐因素——我不得不承认,每当我读到这个项目时,我都很难停止傻笑——这可以被视为一个严肃的数据科学项目。通过创建机器学习模型,您不仅可以描述墨西哥卷饼的质量,还可以无需任何烹饪或食用,确定潜在或理论上的墨西哥卷饼的质量。
数据一旦科尔确定他和他的研究伙伴将从多个维度对墨西哥卷饼进行评分,下一个显而易见的问题是:应该测量哪些维度?
这是数据科学中要问的关键问题。如果您测量了错误的问题,那么即使使用最好的分析方法,您的输出和结论也会是错误的。实际上,凯西·奥尼尔的一本精彩的新书《数学杀器》展示了收集和使用错误的输入如何导致人们的工作、医疗保健和安全遭受灾难性后果。
因此,您要测量正确的事情。但同样重要的是测量不同的事情。为了使统计分析有效,您必须确保您的每个度量都是独立的。例如,假设墨西哥卷饼的大小将纳入质量测量。您不想同时测量体积和长度,因为这两个因素是相关的。通常很难或不可能完全分离两个相关因素,但您可以并且应该尝试这样做。
同时,考虑一下这项研究是如何进行的。研究人员正在进入现场(研究人员的说法是“出去吃午饭”)并吃他们的墨西哥卷饼。他们可能只有一次机会收集数据。这意味着收集比必要更多的数据可能是有意义的,然后只使用其中的一部分来创建模型。这被称为“特征选择”,是构建机器学习模型的一个重要方面。
科尔和他的同事决定测量墨西哥卷饼质量的十个不同方面,从体积到温度到莎莎酱质量。他们还记录了价格,以查看价格是否是质量的因素。他们还有两个一般测量值:总体评分和推荐。所有这些测量值都在 0-5 分的范围内进行,其中 0 表示非常差,5 表示非常好。
重要的是要指出,他们收集了十多个维度的数据,但这并不意味着所有这些测量都需要包含在模型中。然而,这让研究人员有机会进行特征选择,确定哪些因素对墨西哥卷饼质量的影响最大。
我从 Google Docs 中一个公开可见的 电子表格下载了科尔的数据,其中 30 人在 31 家不同的餐厅对 100 多个墨西哥卷饼进行了评分,并将数据导入到一个 CSV 文件(burritos.csv)中。
然后,我启动了 Jupyter(又名 IPython)Notebook,这是数据科学领域常用的工具。在笔记本中,我运行了以下命令来设置我的环境
%pylab inline # load NumPy, display
# Matplotlib graphics
import pandas as pd # load pandas with an alias
from pandas import Series, DataFrame # load useful Pandas classes
df = pd.read_csv('burrito.csv') # read into a data frame
此时,Pandas 数据帧包含有关墨西哥卷饼的所有信息。在继续之前,我需要确定哪些字段是输入(“自变量”,也称为“预测变量”),哪些是输出(“因变量”)。
例如,假设墨西哥卷饼是使用单个因素(即价格)来衡量的。价格将是输入/自变量,质量评分将是输出/因变量。然后,模型将尝试从输入映射到输出。
机器学习(和统计模型)的工作方式相同,只是它使用多个自变量。它还可以帮助您确定每个输入对输出的影响程度。
首先,您需要检查您的数据,并确定哪一列是因变量(输出)。在墨西哥卷饼的情况下,我选择了电子表格 X 列中的 0-5 总体评分。您可以使用以下代码在 Pandas 中查看总体评分
df['overall']
这将返回一个 Pandas 系列,表示来自特定餐厅所有样本的平均总体评分。
既然我已经确定了我的输出,那么我应该选择哪些输入呢?这就是我之前描述的,即特征选择。您不仅要选择相对较少的特征(以使模型运行更快),还要选择那些真正会影响输出并且彼此不混淆的特征。
让我们首先删除除特征列之外的所有内容。与其删除我认为不感兴趣的列,不如创建一个新的数据帧,其值取自此数据帧中感兴趣的列。我想要索引为 11 到 23 的列,这意味着我可以在 Pandas 中发出以下命令
burrito_data = df[range(11,23)]
range()
是一个 Python 函数,它返回一个迭代器;在本例中,迭代器将返回 11 到 22(即,直到但不包括 23)。通过这种方式,您可以检索较小数据帧中的某些列。但是,您仍然需要精简您的特征。
请注意,我的新数据帧仅包含自变量(输入);总体评分(我们的输出变量)暂时保留在一边。
特征选择现在我有了所有的输入变量,我应该选择哪些?哪些变量更依赖于彼此?我可以创建一个“相关矩阵”,为我提供一个介于 0(不相关)和 1(完全相关)之间的数值。如果我在数据帧上调用“corr”方法,我将获得一个新的数据帧,显示它们之间的所有相关性——对角线的相关性为 1.0
burrito_data.corr()
现在,的确,您可以查看此内容并在某种程度上理解它。但是,对于人类来说,理解图像通常更容易。因此,您可以使用 matplotlib,调用以下代码
plt.matshow(burrito_data.corr())
这将生成一个美观的全彩色相关矩阵,其中相关性越高,颜色越红。红色方块显示(例如)“长度”和“体积”之间存在高度相关性(不足为奇),“肉”和“协同作用”之间也存在高度相关性。
另一个考虑因素是:特定输入变量随时间的变化程度如何?如果它始终大致相同,则在统计模型中毫无用处。例如,假设研究人员吃过的所有地方的墨西哥卷饼价格都相同。在这种情况下,尝试查看价格会产生多大影响是毫无用处的。
您可以使用 Pandas 的“var”方法来告诉您这一点。当我执行 burrito_data.var()
时,我得到一个 Pandas 系列对象
burrito_data.var()
Length 4.514376
Circum 2.617380
Volume 0.017385
Tortilla 0.630488
Temp 1.047119
Meat 0.797647
Fillings 0.765259
Meat:filling 1.084659
Uniformity 1.286631
Salsa 0.935552
Synergy 0.898952
Wrap 1.384554
dtype: float64
您可以看到墨西哥卷饼的体积变化很小。因此,您可以考虑在构建模型时忽略它。
这里还有另一个考虑因素:来自所有这些特征的输入数据是否足够?有一些数据丢失是正常的;有几种方法可以处理这个问题,但其中一种方法只是尝试在没有丢失数据的情况下使用该特征。您可以使用数据帧上的“count”方法来查找哪些列可能缺少太多数据而无法忽略
burrito_data.count()
Length 127
Circum 125
Volume 121
Tortilla 237
Temp 224
Meat 229
Fillings 236
Meat:filling 231
Uniformity 235
Salsa 221
Synergy 235
Wrap 235
dtype: int64
如您所见,与墨西哥卷饼大小相关的三个输入的大量数据点丢失了。根据科尔的说法,这是因为研究人员在许多外出活动中没有带卷尺。(这也是为什么我坚持每次和朋友出去吃饭都要带卷尺的原因之一。)
最后,您可以要求 scikit-learn 告诉您哪些预测变量对输出的贡献最大或最小。您在数据帧中向 scikit-learn 提供输入,并在系列中提供输出——例如
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
X = burrito_data
y = df[[23]]
在上面的代码中,我导入了一些我需要的对象,以便帮助进行特征选择。然后,我为输入矩阵和输出系列使用 scikit-learn 中传统的名称 X 和 y。然后,我要求识别最重要的特征
sel = SelectKBest(chi2, k=7)
sel.fit_transform(X, y)
请注意,在调用 SelectKBest
时,您必须为“k”提供一个值,该值指示您希望返回多少个预测变量。通过这种方式,您可以尝试将大量预测变量减少到少量。但是,如果您尝试使用上述方法运行,您会遇到问题。如果您的输入矩阵中缺少数据 (NaN),SelectKBest
将拒绝运行。因此,最好发现您的哪些输入有时会丢失;如果您从输入矩阵中删除这些列,则可以使用一些特征缩减。
科尔和他的同事进行了这种分析,发现他们可以删除一些输入列——“风味协同作用”以及与墨西哥卷饼大小相关的列。在经历了上述过程之后,我相信您可以轻松理解原因。
结论现在您有了一个良好的数据集——包含输入矩阵和输出系列——您可以构建模型了。这涉及选择一种或多种算法,将数据输入到其中,然后测试模型以确保它没有过拟合。
在我的下一篇文章中,我计划完全这样做——从这里获取数据,并了解如何构建机器学习模型。我希望您会看到 Python 和 scikit-learn 使实际开发过程变得多么容易。但是,我仍然需要花时间思考我在做什么以及我将如何做,以及哪些工具最适合这项工作。
资源在本文中,我使用了 Python 和 SciPy 堆栈的许多部分(NumPy、SciPy、Pandas、matplotlib 和 scikit-learn)。所有这些都可从 PyPI 或 SciPy.org 获得。
我为对数据科学和机器学习感兴趣的人推荐了一些资源。
一个长期存在的每周电子邮件列表是 “KDNuggets”。您还应该考虑 Data Science Weekly 新闻通讯和 This Week in Data,其中描述了可供公众使用的最新数据集。
我是播客的忠实粉丝,特别喜欢“Partially Derivative”。其他好的播客还有“Data Stores”和“Linear Digressions”。我定期收听所有这三个播客,并从中学习。
如果您想进入数据科学和机器学习领域,我推荐 Kevin Markham 的 Data School 和 Jason Brownlie 的 “Machine Learning Mastery”,他在那里出售了许多关于这些主题的简短、内容密集但高质量的电子书。
正如我在本文正文中提到的,凯西·奥尼尔的新书《数学杀器》发人深省且引人入胜,而且令人不安。我强烈推荐它。
最后,感谢斯科特·科尔,他的墨西哥卷饼评级工作准备充分、文笔流畅且执行出色,他与在线社区分享了他的成果,为每个人的专业和烹饪利益做出了贡献。