def _run(model_file_name, top_example_dir_name, storm_metafile_name,
         num_examples, output_file_name):
    """Creates dummy saliency map for each storm object.

    This is effectively the main method.

    :param model_file_name: See documentation at top of file.
    :param top_example_dir_name: Same.
    :param storm_metafile_name: Same.
    :param num_examples: Same.
    :param output_file_name: Same.
    """

    file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name)

    model_metafile_name = '{0:s}/model_metadata.p'.format(
        os.path.split(model_file_name)[0])

    print(
        'Reading model metadata from: "{0:s}"...'.format(model_metafile_name))
    model_metadata_dict = cnn.read_model_metadata(model_metafile_name)
    training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY]
    training_option_dict[trainval_io.REFLECTIVITY_MASK_KEY] = None

    print(
        'Reading storm metadata from: "{0:s}"...'.format(storm_metafile_name))
    full_storm_id_strings, storm_times_unix_sec = (
        tracking_io.read_ids_and_times(storm_metafile_name))

    print(SEPARATOR_STRING)

    if 0 < num_examples < len(full_storm_id_strings):
        full_storm_id_strings = full_storm_id_strings[:num_examples]
        storm_times_unix_sec = storm_times_unix_sec[:num_examples]

    example_dict = testing_io.read_predictors_specific_examples(
        top_example_dir_name=top_example_dir_name,
        desired_full_id_strings=full_storm_id_strings,
        desired_times_unix_sec=storm_times_unix_sec,
        option_dict=training_option_dict,
        layer_operation_dicts=model_metadata_dict[cnn.LAYER_OPERATIONS_KEY])
    print(SEPARATOR_STRING)

    predictor_matrices = example_dict[testing_io.INPUT_MATRICES_KEY]
    sounding_pressure_matrix_pa = (
        example_dict[testing_io.SOUNDING_PRESSURES_KEY])

    radar_matrix = predictor_matrices[0]
    num_examples = radar_matrix.shape[0]
    num_channels = radar_matrix.shape[-1]
    num_spatial_dim = len(radar_matrix.shape) - 2

    if num_spatial_dim == 2:
        kernel_matrix = numpy.expand_dims(EDGE_DETECTOR_MATRIX_2D, axis=-1)
    else:
        kernel_matrix = numpy.expand_dims(EDGE_DETECTOR_MATRIX_3D, axis=-1)

    kernel_matrix = numpy.repeat(kernel_matrix, num_channels, axis=-1)
    kernel_matrix = numpy.expand_dims(kernel_matrix, axis=-1)
    kernel_matrix = numpy.repeat(kernel_matrix, num_channels, axis=-1)

    radar_saliency_matrix = numpy.full(radar_matrix.shape, numpy.nan)

    for i in range(num_examples):
        if numpy.mod(i, 10) == 0:
            print((
                'Have created dummy saliency map for {0:d} of {1:d} examples...'
            ).format(i, num_examples))

        if num_spatial_dim == 2:
            this_saliency_matrix = standalone_utils.do_2d_convolution(
                feature_matrix=radar_matrix[i, ...],
                kernel_matrix=kernel_matrix,
                pad_edges=True,
                stride_length_px=1)
        else:
            this_saliency_matrix = standalone_utils.do_3d_convolution(
                feature_matrix=radar_matrix[i, ...],
                kernel_matrix=kernel_matrix,
                pad_edges=True,
                stride_length_px=1)

        radar_saliency_matrix[i, ...] = this_saliency_matrix[0, ...]

    print('Have created dummy saliency map for all {0:d} examples!'.format(
        num_examples))
    print(SEPARATOR_STRING)

    saliency_matrices = [
        radar_saliency_matrix if k == 0 else predictor_matrices[k]
        for k in range(len(predictor_matrices))
    ]
    saliency_matrices = trainval_io.separate_shear_and_reflectivity(
        list_of_input_matrices=saliency_matrices,
        training_option_dict=training_option_dict)
    denorm_predictor_matrices = trainval_io.separate_shear_and_reflectivity(
        list_of_input_matrices=copy.deepcopy(predictor_matrices),
        training_option_dict=training_option_dict)

    print('Denormalizing model inputs...')
    denorm_predictor_matrices = model_interpretation.denormalize_data(
        list_of_input_matrices=denorm_predictor_matrices,
        model_metadata_dict=model_metadata_dict)

    print('Writing saliency maps to file: "{0:s}"...'.format(output_file_name))

    saliency_metadata_dict = saliency_maps.check_metadata(
        component_type_string=model_interpretation.CLASS_COMPONENT_TYPE_STRING,
        target_class=1)

    saliency_maps.write_standard_file(
        pickle_file_name=output_file_name,
        denorm_predictor_matrices=denorm_predictor_matrices,
        saliency_matrices=saliency_matrices,
        full_storm_id_strings=full_storm_id_strings,
        storm_times_unix_sec=storm_times_unix_sec,
        model_file_name=model_file_name,
        metadata_dict=saliency_metadata_dict,
        sounding_pressure_matrix_pa=sounding_pressure_matrix_pa)
Exemple #2
0
def _run(model_file_name, component_type_string, target_class, layer_name,
         ideal_activation, neuron_indices, channel_index, top_example_dir_name,
         storm_metafile_name, num_examples, randomize_weights,
         cascading_random, output_file_name):
    """Computes saliency map for each storm object and each model component.

    This is effectively the main method.

    :param model_file_name: See documentation at top of file.
    :param component_type_string: Same.
    :param target_class: Same.
    :param layer_name: Same.
    :param ideal_activation: Same.
    :param neuron_indices: Same.
    :param channel_index: Same.
    :param top_example_dir_name: Same.
    :param storm_metafile_name: Same.
    :param num_examples: Same.
    :param randomize_weights: Same.
    :param cascading_random: Same.
    :param output_file_name: Same.
    """

    # Check input args.
    file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name)
    model_interpretation.check_component_type(component_type_string)

    # Read model and metadata.
    print('Reading model from: "{0:s}"...'.format(model_file_name))
    model_object = cnn.read_model(model_file_name)

    model_metafile_name = '{0:s}/model_metadata.p'.format(
        os.path.split(model_file_name)[0])

    print(
        'Reading model metadata from: "{0:s}"...'.format(model_metafile_name))
    model_metadata_dict = cnn.read_model_metadata(model_metafile_name)
    training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY]
    training_option_dict[trainval_io.REFLECTIVITY_MASK_KEY] = None

    output_dir_name, pathless_output_file_name = os.path.split(
        output_file_name)
    extensionless_output_file_name, output_file_extension = os.path.splitext(
        pathless_output_file_name)

    if randomize_weights:
        conv_dense_layer_names = _find_conv_and_dense_layers(model_object)
        conv_dense_layer_names.reverse()
        num_sets = len(conv_dense_layer_names)
    else:
        conv_dense_layer_names = []
        num_sets = 1

    print(
        'Reading storm metadata from: "{0:s}"...'.format(storm_metafile_name))
    full_storm_id_strings, storm_times_unix_sec = (
        tracking_io.read_ids_and_times(storm_metafile_name))

    print(SEPARATOR_STRING)

    if 0 < num_examples < len(full_storm_id_strings):
        full_storm_id_strings = full_storm_id_strings[:num_examples]
        storm_times_unix_sec = storm_times_unix_sec[:num_examples]

    example_dict = testing_io.read_predictors_specific_examples(
        top_example_dir_name=top_example_dir_name,
        desired_full_id_strings=full_storm_id_strings,
        desired_times_unix_sec=storm_times_unix_sec,
        option_dict=training_option_dict,
        layer_operation_dicts=model_metadata_dict[cnn.LAYER_OPERATIONS_KEY])
    print(SEPARATOR_STRING)

    predictor_matrices = example_dict[testing_io.INPUT_MATRICES_KEY]
    sounding_pressure_matrix_pa = example_dict[
        testing_io.SOUNDING_PRESSURES_KEY]

    denorm_predictor_matrices = trainval_io.separate_shear_and_reflectivity(
        list_of_input_matrices=copy.deepcopy(predictor_matrices),
        training_option_dict=training_option_dict)

    print('Denormalizing model inputs...')
    denorm_predictor_matrices = model_interpretation.denormalize_data(
        list_of_input_matrices=denorm_predictor_matrices,
        model_metadata_dict=model_metadata_dict)
    print(SEPARATOR_STRING)

    for k in range(num_sets):
        if randomize_weights:
            if cascading_random:
                _reset_weights_in_layer(model_object=model_object,
                                        layer_name=conv_dense_layer_names[k])

                this_model_object = model_object

                this_output_file_name = (
                    '{0:s}/{1:s}_cascading-random_{2:s}{3:s}').format(
                        output_dir_name, extensionless_output_file_name,
                        conv_dense_layer_names[k].replace('_', '-'),
                        output_file_extension)
            else:
                this_model_object = keras.models.Model.from_config(
                    model_object.get_config())
                this_model_object.set_weights(model_object.get_weights())

                _reset_weights_in_layer(model_object=this_model_object,
                                        layer_name=conv_dense_layer_names[k])

                this_output_file_name = '{0:s}/{1:s}_random_{2:s}{3:s}'.format(
                    output_dir_name, extensionless_output_file_name,
                    conv_dense_layer_names[k].replace('_', '-'),
                    output_file_extension)
        else:
            this_model_object = model_object
            this_output_file_name = output_file_name

        # print(K.eval(this_model_object.get_layer(name='dense_3').weights[0]))

        if component_type_string == CLASS_COMPONENT_TYPE_STRING:
            print('Computing saliency maps for target class {0:d}...'.format(
                target_class))

            saliency_matrices = (
                saliency_maps.get_saliency_maps_for_class_activation(
                    model_object=this_model_object,
                    target_class=target_class,
                    list_of_input_matrices=predictor_matrices))

        elif component_type_string == NEURON_COMPONENT_TYPE_STRING:
            print(
                ('Computing saliency maps for neuron {0:s} in layer "{1:s}"...'
                 ).format(str(neuron_indices), layer_name))

            saliency_matrices = (
                saliency_maps.get_saliency_maps_for_neuron_activation(
                    model_object=this_model_object,
                    layer_name=layer_name,
                    neuron_indices=neuron_indices,
                    list_of_input_matrices=predictor_matrices,
                    ideal_activation=ideal_activation))

        else:
            print((
                'Computing saliency maps for channel {0:d} in layer "{1:s}"...'
            ).format(channel_index, layer_name))

            saliency_matrices = (
                saliency_maps.get_saliency_maps_for_channel_activation(
                    model_object=this_model_object,
                    layer_name=layer_name,
                    channel_index=channel_index,
                    list_of_input_matrices=predictor_matrices,
                    stat_function_for_neuron_activations=K.max,
                    ideal_activation=ideal_activation))

        saliency_matrices = trainval_io.separate_shear_and_reflectivity(
            list_of_input_matrices=saliency_matrices,
            training_option_dict=training_option_dict)

        print('Writing saliency maps to file: "{0:s}"...'.format(
            this_output_file_name))

        saliency_metadata_dict = saliency_maps.check_metadata(
            component_type_string=component_type_string,
            target_class=target_class,
            layer_name=layer_name,
            ideal_activation=ideal_activation,
            neuron_indices=neuron_indices,
            channel_index=channel_index)

        saliency_maps.write_standard_file(
            pickle_file_name=this_output_file_name,
            denorm_predictor_matrices=denorm_predictor_matrices,
            saliency_matrices=saliency_matrices,
            full_storm_id_strings=full_storm_id_strings,
            storm_times_unix_sec=storm_times_unix_sec,
            model_file_name=model_file_name,
            metadata_dict=saliency_metadata_dict,
            sounding_pressure_matrix_pa=sounding_pressure_matrix_pa)
