摘要:主成分分析,簡(jiǎn)稱是一種非監(jiān)督學(xué)習(xí)的機(jī)器算法,主要用于數(shù)據(jù)的降維。對(duì)于的目標(biāo)函數(shù)求使得最大,可以使用梯度上升法來解決。利用梯度公式的梯度上升法實(shí)際上是批量梯度上升法還有隨機(jī)梯度上升法和小批量梯度上升法,本文不涉及。
主成分分析(Principle Component Analysis,簡(jiǎn)稱:PCA)是一種非監(jiān)督學(xué)習(xí)的機(jī)器算法,主要用于數(shù)據(jù)的降維。
PCA 基本原理以有2個(gè)特征的二維平面舉例,如圖:
橫軸表示特征1,縱軸表示特征2,其中4個(gè)點(diǎn)表示二維的特征樣本。如果要對(duì)樣本進(jìn)行降維降到一維,可以將這些點(diǎn)映射到橫軸、縱軸或者其它軸上如:
映射到不同的軸后樣本間間距會(huì)不一樣,而要找的就是讓樣本間間距最大的軸。假定這個(gè)軸方向?yàn)?$w = (w1, w2)$。
對(duì)于樣本間間距可以用方差 $Var(x) = frac{1}{m}sum_{i=1}^m(x_i-overline x)^2$ 來衡量,方差越大,樣本間越稀疏。
接著進(jìn)行均值歸0(demean)處理,即 $overline x = 0$,使得 $Var(x) = frac{1}{m}sum_{i=1}^m(x_i)^2$。均值歸0處理使得原始樣本發(fā)生了變化轉(zhuǎn)換成了新的樣本 $X$。將其映射到軸 $w$ 上又得到新的樣本 $X_{pr}$,此時(shí)的方差為:
$$ Var(X_{pr}) = frac{1}{m}sum_{i=1}^m(X_{pr}^{(i)})^2 $$
因?yàn)?$X_{pr}^{(i)}$ 是一個(gè)向量 $(X_{pr1}^{(i)}, X_{pr2}^{(i)})$,所以實(shí)際的方差表示為:
$$ Var(X_{pr}) = frac{1}{m}sum_{i=1}^m||X_{pr}^{(i)}||^2 $$
最后計(jì)算 $||X_{pr}^{(i)}||$,如圖所示:
$||X_{pr}^{(i)}|| = X^{(i)}·w$ ($w$ 為單位向量),如此得到了想要的目標(biāo)函數(shù):
求 $w$ 使得 $Var(X_{pr}) = frac{1}{m}sum_{i=1}^m(X^{(i)}·w)^2$ 最大;對(duì)于多維特征,即 $frac{1}{m}sum_{i=1}^m(X_1^{(i)}w_1+X_2^{(i)}w_2+...+X_n^{(i)}w_n)^2$ 最大。
梯度上升法解決PAC問題在梯度上升法中,$+eta abla f$ 代表了 $f$ 增大的方向。
對(duì)于 PAC 的目標(biāo)函數(shù):求 $w$ 使得 $f(X) = frac{1}{m}sum_{i=1}^m(X_1^{(i)}w_1+X_2^{(i)}w_2+...+X_n^{(i)}w_n)^2$ 最大,可以使用梯度上升法來解決。
$f(X)$ 的梯度為:
$$ abla f = egin{pmatrix} frac{partial f}{partial w_1} frac{partial f}{partial w_2} cdots frac{partial f}{partial w_n} end{pmatrix} = frac{2}{m} egin{pmatrix} sum_{i=1}^{m}(X_1^{(i)}w_1+X_2^{(i)}w_2+...+X_n^{(i)}w_n)X_1^{(i)} sum_{i=1}^{m}(X_1^{(i)}w_1+X_2^{(i)}w_2+...+X_n^{(i)}w_n)X_2^{(i)} cdots sum_{i=1}^{m}(X_1^{(i)}w_1+X_2^{(i)}w_2+...+X_n^{(i)}w_n)X_n^{(i)} end{pmatrix} = frac{2}{m} egin{pmatrix} sum_{i=1}^{m}(X^{(i)}w)X_1^{(i)} sum_{i=1}^{m}(X^{(i)}w)X_2^{(i)} cdots sum_{i=1}^{m}(X^{(i)}w)X_n^{(i)} end{pmatrix} = frac{2}{m}·X^T(Xw) $$
注:這里略去了轉(zhuǎn)換過程。
利用梯度公式 $ abla f = frac{2}{m}·X^T(Xw)$ 的梯度上升法實(shí)際上是批量梯度上升法(還有隨機(jī)梯度上升法和小批量梯度上升法,本文不涉及)。梯度上升法求主成分 求第一主成分
首先定義一組有兩個(gè)特征的數(shù)據(jù)集 $X$,共100個(gè)樣本:
import numpy as np X = np.empty((100, 2)) X[:, 0] = np.random.uniform(0., 100., size=100) X[:, 1] = 0.75 * X[:, 0] + 3. + np.random.normal(0, 10., size=100)
$X$ 可視化如圖:
demean() 方法對(duì) $X$ 進(jìn)行均值歸0處理:
def demean(X): return X - np.mean(X, axis=0) X_demean = demean(X)
均值歸0處理后的 $X\_demean$ 可視化如圖:
f() 方法求函數(shù) $f$ 的值:
def f(w, X): return np.sum(X.dot(w) ** 2) / len(X)
df() 方法根據(jù)梯度公式 $ abla f = frac{2}{m}·X^T(Xw)$ 求梯度:
def df(w, X): return X.T.dot(X.dot(w)) * 2 / len(X)
gradient_ascent() 方法為梯度上升法的過程,在 n_iters 次循環(huán)中,每次獲得新的 $w$,如果新的 $w$ 和舊的 $w$ 對(duì)應(yīng)的函數(shù) $f$ 的值的差值滿足精度 epsilon,則表示找到了合適的 $w$:
def gradient_ascent(X, initial_w, eta, n_iters=1e4, epsilon=1e-8): w = direction(initial_w) cur_iter = 0 while cur_iter < n_iters: gradient = df(w, X) last_w = w w = w + eta * gradient w = direction(w) # 將w轉(zhuǎn)換成單位向量 if(abs(f(w, X) - f(last_w, X)) < epsilon): break cur_iter += 1 return w
其中調(diào)用了一個(gè)方法 direction(),用于將 $w$ 轉(zhuǎn)換成單位向量:
def direction(w): return w / np.linalg.norm(w)
接著使用梯度上升法,先設(shè)定一個(gè)初始的 $w$ 和學(xué)習(xí)率 $eta$:
initial_w = np.random.random(X.shape[1]) eta = 0.001
直接調(diào)用 gradient_ascent() 方法:
w = gradient_ascent(X_demean, initial_w, eta)
將得到的 $w$ 與樣本可視化如圖($w$ 以直線表示):
求前n個(gè)主成分前面求出了第一主成分,如何求出下一個(gè)主成分呢?以二維特征為例,如圖:
樣本 $X^{(i)}$ 在第一主成分 $w$ 上的分量為 $(X_{pr1}^{(i)}, X_{pr2}^{(i)})$,下一個(gè)主成分上的分量 $X^{"(i)} = X^{(i)} - (X_{pr1}^{(i)}, X_{pr2}^{(i)})$,因此只需將數(shù)據(jù)在第一主成分上的分量去掉,再對(duì)新的數(shù)據(jù)求第一主成分即可。
first_n_component() 方法用于求 $X$ 的前 n 個(gè)主成分,在 for 循環(huán)中每次求主成分時(shí)都設(shè)定一個(gè)隨機(jī)的 $w$(initial_w),得到一個(gè)主成分后就去掉在這個(gè)主成分上的分量 X_pca = X_pca - X_pca.dot(w).reshape(-1, 1) * w:
def first_n_component(n, X, eta=0.001, n_iters=1e4, epsilon=1e-8): X_pca = X.copy() X_pca = demean(X_pca) res = [] for i in range(n): initial_w = np.random.random(X_pca.shape[1]) w = gradient_ascent(X_pca, initial_w, eta) res.append(w) X_pca = X_pca - X_pca.dot(w).reshape(-1, 1) * w return res降維映射
得到了多個(gè)主成分后,就可以通過這些主成分將高維數(shù)據(jù)映射到低維數(shù)據(jù)。
對(duì)于有 m 個(gè)樣本,n 個(gè)特征的高維數(shù)據(jù) $X$(m*n),主成分分析后得到前 k(k $$
X = egin{pmatrix} X_1^{(1)} X_2^{(1)} cdots X_n^{(1)} X_1^{(2)} X_2^{(2)} cdots X_n^{(2)} cdots cdots cdots cdots X_1^{(m)} X_2^{(m)} ... X_n^{(m)} end{pmatrix}, W_k= egin{pmatrix} W_1^{(1)} W_2^{(1)} cdots W_n^{(1)} W_1^{(2)} W_2^{(2)} cdots W_n^{(2)} cdots cdots cdots cdots W_1^{(k)} W_2^{(k)} ... W_n^{(k)} end{pmatrix}
$$ n 維降維到 k 維后的新數(shù)據(jù)為:$X_k = X·W_k^T$。 也可以將降維后的新數(shù)據(jù)恢復(fù)到原來的維度:$X_m = X_k·W_k$。 定義一個(gè)類 PCA,構(gòu)造函數(shù)函數(shù)中 n_components 表示主成分個(gè)數(shù)即降維后的維數(shù),components_ 表示主成分 $W_k$; 函數(shù) fit() 與上面的 first_n_component() 方法一樣,用于求出 $W_k$; 函數(shù) transform() 將 $X$ 映射到各個(gè)主成分分量中,得到 $X_k$,即降維; 函數(shù) transform() 將 $X_k$?映射到原來的特征空間,得到 $X_m$。 ? Scikit Learn 中的 PCA 使用的不是梯度上升法,而是使用的相應(yīng)的數(shù)學(xué)方法。使用方式如下: 參數(shù) n_components 表示主成分個(gè)數(shù)。 由于 PCA 降維會(huì)丟失原數(shù)據(jù)的信息,Scikit Learn 中的 PCA 在 0 < n_components < 1 時(shí)表示降維的過程保留多少信息,如: 即保留原數(shù)據(jù) 95% 的信息,此時(shí)程序會(huì)自動(dòng)得到一個(gè) components_。 現(xiàn)在借助于 kNN 分類算法來看一看 PCA 的優(yōu)勢(shì)。首先使用一個(gè)正規(guī)的手寫數(shù)據(jù)集 MNIST 數(shù)據(jù)集,獲取樣本數(shù)據(jù)集的程序?yàn)椋?/p>
先不使用 PCA 來看看 kNN 算法的效率: 此時(shí) fit 的過程消耗的時(shí)間為: 接著驗(yàn)證測(cè)試數(shù)據(jù)集的準(zhǔn)確性: 此過程消耗的時(shí)間為: 并且測(cè)試數(shù)據(jù)集的正確率為0.9688。 然后在來看看 PCA 的優(yōu)勢(shì),使用 PCA 時(shí),設(shè)定保留信息為 90%: 此時(shí) fit 的過程消耗的時(shí)間為: 接著驗(yàn)證測(cè)試數(shù)據(jù)集的準(zhǔn)確性: 此過程消耗的時(shí)間為: 可以看出使用 PCA 后時(shí)間的消耗大大減少,而測(cè)試數(shù)據(jù)集的正確率為0.9728,不僅正確率沒有降低還增加了,這是因?yàn)檫@里的降維過程丟失的信息是無用的信息從而達(dá)到了降燥效果。 Github | ML-Algorithms-Action在這個(gè)降維的過程中可能會(huì)丟失信息。如果原先的數(shù)據(jù)中本身存在一些無用信息,降維也可能會(huì)有降燥效果。
import numpy as np
class PCA:
def __init__(self, n_components):
self.n_components = n_components
self.components_ = None
def fit(self, X, eta=0.001, n_iters=1e4):
def demean(X):
return X - np.mean(X, axis=0)
def f(w, X):
return np.sum(X.dot(w) ** 2) / len(X)
def df(w, X):
return X.T.dot(X.dot(w)) * 2 / len(X)
def direction(w):
return w / np.linalg.norm(w)
def first_component(X, initial_w, eta, n_iters, epsilon=1e-8):
w = direction(initial_w)
cur_iter = 0
while cur_iter < n_iters:
gradient = df(w, X)
last_w = w
w = w + eta * gradient
w = direction(w)
if(abs(f(w, X) - f(last_w, X)) < epsilon):
break
cur_iter += 1
return w
X_pca = demean(X)
self.components_ = np.empty(shape=(self.n_components, X.shape[1]))
for i in range(self.n_components):
initial_w = np.random.random(X_pca.shape[1])
w = first_component(X_pca, initial_w, eta, n_iters)
self.components_[i:] = w
X_pca = X_pca - X_pca.dot(w).reshape(-1, 1) * w
return self
def transform(self, X):
return X.dot(self.components_.T)
def inverse_transform(self, X):
return X.dot(self.components_)
from sklearn.decomposition import PCA
pca = PCA(n_components=1)
pca = PCA(0.95)
import numpy as np
from sklearn.datasets import fetch_mldata
mnist = fetch_mldata("MNIST original")
X, y = mnist["data"], mnist["target"]
# MNIST 數(shù)據(jù)集已經(jīng)默認(rèn)分配好了訓(xùn)練數(shù)據(jù)集和測(cè)試數(shù)據(jù)集,即前60000個(gè)數(shù)據(jù)為訓(xùn)練數(shù)據(jù)
X_train = np.array(X[:60000], dtype=float)
y_train = np.array(y[:60000], dtype=float)
X_test = np.array(X[60000:], dtype=float)
y_test = np.array(y[60000:], dtype=float)
from sklearn.neighbors import KNeighborsClassifier
knn_clf = KNeighborsClassifier()
%time knn_clf.fit(X_train, y_train)
CPU times: user 29.6 s, sys: 306 ms, total: 29.9 s
Wall time: 30.7 s
%time knn_clf.score(X_test, y_test)
CPU times: user 10min 23s, sys: 2.05 s, total: 10min 25s
Wall time: 10min 31s
from sklearn.decomposition import PCA
pca = PCA(0.9)
pca.fit(X_train)
X_train_reduction = pca.transform(X_train)
knn_clf = KNeighborsClassifier()
%time knn_clf.fit(X_train_reduction, y_train)
CPU times: user 317 ms, sys: 5.31 ms, total: 323 ms
Wall time: 323 ms
X_test_reduction = pca.transform(X_test)
%time knn_clf.score(X_test_reduction, y_test)
CPU times: user 1min 15s, sys: 469 ms, total: 1min 15s
Wall time: 1min 17s
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/42653.html
摘要:表示學(xué)習(xí)率,是梯度下降法的一個(gè)超參數(shù),其取值影響最優(yōu)解的速度。因此在使用梯度下降法之前,最好進(jìn)行數(shù)據(jù)歸一化。同時(shí)在隨機(jī)梯度下降法中學(xué)習(xí)率的取值是逐漸遞減的,為了防止固定取值的學(xué)習(xí)率使得梯度下降到達(dá)最優(yōu)解附近時(shí)繼續(xù)跳出這個(gè)范圍。 梯度下降法不是一個(gè)機(jī)器學(xué)習(xí)算法,而是一種基于搜索的最優(yōu)化方法,用于最小化一個(gè)效用函數(shù)。 簡(jiǎn)單理解梯度下降法 假設(shè)存在一個(gè)只有一個(gè)參數(shù) $ heta$ 的損失函數(shù)...
閱讀 2946·2021-11-22 15:25
閱讀 2240·2021-11-18 10:07
閱讀 1045·2019-08-29 15:29
閱讀 472·2019-08-29 13:25
閱讀 1504·2019-08-29 12:58
閱讀 3201·2019-08-29 12:55
閱讀 2911·2019-08-29 12:28
閱讀 500·2019-08-29 12:16