Iris is good|前言

待更

Dataset Exploratory|数据探查

读取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np
from sklearn import decomposition
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
# 导入鸢尾花数据(sklearn库自带)
from sklearn.datasets import load_iris

iris = load_iris() # 读取数据
icls = iris.target #保存类别标签
iris = pd.DataFrame(iris.data,
columns=[
'sepal_length',
'sepal_width',
'petal_length',
'petal_wifth']
)
Setosa = iris.loc[icls==0] #第一类鸢尾花
Versicolour = iris.loc[icls==1] #第二类鸢尾花
Virginica = iris.loc[icls==2] #第三类鸢尾花

协方差矩阵

1
2
3
4
5
6
7
8
9
10
11
print('总协方差矩阵:')
print(iris.cov()) #求取总协方差矩阵

print('Setosa类协方差矩阵:')
print(Setosa.cov())

print('Versicolour类协方差矩阵:')
print(Versicolour.cov())

print('Virginica类协方差矩阵:')
print(Virginica.cov())

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
总协方差矩阵:
sepal_length sepal_width petal_length petal_wifth
sepal_length 0.685694 -0.042434 1.274315 0.516271
sepal_width -0.042434 0.189979 -0.329656 -0.121639
petal_length 1.274315 -0.329656 3.116278 1.295609
petal_wifth 0.516271 -0.121639 1.295609 0.581006

Setosa类协方差矩阵:
sepal_length sepal_width petal_length petal_wifth
sepal_length 0.124249 0.099216 0.016355 0.010331
sepal_width 0.099216 0.143690 0.011698 0.009298
petal_length 0.016355 0.011698 0.030159 0.006069
petal_wifth 0.010331 0.009298 0.006069 0.011106

Versicolour类协方差矩阵:
sepal_length sepal_width petal_length petal_wifth
sepal_length 0.266433 0.085184 0.182898 0.055780
sepal_width 0.085184 0.098469 0.082653 0.041204
petal_length 0.182898 0.082653 0.220816 0.073102
petal_wifth 0.055780 0.041204 0.073102 0.039106

Virginica类协方差矩阵:
sepal_length sepal_width petal_length petal_wifth
sepal_length 0.404343 0.093763 0.303290 0.049094
sepal_width 0.093763 0.104004 0.071380 0.047629
petal_length 0.303290 0.071380 0.304588 0.048824
petal_wifth 0.049094 0.047629 0.048824 0.075433

公共协方差矩阵

根据公共协方差的定义,有:

S=iP^(Ci)Si\mathbf{S}=\sum_i \hat{P}(C_i)\mathbf{S}_i

其中,P^(Ci)=tritN\hat{P}(C_i)=\frac{\sum_tr_i^t}{N},如果第tt个样本xtCi\mathbf{x}^t\in C_i,则rit=1r_i^t=1,否则为00

于是,可以编程对共享协方差进行计算:

1
2
3
4
5
6
7
P0 = Setosa.shape[0]/iris.shape[0]
P1 = Versicolour.shape[0]/iris.shape[0]
P2 = Virginica.shape[0]/iris.shape[0]
# 事实上P0=P1=P2=1/3
publicCov = P0*Setosa.cov()+P1*Versicolour.cov()+P2*Virginica.cov()
print('共享协方差矩阵:')
print(publicCov)

输出结果:

1
2
3
4
5
6
共享协方差矩阵:
sepal_length sepal_width petal_length petal_wifth
sepal_length 0.265008 0.092721 0.167514 0.038401
sepal_width 0.092721 0.115388 0.055244 0.032710
petal_length 0.167514 0.055244 0.185188 0.042665
petal_wifth 0.038401 0.032710 0.042665 0.041882

相关系数矩阵

1
2
3
4
5
print('相关系数矩阵:')
print(iris.corr()) #求取皮尔逊相关系数矩阵

sns.heatmap(iris.corr(),annot=True,cmap='YlGnBu')
plt.show() #相关系数热力图显示

