使用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 对象类型的变量,就像上面的示例程序那样。
|