(self, grads_and_vars, global_step=None, name=None)
| 177 | |
| 178 | @HIDE_DOC |
| 179 | def apply_gradients(self, grads_and_vars, global_step=None, name=None): |
| 180 | grads_and_vars = FilterNoneGrad().process(grads_and_vars) |
| 181 | vs = [] |
| 182 | for g, v in grads_and_vars: |
| 183 | assert isinstance(g, (tf.Tensor, tf.IndexedSlices)) and isinstance(v, tf.Variable), \ |
| 184 | "AccumGradOptimizer does not work for the gradient of {}! " \ |
| 185 | "Types of v and g are {} and {}".format(v.op.name, type(v), type(g)) |
| 186 | vs.append(v) |
| 187 | |
| 188 | with tf.control_dependencies(None): |
| 189 | slots = self._create_accum_slots(vs) |
| 190 | slots_and_vars = [(s, gv[1]) for s, gv in zip(slots, grads_and_vars)] |
| 191 | |
| 192 | with tfv1.variable_scope(self._name), tf.device('/cpu:0'): |
| 193 | counter = tf.Variable( |
| 194 | 0, name="counter", trainable=False, dtype=tf.int32) |
| 195 | |
| 196 | with tf.name_scope('AccumGradOptimizer'): |
| 197 | ops = [] |
| 198 | for s, gv in zip(slots, grads_and_vars): |
| 199 | g, v = gv |
| 200 | ops.append(s.assign_add(g)) |
| 201 | update_counter = tfv1.assign_add(counter, 1, name='update_counter') |
| 202 | update_slot_op = tf.group(update_counter, *ops, name='update_slot') |
| 203 | |
| 204 | def update_grad(): |
| 205 | update_op = self._opt.apply_gradients(slots_and_vars) |
| 206 | with tf.control_dependencies([update_op]): |
| 207 | clear_ops = [tfv1.assign(s, tf.zeros_like(s)) for s in slots] |
| 208 | return tf.group(*clear_ops, name='update_grad') |
| 209 | |
| 210 | pred = tf.equal(tfv1.mod(counter, self._niter), 0) |
| 211 | with tf.control_dependencies([update_slot_op]): |
| 212 | if name is None: |
| 213 | name = 'cond_update_grad' |
| 214 | op = tf.cond(pred, update_grad, tf.no_op) |
| 215 | |
| 216 | if global_step is not None: |
| 217 | # Tensorpack maintains global_step by other means, |
| 218 | # so this option is useless in tensorpack trainers. |
| 219 | # But we include the implementation here for completeness |
| 220 | global_step_increment = tfv1.assign_add(global_step, 1) |
| 221 | op = tf.group(op, global_step_increment, name=name) |
| 222 | else: |
| 223 | op = tf.identity(op, name=name).op |
| 224 | return op |
| 225 | |
| 226 | |
| 227 | if __name__ == '__main__': |
nothing calls this directly
no test coverage detected