Beispiel #1
0
def main():
    args = parseargs()
    resdir = 'results/%s-%s-%s' % (args.model, args.dataset, args.seg)
    if args.layer is not None:
        resdir += '-' + args.layer
    if args.quantile != 0.005:
        resdir += ('-%g' % (args.quantile * 1000))
    if args.thumbsize != 100:
        resdir += ('-t%d' % (args.thumbsize))
    resfile = pidfile.exclusive_dirfn(resdir)

    model = load_model(args)
    layername = instrumented_layername(args)
    model.retain_layer(layername)
    dataset = load_dataset(args, model=model.model)
    upfn = make_upfn(args, dataset, model, layername)
    sample_size = len(dataset)
    is_generator = (args.model == 'progan')
    percent_level = 1.0 - args.quantile
    iou_threshold = args.miniou
    image_row_width = 5
    torch.set_grad_enabled(False)

    # Tally rq.np (representation quantile, unconditional).
    pbar.descnext('rq')
    def compute_samples(batch, *args):
        data_batch = batch.cuda()
        _ = model(data_batch)
        acts = model.retained_layer(layername)
        hacts = upfn(acts)
        return hacts.permute(0, 2, 3, 1).contiguous().view(-1, acts.shape[1])
    rq = tally.tally_quantile(compute_samples, dataset,
                              sample_size=sample_size,
                              r=8192,
                              num_workers=100,
                              pin_memory=True,
                              cachefile=resfile('rq.npz'))

    # Create visualizations - first we need to know the topk
    pbar.descnext('topk')
    def compute_image_max(batch, *args):
        data_batch = batch.cuda()
        _ = model(data_batch)
        acts = model.retained_layer(layername)
        acts = acts.view(acts.shape[0], acts.shape[1], -1)
        acts = acts.max(2)[0]
        return acts
    topk = tally.tally_topk(compute_image_max, dataset, sample_size=sample_size,
            batch_size=50, num_workers=30, pin_memory=True,
            cachefile=resfile('topk.npz'))

    # Visualize top-activating patches of top-activatin images.
    pbar.descnext('unit_images')
    image_size, image_source = None, None
    if is_generator:
        image_size = model(dataset[0][0].cuda()[None,...]).shape[2:]
    else:
        image_source = dataset
    iv = imgviz.ImageVisualizer((args.thumbsize, args.thumbsize),
        image_size=image_size,
        source=dataset,
        quantiles=rq,
        level=rq.quantiles(percent_level))
    def compute_acts(data_batch, *ignored_class):
        data_batch = data_batch.cuda()
        out_batch = model(data_batch)
        acts_batch = model.retained_layer(layername)
        if is_generator:
            return (acts_batch, out_batch)
        else:
            return (acts_batch, data_batch)
    unit_images = iv.masked_images_for_topk(
            compute_acts, dataset, topk,
            k=image_row_width, num_workers=30, pin_memory=True,
            cachefile=resfile('top%dimages.npz' % image_row_width))
    pbar.descnext('saving images')
    imgsave.save_image_set(unit_images, resfile('image/unit%d.jpg'),
            sourcefile=resfile('top%dimages.npz' % image_row_width))

    # Compute IoU agreement between segmentation labels and every unit
    # Grab the 99th percentile, and tally conditional means at that level.
    level_at_99 = rq.quantiles(percent_level).cuda()[None,:,None,None]

    segmodel, seglabels, segcatlabels = setting.load_segmenter(args.seg)
    renorm = renormalize.renormalizer(dataset, target='zc')
    def compute_conditional_indicator(batch, *args):
        data_batch = batch.cuda()
        out_batch = model(data_batch)
        image_batch = out_batch if is_generator else renorm(data_batch)
        seg = segmodel.segment_batch(image_batch, downsample=4)
        acts = model.retained_layer(layername)
        hacts = upfn(acts)
        iacts = (hacts > level_at_99).float() # indicator
        return tally.conditional_samples(iacts, seg)

    pbar.descnext('condi99')
    condi99 = tally.tally_conditional_mean(compute_conditional_indicator,
            dataset, sample_size=sample_size,
            num_workers=3, pin_memory=True,
            cachefile=resfile('condi99.npz'))

    # Now summarize the iou stats and graph the units
    iou_99 = tally.iou_from_conditional_indicator_mean(condi99)
    unit_label_99 = [
            (concept.item(), seglabels[concept],
                segcatlabels[concept], bestiou.item())
            for (bestiou, concept) in zip(*iou_99.max(0))]
    labelcat_list = [labelcat
            for concept, label, labelcat, iou in unit_label_99
            if iou > iou_threshold]
    save_conceptcat_graph(resfile('concepts_99.svg'), labelcat_list)
    dump_json_file(resfile('report.json'), dict(
            header=dict(
                name='%s %s %s' % (args.model, args.dataset, args.seg),
                image='concepts_99.svg'),
            units=[
                dict(image='image/unit%d.jpg' % u,
                    unit=u, iou=iou, label=label, cat=labelcat[1])
                for u, (concept, label, labelcat, iou)
                in enumerate(unit_label_99)])
            )
    copy_static_file('report.html', resfile('+report.html'))
    resfile.done();
Beispiel #2
0
upfn = upsample.upsampler(
    (56, 56),                     # The target output shape
    (7, 7),
    source=dataset,
)

renorm = renormalize.renormalizer(dataset, mode='zc')

def compute_samples(batch, *args):
    image_batch = batch.cuda()
    _ = model(image_batch)
    acts = model.retained_layer(layername)
    hacts = upfn(acts)
    return hacts.permute(0, 2, 3, 1).contiguous().view(-1, acts.shape[1])

pbar.descnext('rq')
rq = tally.tally_quantile(compute_samples, dataset, sample_size=sample_size,
        r=8192, cachefile=resfile('rq.npz'))

if False:
    def compute_conditional_samples(batch, *args):
        image_batch = batch.cuda()
        _ = model(image_batch)
        acts = model.retained_layer(layername)
        seg = segmodel.segment_batch(renorm(image_batch), downsample=4)
        hacts = upfn(acts)
        return tally.conditional_samples(hacts, seg)

    pbar.descnext('condq')
    condq = tally.tally_conditional_quantile(compute_conditional_samples,
            dataset, sample_size=sample_size, cachefile=resfile('condq.npz'))
Beispiel #3
0
def main():
    CHOSEN_UNITS_DIR = os.path.join("/", "home", "dwijaya", "dissect",
                                    "experiment", "ucf101", "datas",
                                    "chosen_units.csv")
    report_dir = os.path.join(
        "/", "home", "dwijaya", "dissect", "experiment",
        "results/vgg16-ucf101-netpqc-conv5_3-10/report.json")
    result_test = load_json(report_dir)['units']
    # getUnitLabel(result_test)
    # groupUnitByLabel(result_test)
    chosen_units_df = pd.read_csv(CHOSEN_UNITS_DIR)
    args = parseargs()
    model = setting.load_ucf101_classifier(args.model)
    model = nethook.InstrumentedModel(model).cuda().eval()
    layername = args.layer
    model.retain_layer(layername)
    dataset = setting.load_ucf101_dataset(crop_size=224,
                                          in_dataloader=False,
                                          is_all_frames=True)
    train_dataset = setting.load_ucf101_dataset(crop_size=224,
                                                in_dataloader=False,
                                                is_all_frames=True,
                                                is_train=True)

    num_units = len(chosen_units_df)
    classlabels = dataset.classes

    def zeroingTopK(k=14):
        directory = os.path.join(os.getcwd(), 'results/shared',
                                 'pra-vgg16-ucf101/per_class')
        save_dir = os.path.join(directory, 'topK_target.csv')
        if (os.path.exists(save_dir)):
            df = pd.read_csv(save_dir)
            print(df)
        else:
            # topK_all_class = []
            # for idx, cl in enumerate(classlabels):
            #     cachefile = sharedfile('pra-%s-%s/%s/%s.npz' % (args.model, args.dataset, args.experiments, cl))
            #     df = pd.read_csv(save_dir)
            #     df2 = pd.read_csv(os.path.join(directory, '%s.csv' % cl))
            #     to_save = []
            #     for idx, (unit, concept) in enumerate(zip(df2['Unit'].loc[14:], df2['Concept'].loc[14:])):
            #         to_save.append((unit, concept))
            #     topK_all_class.append(to_save)
            # df = df.rename(columns={'Unnamed: 0': 'Class', '0': 'Acc_dropped'})
            # df['Unit/Concept'] = topK_all_class
            # df['Class'] = classlabels
            # df.to_csv(save_dir)
            topK_all_class = []
            acc_per_class_list, target_acc_class = [], []
            for idx, cl in enumerate(classlabels):
                cachefile = sharedfile(
                    'pra-%s-%s/%s/%s.npz' %
                    (args.model, args.dataset, args.experiments, cl))
                df = pd.read_csv(os.path.join(directory, '%s.csv' % cl))
                units_to_remove = df['Unit'].loc[:k - 1].to_list()
                accuracy, acc_per_class = my_test_perclass(
                    model,
                    dataset,
                    layername=layername,
                    ablated_units=units_to_remove,
                    cachefile=cachefile)
                target_acc_class.append(acc_per_class[idx])
                acc_per_class_list.append(acc_per_class)
                to_save = []
                for idx, (unit, concept) in enumerate(
                        zip(df['Unit'].loc[:k - 1],
                            df['Concept'].loc[:k - 1])):
                    to_save.append((unit, concept))
                topK_all_class.append(to_save)

            result_df = pd.DataFrame(target_acc_class, columns=['Acc_dropped'])
            # result_df = result_df.rename(columns={'Unnamed: 0': 'Class', '0': 'Acc_dropped'})
            result_df['Unit/Concept'] = topK_all_class
            result_df['Class'] = classlabels

            result_df.to_csv(os.path.join(directory, "topK_target.csv"))
            pd.DataFrame(acc_per_class_list).to_csv(
                os.path.join('topK_per_class.csv'))

    def zeroingBottomK(k=498):  #previously is 498, so it is wrong.
        directory = os.path.join(os.getcwd(), 'results/shared',
                                 'pra-vgg16-ucf101/per_class')
        topK_all_class = []
        acc_per_class_list, target_acc_class = [], []
        for idx, cl in enumerate(classlabels):
            cachefile = sharedfile(
                'pra-%s-%s/%s/%s.npz' %
                (args.model, args.dataset, args.experiments, cl))
            df = pd.read_csv(os.path.join(directory, '%s.csv' % cl))
            units_to_remove = df['Unit'].loc[k:].to_list()
            accuracy, acc_per_class = my_test_perclass(
                model,
                dataset,
                layername=layername,
                ablated_units=units_to_remove,
                cachefile=cachefile)
            target_acc_class.append(acc_per_class[idx])
            acc_per_class_list.append(acc_per_class)
            to_save = []
            for idx, (unit, concept) in enumerate(
                    zip(df['Unit'].loc[k:], df['Concept'].loc[k:])):
                to_save.append((unit, concept))
            topK_all_class.append(to_save)

        result_df = pd.DataFrame(target_acc_class, columns=['Acc_dropped'])
        result_df['Unit/Concept'] = topK_all_class
        result_df['Class'] = classlabels

        result_df.to_csv(os.path.join(directory, "bottomK_target_new.csv"))
        # pd.DataFrame(target_acc_class).to_csv(os.path.join(directory, "bottomK_target_new.csv"))
        pd.DataFrame(acc_per_class_list).to_csv(
            os.path.join(directory, 'bottomK_per_class_new.csv'))

    def zeroKWithConcepts():
        directory = os.path.join(os.getcwd(), 'results/shared',
                                 'pra-vgg16-ucf101/per_class')
        save_dir = os.path.join(directory, 'bottomK_target.csv')
        topK_all_class = []
        for idx, cl in enumerate(classlabels):
            cachefile = sharedfile(
                'pra-%s-%s/%s/%s.npz' %
                (args.model, args.dataset, args.experiments, cl))
            df = pd.read_csv(save_dir)
            df2 = pd.read_csv(os.path.join(directory, '%s.csv' % cl))
            to_save = []
            for idx, (unit, concept) in enumerate(
                    zip(df2['Unit'].loc[14:], df2['Concept'].loc[14:])):
                to_save.append((unit, concept))
            topK_all_class.append(to_save)
        df = df.rename(columns={'Unnamed: 0': 'Class', '0': 'Acc_dropped'})
        df['Unit/Concept'] = topK_all_class
        df['Class'] = classlabels
        df.to_csv(save_dir)
        print("HELLO")
        # df = df.rename(columns={"Unnamed: 0": "Concept"})
        # df.to_csv(os.path.join(directory, '%s.csv' % cl))

    # coba()

    # sortAcc()
    #Getting the baseline accuracy.
    baseline_acc_dir = os.path.join(
        os.getcwd(), 'results/shared',
        'pra-%s-%s/baseline_acc.npz' % (args.model, args.dataset))
    if (os.path.exists(baseline_acc_dir)):
        baseline_ = np.load(baseline_acc_dir)
        baseline_acc, baseline_acc_per_class = baseline_['acc'], baseline_[
            'acc_per_class']
    else:
        pbar.descnext('baseline_pra')
        baseline_acc, baseline_acc_per_class = my_test_perclass(
            model,
            dataset,
            ablated_units=None,
            cachefile=sharedfile('pra-%s-%s/%s_acc.npz' %
                                 (args.model, args.dataset, args.experiments)))
        cachefile = sharedfile('pra-%s-%s/%s_acc.npz' %
                               (args.model, args.dataset, args.experiments))
        np.savez(cachefile,
                 acc=baseline_acc,
                 acc_per_class=baseline_acc_per_class)
        baseline_acc_per_class = np.expand_dims(baseline_acc_per_class, axis=0)
        pd.DataFrame(baseline_acc_per_class,
                     index=['Baseline'],
                     columns=classlabels).to_csv("base_line.csv")

    #Now erase each unit, one at a time, and retest accuracy.
    cached_results_dir = os.path.join(
        os.getcwd(), 'results/shared',
        'pra-%s-%s/%s_acc.npz' % (args.model, args.dataset, args.experiments))

    cachefile = sharedfile('pra-%s-%s/%s_acc.npz' %
                           (args.model, args.dataset, args.experiments))
    all_units = []

    if (args.experiments == "topK"):
        zeroingTopK()
    elif (args.experiments == "bottomK"):
        zeroingBottomK()

    if (args.extract_data):
        baseline_ = {
            'acc': baseline_acc,
            'acc_per_class': baseline_acc_per_class
        }
        # npzToCSV(args.experiments, columns=classlabels, baseline_=baseline_, export_csv=False)
        # sortUnitByClass(baseline_, args.experiments, classlabels)
    else:
        if (args.experiments == 'exp1'):
            df = pd.read_csv(os.path.join(datas_dir, 'Sensible units.csv'))
            if (os.path.exists(cached_results_dir)):
                # IF THE RESULT ALREADY EXISTS
                acc_per_class_list = np.load(
                    cached_results_dir)['acc_per_class']
                acc_list = np.load(cached_results_dir)['acc']
            else:
                #Remove unit one at a time.
                units_to_remove, concepts = df['Unit'], df['Concepts']
                for idx, (units,
                          concept) in enumerate(zip(units_to_remove,
                                                    concepts)):
                    units = units.split(',')
                    units = [(int(u), concept) for u in units]
                    all_units.extend(units)
                acc_per_class_list = np.zeros(
                    [len(all_units), len(classlabels)])
                acc_list = np.zeros(len(classlabels))
                for idx, (unit, c) in enumerate(all_units):
                    accuracy, acc_per_class = my_test_perclass(
                        model,
                        dataset,
                        layername=layername,
                        ablated_units=[unit],
                        cachefile=cachefile)
                    acc_list[idx] = accuracy
                    acc_per_class_list[idx] = acc_per_class

                np.savez(cachefile,
                         acc=acc_list,
                         acc_per_class=acc_per_class_list)

        elif (args.experiments == 'exp2'):
            df = pd.read_csv(os.path.join(datas_dir, 'Sensible units.csv'))
            if (os.path.exists(cached_results_dir)):
                #IF THE RESULT ALREADY EXISTS
                acc_per_class_list = np.load(
                    cached_results_dir)['acc_per_class']
                acc_list = np.load(cached_results_dir)['acc']
            else:
                #Remove multiple units at a time
                units_to_remove, concepts = df['Unit'], df['Concepts']
                acc_per_class_list = np.zeros([num_units, len(classlabels)])
                acc_list = np.zeros(len(classlabels))
                for idx, (units,
                          concept) in enumerate(zip(units_to_remove,
                                                    concepts)):
                    units = units.split(',')
                    units = [int(u) for u in units]
                    accuracy, acc_per_class = my_test_perclass(
                        model,
                        dataset,
                        layername=layername,
                        ablated_units=units,
                        cachefile=cachefile)
                    acc_list[idx] = accuracy
                    acc_per_class_list[idx] = acc_per_class  # in a list

                np.savez(cachefile,
                         acc=acc_list,
                         acc_per_class=acc_per_class_list)
        elif (args.experiments == 'exp3'):
            df = pd.read_csv(os.path.join(datas_dir, 'units_label.csv'))
            if (os.path.exists(cached_results_dir)):
                acc_per_class_list = np.load(
                    cached_results_dir)['acc_per_class']
                acc_list = np.load(cached_results_dir)['acc']
            else:
                # Remove multiple units at a time
                concepts = df['Concepts']
                # acc_per_class_list = np.zeros([len(concepts), len(classlabels)])
                # acc_list = np.zeros(len(concepts))

                # acc_per_class = np.zeros(len(classlabels))
                # acc_per_class = np.zeros(len(classlabels))

                process_complete = tqdm.tqdm(total=len(concepts),
                                             desc='Units Complete',
                                             position=0)
                for idx, (concept) in enumerate(concepts):
                    cachefile = sharedfile(
                        'pra-%s-%s/%s/%s.npz' %
                        (args.model, args.dataset, args.experiments,
                         "unit" + str(idx)))
                    if (not os.path.exists(cachefile)):
                        unit = idx
                        # units = [int(u) for u in units]
                        accuracy, acc_per_class = my_test_perclass(
                            model,
                            dataset,
                            layername=layername,
                            ablated_units=[unit],
                            cachefile=cachefile)
                        # acc_list[idx] = accuracy
                        # acc_per_class_list[idx] = acc_per_class  # in a list
                        np.savez(cachefile,
                                 acc=accuracy,
                                 acc_per_class=acc_per_class,
                                 concept=concept)
                    else:
                        print("Unit %s is done" % (str(idx)))
                    process_complete.update(1)

        elif (args.experiments == 'exp4'):
            with open(os.path.join(datas_dir, 'units_by_labels.json'),
                      'r') as file:
                df = json.load(file)
            acc_per_class_list = np.zeros([len(df), len(classlabels)])
            acc_list = np.zeros(len(df))
            process_complete = tqdm.tqdm(total=len(df),
                                         desc='Concepts Complete',
                                         position=0)
            for idx, (concept, units) in enumerate(df.items()):
                cachefile = sharedfile(
                    'pra-%s-%s/%s/%s.npz' %
                    (args.model, args.dataset, args.experiments, concept))
                if (not os.path.exists(cachefile)):
                    #i.e (concept, units) = ('arm', [42,260,462,464])
                    accuracy, acc_per_class = my_test_perclass(
                        model,
                        dataset,
                        layername=layername,
                        ablated_units=units,
                        cachefile=cachefile)
                    acc_list[idx] = accuracy
                    acc_per_class_list[idx] = acc_per_class
                    np.savez(cachefile,
                             acc=acc_list,
                             acc_per_class=acc_per_class_list)
                else:
                    print("Concept : %s is done" % (concept))
                process_complete.update(1)
Beispiel #4
0
def main():
    args = parseargs()
    resdir = 'results/%s-%s-%s-%s-%s' % (args.model, args.dataset, args.seg,
                                         args.layer, int(args.quantile * 1000))

    def resfile(f):
        return os.path.join(resdir, f)

    model = load_model(args)
    layername = instrumented_layername(args)
    model.retain_layer(layername)
    dataset = load_dataset(args, model=model.model)
    upfn = make_upfn(args, dataset, model, layername)
    sample_size = len(dataset)
    is_generator = (args.model == 'progan')
    percent_level = 1.0 - args.quantile

    # Tally rq.np (representation quantile, unconditional).
    torch.set_grad_enabled(False)
    pbar.descnext('rq')

    def compute_samples(batch, *args):
        data_batch = batch.cuda()
        _ = model(data_batch)
        acts = model.retained_layer(layername)
        hacts = upfn(acts)
        return hacts.permute(0, 2, 3, 1).contiguous().view(-1, acts.shape[1])

    rq = tally.tally_quantile(compute_samples,
                              dataset,
                              sample_size=sample_size,
                              r=8192,
                              num_workers=100,
                              pin_memory=True,
                              cachefile=resfile('rq.npz'))

    # Grab the 99th percentile, and tally conditional means at that level.
    level_at_99 = rq.quantiles(percent_level).cuda()[None, :, None, None]

    segmodel, seglabels, segcatlabels = setting.load_segmenter(args.seg)
    renorm = renormalize.renormalizer(dataset, target='zc')

    def compute_conditional_indicator(batch, *args):
        data_batch = batch.cuda()
        out_batch = model(data_batch)
        image_batch = out_batch if is_generator else renorm(data_batch)
        seg = segmodel.segment_batch(image_batch, downsample=4)
        acts = model.retained_layer(layername)
        hacts = upfn(acts)
        iacts = (hacts > level_at_99).float()  # indicator
        return tally.conditional_samples(iacts, seg)

    pbar.descnext('condi99')
    condi99 = tally.tally_conditional_mean(compute_conditional_indicator,
                                           dataset,
                                           sample_size=sample_size,
                                           num_workers=3,
                                           pin_memory=True,
                                           cachefile=resfile('condi99.npz'))

    # Now summarize the iou stats and graph the units
    iou_99 = tally.iou_from_conditional_indicator_mean(condi99)
    unit_label_99 = [(concept.item(), seglabels[concept],
                      segcatlabels[concept], bestiou.item())
                     for (bestiou, concept) in zip(*iou_99.max(0))]

    def measure_segclasses_with_zeroed_units(zeroed_units, sample_size=100):
        model.remove_edits()

        def zero_some_units(x, *args):
            x[:, zeroed_units] = 0
            return x

        model.edit_layer(layername, rule=zero_some_units)
        num_seglabels = len(segmodel.get_label_and_category_names()[0])

        def compute_mean_seg_in_images(batch_z, *args):
            img = model(batch_z.cuda())
            seg = segmodel.segment_batch(img, downsample=4)
            seg_area = seg.shape[2] * seg.shape[3]
            seg_counts = torch.bincount(
                (seg + (num_seglabels * torch.arange(
                    seg.shape[0], dtype=seg.dtype,
                    device=seg.device)[:, None, None, None])).view(-1),
                minlength=num_seglabels * seg.shape[0]).view(seg.shape[0], -1)
            seg_fracs = seg_counts.float() / seg_area
            return seg_fracs

        result = tally.tally_mean(compute_mean_seg_in_images,
                                  dataset,
                                  batch_size=30,
                                  sample_size=sample_size,
                                  pin_memory=True)
        model.remove_edits()
        return result

    # Intervention experiment here:
    # segs_baseline = measure_segclasses_with_zeroed_units([])
    # segs_without_treeunits = measure_segclasses_with_zeroed_units(tree_units)
    num_units = len(unit_label_99)
    baseline_segmean = test_generator_segclass_stats(
        model,
        dataset,
        segmodel,
        layername=layername,
        cachefile=resfile('segstats/baseline.npz')).mean()

    pbar.descnext('unit ablation')
    unit_ablation_segmean = torch.zeros(num_units, len(baseline_segmean))
    for unit in pbar(random.sample(range(num_units), num_units)):
        stats = test_generator_segclass_stats(
            model,
            dataset,
            segmodel,
            layername=layername,
            zeroed_units=[unit],
            cachefile=resfile('segstats/ablated_unit_%d.npz' % unit))
        unit_ablation_segmean[unit] = stats.mean()

    ablate_segclass_name = 'tree'
    ablate_segclass = seglabels.index(ablate_segclass_name)
    best_iou_units = iou_99[ablate_segclass, :].sort(0)[1].flip(0)
    byiou_unit_ablation_seg = torch.zeros(30)
    for unitcount in pbar(random.sample(range(0, 30), 30)):
        zero_units = best_iou_units[:unitcount].tolist()
        stats = test_generator_segclass_delta_stats(
            model,
            dataset,
            segmodel,
            layername=layername,
            zeroed_units=zero_units,
            cachefile=resfile('deltasegstats/ablated_best_%d_iou_%s.npz' %
                              (unitcount, ablate_segclass_name)))
        byiou_unit_ablation_seg[unitcount] = stats.mean()[ablate_segclass]

    # Generator context experiment.
    num_segclass = len(seglabels)
    door_segclass = seglabels.index('door')
    door_units = iou_99[door_segclass].sort(0)[1].flip(0)[:20]
    door_high_values = rq.quantiles(0.995)[door_units].cuda()

    def compute_seg_impact(zbatch, *args):
        zbatch = zbatch.cuda()
        model.remove_edits()
        orig_img = model(zbatch)
        orig_seg = segmodel.segment_batch(orig_img, downsample=4)
        orig_segcount = tally.batch_bincount(orig_seg, num_segclass)
        rep = model.retained_layer(layername).clone()
        ysize = orig_seg.shape[2] // rep.shape[2]
        xsize = orig_seg.shape[3] // rep.shape[3]

        def gen_conditions():
            for y in range(rep.shape[2]):
                for x in range(rep.shape[3]):
                    # Take as the context location the segmentation
                    # labels at the center of the square.
                    selsegs = orig_seg[:, :, y * ysize + ysize // 2,
                                       x * xsize + xsize // 2]
                    changed_rep = rep.clone()
                    changed_rep[:, door_units, y,
                                x] = (door_high_values[None, :])
                    model.edit_layer(layername,
                                     ablation=1.0,
                                     replacement=changed_rep)
                    changed_img = model(zbatch)
                    changed_seg = segmodel.segment_batch(changed_img,
                                                         downsample=4)
                    changed_segcount = tally.batch_bincount(
                        changed_seg, num_segclass)
                    delta_segcount = (changed_segcount - orig_segcount).float()
                    for sel, delta in zip(selsegs, delta_segcount):
                        for cond in torch.bincount(sel).nonzero()[:, 0]:
                            if cond == 0:
                                continue
                            yield (cond.item(), delta)

        return gen_conditions()

    cond_changes = tally.tally_conditional_mean(
        compute_seg_impact,
        dataset,
        sample_size=10000,
        batch_size=20,
        cachefile=resfile('big_door_cond_changes.npz'))
Beispiel #5
0
def main():
    args = parseargs()

    model = setting.load_classifier(args.model)
    model = nethook.InstrumentedModel(model).cuda().eval()
    layername = args.layer
    model.retain_layer(layername)
    dataset = setting.load_dataset(args.dataset, crop_size=224)
    train_dataset = setting.load_dataset(args.dataset,
                                         crop_size=224,
                                         split='train')
    sample_size = len(dataset)

    # Probe layer to get sizes
    model(dataset[0][0][None].cuda())
    num_units = model.retained_layer(layername).shape[1]
    classlabels = dataset.classes

    # Measure baseline classification accuracy on val set, and cache.
    pbar.descnext('baseline_pra')
    baseline_precision, baseline_recall, baseline_accuracy, baseline_ba = (
        test_perclass_pra(model,
                          dataset,
                          cachefile=sharedfile('pra-%s-%s/pra_baseline.npz' %
                                               (args.model, args.dataset))))
    pbar.print('baseline acc', baseline_ba.mean().item())

    # Now erase each unit, one at a time, and retest accuracy.
    unit_list = random.sample(list(range(num_units)), num_units)
    val_single_unit_ablation_ba = torch.zeros(num_units, len(classlabels))
    for unit in pbar(unit_list):
        pbar.descnext('test unit %d' % unit)
        # Get binary accuracy if the model after ablating the unit.
        _, _, _, ablation_ba = test_perclass_pra(
            model,
            dataset,
            layername=layername,
            ablated_units=[unit],
            cachefile=sharedfile('pra-%s-%s/pra_ablate_unit_%d.npz' %
                                 (args.model, args.dataset, unit)))
        val_single_unit_ablation_ba[unit] = ablation_ba

    # For the purpose of ranking units by importance to a class, we
    # measure using the training set (to avoid training unit ordering
    # on the test set).
    sample_size = None
    # Measure baseline classification accuracy, and cache.
    pbar.descnext('train_baseline_pra')
    baseline_precision, baseline_recall, baseline_accuracy, baseline_ba = (
        test_perclass_pra(
            model,
            train_dataset,
            sample_size=sample_size,
            cachefile=sharedfile('ttv-pra-%s-%s/pra_train_baseline.npz' %
                                 (args.model, args.dataset))))
    pbar.print('baseline acc', baseline_ba.mean().item())

    # Measure accuracy on the val set.
    pbar.descnext('val_baseline_pra')
    _, _, _, val_baseline_ba = (test_perclass_pra(
        model,
        dataset,
        cachefile=sharedfile('ttv-pra-%s-%s/pra_val_baseline.npz' %
                             (args.model, args.dataset))))
    pbar.print('val baseline acc', val_baseline_ba.mean().item())

    # Do in shuffled order to allow multiprocessing.
    single_unit_ablation_ba = torch.zeros(num_units, len(classlabels))
    for unit in pbar(unit_list):
        pbar.descnext('test unit %d' % unit)
        _, _, _, ablation_ba = test_perclass_pra(
            model,
            train_dataset,
            layername=layername,
            ablated_units=[unit],
            sample_size=sample_size,
            cachefile=sharedfile('ttv-pra-%s-%s/pra_train_ablate_unit_%d.npz' %
                                 (args.model, args.dataset, unit)))
        single_unit_ablation_ba[unit] = ablation_ba

    # Now for every class, remove a set of the N most-important
    # and N least-important units for that class, and measure accuracy.
    for classnum in pbar(
            random.sample(range(len(classlabels)), len(classlabels))):
        # For a few classes, let's chart the whole range of ablations.
        if classnum in [100, 169, 351, 304]:
            num_best_list = range(1, num_units)
        else:
            num_best_list = [1, 2, 3, 4, 5, 20, 64, 128, 256]
        pbar.descnext('numbest')
        for num_best in pbar(random.sample(num_best_list, len(num_best_list))):
            num_worst = num_units - num_best
            unitlist = single_unit_ablation_ba[:,
                                               classnum].sort(0)[1][:num_best]
            _, _, _, testba = test_perclass_pra(
                model,
                dataset,
                layername=layername,
                ablated_units=unitlist,
                cachefile=sharedfile(
                    'ttv-pra-%s-%s/pra_val_ablate_classunits_%s_ba_%d.npz' %
                    (args.model, args.dataset, classlabels[classnum],
                     len(unitlist))))
            unitlist = (
                single_unit_ablation_ba[:, classnum].sort(0)[1][-num_worst:])
            _, _, _, testba2 = test_perclass_pra(
                model,
                dataset,
                layername=layername,
                ablated_units=unitlist,
                cachefile=sharedfile(
                    'ttv-pra-%s-%s/pra_val_ablate_classunits_%s_worstba_%d.npz'
                    % (args.model, args.dataset, classlabels[classnum],
                       len(unitlist))))
            pbar.print('%s: best %d %.3f vs worst N %.3f' %
                       (classlabels[classnum], num_best,
                        testba[classnum] - val_baseline_ba[classnum],
                        testba2[classnum] - val_baseline_ba[classnum]))