日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(九)

發布時間:2024/1/17 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(九) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上幾節介紹了多種模型(線性模型、支持向量機、集成學習),這一節介紹一類新的預處理方法。?


九、降維(Dimensionality Reduction)

??在現實生活中很多機器學習問題有上千維,甚至上萬維特征,這不僅影響了訓練速度,通常還很難找到比較好的解。這樣的問題成為維數災難(curse of dimensionality)

??幸運的是,理論上降低維度是可行的。比如MNIST數據集大部分的像素總是白的,因此可以去掉這些特征;相鄰的像素之間是高度相關的,如果變為一個像素,相差也并不大。

??需要注意:降低維度肯定會損失一些信息,這可能會讓表現稍微變差。因此應該先在原維度訓練一次,如果訓練速度太慢再選擇降維。雖然有時候降為能去除噪聲和一些不必要的細節,但通常不會,主要是能加快訓練速度。

??降維除了能訓練速度以外,還能用于數據可視化。把高維數據降到2維或3維,然后就能把特征在2維空間(3維空間)表示出來,能直觀地發現一些規則。

??本節會將兩種主要的降維方法(projection and Manifold Learning),并且通過3中流行的降維技術:PCA,Kernel PCA和LLE。?


1、維數災難

??在高維空間中,許多表現和我們在低維認識的差別很大。例如,在單位正方形(1×1)內隨機選點,那么隨機選的點離所有邊界大于0.001(靠近中間位置)的概率為0.4%(1 - 0.99821 - 0.9982),但在一個10000維單位超立方體(1×1×?×1),這個概率大于99 999999%(1 - 0.998100001 - 0.99810000)。因此高維超立方體中的大多數隨機點都非常接近邊界。

??在高維空間中還有一個與認識不同的:如果在單位超立方體(1×1×?×1)隨機選兩個點,在2維空間,兩個點之間平均距離約為0.52;在3維空間約為0.66,在1,000,000維空間,則約為408.25,可以看到在單位立方體中兩個點距離竟然能相差這么大。因此在高維空間,這很可能會使得訓練集和測試集相差很大,導致訓練過擬合。

??理論上,只要通過增加訓練集,就能達到訓練空間足夠密集。但是隨著維度的增加,需要的訓練集是呈指數增長的。如果100維(比MNIST數據集還要小),要達到每個樣本的距離為0.1(平均的分散開)的密度,則需要的樣本為1010010100個樣本,可見需要的樣本之多。?


2、降維的主要方法

??降為的方法主要為兩種:projection 和 Manifold Learning。

投影(Projection)

??在大多數的真實問題,訓練樣例都不是均勻分散在所有的維度,許多特征都是固定的,同時還有一些特征是強相關的。因此所有的訓練樣例實際上可以投影在高維空間中的低維子空間中,下面看一個例子。

??????????

??可以看到3維空間中的訓練樣例其實都分布在同一個2維平面,因此我們能夠將所有樣例都投影在2維平面。對于更高維的空間可能能投影到低維的子空間中。

??然而投影(projection)不總是降維最好的方法在,比如許多情況下,空間可以扭轉,如著名的瑞士卷(Swiss roll)數據。

?????????

??如果簡單的使用投影(project)降維(例如通過壓平第3維),那么會變成如下左圖的樣子,不同類別的樣例都混在了一起,而我們的預想是變成右下圖的形式。

???????


流行學習(Manifold Learning)

??瑞士卷(Swiss roll)是二維流形的例子。它可以在高維空間中彎曲。更一般地,一個d維流形在n維空間彎曲(其中d<n)。在瑞士卷的情況下,D=2和n=3。

??基于流行數據進行建模的降維算法稱為流形學習(Manifold Learning)。它假設大多數現實世界的高維數據集接近于一個低維流形。

??流行假設通常隱含著另一個假設:通過流形在低維空間中表達,任務(例如分類或回歸)應該變得簡單。如下圖第一行,Swiss roll分為兩類,在3D的空間看起來很復雜,但通過流行假設到2D就能變得簡單。

