def train():
    with tf.Graph().as_default():
        with tf.device('/gpu:' + str(GPU_INDEX)):
            pointclouds_pl, labels_pl = MODEL.placeholder_inputs(
                BATCH_SIZE, NUM_POINT)
            is_training_pl = tf.placeholder(tf.bool, shape=())
            print(is_training_pl)

            # Note the global_step=batch parameter to minimize.
            # That tells the optimizer to helpfully increment the 'batch' parameter for you every time it trains.
            batch = tf.Variable(0)
            bn_decay = get_bn_decay(batch)
            tf.summary.scalar('bn_decay', bn_decay)

            # Get model and loss
            pred, end_points = MODEL.get_model(pointclouds_pl,
                                               is_training_pl,
                                               bn_decay=bn_decay,
                                               num_classes=NUM_CLASSES)
            loss = MODEL.get_loss(pred, labels_pl, end_points)
            tf.summary.scalar('loss', loss)

            if ADV:
                import adversarial_attacks

                def model_loss_fn(x, t):
                    with tf.variable_scope(tf.get_variable_scope(),
                                           reuse=tf.AUTO_REUSE):
                        y, end_points = MODEL.get_model(
                            x,
                            is_training_pl,
                            bn_decay=bn_decay,
                            num_classes=NUM_CLASSES)
                    if t is None:
                        loss = None
                    else:
                        loss = MODEL.get_loss(y, t, end_points)
                    return y, loss

                x_adv = adversarial_attacks.iter_grad_op(pointclouds_pl,
                                                         model_loss_fn,
                                                         one_hot=False,
                                                         iter=1,
                                                         eps=1,
                                                         ord="2")
                _, adv_loss = model_loss_fn(x_adv, labels_pl)

            correct = tf.equal(tf.argmax(pred, 1), tf.to_int64(labels_pl))
            accuracy = tf.reduce_sum(tf.cast(correct,
                                             tf.float32)) / float(BATCH_SIZE)
            tf.summary.scalar('accuracy', accuracy)

            # Get training operator
            learning_rate = get_learning_rate(batch)
            tf.summary.scalar('learning_rate', learning_rate)
            if OPTIMIZER == 'momentum':
                optimizer = tf.train.MomentumOptimizer(learning_rate,
                                                       momentum=MOMENTUM)
            elif OPTIMIZER == 'adam':
                optimizer = tf.train.AdamOptimizer(learning_rate)
            if ADV:
                train_op = optimizer.minimize((loss + adv_loss) / 2.0,
                                              global_step=batch)
            else:
                train_op = optimizer.minimize(loss, global_step=batch)

            # Add ops to save and restore all the variables.
            saver = tf.train.Saver()

        # Create a session
        config = tf.ConfigProto()
        config.gpu_options.allow_growth = True
        config.allow_soft_placement = True
        config.log_device_placement = False
        sess = tf.Session(config=config)

        # Add summary writers
        #merged = tf.merge_all_summaries()
        merged = tf.summary.merge_all()
        train_writer = tf.summary.FileWriter(os.path.join(LOG_DIR, 'train'),
                                             sess.graph)
        test_writer = tf.summary.FileWriter(os.path.join(LOG_DIR, 'test'))

        # Init variables
        init = tf.global_variables_initializer()
        # To fix the bug introduced in TF 0.12.1 as in
        # http://stackoverflow.com/questions/41543774/invalidargumenterror-for-tensor-bool-tensorflow-0-12-1
        #sess.run(init)
        sess.run(init, {is_training_pl: True})

        ops = {
            'pointclouds_pl': pointclouds_pl,
            'labels_pl': labels_pl,
            'is_training_pl': is_training_pl,
            'pred': pred,
            'loss': loss,
            'train_op': train_op,
            'merged': merged,
            'step': batch
        }

        for epoch in range(MAX_EPOCH):
            log_string('**** EPOCH %03d ****' % (epoch))
            sys.stdout.flush()

            train_one_epoch(sess, ops, train_writer)
            eval_one_epoch(sess, ops, test_writer)

            # Save the variables to disk.
            if epoch % 10 == 0:
                save_path = saver.save(sess,
                                       os.path.join(LOG_DIR, "model.ckpt"))
                log_string("Model saved in file: %s" % save_path)
Beispiel #2
0
def targeted_attack(model_path,
                    out_dir,
                    x_pl,
                    t_pl,
                    model_loss_fn,
                    data_x,
                    data_t,
                    num_objects,
                    class_names,
                    iter,
                    eps_list,
                    norm="inf",
                    data_f=None,
                    restrict=False,
                    one_hot=True,
                    mode="iterative",
                    momentum=1.0,
                    clip_min=None,
                    clip_max=None,
                    clip_norm=None,
                    min_norm=0.0,
                    postprocess_fn=None,
                    extra_feed_dict=None):
    if postprocess_fn is None:
        postprocess_fn = lambda x, y: x
    if extra_feed_dict is None:
        extra_feed_dict = {}
    try:
        os.makedirs(out_dir)
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise

    def_logits_op, def_loss_op = model_loss_fn(
        postprocess_fn(x_pl, model_loss_fn), t_pl)
    def_probs_op = tf.nn.softmax(def_logits_op)

    logits_op, loss_op = model_loss_fn(x_pl, t_pl)
    probs_op = tf.nn.softmax(logits_op)

    data_x = np.array(data_x)
    data_t = np.array(data_t)
    if data_f is not None:
        data_f = np.array(data_f)
    eps_list = np.array(eps_list)

    shuffle_idx = np.random.permutation(len(data_x))
    data_x = data_x[shuffle_idx]
    data_t = data_t[shuffle_idx]
    if data_f is not None:
        data_f = data_f[shuffle_idx]

    eps = tf.placeholder(tf.float32, shape=[])
    if one_hot:
        target = tf.placeholder(tf.float32, shape=[1, len(class_names)])
    else:
        target = tf.placeholder(tf.int32, [1])
    if data_f is None:
        faces = None
    else:
        faces = tf.placeholder(tf.float32, shape=[1, None, 3, 3])

    if mode == "iterative":
        x_adv_op = postprocess_fn(
            adversarial_attacks.iter_grad_op(x_pl,
                                             model_loss_fn,
                                             t_pl=target,
                                             faces=faces,
                                             one_hot=one_hot,
                                             iter=iter,
                                             eps=eps,
                                             ord=norm,
                                             restrict=restrict,
                                             clip_min=clip_min,
                                             clip_max=clip_max,
                                             clip_norm=clip_norm,
                                             min_norm=min_norm), model_loss_fn)
    elif mode == "momentum":
        x_adv_op = postprocess_fn(
            adversarial_attacks.momentum_grad_op(x_pl,
                                                 model_loss_fn,
                                                 t_pl=target,
                                                 faces=faces,
                                                 one_hot=one_hot,
                                                 iter=iter,
                                                 eps=eps,
                                                 ord=norm,
                                                 momentum=momentum,
                                                 restrict=restrict,
                                                 clip_min=clip_min,
                                                 clip_max=clip_max,
                                                 clip_norm=clip_norm,
                                                 min_norm=min_norm),
            model_loss_fn)
    elif mode == "saliency":
        x_adv_op = postprocess_fn(
            adversarial_attacks.jacobian_saliency_map_points_op(
                x_pl,
                model_loss_fn,
                t_pl=target,
                faces=faces,
                one_hot=one_hot,
                iter=iter,
                eps=eps,
                restrict=restrict,
                clip_min=clip_min,
                clip_max=clip_max), model_loss_fn)
    else:
        raise ValueError(
            "Only iterative, momentum, and saliency modes are supported!")

    saver = tf.train.Saver()

    config = tf.ConfigProto()
    config.gpu_options.allow_growth = True
    with tf.Session(config=config) as sess:
        saver.restore(sess, model_path)
        print("Model restored!")

        succeeded_x_original = []
        succeeded_target = []
        succeeded_x_adv = []
        if data_f is not None:
            succeeded_faces = []

        total = len(data_x)

        logits = []
        losses = []
        preds = []
        probs = []
        for i in range(total):
            feed_dict = {x_pl: [data_x[i]], t_pl: [data_t[i]]}
            feed_dict.update(extra_feed_dict)
            curr_logit, curr_loss, curr_prob = sess.run(
                [def_logits_op, def_loss_op, def_probs_op],
                feed_dict=feed_dict)
            curr_pred = np.argmax(curr_logit, axis=1)
            logits.append(curr_logit)
            losses.append(curr_loss)
            preds.append(curr_pred)
            probs.append(curr_prob)

        logits = np.concatenate(logits)
        losses = np.array(losses)
        preds = np.concatenate(preds)
        probs = np.concatenate(probs)

        if one_hot:
            sparse_t = np.argmax(data_t, axis=1)
        else:
            sparse_t = data_t

        correct_idx = preds == sparse_t
        logits = logits[correct_idx][:num_objects]
        preds = preds[correct_idx][:num_objects]
        losses = losses[correct_idx][:num_objects]
        probs = probs[correct_idx][:num_objects]
        data_x = data_x[correct_idx][:num_objects]
        data_t = data_t[correct_idx][:num_objects]
        if data_f is not None:
            data_f = data_f[correct_idx][:num_objects]

        correct = len(data_x)

        class_totals = np.zeros(shape=len(class_names), dtype=int)
        np.add.at(class_totals, sparse_t, 1)
        class_correct = np.zeros(shape=len(class_names), dtype=int)
        np.add.at(class_correct, preds, 1)
        heatmap_totals = np.tile(class_correct, (len(class_names), 1)).T

        print("Model evaluated!")
        print("Generating adversarial inputs...")

        for curr_eps in eps_list:
            print("Current eps: %s" % curr_eps)

            curr_succeeded_x_original = []
            curr_succeeded_target = []
            curr_succeeded_x_adv = []
            if data_f is not None:
                curr_succeeded_faces = []
            success_counts = np.zeros(shape=(len(class_names),
                                             len(class_names)),
                                      dtype=int)
            total_succeeded = 0
            total_successful_confidence = 0
            total_unsuccessful_confidence = 0
            eps_str = str(curr_eps).replace(".", "_")

            for curr_target in range(len(class_names)):
                print("Current target: %s" % class_names[curr_target])

                if one_hot:
                    adv_target = np.zeros(shape=len(class_names))
                    adv_target[curr_target] = 1
                else:
                    adv_target = curr_target

                x_adv = []
                for i in range(correct):
                    feed_dict = {
                        x_pl: [data_x[i]],
                        eps: curr_eps,
                        target: [adv_target]
                    }
                    if data_f is not None:
                        feed_dict[faces] = [data_f[i]]
                    feed_dict.update(extra_feed_dict)
                    curr_x_adv = sess.run(x_adv_op, feed_dict=feed_dict)
                    x_adv.append(curr_x_adv)

                x_adv = np.concatenate(x_adv)

                logits_adv = []
                losses_adv = []
                preds_adv = []
                probs_adv = []
                for i in range(correct):
                    feed_dict = {x_pl: [x_adv[i]], t_pl: [data_t[i]]}
                    feed_dict.update(extra_feed_dict)
                    curr_logit_adv, curr_loss_adv, curr_prob_adv = sess.run(
                        [logits_op, loss_op, probs_op], feed_dict=feed_dict)
                    curr_pred_adv = np.argmax(curr_logit_adv, axis=1)
                    logits_adv.append(curr_logit_adv)
                    losses_adv.append(curr_loss_adv)
                    preds_adv.append(curr_pred_adv)
                    probs_adv.append(curr_prob_adv)

                logits_adv = np.concatenate(logits_adv)
                losses_adv = np.array(losses_adv)
                preds_adv = np.concatenate(preds_adv)
                probs_adv = np.concatenate(probs_adv)

                succeeded_idx = (preds != curr_target) & (preds_adv
                                                          == curr_target)
                succeeded = np.sum(succeeded_idx)
                total_succeeded += succeeded
                curr_succeeded_x_original.append(data_x[succeeded_idx])
                curr_succeeded_target.append(data_t[succeeded_idx])
                curr_succeeded_x_adv.append(x_adv[succeeded_idx])
                if data_f is not None:
                    curr_succeeded_faces.append(data_f[succeeded_idx])

                total_successful_confidence += np.mean(
                    probs_adv[succeeded_idx][range(succeeded),
                                             preds_adv[succeeded_idx]])
                total_unsuccessful_confidence += np.mean(
                    probs_adv[~succeeded_idx][range(correct - succeeded),
                                              preds_adv[~succeeded_idx]])

                np.add.at(success_counts,
                          [preds[succeeded_idx], preds_adv[succeeded_idx]], 1)

                if data_f is None:
                    np.savez_compressed(
                        os.path.join(
                            out_dir,
                            "succeeded_point_clouds_target_%s_eps_%s.npz" %
                            (class_names[curr_target], eps_str)),
                        x_original=curr_succeeded_x_original[-1],
                        labels=curr_succeeded_target[-1],
                        x_adv=curr_succeeded_x_adv[-1])
                else:
                    np.savez_compressed(
                        os.path.join(
                            out_dir,
                            "succeeded_point_clouds_target_%s_eps_%s.npz" %
                            (class_names[curr_target], eps_str)),
                        x_original=curr_succeeded_x_original[-1],
                        labels=curr_succeeded_target[-1],
                        x_adv=curr_succeeded_x_adv[-1],
                        faces=curr_succeeded_faces[-1])

            targeted_success_rate_heatmap(
                success_counts,
                os.path.join(out_dir, "success_count_eps_%s.eps" % eps_str),
                class_names=class_names)
            targeted_success_rate_heatmap(
                success_counts,
                os.path.join(out_dir, "success_rate_eps_%s.eps" % eps_str),
                total=heatmap_totals,
                class_names=class_names)

            total_succeeded /= float(len(class_names))
            total_successful_confidence /= float(len(class_names))
            total_unsuccessful_confidence /= float(len(class_names))

            with open(
                    os.path.join(out_dir,
                                 "targeted_stats_eps_%s.csv" % eps_str),
                    "w") as f:
                f.write("Average confidence for correct predictions: %.3f\n" %
                        np.mean(probs[range(correct), preds]))
                f.write(
                    "Average confidence for successful adversarial predictions: %.3f\n"
                    % total_successful_confidence)
                f.write(
                    "Average confidence for unsuccessful adversarial predictions: %.3f\n"
                    % total_unsuccessful_confidence)

                percent = 0 if correct == 0 else float(
                    total_succeeded) / correct
                f.write(
                    "Total %d, Correct %d, Average Attacks Succeeded For All Target Classes %d, Average Succeeded / Correct %.3f\n"
                    % (total, correct, total_succeeded, percent))

            succeeded_x_original.append(curr_succeeded_x_original)
            succeeded_target.append(curr_succeeded_target)
            succeeded_x_adv.append(curr_succeeded_x_adv)
            if data_f is not None:
                succeeded_faces.append(curr_succeeded_faces)

    print("Done!")

    if data_f is None:
        return succeeded_x_original, succeeded_target, succeeded_x_adv
    else:
        return succeeded_x_original, succeeded_target, succeeded_x_adv, succeeded_faces