1111
1212from architecture .single_model import img_alexnet_layers
1313from distance .tfversion import distance
14- from evaluation import MAPs_CQ , MAPs
15- from .util import Dataset
14+ from evaluation import MAPs_CQ
1615
17- @tf .RegisterGradient ("QuantizeGrad" )
18- def quantize_grad (op , grad ):
19- return tf .clip_by_value (tf .identity (grad ), - 1 , 1 )
2016
21- class TripletQuantization (object ):
17+ class DTQ (object ):
2218 def __init__ (self , config ):
2319 # Initialize setting
24- print ("initializing" )
2520 np .set_printoptions (precision = 4 )
2621
2722 with tf .name_scope ('stage' ):
@@ -31,11 +26,10 @@ def __init__(self, config):
3126 self .output_dim = config .output_dim
3227 self .n_class = config .label_dim
3328
34- self .subspace_num = config .n_subspace
35- self .subcenter_num = config .n_subcenter
29+ self .subspace_num = config .subspace
30+ self .subcenter_num = config .subcenter
3631 self .code_batch_size = config .code_batch_size
3732 self .cq_lambda = config .cq_lambda
38- self .q_lambda = config .q_lambda
3933 self .max_iter_update_Cb = config .max_iter_update_Cb
4034 self .max_iter_update_b = config .max_iter_update_b
4135
@@ -72,21 +66,17 @@ def __init__(self, config):
7266 self .log_dir = config .log_dir
7367
7468 # Setup session
75- print ("launching session" )
7669 config_proto = tf .ConfigProto ()
7770 config_proto .gpu_options .allow_growth = True
7871 config_proto .allow_soft_placement = True
7972 self .sess = tf .Session (config = config_proto )
8073
8174 # Create variables and placeholders
8275 self .img = tf .placeholder (tf .float32 , [None , 256 , 256 , 3 ])
83- # TODO useless placeholder
84- self .img_label = tf .placeholder (tf .float32 , [None , self .n_class ])
8576 self .model_weights = config .model_weights
8677 self .img_last_layer , self .deep_param_img , self .train_layers , self .train_last_layer = self .load_model ()
8778
8879 with tf .name_scope ('quantization' ):
89- # C
9080 self .C = tf .Variable (tf .random_uniform (
9181 [self .subspace_num * self .subcenter_num , self .output_dim ],
9282 minval = - 1 , maxval = 1 , dtype = tf .float32 , name = 'centers' ))
@@ -110,9 +100,6 @@ def __init__(self, config):
110100 self .ICM_best_centers_one_hot = tf .one_hot (ICM_best_centers , self .subcenter_num , dtype = tf .float32 )
111101
112102 self .global_step = tf .Variable (0 , trainable = False )
113-
114- self .G = tf .get_default_graph ()
115-
116103 self .train_op = self .apply_loss_function (self .global_step )
117104 self .sess .run (tf .global_variables_initializer ())
118105 return
@@ -153,115 +140,61 @@ def save_codes(self, database, query, C, model_file=None):
153140 def save_model (self , model_file = None ):
154141 if model_file is None :
155142 model_file = self .save_dir
143+
156144 model = {}
157145 for layer in self .deep_param_img :
158146 model [layer ] = self .sess .run (self .deep_param_img [layer ])
147+
159148 print ("saving model to %s" % model_file )
160149 folder = os .path .dirname (model_file )
161150 if os .path .exists (folder ) is False :
162151 os .makedirs (folder )
152+
163153 np .save (model_file , np .array (model ))
164154 return
165155
166-
167- def quantize (self , x ):
168- with self .G .gradient_override_map ({"Sign" : "QuantizeGrad" }):
169- return tf .sign (x )
170-
171156 def triplet_loss (self , anchor , pos , neg , margin ):
172-
173157 with tf .variable_scope ('triplet_loss' ):
174- if 'sign' in self .select_strategy :
175- # first version
176- #anchor_sign = tf.stop_gradient(tf.sign(anchor))
177- #pos_sign = tf.stop_gradient(tf.sign(pos))
178- #neg_sign = tf.stop_gradient(tf.sign(neg))
179-
180- #a_pos_dist = distance(anchor, pos_sign, pair=False, dist_type=self.dist_type)
181- #a_neg_dist = distance(anchor, neg_sign, pair=False, dist_type=self.dist_type)
182- #p_pos_dist = distance(anchor_sign, pos, pair=False, dist_type=self.dist_type)
183- #p_neg_dist = distance(anchor_sign, neg_sign, pair=False, dist_type=self.dist_type)
184- #n_pos_dist = distance(anchor_sign, pos_sign, pair=False, dist_type=self.dist_type)
185- #n_neg_dist = distance(anchor_sign, neg, pair=False, dist_type=self.dist_type)
186-
187- #basic_loss_a = tf.maximum(a_pos_dist - a_neg_dist + margin, 0.0)
188- #basic_loss_p = tf.maximum(p_pos_dist - p_neg_dist + margin, 0.0)
189- #basic_loss_n = tf.maximum(n_pos_dist - n_neg_dist + margin, 0.0)
190-
191- #loss = tf.reduce_mean(basic_loss_a+basic_loss_p+basic_loss_n, 0)/3
192-
193- #tf.summary.histogram('a_pos_dist', a_pos_dist)
194- #tf.summary.histogram('a_neg_dist', a_neg_dist)
195- #tf.summary.histogram('a_pos_dist - a_neg_dist', a_pos_dist - a_neg_dist)
196-
197- # binarynet version
198-
199- anchor_sign = self .quantize (anchor )
200- pos_sign = self .quantize (pos )
201- neg_sign = self .quantize (neg )
202-
203- pos_dist = distance (anchor_sign , pos_sign , pair = False , dist_type = self .dist_type )
204- neg_dist = distance (anchor_sign , neg_sign , pair = False , dist_type = self .dist_type )
205- basic_loss = tf .maximum (pos_dist - neg_dist + margin , 0.0 )
206-
207- pos_dist_1 = distance (anchor , pos , pair = False , dist_type = self .dist_type )
208- neg_dist_1 = distance (anchor , neg , pair = False , dist_type = self .dist_type )
209- basic_loss_1 = tf .maximum (pos_dist_1 - neg_dist_1 + margin , 0.0 )
210-
211- loss = (tf .reduce_mean (basic_loss , 0 ) + tf .reduce_mean (basic_loss_1 , 0 )) / 2
212-
213- tf .summary .histogram ('pos_dist' , pos_dist )
214- tf .summary .histogram ('neg_dist' , neg_dist )
215- tf .summary .histogram ('pos_dist - neg_dist' , pos_dist - neg_dist )
216- else :
217- pos_dist = distance (anchor , pos , pair = False , dist_type = self .dist_type )
218- neg_dist = distance (anchor , neg , pair = False , dist_type = self .dist_type )
219- basic_loss = tf .maximum (pos_dist - neg_dist + margin , 0.0 )
220- loss = tf .reduce_mean (basic_loss , 0 )
221-
222- tf .summary .histogram ('pos_dist' , pos_dist )
223- tf .summary .histogram ('neg_dist' , neg_dist )
224- tf .summary .histogram ('pos_dist - neg_dist' , pos_dist - neg_dist )
158+ pos_dist = distance (anchor , pos , pair = False , dist_type = self .dist_type )
159+ neg_dist = distance (anchor , neg , pair = False , dist_type = self .dist_type )
160+ basic_loss = tf .maximum (pos_dist - neg_dist + margin , 0.0 )
161+ loss = tf .reduce_mean (basic_loss , 0 )
162+
163+ tf .summary .histogram ('pos_dist' , pos_dist )
164+ tf .summary .histogram ('neg_dist' , neg_dist )
165+ tf .summary .histogram ('pos_dist - neg_dist' , pos_dist - neg_dist )
225166
226167 return loss
227168
228- def c_quantization_loss (self , z , h ):
229- with tf .name_scope ('c_quantization_loss' ):
230- q_loss = tf .reduce_mean (tf .reduce_sum (z - tf .matmul (h , self .C ), - 1 ))
231- return q_loss
232-
233- def quantization_loss (self , z ):
169+ def quantization_loss (self , z , h ):
234170 with tf .name_scope ('quantization_loss' ):
235- q_loss = tf .reduce_mean (1.0 - tf .abs ( z ))
171+ q_loss = tf .reduce_mean (tf . reduce_sum ( z - tf .matmul ( h , self . C ), - 1 ))
236172 return q_loss
237173
238174 def apply_loss_function (self , global_step ):
239175 anchor , pos , neg = tf .split (self .img_last_layer , 3 , axis = 0 )
240176 triplet_loss = self .triplet_loss (anchor , pos , neg , self .triplet_margin )
241- cq_loss = self .c_quantization_loss (self .img_last_layer , self .b_img )
242- q_loss = self .quantization_loss (self .img_last_layer )
243- self .loss = triplet_loss + cq_loss * self .cq_lambda + q_loss * self .q_lambda
177+ cq_loss = self .quantization_loss (self .img_last_layer , self .b_img )
178+ self .loss = triplet_loss + cq_loss * self .cq_lambda
244179
245- # Last layer has a 10 times learning rate
246180 self .lr = tf .train .exponential_decay (
247181 self .learning_rate ,
248182 global_step ,
249183 self .decay_step ,
250184 self .decay_factor ,
251185 staircase = True )
252186 opt = tf .train .MomentumOptimizer (learning_rate = self .lr , momentum = 0.9 )
253-
254187 grads_and_vars = opt .compute_gradients (self .loss , self .train_layers + self .train_last_layer )
255188 fcgrad , _ = grads_and_vars [- 2 ]
256189 fbgrad , _ = grads_and_vars [- 1 ]
257190
258191 tf .summary .scalar ('loss' , self .loss )
259192 tf .summary .scalar ('triplet_loss' , triplet_loss )
260193 tf .summary .scalar ('cq_loss' , cq_loss )
261- tf .summary .scalar ('q_loss' , q_loss )
262194 tf .summary .scalar ('lr' , self .lr )
263195 self .merged = tf .summary .merge_all ()
264196
197+ # Last layer has a 10 times learning rate
265198 if self .finetune_all :
266199 return opt .apply_gradients ([(grads_and_vars [0 ][0 ], self .train_layers [0 ]),
267200 (grads_and_vars [1 ][0 ]* 2 , self .train_layers [1 ]),
@@ -285,7 +218,6 @@ def apply_loss_function(self, global_step):
285218
286219 def initial_centers (self , img_output ):
287220 C_init = np .zeros ([self .subspace_num * self .subcenter_num , self .output_dim ])
288- print ("#TripletQuantization train# initilizing Centers" )
289221 all_output = img_output
290222 for i in range (self .subspace_num ):
291223 start = i * int (self .output_dim / self .subspace_num )
@@ -375,7 +307,7 @@ def update_embedding_and_triplets(self, img_dataset):
375307 for i in range (epoch_iter ):
376308 images , labels , codes = img_dataset .next_batch (self .batch_size )
377309 output = self .sess .run (self .img_last_layer ,
378- feed_dict = {self .img : images , self .img_label : labels , self . b_img : codes })
310+ feed_dict = {self .img : images , self .b_img : codes })
379311
380312 img_dataset .feed_batch_output (self .batch_size , output )
381313 img_dataset .update_triplets (self .triplet_margin , n_part = self .n_part , select_strategy = self .select_strategy )
@@ -415,7 +347,6 @@ def train_cq(self, img_dataset, img_query, img_database, R):
415347 _ , output , loss , summary = self .sess .run (
416348 [self .train_op , self .img_last_layer , self .loss , self .merged ],
417349 feed_dict = {self .img : images ,
418- self .img_label : labels ,
419350 self .b_img : codes })
420351 img_dataset .feed_batch_triplet_output (triplet_batch_size , output )
421352 if train_iter < 100 or i % 100 == 0 :
@@ -455,7 +386,6 @@ def val_forward(self, img_dataset, val_print_freq=100):
455386 images , labels , codes = img_dataset .next_batch (self .val_batch_size )
456387 output = self .sess .run ([self .img_last_layer ],
457388 feed_dict = {self .img : images ,
458- self .img_label : labels ,
459389 self .stage : 1 })
460390 img_dataset .feed_batch_output (self .val_batch_size , output )
461391 if i % val_print_freq == 0 :
@@ -480,32 +410,11 @@ def validation(self, img_query, img_database, R=100):
480410 # Evaluation
481411 print ("%s #validation# calculating MAP@%d" % (datetime .now (), R ))
482412 C_tmp = self .sess .run (self .C )
483-
413+ mAPs = MAPs_CQ ( C_tmp , self . subspace_num , self . subcenter_num , R )
484414 self .save_codes (img_database , img_query , C_tmp )
485-
486- mAPs = MAPs (R )
487- prec , rec , mmap = mAPs .get_precision_recall_by_Hamming_Radius (img_database , img_query , 2 )
488-
489415 return {
490416 'map_feature_ip' : mAPs .get_mAPs_by_feature (img_database , img_query ),
491- 'map_sign_ip' : mAPs .get_mAPs_after_sign (img_database , img_query ),
492- 'prec_radius_2' : prec ,
493- 'recall_radius_2' : rec ,
494- 'map_radius_2' : mmap
417+ 'map_AQD_ip' : mAPs .get_mAPs_AQD (img_database , img_query ),
418+ 'map_SQD_ip' : mAPs .get_mAPs_SQD (img_database , img_query )
495419 }
496420
497-
498- def train (train_img , database_img , query_img , config ):
499- model = TripletQuantization (config ) # 0 for train, 1 for val
500- img_database = Dataset (database_img , config .output_dim , config .n_subspace * config .n_subcenter )
501- img_query = Dataset (query_img , config .output_dim , config .n_subspace * config .n_subcenter )
502- img_train = Dataset (train_img , config .output_dim , config .n_subspace * config .n_subcenter )
503- model .train_cq (img_train , img_query , img_database , config .R )
504- return model .save_dir
505-
506-
507- def validation (database_img , query_img , config ):
508- model = TripletQuantization (config ) # 0 for train, 1 for val
509- img_database = Dataset (database_img , config .output_dim , config .n_subspace * config .n_subcenter )
510- img_query = Dataset (query_img , config .output_dim , config .n_subspace * config .n_subcenter )
511- return model .validation (img_query , img_database , config .R )
0 commit comments