Project

Tabular Risk

Client-side risk scoring system demonstrating transparent machine learning with interpretable logistic regression and optional API integration.

Client-Side ML Risk Scoring Transparent Baseline

What This Does

This is a risk scoring tool that runs entirely in your browser. You enter basic financial data (age, income, debt ratio, late payments), and it calculates a risk score from 0-100%. The calculation happens on your device—no data is sent anywhere unless you explicitly choose to test the optional API mode.

It solves the problem of opaque risk assessment by using a simple, transparent mathematical model where you can see exactly how each input affects the final score. This is the opposite of a black-box machine learning system where the decision logic is hidden.

This project demonstrates three key capabilities: building interpretable machine learning models that humans can audit, implementing complex calculations efficiently in client-side JavaScript, and designing flexible systems that work both standalone and as API integrations.

Technical Overview

Purpose and Scope

This system implements a client-side risk scoring engine for tabular financial data. The primary goal is demonstrating interpretable machine learning through a transparent baseline model, contrasted with an optional API integration path for more sophisticated models. The scope is deliberately limited to a four-feature input space to maintain clarity and auditability.

Architecture and Design Decisions

The architecture is a single-page application with zero dependencies. Local scoring uses a logistic regression model with hand-tuned weights (not trained on data), chosen specifically for interpretability. Each feature contribution to the final risk score is exposed in the output, allowing complete transparency into the decision process. The API mode provides a comparison point, demonstrating how the same interface can work with either a simple baseline or a deployed model endpoint.

Data Flow and Execution Model

In local mode: User inputs are read from form fields, validated, normalized to [0,1] ranges, multiplied by fixed weights, summed with a bias term, passed through a sigmoid activation function, and rendered as both a visual progress bar and structured JSON output. The entire pipeline executes synchronously in under 1ms. In API mode: Inputs are serialized to JSON, sent via HTTP POST to a configurable endpoint, and the response is parsed and displayed with the same rendering logic.

Implementation Details

The logistic model uses these weights: age (+0.35), income (-1.10), debt ratio (+1.55), late payments (+1.25), with a bias of -0.35. Inputs are normalized: age divided by 100, income by 150,000, debt ratio used directly, late payments divided by 12. The sigmoid function converts the linear combination into a probability. Risk thresholds: below 33% is low (green), 33-66% is medium (yellow), above 66% is high (red). The UI synchronizes number inputs with range sliders bidirectionally using event listeners.

Technology Stack

Languages: Vanilla JavaScript (ES6+) for logic and DOM manipulation, HTML5 for structure, CSS3 for styling with CSS Grid and custom properties. Why: Zero build step, no dependencies, maximum portability, minimal load time, complete browser compatibility without transpilation.

Model: Logistic regression with explicit weight specification. Why: Fully interpretable, no training data required, deterministic behavior, easy to audit, suitable for demonstration and baseline comparison.

API Integration: Fetch API with AbortController for timeout handling, JSON serialization. Why: Native browser support, modern async/await patterns, no external HTTP library needed, allows graceful degradation when API is unavailable.

UI Components: Custom-built form controls, synchronized number/range inputs, preset buttons, real-time status indicators. Why: Full control over behavior and appearance, no framework overhead, teaches fundamental DOM manipulation patterns.

Technical Challenges and Trade-offs

Challenge: Maintaining interpretability while providing meaningful risk scores. Trade-off: Used hand-tuned weights instead of training on real data, sacrificing predictive accuracy for complete transparency and auditability.

Challenge: Supporting both local and API modes with a unified interface. Trade-off: Duplicated some display logic but gained the ability to demonstrate both lightweight and full-stack deployment scenarios without breaking changes.

Challenge: Client-side JavaScript has no true type safety. Trade-off: Implemented explicit validation and bounds checking at input time, accepting runtime overhead to prevent invalid states from propagating through calculations.

Challenge: API calls may fail or timeout. Trade-off: Used AbortController with a 12-second timeout and structured error handling, prioritizing user feedback over silent failures, at the cost of added code complexity.

Interactive Demo

Try it

Local mode uses a small logistic baseline (hand-tuned weights) for interpretability. API mode expects POST /tabular/score (optional).

Preset: low risk Preset: medium risk Preset: high risk
mode: local status: idle risk: —

Output

{}

Links

RepositoryGitHub

API shape (optional)

{
  "age": 35,
  "income_gbp": 42000,
  "debt_ratio": 0.28,
  "late_payments": 1
}

Notes

  • Local scoring is deterministic and intentionally simple.
  • API mode uses the same payload and returns JSON.
  • Values are illustrative — used only to demonstrate the workflow.