DEV Community

amal org
amal org

Posted on

Data Analyst Guide: Mastering Cross-Validation: Why 80/20 Split is Wrong

Data Analyst Guide: Mastering Cross-Validation: Why 80/20 Split is Wrong

Business Problem Statement

In many real-world scenarios, data analysts and scientists rely on the traditional 80/20 split for training and testing their machine learning models. However, this approach can lead to biased results and poor model performance on unseen data. In this tutorial, we will explore the importance of cross-validation and demonstrate how to implement it using Python and SQL.

Let's consider a real-world example: a company wants to develop a predictive model to forecast sales based on historical data. The model will be used to inform business decisions and optimize marketing strategies. If the model is trained on a biased dataset, it may not generalize well to new data, resulting in poor predictions and potential financial losses.

Assuming the company has a dataset of 10,000 sales records, with each record containing features such as date, location, and product type. The goal is to predict the sales amount based on these features. Using the traditional 80/20 split, the dataset would be split into 8,000 training records and 2,000 testing records.

However, this approach can lead to overfitting and poor model performance on unseen data. By using cross-validation, we can ensure that the model is evaluated on multiple subsets of the data, reducing the risk of overfitting and improving the overall performance.

Step-by-Step Technical Solution

Step 1: Data Preparation (pandas/SQL)

First, let's prepare the data using pandas and SQL. We will use a sample dataset containing sales records.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error

# Load the dataset
data = pd.read_csv('sales_data.csv')

# Define the features and target variable
X = data.drop(['sales'], axis=1)
y = data['sales']

# Split the data into training and testing sets using the traditional 80/20 split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
Enter fullscreen mode Exit fullscreen mode

Alternatively, we can use SQL to prepare the data. Let's assume we have a table called sales_data in a PostgreSQL database.

-- Create a table to store the sales data
CREATE TABLE sales_data (
    id SERIAL PRIMARY KEY,
    date DATE,
    location VARCHAR(255),
    product_type VARCHAR(255),
    sales DECIMAL(10, 2)
);

-- Insert sample data into the table
INSERT INTO sales_data (date, location, product_type, sales)
VALUES
    ('2022-01-01', 'New York', 'Product A', 100.00),
    ('2022-01-02', 'New York', 'Product B', 200.00),
    ('2022-01-03', 'Chicago', 'Product A', 50.00),
    ('2022-01-04', 'Chicago', 'Product B', 150.00),
    -- ...
;

-- Split the data into training and testing sets using the traditional 80/20 split
SELECT * INTO sales_train FROM sales_data TABLESAMPLE SYSTEM_ROWS(8000);
SELECT * INTO sales_test FROM sales_data TABLESAMPLE SYSTEM_ROWS(2000);
Enter fullscreen mode Exit fullscreen mode

Step 2: Analysis Pipeline

Next, let's create an analysis pipeline using scikit-learn. We will use a random forest regressor to predict the sales amount.

# Create a random forest regressor
rf = RandomForestRegressor(n_estimators=100, random_state=42)

# Train the model on the training data
rf.fit(X_train, y_train)

# Make predictions on the testing data
y_pred = rf.predict(X_test)

# Evaluate the model using the mean squared error
mse = mean_squared_error(y_test, y_pred)
print(f'Mean Squared Error: {mse:.2f}')
Enter fullscreen mode Exit fullscreen mode

Step 3: Model/Visualization Code

Now, let's visualize the results using matplotlib and seaborn.

import matplotlib.pyplot as plt
import seaborn as sns

# Plot the actual vs. predicted sales
plt.scatter(y_test, y_pred)
plt.xlabel('Actual Sales')
plt.ylabel('Predicted Sales')
plt.title('Actual vs. Predicted Sales')
plt.show()

# Plot the residual plot
residuals = y_test - y_pred
plt.scatter(y_test, residuals)
plt.xlabel('Actual Sales')
plt.ylabel('Residuals')
plt.title('Residual Plot')
plt.show()
Enter fullscreen mode Exit fullscreen mode

Step 4: Performance Evaluation

To evaluate the performance of the model, we can use cross-validation. We will use the cross_val_score function from scikit-learn to evaluate the model on multiple subsets of the data.

from sklearn.model_selection import cross_val_score

# Define the cross-validation folds
folds = 5

# Evaluate the model using cross-validation
scores = cross_val_score(rf, X, y, cv=folds, scoring='neg_mean_squared_error')

# Print the average score
print(f'Average Cross-Validation Score: {scores.mean():.2f}')
Enter fullscreen mode Exit fullscreen mode

Step 5: Production Deployment

Finally, let's deploy the model to production. We can use a cloud-based platform such as AWS SageMaker or Google Cloud AI Platform to deploy the model.

import joblib

# Save the model to a file
joblib.dump(rf, 'sales_model.pkl')

# Load the model from the file
loaded_rf = joblib.load('sales_model.pkl')

# Make predictions on new data
new_data = pd.DataFrame({'date': ['2022-01-05'], 'location': ['New York'], 'product_type': ['Product A']})
new_pred = loaded_rf.predict(new_data)
print(f'Predicted Sales: {new_pred[0]:.2f}')
Enter fullscreen mode Exit fullscreen mode

Metrics/ROI Calculations

To calculate the return on investment (ROI) of the model, we can use the following formula:

# Define the revenue and cost
revenue = 1000.00
cost = 500.00

# Calculate the ROI
roi = (revenue - cost) / cost
print(f'Return on Investment (ROI): {roi:.2f}')
Enter fullscreen mode Exit fullscreen mode

Edge Cases

To handle edge cases, we can use the following techniques:

# Handle missing values
data.fillna(data.mean(), inplace=True)

# Handle outliers
data = data[(data['sales'] > 0) & (data['sales'] < 1000)]

# Handle categorical variables
data['product_type'] = pd.Categorical(data['product_type'])
Enter fullscreen mode Exit fullscreen mode

Scaling Tips

To scale the model, we can use the following techniques:

# Use parallel processing
from joblib import Parallel, delayed
Parallel(n_jobs=-1)(delayed(rf.fit)(X_train, y_train) for _ in range(10))

# Use distributed computing
from dask.distributed import Client
client = Client(n_workers=10)
futures = client.map(rf.fit, [X_train] * 10)
Enter fullscreen mode Exit fullscreen mode

By following these steps and techniques, we can develop a robust and scalable predictive model that provides accurate predictions and drives business value.

Top comments (0)