• Tensorflow练习


    模型保存

    Keras接口的模型保存

    model.save("xxx.h5")  # 保存模型结构和权重
    model.to_json()  # 保存模型结构
    
    # 加载
    model.load_model('xxx.h5')
    models.model_from_json()  # json
    model.load_weights()  # json
    

    tensorflow接口的模型保存

    model.save('tf_model_savedmodel', save_format="tf")  # 保存模型和结构
    model.save_weights('./data/tf_model_weights.ckpt',save_format = "tf")  # 仅保存权重
    
    # 加载
    tf.keras.models.load_model('tf_model_savedmodel')  # 
    

    数据加载

    数据加载是将其他类型的数据转换为tf.data.Dataset类型。

    最简单的数据加载在方式是从list中加载,tf.data.Dataset.list_files()可以从一系列满足正则条件的文件中(如图片)加载数据。

    Dataset支持的操作

    • Transformations. Dataset.mapDataset.apply
    • Batch. Dataset.batch
    • Cache. 当迭代完成后,会缓存在内存或者文件中,后续的迭代会使用缓存的数据
    • Concatenate. 将两个Dataset类型concatenate,两者必须有相同的数据类型,返回新对象。
    • Filter
    • From_generator
    • Reduce
    • Shuffle
    • Zip
    • unbatch
    • take

    图片数据加载

    可以使用tf.data.Dataset.list_files()读取一系列照片路径,再配合tf.image类进行读取预处理。

    文本数据加载

    使用tf.data.TextLineDataset()对一系列文件路径进行每行文本读取,使用map等函数进行处理。

    数据处理

    特征列

    特征列可以将类别特征转换为one-hot编码特征,将连续特征构建分桶特征,以及对多个特征生成交叉特征。

    • numeric_column
    • bucketized_column
    • categorical_column_with_identity
    • categorical_column_with_vocabulary_list
    • categorical_column_with_vocabulary_file
    • categorical_column_with_hash_bucket
    • indicator_column
    • embedding_column
    • crossed_column

    定义完特征列后通过tf.keras.layers.DenseFeatures将数据进行特征处理。

    图片数据处理

    可以使用tf.data.Dataset.list_files()读取一系列照片路径,然后使用map函数对其进行处理,如tf.io.read_filetf.image.decode_jpeg(img)tf.image.resize.

    tf.image支持的操作

    • crop
    • crop_and_resize
    • crop_to_bounding_box
    • resize

    也可以使用tf.keras.preprocessing.image中的ImageDataGenerator方法从文件中读取一些列照片。

    文本数据处理

    Tensorflow中文本的处理需要使用到tf.keras.preprocessing中的Tokenizen词典和tf.keras.utils.Sequence构建文本数据生成管道,并结合tf.keras.layers.experimental.preprocessing.TextVectorization进行处理。

    tf.strings中的处理操作

    • lower
    • regex_replace

    tf.keras.layers.experimental.preprocess.TextVectorization进行处理,arg

    • max_token
    • standardize
    • split
    • ngrams
    • output_mode
    • pad_to_max_token

    使用方法

    • adapt,拟合数据
    • get_vocabulary(),得到词典

    张量

    张量数据结构

    张量可以分为常量和变量两类。常量值不可以改变,变量的值可一改变,可以使用assignassign_addassign_sub方法。

    结构操作

    • 创建

      rangelinspacezerosoneszeros_likefilluniformnormaltruncated_normal

    • 切片

      gathergather_ndtf.wherescatter_nd

    • 维度变化

      tf.reshapetf.squeezetf.expand_dimstf.transposetf.reshape

    • 合并和分割

      tf.splittf.stacktf.concat

    数学运算

    • 标量运算

      tf.clip_by_valuetf.clip_by_norm

    • 向量运算

      reduce_meanreduce_sumreduce_maxreduce_prodtf.math.cumsumtf.math.cumprod

      tf.argmaxtf.math.top_k

    • 矩阵运算

      tf.matmultf.transposetf.linalg.invtf.linalg.tracetf.linalg.norm

    求导

    张量的求导需要增加tape.watch()

    optimizers.minimize() == loss.gradient, optimizers.apply_gradient

    AutoGraph使用规范

    AutoGraph是将eager转换为静态图,在函数前加入@t f.function修饰

    • 被@tf.function修饰的函数应尽可能使用TensorFlow中的函数而不是Python中的其他函数
    • 避免在@tf.function修饰的函数内部定义tf.Variable
    • 被@tf.function修饰的函数不可修改该函数外部的Python列表或字典等数据结构变量

    AutoGraph的机制原理

    执行步骤

    • 创建计算图
    • 执行计算图

    当计算图已经创建时,不会在执行非计算图中的部分。如果调用被@tf.function装饰的函数时输入的参数不是Tensor类型,则每次都会重新创建计算图。

    tf.Module

    因为tf.function修饰的函数中不宜包含新建的变量,但是修改提前定义的变量显得封装不完美,解决方案是利用tf.Module封装。

    class DemoModule(tf.Module):
        def __init__(self,init_value = tf.constant(0.0),name=None):
            super(DemoModule, self).__init__(name=name)
            with self.name_scope:  #相当于with tf.name_scope("demo_module")
                self.x = tf.Variable(init_value,dtype = tf.float32,trainable=True)
    
         
        @tf.function(input_signature=[tf.TensorSpec(shape = [], dtype = tf.float32)])  
        def addprint(self,a):
            with self.name_scope:
                self.x.assign_add(a)
                tf.print(self.x)
                return(self.x)
    

    网络构建

    定义模型层

    继承tf.keras.layers.Layer类,需要实现初始化,buildcall方法。

    build定义Layer需要被训练的参数。

    def build(self, input_shape): 
        self.w = self.add_weight("w",shape=(input_shape[-1], self.units), initializer='random_normal',trainable=True) #注意必须要有参数名称"w",否则会报错
        self.b = self.add_weight("b",shape=(self.units,), initializer='random_normal', trainable=True)
        super(Linear,self).build(input_shape) # 相当于设置self.built = True
    def get_config(self):  
        config = super(Linear, self).get_config()
        config.update({'units': self.units})
        return config
    

    定义模型

    继承tf.keras.models.Model类,实现初始化,buildcall方法,build中设置需要学习的参数(网络层)

    class ImdbModel(models.Model):
        def __init__(self):
            super(ImdbModel, self).__init__()
            
        def build(self,input_shape):
            self.embedding = layers.Embedding(MAX_WORDS,7)
            self.block1 = ResBlock(7)
            self.block2 = ResBlock(5)
            self.dense = layers.Dense(1,activation = "sigmoid")
            super(ImdbModel,self).build(input_shape)
        
        def call(self, x):
            x = self.embedding(x)
            x = self.block1(x)
            x = self.block2(x)
            x = layers.Flatten()(x)
            x = self.dense(x)
            return(x)
    

    定义损失函数

    损失函数接收两个张量y_turey_pred并输出一个标量作为损失函数值。可以继承与tf.keras.losses.Loss类,要实现初始化和call方法。

    # wrap up
    def focal_loss(alpha, gamma):
        def focal_loss_fixed(y_true,· y_pred):
            pt_1 = tf.where(tf.euqal(y_true, 1), y_pred, tf.ones_like(y_pred))
            pt_0 = tf.where(tf.euqal(y_true, 0), y_pred, tf.zeros_like(y_pred))
            loss = -tf.reduce_sum(alpha * tf.power(1. - pt_1, gamma) * tf.log(1e-07+pt_1)) - tf.reduce_sum((1-alpha) * tf.pow( pt_0, gamma) * tf.log(1. - pt_0 + 1e-07))
           	return loss
        return focal_loss_fixed
    
    # Class
    class FocalLoss(losses.Loss):
        
        def __init__(self,gamma=2.0,alpha=0.25):
            self.gamma = gamma
            self.alpha = alpha
    
        def call(self,y_true,y_pred):
            
            pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))
            pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))
            loss = -tf.reduce_sum(self.alpha * tf.pow(1. - pt_1, self.gamma) * tf.log(1e-07+pt_1)) 
               -tf.reduce_sum((1-self.alpha) * tf.pow( pt_0, self.gamma) * tf.log(1. - pt_0 + 1e-07))
            return loss
    

    评估指标

    与损失函数相同,评估指标需要接收两个张量y_true,y_pred作为输入参数,并输出一个标量作为评估值。用自定义类的方式实现需要继承tf.keras.metrics.Metric

    class KS(metrics.Metric):
        
        def __init__(self, name = "ks", **kwargs):
            super(KS,self).__init__(name=name,**kwargs)
            self.true_positives = self.add_weight(
                name = "tp",shape = (101,), initializer = "zeros")
            self.false_positives = self.add_weight(
                name = "fp",shape = (101,), initializer = "zeros")
       
        @tf.function
        def update_state(self,y_true,y_pred):
            y_true = tf.cast(tf.reshape(y_true,(-1,)),tf.bool)
            y_pred = tf.cast(100*tf.reshape(y_pred,(-1,)),tf.int32)
            
            for i in tf.range(0,tf.shape(y_true)[0]):
                if y_true[i]:
                    self.true_positives[y_pred[i]].assign(
                        self.true_positives[y_pred[i]]+1.0)
                else:
                    self.false_positives[y_pred[i]].assign(
                        self.false_positives[y_pred[i]]+1.0)
            return (self.true_positives,self.false_positives)
        
        @tf.function
        def result(self):
            cum_positive_ratio = tf.truediv(
                tf.cumsum(self.true_positives),tf.reduce_sum(self.true_positives))
            cum_negative_ratio = tf.truediv(
                tf.cumsum(self.false_positives),tf.reduce_sum(self.false_positives))
            ks_value = tf.reduce_max(tf.abs(cum_positive_ratio - cum_negative_ratio)) 
            return ks_value
    

    回调函数

    tf.keras的回调函数实际上是一个类,一般是在model.fit时作为参数指定,用于控制在训练过程开始或者在训练过程结束,在每个epoch训练开始或者训练结束,在每个batch训练开始或者训练结束时执行一些操作,例如收集一些日志信息,改变学习率等超参数,提前终止训练过程等等。

    所有回调函数都继承至keras.callbacks.Callbacks基类,拥有paramsmodel这两个属性。其中params 是一个dict,记录了训练相关参数 (例如 verbosity, batch size, number of epochs 等等)。model即当前关联的模型的引用。

    • BaseLogger。 收集每个epoch上metrics在各个batch上的平均值
    • History。将BaseLogger计算的各个epoch的metrics结果记录到history这个dict变量中,并作为model.fit的返回值。该回调函数被所有模型默认添加,在BaseLogger之后被添加。
    • EarlyStopping。 当被监控指标在设定的若干个epoch后没有提升,则提前终止训练。
    • ModelCheckpoint。在每个epoch后保存模型。
    • ReduceLROnPlateau。如果监控指标在设定的若干个epoch后没有提升,则以一定的因子减少学习率。
    • TerminateOnNaN。如果遇到loss为NaN,提前终止训练。
    • LearningRateScheduler。学习率控制器。给定学习率lr和epoch的函数关系,根据该函数关系在每个epoch前调整学习率。

    GPU设置

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

    参考资料

    1. lyhue1991, eat_tensorflow2_in_30_days
    2. TF API查询
  • 相关阅读:
    java private修饰的类和变量
    Volatile和Synchronized对可见性和原子性的支持
    Socket套接字
    Spring MVC请求执行流程
    Spring AOP术语解释
    equals()和==的区别
    约瑟夫环之递归算法
    数据库特性之原子性和一致性
    设计模式之单例模式
    平衡二叉树的插入旋转
  • 原文地址:https://www.cnblogs.com/DemonHunter/p/12971203.html
Copyright © 2020-2023  润新知