问题描述
现在有一份数据, xi 是数据的特征,y是分类0或1,这是一个二分类问题。我们希望训练一个模型,当有新的数据的时候,判断数据的分类是0,还是1。
x1 | x2 | y |
---|---|---|
-0.017612 | 14.053064 | 0 |
-1.395634 | 4.662541 | 1 |
-0.752157 | 6.538620 | 0 |
-1.322371 | 7.152853 | 0 |
0.423363 | 11.054677 | 0 |
0.406704 | 7.067335 | 1 |
0.667394 | 12.741452 | 0 |
-2.460150 | 6.866805 | 1 |
0.569411 | 9.548755 | 0 |
-0.026632 | 10.427743 | 0 |
… | … | … |
这里的数据只有两个特征值,我们可以在二维图像上画出来。如下图,如果只有两个特征,而数据是线性可分的就可以用一条直线将数据划分开来。如果不止两个特征呢?如果有更多的特征,比如有k个,那么在k维的空间中线性可分的数据也会有一个超平面可以将数据分割开来。
那么这个超平面可以表示为
z=w1x1+w2x2+w3x3+....+wkxk+b
,如果用向量表示则可以写成
z=wTx+b
预备知识
sigma函数
我们需要一个函数输出0和1来预测类别,理想状态下单位阶跃函数符合这个需求,
但是后续的计算需要这个函数是一个可微的函数,显然单位阶跃函数不符合这个需求 ,我们希望能找到一个近似单位阶跃函数并且连续可微的函数,simga函数有很好的性质符合我们的需求。
当输入z=0时,返回0.5,当z越大, σ 逼近1,当z减小 σ 逼近0,
![sigma 两种尺度下的sigma函数,当尺度足够大时,sigma看起来就像阶跃函数](https://i-blog.csdnimg.cn/blog_migrate/3ef35375404f441bd887859f93fdca4e.jpeg)
两种尺度下的sigma函数,当尺度足够大时,sigma看起来就像阶跃函数
σ(z)=11+e−z
的输入为z,而
z=wTx
,那么现在问题就变成,怎么找到最优的
w
,这里我们把
将
z=wTx
带入
σ(z)
得到
上式可以转换为
若将 y 视为样本 x 作为正例的可能性,则 1-h_w(x) 是其反例可能性,两者的比值 hw(x)1−hw(x) ,称为”几率” (odds) ,反映了 m 作为正例的相对可能性.对几率取对数则得到
“对数几率” (log odds,亦称 logit), ln(hw(x)1−hw(x))
由此可看出,上式实际上是在用线性回归模型的预测结果去逼近,真实标记的对数几率,因此,其对应的模型称为”对数几率回归” (logistic regression,亦称 logit regression) .特别需注意到,虽然它的名字是”回归”,但 实际却是一种分类学习方法.这种方法有很多优点,例如它是直接对分类可能 性进行建模,无需事先假设数据分布?这样就避免了假设分布不准确所带来的 问题;它不是仅预测出”类别”,而是可得到近似概率预测,这对许多需利用概 率辅助决策的任务很有用;此外,对率函数是任意阶可导的凸函数,有很好的数学性质,现有的许多数值优化算法都可直接用于求取最优解.
若将式 (3.18) 中的 y 视为类 后验概率估计
p(y=1|x)
, 则
显然
于是可以通过极大似然法来估计w和b,对率回归模型最大化”对数似然” (loglikelihood)
好了我们现在的目标就是求得系数w使得 l(w) 最大。
基于最优化方法确定回归系数
梯度下降求最小值
现在我们使用最优化方法中的梯度下降法来寻找最优回归系数。梯度下降法的思想是:要找到某个函数的最小值,最好的方法是沿着该函数的某一点上减少最快的方向,及梯度方向寻找。
1.梯度
那么梯度怎么得到呢?增长最快的方向,在单变量的函数(如
f(x)=3x2+4x+1
这样的函数)上就是导数。但是我们的函数有n个变量,这时需要计算函数的偏导数,用
▽f(x1,x2)
表示偏导数。
2.梯度下降
一开始可以赋予
w
一个随机值,然后在每次迭代的时候将
回头看之前的似然函数
现在需要计算w的梯度。
那么现在w的更新过程可以写成 w=w−α1m∑(hw(xi)−yi)xi ,
实现
1.sigma函数
输入X是numpy.array类型数据,可以直接按照向量化来计算
def simgoid(X):
return 1.0 / (1.0 + exp(-X))
2.梯度上升
这里
w
初始化为1,
def gradAscent(dataSet,labels):
dataMat = mat(dataSet)
labelMat = mat(labels).transpose()
s = shape(dataMat)
weights = ones((s[1],1))
maxStep = 500
alpha = 0.001
for i in range(maxStep):
h = simgoid(dataMat*weights)
error = labelMat - h
weights = weights + alpha*dataMat.transpose()*error
return weights