| 173 | |
| 174 | |
| 175 | class MultiStepOptimizer(tf.train.Optimizer): |
| 176 | |
| 177 | def __init__(self, optimizer, step=1, use_locking=False, |
| 178 | name="MultiStepOptimizer"): |
| 179 | super(MultiStepOptimizer, self).__init__(use_locking, name) |
| 180 | self._optimizer = optimizer |
| 181 | self._step = step |
| 182 | self._step_t = tf.convert_to_tensor(step, name="step") |
| 183 | |
| 184 | def _all_reduce(self, tensor): |
| 185 | with tf.name_scope(self._name + "_Allreduce"): |
| 186 | if tensor is None: |
| 187 | return tensor |
| 188 | |
| 189 | if isinstance(tensor, tf.IndexedSlices): |
| 190 | tensor = tf.convert_to_tensor(tensor) |
| 191 | |
| 192 | return all_reduce(tensor) |
| 193 | |
| 194 | def compute_gradients(self, loss, var_list=None, |
| 195 | gate_gradients=tf.train.Optimizer.GATE_OP, |
| 196 | aggregation_method=None, |
| 197 | colocate_gradients_with_ops=False, |
| 198 | grad_loss=None): |
| 199 | grads_and_vars = self._optimizer.compute_gradients(loss , var_list, |
| 200 | gate_gradients, aggregation_method, colocate_gradients_with_ops, |
| 201 | grad_loss) |
| 202 | |
| 203 | grads, var_list = list(zip(*grads_and_vars)) |
| 204 | |
| 205 | # Do not create extra variables when step is 1 |
| 206 | if self._step == 1: |
| 207 | grads = [self._all_reduce(t) for t in grads] |
| 208 | return list(zip(grads, var_list)) |
| 209 | |
| 210 | first_var = min(var_list, key=lambda x: x.name) |
| 211 | iter_var = self._create_non_slot_variable( |
| 212 | initial_value=0 if self._step == 1 else 1, name="iter", |
| 213 | colocate_with=first_var) |
| 214 | |
| 215 | new_grads = [] |
| 216 | |
| 217 | for grad, var in zip(grads, var_list): |
| 218 | grad_acc = self._zeros_slot(var, "grad_acc", self._name) |
| 219 | |
| 220 | if isinstance(grad, tf.IndexedSlices): |
| 221 | grad_acc = tf.scatter_add(grad_acc, grad.indices, grad.values, |
| 222 | use_locking=self._use_locking) |
| 223 | else: |
| 224 | grad_acc = tf.assign_add(grad_acc, grad, |
| 225 | use_locking=self._use_locking) |
| 226 | |
| 227 | def _acc_grad(): |
| 228 | return grad_acc |
| 229 | |
| 230 | def _avg_grad(): |
| 231 | return self._all_reduce(grad_acc / self._step) |
| 232 |
nothing calls this directly
no outgoing calls
no test coverage detected