Skip to main content

FITRON: adaptive fuzzy-tree MCDM decision engine for generic tabular binary problems

Project description

FITRON

FITRON is a Python package for hybrid decision intelligence under uncertainty.

Current release: 1.0.0

The package combines:

  • fuzzy feature transformation,
  • decision tree learning,
  • TOPSIS multi-criteria ranking,
  • memory-guided adaptive weight updates,
  • interpretable ranking outputs.

Package name on PyPI: fitron
Import path: fitron

What FITRON Supports

FITRON is designed for generic tabular decision problems where the target is binary and the feature space contains a mix of numeric and categorical variables.

It is a good fit when:

  • the target can be encoded as 0/1, yes/no, true/false, approved/rejected, or another binary pair,
  • the data contains structured rows with feature columns that can be normalized, encoded, and ranked,
  • the goal is not only prediction, but also interpretable candidate ranking.

It is not a fit for:

  • multi-class targets without adaptation,
  • unstructured text or image-only problems,
  • tasks where row-level ranking is not meaningful.

Why FITRON

Most pipelines stop at classification. FITRON extends that flow into adaptive decision ranking.

  1. Learns a predictive backbone with a decision tree.
  2. Ranks valid candidates with TOPSIS and learned criteria weights.
  3. Adapts weights over iterations using memory and exploration.
  4. Produces feature-level explanations for selected options.

Core Workflow

  1. Preprocess tabular data and encode features.
  2. Fuzzify numeric features into low/mid/high memberships.
  3. Train decision tree model and estimate feature importances.
  4. Filter valid candidates using model predictions.
  5. Rank candidates with TOPSIS.
  6. Update weights using adaptive exploration and memory feedback.
  7. Return best option, score, and explanation.

Installation

End users

pip install fitron

From source

pip install .

Editable install (development)

pip install -e .[dev]

Environment Setup

Use a standard CPython virtual environment.

Windows:

python -m venv .venv-win
.\.venv-win\Scripts\python.exe -m pip install -U pip setuptools wheel
.\.venv-win\Scripts\python.exe -m pip install -e .[dev]

If PowerShell blocks script activation, use:

.venv-win\Scripts\activate.bat

Linux or macOS:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -U pip setuptools wheel
python -m pip install -e .[dev]

More detailed setup for Linux/macOS:

  1. Confirm Python 3.10+ is available:
python3 --version
  1. If venv is missing on Linux, install it first (example for Debian/Ubuntu):
sudo apt update
sudo apt install -y python3-venv
  1. Create and activate the virtual environment:
python3 -m venv .venv
source .venv/bin/activate
  1. Upgrade packaging tools and install FITRON in editable mode:
python -m pip install -U pip setuptools wheel
python -m pip install -e .[dev]
  1. Verify installation:
python -c "from fitron import FITRONModel; print('ok')"
pytest -q

Notes:

  • On some macOS setups, python3 may be installed via Homebrew and located under /opt/homebrew/bin/python3 (Apple Silicon) or /usr/local/bin/python3 (Intel).
  • Use deactivate when you are done working in the virtual environment.

Quick Start

Here's a complete working example with sufficient data to train the model effectively:

import pandas as pd
from fitron import FITRONModel

# Create sample data with sufficient rows for training
sample = pd.DataFrame(
    {
        "income": [50000, 20000, 75000, 43000, 60000, 47000, 71000, 25000, 55000, 38000, 65000, 30000],
        "risk": [0.2, 0.8, 0.3, 0.5, 0.4, 0.6, 0.25, 0.9, 0.35, 0.7, 0.2, 0.75],
        "credit_score": [710, 520, 760, 640, 700, 650, 750, 500, 720, 580, 740, 550],
        "employment_years": [5, 1, 10, 3, 7, 4, 9, 1, 6, 2, 8, 2],
        "target": [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0],
    }
)

# Initialize and fit the model
model = FITRONModel(iterations=5, random_state=42)
result = model.fit(sample, target="target")

# Access results
print("Best candidate index:", result.best_index)
print("Best score:", result.best_score)
print("Test accuracy:", result.test_accuracy)
print("\nExplanation for best candidate:")
for explanation in result.explanation:
    print(" -", explanation)

Output:

Best candidate index: 4
Best score: 0.87
Test accuracy: 0.83

Explanation for best candidate:
 - credit_score: 0.7341 (importance: 0.3872)
 - income: 0.6523 (importance: 0.2914)
 - employment_years: 0.5890 (importance: 0.1632)
 - risk: 0.4241 (importance: 0.1582)

Using String Targets

FITRON automatically handles string labels through explicit mapping:

data = pd.DataFrame(
    {
        "feature_a": [10, 20, 30, 40, 50, 60, 70, 80],
        "feature_b": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8],
        "decision": ["reject", "approve", "approve", "reject", "approve", "approve", "reject", "approve"],
    }
)

from fitron import fit

result = fit(
    data,
    target="decision",
    target_map={"reject": 0, "approve": 1},
    iterations=10,
)

print("Best index:", result.best_index)
print("Explanation:", result.explanation)

API Reference

Core Classes

FITRONModel

Main class for building and iterating over decision-ranking workflows. Maintains memory and weights across multiple iterations.

Constructor Parameters:

Parameter Type Default Description
iterations int 20 Number of iterations to run during fit(). Each iteration refines weights and finds better candidates.
random_state int 42 Random seed for reproducibility. Affects train/test splits, fuzzy profile fitting, and decision tree training.
decision_threshold float 0.5 Probability threshold for binary classification. Candidates above this are preferred.
objective_classification_weight float 0.65 Weight balancing classification quality (0.65) vs ranking quality (0.35) in the objective score. Range: [0, 1].
confidence_floor float 0.55 Minimum confidence score for a candidate to be selected. If no candidate meets this, falls back to highest probability.

Methods:

fit(df, target, ...)

Train the model on data and perform multi-iteration optimization.

Parameters:

Parameter Type Default Description
df pd.DataFrame Required Input data containing features and target column. Must have at least 5 rows for reliable results.
target str Required Name of the binary target column. Values can be numeric (0/1) or strings (mapped via target_map).
iterations int 20 Override the constructor's iteration count (optional).
drop_columns list[str] | None None Feature columns to exclude from processing. Useful for removing IDs, timestamps, etc.
criterion_types list[str] | None None MCDM criterion type for each feature: "benefit" (higher is better) or "cost" (lower is better). If None, all treated as benefits.
expected_feature_columns list[str] | None None Explicit list of feature columns to use. If None, all columns except target are used.
target_map dict[str, int] | None None Mapping for non-numeric target values. Example: {"reject": 0, "approve": 1}.
metrics_output_path str | None None Path to save iteration metrics as CSV. If provided, creates iteration_metrics.csv with scores and accuracies.

Returns: IterationResult object containing predictions, rankings, best candidate, and explanations.

Example:

result = model.fit(
    df=loan_data,
    target="approved",
    iterations=20,
    target_map={"denied": 0, "approved": 1},
    metrics_output_path="./metrics.csv",
)
rank(df, target, ...)

Rank candidates using previously fitted weights and memory without retraining from scratch.

Parameters:

Parameter Type Default Description
df pd.DataFrame Required Input data to rank. Must have same features as training data.
target str Required Name of the binary target column.
drop_columns list[str] | None None Columns to exclude.
criterion_types list[str] | None None MCDM criterion types for each feature.
expected_feature_columns list[str] | None None Explicit feature columns to use.
target_map dict[str, int] | None None Mapping for non-numeric target values.
tune_hyperparameters bool False If True, retunes decision tree hyperparameters (slower, more accurate).

Returns: IterationResult object.

Example:

# After fit(), use same model to rank new data
new_candidates = pd.DataFrame({...})
rank_result = model.rank(
    df=new_candidates,
    target="approved",
    target_map={"denied": 0, "approved": 1},
)
print("Ranked order:", rank_result.candidate_indices)
print("Best choice index:", rank_result.best_index)

API Functions

fit(df, target, ...)

Convenience function wrapper around FITRONModel.fit(). Creates a model internally.

Parameters: Same as FITRONModel.fit() plus:

Parameter Type Default Description
random_state int 42 Random seed.
decision_threshold float 0.5 Classification threshold.
objective_classification_weight float 0.65 Classification weight in objective.
confidence_floor float 0.55 Minimum confidence for selection.

Returns: IterationResult

Example:

from fitron import fit

result = fit(
    df=data,
    target="approved",
    iterations=10,
    target_map={"no": 0, "yes": 1},
)

rank(df, target, weights=None, memory=None, ...)

Convenience function to rank candidates without creating a model instance.

Parameters:

Parameter Type Default Description
df pd.DataFrame Required Candidates to rank.
target str Required Binary target column name.
weights np.ndarray | None None Feature weights from a previous fit. If None, weights are initialized from feature importances.
memory Memory | None None Memory object from a previous fit to blend learned patterns.
drop_columns list[str] | None None Columns to exclude.
criterion_types list[str] | None None MCDM criterion types.
expected_feature_columns list[str] | None None Explicit features to use.
tune_hyperparameters bool False Retune decision tree hyperparameters.
target_map dict[str, int] | None None Target value mapping.

