機器學習【八】數據預處理、降維、特征提取及聚類


數據預處理

手工生成一些數據,用來說明數據預處理的原理和方法

#導入numpy
import numpy as np
#導入畫圖工具
import matplotlib.pyplot as plt
#導入數據集生成工具
from sklearn.datasets import make_blobs
X,y = make_blobs(n_samples=40,centers=2,random_state=50,cluster_std=2)
#用散點圖繪制數據點
plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.cool)
plt.show()

【結果分析】

在使用make_blobs函數時,指定了樣本數量n_samples=40,分類centers=2,隨機狀態random_state=50,標注差cluster_std=2

 

1.使用StandardScaler預處理數據

原理:

將所有數據的特征值轉換為均值為0,方差為1的狀態——> 確保數據的“大小”一樣,更利於模型的訓練

#導入StandardScaler
from sklearn.preprocessing import StandardScaler
#使用StandardScaler進行數據預處理
X_1 = StandardScaler().fit_transform(X)
#用散點圖繪制預處理的數據點
plt.scatter(X_1[:,0],X_1[:,1],c=y,cmap=plt.cm.cool)
plt.show()

【結果分析】

以上兩圖,發現數據點的分布情況沒有什么不同,但xy軸發生了變化

現在,特征1的數值在-2,3之間

特征2的數值在-3,2之間

 

 

2.使用MinMaxScaler數據預處理

#導入MinMaxScaler
from sklearn.preprocessing import MinMaxScaler
#使用MinMaxScaler進行數據預處理
X_2 = MinMaxScaler().fit_transform(X)
#用散點圖繪制預處理的數據點
plt.scatter(X_2[:,0],X_2[:,1],c=y,cmap=plt.cm.cool)
plt.show()

【結果分析】

所有數據的兩個特征值都被轉換到0-1之間——> 訓練速度更快,准確率提高

 

3.使用RobustScaler數據預處理

和StandardScaler近似

使用中位數和四分位數,直接把一些異常值踢出

#導入RobustScaler
from sklearn.preprocessing import RobustScaler
#使用RobustScaler進行數據預處理
X_3 = RobustScaler().fit_transform(X)
#用散點圖繪制預處理的數據點
plt.scatter(X_3[:,0],X_3[:,1],c=y,cmap=plt.cm.cool)
plt.show()

【結果分析】

特征1控制在-1.5~2

特征2控制在-2~1.5

 

 4.使用Normalizer數據預處理

將所有樣本的特征向量轉化為歐幾里得距離為1

即,將數據的分布變成一個半徑為1的圓(或球)

通常在我們只想保留數據特征向量的方向,而忽略其數值的時候使用

#導入Normalizer
from sklearn.preprocessing import Normalizer
#使用Normalizer進行數據預處理
X_4 = Normalizer().fit_transform(X)
#用散點圖繪制預處理的數據點
plt.scatter(X_4[:,0],X_4[:,1],c=y,cmap=plt.cm.cool)
plt.show()

 

 

 

通過數據預處理提高模型的准確率

#導入紅酒數據集
from sklearn.datasets import load_wine
#導入MLP神經網絡
from sklearn.neural_network import MLPClassifier
#導入數據集拆分工具
from sklearn.model_selection import train_test_split
#建立訓練集和測試集
wine = load_wine()
X_train,X_test,y_train,y_test = train_test_split(wine.data,wine.target,random_state=62)
#打印數據形態
print(X_train.shape,X_test.shape)

【結果分析】

已成功將數據集拆分為訓練集和測試集。訓練集樣本數量為133個,測試集樣本數量為45個

 

1.用訓練集訓練一個MLP神經網絡,看看在測試集中的得分

#設定MLP神經網絡的參數
mlp = MLPClassifier(hidden_layer_sizes=[100,100],max_iter=400,random_state=62)
#使用MLP擬合數據
mlp.fit(X_train,y_train)
#打印得分
print(mlp.score(X_test,y_test))
0.9333333333333333

 2.預處理數據

#使用MinMaxScaler進行數據預處理
scaler = MinMaxScaler()
scaler.fit(X_train)
X_train_pp = scaler.transform(X_train)
X_test_pp = scaler.transform(X_test)
#重新訓練模型
mlp.fit(X_train_pp,y_train)
#得分
print(mlp.score(X_test_pp,y_test))
1.0

 【結果分析】

