一元线性回归梯度下降法(通俗易懂,初学专属)

一、准备数据

生成N个训练样本(X,Y),其中自变量X取值服从均值为0,方差为1 的正太分布.

设该线性方程的式子为:Y = w*X + b. 

以下我们以Y =3*X+7 + e_r, N=100为例.

Y =3*X+7 + e_r, 其中 e_r为误差项,其取值服从均值为0,方差为1 的正太分布.

 创建数据后查看数据散点图,代码及数据散点图如下:

import numpy as np
import matplotlib.pyplot as plt

a = 0
b = 1
num = 100
#创建样本,均值a=0,方差b=1,数量num为100
x =  np.random.normal(a, b, num)
e_r = np.random.normal(a, b, num)
y =3*x+7 + e_r
plt.scatter(x, y)
plt.show()


 二、定义一个LinearModal 类,实现梯度下降,数据预测等。

         先来理解一些基础概念。Y= w*X+b,w代表权重,b代表偏置值。我们的目的就是要求出合适的w和b,用Y= w*X+b这条曲线来拟合我们的数据集。

2.1 那么如何求w和b呢

        用梯度下降法

        梯度下降的通俗理解就是:我们可以先给未知量w和b一个初始值。然后通过让它们自己学习一直变,变到合适的值为止。

        以我们的例子为例,最终结果应当是Y =3*X+7这条曲线拟合数据集的。我们假设w=1,b=1.进行一次梯度下降后,可能w就变成2,b就变成3(此处夸大了,一般变化不会那么大,一般变化很小,所以需要梯度下降很多次).就这样子一直变化直到w和b合适为止。

2.2 那么如何判断是否已经合适了呢

        用损失函数

        用均方差作为我们的损失函数,当误差值处于可接受范围时,则说明已找到合适的w和b,公式如下所示:

loss=\frac{1}{n}\sum (y-Y)^{2}

y代表预测值,即式子y=w*x+b得到的值,Y代表真实值

        由公式可知loss函数是一条关于y的二次函数,为开口向上的抛物线

2.3 那么如何确定未知量的变化梯度呢

        由高中数学我们就知道,导数可以说是x对y的影响程度,如y=7x,导数为7,而如y=2x,导数为2,很明显,当x变化同等程度时,第一条函数的y值变化更大。

        所以我们要求出w和b的变化梯度就是求导,求它们的偏导。偏导代表他们对loss值的影响程度。求偏导公式如下(因为公式编辑太麻烦,直接手写,字丑见谅)

Tips:公式推导很简单,看一下能看懂的。 

         求出偏导后,w和b的变化公式就是:

w=w-LearningRate*kw

b = b-LearningRate*kb

kw,kb分别代表w和b的偏导

        至于为什么要用减法,简单想想,当偏导值为负数时,则证明此时位于loss函数的左侧,需要增大变量值来趋近极值点。反之同理。如下粗略图,横轴为y,纵轴为loss:

 由上总结出提纲

  1. 数据准备
  2. 定义LinearModal类
    1. 初始化w,b为1
    2. 求loss
    3. 求偏导
    4. 更新w和b
    5. 回到第二点一直循环遍历直至迭代次数完成或loss达到可接受范围
  3. 实例化LinearModal类并进行预测
  4. 绘图

 理解思路后,定义LinearModal类:

class LinearModal():
    def __init__(self, x, y, m, LearningRate):
        self.w = 1     #初始化w
        self.b = 1     #初始化b
        self.LearningRate = LearningRate
        self.x = x
        self.y = y
        self.kb = 0    #b的偏导
        self.kw = 0    #w的偏导
        self.m = m     #训练次数
    
    
    #进行一次梯度下降    
    def gradentdecent(self):
        # 求样本数量
        n = len(self.x)
        loss = 0
        
        #求和
        for j in range(n):
            # kw = 求和 (wx+b-y)*x
            # kb = 求和 (wx+b-y)
            # loss = 求和 (wx+b-y)²
            self.kw = self.kw + ((self.w*self.x[j]+self.b-self.y[j])*x[j])
            self.kb = self.kb + (self.w*self.x[j]+self.b-self.y[j])
            loss = loss + (self.w*self.x[j]+self.b-self.y[j])**2 
            
        self.kw = self.kw*2/n
        self.kb = self.kb*2/n
        loss = loss/n
        return self.kw,self.kb,loss
    
    
    
    #训练函数        
    def train(self):
        #循环训练次数
        for i in range(self.m):
            #训练一次
            self.kw, self.kb, loss = self.gradentdecent()
            
            # 如果误差值已达可接受范围则退出循环
            if loss <= 0.0001:
                break
            #更新w和b
            #   w = w - kw * LearningRate
            #   b = b - kb * LearningRate
            self.w = self.w - self.kw*self.LearningRate
            self.b = self.b - self.kb*self.LearningRate
    
    
    
    #预测
    def predict(self):
        y_predict = self.w*self.x+self.b
        return y_predict

 三、预测

#创建模型
lm = LinearModal(x, y, 10000, 0.001)
#开始训练
lm.train()
#获取训练到的相关预测数据
w_predict = lm.w
b_predict = lm.b
y_predict = lm.predict()
print('预测到的w为{},预测到的b为{}'.format(w_predict,b_predict))

#绘图
plt.scatter(x, y)
plt.plot(x, y_predict, color='red')
plt.show()

 由输出结果可知,w趋近3,b趋近7,证明拟合效果极佳。


自此一元线性回归梯度下降法完成,如有错误还请指教

  • 11
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值