深度学习记录(3) - 网络构建方式与损失函数

1. 神经网络的构建方式

  • jupyter botebook 中可以使用shift + tab查看函数参数提示。

1.1 Sequential构建方式

只能构建序列模型

  • 构建模型
import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.layers as layers

model  = keras.Sequential(
    [
        # 第一个隐藏层
        
        layers.Dense(3, activation="relu", kernel_initializer='he_normal', name = "layer1",input_shape=(3,)),
        
        layers.Dense(2, activation="relu", kernel_initializer='he_normal', name = "layer2"),
        
        layers.Dense(2, activation="sigmoid", kernel_initializer='he_normal', name = "layer3"),
        
    ],
    name = "my_Seq"
)
  • 展示模型
model.summary()

在这里插入图片描述

1.2 利用function API构建

tf.keras提供了Function API,建立更为复杂的模型,使用方法是将层座位可调用的对象并返回张量,并将输入向量和输出向量提供给 tf.keras.Model 的 inputs 和 outputs 参数,实现方法如下:

inputs = keras.Input(shape=(3,), name = "my_input")

layer1 = keras.layers.Dense(2,activation="relu", kernel_initializer='he_normal', name = "layer1" )(inputs)
                            
layer2 = keras.layers.Dense(2,activation="relu", kernel_initializer='he_normal', name = "layer2" )(layer1)

outputs = keras.layers.Dense(2,activation="sigmoid", kernel_initializer='he_normal', name = "layer3" )(layer2)

model = keras.Model(inputs = inputs, outputs = outputs, name="my_model")

效果
在这里插入图片描述

1.3 通过Model的子类构建

  • 需要在子类的 __init__ 中定义神经网络的层,在 call 方法中定义网络的前向传播过程。实现方法如下:

class MyModel(keras.Model):
    # 定义网络层结构
    def __init__(self):
        super(MyModel, self).__init__()
        
        self.layer1 = keras.layers.Dense(3, activation="relu", kernel_initializer='he_normal', name = "layer1")
        
        self.layer2 = keras.layers.Dense(2, activation="relu", kernel_initializer='he_normal', name = "layer2")
        
        self.layer3 = keras.layers.Dense(2, activation="sigmoid", kernel_initializer='he_normal', name = "layer3")
        
    # 定义网络前向传播过程
    def call(self, inputs):
        x = self.layer1(inputs)
        x = self.layer2(x)
        x = self.layer3(x)
        return x


# 实例化模型
model = MyModel()
x = tf.ones((1, 3))
y = model(x)   # 设置一个输入,调用模型,否则模型无法使用summay

model.summary()

2. 损失函数

  • 损失函数用来衡量模型参数的质量的函数,衡量的方式是比较网络输出和真实输出的差异,损失函数在不同的文献中名称是不一样的,主要有以下几种命名方式:
    • 损失函数
    • 代价函数
    • 目标函数
    • 误差函数

2.1 分类任务中的损失函数

  • 在分类任务中使用最多的是交叉熵损失函数,有多分类的交叉熵,也有二分类的交叉熵。

多分类任务

多分类中通常使用softmax转换成概率的形式,一般交叉熵一般在softmax后边,所以多分类的交叉熵损失也叫做softmax损失,它的计算方法是:
在这里插入图片描述
例子:
在这里插入图片描述
从概率论的角度理解,我们的目的是最小化正确类别所对应的预测概率的对数的负值,如下所示:
在这里插入图片描述
代码如下

# 设置真实值与预测值
y_true = [[0,1,0], [0,0,1]]
y_pre = [[0.05, 0.9, 0.05], [0.3, 0.2, 0.5]]  # softmax输出的结果 sum == 1
# 实例化交叉熵损失函数
cce = keras.losses.CategoricalCrossentropy()

# 计算损失结果
cce(y_true, y_pre)

输出

0.39925388

此时,更改第二个预测值的概率分布,

# 设置真实值与预测值
y_true = [[0,1,0], [0,0,1]]
y_pre = [[0.05, 0.9, 0.05], [0.05, 0.05, 0.9]]  # softmax输出的结果 sum == 1
# 实例化交叉熵损失函数
cce = keras.losses.CategoricalCrossentropy()

# 计算损失结果
cce(y_true, y_pre)

输出

0.105360545

可见,符合上边的那个曲线图,综合预测的概率越大(越接近真实值),损失函数越小

二分类任务

  • 二分类任务时,不是用softmax激活函数,而是使用sigmoid函数,所以损失函数也要进行相应调整,是用二分类的交叉熵损失函数:
    在这里插入图片描述
    代码如下:
# 设置真实值与预测值
y_true = [[0], [1]]  # 两个样本  原始标签:一个是  一个不是
y_pre = [[0.4], [0.6]] 
# 实例化二分类的交叉熵损失函数
cce = keras.losses.BinaryCrossentropy()

# 计算损失结果
cce(y_true, y_pre)

输出:

0.5108254

此时,调整一下预测值

# 设置真实值与预测值
y_true = [[0], [1]]  # 两个样本  原始标签:一个是  一个不是
y_pre = [[0.1], [0.9]] 
# 实例化二分类的交叉熵损失函数
cce = keras.losses.BinaryCrossentropy()

# 计算损失结果
cce(y_true, y_pre)

输出:

0.10536041

可见,预测值越接近真实值,损失函数越小。

2.2 回归任务中的损失函数

  • 回归任务中常用损失函数
    • MAE损失(L1 损失)
    • MSE损失(L2 损失)
    • smooth L1损失

MAE(L1 loss)损失

MAE损失也叫 L1 loss,是以绝对误差作为距离:
在这里插入图片描述
曲线图如下:
在这里插入图片描述
特点:L1 loss具有稀疏性,为了惩罚较大的值,因此尝尝将其作为正则项添加到其他loss中作为约束。L1 loss的最大问题是梯度在零点不平滑(不可导),导致会跳过极小值。

# 设置真实值与预测值
y_true = [[0.], [1.]]  # 两个样本
y_pre = [[1.], [0.]] 
# 实例化MAE损失函数
mae = keras.losses.MeanAbsoluteError()

# 计算损失结果
mae(y_true, y_pre)

输出:

1.0

MSE(L2 loss)损失

也叫 L2 loss 或欧氏距离,它以误差的平方和作为距离:
在这里插入图片描述
曲线图如下:
在这里插入图片描述
特点是:L2 loss也常常作为正则项。当预测值与目标值相差很大时,梯度容易爆炸。

代码如下:

# 设置真实值与预测值
y_true = [[0.], [1.]]  # 两个样本  float型
y_pre = [[1.], [1.]] 
# 实例化MSE损失函数
mse = keras.losses.MeanSquaredError()

# 计算损失结果
mse(y_true, y_pre)

输出:

0.5

smooth L1 损失

平滑后的 L1 损失,结合了 L1 和 L2 的优点。|x| < 1时是L2,否则 是L1

在这里插入图片描述
曲线图如下:
在这里插入图片描述
从图可见,smooth L1是一个分段函数,在[-1, 1]之间是一个L2损失,其他范围是L1损失。

代码如下:

# 设置真实值与预测值
y_true = [[0], [1]]  # 两个样本
y_pre = [[0.6], [0.4]] 
# 实例化 smooth L1 损失函数
h = keras.losses.Huber()

# 计算损失结果
h(y_true, y_pre)

输出

0.18

猜你喜欢

转载自blog.csdn.net/u014117943/article/details/114436068
今日推荐