"""
Siamese Neural Network: run the image pair through a cnn twice to compare the output
Contrastive Loss: measure the similarity of two output result
"""
import torch
import torch.nn as nn
import torch.nn.functional as F

def euclidean_dist(input1, input2):
    return F.pairwise_distance(input1, input2, keepdim=True)

class SiameseNet(nn.Module):
    def __init__(self):
        super(SiameseNet, self).__init__()
        self.conv = nn.Sequential(
            nn.ReflectionPad2d(1),
            nn.Conv2d(1, 4, kernel_size=3),
            nn.ReLU(inplace=True),
            nn.BatchNorm2d(4),

            nn.ReflectionPad2d(1),
            nn.Conv2d(4, 8, kernel_size=3),
            nn.ReLU(inplace=True),
            nn.BatchNorm2d(8),

            nn.ReflectionPad2d(1),
            nn.Conv2d(8, 8, kernel_size=3),
            nn.ReLU(inplace=True),
            nn.BatchNorm2d(8))

        self.fc = nn.Sequential(
            nn.Linear(8*100*100, 500),
            nn.ReLU(inplace=True),

            nn.Linear(500, 500),
            nn.ReLU(inplace=True),

            nn.Linear(500, 5))

    def forward_once(self, x):
        conv1 = self.conv(x)
        conv1 = conv1.view(conv1.size()[0], -1)
        fc1 = self.fc(conv1)
        return fc1

    def forward(self, x1, x2):
        output1 = self.forward_once(x1)
        output2 = self.forward_once(x2)
        return output1, output2

class ContrastiveLoss(nn.Module):
    def __init__(self, margin=2.0):
        super(ContrastiveLoss, self).__init__()
        self.margin = margin

    def forward(self, x1, x2, y):
        d_w = euclidean_dist(x1, x2)
        max = torch.clamp(self.margin-d_w,min=0.0)
        loss = 0.5*(1-y)*torch.pow(d_w,2)+0.5*y*torch.pow(max, 2)
        return loss

"""
Siamese Neural Network: run the image pair through a cnn twice to compare the output
Contrastive Loss: measure the similarity of two output result
"""
import torch
import torch.nn as nn
import torch.nn.functional as F

def euclidean_dist(input1, input2):
    return F.pairwise_distance(input1, input2, keepdim=True)

class SiameseNet(nn.Module):
    def __init__(self):
        super(SiameseNet, self).__init__()
        self.conv = nn.Sequential(
            nn.ReflectionPad2d(1),
            nn.Conv2d(1, 4, kernel_size=3),
            nn.ReLU(inplace=True),
            nn.BatchNorm2d(4),

            nn.ReflectionPad2d(1),
            nn.Conv2d(4, 8, kernel_size=3),
            nn.ReLU(inplace=True),
            nn.BatchNorm2d(8),

            nn.ReflectionPad2d(1),
            nn.Conv2d(8, 8, kernel_size=3),
            nn.ReLU(inplace=True),
            nn.BatchNorm2d(8))

        self.fc = nn.Sequential(
            nn.Linear(8*100*100, 500),
            nn.ReLU(inplace=True),

            nn.Linear(500, 500),
            nn.ReLU(inplace=True),

            nn.Linear(500, 5))

    def forward_once(self, x):
        conv1 = self.conv(x)
        conv1 = conv1.view(conv1.size()[0], -1)
        fc1 = self.fc(conv1)
        return fc1

    def forward(self, x1, x2):
        output1 = self.forward_once(x1)
        output2 = self.forward_once(x2)
        return output1, output2

class ContrastiveLoss(nn.Module):
    def __init__(self, margin=2.0):
        super(ContrastiveLoss, self).__init__()
        self.margin = margin

    def forward(self, x1, x2, y):
        d_w = euclidean_dist(x1, x2)
        max = torch.clamp(self.margin-d_w,min=0.0)
        loss = 0.5*(1-y)*torch.pow(d_w,2)+0.5*y*torch.pow(max, 2)
        return loss

Siamese Neural Network: run the image pair through a cnn twice to compare the output Contrastive Loss: measure the similarity of two output result