Skip to main content

Domain-free GLM factor binning, grouping, and model design tools.

Project description

glm-factor-optimizer

CI Security License Python 3.10+

Simple GLM tools for factor binning, grouping, model screening, and workflow automation. The package is domain-free: it works for count-rate, positive continuous, and other small GLM modeling problems.

Full project documentation is included in the source distribution under docs/ and published at csabar.github.io/glm-factor-optimizer. The docs are organized as tutorials, how-to guides, reference, and explanation. Release notes are maintained in CHANGELOG.md.

Minimal runnable example:

import pandas as pd

from glm_factor_optimizer import RateGLM, split

df = pd.DataFrame(
    [
        {
            "events": int((index % 7 == 0) + (index % 10 > 6)),
            "hours": 1.0 + 0.5 * (index % 4),
            "score": (index % 10) / 10,
            "segment": ["standard", "plus", "premium"][index % 3],
        }
        for index in range(60)
    ]
)

train, valid, _ = split(df, seed=42)

glm = RateGLM(target="events", exposure="hours")
score_spec = glm.bins(train, "score", bins=4)

train = glm.apply(train, score_spec)
valid = glm.apply(valid, score_spec)

model = glm.fit(train, factors=[score_spec["output"], "segment"])
valid = glm.predict(valid, model)

print(glm.report(valid)["summary"])

Use RateGLM for count-rate models:

  • count target, like events
  • exposure column, like hours
  • numeric or categorical factors
from glm_factor_optimizer import RateGLM, split

train, valid, holdout = split(df)

glm = RateGLM(target="events", exposure="hours")

score_spec = glm.bins(train, "score", bins=5)
train = glm.apply(train, score_spec)
valid = glm.apply(valid, score_spec)

model = glm.fit(train, factors=[score_spec["output"], "segment"])
valid = glm.predict(valid, model)

report = glm.report(valid)
print(report["summary"])

Use GLM for other families, such as Gamma cost or duration models:

from glm_factor_optimizer import GLM

glm = GLM(target="severity", family="gamma", prediction="predicted_severity")

age_spec = glm.bins(train, "machine_age", bins=6)
train = glm.apply(train, age_spec)
valid = glm.apply(valid, age_spec)

model = glm.fit(train, factors=[age_spec["output"], "equipment_type"])
valid = glm.predict(valid, model)

Optimize one factor manually:

result = glm.optimize(
    train,
    valid,
    "score",
    fixed_factors=["segment"],
    trials=50,
)

train = glm.apply(train, result.spec)
valid = glm.apply(valid, result.spec)
model = glm.fit(train, factors=[result.output, "segment"])

The same optimizer is also exposed as optimize_bins:

from glm_factor_optimizer import optimize_bins

result = optimize_bins(
    train,
    valid,
    target="events",
    exposure="hours",
    factor="score",
)

Add custom penalties with lambdas or named functions:

from glm_factor_optimizer import small_bin_size_penalty, small_count_penalty

result = glm.optimize(
    train,
    valid,
    "score",
    penalties={
        "small_count": small_count_penalty(min_count=5, penalty=0.02),
        "many_bins": lambda c: 0.01 * max(c["bin_count"] - 6, 0),
        "gap": lambda c: max(c["validation_deviance"] - c["train_deviance"], 0),
    },
)

Penalty callables receive a context dictionary with the selected spec, the training bin_table, train/validation deviance, predictions, transformed dataframes, factor name, kind, and fixed factors.

Rank candidate factors before detailed optimization:

ranking = glm.rank(
    train,
    valid,
    ["score", "segment", "region"],
    factor_kinds={"segment": "categorical", "region": "categorical"},
)
print(ranking[["factor", "deviance_improvement"]])

Run a higher-level sequential workflow with optional ranking, logging, and interaction diagnostics:

from glm_factor_optimizer import GLMWorkflow

workflow = GLMWorkflow(
    target="events",
    family="poisson",
    exposure="hours",
    factor_kinds={"segment": "categorical"},
    trials=50,
    rank_candidates=True,
    top_n=5,
    interaction_diagnostics=True,
    output_dir="runs",
)

result = workflow.fit(df, factors=["score", "segment"])
print(result.validation_report["summary"])
print(result.coefficients)

For notebook-style iterative model design, use GLMStudy:

from glm_factor_optimizer import GLMStudy

study = GLMStudy(
    df,
    target="events",
    exposure="hours",
    prediction="predicted_count",
    factor_kinds={"segment": "categorical"},
)

