tools 1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tools/__init__.py +14 -0
- tools/array.py +39 -0
- tools/data.py +90 -0
- tools/exp.py +165 -0
- tools/hydra/__init__.py +6 -0
- tools/modules.py +117 -0
- tools/numpy/__init__.py +8 -0
- tools/numpy/_f.py +60 -0
- tools/numpy/_utils.py +117 -0
- tools/os.py +67 -0
- tools/pandas/__init__.py +45 -0
- tools/plot/__init__.py +5 -0
- tools/plot/sklearn.py +28 -0
- tools/plot/utils.py +70 -0
- tools/random.py +35 -0
- tools/sklearn/__init__.py +2 -0
- tools/sklearn/metrics.py +82 -0
- tools/sklearn/model_selection.py +229 -0
- tools/sklearn/preprocessing.py +125 -0
- tools/stats/__init__.py +43 -0
- tools/tools.py +568 -0
- tools/torch/__init__.py +15 -0
- tools/torch/_pandas.py +12 -0
- tools/torch/data.py +81 -0
- tools/torch/estimator.py +65 -0
- tools/torch/federated_learning.py +376 -0
- tools/torch/layers.py +13 -0
- tools/torch/model.py +397 -0
- tools/torch/optim/__init__.py +2 -0
- tools/torch/optim/lr_scheduler.py +195 -0
- tools/torch/plot.py +13 -0
- tools/torch/utils.py +121 -0
- tools-1.0.dist-info/LICENSE.txt +21 -0
- tools-1.0.dist-info/METADATA +37 -0
- tools-1.0.dist-info/RECORD +37 -0
- tools-1.0.dist-info/WHEEL +5 -0
- tools-1.0.dist-info/top_level.txt +1 -0
tools/torch/model.py
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
from copy import deepcopy as dcopy
|
|
2
|
+
import torch
|
|
3
|
+
import torch.nn as nn
|
|
4
|
+
import torch.nn.functional as F
|
|
5
|
+
import torch.optim as optim
|
|
6
|
+
|
|
7
|
+
class FNN(nn.Module):
|
|
8
|
+
'''
|
|
9
|
+
basic FNN module
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
n_input: number of input (int)
|
|
14
|
+
if n_input is None, then the LazyLinear() is set in the first layer.
|
|
15
|
+
n_hidden_list: list of hidden neurons (list of int)
|
|
16
|
+
activation_list: torch.nn activation function instances (nn object or list of nn object)
|
|
17
|
+
|
|
18
|
+
Example
|
|
19
|
+
-------
|
|
20
|
+
>>> model = FNN(n_input=10, n_hidden_list=[8,6,5], activation_list=[nn.Sigmoid(), nn.ReLU(), nn.Tanh()])
|
|
21
|
+
# n_hidden_list, activation_list corresponds to [h1, h2, output]
|
|
22
|
+
>>> print(model)
|
|
23
|
+
FNN(
|
|
24
|
+
(fc): Sequential(
|
|
25
|
+
(0): Linear(in_features=10, out_features=8, bias=True)
|
|
26
|
+
(1): Sigmoid()
|
|
27
|
+
(2): Linear(in_features=8, out_features=6, bias=True)
|
|
28
|
+
(3): ReLU()
|
|
29
|
+
(4): Linear(in_features=6, out_features=5, bias=True)
|
|
30
|
+
(5): Tanh()
|
|
31
|
+
)
|
|
32
|
+
)
|
|
33
|
+
'''
|
|
34
|
+
def __init__(self, n_hidden_list, activation_list, n_input=None):
|
|
35
|
+
# def __init__(self, n_input, n_hidden_list, activation_list):
|
|
36
|
+
super().__init__()
|
|
37
|
+
if type(activation_list) is not list:
|
|
38
|
+
activation_list = [dcopy(activation_list)]*len(n_hidden_list)
|
|
39
|
+
assert len(activation_list)==len(n_hidden_list), 'length of layers and activations must match. If you want no activation, use nn.Identity'
|
|
40
|
+
|
|
41
|
+
# 1st layer - Select Lazy if n_input is not specified
|
|
42
|
+
if n_input is None:
|
|
43
|
+
layers = [nn.Flatten(1), nn.LazyLinear(n_hidden_list[0]), activation_list[0]]
|
|
44
|
+
else:
|
|
45
|
+
layers = [nn.Flatten(1), nn.Linear(n_input, n_hidden_list[0]), activation_list[0]]
|
|
46
|
+
# Hidden layers ~ Output layer
|
|
47
|
+
for i in range(len(n_hidden_list) - 1):
|
|
48
|
+
layers.extend([nn.Linear(n_hidden_list[i], n_hidden_list[i+1]), activation_list[i+1]])
|
|
49
|
+
|
|
50
|
+
self.fc = nn.Sequential(*layers)
|
|
51
|
+
|
|
52
|
+
def forward(self, x):
|
|
53
|
+
'''x.shape()==(batch_size, feature_dim)'''
|
|
54
|
+
return self.fc(x)
|
|
55
|
+
|
|
56
|
+
class FNN_Resnet(nn.Module):
|
|
57
|
+
'''
|
|
58
|
+
Resnet module
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
n_input : int
|
|
63
|
+
number of input
|
|
64
|
+
n_hidden_list : list of int
|
|
65
|
+
list of hidden neurons
|
|
66
|
+
activation : nn activation instance or list
|
|
67
|
+
torch.nn activation function instances
|
|
68
|
+
skip: int
|
|
69
|
+
number of layers to skip. Interval for skipping
|
|
70
|
+
ex) skip=2, then add skip layer every other 2 layers
|
|
71
|
+
|
|
72
|
+
Example
|
|
73
|
+
-------
|
|
74
|
+
>>> model = Resnet(n_input=10, n_hidden_list=[8,6,5], activation=[nn.Sigmoid(), nn.ReLU(), nn.tanh()], skip=2)
|
|
75
|
+
# activation corresponds to [h1, h2, output]
|
|
76
|
+
>>> print(model)
|
|
77
|
+
|
|
78
|
+
'''
|
|
79
|
+
def __init__(self, n_hidden_list, activation_list, n_input=None, skip=2):
|
|
80
|
+
# def __init__(self, n_input, n_hidden_list, activation_list, skip=2):
|
|
81
|
+
super().__init__()
|
|
82
|
+
if type(activation_list) is not list:
|
|
83
|
+
activation_list = [dcopy(activation_list)]*len(n_hidden_list)
|
|
84
|
+
assert len(activation_list)==len(n_hidden_list), 'length of layers and activations must match. If you want no activation, use nn.Identity'
|
|
85
|
+
assert len(n_hidden_list) >= skip, 'number of layers must be equal or greater than skip. len(n_hidden_list): %s, skip: %s'%(len(n_hidden_list), skip)
|
|
86
|
+
assert skip >= 2, 'skip needs to be: skip >= 2, given: %s'%(skip)
|
|
87
|
+
|
|
88
|
+
# 1st layer
|
|
89
|
+
if n_input is None:
|
|
90
|
+
layers = [nn.LazyLinear(n_hidden_list[0])]
|
|
91
|
+
else:
|
|
92
|
+
layers = [nn.Linear(n_input, n_hidden_list[0])]
|
|
93
|
+
# Hidden layers ~ Output layer
|
|
94
|
+
layers.extend([nn.Linear(n_hidden_list[i], n_hidden_list[i+1]) for i in range(len(n_hidden_list)-1)])
|
|
95
|
+
self.fc = nn.ModuleList(layers)
|
|
96
|
+
self.activation_list = nn.ModuleList(activation_list)
|
|
97
|
+
|
|
98
|
+
# Skip layers
|
|
99
|
+
# Bias already present at original layers
|
|
100
|
+
self.skip = skip
|
|
101
|
+
if n_input is None:
|
|
102
|
+
n_skip_hidden_list = [n_hidden_list[i] for i in range(skip-1, len(n_hidden_list), skip)]
|
|
103
|
+
skip_layers = [nn.LazyLinear(n_skip_hidden_list[0], bias=False)] + [nn.Linear(n_skip_hidden_list[i], n_skip_hidden_list[i+1], bias=False) for i in range(len(n_skip_hidden_list)-1)]
|
|
104
|
+
else:
|
|
105
|
+
n_skip_hidden_list = [n_input] + [n_hidden_list[i] for i in range(skip-1, len(n_hidden_list), skip)]
|
|
106
|
+
skip_layers = [nn.Linear(n_skip_hidden_list[i], n_skip_hidden_list[i+1], bias=False) for i in range(len(n_skip_hidden_list)-1)]
|
|
107
|
+
self.skip_layers = nn.ModuleList(skip_layers) # Need ModuleList, not list, so that the model can recognize this layers
|
|
108
|
+
self.n_skip = len(n_hidden_list) // skip # number of skip layers
|
|
109
|
+
# assert self.n_skip == len(self.skip_layers), 'something\'s wrong'
|
|
110
|
+
|
|
111
|
+
def forward(self, x):
|
|
112
|
+
x = x.flatten(1)
|
|
113
|
+
last_x = x
|
|
114
|
+
skip_layers = iter(self.skip_layers)
|
|
115
|
+
for i, (layer, activation) in enumerate(zip(self.fc, self.activation_list)):
|
|
116
|
+
if (i+1) % self.skip == 0:
|
|
117
|
+
skip_layer = next(skip_layers)
|
|
118
|
+
x = activation(layer(x)+skip_layer(last_x))
|
|
119
|
+
last_x = x
|
|
120
|
+
else:
|
|
121
|
+
x = activation(layer(x))
|
|
122
|
+
return x
|
|
123
|
+
'''To do:
|
|
124
|
+
- weight initialization? modify?
|
|
125
|
+
- optimize using nn.Sequential() and itertools in forward. compute layers in group
|
|
126
|
+
'''
|
|
127
|
+
|
|
128
|
+
class FNN_Densenet(nn.Module):
|
|
129
|
+
def __init__(self, n_hidden_list, activation_list, n_input=None, skip=2):
|
|
130
|
+
# def __init__(self, n_input, n_hidden_list, activation_list, skip=2):
|
|
131
|
+
super().__init__()
|
|
132
|
+
if type(activation_list) is not list:
|
|
133
|
+
activation_list = [dcopy(activation_list)]*len(n_hidden_list)
|
|
134
|
+
assert len(activation_list)==len(n_hidden_list), 'length of layers and activations must match. If you want no activation, use nn.Identity'
|
|
135
|
+
assert len(n_hidden_list) >= skip, 'number of layers must be equal or greater than skip. len(n_hidden_list): %s, skip: %s'%(len(n_hidden_list), skip)
|
|
136
|
+
assert skip >= 2, 'skip needs to be: skip >= 2, given: %s'%(skip)
|
|
137
|
+
|
|
138
|
+
# 1st layer
|
|
139
|
+
if n_input is None:
|
|
140
|
+
layers = [nn.LazyLinear(n_hidden_list[0])]
|
|
141
|
+
else:
|
|
142
|
+
layers = [nn.Linear(n_input, n_hidden_list[0])]
|
|
143
|
+
# Hidden layers ~ Output layer
|
|
144
|
+
layers.extend([nn.Linear(n_hidden_list[i], n_hidden_list[i+1]) for i in range(len(n_hidden_list)-1)])
|
|
145
|
+
self.fc = nn.ModuleList(layers)
|
|
146
|
+
self.activation_list = nn.ModuleList(activation_list)
|
|
147
|
+
|
|
148
|
+
# Skip layers
|
|
149
|
+
self.skip = skip
|
|
150
|
+
if n_input is None:
|
|
151
|
+
n_skip_hidden_list = [None] + [n_hidden_list[i] for i in range(skip-1, len(n_hidden_list), skip)]
|
|
152
|
+
skip_layers = nn.ModuleDict()
|
|
153
|
+
for i in range(1, len(n_skip_hidden_list)):
|
|
154
|
+
for j in range(i):
|
|
155
|
+
if j==0:
|
|
156
|
+
skip_layers[str(j)+'_'+str(i)]=nn.LazyLinear(n_skip_hidden_list[i], bias=False)
|
|
157
|
+
else:
|
|
158
|
+
skip_layers[str(j)+'_'+str(i)]=nn.Linear(n_skip_hidden_list[j], n_skip_hidden_list[i], bias=False)
|
|
159
|
+
else:
|
|
160
|
+
n_skip_hidden_list = [n_input] + [n_hidden_list[i] for i in range(skip-1, len(n_hidden_list), skip)]
|
|
161
|
+
skip_layers = nn.ModuleDict()
|
|
162
|
+
for i in range(1, len(n_skip_hidden_list)):
|
|
163
|
+
for j in range(i):
|
|
164
|
+
skip_layers[str(j)+'_'+str(i)]=nn.Linear(n_skip_hidden_list[j], n_skip_hidden_list[i], bias=False)
|
|
165
|
+
self.skip_layers = skip_layers
|
|
166
|
+
|
|
167
|
+
n = len(n_skip_hidden_list)-1
|
|
168
|
+
self.n_skip = int(n*(n+1)/2)
|
|
169
|
+
assert self.n_skip == len(skip_layers), f'something wrong: n_skip({self.n_skip}), skip_layers({len(skip_layers)})'
|
|
170
|
+
|
|
171
|
+
def forward(self, x):
|
|
172
|
+
x_history = [x]
|
|
173
|
+
dest = 1 # Destination index of skip layers
|
|
174
|
+
for i, (layer, activation) in enumerate(zip(self.fc, self.activation_list)):
|
|
175
|
+
if (i+1) % self.skip == 0:
|
|
176
|
+
assert dest == len(x_history), f'Length of x_history{len(x_history)} and destination number{dest} must match'
|
|
177
|
+
skip_x = torch.stack([self.skip_layers[str(src)+'_'+str(dest)](x_) for src, x_ in enumerate(x_history)], dim=-1).sum(dim=-1)
|
|
178
|
+
x = activation(layer(x)+skip_x)
|
|
179
|
+
x_history.append(x)
|
|
180
|
+
dest += 1
|
|
181
|
+
else:
|
|
182
|
+
x = activation(layer(x))
|
|
183
|
+
|
|
184
|
+
return x
|
|
185
|
+
|
|
186
|
+
class CNN(nn.Module):
|
|
187
|
+
def __init__(self, in_channel, n_channel_list, activation_list, kernel_size=3):
|
|
188
|
+
super().__init__()
|
|
189
|
+
if type(activation_list) is not list:
|
|
190
|
+
activation_list = [dcopy(activation_list)]*len(n_channel_list)
|
|
191
|
+
assert len(activation_list)==len(n_channel_list), 'length of layers and activations must match. If you want no activation, use nn.Identity'
|
|
192
|
+
|
|
193
|
+
# 1st layer
|
|
194
|
+
padding = kernel_size // 2
|
|
195
|
+
layers = [nn.Conv2d(in_channels=in_channel, out_channels=n_channel_list[0], kernel_size=kernel_size, stride=1, padding=padding), activation_list[0]]
|
|
196
|
+
# Hidden layers ~ Output layer
|
|
197
|
+
for i in range(len(n_channel_list) - 1):
|
|
198
|
+
layers.extend([nn.Conv2d(in_channels=n_channel_list[i], out_channels=n_channel_list[i+1], kernel_size=kernel_size, stride=1, padding=padding), activation_list[i+1]])
|
|
199
|
+
self.layers = nn.Sequential(*layers)
|
|
200
|
+
|
|
201
|
+
def forward(self, x):
|
|
202
|
+
return self.layers(x)
|
|
203
|
+
|
|
204
|
+
class CNN_Resnet(nn.Module):
|
|
205
|
+
def __init__(self, in_channel, n_channel_list, activation_list, kernel_size=3, skip=2):
|
|
206
|
+
super().__init__()
|
|
207
|
+
if type(activation_list) is not list:
|
|
208
|
+
activation_list = [dcopy(activation_list)]*len(n_channel_list)
|
|
209
|
+
assert len(activation_list)==len(n_channel_list), 'length of layers and activations must match. If you want no activation, use nn.Identity'
|
|
210
|
+
assert kernel_size % 2 == 1, f'kernel size must be odd number, Got: ({kernel_size})'
|
|
211
|
+
|
|
212
|
+
# 1st layer
|
|
213
|
+
padding = kernel_size // 2
|
|
214
|
+
layers = [nn.Conv2d(in_channels=in_channel, out_channels=n_channel_list[0], kernel_size=kernel_size, stride=1, padding=padding)]
|
|
215
|
+
# Hidden layers ~ Output layer
|
|
216
|
+
layers.extend([nn.Conv2d(in_channels=n_channel_list[i], out_channels=n_channel_list[i+1], kernel_size=kernel_size, stride=1, padding=padding) for i in range(len(n_channel_list)-1)])
|
|
217
|
+
self.layers = nn.ModuleList(layers)
|
|
218
|
+
self.activation_list = nn.ModuleList(activation_list)
|
|
219
|
+
|
|
220
|
+
# Skip layers
|
|
221
|
+
self.skip = skip
|
|
222
|
+
n_skip_channel_list = [in_channel]+[n_channel_list[i] for i in range(skip-1, len(n_channel_list), skip)]
|
|
223
|
+
skip_layers = [nn.Conv2d(in_channels=n_skip_channel_list[i], out_channels=n_skip_channel_list[i+1], kernel_size=kernel_size, stride=1, padding=padding, bias=False) for i in range(len(n_skip_channel_list)-1)] # Bias already present at original layers
|
|
224
|
+
self.skip_layers = nn.ModuleList(skip_layers) # Need ModuleList, not list, so that the model can recognize this layers
|
|
225
|
+
self.n_skip = len(n_channel_list) // skip # number of skip layers
|
|
226
|
+
# assert self.n_skip == len(self.skip_layers), 'something\'s wrong'
|
|
227
|
+
|
|
228
|
+
def forward(self, x):
|
|
229
|
+
last_x = x
|
|
230
|
+
skip_layers = iter(self.skip_layers)
|
|
231
|
+
for i, (layer, activation) in enumerate(zip(self.layers, self.activation_list)):
|
|
232
|
+
if (i+1) % self.skip == 0:
|
|
233
|
+
skip_layer = next(skip_layers)
|
|
234
|
+
x = activation(layer(x)+skip_layer(last_x))
|
|
235
|
+
last_x = x
|
|
236
|
+
else:
|
|
237
|
+
x = activation(layer(x))
|
|
238
|
+
return x
|
|
239
|
+
|
|
240
|
+
class CNN_Densenet(nn.Module):
|
|
241
|
+
def __init__(self, in_channel, n_channel_list, activation_list, kernel_size=3, skip=2):
|
|
242
|
+
super().__init__()
|
|
243
|
+
if type(activation_list) is not list:
|
|
244
|
+
activation_list = [dcopy(activation_list)]*len(n_channel_list)
|
|
245
|
+
assert len(activation_list)==len(n_channel_list), 'length of layers and activations must match. If you want no activation, use nn.Identity'
|
|
246
|
+
assert kernel_size % 2 == 1, f'kernel size must be odd number, Got: ({kernel_size})'
|
|
247
|
+
|
|
248
|
+
# 1st layer
|
|
249
|
+
padding = kernel_size // 2
|
|
250
|
+
layers = [nn.Conv2d(in_channels=in_channel, out_channels=n_channel_list[0], kernel_size=kernel_size, stride=1, padding=padding)]
|
|
251
|
+
# Hidden layers ~ Output layer
|
|
252
|
+
layers.extend([nn.Conv2d(in_channels=n_channel_list[i], out_channels=n_channel_list[i+1], kernel_size=kernel_size, stride=1, padding=padding) for i in range(len(n_channel_list)-1)])
|
|
253
|
+
self.layers = nn.ModuleList(layers)
|
|
254
|
+
self.activation_list = nn.ModuleList(activation_list)
|
|
255
|
+
|
|
256
|
+
# Skip layers
|
|
257
|
+
self.skip = skip
|
|
258
|
+
n_skip_channel_list = [in_channel]+[n_channel_list[i] for i in range(skip-1, len(n_channel_list), skip)]
|
|
259
|
+
|
|
260
|
+
skip_layers = nn.ModuleDict()
|
|
261
|
+
for i in range(1, len(n_skip_channel_list)):
|
|
262
|
+
for j in range(i):
|
|
263
|
+
skip_layers[str(j)+'_'+str(i)]=nn.Conv2d(in_channels=n_skip_channel_list[j], out_channels=n_skip_channel_list[i], kernel_size=kernel_size, stride=1, padding=padding, bias=False)
|
|
264
|
+
self.skip_layers = skip_layers
|
|
265
|
+
|
|
266
|
+
n = len(n_skip_channel_list)-1
|
|
267
|
+
self.n_skip = int(n*(n+1)/2)
|
|
268
|
+
assert self.n_skip == len(skip_layers), f'something wrong: n_skip({self.n_skip}), skip_layers({len(skip_layers)})'
|
|
269
|
+
|
|
270
|
+
def forward(self, x):
|
|
271
|
+
x_history = [x]
|
|
272
|
+
dest = 1 # Destination index of skip layers
|
|
273
|
+
for i, (layer, activation) in enumerate(zip(self.layers, self.activation_list)):
|
|
274
|
+
if (i+1) % self.skip == 0:
|
|
275
|
+
assert dest == len(x_history), f'Length of x_history{len(x_history)} and destination number{dest} must match'
|
|
276
|
+
skip_x = torch.stack([self.skip_layers[str(src)+'_'+str(dest)](x_) for src, x_ in enumerate(x_history)], dim=-1).sum(dim=-1)
|
|
277
|
+
x = activation(layer(x)+skip_x)
|
|
278
|
+
x_history.append(x)
|
|
279
|
+
dest += 1
|
|
280
|
+
else:
|
|
281
|
+
x = activation(layer(x))
|
|
282
|
+
|
|
283
|
+
return x
|
|
284
|
+
|
|
285
|
+
class Gaussian(nn.Module):
|
|
286
|
+
def __init__(self, amp=1, mu=0, sigma=1):
|
|
287
|
+
super().__init__()
|
|
288
|
+
self.register_parameter('mu', nn.Parameter(torch.tensor(mu, dtype=torch.float)))
|
|
289
|
+
self.register_parameter('sigma', nn.Parameter(torch.tensor(sigma, dtype=torch.float)))
|
|
290
|
+
self.register_parameter('amp', nn.Parameter(torch.tensor(amp, dtype=torch.float)))
|
|
291
|
+
|
|
292
|
+
def forward(self, x):
|
|
293
|
+
return self.amp/(self.sigma*np.sqrt(2*np.pi))*torch.exp(-0.5*((x-self.mu)/self.sigma)**2)
|
|
294
|
+
|
|
295
|
+
class SimpleGaussian(nn.Module):
|
|
296
|
+
def __init__(self, amp=1, mu=0, sigma=1):
|
|
297
|
+
super().__init__()
|
|
298
|
+
self.register_parameter('mu', nn.Parameter(torch.tensor(mu, dtype=torch.float)))
|
|
299
|
+
self.register_parameter('sigma', nn.Parameter(torch.tensor(sigma, dtype=torch.float)))
|
|
300
|
+
self.register_parameter('amp', nn.Parameter(torch.tensor(amp, dtype=torch.float)))
|
|
301
|
+
|
|
302
|
+
def forward(self, x):
|
|
303
|
+
return self.amp*torch.exp(-0.5*((x-self.mu)/self.sigma)**2)
|
|
304
|
+
|
|
305
|
+
class Residual(nn.Module):
|
|
306
|
+
"""
|
|
307
|
+
Residual module which computes residual connections in forward pass.
|
|
308
|
+
Note that intermediate tensors need to have the same shape.
|
|
309
|
+
|
|
310
|
+
Parameters
|
|
311
|
+
----------
|
|
312
|
+
blocks : list of nn.Module objects, or an iterable nn.Module object.
|
|
313
|
+
|
|
314
|
+
activation : nn.Module object (default: None)
|
|
315
|
+
activation function to be applied at each residual connection betwee blocks.
|
|
316
|
+
|
|
317
|
+
Examples
|
|
318
|
+
--------
|
|
319
|
+
>>> blocks = [nn.Linear(10,10) for i in range(5)]
|
|
320
|
+
>>> model = Residual(blocks)
|
|
321
|
+
>>> model
|
|
322
|
+
|
|
323
|
+
"""
|
|
324
|
+
def __init__(self, blocks, activation=None):
|
|
325
|
+
super().__init__()
|
|
326
|
+
if issubclass(type(blocks), nn.Module):
|
|
327
|
+
self.blocks = blocks
|
|
328
|
+
elif issubclass(type(blocks), list):
|
|
329
|
+
self.blocks = nn.ModuleList(blocks)
|
|
330
|
+
else:
|
|
331
|
+
raise Exception('')
|
|
332
|
+
self.activation = activation
|
|
333
|
+
|
|
334
|
+
def forward(self, x):
|
|
335
|
+
if self.activation is not None:
|
|
336
|
+
for block in self.blocks:
|
|
337
|
+
x = self.activation(block(x)+x)
|
|
338
|
+
|
|
339
|
+
else: # No activation
|
|
340
|
+
for block in self.blocks:
|
|
341
|
+
x = block(x)+x
|
|
342
|
+
return x
|
|
343
|
+
|
|
344
|
+
class Parallel(nn.Module):
|
|
345
|
+
"""
|
|
346
|
+
Similar to nn.Sequential, but parallel connection.
|
|
347
|
+
Note that the shape of each output from each module must be identical,
|
|
348
|
+
since Parallel() sums up all outputs in forward().
|
|
349
|
+
Also note that Parallel with nn.Identity() is identical to Residual()
|
|
350
|
+
|
|
351
|
+
Parameters
|
|
352
|
+
----------
|
|
353
|
+
args : nn.Modules
|
|
354
|
+
|
|
355
|
+
Examples
|
|
356
|
+
--------
|
|
357
|
+
>>>
|
|
358
|
+
"""
|
|
359
|
+
def __init__(self, *args):
|
|
360
|
+
super().__init__()
|
|
361
|
+
self._layers = args
|
|
362
|
+
for i, layer in enumerate(args):
|
|
363
|
+
self.add_module(str(i), layer)
|
|
364
|
+
|
|
365
|
+
def forward(self, x):
|
|
366
|
+
y_list = [layer(x) for layer in self._layers]
|
|
367
|
+
y = sum(y_list)
|
|
368
|
+
return y
|
|
369
|
+
|
|
370
|
+
def __iter__(self):
|
|
371
|
+
self._i = 0
|
|
372
|
+
return self
|
|
373
|
+
|
|
374
|
+
def __next__(self):
|
|
375
|
+
if self._i < len(self):
|
|
376
|
+
layer = self[self._i]
|
|
377
|
+
self._i +=1
|
|
378
|
+
return layer
|
|
379
|
+
else:
|
|
380
|
+
raise StopIteration
|
|
381
|
+
|
|
382
|
+
def __len__(self):
|
|
383
|
+
return len(self._layers)
|
|
384
|
+
|
|
385
|
+
def __getitem__(self, idx):
|
|
386
|
+
return self._layers[idx]
|
|
387
|
+
|
|
388
|
+
if __name__ == '__main__':
|
|
389
|
+
n_input = 5
|
|
390
|
+
n_hidden_list = [10,20,30,20,10]
|
|
391
|
+
activation_list = [nn.Sigmoid(), nn.ReLU(), nn.LeakyReLU(0.03), nn.Tanh(), nn.Identity()]
|
|
392
|
+
fnn = FNN(n_input, n_hidden_list, activation_list)
|
|
393
|
+
fnn_resnet = FNN_Resnet(n_input, n_hidden_list, activation_list)
|
|
394
|
+
fnn_densenet = FNN_Densenet(n_input, n_hidden_list, activation_list)
|
|
395
|
+
print(fnn)
|
|
396
|
+
print(fnn_resnet)
|
|
397
|
+
print(fnn_densenet)
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
from torch.optim.lr_scheduler import _LRScheduler
|
|
2
|
+
class AdaptiveLR(_LRScheduler):
|
|
3
|
+
"""Modify the learning rate of each parameter group,
|
|
4
|
+
depending on the current & previous loss values.
|
|
5
|
+
|
|
6
|
+
If current_loss < previous_loss:
|
|
7
|
+
lr += a*lr (Increment lr by a * lr)
|
|
8
|
+
If current loss > previous loss:
|
|
9
|
+
lr -= b*lr (Decrement lr by b * lr)
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
optimizer (Optimizer): Wrapped optimizer.
|
|
13
|
+
a: (float or list): A multiplicative factor to increment learning rate
|
|
14
|
+
when the current loss is lower than the previous loss.
|
|
15
|
+
b: (float or list): A multiplicative factor to decrement learning rate
|
|
16
|
+
when the current loss is higher than the previous loss.
|
|
17
|
+
|
|
18
|
+
The increment/decrement of learning rate is done on
|
|
19
|
+
each lr for each group in optimizer.param_groups
|
|
20
|
+
Example:
|
|
21
|
+
>>> # Assuming optimizer has two groups.
|
|
22
|
+
>>> a_list = [0.1, 0.2]
|
|
23
|
+
>>> b_list = [0.5, 0.9]
|
|
24
|
+
>>> scheduler = AdaptiveLR(optimizer, a=a_list, b=b_list)
|
|
25
|
+
>>> for epoch in range(100):
|
|
26
|
+
>>> train(...)
|
|
27
|
+
>>> validate(...)
|
|
28
|
+
>>> scheduler.step(loss)
|
|
29
|
+
"""
|
|
30
|
+
requires_loss = True
|
|
31
|
+
def __init__(self, optimizer, a, b, last_epoch = -1, threshold = -float('inf'), fix = False, last_loss = float('inf')):
|
|
32
|
+
self.last_loss = last_loss
|
|
33
|
+
self.loss = self.last_loss
|
|
34
|
+
self.threshold = threshold
|
|
35
|
+
self.fix = fix
|
|
36
|
+
self.factor = 1
|
|
37
|
+
self.a = a
|
|
38
|
+
self.b = b
|
|
39
|
+
# if (not isinstance(a, list) and not isinstance(a, tuple)) and (not isinstance(b, list) and not isinstance(b, tuple)):
|
|
40
|
+
# self.a_s = [a] * len(optimizer.param_groups)
|
|
41
|
+
# self.b_s = [b] * len(optimizer.param_groups)
|
|
42
|
+
# elif (isinstance(a, list) or isinstance(a, tuple)) and (isinstance(b, list) or isinstance(b, tuple)):
|
|
43
|
+
# if len(a) != len(optimizer.param_groups) or len(b) != len(optimizer.param_groups):
|
|
44
|
+
# raise ValueError("Expected {} 'a's and 'b's, but got {}, {}".format(
|
|
45
|
+
# len(optimizer.param_groups), len(a), len(b)))
|
|
46
|
+
# self.a_s = list(a)
|
|
47
|
+
# self.b_s = list(b)
|
|
48
|
+
# else:
|
|
49
|
+
# raise ValueError("a and b has to be the same type, of either iterable or numeric values."
|
|
50
|
+
# "Got: a: {}, b: {}".format(type(a), type(b)))
|
|
51
|
+
super(AdaptiveLR, self).__init__(optimizer, last_epoch)
|
|
52
|
+
|
|
53
|
+
def step(self, loss = 0, epoch=None):
|
|
54
|
+
if self.last_epoch >= 0:
|
|
55
|
+
self.last_loss = self.loss
|
|
56
|
+
self.loss = loss
|
|
57
|
+
# self.last_epoch gets incremented afterwards
|
|
58
|
+
super(AdaptiveLR, self).step(epoch=epoch)
|
|
59
|
+
|
|
60
|
+
def get_lr(self):
|
|
61
|
+
if not self._get_lr_called_within_step:
|
|
62
|
+
warnings.warn("To get the last learning rate computed by the scheduler, "
|
|
63
|
+
"please use `get_last_lr()`.", DeprecationWarning)
|
|
64
|
+
if self.last_epoch > 0:
|
|
65
|
+
if self.factor < self.threshold:
|
|
66
|
+
# lr fixed after threshold
|
|
67
|
+
if self.fix:
|
|
68
|
+
return [base_lr * self.threshold for base_lr in self.base_lrs]
|
|
69
|
+
# lr not fixed after threshold
|
|
70
|
+
elif self.loss <= self.last_loss:
|
|
71
|
+
self.factor += self.factor * self.a
|
|
72
|
+
return [base_lr * self.factor for base_lr in self.base_lrs]
|
|
73
|
+
# return [group['lr'] + group['lr'] * self.a for group in self.optimizer.param_groups]
|
|
74
|
+
else:
|
|
75
|
+
return [base_lr * self.factor for base_lr in self.base_lrs]
|
|
76
|
+
# return [group['lr'] for group in self.optimizer.param_groups]
|
|
77
|
+
else:
|
|
78
|
+
if self.loss <= self.last_loss:
|
|
79
|
+
self.factor += self.factor * self.a
|
|
80
|
+
return [base_lr * self.factor for base_lr in self.base_lrs]
|
|
81
|
+
# return [group['lr'] + group['lr'] * self.a for group in self.optimizer.param_groups]
|
|
82
|
+
else:
|
|
83
|
+
self.factor -= self.factor * self.b
|
|
84
|
+
return [base_lr * self.factor for base_lr in self.base_lrs]
|
|
85
|
+
# return [group['lr'] - group['lr'] * self.b for group in self.optimizer.param_groups]
|
|
86
|
+
else:
|
|
87
|
+
return self.base_lrs
|
|
88
|
+
|
|
89
|
+
class LinearLR(_LRScheduler):
|
|
90
|
+
"""Decay the learning rate of each parameter group by delta every epoch.
|
|
91
|
+
Every step,
|
|
92
|
+
lr = lr - initial_lr * delta
|
|
93
|
+
-----
|
|
94
|
+
Args:
|
|
95
|
+
optimizer (Optimizer): Wrapped optimizer.
|
|
96
|
+
delta: (float or list): A subtractive factor to decrement learning rate.
|
|
97
|
+
last_epoch (int): The index of last epoch. Default: -1.
|
|
98
|
+
Example:
|
|
99
|
+
>>> # Assuming optimizer has two groups.
|
|
100
|
+
>>> delta_list = [0.1, 0.2]
|
|
101
|
+
>>> scheduler = AdaptiveLR(optimizer, delta=delta_list)
|
|
102
|
+
>>> for epoch in range(100):
|
|
103
|
+
>>> train(...)
|
|
104
|
+
>>> validate(...)
|
|
105
|
+
>>> scheduler.step()
|
|
106
|
+
"""
|
|
107
|
+
def __init__(self, optimizer, delta, last_epoch = -1):
|
|
108
|
+
self.deltas = delta
|
|
109
|
+
if not isinstance(delta, list) and not isinstance(delta, tuple):
|
|
110
|
+
self.deltas = [delta] * len(optimizer.param_groups)
|
|
111
|
+
else:
|
|
112
|
+
if len(delta) != len(optimizer.param_groups):
|
|
113
|
+
raise ValueError("Expected {} deltas, but got {}".format(
|
|
114
|
+
len(optimizer.param_groups), len(delta)))
|
|
115
|
+
self.deltas = list(delta)
|
|
116
|
+
super(LinearLR, self).__init__(optimizer, last_epoch)
|
|
117
|
+
|
|
118
|
+
def get_lr(self):
|
|
119
|
+
if not self._get_lr_called_within_step:
|
|
120
|
+
warnings.warn("To get the last learning rate computed by the scheduler, "
|
|
121
|
+
"please use `get_last_lr()`.", DeprecationWarning)
|
|
122
|
+
if self.last_epoch > 0:
|
|
123
|
+
return [group['lr'] - base_lr * delta for group, base_lr, delta in zip(self.optimizer.param_groups, self.base_lrs, self.deltas)]
|
|
124
|
+
else:
|
|
125
|
+
return self.base_lrs
|
|
126
|
+
|
|
127
|
+
def _get_closed_form_lr(self):
|
|
128
|
+
return [base_lr*(1 - delta * self.epoch) for base_lr, delta in zip(self.base_lrs, self.deltas)]
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class NoneLR(_LRScheduler):
|
|
132
|
+
def __init__(self, optimizer, last_epoch = -1):
|
|
133
|
+
super(NoneLR, self).__init__(optimizer, last_epoch)
|
|
134
|
+
def get_lr(self):
|
|
135
|
+
return self.base_lrs
|
|
136
|
+
#
|
|
137
|
+
# import torch
|
|
138
|
+
# import torch.optim as optim
|
|
139
|
+
# w = torch.randn((1,5), requires_grad=True)
|
|
140
|
+
# y = torch.randn((2,3), requires_grad=True)
|
|
141
|
+
# optimizer = optim.Adam([w,y])
|
|
142
|
+
# optimizer
|
|
143
|
+
# lr_schduler = AdaptiveLR(optimizer, a=[0.1,0.2], b=0.5)
|
|
144
|
+
# help(AdaptiveLR1)
|
|
145
|
+
# lr_schduler.state_dict()
|
|
146
|
+
#
|
|
147
|
+
# for
|
|
148
|
+
# optimizer.step()
|
|
149
|
+
# lr_schduler.step()
|
|
150
|
+
# lr_schduler.state_dict()
|
|
151
|
+
#
|
|
152
|
+
# class AdaptiveLR():
|
|
153
|
+
# def __init__(self, optimizer, a, b, last_epoch = 0):
|
|
154
|
+
# self.optimizer = optimizer
|
|
155
|
+
# self.a = a
|
|
156
|
+
# self.b = b
|
|
157
|
+
# self.last_loss = float('inf')
|
|
158
|
+
# self.base_lrs = [param_group['lr'] for param_group in optimizer.param_groups]
|
|
159
|
+
# self.last_epoch = last_epoch
|
|
160
|
+
# self._last_lr = self.base_lrs
|
|
161
|
+
#
|
|
162
|
+
# def state_dict(self):
|
|
163
|
+
# content = dict(
|
|
164
|
+
# optimizer = self.optimizer,
|
|
165
|
+
# a = self.a,
|
|
166
|
+
# b = self.b,
|
|
167
|
+
# last_loss = self.last_loss,
|
|
168
|
+
# base_lrs = self.base_lrs,
|
|
169
|
+
# last_epoch = self.last_epoch,
|
|
170
|
+
# _last_lr = self._last_lr,
|
|
171
|
+
# )
|
|
172
|
+
# return content
|
|
173
|
+
#
|
|
174
|
+
# def step(self, loss):
|
|
175
|
+
# for i, param_group in enumerate(self.optimizer.param_groups):
|
|
176
|
+
# lr = param_group['lr']
|
|
177
|
+
# if loss <= self.last_loss:
|
|
178
|
+
# self._last_lr[i] += lr * self.a
|
|
179
|
+
# else:
|
|
180
|
+
# self._last_lr[i] -= lr * self.b
|
|
181
|
+
# self.optimizer.param_groups[i]['lr'] = self._last_lr[i]
|
|
182
|
+
# self.last_loss = loss
|
|
183
|
+
# self.last_epoch += 1
|
|
184
|
+
#
|
|
185
|
+
#
|
|
186
|
+
# def get_last_lr(self):
|
|
187
|
+
# return self._last_lr
|
|
188
|
+
|
|
189
|
+
def lr_schedule_VAE(epoch):
|
|
190
|
+
if epoch <= 100:
|
|
191
|
+
lr_target = 1e-4
|
|
192
|
+
lr_decay = (lr_target) ** (1/100 * epoch)
|
|
193
|
+
return lr_decay
|
|
194
|
+
else:
|
|
195
|
+
return 1e-3
|
tools/torch/plot.py
ADDED