title: Class Calling A Function From Another Class
body: <p>I'm attempting to get a better understanding of classes in Python and OOP in general. I'm using code from: &nbsp;&nbsp;<a href="http://neuralnetworksanddeeplearning.com/chap1.html" rel="nofollow"><em>Using neural nets to recognize handwritten digits</em></a></p>
  
  <p>to play with, teach myself how about feed forward neural network, and classes. I'm deconstructing everything and observing its behaviour. One of the options that I would like to add is the ability to pick the type of activation function for the neurons. I've built two classes (one for the sigmoid and another using tanh) where each holds an <code>activation_fn</code> and <code>prime</code> class method, so that:</p>
  
  <pre><code>#### Libraries ####
  # Third Party Libraries
  import numpy as np
  
  class Sigmoid(object):
      @staticmethod
      def activation_fn(z):
          """The sigmoid function.
          """
          return 1.0/(1.0+np.exp(-z))
  
      def prime(self, z):
          """The derivative of the sigmoid function.
          """
          return self.activation_fn(z)*(1-self.activation_fn(z))
  
  class Tanh(object):
      @staticmethod
      def activation_fn(z):
          """The tanh function.
          """
          return np.tanh(z)
  
      def prime(self, z):
          """The derivative of the tahn function.
          """
          return (1-self.activation_fn(z)**2)
  </code></pre>
  
  <p>When I test out both classes they output the desired solutions,</p>
  
  <pre><code>x = Sigmoid()
  print(x.activation_fn(1)) # outputs: 0.73105857863
  print(x.prime(1))         # outputs: 0.196611933241
  
  y = Tanh()
  print(y.activation_fn(1)) # outputs: 0.761594155956
  print(y.prime(1))         # outputs: 0.419974341614
  </code></pre>
  
  <p>When I attempt to to the same for the following code:</p>
  
  <pre><code>#### Libraries ####
  # Third Party Libraries
  import numpy as np
  
  class Sigmoid(object):
      def activation_fn(self, z):
          """The sigmoid function."""
          return 1.0/(1.0+np.exp(-z))
  
      def prime(self, z):
          """The derivative of the sigmoid function."""
          return self.activation_fn(z)*(1-self.activation_fn(z))
  
  class Tanh(object):
      def activation_fn(self, z):
          """The tanh function."""
          return np.tanh(z)
  
      def prime(self, z):
          """The derivative of the tahn function."""
          return (1-self.activation_fn(z)**2)
  
  class Network(object):
      """Builds the initial network and sets the weights and biases
      randomly by every connection and neuron, respectively. One can
      choose between the sigmoid and tanh as an activation.
      """
      def __init__(self, sizes, neurons=Sigmoid):
          self.layer_num = len(sizes)
          self.sizes = sizes
          self.biases = [np.zeros((y, 1)) for y in self.sizes[1:]]
          self.weights = [np.zeros((y, x))
                          for x, y in zip(self.sizes[:-1], self.sizes[1:])]
          self.neurons = neurons
  
      def feedforward(self, a):
          for b, w in zip(self.biases, self.weights):
              a = self.neurons.activation_fn(np.dot(w, a)+b)
  
          return a
  
  if  __name__ == '__main__':
      # Network with 3 nodes in the first layer, 4 in the second, and 2 in
      # the final layer
      test = Network([3, 4, 2])
  
      print(test.feedforward(1))
  </code></pre>
  
  <p>It also outputs a result, namely</p>
  
  <pre><code>[[ 0.5  0.5  0.5]
   [ 0.5  0.5  0.5]]
  </code></pre>
  
  <p>The problem that I'm having is when I try to call <code>prime</code> in a similar fashion to <code>def feedforward(self, a)</code> which I simply change <code>self.neuron.activation_fn(np.dot(w, a)+b)</code> to  <code>self.neuron.prime(np.dot(w, a)+b)</code> which simply becomes</p>
  
  <pre><code>def feedforward(self,a):
      ...
  
  def prime_test(self, a):
      for b, w in zip(self.biases, self.weights):
          a = self.neurons.prime(np.dot(w, a)+b)
  
      return a
  </code></pre>
  
  <p>but when executing the following code</p>
  
  <pre><code>if  __name__ == '__main__':
      # Network with 3 nodes in the first layer, 4 in the second, and 2 in
      # the final layer
      test = Network([3, 4, 2])
  
      print(test.prime_test(1))
  </code></pre>
  
  <p>simarly to the way I tested both classes I get the following error:</p>
  
  <pre class="lang-none prettyprint-override"><code>prime_test
      a = self.neurons.prime(np.dot(w, a)+b)
  TypeError: prime() missing 1 required positional argument: 'z'
  </code></pre>
  
  <p>I'm not sure how to remedy it, especially since it looks nearly identical to <code>x.prime(1)</code> which works.</p>