(1) ravel() usually (see @user2357112 's comments below) returns an object that references the items of the input rather than making a new copy:
>>> a = np.arange(15)
>>> b = a.ravel()
>>> b
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>> a[0]=5
>>> b
array([ 5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
sys.getsizeof(array.ravel()) doesn't change no matter how big array is.
(2) Similarly, reshape() doesn't copy the items:
>>> b = a.reshape(3,5)
>>> b
array([[ 5, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
>>> a[0] = 7
>>> b
array([[ 7, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
Again, the memory usage stays constant when you increase the size of the input array (and adjust the shape accordingly).
(3) Yes, the other answers are right in that sys.getsizeof() may be missing some of the memory needed by third party objects. However, a simple test suggests that the main part of numpy arrays is accounted for:
>>> sys.getsizeof(np.arange(20))
256
>>> sys.getsizeof(np.arange(40))
416
>>> sys.getsizeof(np.arange(400))
3296