mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-11-06 11:46:30 +08:00
Remove breaks to improve readability
This commit is contained in:
parent
cd2c3bd5a8
commit
026945e669
1 changed files with 0 additions and 52 deletions
|
|
@ -39,8 +39,6 @@ Systems of equations are a central theme in numerical computing.
|
|||
These equations are often expressed and solved with multidimensional
|
||||
arrays. For example, this is a two dimensional array:
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
$$
|
||||
\begin{bmatrix}
|
||||
1 & 2 \\
|
||||
|
|
@ -48,8 +46,6 @@ $$
|
|||
\end{bmatrix}
|
||||
$$
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
Elixir programmers typically express a similar data structure using
|
||||
a list of lists, like this:
|
||||
|
||||
|
|
@ -77,8 +73,6 @@ than `Enum.map/2` and `Enum.reduce/3`.
|
|||
In this section, we'll look at some of the various tools for
|
||||
creating and interacting with tensors.
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
To get started, we'll first need to include the Nx dependency.
|
||||
In Livebook, we can simply use Mix install. At the time of this writing,
|
||||
there's no Hex package for Nx, so we'll use a git
|
||||
|
|
@ -102,8 +96,6 @@ Now, everything is set up, so we're ready to create some tensors.
|
|||
|
||||
### Creating tensors
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
Start out by getting a feel for Nx through its documentation.
|
||||
Do so through the IEx helpers, like this:
|
||||
|
||||
|
|
@ -138,8 +130,6 @@ The result shows all of the major fields that make up a tensor:
|
|||
* The shape of the tensor, going left to right, with the outside dimensions listed first.
|
||||
* The names of each dimension.
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
We can easily convert it to a binary:
|
||||
|
||||
```elixir
|
||||
|
|
@ -168,8 +158,6 @@ because they must often be processed. Elixir binaries make quick work
|
|||
of dealing with numerical data structured for platforms other than
|
||||
Elixir.
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
We can get any cell of the tensor:
|
||||
|
||||
```elixir
|
||||
|
|
@ -200,8 +188,6 @@ Now,
|
|||
* return a `{2, 2}` tensor containing the first two columns
|
||||
of the first two rows
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
We can get information about this most recent term with
|
||||
the IEx helper `i`, like this:
|
||||
|
||||
|
|
@ -223,8 +209,6 @@ to get more documentation about tensors. We could also open an Elixir
|
|||
cell, type Nx.tensor, and hover the cursor over the word `tensor`
|
||||
to see the help about that function.
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
We can get the shape of the tensor with `Nx.shape/1`:
|
||||
|
||||
```elixir
|
||||
|
|
@ -242,8 +226,6 @@ changes the metadata, so it has no notable cost.
|
|||
|
||||
The new tensor has the same type, but a new shape.
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
Now, reshape the tensor to contain three dimensions with
|
||||
one batch, one row, and four columns.
|
||||
|
||||
|
|
@ -263,8 +245,6 @@ Nx.tensor([[1, 2, 3]], names: [:rows, :cols], type: {:u, 8})
|
|||
We created a tensor of the shape `{1, 3}`, with the type `u8`,
|
||||
the values `[1, 2, 3]`, and two axes named `rows` and `cols`.
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
Now we know how to create tensors, so it's time to do something with them.
|
||||
|
||||
## Tensor aware functions
|
||||
|
|
@ -324,8 +304,6 @@ Nx.sum(tensor, axes: [:x])
|
|||
Nx sums the values across the `x` dimension: `1 + 2` in the first row
|
||||
and `3 + 4` in the second row.
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
Now,
|
||||
|
||||
* create a `{2, 2, 2}` tensor
|
||||
|
|
@ -341,8 +319,6 @@ Sometimes, we need to combine two tensors together with an
|
|||
operator. Let's say we wanted to subtract one tensor from
|
||||
another. Mathematically, the expression looks like this:
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
$$
|
||||
\begin{bmatrix}
|
||||
5 & 6 \\
|
||||
|
|
@ -358,8 +334,6 @@ $$
|
|||
\end{bmatrix}
|
||||
$$
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
To solve this problem, add each integer on the left with the
|
||||
corresponding integer on the right. Unfortunately, we cannot
|
||||
use Elixir's built-in subtraction operator as it is not tensor-aware.
|
||||
|
|
@ -383,8 +357,6 @@ Often, the dimensions of tensors in an operator don't match.
|
|||
For example, you might want to subtract a `1` from every
|
||||
element of a `{2, 2}` tensor, like this:
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
$$
|
||||
\begin{bmatrix}
|
||||
1 & 2 \\
|
||||
|
|
@ -396,8 +368,6 @@ $$
|
|||
\end{bmatrix}
|
||||
$$
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
Mathematically, it's the same as this:
|
||||
|
||||
$$
|
||||
|
|
@ -415,8 +385,6 @@ $$
|
|||
\end{bmatrix}
|
||||
$$
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
That means we need a way to convert `1` to a `{2, 2}` tensor.
|
||||
`Nx.broadcast/2` solves that problem. This function takes
|
||||
a tensor or a scalar and a shape.
|
||||
|
|
@ -451,8 +419,6 @@ Nx.subtract(10, tensor)
|
|||
|
||||
Or subtract a row or column. Mathematically, it would look like this:
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
$$
|
||||
\begin{bmatrix}
|
||||
1 & 2 \\
|
||||
|
|
@ -467,12 +433,8 @@ $$
|
|||
\end{bmatrix}
|
||||
$$
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
which is the same as this:
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
$$
|
||||
\begin{bmatrix}
|
||||
1 & 2 \\
|
||||
|
|
@ -488,8 +450,6 @@ $$
|
|||
\end{bmatrix}
|
||||
$$
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
This rewrite happens in Nx too, also through a broadcast. We want to
|
||||
broadcast the tensor `[1, 2]` to match the `{2, 2}` shape, like this:
|
||||
|
||||
|
|
@ -531,8 +491,6 @@ h Nx.broadcast
|
|||
Much of the time, you won't have to broadcast yourself. Many of
|
||||
the functions and operators Nx supports will do so automatically.
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
We can use tensor-aware operators via various `Nx` functions and
|
||||
many of them implicitly broadcast tensors.
|
||||
|
||||
|
|
@ -556,8 +514,6 @@ over classic Elixir functions.
|
|||
individual operations and using a just-in-time (JIT) compiler to emit
|
||||
highly specialized native code for the desired computation unit.
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
We don't have to do anything special to get access to
|
||||
get tensor awareness beyond importing `Nx.Defn` and writing
|
||||
our code within a `defn` block.
|
||||
|
|
@ -612,8 +568,6 @@ defn subtract(a, b) do
|
|||
end
|
||||
```
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
Now, it's your turn. Add a `defn` to `TensorMath`
|
||||
that accepts two tensors representing the lengths of sides of a
|
||||
right triangle and uses the pythagorean theorem to return the
|
||||
|
|
@ -647,20 +601,14 @@ a function returning the gradient. We have two functions: `poly/1`
|
|||
is a simple numerical definitin, and `poly_slope_at/1` returns
|
||||
its gradient:
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
$$
|
||||
poly: f(x) = 3x^2 + 2x + 1 \\
|
||||
$$
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
$$
|
||||
polySlopeAt: g(x) = 6x + 2
|
||||
$$
|
||||
|
||||
<!-- livebook:{"break_markdown":true} -->
|
||||
|
||||
Here's the Elixir equivalent of those functions:
|
||||
|
||||
```elixir
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue