1.算法简介
定义:给定d个属性描述示例,其中是在第i个属性上的取值,线性模型就是通过属性的线性组合来进行预测:,一般用向量形式写成:,其中,w和b学得之后,模型就得以确定。
而线性回归模型是在给定数据集(其中,,),利用线性模型试图学得 ,使得函数.像这样有d个属性描述的线性函数,也被称为“多元线性回归”(multivariate linear regression)。
为了确定中的w和b,就要利用预估值()与实际值()之间的差值。当和之间的差值越小,则认为模型越好。为评价预估值与实际值的差别,可以利用均方误差来度量。使用均方误差的原因:有十分好的几何意义,对应了常用的欧式距离。在线性回归中,就是找到一个直线,使得所有样本到直线的欧式距离最小。
当均方误差越小时,也即模型越贴合实际数据。所以有了均方误差最小化,即
式1
1)最小二乘法
基于均方误差最小化进行模型求解的方法称为“最小二乘法”(least square method)。从几何意义上进行表述:最小二乘法就是试图找到一条直线,使得所有样本到直线上的欧式距离之和最小。
求解w和b使得
最小化的过程,称为线性回归模型的最小二乘法的“参数估计”。对分别求w和b的导数,得到
令式1和式2为0可得到w和b的最优解:
式6
把上述公式推理过程用向量形式重新写一遍,则有如下形式:
,,
则的形式可以写成 式7;
令,对求导得到:
令 式8 为0,可得到最优解的闭式解,但由于涉及到矩阵逆的计算,比单变量情形要复杂一些。
当 为满秩矩阵(full-rank matrix)或者正定矩阵(positive definite matrix)时,可使用正规方程法,直接求得闭式解。即令 式8 为0可得:
式9,
其中是矩阵的逆矩阵。
但一般 不能满足满秩矩阵或者正定矩阵的条件,此时可使用梯度下降法。
2)梯度下降(gradient descent)
梯度下降核心内容是对自变量进行不断的更新(针对w和b求偏导),使得目标函数不断逼近最小值的过程
梯度下降的迭代更新:
可得到梯度下降迭代过程,即:
3)解决线性回归过拟合的方法:
L2正则化(Rideg/岭回归):缩小模型参数。
4)解决线性回归欠拟合的方法:
5)线性回归的优缺点
优点
缺点
2、代码实例:
实现线性回归内部的核心函数,并给出使用实例
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
class LinearRegressionMy(object):
def __init__(self,learning_rate,max_iter=1000,seed=None):
# seed( ) 用于指定随机数生成时所用算法开始的整数值。
# 1.如果使用相同的seed( )值,则每次生成的随即数都相同;
# 2.如果不设置这个值,则系统根据时间来自己选择这个值,生成自己的种子,此时每次生成的随机数因时间差异而不同。
# 3.设置的seed()值仅一次有效
np.random.seed(seed)
self.lr=learning_rate
self.max_iter=max_iter
self.loss_arr=[]
self.theta=[[np.random.normal(1,0.1)],[np.random.normal(1,0.1)]]
def fit(self,X,y):
"""模型训练"""
self.X=X
self.y=y
self.m=y.size
for i in np.arange(self.max_iter):
self.theta=self.calc_gradient()
self.loss_arr.append(self.loss(self.X,self.y,self.theta))
def loss(self,X,y,theta=[[0],[0]]):
"""计算经验损失"""
m = y.size
h = X.dot(theta)
J = 1.0 / (2 * m) * (np.sum(np.square(h - y)))
return J
def calc_gradient(self):
"""计算梯度"""
h=self.X.dot(self.theta) # 计算假设值
# # 梯度递减,注意1/m, 请思考为什么要用1/m??
self.theta=self.theta-self.lr*(1.0/self.m*(self.X.T.dot(h-self.y)))
return self.theta
def _func(self,X,theta):
"""模型函数"""
return X.dot(theta)
def predict(self,x=None):
"""预测"""
if x is None:
print('输入为空')
return None
y_pred=self._func(x,self.theta)
return y_pred
if __name__ == '__main__':
# data generation
np.random.seed(272)
data_size = 100
x = np.random.uniform(low=1.0, high=10.0, size=data_size)
y = x * 20 + 10 + np.random.normal(loc=0.0, scale=10.0, size=data_size)
# plt.scatter(x, y, marker='.')
# plt.show()
# train / test split
shuffled_index = np.random.permutation(data_size)
x = x[shuffled_index]
y = y[shuffled_index]
split_index = int(data_size * 0.7)
x_train = x[:split_index]
y_train = y[:split_index]
x_test = x[split_index:]
y_test = y[split_index:]
# 生成模型,并fit训练
linear2=LinearRegressionMy(0.01,1500,18)
X_train=np.c_[np.ones(x_train.shape[0]),x_train]
Y_train=np.c_[y_train]
linear2.fit(X_train,Y_train)
# 预测
print(linear2.theta)
X_test=np.c_[np.ones(x_test.shape[0]),x_test]
print(X_test.shape)
y_pred=linear2.predict(X_test)
print(y_pred)
plt.scatter(x_test, y_test, marker='.')
plt.plot(x_test, y_pred, c='red')
plt.show()
LR回归是在线性回归模型的基础上,使用函数,将线性模型 的结果压缩到 之间,使其拥有概率意义。可以理解为,在求取输入空间到输出空间的非线性函数映射。 其本质仍然是一个线性模型。
- 逻辑斯蒂分布
设X是连续随机变量,X服从逻辑斯蒂分布是指X具有下列的分布函数和密度函数:
上式中,μ 表示位置参数,γ>0为形状参数。图形参见【机器学习】逻辑斯蒂回归(Logistic Regression)详解
- 从逻辑斯蒂分布 到 逻辑斯蒂回归模型
分类算法都是求解,而逻辑斯蒂回归模型,就是用当 时的逻辑斯蒂分布的概率分布函数:函数,对进行建模,所得到的模型,对于二分类的逻辑斯蒂回归模型有:
(式3)
(式4)
一个事件的几率(odds):指该事件发生与不发生的概率比值,若事件发生概率为pp,
那么该事件的对数几率(log odds或者logit)就是: (式6)
那么,对逻辑回归而言,Y=1的对数几率就是: (式7)
也就是说,输出Y=1的对数几率是由输入x的线性函数表示的模型,这就是 逻辑回归模型。当 w⋅x的值越接近正无穷,P(Y=1|x) 概率值也就越接近1.
另外,通过sigmoid函数的变化,我们也可以看到:
可以变化成: (式9)
可以看到(式7)和(式9)是一样的。
由此可见sigmoid函数实际上就是在用线性回归模型的预测结果去逼近真实标记的对数几率。这也是,逻辑回归被称为对数几率回归的原因。
使用对数几率函数的优点:
1.直接对分类可能性进行建模,无需事先假设数据分布,这样避免了假设分布不准确所带来的问题;
2.不仅预测出类别,而且可得到近似概率预测,这对许多需要利用概率辅助决策的任务很有用;
3.对数几率函数是任意阶可导的凸函数,有很好的的数学特性,现有的许多数值优化算法都可以直接求取最优解。
模型的数学形式确定后,剩下就是如何去求解模型中的参数。在统计学中,常常使用极大似然估计法来求解,即找到一组参数,使得在这组参数下,我们的数据的似然度(概率)最大。
似然函数: (式11)
对数似然函数为: (式12)
实际上,对数似然损失在单个数据点上的定义为:
(式13)
如果取整个数据集上的平均对数似然损失,我们恰好可以得到:
即在逻辑回归模型中,我们最大化似然函数和最小化对数似然损失函数实际上是等价的。
梯度的数学求解:
对logistic Regression来说,一般的梯度下降算法如下:
,这里的k是指w迭代的第k轮。就如第一部分中线性回归的迭代一样,一步步求得近似解。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import minimize
from scipy.special import expit
from sklearn.preprocessing import PolynomialFeatures
class LogisticModel(object):
def __init__(self,alpha,init_theta,max_iter,grad='gradient'):
"""
:param alpha:
:param init_theta:
:param lamda:
:param max_iter:
"""
self.alpha = alpha
self.max_iter = max_iter
self.theta=init_theta
self.loss_arr=[]
self.gradientType=grad
def loss(self,X,y,theta,reg):
"""计算损失值"""
m = y.size
# 假设函数
h = expit(X.dot(theta))
J = -(1.0 / m) * (np.log(h).T.dot(y) + np.log(1 - h).T.dot(1 - y))+(reg / (2.0 * m)) * np.sum(np.square(theta[1:]))
if np.isnan(J[0]):
return (np.inf)
return J[0]
def gradientDescent(self,X,y,reg):
m=y.size
# 假设函数
h=expit(X.dot(self.theta))
self.theta=self.theta.reshape(-1,1)-(self.alpha*(1.0/m)*X.T.dot(h.reshape(-1,1)-y))+(reg/m)*np.r_[[[0]],self.theta[1:].reshape(-1,1)]
return self.theta
def fit(self,X,y,reg):
self.X=X
self.y=y
self.lamda=reg
if self.gradientType is 'gradient':
for k in range(self.max_iter):
self.theta=self.gradientDescent(self.X,self.y,self.lamda)
self.loss_arr.append(self.loss(self.X,self.y,self.theta,self.lamda))
def predict(self, X=None, threshold=0.5):
""" 预测 """
if type(X)is not np.ndarray :
print('输入为空')
return None
p = expit(X.dot(self.theta)) >= threshold
# print('pred:',p)
return (p.astype('int'))
if __name__ == '__main__':
logModel=LogisticModel(0.1,init_theta,3000)
但由于J(w)是关于参数w的高阶可导连续的凸函数,也可以使用牛顿算法,或者拟牛顿算法,下面是一个关于BFGS的算法:
一般的梯度向量化表示:
当模型的参数过多时,很容易遇到过拟合的问题。而正则化是结构风险最小化的一种实现方式,通过在经验风险上加一个正则化项,来惩罚过大的参数来防止过拟合。
在优化目标中加入正则项,通过惩罚过大的参数来防止过拟合:
J(w)=>J(w)+λ||w||p
p=1或者2,表示L1 范数和 L2范数,这两者还是有不同效果的。
带有正则化项的损失函数:
(请注意图中正则化项的j,j是从1开始计算 的)
带有正则化项的梯度计算:
L1范数:是指向量中各个元素绝对值之和,也有个美称叫“稀疏规则算子”(Lasso regularization)。那么,参数稀疏 有什么好处呢?
一个关键原因在于它能实现 特征的自动选择。一般来说,大部分特征 xi和输出 yi之间并没有多大关系。在最小化目标函数的时候考虑到这些额外的特征 xi,虽然可以获得更小的训练误差,但在预测新的样本时,这些没用的信息反而会干扰了对正确 yi的预测。稀疏规则化算子的引入就是为了完成特征自动选择的光荣使命,它会学习地去掉这些没有信息的特征,也就是把这些特征对应的权重置为0。去除无用的特征项。
L2范数:它有两个美称,在回归里面,有人把有它的回归叫“岭回归”(Ridge Regression),有人也叫它“权值衰减”(weight decay)。
它的强大之处就是它能 解决过拟合 问题。我们让 L2 范数的规则项 ||w||2最小,可以使得 w的每个元素都很小,都接近于0,但与 L1 范数不同,它不会让它等于0,而是接近于0,这里还是有很大区别的。而越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象。
LR 损失函数为什么用极大似然函数?
因为我们想要让 每一个 样本的预测都要得到最大的概率,
即将所有的样本预测后的概率进行相乘都最大,也就是极大似然函数.对极大似然函数取对数以后相当于对数损失函数,
由上面 梯度更新 的公式可以看出,
对数损失函数的训练求解参数的速度是比较快的,
而且更新速度只和x,y有关,比较的稳定,为什么不用平方损失函数
如果使用平方损失函数,梯度更新的速度会和 sigmod 函数的梯度相关,sigmod 函数在定义域内的梯度都不大于0.25,导致训练速度会非常慢。
而且平方损失会导致损失函数是 theta 的非凸函数,不利于求解,因为非凸函数存在很多局部最优解。什么是极大似然?请看简述极大似然估计
虽然逻辑回归能够用于分类,不过其本质还是线性回归。它仅在线性回归的基础上,在特征到结果的映射中加入了一层sigmoid函数(非线性)映射,即先把特征线性求和,然后使用sigmoid函数来预测。
这主要是由于线性回归在整个实数域内敏感度一致,而分类范围,只需要在[0,1]之内。而逻辑回归就是一种减小预测范围,将预测值限定为[0,1]间的一种回归模型。逻辑曲线在z=0时,十分敏感,在z>>0或z<<0处,都不敏感,将预测值限定为[0,1]。
从梯度更新视角来看,为什么线性回归在整个实数域内敏感度一致不好。
线性回归和LR的梯度更新公式是一样的,如下:
唯一不同的是假设函数,,对于LR而言,,那么梯度更新的幅度就不会太大。而线性回归在整个实数域上,即使已经分类正确的点,在梯度更新的过程中也会大大影响到其它数据的分类,就比如有一个正样本,其输出为10000,此时梯度更新的时候,这个样本就会大大影响负样本的分类。而对于LR而言,这种非常肯定的正样本并不会影响负样本的分类情况!
逻辑回归跟最大熵模型没有本质区别。逻辑回归是最大熵对应类别为二类时的特殊情况
指数簇分布的最大熵等价于其指数形式的最大似然。
二项式分布的最大熵解等价于二项式指数形式(sigmoid)的最大似然;
多项式分布的最大熵等价于多项式分布指数形式(softmax)的最大似然。
对数几率函数:
是一种“Sigmoid函数”,它将值转化为接近0或1的y值,并且在其输出值在附近变化很陡。而 Sigmoid本质上是Softmax的特殊情况,Softmax的二分类情况就是Sigmoid。
Softmax的表达形式:
在而分类的情况下,
参考资料:
1.https://zhuanlan.zhihu.com/p/53979679 线性回归详解
2.https://www.cnblogs.com/geo-will/p/10468253.html 线性回归简介
3.https://blog.csdn.net/zouxy09/article/details/20319673
4.https://blog.csdn.net/qq_32742009/article/details/81839071
5.https://blog.csdn.net/qq_32742009/article/details/81516140
6。https://blog.csdn.net/zouxy09/article/details/24971995 机器学习中的范数规则化之(一)L0、L1与L2范数
7.https://blog.csdn.net/ccblogger/article/details/81739200 详解逻辑回归(LR)计算过程