# -*- coding: utf-8 -*-
"""
Created on Tue Mar 19 16:26:35 2019

@author: Administrator
"""
# Forked from run_rbf_comparison.py

from __future__ import division
from __future__ import print_function
from __future__ import absolute_import
from __future__ import unicode_literals  

import math
import copy
import numpy as np
import pandas as pd
import sklearn.linear_model as linear_model
import sklearn.preprocessing as preprocessing
import scipy
import scipy.linalg as slin
import scipy.sparse.linalg as sparselin
import scipy.sparse as sparse
import random

import sys
sys.path.append("C:/Tang/influence-release-master")  #设置自定义包的搜索路径

from load_vehicles import load_vehicles

import tensorflow as tf
from tensorflow.contrib.learn.python.learn.datasets import base

from sklearn.metrics.pairwise import rbf_kernel

from influence.inceptionModel import BinaryInceptionModel
from influence.smooth_hinge import SmoothHinge
from influence.binaryLogisticRegressionWithLBFGS import BinaryLogisticRegressionWithLBFGS
import influence.dataset as dataset
from influence.dataset import DataSet
from influence.dataset_poisoning import generate_inception_features

#%%
def get_Y_pred_correct_inception(model):
    Y_test = model.data_sets.test.labels
    if np.min(Y_test) < -0.5:
        Y_test = (np.copy(Y_test) + 1) / 2        
    Y_pred = model.sess.run(model.preds, feed_dict=model.all_test_feed_dict)
    Y_pred_correct = np.zeros([len(Y_test)])
    for idx, label in enumerate(Y_test):
        Y_pred_correct[idx] = Y_pred[idx, int(label)]
    return Y_pred_correct

num_classes = 2
num_train_ex_per_class = 40
num_test_ex_per_class = 300

dataset_name = 'carair_%s_%s' % (num_train_ex_per_class, num_test_ex_per_class)
image_data_sets = load_vehicles(
    num_train_ex_per_class=num_train_ex_per_class, 
    num_test_ex_per_class=num_test_ex_per_class)

weight_decay = 0.001
initial_learning_rate = 0.001 
keep_probs = None
decay_epochs = [1000, 10000]

#%%
### Generate kernelized feature vectors
X_train = image_data_sets.train.x
X_test = image_data_sets.test.x

Y_train = np.copy(image_data_sets.train.labels) * 2 - 1
Y_test = np.copy(image_data_sets.test.labels) * 2 - 1

num_train = X_train.shape[0]
num_test = X_test.shape[0]

X_stacked = np.vstack((X_train, X_test))

gamma = 0.05
weight_decay = 0.0001

K = rbf_kernel(X_stacked, gamma = gamma / num_train)

# =============================================================================
# L = slin.cholesky(K, lower=True)
# L_train = L[:num_train, :num_train]
# L_test = L[num_train:, :num_train]
# =============================================================================

K_train = K[:num_train, :num_train]
K_test = K[num_train:, :num_train]

### Compare top 5 influential examples from each network

test_idx = 0

## RBF

input_channels = 1
weight_decay = 0.001
batch_size = num_train
initial_learning_rate = 0.001 
keep_probs = None
max_lbfgs_iter = 1000
use_bias = False
decay_epochs = [1000, 10000]

tf.reset_default_graph()

X_train = image_data_sets.train.x
Y_train = image_data_sets.train.labels * 2 - 1
train = DataSet(K_train, Y_train)
test = DataSet(K_test, Y_test)

data_sets = base.Datasets(train=train, validation=None, test=test)
input_dim = data_sets.train.x.shape[1]

# Train with hinge
print('Train rbf with hinge...')
rbf_model = SmoothHinge(
    temp=0,
    use_bias=use_bias,
    input_dim=input_dim,
    weight_decay=weight_decay,
    num_classes=num_classes,
    batch_size=batch_size,
    data_sets=data_sets,
    initial_learning_rate=initial_learning_rate,
    keep_probs=keep_probs,
    decay_epochs=decay_epochs,
    mini_batch=False,
    train_dir='output7',
    log_dir='log',
    model_name='carair_rbf_hinge_t-0')
    
rbf_model.train()
hinge_W = rbf_model.sess.run(rbf_model.params)[0]

# Then load weights into smoothed version
print('Load weights into smoothed version...')
tf.reset_default_graph()
rbf_model = SmoothHinge(
    temp=0.001,
    use_bias=use_bias,
    input_dim=input_dim,
    weight_decay=weight_decay,
    num_classes=num_classes,
    batch_size=batch_size,
    data_sets=data_sets,
    initial_learning_rate=initial_learning_rate,
    keep_probs=keep_probs,
    decay_epochs=decay_epochs,
    mini_batch=False,
    train_dir='output7',
    log_dir='log',
    model_name='car_air_rbf_hinge_t-0.001')

params_feed_dict = {}
params_feed_dict[rbf_model.W_placeholder] = hinge_W
rbf_model.sess.run(rbf_model.set_params_op, feed_dict=params_feed_dict)

rbf_predicted_loss_diffs = rbf_model.get_influence_on_test_loss(
    [test_idx], 
    np.arange(len(rbf_model.data_sets.train.labels)),
    force_refresh=True)

#%%
## Inception

dataset_name = 'carair_40_300'
test_idx = 0

# Generate inception features
print('Generate inception features...')
img_side = 299
num_channels = 3
num_train_ex_per_class = 40
num_test_ex_per_class = 300
batch_size = 20 #TODO: 需要根据配置修改

# reset_default_graph大概就是重置当前线程，让tf session里定义的东西都失效，重来。就是重开一个神经网络session
tf.reset_default_graph()
full_model_name = '%s_inception' % dataset_name
# 下面的语句是定义一个inception双分类器
full_model = BinaryInceptionModel(
    img_side=img_side,
    num_channels=num_channels,
    weight_decay=weight_decay,
    num_classes=num_classes, 
    batch_size=batch_size,
    data_sets=image_data_sets,
    initial_learning_rate=initial_learning_rate,
    keep_probs=keep_probs,
    decay_epochs=decay_epochs,
    mini_batch=True,
    train_dir='output9',
    log_dir='log',
    model_name=full_model_name)

# 下面的代码是在使用inception的卷积层生成特征
train_inception_features_val = generate_inception_features(
    full_model,
    image_data_sets.train.x, 
    image_data_sets.train.labels, 
    batch_size=batch_size)        
test_inception_features_val = generate_inception_features(
    full_model, 
    image_data_sets.test.x, 
    image_data_sets.test.labels, 
    batch_size=batch_size)  

train = DataSet(
    train_inception_features_val,
    image_data_sets.train.labels)
test = DataSet(
    test_inception_features_val,
    image_data_sets.test.labels)

# train_f = np.load('G:/output/%s_inception_features_new_train.npz' % dataset_name)
# train = DataSet(train_f['inception_features_val'], train_f['labels'])
# test_f = np.load('G:/output/%s_inception_features_new_test.npz' % dataset_name)
# test = DataSet(test_f['inception_features_val'], test_f['labels'])

validation = None

# 上面的代码是训练了inception模型的全连接层前面的部分，因此输出的feature有2048个维度
data_sets = base.Datasets(train=train, validation=validation, test=test)

# train_f = np.load('G:/output/%s_inception_features_new_train.npz' % dataset_name)
# train = DataSet(train_f['inception_features_val'], train_f['labels'])
# test_f = np.load('G:/output/%s_inception_features_new_test.npz' % dataset_name)
# test = DataSet(test_f['inception_features_val'], test_f['labels'])
# validation = None

# data_sets = base.Datasets(train=train, validation=validation, test=test)

# 下面的代码利用从inception卷积层训练完成后的feature进行一个二分类逻辑回归，取消卷积层后面的FC全连接层
print('Train logistic regression after inception...')
input_dim = 2048
weight_decay = 0.001
batch_size = 20
initial_learning_rate = 0.001 
keep_probs = None
decay_epochs = [1000, 10000]
max_lbfgs_iter = 1000
num_classes = 2

tf.reset_default_graph()

inception_model = BinaryLogisticRegressionWithLBFGS(
    input_dim=input_dim,
    weight_decay=weight_decay,
    max_lbfgs_iter=max_lbfgs_iter,
    num_classes=num_classes, 
    batch_size=batch_size,
    data_sets=data_sets,
    initial_learning_rate=initial_learning_rate,
    keep_probs=keep_probs,
    decay_epochs=decay_epochs,
    mini_batch=False,
    train_dir='output9',
    log_dir='log',
    model_name='%s_inception_onlytop' % dataset_name)

inception_model.train()

# =============================================================================
# inception_predicted_loss_diffs = inception_model.get_influence_on_test_loss(
#     [test_idx], 
#     np.arange(len(inception_model.data_sets.train.labels)),
#     force_refresh=True)
# 
# x_test = X_test[test_idx, :]
# y_test = Y_test[test_idx]
# 
# 
# distances = dataset.find_distances(x_test, X_train)
# flipped_idx = Y_train != y_test
# rbf_margins_test = rbf_model.sess.run(rbf_model.margin, feed_dict=rbf_model.all_test_feed_dict)
# rbf_margins_train = rbf_model.sess.run(rbf_model.margin, feed_dict=rbf_model.all_train_feed_dict)
# inception_Y_pred_correct = get_Y_pred_correct_inception(inception_model)
# 
# 
# np.savez(
#     'output7/rbf_carair_results_%s' % test_idx,
#     test_idx=test_idx,
#     distances=distances,
#     flipped_idx=flipped_idx,
#     rbf_margins_test=rbf_margins_test,
#     rbf_margins_train=rbf_margins_train,
#     inception_Y_pred_correct=inception_Y_pred_correct,
#     rbf_predicted_loss_diffs=rbf_predicted_loss_diffs,
#     inception_predicted_loss_diffs=inception_predicted_loss_diffs
# )
# =============================================================================

#%%
print('Save results...')
#rand_test = random.sample(range(1, 600),50)
#np.savez('output7/rand_test_point', rand_test=rand_test)
for test_idx in range(1, 600):
    rbf_predicted_loss_diffs = rbf_model.get_influence_on_test_loss(
        [test_idx], 
        np.arange(len(rbf_model.data_sets.train.labels)),
        force_refresh=True)
    inception_predicted_loss_diffs = inception_model.get_influence_on_test_loss(
        [test_idx], 
        np.arange(len(inception_model.data_sets.train.labels)),
        force_refresh=True)
    x_test = X_test[test_idx, :]
    y_test = Y_test[test_idx]
    
    distances = dataset.find_distances(x_test, X_train)
    flipped_idx = Y_train != y_test
    rbf_margins_test = rbf_model.sess.run(rbf_model.margin, feed_dict=rbf_model.all_test_feed_dict)
    rbf_margins_train = rbf_model.sess.run(rbf_model.margin, feed_dict=rbf_model.all_train_feed_dict)
    inception_Y_pred_correct = get_Y_pred_correct_inception(inception_model)
    
    np.savez(
        'output9/rbf_carair_results_%s' % test_idx,
        test_idx=test_idx,
        distances=distances,
        flipped_idx=flipped_idx,
        rbf_margins_test=rbf_margins_test,
        rbf_margins_train=rbf_margins_train,
        inception_Y_pred_correct=inception_Y_pred_correct,
        rbf_predicted_loss_diffs=rbf_predicted_loss_diffs,
        inception_predicted_loss_diffs=inception_predicted_loss_diffs
    )

[((571, 622), 'sys.path.append', 'sys.path.append', (['"""C:/Tang/influence-release-master"""'], {}), "('C:/Tang/influence-release-master')\n", (586, 622), False, 'import sys\n'), ((1737, 1846), 'load_vehicles.load_vehicles', 'load_vehicles', ([], {'num_train_ex_per_class': 'num_train_ex_per_class', 'num_test_ex_per_class': 'num_test_ex_per_class'}), '(num_train_ex_per_class=num_train_ex_per_class,\n    num_test_ex_per_class=num_test_ex_per_class)\n', (1750, 1846), False, 'from load_vehicles import load_vehicles\n'), ((2245, 2273), 'numpy.vstack', 'np.vstack', (['(X_train, X_test)'], {}), '((X_train, X_test))\n', (2254, 2273), True, 'import numpy as np\n'), ((2315, 2361), 'sklearn.metrics.pairwise.rbf_kernel', 'rbf_kernel', (['X_stacked'], {'gamma': '(gamma / num_train)'}), '(X_stacked, gamma=gamma / num_train)\n', (2325, 2361), False, 'from sklearn.metrics.pairwise import rbf_kernel\n'), ((2969, 2993), 'tensorflow.reset_default_graph', 'tf.reset_default_graph', ([], {}), '()\n', (2991, 2993), True, 'import tensorflow as tf\n'), ((3084, 3109), 'influence.dataset.DataSet', 'DataSet', (['K_train', 'Y_train'], {}), '(K_train, Y_train)\n', (3091, 3109), False, 'from influence.dataset import DataSet\n'), ((3117, 3140), 'influence.dataset.DataSet', 'DataSet', (['K_test', 'Y_test'], {}), '(K_test, Y_test)\n', (3124, 3140), False, 'from influence.dataset import DataSet\n'), ((3154, 3208), 'tensorflow.contrib.learn.python.learn.datasets.base.Datasets', 'base.Datasets', ([], {'train': 'train', 'validation': 'None', 'test': 'test'}), '(train=train, validation=None, test=test)\n', (3167, 3208), False, 'from tensorflow.contrib.learn.python.learn.datasets import base\n'), ((3313, 3672), 'influence.smooth_hinge.SmoothHinge', 'SmoothHinge', ([], {'temp': '(0)', 'use_bias': 'use_bias', 'input_dim': 'input_dim', 'weight_decay': 'weight_decay', 'num_classes': 'num_classes', 'batch_size': 'batch_size', 'data_sets': 'data_sets', 'initial_learning_rate': 'initial_learning_rate', 'keep_probs': 'keep_probs', 'decay_epochs': 'decay_epochs', 'mini_batch': '(False)', 'train_dir': '"""output7"""', 'log_dir': '"""log"""', 'model_name': '"""carair_rbf_hinge_t-0"""'}), "(temp=0, use_bias=use_bias, input_dim=input_dim, weight_decay=\n    weight_decay, num_classes=num_classes, batch_size=batch_size, data_sets\n    =data_sets, initial_learning_rate=initial_learning_rate, keep_probs=\n    keep_probs, decay_epochs=decay_epochs, mini_batch=False, train_dir=\n    'output7', log_dir='log', model_name='carair_rbf_hinge_t-0')\n", (3324, 3672), False, 'from influence.smooth_hinge import SmoothHinge\n'), ((3873, 3897), 'tensorflow.reset_default_graph', 'tf.reset_default_graph', ([], {}), '()\n', (3895, 3897), True, 'import tensorflow as tf\n'), ((3910, 4281), 'influence.smooth_hinge.SmoothHinge', 'SmoothHinge', ([], {'temp': '(0.001)', 'use_bias': 'use_bias', 'input_dim': 'input_dim', 'weight_decay': 'weight_decay', 'num_classes': 'num_classes', 'batch_size': 'batch_size', 'data_sets': 'data_sets', 'initial_learning_rate': 'initial_learning_rate', 'keep_probs': 'keep_probs', 'decay_epochs': 'decay_epochs', 'mini_batch': '(False)', 'train_dir': '"""output7"""', 'log_dir': '"""log"""', 'model_name': '"""car_air_rbf_hinge_t-0.001"""'}), "(temp=0.001, use_bias=use_bias, input_dim=input_dim,\n    weight_decay=weight_decay, num_classes=num_classes, batch_size=\n    batch_size, data_sets=data_sets, initial_learning_rate=\n    initial_learning_rate, keep_probs=keep_probs, decay_epochs=decay_epochs,\n    mini_batch=False, train_dir='output7', log_dir='log', model_name=\n    'car_air_rbf_hinge_t-0.001')\n", (3921, 4281), False, 'from influence.smooth_hinge import SmoothHinge\n'), ((4953, 4977), 'tensorflow.reset_default_graph', 'tf.reset_default_graph', ([], {}), '()\n', (4975, 4977), True, 'import tensorflow as tf\n'), ((5065, 5432), 'influence.inceptionModel.BinaryInceptionModel', 'BinaryInceptionModel', ([], {'img_side': 'img_side', 'num_channels': 'num_channels', 'weight_decay': 'weight_decay', 'num_classes': 'num_classes', 'batch_size': 'batch_size', 'data_sets': 'image_data_sets', 'initial_learning_rate': 'initial_learning_rate', 'keep_probs': 'keep_probs', 'decay_epochs': 'decay_epochs', 'mini_batch': '(True)', 'train_dir': '"""output9"""', 'log_dir': '"""log"""', 'model_name': 'full_model_name'}), "(img_side=img_side, num_channels=num_channels,\n    weight_decay=weight_decay, num_classes=num_classes, batch_size=\n    batch_size, data_sets=image_data_sets, initial_learning_rate=\n    initial_learning_rate, keep_probs=keep_probs, decay_epochs=decay_epochs,\n    mini_batch=True, train_dir='output9', log_dir='log', model_name=\n    full_model_name)\n", (5085, 5432), False, 'from influence.inceptionModel import BinaryInceptionModel\n'), ((5525, 5646), 'influence.dataset_poisoning.generate_inception_features', 'generate_inception_features', (['full_model', 'image_data_sets.train.x', 'image_data_sets.train.labels'], {'batch_size': 'batch_size'}), '(full_model, image_data_sets.train.x,\n    image_data_sets.train.labels, batch_size=batch_size)\n', (5552, 5646), False, 'from influence.dataset_poisoning import generate_inception_features\n'), ((5700, 5819), 'influence.dataset_poisoning.generate_inception_features', 'generate_inception_features', (['full_model', 'image_data_sets.test.x', 'image_data_sets.test.labels'], {'batch_size': 'batch_size'}), '(full_model, image_data_sets.test.x,\n    image_data_sets.test.labels, batch_size=batch_size)\n', (5727, 5819), False, 'from influence.dataset_poisoning import generate_inception_features\n'), ((5847, 5914), 'influence.dataset.DataSet', 'DataSet', (['train_inception_features_val', 'image_data_sets.train.labels'], {}), '(train_inception_features_val, image_data_sets.train.labels)\n', (5854, 5914), False, 'from influence.dataset import DataSet\n'), ((5931, 5996), 'influence.dataset.DataSet', 'DataSet', (['test_inception_features_val', 'image_data_sets.test.labels'], {}), '(test_inception_features_val, image_data_sets.test.labels)\n', (5938, 5996), False, 'from influence.dataset import DataSet\n'), ((6400, 6460), 'tensorflow.contrib.learn.python.learn.datasets.base.Datasets', 'base.Datasets', ([], {'train': 'train', 'validation': 'validation', 'test': 'test'}), '(train=train, validation=validation, test=test)\n', (6413, 6460), False, 'from tensorflow.contrib.learn.python.learn.datasets import base\n'), ((7153, 7177), 'tensorflow.reset_default_graph', 'tf.reset_default_graph', ([], {}), '()\n', (7175, 7177), True, 'import tensorflow as tf\n'), ((7197, 7600), 'influence.binaryLogisticRegressionWithLBFGS.BinaryLogisticRegressionWithLBFGS', 'BinaryLogisticRegressionWithLBFGS', ([], {'input_dim': 'input_dim', 'weight_decay': 'weight_decay', 'max_lbfgs_iter': 'max_lbfgs_iter', 'num_classes': 'num_classes', 'batch_size': 'batch_size', 'data_sets': 'data_sets', 'initial_learning_rate': 'initial_learning_rate', 'keep_probs': 'keep_probs', 'decay_epochs': 'decay_epochs', 'mini_batch': '(False)', 'train_dir': '"""output9"""', 'log_dir': '"""log"""', 'model_name': "('%s_inception_onlytop' % dataset_name)"}), "(input_dim=input_dim, weight_decay=\n    weight_decay, max_lbfgs_iter=max_lbfgs_iter, num_classes=num_classes,\n    batch_size=batch_size, data_sets=data_sets, initial_learning_rate=\n    initial_learning_rate, keep_probs=keep_probs, decay_epochs=decay_epochs,\n    mini_batch=False, train_dir='output9', log_dir='log', model_name=\n    '%s_inception_onlytop' % dataset_name)\n", (7230, 7600), False, 'from influence.binaryLogisticRegressionWithLBFGS import BinaryLogisticRegressionWithLBFGS\n'), ((9472, 9511), 'influence.dataset.find_distances', 'dataset.find_distances', (['x_test', 'X_train'], {}), '(x_test, X_train)\n', (9494, 9511), True, 'import influence.dataset as dataset\n'), ((9836, 10211), 'numpy.savez', 'np.savez', (["('output9/rbf_carair_results_%s' % test_idx)"], {'test_idx': 'test_idx', 'distances': 'distances', 'flipped_idx': 'flipped_idx', 'rbf_margins_test': 'rbf_margins_test', 'rbf_margins_train': 'rbf_margins_train', 'inception_Y_pred_correct': 'inception_Y_pred_correct', 'rbf_predicted_loss_diffs': 'rbf_predicted_loss_diffs', 'inception_predicted_loss_diffs': 'inception_predicted_loss_diffs'}), "('output9/rbf_carair_results_%s' % test_idx, test_idx=test_idx,\n    distances=distances, flipped_idx=flipped_idx, rbf_margins_test=\n    rbf_margins_test, rbf_margins_train=rbf_margins_train,\n    inception_Y_pred_correct=inception_Y_pred_correct,\n    rbf_predicted_loss_diffs=rbf_predicted_loss_diffs,\n    inception_predicted_loss_diffs=inception_predicted_loss_diffs)\n", (9844, 10211), True, 'import numpy as np\n'), ((1248, 1262), 'numpy.min', 'np.min', (['Y_test'], {}), '(Y_test)\n', (1254, 1262), True, 'import numpy as np\n'), ((2075, 2112), 'numpy.copy', 'np.copy', (['image_data_sets.train.labels'], {}), '(image_data_sets.train.labels)\n', (2082, 2112), True, 'import numpy as np\n'), ((2130, 2166), 'numpy.copy', 'np.copy', (['image_data_sets.test.labels'], {}), '(image_data_sets.test.labels)\n', (2137, 2166), True, 'import numpy as np\n'), ((1289, 1304), 'numpy.copy', 'np.copy', (['Y_test'], {}), '(Y_test)\n', (1296, 1304), True, 'import numpy as np\n')]