• (三)tensorflow2.0


    前文分别讲了tensorflow2.0中自定义Layer和自定义Model,本文将来讨论如何自定义损失函数。

    (一)tensorflow2.0 - 自定义layer
    (二)tensorflow2.0 - 自定义Model
    (三)tensorflow2.0 - 自定义loss function(损失函数)
    (四)tensorflow2.0 - 实战稀疏自动编码器SAE


    自定义损失函数有两种情况,一种比较简单,而另一种稍显复杂。
    先来讨论第一种简单的情况,即不需要额外的参数。
    什么叫额外的参数呢?损失函数有两个默认参数,分别为实际输出、预测输出,如果损失函数只需要这两个参数,那么设计起来就很方便。

    # 定义损失函数
    def custom_loss(y_actual,y_pred):
        custom_loss= (y_actual-y_pred)**2
        return custom_loss
    
    # 使用该loss function
    model.compile(loss=custom_loss, optimizer=...)
    

    这种情况下,y_actualy_pred的值会自动传入该损失函数中,无需操心,这种实现也比较简单。

    第二种情况,损失函数需要额外的参数,即损失函数需要的数据不止是预测值和真实值这么简单,比如我要添加一个权重的惩罚项以防权重过大,这时上面方法就行不通了。

    这种情况没办法,只能自己自行设计模型运行流程了。

    class SAEModel(Model):
        # 可以传入一些超参数,用以动态构建模型
        # __init__()方法在创建模型对象时被调用
        def __init__(self, input_shape, hidden_shape=None):
            # 隐藏层节点个数默认为输入层的3倍
            if hidden_shape == None:
                hidden_shape = 3 * input_shape
            # 调用父类__init__()方法
            super(SAEModel, self).__init__()
            
            self.layer_1 = SAELayer(hidden_shape)
            self.layer_2 = layers.Dense(input_shape, activation=tf.nn.sigmoid)
    
        def call(self, input_tensor, training=False):
            # 输入数据
            hidden = self.layer_1(input_tensor)
            output = self.layer_2(hidden)
            return output
        
        # 计算损失值
        def get_loss(self, input_tensor):
            hidden = self.layer_1(input_tensor)
            output = self.layer_2(hidden)
            
            # 计算loss
            # 计算MSE
            mse = (1 / 2) * tf.reduce_sum(kb.square(input_tensor - output))
            # 计算权重乘法项
            alpha = 0.1
            W1 = self.layer_1.kernel
            W2 = self.layer_2.kernel
            weightPunish = (alpha / 2) * (tf.reduce_sum(kb.square(W1)) + tf.reduce_sum(kb.square(W2)))
            ans = tf.constant(mse + weightPunish)
            return ans
        
        def get_grad(self, input_tensor):
            with tf.GradientTape() as tape:
                tape.watch(self.variables)
                L = self.get_loss(input_tensor)
                g = tape.gradient(L, self.variables)
            return g
    
        def network_learn(self, input_tensor):
            g = self.get_grad(input_tensor)
            optimizers.Adam().apply_gradients(zip(g, self.variables))
            
    

    在本模型中,为了自定义带有额外参数的loss function(即权重惩罚项),因此需要对整个模型的流程进行自定义。传统模型只需包括__init__()方法和call()方法即可,但在本例中,可以看出call()方法中的代码被get_loss()方法囊括了,这样是为了方便在计算损失函数时获得需要的参数。
    本模型执行流程为:network_learn -> get_grad -> get_loss(执行一次神经网络训练过程,并计算损失值) -> get_grad(根据返回的损失值计算梯度并返回) -> network_learn(根据返回的梯度,使用某种优化器(本例为Adam)更新模型中所有需要训练的参数(也可以指定某些参数))

    训练过程也变了,代码如下,需要手动进行设置了:

    saeModel = SAEModel(inputList.shape[-1], hiddenNum)
    for i in range(1000):
    	saeModel.network_learn(tf.constant(inputList))
    

    到此,我已介绍完如何使用tensorflow2.0自定义Layer、自定义Model、自定义Loss Function,接下来将会将这三者结合起来,实现一个完整的例子——(四)tensorflow2.0 - 实战稀疏自动编码器SAE


    参考文献:

  • 相关阅读:
    Linux设备模型 学习总结
    平衡二叉树
    数字在排序数组中出现的次数
    两个链表的第一个公共节点
    第一个只出现一次的字符
    丑数
    把数组排成最小的数
    剑指offer 连续子数组的最大和
    查找描述信息中包括robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=5部
    for each
  • 原文地址:https://www.cnblogs.com/yinyoupoet/p/13287355.html
Copyright © 2020-2023  润新知