我已经在Keras接受了一些培训,并试图移到PyTorch进行将来的工作。作为健全性检查,我决定从Keras复制一个成功的培训过程,以确保在Pytorch上一切正常。我正在使用相同的优化器,相同的数据,相同的批处理大小和纪元数来训练相同的模型体系结构。目标是对输入图像执行一些参数估计(基本上是非线性回归)。
keras模型在大约10个纪元内开始收敛。上面是模型预测与测试集中每个图像的实际值的关系图。
pytorch模型的收敛速度不那么快,当它停滞不前时,它正在预测所有输入的近似统一值。上图是经过10个纪元后的情节。随着训练的继续,预测范围逐渐变小,并且开始为每个输入选择0.01左右。
下面是keras模型和训练过程的代码,其中已经加载了xtrain,ytrain。
nchannels = 32
kernel_size = 3
input_size = 64
cnn = Sequential()
cnn.add(
Conv2D(
nchannels,
kernel_size=(kernel_size, kernel_size),
input_shape=[input_size, input_size, 1]
)
)
cnn.add(Activation('tanh'))
cnn.add(MaxPooling2D((2, 2)))
cnn.add(Dropout(0.15))
cnn.add(Flatten())
cnn.add(Dense(32, activation='tanh'))
cnn.add(Dense(1, activation='linear'))
optimizer = Adam(lr=1e-5, eps=1e-7)
cnn.compile(optimizer=optimizer, loss='mse')
hist = cnn.fit(
x=xtrain,
y=ytrain,
batch_size=32,
epochs=10
)
接下来是pytorch模型代码:
class CNN_1Layer(nn.Module):
def __init__(self, nchannels=32, kernel_size=3, input_size=64):
super(CNN_1Layer, self).__init__()
self.flattened_nfeatures = \
int(nchannels * (input_size-2)**2 / 4)
self.conv1 = nn.Conv2d(1,
nchannels,
kernel_size=kernel_size)
self.tanh1 = nn.Tanh()
self.pool = nn.MaxPool2d(kernel_size=2)
self.dropout = nn.Dropout2d(p=0.15)
self.fc1 = nn.Linear(self.flattened_nfeatures, 32)
self.tanh2 = nn.Tanh()
self.fc2 = nn.Linear(32, 1)
def forward(self, x):
x = self.conv1(x)
x = self.tanh1(x)
x = self.pool(x)
x = self.dropout(x)
x = x.view(-1, self.flattened_nfeatures)
x = self.fc1(x)
x = self.tanh2(x)
x = self.fc2(x)
return x
cnn = CNN_1Layer(input_size=crop_size)
criterion = nn.MSELoss()
optimizer = Adam(params=cnn.parameters(), lr=1e-5, eps=1e-7)
#dataset is a wrapper around xtrain and ytrain from the keras segment
loader = DataLoader(
dataset,
batch_size=32
)
for i in range(10):
training_loss = 0.0
for j, data in enumerate(loader):
inputs, labels = data
optimizer.zero_grad()
outputs = cnn(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
我一直在对它们进行并排训练,但我不清楚是什么原因导致它们表现得如此不同。
更新
从将Keras模型的初始权重复制到PyTorch模型开始,我花了更多时间进行调查。由于某种原因,这使得两个模型仅在拟合过程中数据未打乱时才收敛。然后,我使用具有相同效果的xavier_uniform_
在PyTorch中显式初始化了权重。最后,我发现如果替换行
x = x.view(-1, self.flattened_nfeatures)
与
x = x.permute(0, 2, 3, 1).reshape([-1, self.flattened_nfeatures])
我没有回答这个问题,因为我认为没有理由为什么拼合前的排列完全不会影响学习过程。如果有人能解释这种行为,我很想知道。