机器学习——线性回归模型及python代码实现

2023-11-09

《机器学习:公式推导与代码实践》鲁伟著读书笔记。在机器学习的学习过程中,相信大家首先要学习的就是线性模型。而线性模型中,线性回归(Linear Regression)是一种非常经典方法。现在我从线性回归的数学原理出发,手推数学公式,并结合python代码,对线性回归模型进行系统性的总结。

线性回归的数学原理

线性回归从实质上说为通过训练进而得到一个线性模型来根据输入数据 X X X来拟合输出 y y y。面对多元化的线性回归问题,设训练模型的输入矩阵为 X ∈ R m × d X \in \mathbb{R}^{m \times d} XRm×d,其中 m m m为训练集输入数据的组数, d d d为变量 X X X的特征维数。输出 y ∈ R m × 1 y \in \mathbb{R}^{m \times1} yRm×1为了方便矩阵化的最小二乘法的推导,可以设权重为 ω ∈ R d × 1 \omega\in \mathbb{R}^{d \times 1} ωRd×1与偏置为 b ∈ R m × 1 b\in \mathbb{R}^{m\times 1} bRm×1。我采用均方误差来度量预测与标签之间的损失,所以我们的线性回归任务的优化目标便为使线性回归模型的预测值和输出的真实值之间的均方误差最小化。
参数优化的目标函数为: ( ω ∗ , b ∗ ) = arg ⁡ min ⁡ ( y − ( X ω + b ) ) T ( y − ( X ω + b ) ) ({\omega}^{*}, b^{*})=\arg \min (y-(X \omega+b))^{T}(y-(X \omega+b)) (ω,b)=argmin(y(Xω+b))T(y(Xω+b)) L = ( y − ( X ω + b ) ) T ( y − ( X ω + b ) ) L=(y-(X \omega+b))^{T}(y-(X \omega+b)) L=(y(Xω+b))T(y(Xω+b)),并就参数优化的目标函数对 ω \omega ω进行求导,求得权重的梯度。推导过程如下: L = y T y − y T ( X ω + b ) − ( ω T X T + b T ) y + ω T X T X ω + ω T X T b + b T X ω + b T b L=y^{T} y-y^{T}(X \omega+b)-\left(\omega^{T} X^{T}+b^{T}\right) y+\omega^{T} X^{T} X \omega+\omega^{T} X^{T} b+b^{T} X \omega+b^{T} b L=yTyyT(Xω+b)(ωTXT+bT)y+ωTXTXω+ωTXTb+bTXω+bTb又因为矩阵微分公式: ∂ a T x ∂ x = ∂ x T a ∂ x = a \frac{\partial a^{T}x}{\partial x}=\frac{\partial x^{T}a}{\partial x}=a xaTx=xxTa=a ∂ x T A x ∂ x = ( A + A T ) x \frac{\partial x^{T}Ax}{\partial x}=(A+A^{T})x xxTAx=(A+AT)x
∂ L ∂ ω = ∂ y T y ∂ ω − ∂ y T ( X ω + b ) ∂ ω − ∂ ( ω T X T + b T ) y ∂ ω + ∂ ω T X T X ω ∂ ω + ∂ ω T X T b ∂ ω + ∂ b T X ω ∂ ω + ∂ b T b ∂ ω \frac{\partial L}{\partial {\omega}}=\frac{\partial y^{T} y}{\partial {\omega}}-\frac{\partial y^{T}(X \omega+b)}{\partial {\omega}}-\frac{\partial \left(\omega^{T} X^{T}+b^{T}\right) y}{\partial {\omega}}+\frac{\partial {\omega}^{T} X^{T} X {\omega}}{\partial {\omega}}+\frac{\partial {\omega}^{T} X^{T} b}{\partial {\omega}}+\frac{\partial b^{T}X{\omega}}{\partial {\omega}}+\frac{\partial b^{T}b}{\partial {\omega}} ωL=ωyTyωyT(Xω+b)ω(ωTXT+bT)y+ωωTXTXω+ωωTXTb+ωbTXω+ωbTb通过化简得到:
∂ L ∂ ω = 0 − X T y − X T y + ( X T X + X T X ) ω + X T b + X T b + 0 \frac{\partial L}{\partial {\omega}}=0- X^{T}y-X^{T}y+(X^{T}X+X^{T}X)\omega+X^{T}b+X^{T}b+0 ωL=0XTyXTy+(XTX+XTX)ω+XTb+XTb+0 ∂ L ∂ ω = 2 X T ( X ω + b − y ) \frac{\partial L}{\partial {\omega}}=2X^{T}(X\omega+b-y) ωL=2XT(Xω+by)即: ∂ L ∂ ω = 2 X T ( y ^ − y ) \frac{\partial L}{\partial {\omega}}=2X^{T}(\hat{y}-y) ωL=2XT(y^y)下一步对偏置进行求导,得到偏置的梯度。 ∂ L ∂ b = ∂ y T y ∂ b − ∂ y T ( X ω + b ) ∂ b − ∂ ( ω T X T + b T ) y ∂ b + ∂ ω T X T X ω ∂ b + ∂ ω T X T b ∂ b + ∂ b T X ω ∂ b + ∂ b T b ∂ b \frac{\partial L}{\partial b}=\frac{\partial y^{T} y}{\partial b}-\frac{\partial y^{T}(X \omega+b)}{\partial b}-\frac{\partial \left(\omega^{T} X^{T}+b^{T}\right) y}{\partial b}+\frac{\partial {\omega}^{T} X^{T} X {\omega}}{\partial b}+\frac{\partial {\omega}^{T} X^{T} b}{\partial b}+\frac{\partial b^{T}X{\omega}}{\partial b}+\frac{\partial b^{T}b}{\partial b} bL=byTybyT(Xω+b)b(ωTXT+bT)y+bωTXTXω+bωTXTb+bbTXω+bbTb ∂ L ∂ b = 0 − y − y + X ω + X ω + 2 b \frac{\partial L}{\partial b}=0-y-y+X\omega+X\omega+2b bL=0yy+Xω+Xω+2b ∂ L ∂ b = 2 ( X ω + b − y ) \frac{\partial L}{\partial b}=2(X\omega+b-y) bL=2(Xω+by)即: ∂ L ∂ b = 2 ( y ^ − y ) \frac{\partial L}{\partial b}=2(\hat{y}-y) bL=2(y^y)最后便可以运用权重和偏置的梯度值完成在训练过程中参数的更新,例如: ω ∗ = ω − l e a r n i n g r a t e ∗ ∂ L ∂ ω \omega^{*}=\omega-learningrate*\frac{\partial L}{\partial {\omega}} ω=ωlearningrateωL b ∗ = b − l e a r n i n g r a t e ∗ ∂ L ∂ b b^{*}=b-learningrate*\frac{\partial L}{\partial b} b=blearningratebL

线性回归的NumPy手撕代码

按照推理得出的参数更新梯度,线性回归模型主体部分的实现如下:

初始化权重和偏置参数

def init_params(train_dim):
	'''
	输入:
	train_dim:样本特征数
	输出:
	w:初始化后的权重
	b:初始化后的偏置
	'''
	w = np.zeros((train_dim,1))
	b = 0
	return w,b

线性回归算法

def linear_regress(X,y,w,b):
	'''
	输入:
	X:输入数据
	y:输出标签
	w:权重
	b:偏置
	输出:
	y_hat:预测值
	loss:预测值与真实值的均方误差
	dw:权重的一阶梯度
	db:偏置的一阶梯度
	'''
	num_train = X.shape[0]
	num_feature = X.shape[1]
	y_hat = np.dot(X,w) + b
	loss = np.sum((y_hat-y)**2)/num_train
	dw = np.dot(X.T,(y_hat-y))/num_train
	db = np.sum((y_hat-y))/num_train
	return y_hat, loss, dw, db	

定义训练过程

采用梯度下降的方法对参数进行更新。

def train(X, y, learning_rate=0.01, epochs=10000):
	'''
	输入:
	X:输入数据
	y:输出标签
	learning_rate:学习率
	epochs:迭代次数
	输出:
	loss_his:每一代的误差
	params:参数字典
	grads:优化后的梯度
	'''
	loss_his = []
	w, b = init_params(X.shape[1])
	for i in range(epochs):
		y_hat, loss, dw, db = linear_regress(X, y, w, b)
		w += -learning_rate*dw
		b += -learning_rate*db
		loss_his.append(loss)
	params = {'w':w, 'b':b}
	grads = {'dw':dw,'db':db}
	return loss_his, params, grads

定义预测过程

def predict(X, params):
	'''
	输入:
	X:测试数据集
	params:模型训练参数
	输出:
	y_pre:预测值
	'''
	w = params['w']
	b = params['b']
	y_pre = np.dot(X, w) + b
	return y_pre

实战

我们采用sklearn中的diabetes数据集进行测试。其一共有442个样本量,每组样本有10个特征。将数据集按照8:2 的比例进行划分训练集和测试集。具体训练过程如下:
导入数据并划分数据集

from sklearn.datasets import load_diabetes
from sklearn.utils import shuffle # 打乱数据的函数
import numpy as np

diabetes = load_diabetes()
data,target = diabetes.data, diabetes.target
X, y = shuffle(data, target, random_state=13) # 固定random_state后,每次打乱的数据集都是一样的
train_data = int(X.shape[0]*0.8)
X_train, y_train = X[:train_data], y[:train_data]
X_test, y_test = X[train_data:], y[train_data:]
y_train = y_train.reshape((-1,1)) # 将target从(1,m)转变为(m,1),其实就是转置了一下
y_test = y_test.reshape((-1,1))

# train model
loss_his, params, grads = train(X_train, y_train, 0.01, 10000)

# predict model
y_pre = predict(X_test, params)

# 评价模型
def r2_score(y_test, y_pre):
	y_avg = np.mean(y_test)
	ss_tot = np.sum((y_test-y_avg)**2) # 总离差平方和
	ss_res = np.sum((y_test-y_pre)**2) # 残差平方和
	r2 = 1-(ss_res/ss_tot)
	return r2
pre_r2 = r2_score(y_test, y_pre)
print(pre_r2)

最后计算得到的线性回归模型 R 2 R^2 R2系数为0.5334188778093094。预测精准度不是很高,说明线性回归的预测性能不高。下一个章节,我将总结对数几率回归模型,即logistic regression。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器学习——线性回归模型及python代码实现 的相关文章

随机推荐

  • 一步一步教你用idea上交代码到gitee(图文解释)

    一步一步教你用idea上交代码到gitee 图文解释 文章目录 一步一步教你用idea上交代码到gitee 图文解释 工具准备 具体操作 结语 工具准备 首先 我们进行代码的提交需要两个工具包 在我的上一篇中有讲 大家可以自行去提取 2条消
  • .net 批量注册服务

    假设我们需要注册xxxQuery服务 例如下图中的BarQuery和FooQuery 传统的做法是 services TryAddScoped
  • vscode 运行和调试 javascript 代码

    安装node 安装vscode 扩展包 code runer 配置vs code下有关F5的操作的文件 参考地址
  • 【Zabbix实战之运维篇】Zabbix监控Docker容器配置方法

    Zabbix实战之运维篇 Zabbix监控Docker容器配置方法 一 检查Zabbix监控平台状态 1 检查Zabbix各组件容器状态 2 奸诈Zabbix server状态 二 下载监控模板 1 进入Zabbix官网下载页面 2 查看下
  • 微信小程序中识别html标签的方法

    rich text组件 在微信小程序中有一个组件rich text可以识别文本节点或是元素节点 具体入下 需要识别的数据放在data中 然后放在nodes属性中即可
  • 编写程序:5类员工有对应封装类,创建Employee数组,若干不同的Employee对象,并实现增删改查功能(《黑马程序员》P144编程题加强版)

    文章目录 Employee类 SalariedEmployee类 HourlyEmployee类 SalesEmployee类 BasePlusSalesEmployee类 Test类 实现增删改查 原题 1 Employee 这是所有员工
  • 【python】深入了解Selenium-PageObject

    1 PageObject 定义 Page Object 简称PO 模式 是Selenium实战中最为流行 并且是自动化测试中最为熟悉和推崇的一种设计模式 在设计自动化测试时 把页面元素和元素的操作方法按照页面抽象出来 分离成一定的对象 然后
  • Sophus使用记录

    sophus库是一个基于Eigen的C 李群李代数库 可以用来方便地进行李群李代数的运算 头文件 主要用到以下两个头文件 include
  • 基于水文规约SL651-2014的“定时报”解析

    一 概述 水文监测数据通信规约SL651 2014规定了水文监测系统中前端传感器与遥测终端以及中心站之间的数据通信协议 本文将以M21F系列RTU为例 详细描述符合SL651 2014数据通信规约标准的遥测站终端与中心站之间的 定时报 报文
  • Go开源库Excelize介绍,电子Excel表格操作强大的库

    Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库 基于 ECMA 376 ISO IEC 29500 国际标准 项目作者是续 日 现任阿里巴巴软件工程师 曾就职百度 奇虎360公司 前百度Go语言编程委员
  • 循环监测b站用户粉丝数、舰长数及增量 程序

    前言 开发语言 python 3 8 功能介绍 循环监测b站用户粉丝数 舰长数及增量 实时打印 并存入数据库中 使用说明 运行 双击运行 bat 输入用户UID 回车 再输入循环周期 回车 即可开始监测 ps 数据存储是sqlite 可以使
  • 如何处理地址不对齐指令?

    连续不断是处理器取指的另一个目标 如果处理器在每一个时钟周期都能取一条指令 就可以源源不断的为处理器提供后续指令流 而不会出现空闲的时钟周期 地址不对齐导致问题 不管是从指令缓存 还是从ITCM中取指令 若处理器遇到了一条地址不对齐的指令
  • H桥L298N两端输出电压不同的原因

    目录 1 问题的证明 2 L298N的原理 3 问题的解决 在做拉力车的时候 电机总是转速不同 起初以为是电机问题 但换成新电机后仍然存在这种问题 又怀疑是导线的问题 因为两电机的导线粗细不同 误以为PWM调速时会被影响 后来锁定问题 就是
  • Leetcode337:打家劫舍 III

    在上次打劫完一条街道之后和一圈房屋后 小偷又发现了一个新的可行窃的地区 这个地区只有一个入口 我们称之为 根 除了 根 之外 每栋房子有且只有一个 父 房子与之相连 一番侦察之后 聪明的小偷意识到 这个地方的所有房屋的排列类似于一棵二叉树
  • 2605. 从两个数字数组里生成最小数字

    文章目录 Tag 题目来源 题目解读 解题思路 方法一 枚举比较法 方法二 集合的位运算表示法 写在最后 Tag 贪心 位运算 数组 题目来源 2605 从两个数字数组里生成最小数字 题目解读 给定两个各自只包含数字 1 到 9 的两个数组
  • ImportError: No module named ‘seaborn‘

    在已经使用pip install seaborn 或者 conda install seaborn 之后 在虚拟环境下 启动jupyter 但是报出下面错误 1 需要去考虑一下你的内核是不是发生改变 或者建议重启一下内核 注意 一般情况之下
  • ​微众区块链×华南理工:连续四年深度合作,共育区块链+ESG复合型人才

    近日 在经历了六周的紧张学习后 来自华南理工大学软件学院的同学们完成了第四届 区块链实训课 的答辩 该实训课由微众区块链与华南理工大学共建 也是双方第四次合作的成果 令人耳目一新的是 本次实训课在往年成熟的课程体系之上 新增了一门叫做 开源
  • thinkphp 随笔——模型更新成功返回的数据

    thinkphp 随笔 模型更新成功返回的数据 先上图 这是我修改了一个表内的 value 字段 修改成功之后返回了这个字段的最新值 thinkphp 随笔 个人博客 http www sharekong xyz 欢迎访问
  • 关于《时间管理》

    01 为什么需要时间管理 我们 多数人不是富二代 也不是官二代 如何比得过白富美和高富帅 在万千的不公平中 还有这唯一公平的资源 时间 好好把你的时间加以管理 以弥补并创造出其他的资源 人的一生两个最大的财富是 你的才华和你的时间 才华越来
  • 机器学习——线性回归模型及python代码实现

    机器学习 公式推导与代码实践 鲁伟著读书笔记 在机器学习的学习过程中 相信大家首先要学习的就是线性模型 而线性模型中 线性回归 Linear Regression 是一种非常经典方法 现在我从线性回归的数学原理出发 手推数学公式 并结合py