import pandas as pd

diabetes = pd.read_csv('data/pima-indians-diabetes.csv')

diabetes.head()

diabetes.columns

"""
Explanation: TensorFlow Classification
Data
https://archive.ics.uci.edu/ml/datasets/pima+indians+diabetes


Title: Pima Indians Diabetes Database


Sources:
   (a) Original owners: National Institute of Diabetes and Digestive and
                        Kidney Diseases
   (b) Donor of database: Vincent Sigillito (vgs@aplcen.apl.jhu.edu)
                          Research Center, RMI Group Leader
                          Applied Physics Laboratory
                          The Johns Hopkins University
                          Johns Hopkins Road
                          Laurel, MD 20707
                          (301) 953-6231
   (c) Date received: 9 May 1990


Past Usage:

Smith,~J.~W., Everhart,~J.~E., Dickson,~W.~C., Knowler,~W.~C., \&
   Johannes,~R.~S. (1988). Using the ADAP learning algorithm to forecast
   the onset of diabetes mellitus.  In {\it Proceedings of the Symposium
   on Computer Applications and Medical Care} (pp. 261--265).  IEEE
   Computer Society Press.

The diagnostic, binary-valued variable investigated is whether the
   patient shows signs of diabetes according to World Health Organization
   criteria (i.e., if the 2 hour post-load plasma glucose was at least 
   200 mg/dl at any survey  examination or if found during routine medical
   care).   The population lives near Phoenix, Arizona, USA.
Results: Their ADAP algorithm makes a real-valued prediction between
   0 and 1.  This was transformed into a binary decision using a cutoff of 
   0.448.  Using 576 training instances, the sensitivity and specificity
   of their algorithm was 76% on the remaining 192 instances.


Relevant Information:
      Several constraints were placed on the selection of these instances from
      a larger database.  In particular, all patients here are females at
      least 21 years old of Pima Indian heritage.  ADAP is an adaptive learning
      routine that generates and executes digital analogs of perceptron-like
      devices.  It is a unique algorithm; see the paper for details.


Number of Instances: 768


Number of Attributes: 8 plus class 

For Each Attribute: (all numeric-valued)
Number of times pregnant
Plasma glucose concentration a 2 hours in an oral glucose tolerance test
Diastolic blood pressure (mm Hg)
Triceps skin fold thickness (mm)
2-Hour serum insulin (mu U/ml)
Body mass index (weight in kg/(height in m)^2)
Diabetes pedigree function
Age (years)
Class variable (0 or 1)



Missing Attribute Values: Yes


Class Distribution: (class value 1 is interpreted as "tested positive for
   diabetes")


Class Value  Number of instances
   0            500
   1            268

Brief statistical analysis:Attribute number:    Mean:   Standard Deviation:
1.                     3.8     3.4
2.                   120.9    32.0
3.                    69.1    19.4
4.                    20.5    16.0
5.                    79.8   115.2
6.                    32.0     7.9
7.                     0.5     0.3
8.                    33.2    11.8
End of explanation
"""


# Columns that will be normalized
cols_to_norm = ['Number_pregnant', 'Glucose_concentration', 'Blood_pressure', 'Triceps',
                'Insulin', 'BMI', 'Pedigree']

# Normalizing the columns
diabetes[cols_to_norm] = diabetes[cols_to_norm].apply(lambda x: (x - x.min()) / (x.max() - x.min()))

diabetes.head()

"""
Explanation: Clean the Data
End of explanation
"""


diabetes.columns 

import tensorflow as tf

"""
Explanation: Feature Columns
End of explanation
"""


num_preg = tf.feature_column.numeric_column('Number_pregnant')
plasma_gluc = tf.feature_column.numeric_column('Glucose_concentration')
dias_press = tf.feature_column.numeric_column('Blood_pressure')
tricep = tf.feature_column.numeric_column('Triceps')
insulin = tf.feature_column.numeric_column('Insulin')
bmi = tf.feature_column.numeric_column('BMI')
diabetes_pedigree = tf.feature_column.numeric_column('Pedigree')
age = tf.feature_column.numeric_column('Age')

"""
Explanation: Continuous Features

Number of times pregnant
Plasma glucose concentration a 2 hours in an oral glucose tolerance test
Diastolic blood pressure (mm Hg)
Triceps skin fold thickness (mm)
2-Hour serum insulin (mu U/ml)
Body mass index (weight in kg/(height in m)^2)
Diabetes pedigree function
End of explanation
"""


assigned_group = tf.feature_column.categorical_column_with_vocabulary_list('Group',['A','B','C','D'])
# Alternative
# assigned_group = tf.feature_column.categorical_column_with_hash_bucket('Group', hash_bucket_size=10)

"""
Explanation: Categorical Features
If you know the set of all possible feature values of a column and there are only a few of them, you can use categorical_column_with_vocabulary_list. If you don't know the set of possible values in advance you can use categorical_column_with_hash_bucket
End of explanation
"""


import matplotlib.pyplot as plt
%matplotlib inline

diabetes['Age'].hist(bins = 20)

age_buckets = tf.feature_column.bucketized_column(age, boundaries=[20, 30, 40, 50, 60, 70, 80])

"""
Explanation: Converting Continuous to Categorical
End of explanation
"""


feat_cols = [num_preg, plasma_gluc, dias_press, tricep, insulin, 
             bmi, diabetes_pedigree, assigned_group, age_buckets]

"""
Explanation: Putting them together
End of explanation
"""


diabetes.head()

diabetes.info()

# Dropping 'Class' to exclude the column
x_data = diabetes.drop('Class',axis = 1)

labels = diabetes['Class']

from sklearn.model_selection import train_test_split

# Test train split
X_train, X_test, y_train, y_test = train_test_split(x_data,
                                                    labels,
                                                    test_size = 0.33, 
                                                    random_state = 101)

"""
Explanation: Train Test Split
End of explanation
"""


input_func = tf.estimator.inputs.pandas_input_fn(x = X_train,
                                                 y = y_train,
                                                 batch_size = 10, 
                                                 num_epochs = 1000,
                                                 shuffle = True)

"""
Explanation: Input Function
End of explanation
"""


model = tf.estimator.LinearClassifier(feature_columns = feat_cols, 
                                      n_classes = 2)

model.train(input_fn = input_func,
            steps = 1000)

# Useful link for your own data
# https://stackoverflow.com/questions/44664285/what-are-the-contraints-for-tensorflow-scope-names

"""
Explanation: Creating the Model
End of explanation
"""


eval_input_func = tf.estimator.inputs.pandas_input_fn(
    x = X_test,
    y = y_test,
    batch_size = 10,
    num_epochs = 1,
    shuffle = False)

results = model.evaluate(eval_input_func)

results

"""
Explanation: Evaluation
End of explanation
"""


pred_input_func = tf.estimator.inputs.pandas_input_fn(
      x = X_test,
      batch_size = 10,
      num_epochs = 1,
      shuffle = False)

# Predictions is a generator! 
predictions = model.predict(pred_input_func)

list(predictions)[0:5]

"""
Explanation: Predictions
End of explanation
"""


dnn_model = tf.estimator.DNNClassifier(hidden_units=[10, 10, 10],
                                       feature_columns = feat_cols,
                                       n_classes = 2)

# Creating an embedding columns with 4 groups (A, B, C, D)
embedded_group_column = tf.feature_column.embedding_column(assigned_group, 
                                                           dimension = 4)

feat_cols = [num_preg, plasma_gluc, dias_press, tricep, insulin, 
             bmi, diabetes_pedigree, embedded_group_column, age_buckets]

input_func = tf.estimator.inputs.pandas_input_fn(x = X_train,
                                                 y = y_train,
                                                 batch_size = 10,
                                                 num_epochs = 1000,
                                                 shuffle = True)

dnn_model = tf.estimator.DNNClassifier(hidden_units=[10, 10, 10],
                                       feature_columns = feat_cols,
                                       n_classes = 2)

dnn_model.train(input_fn = input_func,
                steps = 1000)

eval_input_func = tf.estimator.inputs.pandas_input_fn(
      x = X_test,
      y = y_test,
      batch_size = 10,
      num_epochs = 1,
      shuffle = False)

dnn_model.evaluate(eval_input_func)

"""
Explanation: DNN Classifier
End of explanation
"""