??但是這個假設并不總是能成立,比如下圖第二行,決策線為x=5,2D的的決策線明顯比3D的要復雜。因此在訓練模型之前先降維能夠加快訓練速度,但是效果可能會又增有減,這取決于數據的形式。

????

??下面介紹幾種著名的降維技術。?


3、主成分分析(PCA)

??主成分分析(PCA)是用的最出名的降維技術,它通過確定最接近數據的超平面,然后將數據投射(project)到該超平面上。?


保留最大方差

??首先需要選擇一個好的超平面。先看下圖的例子,需要將2D降為1D,選擇不同的平面得到右圖不一樣的結果,第1個投影以后方差最大,第3個方差最小,選擇最大方差的一個感覺上應該是比較合理的,因為這樣能保留更多的信息。

??????

??另外一種判斷的方式是:通過最小化原數據和投影后的數據之間的均方誤差。?


主成分(Principal Components)

??算法首先找到第一個主成分,使得投影后方差最大,如上圖的c1。然后再找第二個主成分(要和第一個主成分正交)使得上面投影后的數據集再投影后方差最大,由于上圖是2D平面,因此只有c2符合。如果是n維平面,則找第(t<=n)個主成分(要和1,2,…,t-1個主成分都正交),使得t-1投影后的數據再投影后方差最大。

??需要注意:主成分的方向是不穩定的,如果稍微擾動數據,則可能使方向相反,不過仍會在同一個軸上。在某些情況下,一對主成分甚至可以旋轉或交換,但它們定義的平面一般保持不變。

??要如何才能在訓練集中找到這些主成分?我們可以通過奇異值分解(SVD)來把X矩陣分解為三個矩陣U**VTU*∑*VT,其中VTVT矩陣的每一個列向量就是我們要找的主成分。

??Numpy中提供svd()方法,下面為求主成分的例子

#產生數據 import numpy as np x1=np.random.normal(0,1,100) x2=x1*1+np.random.rand(100) X=np.c_[x1,x2] #svd分解求出主成分 X_centered = X - X.mean(axis=0) U, s, V = np.linalg.svd(X_centered) c1 = V.T[:, 0] c2 = V.T[:, 1]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

??需要注意:PCA假設數據以原點為中心,因此要先減去均值再svd分解。Scikit-learn中的PCA類已經減去均值,但是如果在別的場景使用要記得先減去均值再求主成分。?


投影到d維空間

??得到主成分以后就能將數據降維,假設降到d維空間,則用數據矩陣與前d個主成分形成的矩陣相乘,得到降維后的矩陣。

Xd=X?WdXd=X?Wd
??對應的代碼為:

d=1 Wd = V.T[:, :d] XD = X_centered.dot(Wd)
  • 1
  • 2
  • 3



使用Scikit-Learn

??Scikit-learn提供了PCA類,n_components控制維數

from sklearn.decomposition import PCA pca = PCA(n_components = 1) XD = pca.fit_transform(X)
  • 1
  • 2
  • 3

??fit以后可以通過components_變量來輸出主成分,還可以通過explained_variance_ratio_來查看每個主成分占方差的比率。

#查看主成分 pca.components_.T #顯示PCA主成分比率 print("主成分方差比率為:") print(pca.explained_variance_ratio_)
  • 1
  • 2
  • 3
  • 4
  • 5

??

??在這個2D空間,可以看到第一個主成分占訓練集方差的97%,即第二個主成分占訓練集方差的3%,因此假設第二個主成分含有的信息比較少時比較合理的。?


選擇合理的維數

??合理的選擇維數而不是隨機選擇一個維數,我們可以通過設置一個合適的方差比率(如95%),計算需要多少個主成分的方差比率和能達到這個比率,就選擇該維度,對應代碼如下。(除非需要將數據降到2D或3D用于可視化等)

pca = PCA() pca.fit(X) cumsum = np.cumsum(pca.explained_variance_ratio_) #累加 d = np.argmax(cumsum >= 0.95) + 1
  • 1
  • 2
  • 3
  • 4

??得到維度d后再次設置n_components進行PCA降維。當然還有更加簡便的方法,直接設置n_components_=0.95,那么Scikit-learn能直接作上述的操作。

pca = PCA(n_components=0.95) X_reduced = pca.fit_transform(X)
  • 1
  • 2



增量PCA(IPCA)

??當數據量較大時,使用SVD分解會耗費很大的內存以及運算速度較慢。幸運的是,可以使用IPCA算法來解決。先將訓練樣本分為mini-batches,每次給IPCA算法一個mini-batch,這樣就能處理大量的數據,也能實現在線學習(當有新的數據加入時)。

??下面是使用Numpy的array_split()方法將MNIST數據集分為100份,再分別喂給IPCA,將數據降到154維。需要注意,這里對于mini-batch使用partial_fit()方法,而不是對于整個數據集的fit()方法。

#加載數據 from sklearn.datasets import fetch_mldata mnist = fetch_mldata('MNIST original') X = mnist["data"] #使用np.array_split()方法的IPCA from sklearn.decomposition import IncrementalPCA n_batches = 100 inc_pca = IncrementalPCA(n_components=154) for X_batch in np.array_split(X, n_batches):inc_pca.partial_fit(X_batch) X_mnist_reduced = inc_pca.transform(X)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

??還可以使用Numpy 的memmap類來操縱儲存在硬盤上的二進制編碼的大型數據,只有當數據被用到的時候才會將數據放入內存。由于IPCA每次只需將一部分數據,因此能通過memmap來控制內存。由于使用的是輸入的是整個數據集,因此使用的是fit()方法。

X_mm = np.memmap(filename, dtype="float32", mode="readonly", shape=(m, n)) batch_size = m // n_batches inc_pca = IncrementalPCA(n_components=154, batch_size=batch_size) inc_pca.fit(X_mm)
  • 1
  • 2
  • 3
  • 4



隨機PCA

??隨機PCA是個隨機算法,能快速找到接近前d個主成分,它的計算復雜度為O(m?d3)+O(d3)O(m?d3)+O(d3),而不是O(m?n3)+O(n3)O(m?n3)+O(n3),如果d<

rnd_pca = PCA(n_components=154, svd_solver="randomized") X_reduced = rnd_pca.fit_transform(X_mnist)
  • 1
  • 2



4、核PCA(Kernel PCA)

??在第六節的SVM中提到了核技巧,即通過數學方法達到增加特征類似的功能來實現非線性分類。類似的技巧還能用在PCA上,使得可以實現復雜的非線性投影降維,稱為kPCA。該算法善于保持聚類后的集群(clusters)后投影,有時展開數據接近于扭曲的流形。下面是使用RBF核的例子。

#生成Swiss roll數據 from sklearn.datasets import make_swiss_roll data=make_swiss_roll(n_samples=1000, noise=0.0, random_state=None) X=data[0] y=data[1] #畫3維圖 import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D ax = plt.subplot(111, projection='3d') ax.scatter(X[:,0], X[:,1], X[:,2],c=y) plt.show() #kPCA from sklearn.decomposition import KernelPCA rbf_pca = KernelPCA(n_components = 2, kernel="rbf", gamma=0.04) X_reduced = rbf_pca.fit_transform(X)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

??需要注意,此方法要使用大量內存,可能會使內存溢出。



選擇合適的核與參數

??由于kPCA是非監督算法,因此無法判斷性能的好壞,因此需要結合分類或回歸問題來判斷。通過GridSearch來選擇合適的核與參數,下面是一個例子:

from sklearn.datasets import fetch_mldata mnist = fetch_mldata('MNIST original') X,y = mnist["data"],mnist["target"]from sklearn.decomposition import KernelPCA from sklearn.model_selection import GridSearchCV from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline clf = Pipeline([ ("kpca", KernelPCA(n_components=2)), ("log_reg", LogisticRegression()) ]) param_grid = [{ "kpca__gamma": np.linspace(0.03, 0.05, 10), "kpca__kernel": ["rbf", "sigmoid"] }] grid_search = GridSearchCV(clf, param_grid, cv=3) grid_search.fit(X, y) print(grid_search.best_params_)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19



5、LLE

??局部線性嵌入(Locally Linear Embedding)是另一種非線性降維技術。它基于流行學習而不是投影。LLE首先測量每個訓練樣例到其最近的鄰居(CN)的線性關系,然后尋找一個低維表示使得這種相關性保持得最好(具體細節后面會說)。這使得它特別擅長展開扭曲的流形,特別是沒有太多的噪音的情況。

??下面是使用Scikit-learn中的LocallyLinearEmbedding類來對Swiss roll數據降維。

#生成Swiss roll數據 from sklearn.datasets import make_swiss_roll data=make_swiss_roll(n_samples=1000, noise=0.0, random_state=None) X=data[0] y=data[1] #畫3維圖 import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D ax = plt.subplot(111, projection='3d') ax.scatter(X[:,0], X[:,1], X[:,2],c=y) plt.show() #LLe降維 from sklearn.manifold import LocallyLinearEmbedding lle = LocallyLinearEmbedding(n_components=2, n_neighbors=10) #畫出降為圖 X_reduced = lle.fit_transform(X) plt.scatter(X_reduced[:,0],X_reduced[:,1],c=y)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

?????

??可以看到,Swiss roll展開后局部保持的距離比較好。然而,但是對大的整體距離并不是保持的很好(右下角部分被擠壓,左上角伸展)。但是LLE算法還是在流形中表現的很好。?


LLE原理

第一步:對于每一個訓練樣本x(i)x(i),尋找離它最近的k個樣本(如k=10),然后嘗試重建x(i)x(i)與這些鄰居的線性關系,即用這些鄰居來線性表示x(i)x(i)。如下公式,最小化x(i)x(i)與這個線性表示的距離。其中非鄰居的wi,jwi,j=0。

W^=argminWi=1m||x(i)?j=1mwi,jx(j)||2W^=arg?minW?∑i=1m||x(i)?∑j=1mwi,jx(j)||2 wi,j=0????if????i,j??is??not??neighborwi,j=0????if????i,j??is??not??neighbor j=1mwi,jx(j)=1∑j=1mwi,jx(j)=1

第二步:將訓練集降為d維(d < n),由于上一步已經求出局部特征矩陣W^W^,因此在d維空間也要盡可能符合這個矩陣W^W^,假設樣本x(i)x(i)降維變為z(i)z(i),如下公式:?

Z^=argminZi=1m||z(i)?j=1mw^i,jz(j)||2Z^=arg?minZ?∑i=1m||z(i)?∑j=1mw^i,jz(j)||2

??計算k個鄰居的計算復雜度為:O(mlog(m)nlog(k))O(mlog?(m)nlog?(k));優化權值的復雜度為:O(mnk3)O(mnk3);重建低維向量的復雜度為:O(dm2)O(dm2)。如果訓練樣本數量過大,那么在最后一步重建m2m2會很慢。?


6、其它降維技術

??還有非常多降維的技術,有一些Scikit-learn也提供支持。下面簡單列舉一些比較有名的算法。

1、Multidimensional Scaling (MDS)降維的同時保留樣本之間的距離,如下圖。

2、Isomap通過連接每個樣本和它的最近鄰居來創建一個圖,然后降低維的同時嘗試保留樣本間的測地距離(兩個樣本之間最少經過幾個點)。

3、t-Distributed Stochastic Neighbor Embedding (t-SNE),減少維度的同時試圖保持相似的樣本靠近和不同的樣本分離。它主要用于可視化,特別是可視化高維空間中的聚類。

4、Linear Discriminant Analysis (LDA),是一種分類算法,但是在訓練定義了一個超平面來投影數據。投影使得同一類的樣本靠近,不同一類的樣本分開,所以在運行另一分類算法(如SVM分類器)之前,LDA是一種很好的減少維數的技術。

????????

總結

以上是生活随笔為你收集整理的机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(九)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。