So I have a method with simple lambda functions I use to update my weights and I want to try different functions but I also want to have default parameter for the decay:
void ema_update(int i, const NetImpl& mdl, void (&updwp)(torch::Tensor& w, const torch::Tensor& w1, double decay = 0.999) = [](torch::Tensor& w, const torch::Tensor& w1, double decay) {
w.set_data(w.data().detach() * decay + w1.detach() * (1. - decay));
}, void (&updw)(torch::Tensor& w, const torch::Tensor& w1, double decay = 0.999) = [](torch::Tensor& w, const torch::Tensor& w1, double decay) {
w = w.detach() * decay;
w += w1.detach() * (1. - decay);
}) {
updw(layers[i].cnvtr1->weight, mdl.layers[i].cnvtr1->weight);
updw(layers[i].cnvtr2->weight, mdl.layers[i].cnvtr2->weight);
updw(layers[i].cnvtr3->weight, mdl.layers[i].cnvtr3->weight);
updw(layers[i].lin1->weight, mdl.layers[i].lin1->weight);
updw(layers[i].lin2->weight, mdl.layers[i].lin2->weight);
updw(layers[i].lin3->weight, mdl.layers[i].lin3->weight);
updw(layers[i].cnv1->weight, mdl.layers[i].cnv1->weight);
updw(layers[i].cnv2->weight, mdl.layers[i].cnv2->weight);
updw(layers[i].cnv3->weight, mdl.layers[i].cnv3->weight);
updw(layers[i].cnv4->weight, mdl.layers[i].cnv4->weight);
updw(layers[i].rnnresh, mdl.layers[i].rnnresh);
if (layers[i].mha->in_proj_weight.defined())
updw(layers[i].mha->in_proj_weight, mdl.layers[i].mha->in_proj_weight);
if (layers[i].mha->k_proj_weight.defined())
updw(layers[i].mha->k_proj_weight, mdl.layers[i].mha->k_proj_weight);
if (layers[i].mha->q_proj_weight.defined())
updw(layers[i].mha->q_proj_weight, mdl.layers[i].mha->q_proj_weight);
if (layers[i].mha->v_proj_weight.defined())
updw(layers[i].mha->v_proj_weight, mdl.layers[i].mha->v_proj_weight);
for (size_t pi = 0; pi < layers[i].trans->decoder.ptr()->parameters().size(); ++pi)
updwp(layers[i].trans->decoder.ptr()->parameters()[pi], mdl.layers[i].trans->decoder.ptr()->parameters()[pi].data());//torch::nn::init::xavier_uniform_(p).cuda();
for (size_t pi = 0; pi < layers[i].trans->encoder.ptr()->parameters().size(); ++pi)
updwp(layers[i].trans->encoder.ptr()->parameters()[pi], mdl.layers[i].trans->encoder.ptr()->parameters()[pi].data());
for (size_t pi = 0; pi < layers[i].rnn1->all_weights().size(); ++pi)
updwp(layers[i].rnn1->all_weights()[pi], mdl.layers[i].rnn1->all_weights()[pi].data());
}
Here I specify all the layers I need to update and the small lambdas are default parameters - however I can't set default parameters on the function pointer prototypes for the decay.
MSVC says:
error C2383: 'updwp': default-arguments are not allowed on this symbol
It doesn't matter if I use reference or pointer to the function.
I'm open to alternative suggestions to make both lambdas and decay default parameters.
Also it was originally:
void ema_update(int i, const NetImpl& mdl, double decay = 0.999, void (&updwp)(torch::Tensor& w, const torch::Tensor& w1) = [](torch::Tensor& w, const torch::Tensor& w1) {
w.set_data(w.data().detach() * decay + w1.detach() * (1. - decay));
}, void (&updw)(torch::Tensor& w, const torch::Tensor& w1) = [](torch::Tensor& w, const torch::Tensor& w1) {
w = w.detach() * decay;
w += w1.detach() * (1. - decay);
})
But that doesn't work either.
Self contained example:
void f(void (*pf)(int &a, double b=0.77) = [] (int &a, double b){
a *= b;
}) {
int a = 9;
pf(a);
}
void f1(double b=0.77, void (*pf)(int &a) = [] (int &a){
a *= b;
}) {
int a = 9;
pf(a);
}
https://wandbox.org/permlink/XmZtzsxmcwgUIbJy
I also tried std functions:
#include <functional>
void f3(double b=0.77, std::function<void (double b, int &a)> fa = [] (double b, int &a){
a *= b;
}) {
int a = 9;
std::function f = std::bind(fa, b);
f(a);
}
auto wrapped = [pf, b](int& a) { return pf(a, b); };