一、 無監督學習
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
(1) 數據壓縮
就是把一個三維的數據投影到一個二維的平面上,因此這樣就可以使用一個二維的平面來表示原來的數據。
(2) PCA(主成分分析)
假設我們有一組數據分佈如下,PCA就是找到一個平面,使得每個樣本與該投影的到這個平面的線段長度最小。
-
PCA就是找到一個向量μ(i)來最小化這個間距平方的誤差,將2維數據降成1維數據。也可將N維的向量轉化維K維的向量。
-
PCA就是找到一個平面或一條線,使得實際樣本點與該樣本點在該平面或直線上的間距最小化。
-
PCA與Linear regression的區別
- 線性迴歸是左圖,將作圖點到直線距離最小化。PCA是右圖,即將點到垂直於直線的距離最小化。
- 線性迴歸是爲了預測某一個值,而在PCA當中,沒有某一個值是要被預測的,所有的特徵值都是被同等對待的。
(3) PCA應用
-
首先對數據進行預處理。將每個值轉換爲(實際值-該特徵值的均值)/該特徵值的標準差
-
然後找到一條線或一個平面,對數據進行降維
-
計算協方差
-
通過SVD得到矩陣U,計算UT*X,就可以都得到一個K維的數據
(4) 壓縮重現
-
用U*Z可以近似重現原始數據
-
如何選擇PCA的目標維數K
使得每個樣本點到映射點的距離方差/樣本點的方差<0.01(1%-5%)
或者使用S來計算。分子爲k個對角線的數的和, 分母爲對角線數之和。
(5) 使用PCA的建議
- 面對維數較多的數據時,首先提取沒有標籤的值,然後再使用PCA進行降維,計算U時只能通過訓練集來進行計算,然後可以使用到交叉驗證集和測試集上。
3 代碼實戰
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()
結果如下:
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()
參考資料: