Implementation of Breiman's CART (Classification and Regression Trees) algorithm
Project description
🌳 Breiman CART
A pure Python implementation of Classification and Regression Trees (CART) following the original methodology from Breiman, Friedman, Olshen, and Stone (1984).
Why use this? Unlike sklearn's implementation, this provides a faithful reproduction of the original CART algorithm with full access to the tree-building process, cost-complexity pruning, and educational transparency.
✨ Features
- 🎯 Original CART Algorithm - Faithful implementation of Breiman et al. (1984)
- 🔢 Regression & Classification - Support for both continuous and categorical targets
- 📊 Categorical Features - Native handling of categorical variables without encoding
- ✂️ Cost-Complexity Pruning - Automatic tree pruning to prevent overfitting
- 🎨 Feature Importance - Built-in feature importance calculation
- 💾 Model Persistence - Easy save/load functionality
- 🔍 Tree Inspection - Full access to tree structure and node information
- 🤖 Sklearn Compatible - Familiar API for ML practitioners
🚀 Quick Start
Installation
pip install breiman-cart
Basic Usage
import breiman_cart as brc
import pandas as pd
import numpy as np
# Prepare your data
X = pd.DataFrame({
'age': [25, 30, 35, 40, 45, 50, 55, 60],
'income': [30000, 35000, 50000, 60000, 70000, 80000, 90000, 100000]
})
y = np.array([0, 0, 0, 1, 1, 1, 1, 1])
# Train a classifier
model = brc.BRCClassification(max_depth=5, min_samples_split=2)
model.fit(X, y)
# Make predictions
predictions = model.predict(X)
accuracy = model.score(X, y)
print(f"Accuracy: {accuracy:.2%}")
📚 Complete Examples
🔵 Regression Example
import breiman_cart as brc
import pandas as pd
import numpy as np
# Create regression data
X_train = pd.DataFrame({
'square_feet': [1200, 1500, 1800, 2000, 2200, 2500, 2800, 3000],
'bedrooms': [2, 3, 3, 4, 4, 4, 5, 5],
'age': [10, 8, 5, 3, 2, 1, 0, 0]
})
y_train = np.array([250000, 300000, 350000, 400000, 450000, 500000, 550000, 600000])
# Train model
model = brc.BRCRegression(
max_depth=5,
min_samples_split=2,
min_samples_leaf=1,
verbose=1 # Show training progress
)
model.fit(X_train, y_train)
# Make predictions
X_test = pd.DataFrame({
'square_feet': [1600, 2400],
'bedrooms': [3, 4],
'age': [7, 2]
})
predictions = model.predict(X_test)
print(f"Predicted prices: ${predictions}")
# Get R² score
r2 = model.score(X_train, y_train)
print(f"R² Score: {r2:.3f}")
# Feature importance
importance = model.get_feature_importance()
for feature, score in zip(X_train.columns, importance):
print(f"{feature}: {score:.3f}")
🟢 Classification Example
import breiman_cart as brc
import pandas as pd
import numpy as np
# Create classification data
X_train = pd.DataFrame({
'temperature': [30, 25, 20, 15, 10, 5, 0, -5],
'humidity': [80, 75, 70, 65, 60, 55, 50, 45],
'wind_speed': [5, 10, 15, 20, 25, 30, 35, 40]
})
y_train = np.array([1, 1, 1, 0, 0, 0, 0, 0]) # 1=Rain, 0=No Rain
# Train classifier
clf = brc.BRCClassification(
max_depth=3,
min_samples_split=2,
min_samples_leaf=1
)
clf.fit(X_train, y_train)
# Predictions
X_test = pd.DataFrame({
'temperature': [22, 8],
'humidity': [72, 58],
'wind_speed': [12, 28]
})
predictions = clf.predict(X_test)
print(f"Predictions: {predictions}") # [1, 0]
# Accuracy
accuracy = clf.score(X_train, y_train)
print(f"Accuracy: {accuracy:.2%}")
🔮 Inference Engine
Use the inference engine for production deployments:
import breiman_cart as brc
# Option 1: From trained model
model = brc.BRCRegression(max_depth=5)
model.fit(X_train, y_train)
inference = brc.BRCInference(model)
# Option 2: Load from saved file
inference = brc.BRCInference('my_model.pkl')
# Make predictions
predictions = inference.predict(X_new)
# Get model information
info = inference.get_model_info()
print(f"Model type: {info['model_type']}")
print(f"Tree depth: {info['tree_depth']}")
print(f"Number of leaves: {info['n_leaves']}")
# Feature importance (as dictionary)
importance = inference.get_feature_importance()
print(importance) # {'feature1': 0.65, 'feature2': 0.35}
# Pretty print
print(inference)
🎓 Advanced Features
Cost-Complexity Pruning
Prevent overfitting with automatic pruning:
# Train a full tree
model = brc.BRCRegression(max_depth=10)
model.fit(X_train, y_train)
# Prune using validation set
# (automatically finds optimal alpha)
model.prune(X_val, y_val)
# Or specify alpha manually
model.prune(X_val, y_val, alpha=0.01)
Categorical Features
Native support for categorical variables:
X = pd.DataFrame({
'color': ['red', 'blue', 'red', 'green', 'blue', 'green'],
'size': ['S', 'M', 'L', 'M', 'S', 'L'],
'price': [10, 20, 15, 25, 12, 30]
})
y = np.array([0, 1, 0, 1, 0, 1])
# Specify categorical features
model = brc.BRCClassification(
max_depth=5,
categorical_features=['color', 'size'] # These won't be treated as numerical
)
model.fit(X, y)
Model Persistence
Save and load models:
# Save model
model.save('my_cart_model.pkl')
# Load model later
loaded_model = brc.BRCRegression.load('my_cart_model.pkl')
# Or use with inference
inference = brc.BRCInference('my_cart_model.pkl')
Tree Inspection
Explore the tree structure:
# Get tree statistics
print(f"Tree depth: {model.root.get_depth()}")
print(f"Number of leaves: {model.root.count_leaves()}")
print(f"Total nodes: {model.root.get_n_nodes()}")
# Export tree structure
tree_dict = model.to_dict()
# Save as JSON
model.to_json('tree_structure.json')
🔧 API Reference
BRCRegression
Decision tree regressor using MSE criterion.
brc.BRCRegression(
max_depth=None, # Maximum tree depth
min_samples_split=2, # Min samples to split node
min_samples_leaf=1, # Min samples at leaf
categorical_features=[], # List of categorical feature names
verbose=0 # Verbosity level (0, 1, or 2)
)
Methods:
fit(X, y)- Train the modelpredict(X)- Make predictionsscore(X, y)- Calculate R² scoreget_feature_importance()- Get feature importancesprune(X_val, y_val, alpha=None)- Prune the treesave(filepath)- Save model to diskload(filepath)- Load model from disk (static method)
BRCClassification
Decision tree classifier using Gini impurity criterion.
brc.BRCClassification(
max_depth=None,
min_samples_split=2,
min_samples_leaf=1,
categorical_features=[],
verbose=0
)
Methods: Same as BRCRegression, but score() returns accuracy.
BRCInference
Inference engine for making predictions with trained models.
brc.BRCInference(model) # Pass trained model or file path
Methods:
predict(X)- Make predictionsscore(X, y)- Evaluate performanceget_feature_importance()- Get feature importance dictget_tree_depth()- Get tree depthget_n_leaves()- Get number of leavesget_n_nodes()- Get total nodesget_model_info()- Get comprehensive model infosave_model(filepath)- Save modelexport_to_json(filepath)- Export tree as JSON
📊 Comparison with Sklearn
| Feature | breiman-cart | sklearn DecisionTree |
|---|---|---|
| CART Algorithm | ✅ Original (1984) | Modified |
| Cost-Complexity Pruning | ✅ Automatic | Manual (ccp_alpha) |
| Categorical Features | ✅ Native | Requires encoding |
| Tree Inspection | ✅ Full access | Limited |
| Educational Value | ✅ High | Medium |
| Performance | Good | Excellent (C++) |
| Interpretability | ✅ Excellent | Good |
Use breiman-cart when:
- You want the original CART algorithm
- You need educational transparency
- You're working with categorical features
- You want easy tree inspection
- You need cost-complexity pruning
Use sklearn when:
- Performance is critical
- You need integration with sklearn pipelines
- You're working with very large datasets
🧪 Testing
Run the test suite:
# test_example.py
import breiman_cart as brc
import pandas as pd
import numpy as np
# Test regression
X = pd.DataFrame({'x1': [1, 2, 3, 4, 5], 'x2': [2, 4, 6, 8, 10]})
y = np.array([3, 6, 9, 12, 15])
reg = brc.BRCRegression(max_depth=5)
reg.fit(X, y)
assert reg.score(X, y) > 0.9, "Regression test failed"
# Test classification
y_class = np.array([0, 0, 1, 1, 1])
clf = brc.BRCClassification(max_depth=3)
clf.fit(X, y_class)
assert clf.score(X, y_class) >= 0.8, "Classification test failed"
# Test inference
inference = brc.BRCInference(reg)
preds = inference.predict(X)
assert len(preds) == len(X), "Inference test failed"
print("✅ All tests passed!")
📖 Background
This implementation follows the seminal work:
Breiman, L., Friedman, J., Olshen, R., & Stone, C. (1984).
Classification and Regression Trees.
Wadsworth International Group.
CART is a decision tree algorithm that:
- Recursively partitions the feature space into rectangular regions
- Uses Gini impurity (classification) or MSE (regression) for splitting
- Employs binary splits only (unlike ID3/C4.5)
- Prunes using cost-complexity to find the optimal subtree
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
📬 Contact
Adam Khald - adamkhald@outlook.com
Project Link: https://github.com/Adamkhald/breiman-cart
🙏 Acknowledgments
- Leo Breiman and colleagues for the original CART algorithm
- The scikit-learn team for API inspiration
- The Python data science community
📈 Changelog
Version 0.2.0 (Current)
- ✨ NEW: Clean sklearn-compatible API with
BRCRegression,BRCClassification,BRCInference - ✨ NEW:
BRCInferenceclass for production deployments - 🎨 Improved user experience with intuitive class names
- 📚 Comprehensive documentation and examples
- 🐛 Better error messages and validation
- 🔧 Feature importance as named dictionary in
BRCInference
Version 0.1.1
- Added comprehensive input validation
- Improved performance for categorical features
- Added model save/load functionality
- Enhanced pruning algorithm efficiency
Version 0.1.0
- Initial release
- Basic CART implementation
- Cost-complexity pruning
- Categorical feature support
⭐ Star History
If you find this project useful, please consider giving it a star on GitHub!
Made with ❤️ by Adam Khald
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file breiman_cart-0.2.1.tar.gz.
File metadata
- Download URL: breiman_cart-0.2.1.tar.gz
- Upload date:
- Size: 200.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
170215bd6be03add7acee020047a4d9e888f3c8e7f4a849b75ecfa9d67827f12
|
|
| MD5 |
7be152b0d46562f6ca124e4d7b440435
|
|
| BLAKE2b-256 |
708553320ca41e6ec92d7d2c214c81ed2cd49734092ae111655d3cdea9a2ad44
|
File details
Details for the file breiman_cart-0.2.1-py3-none-any.whl.
File metadata
- Download URL: breiman_cart-0.2.1-py3-none-any.whl
- Upload date:
- Size: 35.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
92421af49394ac763d57750ab533bafb32c2d7ff892b3a34e55a368181da8716
|
|
| MD5 |
0d076b22aa34dff688870b42191ea946
|
|
| BLAKE2b-256 |
980809ea335960738cc87e11bd0ed0ef76cb8147932f2dfed62a03ffcf707426
|