一、無監督學習基礎知識 利用無標簽的數據學習數據的分佈或數據與數據之間的關係被稱作無監督學習 有監督學習和無監督學習的最大區別在於數據是否有標簽 無監督學習最常應用的場景是聚類(Clustering)和降維(Dimension Reduction) 二、聚類 聚類是根據數據的“相似性”將數據分為多類 ...
一、無監督學習基礎知識
利用無標簽的數據學習數據的分佈或數據與數據之間的關係被稱作無監督學習
有監督學習和無監督學習的最大區別在於數據是否有標簽
無監督學習最常應用的場景是聚類(Clustering)和降維(Dimension Reduction)
二、聚類
聚類是根據數據的“相似性”將數據分為多類的過程。評估兩個不同樣本之間的“相似性”,通常使用的方法就是計算兩個樣本之間的“距離”。使用不同的方法計算樣本間的距離會關係到聚類結果的好壞
1、歐氏距離
歐氏距離是最常用的一種距離度量方法,源於歐式空間中兩點的距離
2、曼哈頓距離
曼哈頓距離也稱作“城市街區距離”,類似於在城市之中駕車行駛,從一個十字路口到另一個十字路口的距離
3、馬氏距離
馬氏距離表示數據的協方差距離,是一種尺度無關的度量方式。馬氏距離會先將樣本點的各個屬性標準化,再計算樣本間的距離
4、夾角餘弦
餘弦相似度用向量空間中兩個向量夾角的餘弦值作為衡量兩個樣本差異的大小。餘弦值越接近於1,說明兩個向量夾角越接近0度,表明兩個向量越相似
5、sklearn庫
scikit-learn庫(簡稱sklearn庫)提供的常用聚類演算法函數包含在sklearn.cluster這個模塊中,如:k-means,近鄰傳播演算法,DBSCAN等。以同樣的數據集應用於不同的演算法,可能會得到不同的結果,演算法所耗費的時間也不盡相同,這是由演算法的特性決定的
sklearn.cluster模塊提供的各聚類演算法函數可以使用不同的數據形式作為輸入:
標準數據輸入格式:[樣本個數,特征個數]定義的矩陣形式
相似性矩陣輸入格式:即由[樣本數目]定義的矩陣形式,矩陣中的每一個元素為兩個樣本的相似度,如DBSCAN,AffinityPropagation(近鄰傳播演算法)接收這種輸入。以餘弦相似度為例,對角線元素全為1,矩陣中每個元素的取值範圍為[0,1]
sklearn.cluster模塊
演算法名稱 | 參數 | 可擴展性 | 相似性度量 |
k-means | 聚類個數 | 大規模數據 | 點間距離 |
DBSCAN | 鄰域大小 |
大規模數據 | 點間距離 |
Gaussian Mixtures | 聚類個數及其他超參 | 複雜度較高,不適合處理大規模數據 | 馬氏距離 |
Birch | 分支因數,閾值等其他超參 | 大規模數據 | 兩點間的歐氏距離 |
三、降維
降維是在保證數據所具有的特征或分佈的情況下,將高維數據轉化為低緯數據的過程。常用於數據可視化和精簡數據
聚類和分類都是無監督學習的典型任務,任務之間存在關聯,比如某些高維數據的分類可以通過降維處理更好的獲得,另外學界研究也表明代表性的分類演算法如k-means與降維演算法如NMF之間存在等價性
降維是機器學習領域的一個重要研究內容,有很多被工業界和學術界接收的典型演算法,截止到目前sklearn提供7種降維演算法
降維過程也可以理解為對數據集的組成成分進行分解(decomposition)的過程,因此sklearn為降維模塊命名為decomposition,在對降維演算法調用需要使用sklearn.decomposition模塊
sklearn.decomposition模塊
演算法名稱 | 參數 | 可擴展性 | 適用任務 |
PCA | 所降維度及其他超參 | 大規模數據 | 信號處理等 |
FastICA | 所降維度及其他超參 | 超大規模數據 | 圖形圖像特征提取 |
NMF | 所降維度及其他超參 | 大規模數據 | 圖形圖像特征提取 |
LDA | 所降維度及其他超參 | 大規模數據 | 文本數據,主題挖掘 |
四、演算法
1、k-means聚類演算法
(1)基礎知識
k-means演算法以k為參數,把n個對象分成k個簇,使簇內具有較高的相似度,而簇間的相似度較低
(2)k-means聚類演算法流程
① 隨機選擇k個點作為初始的聚類中心;
② 對於剩下的點,根據其與聚類中心的距離,將其歸入最近的簇
③ 對每個簇,計算所有點的均值作為新的聚類中心
④ 重覆②、③直到聚類中心不再發生改變
(3)具體應用
①數據介紹
現有1999年全國31個省份城鎮居民家庭平均每人全年消費性支出的八個主要變數數據,這八個變數分別是:食品、衣著、家庭設備用品及服務、醫療 保健、交通和通訊、娛樂教育文化服務、居住以及雜項商品和服務。利用已有數據,對31個省份進行聚類
②實驗目的
通過聚類,瞭解1999年各個省份的消費水平在國內的情況
③數據實例
④文本內容
⑤實現過程
a、 建立工程,導入sklearn相關包
b、 載入數據,創建k-means演算法實例,併進行訓練,獲得標簽
c、 輸出標簽,查看結果
⑥結果演示
聚成4類
聚成2類
原代碼
1 ...... 2 km = KMeans(n_clusters=4) #聚成4類 3 ...... 4 CityCluster = [[], [], [], []] #將城市按label分成設定的簇 5 ......
修改為
1 ...... 2 km = KMeans(n_clusters=2) #聚成2類 3 ...... 4 CityCluster = [[], []] #將城市按label分成設定的簇 5 ......
結果為
聚成3類
原代碼
1 ...... 2 km = KMeans(n_clusters=4) #聚成4類 3 ...... 4 CityCluster = [[], [], [], []] #將城市按label分成設定的簇 5 ......
修改為
1 ...... 2 km = KMeans(n_clusters=3) #聚成3類 3 ...... 4 CityCluster = [[], [], []] #將城市按label分成設定的簇 5 ......
結果為
(4)代碼分析
①完整代碼
1 import numpy as np 2 from sklearn.cluster import KMeans 3 4 def loadData(filePath): 5 fr = open(filePath, 'r+') 6 lines = fr.readlines() 7 retData = [] #存儲城市的各項消費信息 8 retCityName = [] #存儲城市名稱 9 for line in lines: 10 items = line.strip().split(",") 11 retCityName.append(items[0]) 12 retData.append([float(items[i]) for i in range(1, len(items))]) 13 return retData, retCityName 14 15 16 if __name__ == '__main__': 17 data, cityName = loadData('city.txt') #利用loadData()方法讀取數據 18 km = KMeans(n_clusters=4) #聚成4類 19 label = km.fit_predict(data) #label為聚類後各數據所屬的標簽,fit_predict()方法計算簇中心以及為簇分配序號 20 expenses = np.sum(km.cluster_centers_, axis=1) #expenses為聚類中心點的數值加和,也就是平均消費水平 21 # print(expenses) 22 CityCluster = [[], [], [], []] #將城市按label分成設定的簇 23 for i in range(len(cityName)): 24 CityCluster[label[i]].append(cityName[i]) #將每個簇的城市輸出 25 for i in range(len(CityCluster)): 26 print("Expenses:%.2f" % expenses[i]) 27 print(CityCluster[i]) #將每個簇的平均花費輸出
②關於相關包的介紹
NumPy是Python語言的一個擴充程式庫。支持高級大量的維度數組與矩陣運算,此外也針對數組 運算提供大量的數學函數庫。
使用sklearn.cluster.KMeans可以調用K-means演算法進行聚類
③調用KMeans()方法所需參數
n_clusters:用於指定聚類中心的個數
init:初始聚類中心的初始化方法
max_iter:最大的迭代次數
一般調用時只用給出n_clusters即可,init 預設是k-means++,max_iter預設是300
④loadData()方法解釋
fr = open(filePath,'r+')
lines = fr.readlines()
r+:讀寫打開一個文本文件
.read() 每次讀取整個文件,它通常用於將文件內容放到一個字元串變數中
.readlines() 一次讀取整個文件(類似於 .read() )
.readline() 每次只讀取一行,通常比 .readlines() 慢得多。僅當沒有足夠記憶體可以一次讀取整個文件時,才應該使用.readline()
2、DBSCAN密度聚類
(1)基礎知識
DBSCAN演算法是一種基於密度的聚類演算法:
聚類的時候不需要預先指定簇的個數
最終的簇的個數不定
DBSCAN演算法將數據點分為三類:
核心點:在半徑Eps內含有超過MinPts數目的點
邊界點:在半徑Eps內點的數量小於MinPts,但是落在核心點的鄰域內
噪音點:既不是核心點也不是邊界點的點
(2)DBSCAN演算法流程
①將所有點標記為核心點、邊界點或雜訊點
②刪除雜訊點
③為距離在Eps之內的所有核心點之間賦予一條邊
④每組連通的核心點形成一個簇
⑤將每個邊界點指派到一個與之關聯的核心點的簇中(哪一個核心點的半徑範圍之內)
示例:
有如下13個樣本點,使用DBSCAN進行聚類
取Eps=3,MinPts=3,依據DBSACN對所有點進行聚類(曼哈頓距離)
對每個點計算其鄰域Eps=3內的點的集合
集合內點的個數超過 MinPts=3的點為核心點
查看剩餘點是否在核心點的鄰域內,若在,則為邊界點,否則為雜訊點
將距離不超過Eps=3的點相互連接,構成一個簇,核心點鄰域內的點也會被加入到這個簇中,則形成3個簇
(3)具體應用
①數據介紹
現有大學校園網的日誌數據,290條大學生的校園網使用情況數據,數據包括用戶ID,設備的MAC地址,IP地址,開始上網時間,停止上網時間,上網時長,校園網套餐等。利用已有數據,分析學生上網的模式
②實驗目的
通過DBSCAN聚類,分析學生上網時間的模式
③數據實例
④文本內容
⑤實現過程
a、建立工程,導入sklearn相關包
b、讀入數據併進行處理
c、上網時間聚類,創建DBSCAN演算法實例,併進行訓練,獲得標簽
d、輸出標簽,查看結果
e、畫直方圖,分析實驗結果
⑥結果演示
Labels為每個數據被劃分的簇的分類
Noise raito為雜訊數據的比例
Estimated number of clusters為簇的個數
Silhouette Coefficient為聚類效果評價指標
上網時間大多集中在22至23點
(4)代碼分析
①完整代碼
1 import numpy as np 2 import sklearn.cluster as skc 3 from sklearn import metrics 4 import matplotlib.pyplot as plt 5 6 mac2id = dict() 7 onlinetimes = [] 8 f = open('TestData.txt', encoding='utf-8') 9 for line in f: 10 mac = line.split(',')[2] #讀取每條數據中的mac地址 11 onlinetime = int(line.split(',')[6]) #上網時長 12 starttime = int(line.split(',')[4].split(' ')[1].split(':')[0]) #開始上網時間 13 if mac not in mac2id: #mac2id是一個字典,key是mac地址,value是對應mac地址的上網時長及開始上網時間 14 mac2id[mac] = len(onlinetimes) 15 onlinetimes.append((starttime, onlinetime)) 16 else: 17 onlinetimes[mac2id[mac]] = [(starttime, onlinetime)] 18 real_X = np.array(onlinetimes).reshape((-1, 2)) 19 20 X = real_X[:, 0:1] 21 22 db = skc.DBSCAN(eps=0.01, min_samples=20).fit(X) #調用DBSCAN方法進行訓練 23 labels = db.labels_ #labels為每個數據的簇標簽 24 25 print('Labels:') 26 print(labels) 27 raito = len(labels[labels[:] == -1]) / len(labels) 28 print('Noise raito:', format(raito, '.2%')) #列印數據被記上的標簽,計算標簽為-1,即雜訊數據的比例 29 30 n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0) 31 32 print('Estimated number of clusters: %d' % n_clusters_) 33 print("Silhouette Coefficient: %0.3f" % metrics.silhouette_score(X, labels)) #計算簇的個數並列印,評價聚類效果 34 35 for i in range(n_clusters_): #列印各簇標號以及各簇內數據 36 print('Cluster ', i, ':') 37 print(list(X[labels == i].flatten())) 38 39 plt.hist(X, 24) 40 plt.show() #畫直方圖
②DBSCAN()方法主要參數
eps: 兩個樣本被看作鄰居節點的最大距離
min_samples: 簇的樣本數
metric:距離計算方式
3、PCA方法(主成分分析)
(1)基礎知識
主成分分析(Principal Component Analysis,PCA)是最常用的一種降維方法,通常用於高維數據集的探索與可視化,還可以用作數據壓縮和預處理等。PCA可以把具有相關性的高維變數合成為線性無關的低維變數,稱為主成分,主成分能夠儘可能保留原始數據的信息
在介紹PCA的原理之前需要回顧涉及到的相關術語:
①方差
方差是各個樣本和樣本均值的差的平方和的均值,用來度量一組數據的分散程度
②協方差
協方差用於度量兩個變數之間的線性相關性程度,若兩個變數的協方差為0,則可認為二者線性無關
③協方差矩陣
協方差矩陣則是由變數的協方差值構成的矩陣(對稱陣)
④特征向量和特征值
矩陣的特征向量是描述數據集結構的非零向量,並滿足如下公式:
A是方陣,是特征向量,是特征值
矩陣的主成分就是其協方差矩陣對應的特征向量,按照對應的特征值大小進行排序,最大的特征值就是第一主成分,其次是第二主成分,以此類推
(2)PCA演算法流程
(3)具體應用
①數據介紹
鳶尾花數據集來自於Python的sklearn庫
②實驗目的
已知鳶尾花數據是4維的,共三類樣本。使用PCA實現對鳶尾花數據進行降維,實現在二維平面上的可視化
③數據實例
④結果演示
可以看出,降維後的數據仍能夠清晰地分成三類。這樣不僅能削減數據的維度,降低分類任務的工作量,還能保證分類的質量
(4)完整代碼
1 import matplotlib.pyplot as plt #載入matplotlib用於數據的可視化 2 from sklearn.decomposition import PCA #載入PCA演算法包 3 from sklearn.datasets import load_iris #載入鳶尾花數據集導入函數 4 5 data = load_iris() #以字典形式載入鳶尾花數據集 6 y = data.target #使用y表示數據集中的標簽 7 X = data.data #使用X表示數據集中的屬性數據 8 pca = PCA(n_components=2) #載入PCA演算法,設置降維後主成分數目為2 9 reduced_X = pca.fit_transform(X) #對原始數據進行降維,保存在reduced_X中 10 11 red_x, red_y = [], [] #第一類數據點 12 blue_x, blue_y = [], [] #第二類數據點 13 green_x, green_y = [], [] #第三類數據點 14 15 for i in range(len(reduced_X)): #按照鳶尾花的類別將降維後的數據點保存在不同的列表中 16 if y[i] == 0: 17 red_x.append(reduced_X[i][0]) 18 red_y.append(reduced_X[i][1]) 19 elif y[i] == 1: 20 blue_x.append(reduced_X[i][0]) 21 blue_y.append(reduced_X[i][1]) 22 else: 23 green_x.append(reduced_X[i][0]) 24 green_y.append(reduced_X[i][1]) 25 26 plt.scatter(red_x, red_y, c='r', marker='x') #第一類數據點 27 plt.scatter(blue_x, blue_y, c='b', marker='D') #第二類數據點 28 plt.scatter(green_x, green_y, c='g', marker='.') #第三類數據點 29 plt.show() #可視化
4、NMF方法(非負矩陣分解)
(1)基礎知識
非負矩陣分解(Non-negative Matrix Factorization ,NMF)是在矩陣中所有元素均為非負數約束條件之下的矩陣分解方法
基本思想:給定一個非負矩陣V,NMF能夠找到一個非負矩陣W和一個非負矩陣H,使得矩陣W和H的乘積近似等於矩陣V中的值
W矩陣:基礎圖像矩陣,相當於從原矩陣V中抽取出來的特征
H矩陣:繫數矩陣
NMF能夠廣泛應用於圖像分析、文本挖掘和語音處理等領域
上圖摘自NMF作者的論文,左側為W矩陣,可以看出從原始圖像中抽取出來的特征,中間的是H矩陣。可以發現乘積結果與原結果是很像的
矩陣分解優化目標:最小化W矩陣H矩陣的乘積和原始矩陣之間的差別
目標函數如下:
基於KL散度的優化目標,損失函數如下:
(2)具體應用
①數據介紹
Olivetti人臉數據共 400個,每個數據是64*64大小
②實驗目的
由於NMF分解得到的W矩陣相當於從原始矩陣中提取的特征,那麼就可以使用NMF對400個Olivetti人臉數據進行特征提取
③數據實例
④實驗方法
通過設置k的大小,設置提取的特征的數目。在本實驗中設置k=6,隨後將提取的特征以圖像的形式展示出來
⑤結果演示
(3)代碼分析
①完整代碼
1 from numpy.random import RandomState #載入RandomState用於創建隨機種子 2 import matplotlib.pyplot as plt #載入matplotlib用於數據的可視化 3 from sklearn.datasets import fetch_olivetti_faces #載入Olivetti人臉數據集導入函數 4 from sklearn import decomposition #載入PCA演算法包 5 6 n_row, n_col = 2, 3 #設置圖像展示時的排列情況 7 n_components = n_row * n_col #設置提取的特征的數目 8 image_shape = (64, 64) #設置人臉數據圖片的大小 9 10 ############################################################################### 11 # Load faces data 12 dataset = fetch_olivetti_faces(shuffle=True, random_state=RandomState(0)) 13 faces = dataset.data #載入數據,並打亂順序 14 15 16 ############################################################################### 17 def plot_gallery(title, images, n_col=n_col, n_row=n_row): 18 plt.figure(figsize=(2. * n_col, 2.26 * n_row)) #創建圖片並指定圖片大小 19 plt.suptitle(title, size=16) #設置標題及字型大小大小 20 21 for i, comp in enumerate(images): 22 plt.subplot(n_row, n_col, i + 1) #選擇畫制的子圖 23 vmax = max(comp.max(), -comp.min()) 24 25 plt.imshow(comp.reshape(image_shape), cmap=plt.cm.gray, 26 interpolation='nearest', vmin=-vmax, vmax=vmax) #對數值歸一化,並以灰度圖形式顯示 27 plt.xticks(()) 28 plt.yticks(()) #去除子圖的坐標軸標簽 29 plt.subplots_adjust(0.01, 0.05, 0.99, 0.94, 0.04, 0.) #對子圖位置及間隔調整 30 31 32 plot_gallery("First centered Olivetti faces", faces[:n_components]) 33 ############################################################################### 34 35 estimators = [ 36 ('Eigenfaces - PCA using randomized SVD', 37 decomposition.PCA(n_components=6, whiten=True)), #PCA實例 38 39 ('Non-negative components - NMF', 40 decomposition.NMF(n_components=6, init='nndsvda', tol=5e-3)) #NMF實例 41 ] #將它們存放在一個列表中 42 43 ############################################################################### 44 45 for name, estimator in estimators: 46 print("Extracting the top %d %s..." % (n_components, name)) 47 print(faces.shape) #分別調用PCA和NMF 48 estimator.fit(faces) #調用PCA或NMF提取特征 49 components_ = estimator.components_ #獲取提取的特征 50 plot_gallery(name, components_[:n_components]) #按固定格式進行排列 51 52 plt.show() #可視化
②NMF()方法參數
在sklearn庫中,可以使用sklearn.decomposition.NMF載入NMF演算法,主要參數有:
n_components:用於指定分解後矩陣的單個維度k
init:W矩陣和H矩陣的初始化方式,預設為‘nndsvdar’
資料來源:《Python機器學習應用》——禮欣,嵩天,北京理工大學,MOOC