爱数课实验 | 汽车款式聚类_数据集

爱数课:idatacourse.cn


领域:消费




简介:市面上的汽车种类繁多,令很多消费者难以选择,根据每种汽车的参数,利用聚类算法(本案例基于k-means聚类、DBSCAN聚类以及层次聚类三种方法)进行聚类,识别出相似的汽车。本案例使用的数据集来源于卡内基梅隆大学维护的StatLib库。汽车款式数据集中共有392个汽车样本, 8个特征,每个字段的说明如下:




数据:

./dataset/Auto.csv



字段名称

字段类型

字段说明

mpg

浮点型

每加仑英里

cylinders

整型

气缸数在4到8之间

displacement

浮点型

发动机排量(立方英寸)

horsepower

整型

引擎马力

weight

整型

车重(磅)

acceleration

浮点型

从0加速到60 mph(秒)的时间

year

整型

型号年份

origin

整型

汽车来源(1.美国,2.欧洲,3.日本)


爱数课实验 | 汽车款式聚类_数据集_02

1. 准备工作

为了后面的数据处理和聚类分析能够顺利的进行,这里先做一些准备工作,如忽略警告信息,导入相关的包和模块,以及查看数据集的基本统计信息。

# 忽略警告信息
import warnings
warnings.filterwarnings("ignore")
#导入相关的包和模块
import numpy as np
import pandas as pd
from sklearn import metrics
#读入数据集并查看数据集的前五行信息
auto = pd.read_csv('./dataset/Auto.csv')
auto.head()

爱数课实验 | 汽车款式聚类_数据集_03

#查看数据集基本信息
auto.info()

爱数课实验 | 汽车款式聚类_聚类_04

该方法将展示数据类型、数据集是否存在缺失值、字段名称等信息,这里的结果显示该数据集不存在缺失值。

2. 数据预处理

由于聚类要计算距离,为了消除量纲的影响以及计算的方便,这里先对​​mpg​​​,​​displacement​​​,​​horsepower​​​,​​weight​​​,​​acceleration​​​五个连续型变量用Z-score标准化,对​​cylinders​​​,​​year​​​,​​origin​​三个类别变量进行哑变量编码。

#Z-score标准化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
auto[['mpg','displacement','horsepower','weight','acceleration']] = scaler.fit_transform(auto[['mpg','displacement','horsepower','weight','acceleration']])
#哑变量编码
auto_scaled = pd.get_dummies(data=auto,columns=['cylinders','year','origin'])
#查看进行标准化处理和哑变量编码后数据集的前两行
auto_scaled.head(2)

爱数课实验 | 汽车款式聚类_聚类_05

3. k-Means聚类

K-Means聚类基于点与点之间的距离的相似度来计算最佳类别归属。其核心目标是将给定的数据集划分成K个簇,并给出每个样本数据对应的中心点。

#导入K-Means聚类方法,将初始K值设为3,随机种子数设为0,并训练模型
from sklearn.cluster import KMeans
model = KMeans(n_clusters=3,random_state=0).fit(auto_scaled)
#将样本标签和簇质心保存在auto_lable和auto_cluster中,展示分类结果标签的前十行,以及簇质心的第一行
auto_label = model.labels_
auto_cluster = model.cluster_centers_
print(auto_label[:10])
print(auto_cluster[0])

爱数课实验 | 汽车款式聚类_数据_06

pd.value_counts(auto_label)

爱数课实验 | 汽车款式聚类_数据_07

簇1有205个样本,簇2有96个样本,簇0有91个样本。

#找出簇质心连续性变量的坐标
centroid_cluster = pd.DataFrame(auto_cluster).copy().iloc[:,:5]
centroid_cluster.columns=['mpg','displacement','horsepower','weight','acceleration']

#将数据逆标准化,转换为原始数据,结果保留两位小数:
centroid_cluster_inversescale = pd.DataFrame(scaler.inverse_transform(centroid_cluster))
centroid_cluster_inversescale.columns=['mpg','displacement','horsepower','weight','acceleration']
centroid_cluster_inversescale.applymap(lambda x:'%.2f'%x)

爱数课实验 | 汽车款式聚类_数据_08

从聚类结果我们可以看到,当把数据聚成三个簇时,各个簇的主要特点如下:
簇0:耗油量小,引擎排量小,引擎马力小,重量轻,加速性能差
簇1:耗油量大,引擎排量大,引擎马力大,重量重,加速性能强
簇2:耗油量中等,引擎排量中等,引擎马力中等,重量中等,加速性能较差

结果评估:选择轮廓系数作为聚类性能的评估指标,轮廓系数取值范围为[-1,1],轮廓系数为-1时表示聚类结果不好,为+1时表示簇内实例之间紧凑,为0时表示有簇重叠。轮廓系数越大,表示簇内实例之间紧凑,簇间距离大,即聚类的效果越好。

#轮廓系数结果保留四位小数
labels = model.labels_
print("轮廓系数(Silhouette Coefficient): %0.4f"
% metrics.silhouette_score(auto_scaled, labels))

轮廓系数(Silhouette Coefficient): 0.3183

选择不同k值比较聚类效果(k值分别选择2,4,6,8,10,12)

for i in range(2,12,2):
model = KMeans(n_clusters=i,random_state=0).fit(auto_scaled)
labels = model.labels_
print("轮廓系数(Silhouette Coefficient): %0.4f"% metrics.silhouette_score(auto_scaled, labels))

爱数课实验 | 汽车款式聚类_数据集_09

根据结果可以看到当k值取2时,其轮廓系数最大,即聚类效果最佳。

4. DBSCAN聚类

DBSCAN是一种典型的基于密度的聚类算法,在DBSCAN算法中将数据点分为一下三类:
1、核心点:在半径Eps内含有超过MinPts数目的点
2、边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域内
3、噪音点:既不是核心点也不是边界点的点(离群点)
在这一节我们首先设置第一种密度参数对其进行聚类分析,然后再调整密度参数,并将不同密度参数的结果进行可视化。

#导入DBSCAN
from sklearn.cluster import DBSCAN
#模型的参数设置:一个是半径eps,这里设置为1.5,另一个是指定的数目MinPts,这里设置为4:
model = DBSCAN(eps=1.5,min_samples=4).fit(auto_scaled)

聚类结果展示:根据我们设置的参数,DBSCAN将所有样本分为四类(包含噪声点),并按照每一类的数量降序展示

auto_label = model.labels_
df=pd.value_counts(auto_label)
df

爱数课实验 | 汽车款式聚类_数据集_10

import matplotlib.pyplot as plt
plt.figure(figsize=(5,5))
df.plot.bar()

爱数课实验 | 汽车款式聚类_数据_11

这里 -1表示噪声点,其样本量有43个,簇1有样本181个,簇0有样本164个,簇2有样本4个。

将不同簇的数据使用均值聚合,得到近似类中心。

#先将数据逆标准化,转为原始数据,并取出前五列,再根据聚类标签分类使用均值聚合,结果保留两位小数
auto_new_continuous = pd.DataFrame(scaler.inverse_transform(auto_scaled.iloc[:, :5]),
columns=['mpg','displacement','horsepower','weight','acceleration'])
auto_new_continuous['label'] = auto_label
auto_new_continuous.groupby('label').mean().applymap(lambda x:'%.2f'%x)

爱数课实验 | 汽车款式聚类_数据_12

从聚类结果我们可以看到,当把数据聚成三个簇时和噪音簇,各个簇的主要特点如下:
簇0:耗油量中等,引擎排量中等,引擎马中等,重量中等,加速性能差
簇1:耗油量大,引擎排量小,引擎马力小,重量轻,加速性能强
簇2:耗油量小,引擎排量大,引擎马力大,重量重,加速性能中等

评估聚类效果:去除噪声点样本后,计算轮廓系数

labels = model.labels_
metrics.silhouette_score(auto_scaled[labels>-1],labels[labels>-1])

0.2642413302454532

调整密度参数,查看聚类结果

# 不同最小样本数下的簇个数
## 设置参数取值范围
min_samples_grid = [1,2,3,4]

## 训练模型并输出簇个数
cluster_number = []
slt_score = []
noise_count = []
for item in min_samples_grid:
model = DBSCAN(eps=1.5,min_samples=item).fit(auto_scaled)
cluster_number.append(len(np.unique(model.labels_))-1)
slt_score.append(metrics.silhouette_score(auto_scaled[model.labels_>-1],
model.labels_[model.labels_>-1]))
noise_count.append((model.labels_==-1).sum())

可视化

## 绘图
import matplotlib.pyplot as plt
plt.plot(min_samples_grid, cluster_number, 'r-*', linewidth=2)
plt.xlabel('最小样本数')
plt.ylabel('簇个数')
plt.title('不同最小样本数下聚类的簇个数')

爱数课实验 | 汽车款式聚类_数据_13

最小样本数越多,其得到的簇个数越少。

plt.plot(min_samples_grid, slt_score, 'b-*', linewidth=2)
plt.xlabel('最小样本数')
plt.ylabel('轮廓系数')
plt.title('不同最小样本数下聚类的轮廓系数')

爱数课实验 | 汽车款式聚类_数据集_14

最小样本数越多,其轮廓系数越大。

plt.plot(min_samples_grid, noise_count, 'g-*', linewidth=2)
plt.xlabel('最小样本数')
plt.ylabel('噪声点数量')
plt.title('不同最小样本数下聚类的噪声点数量')

爱数课实验 | 汽车款式聚类_数据_15

最小样本数越多,噪声点数量越多。

5. 层次聚类

层次聚类(hierarchical clustering)有两种常用的形式,自顶向下和自底向上。
其中,自底向上的主要做法是,在开始时,将每个样本视为一个簇,重复的合并最近的两个簇,直到簇的个数达到给定值。

from sklearn.cluster import AgglomerativeClustering
# 训练模型
model = AgglomerativeClustering(n_clusters=3,linkage='average').fit(auto_scaled)
# 输出模型结果
auto_label = model.labels_
auto_label = model.labels_
df=pd.value_counts(auto_label)
df

爱数课实验 | 汽车款式聚类_数据_16

plt.figure(figsize=(5,5))
df.plot.bar()

爱数课实验 | 汽车款式聚类_聚类_17

#先将数据逆标准化,转为原始数据,并取出前五列,再根据聚类标签分类使用均值聚合,结果保留两位小数
auto_new_continuous = pd.DataFrame(scaler.inverse_transform(auto_scaled.iloc[:, :5]),
columns=['mpg','displacement','horsepower','weight','acceleration'])
auto_new_continuous['label'] = auto_label
auto_new_continuous.groupby('label').mean().applymap(lambda x:'%.2f'%x)

爱数课实验 | 汽车款式聚类_聚类_18

从聚类结果我们可以看到,当把数据聚成三个簇时,各个簇的主要特点如下:
簇0:耗油量中等,引擎排量中等,引擎马中等,重量重,加速性能中等;
簇1:耗油量大,引擎排量大,引擎马力大,重量中等,加速性能较差;
簇2:耗油量小,引擎排量小,引擎马力小,重量轻,加速性能较强;

#轮廓系数结果保留四位小数
labels = model.labels_
print("轮廓系数(Silhouette Coefficient): %0.4f"
% metrics.silhouette_score(auto_scaled, labels))

轮廓系数(Silhouette Coefficient): 0.3075