-
Notifications
You must be signed in to change notification settings - Fork 93
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
Sigmoid support with linearization #492
Sigmoid support with linearization #492
Conversation
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
@@ -3,6 +3,7 @@ | |||
1628 | |||
1668 | |||
1628 | |||
0 |
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 this change?
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.
Ah I think I understand. It denotes the number of transcendental constraints.
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.
src/engine/InputQuery.cpp
Outdated
|
||
printf( "Number of variables: %u\n", _numberOfVariables ); | ||
printf( "Number of lower bounds: %u\n", _lowerBounds.size() ); | ||
printf( "Number of upper bounds: %u\n", _upperBounds.size() ); | ||
printf( "Number of equations: %u\n", _equations.size() ); | ||
printf( "Number of constraints: %u\n", _plConstraints.size() ); | ||
printf( "Number of piecewise-linear constraints: %u\n", _plConstraints.size() ); | ||
printf( "Number of transcendental constraints: %u\n", _tsConstraints.size() ); |
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.
Maybe we can just replace _plConstraints with _nonLinearConstaints which include both the PL constraints and the transcendental constraints. This way the previously generated input query file would remain valid.
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
src/engine/MILPEncoder.cpp
Outdated
double sourceLb = _tableau.getLowerBound( sourceVariable ); | ||
double sourceUb = _tableau.getUpperBound( sourceVariable ); | ||
|
||
if ( sourceLb < 0 && sourceUb > 0 ) |
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.
Use FloatUtils::gt() and FloatUtils::lt() instead of <, >
Marabou/src/common/FloatUtils.h
Line 89 in 9c08e9c
static bool lt( double x, double y, double epsilon = GlobalConfiguration::DEFAULT_EPSILON_FOR_COMPARISONS ) |
src/engine/MILPEncoder.cpp
Outdated
if ( sourceLb < 0 && sourceUb > 0 ) | ||
{ | ||
List<GurobiWrapper::Term> terms; | ||
String binVarName = Stringf( "a%u", _binVarIndex ); // a = 1 -> the caes where x_b >= 0, otherwise where x_b <= 0 |
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.
caes -> case
src/engine/MILPEncoder.cpp
Outdated
int binVal = 1; | ||
|
||
// tangent line: x_f = tangentSlope * (x_b - tangentPoint) + yAtTangentPoint | ||
double tangentPoint = ( 0 + sourceUb ) / 2; |
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.
( 0 + sourceUb ) / 2 => sourceUb / 2
src/engine/MILPEncoder.cpp
Outdated
gurobi.addGeqIndicatorConstraint( binVarName, binVal, terms, 0 ); | ||
terms.clear(); | ||
|
||
// upper bound of x_b |
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.
Addition of the upper bound is redundant?
src/engine/MILPEncoder.cpp
Outdated
gurobi.addGeqIndicatorConstraint( binVarName, binVal, terms, y_l ); | ||
terms.clear(); | ||
|
||
// upper bound of x_f |
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.
Similarly, this should be redundant?
src/engine/MILPEncoder.cpp
Outdated
0, | ||
1, | ||
GurobiWrapper::BINARY ); | ||
// |
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.
Remove extra // to be consistent with rest of the code base?
src/engine/MILPEncoder.cpp
Outdated
binVal = 0; | ||
|
||
// tangent line: x_f = tangentSlope * (x_b - tangentPoint) + yAtTangentPoint | ||
tangentPoint = ( sourceLb + 0 ) / 2; |
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.
tangentPoint = sourceLb / 2
src/engine/MILPEncoder.cpp
Outdated
terms.clear(); | ||
|
||
// secant line: x_f = secantSlope * (x_b - sourceLb) + y_l | ||
y_u = sigmoid->sigmoid( 0 ); |
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.
No need to recompute this? Instead, y_u = y_l
src/engine/MILPEncoder.cpp
Outdated
gurobi.addLeqIndicatorConstraint( binVarName, binVal, terms, y_u ); | ||
terms.clear(); | ||
|
||
// |
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.
Remove extra //
src/engine/MILPEncoder.cpp
Outdated
gurobi.addLeqIndicatorConstraint( binVarName, binVal, terms, -secantSlope * sourceLb + y_l ); | ||
terms.clear(); | ||
|
||
// lower bound of x_b |
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.
Similarly, there is no need to add lowerbounds for x_b and x_f in this case?
src/engine/MILPEncoder.cpp
Outdated
terms.append( GurobiWrapper::Term( 1, Stringf( "x%u", targetVariable ) ) ); | ||
terms.append( GurobiWrapper::Term( -tangentSlope, Stringf( "x%u", sourceVariable ) ) ); | ||
|
||
if ( sourceLb >= 0 ) |
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.
Use FloatUtils::gte
Marabou/src/common/FloatUtils.h
Line 84 in 9c08e9c
static bool gte( double x, double y, double epsilon = GlobalConfiguration::DEFAULT_EPSILON_FOR_COMPARISONS ) |
src/engine/MILPEncoder.cpp
Outdated
{ | ||
gurobi.addLeqConstraint( terms, -tangentSlope * tangentPoint + yAtTangentPoint ); | ||
} | ||
else if ( sourceUb <= 0 ) |
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.
else if ( sourceUb <= 0 ) => else
src/engine/MILPEncoder.cpp
Outdated
double y_l = sigmoid->sigmoid( sourceLb ); | ||
double y_u = sigmoid->sigmoid( sourceUb ); | ||
|
||
if ( sourceUb != sourceLb ) |
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.
Maybe handle the case of "sourceUb == sourceLb" in the very beginning of this method?
src/engine/MILPEncoder.cpp
Outdated
terms.append( GurobiWrapper::Term( 1, Stringf( "x%u", targetVariable ) ) ); | ||
terms.append( GurobiWrapper::Term( -secantSlope, Stringf( "x%u", sourceVariable ) ) ); | ||
|
||
if ( sourceLb >= 0 ) |
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.
Use FloatUtils::gte
src/engine/MILPEncoder.cpp
Outdated
{ | ||
gurobi.addGeqConstraint( terms, -secantSlope * sourceLb + y_l ); | ||
} | ||
else if ( sourceUb <= 0 ) |
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.
else if ( sourceUb <= 0 ) => else
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.
Overall looks good and the implementation looks correct. I have a few more minor comments though for code readability/efficiency.
Signed-off-by: tagomaru <tagomaru@users.noreply.github.com>
* linearlization done, but queryLoader not yet Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * QueryLoader Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * robust_model_sigmoid_linear Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * remove debug print Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * fixed some bugs and removed codes supporting unknown Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * explicitly include GurobiWrapper.h in MILPEncoder.cpp Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * updating GurobiWrapper.h to make a compiler detect the update Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * update indent Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * rollback Marabou.py Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * change ci.yml Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * fix ci error Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * add interfaces in GurobiWrapper Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * fix queryloader bug Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * rollback queryloader stuff Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> * reflect Andrew's comments Signed-off-by: tagomaru <tagomaru@users.noreply.github.com> Co-authored-by: Haoze(Andrew) Wu <haozewu@stanford.edu>
This PR is going to support sigmoid constraints with linearization approach.
How does it work?
The below example test code shows how it works.
test_mnist_model_with_sigmoids.py
robust_model_sigmoid_linear.onnx
is mnist classifier of input -> hidden1(64 sigmoids) -> hidden2(32 sigmoids) -> output.It was trained by an adversarial training with PGD attack of epsilon 0.1.
Accuracy of test data is 0.9543, and accuracy of PGD test data is 0.8546.
Result