栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

吴恩达机器学习笔记-无监督学习

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

吴恩达机器学习笔记-无监督学习

机器学习-无监督学习
  • 一、什么是无监督学习
  • 二、聚类算法(无监督学习)
    • 1、聚类算法的应用
    • 2、K-Means算法
      • 算法流程--图例
      • 算法流程--文字描述
      • K-means分离不佳簇问题
      • K-means代价函数
      • K-means的随机初始化
      • 如何选取聚类数量K
      • 代码实例(鸢尾花)
  • 三、降维
    • 1. 什么是降维
    • 2. 主成分分析方法(principal components analysis,PCA)
      • 文字方式描述PCA
      • PCA过程(n维数据降到k维)
    • 3. 压缩重现
    • 4. 选择K值
    • 5. 应用PCA的建议

一、什么是无监督学习

无监督学习与监督学习的对比:

(1)无监督学习

我们有一组带标签的Training Set,希望通过训练得到一条拟合Training Set的决策边界。
【即有一系列标签,然后假设函数去拟合它】

(2)无监督学习

Training Set不带标签y,无监督学习的任务就是将这些无标签的数据输入算法中,找到一些隐含在数据中的结构。
【例如:聚类算法】

二、聚类算法(无监督学习) 1、聚类算法的应用

(1)市场分割

将客户分成不同人群,针对性产品销售

(2)社会关系网划分

在社交网络中找到关系密切的朋友

2、K-Means算法 算法流程–图例
  1. 存在一些无标签的数据

    目标是将上列数据分成两簇

  2. 先假定两个聚类中心点

  3. 根据距离对数据点进行划分(染色)

  4. 重新确定新的聚类重心点(两类样本的均值)

  5. 由新的聚类中心重新划分样本

  6. 重复5、6(进行迭代),直到聚类中心不发生改变

算法流程–文字描述
  1. K-means的Input:
    (1)K:聚类的个数
    (2)Training Set:{x(1),x(2),…,x(m)}
  1. m表示训练集数据的个数
  2. x(i)是n维的,即训练集样本由n个特征feature
  1. 随机初始化K个聚类中心u1、u2、…、uk
    然后重复以下步骤:
    (1)对第1~m个样本,计算到K各聚类中心的距离||x(i)-u k||,将其划分(染色)给最接近该样本点的聚类中心【划分训练集各样本点】
    (2)对于第1~K个聚类中心,u k=第k类样本的均值【移动聚类中心】

扩展:
若存在某个聚类中心并没有分类到样本点:
(1)删去该聚类中心–>K-1个分类【通常做法】
(2)重新随机初始化这个聚类中心

K-means分离不佳簇问题

假设存在某一家服装厂,记录了客户的身高和体重;想要设计小、中、大三种尺寸的服装,该如何设计?

可以使用K-means将上图数据分成三类,再针对性的对各类样本进行尺寸设计。

K-means代价函数

c(i) :第i个样本所属的簇的索引或序号
uk :第k个聚类中心的位置
uc(i) :第i个样本所属簇的聚类中心的位置

K-means的优化目标函数:

J(c,u)表示各样本点到样本所属簇聚类中心的距离,minJ(c,u)是希望各样本点到所属簇聚类中心距离达到最小
K-means算法过程就是在最小化目标函数J(c,u)

K-means的随机初始化
  1. 应该确保K
  2. 随机选取K个训练集样本
  3. 将k个聚类中心赋值为这K个训练集样本

对于不同的初始化,可能收敛到不同的局部最优
例如下图,你可能会收敛到三种不同的分类结果

为了避免K-means落到局部最优,应该进行多次随机初始化。


例如上图,进行了100次随机初始化,得到了很多种分类结果;接下来要做的就是在很多分类结果中选取代价函数最小的一个。

当K较小时,多次随机初始化优化效果会很好;
当K较大时,多次随机初始化效果不会很明显。

如何选取聚类数量K

如下图,同一份数据可以划分成2类或者4类,这两种分类都可以说是正确的。因为这是无监督学习,因此不存在所谓的绝对正确答案。

在讨论K的选择时,一般会讨论到一个方法,叫作肘部法则

不断改变的K,画出代价函数J,根据图像选取合适的K。
如上图,在K=3时,代价函数下降缓慢,因此我们可以选择K=3。

但在实际应用中,代价函数图像并没有上述的那么"友好",如下图:

你不知道该选择3还是4,或者是5;因此肘部法制在这里并不能很好的确定K的值。

此外,你可以通过分类的后续目的去考虑K值。例如,某厂家要根据客户身高、体重来设计不同大小的尺寸。

当K=3,可把尺寸设计为S、M和L;当K=5,可把尺寸设计为XS、S、M、L、XL。
此时可以通过背后的经济价值去考虑K=3还是5。