输出结果:

1
2
3
4
5
6
相关系数矩阵:
sepal_length sepal_width petal_length petal_wifth
sepal_length 1.000000 -0.117570 0.871754 0.817941
sepal_width -0.117570 1.000000 -0.428440 -0.366126
petal_length 0.871754 -0.428440 1.000000 0.962865
petal_wifth 0.817941 -0.366126 0.962865 1.000000

热力图:

iris-headmap

PCA|主成分分析

关于PCA的相关原理见本站文章:

通过numpy库自写实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 中心化/零均值化
def zeroMean(data):
newData = data - np.mean(data,axis=0)
return newData

def myPCA(data,n):
#数据中心化
newData = zeroMean(data)
#cov用于求协方差矩阵,参数rowvar = 0说明数据一行代表一个样本
covMat = np.cov(newData,rowvar=0)
#np.linalg.eig用于求矩阵的特征值和特征向量
eigVals, eigVects = np.linalg.eig(np.mat(covMat))
#对特征值从小到大排列
eigValIndice = np.argsort(eigVals)
#得到最大的n个特征值的下标
n_eigValIndice = eigValIndice[-1:-(n+1):-1]
#得到下标对应的特征向量
n_eigVects = eigVects[:, n_eigValIndice]
#低维特征空间的数据
lowDData = newData * n_eigVects
return np.array(lowDData)

sklearn库实现

1
2
3
4
5
6
# PCA对数据data降至n维
def PCA(data, n):
from sklearn.decomposition import PCA #引入PCA模块
pca = PCA(n_components=n) #设置最终维度n
pca_result = pca.fit_transform(data) #变换
return pca_result

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import numpy as np
from sklearn import decomposition
import matplotlib.pyplot as plt

# 导入鸢尾花数据(sklearn库自带)
from sklearn.datasets import load_iris

# PCA对数据data降至n维
def PCA(data, n):
from sklearn.decomposition import PCA #引入PCA模块
pca = PCA(n_components=n) #设置最终维度n
pca_result = pca.fit_transform(data) #变换
return pca_result

# 中心化/零均值化
def zeroMean(data):
meanVal = np.mean(data,axis=0)
newData = data - meanVal
return newData, meanVal

def myPCA(data,n):
#数据中心化
newData, meanVal = zeroMean(data)
#cov用于求协方差矩阵,参数rowvar = 0说明数据一行代表一个样本
covMat = np.cov(newData,rowvar=0)
#np.linalg.eig用于求矩阵的特征值和特征向量
eigVals, eigVects = np.linalg.eig(np.mat(covMat))
#对特征值从小到大排列
eigValIndice = np.argsort(eigVals)
#得到最大的n个特征值的下标
n_eigValIndice = eigValIndice[-1:-(n+1):-1]
#得到下标对应的特征向量
n_eigVects = eigVects[:, n_eigValIndice]
#低维特征空间的数据
lowDData = newData * n_eigVects
return np.array(lowDData)


# 可视化
def plot(target,pca_result):
plt.scatter(pca_result[target == 0, 0], pca_result[target == 0, 1], color='r')
plt.scatter(pca_result[target == 1, 0], pca_result[target == 1, 1], color='g')
plt.scatter(pca_result[target == 2, 0], pca_result[target == 2, 1], color='b')
plt.title('iris的PCA降维可视化')


if __name__ == '__main__':
iris = load_iris() # 读取数据
pca_result = PCA(iris.data,2) # 使用PCA进行降维
plt.figure()
plot(iris.target,pca_result) # 画图
plt.figure()
pca_result = myPCA(iris.data,2) # 使用PCA进行降维
plot(iris.target,pca_result) # 画图
plt.show() #显示图像

结果可视化

iris-PCA

Clustering|聚类

kmeans聚类

k=3k=3进行kmeans聚类,主函数如下:

