程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

关注本站官方公众号:程序员总部,领取三大福利!
福利一:python和前端辅导
福利二:进程序员交流微信群,专属于程序员的圈子
福利三:领取全套零基础视频教程(python,java,前端,php)

  价值13000svip视频教程,python大神匠心打造,零基础python开发工程师视频教程全套,基础+进阶+项目实战,包含课件和源码

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2021-10(9)

2021-11(28)

python机器学习 一元线性回归 梯度下降法的实现 【Python机器学习系列(四)】

发布于2022-08-11 19:30     阅读(493)     评论(0)     点赞(22)     收藏(3)


python机器学习 一元线性回归 梯度下降法的实现 【Python机器学习系列(四)】


梯度下降法的机器学习的重要思想之一,梯度下降法的目标,是使得代价函数最小。下边对梯度下降算法的实现展开详细介绍。


①首先读取数据集

导包并读取数据,数据自行任意准备,只要有两列,可以分为自变量x和因变量y即可即可。

import numpy as np
import matplotlib.pyplot as plt

data = np.loadtxt("data.csv", delimiter=",")

x_data = data[:, 0]
y_data = data[:, 1]

②初始化相关参数

# 初始化 学习率 即每次梯度下降时的步长 这里设置为0.0001
learning_rate = 0.0001

# 初始化 截距b 与 斜率k
b = 0
k = 0

# 初始化最大迭代的次数 以50次为例
n_iterables = 50

③定义计算代价函数–>MSE

使用均方误差 MSE (Mean Square Error)来作为性能度量标准
假设共有m个样本数据,则均方误差:

            M S E = 1 m ∑ i = 1 m [ ( k x i + b ) − y i ] 2 MSE=\frac{1}{m}\sum_{i=1}^{m}[(kx_i+b)-y_i]^2 MSE=m1i=1m[(kxi+b)yi]2

将该公式定义为代价函数,此外为例后续求导方便,则使结果在原mse的基础上,再乘以1/2。

def compute_mse(b,  k,  x_data, y_data):
    total_error = 0
    for i in range(len(x_data)):
        total_error += (y_data[i] - (k * x_data[i] + b)) ** 2

    # 为方便求导:乘以1/2
    mse_ = total_error / len(x_data) / 2
    return mse_

梯度下降

分别对上述的MSE表达式(乘以1/2后)中的k,b求偏导,

         ∂ 1 2 M S E ∂ b = ∑ i = 1 m ( k x i + b − y i ) m \frac{∂ \frac{1}{2}MSE}{∂b}=\sum_{i=1}^m\frac{(kx_i+b-y_i)}{m} b21MSE=i=1mm(kxi+byi)

         ∂ 1 2 M S E ∂ k = ∑ i = 1 m ( k x i + b − y i ) x i m \frac{∂ \frac{1}{2}MSE}{∂k}=\sum_{i=1}^m\frac{(kx_i+b-y_i)x_i}{m} k21MSE=i=1mm(kxi+byi)xi

更新b和k时,使用原来的b,k值分别减去关于b、k的偏导数与学习率的乘积即可。至于为什么使用减号,可以这么理解:以斜率k为例,当其导数大于零的时候,则表示均方误差随着斜率的增大而增大,为了使均方误差减小,则不应该使斜率继续增大,所以需要使其减小,反之当偏导大于零的时候也是同理。其次,因为这个导数衡量的是均方误差的变化,而不是斜率和截距的变化,所以这里需要引入一个学习率,使得其与偏导数的乘积能够在一定程度上起到控制截距和斜率变化的作用。

def gradient_descent(x_data, y_data, b,  k,  learning_rate,  n_iterables):
    m = len(x_data)
    # 迭代
    for i in range(n_iterables):
        # 初始化b、k的偏导
        b_grad = 0
        k_grad = 0

        # 遍历m次
        for j in range(m):
            # 对b,k求偏导
            b_grad += (1 / m) * ((k * x_data[j] + b) - y_data[j])
            k_grad += (1 / m) * ((k * x_data[j] + b) - y_data[j]) * x_data[j]

        # 更新 b 和 k  减去偏导乘以学习率
        b = b - (learning_rate * b_grad)
        k = k - (learning_rate * k_grad)
        # 每迭代 5 次  输出一次图形
        if i % 5 == 0:
            print(f"当前第{i}次迭代")
            print("b_gard:", b_grad, "k_gard:", k_grad)
            print("b:", b, "k:", k)
            plt.scatter(x_data, y_data, color="maroon", marker="x")
            plt.plot(x_data, k * x_data + b)
            plt.show()
    return b, k

⑤执行

print(f"开始:截距b={b},斜率k={k},损失={compute_mse(b,k,x_data,y_data)}")
print("开始迭代")
b, k = gradient_descent(x_data, y_data, b, k, learning_rate, n_iterables)
print(f"迭代{n_iterables}次后:截距b={b},斜率k={k},损失={compute_mse(b,k,x_data,y_data)}")

代码执行过程产生了一系列的图像,部分图像如下图所示,随着迭代次数的增加,代价函数越来越小,最终达到预期效果,如下图所示:

第5次迭代:
       在这里插入图片描述


第10次迭代:
       在这里插入图片描述


第50次迭代:
       在这里插入图片描述


执行过程的输出结果如下图所示:
在这里插入图片描述
可以看到,随着偏导数越来越小,斜率与截距的变化也越来越细微。


感谢您对博主的支持!

原文链接:https://blog.csdn.net/weixin_48964486/article/details/126194659



所属网站分类: 技术文章 > 博客

作者:虎王168

链接:https://www.pythonheidong.com/blog/article/1659365/bfed1634f35447d86503/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

22 0
收藏该文
已收藏

评论内容:(最多支持255个字符)