tensorflow 之 Variable的理解

it2025-08-21  7

为什么tensorflow要有Variable的对象?

编程语言中,都有变量之概念,用于保存中间计算结果,如计算100以内正整数的累加和.

int sum = 0; for (int i = 0 ;i<=100;i++){ sum += i; }

上述c++代码中,sum定义变量用于保存累加和.在内部实现时,会为sum变量分配一块固定内存,每次循环,该内存值会变化,但内存地址不变.sum变量和地址是绑定的.

以下为python语言的实现

sum = 0 for i in range(0,101): sum += i print(id(sum))

 也定义了变量sum,观察输出,会发现输出id(sum)在变化,即变量sum的地址在变化.在python中,变量不是和内存的地址绑定的.变量只是对象的一个名称.赋值语句将不同对象赋给某个变量,会改变变量的地址,其实相当于一个新的变量,只是名称没变.

tensorflow中有很多求变量的梯度操作,即变量变化对函数值的影响.该操作要根据变量变化前后的值来计算,如果变量的地址变化,则会增加实现难度.tensorflow通过定义Variable对象来简化梯度的计算.

with tf.GradientTape() as tape: # with结构记录梯度信息 y = tf.matmul(x_train, w1) + b1 # 神经网络乘加运算 y = tf.nn.softmax(y) # 使输出y符合概率分布(此操作后与独热码同量级,可相减求loss) y_ = tf.one_hot(y_train, depth=3) # 将标签值转换为独热码格式,方便计算loss和accuracy loss = tf.reduce_mean(tf.square(y_ - y)) # 采用均方误差损失函数mse = mean(sum(y-out)^2) loss_all += loss.numpy() # 将每个step计算出的loss累加,为后续求loss平均值提供数据,这样计算的loss更准确 # 计算loss对各个参数的梯度 grads = tape.gradient(loss, [w1, b1]) # 实现梯度更新 w1 = w1 - lr * w1_grad b = b - lr * b_grad w1.assign_sub(lr * grads[0]) # 参数w1自更新 b1.assign_sub(lr * grads[1]) # 参数b自更新

上述代码用梯度下降算法训练网络参数.GradientTape对象用于跟踪参数的变化对损失函数值的影响(梯度),网络参数定义为Variable对象,GradientTape会记录Variable的变化,从而计算出梯度.如果用普通变量来定义网络参数,那么每次迭代更新,网络参数就是一个新的对象.GradientTape无法跟踪这些新变量.因此,将网络参数定义成Variable,就是为了让GradientTape跟踪变化,从而计算梯度.在更新网络参数时,用Variable.assign_xxx方法,而不能用赋值操作符,赋值操作符(=)会返回一个新的Variable.

# 实现梯度更新 w1 = w1 - lr * w1_grad b = b - lr * b_grad #w1.assign_sub(lr * grads[0]) # 参数w1自更新 #b1.assign_sub(lr * grads[1]) # 参数b自更新 w1 = w1 - lr*grads[0]#w1就是一个新的对象!!!! b1 = b1 - lr*grads[1] #b1就是一个新的对象!!!!

上述代码会在第二次迭代时出错.

最新回复(0)