softmax依赖pytorch框架的简洁实现

这篇博客介绍了如何简洁地实现softmax回归,包括数据集加载、模型参数初始化、softmax函数的处理技巧、优化算法的选择以及训练过程。使用Fashion-MNIST数据集,通过PyTorch构建了一个全连接层的softmax回归模型,并采用小批量随机梯度下降进行优化。在训练过程中,注意到softmax函数可能出现的上溢和下溢问题,通过调整计算交叉熵的方式避免了这些问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

softmax回归的简洁实现

1. 数据集

我们仍旧使用Fashion-MNIST数据集,并且使用上一节中定义好的函数进行数据集的加载。

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
2. 初始化模型参数

由于softmax回归的输出层是一个全连接层,因此,我们只需要在sequential中添加一个带有10个输出的全连接层。

def init_weight(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight,std=0.01) 
        
net = nn.Sequential(nn.Flatten(),nn.Linear(784,10))
net.apply(init_weight)

注:1)由于pytorch不可以隐式的调整输入的形状,所以在线性层前定义**展平层(flatten())**调整网络输入形状。

​ 2)nn.init.修改参数,net.apply对网络层进行自定义修改,这一部分在后面章节会着重讲解

3. 重新审视softmax实现

上一节说到softmax函数为 y ^ j = e x p ( o j ) ∑ k e x p ( o k ) \hat{y}_j = \frac{exp(o_j)}{\sum_kexp(o_k)} y^j=kexp(ok)exp(oj),由于指数函数本身特点,如果 o k o_k ok中有一些数值非常大,那么 e x p ( o k ) exp(o_k) exp(ok)可能会大于数据类型容许的最大数字,即上溢(overflow)。这将使分母或分子变为inf(无穷大),使得我们最后遇到的是0,inf 或 nan(不是数字)的 y ^ j \hat{y}_j y^j.这种情况下,我们将不能得到一个明确定义的交叉熵函数

softmax处理技巧之一,以下引用原文内容:

解决这个问题的一个技巧是,在继续softmax计算之前,先从所有 o k o_k ok中减去 m a x ( 𝑜 𝑘 ) max(𝑜_𝑘) max(ok)。你可以证明每个 o k o_k ok 按常数进行的移动不会改变softmax的返回值。在减法和归一化步骤之后,可能有些 o j o_j oj 具有较大的负值。由于精度受限, e x p ( 𝑜 𝑗 ) exp(𝑜_𝑗) exp(oj) 将有接近零的值,即 下溢(underflow)。这些值可能会四舍五入为零,使 y ^ j \hat{y}_j y^j 为零,并且使得 $log(𝑦̂ _𝑗) $的值为 -inf。反向传播几步后,我们可能会发现自己面对一屏幕可怕的nan结果。

为了使得交叉熵可以正常计算,我们可以在计算交叉熵时直接传入原始 o j o_j oj(未经过softmax处理过的输出),因为在计算交叉熵时取的是log值,会将exp抵消掉。具体过程将如下公式:
l o g ( y ^ j ) = l o g ( e x p ( o j ) ∑ k e x p ( o k ) )      = l o g ( e x p ( o j ) ) − l o g ( ∑ k e x p ( o k ) ) = o j − l o g ( ∑ k e x p ( o k ) ) log(\hat{y}_j) = log(\frac{exp(o_j)}{\sum_kexp(o_k)})\\ \ \ \ \ \quad \quad \qquad \qquad \qquad =log(exp(o_j)) - log(\sum_kexp(o_k))\\ \quad \qquad \qquad=o_j - log(\sum_kexp(o_k)) log(y^j)=log(kexp(ok)exp(oj))    =log(exp(oj))log(kexp(ok))=ojlog(kexp(ok))
所以我们保留传统的softmax函数,用来评估通过模型输出的概率,但我们并没有将softmax函数传递到损失函数中,而是在交叉熵函数中传递未归一化的预测,并同时计算softmax及其对数

loss = nn.CrossEntropyLoss()
4. 定义优化算法

我们仍然使用小批量随机梯度下降作为优化算法。

trainer = torch.optim.SGD(net.parameters(),lr=0.1)
5. 训练

我们调用之前定义好的函数进行训练

num_epochs = 10
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值