title: Stochastic gradient descent implementation with Python's numpy
body: <p>I have to implement stochastic gradient descent using python numpy library. For that purpose I'm given the following function definitions:</p>
  
  <pre><code>def compute_stoch_gradient(y, tx, w):
      """Compute a stochastic gradient for batch data."""
  
  def stochastic_gradient_descent(
          y, tx, initial_w, batch_size, max_epochs, gamma):
      """Stochastic gradient descent algorithm."""
  </code></pre>
  
  <p>I'm also given the following help function:</p>
  
  <pre><code>def batch_iter(y, tx, batch_size, num_batches=1, shuffle=True):
      """
      Generate a minibatch iterator for a dataset.
      Takes as input two iterables (here the output desired values 'y' and the input data 'tx')
      Outputs an iterator which gives mini-batches of `batch_size` matching elements from `y` and `tx`.
      Data can be randomly shuffled to avoid ordering in the original data messing with the randomness of the minibatches.
      Example of use :
      for minibatch_y, minibatch_tx in batch_iter(y, tx, 32):
          &lt;DO-SOMETHING&gt;
      """
      data_size = len(y)
  
      if shuffle:
          shuffle_indices = np.random.permutation(np.arange(data_size))
          shuffled_y = y[shuffle_indices]
          shuffled_tx = tx[shuffle_indices]
      else:
          shuffled_y = y
          shuffled_tx = tx
      for batch_num in range(num_batches):
          start_index = batch_num * batch_size
          end_index = min((batch_num + 1) * batch_size, data_size)
          if start_index != end_index:
              yield shuffled_y[start_index:end_index], shuffled_tx[start_index:end_index]
  </code></pre>
  
  <p>I implemented the following two functions:</p>
  
  <pre><code>def compute_stoch_gradient(y, tx, w):
      """Compute a stochastic gradient for batch data."""
      e = y - tx.dot(w)
      return (-1/y.shape[0])*tx.transpose().dot(e)
  
  
  def stochastic_gradient_descent(y, tx, initial_w, batch_size, max_epochs, gamma):
      """Stochastic gradient descent algorithm."""
      ws = [initial_w]
      losses = []
      w = initial_w
      for n_iter in range(max_epochs):
          for minibatch_y,minibatch_x in batch_iter(y,tx,batch_size):
              w = ws[n_iter] - gamma * compute_stoch_gradient(minibatch_y,minibatch_x,ws[n_iter])
              ws.append(np.copy(w))
              loss = y - tx.dot(w)
              losses.append(loss)
  
      return losses, ws
  </code></pre>
  
  <p>I'm not sure the iteration should be done in range(max_epochs) or in a larger range. I say this because I read that an epoch is "each time we run through the entire data set". So I think an epoch consists on more of one iteration...</p>