代码实例(鸢尾花)

1、读入数据集

import pandas as pd#读入csv文件
import numpy as np#处理数据
import random #随机初始化需要使用

#导入数据集
iris = pd.read_csv("iris.csv",header=None)
iris.head(10)

数据头十行如下图所示

为了可视化,只考虑前两个特征

#读取鸢尾花的前两个特征
feature = iris.iloc[:,0:2]
#转换成数组
feature = np.array(feature)

2、随机初始化,获得K个聚类中心

'''
dataset:数据集
K:聚类中心个数
'''
def create_centrois(dataset,K):
    data = dataset[random.sample(range(0,len(dataset)),K)]
    return data

random.sample(range(0,len(dataset)),K):
随机产生K个数,范围从0到len(dataset)。代表选取数据集中的下标

3、计算欧式距离

def get_distance(dataset,centrois):
    K = len(centrois)#聚类数
    m = len(dataset)#样本个数
    #计算各样本到K个聚类中心的聚类:m*K大小的二维数组,先初始化为0
    distance = np.zeros((m,K))
    #进行K轮循环,计算各样本点到第k个聚类中心的距离
    for k in range(K):
    	#获取第k个聚类中心坐标
        center = centrois[k]
        #计算欧式距离
        #tile(a,(x,y))-->将a沿x轴扩大x倍,y轴扩大y倍
        #(tile作用就是将聚类中心坐标扩变的和数据集一样大,以进行逐位相减)
        dis = np.tile(center,(m,1))-dataset
        #平方
        sqrDis = dis**2
        #按行相加
        sqrDisSum = sqrDis.sum(axis=1)
        #赋值到distance的第k列
        distance[:,k]=sqrDisSum
    return distance

4、绘图函数

from matplotlib import pyplot as plt
'''
dataset:数据集
lab:分类结果(标签)
centers:K个聚类中心的坐标数组
dic_colors:设置颜色
'''
def draw_kmeans(dataset,lab,centers,dic_colors=None):
    #清除画布
    plt.cla()
    #转换成一维数组
    lab = lab.flatten()
    #将标签转换成列表在通过集合去重
    #val_labs表示目前有几类别,每个类别的标签
    val_labs = set(lab.tolist())
    #遍历集合val_labs
    for i,val in enumerate(val_labs):
    		#获取标签位val的样本下标
        index = np.where(lab==val)
        #将这一类样本的坐标都存到一个数组里面
        sub_dataset = dataset[index]
        #散点图绘制(这里只有两个特征)
        plt.scatter(sub_dataset[:,0],sub_dataset[:,1],s=14,color = dic_colors[i])
     #绘制聚类样本中心
    for i in range(np.shape(centers)[0]):
        plt.scatter(centers[i,0],centers[i,1],s=200,color = "k",marker="+")
    plt.show()

5、K-means函数

'''
dataset:数据集
K:聚类个数
iter:最大迭代次数(最多移动聚类中心次数)
draw:是否绘图
'''
def K_means(dataset,K,iter=20,dic_colors=None,draw=False):
	#m:样本个数;n:样本维度
    m,n = np.shape(dataset)
    
    #随机初始化聚类中心
    centrois = create_centrois(dataset,K)
    #类别标签初始化位0,表示都属于一类
    lab = np.zeros(m)
    if draw:
        #画出未分类时的数据图像
        draw_kmeans(dataset,lab,centrois,dic_colors)
     #迭代iter次,每次更新一次聚类中心
    for i in range(iter):
        #获得欧式距离
        distance = get_distance(dataset,centrois)
        
        #划分样本
        #argmin返回最小值所在的序号(列),axis=1按行比较
        #最小距离所在的序号即当前所属标签
        lab_new = np.argmin(distance,axis=1)
        
        #目标函数值
        cost = np.sum(np.min(distance,axis=1))/m
        print("第%d次聚类目标函数值为%.2f"%(i,cost))
        
        if draw:
            #第i次聚类结果
            draw_kmeans(dataset,lab,centrois,dic_colors)
            
        #计算新的聚类中心
        for k in range(K):
            index = np.where(lab_new==k)[0]
            #取均值
            centrois[k,:] = np.mean(dataset[index,:],axis=0)
        if draw:
            #新值作为聚类中心,进行绘图
            draw_kmeans(dataset,lab,centrois,dic_colors)
            
        #聚类中心不变,则退出
        if np.sum(lab_new-lab) == 0:
            return lab_new
        else:
        #聚类中心移动,进入下一次迭代
            lab = lab_new
            
    #返回分类结果
    return lab

6、调用

K_means(feature,3,20,['red','green','blue'],False)

聚类结果:

真实的聚类结果:

7、完整代码

import pandas as pd#读入csv文件
import numpy as np#处理数据
import random #随机初始化需要使用

