Поместим нейросеть в блок Engee Function¶
В этом примере мы разместим обученную нейросеть на холсте Engee в качестве блока Engee Function
– сгенерируем из нее код на Julia.
Описание задачи¶
Ранее мы обучили полносвязанную нейросеть прогнозировать величину $y$ на основе двух входных переменных: $x_1$ и $x_2$. У нас уже есть файл model.jld2
, где лежит обученная нейросеть. Теперь мы переведем ее в код на Julia и создадим блок, который можно будет использовать в любой модели или сделать из таких блоков собственную библиотеку.
⚠️ Внутри блока
Engee Function
можно использовать только глобальную адресацию. Поэтому если у вас пример расположен в папке, отличной от/user/start/data_analysis/neural_regression_to_engee_function
, нужно отредактировать код внутри блокаEngee Function
, прописав полный путь к файлуneural_net_code.jl
.
Создание маски блока¶
Удобно было бы разместить на лицевой стороне блока некоторый рисунок, который возможно упростит восприятие модели. В качестве маски используем топологию нашей нейросети.
Нам понадобится библиотека ChainPlots
, которая создает "рецепт" визуализации нейросети для функции plot()
, после чего мы просто можем передать нейросеть в качестве аргумента функции вывода графиков.
using Flux, JLD2, ChainPlots
model = load_object( "$(@__DIR__)/model.jld2" ) # Загрузим нейросеть из файла
gr()
p = plot( model, titlefontsize=10, size=(300,300),
xticks=:none, series_annotations="", markersize=8,
markercolor="white", markerstrokewidth=4, linewidth=1 )
savefig( p, "$(@__DIR__)/neural_net_block_mask.png"); # Сохраним график в PNG
☝️ Ссылка на картинку уже прописана в маске блока. Но маска не обновится автоматически. Чтобы иллюстрация загрузилась на лицевую сторону блока, откройте его свойства (в режиме просмотра маски) и нажмите "Обновить маску".
Создание Julia кода для нейросети¶
Создать код нам поможет одна особенность языка Julia.
Поскольку библиотека Flux
целиком написана на Julia, каждый слой нейросети описан Julia-кодом. Что будет, если на вход подать не числа, а математические символы из библиотеки Symbolics
?
using Symbolics
@variables x1 x2
s = model( [x1, x2] );
# Первые 200 символов этого кода
print( string(s[1])[1:200], "..." )
Мы видим много ifelse
... Действительно, нейросеть с активацией ReLU можно переписать как большую кусочно-линейную функцию.
Сохраним код в файл .jl¶
Если мы поместим код в текстовый файл, то его можно будет включить в блок Engee Function
через команду include()
, но только по абсолютному адресу. Но, при этом, в папке с моделью всегда нужно будет хранить этот файл с кодом. Есть и другой способ – поместить код и маску внутрь блока Engee Function
и сделать компонент самодостаточным.
open("$(@__DIR__)/neural_net_code.jl", "w") do f
println(f, "function nn(x1, x2)\n $(s[1])\nend")
end
# Сразу же запустим этот код и получим прогноз нейросети:
include("$(@__DIR__)/neural_net_code.jl")
nn(1,2)
Проверка: запуск нейросети из блока Engee Function¶
Запустим модель и визуализируем результаты.
# Загрузим (если модель еще не открыта) и выполним модель
if "neural_regression_to_engee_function" ∉ getfield.(engee.get_all_models(), :name)
engee.load( "$(@__DIR__)/neural_regression_to_engee_function.engee");
end
model_data = engee.run( "neural_regression_to_engee_function" );
# Подготовим выходные переменные
model_x1 = model_data["X1"].value;
model_x2 = model_data["X2"].value;
model_y = vec( hcat( model_data["Y"].value... ));
# Построим график
scatter!( model_x1, model_x2, model_y, ms=2.5, msw=.5, leg=false, zcolor=model_y, c=:viridis,
xlimits=(-3,3), ylimits=(-3,3), title="Прогноз от блока Engee Function", titlefont=font(10) )
Мы видим знакомую функцию, но каждая выходная точка "предсказана" нейросетью, которая обучилась моделировать нужную нам зависимость $y = f(x_1, x_2)$.
Заключение¶
Пользуясь библиотекой Symbolics
совсем несложно сгенерировать код из функции Julia, даже если эта функция – нейросеть из библиотеки Flux
. Остается выбрать удобный способ размещения кода на холсте, и можно использовать нейросеть в качестве компонента в модельно-ориентированном проекте.