导入库
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.cluster import DBSCAN
from matplotlib import pyplot as plt
KMeans
这个前面都写过,下面是一个完整的流程,可以自己实践完整写一遍
DBSCAN
直接看全文代码吧,DBSCAN在后半部分
全文代码
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.cluster import DBSCAN
from matplotlib import pyplot as plt
### KMeans算法
#### 准备数据集
data = pd.read_csv('销售利润表.csv')
data
data.shape
data.info()
data.head()
data.describe()
data.drop(columns="Unnamed: 0",inplace=True) #删除未命名那列
data.head()
#### 构建KMeans模型
KMeans?
km = KMeans(n_clusters=8,max_iter=300,tol=0.01) #写km = KMeans()也可以,因为是默认值
#### 训练模型
km.fit(data)
#### 查看属性
#质心
km.cluster_centers_
#属于哪个簇
km.labels_
#误差平方和
km.inertia_
#### 最优模型(调参)
result = []
for n_clusters in range(2,10):
for max_iter in range(300,601,50): #最大迭代次数
for tol in range(2,10):
tol=tol*1e-5
km = KMeans(n_clusters=n_clusters,max_iter=max_iter,tol=tol)
km.fit(data)
d={'n_clusters':n_clusters,'max_iter':max_iter,'tol':tol,'inertia':km.inertia_}
result.append(d)
# 一个模型的参数放在字典d里面,用result.append(d)把所有模型的参数存起来到result列表
result
result_df = pd.DataFrame(result) #主要DataFrame的DF都大写
result_df
#导出DataFrame
#outputpath='C:/Users/DANNY/Desktop/DataFrame导出.csv'
#result_df.to_csv(outputpath,sep=',',index=False,header=True)
# 找到误差平方和最小时,对应的那一行的各项参数
result_df["inertia"].argmin() #想找到inertia列的最小值
r=result_df.iloc[result_df["inertia"].argmin(),:] #用iloc[]定位那一行,列都要
#注意,KMeans找拐点才是更准确的,这里只是找了最小簇内平方和
r
#type(r) #如果查看r类型发现上图是pandas中的一维图Series
n_clusters = r["n_clusters"]
n_clusters #簇
max_iter = r["max_iter"]
max_iter #最大迭代数
tol = r['tol']
tol #总的误差平方和
tol = int(tol) #下一行绘图时发现tol不是int报错,所以提前强转
#### 绘图
x=[]
y=[]
for n_clusters in range(2,20):
km=KMeans(n_clusters=n_clusters,max_iter=max_iter,tol=tol)
km.fit(data)
#保存
x.append(n_clusters)
y.append(km.inertia_)
x
y
#绘图
plt.figure(figsize=(20,8))
plt.plot(x,y,"o-")
plt.xlabel('K')
plt.ylabel('inertia')
plt.title('k-inertia relation')
#将数字标注到折线图
for a,b in zip(x,y):
plt.text(a,b,round(b,0),ha='center',va='bottom')
#结论
聚类的簇 7-10个皆可
#### 相对较优参数进行 可视化呈现(簇状图)
clf = KMeans(n_clusters=5,max_iter=600,tol=8e-5)
clf.fit(data)
clf.cluster_centers_ #质心
clf.labels_ #所属簇标签
clf.inertia_ #误差平方和
#绘图
plt.figure(figsize=(20,8))
plt.scatter(data['销售价格'],data['利润'],c=clf.labels_,marker='x') #scatter画散点图
plt.scatter(clf.cluster_centers_[:,0],clf.cluster_centers_[:,1],c='red')
plt.xlabel('price')
plt.ylabel('profit')
plt.title('KMeans-Sales profit Data')
plt.show() #注意写()
### DBSCAN
#### 构建模型
db=DBSCAN()
#### 训练模型
db.fit(data)
#### 查看属性
#核心点索引
db.core_sample_indices_
#核心点
db.components_
#每个样本所属的簇
labels = db.labels_
labels
type(labels) #numpy的数组
#查看是否有噪声点
if -1 in labels:
print('有噪声点')
else:
print('没有噪声点')
#查看噪声点个数
noise = list(labels).count(-1)
print("噪声点的个数:{}".format(noise))
#簇的个数
num_clusters = len(set(labels))-(1 if -1 in labels else 0)
print("簇的个数:{}".format(num_clusters))
#### 调参寻找最优模型
result = []
for r in range(2,20):
eps=r*1e-2 #把eps单独做个变量优化算法
for min_samples in range(2,20):
db=DBSCAN(eps=eps,min_samples=min_samples)
db.fit(data)
labels=db.labels_
noise=list(labels).count(-1)#噪声点个数
num_clusters=len(set(labels))-(1 if -1 in labels else 0)#簇的个数
d={"eps":eps,"min_samples":min_samples,"noise":noise,"num_cluster":num_clusters}
result.append(d)
result
df=pd.DataFrame(result)
df
df["num_cluster"].min() #发现最少都有17个簇,尽量少一点
#for min_samples in range(2,20): 这一行range(2,10)改成(2,20)就只剩七个了
#反正就是不断的调 半径eps和密度min_samples的range范围
df[df["num_cluster"]==7] #输出簇为7的相关行的参数
df[df.noise == df.noise.min()] #看看噪声最少时的参数
#### 可视化呈现
plt.figure(figsize=(20,8))
plt.scatter(data["销售价格"],data["利润"],c=labels)
plt.scatter(db.components_[:,0],db.components_[:,-1],c='red')
plt.xlabel("price")
plt.ylabel("profit")
plt.title("DBSCAN-Sales profit Data")
plt.show()
### 结论
数据集的密度不稠密,聚类质量较差,DBSCAN不太适合,建议用KMeans