建立用戶分類

 

 

 

 

機器學習納米學位

非監督學習

項目 3: 建立用戶分類

 

歡迎來到機器學習工程師納米學位的第三個項目!在這個notebook文件中,有些模板代碼已經提供給你,但你還須要實現更多的功能來完成這個項目。除非有明確要求,你無須修改任何已給出的代碼。以'練習'開始的標題表示接下來的代碼部分中有你必需要實現的功能。每一部分都會有詳細的指導,須要實現的部分也會在註釋中以'TODO'標出。請仔細閱讀全部的提示!javascript

除了實現代碼外,你還必須回答一些與項目和你的實現有關的問題。每個須要你回答的問題都會以'問題 X'爲標題。請仔細閱讀每一個問題,而且在問題後的'回答'文字框中寫出完整的答案。咱們將根據你對問題的回答和撰寫代碼所實現的功能來對你提交的項目進行評分。php

提示:Code 和 Markdown 區域可經過 Shift + Enter 快捷鍵運行。此外,Markdown能夠經過雙擊進入編輯模式。css

 

開始

在這個項目中,你將分析一個數據集的內在結構,這個數據集包含不少客戶真對不一樣類型產品的年度採購額(用金額表示)。這個項目的任務之一是如何最好地描述一個批發商不一樣種類顧客之間的差別。這樣作將可以使得批發商可以更好的組織他們的物流服務以知足每一個客戶的需求。html

這個項目的數據集可以在UCI機器學習信息庫中找到.由於這個項目的目的,分析將不會包括'Channel'和'Region'這兩個特徵——重點集中在6個記錄的客戶購買的產品類別上。html5

運行下面的的代碼單元以載入整個客戶數據集和一些這個項目須要的Python庫。若是你的數據集載入成功,你將看到後面輸出數據集的大小。java

In [1]:
# 檢查你的Python版本
from sys import version_info
if version_info.major != 2 and version_info.minor != 7:
    raise Exception('請使用Python 2.7來完成此項目')
In [2]:
# 引入這個項目須要的庫
import numpy as np
import pandas as pd
import visuals as vs
from IPython.display import display # 使得咱們能夠對DataFrame使用display()函數

# 設置之內聯的形式顯示matplotlib繪製的圖片(在notebook中顯示更美觀)
%matplotlib inline

# 載入整個客戶數據集
try:
    data = pd.read_csv("customers.csv")
    data.drop(['Region', 'Channel'], axis = 1, inplace = True)
    print "Wholesale customers dataset has {} samples with {} features each.".format(*data.shape)
except:
    print "Dataset could not be loaded. Is the dataset missing?"
 
Wholesale customers dataset has 440 samples with 6 features each.
 

分析數據

在這部分,你將開始分析數據,經過可視化和代碼來理解每個特徵和其餘特徵的聯繫。你會看到關於數據集的統計描述,考慮每個屬性的相關性,而後從數據集中選擇若干個樣本數據點,你將在整個項目中一直跟蹤研究這幾個數據點。node

運行下面的代碼單元給出數據集的一個統計描述。注意這個數據集包含了6個重要的產品類型:'Fresh', 'Milk', 'Grocery', 'Frozen', 'Detergents_Paper''Delicatessen'。想一下這裏每個類型表明你會購買什麼樣的產品。python

In [3]:
# 顯示數據集的一個描述
display(data.describe())
 
 
  Fresh Milk Grocery Frozen Detergents_Paper Delicatessen
count 440.000000 440.000000 440.000000 440.000000 440.000000 440.000000
mean 12000.297727 5796.265909 7951.277273 3071.931818 2881.493182 1524.870455
std 12647.328865 7380.377175 9503.162829 4854.673333 4767.854448 2820.105937
min 3.000000 55.000000 3.000000 25.000000 3.000000 3.000000
25% 3127.750000 1533.000000 2153.000000 742.250000 256.750000 408.250000
50% 8504.000000 3627.000000 4755.500000 1526.000000 816.500000 965.500000
75% 16933.750000 7190.250000 10655.750000 3554.250000 3922.000000 1820.250000
max 112151.000000 73498.000000 92780.000000 60869.000000 40827.000000 47943.000000
 

練習: 選擇樣本

爲了對客戶有一個更好的瞭解,而且瞭解表明他們的數據將會在這個分析過程當中如何變換。最好是選擇幾個樣本數據點,而且更爲詳細地分析它們。在下面的代碼單元中,選擇三個索引加入到索引列表indices中,這三個索引表明你要追蹤的客戶。咱們建議你不斷嘗試,直到找到三個明顯不一樣的客戶。jquery

In [11]:
# TODO:從數據集中選擇三個你但願抽樣的數據點的索引
indices = [2, 9, 200]

# 爲選擇的樣本創建一個DataFrame
samples = pd.DataFrame(data.loc[indices], columns = data.keys()).reset_index(drop = True)
print "Chosen samples of wholesale customers dataset:"
display(samples)
 
Chosen samples of wholesale customers dataset:
 
 
  Fresh Milk Grocery Frozen Detergents_Paper Delicatessen
0 6353 8808 7684 2405 3516 7844
1 6006 11093 18881 1159 7425 2098
2 3067 13240 23127 3941 9959 731
 

問題 1

在你看來你選擇的這三個樣本點分別表明什麼類型的企業(客戶)?對每個你選擇的樣本客戶,經過它在每一種產品類型上的花費與數據集的統計描述進行比較,給出你作上述判斷的理由。linux

提示: 企業的類型包括超市、咖啡館、零售商以及其餘。注意不要使用具體企業的名字,好比說在描述一個餐飲業客戶時,你不能使用麥當勞。

 

回答:

  • 0號樣本表明零售商,Fresh在50%,Milk在75%,Grocery在75%,Frozen在50%,Detergents_Paper在75%,Delicatessen在75%,全部基本都在平均數左右,表明每樣東西都有一些,可是都不算特別多,且沒有某列數據特別多,因此是零售商的可能性較大

  • 1號樣本表明其餘,Fresh在75%,Milk在75%,Grocery在75%,Frozen在50%,Detergents_Paper在75%,Delicatessen在75%,大部分數據都超過平均值,類型廣沒有特別類型突出,因此是一個大型超市的可能性比較大

  • 2號樣本表明,Fresh在25%,Milk在75%以上,Grocery在75%以上,Frozen在75%以上,Detergents_Paper在75%以上,Delicatessen在25%,多是奶茶店

 

練習: 特徵相關性

一個有趣的想法是,考慮這六個類別中的一個(或者多個)產品類別,是否對於理解客戶的購買行爲具備實際的相關性。也就是說,當用戶購買了必定數量的某一類產品,咱們是否可以肯定他們必然會成比例地購買另外一種類的產品。有一個簡單的方法能夠檢測相關性:咱們用移除了某一個特徵以後的數據集來構建一個監督學習(迴歸)模型,而後用這個模型去預測那個被移除的特徵,再對這個預測結果進行評分,看看預測結果如何。

在下面的代碼單元中,你須要實現如下的功能:

  • 使用DataFrame.drop函數移除數據集中你選擇的不須要的特徵,並將移除後的結果賦值給new_data
  • 使用sklearn.model_selection.train_test_split將數據集分割成訓練集和測試集。
    • 使用移除的特徵做爲你的目標標籤。設置test_size0.25並設置一個random_state
  • 導入一個DecisionTreeRegressor(決策樹迴歸器),設置一個random_state,而後用訓練集訓練它。
  • 使用迴歸器的score函數輸出模型在測試集上的預測得分。
In [17]:
# TODO:爲DataFrame建立一個副本,用'drop'函數丟棄一個特徵
new_data = data.drop(['Fresh'],axis=1)
labels = data['Fresh']

# TODO:使用給定的特徵做爲目標,將數據分割成訓練集和測試集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(new_data, labels, test_size=0.25, random_state=1)

# TODO:建立一個DecisionTreeRegressor(決策樹迴歸器)並在訓練集上訓練它
from sklearn.tree import DecisionTreeRegressor
regressor = DecisionTreeRegressor(random_state=0)
regressor.fit(X_train,y_train)
y_pred = regressor.predict(X_test)

# TODO:輸出在測試集上的預測得分
from sklearn.metrics import r2_score
score = r2_score(y_test,y_pred)
print score
 
-1.13897180207
 

問題 2

你嘗試預測哪個特徵?預測的得分是多少?這個特徵對於區分用戶的消費習慣來講必要嗎?爲何?
提示: 決定係數(coefficient of determination), R^2,結果在0到1之間,1表示完美擬合,一個負的R^2表示模型不可以擬合數據。

 

回答:

  • Fresh
    • -1.13897180207
    • 模型不可以擬合數據
    • 這個特徵對於區分用戶的消費習慣來講必要
 

可視化特徵分佈

爲了可以對這個數據集有一個更好的理解,咱們能夠對數據集中的每個產品特徵構建一個散佈矩陣(scatter matrix)。若是你發現你在上面嘗試預測的特徵對於區分一個特定的用戶來講是必須的,那麼這個特徵和其它的特徵可能不會在下面的散射矩陣中顯示任何關係。相反的,若是你認爲這個特徵對於識別一個特定的客戶是沒有做用的,那麼經過散佈矩陣能夠看出在這個數據特徵和其它特徵中有關聯性。運行下面的代碼以建立一個散佈矩陣。

In [18]:
# 對於數據中的每一對特徵構造一個散佈矩陣
pd.plotting.scatter_matrix(data, alpha = 0.3, figsize = (14,8), diagonal = 'kde');
 
 

問題 3

這裏是否存在一些特徵他們彼此之間存在必定程度相關性?若是有請列出。這個結果是驗證了仍是否定了你嘗試預測的那個特徵的相關性?這些特徵的數據是怎麼分佈的?

提示: 這些數據是正態分佈(normally distributed)的嗎?大多數的數據點分佈在哪?

 

回答:

  • 不是正態分佈。
  • 大多數數據點分佈在數值較小的左側。
  • Grocery和Milk、Detergents_paper有相關性,Detergents_paper與Grocery有相關性
 

數據預處理

在這個部分,你將經過在數據上作一個合適的縮放,並檢測異常點(你能夠選擇性移除)將數據預處理成一個更好的表明客戶的形式。預處理數據是保證你在分析中可以獲得顯著且有意義的結果的重要環節。

 

練習: 特徵縮放

若是數據不是正態分佈的,尤爲是數據的平均數和中位數相差很大的時候(表示數據很是歪斜)。這時候一般用一個非線性的縮放是很合適的(英文原文) — 尤爲是對於金融數據。一種實現這個縮放的方法是使用Box-Cox 變換,這個方法可以計算出可以最佳減少數據傾斜的指數變換方法。一個比較簡單的而且在大多數狀況下都適用的方法是使用天然對數。

在下面的代碼單元中,你將須要實現如下功能:

  • 使用np.log函數在數據 data 上作一個對數縮放,而後將它的副本(不改變原始data的值)賦值給log_data
  • 使用np.log函數在樣本數據 samples 上作一個對數縮放,而後將它的副本賦值給log_samples
In [19]:
# TODO:使用天然對數縮放數據
log_data = np.log(data)

# TODO:使用天然對數縮放樣本數據
log_samples = np.log(samples)

# 爲每一對新產生的特徵製做一個散射矩陣
pd.plotting.scatter_matrix(log_data, alpha = 0.3, figsize = (14,8), diagonal = 'kde');
 
 

觀察

在使用了一個天然對數的縮放以後,數據的各個特徵會顯得更加的正態分佈。對於任意的你之前發現有相關關係的特徵對,觀察他們的相關關係是否仍是存在的(而且嘗試觀察,他們的相關關係相比原來是變強了仍是變弱了)。

運行下面的代碼以觀察樣本數據在進行了天然對數轉換以後如何改變了。

In [20]:
# 展現通過對數變換後的樣本數據
display(log_samples)
 
 
  Fresh Milk Grocery Frozen Detergents_Paper Delicatessen
0 8.756682 9.083416 8.946896 7.785305 8.165079 8.967504
1 8.700514 9.314070 9.845911 7.055313 8.912608 7.648740
2 8.028455 9.490998 10.048756 8.279190 9.206232 6.594413
 

練習: 異常值檢測

對於任何的分析,在數據預處理的過程當中檢測數據中的異常值都是很是重要的一步。異常值的出現會使得把這些值考慮進去後結果出現傾斜。這裏有不少關於怎樣定義什麼是數據集中的異常值的經驗法則。這裏咱們將使用Tukey的定義異常值的方法:一個異常階(outlier step)被定義成1.5倍的四分位距(interquartile range,IQR)。一個數據點若是某個特徵包含在該特徵的IQR以外的特徵,那麼該數據點被認定爲異常點。

在下面的代碼單元中,你須要完成下面的功能:

  • 將指定特徵的25th分位點的值分配給Q1。使用np.percentile來完成這個功能。
  • 將指定特徵的75th分位點的值分配給Q3。一樣的,使用np.percentile來完成這個功能。
  • 將指定特徵的異常階的計算結果賦值給step.
  • 選擇性地經過將索引添加到outliers列表中,以移除異常值。

注意: 若是你選擇移除異常值,請保證你選擇的樣本點不在這些移除的點當中! 一旦你完成了這些功能,數據集將存儲在good_data中。

In [29]:
outliers = []
# 對於每個特徵,找到值異常高或者是異常低的數據點
for feature in log_data.keys():
    
    # TODO:計算給定特徵的Q1(數據的25th分位點)
    Q1 = np.percentile(log_data[feature], 25)
    
    # TODO:計算給定特徵的Q3(數據的75th分位點)
    Q3 = np.percentile(log_data[feature], 75)
    
    # TODO:使用四分位範圍計算異常階(1.5倍的四分位距)
    step = (Q3 - Q1) * 1.5
    
    outdatas = log_data[~((log_data[feature] >= Q1 - step) & (log_data[feature] <= Q3 + step))]
    outliers.extend(outdatas.index.tolist())
    # 顯示異常點
    print "Data points considered outliers for the feature '{}':".format(feature)
    display(log_data[~((log_data[feature] >= Q1 - step) & (log_data[feature] <= Q3 + step))])
    
# 可選:選擇你但願移除的數據點的索引
# outliers  = []
outliers = [val for val in list(set(outliers)) if outliers.count(val)>=2]
print outliers

# 若是選擇了的話,移除異常點
good_data = log_data.drop(log_data.index[outliers]).reset_index(drop = True)
 
Data points considered outliers for the feature 'Fresh':
 
 
  Fresh Milk Grocery Frozen Detergents_Paper Delicatessen
65 4.442651 9.950323 10.732651 3.583519 10.095388 7.260523
66 2.197225 7.335634 8.911530 5.164786 8.151333 3.295837
81 5.389072 9.163249 9.575192 5.645447 8.964184 5.049856
95 1.098612 7.979339 8.740657 6.086775 5.407172 6.563856
96 3.135494 7.869402 9.001839 4.976734 8.262043 5.379897
128 4.941642 9.087834 8.248791 4.955827 6.967909 1.098612
171 5.298317 10.160530 9.894245 6.478510 9.079434 8.740337
193 5.192957 8.156223 9.917982 6.865891 8.633731 6.501290
218 2.890372 8.923191 9.629380 7.158514 8.475746 8.759669
304 5.081404 8.917311 10.117510 6.424869 9.374413 7.787382
305 5.493061 9.468001 9.088399 6.683361 8.271037 5.351858
338 1.098612 5.808142 8.856661 9.655090 2.708050 6.309918
353 4.762174 8.742574 9.961898 5.429346 9.069007 7.013016
355 5.247024 6.588926 7.606885 5.501258 5.214936 4.844187
357 3.610918 7.150701 10.011086 4.919981 8.816853 4.700480
412 4.574711 8.190077 9.425452 4.584967 7.996317 4.127134
 
Data points considered outliers for the feature 'Milk':
 
 
  Fresh Milk Grocery Frozen Detergents_Paper Delicatessen
86 10.039983 11.205013 10.377047 6.894670 9.906981 6.805723
98 6.220590 4.718499 6.656727 6.796824 4.025352 4.882802
154 6.432940 4.007333 4.919981 4.317488 1.945910 2.079442
356 10.029503 4.897840 5.384495 8.057377 2.197225 6.306275
 
Data points considered outliers for the feature 'Grocery':
 
 
  Fresh Milk Grocery Frozen Detergents_Paper Delicatessen
75 9.923192 7.036148 1.098612 8.390949 1.098612 6.882437
154 6.432940 4.007333 4.919981 4.317488 1.945910 2.079442
 
Data points considered outliers for the feature 'Frozen':
 
 
  Fresh Milk Grocery Frozen Detergents_Paper Delicatessen
38 8.431853 9.663261 9.723703 3.496508 8.847360 6.070738
57 8.597297 9.203618 9.257892 3.637586 8.932213 7.156177
65 4.442651 9.950323 10.732651 3.583519 10.095388 7.260523
145 10.000569 9.034080 10.457143 3.737670 9.440738 8.396155
175 7.759187 8.967632 9.382106 3.951244 8.341887 7.436617
264 6.978214 9.177714 9.645041 4.110874 8.696176 7.142827
325 10.395650 9.728181 9.519735 11.016479 7.148346 8.632128
420 8.402007 8.569026 9.490015 3.218876 8.827321 7.239215
429 9.060331 7.467371 8.183118 3.850148 4.430817 7.824446
439 7.932721 7.437206 7.828038 4.174387 6.167516 3.951244
 
Data points considered outliers for the feature 'Detergents_Paper':
 
 
  Fresh Milk Grocery Frozen Detergents_Paper Delicatessen
75 9.923192 7.036148 1.098612 8.390949 1.098612 6.882437
161 9.428190 6.291569 5.645447 6.995766 1.098612 7.711101
 
Data points considered outliers for the feature 'Delicatessen':
 
 
  Fresh Milk Grocery Frozen Detergents_Paper Delicatessen
66 2.197225 7.335634 8.911530 5.164786 8.151333 3.295837
109 7.248504 9.724899 10.274568 6.511745 6.728629 1.098612
128 4.941642 9.087834 8.248791 4.955827 6.967909 1.098612
137 8.034955 8.997147 9.021840 6.493754 6.580639 3.583519
142 10.519646 8.875147 9.018332 8.004700 2.995732 1.098612
154 6.432940 4.007333 4.919981 4.317488 1.945910 2.079442
183 10.514529 10.690808 9.911952 10.505999 5.476464 10.777768
184 5.789960 6.822197 8.457443 4.304065 5.811141 2.397895
187 7.798933 8.987447 9.192075 8.743372 8.148735 1.098612
203 6.368187 6.529419 7.703459 6.150603 6.860664 2.890372
233 6.871091 8.513988 8.106515 6.842683 6.013715 1.945910
285 10.602965 6.461468 8.188689 6.948897 6.077642 2.890372
289 10.663966 5.655992 6.154858 7.235619 3.465736 3.091042
343 7.431892 8.848509 10.177932 7.283448 9.646593 3.610918
 
[128, 154, 65, 66, 75]
 

問題 4

請列出全部在多於一個特徵下被看做是異常的數據點。這些點應該被從數據集中移除嗎?爲何?把你認爲須要移除的數據點所有加入到到outliers變量中。

 

回答:

  • 12八、15四、6五、6六、75這幾個數據多於一個特徵下被看做了異常點,應該被移除 -
  • 由於異常點的存在會致使訓練數據的偏差增大,因此須要去除
 

特徵轉換

在這個部分中你將使用主成分分析(PCA)來分析批發商客戶數據的內在結構。因爲使用PCA在一個數據集上會計算出最大化方差的維度,咱們將找出哪個特徵組合可以最好的描繪客戶。

 

練習: 主成分分析(PCA)

既然數據被縮放到一個更加正態分佈的範圍中而且咱們也移除了須要移除的異常點,咱們如今就可以在good_data上使用PCA算法以發現數據的哪個維度可以最大化特徵的方差。除了找到這些維度,PCA也將報告每個維度的解釋方差比(explained variance ratio)--這個數據有多少方差可以用這個單獨的維度來解釋。注意PCA的一個組成部分(維度)可以被看作這個空間中的一個新的「特徵」,可是它是原來數據中的特徵構成的。

在下面的代碼單元中,你將要實現下面的功能:

  • 導入sklearn.decomposition.PCA而且將good_data用PCA而且使用6個維度進行擬合後的結果保存到pca中。
  • 使用pca.transformlog_samples進行轉換,並將結果存儲到pca_samples中。
In [35]:
# TODO:經過在good_data上使用PCA,將其轉換成和當前特徵數同樣多的維度
from sklearn.decomposition import PCA
pca = PCA(n_components=6)
pca.fit(good_data)

# TODO:使用上面的PCA擬合將變換施加在log_samples上
pca_samples = pca.transform(log_samples)

# 生成PCA的結果圖
pca_results = vs.pca_results(good_data, pca)
 
 

問題 5

數據的第一個和第二個主成分 總共 表示了多少的方差? 前四個主成分呢?使用上面提供的可視化圖像,討論從用戶花費的角度來看前四個主要成分的消費行爲最能表明哪一種類型的客戶並給出你作出判斷的理由。

提示: 某一特定維度上的正向增加對應正權特徵的增加負權特徵的減小。增加和減小的速率和每一個特徵的權重相關。參考資料(英文)

 

回答:

  • 數據的第一個和第二個主成分總共表示了0.7068的方差。
  • 數據的前四個主成分總共表示了0.9311的方差。
  • 第一個主成分高表示他們買 Fresh 和 Frozen 比較多,其餘的都不多,因此它多是一個烤肉店。
  • 第二個主成分高表示他們買這些東西都不多,都是負的。
  • 第三個是買 Delicatessen和Frozen 比較多,其餘的都不多,因此它多是一個熟食店。
  • 第四個買 Frozen 和 Detergents Paper 比較多,多是一個超市。
 

觀察

運行下面的代碼,查看通過對數轉換的樣本數據在進行一個6個維度的主成分分析(PCA)以後會如何改變。觀察樣本數據的前四個維度的數值。考慮這和你初始對樣本點的解釋是否一致。

In [36]:
# 展現通過PCA轉換的sample log-data
display(pd.DataFrame(np.round(pca_samples, 4), columns = pca_results.index.values))
 
 
  Dimension 1 Dimension 2 Dimension 3 Dimension 4 Dimension 5 Dimension 6
0 -1.8834 -1.5991 1.3204 -0.5432 -0.3934 -0.3117
1 -2.8734 -0.6774 0.1330 -0.1802 -0.0250 0.1224
2 -2.9903 -0.3645 0.2521 1.5653 0.1922 0.1244
 

練習:降維

當使用主成分分析的時候,一個主要的目的是減小數據的維度,這實際上下降了問題的複雜度。固然降維也是須要必定代價的:更少的維度可以表示的數據中的總方差更少。由於這個,累計解釋方差比(cumulative explained variance ratio)對於咱們肯定這個問題須要多少維度很是重要。另外,若是大部分的方差都可以經過兩個或者是三個維度進行表示的話,降維以後的數據可以被可視化。

在下面的代碼單元中,你將實現下面的功能:

  • good_data用兩個維度的PCA進行擬合,並將結果存儲到pca中去。
  • 使用pca.transformgood_data進行轉換,並將結果存儲在reduced_data中。
  • 使用pca.transformlog_samples進行轉換,並將結果存儲在pca_samples中。
In [37]:
# TODO:經過在good data上進行PCA,將其轉換成兩個維度
from sklearn.decomposition import  PCA
pca = PCA(n_components=2)
pca.fit(good_data)

# TODO:使用上面訓練的PCA將good data進行轉換
reduced_data = pca.transform(good_data)

# TODO:使用上面訓練的PCA將log_samples進行轉換
pca_samples = pca.transform(log_samples)

# 爲降維後的數據建立一個DataFrame
reduced_data = pd.DataFrame(reduced_data, columns = ['Dimension 1', 'Dimension 2'])
 

觀察

運行如下代碼觀察當僅僅使用兩個維度進行PCA轉換後,這個對數樣本數據將怎樣變化。觀察這裏的結果與一個使用六個維度的PCA轉換相比較時,前兩維的數值是保持不變的。

In [38]:
# 展現通過兩個維度的PCA轉換以後的樣本log-data
display(pd.DataFrame(np.round(pca_samples, 4), columns = ['Dimension 1', 'Dimension 2']))
 
 
  Dimension 1 Dimension 2
0 -1.8834 -1.5991
1 -2.8734 -0.6774
2 -2.9903 -0.3645
 

可視化一個雙標圖(Biplot)

雙標圖是一個散點圖,每一個數據點的位置由它所在主成分的分數肯定。座標系是主成分(這裏是Dimension 1Dimension 2)。此外,雙標圖還展現出初始特徵在主成分上的投影。一個雙標圖能夠幫助咱們理解降維後的數據,發現主成分和初始特徵之間的關係。

運行下面的代碼來建立一個降維後數據的雙標圖。

In [39]:
# Create a biplot
vs.biplot(good_data, reduced_data, pca)
Out[39]:
<matplotlib.axes._subplots.AxesSubplot at 0x1184c4950>
 
 

觀察

一旦咱們有了原始特徵的投影(紅色箭頭),就能更加容易的理解散點圖每一個數據點的相對位置。

在這個雙標圖中,哪些初始特徵與第一個主成分有強關聯?哪些初始特徵與第二個主成分相關聯?你觀察到的是否與以前獲得的 pca_results 圖相符?

 

聚類

在這個部分,你講選擇使用K-Means聚類算法或者是高斯混合模型聚類算法以發現數據中隱藏的客戶分類。而後,你將從簇中恢復一些特定的關鍵數據點,經過將它們轉換回原始的維度和規模,從而理解他們的含義。

 

問題 6

使用K-Means聚類算法的優勢是什麼?使用高斯混合模型聚類算法的優勢是什麼?基於你如今對客戶數據的觀察結果,你選用了這兩個算法中的哪個,爲何?

 

回答:

  • K-Means算法的優勢是簡潔和快速,設t步算法結束,時間複雜度爲O(nkt),通常有k<<n和t<<n,適合大規模的數據挖掘。
  • 不容易理解,須要翻翻統計學的教材。假設各個特徵的權重不一樣,假設各個聚類中的數據分佈不均勻。理論上能夠擬合任何連續函數。計算量較大。若是其中一個聚類的數據並不服從正態分佈、偏態分佈,聚類算法會出現誤差。
  • 選擇了高斯混合模型聚類,由於處理過的數據基本服從正態分佈,因此可能會有較好的效果
 

練習: 建立聚類

針對不一樣狀況,有些問題你須要的聚類數目多是已知的。可是在聚類數目不做爲一個先驗知道的狀況下,咱們並不可以保證某個聚類的數目對這個數據是最優的,由於咱們對於數據的結構(若是存在的話)是不清楚的。可是,咱們能夠經過計算每個簇中點的輪廓係數來衡量聚類的質量。數據點的輪廓係數衡量了它與分配給他的簇的類似度,這個值範圍在-1(不類似)到1(類似)。平均輪廓係數爲咱們提供了一種簡單地度量聚類質量的方法。

在接下來的代碼單元中,你將實現下列功能:

  • reduced_data上使用一個聚類算法,並將結果賦值到clusterer,須要設置 random_state 使得結果能夠復現。
  • 使用clusterer.predict預測reduced_data中的每個點的簇,並將結果賦值到preds
  • 使用算法的某個屬性值找到聚類中心,並將它們賦值到centers
  • 預測pca_samples中的每個樣本點的類別並將結果賦值到sample_preds
  • 導入sklearn.metrics.silhouette_score包並計算reduced_data相對於preds的輪廓係數。
    • 將輪廓係數賦值給score並輸出結果。
In [60]:
# TODO:在降維後的數據上使用你選擇的聚類算法
from sklearn.mixture import GaussianMixture
from sklearn.metrics import silhouette_score

for i in xrange(2,9):
    clusterer = GaussianMixture(n_components=i,random_state=0)
    clusterer.fit(reduced_data)
    preds = clusterer.predict(reduced_data)
    centers = clusterer.means_
    sample_preds = clusterer.predict(pca_samples)
    score = silhouette_score(reduced_data,preds)
    print score

clusterer = GaussianMixture(n_components=2,random_state=0)
clusterer.fit(reduced_data)
# TODO:預測每個點的簇
preds = clusterer.predict(reduced_data)

# TODO:找到聚類中心
centers = clusterer.means_

# TODO:預測在每個轉換後的樣本點的類
sample_preds = clusterer.predict(pca_samples)

# TODO:計算選擇的類別的平均輪廓係數(mean silhouette coefficient)
score = silhouette_score(reduced_data,preds)
 
0.421916846463
0.37420184754
0.3290804667
0.305874552873
0.224815181533
0.274333813489
0.344370057027
 

問題 7

彙報你嘗試的不一樣的聚類數對應的輪廓係數。在這些當中哪個聚類的數目可以獲得最佳的輪廓係數?

 

回答:

  • 嘗試了2-8的聚類數
  • 2聚類獲得了最佳的輪廓係數
 

聚類可視化

一旦你選好了經過上面的評價函數獲得的算法的最佳聚類數目,你就可以經過使用下面的代碼塊可視化來獲得的結果。做爲實驗,你能夠試着調整你的聚類算法的聚類的數量來看一下不一樣的可視化結果。可是你提供的最終的可視化圖像必須和你選擇的最優聚類數目一致。

In [61]:
# 從已有的實現中展現聚類的結果
vs.cluster_results(reduced_data, preds, centers, pca_samples)
 
 

練習: 數據恢復

上面的可視化圖像中提供的每個聚類都有一箇中心點。這些中心(或者叫平均點)並非數據中真實存在的點,可是是全部預測在這個簇中的數據點的平均。對於建立客戶分類的問題,一個簇的中心對應於那個分類的平均用戶。由於這個數據如今進行了降維並縮放到必定的範圍,咱們能夠經過施加一個反向的轉換恢復這個點所表明的用戶的花費。

在下面的代碼單元中,你將實現下列的功能:

  • 使用pca.inverse_transformcenters 反向轉換,並將結果存儲在log_centers中。
  • 使用np.log的反函數np.exp反向轉換log_centers並將結果存儲到true_centers中。
In [62]:
# TODO:反向轉換中心點
log_centers = pca.inverse_transform(centers)

# TODO:對中心點作指數轉換
true_centers = np.exp(log_centers)

# 顯示真實的中心點
segments = ['Segment {}'.format(i) for i in range(0,len(centers))]
true_centers = pd.DataFrame(np.round(true_centers), columns = data.keys())
true_centers.index = segments
display(true_centers)
 
 
  Fresh Milk Grocery Frozen Detergents_Paper Delicatessen
Segment 0 8953.0 2114.0 2765.0 2075.0 353.0 732.0
Segment 1 3552.0 7837.0 12219.0 870.0 4696.0 962.0
 

問題 8

考慮上面的表明性數據點在每個產品類型的花費總數,你認爲這些客戶分類表明了哪類客戶?爲何?須要參考在項目最開始獲得的統計值來給出理由。

提示: 一個被分到'Cluster X'的客戶最好被用 'Segment X'中的特徵集來標識的企業類型表示。

 

回答:

  • Cluster 0更像是零售商,由於他們的中心點Segment 0的各項特徵值都是50%左右,低於平均值,沒有某個特徵特別高,而量又沒有特別大,比較符合零售商什麼都賣,可是入貨不算多的特色

  • Cluster 1更像是奶茶店,而且他們的中心點Segment 1的值牛奶和、雜物和清潔紙的量超過了75%並且超過了平均數,而其餘的數量較少,奶茶店牛奶和紙巾的消耗必然不少,因此更有多是奶茶店

 

問題 9

對於每個樣本點 問題 8 中的哪個分類可以最好的表示它?你以前對樣本的預測和如今的結果相符嗎?

運行下面的代碼單元以找到每個樣本點被預測到哪個簇中去。

In [63]:
# 顯示預測結果
for i, pred in enumerate(sample_preds):
    print "Sample point", i, "predicted to be in Cluster", pred
 
Sample point 0 predicted to be in Cluster 1
Sample point 1 predicted to be in Cluster 1
Sample point 2 predicted to be in Cluster 1
 

回答:

  • 主要是Cluster 1,Milk,Grocery,Detergents_Paper消耗較大,更像奶茶店
  • 不相符,經驗偏少
 

