using Pkg
Pkg.activate(".")
Activating project at `~/Desktop/MyProjects/Julia_Tutorial_on_AI4MathBiology`
Neural network is no mystery, it is just a function with powerful learning ability.
At this time, you don’t need to care much details about its complicated structure.
In Julia, two deep learning packages are commonly used: - Flux.jl
:Welcome · Flux - Lux.jl
:LuxDL Docs
Here, we use Flux.jl
as an example. More details can be seen in packages official documents.
using Pkg
Pkg.activate(".")
Activating project at `~/Desktop/MyProjects/Julia_Tutorial_on_AI4MathBiology`
You only need to regard neural network as a function \(f(x,p)\), \(x\) input, \(p\) parameters.
using Flux
= Chain(Dense(1, 10, swish), Dense(10, 100,swish),Dense(100, 10, swish), Dense(10, 1))
dnn_model # Remark: In Deep Learning, there is no one dimensional scalar but one dimensional vector
dnn_model([1.0f0])
1-element Vector{Float32}:
-0.040261105
= Chain(Dense(2, 10, swish), Dense(10, 100,swish),Dense(100, 10, swish), Dense(10, 2))
dnn_model2 # Remark: f0 here means we use Float32
dnn_model2([1.0f0,2.0f0])[1]
0.100376524f0
Note here that we didn’t set parameters for this deep learning architecture, however, it has an input. Why?
The reason is that in Flux.jl
, a DNN model has parameters pre defined. Sometimes, it is very inconvenient. Thus, we need to destructure the neural network, so that we can change the parameter of the neural network.
=Flux.destructure(dnn_model2) # parameters and structures
parameter, structure= parameter*0.1 .+ 0.3
newpara # DNN with new parameters
f(x,p)=structure(p)(x)# x input, p parameter
println("DNN with new parameter:", f([1.0f0,2.0f0],newpara))
DNN with new parameter:Float32[286.11746, 278.07166]
using Flux
using Flux:train!,params
# 1. Gennerate Data and Define DNN
= Array(-2π:0.01:2π)'
x = sin.(x)
data #dnn_model = Chain(Dense(1, 1), x-> cos.(x))
#dnn_model = Chain(Dense(1, 128, relu), Dense(128, 1), x-> cos.(x))
= Chain(Dense(1, 10, swish), Dense(10, 100,swish),Dense(100, 10, swish), Dense(10, 1))
dnn_model # dnn_model = Chain(Dense(1, 32, relu), Dense(32, 1, tanh))
# 2. Define Loss Functions
loss2(a,b) = Flux.Losses.mae(dnn_model(x), data)
# Train the model
=ADAM(0.02)
optprintln(loss2(x, data))
train!(loss2, Flux.params(dnn_model), [(x,data)], opt)
println(loss2(x, data))
for epoch in 1:5000
train!(loss2, params(dnn_model), [(x,data)], opt)
if epoch%500==0
println(loss2(x, data))
end
end
0.6178579239993328
0.8133888838007648
0.029455694189493377
0.019722234455541977
0.02941249289718608
0.044564484807402126
0.017978833994311296
0.018942334715419555
0.04541769339893456
0.019092272589503845
0.020229457337176477
0.02070247009650008
Data visulization
using Plots
println(loss2(x, data))
= Array(-2π:0.1:4π)'
y scatter(sin.(y)')
plot!(dnn_model(y)')
0.02070247009650008
Training a deep learning model is an optimization problem. In Julia, there is a unified optimization package with many popular optimizers, such as LBFS, BFGS, ADAM, SGD, evolution algorithms. For more details, one can seen - Optimization.jl: A Unified Optimization Package · Optimization.jl
At this time, you only need to understand the following example: \[\min_{x} (x_1-p_1)^2+p_2*(x_2-x_1^2)^2\] where \(p\) is parameter you can pre defined.
# Import the package and define the problem to optimize
using Optimization
rosenbrock(u, p) = (p[1] - u[1])^2 + p[2] * (u[2] - u[1]^2)^2
= zeros(2)
u0 = [1.0, 100.0]
p
= OptimizationProblem(rosenbrock, u0, p)
prob
# Import a solver package and solve the optimization problem
using OptimizationOptimJL
= solve(prob, NelderMead()) sol
retcode: Success
u: 2-element Vector{Float64}:
0.9999634355313174
0.9999315506115275
Import a different solver package and solve the optimization problem a different way
using OptimizationBBO
= OptimizationProblem(rosenbrock, u0, p, lb = [-1.0, -1.0], ub = [1.0, 1.0])
prob = solve(prob, BBO_adaptive_de_rand_1_bin_radiuslimited()) sol
retcode: Failure
u: 2-element Vector{Float64}:
0.9999999999999876
0.9999999999999785