本文为李沐《动手学深度学习笔记》,用于个人复习记录学习历程,适用于初学者
目录
从回归到分类
回归 | 分类 |
单值连续输出 | 多个输出 |
输出预测数值 | 输出i为第i类的置信度 |
与真实值的区别作为损失 | 通常使用交叉熵损失 |
对类别进行编码
定义Softmax操作
实现softmax由三个步骤组成:
-
对每个项求幂(使用
exp
); -
对每一行求和(小批量中每个样本是一行),得到每个样本的规范化常数;
-
将每一行除以其规范化常数,确保结果的和为1。
表达式为:
def softmax(X):
X_exp = torch.exp(X)
partition = X_exp.sum(1, keepdim=True)
return X_exp / partition
正如上述代码,对于任何随机输入,
我们将每个元素变成一个非负数。 此外,依据概率原理,每行总和为1。
给出一个简单的例子用于理解:
X = torch.normal(0, 1, (2, 5))
X_prob = softmax(X)
print(X)
print(X_prob)
print(X_prob.sum(1)) #参数0是按列求和,参数1是按行求和
其输出为:
tensor([[-0.2170, -0.1885, -1.1823, -1.5760, 0.2740], [ 0.2934, 0.1912, 1.1831, -0.7785, -0.1515]]) tensor([[0.2325, 0.2392, 0.0886, 0.0597, 0.3799], [0.1880, 0.1697, 0.4575, 0.0643, 0.1205]]) tensor([1., 1.])
交叉熵损失(重点)
由于我们是对类别进行了一位有效编码(正确的类为1,其他为0),故而交叉熵损失函数变成了真实正确的那类的概率区负对数。
这里我们用一个简单的函数实现交叉熵损失:
def cross_entropy(y_hat, y):
return - torch.log(y_hat[range(len(y_hat)), y])
配一个简单的例子用于理解:
y = torch.tensor([0, 2])
y_hat = torch.tensor([[0.1, 0.3, 0.6],
[0.3, 0.2, 0.5]])
y_hat[[0, 1], y] #输出tensor([0.1000, 0.5000])
cross_entropy(y_hat, y) #输出tensor([2.3026, 0.6931])
在这里,总共有3类,对两个问题进行了分类,y表示正确的类别,在这里是第0、2类,y_hat表示第一次第二次对问题的分类给出的概率,y_hat[[0, 1], y]表示实际上正确的类被预测为正确的类的概率,cross_entropy(y_hat, y)表示交叉熵,可以看到,第一个较大而第二个较小,这是符合实际的。