TensorFlow实现梯度下降法求解一元和多元线性回归问题

TensorFlow实现梯度下降法求解一元和多元线性回归问题,第1张

使用TensorFlow求解一元线性回归问题
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

# 设置字体
plt.rcParams['font.sans-serif'] = ['SimHei']

# 第一步:加载数据
# x 是商品房面积
x = np.array([137.97, 104.50, 100.00, 124.32, 79.20, 99.00, 124.00, 114.00,
              106.69, 138.05, 53.75, 46.91, 68.00, 63.02, 81.26, 86.21])  # (16, )

# y 是对应的实际房价
y = np.array([145.00, 110.00, 93.00, 116.00, 65.32, 104.00, 118.00, 91.00,
              62.00, 133.00, 51.00, 45.00, 78.50, 69.65, 75.69, 95.30])  # # (16, )

# 第二步:设置超参数
learn_rate = 0.0001
itar = 100  # 迭代次数, 这里让它迭代 100 次

# 如果每次迭代次数都输出结果, 输出就会很长, 这里让它每迭代 10 次就输出一次结果
display_step = 10  # 它不属于超参数, 因为它的取值并不会影响模型的训练。

# 第三步:设置模型参数初值
# 在Numpy的random模块中,使用seed()函数设置随机种子,
# 例如这里就是设置随机种子为612,然后生成随机数。
np.random.seed(612)
# 产生标准正态分布(标准差是1均值是0)的数组, 这里参数为空, 所以返回的是一个浮点数字
w = tf.Variable(np.random.randn())  # 将返回回来的浮点数字封装为 Variable 对象
b = tf.Variable(np.random.randn())  # 将返回回来的浮点数字封装为 Variable 对象

# 第四步:训练模型
mse = []  # 这是个Python列表, 用来保存每次迭代后的损失值

# 下面使用 for 循环来实现迭代
# 循环变量从 0 开始,11 结束,循环 11, 为了描述方便, 以后就说迭代 10 次
# 也就是说, 当 i 等于 10, 我们就说第十次迭代
for i in range(0, itar + 1):

    # 首先计算损失函数对 w 和 b 的偏导数
    with tf.GradientTape() as tape:
        pred = w * x + b  # 第一次使用初始的 w 和 b, 之后每一次循环使用上一次得到的 w 和 b, 计算所有样本的房价的估计值。
        # 损失函数
        Loss = 0.5 * tf.reduce_mean(tf.square(y - pred))
    mse.append(Loss)  # 把得到的均方误差加入列表 mse
    dL_dw, dL_db = tape.gradient(Loss, [w, b])

    # 然后使用迭代公式更新 w 和 b
    w.assign_sub(learn_rate * dL_dw)
    b.assign_sub(learn_rate * dL_db)

    if i % display_step == 0:
        print("i:%i, Loss:%f, w:%f, b:%f" % (i, Loss, w.numpy(), b.numpy()))
    """
    i:0, Loss:4749.362305, w:0.946047, b:-1.153577
    i:10, Loss:89.157196, w:0.957985, b:-1.152950
    i:20, Loss:89.156952, w:0.957980, b:-1.152439
    i:30, Loss:89.156662, w:0.957975, b:-1.151927
    i:40, Loss:89.156403, w:0.957970, b:-1.151416
    i:50, Loss:89.156143, w:0.957965, b:-1.150905
    i:60, Loss:89.155899, w:0.957960, b:-1.150393
    i:70, Loss:89.155624, w:0.957955, b:-1.149882
    i:80, Loss:89.155365, w:0.957950, b:-1.149370
    i:90, Loss:89.155090, w:0.957945, b:-1.148859
    i:100, Loss:89.154831, w:0.957940, b:-1.148347
    """
使用TensorFlow求解多元线性回归问题
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

# 设置字体
plt.rcParams['font.sans-serif'] = ['SimHei']

# 第一步:加载数据
# area 是商品房面积
area = np.array([137.97, 104.50, 100.00, 124.32, 79.20, 99.00, 124.00, 114.00,
                 106.69, 138.05, 53.75, 46.91, 68.00, 63.02, 81.26, 86.21])  # (16, )

# room 是商品房房间数
room = np.array([3, 2, 2, 3, 1, 2, 3, 2,
                 2, 3, 1, 1, 1, 1, 2, 2])

# price 是样本房价
price = np.array([145.00, 110.00, 93.00, 116.00, 65.32, 104.00, 118.00, 91.00,
                  62.00, 133.00, 51.00, 45.00, 78.50, 69.65, 75.69, 95.30])

# 第二步:数据处理
num = len(area)

# 创建元素值全为1的一维数组 x0
x0 = np.ones(num)
# x1 是商品房面积归一化后的结果
x1 = (area - area.min()) / (area.max() - area.min())
# x2 是商品房房间数归一化后的结果
x2 = (room - room.min()) / (room.max() - room.min())

# 将 x0、x1、x2堆叠为形状为 (16, 3) 的二维数组
X = np.stack((x0, x1, x2), axis=1)
X = tf.Variable(X, dtype=tf.float32)

# 将 price 转换为形状为 (16, 1) 的二维数组
Y = price.reshape(-1, 1)
Y = tf.Variable(Y, dtype=tf.float32)

# 第三步:设置超参数 学习率,迭代次数
learn_rate = 0.01
itar = 1000  # 迭代次数为100000次

display_step = 50  # 每循环5000次显示一次训练结果

# 第四步:设置模型参数的初始值
np.random.seed(612)
W = np.random.randn(3, 1)
W = tf.Variable(W, dtype=tf.float32)
# 一般来说, 在这里指定数据类型为float32, 以提高效率

print(W)
"""
<tf.Variable 'Variable:0' shape=(3, 1) dtype=float32, numpy=
array([[-0.01337706],
       [-1.1628988 ],
       [-0.22487308]], dtype=float32)>
"""

# 第五步:训练模型 W
mse = []  # 这是个Python列表, 用来保存每次迭代后的损失值

# 下面使用 for 循环来实现迭代
# 循环变量从 0 开始,101 结束,循环 101, 为了描述方便, 以后就说迭代 100 次
# 同样, 当 i 等于 10, 我们就说第十次迭代
for i in range(0, itar + 1):

    # 首先计算损失函数对 W 的偏导数
    with tf.GradientTape() as tape:
        # 这里的 X 形状为 (16, 3), W 形状为 (3, 1), 得到 Y_PRED 的形状为 (16, 1)
        Y_PRED = tf.matmul(X, W)  # 第一次使用初始的W, 之后每一次循环使用上一次得到的W, 计算所有样本的房价的估计值。
        # 损失函数
        Loss = 0.5 * tf.reduce_mean(tf.square(Y - Y_PRED))
    mse.append(Loss)  # 把得到的均方误差加入列表 mse
    dL_dW = tape.gradient(Loss, W)

    # 然后使用迭代公式更新 W
    W.assign_sub(learn_rate * dL_dW)

    # 我们希望能够观察到每次迭代的结果, 判断是否收敛或者什么时候开始收敛
    # 因此需要使用每次迭代后的 W 来计算损失, 并且把它显示出来
    if i % display_step == 0:
        print("i:%i, Loss:%f" % (i, mse[i]))
        """
        i:0, Loss:4593.851562
        i:50, Loss:998.102661
        i:100, Loss:269.221741
        i:150, Loss:121.190849
        i:200, Loss:90.882095
        i:250, Loss:84.464798
        i:300, Loss:82.924240
        i:350, Loss:82.403328
        i:400, Loss:82.116432
        i:450, Loss:81.900719
        i:500, Loss:81.720032
        i:550, Loss:81.564247
        i:600, Loss:81.428947
        i:650, Loss:81.311172
        i:700, Loss:81.208534
        i:750, Loss:81.118996
        i:800, Loss:81.040794
        i:850, Loss:80.972412
        i:900, Loss:80.912552
        i:950, Loss:80.860046
        i:1000, Loss:80.813942
        """
print(W)
"""
<tf.Variable 'Variable:0' shape=(3, 1) dtype=float32, numpy=
array([[54.248806],
       [37.51803 ],
       [35.713833]], dtype=float32)>
"""

这里需要提及以下几点:
1、程序流程问题,这与之前使用Numpy实现有区别。

2、32位和64位浮点数类型的问题。

numpy 的默认浮点数类型为 float64,而张量的默认浮点数类型为 tf.float32,Variable 对象变量的默认浮点数类型与创建该变量的方式有关,如果是通过numpy 数组创建的,则是float32,而如果是通过Tensor对象创建的,则是float64。

这里,我遇到个问题,为了提高运算效率,将浮点数数据类型指定为float32。

起初,直接使用默认的(float64数据类型)方式,可以使用

# 第四步:设置模型参数的初始值
np.random.seed(612)
W = np.random.randn(3, 1)
W = tf.Variable(W)

这里是直接将 W 这个 Numpy 数组 转化为可训练变量,然后,直接进行运算,可以正常运行代码,

而如果我将其都转化为float32后,则会在运行下面这句代码时,

Y_PRED = tf.matmul(X, W)

因为数据类型不符而报错,

(补充一点,

W = tf.Variable(W, dtype=np.float32)

就算这里指定为np.float32,但前面因为使用的 Variable 方法是TensorFlow的方法,因此,np.float32 还是会被自动转换为 tf.float32 ,所以还是没用。

因此,为了避免这种错误的出现,可以在运算之前都将它们统一的转化为 Variable 对象类型的变量,就像上面的示例程序那样。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/786622.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存