机器学习笔记一元线性回归原理公式及代码实现

Posted 在青青草原上抓羊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器学习笔记一元线性回归原理公式及代码实现相关的知识,希望对你有一定的参考价值。

概要

线性回归是逻辑回归的基础,逻辑回归又是神经网络的组成部分,用于解决2分类问题

线性回归是所有算法的基础

线性关系 与 非线性关系

概念:

  • 线性关系是指变量之间的关系是一次函数,一个自变量x和因变量y的关系表示为一条直线,两个自变量和因变量y的关系表示为一个平面
  • 非线性关系是指一个自变量x和因变量y的关系表示为一条曲线,两个自变量和因变量y的关系表示为一个曲面

一个自变量x就等同于一个特征,拟合的时候就是一条线,而如果是多个特征,则是拟合面

线性关系可以理解为就是一次函数,不管有多少个自变量

示例:

  • 线性关系:$$y = a\\times x + b$$
  • 非线性关系:$$y = x^2$$

回归问题

概念:预测一个连续问题的数值,

线性回归主要用于处理回归问题,少数情况用于处理分类问题

一元线性回归

概念:用来描述自变量和因变量都只有一个(一个自变量称为一元)的情况,且自变量和因变量之间呈线性关系(一次函数)的回归模型

表示形式:$$y = a \\times x + b$$

只有x一个自变量,y为因变量,a为斜率,也称为x的权重,b为截距

作用:通过一元线性回归模型寻找到一条合适的直线,最大程度地拟合自变量 x 和因变量 y 之间的关系,这样我们知道一个 x 的值,就可以通过这条拟合的直线找到最可能的 y

学习一元线性模型的过程就算通过训练数据得到合适的a和b的过程,也就是该一元线性模型的参数即为 a 和 b,当输入一个新的测试数据点的时候,我们可以通过训练好的模型来进行预测。

模型好坏评价方式

目标:预测值与真实值之间的差距越小越好,距离越小,代表我们的模型效果越好

很自然的一个想法是:对于每一个点(x)都计算

\\[y - y\\_predict \\]

然后将所有的值进行累加最后除以样本数,这样是为了减少样本对于结果的影响。

公式:

\\[\\displaystyle\\frac1n\\displaystyle \\sum_i=1^n(y^i-y\\_predict^i) \\]

这个公式存在的问题:预测出来的值有可能大于真实值也可能小于真实值,这将导致误差被虚弱,正负中和导致最终累加误差接近于 0

改进:对每个点的误差计算取绝对值,也就是\\(|y^i-y\\_predict^i|\\),之后我们再进行累加

问题:后续的误差计算以及求导问题

绝对值函数,比如$$y = |x|$$在x=0处连续,但是在x处左导数为-1,右导数为1,不相等,可导函数必须光滑,所以函数在x=0不可导

进一步优化:对于每个点计算得到的误差,对这个结果做一次平方,并且为了忽略样本数的影响,取平均值

公式:

\\[\\displaystyle\\frac1n\\displaystyle \\sum_i=1^n(y^i-y\\_predict^i)^2 \\]

最小二乘法

由于

\\[\\displaystyle y\\_predict^i=ax^i+b \\]

代入上一节的公式中

\\[\\displaystyle\\frac1n\\displaystyle \\sum_i=1^n(y^i-ax^i-b)^2 \\]

通过最小二乘法来寻找最优的参数 a 和 b,从而使这个表达式尽可能的小

概念:一种数学优化技术,通过最小化误差的平方和来寻找最优的参数

公式:

\\[\\displaystyle a=\\frac\\sum_i=1^n(x^i-\\overline x)(y^i-\\overline y)\\sum_i=1^n(x^i-\\overline x)^2 \\]

\\[\\displaystyle b = \\overline y - a\\overline x \\]

代码实现

import numpy as np
from matplotlib import pyplot as plt

if __name__ == \'__main__\':
    # 准备数据
    x = np.array([1, 2, 4, 6, 8])  # 一元线性回归模型仅处理向量,而不能处理矩阵
    y = np.array([2, 5, 7, 8, 9])
    x_mean = np.mean(x)
    y_mean = np.mean(y)
    
    # 求a和b
    denominator = 0.0  # 分母
    numerator = 0.0  # 分子
    for x_i, y_i in zip(x, y):  # 将x, y向量合并起来形成元组(1, 2)、(2, 5)
        numerator += (x_i - x_mean) * (y_i - y_mean)
        denominator += (x_i - x_mean) ** 2
    a = numerator / denominator
    b = y_mean - a * x_mean
    
    # 用a和b构造线性函数,输出的预测值存入y_predict
    y_predict = a * x + b  # 这个函数是非常拟合训练集x的
    
    # 画出这条直线,以及训练集的数据
    plt.scatter(x, y, color=\'b\')
    plt.plot(x, y_predict, color=\'r\')
    plt.xlabel(\'x\', fontsize=15)
    plt.ylabel(\'y\', fontsize=15)
    plt.show()
    
    # 输入测试数据,回归一个值
    x_test = 7
    y_predict_test = a * x_test + b
    print(y_predict_test)

一元线性回归模型仅处理向量,而不能处理矩阵

进行一定的封装以后:

import numpy as np
import matplotlib.pyplot as plt

class SimpleLinearRegressionSelf:

    # 初始化变量
    def __init__(self):
        """初始化simple linear regression模型"""
        self.a_ = None  # 类内使用,非用户外部输入的变量
        self.b_ = None  # 类内使用,非用户外部输入的变量

    # 训练模型
    def fit(self, x_train, y_train):
        assert x_train.ndim == 1
        x_mean = np.mean(x_train)
        y_mean = np.mean(y_train)
        denominator = 0.0
        numerator = 0.0

        for x_i, y_i in zip(x_train, y_train):
            numerator += (x_i - x_mean) * (y_i - y_mean)
            denominator += (x_i - x_mean) ** 2
        self.a_ = numerator / denominator
        self.b_ = y_mean - self.a_ * x_mean

        return self

    # 预测
    def predict(self, x_test_group): # 输入的是向量集合
        # 对输入向量集合中的每一个向量都进行一次预测,预测的具体实现被封装在_predict函数中
        return np.array([self._predict(x_test) for x_test in x_test_group])

    def _predict(self, x_test):
        # 求每一个输入的x_test以得到预测值
        return self.a_ * x_test + self.b_

    # 衡量模型分数
    def mean_squared_error(self, y_true, y_predict):
        return np.sum((y_true - y_predict) ** 2) / len(y_true)

    def r_square(self, y_true, y_predict):
        # 计算指定数据(数组元素)沿指定轴的方差
        return 1 - (self.mean_squared_error(y_true, y_predict) / np.var(y_true))


if __name__ == \'__main__\':
    x = np.array([1, 2, 4, 6, 8])
    y = np.array([2, 5, 7, 8, 9])

    lr = SimpleLinearRegressionSelf()
    lr.fit(x, y)
    print(lr.predict([7]))
    print(lr.r_square([8, 9], lr.predict([6, 8])))

此处衡量模型分数的公式为:

\\[\\displaystyle R^2 = 1-\\frac\\frac1n\\sum_i=1^n(y\\_predict^i-y^i)^2\\sum_i=1^n(\\overline y-y^i)^2 \\]

以上是关于机器学习笔记一元线性回归原理公式及代码实现的主要内容,如果未能解决你的问题,请参考以下文章

sklearn实现一元线性回归 Python机器学习系列

机器学习之线性回归

机器学习--线性回归模型原理

机器学习模型和算法

一元线性回归的数学原理

什么是线性回归方程?