Rokner
Rokner

Reputation: 309

Python strange syntaxis

I have been learning about ANN but the book I'm reading has examples in Python. The problem is that I have never written in Python and these lines of code are too hard for me to understand:

sizes = [3,2,4]
self.weights = [np.random.randn(y, x) 
                    for x, y in zip(sizes[:-1], sizes[1:])]

I read some things about it and found out that the randn() function returns an array with y elements and x dimensions populated with random numbers between 0 and 1. zip() connects two arrays into one. sizes[:-1] returns the last element and sizes[1:] return the array without its first element.

But with all of this I still can't explain to myself what would this generate.

Upvotes: 3

Views: 277

Answers (4)

Chad S.
Chad S.

Reputation: 6631

sizes[:-1] will return the sublist [3,2] (that is, all the elements except the last one).

sizes[1:] will return the sublist [2,4] (that is, all the elements except the first one).

zip([a,b], [c,d]) gives [(a,c), (b,d)].

So zipping the two lists above gives you [(3,2), (2,4)]

The construction of weights is a list comprehension. Therefore this code is equivalent to

weights = []

for x,y in [(3,2), (2,4)]:
       weights.append(np.random.randn(y, x))

So the final result would be the same as

[ np.random.randn(2,3), 
  np.random.randn(4,2) ]

Upvotes: 5

fstab
fstab

Reputation: 5039

a lot is going on here.

let's decompose that expression: as you said zip will create a list of tuples containing each element of sizes and it's successor (except for the last one)

The comprehension list [ ... for x, y in zip(..)] works as follows: the tuple is exploded in the variables x and y and those are passed onto np.random.randn to create a list of random matrices.

These matrices are characterized by having the first dimension (rows) long as specified by each element of sizes and the second dimension (columns) long as the following element.

Interestingly, the matrices have compatible dimensions to be multiplied to each other in that sequence, but I guess that this is not the purpose. The purpose of each matrix in the weights list is to specify the weights that are between fully connected layers of neurons. Good luck! Seems a fun project!

Post Scriptum

since you are a beginner: you can add the import pdb; pdb.set_trace() statement anywhere in your code to get a breakpoint. Then you can just copy and paste different parts of any expression to see what comes out. For example: ipdb> print sizes [3, 2, 4] ipdb> print sizes[:-1] [3, 2] ipdb> print sizes[1:] [2, 4] ipdb> print zip(sizes[:-1], sizes[1:]) [(3, 2), (2, 4)] ipdb> print [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])] [array([[ 0.25933943, 0.59855688, 0.49055744], [ 0.94602292, -0.8012292 , 0.56352986]]), array([[ 0.81328847, -0.53234407], [-0.272656 , -1.24978881], [-1.2306653 , 0.56038948], [ 1.15837792, 1.19408038]])]

Upvotes: 2

James Mertz
James Mertz

Reputation: 8769

Let's break this up into chunks:


self.weights = [some junk]

is going to be a list comprehension. Meaning, do the some junk stuff and you'll end up with a list of elements from that. Usually these look like so:

self.weights = [some_func(x) for x in a_list]

This is the equivalent of:

self.weights = []
for x in a_list:
    self.weights.append(some_func(x))

zip(a, b)

Will piecewise combine the elements of a and b into tuple pairs:

(a1, b1), (a2, b2), (a3, b3), ...

for x, y in zip(a, b):

This iterates through that tuple pairs talked about above


sizes[:-1]

This is stating to get all the elements of list sizes except the last item (-1).

sizes[1:]

This is stating to get the all the elements of list sizes except the first item.


So, finally piecing this all together you get:

self.weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])] 

Which is a list comprehension iterating through the tuple pairs of first sizes from 2nd item to last and second from 1st item to next to last, create a random number based on those two parameters, then append to a list that is stored as self.weights

Upvotes: 2

antlarac
antlarac

Reputation: 28

This code generates a list and assignes it to the self.weights attribute (this is maybe inside a class? That would explain the self). The second line is a list comprehension. It generates a list, applying the function randn to pairs of variables (x, y)

Upvotes: 0

Related Questions