## 二、聚类

①K-means聚类算法

```import numpy as np
from sklearn.cluster import KMeans
# 引入sklearn.cluster库
fr = open(filePath, 'r+')
# 以读写形式打开路径上的文件
retData = []
retCityName = []
# 准备读取数据用的数据结构
for line in lines:
items = line.strip().split(",")
# 去除一行中首尾的空格，之后根据逗号进行划分
retCityName.append(items[0])
# 获得城市名
retData.append([float(items[i]) for i in range(1, len(items))])
# 获得城市数据
return retData, retCityName
if __name__ == '__main__':
# 读取数据
km = KMeans(n_clusters=4)
# 调用KMeans函数，参数表明k的值
label = km.fit_predict(data)
# 将数据导入函数
expenses = np.sum(km.cluster_centers_, axis=1)
# 计算每个簇中城市的数目
CityCluster = [[], [], [], []]
for i in range(len(cityName)):
CityCluster[label[i]].append(cityName[i])
# 存储分类结果
for i in range(len(CityCluster)):
print("Expenses:%.2f" % expenses[i])
print(CityCluster[i])
# 输出每个簇的城市以及平均花费输出```

②DBSCAN算法

DBSCAN算法将数据点分为下面的三类：

```import numpy as np
import sklearn.cluster as skc
from sklearn import metrics
import matplotlib.pyplot as plt
mac2id = dict()
onlinetimes = []
f = open('TestData.txt', encoding='utf-8')
# 读取数据
for line in f:
mac = line.split(',')[2]
onlinetime = int(line.split(',')[6])
starttime = int(line.split(',')[4].split(' ')[1].split(':')[0])
# 读取每一行的开始上网时间和上网时长
if mac not in mac2id:
mac2id[mac] = len(onlinetimes)
onlinetimes.append((starttime, onlinetime))
else:
onlinetimes[mac2id[mac]] = [(starttime, onlinetime)]
# 将上网信息存入字典
real_X = np.array(onlinetimes).reshape((-1, 2))
X = real_X[:, 0:1]
db = skc.DBSCAN(eps=0.01, min_samples=20).fit(X)
# 调用DBSCAN，指定两个参数，并且传入数据
labels = db.labels_
# 得到划分的标签簇
print('Labels:')
print(labels)
# 打印划分
raito = len(labels[labels[:] == -1]) / len(labels)
print('Noise raito:', format(raito, '.2%'))
# 打印噪声率
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
print('Estimated number of clusters: %d' % n_clusters_)
print("Silhouette Coefficient: %0.3f" % metrics.silhouette_score(X, labels))
# 打印结果评价
for i in range(n_clusters_):
print('Cluster ', i, ':')
print(list(X[labels == i].flatten()))
# 打印每个簇的数据
plt.hist(X, 24)
# 以直方图形式打印结果```

## 三、降维

①PCA算法

PCA中文名称主成分分析，是一种常用的降维方法，可以用于高维数据集的探索与可视化，也可以用作数据的预处理和压缩。PCA可以将具有相关性的高维变量合成为线性无关的低位变量，而主成分则尽可能保留原始数据的信息。

```import matplotlib.pyplot as plt
# 数据可视化需要用到matplotlib库
from sklearn.decomposition import PCA
# 使用PCA需要用decomposition库
# 使用鸢尾花数据集需要引入datasets库
# 加载鸢尾花数据集
y = data.target
# 取出数据中的标签,即鸢尾花的分类结果
X = data.data
# 取出数据中的数值，即待降维的四维数据
pca = PCA(n_components=2)
# 加载PCA算法，指定n_components的值为2，即降维为2维数据
reduced_X = pca.fit_transform(X)
# 传入数据，对数据进行降维，结果返回并保存
red_x, red_y = [], []
blue_x, blue_y = [], []
green_x, green_y = [], []
for i in range(len(reduced_X)):
if y[i] == 0:
red_x.append(reduced_X[i][0])
red_y.append(reduced_X[i][1])
elif y[i] == 1:
blue_x.append(reduced_X[i][0])
blue_y.append(reduced_X[i][1])
else:
green_x.append(reduced_X[i][0])
green_y.append(reduced_X[i][1])
# 将结果分为三类显示在图表中
plt.scatter(red_x, red_y, c='r', marker='x')
plt.scatter(blue_x, blue_y, c='b', marker='D')
plt.scatter(green_x, green_y, c='g', marker='.')
plt.show()
# 打印```

