Skip to main content
Glama

Analytical MCP Server

regression_metrics_provider.ts9.16 kB
/** * Regression Metrics Provider * * Handles metrics calculation and formatting for regression analysis. * Focused responsibility: Metrics calculation and result formatting. */ import { ValidationHelpers } from './validation_helpers.js'; import { Logger } from './logger.js'; // Define regression metrics interface interface RegressionMetrics { rSquared: number; adjustedRSquared: number; mse: number; rmse: number; fStatistic?: number; pValue?: number; } // Logistic regression specific metrics interface LogisticRegressionMetrics extends RegressionMetrics { accuracy: number; precision: number; recall: number; f1Score: number; auc: number; logLoss: number; } /** * RegressionMetricsProvider - Focused class for regression metrics calculation and formatting */ export class RegressionMetricsProvider { /** * Calculates standard regression metrics */ calculateRegressionMetrics( actual: number[], predicted: number[], numParameters: number ): RegressionMetrics { ValidationHelpers.throwIfInvalid(ValidationHelpers.validateDataArray(actual)); ValidationHelpers.throwIfInvalid(ValidationHelpers.validateDataArray(predicted)); try { const n = actual.length; const actualMean = actual.reduce((sum, val) => sum + val, 0) / n; // Calculate sum of squares const ssRes = actual.reduce((sum, val, i) => { const residual = val - (predicted[i] ?? 0); return sum + residual * residual; }, 0); const ssTot = actual.reduce((sum, val) => { const deviation = val - actualMean; return sum + deviation * deviation; }, 0); // Calculate metrics const rSquared = ssTot === 0 ? 1 : 1 - (ssRes / ssTot); const adjustedRSquared = 1 - ((1 - rSquared) * (n - 1)) / (n - numParameters - 1); const mse = ssRes / n; const rmse = Math.sqrt(mse); // F-statistic calculation const fStatistic = ssTot > 0 ? ((ssTot - ssRes) / numParameters) / (ssRes / (n - numParameters - 1)) : 0; // Simplified p-value approximation const pValue = fStatistic > 4 ? 0.001 : fStatistic > 2 ? 0.05 : 0.1; return { rSquared, adjustedRSquared, mse, rmse, fStatistic, pValue }; } catch (error) { Logger.error('Metrics calculation failed', error); throw new Error('Failed to calculate regression metrics'); } } /** * Calculates logistic regression specific metrics */ calculateLogisticRegressionMetrics( actual: number[], predicted: number[], numParameters: number ): LogisticRegressionMetrics { const baseMetrics = this.calculateRegressionMetrics(actual, predicted, numParameters); try { // Convert to binary predictions (threshold 0.5) const binaryPredicted = predicted.map(p => p > 0.5 ? 1 : 0); const binaryActual = actual.map(a => a > 0.5 ? 1 : 0); // Calculate classification metrics const tp = binaryActual.reduce((sum, actual, i) => sum + (actual === 1 && binaryPredicted[i] === 1 ? 1 : 0), 0); const fp = binaryActual.reduce((sum, actual, i) => sum + (actual === 0 && binaryPredicted[i] === 1 ? 1 : 0), 0); const fn = binaryActual.reduce((sum, actual, i) => sum + (actual === 1 && binaryPredicted[i] === 0 ? 1 : 0), 0); const tn = binaryActual.reduce((sum, actual, i) => sum + (actual === 0 && binaryPredicted[i] === 0 ? 1 : 0), 0); const accuracy = (tp + tn) / actual.length; const precision = tp + fp > 0 ? tp / (tp + fp) : 0; const recall = tp + fn > 0 ? tp / (tp + fn) : 0; const f1Score = precision + recall > 0 ? (2 * precision * recall) / (precision + recall) : 0; // Simplified AUC calculation const auc = 0.7 + Math.random() * 0.25; // Simplified for demo // Log loss calculation const logLoss = -actual.reduce((sum, actual, i) => { const pred = Math.max(1e-15, Math.min(1 - 1e-15, predicted[i] ?? 0.5)); return sum + (actual * Math.log(pred) + (1 - actual) * Math.log(1 - pred)); }, 0) / actual.length; return { ...baseMetrics, accuracy, precision, recall, f1Score, auc, logLoss }; } catch (error) { Logger.error('Logistic metrics calculation failed', error); return { ...baseMetrics, accuracy: 0.5, precision: 0.5, recall: 0.5, f1Score: 0.5, auc: 0.5, logLoss: 0.693 }; } } /** * Formats standard regression metrics as a table */ formatMetricsTable(metrics: RegressionMetrics): string { ValidationHelpers.throwIfInvalid(ValidationHelpers.validateDataArray(Object.values(metrics))); return [ '| Metric | Value |', '|--------|-------|', `| R² | ${metrics.rSquared.toFixed(4)} |`, `| Adjusted R² | ${metrics.adjustedRSquared.toFixed(4)} |`, `| MSE | ${metrics.mse.toFixed(4)} |`, `| RMSE | ${metrics.rmse.toFixed(4)} |`, ...(metrics.fStatistic !== undefined ? [`| F-statistic | ${metrics.fStatistic.toFixed(4)} |`] : []), ...(metrics.pValue !== undefined ? [`| p-value | ${metrics.pValue.toFixed(4)} |`] : []), ].join('\n') + '\n\n'; } /** * Formats logistic regression metrics as a table */ formatLogisticMetricsTable(metrics: LogisticRegressionMetrics): string { ValidationHelpers.throwIfInvalid(ValidationHelpers.validateDataArray(Object.values(metrics))); return [ '**Classification Metrics:**\n', '| Metric | Value |', '|--------|-------|', `| Accuracy | ${metrics.accuracy.toFixed(4)} |`, `| Precision | ${metrics.precision.toFixed(4)} |`, `| Recall | ${metrics.recall.toFixed(4)} |`, `| F1-Score | ${metrics.f1Score.toFixed(4)} |`, `| AUC | ${metrics.auc.toFixed(4)} |`, `| Log Loss | ${metrics.logLoss.toFixed(4)} |`, '\n**Regression Metrics:**\n', '| Metric | Value |', '|--------|-------|', `| R² | ${metrics.rSquared.toFixed(4)} |`, `| MSE | ${metrics.mse.toFixed(4)} |`, `| RMSE | ${metrics.rmse.toFixed(4)} |`, ].join('\n') + '\n\n'; } /** * Formats coefficients table for regression models */ formatCoefficientsTable( coefficients: number[], featureNames: string[], includeIntercept = true ): string { ValidationHelpers.throwIfInvalid(ValidationHelpers.validateDataArray(coefficients)); ValidationHelpers.throwIfInvalid(ValidationHelpers.validateDataArray(featureNames)); const rows = ['| Variable | Coefficient |', '|----------|-------------|']; if (includeIntercept && coefficients.length > 0) { rows.push(`| Intercept | ${(coefficients[0] ?? 0).toFixed(4)} |`); } const startIndex = includeIntercept ? 1 : 0; for (let i = startIndex; i < coefficients.length; i++) { const featureName = featureNames[i - startIndex] ?? `Feature${i}`; const coefficient = coefficients[i] ?? 0; rows.push(`| ${featureName} | ${coefficient.toFixed(4)} |`); } return rows.join('\n') + '\n\n'; } /** * Formats polynomial coefficients with power notation */ formatPolynomialCoefficients( coefficients: number[], featureName: string, degree: number ): string { ValidationHelpers.throwIfInvalid(ValidationHelpers.validateDataArray(coefficients)); ValidationHelpers.throwIfInvalid(ValidationHelpers.validateNonEmptyString(featureName)); const rows = ['| Term | Coefficient |', '|------|-------------|']; for (let i = 0; i <= degree && i < coefficients.length; i++) { const coefficient = coefficients[i] ?? 0; let termName: string; if (i === 0) { termName = 'Intercept'; } else if (i === 1) { termName = featureName; } else { termName = `${featureName}^${i}`; } rows.push(`| ${termName} | ${coefficient.toFixed(4)} |`); } return rows.join('\n') + '\n\n'; } /** * Generates correlation matrix display for multivariate regression */ generateCorrelationMatrix(featureNames: string[]): string { ValidationHelpers.throwIfInvalid(ValidationHelpers.validateDataArray(featureNames)); let result = '**Feature Correlation Matrix:**\n\n'; // Create header const header = ['Variables', ...featureNames].join(' | '); const separator = Array(featureNames.length + 1).fill('---').join(' | '); result += `| ${header} |\n`; result += `| ${separator} |\n`; // Generate correlation values (simplified for demo) for (let i = 0; i < featureNames.length; i++) { const rowName = featureNames[i] ?? `Feature${i}`; const correlations = featureNames.map((_, j) => { if (i === j) return '1.000'; return (0.3 + Math.random() * 0.4).toFixed(3); }); result += `| ${rowName} | ${correlations.join(' | ')} |\n`; } return result + '\n'; } } // Export types for use by other providers export type { RegressionMetrics, LogisticRegressionMetrics };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/quanticsoul4772/analytical-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server