# ---
# 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
# ---

# # KNeighborsRegressor with Scale & Power Transformer

# This Code template is for the regression analysis using a simple KNeighborsRegressor with Power Transformer as Feature Transformation Technique, rescaling technique Scaling in a pipeline

# # Required Packages
#

import warnings 
import numpy as np 
import pandas as pd
import seaborn as se  
import matplotlib.pyplot as plt 
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import scale, PowerTransformer
from sklearn.model_selection import train_test_split 
from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error 
from sklearn.neighbors import KNeighborsRegressor
warnings.filterwarnings('ignore')

# # Initialization

# Path for csv file

#filepath
file_path= ""

#x_values
features=[]

#y_value
target=''

# # Data fetching
# pandas is an open-source, BSD-licensed library providing high-performance, easy-to-use data manipulation and data analysis tools.
#
# We will use panda's library to read the CSV file using its storage path. And we use the head function to display the initial row or entry.

#read_csv
df=pd.read_csv(file_path)
df

# # Feature Selections
# We will assign all the required input features to X and target/outcome to Y.

#Get training and testing dataset 
X=df[features]
Y=df[target]


# # Data Preprocessing
# Since the majority of the machine learning models in the Sklearn library doesn't handle string category data and Null value, we have to explicitly remove or replace null values. The below snippet have functions, which removes the null value if any exists. And convert the string classes data in the datasets by encoding them to integer classes.

def NullClearner(df):
    if(isinstance(df, pd.Series) and (df.dtype in ["float64","int64"])):
        df.fillna(df.mean(),inplace=True)
        return df
    elif(isinstance(df, pd.Series)):
        df.fillna(df.mode()[0],inplace=True)
        return df
    else:return df
def EncodeX(df):
    return pd.get_dummies(df)


# Calling preprocessing functions on the feature and target set.

x=X.columns.to_list()
for i in x:
    X[i]=NullClearner(X[i])
X=EncodeX(X)
Y=NullClearner(Y)
X.head()

# # Correlation Map
# In order to check the correlation between the features, we will plot a correlation matrix. It is effective in summarizing a large amount of data where the goal is to see patterns.

f,ax = plt.subplots(figsize=(18, 18))
matrix = np.triu(X.corr())
se.heatmap(X.corr(), annot=True, linewidths=.5, fmt= '.1f',ax=ax, mask=matrix)
plt.show()

# # Data Splitting
# The train-test split is a procedure for evaluating the performance of an algorithm. The procedure involves taking a dataset and dividing it into two subsets. The first subset is utilized to fit/train the model. The second subset is used for prediction. The main motive is to estimate the performance of the model on new data.

x_train,x_test,y_train,y_test=train_test_split(X,Y,test_size=0.3,random_state=120)

# # Data Scaling
# Standardize a dataset along any axis.
# Center to the mean and component wise scale to unit variance.

x_train = scale(x_train)
x_test = scale(x_test)

# ## Model
# KNN is one of the easiest Machine Learning algorithms based on Supervised Machine Learning technique. The algorithm stores all the available data and classifies a new data point based on the similarity. It assumes the similarity between the new data and data and put the new case into the category that is most similar to the available categories.KNN algorithm at the training phase just stores the dataset and when it gets new data, then it classifies that data into a category that is much similar to the available data.
#
# ### Model Tuning Parameters
# - n_neighbors -> Number of neighbors to use by default for kneighbors queries.
#
# - weights -> weight function used in prediction. {uniform,distance}
#
# - algorithm -> Algorithm used to compute the nearest neighbors. {‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}
#
# - p -> Power parameter for the Minkowski metric. When p = 1, this is equivalent to using manhattan_distance (l1), and euclidean_distance (l2) for p = 2. For arbitrary p, minkowski_distance (l_p) is used.
#
# - leaf_size -> Leaf size passed to BallTree or KDTree. This can affect the speed of the construction and query, as well as the memory required to store the tree. The optimal value depends on the nature of the problem.

# ## Power Transformer
# Power transforms are a family of parametric, monotonic transformations that are applied to make data more Gaussian-like. This is useful for modeling issues related to heteroscedasticity (non-constant variance), or other situations where normality is desired.
#
# Currently, PowerTransformer supports the Box-Cox transform and the Yeo-Johnson transform. The optimal parameter for stabilizing variance and minimizing skewness is estimated through maximum likelihood.
#
# Apply a power transform featurewise to make data more Gaussian-like.

model=make_pipeline(PowerTransformer(),KNeighborsRegressor(n_jobs=-1))
model.fit(x_train, y_train)

# # Model Accuracy

print("Accuracy score {:.2f} %\n".format(model.score(x_test,y_test)*100))

# ### r2_score: 
# The r2_score function computes the percentage variablility explained by our model, either the fraction or the count of correct predictions.
#
# ### mae: 
# The mean abosolute error function calculates the amount of total error(absolute average distance between the real data and the predicted data) by our model.
#
# ### mse: 
# The mean squared error function squares the error(penalizes the model for large errors) by our model. 

y_pred=model.predict(x_test)
print("R2 Score: {:.2f} %".format(r2_score(y_test,y_pred)*100))
print("Mean Absolute Error {:.2f}".format(mean_absolute_error(y_test,y_pred)))
print("Mean Squared Error {:.2f}".format(mean_squared_error(y_test,y_pred)))

# ### Prediction Plot
# First, we make use of a plot to plot the actual observations, with x_train on the x-axis and y_train on the y-axis. For the regression line, we will use x_train on the x-axis and then the predictions of the x_train observations on the y-axis. 

plt.figure(figsize=(14,10))
plt.plot(range(20),y_test[0:20], color = "green")
plt.plot(range(20),model.predict(x_test[0:20]), color = "red")
plt.legend(["Actual","prediction"]) 
plt.title("Predicted vs True Value")
plt.xlabel("Record number")
plt.ylabel(target)
plt.show()

# # Creator - <NAME>, Github: [Profile](https://github.com/PrajwalNimje1997)

StarcoderdataJupyterScriptsDedupFiltered