【机器学习实战】利用EM聚类算法对王者荣耀英雄进行聚类

您所在的位置:网站首页 基于高斯混合模型的聚类算法实验报告 【机器学习实战】利用EM聚类算法对王者荣耀英雄进行聚类

【机器学习实战】利用EM聚类算法对王者荣耀英雄进行聚类

2024-07-17 20:22| 来源: 网络整理| 查看: 265

目录

一、EM算法的步骤

二、EM算法的工作原理

三、在sklearn中创建GMM模型

四、工作流程

五、实战环节

1. 导包

2. 加载数据

3. 数据可视化分析

4. 特征工程

5. 数据规范化

6. 建模并产生结果,写入文件

7. 显示聚类后的结果

8. 聚类结果的评估

本篇理论性不多,主要是部分总结及实战内容。

一、EM算法的步骤

EM算法(英文叫做Expectation Maximization,最大期望算法)三个主要的步骤:

初始化参数观察预期重新估计

 

二、EM算法的工作原理

EM算法一般用于聚类,也就是无监督模型里面,因为无监督学习没有标签,EM算法可以先给无监督学习估计一个隐状态(即标签),有了标签,算法模型就可以转换成有监督学习,这时就可以用极大似然估计法求解出模型最优参数。其中估计隐状态流程应为EM算法的E步,后面用极大似然估计为M步。

下面介绍一下两种不同类型的聚类算法:

硬聚类算法:如K-Means ,是通过距离来区分样本之间的差别的,且每个样本在计算的时候只能属于一个分类。软聚类算法:如EM 聚类,它在求解的过程中,实际上每个样本都有一定的概率和每个聚类相关。

EM 算法相当于一个框架,你可以采用不同的模型来进行聚类,比如 GMM(高斯混合模型),或者 HMM(隐马尔科夫模型)来进行聚类。

GMM 是通过概率密度来进行聚类,聚成的类符合高斯分布(正态分布)。 HMM 用到了马尔科夫过程,在这个过程中,我们通过状态转移矩阵来计算状态转移的概率。

 

三、在sklearn中创建GMM模型

本案例采用GMM高斯混合模型。因此将介绍下如何在sklearn中创建GMM聚类。

gmm = GaussianMixture(n_components=1, covariance_type='full', max_iter=100)

看一下这几个参数:

1. n_components:即高斯混合模型的个数,也就是我们要聚类的个数,默认值为 1。如果你不指定 n_components,最终的聚类结果都会为同一个值。

2. covariance_type:代表协方差类型。一个高斯混合模型的分布是由均值向量和协方差矩阵决定的,所以协方差的类型也代表了不同的高斯混合模型的特征。协方差类型有 4 种取值:

covariance_type=full,代表完全协方差,也就是元素都不为 0;covariance_type=tied,代表相同的完全协方差;covariance_type=diag,代表对角协方差,也就是对角不为 0,其余为 0;covariance_type=spherical,代表球面协方差,非对角为 0,对角完全相同,呈现球面的特性。

3. max_iter:代表最大迭代次数,EM 算法是由 E 步和 M 步迭代求得最终的模型参数,这里可以指定最大迭代次数,默认值为 100。

创建完GMM聚类器之后,可以传入数据让它进行迭代拟合。我们使用 fit 函数,传入样本特征矩阵,模型会自动生成聚类器,然后使用 prediction=gmm.predict(data) 来对数据进行聚类,传入你想进行聚类的数据,可以得到聚类结果 prediction。

 

四、工作流程

我们使用王者荣耀英雄数据集来进行聚类,数据包括 69 名英雄的 23 个特征属性。这些属性分别是,英雄,最大生命,生命成长,初始生命,最大法力,法力成长,初始法力,最高物攻,物攻成长,初始物攻,最大物防,物防成长,初始物防,最大每5秒回血,每5秒回血成长,初始每5秒回血,最大每5秒回蓝,每5秒回蓝成长,初始每5秒回蓝,最大攻速,攻击范围,主要定位,次要定位。 

王者荣耀英雄数据集链接:https://github.com/cystanford/EM_data

先划分一下流程:

整个训练过程基本上都会包括三个阶段:

首先加载数据集;

在准备阶段,我们需要对数据进行探索,包括采用数据可视化技术,让我们对英雄属性以及这些属性之间的关系理解更加深刻,然后对数据质量进行评估,是否进行数据清洗,最后进行特征选择方便后续的聚类算法;

聚类阶段:选择适合的聚类模型,这里我们采用 GMM 高斯混合模型进行聚类,并输出聚类结果,对结果进行分析。

 

五、实战环节 1. 导包 import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from sklearn.preprocessing import StandardScaler from sklearn.mixture import GaussianMixture 2. 加载数据 # 数据加载,避免中文乱码问题 data_original = pd.read_csv('dataset/heros.csv', encoding = 'gb18030') 3. 数据可视化分析 data_original.head().append(data_original.tail()) # 显示前5行和后5行数据  英雄最大生命生命成长初始生命最大法力法力成长初始法力最高物攻物攻成长初始物攻...最大每5秒回血每5秒回血成长初始每5秒回血最大每5秒回蓝每5秒回蓝成长初始每5秒回蓝最大攻速攻击范围主要定位次要定位0夏侯惇7350288.8330717469443032111.570159...983.35751371.5711528.00%近战坦克战士1钟无艳7000275.0315017609543031811.000164...923.14348371.5711514.00%近战战士坦克2张飞8341329.43450100010030110.570153...1154.1435750.000514.00%近战坦克辅助3牛魔8476352.8353719261044702738.357156...1174.21458421.7861714.00%近战坦克辅助4吕布7344270.0356400034312.360170...973.0715400.000014.00%近战战士坦克64阿轲5968192.8326900042717.860177...812.2145000.000028.00%近战刺客NaN65娜可露露6205211.9323918089745038515.140173...792.28647381.5711614.00%近战刺客NaN66兰陵王6232210.0329218229845038815.500171...993.35752461.9291914.00%近战刺客NaN67铠6700237.5337517849644032810.860176...812.64344381.5711628.00%近战战士坦克68百里守约5611185.1301917849644041015.860188...682.07139381.5711628.00%远程射手刺客 # 对英雄属性之间的关系进行可视化分析 # 设置plt正确显示中文 plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 plt.rcParams['axes.unicode_minus']=False #用来正常显示负号 # 用热力图呈现特征之间的相关性 corr = data.corr() plt.figure(figsize=(14,14)) # annot=True显示每个方格的数据 sns.heatmap(corr, annot=True) plt.show()

我们将 18 个英雄属性之间的关系用热力图呈现了出来,中间的数字代表两个属性之间的关系系数,最大值为 1,代表完全正相关,关系系数越大代表相关性越大。

从图中你能看出来“最大生命”“生命成长”和“初始生命”这三个属性的相关性大,我们只需要保留一个属性即可。同理我们也可以对其他相关性大的属性进行筛选,保留一个。 这既是对原有属性进行降维。

4. 特征工程 # 相关性大的属性保留一个,因此可以对属性进行降维 features_remain = [u'最大生命', u'初始生命', u'最大法力', u'最高物攻', u'初始物攻', u'最大物防', u'初始物防', u'最大每5秒回血', u'最大每5秒回蓝', u'初始每5秒回蓝', u'最大攻速', u'攻击范围'] data = data_original[features_remain] data  最大生命初始生命最大法力最高物攻初始物攻最大物防初始物防最大每5秒回血最大每5秒回蓝初始每5秒回蓝最大攻速攻击范围073503307174632115939710198371528.00%近战170003150176031816440910092371514.00%近战2834134501003011535041251155514.00%近战3847635371926273156394109117421714.00%近战473443564034317039099970014.00%近战.......................................6459683269042717734989810028.00%近战656205323918083851733598679381614.00%近战666232329218223881713428599461914.00%近战6767003375178432817638810781381628.00%近战685611301917844101883299468381628.00%远程 5. 数据规范化

我们能看到“最大攻速”这个属性值是百分数,不适合做矩阵运算,因此我们需要将百分数转化为小数。我们也看到“攻击范围”这个字段的取值为远程或者近战,也不适合矩阵运算,我们将取值做个映射,用 1 代表远程,0 代表近战。然后采用 Z-Score 规范化,对特征矩阵进行规范化。

data[u'最大攻速'] = data[u'最大攻速'].apply(lambda x: float(x.strip('%'))/100) data[u'攻击范围'] = data[u'攻击范围'].map({'远程':1,'近战':0}) # 采用Z-Score规范化数据,保证每个特征维度的数据均值为0,方差为1 ss = StandardScaler() data = ss.fit_transform(data) 6. 建模并产生结果,写入文件 # 构造GMM聚类 gmm = GaussianMixture(n_components=30, covariance_type='full') gmm.fit(data) # 训练数据 prediction = gmm.predict(data) print(prediction) # 将分组结果输出到CSV文件中 data_original.insert(0, '分组', prediction) data_original.to_csv('./EM_data/heros_out.csv', index=False, sep=',') [ 2 13 6 8 26 3 0 6 21 13 7 13 21 20 17 7 27 21 26 5 9 5 5 5 5 5 5 1 4 23 20 4 16 4 23 4 4 19 12 16 16 4 4 4 29 16 13 12 13 29 24 14 10 11 11 2 25 13 22 26 25 10 15 2 18 14 14 28 1]

我们采用了 GMM 高斯混合模型,并将结果输出到 CSV 文件中。聚类个数为 30。

7. 显示聚类后的结果 data_group = pd.read_csv('./EM_data/heros_out.csv') data_group.sort_values('分组')  分组英雄最大生命生命成长初始生命最大法力法力成长初始法力最高物攻物攻成长...最大每5秒回血每5秒回血成长初始每5秒回血最大每5秒回蓝每5秒回蓝成长初始每5秒回蓝最大攻速攻击范围主要定位次要定位60芈月6164281.5310510001002899.786...772.3574400.00000.00%远程法师坦克681百里守约5611185.1301917849644041015.860...682.07139381.5711628.00%远程射手刺客271成吉思汗5799198.0302717429344039415.000...662.07137361.5001542.00%远程射手NaN632哪吒7268270.4348318089745032011.500...983.21453381.5711628.00%近战战士NaN552杨戬7420291.5333916949142032511.360...983.35751361.5001528.00%近战战士NaN02夏侯惇7350288.8330717469443032111.570...983.35751371.5711528.00%近战坦克战士53亚瑟8050316.3362200034613.000...1063.6435500.000014.00%近战战士坦克314甄姬5584181.6304120021084902969.357...712.00043441.8571814.00%远程法师NaN334干将莫邪5583171.0318919461044902929.500...711.85745411.7141714.00%远程法师NaN414小乔5916202.0308819881074902637.857...752.21444431.7861814.00%远程法师NaN

第一列代表的是分组(簇),我们能看到百里守约和成吉思汗分到了一组,哪吒、杨戬和夏侯惇是一组,亚瑟自己是一组,甄姬、干将莫邪和小乔是一组。

聚类的特点是相同类别之间的属性值相近,不同类别的属性值差异大。

8. 聚类结果的评估

聚类和分类不一样,聚类是无监督的学习方式,也就是我们没有实际的结果可以进行比对,所以聚类的结果评估不像分类准确率一样直观,那么有没有聚类结果的评估方式呢?这里我们可以采用 Calinski-Harabaz 指标,代码如下:

from sklearn.metrics import calinski_harabaz_score print(calinski_harabaz_score(data, prediction)) 20.273576816244606

指标分数越高,代表聚类效果越好,也就是相同类中的差异性小,不同类之间的差异性大。当然具体聚类的结果含义,我们需要人工来分析,也就是当这些数据被分成不同的类别之后,具体每个类表代表的含义。

 

 

   


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3