Transfer learning shape mismatch

ddq: <p>I am pretty new to deep learning so please bear with me if i commit some errors.</p>
<p>I have an MLP classifier with 4 layers, fc1, fc2, fc3 and outputLayer.</p>
<p>This is what I want to do. I want to slice the MLP model from fc1, fc2 to fc3 and then add a new layer which is fc4 before the outputLayer. This becomes my new TransferMLP.</p>
<p>However, I am facing come shape mismatch. I know where the problem is just that I dont know how to fix it. I want the new model (TranferMLP ) to start from fc3 but the model end up picking the output layer instead.</p>
<p>Please direct me on how to fix it.</p>
<pre><code class="lang-auto">import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

import torch
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable


# Original MLP classifier
class MLP(nn.Module):
    def __init__(self, input_dim, hidden_dim1, hidden_dim2, hidden_dim3, output_dim, device):
        super(MLP, self).__init__()
        self.device = device
        self.fc1 = nn.Linear(input_dim, hidden_dim1)
        self.relu1 = nn.ReLU()
        self.drop1 = nn.Dropout(0.5)
        self.fc2 = nn.Linear(hidden_dim1, hidden_dim2)
        self.relu2 = nn.ReLU()
        self.drop2 = nn.Dropout(0.5)
        self.fc3 = nn.Linear(hidden_dim2, hidden_dim3)
        self.relu3 = nn.ReLU()
        self.drop3 = nn.Dropout(0.5)
        self.outputLayer = nn.Linear(hidden_dim3, output_dim)
        self.out_act = nn.Sigmoid()

    def forward(self, x):
        out = self.fc1(x)
        out = self.relu1(out)
        out = self.drop1(out)
        out = self.fc2(out)
        out = self.relu2(out)
        out = self.drop2(out)
        out = self.fc3(out)
        out = self.relu3(out)
        out = self.drop3(out)
        out = self.outputLayer(out)
        out = self.out_act(out)
        return out


# Transfer learning model
class TransferMLP(nn.Module):
    def __init__(self, pretrained_model, hidden_dim3, hidden_dim4, output_dim, device): #hidden_dim1, hidden_dim2, 
        super(TransferMLP, self).__init__()
        self.device = device
        self.pretrained_model = pretrained_model
        self.fc3 = nn.Linear(pretrained_model.fc3.in_features, hidden_dim3)
        self.relu3 = nn.ReLU()
        self.drop3 = nn.Dropout(0.5)
        self.fc4 = nn.Linear(hidden_dim3, hidden_dim4)
        self.relu4 = nn.ReLU()
        self.drop4 = nn.Dropout(0.5)
        self.outputLayer = nn.Linear(hidden_dim4, output_dim)
        self.out_act = nn.Sigmoid()

    def forward(self, x):
        out = self.pretrained_model(x)
        out = self.fc3(out)
        out = self.relu3(out)
        out = self.drop3(out)
        out = self.fc4(out)
        out = self.relu4(out)
        out = self.drop4(out)
        out = self.outputLayer(out)
        out = self.out_act(out)
        return out


def train(input_dim, hidden_dim1, hidden_dim2, hidden_dim3, output_dim, learning_rate, num_epochs, trainData, trainLabel,
          device):
    dnn_model = MLP(input_dim, hidden_dim1, hidden_dim2, hidden_dim3, output_dim, device=device)
    dnn_model.to(device)

    # Loss and optimizer
    criterion = nn.BCELoss()
    optimizer = optim.SGD(dnn_model.parameters(), lr=learning_rate)

    trainX_batch = Variable(trainData.float()).to(device)
    trainY_batch = Variable(trainLabel.float()).to(device)

    # Train the network
    for epoch in range(num_epochs):
        outputs = dnn_model(trainX_batch)
        tot_loss = criterion(outputs, trainY_batch)

        optimizer.zero_grad()
        tot_loss.backward()
        optimizer.step()

    return dnn_model


def transferMLP_train(pretrained_model, hidden_dim3, hidden_dim4, output_dim, learning_rate, num_epochs, trainData,
                   trainLabel, device):
    model = TransferMLP(pretrained_model, hidden_dim3, hidden_dim4, output_dim, device=device)
    model.to(device)

    # Freeze pre-trained model parameters
    for param in model.pretrained_model.parameters():
        param.requires_grad = False

    # Loss and optimizer
    criterion = nn.BCELoss()
    optimizer = optim.SGD(model.parameters(), lr=learning_rate)

    trainX_batch = Variable(trainData.float()).to(device)
    trainY_batch = Variable(trainLabel.float()).to(device)

    # Train the network
    for epoch in range(num_epochs):
        outputs = model(trainX_batch)
        tot_loss = criterion(outputs, trainY_batch)

        optimizer.zero_grad()
        tot_loss.backward()
        optimizer.step()

    return model
