为何Numpy中两种SVM损失计算赋值方式结果不同?
问题:两种SVM损失计算写法结果不同的原因
以下是用户的SVM损失计算代码片段:
def svm_loss(x, y): """ Computes the loss and gradient using for multiclass SVM classification. Inputs: - x: Input data, of shape (N, C) where x[i, j] is the score for the jth class for the ith input. - y: Vector of labels, of shape (N,) where y[i] is the label for x[i] and 0 <= y[i] < C Returns a tuple of: - loss: Scalar giving the loss - dx: Gradient of the loss with respect to x """ loss, dx = None, None ########################################################################### # TODO: Copy over your solution from A1. ########################################################################### # *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)***** # 구현 (2023-09-01) N = len(y) x = x - x[np.arange(N),y][:,np.newaxis] + 1 # this part x = np.maximum(0, x) loss = (np.sum(x) - N) / N # *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
用户发现将上述代码中的x = x - x[np.arange(N),y][:,np.newaxis] + 1替换为x -= (x[np.arange(N),y][:,np.newaxis] - 1)后,计算结果不同,询问原因。
核心原因:原地修改的副作用与测试场景的影响
从数学表达式上看,两种写法理论上等价:
- 写法1:
x = x - x_label + 1(其中x_label = x[np.arange(N),y][:,np.newaxis]) - 写法2:
x -= (x_label - 1)展开后为x = x - x_label + 1,和写法1完全一致
但实际运行结果不同,大概率是以下两种情况:
1. 测试时未重置输入数组x
如果在测试时,你复用了同一个x数组先测试写法1,再测试写法2:
- 写法1是重新赋值:创建一个新数组并覆盖局部变量
x,原始输入的x不会被修改 - 写法2是原地修改:直接修改输入的
x数组本身
这会导致测试写法2时,x已经是写法1修改后的结果,而非原始输入,自然得到不同的计算结果。
2. 数组视图与副本的差异(极端场景)
如果输入的x是某个大数组的视图(比如通过切片、非整数索引方式得到的数组),原地修改x会同时修改原始的大数组;而重新赋值的写法会创建独立的新数组,后续计算基于新数组,两者的计算上下文不同也会导致结果差异。
验证方法
每次测试前都重新初始化输入数组x,确保两种写法使用的是完全相同的原始输入,此时两种写法的计算结果(包括x的值和loss)应该完全一致。
内容的提问来源于stack exchange,提问作者sanguineman
相关产品推荐
相关产品推荐