結論

在最後一部分中,你要學習如何使用已經被分類的數據。首先,你要考慮不一樣組的客戶客戶分類,針對不一樣的派送策略受到的影響會有什麼不一樣。其次,你要考慮到,每個客戶都被打上了標籤(客戶屬於哪個分類)能夠給客戶數據提供一個多一個特徵。最後,你會把客戶分類與一個數據中的隱藏變量作比較,看一下這個分類是否辨識了特定的關係。

 

問題 10

在對他們的服務或者是產品作細微的改變的時候,公司常常會使用A/B tests以肯定這些改變會對客戶產生積極做用仍是消極做用。這個批發商但願考慮將他的派送服務從每週5天變爲每週3天,可是他只會對他客戶當中對此有積極反饋的客戶採用。這個批發商應該如何利用客戶分類來知道哪些客戶對它的這個派送策略的改變有積極的反饋,若是有的話?你須要給出在這個情形下A/B 測試具體的實現方法,以及最終得出結論的依據是什麼?
提示: 咱們能假設這個改變對全部的客戶影響都一致嗎?咱們怎樣纔可以肯定它對於哪一個類型的客戶影響最大?

 

回答:

  • 不一樣客戶需求不一樣,改變策略對全部客戶影響確定有差別。
  • 可是咱們能夠假設改變策略對全部客戶影響一致,每一個簇中選擇一些樣本進行A/B測試,過一段時間看客戶反應。
 

問題 11

經過聚類技術,咱們可以將原有的沒有標記的數據集中的附加結構分析出來。由於每個客戶都有一個最佳的劃分(取決於你選擇使用的聚類算法),咱們能夠把用戶分類做爲數據的一個工程特徵。假設批發商最近迎來十位新顧客,而且他已經爲每位顧客每一個產品類別年度採購額進行了預估。進行了這些估算以後,批發商該如何運用它的預估和非監督學習的結果來對這十個新的客戶進行更好的預測?

提示:在下面的代碼單元中,咱們提供了一個已經作好聚類的數據(聚類結果爲數據中的cluster屬性),咱們將在這個數據集上作一個小實驗。嘗試運行下面的代碼看看咱們嘗試預測‘Region’的時候,若是存在聚類特徵'cluster'與不存在相比對最終的得分會有什麼影響?這對你有什麼啓發?

In [64]:
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

# 讀取包含聚類結果的數據
cluster_data = pd.read_csv("cluster.csv")
y = cluster_data['Region']
X = cluster_data.drop(['Region'], axis = 1)

# 劃分訓練集測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=24)

clf = RandomForestClassifier(random_state=24)
clf.fit(X_train, y_train)
print "使用cluster特徵的得分", clf.score(X_test, y_test)

# 移除cluster特徵
X_train = X_train.copy()
X_train.drop(['cluster'], axis=1, inplace=True)
X_test = X_test.copy()
X_test.drop(['cluster'], axis=1, inplace=True)
clf.fit(X_train, y_train)
print "不使用cluster特徵的得分", clf.score(X_test, y_test)
 
使用cluster特徵的得分 0.666666666667
不使用cluster特徵的得分 0.64367816092
 

回答:

  • 使用cluster特徵的得分高於不使用,提升預測準確率
  • 聚類完爲每一個樣本打上標籤可做爲特徵預測其餘變量
 

可視化內在的分佈

在這個項目的開始,咱們討論了從數據集中移除'Channel''Region'特徵,這樣在分析過程當中咱們就會着重分析用戶產品類別。經過從新引入Channel這個特徵到數據集中,並施加和原來數據集一樣的PCA變換的時候咱們將可以發現數據集產生一個有趣的結構。

運行下面的代碼單元以查看哪個數據點在降維的空間中被標記爲'HoReCa' (旅館/餐館/咖啡廳)或者'Retail'。另外,你將發現樣本點在圖中被圈了出來,用以顯示他們的標籤。

In [65]:
# 根據‘Channel‘數據顯示聚類的結果
vs.channel_results(reduced_data, outliers, pca_samples)
 
 

問題 12

你選擇的聚類算法和聚類點的數目,與內在的旅館/餐館/咖啡店和零售商的分佈相比,有足夠好嗎?根據這個分佈有沒有哪一個簇可以恰好劃分紅'零售商'或者是'旅館/飯店/咖啡館'?你以爲這個分類和前面你對於用戶分類的定義是一致的嗎?

 

回答:

  • 聚類點的數目爲2個,從上圖可看出Dimension 1等於-0.5左右能夠將全部客戶分爲2類,基本一致
 

 

 

歡迎掃碼關注,或搜索大數據與知識圖譜,按期分享大數據與知識圖譜相關知識點:

相關文章
相關標籤/搜索