资讯详情

Tensorflow2 自定义层、评价指标及其他 代码实现

1、Coordinate Attention

原论文:Coordinate Attention for Efficient Mobile Network Design

参考资料:将位置信息嵌入通道注意力!NUS提出新机制,显著提高卷积特征表达|CVPR2021

import tensorflow as tf from tensorflow import keras  class CoordAtt(keras.layers.Layer):     def __init__(self, filters, reduction=16, **kwargs):         super(CoordAtt, self).__init__(**kwargs)         self.fc1 = keras.Sequential([             keras.layers.Conv2D(filters//reduction, 1, use_bias=False),             keras.layers.BatchNormalization(),             keras.layers.ReLU()         ])         self.xfc = keras.layers.Conv2D(filters, 1, activation='sigmoid')         self.yfc = keras.layers.Conv2D(filters, 1, activation='sigmoid')     def call(self, inputs):         shape = tf.shape(inputs) # (batch, h, w, c)         xap = tf.math.reduce_mean(inputs, axis=2, keepdims=True) # (batch, h, 1, c)         yap = tf.math.reduce_mean(inputs, axis=1, keepdims=True) # (batch, 1, w, c)         xap_transpose = tf.transpose(xap, perm=[0,2,1,3]) # (batch, 1, h, c)         merge = tf.concat([xap_transpose, yap], axis=2) # (batch, 1, h w, c)         fc = self.fc1(merge) # (batch, 1, h w, c//r)         xat_transpose, yat = tf.split(fc, [shape[1], shape[2]], axis=2) # (batch, 1, h, c//r) (batch, 1, w, c//r)         xac_transpose, yac = self.xfc(xat_transpose), self.yfc(yat) # (batch, 1, h, c) (batch, 1, w, c)         xac = tf.transpose(xac_transpose, perm=[0,2,1,3] # (batch, h, 1, c)          return inputs * xac * yac # (batch, h, w, c) * (batch, h, 1, c) * (batch, 1, w, c)

2、SoftPool(2D)

原论文:Refining activation downsampling with SoftPool

参考资料:在深度学习中阅读各种池化方法!

import tensorflow as tf from tensorflow import keras  class SoftPool(keras.layers.Layer):     def __init__(self, pool_size=(2, 2), **kwargs):         super(SoftPool, self).__init__(**kwargs)         self.pool_size = pool_size     def call(self, inputs):         e_x = tf.math.exp(inputs) # (batch, height, width, channel)         e_x_sum = tf.math.reduce_sum(e_x, axis=-1, keepdims=True) # (batch, height, width, 1)         top = keras.layers.AveragePooling2D(self.pool_size)(inputs*e_x_sum) # (batch, height/2, width/2, channel)         bottom = keras.layers.AveragePooling2D(self.pool_size)(e_x_sum) # (batch, height/2, width/2, 1)         return tf.math.divide_no_nan(top, bottom) # (batch, height/2, width/2, channel)

评价指标适用于二分类:F_beta、IoU、Kappa

import tensorflow as tf  class F1(tf.keras.metrics.Metric):     # beta价值决定了召回率的比例,beta>1.召回率的影响比精度大     def __init__(self, beta=1, name='F1', **kwargs):         super(F1, self).__init__(name=name, **kwargs)         self.Pre = tf.keras.metrics.Precision()         self.Rec = tf.keras.metrics.Recall()         self.beta = self.add_weight(name='beta', initializer='zeros')         self.beta.assign_add( beta )      def update_state(self, y_true, y_pred, sample_weight=None):         self.Pre.update_state(y_true, y_pred, sample_weight=sample_weight)         self.Rec.update_state(y_true, y_pred, sample_weight=sample_weight)      def result(self):         total = self.Pre.result() * self.beta**2   self.Rec.result()         return (1  self.beta**2 )*self.Pre.result()*self.Rec.result() / (total   1e-8)      def reset_states(self):         self.Pre.reset_states()         self.Rec.reset_states()  class IoU(tf.keras.metrics.Metric):     # intersection of union     def __init__(self, name='IoU', **kwargs):         super(IoU, self).__init__(name=name, **kwargs)         self.TP = self.add_weight(name='tp', initializer='zeros')         self.FP = self.add_weight(name='fp', initializer='zeros')         self.FN = self.add_weight(name='fn', initializer='zeros')      def update_state(self, y_true, y_pred, sample_weight=None):          y_true = tf.cast(tf.reshape(y_true, (-1,)), dtype=tf.float32)          y_pred = tf.cast(tf.reshape(y_pred, (-1,)), dtype=tf.float32)         y_pred = tf.cast(y_pred > 0.5, dtype=tf.float32)          tp = y_true*y_pred         fp = (1-y_true)*y_pred         fn = y_true*(1-y_pred)          if sample_weight is not None:             w = tf.cast(tf.reshape(sample_weight, (-1,)), dtype=tf.float32)             tp *= w             fp *= w             fn *= w          self.TP.assign_add( tf.math.reduce_sum(tp) )         self.FP.assign_add( tf.math.reduce_sum(fp) )         self.FN.assign_add( tf.math.reduce_sum(fn) )      def result(self):         total = self.TP   selfFP + self.FN + 1e-8
        return self.TP / total

    def reset_states(self):
        self.TP.assign(0.0)
        self.FP.assign(0.0)
        self.FN.assign(0.0)

class Kappa(tf.keras.metrics.Metric):
    # 只适用于二分类的Kappa系数
    def __init__(self, name='Kappa', **kwargs):
        super(Kappa, self).__init__(name=name, **kwargs)
        self.TP = self.add_weight(name='tp', initializer='zeros')
        self.FP = self.add_weight(name='fp', initializer='zeros')
        self.FN = self.add_weight(name='fn', initializer='zeros')
        self.TN = self.add_weight(name='tn', initializer='zeros')

    def update_state(self, y_true, y_pred, sample_weight=None):

        y_true = tf.cast(tf.reshape(y_true, (-1,)), dtype=tf.float32)

        y_pred = tf.cast(tf.reshape(y_pred, (-1,)), dtype=tf.float32)
        y_pred = tf.cast(y_pred > 0.5, dtype=tf.float32)

        tp = y_true*y_pred
        fp = (1-y_true)*y_pred
        fn = y_true*(1-y_pred)
        tn = (1-y_true)*(1-y_pred)

        if sample_weight is not None:
            w = tf.cast(tf.reshape(sample_weight, (-1,)), dtype=tf.float32)
            tp *= w
            fp *= w
            fn *= w
            tn *= w

        self.TP.assign_add( tf.math.reduce_sum(tp) )
        self.FP.assign_add( tf.math.reduce_sum(fp) )
        self.FN.assign_add( tf.math.reduce_sum(fn) )
        self.TN.assign_add( tf.math.reduce_sum(tn) )

    def result(self):
        total = self.TP + self.FP + self.FN + self.TN + 1e-8
        pre1 = (self.TP + self.FN) * (self.TP + self.FP)
        pre2 = (self.TN + self.FN) * (self.TN + self.FP)
        pre = (pre1 + pre2) / total**2
        oa = (self.TP + self.TN) / total
        return (oa - pre) / (1 - pre)

    def reset_states(self):
        self.TP.assign(0.0)
        self.FP.assign(0.0)
        self.FN.assign(0.0)
        self.TN.assign(0.0)

if __name__=='__main__':
    m = F1()
    m.update_state([[0, 1, 1, 1], [1, 0, 1, 1]], [[0, 0, 1, 0], [0, 0, 1, 1]])
    print('F1:', m.result().numpy())    # F1: 0.6666667
    m = F1(beta = 2)
    m.update_state([[0, 1, 1, 1], [1, 0, 1, 1]], [[0, 0, 1, 0], [0, 0, 1, 1]])
    print('F2:', m.result().numpy())    # F2: 0.5555556
    m = IoU()
    m.update_state([[0, 1, 1, 1], [1, 0, 1, 1]], [[0, 0, 1, 0], [0, 0, 1, 1]])
    print('IoU:', m.result().numpy())   # IoU: 0.5
    m = Kappa()
    m.update_state([[0, 1, 1, 1], [1, 0, 1, 1]], [[0, 0, 1, 0], [0, 0, 1, 1]])
    print('Kappa:', m.result().numpy()) # Kappa: 0.33333334
    print(m.name)

适用于二类语义分割的损失函数:balanced crossentropy、dice loss、focal loss、tversky loss

import tensorflow as tf

def balanced_crossentropy(y_true, y_pred):
    y = tf.keras.layers.Flatten()(y_true)
    y_hat = tf.keras.layers.Flatten()(y_pred)

    _b = tf.math.reduce_sum(y, axis=-1)/(256*256)
    # sigmoid 在输入参数非常大或非常小的情况下,会给出边界值1或者0
    pred1 = tf.clip_by_value(y_hat, 1e-10, 0.99999)
    pred0 = tf.clip_by_value(1-y_hat, 1e-10, 0.99999)
    loss1 = tf.math.reduce_sum(y*tf.math.log(pred1), axis=-1)
    loss0 = tf.math.reduce_sum((1-y)*tf.math.log(pred0), axis=-1)
    loss_bce = -(1-_b)*loss1 -_b*loss0
    return tf.math.reduce_mean(loss_bce)

def dice_loss(y_true, y_pred, delta=1):
    y = tf.keras.layers.Flatten()(y_true)
    y_hat = tf.keras.layers.Flatten()(y_pred)

    total = tf.math.reduce_sum(y, axis=-1) + tf.math.reduce_sum(y_hat, axis=-1) + delta
    loss_dice = 1 - 2*tf.math.reduce_sum(y*y_hat, axis=-1)/total
    return tf.math.reduce_mean(loss_dice)

def focal_loss(y_true, y_pred, alpha=0.25, gamma=2):
    y = tf.keras.layers.Flatten()(y_true)
    y_hat = tf.keras.layers.Flatten()(y_pred)

    pred1 = tf.clip_by_value(y_hat, 1e-10, 0.99999)
    pred0 = tf.clip_by_value(1-y_hat, 1e-10, 0.99999)
    loss1 = tf.math.reduce_sum( y * (1-y_hat)**gamma * tf.math.log(pred1), axis=-1)
    loss0 = tf.math.reduce_sum( (1-y) * (y_hat)**gamma * tf.math.log(pred0), axis=-1)
    loss_focal = -alpha*loss1 -(1-alpha)*loss0
    return tf.math.reduce_mean(loss_focal)

def tversky_loss(y_true, y_pred, alpha=0.5, beta=0.5, delta=1):
    y = tf.keras.layers.Flatten()(y_true)
    y_hat = tf.keras.layers.Flatten()(y_pred)
    
    tp = tf.math.reduce_sum(y*y_hat, axis=-1)
    fp = tf.math.reduce_sum((1-y)*y_hat, axis=-1)
    fn = tf.math.reduce_sum(y*(1-y_hat), axis=-1)
    loss_tversky = tp/(tp + alpha*fp + beta*fn + delta)
    return tf.math.reduce_mean(loss_tversky)

1、GPU使用基础设置

import os 
import tensorflow as tf

# 指定程序运行使用的显卡
os.environ['CUDA_VISIBLE_DEVICES'] = '0,2,3'
# 动态分配显存
gpus = tf.config.experimental.list_physical_devices("GPU")
for gpu in gpus:
    tf.config.experimental.set_memory_growth(gpu, True)

2、训练过程中的loss和指标值可视化

import matplotlib.pyplot as plt

def Visualization(H, names, save_path):# 可视化
    shape = np.shape(names)
    fig,ax = plt.subplots(shape[0], shape[1], figsize=(shape[1]*8, shape[0]*6)) # 宽、高
    for i in range(shape[0]):
        for j in range(shape[1]):
            ax[i,j].set_xlabel('Epoch')
            ax[i,j].set_ylabel(names[i][j])
            ax[i,j].plot(H.history[names[i][j]], '-b.', label='train_'+names[i][j])
            ax[i,j].plot(H.history['val_'+names[i][j]], '-r.', label='val_'+names[i][j])
            ax[i,j].legend(loc='best')
    # plt.show()
    plt.savefig(save_path)

标签: an6xap6xrn6x传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台