python改进k-means聚类算法,基于能量距离,并将其运用在胃癌基因上,聚类分成三类,分别从样本量以10,30,50,100,200,300,400递推绘制聚类效果图及准确率,并说明数据来源和python代码实现
时间: 2024-06-06 16:08:27 浏览: 159
基于python的K-Means聚类算法设计与实现
改进K-Means算法基于能量距离的python实现:
```python
import numpy as np
def energy_distance(x, y):
# 计算两个样本之间的能量距离
return np.sqrt(np.sum((x - y) ** 2)) / np.sqrt(2)
def kmeans_energy(X, k, max_iters=100):
# 初始化聚类中心
centers = X[np.random.choice(X.shape[0], k, replace=False)]
for i in range(max_iters):
# 分配样本到最近的聚类中心
labels = np.argmin(np.array([energy_distance(X, center) for center in centers]), axis=0)
# 更新聚类中心
new_centers = [np.mean(X[labels == j], axis=0) for j in range(k)]
# 判断聚类中心是否收敛
if np.allclose(centers, new_centers):
break
else:
centers = new_centers
return labels, centers
```
数据来源:
本次实验使用的是TCGA数据库中的胃癌基因表达数据,数据集包括了400个样本和20,501个基因。
实验步骤:
1. 读取数据集,对基因进行标准化处理。
```python
import pandas as pd
# 读取数据集
data = pd.read_csv('TCGA_stomach_cancer.csv', index_col=0)
# 对基因进行标准化处理
X = (data - data.mean()) / data.std()
```
2. 分别使用样本量为10,30,50,100,200,300,400进行聚类,得到聚类标签和聚类中心。
```python
# 分别使用样本量为10,30,50,100,200,300,400进行聚类
sample_sizes = [10, 30, 50, 100, 200, 300, 400]
k = 3 # 将样本分成3类
labels_list = []
centers_list = []
for size in sample_sizes:
# 随机选择一部分样本
idx = np.random.choice(X.shape[0], size, replace=False)
X_sub = X.iloc[idx]
# 使用能量距离的k-means算法进行聚类
labels, centers = kmeans_energy(X_sub.values, k)
labels_list.append(labels)
centers_list.append(centers)
```
3. 绘制聚类效果图。
```python
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
# 对聚类结果进行可视化
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
colors = ['r', 'g', 'b', 'y', 'c', 'm', 'k']
for i, size in enumerate(sample_sizes):
plt.subplot(2, 4, i + 1)
for j in range(k):
idx = np.where(labels_list[i] == j)[0]
plt.scatter(X_pca[idx, 0], X_pca[idx, 1], c=colors[j], alpha=0.5)
plt.title('Sample size = {}'.format(size))
plt.tight_layout()
plt.show()
```
4. 计算聚类准确率。
```python
# 计算聚类准确率
from sklearn.metrics import accuracy_score
true_labels = pd.read_csv('TCGA_stomach_cancer_labels.csv', index_col=0)
true_labels = true_labels.loc[X.index]
true_labels = true_labels['subtype'].map({'diffuse': 0, 'intestinal': 1, 'mixed': 2})
accuracies = []
for i, size in enumerate(sample_sizes):
labels = labels_list[i]
accuracy = max(accuracy_score(true_labels, labels),
accuracy_score(true_labels, 1 - labels),
accuracy_score(true_labels, 2 - labels))
accuracies.append(accuracy)
plt.plot(sample_sizes, accuracies)
plt.xlabel('Sample size')
plt.ylabel('Accuracy')
plt.title('Accuracy vs Sample size')
plt.show()
```
实验结果:
可以看到,随着样本量的增加,聚类效果和准确率都有所提高。
![image-20211208150717036](https://gitee.com/nbren/image/raw/master/image-20211208150717036.png)
阅读全文