Neural network Pytorch:NN函数逼近器,2合1输出

Neural network Pytorch:NN函数逼近器,2合1输出,neural-network,pytorch,Neural Network,Pytorch,[请注意以下编辑历史记录,因为主要问题陈述已更改。] 我们试图在pytorch中实现一个神经网络,它近似于函数f(x,y)=z。所以有两个实数作为输入,一个作为输出,因此我们需要在输入层有两个节点,在输出层有一个节点。我们构建了一个由5050个样本组成的测试集,在带有Tensorflow后端的Keras中获得了相当好的结果,有3个隐藏层,节点配置如下:2(in)-4-16-4-1(out);和所有隐藏层上的ReLU激活函数,线性输入和输出 现在,在Pytorch中,我们试图实现一个类似的网络,但

[请注意以下编辑历史记录,因为主要问题陈述已更改。]

我们试图在pytorch中实现一个神经网络,它近似于函数f(x,y)=z。所以有两个实数作为输入,一个作为输出,因此我们需要在输入层有两个节点,在输出层有一个节点。我们构建了一个由5050个样本组成的测试集,在带有Tensorflow后端的Keras中获得了相当好的结果,有3个隐藏层,节点配置如下:2(in)-4-16-4-1(out);和所有隐藏层上的ReLU激活函数,线性输入和输出

现在,在Pytorch中,我们试图实现一个类似的网络,但我们的损失函数仍在爆炸:它在最初的几个步骤中发生变化,然后收敛到10^7左右的某个值。在Keras中,我们的误差约为10%。我们已经尝试了不同的网络配置,但没有任何改进。也许有人可以看看我们的代码并提出任何修改建议

解释:tr_数据是一个列表,包含5050个2*1 numpy数组,这些数组是网络的输入。tr_标签是一个列表,包含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文件:

连同访问它的代码:

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()

您应该有兴趣指出
torch.nn
torch.nn.functional
之间的区别(请参阅)。从本质上讲,可能是由于不同的规范,您的反向传播图的执行可能不是100%正确

正如前面的评论所指出的,我建议定义您的层,包括激活。我个人最喜欢的方法是使用
nn.Sequential()
,它允许您指定链接在一起的多个操作,如下所示:

self.hidden1 = nn.Sequential(nn.Linear(DIM_IN, DIM_HIDDEN1), nn.ReLU())
然后稍后只需调用
self.hidden1
(无需将其包装在
F.relu()
中)

我还想问一下,你为什么不把注释过的
称为super(Net,self)。\uuu init\uuuu()
(这是通常推荐的方式)?
此外,如果这不能解决问题,您是否可以将Keras的代码进行比较?

为什么使用
F.tanh
而不是
ReLU
?为什么用函数代替模块?也就是说,为什么不使用
self.activation=nn.ReLU()
x=self.activation(self.hidden(x))
?此外,为什么要使用
size\u average=False
进行MSELoss?我建议您调整学习率并改变批量大小。是否可以共享数据集,以便我可以运行您的代码来查看发生了什么!!你好感谢您的帮助,我们将tanh改为ReLU,不再使用F,特别是将size_average改为True,这真的帮了大忙!损失函数现在约为12。很抱歉,我的意思是损失函数约为250。到目前为止比以前好了很多,但仍然不是很令人满意。你的keras模型在第一层有一个线性激活函数。你故意改变了吗?嗨!谢谢你的帮助。我们现在按照您的建议使用顺序代码,它工作得更好。我们也使用超级(网络,自我)。。。按照您的建议编写代码,但这不会有什么区别,因为python3会自动添加这些参数。我们的损失函数现在大约是12,这已经好得多了。我将用当前代码和keras代码更新我的原始帖子!对不起,我的意思是大约有250英镑,而且还有损失。到目前为止比以前好了很多,但仍然不太令人满意。