【问题标题】:Converting Keras to Pytorch将 Keras 转换为 Pytorch
【发布时间】:2021-07-10 00:50:48
【问题描述】:

我正在尝试将以下模型转换为 pytorch:

def get_model():

    model = keras.models.Sequential()

    model.add(Conv2D(64, kernel_size=(3,3), activation='relu', padding='same', input_shape=(9,9,1)))
    model.add(BatchNormalization())
    model.add(Conv2D(64, kernel_size=(3,3), activation='relu', padding='same'))
    model.add(BatchNormalization())
    model.add(Conv2D(128, kernel_size=(1,1), activation='relu', padding='same'))

    model.add(Flatten())
    model.add(Dense(81*9))
    model.add(Reshape((-1, 9)))
    model.add(Activation('softmax'))
    
    return model

model = get_model()

adam = keras.optimizers.Adam(lr=.001)
model.compile(loss='sparse_categorical_crossentropy', optimizer=adam)

model.fit(x_train, y_train, batch_size=32, epochs=2)

来自https://github.com/shivaverma/Sudoku-Solver/blob/master/model.py

class Conv2dSame(torch.nn.Module):
def __init__(self, in_channels, out_channels, kernel_size, padding, bias=True, padding_layer=torch.nn.ReflectionPad2d):
    """It only support square kernels and stride=1, dilation=1, groups=1."""
    super(Conv2dSame, self).__init__()
    self.net = nn.Sequential(
        nn.Conv2d(in_channels, out_channels, kernel_size, bias=bias, padding=padding),
        nn.ReLU(True),
    )
def forward(self, x):
    return self.net(x)

CNN 类(torch.nn.Module):

def __init__(self, hidden_channels, batch_size):

    super(CNN, self).__init__()
    self.hidden_channels = hidden_channels
    self.batch_size = batch_size

    self.embed = nn.Sequential(
        
        Conv2dSame(1, hidden_channels, 3, 1),
        nn.BatchNorm2d(hidden_channels),
        Conv2dSame(hidden_channels, hidden_channels, 3, 1),
        nn.BatchNorm2d(hidden_channels),
        Conv2dSame(hidden_channels, 2*hidden_channels, 1, 0),

    )

    self.out = nn.Sequential( 
        
        nn.Linear(2*hidden_channels*81, 81*9),
        
    )

    self.softmax = nn.Softmax(dim=1)

def forward(self, x):
    embed = self.embed(x)
    embed = embed.view(-1, 2*self.hidden_channels*81)
    out = self.out(embed).view(-1,9,81)
    return self.softmax(out)

但它似乎并不适用:

model = CNN(hidden_channels=64,batch_size=32) # GCN(hidden_channels=64)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001) #0.01
criterion = nn.CrossEntropyLoss()

def train():

    model.train()

    for batch_i, data in tqdm(enumerate(train_loader)):  # Iterate in batches over the training dataset.

      optimizer.zero_grad()  # Clear gradients.

      unsolved = data[0]
      solved = data[1]

      out = model(unsolved) # data.x, data.edge_index, data.batch)  # Perform a single forward pass.
      loss = criterion(out, solved)  # Compute the loss.
      if batch_i % 100 == 0:
        print(loss)

      loss.backward()  # Derive gradients.
      optimizer.step()  # Update parameters based on gradients.

batch_size = 32 #64
num_epochs = 2

train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=0)

for _ in range(num_epochs):
  train()

我的损失一直停滞不前,而且我的准确性很差。我知道 keras 代码工作正常。如果我误解了 keras 代码的任何部分,请告诉我。或者,如果我的 pytorch 实现已关闭。我对 keras(和 pytorch)非常陌生。谢谢!

【问题讨论】:

  • 3 件快速的事情:1. 你的第一个代码是 [Conv - ReLU - batch norm],但是你的 pytorch 代码是 [Conv - batch norm - ReLU],2. 你在 batch norm 之前使用了偏差layer,一般不推荐,和3.你reshapes不一样,这是故意的吗?
  • relu 和 batchnorm 非常棒!我已经更新了我的代码,但它似乎仍然不起作用:/。重塑是故意的,因为 keras 似乎最后有通道,但 pytorch 首先有通道。就偏差而言,我很确定偏差也在 keras 代码中,不是吗?

标签: machine-learning keras pytorch


【解决方案1】:

我的尝试如下。在您的 keras 代码中,您将其挤压成不同的形状(-1,9),所以我假设您的标签也是这种格式。因此你需要在你的 pytorch 代码中做同样的事情。

import keras
from keras.layers import Activation
from keras.layers import Conv2D, BatchNormalization, Dense, Flatten, Reshape

def get_model_keras():

    model = keras.models.Sequential()

    model.add(Conv2D(64, kernel_size=(3,3), activation='relu', padding='same', input_shape=(9,9,1)))
    model.add(BatchNormalization())
    model.add(Conv2D(64, kernel_size=(3,3), activation='relu', padding='same'))
    model.add(BatchNormalization())
    model.add(Conv2D(128, kernel_size=(1,1), activation='relu', padding='same'))

    model.add(Flatten())
    model.add(Dense(81*9))
    model.add(Reshape((-1, 9)))
    model.add(Activation('softmax'))
    
    return model

import torch
from torch import nn
import torch.nn.functional as F
 
class get_model_pytorch(nn.Module):
    def __init__(self, in_channels, hidden_channels,kernel_size):
        super(get_model_pytorch, self).__init__()
        self.in_channels = in_channels
        self.hidden_channels = hidden_channels
        self.kernel_size = kernel_size

        self.embed = nn.Sequential(
            nn.Conv2d(self.in_channels,self.hidden_channels,
                      self.kernel_size,padding=self.kernel_size//2, bias=False),
            nn.ReLU(),
            nn.BatchNorm2d(self.hidden_channels),
            nn.Conv2d(self.hidden_channels,self.hidden_channels,
                      self.kernel_size,padding=self.kernel_size//2, bias=False),
            nn.ReLU(),
            nn.BatchNorm2d(self.hidden_channels),
            nn.Conv2d(self.hidden_channels,self.hidden_channels*2,
                      1,padding=0, bias=False),
            nn.ReLU()
            )      
        self.out = nn.Sequential(        
            nn.Linear(2*hidden_channels*81, 81*9),
            )
    def forward(self, x):
        embed = self.embed(x)
        embed = embed.view(-1, 2*self.hidden_channels*81)
        out = self.out(embed).view(-1,9)
        return F.softmax(out,dim=1)

【讨论】:

  • 这太好了,谢谢!我现在正在试一试。我不得不将这一行改回 out = self.out(embed).view(-1,9) -> out = self.out(embed).view(-1,9, 81) 因为我的目标是 [32 ,81] 并且它似乎与 nn.CrossEntropyLoss 一起工作的唯一方法。 (我很确定 keras 代码中的标签是不同的形状)
  • 好的,这意味着您应该将其更改为 .view(-1,81)。我假设您的批量大小是 32?
  • 它似乎在损失 1.58 附近略微收敛。这比我以前的要好,但是 keras 代码似乎从来没有真正停止到 ~0.6
  • 我正在尝试匹配您的 keras 代码,因此那里似乎存在不一致之处。我认为答案在于它处理损失的方式。
  • 当我将其更改为 .view(-1,81) 时,我得到 ValueError: Expected input batch_size (288) to match target batch_size (32)。
猜你喜欢
  • 1970-01-01
  • 2021-04-27
  • 1970-01-01
  • 2019-09-28
  • 2021-07-25
  • 2021-03-19
  • 2020-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多