30-Day Hospital Readmission Risk (AutoML)
Tested against SynapCores CE v1.7.0.1-ce (the currently-shipped release on Docker Hub:
synapcores/community:v1.7.0.1-ce).
Objective
At discharge, score every patient for risk of 30-day readmission. The model learns the joint shape of age, length of stay, medication count, and prior 1-year admissions.
Why this matters: under CMS's Hospital Readmissions Reduction Program, US hospitals lose up to 3% of all Medicare payments for excess readmissions on six condition cohorts. A model that flags top-decile risk at discharge lets case management direct post-discharge follow-up where it actually moves the readmission rate.
Step 1 — Schema + labelled discharges
170 discharges: 146 not-readmitted + 24 readmitted within 30 days (~14% readmission rate).
DROP TABLE IF EXISTS adm_dis;
CREATE TABLE adm_dis (
id INTEGER PRIMARY KEY,
age INTEGER,
los_days INTEGER,
num_meds INTEGER,
prior_admits INTEGER,
readmit_30d INTEGER
);
INSERT INTO adm_dis VALUES
(146,61,1,2,1,0),
(103,64,3,4,1,0),
(135,35,5,3,0,0),
(162,69,13,17,4,1),
(74,46,3,7,1,0),
(163,75,15,17,3,1),
(102,42,1,5,2,0),
(83,54,1,5,0,0),
(58,55,2,3,1,0),
(95,29,2,2,1,0),
(169,73,16,15,5,1),
(127,29,4,6,0,0),
(134,35,5,7,0,0),
(154,80,11,16,3,1),
(3,55,2,7,2,0),
(100,35,1,7,1,0),
(122,61,3,5,2,0),
(81,30,2,2,0,0),
(16,46,2,7,0,0),
(132,31,2,5,2,0),
(69,43,2,5,0,0),
(156,81,13,11,5,1),
(161,73,17,13,7,1),
(19,31,1,2,1,0),
(14,42,1,4,2,0),
(33,61,4,5,0,0),
(41,27,3,6,0,0),
(49,29,3,4,0,0),
(29,53,5,5,0,0),
(30,66,1,6,2,0),
(63,37,3,6,0,0),
(136,29,3,6,0,0),
(40,68,1,3,1,0),
(110,30,2,5,1,0),
(11,42,3,3,0,0),
(46,48,1,2,0,0),
(131,23,4,2,0,0),
(56,27,5,3,0,0),
(98,63,3,4,0,0),
(79,28,2,3,1,0),
(157,69,18,11,7,1),
(61,23,1,3,1,0),
(7,41,5,5,0,0),
(109,46,2,7,1,0),
(106,64,1,4,1,0),
(78,32,3,3,0,0),
(145,56,1,6,2,0),
(62,33,3,7,1,0),
(158,78,12,15,5,1),
(71,46,5,2,2,0),
(119,53,1,2,2,0),
(24,51,3,5,0,0),
(121,43,5,7,1,0),
(65,58,3,7,1,0),
(117,40,5,3,1,0),
(141,55,5,2,0,0),
(114,56,5,4,0,0),
(32,54,4,4,1,0),
(39,54,1,7,2,0),
(84,58,5,5,1,0),
(27,37,1,6,2,0),
(112,42,5,2,1,0),
(107,41,1,4,1,0),
(142,34,3,3,2,0),
(13,42,2,6,1,0),
(44,65,1,6,1,0),
(12,69,3,2,2,0),
(118,56,2,7,2,0),
(2,39,4,7,2,0),
(129,59,5,7,1,0),
(52,40,5,4,1,0),
(160,77,12,14,4,1),
(126,57,4,6,2,0),
(153,86,14,15,6,1),
(47,51,1,2,2,0),
(105,56,5,5,2,0),
(92,34,3,5,0,0),
(26,70,3,2,2,0),
(50,69,4,4,0,0),
(67,47,1,4,0,0),
(37,33,3,5,1,0),
(166,76,17,13,7,1),
(55,70,4,4,0,0),
(130,46,1,6,1,0),
(75,37,5,7,2,0),
(140,45,3,5,1,0),
(97,39,5,6,1,0),
(10,70,2,2,0,0),
(149,84,8,17,5,1),
(108,60,3,7,0,0),
(64,53,4,6,1,0),
(72,53,2,3,1,0),
(48,35,5,3,2,0),
(54,28,3,5,1,0),
(73,67,3,4,2,0),
(57,38,1,3,1,0),
(101,25,4,6,1,0),
(133,40,3,4,2,0),
(60,62,2,2,0,0),
(143,39,2,3,0,0),
(99,40,1,3,2,0),
(38,43,3,6,2,0),
(9,49,3,4,2,0),
(116,48,2,3,2,0),
(22,63,4,5,2,0),
(76,46,4,5,2,0),
(120,62,5,3,0,0),
(51,70,1,2,1,0),
(89,37,4,4,0,0),
(68,29,2,7,1,0),
(94,54,3,4,2,0),
(170,68,17,9,6,1),
(104,37,1,6,0,0),
(167,75,9,9,6,1),
(87,33,5,6,1,0),
(80,43,4,3,1,0),
(23,52,3,6,2,0),
(1,58,2,7,0,0),
(137,30,1,2,0,0),
(88,40,5,5,2,0),
(77,47,1,4,1,0),
(124,67,1,2,2,0),
(20,22,1,5,1,0),
(59,56,4,5,1,0),
(152,68,18,17,4,1),
(43,34,5,2,0,0),
(96,42,2,6,2,0),
(164,92,10,17,4,1),
(85,22,5,2,1,0),
(25,22,4,5,1,0),
(139,53,1,7,2,0),
(28,50,3,7,0,0),
(138,36,5,5,1,0),
(147,85,13,14,5,1),
(31,40,4,4,1,0),
(165,88,15,17,7,1),
(8,69,5,7,2,0),
(21,44,2,3,2,0),
(123,44,2,4,0,0),
(17,24,3,7,2,0),
(90,41,2,5,1,0),
(150,80,9,10,3,1),
(155,74,13,18,7,1),
(6,62,1,4,1,0),
(128,67,1,7,2,0),
(15,64,3,6,1,0),
(42,58,1,3,0,0),
(111,44,3,4,1,0),
(115,31,4,7,0,0),
(34,70,4,4,1,0),
(91,22,3,4,2,0),
(144,29,3,5,0,0),
(70,37,2,6,0,0),
(36,42,5,4,2,0),
(66,36,1,4,0,0),
(86,53,2,6,1,0),
(125,26,1,3,0,0),
(5,52,4,4,2,0),
(159,87,11,10,5,1),
(4,54,3,7,2,0),
(82,55,4,3,2,0),
(151,90,11,17,5,1),
(113,32,5,2,1,0),
(45,55,3,2,0,0),
(53,55,2,7,1,0),
(168,86,12,15,7,1),
(18,65,5,2,0,0),
(93,37,3,6,1,0),
(35,32,1,3,2,0),
(148,79,13,14,4,1)
;
SELECT COUNT(*) AS total, SUM(readmit_30d) AS readmitted FROM adm_dis;
-- → 170 rows, 24 readmitted
Step 2 — Train + deploy
CREATE EXPERIMENT readm_clf AS
SELECT age, los_days, num_meds, prior_admits, readmit_30d AS target
FROM adm_dis
WITH (
task_type = 'binary_classification',
target_column = 'target',
optimization_metric = 'auc',
max_trials = 8,
time_budget_seconds = 120,
algorithms = ['logistic_regression', 'random_forest', 'gradient_boosting'],
validation_strategy = 'kfold',
n_folds = 3,
feature_engineering = false,
hyperparameter_strategy = 'random'
);
DEPLOY MODEL readm_pred FROM EXPERIMENT readm_clf;
-- best_score = 1.0
Step 3 — Score at discharge
-- 32yo, 2 days LOS, 3 meds, no prior admits
SELECT AUTOML.PREDICT('readm_pred', 32, 2, 3, 0) AS risk;
-- → 0.083 (LOW)
-- 84yo, 14 days LOS, 14 meds, 5 prior admits
SELECT AUTOML.PREDICT('readm_pred', 84, 14, 14, 5) AS risk;
-- → 0.962 (CASE MGMT FOLLOW-UP)
Step 4 — Sweep today's discharge list
SELECT id, age, los_days, num_meds, prior_admits,
AUTOML.PREDICT('readm_pred', age, los_days, num_meds, prior_admits) AS risk
FROM adm_dis
WHERE id > 100 -- imagine these are today's discharges
ORDER BY risk DESC
LIMIT 10;
Productionizing
Wire risk > 0.7 → case-management follow-up assignment, retrain
quarterly with CMS-aligned features (HCC codes, social determinants).