study.split(seed=42)
ranking = study.rank_candidates(["score", "segment", "region"])

score = study.factor("score")
score.coarse_bins(bins=10)
score.optimize(trials=100, max_bins=6)
score.compare()
score.accept(comment="score bins looked consistent")

study.fit_main_effects()
study.validation_report()

refined = study.refine_factor("score", trials=200)
refined.accept(comment="full-model refinement")

study.find_interactions()
study.finalize()
study.save("runs")

Useful helper modules are available for manual workflows:

from glm_factor_optimizer.aggregation import aggregate_rate_table
from glm_factor_optimizer.diagnostics import find_interactions
from glm_factor_optimizer.runs import RunLogger
from glm_factor_optimizer.sampling import stratified_sample

Example synthetic datasets live under examples/ and are not part of the installable package API. The examples cover general event-rate, severity, and Spark-style workflows across operational and service settings.

Use the optional Spark backend in PySpark environments:

from glm_factor_optimizer.spark import SparkGLM, SparkGLMWorkflow

glm = SparkGLM(
    target="events",
    family="poisson",
    exposure="hours",
    prediction="predicted_count",
)

score_spec = glm.bins(train_sdf, "score", bins=8)
train_sdf = glm.apply(train_sdf, score_spec)
valid_sdf = glm.apply(valid_sdf, score_spec)

model = glm.fit(train_sdf, factors=[score_spec["output"], "segment"])
valid_sdf = glm.predict(valid_sdf, model)

The top-level notebook helpers also dispatch on Spark dataframes:

from glm_factor_optimizer import RateGLM

glm = RateGLM(target_col="events", exposure_col="hours")
model = glm.fit(train_sdf, factors=["score", "segment"])
valid_sdf = glm.predict(valid_sdf, model)

Spark Optuna optimization runs Optuna on the driver and Spark GLM jobs inside each trial:

result = glm.optimize(
    train_sdf,
    valid_sdf,
    "score",
    fixed_factors=["segment"],
    trials=30,
    cache_input=True,
    cache_trials=False,
)

For a Spark-native factor screening workflow, keep the data in Spark:

from glm_factor_optimizer import RateGLM, split

sdf = spark.table("catalog.schema.modeling_table")
train, valid, holdout = split(sdf)

candidate_factors = [
    "event_type",
    "region",
    "service_channel",
    "equipment_type",
]

glm = RateGLM(
    candidate_factors=candidate_factors,
    target_col="events",
    exposure_col="hours",
    family="poisson",
    prediction_col="predicted_events",
    top_n=10,
)
glm.fit(train, validation_df=valid)

display(glm.identified_factors_)
scored_holdout = glm.predict(holdout)

This path keeps the modeling table as a Spark dataframe and fits with Spark ML generalized linear regression.

Install locally with Spark support using:

pip install "glm-factor-optimizer[spark]"

All binning and grouping specs are plain JSON-serializable dictionaries.

Contributing

Development setup, test commands, coverage, and release notes are documented in CONTRIBUTING.md.

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

glm_factor_optimizer-0.1.1.tar.gz (76.2 kB view details)

Uploaded Source

Built Distribution

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

glm_factor_optimizer-0.1.1-py3-none-any.whl (71.4 kB view details)

Uploaded Python 3

File details

Details for the file glm_factor_optimizer-0.1.1.tar.gz.

File metadata

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

File hashes

Hashes for glm_factor_optimizer-0.1.1.tar.gz
Algorithm Hash digest
SHA256 9d046048ae4d62e2c26bdae17c128a3ff07a0feec311c7af7f4fafc2f981845f
MD5 e66bed5002080b3c0e96051170cfa888
BLAKE2b-256 4c02c764e3d10bad1b0bf8a46d055f8b7c636abab97d9efc866ee8e0a3330b20

See more details on using hashes here.

Provenance

The following attestation bundles were made for glm_factor_optimizer-0.1.1.tar.gz:

Publisher: release.yml on csabar/glm-factor-optimizer

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

File details

Details for the file glm_factor_optimizer-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for glm_factor_optimizer-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 989a48321294c3ee2aae278bd9a993252cbb652902a05ba5201d6f43d0655215
MD5 af9a1488338b53e302400fad68b536fe
BLAKE2b-256 cbdcf851f5cd36d260f30e08959c381d3c8a7bdc6e84bd9d01c1432686e90316

See more details on using hashes here.

Provenance

The following attestation bundles were made for glm_factor_optimizer-0.1.1-py3-none-any.whl:

Publisher: release.yml on csabar/glm-factor-optimizer

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