Softmax 和交叉熵损失函数

Softmax 函数

Softmax 函数函数是机器学习和深度学习中相当常用到的函数,它的公式如下:
s o f t m a x ( S ) = e s k ∑ j e s j softmax(S)=\frac { e ^ { s _ { k } } } { \sum _ { j } e ^ { s _ { j } } } softmax(S)=jesjesk
其中 𝑠𝑘 表示的是输入到 Softmax 函数的数据。Softmax 函数具体的作用是将输入标准化到和为 1 的输出,经过 Softmax 函数的的数据可以被认为是概率。
为了更好理解,假设最后的输出 y y y ( 3.2 , 5.1 , − 1.7 ) (3.2, 5.1, -1.7) (3.2,5.1,1.7),对应的是每一个类别的概率,但是显然这个数字不能直接使用,通常来说概率都是和为 1 的,所以才需要经过 Softmax 进行标准化。
代码实现:

def softmax(input):
    assert len(input.shape) == 2 # 输入 softmax 函数的数据必须是一个二维矩阵
    exp_value = np.exp(input)  # 首先计算指数
    output = exp_value/np.sum(exp_value, axis=1)[:, np.newaxis]  # 然后按行标准化
    return output


test_data = np.array([[3.2, 5.1, -1.7]])
softmax(test_data)

交叉熵损失函数

既然经过 Softmax 函数之后的是概率,那么最根本的想法当然是使正确类别的概率最大。交叉熵损失函数出现的目的就是使正确类别概率最大。
交叉熵是用来衡量两个概率之间的差别。深度学习中使用 softmax 输出的概率拟合真实概率,并使得这两个两个概率之间的交叉熵最小。
假设交叉熵损失函数为 L,那么单个样本的损失定义为:
L i = − Y i log ⁡ P i L _ { i } = - Y_i \log P_i Li=YilogPi
指的是在样本是 x i x_i xi 的情况下,使用概率分布 P i P_i Pi 拟合真实概率分布 Y i Y_i Yi 的误差。​为了更容易理解,代入 Softmax 函数的公式作为概率,交叉熵损失函数可以写成:
L i = − ∑ y i log ⁡ ( e x i ∑ j e x j ) L _ { i } = - \sum y_i \log \left( \frac { e ^ { x_{ i } } } { \sum _ { j } e ^ { x _ { j } } } \right) Li=yilog(jexjexi)
多个样本时,只需要将各个样本的损失相加即可:
L = 1 N ∑ L i L = \frac{1}{N}\sum L _ { i } L=N1Li
其中 Y = ( y 1 , … , y i , …   ) Y=(y_1,\dots,y_i,\dots) Y=(y1,,yi,) 是真实概率,因为是独热编码,所以 y i y_i yi 要么为 0 要么 为 1; X = ( x 1 , … , x i , …   ) X=(x_1,\dots,x_i,\dots) X=(x1,,xi,) 是神经网络的输出。
代码实现:

# 最后的输出是 N*C
N, C = 100, 3
test_data = np.random.randn(N, C)  # 生成随机数据

# 生成随机标签,不包括 C,并独热编码
test_labels = encoder.fit_transform(np.random.randint(0, C, (N, 1))).toarray()
prob = softmax(test_data)  # 每一行对应一个样本,按行计算概率

# 根据公式 7,8 实现
# loss = np.sum(-np.log(prob))  # 根据公式计算 loss
loss = np.sum(-np.log(prob) * test_labels) / N

学习率衰减策略

一般情况下,我们会先设置一个较大的学习率以尽快到达极小点。但固定学习率往往会带来另一个问题,那就是无法准确收敛,并在极小值附近反复波动。所以,为了兼顾梯度下降法后期的收敛速度和准确度,必须要应用学习率衰减策略。
一般情况下,学习率衰减策略有三种,分别是:

  • Step decay(按步长衰减)。
  • Exponential decay(指数衰减): α = α 0 e − k t \alpha = \alpha_0 e^{-k t} α=α0ekt t t t 是迭代次数, α 0 \alpha_0 α0 k k k 是提前设定的值。
  • 1/t decay (1/t 衰减): α = α 0 / ( 1 + k t ) \alpha = \alpha_0 / (1 + k t ) α=α0/(1+kt) t t t 是迭代次数, α 0 \alpha_0 α0 k k k 是提前设定的值。

在实际应用中,按步长衰减是最常用的,其基本公式如下:
l r = b a s e _ l r ∗ α k lr = base\_lr*\alpha^k lr=base_lrαk
其中, α \alpha α 为设定的衰减因子, k k k 为是迭代次数/提前设定的步长,通俗点讲其实是每迭代一个设定的步长数目,则学习率变为上一个步长的 α \alpha α。步长需要根据实际应用调整,但是衰减因子常为 0.1,即学习率是上一个步长的 1 10 \frac{1}{10} 101
实现代码:

class lr_scheduler(object):
    def __init__(self, base_lr, step_size, deacy_factor=0.1):
        self.base_lr = base_lr  # 最初的学习率
        self.deacy_factor = deacy_factor  # 学习率衰减因子
        self.step_count = 0  # 当前的迭代次数
        self.lr = base_lr  # 当前学习率
        self.step_size = step_size  # 步长

    def step(self, step_count=1):  # 默认 1 次
        self.step_count += step_count

    def get_lr(self):
        # 根据公式 12 实现
        self.lr = self.base_lr * \
            (self.deacy_factor**(self.step_count//self.step_size))  # 实现上面的公式
        return self.lr

应用学习率衰减策略时需要注意最大迭代次数足够,否则可能收敛不完全。学习率非常小的时候,会导致收敛速度很慢;学习率很大时,会出现Loss 震荡或超出数值范围。

  • 2
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凡心curry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值