DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Real-Time AI Feature Engineering With Spark Structured Streaming and Databricks Feature Store
  • The Five Stages of AI Adoption: A Practical Maturity Model for Software Teams
  • AI-Era Cybersecurity, Part 2: Building the System Context, Governance and Agent Identity
  • A Brown-Bag Project: babbler

Trending

  • Member Spotlight: Abhishek Sharma
  • Build Software Faster With Three Simple Principles
  • Security Readiness Checklist: From AI Threats to Software Supply Chain Defense
  • Java Backend Development in the Era of Kubernetes and Docker
  1. DZone
  2. Data Engineering
  3. AI/ML
  4. Feature Engineering Techniques That Actually Improve Model Accuracy

Feature Engineering Techniques That Actually Improve Model Accuracy

Feature engineering, not model swapping, drives most accuracy gains — via imputation, encoding, skew correction, interaction features, and feature selection

By 
David Taiwo Balogun user avatar
David Taiwo Balogun
·
Oct. 16, 26 · Analysis
Likes (0)
Comment
Save
Tweet
Share
10 Views

Join the DZone community and get the full member experience.

Join For Free

Most gains in a supervised learning project don't come from switching algorithms; they come from what you feed the algorithm. Feature engineering is the process of transforming raw data into representations that make patterns easier for a model to learn. Done well, it routinely closes more of the accuracy gap than hyperparameter tuning or trying a fancier model.

This article walks through the feature engineering techniques that consistently move the needle in real projects, with working Python code (pandas + scikit-learn) and a visual look at where the gains actually come from.

Where feature engineering sits in a typical supervised ML pipeline

Figure 1: Where feature engineering sits in a typical supervised ML pipeline.


Why Feature Engineering Beats Model Selection (Often)

A gradient-boosted tree with well-engineered features will usually outperform a deep neural network fed raw, unprocessed columns. That's because feature engineering directly encodes domain knowledge and statistical structure that the model would otherwise have to infer from data alone — often with far more examples than you have available.

Cumulative accuracy

Figure 2: Cumulative accuracy gains on a churn-prediction task as each feature engineering step is added.

In this example (a customer churn classifier trained with gradient-boosted trees), accuracy climbs from 0.712 on raw features to 0.851 after five feature engineering passes, a 13.9-point improvement without changing the model or its hyperparameters.

Techniques That Actually Move the Needle

1. Missing Value Imputation (With an Indicator Flag)

Dropping rows with missing values throws away signal. Simple mean/median imputation is a safe default but pairing it with a binary "was this missing" flag preserves the fact that the value was absent, which is often itself predictive (e.g., a missing income field can correlate with churn).

Python
 
import pandas as pd
from sklearn.impute import SimpleImputer
 
# Flag missingness before imputing — the flag is a feature in its own right
df['income_missing'] = df['income'].isna().astype(int)
 
imputer = SimpleImputer(strategy='median')
df['income'] = imputer.fit_transform(df[['income']])


2. Categorical Encoding (Target/Frequency, Not Just One-Hot)

One-hot encoding works fine for low-cardinality columns, but it explodes dimensionality for high-cardinality categoricals (zip codes, product IDs). Target encoding, replacing a category with the mean target value for that category, keeps dimensionality flat and often outperforms one-hot for tree-based models. Always fit encodings on the training fold only to avoid leakage.

Python
 
from category_encoders import TargetEncoder
from sklearn.model_selection import KFold
 
encoder = TargetEncoder(cols=['zip_code'], smoothing=0.3)
 
# Fit only on training data, then apply to validation/test
encoder.fit(X_train['zip_code'], y_train)
X_train['zip_code_enc'] = encoder.transform(X_train['zip_code'])
X_valid['zip_code_enc'] = encoder.transform(X_valid['zip_code'])


3. Scaling and Skew Correction

Distance-based and linear models (KNN, SVM, logistic regression) are sensitive to feature scale; tree-based models are not, but still benefit from skew correction. A log transform on heavily right-skewed features (income, transaction amounts) tightens the distribution and reduces the influence of outliers.

Python
 
import numpy as np
from sklearn.preprocessing import StandardScaler
 
# Log-transform skewed monetary features (add 1 to handle zeros)
df['txn_amount_log'] = np.log1p(df['txn_amount'])
scaler = StandardScaler()
num_cols = ['age', 'tenure_months', 'txn_amount_log']
df[num_cols] = scaler.fit_transform(df[num_cols])


4. Interaction and Ratio Features

Models capture linear or split-based patterns per feature; they don't automatically discover that the ratio of two columns is what matters. Manually creating interaction terms and ratios spend-per-visit, tenure-to-age ratio gives the model shortcuts to patterns it would otherwise need many more splits or much more data to approximate.

Python
 
# Ratio feature: average spend per visit is often more predictive
# than either 'total_spend' or 'visit_count' alone
df['spend_per_visit'] = df['total_spend'] / df['visit_count'].replace(0, 1)
 
