目录
知识树
1、张量与操作
Tensorflow使用一种叫tensor的数据结构去定义所有的数据,我们可以把tensor看成是n维的array或者list。在Tensorflow的各部分图形间流动传递的只是tensor;
编写TensorFlow程序时,操纵并传递的主要对象是tf.Tensor:
- 一个数据类型(例如float32,int32,或者string);
- 以及shape;
张量的维度有三种表示形式:
Rank | Shape | Dimension number | Example |
---|---|---|---|
0 | [] | 0-D | A 0-D tensor. A scalar |
1 | [D0] | 1-D | A 1-D tensor with shape[5] |
2 | [D0,D1] | 2-D | A 2-D tensor with shape[3,4] |
3 | [D0,D1,D2] | 3-D | A 3-D tensor with shape[1,4,3] |
n | [D0,D1,…,Dn-1] | n-D | A tensor with shape [D0,D1,…,Dn-1] |
如上图所示中的Rank、Shape、Dimension number都是用来表示张量的。
# Rank 0
mammal=tf.Variable("Elephant",tf.string) # 定义一个string类型的变量manmal,其变量值为Elephant,这是一个0阶张量
tf.print(tf.rank(mammal)) # 输出 0
tf.print(tf.shape(mammal)) # 输出 []
#Rank 1
mystr=tf.Variable(["Hello"],tf.string)
tf.print(tf.rank(mystr)) # 输出 1
tf.print(tf.shape(mystr)) # 输出 [1]
#Rank 2
mymat=tf.Variable([[7],[11]],tf.int16)
tf.print(tf.rank(mymat)) # 输出 2
tf.print(tf.shape(mymat)) # 输出 [2 1]
1.1 Numpy和tensorflow中的张量对比
# 创建张量
tf.constant([1,2,3],dtype=tf.int16)
tf.zeros((2,2),dtype=tf.int16)
#reshape
rank_three_tensor=tf.ones([3,4,5])
matrix=tf.reshape(rank_three_tensor,[6,10])
print(tf.shape(matrix))
yet_another=tf.reshape(rank_three_tensor,[8, 10])#报错
1.2 张量操作
- tf.strings(常用于推荐算法场景、NLP场景)
- tf.debugging
- tf.dtypes
- tf.math
- tf.random
- tf.feature_column
推荐看这些网站学习tensorflow的一些基础知识:
- https://lyhue1991.github.io/eat_tensorflow2_in_30_days/
- https://zh.d2l.ai/
- https://www.tensorflow.org/api/r2.0
- https://tf.wiki/zh_hans/
1.2.1 tf.string
#字符切割
tf.strings.bytes_split('hello')
#单词切割
tf.strings.split('hello world')
#string hash 哈希处理
tf.strings.to_hash_bucket(['hello','world'], num_buckets=10)
1.2.2 tf.debugging
#tf自带debug函数
a=tf.random.uniform((10,10))
tf.debugging.assert_equal(x=a.shape,y=(10,10))
#错误示范
tf.debugging.assert_equal(x=a.shape,y=(20,10))
1.2.3 tf.random
a = tf.random.uniform(shape=(10,5),minval=0,maxval=10)
a
1.2.4 tf.math
a = tf.constant([[1,2],[3,4]])
b = tf.constant([[5,6],[7,8]])
tf.print(tf.math.add(a,b))
tf.print(tf.math.subtract(a,b))
tf.print(tf.math.multiply(a,b))
tf.print(tf.math.divide(a,b))
1.2.5 tf.dtypes
改变数据的属性:
x =tf.constant([1.8,2.2],dtype=tf.float32)
x1=tf.dtypes.cast(x,tf.int32)
x1
2、常用层
- tf.keras.layers:如果说tf.nn是轮子,那么tf.keras.layers可以说是汽车,tf.keras.layers是基于tf.nn的高度封装;
- tf.nn:低层的函数库,其它各种库可以说都是基于这个低层库来进行扩展的;
在大多数情况下,可以使用tensorflow封装的tf.keras.layers构建的一些层建模,keras层是非常有用的;
可以在文档中查看预先存在的层的完整列表,它包括Dense、Conv2D、LSTM、BatchNormalization、Dropout等;
下面演示一下怎么构建一个模型:
#文本分类
a = tf.random.uniform(shape = (10,100,50),minval=-0.5,maxval=0.5) #张量,[batch_size,length_size,embed_size]
x = tf.keras.layers.LSTM(100)(a) #LSTM
x = tf.keras.layers.Dense(10)(x) #全连接层
x = tf.nn.softmax(x) #激活函数
添加层的配置参数
# 层中增加激活函数
tf.keras.layers.Dense(64, activation='relu')
# 或者另外一种方式
tf.keras.layers.Dense(64, activation=tf.nn.relu)
# 将L1正则化系数为0.01的线性层应用于内核矩阵
tf.keras.layers.Dense(64, kernel_regularizer=tf.keras.regularizers.l1(0.01))
# 将L2正则化系数为0.01的线性层应用于偏差向量:
tf.keras.layers.Dense(64, bias_regularizer=tf.keras.regularizers.l2(0.01))
# 内核初始化为随机正交矩阵的线性层:
tf.keras.layers.Dense(64, kernel_initializer='orthogonal')
# 偏差向量初始化为2.0的线性层:
tf.keras.layers.Dense(64, bias_initializer=tf.keras.initializers.Constant(2.0))
3、三种建模方式
- Sequential model(顺序模型)
- Function model(函数模型)
- Subclassing model(子类化模型)
3.1 Sequential方式构建模型——tf.keras.Sequential
第一种构建Sequential模型的方法:
import tensorflow as tf
from tensorflow.keras import layers
model = tf.keras.Sequential()
model.add(layers.Dense(64, activation='relu')) # 第一层
model.add(layers.Dense(64, activation='relu')) # 第二层
model.add(layers.Dense(10)) # 第三层
第二种构建Sequential模型的方法:
model = tf.keras.Sequential([
layers.Dense(64, activation='relu', input_shape=(32,)), # 第一层
layers.Dense(64, activation='relu'), # 第二层
layers.Dense(10) # 第三层
])
简单建立一个模型跑一下:
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers
model = tf.keras.Sequential()
model.add(layers.Dense(64, activation='relu')) # 第一层
model.add(layers.Dense(64, activation='relu')) # 第二层
model.add(layers.Dense(10)) # 第三层
# 定义优化器、损失函数
model.compile(optimizer=tf.keras.optimizers.Adam(0.01),
loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
# 生成数据和对应的标签
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))
# 模型训练
model.fit(data, labels, epochs=10, batch_size=32)
tf.keras.Model.fit (用于模型训练)
- epochs:训练分为几个时期。每一个epoch是对整个输入数据的一次迭代(此操作以较小的批次完成)。
- batch_size:当传递NumPy数据时,模型将数据切成较小的批次,并在训练期间对这些批次进行迭代。该整数指定每个批次的大小。请注意,如果不能将样本总数除以批次大小,则最后一批可能会更小。
- validation_data:在模型训练时,监控在某些验证数据上监视其性能。传递此参数(输入和标签的元组)可以使模型在每个时期结束时以推断模式显示所传递数据的损失和度量。
3.2 Function model(函数模型)
函数式模型是一种创建模型的方法,该模型比tf.keras.Sequential更灵活。函数式模型可以处理具有非线性拓扑的模型,具有共享层的模型以及具有多个输入或输出的模型等等;
深度学习模型通常是层的有向无环图(DAG)的主要思想。因此,函数式模型是一种构建层图的方法。
上面介绍的顺序模型比较简单,当模型是多输入模型或者是多输出模型,具有共享图层(同一图层被调用多次)的模型,就得使用函数式模型了;搭建好函数式模型之后,训练模型的方式和tf.keras.Sequential一样;
通过代码观察一下:
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers
inputs = tf.keras.Input(shape=(32,))
x = layers.Dense(64, activation='relu')(inputs) #第一层
x = layers.Dense(64, activation='relu')(x) #第二层
predictions = layers.Dense(10)(x) #第三层
model = tf.keras.Model(inputs=inputs, outputs=predictions)
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))
model.fit(data, labels, batch_size=32, epochs=5)
当遇到需要多个输入的模型时,可以采用以下的函数式方法搭建模型:
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers
inputs1 = tf.keras.Input(shape=(32,)) # 输入1
inputs2 = tf.keras.Input(shape=(32,)) # 输入2
x1 = layers.Dense(64, activation='relu')(inputs1) # 第一层
x2 = layers.Dense(64, activation='relu')(inputs2) # 第一层
x = tf.concat([x1,x2],axis=-1) # 张量拼接
x = layers.Dense(64, activation='relu')(x) # 第二层
predictions = layers.Dense(10)(x) # 第三层
model = tf.keras.Model(inputs=[inputs1,inputs2], outputs=predictions)
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
data1 = np.random.random((1000, 32))
data2 = np.random.random((1000, 32))
labels = np.random.random((1000, 10))
model.fit((data1,data2), labels, batch_size=32, epochs=5)
3.3 Subclassing model(子类化模型)
- 通过子类化tf.keras.Model和定义自己的前向传播模型来构建完全可定制的模型;
- 和eager execution模式相辅相成;
通过代码演示一下:
import numpy as np
import tensorflow as tf
class MyModel(tf.keras.Model):
def __init__(self, num_classes=10):
super(MyModel, self).__init__(name='my_model')
self.num_classes = num_classes
# 定义自己需要的层
self.dense_1 = layers.Dense(32, activation='relu') #
self.dense_2 = layers.Dense(num_classes)
def call(self, inputs):
#定义前向传播
# 使用在 (in `__init__`)定义的层
x = self.dense_1(inputs)
x = self.dense_2(x)
return x
model = MyModel(num_classes=10)
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001), # 定义优化器
loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True), # 定义损失函数
metrics=['accuracy'] # 定义评价指标)
data = np.random.random((1000, 32))
labels = np.random.random((1000, 10))
# Trains for 5 epochs.
model.fit(data, labels, batch_size=32, epochs=5)
3.4 三种构建模型的区别
模型 | 使用场景 |
---|---|
Sequential model | 对于顺序结构的模型,优先使用Sequential方法构建 |
Functional model | 如果模型有多输入或者多输出,或者模型需要共享权重,或者模型具有残差链接等非顺序结构,推荐使用函数式API进行创建 |
Subclassing model | 需要自定义层之间的传输、复杂模型 |
4、参考资源
深度之眼课程 —— 《深度学习TensorFlow2.0框架项目班》