Example #1
0
def attack(attacker, attacker_name, model, features, support, y, mask,
           placeholders, sess, **kw):

    mask_split = []
    results = []
    cost, acc = 0, 0
    for i in range(len(mask)):
        if mask[i] == True:
            mask_tmp = mask.copy()
            mask_tmp[:i] = False
            mask_tmp[i + 1:] = False
            mask_tmp[i] = True
            mask_split.append(mask_tmp)
            results.append([])
    if attacker_name.lower() == 'fgsm':
        assert ('epsilon' in kw)
        for i in tqdm(range(len(mask_split))):
            results[i].append(
                fgsm(model=model,
                     feed_dict=construct_feed_dict(features, support, y,
                                                   mask_split[i],
                                                   placeholders),
                     features=features,
                     sess=sess,
                     epsilon=kw['epsilon']))
            cost_tmp, acc_tmp, _ = evaluate(results[i][-1], support, y,
                                            mask_split[i], placeholders)
            cost += cost_tmp
            acc += acc_tmp
    elif attacker_name.lower() == 'flip_single':
        assert ('n_flip' in kw)
        for i in tqdm(range(len(mask_split))):
            features_tmp = features.copy()
            for it in range(kw['n_flip']):
                features_tmp = flip_single(model=model,
                                           feed_dict=construct_feed_dict(
                                               features_tmp, support, y,
                                               mask_split[i], placeholders),
                                           features=features_tmp,
                                           sess=sess)
            results[i].append(features_tmp)
            cost_tmp, acc_tmp, _ = evaluate(results[i][-1], support, y,
                                            mask_split[i], placeholders)
            cost += cost_tmp
            acc += acc_tmp
    else:
        assert False
    return results, cost / len(mask_split), acc / len(mask_split)
Example #2
0
def evaluate(sess, model, val_features_batches, val_support_batches,
             y_val_batches, val_mask_batches, val_data, placeholders):
  """evaluate GCN model."""
  total_pred = []
  total_lab = []
  total_loss = 0
  total_acc = 0

  num_batches = len(val_features_batches)
  for i in range(num_batches):
    features_b = val_features_batches[i]
    support_b = val_support_batches[i]
    y_val_b = y_val_batches[i]
    val_mask_b = val_mask_batches[i]
    num_data_b = np.sum(val_mask_b)
    if num_data_b == 0:
      continue
    else:
      feed_dict = utils.construct_feed_dict(features_b, support_b, y_val_b,
                                            val_mask_b, placeholders)
      outs = sess.run([model.loss, model.accuracy, model.outputs],
                      feed_dict=feed_dict)

    total_pred.append(outs[2][val_mask_b])
    total_lab.append(y_val_b[val_mask_b])
    total_loss += outs[0] * num_data_b
    total_acc += outs[1] * num_data_b

  total_pred = np.vstack(total_pred)
  total_lab = np.vstack(total_lab)
  loss = total_loss / len(val_data)
  acc = total_acc / len(val_data)

  micro, macro = utils.calc_f1(total_pred, total_lab, FLAGS.multilabel)
  return loss, acc, micro, macro
Example #3
0
 def evaluate(labels_mask, noise=0., dropout=0.):
     feed_dict_val = construct_feed_dict(features, support, labels,
                                         labels_mask, placeholders,
                                         noise, dropout)
     outs_val = sess.run([model.loss, model.accuracy],
                         feed_dict=feed_dict_val)
     return outs_val[0], outs_val[1]
Example #4
0
def run_model(session, params, adj, num_cv, features, y, mask, output_dir):
    """
    """
    # compute support matrices
    support, num_supports = utils.get_support_matrices(adj, params['support'])
    # construct placeholders & model
    placeholders = {
        'support': [tf.sparse_placeholder(tf.float32, name='support_{}'.format(i)) for i in range(num_supports)],
        'features': tf.placeholder(tf.float32, shape=features.shape, name='Features'),
        'labels': tf.placeholder(tf.float32, shape=(None, y.shape[1]), name='Labels'),
        'labels_mask': tf.placeholder(tf.int32, shape=mask.shape, name='LabelsMask'),
        'dropout': tf.placeholder_with_default(0., shape=(), name='Dropout')
    }
    model = EMOGI(placeholders=placeholders,
                  input_dim=features.shape[1],
                  learning_rate=params['learningrate'],
                  weight_decay=params['weight_decay'],
                  num_hidden_layers=len(params['hidden_dims']),
                  hidden_dims=params['hidden_dims'],
                  pos_loss_multiplier=params['loss_mul'],
                  logging=False
    )
    # where the results go
    accs = []
    losses = []
    auprs = []
    num_preds = []

    k_sets = gcnPreprocessing.cross_validation_sets(y=y,
                                                    mask=mask,
                                                    folds=num_cv
    )
    for cv_run in range(num_cv):
        # train model
        y_train, y_val, train_mask, val_mask = k_sets[cv_run]
        model = fit_model(model=model,
                          sess=session,
                          features=features,
                          placeholders=placeholders,
                          support=support,
                          epochs=params['epochs'],
                          dropout_rate=params['dropout'],
                          y_train=y_train,
                          train_mask=train_mask,
                          y_val=y_val,
                          val_mask=val_mask,
                          output_dir=os.path.join(output_dir, 'cv_{}'.format(cv_run))
        )
        # Compute performance on validation set
        performance_ops = model.get_performance_metrics()
        sess.run(tf.local_variables_initializer())
        d = utils.construct_feed_dict(features, support, y_val,
                                      val_mask, placeholders)
        val_performance = sess.run(performance_ops, feed_dict=d)
        predictions = sess.run(model.predict(), feed_dict=d)
        accs.append(val_performance[1])
        losses.append(val_performance[0])
        auprs.append(val_performance[2])
        num_preds.append((predictions > 0.5).sum())
    return accs, losses, num_preds, auprs
Example #5
0
def main(args):
    #
    save_dir = args.save_dir
    log_dir = args.log_dir
    train_dir = args.data_dir

    if not os.path.exists(save_dir):
        os.makedirs(save_dir)
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)

    adj, features, y_train, y_val, y_test, train_mask, val_mask, test_mask = utils.load_data(
        args.data_type)
    features = utils.preprocess_features(features)
    support = [utils.preprocess_adj(adj)]
    args.num_supports = 1
    args.input_size, args.features_size = features[2][1], features[2]
    args.output_size = y_train.shape[1]

    config_proto = utils.get_config_proto()
    sess = tf.Session(config=config_proto)
    model = GCN(args, sess, name="gcn")
    summary_writer = tf.summary.FileWriter(log_dir)

    for epoch in range(1, args.nb_epoch + 1):
        epoch_start_time = time.time()

        feed_dict = utils.construct_feed_dict(model, features, support,
                                              y_train, train_mask)
        _, train_loss, train_acc, summaries = model.train(feed_dict)

        if epoch % args.summary_epoch == 0:
            summary_writer.add_summary(summaries, epoch)

        if epoch % args.print_epoch == 0:
            feed_dict_val = utils.construct_feed_dict(model, features, support,
                                                      y_val, val_mask)
            val_loss, val_acc = model.evaluate(feed_dict_val)
            print "epoch %d, train_loss %f, train_acc %f, val_loss %f, val_acc %f, time %.5fs" % \
              (epoch, train_loss, train_acc, val_loss, val_acc, time.time()-epoch_start_time)

        if args.anneal and epoch >= args.anneal_start:
            sess.run(model.lr_decay_op)

    model.saver.save(sess, os.path.join(save_dir, "model.ckpt"))
    print "Model stored...."
 def evaluate(features, adjacency, labels, mask, placeholders):
     t_test = time.time()
     feed_dict_val = construct_feed_dict(features, adjacency, labels, mask,
                                         adjacency, placeholders)
     outs_val = sess.run([model.loss, model.accuracy,
                          model.predict()],
                         feed_dict=feed_dict_val)
     return outs_val[0], outs_val[1], (time.time() - t_test), outs_val[2]
Example #7
0
def evaluate(features, support, labels, mask, placeholders):
    t_test = time.time()
    feed_dict_val = construct_feed_dict(features, support, labels, mask,
                                        placeholders)
    feed_dict_val.update(
        {placeholders['support'][i]: support[i]
         for i in range(len(support))})
    outs_val = sess.run([model.attack_loss, model.accuracy],
                        feed_dict=feed_dict_val)
    return outs_val[0], outs_val[1], (time.time() - t_test)
Example #8
0
def evaluate(sess, model, features, support, labels, mask, placeholders):
    t_test = time.time()
    feed_dict_val = utils.construct_feed_dict(features,
                                              support,
                                              labels,
                                              mask,
                                              placeholders,
                                              sparse_inputs=False)
    outs_val = sess.run([model.loss, model.accuracy, model.y_pred],
                        feed_dict=feed_dict_val)
    return outs_val[0], outs_val[1], outs_val[2], (time.time() - t_test)
Example #9
0
def single_cv_run(session, support, num_supports, features, y_train, y_test,
                  train_mask, test_mask, node_names, feature_names, args,
                  model_dir):
    hidden_dims = [int(x) for x in args['hidden_dims']]
    placeholders = {
        'support': [
            tf.sparse_placeholder(tf.float32, name='support_{}'.format(i))
            for i in range(num_supports)
        ],
        'features':
        tf.placeholder(tf.float32, shape=features.shape, name='Features'),
        'labels':
        tf.placeholder(tf.float32,
                       shape=(None, y_train.shape[1]),
                       name='Labels'),
        'labels_mask':
        tf.placeholder(tf.int32, shape=train_mask.shape, name='LabelsMask'),
        'dropout':
        tf.placeholder_with_default(0., shape=(), name='Dropout')
    }
    # construct model (including computation graph)
    model = EMOGI(placeholders=placeholders,
                  input_dim=features.shape[1],
                  learning_rate=args['lr'],
                  weight_decay=args['decay'],
                  num_hidden_layers=len(hidden_dims),
                  hidden_dims=hidden_dims,
                  pos_loss_multiplier=args['loss_mul'],
                  logging=True)
    # fit the model
    model = fit_model(model, session, features, placeholders, support,
                      args['epochs'], args['dropout'], y_train, train_mask,
                      y_test, test_mask, model_dir)
    # Compute performance on test set
    performance_ops = model.get_performance_metrics()
    session.run(tf.local_variables_initializer())
    d = utils.construct_feed_dict(features, support, y_test, test_mask,
                                  placeholders)
    test_performance = session.run(performance_ops, feed_dict=d)
    print("Validataion/test set results:", "loss=",
          "{:.5f}".format(test_performance[0]), "accuracy=",
          "{:.5f}".format(test_performance[1]), "aupr=",
          "{:.5f}".format(test_performance[2]), "auroc=",
          "{:.5f}".format(test_performance[3]))

    # predict all nodes (result from algorithm)
    predictions = predict(session, model, features, support, y_test, test_mask,
                          placeholders)
    gcnIO.save_predictions(model_dir, node_names, predictions)
    gcnIO.write_train_test_sets(model_dir, y_train, y_test, train_mask,
                                test_mask)
    return test_performance
Example #10
0
def evaluate(sess,
             model,
             features,
             support,
             labels,
             placeholders,
             mask,
             dropout=0.,
             alfa=0,
             beta=1):
    feed_dict_val = construct_feed_dict(features, support, labels, mask,
                                        placeholders, dropout, alfa, beta)
    outs_val = sess.run([model.loss, model.accuracy], feed_dict=feed_dict_val)
    return outs_val[0], outs_val[1]
Example #11
0
def evaluate(sess, model, val_features_batches, val_support_batches,
             y_val_batches, val_mask_batches, val_data, placeholders,
             clusters_adj):
    """evaluate GCN model."""
    total_pred = []
    total_lab = []
    total_loss = 0
    total_acc = 0

    num_batches = len(val_features_batches)
    for batch_id in range(num_batches):
        features_b = val_features_batches[batch_id]
        support_b = val_support_batches[batch_id]
        y_val_b = y_val_batches[batch_id]
        val_mask_b = val_mask_batches[batch_id]
        num_data_b = np.sum(val_mask_b)
        if clusters_adj is not None:
            cluster_adj = clusters_adj[batch_id]
        if num_data_b == 0:
            continue
        else:
            feed_dict = utils.construct_feed_dict(features_b, support_b,
                                                  y_val_b, val_mask_b,
                                                  placeholders)
            outs = sess.run([model.loss, model.accuracy, model.outputs],
                            feed_dict=feed_dict)

        total_pred.append(outs[2][val_mask_b])
        total_lab.append(y_val_b[val_mask_b])
        total_loss += outs[0] * num_data_b
        total_acc += outs[1] * num_data_b

    total_pred = np.vstack(total_pred)
    total_lab = np.vstack(total_lab)
    # import pdb; pdb.set_trace()
    sp.save_npz(f'cluster/clusters_adj', clusters_adj)
    np.save(f'cluster/cluster_y', total_lab)
    np.save(f'cluster/total_pred', total_pred)
    loss = total_loss / len(val_data)
    acc = total_acc / len(val_data)

    micro, macro = utils.calc_f1(total_pred, total_lab, FLAGS.multilabel)
    return loss, acc, micro, macro
Example #12
0
train_support_t = sparse_to_tuple(train_support_t)

u_features = sparse_to_tuple(u_features)
v_features = sparse_to_tuple(v_features)
assert u_features[2][1] == v_features[2][1], 'Number of features of users and items must be the same!'

num_features = u_features[2][1]
u_features_nonzero = u_features[1].shape[0]
v_features_nonzero = v_features[1].shape[0]

# 使用二部图输入作为训练输出的idx以及损失函数的label
# train_labels, train_u_indices, train_v_indices, u_dict, v_dict = get_original_labels()

# Feed_dicts for validation and test set stay constant over different update steps
train_feed_dict = construct_feed_dict(placeholders, u_features, v_features, u_features_nonzero,
                                      v_features_nonzero, train_support, train_support_t,
                                      train_labels, train_u_indices, train_v_indices, class_values, DO,
                                      train_u_features_side, train_v_features_side)
# No dropout for validation and test runs

val_feed_dict = construct_feed_dict(placeholders, u_features, v_features, u_features_nonzero,
                                    v_features_nonzero, val_support, val_support_t,
                                    val_labels, val_u_indices, val_v_indices, class_values, 0.,
                                    val_u_features_side, val_v_features_side)


# Collect all variables to be logged into summary
merged_summary = tf.summary.merge_all()

sess = tf.Session()
sess.run(tf.global_variables_initializer())
Example #13
0
def test_compatibility(args):
    args = namedtuple("Args", args.keys())(*args.values())
    load_from = args.load_from
    config_file = load_from + '/results.json'
    log_file = load_from + '/log.json'

    with open(config_file) as f:
        config = json.load(f)
    with open(log_file) as f:
        log = json.load(f)

    # Dataloader
    DATASET = config['dataset']
    if DATASET == 'polyvore':
        # load dataset
        dl = DataLoaderPolyvore()
        orig_train_features, adj_train, train_labels, train_r_indices, train_c_indices = dl.get_phase(
            'train')
        full_train_adj = dl.train_adj
        orig_val_features, adj_val, val_labels, val_r_indices, val_c_indices = dl.get_phase(
            'valid')
        orig_test_features, adj_test, test_labels, test_r_indices, test_c_indices = dl.get_phase(
            'test')
        full_test_adj = dl.test_adj
        dl.setup_test_compatibility(resampled=args.resampled)
    elif DATASET == 'ssense':
        dl = DataLoaderFashionGen()
        orig_train_features, adj_train, train_labels, train_r_indices, train_c_indices = dl.get_phase(
            'train')
        orig_val_features, adj_val, val_labels, val_r_indices, val_c_indices = dl.get_phase(
            'valid')
        orig_test_features, adj_test, test_labels, test_r_indices, test_c_indices = dl.get_phase(
            'test')
        adj_q, q_r_indices, q_c_indices, q_labels, q_ids, q_valid = dl.get_test_questions(
        )
        full_train_adj = dl.train_adj
        full_test_adj = dl.test_adj
        dl.setup_test_compatibility(resampled=args.resampled)
    else:
        raise NotImplementedError(
            'A data loader for dataset {} does not exist'.format(DATASET))

    NUMCLASSES = 2
    BN_AS_TRAIN = False
    ADJ_SELF_CONNECTIONS = True

    def norm_adj(adj_to_norm):
        return normalize_nonsym_adj(adj_to_norm)

    train_features, mean, std = dl.normalize_features(orig_train_features,
                                                      get_moments=True)
    val_features = dl.normalize_features(orig_val_features, mean=mean, std=std)
    test_features = dl.normalize_features(orig_test_features,
                                          mean=mean,
                                          std=std)

    train_support = get_degree_supports(adj_train,
                                        config['degree'],
                                        adj_self_con=ADJ_SELF_CONNECTIONS)
    val_support = get_degree_supports(adj_val,
                                      config['degree'],
                                      adj_self_con=ADJ_SELF_CONNECTIONS)
    test_support = get_degree_supports(adj_test,
                                       config['degree'],
                                       adj_self_con=ADJ_SELF_CONNECTIONS)

    for i in range(1, len(train_support)):
        train_support[i] = norm_adj(train_support[i])
        val_support[i] = norm_adj(val_support[i])
        test_support[i] = norm_adj(test_support[i])

    num_support = len(train_support)
    placeholders = {
        'row_indices':
        tf.compat.v1.placeholder(tf.int32, shape=(None, )),
        'col_indices':
        tf.compat.v1.placeholder(tf.int32, shape=(None, )),
        'dropout':
        tf.compat.v1.placeholder_with_default(0., shape=()),
        'weight_decay':
        tf.compat.v1.placeholder_with_default(0., shape=()),
        'is_train':
        tf.compat.v1.placeholder_with_default(True, shape=()),
        'support': [
            tf.compat.v1.sparse_placeholder(tf.float32, shape=(None, None))
            for sup in range(num_support)
        ],
        'node_features':
        tf.compat.v1.placeholder(tf.float32, shape=(None, None)),
        'labels':
        tf.compat.v1.placeholder(tf.float32, shape=(None, ))
    }

    model = CompatibilityGAE(placeholders,
                             input_dim=train_features.shape[1],
                             num_classes=NUMCLASSES,
                             num_support=num_support,
                             hidden=config['hidden'],
                             learning_rate=config['learning_rate'],
                             logging=True,
                             batch_norm=config['batch_norm'])

    # Construct feed dicts for train, val and test phases
    train_feed_dict = construct_feed_dict(placeholders, train_features,
                                          train_support, train_labels,
                                          train_r_indices, train_c_indices,
                                          config['dropout'])
    val_feed_dict = construct_feed_dict(placeholders,
                                        val_features,
                                        val_support,
                                        val_labels,
                                        val_r_indices,
                                        val_c_indices,
                                        0.,
                                        is_train=BN_AS_TRAIN)
    test_feed_dict = construct_feed_dict(placeholders,
                                         test_features,
                                         test_support,
                                         test_labels,
                                         test_r_indices,
                                         test_c_indices,
                                         0.,
                                         is_train=BN_AS_TRAIN)

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

    def eval():
        # use this as a control value, if the model is ok, the value will be the same as in log
        val_avg_loss, val_acc, conf, pred = sess.run(
            [model.loss, model.accuracy, model.confmat,
             model.predict()],
            feed_dict=val_feed_dict)

        print("val_loss=", "{:.5f}".format(val_avg_loss), "val_acc=",
              "{:.5f}".format(val_acc))

    with tf.compat.v1.Session() as sess:
        saver.restore(sess, load_from + '/' + 'best_epoch.ckpt')

        count = 0
        preds = []
        labels = []

        # evaluate the the model for accuracy prediction
        eval()

        prob_act = tf.nn.sigmoid

        K = args.k
        for outfit in dl.comp_outfits:
            before_item = time.time()
            items, score = outfit

            num_new = test_features.shape[0]

            new_adj = sp.csr_matrix((num_new, num_new))  # no connections

            if args.k > 0:
                # add edges to the adj matrix
                available_adj = dl.test_adj.copy()
                available_adj = available_adj.tolil()

                i = 0
                for idx_from in items[:-1]:
                    for idx_to in items[i + 1:]:
                        # remove outfit edges, they won't be expanded
                        available_adj[idx_to, idx_from] = 0
                        available_adj[idx_from, idx_to] = 0
                    i += 1
                available_adj = available_adj.tocsr()
                available_adj.eliminate_zeros()

            if args.subset:  # use only a subset (of size 3) of the outfit
                items = np.random.choice(items, 3)

            new_features = test_features

            # predict edges between the items
            query_r = []
            query_c = []

            i = 0
            item_indexes = items
            for idx_from in item_indexes[:-1]:
                for idx_to in item_indexes[i + 1:]:
                    query_r.append(idx_from)
                    query_c.append(idx_to)
                i += 1

            if args.k > 0:
                G = Graph(available_adj)
                nodes_to_expand = np.unique(items)
                for node in nodes_to_expand:
                    edges = G.run_K_BFS(node, K)
                    for edge in edges:
                        u, v = edge
                        new_adj[u, v] = 1
                        new_adj[v, u] = 1

            query_r = np.array(query_r)
            query_c = np.array(query_c)

            new_adj = new_adj.tocsr()

            new_support = get_degree_supports(
                new_adj,
                config['degree'],
                adj_self_con=ADJ_SELF_CONNECTIONS,
                verbose=False)
            for i in range(1, len(new_support)):
                new_support[i] = norm_adj(new_support[i])
            new_support = [sparse_to_tuple(sup) for sup in new_support]

            new_feed_dict = construct_feed_dict(placeholders,
                                                new_features,
                                                new_support,
                                                train_labels,
                                                query_r,
                                                query_c,
                                                0.,
                                                is_train=BN_AS_TRAIN)

            pred = sess.run(prob_act(model.outputs), feed_dict=new_feed_dict)

            predicted_score = pred.mean()
            print("[{}] Mean scores between outfit: {:.4f}, label: {}".format(
                count, predicted_score, score))
            # TODO: remove this print
            print("Total Elapsed: {:.4f}".format(time.time() - before_item))
            count += 1

            preds.append(predicted_score)
            labels.append(score)

        preds = np.array(preds)
        labels = np.array(labels)

        AUC = compute_auc(preds, labels)

        # use this as a control value, if the model is ok, the value will be the same as in log
        eval()

        print('The AUC compat score is: {}'.format(AUC))

    print('Best val score saved in log: {}'.format(config['best_val_score']))
    print('Last val score saved in log: {}'.format(log['val']['acc'][-1]))

    print("mean positive prediction: {}".format(
        preds[labels.astype(bool)].mean()))
    print("mean negative prediction: {}".format(preds[np.logical_not(
        labels.astype(bool))].mean()))
Example #14
0
def run(DATASET='douban',
        DATASEED=1234,
        random_seed=123,
        NB_EPOCH=200,
        DO=0,
        HIDDEN=[100, 75],
        FEATHIDDEN=64,
        LR=0.01,
        decay_rate=1.25,
        consecutive_threshold=5,
        FEATURES=False,
        SYM=True,
        TESTING=False,
        ACCUM='stackRGGCN',
        NUM_LAYERS=1,
        GCMC_INDICES=False):
    np.random.seed(random_seed)
    tf.set_random_seed(random_seed)

    SELFCONNECTIONS = False
    SPLITFROMFILE = True
    VERBOSE = False
    BASES = 2
    WRITESUMMARY = False
    SUMMARIESDIR = 'logs/'

    if DATASET == 'ml_1m' or DATASET == 'ml_100k' or DATASET == 'douban':
        NUMCLASSES = 5
    elif DATASET == 'ml_10m':
        NUMCLASSES = 10
        print(
            '\n WARNING: this might run out of RAM, consider using train_minibatch.py for dataset %s'
            % DATASET)
        print(
            'If you want to proceed with this option anyway, uncomment this.\n'
        )
        sys.exit(1)
    elif DATASET == 'flixster':
        NUMCLASSES = 10
    elif DATASET == 'yahoo_music':
        NUMCLASSES = 71
        if ACCUM == 'sum':
            print(
                '\n WARNING: combining DATASET=%s with ACCUM=%s can cause memory issues due to large number of classes.'
            )
            print(
                'Consider using "--accum stack" as an option for this dataset.'
            )
            print(
                'If you want to proceed with this option anyway, uncomment this.\n'
            )
            sys.exit(1)

    # Splitting dataset in training, validation and test set

    if DATASET == 'ml_1m' or DATASET == 'ml_10m':
        if FEATURES:
            datasplit_path = 'data/' + DATASET + '/withfeatures_split_seed' + str(
                DATASEED) + '.pickle'
        else:
            datasplit_path = 'data/' + DATASET + '/split_seed' + str(
                DATASEED) + '.pickle'
    elif FEATURES:
        datasplit_path = 'data/' + DATASET + '/withfeatures.pickle'
    else:
        datasplit_path = 'data/' + DATASET + '/nofeatures.pickle'

    if DATASET == 'flixster' or DATASET == 'douban' or DATASET == 'yahoo_music':
        u_features, v_features, adj_train, train_labels, train_u_indices, train_v_indices, \
         val_labels, val_u_indices, val_v_indices, test_labels, \
         test_u_indices, test_v_indices, class_values = load_data_monti(DATASET, TESTING)

    elif DATASET == 'ml_100k':
        print(
            "Using official MovieLens dataset split u1.base/u1.test with 20% validation set size..."
        )
        u_features, v_features, adj_train, train_labels, train_u_indices, train_v_indices, \
         val_labels, val_u_indices, val_v_indices, test_labels, \
         test_u_indices, test_v_indices, class_values = load_official_trainvaltest_split(DATASET, TESTING)
    else:
        print("Using random dataset split ...")
        u_features, v_features, adj_train, train_labels, train_u_indices, train_v_indices, \
         val_labels, val_u_indices, val_v_indices, test_labels, \
         test_u_indices, test_v_indices, class_values = create_trainvaltest_split(DATASET, DATASEED, TESTING,
                            datasplit_path, SPLITFROMFILE,
                            VERBOSE)

    num_users, num_items = adj_train.shape
    num_side_features = 0

    # feature loading
    if not FEATURES:
        u_features = sp.identity(
            num_users, format='csr')  # features is just one-hot vector!
        v_features = sp.identity(num_items, format='csr')

        u_features, v_features = preprocess_user_item_features(
            u_features, v_features)

    elif FEATURES and u_features is not None and v_features is not None:
        # use features as side information and node_id's as node input features

        print("Normalizing feature vectors...")
        u_features_side = normalize_features(u_features)
        v_features_side = normalize_features(v_features)

        u_features_side, v_features_side = preprocess_user_item_features(
            u_features_side, v_features_side)

        u_features_side = np.array(u_features_side.todense(), dtype=np.float32)
        v_features_side = np.array(v_features_side.todense(), dtype=np.float32)

        num_side_features = u_features_side.shape[1]

        # node id's for node input features
        id_csr_v = sp.identity(num_items, format='csr')
        id_csr_u = sp.identity(num_users, format='csr')

        u_features, v_features = preprocess_user_item_features(
            id_csr_u, id_csr_v)

    else:
        raise ValueError(
            'Features flag is set to true but no features are loaded from dataset '
            + DATASET)

    # print("User features shape: " + str(u_features.shape))
    # print("Item features shape: " + str(v_features.shape))
    # print("adj_train shape: " + str(adj_train.shape))

    # global normalization
    support = []
    support_t = []
    adj_train_int = sp.csr_matrix(adj_train, dtype=np.int32)

    for i in range(NUMCLASSES):
        # build individual binary rating matrices (supports) for each rating
        support_unnormalized = sp.csr_matrix(adj_train_int == i + 1,
                                             dtype=np.float32)

        if support_unnormalized.nnz == 0 and DATASET != 'yahoo_music':
            # yahoo music has dataset split with not all ratings types present in training set.
            # this produces empty adjacency matrices for these ratings.
            sys.exit(
                'ERROR: normalized bipartite adjacency matrix has only zero entries!!!!!'
            )

        support_unnormalized_transpose = support_unnormalized.T
        support.append(support_unnormalized)
        support_t.append(support_unnormalized_transpose)

    support = globally_normalize_bipartite_adjacency(support, symmetric=SYM)
    support_t = globally_normalize_bipartite_adjacency(support_t,
                                                       symmetric=SYM)

    if SELFCONNECTIONS:
        support.append(sp.identity(u_features.shape[0], format='csr'))
        support_t.append(sp.identity(v_features.shape[0], format='csr'))

    num_support = len(support)
    support = sp.hstack(support, format='csr')
    support_t = sp.hstack(support_t, format='csr')
    # support and support_t become 3000x15000 (for douban with 3000 users/items and 5 ratings)
    # support is n_users x (n_items*n_ratings). support_t is n_items x (n_users*ratings)
    # NOTE: support is sparse matrix so the shape may not be as large as expected (?)
    # When is num_support ever not == num_rating_classes?
    # print('support shape: ' + str(support.shape))
    # print('support_t shape: ' + str(support_t.shape))

    if ACCUM == 'stack' or ACCUM == 'stackRGGCN':
        div = HIDDEN[0] // num_support
        if HIDDEN[0] % num_support != 0:
            print(
                """\nWARNING: HIDDEN[0] (=%d) of stack layer is adjusted to %d such that
					  it can be evenly split in %d splits.\n""" %
                (HIDDEN[0], num_support * div, num_support))
        HIDDEN[0] = num_support * div

    ##################################################################################################################
    """ support contains only training set ratings. index into support using user/item indices to create test set support. """
    test_support = val_support = train_support = support
    test_support_t = val_support_t = train_support_t = support_t

    if GCMC_INDICES:
        # Collect all user and item nodes for test set
        test_u = list(set(test_u_indices))
        test_v = list(set(test_v_indices))
        test_support = support[np.array(test_u)]
        test_support_t = support_t[np.array(test_v)]

        # Collect all user and item nodes for validation set
        val_u = list(set(val_u_indices))
        val_v = list(set(val_v_indices))
        val_support = support[np.array(val_u)]
        val_support_t = support_t[np.array(val_v)]

        # Collect all user and item nodes for train set
        train_u = list(set(train_u_indices))
        train_v = list(set(train_v_indices))
        train_support = support[np.array(train_u)]
        train_support_t = support_t[np.array(train_v)]

        test_u_dict = {n: i for i, n in enumerate(test_u)}
        test_v_dict = {n: i for i, n in enumerate(test_v)}
        test_u_indices = np.array([test_u_dict[o] for o in test_u_indices])
        test_v_indices = np.array([test_v_dict[o] for o in test_v_indices])

        val_u_dict = {n: i for i, n in enumerate(val_u)}
        val_v_dict = {n: i for i, n in enumerate(val_v)}
        val_u_indices = np.array([val_u_dict[o] for o in val_u_indices])
        val_v_indices = np.array([val_v_dict[o] for o in val_v_indices])

        train_u_dict = {n: i for i, n in enumerate(train_u)}
        train_v_dict = {n: i for i, n in enumerate(train_v)}
        print('max train_u_indices: {}'.format(max(train_u_indices)))
        train_u_indices = np.array(
            [train_u_dict[o] for o in train_u_indices]
        )  ### HERE IS WHERE indices get changed to suit the new indexing into smaller set of users
        train_v_indices = np.array([train_v_dict[o] for o in train_v_indices])
        print('max train_u_indices after: {}'.format(max(train_u_indices)))

    # print('train_support_shape: {}'.format(train_support.shape)) # if GCMC_INDICES, THIS IS NO LONGER (n_users, n_items*n_rating_types). but < n_users
    ##################################################################################################################

    # features as side info
    if FEATURES:
        test_u_features_side = u_features_side[np.array(test_u)]
        test_v_features_side = v_features_side[np.array(test_v)]

        val_u_features_side = u_features_side[np.array(val_u)]
        val_v_features_side = v_features_side[np.array(val_v)]

        train_u_features_side = u_features_side[np.array(train_u)]
        train_v_features_side = v_features_side[np.array(train_v)]

    else:
        test_u_features_side = None
        test_v_features_side = None

        val_u_features_side = None
        val_v_features_side = None

        train_u_features_side = None
        train_v_features_side = None

    placeholders = {
        'u_features':
        tf.sparse_placeholder(tf.float32,
                              shape=np.array(u_features.shape,
                                             dtype=np.int64)),
        'v_features':
        tf.sparse_placeholder(tf.float32,
                              shape=np.array(v_features.shape,
                                             dtype=np.int64)),
        'u_features_nonzero':
        tf.placeholder(tf.int32, shape=()),
        'v_features_nonzero':
        tf.placeholder(tf.int32, shape=()),
        'labels':
        tf.placeholder(tf.int32, shape=(None, )),
        'u_features_side':
        tf.placeholder(tf.float32, shape=(None, num_side_features)),
        'v_features_side':
        tf.placeholder(tf.float32, shape=(None, num_side_features)),
        'user_indices':
        tf.placeholder(tf.int32, shape=(None, )),
        'item_indices':
        tf.placeholder(tf.int32, shape=(None, )),
        'class_values':
        tf.placeholder(tf.float32, shape=class_values.shape),
        'dropout':
        tf.placeholder_with_default(0., shape=()),
        'weight_decay':
        tf.placeholder_with_default(0., shape=()),
        'support':
        tf.sparse_placeholder(tf.float32, shape=(None, None)),
        'support_t':
        tf.sparse_placeholder(tf.float32, shape=(None, None)),
    }

    ##################################################################################################################
    E_start, E_end = get_edges_matrices(adj_train)
    # E_start = sp.hstack(E_start, format='csr')  # confirm if vstack is correct and not hstack
    # E_end = sp.hstack(E_end, format='csr')

    # placeholders['E_start'] = tf.sparse_placeholder(tf.float32, shape=(None, None, None))
    # placeholders['E_end'] = tf.sparse_placeholder(tf.float32, shape=(None, None, None))

    placeholders['E_start_list'] = []
    placeholders['E_end_list'] = []
    for i in range(num_support):
        placeholders['E_start_list'].append(
            tf.sparse_placeholder(tf.float32, shape=(None, None)))
        placeholders['E_end_list'].append(
            tf.sparse_placeholder(tf.float32, shape=(None, None)))

    # print('shape of E_end for first rating type: {}'.format(E_end[0].toarray().shape))

    ##################################################################################################################

    # create model
    if FEATURES:
        model = RecommenderSideInfoGAE(placeholders,
                                       input_dim=u_features.shape[1],
                                       feat_hidden_dim=FEATHIDDEN,
                                       num_classes=NUMCLASSES,
                                       num_support=num_support,
                                       self_connections=SELFCONNECTIONS,
                                       num_basis_functions=BASES,
                                       hidden=HIDDEN,
                                       num_users=num_users,
                                       num_items=num_items,
                                       accum=ACCUM,
                                       learning_rate=LR,
                                       num_side_features=num_side_features,
                                       logging=True)
    else:
        model = RecommenderGAE(placeholders,
                               input_dim=u_features.shape[1],
                               num_classes=NUMCLASSES,
                               num_support=num_support,
                               self_connections=SELFCONNECTIONS,
                               num_basis_functions=BASES,
                               hidden=HIDDEN,
                               num_users=num_users,
                               num_items=num_items,
                               accum=ACCUM,
                               learning_rate=LR,
                               num_layers=NUM_LAYERS,
                               logging=True)

    # Convert sparse placeholders to tuples to construct feed_dict. sparse placeholders expect tuple of (indices, values, shape)
    test_support = sparse_to_tuple(test_support)
    test_support_t = sparse_to_tuple(test_support_t)

    val_support = sparse_to_tuple(val_support)
    val_support_t = sparse_to_tuple(val_support_t)

    train_support = sparse_to_tuple(train_support)
    train_support_t = sparse_to_tuple(train_support_t)

    u_features = sparse_to_tuple(u_features)
    v_features = sparse_to_tuple(v_features)
    assert u_features[2][1] == v_features[2][
        1], 'Number of features of users and items must be the same!'

    num_features = u_features[2][1]
    u_features_nonzero = u_features[1].shape[0]
    v_features_nonzero = v_features[1].shape[0]

    # setting E_start to be the same for train, val, and test. E_start already only contains train edges (from preprocessing script)
    train_E_start = []
    train_E_end = []
    # print('LENGTH OF E_START: {}'.format(len(E_start)))
    # print('NUM_SUPPORT: {}'.format(num_support))
    for i in range(num_support):
        train_E_start.append(sparse_to_tuple(E_start[i]))
        train_E_end.append(sparse_to_tuple(E_end[i]))
    val_E_start = test_E_start = train_E_start
    val_E_end = test_E_end = train_E_end

    # Feed_dicts for validation and test set stay constant over different update steps
    train_feed_dict = construct_feed_dict(
        placeholders, u_features, v_features, u_features_nonzero,
        v_features_nonzero, train_support, train_support_t, train_labels,
        train_u_indices, train_v_indices, class_values, DO,
        train_u_features_side, train_v_features_side, train_E_start,
        train_E_end)

    # No dropout for validation and test runs. DO = dropout. input for val and test is same u_features and v_features.
    val_feed_dict = construct_feed_dict(
        placeholders, u_features, v_features, u_features_nonzero,
        v_features_nonzero, val_support, val_support_t, val_labels,
        val_u_indices, val_v_indices, class_values, 0., val_u_features_side,
        val_v_features_side, val_E_start, val_E_end)

    test_feed_dict = construct_feed_dict(
        placeholders, u_features, v_features, u_features_nonzero,
        v_features_nonzero, test_support, test_support_t, test_labels,
        test_u_indices, test_v_indices, class_values, 0., test_u_features_side,
        test_v_features_side, test_E_start, test_E_end)

    # Collect all variables to be logged into summary
    merged_summary = tf.summary.merge_all()

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    if WRITESUMMARY:
        train_summary_writer = tf.summary.FileWriter(SUMMARIESDIR + '/train',
                                                     sess.graph)
        val_summary_writer = tf.summary.FileWriter(SUMMARIESDIR + '/val')
    else:
        train_summary_writer = None
        val_summary_writer = None

    best_val_score = np.inf
    best_val_loss = np.inf
    best_epoch = 0
    wait = 0

    print('Training...')

    #### COUTNING PARAMS
    total_parameters = 0
    for variable in tf.trainable_variables():
        # shape is an array of tf.Dimension
        shape = variable.get_shape()
        variable_parameters = 1
        for dim in shape:
            variable_parameters *= dim.value
        total_parameters += variable_parameters
    print('Total params: {}'.format(total_parameters))

    # FOR A VARIABLE LEARNING RATE
    assign_placeholder = tf.placeholder(tf.float32)
    assign_op = model.learning_rate.assign(assign_placeholder)
    old_loss = float('inf')
    # print('Original learning rate is {}'.format(sess.run(model.optimizer._lr)))

    train_rmses, val_rmses, train_losses, val_losses = [], [], [], []
    for epoch in tqdm(range(NB_EPOCH)):
        t = time.time()
        # Run single weight update
        # outs = sess.run([model.opt_op, model.loss, model.rmse], feed_dict=train_feed_dict)
        # with exponential moving averages
        outs = sess.run([model.training_op, model.loss, model.rmse],
                        feed_dict=train_feed_dict)

        train_avg_loss = outs[1]
        train_rmse = outs[2]

        val_avg_loss, val_rmse = sess.run([model.loss, model.rmse],
                                          feed_dict=val_feed_dict)

        # if train_avg_loss > 0.999*old_loss:
        # 	consecutive += 1
        # 	if consecutive >= consecutive_threshold:
        # 		LR /= decay_rate
        # 		sess.run(assign_op, feed_dict={assign_placeholder: LR})
        # 		print('New learning rate is {}'.format(sess.run(model.optimizer._lr)))
        # 		consecutive = 0
        # else:
        # 	consecutive = 0
        # old_loss = train_avg_loss

        train_rmses.append(train_rmse)
        val_rmses.append(val_rmse)
        train_losses.append(train_avg_loss)
        val_losses.append(val_avg_loss)

        if VERBOSE:
            print("[*] Epoch:", '%04d' % (epoch + 1), "train_loss=",
                  "{:.5f}".format(train_avg_loss), "train_rmse=",
                  "{:.5f}".format(train_rmse), "val_loss=",
                  "{:.5f}".format(val_avg_loss), "val_rmse=",
                  "{:.5f}".format(val_rmse), "\t\ttime=",
                  "{:.5f}".format(time.time() - t))

        if val_rmse < best_val_score:
            best_val_score = val_rmse
            best_epoch = epoch

        if epoch % 20 == 0 and WRITESUMMARY:
            # Train set summary
            summary = sess.run(merged_summary, feed_dict=train_feed_dict)
            train_summary_writer.add_summary(summary, epoch)
            train_summary_writer.flush()

            # Validation set summary
            summary = sess.run(merged_summary, feed_dict=val_feed_dict)
            val_summary_writer.add_summary(summary, epoch)
            val_summary_writer.flush()

        if epoch % 100 == 0 and epoch > 1000 and not TESTING and False:
            saver = tf.train.Saver()
            save_path = saver.save(sess,
                                   "tmp/%s_seed%d.ckpt" %
                                   (model.name, DATASEED),
                                   global_step=model.global_step)

            # load polyak averages
            variables_to_restore = model.variable_averages.variables_to_restore(
            )
            saver = tf.train.Saver(variables_to_restore)
            saver.restore(sess, save_path)

            val_avg_loss, val_rmse = sess.run([model.loss, model.rmse],
                                              feed_dict=val_feed_dict)

            print('polyak val loss = ', val_avg_loss)
            print('polyak val rmse = ', val_rmse)

            # Load back normal variables
            saver = tf.train.Saver()
            saver.restore(sess, save_path)

    # store model including exponential moving averages
    saver = tf.train.Saver()
    save_path = saver.save(sess,
                           "tmp/%s.ckpt" % model.name,
                           global_step=model.global_step)

    if VERBOSE:
        print("\nOptimization Finished!")
        print('best validation score =', best_val_score, 'at iteration',
              best_epoch)

    if TESTING:
        test_avg_loss, test_rmse = sess.run([model.loss, model.rmse],
                                            feed_dict=test_feed_dict)
        print('test loss = ', test_avg_loss)
        print('test rmse = ', test_rmse)

        # restore with polyak averages of parameters
        variables_to_restore = model.variable_averages.variables_to_restore()
        saver = tf.train.Saver(variables_to_restore)
        saver.restore(sess, save_path)

        test_avg_loss, test_rmse = sess.run([model.loss, model.rmse],
                                            feed_dict=test_feed_dict)
        print('polyak test loss = ', test_avg_loss)
        print('polyak test rmse = ', test_rmse)

        sess.close()
        tf.reset_default_graph()
        return train_rmses, val_rmses, train_losses, val_losses, test_rmse
    else:
        # restore with polyak averages of parameters
        variables_to_restore = model.variable_averages.variables_to_restore()
        saver = tf.train.Saver(variables_to_restore)
        saver.restore(sess, save_path)

        val_avg_loss, val_rmse = sess.run([model.loss, model.rmse],
                                          feed_dict=val_feed_dict)
        print('polyak val loss = ', val_avg_loss)
        print('polyak val rmse = ', val_rmse)

        sess.close()
        tf.reset_default_graph()
        return train_rmses, val_rmses, train_losses, val_losses, val_rmse
Example #15
0
def run(user_features, movie_features, learning_rate=0.01, epochs=500, hidden=[500, 75], feat_hidden=64, accumulation='sum', dropout=0.7,
        num_basis_functions=2, features=False, symmetric=True, testing=True):
  """accumulation can be sum or stack"""

  # Set random seed
  # seed = 123 # use only for unit testing
  seed = int(time.time())
  np.random.seed(seed)
  tf.set_random_seed(seed)
  tf.reset_default_graph()

  # Settings
  # ap = argparse.ArgumentParser()
  # # ap.add_argument("-d", "--dataset", type=str, default="ml_100k",
  # #               choices=['ml_100k', 'ml_1m', 'ml_10m', 'douban', 'yahoo_music', 'flixster'],
  # #               help="Dataset string.")

  # ap.add_argument("-lr", "--learning_rate", type=float, default=0.01,
  #                 help="Learning rate")

  # ap.add_argument("-e", "--epochs", type=int, default=2500,
  #                 help="Number training epochs")

  # ap.add_argument("-hi", "--hidden", type=int, nargs=2, default=[500, 75],
  #                 help="Number hidden units in 1st and 2nd layer")

  # ap.add_argument("-fhi", "--feat_hidden", type=int, default=64,
  #                 help="Number hidden units in the dense layer for features")

  # ap.add_argument("-ac", "--accumulation", type=str, default="sum", choices=['sum', 'stack'],
  #                 help="Accumulation function: sum or stack.")

  # ap.add_argument("-do", "--dropout", type=float, default=0.7,
  #                 help="Dropout fraction")

  # ap.add_argument("-nb", "--num_basis_functions", type=int, default=2,
  #                 help="Number of basis functions for Mixture Model GCN.")

  # ap.add_argument("-ds", "--data_seed", type=int, default=1234,
  #                 help="""Seed used to shuffle data in data_utils, taken from cf-nade (1234, 2341, 3412, 4123, 1324).
  #                      Only used for ml_1m and ml_10m datasets. """)

  # ap.add_argument("-sdir", "--summaries_dir", type=str, default='logs/' + str(datetime.datetime.now()).replace(' ', '_'),
  #                 help="Directory for saving tensorflow summaries.")

  # # Boolean flags
  # fp = ap.add_mutually_exclusive_group(required=False)
  # fp.add_argument('-nsym', '--norm_symmetric', dest='norm_symmetric',
  #                 help="Option to turn on symmetric global normalization", action='store_true')
  # fp.add_argument('-nleft', '--norm_left', dest='norm_symmetric',
  #                 help="Option to turn on left global normalization", action='store_false')
  # ap.set_defaults(norm_symmetric=True)

  # fp = ap.add_mutually_exclusive_group(required=False)
  # fp.add_argument('-f', '--features', dest='features',
  #                 help="Whether to use features (1) or not (0)", action='store_true')
  # fp.add_argument('-no_f', '--no_features', dest='features',
  #                 help="Whether to use features (1) or not (0)", action='store_false')
  # ap.set_defaults(features=False)

  # fp = ap.add_mutually_exclusive_group(required=False)
  # fp.add_argument('-ws', '--write_summary', dest='write_summary',
  #                 help="Option to turn on summary writing", action='store_true')
  # fp.add_argument('-no_ws', '--no_write_summary', dest='write_summary',
  #                 help="Option to turn off summary writing", action='store_false')
  # ap.set_defaults(write_summary=False)

  # fp = ap.add_mutually_exclusive_group(required=False)
  # fp.add_argument('-t', '--testing', dest='testing',
  #                 help="Option to turn on test set evaluation", action='store_true')
  # fp.add_argument('-v', '--validation', dest='testing',
  #                 help="Option to only use validation set evaluation", action='store_false')
  # ap.set_defaults(testing=False)


  # args = vars(ap.parse_args())

  # print('Settings:')
  # print(args, '\n')

  # Define parameters
  DATASET = 'ml_100k'
  DATASEED = 1234
  NB_EPOCH = epochs
  DO = dropout
  HIDDEN = hidden
  FEATHIDDEN = feat_hidden
  BASES = num_basis_functions
  LR = learning_rate
  WRITESUMMARY = False
  SUMMARIESDIR = 'logs/' + str(datetime.datetime.now()).replace(' ', '_')
  FEATURES = features
  SYM = symmetric
  TESTING = testing
  ACCUM = accumulation

  SELFCONNECTIONS = False
  SPLITFROMFILE = True
  VERBOSE = True

  NUMCLASSES = 5

  # Splitting dataset in training, validation and test set

  print("Using official MovieLens dataset split u1.base/u1.test with 20% validation set size...")
  u_features = user_features
  v_features = movie_features
  _, _, adj_train, train_labels, train_u_indices, train_v_indices, \
  val_labels, val_u_indices, val_v_indices, test_labels, \
  test_u_indices, test_v_indices, class_values = load_official_trainvaltest_split('ml_100k', TESTING)


  num_users, num_items = adj_train.shape

  num_side_features = 0

  # feature loading
  if not FEATURES:
      u_features = sp.identity(num_users, format='csr')
      v_features = sp.identity(num_items, format='csr')

      u_features, v_features = preprocess_user_item_features(u_features, v_features)

  elif FEATURES and u_features is not None and v_features is not None:
      # use features as side information and node_id's as node input features

      print("Normalizing feature vectors...")
      u_features_side = normalize_features(u_features)
      v_features_side = normalize_features(v_features)

      u_features_side, v_features_side = preprocess_user_item_features(u_features_side, v_features_side)

      u_features_side = np.array(u_features_side.todense(), dtype=np.float32)
      v_features_side = np.array(v_features_side.todense(), dtype=np.float32)

      num_side_features = u_features_side.shape[1]

      # node id's for node input features
      id_csr_v = sp.identity(num_items, format='csr')
      id_csr_u = sp.identity(num_users, format='csr')

      u_features, v_features = preprocess_user_item_features(id_csr_u, id_csr_v)

  else:
      raise ValueError('Features flag is set to true but no features are loaded from dataset ' + DATASET)


  # global normalization
  support = []
  support_t = []
  adj_train_int = sp.csr_matrix(adj_train, dtype=np.int32)

  for i in range(NUMCLASSES):
      # build individual binary rating matrices (supports) for each rating
      support_unnormalized = sp.csr_matrix(adj_train_int == i + 1, dtype=np.float32)

      if support_unnormalized.nnz == 0 and DATASET != 'yahoo_music':
          # yahoo music has dataset split with not all ratings types present in training set.
          # this produces empty adjacency matrices for these ratings.
          sys.exit('ERROR: normalized bipartite adjacency matrix has only zero entries!!!!!')

      support_unnormalized_transpose = support_unnormalized.T
      support.append(support_unnormalized)
      support_t.append(support_unnormalized_transpose)


  support = globally_normalize_bipartite_adjacency(support, symmetric=SYM)
  support_t = globally_normalize_bipartite_adjacency(support_t, symmetric=SYM)

  if SELFCONNECTIONS:
      support.append(sp.identity(u_features.shape[0], format='csr'))
      support_t.append(sp.identity(v_features.shape[0], format='csr'))

  num_support = len(support)
  support = sp.hstack(support, format='csr')
  support_t = sp.hstack(support_t, format='csr')

  if ACCUM == 'stack':
      div = HIDDEN[0] // num_support
      if HIDDEN[0] % num_support != 0:
          print("""\nWARNING: HIDDEN[0] (=%d) of stack layer is adjusted to %d such that
                    it can be evenly split in %d splits.\n""" % (HIDDEN[0], num_support * div, num_support))
      HIDDEN[0] = num_support * div

  # Collect all user and item nodes for test set
  test_u = list(set(test_u_indices))
  test_v = list(set(test_v_indices))
  test_u_dict = {n: i for i, n in enumerate(test_u)}
  test_v_dict = {n: i for i, n in enumerate(test_v)}

  test_u_indices = np.array([test_u_dict[o] for o in test_u_indices])
  test_v_indices = np.array([test_v_dict[o] for o in test_v_indices])

  test_support = support[np.array(test_u)]
  test_support_t = support_t[np.array(test_v)]

  # Collect all user and item nodes for validation set
  val_u = list(set(val_u_indices))
  val_v = list(set(val_v_indices))
  val_u_dict = {n: i for i, n in enumerate(val_u)}
  val_v_dict = {n: i for i, n in enumerate(val_v)}

  val_u_indices = np.array([val_u_dict[o] for o in val_u_indices])
  val_v_indices = np.array([val_v_dict[o] for o in val_v_indices])

  val_support = support[np.array(val_u)]
  val_support_t = support_t[np.array(val_v)]

  # Collect all user and item nodes for train set
  train_u = list(set(train_u_indices))
  train_v = list(set(train_v_indices))
  train_u_dict = {n: i for i, n in enumerate(train_u)}
  train_v_dict = {n: i for i, n in enumerate(train_v)}

  train_u_indices = np.array([train_u_dict[o] for o in train_u_indices])
  train_v_indices = np.array([train_v_dict[o] for o in train_v_indices])

  train_support = support[np.array(train_u)]
  train_support_t = support_t[np.array(train_v)]

  # features as side info
  if FEATURES:
      test_u_features_side = u_features_side[np.array(test_u)]
      test_v_features_side = v_features_side[np.array(test_v)]

      val_u_features_side = u_features_side[np.array(val_u)]
      val_v_features_side = v_features_side[np.array(val_v)]

      train_u_features_side = u_features_side[np.array(train_u)]
      train_v_features_side = v_features_side[np.array(train_v)]

  else:
      test_u_features_side = None
      test_v_features_side = None

      val_u_features_side = None
      val_v_features_side = None

      train_u_features_side = None
      train_v_features_side = None


  placeholders = {
      'u_features': tf.sparse_placeholder(tf.float32, shape=np.array(u_features.shape, dtype=np.int64)),
      'v_features': tf.sparse_placeholder(tf.float32, shape=np.array(v_features.shape, dtype=np.int64)),
      'u_features_nonzero': tf.placeholder(tf.int32, shape=()),
      'v_features_nonzero': tf.placeholder(tf.int32, shape=()),
      'labels': tf.placeholder(tf.int32, shape=(None,)),

      'u_features_side': tf.placeholder(tf.float32, shape=(None, num_side_features)),
      'v_features_side': tf.placeholder(tf.float32, shape=(None, num_side_features)),

      'user_indices': tf.placeholder(tf.int32, shape=(None,)),
      'item_indices': tf.placeholder(tf.int32, shape=(None,)),

      'class_values': tf.placeholder(tf.float32, shape=class_values.shape),

      'dropout': tf.placeholder_with_default(0., shape=()),
      'weight_decay': tf.placeholder_with_default(0., shape=()),

      'support': tf.sparse_placeholder(tf.float32, shape=(None, None)),
      'support_t': tf.sparse_placeholder(tf.float32, shape=(None, None)),
  }

  # create model
  if FEATURES:
      model = RecommenderSideInfoGAE(placeholders,
                                     input_dim=u_features.shape[1],
                                     feat_hidden_dim=FEATHIDDEN,
                                     num_classes=NUMCLASSES,
                                     num_support=num_support,
                                     self_connections=SELFCONNECTIONS,
                                     num_basis_functions=BASES,
                                     hidden=HIDDEN,
                                     num_users=num_users,
                                     num_items=num_items,
                                     accum=ACCUM,
                                     learning_rate=LR,
                                     num_side_features=num_side_features,
                                     logging=True)
  else:
      model = RecommenderGAE(placeholders,
                             input_dim=u_features.shape[1],
                             num_classes=NUMCLASSES,
                             num_support=num_support,
                             self_connections=SELFCONNECTIONS,
                             num_basis_functions=BASES,
                             hidden=HIDDEN,
                             num_users=num_users,
                             num_items=num_items,
                             accum=ACCUM,
                             learning_rate=LR,
                             logging=True)

  # Convert sparse placeholders to tuples to construct feed_dict
  test_support = sparse_to_tuple(test_support)
  test_support_t = sparse_to_tuple(test_support_t)

  val_support = sparse_to_tuple(val_support)
  val_support_t = sparse_to_tuple(val_support_t)

  train_support = sparse_to_tuple(train_support)
  train_support_t = sparse_to_tuple(train_support_t)

  u_features = sparse_to_tuple(u_features)
  v_features = sparse_to_tuple(v_features)
  assert u_features[2][1] == v_features[2][1], 'Number of features of users and items must be the same!'

  num_features = u_features[2][1]
  u_features_nonzero = u_features[1].shape[0]
  v_features_nonzero = v_features[1].shape[0]

  # Feed_dicts for validation and test set stay constant over different update steps
  train_feed_dict = construct_feed_dict(placeholders, u_features, v_features, u_features_nonzero,
                                        v_features_nonzero, train_support, train_support_t,
                                        train_labels, train_u_indices, train_v_indices, class_values, DO,
                                        train_u_features_side, train_v_features_side)
  # No dropout for validation and test runs
  val_feed_dict = construct_feed_dict(placeholders, u_features, v_features, u_features_nonzero,
                                      v_features_nonzero, val_support, val_support_t,
                                      val_labels, val_u_indices, val_v_indices, class_values, 0.,
                                      val_u_features_side, val_v_features_side)

  test_feed_dict = construct_feed_dict(placeholders, u_features, v_features, u_features_nonzero,
                                       v_features_nonzero, test_support, test_support_t,
                                       test_labels, test_u_indices, test_v_indices, class_values, 0.,
                                       test_u_features_side, test_v_features_side)


  # Collect all variables to be logged into summary
  merged_summary = tf.summary.merge_all()

  #sess = tf.Session()
  sess = tf.InteractiveSession()

  sess.run(tf.global_variables_initializer())

  if WRITESUMMARY:
      train_summary_writer = tf.summary.FileWriter(SUMMARIESDIR + '/train', sess.graph)
      val_summary_writer = tf.summary.FileWriter(SUMMARIESDIR + '/val')
  else:
      train_summary_writer = None
      val_summary_writer = None

  best_val_score = np.inf
  best_val_loss = np.inf
  best_epoch = 0
  wait = 0

  print('Training...')

  train_loss_values = []
  train_rmse_values = []
  val_loss_values = []
  val_rmse_values = []
  list_embeddings = []

  for epoch in range(NB_EPOCH):

      t = time.time()

      # Run single weight update
      # outs = sess.run([model.opt_op, model.loss, model.rmse], feed_dict=train_feed_dict)
      # with exponential moving averages
      outs = sess.run([model.training_op, model.loss, model.rmse], feed_dict=train_feed_dict)

  
      #print(len(model.embeddings))
        
        
      train_avg_loss = outs[1]
      train_rmse = outs[2]

      val_avg_loss, val_rmse = sess.run([model.loss, model.rmse], feed_dict=val_feed_dict)

      train_loss_values.append(train_avg_loss)
      train_rmse_values.append(train_rmse)
      val_loss_values.append(val_avg_loss)
      val_rmse_values.append(val_rmse)

      if VERBOSE:
          print("[*] Epoch:", '%04d' % (epoch + 1), "train_loss=", "{:.5f}".format(train_avg_loss),
                "train_rmse=", "{:.5f}".format(train_rmse),
                "val_loss=", "{:.5f}".format(val_avg_loss),
                "val_rmse=", "{:.5f}".format(val_rmse),
                "\t\ttime=", "{:.5f}".format(time.time() - t))

      if epoch==NB_EPOCH - 1:
          embedding_users = model.embeddings[0].eval(feed_dict=train_feed_dict)
          embedding_movies = model.embeddings[1].eval(feed_dict=train_feed_dict)

      if val_rmse < best_val_score:
          best_val_score = val_rmse
          best_epoch = epoch

      if epoch % 20 == 0 and WRITESUMMARY:
          # Train set summary
          summary = sess.run(merged_summary, feed_dict=train_feed_dict)
          train_summary_writer.add_summary(summary, epoch)
          train_summary_writer.flush()

          # Validation set summary
          summary = sess.run(merged_summary, feed_dict=val_feed_dict)
          val_summary_writer.add_summary(summary, epoch)
          val_summary_writer.flush()

      if epoch % 100 == 0 and epoch > 1000 and not TESTING and False:
          saver = tf.train.Saver()
          save_path = saver.save(sess, "tmp/%s_seed%d.ckpt" % (model.name, DATASEED), global_step=model.global_step)

          # load polyak averages
          variables_to_restore = model.variable_averages.variables_to_restore()
          saver = tf.train.Saver(variables_to_restore)
          saver.restore(sess, save_path)

          val_avg_loss, val_rmse = sess.run([model.loss, model.rmse], feed_dict=val_feed_dict)

          print('polyak val loss = ', val_avg_loss)
          print('polyak val rmse = ', val_rmse)

          # Load back normal variables
          saver = tf.train.Saver()
          saver.restore(sess, save_path)


  # store model including exponential moving averages
  saver = tf.train.Saver()
  save_path = saver.save(sess, "tmp/%s.ckpt" % model.name, global_step=model.global_step)


  if VERBOSE:
      print("\nOptimization Finished!")
      print('best validation score =', best_val_score, 'at iteration', best_epoch+1)


  if TESTING:
      test_avg_loss, test_rmse = sess.run([model.loss, model.rmse], feed_dict=test_feed_dict)
      print('test loss = ', test_avg_loss)
      print('test rmse = ', test_rmse)

      # restore with polyak averages of parameters
      variables_to_restore = model.variable_averages.variables_to_restore()
      saver = tf.train.Saver(variables_to_restore)
      saver.restore(sess, save_path)

      test_avg_loss, test_rmse = sess.run([model.loss, model.rmse], feed_dict=test_feed_dict)
      print('polyak test loss = ', test_avg_loss)
      print('polyak test rmse = ', test_rmse)

  else:
      # restore with polyak averages of parameters
      variables_to_restore = model.variable_averages.variables_to_restore()
      saver = tf.train.Saver(variables_to_restore)
      saver.restore(sess, save_path)

      val_avg_loss, val_rmse = sess.run([model.loss, model.rmse], feed_dict=val_feed_dict)
      print('polyak val loss = ', val_avg_loss)
      print('polyak val rmse = ', val_rmse)

  print('global seed = ', seed)

  sess.close()

  return embedding_users, embedding_movies, train_loss_values, train_rmse_values, val_loss_values, val_rmse_values
Example #16
0
val_support_t = sparse_to_tuple(val_support_t)

u_features = sparse_to_tuple(u_features)
v_features = sparse_to_tuple(v_features)
assert u_features[2][1] == v_features[2][
    1], 'Number of features of users and items must be the same!'

num_features = u_features[2][1]
u_features_nonzero = u_features[1].shape[0]
v_features_nonzero = v_features[1].shape[0]

# Feed_dicts for validation and test set stay constant over different update steps
# No dropout for validation and test runs
val_feed_dict = construct_feed_dict(placeholders, u_features, v_features,
                                    u_features_nonzero, v_features_nonzero,
                                    val_support, val_support_t, val_labels,
                                    val_u_indices, val_v_indices, class_values,
                                    0.)

test_feed_dict = construct_feed_dict(placeholders, u_features, v_features,
                                     u_features_nonzero, v_features_nonzero,
                                     test_support, test_support_t, test_labels,
                                     test_u_indices, test_v_indices,
                                     class_values, 0.)

# Collect all variables to be logged into summary
merged_summary = tf.summary.merge_all()

sess = tf.Session()
sess.run(tf.global_variables_initializer())
Example #17
0
                        feed_dict=feed_dict_val)
    return outs_val[0], outs_val[1], (time.time() - t_test), outs_val[2]


# Init variables
sess.run(tf.global_variables_initializer())

cost_val = []
# Train model
for epoch in range(FLAGS.epochs):

    t = time.time()
    # Construct feed dictionary
    feed_dict = construct_feed_dict(features,
                                    support,
                                    y_train,
                                    train_mask,
                                    placeholders,
                                    train=True)
    feed_dict.update({placeholders['dropout']: FLAGS.dropout})

    # Training step
    outs = sess.run([model.opt_op, model.loss, model.accuracy],
                    feed_dict=feed_dict)

    # Validation
    cost, acc, duration, _ = evaluate(features, support, y_val, val_mask,
                                      placeholders)
    cost_val.append(cost)

    # Print results
    print("Epoch:", '%04d' % (epoch + 1), "train_loss=",
def test_fitb(args):
    args = namedtuple("Args", args.keys())(*args.values())
    load_from = args.load_from
    config_file = load_from + '/results.json'
    log_file = load_from + '/log.json'

    with open(config_file) as f:
        config = json.load(f)
    with open(log_file) as f:
        log = json.load(f)

    DATASET = config['dataset']
    NUMCLASSES = 2
    BN_AS_TRAIN = False
    ADJ_SELF_CONNECTIONS = True

    def norm_adj(adj_to_norm):
        return normalize_nonsym_adj(adj_to_norm)

    # Dataloader
    if DATASET == 'fashiongen':
        dl = DataLoaderFashionGen()
    elif DATASET == 'polyvore':
        dl = DataLoaderPolyvore()
    train_features, adj_train, train_labels, train_r_indices, train_c_indices = dl.get_phase(
        'train')
    val_features, adj_val, val_labels, val_r_indices, val_c_indices = dl.get_phase(
        'valid')
    test_features, adj_test, test_labels, test_r_indices, test_c_indices = dl.get_phase(
        'test')
    adj_q, q_r_indices, q_c_indices, q_labels, q_ids, q_valid = dl.get_test_questions(
    )
    train_features, mean, std = dl.normalize_features(train_features,
                                                      get_moments=True)
    val_features = dl.normalize_features(val_features, mean=mean, std=std)
    test_features = dl.normalize_features(test_features, mean=mean, std=std)

    train_support = get_degree_supports(adj_train,
                                        config['degree'],
                                        adj_self_con=ADJ_SELF_CONNECTIONS)
    val_support = get_degree_supports(adj_val,
                                      config['degree'],
                                      adj_self_con=ADJ_SELF_CONNECTIONS)
    test_support = get_degree_supports(adj_test,
                                       config['degree'],
                                       adj_self_con=ADJ_SELF_CONNECTIONS)
    q_support = get_degree_supports(adj_q,
                                    config['degree'],
                                    adj_self_con=ADJ_SELF_CONNECTIONS)

    for i in range(1, len(train_support)):
        train_support[i] = norm_adj(train_support[i])
        val_support[i] = norm_adj(val_support[i])
        test_support[i] = norm_adj(test_support[i])
        q_support[i] = norm_adj(q_support[i])

    num_support = len(train_support)
    placeholders = {
        'row_indices':
        tf.placeholder(tf.int32, shape=(None, )),
        'col_indices':
        tf.placeholder(tf.int32, shape=(None, )),
        'dropout':
        tf.placeholder_with_default(0., shape=()),
        'weight_decay':
        tf.placeholder_with_default(0., shape=()),
        'is_train':
        tf.placeholder_with_default(True, shape=()),
        'support': [
            tf.sparse_placeholder(tf.float32, shape=(None, None))
            for sup in range(num_support)
        ],
        'node_features':
        tf.placeholder(tf.float32, shape=(None, None)),
        'labels':
        tf.placeholder(tf.float32, shape=(None, ))
    }

    model = CompatibilityGAE(placeholders,
                             input_dim=train_features.shape[1],
                             num_classes=NUMCLASSES,
                             num_support=num_support,
                             hidden=config['hidden'],
                             learning_rate=config['learning_rate'],
                             logging=True,
                             batch_norm=config['batch_norm'])

    # Construct feed dicts for train, val and test phases
    train_feed_dict = construct_feed_dict(placeholders, train_features,
                                          train_support, train_labels,
                                          train_r_indices, train_c_indices,
                                          config['dropout'])
    val_feed_dict = construct_feed_dict(placeholders,
                                        val_features,
                                        val_support,
                                        val_labels,
                                        val_r_indices,
                                        val_c_indices,
                                        0.,
                                        is_train=BN_AS_TRAIN)
    test_feed_dict = construct_feed_dict(placeholders,
                                         test_features,
                                         test_support,
                                         test_labels,
                                         test_r_indices,
                                         test_c_indices,
                                         0.,
                                         is_train=BN_AS_TRAIN)
    q_feed_dict = construct_feed_dict(placeholders,
                                      test_features,
                                      q_support,
                                      q_labels,
                                      q_r_indices,
                                      q_c_indices,
                                      0.,
                                      is_train=BN_AS_TRAIN)

    # Add ops to save and restore all the variables.
    saver = tf.train.Saver()
    sigmoid = lambda x: 1 / (1 + np.exp(-x))

    with tf.Session() as sess:
        saver.restore(sess, load_from + '/' + 'best_epoch.ckpt')

        val_avg_loss, val_acc, conf, pred = sess.run(
            [model.loss, model.accuracy, model.confmat,
             model.predict()],
            feed_dict=val_feed_dict)

        print("val_loss=", "{:.5f}".format(val_avg_loss), "val_acc=",
              "{:.5f}".format(val_acc))

        test_avg_loss, test_acc, conf = sess.run(
            [model.loss, model.accuracy, model.confmat],
            feed_dict=test_feed_dict)

        print("test_loss=", "{:.5f}".format(test_avg_loss), "test_acc=",
              "{:.5f}".format(test_acc))

        num_processed = 0
        correct = 0

        kwargs = {
            'K': args.k,
            'subset': args.subset,
            'resampled': args.resampled,
            'expand_outfit': args.expand_outfit
        }

        for question_adj, out_ids, choices_ids, labels, valid in dl.yield_test_questions_K_edges(
                **kwargs):
            q_support = get_degree_supports(question_adj,
                                            config['degree'],
                                            adj_self_con=ADJ_SELF_CONNECTIONS,
                                            verbose=False)
            for i in range(1, len(q_support)):
                q_support[i] = norm_adj(q_support[i])
            q_support = [sparse_to_tuple(sup) for sup in q_support]

            q_feed_dict = construct_feed_dict(placeholders,
                                              test_features,
                                              q_support,
                                              q_labels,
                                              out_ids,
                                              choices_ids,
                                              0.,
                                              is_train=BN_AS_TRAIN)

            # compute the output (correct or not) for the current FITB question
            preds = sess.run(model.outputs, feed_dict=q_feed_dict)
            preds = sigmoid(preds)
            outs = preds.reshape((-1, 4))
            outs = outs.mean(
                axis=0
            )  # pick the item with average largest probability, averaged accross all edges

            gt = labels.reshape((-1, 4)).mean(axis=0)
            predicted = outs.argmax()
            gt = gt.argmax()
            num_processed += 1
            correct += int(predicted == gt)

            print("[{}] Acc: {}".format(num_processed,
                                        correct / num_processed))

    print('Best val score saved in log: {}'.format(config['best_val_score']))
    print('Last val score saved in log: {}'.format(log['val']['acc'][-1]))
Example #19
0
def evaluate(features, support, labels, mask, placeholders):
    t_test = time.time()
    feed_dict_val = construct_feed_dict(features_dense, support, labels, mask,
                                        placeholders)
    outs_val = sess.run([model.loss, model.accuracy], feed_dict=feed_dict_val)
    return outs_val[0], outs_val[1], (time.time() - t_test)
Example #20
0
        outs_val = sess.run([model.loss, model.accuracy,
                             model.predict()],
                            feed_dict=feed_dict_val)
        return outs_val[0], outs_val[1], (time.time() - t_test), outs_val[2]

    # Init variables
    sess.run(tf.global_variables_initializer())

    cost_val = []

    # Train model
    for epoch in range(FLAGS.epochs):

        t = time.time()
        # Construct feed dictionary
        feed_dict = construct_feed_dict(features, adjacency, y_train,
                                        train_mask, adjacency, placeholders)
        feed_dict.update({placeholders['dropout']: FLAGS.dropout})
        # Training step
        outs = sess.run([model.opt_op, model.loss, model.accuracy],
                        feed_dict=feed_dict)
        # Validation
        cost, acc, duration, _ = evaluate(features, adjacency, y_val, val_mask,
                                          placeholders)
        cost_val.append(cost)
        if VERBOSE_TRAINING:
            # Print results
            print("Epoch:", '%04d' % (epoch + 1), "train_loss=",
                  "{:.5f}".format(outs[1]), "train_acc=",
                  "{:.5f}".format(outs[2]), "val_loss=", "{:.5f}".format(cost),
                  "val_acc=", "{:.5f}".format(acc), "time=",
                  "{:.5f}".format(time.time() - t))
Example #21
0
best_acc, best_loss = 0, 1e8
attack = PGDAttack(sess, model, features, eps, FLAGS.att_steps, mu, adj,
                   FLAGS.perturb_ratio)
for n in range(FLAGS.train_steps):
    print(
        '\n\n============================= iteration {}/{} =============================='
        .format(n + 1, FLAGS.train_steps))
    print('TRAIN')

    train_label = attack_label
    train_label_mask = train_mask + test_mask

    old_adv_support = adv_support[:]
    adv_support = new_adv_support[:]
    print('support diff:', np.sum(old_adv_support[0] - adv_support[0]))
    train_feed_dict = construct_feed_dict(features, adv_support, train_label,
                                          train_label_mask, placeholders)
    train_feed_dict.update({
        placeholders['support'][i]: adv_support[i]
        for i in range(len(adv_support))
    })
    train_feed_dict.update({placeholders['lmd']: lmd})
    train_feed_dict.update({placeholders['dropout']: FLAGS.dropout})
    train_feed_dict.update(
        {placeholders['adj'][i]: adj
         for i in range(num_supports)})  # feed ori adj all the time
    train_feed_dict.update({
        placeholders['s'][i]: np.zeros([n_node, n_node])
        for i in range(num_supports)
    })
    train_label_mask_expand = np.tile(train_label_mask,
                                      [train_label.shape[1], 1]).transpose()
Example #22
0
def main(unused_argv):
    """Main function for running experiments."""
    # Load data
    (train_adj, full_adj, train_feats, test_feats, y_train, y_val, y_test,
     train_mask, val_mask, test_mask, _, val_data, test_data, num_data,
     visible_data) = load_data(FLAGS.data_prefix, FLAGS.dataset, FLAGS.precalc,
                               FLAGS.dataset, FLAGS.graph_dir)

    # Partition graph and do preprocessing
    if FLAGS.bsize > 1:
        parts_file = FLAGS.dataset + "-parts-txt"
        parts_pickle_file = FLAGS.dataset + "-parts-pickle" if (
            FLAGS.dataset != 'None') else FLAGS.custom_data + "-parts-pickle"
        print("parts_pickle_file", parts_pickle_file)
        if False and os.path.exists(parts_pickle_file):
            f = open(parts_pickle_file, 'rb')
            parts = pickle.load(f)
            f.close()
        else:
            _, parts = partition_utils.partition_graph(train_adj, visible_data,
                                                       FLAGS.num_clusters)
            #f = open(parts_pickle_file, 'wb')
            #pickle.dump(parts, f)
            #f.close()

        if not os.path.exists(parts_file):
            with open(parts_file, 'w') as f:
                s = "{"
                part_i = 0
                for part in parts:
                    s += '"%d"' % part_i + ':' + str(part) + "\n"
                    if part_i != len(parts) - 1:
                        s += ','
                    part_i += 1
                f.write(s + "}")

        parts = [np.array(pt) for pt in parts]

    else:
        (parts, features_batches, support_batches, y_train_batches,
         train_mask_batches) = utils.preprocess(train_adj, train_feats,
                                                y_train, train_mask,
                                                visible_data,
                                                FLAGS.num_clusters,
                                                FLAGS.diag_lambda)

    # (_, val_features_batches, val_support_batches, y_val_batches,
    #  val_mask_batches) = utils.preprocess(full_adj, test_feats, y_val, val_mask,
    #                                       np.arange(num_data),
    #                                       FLAGS.num_clusters_val,
    #                                       FLAGS.diag_lambda)

    # (_, test_features_batches, test_support_batches, y_test_batches,
    #  test_mask_batches) = utils.preprocess(full_adj, test_feats, y_test,
    #                                        test_mask, np.arange(num_data),
    #                                        FLAGS.num_clusters_test,
    #                                        FLAGS.diag_lambda)
    idx_parts = list(range(len(parts)))

    # Some preprocessing
    model_func = models.GCN

    # Define placeholders
    placeholders = {
        'support': tf.sparse_placeholder(tf.float32),
        'features': tf.placeholder(tf.float32),
        'labels': tf.placeholder(tf.float32, shape=(None, y_train.shape[1])),
        'labels_mask': tf.placeholder(tf.int32),
        'dropout': tf.placeholder_with_default(0., shape=()),
        'num_features_nonzero':
        tf.placeholder(tf.int32)  # helper variable for sparse dropout
    }

    # Create model
    model = model_func(placeholders,
                       input_dim=test_feats.shape[1],
                       logging=True,
                       multilabel=FLAGS.multilabel,
                       norm=FLAGS.layernorm,
                       precalc=FLAGS.precalc,
                       num_layers=FLAGS.num_layers)

    # Initialize session
    sess = tf.Session()
    tf.set_random_seed(seed)

    # Init variables
    sess.run(tf.global_variables_initializer())
    saver = tf.train.Saver()
    cost_val = []
    total_training_time = 0.0
    sampling_time = 0
    training_time = 0
    extraction_time = 0
    # Train model
    for epoch in range(FLAGS.epochs):
        t = time.time()
        np.random.shuffle(idx_parts)
        if FLAGS.bsize > 1:
            t0 = time.time()
            (features_batches, support_batches, y_train_batches,
             train_mask_batches, t) = utils.preprocess_multicluster(
                 train_adj, parts, train_feats, y_train, train_mask,
                 FLAGS.num_clusters, FLAGS.bsize, FLAGS.diag_lambda)
            t1 = time.time()
            extraction_time += t
            sampling_time += t1 - t0
            for pid in range(len(features_batches)):
                # Use preprocessed batch data
                features_b = features_batches[pid]
                support_b = support_batches[pid]
                y_train_b = y_train_batches[pid]
                train_mask_b = train_mask_batches[pid]
                # Construct feed dictionary
                feed_dict = utils.construct_feed_dict(features_b, support_b,
                                                      y_train_b, train_mask_b,
                                                      placeholders)
                feed_dict.update({placeholders['dropout']: FLAGS.dropout})
                t0 = time.time()
                # Training step
                outs = sess.run([model.opt_op, model.loss, model.accuracy],
                                feed_dict=feed_dict)
                t1 = time.time()
                training_time += t1 - t0
        else:
            np.random.shuffle(idx_parts)
            for pid in idx_parts:
                # Use preprocessed batch data
                features_b = features_batches[pid]
                support_b = support_batches[pid]
                y_train_b = y_train_batches[pid]
                train_mask_b = train_mask_batches[pid]
                # Construct feed dictionary
                feed_dict = utils.construct_feed_dict(features_b, support_b,
                                                      y_train_b, train_mask_b,
                                                      placeholders)
                feed_dict.update({placeholders['dropout']: FLAGS.dropout})
                # Training step
                outs = sess.run([model.opt_op, model.loss, model.accuracy],
                                feed_dict=feed_dict)

        total_training_time += time.time() - t

        print_str = 'Epoch: %04d ' % (
            epoch + 1) + 'training time: {:.5f} '.format(
                total_training_time) + 'train_acc= {:.5f} '.format(outs[2])
    print("sampling_time (clustergcn)", sampling_time)
    print("training_time:", training_time)

    #print(sampling_time,"Total sampling time")
    #print(training_time,"Total training time")
    #print(extraction_time,"Total extraction time")
    #   return
    #   # Validation
    #   if FLAGS.validation:
    #     cost, acc, micro, macro = evaluate(sess, model, val_features_batches,
    #                                        val_support_batches, y_val_batches,
    #                                        val_mask_batches, val_data,
    #                                        placeholders)
    #     cost_val.append(cost)
    #     print_str += 'val_acc= {:.5f} '.format(
    #         acc) + 'mi F1= {:.5f} ma F1= {:.5f} '.format(micro, macro)

    #   tf.logging.info(print_str)

    #   if epoch > FLAGS.early_stopping and cost_val[-1] > np.mean(
    #       cost_val[-(FLAGS.early_stopping + 1):-1]):
    #     tf.logging.info('Early stopping...')
    #     break

    # tf.logging.info('Optimization Finished!')
    return
    # Save model
    saver.save(sess, FLAGS.save_name)

    # Load model (using CPU for inference)
    with tf.device('/cpu:0'):
        sess_cpu = tf.Session(config=tf.ConfigProto(device_count={'GPU': 0}))
        sess_cpu.run(tf.global_variables_initializer())
        saver = tf.train.Saver()
        saver.restore(sess_cpu, FLAGS.save_name)
        # Testing
        test_cost, test_acc, micro, macro = evaluate(
            sess_cpu, model, test_features_batches, test_support_batches,
            y_test_batches, test_mask_batches, test_data, placeholders)
        print_str = 'Test set results: ' + 'cost= {:.5f} '.format(
            test_cost) + 'accuracy= {:.5f} '.format(
                test_acc) + 'mi F1= {:.5f} ma F1= {:.5f}'.format(micro, macro)
        tf.logging.info(print_str)
Example #23
0
# Train model
for epoch in range(FLAGS.epochs):

    t = time.time()

    if epoch >= 20:
        # Generate adversarial examples for adversarial training
        if args.method == 'flip':
            # Flip
            n_flip = 5
            features_dense_adv = features_dense
            for i in range(n_flip):
                features_dense_adv = flip(model=model,
                                          feed_dict=construct_feed_dict(
                                              features_dense_adv, support,
                                              y_test, test_mask, placeholders),
                                          features=features_dense_adv,
                                          sess=sess)

        elif args.method == 'fgsm':
            # FGSM
            epsilon = 0.1
            features_dense_adv = fgsm(model=model,
                                      feed_dict=construct_feed_dict(
                                          features_dense, support, y_test,
                                          test_mask, placeholders),
                                      features=features_dense,
                                      sess=sess,
                                      epsilon=epsilon)
        else:
Example #24
0
def train_model(model_func,
                num_supports,
                support,
                features,
                y_train,
                y_val,
                y_test,
                train_mask,
                val_mask,
                test_mask,
                sub_sampled_support=None,
                VERBOSE_TRAINING=False,
                seed=13,
                list_adj=None):
    if model_func is None:
        return knn_hop(y_train, y_val, y_test, train_mask, val_mask, test_mask,
                       list_adj)

    tf.set_random_seed(seed)
    # Define placeholders
    placeholders = {
        'sub_sampled_support':
        [tf.sparse_placeholder(tf.float32) for _ in range(num_supports)],
        'support':
        [tf.sparse_placeholder(tf.float32) for _ in range(num_supports)],
        'features':
        tf.sparse_placeholder(tf.float32,
                              shape=tf.constant(features[2], dtype=tf.int64)),
        'labels':
        tf.placeholder(tf.float32, shape=(None, y_train.shape[1])),
        'labels_mask':
        tf.placeholder(tf.int32),
        'dropout':
        tf.placeholder_with_default(0., shape=()),
        'num_features_nonzero':
        tf.placeholder(tf.int32)  # helper variable for sparse dropout
    }

    # Create model
    model = model_func(placeholders, input_dim=features[2][1], logging=True)

    # Initialize session
    sess = tf.Session()

    # Define model evaluation function
    def evaluate(features, support, labels, mask, sub_sampled_support,
                 placeholders):
        t_test = time.time()
        feed_dict_val = construct_feed_dict(features, support, labels, mask,
                                            sub_sampled_support, placeholders)
        outs_val = sess.run([model.loss, model.accuracy,
                             model.predict()],
                            feed_dict=feed_dict_val)
        return outs_val[0], outs_val[1], (time.time() - t_test), outs_val[2]

    # Init variables
    sess.run(tf.global_variables_initializer())

    cost_val = []

    # Train model
    for epoch in range(FLAGS.epochs):

        t = time.time()
        # Construct feed dictionary
        feed_dict = construct_feed_dict(features, support, y_train, train_mask,
                                        sub_sampled_support, placeholders)
        feed_dict.update({placeholders['dropout']: FLAGS.dropout})
        # Training step
        outs = sess.run([model.opt_op, model.loss, model.accuracy],
                        feed_dict=feed_dict)
        # Validation
        cost, acc, duration, _ = evaluate(features, support, y_val, val_mask,
                                          sub_sampled_support, placeholders)
        cost_val.append(cost)
        if VERBOSE_TRAINING:
            # Print results
            print("Epoch:", '%04d' % (epoch + 1), "train_loss=",
                  "{:.5f}".format(outs[1]), "train_acc=",
                  "{:.5f}".format(outs[2]), "val_loss=", "{:.5f}".format(cost),
                  "val_acc=", "{:.5f}".format(acc), "time=",
                  "{:.5f}".format(time.time() - t))

        if FLAGS.early_stopping is not None and epoch > FLAGS.early_stopping and cost_val[
                -1] > np.mean(cost_val[-(FLAGS.early_stopping + 1):-1]):
            print("Early stopping...")
            break

    print("Optimization Finished!")

    # Testing
    test_cost, test_acc, test_duration, predicted_labels = evaluate(
        features, support, y_test, test_mask, sub_sampled_support,
        placeholders)
    print("Test set results:", "cost=", "{:.5f}".format(test_cost),
          "accuracy=", "{:.5f}".format(test_acc), "time=",
          "{:.5f}".format(test_duration))
    labels_equal = (np.equal(np.argmax(predicted_labels, axis=1),
                             np.argmax(y_test, axis=1)))
    list_node_correctly_classified = np.argwhere(labels_equal).reshape(-1)
    list_node_correctly_classified_test = list(
        filter(lambda x: test_mask[x], list(list_node_correctly_classified)))
    tf.reset_default_graph()
    return test_acc, list_node_correctly_classified_test
def run(seed, gamma, beta, hidden, lr, NB_EPOCH=300):
    """
    Main function. Run the architecture for the initialization defined by seed and by the hyperparameters gamma, beta, hidden, lr
    Inputs:
        seed : seed to defined the initialization of the training/testing/validation split,
        gamma, beta, hidden, lr: hyperparameters of the architecture
        NB_EPOCH: number of runs to do of the same architecture with different weight initializations. Default: 1000
    Outputs:
        auc_test, auc_train, auc_val: AUC on the test, train and validation sets
    """
    tf.reset_default_graph()
    training_set_mask, testing_set_mask, idx_training, idx_testing = preprocessing_dataset.split_train_test(
        0.8, M_str, seed, labels)
    #create a training and test mask on the data
    Otraining = preprocessing_dataset.load_mask(training_set_mask, M_str,
                                                nrRows, nrCols)
    Otest = preprocessing_dataset.load_mask(testing_set_mask, M_str, nrRows,
                                            nrCols)

    new_labels_train = np.copy(labels)
    new_labels_train[idx_testing] = -1
    #split train set into 4 parts to create a validation set
    training_set_mask, validation_set_mask, idx_training, idx_validation = preprocessing_dataset.split_train_validation_4(
        3, M_str, seed, new_labels_train)
    Otraining = preprocessing_dataset.load_mask(training_set_mask, M_str,
                                                nrRows, nrCols)
    Ovalidation = preprocessing_dataset.load_mask(validation_set_mask, M_str,
                                                  nrRows, nrCols)

    Otraining = np.concatenate((Otraining, training_set_mask), axis=1)
    Ocol = np.zeros((Otest.shape[0], 1))
    Otest_support = np.concatenate((Otest, Ocol), axis=1)
    Ovalidation_support = np.concatenate((Ovalidation, Ocol), axis=1)
    Osupport_t = Otraining + Otest_support + Ovalidation_support
    Ovalidation = np.concatenate((Ovalidation, validation_set_mask), axis=1)
    Otest = np.concatenate((Otest, testing_set_mask), axis=1)

    u_features, v_features, train_labels, train_u_indices, train_v_indices, val_labels, val_u_indices, val_v_indices, test_labels, test_u_indices, test_v_indices = load_data_monti_tadpole(
        M, Otraining, Otest, Ovalidation)

    m, n = M.shape

    # global normalization
    support = []
    support_t = []

    path_support_women = "women_synth_noteasy.csv"
    women_support, _, _ = read_tadpole.load_csv_no_header(path_support_women)
    women_support = preprocessing_dataset.str_to_float(women_support)
    women_support = women_support * M_sup
    women_support = sp.csr_matrix(women_support, dtype=np.float32)
    support.append(women_support)
    support_t.append(women_support.T)

    path_support_men = "men_synth_noteasy.csv"
    men_support, _, _ = read_tadpole.load_csv_no_header(path_support_men)
    men_support = preprocessing_dataset.str_to_float(men_support)
    men_support = men_support * M_sup
    men_support = sp.csr_matrix(men_support, dtype=np.float32)
    support.append(men_support)
    support_t.append(men_support.T)

    path_support_women_84 = "age_84_92_women_synth_noteasy.csv"
    women_84_support, _, _ = read_tadpole.load_csv_no_header(
        path_support_women_84)
    women_84_support = preprocessing_dataset.str_to_float(women_84_support)
    women_84_support = women_84_support * M_sup
    women_84_support = sp.csr_matrix(women_84_support, dtype=np.float32)
    support.append(women_84_support)
    support_t.append(women_84_support.T)

    path_support_men_84 = "age_84_92_men_synth_noteasy.csv"
    men_84_support, _, _ = read_tadpole.load_csv_no_header(path_support_men_84)
    men_84_support = preprocessing_dataset.str_to_float(men_84_support)
    men_84_support = men_84_support * M_sup
    men_84_support = sp.csr_matrix(men_84_support, dtype=np.float32)
    support.append(men_84_support)
    support_t.append(men_84_support.T)

    path_support_84 = "age_84_92_synth_noteasy.csv"
    age84_support, _, _ = read_tadpole.load_csv_no_header(path_support_84)
    age84_support = preprocessing_dataset.str_to_float(age84_support)
    age84_support = age84_support * M_sup
    age84_support = sp.csr_matrix(age84_support, dtype=np.float32)
    support.append(age84_support)
    support_t.append(age84_support.T)

    path_support_women_79 = "age_79_84_women_synth_noteasy.csv"
    women_79_support, _, _ = read_tadpole.load_csv_no_header(
        path_support_women_79)
    women_79_support = preprocessing_dataset.str_to_float(women_79_support)
    women_79_support = women_79_support * M_sup
    women_79_support = sp.csr_matrix(women_79_support, dtype=np.float32)
    support.append(women_79_support)
    support_t.append(women_79_support.T)

    path_support_men_79 = "age_79_84_men_synth_noteasy.csv"
    men_79_support, _, _ = read_tadpole.load_csv_no_header(path_support_men_79)
    men_79_support = preprocessing_dataset.str_to_float(men_79_support)
    men_79_support = men_79_support * M_sup
    men_79_support = sp.csr_matrix(men_79_support, dtype=np.float32)
    support.append(men_79_support)
    support_t.append(men_79_support.T)

    path_support_79 = "age_79_84_synth_noteasy.csv"
    age79_support, _, _ = read_tadpole.load_csv_no_header(path_support_79)
    age79_support = preprocessing_dataset.str_to_float(age79_support)
    age79_support = age79_support * M_sup
    age79_support = sp.csr_matrix(age79_support, dtype=np.float32)
    support.append(age79_support)
    support_t.append(age79_support.T)

    path_support_women_74 = "age_74_79_women_synth_noteasy.csv"
    women_74_support, _, _ = read_tadpole.load_csv_no_header(
        path_support_women_74)
    women_74_support = preprocessing_dataset.str_to_float(women_74_support)
    women_74_support = women_74_support * M_sup
    women_74_support = sp.csr_matrix(women_74_support, dtype=np.float32)
    support.append(women_74_support)
    support_t.append(women_74_support.T)

    path_support_men_74 = "age_74_79_men_synth_noteasy.csv"
    men_74_support, _, _ = read_tadpole.load_csv_no_header(path_support_men_74)
    men_74_support = preprocessing_dataset.str_to_float(men_74_support)
    men_74_support = men_74_support * M_sup
    men_74_support = sp.csr_matrix(men_74_support, dtype=np.float32)
    support.append(men_74_support)
    support_t.append(men_74_support.T)

    path_support_74 = "age_74_79_synth_noteasy.csv"
    age74_support, _, _ = read_tadpole.load_csv_no_header(path_support_74)
    age74_support = preprocessing_dataset.str_to_float(age74_support)
    age74_support = age74_support * M_sup
    age74_support = sp.csr_matrix(age74_support, dtype=np.float32)
    support.append(age74_support)
    support_t.append(age74_support.T)

    path_support_women_69 = "age_69_74_women_synth_noteasy.csv"
    women_69_support, _, _ = read_tadpole.load_csv_no_header(
        path_support_women_69)
    women_69_support = preprocessing_dataset.str_to_float(women_69_support)
    women_69_support = women_69_support * M_sup
    women_69_support = sp.csr_matrix(women_69_support, dtype=np.float32)
    support.append(women_69_support)
    support_t.append(women_69_support.T)

    path_support_men_69 = "age_69_74_men_synth_noteasy.csv"
    men_69_support, _, _ = read_tadpole.load_csv_no_header(path_support_men_69)
    men_69_support = preprocessing_dataset.str_to_float(men_69_support)
    men_69_support = men_69_support * M_sup
    men_69_support = sp.csr_matrix(men_69_support, dtype=np.float32)
    support.append(men_69_support)
    support_t.append(men_69_support.T)

    path_support_69 = "age_69_74_synth_noteasy.csv"
    age69_support, _, _ = read_tadpole.load_csv_no_header(path_support_69)
    age69_support = preprocessing_dataset.str_to_float(age69_support)
    age69_support = age69_support * M_sup
    age69_support = sp.csr_matrix(age69_support, dtype=np.float32)
    support.append(age69_support)
    support_t.append(age69_support.T)

    path_support_women_64 = "age_64_69_women_synth_noteasy.csv"
    women_64_support, _, _ = read_tadpole.load_csv_no_header(
        path_support_women_64)
    women_64_support = preprocessing_dataset.str_to_float(women_64_support)
    women_64_support = women_64_support * M_sup
    women_64_support = sp.csr_matrix(women_64_support, dtype=np.float32)
    support.append(women_64_support)
    support_t.append(women_64_support.T)

    path_support_men_64 = "age_64_69_men_synth_noteasy.csv"
    men_64_support, _, _ = read_tadpole.load_csv_no_header(path_support_men_64)
    men_64_support = preprocessing_dataset.str_to_float(men_64_support)
    men_64_support = men_64_support * M_sup
    men_64_support = sp.csr_matrix(men_64_support, dtype=np.float32)
    support.append(men_64_support)
    support_t.append(men_64_support.T)

    path_support_64 = "age_64_69_synth_noteasy.csv"
    age64_support, _, _ = read_tadpole.load_csv_no_header(path_support_64)
    age64_support = preprocessing_dataset.str_to_float(age64_support)
    age64_support = age64_support * M_sup
    age64_support = sp.csr_matrix(age64_support, dtype=np.float32)
    support.append(age64_support)
    support_t.append(age64_support.T)

    path_support_women_59 = "age_59_64_women_synth_noteasy.csv"
    women_59_support, _, _ = read_tadpole.load_csv_no_header(
        path_support_women_59)
    women_59_support = preprocessing_dataset.str_to_float(women_59_support)
    women_59_support = women_59_support * M_sup
    women_59_support = sp.csr_matrix(women_59_support, dtype=np.float32)
    support.append(women_59_support)
    support_t.append(women_59_support.T)

    path_support_men_59 = "age_59_64_men_synth_noteasy.csv"
    men_59_support, _, _ = read_tadpole.load_csv_no_header(path_support_men_59)
    men_59_support = preprocessing_dataset.str_to_float(men_59_support)
    men_59_support = men_59_support * M_sup
    men_59_support = sp.csr_matrix(men_59_support, dtype=np.float32)
    support.append(men_59_support)
    support_t.append(men_59_support.T)

    path_support_59 = "age_59_64_synth_noteasy.csv"
    age59_support, _, _ = read_tadpole.load_csv_no_header(path_support_59)
    age59_support = preprocessing_dataset.str_to_float(age59_support)
    age59_support = age59_support * M_sup
    age59_support = sp.csr_matrix(age59_support, dtype=np.float32)
    support.append(age59_support)
    support_t.append(age59_support.T)

    path_support_women_54 = "age_54_59_women_synth_noteasy.csv"
    women_54_support, _, _ = read_tadpole.load_csv_no_header(
        path_support_women_54)
    women_54_support = preprocessing_dataset.str_to_float(women_54_support)
    women_54_support = women_54_support * M_sup
    women_54_support = sp.csr_matrix(women_54_support, dtype=np.float32)
    support.append(women_54_support)
    support_t.append(women_54_support.T)

    path_support_men_54 = "age_54_59_men_synth_noteasy.csv"
    men_54_support, _, _ = read_tadpole.load_csv_no_header(path_support_men_54)
    men_54_support = preprocessing_dataset.str_to_float(men_54_support)
    men_54_support = men_54_support * M_sup
    men_54_support = sp.csr_matrix(men_54_support, dtype=np.float32)
    support.append(men_54_support)
    support_t.append(men_54_support.T)

    path_support_54 = "age_54_59_synth_noteasy.csv"
    age54_support, _, _ = read_tadpole.load_csv_no_header(path_support_54)
    age54_support = preprocessing_dataset.str_to_float(age54_support)
    age54_support = age54_support * M_sup
    age54_support = sp.csr_matrix(age54_support, dtype=np.float32)
    support.append(age54_support)
    support_t.append(age54_support.T)

    num_support = len(support)
    mask_support_t = []
    Osupport_t = sp.csr_matrix(Osupport_t, dtype=np.int)
    for i in range(num_support):
        mask_support_t.append(Osupport_t.T)

    mask_support_t = sp.hstack(mask_support_t, format='csr')

    support = sp.hstack(support, format='csr')
    support_t = sp.hstack(support_t, format='csr')

    # Collect all user and item nodes for test set
    test_u = list(set(test_u_indices))
    test_v = list(set(test_v_indices))
    test_u_dict = {n: i for i, n in enumerate(test_u)}
    test_v_dict = {n: i for i, n in enumerate(test_v)}

    test_u_indices = np.array([test_u_dict[o] for o in test_u_indices])
    test_v_indices = np.array([test_v_dict[o] for o in test_v_indices])
    test_support = support[np.array(test_u)]
    for i in range(test_support.shape[0]):
        for j in range(563, test_support.shape[1], 564):
            test_support[i, j] = 0.0
    test_support_t = sp.csr_matrix.multiply(support_t, mask_support_t)

    # Collect all user and item nodes for validation set
    val_u = list(set(val_u_indices))
    val_v = list(set(val_v_indices))
    val_u_dict = {n: i for i, n in enumerate(val_u)}
    val_v_dict = {n: i for i, n in enumerate(val_v)}

    val_u_indices = np.array([val_u_dict[o] for o in val_u_indices])
    val_v_indices = np.array([val_v_dict[o] for o in val_v_indices])
    val_support = support[np.array(val_u)]
    for i in range(val_support.shape[0]):
        for j in range(563, val_support.shape[1], 564):
            val_support[i, j] = 0.0
    val_support_t = sp.csr_matrix.multiply(support_t, mask_support_t)

    # Collect all user and item nodes for train set
    train_u = list(set(train_u_indices))
    train_v = list(set(train_v_indices))
    train_u_dict = {n: i for i, n in enumerate(train_u)}
    train_v_dict = {n: i for i, n in enumerate(train_v)}

    train_u_indices = np.array([train_u_dict[o] for o in train_u_indices])
    train_v_indices = np.array([train_v_dict[o] for o in train_v_indices])
    train_support = support[np.array(train_u)]
    train_support_t = sp.csr_matrix.multiply(support_t, mask_support_t)

    placeholders = {
        'u_features':
        tf.sparse_placeholder(tf.float32,
                              shape=np.array(u_features.shape,
                                             dtype=np.int64)),
        'v_features':
        tf.sparse_placeholder(tf.float32,
                              shape=np.array(v_features.shape,
                                             dtype=np.int64)),
        'u_features_nonzero':
        tf.placeholder(tf.int32, shape=()),
        'v_features_nonzero':
        tf.placeholder(tf.int32, shape=()),
        'labels':
        tf.placeholder(tf.float32, shape=(None, )),
        'indices_labels':
        tf.placeholder(tf.int32, shape=(None, )),
        'user_indices':
        tf.placeholder(tf.int32, shape=(None, )),
        'item_indices':
        tf.placeholder(tf.int32, shape=(None, )),
        'dropout':
        tf.placeholder_with_default(0., shape=()),
        'weight_decay':
        tf.placeholder_with_default(0., shape=()),
        'support':
        tf.sparse_placeholder(tf.float32, shape=(None, None)),
        'support_t':
        tf.sparse_placeholder(tf.float32, shape=(None, None)),
    }
    div = hidden[0] // num_support
    if hidden[0] % num_support != 0:
        print(
            """\nWARNING: HIDDEN[0] (=%d) of stack layer is adjusted to %d such that
                      it can be evenly split in %d splits.\n""" %
            (hidden[0], num_support * div, num_support))
    hidden[0] = num_support * div

    # create model
    model = MG_GAE(placeholders,
                   input_dim=u_features.shape[1],
                   num_support=num_support,
                   hidden=hidden,
                   num_users=m,
                   num_items=n,
                   learning_rate=lr,
                   gamma=gamma,
                   beta=beta,
                   logging=True)

    # Convert sparse placeholders to tuples to construct feed_dict
    test_support = sparse_to_tuple(test_support)
    test_support_t = sparse_to_tuple(test_support_t)

    val_support = sparse_to_tuple(val_support)
    val_support_t = sparse_to_tuple(val_support_t)

    train_support = sparse_to_tuple(train_support)
    train_support_t = sparse_to_tuple(train_support_t)

    u_features = sparse_to_tuple(u_features)
    v_features = sparse_to_tuple(v_features)

    assert u_features[2][1] == v_features[2][
        1], 'Number of features of users and items must be the same!'

    num_features = u_features[2][1]
    u_features_nonzero = u_features[1].shape[0]
    v_features_nonzero = v_features[1].shape[0]

    indices_labels = [563] * train_labels.shape[0]
    indices_labels_val = [563] * val_labels.shape[0]
    indices_labels_test = [563] * test_labels.shape[0]

    # Feed_dicts for validation and test set stay constant over different update steps
    train_feed_dict = construct_feed_dict(placeholders, u_features, v_features,
                                          u_features_nonzero,
                                          v_features_nonzero, train_support,
                                          train_support_t, train_labels,
                                          indices_labels, train_u_indices,
                                          train_v_indices, 0.)
    # No dropout for validation and test runs
    val_feed_dict = construct_feed_dict(placeholders, u_features, v_features,
                                        u_features_nonzero, v_features_nonzero,
                                        val_support, val_support_t, val_labels,
                                        indices_labels_val, val_u_indices,
                                        val_v_indices, 0.)

    test_feed_dict = construct_feed_dict(placeholders, u_features, v_features,
                                         u_features_nonzero,
                                         v_features_nonzero, test_support,
                                         test_support_t, test_labels,
                                         indices_labels_test, test_u_indices,
                                         test_v_indices, 0.)

    # Collect all variables to be logged into summary
    merged_summary = tf.summary.merge_all()

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    auc_train = []
    auc_test = []
    auc_val = []
    test_pred = []
    for epoch in range(NB_EPOCH):

        t = time.time()

        # Run single weight update
        outs = sess.run([
            model.training_op, model.loss, model.indices, model.labels,
            model.outputs, model.labels_class, model.classification,
            model.inputs, model.gcn_u, model.gcn_v, model.loss_frob,
            model.binary_entropy, model.u_inputs, model.v_inputs, model.weight,
            model.input_u, model.input_v, model.u_indices, model.v_indices
        ],
                        feed_dict=train_feed_dict)
        train_avg_loss = outs[1]
        label_train = outs[5]
        output_train = outs[6]

        fpr_train, tpr_train, thresholds_train = roc_curve(
            label_train, output_train, pos_label=label_train.max())
        roc_auc_train = auc(fpr_train, tpr_train)
        auc_train.append(roc_auc_train)

        val_avg_loss, val_classification, val_labels_corres = sess.run(
            [model.loss, model.classification, model.labels_class],
            feed_dict=val_feed_dict)  #test_feed_dict)#
        fpr_val, tpr_val, thresholds_train = roc_curve(
            val_labels_corres, val_classification, pos_label=label_train.max())
        roc_auc_val = auc(fpr_val, tpr_val)
        auc_val.append(roc_auc_val)

        test_avg_loss, test_classification, test_labels_corres = sess.run(
            [model.loss, model.classification, model.labels_class],
            feed_dict=test_feed_dict)
        fpr_test, tpr_test, thresholds_test = roc_curve(
            test_labels_corres,
            test_classification,
            pos_label=label_train.max())
        roc_auc_test = auc(fpr_test, tpr_test)
        auc_test.append(roc_auc_test)
        test_pred.append(test_classification)
        if VERBOSE:
            print("[*] Epoch:", '%04d' % (epoch + 1), "train_loss=",
                  "{:.5f}".format(train_avg_loss), "train_auc=",
                  "{:.5f}".format(roc_auc_train), "val_loss=",
                  "{:.5f}".format(val_avg_loss), "val_auc=",
                  "{:.5f}".format(roc_auc_val), "\t\ttime=",
                  "{:.5f}".format(time.time() - t))
            print('test auc = ', roc_auc_test)

    sess.close()

    return auc_test, auc_train, auc_val
Example #26
0
        num_edges=num_edges)


