/ training / downstream_tasks / simple_cd.py
simple_cd.py
  1  #!/usr/bin/env python3
  2  # -*- coding: utf-8 -*-
  3  """
  4  Created on Wed Mar  9 20:15:48 2022
  5  
  6  @author: aleoikon
  7  """
  8  
  9  import sys
 10  sys.path.append('/home/dvalsamis/Documents/projects/Change_detection_SSL_Siamese')
 11  import time
 12  
 13  from architectures.similarity_detection import pretext_task_one_nopool,pretext_task_one_aspp
 14  
 15  # Now you can use pretext_task_one_nopool in your script
 16  
 17  #from tests import change_detection_noup, change_detection_noup_1x1convs
 18  #from similarity_detection import pretext_task_one_nopool
 19  import tensorflow
 20  from tensorflow.keras import layers, Model
 21  from architectures.branch import branches_triplet
 22  from tensorflow.keras.optimizers import Adam
 23  from tensorflow.keras.utils import plot_model
 24  from sklearn.model_selection import KFold
 25  
 26  
 27  import pandas as pd
 28  import numpy as np
 29  import os
 30  from tensorflow import keras
 31  from architectures.conv_classifier import conv_classifier_two, conv_classifier_two_with_nspp,conv_classifier_two_with_aspp
 32  from utils.layer_select import feature_selector, feature_selector_simple, transfer_learning_model #, feature_selector_task2
 33  from utils.my_metrics import recall, accuracy, specificity, precision, f_measure, get_confusion_matrix
 34  from utils.log_params import log_params_sim1
 35  
 36  import matplotlib
 37  matplotlib.use('TkAgg')
 38  import matplotlib.pyplot as plt
 39  import uuid
 40  import random
 41  from utils.weighted_cross_entropy import weighted_categorical_crossentropy
 42  os.environ["CUDA_VISIBLE_DEVICES"]="1"
 43  
 44  channel = 'rgb'
 45  
 46  
 47  # Set random seed for TensorFlow
 48  tensorflow.random.set_seed(1234)
 49  
 50  # Set random seed for NumPy
 51  np.random.seed(1234)
 52  
 53  
 54  
 55  
 56  def create_rgb_onera(x,channel):
 57      if channel == 'red':
 58          r = x[:,:,2]
 59          r = np.expand_dims(r, axis=2)
 60          return r
 61      if channel == 'green':
 62          g = x[:,:,1]
 63          g = np.expand_dims(g, axis=2)
 64          return g
 65      if channel == 'blue':
 66          b = x[:,:,0]
 67          b = np.expand_dims(b, axis=2)
 68          return b
 69      if channel == 'rgb':
 70          r = x[:,:,2]
 71          g = x[:,:,1]
 72          b  = x[:,:,0]
 73          rgb = np.dstack((r,g,b))
 74          return(rgb)
 75      if channel == 'rgbvnir':
 76          r = x[:,:,2]
 77          g = x[:,:,1]
 78          b  = x[:,:,0]
 79          vnir = x[:,:,3]
 80          rgbvnir = np.stack((r,g,b,vnir),axis=2).astype('float')
 81          return(rgbvnir)
 82      else:
 83          return x
 84          print("NOT CORRECT CHANNELS")
 85  
 86  def generate_short_id():
 87      # Generate a UUID
 88      unique_id = uuid.uuid4()
 89  
 90      # Convert UUID to a hex string and take the first 4 characters
 91      short_id = str(unique_id.hex)[:4]
 92  
 93      return short_id
 94  
 95  def get_layer_weights(model, layer_names):
 96      layer_weights = {}
 97      for layer_name in layer_names:
 98          layer = model.get_layer(layer_name)
 99          if layer:
100              weights = layer.get_weights()
101              if weights:
102                  layer_weights[layer_name] = weights
103              else:
104                  print("No weights found for layer:", layer_name)
105          else:
106              print("Layer not found:", layer_name)
107      return layer_weights
108  
109  def compare_weights(before_training_weights, after_training_weights):
110      for layer_name in before_training_weights:
111          if layer_name in after_training_weights:
112              before_weights = before_training_weights[layer_name]
113              after_weights = after_training_weights[layer_name]
114              if len(before_weights) != len(after_weights):
115                  print(f"Number of weight arrays different for layer {layer_name}")
116                  continue
117              
118              all_equal = all((before_weights[i] == after_weights[i]).all() for i in range(len(before_weights)))
119              if all_equal:
120                  print(f"Weights for layer {layer_name} are the same before and after training.")
121              else:
122                  print(f"Weights for layer {layer_name} are different before and after training.")
123          else:
124              print(f"Layer {layer_name} weights not found after training.")
125  
126  def print_layer_weights(model, layer_names):
127      for layer_name in layer_names:
128          layer = model.get_layer(layer_name)
129          if layer:
130              weights = layer.get_weights()
131              if weights:
132                  print("Weights for layer", layer_name, ":", weights)
133              else:
134                  print("No weights found for layer:", layer_name)
135          else:
136              print("Layer not found:", layer_name)
137  
138  
139  #----------------------------------------------------------------------------------------------------------------------------------------------------------
140  
141  
142  onera_train_target =  '/data/valsamis_data/data/CBMI/CBMI_0.3/CBMI_0.3/NPY_dataset/aug_train_data/'  
143  onera_test_target = '/data/valsamis_data/data/CBMI/CBMI_0.3/CBMI_0.3/NPY_dataset/aug_test_data/'
144  
145  #Onera 
146  # onera_train_target = '/home/aleoikon/Documents/data/ssl/onera_npys/patches/downstream/train/'
147  # onera_test_target = '/home/aleoikon/Documents/data/ssl/onera_npys/patches/downstream/test/'
148  
149  
150  #pretext_models_df = pd.read_csv('training/pretext_tasks/pretext_task_one_models.csv')
151  train = pd.read_csv(onera_train_target + "dataset_train.csv")
152  test = pd.read_csv(onera_test_target + "dataset_test.csv")
153  
154  train = train.sample(frac=1, random_state=1)
155  test = test.sample(frac=1, random_state=1)
156  print("Train Data", len(train))
157  print("Test Data", len(test))
158  
159  NORM = True
160  n_ch = 3
161  #Load everything in memory
162  X_train1 = np.ndarray(shape=(len(train),96,96,n_ch))
163  X_train2 = np.ndarray(shape=(len(train),96,96,n_ch))
164  y_train =  np.ndarray(shape=(len(train),96,96))
165  
166  pos = 0
167  for index in train.index:
168      img1 = np.load(onera_train_target + train['pair1'][index])
169      img2 = np.load(onera_train_target + train['pair2'][index])
170      X1 = create_rgb_onera(img1, channel)
171      X2 = create_rgb_onera(img2, channel)
172      X1 = (X1 - X1.mean()) / X1.std()
173      X2 = (X2 - X2.mean()) / X2.std()
174      X_train1[pos] = X1
175      X_train2[pos] = X2
176      y_train[pos] = np.load(onera_train_target + train['change_mask'][index])
177  
178      pos += 1
179  
180  ##### see the ration of 1 to 0s
181  train_balance = y_train.flatten()
182  (unique, counts) = np.unique(train_balance , return_counts=True)
183  frequencies = np.asarray((unique, counts)).T
184  print(frequencies[0][1]/frequencies[1][1])
185  
186  ## one hot the train
187  
188  y_hot_train = keras.utils.to_categorical(y_train, num_classes=2)
189      
190  X_test1 = np.ndarray(shape=(len(test),96,96,n_ch))
191  X_test2 = np.ndarray(shape=(len(test),96,96,n_ch))
192  y_test =  np.ndarray(shape=(len(test),96,96))
193  
194  pos = 0
195  for index in test.index:
196      img1 = np.load(onera_test_target + test['pair1'][index])
197      img2 = np.load(onera_test_target + test['pair2'][index])
198      X1 = create_rgb_onera(img1, channel)
199      X2 = create_rgb_onera(img2, channel)
200      X1 = (X1 - X1.mean()) / X1.std()
201      X2 = (X2 - X2.mean()) / X2.std()
202      X_test1[pos] = X1
203      X_test2[pos] = X2
204      y_test[pos] = np.load(onera_test_target + test['change_mask'][index])
205      pos += 1
206      
207  ## one hot the test
208  y_hot_test = keras.utils.to_categorical(y_test, num_classes=2)
209  #########
210  ind = random.randint(0, 1000)
211  plt.imshow(y_test[ind])
212  ###############
213  
214  depth = 2
215  dropout = 0.1
216  decay = 0.0001
217  LEARNING_RATE = 0.001
218  EPOCHS = 55
219  
220  model_id = generate_short_id()
221  
222  # #------------------------------------------------------------------------------------
223  
224  cd_model = conv_classifier_two_with_aspp(depth, dropout, decay, 96, 96, n_ch)
225  cd_model.summary()
226  #plot_model(cd_model, to_file='/home/dvalsamis/Documents/projects/Change_detection_SSL_Siamese/graphs/'+model_id+'_model_plot.png', show_shapes=True, show_layer_names=True)
227  
228  
229  #task1
230  sim_model = pretext_task_one_nopool( dropout, decay, 96, 96, n_ch)
231  
232  
233  #Load either a task1 or a task2 model
234  pretext_model_name = '/home/dvalsamis/Documents/projects/Change_detection_SSL_Siamese/saved_models/model_pretext1_unclouded_results.h5'
235  pretext_model = 'model_pretext1_unclouded_results'
236  #plot_model(sim_model, to_file='/home/dvalsamis/Documents/projects/Change_detection_SSL_Siamese/graphs/'+model_id+'_Pretext_model_plot.png', show_shapes=True, show_layer_names=True)
237  
238  
239  
240  #task1
241  sim_model.load_weights(pretext_model_name)
242  
243  
244  # Feature selection(task1)
245  cd_model = feature_selector_simple(depth, sim_model, cd_model)
246  
247  
248  
249  wx = 0.1
250  wy = 0.2
251  weights = np.array([wx, wy]) #!!!!!!!!!!!!!!!!!!!!!!!! -> change
252  #weights = np.array([0.1,0.2])
253  
254  
255  LEARNING_RATE = 0.001
256  EPOCHS = 55
257  optimizer= Adam(learning_rate=LEARNING_RATE)
258  #loss='categorical_crossentropy' #weighted_bincrossentropy 'categorical_crossentropy' 'binary_crossentropy'
259  cd_model.compile(optimizer=optimizer, loss=weighted_categorical_crossentropy(weights), metrics=['accuracy'])
260  
261  BATCH_SIZE=5
262  
263      
264  
265  
266  # Before training
267  print("Before Training:")
268  # before_training_weights = get_layer_weights(cd_model, ["norm_1", "conv1_1", "norm1_1", "relu1_1", "dropout1_1", "conv2_1", "norm2_1", "relu2_1", "dropout2_1","conv3_1","norm3_1","relu3_1","dropout3_1"])
269  
270  
271  
272  # Record start time
273  start_time = time.time()
274  
275  history = cd_model.fit(
276      [X_train1 , X_train2],
277      y_hot_train,
278      validation_data=([X_test1, X_test2], y_hot_test),
279      batch_size=BATCH_SIZE,
280      epochs=EPOCHS
281  )
282  
283  
284  
285  
286  # # Record end time
287  # end_time = time.time()
288  
289  # # Calculate elapsed time
290  # elapsed_time = end_time - start_time
291  # elapsed_time_minutes = elapsed_time / 60
292  
293  
294  
295  
296  
297  cd_model_path = '/home/dvalsamis/Documents/projects/Change_detection_SSL_Siamese/saved_models/CD_Simple_Levir_8192.h5'
298  cd_model.load_weights(cd_model_path)
299  
300  
301  ###predictions
302  predictions = cd_model.predict([X_test1, X_test2])
303  y_pred = np.argmax(predictions, axis=3)
304  
305  
306  
307  
308  y_true = y_test
309  
310  
311  get_confusion_matrix(y_true, y_pred)
312  acc = accuracy(y_true,y_pred)
313  spec = specificity(y_true,y_pred)
314  rec = recall(y_true, y_pred)
315  prec = precision(y_true, y_pred)
316  f_m = f_measure(y_true, y_pred)
317  
318  
319  ####see some predictions
320  def scaleMinMax(x):
321      return ((x - np.nanpercentile(x,2)) / (np.nanpercentile(x,98) - np.nanpercentile(x,2)))
322  
323  
324  def create_rgb(x, channel):
325      if channel == 'rgb':
326          r = x[:,:,2]
327          r = scaleMinMax(r)
328          g = x[:,:,1]
329          g = scaleMinMax(g)
330          b  = x[:,:,0]
331          b = scaleMinMax(b)
332          rgb = np.dstack((r,g,b))
333          return(rgb)
334      else:
335          one = x[:,:,0]
336          one = scaleMinMax(one)
337          return one        
338          
339  
340  
341  
342  # '''
343  # Log Params
344  # '''
345  import csv
346  
347  
348  
349  predictions = cd_model.predict([X_test1, X_test2])
350  y_pred = np.argmax(predictions, axis=3)
351  y_true = y_test
352  
353  cd_model_name = "CD_Simple_"+"CBMI_"+model_id+".h5"
354  
355  model_path = '/home/dvalsamis/Documents/projects/Change_detection_SSL_Siamese/saved_models/'
356  cd_model.save_weights(model_path+cd_model_name)
357  print("Saved model to disk")
358  
359  weight_par = '[' + str(wx) + ',' + str(wy) + ']'
360  log_params_sim1("Task 1 (T)", "Linear", 'ASPP', weight_par, depth, "Softmax", LEARNING_RATE, 'Adam', EPOCHS, 'weighted_categorical_crossentropy', BATCH_SIZE, rec, spec, prec, f_m, acc, "CBMI Set", 96, NORM, pretext_model,"CD_Simple_Sysu_d8d2")
361  
362  print("Done")
363