一般來講,在傳統零售行業中80%的收益來自於20%的客戶,所以對客戶的價值進行分類顯得尤爲重要,而在本文咱們基於批發經銷商客戶的真實消費數據,創建K-means聚類模型來對客戶價值進行細分。算法
1. 數據來源及背景app
2. 明確分析目的dom
3. 數據探索分析機器學習
4. 數據預處理佈局
5. 構建模型學習
6. 客戶價值細分spa
數據來源: http://archive.ics.uci.edu/ml/machine-learning-databases/00292;code
數據背景: 這是某批發經銷商客戶在各種型產品的年度支出數據集. 該數據集樣本容量爲440, 共有8個特徵, 其分別爲: 客戶渠道, 客戶所在地區, 以及在新鮮產品, 奶製品, 食品雜貨, 冷凍產品, 洗滌劑和紙製品, 熟食產品這6種類型產品的年度支出.orm
經過提出一系列問題, 明確咱們的分析目的:blog
1) 各種產品的年度支出平均水平如何?哪一個產品最高?哪一個又最低?
2) 如何對這些客戶進行分類呢?他們的消費行爲又是怎樣的呢?
3) 商家該如何根據分類結果制定營銷計劃呢?
1. 查看前2行和後2行
import pandas as pd df = pd.read_csv(r'D:\Data\Wholesale customers data.csv') pd.set_option('display.max_rows', 4) df
可經過以上看出咱們的數據維度的確是440行×8列, 以及每列都是數字, 究竟是字符串類型仍是數值類型, 須要進一步探索.
2. 查看數據總體信息
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 440 entries, 0 to 439 Data columns (total 8 columns): Channel 440 non-null int64 Region 440 non-null int64 Fresh 440 non-null int64 Milk 440 non-null int64 Grocery 440 non-null int64 Frozen 440 non-null int64 Detergents_Paper 440 non-null int64 Delicassen 440 non-null int64 dtypes: int64(8) memory usage: 27.6 KB
經過查看數據總體信息, 能夠肯定每列都是數值型, 且均爲64位整數型;另外, 也能夠看出數據裏是沒有缺失值的, 即所有爲440.
數據類型如今已經肯定了, 接下來尋找咱們第一個問題的答案了.
3. 描述性統計
df.describe()
1) 各種產品的年度支出平均水平如何?哪一個產品最高?哪一個又最低?
這裏的平均水平用平均數和中位數這二者中的哪一個合適呢?經過分別對比各種型產品的平均數和中位數, 發現平均數都大於中位數, 呈現右偏分佈, 顯然這裏採用中位數來表明較爲穩當.
各種型產品的年度支出平均水平分別爲: 新鮮產品8504.0m.u.、奶製品3627.0m.u.、食品雜貨4755.5m.u.、冷凍產品1526.0m.u.、洗滌劑和紙質品816.5m.u.、熟食產品965.5m.u.
其中, 新鮮產品排名第一,第二是食品雜貨,第3、第四和第五分別是奶製品、冰凍產品和熟食產品,第六則是洗滌劑和紙質品.
對於第二個問題,咱們利用k-means聚類模型來對其進行分類,而在建模以前,咱們須要對數據進行數據預處理
1. 數據清洗
1) 缺失值處理
沒有缺失值, 所以不用缺失值處理
2) 異常值處理
在處理異常值以前, 先來經過箱線圖查看異常值.
import seaborn as sns import matplotlib.pyplot as plt def get_boxplot(data, start, end): fig, ax = plt.subplots(1, end-start, figsize=(24, 4)) for i in range(start, end): sns.boxplot(y=data[data.columns[i]], data=data, ax=ax[i-start]) get_boxplot(df, 2, 8)
能夠看到以上6個連續型變量均有不一樣程度的異常值, 因爲k-means算法對異常值較敏感, 所以選擇剔除它
def drop_outlier(data, start, end): for i in range(start, end): field = data.columns[i] Q1 = np.quantile(data[field], 0.25) Q3 = np.quantile(data[field], 0.75) deta = (Q3 - Q1) * 1.5 data = data[(data[field] >= Q1 - deta) & (data[field] <= Q3 + deta)] return data del_df = drop_outlier(df, 2, 8) print("原有樣本容量:{0}, 剔除後樣本容量:{1}".format(df.shape[0], del_df.shape[0])) get_boxplot(del_df, 2, 8)
原有樣本容量:440, 剔除後樣本容量:318
在剔除一次異常值以後, 6個連續變量的波動幅度也都都大體接近, 你可能會問爲何還有異常值存在? 如今的異常值是相對於新數據集產生的, 而咱們把原數據集中的異常值已經剔除了, 一般來講, 對於異常值只需剔除一次便可, 若是完全剔除的話, 樣本容量可能會有大幅度的變化, 好比:
df_new = df.copy() #直到第10次的時候圖像上纔沒有出現異常值 for i in range(10): df_new = drop_outlier(df_new, 2, 8) print("原有樣本容量:{0}, 完全剔除後樣本容量:{1}".format(df.shape[0], df_new.shape[0])) get_boxplot(df_new, 2, 8)
原有樣本容量:440, 完全剔除後樣本容量:97
能夠看到如今的數據集中已經不存在異常了, 可是樣本容量也從440大幅度降低爲97, 所以這裏不建議完全刪除.
2. 數據變換
對數據中的離散型變量和連續型變量分別進行適當的變換,以適應模型的要求
1) 離散型變量
將離散型變量處理成啞變量.
del_df['Channel'] = del_df.Channel.astype(str) del_df['Region'] = del_df.Region.astype(str) del_df = pd.get_dummies(del_df)
2) 連續型變量
因爲連續型變量的數值範圍有大有小, 爲消除其對聚類結果的影響, 這裏採用z-score進行歸一化處理
for i in range(6): field = del_df.columns[i] del_df[field] = del_df[field].apply(lambda x: (x - del_df[field].mean()) / del_df[field].std())
數據預處理這部分的工做已大體完成,下一步進行模型構建.
選取一個初始的k值, 來進行構建k-means聚類模型
1. 構建K=2的聚類模型
from sklearn.cluster import KMeans km = KMeans(n_clusters=2, random_state=10) km.fit(del_df) print(km.cluster_centers_) print(km.labels_)
[[ 0.08057098 -0.36005276 -0.42021772 0.11899282 -0.66737726 -0.10885484 0.97333333 0.02666667 0.2 0.10222222 0.69777778] [-0.19492979 0.8710954 1.01665578 -0.28788585 1.61462241 0.26335849 0.13978495 0.86021505 0.10752688 0.07526882 0.8172043 ]] [1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 1 1 1 0 0 1 0 0 1 0 1 1 1 1 0 0 1 0 0 1 0 0 0 0 1 1 0 1 0 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 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 0 1 1 1 0 0 1 1 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 1 1 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 0 1 1 1 1 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0]
將客戶分爲兩類合適嗎?咱們經過迭代的方式來選擇合適的k值.
2. 迭代選擇合適的k值
import matplotlib.pyplot as plt K = range(1, 10) sse = [] for k in K: km = KMeans(n_clusters=k, random_state=10) km.fit(del_df) sse.append(km.inertia_) plt.figure(figsize=(8, 6)) plt.plot(K, sse, '-o', alpha=0.7) plt.xlabel("K") plt.ylabel("SSE") plt.show()
根據肘部法則, 選擇K=2, 也就是說將客戶分紅兩類.
from pandas.plotting import parallel_coordinates #訓練模型 km = KMeans(n_clusters=2, random_state=10) km.fit(del_df) centers = km.cluster_centers_ labels = km.labels_ customer = pd.DataFrame({'0': centers[0], "1": centers[1]}).T customer.columns = del_df.keys() df_median = pd.DataFrame({'2': del_df.median()}).T customer = pd.concat([customer, df_median]) customer["category"] = ["customer_1", "customer_2", 'median'] #繪製圖像 plt.figure(figsize=(12, 6)) parallel_coordinates(customer, "category", colormap='flag'') plt.xticks(rotation = 15) plt.show()
將各種型產品年度支出的聚類中心以及中位數繪製如上圖所示, 那麼咱們的第二個問題也就有了答案.
2) 如何對這些客戶進行分類呢?他們的消費行爲又是怎樣的呢?
咱們經過k-means聚類模型將這些客戶分爲兩羣: 客戶羣1和客戶羣2.
就六種類型產品的年度支出來看, 客戶羣1在冷凍產品上最高, 在洗滌劑和紙製品上最低; 客戶羣2在冷凍產品上則最低, 在洗滌劑和紙製品上則最高. 另外, 客戶羣2在這六種產品的年度支出聚類中心均位於中位數水平之上上, 所以可將客戶羣2視爲重要價值客戶, 而客戶羣1則爲通常價值客戶.
最後, 咱們將全部客戶的聚類結果繪製在平行座標圖上
#將聚類後的標籤加入數據集 del_df['category'] = labels del_df['category'] = np.where(del_df.category == 0, 'customer_1', 'customer_2') customer = pd.DataFrame({'0': centers[0], "1": centers[1]}).T customer["category"] = ['customer_1_center', "customer_2_center"] customer.columns = del_df.keys() del_df = pd.concat([del_df, customer]) #對6類產品每一年消費水平進行繪製圖像 df_new = del_df[['Fresh', 'Milk', 'Grocery', 'Frozen', 'Detergents_Paper', 'Delicassen', 'category']] plt.figure(figsize=(18, 6)) parallel_coordinates(df_new, "category", colormap='cool') plt.xticks(rotation = 15) plt.show()
經過上圖能夠看出模型的聚類效果較爲理想, 同時也顯示出客戶羣2(重要價值客戶)相對於客戶羣1(通常價值客戶)的數量較少, 畢竟重要的老是佔少數.
針對這些結果, 該採起什麼措施呢?來到咱們的第三個問題
3) 商家該如何根據分類結果制定營銷計劃呢?
就六大類型產品來講, 可經過問卷的方式來調研改善店鋪內佈局以及增長產品種類是否會影響客戶的購買行爲; 另外, 根據聚類結果發現高價值客戶的來源傾向於渠道2, 可加大在該渠道上的宣傳力度; 最後,可進行一些打折促銷活動,刺激客戶的購買行爲.
參考資料:
網易雲課堂《吳恩達機器學習》
《數據分析與挖掘實戰》
聲明: 本文僅用於學習交流