程序 = 数据结构+算法
TensorFlow程序 = 张量数据结构 + 计算图计算语言
张量和计算图是TensorFlow的核心概念。
TensorFlow的基本数据结构是张量tensor,张量即多维数组,类似于numpy中的array
常量 : contant 变量: Variable
常量的值在计算图中不可以被重新赋值,变量可以在计算图中用assign等算子重新赋值。
不同类型的数据可以用不同维度(rank)的张量来表示。
标量为0维张量,向量为1维张量,矩阵为2维张量。
彩色图像有rgb三个通道,可以表示为3维张量。
视频还有时间维,可以表示为4维张量。
可以简单地总结为:有几层中括号,就是多少维的张量
tf.int,tf.float.. tf.bool tf.string
tf.int64==np.int64
tf.bool == np.bool
tf.double == np.float64
tf.string != np.unicode
tf.convert_to_tensor(数据名,dtype=数据类型) 将numpy数据类型转换成Tensor数据类型
张量的操作主要包括张量的结构操作和张量的数学运算。
张量结构操作诸如:张量创建,索引切片,维度变换,合并分割。
张量数学运算主要有:标量运算,向量运算,矩阵运算。
张量运算的广播机制。
标量运算
张量的数学运算符可以分为标量运算符、向量运算符、以及矩阵运算符。
加减乘除乘方,以及三角函数,指数,对数等常见函数,逻辑比较运算符等都是标量运算符。
标量运算符的特点是对张量实施逐元素运算。
有些标量运算符对常用的数学运算符进行了重载。并且支持类似numpy的广播特性。
许多标量运算符都在 tf.math模块下
+ - * / exp,log ** pow square matmul Sqrt // %
向量运算
向量运算符只在一个特定轴上运算,将一个向量映射到一个标量或者另外一个向量。
许多向量运算符都以reduce开头。
reduce_mean reduce_max reduce_min reduce_sum
矩阵运算
矩阵必须是二维的。类似tf.constant([1,2,3])这样的不是矩阵。
矩阵运算包括:矩阵乘法,矩阵转置,矩阵逆,矩阵求迹,矩阵范数,矩阵行列式,矩阵求特征值,矩阵分解等运算。
除了一些常用的运算外,大部分和矩阵有关的运算都在tf.linalg子包中。
广播机制
TensorFlow的广播规则和numpy是一样的:
1、如果张量的维度不同,将维度较小的张量进行扩展,直到两个张量的维度都一样。
2、如果两个张量在某个维度上的长度是相同的,或者其中一个张量在该维度上的长度为1,那么我们就说这两个张量在该维度上是相容的。
3、如果两个张量在所有维度上都是相容的,它们就能使用广播。
4、广播之后,每个维度的长度将取两个张量在该维度长度的较大值。
5、在任何一个维度上,如果一个张量的长度为1,另一个张量长度大于1,那么在该维度上,就好像是对第一个张量进行了复制。
tf.test.is_gpu_available() 测试gpu能否运行
tf.cast(a,type) 可以改变张量的数据类型 强制类型转换
tf.shape() 查看尺寸
tf.range() 随机生成范围内的张量
tf.linspace() 创建等差张量
tf.zeros() 创建全为0 的张量
tf.ones() 创建全为1的张量
tf.fill() 全为指定值的张量
tf.random.normal() 生成正态分布随机数张量 默认均值为0,标准差1
tf.random.truncated_normal(维度,mean=均值,stddev=标准差)
tf.eye()
tf.random.uniform(维度,minval=最小值,maxval=最大值)
tf.reshape 可以改变张量的形状。
tf.squeeze 可以减少维度。
tf.expand_dims 可以增加维度。
tf.transpose 可以交换维度。可以交换张量的维度,与tf.reshape不同,它会改变张量元素的存储顺序。
tf.transpose常用于图片存储格式的变换上。
tf.argmax() 求向量最大值下标 可指定轴0每一列 1--每一行
tf.reduce_mean() 求矩阵向量平均值
tf.reduce_sum() 求元素的和,可按行按列
tf.reduce_min() 计算张量维度上元素的最小值
tf.reduce_max() 计算张量维度上元素的最大值
tf.convert_to_tensor(数据名,dtype=数据类型) 将numpy数据类型转换成Tensor数据类型
tf.Variable() 将变量标记为"可训练" 被表记的变量会在反向传播中记录梯度信息,神经网络中,常用该函数标记训练参数
tf.add() 两个张量相加
tf.subtract() 两个张量相减
tf.multiply() 两个张量相乘
tf.divide() 两个张量相除 (只有维度相同的两个张量才可以参与四则运算)
tf.square() 计算张量的平方
tf.pow(张量名,n次方数) 计算张量n次方
tf.sqrt(张量名) 对张量开方
tf.matmul(矩阵1,矩阵2) 矩阵乘法 == @
data = tf.data.Dataset.from_tensor_slices(输入特征,标签)切分传入张量的第一维度,生成输入特征/标签对,构建数据集
numpy和tensor格式都可用
tf.GradientTape with结构记录计算过程 gradient求出张量的梯度
with tf.GradientTape() as tape:
若干计算过程
grad = tape.gradient(函数,对谁求导)
enumerate 是python内键函数,可以遍历每个元素
tf.one_hot(待转换数据, depth=几分类) 独热编码,变为0,1 1是是,0是非
assign_sub() 自减 可自更新
tf.greater(x,y) 比较函数: 返回x>y的真值 y必须与 x 具有相同的类型.
tf.gather(params,indices,axis=0 ) 从params的axis维根据indices的参数值获取切片
tf.where(条件语句,真返回A,假返回B) eg:tf.where(tf.greater(2,4),2,4)
tf.matmul layers.Dense
tf.nn.conv2d layers.Conv2D
tf.nn.relu layers.SimpleRNN
tf.nn.max_pool2d layers.LSTM
tf.nn.signoid layers.ReLU
tf.nn.softmax 使n分类的n个输出符合概率分布,和为1 layers.MaxPool2D
np.random.RandomState.rand(维度) 返回一个[0,1]之间的随机数 维度为空返回标量
np.vstack(数组1,数组2) 两个数组按垂直方向叠加
np.mgrid[起始值,终止值,步长]
np.ravel() 变为一维数组
np.c_[] 返回间隔数值点配对
tf.keras.backend.clear_session 函数:
定义在:tensorflow/python/keras/backend.py
销毁当前的TF图并创建一个新图 有助于避免旧模型/图层混乱
tensorflow中tf.keras.models.Sequential()用法
Sequential()方法是一个容器,描述了神经网络的网络结构,在Sequential()的输入参数中描述从输入层到输出层的网络结构
model = tf.keras.models.Sequential([网络结构]) #描述各层网络
网络结构举例:
拉直层:tf.keras.layers.Flatten() #拉直层可以变换张量的尺寸,把输入特征拉直为一维数组,是不含计算参数的层
全连接层:tf.keras.layers.Dense(神经元个数,
activation = "激活函数“,
kernel_regularizer = "正则化方式)
其中:activation可选 relu 、softmax、 sigmoid、 tanh等
kernel_regularizer可选 tf.keras.regularizers.l1() 、tf.keras.regularizers.l2()
卷积层:tf.keras.layers.Conv2D(filter = 卷积核个数,
kernel_size = 卷积核尺寸,
strides = 卷积步长,
padding = ”valid“ or “same”)
LSTM层:tf.keras.layers.LSTM()
keras.layers.Dense(units, units:该层有几个神经元
activation=None, activation:该层使用的激活函数
use_bias=True, use_bias:是否添加偏置项
kernel_initializer=‘glorot_uniform’, kernel_initializer:权重初始化方法
bias_initializer=‘zeros’, bias_initializer:偏置值初始化方法
kernel_regularizer=None, kernel_regularizer:权重规范化函数
bias_regularizer=None, bias_regularizer:偏置值规范化方法
activity_regularizer=None, activity_regularizer:输出的规范化方法
kernel_constraint=None, kernel_constraint:权重变化限制函数
bias_constraint=None) bias_constraint:偏置值变化限制函数
dense 全连接层 相当于添加一个层
@tf.function 作用
将python的函数编译成tensorflow的图结构,所以可以方便的直接使用python的语法去写深度学习的一些函数代码
易于将模型导出为GraphDef+checkpoint和saveModel
使得eager exection默认打开。如果不使用@tf.function,虽然可以使用eager exection去写代码,但是模型的中间结果无法保存,所以无法进行预测
tf1.0的代码可以经过@tf.function修饰之后在tf2里面继续使用。
此时其功能就是tf1里面的session
空间复杂度:
层数 = 隐藏层+1个输出层
时间复杂度:
乘加运算次数
w = w - lr * θloss/θw
可以先用较大的学习率,快速得到较优解,然后逐步减小学习率,使模型在训练后期稳定
指数衰减学习率 = 初始学习率*学习率衰减率
sigmoid激活函数
tf.nn.sigmoid(x) f(x) = 1/1+e**(-x)
容易造成梯度消失
输入非0均值,收敛慢
幂运算复杂,训练时间长
Tanh激活函数
tf.math.tanh(x) f(x) = 1-e**(-2x)/1+e**(-2x)
输出是0均值
容易造成梯度消失
幂运算复杂,时间长
ReLU函数
tf.nn.relu(x) f(x) = max(x,0)
优点:解决梯度消失问题, 缺点:输入非0均值 速度慢
判断输入是否大于0,计算速度快 某些神经元可能永远不会被激活 (负数特征过多)
Leaky Relu函数
tf.nn.leaky_relu(x) f(x) = max(ax,x)
不会出现神经元死亡问题,但是实际中不常用
方法:1.均方误差 2.自定义 3.ce(cross Entropy)
均方误差: tf.reduce_mean(tf.square(y_-y))
自定义损失函数:
loss_zdy = tf.raduce_sum(tf.where(tf.greater(y,y_),COST(y-y_),PROFIT(y_-y))
交叉熵:Cross Entropy 两个概率分布之间的距离
tf.losses.categorical_crossentropy(y_,y) 交叉熵计算公式
tf.nn.softmax_cross_entroopy_with_logits(y_,y)输出先过softmax函数,再计算交叉熵
欠拟合解决:增加输入特征2,增加网格参数,3减少正则化参数
过拟合解决:1.数据清洗,2.增大训练集,3.采用正则化,4.增大正则化参数
loss(l1) = ∑|W| loss(l2) = ∑|W**2|
tf.nn.l2_loss() l2
L2正则化会使参数接近于0但不等于,通过减小参数值大小降低复杂度
L1正则化大概率会使很多参数变为0,因此通过稀疏参数,减少参数的数量,降低复杂度
待优化的参数w,损失函数loss,学习率lr,每次迭代一个batch,t表示当前batch迭代的总次数
1.计算时刻损失函数关于挡墙参数的梯度g = loss' = loss(w)''
2.计算t时刻一阶动量m和二阶动量V
3.计算t时刻下降梯度h(t) = lr * m/V**(1/2)
4.计算t+1时刻参数w(t+1) = w(t) - h(t)
SGD 随机梯度下降
m = g v = 1
h(t) = lr * m(t)/V**(1/2) = lr * g
w(t+1) = w(t) - h(t)=w(t) - lr * loss(w)'
w1.assign_sub(lr * grads[0])
SGDM 是在SGD基础上增加一阶动量