Powered by AppSignal & Oban Pro

Ch1: ML in Elixir

Ch1 - ML.livemd

Ch1: ML in Elixir

Mix.install([
  {:axon, "~> 0.5"},
  {:nx, "~> 0.5"},
  {:explorer, "~> 0.5"},
  {:kino, "~> 0.8"},
])

Section

require Explorer.DataFrame, as: DF
# Load data set
iris = Explorer.Datasets.iris()
# normalise data

cols = ~w(sepal_width sepal_length petal_length petal_width)
normalized_iris =
  DF.mutate(
    iris,
    for col <- across(^cols) do
      {col.name, (col - mean(col)) / standard_deviation(col)}
    end
  )

# convert your species column to a categorical feature
normalized_iris = DF.mutate(normalized_iris, [species: Explorer.Series.cast(species, :category)])

# shuffle to simulate less ordered, more IRL data. Useful before splitting into sets
shuffled_normalized_iris = DF.shuffle(normalized_iris)
# Split into test and training 

train_df = DF.slice(shuffled_normalized_iris, 0..119)
test_df = DF.slice(shuffled_normalized_iris, 120..149)
# Convert labels to one-hot encoding

feature_columns = [
  "sepal_length",
  "sepal_width",
  "petal_length",
  "petal_width"
]

x_train =
  Nx.stack(train_df[feature_columns], axis: -1)
  |> Nx.as_type(:f32)

y_train =
  train_df["species"]
  |> Nx.stack(axis: -1)
  |> Nx.equal(Nx.iota({1, 3}, axis: -1))

x_test =
  Nx.stack(test_df[feature_columns], axis: -1)
  |> Nx.as_type(:f32)

y_test =
  test_df["species"]
  |> Nx.stack(axis: -1)
  |> Nx.equal(Nx.iota({1, 3}, axis: -1))
# Defining the model

model = 
  Axon.input("iris_features", shape: {nil, 4})
  |> Axon.dense(3, activation: :softmax)
# Visualise model

Axon.Display.as_graph(model, Nx.template({1,4}, :f32))
# Create stream for minibatches

data_stream = Stream.repeatedly(fn -> {x_train, y_train} end)
# Declare and run training loop

trained_model_state =
  model
  |> Axon.Loop.trainer(:categorical_cross_entropy, :sgd)
  |> Axon.Loop.metric(:accuracy)
  |> Axon.Loop.run(data_stream, %{}, iterations: 500, epochs: 10)
# Evaluate model

data = [{x_test, y_test}] 
  
model
  |> Axon.Loop.evaluator()
  |> Axon.Loop.metric(:accuracy)
  |> Axon.Loop.run(data, trained_model_state)