My function for a struct complains access to undefined reference?

I have 3 julialang files so far… and trying to get a working setup… but hit a snag … here’s my code

dense_layer.jl

mutable struct LayerDense
    num_inputs
    num_neurons
    weights::Matrix{Float64}
    biases::Matrix{Float64}
    output::Matrix{Float64}

    LayerDense(num_inputs::Integer, num_neurons::Integer) = new(0.01 * randn(num_inputs, num_neurons), zeros((1, num_neurons)))
end


function forward(layer::LayerDense, inputs)
    layer.output = inputs * layer.weights + layer.weights
end

exercise.jl

include("dense_layer_exercise/spiral_data.jl")
include("dense_layer_exercise/dense_layer.jl")

coords, color = spiral_data(100, 3)

dense1 = LayerDense(2,3)

forward(dense1, coords)

using Plots

scatter(coords[:,1], coords[:,2], zcolor=color, framestyle=:box)

my error… I can see it is complaining that I have some… reference it cannot understand. I thought adding the output::Matrix{Float64} would fix it but no luck

ERROR: LoadError: UndefRefError: access to undefined reference
Stacktrace:
 [1] getproperty
   @ ./Base.jl:33 [inlined]
 [2] forward(layer::LayerDense, inputs::Matrix{Float64})
   @ Main ~/dense_layer_exercise/dense_layer.jl:15
 [3] top-level scope
   @ ~/exercise.jl:11
in expression starting at /exercise.jll:11

In your dense1 , weights and biases are undefined, because you didn’t initialize them in constructor.

3 Likes

ah I see now…

I had thought I had assigned them via the constructor… but now realize I had referenced the number of neurons and inputs instead… but when I switch to this… it seems to fail as well

mutable struct LayerDense
...
    LayerDense(weights, biases) = new(0.01 * randn(num_inputs, num_neurons), zeros((1, num_neurons)))
....

I think I will read up on constructors… I had some advice from a previous question to get this far but it seems this is not quite 100%

mutable struct LayerDense
    inner_num_inputs
    inner_num_neurons
    weights::Matrix{Float64}
    biases::Matrix{Float64}
    output::Matrix{Float64}

    LayerDense(num_inputs::Integer, num_neurons::Integer)
        weights = new(0.01 * randn(num_inputs, num_neurons))
        biases = zeros((1, num_neurons))
        inner_num_inputs = num_inputs
        inner_num_neurons = num_neurons
end


function forward(layer::LayerDense, inputs)
    layer.output = inputs * layer.weights + layer.weights
end

seems im not grasping how to assign to structs variables in the constructor

edit:

okay I think I have gotten it… my constructor is basically going to go down the line of structs IN-ORDER… which I was not aware of but now seems obvious… so if I want to initialize and save the weights I must bump it up to the top like so


mutable struct LayerDense
    weights::Matrix{Float64}
    biases::Matrix{Float64}
    num_inputs::Integer
    num_neurons::Integer
    output::Matrix{Float64}
    LayerDense(num_inputs::Integer, num_neurons::Integer) = new(0.01 * randn(num_inputs, num_neurons), zeros((1, num_neurons)),num_inputs, num_neurons)
end