줄리아 플럭스에서 MLP 구현해서 비선형함수 근사하는 방법
시작
using Flux
using Plots
using Distributions
using Flux: @epochs
function f(x)
if -5 ≤ x < -2
y = -3x + 2
elseif -2 ≤ x < 1
y = x + 10
elseif 1 ≤ x < 2
y = -2x + 13
elseif 2 ≤ x < 3
y = 4x + 1
elseif 3 ≤ x ≤ 5
y = -4x + 25
end
return y
end
x_ = -5:0.01:5
y_ = f.(x_)
plot(x_, y_)
필요한 패키지를 불러오고, 우리가 근사하고 싶은 비선형함수를 정의하자.

학습집합 생성
julia> Data = convert.(Float32, rand(Uniform(-5,5), 1024))
1024-element Vector{Float32}:
julia> Data = convert(Matrix, reshape(Data, (1,1024)))
1×1024 Matrix{Float32}:
함수의 정의역인 $[-5, 5]$에서 임의의 점 1024개를 뽑았다. 이렇게 뽑으면 자료형이 Float64인데, 딥러닝에서는 기본적으로 Float32 자료형을 다루므로 바꿔주었다. 물론 자료형이 Float64나 Int64인 데이터를 모델에 인풋으로 써도 알아서 자료형을 바꾸고 실행하기는 한다.
또한 각각의 열이 하나의 데이터를 의미하기 때문에(이해가 안된다면 행렬의 곱을 생각해보라) 1024-벡터를 1x1024 매트릭스로 바꿔주었다.
Label = f.(Data)
Train_Set = Flux.DataLoader((Data, Label), batchsize=128)
위에서 정의한 함수 $f$로 레이블을 만들고, Flux.DataLoader로 훈련에 사용할 수 있게 만들었다.
모델 정의
model = Chain(
Dense(1,5, relu),
Dense(5,5, relu),
Dense(5,1)
)
x_input = reshape(x_, (1,1001))
x_input = convert(Matrix{Float32}, x_input)
ŷ = model(x_input)
plot(vec(x_input), vec(ŷ))
Chain()으로 MLP를 만들고, 함수의 그래프를 그려보면 $f$와 전혀 다름을 확인할 수 있다.

손실함수와 옵티마이저 정의
LOSS(x,y) = Flux.mse(model(x), y)
opt = ADAM()
손실함수는 MSE, 옵티마이저는 ADAM으로 정의했다.
훈련
julia> @epochs 5000 @time Flux.train!(LOSS, Flux.params(model), Train_Set, opt,
cb = Flux.throttle(() -> @show(LOSS(Data, Label)), 1))
[ Info: Epoch 5000
LOSS(Data, Label) = 1.3867694f-6
0.001494 seconds (3.04 k allocations: 549.953 KiB)
이제 @epochs 매크로로 훈련시킬 수 있다. 5000 에포크를 반복한 후, 로스가 아주 작아진 것을 확인할 수 있다.
MLP의 그래프를 그려보면 다음과 같다.
ŷ = model(x_input)
plot(vec(x_input), vec(ŷ))

코드 전문
using Flux
using Plots
using Distributions
using Flux: @epochs
function f(x)
if -5 ≤ x < -2
y = -3x + 2
elseif -2 ≤ x < 1
y = x + 10
elseif 1 ≤ x < 2
y = -2x + 13
elseif 2 ≤ x < 3
y = 4x + 1
elseif 3 ≤ x ≤ 5
y = -4x + 25
end
return y
end
x_ = -5:0.01:5
y_ = f.(x_)
plot(x_, y_)
savefig("nonlinear_function.png")
Data = convert.(Float32, rand(Uniform(-5,5), 1024))
Data = convert(Matrix, reshape(Data, (1,1024)))
Label = f.(Data)
Train_Set = Flux.DataLoader((Data, Label), batchsize=128)
model = Chain(
Dense(1,5, relu),
Dense(5,5, relu),
Dense(5,1)
)
x_input = reshape(x_, (1,1001))
x_input = convert(Matrix{Float32}, x_input)
ŷ = model(x_input)
plot(vec(x_input), vec(ŷ))
savefig("initial_MLP.png")
LOSS(x,y) = Flux.mse(model(x), y)
opt = ADAM()
@epochs 5000 @time Flux.train!(LOSS, Flux.params(model), Train_Set, opt, cb = Flux.throttle(() -> @show(LOSS(Data, Label)), 1))
ŷ = model(x_input)
plot(vec(x_input), vec(ŷ))
savefig("trained_MLP.png")
환경
- OS: Windows10
- Version: Julia 1.7.1, Flux 0.12.8

저희들의 저서 「줄리아 프로그래밍」이 2024 세종도서 학술부문에 선정되었습니다!

