def get_step(self, grad):
        """Computes the 'step' to take for the next gradient descent update.

        Returns the step rather than performing the update so that
        parameters can be updated in place rather than overwritten.

        Examples
        --------
        >>> gradient = # ...
        >>> optimizer = AdaGradOptimizer(0.01)
        >>> params -= optimizer.get_step(gradient)

        Parameters
        ----------
        grad

        Returns
        -------
        np.array
            Size matches `grad`.
        """
        if self._momentum is None:
            self._momentum = self.initial_accumulator_value * np.ones_like(grad)
        self._momentum += grad ** 2
        return self.learning_rate * grad / np.sqrt(self._momentum)
Computes the 'step' to take for the next gradient descent update.

        Returns the step rather than performing the update so that
        parameters can be updated in place rather than overwritten.

        Examples
        --------
        >>> gradient = # ...
        >>> optimizer = AdaGradOptimizer(0.01)
        >>> params -= optimizer.get_step(gradient)

        Parameters
        ----------
        grad

        Returns
        -------
        np.array
            Size matches `grad`.