Machine Learning(吴恩达<五>K-means和PCA)

目录

无监督学习1--聚类

什么是无监督学习?

聚类有哪些应用?

 K-means算法

语言表述步骤

 伪代码表示k-means的过程

 常应用来解决分离不佳的簇的问题

优化目标

 随机初始化

如何使算法避免局部最优解?

选取聚类数量

"肘部法则"

无监督学习2--降维

目标1---数据压缩

目标2---可视化

 PCA(也叫 主成分分析)

主成分分析问题规划1

PCA问题的公式描述

 PCA与线性回归

主成分分析问题规划2

数据处理

 总结

主成分数量选择

压缩重现

 应用PCA的建议

K-means应用ex7

1.一个简单的二维数据集

2.应用于图像压缩

PCAex7

1.将PCA应用于一个简单的二维数据集

2.将PCA应用于脸部图像


无监督学习1--聚类

什么是无监督学习?

训练集只有x1,x2...,xi,没有标签y的数据。

我们要将无标签的数据输入,然后让算法找到一些隐含在数据中的结构,

把这些无标签的数据分成一簇一簇的,就是聚类算法(学习的第一个无监督学习的算法)。

聚类有哪些应用?

 K-means算法

语言表述步骤

给定一组未加标签的数据集,希望有一个算法能够自动的讲这些数据分成有紧密关系的子集或簇

K-means算法 是目前比较热门,应用较多的算法之一。 

K-mean步骤:假如下图我想把数据分成两个簇

首先随机生成两点,这两点叫做聚类中心,K-means是一个迭代算法,做两件事:第一件 簇分配,第二个 移动聚类中心簇分类时:需要遍历每个数据,根据它与两个随机点的距离那个近,就把这个数据分配给那个点。移动聚类中心:找到所有同颜色的点计算其均值的位置为新的聚类中心。然后再次计算每个点距离中心点的距离分,重复这两个步骤,直到中心点不再改变

 

 

 伪代码表示k-means的过程

说明:假设uk是某个簇的均值,如果存在一个没有点的聚类中心,直接移除这个聚类中心,最终会得到K-1个簇;如果想要最终的到K个簇,那么需要重新初始化聚类中心;但最常见的做法,一般是直接移除。

 

 常应用来解决分离不佳的簇的问题

例如将根据体重设计衣服的尺寸(S,L,M)

优化目标

K:表示簇的数量;k:表示聚类中心点的下标,c^i:表示xi被划分到第几个簇。

K-means的代价函数为下图中的J,算法最终要找到c^i,μ_i,即能最小化J的参数值。这个代价函数有时也叫做 失真代价函数K-means的失真。 J->畸变函数

 随机初始化

如何使算法避免局部最优解?

初始化点不同,结果也不同。

初始化选择的点可能会使结果陷入局部最优,如下图右下角两张图所示。

 要避免陷入局部最优,我们需要做多次初始化而不是一次。来保证最终得到的是最优的。

常见的初始化次数在 50到1000次。当然如果K比较小,次数少一些。

选取聚类数量

 目前还没有可以自动选择聚类的数目的算法,需要通过可视化数据或观察聚类的输出来选择(手动)

"肘部法则"

如果得到左图的曲线,是好的,但通常得到的图是右图,无法判断那个点,所以相当于啥都没做。

因此不要期望它每次都有用。

 下面仍然以衣服尺寸聚类为例:

衣服的销售量可能会帮你决定分成几类,怎样利用后续的目的决定什么样的衣服作为评价标准来选择聚类数。手动选择时,想想聚类的目的是什么

无监督学习2--降维

目标1---数据压缩

压缩可以减小占用的空间,可以使学习算法运行的更快。

图一-->图二(将数据投影到一个平面)-->最后降到二维空间表示

目标2---可视化

 

 PCA(也叫 主成分分析)

主成分分析问题规划1

PCA问题的公式描述

公式描述即用公式描述PCA的用途。  Principal component analysis(主成分分析)

数学证明过于复杂,因此这里没有数学证明u和z为什么可以这么用。

如下图:对于一个二维数据我们想找到一条直线,将点投影到这条直线上,它会找到一个低维平面(这里是一条直线),将点投影到这个面上,每个点与投影之间的距离叫做"投影误差",PCA会选择误差平方最小的面或线作为投影面或线,以便最小化平法投影误差。 

 PCA与线性回归

首先,PCA不是线性回归,他们是两种不同的算法,他们计算的误差是不一样的,如下图所示。

主成分分析问题规划2

数据处理

无监督学习中,均值标准化过程(使每个特征具有均值为0的特点)特征缩放(根据数据集决定)过程很相似。

 计算u^(i),z的描述过程如下图,协方差∑(大写的σ:一个协方差矩阵)表示,式子左边为协方差,右面是求和符号。svd:表示奇异值分解。不同语言找有这个功能的库就行了。

 总结

进行均值归一化后为确保每一个特征都是均值为0的。根据数据范围任选特征缩放。预处理完后计算载体矩阵Sigma,通过这个方法,如果你的数据 是被给予作为一个矩阵如图中的X训练集矩阵,然后我们先得到要降维矩阵U的前k列,z=..定义了我们如何从一个特征向量x到降维的表示z。

主成分数量选择

我们希望在平均 均方误差与训练集方差的比例尽可能小的情况下选择尽可能小的 k值(从n个特征降到k个特征)如果我们希望这个比例小于1%,就意味着原本数据的偏差有99%都保留下来了,如果我们选择保留90%的偏差,便能非常显著地降低模型中特征的维度了。

 我们可以先令k=1,然后进行主成分分析,获得U_{reduce}Ureduce​和z,然后计算比例是否小于1%。如果不是的话再令k=2,依次类推,直到找到可以使得比例小于1%的最小k值(因为各个特征之间通常情况存在某种相关性).其中的 S是一个n×n 的矩阵只有对角线上有值,而其它单元都是 0,我们可以使用这个矩阵来计算平均均方误差与训练集方差的比例:

即:

压缩重现

重现即怎么从压缩后的数据得到之前的数据表示?

 应用PCA的建议

首先,我们尝尝使用PCA加速无监督学习算法。假设你有一个监督学习的数据,其中x^i有很高的维度,实际中这可能是一个计算机视觉的问题。即假设我们有一张 100×100 像素的图片包含10000 个像素强度值,对于这种很高维的特征向量,运行学习算法时很慢。这是用PCA降低它的维度,步骤如下:

  • 首先,抽出x,不看y;运用PCA将数据压缩至1000个特征

  • 然后,对训练集运行某个学习算法:逻辑回归、SVM、神经网络等

  • 最后,如果有一个新的样本,将新的测试样本x经过PAC的映射关系进行映射获得相应的z,然后把z带到假设函数中

  • note:PCA定义一个从x到z的映射,这个映射只能通过在训练集上运行PCA来定义。所做的是计算一系列参数进行特征缩放和均值归一化,它还计算矩阵U_reduce(只能从训练集上训练得出)错误的使用PCA的情况:

  • 认为PCA是一种防止过拟合的方法。防止过拟合的最好的办法 正则化。原因在于PCA只是近似地丢弃掉一些特征,它并不考虑任何与y有关的影响,因此可能会丢失非常重要的特征

  • 默认地将PCA作为学习过程中的一部分,这虽然很多时候有效果,建议在使用PCA前先从所有原始特征开始,只在当你确定用x无法运行时(算法运行太慢或者占用太多内存)再考虑采用PCA。

  • 总:PCA应用于提高算法运行效率、数据压缩、可视化。

K-means应用ex7

1.一个简单的二维数据集

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sb
from scipy.io import loadmat

def find_closest_centroids(X, centroids):
    m = X.shape[0]
    k = centroids.shape[0]
    idx = np.zeros(m)
    
    for i in range(m):
        min_dist = 1000000
        for j in range(k):
            dist = np.sum((X[i,:] - centroids[j,:]) ** 2)
            if dist < min_dist:
                min_dist = dist
                idx[i] = j
    
    return idx

data = loadmat('E:/Python/machine learning/data/ex7data2.mat')
X = data['X']
initial_centroids = initial_centroids = np.array([[3, 3], [6, 2], [8, 5]])

idx = find_closest_centroids(X, initial_centroids)
idx[0:3]
array([0., 2., 1.])
data2 = pd.DataFrame(data.get('X'), columns=['X1', 'X2'])
data2.head()
X1X2
01.8420804.607572
15.6585834.799964
26.3525793.290854
32.9040174.612204
43.2319794.939894
#数据可视化
sb.set(context="notebook", style="white")
sb.lmplot('X1', 'X2', data=data2, fit_reg=False)
plt.show()

def compute_centroids(X, idx, k):
    m, n = X.shape
    centroids = np.zeros((k, n))
    
    for i in range(k):
        indices = np.where(idx == i)
        centroids[i,:] = (np.sum(X[indices,:], axis=1) / len(indices[0])).ravel()
    
    return centroids

compute_centroids(X, idx, 3)
array([[1.95399466, 5.02557006],
       [3.04367119, 1.01541041],
       [6.03366736, 3.00052511]])
# 将样本分配给最近的簇并重新计算簇的聚类中心
def run_k_means(X, initial_centroids, max_iters):
    m, n = X.shape
    k = initial_centroids.shape[0]
    idx = np.zeros(m)
    centroids = initial_centroids
    
    for i in range(max_iters):
        idx = find_closest_centroids(X, centroids)
        centroids = compute_centroids(X, idx, k)
    
    return idx, centroids

idx, centroids = run_k_means(X, initial_centroids, 10)

cluster1 = X[np.where(idx == 0)[0],:]
cluster2 = X[np.where(idx == 1)[0],:]
cluster3 = X[np.where(idx == 2)[0],:]

fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(cluster1[:,0], cluster1[:,1], s=30, color='r', label='Cluster 1')
ax.scatter(cluster2[:,0], cluster2[:,1], s=30, color='g', label='Cluster 2')
ax.scatter(cluster3[:,0], cluster3[:,1], s=30, color='b', label='Cluster 3')
ax.legend()
plt.show()

# 创建一个选择随机样本并将其用作初始聚类中心的函数

def init_centroids(X, k):
    m, n = X.shape
    centroids = np.zeros((k, n))
    idx = np.random.randint(0, m, k)
    
    for i in range(k):
        centroids[i,:] = X[idx[i],:]
    
    return centroids

init_centroids(X, 3)
array([[3.18412176, 1.41410799],
       [1.30882588, 5.30158701],
       [1.95538864, 1.32156857]])

2.应用于图像压缩

这里需要暗转skimage,但直接安装会报错,需要先pip install scikit-image 这个需要等一段时间,之后再 pip install skimage,我的安装有问题。呜呜呜

from IPython.display import Image
Image(filename='E:/Python/machine learning/data/bird_small.png')

# 原始像素测像素点数值
image_data = loadmat('E:/Python/machine learning/data/bird_small.mat')
image_data
{'__header__': b'MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Tue Jun  5 04:06:24 2012',
 '__version__': '1.0',
 '__globals__': [],
 'A': array([[[219, 180, 103],
         [230, 185, 116],
         [226, 186, 110],
         ...,
         [ 14,  15,  13],
         [ 13,  15,  12],
         [ 12,  14,  12]],
 
        [[230, 193, 119],
         [224, 192, 120],
         [226, 192, 124],
         ...,
         [ 16,  16,  13],
         [ 14,  15,  10],
         [ 11,  14,   9]],
 
        [[228, 191, 123],
         [228, 191, 121],
         [220, 185, 118],
         ...,
         [ 14,  16,  13],
         [ 13,  13,  11],
         [ 11,  15,  10]],
 
        ...,
 
        [[ 15,  18,  16],
         [ 18,  21,  18],
         [ 18,  19,  16],
         ...,
         [ 81,  45,  45],
         [ 70,  43,  35],
         [ 72,  51,  43]],
 
        [[ 16,  17,  17],
         [ 17,  18,  19],
         [ 20,  19,  20],
         ...,
         [ 80,  38,  40],
         [ 68,  39,  40],
         [ 59,  43,  42]],
 
        [[ 15,  19,  19],
         [ 20,  20,  18],
         [ 18,  19,  17],
         ...,
         [ 65,  43,  39],
         [ 58,  37,  38],
         [ 52,  39,  34]]], dtype=uint8)}
A = image_data['A']
A.shape
(128, 128, 3)
# 对数据应用一些预处理,并将其提供给K-means算法

# normalize value ranges
A = A / 255.

# reshape the array
X = np.reshape(A, (A.shape[0] * A.shape[1], A.shape[2]))
print(X.shape)

# randomly initialize the centroids
initial_centroids = init_centroids(X, 16)

# run the algorithm
idx, centroids = run_k_means(X, initial_centroids, 10)

# get the closest centroids one last time
idx = find_closest_centroids(X, centroids)

# map each pixel to the centroid value
X_recovered = centroids[idx.astype(int),:]
print(X_recovered.shape)

# reshape to the original dimensions
X_recovered = np.reshape(X_recovered, (A.shape[0], A.shape[1], A.shape[2]))
print(X_recovered.shape)
(16384, 3)
(16384, 3)
(128, 128, 3)
plt.imshow(X_recovered)
plt.show()

不知道为啥我运行出来就成黑的了

正常应该是这样的:

# 可以看到我们对图像进行了压缩,但图像的主要特征仍然存在
# 这就是K-means 下面我们来用scikit-learn来实现K-means
from skimage import io

# cast to float, you need to do this otherwise the color would be weird after clustring
pic = io.imread('E:/Python/machine learning/data/bird_small.png') / 255.
io.imshow(pic)
plt.show()

print(pic.shape)

# serialize data
data = pic.reshape(128*128, 3)

print(data.shape)

from sklearn.cluster import KMeans#导入kmeans库

model = KMeans(n_clusters=16, n_init=100, n_jobs=-1)

model.fit(data)
(128, 128, 3)
(16384, 3)
KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,
    n_clusters=16, n_init=100, n_jobs=-1, precompute_distances='auto',
    random_state=None, tol=0.0001, verbose=0)
centroids = model.cluster_centers_
print(centroids.shape)

C = model.predict(data)
print(C.shape)

print(centroids[C].shape)

compressed_pic = centroids[C].reshape((128,128,3))

fig, ax = plt.subplots(1, 2)
ax[0].imshow(pic)
ax[1].imshow(compressed_pic)
plt.show()

 PCAex7

1.将PCA应用于一个简单的二维数据集

# PCA1
data = loadmat('E:/Python/machine learning/data/ex7data1.mat')
data
{'__header__': b'MATLAB 5.0 MAT-file, Platform: PCWIN64, Created on: Mon Nov 14 22:41:44 2011',
 '__version__': '1.0',
 '__globals__': [],
 'X': array([[3.38156267, 3.38911268],
        [4.52787538, 5.8541781 ],
        [2.65568187, 4.41199472],
        [2.76523467, 3.71541365],
        [2.84656011, 4.17550645],
        [3.89067196, 6.48838087],
        [3.47580524, 3.63284876],
        [5.91129845, 6.68076853],
        [3.92889397, 5.09844661],
        [4.56183537, 5.62329929],
        [4.57407171, 5.39765069],
        [4.37173356, 5.46116549],
        [4.19169388, 4.95469359],
        [5.24408518, 4.66148767],
        [2.8358402 , 3.76801716],
        [5.63526969, 6.31211438],
        [4.68632968, 5.6652411 ],
        [2.85051337, 4.62645627],
        [5.1101573 , 7.36319662],
        [5.18256377, 4.64650909],
        [5.70732809, 6.68103995],
        [3.57968458, 4.80278074],
        [5.63937773, 6.12043594],
        [4.26346851, 4.68942896],
        [2.53651693, 3.88449078],
        [3.22382902, 4.94255585],
        [4.92948801, 5.95501971],
        [5.79295774, 5.10839305],
        [2.81684824, 4.81895769],
        [3.88882414, 5.10036564],
        [3.34323419, 5.89301345],
        [5.87973414, 5.52141664],
        [3.10391912, 3.85710242],
        [5.33150572, 4.68074235],
        [3.37542687, 4.56537852],
        [4.77667888, 6.25435039],
        [2.6757463 , 3.73096988],
        [5.50027665, 5.67948113],
        [1.79709714, 3.24753885],
        [4.3225147 , 5.11110472],
        [4.42100445, 6.02563978],
        [3.17929886, 4.43686032],
        [3.03354125, 3.97879278],
        [4.6093482 , 5.879792  ],
        [2.96378859, 3.30024835],
        [3.97176248, 5.40773735],
        [1.18023321, 2.87869409],
        [1.91895045, 5.07107848],
        [3.95524687, 4.5053271 ],
        [5.11795499, 6.08507386]])}
X = data['X']

fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(X[:, 0], X[:, 1])
plt.show()

# PCA的算法相当简单。 在确保数据被归一化之后,输出仅仅是原始数据的协方差矩阵的奇异值分解
def pca(X):
    # normalize the features
    X = (X - X.mean()) / X.std()
    
    # compute the covariance matrix
    X = np.matrix(X)
    cov = (X.T * X) / X.shape[0]
    
    # perform SVD
    U, S, V = np.linalg.svd(cov)
    
    return U, S, V

U, S, V = pca(X)
U, S, V
(matrix([[-0.79241747, -0.60997914],
         [-0.60997914,  0.79241747]]),
 array([1.43584536, 0.56415464]),
 matrix([[-0.79241747, -0.60997914],
         [-0.60997914,  0.79241747]]))
# 实现一个计算投影并且仅选择顶部K个分量的函数,有效地减少了维数
def project_data(X, U, k):
    U_reduced = U[:,:k]
    return np.dot(X, U_reduced)

Z = project_data(X, U, 1)
Z
matrix([[-4.74689738],
        [-7.15889408],
        [-4.79563345],
        [-4.45754509],
        [-4.80263579],
        [-7.04081342],
        [-4.97025076],
        [-8.75934561],
        [-6.2232703 ],
        [-7.04497331],
        [-6.91702866],
        [-6.79543508],
        [-6.3438312 ],
        [-6.99891495],
        [-4.54558119],
        [-8.31574426],
        [-7.16920841],
        [-5.08083842],
        [-8.54077427],
        [-6.94102769],
        [-8.5978815 ],
        [-5.76620067],
        [-8.2020797 ],
        [-6.23890078],
        [-4.37943868],
        [-5.56947441],
        [-7.53865023],
        [-7.70645413],
        [-5.17158343],
        [-6.19268884],
        [-6.24385246],
        [-8.02715303],
        [-4.81235176],
        [-7.07993347],
        [-5.45953289],
        [-7.60014707],
        [-4.39612191],
        [-7.82288033],
        [-3.40498213],
        [-6.54290343],
        [-7.17879573],
        [-5.22572421],
        [-4.83081168],
        [-7.23907851],
        [-4.36164051],
        [-6.44590096],
        [-2.69118076],
        [-4.61386195],
        [-5.88236227],
        [-7.76732508]])
# 我们也可以通过反向转换步骤来恢复原始数据。
def recover_data(Z, U, k):
    U_reduced = U[:,:k]
    return np.dot(Z, U_reduced.T)

X_recovered = recover_data(Z, U, 1)
X_recovered
matrix([[3.76152442, 2.89550838],
        [5.67283275, 4.36677606],
        [3.80014373, 2.92523637],
        [3.53223661, 2.71900952],
        [3.80569251, 2.92950765],
        [5.57926356, 4.29474931],
        [3.93851354, 3.03174929],
        [6.94105849, 5.3430181 ],
        [4.93142811, 3.79606507],
        [5.58255993, 4.29728676],
        [5.48117436, 4.21924319],
        [5.38482148, 4.14507365],
        [5.02696267, 3.8696047 ],
        [5.54606249, 4.26919213],
        [3.60199795, 2.77270971],
        [6.58954104, 5.07243054],
        [5.681006  , 4.37306758],
        [4.02614513, 3.09920545],
        [6.76785875, 5.20969415],
        [5.50019161, 4.2338821 ],
        [6.81311151, 5.24452836],
        [4.56923815, 3.51726213],
        [6.49947125, 5.00309752],
        [4.94381398, 3.80559934],
        [3.47034372, 2.67136624],
        [4.41334883, 3.39726321],
        [5.97375815, 4.59841938],
        [6.10672889, 4.70077626],
        [4.09805306, 3.15455801],
        [4.90719483, 3.77741101],
        [4.94773778, 3.80861976],
        [6.36085631, 4.8963959 ],
        [3.81339161, 2.93543419],
        [5.61026298, 4.31861173],
        [4.32622924, 3.33020118],
        [6.02248932, 4.63593118],
        [3.48356381, 2.68154267],
        [6.19898705, 4.77179382],
        [2.69816733, 2.07696807],
        [5.18471099, 3.99103461],
        [5.68860316, 4.37891565],
        [4.14095516, 3.18758276],
        [3.82801958, 2.94669436],
        [5.73637229, 4.41568689],
        [3.45624014, 2.66050973],
        [5.10784454, 3.93186513],
        [2.13253865, 1.64156413],
        [3.65610482, 2.81435955],
        [4.66128664, 3.58811828],
        [6.1549641 , 4.73790627]])
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(list(X_recovered[:, 0]), list(X_recovered[:, 1]))
plt.show()
# 注意,第一主成分的投影轴基本上是数据集中的对角线。 当我们将数据减少到一个维度时,我们失去了该对角线周围的变化,
# 所以在我们的再现中,一切都沿着该对角线

 2.将PCA应用于脸部图像

faces = loadmat('E:/Python/machine learning/data/ex7faces.mat')
X = faces['X']
X.shape
(5000, 1024)
def plot_n_image(X, n):
    """ plot first n images
    n has to be a square number
    """
    pic_size = int(np.sqrt(X.shape[1]))
    grid_size = int(np.sqrt(n))

    first_n_images = X[:n, :]

    fig, ax_array = plt.subplots(nrows=grid_size, ncols=grid_size,
                                    sharey=True, sharex=True, figsize=(8, 8))

    for r in range(grid_size):
        for c in range(grid_size):
            ax_array[r, c].imshow(first_n_images[grid_size * r + c].reshape((pic_size, pic_size)))
            plt.xticks(np.array([]))
            plt.yticks(np.array([]))
            
face = np.reshape(X[3,:], (32, 32))

plt.imshow(face)
plt.show()

# 看起来很糟糕。 这些只有32 x 32灰度的图像(它也是侧面渲染,但我们现在可以忽略)。 我们的下一步是在面数据集上运行PCA,并取得前100个主要特征。

U, S, V = pca(X)
Z = project_data(X, U, 100)

# 现在我们可以尝试恢复原来的结构并再次渲染。
X_recovered = recover_data(Z, U, 100)
face = np.reshape(X_recovered[3,:], (32, 32))
plt.imshow(face)
plt.show()
# 注意,我们失去了一些细节,尽管没有像您预期的维度数量减少10倍

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值