线性回归

线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。 特点:只有一个自变量的情况称为单变量回归,多于一个自变量情况的叫做多元回归

通用公式: $$ h(w)=w_{1} x_{1}+w_{2} x_{2}+w_{3} x_{3} \ldots+\mathrm{b}=w^{T} x+b $$

其中 w,x可以理解为矩阵: $$ w=\left(\begin{array}{c} b \\ w_{1} \\ w_{2} \end{array}\right), x=\left(\begin{array}{c} 1 \\ x_{1} \\ x_{2} \end{array}\right) $$

那么怎么理解呢?我们来看几个例子

  • 期末成绩:0.7×考试成绩+0.3x平时成绩
  • 房子价格=0.02×中心区域的距离+0.04×城市一氧化氮浓度+(-0.12×自住房平均房价)+0.254×城镇犯罪率 上面两个例子,我们看到特征值与目标值之间建立了一个关系,这个关系可以理解为线性模型。

线性回归当中线性模型有两种,一种是线性关系,另一种是非线性关系。在这里我们只能画一个平面更好去理解,所以都用单个特征或两个特征举例子。

效果图

效果图

注释:单特征与目标值的关系呈直线关系,或者两个特征与目标值呈现平面的关系更高维度的我们不用自己去想,记住这种关系即可

效果图

注:线性关系一定是线性模型,线性模型不一定是线性关系

损失函数

描述了最好的参数值应该满足什么条件,从常识来看,数据与函数对应点的欧式距离可以作为有效的指标,因为距离越近,误差越小,说明预测的越准.

假设刚才的房子例子,真实的数据之间存在这样的关系

真实关系:真实房子价格=0.02×中心区域的距离+0.04×城市一氧化氮浓度

那么现在呢,我们随意指定一个关系(猜测)

随机指定关系:预测房子价格=0.25×中心区域的距离+0.14×城市一氧化氮浓度

请问这样的话,会发生什么?真实结果与我们预测的结果之间是不是存在一定的误差呢?类似这样样子

效果图

即:目标就是找到一条直线,使所有点到直线的距离之和最小,即误差最小

$$ \begin{aligned} J(\theta) & =\left(h_{w}\left(x_{1}\right)-y_{1}\right)^{2}+\left(h_{w}\left(x_{2}\right)-y_{2}\right)^{2}+\cdots+\left(h_{w}\left(x_{m}\right)-y_{m}\right)^{2} \ & =\sum_{i=1}^{m}\left(h_{w}\left(x_{i}\right)-y_{i}\right)^{2} \end{aligned} $$

  • $y_i$为第i个训练样本的真实值。
  • $h(x_i)$为第i个训练样本特征值组合预测函数,又称最小二乘法

如何去减少这个损失,使我们预测的更加准确些?既然存在了这个损失,我们一直说机器学习有自动学习的功能,在线性回归这里更是能够体现。这里可以通过一些优化方法去优化(其实是数学当中的求导功能)回归的总损失

极大似然

概率是特定环境下某件事情发生的可能性,在结果没有产生之前,我们会根据环境中的参数来预测某件事情发生的概率。 似然是基于已经确定的结果来推测产生这个结果的可能环境。

maximum likelihood estimate最大的似然估计,就是利用已知的样本标记结果,反推最具有可能或者最大概率导致这些样本结果出现的模型参数。

高斯分布的概率密度函数: $$ f(x)=\frac{1}{\sigma \sqrt{2 \pi}} e^{-\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^{2}} $$

本质是由两个参数控制: $ \mathcal{N}(\mu, \sigma) $

$\mu$是均值,当它越大会在坐标轴上平移 $\sigma$是标准差,控制着峰度,它越大,分布就会越散,图像就会越平,它越小,分布就会越集中,图像就会越尖。

有一组采样数据来自于同一个高斯分布,那么如何确定这些数据是具体来自于哪一个高斯分布呢,因高斯分布的定义域是负无穷到正无穷,任何参数的高斯分布都有可能采样出这组数据,区别只是概率大小。所以真正想知道的是哪个高斯分布能让这组数据出现的概率最大?每一个数据被采样的概率都可以写成一个条件概率的形式。

$ \max \left[\prod_{i}^{n} \mathcal{N}\left(x_{i} \mid \mu, \sigma\right)\right] $

$ \max \sum_{i}^{n} \ln \mathcal{N}\left(x_{i} \mid \mu, \sigma\right) $

$$ \begin{array}{l} \sum_{i}^{n} \ln \left[\frac{1}{\sigma \sqrt{2 \pi}} e^{\left.-\frac{1}{2}\left(\frac{y_{i}-\omega x_{i}}{\sigma}\right)^{2}\right]}\right. \\ \sum_{i}^{n} \ln \left[\frac{1}{\sigma \sqrt{2 \pi}}\right]+\sum_{i}^{n}-\left[\frac{1}{2 \sigma^{2}}\left(y_{i}-\omega x_{i}\right)^{2}\right] \\ \sum_{i}^{n}-\left(y_{i}-\omega x_{i}\right)^{2} \end{array} $$

最小二乘法是极大似然估计在高斯分布下的一种特殊形式。

优化算法

如何去求模型当中的W,使得损失最小?(目的是找到最小损失对应的W值) 线性回归经常使用的两种优化算法。

正规方程

$$ w=\left(X^{T} X\right)^{-1} X^{T} y $$

理解:X为特征值矩阵,y为目标值矩阵。直接求到最好的结果 缺点:当特征过多过复杂时,求解速度太慢并且得不到结果

效果图

sklearn实现正规方程
  • sklearn.linear_model.LinearRegression(fit_intercept=True)
    • 通过正规方程优化:
      • fit_intercept:是否计算偏置
      • LinearRegression.coef_:回归系数
      • LinearRegression.intercept:偏置

梯度下降

$$ \begin{array}{l} w_{1}:=w_{1}-\alpha \frac{\partial \operatorname{cost}\left(w_{0}+w_{1} x_{1}\right)}{\partial w_{1}} \ w_{0}:=w_{0}-\alpha \frac{\partial \operatorname{cost}\left(w_{0}+w_{1} x_{1}\right)}{\partial w_{1}} \end{array} $$

理解:α为学习速率,需要手动指定(超参数),α旁边的整体表示方向沿着这个函数下降的方向找,最后就能找到山谷的最低点,然后更新W值 使用:面对训练数据规模十分庞大的任务,能够找到较好的结果

效果图

效果图

sklearn实现梯度下降
  • sklearn.linear_model.SGDRegressor(loss="squared_loss",fit_intercept=True,learning_rate ='invscaling',eta0=0.01) :实现了随机梯度下降学习,它支持不同的loss函数和正则化惩罚项来拟合线性回归模型。
    • loss:损失类型
      • loss=”squared_loss’”:普通最小二乘法
    • fit_intercept:是否计算偏置
    • learning_rate string,optional:学习率填充
      • 'constant':eta =etao
        • 对于一个常数值的学习率来说,可以使用learning_rate=‘constant’,并使用eta0来指定学习率。
      • ‘optimal’:eta 1.0/(alpha *(t to))[default]
      • ‘invscaling’:eta etao/pow(t,power_t)
        • power_.t=0.25:存在父类当中
    • SGDRegressor.coef_:回归系数
    • SGDRegressor.intercept_:偏置

模型评估

均方误差(Mean Squared Error))MSE)评价机制:

$$ MSE=\frac{1}{m} \sum_{i=1}^{m}\left(y^{i}-\bar{y}\right)^{2} $$

注:y为预测值,y为真实值

  • sklearn.metrics.mean_squared_error(y_true,y_pred)
    • 均方误差回归损失
    • y_true:真实值
    • y_pred:预测值
    • return:浮点数结果

举例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, SGDRegressor
from sklearn.metrics import mean_squared_error
def linear1():
    """
    正规方程的优化方法对波士顿房价进行预测
    :return:
    """
    # 1)获取数据
    boston = load_boston()

    # 2)划分数据集
    x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, random_state=22)

    # 3)标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.transform(x_test)

    # 4)预估器
    estimator = LinearRegression()
    estimator.fit(x_train, y_train)

    # 5)得出模型
    print("正规方程-权重系数为:\n", estimator.coef_)
    print("正规方程-偏置为:\n", estimator.intercept_)

    # 6)模型评估
    y_predict = estimator.predict(x_test)
    print("预测房价:\n", y_predict)
    error = mean_squared_error(y_test, y_predict)
    print("正规方程-均方误差为:\n", error)

    return None


