Сообщество Engee

Аппроксимация данных (Engee-приложение)

Автор
avatar-nkapyrinnkapyrin
Notebook

Аппроксимация данных (Engee-приложение)

Представляем инструментарий для разработки собственных приложений на примере инструмента "Аппроксимация данных".

Цель этого приложения

Инструмент "Аппроксимация данных" создан для того, чтобы помогать находить хорошие функции для аппроксимации векторов входных данных.

Цель конкретно этого примера состоит в том, чтобы показать и обсудить приемы разработки приложений в Engee при помощи GenieFramework.

Запуск приложения

В папке с этим примеров вы найдете файл app.jl, который мы запустим в качестве отдельного приложения в Engee следующими командами:

In [ ]:
genie_app = engee.genie.start("$(@__DIR__)/app.jl", log_file="log.txt");

Приложение можно открыть в отдельном окне:

In [ ]:
using Markdown
Markdown.parse("[Открыть в отдельном окне]($(string(genie_app.url)))")
Out[0]:

using Markdown
Markdown.parse("Открыть в отдельном окне")

А можно отобразить внутри интерактивного скрипта:

In [ ]:
display(MIME("text/html"), """<iframe src="$(string(genie_app.url))" width="1100" height="680" style="border: none;"></iframe>""";)

Остановка приложения (для отладки или перезапуска)

Для остановки приложения выполните следующую команду, раскомментировав ее:

In [ ]:
# engee.genie.stop(string(@__DIR__,"/app.jl"));

Создание входных векторов

Создадим входные данные, которые потребуются для работы приложения:

In [ ]:
# Полиномиальная функция
v1 = 1:5
v2 = (v1.^3 .+ 3v1 .- 5)./150;

# Экспонента
v3 = 3 .* exp.(v1 .- 4);

# Обычная логистическая регрессия
n = 1000
xr = randn(n)
yr = Float32.((1.0 ./ (1.0 .+ exp.(-xr))) .> rand(n))

# Ступенчатая функция (тоже для логистической регрессии)
yr1 = Float32.(xr .> (minimum(xr) + 0.5*abs(maximum(xr)-minimum(xr))))

# Гауссова функция (единичная - осторожно, это всё еще линейная регрессия)
normal_pdf(x; μ=0, σ=1) = exp(-(x-μ)^2/(2σ^2)) / (σ * sqrt(2π))
xn = collect(-3:0.1:3);
yn = normal_pdf.(xn);
yn1 = normal_pdf.(xn, μ=1, σ=0.001);

Построение графика найденной функции

Найденные функции можно скопировать из строки в приложении и вставить в ячейку интерактивного скрипта чтобы получить выходные данные:

In [ ]:
f(x) = 1/(1+exp(-(3.99922 + 8.62808 * x)))

plot(-4:0.1:4, f, lw=3, leg=false)
scatter!(xr,yr1)
Warning: attempting to remove probably stale pidfile
  path = "/user/.jlassetregistry.lock"
@ Pidfile /usr/local/ijulia-core/packages/Pidfile/DDu3M/src/Pidfile.jl:260
Out[0]:

Как это работает?

Вот небольшая демонстрация с тестовыми векторами, приведенными выше:

ezgif_458bb1e9574ef9.gif

Замечания о работе программы

В качестве входных векторов можно использовать любые данные, которые приводятся к векторам внутри инструмента через вызов функции collect().

Часть задач регресси выполняется при помощи метода наименьгих квадратов, часть -- при помощи градиентного спуска с моментом. Это дает некоторую уверенность в сходимости регрессии, но из-за ограниченного количества шагов итерационных алгоритмов наилучшая аппроксимация может быть недостижима для некоторых наборов данных. Стоит увеличить количество шагов в коде инструмента.

Если зайти в код инструмента, вы увидите довольно стандартную структуру приложения:

image.png

Заключение

Надеемся на вашу обратную связь, чтобы сделать инструмент полезнее и устранить ошибки.