大家好,判别分析是多元分析中用于判别样本所属类型的一种统计分析方法,即在已知研究对象用某种方法已经分成若干类的情况下,确定新的样本属于哪一类,今天来讲一下判别分析。
一、距离判别
距离判别的基本思想是按就近原则进行归类。首先根据已知分类的数据分别计算各类的中心,即各类的均值,若任一新样本的观测值都与第i类的中心距离最近,就认为它属于第i类。
用统计语言表述:已知总体G1,G2,…,Gk,先从每个总体中分别抽取n1,n2,…,nk个样本,每个样本皆测量p个指标,对新样本x=(x1,x2,…,xp)计算x到G1,G2,…,Gk的距离,记为d(x,G1),d(x,G2),…,d(x,Gn),然后按距离最近准则判别归类。
使用scikit-learn库中的KNeighborsClassifier类可以实现距离判别,其语法格式如下:
sklearn.neighbors.KNeightborsClassifer(n_neighbors=5,
weights='uniform',algorithm='auto',leaf_size=30,p=2,
metric='minkowski',metric_params=None,n_jors=1,**kwarge)
# n_neighbors:接受int,表示指定K值。默认为s
# weights:接受特定str,表示指定计算的算法。
取值为ball_tree时,表示使用BallTree算法;
取值为kd_tree时,表示使用KDTree算法;
取值为brute时,表示使用暴力搜索法;
取值为auto时,表示自动决定最适合的算法。默认为minkowski
# leaf_size:接受int,表示指定BallTree或者KDTree叶节点规值。默认为30
# metric:接受特定str,表示指定距离度量默认为minkowski。
# p:接受int,表示指定在minkowski度量上的指数。
如果p=1,则对应曼哈顿距离;如果p=2,则对应欧式距离。默认为2
实例:使用scikit-learn库自带的iris数据集,根据距离判别准则,对该数据集进行分类。
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
np.random.seed(1000) # 设置随机种子
iris = datasets.load_iris() # 导入鸢尾花的数据集
# 导入150个样本数据,每个样本4个属性分别为花瓣和花萼的长、宽
iris_x = iris.data
# 导入150个样本数据的标签
iris_y = iris.target
# 产生一个随机打乱的0-149的一维数组
indices = np.random.permutation(len(iris_x))
# 随机选取140个样本作为训练数据集
iris_x_train = iris_x[indices[:-10]]
# 选取这140个样本的标签作为训练数据集的标签
iris_y_train = iris_y[indices[:-10]]
# 剩下的10个样本作为测试数据集
iris_x_test = iris_x[indices[-10:]]
# 把剩下10个样本对应标签作为测试数据集的标签
iris_y_test = iris_y[indices[-10:]]
# 定义一个距离判别分类器对象
knn = KNeighborsClassifier()
# 调用该对象的训练方法,主要接收两个参数:训练数据集及其样本标签
knn.fit(iris_x_train, iris_y_train)
# 调用该对象的测试方法,主要接收一个参数:测试数据集
iris_y_predict = knn.predict(iris_x_test)
# 输出测试数据集的预测标签
print('测试数据集的预测标签为:\n ',
iris.target_names[iris_y_predict])
# 输出测试数据集的正确标签,以方便对比
print('测试数据集的正确标签为:\n ',
iris.target_names[iris_y_test])
# 调用该对象的打分方法,计算出准确率
score = knn.score(iris_x_test,iris_y_test,sample_weight=None)
print('准确率为:',score) # 输出准确率计算结果
输出结果:
测试数据集的预测标签为:
['virginica' 'setosa' 'setosa' 'versicolor' 'virginica' 'setosa'
'versicolor' 'versicolor' 'versicolor' 'versicolor']
测试数据集的正确标签为:
['virginica' 'setosa' 'setosa' 'versicolor' 'virginica' 'setosa'
'versicolor' 'versicolor' 'versicolor' 'versicolor']
准确率为:1.0
二、贝叶斯判别
距离判别准则虽然简单,便于使用,但是也有它明显的不足之处:
一是距离判别准则与各总体出现的机会大小(先验概率)完全无关;
二是距离判别准则没有考虑错判造成的损失,这是不合理的。贝叶斯判别准则正是为了解决这两方面的问题而提出的。
使用scikit-learn库中的MultinomialNB类可以实现贝叶斯判别,其语法格式如下:
class sklearn.naive_bayes.MultinomiaINB(alpha=1.0,fit_prior=True,
class_prior=None)
# alpha:接受float,表示指定o值。默认为1
# class_prior:接受array,表示指定每个分类的先验概率。如果指定了该参数,
则每个分类的先验概率不再从数据集中学得。默认为None
继续上面的实例,使用scikit-learn库自带的iris数据集,根据贝叶斯判别准则,对该数据集进行分类。
from sklearn import datasets
from sklearn.naive_bayes import MultinomialNB
import numpy as np
np.random.seed(1000) # 设置随机种子
iris = datasets.load_iris() # 导入鸢尾花的数据集
# 导入150个样本数据,每个样本4个属性分别为花瓣和花萼的长、宽
iris_x = iris.data
iris_y = iris.target # 导入150个样本数据的标签
indices = np.random.permutation(len(iris_x)) # 产生一个随机打乱的0-149的一维数组
iris_x_train = iris_x[indices[:-10]] # 随机选取140个样本作为训练数据集
iris_y_train = iris_y[indices[:-10]] # 选取这140个样本的标签作为训练数据集的标签
iris_x_test = iris_x[indices[-10:]] # 剩下的10个样本作为测试数据集
iris_y_test = iris_y[indices[-10:]] # 把剩下10个样本对应标签作为测试数据集的标签
bayes = MultinomialNB() # 定义一个贝叶斯判别分类器对象
# 调用该对象的训练方法,主要接收两个参数:训练数据集及其样本标签
bayes.fit(iris_x_train, iris_y_train)
# 调用该对象的测试方法,主要接收一个参数:测试数据集
iris_y_predict = bayes.predict(iris_x_test)
# 输出测试数据集的预测标签
print('测试数据集的预测标签为:\n ', iris.target_names[iris_y_predict])
# 输出测试数据集的正确标签,以方便对比
print("测试数据集的正确标签为:\n", iris.target_names[iris_y_test])
# 调用该对象的打分方法,计算出准确率
score = bayes.score(iris_x_test,iris_y_test,sample_weight=None)
print("准确率为:",score) # 输出准确率计算结果
输出结果:
测试数据集的预测标签为:
['virginica' 'setosa' 'setosa' 'virginica' 'virginica' 'setosa'
'versicolor' 'versicolor' 'versicolor' 'virginica']
测试数据集的正确标签为:
['virginica' 'setosa' 'setosa' 'versicolor' 'virginica' 'setosa'
'versicolor' 'versicolor' 'versicolor' 'versicolor']
准确率为:0.8
三、 费希尔判别
费希尔判别准则也称为LDA判别准则,其基本思想是降维:用p维向量x=(x1,x2,…,xp)T的少数几个线性组合y1=a1Tx,y2=a2Tx,…,yr=arTx,(一般r明显小于p)来代替原始的p个向量x1,x2,…,xp,并根据这r个判别函数y1,y2,…,yr对样本的归属做出判别或将各组分离。在确定需使用的r个判别函数y1,y2,…,yr之后,可制定相应的判别规则。依据(y1,y2,…,yr)值,判别新样本归属于离它最近的那一组。
使用scikit-learn库中的LinearDiscriminantAnalysis类可以实现费希尔判别,其语法格式如下:
class sklearn.discriminant_analysis.LinearDiscriminantAnalysis
(solve='svd',shrinkage=None,priors=None,n_components=None,
store_covariance=False,tol=0.0001)
# solve:接受特定的str,指定求解的算法。取值为svd时,表示奇异值分解;
取值为lsqr时,表示最小平方差算法;取值为eigen时,表示特征值分解算法。默认为svd
# shinkage:接受auto或者float,该参数通常在训练样本数量小于特征数量的场合下使用
该参数只有在solve=lsqr或eigen时才有意义。
接收auto时,表示自动决定该参数大小;
接收float时,表示指定该参数大小;
接收None时,表示不使用该参数;默认为None
# priors:接受array,表示数组中的元素依次指定了每个类别的先验概率
如果为None,则默认为每个类的先验概率相等。默认为None
# n_components:接受int,指定数据降维后的维度。默认为None
# store_covariance:接受boor,表示是否计算每个类别的协方差矩阵。默认为False
实例:使用scikit-learn库自带的iris数据集,根据费希尔判别准则,对该数据集进行分类。
from sklearn import datasets
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
import numpy as np
np.random.seed(1000) # 设置随机种子
iris = datasets.load_iris() # 导入鸢尾花的数据集
# 导入150个样本数据,每个样本4个属性分别为花瓣和花萼的长、宽
iris_x = iris.data
iris_y = iris.target # 导入150个样本数据的标签
indices = np.random.permutation(len(iris_x)) # 产生一个随机打乱的0-149的一维数组
iris_x_train = iris_x[indices[:-10]] # 随机选取140个样本作为训练数据集
iris_y_train = iris_y[indices[:-10]] # 选取这140个样本的标签作为训练数据集的标签
iris_x_test = iris_x[indices[-10:]] # 剩下的10个样本作为测试数据集
iris_y_test = iris_y[indices[-10:]] # 把剩下10个样本对应标签作为测试数据集的标签
fisher = LinearDiscriminantAnalysis() # 定义一个费希尔判别分类器对象
# 调用该对象的训练方法,主要接收两个参数:训练数据集及其样本标签
fisher.fit(iris_x_train, iris_y_train)
# 调用该对象的测试方法,主要接收一个参数:测试数据集
iris_y_predict = fisher.predict(iris_x_test)
# 输出测试数据集的预测标签
print('测试数据集的预测标签为:\n ', iris.target_names[iris_y_predict])
# 输出测试数据集的正确标签,以方便对比
print('测试数据集的正确标签为:\n ', iris.target_names[iris_y_test])
# 调用该对象的打分方法,计算出准确率
score = fisher.score(iris_x_test,iris_y_test,sample_weight=None)
print('准确率为:',score) # 输出准确率计算结果
输出结果:
测试数据集的预测标签为:
['virginica' 'setosa' 'setosa' 'versicolor' 'virginica' 'setosa'
'versicolor' 'versicolor' 'versicolor' 'versicolor']
测试数据集的正确标签为:
['virginica' 'setosa' 'setosa' 'versicolor' 'virginica' 'setosa'
'versicolor' 'versicolor' 'versicolor' 'versicolor']
准确率为:1.0