Esempio n. 1
0
def evaluate_reconstruction(
    net: Network,
    dataset: DataSet,
    criterion_all: torch.nn.MSELoss,
) -> Dict[str, float]:
    """
    return cost reconstructing the world from world input, e.g. "reconstruction cost".
    """

    performance_name = f'cost-reconstruction_avg_{dataset.name}'

    res = {performance_name: 0}

    for event in dataset.get_events():
        x = event.get_x(net.params.x_type)
        y = event.get_y(net.params.y_type)

        o = net.forward(x)
        costs = criterion_all(o, y).detach().cpu().numpy()
        res[performance_name] += np.mean(costs)

    # divide sum by count
    res[performance_name] /= len(dataset)

    return res
Esempio n. 2
0
def evaluate_classification(
    net: Network,
    dataset: DataSet,
    criterion_all: torch.nn.BCEWithLogitsLoss,
) -> Dict[str, float]:
    """
    return cost and accuracy for each feature, averaged across all samples in provided dataset.
    """

    res = {}

    for event in dataset.get_events():

        x = event.get_x(net.params.x_type)
        y = event.get_y(net.params.y_type)

        o = net.forward(x)
        costs_by_feature = criterion_all(o, y).detach().cpu().numpy()
        o = o.detach().cpu().numpy()

        # collect cost for each feature
        for n, feature_label in enumerate(
                event.feature_vector.get_feature_labels()):
            performance_name = f'cost_{feature_label}_{dataset.name}'
            res.setdefault(performance_name, 0.0)
            res[performance_name] += costs_by_feature[n]

        # collect accuracy for each feature_type
        for feature_type, o_ids in event.feature_vector.feature_type2ids.items(
        ):
            performance_name = f'acc_{feature_type}_{dataset.name}'
            res.setdefault(performance_name, 0.0)
            o_restricted = o[o_ids]  # logits restricted to one feature_type
            y_restricted = event.get_y(
                net.params.y_type)[o_ids].detach().cpu().numpy()
            if np.argmax(o_restricted) == np.argmax(y_restricted):
                res[performance_name] += 1

    # divide performance sum by count
    num_events = len(dataset)
    for performance_name in res:
        res[performance_name] /= num_events

    # add average cost and accuracy
    res[f'cost_avg_{dataset.name}'] = np.mean([
        performance for name, performance in res.items()
        if name.startswith('cost')
    ])
    res[f'acc_avg_{dataset.name}'] = np.mean([
        performance for name, performance in res.items()
        if name.startswith('acc')
    ])

    if configs.Evaluation.means_only:
        res = {k: v for k, v in res.items() if 'avg' in k}

    return res
def main():
    project_name = 'PolyominoWorld'
    for param_path, label in gen_param_paths(
            project_name,
            param2requests,
            param2default,
            runs_path=None,
            ludwig_data_path=None,
    ):

        with (param_path / 'param2val.yaml').open('r') as f:
            param2val = yaml.load(f, Loader=yaml.FullLoader)
        params = Params.from_param2val(param2val)

        for rep_id, path_to_net in enumerate(param_path.rglob('model.pt')):

            pytorch_model = Network(params)
            pytorch_model.load_state_dict(
                torch.load(path_to_net, map_location=torch.device('cpu')))
            pytorch_model.eval()

            dummy_input = torch.zeros(
                1, calc_world_vector_size(
                    params.add_grayscale))  # dummy input of expected shape
            onnx_path_out = Path(
                __file__
            ).parent.parent / 'onnx_models' / f'{param2val["param_name"]}_{rep_id}.onnx'
            if not onnx_path_out.parent.exists():
                onnx_path_out.parent.mkdir()
            torch.onnx.export(pytorch_model,
                              dummy_input,
                              onnx_path_out,
                              verbose=True)

            tf_rep = prepare(onnx.load(onnx_path_out))
            tf_path_out = Path(
                __file__
            ).parent.parent / 'tensorflow_models' / f'{param2val["param_name"]}_{rep_id}.pb'
            if not tf_path_out.parent.exists():
                tf_path_out.parent.mkdir()
            tf_rep.export_graph(str(tf_path_out))
        dataset = DataSet(world.generate_sequences(
            leftout_colors=params.leftout_colors,
            leftout_shapes=params.leftout_shapes,
            leftout_variants=params.leftout_variants,
            leftout_positions=get_leftout_positions(params.leftout_half),
        ),
                          params,
                          name='re-generated')

        # multiple models may exist for the same hyper-parameter configuration
        for path_to_net in list(param_path.rglob('model.pt')):

            print(f'Loading net from {path_to_net}')

            # load net
            net = Network(params)
            state_dict = torch.load(path_to_net,
                                    map_location=torch.device('cpu'))
            net.load_state_dict(state_dict)
            net.requires_grad_(False)
            net.eval()

            header2column = {
                'shape': [],
                'size': [],
                'color': [],
            }
            vectors = []
            for event in dataset.get_events():

                x = event.get_x(net.params.x_type)
