Datawhale组队学习第27期:集成学习
本次学习的指导老师萌弟的教学视频
本贴为学习记录帖,有任何问题欢迎随时交流~
部分内容可能还不完整,后期随着知识积累逐步完善。
开始时间:2021年7月19日
最新更新:2021年7月20日(Task4分类问题)
一、度量分类模型的性能指标
1. 混淆矩阵
- 假阴性和假阳性都是分类错误,在现实生活中这两种分类错误的代价有所不同,需要分开讨论。
- 这里有点类似最小错误率决策和最小风险决策。
2.分类模型的指标
准确率Accuracy
-
含义:真阳性和真阴性的占总样本比例
-
调用函数:
sklearn.metrics.accuracy_score
-
计算公式:
A c c u r a c y ( 二 分 类 ) = T P + T N T P + T N + F P + F N Accuracy(二分类) = \frac{TP+TN}{TP+TN+FP+FN} Accuracy(二分类)=TP+TN+FP+FNTP+TN
精度Precision
-
含义:真阳性占预测阳性比例,又称为:查准率
-
调用函数:
sklearn.metrics.average_precision_score
-
计算公式:
P r e c i s i o n ( 二 分 类 ) = T P T P + F P P r e c i s i o n ( 多 分 类 − M i c r o ) = ∑ i = 1 n T P i ∑ i = 1 n ( T P i + F P i ) P r e c i s i o n ( 多 分 类 − M a c r o ) = 1 n ∑ i = 1 n T P i T P i + F P i \begin{aligned} Precision(二分类) &= \frac{TP}{TP+FP} \\ Precision(多分类-Micro) &= \frac{\sum\limits_{i=1}^{n}TP_i}{\sum\limits_{i=1}^{n}(TP_i+FP_i)} \\ Precision(多分类-Macro) &= \frac{1}{n} \sum\limits_{i=1}^{n}\frac{TP_i}{TP_i+FP_i} \end{aligned} Precision(二分类)Precision(多分类−Micro)Precision(多分类−Macro)=TP+FPTP=i=1∑n(TPi+FPi)i=1∑nTPi=n1i=1∑nTPi+FPiTPi
召回率Recall
-
含义:真阳性占实际阳性比例,又称为真阳性率TPR,敏感性Sensitive,查全率
-
调用函数:
sklearn.metrics.recall_score
-
计算公式:
R e c a l l ( 二 分 类 ) = T P T P + F N R e c a l l ( 多 分 类 − M i c r o ) = ∑ i = 1 n T P i ∑ i = 1 n ( T P i + F N i ) R e c a l l ( 多 分 类 − M a c r o ) = 1 n ∑ i = 1 n T P i T P i + F N i \begin{aligned} Recall(二分类) &= \frac{TP}{TP+FN} \\ Recall(多分类-Micro) &= \frac{\sum\limits_{i=1}^{n}TP_i}{\sum\limits_{i=1}^{n}(TP_i+FN_i)} \\ Recall(多分类-Macro) &= \frac{1}{n} \sum\limits_{i=1}^{n}\frac{TP_i}{TP_i+FN_i} \end{aligned} Recall(二分类)Recall(多分类−Micro)Recall(多分类−Macro)=TP+FNTP=i=1∑n(TPi+FNi)i=1∑nTPi=n1i=1∑nTPi+FNiTPi
假阳性率FPR
- 含义:假阳性占实际阴性的比例,常用于ROC曲线中,等于
1 - 特异性Specificity
- 计算公式:
F P R = F N T N + F P FPR = \frac{FN}{TN+FP} FPR=TN+FPFN
F1值
-
含义::综合精度和召回率(注意:在多分类下也有
Micro
和Marco
)。 -
调用函数:
sklearn.metrics.f1_score
-
计算公式:
F 1 = 2 × P r e c i s i o n × R e c a l l P r e c i s i o n + R e c a l l F1 = 2 \times \frac{Precision \times Recall}{Precision + Recall} \\ F1=2×Precision+RecallPrecision×Recall
ROC
- 含义:纵轴为真阳率、横轴为假阳性率的曲线图。
- 调用函数:
sklearn.metrics.roc_curve
- 例子:
AUC
- 含义:ROC曲线与X轴之间的面积
- 调用函数:
sklearn.metrics.roc_auc_score
二、常见的分类模型
1. 感知机
- 常用库:
sklearn.sklearn.neural_network.MLPClassifier
2. Logistic回归
- 常用库:
sklearn.linear_model.LogisticRegression
3. 支持向量机
- 线性可分问题
- 最大间隔
sign
函数
- 非线性可分问题
- 核函数:低维度映射到高维度
- 多项式核函数
- 高斯核函数
- Sigmoid核函数
- 余弦相似度核函数
- 常用库:
sklearn.svm.LinearSVC
4. 决策树
- 关键是分割节点的标准(回归树中使用的是均方误差)
- 常见的分割节点标准:
- 错误率
- 基尼系数
- 交叉熵
- 常用库:
sklearn.tree.DecisionTreeClassifier
5. K近邻
- 常用库:
sklearn.neighbors.KNeighborsClassifier
三、Logistic回归
1. 线性回归模型及其假定回顾
线性回归模型
y = w T x + ϵ y = w^Tx + \epsilon y=wTx+ϵ
线性回归模型的假定
-
线性假定: y = w T x + ϵ y = w^T x + \epsilon y=wTx+ϵ,其中w的元素均为常数
-
严格外生性假定: E ( ϵ ∣ x ) = 0 E(\epsilon|x) = 0 E(ϵ∣x)=0,即扰动项独立于观测数据
-
数值矩阵 x x x 是列满秩,不存在严格的多重共线性
-
球形扰动项假定: V a r ( ϵ ∣ x ) = σ 2 Var(\epsilon|x) = \sigma^2 Var(ϵ∣x)=σ2,即扰动项条件同方差和无自相关
-
正态性假定: ϵ ∣ x ∼ N ( 0 , σ 2 ) \epsilon|x \sim N(0, \sigma^2) ϵ∣x∼N(0,σ2)
离散型变量下的线性回归
-
在普通线性回归中, y y y是一个连续型随机变量,那么 ϵ = y − w T x \epsilon = y - w^Tx ϵ=y−wTx显然也是连续性变量,这时的 c o v ( ϵ , x ) = 0 cov(\epsilon, x) = 0 cov(ϵ,x)=0,满足严格外生性和正态性假定。
-
当 y y y是一个离散型随机变量时(假设是二值离散),那么 ϵ = 1 − w T x \epsilon=1-w^Tx ϵ=1−wTx或 ϵ = − w T x \epsilon = -w^Tx ϵ=−wTx,这时 c o v ( ϵ , x ) ≠ 0 cov(\epsilon, x) \ne 0 cov(ϵ,x)=0,意味着扰动项依赖于观测数据,也表明了扰动项存在异方差;同时 ϵ ∣ x ∼ B ( 0 , 1 ) \epsilon|x \sim B(0,1) ϵ∣x∼B(0,1),不满足原有的正态性假定。
线性回归、感知机与Logistic回归的联系
- 当 y y y是一个离散型随机变量时(假设是二值离散),依旧使用原有的线性回归模型, w T x w^Tx wTx的取值范围有可能是 ( − ∞ , + ∞ ) (-\infty, +\infty) (−∞,+∞)。从分类角度看,存在一个超平面将其划分成两个类别所属的空间,这里的划分一般是采用 s i g n sign sign函数(阶跃函数),将 w T x w^Tx wTx直接转化成二分类的类别,而 s i g n sign sign函数称为连接函数。这里的通过 s i g n sign sign函数进行中间转化的线性模型,称为感知机。
- 上面的模型直接预测成类别,而现实或许更关注某个类别发生的概率。因此,从概率的角度思考, w T x w^Tx wTx需要映射到 [ 0 , 1 ] [0, 1] [0,1]上,即:存在一个连接函数,使得y的预测值介于 [ 0 , 1 ] [0, 1] [0,1]之间。显然,上述使用的 s i g n sign sign函数不适合作为这类模型的连接函数。这时 s i g m o i d sigmoid sigmoid函数作为连接函数,形成的模型称为逻辑斯蒂回归模型。
- 对比之后可以发现,该三类模型依旧是依赖于线性模型,主要区别在于各自选取的连接函数。普通线性回归可以视连接函数为: h ( w T x ) h(w^Tx) h(wTx) = w^Tx,感知机的连接函数为: h ( w T x ) = s i g n ( w T x ) h(w^Tx) = sign(w^Tx) h(wTx)=sign(wTx), L o g i s t i c Logistic Logistic回归的连接函数为: h ( w T x ) = s i g m o i d ( w T x ) h(w^Tx) = sigmoid(w^Tx) h(wTx)=sigmoid(wTx)。
- 下面是三者的对比图,图片选自《机器学习的思考故事》
2. Sigmoid函数引入
-
定义(一般记为 σ \sigma σ)
σ ( x ) = F ( x ) = 1 1 + e − x \sigma(x) = F(x) = \frac{1}{1+e^{-x}} σ(x)=F(x)=1+e−x1 -
特点:
- 将 x x x映射到 [ 0 , 1 ] [0, 1] [0,1]上
- 平滑且易求导
-
导数:
σ ′ ( x ) = F ′ ( x ) = e − x ( 1 + e − x ) 2 = F ( x ) ( 1 − F ( x ) ) \sigma'(x) = F'(x) = \frac{e^{-x}}{(1+e^{-x})^2} = F(x)(1-F(x)) σ′(x)=F′(x)=(1+e−x)2e−x=F(x)(1−F(x)) -
函数图像:
-
实现代码:
import numpy as np import matplotlib.pyplot as plt # 定义sigmoid函数 def sigmoid(x_): return 1 / (1 + np.exp(-x_)) x = np.linspace(-10, 10, 100) y = sigmoid(x) # 画出函数图像 plt.plot(x, y, 'r') plt.title(r'$F(x) = \frac{1}{1+e^{-x}}$') plt.xlabel('x') plt.ylabel('F(x)') plt.show()
3. Logistic回归模型推导
模型设定
-
对于给定的 x x x,有y为类别标签(只为0或1),设定某件事发生的概率为 P ( y = 1 ∣ x ; w ) P(y=1|x;w) P(y=1∣x;w),则有:
P ( y = 1 ∣ x ; w ) = σ ( w T x ) P ( y = 0 ∣ x ; w ) = 1 − σ ( w T x ) P(y=1|x;w) = \sigma(w^Tx) \\ P(y=0|x;w) = 1 - \sigma(w^Tx) P(y=1∣x;w)=σ(wTx)P(y=0∣x;w)=1−σ(wTx) -
从随机试验角度看,箱子中有N个球(只有黑色和白色),抽取一次为白色的球记为事件A,而事件 X X X服从 b ( 1 , P ) b(1,P) b(1,P),即有:
P ( A ) = P ( Y = y ∣ x ; w ) = P ( Y = 1 ∣ x ; w ) y [ 1 − P ( Y = 1 ∣ x ; w ) ] 1 − y , 其 中 y = 0 , 1 P(A) = P(Y=y|x;w) = P(Y=1|x;w)^y[1-P(Y=1|x;w)]^{1-y},其中y=0,1 P(A)=P(Y=y∣x;w)=P(Y=1∣x;w)y[1−P(Y=1∣x;w)]1−y,其中y=0,1
参数估计
-
显然,我们最关注的是每个类别对应的概率(这里只需知道一个类别P,便可知道另一个类别的概率)。因此需要估计 b ( 1 , P ) b(1, P) b(1,P)中的 P P P,可以考虑采用极大似然估计法。
-
记 P ( y = 1 ∣ x ; w ) = π ( x ) P(y=1|x;w) = \pi(x) P(y=1∣x;w)=π(x),则 P ( Y = y ∣ x ; w ) = [ π ( x ) ] y [ 1 − π ( x ) ] 1 − y P(Y=y|x;w) = [\pi(x)]^y[1-\pi(x)]^{1-y} P(Y=y∣x;w)=[π(x)]y[1−π(x)]1−y
-
假设给定样本 x = { x 1 , x 2 , . . . x n } x = \{x_1, x_2, ... x_n\} x={ x1,x2,...xn},对应的标签 y = { y 1 , y 2 , . . . , y n } y = \{y_1, y_2,..., y_n\} y={ y1,y2,...,yn},有样本联合概率分布(似然函数)为:
L ( w ) = ∏ i = 1 n P ( Y i = y i ∣ x i ; w ) = ∏ i = 1 n [ π ( x i ) ] y i [ 1 − π ( x i ) ] 1 − y i = ∏ i = 1 n [ 1 1 + e x p { − w T x i } ] y i [ 1 − 1 1 + e x p { − w T x i } ] 1 − y i \begin{aligned} L(w) &= \prod\limits_{i=1}^{n}P(Y_i=y_i|x_i;w) \\ &= \prod\limits_{i=1}^{n}[\pi(x_i)]^{y_i}[1-\pi(x_i)]^{1-y_i} \\ &= \prod\limits_{i=1}^{n} [\frac{1}{1+exp\{-w^Tx_i\}}]^{y_i}[1 -\frac{1}{1+exp\{-w^Tx_i\}}]^{1-y_i} \end{aligned} L(w)=i=1∏nP(Yi=yi∣xi;w)=i=1∏n[π(xi)]yi[1−π(xi)]1−yi=i=1∏n[1+exp{ −wTxi}1]yi[1−1+exp{ −wTxi}1]1−yi -
对似然函数取对数,得到:
log L ( w ) = ∑ i = 1 n [ y i ⋅ log π ( x i ) + ( 1 − y i ) ⋅ log ( 1 − π ( x i ) ) ] = ∑ i = 1 n [ y i ⋅ log π ( x i ) 1 − π ( x i ) + log ( 1 − π ( x i ) ] = ∑ i = 1 n [ y i ( w T x i ) + l o g ( 1 − π ( x i ) ) ] \begin{aligned} \log L(w) &= \sum\limits_{i=1}^{n} [y_i \cdot \log \pi(x_i)+(1-y_i) \cdot \log(1-\pi(x_i))] \\ &= \sum\limits_{i=1}^{n} [y_i \cdot \log\frac{\pi(x_i)}{1-\pi(x_i)}+ \log(1-\pi(x_i) ] \\ &= \sum\limits_{i=1}^{n} [y_i(w^Tx_i) + log(1-\pi(x_i))] \end{aligned} logL(w)=i=1∑n[yi⋅logπ(xi)+(1−yi)⋅log(1−π(xi))]=i=1∑n[yi⋅log1−π(xi)π(xi)+log(1−π(xi)]=i=1∑n[yi(wTxi)+log(1−π(xi))]
优化问题
-
目标函数:
J ( w ) = − 1 n ∑ i = 1 n [ y i ⋅ ( w T x i ) + log ( 1 − π ( x i ) ) ] = − 1 n [ ( Y T X ⋅ w + ∑ i = 1 n log ( 1 − π ( x i ) ) ] \begin{aligned} J(w) &= -\frac{1}{n}\sum\limits_{i=1}^{n} [y_i \cdot (w^Tx_i) +\log(1-\pi(x_i))] \\ &= -\frac{1}{n}[(Y^TX\cdot w + \sum_{i=1}^{n}\log(1-\pi(x_i))] \end{aligned} J(w)=−n1i=1∑n[yi⋅(wTxi)+log(1−π(xi))]=−n1[(YTX⋅w+i=1∑nlog(1−π(xi))] -
优化任务:
w = argmin w J ( w ) w = \mathop{\text{argmin}}_{w} J(w) w=argminwJ(w)
优化算法(梯度下降法)
-
定义 s i g m o i d sigmoid sigmoid函数
-
初始化参数 w ( 0 ) = [ w 0 ( 0 ) , w 1 ( 0 ) , . . . , w m ( 0 ) ] w^{(0)} = [w_0^{(0)}, w_1^{(0)},..., w_m^{(0)}] w(0)=[w0(0),w1(0),...,wm(0)]
-
设定学习率 α \alpha α,最大迭代次数 l o o p s loops loops,可接受误差 ϵ \epsilon ϵ
-
计算当前梯度(使用链式法则):
∂ J ( w ) ∂ w j = − 1 n ∑ i = 1 n [ y i ∂ w T x i ∂ w j − 1 1 − π ( x i , w ) ∂ π ( x i , w ) ∂ w j ] = − 1 n ∑ i = 1 n [ y i x i j − 1 1 − π ( x i , w ) π ( x i , w ) ( 1 − π ( x i , w ) ) ∂ w T x i ∂ w j ] = − 1 n ∑ i = 1 n [ y i x i j − 1 1 − π ( x i , w ) π ( x i , w ) ( 1 − π ( x i , w ) ) x i j ] = − 1 n ∑ i = 1 n { [ y i − π ( x i , w ) ] x i j } = − 1 n ∑ i = 1 n [ ( y i − y ^ i ) x i j ] = 1 n ∑ i = 1 n [ ( y ^ i − y i ) x i j ] \begin{aligned} \frac{\partial J(w)}{\partial w_j} &= -\frac{1}{n} \sum\limits_{i=1}^{n} [y_i\frac{\partial w^Tx_i}{\partial w_j} - \frac{1}{1-\pi(x_i,w)} \frac{\partial \pi(x_i,w)}{\partial w_j}] \\ &= -\frac{1}{n} \sum\limits_{i=1}^{n} [y_ix^j_i - \frac{1}{1-\pi(x_i,w)} \pi(x_i, w)(1 - \pi(x_i,w))\frac{\partial w^Tx_i}{\partial w_j}] \\ &= -\frac{1}{n} \sum\limits_{i=1}^{n} [y_ix^j_i - \frac{1}{1-\pi(x_i,w)} \pi(x_i, w)(1 - \pi(x_i,w))x_i^j] \\ &= -\frac{1}{n} \sum\limits_{i=1}^{n} \{[y_i - \pi(x_i, w)]x_i^j\} \\ &= -\frac{1}{n} \sum\limits_{i=1}^{n} [(y_i - \hat y_i)x_i^j] \\ &= \frac{1}{n} \sum\limits_{i=1}^{n} [(\hat y_i - y_i)x_i^j] \\ \end{aligned} ∂wj∂J(w)=−n1i=1∑n[yi∂wj∂wTxi−1−π(xi,w)1∂wj∂π(xi,w)]=−n1i=1∑n[yixij−1−π(xi,w)1π(xi,w)(1−π(xi,w))∂wj∂wTxi]=−n1i=1∑n[yixij−1−π(xi,w)1π(xi,w)(1−π(xi,w))xij]=−n1i=1∑n{ [yi−π(xi,w)]xij}=−n1i=1∑n[(yi−y^i)xij]=n1i=1∑n[(y^i−yi)xij]- 转换成矩阵运算( X X X是 n × m n\times m n×m的数值矩阵,有m个特征):
∂ J ( w ) ∂ w = [ 1 n ∑ i = 1 n x i j ( y ^ i − y i ) ] m × 1 = 1 n X T ( Y ^ − Y ) \begin{aligned} \frac{\partial J(w)}{\partial w} &= [\frac{1}{n} \sum\limits_{i=1}^{n} x_i^j(\hat y_i - y_i)]_{m\times1} \\ &=\frac{1}{n} X^T(\hat Y - Y) \end{aligned} ∂w∂J(w)=[n1i=1∑nxij(y^i−yi)]m×1=n1XT(Y^−Y)
-
若 ∂ J ( w ) ∂ w ≥ ϵ \frac{\partial J(w)}{\partial w} \ge \epsilon ∂w∂J(w)≥ϵ,则更新参数,再按上述计算方式更新梯度:
w ( k + 1 ) : = w ( k ) − α ⋅ ∂ J ( w ) ∂ w w^{(k+1)} := w^{(k)} - \alpha \cdot \frac{\partial J(w)}{\partial w} w(k+1):=w(k)−α⋅∂w∂J(w) -
当 ∂ L ( w ) ∂ w < ϵ \frac{\partial L(w)}{\partial w} < \epsilon ∂w∂L(w)<ϵ 或超过最大迭代次数时,返回最新更新的参数 w ( k ) w^{(k)} w(k)。
4. Logisitic回归的实现
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 定义sigmoid函数
def sigmoid(x_):
return 1.0 / (1.0 + np.exp(-x_))
def grad(x_, y_, w_):
y_hat = sigmoid(np.dot(x_, w_))
return np.dot(x_.T, y_hat - y_) / len(y_)
def loss(w_, x_, y_):
n = len(x_)
h = sigmoid(np.dot(x_, w_))
j = -np.dot(np.transpose(y_), np.dot(x_, w_)) + sum(np.log(1 - h)) / n
return j
def sgd(x_, y_, w_, alpha_=0.01, loops_=100, err=0.001):
num = 0
g = grad(x_, y_, w_)
while num < loops_:
theta_ = w_ - alpha_ * g
g = grad(x_, y_, theta_)
if np.all(np.abs(g) < err):
print('已找到最优参数!\n总共迭代的次数为{}'.format(num))
print('最优参数为:{}'.format(np.round(w_, 3)))
break
w_ = theta_
num += 1
if num == loops_:
print('以达到最大迭代次数!\n最终参数为:{}'.format(np.round(w_, 3)))
return w_
if __name__ == '__main__':
# 加载数据集
data = load_iris()
data.keys()
# 选定变量
x = data['data'] # 返回的是ndarray类型,150个样本、4个特征
y = data['target']
# 分割样本(注意:这里是为了二分类)
x_train, x_test, y_train, y_test = train_test_split(x[:100], y[:100],
test_size=0.2, random_state=2021)
# 初始化参数
w = np.zeros((len(x[0]), ))
# 标准化
x_train = (x_train - np.mean(x, axis=0)) / np.std(x_train, axis=0)
# 设定参数
alpha = 0.01
loops = 100000
epsilon = 0.0001
# 梯度下降求解
best_w = sgd(x_train, y_train, w, alpha, loops, epsilon)
# 预测
y_pred = np.zeros(len(x_test))
y_pred[sigmoid(np.dot(x_test, best_w)) > 0.5] = 1
# 精度
print(sum(y_pred == y_test) / len(y_pred))