前言
本系列主要是对pytorch基础知识学习的一个记录,尽量保持博客的更新进度和自己的学习进度。本人也处于学习阶段,博客中涉及到的知识可能存在某些问题,希望大家批评指正。另外,本博客中的有些内容基于吴恩达老师深度学习课程,我会尽量说明一下,但不敢保证全面。
一、问题描述
吴恩达老师的课后训练要求使用softmax层完成一个多分类,pytorch框架有封装好的softmax函数,记录一下softmax的使用以及踩过的一些坑。
二、torch.nn.Softmax
我们知道softmax其实主要包括两个部分:非线性激活和归一化。官方文档给出的解释为:

可以看出,初始化softmax层只需指定归一化的维度,并不关心你需要进行归一化的矩阵维度,但是我们知道输入到softmax的单个向量的维度其实应该等于我们需要分类的类别数,所以我们通常会在softmax层前面加一个线性层,使得线性层输出的单个样本向量维度等于类别数。
在之前的博客中有提及过,样本输入的维度为(n,单个样本向量维度),所以通常是一行表示一个样本。因此,在softmax层设置的dim的值为1,最好是具体问题具体分析,对自己模型的输入有充分了解。
self.softmax = torch.nn.Softmax(dim=1)
三、torch.nn.CrossEntropyLoss
在使用了softmax层做多分类后,我们使用的损失函数为交叉熵损失:
L(y,y_pred)=-y(i)*log(y_pred(i))
具体的公式推导我这里就不再细说,官方文档对torch.nn.CrossEntropyLoss的解释如下:

没有特殊要求一般都使用默认参数,初始化时不传入参数,当然也可以根据自己的需求具体设置参数。
loss_fn = torch.nn.CrossEntropyLoss()
从官方文档可以看出,CrossEntropyLoss也完成了非线性激活(和softmax不太一样,有log操作)和归一化的操作,但是我们在多分类模型最后的输出层通常来说是线性层+softmax,线性层将单个样本向量的维度转换为多分类的类别个数,softmax层完成非线性激活和归一化,CrossEntropyLoss和softmax层的操作有一定的重复。
因此,通常来说,我们在训练阶段直接将输出层的线性计算结果送入到CrossEntropyLoss中,不再通过softmax层。模型训练完成后,进行预测时会加上softmax层,因为softmax层不存在需要优化的参数,所以不参加训练并不会产生影响。
CrossEntropyLoss()的输入维度如下:

loss = loss_fn(y_pred, y)
根据官方文档的要求,这里的预测结果y_pred是二维的,实际标签y是一维的,我最开始用pytorch复现tensorflow的代码会报错,是因为在tensorflow中需要将实际标签值y转换成One-hot的形式,使得y和y_pred的维度相同。
计算loss的时候可能报错,需要将y转换成long类型:

loss = loss_fn(y_pred, y.long())
总结
以上就是我使用pytorch的softmax进行多分类的一个总结,需要注意的有两点:
1.softmax的dim赋值
2.模型训练阶段使用CrossEntropyLoss()时,不需要使用softmax层