我正在计算数千个渐变,并希望在Python中对计算进行矢量化。上下文是SVM,损失函数是铰链损失。 Y是Mx1,X是MxN,w是Nx1。
L(w) = lam/2 * ||w||^2 + 1/m Sum i=1:m ( max(0, 1-y[i]X[i]w) )
这个梯度是
grad = lam*w + 1/m Sum i=1:m {-y[i]X[i].T if y[i]*X[i]*w < 1, else 0}
不是循环求和的每个元素并评估max函数,是否可以对此进行向量化?我想使用像np.where这样的东西,如下面的
grad = np.where(y*X.dot(w) < 1, -X.T.dot(y), 0)
这不起作用,因为条件为真,-X.T * y是错误的维度。
编辑:列表理解版本,想知道是否有更清洁或更优化的方式
def grad(X,y,w,lam):
# cache y[i]*X[i].dot(w), each row of Xw is multiplied by a single element of y
yXw = y*X.dot(w)
# cache y[i]*X[i], note each row of X is multiplied by a single element of y
yX = X*y[:,np.newaxis]
# return the average of this max function
return lam*w + np.mean( [-yX[i] if yXw[i] < 1 else 0 for i in range(len(y))] )
答案 0 :(得分:2)
你有两个向量A和B,并且你想要返回数组C,这样如果B [i] <1,则C [i] = A [i]。 1和0其他,所以你需要做的就是
C := A * sign(max(0, 1-B)) # suprisingly similar to the original hinge loss, right?:)
因为
因此,在您的代码中,它将类似于
A = (y*X.dot(w)).ravel()
B = (X*y[:,np.newaxis]).ravel()
C = A * np.sign(np.maximum(0, 1-B))