-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlayers.py
More file actions
140 lines (116 loc) · 3.93 KB
/
Copy pathlayers.py
File metadata and controls
140 lines (116 loc) · 3.93 KB
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import torch
import torch.nn as nn
import torch.autograd as autograd
from torch.nn.parameter import Parameter
import torch.nn.functional as F
import math
# https://github.com/allenai/hidden-networks
class GetSubnet(autograd.Function):
@staticmethod
def forward(ctx, scores, k):
# Get the subnetwork by sorting the scores and using the top k%
out = scores.clone()
_, idx = scores.flatten().sort()
j = int((1 - k) * scores.numel())
# flat_out and out access the same memory.
flat_out = out.flatten()
flat_out[idx[:j]] = 0
flat_out[idx[j:]] = 1
return out
@staticmethod
def backward(ctx, g):
# send the gradient g straight-through on the backward pass.
return g, None
class SubnetConv(nn.Conv2d):
# self.k is the % of weights remaining, a real number in [0,1]
# self.popup_scores is a Parameter which has the same shape as self.weight
# Gradients to self.weight, self.bias have been turned off by default.
def __init__(
self,
in_channels,
out_channels,
kernel_size,
stride=1,
padding=0,
dilation=1,
groups=1,
bias=True,
):
super(SubnetConv, self).__init__(
in_channels,
out_channels,
kernel_size,
stride,
padding,
dilation,
groups,
bias,
)
self.popup_scores = Parameter(torch.Tensor(self.weight.shape))
nn.init.kaiming_uniform_(self.popup_scores, a=math.sqrt(5))
self.weight.requires_grad = False
if self.bias is not None:
self.bias.requires_grad = False
self.w = 0
def set_prune_rate(self, k):
self.k = k
def forward(self, x):
# Get the subnetwork by sorting the scores.
adj = GetSubnet.apply(self.popup_scores.abs(), self.k)
# Use only the subnetwork in the forward pass.
self.w = self.weight * adj
x = F.conv2d(
x, self.w, self.bias, self.stride, self.padding, self.dilation, self.groups
)
return x
class testConv(nn.Conv2d):
# self.k is the % of weights remaining, a real number in [0,1]
# self.popup_scores is a Parameter which has the same shape as self.weight
# Gradients to self.weight, self.bias have been turned off by default.
def __init__(
self,
in_channels,
out_channels,
kernel_size,
stride=1,
padding=0,
dilation=1,
groups=1,
bias=True,
):
super(testConv, self).__init__(
in_channels,
out_channels,
kernel_size,
stride,
padding,
dilation,
groups,
bias,
)
def forward(self, x):
x = F.conv2d(
x, self.weight, self.bias, self.stride, self.padding, self.dilation, self.groups
)
return x
class SubnetLinear(nn.Linear):
# self.k is the % of weights remaining, a real number in [0,1]
# self.popup_scores is a Parameter which has the same shape as self.weight
# Gradients to self.weight, self.bias have been turned off.
def __init__(self, in_features, out_features, bias=True):
super(SubnetLinear, self).__init__(in_features, out_features, bias=True)
self.popup_scores = Parameter(torch.Tensor(self.weight.shape))
nn.init.kaiming_uniform_(self.popup_scores, a=math.sqrt(5))
self.weight.requires_grad = False
self.bias.requires_grad = False
self.w = 0
# self.register_buffer('w', None)
def set_prune_rate(self, k):
self.k = k
def forward(self, x):
# Get the subnetwork by sorting the scores.
adj = GetSubnet.apply(self.popup_scores.abs(), self.k)
# Use only the subnetwork in the forward pass.
self.w = self.weight * adj
x = F.linear(x, self.w, self.bias)
return x