def freeze_all_but_crossability(self): for layer in self.model.layers: if not layer.name == "crossability_block" and not layer.__class__.__name__ == "InputLayer": layer.trainable = False Verbose.print_text( 1, "[INFO] " + layer.name.ljust(26) + " set to non-trainable")
def download_forecast(forecastTime, grid, h, forecastHour, path): forecastTime = forecastTime[0:4 + 2 + 2] + "%2F" + forecastTime[-2:] url = "https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_" + grid + ".pl?file=gfs.t" + ( "%02d" % forecastHour ) + "z.pgrb2." + grid + ".f" + ("%03d" % h) + "&" + GfsData( ).g_grib_url_levels + "&" + GfsData( ).g_grib_url_meteovars + "&leftlon=0&rightlon=360&toplat=90&bottomlat=-90&dir=%2Fgfs." + forecastTime Verbose.print_text(1, url) Forecast.__download(url, path)
def evaluate(self, days_to_use=None): if days_to_use is None: days_to_use = range(self.nb_days) Verbose.print_text(1, "[INFO] Evaluation: "+ \ str(self.trained_model.model.evaluate(x = [x[days_to_use,...] for x in self.all_X], y = [y[days_to_use,...] for y in self.all_Y], verbose = 0)))
def check_need_to_update_forecast(self, valid_date, last_forecast_time): last_forecast_time_file = os.path.join(self.last_forecast_time_file_dir, valid_date.strftime('%Y-%m-%d')) if os.path.isfile(last_forecast_time_file): with open(last_forecast_time_file, "r") as file: contentLastForecastTime = file.read() if contentLastForecastTime >= last_forecast_time: Verbose.print_text(1, "forecast is up-to-date") return False # my forecast is up-to-date return True
def __check_meteo_files(meteo_files): ok = True for mf in meteo_files: ok = ok and os.path.isfile(mf) and os.path.getsize(mf) > 5000 if ok: Verbose.print_text(1, "[OK ] Meteo files found") return True else: Verbose.print_text(1, "[WARNING] Meteo files not found") return False
def set_population_value(self, popuValue): Verbose.print_arguments() for layer in self.model.layers: if layer.name.startswith("population"): Verbose.print_text( 1, "[INFO] Setting population value %f in layer '%s'" % (popuValue, layer.name)) populationWeights = layer.get_weights() populationWeights[-1][:, :] = popuValue layer.set_weights(populationWeights)
def __load_or_compute_data(self): Verbose.print_arguments() if self.data_not_loaded(): try: self.__load() except: pass if self.data_not_loaded(): Verbose.print_text( 0, "[WARNING] data_not_loaded, __computeSpotsInformation") self.__compute_spots_information() self.__save()
def __download(url, path): Verbose.print_arguments() r = requests.get(url, stream=True) downloaded_size = 0 tmpPath = path + ".downloading" with open(tmpPath, 'wb') as f: for chunk in r.iter_content(chunk_size=None): if chunk: if downloaded_size // (1024 * 1024) != (downloaded_size + len(chunk)) // (1024 * 1024): Verbose.print_text(1, str(round(downloaded_size/(1024.0 * 1024.0),1)) +"Mo", True) downloaded_size += len(chunk) f.write(chunk) os.rename(tmpPath, path) Verbose.print_text(1, "")
def __compute_spots_forecasts(self, models_directory, problem_formulation, lats, lons, meteo_matrix, filename): Verbose.print_arguments() predict = Predict(models_directory, ModelType.SPOTS, problem_formulation) predict.set_meteo_data(meteo_matrix, GfsData().parameters_vector_all) #============================================================= # depend de GribReader.get_values_array(self, params, crops): forecastCellsLine = {} line = 0 for crop in self.crops: for iLat in range(crop[0], crop[1]): for iLon in range(crop[2], crop[3]): forecastCellsLine[(iLat, iLon)] = line line += 1 #============================================================= # Compute or load cells_and_spots #============================================================= filename_cells_and_spots = "Forecast_cellsAndSpots_" + "_".join( [str(crop[d]) for crop in self.crops for d in range(4)]) if not BinObj.exists(filename_cells_and_spots): Verbose.print_text( 0, "Generating precomputation file because of new crop, it may crash on the server... To be computed on my computer" ) cells_and_spots = {} # find forecast cell for each spot # C'est comme le cellsAndSpots de Train sauf que les cellules sont les cells de forecast (32942 cells) spots_data = SpotsData() spots = spots_data.getSpots(range(80)) for kc, cell_spots in enumerate(spots): for ks, spot in enumerate(cell_spots): iCell = (np.abs(lats - spot.lat).argmin(), np.abs(lons - spot.lon).argmin()) cellLine = forecastCellsLine[iCell] kcks_spot = ( (kc, ks), spot.toDict()) # (training cell, ks) if not cellLine in cells_and_spots: cells_and_spots[cellLine] = [kcks_spot] else: cells_and_spots[cellLine] += [kcks_spot] BinObj.save(cells_and_spots, filename_cells_and_spots) else: cells_and_spots = BinObj.load(filename_cells_and_spots) #============================================================= # Create a model with 1 cell of 1 spot #============================================================= predict.set_trained_spots() #============================================================= # Compute prediction for each spot, one by one #============================================================= spots_and_prediction = [] for kcslst, cslst in enumerate(cells_and_spots.items()): meteoLine, spotsLst = cslst for cs in spotsLst: modelContent = ModelContent() modelContent.add(cs[0][0], cs[0][1]) predict.trainedModel.load_all_weights( modelContent) # TODO do not reload shared weights predict.set_prediction_population() NN_X = predict.get_X([meteoLine]) prediction = predict.trainedModel.model.predict(NN_X)[0][0] spots_and_prediction += [ Spot((cs[1]['name'], cs[1]['lat'], cs[1]['lon']), cs[1]['id'], cs[1]['nbFlights'], prediction) ] #[cs[1]] #============================================================= # Export all results #============================================================= Forecast.__export_spots_forecasts(spots_and_prediction, filename)
def main(self): last_forecast_times = Forecast.get_last_forecast_times( self.GFS_resolution) Verbose.print_text(1, "last_forecast_times: " + str(last_forecast_times)) for last_forecast_time in last_forecast_times[0:4]: last_forecast_time_dt = datetime.datetime( int(last_forecast_time[0:4]), int(last_forecast_time[4:6]), int(last_forecast_time[6:8])) last_forecast_hour = int(last_forecast_time[-2:]) # 0, 6, 12, 18 Verbose.print_text( 2, "last_forecast_hour: " + str(last_forecast_hour)) Verbose.print_text( 2, "last_forecast_time: " + str(last_forecast_time)) #================================================================== # Update each day #================================================================== for days in range(self.nb_days): day_datetime = last_forecast_time_dt + datetime.timedelta( days=days) strdate = day_datetime.strftime("%Y-%m-%d") tiles_dir_this_day = self.tiles_dir + "/" + strdate #====================================================================================== # Skip if no need to update #====================================================================================== if not self.check_need_to_update_forecast( day_datetime, last_forecast_time): continue #====================================================================================== # Make tiles dir #====================================================================================== os.makedirs(tiles_dir_this_day, exist_ok=True) #====================================================================================== # Download / update next hours grib files #====================================================================================== if self.forced_meteo_files is None: meteo_files = [] l_h = [(hh + 24 * days - last_forecast_hour) for hh in [6, 12, 18] if (hh + 24 * days - last_forecast_hour) >= 0] for kh, h in enumerate(l_h): forecast_datetime_with_hours = datetime.datetime( int(last_forecast_time[0:4]), int(last_forecast_time[4:6]), int(last_forecast_time[6:8]), int(last_forecast_time[8:10])) valid_datetime = forecast_datetime_with_hours + datetime.timedelta( hours=h) meteo_file = self.destination_forecast_file % valid_datetime.strftime( "%Y-%m-%d-%H") Verbose.print_text(1, "download " + meteo_file) if not self.DEBUG_MODE or not os.path.exists( meteo_file): self.download_forecast(last_forecast_time, self.GFS_resolution, h, last_forecast_hour, meteo_file) meteo_files += [meteo_file] #====================================================================================== # Re-create a complete list of 3 files even with those not updated (in the past) # # params: # - destinationForecastFile # input: # - dayDateTime # output: # - meteo_files #====================================================================================== meteo_files = [ self.destination_forecast_file % (day_datetime + datetime.timedelta(hours=h)).strftime("%Y-%m-%d-%H") for h in [6, 12, 18] ] Verbose.print_text(1, str(meteo_files)) else: # self.forced_meteo_files is not None # ====================================================================================== # Use forced meteo files # # params: # - forced_meteo_files # ====================================================================================== assert (len(self.forced_meteo_files) == 3) meteo_files = [ "/tmp/forced_meteo_06", "/tmp/forced_meteo_12", "/tmp/forced_meteo_18" ] for m in range(len(meteo_files)): shutil.copyfile(self.forced_meteo_files[m], meteo_files[m]) #====================================================================================== # Skip if meteo files are missing #====================================================================================== if not self.__check_meteo_files(meteo_files): if not self.DEBUG_MODE: Forecast.clean_meteo_files(meteo_files) else: for mf in meteo_files: if os.path.isfile( mf) and os.path.getsize(mf) <= 5000: Forecast.remove_file(mf) continue #====================================================================================== # PROGRESS: start computation #====================================================================================== self.set_progress(10, strdate) #====================================================================================== # Read weather data #====================================================================================== distinct_latitudes, distinct_longitudes, meteo_matrix = ForecastData.readWeatherData( meteo_files, self.crops) #====================================================================================== # Compute and generate the predictions file for tiler #====================================================================================== ForecastAndAnl.compute_prediction_file_cells( # predictions ForecastAndAnl.compute_cells_forecasts( self.models_directory, self.problem_formulation, meteo_matrix), # other params self.prediction_filename_for_tiler, distinct_latitudes, distinct_longitudes, np.copy(meteo_matrix), self.crops, self.meteoParams, self.grid_desc_predictions) #====================================================================================== # Compute spots prediction #====================================================================================== if True: self.__compute_spots_forecasts( self.models_directory, self.problem_formulation, distinct_latitudes, distinct_longitudes, np.copy(meteo_matrix), os.path.join(self.tiles_dir, os.path.join(strdate, "spots.json"))) #====================================================================================== # Clean files #====================================================================================== if not self.DEBUG_MODE: Forecast.clean_meteo_files(meteo_files) #======================================================================== # PROGRESS: end of prediction computation #======================================================================== self.set_progress(20, strdate) #======================================================================== # Render tiles #======================================================================== if self.render_tiles: ForecastAndAnl.generate_tiler_argument_file( self.tiler_arguments_filename, self.prediction_filename_for_tiler, tiles_dir_this_day, self.tiler_cache_dir, self.geo_json_borders, self.min_tiles_zoom, self.max_tiles_zoom, self.background_tiles_dir, True, "", self.skipped_tiles, generateTranspaVersion=True) call([self.tiler_program, self.tiler_arguments_filename]) #======================================================================== # Set last update date #======================================================================== self.save_last_update_time(day_datetime, last_forecast_time) #======================================================================== # PROGRESS: end for this date #======================================================================== self.set_progress(100, strdate)
# main ########################################################################################################## if __name__ == "__main__": problem_formulation = ProblemFormulation.CLASSIFICATION model_dir = "./bin/models/%s_1.0.0" % str(problem_formulation).split( ".")[-1] ####################################################################### # Check if script is already running ####################################################################### process = Utils.get_elapsed_time("forecast.py") if len(process) > 1: Verbose.print_text(0, "[WARNING] already running: " + str(process)) for p in process: if p[1] > 4 * 3600: Verbose.print_text( 0, "[WARNING] running for more than 3h, killing it !") os.kill(p[0], signal.SIGTERM) else: sys.exit(0) ####################################################################### # RUN ####################################################################### forecast = Forecast(model_dir, problem_formulation) forecast.main()
def createNewModel(cls, problem_formulation, model_content, wind_dim, other_dim, humidity_dim, nb_altitudes, initialization): Verbose.print_arguments() # Check initialization assert(not initialization is None) for k in initialization: assert(k in ["date_factor", "dow_factor"]) Verbose.print_text(1, "initialization "+ str(initialization)) # ============================================================================================================== # Shared variables # ============================================================================================================== # Not trainable var_date_factor = tf.keras.backend.constant(value=initialization['date_factor'], name="var_date_factor") if ModelSettings.optimize_dow: var_dow_factor = tf.keras.backend.constant(value=initialization['dow_factor'], name="var_dow_factor") else: var_dow_factor = tf.keras.backend.constant(value=ModelSettings.dow_init, name="var_dow_factor") # ============================================================================================================== # Inputs # ============================================================================================================== input_date = tf.keras.layers.Input(shape=(1,), name="in_date") input_dow = tf.keras.layers.Input(shape=(7,), name="in_dow") input_mountainess = tf.keras.layers.Input(shape=(model_content.nbCells(), nb_altitudes), name="in_mountainess") input_other = tf.keras.layers.Input(shape=(model_content.nbCells(), 3, other_dim), name="in_other") input_humidity = tf.keras.layers.Input(shape=(model_content.nbCells(), 3, humidity_dim), name="in_rain") input_wind = tf.keras.layers.Input(shape=(model_content.nbCells(), nb_altitudes, 3, wind_dim), name="in_wind") all_inputs = [input_date, input_dow, input_mountainess, input_other, input_humidity, input_wind] # ============================================================================================================== # Blocks # ============================================================================================================== flyabilityModel = get_flyability_block(other_dim, humidity_dim, name="flyability_block") flyabilityModel.trainable = False # freeze the block # ============================================================================================================== # Iterations over cells # ============================================================================================================== all_outputs = [] # 1 by cell for kc,c in enumerate(model_content.cells()): nb_spots = len(model_content.spots(c)) if nb_spots > 0: # inputs for this cell input_wind_this_cell = tf.keras.layers.Lambda(lambda x: x[:,kc,...])(input_wind) input_other_this_cell = tf.keras.layers.Lambda(lambda x: x[:,kc,...])(input_other) input_humidity_this_cell = tf.keras.layers.Lambda(lambda x: x[:,kc,...])(input_humidity) # blocks population_block = get_population_block(problem_formulation, var_date_factor, var_dow_factor, 1, name="population__cell_%d"%c) wind_block = get_wind_block_spots(nb_spots, name="wind_block_spots__cell_%d"%c) # Flyability wind_prediction = wind_block(input_wind_this_cell) wind_prediction = tf.keras.layers.Lambda(lambda x: tf.keras.backend.reshape(x, (-1, 1, nb_spots, 3)))(wind_prediction) flyability_prediction = encapsulate_flyability(flyabilityModel, 1, nb_spots, other_dim, humidity_dim, [wind_prediction, input_other_this_cell, input_humidity_this_cell]) # Apply population flown_prediction = population_block([flyability_prediction, input_date, input_dow]) flown_prediction = tf.keras.layers.Lambda(lambda x: tf.keras.backend.reshape(x, (-1, nb_spots)))(flown_prediction) all_outputs += [flown_prediction] #========================================================================================= # Make model #========================================================================================= return tf.keras.models.Model(all_inputs, all_outputs)
def load_all_weights(self, modelContentToLoad=None, wind_bias=-1.0): Verbose.print_arguments() # self.modelContent est le contenu du network, il définit le nom des layers # modelContentToLoad définit le nom des fichiers de weights à utiliser if modelContentToLoad is None: modelContentToLoad = self.modelContent else: assert (self.modelContent.sameStructure(modelContentToLoad)) if self.modelClass == ModelCells: layers = [ "flyability_block", "crossability_block", "wind_block_cells", "wind_flyability_block", "humidity_flyability_block" ] else: layers = ["flyability_block"] #=============================================================================================================== # shared #=============================================================================================================== # Flyability, Fufu, Wind, WindFlyability, RainFlyability for layer in layers: try: arrs = self.model.get_layer(layer).get_weights() for kArr, arr in enumerate(arrs): arr = np.load( self.filesLayerWeights(layer + "_%d" % kArr) + ".npy") if wind_bias > 0.0 and layer == "wind_block_cells": arr = wind_bias * arr arrs[kArr] = arr self.model.get_layer(layer).set_weights(arrs) except: pass if self.modelClass == ModelCells: populationWeights = self.model.get_layer( "population_block").get_weights() #[(1,), (7,), (5,)] try: populationWeights[0] = np.load( self.filesLayerWeights("population_date") + ".npy") # date factor (1,) if ModelSettings.optimize_dow: assert (len(populationWeights) == 3) populationWeights[1] = np.load( self.filesLayerWeights("population_dow") + ".npy") # DOW factor (7,) else: assert (len(populationWeights) == 2) except: Verbose.print_text( 1, "[ERROR] Could not load weights population_date population_dow" ) raise # =============================================================================================================== # specific # =============================================================================================================== if self.modelClass == ModelCells: for c, cell in enumerate( self.modelContent.cells()): # TODO super_resolution for sr in range(self.modelContent.super_resolution * self.modelContent.super_resolution): c_sr = c * self.modelContent.super_resolution * self.modelContent.super_resolution + sr cell_sr = cell * self.modelContent.super_resolution * self.modelContent.super_resolution + sr try: populationWeights[-1][c_sr, :] = np.load( self.filesLayerWeights( "population_alt_cell_%d" % cell_sr) + ".npy") # population at each altitude except: Verbose.print_text( 1, "[ERROR] Could not load weights for population cell %d" % cell_sr) raise self.model.get_layer("population_block").set_weights( populationWeights) else: Verbose.print_text(1, "modelContent :" + str(self.modelContent)) Verbose.print_text(1, "modelContentToLoad:" + str(modelContentToLoad)) for c, cell in enumerate(self.modelContent.cells()): cellToLoad = modelContentToLoad.cells()[c] spotsToLoad = modelContentToLoad.spots(cellToLoad) try: self.model.get_layer( "population__cell_%d" % cell).set_weights([ np.load( self.filesLayerWeights( "population_0_spots__cell_%d" % cellToLoad) + ".npy") ]) except: Verbose.print_text( 1, "[WARNING] Could not load weights for " + ("population__cell_%d" % cell)) try: # load weights for all spots WindSpots_cell_0 = np.load( self.filesLayerWeights( "wind_block_spots_0__cell_%d" % cellToLoad) + ".npy") # shape (nbSpots, nbWindDim) WindSpots_cell_1 = np.load( self.filesLayerWeights( "wind_block_spots_1__cell_%d" % cellToLoad) + ".npy") # shape ( 1, nbWindDim) # keep only spots of modelContent WindSpots_cell_0 = WindSpots_cell_0[spotsToLoad, :] WindSpots_cell_1 = WindSpots_cell_1[spotsToLoad, :] self.model.get_layer( "wind_block_spots__cell_%d" % cell).set_weights( [WindSpots_cell_0, WindSpots_cell_1]) except: Verbose.print_text( 1, "[WARNING] Could not load weights for " + ("wind_block_spots__cell_%d" % cell))
def compute_prediction_file_cells( cells_forecasts, prediction_filename_for_tiler, distinct_latitudes, distinct_longitudes, meteo_matrix, crops, meteo_params, grid_desc_predictions, export_for_tiler=True): Verbose.print_arguments() # ====================================================================================== # Retrieve geopotential height at 12h indices in meteoParams # # inputs: # - meteoParams # - parameters_geopotential_height # outputs: # - geopotential_height_indices # ====================================================================================== geopotential_height_indices = [] for geopotential_height_param in GfsData().parameters_geopotential_height: for kParam, param in enumerate(meteo_params): if param == (12,) + geopotential_height_param: geopotential_height_indices += [kParam] break assert (len(geopotential_height_indices) == len(GfsData().parameters_geopotential_height)) # ====================================================================================== # Retrieve wind at 12h # # inputs: # - meteoParams # - parameters_wind # outputs: # - wind_indices # ====================================================================================== wind_indices = [] for wind_param in GfsData().parameters_wind: for kParam, param in enumerate(meteo_params): if param == (12,) + wind_param: wind_indices += [kParam] break assert (len(wind_indices) == len(GfsData().parameters_wind)) # ======================================================================== # Create and fill prediction grid # # params: # - grid_desc_predictions # inputs: # - distinct_latitudes # - distinct_longitudes # - meteo_matrix # - geopotential_height_indices # - predictions # outputs: # - prediction_grid # ======================================================================== prediction_grid = GridLatLon(grid_desc_predictions[0], grid_desc_predictions[1], grid_desc_predictions[2], grid_desc_predictions[3]) p = 0 for crop in crops: # number of data rectangles to read in the GRIB grid lat_range = (crop[0], crop[1]) lon_range = (crop[2], crop[3]) Verbose.print_text(1, "lats: " + str(distinct_latitudes[lat_range[0]]) +" , "+ str(distinct_latitudes[lat_range[1]-1])) Verbose.print_text(1, "lons: " + str(distinct_longitudes[lon_range[0]]) +" , "+ str(distinct_longitudes[lon_range[1]-1])) for ilat in range(lat_range[0], lat_range[1]): for ilon in range(lon_range[0], lon_range[1]): predictions_data_sample = () # Add geopential heights (not predicted, simply meteo variables) predictions_data_sample += (meteo_matrix[p, geopotential_height_indices[0]], # 0 meteo_matrix[p, geopotential_height_indices[1]], # 1 meteo_matrix[p, geopotential_height_indices[2]], # 2 meteo_matrix[p, geopotential_height_indices[3]], # 3 meteo_matrix[p, geopotential_height_indices[4]]) # 4 predictions_data_sample += (cells_forecasts[0][p,0,0], # flyability at 1000 # 5 cells_forecasts[0][p,0,1], # flyability at 900 # 6 cells_forecasts[0][p,0,2], # flyability at 800 # 7 cells_forecasts[0][p,0,3], # flyability at 700 # 8 cells_forecasts[0][p,0,4], # flyability at 600 # 9 np.mean(cells_forecasts[1][p,0,0:5]),# crossability # 10 cells_forecasts[2][p,0,0], # wind at 1000 # 11 cells_forecasts[2][p,0,1], # wind at 900 # 12 cells_forecasts[2][p,0,2], # wind at 800 # 13 cells_forecasts[2][p,0,3], # wind at 700 # 14 cells_forecasts[2][p,0,4], # wind at 600 # 15 np.mean(cells_forecasts[3][p,0,0:5]), # humidity # 16 0.0) # Attractiveness # 17 predictions_data_sample += (meteo_matrix[p, wind_indices[0 + 0]], # U 1000 12h # 18 meteo_matrix[p, wind_indices[2 + 0]], # U 900 12h # 19 meteo_matrix[p, wind_indices[4 + 0]], # U 800 12h # 20 meteo_matrix[p, wind_indices[6 + 0]], # U 700 12h # 21 meteo_matrix[p, wind_indices[8 + 0]], # U 600 12h # 22 meteo_matrix[p, wind_indices[0 + 1]], # V 1000 12h # 23 meteo_matrix[p, wind_indices[2 + 1]], # V 900 12h # 24 meteo_matrix[p, wind_indices[4 + 1]], # V 800 12h # 25 meteo_matrix[p, wind_indices[6 + 1]], # V 700 12h # 26 meteo_matrix[p, wind_indices[8 + 1]]) # V 600 12h # 27 # Push the sample prediction_grid.add(distinct_latitudes[ilat], distinct_longitudes[ilon], predictions_data_sample) p += 1 # ======================================================================== # Export predictions for tiler # # params: # - predictionFilenameForTiler # inputs: # - prediction_grid # ======================================================================== accessors = [lambda x, ix=ixVal: sum([xx[ix] for xx in x]) / len(x) for ixVal in range(len(predictions_data_sample))] if export_for_tiler: prediction_grid.export_data_for_tiler(prediction_filename_for_tiler, accessors) else: prediction_grid.export_json(prediction_filename_for_tiler, accessors)
Utils.move_dir(model_dir, cur_model_dir + str(m)) os.makedirs(model_dir) # Keep best training best_training = np.argmin(np.array(val_losses)) Utils.copy_dir(cur_model_dir + str(best_training), model_dir) # Re-train best with all samples train = Train(model_dir, ModelType.CELLS, problem_formulation) train.set_trained(range(55), super_resolution=1, load_weights=True) train.train(lr_schedules[1], use_validation_set=False) train.save() #========================================================================================== if True: # 2) Train [spots population], [wind + alti] by cell #========================================================================================== train = Train(model_dir, ModelType.SPOTS, problem_formulation) for c in range(0, nb_cells): Verbose.print_text( 0, "=================================[ cell %d ]=================================" % c) if train.set_trained([c], load_weights=True): train.train((0.008, 5.e-6, 110)) train.save() else: print("No spot in cell %d" % c)