交叉熵损失
交叉熵损失(也称为对数损失)衡量分类模型的性能,其输出是介于0和1之间的概率值。当预测概率与实际标签的差异增大时,损失也会增加。
对于二分类问题,交叉熵损失可以定义为:
L=−N1i=1∑N[yilog(pi)+(1−yi)log(1−pi)]
其中:
- $ N $ 是样本数量
- $ y_i $ 是实际标签(0或1)
- pi 是样本属于类别1的预测概率
对于多分类问题,交叉熵损失可以推广为:
L=−i=1∑Nc=1∑Cyi,clog(pi,c)
其中:
- C 是类别数量
- yi,c 是一个二进制指示器(0或1),如果类别标签 c 是样本 i 的正确分类
- pi,c 是样本 i 属于类别 c 的预测概率
交叉熵损失在机器学习中广泛用于训练分类模型,尤其是在神经网络中。
1 2 3 4 5 6 7 8 9 10
| def cross_entropy(y_hat, y):\ """交叉熵""" return - torch.log(y_hat[range(len(y_hat)), y])
def accuracy(y_hat, y): """计算预测正确的数量""" if len(y_hat.shape) > 1 and y_hat.shape[1] > 1: y_hat = y_hat.argmax(axis=1) cmp = y_hat.type(y.dtype) == y return float(cmp.type(y.dtype).sum())/len(y)
|
Softmax 函数
Softmax 函数是一种激活函数,常用于多分类问题的输出层。它将未归一化的输出(称为 logits)转换为归一化的概率分布。
Softmax 函数的定义如下:
σ(z)i=∑j=1Cezjezi
其中:
- z 是输入向量
- zi 是输入向量 z 的第 i 个分量
- C 是类别数量
- σ(z)i 是输入 z 对应类别 i 的概率
Softmax 函数的输出是一个概率分布,其所有元素的和为 1。这使得它非常适合用于多分类问题的模型输出。
在神经网络中,Softmax 函数通常与交叉熵损失一起使用,以优化模型的分类性能。
交叉熵损失对 Softmax 函数的求导
L=−j=1∑nyjlog(pj)=
−j=1∑nyjlog∑k=1nexp(ok)exp(oj)=
j=1∑nyjlogk=1∑nexp(ok)−j=1∑nyjoj=
logk=1∑nexp(ok)−j=1∑nyjoj
∂oj∂L=∑k=1nexp(ok)exp(oj)−yj=softmax(oj)−yj
其中:
- o是估计值,y 是预测值,log 是以 e为底数
Jacobian Matrix
1 2 3 4 5 6 7
| x = torch.tensor([-1, 2, 3, 4], dtype=torch.float32, requires_grad=True) y = x.softmax(dim=0) print(y) y[0].backward() print(x.grad)
|
其中:
yi=∑jexp(xj)exp(xi)
1 2 3 4 5 6 7 8
| u = torch.tensor(3.0, requires_grad=True) v = torch.tensor(4.0, requires_grad=True) f = u * v + u**2 + v**3 f.backward() print(u.grad) print(v.grad)
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| x = torch.rand(size=(3, 3), requires_grad=True) w1 = torch.rand(size=(3, 3), requires_grad=True) w2 = torch.rand(size=(3, 3), requires_grad=True) w3 = torch.rand(size=(3, 3), requires_grad=True) w4 = torch.rand(size=(3, 3), requires_grad=True) y = x * w1 z = x * w2 f = y + z g = f * w3 g.sum().backward() print(x.grad) print(w3 * (w1 + w2))
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| x = torch.tensor([1, 2, 3, 4], dtype=torch.float32, requires_grad=True) y = 100 * x loss = nn.MSELoss() optimizer = torch.optim.SGD([x], lr=0.01) optimizer.zero_grad() y.sum().backward() print(x) print(x.grad) optimizer.step() print(x)
|