#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Jun  7 18:56:46 2017

@author: zhouying
"""

#from __future__ import division, print_function, absolute_import

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from sklearn import cross_validation
#%matplotlib inline

# Import MNIST data
#from tensorflow.examples.tutorials.mnist import input_data
#mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
data=np.loadtxt('./MNIST_data/ionosphere.txt',dtype='float32')

# Parameters
learning_rate = 0.01
training_epochs = 20
batch_size = 10
display_step = 1
examples_to_show = 10
divide_rate = 0.1
# Network Parameters
n_hidden_1 = 25 # 1st layer num features
n_hidden_2 = 128 # 2nd layer num features
n_input = 34 # MNIST data input (img shape: 28*28)

# tf Graph input (only pictures)
X = tf.placeholder("float", [None, n_input])

weights = {
    'encoder_h1': tf.Variable(tf.random_normal([n_input, n_hidden_1])),
#    'encoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
#    'decoder_h1': tf.Variable(tf.random_normal([n_hidden_2, n_hidden_1])),
    'decoder_h1': tf.Variable(tf.random_normal([n_hidden_1, n_input])),
#    'decoder_h2': tf.Variable(tf.random_normal([n_hidden_1, n_input])),
}
biases = {
    'encoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
#    'encoder_b2': tf.Variable(tf.random_normal([n_hidden_2])),
#    'decoder_b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'decoder_b1': tf.Variable(tf.random_normal([n_input])),
#    'decoder_b2': tf.Variable(tf.random_normal([n_input])),
}


# Building the encoder
def encoder(x):
    # Encoder Hidden layer with sigmoid activation #1
    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']),
                                   biases['encoder_b1']))
    # Decoder Hidden layer with sigmoid activation #2
#    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['encoder_h2']),
#                                   biases['encoder_b2']))
#    return layer_2
    return layer_1


# Building the decoder
def decoder(x):
    # Encoder Hidden layer with sigmoid activation #1
    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']),
                                   biases['decoder_b1']))
    # Decoder Hidden layer with sigmoid activation #2
#    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['decoder_h2']),
#                                   biases['decoder_b2']))
#    return layer_2
    return layer_1

# Construct model
encoder_op = encoder(X)
decoder_op = decoder(encoder_op)

# Prediction
y_pred = decoder_op
# Targets (Labels) are the input data.
y_true = X

# Define loss and optimizer, minimize the squared error
cost = tf.reduce_mean(tf.pow(y_true - y_pred, 2)) + tf.reduce_mean(tf.pow(weights['encoder_h1'],2)) + tf.reduce_mean(tf.pow(weights['decoder_h1'],2))
optimizer = tf.train.RMSPropOptimizer(learning_rate).minimize(cost)

# Initializing the variables
init = tf.global_variables_initializer()
#x_train,x_test = cross_validation.train_test_split(data,test_size=0.1)
#y_train = x_train[:,8]
#x_train = x_train[:,0:8]
#y_test = x_test[:,8]
#x_train = x_train[:,0:8]


# Launch the graph
#with tf.Session() as sess:
#    sess.run(init)
#    total_batch = int(x_train.num_examples/batch_size)
#    # Training cycle
#    for epoch in range(training_epochs):
#        # Loop over all batches
#        for i in range(total_batch):
#            batch_xs, batch_ys = x_train.next_batch(batch_size)
#            # Run optimization op (backprop) and cost op (to get loss value)
#            _, c = sess.run([optimizer, cost], feed_dict={X: batch_xs})
#        # Display logs per epoch step
#        if epoch % display_step == 0:
#            print("Epoch:", '%04d' % (epoch+1),
#                  "cost=", "{:.9f}".format(c))
#
#    print("Optimization Finished!")

    # Applying encode and decode over test set
#    encode_decode = sess.run(
#        y_pred, feed_dict={X: mnist.test.images[:examples_to_show]})
#    # Compare original images with their reconstructions
#    f, a = plt.subplots(2, 10, figsize=(10, 2))
#    for i in range(examples_to_show):
#        a[0][i].imshow(np.reshape(mnist.test.images[i], (28, 28)))
#        a[1][i].imshow(np.reshape(encode_decode[i], (28, 28)))
#    f.show()
#    plt.draw()
#    plt.waitforbuttonpress()


def reconstruction_error(x):
   encoder_op = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']),
                                   biases['encoder_b1']))
   decoder_op = tf.nn.sigmoid(tf.add(tf.matmul(encoder_op, weights['decoder_h1']),
                                   biases['decoder_b1']))

# Prediction
    
# Targets (Labels) are the input data.
    
   cost = x-decoder_op
   return cost

from sklearn.cross_validation import StratifiedKFold
skf = StratifiedKFold(data[:,n_input],n_folds=int(1/divide_rate))
for train_1,test_1 in skf:
    train = data[train_1,:]
    test = data[test_1,:]
    negative = []
    positive = []#np.empty([None,9])
    for i in range(train.shape[0]):
        if train[i,n_input] == 0:
            negative.append(train[i,:])
        else:
            positive.append(train[i,:])
    negative = np.array(negative)
    positive = np.array(positive)
    
x_train_negative,x_test_negative = cross_validation.train_test_split(negative,test_size=divide_rate)
x_train_positive,x_test_positive = cross_validation.train_test_split(positive,test_size=divide_rate)
y_train_negative = x_train_negative[:,n_input]
x_train_negative = x_train_negative[:,0:n_input]
y_test_negative = x_test_negative[:,n_input]
x_test_negative = x_test_negative[:,0:n_input]

y_train_positive = x_train_positive[:,n_input]
x_train_positive = x_train_positive[:,0:n_input]
y_test_positive = x_test_positive[:,n_input]
x_test_positive = x_test_positive[:,0:n_input]


#saver = tf.train.Saver()


#ne_po the ne means the recontruction model, po means the true labels
#b_ne_po = []
#b_ne_ne = []
#b_po_po = []
#b_po_ne = []



with tf.Session() as sess1:
    sess1.run(init)
    total_batch = int(y_train_negative.shape[0]/batch_size)
    # Training cycle
    for epoch in range(training_epochs):
        # Loop over all batches
        for i in range(total_batch):
            batch_xs = x_train_negative[i*batch_size:(i+1)*batch_size,:]
            # Run optimization op (backprop) and cost op (to get loss value)
            _, c = sess1.run([optimizer, cost], feed_dict={X: batch_xs})
        # Display logs per epoch step
#        if epoch % display_step == 0:
#            print("Epoch:", '%04d' % (epoch+1),
#                  "cost=", "{:.9f}".format(c))
#    saver.save(sess1, "./model_negative.ckpt")
    b_ne_ne = sess1.run(reconstruction_error(x_test_negative)) 
    b_ne_po = sess1.run(reconstruction_error(x_test_positive))
    print("Sess1 Optimization Finished!")
    
with tf.Session() as sess2:
    sess2.run(init)
    total_batch = int(y_train_negative.shape[0]/batch_size)
    # Training cycle
    for epoch in range(training_epochs):
        # Loop over all batches
        for i in range(total_batch):
            batch_xs = x_train_positive[i*batch_size:(i+1)*batch_size,:]
            # Run optimization op (backprop) and cost op (to get loss value)
            _, c = sess2.run([optimizer, cost], feed_dict={X: batch_xs})
        # Display logs per epoch step
#        if epoch % display_step == 0:
#            print("Epoch:", '%04d' % (epoch+1),
#                  "cost=", "{:.9f}".format(c))
#    saver.save(sess2, "./model_positive.ckpt")
    b_po_ne = sess2.run(reconstruction_error(x_test_negative)) 
    b_po_po = sess2.run(reconstruction_error(x_test_positive))
    print("Sess2 Optimization Finished!")

#count the recontrustion error and then compare in the two model
b_ne_ne = (b_ne_ne **2)
b_ne_po = (b_ne_po **2)
b_po_ne = (b_po_ne **2)
b_po_po = (b_po_po **2)

b_ne_ne_1 = b_ne_ne.sum(axis=1)
b_ne_po_1 = b_ne_po.sum(axis=1)
b_po_ne_1 = b_po_ne.sum(axis=1)
b_po_po_1 = b_po_po.sum(axis=1)

#predict the labels
pre_ne = []
for i in range(b_ne_ne_1.shape[0]):
    if b_ne_ne_1[i]<= b_po_ne_1[i]:
        pre_ne.append(0)
    else:
        pre_ne.append(1)
pre_po = []
for i in range(b_po_po_1.shape[0]):
    if b_po_po_1[i]<= b_ne_po_1[i]:
        pre_po.append(1)
    else:
        pre_po.append(0)

y_test_1 = []
y_test_1.extend(y_test_negative)
y_test_1.extend(y_test_positive)
y_pre =[]
y_pre.extend(pre_ne)
y_pre.extend(pre_po)
##################################
#compute F1 score
from sklearn import metrics
print('my model F1:',metrics.f1_score(y_test_1, y_pre))
print('my model roc:',metrics.roc_auc_score(y_test_1, y_pre))



####################################
#compute the normal classification's F1 score
x_train = []
x_test = []
y_train = []
x_train.extend(x_train_negative)
x_train.extend(x_train_positive)
x_test.extend(x_test_negative)
x_test.extend(x_test_positive)
y_train.extend(y_train_negative)
y_train.extend(y_train_positive)
from sklearn.naive_bayes import GaussianNB
gnb = GaussianNB()
y_pred = gnb.fit(x_train, y_train).predict(x_test)
print('F1:',metrics.f1_score(y_test_1, y_pred))
print('roc:',metrics.roc_auc_score(y_test_1, y_pred))
