线性回归

  做了一个线性回归的小的demo。训练样本sample_size = 100,每次参与训练的数据个数 batch_size = 50,采用L2 loss,也就是测试结果和真实结果之间的距离。利用梯度下降法训练模型参数。
在这里插入图片描述
  这里求梯度的时候,利用了链式法则。

  具体的代码如下:

import numpy as np
import random
from matplotlib import pyplot as plt

# 利用训练的模型计算预测值
def inference(x, w, b):
    pred_y = w * x + b
    return pred_y
    
# 求梯度
def gradient(pred_y, gt_y, x):
    diff = pred_y - gt_y
    dw = diff * x
    db = diff
    return dw, db

# 梯度下降法求梯度的过程,调用一次该函数,则进行一次梯度下降,也就是更新一次模型参数
def cal_step_gradient(batch_x_list, batch_gt_y_list, w, b, lr):
	# 因为这里每次是选一批的样本数据,所以需要对这批数据的 loss 求一个平均值,利用这个平均值来训练模型。
    batch_size = len(batch_x_list)
    avg_dw = 0
    avg_db = 0
    for i in range(batch_size):       
        pred_y = inference(batch_x_list[i], w, b)
        batch_w, batch_b = gradient(pred_y, batch_gt_y_list[i], batch_x_list[i])
        avg_dw += batch_w
        avg_db += batch_b
    avg_dw /= batch_size
    avg_db /= batch_size
    w -= avg_dw * lr
    b -= avg_db * lr
    return w, b

# 模型质量评价函数,利用全量的真实值和预测值计算 L2 loss, loss越小模型质量越好
def eval_loss(x_list, gt_y_list, w, b):
    avg_loss = 0.0
    for i in range(len(x_list)):
        avg_loss = 0.5 * (x_list[i] * w + b - gt_y_list[i]) ** 2
    avg_loss /= len(gt_y_list)
    return avg_loss

# 画图函数
def draw(x_list, w, b):
    batch_size = len(x_list)
    pre_y_list = []
    for i in range(batch_size):
        pre_y_list.append(w * x_list[i] + b)
    plt.scatter(x_list, pre_y_list)        

# 模型训练过程
def train(x_list, gt_y_list, batch_size, max_iter, lr):
	# 初始化参数
    w = 0
    b = 0
    # 在样本数据中随机选择 batch_size 大小的数据,用来训练
    batch_idx = np.random.choice(len(x_list), batch_size)
    batch_x_list = []
    batch_gt_y_list = []
    for i in range(max_iter):
        batch_x_list = [x_list[j] for j in batch_idx]
        batch_gt_y_list = [gt_y_list[j] for j in batch_idx]
        w, b = cal_step_gradient(batch_x_list, batch_gt_y_list, w, b ,lr)
        print('w:{0}, b:{1}'.format(w, b))
        print('loss is {0}'.format(eval_loss(x_list, gt_y_list, w, b)))
    # 画出训练好的模型的样本数据分布
    draw(x_list, w, b)

# 数据生成函数,利用random函数随机生成一批样本数据
def gen_sample_data():
    w = random.randint(0, 5) + random.random()
    b = random.randint(0, 10) + random.random()
    sample_size = 100
    x_list = []
    y_list = []
    for i in range(sample_size):
        x = random.randint(0, 100) + random.random()
        y = w * x + b + random.random() * np.random.randint(-1, 1)
        x_list.append(x)
        y_list.append(y)
    # 画出样本的原始分布
    plt.scatter(x_list, y_list)   
    return x_list, y_list, w, b

# 初始化模型参数,包括batch_size, 最大训练次数, 学习率 learn_rate 
def run():
    x_list, y_list, w, b = gen_sample_data()
    batch_size = 50
    max_iter = 100
    lr = 0.0001
    train(x_list, y_list, batch_size, max_iter, lr)
    
# 主函数
if __name__ == '__main__':
    run()

  训练效果如下图所示,蓝色的点是原始数据分布,黄色的点是训练的模型预测的数据值,可以看到,它们几乎完全重叠在一起了,可以说效果还是不错的。
在这里插入图片描述
  不过这里需要注意learn_rate 的选择,如果这个值过大,比如可以尝试一下0.01,那就会发生梯度爆炸,最后训练出来的模型可能和原本的数据分布就完全是两码事,至于为什么会出现梯度爆炸,下次再写。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值