Python 支持GPU的Levenberg-Marquardt算法

Python 支持GPU的Levenberg-Marquardt算法,python,matlab,optimization,levenberg-marquardt,neupy,Python,Matlab,Optimization,Levenberg Marquardt,Neupy,对于浅层神经网络,LM算法表现得非常好 然而,似乎只有MatLab和pyrenn(Python包)有一个健壮的实现。这两种实现的一个问题是它们没有GPU支持。我还尝试了neupy(一个python包),但它并不健壮,当您尝试为更长的历元或大型数据集进行训练时,它会失败。你们知道一个很好的LM python包,可以使用GPU来训练NN吗 我不确定这样的实现是否会对任何东西有用,除了最简单的网络,计算Hessian是非常不切实际的。然而,我认为在pytorch中为浅层网络实现Levenberg-Ma

对于浅层神经网络,LM算法表现得非常好


然而,似乎只有MatLab和pyrenn(Python包)有一个健壮的实现。这两种实现的一个问题是它们没有GPU支持。我还尝试了neupy(一个python包),但它并不健壮,当您尝试为更长的历元或大型数据集进行训练时,它会失败。你们知道一个很好的LM python包,可以使用GPU来训练NN吗

我不确定这样的实现是否会对任何东西有用,除了最简单的网络,计算Hessian是非常不切实际的。然而,我认为在pytorch中为浅层网络实现Levenberg-Marquardt其实并不难。至少,即使您的实现不是最优的,与CPU版本相比,您仍然会获得一些速度提升。这是一个在GPU上运行的非常快速、因而非常不完美/次优的示例。在
1080ti
上,大小为
3x20x20
的输入的加速比约为3倍(我目前没有免费的GPU来测试更大的输入)。但是,如果您对损失函数有先验知识(例如,如果它是最小二乘法,并且您知道Hessian可以近似为
2*Jacobian^t*Jacobian
),那么下面代码的一些变体可能有用:

import torch
import numpy as np
import functools
import matplotlib.pyplot as plt

def LM(model,loss,n_iter=30):

    alpha=1e-3
    loss_hist=[]
    for i in range(n_iter):
        model.train()
        out=model(toy_input).unsqueeze(1)
        loss_out=loss(out)
        prev_loss=loss_out.item()
        gradients=torch.autograd.grad(loss_out, model.parameters(), create_graph=True)

        model.eval()
        Hessian, g_vector=eval_hessian(gradients, model)

        dx=-1(alpha*torch.eye(Hessian.shape[-1]).cuda()+Hessian).inverse().mm(g_vector).detach()

        cnt=0
        model.zero_grad()

        for p in model.parameters():

            mm=torch.Tensor([p.shape]).tolist()[0]
            num=int(functools.reduce(lambda x,y:x*y,mm,1))
            p.requires_grad=False
            p+=dx[cnt:cnt+num,:].reshape(p.shape)
            cnt+=num
            p.requires_grad=True


        out=model(toy_input).unsqueeze(1)
        loss_out=loss(out)

        if loss_out<prev_loss:
            print("Successful iteration")
            loss_hist.append(loss_out)
            alpha/=10
        else:
            print("Augmenting step size")
            alpha*=10
            cnt=0
            for p in model.parameters():

                mm=torch.Tensor([p.shape]).tolist()[0]
                num=int(functools.reduce(lambda x,y:x*y,mm,1))
                p.requires_grad=False
                p-=dx[cnt:cnt+num,:].reshape(p.shape)
                cnt+=num
                p.requires_grad=True

    return loss_hist 



def eval_hessian(loss_grad, model):
    cnt = 0
    for g in loss_grad:
        g_vector = g.contiguous().view(-1) if cnt == 0 else torch.cat([g_vector,     g.contiguous().view(-1)])
        cnt = 1
    l = g_vector.size(0)
    hessian = torch.zeros(l, l).cuda()
    for idx in range(l):
        grad2rd = torch.autograd.grad(g_vector[idx], model.parameters(), create_graph=True)
        cnt = 0
        for g in grad2rd:
            g2 = g.contiguous().view(-1) if cnt == 0 else torch.cat([g2, g.contiguous().view(-1)])
            cnt = 1
        hessian[idx] = g2
    return hessian, g_vector.unsqueeze(1)

def toy_loss(vec):
    return vec.transpose(0,1).mm(vec)

class toy_model(torch.nn.Module):

    def __init__(self,in_c,width,height):

        super().__init__()

        self.cnv=torch.nn.Conv2d(in_c,1,3,1,padding=1)
        self.lin=torch.nn.Linear(1*width*height,16)

    def forward(self,tns):

        out=self.cnv(tns)
        out=self.lin(out.view(-1))
        return out

if __name__=="__main__":

    H=20
    W=20
    toy_input=torch.rand(1,3,H,W).cuda()
    toy_mdl=toy_model(3,W,H)
    toy_mdl.cuda()

    loss_hist=LM(toy_mdl,lambda x:toy_loss(x))
导入火炬
将numpy作为np导入
导入功能工具
将matplotlib.pyplot作为plt导入
def LM(型号,损耗,n_iter=30):
α=1e-3
损失历史=[]
对于范围内的i(n_iter):
模型列车()
输出=模型(玩具输入)。取消查询(1)
损耗=损耗(损耗)
上一次损失=损失。项目()
渐变=torch.autograd.grad(丢失,model.parameters(),create\u graph=True)
model.eval()
Hessian,g_矢量=评估Hessian(梯度,模型)
dx=-1(alpha*torch.eye(Hessian.shape[-1]).cuda()+Hessian.inverse().mm(g_向量).detach()
cnt=0
模型0_梯度()
对于model.parameters()中的p:
mm=火炬张量([p.shape]).tolist()[0]
num=int(functools.reduce(λx,y:x*y,mm,1))
p、 需要_grad=False
p+=dx[cnt:cnt+num,:]。重塑(p.shape)
cnt+=num
p、 需要_grad=True
输出=模型(玩具输入)。取消查询(1)
损耗=损耗(损耗)

如果loss_超过neupy,那么您的代码在什么地方可用吗?@itdxer给您(LM在笔记本底部):我遇到的两个问题是崩溃和不可逆矩阵。。对于同一个问题,Matlab没有任何问题。PyTorch对我来说是一个新事物。我会试着玩它,看看它会怎么样。我完全同意基于Hessian的方法对于DNN是无效的。对于我的问题,由于我有MSE损失函数和浅层前馈神经网络,LM给出了更好的结果。