3 from __future__
import absolute_import
4 from __future__
import division
5 from __future__
import print_function
6 from __future__
import unicode_literals
17 def __init__(self, model, input_record, output_dims, weight_init=None,
18 bias_init=
None, weight_optim=
None, bias_optim=
None, name=
'fc',
19 weight_reg=
None, bias_reg=
None, clip_param=
None,
20 max_fc_size=
None, axis=1,
22 super(FC, self).__init__(model, name, input_record, **kwargs)
24 "Incorrect input type {}".format(input_record))
25 assert len(input_record.field_types()[0].shape) > 0, (
26 "FC expects limited dimensions of the input tensor")
27 assert axis >= 1,
"axis {} should >= 1.".format(axis)
29 input_dims = np.prod(input_record.field_types()[0].shape[axis - 1:])
31 assert input_dims > 0, (
32 "FC expects input dimensions > 0, got {}".format(input_dims))
35 if (clip_param
is not None):
36 assert len(clip_param) == 2, (
37 'clip_param must be a tuple / list ' 38 'of length 2 and in the form of (clip_min, clip max)' 40 clip_min, clip_max = clip_param
41 assert clip_min
is not None or clip_max
is not None, (
42 'clip_min, and clip_max in clip_param cannot both be None' 45 (clip_min
is None or clip_max
is None)
or clip_min < clip_max
47 'clip_param = [clip_min, clip_max] must have clip_min < clip_max' 50 if clip_min
is not None:
52 if clip_max
is not None:
55 scale = math.sqrt(1.0 / input_dims)
56 weight_init = weight_init
if weight_init
else (
57 'UniformFill', {
'min': -scale,
'max': scale})
58 bias_init = bias_init
if bias_init
else (
59 'UniformFill', {
'min': -scale,
'max': scale})
62 max_fc_size, input_dims, output_dims)
66 shape=[output_dims, input_dims],
67 initializer=weight_init,
68 optimizer=weight_optim,
69 regularizer=weight_reg)
72 shape=[output_dims, ],
73 initializer=bias_init,
81 self.w_vec.append(self.
create_param(param_name=
'w_sub_{}'.format(idx),
82 shape=[output_dim, input_dims],
83 initializer=weight_init,
84 optimizer=weight_optim,
85 regularizer=weight_reg))
87 self.b_vec.append(self.
create_param(param_name=
'b_sub_{}'.format(idx),
89 initializer=weight_init,
90 optimizer=weight_optim,
91 regularizer=weight_reg))
93 output_shape = (output_dims, )
95 output_shape = list(input_record.field_types()[0].shape)[0: axis - 1]
96 output_shape = tuple(output_shape + [output_dims])
99 (np.float32, output_shape),
104 def calculate_fc_output_dims(max_fc_size, input_dim, output_dim):
106 if not max_fc_size
or max_fc_size < 0:
109 assert max_fc_size >= input_dim,
"Currently we split along the output " \
110 "dimension. So we need max_fc_size >= input_dim. But, max_fc_size: " \
111 "{}, input_dim: {}".format(max_fc_size, input_dim)
113 output_dim_allowed = int(np.floor(max_fc_size / input_dim))
114 num_fc = int(np.floor((output_dim - 1) / output_dim_allowed) + 1)
116 output_dim_vec = [output_dim_allowed] * (num_fc - 1)
118 output_dim_vec.append(output_dim - sum(output_dim_vec))
120 return output_dim_vec
122 def _add_ops(self, net, params):
124 clipped_params = [net.NextScopedBlob(
125 'clipped_%s' % str(p))
for p
in params]
126 for p, cp
in zip(params, clipped_params):
129 params = clipped_params
132 net.FC(self.input_record.field_blobs() + params,
133 self.output_schema.field_blobs(), axis=self.
axis, **self.
kwargs)
135 w_vec = params[:int(len(params) / 2)]
136 b_vec = params[int(len(params) / 2):]
138 assert len(w_vec) == len(b_vec)
143 output_blob = net.NextScopedBlob(
144 'output_sub_{}'.format(i))
145 output_blob_vec.append(
146 net.FC(self.input_record.field_blobs() +
147 [w_vec[i], b_vec[i]],
148 [output_blob], axis=self.
axis, **self.
kwargs))
150 net.Concat(output_blob_vec,
151 self.output_schema.field_blobs() +
152 [self.output_schema.field_blobs()[0] +
"_concat_dims"])
155 def param_blobs(self):
157 return [self.
w, self.
b]
def get_next_blob_reference(self, name)
def create_param(self, param_name, shape, initializer, optimizer, ps_param=None, regularizer=None)