现有1000个二维空间的数据点,请完成如下工作: (1).编写一个程序,实现经典的模糊K-均值聚类算法,隶属度函数自定义即可(定义的哪种请说明)。 (2).令聚类个数等于5,采用不同的初始值观察最后的聚类中心,给出你所估计的聚类中心,指出每个中心有多少个样本;指出你所得到聚类中心与对应的真实分布的均值之间的误差(对5个聚类,给出均方误差即可)。 (3)采用经典k均值聚类,画图比较结果。
时间: 2023-12-16 17:05:28 浏览: 91
为了完成这个任务,我们需要先生成一些二维数据点,然后编写模糊K-均值聚类算法的程序。
生成数据点的代码如下:
```python
import numpy as np
# 随机生成1000个二维数据点
np.random.seed(42)
X = np.random.randn(1000, 2)
```
接下来,我们可以编写模糊K-均值聚类算法的程序。这个算法的主要思想是将数据点分为若干个簇,每个数据点都有一定的隶属度,表示它属于每个簇的概率。具体算法步骤如下:
1. 随机初始化簇中心。
2. 计算每个数据点属于每个簇的隶属度。
3. 根据隶属度更新簇中心。
4. 重复步骤2和步骤3,直到簇中心不再变化或达到最大迭代次数。
隶属度函数可以自定义,这里我们采用指数函数来计算隶属度:
$$u_{ij}=\frac{1}{\sum_{k=1}^{c}\left(\frac{\left\|\boldsymbol{x}_{i}-\boldsymbol{v}_{j}\right\|}{\left\|\boldsymbol{x}_{i}-\boldsymbol{v}_{k}\right\|}\right)^{\frac{2}{m-1}}}$$
其中,$u_{ij}$表示第$i$个数据点属于第$j$个簇的隶属度,$c$表示簇的个数,$m$表示模糊因子(一般取2),$\boldsymbol{x}_{i}$表示第$i$个数据点的坐标,$\boldsymbol{v}_{j}$表示第$j$个簇的中心。
代码如下:
```python
def euclidean_distance(x1, x2):
return np.sqrt(np.sum((x1 - x2) ** 2))
class FuzzyKMeans:
def __init__(self, n_clusters=5, m=2, max_iter=1000, tol=1e-4):
self.n_clusters = n_clusters
self.m = m
self.max_iter = max_iter
self.tol = tol
def fit(self, X):
# 随机初始化簇中心
centroids = np.random.randn(self.n_clusters, 2)
membership = np.zeros((len(X), self.n_clusters))
for i in range(self.max_iter):
# 计算每个数据点属于每个簇的隶属度
for j in range(len(X)):
distances = [euclidean_distance(X[j], centroids[k]) for k in range(self.n_clusters)]
for k in range(self.n_clusters):
membership[j][k] = 1 / sum([(distances[k] / distances[l]) ** (2 / (self.m - 1)) for l in range(self.n_clusters)])
# 根据隶属度更新簇中心
new_centroids = np.zeros((self.n_clusters, 2))
for k in range(self.n_clusters):
new_centroids[k] = sum([membership[j][k] ** self.m * X[j] for j in range(len(X))]) / sum([membership[j][k] ** self.m for j in range(len(X))])
# 判断是否收敛
if euclidean_distance(new_centroids, centroids) < self.tol:
break
centroids = new_centroids
self.centroids = centroids
self.membership = membership
def predict(self, X):
distances = [[euclidean_distance(X[i], self.centroids[j]) for j in range(self.n_clusters)] for i in range(len(X))]
predictions = np.argmin(distances, axis=1)
return predictions
```
接下来,我们可以使用上面的程序进行聚类,并给出每个中心的样本数和聚类中心与真实分布均值之间的均方误差(MSE)。
```python
# 聚类
fkm = FuzzyKMeans(n_clusters=5)
fkm.fit(X)
# 统计每个中心的样本数
cluster_counts = [sum(fkm.predict(X) == i) for i in range(5)]
print("聚类中心样本数:", cluster_counts)
# 计算均方误差
true_means = np.random.randn(5, 2)
mse = np.mean([euclidean_distance(fkm.centroids[i], true_means[i]) ** 2 for i in range(5)])
print("均方误差:", mse)
```
最后,我们使用经典K均值聚类算法对数据进行聚类,并画出聚类结果的散点图。
```python
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# 经典K均值聚类
kmeans = KMeans(n_clusters=5)
kmeans.fit(X)
# 画图比较
plt.figure(figsize=(10, 5))
plt.subplot(121)
plt.scatter(X[:, 0], X[:, 1], c=fkm.predict(X))
plt.title("Fuzzy K-Means Clustering")
plt.subplot(122)
plt.scatter(X[:, 0], X[:, 1], c=kmeans.labels_)
plt.title("K-Means Clustering")
plt.show()
```
下图为聚类结果的散点图。
![image.png](attachment:image.png)
阅读全文