# Exercise_1 
#1
import numpy as np

# Import MSE from sklearn
from sklearn.metrics import mean_squared_error

# Define your own MSE function
def own_mse(y_true, y_pred):
  	# Raise differences to the power of 2
    squares = np.power(y_true - y_pred, 2)
    # Find mean over all observations
    err = np.mean(squares)
    return err

print('Sklearn MSE: {:.5f}. '.format(mean_squared_error(y_regression_true, y_regression_pred)))
print('Your MSE: {:.5f}. '.format(own_mse(y_regression_true, y_regression_pred)))
#2
import numpy as np

# Import log_loss from sklearn
from sklearn.metrics import log_loss

# Define your own LogLoss function
def own_logloss(y_true, prob_pred):
    # Find loss for each observation
    terms = y_true * np.log(prob_pred) + (1 - y_true) * np.log(1 - prob_pred)
    # Find mean over all observations
    err = np.mean(terms) 
    return -err

print('Sklearn LogLoss: {:.5f}'.format(log_loss(y_classification_true, y_classification_pred)))
print('Your LogLoss: {:.5f}'.format(own_logloss(y_classification_true, y_classification_pred)))


--------------------------------------------------
# Exercise_2 
#1
# Shapes of train and test data
print('Train shape:', train.shape)
print('Test shape:', test.shape)

# Train head()
print(train.head())
#2
# Shapes of train and test data
print('Train shape:', train.shape)
print('Test shape:', test.shape)

# Train head()
print(train.head())

# Describe the target variable
print(train.fare_amount.describe())

# Train distribution of passengers within rides
print(train.passenger_count.value_counts())


--------------------------------------------------
# Exercise_3 
# Calculate the ride distance
train['distance_km'] = haversine_distance(train)

# Draw a scatterplot
plt.scatter(x=train['fare_amount'], y=train['distance_km'], alpha=0.5)
plt.xlabel('Fare amount')
plt.ylabel('Distance, km')
plt.title('Fare amount based on the distance')

# Limit on the distance
plt.ylim(0, 50)
plt.show()

--------------------------------------------------
# Exercise_4 
# Create hour feature

train['pickup_datetime'] = pd.to_datetime(train.pickup_datetime)

train['hour'] = train.pickup_datetime.dt.hour



# Find median fare_amount for each hour

hour_price = train.groupby('hour', as_index=False)['fare_amount'].median()



# Plot the line plot

plt.plot(hour_price['hour'], hour_price['fare_amount'], marker='o')

plt.xlabel('Hour of the day')

plt.ylabel('Median fare amount')

plt.title('Fare amount based on day time')

plt.xticks(range(24))

plt.show()

--------------------------------------------------
# Exercise_5 
# Import KFold

from sklearn.model_selection import KFold # random sampling



# Create a KFold object

kf = KFold(n_splits=3, shuffle=True, random_state=123)



# Loop through each split

fold = 0

for train_index, test_index in kf.split(train):

    # Obtain training and testing folds

    cv_train, cv_test = train.iloc[train_index], train.iloc[test_index]

    print('Fold: {}'.format(fold))

    print('CV train shape: {}'.format(cv_train.shape))

    print('Medium interest listings in CV train: {}\n'.format(sum(cv_train.interest_level == 'medium')))

    fold += 1

--------------------------------------------------
# Exercise_6 
# Import StratifiedKFold

from sklearn.model_selection import StratifiedKFold



# Create a StratifiedKFold object

str_kf = StratifiedKFold(n_splits=3, shuffle=True, random_state=123)



# Loop through each split

fold = 0

for train_index, test_index in str_kf.split(train, train['interest_level']):

    # Obtain training and testing folds

    cv_train, cv_test = train.iloc[train_index], train.iloc[test_index]

    print('Fold: {}'.format(fold))

    print('CV train shape: {}'.format(cv_train.shape))

    print('Medium interest listings in CV train: {}\n'.format(sum(cv_train.interest_level == 'medium')))

    fold += 1

--------------------------------------------------
# Exercise_7 
# Create TimeSeriesSplit object

#Create TimeSeriesSplit object

time_kfold = TimeSeriesSplit(n_splits=3)



# Sort train data by date

train = train.sort_values('date')



# Iterate through each split

fold = 0

for train_index, test_index in time_kfold.split(train):

    cv_train, cv_test = train.iloc[train_index], train.iloc[test_index]

    

    print('Fold :', fold)

    print('Train date range: from {} to {}'.format(cv_train.date.min(), cv_train.date.max()))

    print('Test date range: from {} to {}\n'.format(cv_test.date.min(), cv_test.date.max()))

    fold += 1

--------------------------------------------------
# Exercise_8 
#1
from sklearn.model_selection import TimeSeriesSplit
import numpy as np

# Sort train data by date
train = train.sort_values('date')

# Initialize 3-fold time cross-validation
kf = TimeSeriesSplit(n_splits=3)

# Get MSE scores for each cross-validation split
mse_scores = get_fold_mse(train, kf)

print('Mean validation MSE: {:.5f}'.format(np.mean(mse_scores)))

#2
from sklearn.model_selection import TimeSeriesSplit
import numpy as np

# Sort train data by date
train = train.sort_values('date')

# Initialize 3-fold time cross-validation
kf = TimeSeriesSplit(n_splits=3)

# Get MSE scores for each cross-validation split
mse_scores = get_fold_mse(train, kf)

print('Mean validation MSE: {:.5f}'.format(np.mean(mse_scores)))
print('MSE by fold: {}'.format(mse_scores))

#3
from sklearn.model_selection import TimeSeriesSplit
import numpy as np

# Sort train data by date
train = train.sort_values('date')

# Initialize 3-fold time cross-validation
kf = TimeSeriesSplit(n_splits=3)

# Get MSE scores for each cross-validation split
mse_scores = get_fold_mse(train, kf)

print('Mean validation MSE: {:.5f}'.format(np.mean(mse_scores)))
print('MSE by fold: {}'.format(mse_scores))
print('Overall validation MSE: {:.5f}'.format(np.mean(mse_scores) + np.std(mse_scores)))



--------------------------------------------------
