11.19 机器学习-梯度下降

server/2024/11/23 20:22:05/

# **正规方程求解的缺点**

# 最小二乘法的缺点

# 之前利用正规方程求解的W是最优解的原因是MSE这个损失函数是凸函数。

# 但是,机器学习的损失函数并非都是凸函数,设置导数为0会得到很多个极值,不能确定唯一解,MSE还有一个问题,当数据量和特征较多时,矩阵计算量太大.

# 极值点不止一个 计算量大 求逆矩阵的时间复杂度为O(n^3)

# 梯度下降 一点一点的靠近损失函数的的极值点

# 求出损失函数 然后一点点的调整W的值使得损失函数的值变小 多个W的话随机生成一组成正太分布的数值w_0,w_1,w_2....w_n,这个随机是成正太分布的(高斯说的)

# 首先要初始化一个W 即选择一个起点 然后变大或者变小 带入导函数 导函数的值为负数 就要增大 此时的点肯定在极小值的左边 为正数要变小 此时在极小值的右边 最后导函数的值越来越靠近0

# 但是算法没有对此时的导函数的值进行正负性判断 而是依靠公式判断

# 公式   w新= w旧 -学习率a*梯度  a为正  梯度就是w旧带入导函数的值 如果为负 就说明在左边 就会+ 反之为正说明在右边就会减 离得远梯度大步子大 反之步子小

# ### 6.3学习率

# 根据我们上面讲的梯度下降公式,我们知道α是学习率,设置大的学习率α;每次调整的幅度就大,设置小的学习率α;每次调整的幅度就小,然而如果步子迈的太大也会有问题!

# 学习率大,可能一下子迈过了,到另一边去了(从曲线左半边跳到右半边),继续梯度下降又迈回来,使得来来回回震荡。步子太小呢,就像蜗牛一步步往前挪,也会使得整体迭代次数增加。

# ### 6.3学习率

# 学习率的设置是门一门学问,

# 一般我们会把它设置成一个小数,0.1、0.01、0.001、0.0001,都是常见的设定数值(然后根据情况调整)。一般情况下学习率在整体迭代过程中是不变,但是也可以设置成**随着迭代次数增多学习率逐渐变小**,

# 因为越靠近山谷我们就可以步子迈小点,可以更精准的走入最低点,同时防止走过。还有一些深度学习的优化算法会自己控制调整学习率这个值

# 自己实现一遍梯度下降

import numpy as np

import matplotlib.pyplot as plt

import random

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

import random

import numpy as np

def gradient_descent():

    w=np.linspace(-10,20,100) # 画图用的x的坐标

    loss=lambda w_1:(w_1-3.5)**2-4.5*w_1+10 # 损失函数 ***

    # plt.plot(w,loss)

    # plt.show()

    g=lambda w_1:2*(w_1-3.5)-4.5#导函数***

    w1=random.randint(-10,20) # 随机一个初始w***

    alpha=0.1

    w2_list=[]

    for x in range(100):

        w2=w1-alpha*g(w1)  #梯度下降公式

        w2_list.append(w2)

        w1=w2

        alpha=alpha-alpha/10 # 控制学习率越来越小

    plt.plot(w,loss(w))

    plt.scatter(w2_list,loss(np.array(w2_list)),marker="o")

    plt.show()

    pass

# 如果有两个w w1 ,w2 就要用偏导数

def gradient_descent2():

    # 损失函数 关于w1,w2的二次方程

    loss=lambda w_1,w_2:(w_1-3.5)**2+(w_2-2)**2+2*w_2-4.5*w_1+3*w_1*w_2+20

    # w1 w2 的偏导

    dw_1=lambda w_1,w_2:2*(w_1-3.5)+3*w_2-4.5#w_1的导函数

    dw_2=lambda w_1,w_2:3*w_1+2*w_2-2#w_2的导函数

    # 初始化随机w1 w2

    w_1=10#np.random.randint(0,100,size=1)[0]#随机初始值

    w_2=40#np.random.randint(0,100,size=1)[0]#随机初始值

    # 学习率初始化 0.1

    alpha=0.1

    w1_list=[]

    w2_list=[]

    for x in range(10):

        w1=w_1-alpha*dw_1(w_1,w_2)

        w2=w_2-alpha*dw_2(w_1,w_2)

        w1_list.append(w1)

        w2_list.append(w2)

        w_1,w_2=w1,w2

    pass

    print(w1_list)

    print(w2_list)

# API

# 官方的梯度下降API常用有三种:

# 批量梯度下降BGD(Batch Gradient Descent)

# 小批量梯度下降MBGD(Mini-BatchGradient Descent)

