aaryank1411 commited on
Commit
c9b7db6
·
verified ·
1 Parent(s): 2af768b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -0
app.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cell 3: Twin CNN Architecture and Contrastive Loss
2
+ import torch.nn as nn
3
+ import torch.nn.functional as F
4
+
5
+ class SigNetTwinEncoder(nn.Module):
6
+ def __init__(self):
7
+ super(SigNetTwinEncoder, self).__init__()
8
+
9
+ self.conv = nn.Sequential(
10
+ # Input: (1, 220, 155)
11
+ nn.Conv2d(1, 32, kernel_size=5, stride=1, padding=2),
12
+ nn.BatchNorm2d(32),
13
+ nn.ReLU(inplace=True),
14
+ nn.MaxPool2d(2, 2), # -> (32, 110, 77)
15
+
16
+ nn.Conv2d(32, 64, kernel_size=5, stride=1, padding=2),
17
+ nn.BatchNorm2d(64),
18
+ nn.ReLU(inplace=True),
19
+ nn.MaxPool2d(2, 2), # -> (64, 55, 38)
20
+
21
+ nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
22
+ nn.BatchNorm2d(128),
23
+ nn.ReLU(inplace=True),
24
+ nn.MaxPool2d(2, 2) # -> (128, 27, 19)
25
+ )
26
+
27
+ # Flattened feature map: 128 * 27 * 19 = 65,664
28
+ self.fc = nn.Sequential(
29
+ nn.Linear(128 * 27 * 19, 256),
30
+ nn.ReLU(inplace=True),
31
+ nn.Dropout(0.3),
32
+ nn.Linear(256, 128) # 128-dimensional embedding
33
+ )
34
+
35
+ def forward_once(self, x):
36
+ features = self.conv(x)
37
+ features = features.view(features.size(0), -1)
38
+ embeddings = self.fc(features)
39
+ # L2-normalization on unit hypersphere
40
+ embeddings = F.normalize(embeddings, p=2, dim=1)
41
+ return embeddings
42
+
43
+ def forward(self, input1, input2):
44
+ out1 = self.forward_once(input1)
45
+ out2 = self.forward_once(input2)
46
+ return out1, out2
47
+
48
+ class ContrastiveLoss(nn.Module):
49
+ def __init__(self, margin=1.0):
50
+ super(ContrastiveLoss, self).__init__()
51
+ self.margin = margin
52
+
53
+ def forward(self, out1, out2, label):
54
+ # Euclidean distance
55
+ euclidean_distance = F.pairwise_distance(out1, out2)
56
+ # label=1 (genuine): minimize distance^2
57
+ # label=0 (forged): push distance beyond margin
58
+ loss_contrastive = torch.mean(
59
+ label * torch.pow(euclidean_distance, 2) +
60
+ (1.0 - label) * torch.pow(torch.clamp(self.margin - euclidean_distance, min=0.0), 2)
61
+ )
62
+ return loss_contrastive
63
+
64
+ # Verify parameter count
65
+ model_check = SigNetTwinEncoder()
66
+ param_count = sum(p.numel() for p in model_check.parameters() if p.requires_grad)
67
+ print(f"Total Trainable Parameters: {param_count:,} (~{param_count / 1e6:.2f}M)")