# Initialize session
sess = tf.Session()
sess.run(tf.global_variables_initializer())

adj_label = adj_train + sp.eye(adj_train.shape[0])
adj_label = sparse_to_tuple(adj_label)

# Train model
for epoch in range(FLAGS.epochs):
    t = time.time()
    # Construct feed dictionary
    # placeholdersに代入する辞書作り
    feed_dict = construct_feed_dict(adj_norm, adj_label, features, placeholders)
    feed_dict.update({placeholders['dropout']: FLAGS.dropout})
    # One update of parameter matrices
    _, avg_cost = sess.run([opt.opt_op, opt.cost], feed_dict=feed_dict)  # optimizeして, コスト関数を出力
    # Performance on validation set
    roc_curr, ap_curr = get_roc_score(val_edges, val_edges_false)  # ただ各エポックで精度を見るためだけのもの

    print("Epoch:", '%04d' % (epoch + 1),
          "train_loss=", "{:.5f}".format(avg_cost),
          "val_roc=", "{:.5f}".format(roc_curr),
          "val_ap=", "{:.5f}".format(ap_curr),
          "time=", "{:.5f}".format(time.time() - t))

print('Optimization Finished!')

roc_score, ap_score = get_roc_score(test_edges, test_edges_false)
Example #27
0
def main(unused_argv):
  """Main function for running experiments."""
  # Load data
  (train_adj, full_adj, train_feats, test_feats, y_train, y_val, y_test,
   train_mask, val_mask, test_mask, _, val_data, test_data, num_data,
   visible_data) = load_data(FLAGS.data_prefix, FLAGS.dataset, FLAGS.precalc)

  # Partition graph and do preprocessing
  if FLAGS.bsize > 1:
    _, parts = partition_utils.partition_graph(train_adj, visible_data,
                                               FLAGS.num_clusters)
    parts = [np.array(pt) for pt in parts]
  else:
    (parts, features_batches, support_batches, y_train_batches,
     train_mask_batches) = utils.preprocess(train_adj, train_feats, y_train,
                                            train_mask, visible_data,
                                            FLAGS.num_clusters,
                                            FLAGS.diag_lambda)

  (_, val_features_batches, val_support_batches, y_val_batches,
   val_mask_batches) = utils.preprocess(full_adj, test_feats, y_val, val_mask,
                                        np.arange(num_data),
                                        FLAGS.num_clusters_val,
                                        FLAGS.diag_lambda)

  (_, test_features_batches, test_support_batches, y_test_batches,
   test_mask_batches) = utils.preprocess(full_adj, test_feats, y_test,
                                         test_mask, np.arange(num_data),
                                         FLAGS.num_clusters_test,
                                         FLAGS.diag_lambda)
  idx_parts = list(range(len(parts)))

  # Some preprocessing
  model_func = models.GCN

  # Define placeholders
  placeholders = {
      'support':
          tf.sparse_placeholder(tf.float32),
      'features':
          tf.placeholder(tf.float32),
      'labels':
          tf.placeholder(tf.float32, shape=(None, y_train.shape[1])),
      'labels_mask':
          tf.placeholder(tf.int32),
      'dropout':
          tf.placeholder_with_default(0., shape=()),
      'num_features_nonzero':
          tf.placeholder(tf.int32)  # helper variable for sparse dropout
  }

  # Create model
  model = model_func(
      placeholders,
      input_dim=test_feats.shape[1],
      logging=True,
      multilabel=FLAGS.multilabel,
      norm=FLAGS.layernorm,
      precalc=FLAGS.precalc,
      num_layers=FLAGS.num_layers)

  # Initialize session
  sess = tf.Session()
  tf.set_random_seed(seed)

  # Init variables
  sess.run(tf.global_variables_initializer())
  saver = tf.train.Saver()
  cost_val = []
  total_training_time = 0.0
  # Train model
  for epoch in range(FLAGS.epochs):
    t = time.time()
    np.random.shuffle(idx_parts)
    if FLAGS.bsize > 1:
      (features_batches, support_batches, y_train_batches,
       train_mask_batches) = utils.preprocess_multicluster(
           train_adj, parts, train_feats, y_train, train_mask,
           FLAGS.num_clusters, FLAGS.bsize, FLAGS.diag_lambda)
      for pid in range(len(features_batches)):
        # Use preprocessed batch data
        features_b = features_batches[pid]
        support_b = support_batches[pid]
        y_train_b = y_train_batches[pid]
        train_mask_b = train_mask_batches[pid]
        # Construct feed dictionary
        feed_dict = utils.construct_feed_dict(features_b, support_b, y_train_b,
                                              train_mask_b, placeholders)
        feed_dict.update({placeholders['dropout']: FLAGS.dropout})
        # Training step
        outs = sess.run([model.opt_op, model.loss, model.accuracy],
                        feed_dict=feed_dict)
    else:
      np.random.shuffle(idx_parts)
      for pid in idx_parts:
        # Use preprocessed batch data
        features_b = features_batches[pid]
        support_b = support_batches[pid]
        y_train_b = y_train_batches[pid]
        train_mask_b = train_mask_batches[pid]
        # Construct feed dictionary
        feed_dict = utils.construct_feed_dict(features_b, support_b, y_train_b,
                                              train_mask_b, placeholders)
        feed_dict.update({placeholders['dropout']: FLAGS.dropout})
        # Training step
        outs = sess.run([model.opt_op, model.loss, model.accuracy],
                        feed_dict=feed_dict)

    total_training_time += time.time() - t
    print_str = 'Epoch: %04d ' % (epoch + 1) + 'training time: {:.5f} '.format(
        total_training_time) + 'train_acc= {:.5f} '.format(outs[2])

    # Validation
    if FLAGS.validation:
      cost, acc, micro, macro = evaluate(sess, model, val_features_batches,
                                         val_support_batches, y_val_batches,
                                         val_mask_batches, val_data,
                                         placeholders)
      cost_val.append(cost)
      print_str += 'val_acc= {:.5f} '.format(
          acc) + 'mi F1= {:.5f} ma F1= {:.5f} '.format(micro, macro)

    tf.logging.info(print_str)

    if epoch > FLAGS.early_stopping and cost_val[-1] > np.mean(
        cost_val[-(FLAGS.early_stopping + 1):-1]):
      tf.logging.info('Early stopping...')
      break

  tf.logging.info('Optimization Finished!')

  # Save model
  saver.save(sess, FLAGS.save_name)

  # Load model (using CPU for inference)
  with tf.device('/cpu:0'):
    sess_cpu = tf.Session(config=tf.ConfigProto(device_count={'GPU': 0}))
    sess_cpu.run(tf.global_variables_initializer())
    saver = tf.train.Saver()
    saver.restore(sess_cpu, FLAGS.save_name)
    # Testing
    test_cost, test_acc, micro, macro = evaluate(
        sess_cpu, model, test_features_batches, test_support_batches,
        y_test_batches, test_mask_batches, test_data, placeholders)
    print_str = 'Test set results: ' + 'cost= {:.5f} '.format(
        test_cost) + 'accuracy= {:.5f} '.format(
            test_acc) + 'mi F1= {:.5f} ma F1= {:.5f}'.format(micro, macro)
    tf.logging.info(print_str)
Example #28
0
test_support = sparse_to_tuple(test_support)
test_support_t = sparse_to_tuple(test_support_t)

u_features = sparse_to_tuple(u_features)
v_features = sparse_to_tuple(v_features)
assert u_features[2][1] == v_features[2][
    1], 'Number of features of users and items must be the same!'

num_features = u_features[2][1]
u_features_nonzero = u_features[1].shape[0]
v_features_nonzero = v_features[1].shape[0]

# No dropout for test runs
test_feed_dict = construct_feed_dict(placeholders, u_features, v_features,
                                     u_features_nonzero, v_features_nonzero,
                                     test_support, test_support_t, test_labels,
                                     test_u_indices, test_v_indices,
                                     class_values, 0., test_u_features_side,
                                     test_v_features_side)

sess = tf.Session()
sess.run(tf.global_variables_initializer())

model.load(sess)

# store model including exponential moving averages
saver = tf.train.Saver()
save_path = saver.save(sess,
                       "models/%s.ckpt" % model.name,
                       global_step=model.global_step)

# test_avg_loss, test_rmse = sess.run([model.loss, model.rmse], feed_dict=test_feed_dict)
Example #29
0
def test_amazon(args):
    args = namedtuple("Args", args.keys())(*args.values())

    load_from = args.load_from
    config_file = load_from + '/results.json'
    log_file = load_from + '/log.json'

    with open(config_file) as f:
        config = json.load(f)
    with open(log_file) as f:
        log = json.load(f)

    NUMCLASSES = 2
    BN_AS_TRAIN = False
    ADJ_SELF_CONNECTIONS = True

    # evaluate in the specified version
    print("Trained with {}, evaluating with {}".format(config['amz_data'],
                                                       args.amz_data))
    cat_rel = args.amz_data
    dp = DataLoaderAmazon(cat_rel=cat_rel)
    train_features, adj_train, train_labels, train_r_indices, train_c_indices = dp.get_phase(
        'train')
    _, adj_val, val_labels, val_r_indices, val_c_indices = dp.get_phase(
        'valid')
    _, adj_test, test_labels, test_r_indices, test_c_indices = dp.get_phase(
        'test')
    full_adj = dp.adj

    def norm_adj(adj_to_norm):
        return normalize_nonsym_adj(adj_to_norm)

    train_features, mean, std = dp.normalize_features(train_features,
                                                      get_moments=True)

    train_support = get_degree_supports(adj_train,
                                        config['degree'],
                                        adj_self_con=ADJ_SELF_CONNECTIONS)
    val_support = get_degree_supports(adj_val,
                                      config['degree'],
                                      adj_self_con=ADJ_SELF_CONNECTIONS)
    test_support = get_degree_supports(adj_test,
                                       config['degree'],
                                       adj_self_con=ADJ_SELF_CONNECTIONS)

    for i in range(1, len(train_support)):
        train_support[i] = norm_adj(train_support[i])
        val_support[i] = norm_adj(val_support[i])
        test_support[i] = norm_adj(test_support[i])

    num_support = len(train_support)

    num_support = len(train_support)
    placeholders = {
        'row_indices':
        tf.compat.v1.placeholder(tf.int32, shape=(None, )),
        'col_indices':
        tf.compat.v1.placeholder(tf.int32, shape=(None, )),
        'dropout':
        tf.compat.v1.placeholder_with_default(0., shape=()),
        'weight_decay':
        tf.compat.v1.placeholder_with_default(0., shape=()),
        'is_train':
        tf.compat.v1.placeholder_with_default(True, shape=()),
        'support': [
            tf.compat.v1.sparse_placeholder(tf.float32, shape=(None, None))
            for sup in range(num_support)
        ],
        'node_features':
        tf.compat.v1.placeholder(tf.float32, shape=(None, None)),
        'labels':
        tf.compat.v1.placeholder(tf.float32, shape=(None, ))
    }

    model = CompatibilityGAE(placeholders,
                             input_dim=train_features.shape[1],
                             num_classes=NUMCLASSES,
                             num_support=num_support,
                             hidden=config['hidden'],
                             learning_rate=config['learning_rate'],
                             logging=True,
                             batch_norm=config['batch_norm'])

    train_feed_dict = construct_feed_dict(placeholders, train_features,
                                          train_support, train_labels,
                                          train_r_indices, train_c_indices,
                                          config['dropout'])
    # No dropout for validation and test runs
    val_feed_dict = construct_feed_dict(placeholders,
                                        train_features,
                                        val_support,
                                        val_labels,
                                        val_r_indices,
                                        val_c_indices,
                                        0.,
                                        is_train=BN_AS_TRAIN)
    test_feed_dict = construct_feed_dict(placeholders,
                                         train_features,
                                         test_support,
                                         test_labels,
                                         test_r_indices,
                                         test_c_indices,
                                         0.,
                                         is_train=BN_AS_TRAIN)

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

    with tf.compat.v1.Session() as sess:
        saver.restore(sess, load_from + '/' + 'best_epoch.ckpt')

        val_avg_loss, val_acc, conf, pred = sess.run(
            [model.loss, model.accuracy, model.confmat,
             model.predict()],
            feed_dict=val_feed_dict)

        print("val_loss=", "{:.5f}".format(val_avg_loss), "val_acc=",
              "{:.5f}".format(val_acc))

        test_avg_loss, test_acc, conf = sess.run(
            [model.loss, model.accuracy, model.confmat],
            feed_dict=test_feed_dict)

        print("test_loss=", "{:.5f}".format(test_avg_loss), "test_acc=",
              "{:.5f}".format(test_acc))

        # rerun for K=0 (all in parallel)
        k_0_adj = sp.csr_matrix(adj_val.shape)
        k_0_support = get_degree_supports(k_0_adj,
                                          config['degree'],
                                          adj_self_con=ADJ_SELF_CONNECTIONS,
                                          verbose=False)
        for i in range(1, len(k_0_support)):
            k_0_support[i] = norm_adj(k_0_support[i])
        k_0_support = [sparse_to_tuple(sup) for sup in k_0_support]

        k_0_val_feed_dict = construct_feed_dict(placeholders,
                                                train_features,
                                                k_0_support,
                                                val_labels,
                                                val_r_indices,
                                                val_c_indices,
                                                0.,
                                                is_train=BN_AS_TRAIN)
        k_0_test_feed_dict = construct_feed_dict(placeholders,
                                                 train_features,
                                                 k_0_support,
                                                 test_labels,
                                                 test_r_indices,
                                                 test_c_indices,
                                                 0.,
                                                 is_train=BN_AS_TRAIN)

        val_avg_loss, val_acc, conf, pred = sess.run(
            [model.loss, model.accuracy, model.confmat,
             model.predict()],
            feed_dict=k_0_val_feed_dict)
        print("for k=0 val_loss=", "{:.5f}".format(val_avg_loss),
              "for k=0 val_acc=", "{:.5f}".format(val_acc))

        test_avg_loss, test_acc, conf = sess.run(
            [model.loss, model.accuracy, model.confmat],
            feed_dict=k_0_test_feed_dict)
        print("for k=0 test_loss=", "{:.5f}".format(test_avg_loss),
              "for k=0 test_acc=", "{:.5f}".format(test_acc))

        K = args.k

        available_adj = dp.full_valid_adj + dp.full_train_adj
        available_adj = available_adj.tolil()
        for r, c in zip(test_r_indices, test_c_indices):
            available_adj[r, c] = 0
            available_adj[c, r] = 0
        available_adj = available_adj.tocsr()
        available_adj.eliminate_zeros()

        G = Graph(available_adj)
        get_edges_func = G.run_K_BFS

        new_adj = sp.csr_matrix(full_adj.shape)
        new_adj = new_adj.tolil()
        for r, c in zip(test_r_indices, test_c_indices):
            before = time.time()
            if K > 0:  #expand the edges
                nodes_to_expand = [r, c]
                for node in nodes_to_expand:
                    edges = get_edges_func(node, K)
                    for edge in edges:
                        i, j = edge
                        new_adj[i, j] = 1
                        new_adj[j, i] = 1

        new_adj = new_adj.tocsr()

        new_support = get_degree_supports(new_adj,
                                          config['degree'],
                                          adj_self_con=ADJ_SELF_CONNECTIONS,
                                          verbose=False)
        for i in range(1, len(new_support)):
            new_support[i] = norm_adj(new_support[i])
        new_support = [sparse_to_tuple(sup) for sup in new_support]

        new_feed_dict = construct_feed_dict(placeholders,
                                            train_features,
                                            new_support,
                                            test_labels,
                                            test_r_indices,
                                            test_c_indices,
                                            0.,
                                            is_train=BN_AS_TRAIN)

        loss, acc = sess.run([model.loss, model.accuracy],
                             feed_dict=new_feed_dict)

        print("for k={} test_acc=".format(K), "{:.5f}".format(acc))

    print('Best val score saved in log: {}'.format(config['best_val_score']))
    print('Last val score saved in log: {}'.format(log['val']['acc'][-1]))
