0

I've got a question about iteration in python. At the moment I am trying to build a very simple neural net, using the following (parts of the) code:

class neural_net:
    def __init__(self, n_neurons, n_input):
        self.n_neurons = n_neurons
        self.n_input = n_input
        self.input = []
        self.weights = []
        self.output = []


    def generate_input(self):
        input = [0.0,0.0,1.0]
        self.input = input


    def generate_random_weights(self):
        weights = [[0] * self.n_input ] * (self.n_neurons)
        for i in range(self.n_neurons):
            for ii in range(self.n_input):
                weights[i][ii] =  round(random.random(), 1)
        self.weights = weights

In the function generate_random_weights, i=0 and i=1 are always updates at the same time. The result is always something like the following when a print it, using print'weights:', self.weights:

weights: [[0.2, 0,1, 0,8], [0,2, 0,1, 0,8]]

The first and the second list are always the same: does anyone know why this happens?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Blee
  • 419
  • 5
  • 11

1 Answers1

1

Your issue is with how you initialize weights:

weights = [[0] * self.n_input ] * (self.n_neurons)

This is equivalent to the following:

inner_list = [0] * self.n_input
weights = [inner_list] * (self.n_neurons)

Hopefully this makes it clear that each element of weights is a copy of the same list, instead you should use something like this:

weights = [[0] * self.n_input for _ in range(self.n_neurons)]

The important thing to remember here is that you should only use * to create a list if the values are all immutable, so [0] * 4 is safe but [[0]] * 4 will create a new list with four references to the same inner list.

By using a list comprehension instead you can ensure that you are creating a new inner list for each location in your outer list.

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306