PyTorch中softmax函数的使用详解
PyTorch中softmax函数的使用详解
softmax
softmax又称归一化指数函数。主要存在于两个包Package中,分别是:
torch.nn.Softmax(dim=None)
和
torch.nn.functional.softmax(input, dim=None, _stacklevel=3, dtype=None)
torch.nn.Softmax
torch.nn.Softmax中只有一个参数dim,用于制定归一化维度。其中,dim=0指代的是行,dim=1指代的是列。
import torch
import torch.nn as nn
input_0 = torch.Tensor([1, 2, 3, 4])
input_1 = torch.Tensor([[1, 2, 3, 4], [5, 6, 7, 8]])
# Parameter --- dim
softmax_0 = nn.Softmax(dim=0)
softmax_1 = nn.Softmax(dim=1)
# Output tensors
output_0 = softmax_0(input_0) # dim=0
output_1 = softmax_1(input_1) # dim=1
output_2 = softmax_0(input_1) # dim=0
# Print
print(output_0)
print(output_1)
print(output_2)
输出结果为:
tensor([0.0321, 0.0871, 0.2369, 0.6439])
tensor([[0.0321, 0.0871, 0.2369, 0.6439],
[0.0321, 0.0871, 0.2369, 0.6439]])
tensor([[0.0180, 0.0180, 0.0180, 0.0180],
[0.9820, 0.9820, 0.9820, 0.9820]])
torch.nn.functional.softmax
torch.nn.functional.softmax除了dim参数外,还多了一个input参数,用于输入张量tensor。
import torch
import torch.nn.functional as F
input_0 = torch.Tensor([1, 2, 3, 4])
input_1 = torch.Tensor([[1, 2, 3, 4], [5, 6, 7, 8]])
output_0 = F.softmax(input_0)
output_1 = F.softmax(input_1, dim=0)
output_2 = F.softmax(input_1, dim=1)
print(output_0)
print(output_1)
print(output_2)
输出结果为:
tensor([0.0321, 0.0871, 0.2369, 0.6439])
tensor([[0.0180, 0.0180, 0.0180, 0.0180],
[0.9820, 0.9820, 0.9820, 0.9820]])
tensor([[0.0321, 0.0871, 0.2369, 0.6439],
[0.0321, 0.0871, 0.2369, 0.6439]])
例如,在一个基于ConvNet的简单神经网络中,最后一层返回一个[-infinity, infinity]的值logits,通过softmax函数或层,将其收敛或映射到[0, 1],表示模型对每个类别的预测概率,dim参数指示需要为总和为1的维度。
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
print("Pytorch Version: ", torch.__version__)
import numpy as np
import matplotlib.pyplot as plt
# 首先定义一个基于ConvNet的简单神经网络
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 20, 5, 1)
self.conv2 = nn.Conv2d(20, 50, 5, 1)
self.fc1 = nn.Linear(4 * 4 * 50, 500)
self.fc2 = nn.Linear(500, 10)
def forward(self, x):
x = F.relu(self.conv1(x))
x = F.max_pool2d(x, 2, 2)
x = F.relu(self.conv2(x))
x = F.max_pool2d(x, 2, 2)
x = x.view(-1, 4 * 4 * 50) # 相当于reshape,展平特征向量
x = F.relu(self.fc1(x))
x = self.fc2(x)
return F.log_softmax(x, dim=1) # 得到概率值
softmax = nn.Softmax(dim=1)
pred_probab = softmax(logits)
softmax作用
它是二分类函数sigmoid在多分类上的推广,目的是将多分类的结果以概率的形式展现出来。
softmax的计算方法
Softmax将在负无穷到正无穷上的预测结果按照以下两步转换为概率值:
Step 1:预测的概率为非负数
下图为y=exp(x)的图像,可以知道指数函数的值域取值范围是零到正无穷。softmax第一步就是:将模型的预测结果转化到指数函数上,这样保证了概率的非负性。
Step 2:各种预测结果概率之和等于1
为了确保各个预测结果的概率之和等于1。我们只需要将转换后的结果进行归一化处理。方法是将转化后的结果除以所有转化后结果之和,可以理解为转化后结果占总数的百分比。这样就得到近似的概率。
例如,假如模型对一个三分类问题的预测结果为-3、1.5、2.7。
要用softmax将模型结果转为概率。
Step 1:
将预测结果转化为非负数
y1 = exp(x1) = exp(-3) = 0.05
y2 = exp(x2) = exp(1.5) = 4.48
y3 = exp(x3) = exp(2.7) = 14.88
Step 2:
各种预测结果概率之和等于1
z1 = y1/(y1+y2+y3) = 0.05/(0.05+4.48+14.88) = 0.0026
z2 = y2/(y1+y2+y3) = 4.48/(0.05+4.48+14.88) = 0.2308
z3 = y3/(y1+y2+y3) = 14.88/(0.05+4.48+14.88) = 0.7666
输入输出具体操作
分类任务
- 输入:x=torch.rand(1,C)(1是batchsize, C是类别数)
- torch运算:out=F.softmax(x, dim=-1)(在最后一维进行概率化)
- onnx 可视化:
分割任务
- 输入: x=torch.rand(1,C,M, M)(1是batchsize, C是类别数,M为特征图尺寸)
- torch运算:out=F.softmax(x, dim=1)(在C维进行概率化)
- onnx 可视化:(注意,中间会多出两个节点)
检测任务
anchor-free的方法:
- 其softmax操作和分割任务的类似。
anchor-base的方法,操作如下:
- 输入: x=torch.rand(N, C)(C是类别数,N 是anchor个数)
- torch运算:out=F.softmax(x, dim=-1)(在C维进行概率化)
- onnx 可视化:
In addition
对于log_softmax和softmax用法一模一样,但是输出结果不一样。对于一些较大的数可以采取log_softmax,来防止溢出。