做机械设备的做哪个网站推广较好,如何清空网站空间,wordpress前台多语言,asp.net mvc5网站开发之美#x1f468;#x1f393;作者简介#xff1a;一位即将上大四#xff0c;正专攻机器学习的保研er #x1f30c;上期文章#xff1a;机器学习深度学习——softmax回归从零开始实现 #x1f4da;订阅专栏#xff1a;机器学习深度学习 希望文章对你… 作者简介一位即将上大四正专攻机器学习的保研er 上期文章机器学习深度学习——softmax回归从零开始实现 订阅专栏机器学习深度学习 希望文章对你们有所帮助 继续使用Fashion-MNIST数据集并保持批量大小为256
import torch
from torch import nn
from d2l import torch as d2lbatch_size 256
train_iter, test_iter d2l.load_data_fashion_mnist(batch_size)softmax回归的简洁实现 初始化模型参数重新审视softmax的实现数学推导交叉熵函数 优化算法训练 初始化模型参数
softmax的输出层是一个全连接层因此为了实现模型我们只需要在Sequential中添加一个带有10个输出的全连接层。当然这里的Sequential并不是必要的但是他是深度模型的基础。我们仍旧以均值为0标准差为0.01来随机初始化权重。
# pytorch不会隐式地调整输入的形状
# 因此在线性层前就定义了展平层flatten来调整网络输入的形状
net nn.Sequential(nn.Flatten(), nn.Linear(784, 10))def init_weights(m):if type(m) nn.Linear:nn.init.normal_(m.weight, std0.01)net.apply(init_weights) # 给net每一层跑一次init_weights函数重新审视softmax的实现
数学推导
在之前的例子里我们计算了模型的输出然后将此输出送入交叉熵损失。看似合理但是指数级计算可能会造成数值的稳定性问题。 回想一下之前的softmax函数 y ^ j e x p ( o j ) ∑ k e x p ( o k ) 其中 y ^ j 是预测的概率分布 o j 是未规范化的第 j 个元素 \hat{y}_j\frac{exp(o_j)}{\sum_kexp(o_k)}\\ 其中\hat{y}_j是预测的概率分布o_j是未规范化的第j个元素 y^j∑kexp(ok)exp(oj)其中y^j是预测的概率分布oj是未规范化的第j个元素 由于o中的一些数值会非常大所以可能会让其指数值上溢使得分子或分母变成inf最后得到的预测值可能变成的0、inf或者nan。此时我们无法得到一个明确的交叉熵值。 提出解决这个问题的一个技巧在继续softmax计算之前先从所有的o中减去max(o)修改softmax函数的构造且不改变其返回值 y ^ j e x p ( o j − m a x ( o k ) ) e x p ( m a x ( o k ) ) ∑ k e x p ( o j − m a x ( o k ) ) e x p ( m a x ( o k ) ) \hat{y}_j\frac{exp(o_j-max(o_k))exp(max(o_k))}{\sum_kexp(o_j-max(o_k))exp(max(o_k))} y^j∑kexp(oj−max(ok))exp(max(ok))exp(oj−max(ok))exp(max(ok)) 这样操作以后可能会使得一些分子的exp(o-max(o))有接近0的值即为下溢。这些值可能会四舍五入为0这样就会使得预测值为0那么此时要是取对数以后就会变为-inf。要是这样反向传播几步我们可能会发现自己屏幕有一堆的nan。 尽管我们需要计算指数函数但是我们最终会在计算交叉熵损失的时候会取他们的对数。尽管通过将softmax和交叉熵结合在一起可以避免反向传播过程中可能会困扰我们的数值稳定性问题。如下面的式子 l o g ( y ^ j ) l o g ( e x p ( o j − m a x ( o k ) ) ∑ k e x p ( o k − m a x ( o k ) ) ) l o g ( e x p ( o j − m a x ( o k ) ) ) − l o g ( ∑ k e x p ( o k − m a x ( o k ) ) ) o j − m a x ( o k ) − l o g ( ∑ k e x p ( o k − m a x ( o k ) ) ) log(\hat{y}_j)log(\frac{exp(o_j-max(o_k))}{\sum_kexp(o_k-max(o_k))})\\ log(exp(o_j-max(o_k)))-log(\sum_kexp(o_k-max(o_k)))\\ o_j-max(o_k)-log(\sum_kexp(o_k-max(o_k))) log(y^j)log(∑kexp(ok−max(ok))exp(oj−max(ok)))log(exp(oj−max(ok)))−log(k∑exp(ok−max(ok)))oj−max(ok)−log(k∑exp(ok−max(ok))) 通过上式我们避免了计算单独的exp(o-max(o))而是直接使用o-max(o)。 因此我们计算交叉熵函数的时候传递的不是未规范化的预测o而不是softmax。 但是我们也希望保留传统的softmax函数以备我们要评估通过模型输出的概率。
交叉熵函数
在这里介绍一下交叉熵函数以用于上面推导所需的需求
torch.nn.CrossEntropyLoss(weightNone,ignore_index-100,reductionmean)交叉熵函数是将LogSoftMax和NLLLoss集成到一个类中通常用于多分类问题。其参数使用情况 ignore_index指定被忽略且对输入梯度没有贡献的目标值。 reductionstring类型的可选项可在[none,mean,sum]中选。none表示不降维返回和target一样的形状mean表示对一个batch的损失求均值sum表示对一个batch的损失求和。 weight是一个一维的张量包含n个元素分别代表n类的权重在训练样本不均衡时很有用默认为None 1当weightNone时损失函数计算方式为 loss(x,class)-log(exp(x[class])/Σexp(x[j]))-x[class]log(Σexp(x[j]) 2当weight被指定时损失函数计算方式为 loss(x,class)weight[class]×(-x[class]log(Σexp(x[j])) # 在交叉熵损失函数中传递未归一化的预测并同时计算softmax及其导数
loss nn.CrossEntropyLoss(reductionnone)优化算法
# 优化算法
trainer torch.optim.SGD(net.parameters(), lr0.1)训练
调用之前定义的训练函数来训练模型
# 调用之前的训练函数来训练模型
num_epochs 10
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)
d2l.plt.show()