回归分析
线性回归
回归分析是一种统计学上分析数据的方法,目的在于了解两个或多个变量是否相关、相关方向与程度,并建立数学模型以便观察特定变量来预测研究者感兴趣的变量。更具体的来说,回归分析可以帮助人们了解在只有一个自变量变化时因变量的变化量。一般来说,通过回归分析我们可以由给出的自变量估计因变量的条件期望。
线性回归可以说是机器学习中最简单的模型,但是其实际地位很重要。先通过房价预测的例子来了解线性回归。
假设有一个房屋销售的数据如下
房屋面积(m^2) | 销售价钱(万元) |
---|---|
123 | 250 |
150 | 320 |
87 | 160 |
102 | 220 |
………. | ……….. |
我们用几何图表示出这样的数据
当我们有很多组这样的数据时,这些就是训练数据,我们希望学习一个模型,当有新的一个面积数据来到时,可以自动预测出销售价钱。也就是我们可以在这张图上用一条直线去尽量拟合这些数据,当有新的值来到时,可以用这条直线所对应的值去返回预测的价钱, 绿色的点就是我们所想要预测的点。当然,不是说线性回归就一定是一条直线,当变量x是一维的时候才是一条直线,而在高维时,是超平面 。
在这里先定义下数学符号,我们用$X=(x_{1}, x_{2}, x_{3},…,x_{n})^{T}$来表示输入数据矩阵,其中$x_{i}\in R^{p}$表示一个p维度长的数据样本,$y = (y_{1}, y_{2}, ….,y_{n}) \in R^{n}$表示数据的标签。
线性回归的模型可以表示为, 对于一个样本$x_{i}$,它的输出值是其特征的线性组合:
其中$w_{0}$称为截距,或者bias 。线性回归的目标是用预测结果尽可能地拟合目标label 。对于机器学习模型,需要定义一个损失函数(Loss function),用它来表示其与真实输出之间的误差, 从而评判模型的好坏。在这里定义如下的损失函数:
这个错误估计函数是去对$x^{i}$的估计值与真实值$y^{i}$差的平方和作为错误估计函数,前面乘上的1/2是为了在求导的时候,这个系数就不见了, 从而方便之后的求导计算。为了训练模型,去最小化误差 , 使其接近于0, 这里需要用到的方法称为梯度下降法 。先用张图表示:
梯度下降法,就是要一步步沿着梯度反向方向逐渐下降,从而走到局部甚至全局最小值。
梯度下降法是按以下流程逐渐进行的:
- 首先对$w$赋值, 这个值可以是随机的,也可以让其是个全零的向量。
- 改变$w$的值,使得$J(w)$按梯度下降的方向进行减少。这一步,就需要先求得每个参数的梯度,再通过梯度,逐渐改变其值。数学公式表示为:
- 求得梯度后,就能通过设置一个学习率$\alpha$来沿着梯度减少的方向变化:
代入上式的损失函数和所计算的梯度,也就得到:
在真实计算时,往往参数使用矩阵或向量表示:
- 线性回归实现:
# Linear Regression Model
class LinearRegression(nn.Module):
def __init__(self, input_size, output_size):
super(LinearRegression, self).__init__()
self.linear = nn.Linear(input_size, output_size)
def forward(self, x):
out = self.linear(x)
return out
逻辑回归
逻辑回归也称为对数几率回归。明明叫回归,但却是分类问题中极为重要的手段。其思想也是基于线性回归,属于广义线性回归模型。
对于二分类问题来讲,给你一个输入特征向量$X$,它可能对应一张图片,你想识别看它是否是一张猫的图片, 通过一个算法输出预测$\hat{y}$, 也就是对于实际值$y$的估计。换句话说,也就是想通过输入图片$X$, 想通过输出$\hat{y}$来知道这张图片是猫的几率有多大。用$w$来表示逻辑回归的参数,$x$是一个$n_{x}$维的特征向量,$b$表示这个模型中所要用到的偏置。如果用线性回归的方法来表示这个模型:
这时候我们得到一个关于输入$x$的线性函数,但是对于这个二元分类来讲,似乎并不是一个很好的算法。因为我们想要得到的是这张图片是否为猫的概率,所以输出值应该介于0 ~ 1之间,而通过线性回归输出的$\hat{y}$可能要比1大很多,甚至为负值,这样来说这个模型就没有意义了,因此在逻辑回归当中,我们应将输出局限在0~1之间, 所以增加了一个Sigmoid函数将线性函数转换为非线性函数。
使用matplotlib画出Sigmoid的图形表示如下,可以看出输出值都在0~1之间
# 画sigmoid
import matplotlib.pyplot as plt
import numpy as np
import math
%matplotlib inline
def sigmoid(x):
a = []
for item in x:
a.append(1/(1+math.exp(-item)))
return a
x = np.arange(-10, 10, 0.2)
sig = sigmoid(x)
plt.plot(x, sig)
plt.show()
如果$z$非常大那么$e^{-z}$将会接近于0,那么sigmoid函数的值将会近似等于1除以1加上某个非常接近于0的项,因为$e$ 的指数如果是个绝对值很大的负数的话,这项将会接近于0,所以如果$z$很大的话那么关于$z$的sigmoid函数会非常接近1。相反地,如果$z$非常小或者说是一个绝对值很大的负数,那么关于$e^{-z}$这项会变成一个很大的数,你可以认为这是1除以1加上一个非常非常大的数,所以这个就接近于0 。
所以要将识别猫这个任务所得到的结果规定在0~1之间,那么久需要对刚才定义的线性模型增加一个sigmoid函数,使其变为非线性:
也就是:
有了这个模型,要去实现这个识别猫的分类任务,接下来要做的就是通过给定的数据集,通过训练模型,把$w$参数给找出来。要找模型中的权重,就需要先定义损失函数。那么怎么去找到能衡量这个二分类的损失函数,通过使用极大似然估计。由于所要判断出的图片,只有两种可能:
- 1表示图片里是猫
- 0表示图片里不是猫
所以这两种情况的概率分别为:
根据上面两式,通过最大似然估计求解损失函数,首先得到概率函数为:
因为数据集中样本数据是相互独立的,所以它们的联合分布可以表示为总的乘积:
取对数似然函数:
最大似然估计就是要取使$l(w)$最大时的$w$,所以在前面加上一个负号不就是使求其最小了吗?这样就得到损失函数:
所以简化形式的损失函数为:
当$y=1$时损失函数$L=-ln(\hat{y})$,如果想要损失函数$L$尽可能得小,那么$\hat{y}$就要尽可能大,因为sigmoid函数取值$[0,1]$,所以$\hat{y}$会无限接近于1。
当$y=0$时损失函数$L=-ln(1-\hat{y})$,如果想要损失函数$L$尽可能得小,那么$\hat{y}$就要尽可能小,因为sigmoid函数取值$[0,1]$,所以$\hat{y}$会无限接近于0。
这只是对于单个样本的损失函数,对于总的样本,需将所有代价加起来除以m:
接下来要做的就是通过梯度下降法求得导数,再如之前一样更新参数$w$和$b$的值即可。
同样使用pytorch来实现逻辑回归模型:
class LogisticRegression(nn.Module):
def __init__(self, input_size, num_classes):
super(LogisticRegression, self).__init__()
self.linear = nn.Linear(input_size, num_classes)
def forward(self, x):
out = self.linear(x)
out = torch.sigmoid(out)
return out