when we reshape numpy array, how is the stride size inferred?
I have an 1x1024 1-d array (flattened image). To see the image, I want to reshape its size as 32x32.
I can easily achieve this by doing x.reshape(-1,32) and it works as I intended. It doesn't screw the image. It reads the 1d array with 32-width stride each time.
Say this time, there are 4 images, sized 32 by 8. What's the safe way to reshape this?
What is the logic behind how strides are defined? Is it always starting from the largest dimension (say, 3d-&gt;2d-&gt;1d)? It seems like it..
In [2]: a = np.arange(1024)


In [3]: a.reshape(4,32,8)
Out[3]:
array([[[   0,    1,    2, ...,    5,    6,    7],
        [   8,    9,   10, ...,   13,   14,   15],
        [  16,   17,   18, ...,   21,   22,   23],
        ...,
        [ 232,  233,  234, ...,  237,  238,  239],
        [ 240,  241,  242, ...,  245,  246,  247],
        [ 248,  249,  250, ...,  253,  254,  255]],

       [[ 256,  257,  258, ...,  261,  262,  263],
        [ 264,  265,  266, ...,  269,  270,  271],
        [ 272,  273,  274, ...,  277,  278,  279],
        ...,
        [ 488,  489,  490, ...,  493,  494,  495],
        [ 496,  497,  498, ...,  501,  502,  503],
        [ 504,  505,  506, ...,  509,  510,  511]],

       [[ 512,  513,  514, ...,  517,  518,  519],
        [ 520,  521,  522, ...,  525,  526,  527],
        [ 528,  529,  530, ...,  533,  534,  535],
        ...,
        [ 744,  745,  746, ...,  749,  750,  751],
        [ 752,  753,  754, ...,  757,  758,  759],
        [ 760,  761,  762, ...,  765,  766,  767]],

       [[ 768,  769,  770, ...,  773,  774,  775],
        [ 776,  777,  778, ...,  781,  782,  783],
        [ 784,  785,  786, ...,  789,  790,  791],
        ...,
        [1000, 1001, 1002, ..., 1005, 1006, 1007],
        [1008, 1009, 1010, ..., 1013, 1014, 1015],
        [1016, 1017, 1018, ..., 1021, 1022, 1023]]])

In [4]: a.reshape(4,-1,8)
Out[4]:
array([[[   0,    1,    2, ...,    5,    6,    7],
        [   8,    9,   10, ...,   13,   14,   15],
        [  16,   17,   18, ...,   21,   22,   23],
        ...,
        [ 232,  233,  234, ...,  237,  238,  239],
        [ 240,  241,  242, ...,  245,  246,  247],
        [ 248,  249,  250, ...,  253,  254,  255]],

       [[ 256,  257,  258, ...,  261,  262,  263],
        [ 264,  265,  266, ...,  269,  270,  271],
        [ 272,  273,  274, ...,  277,  278,  279],
        ...,
        [ 488,  489,  490, ...,  493,  494,  495],
        [ 496,  497,  498, ...,  501,  502,  503],
        [ 504,  505,  506, ...,  509,  510,  511]],

       [[ 512,  513,  514, ...,  517,  518,  519],
        [ 520,  521,  522, ...,  525,  526,  527],
        [ 528,  529,  530, ...,  533,  534,  535],
        ...,
        [ 744,  745,  746, ...,  749,  750,  751],
        [ 752,  753,  754, ...,  757,  758,  759],
        [ 760,  761,  762, ...,  765,  766,  767]],

       [[ 768,  769,  770, ...,  773,  774,  775],
        [ 776,  777,  778, ...,  781,  782,  783],
        [ 784,  785,  786, ...,  789,  790,  791],
        ...,
        [1000, 1001, 1002, ..., 1005, 1006, 1007],
        [1008, 1009, 1010, ..., 1013, 1014, 1015],
        [1016, 1017, 1018, ..., 1021, 1022, 1023]]])

In [5]: a.reshape(4,8,32)
Out[5]:
array([[[   0,    1,    2, ...,   29,   30,   31],
        [  32,   33,   34, ...,   61,   62,   63],
        [  64,   65,   66, ...,   93,   94,   95],
        ...,
        [ 160,  161,  162, ...,  189,  190,  191],
        [ 192,  193,  194, ...,  221,  222,  223],
        [ 224,  225,  226, ...,  253,  254,  255]],

       [[ 256,  257,  258, ...,  285,  286,  287],
        [ 288,  289,  290, ...,  317,  318,  319],
        [ 320,  321,  322, ...,  349,  350,  351],
        ...,
        [ 416,  417,  418, ...,  445,  446,  447],
        [ 448,  449,  450, ...,  477,  478,  479],
        [ 480,  481,  482, ...,  509,  510,  511]],

       [[ 512,  513,  514, ...,  541,  542,  543],
        [ 544,  545,  546, ...,  573,  574,  575],
        [ 576,  577,  578, ...,  605,  606,  607],
        ...,
        [ 672,  673,  674, ...,  701,  702,  703],
        [ 704,  705,  706, ...,  733,  734,  735],
        [ 736,  737,  738, ...,  765,  766,  767]],

       [[ 768,  769,  770, ...,  797,  798,  799],
        [ 800,  801,  802, ...,  829,  830,  831],
        [ 832,  833,  834, ...,  861,  862,  863],
        ...,
        [ 928,  929,  930, ...,  957,  958,  959],
        [ 960,  961,  962, ...,  989,  990,  991],
        [ 992,  993,  994, ..., 1021, 1022, 1023]]])



reshape does not reorder the underlying values.  The array is stored as a 1d array of bytes, plus shape, strides and dtype which are used to view it as particular multidimensional array.
You can look at the strides attribute:
In [513]: arr = np.arange(1024)                                                                      
In [514]: arr.shape, arr.strides                                                                     
Out[514]: ((1024,), (8,))
In [515]: arr1=arr.reshape(32,32);arr1.shape, arr1.strides                                           
Out[515]: ((32, 32), (256, 8))
In [516]: arr1=arr.reshape(4,32,8);arr1.shape, arr1.strides                                          
Out[516]: ((4, 32, 8), (2048, 64, 8))

With 1d, it just steps 8 bytes at a time (the size of the int64)
With 2d, 256=32*8; to traverse rows it has to step 256 bytes
With 3d, 2048 = 32 * 8 * 8; the step between blocks.
And for fun, look at a transpose:
In [517]: arr1=arr.reshape(4,32,8).T;arr1.shape, arr1.strides                                        
Out[517]: ((8, 32, 4), (8, 64, 2048))

shape has been reversed, and so has strides.
Often when reshaping an image array into blocks, we need to reshape into small blocks, do partial transpose, and reshape to a target.  The first reshape and transpose create a view, just playing with the shapes and strides.  But the last reshape often requires a copy.
