29. 多元分析
定义
多元分析是多变量的统计分析方法,是数理统计中应用广泛的一个重要分支。
判别分析
判别分析是一种分类方法。假定有
类判别对象 ,每一类 由 个指标的 个样本确定,即 其中 矩阵的第 行是 的第 个样本点的观测值向量。
记 , 分别表示 的均值向量和离差矩阵,即
对待判定对象 ,有一个一般规则,可以依据
的值,对 属于
的哪一类作出判别,称判别规则,其函数称判别函数,记 。
距离判别法
根据距离最近原则判别。 若 则 。
距离
一般用马氏距离,
个总体协方差矩阵相等时
不等时
Fisher 判别法
Fisher
判别法的思想是,将样例投影到一条或多条直线上,使同类样例的投影点尽可能接近,不同类样例的投影点尽可能远离。
对于二分类情况,若给定直线 ,则第 类样本的中心在直线上的投影为 。
第 类中第 个样本的组内偏差为 ,故第 类的组内偏差之和为
去掉 得 即离差矩阵。
所有类的组内偏差总和即为 要使同类样例的投影点尽可能接近,只需使 最小化。
而组间偏差同理有 要使不同类样例的投影点尽可能远离,只需使 最大化。
于是构造代价函数 使得 最大,也就等价于
根据拉格朗日乘子法,即 则 得 ,即
为矩阵 的特征向量。于是
于是有直线 ,和
垂直的两类的中心线可作为两类的判别直线。
即有阈值 ,比较
与 的大小,得出分类。
对于多分类情况,则有
之后求解 的闭式解为 的
个最大广义特征值所对应的特征向量组成的矩阵。
主成分分析
主成分分析,是利用降维把多指标转化为几个综合指标的多元统计分析方法。
设 表示以
为样本观测值的随机变量,如果能找到 ,使得方差 最大,就表明这
个变量的最大差异。
一般说来,代表原来
个变量的主成分不止一个,但不同主成分的信息不能相互包含,即协方差为
0,在几何上即方向正交。
设 表示第 个主成分 其中 ,
使
最大,
使
并使 最大,
使
并使 最大,
……
为实现上述目标,步骤如下:
假设有 个对象, 个指标 ,设第 个对象的第 个指标为 ,对原来的 个指标进行标准化 其中 得标准化的数据矩阵 ,记标准化后的指标为 ;
求相关系数矩阵 ,
计算相关系数矩阵 的特征值
及对应的标准正交化特征向量 ,其中 ,组成 个新的指标变量
计算主成分贡献率 累计贡献率
因子分析
因子分析将原始变量分解为若干个因子的线性组合
是 的期望变量, 称公共因子向量,
称特殊因子向量, 称因子载荷矩阵,
是变量 在公共因子 上的载荷,反映 对 的重要程度。
通常假设
互不相关且具有单位方差, 互不相关且与 互不相关, 为对角阵,于是有
每个原始变量
的方差都可以分解成共性方差
和特殊方差 之和,其中
反映全部公共因子对
的方差贡献,
反映特殊因子的方差贡献。
令 ,则 是公共因子 对 总方差的贡献,称
为 的贡献率。
利用主成分分析法求因子载荷矩阵,设
为相关系数矩阵 的特征值,
为对应的正交特征向量, ,则
特殊因子的方差用
的对角元估计,即 一般来说,理想的载荷结构是,每一列或每一行各载荷平方接近 0 或
1,需要对因子载荷矩阵进行旋转。
选取方差最大的正交旋转矩阵 ,使得因子上的载荷尽量拉开距离,从而使其接近
0 或 1
聚类分析
聚类分析,就是指将相似元素聚为一类。
层次聚类
基本思想:距离相近的样品先聚为一类,距离远的后聚成类,步骤如:
将每个样品独自聚成一类,构造
个类;
根据选定的距离公式,计算样品两两间距离,构造距离矩阵;
把距离最近的两类归为一类,聚成 类;
计算新类与当前各类的距离,再选距离最近的两类归为一类,聚成 类;
按步骤 4 重复迭代,直到所有样品聚为一类。
类和类之间的距离有各种定义,如最短距离法,对于类 ,有 除此之外,还有最长距离法、中间距离法等。
K 均值聚类
动态聚类法的思想是先粗略分一下类,然后按某种最优原则进行修正,直到类分得较合理为止,K
均值法是动态聚类的一种方法。
假定样本可分为 ,并选定
个初始聚类中心,然后根据最小距离原则将每个样本分配到某一类中,之后计算新的聚类中心,并调整聚类情况,直到收敛。
步骤如下:
将样本集任意划分为 类,记
,计算聚类中心
, 其中 为当前 类中的样本数,以及计算误差平方和
再令 ,按最小距离原则重新聚类,并重新计算聚类中心;
若连续两次迭代
不变,算法终止,否则转步骤 2。
最佳簇数 k 的确定
方法有簇内离差平方和拐点法和轮廓系数法。
计算不同
值下计算簇内离差平方和,然后画图找到拐点。当斜率由大突然变小,且之后斜率变化缓慢,则认为突然变换的点就是寻找的目标点。 再增加聚类效果不再有大的变化。
思想为使簇内样本密集,簇间样本分散。
对于每个样本点 有:
簇内不相似度 :样本点 与其所在簇内其他样本的平均距离;
簇间不相似度 :样本点 与其他簇样本的平均距离的最小值。
于是有样本点 的轮廓系数 总轮廓系数为所有样本点轮廓系数的平均值。
总轮廓系数小于 0 说明聚类效果不佳;接近 1
说明簇内样本平均距离非常小,簇间最近距离非常大,聚类效果非常理想。
Python 代码
距离判别法
蠓虫分为 Af 和 Apf,测得 Af、Apf 的触角长度和翅膀长度数据。
Af: , , , , ;
Apf: , , , , ;
试判别
属于哪一类,代码如下:
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 import numpy as npfrom sklearn.neighbors import KNeighborsClassifierx0 = np.array([[1.24 , 1.27 ], [1.36 , 1.74 ], [1.38 , 1.64 ], [1.38 , 1.82 ], [1.38 , 1.90 ], [1.14 , 1.78 ], [1.18 , 1.96 ], [1.20 , 1.86 ], [1.26 , 2.00 ], [1.28 , 2.00 ]]) label = np.array([1 for i in range (5 )] + [2 for i in range (5 )]) x = np.array([[1.24 , 1.80 ]]) import matplotlib.pyplot as pltplt.scatter(x0[:5 ,0 ], x0[:5 ,1 ],label='Af' ) plt.scatter(x0[5 :,0 ], x0[5 :,1 ],label='Apf' ) plt.scatter(x[0 ][0 ],x[0 ][1 ], label='Unknown' ) plt.legend() v = np.cov(x0.T) knn = KNeighborsClassifier(2 , metric='mahalanobis' , metric_params={'V' : v}) knn.fit(x0, label) knn.predict(x)
输出如下:
从图中大致可以看出未知样本接近 Apf 类,而计算结果为 2,即 Apf
类,与直觉相吻合。
Fisher 判别法
对上例使用 Fisher 判别法求解,代码如下:
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 import numpy as npfrom sklearn.discriminant_analysis import LinearDiscriminantAnalysisx0 = np.array([[1.24 , 1.27 ], [1.36 , 1.74 ], [1.38 , 1.64 ], [1.38 , 1.82 ], [1.38 , 1.90 ], [1.14 , 1.78 ], [1.18 , 1.96 ], [1.20 , 1.86 ], [1.26 , 2.00 ], [1.28 , 2.00 ]]) label = np.array([1 for i in range (5 )] + [2 for i in range (5 )]) x = np.array([[1.24 , 1.80 ]]) v = np.cov(x0.T) model = LinearDiscriminantAnalysis() model.fit(x0, label) model.predict(x)
输出如下:
结果与距离判别法一致。
主成分分析
对下列数据进行主成分分析
1
149.5
69.5
38.5
2
162.5
77.0
55.5
3
162.7
78.5
50.8
4
162.2
87.5
65.5
5
156.5
74.5
49.0
代码如下:
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 import numpy as npimport pandas as pdfrom sklearn.decomposition import PCAdf = pd.DataFrame({ 'x1' : [149.5 , 162.5 , 162.7 , 162.2 , 156.5 ], 'x2' : [69.5 , 77 , 78.5 , 87.5 , 74.5 ], 'x3' : [38.5 , 55.5 , 50.8 , 65.5 , 49 ] }) model = PCA().fit(np.array(df)) print ('特征值:' , model.explained_variance_)print ('贡献率:' , model.explained_variance_ratio_)print ('各主成分的系数:' , model.components_)pca_df = pd.DataFrame(model.transform(np.array(df))) pca_df.columns = ['F1' , 'F2' , 'F3' ] pca_df
输出如下:
1 2 3 4 5 特征值: [161.47423448 9.60080441 2.28996111 ] 贡献率: [0.93141196 0.05537914 0.0132089 ] 各主成分的系数: [[-0.39412803 -0.5037512 -0.76869878 ] [-0.90779807 0.34389304 0.24008381 ] [ 0.14340765 0.79244703 -0.59284226 ]]
0
17.867546
2.409312
0.343559
1
-4.102132
-2.731441
-1.927107
2
-1.323700
-3.525555
2.076603
3
-16.960269
3.552614
0.422142
4
4.518556
0.295070
-0.915196
层次聚类
对下列 7 种岩石聚类
Cu
2.9909
3.2044
2.8392
2.5315
2.5897
2.9600
3.1184
W
0.3111
0.5348
0.5696
0.4528
0.3010
3.0480
2.8395
Mo
0.5324
0.7718
0.7614
0.4893
0.2735
1.4997
1.9350
代码如下:
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 import numpy as npimport pandas as pdimport scipy.cluster.hierarchy as schdf = pd.DataFrame({ 'Cu' : [2.9909 ,3.2044 ,2.8392 ,2.5315 ,2.5897 ,2.9600 ,3.1184 ], 'W' :[.3111 ,.5348 ,.5696 ,.4528 ,.3010 ,3.0480 ,2.8395 ], 'Mo' : [.5324 ,.7718 ,.7614 ,.4893 ,.2735 ,1.4997 ,1.9350 ], }) dist = sch.distance.pdist(df) dist_mat = sch.distance.squareform(dist) z = sch.linkage(dist) sch.dendrogram(z)
输出如下:
K 均值聚类
对鸢尾花数据集进行 K 均值聚类
0
5.1
3.5
1
4.9
3.0
2
4.7
3.2
3
4.6
3.1
4
5.0
3.6
...
...
...
145
6.7
3.0
146
6.3
2.5
147
6.5
3.0
148
6.2
3.4
149
5.9
3.0
代码如下:
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 import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.datasets import load_irisfrom sklearn.cluster import KMeansfrom sklearn.metrics import silhouette_scoredf = pd.DataFrame(load_iris()['data' ], columns=load_iris()['feature_names' ]) score_list = [] for i in range (2 ,10 ): model = KMeans(i) model.fit(df.iloc[:,:2 ]) score_list.append(silhouette_score(df, model.labels_)) plt.plot([i for i in range (2 ,10 )], score_list) model = KMeans(3 ) model.fit(df.iloc[:,:2 ]) df2 = df.iloc[:,:2 ].copy() df2['label' ] = model.labels_ from plotnine import *( ggplot(df2,aes('sepal length (cm)' , 'sepal width (cm)' , color='label' )) + geom_point() + theme_matplotlib() )
输出如下:
可以看到,分 3 类是轮廓系数最大,聚类效果如图。