当有一组预测变量需要被分为两个类,一般使用逻辑回归模型。举例,使用信用分和平均存款余额预测贷款是否违约。但当预测变量有多种可能时,则一般会使用线性判别分析(linear discriminant analysis, 简称 LDA).

线性判别分析

线性判别分析的场景举例:
给定高校篮球运动员的场均篮板和得分,预测他们会被三个高校中的一个录取。虽然LDA和逻辑回归模型都可以进行分类。实践表明,在对多个类进行预测时,LDA比逻辑回归要稳定得多,因此当响应变量有两个以上类别时,LDA是首选的算法。与逻辑回归相比,当样本量较小时LDA的表现也更好,这让它成为无法收集大样本时的首选方法。

构建LDA模型

线性判别算法对数据有一些要求:

  • 响应变量必须是类别变量。线性判别是分类算法,因此响应变量应该是类别变量。

  • 预测变量应遵循正太分布。首先检查每个预测变量是否大致符合正太分布,如果不满足,需要选择转换算法使其近似满足。

  • 每个预测变量有相同的标准差。现实中很难能够满足该条件,但我们可以对数据进行标准化,让变量统一为标准差为1,均值为0.

  • 检查异常值。在用于LDA之前要检查异常值。可以简单通过箱线图或散点图查进行检测。

一旦这些假设满足,LDA会估计下面值:

μ k {μ_k} μk: 第 k t h {k^{th}} kth类所有训练集的均值.

σ 2 {σ^2} σ2: 第k类样本方差的加权平均值.

π k {π_k} πk: 属于第k类的训练观察值的比例.

然后LDA将这些数字代入以下公式,并将每个观测值X = X分配给公式产生最大值的类:

D k ( x ) = x ∗ ( μ k / σ 2 ) – ( μ k 2 / 2 σ 2 ) + l o g ( π k ) {D_k(x) = x * (μ_k/σ^2) – (μ_k^2/2σ^2) + log(π_k)} Dk(x)=x(μk/σ2)(μk2/2σ2)+log(πk)

注意,LDA的名称中有线性,因为上面函数产生的值来自x的线性函数的结果。

LDA应用场景

LDA模型在现实中应用广泛,下面简单举例:

市场营销
零售公司经常使用LDA将购物者分为几类。然后利用建立LDA模型来预测特定购物者是低消费者、中等消费者还是高消费者,使用预测变量如收入、年度总消费额和家庭人数等变量。

医学领域
医院或医疗机构的研究人员通常利用LDA预测给定一组异常细胞是否会导致轻微、中度或严重疾病。

产品研发
一些公司会利用LDA模型预测消费者属于每天、每周、每月或年使用他们的产品,基于预测变量有性别、年度收入、使用类似产品的频率。

生态领域
研究者利用LDA模型预测是否给定珊瑚礁的健康状况:好、中等、坏、严重。预测变量包括大小、年度污染情况、年份。

示例

下面分步实现LDA,首先加载必要的包。

加载工具包

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn import datasets
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.model_selection import cross_val_score

加载数据

本实例使用iris数据集,下面代码展示如何加载数据,并转为DataFrame:

# load iris dataset
iris = datasets.load_iris()

# convert dataset to pandas DataFrame
df = pd.DataFrame(data=np.c_[iris['data'], iris['target']],
                  columns=iris['feature_names'] + ['target'])
df['species'] = pd.Categorical.from_codes(iris.target, iris.target_names)
df.columns = ['s_length', 's_width', 'p_length', 'p_width', 'target', 'species']

# view first six rows of DataFrame
print(df.head())

print(len(df.index))

输出结果:

#    s_length  s_width  p_length  p_width  target species
# 0       5.1      3.5       1.4      0.2     0.0  setosa
# 1       4.9      3.0       1.4      0.2     0.0  setosa
# 2       4.7      3.2       1.3      0.2     0.0  setosa
# 3       4.6      3.1       1.5      0.2     0.0  setosa
# 4       5.0      3.6       1.4      0.2     0.0  setosa

# 150 

我们看到包括150条观测记录,下面构建LDA预测属于那个分类。

预测变量为:

Sepal length
Sepal width
Petal length
Petal width

结果分类包括:

setosa
versicolor
virginica

拟合模型

使用LinearDiscriminantAnalysis 函数拟合模型:

# define predictor and response variables
x = df[['s_length', 's_width', 'p_length', 'p_width']]
y = df['species']

# Fit the LDA model
model = LinearDiscriminantAnalysis()
model.fit(x.values, y.values)

使用模型进行预测

我们已经拟合了模型,为了评估模型,使用k折分组教程验证. 使用10个分组,重复3次:

# Define method to evaluate model
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)

# evaluate model
scores = cross_val_score(model, x, y, scoring='accuracy', cv=cv, n_jobs=-1)
print(np.mean(scores))

# 0.9800000000000001

模型平均准确率为:98%。 下面使用测试数据进行预测:

# define new observation
new = [5, 3, 1, .4]

# predict which class the new observation belongs to
model.predict([new])

# array([0]) 即第一类:setosa

可视化结果

最后使用LDA图查看线性判别结果:

# define data to plot
x = iris.data
y = iris.target
model = LinearDiscriminantAnalysis()
data_plot = model.fit(x, y).transform(x)
target_names = iris.target_names

# create LDA plot
plt.figure()
colors = ['red', 'green', 'blue']
lw = 2
for color, i, target_name in zip(colors, [0, 1, 2], target_names):
    plt.scatter(data_plot[y == i, 0], data_plot[y == i, 1], alpha=.8, color=color,
                label=target_name)

# add legend to plot
plt.legend(loc='best', shadow=False, scatterpoints=1)

# display LDA plot
plt.show()

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