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:无监督分类算法,不需要标签集
1 给一个无标签的数据集,随机初始化K个聚类中心
2 簇分配:遍历所有数据,将数据划分到最近的聚类中心
3 计算所有类的平均值,作为新的聚类中心
4 重复簇分配和计算聚类中心两个步骤,直到聚类中心不再变化,达到设定的迭代次数
计算每个样本点到每类聚类中心点的距离(损失函数)
that minimizes
计算新的聚类中心点
:被划分到的簇的序号
:第K个聚类中心
:表示所属簇的聚类中心
防止陷入局部最优解的方法
尝试多次(100次)初始化k-means算法并实现,选择代价函数最小的作为最优解。一般对于聚类中心在2-10比较有效。
python语法
1.np.argmin函数返回最小值的索引。
2 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)
yuzu!!!!耶!!!!!!!!!!!