# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# __Machine Learningn Lyfecycle Example__
#
# **1.Define Objective**
#
#     Objective: Infer how IQ, Year Experience, and Age effects income using a linear model. 
#
# __2. Collect Data__
#

import tensorflow as tf
import numpy as np 
import pandas as pd 
from pandas import DataFrame as DF

# **Create Dataset**

# +
np.random.seed(555)
X1 = np.random.normal(loc=100,scale=15,size=200).astype(int)
X2 = np.random.normal(10,4.5,200)
X3 = np.random.normal(32,4,200).astype(int)
dateOfBirth = np.datetime64('2017-10-31') - 365 * X3
intercept = 5
noiseOrError = np.random.normal(0,1.5,200)

Y = np.array([0.3*x1 + 1.5*x2 + 0.83*x3 + intercept + e for x1,x2,x3,e in zip(X1,X2,X3,noiseOrError)])
# -

# **3. Cleaning the Data**

columns = ['iq','years_Experience','dateOfBirth']
dataFrame = DF(list(zip(X1,X2,dateOfBirth)), columns = columns)
dataFrame['income'] = Y
dataFrame.info()

dataFrame.describe()

dataFrame = dataFrame[dataFrame.years_Experience >= 0]
dataFrame.describe()

# **4. EDA **

dataFrame.describe(include=['datetime64'])

import matplotlib.pyplot as plot
# %matplotlib inline 
pd.plotting.scatter_matrix(dataFrame,figsize=(16,9))

print(dataFrame.corr())

import seaborn as sb 
plot.figure(figsize=(21,9))
sb.heatmap(dataFrame.corr())

# **5. Data Processing / Feature Engineering **

# +
from datetime import datetime as dt 

dataFrame['age'] = dataFrame.dateOfBirth.apply(lambda x: (dt.strptime('2017-10-31','%Y-%m-%d')-x).days / 365)
dataFrame.drop('dateOfBirth',axis=1, inplace=True)
dataFrame.head()
# -

import matplotlib.pyplot as plot
# %matplotlib inline 
pd.plotting.scatter_matrix(dataFrame,figsize=(16,9))

import seaborn as sb 
plot.figure(figsize=(21,9))
sb.heatmap(dataFrame.corr())

# **6. Train/Evaluate Models**    

# +
import tensorflow as tf
#Train/Test Split
X = dataFrame.iloc[:,[0,1,3]]
Y = dataFrame.income

tranning_index = X.sample(frac=0.67).index
x_training = X[X.index.isin(tranning_index)].values
x_test     = X[~X.index.isin(tranning_index)].values

y_training = Y[Y.index.isin(tranning_index)].values
y_test     = Y[~Y.index.isin(tranning_index)].values
# -

# **Create Model**

tf.reset_default_graph()

# +
session = tf.Session()

#create parameters 
w = tf.get_variable(name='w', initializer=[[0.1],[0.1],[0.1]])
b = tf.get_variable(name='b', initializer=0.)

#create input placeholders 
x = tf.placeholder('float32',name='x')
y = tf.placeholder('float32',name='y_true')

#create linear model 
yhat = tf.reshape(tf.matmul(x,w) + b, [-1,], name='yhat')

# -

# **create the loss and test score function**

# +
mse = tf.reduce_mean(tf.square(y-yhat),name='mse')
rmse = tf.sqrt(mse,name='rmse')

#test score NRMSE normalized root mean square error
test_nrmse = tf.divide(rmse, tf.abs(tf.reduce_mean(y)),name='nrmse')
# -

#init variables 
init = tf.variables_initializer([w,b])
session.run(init)

# **Tranning/Evaluate**

# +
#reset parameters w and b 
session.run(init)

#run optimization again with smaller learning rate 
opt = tf.train.GradientDescentOptimizer(learning_rate=0.001)
train = opt.minimize(rmse)

for i in range(800): 
    if(i%50 == 0) & (i > 0):
        nrmse = session.run(test_nrmse,{x: x_test, y: y_test})
        print('test NRMSE: {}'.format(nrmse))
    else:
        session.run(train, {x: x_training, y: y_training})

# +
#0.3*x1 + 1.5*x2 + 0.83*x3 + 5
# -

session.run([w,b])

# **Result: **
#
#     iq: for ever .001 increase in iq we have increase around ~260 dollar (260 = 0.265 * 1000) anually
#     for every additional year of expeience the person will earn 1400 dollar (1400 = 1.425 * 1000 )
#     the last value 0.942 is for age
#     

# # ** How our model evolve over time and how are the mse values changes **

# **Create Mode**
# - create summeries 
# - merge summeries 
# - create a summery writer 
# - run merge summeries wit model in session 
# - use the weiter to write the output 
#

tf.reset_default_graph()

# +
session = tf.Session()

#create parameters 
w = tf.get_variable(name='w', initializer=[[0.1],[0.1],[0.1]])
tf.summary.scalar('wMean',tf.reduce_mean(w))
tf.summary.scalar('wSum',tf.reduce_sum(w))
tf.summary.histogram('weights',w)

b = tf.get_variable(name='b', initializer=0.)
tf.summary.scalar('intercept',b)

#create input placeholders 
x = tf.placeholder('float32',name='x')
y = tf.placeholder('float32',name='y_true')

#create linear model 
yhat = tf.reshape(tf.matmul(x,w) + b, [-1,], name='yhat')
# -

# **create the loss and test score function**

# +
mse = tf.reduce_mean(tf.square(y-yhat),name='mse')
rmse = tf.sqrt(mse,name='rmse')

#test score NRMSE normalized root mean square error
test_nrmse = tf.divide(rmse, tf.abs(tf.reduce_mean(y)),name='nrmse')

#merge all the summeries and create the writer that will output them during the training 
summaries = tf.summary.merge_all()
writer = tf.summary.FileWriter(logdir='temp/linear_logs', graph=session.graph)
# -

#init variables 
init = tf.variables_initializer([w,b])
session.run(init)

# **Tranning/Evaluate**

# +
#reset parameters w and b 
session.run(init)

#run optimization again with smaller learning rate 
opt = tf.train.GradientDescentOptimizer(learning_rate=0.001)
train = opt.minimize(rmse)

for i in range(800): 
    if(i%50 == 0) & (i > 0):
        smry, nrmse = session.run([summaries, test_nrmse],{x: x_test, y: y_test})
        writer.add_summary(smry,i)
        #print('test NRMSE: {}'.format(nrmse))
    else:
        smry, _ = session.run([summaries,train], {x: x_training, y: y_training})
        writer.add_summary(smry,i)
        
# -

session.run([w,b])

# **in the termenal write**
#
# tensorboard --logdir=temp/linear_logs

StarcoderdataJupyterScriptsDedupFiltered