梯度下降算法--一元线性回归

前言:开始学习吴恩达教授的机器学习课程,记录并实现其中的算法。在实现过程中,还未理解如何准确的找到α这个值的取值。

一、一元线性回归

一元线性回归其实就是从一堆训练集中去算出一条直线,使数据集到直线之间的距离差最小。举个例子,唯一特征X(工龄),共有m = 50个数据数量,Y(薪水)是实际结果,要从中找到一条直线,使数据集到直线之间的距离差最小,如下图所示:
在这里插入图片描述
在这里插入图片描述
这里的薪水数据为手动自定义的,导致了误差较大…

线性回归所提供的思路就是:在这里插入图片描述
可以将特征X中每一个值xi都带入其中,得到对应的 h_θ(xi),可以将损失J(θ)定义为yi和hg(xi)之间的差值平方的和:在这里插入图片描述
接着求出 min( θ_0, θ_1) J( θ_0, θ_1)的值。

二、梯度下降

算法思路:

在这里插入图片描述
将梯度下降应用到最小化平方差代价函数中,得出期望的J(θ_0, θ_1)。如下图所示:

在这里插入图片描述
其中最为关键的为梯度下降算法中的导数项,可以对其进行简化,如下所示:
在这里插入图片描述

  • 直接引用的手写图(字有点儿丑)

通过对导数项的计算,就可以按照梯度下降的公式同步跟新θ_0, θ_1的值。
公式里的 α,表示学习速率,控制以多大幅度更新参数θj。

三、python代码实现

import numpy as np
import matplotlib.pyplot as plt


### 载入数据----画出图像
# 导入数据
data = np.genfromtxt('data_1.csv', delimiter=',')
#data = np.genfromtxt('data.csv', delimiter=',')
# print(data)   列表
x_data = data[:, 0]
y_data = data[:, 1]

# 画图
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.title("工龄 与 薪水 散点图")
plt.xlabel("X 工龄")
plt.ylabel("Y 薪水(元)")
plt.scatter(x_data,y_data)
plt.show()

# 学习率 learning_rate
#lr = 0.0001
#lr = 0.003
lr = 0.35
# 截距 θ_0
theta_0 = 0
# 斜率 θ_1
theta_1 = 0
# 最大迭代次数
#iterations = 1000
iterations = 50

###### 求解拟合此数据的直线参数

# 将梯度下降法应用到最小化平方差代价函数
## 线性回归
# 线性假设          h_θ(x) = θ_0 + θ_1 * x
# 平方差代价函数     J(θ) = 循环{ (h_θ(x^(i) - y^(i))** 2 } / 2m  其中 m为循环次数
## 梯度下降
# θ_j = θ_j - α {J(θ_0, θ_1)的偏导}


# 什么叫做损失函数?其实就是计算一个模型与各个点之间的差距到底有多大!!如果差距大,说明我们所选择的模型比较差,如果差距很小,说明这个模型不错。
# 平方差代价函数,求J(θ)
def compute_error(theta_0, theta_1, x_data, y_data):
    totalError = 0 # 即J(θ)
    for i in range(0,len(x_data)):
        # 预测值 - 实际值
        totalError += ( theta_0 + theta_1 * x_data[i] - y_data[i] ) ** 2
    return totalError / float(len(x_data)) / 2.0 # 即得出 J(θ)

# 梯度下降---算法思路
# 开始时 theta_0 和 theta_1通常 设置为0
# 持续改变 theta_0 和 theta_1 去减少 J(theta_0 ,theta_1),
# 直到出现我们期望的结果出现
def gradient_descent(theta_0, theta_1, x_data, y_data, lr,iterations):
    # 数据集的总量 m
    m = float(len(x_data))
    # 循环 迭代次数 iteartions
    for i in range(iterations):
        theta_0_grad = 0
        theta_1_grad = 0

        # 计算总和,再求平均  即==> 求梯度下降式子中的 导数项
        for j in range(0, len(x_data)):
            theta_0_grad += (1/m) * (theta_0 + theta_1 * x_data[j] - y_data[j] )
            theta_1_grad += (1/m) * (theta_0 + theta_1 * x_data[j] - y_data[j] ) * x_data[j]

        # 同步更新 theta_0 和 theta_1    梯度下降
        theta_0 = theta_0 - lr * theta_0_grad
        theta_1 = theta_1 - lr * theta_1_grad

        # 每迭代2次,输出一次图像
        if i % 5 == 0:
            print("当前迭代次数:",i + 1)
            plt.plot(x_data, y_data, 'b.')
            plt.plot(x_data, theta_0 + theta_1 * x_data, 'r')
            plt.title("工龄 与 薪水 散点图")
            plt.xlabel("工龄")
            plt.ylabel("薪水(元)")
            plt.show()
            # print中的字符串里面的 {0} 相当于索引,所取值对应于 format括号里的每个值的顺序
            print(" theta_0 = {0}, theta_1 = {1}, 误差 = {2}".format(theta_0, theta_1,compute_error(theta_0, theta_1, x_data,y_data)))

    return theta_0, theta_1
# 开始运行
print("Running...")
# 执行 梯度下降
theta_0, theta_1 = gradient_descent(theta_0, theta_1, x_data, y_data, lr, iterations)

# 输出最终的值
print("final ==> theta_0 = {0}, theta_1 = {1}, 误差 = {2}".format(theta_0, theta_1, compute_error(theta_0, theta_1, x_data, y_data)))

四、实现效果

1.通过数据生成散点图

在这里插入图片描述

2. 第1次迭代

在这里插入图片描述

3. 第6次迭代

在这里插入图片描述

4. 第11次迭代

在这里插入图片描述

5. 第16次迭代

在这里插入图片描述

6. 第46次迭代

在这里插入图片描述
可以看出,随着迭代次数的增加,其差值的缩减将会越来越小。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值