Python 人工智能 - 无监督学习:聚类

无监督机器学习算法没有任何监督者提供任何形式的指导。这就是为什么它们与某些人所说的真正的人工智能密切相关。

在无监督学习中,没有正确答案,也没有老师提供指导。算法需要发现数据中有趣的模式才能学习。

什么是聚类?

基本上,它是一种无监督学习方法,也是许多领域中使用的统计数据分析的常用技术。聚类主要是一项将一组观察结果划分为子集(称为聚类)的任务,这样同一聚类中的观察结果在某种意义上是相似的,而与其他聚类中的观察结果不同。简单来说,我们可以说聚类的主要目标是根据相似性和不相似性对数据进行分组。

例如,下图显示了不同聚类中的类似数据 −

Clustering

数据聚类算法

以下是一些常见的数据聚类算法 −

K-Means 算法

K-means 聚类算法是众所周知的数据聚类算法之一。我们需要假设聚类的数量是已知的。这也称为平面聚类。它是一种迭代聚类算法。对于此算法,需要遵循下面给出的步骤 −

步骤 1 −我们需要指定所需的 K 个子组数量。

步骤 2 − 固定簇的数量并将每个数据点随机分配给一个簇。或者换句话说,我们需要根据簇的数量对数据进行分类。

在此步骤中,应计算簇质心。

由于这是一种迭代算法,我们需要在每次迭代中更新 K 个质心的位置,直到找到全局最优值,或者换句话说,质心达到其最佳位置。

以下代码将有助于在 Python 中实现 K-means 聚类算法。我们将使用 Scikit-learn 模块。

让我们导入必要的包 −

import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
import numpy as np
from sklearn.cluster import KMeans

以下代码行将通过使用 sklearn.dataset 包中的 make_blob 来帮助生成包含四个 blob 的二维数据集。

from sklearn.datasets.samples_generator import make_blobs

X, y_true = make_blobs(n_samples = 500, centers = 4,
            cluster_std = 0.40, random_state = 0)

我们可以使用以下代码可视化数据集 −

plt.scatter(X[:, 0], X[:, 1], s = 50);
plt.show()
K 均值算法

在这里,我们将 kmeans 初始化为 KMeans 算法,所需参数为有多少个簇 (n_clusters)。

kmeans = KMeans(n_clusters = 4)

我们需要使用输入数据训练 K-means 模型。

kmeans.fit(X)
y_kmeans = kmeans.predict(X)
plt.scatter(X[:, 0], X[:, 1], c = y_kmeans, s = 50, cmap = 'viridis')

centers = kmeans.cluster_centers_

下面给出的代码将帮助我们根据我们的数据绘制和可视化机器的发现,并根据要找到的聚类数量进行拟合。

plt.scatter(centers[:, 0], centers[:, 1], c = 'black', s = 200, alpha = 0.5);
plt.show()
K Means algorithm2

均值偏移算法

这是另一种流行且强大的无监督学习聚类算法。它不做任何假设,因此它是一种非参数算法。它也被称为层次聚类或均值偏移聚类分析。以下是该算法的基本步骤 −

  • 首先,我们需要从分配给其自身集群的数据点开始。

  • 现在,它计算质心并更新新质心的位置。

  • 通过重复此过程,我们更接近集群的峰值,即朝向更高密度的区域。

  • 该算法在质心不再移动的阶段停止。

借助以下代码,我们在 Python 中实现 Mean Shift 聚类算法。我们将使用 Scikit-learn 模块。

让我们导入必要的包 −

import numpy as np
from sklearn.cluster import MeanShift
import matplotlib.pyplot as plt
from matplotlib import style
style.use("ggplot")

以下代码将有助于使用 sklearn.dataset 包中的 make_blob 生成包含四个 blob 的二维数据集。

from sklearn.datasets.samples_generator import make_blobs

我们可以使用以下代码可视化数据集

centers = [[2,2],[4,5],[3,10]]
X, _ = make_blobs(n_samples = 500, centers = centers, cluster_std = 1)
plt.scatter(X[:,0],X[:,1])
plt.show()
Mean Shift 算法

现在,我们需要使用输入数据训练 Mean Shift 聚类模型。

ms = MeanShift()
ms.fit(X)
labels = ms.labels_
cluster_centers = ms.cluster_centers_

以下代码将根据输入数据打印聚类中心和预期聚类数量 −

