无监督学习

2019-04-14 19:33发布

1、无监督学习的类型
无监督学习常见的两种类型是:数据集变换和聚类。
数据集变换,就是创建数据集新的表示算法,与数据的原始原始表示相比,新的表示可能更容易被人或其他机器学习算法所理解。
常见的应用有降维,就是对于许多特征表示的高维数据,找到表示该数据的一种新方法,用较少的特征就可以概括其重要特性。另一个应用就是找到“构成”数据的各个组成部分,比如对文本文档的关键字提取。
聚类就是将数据划分成不同的组,每组包含相似的物项。举个例子,在社交平台上传的照片,网站可能想要将同一个人的照片分在一组。但网站并不知道每张照片是谁,也不知道你的照片集中出现了多少个人。明智的做法是提取所有的人脸,并将看起来相似的人脸分在一组。但愿这些人脸对应同一个人,这样图片的分组也就完成了。
2、无监督学习的挑战
无监督学习的一个主要挑战就是评估算法是否学到了有用的东西。无监督学习算法一般用于不包含任何标签信息的数据,所以我们不知道正确的输出应该是什么。因此很难判断一个模型是否“表现很好”。例如,假设我们的聚类算法已经将所有的侧脸照片和所有的正面照片进行分组。这肯定是人脸照片集合的一种可能的划分方法,但并不是我们想要的那种方法。然而,我们没有办法“告诉”算法我们要的是什么,通常来说,评估无监督算法结果的唯一方法就是人工检查。
因此,无监督算法通常可用于探索性的目的, 而不是作为大型自动化系统的一部分。无监督算法的另一个常见应用是作为监督算法的预处理步骤。学习数据的一种新表示,有时可以提高监督算法的精度,或者可以减少内存占用和时间开销。
3、预处理与缩放
3.1 不同类型的预处理
7820436-b3984154257bfdcb.png 不用类型的预处理
在上图中,左侧的显示的是一个模拟的有两个特征的二分类数据集。数据的第一个特征(x轴)位于 10 到 15 之间。第二个特征(y 轴)大约位于 1 到 9 之间。
右侧的4个图,对应的是4种不同的数据变换方法,而且都生成了更加标准的范围。
a、scikit-learn 中 的 StandardScaler 确保每个特征的平均值为 0、方差为 1,使所有特征都位于同一量级。但这种缩放不能保证特征任何特定的最大值和最小值。
b、RobustScaler 的工作原理与 StandardScaler 类似,确保每个特征的统计属性都位于同一范围。但 RobustScaler 使用的是中位数和四分位数,而不是平均值和方差。这样 RobustScaler 会忽略与其他点有很大不同的数据点(比如测量误差)。这些与众不同的数据点也叫异常值(outlier),可能会给其他缩放方法造成麻烦。(对于一组数字来说,中位数指的是这样的数值 x:有一半数值小于 x,另一半数值大于 x。较小四分 位数指的是这样的数值 x:有四分之一的数值小于 x。较大四分位数指的是这样的数值 x:有四分之 一的数值大于 x)
c、MinMaxScaler 移动数据,使所有特征都刚好位于 0 到 1 之间。对于二维数据集来说,所有的数据都包含在 x 轴 0 到 1 与 y 轴 0 到 1 组成的矩形中。
d、Normalizer 用到一种完全不同的缩放方法。它对每个数据点进行缩放,使得特征向量的欧式长度等于 1。换句话说,它将一个数据点投射到半径为 1 的圆上(对于更高维度的情况,是球面)。这意味着每个数据点的缩放比例都不相同(乘以其长度的倒数)。如果只有数据的方向(或角度)是重要的,而特征向量的长度无关紧要,那么通常会使用这种归一化。 3.2 对训练数据和测试数据进行相同的缩放 import mglearn import matplotlib.pyplot as plt from sklearn.datasets import make_blobs from sklearn.model_selection import train_test_split from sklearn.preprocessing import MinMaxScaler # 构造数据 X, _ = make_blobs(n_samples=50, centers=5, random_state=4, cluster_std=2) # 将其分为训练集和测试集 X_train, X_test = train_test_split(X, random_state=5, test_size=.1) # 绘制训练集和测试集 fig, axes = plt.subplots(1, 3, figsize=(13, 4)) axes[0].scatter(X_train[:, 0], X_train[:, 1], c=mglearn.cm2(0), label="Training set", s=60) axes[0].scatter(X_test[:, 0], X_test[:, 1], marker='^', c=mglearn.cm2(1), label="Test set", s=60) axes[0].legend(loc='upper left') axes[0].set_title("Original Data") # 利用MinMaxScaler缩放数据 scaler = MinMaxScaler() # 使用 fit 方法拟合缩放器(scaler),并将其应用于训练数据 scaler.fit(X_train) X_train_scaled = scaler.transform(X_train) X_test_scaled = scaler.transform(X_test) # 将正确缩放的数据可视化 axes[1].scatter(X_train_scaled[:, 0], X_train_scaled[:, 1], c=mglearn.cm2(0), label="Training set", s=60) axes[1].scatter(X_test_scaled[:, 0], X_test_scaled[:, 1], marker='^', c=mglearn.cm2(1), label="Test set", s=60) axes[1].set_title("Scaled Data") # 单独对测试集进行缩放 # 使得测试集的最小值为0,最大值为1 # 千万不要这么做!这里只是为了举例 test_scaler = MinMaxScaler() test_scaler.fit(X_test) X_test_scaled_badly = test_scaler.transform(X_test) # 将错误缩放的数据可视化 axes[2].scatter(X_train_scaled[:, 0], X_train_scaled[:, 1], c=mglearn.cm2(0), label="training set", s=60) axes[2].scatter(X_test_scaled_badly[:, 0], X_test_scaled_badly[:, 1], marker='^', c=mglearn.cm2(1), label="test set", s=60) axes[2].set_title("Improperly Scaled Data") for ax in axes: ax.set_xlabel("Feature 0") ax.set_ylabel("Feature 1") plt.show() 7820436-a4d27d1f38994c95.png 对左图中的训练数据和测试数据同时缩放的效果(中)和分别缩放的效果(右)
第一张图是未缩放的二维数据集,其中训练集用圆形表示,测试集用三角形表示。
第二张图中是同样的数据,但使用 MinMaxScaler 缩放。这里我们调用 fit 作用在训练集上,然后调用 transform 作用在训练集和测试集上。你可以发现,第二张图中的数据集看起来与第 一张图中的完全相同,只是坐标轴刻度发生了变化。现在所有特征都位于 0 到 1 之间。还可以发现,测试数据(三角形)的特征最大值和最小值并不是 1 和 0。
第三张图展示了如果我们对训练集和测试集分别进行缩放会发生什么。在这种情况下,对 训练集和测试集而言,特征的最大值和最小值都是 1 和 0。但现在数据集看起来不一样。 测试集相对训练集的移动不一致,因为它们分别做了不同的缩放。我们随意改变了数据的排列。这显然不是想要的数据。
根据上图,我们得出的结论就是,对于数据的缩放,我们需要对测试数据进行缩放,而fit的作用都是在训练数据上,而不是单独为测试数据创建新的缩放。
4、降维、特征提取与流形分析
4.1 主成分分析PCA
主成分分析是一种旋转数据集的方法,旋转后的特征在统计上不相关。在做完这种旋转之后,通常是根据新特征对解释数据的重要性来选择它的一个子集。 4.2 非负矩阵分解NMF
非负矩阵分解(NMF)是另一种无监督学习算法,其目的在于提取有用的特征。它的工作原理类似于 PCA,也可以用于降维。
与 PCA 相同,我们试图将每个数据点写成一些分量的加权求和。但在 PCA 中,我们想要的是正交分量,并且能够解释尽可能多的数据方差;而在 NMF 中,我们希望分量和系数均为非负,也就是说,我们希望分量和系数都大于或等于 0。因此,这种方法只能应用于每个特征都是非负的数据,因为非负分量的非负求和不可能变为负值。
将数据分解成非负加权求和的这个过程,对由多个独立源相加(或叠加)创建而成的数据特别有用,比如多人说话的音轨或包含多种乐器的音乐。在这种情况下,NMF 可以识别出组成合成数据的原始分量。总的来说,与 PCA 相比,NMF 得到的分量更容易解释,因为负的分量和系数可能会导致难以解释的抵消效应。 4.3 用t-SNE进行流形学习
t-SNE 背后的思想是找到数据的 一个二维表示,尽可能地保持数据点之间的距离。t-SNE 首先给出每个数据点的随机二维 表示,然后尝试让在原始特征空间中距离较近的点更加靠近,原始特征空间中相距较远的 点更加远离。t-SNE 重点关注距离较近的点,而不是保持距离较远的点之间的距离。换句 话说,它试图保存那些表示哪些点比较靠近的信息。
5、聚类
聚类是将数据集划分成组的任务,这些组叫作簇。 其目标是划分数据,使得一个簇内的数据点非常相似且不同簇内的数据点非常不同。与分类算法类似,聚类算法为每个数据点分配(或预测)一个数字,表示这个点属于哪个簇。
5.1 k均值聚类
k 均值聚类是最简单也最常用的聚类算法之一。它试图找到代表数据特定区域的簇中心 。算法交替执行以下两个步骤:将每个数据点分配给最近的簇中心,然后将每个簇中心设置为所分配的所有数据点的平均值。如果簇的分配不再发生变化,那么算法结束。 5.2 凝聚聚类
凝聚聚类指的是许多基于相同原则构建的聚类算法,这一原则是:算法首先声明每个点是自己的簇,然后合并两个最相似的簇,直到满足某种停止准则为止。 scikit-learn 中实现的停止准则是簇的个数,因此相似的簇被合并,直到仅剩下指 定个数的簇。还有一些链接(linkage)准则,规定如何度量“最相似的簇”。这种度量总是定义在两个现有的簇之间。 5.3 DBSCAN
另一个非常有用的聚类算法是 DBSCAN(即“具有噪声的基于密度的空间聚类应用”)。DBSCAN 的主要优点是它不需要用户先验地设置簇的个数,可以划分具有复杂形状的簇,还可以找出不属于任何簇的点。 DBSCAN 比凝聚聚类和 k 均值稍慢,但仍可以扩展到相对较大的数据集。
DBSCAN 的原理是识别特征空间的“拥挤”区域中的点,在这些区域中许多数据点靠近在一起。这些区域被称为特征空间中的密集区域。DBSCAN 背后的思想是,簇形成数据的密集区域,并由相对较空的区域分隔开。
在密集区域内的点被称为核心样本(或核心点),它们的定义如下。DBSCAN 有两个参数: min_samples 和 eps。如果在距一个给定数据点 eps 的距离内至少有 min_ samples 个数据点,那么这个数据点就是核心样本。DBSCAN 将彼此距离小于 eps 的核心样本放到同一个簇中。
算法首先任意选取一个点,然后找到到这个点的距离小于等于 eps 的所有的点。如果距起始点的距离在 eps 之内的数据点个数小于 min_samples,那么这个点被标记为噪声(noise),也就是说它不属于任何簇。如果距离在 eps 之内的数据点个数大于 min_ samples,则这个点被标记为核心样本,并被分配一个新的簇标签。然后访问该点的所有邻居(在距离 eps 以内)。如果它们还没有被分配一个簇,那么就将刚刚创建的新的簇标 签分配给它们。如果它们是核心样本,那么就依次访问其邻居,以此类推。簇逐渐增大, 直到在簇的 eps 距离内没有更多的核心样本为止。然后选取另一个尚未被访问过的点, 并重复相同的过程。
最后,一共有三种类型的点:核心点、与核心点的距离在 eps 之内的点(叫作边界点, boundary point)和噪声。如果 DBSCAN 算法在特定数据集上多次运行,那么核心点的聚 类始终相同,同样的点也始终被标记为噪声。但边界点可能与不止一个簇的核心样本相 邻。因此,边界点所属的簇依赖于数据点的访问顺序。一般来说只有很少的边界点,这种 对访问顺序的轻度依赖并不重要。