import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns   #to have pair plot


# Make numpy printouts easier to read.
np.set_printoptions(precision=3, suppress=True)



import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.layers.experimental import preprocessing

print(tf.__version__)


# -----Get the data from the archive
dftrain = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/train.csv') # training data
dfeval = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/eval.csv') # testing data
y_train = dftrain.pop('survived')
y_eval = dfeval.pop('survived')


print(dftrain.head())
print(dftrain.describe())
print(dftrain.shape)
print(y_train.head())

plt.figure()
dftrain.age.hist(bins=30)

plt.figure()
dftrain.sex.value_counts().plot(kind='barh')

plt.figure()
dftrain['class'].value_counts().plot(kind='barh')

plt.figure()
pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive')



# -----Converting the feature columns into numeric

CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck',
                       'embark_town', 'alone']
NUMERIC_COLUMNS = ['age', 'fare']

feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  vocabulary = dftrain[feature_name].unique()  # gets a list of all unique values from given feature column
  feature_columns.append(tf.feature_column.categorical_column_with_vocabulary_list(feature_name, vocabulary))

for feature_name in NUMERIC_COLUMNS:
  feature_columns.append(tf.feature_column.numeric_column(feature_name, dtype=tf.float32))

print(feature_columns) #This list helps the model to conert the data



# ----- Preparing the input data

def make_input_fn(data_df, label_df, num_epochs=10, shuffle=True, batch_size=32): #This function is compied from tf website, num_epochs means ho many times the whole data reached, batch_size, each batch
  def input_function():  							# inner function, this will be returned
    ds = tf.data.Dataset.from_tensor_slices((dict(data_df), label_df))  	# create tf.data.Dataset object with data and its label
    if shuffle:
      ds = ds.shuffle(1000)  # randomize order of data
    ds = ds.batch(batch_size).repeat(num_epochs)  # split dataset into batches of 32 and repeat process for number of epochs
    return ds  # return a batch of the dataset
  return input_function  # return a function object for use

train_input_fn = make_input_fn(dftrain, y_train)  # here we will call the input_function that was returned to us to get a dataset object we can feed to the model
eval_input_fn = make_input_fn(dfeval, y_eval, num_epochs=1, shuffle=False)


# ----- Model and train

linear_est = tf.estimator.LinearClassifier(feature_columns=feature_columns) #The list created above, "feature_columns" is used here
linear_est.train(train_input_fn)  # train
result = linear_est.evaluate(eval_input_fn)  # get model metrics/stats by testing on tetsing data

#clear_output()  # clears consoke output
print(result['accuracy'])  # the result variable is simply a dict of stats about our model



pred_dicts = list(linear_est.predict(eval_input_fn))
print(pred_dicts[0])

probs = pd.Series([pred['probabilities'][1] for pred in pred_dicts])

plt.figure()
probs.plot(kind='hist', bins=20, title='predicted probabilities')

#plt.show()




