我在尝试理解来自lightaime的Github页面上的这段代码。这是一个向量化的Softmax方法。让我困惑的是”softmax_output[range(num_train), list(y)]”
这个表达式的意思是什么?
def softmax_loss_vectorized(W, X, y, reg): """ Softmax损失函数,向量化实现 输入的维度为D,有C个类别,我们处理N个样本的迷你批次。 输入: W: 形状为(D, C)的numpy数组,包含权重。 X: 形状为(N, D)的numpy数组,包含一个迷你批次的数据。 y: 形状为(N,)的numpy数组,包含训练标签;y[i] = c表示X[i]的标签为c,其中0 <= c < C。 reg: (浮点数)正则化强度 返回一个元组: 单个浮点数的损失 相对于权重W的梯度;与W形状相同的数组 """ # 初始化损失和梯度为零。 loss = 0.0 dW = np.zeros_like(W) num_classes = W.shape[1] num_train = X.shape[0] scores = X.dot(W) shift_scores = scores - np.max(scores, axis = 1).reshape(-1,1) softmax_output = np.exp(shift_scores)/np.sum(np.exp(shift_scores), axis = 1).reshape(-1,1) loss = -np.sum(np.log(softmax_output[range(num_train), list(y)])) loss /= num_train loss += 0.5* reg * np.sum(W * W) dS = softmax_output.copy() dS[range(num_train), list(y)] += -1 dW = (X.T).dot(dS) dW = dW/num_train + reg* W return loss, dW
回答:
这个表达式的意思是:切片一个形状为(N, C)
的数组softmax_output
,只提取与训练标签y
相关的数值。
二维numpy.array
可以使用两个包含适当值的列表进行切片(即它们不应该引起索引错误)
range(num_train)
为第一轴创建了一个索引,允许使用第二个索引list(y)
在每一行中选择特定的值。你可以在numpy索引文档中找到相关信息。
第一个索引range_num的长度等于softmax_output
的第一维(= N
)。它指向矩阵的每一行;然后对于每一行,通过第二个索引部分list(y)
的相应值选择目标值。
示例:
softmax_output = np.array( # 虚拟值,不是Softmax [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])num_train = 4 # 数组的长度y = [2, 1, 0, 2] # 标签;用于沿第二轴索引的值softmax_output[range(num_train), list(y)]Out:[3, 5, 7, 12]
所以,它从第一行中选择第三个元素,从第二行中选择第二个元素等等。这就是它的工作原理。
(附注:我误解了你的意思,你是想问“为什么”而不是“如何”吗?)