def check_metadata(component_type_string,
                   num_iterations,
                   learning_rate,
                   target_class=None,
                   layer_name=None,
                   ideal_activation=None,
                   neuron_indices=None,
                   channel_index=None,
                   l2_weight=None,
                   radar_constraint_weight=None,
                   minmax_constraint_weight=None):
    """Error-checks metadata.

    :param component_type_string: See doc for `saliency_maps.check_metadata`.
    :param num_iterations: Number of iterations.
    :param learning_rate: Learning rate.
    :param target_class: See doc for `saliency_maps.check_metadata`.
    :param layer_name: Same.
    :param ideal_activation: Same.
    :param neuron_indices: Same.
    :param channel_index: Same.
    :param l2_weight: Weight for L_2 regularization.
    :param radar_constraint_weight: Weight used to multiply part of loss
        function with radar constraints (see doc for
        `_radar_constraints_to_loss_fn`).
    :param minmax_constraint_weight: Weight used to multiply part of loss
        function with min-max constraints (see doc for
        `_minmax_constraints_to_loss_fn`).

    :return: metadata_dict: Dictionary with the following keys.
    metadata_dict['component_type_string']: See input doc.
    metadata_dict['num_iterations']: Same.
    metadata_dict['learning_rate']: Same.
    metadata_dict['target_class']: Same.
    metadata_dict['layer_name']: Same.
    metadata_dict['ideal_activation']: Same.
    metadata_dict['neuron_indices']: Same.
    metadata_dict['channel_index']: Same.
    metadata_dict['l2_weight']: Same.
    metadata_dict['radar_constraint_weight']: Same.
    metadata_dict['minmax_constraint_weight']: Same.
    """

    metadata_dict = saliency_maps.check_metadata(
        component_type_string=component_type_string,
        target_class=target_class,
        layer_name=layer_name,
        ideal_activation=ideal_activation,
        neuron_indices=neuron_indices,
        channel_index=channel_index)

    error_checking.assert_is_integer(num_iterations)
    error_checking.assert_is_greater(num_iterations, 0)
    error_checking.assert_is_greater(learning_rate, 0.)
    error_checking.assert_is_less_than(learning_rate, 1.)

    if l2_weight is not None:
        error_checking.assert_is_greater(l2_weight, 0.)
    if radar_constraint_weight is not None:
        error_checking.assert_is_greater(radar_constraint_weight, 0.)
    if minmax_constraint_weight is not None:
        error_checking.assert_is_greater(minmax_constraint_weight, 0.)

    metadata_dict.update({
        NUM_ITERATIONS_KEY: num_iterations,
        LEARNING_RATE_KEY: learning_rate,
        L2_WEIGHT_KEY: l2_weight,
        RADAR_CONSTRAINT_WEIGHT_KEY: radar_constraint_weight,
        MINMAX_CONSTRAINT_WEIGHT_KEY: minmax_constraint_weight
    })

    return metadata_dict
