Pytorch简单线性Sigmoid网络不学习

问题描述 投票:0回答:2

我正在学习 pytorch,并尝试将网络训练为异或门。一切都进行得很顺利,但它就是不学习。它确实改变了它的权重,但它会收敛到每个输入的结果,这远远超出了预期结果。

我尝试过很多学习率和权重初始化。

因此输入是 A 门和 B 门,如果两者相等则应返回 1,否则应返回 0,如下所示:


    [0,0] => 1
    [0,1] => 0
    [1,0] => 0
    [1,1] => 1

这是我对模型建模和训练的尝试:


    导入火炬作为火炬
    将 torch.nn 导入为 nn
    
    网络类(nn.Module):
        
        def __init__(自身):
            超级(网络,自我).__init__()
            self.x1 = nn.Linear(2,4)
            self.s1 = nn.Sigmoid()
            self.x2 = nn.Linear(4,1)
            self.s2 = nn.Sigmoid()
        
        定义初始化(自身):
            nn.init.uniform_(self.x1.weight)
            nn.init.uniform_(self.x2.weight)
    
        def前锋(自我,功绩):
            f1 = torch.tensor(feats).float()
            xr1= 自身.x1(f1)
            xs1= self.s1(xr1)
            xr2= 自身.x2(xs1)
            输出 = self.s2(xr2)
            返回
    
        def 火车(自我,val_expected,feats_next):
            val_expected_tensor = torch.tensor(val_expected)
            标准 = nn.MSELoss()
            优化器 = torch.optim.SGD(self.parameters(), lr=0.01)
            def 闭包():
                优化器.zero_grad()
                resp = self.forward(feats_next)
                误差 = 标准(分别,val_expected_tensor)
                error.backward()
                返回错误
            优化器.step(闭包)
    
    网络=网络()
    .net.init()
    
    对于 ([0.,0.],[0.,1.],[1.,0.],[1.,1.]) 中的输入:
        响应=net.forward(输入)
        打印(响应)
    
    打印(“--火车开始-”)
    对于范围(1000)内的 i:
        net.train([1.],[0.,0.])
        net.train([0.],[1.,0.])
        net.train([0.],[0.,1.])
        net.train([1.],[1.,1.])
    print ("---火车结束---")
    
    对于 ([0.,0.],[0.,1.],[1.,0.],[1.,1.]) 中的输入:
        响应=net.forward(输入)
        打印(响应)

这是一次以 0.001 学习率进行 100000 次迭代的运行:


    张量([0.7726], grad_fn=)
    张量([0.7954], grad_fn=)
    张量([0.8229], grad_fn=)
    张量([0.8410], grad_fn=)
    --列车启动-
    *.........*........*.........*.........*......... *.........*........*.........*.........*.........
    ---火车结束---
    张量([0.6311], grad_fn=)
    张量([0.6459], grad_fn=)
    张量([0.6770], grad_fn=)
    张量([0.6906], grad_fn=)

我真的迷路了。这个不行吗?

pytorch artificial-intelligence reinforcement-learning
2个回答
1
投票

因此,就您而言,请将

train
方法保留在网络类之外。代码如下。

net = Network()
net.init()
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)
for input in ([0., 0.], [0., 1.], [1., 0.], [1., 1.]):
    response = net.forward(input)
    print (response)

def train(val_expected, feats_next, criterion, optimizer):
    val_expected_tensor = torch.tensor(val_expected)
    optimizer.zero_grad()
    resp = net.forward(feats_next)
    # print (resp)
    error = criterion(resp, val_expected_tensor)
    # print (error, resp, val_expected_tensor)
    error.backward()
    # print (error)
    optimizer.step()


print("--TRAIN START-")
for i in range(10000):
    train([1.], [0., 0.], criterion, optimizer)
    train([0.], [1., 0.], criterion, optimizer)
    train([0.], [0., 1.], criterion, optimizer)
    train([1.], [1., 1.], criterion, optimizer)
print("---TRAIN END---")

for input in ([0., 0.], [0., 1.], [1., 0.], [1., 1.]):
    response = net.forward(input)
    print(response)

结果如下:

tensor([0.9571], grad_fn=<SigmoidBackward>)
tensor([0.0414], grad_fn=<SigmoidBackward>)
tensor([0.0459], grad_fn=<SigmoidBackward>)
tensor([0.9621], grad_fn=<SigmoidBackward>)

我只是提高了学习率,而且

train
中有一个
nn.Module
方法,因此在模型实例化中使用训练器方法不是一个好主意。


0
投票

您的代码很好,但有两个问题:

  1. 对于这个问题你的学习率太低了。如果您设置 lr=1(而不是 0.01),您的原始代码将完美运行。
  2. 您应该避免执行
    resp = self.forward(feats_next)
    ,而应执行以下操作:
    resp = self(feats_next)
    。不过,在您的示例中,两者都可以正常工作。但在更复杂的模型中,使用
    forward
    可能会导致问题,因为
    forward
    不会调用钩子和其他一些东西。更多相关内容这里

(感谢 Anurag 的有效回答)

© www.soinside.com 2019 - 2024. All rights reserved.