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

# +
import os,sys
sys.path.append('../../src/python/')

import copy

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

from sklearn.compose import ColumnTransformer
from sklearn.datasets import make_blobs
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

from sklearn.model_selection import train_test_split, GridSearchCV, RandomizedSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import MinMaxScaler, OneHotEncoder, OrdinalEncoder
from sklearn.preprocessing import PolynomialFeatures
from sklearn.feature_selection import SelectFromModel
from sklearn.preprocessing._encoders import _BaseEncoder
# -



# # Loading the dataset:

# ## Data Set Information:
#
# Predicting the age of abalone from physical measurements. The age of abalone is determined by cutting the shell through the cone, staining it, and counting the number of rings through a microscope -- a boring and time-consuming task. Other measurements, which are easier to obtain, are used to predict the age. Further information, such as weather patterns and location (hence food availability) may be required to solve the problem.
#
# From the original data examples with missing values were removed (the majority having the predicted value missing), and the ranges of the continuous values have been scaled for use with an ANN (by dividing by 200).
#
#
# Attribute Information:
#
# Given is the attribute name, attribute type, the measurement unit and a brief description. The number of rings is the value to predict: either as a continuous value or as a classification problem.
#
# ## Name / Data Type / Measurement Unit / Description
# -----------------------------
# - Sex / nominal / -- / M, F, and I (infant)
# - Length / continuous / mm / Longest shell measurement
# - Diameter / continuous / mm / perpendicular to length
# - Height / continuous / mm / with meat in shell
# - Whole weight / continuous / grams / whole abalone
# - Shucked weight / continuous / grams / weight of meat
# - Viscera weight / continuous / grams / gut weight (after bleeding)
# - Shell weight / continuous / grams / after being dried
# - Rings / integer / -- / +1.5 gives the age in years

data = pd.read_csv('../../data/raw/abalone.csv')
data.columns = [x.replace(' ', '_').lower() for x in data.columns]
data

data['sex'].value_counts(dropna=False)

data.columns

data.info()

data.describe().transpose()



# # Data preparation:

TARGET_COL = 'rings'

X = data.drop(columns=[TARGET_COL])
y = data[TARGET_COL]

x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

print('Train:', x_train.shape[0], 'samples', x_train.shape[1], 'columns')
print('Test:', x_test.shape[0], 'samples', x_test.shape[1], 'columns')

x_train.shape[1]

# # Pre-processing Pipeline:

# Creating the transformation:
numeric_transformer = Pipeline(steps=[('scaler', MinMaxScaler())])
categorical_transformer = Pipeline(steps=[('onehot', OneHotEncoder(handle_unknown='ignore', dtype=np.float32))])

# +
# Feature Encoding:

# numeric_features = []
numeric_features = ['length', 'diameter', 'height', 'whole_weight', 'shucked_weight', 'viscera_weight', 'shell_weight']

# categorical_features  = []
categorical_features  = ['sex']

passthrough_features = []
all_features_ = (numeric_features + categorical_features
                 + passthrough_features)

features_encoder = ColumnTransformer(transformers=[('num', numeric_transformer, numeric_features),
                                                   ('cat', categorical_transformer, categorical_features),
#                                                    ('passthrough', 'passthrough', passthrough_features),
                                                  ],
                                     remainder='drop')
# -

# Feature Construction:
features_creator = PolynomialFeatures(2, include_bias=False)

# Feature Selection:
regr_select = RandomForestRegressor()
features_selector = SelectFromModel(regr_select)

preprocessor = Pipeline([('feature_encoding', features_encoder),
#                          ('feature_creation', features_creator),
#                          ('feature_selection', features_selector),
                        ])

# Columns dropped by preprocessor:
columns_to_drop = data.columns[~np.isin(data.columns, all_features_)]
columns_to_drop

x_train_encoded = preprocessor.fit_transform(x_train, y_train)
pd.DataFrame(x_train_encoded)

x_test_encoded = pd.DataFrame(preprocessor.transform(x_test))
x_test_encoded



# # Training the model into the main pipeline:

# +
# # Training the model and getting the results:
# lr_regr = LinearRegression()
# estimator = lr_regr.fit(x_train_encoded, y_train)

# model_full = Pipeline(steps=[('preprocessor', preprocessor),
#                              ('estimator', lr_regr)])

# # Com o linear regressor e OneHotEncoder houve problema na predição do ONNX
# # Aparentemente os coeficientes ligados ao OneHot ficavam com valores inadequados.

# +
# Training the model and getting the results:
rf_regr = RandomForestRegressor()
estimator = rf_regr.fit(x_train_encoded, y_train)

model_full = Pipeline(steps=[('preprocessor', preprocessor),
                             ('estimator', estimator)])
# -

y_train_pred = model_full.predict(x_train)
y_test_pred = model_full.predict(x_test)



# # Model evaluation:

print(f'MAE (train): {mean_absolute_error(y_train, y_train_pred)} MAE (test): {mean_absolute_error(y_test, y_test_pred)}')
print(f'MSE (train): {mean_squared_error(y_train, y_train_pred)} MSE (test): {mean_squared_error(y_test, y_test_pred)}')
print(f'RMSE (train): {mean_squared_error(y_train, y_train_pred)**0.5} RMSE (test): {mean_squared_error(y_test, y_test_pred)**0.5}')
print(f'R2 score (train): {r2_score(y_train, y_train_pred)} R2 score (test): {r2_score(y_test, y_test_pred)}')



StarcoderdataJupyterScriptsDedupFiltered