Exemple #4
0
def write_file(pickle_file_name,
               normalized_predictor_matrix,
               saliency_matrix,
               model_file_name,
               component_type_string,
               target_class=None,
               layer_name=None,
               ideal_activation=None,
               neuron_indices=None,
               channel_index=None):
    """Writes saliency maps to Pickle file.

    E = number of examples
    M = number of rows in each grid
    N = number of columns in each grid
    C = number of channels (predictor variables)

    :param pickle_file_name: Path to output file.
    :param normalized_predictor_matrix: E-by-M-by-N-by-C numpy array of
        normalized predictor values (input images).
    :param saliency_matrix: E-by-M-by-N-by-C numpy array of saliency values.
    :param model_file_name: Path to file containing trained CNN on which
        saliency maps are based.  Should be readable by
        `traditional_cnn.read_keras_model`.
    :param component_type_string: See doc for
        `gewittergefahr.deep_learning.saliency_maps.check_metadata`.
    :param target_class: Same.
    :param layer_name: Same.
    :param ideal_activation: Same.
    :param neuron_indices: Same.
    :param channel_index: Same.
    """

    gg_saliency.check_metadata(component_type_string=component_type_string,
                               target_class=target_class,
                               layer_name=layer_name,
                               ideal_activation=ideal_activation,
                               neuron_indices=neuron_indices,
                               channel_index=channel_index)

    error_checking.assert_is_numpy_array_without_nan(
        normalized_predictor_matrix)
    error_checking.assert_is_numpy_array(normalized_predictor_matrix,
                                         num_dimensions=4)

    error_checking.assert_is_numpy_array_without_nan(saliency_matrix)
    error_checking.assert_is_numpy_array(
        saliency_matrix,
        exact_dimensions=numpy.array(normalized_predictor_matrix.shape))

    error_checking.assert_is_string(model_file_name)

    metadata_dict = {
        MODEL_FILE_NAME_KEY: model_file_name,
        COMPONENT_TYPE_KEY: component_type_string,
        TARGET_CLASS_KEY: target_class,
        LAYER_NAME_KEY: layer_name,
        IDEAL_ACTIVATION_KEY: ideal_activation,
        NEURON_INDICES_KEY: neuron_indices,
        CHANNEL_INDEX_KEY: channel_index
    }

    file_system_utils.mkdir_recursive_if_necessary(file_name=pickle_file_name)
    pickle_file_handle = open(pickle_file_name, 'wb')
    pickle.dump(normalized_predictor_matrix, pickle_file_handle)
    pickle.dump(saliency_matrix, pickle_file_handle)
    pickle.dump(metadata_dict, pickle_file_handle)
    pickle_file_handle.close()
