[由于主要问题陈述已更改,请注意下面的“编辑历史记录”。
我们正在尝试在pytorch中实现一个神经网络,该网络近似函数f(x,y)= z。因此,有两个实数作为输入,一个为输出,因此我们希望在输入层中有2个节点,在输出层中有一个节点。我们构建了一个包含5050个样本的测试集,并在具有Tensorflow后端的Keras中完成了该任务,效果很好,其中3个隐藏层的节点配置如下:2(in)-4-16-4-1(out);和ReLU激活功能在所有隐藏层上起作用,在输入和输出上呈线性。
现在在Pytorch中,我们尝试实现一个类似的网络,但是损失函数实际上仍在爆炸:它在前几个步骤中发生变化,然后收敛到大约10 ^ 7的某个值。在Keras,我们有大约10%的错误。我们已经尝试了不同的网络配置,而没有任何改进。也许有人可以看看我们的代码并提出任何建议?
要说明:tr_data是一个列表,包含5050个2 * 1 numpy数组,它们是网络的输入。 tr_labels是一个列表,包含5050个数字,这是我们要学习的输出。 loadData()仅加载这两个列表。
import torch.nn as nn
import torch.nn.functional as F
BATCH_SIZE = 5050
DIM_IN = 2
DIM_HIDDEN_1 = 4
DIM_HIDDEN_2 = 16
DIM_HIDDEN_3 = 4
DIM_OUT = 1
LEARN_RATE = 1e-4
EPOCH_NUM = 500
class Net(nn.Module):
def __init__(self):
#super(Net, self).__init__()
super().__init__()
self.hidden1 = nn.Linear(DIM_IN, DIM_HIDDEN_1)
self.hidden2 = nn.Linear(DIM_HIDDEN_1, DIM_HIDDEN_2)
self.hidden3 = nn.Linear(DIM_HIDDEN_2, DIM_HIDDEN_3)
self.out = nn.Linear(DIM_HIDDEN_3, DIM_OUT)
def forward(self, x):
x = F.relu(self.hidden1(x))
x = F.tanh(self.hidden2(x))
x = F.tanh(self.hidden3(x))
x = self.out(x)
return x
model = Net()
loss_fn = nn.MSELoss(size_average=False)
optimizer = torch.optim.Adam(model.parameters(), lr=LEARN_RATE)
tr_data,tr_labels = loadData()
tr_data_torch = torch.zeros(BATCH_SIZE, DIM_IN)
tr_labels_torch = torch.zeros(BATCH_SIZE, DIM_OUT)
for i in range(BATCH_SIZE):
tr_data_torch[i] = torch.from_numpy(tr_data[i])
tr_labels_torch[i] = tr_labels[i]
for t in range(EPOCH_NUM):
labels_pred = model(tr_data_torch)
loss = loss_fn(labels_pred, tr_labels_torch)
#print(t, loss.item())
optimizer.zero_grad()
loss.backward()
optimizer.step()
我不得不说,这些是我们在Pytorch迈出的第一步,所以如果有一些明显的愚蠢错误,请原谅我。感谢您的帮助或提示, 谢谢!
编辑1 --------------------------------------------- ---------------------
在评论和答案之后,我们改进了代码。现在,“损失”函数首次具有合理的值,约为250。我们的新类定义如下:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
#super().__init__()
self.hidden1 = nn.Sequential(nn.Linear(DIM_IN, DIM_HIDDEN_1), nn.ReLU())
self.hidden2 = nn.Sequential(nn.Linear(DIM_HIDDEN_1, DIM_HIDDEN_2), nn.ReLU())
self.hidden3 = nn.Sequential(nn.Linear(DIM_HIDDEN_2, DIM_HIDDEN_3), nn.ReLU())
self.out = nn.Linear(DIM_HIDDEN_3, DIM_OUT)
def forward(self, x):
x = self.hidden1(x)
x = self.hidden2(x)
x = self.hidden3(x)
x = self.out(x)
return x
和损失函数:
loss_fn = nn.MSELoss(size_average=True, reduce=True)
正如我们之前所说,在具有tensorflow后端的keras中,我们已经获得了令人满意的结果。丢失功能约为30,具有类似的网络配置。我在这里分享我们的keras代码的基本部分(!):
model = Sequential()
model.add(Dense(4, activation="linear", input_shape=(2,)))
model.add(Dense(16, activation="relu"))
model.add(Dense(4, activation="relu"))
model.add(Dense(1, activation="linear" ))
model.summary()
model.compile ( loss="mean_squared_error", optimizer="adam", metrics=["mse"] )
history=model.fit ( np.array(tr_data), np.array(tr_labels), \
validation_data = ( np.array(val_data), np.array(val_labels) ),
batch_size=50, epochs=200, callbacks = [ cbk ] )
感谢您的所有帮助!如果还有人提出改善网络的建议,我们将为此感到高兴。正如有人已经要求数据一样,我们要在此处共享一个pickle文件:
https://mega.nz/#!RDYxSYLY!P4a9mEDtZ7A5Bl7ZRjRk8EzLXQt2gyURa3wN3NCWFPA
连同访问它的代码:
import pickle
f=open("data.pcl","rb")
tr_data=pickle.load ( f )
tr_labels=pickle.load ( f )
val_data=pickle.load ( f )
val_labels=pickle.load ( f )
f.close()
答案 0 :(得分:0)
您应该指出torch.nn
和torch.nn.functional
之间的区别(请参阅here)。从本质上讲,由于规格不同,反向传播图可能执行不正确100%。
正如以前的评论者所指出的,我建议定义包括激活的层。我个人最喜欢的方法是使用nn.Sequential()
,它允许您指定链接在一起的多个操作,如下所示:
self.hidden1 = nn.Sequential(nn.Linear(DIM_IN, DIM_HIDDEN1), nn.ReLU())
,然后稍后简单地调用self.hidden1
(而无需将其包装在F.relu()
中)。
我也可以问一下为什么您不拨打带注释的super(Net, self).__init__()
(这是通常推荐的方式)吗?
此外,如果那不能解决问题,您是否可以在比较中共享Keras的代码?