Tensorflow 2.0.0 简介和基础语法
Reference
龙龙老师 --- 深度学习 TensorFlow 电子书
下面是学习的一些笔记,希望大家也能去看原版的书,写的很好,受益匪浅!
背景:TensorFlow 是 Google 于 2015 年发布的深度学习框架,最初版本只支持符号式编程。 得益于发布时间较早,以及 Google 在深度学习领域的影响力,TensorFlow 很快成为最流行的深度学习框架。但是由于 TensorFlow 接口设计频繁变动,功能设计重复冗余, 符号式编程开发和调试非常困难等问题,TensorFlow 1.x 版本一度被业界诟病。2019 年,Google 推出 TensorFlow 2 正式版本,将以动态图优先模式运行,从而能够避免 TensorFlow 1.x 版本的诸多缺陷,已获得业界的广泛认可。
与TensorFlow1.x 比较:
计算 2.0 + 4.0 :
import tensorflow as tf
# 1. 创建计算图阶段
# 创建2各输入端子,指定类型和名字
a_ph = tf.placeholder(tf.float32, name='variable_a')
b_ph = tf.placeholder(tf.float32, name='variable_b')
# 创建输出端子的运算操作,并命名
c_op = tf.add(a_ph, b_ph, name='variable_c')
# 2. 运算计算图阶段
# 创建运行环境
sess = tf.InteractiveSession()
# 初始化
init = tf.global_variables_initializer()
sess.run(init)
# 运行输出端子,需要给输入端子赋值
c_numpy = sess.run(c_op, feed_dict={a_ph: 2., b_ph: 4.})
print('a+b=', c_numpy)
# 1. 创建输入张量
a = tf.constant(2.)
b = tf.constant(4.)
# 2. 直接计算并打印
print('a+b=', a+b)
三大核心功能:
-
加速计算
神经网络本质上由大量的矩阵相乘,矩阵相加等基本数学运算构成,TensorFlow 的重 要功能就是利用 GPU 方便地实现并行计算加速功能。
-
自动梯度
在使用 TensorFlow 构建前向计算过程的时候,除了能够获得数值结果,TensorFlow 还 会自动构建计算图,通过 TensorFlow 提供的自动求导的功能,可以不需要手动推导,即可计算出输出对网络的偏导数。
-
常用神经网络接口
TensorFlow 除了提供底层的矩阵相乘,相加等运算函数,还内建了常用网络运算函 数,常用网络层,网络训练,网络保存与加载,网络部署等一系列深度学习系统的便捷功 能。使用 TensorFlow 开发网络,可以方便地利用这些功能完成常用业务流程,高效稳定。
Tensorflow 基础
TensorFlow 是一个面向于深度学习算法的科学计算库,内部数据保存在张量(Tensor)对象上,所有的运算操作也都是基于张量对象进行。复杂的神经网络算法本质 上就是各种张量相乘、相加等基本运算操作的组合。
1. 数据类型
基本数据类型包含了数值型、字符串型和布尔型
-
数值类型
数值型的张量是 Tensorflow 的主要数据载体,分为:
- 标量(Scalar):单个的实数,如 1.2,7.8等,维度数(Dimension,也叫秩)为0,shape 为[]
- 向量(Vector):n 个实数的有序集合,通过中括号包裹,如[1.2], [1.2, 2.0]等,维度数为1,长度不定,shape为[n]
- 矩阵(Matrix):n行m列实数的有序集合,如[[1,2],[3,4]]等,维度数为2,每个维度上的长度不定,shape为[n,m]
- 张量(Tensor):所有维度数 dim > 2的数组统称为张量。张量的每个维度也叫做轴(Axis),一般维度代表了具体的物理含义,如Shape为[2,32,32,3]的张量共有4维,如果表示图片数据的话,每个维度/轴的含义分别是:图片数量、图片高度、图片宽度、图片通道数。张量的维度数以及每个维度所代表的具体物理含义需要由用户自行定义
在Tensorflow中,为了表达方便,一般会把标量、向量、矩阵也统称为张量,不作区分,需要根据张量的维度数和形状自行判断
实例:
import tensorflow as tf # 创建标量 a = tf.constant(1.2) # 创建向量 b = tf.constant([1,2,3]) # 创建矩阵 c = tf.constant([[1,2],[3,4]])
-
字符串类型
通过传入字符串对象即可创建字符串类型的张量,在tf.strings模块中,提供了常见的字符串类型的工具函数
# 创建字符串张量 str = tf.constant('Hello, Deep Learning.') # 将大写的字符串转换成小写 tf.strings.lower(str)
-
布尔型
布尔类型的张量只需要传入python语言的布尔类型数据,转换成Tensorflow内部布尔型即可(需要注意的是两者布尔类型并不对等,不能通用):
# 创建布尔张量 d = tf.constant(True)
2.数值精度
常用的精度类型有 tf.int16, tf.int32, tf.int64, tf.float16, tf.float32, tf.float64(tf.double)
通过访问张量的 dtype 成员属性来读取张量的保存精度
对于不符合要求的张量的类型及精度,可通过 tf.cast函数进行转换
3.待优化张量
为了区分需要计算梯度信息的张量以及不需要计算梯度信息的张量,使用一种专门的数据类型来支持梯度信息的记录:tf.Variable。tf.Variable 类型在普通的张量类 型基础上添加了 name(由内部维护),trainable (表征当前张量是否需要被优化)等属性来支持计算图的构建。
4.创建张量
-
从Numpy,List对象创建
通过 tf.convert_to_tensor 可以创建新 Tensor,并将保存在 Python List 对象或者 Numpy Array 对象中的数据导入到新 Tensor 中
# 创建张量 tf.convert_to_tensor([1,2.])
tf.constant()和 tf.convert_to_tensor()都能够自动的把 Numpy 数组或者 Python List 数据类型转化为 Tensor 类型
-
创建全0,全1张量
将张量创建为全0或全1数据常作为张量初始化手段。
# 创建全0或全1的矩阵 tf.zeros([2,2]) # [[0., 0.], [0., 0.]] tf.ones([3,3]) # [[1., 1.], [1., 1.], [1., 1.]]
-
创建自定义数值张量
通过 tf.fill(shape, value) 可以创建全为自定义数值 value 的张量。
# 创建所有元素为16的矩阵 tf.fill([2,2], 16) # [[16, 16], [16, 16]]
-
创建已知分布的张量
常用的 正态分布(Normal Distribution 或 Gaussian Distribution)和 均匀分布(Uniform Distributiion)。如在卷积神经网络中,卷积核张量W初始化为正态分布有利于网络的训练,在;在对抗生成网络中,隐藏变量z一般采样自均匀分布。
# 创建均值为1,标准差为2的正太分布 tf.random.normal([2,2], mean=1, stddev=2) # 创建采样自区间[0,1]的均匀分布,shape为[2,2]的矩阵 tf.random.uniform([2,2], minval=0, maxval=1)
-
创建序列
在循环计算或者对张量进行索引时,经常需要创建一段连续的整形序列,可以通过tf.range()函数实现。
# 创建1~10,步长为2的序列 tf.range(1, 10, delta=2) # [1, 3, 5, 7, 9]
5.张量的典型应用
-
标量
标量就是一个简单的数字,维度数为0,shape为[]。它的典型用途之一是误差值的表示、各种测量指标的表示,比如准确度(Accuracy),精度(Percision)和召回率(Recall)等
如下图的损失值和准确度:
# 随机模拟网络输出 out = tf.random.uniform([4,10]) # 随机构造样本真实标签 y = tf.constant([2,3,2,0]) # one-hot编码 y = tf.one_hot(y, depth=10) # 计算每个样本的MSE(均方误差) loss = tf.keras.losses.mse(y, out) # 平均MSE loss = tf.reduce_mean(loss)
-
向量
向量是一种常见的数据载体,如在全连接层和卷积神经网络中,偏置张量b就使用向量来表示。如下图把所有输出节点的偏置表示成向量形式:
# z=wx,模拟获得激活函数的输入z z = tf.random.normal([4,2]) b = tf.zeros([2]) # 模拟偏置向量 z = z + b # 累加偏置
-
矩阵
如全连接层的批量输入 x=[b,d], b表示输入样本的个数(batch size),d表示输入特征的长度。
-
3维张量
三维的张量一个典型应用是表示序列信号,它的格式是
其中𝑏表示序列信号的数量,sequence len 表示序列信号在时间维度上的采样点数,feature len 表示每个点的特征长度。
如NLP中,评价句子是否为正面情绪的情感分类任务网络,如下图:
为了能够方便字符串被神经网络处理,一般将单词通过嵌入层(Embedding Layer
)编码为固定长度的向量
# 自动加载IMDB电影评价数据集 x_train, y_train, x_test, y_test = tf.keras.datasets.imdb.load_data(num_words=10000) # 将句子填充、截断为等长 80 个单词的句子 x_train = tf.keras.preprocessing.sequence.pad_sequences(x_train,maxlen=80) # 创建词向量Embedding层类(每个单词转换为长度为100个词向量) embedding = layers.Embedding(10000, 100) # 将数字编码的单词转换为词向量 out = embedding(x_train) out.shape # [25000, 80, 100]
-
4维张量
4维张量在卷积神经网络中应用的非常广泛,它用于保存特征图(Feature maps)数据,格式一般定义为
其中 b 表示输入的数量,h/w分布表示特征图的高宽,𝑐表示特征图的通道数。
# 创建32x32的彩色图片输入,个数为4 x = tf.random.normal([4, 32, 32, 3]) # 创建卷积神经网络 layer = layers.Conv2D(16, kernel_size=3) out = layer(x) # 前向计算
6.维度变换
通过维度变换可以将数据任意地切换形式,满足不同场合的运算需求。
基本的维度变换包含了改变视图reshape,插入新维度expand_dims,删除维度squeeze,交换维度transpose,复制数据tile等
7.数学运算
加减乘除,分别通过 tf.add, tf.substract, tf.multiply, tf.divide 函数实现,但直接使用运算符来完成更方便。
a = tf.range(5) # [0, 1, 2, 3, 4]
b = tf,constant(2)
a + b # [2, 3, 4, 5, 6]
a - b # [-2, -1, 0, 1, 2]
a * b # [0, 2, 4, 6, 8]
a // b # [0, 0, 1, 1, 2]
a ** b # [0, 1, 4, 9, 16]
# 自然对数 lnx 函数实现(其它底数的对数,通过换底公式实现)
x = tf.math.log(b)
# 矩阵相乘(通过@或tf.matmul(a,b)实现)
a = tf.random.normal([4,28,32,3])
b = tf.random.normal([4,32,2,3])
a@b
tf.matmul(a,b)
8.合并与分割
合并是指将多个张量在某个维度上合并为一个张量。张量的合并可以使用拼接(Concatenate)和堆叠(Stack)操作实现,拼接并不会产生新的维度,而堆叠会创建新维度。合并操作的逆过程就是分割,将一个张量分拆为多个张量,tf.split(x, axis, num_or_size_splits)可以完成张量的分割操作。
# 拼接
a = tf.random.normal([4,35,8]) # 模拟成绩册 A
b = tf.random.normal([6,35,8]) # 模拟成绩册 B
tf.concat([a,b],axis=0) # 合并成绩册(axis指定需要合并的维度[10,35,8])
# 堆叠(前提条件是合并的张量shape完全一致)
a = tf.random.normal([35,8])
b = tf.random.normal([35,8])
tf.stack([a,b],axis=0) # 堆叠合并为 2 个班级([2,35,8])
x = tf.random.normal([10,35,8])
# 等长切割
result = tf.split(x,axis=0,num_or_size_splits=10)
9.数据统计
-
向量范数
向量范数(Vector norm)是表征向量“长度”的一种度量方法,在神经网络中,常用来表示张量的权值大小,梯度大小等。常用的向量范数有:
- L1范数:定义为向量 𝒙 的所有元素绝对值之和
- L2范数:定义为向量 𝒙 的所有元素的平方和,再开根号
- ∞ 范数:定义为向量 𝒙 的所有元素绝对值的最大值
对于矩阵、张量,同样可以利用向量范数的计算公式,等价于将矩阵、张量打平成向量后计算,在 TensorFlow 中,可以通过 tf.norm(x, ord)求解张量的 L1, L2, ∞等范数,其中参数 ord 指定为 1,2 时计算 L1, L2 范数,指定为 np.inf 时计算 ∞ 范数。
x = tf.norm([2,2]) tf.norm(x, ord=1) tf.norm(x, ord=2) tf.norm(x, ord=np.inf)
-
最大最小值、均值、和
通过 tf.reduce_max, tf.reduce_min, tf.reduce_mean, tf.reduce_sum 可以求解张量在某个维 度上的最大、最小、均值、和,也可以求全局最大、最小、均值、和。
-
张量比较
为了计算分类任务的准确率等指标,一般需要将预测结果和真实标签比较,统计比较结果中正确的数量来就是计算准确率。
out = tf.random.normal([100,10]) out = tf.nn.softmax(out, axis=1) # 输出转换为概率 pred = tf.argmax(out, axis=1) # 选取预测值 # 真实标签 y = tf.random.uniform([100]) # 预测值与真实值比较(tf.equal返回的是布尔型的张量比较结果) out = tf.equal(pred,y) out = tf.cast(out, dtype=tf.float32) # 布尔型转换为int型 correct = tf.reduce_sum(out) # 统计True的个数
-
填充与复制
填充
对于图片数据的高和宽、序列信号的长度,维度长度可能各不相同。为了方便网络的并行计算,需要将不同长度的数据扩张为相同长度。通常做法是,在需要补充长度的信号开始或结束处填充足够数量的特定数值,如0。
填充的操作通过 tf.pad(x,paddings) 函数实现,paddings是包含了多个[𝐿𝑒𝑓𝑡 𝑃𝑎𝑑𝑑𝑖𝑛𝑔,𝑅𝑖𝑔ℎ𝑡 𝑃𝑎𝑑𝑑𝑖𝑛𝑔]的嵌套方案 List。
a = tf.constant([1,2,3,4,5,6]) b = tf.constant([7,8,1,6]) b = tf.pad(b, [[0,2]]) # [7,8,1,6,0,0] # 合并 tf.stack([a,b],axis=0) #[[1, 2, 3, 4, 5, 6], [7, 8, 1, 6, 0, 0]]
复制
通过 tf.tile 函数可以在任意维度将数据重复复制多份,如 shape 为[4,32,32,3]的数据, 复制方案 multiples=[2,3,3,1],即通道数据不复制,高宽方向分别复制 2 份,图片数再复制 1 份。
-
经典数据集加载
在 TensorFlow 中,keras.datasets 模块提供了常用经典数据集的自动下载、管理、加载与转换功能,并且提供了 tf.data.Dataset 数据集对象,方便实现多线程(Multi-thread),预处理(Preprocess),随机打散(Shuffle)和批训练(Train on batch)等常用数据集功能。
常用的一些数据集:
- Boston Housing 波士顿房价趋势数据集,用于回归模型训练与测试
- CIFAR10/100 真实图片数据集,用于图片分类任务
- MNIST 手写数字图片数据集,用于图片分类任务
- IMDB 情感分类任务数据集
import tensorflow as tf from tensorflow import keras from tensorflow.keras import datasets # 加载 MNIST 数据集 (60000, 28, 28)、(60000,)、(10000, 28, 28) (10000,) (x_train, y_train), (x_test, y_test) = datasets.minst.load_data() # 转换成 DataSet对象 train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)) # 随机打散(防止每次训练数据按固定顺序产生) train_db = train_db.shuffle(10000) # 批训练 train_db = train_db.batch(128) # 预处理(Dataset对象通过 map(func) 调用用户自定义的预处理函数) train_db = train_db.map(preprocess) def preprocess(x, y): # 标准化到 0~1 x = tf.cast(x, dtype=tf.flaot32) / 255 x = tf.reshape(x, [-1, 28*28]) # 打平 y = tf.cast(y, dtype=tf.int32) # one_hot 编码 y = tf.one_hot(y, depth=10) return x, y
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端