Python 如何在PyTorch中实现ResNet50?

Python 如何在PyTorch中实现ResNet50?,python,neural-network,pytorch,conv-neural-network,cnn,Python,Neural Network,Pytorch,Conv Neural Network,Cnn,我在Coursera课程中通过deeplearning.ai学习NN,因为我的一个家庭作业是使用Keras实现ResNet50,但我认为Keras太高级了),并决定在更复杂的库中实现它-PyTorch。我录了下来,但出了点问题。请有人告诉我发生了什么,为什么在我将方法ResNet.parameters()放入Adam优化时,参数出现错误 类实现: class ResNet50(torch.nn.Module): def __init__(self, input_shape = (3, 9

我在Coursera课程中通过deeplearning.ai学习NN,因为我的一个家庭作业是使用Keras实现ResNet50,但我认为Keras太高级了),并决定在更复杂的库中实现它-PyTorch。我录了下来,但出了点问题。请有人告诉我发生了什么,为什么在我将方法ResNet.parameters()放入Adam优化时,参数出现错误

类实现:

class ResNet50(torch.nn.Module):
    def __init__(self, input_shape = (3, 96, 96), classes = 10):
        super(ResNet50, self).__init__()    
        """
        Implementation of the popular ResNet50 the following architecture:
        Conv2d -> BatchNorm -> ReLU -> MaxPool -> ConvBlock - > IdBlock*2 - > convBlock -> IdBlock*3 -> ConvBlock -> IdBlock*5 -> ConvBlock -> IdBlock*2 -> AvgPool -> FCLayer
    
        Arguments:
        input_shape -- shape of the image of the dataset
        classes -- integer, number of classes    
        """
    
        self.input_shape = input_shape
        self.classes = classes
        self.relu = torch.nn.ReLU() 
        
    def identity_block(self, X, f, filters):
        # Notice that there is no any kind of Pooling.
        """
        Implementation of the identity block.
    
        Arguments:
        X -- input tensor of shape(m , n_H_prev, n_W_prev, n_C_prev)
        f -- integer, specifying the shape of the middle CONV's window for the main path
        filters -- python list of integers, defining the number of filters in the CONV layers of the main path
        
        Returns:
        X -- output of the identity block, tensor of shape (n_H, n_W, n_C)
        """
    
        # Retrieve Filters
        F1, F2, F3 = filters
    
        # Save the input value. It will be needed later to be added back to the main path.
        X_shortcut = X
    
        # First component of the main path
        X = torch.nn.Conv2d(in_channels=X.shape[0], out_channels=F1, kernel_size=1, stride=1, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F1)(X)
        X = self.relu(X)
    
        # Second component of the main path
        X = torch.nn.Conv2d(in_channels=F1, out_channels=F2, kernel_size=f, stride=1, padding=f//2)(X)
        X = torch.nn.BatchNorm2d(num_features=F2)(X)
        X = self.relu(X)
    
        # Third component of the main path
        X = torch.nn.Conv2d(in_channels=F2, out_channels=F3, kernel_size=1, stride=1, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F3)(X)
        # X = self.relu(X) - NO RELU, notice this!
    
        # Final step: Add shortcut value to main path, and pass it through a ReLU
        X = X_shortcut + X
        X = self.relu(X)

        return X 
    def convolution_block(self, X, f, filters, s = 2):
        # Notice that here is no any kind of Pooling.
        """
        Implementation of the convolutional block.
    
        Arguments:
        X -- input tensor of shape (m, n_H_prev, n_W_prev, n_C_prev)
        f -- integer, specifying the shape of middle CONV's window for main path
        filters -- python list of integers, defining the number of filters in the CONV layers of the main path
        s -- integer, specifying the stride to be used
    
        Returns:
        X -- output of the convolution block, tensor of shape (n_H, n_W, n_C)
        """
    
        # Retrieve Filters
        F1, F2, F3 = filters
    
        # Save the input value
        X_shortcut = X
    
        # First component of the main path
        X = torch.nn.Conv2d(in_channels=X.shape[0], out_channels=F1, kernel_size=1, stride=s, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F1)(X)
        X = self.relu(X)
    
        # Second component of the main path
        X = torch.nn.Conv2d(in_channels=F1, out_channels=F2, kernel_size=f, stride=1, padding=f//2)(X)
        X = torch.nn.BatchNorm2d(num_features=F2)(X)
        X = self.relu(X)
    
        # Third component of the main path
        X = torch.nn.Conv2d(in_channels=F2, out_channels=F3, kernel_size=1, stride=1, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F2)(X)
        # X = self.relu(X) - NO RELU, notice this!
    
        # Shortcut path
        X_shortcut = torch.nn.Conv2d(in_channels=X_shortcut.shape[0], out_channels=F3, kernel_size=1, stride=s, padding=0)(X)
        X_shortcut = torch.nn.BatchNorm2d(num_features=F3)(X)
        # X = self.relu(X) - NO RELU, notice this!
    
        # Final step: Add shortcut value to main path, and pass it through a ReLU
        X = X_shortcut + X
        X = self.relu(X)
    
        return X
    def forward(self, X):
        """
        Forward propogation by the following architecture:
        Conv2d -> BatchNorm -> ReLU -> MaxPool -> ConvBlock - > IdBlock*2 - > convBlock -> IdBlock*3 -> ConvBlock -> IdBlock*5 -> ConvBlock -> IdBlock*2 -> AvgPool -> FCLayer
    
        Arguments:
        X -- input data for Network that needed to be propagated
    
        Returns:
        X -- output of the ResNet50, that propagated through it
        """
    
        # # Define the input as a tensor with shape self.input_shape
        # X = torch.zeros_like(self.input_shape)
    
        # Stage 1 
        X = torch.nn.Conv2d(in_channels=3, out_channels=64, kernel_size=7, stride=2, padding=3)(X) # 96x96x3 -> 48x48x64
        X = torch.nn.BatchNorm2d(num_features=64)(X)
        X = self.relu(X)
        X = torch.nn.MaxPool2d(kernel_size=3, stride=2, padding=0)(X) # 48x48x64 -> 23x23x64
    
        # Stage 2
        X = self.convolution_block(X, f=3, filters=[64, 64, 256], s=1) # 23x23x64 -> 23x23x256
        X = self.identity_block(X, 3, [64, 64, 256]) # same
        X = self.identity_block(X, 3, [64, 64, 256]) # same
    
        # Stage 3
        X = self.convolution_block(X, f=3, filters=[128, 128, 512], s=2) # 23x23x256 -> 12x12x512
        X = self.identity_block(X, 3, [128, 128, 512]) # same
        X = self.identity_block(X, 3, [128, 128, 512]) # same
        X = self.identity_block(X, 3, [128, 128, 512]) # same
    
        # Stage 4
        X = self.convolution_block(X, f=3, filters=[256, 256, 1024], s=2) # 12x12x512 -> 6x6x1024
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
    
        # Stage 5
        X = self.convolution_block(X, f=3, filters=[512, 512, 2048], s=2) # 6x6x1024 -> 3x3x2048
        X = self.identity_block(X, 3, [512, 512, 2048]) # same
        X = self.identity_block(X, 3, [512, 512, 2048]) # same
    
        # AvgPool
        X = torch.nn.AvgPool2d(kernel_size=2)(X) # 3x3x2048 -> 2x2x2048
    
        # Output layer
        X = X.reshape(X.shape[0], -1)
        X = torch.nn.Linear(in_features=X.shape[1], out_features=self.classes)
        X = torch.nn.Softmax(X)
    
        return X
NNet = ResNet50()

device = torch.device('cuda:0' if torch.cuda.is_available else 'cpu')
NNet = NNet.to(device)

loss = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(NNet.parameters(), lr = 0.001)

random.seed(k)
np.random.seed(k)
torch.manual_seed(k)
torch.cuda.manual_seed(k)
torch.backends.cudnn.deterministic = True
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-18-71ee8a51c6b2> in <module>()
      5 
      6 loss = torch.nn.CrossEntropyLoss()
----> 7 optimizer = torch.optim.Adam(NNet.parameters(), lr = 0.001)
      8 
      9 random.seed(k)

1 frames
/usr/local/lib/python3.6/dist-packages/torch/optim/optimizer.py in __init__(self, params, defaults)
     44         param_groups = list(params)
     45         if len(param_groups) == 0:
---> 46             raise ValueError("optimizer got an empty parameter list")
     47         if not isinstance(param_groups[0], dict):
     48             param_groups = [{'params': param_groups}]

ValueError: optimizer got an empty parameter list
下一个脚本:

class ResNet50(torch.nn.Module):
    def __init__(self, input_shape = (3, 96, 96), classes = 10):
        super(ResNet50, self).__init__()    
        """
        Implementation of the popular ResNet50 the following architecture:
        Conv2d -> BatchNorm -> ReLU -> MaxPool -> ConvBlock - > IdBlock*2 - > convBlock -> IdBlock*3 -> ConvBlock -> IdBlock*5 -> ConvBlock -> IdBlock*2 -> AvgPool -> FCLayer
    
        Arguments:
        input_shape -- shape of the image of the dataset
        classes -- integer, number of classes    
        """
    
        self.input_shape = input_shape
        self.classes = classes
        self.relu = torch.nn.ReLU() 
        
    def identity_block(self, X, f, filters):
        # Notice that there is no any kind of Pooling.
        """
        Implementation of the identity block.
    
        Arguments:
        X -- input tensor of shape(m , n_H_prev, n_W_prev, n_C_prev)
        f -- integer, specifying the shape of the middle CONV's window for the main path
        filters -- python list of integers, defining the number of filters in the CONV layers of the main path
        
        Returns:
        X -- output of the identity block, tensor of shape (n_H, n_W, n_C)
        """
    
        # Retrieve Filters
        F1, F2, F3 = filters
    
        # Save the input value. It will be needed later to be added back to the main path.
        X_shortcut = X
    
        # First component of the main path
        X = torch.nn.Conv2d(in_channels=X.shape[0], out_channels=F1, kernel_size=1, stride=1, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F1)(X)
        X = self.relu(X)
    
        # Second component of the main path
        X = torch.nn.Conv2d(in_channels=F1, out_channels=F2, kernel_size=f, stride=1, padding=f//2)(X)
        X = torch.nn.BatchNorm2d(num_features=F2)(X)
        X = self.relu(X)
    
        # Third component of the main path
        X = torch.nn.Conv2d(in_channels=F2, out_channels=F3, kernel_size=1, stride=1, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F3)(X)
        # X = self.relu(X) - NO RELU, notice this!
    
        # Final step: Add shortcut value to main path, and pass it through a ReLU
        X = X_shortcut + X
        X = self.relu(X)

        return X 
    def convolution_block(self, X, f, filters, s = 2):
        # Notice that here is no any kind of Pooling.
        """
        Implementation of the convolutional block.
    
        Arguments:
        X -- input tensor of shape (m, n_H_prev, n_W_prev, n_C_prev)
        f -- integer, specifying the shape of middle CONV's window for main path
        filters -- python list of integers, defining the number of filters in the CONV layers of the main path
        s -- integer, specifying the stride to be used
    
        Returns:
        X -- output of the convolution block, tensor of shape (n_H, n_W, n_C)
        """
    
        # Retrieve Filters
        F1, F2, F3 = filters
    
        # Save the input value
        X_shortcut = X
    
        # First component of the main path
        X = torch.nn.Conv2d(in_channels=X.shape[0], out_channels=F1, kernel_size=1, stride=s, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F1)(X)
        X = self.relu(X)
    
        # Second component of the main path
        X = torch.nn.Conv2d(in_channels=F1, out_channels=F2, kernel_size=f, stride=1, padding=f//2)(X)
        X = torch.nn.BatchNorm2d(num_features=F2)(X)
        X = self.relu(X)
    
        # Third component of the main path
        X = torch.nn.Conv2d(in_channels=F2, out_channels=F3, kernel_size=1, stride=1, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F2)(X)
        # X = self.relu(X) - NO RELU, notice this!
    
        # Shortcut path
        X_shortcut = torch.nn.Conv2d(in_channels=X_shortcut.shape[0], out_channels=F3, kernel_size=1, stride=s, padding=0)(X)
        X_shortcut = torch.nn.BatchNorm2d(num_features=F3)(X)
        # X = self.relu(X) - NO RELU, notice this!
    
        # Final step: Add shortcut value to main path, and pass it through a ReLU
        X = X_shortcut + X
        X = self.relu(X)
    
        return X
    def forward(self, X):
        """
        Forward propogation by the following architecture:
        Conv2d -> BatchNorm -> ReLU -> MaxPool -> ConvBlock - > IdBlock*2 - > convBlock -> IdBlock*3 -> ConvBlock -> IdBlock*5 -> ConvBlock -> IdBlock*2 -> AvgPool -> FCLayer
    
        Arguments:
        X -- input data for Network that needed to be propagated
    
        Returns:
        X -- output of the ResNet50, that propagated through it
        """
    
        # # Define the input as a tensor with shape self.input_shape
        # X = torch.zeros_like(self.input_shape)
    
        # Stage 1 
        X = torch.nn.Conv2d(in_channels=3, out_channels=64, kernel_size=7, stride=2, padding=3)(X) # 96x96x3 -> 48x48x64
        X = torch.nn.BatchNorm2d(num_features=64)(X)
        X = self.relu(X)
        X = torch.nn.MaxPool2d(kernel_size=3, stride=2, padding=0)(X) # 48x48x64 -> 23x23x64
    
        # Stage 2
        X = self.convolution_block(X, f=3, filters=[64, 64, 256], s=1) # 23x23x64 -> 23x23x256
        X = self.identity_block(X, 3, [64, 64, 256]) # same
        X = self.identity_block(X, 3, [64, 64, 256]) # same
    
        # Stage 3
        X = self.convolution_block(X, f=3, filters=[128, 128, 512], s=2) # 23x23x256 -> 12x12x512
        X = self.identity_block(X, 3, [128, 128, 512]) # same
        X = self.identity_block(X, 3, [128, 128, 512]) # same
        X = self.identity_block(X, 3, [128, 128, 512]) # same
    
        # Stage 4
        X = self.convolution_block(X, f=3, filters=[256, 256, 1024], s=2) # 12x12x512 -> 6x6x1024
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
    
        # Stage 5
        X = self.convolution_block(X, f=3, filters=[512, 512, 2048], s=2) # 6x6x1024 -> 3x3x2048
        X = self.identity_block(X, 3, [512, 512, 2048]) # same
        X = self.identity_block(X, 3, [512, 512, 2048]) # same
    
        # AvgPool
        X = torch.nn.AvgPool2d(kernel_size=2)(X) # 3x3x2048 -> 2x2x2048
    
        # Output layer
        X = X.reshape(X.shape[0], -1)
        X = torch.nn.Linear(in_features=X.shape[1], out_features=self.classes)
        X = torch.nn.Softmax(X)
    
        return X
NNet = ResNet50()

device = torch.device('cuda:0' if torch.cuda.is_available else 'cpu')
NNet = NNet.to(device)

loss = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(NNet.parameters(), lr = 0.001)

random.seed(k)
np.random.seed(k)
torch.manual_seed(k)
torch.cuda.manual_seed(k)
torch.backends.cudnn.deterministic = True
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-18-71ee8a51c6b2> in <module>()
      5 
      6 loss = torch.nn.CrossEntropyLoss()
----> 7 optimizer = torch.optim.Adam(NNet.parameters(), lr = 0.001)
      8 
      9 random.seed(k)

1 frames
/usr/local/lib/python3.6/dist-packages/torch/optim/optimizer.py in __init__(self, params, defaults)
     44         param_groups = list(params)
     45         if len(param_groups) == 0:
---> 46             raise ValueError("optimizer got an empty parameter list")
     47         if not isinstance(param_groups[0], dict):
     48             param_groups = [{'params': param_groups}]

ValueError: optimizer got an empty parameter list
返回错误:

class ResNet50(torch.nn.Module):
    def __init__(self, input_shape = (3, 96, 96), classes = 10):
        super(ResNet50, self).__init__()    
        """
        Implementation of the popular ResNet50 the following architecture:
        Conv2d -> BatchNorm -> ReLU -> MaxPool -> ConvBlock - > IdBlock*2 - > convBlock -> IdBlock*3 -> ConvBlock -> IdBlock*5 -> ConvBlock -> IdBlock*2 -> AvgPool -> FCLayer
    
        Arguments:
        input_shape -- shape of the image of the dataset
        classes -- integer, number of classes    
        """
    
        self.input_shape = input_shape
        self.classes = classes
        self.relu = torch.nn.ReLU() 
        
    def identity_block(self, X, f, filters):
        # Notice that there is no any kind of Pooling.
        """
        Implementation of the identity block.
    
        Arguments:
        X -- input tensor of shape(m , n_H_prev, n_W_prev, n_C_prev)
        f -- integer, specifying the shape of the middle CONV's window for the main path
        filters -- python list of integers, defining the number of filters in the CONV layers of the main path
        
        Returns:
        X -- output of the identity block, tensor of shape (n_H, n_W, n_C)
        """
    
        # Retrieve Filters
        F1, F2, F3 = filters
    
        # Save the input value. It will be needed later to be added back to the main path.
        X_shortcut = X
    
        # First component of the main path
        X = torch.nn.Conv2d(in_channels=X.shape[0], out_channels=F1, kernel_size=1, stride=1, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F1)(X)
        X = self.relu(X)
    
        # Second component of the main path
        X = torch.nn.Conv2d(in_channels=F1, out_channels=F2, kernel_size=f, stride=1, padding=f//2)(X)
        X = torch.nn.BatchNorm2d(num_features=F2)(X)
        X = self.relu(X)
    
        # Third component of the main path
        X = torch.nn.Conv2d(in_channels=F2, out_channels=F3, kernel_size=1, stride=1, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F3)(X)
        # X = self.relu(X) - NO RELU, notice this!
    
        # Final step: Add shortcut value to main path, and pass it through a ReLU
        X = X_shortcut + X
        X = self.relu(X)

        return X 
    def convolution_block(self, X, f, filters, s = 2):
        # Notice that here is no any kind of Pooling.
        """
        Implementation of the convolutional block.
    
        Arguments:
        X -- input tensor of shape (m, n_H_prev, n_W_prev, n_C_prev)
        f -- integer, specifying the shape of middle CONV's window for main path
        filters -- python list of integers, defining the number of filters in the CONV layers of the main path
        s -- integer, specifying the stride to be used
    
        Returns:
        X -- output of the convolution block, tensor of shape (n_H, n_W, n_C)
        """
    
        # Retrieve Filters
        F1, F2, F3 = filters
    
        # Save the input value
        X_shortcut = X
    
        # First component of the main path
        X = torch.nn.Conv2d(in_channels=X.shape[0], out_channels=F1, kernel_size=1, stride=s, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F1)(X)
        X = self.relu(X)
    
        # Second component of the main path
        X = torch.nn.Conv2d(in_channels=F1, out_channels=F2, kernel_size=f, stride=1, padding=f//2)(X)
        X = torch.nn.BatchNorm2d(num_features=F2)(X)
        X = self.relu(X)
    
        # Third component of the main path
        X = torch.nn.Conv2d(in_channels=F2, out_channels=F3, kernel_size=1, stride=1, padding=0)(X)
        X = torch.nn.BatchNorm2d(num_features=F2)(X)
        # X = self.relu(X) - NO RELU, notice this!
    
        # Shortcut path
        X_shortcut = torch.nn.Conv2d(in_channels=X_shortcut.shape[0], out_channels=F3, kernel_size=1, stride=s, padding=0)(X)
        X_shortcut = torch.nn.BatchNorm2d(num_features=F3)(X)
        # X = self.relu(X) - NO RELU, notice this!
    
        # Final step: Add shortcut value to main path, and pass it through a ReLU
        X = X_shortcut + X
        X = self.relu(X)
    
        return X
    def forward(self, X):
        """
        Forward propogation by the following architecture:
        Conv2d -> BatchNorm -> ReLU -> MaxPool -> ConvBlock - > IdBlock*2 - > convBlock -> IdBlock*3 -> ConvBlock -> IdBlock*5 -> ConvBlock -> IdBlock*2 -> AvgPool -> FCLayer
    
        Arguments:
        X -- input data for Network that needed to be propagated
    
        Returns:
        X -- output of the ResNet50, that propagated through it
        """
    
        # # Define the input as a tensor with shape self.input_shape
        # X = torch.zeros_like(self.input_shape)
    
        # Stage 1 
        X = torch.nn.Conv2d(in_channels=3, out_channels=64, kernel_size=7, stride=2, padding=3)(X) # 96x96x3 -> 48x48x64
        X = torch.nn.BatchNorm2d(num_features=64)(X)
        X = self.relu(X)
        X = torch.nn.MaxPool2d(kernel_size=3, stride=2, padding=0)(X) # 48x48x64 -> 23x23x64
    
        # Stage 2
        X = self.convolution_block(X, f=3, filters=[64, 64, 256], s=1) # 23x23x64 -> 23x23x256
        X = self.identity_block(X, 3, [64, 64, 256]) # same
        X = self.identity_block(X, 3, [64, 64, 256]) # same
    
        # Stage 3
        X = self.convolution_block(X, f=3, filters=[128, 128, 512], s=2) # 23x23x256 -> 12x12x512
        X = self.identity_block(X, 3, [128, 128, 512]) # same
        X = self.identity_block(X, 3, [128, 128, 512]) # same
        X = self.identity_block(X, 3, [128, 128, 512]) # same
    
        # Stage 4
        X = self.convolution_block(X, f=3, filters=[256, 256, 1024], s=2) # 12x12x512 -> 6x6x1024
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
        X = self.identity_block(X, 3, [256, 256, 1024]) # same
    
        # Stage 5
        X = self.convolution_block(X, f=3, filters=[512, 512, 2048], s=2) # 6x6x1024 -> 3x3x2048
        X = self.identity_block(X, 3, [512, 512, 2048]) # same
        X = self.identity_block(X, 3, [512, 512, 2048]) # same
    
        # AvgPool
        X = torch.nn.AvgPool2d(kernel_size=2)(X) # 3x3x2048 -> 2x2x2048
    
        # Output layer
        X = X.reshape(X.shape[0], -1)
        X = torch.nn.Linear(in_features=X.shape[1], out_features=self.classes)
        X = torch.nn.Softmax(X)
    
        return X
NNet = ResNet50()

device = torch.device('cuda:0' if torch.cuda.is_available else 'cpu')
NNet = NNet.to(device)

loss = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(NNet.parameters(), lr = 0.001)

random.seed(k)
np.random.seed(k)
torch.manual_seed(k)
torch.cuda.manual_seed(k)
torch.backends.cudnn.deterministic = True
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-18-71ee8a51c6b2> in <module>()
      5 
      6 loss = torch.nn.CrossEntropyLoss()
----> 7 optimizer = torch.optim.Adam(NNet.parameters(), lr = 0.001)
      8 
      9 random.seed(k)

1 frames
/usr/local/lib/python3.6/dist-packages/torch/optim/optimizer.py in __init__(self, params, defaults)
     44         param_groups = list(params)
     45         if len(param_groups) == 0:
---> 46             raise ValueError("optimizer got an empty parameter list")
     47         if not isinstance(param_groups[0], dict):
     48             param_groups = [{'params': param_groups}]

ValueError: optimizer got an empty parameter list
---------------------------------------------------------------------------
ValueError回溯(最近一次调用上次)
在()
5.
6损耗=火炬.nn.交叉熵()
---->7优化器=torch.optim.Adam(NNet.parameters(),lr=0.001)
8.
9.随机种子(k)
1帧
/usr/local/lib/python3.6/dist-packages/torch/optim/optimizer.py在__init___中(self,params,默认值)
44参数组=列表(参数)
45如果len(参数组)=0:
--->46 raise VALUELERROR(“优化器得到一个空参数列表”)
47如果不存在(参数组[0],dict):
48个参数组=[{'params':参数组}]
ValueError:优化器获取的参数列表为空

您的类没有任何参数,因此
.parameters()
将为您提供一个空列表

您必须实际创建各个图层并将其存储在变量中

现在你要做的就是打电话

X=torch.nn.Conv2d(in_channels=X.shape[0],out_channels=F1,kernel_size=1,stride=1,padding=0)(X)
它创建一个临时的
Conv2d
对象,调用该对象的forward函数,然后该对象丢失,因为只有forward的输出保存在
x

正确的做法是在
\uu init\uu()中定义层,或者在init中调用函数

所以正确的做法是

def\uuuuu init\uuuuuu(self,input\u shape=(3,96,96),class=10):
超级(ResNet50,self)。\uu初始化
"""
采用以下体系结构实现流行的ResNet50:
Conv2d->BatchNorm->ReLU->MaxPool->ConvBlock->IdBlock*2->ConvBlock->IdBlock*3->ConvBlock->IdBlock*5->ConvBlock->IdBlock*2->AvgPool->FCLayer
论据:
input_shape——数据集图像的形状
类--整数,类数
"""
self._conv_1=torch.nn.Conv2d(in_channels=X.shape[0],out_channels=F1,kernel_size=1,stride=1,padding=0)
self._bn_1=torch.nn.BatchNorm2d(num_features=F1)
...
self.input\u shape=input\u shape
self.classes=类
self.relu=torch.nn.relu()
稍后在forward或forward调用的函数中

def转发(自身,X):
"""
通过以下体系结构进行正向传播:
Conv2d->BatchNorm->ReLU->MaxPool->ConvBlock->IdBlock*2->ConvBlock->IdBlock*3->ConvBlock->IdBlock*5->ConvBlock->IdBlock*2->AvgPool->FCLayer
论据:
X——需要传播的网络输入数据
返回:
X——ResNet50的输出,通过它传播
"""
##将输入定义为具有形状self.input_形状的张量
#X=火炬式零点(自输入形状)
x=self.relu(self.\u bn_1(self.\u conv_1(x)))
返回X
所以你必须按照这些思路来做。创建图层并将其保存在变量中,然后在转发中使用变量


有关进一步的参考和帮助,请参阅官方教程

为什么不在init中编写模型定义?你会有同样的错误吗?我更新了几个断开的链接。但错误仍然没有得到解决。