x = tf.range(12, dtype=tf.float32)
xDive into Deep Learning · §1.1
Storing & transforming data with tensors
The n-dimensional arrays that every model in this book is built on.
Motivation
ndarray.Rank = number of axes; shape = size per axis.
01
Getting Started
creating & inspecting tensors
Getting Started
arange(n) builds a 1-D tensor of evenly spaced values:
<tf.Tensor: shape=(12,), dtype=float32, numpy=
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.],
dtype=float32)>
TensorShape([12])
numel() → total elements. shape → size along each axis. We ask for float32 because nearly all neural-net math is in floating point.
Getting Started
For weight init, randn draws from \mathcal{N}(0, 1):
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[ 1.3810029 , -0.22911465, -0.5846182 , 0.43986928],
[-0.56185037, 0.5317954 , 2.0249772 , 0.27406558],
[-0.27821013, -0.01750856, -0.08361343, -0.95873785]],
dtype=float32)>
Also zeros, ones, full(shape, value), eye(n). Random values break symmetry when initializing network weights; lists let you type a tensor by hand.
Getting Started
Same elements in a new shape; numel is preserved:
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]], dtype=float32)>
Usually no copy: only the shape metadata changes. Use -1 to infer an axis: x.reshape(3, -1).
02
Indexing & Slicing
reading & writing elements, rows, ranges
Indexing & Slicing
X[-1] is the last row;X[1:3] is rows 1–2:
(<tf.Tensor: shape=(4,), dtype=float32, numpy=array([ 8., 9., 10., 11.], dtype=float32)>,
<tf.Tensor: shape=(2, 4), dtype=float32, numpy=
array([[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]], dtype=float32)>)
0-based; negatives count from the end; a range a:b is half-open (b excluded).
Indexing & Slicing
Indexing & Slicing
A slice on the left assigns to a whole region at once:
<tf.Variable 'Variable:0' shape=(3, 4) dtype=float32, numpy=
array([[12., 12., 12., 12.],
[12., 12., 12., 12.],
[ 8., 9., 10., 11.]], dtype=float32)>
03
Operations
elementwise math, joins, comparisons, broadcasting
Operations
The operators + - * / ** act elementwise on matching shapes:
(<tf.Tensor: shape=(4,), dtype=float32, numpy=array([ 3., 4., 6., 10.], dtype=float32)>,
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([-1., 0., 2., 6.], dtype=float32)>,
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([ 2., 4., 8., 16.], dtype=float32)>,
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0.5, 1. , 2. , 4. ], dtype=float32)>,
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([ 1., 4., 16., 64.], dtype=float32)>)
Unary functions like exp map each element:
<tf.Tensor: shape=(12,), dtype=float32, numpy=
array([1.0000000e+00, 2.7182817e+00, 7.3890562e+00, 2.0085537e+01,
5.4598148e+01, 1.4841316e+02, 4.0342880e+02, 1.0966332e+03,
2.9809580e+03, 8.1030840e+03, 2.2026467e+04, 5.9874145e+04],
dtype=float32)>
Any scalar→scalar map (exp, sin, log) extends to a whole tensor.
Operations
Operations
Comparisons return a boolean tensor.
A ready-made mask:
<tf.Tensor: shape=(3, 4), dtype=bool, numpy=
array([[False, True, False, True],
[False, False, False, False],
[False, False, False, False]])>
==, <, > build masks; sum, mean, max collapse axes; add dim= to reduce just one.
Operations · the exception
Size-1 axes are virtually stretched
a 3\times1 plus a 1\times2 gives a 3\times2:
<tf.Tensor: shape=(3, 2), dtype=int32, numpy=
array([[0, 1],
[1, 2],
[2, 3]], dtype=int32)>
Any axis of size 1 stretches to match the other tensor, without a copy.
Compatible only if each axis is equal or 1.
Operations · the exception
Line up (3, 2) and (2, 3) from the right, pairing 2 with 3 and 3 with 2: no pair matches, neither member is 1, so the framework raises rather than guessing:
{{function_node __wrapped__AddV2_device_/job:localhost/replica:0/task:0/device:GPU:0}} required broadcastable shapes [Op:AddV2] name:
Broadcasting aligns shapes from the right; each axis pair must be equal or 1.
04
Memory & Interop
in-place updates and leaving the tensor world
Y = Y + XPerformance
Every arithmetic expression allocates a new tensor
costly when Y is gigabytes and updated many times per second:
False
id(Y) changed: Y is now bound to a new tensor object.
Performance
Interop
Convert to / from a NumPy ndarray:
(numpy.ndarray, tensorflow.python.framework.ops.EagerTensor)
The result is a copy; host/device arrays don’t share storage here.
Wrap-up
arange, zeros, ones, randn, tensor([…])..shape, .numel(), reshape.cat.X[:] = …, +=), or in JAX via jit buffer reuse..item() for scalars.