1
2
3
4
5
6
7
if __name__ == '__main__':
iris = load_iris() #读取数据
estimator = KMeans(n_clusters=3) #取k=3
estimator.fit(iris.data) #对鸢尾花数据集(剔除已有标签)进行聚类
pred_target = estimator.labels_ #获取聚类标签
plot(pred_target,iris.data) #画图
plt.show()

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import numpy as np
import matplotlib.pyplot as plt
# 导入鸢尾花数据(sklearn库自带)
from sklearn.datasets import load_iris
# 从sklearn库中导入cluster中的kmeans
from sklearn.cluster import KMeans

# 可视化
def plot(target,pca_result,title):
plt.scatter(pca_result[target == 0, 0], pca_result[target == 0, 1], color='r')
plt.scatter(pca_result[target == 1, 0], pca_result[target == 1, 1], color='g')
plt.scatter(pca_result[target == 2, 0], pca_result[target == 2, 1], color='b')
plt.title(title)

if __name__ == '__main__':
iris = load_iris() #读取数据
estimator = KMeans(n_clusters=3) #取k=3
estimator.fit(iris.data) #对鸢尾花数据集(剔除已有标签)进行聚类
pred_target = estimator.labels_ #获取聚类标签
plt.figure()
plot(pred_target,iris.data,'iris的kmeans聚类可视化') #画图
plt.show()

结果可视化与比较

iris的kmeans聚类结果

在原代码的基础上,再绘制带标签的分类图像,并将二者进行比较,代码如下:

1
2
3
4
5
6
7
8
9
10
if __name__ == '__main__':
iris = load_iris() #读取数据
estimator = KMeans(n_clusters=3) #取k=3
estimator.fit(iris.data) #对鸢尾花数据集(剔除已有标签)进行聚类
pred_target = estimator.labels_ #获取聚类标签
plt.subplot(1,2,1)
plot(iris.target,iris.data,'iris原始标签分类可视化')
plt.subplot(1,2,2)
plot(pred_target,iris.data,'iris的kmeans聚类可视化')
plt.show()

聚类与标签对比

可见,图中红色和蓝色点聚类效果较好;但由于kmeanskmeans聚类算法中心点最近距离选取的思想,与原始数据相比,聚类后得到的图中,绿色的点明显多于实际绿色标签的点。

层次聚类

利用sklearn库中的AgglomerativeClustering()函数进行层次聚类。

分别取singallinksingal-linkk=2,3,4k=2,3,4 以及completelinkcomplete-linkk=2,3,4k=2,3,4进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import numpy as np
import matplotlib.pyplot as plt
# 导入鸢尾花数据(sklearn库自带)
from sklearn.datasets import load_iris
# 从sklearn库中导入cluster中的AgglomerativeClustering
from sklearn.cluster import AgglomerativeClustering

# 可视化
def plot(target,pca_result,title):
plt.scatter(pca_result[target == 0, 0], pca_result[target == 0, 1], color='r')
plt.scatter(pca_result[target == 1, 0], pca_result[target == 1, 1], color='g')
plt.scatter(pca_result[target == 2, 0], pca_result[target == 2, 1], color='b')
plt.scatter(pca_result[target == 3, 0], pca_result[target == 3, 1])
plt.title(title)

if __name__ == '__main__':
iris = load_iris() #读取数据
mode = ['ward' for i in range(3)] + ['complete' for i in range(3)]
Kset = [2,3,4,2,3,4]
for i in range(6):
estimator = AgglomerativeClustering(linkage=mode[i], n_clusters=Kset[i])
estimator.fit(iris.data)
plt.subplot(2,3,i+1)
plot(estimator.labels_,iris.data,f'{mode[i]}模式 {Kset[i]}分类')
plt.show()

Hierarchical聚类结果

SVM|支持向量机

为了便于可视化与比较,此处我们先利用前文的PCAPCA方法将数据降维成2D2-D,然后继续使用操作。

这里假定如下规则:

C={0.0001,软边缘10000,硬边缘C=\begin{cases} 0.0001 &,软边缘 \\ 10000 &,硬边缘 \\ \end{cases}

利用sklearn库中的SVC可以实现多种核的训练。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import numpy as np
from sklearn import svm #SVM包导入
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

# 导入鸢尾花数据(sklearn库自带)
from sklearn.datasets import load_iris
# 训练集分割
from sklearn.model_selection import train_test_split

# PCA对数据data降至n维
def PCA(data, n):
from sklearn.decomposition import PCA #引入PCA模块
pca = PCA(n_components=n) #设置最终维度n
pca_result = pca.fit_transform(data) #变换
return pca_result

# 可视化
def plot(target,pca_result,title):
plt.scatter(pca_result[target == 0, 0], pca_result[target == 0, 1], color='r')
plt.scatter(pca_result[target == 1, 0], pca_result[target == 1, 1], color='g')
plt.scatter(pca_result[target == 2, 0], pca_result[target == 2, 1], color='b')
plt.title(title)


if __name__ == '__main__':
iris = load_iris() #读取数据
pca_result = PCA(iris.data,2) # 使用PCA进行降维
X_train, X_test, y_train, y_test = train_test_split(pca_result, iris.target,
test_size=0.3, # 三七分割数据
random_state=0) #保持程序每次运行结果不变
# 线性核 RBF核 软边缘 硬边缘
lin_svc1 = svm.SVC(kernel='linear',C=0.0001).fit(X_train, y_train)
lin_svc2 = svm.SVC(kernel='linear',C=10000).fit(X_train, y_train)
lin_svc1 = svm.SVC(kernel='linear',C=0.0001).fit(X_train, y_train)
rbf_svc1 = svm.SVC(kernel='rbf',C=0.0001).fit(X_train, y_train)
rbf_svc2 = svm.SVC(kernel='rbf',C=10000).fit(X_train, y_train)
# 设置网格步长
h = .02
# 根据最值设置网格大小用于预测
x_min, x_max = X_train[:, 0].min() - 1, X_train[:, 0].max() + 1
y_min, y_max = X_train[:, 1].min() - 1, X_train[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))

# 图像标题
titles = ['Linear and C=0.0001','Linear and C=10000',
'RBF and C=0.0001','RBF and C=10000']

# 循环 依次绘制出不同训练的结果
for i, clf in enumerate(( lin_svc1, lin_svc2,rbf_svc1,rbf_svc2)):
# 计算预测值
xy = np.c_[xx.ravel(),yy.ravel()]
Z = clf.predict(xy)
Z = Z.reshape(xx.shape)
# 绘制结果图
plt.subplot(2, 2, i + 1)
# 边界
# plt.pcolormesh(xx, yy, Z, cmap=plt.cm.Paired)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.5)
plt.contour(xx,yy,Z,colors=['k','k','k'],levels=[-125,0,125],linestyles=['--','-','--'])
# 真实散点图
plt.scatter(pca_result[:, 0], pca_result[:, 1], c=iris.target, cmap=plt.cm.Paired)
# 支持向量
plt.scatter(clf.support_vectors_[:,0],clf.support_vectors_[:,1], s=80,facecolors='none', edgecolors='k')
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.xticks(())
plt.yticks(())
plt.title(titles[i])

plt.show()

SVM结果对比可视化

由图可知,在数据分布不具备明显的线性可分情况下,RBF核的效果优于线性核。此外,当惩罚因子过小时,对边界的限制会相应降低,从而导致允许更多的支持向量被划入边界内,导致分类效果不佳。甚至当惩罚因子CC小到一定程度时,所有点都将包含。

Reference|参考

  1. 鸢尾花(iris)数据集
  2. Iris Dataset - Exploratory Data Analysis|Kaggle
  3. 玩转鸢尾花iris数据集|bilibili
  4. 主成分分析(PCA)算法实现iris数据集降维
  5. 利用python内置K-Means聚类算法实现鸢尾花数据的聚类
  6. Plot different SVM classifiers in the iris dataset¶
  7. sklearn对iris数据集进行分类