在 python 中实现 softmax 方法
implementing softmax method in python
我试图从 lightaime 的 Github 页面理解这段代码。它是一种向量化的 softmax 方法。让我困惑的是 "softmax_output[range(num_train), list(y)]"
这个表达式是什么意思?
def softmax_loss_vectorized(W, X, y, reg):
"""
Softmax loss function, vectorize implementation
Inputs have dimension D, there are C classes, and we operate on minibatches of N examples.
Inputs:
W: A numpy array of shape (D, C) containing weights.
X: A numpy array of shape (N, D) containing a minibatch of data.
y: A numpy array of shape (N,) containing training labels; y[i] = c means that X[i] has label c, where 0 <= c < C.
reg: (float) regularization strength
Returns a tuple of:
loss as single float
gradient with respect to weights W; an array of same shape as W
"""
# Initialize the loss and gradient to zero.
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)
为第一个轴创建一个索引,允许 select 每行中的特定值与第二个索引 - list(y)
。您可以在 numpy documentation for indexing.
中找到它
第一个索引 range_num 的长度等于 softmax_output
(= N
) 的第一个维度。它指向矩阵的每一行;然后对于每一行,它 select 的目标值通过索引第二部分的相应值 - list(y)
.
示例:
softmax_output = np.array( # dummy values, not softmax
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]]
)
num_train = 4 # length of the array
y = [2, 1, 0, 2] # a labels; values for indexing along the second axis
softmax_output[range(num_train), list(y)]
Out:
[3, 5, 7, 12]
所以,它 select 是第一行的第三个元素,第二行的第二个元素等等。这就是它的工作原理。
(p.s。我是否误解了你,你对“为什么”而不是“如何”感兴趣?)
此处的损失由以下等式定义
此处,对于 class 数据点所属的 y 为 1,对于所有其他 classes 为 0。因此我们只对数据点 class 的 softmax 输出感兴趣。因此上面的等式可以改写为
因此下面的代码表示上面的等式。
loss = -np.sum(np.log(softmax_output[range(num_train), list(y)]))
代码softmax_output[range(num_train), list(y)]
用于select各自classes的softmax输出。 range(num_train)
代表所有的训练样本,list(y)
代表各自的classes.
Mikhail 在他的回答中很好地解释了这个索引。
我试图从 lightaime 的 Github 页面理解这段代码。它是一种向量化的 softmax 方法。让我困惑的是 "softmax_output[range(num_train), list(y)]"
这个表达式是什么意思?
def softmax_loss_vectorized(W, X, y, reg):
"""
Softmax loss function, vectorize implementation
Inputs have dimension D, there are C classes, and we operate on minibatches of N examples.
Inputs:
W: A numpy array of shape (D, C) containing weights.
X: A numpy array of shape (N, D) containing a minibatch of data.
y: A numpy array of shape (N,) containing training labels; y[i] = c means that X[i] has label c, where 0 <= c < C.
reg: (float) regularization strength
Returns a tuple of:
loss as single float
gradient with respect to weights W; an array of same shape as W
"""
# Initialize the loss and gradient to zero.
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)
为第一个轴创建一个索引,允许 select 每行中的特定值与第二个索引 - list(y)
。您可以在 numpy documentation for indexing.
第一个索引 range_num 的长度等于 softmax_output
(= N
) 的第一个维度。它指向矩阵的每一行;然后对于每一行,它 select 的目标值通过索引第二部分的相应值 - list(y)
.
示例:
softmax_output = np.array( # dummy values, not softmax
[[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]]
)
num_train = 4 # length of the array
y = [2, 1, 0, 2] # a labels; values for indexing along the second axis
softmax_output[range(num_train), list(y)]
Out:
[3, 5, 7, 12]
所以,它 select 是第一行的第三个元素,第二行的第二个元素等等。这就是它的工作原理。
(p.s。我是否误解了你,你对“为什么”而不是“如何”感兴趣?)
此处的损失由以下等式定义
此处,对于 class 数据点所属的 y 为 1,对于所有其他 classes 为 0。因此我们只对数据点 class 的 softmax 输出感兴趣。因此上面的等式可以改写为
因此下面的代码表示上面的等式。
loss = -np.sum(np.log(softmax_output[range(num_train), list(y)]))
代码softmax_output[range(num_train), list(y)]
用于select各自classes的softmax输出。 range(num_train)
代表所有的训练样本,list(y)
代表各自的classes.
Mikhail 在他的回答中很好地解释了这个索引。