Often when running exprimental code to empirically investigate an algorithm, you tweak a parameter, then rerun the code, and generate a bunch of saved models for various parameters.
To make sure I don't loose what the parameters were set to I defined a macro that saves there values.
module Util
using JLD
export @param_save #...
function names_candidates(blk::Expr)
names_in_block = Vector{Symbol}()
for a in blk.args
typeof(a) <: Expr || continue
if a.head == :(=)
push!(names_in_block, a.args[1])
else #Recurse, so we captured things in blocks or behind `const`
append!(names_in_block, names_candidates(a))
end
end
names_in_block
end
macro param_save(filename, blk::Expr)
names_in_block = names_candidates(blk)
quote
$(esc(blk))
names_defined = Set($(names_in_block)) ∩ Set(names(current_module()))
names_and_vals =[(string(name), eval(name)) for name in names_defined]
println("Paramaters -- saving to $($filename)")
println("----------")
println(join(("$n = $v" for (n,v) in names_and_vals),"\n"))
JLD.save($filename, Base.flatten(names_and_vals)...)
println("----------")
end
end
#...
end #module
Usage:
using Util
base_name = "paper_v1"
param_save_fn = "../models/adagram/$(base_name).params.jld"
output_fn = "../models/adagram/$(base_name).adagram_model"#"file to save the model (in Julia format)"
@assert !isfile(output_fn)
@param_save param_save_fn begin
nprocessors = nprocs()
train_fn = "../data/corpora/WikiCorp/tokenised_lowercase_WestburyLab.wikicorp.201004.txt" #"training text data"
output_fn = output_fn #file to save the model (in Julia format)"
dict_fn = "../data/corpora/WikiCorp/tokenised_lowercase_WestburyLab.wikicorp.201004.1gram" #"dictionary file with word frequencies"
window = 10 #"(max) window size" C in the paper
min_freq = 20 #"min. frequency of the word"
remove_top_k = 0 #"remove top K most frequent words"
dim = 300 #"dimensionality of representations"
prototypes = 5 #"number of word prototypes" T in the paper
alpha = 0.15 #"prior probability of allocating a new prototype"
d = 0.0 #"parameter of Pitman-Yor process" D in paper
subsample = 1e-5 #"subsampling treshold. useful value is 1e-5"
context_cut = true #"randomly reduce size of the context"
epochs = 1 #"number of epochs to train"
initcount = 1. #"initial weight (count) on first sense for each word"
stopwords = Set{AbstractString}() #"list of stop words"
sense_treshold = 1e-10 #"minimal probability of a meaning to contribute into gradients"
save_treshold = 0.0 #"minimal probability of a meaning to save after training"
end
Output:
Paramaters -- saving to ../models/adagram/paper_v1btempexample.params.jld
----------
train_fn = ../data/corpora/WikiCorp/tokenised_lowercase_WestburyLab.wikicorp.201004.txt
alpha = 0.15
subsample = 1.0e-5
sense_treshold = 1.0e-10
initcount = 1.0
nprocessors = 1
epochs = 1
window = 10
output_fn = ../models/adagram/paper_v1btempexample.adagram_model
min_freq = 20
prototypes = 5
context_cut = true
stopwords = Set{AbstractString}()
remove_top_k = 0
save_treshold = 0.0
dict_fn = ../data/corpora/WikiCorp/tokenised_lowercase_WestburyLab.wikicorp.201004.1gram
dim = 300
d = 0.0
----------
Writing code with macros is hard. It took me a few shots to get the escaping all right.
Is this reasonable code?
AFAICT julia doesn't have a method like pythons locals()
that lists all variables in a given scope.
So I have to work around that by finding possible variables in the AST then cross referencing that against all variables in the module.