</code></pre>
<p>Please see the error below:</p>
<pre><code class="lang-auto">real_input_dim :  103
real_input_label_dim:  torch.Size([3015, 1])
input_dim:  103
input_label_dim:  torch.Size([59264, 1])
MLP(
  (fc1): Linear(in_features=103, out_features=60, bias=True)
  (relu1): ReLU()
  (drop1): Dropout(p=0.5, inplace=False)
  (fc2): Linear(in_features=60, out_features=30, bias=True)
  (relu2): ReLU()
  (drop2): Dropout(p=0.5, inplace=False)
  (fc3): Linear(in_features=30, out_features=15, bias=True)
  (relu3): ReLU()
  (drop3): Dropout(p=0.5, inplace=False)
  (outputLayer): Linear(in_features=15, out_features=1, bias=True)
  (out_act): Sigmoid()
)
TransferMLP(
  (pretrained_model): MLP(
    (fc1): Linear(in_features=103, out_features=60, bias=True)
    (relu1): ReLU()
    (drop1): Dropout(p=0.5, inplace=False)
    (fc2): Linear(in_features=60, out_features=30, bias=True)
    (relu2): ReLU()
    (drop2): Dropout(p=0.5, inplace=False)
    (fc3): Linear(in_features=30, out_features=15, bias=True)
    (relu3): ReLU()
    (drop3): Dropout(p=0.5, inplace=False)
    (outputLayer): Linear(in_features=15, out_features=1, bias=True)
    (out_act): Sigmoid()
  )
  (fc3): Linear(in_features=30, out_features=15, bias=True)
  (relu3): ReLU()
  (drop3): Dropout(p=0.5, inplace=False)
  (fc4): Linear(in_features=15, out_features=5, bias=True)
  (relu4): ReLU()
  (drop4): Dropout(p=0.5, inplace=False)
  (outputLayer): Linear(in_features=5, out_features=1, bias=True)
  (out_act): Sigmoid()
)
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[9], line 90
     88 t_mlp = TransferMLP(mlp, hidden_dim3, hidden_dim4, output_dim, device)
     89 print(t_mlp)
---&gt; 90 final_mlp = transferMLP_train(mlp, hidden_dim3, hidden_dim4, output_dim, learning_rate, 
     91                               num_epochs, real_trainData, real_trainLabel, device)
     93 # Test the model
     94 with torch.no_grad():

File /RAID5/DataStorage/davidd/experiments/pb1_july/models/classifer_transfer.py:113, in transferMLP_train(pretrained_model, hidden_dim3, hidden_dim4, output_dim, learning_rate, num_epochs, trainData, trainLabel, device)
    111 # Train the network
    112 for epoch in range(num_epochs):
--&gt; 113     outputs = model(trainX_batch)
    114     tot_loss = criterion(outputs, trainY_batch)
    116     optimizer.zero_grad()

File /RAID5/DataStorage/davidd/apps/anaconda/envs/pt2.0.1/lib/python3.10/site-packages/torch/nn/modules/module.py:1194, in Module._call_impl(self, *input, **kwargs)
   1190 # If we don't have any hooks, we want to skip the rest of the logic in
   1191 # this function, and just call forward.
   1192 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1193         or _global_forward_hooks or _global_forward_pre_hooks):
-&gt; 1194     return forward_call(*input, **kwargs)
   1195 # Do not call functions when jit is used
   1196 full_backward_hooks, non_full_backward_hooks = [], []

File /RAID5/DataStorage/davidd/experiments/pb1_july/models/classifer_transfer.py:60, in TransferMLP.forward(self, x)
     58 def forward(self, x):
     59     out = self.pretrained_model(x)
---&gt; 60     out = self.fc3(out)
     61     out = self.relu3(out)
     62     out = self.drop3(out)

File /RAID5/DataStorage/davidd/apps/anaconda/envs/pt2.0.1/lib/python3.10/site-packages/torch/nn/modules/module.py:1194, in Module._call_impl(self, *input, **kwargs)
   1190 # If we don't have any hooks, we want to skip the rest of the logic in
   1191 # this function, and just call forward.
   1192 if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1193         or _global_forward_hooks or _global_forward_pre_hooks):
-&gt; 1194     return forward_call(*input, **kwargs)
   1195 # Do not call functions when jit is used
   1196 full_backward_hooks, non_full_backward_hooks = [], []

File /RAID5/DataStorage/davidd/apps/anaconda/envs/pt2.0.1/lib/python3.10/site-packages/torch/nn/modules/linear.py:114, in Linear.forward(self, input)
    113 def forward(self, input: Tensor) -&gt; Tensor:
--&gt; 114     return F.linear(input, self.weight, self.bias)

RuntimeError: mat1 and mat2 shapes cannot be multiplied (3015x1 and 30x15)
</code></pre>