# Interaction: tenure relative to customer age
df['tenure_ratio'] = df['tenure_months'] / (df['age'] * 12)


5. Date/Time Decomposition

A raw timestamp is nearly useless to a model. Decomposing it into cyclical and calendar components day of week, month, is-weekend, sine/cosine encodings for cyclical features exposes seasonality and recurring patterns that the model can actually split on.

Python
 
df['signup_date'] = pd.to_datetime(df['signup_date'])
df['signup_dow'] = df['signup_date'].dt.dayofweek
df['signup_month'] = df['signup_date'].dt.month
df['is_weekend'] = (df['signup_dow'] >= 5).astype(int)
 
# Cyclical encoding so December and January are 'close' to the model
df['month_sin'] = np.sin(2 * np.pi * df['signup_month'] / 12)
df['month_cos'] = np.cos(2 * np.pi * df['signup_month'] / 12)


6. Feature Selection (Prune After You Expand)

Adding interaction and encoded features inflates dimensionality, which can reintroduce noise and overfitting. Closing the loop with feature selection, dropping low-importance or highly correlated features, is what typically delivers the last, and sometimes largest, accuracy gain in the pipeline.

Python
 
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier
 
base_model = GradientBoostingClassifier(random_state=42)
base_model.fit(X_train, y_train)
 
# Keep only features with above-median importance
selector = SelectFromModel(base_model, threshold='median', prefit=True)
X_train_selected = selector.transform(X_train)
X_valid_selected = selector.transform(X_valid)
 
print(f'Kept {X_train_selected.shape[1]} of {X_train.shape[1]} features')

Common pitfall: fitting imputers, encoders, and scalers on the full dataset before splitting into train/test. This leaks information from the validation set into training and inflates your reported accuracy. Always fit transformations on the training fold only, inside a cross-validation loop or an sklearn Pipeline.

Putting It Together: Before vs. After

The table below summarizes the cumulative effect of each technique from the churn-prediction example, holding the model (gradient boosted trees, default hyperparameters) constant throughout.

step technique added accuracy Δ vs. Baseline

0

Baseline (raw features)

0.712

—

1

Missing value imputation + flag

0.741

+2.9 pts

2

Target encoding for categoricals

0.768

+5.6 pts

3

Log transform + scaling

0.781

+6.9 pts

4

Interaction/ratio features

0.824

+11.2 pts

5

Feature selection (prune to median importance)

0.851

 +13.9 pts


Wrapping It in a Reproducible Pipeline

Scattered feature engineering code is a common source of train/serve skew. Wrapping the steps in an sklearn Pipeline (or ColumnTransformer) keeps fitting and transforming consistent between training and inference, and makes the whole thing a single object you can version and deploy.

Python
 
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
from category_encoders import TargetEncoder
from sklearn.ensemble import GradientBoostingClassifier
 
numeric_features = ['age', 'tenure_months', 'txn_amount_log']
categorical_features = ['zip_code']
 
preprocessor = ColumnTransformer(transformers=[
    ('num', Pipeline([
        ('impute', SimpleImputer(strategy='median')),
        ('scale', StandardScaler()),
    ]), numeric_features),
    ('cat', TargetEncoder(), categorical_features),
])
 
full_pipeline = Pipeline([('preprocess', preprocessor),
    ('model', GradientBoostingClassifier(random_state=42)),
])
 
full_pipeline.fit(X_train, y_train)
print(full_pipeline.score(X_valid, y_valid))


Best Practices Checklist

  • Always fit transformers (imputers, encoders, scalers) on the training fold only, never on the full dataset before splitting.
  • Flag missingness explicitly instead of silently imputing; the flag itself often carries signal.
  •  Prefer target/frequency encoding over one-hot for high-cardinality categorical columns.
  •  Log-transform heavily skewed numeric features before scaling.
  •  Create interaction and ratio features that reflect domain knowledge, not random combinations.
  •  Decompose timestamps into calendar and cyclical components rather than using raw dates.
  •  Re-run feature selection after adding new engineered features to control dimensionality and overfitting.
  •  Wrap the whole process in a pipeline/column transformer so training and inference stay in sync.

Conclusion

Feature engineering is unglamorous compared to trying the newest architecture, but it's usually the highest-leverage work in a supervised learning project. Handle missing data deliberately, encode categoricals to fit their cardinality, correct skew, build interactions that reflect real relationships in your domain, decompose dates, and prune what you don't need. In the example walked through here, that sequence alone was responsible for nearly 14 points of accuracy, with the model and hyperparameters held constant the entire time.

Feature engineering AI

Opinions expressed by DZone contributors are their own.

Related

  • Real-Time AI Feature Engineering With Spark Structured Streaming and Databricks Feature Store
  • The Five Stages of AI Adoption: A Practical Maturity Model for Software Teams
  • AI-Era Cybersecurity, Part 2: Building the System Context, Governance and Agent Identity
  • A Brown-Bag Project: babbler

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook