k-均值聚类:算法、应用、评价方法和缺点
使聚集
聚类是最常见的探索性数据分析技术之一,用于获得关于数据结构的直觉。它可以被定义为识别数据中的子组的任务,使得同一子组(聚类)中的数据点非常相似,而不同聚类中的数据点非常不同。换句话说,我们试图在数据中找到同质的子组,使得每个聚类中的数据点根据相似性度量(例如基于欧几里德的距离或基于相关性的距离)尽可能相似。使用哪种相似性度量的决定是特定于应用的。
聚类分析可以在特征的基础上进行,我们试图根据特征找到样本的子组,或者在样本的基础上进行,我们试图根据样本找到特征的子组。我们将在这里讨论基于特征的聚类。聚类用于市场细分;我们试图找到在行为或属性、图像分割/压缩方面彼此相似的客户;其中我们尝试将相似的区域分组在一起,基于主题的文档聚类等。
与监督学习不同,聚类被认为是一种非监督学习方法,因为我们没有将聚类算法的输出与真实标签进行比较以评估其性能的基本事实。我们只想通过将数据点分组到不同的子组来研究数据的结构。
在本帖中,我们将只讨论 Kmeans ,由于其简单性,它被认为是最常用的聚类算法之一。
Kmeans 算法
Kmeans 算法是一种迭代算法,试图将数据集划分为 K 个预定义的不同非重叠子组(聚类),其中每个数据点仅属于一个组。它试图使簇内数据点尽可能相似,同时保持簇尽可能不同(远)。它将数据点分配给一个聚类,使得数据点和聚类质心(属于该聚类的所有数据点的算术平均值)之间的平方距离之和最小。聚类中的差异越小,同一聚类中的数据点就越相似。
kmeans 算法的工作方式如下:
- 指定集群数量 K 。
- 通过首先混洗数据集,然后为质心随机选择 K 个数据点来初始化质心,而无需替换。
- 继续迭代,直到质心没有变化。也就是说,数据点到聚类的分配没有改变。
- 计算数据点和所有质心之间距离的平方和。
- 将每个数据点分配给最近的聚类(质心)。
- 通过取属于每个聚类的所有数据点的平均值来计算聚类的质心。
kmeans 解决问题的方法叫做期望最大化。E 步骤是将数据点分配给最近的聚类。M 步骤是计算每个聚类的质心。下面是我们如何用数学方法解决它的分解(随意跳过)。
目标函数是:
其中,如果数据点 xi 属于聚类 k ,则 wik = 1;否则,wik=0。另外,μk 是 xi 星系团的质心。
这是两部分的最小化问题。我们首先最小化 J . w . r . t . wik,并处理μk 固定。然后我们最小化 J . w . r . t .μk 并处理 wik 固定。从技术上讲,我们首先区分 J w.r.t. wik 并更新集群分配( E-step )。然后,我们对 J . w . r . t .μk 进行微分,并在上一步进行聚类分配后重新计算质心( M 步)。因此,电子步骤是:
换句话说,将数据点 xi 分配给根据其与聚类质心的距离平方和判断的最近的聚类。
而 M-step 是:
这转化为重新计算每个聚类的质心以反映新的分配。
这里需要注意几件事:
- 由于包括 kmeans 在内的聚类算法使用基于距离的测量来确定数据点之间的相似性,因此建议将数据标准化为平均值为零且标准差为一,因为任何数据集中的要素几乎总是具有不同的测量单位,例如年龄与收入。
- 给定 kmeans 的迭代性质和算法开始时质心的随机初始化,不同的初始化可能导致不同的聚类,因为 kmeans 算法可能陷入局部最优,并且可能不会收敛到全局最优。因此,建议使用不同的质心初始化来运行该算法,并选择产生较小距离平方和的运行结果。
- 示例分配不变与组内变化不变是一回事:
履行
这里我们将使用 kmeans 的简单实现来说明一些概念。然后,我们将使用更有效的sklearn
实现来为我们处理许多事情。
应用程序
kmeans 算法是一种非常流行的算法,广泛应用于市场分割、文档聚类、图像分割和图像压缩等领域。我们进行聚类分析的目标通常是:
- 对我们正在处理的数据结构有一个有意义的直觉。
- 如果我们认为不同子群的行为有很大的差异,那么聚类然后预测不同子群将在哪里建立不同的模型。一个例子是将患者分成不同的小组,并为每个小组建立一个模型来预测心脏病发作的风险概率。
在本文中,我们将在两种情况下应用聚类:
- 间歇泉喷发分割(2D 数据集)。
- 图像压缩。
间歇泉喷发分段的方法
我们将首先在 2D 数据集上实现 kmeans 算法,看看它是如何工作的。该数据集有 272 个观测值和 2 个要素。这些数据涵盖了美国怀俄明州黄石国家公园老忠实间歇泉的喷发间隔时间和喷发持续时间。我们将尝试在数据点中找到 K 子群,并相应地对它们进行分组。以下是对这些功能的描述:
- 喷发(浮动):以分钟为单位的喷发时间。
- 等待(int):等待下一次喷发的时间。
让我们先绘制数据:
我们将使用该数据,因为它是一个二维数据集,很容易绘制和直观地发现聚类。很明显,我们有两个集群。让我们首先对数据进行标准化,并对 K=2 的标准化数据运行 kmeans 算法。
上图显示了数据的散点图,这些数据由它们所属的聚类进行着色。在这个例子中,我们选择 K=2。符号 ‘*’ 是每个簇的质心。我们可以认为这两个星团在不同的场景下有不同的行为。
接下来,我们将展示不同的质心初始化可能会产生不同的结果。我将使用 9 个不同的random_state
来改变质心的初始化并绘制结果。每个图的标题将是每个初始化的平方距离之和。
作为一个旁注,这个数据集被认为是非常容易的,收敛不到 10 次迭代。因此,为了查看随机初始化对收敛的影响,我将使用 3 次迭代来说明这个概念。然而,在现实世界的应用程序中,数据集一点也不干净漂亮!
如上图所示,基于不同的初始化,我们最终只有两种不同的聚类方式。我们会选择距离平方和最小的一个。
图像压缩方法
在这一部分,我们将实现 kmeans 来压缩图像。我们将要处理的图像是 396 x 396 x 3。因此,对于每个像素位置,我们将有 3 个 8 位整数来指定红色、绿色和蓝色强度值。我们的目标是将颜色数量减少到 30 种,并且只使用这 30 种颜色来表示(压缩)照片。为了挑选要使用的颜色,我们将对图像使用 kmeans 算法,并将每个像素视为一个数据点。这意味着将图像从高 x 宽 x 通道重塑为(高*宽)x 通道,也就是说,我们在三维空间中将有 396 x 396 = 156,816 个数据点,这是 RGB 的强度。这样做将允许我们使用每个像素的 30 个质心来表示图像,并将图像的大小显著减小到 1/6。原始图像大小为 396 x 396 x 24 = 3,763,584 位;但是,新的压缩图像将是 30 x 24 + 396 x 396 x 4 = 627,984 位。巨大的差异来自于这样一个事实,我们将使用质心作为像素颜色的查找,这将把每个像素位置的大小减少到 4 位而不是 8 位。
从现在开始,我们将使用 kmeans 的sklearn
实现。这里需要注意几件事:
n_init
是运行不同质心初始化的 kmeans 的次数。最佳结果将会公布。tol
是用于宣告收敛的类内变异度量。init
的缺省值是 k-means++ ,这应该比随机初始化质心产生更好的结果。
我们可以看到原始图像和压缩图像之间的对比。压缩图像看起来接近原始图像,这意味着我们能够保留原始图像的大部分特征。使用较少的聚类数,我们会以牺牲图像质量为代价获得较高的压缩率。顺便说一下,这种图像压缩方法被称为有损数据压缩,因为我们无法从压缩图像中重建原始图像。
评估方法
与监督学习相反,在监督学习中,我们有基础事实来评估模型的性能,聚类分析没有可靠的评估度量,我们可以使用它来评估不同聚类算法的结果。此外,由于 kmeans 需要 k 作为输入,并且不从数据中学习它,所以就我们在任何问题中应该拥有的集群数量而言,没有正确的答案。有时领域知识和直觉可能会有所帮助,但通常情况并非如此。在聚类预测方法中,我们可以基于不同的 K 聚类来评估模型的性能,因为聚类用于下游建模。
在本帖中,我们将讨论两个指标,它们可能会给我们一些关于 k 的直觉:
- 肘法
- 轮廓分析
肘法
Elbow 方法给了我们一个概念,即基于数据点和它们所分配的聚类质心之间的平方距离(SSE)之和,聚类的数量应该是多少。我们在 SSE 开始变平并形成弯头的地方选择 k。我们将使用 geyser 数据集,针对不同的 k 值评估 SSE,并查看曲线可能在何处形成肘部并变平。
上图显示 k=2 是个不错的选择。有时仍然很难确定要使用的聚类的数量,因为曲线是单调递减的,可能不会显示任何弯头,或者在曲线开始变平的地方有一个明显的点。
轮廓分析
侧影分析可用于确定聚类之间的分离程度。对于每个样品:
- 计算同一聚类中所有数据点的平均距离(ai)。
- 计算最近聚类中所有数据点的平均距离(bi)。
- 计算系数:
该系数可以取区间[-1,1]内的值。
- 如果为 0 –>样本非常接近相邻的簇。
- 如果是 1 –>样本远离相邻的聚类。
- 如果是-1 –>样本被分配到错误的簇。
因此,我们希望系数尽可能大,并接近 1,以获得良好的聚类。我们将在这里再次使用间歇泉数据集,因为它运行剪影分析更便宜,实际上很明显,最有可能只有两组数据点。
如上图所示,n_clusters=2
的平均轮廓分数最好,约为 0.75,所有聚类都高于平均值,这表明它实际上是一个不错的选择。此外,轮廓图的厚度给出了每个簇有多大的指示。该图显示,聚类 1 的样本几乎是聚类 2 的两倍。然而,随着我们将n_clusters
增加到 3 和 4,平均轮廓分数分别急剧下降到 0.48 和 0.39 左右。此外,轮廓图的厚度开始出现大幅波动。底线是:好的n_clusters
将有一个远高于 0.5 的剪影平均分,以及所有的集群都高于平均分。
缺点
如果聚类具有类似球形的形状,Kmeans 算法在捕获数据结构方面是很好的。它总是试图围绕质心构造一个漂亮的球形。这意味着,当聚类具有复杂的几何形状时,kmeans 在数据聚类方面表现不佳。我们将举例说明 kmeans 表现不佳的三种情况。
首先,kmeans 算法不会让彼此远离的数据点共享同一个聚类,即使它们显然属于同一个聚类。下面是两条不同水平线上的数据点示例,说明了 kmeans 如何尝试将每条水平线上的一半数据点组合在一起。
Kmeans 认为点“B”比点“C”更接近点“A ”,因为它们具有非球形形状。因此,点‘A’和‘B’将在同一聚类中,但是点‘C’将在不同的聚类中。注意单链层次聚类方法得到了正确的结果,因为它没有分离相似的点)。
其次,我们将从具有不同均值和标准差的多元正态分布中生成数据。因此,我们将有 3 组数据,每组数据都是从不同的多元正态分布(不同的均值/标准差)中生成的。一个组的数据点将比另外两个组的总和多得多。接下来,我们将对 K=3 的数据运行 kmeans,看看它是否能够正确地对数据进行聚类。为了便于比较,我将首先根据数据来自的分布情况对数据进行着色。然后,我将绘制相同的数据,但现在根据它们被分配到的分类进行着色。
看起来 kmeans 不能正确地计算出聚类。因为它试图最小化类内的变化,所以它给予较大的类比较小的类更多的权重。换句话说,较小聚类中的数据点可以远离质心,以便更多地集中在较大的聚类上。
最后,我们将生成具有复杂几何形状的数据,例如相互重叠的月亮和圆圈,并在两个数据集上测试 kmeans。
正如所料,kmeans 无法找出两个数据集的正确聚类。然而,如果我们使用内核方法,我们可以帮助 kmeans 完美地聚类这些类型的数据集。这个想法是我们转换到更高维的表示,使数据线性分离(同样的想法,我们用在支持向量机)。不同种类的算法在诸如SpectralClustering
的场景中工作得非常好,见下文:
结论
Kmeans 聚类是最流行的聚类算法之一,通常是从业者在解决聚类任务时首先应用的,以了解数据集的结构。kmeans 的目标是将数据点分组到不同的非重叠子组中。当集群有一种球形时,它做得非常好。然而,由于团簇的几何形状偏离球形,它受到了影响。此外,它也无法从数据中获知集群的数量,并且需要预先定义。作为一名优秀的实践者,了解算法/方法背后的假设是很好的,这样你就可以很好地了解每种方法的优缺点。这将帮助您决定何时以及在何种情况下使用每种方法。在这篇文章中,我们讨论了与 kmeans 相关的优点、缺点和一些评估方法。
以下是主要的收获:
- 应用 kmeans 算法时,对数据进行缩放/标准化。
- 选择聚类数的肘方法通常不起作用,因为对于所有的 k s,误差函数是单调递减的。
- Kmeans 给予更大的集群更多的权重。
- Kmeans 采用球形的簇形状(半径等于质心和最远数据点之间的距离),当簇的形状不同时,例如椭圆形簇,Kmeans 就不能很好地工作。
- 如果聚类之间存在重叠,则 kman 没有固有的不确定性度量,因为示例属于重叠区域,无法确定为哪个聚类分配每个数据点。
- 即使数据不能被聚类,比如来自均匀分布的数据,kman 仍然可以对数据进行聚类。
创建此帖子的笔记本可以在这里找到。
原载于 2018 年 9 月 17 日imaddababura . github . io。
k-均值聚类:从 A 到 Z
关于 K-均值聚类你需要知道的一切
Picture by Radu Marcusu on Unsplash
D ata 对于数据科学来说是必不可少的(好像这个名字还不够有启发性)。由于每毫秒都会生成大量数据,因此这些数据中的大部分都没有标记也就不足为奇了。但这没关系,因为有不同的技术可以用来处理未标记的数据集。事实上,有一个完整的机器学习领域叫做“无监督学习”,处理未标记的数据。
有时我们只想看看数据是如何组织的,这就是集群发挥作用的地方。尽管它主要用于未标记的数据,但是它也适用于有标记的数据。“群集”这个词的意思是把相似的东西组合在一起。最常用的聚类方法是 K-Means(因为它很简单)。
这篇文章解释了 K-Means 聚类如何工作(深入),如何测量聚类的质量,选择最佳的 K 数,并提到了其他聚类算法。
这个概念
想象你正在开一家小书店。你有一堆不同的书和三个书架。你的目标是把相似的书放在一个书架上。你要做的是拿起 3 本书,每个书架一本,为每个书架设定一个主题。这些书现在将决定剩下的书放在哪个书架上。
每次你从书架上拿起一本新书,你会把它和前三本书进行比较,然后把这本新书放在有类似书的书架上。你可以重复这个过程,直到所有的书都放好。
完成后,你可能会注意到,改变书架的数量,为这些书架挑选不同的初始书籍(改变每个书架的主题)会增加你对书籍的分组效果。所以,你重复这个过程,希望得到更好的结果。
K-Means 算法的工作原理大概就是这样。
该算法
K-means 聚类是开始探索未标记数据集的好地方。K-Means 中的 K 表示聚类数。这个算法一定会在一些迭代之后收敛到一个解。它有 4 个基本步骤:
- 初始化群集质心(选择这 3 本书开始)
- 将数据点分配给集群(将剩余的书籍逐一放置)
- 更新群集质心(从 3 本不同的书开始)
- 重复步骤 2–3,直到满足停止条件。
您不必一开始就从 3 个集群开始,但是 2-3 个集群通常是一个很好的起点,以后再进行更新。
1.初始化 K 形心
作为起点,您告诉您的模型它应该生成多少个集群。首先,模型从数据集中选取 K 个(让 K = 3)数据点。这些数据点被称为簇形心。
现在有不同的方法来初始化质心,你可以随机选择它们,或者对数据集进行排序,将其分成 K 个部分,并从每个部分中选取一个数据点作为质心。
2.将聚类分配给数据点
从现在开始,模型自己执行计算,并为每个数据点分配一个聚类。您的模型将计算数据点和所有质心之间的距离,并将被分配给具有最近质心的簇。同样,有不同的方法可以计算这个距离;各有利弊。通常我们使用 L2 距离。
下图显示了如何计算中心体和数据点之间的 L2 距离。每次一个数据点被分配给一个集群时,都要遵循以下步骤。
L2 or Euclidean distance
3.更新质心
因为初始质心是任意选择的,所以模型会用新的聚类值更新它们。新值可能出现在数据集中,也可能不出现在数据集中,事实上,如果出现,也只是巧合。这是因为更新的聚类 centorid 是该聚类内所有数据点的平均值。
Updating cluster centroids
现在,如果使用其他算法,如 K-Mode 或 K-Median,而不是取平均值,将分别取 Mode 和 Median。
4.停止准则
由于第 2 步和第 3 步会迭代执行,如果我们不设置停止标准,它将永远继续下去。停止标准告诉我们的算法何时停止更新聚类。值得注意的是,设置一个停止标准不一定会返回最好的集群,但是为了确保它返回相当好的集群,更重要的是至少返回一些集群,我们需要有一个停止标准。
像其他事情一样,有不同的方法来设置停止标准。您甚至可以设置多个条件,如果满足这些条件,就会停止迭代并返回结果。一些停止条件是:
- 分配给特定集群的数据点保持不变(花费太多时间)
- 质心保持不变(耗时)
- 数据点距其质心的距离最小(您设置的阈值)
- 已经达到固定的迭代次数(迭代次数不足→结果不佳,明智地选择最大迭代次数)
评估集群质量
这里的目标不仅仅是制造集群,而是制造好的、有意义的集群。质量聚类是指一个聚类中的数据点靠得很近,而与其他聚类相距较远。
测量群集质量的两种方法如下所述:
- **惯性:**直觉上,惯性告诉我们一个星团内的点有多远。因此,小惯性是目标。惯性值的范围从零开始上升。
- **轮廓分数:**轮廓分数表示一个聚类中的数据点与另一个聚类中的数据点的距离。轮廓分数的范围是从-1 到 1。分数应该更接近于 1 而不是-1。
有多少个集群?
您必须指定想要创建的集群数量。有几种方法可以选择 k 的最佳值。直接的方法是绘制数据点,看看它是否能给你提示。如下图所示,创建 3 个集群似乎是个不错的选择。
K=3 seems like a good choice
另一种方法是使用惯性值。好的聚类背后的思想是具有小的惯性值和少量的聚类。
惯性值随着簇数量的增加而减小。所以,这是一个权衡。经验法则:惯性图中的肘点是一个很好的选择,因为在那之后惯性值的变化就不显著了。
K=3 is the optimal choice
命名集群
当你形成一个集群时,你给它一个名字,集群中的所有数据点都被赋予这个名字作为它们的标签。现在你的数据集有标签了!您可以使用这些标签进行测试。为了深入了解您的数据,您可以查看一个聚类中的数据点有什么相似性,以及它与其他聚类有什么不同。
将聚类分配给新的数据点
一旦您最终确定了您的模型,它现在可以将一个集群分配给一个新的数据点。分配聚类的方法保持不变,即,将其分配给质心最近的聚类。
⚠️警告!
在执行 K-Means 之前对数据进行预处理是很重要的。如果您的数据集还没有转换成数值,那么您必须将它转换成数值,以便可以执行计算。此外,应用特征约简技术将会加速该过程,并且还会改善结果。这些步骤很重要,因为 K-Means 对异常值很敏感,就像其他使用平均值的算法一样。遵循这些步骤可以缓解这些问题。
我过去常常被聚类和任何非监督算法吓倒,因为我对此知之甚少。我记得我第一次不得不使用 K-Means 来开发音乐推荐引擎时,我一直在想,如果没有标签,我该如何测试最终的模型。在这篇文章中,我试图把 K-Means 的每一个重要的东西打包,并提到了替代方法。我希望这篇文章能帮助你,如果你曾经发现自己处于我的处境。
如果你觉得这篇文章有帮助,请鼓掌👏拍手可以让更多的人看到一个帖子。🐦
数据科学新手?给这篇文章读一读!📖
如果您有任何问题或建议,请随时在下面发表。你也可以在 Linkedin 和我联系。💼
直到那时和平结束。✌
k 表示聚类:在陌生人的世界里识别出 F.R.I.E.N.D
Quickie 竞猜时间 : 是什么把某人定义为某人的朋友?你如何在混乱中认出那个人?你如何交朋友?
嗯,最常见的答案是,两个人之间必须有一些基本的协调,意见的联盟,思想的联盟和喜欢才能形成友谊的纽带。最小的差异会导致亲密和更强的牢不可破的忠诚纽带。交朋友有无数种方式,因人而异,因情况而异。
- 就是这样!!就这些了…!鉴于上述背景,你将更容易联系和理解接下来出现在银盘上的类似类比。事不宜迟,让我们直接进入今天最重要的讨论主题-【K-均值聚类】 。
我知道这听起来有点像带有 K-means 的沉重的数据科学行话?!还有聚类?!但没必要惊慌,因为这只是科学家口袋里的另一个花哨术语。所以要理解背后的直觉,我们就来“”。【分裂()】“这个术语,尽量”。描述()“每一个令牌以及随之而来的问题。
我们开始吧…?!…大声说“是”会有帮助…!!…是啊。…酷…蹬踏板!
什么是聚类?-这是一种无监督的机器学习技术,将数据分成不同的组,以便每个组内的观察结果都是相似的。这里每个组都被称为簇。
什么是无监督机器学习?-输出未知的机器学习类型。我们试图从给定的输入数据中学习关系、结构和潜在模式。
什么是 K?-是你要从数据中形成多少个聚类的数目。它的“手段”部分将在后面更详细地解释。
那么 K-means 聚类最终是什么呢?-这是一种无监督的机器学习算法,它将尝试在您的数据中将相似的聚类分组在一起。
既然我们有了基本的想法,让我们进入主题的实质。
k 均值算法;
研究表明,图形信息比文本信息更容易记忆。所以让我们用图片来学习,因为它们更好回忆!
好了,这里我们有一个散点图。假设我们有两个变量从数据集中沿 X 轴和 Y 轴绘制(在 K 均值图之前)。问题是我们能否在变量中识别出某些群体,以及我们如何去做。我们如何识别组的数量?
因此,K-means 为您所做的是,它减少了决策过程的复杂性,并允许您轻松地从数据集中识别那些数据点集群(在 K-means 图之后)。就这样,我们有三个集群(红色,蓝色,绿色)。这是一个非常简单的例子,这里我们只有两个变量,所以是二维的,但请注意,K-means 可以处理多维数据。
工作原理:
我将用简单的逐步格式来分解它。
步骤 1 :选择集群的数量 K——我们将在下一节看到如何选择最佳的集群数量。但是现在我们假设我们选择 K。它可以是任何数字(3、5 或 2 等)。
第二步:随机选择 K 个点,质心(不一定来自你的数据集)——质心就是聚类的中心点。您可以从第一个散点图中选择任意两个点,它们可以是任意随机的 X 和 Y 值,前提是您选择的质心数量等于步骤 1 中选择的聚类数量。
步骤 3 :将每个数据点分配到形成 K 聚类的最近的质心>——现在理解最近是这里的模糊术语。这取决于你测量的是哪种距离,这将由业务问题来定义。最常遵循的是欧几里德距离。当数据包含大值时,曼哈顿距离将是一个很好的选择,如果数据集充满了分类变量,则首选余弦距离。
步骤 4 :计算并放置每个聚类的新质心。——这在我们研究一个例子的时候会更加清晰。
步骤 5 :将每个数据点重新分配给新的最近质心。如果发生了任何重新分配,则转到步骤 4,否则停止,这显然是步骤 4 和 5 的迭代过程。
我知道这可能看起来有点复杂,但让我们通过一个视觉示例,以便我们在非常直观的水平上理解这一点,稍后您可以参考这些步骤来挖掘后台发生的事情。
STEP 1: Choose Number K of Clusters: K=2
这里,我们的数据集中有观察值。它们是针对两个变量绘制的,现在的第一个问题是,你能否直观地识别出我们最终将得到的最终集群。那很难,不是吗!这只是两个变量,想象一下,如果我们有三个变量和五个变量,会有什么挑战。我们无法绘制这样的五维散点图。这就是 K-means 算法出现并简化过程的原因。现在让我们看看它是如何进行。在这种情况下,我们将手动执行 K-means 聚类算法,并查看它是如何工作的。通常由 python、R 等工具完成的工作
好吧,假设我们以某种方式确定了最佳聚类数等于 2。我们将再次讨论如何进一步找到最佳集群数量,但目前我们同意只有 2 个集群。
STEP 2: Select at random K points,the centroids(not necessarily from your dataset)
在这一步,我们选择了数据集外的两个随机点,蓝色正方形和红色正方形作为我们的质心。
STEP 3: Assign each data point to the closest centroid >That forms K Cluster. (Fig.1b)
对于第 3 步,基本上我们必须检查数据集中的每个数据点,确定两个质心(蓝色或红色)中哪个最近。这一点我们将通过刷新我们的几何知识来确定。我们要做的是用直线连接这些质心,然后用垂线(用绿色虚线标出)平分这条线。绿线上的任何一点与两个质心的距离都是相等的。位于该线上方的点属于蓝色聚类质心,同样,位于该线下方的点属于红色聚类质心。为了简单起见,它们所属的簇的点将被涂上相同的颜色。在我们继续之前,我想提一下“最近”是一个模糊的术语。因为当你在散点图上想象事物时,最近的距离是非常直接的,这意味着我们所看到的距离。根据散点图,我们可以很好地得出结论,点 x 更接近集群 A,点 y 更接近集群 b。(距离度量的类型: 欧几里得 , 曼哈顿 , 余弦 等。)
STEP 4: Compute and place the new centroid of each cluster.(Fig.1a)
请记住这一点,继续进行第 4 步。想象每个数据点都有一定的权重。所以你需要找到质心,并在散点图上精确定位(用虚线方块表示)。
STEP 5: Reassign each data point to the new closest centroid. If any reassignment took place,go to STEP 4, otherwise stop.(Fig.1a)
这基本上是通过计算属于特定聚类的数据点的平均值来实现的。在我们的例子中,让我们看看蓝色的聚类点,取每个聚类点的 y 坐标和 x 坐标,分别进行平均,并绘制出平均点。
STEP 5: Reassign each data point to the new closest centroid. If any reassignment took place,go to STEP 4, otherwise stop.(Fig.1b)
太好了!现在我们进入第五步。在绘制绿线后,我们可以看到有三个点由于以前的隶属关系而被错误分类。
STEP 5: Reassign each data point to the new closest centroid. If any reassignment took place,go to STEP 4, otherwise stop.(Fig.1c)
因此,我们将移动它们,并根据聚类的质心对它们重新着色。由于重新分配了数据点,我们将返回到步骤 4。
STEP 4: Compute and place the new centroid of each cluster.(Fig. 2a)
基于重新分配,我们重新计算质心,并为每个聚类放置质心。
STEP 4: Compute and place the new centroid of each cluster.(Fig. 2b)
确定每个簇的新质心,用虚线方块表示,并在这些位置移动质心。
STEP 5: Reassign each data point to the new closest centroid. If any reassignment took place,go to STEP 4, otherwise stop.(Fig.2b)
重复步骤 5。
STEP 5: Reassign each data point to the new closest centroid. If any reassignment took place,go to STEP 4, otherwise stop.(Fig.2a)
注意绿线上方的红色数据点(见步骤 5 的图 2a)被重新分配给蓝色聚类。
STEP 4: Compute and place the new centroid of each cluster.(Fig. 3a)
重复步骤 4。正如我们所见,这是一个迭代过程。我们继续这样做,直到算法收敛。
STEP 4: Compute and place the new centroid of each cluster.(Fig. 3b)
第三次迭代的步骤 4。
STEP 5: Reassign each data point to the new closest centroid. If any reassignment took place,go to STEP 4, otherwise stop.(Fig.3a)
第五步第三次迭代。
STEP 5: Reassign each data point to the new closest centroid. If any reassignment took place,go to STEP 4, otherwise stop.(Fig.3b)
你可以再次看到等距的绿线。
HSTEP 4: Compute and place the new centroid of each cluster.(Fig. 4a)
第四次迭代的步骤 4。
STEP 4: Compute and place the new centroid of each cluster.(Fig. 5a)
在步骤 5 中,将每个数据点重新分配给新的最近质心。
STEP 5: Reassign each data point to the new closest centroid. If any reassignment took place,go to STEP 4, otherwise stop.(Fig.4a)
第五次迭代的第四步。
STEP 5: Reassign each data point to the new closest centroid. If any reassignment took place,go to STEP 4, otherwise stop.(Fig.5a)
我们非常接近我们集群的最终成员。
STEP 4: Compute and place the new centroid of each cluster.(Fig. 6a)
第六次重复步骤 4。
STEP 4: Compute and place the new centroid of each cluster.(Fig. 6b)
计算并在每个簇中放置新的质心。
STEP 5: Reassign each data point to the new closest centroid. If any reassignment took place,go to STEP 4, otherwise stop.(Fig.6a)
现在,当我们第六次运行步骤 5 时,请注意集群成员没有变化。比较步骤 5 的图 5a 和图 6a。因此,我们可以安全地得出结论,我们的 K-means 算法已经收敛,最终模型准备就绪。
Finally !!!
这是我们用 K-means 算法建议的两个聚类。希望我已经用简单的术语成功地揭开了算法的神秘面纱。
这里的 是在 Iris 数据集上尝试 K-means 聚类的实际例子。
选择最佳 K 值-
K 均值聚类的一个严重缺点是 K 值。
现在,为了便于理解,举例来说,如果在上述场景中有 2 个集群会更好,或者有 10 个集群会更好。我们需要一定的度量。我们需要一种方法来评估特定数量的群集如何比不同的群集表现得更好,并且该指标最好是可量化的。那么,我们对聚类算法施加什么样的度量,会告诉我们一些关于最终结果的信息呢?
对此的补救措施是簇内变异**。**
组内变异在数学上表示为误差平方和(WCSS/SSE)。它也被称为“肘法”。
乍一看,这个公式似乎很复杂,但实际上非常简单。根据我们的使命,化繁为简,让我们把它分解开来。
基本上我们在这里做的是…
聚类 1 中的每个数据点(聚类 1 中的 Pi),测量 Pi 数据点和聚类 1 的 C1 质心之间的差{距离(Pi,C1)}并将它们相加(大的“E”符号称为 sigma,它表示相加)
其他集群也是如此。
如果你把 K 对着上证指数作图,你会看到误差随着 K 变大而减小;这是因为当集群数量增加时,它们应该更小,因此失真也更小。
肘法的思路是选择 SSE 突然下降的 K。
这在图中产生了“肘效应”。
在这里 我已经接触了肘方法的概念和其他一些概念。
参考文献:
[## 机器学习 A-Z:数据科学中的 Python & R 实践
向两位数据科学专家学习用 Python 和 R 创建机器学习算法。包括代码模板。
www.udemy.com](https://www.udemy.com/machinelearning/) [## Python 用于数据科学和机器学习训练营
了解如何使用 NumPy、Pandas、Seaborn、Matplotlib、Plotly、Scikit-Learn、机器学习、Tensorflow 等等!
www.udemy.com](https://www.udemy.com/python-for-data-science-and-machine-learning-bootcamp) [## 统计学习导论
作为一名前数据科学家,我最常被问到的问题莫过于“学习统计学的最佳方法是什么?”?“我……
www-bcf.usc.edu](http://www-bcf.usc.edu/~gareth/ISL/)
从 1 到哈姆雷特,你有多优柔寡断?好吧,有一个巧妙的方法可以解决生活中令人烦恼的困境,我们下次再见时再看 !
阅读我发表的其他文章—
潜入 K-Means…
我们已经在上一篇 这里 完成了我们的第一个基本监督学习模型,即线性回归模型。因此,在这篇文章中,我们从最基本的无监督学习算法开始- K 均值聚类。事不宜迟,我们开始吧!
背景:
顾名思义,K-means 聚类是一种聚类算法,没有预先确定的标签,就像我们对线性回归模型一样,因此被称为无监督学习算法。
逻辑与工作:
K-means 简单地将给定数据集划分成具有不同特征的各种聚类(组)。
到底如何?
k 是指在整个数据集中定义的聚类总数。有一个为给定聚类类型选择的质心,用于计算给定数据点的距离。距离本质上表示数据点的特征与聚类类型的相似性。
我们可以以校车为例来说明这一点。如果我们有来自特定区域(集群)的许多学生(数据点)通过校车前往学校,学校声明一个中心汽车站(质心),来自附近地区的所有学生可以在此集合登上校车(集群过程)。
约束:
只能使用数值数据。一般来说,k-means 最适合二维数值数据。在 2d 或 3d 数据中可视化是可能的。但实际上,一次总有多个特征需要考虑。
因此,可以使用多维数据,但是在将数据用于 k-均值之前,必须对数据进行降维。
选择 K:
没有确切的方法来确定 K(用于划分的总聚类数)的理想值。我们必须对给定的数据集尝试不同的 K 值,并比较由此获得的结果。
为什么要用 K-means?
使用 k-means,在分析数据之后对数据进行聚类,而不是基于预定义的标签将其原始地定义在一个组下。每个质心都是本质上代表其所属聚类类型的特征的集合。因此,质心可以用来解释所形成的集群的类型。
现实生活应用:
- 客户零售细分分为不同数据分析应用的聚类,例如了解忠诚客户、分析客户的消费行为或特定类型客户的需求。
- 网络犯罪欺诈的欺诈检测。
- MP3 文件、手机是使用这种技术的一般领域。英语中大约有 40 种不同的声音。
TL;速度三角形定位法(dead reckoning)
在这里,我们执行整个机器学习过程,而不仅仅是算法实现。
注意:我们在这里从头开始实现 K-means。“scikit-learn”库,Python 中的机器学习库内置了 K-means 方法,可以直接使用。
为机器学习方法执行的步骤是:
- 数据预处理
- 数据分析
- 模型实现
k-means 算法的基本步骤:
步骤 1:从数据集中的值中选择 k 个质心的随机值(这里 k=2)
步骤 2:计算每个质心的每个点的欧几里德距离
步骤 3:比较距离并分配聚类
第四步:取平均值,重复直到误差为零
4.结果可视化
实施:
1.数据预处理
在使用现有数据之前,我们必须对其进行预处理,以获得准确的结果。预处理包括数据清洗、数据争论、特征提取、数据归约等。这些根据数据和要求而变化。
这里我们导入 numpy、pandas、matplotlib 库,分别用于数组处理、数据帧使用和数据可视化。数据被读取并存储在名为“data”的数据帧中。这里的编码被指定为“ISO-8859–1 ”,因为我们的 csv 文件是“utf-8”格式的,以便于阅读。data.head()显示整个数据集的前 5 行。
我们通过(total_rows,total_columns)格式的 data.shape 找到数据帧的大小。数据清理是为了清除空值或缺失值。为此,我们需要使用 data.isnull()知道数据中空值的数量。sum()。它在每个属性列中提供总的空值。我们可以使用“data.drop.na()”删除所有空值条目。
因为我们在这里只想使用数字数据来表示 K-means,而且属性中没有空值,所以我们可以让数据保持原样。
特征提取在数据分析部分进一步完成。
2.数据分析
我们用 data.describe()存储在“summary”变量中获得数据的摘要。我们转置它来交换行和列。summary.head()显示摘要。
可以进行数据可视化,以可视化该列中的分布,无论它是否倾斜,绘制直方图、箱线图、散点图。这里绘制了“销售额”、“订购数量”和“价格”的直方图。我们可以使用“SALES”和“QUANTITYORDERED”来根据产品的销售额和订购数量形成集群。
现在我们绘制一个散点图。“x”仅用于保存我们需要的“数据”中的 2 列,以及所有行条目。接下来,我们绘制散点图,将图形大小设置为 16x9,样式设置为 ggplot,这样就形成了一个网格。plt.scatter()用黑色圆点绘制 x 数据帧的第 0 列和第 1 列,大小为 7。
我们的初始数据看起来像这样,没有分组:
我们的数据中有异常值。离群值只是远离其他数据点的值,它们不适合我们的数据,可能会妨碍我们的准确性。
正如我们看到的,在我们的数据中有许多异常值,我们通过计算 z-score 来删除这些异常值。zscore()是 python 的 scipy 库中的内置函数。
Z score 使我们的数据正常化。在这里,我们得到的 z 得分的绝对值在-3 到 3 的范围内,所有点都存储回 x 中,所有其他行都被删除。
正如我们注意到的,x 的形状从最初的行数变化到更少的行数,因为删除的行数更少。
3.k-均值实现
因此,现在我们终于在获得最终数据后开始实际的算法实现。我们只是在这里导入复制库和其他基本库。deepcopy 用于将一个数组复制到另一个数组中。我们用它来存储质心的历史,可以用来提前计算误差。
我们定义一个函数“欧几里得”来计算两点“a”和“b”之间的距离。np.linalg.norm()是 numpy 库中的内置函数,它在这里计算 a 和 b 的欧氏距离。
接下来我们定义 main()函数。这里我们应用所有的 k 均值算法步骤。
K-Means 的第一步:选择随机质心
因此,第一步是从数据集本身选择随机质心。Numpy 具有内置函数 np.random.choice(),其参数为 x.shape[0],给出了总行数和 2 列数,即聚类数,replace 设置为 false,即 x 不被这些值替换。
我们可以打印出质心的随机值,然后我们定义所有的变量以备将来使用。我们将“total”变量定义为 x 的形状值。“ditance_1”和“distance_2”分别定义为从数据中的每个点到质心 1 和质心 2 的距离,我们用大小为 total[0]的零对其进行初始化。因此,这些是 x 中总行数的 1D 数组
“belongs_to”用于存储数据点所属的簇的值。它通过索引对应于 x 中的每个数据点。它还被初始化为零和 total[0]的大小,以便存储每个数据点的逐行的簇号(这里是-0,1 编号的簇)。“c_old”存储质心的旧值。这里它被初始化为零,并且是“形心”的形状。
“误差”用于存储当前质心和旧质心的欧几里德距离,即如果两个质心值相同,误差变为零。“mean”用于存储新的质心。因此,它是“质心”的大小,并被初始化为零。“np.zeros()”是 Numpy 中的内置函数,它通过将大小作为参数传递来将给定数组初始化为零。最后“iterator”计算执行的迭代总数。目前为零。
K-Means 的第二步:计算欧氏距离
接下来,我们执行步骤 2,计算每个质心的每个数据点的欧几里德距离。循环条件是误差不等于零,如果误差变为零,那么计算的质心与前一个相同,所以循环将在那里停止。我们打印出迭代次数,并开始 for 循环来计算欧几里得距离。
K-Means 的步骤 3:比较距离
因此,步骤 3 将这些距离相互比较,并相应地分配聚类。因此,“if”条件为第一组分配 0,为第二组分配 1。“属于”值根据每个数据点与第一个和第二个质心的距离而变化。
K 均值第 4 步:取均值,重复
最后一步现在通过分别对聚类 1 数据点和聚类 2 数据点取平均值来计算新的质心。我们使用“deepcopy”复制 c_old 中旧质心的值。for 循环一直进行到 belongs_to 的范围,为第一个聚类分配每列的平均值。“np.mean()”是用于计算平均值的内置 Numpy 函数。现在我们知道为什么我们在 Python 中如此广泛地使用 Numpy 了!😛
为了清楚起见,我在这里使用了单独的“均值”变量。我们可以替换“质心”变量并在这里重新使用它。
我们对聚类 2 的平均值进行相同的循环,其中 belongs_to()值为 1,而聚类 1 的平均值为 0。
然后,我们将平均值分配给质心,并计算旧质心和新质心的误差。迭代器加 1,条件错误检查在这里完成。如果误差为 0,则传送相同质心值的消息,然后循环停止。
4.结果可视化
最后,我们执行机器学习过程的最后一步,可视化我们的聚类点。我们使用和以前一样的情节。唯一改变的是每个簇的颜色。我们用红色‘r’和绿色‘g’来代表每个聚类。我们将“点”指定为 x 的数组,该数组位于其所属行的范围内,其中“所属行”的值为 0 或 1。我们只是将红色点(颜色[0])分散到聚类 1(属于 _ 属于[]=0),将绿色点(颜色[1])分散到聚类 2(属于 _ 属于[]=1)。我们指定星号(*)标记,用黑色标出最终质心。
最后,我们调用主函数来执行模型。
完整的代码和数据集可在这里获得。我还添加了运动员数据的另一个实现,这可以使数据清理部分变得清晰,因为我们删除了那里的重复值和空值。
输出:
我得到的输出如下:
注意:这里的输出可能会有所不同,因为我们最初是随机选择质心的。这里仅执行 2 次迭代,直到误差变为零。
聚类:
绘制散点图时考虑最终迭代质心和聚类。
对于任何疑问或评论,请在下面评论,让我知道你是否喜欢这个博客!;)
k-均值聚类—机器学习算法简介
最简单的聚类算法—代码和解释
简介—无监督学习
在机器学习中,我们并不总是被提供一个目标来优化,我们也不总是被提供一个目标标签来对输入数据点进行分类。在人工智能领域中,没有目标或标签可供我们分类的问题被称为无监督学习问题。在无监督学习问题中,我们试图对数据中存在的潜在结构化信息进行建模。聚类是一种无监督学习问题,我们试图根据相似数据的底层结构将它们分组到群组/聚类中。K-means 算法是一种广泛使用的著名聚类算法。k 代表我们要将数据点分类到的聚类数。
K-Means 伪代码
## K-Means Clustering 1\. Choose the number of clusters(K) and obtain the data points
2\. Place the centroids c_1, c_2, ..... c_k randomly
3\. Repeat steps 4 and 5 until convergence or until the end of a fixed number of iterations
4\. for each data point x_i:
- find the nearest centroid(c_1, c_2 .. c_k)
- assign the point to that cluster
5\. for each cluster j = 1..k
- new centroid = mean of all points assigned to that cluster
6\. End
下面的模拟将提供对 K-means 算法的更好理解。
K — Means Algorithm
怎么选 K??
在某些情况下,我们不知道集群的数量。那么,我们如何选择 K 的值呢???有一种方法叫肘法。在这种方法中,选择不同数量的簇,并开始绘制簇内到质心的距离。图表如下所示。
Elbow method
从上图中我们可以推断出,在 k=4 时,该图达到最佳最小值。即使类内距离在 4 之后减少,我们也会做更多的计算。这类似于收益递减定律。因此,我们选择值 4 作为聚类的最佳数量。之所以称之为肘关节法,是因为最佳聚类数代表一个肘关节!
K-均值聚类算法的应用
- 行为细分
- 异常检测
- 社会网络分析
- 市场细分
只有几个应用聚类算法(如 K-means)的例子。
让我们写一些代码
我们将使用虹膜数据集来构建我们的算法。即使虹膜数据集有标签,我们也将丢弃它们,只使用特征点对数据进行聚类。我们知道有 3 个聚类(“鸢尾-海滨鸢尾”、“鸢尾-刚毛鸢尾”、“鸢尾-杂色”)。因此,在我们的例子中 k=3。
我们加载数据集并删除目标值。我们将特征点转换成一个 numpy 数组,并将其分成训练和测试数据。
我们实现了上面显示的伪代码,我们可以发现我们的算法在 6 次迭代后收敛。我们现在可以输入一个测试数据点,找到它最接近的质心,并将该点分配给相应的聚类。
Scikit-learn 库通过提供一个我们可以用来实现算法的抽象层次对象,再一次使我们免于编写这么多行代码。
结论
K-means 是聚类技术的入门算法,也是最简单的算法。你可能已经注意到了,这里没有目标/损失函数。因此,不需要偏导数,并且消除了复杂的数学运算。K-means 是一种易于实现的简便算法。
参考
具体话题经验:新手职业经验:无行业经验机器知识…
www.datascience.com](https://www.datascience.com/blog/k-means-clustering)
k-means 聚类:MATLAB、R 和 Python 代码——你所要做的只是准备数据集(非常简单、容易和实用)
我发布 k-means 聚类的 MATLAB,R 和 Python 代码。它们非常容易使用。你准备数据集,然后运行代码!然后,可以执行 AP 聚类。非常简单容易!
你可以从下面的网址购买每一个代码。
矩阵实验室
https://gum.co/Lowcz
请从下面的网址下载补充压缩文件(这是免费的)来运行 k-means 代码。
http://univproblog . html . xdomain . jp/code/MATLAB _ scripts _ functions . zip
稀有
https://gum.co/YdBm
请从下面的网址下载补充压缩文件(这是免费的)来运行 k-means 代码。
http://univproblog . html . xdomain . jp/code/R _ scripts _ functions . zip
计算机编程语言
https://gum.co/EYGPR
请从下面的网址下载补充压缩文件(这是免费的)来运行 k-means 代码。
http://univprovblog . html . xdomain . jp/code/supporting functions . zip
k-means 在 MATLAB 中的程序,R 和 Python 代码
为了执行适当的 k-means,加载数据集后,MATLAB、R 和 Python 代码遵循以下程序。
1。决定集群的数量
2。自动缩放解释变量(X)(如有必要)
自动缩放意味着居中和缩放。通过从居中的变量中减去每个变量的平均值,每个变量的平均值变为零。通过将每个变量的标准偏差除以换算中的变量,每个变量的标准偏差变为 1。
3。运行 k-means
4。可视化聚类结果
例如通过 PCA 进行数据可视化。通过改变散点图中不同聚类的颜色,可以很容易地看到聚类。
如何进行 k-means?
1.购买代码并解压文件
MATLAB:https://gum.co/Lowcz
蟒蛇:【https://gum.co/EYGPR】T2
2.下载并解压缩补充 zip 文件(这是免费的)
MATLAB:http://univprovblog . html . xdomain . jp/code/MATLAB _ scripts _ functions . zip
R:http://univprovblog . html . xdomain . jp/code/R _ scripts _ functions . zip
Python:http://univprovblog . html . xdomain . jp/code/supporting functions . zip
3.将补充文件放在与 k-means 代码相同的目录或文件夹中。
4.准备数据集。有关数据格式,请参见下面的文章。
5.运行代码!
每个样本的聚类数保存在“ClusterNum.csv”中。
必需的设置
执行结果的示例
葡萄酒数据的 k-均值聚类
我们在这篇文章中要分析的数据集是对意大利某个特定地区的葡萄酒进行化学分析的结果,这些葡萄酒来自三个不同的品种。这项分析确定了三种葡萄酒中 13 种成分的含量。属性有:酒精、苹果酸、灰分、灰分的碱度、镁、总酚、类黄酮、非类黄酮酚、原花青素、颜色强度、色调、稀释酒的 OD280/OD315、和脯氨酸。数据集有 178 个观察值,没有缺失值。可以在这里下载。
我们的目标是尝试将相似的观察结果分组在一起,并确定可能的聚类数(可能不是 3)。这将有助于我们进行预测并降低维数。第一步是将数据集分成训练集(2/3)和测试集(1/3)。包 caTools 中的函数 sample.split 做得很好,它在训练集和测试集中处理了 3 个品种大致相同的分布。
下面是数据集的摘要。注意到这些属性不在同一个尺度上是非常重要的;因此,我们稍后将缩放数据。
让我们确定将要使用的集群数量。根据肘方法,我们可以使用 3 个集群,因为从这一点开始,总 WCSS ( 在集群平方和内)不会显著降低。
原始数据和欧几里德距离
首先,我们要处理原始的、未经处理的、未经润色的数据。这不是最好的方法,但我们对结果感兴趣。我们用 100 种不同的种子创建了一个包含 100 种可能的聚类方式的列表(名为 L1)。这考虑到了再现性。在这 100 个结果中,我们选择具有最小总 WCSS 的结果,并且在这些结果中,我们选择 L1[[3]],因为原始类名“1”、“2”、“3”匹配聚类类名“1”、“2”、“3”。这不是必须的,但是解释结果更容易。
我们看到,该算法在训练集上表现不错(准确率为 70.3%),但在测试集上表现更好,准确率为 73.3%(这一点更重要,因为我们更喜欢在之前尚未“看到”的数据上测试该算法)。我们希望将这些结果可视化——“抖动”图可能是个好主意。
我们注意到 SSE 相当高,因为我们处理的是未缩放的数据。这就是为什么我们可能看不到抖动图上的所有数据。
原始数据和曼哈顿距离
这次我们用的是 k-means 算法中的曼哈顿距离,在不同维度没有可比性的情况下可能更有用。下面是原始数据的结果—我们选择了具有最小总 WCSS 的聚类。
训练集的准确率为 83/118 = 70.3%,测试集的准确率为 44/60 = 73.3%。下面给出了训练集和测试集的抖动图。
缩放数据和欧几里德距离
接下来,让我们看看缩放后的数据会发生什么。请注意,测试集是用用于缩放训练集的相同参数来缩放的。我们得到了以下结果:
显然,与未缩放的数据相比,精确度有所提高。对于训练集,准确率为 110/118 = 93.2%,对于测试集,准确率为 58/60 = 96.7%。但是我们需要小心——太接近 100%并不总是好的,因为我们可能会有过度拟合的问题。
训练集和测试集的抖动图如下所示:
缩放数据和曼哈顿距离
对于缩放数据和曼哈顿距离,最佳聚类是:
我们注意到,与使用欧几里德距离对缩放数据进行聚类相比,测试集上的聚类没有改进,但在训练集上有所改进。现在,训练集的准确率为 112/118 = 94.5%,测试集的准确率为 58/60 = 96.7%。抖动曲线如下所示。
主成分分析
主成分分析在这一点上可能会有所帮助。我们的目标是提取预测变量的线性组合,解释数据中最大的方差。函数 prcomp 用于进行分析,以下是结果汇总。
如果我们观察累积比例,我们会发现前两个主成分解释了数据中 60.9%的方差,而前三个主成分解释了数据中大约 69.6%的方差。下面的 scree 图显示了方差的衰减。
我们决定保留前两个主成分,因为我们将能够看到结果。训练数据包含矩阵 A1$x 的前两个 PC,但是测试数据应该使用相同的变换进行变换。运行 k-means 算法后,我们发现最佳聚类如下:
训练数据的准确率为 112/118 = 94.9%,测试数据的准确率为 57/60 = 95%。测试数据的准确性仅比 PCA 之前的缩放测试数据的准确性差 1.7%,但是我们显著降低了维度(从 13 个变量减少到仅 2 个变量)。下面给出了训练和测试数据的抖动图。
包 clusterSim 中的函数 clusplot 允许我们显示聚类:
聚类的问题发生在交叉区域——这是我们得到错误分类的数据点的地方。成对图也有助于了解前两台 PC 在群集时的表现。第一台电脑本身做得很好(我们通过观察行/列 PC1 可以看出这一点),第二台电脑稍差一些。其他的很糟糕,因为颜色混在一起了。前两台电脑(位于交叉点)在集群时表现出色。
前三个 PC 甚至更高效,来自包散点图 3d 的函数散点图 3d 表明这确实是真的:
独立成分分析
与 PCA 不同,ICA 的目标是产生 13 个统计上独立的成分,没有特定的顺序,然后使用这些成分对数据进行聚类。我们使用来自包脱字符的函数预处理来转换训练数据,并且相同的转换已经被应用到测试数据。我们在下面看到,当对数据进行聚类时,组件 ICA6 做得很好,而其他 12 个组件单独地不能很好地对数据进行聚类。
下面是第六个独立成分与自身的对比图——事实上,它可以非常准确地分离数据。
k-means 算法还需要一个组件——如果我们仔细观察获得的成对图,我们可以看到组件 6 和 8 可以保留用于聚类。下面是聚类的结果。
对于训练集,聚类准确率为 91/118 = 77.1%,对于测试集,聚类准确率为 46/60 = 76.7%。精度尚可,但维度从 13 降到只有 2!下面给出了训练集和测试集的抖动图。
我们的结果总结
下表提供了关于所获得的聚类结果的结论。
PCA 做的最好!它在测试集上的表现比缩放数据稍差,但维度已经减少。
完整的 R 代码,请访问我的 GitHub 简介这里。
k-均值数据聚类
在当今世界,随着互联网使用的增加,产生的数据量惊人地庞大。即使单个数据的性质很简单,但要处理的数据量之大,甚至连计算机都难以处理。
我们需要大数据分析工具来处理这样的流程。数据挖掘算法和技术以及机器学习为我们提供了以可理解的方式解释大数据的方法。k-means 是一种数据聚类算法,可用于无监督的机器学习。它能够将相似的未标记数据分组到预定数量的簇(k)中。需要注意的是,我们需要事先知道数据中的自然聚类数,尽管可以对代码进行轻微的修改,以计算为代价找到最优的聚类数。
Source: https://i.stack.imgur.com/cIDB3.png
K-means 聚类问题可以正式表述为*“给定一个整数 k 和 R^d 中的一组 n 个数据点,目标是选择 k 个中心,以最小化每个数据点与其最近中心之间的总平方距离”*。精确地解决这个问题是 NP 难的,但是有算法可以局部搜索它的解。标准算法是由 Stuart Lloyd 在 1957 年首先提出的,它依赖于迭代改进。
首先,必须确定聚类中心的初始集合。这可以随机分配。但是这不能保证准确性。这可以在 python 中完成,如下所示:
#datapoints is a 2D array initialized with the points to be clustered
centroids = []
for i in range(1,k+1):
uniqueNumber = False
while(uniqueNumber==False):
a = randint(0, len(dataPoints)-1)
if (dataPoints[a] not in centroids):
uniqueNumber = True
centroids.append(dataPoints[a])
那么算法通过在两个步骤之间交替进行。
步骤 1: (分配步骤)将每个数据点分配给根据欧几里德距离具有最接近该数据点的中心的聚类。
步骤 2: (更新步骤)使用每个聚类的所有成员重新计算每个聚类的质心。
保证每个点与其最近的中心之间的总平方距离单调递减,以便配置不会重复。此外,由于只有 k^n 可能的集群,该过程将总是终止。由于该算法是局部搜索,不能保证全局最优解,初始种子在很大程度上影响结果。取决于初始种子的质量,聚类可能是任意差的。有一些选择初始种子的方法可以增加找到全局最优解的概率。
选择初始中心后,数据点可以聚类为:
closestCluster = [0,euclidean_distance(point,centroids[0])]
for i in range(1,k):
dist = euclidean_distance(point,centroids[i])
if (dist<closestCluster[1]):
closestCluster=[i,dist] clusters[closestCluster[0]].append(point)
在第一次聚类之后,使用如下聚类来找到新的质心:
#np is numpy
newCentroids = []
for i in range(k):
newCentroids.append(np.mean(clusters[i],axis=0).tolist())
然后,我们比较以前的聚类中心和新的质心,如果有任何变化,我们回到分配步骤。如果质心没有变化,我们就终止循环。
请务必访问我的回购在https://github.com/niruhan/k-means-clustering的完整代码。标准算法有许多改进,有望提高性能。有些是 k-means++,k-means#。此外,标准算法是一个批处理算法,这意味着我们应该在开始处理之前拥有所有的数据点。但实际上,数据是以流的形式到达处理引擎的,需要进行实时分析。k-means 算法有在线版本,可以对流数据集进行聚类。顺序 k-means 是一种标准算法。还有小批量 k-means,以及使用衰减率处理非平稳数据的方法。
参考文献:
- “k-means ++小心播种的好处”——大卫·亚瑟和谢尔盖·瓦西里维茨基
- “k 均值聚类”在 https://en.wikipedia.org/wiki/K-means_clustering
K-Means++在 Python 和 Spark 中的实现
对于本教程,我们将使用 PySpark,Apache Spark 的 Python 包装器。虽然 PySpark 有一个很好的 K-Means++实现,但我们将从头开始编写自己的实现。
配置 PySpark 笔记本
如果你在 Jupyter 笔记本上没有 PySpark,我觉得这个教程很有用:
[## 3 分钟内开始使用 PySpark 和 Jupyter 笔记本
Apache Spark 是大数据爱好者的必备品。简而言之,Spark 是一个快速而强大的框架,它提供了一个…
blog.sicara.com](https://blog.sicara.com/get-started-pyspark-jupyter-guide-tutorial-ae2fe84f594f)
将数据集作为 RDD 加载
开始前,请确保您可以访问气象站数据集:
https://github . com/yoavfreund/UCSD _ BigData _ 2016/tree/master/Data/Weather
**def** parse_data(row):
*'''*
*Parse each pandas row into a tuple of
(station_name, feature_vec),`l*
*where feature_vec is the concatenation of the projection vectors*
*of TAVG, TRANGE, and SNWD.*
*'''*
**return** (row[0],
np.concatenate([row[1], row[2], row[3]]))*## Read data*
data = pickle.load(open("stations_projections.pickle", "rb"))
rdd = sc.parallelize([parse_data(row[1])
**for** row **in** data.iterrows()])
让我们看看第一行:
rdd.take(1)
气象站的名称是 USC00044534 ,其余的是我们将用于聚类的不同天气信息。
导入库
**import** numpy as np
**import** pickle
**import** sys
**import** time
**from** numpy.linalg **import** norm
**from** matplotlib **import** pyplot **as** plt
定义全局参数
*# Number of centroids* K = 5 *# Number of K-means runs that are executed in parallel. Equivalently, number of sets of initial points* RUNS = 25 # For reproducability of results
RANDOM_SEED = 60295531 *# The K-means algorithm is terminated when the change in the
# location of the centroids is smaller than 0.1* converge_dist = 0.1
效用函数
随着我们的发展,以下功能将会派上用场:
**def** print_log(s):
'''
Print progress logs
'''
sys.stdout.write(s + "**\n**")
sys.stdout.flush() **def** compute_entropy(d):
*'''*
*Compute the entropy given the frequency vector `d`*
*'''*
d = np.array(d)
d = 1.0 * d / d.sum()
**return** -np.sum(d * np.log2(d))
**def** choice(p):
*'''*
*Generates a random sample from [0, len(p)),*
*where p[i] is the probability associated with i.*
*'''*
random = np.random.random()
r = 0.0
**for** idx **in** range(len(p)):
r = r + p[idx]
**if** r > random:
return idx
assert(False)
质心的初始化
对于 K-Means++来说,我们希望在初始化时质心尽可能的分开。这个想法是让质心在初始化时更接近不同的聚类中心,从而更快地达到收敛。
**def** kmeans_init(rdd, K, RUNS, seed):
'''
Select `RUNS` sets of initial points for `K`-means++
'''
# the `centers` variable is what we want to return
n_data = rdd.count()
shape = rdd.take(1)[0][1].shape[0]
centers = np.zeros((RUNS, K, shape)) **def** update_dist(vec, dist, k):
new_dist = norm(vec - centers[:, k], axis=1)**2
**return** np.min([dist, new_dist], axis=0) # The second element `dist` in the tuple below is the
# closest distance from each data point to the selected
# points in the initial set, where `dist[i]` is the
# closest distance to the points in the i-th initial set
data = (rdd
.map(**lambda** p: (p, [np.inf] * RUNS)) \
.cache()) # Collect the feature vectors of all data points
# beforehand, might be useful in the following
# for-loop
local_data = (rdd
.map(**lambda** (name, vec): vec)
.collect()) # Randomly select the first point for every run of
# k-means++, i.e. randomly select `RUNS` points
# and add it to the `centers` variable
sample = [local_data[k] **for** k **in**
np.random.randint(0, len(local_data), RUNS)]
centers[:, 0] = sample **for** idx **in** range(K - 1):
########################################################
# In each iteration, you need to select one point for
# each set of initial points (so select `RUNS` points
# in total). For each data point x, let D_i(x) be the
# distance between x and the nearest center that has
# already been added to the i-th set. Choose a new
# data point for i-th set using a weighted probability
# where point x is chosen with probability proportional
# to D_i(x)^2 . Repeat each data point by 25 times
# (for each RUN) to get 12140x25
######################################################## #Update distance
data = (data
.map(**lambda** ((name,vec),dist):
((name,vec),update_dist(vec,dist,idx)))
.cache()) #Calculate sum of D_i(x)^2
d1 = data.map(**lambda** ((name,vec),dist): (1,dist))
d2 = d1.reduceByKey(**lambda** x,y: np.sum([x,y], axis=0))
total = d2.collect()[0][1] #Normalize each distance to get the probabilities and
#reshapte to 12140x25
prob = (data
.map(**lambda** ((name,vec),dist):
np.divide(dist,total))
.collect())
prob = np.reshape(prob,(len(local_data), RUNS)) #K'th centroid for each run
data_id = [choice(prob[:,i]) **for** i **in** xrange(RUNS)]
sample = [local_data[i] **for** i **in** data_id]
centers[:, idx+1] = sample **return** centers # The second element `dist` in the tuple below is the
# closest distance from each data point to the selected
# points in the initial set, where `dist[i]` is the
# closest distance to the points in the i-th initial set
data = (rdd
.map(**lambda** p: (p, [np.inf] * RUNS)) \
.cache()) # Collect the feature vectors of all data points
# beforehand, might be useful in the following
# for-loop
local_data = (rdd
.map(**lambda** (name, vec): vec)
.collect()) # Randomly select the first point for every run of
# k-means++, i.e. randomly select `RUNS` points
# and add it to the `centers` variable
sample = [local_data[k] **for** k **in** np.random.randint(0, len(local_data), RUNS)]
centers[:, 0] = sample **for** idx **in** range(K - 1):
########################################################
# In each iteration, you need to select one point for
# each set of initial points (so select `RUNS` points
# in total). For each data point x, let D_i(x) be the
# distance between x and the nearest center that has
# already been added to the i-th set. Choose a new
# data point for i-th set using a weighted probability
# where point x is chosen with probability proportional
# to D_i(x)^2 . Repeat each data point by 25 times
# (for each RUN) to get 12140x25
######################################################## #Update distance
data = (data
.map(**lambda** ((name,vec),dist):
((name,vec),update_dist(vec,dist,idx)))
.cache()) #Calculate sum of D_i(x)^2
d1 = data.map(**lambda** ((name,vec),dist): (1,dist))
d2 = d1.reduceByKey(lambda x,y: np.sum([x,y], axis=0))
total = d2.collect()[0][1] #Normalize each distance to get the probabilities and
# reshape to 12140x25
prob = (data
.map(**lambda** ((name,vec),dist):
np.divide(dist,total))
.collect())
prob = np.reshape(prob,(len(local_data), RUNS)) #K'th centroid for each run
data_id = [choice(prob[:,i]) **for** i **in** xrange(RUNS)]
sample = [local_data[i] **for** i **in** data_id]
centers[:, idx+1] = sample **return** centers
K-Means++实现
现在我们有了初始化函数,我们可以用它来实现 K-Means++算法。
**def** get_closest(p, centers):
*'''*
*Return the indices the nearest centroids of `p`.*
*`centers` contains sets of centroids, where `centers[i]` is*
*the i-th set of centroids.*
*'''*
best = [0] * len(centers)
closest = [np.inf] * len(centers)
**for** idx **in** range(len(centers)):
**for** j **in** range(len(centers[0])):
temp_dist = norm(p - centers[idx][j])
**if** temp_dist < closest[idx]:
closest[idx] = temp_dist
best[idx] = j
**return** best
**def** kmeans(rdd, K, RUNS, converge_dist, seed):
*'''*
*Run K-means++ algorithm on `rdd`, where `RUNS` is the number of*
*initial sets to use.*
*'''*
k_points = kmeans_init(rdd, K, RUNS, seed)
print_log("Initialized.")
temp_dist = 1.0
iters = 0
st = time.time() **while** temp_dist > converge_dist:
*# Update all `RUNS` sets of centroids using standard k-means
# algorithm*
*# Outline:*
*# - For each point x, select its nearest centroid in i-th
# centroids set*
*# - Average all points that are assigned to the same
# centroid*
*# - Update the centroid with the average of all points
# that are assigned to it*
temp_dist = np.max([
np.sum([norm(k_points[idx][j] - new_points[(idx,
j)]) **for** idx,j **in** new_points.keys()])
])
iters = iters + 1
**if** iters % 5 == 0:
print_log("Iteration **%d** max shift: **%.2f** (time: **%.2f**)" %
(iters, temp_dist, time.time() - st))
st = time.time()
*# update old centroids*
*# You modify this for-loop to meet your need*
**for** ((idx, j), p) **in** new_points.items():
k_points[idx][j] = p
**return** k_points
基准测试
K-Means++优于 K-Means 之处在于它的初始化算法带来的收敛速度。此外,Spark 被用来尽可能地并行化这个算法。因此,让我们对这个实现进行基准测试。
st = time.time()
np.random.seed(RANDOM_SEED)
centroids = kmeans(rdd, K, RUNS, converge_dist,
np.random.randint(1000))
group = rdd.mapValues(**lambda** p: get_closest(p, centroids)) \
.collect()
**print** "Time takes to converge:", time.time() - st
根据处理器内核的数量、为每个执行器设置的内核内存以及使用的执行器数量,这个结果会有所不同。
价值函数
为了验证模型的准确性,我们需要选择一个成本函数,并尝试使用该模型将其最小化。最终的成本函数会给我们一个准确性的概念。对于 K-Means,我们查看数据点和最近的质心之间的距离。
**def** get_cost(rdd, centers):
*'''*
*Compute the square of l2 norm from each data point in `rdd`*
*to the centroids in `centers`*
*'''*
**def** _get_cost(p, centers):
best = [0] * len(centers)
closest = [np.inf] * len(centers)
**for** idx **in** range(len(centers)):
**for** j **in** range(len(centers[0])):
temp_dist = norm(p - centers[idx][j])
**if** temp_dist < closest[idx]:
closest[idx] = temp_dist
best[idx] = j
**return** np.array(closest)**2
cost = rdd.map(**lambda** (name, v): _get_cost(v,
centroids)).collect()
**return** np.array(cost).sum(axis=0)
cost = get_cost(rdd, centroids)
log2 = np.log2**print** "Min Cost:\t"+str(log2(np.max(cost)))
**print** "Max Cost:\t"+str(log2(np.min(cost)))
**print** "Mean Cost:\t"+str(log2(np.mean(cost)))
最小成本:33.7575332525
最大成本:33.8254902123
平均成本:33.2533332335
决赛成绩
以下是最终结果:
**print** 'entropy=',entropybest = np.argmin(cost)
**print** 'best_centers=',list(centroids[best])
现实生活中的 K-Means:聚类锻炼时段
K -means 聚类是一种非常流行的无监督学习算法。在这篇文章中,我想提供一些关于它的背景知识,并展示我们如何在真实生活中使用它。
K 均值聚类是一种算法,给定一个数据集,它将识别哪些数据点属于 k 个聚类中的每一个。它获取你的数据,并学习如何对其进行分组。
通过一系列迭代,该算法创建多组数据点(称为聚类),这些数据点具有相似的方差,并最小化特定的成本函数:类内平方和。
Within-Cluster Sum of Squares: where C_i is a cluster and “mu_i” is the mean of the data points in cluster C_i
通过使用组内平方和作为成本函数,相同组中的数据点将彼此相似,而不同组中的数据点将具有较低水平的相似性。
K-Means 聚类是一组名为 无监督学习 的学习算法的一部分。在这种类型的学习模型中,没有对每个数据点的标签/类/类别的明确标识。
数据集中的每个数据点都是一个属性向量,也就是说,没有特定标注的要素可以将其分配给特定的聚类或类。然后,该算法将自行学习如何对具有相似特征的数据点进行分组,并将它们聚集在一起。
关于 K-Means 聚类的一个重要细节是,即使它确定哪个数据点应该属于哪个聚类,您也必须指定参数 *K,*来表示您想要用来“分布”您的数据的聚类总数。
你最喜欢的锻炼是慢跑,因为你非常喜欢数据,所以你要确保记录你的表现。所以你最终会编译一个类似这样的数据集
它包括您慢跑的日期、总跑步距离(公里)、持续时间(分钟)和自上次锻炼以来的天数。数据集中的每一行都包含每个健身程序的属性或功能。
最终,你想要回答的问题是:“我如何识别相似的锻炼时段?”
通过识别彼此相似的锻炼时段,您可以更好地了解自己的整体表现,并获得如何改进的新想法。
像 K-Means 聚类这样的聚类算法可以帮助您将数据分组到不同的组中,保证每个组中的数据点彼此相似。
数据科学和分析的一个良好实践是,在进行任何分析之前,首先要对数据集有很好的理解。
对数据集进行探索性观察,首先绘制一个对图,以便更好地了解不同特征之间的相关性。
对角线上的图对应于每个特征的分布,而其他图是每对特征的散点图。
一个有趣的图是距离对持续时间,它显示了线性相关性。
然而,当我们将距离和持续时间与自上次锻炼以来的天数进行比较时,它们之间没有明显的相关性。
现在你已经对你的数据集如何看起来像有了一个很好的想法,是时候使用 K-Means 并查看单个会话是如何分组的。你可以从把你的数据集分成两个不同的组开始。
在该图中,与 pair 图一样,我们看到了距离和锻炼持续时间之间的关系,但现在每个数据点都有其聚类的颜色。
快速浏览一下这个散点图,我们可以看到,例如,所有 25 分钟以下的锻炼都在一个簇中。
我们如何知道使用哪个 K 值?
根据数据集和您正在解决的问题,您可能知道如何对数据进行聚类。也许你想看到数据分成 3 组,5 组,10 组…
如果不是这样,我们如何确定使用哪个 K 值呢?
像算法中的任何参数一样,它需要一些实验,即调整。
为了试验不同的 K 值,您还需要一个决定因素或度量,您将使用它来决定哪个 K 值提供最佳结果。
上图是对健身数据集运行 K 均值聚类的结果,K 值介于 2 和 43 之间,对应于数据集的大小。K 的每个值与各自的失真值相对应。
y 轴上的失真对应于我们的成本函数:每个数据点和质心(即聚类中心)之间的平方差之和。
随着 K 的增加,相应的失真值将趋于零,因为最终每个聚类只有一个数据点。由于每个聚类中只有一个数据点,质心就是数据点本身,因此失真将等于零。
对于该数据集,曲线的弯头大约为 K= 5。对于大于 5 的 K 值,失真值开始稳定衰减。
回到原始数据集,用新找到的 K 重新运行 K-Means,就可以把数据聚类成 5 个不同的组!
至此,K-Means 聚类的工作已经完成,您的数据分析工作开始了😀🤓
下一步需要人工干预,以便解释结果并获得额外的洞察力。
简单回顾一下,这些是使用 K-Means 的优势:
- 易于实施
- 相对快速和高效
- 只有一个参数需要调整,您可以很容易地看到调整参数 K 值的直接影响
感谢阅读!
R 中的 k-最近邻算法及实例(简单解释 knn)
在这篇文章中,我将举例说明什么是 k-最近邻算法,以及它如何帮助我们。但是在我们继续之前,我们意识到我的目标受众是那些希望对概念有直观理解而不是非常深入理解的人,这就是为什么我避免对这个话题过于迂腐,对理论概念关注较少。让我们开始吧。
假设我们有一定数量的物体,每个物体都有自己独特的属性,例如,你有 5 把椅子,10 张床和 15 张桌子,我们知道每个物体的长度、宽度和高度。现在,如果有人给我们一个具有新属性的新对象,并要求我们预测该新对象属于哪个类别,这意味着我们获得了维度,并要求我们预测它是椅子、床还是桌子,那么我们必须使用 knn 算法来确定这一点。
因此,属性意味着每个对象的属性,每个对象可以被认为是一个类别。我们的工作是检查新对象的属性与任何一个已知类别的关系有多密切。现在,我将向你们展示多种场景,并尽可能简单地解释这些场景。
当我们得到属性时,我们试着把它们画在图上。这些属性的图形表示将帮助我们计算新值和已知值之间的欧几里德距离。通过这样做,我们可以确定新对象最接近哪个类别。
欧几里得距离
不要被这个名字吓倒,它只是简单地表示平面上两点之间的距离。通过简单地使用这个公式,你可以计算两点之间的距离,不管你有多少属性,比如高度,宽度,宽度,重量等等,直到 n,其中 n 可以是你拥有的物体的最后一个属性。公式为√( x2 x1)+(y2 y1)+(z2 Z1)……(N2-n1)
两类一属性(1D)
我们分为男性和女性两类,下表给出了他们各自的身高。然后,如果出现一名新成员,并要求您在已知他/她的身高的情况下确定他/她的性别,那么您可以在 1D 平面上绘制该身高,并检查该新身高与其他已绘制身高的接近度。理想情况下,我们将计算该图上的欧几里德距离,以确定新成员高度的最近高度。我们看到,如果我们绘制 180 厘米的身高图,它更接近男性身高,而不是女性身高。这就是我们如何确定它是一个男性。(a)显示表格(b)显示图表上的表示©显示新成员的引入(d)显示男性的预测值。
两类两属性(2D)
假设我们提出一个名为 weight 的新属性,它也可以描述男性和女性的特征,如下表所示。现在我们创建一个 2D 平面,并按照同样的程序计算新物体与旧物体的距离,它越接近其中一个类别,就被认为是它自己的类别。在下面的例子中,我们可以看到身高 169cm、体重 68kg 的新成员与女性的亲密度高于男性。因此,我们预测新成员是女性。
两个类别和两个以上属性(> 3D)
大多数情况下,你会有很多与你的分类对象相关的属性,它们不能简单地画在白板上的 2D 或 1D 平面上。然而,只要你理解了它的功能,你就可以开始了。假设你有 5 个属性,即。性别、身高、体重、颜色、头发长度和音调,然后你只需使用上述欧几里德公式来计算新出现的物体与已有物体的距离。取(sex 1-sex 2)+(height 1-height 2)+(weight 1—weight 2)+(color 1—color 2)+(hair _ length 1—hair _ length 2)+(voice _ pitch 1)—(voice _ pitch 2)的平方根,其中 1 表示已经绘制的数据点,2 表示要确定其类别的新数据点。请记住,上面的这个公式将用于每一个可用的数据点,也就是说,只要数据集中有多少行,它就会运行多少次。
R 中的示例
在我们继续在 R 中实现它们之前,请注意以下几点:
1-您要检查的最近邻将被称为由值“k”定义。如果 k 是 5,那么您将检查 5 个最近的邻居以确定类别。如果大多数邻居属于这五个最近邻居中的某个类别,那么它将被选为即将到来的对象的类别。如下图所示。
2-不同的变量有不同的比例单位,如体重以千克为单位,身高以厘米为单位。那我们如何在欧几里德公式中使用它们呢?我们用公式(x-min(x))/(min(x)-max(x))对每个变量进行归一化,在下面的例子中也会看到。现在,如果你有一个 200 公斤的变量和一个 50 公斤的变量,归一化后,两者都将由 0 和 1 之间的值表示。假设您已经创建了一个只能容纳 0 到 1 范围内的内容的盒子,但是因为您已经使用了规范化公式将所有内容转换为 0 到 1 之间的值,所以您可以很好地使用这个盒子。注意:那个方框是你的图。
knn 算法适用于数值变量,这并不是说它不能适用于分类变量,只是如果你混合了分类变量和数值变量作为预测变量,那么它需要一点点不同的方法。但是如果所有的预测值都是数字,那么 knn 是最好的,因为我们处理的是距离,因此我们需要硬数字。
4-当我们将数据分成训练集和测试集时,数据应该已经被规范化了。这意味着我们首先将数据标准化,然后将其拆分。
knn 算法不适用于 R 中的有序因子,而是适用于因子。我们将在下面的代码中看到这一点。
6-K-均值算法不同于 K-最近邻算法。K-mean 用于聚类,是一种非监督学习算法,而 Knn 是一种监督学习算法,用于处理分类问题。
df <- data(iris) ##load data
head(iris) ## see the studcture## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa##Generate a random number that is 90% of the total number of rows in dataset.
ran <- sample(1:nrow(iris), 0.9 * nrow(iris))
##the normalization function is created
nor <-function(x) { (x -min(x))/(max(x)-min(x)) }
##Run nomalization on first 4 coulumns of dataset because they are the predictors
iris_norm <- as.data.frame(lapply(iris[,c(1,2,3,4)], nor))
summary(iris_norm)## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :0.0000 Min. :0.0000 Min. :0.0000 Min. :0.00
## 1st Qu.:0.2222 1st Qu.:0.3333 1st Qu.:0.1017 1st Qu.:0.08
## Median :0.4167 Median :0.4167 Median :0.5678 Median :0.50
## Mean :0.4287 Mean :0.4406 Mean :0.4675 Mean :0.45
## 3rd Qu.:0.5833 3rd Qu.:0.5417 3rd Qu.:0.6949 3rd Qu.:0.70
## Max. :1.0000 Max. :1.0000 Max. :1.0000 Max. :1.00##extract training set
iris_train <- iris_norm[ran,] ##extract testing set
iris_test <- iris_norm[-ran,] ##extract 5th column of train dataset because it will be used as 'cl' argument in knn function.
iris_target_category <- iris[ran,5] ##extract 5th column if test dataset to measure the accuracy
iris_test_category <- iris[-ran,5]##load the package class
library(class) ##run knn function
pr <- knn(iris_train,iris_test,cl=iris_target_category,k=13)
##create confusion matrix
tab <- table(pr,iris_test_category)
##this function divides the correct predictions by total number of predictions that tell us how accurate teh model is.
accuracy <- function(x){sum(diag(x)/(sum(rowSums(x)))) * 100}
accuracy(tab)## [1] 80
在 R 中已经可用的虹膜数据集中,我运行了 k-最近邻算法,得到了 80%的准确结果。首先,我将数据标准化,将 petal.length、sepal.length、petal.width 和 sepal.length 转换为标准化的 0 到 1 形式,以便我们可以将它们放入一个框(一个图)中,还因为我们的主要目标是预测一朵花是 virginica、Versicolor 还是 setosa,这就是为什么我排除了列 5,并将其存储到另一个名为 iris_target_category 的变量中。然后,我将规范化的值分成训练和测试数据集。想象一下,首先在图上绘制来自训练数据集的值,在我们使用所有必要的参数运行 knn 函数后,我们将测试数据集的值引入图中,并计算图中每个已存储点的欧几里德距离。现在,虽然我们知道它是测试数据集中的哪一朵花,但我们仍然预测这些值,并将它们存储在名为“pr”的变量中,以便我们可以将预测值与原始测试数据集的值进行比较。通过这种方式,我们可以了解我们模型的准确性,如果我们将来要获得新的 50 个值,并且要求我们预测这 50 个值的类别,我们可以使用该模型进行预测。
##because diamonds dataset is in ggplot2 package
library(ggplot2)##load data
data(diamonds)
##store it as data frame
dia <- data.frame(diamonds)
##create a random number equal 90% of total number of rows
ran <- sample(1:nrow(dia),0.9 * nrow(dia))
##the normalization function is created
nor <-function(x) { (x -min(x))/(max(x)-min(x)) }
##normalization function is created
dia_nor <- as.data.frame(lapply(dia[,c(1,5,6,7,8,9,10)], nor))
##training dataset extracted
dia_train <- dia_nor[ran,]
##test dataset extracted
dia_test <- dia_nor[-ran,]##the 2nd column of training dataset because that is what we need to predict about testing dataset
##also convert ordered factor to normal factor
dia_target <- as.factor(dia[ran,2])
##the actual values of 2nd couln of testing dataset to compaire it with values that will be predicted
##also convert ordered factor to normal factor
test_target <- as.factor(dia[-ran,2])
##run knn function
library(class)
pr <- knn(dia_train,dia_test,cl=dia_target,k=20)
##create the confucion matrix
tb <- table(pr,test_target)
##check the accuracy
accuracy <- function(x){sum(diag(x)/(sum(rowSums(x)))) * 100}
accuracy(tb)## [1] 71.09752
在这个模型中,我试图预测“切割”变量,因为它是一个分类变量,我们知道 knn 更适合分类问题。我没有考虑第 3 列和第 4 列,因为它们也是绝对的,并且会引起歧义,因为其他预测变量是整数。注意,有一些方法可以对分类变量和整数变量的混合运行 knn,但是我们在这里不讨论它。其余的过程与 iris 数据集相同,最终我们获得了 71%的准确结果。
参考
匿名。(2015 年 3 月 9 日)。“R-kNN-k 最近邻(第 1 部分)”。 贾莱尔书院 。https://www.youtube.com/watch?v=GtgJEVxl7DY
库马尔,s .(2017 年 10 月 8 日)。" R 中的 kNN(k-最近邻)算法"。RSTUDIO。https://r studio-pubs-static . S3 . Amazon AWS . com/316172 _ a 857 ca 788d 1441 F8 be 1 BC D1 e 31 f 0 e 875 . html
d . bhal la(2017 年 12 月 18 日)。《K 近邻:循序渐进教程》。红色记录器。https://www . r-bloggers . com/k-nearest-neighbor-step-by-step-tutorial/
声明:所有图片均由 BING 使用 BING 图片搜索 API 提供。所有图片仅供个人使用,我们从不…
homedecoration.nu](https://homedecoration.nu/galleries/black-people-christmas-village-clip-art.html)
k 最近邻,它的用途和如何使用它
对于那些不知道 k 最近邻是什么的人来说,这是一个预测模型。它的目的是什么,为什么使用它?这些是我们将在这篇文章中深入探讨的问题。
为了让这个模型工作,数据必须有一个距离的概念。用外行人的话来说,我们需要能够用图表表示我们的数据。
这个模型将是非线性的,可以用在课堂上。我所说的类是指它可以帮助确定一个数据点是属于一个类还是另一个类。一个很好的例子是根据收入和年龄来决定某人是共和党人还是民主党人。该模型将被证明是有用的,因为本质上它查看邻近的数据点来确定这个新数据点将落入什么样的位置。
现在我们知道了为什么这是有用的,让我们给出一个用 python 来做这件事的例子。
这个例子将使用花瓣宽度、花瓣长度、萼片长度和萼片宽度来尝试确定花的分类
**import** **pandas** **as** **pd**
url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
col_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species']
iris = pd.read_csv(url, header=None, names=col_names)
首先,我导入 pandas(一个 python 库),然后读入我的数据集并设置列名。这将我的数据放入一个很好的数据框架中,可以很容易地进行分析。
**from** **matplotlib.colors** **import** ListedColormap
cmap_bold = ListedColormap(['#FF0000', '#00FF00', '#0000FF']
上面的代码块引入了颜色绘图能力。
iris["Species_number"] = iris.species.map({'Iris-setosa':0,'Iris-versicolor':1,'Iris-virginica':2 })
然后,我制作了一个新的列,将每个物种映射到不同的 bin,bin 为 0、1 或 2。
iris.plot(kind = 'scatter', x = "petal_length", y = "petal_width", c ="Species_number" ,colormap= cmap_bold )
这显示踏板宽度和花瓣长度,以确定物种。每个物种都有不同的颜色。
feature_cols = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']
X = iris[feature_cols]
y = iris.Species_number
这使得我们的 X 是萼片长度,萼片宽度,花瓣长度,花瓣宽度。我们的 Y 是有三个箱的物种栏。我们试图使用 X 特征来确定 Y
**from** **sklearn.model_selection** **import** train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y)
对于任何一个好的模型,你都需要做一个训练测试来避免过度拟合你的模型。这是把你的数据分成一个训练集,然后是一个测试集来测试你的模型有多好。k 最近邻(也称为 KNN)是一个懒惰模型,这意味着它不使用训练数据点来做任何泛化。所以我们不打算训练一个模特。你可能会问,为什么要进行列车试运行?因为我们仍然需要那个测试集来测试这 70%,看看我们的 X 变量是否是好的预测器。
**from** **sklearn.neighbors** **import** KNeighborsClassifier
**from** **sklearn** **import** metrics
*# make an instance of a KNeighborsClassifier object*
knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train, y_train)
然后我们从 sklearn.neighbors 导入,以便能够使用我们的 KNN 模型。使用 KNeighborsClassifier,然后使用里面的参数确定您希望您的数据点查看多少个最近邻。没有经验法则告诉你应该看多少个邻居。确定要查看多少个相邻要素的最佳方法是测试一系列相邻要素,并确定哪一个具有最佳精度。
y_pred_class = knn.predict(X_test) **print** metrics.accuracy_score(y_test, y_pred_class)
这将让您看到准确性分数,因为我们只有 1 个最近邻要检查,所以我们的分数最终是 1(也称为 100%),这有可能被过度拟合。
**def** length(X, y):
empty_list = []
**for** n **in** range(1,100):
X_train, X_test, y_train, y_test = train_test_split(X, y)
knn = KNeighborsClassifier(n_neighbors=(n))
knn.fit(X_train, y_train)
y_pred_class = knn.predict(X_test)
empty_list.append(metrics.accuracy_score(y_test, y_pred_class))
**return** empty_list
该函数将测试 1-100 个最近邻,并返回每个最近邻的精度。这将有助于您为您的模型寻找最佳数量的邻居
一旦您确定了最佳邻居,您就可以在其他数据点上使用您的模型,将它们放入一个类中。
这就是你使用 KNN 的方式,我希望这能帮助那些对预测数据点将属于哪一类感兴趣的人
k 近邻—机器学习算法简介
另一种分类算法
介绍
我们发现分类算法非常重要而回归算法不太重要的原因是因为我们日常工作中面临的许多问题都属于分类任务。例如,我们想知道肿瘤是恶性的还是良性的,我们想知道消费者对我们出售的产品的反应是积极的还是消极的,等等。k 近邻是另一种分类算法,也是非常简单的一种。如果你在 K 意味着算法之后阅读这篇文章,不要混淆,因为它们属于不同的学习领域。K 均值是一种聚类/无监督算法,而 K 最近邻是一种分类/监督学习算法。
K 是什么??
在 K 均值算法中,对于每个测试数据点,我们将查看 K 个最近的训练数据点,并选取最频繁出现的类,并将该类分配给测试数据。因此,K 表示位于测试数据点附近的训练数据点的数量,我们将使用该测试数据点来找到类。
k 最近邻—伪代码
1\. Load the training and test data
2\. Choose the value of K
3\. For each point in test data:
- find the Euclidean distance to all training data points
- store the Euclidean distances in a list and sort it
- choose the first k points
- assign a class to the test point based on the majority of classes present in the chosen points
4\. End
K Nearest Neighbours
KNN 电码
我们将使用虹膜数据集来说明 KNN 算法。虹膜数据集有四个特征,我们将只使用其中的两个(萼片长度,花瓣长度)。这有助于我们更好地可视化数据点。
我们加载 Iris 数据集,获取目标值并将其存储在一个数组中。我们从数据框中删除目标值和两个不需要的要素。
通过绘制基于这两个特征的数据点,我们获得了如下所示的散点图。
Iris data — Scatter plot
我们将字符串类型中的类转换成整数类型。我们将数据混洗并分成训练和测试数据,90%的数据用于训练,而剩余的 10%用于测试。
我们使用 Scikit-learn 库来实现我们的 KNN 算法。我们取 K 值的范围,从 1 到 20,并根据不同的 K 值绘制我们的 KNN 模型的精确度
K vs accuracy plot
您可以看到,在 K = 3 时,我们能够实现 100%的精度,并且对于更大的 K 值,精度保持不变。现在,我们已经使用 Scikit-learn 库实现了该算法,让我们尝试在不使用 Scikit-learn 的情况下实现 KNN 算法。这将为我们提供对算法如何工作的更好的直观理解。
我们基于上述伪代码实现了该算法。我们使用 K = 3 的值。该模型的准确度也是 100%。
结论
k 近邻算法是一种简单的分类算法,具有广泛的应用。了解它的工作原理肯定会有帮助:)
k-NN —了解你最近的邻居
Evolving Science
本文是探索 10 种基本机器学习算法的 BAI 系列文章的一部分*
在一系列客户会议之后,这是明年某个时候的傍晚,在纽约市的高架线上。你在一个户外酒吧停下来,喝了第一杯酒,吃了点东西。坐在你的饮料旁边,你开始想你最近的邻居。你忍不住掏出手机来试试它新的面部识别技术。这款应用近乎实时地识别出你周围的人、他们的工作经历、他们的朋友和共同兴趣。除了隐私问题,k-NN 是什么,它是如何工作的,它在数据科学中的使用场景是什么,以及它如何促进面部识别技术的创新?
k-NN 是一种机器学习算法,自 20 世纪 70 年代以来被广泛用于在监督学习环境中分析数据。它的流行源于它的易用性和清晰易懂的结果。k-NN 中的“k”是指用于分类或预测数据集中结果的最近邻的数量。每个新观察值的分类或预测是基于加权平均值关于指定的距离(即最近邻)计算的。k-NN 分析是一个合理的选择,当很少有先验知识的观察分布的数据。
An example of k-NN classification — Adi Bronshtein
当我们被给定一个训练观察的标记数据集,并且目标是捕获每个观察之间的关系时,我们使用 k-NN。这种相似性关系被表示为数据点之间的距离度量。观察值之间的间隔被测量为欧几里德、曼哈顿、切比雪夫、汉明距离或甚至余弦相似性。k-NN 是一种非参数算法,因为它对关系的函数形式没有明确的假设。它也是基于实例学习的一个例子,因为它直接关注训练实例,而不是应用特定的数据模型。
k-NN 算法处理整个数据集,而不是训练数据的子集。最近邻的数量(k)是一个超参数,超过了数据科学家为了获得数据集的最佳拟合而选择的参数。当数量 k 较小时,我们限制了预测的区域,并使分类器对整体分布不太敏感。对于分类问题,这可能是最常见的类值。对于回归问题,这可能是平均输出变量。
你什么时候会用 k-NN?该算法被部署在概念搜索中,在概念搜索中,数据科学家在语义上搜索相似的文档。Discovery 是另一个使用场景,其中该算法可用于查找所有电子邮件、简报、合同等。与给定问题相关。推荐系统通常集成了 k-NN,因为如果你知道一个顾客喜欢某个特定的商品,你就可以向他们推荐类似的商品。最后,k-NN 通常用作更复杂分类器的基准,如人工神经网络(ANN)和支持向量机(SVM)。【1】
A k-NN classifier example using the CIIFAR 10 dataset — — Andrej Karpathy
他的算法有什么局限?当超参数 k 较高时,预测对异常值更有弹性。如果一类观察值在数据中非常频繁,K-NN 也会受到偏斜类分布的影响。k-NN 的易用性是以内存和计算为代价的,因为使用 k-NN 需要处理整个数据集而不是一个样本。由于所有这些原因,k-NN 算法在工业环境中可能不实用。
有几种技术可以提高算法的针对性。重新调整数据可以使距离度量更有意义。改变距离度量的性质可以帮助提高分类/预测的准确性(例如用汉明或曼哈顿代替欧几里德距离)。像 PCA 这样的降维技术可以在应用 k-NN 之前执行,以提供更易管理的结果。最后,使用类似 k-d 树的近似最近邻技术来存储训练观察值可以用来减少测试时间。
回到面部识别和高线上的酒吧,k-NN 在像 Herta Security 这样的应用程序中起着重要作用。【2】考虑到应用程序的性质,为城市中的每个人训练一个单独的分类器既具有挑战性又成本高昂。Herta 的数据科学家开发了深度学习算法,来生成代表人脸的特征向量。该应用程序然后使用 k-NN 来识别个人,将他们的脸与观察列表进行比较。一旦确定了一个引用,就可以将它链接到任何可用的数据库。当你啜饮第二杯葡萄酒时,你可能会思考面部识别的道德问题,因为知道你最近的邻居就在你的手边。【3】
李施伦克博士,商业分析研究所,2018 年 9 月 20 日
- 之前在白系列中发表的关于基本机器学习算法的文章包括 贝叶斯定理——熟能生巧 和 鲨鱼攻击——解释泊松回归的用法
Lee Schlenker 是商业分析和社区管理教授,也是 http://baieurope.com 商业分析研究所的负责人。可以在查看他的 LinkedIn 个人资料可以在的 Twitter 上关注白
【3】Jon Christian,(2018),面部识别如何将我们撕裂,
卡夫卡-Python 用 10 行代码解释
虽然它不是 Python 提供的最新库,但很难找到关于如何将 Apache Kafka 与 Python 结合使用的全面教程。通过大约十行代码,我将解释Kafka 的基础以及它与 Kafka-Python 的交互。
设置环境
首先你要在你的机器上安装卡夫卡和动物园管理员。对于 Windows 来说,有一个由 Shahrukh Aslam 编写的优秀指南,它们肯定也适用于其他操作系统。
接下来安装 Kafka-Python 。如果您使用的是 Anaconda 发行版,那么您可以使用 pip 或 conda 来实现这一点。
pip install kafka-pythonconda install -c conda-forge kafka-python
在执行下面的示例代码之前,不要忘记启动 Zookeeper 服务器和 Kafka broker 。在这个例子中,我们假设 Zookeeper 在 localhost:2181 上运行 default,在 localhost:9092 上运行 Kafka。
我们还使用了一个名为 numtest 的主题。在本例中,您可以创建一个新主题,方法是打开一个新的命令提示符,导航到 …/kafka/bin/windows 并执行:
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic numtest
卡夫卡是什么?
简而言之,Kafka 是一个分布式发布-订阅消息系统,它以分区和复制的主题维护消息提要。最简单的说,Kafka 生态系统中有三个参与者:生产者、主题(由经纪人管理)和消费者。
制作人根据他们选择的主题制作信息。可以给每个消息附加一个密钥,在这种情况下,生产者保证所有具有相同密钥的消息将到达相同的分区。
主题是日志,它从生产者那里接收数据,并将它们存储在它们的分区中。生产者总是在日志的末尾写新的消息。在我们的例子中,我们可以对分区进行抽象,因为我们在本地工作。
消费者按照自己的节奏阅读他们选择的主题的一组分区的信息。如果消费者是消费者组的一部分,即订阅相同主题的一组消费者,他们可以提交他们的补偿。如果您希望与不同的使用者并行使用一个主题,这可能很重要。
source: https://www.cloudera.com/documentation/kafka/1-2-x/topics/kafka.html
偏移量是日志中消费者最后消费或读取消息的位置。然后,用户可以提交该偏移量,使读数成为“官方”读数。偏移量提交可以在后台自动完成,也可以显式完成。在我们的示例中,我们将在后台自动提交。
让我们编码
在我们的例子中,我们将创建一个生产者,它发出从 1 到 1000 的数字,并将它们发送给我们的 Kafka 经纪人。然后消费者将从代理读取数据,并将它们存储在 MongoDb 集合中。
使用卡夫卡的好处在于,如果我们的消费者崩溃了,新的或固定的消费者会从上一个消费者停止阅读的地方继续阅读。这是一个很好的方法来确保所有的数据都输入到数据库中,没有重复或丢失的数据。
创建一个名为 producer.py 的新 Python 脚本,从我们全新的 Kafka-Python 库中导入 json 、 time.sleep 和 KafkaProducer 开始。
from time import sleep
from json import dumps
from kafka import KafkaProducer
然后初始化一个新的卡夫卡制作人。请注意以下参数:
- bootstrap _ servers =[’ localhost:9092 ']:设置生产者应该联系的主机和端口,以引导初始集群元数据。没有必要在这里设置,因为默认设置是 localhost:9092 。
- value _ serializer = lambda x:dumps(x)。encode(‘utf-8’) :数据在发送到代理之前应该如何序列化的函数。这里,我们将数据转换为 json 文件,并将其编码为 utf-8。
producer = KafkaProducer(bootstrap_servers=['localhost:9092'],
value_serializer=lambda x:
dumps(x).encode('utf-8'))
现在,我们想生成从 1 到 1000 的数字。这可以通过一个 for 循环来实现,我们将每个数字作为值输入到一个只有一个键的字典中: number 。这不是话题键,只是我们数据的一个键。在同一个循环中,我们还将把数据发送给一个代理。
这可以通过调用生成器上的 send 方法并指定主题和数据来完成。请注意,我们的值序列化程序将自动转换和编码数据。为了结束我们的迭代,我们休息 5 秒钟。如果您想确保消息被代理收到,建议包含一个回调。
for e in range(1000):
data = {'number' : e}
producer.send('numtest', value=data)
sleep(5)
如果您想测试代码,建议创建一个新主题并将数据发送到这个新主题。这样,当我们稍后一起测试生产者和消费者时,您将避免在 numtest 主题中的重复和可能的混淆。
消费数据
在我们开始编码我们的消费者之前,创建一个新文件 consumer.py 并从 pymongo 导入 json.loads 、 KafkaConsumer 类和 MongoClient 。我不会深入研究 PyMongo 代码,因为这超出了本文的范围。
此外,您可以用任何其他代码替换 mongo 代码。这可以是将数据输入到另一个数据库的代码,处理数据的代码或者任何你能想到的代码。关于 PyMongo 和 MongoDb 的更多信息,请查阅文档。
from kafka import KafkaConsumer
from pymongo import MongoClient
from json import loads
让我们创造我们的 KafkaConsumer 并仔细看看这些论点。
- 第一个参数是主题,在我们的例子中是 numtest 。
- bootstrap _ servers =[’ localhost:9092 ']:与我们的生产者相同
- auto _ offset _ reset = ’ earliest ':最重要的参数之一。它处理消费者在故障或关闭后重新开始阅读的位置,并且可以设置为最早最早或最晚最晚。当设置为最新时,用户从日志末尾开始读取。当设置为最早时,消费者从最新提交的偏移开始读取。这正是我们想要的。
- enable _ auto _ commit = True:确保消费者每隔一段时间提交一次读取偏移量。
- auto _ commit _ interval _ ms = 1000 ms:设置两次提交的时间间隔。因为每五秒钟就有一条消息进来,所以每秒钟提交一次似乎是公平的。
- group_id=‘counters’ :消费者所属的消费群。请记住,在介绍中,消费者需要成为消费者组的一部分,以使自动提交工作。
- 值反序列化器将数据反序列化为一种通用的 json 格式,与我们的值序列化器所做的相反。
consumer = KafkaConsumer(
'numtest',
bootstrap_servers=['localhost:9092'],
auto_offset_reset='earliest',
enable_auto_commit=True,
group_id='my-group',
value_deserializer=lambda x: loads(x.decode('utf-8')))
下面的代码连接到我们的 MongoDb 数据库的 numtest 集合(集合类似于关系数据库中的表)。
client = MongoClient('localhost:27017')
collection = client.numtest.numtest
我们可以通过循环从消费者那里提取数据(消费者是可迭代的)。消费者会一直听下去,直到代理不再响应。可以使用 value 属性访问消息的值。这里,我们用消息值覆盖消息。
下一行将数据插入我们的数据库集合。最后一行打印了一条确认消息,表明该消息已被添加到我们的集合中。注意,可以在这个循环中为所有动作添加回调。
for message in consumer:
message = message.value
collection.insert_one(message)
print('{} added to {}'.format(message, collection))
测试
让我们测试我们的两个脚本。打开命令提示符,转到保存 producer.py 和 consumer.py 的目录。执行 producer.py ,打开一个新的命令提示符。启动 consumer.py ,看看它如何读取所有消息,包括新消息。
现在中断消费者,记住它是哪个号码(或者在数据库中检查它)并重新启动消费者。请注意,消费者会拾取所有错过的消息,然后继续收听新消息。
请注意,如果您在阅读消息后 1 秒钟内关闭消费者,消息将在重新启动时再次被检索。为什么?因为我们的 auto_commit_interval 被设置为 1 秒,记住如果偏移量没有被提交,消费者将再次读取消息(如果 auto_offset_reset 被设置为最早)。
—请随时在评论中或私信中向我指出任何不一致或错误。—
承认
本文绝不是 Kafka 或 Kafka-Python 的完整指南,而是一个全面的介绍,它将使您熟悉 Kafka 的基本概念以及如何用有用的 Python 代码来转换这些概念。
对于更高级的主题,建议阅读文档。如果你想部署代码,看看 Russell Jurney 的 Confluent-Kafka 和这篇文章可能是个好主意。
来源
使用 Kafka-Python 的反序列化器消费来自 Kafka 的 JSON 消息
介绍 Kafka 消费者:开始使用新的 Apache Kafka 0.9 消费者客户端
环游世界
The World Clock at Alexanderplatz, Berlin
不言而喻,数据科学家、机器学习工程师和 AI 研究人员的数量在全球并不是平均分布的。有各种各样的指标可以用来了解国家和大陆之间的机器学习差距有多大。例如,来自深度学习 Indaba 的人们使用神经信息处理系统年度会议(NeurIPS 以前的 NIPS)上被接受的论文数量来观察当代机器学习景观中缺失了两个完整的大陆:南美和非洲。
我们可以通过查看关于 Kaggle 的现有数据来做类似的工作。如果你不知道,Kaggle 是一个在线平台,用户可以在那里找到并发布数据集。它还举办不同的机器学习比赛,吸引了一千多个团队和个人。由于 Kaggle 在数据科学人士中非常受欢迎,因此将其作为每个国家的数据科学社区的代理并不为过。我们想在这里解决的主要问题如下:我们能看到来自不同大陆的机器学习/数据科学社区之间的明显差异吗?这些差异仅与绩效相关吗?还是仅仅是社会经济差异,反映了国家和大陆之间现存的不平等?
为了回答这些问题,我们将使用两个来源:
- 排名用户数据集:由爬虫获取并由 Norconsult 智能显示的 Kaggle 用户数据。
- Kaggle 第二次年度机器学习和数据科学调查 (ML & DS 调查):ka ggle 进行的一项调查,共有来自不同国家的 23859 人参与。
第一个数据集将帮助我们了解每个大陆在 Kaggle 中的表现;第二个将引导我们看到不同 ML/DS 社区的相关特征。本分析中使用的所有代码和数据均可在这里找到。
衡量绩效
排名用户数据集是通过从 Kaggle 的网站上抓取位置数据获得的。Kaggle 有不同类别的专业知识。我们将只与其中一个合作:*竞争。*在这个类别中有五个表现等级:新手、贡献者、专家、大师和特级大师。分级用户是专家级或更高级别的用户。
查看数据,我们可以看到每一行代表一个排名用户。栏目有:报名日期、当前积分、当前排名、最高排名、国家和*洲。*在 Kaggle 中,积分和排名会随着时间而变化。所以,这里代表的所有位置只对应一个特定的时间点(2018 年 8 月左右)。
全球排名用户
需要注意的是,这些地块并不完整,总排名用户(1267 个用户)中有 26.6% 没有公开他们的位置。
看着情节 1 很明显,美国是排名用户最多的国家,遥遥领先。如果你把美国从这里列出的国家名单中去掉,差距就没那么大了。
剧情二显示有两组截然不同的大陆:一边是北美、亚洲和欧洲(第一组);另一边,大洋洲,南美,非洲,中美洲(第二组)。第一组负责 Kaggle 所有排名用户的 69.1% ,因此第二组仅保留排名用户的 4.3% 。
使用每个用户的注册日期,我们可以看到世界上不同地区在 Kaggle 内部是如何发展的:
我们也可以看到每个国家的演变:
剧情 3 清晰地展现了两组大陆的差异。这里需要注意的一点是,尽管欧洲一直主导着亚洲,但在 2016 年,后者开始缩小它们之间的差距,从 2017 年开始,亚洲的排名用户开始超过欧洲。
图 4–10显示了每个区域的动态。在北美、亚洲、大洋洲、南美和非洲,我们可以清楚地看到一个国家统治着其他国家:分别是美国、俄罗斯、澳大利亚、巴西和南非。中美洲国家拥有相同数量的用户(每个国家只有一个)。在欧洲,我们可以看到法国、英国和德国争夺第一的位置。
点数和等级
Kaggle 有一个积分系统。它们被设计成随着时间的推移而衰减。所以它们只反映了收集数据时的卡格尔地貌。将特定国家的每个用户的积分相加,我们得到了以下图表:
剧情 11 展示了一个与剧情 1 相似的场景,这里唯一大的不同是巴西的出现(把澳洲排除在名单之外)。这是来自这个国家的一些高排名用户的影响(在收集数据时,第一名属于一个巴西用户)。
在第 12 集中可以看出的一点是,亚洲和欧洲的分数都比北美高。记住我们在剧情 2 中看到的,北美是排名用户最多的大陆。点衰减解释了图 2 和图 12 之间的差异。当我们分析排名信息时,这一点就会变得清楚。
在该数据中,我们有每个排名用户的当前排名以及他/她曾经达到的最高排名。为了比较国家和大洲,我们可以使用以下得分函数:
Figure 1: score function
该函数返回一个分数,最高等级的用户得到 1 分,最低等级的用户得到 0 分,对于两者之间的任何人,它返回一个区间(0,1)内的实数。
将各大洲的得分相加,我们得到:
如果我们比较图 13 和图 14 的差异,我们会看到以下情况:北美呈现最高的最高排名分数,因为来自该大陆的许多排名用户在过去的中取得了不错的排名,但是当我们查看当前排名分数时,亚洲和欧洲的表现更好。同样,当我们查看第 2 组时,我们可以看到南美洲拥有目前该组大陆中的最佳成绩,大洋洲位居第二。
这里的关键事实是,在某个时间点,来自亚洲和欧洲的用户在机器学习竞赛中变得更好,并取代了北美的位置。根据这些数据,我们不能说确切的时间。但是转变是明显的。
仔细观察每个社区
通过提出各种有趣的问题,ML & DS 调查对每个国家的机器学习社区进行了丰富的描述。为了简洁起见,我们只把重点放在一些具体问题上。所选问题反映的被试者的地域差异通常更为突出:年龄,正规教育,年使用机器学习,年报酬和使用技术。
ML & DS 调查的地理分布
与图 1 和图 2 相比,图 15 和图 16 显示了不同的分布。我们可以看到,有大量来自印度的参与者,使亚洲成为调查中最具代表性的大陆。请注意这里没有中美洲国家的代表。与已排名的用户数据相比,我们没有公开其位置的用户百分比更低:参与者的 6%(1430)。
将响应作为分布进行分析
参与者被问及一系列选择题(我们没有分析调查中的开放式问题)。在这里,我们将按大洲显示一些答案,为了有助于形象化,我们将打破显示第组 1 (亚洲、北美和欧洲)和第组 2 (南美、非洲和大洋洲)的大洲的图表。
当我们按洲汇总多个答案时,我们在这些答案上构建了一个分布。比较大陆之间差异的一种方法是比较它们各自分布之间的差异。为此,我们将利用库尔贝克-莱布勒散度:
当 p 与 q 同分布时,DKL(p || q)的值为 0,当它们不同时,DKL(p || q) > 0。DKL(p || q)的值随着 p 和 q 之间的散度的增加而增加。我们可以在 DKL(p || q)之上定义一个距离度量如下:
distance k1(p,q) = DKL(p || q) + DKL(q || p)
因此,对于每个问题,我们可以构建一个距离矩阵来观察每个大陆之间的差异。
问:“你的年龄是多少岁?”
从图 17–19 中可以看出,本次调查中的绝大多数年轻人来自亚洲(大部分来自印度)。客观地看,来自印度的自称 18 到 21 岁的人数(1225)比来自南美的所有参与者的人数(1140)都多。
另一个值得注意的事实是,据报道 40 岁或以上的人很少来自非洲(在 40 岁以上的人群中,只有 1.8%来自非洲)。当我们观察第 20 幅图时,我们可以看到大洋洲和亚洲在年龄上的巨大差异。前者比后者拥有更多的老年 Kaggle 用户。
问:“你已经达到或计划在未来两年内达到的最高正规教育水平是什么?”
在图 21–23中,最引人注目的事实是来自欧洲的 Kaggle 用户中拥有或计划拥有研究生学位的人数。欧洲集中了大部分拥有博士学位的用户(1083),而 77.5% 的欧洲用户已经或计划拥有硕士或博士学位。正如图 24 所示,欧洲与几乎所有大陆都有很大差异(北美是唯一的例外)。
问:“你使用机器学习方法(在工作中或在学校)有多少年了?”
图 25–27显示了与图 17–19 中呈现的场景相似的场景:亚洲集中了大量的 ML 新手用户,主要是由于印度;北美和欧洲拥有最多的经验用户(在所有拥有 5 年以上 ML 经验的人中,39.7%在北美, 36.6% 在欧洲);而非洲只有 1.2%的 ML 老兵。我们在剧情 24 中首次发现的欧洲和非洲之间的差异再次出现在剧情 28 中。这可以用正规教育和使用机器学习的年数之间的正相关来解释。
问:“你目前的年薪是多少(大约美元)?”
当我们看到薪酬的差异时,各大洲之间的差距就非常明显了。图 33 显示了整个内核中 KL 距离的最高值!北美明显不同于世界其他地区。从这个具体答案的 KL 距离上,我们也可以看到两个遥远的群体:一边是北美、欧洲、大洋洲;另一边是南美、亚洲和非洲。另一种方法是看数字。一个极端是,高薪工作集中在北美,收入超过 125,000 英镑的人中有 68.8%来自美国。另一方面,南美洲、亚洲和非洲总共集中了 75.9% 报告年度薪酬最低的所有用户。
问:在过去 5 年中,您在工作或学校中使用过以下哪些云计算服务?
对技术的获取塑造了每个 ML/DS 社区的潜力。幸运的是,关于云计算服务的数量,我们在世界各地看到了相同的模式( Plots 34 和 35 )。我们可以观察到的唯一显著差异是,亚洲使用的服务类型有很小的差异,报告使用阿里云服务的绝大多数用户来自亚洲( Plots 36 和 37 )。
问:在过去的 5 年里,你使用过哪些机器学习框架?
与图 34–37中呈现的结果类似,图 38–41中传达的信息是,就机器学习框架的使用而言,各大洲之间存在微小差异。
最后的想法
根据我们的分析,出现了两个不同的大陆群:第 1 群(亚洲、北美和欧洲)和第 2 群(南美、非洲、大洋洲和中美洲)。这种区分是基于用户数量、点数和排名位置(一种基于业绩的区分)。但是,正如 ML & DS 调查所显示的,这些群体的大陆之间没有社会经济的统一。如果我们采用 KL 距离度量,我们可以定义另外两个更一致的组:组 3 (北美、欧洲和大洋洲)和组 4 (非洲、亚洲、南美洲和中美洲)。
KL distance table by continent groups
这不应该被视为意外,当我们按人均国内生产总值对各大洲进行排名时,第 3 组和第 4 组也出现了。看起来 ML & DS 调查是世界现实的反映,就像它应该的那样。
幸运的是,我们还可以推导出一些非平凡的结论。
第一个是,亚洲目前在 Kaggle ( Plots 12 和 14 )中扮演着核心角色,正如 ML & DS 调查显示的那样,它在未来将继续扮演重要角色。一大群年轻数据科学家属于这个大陆,大部分来自印度。虽然印度在调查中有很好的代表性,但它不应该被高估。正如图 11 所示,与印度相比,俄罗斯、日本和中国目前在比赛中表现更好。
第二个是技术的使用在不同的 ML/DS 社区中非常相似。虽然电力、计算机和互联网的接入因洲而异,但我们没有发现云服务和机器学习框架的数量和类型存在巨大差距(Plots 34–41)。看起来这些技术的使用已经相当大众化了,至少在 Kaggle 用户中是这样。
回到启发我们分析的博文(来自深度学习 Indaba 的那篇),我们看到了关于南美和非洲的更光明的前景。这些大陆并没有在 Kaggle 景观中消失(唯一真正消失的是中美洲)。他们在场,他们竞争,南美领先第 3 组 ( 第 12 地块和第 14 地块)。但是他们仍然有很多问题(因为我来自巴西,这些问题切中要害)。南美洲是一个经济规模可观的大洲(该洲的人均 GDP 大于亚洲),然而来自该洲的排名用户数量与来自荷兰的排名用户数量相同 (64)。这是一个令人震惊的小数字。非洲仍然面临许多困难。当我们看一些重要的社会经济特征时,如正规教育、从事机器学习的年限和每年的薪酬,最高的 KL 距离是在 组 3 的一个大陆和非洲 ( 地块 24 、 28 和 33 )。
归根结底,我们面临的最大挑战不是最新的 Kaggle 竞赛,而是我们社区的改善和培育。
Kaggle Avito 需求挑战:第 18 名解决方案—神经网络
前几天刚和队友在俄罗斯广告公司 Avito 主办的一场 Kaggle 比赛中获得银牌,以第 18 名结束。这项挑战的目标是根据他们提供的数据预测在线分类广告的需求。在这篇文章中,我将说明我的方法,我专门研究的神经网络(NN)(我的队友主要负责基于树和其他线性模型)。然后,我将谈谈我从顶级赢家的解决方案中学到的经验。
我的方法
NN Structure
如上图所示,我的神经网络模型由 4 个不同的模块组成,这些模块使用组织者提供的所有数据,图像、分类、连续和文本数据。我将在下面的段落中解释每一部分。
连续的
这是最不令人惊讶的部分。连续特征的输入张量直接与其他模块连接。需要注意的一点是处理空值。对于缺失的连续数据,我要么填 0,要么填平均值。
绝对的
对于分类数据,嵌入层用于学习这些离散值的潜在表示。我知道这可能不是一个新的想法,但这是我第一次使用分类嵌入,因为我从来没有使用 NN 来处理结构化/表格数据。范畴嵌入的概念类似于单词嵌入。类别值被映射到可学习的嵌入向量上,使得这些向量包含潜在空间中的含义。这有助于避免一次性编码分类特征的稀疏性,提高模型的性能。
文本
我的神经网络的文本部分比其他顶级赢家的方法相对简单。没有复杂的递归单元或卷积层,也没有使用预先训练的嵌入。我不知道为什么,但它们都不适合我的神经网络模型。这里唯一的技巧是使用一个共享的嵌入层,受 Mercari 挑战赛中第二名解决方案的启发。基于相同的嵌入矩阵嵌入两个文本条目,标题和描述。它不仅有助于加快神经网络的训练,而且还导致更快的收敛和更低的损失。
图像
我对图像数据的第一种方法是使用预先训练的 ImageNet 模型来提取有或没有这些模型头部的特征。我试过 ResNet50 和 InceptionV3 不幸的是,它们都不起作用。在比赛还有 2 周的时候,有人在论坛上说他的模型包括几个卷积层来训练原始图像和其他特征。因此,我开始重写我的代码,以便它利用一个生成器来读取图像和表格数据,因为不可能将所有图像数据加载到 RAM 中。在尝试了一些结构后,我发现 1 个 InceptionV3 单元+几个卷积层最适合我(因为我在 GCP 上只有一个 K80 GPU,所以需要很长时间来验证几次实验的结果)。
从顶级解决方案中吸取的经验教训
- 第一位置 NN 解决方案也遇到了从大多数预先训练的 ImageNet 模型中提取的特征的较差性能。他们最终使用了 VGG 顶层+ ResNet50 中间层。他们的方法与我之前的方法最大的不同是,在提取的图像特征与其他条目连接之前,他们应用了平均池并添加了密集层。
- 类别特征交互:连接两个类别特征,并将其视为一个新特征。
- 无监督学习:使用自动编码器从分类数据中提取向量。
- 验证策略:注意每个折叠之间的重叠特征值应该类似于训练/测试分割的特征值。(特别是本次比赛中的用户 id)
- 损失函数:所有前 3 名的解决方案都使用二元交叉熵作为损失函数,而我在整个比赛中使用 MSE。我应该尝试更多的损失函数,如 BCE 和 Huber 损失。
- 堆叠:我们在比赛结束前一周开始堆叠,所以我们只有几个浅堆叠的基础模型。几乎所有的顶级解决方案都使用了大量的模型进行更宽更深的堆叠(第二名获奖者使用了 6 层…)
我在这场比赛中玩得很开心。我要感谢我的队友,所有公开分享他们想法/解决方案的人。我从你身上学到了很多!我也要感谢 Kaggle 和主办方举办了这样一场伟大的比赛。没有你,我就无法提高我的机器学习技能。
如果想了解更多我的解决方案,可以参考这个 Github repo 。
Kaggle 竞赛—图像分类
如何使用迁移学习建立一个可以预测输入图像分类的 CNN 模型
第一个误区 — Kaggle 是一个举办机器学习竞赛的网站。我相信这种误解让很多数据科学初学者——包括我——认为 Kaggle 只适合数据专业人士或有多年经验的专家。事实上,Kaggle 提供的不仅仅是竞赛!
Kaggle 上有如此多的开放数据集,我们可以简单地从玩我们选择的数据集开始,并在过程中学习。如果你是一个对数据科学毫无经验的初学者,并且可能想在加入之前参加更多的在线课程,请三思!Kaggle 甚至为你提供一些基础而实用的编程和数据科学课程。此外,您可以随时在 Kaggle 讨论中提出您的问题,以便向活跃的数据科学社区寻求建议或澄清任何数据科学问题。
脸书创始人兼首席执行官马克·扎克伯格在哈佛毕业典礼上的演讲中分享了一段真正启发了我的话
你只需要开始。
—马克·扎克伯格
开始并迈出第一步一直是做任何事情之前最难的部分,更不用说取得进展或提高了。
有很多在线资源可以帮助我们开始使用 Kaggle,我将在这里列出一些我认为非常有用的资源:
在接下来的部分,我希望与你分享一个初学者在他的第一次 Kaggle 比赛中的旅程(和他的团队成员一起)以及一些错误和教训。你可以在这里查看代码。这些部分分布如下:
- 竞争的背景和数据
- 方法
- 结果
- 最后的想法
让我们开始吧,我希望你会喜欢它!
竞争背景和数据
在我的第一篇关于 Medium 的帖子——我从物理到数据科学的旅程中,我提到了我和我的团队成员——罗伟鸿 、 崇科信 **、**和Onn一起参加了由**** Shopee 和(IET)工程技术学院举办的首届 Kaggle 机器学习竞赛我们在旅途中玩得很开心,我确实从他们身上学到了很多!!
Shopee 给了我们 18 个类别的商品图像,我们的目标是建立一个模型,可以预测输入图像到不同类别的分类。
太好了。现在我们已经了解了上下文。让我们继续我们的图像分类预测方法——这是 有趣(我是说最难) 的部分!
用于分类的一些图像
Different Images for Classification
正如您从图像中看到的,一些图像中存在一些噪声(不同的背景、描述或裁剪的文字),这使得图像预处理和模型建立更加困难。
在下一节中,我将讨论我们解决这个问题的方法,直到构建我们定制的 CNN 模型。
方法
每当人们谈论图像分类时,卷积神经网络(CNN) 就会自然而然地出现在他们的脑海中——毫不奇怪——我们也不例外。
我第一次接触 CNN 时,知识和经验都很少, Google 是我最好的老师,我不得不强烈推荐这本由阿迪特·德什潘德撰写的简明而全面的 CNN 简介。高水平的解释打破了 CNN 一度令人生畏的结构,变成了我能理解的简单术语。
图像预处理
图像预处理也可以称为数据增强。
Generate batches of tensor image data with real-time data augmentation that will be looped over in batches
在将图像输入模型之前,数据扩充步骤是必要的,特别是对于给定的 不平衡且有限的数据集。通过对图像进行不同的变换、缩放和剪切范围来人为扩展我们的数据集,我们增加了训练数据的数量。
—第一个错误—
我相信每一种方法都来自于背后的多次尝试和错误。因此,在展示我们的最终方法之前,让我们先谈谈我们的第一个错误。
我们开始尝试从零开始构建我们的 CNN 模型(没错,就是这样!)来查看 CNN 模型基于训练和测试图像的表现。我们不知道大多数人很少从零开始训练 CNN 模型,原因如下:
- 数据集不足(训练图像)
- CNN 模型很复杂,通常需要几周甚至几个月来训练,尽管我们有集群机器和高性能 GPU。
- 成本和时间不能保证和证明模型的性能
幸好转学来救我们了。
迁移学习
那么……迁移学习到底是什么?
迁移学习 是一种机器学习方法,其中为一个任务开发的模型被重新用作第二个任务的模型的起点。在我们的例子中,这是一种
Inception V3 Google Research
最终我们选择了 InceptionV3 模型 ,权重在 ImageNet 上预训练,准确率最高。
为无休止的评论道歉,因为我们想确保每一行都是正确的。
乍一看,这些代码可能有点令人困惑。让我们通过下面解释的逻辑来进行分解,使事情变得更清楚:
- 我们首先使用之前导入的预训练的 InceptionV3 模型创建了一个基础模型。为了以后的定制目的,在神经网络的顶部移除了完全连接的最后一层。
- 然后我们添加了一个 全局空间平均池层 ,原因可以在这里找到。
- 之后,我们创建了一个新的全连接输出层,接着是一个脱落层用于正则化目的。
- 最后,我们为 18 个类别(18 类图像)添加了一个 softmax 层,并且将基础模型与创建的新输出层相结合。
在这个阶段,我们冻结了基础模型的所有层,只训练新的输出层。
这就是迁移学习的美妙之处,因为我们不需要重新训练整个组合模型,因为基础模型已经被训练过了。
微调组合模型
一旦顶层训练好了,我们就微调内层的一部分。
可选地,通过选择和训练顶部的 2 个先启块(组合模型中 249 层之后的所有剩余层)来实现微调过程。训练过程与以前相同,只是包括的层数不同。
是的,我们结束了!
结果
最终准确率为 78.96%。
我们尝试了不同的方法来微调超参数,但无济于事。
当所有的结果和方法在比赛结束后揭晓时,我们发现了我们的第二个错误…
—第二个错误—
我们没有使用叠加法的集合模型。
所有顶级团队的共同点是他们都使用集合模型。
相反,我们分别训练不同的预训练模型,只选择最佳模型。这种方法间接使得我们的模型在只使用一个模型测试数据时不够健壮,并且容易过度拟合。
最后的想法
尽管比赛时间很短,但我从我的团队成员和其他团队那里学到了很多东西——从理解 CNN 模型,应用迁移学习,制定我们学习其他团队使用的其他方法的方法。
这个过程并不容易。学习曲线很陡。学习之旅充满挑战,但同时也很有收获。我非常期待另一场比赛!😄
感谢您的阅读。
一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!😄
关于作者
阿德蒙德·李 目前是东南亚排名第一的商业银行 API 平台 Staq — 的联合创始人/首席技术官。
想要获得免费的每周数据科学和创业见解吗?
你可以在 LinkedIn 、 Medium 、 Twitter 、脸书上和他联系。
让每个人都能接触到数据科学。Admond 正在通过先进的社交分析和机器学习,利用可操作的见解帮助公司和数字营销机构实现营销投资回报。
www.admondlee.com](https://www.admondlee.com/)*
Kaggle 竞赛:英特尔和 MobileODT 宫颈癌筛查
我开始看 Kaggle 比赛来练习我的机器学习技能。当前正在进行的竞赛之一被框架化为图像分类问题。英特尔与 MobileODT 合作,开始了一场 Kaggle 比赛,以开发一种基于图像识别女性子宫颈类型的算法。
训练集包含分成三种类型的 1481 幅图像。Kagglers 可以使用 6734 额外的图像。其中一些来自重复的病人。一些附加图像质量较低。比赛的两个阶段的测试集是可用的,kagglers 必须提交一组预测概率,3 个类别中的每一个,测试集的每个图像。总奖金为 100,000 美元。
我试图以一种天真的方式来解决这个问题:只需获得一个预训练的 Inception V3 图像分类模型,并在这个数据集上对其进行微调。
数据
Philipp Schmidt 出版了子宫颈 EDA 笔记本:研究数据集的基本属性。
我加载了所有带标签的图像,并将它们的大小调整为 224x224 的形状,这在 Inception V3 中使用。以 80/20 的比例混合并分成训练集和开发集。
型号
使用 Keras 加载在 ImageNet 数据集上预先训练的 Inception V3 模型和权重。移除了顶部分类层,在顶部添加了一个新的带有 dropout 的密集层和一个 softmax 层。我冻结了所有的初始层,首先训练新的密集层。然后《盗梦空间》的最后两个卷积块被解冻,我也对它们进行了微调。该模型在 80%的标记数据上进行训练,在 20%上进行验证。
结果
不太好。验证损失不会低于 0.95。该模型过拟合很快。我在验证集上得到 54.5%的准确率。
我的代码在这里可用。
正如你在关于 Kaggle ( 1 、 2 、 3 的讨论中所看到的,一个未经训练的人很难对这些图像进行分类。参见 visoft 的如何(人工)识别子宫颈类型的简短教程。
低画质更难。另一个挑战是数据集的规模较小。
看起来最好的前进方式是将问题一分为二:图像分割以在图像中找到子宫颈,然后进行图像分类。图像分割问题需要人工审查训练样本,以找到包围盒。光照校正可以另当别论去尝试。数据扩充(旋转、翻转)有助于增加训练样本的数量。
在这一步,我想我对处理图像分类问题有了很好的感觉。这个对我来说太难了,我现在无法竞争,计算机视觉也不是我关注的领域。我去查查其他比赛。这个看起来很有趣:两个适马连接:租赁列表查询。这是一个分类问题。数据集包括结构化数据、文本和图像。
文章原载于http://Pavel . surmenok . com/2017/04/09/ka ggle-competition-Intel-mobile ODT-宫颈癌-筛查/
Kaggle 星球大赛:如何登陆前 4%
在这篇博文中,我们将学习如何在著名的 Kaggle 竞赛“星球:从太空了解亚马逊”中取得世界级的成绩。
博客中使用的技术是通用的,可以应用于任何其他需要物体检测的问题。这些技巧都在fast . ai deep learning MOOC中有所教授。在本教程中,我们将使用基于 PyTorch 构建的fastaideep learning 库。
下载比赛数据
让我们开始吧,登录 Kaggle 账号,前往竞赛页面,接受竞赛规则,前往数据标签,下载以下文件。
- sample _ submission _ v2 . CSV . zip
- test-jpg-additional . tar . 7z
- test-jpg.tar.7z
- train-jpg.tar.7z
- train_v2.csv.zip
我们可以使用kaggle-clI下载文件,这在你使用 AWS、Paperspace 等云 VM 实例时很有用。要使用 kaggle-cli 下载文件,请使用以下命令。
$ kg download -u <username> -p <password> -c planet-understanding-the-amazon-from-space -f <name of file>
其中planet-understanding-the-amazon-from-space
是比赛名称,你可以在比赛 URL 的末尾 /c/
部分[https://www.kaggle.com/c/planet-understanding-the-amazon-from-spac](https://www.kaggle.com/c/planet-understanding-the-amazon-from-space)e
后找到比赛名称。还有另一个很棒的 Chrome 扩展Curl Widget下载云实例上的数据。你可以在这里[查看](http://Builds a command line for ‘curl/wget’ tools to enable the download of data on a console only session.)。
文件下载完成后,我们可以使用以下命令提取文件。
*#To extract .7z files
7z x -so <file_name>.7z | tar xf -#To extract.zip files
unzip <file_name>.zip*
一旦提取完成,将所有文件从文件夹test-jpg-additional
移动到test-jpg
。
我们的数据准备好了。让我们开始构建模型。
初始模型
注意:只有重要的代码片段显示在这篇博文中,完整的笔记本在这里。**
- 如果你看了比赛的评价标准,你会知道它是基于 f2 分数。我们相应地为模型定义度量。我们将使用由微软公布的深度剩余模型 renet34 的预训练实现。
获取 20%的可用训练数据作为验证数据,并加载预训练模型。
寻找学习率
学习率是该模型最重要的超参数之一。它决定了模型学习的快慢。如果 LR 太高,模型将试图学习得太快,损失函数将不收敛。如果 LR 太低,模型将需要太长时间才能收敛。
使用 fastai 库找到一个好的学习率非常容易,只需运行下面两行代码。(它有助于使用研究论文 中介绍的技术找到 LR,用于训练神经网络 的循环学习率)
这将绘制 LR 对损失函数的曲线图。LR 的一个好值是损失函数斜率最高的地方。正如我们所见,斜率在 0.1 左右最高,您可以使用任何接近它的值。用 0.1 左右的几个值进行实验,以找到 LR 的最佳值,这将是一个好主意。在尝试了几个值之后,0.2 似乎对我最有效。
训练模型
比赛中的芯片总尺寸为 256X256,我们开始用 64x64 来训练我们的模型,并将随着训练的进展逐渐增加图像的尺寸。这是避免过度拟合的非常好的技术。**
输出具有以下格式
[ <epoch_number> <train loss> <val loss> <val set f2 score>]
**让我们试着轻描淡写一下fit function
。在训练模型时 fastai 实现了一种叫做带重启的随机梯度下降(SGDR)的技术( 论文链接 )。它在循环中训练模型,其中每个循环由一个或多个时期组成。对于每个周期,它从给定的 LR 值开始,并将随着训练的进行而指数地降低 LR ( 指数学习速率表)。拟合中的第二个参数表示循环总数。一个循环中的总次数由以下两个参数cycle_len
和cycle_mult
控制。
epochs in first cycle = cycle_len epochs in second cycle = epochs in previous(first) cycle x cycle_mult epochs in third cycle = epochs in previous(second) cycle x cycle_mult
这是显示每个周期 LR 变化的图表。
解冻所有图层,并为图层设置不同的学习速率
默认情况下,fastai
将冻结所有图层的权重,除了最后几个图层和它添加的用于微调给定数据集模型的图层。(有 Keras 背景的数据科学家会欣赏这个,不需要 *model.pop*
、 *model.add*
、*model.layers[index].trainable=False*
*model.compile*
……)
所以在上述时代,所有的学习都是由那些解冻的最后一层完成的。
接下来,我们将解冻所有层的权重,以提高模型的准确性。
如果你给 fastai 一个 3 元素的数组,它会把层分成 3 组,【<初始卷积层>,<剩余卷积层>,<最后完全连接层>。对于每个集合,它将使用数组中相应的值。
在 CNN 的初始层学习寻找简单的特征(如边缘,颜色渐变,角落),这些特征对行星数据集同样有帮助。因此,我们对它们使用最低的 LR。CNN 的更高层学习寻找复杂的特征(像几何图案、脸、特定物体等)。更高层的 LR 值的增加将有助于它们更快地适应给定的数据集。
正如您从输出中看到的,我们的模型已经开始过度适应。我将在这里停止训练,并将训练图像大小增加到 128x128。
同样,通过将图像大小增加到 256x256 来训练模型。这将结束模型的训练阶段。
fastai 还有一个非常好的特性叫做测试时间增强(TTA)** 。这个想法很简单;对每个测试图像应用简单的增强以生成它的五个副本,然后对每个副本进行预测。您可以对这些预测进行平均,以显著降低误差(1–2%)。正如您在下面的代码中看到的,使用 TTA,F2 分数从 0.928 增加到 0.930。这是一个很好的分数。**
第一次提交给 Kaggle
在提交文件中,我们需要对每个图像放置预测标签。每个图像可以属于多个类别。
file_10770,agriculture clear cultivation primary road test_26732,agriculture clear cultivation haze primary
如果您查看我们的验证集(下图)中的预测示例,您会看到我们的原始标签是 1 和 0 的形式,但我们的预测是浮点数。因此,我们需要为提交文件中包含的预测选择一个阈值(0.66 对于下面的例子是理想的)。
op_th
函数在给定范围内尝试多个阈值,并返回使 F2 分数最大化的阈值。
现在我们有了最佳阈值,让我们生成一个提交文件
这是 Kaggle 的提交结果。
私人得分 0.92997 将使我们在 938 名中排名第 65 位。这款最初的车型本应排在前 7%。这是相当大的成就。让我们进一步改进它。****
Private leader board of Kaggle planet competition.
组装
我的下一个目标是进入前 5%。我训练了 5 个 resnet34 模型。每个模型的训练集由 90%的可用训练数据和剩余的 10 %数据组成,作为验证集。我还对每个模型的训练集应用了略有不同的数据扩充。这是所有模特的 F2 分数。
**f2 Score: 0.9285756738073999
f2 Score: 0.9325735931488134
f2 Score: 0.9345646226806884
f2 Score: 0.9331467241762751
f2 Score: 0.9349772800026489**
看到这一点后,我对职位的提高充满了希望。我准备了提交文件,并提交给 Kaggle。这是结果。
Kaggle submission result for ensemble
这里是 Kaggle 的私人领袖板。
0.93078 的个人得分将使我们在 938 分中排在第 35 位。这是最高的 3.7%。
所以我们进入了前 4%。目标实现
代码为合奏可以在 这里找到 或者便签本底部。
如何进一步提高
我将给你留下进一步改进的建议。
- ****找到阈值的更好方法:在准备提交文件时,我使用了大约 0.2 的阈值来为所有测试图像选择类别,但理想情况下,每个测试图像都应该有一个独立的阈值,具体取决于模型的预测值。我尝试训练一个 ML 模型来寻找更好的阈值,但没有成功。(代码在笔记本
- ****找出模型预测错误的类别:从验证集预测中,您可以找出模型预测最不正确的类别。您可以在训练集中引入这些类的多个稍微扩充的副本。
- 用 tiff 代替 jpg: 对于相同数量的图像,tiff 格式的训练数据集大小为 12.87 GB,而 jpg 格式的大小仅为 600MB,因此很明显 tiff 数据比 jpg 包含更多的信息。这必将有助于进一步改进模型。
- ****尝试其他架构:我只用过 resnet34 型号,它们是很多其他高级型号,比如 resnet50,resent101。你可以尝试这些。
- ****减少过拟合:如果你在笔记本上看集合训练的输出,你会知道我的一些模型在训练时开始过拟合。您可以尝试提前停止或退出,以减少过度拟合。
- ****训练多个 CNN 架构的系综:在准备系综的时候,我只用过 resnet34 的系综。您可以准备一个包括多种架构的系综,如 resnet50、resnet101 等。
如果你喜欢读这篇文章,请鼓掌。😃
Kaggle-竞赛-我的 ka ggle 竞赛笔记本
github.com](https://github.com/irshadqemu/Kaggle-Competitions/blob/master/Planet_amazon_resnet34.ipynb)**