深度学习7-常用损失函数和自定义损失函数

文章目录

      • 1.常用损失函数
      • 2.自定义损失函数
        • mse
        • Focal loss损失函数
      • 3.实战1:Focal Loss实现自定义损失函数(以minist数据集构建图像分类算法)

深度学习7-常用损失函数和自定义损失函数_第1张图片

1.常用损失函数

tf.keras.losses

列举常用的,如下:
深度学习7-常用损失函数和自定义损失函数_第2张图片

BinaryCrossentropy和binary_crossentropy有什么区别?
前者是类的实现形式,后者是函数的实现形式
这两者并没有本质的区别

使用损失函数时,首先要确定到底是分类还是回归问题?一定要对应
每个损失函数是如何实现的一定要清楚

交叉熵损失函数-多分类
深度学习7-常用损失函数和自定义损失函数_第3张图片

# tf版本
import tensorflow as tf

# 调用类,输入损失函数
cce = tf.keras.losses.CategoricalCrossentropy()

loss = cce(
    [[1.,0.,0.],[0.,1.,0.],[0.,0.,1.]],
    [[.9,.05,.05],[.05,.89,.06],[.05,.01,.94]])
print('Loss:',loss.numpy())     # Loss: 0.09458993


# Numpy版本
import numpy as np 

a = np.array([[1.,0.,0.],[0.,1.,0.],[0.,0.,1.]])
b = np.array([[.9,.05,.05],[.05,.89,.06],[.05,.01,.94]])

np.average(-np.sum(a * np.log(b),axis=1))     # 0.09458991187728844

2.自定义损失函数

mse

深度学习7-常用损失函数和自定义损失函数_第4张图片

Focal loss损失函数

深度学习7-常用损失函数和自定义损失函数_第5张图片

多分类的Focal loss函数:
gamma 用来减小易分类样本的权重,使得模型训练时更加专注于难分类的样本
α 用来计算每个类别的概率-权重-二分类变成多分类时,α会失效
# 类的实现
class SparseFocalLoss(tf.keras.losses.Loss):
    
    def __init__(self,gamma=2.0,alpha=0.25,class_num=10):
    	# 初始化参数
        self.gamma = gamma
        self.alpha = alpha
        self.class_num = class_num
        super(SparseFocalLoss,self).__init__()
        
        
    def call(self,y_true,y_pred):
        # 激活函数
        y_pred = tf.nn.softmax(y_pred,axis=-1)
        # 使预测值在某个区间不为0
        epsilon = tf.keras.backend.epsilon()
        y_pred = tf.clip_by_value(y_pred,epsilon,1.0)
        
        # 转换成one_hot格式
        y_true = tf.one_hot(y_true,depth=self.class_num)
        # 数据类型转化
        y_true = tf.cast(y_true,tf.float32)
        
        loss = -y_true * tf.math.pow(1 - y_pred,self.gamma) * tf.math.log(y_pred)
        
        loss = tf.math.reduce_sum(loss,axis=1)
        return loss
# 函数的实现
def focal_loss(gamma=2.0,alpha=0.25):
    def focal_loss_fixed(y_true,y_pred):
        y_pred = tf.nn.softmax(y_pred,axis=-1)
        epsilon = tf.keras.backend.epsilon()
        y_pred = tf.clip_by_value(y_pred,epsilon,1.0)
        
        # 数据类型转换
        y_true = tf.cast(y_true,tf.float32)
        
        loss = -y_true * tf.math.pow(1-y_pred,gamma) * tf.math.log(y_pred)
        loss = tf.reduce_sum(loss,axis=1)
        return loss
    
    return focal_loss_fixed

3.实战1:Focal Loss实现自定义损失函数(以minist数据集构建图像分类算法)

深度学习7-常用损失函数和自定义损失函数_第6张图片
子类模型

from __future__ import absolute_import, division, print_function, unicode_literals

import tensorflow as tf

from tensorflow.keras.layers import Dense, Flatten, Conv2D
from tensorflow.keras import Model
import numpy as np

print(tf.__version__)
print(np.__version__)

# 数据集处理
mnist = np.load("mnist.npz")
x_train, y_train, x_test, y_test = 
mnist['x_train'],mnist['y_train'],mnist['x_test'],mnist['y_test']
# 神经网络需要归一化
x_train, x_test = x_train / 255.0, x_test / 255.0

# 画图展示
import matplotlib.pyplot as plt
 
fig, ax = plt.subplots(
    nrows=2,
    ncols=5,
    sharex=True,
    sharey=True, )
 
ax = ax.flatten()
for i in range(10):
    img = x_train[y_train == i][0].reshape(28, 28)
    ax[i].imshow(img, cmap='Greys', interpolation='nearest')
    
ax[0].set_xticks([])
ax[0].set_yticks([])
plt.tight_layout()
plt.show()


# 增加一个通道(28,28,1)
x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]

y_train = tf.one_hot(y_train,depth=10)
y_test = tf.one_hot(y_test,depth=10)

train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train)).shuffle(10000).batch(32)
test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)

# 简单的神经网络
# 定义模型
class MyModel(Model):
    
    def __init__(self):
        super(MyModel,self).__init__()
        # 定义二维的卷积层
        self.conv1 = Conv2D(32,3,activation='relu')
        self.flatten = Flatten()
        # 定义全连接层
        self.d1 = Dense(128,activation='relu')
        # 输出层
        self.d2 = Dense(10,activation='softmax')
        
        
    def call(self,x):
        # 定义前向传播
        x = self.conv1(x)     # 卷积
        x = self.flatten(x)   # 压缩
        x = self.d1(x)        # 全连接层
        return self.d2(x)     # 输出


# 类的实现
#多分类的focal loss 损失函数
class FocalLoss(tf.keras.losses.Loss):

    def __init__(self,gamma=2.0,alpha=0.25):
        self.gamma = gamma
        self.alpha = alpha
        super(FocalLoss, self).__init__()

    def call(self,y_true,y_pred):
        y_pred = tf.nn.softmax(y_pred,axis=-1)
        epsilon = tf.keras.backend.epsilon()#1e-7
        y_pred = tf.clip_by_value(y_pred, epsilon, 1.0)
        
       
        y_true = tf.cast(y_true,tf.float32)
        
        loss = -  y_true * tf.math.pow(1 - y_pred, self.gamma) * tf.math.log(y_pred)
        
        loss = tf.math.reduce_sum(loss,axis=1)
        return loss

# 类的实现与函数的实现选择一个
# 函数的实现
def FocalLoss(gamma=2.0,alpha=0.25):
    def focal_loss_fixed(y_true, y_pred):
        y_pred = tf.nn.softmax(y_pred,axis=-1)
        # 使预测值在某个区间不为0
        epsilon = tf.keras.backend.epsilon()
        y_pred = tf.clip_by_value(y_pred, epsilon, 1.0)
		 # 转换数据格式
        y_true = tf.cast(y_true,tf.float32)

        loss = -  y_true * tf.math.pow(1 - y_pred, gamma) * tf.math.log(y_pred)

        loss = tf.math.reduce_sum(loss,axis=1)
        return  loss
    return focal_loss_fixed


model = MyModel()

#loss_object = tf.keras.losses.CategoricalCrossentropy()
loss_object = FocalLoss(gamma=2.0,alpha=0.25)

optimizer = tf.keras.optimizers.Adam()

train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.CategoricalAccuracy(name='train_accuracy')

test_loss = tf.keras.metrics.Mean(name='test_loss')
test_accuracy = tf.keras.metrics.CategoricalAccuracy(name='test_accuracy')

# 将动态图转化为静态图
@tf.function
def train_step(images, labels):
    with tf.GradientTape() as tape:
        predictions = model(images)
        loss = loss_object(labels, predictions)
     # 计算梯度
    gradients = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))
	# 参数更新
    train_loss(loss)
    train_accuracy(labels, predictions)


@tf.function
def test_step(images, labels):
    predictions = model(images)
    t_loss = loss_object(labels, predictions)

    test_loss(t_loss)
    test_accuracy(labels, predictions)


EPOCHS = 5
for epoch in range(EPOCHS):
    # 在下一个epoch开始时,重置评估指标
    train_loss.reset_states()
    train_accuracy.reset_states()
    test_loss.reset_states()
    test_accuracy.reset_states()

    for images, labels in train_ds:
        train_step(images, labels)

    for test_images, test_labels in test_ds:
        test_step(test_images, test_labels)

    template = 'Epoch {}, Loss: {}, Accuracy: {}, Test Loss: {}, Test Accuracy: {}'
    print(template.format(epoch + 1,
                          train_loss.result(),
                          train_accuracy.result() * 100,
                          test_loss.result(),
                          test_accuracy.result() * 100))

深度学习7-常用损失函数和自定义损失函数_第7张图片
在这里插入图片描述
函数模型

from __future__ import absolute_import, division, print_function, unicode_literals

import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten, Conv2D
from tensorflow.keras import Model
import numpy as np

print(tf.__version__)
print(np.__version__)

mnist = np.load("mnist.npz")
x_train, y_train, x_test, y_test = mnist['x_train'],mnist['y_train'],mnist['x_test'],mnist['y_test']

x_train, x_test = x_train / 255.0, x_test / 255.0
y_train = np.int32(y_train)
y_test = np.int32(y_test)

# 增加一个通道
x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]
y_train = tf.one_hot(y_train,depth=10)
y_test = tf.one_hot(y_test,depth=10)

train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train)).shuffle(10000).batch(32)
test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test)).shuffle(100).batch(32)


# 函数式定义模型
def MyModel():
    inputs = tf.keras.Input(shape=(28,28,1), name='digits')         # 输入层
    x = tf.keras.layers.Conv2D(32, 3, activation='relu')(inputs)    # 卷积层 32个通道  3表示卷积和
    x = tf.keras.layers.Flatten()(x)                                # 压缩
    x = tf.keras.layers.Dense(128, activation='relu')(x)            # 128个神经元的全连接层
    outputs = tf.keras.layers.Dense(10,activation='softmax', name='predictions')(x)# 输出层
    model = tf.keras.Model(inputs=inputs, outputs=outputs)          
    return model

# 类的实现
#多分类的focal loss 损失函数
class FocalLoss(tf.keras.losses.Loss):

    def __init__(self,gamma=2.0,alpha=0.25):
        self.gamma = gamma
        self.alpha = alpha
        super(FocalLoss, self).__init__()

    def call(self,y_true,y_pred):
        y_pred = tf.nn.softmax(y_pred,axis=-1)
        epsilon = tf.keras.backend.epsilon()
        y_pred = tf.clip_by_value(y_pred, epsilon, 1.0)
        
       
        y_true = tf.cast(y_true,tf.float32)
        
        loss = -  y_true * tf.math.pow(1 - y_pred, self.gamma) * tf.math.log(y_pred)
        
        loss = tf.math.reduce_sum(loss,axis=1)
        return loss
    
# keras版本
model = MyModel()
model.compile(optimizer = tf.keras.optimizers.Adam(0.001), #优化器
              loss =  FocalLoss(gamma=2.0,alpha=0.25), #损失函数
              metrics = [tf.keras.metrics.CategoricalAccuracy()]
             ) #评估函数

model.fit(train_ds, epochs=5,validation_data=test_ds)

深度学习7-常用损失函数和自定义损失函数_第8张图片

你可能感兴趣的:(深度学习,tensorflow,神经网络,损失函数)