ByeonghooLee-ku / ICASSP2020-2020-code

3 stars 1 forks source link

How do I change the model to use a model with a different input geometry? #1

Open Buddies-as-you-know opened 1 year ago

Buddies-as-you-know commented 1 year ago

How do I change the model to use a model with a different input geometry? I want to apply MI-EEG with 16 channels and 125hz for classification. I want to classify three different types: right hand, left hand and state. Which model should I use in this case? How should I change the model to match the input?

ByeonghooLee-ku commented 1 year ago

Hello, thank you for your interest in my git hub. Firstly, you can use Shared model. In network.py script, change hyper-parameter "channel = 16" on the top. My code is configured for 500 time points, so you can simply calculate the ratio and change the parameters. Then, in "Shared" class, all kernel filter sizes will be reduced by 0.25 times. (excluding channel size). Finally, change "self.outputSIze -> 3" Thank you!

Buddies-as-you-know commented 1 year ago

Thank you for your reply! I have two questions. 1.I would like to test a model, should the input be in the form (1,1,C,T)? (C is channel, T is seconds * Hz)

  1. Do I need a for statement if I want to classify at 125hz for 1 second?
Buddies-as-you-know commented 1 year ago
import torch.nn as nn
import torch
receptive_field = 65
channel = 16
mean_pool = 3
kernel_size = int(15*0.25)
Shared_output = 216
Final_output = 6

class Flatten(nn.Module):
    def forward(self, input):
        return input.view(input.size(0), -1)

class Shared(nn.Module):
    def __init__(self,outputSize):
        self.outputSize=outputSize
        super(Shared,self).__init__()
        self.temporal=nn.Sequential(
            nn.Conv2d(1,36,kernel_size=[1,receptive_field],padding=0),
            nn.BatchNorm2d(36),
            nn.ELU(True),
        )
        self.spatial=nn.Sequential(
            nn.Conv2d(36,36,kernel_size=[channel,1],padding=0),
            nn.BatchNorm2d(36),
            nn.ELU(True),
        )
        self.avgpool1 = nn.AvgPool2d([1, mean_pool], stride=[1, mean_pool], padding=0)
        self.conv1=nn.Sequential(
            nn.Conv2d(36,36,kernel_size=[1,kernel_size],padding=0),
            nn.BatchNorm2d(36),
            nn.ELU(True)
        )
        self.avgpool2=nn.AvgPool2d(kernel_size=[1,mean_pool],stride=[1,mean_pool])

        self.view = nn.Sequential(
            Flatten()
        )
        self.fc=nn.Linear(Shared_output,self.outputSize)

    def forward(self,x):
      Cropped_Inputs = x[:,:,:, 0:500]
      out = self.temporal(Cropped_Inputs)
      out = self.spatial(out)
      out = self.avgpool1(out)
      featureOutput = out
      out = self.conv1(out)
      out = self.avgpool2(out)
      out = out.view(out.size(0), -1)
      prediction = self.fc(out)
      return prediction, featureOutput

net = Shared(3)
x = torch.rand(1, 1, 16, 125)
predict, fearture = net(x)
print(predict.shape)

Is this the test code? Classification is done at 125hz for 1 second. And I used 16 channels, so this is what I got.

ByeonghooLee-ku commented 1 year ago
import torch.nn as nn
import torch
receptive_field = 65
channel = 16
mean_pool = 3
kernel_size = int(15*0.25)
Shared_output = 216
Final_output = 6

class Flatten(nn.Module):
    def forward(self, input):
        return input.view(input.size(0), -1)

class Shared(nn.Module):
    def __init__(self,outputSize):
        self.outputSize=outputSize
        super(Shared,self).__init__()
        self.temporal=nn.Sequential(
            nn.Conv2d(1,36,kernel_size=[1,receptive_field],padding=0),
            nn.BatchNorm2d(36),
            nn.ELU(True),
        )
        self.spatial=nn.Sequential(
            nn.Conv2d(36,36,kernel_size=[channel,1],padding=0),
            nn.BatchNorm2d(36),
            nn.ELU(True),
        )
        self.avgpool1 = nn.AvgPool2d([1, mean_pool], stride=[1, mean_pool], padding=0)
        self.conv1=nn.Sequential(
            nn.Conv2d(36,36,kernel_size=[1,kernel_size],padding=0),
            nn.BatchNorm2d(36),
            nn.ELU(True)
        )
        self.avgpool2=nn.AvgPool2d(kernel_size=[1,mean_pool],stride=[1,mean_pool])

        self.view = nn.Sequential(
            Flatten()
        )
        self.fc=nn.Linear(Shared_output,self.outputSize)

    def forward(self,x):
      Cropped_Inputs = x[:,:,:, 0:500]
      out = self.temporal(Cropped_Inputs)
      out = self.spatial(out)
      out = self.avgpool1(out)
      featureOutput = out
      out = self.conv1(out)
      out = self.avgpool2(out)
      out = out.view(out.size(0), -1)
      prediction = self.fc(out)
      return prediction, featureOutput

net = Shared(3)
x = torch.rand(1, 1, 16, 125)
predict, fearture = net(x)
print(predict.shape)

Is this the test code? Classification is done at 125hz for 1 second. And I used 16 channels, so this is what I got.

import torch.nn as nn
import torch
receptive_field = 65
channel = 16
mean_pool = 3
kernel_size = int(15*0.25)
Shared_output = 216
Final_output = 6

class Flatten(nn.Module):
    def forward(self, input):
        return input.view(input.size(0), -1)

class Shared(nn.Module):
    def __init__(self,outputSize):
        self.outputSize=outputSize
        super(Shared,self).__init__()
        self.temporal=nn.Sequential(
            nn.Conv2d(1,36,kernel_size=[1,receptive_field],padding=0),
            nn.BatchNorm2d(36),
            nn.ELU(True),
        )
        self.spatial=nn.Sequential(
            nn.Conv2d(36,36,kernel_size=[channel,1],padding=0),
            nn.BatchNorm2d(36),
            nn.ELU(True),
        )
        self.avgpool1 = nn.AvgPool2d([1, mean_pool], stride=[1, mean_pool], padding=0)
        self.conv1=nn.Sequential(
            nn.Conv2d(36,36,kernel_size=[1,kernel_size],padding=0),
            nn.BatchNorm2d(36),
            nn.ELU(True)
        )
        self.avgpool2=nn.AvgPool2d(kernel_size=[1,mean_pool],stride=[1,mean_pool])

        self.view = nn.Sequential(
            Flatten()
        )
        self.fc=nn.Linear(Shared_output,self.outputSize)

    def forward(self,x):
      Cropped_Inputs = x[:,:,:, 0:500]
      out = self.temporal(Cropped_Inputs)
      out = self.spatial(out)
      out = self.avgpool1(out)
      featureOutput = out
      out = self.conv1(out)
      out = self.avgpool2(out)
      out = out.view(out.size(0), -1)
      prediction = self.fc(out)
      return prediction, featureOutput

net = Shared(3)
x = torch.rand(1, 1, 16, 125)
predict, fearture = net(x)
print(predict.shape)

Is this the test code? Classification is done at 125hz for 1 second. And I used 16 channels, so this is what I got.

sorry, I misunderstood, My code works at 250 Hz, so the kernel size should be reduced by 0.5 times (not 0.25). The time point will also be calculated from 500 to 250. Please double check the time points.

Buddies-as-you-know commented 1 year ago

I changed kernel_size = int(15*0.5) like this. And changed Cropped_Inputs = x[:,:,:, 0:125]. Is this okay?

ByeonghooLee-ku commented 1 year ago

The kernel size is recommended to be in integer. (15*0.5 = 7.5 but 7.0 or 8.0 recommended) The cropping input is 125 time points. I hope the code works well.

Buddies-as-you-know commented 1 year ago

Thank you very much.