机器学习之聚类分析K-Means

最近一直想用聚类来分析一下现在的数据,今天发现了一本《python数据分析与挖掘实战》,其中有个案例是介绍航空公司客户价值的分析,其中用到的聚类方法是K-Means方法,搜索网上相关的内容发现好多博客都有些这个案例,找了一个认为比较好的博客来学习,并用自己的数据进行了聚类。
参考博客:https://blog.csdn.net/a857553315/article/details/79177524

1. 读取数据

import pandas as pd #数据分析
import numpy as np #科学计算
from pandas import Series,DataFrame

//读取数据
columns = ['mac', 'tv_duration', 'movie_duration', 'variety_duration', 'tourism_duration','sports_duration',
          'life_duration','game_duration','fashion_duration','entertainment_duration','education_duration',
   'doc_duration','children_duration','cartoon_duration','car_duration','baby_duration','MV_duration']
df = pd.read_table("duartion_user.txt")
df.columns=columns
#因为其他几类数据用户看的较少,因此只选择下面的7类内容进行分析
data_train=df[['tv_duration', 'movie_duration', 'variety_duration','sports_duration','doc_duration','children_duration','cartoon_duration']]
data_train.head()

结果为:
这里写图片描述

2.过滤离群值

本文刚开始没有对数据进行过滤,发现怎么聚类都聚不好,后来发现可能是存在离群值,因此参考:
https://www.jianshu.com/p/b490ac402fe6 中最简单的统计分析,进行了简单处理。

min_data= data_train.mean(axis=0)-2*data_train.std(axis=0)
max_data=data_train.mean(axis=0)+2*data_train.std(axis=0)

data_train=data_train[data_train>min_data]
data_train=data_train[data_train<max_data]
data_train

这里写图片描述

发现存在NaN值,因此对行存在NaN的值进行过滤

data_train=data_train.dropna()
data_train

发现11行的被过滤掉了。
这里写图片描述

3.归一化处理

#归一化处理
filter_zscore_data=(data_train - data_train.mean(axis=0))/(data_train.std(axis=0))

4.聚类分析

#中文和负号的正常显示
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

def distEclud(vecA,vecB):
    '''
    计算两个向量的欧式距离的平方,并返回
    '''
    return np.sum(np.power(vecA-vecB,2))

def test_Kmeans_nclusters(data_train):
    '''
    计算不同的k值时,SSE的大小变化
    '''
    data_train=data_train.values
    nums=range(2,10)
    SSE=[]
    for num in nums:
        sse=0
        kmodel=KMeans(n_clusters=num,n_jobs=4)
        kmodel.fit(data_train)
        #簇中心
        cluster_center_list=kmodel.cluster_centers_
        #个样本属于的簇序号列表
        cluster_list=kmodel.labels_.tolist()

        for index in range(len(data_train)):
            cluster_num=cluster_list[index]
            sse+=distEclud(data_train[index],cluster_center_list[cluster_num])
        print (u"簇数是",num,u"时;SSE是",sse)
        SSE.append(sse)
    return nums,SSE

nums,SSE = test_Kmeans_nclusters(filter_zscore_data)
#画图,通过观察SSE与K的取值尝试找出合适的k值

plt.rcParams['font.sans-serif']='SimHei'
plt.rcParams['font.size']=12
plt.rcParams['axes.unicode_minus']= False
#使用ggplot的绘图风格
plt.style.use('ggplot')
##绘图观测SSE与簇个数的关系
fig=plt.figure(figsize=(10,8))
ax= fig.add_subplot(1,1,1)
ax.plot(nums,SSE,marker='+')
ax.set_xlabel("n_clusters",fontsize=18)
ax.set_xlabel("SSE",fontsize=20)
fig.suptitle("KMeans",fontsize=20)
plt.show()

这里写图片描述

def test_keams(num):
    kmodel=KMeans(n_clusters=num,n_jobs=4)
    kmodel.fit(filter_zscore_data)
    #简单打印结果
    r1 = pd.Series(kmodel.labels_).value_counts()#统计各个类别的数目
    r2 = pd.DataFrame(kmodel.cluster_centers_)#找出聚类中心
    print r1
    print r2
   #所有簇中心坐标中最大值和最小值
    max = r2.values.max()
    min= r2.values.min()
    r = pd.concat([r2,r1],axis=1) #横向连接(0是纵向),得到聚类中心对应的类别下的数目
    r.columns=list(filter_zscore_data.columns)+[u'类别数目'] #重命名表头
    fig = plt.figure(figsize=(10,8))
    ax= fig.add_subplot(111,polar= True)
    center_num=r.values
    feature=['tv_duration','movie_duration','variety_duration','sports_duration','doc_duration','children_duration','cartoon_duration']
    N =len(feature)  
    for i,v in enumerate(center_num):
        #设置雷达图的角度,用于平分切开一个圆面
        angles=np.linspace(0,2*np.pi,N,endpoint=False)
        #为了使雷达图一圈封闭起来,需要下面的步骤
        center=np.concatenate((v[:-1],[v[0]]))
        angles=np.concatenate((angles,[angles[0]]))  
        # 绘制折线图  
        ax.plot(angles, center, 'o-', linewidth=2, label = "第%d簇人群,%d人"% (i+1,v[-1]))  
        # 填充颜色  
        ax.fill(angles, center, alpha=0.25)  
        # 添加每个特征的标签  
        ax.set_thetagrids(angles * 180/np.pi, feature, fontsize=15)  
        # 设置雷达图的范围  
        ax.set_ylim(min-0.1, max+0.1)  
        # 添加标题  
        plt.title('客户群特征分析图', fontsize=20)  
        # 添加网格线  
        ax.grid(True)  
        # 设置图例  
        plt.legend(loc='upper right', bbox_to_anchor=(1.3,1.0),ncol=1,fancybox=True,shadow=True)  
        # 显示图形  
    plt.show()  
test_keams(8)

尝试了聚类次数发现当为8时,效果不错,如图。
这里写图片描述

当k取值为8时,得到最好的聚类效果,将所有的客户分成8个人群,
其中7个是各个视频类型使用较多的用户,这种往往用户都会相对较少;剩下的就是各个领域都不突出的用户,往往占据大多数。除了第一类,应该都是价值较大的用户,应重点分析

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值