Search code examples
pythonnumpyshapesdimensions

Python- list with arrays shape issues


I'm creating a code to run a perceptron algorithm and I can't create a random matrix the way I need it:

from random import choice
from numpy import array, dot, random
unit_step = lambda x: -1 if x < 0 else 1
import numpy as np
m=3 #this will be the number of rows
allys=[]
for j in range(m):
    aa=np.random.rand(1,3)
    tt=np.random.rand(3)
    yy=dot(aa,tt)
    ally = [aa, yy]
    allys.append(ally)
print  "allys", allys

w = random.rand(3)
errors = []
eta = 0.2
n = 10
x=[1,3]

for i in xrange(n):
    print i 
    x, expected = choice(allys)
    print "x", x

And I get the problem here:

    result = dot(x,w)    
    error = expected - unit_step(result) 
    errors.append(error) 
    w += eta * error * x 
    print x, expected, w, error, result, errors

The log says

w += eta * error * x ValueError: non-broadcastable output operand with shape (3,) doesn't match the broadcast shape (1,3)

The idea is to get result looping randomly over the "table" allys.

How can I solve this? What is shape(3,)?

Thanks!


Solution

  • The error message actually tells you what is wrong. The result of your multiplication is a (1,3) array (2D array, one row, three columns), whereas you try to add it into a 3-element vector.

    Both arrays have three elements in a row, so if you do this:

    w = w + eta * error * x
    

    there will be no error on that line, but the resulting vector will actually be a (1,3) array. That is unwanted, because then your dot does not work.

    There are several ways to fix the problem, but possibly the easiest to read is to reshape x for the calculation to be a 3-element vector (1D array):

    w += eta * error * x.reshape(3,)
    

    Possibly a cleaner solution would be to define w as a (1,3) 2D array, as well, and then transpose w for the dot. This is really a matter of taste.