def linear2():
    """
    梯度下降的优化方法对波士顿房价进行预测
    :return:
    """
    # 1)获取数据
    boston = load_boston()
    print("特征数量:\n", boston.data.shape)

    # 2)划分数据集
    x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, random_state=22)

    # 3)标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.transform(x_test)

    # 4)预估器
    estimator = SGDRegressor(learning_rate="constant", eta0=0.01, max_iter=10000, penalty="l1")
    estimator.fit(x_train, y_train)

    # 5)得出模型
    print("梯度下降-权重系数为:\n", estimator.coef_)
    print("梯度下降-偏置为:\n", estimator.intercept_)

    # 6)模型评估
    y_predict = estimator.predict(x_test)
    print("预测房价:\n", y_predict)
    error = mean_squared_error(y_test, y_predict)
    print("梯度下降-均方误差为:\n", error)

    return None

if __name__ == '__main__':
    linear1()
    linear2()

两种方法的对比

梯度下降正规方程
需要选择学习率不需要
需要迭代求解一次运算得出
特征数量较大可以使用需要计算方程,时间复杂度高$O(n^3)$
  • 选择:
    • 小规模数据:
      • LinearRegression(不能解决拟合问题)
      • 岭回归
    • 大规模数据:
      • SGDRegressor

欠拟合与过拟合

  • 过拟合:一个假设在训练数据上能够获得比其他假设更好的拟合,但是在测试数据集上却不能很好地拟合数据,此时认为这个假设出现了过拟合的现象。(模型过于复杂)
  • 欠拟合:一个假设在训练数据上不能获得更好的拟合,并且在测试数据集上也不能很好地拟合数据,此时认为这个假设出现了欠拟合的现象。(模型过于简单)

效果图


  • 欠拟合原因以及解决办法
    • 原因:学习到数据的特征过少
    • 解决办法:增加数据的特征数量
  • 过拟合原因以及解决办法
    • 原因:原始特征过多,存在一些嘈杂特征,模型过于复杂是因为模型尝试去兼顾各个测试数据点
    • 解决办法:正则化

在这里针对回归,我们选择了正则化。但是对于其他机器学习算法如分类算法来说也会出现这样的问题,除了一些算法本身作用之外(决策树、神经网络),我们更多的也是去自己做特征选择,包括之前说的删除、合并一些特征

效果图

在学习的时候,数据提供的特征有些影响模型复杂度或者这个特征的数据点异常较多,所以算法在学习的时候尽量减少这个特征的影响(甚至刚除某个特征的影响),这就是正则化

注:调整时候,算法并不知道某个特征影响,而是去调超参数得出优化的结果

正则化类别

L2正则化

  • 作用:可以使得其中一些W的都很小,都接近于0,削弱某个特征的影响
  • 优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象
  • Ridge回归
  • 加入L2正则化后的损失函数:

$$ J(w)=\frac{1}{2 m} \sum_{i=1}^{m}\left(h_{w}\left(x_{i}\right)-y_{i}\right)^{2}+\lambda \sum_{j=1}^{n} w_{j}^{2} $$

注:m为样本数,n为特征数 $h_w(x_i)$ 为预测值,$y_i$ 为真实值,L1正则化就是把 $w_{j}^{2}$ 改为 $|w_j|$

线性回归的改进-岭回归

带有L2正则化的线性回归(岭回归)

岭回归,其实也是一种线性回归。只不过在算法建立回归方程时候,加上正则化的限制,从而达到解决过拟合的效果

  • sklearn.linear_model.Ridge(alpha=1.0,fit_intercept=True,solver="auto",normalize=False):具有2正则化的线性回归
    • alpha:正则化力度,也叫入SAG
      • λ取值:0~11~10
    • solver:会根据数据自动选择优化方法
      • sag如果数据集、特征都比较大,选择该随机梯度下降优化
    • normalize:数据是否进行标准化
      • normalize=False:可以在fit之前调用preprocessing.StandardScaler标准化数据
    • Ridge.coef:回归权重
    • Ridge.intercept:回归偏置

