【Python實戰】無監督學習—聚類、層次聚類、t-SNE,DBSCAN
【導讀】本文主要介紹了無監督學習在Python上的實踐,圍繞著無監督學習,講述了當前主流的無監督聚類方法:數據準備,聚類,K-Means Python實現,層次聚類和其Python實現,t-SNE聚類,DBSCAN 聚類。並且附上作者自己的經驗總結,博文附完整詳細代碼,建議大家收藏學習!
作者 | Vihar Kurama
編譯 | 專知
整理 | Mandy, Shengsheng
Unsupervised Learning with Python
無監督學習是一類機器學習技術,用來發現數據中的模式。注意:在無監督演算法中,數據是沒有標註的,即只給出輸入變數(X),不給出相應的輸出變數。無監督學習是讓演算法自己去發現數據中有趣的結構。
人工智慧科學家Yan Lecun解釋說,無監督學習——讓機器自己學習,而不必被明確告知他們所做的每件事是對是錯——是「真正的」人工智慧的關鍵。
監督學習VS無監督學習
在監督學習中,系統試圖從之前給出的例子中學習。然而,在無監督學習中,系統試圖直接從給出的示例中找到模式。如果數據集被標記了,則是一個監督學習的問題,如果數據集沒有被標記,那麼它就是一個無監督學習的問題。
左邊的圖像是監督學習的一個例子;我們使用回歸方法找到特徵之間的最佳擬合線。右邊的圖像是無監督學習的一個例子;在無監督學習中,輸入是基於特徵進行分離的,預測是基於它屬於哪個簇(cluster)。
重要術語
特徵(Feature):用於進行預測的輸入變數。
預測(Predictions):當提供輸入示例時,模型的輸出。
示例(Example):數據集的一行。一個示例包含一個或多個特徵, 可能還有一個標籤。
標籤(Label):特徵的結果。
為無監督學習準備數據
在本文中,我們使用Iris數據集進行第一次預測。該數據集包含一組具有5個屬性的150條記錄,這5個屬性為花瓣長度、花瓣寬度、萼片長度、萼片寬度和類別。Iris Setosa, Iris Virginica和Iris Versicolor是三個類。對於我們的無監督演算法,我們給出了Iris花的四個特徵,並預測了它屬於哪個類。
我們使用Python中的sklearn庫載入Iris數據集,使用matplotlib進行數據可視化。下面是用於處理數據集的代碼部分。
# Importing Modulesfrom sklearn import datasetsimport matplotlib.pyplot as plt# Loading datasetiris_df = datasets.load_iris()# Available methods on datasetprint(dir(iris_df))# Featuresprint(iris_df.feature_names)# Targetsprint(iris_df.target)# Target Namesprint(iris_df.target_names)label = {0: "red", 1: "blue", 2: "green"}# Dataset Slicingx_axis = iris_df.data[:, 0] # Sepal Lengthy_axis = iris_df.data[:, 2] # Sepal Width# Plottingplt.scatter(x_axis, y_axis, c=iris_df.target)plt.show()輸出結果:
["DESCR", "data","feature_names", "target", "target_names"]["sepal length (cm)", "sepal width (cm)","petal length (cm)", "petal width (cm)"][0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]["setosa" "versicolor" "virginica"]圖中:紫羅蘭色表示Setosa,綠色表示Versicolor,黃色表示Virginica
聚類(Clustering)
在聚類中,數據被分成幾個組。簡單來說:目的是將具有相似特徵的群體分開並將它們賦予不同的簇(cluster)中。
可視化的例子,
在上圖中,左邊的圖像是未進行分類的原始數據,右邊的圖像是聚類的結果(根據數據的特徵對數據進行劃分)。當給定一個要預測的輸入時,它將根據其特徵在簇(cluster)中檢查其所屬哪一個類別,並進行預測。
Python中的K-Means聚類
K-Means是一種迭代聚類演算法,旨在找到每次迭代中的局部最大值。由於我們知道涉及3個類,因此我們通過將參數「n_clusters」傳遞到KMeans模型中,對演算法進行編程,將數據分組為3個類。
現在隨機的三個樣本點(輸入)被分配到三個簇(cluster)中。然後後面樣本點和這每一個點算一下質心距離(centroid distance),然後選出並放入最優的簇(cluster)中。然後,重新計算所有簇(cluster)的centroids。
每一個聚類的中心是定義這一組樣本點的特徵值的集合,檢查中心特徵權重可以解釋每一個簇(cluster)代表的類型。
我們從sklearn庫中導入KMeans模型,擬合特徵並進行預測。
K-Means在Python中的實現:
# Importing Modulesfrom sklearn import datasetsfrom sklearn.cluster import KMeans# Loading datasetiris_df = datasets.load_iris()# Declaring Modelmodel = KMeans(n_clusters=3)# Fitting Modelmodel.fit(iris_df.data)# Predicitng a single inputpredicted_label = model.predict([[7.2, 3.5, 0.8, 1.6]])# Prediction on the entire dataall_predictions = model.predict(iris_df.data)# Printing Predictionsprint(predicted_label)print(all_predictions)輸出結果:
[0][0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 1 1 2 1 1 1 1 1 1 2 2 1 1 1 1 2 1 2 1 2 1 1 2 2 1 1 1 1 1 2 1 1 1 1 2 1 1 1 2 1 1 1 2 1 1 2]層次聚類(Hierarchical Clustering)
顧名思義,層次聚類是一種構建聚類層次結構的演算法。該演算法從分配給自己簇(cluster)的所有數據開始。然後將兩個最近的簇(cluster)連接到同一個簇(cluster)中。最後,當只剩下一個簇(cluster)時,該演算法就結束了。
層次聚類的完成可以用dendrogram來表示。現在讓我們看一個grain穀粒數據層次聚類的例子。
數據集地址:
https://raw.githubusercontent.com/vihar/unsupervised-learning-with-python/master/seeds-less-rows.csv.
Python中的層次聚類實現:
# Importing Modulesfrom scipy.cluster.hierarchy import linkage, dendrogramimport matplotlib.pyplot as pltimport pandas as pd# Reading the DataFrameseeds_df = pd.read_csv( "https://raw.githubusercontent.com/vihar/unsupervised-learning-with-python/master/seeds-less-rows.csv")# Remove the grain species from the DataFrame, save for latervarieties = list(seeds_df.pop("grain_variety"))# Extract the measurements as a NumPy arraysamples = seeds_df.values"""Perform hierarchical clustering on samples using thelinkage() function with the method="complete" keyword argument.Assign the result to mergings."""mergings = linkage(samples, method="complete")"""Plot a dendrogram using the dendrogram() function on mergings,specifying the keyword arguments labels=varieties, leaf_rotation=90,and leaf_font_size=6."""dendrogram(mergings, labels=varieties, leaf_rotation=90, leaf_font_size=6, )plt.show()輸出結果:
K-Means與層次聚類的區別
層次聚類不能很好地處理大數據,但K-Means聚類可以。這是因為K-Means的時間複雜度是線性的,即O(n),而層次聚類的時間複雜度是二次方,即O(n2)。
在K-Means聚類中,因為我們初始化的時候,會任意選擇不同的簇(cluster),所以多次運行演算法產生的結果可能會有所不同。然而層次聚類中是可重現的。
當簇(cluster)的形狀是超球形時(如2D中的圓,3D中的球),K-Means表現地很好。
K-Means不允許嘈雜的數據,而在層次中我們可以直接使用有雜訊的數據集進行聚類。
t-SNE聚類
它是一種無監督學習可視化的方法。t-SNE表示t-distributed stochastic neighborembedding。
它將高維空間映射到可以可視化的二維或三維空間。具體地說,它通過一個二維或三維點對每個高維對象進行建模,其方式是相似的對象由附近的點建模,而不相似的對象則由高概率的遠點建模。
具體可以查看專知以前的t-SNE詳解:
你真的會用 t-SNE 么?有關 t-SNE 的小技巧
Python中,基於Iris數據集的t-SNE聚類實現:
# Importing Modulesfrom sklearn import datasetsfrom sklearn.manifold import TSNEimport matplotlib.pyplot as plt# Loading datasetiris_df = datasets.load_iris()# Defining Modelmodel = TSNE(learning_rate=100)# Fitting Modeltransformed = model.fit_transform(iris_df.data)# Plotting 2d t-Snex_axis = transformed[:, 0]y_axis = transformed[:, 1]plt.scatter(x_axis, y_axis, c=iris_df.target)plt.show()輸出結果:
其中,紫羅蘭色:Setosa,綠色:Versicolor,黃色:Virginica
這裡Iris數據集具有四個特徵(4d),它被變換並以二維圖形表示。類似地,t-SNE模型可以應用於具有n個特徵的數據集。
DBSCAN聚類
DBSCAN(Density-Based Spatial Clusteringof Applications with Noise,具有雜訊的基於密度的聚類方法)是一種流行的聚類演算法,用於替代預測分析中的K-means。它不要求您輸入簇(cluster)的個數才能運行。但作為交換,你必須調整其他兩個參數(eps和min_samples)。
DBSCAN演算法的目的在於過濾低密度區域,發現稠密度樣本點。跟傳統的基於層次的聚類和劃分聚類的凸形聚類簇不同,該演算法可以發現任意形狀的聚類簇,與傳統的演算法相比它有如下優點:
(1)與K-MEANS比較起來,不需要輸入要劃分的聚類個數;
(2)聚類簇的形狀沒有偏倚;
(3)可以在需要時輸入過濾雜訊的參數;
scikit-learn為eps和min_samples參數提供了一個默認值,但通常需要對它們進行優化。eps是在同一鄰域中考慮的兩個數據點之間的最大距離。min_samples指的是簇(cluster)在鄰域中數據點數量的最小數目。
DBSCAN聚類的Python實現:
# Importing Modulesfrom sklearn.datasets import load_irisimport matplotlib.pyplot as pltfrom sklearn.cluster import DBSCANfrom sklearn.decomposition import PCA# Load Datasetiris = load_iris()# Declaring Modeldbscan = DBSCAN()# Fittingdbscan.fit(iris.data)# Transoring Using PCApca = PCA(n_components=2).fit(iris.data)pca_2d = pca.transform(iris.data)# Plot based on Classfor i in range(0, pca_2d.shape[0]): if dbscan.labels_[i] == 0: c1 = plt.scatter(pca_2d[i, 0], pca_2d[i, 1], c="r", marker="+") elif dbscan.labels_[i] == 1: c2 = plt.scatter(pca_2d[i, 0], pca_2d[i, 1], c="g", marker="o") elif dbscan.labels_[i] == -1: c3 = plt.scatter(pca_2d[i, 0], pca_2d[i, 1], c="b", marker="*")plt.legend([c1, c2, c3], ["Cluster 1", "Cluster 2", "Noise"])plt.title("DBSCAN finds 2 clusters and Noise")plt.show()輸出結果:
更多無監督方法:
主成分分析(PCA)
異常檢測(Anomaly detection)
自編碼(Autoencoders)
深度置信網路(Deep BeliefNets)
Hebbian Learning
生成對抗網路(GANs)
自組織映射(Self-Organizingmaps)
原文鏈接:
https://towardsdatascience.com/unsupervised-learning-with-python-173c51dc7f03
推薦閱讀: