2
\$\begingroup\$

I want to assign the row of a matrix the return value of a function, but the only way I can figure out how to do this is with a for-loop. I'm assuming this is bad and vectorization would be better.

I'm trying to implement the first principle of the Neural Engineering Framework for a class. The function of the code is to get activation levels of a neuron and put them into an activities matrix.

# I'm going to use a rectified linear neuron model, because it's super easy to implement
def rec_lin_neuron(x_inter, max_fire, gain_sign, x_max=1.0):
    def rec_lin(x):
        return np.minimum(
                np.maximum(
                    np.dot(gain_sign, x) * (max_fire/(x_max-x_inter))
                    - x_inter * (max_fire/(x_max-x_inter)),
                    np.zeros(x.size)
                ),
                max_fire
            )
    return rec_lin

# We're going to make 16 neurons
n_neurons = 16

# These are the neuron attributes that will be created randomly
max_firing_rates = np.random.uniform(100, 200, n_neurons)
x_cepts = np.random.uniform(-0.95, 0.95, n_neurons)
gain_signs = np.random.choice([-1, 1], n_neurons)

# Create the neurons and stick them in a list, because I don't know how else to keep track of them  
neurons = []
for i in range(n_neurons):
    neurons.append(rec_lin_neuron(x_cepts[i], max_firing_rates[i], gain_signs[i]))

# Now let's calculate the response of these neurons to an input and plot it
x_vals = np.arange(-1, 1, 0.05)
A = np.zeros((n_neurons, x_vals.size))

fig = plt.figure()
for i in range(n_neurons):
    A[i,:] = neurons[i](x_vals)
    plt.plot(x_vals, A[i,:])
plt.show()
\$\endgroup\$
2
\$\begingroup\$

You could start by adding the necessary imports as well:

import numpy as np
from matplotlib import pyplot as plt

Since you already said how you can improve performance here (it's not going to be easier to read, at least not to people who don't "live" matrixes), I'm going to sketch the idea, although at least one step isn't clear to me as well. Which is to say, I find the function plus for-loop way more readable than the following.

Now, instead of computing the response one by one, just vectorise each step in rec_lin. With the following rewrite, which is a tiny bit more structured:

def rec_lin_neuron(x_inter, max_fire, gain_sign, x_max=1.0):
    def rec_lin(x):
        factor = max_fire/(x_max-x_inter)
        fire = np.maximum(np.dot(gain_sign, x) * factor - x_inter * factor,
                          np.zeros(x.size))
        return np.minimum(fire, max_fire)
    return rec_lin

That would be:

diffs = np.subtract(np.repeat(1.0, n_neurons), x_cepts) # aka x_max-x_inter
factors = np.divide(max_firing_rates, diffs) # aka factor

Similarly for the rest of that function, with the exception of np.dot, where it's not clear to me how you'd run that function element-wise against the input array, maybe you already know the answer, otherwise I'll try to update it later.

The maximum and minimum for the matrixes should be np.amax and np.amin.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Why should I use np.amax? I'm trying to assign everything that is below zero to zero. From what I understand np.amax would just find the minimum value of my array. \$\endgroup\$ – Seanny123 Jan 23 '15 at 2:01
  • \$\begingroup\$ From what I understood from the documentation, np.minimum would give a single value for a matrix, whereas np.amin could be used to give you all the minimum values on one axis only, so basically getting the minimum for each row in the matrix? \$\endgroup\$ – ferada Jan 23 '15 at 13:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.