用神经网络和随机森林预测微量营养素(下)
联合国儿童基金会希望你利用机器学习的力量,帮助他们预测食物中的重要营养成分。
欢迎回来!很高兴你能加入我的“使用神经网络和随机森林预测微量营养素”系列的第 2 部分。
在之前的博文中,我提到了联合国儿童基金会邀请我们加入他们的数据科学团队,通过使用机器学习的力量来预测某些食物中的微量营养素成分。
此外,我们还对来自美国农业部的数据集进行了数据清理。
现在,我们将进入几乎每个数据科学项目中最令人兴奋的部分之一,构建机器学习模型。
你可能从标题本身就能看出,我们将使用随机森林和神经网络来构建模型。但是对于第 2 部分,我们还没有进展到神经网络。
事实上,建议您在从事数据科学或机器学习项目时,从使用简单的模型开始,逐步转向更复杂的模型。
好的,我们在联合国儿童基金会数据科学团队的同事正在会议室等我们,所以让我们开始建立机器学习模型吧。
概观
这篇博文包含以下内容:
- 介绍
- 机器学习简介
- 多元线性回归:线性回归和多元回归
- 随机森林:决策树和引导
机器学习简介
在本系列的第一部分中,我提到了一些资料,这些资料是任何人能够更好地理解我在本系列中所谈论的内容的先决条件。
其中一个是关于“机器学习导论”然而,我决定我们应该做一个小的介绍来保持这篇博文的流畅。
但是如果你想获得更好的理解,我强烈推荐你阅读这篇由维哈尔·鞍马写的博客。
什么是机器学习?
我们将不得不对这个问题有更多的批判,因为已经有很多尝试来定义什么是机器学习,什么不是机器学习。这里有几个例子。
机器学习:在没有明确编程的情况下赋予计算机学习能力的研究领域。
阿瑟·塞缪尔(1959)
20 世纪 50 年代,亚瑟·塞缪尔(Arthur Samuel)编写了一个程序,让计算机通过与自己对弈来学习下跳棋。最后连 Samul 自己都在跳棋中输给了自己的程序。
第二个定义可能是机器学习社区中最流行和最知名的。
适定的学习问题:如果一个计算机程序在 T 上的表现,如 P 所测量的,随着经验 E 的增加而提高,那么就说它从关于某个任务 T 和某个表现测量 P 的经验 E 中学习。
汤姆·米切尔(1998)
让我们以目前的任务为例,预测某些食物中的微量营养素。
在这种情况下,E 是每种食物中营养成分数量的记录,T 是根据其他营养成分预测微量营养素的任务,P 是预测值与实际值的差距。
E: the records of the amount of nutrient composition within each food. T: the task of predicting the micronutrients based on other nutrients. P: how far are the predicted values from the ground truth.
在通常的实践中,当涉及到任务时,有三种不同类型的机器学习算法:
- 监督学习。当我们有输入变量和输出变量进行训练时,这就是我们实际在做的事情。
- 无监督学习。它与监督学习基本相同,但没有输出变量。
- 强化学习。这种类型的机器学习处理没有输入或输出变量的任务。相反,计算机程序将与动态环境交互,通过试错来实现某个目标。
当谈到监督学习时,我们实际上试图学习一个将输入变量映射到输出变量的函数。
这个函数的形式是未知的,我们的工作是评估各种机器学习算法,并观察哪种算法在逼近底层函数方面更好。
我们认为函数的另一种方式就像一个永远无法打开的魔法盒子。但是这个盒子可以接受输入,并根据输入做出预测。
例如,如果你把一封来自可疑未知电子邮件放入邮箱,它可以 100%正确地告诉你这是一封垃圾邮件还是你的一个朋友刚刚创建了一封新邮件。
既然我们看不到盒子里面是什么,那么也许我们可以创造出类似于那个盒子的东西。这个东西的形式不一定是盒子。它可以是球形、棱柱形或任何其他形状。
(假设我们以一个球结束)
最重要的是我们的球可以做出和魔盒预测一样好的近似。这意味着它可以正确预测 99%而不是 100%。
多元线性回归
正如我之前提到的,当处理一个数据科学或机器学习项目时,建议我们从更简单的模型开始。
在这里,我们将介绍多元线性回归并使用 Scikit-learn 实现它。
线性回归
线性回归是预测建模中使用最广泛的机器学习算法之一。它也通常在监督学习场景中实现。
它被称为线性模型,因为它推断出我们的输入和输出变量之间的线性关系。基本上,它给了我们一个类似下图的线性方程
注意——当我们谈论线性回归时,输入和输出变量通常分别被称为自变量和因变量。我将交替使用这两个术语。这也适用于系数、权重和参数。
在上面的等式中,我们有一个因变量,y,和一个自变量,x。此外,我们还有两个β,它们是线性等式的系数。
ε是随机采样产生的误差项。
第一个系数(beta null)是截距项,而第二个系数(beta one)是分配给变量的权重。权重表示变量的重要性。
这意味着如果 beta one 是 2.5,那么我们的变量(x one)的单位也会增加 2.5。
请注意,上面的等式只有一个变量和一个系数。当我们有一个以上的变量时,假设有 n 个变量,那么我们需要在方程中包含 n 个系数。
当我们使用多变量线性回归建立预测模型时,它通常被称为多变量线性回归。
Based on the preprocessing step that we’ve done in the previous blog post, we have 43 input variables for training. That means we will have 44 coefficients (43 for each variable plus the intercept term).
线性模型的目标是通过最小化残差平方和(RSS)来找到最佳学习数据的参数。
RSS 是真实值 y 和模型预测值ŷ(发音为 y-hat)之间的平方差总和,表示估计值。
在这篇博文中,我们不打算讨论 RSS 的细节。对详细的解释和推导感兴趣的可以查看这里。
好吧,让我们在这里等一会儿。你能发现我们的讨论遗漏了什么吗?与我们提议的任务特别相关的东西?
如果你在想“但是我们有不止一个输出标签”或者“为什么线性方程中只有一个 y ?”那你应该升职了我的朋友(开个玩笑,也许一颗糖就够了?)
当我们必须预测一个输出变量的值时,这被称为**单变量回归。**事实上,这在你能在网上找到的大多数线性回归教程中都很常见。
但是当我们有不止一个输出变量时该怎么办呢?
多变量回归
在我们必须对多个输出变量进行预测的情况下,这被称为多元回归,我们将首先简要介绍一下。
还记得我们刚才谈到的线性方程吗?我们实际上可以进一步扩展这个公式,看起来像这样
基本上,我们现在有了更多的因变量、参数和误差项。我们的目标类似于单变量回归。只是这一次,我们必须找到最小化所有输出变量 RSS 的参数。
而且,这意味着我们现在有 264 个参数(44x6),而不是 44 个参数需要估计。
哇,真多,对吧?不完全是。这在大多数机器学习实践中很常见。尤其是当我们谈论深度学习时,我们可以拥有数千个参数。
我们不打算在多元回归的背景下讨论 RSS。然而,如果你想知道更多关于多元回归的细节,请参考这张幻灯片。
对于不熟悉统计学的人来说,这张幻灯片可能太专业了。但是如果你感兴趣,试试吧!
接下来,我们将使用 Scikit-learn 实现多元线性回归。如果需要的话,别忘了休息一下。
是时候编码了!
好了,我们终于要开始编码了。确保您安装了 Scikit-learn。此外,我们将在这一部分进行数据可视化,因此请确保您还拥有 Matlotlib 和 Seaborn。
在我们构建模型之前,让我们使用一些可视化来更好地理解我们的数据。
让我们分析每两个变量之间线性关系的强度。这也就是每两个变量之间的 相关性 。
我们可以使用 pandas 提供的corr
属性构建一个相关矩阵。
您将看到类似这样的输出。
啊,看看这些数字!我认为我们应该以这样一种方式让我们的团队成员能够更好地理解这种相关性。
让我们使用 Seaborn 来可视化相关矩阵。我们可以使用中的一小段代码来快速制作相关矩阵的热图。
通过一些小的调整,我们可以运行下面几行代码…
…应该会出现类似下面这样的内容。
好吧,这样看起来好多了。让我们来看看。
我们可以看到,其中一些营养素与其他营养素要么正相关,要么不相关,而只有一对是负相关的。
想知道正相关、负相关、无相关的区别,请看这里的。
虽然相关矩阵直观地显示了每两个变量之间的线性关系,但它并没有解释两个变量是否会导致彼此上升或下降。
事实上,很多时候你这里会有大量参与统计(包括机器学习)的人说类似“相关性不会导致因果关系”或者“相关性并不意味着因果关系”。
出于这个原因,绘制我们的数据是一个好主意,以便更好地了解每个变量之间的关系。
让我们用 Matplotlib 来做这件事吧!
看起来碳水化合物和铁呈正相关。我们可以使用下面一行代码来绘制数据。
嗯,看起来尽管相关矩阵表明碳水化合物和铁是正相关的,但它们似乎缺乏 共线性 。
这就是为什么在建立模型之前绘制数据很重要。
好的,回到我们的数据,在图的底部看起来很混乱。不如我们用纤维和铁再试试。
看起来纤维和铁也是一样的。然而,在这种情况下,数据点都杂乱地堆在图的左下方。
另一个需要注意的是图上显示的 异常值 的高可变性。
显然,如果我们的最初目标是基于碳水化合物或纤维的量来预测铁的量,线性模型肯定会显示出较差的结果。
但是,我们在这里处理多个变量,让我们从 2D 进入三维。同样,Matplotlib 提供了一种绘制 3D 图的好方法。
好的,现在这个图明确显示了线性模型在这里不适用。我们的数据是高度非线性的,使用线性回归不会给我们带来任何好的表现。
不过为了好玩,还是试试吧。
首先,我们需要在一个训练和测试集中拆分输入数据和标签。Scikit-learn 的train_test_split
函数使这个过程变得很方便。
我们将把 75%的数据分配给训练集,15%的数据分配给测试集。
在大多数实践中,强烈建议我们应该增加一个叫做验证集的集合。但是由于我们的数据集很小,我们不必在这里这样做。
现在,我们需要在编码模型之前标准化我们的数据。这一点很重要,因为有些营养素使用不同的单位。例如,维生素 A 使用 UI 单位,而碳水化合物使用克。
我们将使用 Scikit-learn 的RobustScaler
来标准化我们的数据,这样所有的数据都可以抵抗单位的差异。
好了,看起来我们已经准备好使用数据来建立模型了。
我假设大多数读者已经熟悉 Scikit-learn 的[LinearRegression](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html)
类。在很多在线教程中都是常用的。
但是,该类假定只提供了一个输出变量。
对于多个输出变量,我们需要添加一个类,这个类在大多数教程中通常不会提到,叫做MultiOutputRegressor
。
简单来说,就是 Scikit-learn 扩展 regressor 的一种方式,它本身不支持多输出回归。
我们将从简单地导入类开始。
接下来,我们可以开始拟合模型。
通常,在大多数关于线性回归的教程中,你很可能会看到这样的内容。
我们需要稍微修改一下,以包含MultiOutputRegressor
类。
目前看起来不错。接下来,我们需要检查我们的模型在训练期间是否表现良好。Scikit-learn 的score
属性应该可以做到这一点。
我们的模型显示了大约 72%的准确性。这是怎么回事?好吧,看起来仅仅用线性回归,我们就能得到比抛硬币更好的性能。
但是让我们继续每一个机器学习实践中非常重要的一步,在测试集上验证我们的训练性能。
我们这样做是为了避免在训练中过度适应。简而言之,当模型试图预测噪音过大的数据趋势时,就会发生过度拟合。
The black line is when the model was able to generalize well on the data. On the other hand, the blue line displays the line when the model has overfitted. (source: wikipedia.org)
因此,让我们检查模型在测试集上的表现。我们可以像训练集一样做一些小的改动。
看起来我们的模型能够在一定程度上避免过度拟合(训练和测试集精度之间的差异约为 7%)。
你现在可能会在脑海中嘀咕“那么我们如何避免过度适应和适应不足呢?”嗯,跟 偏差-方差权衡 有关系。
如果我们回到图中,我们的数据看起来杂乱无章。从视觉上看,这应该是高偏差的标志,这将导致拟合不足。然而,看起来我们的模型有更多的机会过度拟合。
虽然我们做了很好的工作来避免过度适应和适应不足,但这还不足以向我们在联合国儿童基金会的团队展示。
既然我们能够影响的人数很大(我指的是联合国儿童基金会),那么我们就应该提高我们模型的性能。
就像我之前说过的,数据集本身是高度非线性的,包含许多异常值。使用这样的数据集进行线性回归肯定不会产生最佳性能
作为一个有趣的练习,您可以尝试使用模型的预测值再次绘制数据。这将使我们对数据有更好的视觉理解(我们将在本系列的后面部分进行更多的可视化)。
因此,基本上,我们需要做的是使用一个不同的模型,可以处理非线性数据,并对异常值具有鲁棒性。
进入随机森林!
随机森林
如果我们试图找到一些最常用的机器学习模型来提高 Kaggle 的性能,它要么是随机森林,要么是梯度增强树。
然而,在这篇博文中,我们将讨论第一个问题。
但是在开始研究算法之前,我们需要先讨论一下决策树和自举。
决策树
想象一下,一边在公园散步,一边观察周围的环境。没有明显的原因,你决定看一棵树。它从根部开始,一路向上,直到最后一片叶子。
决策树也是一样,只是颠倒了。决策树算法也称为 CART、分类和回归树。
现在,我们将把注意力集中在回归树上,因为,当然,我们正在处理一个多元回归任务。
与线性回归不同,决策树算法不考虑数据中的线性假设。此外,它不需要任何重量。
相反,当使用决策树时,我们试图使用特征空间的满意度来进行预测。
根据《统计学习入门》一书的第 8 章,我们需要遵循两个步骤来构建决策树:
1.我们将预测空间(即 X1,X2,…,Xp 的可能值集)划分为 J 个不同且不重叠的区域,R1,R2,…,RJ。
2。对于落在区域 Rj 中的每个观察值,我们进行相同的预测,这只是 Rj 中训练观察值的响应值的平均值。
注意,作者使用 Xj 作为自变量的符号,而不是 xi。从现在开始,我们将做同样的事情。
现在,对于那些不熟悉决策树算法的人来说,可能会发现上面的陈述相当不清楚。
但简单地说,第一个陈述表明我们需要选择一个变量,并基于这些观察建立观察区域(数据点)。
而第二种说法是,在我们有了我们的区域之后,我们可以通过计算每个区域的观察值的平均值来进行预测。
有两种方法可以让我们通过视觉化直观地理解这个概念。
首先,我们可以绘制我们的数据点,并画一条线来分隔它的两个区域。让我们用纤维和碳水化合物来估计铁的价值。
这里我们看到一条线,将图分成两个区域。如果我们仔细观察,这条线在轴上代表碳水化合物的大约 41 个标记处开始分裂。
在回归方面,决策树算法通过平均每个区域的数据点来进行预测。
然后,算法将继续对变量进行分割,直到估计值与实际值相差不远。
我们可以形象化决策树的另一种方法是使用图表。
这里我们可以看到图表从顶部开始分裂。这些方框被称为节点,而指向/连接另一个节点的箭头被称为边。
如果你注意到了,第一个节点在 41.32 的值上做了一个分割,这和图中几乎一样。
与现实生活中的树不同,决策树通常通过向下的分支来可视化。
从顶层节点分支出来的两个节点被称为内部节点。上图中,每个内部节点内部都有字值。
这些值是算法通过对每个区域的观察值进行平均而得出的预测值。
然而,上面的图和图都只有一个深度。如果我们让树长到深度为 2,那么我们会得到这样的结果。
The plot and the graph with a depth of two.
在剧情上,我们可以看到现在另一条线对上一条线做了拆分。而该图具有更多的内部节点,这使得纤维分裂。
对于这个图,如果我们让树一直增长,直到它进行了最好的分裂,它将有更多的内部节点,最终可能不再是视觉上可理解的。
但问题是什么是最好的分割?好吧,最好的拆分是最小化预测值和真实值之间的误差的拆分。
如果我们仔细观察我们的图表,我们可以看到其中有单词 mse 。
这是指 均方误差 ,由以下公式给出
这类似于我们之前讨论过的 RSS,只是略有不同。
正如我们看到的,该公式具有 1/N 符号。这意味着在对所有平方误差求和后,我们用 N 个观察值对它们进行平均。
MSE 可能看起来像 RSS 加平均符号,但是在得出结论之前,这个讨论可能值得一查。
无论如何,理解决策树算法是使用随机森林算法的关键一步。
然而,这只是对决策树能力的简要说明,并推荐您查看《统计学习介绍》 第八章书。
该书对决策树给出了更好的高级数学解释。
在我们继续之前,我可能需要提到使用决策树时的一个更重要的方面。它被称为基尼指数。
简而言之,就是用来衡量某个变量在任意选择时被错误分类的概率。基尼指数基于熵的概念,熵是不确定性的程度。
这个概念通常在各种使用决策树相关算法进行分类任务的博客文章中很常见。
在分类任务中,我们想要测量信息增益,以便了解哪些特征给出了关于某个类别的最多信息。
然后,该信息用于解释每个变量的重要性,并利用它了解哪个变量对预测影响最大,或者最常被理解为变量重要性。
就回归而言,正如我们之前讨论的,我们使用 mse 找到最佳分割。
我们可能会在本系列的一篇特色博文中讨论更多的可变重要性。
接下来,我们将介绍随机森林的另一个重要方面,引导。
拔靴带
使用机器学习项目的挑战之一是收集数据可能非常昂贵和困难。
虽然互联网上有各种开放数据集(如我们正在使用的数据集),但一些模型需要更多数据来提高训练期间的性能。
但是在实践中,收集数据有时既昂贵又困难。我们可以使用一种叫做自举的重采样方法
简而言之,bootstrapping 包括用替换随机地从我们已经可用的数据集中重新采样数据。“With replacement”基本上意味着我们可以在新数据集中两次使用相同的观察值。
我们重复这个过程一段时间,直到我们得到所需数量的引导数据集。每个引导数据集包含相同数量的原始数据集的观测值。
让我们以数据集为例,使用碳水化合物变量的前五个观察值。
前五个观察值分别是 0.06、2.87、00.0、2.34 和 2.79。
让我们将引导数据集表示为子*。如果我们有 4 个数据集,那么每个数据集将分别命名为 *Z1、Z2、Z3、和 Z4 。
如果查看上面的图像,所有自举数据集的观测值都有重复值。这就是“用替换”的意思。
那么我们该如何处理这些自举数据集呢?当然,我们用它们来制作机器学习模型。
这听起来可能有点奇怪,因为我们已经有了用于训练的原始数据集。
但是,一旦我们进入这个主题令人兴奋的部分,编码随机森林,这一切就都有意义了!
编码随机森林
既然我们对决策树和自举有了一些直觉,我们可以继续讨论随机森林。
你看,这个算法被称为随机森林是有原因的。思考我们刚刚讨论的两个重要方面。
该算法使用 bootstrapping 使用原始数据集中的要素子集随机创建数据子集。然后使用决策树算法对每个子集建立模型。
然后,对每个模型的每个预测进行平均,以创建一个最终预测。
这对于多变量任务也是一样的。唯一的区别是每个决策树输出维生素 A、铁、锌、钙、维生素 D 和叶酸的值。
我们开始吧!与线性回归一样,我们需要导入RandomForestRegression
类和MultiOutputRegressor
类。
现在我们可以将数据放入模型中。
如我们所见,这里设置了一些参数。n_estimators
为 100,因为 Scikit-learn 的下一个版本将把这个值作为默认值。
max_features
仅仅是确保我们子集特征数量的平方根。这是我们需要为我们的模型调整的超参数之一。我们将在另一篇博文中讨论这个问题。
接下来,我们可以尝试检查我们的模型的准确性。
哇,看起来我们的模型在训练数据上表现得非常好。我是说,95%的准确率?听起来不错,对吧?
不完全是。我们仍然需要检查测试的准确性,因为我们想要的是模型在我们以前没有观察到的数据上表现良好。
看起来性能似乎相当不错。几乎比线性回归好 20%
与线性回归不同,我们的模型过度拟合,因为训练精度远大于测试精度(大约 15%的差异)。
我们可以用各种方法来改进这个模型。然而,让我们看看我们是否可以使用近年来获得高人气的算法来制作模型。
在本系列的下一部分,我们将构建一个神经网络算法来训练我们的数据。
当我们在数据集上使用神经网络时,您认为会发生什么?还会一样吗?好些了吗?或者更糟?
请在评论中告诉我你的想法。期待反馈和进一步的讨论。
第 3 部分见。干杯!
一名目前在韩国留学的印尼学生,对人工智能世界有着浓厚的兴趣。最近以 AI 研究实习生的身份跳槽到 IBM。相信不断的学习。我想回馈在我追求知识的过程中贡献良多的人工智能。当我不写代码时,我喜欢阅读航天工业的最新趋势,并为我大学的美式足球队效力。
用神经网络和随机森林预测微量营养素(三)
联合国儿童基金会希望你利用机器学习的力量,帮助他们预测食物中的重要营养成分。
Photo by Zoltan Tasi on Unsplash
问候!欢迎来到“使用神经网络和随机森林预测微量营养素”博客系列的第 3 部分。
在之前的博客文章中,我们通过对数据进行一些可视化技术,稍微看了一下我们的数据是什么样子的。
然后,我们尝试使用两种最常见的监督机器学习算法:线性回归和随机森林。然而,似乎我们没有得到我们想要的结果。
如果你是深度学习的新手,请注意,虽然内容包含对深度学习的介绍,但这不是一篇关于深度学习如何漂亮地工作的博客文章。
相反,这篇博客文章是为了表明,当试图建立机器学习模型或解决数据问题时,深度学习是而不是的银弹。
如果你想看看深度学习何时起作用的例子,我会在这篇博文的结尾附上一些文章。
到目前为止,我们只有几天时间来准备我们向联合国儿童基金会数据科学团队提出的模型。当然,鉴于该组织的声誉,我们不想让他们失望,对吗?
太好了,现在我们站在同一边了,让我们开始吧。
概述 :
这篇博文包含以下内容:
- 深度学习简介
- 深度神经网络是如何“学习”的?
- 使用 Keras 编码深度神经网络
- 反射部分
深度学习简介
关于深度学习的所有宣传,我假设大多数正在阅读这篇文章的人对它的总体情况有所了解。
简而言之,深度学习是主要利用堆叠感知机从数据中学习的各种机器学习方法之一。
这些堆叠的感知器被称为神经网络,其灵感来自人脑复杂的生物结构。一般来说,一个神经网络有三个主要层 : 输入、隐藏和输出。
隐藏层中的每个单元称为一个隐藏单元。
A general structure of a neural network has an input, hidden, and output layer.
现在你可能会想,“好吧,但我还是不明白这到底是怎么回事。”嗯,你完全正确。然而,在大多数实践中,更多的隐藏层和隐藏单元堆叠在架构中。
一些复杂的网络使用了数十万甚至数百万个隐藏层和单元。随着隐藏层和单元数量的增长,大多数专家将该网络称为深度神经网络。
A Deep Neural Network
另一个可能会突然出现在你脑海中的问题是“那么这个深度神经网络有什么特别之处?”深度学习的一个特殊之处就是它的“学习”部分。
我们已经讨论了“深”的部分,现在让我们谈谈第二部分。
深度神经网络是如何“学习”的?
各种有监督的机器学习算法的目标从根本上是相似的:最小化预测值和地面真实值之间的误差。
在深度学习流行之前,大多数机器学习过程都试图通过特征工程 的方式来做到这一点。
不要太深入细节,特征工程只是一种创建特征以使机器学习工作的方法。在这种情况下,特性意味着数据的变量。
然而,在深度学习算法中却不是这样。相反,一个 优化算法 被用来寻找最佳执行模型。其中最流行的一种叫做 渐变下降 。
基本上,梯度下降的主要目标是找到一个损失函数的局部最小值。
它能够通过称为 反向传播 的过程,相对于隐藏层中的所有权重取误差的梯度来做到这一点。
然后,你要向梯度方向迈出负的一步。我们将尝试使用类比来更好地理解这一点。
我们不打算在这里讨论数学,但从视觉上看,它大概是这样的。
What a gradient descent process looks like in three dimensions.
或者,我们可以用一个人蒙着眼睛下山的类比。向山下一大步,或者在山的某个安全的地方迈出一小步,会更好吗?
如果有人还想再活一天,那么后者当然会好得多。基本上,我们想做的是采取一个小的渐进步骤,将我们带到山的底部。
这些小步骤就是“向梯度负移一步”的意思,但这一次,它来自“误差函数”山。
optimization using gradient descent be like…
注意梯度下降有它的变体。选择使用哪种深度学习算法是训练深度神经网络艺术的一部分。
具体来说,我们使用的是最常见的变体之一,称为 Adam optimizer。同样,我们不打算在这里讨论,但可以随意参考原始论文。
好了,现在是我们一直在等待的时刻,Keras 的编码部分!
使用 Keras 编码深度神经网络
Keras 是一个用 python 编写的开源神经网络库。它运行在各种现有的深度学习库之上,如 Tensorflow、MXNet 和微软认知工具包。
此外,我们将使用另一个名为权重和偏差的工具,用于跟踪可视化神经网络的训练进度。现在,我们将把注意力集中在跟踪训练精度上。
在我们开始编码之前,请注意我们已经准备好了数据集。在本博客系列的第一部分中,它已经被清理、扩展并分成了训练集和测试集。
数据准备好了,我们就可以开始编码神经网络了。我假设读者熟悉 Keras。如果没有,那么文档会非常有用。
让我们从 Keras 库中导入所有需要的东西。
这里,我们使用Sequential
来堆叠层。我们将使用四种类型的层对象:Activation
、Dense
、BatchNormalization
、Dropout
。
只是指出,Dense
就是我们之前讲过的全连通层。根据名称,Activation
、Dense
和BatchNormalization
层非常简单。
如果你不熟悉最后两个,那么我强烈建议你读一点,因为它们在实践中经常被使用。
如前所述,Adam
被选为优化器。此外,我们使用mean_squared_error
作为损失函数,因为它是我们用于随机森林和线性回归的函数。
好了,我们从 Keras 得到了我们需要的东西,但是我们还需要一些东西来跟踪我们的模型在训练时的表现。这样,我们可以看到一段时间后精度是否停止提高。
我们可以使用很多开源工具,但我更喜欢的是一个叫做权重&偏差 (wandb)的工具。它为 Keras、Tensorflow 和 Pytorch 提供支持。
要使用它,我们需要在官网注册,下载 Python 的 SDK,做一点点设置。
wandb.init()
初始化图表,将显示图表。config
允许我们设置参数(批量、学习率等。)将被发送到图表轴的 wandb 服务器;例如像纪元。
现在我们需要将参数设置为 config。请随意修改参数。
太好了!让我们从神经网络架构开始。首先,让我们建立一个 2 个隐藏层的神经网络。第一层有 128 个隐藏单元,第二层有 64 个。
我们将在每一层之后使用一个 ReLU 激活。然后我们再做批量归一化,后面会有一个掉线。最后一层有 6 个输出单元。
我们得到了我们的架构,现在我们只需要编译我们的优化器和损失函数。
现在,是训练的时间了!
正如我们在这里看到的,我们有一个callbacks
参数,它接受一个列表作为它的输入。我们可以有多个性能跟踪器,但是在这种情况下,我们将只在列表中使用WandbCallback
。
要查看模型的性能,我们可以直接查看 wandb 网站上的仪表板。
根据您的内存能力,可能需要一段时间来训练模型。然而,有了追踪器,如果我们的表现似乎一点也没有改善,我们可以随时停止。
让我们看看进展如何。
在整个训练过程中,我们的模型似乎只能达到大约 30%的准确率。具体来说,在第 20 个纪元前后,精确度停止提高。看起来我们必须稍微改变一下架构。
让我们试着在两层中使用较少的隐藏单元。注意,我们需要重新运行wandb.init()
和config = wandb.config
来开始一个新的图表。
如果没有,那么 wandb 会认为我们在继续之前的培训课程,而实际上我们正在开始一个新的课程。
也就是说,让我们建立架构。
而且准确率还在 30%左右。嗯,我想知道这是怎么回事?但是在前 40 个纪元的训练中似乎有剧烈的变化。
这里有很多假设,但是减少隐藏单元的数量可能不是一个好主意。那么,如果我们添加比第一种架构更多的隐藏单元,会发生什么呢?
让我们找出答案。
准确率还是~30%?(混乱开始了)。
到目前为止,我们所做的只是改变隐藏单元的数量。也许是时候用图层来增加一些东西的味道了。让我们就这么做吧!我们要做 5 层,而不是 2 层。
好吧,现在我很确定我们没有朝着正确的方向前进。
在这种情况下,人们很容易得出这样的结论,即深度学习在这种情况下可能不是一个可行的解决方案,并提出一个解决方案。
然而,后退一步,花时间去理解为什么这不是一个可行的解决方案,这总是一个好的做法。
理解为什么某个解决方案对某个问题不起作用是每一次失败的学习部分。这样,当被问及为什么有些东西不起作用时,我们将能够解释为什么
那么让我们继续下一部分,反射部分。
反射部分
首先,让我们多想想我们的数据。我们的数据集大约有 8000 个数据点。
在深度学习实践者的眼中,这是相当小数量的数据点。通常,深度神经网络需要数百万,甚至数千万个数据点。
此外,我们在数据集中使用许多变量,这些变量可能充当噪声,而不是实际信号。也许我们不需要全部都用上。
也许如果我们做更多的可视化,我们可以更好地理解我们的数据,并使用更好的方法而不是深度学习。这正是我们在这个博客系列的第四部分也是最后一部分要做的。
尽管有深度学习的大肆宣传,但我们现在明白,深度学习并不总是答案;至少在这种情况下不会。还有其他方法可以解决数据问题。
顺便说一下,正如承诺的那样,这里有一些深度学习工作得非常好的文章(当然有 Keras):
上面的文章是很好的例子,当有足够数量的数据时,它们将向你展示深度神经网络的真正力量。
如果你一直读到最后,非常感谢你。如果你有进一步的问题或者想要给我一些反馈,请在评论中告诉我,或者在我的 Linkedin 上给我发消息。
希望下一部能见到你。到那时,干杯!
关于我:
一名目前在韩国留学的印尼学生,对 AI 世界有着浓厚的兴趣。大部分时间是后端和机器学习开发者。相信不断的学习。我想回馈在我追求知识的过程中贡献良多的人工智能。
基于比赛情况预测 MLB 投球概率
Can we determine what this pitch will be before it is thrown?
对许多人来说,棒球是一项很棒的运动。这是第一个想到利用数据在各个层面做出决策的运动之一。经理使用数据做出游戏决策,总经理使用数据决定合同支出。
棒球也是最早将统计数据纳入电视转播内容的运动之一。实时投球速度,投球位置,得分概率和偷垒概率。这些只是观众在观看这项全国性娱乐节目时可以吸收的一些东西。随着最近人工智能的加入,更多的预测和实时内容可用。
Pitch location is just one of the many AI uses of real-time mediated content
作为一个游戏爱好者,我想深入到一个目前还不属于本内容的领域,但在未来将会是:根据游戏情况预测接下来会有什么样的投球。我对最初的结果感到非常兴奋。
第一,数据。Kaggle 提供了一个数据集,其中包含 2015-2018 赛季在https://www.kaggle.com/pschale/mlb-pitch-data-20152018的所有球场数据。数据来自几个方面。csv 文件包括投球,击球,比赛,弹射和球员姓名。为了达到我们的目标,只使用了击球和投球数据集。
以下是加载到笔记本中的包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import RobustScaler, LabelEncoder
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix, classification_report, precision_score
import xgboost as xgb
from keras.utils.np_utils import to_categorical
import random
from keras import models, layers, optimizers, regularizers
from keras.layers import Embedding, GRU, Dropout, GlobalMaxPool1D, Dense
from sklearn.model_selection import GridSearchCV
读入数据并将两个数据集合并在一起(在 ab_id 上)后,第一个障碍是要处理的数据量。从 2015 年到 2018 年,记录了超过 280 万次投球。出于计算费用和最相关数据的目的,数据集被缩减为仅反映 2018 赛季。
#isolating the data that only contains the 2018 season
data18 = data[data['year'] == '2018']
这仍然提供了超过 70 万次的观测。现在,有超过 40 列,其中许多包含俯仰速度,轨迹和位置信息。这些对我们预测下一次投球没有任何好处,因为在那个时候,投球已经投出了。我们关心的是所有可能有助于投球的信息,所以我们将只保留我们需要的信息:
- pitch_type —音高的类型。这是我们的目标
- b_score —击球手所在队的得分
- b_count —当前计数中的球
- s_count —当前计数中的打击数
- 出局数——出局数(投球前)
- 投球数——击球时的投球数
- on_1b —如果第一个上有跑步者,则为 True,如果为空,则为 False
- on_2b —如果二垒上有跑垒者,则为真;如果二垒上没有跑垒者,则为假
- on_3b —如果三垒上有跑垒员,则为真,如果为空,则为假
- 击球手 id —击球手的球员 id。由 MLB 提供,在 player_names.csv 中找到的球员姓名
- 第一局——第几局
- p_score —投手队的得分
- p _ throws——投手用哪只手投球。单个字符,R 或 L
- pitcher_id —投手的玩家 id。
- 站立——击球手击中哪一方。单个字符,R 或 L
- topTrue 如果是一局的开始,如果是结束,则为 False
#new dataframe with what is initially determined as situational + the target (pitch_type)pXs = pd.DataFrame(data18[['pitch_type', 'b_score', 's_count', 'outs', 'pitch_num', 'on_1b', 'on_2b', 'on_3b', 'batter_id', 'inning', 'p_score', 'p_throws','pitcher_id', 'stand', 'top', 'b_count']])
这些是我们将瞄准的推销类型:
- CH —变速
- CU —弧线球
- FC —刀具
- FF——四缝线快速球
- FS —拆分器
- 双缝线快速球
- KC —关节曲线
- KN——球
- SI —沉降片
- SL —滑块
数据集中还有其他类型的音高,但只占总观测值的不到 0.1%(投球、螺旋球或罕见的以弗所音高)。这些都从数据集中删除,布尔和二进制对象转换为整数和空删除(代表不到 1%的总数据)。
看一下数据本身,数据中的异常值代表了局数和得分。这是典型的加时赛,但不像高分比赛那样频繁。得分和局数确实与投球有关,所以删除它们可能会对结果产生负面影响,所以那些异常值被保留了下来。
Outliers for batters score, pitch number and on second base
outliers for inning and pitchers score
检查多重共线性,发现球场数与球数和击球数高度正相关。,因此将其从数据集中移除。
Multicollinearity of pitch_num
在这一点上,执行了几个测试模型和试验,但是在这一点上,超调 XGBoostClassifier 为我们的数据提供了最好的结果。
X_train, X_test, y_train, y_test = train_test_split(features2, target2, test_size=0.30)#create xgb instance with parameters
clf = xgb.XGBClassifier(learning_rate=0.1,max_depth=10,min_child_weight=15,n_estimators=250)#fit data
clf.fit(X_train, y_train)#make predictions
training_preds = clf.predict(X_train)
val_preds = clf.predict(X_test)#run classification report and confusion matrix
gbt_confusion_matrix = confusion_matrix(y_test, val_preds)
print(gbt_confusion_matrix)
gbt_classification_report = classification_report(y_test, val_preds)
print(gbt_classification_report)
Classification Report for hypertuned XGBoostClassifier
这是一个彻底的分类,因此在 11 种音高类型上获得 51%的总体准确率是很好的。然而,将这一点转化为实际的游戏,只在一半的时间里获得正确的音高对于现场消费来说并不是最佳的。在这一点上决定,也许预测每个投球的概率会更有益。幸运的是,XGBoost 的包中有一个概率选项,只需将目标切换到 multi:softprob。
le = LabelEncoder()
le.fit(target3)
target_num = le.transform(target3)# list(le.inverse_transform(target_num)) #If you wish to retrieve the original descriptive labels post productionX_train, X_test, y_train, y_test = train_test_split(features3, target_num, test_size=0.3, random_state=42)# use DMatrix for xgboost
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)
fit = xgb.XGBClassifier(objective = 'multi:softprob')
fit.fit(X_train,y_train)# set xgboost params
param = {
'max_depth': 10, # the maximum depth of each tree
'learning_rate': 0.1, # the training step for each iteration
'min_child_weight': 20,
'n_estimators': 300,
'objective': 'multi:softprob', # error evaluation for multiclass training
'num_class': 10} # the number of classes that exist in this datset
num_rounds=30#------------- numpy array ------------------#training and testing - numpy matrices
bst = xgb.train(param, dtrain,num_rounds)
preds = bst.predict(dtest)#extracting most confident predictions
best_preds = np.asarray([np.argmax(line) for line in preds])print ("Numpy array test precision:", precision_score(y_test, best_preds, average='macro'))
Probability predictions for each observation (example)
我们将 dataframe 转换为 numpy 数组进行计算,因此为了可视化结果,有必要将数据转换回 dataframe,并使用 matplotlib 重新标记列以创建一个视图。
#creating a dataframe for plotting purposes
plot = pd.DataFrame(data=preds[:,:], columns=['Changeup', 'Curveball', 'Cutter', 'Fastball_4S', 'Splitter', 'Fastball_2S', 'Knucklecurve', 'Knuckleball', 'Sinker', 'Slider'])#visualization function
def pitch_pred(data):
print(X_test.iloc[data])
ax = plot.iloc[data].plot(kind='barh',title ="Pitch Prediction", figsize=(15, 10), fontsize=20)
ax.set_xlabel("Percent Chance", fontsize=24)
ax.set_ylabel("Pitchtype", fontsize=24)
plt.show()#visualize observation 6754
pitch_pred(6754)
Parameters for observation 6754
Visual for observation 6754
正如你所看到的,在彻底分类的基础上,展示下一个音高的可能性更有意义。未来的工作包括部署模型后的实时测试。也可能找到一些有用的附加数据,如体育场和天气。由于数据量巨大,笔记本可以在 Google Colab 和 Github 上找到,但我无法将数据文件保存在云中。数据集可以从 Kaggle 下载。
棒球 _ 投球 _ 预测
colab.research.google.com](https://colab.research.google.com/drive/1VaHWXq2yYuH-S-6WL_WD8VFSugcgoiUz#scrollTo=eNI5nrnYrxPV) [## 杰森·M·理查兹/棒球投球预测
作为职业棒球的狂热观众,越来越明显的是,统计数据不仅有助于经理们…
github.com](https://github.com/Jason-M-Richards/Baseball-Pitch-Prediction)
使用 AdaBoost、XGBoost 和 LightGBM 预测电影收入
决定电影成功的因素是什么?
漫威的复仇者联盟 4:终局之战最近取代阿凡达 成为历史上票房最高的电影,尽管这部电影无疑会非常成功,但我想知道是什么让任何一部电影成功。
我要回答的问题是:
- 哪些变量特别能预测绝对收入数字?
- 将问题限制在二进制“失败”或“成功”的情况下,收入预测有多准确?
我正在使用通过 kaggle 提供的电影数据库中的数据。数据集被分成训练集和测试集,训练集包含 3,000 部电影,测试集包含 4,398 部电影。在训练集和测试集中有 22 个特性,包括预算、流派、所属集合、运行时间、关键字和更多*。训练数据集还包含目标变量收入*。
List of variables in the train data set
探索性数据分析
难点:
- 在进行任何探索性的数据分析之前,我必须将文本格式的看起来像 JSON 的数据转换成实际的数据类型,这实际上是字典列表。完成这个任务的一个非常有用的函数是
ast
包中的literal_eval()
。 - 这个数据集中有很多分类特征,包括制作国家、制作公司、演员和剧组。要包括他们所有的回报是不可能的,所以我决定对每种类型的特性的前 30 个回报进行任意限制。
- 数据集中的流行度变量基于不同的指标,如每天的用户投票和浏览量。因为一旦一部电影上映,这一功能就会变得更加强大,所以这个变量可能不应该包含在一个旨在对正在上映的电影进行稳健的未来预测的模型中。
- 有很多缺失的值,特别是在预算变量中,还有剧组和剧组的性别子变量中。因为预算似乎是一个非常重要的指标,基于最初对收入数字的绘制,我决定删除任何预算为 0 的电影。由于数据不一致,我决定不在我的模型中包含性别比例。
见解:
**前传和续集:**也许不出所料,相关电影的前传或续集的平均收入高于独立电影。
Boxplots for movies that are part of collections (1) and those that are not (0)
**预算:**图表清楚地表明收入与预算正相关。人们实际上希望大笔投资会产生更大的回报。
Budget variable plotted against revenue
train 数据集中的前六名演员似乎都是赚钱的人,其中一些人——比如塞缪尔·L·杰克逊——比其他人多。
Boxplots comparing revenue of movies including certain actors (1) and excluding certain actors (0)
**上映日期:**随着时间的推移,电影的数量和收入都在增加,然而,20 世纪 70 年代有一些电影产生了大量的收入,导致收入数字飙升。2017/2018 年也发生过类似事件。
Number of movies and revenue over time
数据预处理
我将演职人员、剧组、制作公司、制作国家和关键词变量的前 30 个回报作为虚拟变量添加到数据集。我还创建了新的功能来计算每个样本的不同退货数量(生产公司、生产国家、口语)以及字母数量(标题、标语)。因为预算因通货膨胀而增加加班,所以我添加了一个可变的预算 _ 到 _ 年比率。
为了让数据进入统一的区间,我将对数函数应用于预算、人气和收入变量,并借助 0 到 1 之间的MinMaxScaler()
对所有数据进行缩放。我将发布日期转换成 4 个不同的变量:发布年份、发布月份、发布周和发布工作日。我没有对概述、标题或标语变量使用任何自然语言处理,并且忽略了单词内容。
在数据清理和工程之后,我的训练集中有 201 个特征。我把训练集拆分成 X_train,y_train,X_cross,y_cross。我的测试数据集不包含任何收入特征,我的预测仅包含在我的 Jupyter 笔记本中。
建模和评估
为了预测绝对收入数字,我决定使用三种不同的集成算法。我对它们每个都应用了参数调整技术。
AdaBoost
AdaBoost (自适应增强)是一种元估计器,它首先将一个回归变量拟合到数据中,然后添加额外的回归变量,旨在改善与回归变量偏差较大的情况。所有回归变量的结果是平均的,并导致最终的模型。
该算法的最重要的参数是 n_estimators (应该高些以获得更好的精度)和 learning_rate (应该小些以获得更好的精度)。我使用GridSearchCV
来确定最优参数,对于 n_estimators 为 100,000,对于 learning_rate 为 0.001。
XGBoost
XGBoost (极限梯度提升)是一种基于梯度下降的提升算法,比 AdaBoost 算法更高效。它使用提升树和并行提升,使其快速准确。提升树的底层算法类似于 RandomForests。
我查看了许多不同的参数,并调整了以下内容:
Parameters tuned for the XGBoost model
LightGBM
我使用的最后一个模型是 LightGBM ,这也是一个基于树的梯度推进算法。它提高了 XGBoost 的速度,可以很快得到高精度的结果。关于 LightGBM 和 XGBoost 之间的差异的更多细节可以在这里找到。
我向我的模型添加了以下调整后的参数:
Parameters tuned for the LightGBM model
均方根误差
我检查了训练和交叉验证数据集的预测,并决定将重点放在 XGBoost 模型上进行进一步的分析。它确实过拟合,但是,它仍然具有最佳比例对数均方根误差。
Scaled logarithmic root mean squared error for training set on the left and cross-validation set on the right
1。哪些特征特别能预测电影收入?
使用lightgbm
包中非常有用的方法plot_importance
,预测收入时最重要的特性是流行度、预算、预算 _ 年 _ 比率、发行 _ 年、运行时间、标题 _ 长度、标语 _ 长度和*发行 _ 周。*这些特性类似于 AdaBoost 模型和 LightGBM 模型的最重要特性。
Feature importance based on the XGBoost model
2.这个模型能多好地预测失败和成功的电影?
上述衡量尺度和对数均方根误差的指标可能难以理解和判断,因此我在我的数据集中添加了一个利润目标标签,其定义如下,先前由本研究论文介绍:
利润= (1/2) *收入-预算
计算 X_train 和 X_cross 数据集的实际利润和预测利润,得出训练数据的准确率为 78.9%,交叉验证数据的准确率为 68%。
43.2%的失败电影被错误地预测为成功电影,而 21.3%的成功电影被错误地预测为失败电影。这表明该模型有预测高于实际值的趋势。
结论
- 哪些特征特别能预测电影收入? 人气、预算、预算年比率、发行年、运行时间、标题长度、标语长度和发行周
- 这个模型能多好地预测失败和成功的电影?将绝对值转换为二进制分类系统(翻牌或成功)只会导致交叉验证集中的准确率为 68% 。
限制
- **相对较小的训练集规模。**更大的训练集可以产生更精确的模型。
- **特征选择。**添加其他变量,包括用户评级、评论家评分、社交媒体内容,甚至来自网飞等推荐系统的数据,在试图提高准确性时,可能会被证明是有价值的。
- **线性回归。**根据这篇的研究论文,在应用的三个不同模型中,使用线性回归作为基本回归变量在预测低票房电影时表现良好,但在预测高票房电影时表现较差。
- **将回归转换为分类输出。**我只是简单地将我的回归输出转换成一个二进制类案例,并计算准确性。但是,我的模型只针对绝对收入数字进行了优化,而不是这两个类别。如果我们对失败与成功预测感兴趣,那么使用分类器和深度学习算法来获得高准确性会更好。
这个项目是我的 Udacity 的数据科学家纳米学位项目的顶点项目。在我的 Jupyter 笔记本上,还有很多关于电影数据集的有趣见解。详细代码请看我的 GitHub 。
你想在媒体上阅读更多高质量的故事吗?考虑注册一个支持我和其他媒体作者的会员。
[## 通过我的推荐链接加入 Medium-Julia Nikulski
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@julia.nikulski/membership)
想知道 AdaBoost 和 XGBoost 算法实际上是如何工作的吗?查看我关于 bagging、boosting、AdaBoost、random forests 和 XGBoost 的深入指南。
[## AdaBoost、随机森林和 XGBoost 的终极指南
它们是如何工作的,有何不同,何时应该使用?
towardsdatascience.com](/the-ultimate-guide-to-adaboost-random-forests-and-xgboost-7f9327061c4f)
使用我的 Spotify 数据预测我的情绪
上个月那是一个命运攸关的夜晚,我赶上了我最好的朋友。像往常一样,我们分享了我们最喜欢的新歌,并讨论了当前嘻哈游戏的氛围。有趣的是,我们的谈话最终引导我们讨论音乐流媒体服务(如 Apple Music 和 Spotify)可能有多少关于我们音乐行为和情绪状态的数据。
这段对话引发了我脑海中的一个问题:
给定听众的音乐数据,我们能推断出他们的情绪吗?
在本文中,我将概述我使用聚类和监督学习方法来回答这个问题的方法。
获取我的 Spotify 数据
第一步是通过 Spotify 的便捷 API 建立我的 Spotify 歌曲数据集!
我使用 Spotipy 库编写了一个 Python 脚本来连接到 Spotify API,并获取我曾经创建的每个播放列表以及其中的歌曲的列表。
对于每首给定的歌曲,Spotify API 都会提供其音频功能。
这些特征从一首歌的节奏到它的可跳舞性(是的,你没听错),衡量一首歌可跳舞的程度!
在这个项目中,我使用了 5 个音频特征来预测情绪:
- acoustic ness:0.0 到 1.0 的音轨是否声学的置信度度量。1.0 表示音轨是声学的高置信度。
- 可跳舞性:根据音乐元素的组合,包括速度、节奏稳定性、节拍强度和整体规律性,衡量一首曲目是否适合跳舞。值 0.0 最不适合跳舞,1.0 最适合跳舞。
- 活跃度:检测录像中是否有观众。较高的活跃度值表示音轨被现场执行的概率增加。高于 0.8 的值表示该轨迹很有可能是实时的。
- 响度:音轨的整体响度,单位为分贝(dB)。响度值是整个轨道的平均值,可用于比较轨道的相对响度。响度是声音的质量,是与体力(振幅)相关的主要心理因素。值的典型范围在-60 和 0 db 之间。
- 语速:检测音轨中是否存在口语单词。高于 0.66 的值描述可能完全由口语单词组成的轨道。介于 0.33 和 0.66 之间的值描述可能包含音乐和语音的轨道,可以是分段的,也可以是分层的,包括说唱音乐。低于 0.33 的值很可能代表工具性的。
(显示的定义来自 Spotify API 文档。)
然后,我将每首歌曲的特征导出到 csv,总共包含 822 首歌曲。
first 5 songs in the data set
使音量正常化
在将数据输入任何最大似然算法之前,我必须确保特征被正确地缩放。典型地,当数值属性在非常不同的尺度上操作时,ML 算法表现不佳,因为它向它们的目标函数引入了偏差。
幸运的是,API 提供的大多数特性都在 1 到 0 之间。除了值在-60 和 0 db 之间的响度特性。
因此,我使用 sklearn MinMaxScaler 将响度特性标准化,使其值介于 0 和 1 之间。
from sklearn import preprocessingloudness = songs[['loudness']].values
min_max_scaler = preprocessing.MinMaxScaler()
loudness_scaled = min_max_scaler.fit_transform(loudness)
将歌曲分成不同的情绪
有了现在准备好的数据,下一步就是将我的歌曲分组,并确定每个分组所代表的情绪。
我决定使用 K-Means 聚类算法,它在发现数据中的潜在分布方面非常出色。它是一种无监督学习算法,只有一个目标:
将相似的数据点分成 k 组,并发现潜在的模式。为了实现这个目标,它寻找预定数量( k )的聚类。
那么,我们如何决定 k 的最优个数呢?
有许多方法可以做到这一点,其中最流行的方法是肘法。这包括对范围 k(例如1–15)运行 K 均值,并绘制到聚类中心的平均平方和距离与聚类数量的关系图以找到视觉“肘”,这是聚类的最佳数量。
from sklearn.cluster import KMeansSum_of_squared_distances = []
K = range(1,15)
for k in K:
km = KMeans(n_clusters=k)
km = km.fit(songs_features)
Sum_of_squared_distances.append(km.inertia_)
现在,如果我们针对 k. 的范围绘制我们的距离,我们会得到以下图表:
正如你所看到的,当 k = 4 时,到聚类中心的平均平方距离开始显著下降。这就是期待已久的肘子,我们的优 k 。
使用主成分分析和 t-SNE 可视化聚类
确定了聚类的数量后,下一步就是探索由 K-均值构成的聚类,并识别它们可能代表的情绪!
由于数据集包含 5 个特征,我们正在处理**高维数据,**这意味着这很难想象(更不用说绘图了 lol)。
幸运的是,我们可以使用降维技术来降低数据的维度,使其更容易可视化,同时保留数据中的大部分信息(如方差)。
我使用了两种降维算法,主成分分析( PCA )和 t 分布随机邻居嵌入( t-SNE )来可视化下面看到的聚类。
2D Visualisation of song clusters using PCA
2D Visualisation of song clusters using t-SNE
从图中,我们可以看到集群形成良好,具有清晰的边界和最小的重叠。最大的重叠在簇 1 和簇 2 之间。
聚类 0 是最小的聚类,并且其歌曲离聚类 1 & 2 最远,这表明 0 中的歌曲与聚类 1 & 2 非常不同。
有趣的是,在 t-SNE 表示中,与更密集的 PCA 簇相比,簇的形状更加扩展和广泛分布。在 t-SNE 图像中,我们可以看到来自与簇 2 重叠的簇 0 的几个极值点,另一方面,在 PCA 表示中没有重叠。
下图显示了每个聚类中的歌曲数量。聚类 1 是最大的聚类,包含数据集中超过一半的歌曲!这可能表示我的播放列表中的一种主要情绪。其余分类的大小较小,分类 0 包含的数据集不到 10%!
Number of songs in each cluster
识别情绪
然后,我通过查看每个集群中的歌曲,并确定我与特定集群中大多数歌曲相关联的关键情绪,为每个集群分配一种情绪。
所以让我们来看看其中的一些歌曲吧!
群集 0
4 个集群中最小的一个。我非常感兴趣地看到了聚集在这里的少数歌曲。
- 弗洛里汽车收音机(L o-fi 嘻哈
- 米勒·戴维斯-那又怎么样(爵士)
- 植松信夫-最终幻想 X(钢琴协奏曲):三。凯森(管弦乐,钢琴)
- Destati - Kairi 项目(管弦乐)
- 植松信夫-最终幻想 X(钢琴协奏曲):I .扎纳尔坎德(管弦乐,钢琴)
这 5 首歌我注意到的第一件事就是都是器乐曲目!例如,Flovry 的汽车收音机是一种高保真嘻哈乐器,我通常在放松时听。后 3 首是我学习时听的游戏原声(最终幻想&王国之心)。
Car Radio by Flovry
在进一步检查集群后,我开始看到更多的高保真和爵士乐乐器(包括更多的米勒·戴维斯,戴夫·布鲁贝克和艾拉·费兹杰拉)。
所有这些歌曲都有一个共同点。相对高的 声音度接近 1,表示使用真实乐器。因为大多数乐器的音轨都是声学的,所以它们共享这个属性是有意义的。下图显示了分类 0 的平均分类值。正如所料,声音值最高,语音值最低,表明在这些聚类的歌曲中很少或没有语音。
Average Features in Cluster 0
这一簇绝对代表了我“下雨时的舒适热巧克力”的心情。
因此,我将第 0 组标记为寒冷情绪。
群组 1
- 古驰马内-梅特加拉(壮举。偏移)(陷印)
- 肯德里克·拉马尔——大人物(与特拉维斯·斯科特)
- damso-θ。马卡雷纳(法国陷阱)
- 逻辑不锈钢(嘻哈)
- 一个 A P 洛基 − 一个 AP 洛基-一个 AP洛基−一个AP 永远(嘻哈)
Big Shot by Kendrick Lamar
从第一组的前五首歌来看,它们都是一贯响亮而乐观的嘻哈音乐。这些是我可能会在健身房或者和朋友一起听的歌曲!
从下面的平均群集特征中,我们可以看到该群集比之前的 chill 群集具有更高的可跳舞性和响度。此外,声音低得多,表明在这些集群歌曲中使用了更多的电子和合成声音。
Average Features in Cluster 1
这组歌曲向我传达了一个明确的信息,那就是能量!
因此,我将第一组标记为充满活力的情绪。
群组 2
- 萨巴-光合作用(嘻哈)
- 杰米 xx -我知道会有(美好时光)(舞蹈,电子)
- 坎耶·韦斯特-触摸天空(嘻哈)
- Epik High - 막을 올리며安可(k嘻哈
- Téo?- Orso (off top) ( 新美国嘻哈)
Photosynthesis by Saba
这绝对是最多样化的 4 个集群,包含了各种不同类型的音乐,从电子音乐到令人惊讶的年轻暴徒…
我发现第二组和第一组非常相似,因为有大量的嘻哈音乐,这解释了在可视化中看到的重叠。然而,我发现这个集群中的歌曲有更多的口语词(例如 A$AP Rocky 的 1Train 和创作者 Tyler 的 11 月)。
集群 2 的平均特征支持这一点,因为我们可以看到语音和活跃度(指示现场表演)高于集群 1。
Average Features in cluster 2
集群 2 中的歌曲让我想起我感到欢欣鼓舞和快乐的时候。
因此,我将第二组标记为愉快的心情。
第 3 组
- 玛丽娅-我希望我错过了我的前任( RnB,灵魂)
- 爱莉安娜·格兰德-陈哥( RnB )
- Joji -忘不了你(专长。蛤蜊赌场)( RnB 电子)
- gianni & kyle -你有没有想过我?( RnB,嘻哈)
- RAYE -自信( RnB,舞蹈)
I Wish I Missed My Ex by Mahalia
当我看到这个集群的时候,它已经在我的情绪中尖叫了。在这个集群中有明显的 RnB 歌曲趋势,我喜欢的很多歌手都聚集在这里(Syd,Jorja Smith 和 Daniel Caesar)。有趣的是,平均而言,这一组是最适合跳舞的,可能是因为 Rnb 和舞曲的自然反弹。
由于这个集群的“浪漫”本质,我决定将集群 3 标记为我的浪漫心情!
预测我的情绪标签
每首歌现在都被贴上了各自心情的标签。我想看看我们是否可以训练一个监督学习模型,然后准确地预测给定歌曲时我的情绪。
我将数据集分成训练集和测试集(70:30),并在训练集上训练 4 个不同的分类器模型。
- 随机森林
- KNN
- SVM
- MLP 分类器
每首歌曲的情绪标签被用作目标数据,我们的目标是正确预测(寒冷,充满活力,欢快,浪漫)。
混淆矩阵和 F1 分数
为了评估分类器的性能,我比较了它们的混淆矩阵。
混淆矩阵是查看哪个分类器误差最小的好方法,在理想世界中,一个完美的分类器只在对角线轴上有值(100%准确)。
我们可以在下面看到,大多数分类器都非常擅长识别充满活力的情绪歌曲。SVM 显示出最高的错误,例如,它把 11 首寒冷的歌曲归类为浪漫的歌曲。另一方面,随机森林显示出最少的错误,具有最少的假阳性。它能够预测所有充满活力的歌曲,除了 1!
然后,我计算 F1 分数,定量比较每个分类器的准确性。它是一个分类器的精度和召回的调和平均值(这里解释得很好)。只有当分类器的精度和召回率都很高时,F1 分数才能很高。
F1 Scores for each classifier
不出所料,兰登森林得分最高,KNN 和 MLP 紧随其后,得分相同。或许,SVM 的性能可以通过调整内核等超级参数来提高。
厉害!我们现在有了一个强大的模型选择,开始根据看不见的歌曲预测听众的情绪。
特征重要性
当使用随机森林分类器时,我们可以输出每个特征相对于它们在构建森林时提供的信息量的重要性(减少熵)。
Feature Importance from Random Forest
声音是最重要的。这可能是因为数据集中原声/非原声歌曲之间的明显区别,以及大多数 Chill 集群是如何由高度原声的乐器音轨组成的!
另一方面,语言能力和舞蹈能力似乎是数据中最没有帮助的特征。这可能是因为我听的大多数歌曲都含有大量的话语,因为我喜欢说唱和嘻哈音乐。这也表明了我听的大多数歌曲都是适合跳舞的(所以至少我可以说我的音乐在大多数时候并不无聊👊).
结论
总之,这个项目是探索我的 Spotify 播放列表数据并了解更多关于我的音乐品味和行为的有趣方式。
和音乐评价一样,一首歌能创造出什么样的情感和感受,这是一个人的主观性问题。尽管如此,我认为在了解每个独特的听众的口味之后,我们可以慢慢地但肯定地开始在更大的范围内理解这些感受。
作为这个项目的后续,我们有可能预测听众的情绪。如果能建立一个推荐引擎,向听众推荐类似情绪的歌曲,那就太棒了!
感谢你阅读这篇文章,我希望你已经学到了一些新的东西(并且发现了一些新的音乐)。如果你想聊天或者有任何反馈,请在下面评论!
我在这里写的代码。
和平 Out✌️
预测 NBA Instagram 与机器学习的互动
今年早些时候,我有幸参加了在新泽西 Secaucus 联盟办公室举行的 2019 NBA 黑客马拉松。作为申请过程的一部分,NBA 提出了两个技术筛选问题——一个涉及计算 2019 年季后赛每场比赛的高级球员指标,另一个侧重于预测 1000 个 Instagram 帖子被 NBA 雇佣的数量。
第二个筛选问题非常适合机器学习,我真的很享受在这个问题上全力以赴的时光。在这篇文章中,我将概述我的总体方法和最终解决方案。
问题陈述
手头的任务相当简单:我们有超过 7500 个 NBA Instagram 帖子的相关数据,根据这些数据,我们被要求预测 1000 个帖子的参与人数。
这两个数据集包括以下字段:
- 发帖时的关注者(发帖时 Instagram 关注者的数量)
- 创建日期(帖子的日期戳)
- 文章类型(文章分类为照片、相册或视频)
- 描述 (Instagram 帖子标题/描述)
- 参与度 (Instagram 参与度——我们将对我们的抵制活动进行预测)
解决方案根据预测约定的平均绝对百分比误差进行分级,这可以通过找到 1000 个预测中每个预测的百分比误差的平均值来计算。
由于目标变量(参与度)是由 NBA 人为生成的,任何解决问题的方法都是公平的!让我们深入了解我是如何用机器学习来应对这一挑战的。
第一步:探索性数据分析
就像几乎所有的机器学习问题一样,我的第一步是通过探索性数据分析(EDA)在笔记本上熟悉数据。我们可以将训练数据集导入到熊猫数据框架中,并从查看数据开始。
接下来,我喜欢创建简单的可视化来更好地理解什么可能影响我们的目标变量。首先,我们可以从我们的数据集中绘制出参与次数与两个连续变量的关系:发帖时间和发帖时的关注者。
Engagement vs Post Date-Time
Engagement vs Followers at time of post
从这些想象中,我很快注意到两个观察结果。首先,NBA 休赛期(7 月至 10 月)的参与度似乎有所下降。此外,除了一些异常值,似乎有两个不同的“波段”的业务。
帖子参与之间的这种明显区别表明,我们可能正在查看两种不同类型的 Instagram 帖子,仔细看看我们的数据集,我们有一个分类变量在其他连续变量中脱颖而出: Type 。摘下我们的分析帽子,这具有定性意义——insta gram 照片可能会表现出与自动播放视频明显不同的参与度表现。通过根据帖子类型将我们的帖子映射到特定的颜色,我们可以更清楚地了解正在发生的事情。
Videos appear to be in a league of their own
看起来,当谈到一个给定帖子的参与次数时,我们实际上有两种类型:视频和照片/相册。为了更深入地了解这一点,我们可以通过叠加多个直方图来检查这些职位类型的聘用分布。
基于上述分析,很明显,为了有效地解决这个问题,我们可能需要建立多个机器学习模型。虽然有可能创建一个处理所有帖子类型的单一模型(使用“虚拟”分类变量),但这个模型很可能只会适度地推广。在我们开始构建我们的机器学习模型之前,我们先来看看这个问题中可能是我最喜欢的部分:特征工程。
步骤 2:特征工程
虽然我们的数据集只包括 4 个“开箱即用”的输入字段,但我们可以通过直觉和创造力创建更多的功能。两个字段包含丰富的基础数据,可用于生成额外的有价值的特征:创建日期和描述。让我们看看如何从这些领域中梳理出有用的特性。
创建日期- 直觉告诉我们,休赛期的帖子可能比 NBA 赛季中期的帖子表现更差,同样,美国东部时间凌晨 1 点的帖子可能比美国东部时间晚上 7 点的帖子表现更差。从这个假设出发,我们有必要从我们独有的时间戳中提取一些常见的与日期相关的特征,比如:月、工作日和小时。
我们可以使用 Pandasdt系列访问器对象在我们的训练集数据框架中创建这些新特征,如下所示:
posts_df['month'] = posts_df.created_ts.dt.month
posts_df['weekday'] = posts_df.created_ts.dt.weekday
posts_df['hour'] = posts_df.created_ts.dt.hour
使用一些箱线图,我们可以更好地了解这些新功能是否指示帖子的参与度。
Engagements vs Instagram post Month
Engagements vs Instagram post Weekday
Engagements vs Instagram post Hour
描述- 我们的 Instagram 帖子描述了无尽的可能特征的来源。首先,我们可以检查一些可能影响帖子性能的连续和分类特征。以下是我能确定的一些最有影响力的特征:
- 长度 —我们可以很容易地计算出每个职位的描述长度,并检查与聘用的对应关系。对于所有类型的职位,描述长度和聘用之间存在负相关关系。下面是视频的散点图。
For Videos, there seems to be a negative correlation between Description Length and Engagements
- 表情符号— 虽然看起来很傻,但我很好奇表情符号是否会影响帖子的参与度。在我们的数据集中,表情符号显示为*’??'* string,所以我们可以在我们的描述中搜索这个子串,并创建一个数据透视表来理解结果。
🚀 Emojis! Continuous performance.
我们可以构建一个数据透视表,显示每个月的参与人数中位数,根据职位描述是否包含表情符号进行分组。值得注意的是,月复一月,描述中有表情符号的帖子表现优于没有表情符号的帖子。
- 标记账户——虽然我们无法分析图片本身,但我们可以通过对 NBA 球员的潜在标记,围绕 Instagram 帖子做出有根据的猜测(例如:“@ Stephen curry at the buzzer!”)。解决这个问题有点棘手,如果我们看看表现最好和最差的帖子,并确定是否有任何标记帐户与参与度高度相关,这可能是最容易的。
Top 20 performing posts — looks like the audience has some favorite players
看看排名前 20 的表演帖子,我们看到两名球员脱颖而出:勒布朗詹姆斯(@金詹姆斯)和凯里·欧文(@凯里欧文)。事实上,77 篇热门帖子中的每一篇都提到了这两个球员中的一个或两个。陪审团已经明确表态,他们有一些喜欢的球员。我们将确保为勒布朗和垂怜经创建分类变量(例如: contains_kingjames ),以表示给定的帖子描述是否包括对相关球员的提及。虽然这种方法可能不适用于预测未来 10 年的职位表现(外推),但由于我们正在解决一个插值问题(属于我们训练数据集的职位),这似乎完全有效。
Bottom 20 performing posts (worst at the top)
同样,我们可以在表现最差的职位中发现一些趋势。提到替代联赛或比赛的帖子(例如: *NBA 非洲赛,WNBA,Jr NBA 等。)*似乎都表现不佳。此外,包含大量标记球员的描述似乎也会出现在我们列表的底部。我们可以通过创建一个分类变量(contains _ alternate _ league),以及一个连续变量( player_mentions )并检查结果来测试这些假设。
Be warned if you post about an alternate league and mention a slew of players!
第三步:建模
创建了自定义功能后,我们可以开始测试不同的回归算法来预测雇佣关系。在高层次上,当选择算法时,我们将把数据分成两个子集:训练数据和测试数据,使我们的模型适合训练数据,并对我们的测试数据进行预测。然后,我们将计算我们的预测和测试数据集中的实际值之间的误差,并比较我们的各种模型。
虽然让我们的模型适应所提供的整个训练数据集(7500 个 Instagram 帖子的参与度值)很有吸引力,但我们会发现自己无法评估我们的模型对数据的预测有多好没有看到。我们将被迫对用于拟合模型的训练数据进行预测,这很可能导致过度拟合。相反,我们将留出一部分训练数据集,并将其视为测试数据集。
如前所述,我们需要创建一个模型来对视频进行预测,并创建另一个模型来对照片和相册进行预测。因此,我们首先将训练数据分成两个较小的数据集:视频数据和照片/相册数据。然后,我们可以使用 SciKitLearn 的 train_test_split 将每个数据集进一步分割成训练集和测试集。以下是用于预测视频参与度的各种初始模型的计算平均绝对百分比误差(我们提供的误差函数):
根据我们的初始模型,我们的线性回归模型对以前没有见过的数据做出预测,平均误差约为 3%。平均雇佣值约为 692,000 次雇佣,我们做出的预测平均错误 21,036 次雇佣(不错!)
在我们继续微调我们的线性回归模型之前,重要的是停下来考虑这样一个事实,即我们的视频数据集的分割有可能导致非常有利的训练数据。换句话说,我们只是运气好吗?我们是不是碰巧通过让他们在 Instagram 帖子上做出预测来测试我们的模型,与 K 近邻模型相比,线性回归模型更容易做出预测?有可能!为了更加确信我们选择了正确的算法,我们将利用交叉验证。
交叉验证是一种技术,通过这种技术,我们可以评估模型归纳为独立数据集的能力,并更有把握地排除好运。最常见的交叉验证形式之一是 **K-Folds 交叉验证,**其中数据集被分成 K 个部分(或“折叠”),从一个折叠创建测试集,从其余折叠创建训练集。重复这个过程,直到每个折叠都被用作测试数据集,并且我们已经为每个独特的训练和测试计算了模型的误差。
source: K-folds cross-validation, Kaggle
在执行一轮 K 倍交叉验证(K 值为 5)后,我们可以通过对每次训练和测试的平均绝对百分比误差进行平均来再次比较我们的不同模型。毫不奇怪,我们的线性回归模型仍然表现最好(平均绝对百分误差为 3.0%)。
这个过程可以在我们的照片/相册中重复,在我的例子中,线性回归再次表现得最好。
随着我们最终模型的选定,我们可以通过对我们训练数据的整体训练新的线性回归模型来结束这个项目。值得注意的是,SciKit-Learn 的标准线性回归模型实际上是一个普通的最小二乘(OLS)回归。该模型优化了我们的特征系数,以最小化观察到的和预测的参与度值之间的差的平方和。在我们的具体应用中,我们的任务是针对平均绝对百分比误差(MAPE,一种不同的损失函数)进行优化。从高层次来看,OLS 是规模依赖型的,而 MAPE 是而不是。由于我们没有任何明显的异常值会扭曲我们的模型,我决定用 SciKit-Learn 的“普通”线性回归模型来训练我的线性回归模型。我在这个项目上的工作的一个改进将是创建一个定制的求解器来根据定制的损失函数优化特征系数——这是另一个有趣的项目!
结论
由于这个挑战是基于人工 Instagram 参与数据,不幸的是,我可能永远不会知道我最终预测的准确性。然而,我所知道的是,我的提交奖励了我一次去 NBA 总部的旅行,与体育分析世界中一些最聪明的头脑一起参加进一步的数据科学挑战。
有机会将我最大的两个爱好——数据科学和篮球——结合在一起无异于梦想成真,能够会见来自 NBA 各地的分析师是一次我将永远珍惜的经历。
Team 3!
用机器学习预测 NBA 新秀数据
Photo by NeONBRAND on Unsplash
每年,来自世界各地的数百万篮球迷都会收看 NBA 选秀,希望他们最喜爱的球队能够夺金,发现下一个 NBA 巨星。这些 NBA 球队前台办公室的人花费数千小时来寻找和评估大学和国际人才,试图找到能够在职业水平上取得成功并为球队做出贡献的球员。随着数据科学领域的发展,尝试超越传统方法来评估人才是有意义的。这篇文章记录了一个项目,试图通过预测最新一批 NBA 新秀的统计数据来做到这一点。
数据准备
这个项目的总体目标是预测某些球员在 NBA 的第一年在得分、助攻、篮板、抢断和盖帽方面的表现,实现这一目标的第一步是创建正确的数据集。有很多变量有助于 NBA 球员的成功,但对于这个项目,我决定专注于这些不同的球员在大学水平上的表现。为了创建这个数据集,BeautifulSoup 被用来收集 2000 年至 2018 年期间从www.basketball-reference.com选秀的 NBA 新秀数据。在那之后,所有那些被选中的球员的平均大学统计数据都是从 www.sports-reference.com/cbb 的 T2 收集来的,所有的数据都被很好地格式化成 python 上的熊猫数据框。所有为这个项目而创建的数据集现在都可以在这里找到。csv 文件。
分析
在进入机器学习模型之前,最好先检查数据集,寻找任何基本/有趣的模式和异常。
统计趋势
通过创建不同年份的各种统计数据的箱线图,对大学篮球和职业篮球的演变进行了可视化。
Box plot distribution of the average points scored in college of players drafted by Year.
今年的草案类别(由 2020 年的方框图表示)在任何统计类别中都不突出。这应该转化为今年的选秀班是一个非常典型的选秀班,因为它将遵循前几年设定的模式,即有几个超级明星,有太多中等或中等以下的角色球员…
Box plot distribution of the average 3 pointers attempted by NBA Rookies by Year
NBA 新秀方框图被证明是更有趣的,虽然有很多更重要的趋势和模式。这里最吸引人的模式是关于三分球的演变以及它是如何在最近几年变得越来越流行的。与近年来平均三分球命中率的上升一样有趣的是,这一三分球趋势的支点最近出现了。在 2010 年之前,看起来没有任何一个新秀赛季场均 1 3 分,而在 2010 年之后,几乎每个新秀赛季都超过了这个数据。
簇
除了从寻找历史统计趋势的角度分析数据之外,还从具有两个主要目标的聚类分析角度分析数据。生成的聚类透视了这个选秀职业中的球员如何相互堆叠,以及这个选秀职业中的球员如何堆叠前几年的新秀。
Agglomerative Clustering on college stats of 2019 draft class
三种不同的聚类算法(K-Means 聚类、凝聚聚类和相似性传播)在今年选秀班的大学统计数据集中运行。锡安·威廉姆森(Zion Williamson)是一位受到体育媒体界大量炒作的下一位超级巨星,所有聚类算法都将他的大学表现与布兰登·克拉克(Brandon Clarke)和波尔·波尔(Bol Bol)进行比较。
Affinity Propagation Clustering on college stats of 2000-2019 draft class
同样的三个聚类算法在由过去 20 个 NBA 选秀班的球员的大学统计数据组成的数据集上运行,并且获得了一些有趣的结果。亲和力传播模型在这里将锡安描述为布雷克·格里芬和迪安卓·艾顿的混血儿,它相应地估计他每场比赛将得到令人印象深刻的 19.4 分,11.2 个篮板,2.8 次助攻,0.85 次抢断和 0.7 次盖帽。
特征工程
创建强大的机器学习模型的三个主要步骤来自于选择/操纵输入特征,选择最成功的算法,以及微调该算法的超参数。这就是为什么在通过所有的 ML 算法运行数据之前,需要对数据集进行一些调整。
分类变量,例如学院的名称和选拔球员的球队的名称,最初被分解成一系列虚拟变量,唯一地代表每个学院/球队。这项技术最终没有成功,因为在这个修改的数据集上运行的算法往往比在没有团队或学院的原始数据集上运行的算法产生更低的指标。
团队变量不是很强,因为团队每年都会发生根本性的变化。例如,将 2010 年赢得 74%比赛的克利夫兰骑士队与 2011 年赢得 23%比赛的克利夫兰骑士队相提并论似乎不太正确。这就是为什么球队变量在球员被选中前一年被替换为一些关于球队成功的元数据特征。获胜、每场比赛的点数差异等)。结果在一定程度上验证了这种功能扩展,因为在修改的数据集上运行的算法比在只有 team 的原始数据集上运行的算法产生了更好的度量。
Correlation matrix between various features
除了用虚拟变量进行实验之外,还构建了一个相关矩阵,以更好地理解输入变量和目标变量之间的关系强度。例如,如上图所示,在大学里每场比赛的投篮次数和 NBA 里每场比赛的实际得分之间似乎有很强的相关性。
循环特征消除也用于确定要考虑的最佳变量子集。这种方法的工作原理是从线性回归模型中重复检索特征重要性,并删除重要性最低的特征。根据实验,发现使用 RFE 将输入变量从 37 个减少到 30 个产生了最好的结果。
模型
在整个实验过程中运行了许多不同的算法,下面描述的所有算法的原始代码可以在这里找到。
线性回归
Linear Regression via the Method of Least Squares in 2 dimensions
在进入所有花哨的算法之前,运行一个基本的回归模型来设置一些基线基准。线性回归被选为基准模型,该算法的工作原理是尝试绘制一条直线,穿过 N 维训练集中提供的所有点(其中 N 是数据集中的要素数量)。这条线的方程是按照最小二乘法计算的,其目标是使误差的平方和最小。
随机福里斯特
A simple Decision Tree example
使用的第一个主要算法是随机 Forrest 回归器,该算法通过挑选位于 N 个随机输入要素和 M 个随机列的交集中的数据的过程,从原始训练数据集中随机提取各种子集。接下来,对所有这些不同的子集运行上面说明的基本决策树算法。一旦创建了所有的树,就通过对每个决策树运行输入特征所产生的结果取平均值来计算测试集中元素的预测。
额外的树
The process of creating multiple decision trees to make a prediction
第二次运行的算法是额外树回归器,该算法的行为方式与随机 Forrest 回归器非常相似。就像 Random Forrest 一样,Extra Trees 对从训练数据集生成的各种随机子集运行决策树算法来创建预测。这两种算法的最大区别在于决策树在子集上运行的方式。随机森林算法使用传统的决策树方法,其中在分割点使用的特征和值是基于在该步骤获得的信息来确定的。额外树算法使用一种更宽松的决策树方法,其中在分割点使用的特征和值是随机选择的。
XGBoost
Process behind the Gradient Boosting technique
下一次运行的算法是 XGBoost,该算法使用一种称为梯度增强的技术来创建一个强大而准确的模型。梯度推进的工作原理是递归地在彼此之上构建不同的模型,以最小化误差值。由于 XGBoost 的整个目标是最小化在训练集上发现的错误,所以该算法偶尔会过度拟合数据,并在测试集上执行 subpar。
神经网络
Example of a simple feed forward Neural Network
接下来的挑战是设计有效和适当的神经网络来理解提供的数据。神经网络的工作方式与上述所有算法完全不同,但神经网络的核心组成可以描述为一系列由节点组成的层,这些节点通过权重和激活函数连接到下一层的节点。更具体地说,某个隐藏层 N 的节点中的值由前一层的节点内部的值定义,这些值与初始随机化的权重进行线性组合,并通过某个激活函数运行。神经网络背后的算法试图不断地修改这些最初随机的权重,目的是产生接近于所提供的目标输出的输出。
TPOT
The automated pipeline process behind TPOT
最终运行的算法是 TPOT,这个算法本质上与前面提到的算法有很大的不同,因为它实际上是一个用来寻找好的算法和模型的工具。它的本质是利用遗传编程不断淘汰效果不佳的模型,从而返回最成功的模型。
结果
归根结底,机器学习实际上是一个结果驱动的游戏,产生更高指标的模型比不产生更高指标的模型更有价值。就本项目而言,有 5 个主要指标用于比较不同模型的成功性。
- 调整后的测试 r:该统计测量测试集上调整后的 r 值。该统计值的范围从-inf 到 1,值越大表示结果越好。
- 交叉验证得分:该统计数据是通过将 100 乘以在数据集内不同的训练测试分割上运行算法所产生的原始 r 的平均值而得到的。该统计值的范围从-inf 到 100,值越大表示结果越好。
- 百分比非常准确:如果预测与实际结果相差在 20%以内,则认为预测“非常准确”。这个统计数据查看测试集中被标记为“非常准确”的百分比。
- 准确百分比:如果预测与实际结果相差 20%到 50%,则认为预测是“准确的”。这个统计数据查看测试集中被标记为“准确”的百分比。
- 点差误差:该统计信息查看测试集中有多少百分比的预测与实际结果相差不到 2 个点。
Result metrics from the different algorithms
创建了一个基本网站,以更深入和互动的方式显示上表中的结果。
预言
这个项目的最后一步是通过使用上述见解来预测即将到来的新秀职业的统计数据,从而完成最初的目标。
在所有预期的算法中,随机福里斯特回归器被选中来分析即将到来的新秀班的大学数据,并预测这些球员一旦进入 NBA 会有什么样的统计数据。随机福里斯特被选中是因为它有最高的点差错误分数,它有第二高的 CV 分数。Extra Trees 可以说是更好的算法,因为它比 Random Forrest 具有更高的 CV 分数和更高的调整后 r,但经过更仔细的检查,Extra Trees 在分析“精英”球员时的表现不如 Random Forrest。Random Forrest 将“精英”球员定义为在新秀年平均每场比赛超过 10 分的球员,他非常准确地识别了 14 名球员中的 5 名,并准确地识别了 14 名球员中的 2 名。另一方面,额外的树只能非常准确地识别 14 个玩家中的 3 个,并准确地识别 14 个玩家中的 2 个。
下面的表格在左边显示了按照他们被选中的位置排序的新人,在右边显示了按照总价值排序的预测数据的新人。总价值是根据这些指导方针预测的每场游戏的幻想点数输出。表格也按照位置进行了划分,以便读者能够容易地理解在这个特定的选秀职业中,一个玩家如何与其他类似的玩家进行较量。
控球后卫:
得分后卫:
小前锋:
大前锋:
中心:
生成的结果的完整表格可以在这里找到。创建了一个简单的网站,以更具交互性的方式显示上表中的结果。
This module displays the predicted stats of individual prospective players. The full website is available here.
未来的工作
“数据科学家的天性就是永远不会对自己的工作感到完全满意”。— 尼拉布·潘特博士
这个项目有很大的潜力,可以帮助 NBA 球探在 NCAA 找到能够在下一阶段茁壮成长并取得成功的球员。尽管如此,这个项目还远远没有真正结束。以上所有模型仍可进一步调整和试验,以提供更好和更准确的结果。
关于这个项目的更多信息,你可以参考我的 GitHub ,如果你有任何意见或问题,欢迎在下面发帖或在 siddhesvark@gmail.com 给我发邮件。
预测下一个购买日
使用 Python 实现数据驱动的增长
机器学习模型预测顾客下次购买的时间
这一系列文章旨在解释如何以一种简单的方式使用 Python,通过将预测方法应用于您的所有行动来推动您公司的发展。它将是编程、数据分析和机器学习的结合。
我将在以下九篇文章中讨论所有主题:
1- 了解你的衡量标准
2- 客户细分
3- 客户终身价值预测
4- 流失预测
5-预测下一个购买日
文章将有自己的代码片段,使您可以轻松地应用它们。如果你是编程的超级新手,你可以在这里很好地介绍一下 Python 和 Pandas (一个我们将在任何事情上使用的著名库)。但是仍然没有编码介绍,您可以学习概念,如何使用您的数据并开始从中产生价值:
有时候你得先跑,然后才能走——托尼·斯塔克
作为先决条件,确保你的电脑上安装了 J upyter Notebook 和 P ython 。代码片段只能在 Jupyter 笔记本上运行。
好吧,我们开始吧。
第 5 部分:预测下一个购买日
我们在“数据驱动增长”系列中解释的大多数行动背后都有相同的思路:
在客户期望之前,以他们应得的方式对待他们(如 LTV 预测),在不好的事情发生之前采取行动(如流失)。
预测分析在这一点上对我们帮助很大。它可以提供的众多机会之一是预测客户的下一个购买日。如果您知道客户是否可能在 7 天内再次购买,该怎么办?
我们可以在此基础上构建我们的战略,并提出许多战术行动,例如:
- 此客户没有促销优惠,因为她/他无论如何都会购买
- 如果在预测的时间窗口内没有购买,用集客营销来推动客户(或者解雇预测🦹♀️ 🦹♂️的人)
在本文中,我们将使用在线零售数据集,并遵循以下步骤:
- 数据争论(创建上一个/下一个数据集并计算购买日差异)
- 特征工程
- 选择机器学习模型
- 多分类模型
- 超参数调谐
数据争论
让我们从导入数据开始,并做初步的数据工作:
导入 CSV 文件和日期字段转换
我们已经导入了 CSV 文件,将日期字段从字符串转换为日期时间以使其可用,并过滤掉了除英国以外的国家。
为了构建我们的模型,我们应该将数据分成两部分:
Data structure for training the model
我们使用六个月的行为数据来预测客户未来三个月的首次购买日期。如果没有购买,我们也会预测。假设我们的截止日期是 2011 年 9 月 9 日,然后分割数据:
tx_6m = tx_uk[(tx_uk.InvoiceDate < date(2011,9,1)) & (tx_uk.InvoiceDate >= date(2011,3,1))].reset_index(drop=True)tx_next = tx_uk[(tx_uk.InvoiceDate >= date(2011,9,1)) & (tx_uk.InvoiceDate < date(2011,12,1))].reset_index(drop=True)
tx_6m 代表六个月的业绩,而我们将使用 tx_next 来找出 tx_6m 中最后一次购买日期和 tx_next 中第一次购买日期之间的天数。
此外,我们将创建一个名为 tx_user 的数据帧,以拥有预测模型的用户级特征集:
tx_user = pd.DataFrame(tx_6m['CustomerID'].unique())
tx_user.columns = ['CustomerID']
通过使用 tx_next 中的数据,我们需要计算我们的标签(截止日期前最后一次购买和之后第一次购买之间的天数):
现在,tx_user 看起来如下:
正如你很容易注意到的,我们有 NaN 值,因为那些客户还没有购买。我们用 999 填充 NaN,以便稍后快速识别它们。
我们在数据帧中有客户 id 和相应的标签。让我们用我们的功能集来丰富它,以建立我们的机器学习模型。
特征工程
对于这个项目,我们选择了如下候选功能:
- RFM 分数和聚类
- 最近三次购买的间隔天数
- 购买天数差异的均值和标准差
添加这些特征后,我们需要通过应用 get_dummies 方法来处理分类特征。
对于 RFM,为了不重复第 2 部分,我们共享代码块并继续前进:
RFM Scores & Clustering
让我们来关注如何添加接下来的两个特性。在这一部分我们将会大量使用 shift() 方法。
首先,我们用客户 ID 和发票日期(不是日期时间)创建一个 dataframe。然后,我们将删除重复的,因为客户可以在一天内多次购买,差异将成为 0。
#create a dataframe with CustomerID and Invoice Date
tx_day_order = tx_6m[['CustomerID','InvoiceDate']]#convert Invoice Datetime to day
tx_day_order['InvoiceDay'] = tx_6m['InvoiceDate'].dt.datetx_day_order = tx_day_order.sort_values(['CustomerID','InvoiceDate'])#drop duplicates
tx_day_order = tx_day_order.drop_duplicates(subset=['CustomerID','InvoiceDay'],keep='first')
接下来,通过使用 shift,我们创建包含最近 3 次购买日期的新列,并查看我们的数据帧看起来是什么样的:
#shifting last 3 purchase dates
tx_day_order['PrevInvoiceDate'] = tx_day_order.groupby('CustomerID')['InvoiceDay'].shift(1)
tx_day_order['T2InvoiceDate'] = tx_day_order.groupby('CustomerID')['InvoiceDay'].shift(2)
tx_day_order['T3InvoiceDate'] = tx_day_order.groupby('CustomerID')['InvoiceDay'].shift(3)
输出:
让我们开始计算每个发票日期的天数差异:
tx_day_order['DayDiff'] = (tx_day_order['InvoiceDay'] - tx_day_order['PrevInvoiceDate']).dt.daystx_day_order['DayDiff2'] = (tx_day_order['InvoiceDay'] - tx_day_order['T2InvoiceDate']).dt.daystx_day_order['DayDiff3'] = (tx_day_order['InvoiceDay'] - tx_day_order['T3InvoiceDate']).dt.days
输出:
对于每个客户 ID,我们使用**。agg()** 找出购买天数差异的平均值和标准差的方法:
tx_day_diff = tx_day_order.groupby('CustomerID').agg({'DayDiff': ['mean','std']}).reset_index()tx_day_diff.columns = ['CustomerID', 'DayDiffMean','DayDiffStd']
现在我们要做一个艰难的决定。上面的计算对于有很多采购的客户来说相当有用。但是我们不能对那些购买 1-2 次的人说同样的话。例如,将一个客户标记为 频繁 还为时过早,他只有两次购买,但却是连续购买。
我们只保留购买次数超过 3 次的客户,使用以下热线:
tx_day_order_last = tx_day_order.drop_duplicates(subset=['CustomerID'],keep='last')
最后,我们删除 NA 值,将新数据帧与 tx_user 合并,并应用**。get_dummies()** for 转换分类值:
tx_day_order_last = tx_day_order_last.dropna()tx_day_order_last = pd.merge(tx_day_order_last, tx_day_diff, on='CustomerID')tx_user = pd.merge(tx_user, tx_day_order_last[['CustomerID','DayDiff','DayDiff2','DayDiff3','DayDiffMean','DayDiffStd']], on='CustomerID')#create tx_class as a copy of tx_user before applying get_dummies
tx_class = tx_user.copy()
tx_class = pd.get_dummies(tx_class)
我们的特征集已准备好构建分类模型。但是有很多不同的型号,我们应该使用哪一种呢?
选择机器学习模型
在开始选择模型之前,我们需要采取两个行动。首先,我们需要识别标签中的类。一般来说,百分位数给出了这个权利。还是用吧。describe() 方法在 NextPurchaseDay: 中看到它们
决定边界是一个统计和商业需求的问题。就第一点而言,它应该是有意义的,并且易于采取行动和沟通。考虑到这两个,我们将有三个类:
- 0–20:将在 0–20 天内购买的客户— 类别名称:2
- 21–49:将在 21–49 天内购买的客户— 类别名称:1
- ≥ 50:将在 50 天以上购买的客户— 类别名称:0
tx_class['NextPurchaseDayRange'] = 2
tx_class.loc[tx_class.NextPurchaseDay>20,'NextPurchaseDayRange'] = 1
tx_class.loc[tx_class.NextPurchaseDay>50,'NextPurchaseDayRange'] = 0
最后一步是查看我们的特征和标签之间的相关性。相关矩阵是展示这一点的最简洁的方式之一:
corr = tx_class[tx_class.columns].corr()
plt.figure(figsize = (30,20))
sns.heatmap(corr, annot = True, linewidths=0.2, fmt=".2f")
看起来总分正相关度最高(0.45),而新近度负相关度最高(-0.54)。
对于这个特殊的问题,我们希望使用精度最高的模型。让我们分开训练和测试测试,并测量不同模型的准确性:
Selecting the ML model for the best accuracy
每个型号的精度:
从这个结果中,我们看到朴素贝叶斯是性能最好的一个(大约 64%的准确率)。但在此之前,让我们看看我们到底做了什么。我们应用了机器学习中的一个基本概念,那就是交叉验证。
我们如何确定我们的机器学习模型在不同数据集之间的稳定性?此外,如果我们选择的测试集中有噪声怎么办。
交叉验证是衡量这一点的一种方式。它通过选择不同的测试集来提供模型的得分。如果偏差较低,则表示模型稳定。在我们的例子中,分数之间的偏差是可以接受的(除了决策树分类器)。
通常,我们应该用朴素贝叶斯。但是对于这个例子,让我们用 XGBoost 来展示我们如何用一些先进的技术来改进一个现有的模型。
多分类模型
为了构建我们的模型,我们将遵循前面文章中的步骤。但是为了进一步改进,我们将进行超参数调整。
从程序上讲,我们将找出我们的模型的最佳参数,以使它提供最佳的准确性。
让我们首先从编码我们的模型开始:
xgb_model = xgb.XGBClassifier().fit(X_train, y_train)print('Accuracy of XGB classifier on training set: {:.2f}'
.format(xgb_model.score(X_train, y_train)))
print('Accuracy of XGB classifier on test set: {:.2f}'
.format(xgb_model.score(X_test[X_train.columns], y_test)))
在这个版本中,我们在测试集上的准确率是 58%:
XGBClassifier 有许多参数。你可以在这里找到他们的名单。对于这个例子,我们将选择最大 _ 深度和最小 _ 子 _ 重量。
以下代码将为这些参数生成最佳值:
from sklearn.model_selection import GridSearchCVparam_test1 = {
'max_depth':range(3,10,2),
'min_child_weight':range(1,6,2)
}
gsearch1 = GridSearchCV(estimator = xgb.XGBClassifier(),
param_grid = param_test1, scoring='accuracy',n_jobs=-1,iid=False, cv=2)
gsearch1.fit(X_train,y_train)
gsearch1.best_params_, gsearch1.best_score_
该算法认为最大深度和最小子权重的最佳值分别为 3 和 5。了解它如何提高精确度:
我们的分数从 58%上升到 62%。这是相当大的进步。
知道下一个购买日也是预测销售的一个很好的指标。我们将在第 6 部分中深入探讨这个话题。
你可以在这里找到这篇文章的笔记本。
享受数据驱动增长系列?给我买杯咖啡这里 …
用 Julia 中的车床预测纽约市的拍品价格
没错女士们先生们,介绍:第一个车床. jl 模型,并不意外;是线性回归。
Julia 是一种奇妙的、强大的语言(尤其是如果你喜欢编程 arduino 板。也就是说,鉴于 Julia 是一种非常函数式的语言,它几乎与生俱来的基础结构使得它非常适用于传统上被认为是面向对象的编程。然而,Julia 相对缺乏的目标受众是数据科学家。
虽然很多 Julia 的老手可能对 pkg . add()-为 3 个不同的模型提供 7 个不同的包没有问题,但这却是我对 Julia 最大的不满。Julia 有一个绝对神奇(更不用说简单)的包,Flux.jl 用于渐变、图像识别,所有这些有趣的东西,但不幸的是,我觉得这些包在预测性机器学习方面存在不足,特别是无监督学习。随着我计划改变这一点,通过为 Julia 数据科学家(包括我自己)将大量数据科学工具放在一个地方,我最终开始了一个小的包,起初是几个标量,t 测试,f 测试,在某一点上,我开始考虑创建我自己的模型模块,这已经发生在过去的两个月里。
虽然我不认为我的包会改变生活(只是暂时的),但我认为即使在预发布状态,我仍然选择使用它,而不是 Julia 提供的更传统的选项(主要得益于我的本地存储)。)所以今天,我很自豪地向大家呈现 Lathe.jl 的官方 SimpleLinearRegression。
Lathe.jl
如果你有兴趣尝试目前状态的车床. jl,这里是。我适合这个型号的笔记本在这里。我决定用缩放后的数据开始这个项目。虽然有人强烈反对创建和使用缩放数据来测试模型(因为它的发明是泄漏),但这是一个很好的方式来看看你的线性模型是否可以找到一个简单的斜率。对于我的斜率,我选择了 250,我生成了一串随机数,并在 For 循环中将所有迭代乘以 250。
当然,生成的数据总是干净的,所以我直接为我的模型获取基线:
using Lathe: models
# Our y is going to be Price,
# Our x is going to be Doors:
# Fitting our model:
model = models.meanBaseline(traindf.Price)
嘣,就这样,一个合身的模特。当然,下一步是我们的列车预测:
# Put our model, and our xtrain into our predict method
testdf.Baseline = models.predict(model,testdf.Doors)
简单,那么我们能期望什么样的精度呢?
accuracy = Validate.mae(testdf.Price,testdf.Baseline)
println("Baseline accuracy: ",accuracy)Baseline accuracy: -41321.739130434784
我们的平均绝对误差约为 41000,相当糟糕。但这当然是意料之中的,这让我对实际模型的验证更加兴奋。让我们开始吧!:
# Fitting our model:
linreg = models.SimpleLinearRegression(traindf.Doors,traindf.Price)
# Put our x and y into the predict method:
testdf.Prediction = models.predict(linreg,testdf.Doors)
你可能想知道我们的平均绝对误差怎么样了?
linaccuracy = Validate.mae(testdf.Price,testdf.Prediction)
println("Linear Regression Accuracy: ",linaccuracy)Linear Regression Accuracy: 0.0
没错,0.0。如果你是数据科学的杰出人士,你可能会理解为什么它是 0。还记得我说过这是缩放数据吗?不管怎样,这个例子表明,我们的模型能够计算出线性方程的斜率。当然,这太好了!这在现实世界中基本上是没有用的,但至少我有理由做一些很酷的可视化!
The Original Door Data
The slope prediction of the door data
线的斜率几乎相同,这是预期的,平均绝对误差为零。当然,这是我们非常搞笑的基线模型:
Baseline door price prediction
真实世界的数据
现在终于到了将该模型应用于一些真实世界数据的时候了。这是我既喜欢又讨厌做的事情,因为有些数据集真的需要你跳出框框思考,而其他的数据集则很乏味。对于我的数据,我最终选择了来自 Kaggle 的纽约数据集。奇怪的是,由于某种原因,这个数据集看起来有点熟悉,我觉得好像我以前用过它。然而,我认为事实并非如此。我认为我脑海中的数据集只是关于同一主题的数据集。
我最小化了数据集,并检查是否有丢失的值,但没有发现任何丢失的值。
df = DataFrame(:LotArea => df.LotArea, :SalePrice => df.SalePrice,
:YearBuilt => df.YearBuilt,:YearSold => df.YrSold, :Rooms => df.TotRmsAbvGrd)
手里只拿着我喜欢的功能,我跳入了数据探索的奇妙世界。我认为基本的可视化对于更好地理解数据是不可或缺的,这一点我怎么强调都不为过。统计学也很棒,但是一些可视化通常可以用来证明同样的想法,只需要一半的时间,而且在我看来更有趣。
Sale Price and Year Built ; Sale Price and Area (left to right)
有两个特点非常突出,与我的销售价格直接相关。建造年份和地段面积,所以我把数据分开,对它们都进行了 f 检验。它们都显示了很强的统计显著性,我最终选择了 Lot Area,最初是因为我的 x 特征进入了模型。我认为将两个都拟合并比较结果比只拟合一个更有趣(这是拟合的两倍!)
我很兴奋去适应我的模型,但控制和冷静下来是一件好事,首先去获得一个基线。所以,我做了:
# Fit our model once again:
using Lathe: models
model = models.meanBaseline(df.SalePrice)
然后,我创建了一个空的数据框架来处理来自各种预测方法的所有输入数据。
# we'll have a new dataframe for our predictions
using DataFrames
predictions = DataFrame()predictions.Baseline = models.predict(model,testdf.SalePrice)
之后,我们当然会验证:
using Lathe: Validate
baseline_accuracy = Validate.mae(testdf.SalePrice,predictions.Baseline)
println("==========>")
println("Baseline Accuracy - ",baseline_accuracy)
println("==========>")==========>
Baseline Accuracy - 1.9455711319021984e-11
==========>
哇哦!这是一些可怕的准确性!我当然跳出来拟合一个模型,比较这些分数。
# Fit our new model!
model = models.SimpleLinearRegression(testdf.LotArea,testdf.SalePrice)
# And we'll check out what that looks like:
predictions.Prediction = models.predict(model,testdf.LotArea)
我开始验证:
BasePredAccuracy = Validate.mae(testdf.SalePrice,predictions.Prediction)
println("=========>")
println("Baseline Accuracy: ",baseline_accuracy)
println("-------------------")
println("Model Accuracy: ",BasePredAccuracy)
println("=========>")=========>
Baseline Accuracy: 1.9455711319021984e-11
-------------------
Model Accuracy: 173848.28232265453
=========>
如此之大,模型的准确性比基线有了显著的提高。
我尝试用一个重标量进行一些预处理,但是看起来 Z 标量对于大幅度提高精度是必要的。但是当然,如果没有更多的视觉化,我不能结束。
Visualizing my model, room frequency, and lot area.
最后,我对车床的未来感到非常兴奋。这个模型是许多的开始,并且当前的统计是更多的开始。对我来说,在 Julia 中,车床使机器学习变得容易得多。我希望它在未来对其他人也是如此,如果你想做任何改进,请随意在这里发表。
使用线性回归预测 PewDiePie 的每日订户。
让我们了解一下如何使用线性回归来预测 PewDiePie 的日订阅人数。
Credits: Fandom
PewDiePie 是瑞典的 YouTube,在 YouTube 上拥有 1 亿订户(他是我的最爱)。他每天都有成千上万的用户,所以我想写一篇关于他的用户增长的教程。所以我想给你们展示一个机器学习的线性回归算法的实际实现。这里我们可以应用线性回归来预测他的 YouTube 日订阅量。我将在本教程中指导你们如何去做。本教程的完整代码可以在我的 GitHub 上找到。我不会解释线性回归算法背后的理论,因为根据我的说法,理论并不重要,只有实现才是非常重要的,因为你需要知道如何以及在哪里应用算法。不过,我会鼓励你在网上浏览一些理论,其中一篇最好的文章如下所示:
线性回归通常是每个数据科学家遇到的第一个机器学习算法。这是一个…
towardsdatascience.com](/linear-regression-using-python-b136c91bf0a2)
让我们开始吧:
我们将遵循以下步骤来完成此实施:
- 导入必要的库。
- 从 CSV 文件中读取数据集。
- 将数据集分成独立变量(x)和因变量(y)。
- 将完整数据集划分为训练数据集和测试数据集。
- 基于简单线性回归实现我们的分类器。
1.导入必要的库。
在本教程中,我将使用一些重要的库,如:
- numpy
- 熊猫
- sklearn.linear
- sklearn.model_selection
Numpy: 我使用 Numpy 库的原因是,在本教程的结尾,我对一些值进行了四舍五入,以获得更准确的结果。为了调用 round 方法,我需要导入 numpy 库。要阅读 numpy 库的官方文档,请访问下面的链接:
欢迎光临!这是 NumPy 1.18.0.dev0+07a5753 的文档,最后更新于 2019 年 9 月 25 日。部分…
numpy.org](https://numpy.org/devdocs/)
如你所知,我正在使用 YouTube 上的 PewDiePie 的数据,我需要将它们存储在某种形式的数据框中,为了将数据存储在数据框中,我正在使用 pandas 数据框,使用 Pandas 数据框非常简单和有趣。要阅读熊猫图书馆的官方文件,请访问下面的链接:
[## pandas:强大的 Python 数据分析工具包- pandas 0.25.1 文档
是一个开源的、BSD 许可的库,提供高性能、易于使用的数据结构和数据分析工具…
pandas.pydata.org](https://pandas.pydata.org/pandas-docs/stable/)
Sklearn.linear: 如你所知,现在我正在使用线性回归算法来预测数据,我需要导入线性回归库,但是你不能直接导入线性回归库,虽然你需要导入 sci-kit learn 来帮助你访问线性回归库。这就是我使用 sklearn.linear 的原因。要阅读该库的官方文档,请访问下面的链接:
[## sklearn.linear_model。线性回归-sci kit-学习 0.21.3 文档
当 fit_intercept 设置为 False 时,此参数将被忽略。如果为真,回归量 X 将在…之前被标准化
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html)
sklearn.model_selection: 如果您正在实施线性回归来预测数据,那么将数据分为训练数据和测试数据通常是一个好的做法,只有这样,您预测的数据才会更加准确。为此,您需要从 scikit learn 导入 model_selection 库。要阅读官方文档,请访问以下链接:
[## 模型选择:选择估计量及其参数-sci kit-学习 0.21.3 文档
Scikit-learn 有一个类集合,可以用来为流行的
scikit-learn.org](https://scikit-learn.org/stable/tutorial/statistical_inference/model_selection.html)
在 python 中导入任何库的快速注意事项你所要做的就是说“导入库名”,库名如 pandas,numpy 等等。
导入本教程所需的库如下所示:
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
2。从 CSV 文件中读取数据集。
我已经将 PewDiePie 的订户数据以 CSV 格式存储在 Kaggle 中。Kaggle 是世界各地的人们发布和存储数据集的地方。在这里,我将数据存储为 CSV(逗号分隔值)格式。要下载数据集,请查看以下链接:
下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…
www.kaggle.com](https://www.kaggle.com/tanuprabhu/pewdiepies-subscribers)
您可以通过单击下载选项下载数据集。要将数据转换成 python 中的格式,您必须使用 pandas 数据框。在此之前,你必须将数据加载到你的笔记本中(我正在使用 Google Colab 来键入我所有的 python 代码),在线上有多种方法可以将数据加载到笔记本中,但最简单的方法是在笔记本左侧的 Google Colab 中,你会发现一个“>”(大于符号)。当你点击它时,你会发现一个有三个选项的标签,你只需要选择文件。然后你可以在上传选项的帮助下轻松上传你的文件。无需安装到 google drive 或使用任何特定的库,只需上传数据集,您的工作就完成了。在这一步要记住的一点是,当运行时被回收时,上传的文件将被删除。这就是我如何把数据集放进笔记本的。
**# Storing the data in a pandas data frame.**
df = pd.read_csv(“PewDiePie.csv”)
df.head(5)
如您所见,上面的数据集包含两列,data 和 subscribers。我知道日期列看起来很混乱,不要担心,多想想,它只是存储了 2019 年 5 月的第一天(像 5 月 1 日、5 月 2 日等等)。订户列包含 PewDiePie 的所有订户。
3。将数据集分成独立变量(x)和因变量(y)。
在将数据集划分为训练数据和测试数据之前,您需要区分哪些是因变量,哪些是自变量,然后才能进行划分。这可以通过以下方式完成:
x = df.iloc[:, :-1]
y = df.iloc[:, 1]
这里,“x”值包含数据,“y”值包含用户,iloc 用于从数据帧中获取值。我使用[:,:-1]的原因是因为我需要数据帧的倒数第二列,而[:1]给出了数据帧的最后一列。您可以打印该值进行确认。
4。将完整数据集划分为训练数据集和测试数据集。
为了得到一个好的预测,将数据分为训练和测试数据,这是因为顾名思义,你将训练几个数据点和测试几个数据点,并继续这样做,除非你得到好的结果。
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 0)
这里,“x”和“y”变量被分为训练和测试数据,如上面的代码片段所示,测试数据的大小为 0.3 或 30%,其余为 70%(训练数据),random_state 是随机数生成器使用的种子。
注意:试着把 x 和 y 的训练值都打印出来,你就明白我在说什么了。
**HINT:** print(x_test)
5。基于简单线性回归实现我们的分类器。
这是最重要的一点,因为这是我们应用线性回归算法的地方,要做到这一点,我们必须将经过训练的测试值提供给实际算法,这样我们就可以预测订户。为此,请遵循以下代码:
simplelinearRegression = LinearRegression()
simplelinearRegression.fit(x_train, y_train)**LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)**
在上面的代码中,我们调用了线性回归函数,然后试图绕过训练值来拟合模型。
y_predict = simplelinearRegression.predict(x_test)
predict = pd.DataFrame(y_predict)
predict.apply(np.round)
然后我们需要使用 then predict 方法来预测这些值,为此我们需要传递“x”变量的测试值,这样我们就可以获得预测值(订户)。下一行代码只是转换,这是因为 y_predict 是 numpy 数组类型,所以我们需要将其转换为数据帧,然后才能应用 round 函数。现在,变量 predict 包含所有预测的订户,如下所示:
稍后,我会将数据放入 while 循环中,以实际格式获取它,不要担心,这只是一个带有预测值的打印语句,一旦您跟踪它,就会得到它:
while i <= 28:
print(“Total number of increase in subscribers on May %d ==>” %(i) , int(simplelinearRegression.predict([[i]])))
i= i+1 **Total number of increase in subscribers on May 21 ==> 29154
Total number of increase in subscribers on May 22 ==> 28210
Total number of increase in subscribers on May 23 ==> 27266
Total number of increase in subscribers on May 24 ==> 26322
Total number of increase in subscribers on May 25 ==> 25378
Total number of increase in subscribers on May 26 ==> 24434
Total number of increase in subscribers on May 27 ==> 23491
Total number of increase in subscribers on May 28 ==> 22547**
这就是 predict 函数预测订户的方式,predict 函数返回的订户是准确的。下面给出的是社会刀片统计,你可以比较其余的。
Credits: Social Blade
如下图所示,当您将预测值的结果与上面由 Social Blade 获得的实际订户进行比较时,结果几乎相同,除了这里或那里可以找到一些或多或少的订户,但没关系,机器学习无法 100%准确地预测。因此,这就是你如何使用机器学习算法来预测 PewDiePie 的每日订户。如果你对代码有任何疑问,评论区都是你的。如有疑问,请联系我。此外,代码可以在我的 GitHub 库中找到。谢谢你们阅读我的文章。再见,开始练代码,下次见。
用确定性模型预测药代动力学
临床数据科学
精准医疗之路。
Photo by Myriam Zilles on Unsplash
介绍
药物动力学
【药代动力学】 处理 异生素 在生物体内的分布和代谢。在药物开发和临床研究中,人们会遇到 药理学家 ,他们的工作是建议医生给病人提供药物的剂量。为此,他们经常运行所谓的药代动力学模型的模拟,这些模型是确定性的,即它们由关于时间变量的 常微分方程 组成,并描述以下过程(称为 LADME):
- ****:药物从药物配方中释放出来的过程
- 吸收 : 物质进入血液循环的过程
- 分布 : 物质在身体的体液和组织中的扩散或散布
- 代谢 : 生物体对存在外来物质的识别以及母体化合物向子代谢物的不可逆转化
- 清除 :从体内清除物质
这种模型有助于确定药物的最佳剂量,作为患者属性的函数,如体重、身高、年龄或性别。此外,可以预测药物在血浆中随时间的浓度分布。此外,可以监测 药物相互作用 。这样,可以为单个患者定义给药间隔,为 个性化治疗 铺平道路(更多信息请访问 openPK )。
确定性建模
通常,作为确定性模型一部分的这些方程组具有未知的参数,并且必须根据实验数据进行估计。身体本身被描述为一个 多隔室 系统(器官是隔室),在其中发生所述过程的子集,并且药物/代谢物分子从一个隔室(器官)流向另一个隔室。通常假设所述隔室是理想混合的,即进来的分子立即混合。请注意,依赖于时间的实验数据通常并不适用于所有的房室,尤其是人类。**
Plasma concentration of paracetamol for a 50-kg patient and a dose of 1 g as it can be encountered on openPK. (image by author)
模型开发
模型组成
开发这样一个模型的方法是制定一组微分方程(在我的 GitHub 上可以找到一个在 MATLAB 中编程的处理 乙醇 代谢的例子)。下面的等式是对隔室 k 中的化合物 i 具有流量 Q 和体积 V 的质量平衡的一般公式。 P 是一个分配系数,表示某一组织中保留了多少化合物。 Q 和 V 取决于患者的体重、身高、年龄和性别(用 异速生长标度 建模)。
**dc_dt_i_k = (Q_k/V_k)*(c_in_i_(k-1)-c_i_k/P_i_k)**
每个隔间的 Q 、 V 、和 P 的值可在文献中找到。此外,药物在肝脏部分代谢,在肾脏部分排泄。在这种情况下,肝脏和肾脏的方程被修改。
**dc_dt_i_liver = (1/V_liver)*(Q_liver*(c_in_i-c_i_liver/P_i_liver)-**v_max_i*c_i_liver/(K_m_i+c_i_liver)**)dc_dt_i_kidney = (1/V_kidney)*(Q_kidney*(c_in_i-c_i_kidney/P_i_kidney)-**k_r_i*c_i_kidney****
肝方程式中的粗体术语代表由酶催化的反应的所谓的 米氏-门滕 表达式。它将反应限制到最大反应速度 vmax ,因为用于反应的活性位点的数量是有限的。但是 vmax 和 Km 在文献中并不容易得到,必须从实验数据中估算(间隙项 kr 也是如此)。此外,可能发生与其他分子竞争活性位点的情况,并且反应项可能需要通过包括抑制表达来修改。先验地不清楚哪些过程包括在哪些区间中。例如,药物在胃肠道内被吸收到血液中,但它也可能在那里分解。要走的路是制定一个初始模型,估计其参数,并在测试集上评估其性能。如果模型性能不足,则通过添加或删除一些项来改进模型,并重复该过程直到收敛。
参数估计
有不同的目标函数用于参数估计。首先,常规的 最小二乘问题 可以被最小化(浓度是参数 p 的函数,目标函数 J 也是如此)。为此,所有隔室 k 中的所有化合物 i 的浓度堆叠在一列中(使用整形功能以避免 for 循环)。变量 c_m 是指测量的浓度,而 c_ p 是预测的浓度。**
**J = (1/N)*(c_m-c_p)'*(c_m-c_p)**
这个函数的缺点是,它比低浓度的分子更适合高浓度的分子,因为它们对目标的贡献小得多。另一种可能性是用一个协方差矩阵的逆来缩放点积,并将其重新表述为一个 最大似然 问题。当然,方差矩阵 E 也得知道。
**J = (1/N)*(c_m-c_p)'***inv(E)***(c_m-c_p)**
E 可以例如从每个隔室中每种化合物的 变异系数 cv 中估算。
**E = cv'*c_m**
最后,模型必须包含在目标函数中。利用这些参数,使用微分方程求解器(例如, ode15s 处理 刚度 )评估模型并计算预测浓度,即通过 龙格-库塔法 。使用基于实现的 fminunc 之类的解算器来最小化目标函数(类似于 梯度下降 ,但是梯度是围绕当前参数点近似的,并且与目标函数的二阶导数的幅度成比例缩放,这通过允许平坦区域中的更大的步长来增强性能)。执行多起点(参数 p 的不同起点)很重要,以便找到全局最优,而不是以局部最优结束。(注意,最小二乘法可以作为更复杂方法的起点。)
模型验证
该模型最好使用测试集来验证,即该模型没有被训练的数据。平均相对/绝对(平方)误差可以用作度量。另外,重要的是执行一次 灵敏度分析 。为此,计算所有浓度(每个隔室中的每种化合物)相对于所有参数的偏导数。注意,它们是时间相关的,因为浓度是时间相关的。因此,一个参数对输出变量的影响会随时间而变化。必须进一步研究非常敏感的参数和它们所描述的过程。
灵敏度矩阵的 秩 揭示了所有参数是否相互独立( 结构可辨识性);如果秩低于参数的数量,则必须通过移除或重新调整从属参数来重新定义模型。
**R = rank(S)**
此外,应计算参数的置信区间,以检验的实际可识别性。可以使用 费希尔信息 和 克拉美罗界限 来计算参数的方差。
**E_p = inv(S'*inv(E)*S)**
置信区间通过单变量方法计算,仅使用参数协方差矩阵的对角元素和 学生 t 分布 的分位数。
**sigma = sqrt(diag(E_p))CI_lb = p_fit-sigma*tinv(0.95, number_points-number_parameters)CI_ub = p_fit+sigma*tinv(0.95, number_points-number_parameters)**
如果置信区间包括零,那么参数也可以是零,即不参与方程,因此模型应该被改进。请注意,所有参数都应该是正数。
经过几次迭代的拟合和精化,构建过程当然就完成了,得到了合理的测试集性能,模型就可以用于预测了。
Photo by Marcelo Leal on Unsplash
预测英超联赛排名——让数学派上用场
Photo by Abigail Keenan on Unsplash
我最近遇到了一个有趣的问题任务,这是一个基于数学和其他有趣主题的在线地穴搜索的最终挑战(数学和有趣通常不在一起:P),我试图在短时间内找到一个解决方案,这并不坏。在本文中,我试图描述我采用的解决方法,并讨论一些可能的改进。
简单来说,问题任务是:
预测曼联足球俱乐部在英超本赛季(18-19 赛季)积分榜上的最终排名
一些背景
超级联赛是英国足球联赛体系的最高级别,也是世界上收视率最高的体育联赛,潜在电视观众达 47 亿人(是的,它很受欢迎!).20 个俱乐部在一个赛季中比赛,每个俱乐部与其他俱乐部比赛两次(双循环制),一次在他们的主场体育场,一次客场,在他们对手的体育场,每队总共 38 场比赛。
总部位于老特拉福德的足球俱乐部曼彻斯特联队是最成功的俱乐部,创下了 20 个联赛冠军的记录,也是世界上最受支持的足球俱乐部之一。然而,起飞晚了,俱乐部一直遭受着一个混合了 管理 和 投资 的问题,这使得它(几乎)自上次举起这个有声望的头衔以来已经六年了。
谈到足球,我只是一个普通的球迷,但建立一个可以应用于现实世界问题的数学模型的想法似乎足够令人兴奋,值得一试。那我们开始吧,好吗?⚽️)
分解问题
联赛排名主要由每支球队的积分决定,平局则由净胜球打破。因此,为了预测曼联的最终排名,有必要估计所有球队的总积分。然后问题就变成了预测所有比赛的结果。
为了简单起见,可以假设每个匹配结果彼此独立,即任何匹配 X 的结果独立于任何其他匹配 y
两支球队之间的比赛可能有 3 种结果:主队获胜(H),客场获胜(A)或平局(T)。获胜的队伍得 3 分,平局得 1 分。
我们可以随机挑选结果,但那是而不是适合真实世界场景的好模型。实际上,顶级球队战胜低级弱队的机会更大。因此需要一些参数来衡量团队的实力
获取数据和选择参数
有什么比查看团队过去的数据更好的方法来衡量团队的表现呢?我使用了 http://www.football-data.co.uk/data的数据集,其中包括自 1992 年英超联赛成立以来的所有比赛结果,它们被整齐地编译成 CSV 文件。下一步是确定与团队实力密切相关的主导因素。我不得不提到 这篇 出色的博文,它在理解变量方面提供了一些很好的见解,以及非常整洁的 可视化 。可以总结出以下几点:
- 角球、犯规、红黄牌等因素与积分以及球队实力的关系很弱。
- 正相关性最高的最显著因素是净胜球,它基本上转化为一支球队的进攻和防守实力的平衡。**
- 有趣的是,拍摄的数量是成反比的!这意味着一支球队投篮次数越多,得分就越少😮。虽然乍一看似乎有悖逻辑,但事后看来,每一次没有转化为进球的射门尝试都不可避免地将控球权交还给对手,并让他们占据上风,因此出现了负相关。
坚持一个简单的模型,然后我决定使用主客场球队的全职进球数作为参数。
给我看看数学
有效地说,比赛的结果取决于双方的进球数。因此,我们需要对进球的概率分布进行建模。最常见的方法之一是通过泊松分布。( 来源 )
泊松分布测量给定数量的事件在固定时间间隔内发生的概率,前提是这些事件以已知的恒定速率发生,并且与上次事件后的时间无关。
Poisson distribution for x occurrences of the event, λ is the average rate and e is the Euler’s constant
为了理解为什么这个模型适合我们的情况,我们可以认为一个进球得分是一个事件*。那么在 90 分钟的比赛时间内,每个这样的事件可以独立地发生任意次。*
举个例子,让我们试着预测阿森纳和莱斯特城的比赛以 2-1 的比分结束的概率。
剩下的就是计算出恒定速率(λ)* 😗
可以直观地看出,该参数反映了球队的表现,越好的球队平均进球率越高。此外,这个比率取决于两个因素,球队的进攻实力和对手的防守实力。最后,我们还必须考虑到主场优势,也就是说,要考虑到一支球队通常在主场打得更好。
基于上面的讨论,我们可以将参数λ定义为一个队在特定场地的平均进球数,它可以使用过去的数据来计算。**
构建模型
那么让我们建立一些统计数据:
使用上述统计数据,我们现在可以将 λ 参数公式化为 :
模拟比赛
如前所述,两支球队之间的比赛可能有 3 种结果:主队获胜(H),客场获胜(A)或平局(T)。让主队进 X 球,客场进 Y 球。然后:
我们已经看到了如何计算比赛以比分 X-Y 结束的概率。此外,我们可以为一个球队的进球数设定一个实际的上限,比如说 10 个。最后,由于所有得分线都是相互独立的,因此可以简单地将概率相加:
因此,我们可以模拟主队(H)和客场队(A)之间的比赛,并预测各队的得分:
把所有的放在一起
为了预测最终的排名,我们简单地使用模型模拟所有的联赛比赛,并将预测的分数加到积分表中。
最终获得的结果:
所以看起来利物浦和曼城将会获得冠军,而切尔西将会超越热刺。预计曼联将获得第五名,阿森纳紧随其后。结果似乎与当时的普遍舆论一致— 让我们把弗格森带回来吧
点击 找到 的完整代码
结论
一如既往,还有很大的改进空间。一些想法可以尝试:
- 将时间作为一个因素考虑:一个团队的形式可以发挥重要作用,并且时间加权平均值可以被认为赋予最近的比赛更多的重要性
- 看看经理当时的排名作为一个参数是否能提高效率,这可能会很有趣
- 改善模型对平局的低估,一般的想法是现实世界中的平局机会碰巧比模型对平局的平均估计要多
尽管有缺点,这个模型是一个很好的起点,具有相当的准确性。这个练习很有趣,毕竟,它让我在:D 获得了第一名
使用机器学习预测心脏病的存在
机器学习在世界各地的许多领域都有应用。医疗保健行业也不例外。机器学习可以在预测运动障碍、心脏病等疾病的存在/不存在方面发挥重要作用。如果提前预测,这些信息可以为医生提供重要的见解,然后医生可以针对每个患者调整他们的诊断和治疗。
在这篇文章中,我将讨论一个项目,在这个项目中,我使用机器学习算法来预测人们潜在的心脏病。这些算法包括K Neighbors Classifier
、Support Vector Classifier
、Decision Tree Classifier
和Random Forest Classifier
。数据集取自 Kaggle 。我的完整项目可在心脏病预测获得。
导入库
我为这个项目导入了几个库:
- numpy :使用数组
- pandas :处理 csv 文件和数据帧
- matplotlib :用
pyplot
创建图表,用rcParams
定义参数,用cm.rainbow
着色 - 警告:忽略笔记本中可能出现的所有警告,这些警告可能是由于某项功能过去/未来的折旧
- train_test_split :将数据集拆分成训练和测试数据
- StandardScaler :对所有特征进行缩放,使机器学习模型更好地适应数据集
接下来,我导入了所有必要的机器学习算法。
导入数据集
从 Kaggle 下载数据集后,我将它保存到我的工作目录中,命名为dataset.csv
。接下来,我使用read_csv()
读取数据集并将其保存到dataset
变量中。
在做任何分析之前,我只想看一看数据。所以,我用了info()
的方法。
从上面的输出可以看出,总共有 13 个特性和 1 个目标变量。此外,没有丢失的值,所以我们不需要关心任何空值。接下来我用了describe()
的方法。
dataset.describe()
该方法揭示了每个变量的范围是不同的。age
的最大值是 77,而chol
的最大值是 564。因此,必须对数据集执行要素缩放。
理解数据
相关矩阵
首先,让我们看看特征的相关矩阵,并尝试分析它。使用rcParams
将图形尺寸定义为 12 x 8。然后,我用 pyplot 展示了相关矩阵。使用xticks
和yticks
,我将名字添加到关联矩阵中。colorbar()
显示矩阵的颜色条。
Correlation Matrix
很容易看出,没有一个单一的特征与我们的目标值有非常高的相关性。此外,一些特征与目标值负相关,一些特征与目标值正相关。
柱状图
这种类型的图最好的部分是,它只需要一个命令来绘制图,并提供如此多的信息作为回报。用dataset.hist()
就行了。
dataset.hist()
我们来看看剧情。它显示了每个要素和标注在不同范围内的分布情况,这进一步证实了缩放的必要性。接下来,无论你在哪里看到离散的条,它基本上意味着这些实际上是一个分类变量。在应用机器学习之前,我们需要处理这些分类变量。我们的目标标签有两类,0 表示无疾病,1 表示有疾病。
目标类的条形图
我们正在处理的数据集应该大致平衡,这一点非常重要。一个极度不平衡的数据集会使整个模型训练变得无用,因此是没有用的。我们用一个例子来理解一下。
假设我们有一个 100 人的数据集,其中有 99 名非患者和 1 名患者。甚至不需要训练和学习任何东西,该模型总是可以说任何新人都将是非患者,并且准确率为 99%。然而,由于我们更感兴趣的是识别患者,我们需要平衡的数据集,以便我们的模型实际学习。
对于 x 轴,我使用了来自target
列的unique()
值,然后使用xticks
设置它们的名称。对于 y 轴,我使用value_count()
来获取每个类的值。我把条形涂成绿色和红色。
从图中,我们可以看到,类几乎是平衡的,我们很好地进行数据处理。
数据处理
为了处理分类变量,我们应该将每个分类列分成包含 1 和 0 的伪列。
假设我们有一个列Gender
,值 1 表示男性,值 0 表示女性。它需要被转换成两列,其中值 1 表示该列为真,值 0 表示该列为假。看看下面的要点。
为了做到这一点,我们使用熊猫的get_dummies()
方法。接下来,我们需要缩放数据集,我们将使用 StandardScaler。缩放器的fit_transform()
方法缩放数据,我们更新列。
数据集现在准备好了。我们可以从训练我们的模型开始。
机器学习
在这个项目中,我采用了 4 种算法,改变了它们的各种参数,并比较了最终的模型。我将数据集分为67% training data
和33% testing data
。
k 近邻分类器
该分类器寻找给定数据点的 K 个最近邻的类别,并且基于多数类别,它将类别分配给该数据点。然而,邻居的数量可以变化。我让他们从 1 到 20 个邻居变来变去,计算每种情况下的测试分数。
然后,我绘制了邻居数量和每种情况下的测试分数的线图。
如您所见,当邻居数量选择为 8 时,我们获得了 87%的最高分数。
支持向量分类器
该分类器旨在通过调整数据点和超平面之间的距离来形成一个能够尽可能多地分离类别的超平面。基于几个kernels
来决定超平面。我试了四个内核,分别是,线性, poly , rbf ,和 sigmoid 。
一旦我得到了每个人的分数,我就使用rainbow
方法为每个条选择不同的颜色,并绘制出每个人所获得分数的条形图。
从上面的图中可以看出,
linear
内核在这个数据集上表现最好,获得了 83%的分数。
决策树分类器
该分类器创建一个决策树,并基于该决策树将类值分配给每个数据点。在这里,我们可以改变创建模型时要考虑的最大特征数。我将特征的范围从 1 到 30(添加虚拟列后数据集中的全部特征)。
一旦我们有了分数,我们就可以绘制一个线图,看看特征的数量对模型分数的影响。
从上面的线形图中,我们可以清楚地看到,最高得分为 79%,并且是在最大特征被选择为 2、4 或 18 的情况下实现的。
随机森林分类器
这个分类器将决策树的概念带到了下一个层次。它创建了一个树的森林,其中每棵树都是由从所有要素中随机选择的要素组成的。在这里,我们可以改变用于预测类别的树的数量。我计算了 10、100、200、500 和 1000 棵树的测试分数。
接下来,我将这些分数绘制在一个条形图上,看看哪个给出了最好的结果。您可能会注意到,我没有直接将 X 值设置为数组[10, 100, 200, 500, 1000]
。它将显示从 10 到 1000 的连续图,这将是不可能破译的。所以,为了解决这个问题,我首先使用 X 值作为[1, 2, 3, 4, 5]
。然后,我用xticks
给它们重新命名。
看一下条形图,我们可以看到 100 和 500 棵树都达到了 84%的最高分数。
结论
该项目涉及通过适当的数据处理对心脏病患者数据集进行分析。然后,对 4 个模型进行训练和测试,最高得分如下:
- k 近邻分类器:87%
- 支持向量分类器:83%
- 决策树分类器:79%
- 随机森林分类器:84%
k 个邻居分类器在 8 个邻居的情况下取得了 87%的最好成绩。
感谢您的阅读!请随意分享你的想法和主意。