线性回归——最小二乘和梯度下降

  • 一、线性回归
  • 1.概念
  • 2.损失函数
  • 二、最小二乘法
  • 三、梯度下降法
  • 四、代码


一、线性回归

1.概念

线性回归,能够用一个直线较为精确地描述数据之间的关系。这样当出现新的数据的时候,就能够预测出一个合理的值

如下图,平面中存在200个样本,需找出一条合理的直线对其进行拟合

线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习


通过线性回归,拟合直线效果如下

线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_02

在上述二维平面中,需要做的就是找出一条最佳拟合直线方程,形式如下:
线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_03
通过不同的算法求解线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_04得到直线方程,线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_05代表第一个特征值,线性回归过拟合岭回归解决 线性回归的拟合效果_拟合_06代表第二个特征值
实际中,若舍去特征值线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_05, 则得到的直线恒过原点,而为了使直线拟合度更高,加入了常数项线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_08, 相当于线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_09中的线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_10,为了方便与线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_04相乘相加,线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_05是人为添加的,且恒为1,直线可以看成线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_13

由此可得,在一般情况下,样本可能具有n个特征值,线性回归过拟合岭回归解决 线性回归的拟合效果_拟合_14,加入常数项线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_15,则需求解的超平面方程如下:
线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_16
需求解线性回归过拟合岭回归解决 线性回归的拟合效果_拟合_17的值以确定该方程。

为了方便表示该方程,设w参数向量为
线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_18
样本特征值为:
线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_19

线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_20可表示为:
线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_21

目标: 求解线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_22向量的最优解

2.损失函数

通过建立一个损失函数来衡量估计值和实际之间的误差的大小,将最小化损失函数作为一个约束条件来求出参数向量的最优解。
样本集为:
线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_23
线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_24为样本数量,线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_25为特征值数量
单个样本向量可以如下
线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_26

i个样本向量如下:
线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_27

i个样本的预测值为:
线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_28

损失函数如下:
线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_29

线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_30为某一个样本的实际值,线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_31为预测值,线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_32函数即为误差的平方和,求当线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_32取最小时,线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_34(参数向量)的值,线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_35为常数项对最小值无影响,方便后续求导

二、最小二乘法

为了方便计算,对样本集特征矩阵X,参数向量w,以及y向量做以下规定:

样本集特征矩阵X
线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_36

参数向量w:
线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_37
XW矩阵相乘:
线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_38

线性回归过拟合岭回归解决 线性回归的拟合效果_拟合_39为第i个样本预测值

y向量:
线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_40

线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_41为样本实际值

损失函数:线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_42
可以表示为线性回归过拟合岭回归解决 线性回归的拟合效果_拟合_43

线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_44求导得:

线性回归过拟合岭回归解决 线性回归的拟合效果_特征值_45

令:线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_46

相当于对J(W)中,分别对w0,w1,w2,…,wn求偏导,令偏导等于0,解出w0,w1,w2…,wn

解得:线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_47

即求得最优参数向量W

三、梯度下降法

使用最小二乘法效率可能比较低,需解出n(特征值数量)个方程,可使用梯度下降法,对w参数向量进行迭达

梯度下降:沿着增长最快的相反方向,移动线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_48
线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_49

线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_50表示增长最快的方向,使用减号表示递减(梯度下降),若加表示递增(梯度上升)

使用梯度下降(或上升)时,一般给定w一个初始值,再通过不断迭代得到最优值
此时即需求线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_51的梯度, 需分别对对线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_52求偏导

线性回归过拟合岭回归解决 线性回归的拟合效果_拟合_53

通过对对损失函数线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_54求偏导后(参考梯度上升),梯度可以表示为:

线性回归过拟合岭回归解决 线性回归的拟合效果_机器学习_55

所以代入原方程,
梯度上升算法的迭代过程:线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归过拟合岭回归解决_48 为步长 线性回归过拟合岭回归解决 线性回归的拟合效果_线性回归_57
线性回归过拟合岭回归解决 线性回归的拟合效果_拟合_58
经过上述不断迭代的过程,最终得到一个合适的线性回归过拟合岭回归解决 线性回归的拟合效果_拟合_59参数

四、代码

import numpy as np
#from matplotlib import pyplot as plt

def load_datas(filename):
    with open(filename, 'r') as fr:
        data_mat=[]
        data_labels=[]
        for line in fr:
            curr_line=line.strip().split('\t')
            data_mat.append(list(map(float, curr_line[:-1])))
            data_labels.append(float(curr_line[-1]))
    return np.mat(data_mat), np.mat(data_labels)


def get_weights0(datas, labels):
    """
    最小二乘法

    :param datas:
    :param labels:
    :return:weights
    """
    xTx=datas.T*datas
    if(np.linalg.det(xTx)!=0.0):
        weights=xTx.I*datas.T*labels.T
        return weights
    return None


def get_weights1(datas, y_labels, alpha=1, r=300):
    """
    梯度下降法

    :param datas:
    :param labels:
    :return:weights
    """
    shape = datas.shape
    weights=np.ones((shape[1], 1))
    for i in range(r):
        err = y_labels-datas*weights
        weights=weights+(alpha/shape[0])*datas.T*err
    return weights


print('最小二乘法')
data_mat, data_labels = load_datas('ex1.txt')
weights=get_weights0(data_mat, data_labels)
print(weights)
print('梯度下降法')
weights=get_weights1(data_mat, data_labels.T)
print(weights)