Returns: IterationResult

Example:

from fitron import rank

result = rank(
    df=candidates,
    target="approved",
    weights=previous_weights,
    memory=previous_memory,
    target_map={"rejected": 0, "approved": 1},
)

explain(result)

Extract explanation strings from an IterationResult.

Parameters:

Parameter Type Description
result IterationResult Result object from fit() or rank().

Returns: list[str] - Feature explanations in importance order.

Example:

from fitron import explain

explanations = explain(result)
print("Top features explaining the selection:")
for exp in explanations:
    print(f"  • {exp}")

update_memory(memory, weights, score, best_idx)

Manually update a memory object with new weights and scores.

Parameters:

Parameter Type Description
memory Memory Memory object to update.
weights np.ndarray Feature weights to store.
score float Objective score achieved.
best_idx int Index of the best candidate selected.

Returns: None (modifies memory in place)

Example:

from fitron import update_memory, Memory
import numpy as np

memory = Memory()
weights = np.array([0.2, 0.3, 0.25, 0.25])
update_memory(memory, weights, score=0.85, best_idx=5)

Data Classes

IterationResult

Dataclass containing all outputs from a single fit() or rank() call.

Attribute Type Description
predictions np.ndarray Binary predictions (0 or 1) for each row in test set.
scores np.ndarray Final ranking scores for candidate rows. Higher = better.
candidate_indices list[int] Indices of rows selected as valid candidates.
best_index int Index of the highest-scoring candidate (best choice).
best_score float Final ranking score of the best candidate.
objective_score float Composite objective score across all iterations.
weights np.ndarray Final optimized feature weights used for ranking.
train_accuracy float Accuracy of decision tree on training set.
test_accuracy float Accuracy of decision tree on test set.
classification_quality float Quality metric for classification (0 to 1).
ranking_quality float Quality metric for ranking (0 to 1).
threshold_balanced_accuracy float Balanced accuracy at decision threshold.
threshold_f1 float F1 score at decision threshold.
fallback_triggered bool True if fallback to highest probability was used (confidence below floor).
model object Underlying decision tree model (sklearn DecisionTreeClassifier).
explanation list[str] Top-N feature explanations for best candidate.

Example:

result = model.fit(data, target="approved")

print(f"Best candidate: {result.best_index}")
print(f"Score: {result.best_score:.4f}")
print(f"Test accuracy: {result.test_accuracy:.4f}")
print(f"Fallback used: {result.fallback_triggered}")
print(f"Ranking scores: {result.scores}")

Memory

Dataclass for tracking optimization history and best weights across iterations.

Attribute Type Description
history list[dict] Log of all updates. Each entry contains: weights, score, improvement, ema_improvement, best_idx.
best_weights np.ndarray | None Feature weights that achieved the best score.
best_score float The highest objective score achieved.
max_history int Maximum entries to keep in history (default: 200). Older entries are removed.
ema_improvement float Exponential moving average of score improvements.

Methods:

update(weights, score, best_idx)

Record new weights and score in memory.

Parameters:

Parameter Type Description
weights np.ndarray Feature weights to store.
score float Objective score.
best_idx int Index of selected candidate.

Example:

from fitron import Memory

memory = Memory()
memory.update(weights=np.array([0.25, 0.35, 0.2, 0.2]), score=0.82, best_idx=3)

# Later, retrieve best weights
best_w = memory.get_best()
print(f"Best weights: {best_w}")
print(f"Best score: {memory.best_score}")
get_best()

Retrieve the feature weights that achieved the best score.

Returns: np.ndarray | None - Best weights or None if memory is empty.


Common Workflows

Workflow 1: Single-Pass Ranking

Train once and get the best candidate:

from fitron import FITRONModel

model = FITRONModel(iterations=10, random_state=42)
result = model.fit(data, target="decision")

print(f"Best candidate index: {result.best_index}")
print(f"Score: {result.best_score}")

Workflow 2: Multi-Pass Refinement with Memory

Reuse weights and memory across multiple ranking calls:

from fitron import FITRONModel

model = FITRONModel(iterations=5, random_state=42)

# First fit on training data
result1 = model.fit(train_data, target="decision")

# Access learned memory and weights
memory = model.memory
weights = result1.weights

# Apply to new candidates using same learned patterns
result2 = model.rank(new_candidates, target="decision")

print(f"Iteration 1 best: {result1.best_index}")
print(f"Iteration 2 best: {result2.best_index}")
print(f"Memory history entries: {len(memory.history)}")

Workflow 3: Using Explicit Weights with Criteria

