在我的前几篇文章中,我研究了机器学习以及如何构建一个以某种方式描述世界的模型。我研究的所有例子都是“监督学习”,这意味着您加载的数据已经以某种方式被分类或归类,然后创建一个模型来“学习”输入映射到输出的方式。有了好的模型,您就可以预测新输入集的输出。

监督学习是一种非常有用的技术,并且非常普及。但是,机器学习中还有另一组称为无监督学习的技术。广义而言,这些技术要求计算机找到数据中隐藏的结构——换句话说,要“学习”数据的含义、它包含的关系、哪些特征是重要的,以及哪些数据记录应被视为异常值或异常。

无监督学习也可以用于所谓的“降维”,其中模型充当预处理步骤,减少特征的数量,以简化您将交给另一个模型的输入。

换句话说,在监督学习中,您教计算机关于您的数据,并希望它能够充分理解关系和分类,从而成功地对它以前未见过的数据进行分类。

相比之下,在无监督学习中,您要求计算机告诉您一些关于数据的有趣之处。

本月,我对无监督学习的世界进行了初步的了解。计算机能否像人类一样对数据进行分类?您如何使用 Python 的 scikit-learn 来创建这样的模型?

无监督学习

有一种名为Set的儿童纸牌游戏,它可以帮助您思考机器学习。游戏中的每张牌都包含一张图片。图片包含一个、两个或三个形状。有几种不同的形状,并且每个形状都有颜色和填充图案。在游戏中,玩家应该使用这些属性中的任何一个来识别三张牌的组合。因此,您可以创建一个基于绿色的组,其中所有卡片都是绿色的(但包含不同数量的形状、形状和填充图案)。您可以创建一个基于形状数量的组,其中每张卡片都有两个形状,但这些形状可以是任何颜色、任何形状和任何填充图案。

这个游戏背后的想法是,玩家可以创建各种不同的组,并且应该利用这一点来赢得游戏。

我经常将无监督学习视为要求计算机玩Set游戏。您给计算机一个数据集,并要求它将大量数据分成不同的类别。该模型可以选择任何特征或特征集,而这可能(也可能不)是人类认为重要的特征。但是,它会找到那些联系,或者至少尝试这样做。

对于初学者来说,最常见的机器学习模型之一是“iris”数据集,其中包含 150 朵花,每种鸢尾花 50 朵。几个月前,我展示了如何创建一个监督模型来识别鸢尾花。换句话说,您可以创建和训练一个模型,该模型可以根据鸢尾花的花瓣和萼片大小准确地对其进行分类。

无监督学习能否实现相同的目标?也就是说,您能否创建一个模型,将花朵分成三个不同的组,做与人类所做的工作相同(或接近)的工作?

提出这个问题的另一种方式是,生物学家区分花卉品种的方式是否得到底层测量数据的支持。

让我们加载 iris 数据,然后开始创建一个无监督模型。假设我在 Jupyter 笔记本中工作,我可以执行以下操作


%pylab inline
import pandas as pd
from pandas import DataFrame, Series

from sklearn.datasets import load_iris
iris = load_iris()

df = DataFrame(iris.data, columns=iris.feature_names)
df['response'] = iris.target

换句话说,我已经创建了一个 Pandas 数据帧,其中包含五列——四个特征以及响应(即分类)。您不会将分类传递给模型(尽管这可能会提高模型对花卉进行分类的能力),但以这种方式将所有内容放在一起很方便。

创建模型

加载数据后,就该创建模型了。您正在寻找做所谓的“聚类”,这意味着计算机将数据集划分为类别或集群。

那么,现在怎么办?在监督学习中,您将从分类器创建一个新模型,然后使用 scikit-learn 的“fit”方法对其进行训练。然后,您可以给训练好的模型一个或多个数据点,并要求它根据模型对这些数据点进行分类。

在无监督学习中,这有点棘手——毕竟,您要求计算机进行分类。如果您没有任何预先标记的类别,就很难知道您的模型是否有用、准确或两者兼而有之。

但在进入评估之前,让我们构建一个模型。Sklearn 附带了许多处理聚类的分类器。一种流行的分类器称为“K 均值”。在 K 均值聚类中,其思想是模型将每个数据点放入均值最接近的集群中。因此,如果有三个集群,则每个集群将包含计算出最接近的点。“惯性”是对组的连贯性的度量——也就是说,已分组在一起的元素彼此之间有多密切的关联。

我应该注意到,由于 K 均值使用距离来计算如何组成一个组,因此您可能希望所有特征都处于相同的尺度上。在花卉的情况下,所有特征都在相同的数量级内。但是,您可以想象,如果三个测量值在 1-10 的尺度上,而第四个测量值在 1-100 万的尺度上,则计算可能无法很好地进行。因此,使用标量可能是一个好主意——sklearn 附带了几个标量——将所有数据都放在相同的尺度上。这种缩放在创建模型时通常很重要;它有助于计算识别两个或多个项目是否彼此靠近。

因此,使用 Python 的 scikit-learn,您可以说


from sklearn.cluster import KMeans
k = KMeans(n_clusters=3)

上面的代码表明您将使用 K 均值算法。您创建一个新模型,并在创建模型时指示您想要三个组。

现在,您可能会立即问自己如何知道会有三个类别——而权宜之计的答案是您猜测。您可以尝试n_clusters的不同值,并评估模型以查看其效果如何。但在许多情况下,您将不得不进行一些实验。

现在让我们在数据上运行 K 均值。X(即输入矩阵)将是数据帧,减去“response”列。您可以按如下方式创建它


X = df.drop('response', axis=1)

在监督学习中,“fit”方法是您教模型建立输入矩阵 X 和输出向量 y 之间关联的过程。在无监督学习中,您要求模型本身进行这种划分并创建输出向量。您可以使用“fit”来做到这一点


k.fit(X)

评估模型

您将问模型的第一个问题是:“它是如何划分花朵的?”您知道鸢尾花应该分为三个不同的组,每组 50 朵花。K 均值做得怎么样?

您可以使用各种属性来询问模型本身。这些属性通常以下划线 (_) 结尾,表明它们可能会随着模型的更多训练而不断变化。

的确,这是要强调的重要一点。当您调用“fit”方法时,您是从头开始教模型。但是,有时您有如此多的数据,以至于无法合理地一次教完模型。对于这种情况,您可能需要尝试一种支持“partial_fit”方法的算法,该方法允许您一次抓取一点输入,迭代地教模型。但是,并非所有算法都支持 partial_fit;大量的数据点可能会迫使您做出选择,并减少您可以选择的算法数量。

对于此示例,以及 K 均值的情况,您无法增量地教模型。让我们向模型询问其惯性度量


k.inertia_

(再次注意尾部的下划线。)我得到的值是 0.78.9。惯性值不在尺度上;一般感觉是惯性分数越低越好,零是最好的。

如果我将花朵仅分为两组或四组怎么办?使用 scikit-learn,我可以非常快速地做到这一点,并确定计算机是否认为手动分类(分为三组)是一个不错的选择


output = [ ]
for i in range(2,20):
    model = KMeans(n_clusters=i)
    model.fit(X)
    output.append((i, model.inertia_))
kmeans = DataFrame(output, columns=['i', 'inertia'])

现在,将 150 朵花分成最多 19 个不同的组似乎很荒谬!的确,当我设置n_clusters=19时,我得到的最低惯性值,而惯性值随着组数的减少而上升。

也许这意味着每朵花都是独一无二的,无法分类?也许是这样。但这似乎更可能是我们的数据不适合 K 均值。也许它的形状不对。也许它的值变化不够大。的确,当您查看 n_clusters=3 的花朵聚类方式时,您会发现聚类与人们提出的聚类方式截然不同。我可以将自动标记的花朵变成 Pandas Series,然后计算每种花朵的数量


Series(k.labels_).value_counts()

我得到


2    62
1    50
0    38

好吧,情况可能会更糟——但也可能会好得多。也许您可以并且应该尝试另一种算法,看看它是否能更好地将花朵分组在一起。

我应该注意到,这现在属于“半监督学习”的范畴——也就是说,尝试查看无监督技术是否可以达到与以前使用的监督技术相同的结果,或者至少是相似的结果。

在这种情况下,您不仅可以使用统计测试来评估您的模型,还可以使用我在之前关于监督学习的文章中描述的技术之一,即 train-test-split。您对一部分输入数据使用无监督学习,然后对剩余部分进行预测。将模型的输出与该子集的预期输出进行比较可以帮助您评估和调整模型。

不同的算法

但在这种情况下,让我们尝试使用不同的模型来实现不同的结果,只是为了看看 sklearn 让您多么容易地尝试不同的模型。无监督学习中的一个常见选择是高斯混合,在以前版本的 scikit-learn 中称为 GMM。让我们使用它


from sklearn.mixture import GaussianMixture
model = GaussianMixture(n_components=3)
model.fit(X)

现在,让模型使用用于训练它的数据进行预测,这将返回一个包含类别的 NumPy 数组


model.predict(X)

效果如何?让我们将此数据放入 Pandas Series 对象中,然后计算值


Series(model.predict(X)).value_counts()

果然,结果


2    55
1    50
0    45

这仍然是不完美的——假设人类的分类算作“完美”,但它显然比 K 均值的尝试要好。而且由于这里是半监督学习,您拥有一些原始分数,因此您可以使用 sklearn 的一些指标来查找模型的好坏


from sklearn import metrics
labels_true = iris.target
labels_pred = model.predict(X)

让我们找出它的效果如何


metrics.homogeneity_score(labels_true, labels_pred)
0.89832636726027748

metrics.completeness_score(labels_true, labels_pred)
0.90106489086402064

嘿,非常好!不是完美的(即 1.0),但还不错。如果您将其与 K 均值模型进行比较


labels_pred = k.labels_
metrics.homogeneity_score(labels_true, labels_pred)
0.75148540219883375

metrics.completeness_score(labels_true, labels_pred)
0.76498615144898152

换句话说,我的直觉是正确的。GaussianMixture 模型比 K 均值模型更擅长聚类花朵。

结论

在许多方面,无监督学习是机器学习世界中真正的魔力和潜力。通过使用计算机比您自己更快更准确地识别数据中的模式和组,您可以开始识别和预测各种事物。但是,与监督学习一样,无监督学习也要求您尝试各种模型,将它们相互比较,并了解每个模型都有其自身的优点、缺点和偏差。

总的来说,数据科学领域,尤其是机器学习领域,继续以极快的速度增长,新的想法、技术和教程不断涌现。此处的“资源”部分介绍了几个您可以了解更多信息并开始您在这组概念和技术中的旅程的地方。

资源

我在本文中使用了 Python 和 SciPy 堆栈的许多部分(NumPy、SciPy、Pandas、Matplotlib 和 scikit-learn)。所有这些都可以从 PyPISciPy.org 获得

我为对数据科学和机器学习感兴趣的人推荐了一些资源。

一个长期存在的每周电子邮件列表是 “KDNuggets”。您还应该考虑 “Data Science Weekly” 新闻通讯和 “This Week in Data”,其中介绍了最新的公开数据集。

我是播客的忠实粉丝,我特别喜欢“Partially Derivative”。其他好的播客有“Data Stories”和“Linear Digressions”。我定期收听所有这三个播客,并从中学习。

如果您想进入数据科学和机器学习领域,我推荐 Kevin Markham 的 Data School 和 Jason Brownlie 的 Machine Learning Mastery",他在那里销售了许多关于这些主题的简短而密集的,但高质量的电子书。

Reuven Lerner 在世界各地的公司教授 Python、数据科学和 Git。您可以订阅他的免费每周“更好的开发者”电子邮件列表,并从他的书籍和课程中学习,网址为 http://lerner.co.il。Reuven 与他的妻子和孩子住在以色列的莫迪因。

加载 Disqus 评论