-
Notifications
You must be signed in to change notification settings - Fork 3
/
HASHI_cnn_utils.py
115 lines (90 loc) · 4.76 KB
/
HASHI_cnn_utils.py
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Jan 16 14:36:31 2019
@author: sipo
INESCTEC
"""
import os
import sys
import math
import numpy as np
from PIL import Image
import torch
from torch import nn
from torch.nn import functional as F
def get_flat_dim(input_dim, n_conv, conv_filters, kernel_sizes, p_kernel, strides, p_strides, paddings):
_, H, W = input_dim
for i in range(n_conv):
H = int(math.floor((H + 2*paddings[i] - kernel_sizes[i])/(1.*strides[i]) + 1))
H = int(math.floor((H - p_kernel[i])/(1.*p_strides[i]) + 1)) # 0 padding in pooling
W = int(math.floor((W + 2*paddings[i] - kernel_sizes[i])/(1.*strides[i]) + 1))
W = int(math.floor((W - p_kernel[i])/(1.*p_strides[i]) + 1)) # 0 padding in pooling
flat_dim = H * W * conv_filters[-1]
return flat_dim
class ConvNet(nn.Module):
def __init__(self, n_conv, n_pool, n_fc, conv_filters, kernel_sizes, p_kernels, strides, p_strides,
paddings, fc_dims, in_channels, flat_dim, dropout=.0, batch_norm=False):
super(ConvNet, self).__init__()
self.n_conv = n_conv # integer
self.n_pool = n_pool # integer
self.n_fc = n_fc # integer
self.conv_filters = conv_filters # list with length n_conv
self.kernel_sizes = kernel_sizes # list with length n_conv (square filters)
self.p_kernels = p_kernels # list with length n_pool (square filters)
self.strides = strides # list with length n_conv
self.p_strides = p_strides # list with length n_pool
self.paddings = paddings # list with length n_conv
self.fc_dims = fc_dims # list with length n_fc
self.in_channels = in_channels # integer
self.flat_dim = flat_dim # integer
# convolutional layers
self.conv_layers = nn.ModuleList([nn.Conv2d(self.in_channels,
self.conv_filters[0],
self.kernel_sizes[0],
stride=self.strides[0],
padding=self.paddings[0])])
self.conv_layers.extend([nn.Conv2d(self.conv_filters[i-1],
self.conv_filters[i],
self.kernel_sizes[i],
stride=self.strides[i],
padding=self.paddings[i])
for i in range(1, self.n_conv)])
# pooling layers
self.pool_layers = nn.ModuleList([nn.LPPool2d(2,
self.p_kernels[0],
stride=self.p_strides[0])])
self.pool_layers.extend([nn.LPPool2d(2,
self.p_kernels[i],
stride=self.p_strides[i])
for i in range(1, self.n_pool)])
# fully connected layers
self.fc_layers = nn.ModuleList([nn.Linear(self.flat_dim, self.fc_dims[0])])
self.fc_layers.extend([nn.Linear(self.fc_dims[i-1], self.fc_dims[i]) for i in range(1, self.n_fc)])
def forward(self, X, get_activations=False):
activations = []
N = X.shape[0]
# forward pass through the conv. layers
h = X
for i in range(self.n_conv):
h = self.conv_layers[i](h)
h = F.relu(h)
activations.append(h)
h = self.pool_layers[i](h)
# flatten the activation before applying the fc layers
h = h.reshape(N, -1)
# forward pass through the fc layers
for i in range(self.n_fc-1):
h = self.fc_layers[i](h)
h = F.relu(h)
activations.append(h)
# the output layer does not have ReLU, batch norm. and dropout, so we leave it outside the loop
y = self.fc_layers[self.n_fc-1](h)
if get_activations:
return y, activations
else:
return y
def predict(self, X): #Computes the probabilities of each class for each example in X.
logits = self.forward(X)
probs = F.softmax(logits, dim=1)
return probs