# 随机梯度下降SGD(Stochastic Gradient Descent)

# 三种梯度下降有什么不同呢?

# - **Batch Gradient Descent (BGD)**: 在这种情况下,每一次迭代都会使用全部的训练样本**计算梯度**来更新权重。 就是上面自己做的方式 这个数量大了太慢 把全部的数据集拿来做梯度下降 均方差公式的n值 写均方差公式的时候 全部的样本都考虑

# 这意味着每一步梯度更新都是基于整个数据集的平均梯度。这种方法的优点是每次更新的方向是最准确的,但缺点是计算量大且速度慢,尤其是在大数据集上。

"""

**特点**

- **准确性**:由于使用了所有训练样本,所以得到的梯度是最准确的,这有助于找到全局最小值。

- **计算成本**:每次更新都需要遍历整个数据集,因此计算量较大,特别是在数据集很大的情况下。

- **收敛速度**:虽然每一步的更新都是准确的,但由于计算成本较高,实际收敛到最小值的速度可能不如其他方法快。

- **内存需求**:需要在内存中存储整个数据集,对于大型数据集来说可能成为一个问题。

**使用场景**

- **小数据集**:当数据集较小时,批量梯度下降是一个不错的选择,因为它能保证较好的收敛性和准确性。

- **不需要实时更新**:如果模型不需要实时更新,例如在离线训练场景下,批量梯度下降是一个合理的选择。

**实现注意事项**

- **选择合适的学习率**:选择合适的学习率对于快速且稳定的收敛至关重要。如果学习率太小,收敛速度会很慢;如果太大,则可能会导致不收敛。

- **数据预处理**:对数据进行标准化或归一化,可以提高批量梯度下降的效率。

- **监控损失函数**:定期检查损失函数的变化趋势,确保算法正常工作并朝着正确的方向前进。

**API**

批量梯度下降通常不是首选方法,因为它在大数据集上的计算成本较高。如果你确实需要批量梯度下降,那么可以考虑自己实现。

"""

# - **Mini-Batch Gradient Descent (MBGD)**: 这种方法介于批量梯度下降和随机梯度下降之间。它不是用全部样本也不是只用一个样本,  每次下降考虑一部分数据 均方差公式的n值

# 而是每次迭代从数据集中随机抽取一小部分样本(例如,从500个样本中选取32个),然后基于这一小批样本的平均梯度来更新权重。这种方法在准确性和计算效率之间取得了一个平衡。 每次一般选择2的次方个




 

# - **Stochastic Gradient Descent (SGD)**: 在随机梯度下降中,每次迭代仅使用随机单个样本(或有时称为“例子”)来计算梯度并更新权重。

# 这种方法能够更快地收敛,但由于每次更新都基于单个样本,所以会导致权重更新路径不稳定。 最快 每次n变为了1

"""

**基本步骤**

1. **初始化参数**:

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

2. **选择样本**:

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

3. **计算梯度**:

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

4. **更新参数**:

   - 根据梯度的方向来更新参数 $\theta$。更新公式为:

     $\theta := \theta - \alpha \cdot \nabla J(\theta)$

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

5. **重复步骤 2 到 4**:

   - 对所有的训练样本重复此过程,直到完成一个完整的 epoch(即所有样本都被访问过一次)。

6. **重复多个 epoch**:

   - 重复上述过程,直到满足某个停止条件,比如达到最大迭代次数或者梯度足够小。

7. **输出结果**:

   - 输出最小化损失函数后的最优参数 $\theta^*$。

**注意事项**

- **学习率 $\alpha$**: 需要适当设置,太大会导致算法不收敛,太小则收敛速度慢。

- **随机性**: 每次迭代都从训练集中随机选择一个样本,这有助于避免陷入**局部最小值**。

- **停止条件**: 可以是达到预定的最大迭代次数,或者梯度的范数小于某个阈值。

"""

# API

# sklearn.linear_model.SGDRegressor()

# 功能:梯度下降法线性回归

# 参数:

#  loss: 损失函数,默认为 ’squared_error’

#  fit_intercept: 是否计算偏置, default=True

#  eta0: float, default=0.01学习率初始值

#     learning_rate:  str, default=’invscaling’  

#        The learning rate schedule:

#             ‘constant’: eta = eta0 学习率为eta0设置的值,保持不变

#             ‘optimal’: eta = 1.0 / (alpha * (t + t0))

#             ‘invscaling’: eta = eta0 / pow(t, power_t)

#             ‘adaptive’: eta = eta0, 学习率由eta0开始,逐步变小

#     max_iter: int,  default=1000 经过训练数据的最大次数(又名epoch)

#     shuffle=True 每批次是否洗牌

#     penalty: {‘l2’, ‘l1’, ‘elasticnet’, None}, default=’l2’

#        要使用的惩罚(又称正则化项)。默认为' l2 ',这是线性SVM模型的标准正则化器。' l1 '和'

#        elasticnet '可能会给模型(特征选择)带来' l2 '无法实现的稀疏性。当设置为None时,不添加惩罚。

# 属性:  

# coef_ 回归后的权重系数

# intercept_ 偏置

def sgd1():

   data=fetch_california_housing(data_home="assets/datasets")

   # print(data.feature_names)

   # print(data.target_names)

   x=data.data

   y=data.target

   # print(x)

   # print(y)

   

   scaler1=StandardScaler()

   scaler2=StandardScaler()

   # 创建sgd工具

   sgd=SGDRegressor(loss="squared_error",max_iter=10000,shuffle=True,eta0=0.001)  # loss 损失函数,默认为 ’squared_error’

   x_train,x_test,y_train,y_test=train_test_split(x,y,random_state=666,train_size=0.7)

   x_train_stand=scaler1.fit_transform(x_train)

   x_test_stand=scaler1.transform(x_test)

   sgd.fit(x_train_stand,y_train)

   score1=sgd.score(x_test_stand,y_test)

   

   print(score1) # 得分范围为 负无穷到1 sgd.score使用的是R² score(决定系数)可以为负 使用mse不能为负

   pass


 

if __name__=="__main__":

    # gradient_descent()

    # gradient_descent2()

    sgd1()


http://www.ppmy.cn/server/144342.html

相关文章

前端速通(HTML)

1. HTML HTML基础&#xff1a; 什么是HTML&#xff1f; 超文本&#xff1a; "超文本"是指通过链接连接不同网页或资源的能力。HTML支持通过<a>标签创建超链接&#xff0c;方便用户从一个页面跳转到另一个页面。 标记语言&#xff1a; HTML使用一组预定义的标签…

失落的Apache JDBM(Java Database Management)

简介 Apache JDBM&#xff08;Java Database Management&#xff09;是一个轻量级的、基于 Java 的嵌入式数据库管理系统。它主要用于在 Java 应用程序中存储和管理数据。这个项目已经过时了&#xff0c;只是发表一下以示纪念&#xff0c;现在已经大多数被SQLite和Derby代替。…

基于 SpringBoot 的作业管理系统【附源码】

基于 SpringBoot 的作业管理系统 效果如下&#xff1a; 系统注册页面 学生管理页面 作业管理页面 作业提交页面 系统管理员主页面 研究背景 随着社会的快速发展&#xff0c;信息技术的广泛应用已经渗透到各个行业。在教育领域&#xff0c;课程作业管理是学校教学活动中的重要…

简单的使用Ngrok使用https

1、ngrok 使用谷歌邮箱 https://dashboard.ngrok.com/ 2、使用ngrok docker化部署 最快 https://dashboard.ngrok.com/get-started/setup/docker 本地网络不行无法下载&#xff0c;使用其他工具下载 然后保存 docker save -o ngrok.tar ngrok/ngrok3、静态域名 docker ru…

持续集成与持续部署:CI/CD简介

一、概念及含义 CI/CD 是一种在软件开发和交付过程中广泛应用的实践方法&#xff0c;它由持续集成&#xff08;Continuous Integration&#xff0c;简称 CI&#xff09;和持续交付 / 持续部署&#xff08;Continuous Delivery/Continuous Deployment&#xff0c;简称 CD&#…

鸿蒙动画开发07——粒子动画

1、概 述 粒子动画是在一定范围内随机生成的大量粒子产生运动而组成的动画。 动画元素是一个个粒子&#xff0c;这些粒子可以是圆点、图片。我们可以通过对粒子在颜色、透明度、大小、速度、加速度、自旋角度等维度变化做动画&#xff0c;来营造一种氛围感&#xff0c;比如下…

分布式锁RedissonClient应用

文章目录 一、RedissonClient 的由来二、RedissonClient 的优势三、RedissonClient 的应用场景四、实际应用4.1引入依赖4.2代码示例 一、RedissonClient 的由来 在分布式系统中&#xff0c;为了保证多个节点或进程对共享资源的并发访问的正确性和一致性&#xff0c;需要一种有效…

Python数据结构day2

一、链表 1.1目的 解决顺序表存储数据有上限&#xff0c;并且插入和删除操作效率低的问题 1.2概念 链表&#xff1a;链式存储的线性表&#xff0c;使用随机物理内存存储逻辑上连续的数据 链表的组成&#xff1a;由一个个结点组成 结点&#xff1a;由数据域和链接域组成&a…