本次修炼方法请往下查看
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/531165c3ae494a6ea813e245d31082c8.gif#pic_center)
🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地!
🎇 免费获取相关内容文档关注:微信公众号,发送 pandas 即可获取
🎇 相关内容视频讲解 B站
🎓 博主简介:AI算法驯化师,混迹多个大厂搜索、推荐、广告、数据分析、数据挖掘岗位 个人申请专利40+,熟练掌握机器、深度学习等各类应用算法原理和项目实战经验。
🔧 技术专长: 在机器学习、搜索、广告、推荐、CV、NLP、多模态、数据分析等算法相关领域有丰富的项目实战经验。已累计为求职、科研、学习等需求提供近千次有偿|无偿定制化服务,助力多位小伙伴在学习、求职、工作上少走弯路、提高效率,近一年好评率100% 。
📝 博客风采: 积极分享关于机器学习、深度学习、数据分析、NLP、PyTorch、Python、Linux、工作、项目总结相关的实用内容。
下滑查看解决方法
🎯 1. 基本介绍
支持向量机(Support Vector Machine, SVM)是一种监督学习算法,用于分类和回归任务。SVM通过找到数据点之间的最优边界(称为超平面)来区分不同的类别。在scikit-learn(简称sklearn)中,SVM模型通过SVC(用于分类)和SVR(用于回归)类实现。
💡 2. 原理介绍
2.1 基础知识
样本空间任意点x到超平面 ( w T x + b = 0 ) (w^Tx+b=0) (wTx+b=0)的距离为:
r = ∣ w T x + b ∣ ∣ ∣ w ∣ ∣ , ∣ ∣ w ∣ ∣ = w 1 2 + w 2 2 + w 3 2 + . . . r=\frac{|w^{T}x+b|} {||w||}, ||w||=\sqrt {w_1^2+w_2^2+w_3^2+...} r=∣∣w∣∣∣wTx+b∣,∣∣w∣∣=w12+w22+w32+...
对偶问题: 有点时候不好去求解原问题的最优解,而通过求解对偶问题的解确很好求。对于对偶问题的理解:现在的问题是在满足KKT条件的基础上去求解:min:f(x),通过拉格朗日乘子法将约束条件转换为函数后,该式则变成:min(x):max(a):f(x, a),由于去直接求解这个问题需要先求含有两个变量的函数再去求含有x的函数比较麻烦,因此,可以先去求解x再去求解其它的变量因此,上述的最优结果可以改写为:max(a):min(x):f(x,a),具体的证明过程如下所示:
对偶问题具体表达如下:
m a x α , β : α i ⩾ 0 m i n x L ( x , α , β ) ⩽ m i n x m a x α , β : α i ⩾ 0 L ( x , α , β ) \underset{\alpha,\beta:\alpha_i\geqslant0}{max} \underset{x}{min}L(x,\alpha, \beta) \leqslant \underset{x}{min}\underset{\alpha,\beta:\alpha_i\geqslant0}{max}L(x,\alpha, \beta) α,β:αi⩾0maxxminL(x,α,β)⩽xminα,β:αi⩾0maxL(x,α,β)
具体的证明如下所示:
m i n x L ( x , α , β ) ⩽ L ( x , α , β ) ⩽ m a x α , β : α i ⩽ 0 L ( x , α , β ) \underset{x}{min}L(x,\alpha,\beta) \leqslant L(x, \alpha, \beta) \leqslant \underset{\alpha, \beta:\alpha_i \leqslant 0}{max}L(x, \alpha, \beta) xminL(x,α,β)⩽L(x,α,β)⩽α,β:αi⩽0maxL(x,α,β),因此,在对公式的左边取最大值,公式的右边取最小值,公式同样满足,就可以得到上述的对偶问题的公式表达式。
KKT条件和拉格朗日乘子法: 用来求解最优问题的两种常用方法,基本的思想就是将有约束条件的优化问题转换为没有约束条件的约束问题,当约束条件为等式时,直接使用拉格朗日乘子法就可以,当存在不等式约束条件时使用KKT条件加上拉格朗日乘子法来求解最优解,对于最优化问题,一般由如下三种情况组成:
(1): 无等式约束条件: 这种情况直接通过函数对相应变量进行求导,然后令导函数等于0,求得相应的可能极值点,然后再带入原函数进行对比,即可得出最小或最大值。
(2): 等式约束条件: 如目标函数f(x), 约束条件为h(x),具体的数学表达形式如下:
m
i
n
:
f
(
x
)
min: f(x)
min:f(x)
s
.
t
.
h
k
(
x
)
=
0
,
k
=
1
,
2
,
3...
l
s.t. h_{k}(x)=0, k=1,2,3...l
s.t.hk(x)=0,k=1,2,3...l
对于形如上述的最优化问题,之前高中课本教的是消元法,主要思路就是将约束条件进行变化,然后在带入目标函数中消除一个参数从而变成没有等式约束条件,再进行参数求导等于零即可得出结果。但是这种方法有时候计算太复杂了,这时拉格朗日乘子法就出来了,将上述数学表达使用拉朗乘数法,为了表达清晰举例说明:
f
(
x
,
y
,
z
)
=
8
x
y
z
f(x,y,z)=8xyz
f(x,y,z)=8xyz
h
(
x
,
y
,
z
)
=
x
2
a
2
+
y
2
b
2
+
z
2
c
2
−
1
h(x,y,z)=\frac{x^2}{a^2} + \frac{y^2}{b^2}+\frac{z^2}{c^2}-1
h(x,y,z)=a2x2+b2y2+c2z2−1
则上式的拉朗表达如下,转为无约束的优化问题,这里的参数
λ
\lambda
λ没有相关的限制:
F
(
x
,
y
,
z
,
λ
)
=
f
(
x
,
y
,
z
)
+
λ
h
(
x
,
y
,
z
)
F(x,y,z,\lambda)=f(x,y,z)+\lambda h(x,y,z)
F(x,y,z,λ)=f(x,y,z)+λh(x,y,z)
F
(
x
,
y
,
z
,
λ
)
=
8
x
y
z
+
λ
(
x
2
a
2
+
y
2
b
2
+
z
2
c
2
−
1
)
F(x,y,z,\lambda)=8xyz+\lambda (\frac{x^2}{a^2} +\frac{y^2}{b^2}+\frac{z^2}{c^2}-1)
F(x,y,z,λ)=8xyz+λ(a2x2+b2y2+c2z2−1)
然后对上式种的参数
x
,
y
,
z
,
λ
x,y,z,\lambda
x,y,z,λ进行求导令其等于0,即可求得目标函数的极值。
(3): 不等式约束条件: 此时为了得到最优解拉朗有点乏力了,至于为啥乏力,我也不知道了,等我知道了再告诉你们,哈哈:,此时KKT条件就派上用场了,如果在拉朗的基础上再加上KKT条件,就又可以得到最优解了,这也是svm的核心思想吧,具体数学表达如下所示:
m
i
n
:
f
(
x
)
min:f(x)
min:f(x)
s
.
t
.
h
j
(
x
)
=
0
,
j
=
1
,
2...
p
s.t. h_{j}(x)=0,j=1,2...p
s.t.hj(x)=0,j=1,2...p
g
k
(
x
)
⩽
0
,
k
=
1
,
2...
q
g_{k}(x)\leqslant 0, k=1,2...q
gk(x)⩽0,k=1,2...q
对上述进行拉朗操作转为无约束条件的优化问题,如下:
L
(
x
,
λ
,
β
)
=
f
(
x
)
+
∑
j
=
1
p
λ
j
h
j
(
x
)
+
∑
k
=
1
q
β
k
g
k
(
x
)
L(x,\lambda, \beta)=f(x)+\sum_{j=1}^{p}\lambda_{j}h_{j}(x)+\sum_{k=1}^{q}\beta_kg_k(x)
L(x,λ,β)=f(x)+∑j=1pλjhj(x)+∑k=1qβkgk(x)
此时,为了上述目标函数进行拉朗后能求得最优解,需要满足如下条件(KKT):
1.
L
(
a
,
b
,
x
)
对
x
求导为
0
1. L(a,b,x)对x求导为0
1.L(a,b,x)对x求导为0
$2.h_{j}(x)=0 $
3.
β
k
g
k
(
x
)
=
0
3.\beta_k g_k(x)=0
3.βkgk(x)=0
$4.\beta_k \geqslant 0 $
对于上述的KKT,各人感觉最有趣的地方在于第三项,因为
g
k
(
x
)
⩽
0
g_k(x)\leqslant 0
gk(x)⩽0,但是又有上述的3条件,那就是说要不
g
k
(
x
)
=
0
g_k(x)=0
gk(x)=0,要不
β
k
=
0
\beta_k=0
βk=0,这也就是SVM的核心地方吧,如果
β
k
=
0
\beta_k=0
βk=0表明训练样本对目标函数没有影响,如果
g
k
(
x
)
=
0
g_k(x)=0
gk(x)=0,则此时的样本处在最大间隔边界,因此,决定svm算法的是边界附近的样本。
- 核函数: 当数据在平面内不能进行划分时,可以通过将数据映射到更高的可分维度空间,而且通过核函数可以
2.2 原理推导
硬间隔平面的SVM算法: 假设存在超平面(w,b)可以使得所以训练样本正确分类,将平面结果通过sign函数进行转换,则有存在如下等式:
w T x i + b ⩾ + 1 , y i = + 1 w^Tx_{i}+b \geqslant +1, y_i = +1 wTxi+b⩾+1,yi=+1
w T x i + b ⩽ − 1 , y i = − 1 w^Tx_i+b\leqslant-1,y_i=-1 wTxi+b⩽−1,yi=−1
- 选取上面两个平面到平面 w T x + b = 0 w^Tx+b=0 wTx+b=0的距离之和为:
r = 2 ∣ ∣ w ∣ ∣ r=\frac{2}{||w||} r=∣∣w∣∣2
- 因此上面的问题可以转化为如下数学公式:
$\underset{w,b}{max}\frac{2}{||w||} $
s . t : y i ( w T x i + b ) ⩾ 1 , i = 1 , 2... s.t: y_i(w^Tx_i+b)\geqslant 1, i=1,2... s.t:yi(wTxi+b)⩾1,i=1,2...
- 为了求解方便将最大值转为求最小值:
m i n w , b 1 2 ∣ ∣ w ∣ ∣ 2 \underset{w,b}{min}\frac{1}{2} ||w||^2 w,bmin21∣∣w∣∣2
s . t : y i ( w T x i + b ) ⩾ 1 , i = 1 , 2... s.t: y_i(w^Tx_i+b)\geqslant 1, i=1,2... s.t:yi(wTxi+b)⩾1,i=1,2...
- 上式为一个凸的二次规划问题,有很多种方法进行求解,下面介绍svm官方的求解过程,拉格朗日乘子法,由于是不等式的约束优化问题,为了求得最优解,需要满足KKT条件:
$L(w,b,\alpha)=\frac{1}{2}||w||2+\sum_{i=1}{m}\alpha_i(1-y_i(w^Tx_i+b)) $
KKT条件( f ( x i ) = w T x i + b ) f(x_i)=w^Tx_i+b) f(xi)=wTxi+b):
α i ⩾ 0 \alpha_i \geqslant0 αi⩾0
y i f ( x i ) − 1 ⩾ 0 y_if(x_i)-1\geqslant0 yif(xi)−1⩾0
α i ( y i f ( x i ) − 1 ) = 0 \alpha_i(y_if(x_i)-1) =0 αi(yif(xi)−1)=0
其中 α = ( α i , α 2 ; . . . . . α m ) \alpha=(\alpha_i,\alpha_2;.....\alpha_m) α=(αi,α2;.....αm), 令 L ( w , b , α ) L(w,b,\alpha) L(w,b,α)对w,b进行求导为零可得:
$w = \sum_{i=1}^{m}\alpha_iy_ix_i $
$0=\sum_{i=1}^{m} \alpha_iy_i $
- 将上式的结果加入到拉格朗日乘子公式中,则:
L ( α ) = 1 2 ∣ w ∣ T ∣ w ∣ + ∑ i = 1 m α i − ∑ i = 1 m α i y i ( ∑ j = 1 m α j y j x j T ) x i L(\alpha)=\frac{1}{2}|w|^T|w| + \sum_{i=1}^{m}\alpha_i-\sum_{i=1}^{m}\alpha_iy_i(\sum_{j=1}^{m}\alpha_jy_jx_j^T)x_i L(α)=21∣w∣T∣w∣+∑i=1mαi−∑i=1mαiyi(∑j=1mαjyjxjT)xi
L ( α ) = ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α i y i y j x i T x j L(\alpha)=\sum_{i=1}^{m}\alpha_i-\frac{1}{2}\sum_{i=1}^{m}\sum_{j=1}^{m}\alpha_i\alpha_iy_iy_jx_i^Tx_j L(α)=∑i=1mαi−21∑i=1m∑j=1mαiαiyiyjxiTxj
- 因此上式的公式中只要求出参数 α \alpha α就可以求出参数 w w w,再通过函数 f ( x ) = w T x + b f(x)=w^Tx+b f(x)=wTx+b就可以求出b
- 软间隔SVM算法: 对于上述的软间隔svm算法,在现实任务中样本空间和特征空间如果不是线性可分的,此时很难找到一个核函数将样本进行维度的变化,即使找到了这样一个核函数也很难断定是不是由于过拟合而导致的,解决这个问题的方法就是引入软间隔平面,大致的思想就是允许一定的样本不满足约束条件,这样就能更好的进行样本划分,具体的表达式如下所示:
m i n w , b 1 2 ∣ ∣ w ∣ ∣ 2 + c ∑ i = 1 m l 0 / 1 ( y i ( x T x i + b ) − 1 ) , 其中 l 0 / 1 ( z ) 为 0 / 1 损失函数 , 当 z 小于 0 时为 1 ,否则为 0 (这样就可以代表某些样本不满足条件) \underset{w,b}{min}\frac{1}{2} ||w||^2 + c\sum_{i=1}^{m}l_{0/1}(y_i(x^Tx_i+b)-1), 其中l_{0/1}(z)为0/1损失函数,当z小于0时为1,否则为0(这样就可以代表某些样本不满足条件) w,bmin21∣∣w∣∣2+c∑i=1ml0/1(yi(xTxi+b)−1),其中l0/1(z)为0/1损失函数,当z小于0时为1,否则为0(这样就可以代表某些样本不满足条件)
- 由于上述得损失函数为不可凸时,通过需要通过一个替代的函数并且这个替代函数需要于其具有相同的上界,此时就可以通过求解这个相同上界且为凸的替代函数进行求解,常用的 l 0 / 1 l_{0/1} l0/1替代函数如下:
h i n g e 损失: l h i n g e ( z ) = m a x ( 0 , 1 − z ) hinge损失:l_{hinge}(z)=max(0,1-z) hinge损失:lhinge(z)=max(0,1−z)
指数损失: l e x p ( z ) = e x p ( − z ) 指数损失:l_{exp}(z)=exp(-z) 指数损失:lexp(z)=exp(−z)
对数损失: l l o g ( z ) = l o g ( 1 + e x p ( − z ) ) 对数损失:l_{log}(z) = log(1+exp(-z)) 对数损失:llog(z)=log(1+exp(−z))
- 对上述的表达式,如果采用hinge损失,则可以改写为:
m i n w , b 1 2 ∣ ∣ w ∣ ∣ 2 + c ∑ i = 1 m m a x ( 0 , 1 − y i ( w T x i + b ) ) \underset{w,b}{min}\frac{1}{2} ||w||^2 + c\sum_{i=1}^{m}max(0, 1-y_i(w^Tx_i+b)) w,bmin21∣∣w∣∣2+c∑i=1mmax(0,1−yi(wTxi+b))
- 对于上述公式引入松弛的概念 e i ⩾ 0 e_i \geqslant0 ei⩾0,则可以改写为:
m i n w , b 1 2 ∣ ∣ w ∣ ∣ 2 + c ∑ i = 1 m e i \underset{w,b}{min}\frac{1}{2} ||w||^2 + c\sum_{i=1}^{m}e_i w,bmin21∣∣w∣∣2+c∑i=1mei
s . t : y i ( w T x i + b ) ⩾ 1 − e i s.t: y_i(w^Tx_i+b)\geqslant 1-e_i s.t:yi(wTxi+b)⩾1−ei
s . t : e i ⩾ 0 , i = 1 , 2 , 3 , . . . . m s.t: e_i \geqslant 0, i = 1,2,3,....m s.t:ei⩾0,i=1,2,3,....m
- 和硬间隔同样的求解方法,对其进行拉朗变换,则:
$L(w,b,\alpha, e, u)=\frac{1}{2}||w||^2+ c\sum_{i=1}{m}e_i+\sum_{i=1}{m}\alpha_i(1-e_i-y_i(wTx_i+b))-\sum_{i=1}{m}u_ie_i $
其中 a i ⩾ 0 , u i ⩾ 0 是拉格朗日乘子: a_i \geqslant 0 , u_i \geqslant 0是拉格朗日乘子: ai⩾0,ui⩾0是拉格朗日乘子:
- 对上述公式中的各个参数进行求导并并其为0可得:
L ( α ) = ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α i y i y j x i T x j L(\alpha)=\sum_{i=1}^{m}\alpha_i-\frac{1}{2}\sum_{i=1}^{m}\sum_{j=1}^{m}\alpha_i\alpha_iy_iy_jx_i^Tx_j L(α)=∑i=1mαi−21∑i=1m∑j=1mαiαiyiyjxiTxj
s . t : ∑ i = 1 m a i y i = 0 , s.t: \sum_{i=1}^{m}a_iy_i=0, s.t:∑i=1maiyi=0,
s . t : 0 ⩽ a i ⩽ c , i = 1 , 2 , 3 , . . . m s.t: 0 \leqslant a_i \leqslant c, i = 1,2,3,...m s.t:0⩽ai⩽c,i=1,2,3,...m
- 同样,软间隔的kkt条件如下:
$\alpha_i \geqslant0, u_i \geqslant 0 $
y i f ( x i ) − 1 + e i ⩾ 0 y_if(x_i)-1 + e_i\geqslant0 yif(xi)−1+ei⩾0
α i ( y i f ( x i ) − 1 + e i ) = 0 \alpha_i(y_if(x_i)-1+e_i) =0 αi(yif(xi)−1+ei)=0
$e_i \geqslant 0, u_ie_i = 0 $
- 对于上述的KKT条件,对于任意的样本 ( x i , y i ) (x_i, y_i) (xi,yi),总有 a i = 0 或者 y i f ( x i ) = 1 − e i a_i=0或者y_if(x_i)=1-e_i ai=0或者yif(xi)=1−ei,如果 a i = 0 , 则该样本不会对 f ( x ) 有任何的影响,如果 a i > 0 ,则必有 y i f ( x i ) = 1 − e i a_i=0,则该样本不会对f(x)有任何的影响,如果a_i > 0 ,则必有y_if(x_i)=1-e_i ai=0,则该样本不会对f(x)有任何的影响,如果ai>0,则必有yif(xi)=1−ei,则此时该样本恰在最大间隔边界上为支持向量,
- 因此,可以得出采用hinge损失函数保持了其稀疏性
- 对于上述的 L ( α ) L(\alpha) L(α)函数的求解方法,采用的是smo算法,其基本的思想就是先挑选两个变量 α 1 , α 2 \alpha_1, \alpha_2 α1,α2然后再固定其它的变量 α i \alpha_i αi,上述就变成了一个两个变量的二次规划问题,对于这个问题的求解就比较容易了,具体的在不断的更新 α i , b i \alpha_i,b_i αi,bi就可以求出最优的参数
🔍 3. 代码实践
3.1 svm分类
我们通过莺尾花的监督分类数据集来实践svm分类,具体的代码如下所示:
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
# 加载iris数据集
iris = datasets.load_iris()
X, y = iris.data, iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建SVM分类器实例
svm_clf = SVC(kernel='linear') # 可以选择不同的核函数,如'rbf', 'poly'
# 训练模型
svm_clf.fit(X_train, y_train)
# 在测试集上进行预测
y_pred = svm_clf.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"准确率: {accuracy:.2f}")
然后,我们使用str.split方法将’c’列中的字符串按逗号分割,并设置expand=True来将分割后的列表转换为单独的列:
df = df.str.split(',', expand=True)
0 1 2
0 a b c
1 b c NaN
2 d e NaN
# 接着,我们使用stack方法将列转换为行,创建一个层次化索引:
df = df.stack()
a b
1 2 a 0
2 b 1
3 c 2
2 3 b 0
3 4 d 0
4 e 1
dtype: object
3.2 svm回归
svm算法除了能够做分类算法之外,还可以用来做回归算法,具体的代码如下所示:
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.svm import SVR
from sklearn.metrics import mean_squared_error, r2_score
# 生成模拟回归数据
X, y = make_regression(n_samples=100, n_features=1, noise=0.4, random_state=42)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建SVR回归模型实例
svr_model = SVR(kernel='rbf') # 可以选择不同的核函数,如'linear', 'poly', 'sigmoid'
# 训练模型
svr_model.fit(X_train, y_train)
# 在测试集上进行预测
y_pred = svr_model.predict(X_test)
# 计算MSE和R²
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"均方误差(MSE): {mse:.2f}")
print(f"R²分数: {r2:.2f}")
🔍 4. 注意事项
- SVM是分类、回归算法,在小数据集上,效果相对较好;
- SVM分类算法的思想是在空间中找到一个超平面 ( w T x + b = 0 ) (w^Tx+b=0) (wTx+b=0)能够将各类数据进行类别划分,而这个超平面由法向量参数 w = ( w 1 , w 2 , w 3 . . . . . . ; w d ) w=(w_{1},w_{2}, w_{3}......;w_{d}) w=(w1,w2,w3......;wd)和位移项b决定;
- 个人理解:为了得到最优参数w,b,SVM算法将超平面弱化为寻找与其平行的两个超平面的最大距离,也可以理解为与其平行的两个超平面各自到超平面 ( w T x + b = 0 ) (w^Tx+b=0) (wTx+b=0)的距离之和r,而两个平行平面之间的距离可以通过点到平面的距离间接的得出,因此,可以得出最大距离r时的参数w,b为最优参数;
- 当数据集在某个维度空间中线性不可分时,可以通过核函数映射到更高能进行划分的维度进行线性划分;
- 对于svm个人感觉其实和逻辑回归很像,都是将平面 ( w T x + b ) (w^Tx+b) (wTx+b)的结果通过某个函数进行输出,逻辑回归是通过sigmod函数来输出概率得到分类结果,而svm是通过sign函数输出分类结果;
- svm的间隔平面有硬间隔和软间隔两种形态,表示的意义是否能允许对样本进行错误的分类;
- 核参数的选择方法:当训练样本核数据比较多时,各个核的模型结果差距不大,当情况1:当训练集不大,feature比较多的时候,用线性的核。因为多feature的情况下就已经可以给线性的核提供不错的variance去fit训练集。情况2:当训练集相对可观,而feature比较少,用非线性的核。因为需要算法提供更多的variance去fit训练集。情况3:feature少,训练集非常大,用线性的核。因为非线性的核需要的计算量太大了。而庞大的训练集,本身就可以给非线性的核提供很好的分类效果;
- svm中的松弛因子 ξ i \xi_i ξi是允许分类器存在一定的错误分类,但是最大化了间隔平面
- svm中惩罚因子C表示你对离群值的重视程度,如果C越大表示越不想丢弃,因此,当样本不平衡是可以调节该系数来处理样本不平衡问题;
🔍 5. 总结
SVM是一种强大的分类和回归算法,它通过最大化决策边界的宽度来提高模型的泛化能力。scikit-learn提供了易于使用的SVM实现,支持多种核函数。通过本博客的代码示例,我们学习了如何创建SVM模型,进行训练、预测和评估。希望这篇博客能够帮助你更好地理解SVM模型,并将其应用于实际的机器学习问题中。