【機(jī)器學(xué)習(xí)】降維代碼練習(xí)
本課程是中國(guó)大學(xué)慕課《機(jī)器學(xué)習(xí)》的“降維”章節(jié)的課后代碼。
課程地址:
https://www.icourse163.org/course/WZU-1464096179
課程完整代碼:
https://github.com/fengdu78/WZU-machine-learning-course
代碼修改并注釋:黃海廣,[email protected]
Principal component analysis(主成分分析)
PCA是在數(shù)據(jù)集中找到“主成分”或最大方差方向的線性變換。它可以用于降維。在本練習(xí)中,我們首先負(fù)責(zé)實(shí)現(xiàn)PCA并將其應(yīng)用于一個(gè)簡(jiǎn)單的二維數(shù)據(jù)集,以了解它是如何工作的。我們從加載和可視化數(shù)據(jù)集開始。
import?numpy?as?np
import?pandas?as?pd
import?matplotlib.pyplot?as?plt
import?seaborn?as?sb
from?scipy.io?import?loadmat
data?=?pd.read_csv('data/pcadata.csv')
data.head()
| X1 | X2 | |
|---|---|---|
| 0 | 3.381563 | 3.389113 |
| 1 | 4.527875 | 5.854178 |
| 2 | 2.655682 | 4.411995 |
| 3 | 2.765235 | 3.715414 |
| 4 | 2.846560 | 4.175506 |
X?=?data.values
fig,?ax?=?plt.subplots(figsize=(12,8))
ax.scatter(X[:,?0],?X[:,?1])
plt.show()

PCA的算法相當(dāng)簡(jiǎn)單。在確保數(shù)據(jù)被歸一化之后,輸出僅僅是原始數(shù)據(jù)的協(xié)方差矩陣的奇異值分解。
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]]))
現(xiàn)在我們有主成分(矩陣U),我們可以用這些來將原始數(shù)據(jù)投影到一個(gè)較低維的空間中。對(duì)于這個(gè)任務(wù),我們將實(shí)現(xiàn)一個(gè)計(jì)算投影并且僅選擇頂部K個(gè)分量的函數(shù),有效地減少了維數(shù)。
def?project_data(X,?U,?k):
????U_reduced?=?U[:,:k]
????return?np.dot(X,?U_reduced)
Z?=?project_data(X,?U,?1)
我們也可以通過反向轉(zhuǎn)換步驟來恢復(fù)原始數(shù)據(jù)。
def?recover_data(Z,?U,?k):
????U_reduced?=?U[:,:k]
????return?np.dot(Z,?U_reduced.T)
X_recovered?=?recover_data(Z,?U,?1)
fig,?ax?=?plt.subplots(figsize=(12,8))
ax.scatter(list(X_recovered[:,?0]),?list(X_recovered[:,?1]))
plt.show()

請(qǐng)注意,第一主成分的投影軸基本上是數(shù)據(jù)集中的對(duì)角線。當(dāng)我們將數(shù)據(jù)減少到一個(gè)維度時(shí),我們失去了該對(duì)角線周圍的變化,所以在我們的再現(xiàn)中,一切都沿著該對(duì)角線。
我們?cè)诖司毩?xí)中的最后一個(gè)任務(wù)是將PCA應(yīng)用于臉部圖像。通過使用相同的降維技術(shù),我們可以使用比原始圖像少得多的數(shù)據(jù)來捕獲圖像的“本質(zhì)”。
faces?=?loadmat('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([]))
練習(xí)代碼包括一個(gè)將渲染數(shù)據(jù)集中的前100張臉的函數(shù)。而不是嘗試在這里重新生成,您可以在練習(xí)文本中查看他們的樣子。我們至少可以很容易地渲染一個(gè)圖像。
face?=?np.reshape(X[3,:],?(32,?32))
plt.imshow(face)
plt.show()

看起來很糟糕。這些只有32 x 32灰度的圖像(它也是側(cè)面渲染,但我們現(xiàn)在可以忽略)。我們的下一步是在面數(shù)據(jù)集上運(yùn)行PCA,并取得前100個(gè)主要特征。
U,?S,?V?=?pca(X)
Z?=?project_data(X,?U,?100)
現(xiàn)在我們可以嘗試恢復(fù)原來的結(jié)構(gòu)并再次渲染。
X_recovered?=?recover_data(Z,?U,?100)
face?=?np.reshape(X_recovered[3,:],?(32,?32))
plt.imshow(face)
plt.show()

我們可以看到:數(shù)據(jù)維度減少,但細(xì)節(jié)并沒有怎么損失。
參考
Prof. Andrew Ng. Machine Learning. Stanford University
