def _check_input_args(list_of_baseline_matrices, list_of_trial_matrices, num_iterations, confidence_level): """Error-checks input args for Monte Carlo test. :param list_of_baseline_matrices: See doc for `run_monte_carlo_test`. :param list_of_trial_matrices: Same. :param num_iterations: Same. :param confidence_level: Same. :raises: ValueError: if number of baseline matrices (input tensors to model) != number of trial matrices. :raises: TypeError: if all "input matrices" are None. :return: num_examples_per_set: Number of examples in each set. """ error_checking.assert_is_integer(num_iterations) error_checking.assert_is_geq(num_iterations, 100) error_checking.assert_is_geq(confidence_level, 0.) error_checking.assert_is_leq(confidence_level, 1.) num_baseline_matrices = len(list_of_baseline_matrices) num_trial_matrices = len(list_of_trial_matrices) if num_baseline_matrices != num_trial_matrices: error_string = ( 'Number of baseline matrices ({0:d}) should = number of trial ' 'matrices ({1:d}).').format(num_baseline_matrices, num_trial_matrices) raise ValueError(error_string) num_matrices = num_trial_matrices num_examples_per_set = None for i in range(num_matrices): if (list_of_baseline_matrices[i] is None and list_of_trial_matrices[i] is None): continue error_checking.assert_is_numpy_array(list_of_baseline_matrices[i]) if num_examples_per_set is None: num_examples_per_set = list_of_baseline_matrices[i].shape[0] these_expected_dim = numpy.array( (num_examples_per_set, ) + list_of_baseline_matrices[i].shape[1:], dtype=int) error_checking.assert_is_numpy_array( list_of_baseline_matrices[i], exact_dimensions=these_expected_dim) these_expected_dim = numpy.array(list_of_baseline_matrices[i].shape, dtype=int) error_checking.assert_is_numpy_array( list_of_trial_matrices[i], exact_dimensions=these_expected_dim) if num_examples_per_set is None: raise TypeError('All "input matrices" are None.') return num_examples_per_set
def get_confidence_interval(stat_values, confidence_level=DEFAULT_CONFIDENCE_LEVEL): """Computes confidence interval for bootstrapped statistic. K = number of bootstrapping iterations (number of samples drawn) :param stat_values: length-K numpy array with values of bootstrapped statistic. Each value comes from a different sample ("bootstrap replicate"). :param confidence_level: Level for confidence interval (may range from 0...1). For example, if confidence_level = 0.95, this method will create a 95% confidence interval. :return: confidence_interval_min: Minimum value in confidence interval. :return: confidence_interval_max: Maximum value in confidence interval. """ error_checking.assert_is_numpy_array(stat_values, num_dimensions=1) error_checking.assert_is_real_numpy_array(stat_values) error_checking.assert_is_geq(confidence_level, 0.) error_checking.assert_is_leq(confidence_level, 1.) min_percentile = 50. * (1. - confidence_level) max_percentile = 50. * (1. + confidence_level) confidence_interval_min = numpy.nanpercentile(stat_values, min_percentile, interpolation='linear') confidence_interval_max = numpy.nanpercentile(stat_values, max_percentile, interpolation='linear') return confidence_interval_min, confidence_interval_max
def get_noisings(num_noisings, max_standard_deviation): """Creates an array of standard deviations for Gaussian noising. These standard deviations are meant for use in `noise_radar_images`. N = number of noisings :param num_noisings: Number of times to noise the image. :param max_standard_deviation: Max standard deviation of Gaussian noise. :return: standard_deviations: length-N numpy array of standard deviations. """ error_checking.assert_is_integer(num_noisings) if num_noisings == 0: return numpy.array([], dtype=float) error_checking.assert_is_greater(num_noisings, 0) error_checking.assert_is_geq(max_standard_deviation, MIN_NOISE_STANDARD_DEVIATION) error_checking.assert_is_leq(max_standard_deviation, MAX_NOISE_STANDARD_DEVIATION) return numpy.random.uniform(low=0., high=max_standard_deviation, size=num_noisings)
def _check_args_one_step(predictor_matrix, permuted_flag_matrix, scalar_channel_flags, shuffle_profiles_together, num_bootstrap_reps): """Checks input args for `run_*_test_one_step`. :param predictor_matrix: See doc for `run_forward_test_one_step` or `run_backwards_test_one_step`. :param permuted_flag_matrix: Same. :param scalar_channel_flags: Same. :param shuffle_profiles_together: Same. :param num_bootstrap_reps: Same. :return: num_bootstrap_reps: Same as input but maxxed with 1. """ error_checking.assert_is_numpy_array_without_nan(predictor_matrix) num_predictor_dim = len(predictor_matrix.shape) error_checking.assert_is_geq(num_predictor_dim, 3) error_checking.assert_is_leq(num_predictor_dim, 3) error_checking.assert_is_boolean_numpy_array(permuted_flag_matrix) these_expected_dim = numpy.array(predictor_matrix.shape[1:], dtype=int) error_checking.assert_is_numpy_array(permuted_flag_matrix, exact_dimensions=these_expected_dim) error_checking.assert_is_boolean_numpy_array(scalar_channel_flags) these_expected_dim = numpy.array([predictor_matrix.shape[-1]], dtype=int) error_checking.assert_is_numpy_array(scalar_channel_flags, exact_dimensions=these_expected_dim) error_checking.assert_is_boolean(shuffle_profiles_together) error_checking.assert_is_integer(num_bootstrap_reps) return numpy.maximum(num_bootstrap_reps, 1)
def get_rotations(num_rotations, max_absolute_rotation_angle_deg): """Creates an array of rotation angles. These angles are meant for use in `rotate_radar_images`. N = number of rotations :param num_rotations: Number of rotations. Image will be rotated only in the xy-plane (about the z-axis). :param max_absolute_rotation_angle_deg: Max absolute rotation angle (degrees). In general, the image will be rotated both clockwise and counterclockwise, up to this angle. :return: ccw_rotation_angles_deg: length-N numpy array of counterclockwise rotation angles (degrees). """ error_checking.assert_is_integer(num_rotations) if num_rotations == 0: return numpy.array([], dtype=float) error_checking.assert_is_greater(num_rotations, 0) error_checking.assert_is_geq(max_absolute_rotation_angle_deg, MIN_ABSOLUTE_ROTATION_ANGLE_DEG) error_checking.assert_is_leq(max_absolute_rotation_angle_deg, MAX_ABSOLUTE_ROTATION_ANGLE_DEG) absolute_rotation_angles_deg = numpy.random.uniform( low=1., high=max_absolute_rotation_angle_deg, size=num_rotations) possible_signs = numpy.array([-1, 1], dtype=int) return absolute_rotation_angles_deg * numpy.random.choice( possible_signs, size=num_rotations, replace=True)
def get_saliency_maps_for_class_activation(model_object, target_class, list_of_input_matrices): """For each input example, creates saliency map for prob of target class. :param model_object: Instance of `keras.models.Model`. :param target_class: Saliency maps will be created for this class. Must be an integer in 0...(K - 1), where K = number of classes. :param list_of_input_matrices: See doc for `_do_saliency_calculations`. :return: list_of_saliency_matrices: See doc for `_do_saliency_calculations`. """ check_metadata( component_type_string=model_interpretation.CLASS_COMPONENT_TYPE_STRING, target_class=target_class) num_output_neurons = model_object.layers[-1].output.get_shape().as_list( )[-1] if num_output_neurons == 1: error_checking.assert_is_leq(target_class, 1) if target_class == 1: loss_tensor = K.mean( (model_object.layers[-1].output[..., 0] - 1)**2) else: loss_tensor = K.mean(model_object.layers[-1].output[..., 0]**2) else: error_checking.assert_is_less_than(target_class, num_output_neurons) loss_tensor = K.mean( (model_object.layers[-1].output[..., target_class] - 1)**2) return _do_saliency_calculations( model_object=model_object, loss_tensor=loss_tensor, list_of_input_matrices=list_of_input_matrices)
def do_batch_normalization(feature_matrix, scale_parameter=1., shift_parameter=0.): """Performs batch normalization on each feature in the batch. E = number of examples in batch :param feature_matrix: Input feature maps (numpy array). Dimensions must be E x M x N x C or E x M x N x H x C. :param scale_parameter: Scale parameter (beta in the equation on page 3 of Ioffe and Szegedy 2015). :param shift_parameter: Shift parameter (gamma in the equation). :return: feature_matrix: Feature maps after batch normalization (same dimensions). """ error_checking.assert_is_numpy_array_without_nan(feature_matrix) error_checking.assert_is_greater(scale_parameter, 0.) num_dimensions = len(feature_matrix.shape) error_checking.assert_is_geq(num_dimensions, 4) error_checking.assert_is_leq(num_dimensions, 5) stdev_matrix = numpy.std(feature_matrix, axis=0, ddof=1) stdev_matrix = numpy.expand_dims(stdev_matrix, axis=0) stdev_matrix = numpy.repeat(stdev_matrix, feature_matrix.shape[0], axis=0) mean_matrix = numpy.mean(feature_matrix, axis=0) mean_matrix = numpy.expand_dims(mean_matrix, axis=0) mean_matrix = numpy.repeat(mean_matrix, feature_matrix.shape[0], axis=0) return shift_parameter + scale_parameter * ( (feature_matrix - mean_matrix) / (stdev_matrix + K.epsilon()))
def determinize_probabilities(class_probability_matrix, binarization_threshold): """Determinizes probabilistic predictions. P = number of evaluation pairs :param class_probability_matrix: See documentation for `check_evaluation_pairs`. :param binarization_threshold: See documentation for `find_best_binarization_threshold`. :return: predicted_labels: length-P numpy array of predicted class labels (integers). """ error_checking.assert_is_numpy_array( class_probability_matrix, num_dimensions=2) error_checking.assert_is_geq_numpy_array(class_probability_matrix, 0.) error_checking.assert_is_leq_numpy_array(class_probability_matrix, 1.) error_checking.assert_is_geq(binarization_threshold, 0.) error_checking.assert_is_leq(binarization_threshold, 1.01) num_evaluation_pairs = class_probability_matrix.shape[0] predicted_labels = numpy.full(num_evaluation_pairs, -1, dtype=int) for i in range(num_evaluation_pairs): if class_probability_matrix[i, 0] >= binarization_threshold: predicted_labels[i] = 0 continue predicted_labels[i] = 1 + numpy.argmax(class_probability_matrix[i, 1:]) return predicted_labels
def write_pmm_file(pickle_file_name, mean_denorm_predictor_matrices, mean_saliency_matrices, model_file_name, non_pmm_file_name, pmm_max_percentile_level, mean_sounding_pressures_pa=None): """Writes composite saliency map to Pickle file. The composite should be created by probability-matched means (PMM). H = number of sounding heights :param pickle_file_name: Path to output file. :param mean_denorm_predictor_matrices: See doc for `_check_in_and_out_matrices`. :param mean_saliency_matrices: Same. :param model_file_name: Path to model that created saliency maps (readable by `cnn.read_model`). :param non_pmm_file_name: Path to standard saliency file (containing non-composited saliency maps). :param pmm_max_percentile_level: Max percentile level for PMM. :param mean_sounding_pressures_pa: length-H numpy array of PMM-composited sounding pressures. Needed only if the model is trained with soundings but without pressure as a predictor. """ error_checking.assert_is_string(model_file_name) error_checking.assert_is_string(non_pmm_file_name) error_checking.assert_is_geq(pmm_max_percentile_level, 90.) error_checking.assert_is_leq(pmm_max_percentile_level, 100.) _check_in_and_out_matrices( predictor_matrices=mean_denorm_predictor_matrices, num_examples=None, saliency_matrices=mean_saliency_matrices) if mean_sounding_pressures_pa is not None: num_heights = mean_denorm_predictor_matrices[-1].shape[-2] these_expected_dim = numpy.array([num_heights], dtype=int) error_checking.assert_is_geq_numpy_array(mean_sounding_pressures_pa, 0.) error_checking.assert_is_numpy_array( mean_sounding_pressures_pa, exact_dimensions=these_expected_dim) mean_saliency_dict = { MEAN_PREDICTOR_MATRICES_KEY: mean_denorm_predictor_matrices, MEAN_SALIENCY_MATRICES_KEY: mean_saliency_matrices, MODEL_FILE_KEY: model_file_name, NON_PMM_FILE_KEY: non_pmm_file_name, PMM_MAX_PERCENTILE_KEY: pmm_max_percentile_level, MEAN_SOUNDING_PRESSURES_KEY: mean_sounding_pressures_pa } file_system_utils.mkdir_recursive_if_necessary(file_name=pickle_file_name) pickle_file_handle = open(pickle_file_name, 'wb') pickle.dump(mean_saliency_dict, pickle_file_handle) pickle_file_handle.close()
def get_translations(num_translations, max_translation_pixels, num_grid_rows, num_grid_columns): """Creates an array of x- and y-translations. These translations ("offsets") are meant for use in `shift_radar_images`. N = number of translations :param num_translations: Number of translations. Image will be translated in only the x- and y-directions, not the z-direction. :param max_translation_pixels: Max translation in either direction. Must be an integer. :param num_grid_rows: Number of rows in the image. :param num_grid_columns: Number of columns in the image. :return: x_offsets_pixels: length-N numpy array of x-translations (integers). :return: y_offsets_pixels: length-N numpy array of y-translations (integers). """ error_checking.assert_is_integer(num_translations) if num_translations == 0: return numpy.array([], dtype=int), numpy.array([], dtype=int) error_checking.assert_is_greater(num_translations, 0) error_checking.assert_is_integer(num_grid_rows) error_checking.assert_is_geq(num_grid_rows, 2) error_checking.assert_is_integer(num_grid_columns) error_checking.assert_is_geq(num_grid_columns, 2) error_checking.assert_is_integer(max_translation_pixels) error_checking.assert_is_greater(max_translation_pixels, 0) smallest_horiz_dimension = min([num_grid_rows, num_grid_columns]) max_max_translation_pixels = int( numpy.floor(float(smallest_horiz_dimension) / 2)) error_checking.assert_is_leq(max_translation_pixels, max_max_translation_pixels) x_offsets_pixels = numpy.random.random_integers( low=-max_translation_pixels, high=max_translation_pixels, size=num_translations * 4) y_offsets_pixels = numpy.random.random_integers( low=-max_translation_pixels, high=max_translation_pixels, size=num_translations * 4) good_indices = numpy.where( numpy.absolute(x_offsets_pixels) + numpy.absolute(y_offsets_pixels) > 0)[0] good_indices = numpy.random.choice(good_indices, size=num_translations, replace=False) return x_offsets_pixels[good_indices], y_offsets_pixels[good_indices]
def _check_regression_params(min_lead_time_sec=None, max_lead_time_sec=None, min_distance_metres=None, max_distance_metres=None, percentile_level=None): """Error-checks (and if necessary, rounds) parameters for regression labels. t = time of a given storm object :param min_lead_time_sec: Minimum lead time (wind time minus storm-object time). Wind observations occurring before t + min_lead_time_sec are ignored. :param max_lead_time_sec: Maximum lead time (wind time minus storm-object time). Wind observations occurring after t + max_lead_time_sec are ignored. :param min_distance_metres: Minimum distance between storm boundary and wind observations. Wind observations nearer to the storm are ignored. :param max_distance_metres: Maximum distance between storm boundary and wind observations. Wind observations farther from the storm are ignored. :param percentile_level: The label for each storm object will be the [q]th- percentile speed of wind observations in the given time and distance ranges, where q = percentile_level. :return: parameter_dict: Dictionary with the following keys. parameter_dict['min_lead_time_sec']: Same as input, but maybe rounded. parameter_dict['max_lead_time_sec']: Same as input, but maybe rounded. parameter_dict['min_distance_metres']: Same as input, but maybe rounded. parameter_dict['max_distance_metres']: Same as input, but maybe rounded. parameter_dict['percentile_level']: Same as input, but maybe rounded. """ error_checking.assert_is_integer(min_lead_time_sec) error_checking.assert_is_geq(min_lead_time_sec, 0) error_checking.assert_is_integer(max_lead_time_sec) error_checking.assert_is_geq(max_lead_time_sec, min_lead_time_sec) error_checking.assert_is_geq(min_distance_metres, 0.) error_checking.assert_is_geq(max_distance_metres, min_distance_metres) error_checking.assert_is_geq(percentile_level, 0.) error_checking.assert_is_leq(percentile_level, 100.) min_distance_metres = rounder.round_to_nearest(min_distance_metres, DISTANCE_PRECISION_METRES) max_distance_metres = rounder.round_to_nearest(max_distance_metres, DISTANCE_PRECISION_METRES) percentile_level = rounder.round_to_nearest(percentile_level, PERCENTILE_LEVEL_PRECISION) return { MIN_LEAD_TIME_NAME: min_lead_time_sec, MAX_LEAD_TIME_NAME: max_lead_time_sec, MIN_DISTANCE_NAME: min_distance_metres, MAX_DISTANCE_NAME: max_distance_metres, PERCENTILE_LEVEL_NAME: percentile_level }
def check_target_array(target_array, num_dimensions, num_classes): """Error-checks target values. :param target_array: numpy array in one of two formats. [1] length-E integer numpy array of target values. All values are -2 ("dead storm") or 0...[K - 1], where K = number of classes. [2] E-by-K numpy array, where each value is 0 or 1. If target_array[i, k] = 1, the [i]th storm object belongs to the [k]th class. Classes are mutually exclusive and collectively exhaustive, so the sum across each row of the matrix is 1. :param num_dimensions: Number of dimensions expected in `target_array`. :param num_classes: Number of classes that should be represented in `target_array`. """ error_checking.assert_is_integer(num_dimensions) error_checking.assert_is_geq(num_dimensions, 1) error_checking.assert_is_leq(num_dimensions, 2) error_checking.assert_is_integer(num_classes) error_checking.assert_is_geq(num_classes, 2) num_examples = target_array.shape[0] if num_dimensions == 1: error_checking.assert_is_integer_numpy_array(target_array) these_expected_dim = numpy.array([num_examples], dtype=int) error_checking.assert_is_numpy_array( target_array, exact_dimensions=these_expected_dim) # TODO(thunderhoser): This is a HACK. Should do better input-checking. # live_storm_object_indices = numpy.where( # target_array != target_val_utils.DEAD_STORM_INTEGER # )[0] # error_checking.assert_is_geq_numpy_array( # target_array[live_storm_object_indices], 0 # ) error_checking.assert_is_geq_numpy_array( target_array, target_val_utils.DEAD_STORM_INTEGER) error_checking.assert_is_less_than_numpy_array(target_array, num_classes) else: error_checking.assert_is_geq_numpy_array(target_array, 0) error_checking.assert_is_leq_numpy_array(target_array, 1) these_expected_dim = numpy.array([num_examples, num_classes], dtype=int) error_checking.assert_is_numpy_array( target_array, exact_dimensions=these_expected_dim)
def get_random_colours(num_colours, colour_to_exclude_rgb=None, min_rgb_distance=DEFAULT_MIN_RGB_DISTANCE): """Returns list of random colours. N = number of colours :param num_colours: Number of colours desired. :param colour_to_exclude_rgb: Colour to exclude (length-3 numpy array with values in 0...1). :param min_rgb_distance: All colours returned will be at least this far away from `colour_to_exclude_rgb`. Distance is Euclidean. :return: rgb_matrix: N-by-3 numpy array with values in 0...1. Each row is one colour. """ orig_num_colours = num_colours + 0 if colour_to_exclude_rgb is not None: error_checking.assert_is_numpy_array( colour_to_exclude_rgb, exact_dimensions=numpy.array([3], dtype=int) ) error_checking.assert_is_geq_numpy_array(colour_to_exclude_rgb, 0.) error_checking.assert_is_leq_numpy_array(colour_to_exclude_rgb, 1.) error_checking.assert_is_greater(min_rgb_distance, 0.) error_checking.assert_is_leq(min_rgb_distance, 1.) num_colours = 10 * num_colours rgb_matrix = numpy.random.uniform(low=0., high=1., size=(num_colours, 3)) if colour_to_exclude_rgb is not None: colour_to_exclude_rgb = numpy.reshape(colour_to_exclude_rgb, (1, 3)) squared_distances = euclidean_distances( X=rgb_matrix, Y=numpy.reshape(colour_to_exclude_rgb, (1, 3)), squared=True ) good_indices = numpy.where( squared_distances >= min_rgb_distance ** 2 )[0] rgb_matrix = rgb_matrix[good_indices, ...] num_colours = min([ orig_num_colours, rgb_matrix.shape[0] ]) rgb_matrix = rgb_matrix[:num_colours, ...] numpy.random.shuffle(rgb_matrix) return rgb_matrix
def get_default_colour_scheme(field_name, opacity=DEFAULT_OPACITY): """Returns default colour scheme for radar field. :param field_name: Field name (must be accepted by `radar_utils.check_field_name`). :param opacity: Opacity (in range 0...1). :return: colour_map_object: Instance of `matplotlib.colors.ListedColormap`. :return: colour_norm_object: Instance of `matplotlib.colors.BoundaryNorm`. """ radar_utils.check_field_name(field_name) error_checking.assert_is_greater(opacity, 0.) error_checking.assert_is_leq(opacity, 1.) colour_map_object = None colour_norm_object = None if field_name in radar_utils.REFLECTIVITY_NAMES: colour_map_object, colour_norm_object = ( _get_reflectivity_colour_scheme()) elif field_name in radar_utils.SHEAR_NAMES: colour_map_object, colour_norm_object = _get_az_shear_colour_scheme() elif field_name in radar_utils.ECHO_TOP_NAMES: colour_map_object, colour_norm_object = _get_echo_top_colour_scheme() elif field_name == radar_utils.MESH_NAME: colour_map_object, colour_norm_object = _get_mesh_colour_scheme() elif field_name == radar_utils.SHI_NAME: colour_map_object, colour_norm_object = _get_shi_colour_scheme() elif field_name == radar_utils.VIL_NAME: colour_map_object, colour_norm_object = _get_vil_colour_scheme() elif field_name == radar_utils.DIFFERENTIAL_REFL_NAME: colour_map_object, colour_norm_object = _get_zdr_colour_scheme() elif field_name == radar_utils.SPEC_DIFF_PHASE_NAME: colour_map_object, colour_norm_object = _get_kdp_colour_scheme() elif field_name == radar_utils.CORRELATION_COEFF_NAME: colour_map_object, colour_norm_object = _get_rho_hv_colour_scheme() elif field_name == radar_utils.SPECTRUM_WIDTH_NAME: colour_map_object, colour_norm_object = ( _get_spectrum_width_colour_scheme()) elif field_name == radar_utils.VORTICITY_NAME: colour_map_object, colour_norm_object = _get_vorticity_colour_scheme() elif field_name == radar_utils.DIVERGENCE_NAME: colour_map_object, colour_norm_object = _get_divergence_colour_scheme() num_colours = len(colour_map_object.colors) for i in range(num_colours): colour_map_object.colors[i] = matplotlib.colors.to_rgba( colour_map_object.colors[i], opacity) return colour_map_object, colour_norm_object
def check_output(monte_carlo_dict): """Error-checks output from Monte Carlo test. :param monte_carlo_dict: Dictionary created by `run_monte_carlo_test`. :raises: ValueError: if not (number of trial matrices = number of MIN matrices = number of MAX matrices). """ error_checking.assert_is_greater(monte_carlo_dict[MAX_PMM_PERCENTILE_KEY], 50.) error_checking.assert_is_leq(monte_carlo_dict[MAX_PMM_PERCENTILE_KEY], 100.) error_checking.assert_is_integer(monte_carlo_dict[NUM_ITERATIONS_KEY]) error_checking.assert_is_geq(monte_carlo_dict[NUM_ITERATIONS_KEY], 100) error_checking.assert_is_geq(monte_carlo_dict[CONFIDENCE_LEVEL_KEY], 0.) error_checking.assert_is_leq(monte_carlo_dict[CONFIDENCE_LEVEL_KEY], 1.) num_trial_matrices = len(monte_carlo_dict[TRIAL_PMM_MATRICES_KEY]) num_min_matrices = len(monte_carlo_dict[MIN_MATRICES_KEY]) num_max_matrices = len(monte_carlo_dict[MAX_MATRICES_KEY]) if not num_trial_matrices == num_min_matrices == num_max_matrices: error_string = ( 'Number of trial ({0:d}), MIN ({1:d}), and MAX ({2:d}) matrices ' 'should be the same.').format(num_trial_matrices, num_min_matrices, num_max_matrices) raise ValueError(error_string) num_matrices = num_trial_matrices for i in range(num_matrices): if (monte_carlo_dict[TRIAL_PMM_MATRICES_KEY][i] is None and monte_carlo_dict[MIN_MATRICES_KEY][i] is None and monte_carlo_dict[MAX_MATRICES_KEY][i] is None): continue error_checking.assert_is_numpy_array( monte_carlo_dict[TRIAL_PMM_MATRICES_KEY][i]) these_expected_dim = numpy.array( monte_carlo_dict[TRIAL_PMM_MATRICES_KEY][i].shape, dtype=int) error_checking.assert_is_numpy_array( monte_carlo_dict[MIN_MATRICES_KEY][i], exact_dimensions=these_expected_dim) error_checking.assert_is_numpy_array( monte_carlo_dict[MAX_MATRICES_KEY][i], exact_dimensions=these_expected_dim)
def _check_convolution_options( num_kernel_rows, num_rows_per_stride, padding_type_string, num_filters, num_kernel_dimensions, num_kernel_columns=None, num_columns_per_stride=None, num_kernel_heights=None, num_heights_per_stride=None): """Checks input args for 1-D, 2-D, or 3-D convolution layer. :param num_kernel_rows: Number of rows in kernel. :param num_rows_per_stride: Number of rows per stride (number of rows moved by the kernel at once). :param padding_type_string: Padding type (must be in `VALID_PADDING_TYPE_STRINGS`). :param num_filters: Number of output filters (channels). :param num_kernel_dimensions: Number of dimensions in kernel. :param num_kernel_columns: [used only if num_kernel_dimensions > 1] Number of columns in kernel. :param num_columns_per_stride: [used only if num_kernel_dimensions > 1] Number of columns per stride. :param num_kernel_heights: [used only if num_kernel_dimensions = 3] Number of heights in kernel. :param num_heights_per_stride: [used only if num_kernel_dimensions = 3] Number of heights per stride. :raises: ValueError: if `padding_type_string not in VALID_PADDING_TYPE_STRINGS`. """ error_checking.assert_is_integer(num_kernel_rows) error_checking.assert_is_geq(num_kernel_rows, 3) error_checking.assert_is_integer(num_rows_per_stride) error_checking.assert_is_geq(num_rows_per_stride, 1) error_checking.assert_is_leq(num_rows_per_stride, num_kernel_rows) error_checking.assert_is_string(padding_type_string) if padding_type_string not in VALID_PADDING_TYPE_STRINGS: error_string = ( '\n{0:s}\nValid padding types (listed above) do not include ' '"{1:s}".' ).format(str(VALID_PADDING_TYPE_STRINGS), padding_type_string) raise ValueError(error_string) error_checking.assert_is_integer(num_filters) error_checking.assert_is_geq(num_filters, 1) error_checking.assert_is_integer(num_kernel_dimensions) error_checking.assert_is_geq(num_kernel_dimensions, 1) error_checking.assert_is_leq(num_kernel_dimensions, 3) if num_kernel_dimensions >= 2: error_checking.assert_is_integer(num_kernel_columns) error_checking.assert_is_geq(num_kernel_columns, 3) error_checking.assert_is_integer(num_columns_per_stride) error_checking.assert_is_geq(num_columns_per_stride, 1) error_checking.assert_is_leq(num_columns_per_stride, num_kernel_columns) if num_kernel_dimensions == 3: error_checking.assert_is_integer(num_kernel_heights) error_checking.assert_is_geq(num_kernel_heights, 3) error_checking.assert_is_integer(num_heights_per_stride) error_checking.assert_is_geq(num_heights_per_stride, 1) error_checking.assert_is_leq(num_heights_per_stride, num_kernel_heights)
def create_gif(input_file_names, output_file_name, num_seconds_per_frame, resize_factor=0.5, convert_exe_name=DEFAULT_CONVERT_EXE_NAME): """Creates GIF from static images. :param input_file_names: 1-D list of paths to input files (static images). :param output_file_name: Path to output file (GIF). :param num_seconds_per_frame: Number of seconds per frame. :param resize_factor: Resize factor. When creating GIF, each static image (frame) will be resized to q times its original size, where q = `resize_factor`. This will affect only the GIF. The images themselves, at locations specified in `input_file_names`, will not be changed. :param convert_exe_name: See doc for `trim_whitespace`. :raises: ValueError: if ImageMagick command (which is ultimately a Unix command) fails. """ error_checking.assert_is_string_list(input_file_names) error_checking.assert_is_numpy_array(numpy.array(input_file_names), num_dimensions=1) file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name) error_checking.assert_file_exists(convert_exe_name) error_checking.assert_is_greater(num_seconds_per_frame, 0.) error_checking.assert_is_leq(num_seconds_per_frame, 10.) error_checking.assert_is_geq(resize_factor, 0.2) error_checking.assert_is_leq(resize_factor, 1.) num_centiseconds_per_frame = int(numpy.round(100 * num_seconds_per_frame)) num_centiseconds_per_frame = max([num_centiseconds_per_frame, 1]) resize_percentage = int(numpy.round(100 * resize_factor)) resize_percentage = max([resize_percentage, 1]) command_string = '"{0:s}" -delay {1:d} '.format( convert_exe_name, num_centiseconds_per_frame) command_string += ' '.join(['"{0:s}"'.format(f) for f in input_file_names]) command_string += ' -resize {0:d}% "{1:s}"'.format(resize_percentage, output_file_name) exit_code = os.system(command_string) if exit_code == 0: return raise ValueError(ERROR_STRING)
def _run(saliency_file_name, num_examples_to_plot, colour_map_name, max_colour_percentile, output_dir_name): """Plots saliency maps for all target variables. This is effectively the main method. :param saliency_file_name: See documentation at top of file. :param num_examples_to_plot: Same. :param colour_map_name: Same. :param max_colour_percentile: Same. :param output_dir_name: Same. """ colour_map_object = pyplot.get_cmap(colour_map_name) error_checking.assert_is_geq(max_colour_percentile, 90.) error_checking.assert_is_leq(max_colour_percentile, 100.) file_system_utils.mkdir_recursive_if_necessary( directory_name=output_dir_name) print( 'Reading saliency values from: "{0:s}"...'.format(saliency_file_name)) saliency_dict = saliency.read_all_targets_file(saliency_file_name) model_file_name = saliency_dict[saliency.MODEL_FILE_KEY] model_metafile_name = neural_net.find_metafile( model_dir_name=os.path.split(model_file_name)[0]) print( 'Reading model metadata from: "{0:s}"...'.format(model_metafile_name)) model_metadata_dict = neural_net.read_metafile(model_metafile_name) num_examples_total = len(saliency_dict[saliency.EXAMPLE_IDS_KEY]) if num_examples_to_plot <= 0: num_examples_to_plot = num_examples_total num_examples_to_plot = numpy.minimum(num_examples_to_plot, num_examples_total) print(SEPARATOR_STRING) for i in range(num_examples_to_plot): _plot_saliency_one_example(saliency_dict=saliency_dict, example_index=i, model_metadata_dict=model_metadata_dict, colour_map_object=colour_map_object, max_colour_percentile=max_colour_percentile, output_dir_name=output_dir_name) print(SEPARATOR_STRING)
def plot_taylor_diagram(target_stdev, prediction_stdev, correlation, marker_colour, figure_object): """Plots Taylor diagram. :param target_stdev: Standard deviation of target (actual) values. :param prediction_stdev: Standard deviation of predicted values. :param correlation: Correlation between actual and predicted values. :param marker_colour: Colour for markers (in any format accepted by matplotlib). :param figure_object: Will plot on this figure (instance of `matplotlib.figure.Figure`). :return: taylor_diagram_object: Handle for Taylor diagram (instance of `taylor_diagram.TaylorDiagram`). """ error_checking.assert_is_geq(target_stdev, 0.) error_checking.assert_is_geq(prediction_stdev, 0.) error_checking.assert_is_geq(correlation, -1., allow_nan=True) error_checking.assert_is_leq(correlation, 1., allow_nan=True) taylor_diagram_object = taylor_diagram.TaylorDiagram(refstd=target_stdev, fig=figure_object, srange=(0, 2), extend=False) target_marker_object = taylor_diagram_object.samplePoints[0] target_marker_object.set_marker(TAYLOR_TARGET_MARKER_TYPE) target_marker_object.set_markersize(TAYLOR_TARGET_MARKER_SIZE) target_marker_object.set_markerfacecolor(marker_colour) target_marker_object.set_markeredgewidth(0) if not numpy.isnan(correlation): taylor_diagram_object.add_sample(stddev=prediction_stdev, corrcoef=correlation) prediction_marker_object = taylor_diagram_object.samplePoints[-1] prediction_marker_object.set_marker(TAYLOR_PREDICTION_MARKER_TYPE) prediction_marker_object.set_markersize(TAYLOR_PREDICTION_MARKER_SIZE) prediction_marker_object.set_markerfacecolor(marker_colour) prediction_marker_object.set_markeredgewidth(0) crmse_contour_object = taylor_diagram_object.add_contours(levels=5, colors='0.5') pyplot.clabel(crmse_contour_object, inline=1, fmt='%.0f') taylor_diagram_object.add_grid() taylor_diagram_object._ax.axis[:].major_ticks.set_tick_out(True) return taylor_diagram_object
def _check_pooling_options( num_rows_in_window, num_rows_per_stride, pooling_type_string, num_dimensions, num_columns_in_window=None, num_columns_per_stride=None, num_heights_in_window=None, num_heights_per_stride=None): """Checks input args for 1-D, 2-D, or 3-D pooling layer. :param num_rows_in_window: Number of rows in pooling window. :param num_rows_per_stride: Number of rows per stride (number of rows moved by the window at once). :param pooling_type_string: Pooling type (must be in `VALID_POOLING_TYPE_STRINGS`). :param num_dimensions: Number of dimensions in pooling window. :param num_columns_in_window: [used only if num_dimensions > 1] Number of columns in window. :param num_columns_per_stride: [used only if num_dimensions > 1] Number of columns per stride. :param num_heights_in_window: [used only if num_dimensions = 3] Number of heights in window. :param num_heights_per_stride: [used only if num_dimensions = 3] Number of heights per stride. :raises: ValueError: if `pooling_type_string not in VALID_POOLING_TYPE_STRINGS`. """ error_checking.assert_is_integer(num_rows_in_window) error_checking.assert_is_geq(num_rows_in_window, 2) error_checking.assert_is_integer(num_rows_per_stride) error_checking.assert_is_geq(num_rows_per_stride, 1) error_checking.assert_is_leq(num_rows_per_stride, num_rows_in_window) error_checking.assert_is_string(pooling_type_string) if pooling_type_string not in VALID_POOLING_TYPE_STRINGS: error_string = ( '\n{0:s}\nValid pooling types (listed above) do not include ' '"{1:s}".' ).format(str(VALID_POOLING_TYPE_STRINGS), pooling_type_string) raise ValueError(error_string) error_checking.assert_is_integer(num_dimensions) error_checking.assert_is_geq(num_dimensions, 1) error_checking.assert_is_leq(num_dimensions, 3) if num_dimensions >= 2: error_checking.assert_is_integer(num_columns_in_window) error_checking.assert_is_geq(num_columns_in_window, 2) error_checking.assert_is_integer(num_columns_per_stride) error_checking.assert_is_geq(num_columns_per_stride, 1) error_checking.assert_is_leq(num_columns_per_stride, num_columns_in_window) if num_dimensions == 3: error_checking.assert_is_integer(num_heights_in_window) error_checking.assert_is_geq(num_heights_in_window, 1) error_checking.assert_is_integer(num_heights_per_stride) error_checking.assert_is_geq(num_heights_per_stride, 1) error_checking.assert_is_leq(num_heights_per_stride, num_heights_in_window)
def _check_decision_tree_hyperparams( num_trees, loss_function_string, num_features_total, num_features_per_split, max_depth, min_examples_per_split, min_examples_per_leaf, learning_rate=None, subsampling_fraction=None): """Checks decision-tree hyperparameters (input parameters) for errors. :param num_trees: Number of trees in ensemble. :param loss_function_string: Loss function. This method ensures only that the loss function is a string. The specific learning method will determine whether or not the string is valid. :param num_features_total: Number of features in training data. :param num_features_per_split: Number of features to investigate at each split point (branch node). :param max_depth: Max depth of any tree in ensemble. :param min_examples_per_split: Minimum number of examples (storm objects) at a split point (branch node). :param min_examples_per_leaf: Minimum number of examples (storm objects) at a leaf node. :param learning_rate: [for gradient-boosting only] Learning rate (used to decrease the contribution of each successive tree). :param subsampling_fraction: [for gradient-boosting only] Fraction of examples to use in training each tree. """ error_checking.assert_is_integer(num_trees) error_checking.assert_is_geq(num_trees, 2) error_checking.assert_is_string(loss_function_string) error_checking.assert_is_integer(num_features_per_split) error_checking.assert_is_greater(num_features_per_split, 0) error_checking.assert_is_leq(num_features_per_split, num_features_total) if max_depth is not None: error_checking.assert_is_integer(max_depth) error_checking.assert_is_greater(max_depth, 0) error_checking.assert_is_integer(min_examples_per_split) error_checking.assert_is_greater(min_examples_per_split, 1) error_checking.assert_is_integer(min_examples_per_leaf) error_checking.assert_is_greater(min_examples_per_leaf, 0) if learning_rate is not None: error_checking.assert_is_greater(learning_rate, 0.) error_checking.assert_is_less_than(learning_rate, 1.) if subsampling_fraction is not None: error_checking.assert_is_greater(subsampling_fraction, 0.) error_checking.assert_is_leq(subsampling_fraction, 1.)
def optimize_input_for_class(model_object, target_class, init_function_or_matrices, num_iterations=DEFAULT_NUM_ITERATIONS, learning_rate=DEFAULT_LEARNING_RATE): """Creates synthetic input example to maximize probability of target class. :param model_object: Trained instance of `keras.models.Model` or `keras.models.Sequential`. :param target_class: Input data will be optimized for this class. Must be an integer in 0...(K - 1), where K = number of classes. :param init_function_or_matrices: See doc for `_do_gradient_descent`. :param num_iterations: Same. :param learning_rate: Same. :return: list_of_optimized_matrices: Same. """ model_interpretation.check_component_metadata( component_type_string=model_interpretation.CLASS_COMPONENT_TYPE_STRING, target_class=target_class) _check_input_args(num_iterations=num_iterations, learning_rate=learning_rate) num_output_neurons = ( model_object.layers[-1].output.get_shape().as_list()[-1]) if num_output_neurons == 1: error_checking.assert_is_leq(target_class, 1) if target_class == 1: loss_tensor = K.mean( (model_object.layers[-1].output[..., 0] - 1)**2) else: loss_tensor = K.mean(model_object.layers[-1].output[..., 0]**2) else: error_checking.assert_is_less_than(target_class, num_output_neurons) loss_tensor = K.mean( (model_object.layers[-1].output[..., target_class] - 1)**2) return _do_gradient_descent( model_object=model_object, loss_tensor=loss_tensor, init_function_or_matrices=init_function_or_matrices, num_iterations=num_iterations, learning_rate=learning_rate)
def _check_unet_input_args(num_predictors, weight_loss_function, convolve_over_time, assumed_class_frequencies=None, num_classes=None, num_predictor_time_steps=None): """Checks input arguments for U-net. K = number of classes :param num_predictors: See documentation for `get_unet_with_2d_convolution`. :param weight_loss_function: Same. :param convolve_over_time: Same. :param assumed_class_frequencies: [used only if weight_loss_function = True] Same. :param num_classes: [used only if weight_loss_function = False] Same. :param num_predictor_time_steps: [used only if convolve_over_time = True] Same. :return: class_weights: length-K numpy array of class weights for loss function. """ error_checking.assert_is_integer(num_predictors) error_checking.assert_is_geq(num_predictors, 1) error_checking.assert_is_boolean(weight_loss_function) error_checking.assert_is_boolean(convolve_over_time) if weight_loss_function: class_weight_dict = ml_utils.get_class_weight_dict( assumed_class_frequencies) class_weights = numpy.array(class_weight_dict.values()) num_classes = len(class_weights) error_checking.assert_is_integer(num_classes) error_checking.assert_is_geq(num_classes, 2) error_checking.assert_is_leq(num_classes, 3) if not weight_loss_function: class_weights = numpy.array(num_classes, 1. / num_classes) if convolve_over_time: error_checking.assert_is_integer(num_predictor_time_steps) error_checking.assert_is_geq(num_predictor_time_steps, 6) return class_weights
def check_input_args(input_matrix, max_percentile_level): """Error-checks input arguments. :param input_matrix: See doc for `run_pmm_many_variables`. :param max_percentile_level: Same. :return: metadata_dict: Dictionary with the following keys. metadata_dict['max_percentile_level']: See input doc. """ error_checking.assert_is_numpy_array_without_nan(input_matrix) num_spatial_dimensions = len(input_matrix.shape) - 2 error_checking.assert_is_geq(num_spatial_dimensions, 1) error_checking.assert_is_geq(max_percentile_level, 90.) error_checking.assert_is_leq(max_percentile_level, 100.) return {MAX_PERCENTILE_KEY: max_percentile_level}
def colour_from_numpy_to_tuple(input_colour): """Converts colour from numpy array to tuple (if necessary). :param input_colour: Colour (possibly length-3 or length-4 numpy array). :return: output_colour: Colour (possibly length-3 or length-4 tuple). """ if not isinstance(input_colour, numpy.ndarray): return input_colour error_checking.assert_is_numpy_array(input_colour, num_dimensions=1) num_entries = len(input_colour) error_checking.assert_is_geq(num_entries, 3) error_checking.assert_is_leq(num_entries, 4) return tuple(input_colour.tolist())
def check_input_args(input_matrix, max_percentile_level, threshold_var_index, threshold_value, threshold_type_string): """Error-checks input arguments. :param input_matrix: See doc for `run_pmm_many_variables`. :param max_percentile_level: Same. :param threshold_var_index: Same. :param threshold_value: Same. :param threshold_type_string: Same. :return: metadata_dict: Dictionary with the following keys. metadata_dict['max_percentile_level']: See input doc. metadata_dict['threshold_var_index']: See input doc. metadata_dict['threshold_value']: See input doc. metadata_dict['threshold_type_string']: See input doc. """ error_checking.assert_is_numpy_array_without_nan(input_matrix) num_spatial_dimensions = len(input_matrix.shape) - 2 error_checking.assert_is_geq(num_spatial_dimensions, 1) error_checking.assert_is_greater(max_percentile_level, 50.) error_checking.assert_is_leq(max_percentile_level, 100.) use_threshold = not (threshold_var_index is None and threshold_value is None and threshold_type_string is None) if use_threshold: _check_threshold_type(threshold_type_string) error_checking.assert_is_not_nan(threshold_value) error_checking.assert_is_integer(threshold_var_index) error_checking.assert_is_geq(threshold_var_index, 0) num_variables = input_matrix.shape[-1] error_checking.assert_is_less_than(threshold_var_index, num_variables) else: threshold_var_index = -1 return { MAX_PERCENTILE_KEY: max_percentile_level, THRESHOLD_VAR_KEY: threshold_var_index, THRESHOLD_VALUE_KEY: threshold_value, THRESHOLD_TYPE_KEY: threshold_type_string }
def _run(gradcam_file_name, colour_map_name, max_colour_percentile, output_dir_name): """Plots Grad-CAM output (class-activation maps) for all target variables. This is effectively the main method. :param gradcam_file_name: See documentation at top of file. :param colour_map_name: Same. :param max_colour_percentile: Same. :param output_dir_name: Same. """ colour_map_object = pyplot.get_cmap(colour_map_name) error_checking.assert_is_geq(max_colour_percentile, 90.) error_checking.assert_is_leq(max_colour_percentile, 100.) file_system_utils.mkdir_recursive_if_necessary( directory_name=output_dir_name ) print('Reading class-activation maps from: "{0:s}"...'.format( gradcam_file_name )) gradcam_dict = gradcam.read_all_targets_file(gradcam_file_name) model_file_name = gradcam_dict[gradcam.MODEL_FILE_KEY] model_metafile_name = neural_net.find_metafile( model_dir_name=os.path.split(model_file_name)[0] ) print('Reading model metadata from: "{0:s}"...'.format(model_metafile_name)) model_metadata_dict = neural_net.read_metafile(model_metafile_name) num_examples = len(gradcam_dict[gradcam.EXAMPLE_IDS_KEY]) print(SEPARATOR_STRING) for i in range(num_examples): _plot_gradcam_one_example( gradcam_dict=gradcam_dict, example_index=i, model_metadata_dict=model_metadata_dict, colour_map_object=colour_map_object, max_colour_percentile=max_colour_percentile, output_dir_name=output_dir_name ) print(SEPARATOR_STRING)
def create_model( num_classes, num_trees=DEFAULT_NUM_TREES, learning_rate=DEFAULT_LEARNING_RATE, max_depth=DEFAULT_MAX_TREE_DEPTH, fraction_of_examples_per_tree=DEFAULT_FRACTION_OF_EXAMPLES_PER_TREE, fraction_of_features_per_split=DEFAULT_FRACTION_OF_FEATURES_PER_SPLIT, l2_weight=DEFAULT_L2_WEIGHT): """Creates GBT model for classification. :param num_classes: Number of target classes. If num_classes = 2, the model will do binary probabilistic classification. If num_classes > 2, the model will do multiclass probabilistic classification. :param num_trees: Number of trees. :param learning_rate: Learning rate. :param max_depth: Maximum depth (applied to each tree). :param fraction_of_examples_per_tree: Fraction of examples (storm objects) to be used in training each tree. :param fraction_of_features_per_split: Fraction of features (predictor variables) to be used at each split point. :param l2_weight: L2-regularization weight. :return: model_object: Untrained instance of `xgboost.XGBClassifier`. """ error_checking.assert_is_integer(num_classes) error_checking.assert_is_geq(num_classes, 2) error_checking.assert_is_integer(num_trees) error_checking.assert_is_geq(num_trees, 10) error_checking.assert_is_leq(num_trees, 1000) error_checking.assert_is_greater(learning_rate, 0.) error_checking.assert_is_less_than(learning_rate, 1.) error_checking.assert_is_integer(max_depth) error_checking.assert_is_geq(max_depth, 1) error_checking.assert_is_leq(max_depth, 10) error_checking.assert_is_greater(fraction_of_examples_per_tree, 0.) error_checking.assert_is_leq(fraction_of_examples_per_tree, 1.) error_checking.assert_is_greater(fraction_of_features_per_split, 0.) error_checking.assert_is_leq(fraction_of_features_per_split, 1.) error_checking.assert_is_geq(l2_weight, 0.) if num_classes == 2: return xgboost.XGBClassifier( max_depth=max_depth, learning_rate=learning_rate, n_estimators=num_trees, silent=False, objective='binary:logistic', subsample=fraction_of_examples_per_tree, colsample_bylevel=fraction_of_features_per_split, reg_lambda=l2_weight) return xgboost.XGBClassifier( max_depth=max_depth, learning_rate=learning_rate, n_estimators=num_trees, silent=False, objective='multi:softprob', subsample=fraction_of_examples_per_tree, colsample_bylevel=fraction_of_features_per_split, reg_lambda=l2_weight, num_class=num_classes)
def get_class_activation_for_examples( model_object, target_class, list_of_input_matrices): """For each input example, returns predicted probability of target class. :param model_object: Instance of `keras.models.Model`. :param target_class: Predictions will be returned for this class. Must be an integer in 0...(K - 1), where K = number of classes. :param list_of_input_matrices: length-T list of numpy arrays, comprising one or more examples (storm objects). list_of_input_matrices[i] must have the same dimensions as the [i]th input tensor to the model. :return: activation_values: length-E numpy array, where activation_values[i] is the activation (predicted probability or logit) of the target class for the [i]th example. """ check_metadata( component_type_string=model_interpretation.CLASS_COMPONENT_TYPE_STRING, target_class=target_class) if isinstance(model_object.input, list): list_of_input_tensors = model_object.input else: list_of_input_tensors = [model_object.input] num_output_neurons = model_object.layers[-1].output.get_shape().as_list()[ -1] if num_output_neurons == 1: error_checking.assert_is_leq(target_class, 1) if target_class == 1: output_tensor = model_object.layers[-1].output[..., 0] else: output_tensor = 1. - model_object.layers[-1].output[..., 0] else: error_checking.assert_is_less_than(target_class, num_output_neurons) output_tensor = model_object.layers[-1].output[..., target_class] activation_function = K.function( list_of_input_tensors + [K.learning_phase()], [output_tensor]) return activation_function(list_of_input_matrices + [0])[0]
def _check_architecture_args(option_dict): """Error-checks input arguments for architecture. :param option_dict: See doc for `create_model`. :return: option_dict: Same as input, except defaults may have been added. """ orig_option_dict = option_dict.copy() option_dict = DEFAULT_ARCHITECTURE_OPTION_DICT.copy() option_dict.update(orig_option_dict) error_checking.assert_is_integer(option_dict[NUM_HEIGHTS_KEY]) error_checking.assert_is_greater(option_dict[NUM_HEIGHTS_KEY], 0) error_checking.assert_is_integer(option_dict[NUM_FLUX_COMPONENTS_KEY]) error_checking.assert_is_geq(option_dict[NUM_FLUX_COMPONENTS_KEY], 0) error_checking.assert_is_leq(option_dict[NUM_FLUX_COMPONENTS_KEY], 2) error_checking.assert_is_integer(option_dict[NUM_INPUTS_KEY]) error_checking.assert_is_geq(option_dict[NUM_INPUTS_KEY], 10) hidden_layer_neuron_nums = option_dict[HIDDEN_LAYER_NEURON_NUMS_KEY] error_checking.assert_is_integer_numpy_array(hidden_layer_neuron_nums) error_checking.assert_is_numpy_array(hidden_layer_neuron_nums, num_dimensions=1) error_checking.assert_is_geq_numpy_array(hidden_layer_neuron_nums, 1) num_hidden_layers = len(hidden_layer_neuron_nums) these_dimensions = numpy.array([num_hidden_layers], dtype=int) hidden_layer_dropout_rates = option_dict[HIDDEN_LAYER_DROPOUT_RATES_KEY] error_checking.assert_is_numpy_array(hidden_layer_dropout_rates, exact_dimensions=these_dimensions) error_checking.assert_is_leq_numpy_array(hidden_layer_dropout_rates, 1., allow_nan=True) error_checking.assert_is_geq(option_dict[L1_WEIGHT_KEY], 0.) error_checking.assert_is_geq(option_dict[L2_WEIGHT_KEY], 0.) error_checking.assert_is_boolean(option_dict[USE_BATCH_NORM_KEY]) return option_dict