无监督学习
1 K-Means
- K-Means聚类分析方法的步骤:
-
首先随机初始化K个点(K取决于需要分成的类别数)
-
将离初始化点近的点分别归类,比如下图,蓝色的原点离蓝色的×比较近,所以就被归为此类。红色的也同理
-
再计算每个类的均值,将聚类中心点移动到每类均值上
-
再计算距离分类
-
如此循环3、4两个步骤
- 输入的值:
- K:类别数
- 数据
- 优化目标:
- c(i):样本x(i)被分配到类的索引
- μk: 第k个簇的中心
- μ_c(i): 样本x(i)被分配到类的类中心点
目标:最小化代价函数。
- 如何随机初始化聚类中心点
- 首先保证K<m(样本总数)
- 其次选择K个样本点作为初始的聚类中心点
-
局部最优问题:
根据随机初始化聚类中心点的不同,我们最终所获得的聚类结果也会有所不同,很有可能出现局部最优。
-
那么如何避免出现局部最优?
一般情况下是尝试多次初始化聚类中心,依此计算代价函数值,最后选择一个代价函数值最小的作为初始化点。 -
如何确定K的值呢?
-
肘部法
逐个尝试k的值,并计算代价函数,然后选择肘部作为合适的点。但有时候可能不会出现肘部。
-
从商业的角度考虑
看分成几类比较好,比如说将T-shirt的尺寸分为三种比较有利呢?还是5种比较有利。
2 Dimensionality Reduction
2.1 数据压缩
就是把一个三维的数据投影到一个二维的平面上,因此这样就可以使用一个二维的平面来表示原来的数据。
2.2 PCA(主成分分析)
假设我们有一组数据分布如下,PCA就是找到一个平面,使得每个样本与该投影的到这个平面的线段长度最小。
-
PCA就是找到一个向量μ(i)来最小化这个间距平方的误差,将2维数据降成1维数据。也可将N维的向量转化维K维的向量。
-
PCA就是找到一个平面或一条线,使得实际样本点与该样本点在该平面或直线上的间距最小化。
-
PCA与Linear regression的区别
- 线性回归是左图,将作图点到直线距离最小化。PCA是右图,即将点到垂直于直线的距离最小化。
- 线性回归是为了预测某一个值,而在PCA当中,没有某一个值是要被预测的,所有的特征值都是被同等对待的。
2.3 PCA应用
-
首先对数据进行预处理。将每个值转换为(实际值-该特征值的均值)/该特征值的标准差
-
然后找到一条线或一个平面,对数据进行降维
-
计算协方差
-
通过SVD得到矩阵U,计算UT*X,就可以都得到一个K维的数据
2.4 压缩重现
-
用U*Z可以近似重现原始数据
-
如何选择PCA的目标维数K
使得每个样本点到映射点的距离方差/样本点的方差<0.01(1%-5%)
或者使用S来计算。分子为k个对角线的数的和, 分母为对角线数之和。
2.5 使用PCA的建议
- 面对维数较多的数据时,首先提取没有标签的值,然后再使用PCA进行降维,计算U时只能通过训练集来进行计算,然后可以使用到交叉验证集和测试集上。
3 代码实战
3.1 K-means
- 读取数据
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sb
from scipy.io import loadmat
data = loadmat('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex7-kmeans and PCA/data/ex7data2.mat')
X = data['X']
initial_centroids = np.array([[2,5],[2,2],[8,3]])#初始化聚类中心
- 相关函数
def init_centroids(X,k):
"""随机初始化聚类中心点
Params:
X:原始数据
k:簇数
return:
centroids:随机初始化的聚类中心点"""
m,n =X.shape
index = np.random.randint(0,m,k) #从0到m内选择k个值(对应的是X的索引)
centroids = np.zeros((k,n))
for i in range(k):#取k个聚类中心
centroids[i,:] = X[index[i],:]
return centroids
def find_closest_centroids(X,initial_centroids):
"""找到每个样本点的离初始聚类中心点的最近距离,并进行分类
Params:
X:原始数据集
initial_centrodis: 随机初始化的聚类中心点
return:
index:存放每一个样本对应类别标签的列表"""
m = X.shape[0]
n = initial_centroids.shape[0]
index = np.zeros(m)
for i in range(m):
min_dist = 1000000
for j in range(n):
dist = np.sum((X[i,:]-initial_centroids[j,:])**2)
if dist < min_dist:
min_dist = dist
index[i] = j
return index
def compute_centroids(X,index,k):
"""计算聚类中心点
Params
X : 原始数据
index:存放每个样本对应的类别标签的列表
k:类别总数
return
centroids:移动后的聚类中心点"""
m,n = X.shape #获取数据的特征值数
centroids = np.zeros((k,n)) #初始化聚类中心矩阵
for i in range(k): #逐个极端聚类中心点
indeices = np.where(index == i ) #找到index当中为i的所有样本的索引值
centroids[i,:] = (np.sum(X[indeices,:],axis=1)/len(indeices[0])).ravel()
return centroids
def run_k_means(X,initial_centroids,max_iter):
"""迭代找到每个样本所属的类别,以及最佳聚类中心
Params:
X:原始数据
initial_centroids:初始化的聚类中心点
max_iter:最大迭代次数
return:
index:存放每个样本对应的类别标签的列表
centroids:最终的聚类中心点
"""
m,n = X.shape
index = np.zeros(m)
k = initial_centroids.shape[0]
centroids = initial_centroids
for i in range(max_iter):
index = find_closest_centroids(X,centroids)
centroids = compute_centroids(X,index,k)
return index,centroids
if __name__ == '__main__':
initial_centroids = init_centroids(X,3)
index,centroids = run_k_means(X,initial_centroids,50)
cluster1 = X[np.where(index == 0)[0],:]
cluster2 = X[np.where(index == 1)[0],:]
cluster3 = X[np.where(index == 2)[0],:]
fig,ax = plt.subplots(figsize = (12,8))
ax.scatter(cluster1[:,0],cluster1[:,1],s = 30 ,color='orange',label='Cluster1')
ax.scatter(cluster2[:,0],cluster2[:,1],s = 30 ,color='red',label='Cluster2')
ax.scatter(cluster3[:,0],cluster3[:,1],s = 30 ,color='blue',label='Cluster3')
plt.legend(loc=1)
plt.show()
结果如下:
3.2 PCA
- 读取数据,查看数据分布:
data = loadmat('E:/Data/Ng/Coursera-ML-AndrewNg-Notes-master/code/ex7-kmeans and PCA/data/ex7data1.mat')
X= data['X']
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(X[:,0],X[:,1],s=60,color='red')
plt.show()
结果如下:
- 特征值缩放,并计算sigma值,并获取矩阵U
X_process = (X - X.mean())/X.std()
def sigma(data):
m= data.shape[0]
sigma = (data.T @ data)/m
return sigma
cov=sigma(X_process)
U,S,V=np.linalg.svd(cov) #得到U
- 相关函数
def prepare_data(data):
"""数据预处理"""
X = (data-data.mean())/data.std()
return X
def sigma(X):
X = np.mat(X)
m = X.shape[0]
return np.dot(X.T,X)
def pca(sigma):
U,S,V=np.linalg.svd(sigma)
return U,S,V
def project_data(X,U,k):
U_reduce = U[:,k:]
return np.dot(X,U_reduce)
def recover(z,U,k):
U_reduce = U[:,:k]
return np.dot(z,U_reduce.T)
if __name__ == '__main__':
X_process=prepare_data(X)
cov=sigma(X_process)
U,S,V = pca(sigma)
z = project_data(X,U,k)
X_recover = recover(z,U,1)
fig,ax = plt.subplots(figsize=(12,8))
ax.scatter(list(X_recover[:,0]),list(X_recover[:,1]))
plt.show()