def _run(model_file_name, component_type_string, target_class, layer_name,
         ideal_activation, neuron_indices, channel_index, top_example_dir_name,
         storm_metafile_name, num_examples, output_file_name):
    """Computes saliency map for each storm object and each model component.

    This is effectively the main method.

    :param model_file_name: See documentation at top of file.
    :param component_type_string: Same.
    :param target_class: Same.
    :param layer_name: Same.
    :param ideal_activation: Same.
    :param neuron_indices: Same.
    :param channel_index: Same.
    :param top_example_dir_name: Same.
    :param storm_metafile_name: Same.
    :param num_examples: Same.
    :param output_file_name: Same.
    """

    # Check input args.
    file_system_utils.mkdir_recursive_if_necessary(file_name=output_file_name)
    model_interpretation.check_component_type(component_type_string)

    # Read model and metadata.
    print 'Reading model from: "{0:s}"...'.format(model_file_name)
    model_object = cnn.read_model(model_file_name)
    model_metafile_name = '{0:s}/model_metadata.p'.format(
        os.path.split(model_file_name)[0])

    print 'Reading model metadata from: "{0:s}"...'.format(model_metafile_name)
    model_metadata_dict = cnn.read_model_metadata(model_metafile_name)
    training_option_dict = model_metadata_dict[cnn.TRAINING_OPTION_DICT_KEY]
    training_option_dict[trainval_io.REFLECTIVITY_MASK_KEY] = None

    print 'Reading storm metadata from: "{0:s}"...'.format(storm_metafile_name)
    storm_ids, storm_times_unix_sec = tracking_io.read_ids_and_times(
        storm_metafile_name)
    print SEPARATOR_STRING

    if 0 < num_examples < len(storm_ids):
        storm_ids = storm_ids[:num_examples]
        storm_times_unix_sec = storm_times_unix_sec[:num_examples]

    list_of_input_matrices, sounding_pressure_matrix_pascals = (
        testing_io.read_specific_examples(
            top_example_dir_name=top_example_dir_name,
            desired_storm_ids=storm_ids,
            desired_times_unix_sec=storm_times_unix_sec,
            option_dict=training_option_dict,
            list_of_layer_operation_dicts=model_metadata_dict[
                cnn.LAYER_OPERATIONS_KEY]))
    print SEPARATOR_STRING

    if component_type_string == CLASS_COMPONENT_TYPE_STRING:
        print 'Computing saliency maps for target class {0:d}...'.format(
            target_class)

        list_of_saliency_matrices = (
            saliency_maps.get_saliency_maps_for_class_activation(
                model_object=model_object,
                target_class=target_class,
                list_of_input_matrices=list_of_input_matrices))

    elif component_type_string == NEURON_COMPONENT_TYPE_STRING:
        print('Computing saliency maps for neuron {0:s} in layer "{1:s}"...'
              ).format(str(neuron_indices), layer_name)

        list_of_saliency_matrices = (
            saliency_maps.get_saliency_maps_for_neuron_activation(
                model_object=model_object,
                layer_name=layer_name,
                neuron_indices=neuron_indices,
                list_of_input_matrices=list_of_input_matrices,
                ideal_activation=ideal_activation))

    else:
        print('Computing saliency maps for channel {0:d} in layer "{1:s}"...'
              ).format(channel_index, layer_name)

        list_of_saliency_matrices = (
            saliency_maps.get_saliency_maps_for_channel_activation(
                model_object=model_object,
                layer_name=layer_name,
                channel_index=channel_index,
                list_of_input_matrices=list_of_input_matrices,
                stat_function_for_neuron_activations=K.max,
                ideal_activation=ideal_activation))

    print 'Denormalizing model inputs...'
    list_of_input_matrices = model_interpretation.denormalize_data(
        list_of_input_matrices=list_of_input_matrices,
        model_metadata_dict=model_metadata_dict)

    print 'Writing saliency maps to file: "{0:s}"...'.format(output_file_name)

    saliency_metadata_dict = saliency_maps.check_metadata(
        component_type_string=component_type_string,
        target_class=target_class,
        layer_name=layer_name,
        ideal_activation=ideal_activation,
        neuron_indices=neuron_indices,
        channel_index=channel_index)

    saliency_maps.write_standard_file(
        pickle_file_name=output_file_name,
        list_of_input_matrices=list_of_input_matrices,
        list_of_saliency_matrices=list_of_saliency_matrices,
        storm_ids=storm_ids,
        storm_times_unix_sec=storm_times_unix_sec,
        model_file_name=model_file_name,
        saliency_metadata_dict=saliency_metadata_dict,
        sounding_pressure_matrix_pascals=sounding_pressure_matrix_pascals)