基于tensorflow自动求导实现的二元梯度下降法

之前用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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值