Simon Danisch / Jul 08 2019

WGLMakie Image

apt-get update
apt-get install build-essential -y
ln -fs /lib/x86_64-linux-gnu/libz.so.1 /usr/local/lib/libz.so
ldconfig
pkg"up; add https://github.com/SimonDanisch/ShaderAbstractions.jl https://github.com/JuliaPlots/WGLMakie.jl#sd-buffers GeometryBasics#master Tables Observables AbstractPlotting#sd-webgl GeometryTypes JSCall#master StaticArrays WebIO#master Zygote PackageCompiler#sd-notomls Cassette"
0.3s
Julia 1.1 WGLMakie + Zygote (Julia)
write("snoop.jl", """
using WGLMakie, AbstractPlotting
import GeometryBasics
using AbstractPlotting: Node
using Zygote
using LinearAlgebra
# We store parameters as tracked one element arrays
# To easily update them inplace & take the gradient
function chain2points(chain, input)
  points = [input]
  return reduce(chain, init = [input]) do v0, angle
    [v0; next_position(v0[end], angle)]
  end
end


function visualize(input, target)
  points = Node(chain2points(chain, input))
  segments = lift(points) do points
    # repeat each points to form connected segments
    collect(GeometryBasics.TupleView{2, 1}(points))
  end
  s = linesegments(segments, color = :lightgray)
  scatter!(points, markersize = 0.2)
  scatter!([target], color = :red, markersize = 0.3)
  dots = lift(points) do x
    diff = norm(last(x) .- target)
    LinRange(Point(last(x)), Point(target), 10)
  end
  # CairoMakie doesn't support dotted lines yet -.-
  scatter!(
    dots,
    color = (:indianred1, 0.5), markersize = 0.05,
    limits = FRect(0, -3, 6, 7), scale_plot = false
  )
  return points, s
end
@inline function next_position(position, angle)
    position .+ (sin(angle), cos(angle))
end

# Our "neuronal network" ... or chain of flexible links
@inline function predict(chain, input)
    output = next_position(input,  chain[1]) # Layer 1
    output = next_position(output, chain[2]) # Layer 2
    output = next_position(output, chain[3]) # Layer 3
    output = next_position(output, chain[4]) # Layer 4
    return output
end

function loss(chain, input, target)
    return sum((predict(chain, input) .- target) .^ 2)
end

chain = [(rand() * pi) for i in 1:4]

input, target = (0.0, 0.0), (3.0, 3.0)
points, s = visualize(input, target)
# this should be like display almost
repr(MIME"text/html"(), s);
function loss_gradient(chain, input, target)
  # first index, to get gradient of first argument
  Zygote.gradient(loss, chain, input, target)[1]
end

for i in 1:100
  # get gradient of loss function
  angle∇= loss_gradient(chain, input, target)
  # update weights with our loss gradients
  # this updates the weights in the direction of smaller loss
  chain .-= 0.01 .* angle∇
  # update visualization
  points[] = chain2points(chain, input)
  yield()
end
""")
2230
using PackageCompiler
open("/results/precompiles.jl", "w") do io
  PackageCompiler.snoop(abspath("snoop.jl"), io)
end
false
precompiles.jl
# add the correct usings + imports to the precompile file
using Pkg
packages = ["WGLMakie", "GeometryBasics", "AbstractPlotting", "Zygote", "LinearAlgebra"]
ctx = Pkg.Types.Context()
pkgs = PackageSpec.(packages)
packages = PackageCompiler.flat_deps(ctx, packages)
# remove blacklisted packages from full list of packages
imports = PackageCompiler.to_pkgid.(packages)
filter!(x-> !(x.name in ("WinRPM", "HTTPClient")), imports)
usings = join(["const $(x.name) = Base.require($(PackageCompiler.prepr(x)))" for x in imports], "\n")
open("/results/precompiles2.jl", "w") do io
  println(io, usings)
  open(
precompiles.jl
) do io2 write(io, io2) end end
1975515
precompiles2.jl
using WGLMakie, AbstractPlotting
scatter(rand(4))
using PackageCompiler
syso, sysold = compile_incremental(
precompiles2.jl
)
("/root/.julia/packages/PackageCompiler/RRsVs/sysimg/sys.so", "/usr/local/julia/lib/julia/sys.so")
cp(syso, sysold, force = true)
"/usr/local/julia/lib/julia/sys.so"
2.2s
Julia
Julia 1.1 WGLMakie + Zygote
using WGLMakie, AbstractPlotting
import GeometryBasics
using AbstractPlotting: Node
using Zygote
using LinearAlgebra
# We store parameters as tracked one element arrays
# To easily update them inplace & take the gradient
function chain2points(chain, input)
  points = [input]
  return reduce(chain, init = [input]) do v0, angle
    [v0; next_position(v0[end], angle)]
  end
end

function visualize(input, target)
  points = Node(chain2points(chain, input))
  segments = lift(points) do points
    # repeat each points to form connected segments
    collect(GeometryBasics.TupleView{2, 1}(points))
  end
  s = linesegments(segments, color = :lightgray)
  scatter!(points, markersize = 0.2)
  scatter!([target], color = :red, markersize = 0.3)
  dots = lift(points) do x
    diff = norm(last(x) .- target)
    LinRange(Point(last(x)), Point(target), 10)
  end
  # CairoMakie doesn't support dotted lines yet -.-
  scatter!(
    dots,
    color = (:indianred1, 0.5), markersize = 0.05,
    limits = FRect(0, -3, 6, 7), scale_plot = false
  )
  return points, s
end
@inline function next_position(position, angle)
    position .+ (sin(angle), cos(angle))
end

# Our "neuronal network" ... or chain of flexible links
@inline function predict(chain, input)
    output = next_position(input,  chain[1]) # Layer 1
    output = next_position(output, chain[2]) # Layer 2
    output = next_position(output, chain[3]) # Layer 3
    output = next_position(output, chain[4]) # Layer 4
    return output
end

function loss(chain, input, target)
    return sum((predict(chain, input) .- target) .^ 2)
end

chain = [(rand() * pi) for i in 1:4]

input, target = (0.0, 0.0), (3.0, 3.0)
points, s = visualize(input, target)
# this should be like display almost
s
function loss_gradient(chain, input, target)
  # first index, to get gradient of first argument
  Zygote.gradient(loss, chain, input, target)[1]
end

for i in 1:100
  # get gradient of loss function
  angle∇= loss_gradient(chain, input, target)
  # update weights with our loss gradients
  # this updates the weights in the direction of smaller loss
  chain .-= 0.01 .* angle∇
  # update visualization
  points[] = chain2points(chain, input)
  yield()
end