赞
踩
在前面学习线性回归时,我们知道可以对一组测试数据来进行预测输出,线性回归模型能不能用来解决分类问题呢,答案是否定的,但是我们可以利用线性回归再配合辅助函数来构建分类器。逻辑回归是基于
S
i
g
m
o
i
d
Sigmoid
Sigmoid函数,这个函数有很明显的特点。
当
x
x
x>0时,
y
y
y>0.5,
x
x
x<0,时
y
y
y<0.5,并且
y
y
y值在左边区域1,右边趋于0。
S
i
g
m
o
i
d
Sigmoid
Sigmoid公式如下
g
(
z
)
=
1
1
+
e
−
z
(
1.1
)
g(z)=\frac{1}{1+e^{-z}}\quad\quad\quad(1.1)
g(z)=1+e−z1(1.1)
这里有一份已经分好类的数据集,不同颜色代表不同的类别,我么可以很明显的观察到在这两类中间存在这一条分割线,这条线在这里被称作决策边界。我们可以定义这条在决策边界的直线方程为
z
=
f
(
x
(
i
)
)
=
θ
1
x
1
(
i
)
+
θ
2
x
2
(
i
)
+
.
.
.
+
θ
j
x
j
(
i
)
(
1.2
)
z=f(x^{(i)})=\theta_1x_1^{(i)}+\theta_2x_2^{(i)}+...+\theta_jx_j^{(i)}\quad(1.2)
z=f(x(i))=θ1x1(i)+θ2x2(i)+...+θjxj(i)(1.2)
这里我用上标
i
i
i表示第
i
i
i个样本,用
j
j
j表示特征维度。虽然决策边界方程已经确定下来了,但是如何使用决策边界来做分类问题呢,根据我们高中所学的方程思想,在决策边界上的数据点对于1.2式的值会等于0,在决策边界上的数据点对于1.2式会大于0,对于决策边界下的数据点对于1.2式会小于0。若预测z值大于0为1类,z值小于0为0类,这样就很好的解决了二分类问题。目前的问题只需要将z值转化为0/1值
z
=
f
(
x
(
i
)
)
=
θ
T
X
(
1.3
)
z=f(x^{(i)})=\theta^TX\quad\quad\quad(1.3)
z=f(x(i))=θTX(1.3)
其中X是
m
∗
n
m*n
m∗n的矩阵
X
=
[
x
1
(
1
)
x
1
(
2
)
.
.
.
x
1
(
j
)
x
2
(
1
)
x
2
(
2
)
.
.
.
x
2
(
j
)
.
.
.
x
i
(
1
)
x
i
(
2
)
.
.
.
x
i
(
j
)
]
(
1.4
)
X=
观察上面的sigmoid辅助函数函数的特性。令p=g(z),它可以将z值转化为一个接近于0或1的p值,
p
=
1
1
+
e
−
z
(
1.5
)
p=\frac{1}{1+e^{-z}}\quad\quad(1.5)
p=1+e−z1(1.5)
根据上式1.5可以将p视为类后验概率估计P(y=1|x),由于类别标签不是1就是0,所以类别0的后验概率也可以得出(此句来自西瓜书p59,目前还未深究)
P
(
y
=
1
∣
x
)
=
p
P
(
y
=
0
∣
x
)
=
1
−
p
(
1.6
)
P(y=1|x)=p\quad\quad\quad P(y=0|x)=1-p\quad(1.6)
P(y=1∣x)=pP(y=0∣x)=1−p(1.6)
将公式1.6一般化
P
(
y
∣
x
)
=
{
p
if
y
=
1
1
−
p
if
y
=
0
(
1.7
)
P(y|x)=
分段函数不好计算,继续转换
P
(
y
∣
x
)
=
p
y
(
1
−
p
)
(
1
−
y
)
(
1.8
)
P(y|x)=p^y(1-p)^{(1-y)}\quad\quad(1.8)
P(y∣x)=py(1−p)(1−y)(1.8)
当然只是一个样本的类别后验概率,对于训练数据集中有m个数据样本,采用极大似然法计算整个样本的总后验概率
P
总
=
P
(
y
1
∣
x
1
)
P
(
y
1
∣
x
1
)
.
.
.
P
(
y
m
∣
x
m
)
=
∏
i
=
1
m
P
(
y
i
∣
x
i
)
(
1.9
)
P_总=P(y_1|x_1)P(y_1|x_1)...P(y_m|x_m)\\=\prod_{i=1}^mP(y_i|x_i)\quad\quad(1.9)
P总=P(y1∣x1)P(y1∣x1)...P(ym∣xm)=i=1∏mP(yi∣xi)(1.9)
由于1.9式中连乘容易造成结果下溢,常采用对数似然
l
n
(
P
总
)
=
∑
i
=
1
m
y
i
l
n
(
p
)
+
(
1
−
y
i
)
l
n
(
1
−
p
)
)
(
1.10
)
ln(P_总)=\sum_{i=1}^my_iln(p)+(1-y_i)ln(1-p))\quad(1.10)
ln(P总)=i=1∑myiln(p)+(1−yi)ln(1−p))(1.10)
得到式1.10后,我们就可以开始定义损失函数,损失函数是用来衡量模型预测值与真实值的差距,我们希望这种差距越小越好,式1.10中计算出来的结果是训练集总后验概率的极大似然,我们希望这个概率越大越好,与损失函数理念违背,加个负号后就与损失函数理念相符,所以这里的损失函数定义为
J
(
θ
)
=
−
l
n
(
P
总
)
=
∑
i
=
1
m
−
y
i
l
n
(
p
)
−
(
1
−
y
i
)
l
n
(
1
−
p
)
)
(
1.11
)
J(\theta)=-ln(P_总)=\sum_{i=1}^m-y_iln(p)-(1-y_i)ln(1-p))\quad(1.11)
J(θ)=−ln(P总)=i=1∑m−yiln(p)−(1−yi)ln(1−p))(1.11)
损失函数定义出来后,求解最佳参数的决策边界方程转化求解最佳参数
θ
\theta
θ使得损失函数值最小对这里求解最佳参数方法使用梯度下降法,所谓的梯度就是损失函数对各个参数的偏导向量,其求偏导有
α
J
α
θ
j
=
∑
i
=
1
m
(
p
−
y
i
)
x
i
\frac{\alpha J}{\alpha \theta_j}=\sum_{i=1}^{m}(p-y_i)x_i
αθjαJ=i=1∑m(p−yi)xi
利用线性回归中接受的梯度下降法求解最佳
θ
\theta
θ,其中
β
\beta
β时是学习率
θ
j
n
e
w
=
θ
j
o
l
d
−
β
α
J
o
l
d
α
θ
j
\theta_j^{new}=\theta_j^{old}-\beta\frac{\alpha J^{old}}{\alpha \theta_j}
θjnew=θjold−βαθjαJold
#导入科学计算包 from numpy import * #导入matplot第三方包 import matplotlib.pyplot as plt #读取文本文件,创建数据集 def loadDataSet(): #定义数据集,标签集 dataMat=[] labelMat=[] #打开文本文件 f=open("D:/学习资料\机器学习实战/《机器学习实战》源代码/machinelearninginaction/Ch05/testSet.txt") #存储数据集 for line in f.readlines(): lineArr=line.strip().split() #添加一列全为1的数据 dataMat.append([1.0,float(lineArr[0]),float(lineArr[1])]) labelMat.append(int(lineArr[2])) return dataMat,labelMat #定义sigmoid函数 def sigmoid(inx): return 1.0/(1+exp(-inx)) #计算梯度 def get_gent(data,label,theta,m): return dot(data.T,(sigmoid(dot(data,theta))-label)) #计算损失函数 def get_loss(data,label,theta,m): var=ones((m,1)) print(shape(var)) return -(label.T*log(sigmoid(dot(data,theta)))+(var-label).T*log(var-sigmoid(dot(data,theta)))) #梯度下降法 def gent_dense(data,label,alpha,epochs): #获取数据集形状 m,n=shape(data) # 初始化theta theta=ones((n,1)) #获取损失值 loss=get_loss(data,label,theta,m) #定义存储损失值列表 loss_list=list() # print(loss) loss_list.append(loss.tolist()[0][0]) # 获取梯度 gent=get_gent(data,label,theta,m) #迭代 for i in range(epochs): #获取新的参数 # print(shape(gent)) theta=theta-alpha*gent #获取梯度 gent=get_gent(data, label, theta, m) #获取损失值 # print(shape(theta)) loss=get_loss(data,label,theta,m) loss_list.append(loss.tolist()[0][0]) return theta,loss_list #绘图 def ploter(data,label,theta,loss_list,epochs): # # 设置中文 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False plt.plot(range(epochs+1),loss_list) plt.xlabel("迭代次数") plt.ylabel("损失函数值") plt.show() fig = plt.figure() # 创建一个1X1的绘图区域 ax = fig.add_subplot(111) x1=list() y1=list() x2=list() y2=list() x3=list() for i in range(len(data)): if label[i]==0: x1.append(data[i][1]) y1.append((data[i][2])) else: x2.append((data[i][1])) y2.append((data[i][2])) x3=data[i][0] plt.scatter(x1,y1,color='green') plt.scatter(x2, y2, color='red') # 创建一个等距离的一维数组,作为X轴的间隔 x = arange(-3.0, 3.0, 0.1) # 划分最佳直线方程 print(theta.tolist()[0]) y = (-theta.tolist()[0][0] - theta.tolist()[1][0] * x) / theta.tolist()[2][0] plt.plot(x,y) plt.show() #测试 if __name__=='__main__': data,label=loadDataSet() epchos=500 theta,loss_list=gent_dense(mat(data),mat(label).T,0.001,epchos) print(theta,loss_list) ploter(data,label,theta,loss_list,epchos)
损失函数图像,决策边界拟合图像如下
可以看出仍然有几个点预测错误,但是这个拟合出来的决策边界还是相当可靠的
求解最佳参数的方法不止有梯度下降法,还有牛顿法,BFGS等方法。
参考博客:https://zhuanlan.zhihu.com/p/44591359
参考书籍:《机器学习》周志华 《机器学习实战》Peter
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。