Skip to content

Latest commit

 

History

History

tensorflow2.x

tf2学习

版本tensorflow2.2.0 学习github网址

目录

安装

docker pull binzhouchn/tensorflow:2.2.0-cuda10.1-cudnn7

tf2基础笔记

tf2 basic

  • 自变量转换成tf.float32
  • Tensorflow一般使用梯度磁带tf.GradientTape来记录正向运算过程,然后反播磁带自动得到梯度值
  • 利用梯度磁带和优化器求最小值
  • 取切片数据
  • 矩阵乘法
  • tf2低阶api-张量的结构操作(维度变换、合并分割)
  • 如果调用被@tf.function装饰的函数时输入的参数不是Tensor类型,则每次都会重新创建计算图。因此,一般建议调用@tf.function时应传入Tensor类型
  • 查看模型文件相关信息,红框标出来的输出信息在模型部署和跨平台使用时有可能会用到
  • 数据管道Dataset
  • tf.keras.layers内置了非常丰富的各种功能的模型层
  • 训练模型的3种方法
  • 查看是否有GPU及相关设置

基于AI的信道信息反馈性能提升(自定义metrics和callback)

mnist_demo

用tf.keras构建自己的网络层

保持序列模型和函数模型

结构化数据分类(一般csv文件数据特征处理)

mlp及深度学习常见技巧

使用低级api训练(非tf.keras)

GAN

Transformer

tensorflow serving模型部署


basic

1. 自变量转换成tf.float32

x = tf.cast(x, tf.float32)

2. Tensorflow一般使用梯度磁带tf.GradientTape来记录正向运算过程,然后反播磁带自动得到梯度值

# 一阶导
x = tf.Variable(0.0,name = "x",dtype = tf.float32)
with tf.GradientTape() as tape:
    y = a*tf.pow(x,2) + b*x + c
tape.gradient(y,x)

# 二阶导
with tf.GradientTape() as tape2:
    with tf.GradientTape() as tape1:   
        y = a*tf.pow(x,2) + b*x + c
    dy_dx = tape1.gradient(y,x)   
dy2_dx2 = tape2.gradient(dy_dx,x)

3. 利用梯度磁带和优化器求最小值

自动微分详见

# 求f(x) = a*x**2 + b*x + c的最小值
# 使用optimizer.apply_gradients

x = tf.Variable(0.0,name = "x",dtype = tf.float32)
a = tf.constant(1.0)
b = tf.constant(-2.0)
c = tf.constant(1.0)

optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
for _ in range(1000):
    with tf.GradientTape() as tape:
        y = a*tf.pow(x,2) + b*x + c
    dy_dx = tape.gradient(y,x)
    optimizer.apply_gradients(grads_and_vars=[(dy_dx,x)])
    
tf.print("y =",y,"; x =",x)

4. 取切片数据

x = tf.Variable([1,2,3,4,5,6])
slice_idx = tf.constant([0,3,5])
tf.gather(x, slice_idx)
#得到<tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 4, 6], dtype=int32)>

5. 矩阵乘法

用tf.matmul或者@

6. tf2低阶api - 张量的结构操作

  • 6.1 维度变换

tf.reshape 可以改变张量的形状
tf.squeeze 可以减少维度
tf.expand_dims 可以增加维度
tf.transpose 可以交换维度,比如tf.transpose(x,perm=[0,2,1])

  • 6.2 合并分割

4.1 tf.concat和tf.stack有略微的区别,tf.concat是连接,不会增加维度,而tf.stack是堆叠,会增加维度
4.2 tf.split是tf.concat的逆运算,可以指定分割份数平均分割,也可以通过指定每份的记录数量进行分割。tf.split(c,3,axis = 0) #指定分割份数,平均分割

链接,和numpy很类似

7. 如果调用被@tf.function装饰的函数时输入的参数不是Tensor类型,则每次都会重新创建计算图。因此,一般建议调用@tf.function时应传入Tensor类型

8. 查看模型文件相关信息,红框标出来的输出信息在模型部署和跨平台使用时有可能会用到

!saved_model_cli show --dir ./data/demo/1 --all

9. 数据管道Dataset

不同方法构建数据管道及提升管道性能

/构建/

  • 1,从Numpy array构建数据管道
  • 2,从 Pandas DataFrame构建数据管道
  • 3,从Python generator构建数据管道
  • 4,从csv文件构建数据管道
  • 5,从文本文件构建数据管道
  • 6,从文件路径构建数据管道
  • 7,从tfrecords文件构建数据管道

/加速/

  • 1,使用 prefetch 方法让数据准备和参数迭代两个过程相互并行
  • 2,使用 interleave 方法可以让数据读取过程多进程执行,并将不同来源数据夹在一起
  • 3,使用 map 时设置num_parallel_calls 让数据转换过程多进行执行
  • 4,使用 cache 方法让数据在第一个epoch后缓存到内存中,仅限于数据集不大情形
  • 5,使用 map转换时,先batch, 然后采用向量化的转换方法对每个batch进行转换

10. tf.keras.layers内置了非常丰富的各种功能的模型层

  • layers.Dense
  • layers.Flatten
  • layers.Input
  • layers.DenseFeature
  • layers.Dropout
  • layers.Conv2D
  • layers.MaxPooling2D
  • layers.Conv1D
  • layers.Embedding
  • layers.GRU
  • layers.LSTM
  • layers.Bidirectional

如果这些内置模型层不能够满足需求,我们也可以通过编写tf.keras.Lambda匿名模型层或继承tf.keras.layers.Layer基类构建自定义的模型层。

其中tf.keras.Lambda匿名模型层只适用于构造没有学习参数的模型层。

11. 训练模型的3种方法

6-2,训练模型的3种方法

12. 查看是否有GPU及相关设置

gpus = tf.config.experimental.list_physical_devices('GPU')

if gpus:
    gpu2 = gpus[2] #如果有多个GPU,仅使用第3个GPU
    tf.config.experimental.set_memory_growth(gpu2, True) #设置GPU显存用量按需使用,可以不需要这行
    # 或者也可以设置GPU显存为固定使用量(例如:4G)
    #tf.config.experimental.set_virtual_device_configuration(gpu0,
    #    [tf.config.experimental.VirtualDeviceConfiguration(memory_limit=4096)]) 
    tf.config.experimental.set_visible_devices(gpu2, 'GPU') #GPU='2'即用第三个GPU

还有一种方法

import os
gpu_list = '0,1'
os.environ['CUDA_VISIBLE_DEVICES'] = gpu_list

使用多GPU训练模型,待补充

基于ai的信道信息反馈性能提升

代码在基于AI的信道信息反馈性能提升文件夹中,其中modelDesign.py文件中用model.fit跑模型的时候自定义metrics和callback

#自定义metrics
class NMSE_tf(keras.metrics.Metric):
    def __init__(self, name="nmse", **kwargs):
        super(NMSE_tf, self).__init__(name=name, **kwargs)
        self.totalLoss = self.add_weight(name="totalLoss", initializer="zeros")
        self.totalCount = self.add_weight(name="totalCount", dtype=tf.int32, initializer="zeros")
    def update_state(self, y_true, y_pred):
        x_real = tf.reshape(y_true[:, :, :, 0], (tf.shape(y_true)[0], -1))-0.5
        x_imag = tf.reshape(y_true[:, :, :, 1], (tf.shape(y_true)[0], -1))-0.5
        x_hat_real = tf.reshape(y_pred[:, :, :, 0], (tf.shape(y_pred)[0], -1))-0.5
        x_hat_imag = tf.reshape(y_pred[:, :, :, 1], (tf.shape(y_pred)[0], -1))-0.5
        power = tf.reduce_sum(x_real ** 2 + x_imag ** 2, axis=1)
        mse = tf.reduce_sum((x_real - x_hat_real) ** 2 + (x_imag - x_hat_imag) ** 2, axis=1)
        nmse = tf.reduce_sum(mse / power)
        self.totalCount.assign_add(tf.shape(y_true)[0])
        self.totalLoss.assign_add(nmse)
    def result(self):
        return self.totalLoss / tf.cast(self.totalCount, tf.float32)#必须要转化成一样的类型才能相除
    def reset_states(self):
        # The state of the metric will be reset at the start of each epoch.
        self.totalLoss.assign(0.0)
        self.totalCount.assign(0)
#自定义callback用于评估与保存
class CheckPointer(keras.callbacks.Callback):
    """自定义评估与保存
    """
    def __init__(self, valid_generator):
        self.valid_generator = valid_generator
        self.best_val_nmse = 0.55
    def evaluate(self, data):
        y_true = data #autoencoder中y_true就是输入数据
        y_pred = autoencoderModel.predict(y_true, batch_size=512)
        res = NMSE(y_true, y_pred)
        return res
    def on_epoch_end(self, epoch, logs=None):
        val_nmse = self.evaluate(self.valid_generator)
        if val_nmse < self.best_val_nmse:
            self.best_val_nmse = val_nmse
            # Encoder Saving
            encModel.save('./modelSubmit/encoder.h5')
            # Decoder Saving
            decModel.save('./modelSubmit/decoder.h5')
            print("tf model saved!")
        print('\nval NMSE = ' + np.str(val_nmse))

mnist_demo

见代码mnist_demo.py

用tf_keras构建自己的网络层

见代码myLayer.py

保持序列模型和函数模型

1.1 保存模型参数(推荐)

# 保存
model.save_weights('my_model_weights', save_format='tf')
# 读取
new_model = get_model() # 之前设计好的模型结构
new_model.compile(loss='sparse_categorical_crossentropy',
                  optimizer=keras.optimizers.RMSprop())
new_model.load_weights('my_model_weights')

#保存成h5模型例子看AI信道信息代码

1.2 保持全模型(子类模型的结构无法保存和序列化,只能保持参数)
可以对整个模型进行保存,其保持的内容包括:

  • 该模型的架构
  • 模型的权重(在训练期间学到的)
  • 模型的训练配置(你传递给编译的),如果有的话
  • 优化器及其状态(如果有的话)(这使您可以从中断的地方重新启动训练)
import numpy as np
model.save('the_save_model.h5')
new_model = keras.models.load_model('the_save_model.h5')
new_prediction = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_prediction, atol=1e-6) # 预测结果一样

结构化数据分类

分类
回归

见代码5.csv_binary_classify.py

mlp及深度学习常见技巧

以mlp为基础模型,然后介绍一些深度学习常见技巧, 如: 权重初始化, 激活函数, 优化器, 批规范化, dropout,模型集成

使用低级api训练

使用Tensor, Variable和GradientTape这些简单的要是,就可以构建一个简单的模型。步骤如下:

链接

见代码6.low_api_demo.py

gan

链接

见代码files/002-DCGAN.ipynb

transformer

这篇讲的确实详细非常好

已讲网页保存至files,还有001-Transformer.ipynb也在files中

tensorflow_serving

使用tensorflow-serving部署模型

保存:linear_model/1/下有三个文件;并启动服务

# docker pull tensorflow/serving
# cd到linear_model文件夹的上一层目录,然后运行如下命令
docker run -t --rm -p 8501:8501 \
    -v $PWD/linear_model:/models/linear_model\
    -e MODEL_NAME=linear_model \
    tensorflow/serving & >server.log 2>&1

shell调用

curl -d '{"instances": [[1.0, 2.0], [5.0,7.0]]}' -X POST http://localhost:8501/v1/models/linear_model:predict

python调用

import json,requests
data = json.dumps({"signature_name": "serving_default", "instances": [[1.0, 2.0], [5.0,7.0]]})
headers = {"content-type": "application/json"}
json_response = requests.post('http://localhost:8501/v1/models/linear_model:predict', data=data, headers=headers)
predictions = json.loads(json_response.text)["predictions"]
print(predictions)

15. tf-serving多模型部署

15.1 模型放置的目录结构如下:

其中models.config文件写法如下:

model_config_list: {
  config: {
    name: "ner_model",
    base_path: "/models/multimodel/ner_model/",
    model_platform: "tensorflow"
  },
  config: {
    name: "linear_model",
    base_path: "/models/multimodel/linear_model/",
    model_platform: "tensorflow"
  }
}

15.2 启动docker

# cd到multimodel文件夹的上一层目录,然后运行如下命令
docker run -t --rm -p 8501:8501 -v $PWD/multimodel:/models/multimodel tensorflow/serving --model_config_file=/models/multimodel/models.config --model_config_file_poll_wait_seconds=60 & >server.log 2>&1

15.3 调用方法和之前一样,调用不同的模型只要把:predict前面的模型换成想要用的模型名即可

建模

文本数据建模流程范例

使用spark-scala调用tensorflow2.0训练好的模型