Ridge方法相当于SGDRegressor(penalty:='I2',loss="squared_loss"),只不过SGDRegressor实现了一个普通的随机梯度下降学习,推荐使用Ridge(实现了SAG)

  • sklearn.linear_model.RidgeCV(BaseRidgeCV,RegressorMixin):具有2正则化的线性回归,可以进行交叉验证
    • coef:回归系数

效果图

正则化力度越大,权重系数会越小 正则化力度越小,权重系数会越大

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression, SGDRegressor,Ridge
from sklearn.metrics import mean_squared_error

def linear3():
    """
    岭回归对波士顿房价进行预测
    :return:
    """
    # 1)获取数据
    boston = load_boston()
    print("特征数量:\n", boston.data.shape)

    # 2)划分数据集
    x_train, x_test, y_train, y_test = train_test_split(boston.data, boston.target, random_state=22)

    # 3)标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.transform(x_test)

    #4)预估器
    estimator = Ridge(alpha=0.5, max_iter=10000)
    estimator.fit(x_train, y_train)


    # 5)得出模型
    print("岭回归-权重系数为:\n", estimator.coef_)
    print("岭回归-偏置为:\n", estimator.intercept_)

    # 6)模型评估
    y_predict = estimator.predict(x_test)
    print("预测房价:\n", y_predict)
    error = mean_squared_error(y_test, y_predict)
    print("岭回归-均方误差为:\n", error)

    return None
if __name__ == '__main__':
    linear3()

逻辑回归

逻辑回归(Logistic Regression)是机器学习中的一种分类模型,逻辑回归是一种分类算法,虽然名字中带有回归,但是它与回归之间有一定的联系。由于算法的简单和高效,在实际中应用非常广泛。

原理

输入

$$ h(w)=w_{1} x_{1}+w_{2} x_{2}+w_{3} x_{3} \ldots+\mathrm{b} $$

逻辑回归的输入就是一个线性回归的结果。

激活函数

sigmoid函数

$$ g\left(\theta^{T} x\right)=\frac{1}{1+e^{-\theta^{T} x}} $$

  • 分析
    • 回归的结果输入到sigmoid函数当中
    • 输出结果:[0,1]区间中的一个概率值,默认为0.5为阈值

效果图

逻辑回归最终的分类是通过属于某个类别的概率值来判断是否属于某个类别,并且这个类别默认标记为1(正例,另外的一个类别会标记为0(反例)。(方便损失计算)

输出结果解释(重要):假设有两个类别A,B,并且假设我们的概率值为属于A(1)这个类别的概率值。现在有一个样本的输入到逻辑回归输出结果0.6,那么这个概率值超过0.5,意味着我们训练或者预测的结果就是A(1)类别。那么反之,如果得出结果为0.3那么,训练或者预测结果就为B(O)类别。

所以接下来我们回忆之前的线性回归预测结果我们用均方误差衡量,那如果对于逻辑回归,我们预测的结果不对该怎么去衡量这个损失呢?我们来看这样一张图

效果图

假设得出概率值是属于A的概率值

那么如何去衡量逻辑回归的预测结果与真实结果解差异呢?

损失函数

1损失 逻辑回归的损失,称之为对数似然损失,公式如下: ·分开类别:

$$ \operatorname{cost}\left(h_{\theta}(x), y\right)=\left{\begin{array}{ll} -\log \left(h_{\theta}(x)\right) & \text { if } \mathrm{y}=1 \ -\log \left(1-h_{\theta}(x)\right) & \text { if } \mathrm{y}=0 \end{array}\right. $$

当y=1时:

效果图

同理,我们也可以画出当y=0时,函数C()的图像:

效果图

综合完整损失函数

$$ \operatorname{cost}\left(h_{\theta}(x), y\right)=\sum_{i=1}^{m}-y_{i} \log \left(h_{\theta}(x)\right)-\left(1-y_{i}\right) \log \left(1-h_{\theta}(x)\right) $$

效果图

优化损失

同样使用梯度下降优化算法,去减少损失函数的值。这样去更新逻辑回归前面对应算 法的权重参数,提升原本属于1类别的概率,降低原本是0类别的概率

逻辑回归API

  • sklearn.linear_model.LogisticRegression(solver=‘liblinear’,penalty=‘12’,C=1.0)
    • solver:优化求解方式(默开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数)
      • Sag:根据数据集自动选择,随机平均梯度下降
    • penalty:正则化的种类
    • C:正则化力度

默认将类别数量少的当做正例

LogisticRegression方法相当于SGDClassifier(loss="log",penalty=""),SGDClassifier实现了一个普通的随机梯度下降学习,也支持平均随机梯度下降法(ASGD),可以通过设置average:=True。而使用LogisticRegression(实现了SAG)

模型评估(二分类)

精确率与召回率

  1. 混淆矩阵

在分类任务下,预测结果(Predicted Condition)与正确标记(True Condition)之间存在四种不同的组合,构成混淆矩阵(适用于多分类)

预测.正例预测.假例
真实.正例真正例TP伪反例FN
真实.假例伪正例FP真反例TN
  1. 精确率(Precision)与召回率(Recall)
  • 精确率: 预测结果为正例样本中真实为正例的比例
$\color{red}{预测.正例}$预测.假例
$\color{red}{真实.正例}$$\color{red}{真正例TP}$伪反例FN
真实.假例$\color{red}{伪正例FP}$真反例TN
  • 召回率:真实为正例的样本中预测结果为正例的比例 (查得全,对正样本的区分能力)
$\color{red}{预测.正例}$预测.假例
$\color{red}{真实.正例}$$\color{red}{真正例TP}$$\color{red}{伪反例FN}$
真实.假例伪正例FP真反例TN
  • 还有其他的评估标准, F1-score, 反映了模型的稳健型

$$ F1=\frac{2 T P}{2 T P+F N+F P}=\frac{2 \cdot \text { Precision } \cdot \text { Recall }}{\text { Precision }+ \text { Recall }} $$

分类评估报告API

  • sklearn.metrics.classification_report(y_true,y_pred,labels,target_names=None)
    • y_true:真实目标值
    • y_pred:估计器预测目标值
    • labels:指定类别对应的数字
    • target_names:目标类别名称
    • return:每个类别精确率与召回率

假设这样一个情况,如果99个样本癌症,1个样本非癌症,不管怎样我全都预测正例(默认癌症为正例),准确率就为99%但是这样效果并不好,这就是样本不均衡下的评估问题

如何衡量样本不均衡下的评估?

ROC曲线与AUC指标

知道TPR与FPR

  • $ TPR=\frac{TP}{TP+FN} $: 所有真实类别为1的样本中,预测类别为1的比例
  • $ FPR=\frac{FP}{FP+TN} $: 所有真实类别为0的样本中,预测类别为1的比例
  1. ROC曲线

ROC曲线的横轴就是FPRate,纵轴就是TPRate,当二者相等时,表示的意义则是:对于不论真实类别是1还是0的样本,分类器预测为1的概率是相等的,此时AUC为0.5

效果图

  1. AUC指标
  • AUC的概率意义是随机取一对正负样本,正样本得分大于负样本的概率
  • AUC的最小值为0.5,最大值为1,取值越高越好
  • AUC=1,完美分类器,采用这个预测模型时,不管设定什么阈值都能得出完美预测。绝大多数预测的场合,不存在完美分类器。
  • 0.5<AUC<1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。

最终AUC的范围在[0.5,1]之间,并且越接近1越好

  1. AUC计算API
1
2
3
4
5
from sklearn.metrics import roc_auc_score
sklearn.metrics.roc_auc_score(y_true,y_score)
#计算ROC曲线面积,即AUC值
# y_tue:每个样本的真实类别,必须为0(反例,1(正例标记
# y_score:预测得分,可以是正类的估计概率、置信值或者分类器方法的返回值