#导入数据集
iris = pd.read_csv("iris.csv",header=None)
iris.head(10)

#读取鸢尾花的前两个特征
feature = iris.iloc[:,0:2]
#转换成数组
feature = np.array(feature)
'''
dataset:数据集
K:聚类中心个数
'''
def create_centrois(dataset,K):
    data = dataset[random.sample(range(0,len(dataset)),K)]
    return data

def get_distance(dataset,centrois):
    K = len(centrois)#聚类数
    m = len(dataset)#样本个数
    #计算各样本到K个聚类中心的聚类:m*K大小的二维数组,先初始化为0
    distance = np.zeros((m,K))
    #进行K轮循环,计算各样本点到第k个聚类中心的距离
    for k in range(K):
    	#获取第k个聚类中心坐标
        center = centrois[k]
        #计算欧式距离
        #tile(a,(x,y))-->将a沿x轴扩大x倍,y轴扩大y倍
        #(tile作用就是将聚类中心坐标扩变的和数据集一样大,以进行逐位相减)
        dis = np.tile(center,(m,1))-dataset
        #平方
        sqrDis = dis**2
        #按行相加
        sqrDisSum = sqrDis.sum(axis=1)
        #赋值到distance的第k列
        distance[:,k]=sqrDisSum
    return distance

from matplotlib import pyplot as plt
'''
dataset:数据集
lab:分类结果(标签)
centers:K个聚类中心的坐标数组
dic_colors:设置颜色
'''
def draw_kmeans(dataset,lab,centers,dic_colors=None):
    #清除画布
    plt.cla()
    #转换成一维数组
    lab = lab.flatten()
    #将标签转换成列表在通过集合去重
    #val_labs表示目前有几类别,每个类别的标签
    val_labs = set(lab.tolist())
    #遍历集合val_labs
    for i,val in enumerate(val_labs):
    		#获取标签位val的样本下标
        index = np.where(lab==val)
        #将这一类样本的坐标都存到一个数组里面
        sub_dataset = dataset[index]
        #散点图绘制(这里只有两个特征)
        plt.scatter(sub_dataset[:,0],sub_dataset[:,1],s=14,color = dic_colors[i])
     #绘制聚类样本中心
    for i in range(np.shape(centers)[0]):
        plt.scatter(centers[i,0],centers[i,1],s=200,color = "k",marker="+")
    plt.show()

'''
dataset:数据集
K:聚类个数
iter:最大迭代次数(最多移动聚类中心次数)
draw:是否绘图
'''
def K_means(dataset,K,iter=20,dic_colors=None,draw=False):
	#m:样本个数;n:样本维度
    m,n = np.shape(dataset)
    
    #随机初始化聚类中心
    centrois = create_centrois(dataset,K)
    #类别标签初始化位0,表示都属于一类
    lab = np.zeros(m)
    if draw:
        #画出未分类时的数据图像
        draw_kmeans(dataset,lab,centrois,dic_colors)
     #迭代iter次,每次更新一次聚类中心
    for i in range(iter):
        #获得欧式距离
        distance = get_distance(dataset,centrois)
        
        #划分样本
        #argmin返回最小值所在的序号(列),axis=1按行比较
        #最小距离所在的序号即当前所属标签
        lab_new = np.argmin(distance,axis=1)
        
        #目标函数值
        cost = np.sum(np.min(distance,axis=1))/m
        print("第%d次聚类目标函数值为%.2f"%(i,cost))
        
        if draw:
            #第i次聚类结果
            draw_kmeans(dataset,lab,centrois,dic_colors)
            
        #计算新的聚类中心
        for k in range(K):
            index = np.where(lab_new==k)[0]
            #取均值
            centrois[k,:] = np.mean(dataset[index,:],axis=0)
        if draw:
            #新值作为聚类中心,进行绘图
            draw_kmeans(dataset,lab,centrois,dic_colors)
            
        #聚类中心不变,则退出
        if np.sum(lab_new-lab) == 0:
            return lab_new
        else:
        #聚类中心移动,进入下一次迭代
            lab = lab_new
            
    #返回分类结果
    return lab

if __name__=="__main__":
	K_means(feature,3,20,['red','green','blue'],False)
三、降维 1. 什么是降维

例如存在两个特征x1,x2,x1表示该对象的英寸长度,x2表示该对象的厘米长度。

我们可以通过降维,将二维数据降成一维数据。只通过一个特征来表示对象的长度

降维意味着什么呢?

现在对于第i个样本x(i),可以需要二维的数据才能表示。降维后意味着仅需要一维数据z(i)就可以表示x(i),如下图。【x(i)→z(i)】
降维后,只需要一个值就可以指定在二维图中直线上的位置。

三维降成二维的例子:

图中的三维数据大致都处于一个平面,因此可以将此投影在一个二维平面上,从而降为二维的数据。
【三维投影到面,二维投影到线】

2. 主成分分析方法(principal components analysis,PCA)

对于二维的数据降维,其实就是找到一条一维的投影(线);各样本到该投影的距离最小。

所以,PCA做的就是找一条低纬平面,然后将数据投影在上面,使各样本到该投影的长度平方(投影误差)最小

文字方式描述PCA

对于2维到1维:我们需要找到一个向量u(1)【u(1)是正是负都可以,即方向不重要,投影误差最小即可】

对于高纬的数据:
从n维降到k维:找到k个向量:u(1),u(2),…,u(k);我们要将数据投影到这k个向量展开的线性子空间上。

PCA与线性回归

(1)他们想缩小的误差,在方向上不同。线性回归是缩小在x轴投影上的误差;PCA是缩小到投影线的误差。
(2)线性回归有特殊的值y,而PCA钟的变量都是平等对待的。

PCA过程(n维数据降到k维)

1、 在使用PCA之前需要对数据进行预处理,与监督学习的特征缩放相同。
(1)对于每个feature,减去其对应的均值【期望变成0】
(2)若各feature取值范围跨度差距大,除于max-min或者标准差

2、计算协方差矩阵(covariance matrix)
∑是一个n*n的矩阵

(1)前面的∑表示希腊字母σ的大写,表示协方差;后面的是求和符号。两者不相同
(2)特征缩放后期望为0,所以协方差就是两个输入的内积

3、 计算协方差矩阵(Sigma)的特征向量。
下图是octave代码

S对应的是奇异值分解中的奇异值矩阵,奇异值类似方阵中的特征值,是表示特征值向量重要程度的一个东西。S中的矩阵是按照奇异值递减排序的,所以取前k个就能得到最重要的k个向量。这k个向量作为我们降维后要用的特征向量,这k个特征向量蕴含了原来的特征的绝大部分,所以用他们来代替而不损伤太多信息。

4、奇异值分解后,从特征向量中选取前K个特征向量;得到一个n*k的矩阵,称为为U_reduce矩阵

5、降维
将U_reduce转置乘于输入x(i),得到一个k*1矩阵,从而实现降维。

3. 压缩重现

在PCA中我们将n维的输入x降到了k维的z,那能否通过k维的z返回到原来的n维x呢?
降维过程如下图所示:

U是酉矩阵,即UUT=1,上图式子右边同时乘于U得到:x_approx =U_reduce*z

关于什么是x_approx:
(1)首先z是x投影到k维平面上的坐标。例如三维降到二维,z是在二维平面上的坐标
(2)我们逆向从z推导x,逆推的是x在n维空间中的z维平面上的坐标,这个坐标就是x_approx

举个实例:x_approx就是下图图(b)坐标,而不是逆推到图(a)中的坐标

4. 选择K值


Average squared projection erro:投影后的平均均方误差。这个误差可以看作投影过后与原数据的差异程度,误差过大则原数据之间的关系信息很多都丢失了。所以我们希望Average squared projection erro越小越好

Total variation in data:训练集的总方差,也可以看作与原点之间的距离。

选择K值时希望能够满足下面的条件:

也可以不选择0.01,当我们讨论选择k时,不是直接选择k,而是要选择0.01这个数字或者其他数字。

这里选择了0.01,用术语说是保留了99%的方差特性。或者用另一种PCA的说法是99%的差异值被保留下来了。
大于等于85%的值都是比较典型的,95%-99%是比较常用的。

选择实现过程

从k=1开始计算这个数值,若不等式不成立则让k=2,k=3……,假设到k=17时满足了不等式则用17作为k值。

但是这种选择算法效率并不高,好在奇异值分解svd可以让这个事好算很多


SVD会返回三个值,其中S是一个对角矩阵,对于给定的k,我们可以将不等式左部进行替换,如下图:

从而验证下图式子即可:

选择满足不等式的最小k值即可

这样就可以只调用一次svd函数得到S矩阵,迭代计算S矩阵中的数值

5. 应用PCA的建议

通常运用PCA对监督学习算法进行加速。

例如下图,在监督学习原始训练集数据中,输入x是10000维的数据,数量级很大训练过程会很复杂;可以通过PCA降维成1000维的数据集,降低了训练的复杂性。

PCA做的是寻找x到z的映射,对于测试集中的样本,也应该经过PCA降维后再输入到假设模型中。

PCA的应用:
(1)能进行压缩,减少存储空间
(2)加快算法速度
(3)可视化数据

PCA的错误用法:去防止过拟合:

推荐使用正则化来防止过拟合

在使用PCA前应该先考虑完整的原始数据是否能满足你的需要;当内存不够或训练速度过慢才应该考虑PCA。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/980024.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号