目录
线性判别介绍
线性判别分析(Linear Discriminant Analysis,LDA)是一种经典的统计学习方法,主要用于分类问题。它的原理基于贝叶斯决策理论,假设数据服从多元正态分布,并试图寻找一个能够最大化类间差异、同时最小化类内差异的线性投影方向,以实现对数据的分类。
LDA的发展
LDA的发展可以追溯到20世纪初,最早由英国统计学家R.A. Fisher提出,后来被广泛应用于生物统计学、医学图像分析、人脸识别等领域。除了作为分类器之外,LDA还可以用于降维,即将高维数据映射到低维空间中,从而减少特征数量,避免过拟合等问题。
LDA的原理
LDA的主要思想是在类别之间最大化类间距离、同时最小化类内距离。具体来说,给定n个样本数据集D={x1,x2,...,xn},其中xi=(xi1,xi2,...,xid)表示d维特征向量,对于每个类别ωi,我们可以计算其类别均值向量μi以及协方差矩阵Σi。
LDA的目标是找到一个线性变换W,将d维特征向量xi映射到k维空间中(k<<d),以使得数据在新空间中的类间距离最大化、类内距离最小化。具体来说,我们需要最大化类间距离的指标是样本均值向量之间的距离,最小化类内距离的指标是各个类别的协方差矩阵之和。
LDA的应用范围
LDA主要用途包括以下几个方面:
-
分类问题:LDA可以作为分类器来预测新样本的类别。它的优点在于对于高维数据,即使样本数量比特征数量还小,也能够较为准确地进行分类。
-
特征选择:通过计算LDA模型的投影方向,可以评估每个特征的重要性,从而进行特征选择或降维。这种方法通常被称为Fisher特征选择。
-
图像处理:LDA可以用于人脸识别、指纹识别等图像处理领域。通过对人脸图像进行LDA降维,可以将高维图像数据压缩到较低的维度,从而加快图像处理速度。
R语言 LDA实例
用LDA区分UCI Machine Learning Repository 中的小麦种子:
seed <- read.table("seeds_dataset.txt",sep = "",header = FALSE)
names(seed) <- c("x1","x2","x3","x4","x5","x6","x7","y")
seed$y <- factor(seed$y,levels=1:3)
str(seed)
将麦子数据集读入到变量
seed
中,并且设置数据的分隔符为默认值(空格)和表头行的存在状态为FALSE
。同时,将数据集的变量名从x1到x7分别对应不同的麦子属性,而最后一个变量y则表示麦子的品种。并且打印出数据集的结构。
数据结构如下:
str(wine)
'data.frame': 178 obs. of 14 variables:
$ Type : Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
$ Alcohol : num 14.2 13.2 13.2 14.4 13.2 ...
$ Malic : num 1.71 1.78 2.36 1.95 2.59 1.76 1.87 2.15 1.64 1.35 ...
$ Ash : num 2.43 2.14 2.67 2.5 2.87 2.45 2.45 2.61 2.17 2.27 ...
$ Alcalinity : num 15.6 11.2 18.6 16.8 21 15.2 14.6 17.6 14 16 ...
$ Magnesium : int 127 100 101 113 118 112 96 121 97 98 ...
$ Phenols : num 2.8 2.65 2.8 3.85 2.8 3.27 2.5 2.6 2.8 2.98 ...
$ Flavanoids : num 3.06 2.76 3.24 3.49 2.69 3.39 2.52 2.51 2.98 3.15 ...
$ Nonflavanoids : num 0.28 0.26 0.3 0.24 0.39 0.34 0.3 0.31 0.29 0.22 ...
$ Proanthocyanins: num 2.29 1.28 2.81 2.18 1.82 1.97 1.98 1.25 1.98 1.85 ...
$ Color : num 5.64 4.38 5.68 7.8 4.32 6.75 5.25 5.05 5.2 7.22 ...
$ Hue : num 1.04 1.05 1.03 0.86 1.04 1.05 1.02 1.06 1.08 1.01 ...
$ Dilution : num 3.92 3.4 3.17 3.45 2.93 2.85 3.58 3.58 2.85 3.55 ...
$ Proline : int 1065 1050 1185 1480 735 1450 1290 1295 1045 1045 ...
结果表明,这个数据框中包含178个样本和14个变量,其中有:
Type
:表示葡萄酒类型,是一个分类变量,有三个水平值(1, 2, 3)。
Alcohol
:表示酒精含量,是一个数值变量,以百分比表示。
……
等等。
set.seed(1)
train_index <- sample(210,140)
train_data <- seed[train_index,]
test_data <- seed[-train_index,]
library(MASS)
fit1 <- lda(y~.,data=train_data)
fit1
使用set.seed()函数是为了使随机数生成可重复,便于调试,即设置随机数种子。
sample()函数生成一个由样本序号构成的大小为140的训练集索引,train_data和test_data则分别是训练集和测试集的数据。
调用MASS库的lda()函数来对训练数据集进行LDA拟合,其中
y~.
表示使用除y以外的所有变量来拟合模型。
模型输出结果如下:
fit1
Call:
lda(y ~ ., data = train_data)
Prior probabilities of groups:
1 2 3
0.3071429 0.3000000 0.3928571
Group means:
x1 x2 x3 x4 x5 x6 x7
1 14.26930 14.29953 0.8756326 5.532930 3.219535 2.678191 5.102349
2 18.74405 16.28690 0.8868857 6.185405 3.739095 3.676714 6.042405
3 11.85800 13.24545 0.8485073 5.232891 2.850509 4.961364 5.120345
Coefficients of linear discriminants:
LD1 LD2
x1 1.1327015 4.0212482
x2 0.4316044 -8.0367795
x3 -23.3036592 -66.2269273
x4 -4.4228574 -6.9281534
x5 0.8566987 -1.0455113
x6 -0.1143737 0.3053494
x7 2.1791191 6.9749824
Proportion of trace:
LD1 LD2
0.7557 0.2443
模型结果解释如下:
- 模型使用y作为响应变量,其他变量(x1到x7)作为预测变量。
- "Prior probabilities of groups"给出了训练集中每个响应类别的先验概率。可以看出三种小麦种子得先验概率基本相等。
- "Group means"给出了每个响应类别中每个预测变量的均值。
- "Coefficients of linear discriminants"给出了线性判别函数的系数,以便将每个样本映射到LDA的第一和第二线性判别变量(LD1和LD2)上。这些系数可用于计算LDA分类器。
- "Proportion of trace"表示每个线性判别变量的解释方差量,也称为特征值。在本例中,LD1占总方差的75.57%,LD2占总方差的24.43%。也就是说第一线性判元几乎可以区分百分之七十五的数据,而第二线性判元只能解释百分之二十四的数据,因此应该选择第一线性判元,这个结论从下面的可视化图中可以明显。
plot(fit1,main="Linear Discriminant Analysis",col=as.numeric(train_data$y))
将LDA模型的拟合结果可视化,其中main参数是可视化图表的标题,col参数是为每个样本选择一个颜色,这里as.numeric(train_data$y)表示将y变量转换为数值型变量以便于设置颜色。
所得图形如下:
接下来对测试集进行预测:
pred_test <- predict(fit1,newdata=test_data)
names(pred_test)
table_test <- table(predict=pred_test$class,actual=test_data$y)
table_test
sum(diag(table_test))/sum(table_test )
利用训练好的LDA模型
fit1
对测试集进行预测,将预测结果存储在pred_test
中。predict()函数返回一个列表,包括分类预测和概率估计。其中,pred_test$class
是预测的类别结果。将预测结果和实际结果的混淆矩阵存储在table_test
中,然后计算准确率。
所得
names(pred_test)
[1] "class" "posterior" "x"
将预测结果存储在一个数据框中,数据框的列可以包括预测的分类、每个分类的后验概率和用于预测的原始数据。这样做可以方便后续的分析和可视化
table_test
actual
predict 1 2 3
1 25 2 1
2 1 26 0
3 1 0 14
所得的混淆矩阵如上所示可以看出分类的效果较好
准确率如下:
sum(diag(table_test))/sum(table_test )#Ԥ??ȷ??
[1] 0.9285714
接下来,进行二次判别分析:
fit2 <- qda(y~.,data=train_data)
fit2
使用qda对数据进行二次判别分析的建模,其中y~.表示因变量y与所有自变量之间的二次关系。训练数据使用train_data。
所得模型结果如下:
fit2
Call:
qda(y ~ ., data = train_data)
Prior probabilities of groups:
1 2 3
0.3071429 0.3000000 0.3928571
Group means:
x1 x2 x3 x4 x5 x6 x7
1 14.26930 14.29953 0.8756326 5.532930 3.219535 2.678191 5.102349
2 18.74405 16.28690 0.8868857 6.185405 3.739095 3.676714 6.042405
3 11.85800 13.24545 0.8485073 5.232891 2.850509 4.961364 5.120345
此运行结果可参照上述第一次运行结果。
qda_test <- predict(fit2,newdata=test_data)#Ԥ??
names(qda_test)
qda_test <- table(predict=qda_test$class,actual=test_data$y)#????????
qda_test
sum(diag(qda_test))/sum(qda_test )#Ԥ??ȷ??
预测测试数据的类别,并将预测结果与实际结果进行比较。计算模型的准确率。
所得结果如下:
names(pred_test)
[1] "class" "posterior" "x"
混淆矩阵展示如下:
qda_test
actual
predict 1 2 3
1 24 4 0
2 2 24 0
3 1 0 15
计算所得准确率如下:
sum(diag(qda_test))/sum(qda_test )#Ԥ??ȷ??
[1] 0.9
由上述两次判别分析的结果可以知道,模型效果较好,基本可以区分百分之九十的样本。