title: How to reproduce a Keras model from the weights/biases?
body: <p>I want to use the weights and biases from a Keras ML model to make a mathematical prediction function in another program that does not have Keras installed (and cannot).</p>
  
  <p>I have a simple, MLP model that I'm using to fit data. I'm running in Python with Keras and a TensorFlow backend; for now, I'm using an input layer, 1 hidden layer, and 1 output layer. All layers are RELU, my optimizer is adam, and the loss function is mean_squared_error.</p>
  
  <p>From what I understand, the weights I get for the layers should be used mathematically in the form:</p>
  
  <pre class="lang-py prettyprint-override"><code>(SUM (w*i)) + b
  </code></pre>
  
  <p>Where the sum is over all weights and inputs, and b is for the bias on the neuron. For example, let's say I have an input layer of shape (33, 64). There are 33 inputs with 64 neurons. I'll have a vector input of dim 33 and a vector output of dim 64. This would make each SUM 33 terms * 33 weights, and the output would be all of the 64 SUMs plus the 64 biases (respectively).</p>
  
  <p>The next layer, in my case it's 32 neurons, will do the same but with 64 inputs and 32 outputs. The output layer I have goes to a single value, so input 32 and output 1.</p>
  
  <p>I have written code to try to mimic the model. Here is a snippet for making a single prediction:</p>
  
  <pre class="lang-py prettyprint-override"><code>    def modelR(weights, biases, data):
         # This is the input layer.
         y = []
         for i in range(len(weights[0][0])):
             x = np.zeros(len(weights[0][0]))
             for j in range(len(data)):
                 x[i] += weights[0][j][i]*data[j]
             y.append(x[i]+biases[0][i])
  
         # This is the hidden layer.
         z = []
         for i in range(len(weights[1][0])):
             x = np.zeros(len(weights[1][0]))
             for j in range(len(y)):
                 x[i] += weights[1][j][i]*y[j]
             z.append(x[i]+biases[1][i])
  
         # This is the output layer.
         p = 0.0
         for i in range(len(z)):
             p += weights[-1][i][0]*z[i]
         p = p+biases[-1][0]
  
         return p
  </code></pre>
  
  <p>To be clear, "weights" and "biases are derived via:</p>
  
  <pre class="lang-py prettyprint-override"><code>    weights = []
      biases = []
      for i in range(len(model.layers)):
         weights.append(model.layers[i].get_weights()[0])
         biases.append(model.layers[i].get_weights()[1])
  
      weights = np.asarray(weights)
      biases = np.asarray(biases)
  </code></pre>
  
  <p>So the first weight on the first neuron for the first input is weight[0][0][0], the first weight on the first input for the second neuron is weight[0][1][0], etc. I could be wrong on this, which may be where I'm getting stuck. But this makes sense as we're going from (1 x 33) vector to a (1 x 64) vector, so we ought to have a (33 x 64) matrix.</p>
  
  <p>Any ideas of where I'm going wrong? Thanks!</p>
  
  <p>EDIT: ANSWER FOUND
  I'm marking jhso's answer as correct, even though it didn't work properly in my code as such (I'm probably missing an import statement somewhere). The key was the activation function. I was using RELU, so I shouldn't have been passing along any negative values. Also, jhso shows a nice way to not use loops but to simply do the matrix multiplication (which I didn't know Python did). Now I just have to figure out how to do it in c++!</p>