对数回归损失的梯度

我正在尝试为日志回归编写小批量梯度下降。

对数回归损失的梯度

给出numpy矩阵X_batch(形状为(n_samples,n_features))和y_batch(形状为(n_samples,))。

天真的方法是编写循环:

def calc_loss_grad(self,X_batch,y_batch):
    n_samples,n_features = X_batch.shape
    loss_grad = np.zeros((n_features,))
    for i in range(n_samples):
        sigm = sigmoid(X_batch[i] @ self.weights)
        loss_grad += - (y_batch[i] - sigm) * X_batch[i]            
    return loss_grad

但是使用循环似乎是个坏主意。速度。还有更好的方法吗?没有循环的纯numpy?重写表达式以某种方式?

wwl776 回答:对数回归损失的梯度

请注意,此算法受内存带宽限制。如果您在较大的上下文(实际应用程序)中对此进行优化,则很有可能会实现更高的加速。

示例

import numpy as np

#https://stackoverflow.com/a/29863846/4045774
def sigmoid(x):  
    return np.exp(-np.logaddexp(0,-x))

def calc_loss_grad_1(weights,X_batch,y_batch):
    n_samples,n_features = X_batch.shape
    loss_grad = np.zeros((n_features,))
    for i in range(n_samples):
        sigm = sigmoid(X_batch[i,:] @ weights)
        loss_grad += - (y_batch[i] - sigm) * X_batch[i]            
    return loss_grad

def calc_loss_grad_2(weights,y_batch):
    sigm =-y_batch+sigmoid(X_batch@weights)          
    return sigm@X_batch

weights=np.random.rand(n_features)
X_batch=np.random.rand(n_samples,n_features)
y_batch=np.random.rand(n_samples)

#n_samples=int(1e5)
#n_features=int(1e4)
%timeit res=calc_loss_grad_1(weights,y_batch)
#1.79 s ± 35.8 ms per loop (mean ± std. dev. of 7 runs,1 loop each)
%timeit res=calc_loss_grad_2(weights,y_batch)
#539 ms ± 21.9 ms per loop (mean ± std. dev. of 7 runs,1 loop each)

#n_samples=int(1e3)
#n_features=int(1e2)
%timeit res=calc_loss_grad_1(weights,y_batch)
#3.68 ms ± 44.7 µs per loop (mean ± std. dev. of 7 runs,100 loops each)
%timeit res=calc_loss_grad_2(weights,y_batch)
#49.1 µs ± 503 ns per loop (mean ± std. dev. of 7 runs,10000 loops each) 
本文链接:https://www.f2er.com/3166965.html

大家都在问