②NMF算法

NMF中文名称非负矩阵分解，是在矩阵中所有元素均为非负数的条件下的矩阵分解方法。基本的思想是给定一个非负矩阵V，找到一个非负矩阵W和一个非负矩阵H，使得两个矩阵的乘积近似等于矩阵V中的值。

```from numpy.random import RandomState
import matplotlib.pyplot as plt
# 用于数据的可视化
from sklearn.datasets import fetch_olivetti_faces
# 加载人脸数据集
from sklearn import decomposition
# 加载算法包
n_row, n_col = 2, 3
n_components = n_row * n_col
# 打印时的排布
image_shape = (64, 64)
# 图片分辨率
dataset = fetch_olivetti_faces(shuffle=True, random_state=RandomState(0))
# 加载数据
faces = dataset.data
# 提取出数据中的数值部分
def plot_gallery(title, images, n_col=n_col, n_row=n_row):
# 打印函数
plt.figure(figsize=(2. * n_col, 2.26 * n_row))
# 创建并设置好图片大小
plt.suptitle(title, size=16)
# 副标题设置
for i, comp in enumerate(images):
plt.subplot(n_row, n_col, i + 1)
# 将图片添加到对应的框中
vmax = max(comp.max(), -comp.min())
plt.imshow(comp.reshape(image_shape), cmap=plt.cm.gray,
interpolation='nearest', vmin=-vmax, vmax=vmax)
# 对数值进行归一化，并且以灰度形式显示
plt.xticks(())
plt.yticks(())
# 去除坐标轴
plt.subplots_adjust(0.01, 0.05, 0.99, 0.94, 0.04, 0.)
# 调整间隔位置
plot_gallery("First centered Olivetti faces", faces[:n_components])
# 打印原来的图像
estimators = [
('Eigenfaces - PCA using randomized SVD',
decomposition.PCA(n_components=6, whiten=True)),
# 调用PCA实例并打印
('Non-negative components - NMF',
decomposition.NMF(n_components=6, init='nndsvda', tol=5e-3))
# 调用NMF实例并打印
]
for name, estimator in estimators:
print("Extracting the top %d %s..." % (n_components, name))
print(faces.shape)
estimator.fit(faces)
# 传入数据并进行特征提取
components_ = estimator.components_
# 得到返回结果
plot_gallery(name, components_[:n_components])
# 打印当次图像
plt.show()```

## 四、小实验：基于聚类的图像分割

```import numpy as np
import PIL.Image as image
from sklearn.cluster import KMeans
# 引入需要的库文件
f = open(filePath, 'rb')
# 打开文件
data = []
img = image.open(f)
# 以列表形式返回图片像素值
m, n = img.size
# 获得图片的大小

for i in range(m):
for j in range(n):
x, y, z = img.getpixel((i, j))
data.append([x / 256.0, y / 256.0, z / 256.0])
# 将每个像素的颜色值处理到0-1

f.close()
return np.mat(data), m, n
# 以矩阵形式返回处理的图像以及图片的大小
loc = 'C:\\Users\\Binary\\Pictures\\401.jpg'
# 选择一张照片
label = KMeans(n_clusters=4).fit_predict(imgData)
# 加载Kmeans算法并进行处理
label = label.reshape([row, col])
pic_new = image.new("L", (row, col))
# 创建一张新照片
for i in range(row):
for j in range(col):
pic_new.putpixel((i, j), int(256 / (label[i][j] + 1)))
# 向内部添加像素的值
filename = 'C:\\Users\\Binary\\Desktop\\'+loc.split('\\')[-1]
# 在桌面以原文件名保存
pic_new.save(filename, "JPEG")```