梯度下降实践

这篇博客介绍了使用梯度下降算法求解线性回归模型的参数,展示了如何通过Python实现这一过程。首先,定义了预期函数和函数模型,并提供了数据集读取函数。接着,详细解释了梯度下降的原理,并给出了一段核心代码来迭代更新参数a和b,直到达到极小值。最后,博客提到了向量化操作的优势,用numpy库实现了线性回归的向量化版本,用于提高计算效率。
摘要由CSDN通过智能技术生成

预期函数:y = 5+3*x

函数模型:y = a +b*x,训练求参:a,b值

数据集:第一列是x值,第二列是y值

 梯度下降算法:原理请看吴恩达机器学习课程“单变量线性回归”

# 数据获取函数
def fileIn(fileName):
    data = [[],[]]
    fr = open(fileName,'r',encoding='utf-8')
    # 读出文件所有内容
    arrayLines = fr.readlines()
    # 针对有BOM的UTF-8文本,应该去掉BOM,否则后面会引发错误。
    arrayLines[0] = arrayLines[0].lstrip('\ufeff')
    for line in arrayLines:
        # s.strip(rm),当rm空时,默认删除空白符(包括'\n','\r','\t',' ')
        line = line.strip()
        line = line.split(' ')  # line = [xxx,xxx,xxx,xxx] 列表
        data[0].append(float(line[0]))
        data[1].append(float(line[1]))
    return data  # [[0.0,0.1,0.2,0.3,...x],[5.0,5.3,5.6,5.9,...y]]

# 梯度下降核心计算机参数值 ,inialArg表示a,b初始化参数值,stepL表示梯度下降时学习速率
# 假设函数:f(x)=a+bx  
# 代价函数:J = 1/(2len(data[0]))Sum((a+bx-y)^2)  
# 代价函数对参数a求偏导:deva=suma/len(data[0]),len(data[0])表示数据的数量
# 代价函数对参数b求偏导:deva=sumb/len(data[0]),
# a = a - stepL*deva  
# b = b - stepL*devb
def calArg(data,inialArg,stepL):
    a,b = inialArg[0],inialArg[1]
    while 1:
        dev1 = 0  # 参数a的偏导
        dev2 = 0  # 参数b的偏导
        suma = 0  # 参数a的偏导值求和
        sumb = 0  # 参数b的偏导值求和
        for i in range(len(data[0])):
            tempy1 = a+b*data[0][i]-data[1][i]  # (a+b*xi) - yi  x=xi时,参数a的偏导值
            tempy2 = (a+b*data[0][i]-data[1][i])*data[0][i]  # [(a+b*xi) - yi]*xi x=xi时,参数b的偏导值
            suma += tempy1
            sumb += tempy2
        dev1 = suma/len(data[0])
        dev2 = sumb/len(data[0])
        tempa = a - stepL*(dev1)
        tempb = b - stepL*(dev2)
        a = tempa
        b = tempb
        print(dev1,dev2)  # 每次参数a,b相应的偏导数值
        if abs(dev1-0)<0.00001 and abs(dev2-0)<0.00001:  # 当偏导都趋近于0时,代表已经达到最优点了,训练完成,凸面的最小值导数等于0
            break
    return a,b

def alg(stepL):
    data = fileIn("data.txt")
    a,b=0,0  # 初始化(a,b)参数值为0,0
    a,b=calArg(data,[a,b],stepL)
    print(a,b)

if __name__ == '__main__':
    alg(0.0001)  # 设置参数修改步长为0.0001

 梯度下降效果:前面的数值是参数a,b在相应变化值的偏导数值,最后一行是最终得到的参数值

向量化:numpy数组操作比循环高效

原公式:3x+5y-13 = z

import numpy as np
import math
# n为一个样本中,属性的数量
# m为样本的数量
# X=[x1,x2,x3] (n,m)
# xList = np.array([[0,1],[0,2],[0,3],[0,0],[1,0],[1,1],[1,2],[1,3],[2,0],[2,1],[2,2],[2,3],[3,0],[3,1],[3,2],[3,3]])
# 第一行表示x,第二行表示y
xList = np.array([[0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3],[1,2,3,0,0,1,2,3,0,1,2,3,0,1,2,3]])
# 原始正确的z值
zList = np.array([-7,-2,3,-12,-9,-3,3,8,-6,-1,6,9,-3,2,7,12])  # >12表示1,小于12表示0
# 原始z值经过激活函数后的y
yVal = 1/(1+np.exp(-1*zList))  # >12表示1
yVal = np.round(yVal,3)  # 保留3位小数,四舍五入
zList.resize(16,1)
# 定义w,dw,b
w1,w2 = 0,0
dw = np.zeros((2,1))  # dw = np.zeros((n,1))
w=np.array([[w1],[w2]])
b=np.zeros((1,16))

a = 0.03
i=0
while(i<1000000):
    zhat=np.dot(w.T,xList)+b  # 求Z=[z1,z2,...,zm] = w.T*X +b
    yhat = 1/(1+np.exp(-1*zhat))  # 求a
    dz = yhat-yVal
    print(np.round(dz,3))
    dz.resize((16, 1))
    m = len(dz)
    dw = 1/m*np.dot(xList,dz)
    db = 1 / m * np.sum(dz)
    w = w - a*dw
    b = b - a*db
    i+=1

print("b:",np.round(b,3),"  w:",np.round(w,3))

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值