tensorflow 之 Variable的理解

为什么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就是一个新的对象!!!!

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值