摘要:本文簡單敘述瞭如何用聚類來經過投票記錄分析美國參議員的實際政治傾向python
聲明:(本文的內容非原創,但通過本人翻譯和總結而來,轉載請註明出處)算法
本文內容來源:https://www.dataquest.io/mission/60/clustering-basicsdom
在前面的兩篇文章中使用的線性迴歸和分類都屬於有監督的機器學習(根據已有的數據訓練模型,而後預測未知的數據),而無監督的學習則不是嘗試預測任何東西,而是尋找數據中的特徵,在無監督學習中,有一個重要的方法稱爲聚類。聚類算法是把具備相同特徵的數據彙集在一組。機器學習
原始數據展示ide
在美國的參議院要經過一項法律時,須要由參議員來投票,而這些議員主要來自於兩個政黨,共和黨(Democrats)和民主黨(Republicans),如今使用的數據就是這些議員的投票記錄,每一行表明了一個議員的狀況(party – 所屬政黨,D表明共和黨,R表明民主黨,I表明無黨派, 第三列以後都表明了某一個法案的投票狀況,1表明同意,0表明反對,0.5表明棄權)學習
import pandas votes = pandas.read_csv('114_congress.csv')
統計一下每一個政黨的人數idea
print(votes["party"].value_counts())
聚類算法spa
計算距離翻譯
爲了把具備相同特徵的議員彙集在一組,就須要衡量兩個議員的特徵究竟有多麼的接近,在這裏使用的是歐幾里德距離計算公式3d
譬如取前兩個議員的記錄來進行計算,這是他們的投票結果:
計算結果:d = 1.73
在python中計算歐幾里德距離,能夠經過scikit-learn庫的euclidean_distances()方法,如今仍然計算前兩個議員的距離
from sklearn.metrics.pairwise import euclidean_distances print(euclidean_distances(votes.iloc[0,3:], votes.iloc[1,3:])) # 由於前三列不是數字類型,因此要排除前三列的數據
聚類
接下來會使用k-means聚類算法來根據歐幾里德距離來將數據進行分組彙集,每一組都會有一箇中心點,而後計算每一個議員到這個中心點的距離,再將該議員分配到距離最小的那個中心點所屬的組中。下面使用scikit-learn庫來訓練一個k-means模型(由於主要有兩個政黨,因此分爲兩組便可)
import pandas as pd from sklearn.cluster import KMeans # n_clusters參數指定分組數量,random_state = 1用來重現一樣的結果 kmeans_model = KMeans(n_clusters=2, random_state=1) # 經過fit_transform()方法來訓練模型 senator_distances = kmeans_model.fit_transform(votes.iloc[:, 3:])
生成的是一個ndarray,每一行表明了一個議員,第一列表明瞭該議員與第一組中心點的距離,第二列表明瞭該議員與第二組中心點的距離
統計
通過上面的計算,如今要統計在每一組中究竟分佈着多少個來自於不一樣政黨的議員(相似於透視圖),使用Pandas中的crosstab()方法能夠進行統計,該方法須要兩個向量或者Series做爲參數來進行統計
labels = kmeans_model.labels_ print(pd.crosstab(labels, votes["party"]))
上面語句中的labels變量的結果以下:(在ndarray中的每一個元素表明了一個議員所屬的組編號,其編號取其距離最小的那組)
上面的結果顯示,第一組包含了41個民主黨議員和兩個無黨派議員,第二組包含了3個民主黨議員和54個共和黨議員,看起來有3個民主黨議員的政治傾向更偏於共和黨,而這三位仁兄就是
democratic_outliers = votes[(labels == 1) & (votes["party"] == "D")]
數據可視化
在上面的計算中,已經把每位議員到兩個組的舉例計算出來了,如今將這兩個距離數據分別做爲x和y座標,而後作一個散點圖,而且根據它們的組編號進行不一樣着色
plt.scatter(x=senator_distances[:,0], y=senator_distances[:,1], c=labels)
plt.show()
尋找激進分子
能夠根據上面計算的每一個議員與組的距離來判斷一個議員是否屬於激進分子,最激進的議員就是那些遠離一個組中心點最遠的數據點,而處於兩個中心點的數據點則代表這是比較溫和的議員。要衡量這個激進程度,能夠經過對兩個距離計算結果進行指數運算來放大差別性。例如對於某個激進議員extremist = [3.4, .24]和溫和議員moderate = [2.6, 2],若是隻是簡單相加其結果,就會獲得3.4 + .24 = 3.64, 和2.6 + 2 = 4.6,看起來他們之間的差距並不大。然而,將它們分別進行立方運算再相加3.4 ** 3 + .24 ** 3 = 39.3, 和2.6 ** 3 + 2 ** 3 = 25.5,就能體現他們之間的差別性了
extremism = (senator_distances ** 3).sum(axis=1) votes["extremism"] = extremism votes.sort("extremism", inplace=True, ascending=False) # 根據激進性進行降序排序
總結
聚類是一個用來尋找數據特徵的強有力的方法,在使用有監督的機器學習方法並無取得進展時,能夠嘗試使用無監督的學習方法,一般來講,在使用有監督學習方法以前先使用無監督學習方法是一個不錯的開始。