File size: 2,594 Bytes
6028065
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import torch
import torch.nn as nn

class ViolenceGRU(nn.Module):
    def __init__(self):
        super(ViolenceGRU, self).__init__()
        
        # 2D CNN Backbone (Applied to each frame independently)
        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)
        self.bn1 = nn.BatchNorm2d(32)
        self.pool1 = nn.MaxPool2d(2, 2)
        
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm2d(64)
        self.pool2 = nn.MaxPool2d(2, 2)
        
        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
        self.bn3 = nn.BatchNorm2d(128)
        self.pool3 = nn.MaxPool2d(2, 2)
        
        self.conv4 = nn.Conv2d(128, 256, kernel_size=3, padding=1)
        self.bn4 = nn.BatchNorm2d(256)
        self.pool4 = nn.MaxPool2d(2, 2)
        
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout(0.5)
        
        # Calculate feature dim after CNN
        # Input: 112x112
        # Pool1: 56x56
        # Pool2: 28x28
        # Pool3: 14x14
        # Pool4: 7x7
        self.feature_dim = 256 * 7 * 7
        
        # GRU Layer
        # input_size: Feature vector from CNN
        # hidden_size: 256
        # num_layers: 2
        self.gru = nn.GRU(input_size=self.feature_dim, hidden_size=256, num_layers=2, batch_first=True, dropout=0.5)
        
        self.fc = nn.Linear(256, 2) # Binary Classification
        
    def forward(self, x):
        # x shape from Dataset: (Batch, C, Seq, H, W)
        b, c, s, h, w = x.size()
        
        # Reshape for 2D CNN: (Batch * Seq, C, H, W)
        x = x.permute(0, 2, 1, 3, 4).contiguous() # (B, S, C, H, W)
        x = x.view(b * s, c, h, w)
        
        # Pass through CNN
        x = self.relu(self.bn1(self.conv1(x)))
        x = self.pool1(x)
        
        x = self.relu(self.bn2(self.conv2(x)))
        x = self.pool2(x)
        
        x = self.relu(self.bn3(self.conv3(x)))
        x = self.pool3(x)
        
        x = self.relu(self.bn4(self.conv4(x)))
        x = self.pool4(x)
        
        # Flatten features: (Batch * Seq, Feature_Dim)
        x = x.view(b * s, -1)
        
        # Reshape for GRU: (Batch, Seq, Feature_Dim)
        x = x.view(b, s, -1)
        
        # GRU Pass
        # out: (Batch, Seq, Hidden_Dim)
        out, _ = self.gru(x)
        
        # Take the last time step output for classification
        out = out[:, -1, :] 
        
        out = self.dropout(out)
        out = self.fc(out)
        return out