可以不用sklearn相关函数实现上述代码吗
时间: 2024-03-10 14:45:16 浏览: 67
当然可以,以下是不使用sklearn相关函数的代码实现:
```python
import numpy as np
import matplotlib.pyplot as plt
# 加载鸢尾花数据集
data = np.genfromtxt('iris.data', delimiter=',', usecols=(0, 1, 2, 3))
X = data[:, :-1]
# 定义k-means算法函数
def k_means(X, k, max_iter=100):
# 随机初始化聚类中心
centers = X[np.random.choice(len(X), k, replace=False)]
for i in range(max_iter):
# 计算每个样本到聚类中心的距离
distances = np.sqrt(((X - centers[:, np.newaxis])**2).sum(axis=2))
# 确定每个样本所属的聚类
labels = np.argmin(distances, axis=0)
# 更新聚类中心
new_centers = np.array([X[labels == j].mean(axis=0) for j in range(k)])
# 判断聚类中心是否发生变化
if np.allclose(centers, new_centers):
break
centers = new_centers
return centers, labels
# 计算平方误差和平均轮廓系数
def calc_metrics(X, k):
centers, labels = k_means(X, k)
sse = ((X - centers[labels]) ** 2).sum()
if k == 1:
return sse, 0
else:
a = np.array([np.mean(np.linalg.norm(X[labels == i] - centers[i], axis=1)) for i in range(k)])
b = np.array([np.min(np.concatenate([np.mean(np.linalg.norm(X[labels == j] - centers[i], axis=1)) for j in range(k) if j != i], axis=0)) for i in range(k)])
score = np.mean((b - a) / np.maximum(a, b))
return sse, score
# 确定最优的k值
inertias = []
silhouette_scores = []
for k in range(1, 11):
sse, score = calc_metrics(X, k)
inertias.append(sse)
silhouette_scores.append(score)
best_k = np.argmin(inertias) + 1
# 基于最优的k值进行聚类
centers, labels = k_means(X, best_k)
# 可视化聚类结果
colors = ['red', 'blue', 'green']
for i in range(best_k):
plt.scatter(X[labels == i, 0], X[labels == i, 1], c=colors[i], label=f'Cluster {i+1}')
plt.scatter(centers[:, 0], centers[:, 1], marker='x', s=200, linewidths=3, color='black', label='Centroids')
plt.legend()
plt.show()
```
代码中使用`numpy`库中的函数来计算聚类中心和距离,并使用`argmin`函数来确定每个样本所属的聚类。计算平均轮廓系数时,使用了numpy的广播功能和`concatenate`函数来避免使用循环。
阅读全文