k-means算法

聚类算法-K-means-超市顾客聚类

1. 算法介绍

不同的用户对产品有不同的需求,所以需要针对不同的用户设计不同的产品功能,首先需要对用户进行分群。用于客户分类的方法有如RFM模型,即通过一个客户的近期购买行为(RecencyR)、购买的总体频率(FrequencyF)以及花了多少钱(MonetaryM)这三项指标来描述该客户的价值状况。

RFM是一个简洁、有效的模型,但是这三个维度包含的信息有限,对商业问题的解释度不够,分类效果不稳定、模型可优化性差,k-means可以有效解决。

k-means是根据样本间的某种距离或者相似性来定义聚类,把相似的(或距离近的)样本聚为同一类,而把不相似的(或距离远的)样本归在其他类。

2.代码实现

数据来源:Mall Customer Segmentation Data | Kaggle

字段解释:

CustomerID:Unique ID assigned to the customer

Gender:Gender of the customer

Age:Age of the customer

Annual Income (k$):Annual Income of the customee

Spending Score (1-100):Score assigned by the mall based on customer behavior and spending nature

  • 导包

    1
    2
    3
    4
    import math
    import matplotlib.pyplot as plt
    import random
    import pandas as pd
  • 加载数据

    1
    2
    3
    def load_data():
    df = pd.read_csv(r'C:/Users/Sheng/Desktop/Mall_Customers.csv')
    df.head()
  • 计算欧式距离

    1
    2
    3
    4
    5
    6
    7
    # 获取欧式距离
    def get_euclidean_distance(point1, point2):
    dimension = len(point1)
    dist = 0.0
    for i in range(dimension):
    dist += (point1[i] - point2[i]) ** 2
    return math.sqrt(dist)
  • 开始聚类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    def k_means(dataset, k, iteration):
    #初始化簇心
    index = random.sample(list(range(len(dataset))), k)
    vectors = []
    for i in index:
    vectors.append(dataset[i])

    #初始化标签
    labels = []
    for i in range(len(dataset)):
    labels.append(-1)

    #根据迭代次数重复k-means聚类过程
    while(iteration > 0):
    #初始化簇
    C = []
    for i in range(k):
    C.append([])

    # 遍历数据
    for labelIndex, item in enumerate(dataset):
    # 属于的中心点编号
    classIndex = -1
    # 最小距离
    minDist = 1e6
    # 计算到 k 个中心点之间的距离
    for i, point in enumerate(vectors):
    dist = get_euclidean_distance(item, point)
    if(dist < minDist):
    classIndex = i
    minDist = dist
    # 把当前元素放到距离最近的中心点的下标的数组中
    C[classIndex].append(item)
    # 记录当前元素属于哪个中心点
    labels[labelIndex] = classIndex

    for i, cluster in enumerate(C):
    clusterHeart = []
    dimension = len(dataset[0])
    for j in range(dimension):
    clusterHeart.append(0)
    for item in cluster:
    for j, coordinate in enumerate(item):
    clusterHeart[j] += coordinate / len(cluster)
    vectors[i] = clusterHeart
    iteration -= 1
    return C, labels
  • 主方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    if __name__ == "__main__":
    df = pd.read_csv(r'C:\\Users\\Sheng\\Desktop\\Mall_Customers.csv')
    dataset = df[['Age', 'Spending Score (1-100)']].iloc[: , :].values
    # dataset:数据集
    # k:聚成几类
    # iteration: 迭代次数
    C, labels = k_means(dataset, 3, 20)

    colValue = ['r', 'y', 'g', 'b', 'c', 'k', 'm']
    for i in range(len(C)):
    coo_X = [] #x坐标列表
    coo_Y = [] #y坐标列表
    for j in range(len(C[i])):
    coo_X.append(C[i][j][0])
    coo_Y.append(C[i][j][1])
    plt.scatter(coo_X, coo_Y, marker='x', color=colValue[i%len(colValue)], label=i) plt.show()
  • 结果查看

迭代1次:图片丢失了…跑一下程序自己看吧

迭代10次:图片丢失了…跑一下程序自己看吧

迭代20次:图片丢失了…跑一下程序自己看吧

迭代50次:图片丢失了…跑一下程序自己看吧

迭代100次:图片丢失了…跑一下程序自己看吧

迭代200次:图片丢失了…跑一下程序自己看吧

取得了良好的效果,可以停止迭代。

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×