Esempio n. 5
0
        ),
                       params,
                       name='re-generated')

        if RGB_ID is not None:
            name_of_color_channel = {0: 'red', 1: 'green', 2: 'blue'}[RGB_ID]
        else:
            name_of_color_channel = None

        # multiple models may exist for the same hyper-parameter configuration - use first only
        for path_to_net in list(param_path.rglob('model.pt'))[:1]:

            print(f'Loading net from {path_to_net}')

            # load net
            net = Network(params)
            state_dict = torch.load(path_to_net,
                                    map_location=torch.device('cpu'))
            net.load_state_dict(state_dict)
            net.eval()
            h_x = net.h_xs[HIDDEN_LAYER_ID].weight.detach().numpy(
            )  # [num hidden, num world cells]

            # get set of detectors for one or all color channel
            detectors = []
            for h_id, hi in enumerate(h_x):
                # get weights to one color or all channel
                if RGB_ID is not None:
                    hi_reshaped = hi.reshape(
                        (3, configs.World.max_x,
                         configs.World.max_y))[RGB_ID, :, :]
            leftout_colors=params.leftout_colors,
            leftout_shapes=params.leftout_shapes,
            leftout_variants=params.leftout_variants,
            leftout_positions=get_leftout_positions(params.leftout_half),
        ),
                       params,
                       name='re-generated')

        # multiple models may exist for the same hyper-parameter configuration - iterate over each
        paths_to_net = list(sorted(param_path.rglob(f'model_*.pt')))
        if not paths_to_net:
            raise FileNotFoundError('Did not find any model files')

        rep_names = [p.name for p in param_path.glob('*') if p.is_dir()]

        net = Network(params)

        x_tick2ys = defaultdict(list)
        for path_to_net in paths_to_net:

            print(f'Loading net from {path_to_net}')

            # load weights into net
            state_dict = torch.load(path_to_net,
                                    map_location=torch.device('cpu'))
            net.load_state_dict(state_dict)
            net.requires_grad_(False)
            net.eval()

            accuracy = evaluate_linear_readout(data, net, FEATURE_TYPE,
                                               HIDDEN_LAYER_ID)
Esempio n. 7
0
                    reduction='none')  # for evaluation
        elif params.criterion == 'bce':
            criterion_avg = torch.nn.BCEWithLogitsLoss(
            )  # sigmoid function and then a binary cross entropy
            criterion_all = torch.nn.BCEWithLogitsLoss(reduction='none')
        else:
            raise AttributeError(f'Invalid arg to criterion')

        # multiple models may exist for the same hyper-parameter configuration - iterate over each
        for path_to_net in param_path.rglob('model.pt'):

            print()
            print(f'Evaluating model={path_to_net}')

            # load net
            net = Network(params)
            state_dict = torch.load(path_to_net,
                                    map_location=torch.device('cpu'))
            net.load_state_dict(state_dict)
            net.eval()

            cost_by_shape = np.zeros((len(configs.World.master_shapes), 1))
            num_by_shape = np.zeros((len(configs.World.master_shapes), 1))

            shape2id = {
                s: n
                for n, s in enumerate(configs.World.master_shapes)
            }

            # evaluate
            for event in dataset.get_events():
Esempio n. 8
0
def make_l_and_p(
    data: DataSet,
    net: Network,
    feature_type: str,
    h_layer_id: int,
    h_ids: Optional[List[int]] = None,
    state_is_random: bool = False,
    state_is_input: bool = False,
) -> Tuple[np.array, np.array]:
    """
    build data structures for evaluating linear readout
    """

    lis = []
    pis = []
    for event in data.get_events():

        # make l
        if feature_type == 'shape':
            li = [
                1 if event.shape == s else 0
                for s in configs.World.master_shapes
            ]
        elif feature_type == 'color':
            li = [
                1 if event.color == s else 0
                for s in configs.World.master_colors
            ]
        elif feature_type == 'size':
            li = [
                1 if event.size == s else 0 for s in configs.World.master_sizes
            ]
        else:
            raise AttributeError('Invalid feature type')
        lis.append(li)

        # make p
        x = event.world_vector.vector

        if state_is_input:
            state = x.numpy()
        else:
            if h_ids is None:
                state = [h for h in net.compute_hs(x)][h_layer_id].numpy()
            else:
                state = x
                for h_x in net.h_xs:
                    term1 = h_x.weight.numpy()[h_ids, :] @ state.numpy()
                    term2 = h_x.bias.numpy()[h_ids]
                    if net.params.hidden_activation_function == 'tanh':
                        state = np.tanh(term1 + term2)
                    else:
                        raise NotImplementedError

        if state_is_random:
            state = np.random.permutation(state)

        pi = state.T
        pis.append(pi)

    l = np.array(lis).T  # l has columns of localist target vectors
    p = np.array(pis).T  # p has columns of representation vectors

    return l, p