# UndefVarError: θ not defined

**URL:** <https://discourse.julialang.org/t/undefvarerror-not-defined/43820>\
**Category:** Machine Learning\
**Created:** [July 28, 2020, 3:56pm UTC](https://discourse.julialang.org/t/undefvarerror-not-defined/43820 "2020-07-28T15:56:19Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Irene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/irene/32/16648_2.png) [@Irene](https://discourse.julialang.org/u/Irene)\
**Post date:** [July 28, 2020, 3:56pm UTC](https://discourse.julialang.org/t/undefvarerror-not-defined/43820/1 "2020-07-28T15:56:19Z")

</div>

Hi,

I stumbled upon this [very nice example](https://sebastiancallh.github.io/post/neural-ode-weather-forecast/) from @SebastianCallh in which Neural ODE are used to model and forecast the weather in the city of Delhi. I have a keen interest in learning how to apply differential equations using Julia, so I thought I could give it a try and adapt this code to work on my data.

Took some time to understand the basics of Julia (first timer coming from Python!), but in the end I managed to use @SebastianCallh example to put everything together as follows:

```julia
using Dates
using Plots
using Plotly
using DiffEqFlux
using Statistics
using DataFrames, CSV
using OrdinaryDiffEq, Flux, Random

function neural_ode(t, data_dim; saveat = t)
    f = FastChain(FastDense(data_dim, 64, swish),
		      FastDense(64, 32, swish),
		      FastDense(32, data_dim))

    node = NeuralODE(f, (minimum(t), maximum(t)), Tsit5(),
			 saveat = saveat, abstol = 1e-9,
			 reltol = 1e-9)
end

function train(node, θ, y, opt, maxiters, y0 = y[:, 1]; kwargs...)
	predict(θ) = Array(node(y0, θ))
	loss(θ) = begin
	    ŷ = predict(θ)
	    Flux.mse(ŷ, y)
    end

    θ = θ == nothing ? node.p : θ
    res = DiffEqFlux.sciml_train(
	    loss, θ, opt,
	    maxiters = maxiters;
	    kwargs...
    )
    return res.minimizer
end

log_results(θs, losses) =
    (θ, loss) -> begin
	    push!(θs, copy(θ))
	    push!(losses, loss)
	    false
    end

################
# Main program #
################

# Loading data and setting up metadata

meta_cols = ["rowid", "SiteId", "datetime", "longitude", "latitude"]
data_cols = ["datetime", "DryBulbTemperature_Celsius"]

# Loading 168 records of hourly temperature for a given week in July 2018
# Note: Contains 'missing' values that are casted to NaN and then ignored with filter(!isnan, )
path_in = "PATH/week_of_hourly_temperature_records.csv"

df = DataFrame!(CSV.read(path_in))[data_cols]
df["DryBulbTemperature_Celsius"] = replace(df["DryBulbTemperature_Celsius"], missing=>NaN)

# Normalizing and splitting on train/test
T = 72 # first 3 days for training, remaining 4 days for testing
mean_temp = mean(filter(!isnan, df["DryBulbTemperature_Celsius"])) # taking care of NaNs
stdev_temp = std(filter(!isnan, df["DryBulbTemperature_Celsius"]))

y = Matrix(df[:, ["DryBulbTemperature_Celsius"]] |>
    y -> Matrix(y)' |>
    y -> (y .- mean_temp) ./ stdev_temp)

train_dates, test_dates = df["datetime"][1:T], df["datetime"][T:end]
vals_train_norm, vals_test_norm = y[1:T], y[T:end]

# Starting with the analysis
Random.seed!(1);
maxiters = 150
θs, losses = [], []
θ = nothing
num_obs = 4:4:length(vals_train_norm)

for k in num_obs
    chunk = filter(!isnan, vals_train_norm[1:k])
    node = neural_ode(chunk, size(y, 1))

    θ = train(
	    node, θ, chunk,
	    ADAMW(8e-3), maxiters;
	    cb = log_results(θs, losses)
    )

end

```

However, I found this persistent error and I don’t know how to fix it:

```julia
ERROR: LoadError: **UndefVarError: θ not defined**
Stacktrace:
 [1] top-level scope at /PATH/JuliaProjects/basics_of/attempt.jl:87
in expression starting at /PATH/JuliaProjects/basics_of/attempt.jl:78

```

Because this θ is first set to “nothing” and it seems that will become iteratively calculated/updated. So it seems it makes sense to set up the variable with and empty value and let it change. I printed “node” and “f” and they contain values, so something starts happening, but then it crashes. I even changed the Greek symbol to “theta” just in case there was some problem there 😅, but nothing.

Please, could you let me know what is missing in this code? How can I “define” theta properly? Perhaps an extra library import is required? Maybe the author can share the version creating these nice plots as well? 🙂

Thanks for your help!

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [July 28, 2020, 4:15pm UTC](https://discourse.julialang.org/t/undefvarerror-not-defined/43820/2 "2020-07-28T16:15:04Z")

</div>

> [@Irene](#):
>
> ```julia
> for k in num_obs
> chunk = filter(!isnan, vals_train_norm[1:k])
> node = neural_ode(chunk, size(y, 1))
> 
> θ = train(
> node, θ, chunk,
> ADAMW(8e-3), maxiters;
> cb = log_results(θs, losses)
> )
> 
> end
> 
> ```

You need a `global θ` declaration in this loop, since the loop is in global scope. (It wouldn’t show up if you were writing your loop in a function.)

See [Scope of Variables · The Julia Language](https://docs.julialang.org/en/v1.3-dev/manual/variables-and-scoping/#Local-Scope-1)

This is the infamous global-scope rule ([Global variable scope rules lead to unintuitive behavior at the REPL/notebook · Issue #28789 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/28789)); the error message should be clearer in Julia 1.5.

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [July 28, 2020, 4:15pm UTC](https://discourse.julialang.org/t/undefvarerror-not-defined/43820/3 "2020-07-28T16:15:14Z")

</div>

This is due to Julia’s scoping rules, which regularly trip up beginners. Variables defined in global scope (in this case, `θ`) aren’t visible within for loops unless they’re explicitly annotated as global variables. See [here](https://discourse.julialang.org/t/tips-to-cope-with-scoping-rules-of-top-level-for-loops-etc/24902) for further discussion.

A quick example:

```julia
julia> θ = 0
0

julia> for i = 1:10
         θ += 1
       end
ERROR: UndefVarError: θ not defined
Stacktrace:
 [1] top-level scope at .\REPL[8]:2

```

```julia
julia> for i = 1:10
         global θ += 1
       end

julia> θ
10

```

---

<div class="post-metadata">

**Author:** ![SebastianCallh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sebastiancallh/32/16102_2.png) [@SebastianCallh](https://discourse.julialang.org/u/SebastianCallh)\
**Post date:** [July 28, 2020, 4:37pm UTC](https://discourse.julialang.org/t/undefvarerror-not-defined/43820/4 "2020-07-28T16:37:52Z")

</div>

@Irene I’m glad you found it useful, and welcome to Julia! 🙂 @stevengj and @stillyslalom are absolutely right. The code you see in my blog post is inside a function which has different scoping rules. So it is totally fine to initialize a variable to `nothing`, but in this case the variable itself is not “seen” from inside the loop.

---

<div class="post-metadata">

**Author:** ![Irene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/irene/32/16648_2.png) [@Irene](https://discourse.julialang.org/u/Irene)\
**Post date:** [July 29, 2020, 5:57am UTC](https://discourse.julialang.org/t/undefvarerror-not-defined/43820/5 "2020-07-29T05:57:16Z")

</div>

Well, this certainly did the trick! Thanks to all of your for your super fast response, much appreciated 🙂 Indeed, I could not imagine it was a scope problem, but now that I know (and read) about that, I might spot this issue sooner the next time. Thanks!

---

<div class="post-metadata">

**Author:** ![Irene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/irene/32/16648_2.png) [@Irene](https://discourse.julialang.org/u/Irene)\
**Post date:** [July 29, 2020, 6:21am UTC](https://discourse.julialang.org/t/undefvarerror-not-defined/43820/6 "2020-07-29T06:21:53Z")

</div>

Actually, only if the error could add the substring “in this scope” would probably be sufficient and/or informative for the user. As in `"UndefVarError: θ not defined *in this scope*"`. Step by step, thanks for your efforts! 🙂

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [July 29, 2020, 7:02am UTC](https://discourse.julialang.org/t/undefvarerror-not-defined/43820/7 "2020-07-29T07:02:53Z")

</div>

That change is a good suggestion, but this has already been changed more significantly in the upcoming 1.5 release. This works heuristically in the REPL and errors more clearly in a file. In the REPL:

```julia
julia> θ = 0
0

julia> for i = 1:10
           θ += 1
       end

julia> θ
10

```

In a file:

```julia
┌ Warning: Assignment to `θ` in soft scope is ambiguous because
| a global variable by the same name exists: `θ` will be treated
| as a new local. Disambiguate by using `local θ` to suppress this
| warning or `global θ` to assign to the existing global variable.
└ @ string:5
ERROR: LoadError: UndefVarError: θ not defined

```

Hopefully that’s clear enough that it would have helped you figure it out.

---

<div class="post-metadata">

**Author:** ![Irene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/irene/32/16648_2.png) [@Irene](https://discourse.julialang.org/u/Irene)\
**Post date:** [July 29, 2020, 8:14am UTC](https://discourse.julialang.org/t/undefvarerror-not-defined/43820/8 "2020-07-29T08:14:43Z")

</div>

Well this is a fantastic error message! 👏 👏 👏
