机器学习day6-线性代数2-梯度下降

6梯度下降

1.概念

引入梯度下降的原因:1.并不是所有的机器学习都是凸函数,并且可能存在多个极值,不能确定唯一解;2.特征和数据量较多时,矩阵计算量太大(逆矩阵运算的时间复杂度是(

$$
O(n^3)
$$

))

梯度下降:梯度表示损失函数对于模型参数的偏导数。对于每个可训练的参数,梯度告诉我们在当前参数下,沿着每个参数方向变化时,损失函数的变化率。通过计算损失函数对参数的梯度,算法可以根据梯度信息来调整参数从而沿着减少损失的方向更新模型进行调优。

$$
\bar e={\frac{1}{n}}\sum_{i=1}^{n}x_{i}^{2}w^{2}-{\frac{2}{n}}\sum_{i=1}^{n} x_{i}y_{i}w+{\frac{1}{n}}\sum_{i=1}^{n} y_{i}^{2}
$$

中损失函数对于参数w的梯度就是此时w的切线斜率。

梯度下降法是通过不断地优化从而得到最优解。(优化算法都是期望以最快的速度把模型参数w求解出来)

2.步骤

①.Random随机生成初始w,随机生成一组正态分布的数值

$$
w_0,w_1,w_2....w_n
$$

②.求梯度g,即损失函数在此w点上的切线斜率(求导)

③.g<0,表示切线斜率为负数,表示在导数为0的w值的左边,那么就应该把w往右调大不断逼近导数为0的w值;g>0,表示切线斜率为正,表示在导数为0的w值的右边,将w往左调小不断逼近导数为0的w值

④.判断是否收敛,如果收敛就跳出迭代,否则重复②-④。判断收敛的标准是:随着迭代看loss的值变化多少,如果很小甚至不再变化,则认为达到迭代。(迭代次数可以固定)

3.公式

$$
w^{n+1}=w^n-α*gradient
$$

$$
新值=旧值-学习率*导数
$$

学习率:学习率很小可以保证收敛,但是会增加计算;学习率较大,训练会震荡收敛;学习率过大,系统会来回震荡无法收敛

一般将学习率设置成一个小数,0.1,0.01,0.001,0.0001等,可以根据情况进行调整。一般学习率在整体迭代过程中不变,也可以设置成随着迭代次数增多学习率逐渐变小以更精准地得到最优解。

按照步骤来计算w的值

假设要求的损失函数的抛物线公式为:

$$
\bar e=10w^{2}-15.9w+6.5
$$

那么切线公式为:

$$
e'=20w-15.9
$$

w0=0.2,假设学习率为0.01(w0表示第0次w的值)

w1=w0-0.01*e'(w0)=0.2-0.01 *(20 * 0.2-15.9)=0.319

w2=w1-0.01 * e'(w1)=0.319-0.01 * (20 * 0.319-15.9)=0.4142

以此类推

w在最低点的左边还是右边:导数为负值,则w在最低值的左边,应该往右移动(减去一个负数=加上一个正数=往右移动);导数为正值,则w在最低值的右边,应该往左移动(加上一个负数=往左移动)

4.代码实现梯度下降

①.损失函数为一个特征的抛物线:

$$
loss(w_1)=(w_1-3.5)^2-4.5w_1+10
$$

#自己实现一维梯度下降算法(一个w)
import numpy as np
import matplotlib.pyplot as plt
​
w=np.linspace(-10,10,100)
#print(w)
def loss(w):return (w-3.5)**2-4.5*w+10
​
def dloss(w):return 2*(w-3.5)-4.5
#print(loss)
plt.plot(w,loss(w))
plt.show()
​
#梯度下降
#学习率
learning_rate=0.1
#初始化一个w值
np.random.seed(1)
w=np.random.randint(-10,20)#随机给一个w值:-5
print(w)
e=loss(w)#初始化的w为-5时的loss值
​
x=[w]
y=[e]
#第1次梯度下降
w=w-learning_rate*dloss(w)
e=loss(w)
x.append(w)
y.append(e)
#第2次梯度下降
w=w-learning_rate*dloss(w)
e=loss(w)
x.append(w)
y.append(e)
#第3次梯度下降
w=w-learning_rate*dloss(w)
e=loss(w)
x.append(w)
y.append(e)
​
plt.scatter(x,y)#画点
plt.show()
#自己实现一维梯度下降算法(一个w)-循环
import numpy as np
import matplotlib.pyplot as plt
#假设有一个函数是y=wx 通过损失函数的思路已经得出了损失函数
def loss(w):return (w-3.5)**2-4.5*w+10
#得出导函数
def dloss(w):return x*(w-3.5)-4.5
def train():#初始化随机给一个w值w=-10#np.random.randint(-10,20)#初始化学习率lr=0.1#更新次数epoch=1000#梯度下降更新wt0,t1=1,100for i in range(0,epoch):#print(i)lr=t0/(t1+i)w=w-lr*dloss(w)print(f"第{i}次w更新后的值:{w},更新后损失函数的值{loss(w)}")
​
train()
​

②.损失函数为两个特征的抛物线:

$$
loss(w_1,w_2)=(w_1-3.5)^2+(w_2-2)^2+3w_1w_2-4.5w_1+2w_2+20
$$

分别对w1,w2求导

$$
对w_1求导,就是把w_2看成一个常数: loss(w1)’=2(w_1-3.5)+0+3w_2-4.5=2w_1+3w_2-11.5
$$

$$
对w_2求导,就是把w_1看成一个常数: loss(w2)’=0+2(w_2-2)+3w_1+2=2w_2+3w_1-2
$$

参照一维求梯度下降的算法:

#自己实现二维梯度下降算法(两个w)
import numpy as np
​
#假设有一个函数是y=wx 通过损失函数的思路已经得出了损失函数
def loss(w1,w2):return (w1-3.5)**2+(w2-2)**2+3*w1*w2-4.5*w1+2*w2+20
#得出导函数
def dloss_w1(w1,w2):return 2*(w1-3.5)+3*w2-4.5
def dloss_w1(w1,w2):return 2*(w2-2)+3*w1+2
#梯度下降算法
def train():#初始化随机给一个w1,w2值w1=10#np.random.randint(-10,20)w2=10#初始化学习率lr=0.1#更新次数epoch=1000#梯度下降更新wt0,t1=1,100for i in range(0,epoch):#更新w1,w2lr=t0/(t1+i)w1_=w1w2_=w2w1=w1-lr*dloss(w1_,w2_)w2=w2-lr*dloss(w1_,w2_)print(i,w1,w2,loss(w1_,w2_))#print(f"第{i}次w更新后的值:{w1,w2},更新后损失函数的值{loss(w)}")
​
train()
5.API

①.Batch Gradient Descent (BGD):批量梯度下降,每一次迭代都使用全部的训练样本来计算梯度更新权重。优点:更新方向最准确;缺点:计算量大且速度慢。

②.Mini-Batch Gradient Descent (MBGD): 小批量梯度下降,每一次迭代都从数据集中随机抽取一小部分样本,然后基于这一批样本的平均梯度来更新权重。保证了准确性和计算效率。

③.Stochastic Gradient Descent (SGD): 随机梯度下降,每一次迭代都只使用随机单个样本来计算梯度并更新权重。优点:更快地收敛;缺点:权重更新路径不稳定

6.批量梯度下降BGD

用于最小化损失函数(目标函数),每次迭代都使用所有的训练样本 来计算损失函数的梯度并更新模型。

更新规则

①.数据集(包含m个训练样本)

$$
\{(x^{(i)}, y^{(i)})\}_{i=1}^{m}
$$

$$
其中 x^{(i)} 是输入特征,y^{(i)} 是对应的标签。目标是最小化损失函数J(\theta)相对于模型参数\theta 的值。
$$

损失函数可以定义为:

$$
J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)})^2
$$

$$
其中 h_\theta(x^{(i)}) 是模型对第 i 个样本的预测输出。
$$

批量梯度下降的更新规则为:

$$
\theta_j := \theta_j - \alpha \frac{1}{m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)}) \cdot x_j^{(i)} , 对于 j = 0, 1, \ldots, n (其中 n 是特征的数量),并且 \alpha 是学习率。
$$

特点

最准确,计算量大,收敛到最小值的速度较慢,内存需求大

使用场景

小数据集,不需要实时更新模型

注意事项

选择合适的学习率:太小收敛速度会很慢,太大可能会不收敛

数据预处理:标准化或归一化,提高批量梯度下降的效率

监控损失函数:定期检查损失函数的变化趋势,确保方向正确

7.随机梯度下降SGD

SGD每一步更新参数时仅使用单个训练样本,使得它更加灵活且计算效率更高,特别是处理大规模数据集时

步骤:

①.初始化参数:

$$
选择一个初始点作为参数向量 \theta的初始值
$$

②.选择样本:

$$
随机选取一个训练样本 (x^{(i)}, y^{(i)})
$$

③.计算梯度:

$$
使用所选样本 (x^{(i)}, y^{(i)})来近似计算损失函数 J(\theta) 的梯度 \nabla J(\theta)
$$

④.更新参数:

$$
根据梯度的方向来更新参数 \theta
$$

$$
更新公式为:\theta := \theta - \alpha \cdot \nabla J(\theta)
$$

其中 α是学习率,决定了每次迭代时参数更新的步长。

5.重复②-④,直到完成一个完整的epoch,即所有的样本都被访问过一次

6.重复,直到满足最大迭代次数或者梯度变化足够小

7.输出最小化损失函数后的最优参数

$$
\theta^*
$$

数学公式:

$$
假设我们有一个包含 m个样本的数据集 \{(x^{(i)}, y^{(i)})\},J(\theta) = \frac{1}{2}(h_\theta(x^{(i)}) - y^{(i)})^2
$$

$$
其中 h_\theta(x^{(i)}) = \theta^T x^{(i)}是模型对第 i个样本的预测值。
$$

$$
梯度 \nabla J(\theta) 对于每个参数 \theta_j 的偏导数可以表示为:\frac{\partial J(\theta)}{\partial \theta_j} = (h_\theta(x^{(i)}) - y^{(i)})x_j^{(i)}
$$

更新规则:

$$
参数\theta的更新规则为:\theta_j := \theta_j - \alpha \cdot \frac{\partial J(\theta)}{\partial \theta_j}
$$

注意事项:

选择合适的学习率:太小收敛速度会很慢,太大可能会不收敛

随机性:随机选择一个样本,避免陷入局部最小值

停止条件:达到最大迭代次数或者梯度的范围小于某个阈值

优点:快速迭代并适应较大的数据集

缺点:每次只使用一个样本进行更新,梯度可能较为嘈杂,更新中可能会出现较大的波动。可以通过减少学习率(例如采用学习衰减策略)来解决

eg1
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import SGDRegressor
from sklearn.metrics import mean_squared_error
# 加载数据集
data=fetch_california_housing(data_home="./src")
# print(data.data.shape)
# # print(data.target[0:10])
# print(data.feature_names)
# print(data.target_names)
x=data.data
y=data.target
​
# 数据标准化
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2)
stander=StandardScaler()
x_train=stander.fit_transform(x_train)
​
# 生成SGD随机梯度下降模型
sgd_model=SGDRegressor(loss="squared_error",alpha=0.01,fit_intercept=True,max_iter=1000,shuffle=True,random_state=666)
# 训练
sgd_model.fit(x_train,y_train)
​
# 评估
x_test=stander.transform(x_test)
print(sgd_model.score(x_test,y_test))
# 训练的结果
print(sgd_model.coef_)#w   
​
# 预测
# y=sgd_model.predict([[1,2,3,4,5,6,7,7]])
# print(y)
​
# 算均方差
y_predict=sgd_model.predict(x_test)
e=mean_squared_error(y_predict,y_test)
print(e)
8.小批量梯度下降MBGD

在每个迭代步骤中使用一小部分训练样本来计算损失函数的梯度,并进行更新。能减少计算资源的需求,保持一定程度的梯度准确性。

更新规则

$$
假设我们有一个包含 m 个训练样本的数据集 \{(x^{(i)}, y^{(i)})\}_{i=1}^{m},其中 x^{(i)} 是输入特征,y^{(i)} 是对应的标签。我们将数据集划分为多个小批量,
$$

$$
每个小批量包含b个样本,其中b称为批量大小(batch size)(一般是2的n次方),通常 b远小于m。
$$

损失函数可以定义为:

$$
J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)})^2,其中 h_\theta(x^{(i)}) 是模型对第 i 个样本的预测输出。
$$

小批量梯度下降的更新规则为:

$$
\theta_j := \theta_j - \alpha \frac{1}{b} \sum_{i \in B} (h_\theta(x^{(i)}) - y^{(i)}) \cdot x_j^{(i)}
$$

$$
对于 j = 0, 1, \ldots, n (其中 n 是特征的数量),并且 \alpha 是学习率,B表示当前小批量中的样本索引集合。
$$

特点

计算效率:相比于BGD,减少了计算成本

梯度估计:相比于SGD,提供了更准确的梯度估计,可以更稳定地接近最小值

内存需求:相比于BGD,降低了内存需求

收敛速度与稳定性:保持较快的收敛速度的同时保持相对较高的稳定性

使用场景

中等规模数据集:高效、良好的收敛性

在线学习:可以有效地处理新到来的数据流式批次

分布式环境:多台机器

注意事项

选择合适的批量大小

选择合适的学习率:太小收敛速度会很慢,太大可能会不收敛

数据预处理:标准化或归一化,提高批量小梯度下降的效率

监控损失函数:定期检查损失函数的变化趋势,确保方向正确

eg2

调用partial_fit函数训练会直接更新权重,而不需要调fit从头开始训练

from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import SGDRegressor
from sklearn.metrics import mean_squared_error
import math
import random
# 加载数据集
data=fetch_california_housing(data_home="./src")
# print(data.data.shape)
# # print(data.target[0:10])
# print(data.feature_names)
# print(data.target_names)
x=data.data
y=data.target
​
# 数据标准化
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2)
stander=StandardScaler()
x_train=stander.fit_transform(x_train)
​
def train():# 配置一些训练参数eta0=0.001epoch=1000batch_size=16n_sample=len(x_train)#样本数量,假设是20000个model=SGDRegressor()for epoch_i in range(epoch):n_batch=math.ceil(n_sample/batch_size)for i in range(n_batch):start=i*batch_sizeend=min((i+1)*batch_size,n_sample)x_train[start:end]model.partial_fit(x_train[start:end],y_train[start:end])# 一轮训练结束y_pred=model.predict(stander.transform(x_test))mse=mean_squared_error(y_pred,y_test)print(f"第{epoch_i}轮,mse:{mse}")train()
​
​
9.优化

①.数据预处理:标准化

②.正则化:防止过拟合

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/476122.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Keil+VSCode优化开发体验

目录 一、引言 二、详细步骤 1、编译器准备 2、安装相应插件 2.1 安装C/C插件 2.2 安装Keil相关插件 3、添加keil环境变量 4、加载keil工程文件 5、VSCode中成功添加工程文件后可能出现的问题 5.1 编码不一致问题 6、在VSCode中进行编译工程以及烧录程序 7、效果展示…

Llama模型文件介绍

文章目录 概要文件组成 概要 在使用 LLaMA&#xff08;Large Language Model Meta AI&#xff09;权重时&#xff0c;通常会涉及到与模型权重存储和加载相关的文件。这些文件通常是以二进制格式存储的&#xff0c;具有特定的结构来支持高效的模型操作。以下以Llama-7B为例&…

Spring Web入门练习

加法计算器 约定前后端交互接⼝ 约定 "前后端交互接⼝" 是进⾏ Web 开发中的关键环节. 接⼝⼜叫 API&#xff08;Application Programming Interface), 我们⼀般讲到接⼝或者 API&#xff0c;指的都是同⼀个东西. 是指应⽤程序对外提供的服务的描述, ⽤于交换信息…

Easyexcel(5-自定义列宽)

相关文章链接 Easyexcel&#xff08;1-注解使用&#xff09;Easyexcel&#xff08;2-文件读取&#xff09;Easyexcel&#xff08;3-文件导出&#xff09;Easyexcel&#xff08;4-模板文件&#xff09;Easyexcel&#xff08;5-自定义列宽&#xff09; 注解 ColumnWidth Data…

FIFO和LRU算法实现操作系统中主存管理

FIFO&#xff0c;用数组实现 1和2都是使用nextReplace实现新页面位置的更新 1、不精确时间&#xff1a;用ctime输出运行时间都是0.00秒 #include <iostream> #include <iomanip> #include<ctime>//用于计算时间 using namespace std;// 页访问顺序 int pa…

Unity3d场景童话梦幻卡通Q版城镇建筑植物山石3D模型游戏美术素材

注明&#xff1a;网络素材&#xff0c;仅供学习使用&#xff01; https://download.csdn.net/download/elineSea/90017291

batchnorm与layernorn的区别

1 原理 简单总结&#xff1a; batchnorn 和layernorm是在不同维度上对特征进行归一化处理。 batchnorm在batch这一维度上&#xff0c; 对一个batch内部所有样本&#xff0c; 在同一个特征通道上进行归一化。 举个例子&#xff0c; 假设输入的特征图尺寸为16x224x224x256&…

SpringAOP模拟实现

文章目录 1_底层切点、通知、切面2_切点匹配3_从 Aspect 到 Advisor1_代理创建器2_代理创建时机3_Before 对应的低级通知 4_静态通知调用1_通知调用过程2_模拟 MethodInvocation 5_动态通知调用 1_底层切点、通知、切面 注意点&#xff1a; 底层的切点实现底层的通知实现底层的…

标准驱动开发(Linux2.6(cdev) 的开发)

Linux2.6&#xff08;cdev&#xff09; 的开发 目录 Linux2.6&#xff08;cdev&#xff09; 的开发 回顾 Linux2.6&#xff08;cdev&#xff09; 的开发 了解一下 Linux2.6 开发框架 学习 Linux2.6 的相关接口 1、申请设备号&#xff08;alloc_chrdev_region&#xff09…

硬件知识 cadence16.6 原理图输出为pdf 网络名下划线偏移 (ORCAD)

1. cadence原理图输出为PDF网络名下划线偏移 生这种情况的原因 1. 设计的原理图图纸大小比正常的 A4图纸大。 2. 打印为PDF 的时候&#xff0c;打印机的设置有问题。 2.cadence原理图输出为 PDF网络名下划线偏移的情况 可以看到上图&#xff0c;网络名往上漂移。 3. 解决办法 …

HarmonyOs DevEco Studio小技巧31--卡片的生命周期与卡片的开发

Form Kit简介 Form Kit&#xff08;卡片开发服务&#xff09;提供一种界面展示形式&#xff0c;可以将应用的重要信息或操作前置到服务卡片&#xff08;以下简称“卡片”&#xff09;&#xff0c;以达到服务直达、减少跳转层级的体验效果。卡片常用于嵌入到其他应用&#xff0…

SSRF漏洞利用

2.漏洞利用 2.1 SSRF中URL的伪协议 file:// 从⽂件系统中获取⽂件内容&#xff0c;如&#xff0c;file:///etc/passwd dict:// 字典服务器协议&#xff0c;访问字典资源&#xff0c;如dict://ip:6379/info sftp:// ssh⽂件传输协议或安全⽂件传输协议 ldap:// 轻量级⽬录访问…

nacos镜像启动时候报Public Key Retrieval is not allowed

在nacos的配置文件里加上一句allowPublicKeyRetrievaltrue

【pytorch-04】:线性回归案例(手动构建)

文章目录 1 构建数据集2 构建假设函数3 损失函数4 优化方法5 训练函数6.总结 1 构建数据集 为什么构建数据加载器&#xff1f; 在进行训练的时候都是采用的不是全部的数据&#xff0c;而是采用一个batch_size的数据进行训练&#xff0c;每次向模型当中送入batch_size数据&#…

实验室管理效率提升:Spring Boot技术的力量

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

STM32H7开发笔记(2)——H7外设之多路定时器中断

STM32H7开发笔记&#xff08;2&#xff09;——H7外设之多路定时器中断 文章目录 STM32H7开发笔记&#xff08;2&#xff09;——H7外设之多路定时器中断0.引言1.CubeMX配置2.软件编写 0.引言 本文PC端采用Win11STM32CubeMX4.1.0.0Keil5.24.2的配置&#xff0c;硬件使用STM32H…

springboot基于微信小程序的旧衣回收系统的设计与实现

摘 要 微信小程序的旧衣回收系统是一种专为环保生活设计的应用软件。这款小程序的主要功能包括&#xff1a;系统首页、个人中心、用户管理、回收人员管理、旧衣服分类管理、旧衣信息管理、回收预约管理、回收派单管理、回收订单管理、积分商品管理、积分兑换管理、管理员管理、…

路由缓存后跳转到新路由时,上一路由中的tip信息框不销毁问题解决

上一路由tip信息框不销毁问题解决 路由缓存篇问题描述及截图解决思路关键代码 路由缓存篇 传送门 问题描述及截图 路由缓存后跳转新路由时&#xff0c;上一个路由的tip信息框没销毁。 解决思路 在全局路由守卫中获取DOM元素&#xff0c;通过css去控制 关键代码 修改文…

40分钟学 Go 语言高并发:并发下载器开发实战教程

并发下载器开发实战教程 一、系统设计概述 1.1 功能需求表 功能模块描述技术要点分片下载将大文件分成多个小块并发下载goroutine池、分片算法断点续传支持下载中断后继续下载文件指针定位、临时文件管理进度显示实时显示下载进度和速度进度计算、速度统计错误处理处理下载过…

【前端】JavaScript中的indexOf()方法详解:基础概念与背后的应用思路

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: 前端 文章目录 &#x1f4af;前言&#x1f4af;什么是indexOf()方法&#xff1f;参数解释返回值示例 &#x1f4af;indexOf() 方法的工作原理&#x1f4af;特殊案例&#xff1a;undefined 的处理示例代码图示解释 &#x1f4af;i…