This document discusses using neuroevolution techniques to evolve neural networks represented as ONNX models in Elixir. It describes representing neural network genotypes as ONNX graphs that can be mutated and evolved over generations. Mutation functions are defined that modify parameters in the ONNX models, and an approach is outlined for loading ONNX models into Elixir and mutating their attributes to evolve new models. Opportunities are mentioned for developing additional tools for working with ONNX models in Elixir.
32. Model Library
defmodule GN.Library do
use Agent
def start_link(opts []) do
opts = Keyword.put_new(opts, :name, __MODULE__)
Agent.start_link(fn -> %{} end, opts)
end
def put(pid __MODULE__, net) do
Agent.update(pid, &Map.put(&1, net.id, net))
end
def get_all(pid __MODULE__) do
Agent.get(pid, & &1)
end
end
40. Layers in Elixir
def dense(py, n, activation) do
act_type = Atom.to_string(activation)
py |> call(dense(n, act_type))
end
def activation(py, activation) do
act_type = Atom.to_string(activation)
py |> call(activation(act_type))
end
def dropout(py, rate) do
py |> call(dropout(rate))
end
def batch_norm(py) do
py |> call(batch_norm())
end
51. def mutate(
%Onnx.NodeProto{
attribute: [%Onnx.AttributeProto{t: %Onnx.TensorProto{float_data: float_data}}]
} = layer,
mutation_rate
) do
mutated_data = mutate_params(float_data, mutation_rate)
update_in(
layer,
[Access.key!(:attribute), Access.all(), Access.key!(:t), Access.key!(:float_data)],
fn d -> mutated_data end
)
end
Mutation V2
52. Mutation V2
def mutate_params(params, mutation_rate) do
for param <- params do
cond do
should_mutate(mutation_rate) ->
cond do
is_float(param) ->
Statistics.Distributions.Normal.rand(param, @std_dev)
end
true ->
param
end
end
end