之前用tensorflow的张量完成了二元随机梯度下降法,但是tensorflow可以自动求导,这样的话就不用进行复杂的矩阵变换以求得损失函数的导数,可以直接用tensorflow获取导数(GradientTape()方法),同样这里也有一些坑
首先,还是导入模块
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from mpl_toolkits.mplot3d import Axes3D
然后导入数据,并转换为可处理的形式
x0 = tf.ones([13], dtype=tf.float32)
area = tf.Variable([125, 145, 361, 123, 451, 233, 451, 123,
411, 236, 452, 123, 411], dtype=tf.float32)
room = tf.Variable([1, 1, 3, 1, 4, 2, 4, 1, 4, 2, 4, 1, 4], dtype=tf.float32)
price = tf.Variable([124, 125, 355, 143, 481, 243, 461, 143,
451, 237, 472, 153, 441], dtype=tf.float32)
x1 = tf.reshape((area-tf.reduce_min(area)) /
(tf.reduce_max(area)-tf.reduce_min(area)), [13])
x2 = tf.reshape((room-tf.reduce_min(room)) /
(tf.reduce_max(room)-tf.reduce_min(room)), [13])
X = tf.stack((x0, x1, x2), axis=1) # 堆叠
Y = tf.reshape(price, [13, 1])
g1 = tf.random.Generator.from_seed(211) # 随机数种子
W = g1.normal([3, 1])
W = tf.Variable(W) # 转换为图变量
基本的数据导入以及矩阵变换,因为之后要计算损失函数因此还需要对矩阵形状进行修改。值得注意的是由于损失函数loss=tf.reduce_sum(tf.square(Y-tf.matmul(X,W))),在函数之中需要追踪的是W的变化梯度,因此需要将W变换为Variable类型的变量进行运算.
完成数据导入之后就设置超参数以及进行运算
learn_rate=0.001 #学习率
iters=10000 #迭代次数
display=1000 #展示间隔
mse=[]
for i in range(iters+1):
with tf.GradientTape() as tape:
loss=tf.reduce_sum(tf.square(Y-tf.matmul(X,W))) #损失函数
dw=tape.gradient(loss,W)
W=tf.Variable(W-learn_rate*dw) #转换为图变量
pred=tf.matmul(X,W)
LOSS=tf.reduce_mean(tf.square(Y-pred))/2
mse.append(LOSS)
if i%display==0:
print("i:%d LOSS:%f"%(i,LOSS)) #输出损失
值得注意的是通过tape.gradient获得的导数dw的变量类型并不是Variable,因此需要在运算后转换为Variable变量,否则在第二次迭代的时候tape.gradient会无法获取变量,导致dw变成None,进而无法继续运行。最后就这样获得了一个迭代结果
最后是画图表现结果不过要加一句
price=np.array(price)
转换为numpy数组,否则二维图会报错。
然后画图——
plt.rcParams['font.sans-serif']=['SimHei']
plt.figure(figsize=(12,4))
plt.subplot(1,2,1)
plt.plot(mse)
plt.xlabel("Iter",fontsize=14)
plt.ylabel("Loss",fontsize=14)
plt.subplot(1,2,2)
pred=tf.reshape(pred,-1)
plt.plot(price,color='red',label="销售记录")
plt.plot(pred,color='blue',label="预测房价")
plt.xlabel("Sample",fontsize=14)
plt.ylabel("Price",fontsize=14)
plt.legend()
plt.show
然后是三维网格图——(代码我就直接复制上我一篇文章的代码了,关于这段代码,上一篇文章上有详解)
fig=plt.figure()
ax3d=Axes3D(fig,auto_add_to_figure=False)
fig.add_axes(ax3d)
ax3d.scatter(area,room,price,color="blue",marker="*")
A, R = np.meshgrid(x1, x2)
AREA,ROOM=np.meshgrid(area, room)
P=W[0,0]+W[1,0]*A+W[2,0]*R
ax3d.plot_wireframe(AREA,ROOM,P,linewidth=0.5) # 设置颜色映射
# 设置标题
plt.title("3D图")
ax3d.set_xlabel("areas",color="r",fontsize=14)
ax3d.set_ylabel("rooms",color="r",fontsize=14)
ax3d.set_zlabel("prices",color="r",fontsize=14)
ax3d.set_yticks([1,2,3])
plt.show
至此终于完成了利用tensorflow自动求导的梯度下降算法以及可视化展示,下面贴一个完整代码。
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from mpl_toolkits.mplot3d import Axes3D
x0 = tf.ones([13], dtype=tf.float32)
area = tf.Variable([125, 145, 361, 123, 451, 233, 451, 123,
411, 236, 452, 123, 411], dtype=tf.float32)
room = tf.Variable([1, 1, 3, 1, 4, 2, 4, 1, 4, 2, 4, 1, 4], dtype=tf.float32)
price = tf.Variable([124, 125, 355, 143, 481, 243, 461, 143,
451, 237, 472, 153, 441], dtype=tf.float32)
x1 = tf.reshape((area-tf.reduce_min(area)) /
(tf.reduce_max(area)-tf.reduce_min(area)), [13])
x2 = tf.reshape((room-tf.reduce_min(room)) /
(tf.reduce_max(room)-tf.reduce_min(room)), [13])
X = tf.stack((x0, x1, x2), axis=1) # 堆叠
X = tf.Variable(X)
Y = tf.reshape(price, [13, 1])
g1 = tf.random.Generator.from_seed(211) # 随机数种子
W = g1.normal([3, 1])
W = tf.Variable(W)
learn_rate=0.001
iters=10000
display=1000
mse=[]
for i in range(iters+1):
with tf.GradientTape() as tape:
loss=tf.reduce_sum(tf.square(Y-tf.matmul(X,W)))
dw=tape.gradient(loss,W)
W=tf.Variable(W-learn_rate*dw)
pred=tf.matmul(X,W)
LOSS=tf.reduce_mean(tf.square(Y-pred))/2
mse.append(LOSS)
if i%display==0:
print("i:%d LOSS:%f"%(i,LOSS))
price=np.array(price)
plt.rcParams['font.sans-serif']=['SimHei']
plt.figure(figsize=(12,4))
plt.subplot(1,2,1)
plt.plot(mse)
plt.xlabel("Iter",fontsize=14)
plt.ylabel("Loss",fontsize=14)
plt.subplot(1,2,2)
pred=tf.reshape(pred,-1)
plt.plot(price,color='red',label="销售记录")
plt.plot(pred,color='blue',label="预测房价")
plt.xlabel("Sample",fontsize=14)
plt.ylabel("Price",fontsize=14)
plt.legend()
plt.show
fig=plt.figure()
ax3d=Axes3D(fig,auto_add_to_figure=False)
fig.add_axes(ax3d)
ax3d.scatter(area,room,price,color="blue",marker="*")
A, R = np.meshgrid(x1, x2)
AREA,ROOM=np.meshgrid(area, room)
P=W[0,0]+W[1,0]*A+W[2,0]*R
ax3d.plot_wireframe(AREA,ROOM,P,linewidth=0.5) # 设置颜色映射
# 设置标题
plt.title("3D图")
ax3d.set_xlabel("areas",color="r",fontsize=14)
ax3d.set_ylabel("rooms",color="r",fontsize=14)
ax3d.set_zlabel("prices",color="r",fontsize=14)
ax3d.set_yticks([1,2,3])
plt.show