我正在学习 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=)
我真的迷路了。这个不行吗?
因此,就您而言,请将
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
方法,因此在模型实例化中使用训练器方法不是一个好主意。
您的代码很好,但有两个问题:
resp = self.forward(feats_next)
,而应执行以下操作:resp = self(feats_next)
。不过,在您的示例中,两者都可以正常工作。但在更复杂的模型中,使用 forward
可能会导致问题,因为 forward
不会调用钩子和其他一些东西。更多相关内容这里。(感谢 Anurag 的有效回答)