本文已参与「新人创作礼」活动,一起开启掘金创作之路。
机器学习入门(一) 无监督学习
写在前面
本文从机器学习大方向着手,分三篇,从无监督,有监督,强化学习三大部分介绍最简单的概念和知识,涉及部分数学推导和代码。主要参考:北理工礼欣老师的MOOC《Python机器学习应用》,布客飞龙译《写给人类的机器学习》,吴恩达老师机器学习教程中文笔记-在线版
无监督学习:无标签分类
聚类(clustering):将数据按相似度分成不同的分组
原理:根据定义的“距离”,评估相似性
- 欧式距离:即直线相连距离
- 曼哈顿距离:沿着坐标轴走直线,将每个维度的差绝对值相加
- 马氏距离:协方差距离,尺度无关,下面是某知乎用户的回答,“将变量按照主成分进行旋转,让维度间相互独立,然后进行标准化,让维度同分布就OK了”
- 夹角余弦:a和b的点乘,考虑了夹角关系
算法:这里以Sklearn.cluster中提供的几个算法+常用聚类算法为例
-
K-means
-
提供聚类个数,不断调整聚类中心的算法。该算法的输出是一组「标签」,这些标签将每个数据点都分配到了 K 组中的一组。在 K 均值聚类中,这些组的定义方式是为每个组创造一个重心(centroid)。这些重心就像是聚类的心脏,它们可以「捕获」离自己最近的点并将其加入到自己的聚类中。
-
步骤:随意选定重心-所有点加入最近的点(通常是按照欧几里得距离计算的)-重心移动至每类中心。重复2,3步骤,直到每次迭代时重心位置不再显著变化。
-
调包使用示意:
if __name__ == '__main__': # 自己写的函数,生成列表 data,cityName = loadData('city.txt') # KMeans(n_clusters聚类数,[init=k-means++聚类方法,max_iter=300迭代次数]) km = KMeans(n_clusters=4) # 计算中心并分配序号,对应了后面的label[i]为相应的簇 label = km.fit_predict(data) # axis按行求和 expenses = numpy.sum(km.cluster_centers_,axis=1) CityCluster = [[],[],[],[]] for i in range(len(cityName)): CityCluster[label[i]].append(cityName[i]) for i in range(len(CityCluster)): print("Expenses:%.2f" % expenses[i]) print(CityCluster[i])
-
-
DBSCAN:
- 原理:基于密度,提供最大距离,样本数(几个点落入),方式。
- 步骤:分核心点(在半径EPS内含有超过MINPTS数目的点),边界点(落在核心点内但邻域内,但不是核心点),噪音点(不是核心点,也不是边界点),然后不断合并核心点,删除噪音点。这里我想着重学习的是其归属的**“层次聚类”算法,专业一点来说,层次聚类通过计算不同类别数据点间的相似度来创建一棵有层次的嵌套聚类树**。层次聚类的好处是不需要指定具体类别数目的,其得到的是一颗树,聚类完成之后,可在任意层次横切一刀,得到指定数目的簇。这两篇文章从不同角度分析了几种层次分类的方法:数据挖掘入门笔记——层次聚类 ( 浮光掠影),聚类算法之层次聚类(Python实现)
- 补充:更多关于具体的DBSCAN算法,可见这个链接。
-
Gaussian Mixtures:复杂度高,不适合大规模,马氏距离。
-
Birch:欧氏距离。
降维(reducing dimensionality):在保留数据结构和有用性的同时对数据进行压缩
原理:数据可视化&精简数据
- 大多数情况下,降维是为聚类服务的,但某种程度和聚类相通,比如聚类是对类别变量做降维的方法之一。
- 根本目的是为了在尽可能保存相关的结构的同时降低数据的复杂度。
算法:主成分分析和奇异值分解
-
主成分分析PCA:
-
简介:中心化,协方差矩阵,对应的特征向量的特征值大小排序,最大的为主成分。“PCA的工作就是从原始的空间中顺序地找一组相互正交的坐标轴,新的坐标轴的选择与数据本身是密切相关的。其中,第一个新坐标轴选择是原始数据中方差最大的方向,第二个新坐标轴选取是与第一个坐标轴正交的平面中使得方差最大的,第三个轴是与第1,2个轴正交的平面中方差最大的。依次类推,可以得到n个这样的坐标轴。通过这种方式获得的新的坐标轴,我们发现,大部分方差都包含在前面k个坐标轴中,后面的坐标轴所含的方差几乎为0。于是,我们可以忽略余下的坐标轴,只保留前面k个含有绝大部分方差的坐标轴。”该方法常用于数据压缩,预处理,信号处理。
-
步骤:先补一下线性代数🤡,里边的一句话可以很清晰地表述出我们需要进行的工作——“我们通过特征值分解得到的前N个特征向量,就对应了这个矩阵最主要的N个变化方向。而特征值表示的是这个特征到底有多么重要。我们利用这前N个变化方向,就可以近似这个矩阵变换。也就是之前说的:提取这个矩阵最重要的特征。”然后就是特征值的求法和特征向量的求法啦。要充分体会特征值的意义,即将当前坐标系投影至另一个坐标系,存在这样一个向量只放缩而没有旋转,
Ax=λx,其中A就是要投影过去的坐标基向量,x为特征向量,λ就是特征值,而为了方便计算,因为E除了对角元之外都是0所以我们将λ=λE,上式也就是最熟悉的|A-λE|x=0。这是通用的求法,如果还不懂,可以看这个知乎回答,太好了写的。 -
计算过程:
- 来源于PCA(主成分分析)过程详解,其中协方差矩阵的表征的是特征与样本之间的相似相关程度,而方差越大说明该特征对样本的影响越大,特征值分解的意义是找到对应的一组基使得原矩阵表示为 Q ∑ Q − 1 Q\sum Q^{-1} Q∑Q−1的形式,即该矩阵作用于任意一个点,相当于对他们先旋转变化至某个向量空间(基向量),再拉伸,最后还原。而通过特征值分解得到的前N个特征向量,就对应了这个矩阵最主要的N个变化方向。
- 举例说明:
- 来源于PCA(主成分分析)过程详解,其中协方差矩阵的表征的是特征与样本之间的相似相关程度,而方差越大说明该特征对样本的影响越大,特征值分解的意义是找到对应的一组基使得原矩阵表示为 Q ∑ Q − 1 Q\sum Q^{-1} Q∑Q−1的形式,即该矩阵作用于任意一个点,相当于对他们先旋转变化至某个向量空间(基向量),再拉伸,最后还原。而通过特征值分解得到的前N个特征向量,就对应了这个矩阵最主要的N个变化方向。
-
程序调包:
import matplotlib.pyplot as plt from sklearn.decomposition import PCA from sklearn.datasets import load_iris data = load_iris() y = data.target X = data.data # 降维后主成分为2 pca = PCA(n_components=2) reduced_X = pca.fit_transform(X) red_x, red_y = [], [] blue_x, blue_y = [], [] green_x, green_y = [], [] for i in range(len(reduced_X)): if y[i] == 0: red_x.append(reduced_X[i][0]) red_y.append(reduced_X[i][1]) elif y[i] == 1: blue_x.append(reduced_X[i][0]) blue_y.append(reduced_X[i][1]) else: green_x.append(reduced_X[i][0]) green_y.append(reduced_X[i][1]) # 数据可视化 plt.scatter(red_x, red_y, c='r', marker='x') plt.scatter(blue_x, blue_y, c='b', marker='D') plt.scatter(green_x, green_y, c='g', marker='.') plt.show() -
-
奇异值分解SVD:
- 简介:主要用于主要用在降维算法中的特征分解、推荐系统、自然语言处理计算机视觉,本质上还是保留主要特征(这里称之为基),先直观感受一下这个比喻“橡皮筋的拉伸”。
其数学原理如下(我听的这个up主讲的),其中对角矩阵的作用是拉伸,正交矩阵的意义就是旋转,我们想要找到的就是一组基,这样的一组基在经过变换后仍然保持正交,它们分别的长度变化就称为奇异值!可以看出,奇异值决定了形变,大小决定在形变中的重要性。
下面这张图是公式的推导,M经过线性变换(相当于投影到v1v2方向)所得到的那个扁扁的椭圆,可以表示为同样的另一组正交的u1u2方向,分别在各自方向进行拉伸后得到的椭圆。而v1v2就是那组基,经过线性变换成了u1u2。正交矩阵的转置就是其逆矩阵,所以M=UΣVt这个式子就推出来啦。 - 步骤:过后再补,没听明白
- 和PCA的联系以及区别:
- 上代码:这是一个用于图片压缩的
import numpy as np import numpy.linalg as la import matplotlib.pyplot as plt from sklearn import datasets from skimage import io def getImgAsMat(index): ds = datasets.fetch_olivetti_faces() return np.mat(ds.images[index]) def getImgAsMatFromFile(filename): img = io.imread(filename, as_grey=True) return np.mat(img) def plotImg(imgMat): plt.imshow(imgMat, cmap=plt.cm.gray) plt.show() def recoverBySVD(imgMat, k): # singular value decomposition U, s, V = la.svd(imgMat) # choose top k important singular values (or eigens) Uk = U[:, 0:k] Sk = np.diag(s[0:k]) Vk = V[0:k, :] # recover the image imgMat_new = Uk * Sk * Vk return imgMat_new A = getImgAsMatFromFile('D:/pic.jpg') plotImg(A) A_new = recoverBySVD(A, 30) plotImg(A_new) - 简介:主要用于主要用在降维算法中的特征分解、推荐系统、自然语言处理计算机视觉,本质上还是保留主要特征(这里称之为基),先直观感受一下这个比喻“橡皮筋的拉伸”。
-
FastLCA:图形图像。
-
NMF:非负矩阵分解,将原图像分解为一个基础图像矩阵和系数矩阵相乘,以提取特征的不同之处。图形图像,文本挖掘,语音处理。
-
LDA:文本数据。