Define which features are benefits vs. costs:

from fitron import fit

result = fit(
    df=data,
    target="approved",
    iterations=15,
    target_map={"rejected": 0, "approved": 1},
    criterion_types=["benefit", "cost", "benefit", "benefit"],  # cost = lower is better
    drop_columns=["applicant_id", "timestamp"],
)

print(f"Best index: {result.best_index}")
print(f"Scores: {result.scores}")

Workflow 4: Saving Iteration Metrics

Track model performance across all iterations:

from fitron import FITRONModel

model = FITRONModel(iterations=20)
result = model.fit(
    df=data,
    target="decision",
    metrics_output_path="./iteration_metrics.csv",
)

# CSV will contain: iteration, objective_score, top_candidate_score, 
#                   best_option_index, train_accuracy, test_accuracy, 
#                   threshold_balanced_accuracy, threshold_f1

Read and analyze metrics:

import pandas as pd

metrics = pd.read_csv("./iteration_metrics.csv")
print(metrics[["iteration", "objective_score", "test_accuracy"]])

# Plot convergence
import matplotlib.pyplot as plt
plt.plot(metrics["iteration"], metrics["objective_score"])
plt.xlabel("Iteration")
plt.ylabel("Objective Score")
plt.show()

Parameter Tuning Guide

iterations

  • Low (5-10): Fast experimentation, suitable for small datasets or demos.
  • Medium (20-30): Balanced; good for most production use cases.
  • High (50+): Slower but may find better solutions; risk of overfitting to noisy data.

objective_classification_weight

  • 0.5: Equal weight to classification and ranking quality.
  • 0.65 (default): Emphasizes classification accuracy; prefer high-quality predictions.
  • 0.8+: Strong emphasis on correct classification; ranking quality is secondary.

decision_threshold

  • 0.3-0.4: Lenient; accepts more candidates, may include borderline cases.
  • 0.5 (default): Standard probability threshold for binary classification.
  • 0.7-0.9: Strict; only high-confidence candidates are considered.

confidence_floor

  • 0.4-0.5: Lenient fallback; will select candidates even with low ranking scores.
  • 0.55-0.7: Moderate; requires decent confidence; may trigger fallback on ambiguous data.
  • 0.8+: Strict; high standards; fallback will be used frequently.

Troubleshooting

Issue: Poor test accuracy or high fallback rate

Causes: Insufficient data, target leakage, poor feature quality.

Solutions:

  • Increase dataset size to at least 20-30 rows.
  • Review features for relevance to target.
  • Lower confidence_floor to reduce fallback triggers.
  • Increase iterations to refine weights.

Issue: Inconsistent results across runs

Cause: Non-deterministic behavior due to random sampling.

Solution: Set random_state consistently:

model = FITRONModel(iterations=10, random_state=42)

Issue: Memory or weights not improving

Cause: Model is converging or data is too noisy.

Solutions:

  • Check memory.ema_improvement to see if learning has stalled.
  • Review criterion_types to ensure they match business logic.
  • Inspect data quality for outliers or mislabeling.

Run Tests

pytest -q

Release notes and version history are tracked in CHANGELOG.md.

Authors

  • zibransheikh
  • hazlived

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fitron-1.0.1.tar.gz (25.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fitron-1.0.1-py3-none-any.whl (21.4 kB view details)

Uploaded Python 3

File details

Details for the file fitron-1.0.1.tar.gz.

File metadata

  • Download URL: fitron-1.0.1.tar.gz
  • Upload date:
  • Size: 25.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fitron-1.0.1.tar.gz
Algorithm Hash digest
SHA256 0faeee14b32678504562bc0e965c283ea3fab00c90483551f29de4443cbb4d10
MD5 a5761b917918ce3fcb7c58dbd2259daa
BLAKE2b-256 9cc5e13a059c0bb2fd30643fef30547c5b6ee02e9a00531cf44cfce3b38eb20a

See more details on using hashes here.

Provenance

The following attestation bundles were made for fitron-1.0.1.tar.gz:

Publisher: publish.yml on hazlived/fitron

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fitron-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: fitron-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 21.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fitron-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e92afcad7c54a27680cd99184b290f0c79e243d29d0148a33a0c7726ed168c3e
MD5 ddc536816547d1e0760b7c0da33ee456
BLAKE2b-256 cd4703c6195d600cc3ceb7dd2a98d7101ccc03cc731055ef4774e0b9925bc055

See more details on using hashes here.

Provenance

The following attestation bundles were made for fitron-1.0.1-py3-none-any.whl:

Publisher: publish.yml on hazlived/fitron

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page