Приложение для линейной регрессии
作者
using GenieFramework, PlotlyBase, Printf
# Начальные демонстрационные данные
const TEST_VEC_X = -10:10
const TEST_VEC_Y = (-10:10).^2 + 10 .* rand(21) .- 5
# Создает трассировки для графика
function create_plot_traces(vec_x, vec_y, x_interp, y_interp)
traces = [scatter(x=vec_x, y=vec_y, mode="markers", name="Данные")]
if !isempty(x_interp)
push!(traces, scatter(x=x_interp, y=y_interp, mode="lines", name="Аппроксимация"))
end
return traces
end
# Линейная регрессия
function linear_regression(vec_x, vec_y)
# Проверка длины векторов
if length(vec_x) != length(vec_y)
return "Ошибка: векторы разной длины", [], [], []
end
if length(vec_x) < 2
return "Нужно хотя бы 2 точки", [], [], []
end
# Матричный метод A \ b
A = [ones(length(vec_x)) vec_x] # Матрица планирования
a, b = A \ vec_y # Решение СЛАУ
# Интерполяция
x_interp = range(minimum(vec_x), maximum(vec_x), length=32)
y_interp = a .+ b .* x_interp
y_interp_x = a .+ b .* vec_x
return "f(x) = $(@sprintf("%.2f", a)) + $(@sprintf("%.2f", b)) * x", collect(x_interp), y_interp, y_interp_x
end
# Основная функция обновления
function update_plot_data(data_x, data_y)
vec_x = []
vec_y = []
try
# Конвертация строк в векторы чисел
vec_x = parse.(Float64, split(data_x, ','))
vec_y = parse.(Float64, split(data_y, ','))
catch e
return "Ожидание данных...", []
end
if isempty(vec_x) || isempty(vec_y) || length(vec_x) != length(vec_y)
return "Ожидание данных...", create_plot_traces(TEST_VEC_X, TEST_VEC_Y, [], [])
end
message, x_interp, y_interp, y_interp_x = linear_regression(vec_x, vec_y)
plot_traces = create_plot_traces(vec_x, vec_y, x_interp, y_interp)
return message, plot_traces
end
@app begin
@in x_data = ""
@in y_data = ""
@out message = "Введите данные"
@out plot_data = create_plot_traces(TEST_VEC_X, TEST_VEC_Y, [], [])
@onchange x_data, y_data begin
message, plot_data = update_plot_data(x_data, y_data)
end
end
function ui()
[
h1("Линейная регрессия"),
textfield("X данные (через запятую)", :x_data),
textfield("Y данные (через запятую)", :y_data),
p("{{message}}"),
plot(:plot_data)
]
end
@page("/", ui)