ekosman / AnomalyDetectionCVPR2018-Pytorch

Pytorch version of - https://github.com/WaqasSultani/AnomalyDetectionCVPR2018
172 stars 52 forks source link

Question for anomaly detector model #175

Closed SkyWalkerJJJ closed 1 year ago

SkyWalkerJJJ commented 1 year ago

I wonder why using two dropout function at line 15 an 18 I think only using one dropout function at line 18 will increase the performance since C3D cannot achieve 75% accuracy as mentioned in the paper.

ekosman commented 1 year ago

I followed the original detailed of the paper: Section 5.1

The first FC layer has 512 units followed by 32 units and
1 unit FC layers. 60% dropout regularization [33] is used
between FC layers
SkyWalkerJJJ commented 1 year ago

I am currently changing the structure to below, but receive an error saying "RuntimeError: running_mean should contain 32 elements not 256" Do you know the reason? I'm new to the deep learning area.

class AnomalyDetector(nn.Module):
    """Anomaly detection model for videos."""

    def __init__(self, input_dim=512) -> None:
        super().__init__()

        self.fc1 = nn.Linear(input_dim, 256)
        self.bn1 = nn.BatchNorm1d(256)
        self.relu1 = nn.ReLU()
        #self.dropout1 = nn.Dropout(0.6)

        self.fc2 = nn.Linear(256, 128)
        self.bn2 = nn.BatchNorm1d(128)
        self.relu2 = nn.ReLU()
        #self.dropout2 = nn.Dropout(0.6)

        self.fc3 = nn.Linear(128,32)
        self.bn3 = nn.BatchNorm1d(32)
        self.dropout3 = nn.Dropout(0.6)

        self.fc4 = nn.Linear(32, 1)
        self.sig = nn.Sigmoid()

        # In the original keras code they use "glorot_normal"
        # As I understand, this is the same as xavier normal in Pytorch
        nn.init.xavier_normal_(self.fc1.weight)
        nn.init.xavier_normal_(self.fc2.weight)
        nn.init.xavier_normal_(self.fc3.weight)
        nn.init.xavier_normal_(self.fc4.weight)

    def forward(self, x: Tensor) -> Tensor:  # pylint: disable=arguments-differ

        x = self.relu1(self.bn1(self.fc1(x)))
        x = self.relu2(self.bn2(self.fc2(x)))
        x = self.dropout3(self.fc3(x))
        x = self.sig(self.fc4(x))
        return x
ekosman commented 1 year ago

Which script are you trying to run?

If you load an existing model, you can't change the architecture, as the saved weights won't match the new architecture.

SkyWalkerJJJ commented 1 year ago

I am running the train anomaly detector python file. I did not load any checkpoint. I want to train it from scratch.

ekosman commented 1 year ago

Can you share the complete stack trace, please?

SkyWalkerJJJ commented 1 year ago

Hi, below is the full error code, and let me briefly introduce the problem. The input of the anomaly detector torch size is torch.Size([60, 32, 256]) 32 I think represents 32 segments, and the last 256 is the channel size. However, the batchNorm1d expects an input of shape (B, C, L). That's why it 32 could not match 256 in the code. Any suggestion?

File "anomaly_detector_model.py", line 161, in <module>
    output = model(input)
  File "/root/miniconda3/lib/python3.8/site-packages/torch/nn/modules/module.py", line 1110, in _call_impl
    return forward_call(*input, **kwargs)
  File "anomaly_detector_model.py", line 74, in forward
    x = self.relu1(self.bn1(self.fc1(x)))
  File "/root/miniconda3/lib/python3.8/site-packages/torch/nn/modules/module.py", line 1110, in _call_impl
    return forward_call(*input, **kwargs)
  File "/root/miniconda3/lib/python3.8/site-packages/torch/nn/modules/batchnorm.py", line 168, in forward
    return F.batch_norm(
  File "/root/miniconda3/lib/python3.8/site-packages/torch/nn/functional.py", line 2421, in batch_norm
    return torch.batch_norm(
RuntimeError: running_mean should contain 32 elements not 256
ekosman commented 1 year ago

According to this, if the input tensor is 3D, then the last dimension corresponds to L which is the sequence length. However, you feed it with a tensor where the last dimension is C. One direct solution would permute the second and third dimensions of the tensor, before and after the batchnorm call.

SkyWalkerJJJ commented 1 year ago

You mean do something like the below? Originally, I did the permute before batch normalization, but not after the batch normalization. Then it causes an error when entering the second batch normalization.

        x = self.fc1(x)
        x = x.permute(0,2,1)
        x = self.relu1(self.bn1(x))
        x = x.permute(0,2,1)
        x = self.fc2(x)
        x = x.permute(0,2,1)
        x = self.relu2(self.bn2(x))
        x = x.permute(0,2,1)
        x = self.dropout3(self.fc3(x))
        x = self.sig(self.fc4(x))
ekosman commented 1 year ago

This works for me

You mean do something like the below? Originally, I did the permute before batch normalization, but not after the batch normalization. Then it causes an error when entering the second batch normalization.

        x = self.fc1(x)
        x = x.permute(0,2,1)
        x = self.relu1(self.bn1(x))
        x = x.permute(0,2,1)
        x = self.fc2(x)
        x = x.permute(0,2,1)
        x = self.relu2(self.bn2(x))
        x = x.permute(0,2,1)
        x = self.dropout3(self.fc3(x))
        x = self.sig(self.fc4(x))