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
Refactored linalg operations tests ( addresses #4383) #4405
Conversation
Refactored all the opeations tests. * Decreased tolerance for float type tests to work with `float32_t`, `float64_t` and `floatmax_t` * Changed tests where `int` types are required to work with both `int` and `float` * Did not add `complex128_t`, `bool` or `char` tests
I added the SE test whilst there is no fix for the typed test for this case (see my PR description)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi
Wow this is a big patch! We really appreciate your efforts! I put a few inline comments for a first iteration.
A few questions:
-Did you run all the tests locally?
-They pass?
-No memory errors?
Our CI currently has issues and therefore didnt execute them (we will fix that soon) this is why I ask
// TODO: make global definitions | ||
// Definition of the 4 groups of Shogun types (shogun/mathematics/linalg/LinalgBackendBase.h) | ||
// TODO: add bool, chars and complex128_t types | ||
typedef ::testing::Types<int8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float32_t, float64_t, floatmax_t> AllTypes; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep!
} | ||
TYPED_TEST_CASE(LinalgBackendEigenAllTypesTest, AllTypes); | ||
TYPED_TEST_CASE(LinalgBackendEigenNonComplexTypesTest, NonComplexTypes); | ||
TYPED_TEST_CASE(LinalgBackendEigenRealTypesTest, RealTypes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vigsterkr what's your opinion in making those things globally visible so that we wont have to re-declare them?
|
||
|
||
template <typename ST> | ||
void check_SGVector_add() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the motivation to have the "check_" prefix here?
} | ||
for (index_t i = 0; i < 9; ++i) | ||
{ | ||
A[i] = i; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are some minor formatting issues here.
You an actually automatically format this properly... see the output from the first travis job here:
https://travis-ci.org/shogun-toolbox/shogun/jobs/441713579#L723
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would also make the diff of this PR much smaller, as there are fewer whitespace changes
SGMatrix<float64_t> A(nrows, ncols); | ||
SGMatrix<float64_t> B(nrows, ncols); | ||
SGMatrix<float64_t> C(nrows, ncols); | ||
const ST alpha = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uh I didn't reallise that some tests actually operated with floating point number constants and we now have to change all those numbers. Quite some work! Thanks for going into this!
{ | ||
const index_t size=2; | ||
SGMatrix<float64_t> m(size, size); | ||
SGMatrix<ST> m(size, size); | ||
typedef Matrix<ST, Dynamic, Dynamic> Mxx; // need to adapt the Eigen::Matrix to ST type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we might have something similar in SGVector.h
EXPECT_NEAR((map_A-map_L*map_L.transpose()).norm(), | ||
0.0, 1E-15); | ||
0.0, 1E-6); // need to change the treshold to work with floats |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as an idea, we could use a templated function get_epsilon<T>
that looks up the appropriate epsilons?
A2(1, 1) += b[1] * b[1]; | ||
|
||
cholesky_rank_update(U, b, alpha, false); | ||
EXPECT_NEAR((A2_eig - U_eig.transpose() * U_eig).norm(), 0.0, 1e-5); // need to change the treshold to work with floats |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor style: we do comments in a line above usually (+ a whitespace line above that)
|
||
SGMatrix<float64_t> A(data_A, n, n, fa |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the motivation for putting these one liners in here rather than the test code directly?
How does it look when a test fails? Is it easy to exactly identify where the program is coming from? Sometimes with googltest, it is hard to figure out which case the tester is exactly in
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or in other words: Why not put the test code in there straight away and use TypeParam
instead of ST
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, it seems like my previous answer disappeared. There was no specific motivation for this. I just used other code in shogun as a template. The way it was written here is the same as in shogun/tests/unit/classifier/LDA_unittest.cc
. The error traceback works fine when the test fails.
|
||
SGMatrix<float64_t> A(data_A, n, n, fa |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure the method is even defined for int types?
Generally, we try to avoid TODOs in the codebase (they never get addressed ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does a call to this method with int type even compile?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this compiles, but it might not make much sense...
shogun/src/shogun/mathematics/linalg/LinalgBackendBase.h
Lines 255 to 262 in f6efd89
#define BACKEND_GENERIC_RANK_UPDATE(Type, Container) \ | |
virtual void rank_update( \ | |
Container<Type>& A, const SGVector<Type>& b, Type alpha) const \ | |
{ \ | |
SG_SNOTIMPLEMENTED; \ | |
} | |
DEFINE_FOR_ALL_PTYPE(BACKEND_GENERIC_RANK_UPDATE, SGMatrix) | |
#undef BACKEND_GENERIC_RANK_UPDATE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well as long as the eigen3 call goes through it makes sense to offer it :)
But I am surprised ...
|
* get_epsilon is called inside each test case to determine the tolerance * tested these values with my own machine * solver tests will have a lower threshold, as these seem to change quite a bit depending on machine and lapack/blas installations * if typed testing is rolled out for all unit tests should move this to its own header file
* solvers have a fixed threshold * also fixed indentation
Hi Gil, The error when running with valgrind seems strange, this usually happens when there is an uninitialized read somewhere in the code (something which valgrind shows). For the pinv, it might be worth checking how it is implemented and then dig in the code and eigen3 docs to see whether the way it is done works with long (eigen might bail actually). If it is unfixable, we will have to remove the definition for long |
1 similar comment
Hi Gil, The error when running with valgrind seems strange, this usually happens when there is an uninitialized read somewhere in the code (something which valgrind shows). For the pinv, it might be worth checking how it is implemented and then dig in the code and eigen3 docs to see whether the way it is done works with long (eigen might bail actually). If it is unfixable, we will have to remove the definition for long |
Hi, I will have a better look at it today. Github wasn't working properly so I didn't really want to push any code. |
It seems like after changing some values of the matrix tested by
By changing one of any |
It might be worth filing this as a bug report with the eigen3 guys, they are quick in fixing bugs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made a few more relatively minor comments
tests/unit/mathematics/linalg/operations/Eigen3_operations_unittest.cc
Outdated
Show resolved
Hide resolved
tests/unit/mathematics/linalg/operations/Eigen3_operations_unittest.cc
Outdated
Show resolved
Hide resolved
|
||
SGMatrix<float64_t> A(data_A, n, n, fa |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does a call to this method with int type even compile?
What's missing for this to be finished? |
I think all that is missing is the addition of bool, chars and complex type tests. I am just not sure how those test would look like..? For example you could compile a test with dot product of |
We should follow c++ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me now.
Only thing that would be cool to sort out otherwise is the definition of the testing types.
But maybe we can do that in another patch, this is big enough already.
@gf712 are you happy to get this merged ?
Yes, I agree, in another patch could move the definitions to a header file with definitions that can be accessed by all tests? |
yes
Ok then, I will wait for a few more days for others to comment and then merge this |
…hogun-toolbox#4405) * Refactored linalg operations tests * Changed tests where `int` types are required to work with both `int` and `float` * Did not add `complex128_t`, `bool` or `char` tests * added original SE test * solver tests will have a lower threshold, as these seem to change quite a bit depending on machine and lapack/blas installations * automatic tolerance detection
…hogun-toolbox#4405) * Refactored linalg operations tests * Changed tests where `int` types are required to work with both `int` and `float` * Did not add `complex128_t`, `bool` or `char` tests * added original SE test * solver tests will have a lower threshold, as these seem to change quite a bit depending on machine and lapack/blas installations * automatic tolerance detection
Refactored all the linalg Eigen3 operations in
Eigen3_operations_unittest.cc
as suggested in #4383.In addtion to typed testing, changes include:
float
type tests to work withfloat32_t
,float64_t
andfloatmax_t
int
andfloat
typesI did not add
complex128_t
,bool
orchar
tests at this point.I just need help writing a test for
SGMatrix_squared_error
as this potentially requires changing CMath::pow (mentioned in #4383). At this point I left the original test.I know it's quite a large number of lines changed in one PR, but this is mainly a code refactor and the tests are almost identical.
All tests run fine locally!