Keras和Pytorch训练中的相同模型不同

时间:2019-08-21 19:11:21

标签: python machine-learning keras pytorch

我已经在Keras接受了一些培训,并试图移到PyTorch进行将来的工作。作为健全性检查,我决定从Keras复制一个成功的培训过程,以确保在Pytorch上一切正常。我正在使用相同的优化器,相同的数据,相同的批处理大小和纪元数来训练相同的模型体系结构。目标是对输入图像执行一些参数估计(基本上是非线性回归)。

Keras training results

keras模型在大约10个纪元内开始收敛。上面是模型预测与测试集中每个图像的实际值的关系图。

Pytorch training results

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中显式初始化了权重。最后,我发现如果替换行

,PyTorch模型在每种情况下都会收敛
x = x.view(-1, self.flattened_nfeatures)

x = x.permute(0, 2, 3, 1).reshape([-1, self.flattened_nfeatures])

我没有回答这个问题,因为我认为没有理由为什么拼合前的排列完全不会影响学习过程。如果有人能解释这种行为,我很想知道。

0 个答案:

没有答案
相关问题