【机器学习】吴恩达作业7.0,python实现kmeans聚类

目录

无监督学习

自监督学习的区别:

聚类算法实现场景:

k_means:无监督分类算法,不需要标签集

k_means算法流程

簇内平方和 

计算新的聚类中心点

防止陷入局部最优解的方法

 python语法

代码 

1 导入数据及可视化 

2 簇分配,计算聚类中心,执行kmeans过程 

 3 绘制kmeans过程

案例 对图片颜色进行聚类  

 降维,可视化自己的图片

7.0 k-means聚类以及图像压缩

使用k-means聚类算法并且将其应用于压缩图像。在第二部分中你将使用主成分分析来找到脸部图像的一个低维表示。
第一部分为k-means聚类,首先从一个2维的样本集开始,他可以帮助你对k-means算法有一个直观的感受。然后你将使用k-means算法对图像进行压缩,通过减少颜色数量,直到只出现在该图像中最常见的那些颜色。

无监督学习

根据类别未知(没有被标记)的训练样本解决模式识别中的各种问题,称之为无监督学习,“监督”的意思可以直观理解为“是否有标注的数据”。

无监督学习的特点是,传递给算法的数据在内部结构中非常丰富,而用于训练的目标和奖励非常稀少。无监督学习算法学到的大部分内容必须包括理解数据本身,而不是将这种理解应用于特定任务。

聚类是无监督学习的常见任务,就是将观察值聚成一个一个的组,每一个组都含有一个或者几个特征,‎聚类的目的在于‎‎把相似的东西聚在一起,而我们并不关心这一类是什么‎‎。 因此,一个聚类算法通常只需要知道‎‎如何计算相似度‎‎就可以开始工作了。‎例如无监督学习应该能在不给任何额外提示的情况下,仅依据一定数量的“狗”的图片特征,将“狗”的图片从大量的各种各样的图片中将区分出来。

自监督学习的区别

1 对训练集与测试集的使用方式不同。
监督学习的目的是在训练集中找规律,然后对测试集运用这种规律。而无监督学习没有训练集,只有一组数据所构成的数据集,在该组数据集内寻找规律。
2 训练集是否有标签。
有监督学习的识别的结果表现在:给待识别数据加上标签,因此训练集必须由带标签的样本组成。而无监督学习方法只有要分析的数据集的本身,预先没有标签。如果发现数据集呈现某种聚集性,则可按自然的聚集性分类,但不按照某种预先定义的分类标签进行标注。
3 无监督学习方法是在数据集中寻找规律性。
这种规律性并不一定要达到划分数据集的目的,也就是说不一定要“分类”。比如,一组颜色各异的积木,它可以按形状为维度来分类,也可以按颜色为维度来分类 。而有监督学习则是通过对有标签的数据集进行训练得到一个最优模型。

https://blog.csdn.net/qq_37635772/article/details/110731807

聚类算法实现场景:

市场划分 社交网络用户划分 大型计算机集成系统管理 天文数据分析

k_means:无监督分类算法,不需要标签集

k_means算法流程

1 给一个无标签的数据集,随机初始化K个聚类中心,即质心

2 簇分配:遍历所有数据,将数据划分到最近的聚类中心

3 计算所有类的平均值,作为新的聚类中心

4 重复簇分配和计算聚类中心两个步骤,直到聚类中心不再变化,达到设定的迭代次数

簇内平方和 

计算每个样本点到每类聚类中心点的距离(损失函数)

聚类算法追求“簇内差异小,簇外差异大”。而这个“差异“,由样本点到其所在簇的质心的距离来衡量。

对于一个簇来说,所有样本点到质心的距离之和越小,我们就认为这个簇中的样本越相似,簇内差异就越小。而距离的衡量方法有多种,令表示簇中的一个样本点,表示该簇中的质心,n表示每个样本点中的特征数目,i表示组成点的每个特征,则该样本点到质心的距离可以由以下距离来度量:

 m为一个簇中样本的个数,j是每个样本的编号。这个公式被称为簇内平方和(cluster Sum of Square),又叫做Inertia。表示的是簇中某一点到簇中距离的和,统计学中 “和方差”、“簇内离差平方和”(SSE)在这里指同一意思。而将一个数据集中的所有簇的簇内平方和相加,就得到了整体平方和(Total Cluster Sum of Square),又叫做total inertia。Total Inertia越小,代表着每个簇内样本越相似,聚类的效果就越好。因此KMeans追求的是,求解能够让Inertia最小化的质心。实际上,在质心不断变化不断迭代的过程中,总体平方和是越来越小的。我们可以使用数学来证明,当整体平方和最小的时候,质心就不再发生变化了。如此,K-Means的求解过程,就变成了一个最优化问题。

损失函数:

c^{i} = j that minimizes \left \| x^{i}-\mu _{c^{i}} \right \|^{2}

计算新的聚类中心点

\mu k = \frac{1}{\left | C_{k} \right |}\sum _{i\epsilon C_{k}}X^{(i)}

C^{^{(i)}} :x^{(i)}被划分到的簇的序号

\mu _{k}  :第K个聚类中心

\mu _{C^{i}}  :表示x^{(i)}所属簇的聚类中心

 

防止陷入局部最优解的方法

尝试多次(100次)初始化k-means算法并实现,选择代价函数最小的作为最优解。一般对于聚类中心在2-10比较有效。

 

 python语法

1.np.argmin函数返回最小值的索引。

np.linalg.norm()用于求范数linalg本意为linear(线性) + algebra(代数)norm则表示范数。np.linalg.norm(x, ord=None, axis=None, keepdims=False)

x: 表示矩阵(一维数据也是可以)
ord: 表示范数类型

3  matplotlib.image程序包中 mpimg.imread函数,读取图片,imsave函数,保存图片。

代码 

1 导入数据及可视化 

import numpy as np
import matplotlib.pyplot as plt
import scipy.io as sio

data = sio.loadmat('ex7data2.mat')
data.keys()#dict_keys(['__header__', '__version__', '__globals__', 'X'])

X = data['X']
X.shape

def plot_data(x):
    plt.scatter(X[:,0],X[:,1],label = 'train',marker='o', c='y', edgecolors='g')
    plt.show

plot_data(X)

 

2 簇分配,计算聚类中心,执行kmeans过程 

#簇分配
def find_centroids(X,centros):
    idx = []
    for i in range(len(X)):
        #X[i](2,)centros(k,2)=>(k,2)
#计算距离
        dist  = np.linalg.norm((X[i]-centros),axis = 1)#(k,)
        id_i = np.argmin(dist)
        idx.append(id_i)
    return np.array(idx)

#初始聚类中心
centros = np.array([[3,3],[6,2],[8,5]])
idx = find_centroids(X,centros)
idx[:3]

#计算聚类中心
def compute_centros(X,idx,k):
    centros = []
    for i in range(k):
        centros_ = np.mean(X[idx == i],axis = 0)
        centros.append(centros_)
    return centros

compute_centros(X,idx,k = 3)
#[array([2.42830111, 3.15792418]),
 array([5.81350331, 2.63365645]),
 array([7.11938687, 3.6166844 ])]

#执行k—means过程
def run_kmeans(X,centros,iters):
    k = len(centros)
    centros_all = []
    centros_all.append(centros)
    centros_i  = centros
    for i in range(iters):
        idx = find_centroids(X,centros_i)
        centros_i  = compute_centros(X,idx,k)
        centros_all.append(centros_i)
    return idx,np.array(centros_all)

 3 绘制kmeans过程

#绘制数据集和聚类中心的移动轨迹
def plot_data1(X,centros_all,idx):
    plt.figure()
    plt.scatter(X[:,0],X[:,1],c= idx,cmap = 'rainbow')#数据集颜色根据x类别来区分
    plt.plot(centros_all[:,:,0],centros_all[:,:,1],'kx--')

idx,centros_all = run_kmeans(X,centros,iters = 100)
plot_data1(X,centros_all,idx)

案例 对图片颜色进行聚类  

#案例:使用kmeans对图片颜色进行聚类
#RGB图像,每个像素点值范围0-255
data = sio.loadmat('bird_small.mat')
data
data.keys()#dict_keys(['__header__', '__version__', '__globals__', 'A'])

A = data['A']
A.shape#(128, 128, 3)

#初始化聚类中心
def kMeansInitCentroids(x, K):
    randidx = np.random.permutation(x) #随机排列
    centroids = randidx[:K, :] #选前K个
    return centroids
#方法二
# def inti_centroids(X,k):
#     index  = np.random.choice(len(X),k)
#     return X[index]

from skimage import io

image = io.imread('bird_small.png')#读取图片
plt.imshow(image)
plt.axis('off')#去掉坐标轴
plt.show()
A = A/255  #标准化   #使得像素数据为0-1之间
A = A.reshape(-1,3)  #reshape(-1, 3)表示行数由Numpy自动计算,3列
A.shape#(16384, 3)

k = 16  #16种颜色
centroids = kMeansInitCentroids(A, K = 16)
centroids.shape

idx,centros_all = run_kmeans(A,centroids,iters = 20)
centros = centros_all[-1]#取迭代完的最后一个
im = np.zeros(A.shape)
for i in range(k):
    im[idx == i] = centros[i]
im = im.reshape(128,128,3)
plt.imshow(im)

 降维,可视化自己的图片

#降维并可视化自己的图片
import matplotlib.image as mpimg #用于读取、保存图片
from sklearn.cluster import MiniBatchKMeans #Mini Batch K-Means聚类


#picture = A #优化上面的图片
picture = mpimg.imread('R-C.jpg') #读取图片
picture #查看下是不是0-1之间
data = picture/255 #如果是0-255的话需要除以255,如果已经是0-1就不需要
data = data.reshape(data.shape[0]*data.shape[1],3) 

'''用sklearn中的MiniBatchKMeans'''
#MiniBatchKMeans聚类
kmeans = MiniBatchKMeans(k) 
kmeans.fit(data) #先fit
picture_recolored = kmeans.cluster_centers_[kmeans.predict(data)] #再predict,然后再分配标记的聚类中心的RGB编码
picture_recolored = picture_recolored.reshape(picture.shape)

#画图
fig, axes = plt.subplots(1, 2, figsize=(10,10))
axes[0].imshow(picture)
axes[0].set_title('Original')
axes[1].imshow(picture_recolored)
axes[1].set_title('Compressed, with %d colors'%k)#.set_title可以给子图加标题。

#保存,观察文件大小是否变化
mpimg.imsave('IMG_4994_recoverd.jpeg', picture_recolored)

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值