This repository was archived by the owner on Aug 20, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmodel_mlp.py
91 lines (79 loc) · 3.16 KB
/
model_mlp.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
import torch
import torch.nn as nn
class MLP(nn.Module):
"""mlp can specify number of hidden layers and hidden layer channels"""
def __init__(self, input_dim, output_dim, act='relu', num_hidden_lyr=2,
dropout_prob=0.5, return_layer_outs=False,
hidden_channels=None, bn=False):
super().__init__()
self.out_dim = output_dim
self.dropout = nn.Dropout(dropout_prob)
self.return_layer_outs = return_layer_outs
if not hidden_channels:
hidden_channels = [input_dim for _ in range(num_hidden_lyr)]
elif len(hidden_channels) != num_hidden_lyr:
raise ValueError(
"number of hidden layers should be the same as the lengh of hidden_channels")
self.layer_channels = [input_dim] + hidden_channels + [output_dim]
self.act_name = act
self.activation = create_act(act)
self.layers = nn.ModuleList(list(
map(self.weight_init, [nn.Linear(self.layer_channels[i], self.layer_channels[i + 1])
for i in range(len(self.layer_channels) - 2)])))
final_layer = nn.Linear(self.layer_channels[-2], self.layer_channels[-1])
self.weight_init(final_layer, activation='linear')
self.layers.append(final_layer)
self.bn = bn
if self.bn:
self.bn = nn.ModuleList([torch.nn.BatchNorm1d(dim) for dim in self.layer_channels[1:-1]])
def weight_init(self, m, activation=None):
if activation is None:
activation = self.act_name
torch.nn.init.xavier_uniform_(m.weight, gain=nn.init.calculate_gain(activation))
return m
def forward(self, x):
"""
:param x: the input features
:return: tuple containing output of MLP,
and list of inputs and outputs at every layer
"""
layer_inputs = [x]
for i, layer in enumerate(self.layers):
input = layer_inputs[-1]
if layer == self.layers[-1]:
layer_inputs.append(layer(input))
else:
if self.bn:
output = self.activation(self.bn[i](layer(input)))
else:
output = self.activation(layer(input))
layer_inputs.append(self.dropout(output))
# model.store_layer_output(self, layer_inputs[-1])
if self.return_layer_outs:
return layer_inputs[-1], layer_inputs
else:
return layer_inputs[-1]
def calc_mlp_dims(input_dim, division=2, output_dim=1):
dim = input_dim
dims = []
while dim > output_dim:
dim = dim // division
dims.append(int(dim))
dims = dims[:-1]
return dims
def create_act(act, num_parameters=None):
if act == 'relu':
return nn.ReLU()
elif act == 'prelu':
return nn.PReLU(num_parameters)
elif act == 'sigmoid':
return nn.Sigmoid()
elif act == 'tanh':
return nn.Tanh()
elif act == 'linear':
class Identity(nn.Module):
def forward(self, x):
return x
return Identity()
else:
raise ValueError('Unknown activation function {}'.format(act))