經過數據預處理后,神經網絡進行了完美分類

 

 

 

 

數據降維

數據集中,樣本往往有很多特征,這些特征都是同樣重要的嗎?

是否有一些關鍵特征對預測的結果起着決定性的作用呢?

 

1.PCA主成分分析原理

經過這樣的處理后,數據集從一個散點組成的面變成了一條直線,即從二維變成了以為,這就是 數據降維

這里用到的方法,即主成分分析法—— PCA

 

適用數據降維的情況:

  • 超高維度數據
  • 特征之間有非常強烈的相關性【比如,人口數據中,男性為1,女性為0,去掉其中任何一列,不會丟失任何信息,可以降維,以降低模型的復雜度】

 

 

對數據降維以便於進行可視化

#導入數據預處理工具
from sklearn.preprocessing import StandardScaler
#對紅酒數據集預處理
scaler = StandardScaler()
X = wine.data
y = wine.target
X_scaled = scaler.fit_transform(X)
#打印處理后的數據集形態
print(X_scaled.shape)
(178, 13)

 接下來導入PCA模塊,並對數據進行處理

注意:PCA主成分分析法屬於無監督學習算法,所以這里值對X_scaled進行了擬合,而並沒有涉及分類標簽y

#導入PCA
from sklearn.decomposition import PCA
#設置生成分數量為2以便可視化
pca  = PCA(n_components=2)
pca.fit(X_scaled)
X_pca = pca.transform(X_scaled)
#打印主成分提取后的數據形態
print(X_pca.shape)
(178, 2)

 

#將三個分類中的主成分提取出來
X0 = X_pca[wine.target==0]
X1 = X_pca[wine.target==1]
X2 = X_pca[wine.target==2]
#繪制散點圖
plt.scatter(X0[:,0],X0[:,1],c='b',s=60,edgecolor='k')
plt.scatter(X1[:,0],X1[:,1],c='g',s=60,edgecolor='k')
plt.scatter(X2[:,0],X2[:,1],c='r',s=60,edgecolor='k')
#設置圖注
plt.legend(wine.target_names,loc='best')
plt.xlabel('component 1')
plt.ylabel('component 2')
plt.show()

【結果分析】

 在之前的章節中,為了進行可視化,只能選取酒數據集的前兩個特征,而去掉了其余的11個特征

使用PCA將數據集的特征向量降至二維,從而輕松進行可視化處理,同時不會丟失太多信息

 

原始特征與PCA主成分之間的關系

酒的數據集中的13個原始特征與經過PCA降維處理后的兩個主成分是怎樣的關系?

#使用主成分繪制熱度圖
plt.matshow(pca.components_,cmap='plasma')
#縱軸為主成分數
plt.yticks([0,1],['component 1','component 2'])
plt.colorbar()
#橫軸為原始特征數量
plt.xticks(range(len(wine.feature_names)),wine.feature_names,rotation=60,ha='left')
plt.show()

【結果分析】

本圖中 ,不同的顏色表示一個位於-0.5~0.4之間的數值,分別涉及了13個特征

如果某個特征對應的數字是正數,則說明它和主成分之間是正相關的關系,如果是負數,則相反

 

特征提取

由以上,可以得到:

我們通過對數據集原來的特征進行轉換,生成新的“特征”或者說“成分”,會比直接使用原始的特征效果更好

 

1.PCA主成分分析法用於特征提取

這次使用一個復雜一點的數據集——LFW人臉識別數據

#導入數據集獲取工具
from sklearn.datasets import fetch_lfw_people
#載入人臉數據集
faces = fetch_lfw_people(min_faces_per_person=20,resize=0.8)
image_shape = faces.images[0].shape
#將照片打印出來
fig,axes = plt.subplots(3,4,figsize=(12,9),subplot_kw={'xticks':(),'yticks':()})
for target,image,ax in zip(faces.target,faces.images,axes.ravel()):
    ax.imshow(image,cmap=plt.cm.gray)
    ax.set_title(faces.target_names[target])
plt.show()

 

接下來,再未經處理的情況下,嘗試訓練一個神經網絡:

#導入神經網絡
from sklearn.neural_network import MLPClassifier
#對數據集拆分
X_train,X_test,y_train,y_test = train_test_split(faces.data/255,faces.target,random_state=62)
#訓練神經網絡
mlp=MLPClassifier(hidden_layer_sizes=[100,100],random_state=62,max_iter=400)
mlp.fit(X_train,y_train)
print(mlp.score(X_test,y_test))

 

0.7477064220183486

【結果分析】 

 在使用2個節點數為100的隱藏層時,神經網絡的識別准確率只有0.74

 

2.使用一些方法來提升模型的表現

A.PCA中的數據白化功能

 雖然每個人的面部特征由很大差異,但從像素級別觀察圖像,差異並不大

且相鄰的像素之間有很大的相關性,這樣一來,基本特征的輸入就是冗余的了,白化的目的就是未了降低冗余性

所以,白化的過程會讓樣本特征之間的相關度降低,且所有特征具有相同的方差

 

#使用白化功能處理人臉數據
pca = PCA(whiten=True,n_components=0.9,random_state=62).fit(X_train)
X_train_whiten = pca.transform(X_train)
X_test_whiten = pca.transform(X_test)
#打印白化后數據形態
print(X_train_whiten.shape)
(1306, 99)

 【結果分析】

 這里我們要求保留原始特征中90%的信息,所以n_components=0.9

 可見,經過PCA白化處理后的數據成分為99個,遠遠小於原始特征數量

 

#使用白化后的數據訓練神經網絡
mlp.fit(X_train_whiten,y_train)
print(mlp.score(X_test_whiten,y_test))
0.7293577981651376

 【結果分析】

書上的得分分別是:神經網絡:0.52    PCA 0.57 ——> PCA的數據白化功能對於提高神經網絡的准確率是有一定幫助的

 

B.非負矩陣分解用於特征提取

NMF, 也是一種無監督學習算法

矩陣分解就是一個把矩陣拆解為n個矩陣的乘積

非負矩陣分解,就是原始的矩陣中所有的數值必須大於或等於0,當然分解之后的矩陣中數據也是大於或等於0的

#導入NMF
from sklearn.decomposition import NMF
nmf = NMF(n_components=105,random_state=62).fit(X_train)
X_train_nmf = nmf.transform(X_train)
X_test_nmf = nmf.transform(X_test)
#打印NMF處理后的數據形態
print(X_train_nmf.shape)
(1306, 105)

 【結果分析】

 NMF的n_components參數不支持使用浮點數,只能設置為正的整型數

#使用NMF處理后的數據訓練神經網絡
mlp.fit(X_train_nmf,y_train)
print(mlp.score(X_test_nmf,y_test))
0.7591743119266054

 

 聚類算法

有監督學習——主要用於——> 分類和回歸

無監督學習——主要用於——> 聚類

 

分類是算法基於已有標簽的數據進行學習並對新數據進行分類

聚類是在完全沒有現有標簽的情況下,由算法“猜測”哪些數據像是應該“堆”在一起的,並且讓算法給不同“堆”里的數據貼上一個數字標簽

 

1.K均值算法

#導入數據集生成工具
from sklearn.datasets import make_blobs
#生成分類數為1的數據集
blobs = make_blobs(random_state=1,centers=1)
X_blobs = blobs[0]
#繪制散點圖
plt.scatter(X_blobs[:,0],X_blobs[:,1],c='r',edgecolor='k')
plt.show()

【結果分析】

 這段代碼,主要是生成一坨沒有類別的數據點

make_blobs的centers參數為1,因此這些數據都屬於1類

 

使用K均值幫助這些數據進行聚類:

#導入KMeans工具
from sklearn.cluster import KMeans
#要求KMeans將數據聚為3類
kmeans = KMeans(n_clusters=3)
#擬合數據
kmeans.fit(X_blobs)
#畫圖
x_min,x_max =  X_blobs[:,0].min() -0.5,X_blobs[:,0].max() +0.5
y_min,y_max =  X_blobs[:,1].min() -0.5,X_blobs[:,1].max() +0.5
xx,yy = np.meshgrid(np.arange(x_min,x_max,.02),np.arange(y_min,y_max,.02))
Z = kmeans.predict(np.c_[(xx.ravel(),yy.ravel())])
#將每個分類中的樣本分配不同的顏色
Z = Z.reshape(xx.shape)
plt.figure(1)
plt.imshow(Z,interpolation='nearest',extent=(xx.min(),xx.max(),yy.min(),yy.max()),cmap=plt.cm.summer,aspect='auto',origin='lower')
plt.plot(X_blobs[:,0],X_blobs[:,1],'r.',markersize=5)
#用藍色叉號表示聚類的中心
centroids = kmeans.cluster_centers_
plt.scatter(centroids[:,0],centroids[:,1],marker='x',s=150,linewidth=3,color='b',zorder=10)
plt.xlim(x_min,x_max)
plt.ylim(y_min,y_max)
plt.xticks(())
plt.yticks(())
plt.show()

