從0開始學pyspark(十):使用pyspark.ml.clustering模組對商場顧客聚類
資料下載:
資料為kaggle上的關於商場客戶的資料,地址:https://www.kaggle.com/vjchoudhary7/customer-segmentation-tutorial-in-python
資料準備:
資料集很小,四個特徵值:性別,年齡,收入能力,消費能力,這裡我們用收入能力和消費能力兩項對客戶進行聚類處理
from pyspark.sql import SparkSession
spark = SparkSession.builder.master('local[1]').appName('learn_cluster').getOrCreate()
# 匯入資料
df = spark.read.csv('file:///home/ffzs/python-projects/learn_spark/Mall_Customers.csv', header=True, inferSchema=True)
# 更換列名
df = df.withColumnRenamed('Annual Income (k$)', 'Income').withColumnRenamed('Spending Score (1-100)', 'Spend')
# 看下資料
df.show(3)
+----------+------+---+------+-----+
|CustomerID| Gender|Age|Income|Spend|
+----------+------+---+------+-----+
| 1| Male| 19| 15| 39|
| 2| Male| 21| 15| 81|
| 3|Female| 20| 16| 6|
+----------+------+---+------+-----+
only showing top 3 rows
# 檢視是否有缺失值
df.toPandas().isna().sum()
CustomerID 0
Gender 0
Age 0
Income 0
Spend 0
dtype: int64
# 沒有缺失值,都是0
#選取特徵項,將特徵項合併成向量
from pyspark.ml.feature import VectorAssembler
vecAss = VectorAssembler(inputCols = df.columns[3:], outputCol = 'features')
df_km = vecAss.transform(df).select('CustomerID', 'features')
df_km.show(3)
#看一下
+----------+-----------+
|CustomerID| features|
+----------+-----------+
| 1|[15.0,39.0]|
| 2|[15.0,81.0]|
| 3| [16.0,6.0]|
+----------+-----------+
only showing top 3 rows
## 視覺化資料看一下
# spark不方便提取列資料轉換成pandas dataframe
pd_df = df.toPandas()
from plotly.offline import iplot, init_notebook_mode
import plotly.graph_objs as go
init_notebook_mode(connected=True)
trace = go.Scatter(x=pd_df.Income, y=pd_df.Spend ,
mode='markers',
marker = {'size':6})
iplot([trace])
結果如下:
看上去是5類;是不是我們接下來看。。
KMeans k均值聚類
class pyspark.ml.clustering.KMeans(self, featuresCol="features", predictionCol="prediction", k=2, initMode="k-means||", initSteps=2, tol=1e-4, maxIter=20, seed=None)
引數
initMode: 初始化演算法,可以使隨機的“random",也可以是”k-means||"
initSteps: k-means||初始化的步數,需>0
fit(datast,params=None)方法
model方法
cluster: 每個訓練資料點預測的聚類中心資料框
clusterSize: 每個簇的大小(簇內資料點的個數)
k: 模型訓練的簇個數
predictions: 由模型transform方法產生的資料框
from pyspark.ml.clustering import KMeans
# k取 2-19 時 獲取對應 cost 來確定 k 的最優取值
cost = list(range(2,20))
for k in range(2, 20):
kmeans = KMeans(k=k, seed=1)
km_model = kmeans.fit(df_km)
# computeCost:計算輸入點與其對應的聚類中心之間的平方距離之和。
cost[k-2] = km_model.computeCost(df_km)
# 視覺化
import matplotlib.pyplot as plt
%matplotlib inline
fig, ax = plt.subplots(1,1, figsize=(8,6))
ax.plot(range(2,20), cost)
ax.set_xlabel('k')
ax.set_ylabel('cost')
結果如下:
可以見到在k=5時,出現了拐角,我們取k=5
# k=5 建立模型
kmeans = KMeans(k=5, seed=1)
km_model = kmeans.fit(df_km)
centers = km_model.clusterCenters()
# 集簇中心點
centers
[array([55.2962963 , 49.51851852]),
array([25.72727273, 79.36363636]),
array([86.53846154, 82.12820513]),
array([88.2 , 17.11428571]),
array([26.30434783, 20.91304348])]
# 獲取聚類預測結果
transformed = km_model.transform(df_km).select('CustomerID', 'prediction')
# 合併表格
df_pred = df.join(transformed, 'CustomerID')
# 轉化pandas dataframe 然後視覺化
pd_df = df_pred.toPandas()
trace = go.Scatter(x=pd_df.Income, y=pd_df.Spend,
mode='markers',
marker = {'size':10,'color':pd_df.prediction,'colorscale':'Viridis'})
iplot([trace])
結果如下:
BisectingKMeans 二分k均值
pyspark.ml.clustering.BisectingKMeans(featuresCol='features', predictionCol='prediction', maxIter=20, seed=None, k=4, minDivisibleClusterSize=1.0, distanceMeasure='euclidean')
二分k均值(bisecting k-means)演算法的主要思想是:首先將所有點作為一個簇,然後將該簇一分為二。之後選擇能最大程度降低聚類代價函式(也就是誤差平方和)的簇劃分為兩個簇。以此進行下去,直到簇的數目等於使用者給定的數目k為止。
以上隱含著一個原則是:因為聚類的誤差平方和能夠衡量聚類效能,該值越小表示資料點月接近於它們的質心,聚類效果就越好。所以我們就需要對誤差平方和最大的簇進行再一次的劃分,因為誤差平方和越大,表示該簇聚類越不好,越有可能是多個簇被當成一個簇了,所以我們首先需要對這個簇進行劃分。
引數
maxIter: 最大迭代次數
K:聚類簇數
minDivisibleClusterSize: 聚類的最少資料點數(>1)或比例(0-1之間)
fit(dataset, params=None)方法
model方法
clusterCenters(): 獲取聚類中心,numpy array型別
computeCost():計算點與其中心的平方和距離
Transform():對預測資料進行預測
hasSummary:訓練模型是否有summary
Summary:獲取summary
Summary擁有的屬性
cluster:預測的聚類中心
clusterSizes:每個聚類的大小
K:聚類個數
Predictions:由模型的transforn方法產生的預測資料框
GaussianMixture 高斯混合模型
pyspark.ml.clustering.GaussianMixture(featuresCol='features', predictionCol='prediction', k=2, probabilityCol='probability', tol=0.01, maxIter=100, seed=None)
物件實現了用來擬合高斯混合模型的 期望最大化 (EM) 演算法。它還可以為多變數模型繪製置信區間,同時計算 BIC(Bayesian Information Criterion,貝葉斯資訊準則)來評估資料中聚類的數量。
優點:GMM的優點是投影后樣本點不是得到一個確定的分類標記,而是得到每個類的概率,這是一個重要資訊。GMM不僅可以用在聚類上,也可以用在概率密度估計上。缺點:當每個混合模型沒有足夠多的點時,估算協方差變得困難起來,同時演算法會發散並且找具有無窮大似然函式值的解,除非人為地對協方差進行正則化。GMM每一步迭代的計算量比較大,大於k-means。GMM的求解辦法基於EM演算法,因此有可能陷入區域性極值,這和初始值的選取十分相關了。
引數
fit(dataset,params=None)方法
k: 獨立高斯分佈的個數,>1
maxIter: 最大迭代次數 >=0
tol: 迭代演算法的收斂偏差 >=0
model方法
gaussianDF: 抽取高斯分佈作為資料框,每一行代表高斯分佈,有兩列:mean(vector)和 cov(Matrix)
hasSummary: 模型是否有總括函式
summary: 獲取總括資訊
transform(dataset,params=None)方法
weights: 高斯混合模型的權重,和為1
Summary擁有的屬性
cluster:預測的聚類中心
clusterSizes:每個聚類的大小
K:聚類個數
Predictions:由模型的transforn方法產生的預測資料框