zoukankan      html  css  js  c++  java
  • 单变量线性回归:TensorFlow 实战(实战篇)

    导语

    慕课:《深度学习应用开发-TensorFlow实践》
    章节:第五讲 单变量线性回归:TensorFlow 实战
    这一讲理论部分请看https://www.cnblogs.com/tangkc/p/15371331.html,TensorFlow版本为2.3

    我们所要实现的是一个单变量的线性方程,这个方程可以表示为y=w*x+b。本案例通过生成人工数据集,随机生成一个近似采样随机分布,使得w=2.0b=1,并加入一个噪声,噪声的最大振幅为0.4

    导入库并生成数据集

    导入库

    import tensorflow as tf
    import numpy as np
    import matplotlib.pyplot as plt
    #在jupyter中使用matplotlib显示图像需要设置为inline模式,否则不会在网页中显示图像
    %matplotlib inline
    tf.__version__
    

    output:

    2.3.0
    

    生成数据集

    首先生成输入数据,构造满足这个函数的x和y,同时加入一些不满足方程的噪声

    #直接采用np生成等差数列的方法,生成100个点,取值在[-1,1]
    x_data=np.linspace(-1,1,100)
    np.random.seed(5)#设置随机数种子
    #产生对应的y=2x+1的值,同时加入噪声
    y_data=2*x_data+1.0+np.random.randn(*x_data.shape)*0.4
    

    np.random.randn是从标准正态分布中返回一个或多个样本值,举个简单的例子
    在这里插入图片描述
    而源代码中的np.random.randn(*x_data.shape)效果和np.random.randn(100)是一样的

    下面我们画一下生成的xy的图像

    plt.scatter(x_data,y_data)
    plt.xlabel('x')
    plt.ylabel('y')
    plt.title("Training Data")
    # 画出我们想要得到的目标函数y=2x+1
    plt.plot(x_data,1.0+2*x_data,'r',linewidth=3)
    

    在这里插入图片描述

    构建模型

    建模

    这个模型还是比较的简单的

    def model(x,w,b):
        return tf.multiply(x,w)+b
    

    创建待优化变量

    w=tf.Variable(np.random.randn(),tf.float32)# 斜率
    b=tf.Variable(0.0,tf.float32)#截距
    

    定义损失函数

    损失函数用于描述预测值和真实值之间的误差,从而指导模型收敛方向,常用的有均方差(MSE)和交叉熵
    这里我们用的是均方差

    #定义均方差损失函数
    def loss(x,y,w,b):
        err=model(x,w,b)-y#计算预测值和真实值之间的差异
        squarred_err=tf.square(err)#求平方,得出方差
        return tf.reduce_mean(squarred_err)#求均值,得出均方差
    

    训练模型

    设置训练超参数

    epochs=10#迭代次数
    lr=0.01#学习率
    

    定义计算梯度函数

    def grad(x,y,w,b):
        with tf.GradientTape() as tape:
            loss_=loss(x,y,w,b)
        return tape.gradient(loss_,[w,b])# 返回梯度向量
    

    这里有一个TF1TF2不同的地方,在 TensorFlow 2 中,使用 tf.GradientTape() 这一上下文管理器封装需要求导的计算步骤,并使用其 gradient() 方法求导。

    执行训练(SGD)

    step=0# 记录训练步数
    loss_list=[]# 保存loss值的列表
    display_step=10# 控制训练过程数据数据显示频率,不是超参数
    for epoch in range(epochs):
        for xs,ys in zip(x_data,y_data):
            loss_=loss(xs,ys,w,b)# 计算loss
            loss_list.append(loss_)
            delta_w,delta_b=grad(xs,ys,w,b)#计算梯度
            change_w=delta_w*lr#计算w需要调整的量
            change_b=delta_b*lr#计算b需要调整的量
            w.assign_sub(change_w)
            b.assign_sub(change_b)#将w,b变更为减去对应变化量后的值
            step=step+1
            if step%display_step==0:#显示训练过程
                print(f'Training Epoch:{epoch+1}  Step:{step}  Loss:{loss_}')
        plt.plot(x_data,w.numpy()*x_data+b.numpy())
    

    在这里插入图片描述
    在这里插入图片描述

    这里就展示一部分的运行结果
    本案例所拟合的模型较简单,训练5轮之后已经接近收敛,对于复杂模型,需要更多次训练才能收敛

    显示训练结果并可视化

    print(f'w:{w.numpy()}, b:{b.numpy()}')
    

    在这里插入图片描述

    plt.scatter(x_data,y_data,label='Original data')
    plt.plot(x_data,x_data*2.0+1.0,label="Object line",color='g',linewidth=3)
    plt.plot(x_data,x_data*w.numpy()+b.numpy(),label="Fitted line",color='r',linewidth=3)
    plt.legend(loc=2)#设置图例位置
    

    在这里插入图片描述

    查看损失变化情况

    plt.plot(loss_list)
    

    在这里插入图片描述

    进行预测

    x_test=3.21
    predict=model(x_test,w.numpy(),b.numpy())
    target=2*x_test+1.0
    print(f'预测值:{predict}, 目标值:{target}')
    

    输出

    预测值:7.426405906677246, 目标值:7.42
    

    批量梯度下降BGD模型训练

    随机梯度下降法 (SGD) 每次迭代只使用一个样本(批量大小为 1),如果进行足够的迭代,SGD 也可以发挥作用。“随机”这一术语表示构成各个批量的一个样本都是随机选择的。
    在梯度下降法中,批量指的是用于在单次迭代中计算梯度的样本总数。
    假定批量是指整个数据集,数据集通常包含很大样本(数万甚至数千亿),此外,数据集通常包含多个特征。因此,一个批量可能相当巨大。如果是超大批量,则单次迭代就可能要花费很长时间进行计算。
    小批量随机梯度下降法(小批量 SGD) 是介于全批量迭代与 SGD 之间的折衷方案。小批量通常包含 10-1000 个随机选择的样本。小批量 SGD 可以减少 SGD 中的杂乱样本数量,但仍然比全批量更高效。
    那么,接下来是实现,我们只需要修改一下上面的一部分代码就好了。

    修改训练超参数

    epochs=100#迭代次数
    lr=0.05#学习率
    

    训练周期和学习率需要做一些调整。训练周期暂设为100,意味着所有样本要参与100次训练。学习率设置为0.05,比SGD版本的要大。

    修改模型训练过程

    loss_list=[]# 保存loss值的列表
    for epoch in range(epochs):
        loss_=loss(x_data,y_data,w,b)# 计算loss
        loss_list.append(loss_)
        delta_w,delta_b=grad(x_data,y_data,w,b)#计算梯度
        change_w=delta_w*lr#计算w需要调整的量
        change_b=delta_b*lr#计算b需要调整的量
        w.assign_sub(change_w)
        b.assign_sub(change_b)#将w,b变更为减去对应变化量后的值
        print(f'Training Epoch:{epoch+1}  Loss={loss_}')
        plt.plot(x_data,w.numpy()*x_data+b.numpy())
    

    在这里插入图片描述
    在这里插入图片描述

    显示训练结果并可视化

    print(f'w:{w.numpy()}, b:{b.numpy()}')
    plt.scatter(x_data,y_data,label='Original data')
    plt.plot(x_data,x_data*2.0+1.0,label="Object line",color='g',linewidth=3)
    plt.plot(x_data,x_data*w.numpy()+b.numpy(),label="Fitted line",color='r',linewidth=3)
    plt.legend(loc=2)#设置图例位置
    

    在这里插入图片描述

    损失值可视化

    plt.plot(loss_list)
    

    在这里插入图片描述

    完整代码

    点击查看代码
    import tensorflow as tf
    import numpy as np
    import matplotlib.pyplot as plt
    #在jupyter中使用matplotlib显示图像需要设置为inline模式,否则不会在网页中显示图像
    %matplotlib inline
    #直接采用np生成等差数列的方法,生成100个点,取值在[-1,1]
    x_data=np.linspace(-1,1,100)
    np.random.seed(5)#设置随机数种子
    #产生对应的y=2x+1的值,同时加入噪声
    y_data=2*x_data+1.0+np.random.randn(*x_data.shape)*0.4
    # np.random.randn是从标准正态分布中返回一个或多个样本值,
    np.random.randn(10)
    plt.scatter(x_data,y_data)
    plt.xlabel('x')
    plt.ylabel('y')
    plt.title("Training Data")
    # 画出我们想要得到的目标函数y=2x+1
    plt.plot(x_data,1.0+2*x_data,'r',linewidth=3)
    def model(x,w,b):
        return tf.multiply(x,w)+b
    w=tf.Variable(np.random.randn(),tf.float32)# 斜率
    b=tf.Variable(0.0,tf.float32)#截距
    #定义均方差损失函数
    def loss(x,y,w,b):
        err=model(x,w,b)-y#计算预测值和真实值之间的差异
        squarred_err=tf.square(err)#求平方,得出方差
        return tf.reduce_mean(squarred_err)#求均值,得出均方差
    def grad(x,y,w,b):
        with tf.GradientTape() as tape:
            loss_=loss(x,y,w,b)
        return tape.gradient(loss_,[w,b])# 返回梯度向量
    epochs=100#迭代次数
    lr=0.05#学习率
    loss_list=[]# 保存loss值的列表
    for epoch in range(epochs):
        loss_=loss(x_data,y_data,w,b)# 计算loss
        loss_list.append(loss_)
        delta_w,delta_b=grad(x_data,y_data,w,b)#计算梯度
        change_w=delta_w*lr#计算w需要调整的量
        change_b=delta_b*lr#计算b需要调整的量
        w.assign_sub(change_w)
        b.assign_sub(change_b)#将w,b变更为减去对应变化量后的值
        print(f'Training Epoch:{epoch+1}  Loss={loss_}')
        plt.plot(x_data,w.numpy()*x_data+b.numpy())
    print(f'w:{w.numpy()}, b:{b.numpy()}')
    plt.scatter(x_data,y_data,label='Original data')
    plt.plot(x_data,x_data*2.0+1.0,label="Object line",color='g',linewidth=3)
    plt.plot(x_data,x_data*w.numpy()+b.numpy(),label="Fitted line",color='r',linewidth=3)
    plt.legend(loc=2)#设置图例位置
    plt.plot(loss_list)
    

    梯度下降算法总结

    批量梯度下降每次迭代都考虑了全部的样本,做的是全局优化,但花费的计算资源较大,如果训练数据非常大,还无法实现全部样本同步参与。
    随机梯度下降每次迭代只取一条样本数据, 由于单个样本的训练可能会带来很多噪声,使得SGD并不是每次迭代都向着整体最优化方向,因此在刚开始训练时可能收敛得很快,但是训练一段时间后就会变得很慢。
    在SGD和BGD中间,还有一个集合了两种梯度下降法的优点的方法:小批量梯度下降(MBGD,Mini-batch gradient descent),每次迭代从训练样本中随机抽取一小批进行训练,这个一小批的数量取值也是一个超参数。

    小结

    通过一个简单的例子介绍了利用Tensorflow实现机器学习的思路,重点讲解了下述步骤:

    1. 生成人工数据集及其可视化
    2. 构建线性模型
    3. 定义损失函数
    4. (梯度下降) 优化过程
    5. 训练结果的可视化
    6. 利用学习到的模型进行预测

    学习笔记,仅供参考,如有错误,敬请指正!

    同时发布在CSDN中:https://blog.csdn.net/tangkcc/article/details/120624865

  • 相关阅读:
    (暂时弃坑)(半成品)ACM数论之旅18---反演定理 第二回 Mobius反演(莫比乌斯反演)((づ ̄3 ̄)づ天才第一步,雀。。。。)
    ACM数论之旅17---反演定理 第一回 二项式反演(神说要有光 于是就有了光(´・ω・`))
    ACM数论之旅16---母函数(又名生成函数)(痛并快乐着(╭ ̄3 ̄)╭)
    (暂时弃坑)ACM数论之旅15---置换群与Polya定理(我把标题看成poi了,poipoipoi(*≧▽≦)ツ)
    ACM数论之旅14---抽屉原理,鸽巢原理,球盒原理(叫法不一又有什么关系呢╮(╯▽╰)╭)
    ACM数论之旅13---容斥原理(一切都是命运石之门的选择(=゚ω゚)ノ)
    ACM数论之旅12---康托展开((*゚▽゚*)装甲展开,主推进器启动,倒计时3,2,1......)
    还有哪些东西要写눈_눈
    ACM数论之旅11---浅谈指数与对数(长篇)(今天休息,不学太难的数论> 3<)
    ACM数论之旅10---大组合数-卢卡斯定理(在下卢卡斯,你是我的Master吗?(。-`ω´-) )
  • 原文地址:https://www.cnblogs.com/tangkc/p/15371698.html
Copyright © 2011-2022 走看看