【結果分析】

 n_clusters=3,所以K均值將數據點聚為3類

圖中的3個藍色X,代表了K均值對數據進行聚類的3個中心

 

那么K均值怎樣來表示這些聚類?

#打印KMeans進行聚類的標簽
print(kmeans.labels_)

【結果分析】

 K均值對數據進行的聚類和分類有些類似,是用0、1、2三個數字來代表數據的類,並且存儲在 .labels_ 屬性中

局限性:

認為每個數據點到聚類中心的方向都是同等重要的——> 對於形狀復雜的數據集,K均值算法就不能很好工作

 

 

2.凝聚聚類算法

 

用圖像對凝聚算法的工作機制說明:

#導入dendrogram和ward工具
from scipy.cluster.hierarchy import dendrogram,ward
#使用連線的方式可視化
linkage = ward(X_blobs)
dendrogram(linkage)
ax = plt.gca()
plt.xlabel("sample index")
plt.ylabel("cluster distance")
plt.show()

 【結果分析】

 凝聚聚類算法是自下而上,不斷合並相似的聚類中心,以便讓類別變少

同時,每個聚類中心的距離也就越來越遠

這種逐級生成的聚類方法為:Hierarchy clustering

但,凝聚聚類算法也無法對“形狀復雜的數據進行正確的聚類

 

 

3.DBSCAN算法

 基於密度的有噪聲應用空間聚類

通過對特征空間內的密度進行檢測,密度大的地方,它會認為是一個類,而密度較小的地方,它會認為是一個分界線

 

再用之前生成的數據集來展示一下DBSCAN的工作機制:

#導入DBSCAN
from sklearn.cluster import DBSCAN
db = DBSCAN()
#使用DBSCAN擬合數據
clusters = db.fit_predict(X_blobs)
#繪制散點圖
plt.scatter(X_blobs[:,0],X_blobs[:,1],c=clusters,cmap=plt.cm.cool,s=60,edgecolor='k')
plt.xlabel("feature 0")
plt.ylabel("feature 1")
plt.show()

#打印聚類個數
print(clusters)

【結果分析】

 -1 代表該數據是噪聲

中間深色的數據點密度相對較大,所以DBSCAN把它歸為一坨

而外圍的淺色數據點,DBSCAN認為根本不屬於任何一類,所以放在“噪聲”一類

 

eps參數,指考慮化入同一“坨”的樣本距離多遠

默認0.5

#設置DBSCAN參數eps=2
db_1 = DBSCAN(eps=2)
#使用DBSCAN擬合數據
clusters_1 = db_1.fit_predict(X_blobs)
#繪制散點圖
plt.scatter(X_blobs[:,0],X_blobs[:,1],c=clusters_1,cmap=plt.cm.cool,s=60,edgecolor='k')
plt.xlabel("feature 0")
plt.ylabel("feature 1")
plt.show()

min_samples參數,指定再某個數據點周圍,被看成是聚類核心點的個數。越大,則核心數據點越少,噪聲就越多

默認是2

#設置DBSCAN的最小樣本數為20
db_2 = DBSCAN(min_samples=20)
#使用DBSCAN擬合數據
clusters_2 = db_2.fit_predict(X_blobs)
#繪制散點圖
plt.scatter(X_blobs[:,0],X_blobs[:,1],c=clusters_2,cmap=plt.cm.cool,s=60,edgecolor='k')
plt.xlabel("feature 0")
plt.ylabel("feature 1")
plt.show()

 【結果分析】

淺色的數據,也就是噪聲變多了

深色的數據,也就是聚類中被划為類別1的數據點少了

 

 

對於機器學習來說,合理有效地對數據進行表達是至關重要的

對於沒有分類標簽的數據來說,無監督學習的聚類算法可以幫助我們更好的理解數據集,並且為進一步訓練模型打好基礎

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM