逻辑回归

概述

什么是逻辑回归

逻辑回归(Logistic Regression) 虽然被称为回归,但其实际上是分类模型,常用于二分类。逻辑回归因其简单、可并行化、可解释强而受到广泛应用。二分类(也称为逻辑分类)是常见的分类方法,是将一批样本或数据划分到两个类别,例如一次考试,根据成绩可以分为及格、不及格两个类别,如下表所示:

姓名 成绩 分类
Jerry 86 1
Tom 98 1
Lily 58 0
…… …… ……

这就是逻辑分类,将连续值映射到两个类别中。

逻辑函数

逻辑回归是一种广义的线性回归,其原理是利用线性模型根据输入计算输出(线性模型输出值为连续),并在逻辑函数作用下,将连续值转换为两个离散值(0或1),其表达式如下:

y=h(w1x1+w2x2+w3x3+...+wnxn+b)y = h(w_1x_1 + w_2x_2 + w_3x_3 + ... + w_nx_n + b)

其中,括号中的部分为线性模型,计算结果在函数h()h()的作用下,做二值化转换,函数h()h()的定义为:

h=11+eth= \frac{1}{1+e^{-t}}

t=wTx+b\quad t=w^Tx+b

该函数称为Sigmoid函数(又称逻辑函数),能将(,+)(-\infty, +\infty)的值映射到(0,1)(0, 1)之间,其图像为:

可以设定一个阈值(例如0.5),当函数的值大于阈值时,分类结果为1;当函数值小于阈值时,分类结果为0. 也可以根据实际情况调整这个阈值.

分类问题的损失函数

对于回归问题,可以使用均方差作为损失函数,对于分类问题,如何度量预测值与真实值之间的差异?分类问题采用交叉熵作为损失函数,当只有两个类别时,交叉熵表达式为:

E(y,y^)=[y log(y^)+(1y)log(1y^)]E(y, \hat{y}) = -[y \ log(\hat{y}) + (1-y)log(1-\hat{y})]

其中,y为真实值,y^\hat{y}为预测值.

  • y=1y=1时,预测值y^\hat{y}越接近于1,log(y^)log(\hat{y})越接近于0,损失函数值越小,表示误差越小,预测的越准确;当预测时y^\hat{y}接近于0时,log(y^)log(\hat{y})接近于负无穷大,加上符号后误差越大,表示越不准确;
  • y=0y=0时,预测值y^\hat{y}越接近于0,log(1y^)log(1-\hat{y})越接近于0,损失函数值越小,表示误差越小,预测越准确;当预测值y^\hat{y}接近于1时,log(1y^)log(1-\hat{y})接近于负无穷大,加上符号后误差越大,表示越不准确.

逻辑回归实现

sklearn中,逻辑回归相关API如下:

1
2
3
4
5
6
7
8
9
10
# 创建模型
# solver参数:逻辑函数中指数的函数关系(liblinear表示线性关系)
# C参数:正则强度,越大拟合效果越小,通过调整该参数防止过拟合
model = lm.LogisticRegression(solver='liblinear', C=1)

# 训练
model.fit(x, y)

# 预测
pred_y = model.predict(x)

以下是使用sklearn库提供的逻辑分类器(LogisticRegression)实现的代码:

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
# 逻辑分类器示例
import numpy as np
import sklearn.linear_model as lm
import matplotlib.pyplot as mp

x = np.array([[3, 1], [2, 5], [1, 8], [6, 4],
[5, 2], [3, 5], [4, 7], [4, -1]])
y = np.array([0, 1, 1, 0, 0, 1, 1, 0])

# 创建逻辑分类器对象
model = lm.LogisticRegression()
model.fit(x, y) # 训练

# 预测
test_x = np.array([[3, 9], [6, 1]])
test_y = model.predict(test_x) # 预测
print(test_y)

# 计算显示坐标的边界
left = x[:, 0].min() - 1
right = x[:, 0].max() + 1
buttom = x[:, 1].min() - 1
top = x[:, 1].max() + 1

# 产生网格化矩阵
grid_x, grid_y = np.meshgrid(np.arange(left, right, 0.01),
np.arange(buttom, top, 0.01))

print("grid_x.shape:", grid_x.shape)
print("grid_y.shape:", grid_y.shape)

# 将x,y坐标合并成两列
mesh_x = np.column_stack((grid_x.ravel(), grid_y.ravel()))
print("mesh_x.shape:", mesh_x.shape)

# 根据每个点的xy坐标进行预测,并还原成二维形状
mesh_z = model.predict(mesh_x)
mesh_z = mesh_z.reshape(grid_x.shape)

mp.figure('Logistic Regression', facecolor='lightgray')
mp.title('Logistic Regression', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x, grid_y, mesh_z, cmap='gray')
mp.scatter(x[:, 0], # 样本x坐标
x[:, 1], # 样本y坐标
c=y, cmap='brg', s=80)
mp.scatter(test_x[:, 0], test_x[:, 1], c="red", marker='s', s=80)
mp.show()

执行结果:

logi_regression_1

多分类实现

逻辑回归产生两个分类结果,可以通过多个二元分类器实现多元分类(一个多元分类问题转换为多个二元分类问题). 如有以下样本数据:

特征1 特征2 特征3 实际类别
x1x_1 x2x_2 x3x_3 A
x1x_1 x2x_2 x3x_3 B
x1x_1 x2x_2 x3x_3 C

进行以下多次分类,得到结果:

第一次:分为A类(值为1)和非A类(值为0)

第二次:分为B类(值为1)和非B类(值为0)

第三次:分为C类(值为1)和非C类(值为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
44
45
46
47
# 多元分类器示例
import numpy as np
import sklearn.linear_model as lm
import matplotlib.pyplot as mp

# 输入
x = np.array([[4, 7],
[3.5, 8],
[3.1, 6.2],
[0.5, 1],
[1, 2],
[1.2, 1.9],
[6, 2],
[5.7, 1.5],
[5.4, 2.2]])
# 输出(多个类别)
y = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2])

# 创建逻辑分类器对象
model = lm.LogisticRegression(C=200) # 调整该值为1看效果
model.fit(x, y) # 训练

# 坐标轴范围
left = x[:, 0].min() - 1
right = x[:, 0].max() + 1
h = 0.005

buttom = x[:, 1].min() - 1
top = x[:, 1].max() + 1
v = 0.005

grid_x, grid_y = np.meshgrid(np.arange(left, right, h),
np.arange(buttom, top, v))

mesh_x = np.column_stack((grid_x.ravel(), grid_y.ravel()))
mesh_z = model.predict(mesh_x)
mesh_z = mesh_z.reshape(grid_x.shape)

# 可视化
mp.figure('Logistic Classification', facecolor='lightgray')
mp.title('Logistic Classification', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x, grid_y, mesh_z, cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=y, cmap='brg', s=80)
mp.show()

执行结果:

logi_regression_2

总结

1)逻辑回归是分类问题,用于实现二分类问题

2)实现方式:利用线性模型计算,在逻辑函数作用下产生分类

3)多分类实现:可以将多分类问题转化为二分类问题实现

4)用途:广泛用于各种分类问题

决策树

什么是决策树

决策树是一种常见的机器学习方法,其核心思想是相同(或相似)的输入产生相同(或相似)的输出,通过树状结构来进行决策,其目的是通过对样本不同属性的判断决策,将具有相同属性的样本划分到一个叶子节点下,从而实现分类或回归. 以下是几个生活中关于决策树的示例.

【示例1】

decision_tree3

男生看女生与女生看男生的决策树模型
【示例2】

decision_tree4

挑选西瓜的决策树模型
在上述示例模型中,通过对西瓜一系列特征(色泽、根蒂、敲声等)的判断,最终我们得出结论:这是否为一个好瓜. 决策过程中提出的每个判定问题都是对某个属性的“测试”,例如“色泽=?”,“根蒂=?”. 每个测试的结果可能得到最终结论,也可能需要进行下一步判断,其考虑问题的范围是在上次决策结果限定范围之内. 例如若在“色泽=青绿”之后再判断“根蒂=?”.

决策树的结构

一般来说,一棵决策树包含一个根节点、若干个内部节点和若干个叶子节点. 叶子节点对应最终的决策结果,其它每个节点则对应与一个属性的测试. 最终划分到同一个叶子节点上的样本,具有相同的决策属性,可以对这些样本的值求平均值来实现回归,对这些样本进行投票(选取样本数量最多的类别)实现分类.

decision_tree_stucture

如何构建决策树

构建决策树算法

决策树的构建,就是不断选取好的特征作为决策节点,构建一颗泛化能力较强的树结构,其基本算法描述如下:

decision_tree5

显然,决策树的构建是一个递归的过程,核心是以下两个问题:

  • 如何选取特征. 决策树构建的每一步,应该挑选最优的特征,进行决策对数据集划分效果最好;
  • 决定何时停止分裂子节点.

如何选择特征

① 信息熵

信息熵(information entropy)是度量样本集合纯度的常用指标,该值越大,表示该集合纯度越低(或越混乱),该值越小,表示该集合纯度越高(或越有序). 信息熵定义如下:

H=i=1nP(xi)log2P(xi)H = -\sum_{i=1}^{n}{P(x_i)log_2P(x_i)}

其中,P(xi)P(x_i)表示集合中第i类样本所占比例,当P(xi)P(x_i)为1时(只有一个类别,比例为100%), log2P(xi)log_2P(x_i)的值为0,整个系统信息熵为0;当类别越多,则P(xi)P(x_i)的值越接近于0,log2P(xi)log_2P(x_i)趋近去负无穷大,整个系统信息熵就越大.以下代码,展示了类别数量从1…10的集合信息熵变化:

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
# 信息熵计算演示
import math
import numpy as np
import matplotlib.pyplot as mp

class_num = 10 # 类别最大数量


def entropy_calc(n):
p = 1.0 / n # 计算每个类别的概率
entropy_value = 0.0 # 信息熵

for i in range(n):
p_i = p * math.log(p)
entropy_value += p_i

return -entropy_value # 返回熵值


entropies = []
for i in range(1, class_num + 1):
entropy = entropy_calc(i) # 计算类别为i的熵值
entropies.append(entropy)

print(entropies)

# 可视化回归曲线
mp.figure('Entropy', facecolor='lightgray')
mp.title('Entropy', fontsize=20)
mp.xlabel('Class Num', fontsize=14)
mp.ylabel('Entropy', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle='-')
x = np.arange(0, 10, 1)
print(x)
mp.plot(x, entropies, c='orangered', label='entropy')

mp.legend()
mp.show()

执行结果:

decision_tree6

② 信息增益

决策树根据属性进行判断,将具有相同属性的样本划分到相同节点下,此时,样本比划分之前更加有序(混乱程度降低),信息熵的值有所降低。用划分前的信息熵减去划分后的信息熵,就是决策树获得的信息增益。可以用以下表达式表示:

Gain(D,a)=Ent(D)v=1VDvDEnt(Dv)Gain(D, a) = Ent(D) - \sum_{v=1}^{V} \frac{|D^v|}{|D|} Ent(D^v)

其中,D表示样本集合,a表示属性,v表示属性可能的取值v1,v2,...,vn{v^1, v^2,...,v^n}, DvD\frac{|D^v|}{|D|}表示权重,样本越多的分支对分类结果影响更大,赋予更高的权重, Gain(D,a)Gain(D, a)表示在样本集合D上使用属性a来划分子节点所获得的信息增益. 以下是一个关于信息增益计算的示例.

decision_tree7

说明:

  • 香蕉占2/5,所以P1=0.4P_1=0.4;梨占1/5,所以P2=0.2P_2 = 0.2;黄瓜占1/5,所以P3=0.4P_3 = 0.4
  • 根节点信息熵:(0.4log20.4+0.2log20.2+0.4log20.4)1.522-(0.4 * log_2 0.4 + 0.2 * log_2 0.2 + 0.4 * log_2 0.4) \approx 1.522
  • 根据颜色划分后:黄色分支信息熵(23log223+13log213)0.918-(\frac{2}{3} * log_2 \frac{2}{3} + \frac{1}{3} * log_2 \frac{1}{3}) \approx 0.918;绿色分支信息熵(1.0log21.0)=0-(1.0 * log_2 1.0) = 0;整个第二层信息熵为0.60.918+0.400.550.6 * 0.918 + 0.4 * 0 \approx 0.55
  • 根据颜色划分后的信息增益:1.5220.550.971.522 - 0.55 \approx 0.97

由以上示例可知,经过对样本按颜色进行类别划分,划分后的信息熵比原来下降了,下降的值就是信息增益。一般来说,信息增益越大,以该属性划分所获得的“纯度提升”越大. 著名的ID3决策树学习算法就是以信息增益为准则来划分属性.

③ 增益率

增益率不直接采用信息增益,而采用信息增益与熵值的比率来作为衡量特征优劣的标准. C4.5算法就是使用增益率作为标准来划分属性. 增益率定义为:

Gain_ratio(D,a)=Gain(D,a)IV(a)Gain\_ratio(D, a) = \frac{Gain(D, a)}{IV(a)}

其中

IV(a)=v=1VDvDlog2DvDIV(a) = - \sum_{v=1}^{V} \frac{|D^v|}{|D|} log_2 \frac{|D^v|}{|D|}

④ 基尼系数

基尼系数定义为:

Gini(p)=k=1kpk(1pk)=1k=1kpk2Gini(p) = \sum_{k=1}^{k} p_k (1-p_k) = 1 - \sum_{k=1}^{k} p_k^2

直观来说,基尼系数反映了从数据集D中随机抽取两个样本,类别标记不一致的概率. 因此,基尼系数越小,数据集的纯度越高. CART决策树(Classification And Regression Tree)使用基尼系数来选择划分属性,选择属性时,选择划分后基尼值最小的属性作为最优属性. 采用和上式相同的符号表示,数据集D下属性a的基尼系数定义为:

Gini_index(D,a)=v=1VDvDGini(Dv)Gini\_index(D, a) = \sum_{v=1}^{V} \frac{|D^v|}{|D|} Gini(D^v)

如何停止分裂

以下几种情况会停止决策树子节点的构建:

  • 当前节点所有样本属于同一个类别,无需划分
  • 当前属性集为空,或者所有样本取值相同,无法划分
  • 当前节点包含的样本集合为空,不能划分
  • 当前节点样本数量少于指定数量

如何实现决策树

scikit-learn中决策树相关API:

1
2
3
4
5
6
# 模型
model = st.DecisionTreeRegressor(max_depth=4) # 决策树回归器
# 训练
model.fit(train_x, train_y)
# 预测
pre_test_y = model.predict(test_x)

【案例】波士顿房价预测

  • 数据集介绍

    该数据集为一个开放房价数据集,包含506笔样本,每个样本包含13个特征和1个标签,具体如下所示:

boston_housing_features

  • 代码实现
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 sklearn.datasets as sd
import sklearn.utils as su
import sklearn.tree as st
import sklearn.ensemble as se
import sklearn.metrics as sm


boston = sd.load_boston() # 加载boston地区房价数据
print(boston.feature_names)
print(boston.data.shape)
print(boston.target.shape)

random_seed = 7 # 随机种子,计算随机值,相同的随机种子得到的随机值一样
x, y = su.shuffle(boston.data, boston.target, random_state = random_seed)
# 计算训练数据的数量
train_size = int(len(x) * 0.8) # 以boston.data中80%的数据作为训练数据
# 构建训练数据、测试数据
train_x = x[:train_size] # 训练输入, x前面80%的数据
test_x = x[train_size:] # 测试输入, x后面20%的数据
train_y = y[:train_size] # 训练输出
test_y = y[train_size:] # 测试输出

######## 单棵树进行预测 ########
# 模型
model = st.DecisionTreeRegressor(max_depth=4) # 决策回归器

# 训练
model.fit(train_x, train_y)
# 预测
pre_test_y = model.predict(test_x)
# 打印预测输出和实际输出的R2值
print(sm.r2_score(test_y, pre_test_y))
  • 执行结果
1
2
3
4
5
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
'B' 'LSTAT']
(506, 13)
(506,)
0.8202560889408634
  • 特征重要性

作为决策树模型训练过程中的副产品,根据每个特征划分子表前后信息熵减少量就标志了该特征的重要程度,此即为该特征重要性的指标。训练后得到的模型对象提供了属性feature_importances_来存储每个特征的重要性。在工程应用上,可以对决策树做一些优化,不必让每一个特征都参与子表划分,而只选择其中较重要的(或者说影响因素较大的)的特征作为子表划分依据。特征重要性的评价指标,就是根据该特征划分子表后所带来的信息熵减少量,熵减越大的就越重要,也就越优先参与子表的划分。

在上述示例中加入如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import matplotlib.pyplot as mp
import numpy as np
fi = model.feature_importances_ # 获取特征重要性
print("fi:", fi)

# 特征重要性可视化
mp.figure("Feature importances", facecolor="lightgray")
mp.plot()
mp.title("DT Feature", fontsize=16)
mp.ylabel("Feature importances", fontsize=14)
mp.grid(linestyle=":", axis=1)
x = np.arange(fi.size)
sorted_idx = fi.argsort()[::-1] # 重要性排序(倒序)
fi = fi[sorted_idx] # 根据排序索引重新排特征值
mp.xticks(x, boston.feature_names[sorted_idx])
mp.bar(x, fi, 0.4, color="dodgerblue", label="DT Feature importances")

mp.legend()
mp.tight_layout()
mp.show()

执行结果:

decision_tree8

决策树的剪枝

剪枝(pruning)是决策树学习算法对付“过拟合”的主要手段. 在决策树学习中,为了尽可能正确分类训练样本,节点划分过程将不断重复,有时会造成决策树分支过多,这时就可能因训练样本学的“太好了”,以至于把训练集本身的一些特点当做数据所具有的一般性质而导致过拟合. 因此,可通过主动去掉一些分支来降低过拟合风险.

(1)预剪枝. 决策树生成过程中,对每个节点在划分前进行评估,若当前节点不能带来决策树泛化性能的提升,则停止划分并将当前节点标记为叶子节点.

(2)后剪枝. 先训练为一颗完整的决策树,然后自低向上对非叶子节点进行考察,若将该节点对应的子树替换为叶节点能带来决策树泛化能力提升,则将该子树替换为叶节点.

集成学习与随机森林

集成学习

集成学习(ensemble learning)通过构建并合并多个模型来完成学习任务,从而获得比单一学习模型更显著优越的泛化性能,简言之,集成学习就是利用模型的“集体智慧”,提升预测的准确率. 根据单个模型方式,集成学习可以分为两大类:

  • 个体间存在强依赖关系,必须串行生成的序列化方法,其代表为Boosting算法;
  • 个体之间不存在强依赖关系,可同时生成的并行化方法,代表是Bagging和随机森林算法.

Boosting

什么是Boosting

Boosting(直译为推进、提升)是一族可以将弱学习器提升为强学习器的算法,其工作原理是:

  • 先训练出一个初始模型;
  • 根据模型的表现进行调整,使得模型预测错误的数据获得更多的关注,再重新训练下一个模型;
  • 不断重复第二步,直到模型数量达到预先设定的数目T,最终将这T个模型加权结合.

AdaBoosting是Boosting算法族中最著名的算法,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次训练得到的分类器最后融合起来,作为最后的决策分类器。

实现Boosting

sklearn中,AdaBoosting相关API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import sklearn.tree as st
import sklearn.ensemble as se

# model: 决策树模型(单个模型,基学习器)
model = st.DecisionTreeRegressor(max_depth=4)

# n_estimators:构建400棵不同权重的决策树,训练模型
model = se.AdaBoostRegressor(model, # 单模型
n_estimators=400, # 决策树数量
random_state=7)# 随机种子

# 训练模型
model.fit(train_x, train_y)

# 测试模型
pred_test_y = model.predict(test_x)

代码:

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
# AdaBoosting示例
# 使用AdaBoosting预测波士顿房价
import sklearn.datasets as sd
import sklearn.utils as su
import sklearn.tree as st
import sklearn.ensemble as se
import sklearn.metrics as sm

boston = sd.load_boston() # 加载boston地区房价数据
print(boston.feature_names)
print(boston.data.shape)
print(boston.target.shape)

random_seed = 7 # 随机种子,计算随机值,相同的随机种子得到的随机值一样
x, y = su.shuffle(boston.data, boston.target, random_state = random_seed)
# 计算训练数据的数量
train_size = int(len(x) * 0.8) # 以boston.data中80%的数据作为训练数据
# 构建训练数据、测试数据
train_x = x[:train_size] # 训练输入, x前面80%的数据
test_x = x[train_size:] # 测试输入, x后面20%的数据
train_y = y[:train_size] # 训练输出
test_y = y[train_size:] # 测试输出

model2 = se.AdaBoostRegressor(st.DecisionTreeRegressor(max_depth=4),
n_estimators=400, # 决策树数量
random_state=random_seed) # 随机种子
# 训练
model2.fit(train_x, train_y)
# 预测
pre_test_y2 = model2.predict(test_x)
# 打印预测输出和实际输出的R2值
print(sm.r2_score(test_y, pre_test_y2))

执行结果:

1
2
3
4
5
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
'B' 'LSTAT']
(506, 13)
(506,)
0.9068598725149652

可以看到,通过AdaBoosting算法,回归模型获得了更高的R2值.

随机森林

什么是随机森林

随机森林(Random Forest,简称RF)是专门为决策树设计的一种集成方法,是Bagging法的一种拓展,它是指每次构建决策树模型时,不仅随机选择部分样本,而且还随机选择部分特征来构建多棵决策树. 这样不仅规避了强势样本对预测结果的影响,而且也削弱了强势特征的影响,使模型具有更强的泛化能力.

随机森林简单、容易实现、计算开销小,在很多现实任务中展现出强大的性能,被誉为“代表集成学习技术水平的方法”.

如何实现随机森林

sklearn中,随机森林相关API:

1
2
3
4
5
6
import sklearn.ensemble as se

model = se.RandomForestRegressor(
max_depth, # 决策树最大深度
n_estimators, # 决策树数量
min_samples_split)# 子表中最小样本数 若小于这个数字,则不再继续向下拆分

以下是利用随机森林实现波士顿房价预测的代码:

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
# 使用随机森林预测波士顿房价
import sklearn.datasets as sd
import sklearn.utils as su
import sklearn.tree as st
import sklearn.ensemble as se
import sklearn.metrics as sm

boston = sd.load_boston() # 加载boston地区房价数据
print(boston.feature_names)
print(boston.data.shape)
print(boston.target.shape)

random_seed = 7 # 随机种子,计算随机值,相同的随机种子得到的随机值一样
x, y = su.shuffle(boston.data, boston.target, random_state=random_seed)
# 计算训练数据的数量
train_size = int(len(x) * 0.8) # 以boston.data中80%的数据作为训练数据
# 构建训练数据、测试数据
train_x = x[:train_size] # 训练输入, x前面80%的数据
test_x = x[train_size:] # 测试输入, x后面20%的数据
train_y = y[:train_size] # 训练输出
test_y = y[train_size:] # 测试输出

# 创建随机森林回归器,并进行训练
model = se.RandomForestRegressor(max_depth=10, # 最大深度
n_estimators=1000, # 树数量
min_samples_split=2) # 最小样本数量,小于该数就不再划分子节点
model.fit(train_x, train_y) # 训练

# 基于天统计数据的特征重要性
fi_dy = model.feature_importances_
# print(fi_dy)
pre_test_y = model.predict(test_x)
print(sm.r2_score(test_y, pre_test_y)) # 打印r2得分

打印输出:

1
2
3
4
5
['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO'
'B' 'LSTAT']
(506, 13)
(506,)
0.9271955403309159

总结

1)什么是决策树:利用样本特征进行决策归类,将具有相同属性的样本划入一个子节点

2)决策树的用途:用作分类器、回归器

3)如何构建决策树:根据信息增益、增益率、基尼系数构建

4)什么情况下使用决策树:实用性较广,课用于一般回归、分类问题

5)决策树优化:集成学习、随机森林

练习

(1)有一批水果(如下图所示),按照形状进行分类,将长条形、椭圆形各划分到不同子节点中,计算划分后的信息增益.

decision_tree11

(2)一批样本包含A和B两个类别,计算:当A类别比率依次占0%, 10%, 20%, …, 100%时,这批样本信息熵值,并以占比作为x轴数值、信息熵作为y轴数值绘制图像.

延伸阅读

  • VMware公司使用定制的决策树进行定价优化
1
2
3
4
VMware(VMW)是一家提供虚拟化技术、终端服务和云处理的公司,它将产品销售给B2B客户。长期以来,VMW公司的产品价格罕有变动。当接收到大订单的时候,销售代表会通过销售人员特别折扣(Sales Person Specific discount,SPF)标识来给出特定折扣。而VMW的定价部门则希望找到一种方法来优化其产品定价。在各个商业领域,市场上都有着对应的解决定价问题的数据挖掘解决方案。解决方案的目标不仅是优化定价,同时还要让客户的利益最大化。

VMW公司的分析和数据科学小组通过分析历史价格和相应的销量变化,来理解折扣百分比与SPF标识的关联性,并以此为依据归纳出所有产品的推荐定价。传统的定价优化会根据数量变化来进行价格变动,但是VMW公司并不会改变价格,而是使用折扣作为替代方法,但是使用折扣需要额外的步骤来确定是否需要给出折扣以及折扣率。
小组使用决策树的方法,基于折扣率和SPF标识的使用情况来对所有订单进行分类。根据业务的需求,以一种特定顺序构建出多分支(非二元)决策树。各种可能订单定价的属性都在决策树构建中被考虑进来。决策树构建过程中,基于均方误差、熵、log-loss、Gini指标等确定了决策树构建过程中分支属性的顺序。相比于使用标准分裂标准,使用的是根据业务需求定制的分裂标准。分裂停止标准是最小化观测对象数目。针对完成的分块,基于分块的属性特性观察其折扣百分比与SPF使用情况的关联性,并完成产品平台级的定价推荐。

、支持向量机

基本概念

什么是支持向量机

支持向量机(Support Vector Machines)是一种二分类模型,在机器学习、计算机视觉、数据挖掘中广泛应用,主要用于解决数据分类问题,它的目的是寻找一个超平面来对样本进行分割,分割的原则是间隔最大化(即数据集的边缘点到分界线的距离d最大,如下图),最终转化为一个凸二次规划问题来求解。通常SVM用于二元分类问题,对于多元分类可将其分解为多个二元分类问题,再进行分类。所谓“支持向量”,就是下图中虚线穿过的边缘点。支持向量机就对应着能将数据正确划分并且间隔最大的直线(下图中红色直线)。

最优分类边界

什么才是最优分类边界?什么条件下的分类边界为最优边界呢?

如图中的A,B两个样本点,B点被预测为正类的确信度要大于A点,所以SVM的目标是寻找一个超平面,使得离超平面较近的异类点之间能有更大的间隔,即不必考虑所有样本点,只需让求得的超平面使得离它近的点间隔最大。超平面可以用如下线性方程来描述:

wTx+b=0w^T x + b = 0

其中,x=(x1;x2;...;xn)x=(x_1;x_2;...;x_n)w=(w1;w2;...;wn)w=(w_1;w_2;...;w_n)bb为偏置项. 可以从数学上证明,支持向量到超平面距离为:

γ=1w\gamma = \frac{1}{||w||}

为了使距离最大,只需最小化w||w||即可.

SVM最优边界要求

SVM寻找最优边界时,需满足以下几个要求:

(1)正确性:对大部分样本都可以正确划分类别;

(2)安全性:支持向量,即离分类边界最近的样本之间的距离最远;

(3)公平性:支持向量与分类边界的距离相等;

(4)简单性:采用线性方程(直线、平面)表示分类边界,也称分割超平面。如果在原始维度中无法做线性划分,那么就通过升维变换,在更高维度空间寻求线性分割超平面. 从低纬度空间到高纬度空间的变换通过核函数进行。

线性可分与线性不可分

① 线性可分

如果一组样本能使用一个线性函数将样本正确分类,称这些数据样本是线性可分的。那么什么是线性函数呢?在二维空间中就是一条直线,在三维空间中就是一个平面,以此类推,如果不考虑空间维数,这样的线性函数统称为超平面。

② 线性不可分

如果一组样本,无法找到一个线性函数将样本正确分类,则称这些样本线性不可分。以下是一个一维线性不可分的示例:

一维线性不可分
以下是一个二维不可分的示例:

二维线性不可分
对于该类线性不可分问题,可以通过升维,将低纬度特征空间映射为高纬度特征空间,实现线性可分,如下图所示:

一维空间升至二维空间实现线性可分
![](https://image.discover304.top/ai/svm_6.png)
二维空间升至三维空间实现线性可分
那么如何实现升维?这就需要用到核函数。

核函数

通过名为核函数的特征变换,增加新的特征,使得低维度线性不可分问题变为高维度线性可分问题。如果低维空间存在K(x,y),x,y∈Χ,使得K(x,y)=ϕ(x)·ϕ(y),则称K(x,y)为核函数,其中ϕ(x)·ϕ(y)为x,y映射到特征空间上的内积,ϕ(x)为X→H的映射函数。以下是几种常用的核函数。

线性核函数

线性核函数(Linear)表示不通过核函数进行升维,仅在原始空间寻求线性分类边界,主要用于线性可分问题。

示例代码:

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
# 支持向量机示例
import numpy as np
import sklearn.model_selection as ms
import sklearn.svm as svm
import sklearn.metrics as sm
import matplotlib.pyplot as mp

x, y = [], []
with open("../data/multiple2.txt", "r") as f:
for line in f.readlines():
data = [float(substr) for substr in line.split(",")]
x.append(data[:-1]) # 输入
y.append(data[-1]) # 输出

# 列表转数组
x = np.array(x)
y = np.array(y, dtype=int)

# 线性核函数支持向量机分类器
model = svm.SVC(kernel="linear") # 线性核函数
# model = svm.SVC(kernel="poly", degree=3) # 多项式核函数
# print("gamma:", model.gamma)
# 径向基核函数支持向量机分类器
# model = svm.SVC(kernel="rbf",
# gamma=0.01, # 概率密度标准差
# C=200) # 概率强度
model.fit(x, y)

# 计算图形边界
l, r, h = x[:, 0].min() - 1, x[:, 0].max() + 1, 0.005
b, t, v = x[:, 1].min() - 1, x[:, 1].max() + 1, 0.005

# 生成网格矩阵
grid_x = np.meshgrid(np.arange(l, r, h), np.arange(b, t, v))
flat_x = np.c_[grid_x[0].ravel(), grid_x[1].ravel()] # 合并
flat_y = model.predict(flat_x) # 根据网格矩阵预测分类
grid_y = flat_y.reshape(grid_x[0].shape) # 还原形状

mp.figure("SVM Classifier", facecolor="lightgray")
mp.title("SVM Classifier", fontsize=14)

mp.xlabel("x", fontsize=14)
mp.ylabel("y", fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y, cmap="gray")

C0, C1 = (y == 0), (y == 1)
mp.scatter(x[C0][:, 0], x[C0][:, 1], c="orangered", s=80)
mp.scatter(x[C1][:, 0], x[C1][:, 1], c="limegreen", s=80)
mp.show()

绘制图形:

多项式核函数

多项式核函数(Polynomial Kernel)用增加高次项特征的方法做升维变换,当多项式阶数高时复杂度会很高,其表达式为:

K(xy)=(αxTy+c)dK(x,y)=(αx^T·y+c)d

y=x1+x2y=x12+2x1x2+x22y=x13+3x12x2+3x1x22+x23y = x_1 + x_2\\ y = x_1^2 + 2x_1x_2+x_2^2\\ y=x_1^3 + 3x_1^2x_2 + 3x_1x_2^2 + x_2^3

其中,α表示调节参数,d表示最高次项次数,c为可选常数。

示例代码(将上一示例中创建支持向量机模型改为一下代码即可):

1
model = svm.SVC(kernel="poly", degree=3)  # 多项式核函数

生成图像:

径向基核函数

径向基核函数(Radial Basis Function Kernel)具有很强的灵活性,应用很广泛。与多项式核函数相比,它的参数少,因此大多数情况下,都有比较好的性能。在不确定用哪种核函数时,可优先验证高斯核函数。由于类似于高斯函数,所以也称其为高斯核函数。表达式如下:

示例代码(将上一示例中分类器模型改为如下代码即可):

1
2
3
4
# 径向基核函数支持向量机分类器
model = svm.SVC(kernel="rbf",
gamma=0.01, # 概率密度标准差
C=600) # 概率强度,该值越大对错误分类的容忍度越小,分类精度越高,但泛化能力越差;该值越小,对错误分类容忍度越大,但泛化能力强

生成图像:

总结

(1)支持向量机是二分类模型

(2)支持向量机通过寻找最优线性模型作为分类边界

(3)边界要求:正确性、公平性、安全性、简单性

(4)可以通过核函数将线性不可分转换为线性可分问题,核函数包括:线性核函数、多项式核函数、径向基核函数

(5)支持向量机适合少量样本的分类

网格搜索

获取一个最优超参数的方式可以绘制验证曲线,但是验证曲线只能每次获取一个最优超参数。如果多个超参数有很多排列组合的话,就可以使用网格搜索寻求最优超参数组合。

针对超参数组合列表中的每一个超参数组合,实例化给定的模型,做cv次交叉验证,将其中平均f1得分最高的超参数组合作为最佳选择,实例化模型对象。

网格搜索相关API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import sklearn.model_selection as ms
params =
[{'kernel':['linear'], 'C':[1, 10, 100, 1000]},
{'kernel':['poly'], 'C':[1], 'degree':[2, 3]},
{'kernel':['rbf'], 'C':[1,10,100], 'gamma':[1, 0.1, 0.01]}]


model = ms.GridSearchCV(模型, params, cv=交叉验证次数)
model.fit(输入集,输出集)
# 获取网格搜索每个参数组合
model.cv_results_['params']
# 获取网格搜索每个参数组合所对应的平均测试分值
model.cv_results_['mean_test_score']
# 获取最好的参数
model.best_params_
model.best_score_
model.best_estimator_

朴素贝叶斯

朴素贝叶斯是一组功能强大且易于训练的分类器,它使用贝叶斯定理来确定给定一组条件的结果的概率,“朴素”的含义是指所给定的条件都能独立存在和发生. 朴素贝叶斯是多用途分类器,能在很多不同的情景下找到它的应用,例如垃圾邮件过滤、自然语言处理等.

概率

定义

概率是反映随机事件出现的可能性大小. 随机事件是指在相同条件下,可能出现也可能不出现的事件. 例如:

(1)抛一枚硬币,可能正面朝上,可能反面朝上,这是随机事件. 正/反面朝上的可能性称为概率;

(2)掷骰子,掷出的点数为随机事件. 每个点数出现的可能性称为概率;

(3)一批商品包含良品、次品,随机抽取一件,抽得良品/次品为随机事件. 经过大量反复试验,抽得次品率越来越接近于某个常数,则该常数为概率.

我们可以将随机事件记为A或B,则P(A), P(B)表示事件A或B的概率.

联合概率与条件概率

① 联合概率

指包含多个条件且所有条件同时成立的概率,记作P(A,B)P ( A , B ) ,或P(AB)P(AB),或P(AB)P(A \bigcap B)

② 条件概率

已知事件B发生的条件下,另一个事件A发生的概率称为条件概率,记为:P(AB)P(A|B)

p(下雨|阴天)

③ 事件的独立性

事件A不影响事件B的发生,称这两个事件独立,记为:

P(AB)=P(A)P(B)P(AB)=P(A)P(B)

因为A和B不相互影响,则有:

P(AB)=P(A)P(A|B) = P(A)

可以理解为,给定或不给定B的条件下,A的概率都一样大.

先验概率与后验概率

① 先验概率

先验概率也是根据以往经验和分析得到的概率,例如:在没有任何信息前提的情况下,猜测对面来的陌生人姓氏,姓李的概率最大(因为全国李姓为占比最高的姓氏),这便是先验概率.

② 后验概率

后验概率是指在接收了一定条件或信息的情况下的修正概率,例如:在知道对面的人来自“牛家村”的情况下,猜测他姓牛的概率最大,但不排除姓杨、李等等,这便是后验概率.

③ 两者的关系

事情还没有发生,求这件事情发生的可能性的大小,是先验概率(可以理解为由因求果). 事情已经发生,求这件事情发生的原因是由某个因素引起的可能性的大小,是后验概率(由果求因). 先验概率与后验概率有不可分割的联系,后验概率的计算要以先验概率为基础.

贝叶斯定理

定义

贝叶斯定理由英国数学家托马斯.贝叶斯 ( Thomas Bayes)提出,用来描述两个条件概率之间的关系,定理描述为:

P(AB)=P(A)P(BA)P(B)P(A|B) = \frac{P(A)P(B|A)}{P(B)}

其中,P(A)P(A)P(B)P(B)是A事件和B事件发生的概率. P(AB)P(A|B)称为条件概率,表示B事件发生条件下,A事件发生的概率. 推导过程:

P(A,B)=P(B)P(AB)P(B,A)=P(A)P(BA)P(A,B) =P(B)P(A|B)\\ P(B,A) =P(A)P(B|A)

其中P(A,B)P(A,B)称为联合概率,指事件B发生的概率,乘以事件A在事件B发生的条件下发生的概率. 因为P(A,B)=P(B,A)P(A,B)=P(B,A), 所以有:

P(B)P(AB)=P(A)P(BA)P(B)P(A|B)=P(A)P(B|A)

两边同时除以P(B),则得到贝叶斯定理的表达式. 其中,P(A)P(A)是先验概率,P(AB)P(A|B)是已知B发生后A的条件概率,也被称作后验概率.

贝叶斯定理示例

【示例一】计算诈骗短信的概率

事件 概率 表达式
所有短信中,诈骗短信 5% P(A)= 0.05
所有短信中,含有“中奖”两个字 4% P(B)= 0.04
所有短信中,是诈骗短信,并且含有“中奖”两个字 50% P(B|A) = 0.5

求:收到一条新信息,含有“中奖”两个字,是诈骗短信的概率?

P(AB)=P(A)P(BA)/P(B)=0.050.5/0.04=0.625P(A|B) = P(A) P(B|A) / P(B) = 0.05 * 0.5 / 0.04 = 0.625

【示例二】计算喝酒驾车的概率

事件 概率 表达式
所有客人中,驾车 20% P(A)= 0.2
所有客人中,喝酒 10% P(B)= 0.1
所有客人中,开车并且喝酒 5% P(B|A)= 0.05

求:喝过酒仍然会开车的人的比例是多少?

P(AB)=P(A)P(BA)/P(B)=0.20.05/0.1=0.1P(A|B) = P(A) P(B|A) / P(B) = 0.2 * 0.05 / 0.1 = 0.1

假设一个学校中 60%的男生 和40%的女生

女生穿裤子的人数和穿裙子的人数相等

所有的男生都穿裤子
一个人随机在远处眺望,看一个穿裤子的学生

请问这个学生是女生的概率

p(女) = 0.4

p(裤子|女) = 0.5

p(裤子) = 0.8

P(女|裤子) = 0.4 * 0.5 / 0.8 = 0.25

P(AB)=P(A)P(BA)P(B)P(A|B) = \frac{P(A)P(B|A)}{P(B)}

朴素贝叶斯分类器

分类原理

朴素贝叶斯分类器就是根据贝叶斯公式计算结果进行分类的模型,“朴素”指事件之间相互独立无影响. 例如:有如下数据集:

Text Category
A great game(一个伟大的比赛) Sports(体育运动)
The election was over(选举结束) Not sports(不是体育运动)
Very clean match(没内幕的比赛) Sports(体育运动)
A clean but forgettable game(一场难以忘记的比赛) Sports(体育运动)
It was a close election(这是一场势均力敌的选举) Not sports(不是体育运动)

求:”A very close game“ 是体育运动的概率?数学上表示为 P(Sports | a very close game)​. 根据贝叶斯定理,是运动的概率可以表示为:

P(Sportsa very close game)=P(a very close gamesports)P(sports)P(a very close game)P(Sports | a \ very \ close \ game) = \frac{P(a \ very \ close \ game | sports) * P(sports)}{P(a \ very \ close \ game)}

不是运动概率可以表示为:

P(Not Sportsa very close game)=P(a very close gameNot sports)P(Not sports)P(a very close game)P(Not \ Sports | a \ very \ close \ game) = \frac{P(a \ very \ close \ game | Not \ sports) * P(Not \ sports)}{P(a \ very \ close \ game)}

概率更大者即为分类结果. 由于分母相同,即比较分子谁更大即可. 我们只需统计”A very close game“ 多少次出现在Sports类别中,就可以计算出上述两个概率. 但是”A very close game“ 并没有出现在数据集中,所以这个概率为0,要解决这个问题,就假设每个句子的单词出现都与其它单词无关(事件独立即朴素的含义),所以,P(a very close game)可以写成:

P(a very close game)=P(a)P(very)P(close)P(game)P(a \ very \ close \ game) = P(a) * P(very) * P(close) * P(game)

Pa very close gameSports)=P(aSports)P(verySports)P(closeSports)P(gameSports)P(a \ very \ close \ game|Sports)= \\ P(a|Sports)*P(very|Sports)*P(close|Sports)*P(game|Sports)

统计出“a", “very”, “close”, "game"出现在"Sports"类别中的概率,就能算出其所属的类别. 具体计算过程如下:

  • 第一步:计算总词频:Sports类别词语总数14,Not Sports类别词语总数9

  • 第二步:计算每个类别的先验概率

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # Sports和Not Sports概率
    P(Sports) = 3 / 5 = 0.6
    P(Not Sports) = 2 / 5 = 0.4

    # Sports条件下各个词语概率
    P(a | Sports) = (2 + 1) / (11 + 14) = 0.12
    P(very | Sports) = (1 + 1) / (11 + 14) = 0.08
    P(close | Sports) = (0 + 1) / (11 + 14) = 0.04
    P(game | Sports) = (2 + 1) / (11 + 14) = 0.12

    # Not Sports条件下各个词语概率
    P(a | Not Sports) = (1 + 1) / (9 + 14) = 0.087
    P(very | Not Sports) = (0 + 1) / (9 + 14) = 0.043
    P(close | Not Sports) = (1 + 1) / (9 + 14) = = 0.087
    P(game | Not Sports) = (0 + 1) / (9 + 14) = 0.043

    其中,分子部分加1,是为了避免分子为0的情况;分母部分都加了词语总数14,是为了避免分子增大的情况下计算结果超过1的可能.

  • 第三步:将先验概率带入贝叶斯定理,计算概率:

    是体育运动的概率:

Pa very close gameSports)=P(aSports)P(verySports)P(closeSports)P(gameSports)=0.120.080.040.12=0.00004608P(a \ very \ close \ game|Sports)= \\ P(a|Sports)*P(very|Sports)*P(close|Sports)*P(game|Sports)= \\ 0.12 * 0.08 * 0.04 * 0.12 = 0.00004608

​ 不是体育运动的概率:

Pa very close gameNot Sports)=P(aNot Sports)P(veryNot Sports)P(closeNot Sports)P(gameNot Sports)=0.0870.0430.0870.043=0.000013996P(a \ very \ close \ game|Not \ Sports)= \\ P(a|Not \ Sports)*P(very|Not \ Sports)*P(close|Not \ Sports)*P(game|Not \ Sports)= \\ 0.087 * 0.043 * 0.087 * 0.043 = 0.000013996

分类结果:P(Sports) = 0.00004608 , P(Not Sports) = 0.000013996, 是体育运动.

实现朴素贝叶斯分类器

在sklearn中,提供了三个朴素贝叶斯分类器,分别是:

  • GaussianNB(高斯朴素贝叶斯分类器):适合用于样本的值是连续的,数据呈正态分布的情况(比如人的身高、城市家庭收入、一次考试的成绩等等)
  • MultinominalNB(多项式朴素贝叶斯分类器):适合用于大部分属性为离散值的数据集
  • BernoulliNB(伯努利朴素贝叶斯分类器):适合用于特征值为二元离散值或是稀疏的多元离散值的数据集

该示例中,样本的值为连续值,且呈正态分布,所以采用GaussianNB模型. 代码如下:

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
# 朴素贝叶斯分类示例
import numpy as np
import sklearn.naive_bayes as nb
import matplotlib.pyplot as mp

# 输入,输出
x, y = [], []

# 读取数据文件
with open("../data/multiple1.txt", "r") as f:
for line in f.readlines():
data = [float(substr) for substr in line.split(",")]
x.append(data[:-1]) # 输入样本:取从第一列到倒数第二列
y.append(data[-1]) # 输出样本:取最后一列

x = np.array(x)
y = np.array(y, dtype=int)

# 创建高斯朴素贝叶斯分类器对象
model = nb.GaussianNB()
model.fit(x, y) # 训练

# 计算显示范围
left = x[:, 0].min() - 1
right = x[:, 0].max() + 1

buttom = x[:, 1].min() - 1
top = x[:, 1].max() + 1

grid_x, grid_y = np.meshgrid(np.arange(left, right, 0.01),
np.arange(buttom, top, 0.01))

mesh_x = np.column_stack((grid_x.ravel(), grid_y.ravel()))
mesh_z = model.predict(mesh_x)
mesh_z = mesh_z.reshape(grid_x.shape)

mp.figure('Naive Bayes Classification', facecolor='lightgray')
mp.title('Naive Bayes Classification', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x, grid_y, mesh_z, cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=y, cmap='brg', s=80)
mp.show()

执行结果:

总结

1)什么是朴素贝叶斯:朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。“朴素”的含义为:假设问题的特征变量都是相互独立地作用于决策变量的,即问题的特征之间都是互不相关的。

2)朴素贝叶斯分类的特点

① 优点

  • 逻辑性简单
  • 算法较为稳定。当数据呈现不同的特点时,朴素贝叶斯的分类性能不会有太大的差异。
  • 当样本特征之间的关系相对比较独立时,朴素贝叶斯分类算法会有较好的效果。

② 缺点

  • 特征的独立性在很多情况下是很难满足的,因为样本特征之间往往都存在着相互关联,如果在分类过程中出现这种问题,会导致分类的效果大大降低。

3)什么情况下使用朴素贝叶斯:根据先验概率计算后验概率的情况,且样本特征之间独立性较强。