1、逻辑回归简介
逻辑回归也叫对数几率回归,理解了线性回归,逻辑回归理解起来就容易多了。逻辑回归虽然名字叫做回归,但实际上却是一种分类学习方法。线性回归完成的是回归拟合任务,而对于分类任务,我们同样需要一条线,但不是去拟合每个数据点,而是把不同类别的样本区分开来。
2、假设函数
线性回归中预测函数为:
它的值域为R。
而我们需要的是个分类模型,对于二分类问题来说结果不是1(正例)就是0(负例),。怎么样实现在线性回归的基础上实现分类功能呢?我们知道线性回归的输出值为:
我们可以寻找一个假设函数将线性回归输出的值映射到0,1之间,如果>=0.5,则y=1,否则y=0。
我们发现有一个函数,叫做对数几率函数(logistic function):
它的图像如下:
对数几率函数是Sigmoid函数(形状为S型的函数)的重要代表,它的定义域为R,值域为(0,1)。把线性回归的输出值当做对数几率函数的输入值z,则输出值在0~1之间,刚好符合我们的要求。
则逻辑回归的假设函数为:
对于更直观的解释是:对于给定的输入x,表示该样本属于正例y=1的概率。
1.为什么逻辑回归又叫对数几率回归?
逻辑回归假设函数可以变形为:
是x属于正例的概率,则是x属于负例的概率,两者比值叫做几率(odds),表示x作为正例相对负例的可能性,取对数就叫对数几率。
2.也有其它值域为(0,1)的函数,为什么选择对数几率函数?
参考:https://blog.csdn.net/a1628864705/article/details/62233395
3、损失函数/代价函数
线性回归中我们采用的是平方误差:
但是当我们把
带入上式时,得到的是一个非凸函数(下面左图)
这意味着代价函数有许多局部最小值,这无疑影响了我们寻找全局最优解。
于是我们转换思路,既然是分类问题,那么我们可以对每个类别分别计算它们各自的损失。对于正例,预测值越接近1,损失越小;对于负例越接近0,损失越小。-log(x)函数正好满足以上情况,图像如下:
这样每个样本的损失计算公式为:
合并后(方便后面计算和书写):
则逻辑回归的代价函数计算公式为:
即为:
4、求最优解
求解使代价函数最小的参数θ,这里使用梯度下降法。
其梯度更新公式为:
其中:
除了梯度下降算法外,还有其它算法被用来求最优解,这些算法更加复杂和优越,而且不需要人工选择学习率,通常还更快。有共轭梯度,局部优化法,有限内存局部优化法。
5、多类别分类
前面讲的是二分类情况,当遇到多分类时怎么实现分类呢?
上面二图分别展示二分类和多分类,不同符号代表不同类别。
对于多分类,我们可以把它变为多个二分类问题
首先我们把class1当作正例,然后将其它所有类记为负例,训练得到。然后把class2当作正例,其它所有类当作负例,训练得到模型,依次类推。
做预测时,我们选择一个让最大的,即。
6、正则化
正则化用来解决过拟合问题。
1.什么是过拟合?
先看看下面这些图(回归问题):
第一个图,模型不能很好的拟合我们的原始数据,欠拟合;
第三个图,是个四次方的模型,过于强调拟合原始数据,过拟合。若给出一个新的值使之预测,它将表现很差。即泛化能力差;
中间的模型是比较合适的。
分类问题也存在这样的问题:
x的次数越高,或者说模型越复杂,拟合的越好,但预测能力可能变差,这就是过拟合。
2.如何解决过拟合?
a.正则化;
b.增加数据样本;
c.PCA、特征那选择等技术降维、去掉冗余特征;
d.提前结束训练;
这里我们讲使用正则化方法来解决过拟合问题。
3.什么是正则化?
回归问题中如果我们的模型是:
对我们结果影响最大的往往是高次项,那么我们所要做的就是减小高次项的系数和,从而减小高次项的影响。正则化就是保留所有特征,但是减小参数大小。
4.如何实现正则化?
我们知道,正则化是要减小参数,即对特征进行惩罚,但是我们并不知道惩罚哪些特征,也不知道惩罚的程度。我们可以放入代价函数中,让优化算法来选择。
在线性回归中,加入正则化的代价函数为:
为惩罚系数。
在逻辑回归中,加入正则化的代价函数为:
5.如何选择合适的惩罚系数?
若太大,那么所有系数都会趋近于0,这样容易造成欠拟合。至于如何选择合适的惩罚系数,这个我在网上找了下暂时没找到,我觉得可以用学习率的选择方法来选择。
7、正则化的逻辑回归
从上面我们可以知道,加入正则项的代价函数为:
使用梯度下降法,对代价函数求导,得其梯度更新方式为:
注意:
1.不参与其中的任何一个正则化。
2.使用梯度下降法一定要做Feature Scaling。
8、代码实现(python)
# -*- coding: utf-8 -*-
import numpy as np
from sklearn.datasets import load_breast_cancer #导入威斯康辛州乳腺癌数据
from sklearn import linear_model #导入sklearn库线性模型
class LogisticRegression:
penalty_coef = 0.5 #惩罚系数
learing_rate = 0.05 #学习率
num_iter = 300 #迭代次数
theta = [] #参数
#训练函数
def fit(self, X, y):
X = np.matrix(X) #转成矩阵
y = y.reshape(len(y),-1) #转成列的形式
y = np.matrix(y) #转成矩阵
m = X.shape[0] #样本数
X_0 = np.ones((len(X), 1)) #创建分量x0
X = np.hstack((X_0, X)) #加入分量x0到x中
#step 1.初始化参数为任意值,这里设为全0
self.theta = np.zeros((X.shape[1], 1)) #初始化参数
#step 2.求解梯度(注意:theta_0不参与任何一个正则化)
grad = (X.T * (sigmoid(X * self.theta) - y)) / m + self.penalty_coef / m * self.theta
grad[0,0] = grad[0,0] - self.penalty_coef / m * self.theta[0,0] #theta_0不参与正则化所以要减去一个正则项
#step 3.更新参数(同步更新)
self.theta = self.theta - self.learing_rate * grad
#step 4. 若达到指定迭代次数或收敛条件,训练结束,否则,继续执行step2、step3
for i in range(self.num_iter):
#求解梯度
grad = (X.T * (sigmoid(X * self.theta) - y)) / m + self.penalty_coef / m * self.theta
grad[0,0] = grad[0,0] - self.penalty_coef / m * self.theta[0,0]
#更新参数(同步更新)
self.theta = self.theta - self.learing_rate * grad
#看每次迭代更新参数后的代价函数值
first = np.sum((-y).T * np.log(sigmoid(X * self.theta)) - (1 - y).T * np.log(1 - sigmoid(X * self.theta))) / m
second = self.penalty_coef / (2 * m) * (self.theta[1:,:].T * self.theta[1:,:])
J = first + second
print(J)
#预测函数
def predict(self, test_x):
M_test_x = np.matrix(test_x)
x_0 = np.ones((len(M_test_x), 1)) #创建分量x0
M_test_x = np.hstack((x_0, M_test_x)) #加入分量x0到x中
result = (sigmoid(M_test_x * self.theta) >= 0.5) + 0 #预测结果,+0是把false/true转为0/1
return result
#对数几率函数
def sigmoid(x):
return 1 / (1 + np.exp(-x))
if __name__ == '__main__':
X, y = load_breast_cancer(return_X_y = True) #取出威斯康辛州乳腺癌数据
X = (X - np.mean(X, axis=0)) / np.std(X, axis = 0) #featrue scaling
#自己的模型结果
my_lr = LogisticRegression()
my_lr.fit(X,y)
estimate1 = my_lr.predict(X[-10:,:])
#sklearn库逻辑回归模型结果
lr = linear_model.LogisticRegression()
lr.fit(X,y)
estimate2 = lr.predict(X[-10:,:])
#打印输出,对比结果
for i in range(10):
print("实际值:",y[-10+i]," 估计值1:",estimate1[i,0],"估计值2:", estimate2[i])
参考:
《统计学习方法》李航
《机器学习》吴恩达
https://www.cnblogs.com/lianyingteng/p/7679825.html
https://blog.csdn.net/jk123vip/article/details/80591619
https://blog.csdn.net/a1628864705/article/details/62233395