Python Pytorch简单模型没有改进
我正在制作一个简单的PyTorch神经网络来近似x=[0,2pi]上的正弦函数。这是一个简单的体系结构,我使用不同的深度学习库来测试我是否理解如何使用它。未经训练的神经网络总是产生一条水平直线,而经过训练的神经网络则在y=0时产生一条直线。通常,它总是在y=(函数的平均值)处生成一条直线。这让我相信它的前支柱部分有问题,因为未经训练时,边界不应该只是一条直线。以下是网络的代码:Python Pytorch简单模型没有改进,python,machine-learning,neural-network,pytorch,Python,Machine Learning,Neural Network,Pytorch,我正在制作一个简单的PyTorch神经网络来近似x=[0,2pi]上的正弦函数。这是一个简单的体系结构,我使用不同的深度学习库来测试我是否理解如何使用它。未经训练的神经网络总是产生一条水平直线,而经过训练的神经网络则在y=0时产生一条直线。通常,它总是在y=(函数的平均值)处生成一条直线。这让我相信它的前支柱部分有问题,因为未经训练时,边界不应该只是一条直线。以下是网络的代码: class Net(nn.Module): def __init__(self): super(N
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.model = nn.Sequential(
nn.Linear(1, 20),
nn.Sigmoid(),
nn.Linear(20, 50),
nn.Sigmoid(),
nn.Linear(50, 50),
nn.Sigmoid(),
nn.Linear(50, 1)
)
def forward(self, x):
x = self.model(x)
return x
这是训练循环
def train(net, trainloader, valloader, learningrate, n_epochs):
net = net.train()
loss = nn.MSELoss()
optimizer = torch.optim.SGD(net.parameters(), lr = learningrate)
for epoch in range(n_epochs):
for X, y in trainloader:
X = X.reshape(-1, 1)
y = y.view(-1, 1)
optimizer.zero_grad()
outputs = net(X)
error = loss(outputs, y)
error.backward()
#net.parameters() net.parameters() * learningrate
optimizer.step()
total_loss = 0
for X, y in valloader:
X = X.reshape(-1, 1).float()
y = y.view(-1, 1)
outputs = net(X)
error = loss(outputs, y)
total_loss += error.data
print('Val loss for epoch', epoch, 'is', total_loss / len(valloader) )
它被称为:
net = Net()
losslist = train(net, trainloader, valloader, .0001, n_epochs = 4)
其中trainloader和valloader是培训和验证装载机。谁能帮我看看这有什么问题吗?我知道这不是学习速度,因为这是我在其他框架中使用的速度,我也知道这不是我使用SGD或sigmoid激活函数的事实,尽管我怀疑错误在激活函数的某个地方
有人知道如何解决这个问题吗?谢谢。在玩了一些超参数、修改网络和更改优化器(遵循极好的配方)一段时间后,我最终将行
优化器=torch.optim.SGD(net.parameters(),lr=learningrate)
更改为优化器=torch.optim.Adam(net.parameters())
(使用了优化器参数),运行100个历元,批大小等于1
使用了以下代码(仅在CPU上测试):
Adam优化器的结果:
SGD优化器的结果:
通常,它总是在y=(函数的平均值)处生成一条直线
通常,这意味着NN到目前为止只成功地训练了最后一层。正如ViniciusArruda在这里所示,您需要对其进行更长时间的培训或进行更好的优化
编辑:进一步解释。。当只训练了最后一层时,NN有效地尝试猜测输出y,而不知道输入X。在这种情况下,它能做出的最佳猜测是平均值。这样,它可以将其MSE损失降至最低
import torch
import torch.nn as nn
from torch.utils import data
import numpy as np
import matplotlib.pyplot as plt
# for reproducibility
torch.manual_seed(0)
np.random.seed(0)
class Dataset(data.Dataset):
def __init__(self, init, end, n):
self.n = n
self.x = np.random.rand(self.n, 1) * (end - init) + init
self.y = np.sin(self.x)
def __len__(self):
return self.n
def __getitem__(self, idx):
x = self.x[idx, np.newaxis]
y = self.y[idx, np.newaxis]
return torch.Tensor(x), torch.Tensor(y)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.model = nn.Sequential(
nn.Linear(1, 20),
nn.Sigmoid(),
nn.Linear(20, 50),
nn.Sigmoid(),
nn.Linear(50, 50),
nn.Sigmoid(),
nn.Linear(50, 1)
)
def forward(self, x):
x = self.model(x)
return x
def train(net, trainloader, valloader, n_epochs):
loss = nn.MSELoss()
# Switch the two following lines and run the code
# optimizer = torch.optim.SGD(net.parameters(), lr = 0.0001)
optimizer = torch.optim.Adam(net.parameters())
for epoch in range(n_epochs):
net.train()
for x, y in trainloader:
optimizer.zero_grad()
outputs = net(x).view(-1)
error = loss(outputs, y)
error.backward()
optimizer.step()
net.eval()
total_loss = 0
for x, y in valloader:
outputs = net(x)
error = loss(outputs, y)
total_loss += error.data
print('Val loss for epoch', epoch, 'is', total_loss / len(valloader) )
net.eval()
f, (ax1, ax2) = plt.subplots(1, 2, sharey=True)
def plot_result(ax, dataloader):
out, xx, yy = [], [], []
for x, y in dataloader:
out.append(net(x))
xx.append(x)
yy.append(y)
out = torch.cat(out, dim=0).detach().numpy().reshape(-1)
xx = torch.cat(xx, dim=0).numpy().reshape(-1)
yy = torch.cat(yy, dim=0).numpy().reshape(-1)
ax.scatter(xx, yy, facecolor='green')
ax.scatter(xx, out, facecolor='red')
xx = np.linspace(0.0, 3.14159*2, 1000)
ax.plot(xx, np.sin(xx), color='green')
plot_result(ax1, trainloader)
plot_result(ax2, valloader)
plt.show()
train_dataset = Dataset(0.0, 3.14159*2, 100)
val_dataset = Dataset(0.0, 3.14159*2, 30)
params = {'batch_size': 1,
'shuffle': True,
'num_workers': 4}
trainloader = data.DataLoader(train_dataset, **params)
valloader = data.DataLoader(val_dataset, **params)
net = Net()
losslist = train(net, trainloader, valloader, n_epochs = 100)