Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Harness the power of math

math-with-nx.livemd

Harness the power of math

Section

Mix.install([
  {:nx, "~> 0.5"},
  {:exla, "~> 0.5"},
  {:kino, "~> 0.8"},
  {:stb_image, "~> 0.6"},
  {:vega_lite, "~> 0.1"},
  {:kino_vega_lite, "~> 0.1"}
])
# Make EXLA the default backend
Nx.default_backend(EXLA.Backend)
# Create Nx vectors
a = Nx.tensor([1, 2, 3])
b = Nx.tensor([4.0, 5.0, 6.0])
c = Nx.tensor([1, 0, 1], type: {:u, 8})
IO.inspect(a, label: :a)
IO.inspect(b, label: :b)
IO.inspect(c, label: :c)
# Vector addition
Nx.add(Nx.tensor([32, 10, 14]), Nx.tensor([10, 24, 21]))
sales_day_1 = Nx.tensor([32, 10, 14])
sales_day_2 = Nx.tensor([10, 24, 21])
total_sales = Nx.add(sales_day_1, sales_day_2)

keep_rate = 0.9
# scalar multiplication, a broadcasted multiplication of a scaler and a vector
unreturned_sales = Nx.multiply(keep_rate, total_sales)
price_per_product = Nx.tensor([9.95, 10.95, 5.99])
revenue_per_product = Nx.multiply(unreturned_sales, price_per_product)
# Transpose,A matrix that is flipped along it's diagonals
sales_matrix =
  Nx.tensor([
    [32, 10, 14],
    [10, 24, 21]
  ])

Nx.transpose(sales_matrix)
# No difference between row and column vectors
vector = Nx.tensor([1, 2, 3])
Nx.transpose(vector)
# Linear transformation/Linear map-> a function that maps input to output
invert_color_channels =
  Nx.tensor([
    [-1, 0, 0],
    [0, -1, 0],
    [0, 0, -1]
  ])

image =
  "model.jpg"
  |> StbImage.read_file!()
  |> StbImage.resize(256, 256)
  |> StbImage.to_nx()

image
|> Nx.dot(invert_color_channels)
|> Nx.as_type({:u, 8})
|> Kino.Image.new()
serpian_transformation =
  Nx.tensor([
    [0.393, 0.349, 0.272],
    [0.769, 0.686, 0.534],
    [0.189, 0.168, 0.131]
  ])

image
|> Nx.dot(serpian_transformation)
|> Nx.as_type({:u, 8})
|> Kino.Image.new()
simulation = fn key ->
  {value, key} = Nx.Random.uniform(key)
  if Nx.to_number(value) < 0.5, do: {0, key}, else: {1, key}
end
key = Nx.Random.key(42)

for n <- [10, 100, 1000, 10000] do
  Enum.map_reduce(1..n, key, fn _, key -> simulation.(key) end)
  |> elem(0)
  |> Enum.sum()
  |> IO.inspect()
end
defmodule BerryFarm do
  import Nx.Defn

  defn profits(trees) do
    trees
    |> Nx.subtract(1)
    |> Nx.pow(4)
    |> Nx.negate()
    |> Nx.add(Nx.pow(trees, 3))
    |> Nx.add(Nx.pow(trees, 2))
  end
end
trees = Nx.linspace(0, 4, n: 100)
profits = BerryFarm.profits(trees)

alias VegaLite, as: Vl

Vl.new(title: "Berry Profits", width: 720, height: 540)
|> Vl.data_from_values(%{
  trees: Nx.to_flat_list(trees),
  profits: Nx.to_flat_list(profits)
})
|> Vl.mark(:line, interpolate: :basis)
|> Vl.encode_field(:x, "trees", type: :quantitative)
|> Vl.encode_field(:y, "profits", type: :quantitative)
defmodule BerryFarmProfits do
  import Nx.Defn

  defn profits(trees) do
    -((trees - 1) ** 4) + trees ** 3 + trees ** 2
  end

  defn profits_derivative(trees) do
    grad(trees, &amp;profits/1)
  end
end

trees = Nx.linspace(0, 4, n: 100)
profits = BerryFarmProfits.profits(trees)
profits_derivative = BerryFarmProfits.profits_derivative(trees)

alias VegaLite, as: Vl

title = "Berry Profits and Profits Rate of Change"

Vl.new(title: title, width: 720, height: 540)
|> Vl.data_from_values(%{
  trees: Nx.to_flat_list(trees),
  profits: Nx.to_flat_list(profits),
  profits_derivative: Nx.to_flat_list(profits_derivative)
})
|> Vl.layers([
  Vl.new()
  |> Vl.mark(:line, interpolate: :basis)
  |> Vl.encode_field(:x, "trees", type: :quantitative)
  |> Vl.encode_field(:y, "profits", type: :quantitative),
  Vl.new()
  |> Vl.mark(:line, interpolate: :basis)
  |> Vl.encode_field(:x, "trees", type: :quantitative)
  |> Vl.encode_field(:y, "profits_derivative", type: :quantitative)
  |> Vl.encode(:color, value: "#ff0000")
])