import numpy as np
import copy
pairs = [(2, 3), (3, 4), (4, 5)]
array_of_arrays = np.array([np.arange(a*b).reshape(a,b) for (a, b) in pairs])
a = copy.deepcopy(array_of_arrays)
Feel free to read up more about this here.
Oh, here is simplest test case:
a[0][0,0]
print a[0][0,0], array_of_arrays[0][0,0]
Answer from Tomasz Plaskota on Stack Overflowimport numpy as np
import copy
pairs = [(2, 3), (3, 4), (4, 5)]
array_of_arrays = np.array([np.arange(a*b).reshape(a,b) for (a, b) in pairs])
a = copy.deepcopy(array_of_arrays)
Feel free to read up more about this here.
Oh, here is simplest test case:
a[0][0,0]
print a[0][0,0], array_of_arrays[0][0,0]
In [276]: array_of_arrays
Out[276]:
array([array([[0, 1, 2],
[3, 4, 5]]),
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]]),
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])], dtype=object)
array_of_arrays is dtype=object; that means each element of the array is a pointer to an object else where in memory. In this case those elements are arrays of different sizes.
a = array_of_arrays[:]
a is a new array, but a view of array_of_arrays; that is, it has the same data buffer (which in this case is list of pointers).
b = array_of_arrays[:][:]
this is just a view of a view. The second [:] acts on the result of the first.
c = np.array(array_of_arrays, copy=True)
This is the same as array_of_arrays.copy(). c has a new data buffer, a copy of the originals
If I replace an element of c, it will not affect array_of_arrays:
c[0] = np.arange(3)
But if I modify an element of c, it will modify the same element in array_of_arrays - because they both point to the same array.
The same sort of thing applies to nested lists of lists. What array adds is the view case.
d = np.array([np.array(x, copy=True) for x in array_of_arrays])
In this case you are making copies of the individual elements. As others noted there is a deepcopy function. It was designed for things like lists of lists, but works on arrays as well. It is basically doing what you do with d; recursively working down the nesting tree.
In general, an object array is like list nesting. A few operations cross the object boundary, e.g.
array_of_arrays+1
but even this effectively is
np.array([x+1 for x in array_of_arrays])
One thing that a object array adds, compared to a list, is operations like reshape. array_of_arrays.reshape(3,1) makes it 2d; if it had 4 elements you could do array_of_arrays.reshape(2,2). Some times that's handy; other times it's a pain (it's harder to iterate).
I've done a ton of reading about this and I sort of know the difference between the two, but I still don't know when I need to use copy.copy() vs copy.deepcopy(). It seems like copy.copy() makes a new object of the "container" (for instance, if it is a list then you get a new list object) but then populates this container with the references to the original element objects (so each element in the two different lists point to the same spot in memory).
Essentially, my question is that I have a bunch of numpy arrays and I don't think I'm using copy correctly (or if I need ot be using it at all). It seems like if I am only doing assignments or using these values to set other values (eg output = self.weights*input or whatever) then I don't need to make copies (its fine that the references point to the same spot in memory since I just need read not write access), but if I am doing things like increments / decrements or setting the new value based on the previous value, then I would be changing the values in memory and these are shared by all my objects? Some code:
For instance, let's say I have some Parent class and it has its children Child objects and the parent sends its models to the children and the children update the models based on their own data. Specifically, each child should get (a copy?) the parent's weight matrix (numpy array) to use as initialization, and then start updating its own matrix (not shared with any other children or the parent).
parent = Parent()
child1 = Child()
child2 = Child()
...
childN = Child()
for child in children_list:
child.weights = parent.weights # copy? deepcopy?
for child in children_list:
for _ in num_grad_steps:
child.weights -= child.learning_rate * child.gradient(child.weights, child.input_data)
# Send the updated weights back to the parent
parent.new_weights_list.append(child.weights)
In this case, child.weights is being updated by each child (note I don't want a single matrix that is updated by all children, I want one matrix as initialization, then every child runs with it so I end up with N unique final matrices), and if it is either just the same object (basic assignment: child.weights = self.weights) or just a shallow copy (child.weights = copy.copy(parent.weights)) then FOR ALL THE CHILDREN the weights are shared instead of each child getting the same initial matrix and privately updating its own copy, right? If I instead switch this to child.weights = copy.deepcopy(parent.weights) then I think this fixes it, but since my weights matrix is pretty large this just takes an extremely long time to run (and it seems like I'm missing something, like it shouldn't be this hard. I feel like code I see online in similar applications doesn't do this, but many don't have the weights distributed across so many objects at once I guess?). Do I need to be using deepcopy or is there something I'm missing? Greatly appreciate any help!
Why is copying a list so damn difficult in python?
Do I need to be using deepcopy with numpy arrays in this situation?
Error Help: ValueError: Object Too Deep for Desired Array
Deep learning: Memory error with arrays and lists in python
First of all, 25396 images seems like a very low number, especially if you're building your own CNN. The n/w will most likely always overfit to your data and pick up sampling errors. Karpathy himself has quoted - "Don't try to be a hero". Most of the time, you'll be battling the variance, which will just result in you dumbing down your own network. Have you tried transfer learning?
Regarding the memory problem - It's pretty obvious. You're loading two tensors of shapes (25369, 204, 204, 3) and (25369, 39) directly into memory, which seems to be too much. If you're using Keras, use the ImageDataGenerator utility and it's flow_from_directory method. You can stream images from folders with a specific batch size - very handy while handling a large number of images.
More on reddit.com