• (四)tensorflow2.0


    前文已经介绍完了tensorflow2.0自定义layer、model、loss function,本文将结合前述知识,搭建一个稀疏自动编码器SAE。
    (一)tensorflow2.0 - 自定义layer
    (二)tensorflow2.0 - 自定义Model
    (三)tensorflow2.0 - 自定义loss function(损失函数)
    (四)tensorflow2.0 - 实战稀疏自动编码器SAE


    先简单介绍稀疏自动编码器SAE,其架构如下图所示(图源网络,侵删),三层结构,输出层应尽量和输入层接近,其重点在于中间的隐藏层,隐藏层将数据进行了重新编码,这样做的目的是获得输入数据更好的数据表示。在普通自动编码器中,往往要求隐藏层元素个数要比输入层元素个数少,但是稀疏自动编码器的要求不同,它可以允许隐藏层元素比输入层元素多,但是要保证稀疏性,即大多数隐藏层节点的输出值为0。
    在这里插入图片描述
    而SAE的损失函数,则为:
    在这里插入图片描述
    第一部分为预测值与真实值的SAE,第二部分为对权重的惩罚项,第三部分ρ和ρ帽分别代表期望的稀疏度和实际的稀疏度。

    下面放上代码:

    import tensorflow as tf
    import numpy as np
    import pandas as pd
    from tensorflow.keras import *
    import tensorflow.keras.backend as kb
    import sys
    import matplotlib.pyplot as plt
    
    
    # 输入输出为16 × 1的列表
    # inputList为输入列表
    def SAEFC(inputList):
        inputList = np.array(inputList)
        # 输入特征个数
        inputFeatureNum = len(inputList[0])
        # 隐藏层参数个数:输入特征3倍
        hiddenNum = 3 * inputFeatureNum
        # 稀疏度(密度)
        density = 0.1
    
        lossList = []
        saeModel = SAEModel(inputList.shape[-1], hiddenNum)
        for i in range(1000):
            loss = saeModel.network_learn(tf.constant(inputList))
            lossList.append(loss)
            print(loss)
    
        # 绘制损失值图像
        x = np.arange(len(lossList)) + 1
        plt.plot(x, lossList)
        plt.show()
    
        return saeModel
    
    
    
    # 自定义隐藏层
    class SAELayer(layers.Layer):
        def __init__(self, num_outputs):
            super(SAELayer, self).__init__()
            # 该层最后一个节点,其值固定为1,
            # 前期可以按照同样的手段让该节点和其他节点一样进行计算,
            # 最后在传递给下一层前,将其设置为1即可(即其值固定为1)
            self.num_outputs = num_outputs
    
        def build(self, input_shape):
            self.kernel = self.add_variable("kernel",
                                            shape=[int(input_shape[-1]),
                                                   self.num_outputs - 1])
            self.bias = self.add_variable("bias",
                                          shape=[self.num_outputs - 1])
        def call(self, input):
            output = tf.matmul(input, self.kernel) + self.bias
            # sigmoid函数
            output = tf.nn.sigmoid(output)
            bias_list = tf.ones([input.shape[0], 1])
            output = tf.concat([output, bias_list], 1)
            self.result = output
            return output
    
    
    # 自定义模型
    class SAEModel(Model):
        # 可以传入一些超参数,用以动态构建模型
        # __init_——()方法在创建模型对象时被调用
        # input_shape: 输入层和输出层的节点个数(输入层实际要比这多1,因为有个bias)
        # hidden_shape: 隐藏层节点个数,隐藏层节点的最后一个节点值固定为1,也是bias
        # 使用方法:直接传入实际的input_shape即可,在call中也直接传入原始Input_tensor即可
        # 一切关于数据适配模型的处理都在模型中实现
        def __init__(self, input_shape, hidden_shape=None):
            # print("init")
            # 隐藏层节点个数默认为输入层的3倍
            if hidden_shape == None:
                hidden_shape = 3 * input_shape
            # 调用父类__init__()方法
            super(SAEModel, self).__init__()
    
            self.train_loss = None
            self.layer_2 = SAELayer(hidden_shape)
            self.layer_3 = layers.Dense(input_shape, activation=tf.nn.sigmoid)
    
    
        def call(self, input_tensor, training=False):
            # 将input_tensor最后加一列1
            bias_list = tf.ones([len(input_tensor), 1])
            input_tensor = tf.concat([input_tensor, bias_list], 1)
            # 输入数据
            # x = self.layer_1(input_tensor)
            hidden = self.layer_2(input_tensor)
            output = self.layer_3(hidden)
            return output
        
        def get_loss(self, input_tensor):
            # print("get_loss")
            bias_list = tf.ones([len(input_tensor), 1])
            new_input = tf.concat([input_tensor, bias_list], 1)
            hidden = self.layer_2(new_input)
            output = self.layer_3(hidden)
            
            # 计算loss
            # 计算MSE
            mse = (1 / 2) * tf.reduce_sum(kb.square(input_tensor - output))
    
            # 计算权重乘法项
            alpha = 0.1
            W1 = self.layer_2.kernel
            W2 = self.layer_3.kernel
            weightPunish = (alpha / 2) * (tf.reduce_sum(kb.square(W1)) + tf.reduce_sum(kb.square(W2)))
    
            # 计算KL散度
            beita = 0.1
            desired_density = 0.1
            layer2_output = self.layer_2.result
            # 实际密度是所有输入数据的密度的平均值
            actual_density = tf.reduce_mean(tf.math.count_nonzero(layer2_output, axis=1) / layer2_output.shape[1])
            actual_density = tf.cast(actual_density, tf.float32)
            if actual_density == tf.constant(1.0, dtype=tf.float32):
                actual_density = tf.constant(0.999)
            actual_density = actual_density.numpy()
    
    		
            KL = desired_density * np.log(desired_density / actual_density)
            KL += (1 - desired_density) * np.log((1 - desired_density) / (1 - actual_density))
            KL *= beita
            ans = tf.constant(mse + weightPunish + KL)
            return ans
        
        def get_grad(self, input_tensor):
            with tf.GradientTape() as tape:
                tape.watch(self.variables)
                L = self.get_loss(input_tensor)
                # 保存一下loss,用于输出
                self.train_loss = L
                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))
            return self.train_loss
    
        # 如果模型训练好了,需要获得隐藏层的输出,直接获取麻烦,则直接运行一遍
        def getReprestation(self, input_tensor):
            bias_list = tf.ones([len(input_tensor), 1])
            new_input = tf.concat([input_tensor, bias_list], 1)
            hidden = self.layer_2(new_input)
            return hidden
    
  • 相关阅读:
    linux shell创建目录、遍历子目录
    linux shell写入单行、多行内容到文件
    如何起个好名字
    linux shell编程中的数组定义、遍历
    详解浏览器分段请求基础——Range,助你了解断点续传基础
    实现一个大文件上传和断点续传
    localStorage设置过期时间
    Python3 __slots__
    Nginx 流量统计分析
    argparse简要用法总结
  • 原文地址:https://www.cnblogs.com/yinyoupoet/p/13287354.html
Copyright © 2020-2023  润新知