[PyTorch][Numpy][Softmax]计算概率

softmax是常用的分类器之一,其一大特点就是输出每个类别的分类概率。之前已经学习和使用过softmax,在这里小结计算概率实现

计算公式

\[ \text{Softmax}(x_{i}) = \frac{exp(x_i)}{\sum_j exp(x_j)} \]

为了防止指数函数\(exp(x)\)对线性操作的结果进行归一化,从而有可能会造成数值溢出,额外乘以一个常数C

\[ \text{Softmax}(x_{i}) = \frac{Cexp(x_i)}{C\sum_j exp(x_j)} =\frac{exp(x_i+\log C)}{\sum_j exp(x_j+ \log C)} \]

设置C为线性操作结果最大值负数\(logC=−\max x\),就能够将向量\(x\)的取值范围降低,最大值为\(0\),避免数值不稳定

numpy实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np

def softmax(x):
"""
softmax归一化计算
:param x: 大小为(m, k)
:return: 大小为(m, k)
"""
# 数值稳定性考虑,减去最大值
x -= np.atleast_2d(np.max(x, axis=1)).T
exps = np.exp(x)
return exps / np.atleast_2d(np.sum(exps, axis=1)).T


if __name__ == '__main__':
x = np.array([[0.3232, -1.341]])
print(x.shape)

scores = softmax(x)
print(scores)
########### 输出
(1, 2)
[[0.840801 0.159199]]

pytorch实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import torch
import numpy as np

def softmax(x):
"""
softmax归一化计算
:param x: 大小为(m, k)
:return: 大小为(m, k)
"""
x -= torch.unsqueeze(torch.max(x, 1)[0], 1)
exps = torch.exp(x)
return exps / torch.unsqueeze(torch.sum(exps, dim=1), 1)


if __name__ == '__main__':
x = np.array([[0.3232, -1.341]])
print(x.shape)

scores = softmax(torch.from_numpy(x))
print(scores)
############# 输出
(1, 2)
tensor([[0.8408, 0.1592]], dtype=torch.float64)

torch.nn.functional同时提供了函数softmax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import torch
import numpy as np

if __name__ == '__main__':
# 数据格式为[N, K]
# N表示个数
# K表示类别数
x = np.array([[0.3232, -1.341]])
print(x.shape)
scores = torch.softmax(torch.from_numpy(x), dim=1)
print(scores)
# 数据格式为[K]
x = np.array([0.3232, -1.341])
print(x.shape)
scores = torch.softmax(torch.from_numpy(x), dim=0)
print(scores)
####################### 输出
(1, 2)
tensor([[0.8408, 0.1592]], dtype=torch.float64)
(2,)
tensor([0.8408, 0.1592], dtype=torch.float64)

相关阅读