欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

机器学习个人笔记——(二)线性回归,最小二乘法和梯度下降

程序员文章站 2022-05-06 19:13:52
线性回归——最小二乘和梯度下降一、线性回归1.概念2.损失函数二、最小二乘法三、梯度下降法一、线性回归1.概念线性回归,能够用一个直线较为精确地描述数据之间的关系。这样当出现新的数据的时候,就能够预测出一个合理的值如下图,平面中存在200个样本,需找出一条合理的直线对其进行拟合通过线性回归,拟合直线效果如下在上述二维平面中,需要做的就是找出一条最佳拟合直线方程,形式如下:h(x)=w0x0+w1x1(通常x0为1)∴直线表达式为=>h(x)=w0+w1x1\begin{aligne...

一、线性回归

1.概念

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

如下图,平面中存在200个样本,需找出一条合理的直线对其进行拟合
机器学习个人笔记——(二)线性回归,最小二乘法和梯度下降
通过线性回归,拟合直线效果如下
机器学习个人笔记——(二)线性回归,最小二乘法和梯度下降

在上述二维平面中,需要做的就是找出一条最佳拟合直线方程,形式如下:
h(x)=w0x0+w1x1x01线=>h(x)=w0+w1x1\begin{aligned} h(x) & = w_{0}x_{0}+w_{1}x_{1}{(通常x_{0}为1)}\\{\therefore 直线表达式为=>}h(x)& = w_{0}+w_{1}x_{1} \end{aligned}
通过不同的算法求解w0w1w_{0},w_{1}得到直线方程,x0x_{0}代表第一个特征值,x1x_{1}代表第二个特征值
实际中,若舍去特征值x0x_{0}, 则得到的直线恒过原点,而为了使直线拟合度更高,加入了常数项w0w_{0}, 相当于y=kx+by=kx+b中的bb,为了方便与w0w1w_{0},w_{1}相乘相加,x0x_{0}是人为添加的,且恒为1,直线可以看成y=kx+b1=>h=w0+w1x1y=kx+b*1=>h= w_{0}+w_{1}x_{1}

由此可得,在一般情况下,样本可能具有n个特征值,x1,x2,...,xnx_{1},x_{2},...,x_{n},加入常数项x0=1x_{0}=1,则需求解的超平面方程如下:
h(x)=w0x0+w1x1+w2x2+...+wnxnx01\begin{aligned} h(x)& = w_{0}x_{0}+w_{1}x_{1}+w_{2}x_{2}+...+w_{n}x_{n}{(通常x_{0}为1)} \end{aligned}
需求解w0,w1x,w2,..wnw_{0},w_{1}x,w_{2},..w_{n}的值以确定该方程。

为了方便表示该方程,设w参数向量为
wT=[w0w1w2...wn]\mathbf{w^{T}}=\begin{bmatrix} w_{0}&w_{1} &w_{2} &...&w_{n} \end{bmatrix}
样本特征值为:
xT=[x0x1x2...xn](x0=1)\mathbf{x^{T}}=\begin{bmatrix} x_{0}&x_{1} &x_{2} &...&x_{n} \end{bmatrix}{(x_{0}=1)}

h(x)h(x)可表示为:
h(x)=wTxh(\mathbf{x})=\mathbf{w^{T}x}

目标: 求解w\mathbf{w}向量的最优解

2.损失函数

通过建立一个损失函数来衡量估计值和实际之间的误差的大小,将最小化损失函数作为一个约束条件来求出参数向量的最优解。
样本集为:
X=[x10x20...xm0x11x21...xm1............x1nx2n...xmn]\mathbf{X} =\begin{bmatrix} x_{10}&x_{20}&...&x_{m0}\\ x_{11}&x_{21}&...&x_{m1}\\ ...&...&...&...\\ x_{1n}&x_{2n}&...&x_{mn} \end{bmatrix}
mm为样本数量,nn为特征值数量
单个样本向量可以如下
x1=[x10x11...x1n],x2=[x20x21...x2n],...,xm=[xm0xm1...xmn]\mathbf{x^{1}}=\begin{bmatrix} x_{10}\\x_{11}\\...\\x_{1n}\\ \end{bmatrix},\mathbf{x^{2}}=\begin{bmatrix} x_{20}\\x_{21}\\...\\x_{2n}\\ \end{bmatrix},...,\mathbf{x^{m}}=\begin{bmatrix} x_{m0}\\x_{m1}\\...\\x_{mn}\\ \end{bmatrix}

i个样本向量如下:
xi=[xi0xi1...xin]\mathbf{x^{i}}=\begin{bmatrix} x_{i0}\\x_{i1}\\...\\x_{in}\\ \end{bmatrix}

i个样本的预测值为:
h(xi)=wTxih(\mathbf{x^{i}})=\mathbf{w^{T}x^{i}}

损失函数如下:
J(w)=12mi=1m(wTxyi)2=12mi=1m(h(xi)yi)2minJ(w)\begin{aligned} J(\mathbf{w}) &= \frac{1}{2m}\sum_{i = 1}^{m}(\mathbf{w^{T}x}-y^{i})^{2}\\ &=\frac{1}{2m}\sum_{i = 1}^{m}(h(\mathbf{x^{i}})-y^{i})^{2}\\\\{求}&\min J(\mathbf{w}) \end{aligned}

yiy^{i}为某一个样本的实际值,h(xi)h(\mathbf{x^{i}})为预测值,J(w)J(\mathbf{w})函数即为误差的平方和,求当J(w)J(\mathbf{w})取最小时,w\mathbf{w}(参数向量)的值,12\frac{1}{2}为常数项对最小值无影响,方便后续求导

二、最小二乘法

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

样本集特征矩阵X
X=[x10x11x12...x1nx20x21x22...x2n...............xm0xm1xm2...xmn]Xi=[xi0xi1xi2...xin]\begin{aligned} \mathbf{X} & = \begin{bmatrix} x_{10}&x_{11}&x_{12}&...&x_{1n}\\ x_{20}&x_{21}&x_{22}&...&x_{2n}\\ ...&...&...&...&...\\ x_{m0}&x_{m1}&x_{m2}&...&x_{mn}\\ \end{bmatrix}\\\\\mathbf{X^{i}} &= \begin{bmatrix} x_{i0}&x_{i1}&x_{i2}&...&x_{in} \end{bmatrix} \end{aligned}

参数向量w:
W=[w0w1w2...wn]\mathbf{W}=\begin{bmatrix} w_{0}\\w_{1} \\w_{2} \\...\\w_{n} \end{bmatrix}
XW矩阵相乘:
XW=[h1h2h3...hm]\mathbf{XW}= \begin{bmatrix} h_{1} \\ h_{2}\\ h_{3}\\...\\ h_{m} \end{bmatrix}

hih_{i}为第i个样本预测值

y向量:
Y=[y1y2y3...ym]\mathbf{Y}=\begin{bmatrix} y_{1}\\y_{2} \\y_{3} \\...\\y_{m} \end{bmatrix}

yiy_{i}为样本实际值

损失函数:J(w)=i=1m(h(xi)yi)2\begin{aligned} J(\mathbf{w}) =\sum_{i = 1}^{m}(h(\mathbf{x^{i}})-y^{i})^{2} \end{aligned}
可以表示为J(W)=(YXW)T(YXW):J(\mathbf{W})=(\mathbf{Y}-\mathbf{XW})^{T}(\mathbf{Y}-\mathbf{XW})

W\mathbf{W}求导得:

J(W)W=2XTY+2XTXW\frac{\partial J(\mathbf{W})}{\partial \mathbf{W}} =-2\mathbf{X^{T}Y}+2\mathbf{X^{T}XW}

令:J(W)W=2XTY+2XTXW=0\frac{\partial J(\mathbf{W})}{\partial \mathbf{W}} =-2\mathbf{X^{T}Y}+2\mathbf{X^{T}XW}=0

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

解得:W=(XTX)1XY\mathbf{W}=(\mathbf{X^{T}X})^{-1}\mathbf{X}\mathbf{Y}

即求得最优参数向量W

三、梯度下降法

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

梯度下降:沿着增长最快的相反方向,移动α\alpha 的步长,即逐步递减值最低值,迭代公式如下
w=wαf\large w=w-\alpha \nabla {f}

f\nabla {f}表示增长最快的方向,使用减号表示递减(梯度下降),若加表示递增(梯度上升)

使用梯度下降(或上升)时,一般给定w一个初始值,再通过不断迭代得到最优值
此时即需求J(w)J(\mathbf{w})的梯度, 需分别对对wiw_{i}求偏导

f=[J(w)w0J(w)w1J(w)w2...J(w)wn]\large \nabla {f}=\begin{bmatrix} \frac{\partial\mathrm J(\mathbf{w})}{\partial w_{0}}\\ \frac{\partial\mathrm J(\mathbf{w})}{\partial w_{1}}\\ \frac{\partial\mathrm J(\mathbf{w})}{\partial w_{2}}\\ ...\\ \frac{\partial\mathrm J(\mathbf{w})}{\partial w_{n}}\\ \end{bmatrix}

通过对对损失函数J(w)J(\mathbf w)求偏导后(参考梯度上升),梯度可以表示为:

f=1m[i=1m(yih(wTxi))xi0i=1m(yih(wTxi))xi1i=1m(yih(wTxi))xi2......i=1m(yih(wTxi))xin]\large \nabla {f}=-\frac{1}{m} \begin{bmatrix} \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i0}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i1}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i2}\\ ......\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{in}\\ \end{bmatrix}

所以代入原方程,
梯度上升算法的迭代过程:α\alpha 为步长 (α>0)(\alpha >0)
w=wαf=[w0w1w2...wn]+α1m[i=1m(yih(wTxi))xi0i=1m(yih(wTxi))xi1i=1m(yih(wTxi))xi2......i=1m(yih(wTxi))xin]\begin{aligned} \mathbf{w} &=\mathbf{w} -\alpha \nabla f\\\\&=\begin{bmatrix} w_{0}\\ w_{1}\\ w_{2}\\...\\w_{n} \end{bmatrix}+\alpha \frac{1}{m}\begin{bmatrix} \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i0}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i1}\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{i2}\\ ......\\ \sum_{i=1}^{m}(y_{i}-h(\mathbf{w^{T}x_{i}}))x_{in}\\ \end{bmatrix} \end{aligned}
经过上述不断迭代的过程,最终得到一个合适的w\mathbf{w}参数

四、代码

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)


本文地址:https://blog.csdn.net/weixin_42582355/article/details/107548744