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 import numpy as np
35 from .parameterized import Parameterized
36 from .param import Param
37
40 """
41 The return value of this function gives the values which the re-mapped
42 parameters should take. Implement in sub-classes.
43 """
44 raise NotImplementedError
45
47 raise NotImplementedError
48
51
57
58 -class Fix(Remapping):
60
61
62
63
64 -class Tie(Parameterized):
65 """
66 The new parameter tie framework. (under development)
67
68 All the parameters tied together get a new parameter inside the *Tie* object.
69 Its value should always be equal to all the tied parameters, and its gradient
70 is the sum of all the tied parameters.
71
72 Implementation Details:
73
74 The *Tie* object should only exist on the top of param tree (the highest parent).
75
76 self.label_buf:
77 It uses a label buffer that has the same length as all the parameters (self._highest_parent_.param_array).
78 The buffer keeps track of all the tied parameters. All the tied parameters have a label (an interger) higher
79 than 0, and the parameters that have the same label are tied together.
80
81 self.buf_index:
82 An auxiliary index list for the global index of the tie parameter inside the *Tie* object.
83
84 .. warning::
85
86 This is not implemented yet and will be different, with high degree of certainty.
87 Do not use!
88
89 """
91 super(Tie, self).__init__(name)
92 self.tied_param = None
93
94 self.label_buf = None
95
96 self.buf_idx = None
97
98 self._tie_ = None
99
107
113
115 if self._tie_.size != self.label_buf.size:
116 self._tie_ = np.ones((self._highest_parent_.param_array.size,),dtype=np.bool)
117 self._tie_[self.label_buf>0] = False
118 self._tie_[self.buf_idx] = True
119
145
147 """Merge the tie parameters with ids in the list."""
148 if len(ids)==1:
149 id_final_idx = self.buf_idx[self.label_buf[self.buf_idx]==ids[0]][0]
150 return ids[0],id_final_idx
151 id_final = ids[0]
152 ids_rm = ids[1:]
153 label_buf_param = self.label_buf[self.buf_idx]
154 idx_param = [np.where(label_buf_param==i)[0][0] for i in ids_rm]
155 self._removeTieParam(idx_param)
156 [np.put(self.label_buf, np.where(self.label_buf==i), id_final) for i in ids_rm]
157 id_final_idx = self.buf_idx[self.label_buf[self.buf_idx]==id_final][0]
158 return id_final, id_final_idx
159
163
165 """Expand the tie param with the number of *num* parameters"""
166 if self.tied_param is None:
167 new_buf = np.empty((num,))
168 else:
169 new_buf = np.empty((self.tied_param.size+num,))
170 new_buf[:self.tied_param.size] = self.tied_param.param_array.copy()
171 self.remove_parameter(self.tied_param)
172 self.tied_param = Param('tied',new_buf)
173 self.add_parameter(self.tied_param)
174 buf_idx_new = self._highest_parent_._raveled_index_for(self.tied_param)
175 self._expand_label_buf(self.buf_idx, buf_idx_new)
176 self.buf_idx = buf_idx_new
177 return self.buf_idx[-num:]
178
180 """idx within tied_param"""
181 new_buf = np.empty((self.tied_param.size-len(idx),))
182 bool_list = np.ones((self.tied_param.size,),dtype=np.bool)
183 bool_list[idx] = False
184 new_buf[:] = self.tied_param.param_array[bool_list]
185 self.remove_parameter(self.tied_param)
186 self.tied_param = Param('tied',new_buf)
187 self.add_parameter(self.tied_param)
188 buf_idx_new = self._highest_parent_._raveled_index_for(self.tied_param)
189 self._shrink_label_buf(self.buf_idx, buf_idx_new, bool_list)
190 self.buf_idx = buf_idx_new
191
193 """Expand label buffer accordingly"""
194 if idx_old is None:
195 self.label_buf = np.zeros(self._highest_parent_.param_array.shape, dtype=np.int)
196 else:
197 bool_old = np.zeros((self.label_buf.size,),dtype=np.bool)
198 bool_old[idx_old] = True
199 bool_new = np.zeros((self._highest_parent_.param_array.size,),dtype=np.bool)
200 bool_new[idx_new] = True
201 label_buf_new = np.zeros(self._highest_parent_.param_array.shape, dtype=np.int)
202 label_buf_new[np.logical_not(bool_new)] = self.label_buf[np.logical_not(bool_old)]
203 label_buf_new[idx_new[:len(idx_old)]] = self.label_buf[idx_old]
204 self.label_buf = label_buf_new
205
207 bool_old = np.zeros((self.label_buf.size,),dtype=np.bool)
208 bool_old[idx_old] = True
209 bool_new = np.zeros((self._highest_parent_.param_array.size,),dtype=np.bool)
210 bool_new[idx_new] = True
211 label_buf_new = np.empty(self._highest_parent_.param_array.shape, dtype=np.int)
212 label_buf_new[np.logical_not(bool_new)] = self.label_buf[np.logical_not(bool_old)]
213 label_buf_new[idx_new] = self.label_buf[idx_old[bool_list]]
214 self.label_buf = label_buf_new
215
234
241
243 if self.tied_param is not None:
244 self.tied_param.gradient = 0.
245 [np.put(self.tied_param.gradient, i, self._highest_parent_.gradient[self.label_buf==self.label_buf[self.buf_idx[i]]].sum())
246 for i in range(self.tied_param.size)]
247
249 if self.tied_param is not None:
250 for i in range(self.tied_param.size):
251 self._highest_parent_.param_array[self.label_buf==self.label_buf[self.buf_idx[i]]] = self.tied_param[i]
252