• tensorflow1.基础案例2


    前言

    TensorFlow 1.x中实现线性回归通常指的是使用静态图的方式,而在TensorFlow 1.x中使用Eager API实现线性回归是在TensorFlow 1.x的晚期版本中引入的,以提供类似于TensorFlow 2.x的编程体验。以下是两种方式的区别、各自的优点以及对比的作用:

    TensorFlow 1.x 静态图方式

    实现方式:

    • 首先构建一个计算图,包括数据的输入、模型的定义、损失函数和优化器。
    • 使用tf.placeholder来定义输入数据占位符。
    • 通过tf.Session()来启动会话,并在会话中执行图的操作。

    优点:

    • 图优化: 静态图允许在执行前对整个计算图进行优化,可能提高执行效率。
    • 多GPU支持: 更好地支持多GPU环境,适合大规模训练。

    TensorFlow 1.x Eager API

    实现方式:

    • TensorFlow 1.x在其后期版本中通过tf.contrib.eager模块引入了Eager API。
    • 允许立即执行操作,无需构建静态图,操作的返回值可以直接用于进一步的计算。

    优点:

    • 即时反馈: 操作执行后立即返回结果,便于调试和实验。
    • 简化的API: 减少了编写和理解代码的复杂性。

    对比作用

    • 编程模型: 静态图需要事先定义所有的操作,而Eager API允许逐步执行操作。
    • 易用性: Eager API通常更易于学习和使用,特别是对于习惯了Python即时执行特性的程序员。
    • 灵活性: Eager API提供了更高的灵活性,可以动态地修改和执行操作。
    • 性能: 静态图可能在性能上更有优势,尤其是在需要执行大量预定义计算的情况下。

    实际应用

    • 研究和开发: Eager API适合快速迭代和实验,因为它可以即时看到操作结果。
    • 生产环境: 静态图可能更适合生产环境,特别是当模型训练和推断需要高性能和稳定性时。

    总结

    尽管TensorFlow 1.x的Eager API为1.x版本带来了更现代的编程体验,但它实际上是TensorFlow 2.x中Eager执行的预演。TensorFlow 2.x默认启用Eager执行,提供了更简洁和Pythonic的API,同时保持了向后兼容性。因此,对于新项目,推荐使用TensorFlow 2.x,它结合了1.x的静态图性能和Eager API的易用性。

    2.1线性回归

    所需的库:

    tensorflow    1.12.0
    numpy         1.19.5
    matplotlib    3.3.4
    

    代码:

    # 线性回归
    import tensorflow as tf
    import numpy
    import matplotlib.pyplot as plt
    rng = numpy.random
    
    # 参数
    learning_rate = 0.01
    training_epochs = 1000
    display_step = 200
    
    # 训练数据
    train_X = numpy.asarray([3.3, 4.4, 5.5, 6.71, 6.93, 4.168, 9.779, 6.182, 7.59, 2.167,
                             7.042, 10.791, 5.313, 7.997, 5.654, 9.27, 3.1])
    train_Y = numpy.asarray([1.7, 2.76, 2.09, 3.19, 1.694, 1.573, 3.366, 2.596, 2.53, 1.221,
                             2.827, 3.465, 1.65, 2.904, 2.42, 2.94, 1.3])
    n_samples = train_X.shape[0]
    
    # tf 图输入
    X = tf.placeholder('float')
    Y = tf.placeholder('float')
    W = tf.Variable(rng.randn(), name='weight')
    b = tf.Variable(rng.randn(), name='bias')
    
    # 创建一个线性模型
    pre = tf.add(tf.multiply(X, W), b)
    
    # 均方误差损失
    cost = tf.reduce_sum(tf.pow(pre - Y, 2))/(2 * n_samples)
    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
    
    # 初始化变量(分配默认值)
    init = tf.global_variables_initializer()
    
    # 开始训练
    with tf.Session() as sess:  # 创建并进入一个TensorFlow会话的上下文管理器
        sess.run(init)  # 运行初始化器init
        for epoch in range(training_epochs):
            for (x, y) in zip(train_X, train_Y):  # 遍历训练数据集,每次迭代提供一对特征x和标签y
                sess.run(optimizer, feed_dict={X: x, Y: y})  # 运行优化器操作,如梯度下降步骤,来更新模型的参数。
    
            # 记录损失
            if (epoch + 1) % display_step == 0:
                c = sess.run(cost, feed_dict={X: train_X, Y: train_Y})
                print(f"epoch{epoch + 1} cost= {c}, W = {sess.run(W)}, b = {sess.run(b)}")
    
        print("optimization finished!")
        training_cost = sess.run(cost, feed_dict={X: train_X, Y: train_Y})
        print(f"training cost={training_cost}, W = {sess.run(W)}, b = {sess.run(b)}")
    
        # 画图
        plt.plot(train_X, train_Y, 'ro', label='Original data')
        plt.plot(train_X, sess.run(W) * train_X + sess.run(b), label='Fitted line')
        plt.legend()
        plt.show()
    
    

    输出:

    epoch200 cost= 0.08749574422836304, W = 0.30706509947776794, b = 0.3880200982093811
    epoch400 cost= 0.08340831100940704, W = 0.29456469416618347, b = 0.47794750332832336
    epoch600 cost= 0.08090882748365402, W = 0.28478333353996277, b = 0.5483137965202332
    epoch800 cost= 0.07938076555728912, W = 0.27712881565093994, b = 0.6033796668052673
    epoch1000 cost= 0.07844720780849457, W = 0.27114012837409973, b = 0.6464620232582092
    optimization finished!
    training cost=0.07844720780849457, W = 0.27114012837409973, b = 0.6464620232582092
    

    在这里插入图片描述

    2.2 使用 TensorFlow 的 Eager API 实现线性回归

    代码:

    import matplotlib.pyplot as plt
    import numpy as np
    import tensorflow as tf
    
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
    
    # 设置Eager API
    tf.enable_eager_execution()
    tfe = tf.contrib.eager
    
    # 训练数据
    train_X = [3.3, 4.4, 5.5, 6.71, 6.93, 4.168, 9.779, 6.182, 7.59, 2.167,
               7.042, 10.791, 5.313, 7.997, 5.654, 9.27, 3.1]
    train_Y = [1.7, 2.76, 2.09, 3.19, 1.694, 1.573, 3.366, 2.596, 2.53, 1.221,
               2.827, 3.465, 1.65, 2.904, 2.42, 2.94, 1.3]
    n_samples = len(train_X)
    
    # 参数设置
    learning_rate = 0.01
    display_step = 200
    num_steps = 1000
    
    # 权重与偏置
    W = tfe.Variable(np.random.randn())
    b = tfe.Variable(np.random.randn())
    
    # 线性回归
    def linear_regression(inputs):
        return inputs * W + b
    
    # 均方误差
    def mean_square_fn(model_fn, inputs, labels):
        return tf.reduce_sum(tf.pow(model_fn(inputs) - labels, 2)) / (2 * n_samples)
    
    # 梯度下降优化器
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
    
    # 计算梯度
    grad = tfe.implicit_gradients(mean_square_fn)
    
    # 初始损失
    print(f"初始损失:{mean_square_fn(linear_regression, train_X, train_Y)}, W = {W.numpy()}, b = {b.numpy()}.")
    
    # 开始训练
    for step in range(num_steps):
        optimizer.apply_gradients(grad(linear_regression, train_X, train_Y))
        if (step + 1) % display_step == 0 or step == 0:
            print(f"Epoch:{step + 1}, 损失:{mean_square_fn(linear_regression, train_X, train_Y)}, W = {W.numpy()}, b = {b.numpy()}.")
    
    plt.plot(train_X, train_Y, 'ro', label='初始数据')
    plt.plot(train_X, np.array(W * train_X + b), label='拟合曲线')
    plt.legend()
    plt.show()
    

    输出结果:

    初始损失:25.554563522338867, W = 1.414129614830017, b = 0.1566573679447174.
    Epoch:1, 损失:7.765857696533203, W = 0.9393506050109863, b = 0.09066701680421829.
    Epoch:200, 损失:0.10071783512830734, W = 0.33907845616340637, b = 0.17886608839035034.
    Epoch:400, 损失:0.09156356751918793, W = 0.32022035121917725, b = 0.3125614523887634.
    Epoch:600, 损失:0.08593194931745529, W = 0.3054291903972626, b = 0.41742414236068726.
    Epoch:800, 损失:0.0824674665927887, W = 0.2938278913497925, b = 0.4996721148490906.
    Epoch:1000, 损失:0.08033612370491028, W = 0.2847285568714142, b = 0.5641824007034302.
    

    在这里插入图片描述

    小tips

    权重(W)和偏置(b)的初始化已经在创建这两个变量时完成了。这是通过使用tf.Variable来实现的,并且使用numpy.random.randn()生成了随机数作为它们的初始值。:

    W = tf.Variable(rng.randn(), name='weight')
    b = tf.Variable(rng.randn(), name='bias')
    

    如果想给权重和偏置赋予初始值,可以这样:

    W = tf.Variable(0.4, name='weight')
    b = tf.Variable(0.7, name='bias')
    

    结果对比:

    随机数赋初值:

    training cost=0.07943815737962723, W = 0.22219787538051605, b = 0.998549222946167
    
    

    手动赋初值:

    training cost=0.07706085592508316, W = 0.25450703501701355, b = 0.7661195993423462
    
    

    赋初值的优点:

    • 能够精确控制模型参数的起始点,有助于调试和验证模型的行为;
    • 从特定的值开始训练可以提高模型的稳定性和收敛速度;
    • 使用固定的初始值时,实验结果是可重复的,这对于科学研究和调试至关重要。
    • 适当的初始化可以减少过拟合的风险
    • 在超参数调优过程中,固定的初始化策略可以确保不同设置之间的比较是公平的。
  • 相关阅读:
    Unity URP入门实战
    Python爬取数据分析
    URL组成及对应的编程变量
    Flutter基础学习(一)Dart语言入门
    配置基于 SSH 的跳转主机(跳板机)
    寻路算法之A*算法详解
    使用jdbc技术,在数据库中存储大数据对象(使用字节IO流读取图片等给blob等二进制类型数据赋值)
    Java进阶知识
    大屏小程序探索实践 | Cube 技术解读
    二十二,加上各种贴图
  • 原文地址:https://blog.csdn.net/kinkinhe/article/details/140353057