<jupyter_start><jupyter_text>0. Setup<jupyter_code># -*- coding: utf-8 -*-
import os
import sys
import numpy as np
import pandas as pd
import sklearn as sk
import pickle as pkl<jupyter_output><empty_output><jupyter_text>--- 1. Data  About the datasetPredicting 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. + 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<jupyter_code># variable names
names = [
    'sex',
    'length',
    'diameter',
    'height',
    'whole_weight',
    'shucked_weight',
    'viscera_weight',
    'shell_weight',
    'rings'
]

# reading dataset
df = pd.read_csv('data/abalone.data', header=None, names=names)

# building prediction target
df['target'] = (df['rings'] >= 10).astype(int)
df = df.drop('rings', axis=1)
df.head()<jupyter_output><empty_output><jupyter_text>--- 2. Feature Preparation<jupyter_code># seperating target from features
y = np.array(df['target'])
X = df.drop('target', axis=1)
# shuffling and splitting data into training and test sets
from sklearn.model_selection import train_test_split

SPLIT = 0.33
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=SPLIT, random_state=42)<jupyter_output><empty_output><jupyter_text>Pre-processing Categorical FeaturesExample: one-hot encoding<jupyter_code># one-hot encoding categorical features
CATEGORICALS = ['sex']
DUMMIES = {
    'sex':['M','F','I']
}

def dummy_encode(in_df, dummies):
    out_df = in_df.copy()
    
    for feature, values in dummies.items():
        for value in values:
            dummy_name = '{}__{}'.format(feature, value)
            out_df[dummy_name] = (out_df[feature] == value).astype(int)
            
        del out_df[feature]
        # print('Dummy-encoded feature\t\t{}'.format(feature))
    return out_df
        
X_train = dummy_encode(in_df=X_train, dummies=DUMMIES)

X_test = dummy_encode(in_df=X_test, dummies=DUMMIES)

X_train.head()<jupyter_output><empty_output><jupyter_text>Pre-processing Numeric FeaturesExample: min-max scaling<jupyter_code># rescaling numerical features
NUMERICS = ['length','diameter','height','whole_weight','shucked_weight','viscera_weight','shell_weight']
BOUNDARIES = {
    'length': (0.075000, 0.815000),
    'diameter': (0.055000, 0.650000),
    'height': (0.000000, 1.130000),
    'whole_weight': (0.002000, 2.825500),
    'shucked_weight': (0.001000, 1.488000),
    'viscera_weight': (0.000500, 0.760000),
    'shell_weight': (0.001500, 1.005000)
}

def minmax_scale(in_df, boundaries):
    out_df = in_df.copy()
    
    for feature, (min_val, max_val) in boundaries.items():      
        col_name = '{}__norm'.format(feature)
        
        out_df[col_name] = round((out_df[feature] - min_val)/(max_val - min_val),3)
        out_df.loc[out_df[col_name] < 0, col_name] = 0
        out_df.loc[out_df[col_name] > 1, col_name] = 1
            
        del out_df[feature]
        # print('MinMax Scaled feature\t\t{}'.format(feature))
    return out_df
        
X_train = minmax_scale(in_df=X_train, boundaries=BOUNDARIES)

X_test = minmax_scale(in_df=X_test, boundaries=BOUNDARIES)

X_train.head()<jupyter_output><empty_output><jupyter_text>Notes+ *Scikit-Learn* already has implementations of the most common variable transformers, however they tend to break down or behave unusually when they encounter values different from those they were fitted on.+ Your transformations need to be executed in the same order in production because *Scikit-Learn* (silently) assumes that your columns in prediction are in the same order as they were during training. --- 3. Training<jupyter_code>from sklearn.ensemble import RandomForestClassifier

clf = RandomForestClassifier(
    n_estimators=100, # number of trees
    n_jobs=-1, # parallelization
    random_state=1337, # random seed
    max_depth=10, # maximum tree depth
    min_samples_leaf=10
)
%time model = clf.fit(X_train, y_train)<jupyter_output>CPU times: user 428 ms, sys: 16 ms, total: 444 ms
Wall time: 306 ms<jupyter_text>--- 4. Evaluation<jupyter_code># computing ROC AUC over training set
train_auc = sk.metrics.roc_auc_score(y_train, model.predict(X_train))
print('Training ROC AUC:\t', round(train_auc, 3))
# computing ROC AUC over test set
test_auc = sk.metrics.roc_auc_score(y_test, model.predict(X_test))
print('Test ROC AUC:\t\t', round(test_auc, 3))<jupyter_output>Test ROC AUC:		 0.783<jupyter_text>--- 5. Storing Model<jupyter_code>pkl.dump(model, open('pickles/model_v1.pkl','wb'))<jupyter_output><empty_output><jupyter_text>--- 6. Loading Model<jupyter_code>m = pkl.load(open('pickles/model_v1.pkl','rb'))
m<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12032580525731211, 'fraction_numerical': 0.028322843391336543, 'mean_word_length': 4.381474103585657, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '419442', 'license': 'MIT', 'n_tokens_mistral': 1956, 'n_tokens_neox': 1802, 'n_words': 478, 'path': 'modeling.ipynb', 'repo_name': 'NawfalTachfine/PredictionAPI', 'size': '5402'}