Отсутствие разреженного решения с регуляризацией L1 в Pytorch - PullRequest
0 голосов
/ 27 апреля 2018

Я пытаюсь реализовать регуляризацию L1 на первом уровне простой нейронной сети (1 скрытый слой). Я изучил некоторые другие сообщения о StackOverflow, которые применяют регуляризацию l1 с использованием Pytorch, чтобы выяснить, как это должно быть сделано (ссылки: Добавление регуляризации L1 / L2 в PyTorch? , В Pytorch как добавить L1 регуляризатор активаций? ). Независимо от того, насколько сильно я увеличиваю лямбду (параметр силы регуляризации l1), я не получаю истинные нули в первой весовой матрице. С чего бы это? (Код ниже)

import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np

class Network(nn.Module):
    def __init__(self,nf,nh,nc):
        super(Network,self).__init__()
        self.lin1=nn.Linear(nf,nh)
        self.lin2=nn.Linear(nh,nc)

    def forward(self,x):
        l1out=F.relu(self.lin1(x))
        out=F.softmax(self.lin2(l1out))
        return out, l1out

def l1loss(layer):
    return torch.norm(layer.weight.data, p=1)

nf=10
nc=2
nh=6
learningrate=0.02
lmbda=10.
batchsize=50

net=Network(nf,nh,nc)

crit=nn.MSELoss()
optimizer=torch.optim.Adagrad(net.parameters(),lr=learningrate)


xtr=torch.Tensor(xtr)
ytr=torch.Tensor(ytr)
#ytr=torch.LongTensor(ytr)
xte=torch.Tensor(xte)
yte=torch.LongTensor(yte)
#cyte=torch.Tensor(yte)

it=200
for epoch in range(it):
    per=torch.randperm(len(xtr))
    for i in range(0,len(xtr),batchsize):
        ind=per[i:i+batchsize]
        bx,by=xtr[ind],ytr[ind]            
        optimizer.zero_grad()
        output, l1out=net(bx)
#        l1reg=l1loss(net.lin1)    
        loss=crit(output,by)+lmbda*l1loss(net.lin1)
        loss.backward()
        optimizer.step()
    print('Epoch [%i/%i], Loss: %.4f' %(epoch+1,it, np.float32(loss.data.numpy())))

corr=0
tot=0
for x,y in list(zip(xte,yte)):
    output,_=net(x)
    _,pred=torch.max(output,-1)
    tot+=1 #y.size(0)
    corr+=(pred==y).sum()
print(corr)

Примечание: данные имеют 10 функций (2 класса и 800 обучающих выборок), и только первые 2 имеют отношение (по замыслу), поэтому можно предположить, что истинные нули должны быть достаточно легкими для изучения.

1 Ответ

0 голосов
/ 27 апреля 2018

Использование layer.weight.data удаляет параметр (который является переменной PyTorch) из его контекста автоматического дифференцирования, делая его постоянным, когда оптимизатор принимает градиенты. Это приводит к нулевым градиентам и что потери L1 не рассчитываются.

Если вы удалите .data, норма вычисляется для переменной PyTorch, и градиенты должны быть правильными.

Для получения дополнительной информации о механике автоматического дифференцирования PyTorch см. Эту статью документов или это руководство .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...