forked from chong-z/tree-ensemble-attack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
neighbor_attack.h
190 lines (156 loc) · 7.26 KB
/
neighbor_attack.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#pragma once
#include <functional>
#include <memory>
#include "utility.h"
namespace cz {
class BoundingBox;
class DecisionForest;
class LayeredBoundingBox;
// Larger score is better.
using ScoreType = std::pair<double, double>;
class NeighborScore {
public:
virtual ScoreType Slow(const Point& point,
const Point& ref_point) const = 0;
virtual ScoreType Fast(const ScoreType& old_score,
const Point& old_point,
const Point& ref_point,
const Patch& new_patch) const = 0;
};
class NeighborAttack {
public:
static const std::vector<int> kAllowedNormTypes;
struct Result {
std::map<int, double> best_norms;
std::map<int, Point> best_points;
std::vector<Point> hist_points;
Result() {
for (const int norm_type : kAllowedNormTypes) {
best_norms[norm_type] = std::numeric_limits<double>::max();
}
}
std::string ToNormString() {
std::string str;
for (const int norm_type : kAllowedNormTypes) {
str += "Norm(" + std::to_string(norm_type) +
")=" + std::to_string(best_norms[norm_type]) + " ";
}
return str;
}
std::string ToPointString() {
std::string str;
for (const int norm_type : kAllowedNormTypes) {
str += "Point(" + std::to_string(norm_type) +
")=" + best_points[norm_type].ToDebugString() + "\n";
}
return str;
}
bool success() {
for (const int norm_type : kAllowedNormTypes) {
if (best_norms[norm_type] < std::numeric_limits<double>::max())
return true;
}
return false;
}
};
explicit NeighborAttack(const Config&);
~NeighborAttack();
void LoadForestFromJson(const std::string& path);
Result FindAdversarialPoint(const Point& victim_point) const;
int PredictLabel(const Point& point) const;
int HammingDistanceBetween(const Point& p1, const Point& p2, int class1, int class2) const;
int NeighborDistanceBetween(const Point& start_point,
const Point& end_point,
int adv_class,
int victim_class,
const Point& victim_point) const;
const DecisionForest* ForestForTesting() const;
private:
friend class NeighborAttackTest;
void FindAdversarialPoint_ThreadRun(int task_id,
const Point& victim_point,
int victim_label,
Result* result) const;
void NeighborDistanceBetween_ThreadRun(int task_id,
const Point& start_point,
const Point& end_point,
int adv_class,
int victim_class,
const Point& victim_point,
int* out_neighbor_dist) const;
void RegionBasedAttackAppr_ThreadRun(int task_id,
const Point& victim_point,
int victim_label,
Result* result) const;
// Start with an |adv_point| and continously move it closer to |victim_point|.
Point OptimizeAdversarialPoint(Point adv_point,
const Point& victim_point,
int target_label,
int victim_label,
Result* result) const;
Point OptimizeLocalSearch(const BoundingBox* box,
const Point& victim_point) const;
Point OptimizeBinarySearch(const Point& adv_point,
const Point& victim_point,
int target_label,
int victim_label) const;
// bool OptimizeSingleNeighborSearch(LayeredBoundingBox* layered_box,
// const Point& victim_point,
// int victim_label) const;
bool OptimizeNeighborSearch(LayeredBoundingBox* layered_box,
const Point& victim_point,
int target_label,
int victim_label,
const NeighborScore& neighbor_score,
SearchMode search_mode,
int max_dist) const;
std::pair<bool, Point> OptimizeRandomSearch(const Point& adv_point,
const Point& victim_point,
int victim_label) const;
std::pair<bool, Point> ReverseNeighborSearch(
const Point& initial_point,
int target_label,
int victim_label,
const BoundingBox& p_constrain) const;
// The resulting patch must have better norm on |target_feature_id|.
void GetNeighborsWithinDistance(int max_dist,
int target_feature_id,
const ScoreType& starting_score,
const Point& starting_point,
const Point& victim_point,
const BoundingBox* box_to_replace,
const LayeredBoundingBox* layered_box,
const std::vector<FeatureDir>& is_bounded,
std::vector<Patch>* candidate_patches) const;
double Norm(const Point& p1, const Point& p2) const;
double NormFast(const Patch& new_patch,
double old_norm,
const Point& old_point,
const Point& ref_point) const;
std::pair<bool, Point> PureRandomPoint(const Point& ref_point,
int victim_label,
int rseed) const;
std::pair<bool, Point> NormalRandomPoint(int victim_label,
const Point& ref_point,
int rseed) const;
std::pair<bool, Point> FeatureSplitsRandomPoint(int victim_label,
const Point& ref_point,
int rseed) const;
// std::optional<Point> GenFromVictim(const Point& victim_point,
// int victim_label,
// double norm_weight) const;
bool FlipWithDirection(LayeredBoundingBox* layered_box,
const Patch& dir) const;
void ResetAttackCache() const;
void UpdateResult(const Point& adv_point,
const Point& victim_point,
Result* result) const;
std::string GetNormStringForLogging(const Point& adv_point,
const Point& victim_point) const;
Config config_;
std::unique_ptr<DecisionForest> forest_;
// Only for RBA-Appr (Yang et al. 2019).
std::vector<std::pair<int, Point>> train_data_;
DISALLOW_COPY_AND_ASSIGN(NeighborAttack);
};
} // namespace cz