Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use iterative machine mixin in AveragedPerceptron #4551

Merged
merged 4 commits into from Mar 11, 2019
Merged

Use iterative machine mixin in AveragedPerceptron #4551

merged 4 commits into from Mar 11, 2019

Conversation

ghost
Copy link

@ghost ghost commented Mar 2, 2019

@shubham808 This PR addresses the project 'inside the black box II' and issue #4488.
I still need to write some unit tests, but I would like to get confirmation that this is the right way, since I'm still new to this project.

Copy link
Member

@karlnapf karlnapf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi

Thanks a lot for the PR! Much appreciated!
I made some initial comments. It probably needs a few more iterations or minor changes, @shubham808 will probably have more comments.

The tests fail because the class is not recognised by class list anymore. Check the formatting of the class definition of perceptron and make it like this here, then the error should go away (there is some python code that scans the codebase for all classes and it expects a certain formatting iirc

src/shogun/classifier/AveragedPerceptron.cpp Outdated Show resolved Hide resolved
src/shogun/classifier/AveragedPerceptron.cpp Outdated Show resolved Hide resolved
src/shogun/classifier/AveragedPerceptron.cpp Outdated Show resolved Hide resolved
src/shogun/classifier/AveragedPerceptron.cpp Outdated Show resolved Hide resolved
src/shogun/classifier/AveragedPerceptron.cpp Outdated Show resolved Hide resolved
src/shogun/classifier/AveragedPerceptron.h Outdated Show resolved Hide resolved
max_iter = 1000;
learn_rate = 0.1;
SG_ADD(&max_iter, "max_iter", "Maximum number of iterations.", ParameterProperties::HYPER);
set_max_iter(1000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes this is better

@shubham808
Copy link
Contributor

good first pr :)
a unit test is also necessary since we need to make sure what we did actually works, see consistency tests here

@ghost
Copy link
Author

ghost commented Mar 3, 2019

@shubham808 consistency_training_tests has that test that makes sure that two models: one with max_iterations = 1 and the other stopped after an iteration, yield the same results. This isn't true here, since the one with max_iterations=1 has different weights because end_training() method is called after training is finished, which changes the weights to the final form (performs averaging).
For this to work, end_trainig() has to be called when training is stopped for whatever reason. But this will require us to copy intermediate weights, so that training can be resumed with the intermediate weights instead of the averaged ones.
Edit: My suggestion won't work since end_training() is also used to free used resources by other algorithms. So maybe something like pause_training()?
Edit2: In this implementation of AveragedPerceptron, weights are summed across iterations, then averaged. Maybe this can happen online: mean_{n+1} = mean_{n} + (x - mean_{n}) / (n + 1)

Copy link
Member

@karlnapf karlnapf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments

int32_t max_iter;

private:
float64_t tmp_bias;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we maybe name those two a bit better?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current name is cached_bias and cached_w, which is still bad I think. I will think of something better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about just saying what it is? w_averaged etc?

tests/unit/classifier/AveragedPeceptron_unittest.cc Outdated Show resolved Hide resolved
src/shogun/classifier/AveragedPerceptron.h Show resolved Hide resolved
tests/unit/classifier/AveragedPeceptron_unittest.cc Outdated Show resolved Hide resolved
@karlnapf
Copy link
Member

karlnapf commented Mar 3, 2019

@shubham808 consistency_training_tests has that test that makes sure that two models: one with max_iterations = 1 and the other stopped after an iteration, yield the same results. This isn't true here, since the one with max_iterations=1 has different weights because end_training() method is called after training is finished, which changes the weights to the final form (performs averaging).
For this to work, end_trainig() has to be called when training is stopped for whatever reason. But this will require us to copy intermediate weights, so that training can be resumed with the intermediate weights instead of the averaged ones.
Edit: My suggestion won't work since end_training() is also used to free used resources by other algorithms. So maybe something like pause_training()?
Edit2: In this implementation of AveragedPerceptron, weights are summed across iterations, then averaged. Maybe this can happen online: mean_{n+1} = mean_{n} + (x - mean_{n}) / (n + 1)

We had this issue before. I dont remember how we exactly solved it. A running average seems to work here and seems like a very good idea. Make sure to pick a numerically stable one (might require some googling). Could you add a way to update a mean vector/scalar in linalg in a separate PR? Then you can rebase this PR here to use it. This would be better than just adding the explicit code in here and then it could be used in other algorithms (LARS comes to mind where it is done explicitly as well)

cached_w = SGVector<float64_t>(num_feat);
// start with uniform w, bias=0, tmp_bias=0
bias = 0;
cached_bias = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually this name is fine imo

}
iter++;
pb.print_progress();
linalg::update_mean(w, cached_w, num_prev_weights);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sweet, much nicer to read!

return std::string(XSTRING__(ptype)); \
}

SG_PRIMITIVE_TYPE(bool, PT_BOOL);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gf712 do we have a central map for these?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all the supported types should go here

using sg_feature_types = Types<

and all the any supported types are here
SG_ADD_PRIMITIVE_TYPE(bool, TYPE::T_BOOL)

Copy link
Author

@ghost ghost Mar 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gf712 DataType.h seems to be obsolete, but I can't use sg_types and type_case yet since the class_list script (which has the create function) uses the old code.
Btw, the implementation of these two files is very interesting!

@@ -0,0 +1,164 @@
#ifndef __SG_OBJECT_ITERATOR_H__
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea moving this into a new file!


using namespace shogun;

std::set<std::string> sg_linear_machines = {"Perceptron", "AveragedPerceptron",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok! This is definitely better than before. I have a question: If a test fails, is it easy to see which class is the offender?

Filtering the tests obviously is not possible via this though. Compile time is an advantage to the typed version of this we had before (we define a bunch of types and then essentially template the test). This then allows for filtering. Maybe in a follow up PR, we can do something about that. I think the current blocker was that it is hard to find all subclasses automatically. However, if we simply define a type list (as you have done here with strings), that is also acceptable for now.

@gf712 might also be interesting for you

Copy link
Author

@ghost ghost Mar 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be easy using SCOPED_TRACE.
Hard coding the linear machines may not be so scaleable. Can't the class_list script be extended to detect hierarchies?
Sorry I don't get your point about filtering, and why templated tests can be better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool add the scoping!
Yes we can do this extension, but for now the explicit list is fine.
Compiled types can be helpful but for now this is good!

machine_stop->train(features);

machine_iters->set_labels(labels);
machine_iters->put<int32_t>("max_iterations", max_iters);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there should be yet a typed setter for this or?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this helps to make the tests for reliable (no runtime error when setting things as here), we can keep the setter (even though it will be hidden from users in the future)

Copy link
Member

@karlnapf karlnapf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this update! :) Thanks!

So two things.

  • Can we somehow set the continue features in IterativeMachine?
  • a compiled test for every IterativeMachine might be easier to handle debugging wise. Something to look into? We can keep the runtime version for now
  • See some minor inline comments

@shubham808
Copy link
Contributor

@theartful Nice clean up for the tests, CI error seems unrelated
about the setting of continue features maybe we could try doing that here ?

@ghost
Copy link
Author

ghost commented Mar 10, 2019

Unrelated, but for some reason the LibLinearRegression test on MacOS passed :"D

@karlnapf
Copy link
Member

Cool ci passed so this is almost good to go. I’ll do one more detailed read through later and then we can merge

@shubham808
Copy link
Contributor

@theartful lets check for memory leaks of the new test and then this is good to go from my side 👍

@karlnapf karlnapf merged commit 5c45bbd into shogun-toolbox:develop Mar 11, 2019
#include <string>
#include <shogun/base/class_list.h>

using namespace shogun;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@theartful plz never do this in a header file...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my bad didn't see it

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ouch! sorry for that

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vigsterkr


shouldn't it be namespace shogun?

ktiefe pushed a commit to ktiefe/shogun that referenced this pull request Jul 30, 2019
* Add function to set features in iterative machine

* Use iterative machine mixin in AveragedPerceptron

* Add generic iterative machine test

* Move m_continue_features assignment to IterativeMachine
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants