损失函数
损失函数-均方差
MSE mean square error
对均方差在做开根号,可以得到根方差
损失函数-交叉熵
Cross Entropy常用于分类任务分类任务中,网络输出经常是所有类别上的概率分布
公式
例子
- 数据会先过激活函数Softmax,做归一化处理得到类似 [1, 0, 0],然后再进入交叉熵函数
- 假设一个三分类任务,某样本的正确标签是第一类,则p = [1, 0, 0]
- 模型预测值假设为[0.5, 0.4, 0.1], 则交叉熵计算如下(log是以e为底的
2.71828):
代码
import torch
import torch.nn as nn
import numpy as np
#使用torch计算交叉熵
ce_loss = nn.CrossEntropyLoss()
#假设有3个样本,每个都在做3分类
pred = torch.FloatTensor([[0.3, 0.1, 0.3],
[0.9, 0.2, 0.9],
[0.5, 0.4, 0.2]])
# 正确的类别分别为1,2,0
target = torch.LongTensor([1,2,0])
# 计算交叉熵, 交叉熵损失的值域是 [0,+∞)。值越小,说明模型预测得越准确
loss = ce_loss(pred, target)
print("torch输出交叉熵:", loss, "\n")
"""
实现softmax函数
1、 np.exp(matrix) 将输入矩阵中的每个元素进行指数计算
2、 np.sum(np.exp(matrix), axis=1, keepdims=True) 对指数化后的矩阵进行行求和
axis=1表示沿着行的方向进行求和,keepdims=True表示保持求和后结果的维度是二维的
3、 exp_matrix / sum_of_rows 计算softmax概率
"""
def softmax(matrix):
exp_matrix = np.exp(matrix)
print("softmax归一化处理 矩阵每个值指数计算:", exp_matrix, "\n")
sum_of_rows = np.sum(exp_matrix, axis=1, keepdims=True)
print("softmax归一化处理 矩阵行求和:", sum_of_rows, "\n")
return exp_matrix / sum_of_rows
"""
将输入转化为onehot矩阵
将[1,2,0]转换为
[0, 1, 0]
[0, 0, 1]
[1, 0, 0]
"""
def to_one_hot(target, shape):
one_hot_target = np.zeros(shape)
for i, t in enumerate(target):
one_hot_target[i][t] = 1
return one_hot_target
# 手动实现交叉熵
def cross_entropy(pred, target):
print("=======================手动实现交叉熵=======================")
batch_size, class_num = pred.shape
print("输入矩阵的维度 batch_size:", batch_size, " class_num:",class_num, "\n")
print("输入矩阵 pred:", pred, "\n")
pred = softmax(pred)
print("softmax归一化处理 输出矩阵 pred:", pred, "\n")
print("正确类别 target:", target, "\n")
target = to_one_hot(target, pred.shape)
print("通过onehot矩阵后的正确类别 target:", target, "\n")
"""
计算交叉熵
np.log(pred) 计算预测概率的对数
target * np.log(pred) 逐元素相乘
- np.sum( ... , axis=1) 求和并取负, axis=1表示对每个样本的所有类别维度进行求和
"""
entropy = - np.sum(target * np.log(pred), axis=1)
"""
sum(entropy):将上一步得到的每个样本的损失值加在一起,得到这个批次的总损失。
/ batch_size:用总损失除以批次中的样本数量,得到平均损失。这个平均损失才是模型本次预测的最终损失值
"""
return sum(entropy) / batch_size
print("手动实现交叉熵:", cross_entropy(pred.numpy(), target.numpy()))
输出
torch输出交叉熵: tensor(1.0414)
=======================手动实现交叉熵=======================
输入矩阵的维度 batch_size: 3 class_num: 3
输入矩阵 pred: [[0.3 0.1 0.3]
[0.9 0.2 0.9]
[0.5 0.4 0.2]]
softmax归一化处理 矩阵每个值指数计算: [[1.3498588 1.105171 1.3498588]
[2.459603 1.2214028 2.459603 ]
[1.6487212 1.4918246 1.2214028]]
softmax归一化处理 矩阵行求和: [[3.8048885]
[6.140609 ]
[4.3619485]]
softmax归一化处理 输出矩阵 pred: [[0.3547696 0.2904608 0.3547696 ]
[0.40054712 0.19890581 0.40054712]
[0.37797815 0.34200877 0.2800131 ]]
正确类别 target: [1 2 0]
通过onehot矩阵后的正确类别 target: [[0. 1. 0.]
[0. 0. 1.]
[1. 0. 0.]]
手动实现交叉熵: 1.0413764715194702