机器学习_线性回归_回归系数

1、用线性回归找到最佳拟合直线

应该怎么从一大堆数据里求出回归方程呢?假定输入数据存放在矩阵X中,结果存放在向量y中:机器学习实战教程(十一):线性回归基础篇之预测鲍鱼年龄

而回归系数存放在向量w中:

机器学习实战教程(十一):线性回归基础篇之预测鲍鱼年龄

那么对于给定的数据x1,即矩阵X的第一列数据,预测结果u1将会通过如下公式给出:

机器学习实战教程(十一):线性回归基础篇之预测鲍鱼年龄

现在的问题是,手里有数据矩阵X和对应的标签向量y,怎么才能找到w呢?一个常用的方法就是找出使误差最小的w。这里的误差是指预测u值和真实y值之间的差值,使用该误差的简单累加将使得正差值和负差值相互抵消,所以我们采用平方误差。

平方误差和可以写做:

机器学习实战教程(十一):线性回归基础篇之预测鲍鱼年龄

用矩阵表示还可以写做:

机器学习实战教程(十一):线性回归基础篇之预测鲍鱼年龄

为啥能这么变化,记住一个前提:若x为向量,则默认x为列向量,x^T为行向量。将上述提到的数据矩阵X和标签向量y带进去,就知道为何这么变化了。

在继续推导之前,我们要先明确一个目的:找到w,使平方误差和最小。因为我们认为平方误差和越小,说明线性回归拟合效果越好。

现在,我们用矩阵表示的平方误差和对w进行求导:

机器学习实战教程(十一):线性回归基础篇之预测鲍鱼年龄

如果对于矩阵求不熟悉的,可以移步这里:点击查看

令上述公式等于0,得到:

机器学习实战教程(十一):线性回归基础篇之预测鲍鱼年龄

w上方的小标记表示,这是当前可以估计出的w的最优解。从现有数据上估计出的w可能并不是数据中的真实w值,所以这里使用了一个"帽"符号来表示它仅是w的一个最佳估计。

值得注意的是,上述公式中包含逆矩阵,也就是说,这个方程只在逆矩阵存在的时候使用,也即是这个矩阵是一个方阵,并且其行列式不为0。

述的最佳w求解是统计学中的常见问题,除了矩阵方法外还有很多其他方法可以解决。通过调用NumPy库里的矩阵方法,我们可以仅使用几行代码就完成所需功能。该方法也称作OLS, 意思是“普通小二乘法”(ordinary least squares)。

import matplotlib.pyplot as plt
import numpy as np

"""
应该怎么从一大堆数据里求出回归方程呢?假定输入数据存放在矩阵X中,结果存放在向量y中:
    |x11 x12 x13|     |y1|                                        |w1|
X = |x21 x22 s23| Y = |y2|            而回归系数存放在向量w中: W = |w2|
    |x31 x32 x33|     |y3|                                        |w3|
那么对于给定的数据x1,即矩阵X的第一列数据,预测结果u1:
          T
     |x11|     |w1|
u1 = |x21|  *  |w2|
     |x31|     |w3|
     
现在的问题是,手里有数据矩阵X和对应的标签向量y,怎么才能找到w呢?
一个常用的方法就是找出使误差最小的w。这里的误差是指预测u值和真实y值之间的差值,
使用该误差的简单累加将使得正差值和负差值相互抵消,所以我们采用平方误差。
                      T
平方误差和: ( y - X*w )*( y - X*w )
                  T
对上式进行求导: 2X ( y - X*w )
                           T     -1  T
令上式等于0,解出: w = ( X * X )* X * y
"""

"""
函数说明:加载数据
Parameters:
    fileName - 文件名
Returns:
    xArray - x数据集
    yArray - y数据集
Author:
    ZhengYuXiao
Modify:
    2019-02-23
"""


def loadDataSet(fileName):
    numFeat = len(open(fileName).readline().split('\t')) - 1  # 列数-1
    xArray = []
    yArray = []
    fr = open(fileName)
    print("numFeat=", numFeat)
    for line in fr.readlines():
        lineArr = []
        curLine = line.strip().split('\t')
        # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列.
        # 该方法只能删除开头或是结尾的字符,不能删除中间部分的字符
        for i in range(numFeat):
            lineArr.append(float(curLine[i]))  # 前两列  字符转数值 保存
        xArray.append(lineArr)  # 前两列
        yArray.append(float(curLine[-1]))  # 最后一列
    print("xArray=\n", np.array(xArray))
    print("yArray=\n", np.array(yArray))
    return xArray, yArray


"""
函数说明:绘制数据点
Parameters:
    xArray - x数据集
    yArray - y数据集
Returns:
    null
Author:
    ZhengYuXiao
Modify:
    2019-02-23
"""


def plotDataSet(xArray, yArray):
    numberOfData = len(xArray)  # 数据条数/坐标点个数
    xcord = []  # x列表
    ycord = []  # y列表
    for i in range(numberOfData):
        xcord.append(xArray[i][1])
        ycord.append(yArray[i])
    fig = plt.figure()  # 画板
    ax = fig.add_subplot(111)  # 画纸
    ax.scatter(xcord, ycord, s=20, c='blue', alpha=.5)
    plt.title('DataSet')
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.show()


"""
函数说明:计算回归系数w
Parameters:
    xArray - x数据集
    yArray - y数据集
Returns:                 T      -1   T
    w - 回归系数   w = ( X  *  X ) * X * Y
Author:
    ZhengYuXiao
Modify:
    2019-02-24
"""


def standRegres(xArray, yArray):
    xMat = np.mat(xArray)  # 生成矩阵X
    yMat = np.mat(yArray).T  # 生成矩阵Y      T
    xTx = xMat.T * xMat  # 计算          ( X * X )
    # numpy.linalg模块包含线性代数的函数。
    # .det 计算矩阵的行列式
    # 矩阵A可逆的条件之一:行列式|A|≠0(也可表述为A不是奇异矩阵,即行列式为0的矩阵)
    if np.linalg.det(xTx) == 0.0:
        print("矩阵为奇异矩阵,不能求逆矩阵")
        return
    w = xTx.I * (xMat.T * yMat)  # 根据公式求出回归系数
    return w


"""
函数说明:数据点和回归曲线
Parameters:
    xArray - x数据集
    yArray - y数据集
    w - 回归系数
Returns:
    none
Author:
    ZhengYuXiao
Modify:
    2019-02-24
"""


def plotRegression(xArray, yArray, w):
    xMat = np.mat(xArray)  # X矩阵
    yMat = np.mat(yArray)  # Y矩阵
    xCopy = xMat.copy()  # 深拷贝
    """
    浅拷贝和深拷贝的区别是:浅拷贝只是将原对象在内存中引用地址拷贝过来了。
    让新的对象指向这个地址。而深拷贝是将这个对象的所有内容遍历拷贝过来了,
    相当于跟原来没关系了,所以如果你这时候修改原来对象的值跟他没关系了,不会随之更改。
    """
    xCopy.sort(0)  # 排序
    yHat = xCopy * w  # 计算相应的y值
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(xCopy[:, 1], yHat, c='red')  # 绘制回归曲线
    ax.scatter(xMat[:, 1].flatten().A[0], yMat.flatten().A[0], s=20, c='blue', alpha=.5)
    plt.title('DataSet')
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.show()


"""
函数说明:判断拟合曲线的拟合效果
Parameters:
    xArray - x数据集
    yArray - y数据集
    w - 回归系数
Returns:
    correlation - 相关性
Author:
    zyx
Modify:
    2019-03-24
"""


def Correlation(xArray, yArray, w):
    xMat = np.mat(xArray)
    yMat = np.mat(yArray)
    yHat = xMat * w
    correlation = np.corrcoef(yHat.T, yMat)
    print("拟合度:", correlation)
    return correlation


if __name__ == '__main__':
    xArray, yArray = loadDataSet("ex0.txt")
    plotDataSet(xArray, yArray)
    w = standRegres(xArray, yArray)
    plotRegression(xArray, yArray, w)
    Correlation(xArray, yArray, w)

猜你喜欢

转载自blog.csdn.net/qq_39514033/article/details/88780199