TensorFlow 基础 (02)

前面对 tensorflow 的基础数据类型, 数值, 字符串, 布尔等, 有初步认识,尤其是重点的 tensor 张量, 包含了, 标量, 向量, 矩阵 ... 这样的基本概念. 我现在回过头来看, 其实这些编程概念和数学概念, 如果不那么严格区分的话, 其表现形式大体上是相似的. 编程语言的这些基本数据类型, 数据结构, 让一些数学概念能够更好地被认识和理解, 比如, 积分的概念, 线性代数中, 向量, 矩阵的认识... 这些从编程来认识, 则是多么直观和自然啊.

明天要过 6.1 儿童节了, 对我而言, 其实是意味着, 2020 过去了一半, 而编程技术有没有提高呢, 这是我最关系的点. 当然我也相信这块是 唯手熟尔, 每天坚持学习和练习, 终有一天, 能够让别人看到吧.

不扯了... 继续整学习笔记, 学一波 tensorflow, 成为一把工具人, 虽然很多算法的数学原理我已能推导, 但应用上还是有欠缺,这正好是用工具来进行弥补的.

读取数值精度

通过张量的 dtype 属性, 可以访问和修改其保存的精度, 转换用 tf.cast() 来实现.

# 精度调整

tf_arr = tf.constant([1, 2, 3])

print('before:', tf_arr.dtype)
# 对精度进行转换: tf.cast()
if tf_arr.dtype != tf.float32:
    tf_arr = tf.cast(tf_arr, tf.float32)
    
print('after', tf_arr.dtype)
before: <dtype: 'int32'>
after <dtype: 'float32'>

类型转换

同上, 类型, 精度啥的, 为了满足特定需求, 需要进行转换, 也是用 tf.cast() 函数来实现转换哦.

from math import pi

# 创建 tf.float16 低精度张量
arr = tf.constant(pi, dtype=tf.float16)
print(arr)
# 转为 tf.float64 高精度张量
tf.cast(arr, tf.float64)
tf.Tensor(3.14, shape=(), dtype=float16)

<tf.Tensor: id=10, shape=(), dtype=float64, numpy=3.140625>

转换时需注意操作的合理性, 如要将高精度的张量转为低精度的张量, 可能会发生 数据溢出的风险哦.

# 高精度 => 低精度 => 数据溢出

print(tf.cast(arr, tf.int8))
tf.Tensor(3, shape=(), dtype=int8)

似乎溢出好像也没报错, 当然我们都知道, 精度下降了而已. 另外, 布尔类型 和 整形 之间的转换也是可以的哦.

# bool => int32 即吧 True, False 转为了 1,0 
arr = tf.constant([True, False])
tf.cast(arr, tf.int32)
<tf.Tensor: id=14, shape=(2,), dtype=int32, numpy=array([1, 0])>

一般都是默认 0 表示 False, 1 表示 True, 在 tf 中, 将 非 0 的数字都视为 True , 跟 Python 差不多哈. Python 中的 布尔是, 除了, False, None, 0, [ ], ( ), { } ...外, 都是 True 的呀.

arr = tf.constant([-1, 0, 1, 2])
print(tf.cast(arr, tf.bool))
tf.Tensor([ True False  True  True], shape=(4,), dtype=bool)

待优化张量

在计算中, 一般要区分张量为两拨. 需要计算梯度信息的张量, 和无需算梯度的张量.

TensorFlow 增加了一种数据类型 tf.Variable 来支持 需要进行梯度计算的张量. tf.Variable 类型, 在普通的张量类型上, 新增了 name, trainable 等属性来支持计算图的构建.

为啥要 tf.Variable

tf 是是一种图计算网络嘛, 熟悉神经网络的小伙伴也都清楚, 整个训练过程就是一直在计算梯度, 每层..循环迭代. 梯度计算会消耗大量的计算资源, 而且会 自动更新相关参数.

  • 对于不需要优化的张量, 如神经网络输入 x 这个一维向量, 就不需要 tf.Variable 封装;

  • 而需要求梯度的张量, 如神经网络层的 \(W_{ij}, b_j\) 需要 tf.Variable 来存储, 和跟踪梯度信息

通过 tf.Variable( ) 函数, 即可将普通的张量, 转换为待优化的张量.

# 待优化张量
tf_arr = tf.constant([-1, 0, 1, 2])
print(tf_arr)

# 转为 Variable 类型
tf_arr_v = tf.Variable(tf_arr)
print(tf_arr_v)
# Variable 特有属性
print(tf_arr_v.name, tf_arr_v.trainable)	
tf.Tensor([-1  0  1  2], shape=(4,), dtype=int32)

<tf.Variable 'Variable:0' shape=(4,) dtype=int32, numpy=array([-1,  0,  1,  2])>

Variable:0 True

name 和 trainable 属性是 Variable 类型特有的. name 用于命名计算图变量, 当然这些命名是 tf 自己内部维护的, 就跟那个 mongodb 自己生成的 ID 是一样的吧. trainable 属性表示当前张量是否需要被优化, 默认 trainable=False.

# 直接创建 tf.Variable
tf_arr = tf.Variable([[1,2,3], [4,5,6]])

print(tf_arr)
<tf.Variable 'Variable:0' shape=(2, 3) dtype=int32, numpy=
array([[1, 2, 3],
       [4, 5, 6]])>

这些优化或者被特殊对待的张量, 目的就是上面说的可以跟踪梯度信息 list. 普通的张量, 也可以通过 GradientTape.watch( ) 方法临时加入公祖梯度信息的列表, 从而也能 自动求导. 类似于 sodu 下, 临时用用.

小结

  • 获取精度用 dtype 属性, 直接获取即可, 转换用 tf.cast( ) 实现, 会生成新的 tf 对象哦.
  • 类型转换 也是用 tf.cast( ), 低精度 => 高精度 ok, 但反之则可能数据溢出, 测了没有报错, 精度降低了而已
  • tf.Variable( ) 是"特殊" 的张量, 能跟踪自动求导的梯度信息, 由 trainable = False / True 来指定.
posted @ 2020-05-31 21:16  致于数据科学家的小陈  阅读(196)  评论(0编辑  收藏  举报