開始
在這個項目中,你將分析一個數據集的內在結構,這個數據集包含很多客戶針對不同類型產品的年度采購額(用金額表示)。這個項目的任務之一是如何最好地描述一個批發商不同種類顧客之間的差異。這樣做將能夠使得批發商能夠更好的組織他們的物流服務以滿足每個客戶的需求。
這個項目的數據集能夠在UCI機器學習信息庫中找到.因為這個項目的目的,分析將不會包括 'Channel' 和 'Region' 這兩個特征——重點集中在6個記錄的客戶購買的產品類別上。
運行下面的的代碼單元以載入整個客戶數據集和一些這個項目需要的 Python 庫。如果你的數據集載入成功,你將看到后面輸出數據集的大小。
# 檢查你的Python版本
from sys import version_info if version_info.major != 3: raise Exception('請使用Python 3.x 來完成此項目')
# 引入這個項目需要的庫
import numpy as np import pandas as pd import visuals as vs from IPython.display import display # 使得我們可以對DataFrame使用display()函數
# 設置以內聯的形式顯示matplotlib繪制的圖片(在notebook中顯示更美觀)
%matplotlib inline # 高分辨率顯示 # %config InlineBackend.figure_format='retina'
# 載入整個客戶數據集
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.
分析數據
在這部分,你將開始分析數據,通過可視化和代碼來理解每一個特征和其他特征的聯系。你會看到關於數據集的統計描述,考慮每一個屬性的相關性,然后從數據集中選擇若干個樣本數據點,你將在整個項目中一直跟蹤研究這幾個數據點。
運行下面的代碼單元給出數據集的一個統計描述。注意這個數據集包含了6個重要的產品類型:'Fresh', 'Milk', 'Grocery', 'Frozen', 'Detergents_Paper'和 'Delicatessen'。想一下這里每一個類型代表你會購買什么樣的產品。
# 顯示數據集的一個描述
display(data.describe())
練習: 選擇樣本
為了對客戶有一個更好的了解,並且了解代表他們的數據將會在這個分析過程中如何變換。最好是選擇幾個樣本數據點,並且更為詳細地分析它們。在下面的代碼單元中,選擇三個索引加入到索引列表indices中,這三個索引代表你要追蹤的客戶。我們建議你不斷嘗試,直到找到三個明顯不同的客戶。
# TODO:從數據集中選擇三個你希望抽樣的數據點的索引
indices = [4,9,12] # 為選擇的樣本建立一個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:
問題 1
在你看來你選擇的這三個樣本點分別代表什么類型的企業(客戶)?對每一個你選擇的樣本客戶,通過它在每一種產品類型上的花費與數據集的統計描述進行比較,給出你做上述判斷的理由。
提示: 企業的類型包括超市、咖啡館、零售商以及其他。注意不要使用具體企業的名字,比如說在描述一個餐飲業客戶時,你不能使用麥當勞。
回答:第一個樣本點可能是餐館,因為在Fresh和Delicatessen上的花銷遠高於均值;第二個樣本點可能是咖啡館,因為在Milk、Grocery和Detergents_Paper上的花銷遠高於均值;第三個樣本點可能是超市,因為在Frozen上的花銷非常低,而其他種類的花銷都超過均值。
Tips:建議選擇 percentile 而非 mean對數據集的統計特征進行比較,因為在未知數據分布的情況下使用均值作為比較對象是比較危險的——因為不清楚概率分布。
練習: 特征相關性
一個有趣的想法是,考慮這六個類別中的一個(或者多個)產品類別,是否對於理解客戶的購買行為具有實際的相關性。也就是說,當用戶購買了一定數量的某一類產品,我們是否能夠確定他們必然會成比例地購買另一種類的產品。有一個簡單的方法可以檢測相關性:我們用移除了某一個特征之后的數據集來構建一個監督學習(回歸)模型,然后用這個模型去預測那個被移除的特征,再對這個預測結果進行評分,看看預測結果如何。
在下面的代碼單元中,你需要實現以下的功能:
使用 DataFrame.drop 函數移除數據集中你選擇的不需要的特征,並將移除后的結果賦值給 new_data 。
使用 sklearn.model_selection.train_test_split 將數據集分割成訓練集和測試集。使用移除的特征作為你的目標標簽。設置 test_size 為 0.25 並設置一個 random_state 。
導入一個 DecisionTreeRegressor (決策樹回歸器),設置一個 random_state,然后用訓練集訓練它。
使用回歸器的 score 函數輸出模型在測試集上的預測得分。
# TODO:為DataFrame創建一個副本,用'drop'函數丟棄一個特征# TODO:
labels = data['Grocery'] new_data = data.drop('Grocery',axis=1) # 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=0) # TODO:創建一個DecisionTreeRegressor(決策樹回歸器)並在訓練集上訓練它
from sklearn.tree import DecisionTreeRegressor regressor = DecisionTreeRegressor(random_state=0) regressor.fit(X_train,y_train) # TODO:輸出在測試集上的預測得分
from sklearn.metrics import r2_score y_pred = regressor.predict(X_test) score = r2_score(y_test,y_pred) print (score)
0.602801978878
問題 2
你嘗試預測哪一個特征?預測的得分是多少?這個特征對於區分用戶的消費習慣來說必要嗎?為什么?
提示: 決定系數(coefficient of determination),R2 結果在0到1之間,1表示完美擬合,一個負的 R2 表示模型不能夠擬合數據。
回答:我嘗試預測Grocery;得分0.6;這個特征對於區分用戶的消費習慣來說不必要;因為它可以由其他特征較好地預測出來。
可視化特征分布
為了能夠對這個數據集有一個更好的理解,我們可以對數據集中的每一個產品特征構建一個散布矩陣(scatter matrix)。如果你發現你在上面嘗試預測的特征對於區分一個特定的用戶來說是必須的,那么這個特征和其它的特征可能不會在下面的散射矩陣中顯示任何關系。相反的,如果你認為這個特征對於識別一個特定的客戶是沒有作用的,那么通過散布矩陣可以看出在這個數據特征和其它特征中有關聯性。運行下面的代碼以創建一個散布矩陣。
# 對於數據中的每一對特征構造一個散布矩陣
pd.plotting.scatter_matrix(data, alpha = 0.3, figsize = (14,8), diagonal = 'kde');
問題 3
這里是否存在一些特征他們彼此之間存在一定程度相關性?如果有請列出。這個結果是驗證了還是否認了你嘗試預測的那個特征的相關性?這些特征的數據是怎么分布的?
提示: 這些數據是正態分布(normally distributed)的嗎?大多數的數據點分布在哪?
回答:存在一些特征他們彼此之間存在一定程度相關性;比如Milk和Grocery、Milk和Detergents Paper、Grocery和Detergents Paper等。這個結果驗證了我嘗試預測的那個特征的相關性;這些特征的數據不是正態分布的,大多數的數據點分布在0值附近。
數據預處理
在這個部分,你將通過在數據上做一個合適的縮放,並檢測異常點(你可以選擇性移除)將數據預處理成一個更好的代表客戶的形式。預處理數據是保證你在分析中能夠得到顯著且有意義的結果的重要環節。
練習: 特征縮放
如果數據不是正態分布的,尤其是數據的平均數和中位數相差很大的時候(表示數據非常歪斜)。這時候通常用一個非線性的縮放是很合適的,尤其是對於金融數據。一種實現這個縮放的方法是使用 Box-Cox 變換,這個方法能夠計算出能夠最佳減小數據傾斜的指數變換方法。一個比較簡單的並且在大多數情況下都適用的方法是使用自然對數。
在下面的代碼單元中,你將需要實現以下功能:
使用 np.log 函數在數據 data 上做一個對數縮放,然后將它的副本(不改變原始data的值)賦值給 log_data。
使用 np.log 函數在樣本數據 samples 上做一個對數縮放,然后將它的副本賦值給 log_samples。
# 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');
觀察
在使用了一個自然對數的縮放之后,數據的各個特征會顯得更加的正態分布。對於任意的你以前發現有相關關系的特征對,觀察他們的相關關系是否還是存在的(並且嘗試觀察,他們的相關關系相比原來是變強了還是變弱了)。
運行下面的代碼以觀察樣本數據在進行了自然對數轉換之后如何改變了。
# 展示經過對數變換后的樣本數據
display(log_samples)
練習: 異常值檢測
對於任何的分析,在數據預處理的過程中檢測數據中的異常值都是非常重要的一步。異常值的出現會使得把這些值考慮進去后結果出現傾斜。這里有很多關於怎樣定義什么是數據集中的異常值的經驗法則。這里我們將使用 Tukey 的定義異常值的方法:一個異常階(outlier step)被定義成1.5倍的四分位距(interquartile range,IQR)。一個數據點如果某個特征包含在該特征的 IQR 之外的特征,那么該數據點被認定為異常點。
在下面的代碼單元中,你需要完成下面的功能:
將指定特征的 25th 分位點的值分配給 Q1 。使用 np.percentile 來完成這個功能。
將指定特征的 75th 分位點的值分配給 Q3 。同樣的,使用 np.percentile 來完成這個功能。
將指定特征的異常階的計算結果賦值給 step。
選擇性地通過將索引添加到 outliers 列表中,以移除異常值。
注意: 如果你選擇移除異常值,請保證你選擇的樣本點不在這些移除的點當中! 一旦你完成了這些功能,數據集將存儲在 good_data 中。
# 對於每一個特征,找到值異常高或者是異常低的數據點
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
# 顯示異常點
print("Data points considered outliers for the feature '{}':".format(feature)) display(log_data[~((log_data[feature] >= Q1 - step) & (log_data[feature] <= Q3 + step))]) # TODO(可選): 選擇你希望移除的數據點的索引
outliers = [65, 66, 75, 128, 154] # 以下代碼會移除outliers中索引的數據點, 並儲存在good_data中
good_data = log_data.drop(log_data.index[outliers]).reset_index(drop = True)
問題 4
請列出所有在多於一個特征下被看作是異常的數據點。這些點應該被從數據集中移除嗎?為什么?把你認為需要移除的數據點全部加入到到 outliers 變量中。
回答:[65, 66, 75, 128, 154];這些點應該被從數據集中移除;因為異常值的出現會使得把這些值考慮進去后結果出現傾斜。
Tips:我們一般不會移除 “只在一個 feature 中被認為是異常點” 的點,而是會移除 “在至少兩個 feature 中被認為是異常點” 的數據點。這是因為:
1)在一個 feature 中被認為是異常點的點,可能在其他 feature 中有着很重要的作用,甚至可能反映新的一種類型;
2)我們不希望省略很多的點——否則我們的訓練樣本會很少,導致它可能無法學到正確的內容。
Tips:可以考慮使用 boxplot 來對離群點進行可視化:
import seaborn as sns import matplotlib.pyplot as plt # create "melted" dataframe
df = pd.DataFrame(columns=['variable', 'value']) for col in log_data.columns: df = df.append(pd.melt(log_data, value_vars=[col])) print df.shape # create the boxplot with data points overlay
plt.figure(figsize=(8,6)) sns.boxplot(x="value", y="variable", data=df, color="c") sns.stripplot(x="value", y="variable", data=df, jitter=True, size=4, alpha=.4, color=".3", linewidth=0) sns.despine(trim=True)
特征轉換
在這個部分中你將使用主成分分析(PCA)來分析批發商客戶數據的內在結構。由於使用PCA在一個數據集上會計算出最大化方差的維度,我們將找出哪一個特征組合能夠最好的描繪客戶。
練習: 主成分分析(PCA)
既然數據被縮放到一個更加正態分布的范圍中並且我們也移除了需要移除的異常點,我們現在就能夠在 good_data 上使用PCA算法以發現數據的哪一個維度能夠最大化特征的方差。除了找到這些維度,PCA 也將報告每一個維度的解釋方差比(explained variance ratio)--這個數據有多少方差能夠用這個單獨的維度來解釋。注意 PCA 的一個組成部分(維度)能夠被看做這個空間中的一個新的“特征”,但是它是原來數據中的特征構成的。
在下面的代碼單元中,你將要實現下面的功能:
導入 sklearn.decomposition.PCA 並且將 good_data 用 PCA 並且使用6個維度進行擬合后的結果保存到 pca 中。
使用 pca.transform 將 log_samples 進行轉換,並將結果存儲到 pca_samples 中。
# TODO:通過在good data上進行PCA,將其轉換成6個維度
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)
Tips:可以使用 seaborn庫 中的代碼,來實現對變化后每個特征 核密度估計(KDE)的可視化。
import matplotlib.pyplot as plt import seaborn as sns sns.set_palette("Reds_r") sns.set_style('ticks') # plot densities of log-transformed data
plt.figure(figsize=(8,4)) for col in data.columns: sns.kdeplot(log_data[col], shade=True) plt.legend(loc=2);
問題 5
數據的第一個和第二個主成分總共表示了多少的方差? 前四個主成分呢?使用上面提供的可視化圖像,從用戶花費的角度來討論前四個主要成分中每個主成分代表的消費行為並給出你做出判斷的理由。
提示:
對每個主成分中的特征分析權重的正負和大小。
結合每個主成分權重的正負討論消費行為。
某一特定維度上的正向增長對應正權特征的增長和負權特征的減少。增長和減少的速率和每個特征的權重相關。參考資料:Interpretation of the Principal Components
回答:數據的第一個和第二個主成分總共表示了0.7068的方差;前四個主成分總共表示了0.9311的方差;第一個主成分代表咖啡館的消費行為,因為Detergents Paper、Milk和Grocery的權重絕對值較大,且它們三者呈正相關,咖啡館就在這三種類型上花銷較大;第二個主成分代表菜市場的消費行為,因為Fresh、Frozen、Delicatessen的權重絕對值最大,且它們三者呈正相關,說明在食材上的花銷最大且品類齊全;第三個主成分代表熟食店或生鮮店的消費行為,因為Fresh和Delicatessen的權重絕對值最大,但它們負相關,說明其中之一買得多,而另一個買得少;第四個主成分代表牛奶店或雜貨鋪的消費行為,因為Grocery和Milk的權重絕對值最大,但它們負相關,說明其中之一買得多,而另一個買得少。
觀察
運行下面的代碼,查看經過對數轉換的樣本數據在進行一個6個維度的主成分分析(PCA)之后會如何改變。觀察樣本數據的前四個維度的數值。考慮這和你初始對樣本點的解釋是否一致。
# 展示經過PCA轉換的sample log-data display(pd.DataFrame(np.round(pca_samples, 4), columns = pca_results.index.values))
練習:降維
當使用主成分分析的時候,一個主要的目的是減少數據的維度,這實際上降低了問題的復雜度。當然降維也是需要一定代價的:更少的維度能夠表示的數據中的總方差更少。因為這個,累計解釋方差比(cumulative explained variance ratio)對於我們確定這個問題需要多少維度非常重要。另外,如果大部分的方差都能夠通過兩個或者是三個維度進行表示的話,降維之后的數據能夠被可視化。
在下面的代碼單元中,你將實現下面的功能:
將 good_data 用兩個維度的PCA進行擬合,並將結果存儲到 pca 中去。
使用 pca.transform 將 good_data 進行轉換,並將結果存儲在 reduced_data 中。
使用 pca.transform 將 log_samples 進行轉換,並將結果存儲在 pca_samples 中。
# TODO:通過在good data上進行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'])
Tips:可以考慮對變換后的數據進行可視化。使用seaborn庫,你可以繪制分布的聯合核密度圖。
import seaborn as sns g = sns.JointGrid("Dimension 1", "Dimension 2", reduced_data, xlim=(-6,6), ylim=(-5,5)) g = g.plot_joint(sns.kdeplot, cmap="Blues", shade=True) g = g.plot_marginals(sns.kdeplot, shade=True)
觀察
運行以下代碼觀察當僅僅使用兩個維度進行 PCA 轉換后,這個對數樣本數據將怎樣變化。觀察這里的結果與一個使用六個維度的 PCA 轉換相比較時,前兩維的數值是保持不變的。
# 展示經過兩個維度的PCA轉換之后的樣本log-data
display(pd.DataFrame(np.round(pca_samples, 4), columns = ['Dimension 1', 'Dimension 2']))
可視化一個雙標圖(Biplot)
雙標圖是一個散點圖,每個數據點的位置由它所在主成分的分數確定。坐標系是主成分(這里是 Dimension 1 和 Dimension 2)。此外,雙標圖還展示出初始特征在主成分上的投影。一個雙標圖可以幫助我們理解降維后的數據,發現主成分和初始特征之間的關系。
運行下面的代碼來創建一個降維后數據的雙標圖。
# 可視化雙標圖
vs.biplot(good_data, reduced_data, pca)
<matplotlib.axes._subplots.AxesSubplot at 0x7f13c3c8bf98>
觀察
一旦我們有了原始特征的投影(紅色箭頭),就能更加容易的理解散點圖每個數據點的相對位置。
在這個雙標圖中,哪些初始特征與第一個主成分有強關聯?哪些初始特征與第二個主成分相關聯?你觀察到的是否與之前得到的 pca_results 圖相符?
聚類
在這個部分,你將選擇使用 K-Means 聚類算法或者是高斯混合模型聚類算法以發現數據中隱藏的客戶分類。然后,你將從簇中恢復一些特定的關鍵數據點,通過將它們轉換回原始的維度和規模,從而理解他們的含義。
問題 6
使用 K-Means 聚類算法的優點是什么?使用高斯混合模型聚類算法的優點是什么?基於你現在對客戶數據的觀察結果,你選用了這兩個算法中的哪一個,為什么?
回答:K-Means 聚類算法的優點是計算速度快,容易理解;高斯混合模型聚類的優點是可以得到樣本點屬於每個類的概率,理論上可以擬合任何連續的概率密度函數;基於對客戶數據的觀察結果,我選擇高斯混合模型聚類;因為高斯混合模型並不需要假設每個特征符合高斯分布。
練習: 創建聚類
針對不同情況,有些問題你需要的聚類數目可能是已知的。但是在聚類數目不作為一個先驗知道的情況下,我們並不能夠保證某個聚類的數目對這個數據是最優的,因為我們對於數據的結構(如果存在的話)是不清楚的。但是,我們可以通過計算每一個簇中點的輪廓系數來衡量聚類的質量。數據點的輪廓系數衡量了它與分配給他的簇的相似度,這個值范圍在-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 並輸出結果。
# TODO:在降維后的數據上使用你選擇的聚類算法
from sklearn.mixture import GaussianMixture from sklearn.metrics import silhouette_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) print(score)
0.421916846463
問題 7
匯報你嘗試的不同的聚類數對應的輪廓系數。在這些當中哪一個聚類的數目能夠得到最佳的輪廓系數?
回答:聚類數為2時,輪廓系數為0.421916846463; 聚類數為3時,輪廓系數為0.37420184754; 聚類數為4時,輪廓系數為0.3290804667; 聚類數為5時,輪廓系數為0.305874552873; 聚類數為6時,輪廓系數為0.224815181533; 聚類數為2時能夠得到最佳的輪廓系數。
聚類可視化
一旦你選好了通過上面的評價函數得到的算法的最佳聚類數目,你就能夠通過使用下面的代碼塊可視化來得到的結果。作為實驗,你可以試着調整你的聚類算法的聚類的數量來看一下不同的可視化結果。但是你提供的最終的可視化圖像必須和你選擇的最優聚類數目一致。
# 從已有的實現中展示聚類的結果
vs.cluster_results(reduced_data, preds, centers, pca_samples)
練習: 數據恢復
上面的可視化圖像中提供的每一個聚類都有一個中心點。這些中心(或者叫平均點)並不是數據中真實存在的點,但是是所有預測在這個簇中的數據點的平均。對於創建客戶分類的問題,一個簇的中心對應於那個分類的平均用戶。因為這個數據現在進行了降維並縮放到一定的范圍,我們可以通過施加一個反向的轉換恢復這個點所代表的用戶的花費。
在下面的代碼單元中,你將實現下列的功能:
使用 pca.inverse_transform 將 centers 反向轉換,並將結果存儲在 log_centers 中。
使用 np.log 的反函數 np.exp 反向轉換 log_centers 並將結果存儲到 true_centers 中。
# 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)
Tips:補充一個與mean對比的可視化方法:
# Import Seaborn, a very powerful library for Data Visualisation
import seaborn as sns true_centers = true_centers.append(data.describe().loc['mean']) _ = true_centers.plot(kind='bar', figsize=(15,6))
問題 8
考慮上面的代表性數據點在每一個產品類型的花費總數,你認為這些客戶分類代表了哪類客戶?為什么?需要參考在項目最開始得到的統計值來給出理由。
提示: 一個被分到'Cluster X'的客戶最好被用 'Segment X'中的特征集來標識的企業類型表示。
回答:Cluster 0代表零售類客戶,因為各項支出都低於平均值,符合零售店的特征;Cluster 1代表咖啡廳類客戶,因為Milk、Grocery、Detergents Paper這三項支出遠高於平均值,符合咖啡店的特征。
問題 9
對於每一個樣本點*問題 8 *中的哪一個分類能夠最好的表示它?你之前對樣本的預測和現在的結果相符嗎?
運行下面的代碼單元以找到每一個樣本點被預測到哪一個簇中去。
# 顯示預測結果
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 0
Sample point 1 predicted to be in Cluster 1
Sample point 2 predicted to be in Cluster 1
回答:樣本點0最好的分類是Cluster 0;樣本點1和2最好的分類是Cluster 1;我之前對樣本的預測和現在的結果相符。
結論
在最后一部分中,你要學習如何使用已經被分類的數據。首先,你要考慮不同組的客戶分類,針對不同的派送策略受到的影響會有什么不同。其次,你要考慮到,每一個客戶都被打上了標簽(客戶屬於哪一個分類)可以給客戶數據提供一個多一個特征。最后,你會把客戶分類與一個數據中的隱藏變量做比較,看一下這個分類是否辨識了特定的關系。
問題 10
在對他們的服務或者是產品做細微的改變的時候,公司經常會使用 A/B tests 以確定這些改變會對客戶產生積極作用還是消極作用。這個批發商希望考慮將他的派送服務從每周5天變為每周3天,但是他只會對他客戶當中對此有積極反饋的客戶采用。這個批發商應該如何利用客戶分類來知道哪些客戶對它的這個派送策略的改變有積極的反饋,如果有的話?你需要給出在這個情形下A/B 測試具體的實現方法,以及最終得出結論的依據是什么?
提示: 我們能假設這個改變對所有的客戶影響都一致嗎?我們怎樣才能夠確定它對於哪個類型的客戶影響最大?
回答:A/B 測試具體的實現方法:從兩個分類中隨機選取數量相等的部分客戶,把他們的派送時間由每周5天改為每周3天,四周后,觀察兩個分類中客戶的留存率,留存率高,說明該分類的客戶對新的派送策略有積極反饋。
問題 11
通過聚類技術,我們能夠將原有的沒有標記的數據集中的附加結構分析出來。因為每一個客戶都有一個最佳的划分(取決於你選擇使用的聚類算法),我們可以把用戶分類作為數據的一個工程特征。假設批發商最近迎來十位新顧客,並且他已經為每位顧客每個產品類別年度采購額進行了預估。進行了這些估算之后,批發商該如何運用它的預估和非監督學習的結果來對這十個新的客戶進行更好的預測?
提示:在下面的代碼單元中,我們提供了一個已經做好聚類的數據(聚類結果為數據中的cluster屬性),我們將在這個數據集上做一個小實驗。嘗試運行下面的代碼看看我們嘗試預測‘Region’的時候,如果存在聚類特征'cluster'與不存在相比對最終的得分會有什么影響?這對你有什么啟發?
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) score_with_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) score_no_cluster = clf.score(X_test, y_test) print("不使用cluster特征的得分: %.4f"%score_no_cluster) print("使用cluster特征的得分: %.4f"%score_with_cluster)
不使用cluster特征的得分: 0.6437
使用cluster特征的得分: 0.6667
回答:使用cluster特征的得分更高,因此預測更准確;cluster特征相當於一個新的維度,增加一個維度有助於預測的准確性。
Tips:關於特征工程的進一步了解,可以參考這個知乎回答來了解更多相關的信息:特征工程到底是什么?
可視化內在的分布
在這個項目的開始,我們討論了從數據集中移除 'Channel' 和 'Region' 特征,這樣在分析過程中我們就會着重分析用戶產品類別。通過重新引入 Channel 這個特征到數據集中,並施加和原來數據集同樣的 PCA 變換的時候我們將能夠發現數據集產生一個有趣的結構。
運行下面的代碼單元以查看哪一個數據點在降維的空間中被標記為 'HoReCa' (旅館/餐館/咖啡廳)或者 'Retail'。另外,你將發現樣本點在圖中被圈了出來,用以顯示他們的標簽。
# 根據‘Channel‘數據顯示聚類的結果
vs.channel_results(reduced_data, outliers, pca_samples)
問題 12
你選擇的聚類算法和聚類點的數目,與內在的旅館/餐館/咖啡店和零售商的分布相比,有足夠好嗎?根據這個分布有沒有哪個簇能夠剛好划分成'零售商'或者是'旅館/飯店/咖啡館'?你覺得這個分類和前面你對於用戶分類的定義是一致的嗎?
回答:不夠好;沒有;不一致。