变量是指在程序运行过程中,存储可以变化的数据;而常量是指在程序运行过程中,值不能改变的量。常量因其不变性,编译器可以直接将其编译成目标代码,有利于提升程序的性能。
constant 常量
基于 python 数据构建常量
在 TensorFlow 中,可以利用 tf.constant()
方法来生成常量,例如用 Python 列表来生成常量:
import tensorflow as tf
a_list = [1, 2, 3, 4, 5]
b = tf.constant(a_list)
print(b)
上述代码运行结果为:
tf.Tensor([1 2 3 4 5], shape=(5,), dtype=int32)
基于 numpy 数据构建常量
也可以利用 Numpy 数组来生成常量:
import numpy as np
import tensorflow as tf
np_arr = np.array([[1, 2, 3], [4, 5, 6]])
c = tf.constant(np_arr)
print(c)
上述代码运行结果为:
tf.Tensor(
[[1 2 3]
[4 5 6]], shape=(2, 3), dtype=int64)
利用数据扩展构建常量
若提供的数据不完整,可以设置 shape
参数,利用数据扩展来构建常量:
import tensorflow as tf
const_float_tensor = tf.constant(10.0, shape=[2, 3, 4], dtype=tf.float32)
print(const_float_tensor)
上述代码运行结果为:
tf.Tensor(
[[[10. 10. 10. 10.]
[10. 10. 10. 10.]
[10. 10. 10. 10.]]
[[10. 10. 10. 10.]
[10. 10. 10. 10.]
[10. 10. 10. 10.]]], shape=(2, 3, 4), dtype=float32)
Variable 变量
在机器学习中,某些参数(如模型参数)可能需要长期保存,且值会不断发生更迭,这时就需要用变量(Variable)来保存。
tf.Variable
对象是一个常驻内存,不会被轻易回收的张量。在神经网络中,由于梯度运算会消耗大量计算资源,因此对于那些不需要进行优化的张量(例如神经网络的输入层 X
),无需利用 tf.Variable
进行构建。
对于需要进行梯度运算和优化的张量,如神经网络中的权值 w
和偏置 b
,它们的值在不断变化,同时在更新值的时候,还要用到上一次的值,因此需要利用 tf.Variable
来构建,便于 TensorFlow 跟踪梯度相关信息。
我们可以利用 tf.Variable()
方法来创建变量,如下:
import tensorflow as tf
my_state = tf.Variable(1.0) # 定义变量
one = tf.constant(1.0) # 定义常量
read_and_increment = tf.function(lambda: my_state.assign_add(one)) # 自定义 TensorFlow 函数
print(my_state)
for _ in range(3):
read_and_increment() # 调用 read_and_increment 函数
print(my_state.numpy()) # 将张量转换为 numpy 数据类型并输出
上述代码运行结果为:
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>
2.0
3.0
4.0
上述代码中
read_and_increment = tf.function(lambda: my_state.assign_add(one))
中利用tf.function()
方法创建了一个名称为read_and_increment
的 TensorFlow 函数,该函数通过lamda
表达式方法实现了my_state
变量的自增操作,类似于i++
,assign_add()
方法是每个tf.Variable
对象都拥有的方法,可以实现求和与自我赋值操作。
tf.Variable 详解
name 和 trainable 属性
我们注意到一个问题,在 tf
作为前缀名时,有时后面的成员是小写(tf.constant
),有时又是大写(例如 tf.Variable
),这是什么原因呢?这是 TensorFlow 中的编程约定,若成员首字母小写,表明其是一级方法成员;若成员首字母大写,表明其是类(class
)。
tf.Variable
有两个属性:name
和 trainable
。不指定 name
属性的话,TensorFlow 会自动维护命名体系;trainable
表明是否参与梯度运算,默认值为 True
(表明参与梯度运算,TensorFlow 会对其进行优化)。
我们通过代码来查看下 tf.Variable
对象的两个属性:
import tensorflow as tf
my_state = tf.Variable(1.0) # 定义变量
print(my_state.name)
print(my_state.trainable)
上述代码运行结果为:
Variable:0
True
注意:
trainable
是只读属性,在tf.Variable
对象初始化之后,trainable
属性就无法改变了。
计算图
TensorFlow 1.x 版本中的计算图使用起来非常麻烦,因此 TensorFlow 2.0 版本推荐使用即时执行模式,但也带来了执行效率低下的问题,因为在即时执行模式中,需要依赖 Python 解释器进行计算,无法对数据流和计算图进行优化,为了解决该问题, TensorFlow 2.0 引入了 tf.function
概念来构建计算图。
在之前 read_and_increment = tf.function(lambda: my_state.assign_add(one...[^1] 中我们使用了 tf.function
方法来构建一个简单的计算图,我们还可以通过装饰器 @tf.function
来构建一个计算图,如下所示:
import tensorflow as tf
@tf.function
def func1(x):
if tf.reduce_sum(x) > 0:
return x * x
else:
return -x // 2
my_var = tf.Variable([3, -2, 4])
tf.print(func1(my_var).numpy())
上述代码运行结果为:
array([ 9, 4, 16], dtype=int32)