Example #30
0
def exp(dataset, data_seed, init_seed):
    '''
    dataset - name of dataset
    data_seed - data_seed corresponds to train/dev/test split
    init_seed - seed for initializing NN weights
    '''
    print('running {} on {}'.format(FLAGS.model, dataset))

    tf.reset_default_graph()
    adj, subgraphs, features, labels, train_mask, val_mask, test_mask = load_data(
        dataset, data_seed)
    features = preprocess_features(features)

    # if early_stopping is not used, then put validation data into the testing data
    if FLAGS.early_stop == 0:
        mask = np.logical_or(val_mask, test_mask)
        test_mask = mask
        val_mask = mask

    config = tf.ConfigProto()
    config.graph_options.optimizer_options.global_jit_level = tf.OptimizerOptions.ON_1
    #config.log_device_placement = True
    config.gpu_options.allow_growth = True

    train_loss = []
    train_acc = []
    valid_loss = []
    valid_acc = []
    with tf.Graph().as_default():
        random.seed(init_seed)
        np.random.seed(init_seed)
        tf.set_random_seed(init_seed)

        with tf.Session(config=config) as sess:

            model, support, placeholders = build_model(adj, features,
                                                       labels.shape[1],
                                                       subgraphs)
            sess.run(tf.global_variables_initializer())

            def evaluate(labels_mask, noise=0., dropout=0.):
                feed_dict_val = construct_feed_dict(features, support, labels,
                                                    labels_mask, placeholders,
                                                    noise, dropout)
                outs_val = sess.run([model.loss, model.accuracy],
                                    feed_dict=feed_dict_val)
                return outs_val[0], outs_val[1]

            start_t = time.time()
            for epoch in range(FLAGS.epochs):
                feed_dict = construct_feed_dict(features, support, labels,
                                                train_mask, placeholders,
                                                FLAGS.fisher_noise,
                                                FLAGS.dropout)
                feed_dict.update({tf.keras.backend.learning_phase(): 1})
                outs = sess.run([model.opt_op, model.loss, model.accuracy],
                                feed_dict=feed_dict)
                train_loss.append(outs[1])
                train_acc.append(outs[2])

                # Validation
                outs = evaluate(val_mask)
                valid_loss.append(outs[0])
                valid_acc.append(outs[1])

                if (epoch + 1) % 10 == 0:
                    print("Epoch:", '%04d' % (epoch + 1), "train_loss=",
                          "{:.5f}".format(train_loss[-1]), "train_acc=",
                          "{:.5f}".format(train_acc[-1]), "val_loss=",
                          "{:.5f}".format(valid_loss[-1]), "val_acc=",
                          "{:.5f}".format(valid_acc[-1]))
                    #print( 'perterbation radius:', sess.run( pradius ) )

                if FLAGS.early_stop == 0:
                    if epoch > 10 and (train_loss[-1] > 1.5 * train_loss[0]
                                       or np.isnan(train_loss[-1])):
                        print("Early stopping at epoch {}...".format(epoch))
                        break

                elif FLAGS.early_stop == 1:  # simple early stopping
                    if epoch > 20 and valid_loss[-1] > np.mean( valid_loss[-10:] ) \
                                  and valid_acc[-1] < np.mean( valid_acc[-10:] ):
                        print("Early stopping at epoch {}...".format(epoch))
                        break

                elif FLAGS.early_stop == 2:  # more strict conditions
                    if epoch > 100 \
                        and np.mean( valid_loss[-10:] ) > np.mean( valid_loss[-100:] ) \
                        and np.mean( valid_acc[-10:] ) < np.mean( valid_acc[-100:] ):
                        print("Early stopping at epoch {}...".format(epoch))
                        break
                else:
                    print('unknown early stopping strategy:', FLAGS.early_stop)
                    sys.exit(0)

            test_loss, test_acc = evaluate(test_mask)
            sec_per_epoch = (time.time() - start_t) / epoch
            print("Test set results:", "loss=", "{:.5f}".format(test_loss),
                  "accuracy=", "{:.5f}".format(test_acc), "epoch_secs=",
                  "{:.2f}".format(sec_per_epoch))

    tf.reset_default_graph()

    return {
        'train_loss': train_loss,
        'train_acc': train_acc,
        'valid_loss': valid_loss,
        'valid_acc': valid_acc,
        'test_loss': test_loss,
        'test_acc': test_acc,
    }