def svm_loss(x, y): N = x.shape[0] correct_class_scores = x[np.arange(N), y] margins = np.maximum(0, x - correct_class_scores[:, np.newaxis] + 1.0) margins[np.arange(N), y] = 0 loss = np.sum(margins) / N num_pos = np.sum(margins > 0, axis=1) dx = np.zeros_like(x) dx[margins > 0] = 1 dx[np.arange(N), y] -= num_pos dx /= N return loss, dx def softmax_loss(x, y): probs = np.exp(x - np.max(x, axis=1, keepdims=True)) probs /= np.sum(probs, axis=1, keepdims=True) N = x.shape[0] loss = -np.sum(np.log(probs[np.arange(N), y])) / N dx = probs.copy() dx[np.arange(N), y] -= 1 dx /= N return loss, dx
时间: 2024-01-25 07:03:11 浏览: 132
这是两个常用的损失函数,SVM损失和Softmax损失。它们通常用于多分类问题中,其中$x$是一个矩阵,每一行代表一个样本的得分,$y$是一个向量,表示每个样本的真实标签。
SVM损失函数的实现中,首先计算出正确标签的得分(correct_class_scores),然后计算出每个样本的margin(间隔),$margins = max(0, x - correct_class_scores[:, np.newaxis] + 1.0)$。如果margin大于0,则样本被分类错误,贡献到损失函数中。将正确标签的margin设为0,然后将所有margin求和并除以样本个数,得到平均SVM损失。同时,还需要计算出输入$x$的梯度$dx$,$dx$的值为1或0,如果margin>0,则为1,否则为0。对于正确分类的那个类,需要将所有贡献给该类的梯度和减去$dx$中正值的个数,因为每个正值都对该类的梯度有贡献。
Softmax损失函数的实现中,首先将每个样本的得分减去该行得分的最大值,以防止指数爆炸,然后将得分转换成概率。计算交叉熵损失,$loss = -sum(log(probs[range(N), y])) / N$,其中probs是概率矩阵,$probs[i, j]$表示第$i$个样本被分为第$j$个类的概率。最后,计算输入$x$的梯度$dx$,$dx$的值为每个样本的概率减去1,然后除以样本个数。对于正确分类的那个类,由于$y$只有一个元素,因此只需要将对应位置的概率减去1即可。
需要注意的是,这里的实现是针对单个样本的输入$x$和输出$dout$,如果使用批量输入,则需要对每个样本进行计算。
阅读全文