時(shí)隔兩月開始繼續(xù)儲(chǔ)備機(jī)器學(xué)習(xí)的知識莹捡,監(jiān)督學(xué)習(xí)已經(jīng)告一段落加派,非監(jiān)督學(xué)習(xí)從聚類開始铸豁。
非監(jiān)督學(xué)習(xí)與監(jiān)督學(xué)習(xí)最大的區(qū)別在于目標(biāo)變量事先不存在慷荔,也就是說
監(jiān)督學(xué)習(xí)可以做到“對于輸入數(shù)據(jù)X能預(yù)測變量Y”汰寓,而非監(jiān)督學(xué)習(xí)能做到的是“從數(shù)據(jù)X中能發(fā)現(xiàn)什么口柳?”,比如“構(gòu)成X的最佳6個(gè)數(shù)據(jù)簇都是哪些有滑?”或者“X中哪三個(gè)特征最頻繁共現(xiàn)跃闹?”
這就很好玩了,比如我在Udacity的第三個(gè)項(xiàng)目毛好,一家批發(fā)經(jīng)銷商想將發(fā)貨方式從每周五次減少到每周三次望艺,簡稱成本,但是造成一些客戶的不滿意肌访,取消了提貨找默,帶來更大虧損,項(xiàng)目要求是通過分析客戶類別吼驶,選擇合適的發(fā)貨方式惩激,達(dá)到技能降低成本又能降低客戶不滿意度的目的。
什么是聚類
聚類將相似的對象歸到同一個(gè)簇中旨剥,幾乎可以應(yīng)用于所有對象咧欣,聚類的對象越相似,聚類效果越好轨帜。聚類與分類的不同之處在于分類預(yù)先知道所分的類到底是什么魄咕,而聚類則預(yù)先不知道目標(biāo),但是可以通過簇識別(cluster identification)告訴我們這些簇到底都是什么蚌父。
K-means
聚類的一種哮兰,之所以叫k-均值是因?yàn)樗梢园l(fā)現(xiàn)k個(gè)不同的簇毛萌,且每個(gè)簇的中心采用簇中所含值的均值計(jì)算而成。簇個(gè)數(shù)k是用戶給定的喝滞,每一個(gè)簇通過質(zhì)心來描述阁将。
k-means的工作流程是:
- 隨機(jī)確定k個(gè)初始點(diǎn)做為質(zhì)心
- 給數(shù)據(jù)集中的每個(gè)點(diǎn)找距其最近的質(zhì)心,并分配到該簇
- 將每個(gè)簇的質(zhì)心更新為該簇所有點(diǎn)的平均值
- 循環(huán)上兩部右遭,直到每個(gè)點(diǎn)的簇分配結(jié)果不在改變?yōu)橹?/li>
項(xiàng)目流程
載入數(shù)據(jù)集
import pandas as pd
data = pd.read_csv("customers.csv");
分析數(shù)據(jù)
顯示數(shù)據(jù)的一個(gè)描述
from IPython.display import display
display(data.discrie());
分析數(shù)據(jù)是一門學(xué)問做盅,感覺自己在這方面還需要多加練習(xí),數(shù)據(jù)描述包含數(shù)據(jù)總數(shù)窘哈,特征吹榴,每個(gè)特征的均值,標(biāo)準(zhǔn)差滚婉,還有最小值图筹、25%、50%让腹、75%远剩、最大值處的值,這些都可以很容易列出來骇窍,但是透過這些數(shù)據(jù)需要看到什么信息瓜晤,如何與需求目的結(jié)合,最開始還是比較吃力的像鸡』钣ィ可以先選擇幾個(gè)數(shù)值差異較大的樣本,然后結(jié)合數(shù)據(jù)描述和需求只估,對數(shù)據(jù)整體有一個(gè)把控志群。比如在Udacity的第三個(gè)項(xiàng)目中,給出客戶針對不同類型產(chǎn)品的年度采購額蛔钙,分析猜測每個(gè)樣本客戶的類型锌云。
三個(gè)樣本客戶
每個(gè)客戶究竟是什么類型,這個(gè)問題困擾我好久吁脱,第一次回答我只是看那個(gè)方面采購額最大桑涎,就給它一個(gè)最近的類型,提交項(xiàng)目后Reviewer這樣建議:
這里有一個(gè)問題, 你在討論一個(gè)樣本對某產(chǎn)品的采購時(shí)沒有以統(tǒng)計(jì)數(shù)據(jù)為參考. 注意, "大量" 和 "少量" 的描述都應(yīng)該相對于統(tǒng)計(jì)數(shù)據(jù)而言.
提示: 從data.describe()中你已經(jīng)得到了均值和四分位數(shù), 把它們利用起來.
恍然大悟兼贡,這才知道了該如何分析一份數(shù)據(jù)集攻冷,于是有了下面的回答
所以分析數(shù)據(jù)一定要結(jié)合統(tǒng)計(jì)數(shù)據(jù),四分位數(shù)和均值可以看做數(shù)據(jù)的骨架遍希,能夠一定程度勾勒出數(shù)據(jù)的分布等曼,可以通過箱線圖來可視化四分位數(shù)。
分析特征相關(guān)性
特征之間通常都有相關(guān)性,可以通過用移除某個(gè)特征后的數(shù)據(jù)集構(gòu)建一個(gè)監(jiān)督學(xué)習(xí)模型禁谦,用其余特征預(yù)測移除的特征胁黑,對結(jié)果進(jìn)行評分的方法來判斷特征間的相關(guān)性。比如用決策樹回歸模型和R2分?jǐn)?shù)來判斷某個(gè)特征是否必要州泊。
from sklearn.model_selection import train_test_split
from sklearn import tree
new_data = data.drop('Feature name', axis = 1);
X_train, X_test, y_train, y_test = train_test_split(new_data, data['Feature name'], test_size = 0.25, random_state = 50)
regressor = tree.DecisionTreeRegressor(random_state = 50).fit(X_train, y_train);
score = regressor.score(X_test, y_test)
print(score);
如果是負(fù)數(shù)丧蘸,說明該特征絕對不能少,因?yàn)槿鄙倭司蜔o法擬合數(shù)據(jù)遥皂。如果是1力喷,表示少了也無所謂,有一個(gè)跟它相關(guān)聯(lián)的特征能代替它渴肉,如果是0到1間的其他數(shù)冗懦,則可以少,只是有一定的影響仇祭,越靠近0,影響越大颈畸。
也可以通過散布矩陣(scatter matrix)來可視化特征分布乌奇,如果一個(gè)特征是必須的,則它和其他特征可能不會(huì)顯示任何關(guān)系眯娱,如果不是必須的礁苗,則可能和某個(gè)特征呈線性或其他關(guān)系。
# 對于數(shù)據(jù)中的每一對特征構(gòu)造一個(gè)散布矩陣
pd.tools.plotting.scatter_matrix(data, alpha = 0.3, figsize = (14,8), diagonal = 'kde');
數(shù)據(jù)預(yù)處理
(一)特征縮放
如果數(shù)據(jù)特征呈偏態(tài)分布徙缴,通常進(jìn)行非線性縮放试伙。
# 使用自然對數(shù)縮放數(shù)據(jù)
log_data = np.log(data);
# 為每一對新產(chǎn)生的特征制作一個(gè)散射矩陣
pd.tools.plotting.scatter_matrix(log_data, alpha = 0.3, figsize = (14,8), diagonal = 'kde');
可以發(fā)現(xiàn)散布矩陣變成了下圖
(二)異常值檢測
通常用Tukey的定義異常值的方法檢測異常值。
一個(gè)異常階(outlier step)被定義成1.5倍的四分位距(interquartile range于样,IQR)疏叨。一個(gè)數(shù)據(jù)點(diǎn)如果某個(gè)特征包含在該特征的IQR之外的特征,那么該數(shù)據(jù)點(diǎn)被認(rèn)定為異常點(diǎn)穿剖。
# 對于每一個(gè)特征蚤蔓,找到值異常高或者是異常低的數(shù)據(jù)點(diǎn)
for feature in log_data.keys():
# 計(jì)算給定特征的Q1(數(shù)據(jù)的25th分位點(diǎn))
Q1 = np.percentile(log_data[feature], 25);
#計(jì)算給定特征的Q3(數(shù)據(jù)的75th分位點(diǎn))
Q3 = np.percentile(log_data[feature], 75);
#使用四分位范圍計(jì)算異常階(1.5倍的四分位距)
step = (Q3 - Q1) * 1.5;
# 顯示異常點(diǎn)
print "Data points considered outliers for the feature '{}':".format(feature)
display(log_data[~((log_data[feature] >= Q1 - step) & (log_data[feature] <= Q3 + step))])
# 可選:選擇你希望移除的數(shù)據(jù)點(diǎn)的索引
outliers = [65, 66, 75, 154, 128];
# 如果選擇了的話,移除異常點(diǎn)
good_data = log_data.drop(log_data.index[outliers]).reset_index(drop = True)
移除異常值需要具體情況具體考慮糊余,但是要謹(jǐn)慎秀又,因?yàn)槲覀冃枰浞掷斫鈹?shù)據(jù),記錄號移除的點(diǎn)以及移除原因贬芥⊥抡蓿可以用counter來輔助尋找出現(xiàn)次數(shù)大于1的離群點(diǎn)。
from collections import Counter
print dict(Counter(['a', 'b', 'c', 'a', 'b', 'b'])) # {'b': 3, 'a': 2, 'c': 1}
(三)特征轉(zhuǎn)換
特征轉(zhuǎn)換主要用到主成分分析發(fā)蘸劈,請查看之前介紹昏苏。
聚類
有些問題的聚類數(shù)目可能是已知的,但是我們并不能保證某個(gè)聚類的數(shù)目對這個(gè)數(shù)據(jù)是最優(yōu)的,因?yàn)槲覀儗?shù)據(jù)的結(jié)構(gòu)是不清楚的捷雕。但是我們可以通過計(jì)算每一個(gè)簇中點(diǎn)的輪廓系數(shù)來衡量聚類的質(zhì)量椒丧。數(shù)據(jù)點(diǎn)的輪廓系數(shù)衡量了分配給它的簇的相似度,范圍-1(不相似)到1(相似)救巷。平均輪廓系數(shù)為我們提供了一種簡單地度量聚類質(zhì)量的方法壶熏。
下面代碼會(huì)顯示聚類數(shù)為2時(shí)的平均輪廓系數(shù),可以修改n_clusters來得到不同聚類數(shù)目下的平均輪廓系數(shù)浦译。
from sklearn.cluster import KMeans
clusterer = KMeans(n_clusters=2, random_state=50).fit(reduced_data);
# 預(yù)測每一個(gè)點(diǎn)的簇
preds = clusterer.predict(reduced_data);
# 找到聚類中心
centers = clusterer.cluster_centers_;
# 計(jì)算選擇的類別的平均輪廓系數(shù)(mean silhouette coefficient)
from sklearn.metrics import silhouette_score
score = silhouette_score(reduced_data, preds);
數(shù)據(jù)恢復(fù)
如果用對數(shù)做了降維棒假,可以用指數(shù)將數(shù)據(jù)恢復(fù)。