任務安排
1、機器學習導論 8、稀疏表示
2、KNN及其實現 9、核方法
3、K-means聚類 10、高斯混合模型
4、主成分分析 11、嵌入學習
5、線性判別分析 12、強化學習
6、貝葉斯方法 13、PageRank
7、邏輯迴歸 14、深度學習
主成分分析(PCA)
Ⅰ算法背景:維數災難
維數災難最早是由理查德·貝爾曼(Richard E. Bellman)在考慮優化問題時提出來的 ,它用來描述當(數學)空間維度增加時,分析和組織高維空間(通常有成百上千維)中的數據,因體積指數增加而遇到各種問題場景。
維數災難這個概念具有的共同特點是:當維度增加時,空間的體積增加得很快,使得可用的數據變得稀疏。
生活中多維數據比較的例子很多,比如人的三圍及身高體重、遊戲角色的六維屬性等等。我們拿大家最熟悉的成績來說,小學時,我們可能只有語數英三科(三維),想要和小夥伴比較成績,關鍵看到底是哪一個科目(某一特徵值)具體影響了我們之間的差距,因爲科目不多,還比較容易,但到了中學,我們可能要學八科、九科、十科…,身邊小夥伴也變多了,想要比較起來就沒有之前那麼容易了,而當分析某一數學問題時,可能有成百上千維的數據,樣本個數也不在少數,那麼總體分析就顯得舉步維艱。因此,我們就想讓數據變得簡單一些,就有了維數約簡思想。
Ⅱ 維數約簡
維數約簡又稱降維,是機器學習的一種必要手段。若數據{}是屬於維空間的,通過特徵提取或者特徵選擇的方法,將原空間的維數降至維,要求遠小於,並滿足:維空間的特性能反映原空間數據的特徵,這個過程稱之爲維數約簡
維數約簡即通過某種數學變換,將原始高維屬性空間轉變爲一個低維子空間,在這個子空間中樣本密度大幅度提高,距離計算也變得容易起來
由線性代數的知識我們知道,空間維度的改變依賴於變換矩陣,如是一個維列向量,我們想要把它變成,即在前面乘上一個的變換矩陣
而主成分分析,就是降維裏的一種重要方法。
既然要對已有的特徵值進行降維變換,那麼首先,我們要先得到原樣本集的特徵值,回顧一下線性代數的知識。
有一個階矩陣,若存在數和非零維列向量,滿足,則稱λ爲A的一個特徵值,X爲A的對應於λ的一個特徵向量
Ⅲ 核心思想
主成分分析(Principal Component Analysis)的出發點是從一組特徵(維)中計算出一組按重要性從大到小排列的新特徵(維,,通常取遠小於),它們是原有特徵的線性組合,並且相互之間不相關。(比如你和小夥伴的理科成績非常接近,那麼決定你們之間差距的主要科目(新特徵值PC)就是文科類的了,只關注這幾科,即降維了)
①主成分特點
1. 源於質心的矢量
2. 主成分①指向最大方差的方向
3. 各後續主成分與前一主成分正交,且指向殘差(剩餘)子空間最大方差的方向
②舉例(二維)
爲了便於分析說明,我們舉二維樣本集的例子:
如下圖所示,紅色的兩向量表示“藍色橢圓”的長軸短軸,很明顯可以看出,假如我們把樣本集的點投影到長軸上,更能反映出樣本集整體的分佈,故在這個例子裏我們把長軸記爲主成分#1,與長軸正交(互不相關)的短軸記爲主成分#2,理想情況下,短軸的模(高維情況下稱範數)爲0,即僅通過長軸就可以完全分析出樣本集的分佈,這就實現了完美的降維,因而我們容易知道,長短軸的模(範數)相差越大,即降維的效果越好,所以我們的目標就是,找出儘量長的長軸(標號靠前的主成分)
③最大方差理論
通常,我們認爲信號具有較大的方差,噪聲具有較小的方差,信噪比就是信號與噪聲的功率之差(),越大越好。如下圖所示,我們把紫色線上的數據認爲是信號,而藍色線上的數據認爲是噪聲,因此我們的目的就是最大化投影數據的方差(樣本點在紫線上最分散),最小化數據點與投影之間的均方距離(藍線和越小)
④目的
PCA的目的就是“降噪”和“去冗餘”。
“降噪”即使保留下來的維度間的相關性儘可能小
“去冗餘”即使保留下來的維度含有的方差(能量)儘可能大
★Ⅳ 算法剖析
輸入:樣本集{},低維空間維數k(即所要保留的新特徵值個數)
輸出:投影矩陣
下面介紹兩種PCA的實現方法:
①順序排列
1.對所有樣本進行中心化(和期望作差)
2.對中心化的數據{},計算主成分#1:(即目標函數)
即內積運算(爲單位向量),求的是在上的投影,平方是爲了省去求絕對值
利用拉格朗日乘數法求解最優,約束條件爲||w||=1(即)
(矩陣求導)對求導
實際上,令,則
3.最大化投影方差
後面一串 可以簡單點理解爲,扣掉前面那個主成分的方向,在剩下的殘差子空間裏求新的主成分
②協方差矩陣法
1.對所有樣本進行去中心化(和期望作差)
2.計算樣本的協方差矩陣
(對角線元素爲某一維度的方差)
3.對協方差矩陣C做特徵值分解(即求所有滿足的特徵值和特徵向量)(也可以用拉格朗日乘數法只求所需的最大的k個)
4.取最大的k個特徵值所對應的特徵向量
比較詳細的PCA數學推導過程主成分分析(PCA)原理詳解
——————————這節課的理論理解是真的費勁啊!————————
今日任務
1.給定的圖像數據集,可視化並輸出聚類性能(上節課還想偷懶,沒想到該來的這麼快就來了)
2.給定的圖像數據集,計算相應的特徵臉(Eigenfaces)
注:不是每一組20張算一個特徵臉,是200張取前十個特徵臉(這特徵臉有點恐怖,不是說好提取完是張偉嗎)
3.給定圖像數據集,探討PCA降維後特徵個數與聚類性能的關係
任務解決
1、今天要用到python的庫cv2(版本更新被合併到opencv_python裏了),提前裝一下
pip install opencv_python -i https://pypi.tuna.tsinghua.edu.cn/simple
import matplotlib.pyplot as plt
import os
import cv2 as cv
import numpy as np
from sklearn.cluster import KMeans
from PIL import Image
from ML_clustering_performance import clusteringMetrics
path = 'C:/Users/1233/Desktop/Machine Learning/face_images/'
h, w = 200, 180
IMAGE_COLUMN = 20 # 列
IMAGE_ROW = 10 # 行
to_image = Image.new('RGB', (IMAGE_COLUMN * w, IMAGE_ROW * h))
def createDatabase(path):
# 查看路徑下所有文件
TrainFiles = os.listdir(path) # 遍歷每個子文件夾
# 計算有幾個文件(圖片命名都是以 序號.jpg方式)
Train_Number = len(TrainFiles) # 子文件夾個數
train = []
y_sample = []
# 把所有圖片轉爲1維並存入T中
for k in range(0, Train_Number):
Trainneed = os.listdir(path + '/' + TrainFiles[k]) # 遍歷每個子文件夾裏的每張圖片
Trainneednumber = len(Trainneed) # 每個子文件裏的圖片個數
for i in range(0, Trainneednumber):
img = Image.open(path + '/' + TrainFiles[k] + '/' + Trainneed[i])
to_image.paste(img, (i * w, k * h)) # 把讀出來的圖貼到figure上
image = cv.imread(path + '/' + TrainFiles[k] + '/' + Trainneed[i]).astype(np.float32) # 數據類型轉換
image = cv.cvtColor(image, cv.COLOR_RGB2GRAY) # RGB變成灰度圖
train.append(image)
y_sample.append(k)
train = np.array(train)
y_sample = np.array(y_sample)
return train, y_sample
# n_samples, h, w = 200, 200, 180
X, y = createDatabase(path)
# print(X.shape)
X_ = X.reshape(X.shape[0], h*w)
kms = KMeans(n_clusters=10)
y_sample = kms.fit_predict(X_, y)
print(clusteringMetrics(y, y_sample))
plt.imshow(to_image)
plt.show()
(別人家的代碼系列)
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import matplotlib.image as imgplt
import os
import pandas as pd
from ML_clustering_performance import clusteringMetrics
name = []
target = []
def getimage():
# 獲取文件並構成向量
# 預測值爲1維,把一張圖片的三維(RGB)壓成1維,那麼n張圖片就是二維
global total_photo
file = os.listdir('C:\\Users\\1233\\Desktop\\Machine Learning\\face_images') # 遍歷face_images裏每個子文件夾
i = 0
for subfile in file:
photo = os.listdir('C:\\Users\\1233\\Desktop\\Machine Learning\\face_images\\' + subfile) # 遍歷每個子文件夾裏的照片
for name in photo:
photo_name.append('C:\\Users\\1233\\Desktop\\Machine Learning\\face_images\\' + subfile+'\\'+name)
target.append(i)
i += 1
print(photo_name)
for path in photo_name:
photo = imgplt.imread(path)
# photo = cv.imread(path)
photo = photo.reshape(1, -1)
photo = pd.DataFrame(photo)
total_photo = total_photo.append(photo, ignore_index=True)
total_photo = total_photo.values
def kmeans():
clf = KMeans(n_clusters=10)
clf.fit(total_photo)
y_predict = clf.predict(total_photo)
centers = clf.cluster_centers_
result = centers[y_predict]
result = result.astype("int64")
result = result.reshape(200, 200, 180, 3) # 圖像的矩陣大小爲200,180,3
return result, y_predict
def draw():
fig, ax = plt.subplots(nrows=10, ncols=20, sharex=True, sharey=True, figsize=[15, 8], dpi=80)
plt.subplots_adjust(wspace=0, hspace=0)
count = 0
for i in range(10):
for j in range(20):
ax[i, j].imshow(result[count])
count += 1
plt.show()
def score():
print(clusteringMetrics(target, y_predict))
total_photo = pd.DataFrame()
getimage()
result, y_predict = kmeans()
draw()
score()
效果圖(就這,也跑了十幾秒T∩T)
2、直接放代碼吧,PCA理論分析比較難,但用起來挺簡單的,學着別人的例子用改改參數就行了(Python真香)
參考了Scikit-learn實例之Pca+Svm人臉識別(AT&T數據集)
import matplotlib.pyplot as plt
import os
import cv2 as cv
import numpy as np
from sklearn.decomposition import PCA
path = 'C:/Users/1233/Desktop/Machine Learning/face_images/'
h, w = 200, 180
IMAGE_COLUMN = 20
IMAGE_ROW = 10
def createDatabase(path):
TrainFiles = os.listdir(path)
Train_Number = len(TrainFiles)
train = []
y_sample = []
for k in range(0, Train_Number):
Trainneed = os.listdir(path + '/' + TrainFiles[k])
Trainneednumber = len(Trainneed)
for i in range(0, Trainneednumber):
image = cv.imread(path + '/' + TrainFiles[k] + '/' + Trainneed[i]).astype(np.float32)
image = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
train.append(image)
y_sample.append(k)
train = np.array(train)
y_sample = np.array(y_sample)
return train, y_sample
# n_samples, h, w = 200, 200, 180
X, y = createDatabase(path)
X_ = X.reshape(X.shape[0], h*w)
# 從200張圖裏挑出特徵值前10的特徵臉
n_components = 10
pca = PCA(n_components).fit(X_) # svd_solver='randomized', whiten=True
eigenfaces = pca.components_.reshape((n_components, h, w))
# 將輸入數據投影到特徵面正交基上
X_train_pca = pca.transform(X_)
def plot_gallery(images, titles, h, w, n_row=1, n_col=10):
"""Helper function to plot a gallery of portraits"""
plt.figure(figsize=(1.8 * n_col, 2 * n_row))
plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35) # 圖片位置佈局
for i in range(10):
plt.subplot(n_row, n_col, i + 1)
plt.imshow(images[i].reshape((h, w)))
# plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray)
plt.title(titles[i], size=12)
# 把座標去了
plt.xticks(())
plt.yticks(())
eigenface_titles = ["eigenface %d" % (i+1) for i in range(eigenfaces.shape[0])]
plot_gallery(eigenfaces, eigenface_titles, h, w)
plt.show()
效果圖
3、循環聚類下畫個圖就OK了
import matplotlib.pyplot as plt
import os
import cv2 as cv
import numpy as np
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from PIL import Image
from ML_clustering_performance import clusteringMetrics
path = 'C:/Users/1233/Desktop/Machine Learning/face_images/'
h, w = 200, 180
IMAGE_COLUMN = 20
IMAGE_ROW = 10
def createDatabase(path):
TrainFiles = os.listdir(path)
Train_Number = len(TrainFiles)
train = []
y_sample = []
for k in range(0, Train_Number):
Trainneed = os.listdir(path + '/' + TrainFiles[k])
Trainneednumber = len(Trainneed)
for i in range(0, Trainneednumber):
img = Image.open(path + '/' + TrainFiles[k] + '/' + Trainneed[i])
image = cv.imread(path + '/' + TrainFiles[k] + '/' + Trainneed[i]).astype(np.float32)
image = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
train.append(image)
y_sample.append(k)
train = np.array(train)
y_sample = np.array(y_sample)
return train, y_sample
# n_samples, h, w = 200, 200, 180
X, y = createDatabase(path)
X_ = X.reshape(X.shape[0], h*w)
n_components = 10
ACCS = []
NMIS = []
ARIS = []
for i in range(1, 9):
n_components = i
pca = PCA(n_components=n_components).fit(X_) # svd_solver='randomized', whiten=True
eigenfaces = pca.components_.reshape((n_components, h, w))
# 將輸入數據投影到特徵面正交基上
X_train_pca = pca.transform(X_)
# 聚類
kms = KMeans(n_clusters=10)
y_sample = kms.fit_predict(X_train_pca, y)
ACC, NMI, ARI = clusteringMetrics(y, y_sample)
ACCS.append(ACC)
NMIS.append(NMI)
ARIS.append(ARI)
fig, ax = plt.subplots()
bar_width = 0.35
opacity = 0.4 # 不透明度
index = np.arange(8)
# error_config = {'ecolor': '0.3'}
rects1 = ax.bar(index, ACCS, bar_width, alpha=opacity, color='r', label='ACC') # error_kw=error_config
rects2 = ax.bar(index + bar_width, NMIS, bar_width, alpha=opacity, color='g', label='NMI')
rects3 = ax.bar(index + 2*bar_width, ARIS, bar_width, alpha=opacity, color='b', label='ARI')
ax.set_xticks(index + bar_width / 2)
ax.set_xticklabels(('1', '2', '3', '4', '5', '6', '7', '8'))
ax.legend()
plt.show()
效果圖