print(cluster_centers)
n_clusters_ = len(np.unique(labels))
print("估计的聚类:", n_clusters_)
[[ 3.23005036 3.84771893]
[ 3.02057451 9.88928991]]
估计的聚类:2

下面给出的代码将有助于根据我们的数据绘制和可视化机器的发现,并根据要找到的聚类数量进行拟合。

colors = 10*['r.','g.','b.','c.','k.','y.','m.']
   for i in range(len(X)):
   plt.plot(X[i][0], X[i][1], colors[labels[i]], markersize = 10)
plt.scatter(cluster_centers[:,0],cluster_centers[:,1],
   marker = "x",color = 'k', s = 150, linewidths = 5, zorder = 10)
plt.show()
簇数

测量聚类性能

现实世界的数据并非自然地组织成许多不同的簇。由于这个原因,它不容易可视化和得出推论。这就是为什么我们需要测量聚类性能及其质量。这可以借助轮廓分析来完成。

轮廓分析

此方法可用于通过测量簇之间的距离来检查聚类的质量。基本上,它提供了一种通过给出轮廓分数来评估簇数等参数的方法。该分数是一个衡量一个簇中每个点与相邻簇中点的接近程度的指标。

轮廓分数分析

分数范围为 [-1, 1]。以下是对这个分数 − 的分析

  • 分数为 +1 − 接近 +1 的分数表示样本距离相邻簇较远。

  • 分数为 0 − 分数为 0 表示样本位于或非常接近两个相邻簇之间的决策边界。

  • 分数为 -1 − 负分数表示样本被分配到了错误的簇。

计算轮廓分数

在本节中,我们将学习如何计算轮廓分数。

轮廓分数可以使用以下公式计算 −

$$silhouette score = \frac{\left ( p-q \right )}{max\left ( p,q \right )}$$

这里,𝑝 是到数据点不属于的最近簇中点的平均距离。而 𝑞 是到其自身簇中所有点的平均簇内距离。

为了找到最佳簇数,我们需要通过从 sklearn 包中导入 metrics 模块再次运行聚类算法。在下面的例子中,我们将运行 K-means 聚类算法来找到最佳聚类数 −

按照图示导入必要的包 −

import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
import numpy as np
from sklearn.cluster import KMeans

借助以下代码,我们将使用 sklearn.dataset 包中的 make_blob 生成包含四个 blob 的二维数据集。

from sklearn.datasets.samples_generator import make_blobs

X, y_true = make_blobs(n_samples = 500, centers = 4, cluster_std = 0.40, random_state = 0)

初始化变量,如图所示 −

scores = []
values = np.arange(2, 10)

我们需要遍历 K-means 模型中的所有值,还需要使用输入数据对其进行训练。

for num_clusters in values:
kmeans = KMeans(init = 'k-means++', n_clusters = num_clusters, n_init = 10)
kmeans.fit(X)

现在,使用欧几里得距离度量 − 估计当前聚类模型的轮廓分数

score = metrics.silhouette_score(X, kmeans.labels_,
metric = 'euclidean', sample_size = len(X))

以下代码行将有助于显示聚类数量以及轮廓分数。

print("\nNumber of clusters =", num_clusters)
print("Silhouette score =", score)
scores.append(score)

您将收到以下输出 −

Number of clusters = 9
Silhouette score = 0.340391138371

num_clusters = np.argmax(scores) + values[0]
print('\nOptimal number of clusters =', num_clusters)

现在,最佳聚类数的输出如下 −

Optimal number of clusters = 2

查找最近邻居

如果我们想要构建推荐系统(例如电影推荐系统),那么我们需要了解查找最近邻居的概念。这是因为推荐系统利用了最近邻居的概念。

查找最近邻居的概念可以定义为从给定数据集中查找距离输入点最近的点的过程。此 KNN)K 最近邻居)算法的主要用途是构建分类系统,根据输入数据点与各种类别的接近程度对数据点进行分类。

下面给出的 Python 代码有助于查找给定数据集的 K 最近邻居 −

导入必要的包,如下所示。在这里,我们使用 sklearn 包中的 NearestNeighbors 模块

import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import NearestNeighbors

现在让我们定义输入数据 −

A = np.array([[3.1, 2.3], [2.3, 4.2], [3.9, 3.5], [3.7, 6.4], [4.8, 1.9], 
             [8.3, 3.1], [5.2, 7.5], [4.8, 4.7], [3.5, 5.1], [4.4, 2.9],])

现在,我们需要定义最近邻居 −

k = 3

我们还需要提供测试数据,以便从中找到最近邻居 −

test_data = [3.3, 2.9]

以下代码可以可视化和绘制我们定义的输入数据 −

plt.figure()
plt.title('输入数据')
plt.scatter(A[:,0], A[:,1], marker = 'o', s = 100, color = 'black')
Finding Nearest Neighbors

现在,我们需要构建 K 最近邻。对象也需要进行训练

knn_model = NearestNeighbors(n_neighbors = k, algorithm = 'auto').fit(X)
distances, indices = knn_model.kneighbors([test_data])

现在,我们可以按如下方式打印 K 个最近邻居

print("\nK Nearest Neighbors:")
	for rank, index in enumerate(indices[0][:k], start = 1):
print(str(rank) + " is", A[index])

我们可以将最近邻居与测试数据点一起可视化

plt.figure()
plt.title('Nearest neighbors')
plt.scatter(A[:, 0], X[:, 1], marker = 'o', s = 100, color = 'k')
plt.scatter(A[indices][0][:][:, 0], A[indices][0][:][:, 1],
   marker = 'o', s = 250, color = 'k', facecolors = 'none')
plt.scatter(test_data[0], test_data[1],
   marker = 'x', s = 100, color = 'k')
plt.show()
测试数据点

输出

K Nearest Neighbors

1 is [ 3.1 2.3]
2 is [ 3.9 3.5]
3 is [ 4.4 2.9]

K-最近邻分类器

K-最近邻 (KNN) 分类器是一种使用最近邻算法对给定数据点进行分类的分类模型。我们在上一节中实现了 KNN 算法,现在我们将使用该算法构建 KNN 分类器。

KNN 分类器的概念

K-最近邻分类的基本概念是找到一个预定义的数量,即距离要分类的新样本最近的训练样本的"k"减号。新样本将从邻居本身获得标签。KNN 分类器具有固定的用户定义常数,用于确定必须确定的邻居数量。对于距离,标准欧几里得距离是最常见的选择。KNN 分类器直接对学习到的样本进行操作,而不是创建学习规则。KNN 算法是所有机器学习算法中最简单的算法之一。它在大量分类和回归问题中取得了相当大的成功,例如字符识别或图像分析。

示例

我们正在构建一个 KNN 分类器来识别数字。为此,我们将使用 MNIST 数据集。我们将在 Jupyter Notebook 中编写此代码。

导入必要的包,如下所示。

这里我们使用 sklearn.neighbors 包中的 KNeighborsClassifier 模块 −

from sklearn.datasets import *
import pandas as pd
%matplotlib inline
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
import numpy as np

以下代码将显示数字图像以验证我们要测试的图像 −

def Image_display(i):
   plt.imshow(digit['images'][i],cmap = 'Greys_r')
   plt.show()

现在,我们需要加载 MNIST 数据集。实际上总共有 1797 张图像,但我们使用前 1600 张图像作为训练样本,其余 197 张将用于测试目的。

digit = load_digits()
digit_d = pd.DataFrame(digit['data'][0:1600])

现在,在显示图像时,我们可以看到输出如下 −

Image_display(0)

Image_display(0)

0 的图像显示如下 −

Image_display(0)

Image_display(9)

9 的图像显示如下−

Image_display(9)

digit.keys()

现在,我们需要创建训练和测试数据集,并将测试数据集提供给 KNN 分类器。

train_x = digit['data'][:1600]
train_y = digit['target'][:1600]
KNN = KNeighborsClassifier(20)
KNN.fit(train_x,train_y)

以下输出将创建 K 最近邻分类器构造函数−

KNeighborsClassifier(algorithm = 'auto', leaf_size = 30, metric = 'minkowski',
   metric_params = None, n_jobs = 1, n_neighbors = 20, p = 2,
   weights = 'uniform')

我们需要通过提供大于 1600 的任意数字来创建测试样本,这些数字是训练样本。

test = np.array(digit['data'][1725])
test1 = test.reshape(1,-1)
Image_display(1725)

Image_display(6)

6 的图像显示如下 −

Image_display(6)

现在我们将预测测试数据如下 −

KNN.predict(test1)

上述代码将生成以下输出 −

array([6])

现在,考虑以下 −

digit['target_names']

上述代码将生成以下输出 −

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])