机器学习基础学习-多元线性回归问题(梯度下降法实现)

2023-11-15

1、基本概念

在之前的博客当中描述了怎样模拟出了梯度下降的过程
gradientDescent
如果是多维情况,theta其实是一个向量,那么对其求导的损失函数也是向量,梯度就是损失函数对每个方向的theta求偏导。
和之前的一维线性回归相比,我们对只是对w这个数字进行求导,而现在针对多系数theta,对theta整个向量进行求导。
在这里插入图片描述
在这里插入图片描述

有两个参数的梯度下降法进行可视化,一圈一圈代表等高线,圈上的值就是梯度。越外层J的取值越大,越里层J的取值越小,在图的中心位置达到损失函数的最小值
在这里插入图片描述
在这里插入图片描述
对每一个维度的theta进行求导(这里的Xb注意依然是加上了一列恒为1的一列,代表截距)
在这里插入图片描述
在上面的式子当中,可以看到求导之后的结果其实是一个求和的过程,也就是说在这里如果样本数量越大,梯度也就越大,这显然是不合理的,最后我们的梯度应该和样本数量m是无关的。所以下面改变目标函数(除以样本数量m,再提取公共的2),最后发现这个结果就是y的预测值和真值之间的MSE值(均方误差)
在这里插入图片描述

2、代码实现

这里为了可视化方便,采取的数据都是一维的数据,但是实际上是对矩阵进行处理。

(1)损失函数
在这里插入图片描述

np.sum((y - X_b.dot(theta)) ** 2 / len(X_b)

(2)求梯度
在这里插入图片描述

# 梯度(比较笨的方法)
def dJ(theta, X_b, y):
  res = np.empty(len(theta)) # 开一个和theta一样大的空间(因为要对theta的每一个元素求偏导)
  res[0] = np.sum(X_b.dot(theta) - y) # 第一行单独写,其他的要写一个循环
  for i in range(1, len(theta)):
    res[i] = (X_b.dot(theta) - y).dot(X_b[:,i]) # X_b[:,i]相当于取出第i列,也就是第i个特征值
  return res * 2 / len(X_b)

(3)X_b
在这里插入图片描述

# X添加一列样本个数行、1列,每个取值都是1的一列
X_b = np.hstack([np.ones((len(X), 1)), X])

(4)总体代码

# 多维线性回归问题(梯度下降法)

import numpy as np
import matplotlib.pyplot as plt

# 设置随机种子
np.random.seed(666)
# 用一维数据方便可视化,但实际是对矩阵进行操作
x = np.random.random(size = 100)
y = x * 3. + 4. + np.random.normal(size = 100) # 噪音:均值为0,方差为1

X = x.reshape(-1, 1) # 数组array中的方法,作用是将数据重新组织成100行1列的数据

# print('X数组', X.shape)
# print('y数组', y.shape)

plt.scatter(x, y)
plt.show()

# 损失函数
def J(theta, X_b, y):
  try:
    return np.sum((y - X_b.dot(theta)) ** 2 / len(X_b))
  except:
    return float('inf') # 返回float最大值

# 梯度(比较笨的方法)
def dJ(theta, X_b, y):
  res = np.empty(len(theta)) # 开一个和theta一样大的空间(因为要对theta的每一个元素求偏导)
  res[0] = np.sum(X_b.dot(theta) - y) # 第一行单独写,其他的要写一个循环
  for i in range(1, len(theta)):
    res[i] = (X_b.dot(theta) - y).dot(X_b[:,i]) # X_b[:,i]相当于取出第i列,也就是第i个特征值
  return res * 2 / len(X_b)

# 直接复制之前模拟梯度下降过程的代码,然后进行更改
def gradient_descent(X_b, y, initial_theta, eta, n_iters = 1e4, epsilon = 1e-8):
  theta = initial_theta
  i_iters = 0

  while i_iters < n_iters:
      gradient = dJ(theta, X_b, y) # 求梯度
      last_theta = theta # theta重新赋值前,记录上一场的值
      theta = theta - eta * gradient # 通过一定的eta学习率取得下一个点的theta
      # 最近两点的损失函数差值小于一定精度,退出循环
      if(abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
          break
      i_iters += 1
  return theta


''' 
  初始化数值
'''
# X添加一列样本个数行、1列,每个取值都是1的一列
X_b = np.hstack([np.ones((len(X), 1)), X])
initial_theta = np.zeros(X_b.shape[1]) # 设置n+1维的向量,X_b.shape[1]:第一行的维数
eta = 0.1

theta = gradient_descent(X_b, y, initial_theta, eta)

print('theta', theta)

运行结果
在这里插入图片描述
这里的theta[0]就是截距,theta[1]就是斜率,和我们一开始设置的一致,说明梯度下降法成功训练了我们的模型

y = x * 3. + 4. + np.random.normal(size = 100)

最后

所有的思想都在上面,最后我把多元线性回归的两种方法总结在了一起

# 多元线性回归问题;解析解+梯度下降法(也能解决一元线性回归问题)
import numpy as np
from sklearn import datasets
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split

class LinearRegression:
  def __init__(self):
      # 初始化Linear Regression模型
      self.coef_ = None # 系数,对应theta1-n,对应的向量
      self.interception_ = None # 截距,对应theta0
      self._theta = None # 定义私有变量,整体计算的theta



  '''
    梯度下降
  '''
  def fit_gd(self, X_train, y_train, eta = 0.01, n_iters = 1e4): 
    # 根据训练数据集X_train, y_ .train训练Linear Regression模型
    # X_train的样本数量和y_train的标记数量应该是一致的
    # 使用shape[0]读取矩阵第一维度的长度,在这里就是列数
    assert X_train.shape[0] == y_train.shape[0], \
    "the size of x_ .train must be equal to the size of y_ train"
    # 损失函数
    def J(theta, X_b, y):
      try:
        return np.sum((y - X_b.dot(theta)) ** 2 / len(y))
      except:
        return float('inf') # 返回float最大值

    # 梯度(比较笨的方法)
    def dJ(theta, X_b, y):
      res = np.empty(len(theta)) # 开一个和theta一样大的空间(因为要对theta的每一个元素求偏导)
      res[0] = np.sum(X_b.dot(theta) - y) # 第一行单独写,其他的要写一个循环
      for i in range(1, len(theta)):
        res[i] = (X_b.dot(theta) - y).dot(X_b[:,i]) # X_b[:,i]相当于取出第i列,也就是第i个特征值
      return res * 2 / len(X_b)


    # 求解theta矩阵
    def gradient_descent(X_b, y, initial_theta, eta, n_iters = 1e4, epsilon = 1e-8):
      theta = initial_theta
      cur_iters = 0

      while cur_iters < n_iters:
          gradient = dJ(theta, X_b, y) # 求梯度
          last_theta = theta # theta重新赋值前,记录上一场的值
          theta = theta - eta * gradient # 通过一定的eta学习率取得下一个点的theta
          # 最近两点的损失函数差值小于一定精度,退出循环
          if(abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
              break
          cur_iters += 1
      return theta

    # 得到X_b
    X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
    initial_theta = np.zeros(X_b.shape[1]) # 设置n+1维的向量,X_b.shape[1]:第一行的维数
    # X_b.T是X_b的转置,.dot是点乘,np.linalg.inv是求逆
    # 获取theta
    self._theta = gradient_descent(X_b, y_train, initial_theta, eta, n_iters)

    self.interception_ = self._theta[0] # 截距
    self.coef_ = self._theta[1:] # 系数 
    return self




  '''
    解析解
  '''
  # 正规化方程
  # 训练过程(解析解)
  def fit_normal(self, X_train, y_train): # X_train和y_train都是矩阵
    # 根据训练数据集X_train, y_ .train训练Linear Regression模型
    # X_train的样本数量和y_train的标记数量应该是一致的
    # 使用shape[0]读取矩阵第一维度的长度,在这里就是列数
    assert X_train.shape[0] == y_train.shape[0], \
    "the size of x_ .train must be equal to the size of y_ train"
    # np.hstack():在水平方向上平铺,就是在横向上多加一列
    # np.ones(矩阵大小, 列数)是增加一列恒为1的一列
    # 得到X_b
    X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
    # X_b.T是X_b的转置,.dot是点乘,np.linalg.inv是求逆
    self._theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y_train)

    self.interception_ = self._theta[0] # 截距
    self.coef_ = self._theta[1:] # 系数
    return self
  
  '''
    预测过程
  '''
  def predict(self, X_predict):
    # 给定待预测数据集X_predict,返回表示X_predict的结果向量
    X_b = np.hstack([np.ones((len(X_predict), 1)), X_predict])
    return X_b.dot(self._theta)

  '''
    确定精度,评价多元线性回归的结果
  '''
  def score(self, X_test, y_test):
    # 根据测试数据集X_test 和y_test 确定当前模型的准确度
    y_predict = self.predict(X_test)
    return r2_score(y_test, y_predict) # r2_score求真值y_test和预测值y_predict的r方

  '''
    显示属性
  '''
  def __repr__(self):
      return "LinearRegression()"


# 加载波士顿房价数据集,并划分为X_train,y_train
# 波士顿房价
boston = datasets.load_boston()

# X_train = boston.data
# y_train = boston.target

X = boston.data
y = boston.target

X = X[y < 50.0]
y = y[y < 50.0]
# 分出测试集合训练集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)

'''
  实例化(数学解解法)
'''
reg = LinearRegression()
# 进行训练
reg.fit_normal(X_train, y_train) # LinearRegression()
# 预测r方值
print('预测精确度', reg.score(X_test, y_test))
# 截距
print('数学解系数reg.coef_', reg.coef_)
print('数学解截距reg.interception_', reg.interception_)
print('数学解预测值', reg.predict(X_test))
print('y_test测试值', y_test)



'''
  实例化(梯度下降解法)
'''
lin_reg = LinearRegression()
# 设置随机种子
np.random.seed(666)
# 用一维数据方便可视化,但实际是对矩阵进行操作
x = np.random.random(size = 100)
y = x * 3. + 4. + np.random.normal(size = 100) # 噪音:均值为0,方差为1

X = x.reshape(-1, 1) # 数组array中的方法,作用是将数据重新组织成100行1列的数据
# 梯度下降法进行训练
lin_reg.fit_gd(X, y) # LinearRegression()

print('梯度下降系数reg.coef_', lin_reg.coef_)
print('梯度下降截距reg.interception_', lin_reg.interception_)




运行结果
在这里插入图片描述

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

机器学习基础学习-多元线性回归问题(梯度下降法实现) 的相关文章

随机推荐

  • EasyTalking微博系统

    EasyTalking微博系统 摘要 随着互联网的迅猛发展 人们的日常生活 学习工作已经离不开网络 人们的生活和工作在未来的生活中将越来越依赖于计算机网络技术的发展 越来越网络化 电子化 虚拟化 便捷化 Internet目前的应用历程和发展
  • 如何const定义一个不可变数组

    有个常见的面试题 我们知道 const是es6中新增用于定义常量 但是对于引用类型来说 const 所说的常量 是指 对应的指针或者说地址是常量 那么 如果我们要求 我们定义的数组里面的元素也是不可改变的呢 先来看现象 const a 1
  • webgl--attribute相关使用

    attribute 是存储限定符 是专门用于向外部导出与点位相关的对象的 这类似于es6模板语法中export vec4 是变量类型 vec4是4维矢量对象 a position 是变量名 之后在js中会根据这个变量名导入变量 这个变量名是
  • [CTSC2008]网络管理Network【树状数组+主席树】

    题目链接 题意 有一棵N个点的树 每个点有对应的权值 现在有这样的操作 0 a b 将a点的权值改成为b k a b 询问a到b的链上第k大的权值是几 我们可以用dfs序的树上差分的方式来解决这个问题 可以发现 求u到v的信息 其实就是求u
  • 【c++】角度与弧度转换

    角度转换为弧度 double angle to radian double degree double min double second double flag degree lt 0 1 0 1 0 判断正负 if degree lt
  • matlab与机器学习(二)程序基本操作(含代码解析)

    备注 之间的为注释内容 注释后面的内容 matlab形成自己的编程风格更有利于简洁的编程界面 图像的初步处理可应用于论文撰写上 文章更有说服力 程序调试有利于发现逻辑问题 都是必备的基础知识 I 清空环境变量及命令 clear all cl
  • Python selenium基础用法详解

    活动地址 CSDN21天学习挑战赛 学习的最大理由是想摆脱平庸 早一天就多一份人生的精彩 迟一天就多一天平庸的困扰 学习日记 目录 学习日记 一 Selenium库介绍 1 Selenium简介 2 Selenium的安装 3 安装浏览器驱
  • RabbitMQ系列(十五)RabbitMQ进阶-SprintBoot集成RabbitMQ使用

    RabbitMQ进阶 SprintBoot集成RabbitMQ使用 文章目录 RabbitMQ进阶 SprintBoot集成RabbitMQ使用 1 构建项目 1 1 Spring Init创建项目 1 2 新建项目包 2 初始化Rabbi
  • 【Chrome】分享几个常用的插件,持续集成

    文章目录 一 准备 打开扩展程序 1 1 方式一 1 2 方式二 1 3 打开开发者模式 二 Chrome应用商店在线安装 需要科学上网 三 离线安装 3 1 离线crx下载地址 3 2 crx方式安装 3 3 加载已解压的扩展程序 方式安
  • 计算机组成原理实验——五、单周期CPU设计

    一 实验目的 掌握指令执行过程的5个阶段 掌握每条指令的数据通路选择 掌握译码器和控制器的功能和实现 掌握数据输入输出处理的方法 实现risc v中RV32I指令的单周期CPU 利用实现的risc v CPU实现平方数 二 实验内容 实现r
  • DHorse系列文章之操作手册

    在介绍DHorse的操作之前 我们先来看一下发布一个系统的流程是什么样的 发布系统的流程 我们以一个Springboot系统为例 来说明一下发布流程 1 首先从代码仓库下载代码 比如Gitlab 2 接着是进行打包 比如使用Maven 3
  • 求和2.14

    n int input 输入数字的数量 a list map int input split 输入一个列表 print a S 0 s1 sum a for i in range 0 n s1 a i S a i s1 print S
  • 使用PHPExcel实现数据批量导入到数据库

    此例子只使用execel2003的 xls文档 若使用的是其他版本 可以保存格式为 Execel 97 2003 工作簿 xls 即 xls文件类型即可 功能说明 只能上传Excel2003类型的xls文件 大小不超过5M 可下载例子模板添
  • 配置服务器实现无缝连接

    在进行网络爬虫时 经常会面临目标网站的IP封锁 反爬虫策略等问题 为了解决这些问题 配置代理服务器是一种常见的方法 本文将向您介绍如何配置代理服务器与爬虫实现无缝连接 助您顺利进行数据采集 一 了解代理服务器的作用 代理服务器充当中间人的角
  • vue3.0 vue.config.js 配置实战

    项目常用配置 const path require path const UglifyJsPlugin require uglifyjs webpack plugin function resolve dir return path joi
  • MIUI11系统详细卡刷开发版获取Root超级权限的步骤

    小米的机器不同手机型号一般情况官方论坛都提供两个不同的系统 它们是稳定版和开发版 稳定版没有提供root权限管理 开发版中就提供了root权限 很多情况下我们需要使用的一些功能强大的工具 都需要在root权限下工作 就比如我们公司在使用的营
  • 2、应用入口类 SpringbootApplication&核心注解

    官网 https docs spring io spring boot docs 2 5 8 SNAPSHOT reference htmlsingle getting started installing 核心注解分析 许多 Spring
  • 【Postgresql】触发器某个字段更新时执行,行插入或更新执行

    Postgresql 触发器某个字段更新时执行 行插入或更新执行 1 postgresql触发器 2 触发器的创建及示例 1 字段更新时 触发 2 行插入或更新时 触发 3 触发器的删除 4 触发器的坑 参考 1 postgresql触发器
  • 服务器好玩的项目_推荐!github上四个与100有关的优质项目

    编辑 zero 关注 搜罗最好玩的计算机视觉论文和应用 AI算法与图像处理 微信公众号 获得第一手计算机视觉相关信息 今天要分享四个非常优质的开源项目 一定能够有效的提升你的coding能力 1 Python 100天从新手到大师 2 10
  • 机器学习基础学习-多元线性回归问题(梯度下降法实现)

    1 基本概念 在之前的博客当中描述了怎样模拟出了梯度下降的过程 如果是多维情况 theta其实是一个向量 那么对其求导的损失函数也是向量 梯度就是损失函数对每个方向的theta求偏导 和之前的一维线性回归相比 我们对只是对w这个数字进行求导