Mercurial > repos > goeckslab > multimodal_learner
view test-data/sample_output.html @ 0:375c36923da1 draft default tip
planemo upload for repository https://github.com/goeckslab/gleam.git commit 1c6c1ad7a1b2bd3645aa0eafa2167784820b52e0
| author | goeckslab |
|---|---|
| date | Tue, 09 Dec 2025 23:49:47 +0000 |
| parents | |
| children |
line wrap: on
line source
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Galaxy-Ludwig Report</title> <style> body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f4f4f4; } .container { max-width: 1200px; margin: auto; background: white; padding: 20px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); overflow-x: auto; } h1 { text-align: center; color: #333; } h2 { border-bottom: 2px solid #4CAF50; color: #4CAF50; padding-bottom: 5px; margin-top: 28px; } h3 { margin-top: 20px; color: #333; } .section { margin-bottom: 30px; } .section-title { border-bottom: 2px solid #4CAF50; color: #4CAF50; padding-bottom: 5px; margin-top: 28px; } .card { background: #fff; padding: 15px; border: 1px solid #ddd; border-radius: 4px; margin: 10px 0; } /* baseline table setup */ table { border-collapse: collapse; margin: 20px 0; width: 100%; table-layout: fixed; background: #fff; } table, th, td { border: 1px solid #ddd; } th, td { padding: 10px; text-align: center; vertical-align: middle; word-break: break-word; white-space: normal; overflow-wrap: anywhere; } th { background-color: #4CAF50; color: white; } .metric-table { width: 100%; } .kv-table { width: 100%; } .kv-table th:first-child, .kv-table td:first-child { text-align: left; width: 30%; } .plot { text-align: center; margin: 20px 0; } .plot img { max-width: 100%; height: auto; border: 1px solid #ddd; } /* ------------------- sortable columns (3-state: none ⇅, asc ↑, desc ↓) ------------------- */ table.performance-summary th.sortable { cursor: pointer; position: relative; user-select: none; } /* default icon space */ table.performance-summary th.sortable::after { content: '⇅'; position: absolute; right: 12px; top: 50%; transform: translateY(-50%); font-size: 0.8em; color: #eaf5ea; /* light on green */ text-shadow: 0 0 1px rgba(0,0,0,0.15); } /* three states override the default */ table.performance-summary th.sortable.sorted-none::after { content: '⇅'; color: #eaf5ea; } table.performance-summary th.sortable.sorted-asc::after { content: '↑'; color: #ffffff; } table.performance-summary th.sortable.sorted-desc::after { content: '↓'; color: #ffffff; } /* show ~30 rows with a scrollbar (tweak if you want) */ .scroll-rows-30 { max-height: 900px; /* ~30 rows depending on row height */ overflow-y: auto; /* vertical scrollbar ("sidebar") */ overflow-x: auto; } /* Tabs + Help button (used by build_tabbed_html) */ .tabs { display: flex; align-items: center; border-bottom: 2px solid #ccc; margin-bottom: 1rem; gap: 6px; flex-wrap: wrap; } .tab { padding: 10px 20px; cursor: pointer; border: 1px solid #ccc; border-bottom: none; background: #f9f9f9; margin-right: 5px; border-top-left-radius: 8px; border-top-right-radius: 8px; } .tab.active { background: white; font-weight: bold; } .help-btn { margin-left: auto; padding: 6px 12px; font-size: 0.9rem; border: 1px solid #4CAF50; border-radius: 4px; background: #4CAF50; color: white; cursor: pointer; } .tab-content { display: none; padding: 20px; border: 1px solid #ccc; border-top: none; background: #fff; } .tab-content.active { display: block; } .plotly-center { display: flex; justify-content: center; } .plotly-center .plotly-graph-div, .plotly-center .js-plotly-plot { margin: 0 auto !important; } .js-plotly-plot, .plotly-graph-div { margin-left: auto !important; margin-right: auto !important; } /* Modal (used by get_metrics_help_modal) */ .modal { display: none; position: fixed; z-index: 9999; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4); } .modal-content { background-color: #fefefe; margin: 8% auto; padding: 20px; border: 1px solid #888; width: 90%; max-width: 900px; border-radius: 8px; } .modal .close { color: #777; float: right; font-size: 28px; font-weight: bold; line-height: 1; margin-left: 8px; } .modal .close:hover, .modal .close:focus { color: black; text-decoration: none; cursor: pointer; } .metrics-guide h3 { margin-top: 20px; } .metrics-guide p { margin: 6px 0; } .metrics-guide ul { margin: 10px 0; padding-left: 20px; } </style> <script> // Guard to avoid double-initialization if this block is included twice (function(){ if (window.__perfSummarySortInit) return; window.__perfSummarySortInit = true; function initPerfSummarySorting() { // Record original order for "back to original" document.querySelectorAll('table.performance-summary tbody').forEach(tbody => { Array.from(tbody.rows).forEach((row, i) => { row.dataset.originalOrder = i; }); }); const getText = td => (td?.innerText || '').trim(); const cmp = (idx, asc) => (a, b) => { const v1 = getText(a.children[idx]); const v2 = getText(b.children[idx]); const n1 = parseFloat(v1), n2 = parseFloat(v2); if (!isNaN(n1) && !isNaN(n2)) return asc ? n1 - n2 : n2 - n1; // numeric return asc ? v1.localeCompare(v2) : v2.localeCompare(v1); // lexical }; document.querySelectorAll('table.performance-summary th.sortable').forEach(th => { // initialize to "none" th.classList.remove('sorted-asc','sorted-desc'); th.classList.add('sorted-none'); th.addEventListener('click', () => { const table = th.closest('table'); const headerRow = th.parentNode; const allTh = headerRow.querySelectorAll('th.sortable'); const tbody = table.querySelector('tbody'); // Determine current state BEFORE clearing const isAsc = th.classList.contains('sorted-asc'); const isDesc = th.classList.contains('sorted-desc'); // Reset all headers in this row allTh.forEach(x => x.classList.remove('sorted-asc','sorted-desc','sorted-none')); // Compute next state let next; if (!isAsc && !isDesc) { next = 'asc'; } else if (isAsc) { next = 'desc'; } else { next = 'none'; } th.classList.add('sorted-' + next); // Sort rows according to the chosen state const rows = Array.from(tbody.rows); if (next === 'none') { rows.sort((a, b) => (a.dataset.originalOrder - b.dataset.originalOrder)); } else { const idx = Array.from(headerRow.children).indexOf(th); rows.sort(cmp(idx, next === 'asc')); } rows.forEach(r => tbody.appendChild(r)); }); }); } // Run after DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initPerfSummarySorting); } else { initPerfSummarySorting(); } })(); </script> </head> <body> <div class="container"> <script src="https://cdn.plot.ly/plotly-2.30.0.min.js"></script> <style> .plotly-center { display: flex; justify-content: center; margin: 20px 0; width: 100%; } .plotly-center .plotly-graph-div, .plotly-center .js-plotly-plot { margin: 0 auto !important; } .js-plotly-plot, .plotly-graph-div { margin-left: auto !important; margin-right: auto !important; } #learning-curve-accuracy, #learning-curve-loss, #threshold-plot, #confusion-matrix, #per-class-metrics, #roc-curve, #pr-curve { min-height: 400px; } </style> <div class="tabs"> <div class="tab active" onclick="showTab('summary')">Model Summary & Config</div> <div class="tab" onclick="showTab('train')">Train/Validation Summary</div> <div class="tab" onclick="showTab('test')">Test Summary</div> <div class="tab" onclick="showTab('feature')">Feature Importance</div> <button id="openMetricsHelp" class="help-btn">Help</button> </div> <!-- Summary Tab --> <div id="summary" class="tab-content active"> <section class="section"> <h2 class="section-title">Model Performance Summary</h2> <div class="card"> <table class="metric-table"> <thead><tr><th>Metric</th><th>Train</th><th>Validation</th><th>Test</th></tr></thead> <tbody> <tr><td>accuracy</td><td>0.9234</td><td>0.8912</td><td>0.8856</td></tr> <tr><td>f1</td><td>0.9201</td><td>0.8876</td><td>0.8823</td></tr> <tr><td>precision</td><td>0.9156</td><td>0.8845</td><td>0.8798</td></tr> <tr><td>recall</td><td>0.9245</td><td>0.8907</td><td>0.8849</td></tr> <tr><td>roc_auc</td><td>0.9789</td><td>0.9543</td><td>0.9512</td></tr> <tr><td>log_loss</td><td>0.2134</td><td>0.2876</td><td>0.3012</td></tr> </tbody> </table> </div> </section> <section class="section"> <h2 class="section-title">Run Configuration</h2> <div class="card"> <table class="kv-table"> <thead><tr><th>Key</th><th>Value</th></tr></thead> <tbody> <tr><td>Predictor type</td><td>MultiModalPredictor</td></tr> <tr><td>Framework</td><td>AutoGluon Multimodal</td></tr> <tr><td>Model architecture</td><td>timm_image=resnet50, hf_text=bert-base-uncased</td></tr> <tr><td>Modalities & Inputs</td><td>Images + Tabular</td></tr> <tr><td>Label column</td><td>target</td></tr> <tr><td>Image columns</td><td>image_path</td></tr> <tr><td>Tabular columns</td><td>15</td></tr> <tr><td>Presets</td><td>medium_quality</td></tr> <tr><td>Eval metric</td><td>accuracy</td></tr> <tr><td>Decision threshold calibration</td><td>enabled</td></tr> <tr><td>Decision threshold (Test only)</td><td>0.500</td></tr> <tr><td>Seed</td><td>42</td></tr> <tr><td>time limit(s)</td><td>3600</td></tr> </tbody> </table> </div> </section> <section class="section"> <h2 class="section-title">Class Balance (Train Full)</h2> <div class="card"> <h3>Class Balance (Train Full)</h3> <table class="table"> <thead><tr><th>Class</th><th>Count</th><th>Percent</th></tr></thead> <tbody> <tr><td>0</td><td>1245</td><td>45.23%</td></tr> <tr><td>1</td><td>1508</td><td>54.77%</td></tr> </tbody> </table> </div> </section> </div> <!-- Train Tab --> <div id="train" class="tab-content"> <h2>Train/Validation Performance Summary</h2> <div class="card"> <table class="metric-table"> <thead><tr><th>Metric</th><th>Train</th><th>Validation</th></tr></thead> <tbody> <tr><td>accuracy</td><td>0.9234</td><td>0.8912</td></tr> <tr><td>f1</td><td>0.9201</td><td>0.8876</td></tr> <tr><td>precision</td><td>0.9156</td><td>0.8845</td></tr> <tr><td>recall</td><td>0.9245</td><td>0.8907</td></tr> <tr><td>roc_auc</td><td>0.9789</td><td>0.9543</td></tr> <tr><td>log_loss</td><td>0.2134</td><td>0.2876</td></tr> </tbody> </table> </div> <h2>Learning Curves — Label Accuracy</h2> <div class="plotly-center"> <div id="learning-curve-accuracy" style="width:900px;height:500px;"></div> </div> <h2>Learning Curves — Label Loss</h2> <div class="plotly-center"> <div id="learning-curve-loss" style="width:900px;height:500px;"></div> </div> </div> <!-- Test Tab --> <div id="test" class="tab-content"> <h2>Test Performance Summary</h2> <table class="performance-summary"> <thead> <tr> <th class="sortable">Metric</th> <th class="sortable">Test</th> </tr> </thead> <tbody> <tr><td>accuracy</td><td>0.8856</td></tr> <tr><td>f1</td><td>0.8823</td></tr> <tr><td>precision</td><td>0.8798</td></tr> <tr><td>recall</td><td>0.8849</td></tr> <tr><td>roc_auc</td><td>0.9512</td></tr> <tr><td>log_loss</td><td>0.3012</td></tr> <tr><td>specificity (TNR)</td><td>0.8765</td></tr> <tr><td>sensitivity (Sensitivity/TPR)</td><td>0.8923</td></tr> </tbody> </table> <h2>Confusion Matrix</h2> <div class="plotly-center"> <div id="confusion-matrix" style="width:700px;height:600px;"></div> </div> <h2>Per-Class Metrics</h2> <div class="plotly-center"> <div id="per-class-metrics" style="width:900px;height:500px;"></div> </div> <h2>ROC Curve</h2> <div class="plotly-center"> <div id="roc-curve" style="width:800px;height:600px;"></div> </div> <h2>Precision–Recall Curve</h2> <div class="plotly-center"> <div id="pr-curve" style="width:800px;height:600px;"></div> </div> <h2>Threshold Plot</h2> <div class="plotly-center"> <div id="threshold-plot" style="width:900px;height:500px;"></div> </div> </div> <!-- Feature Importance Tab --> <div id="feature" class="tab-content"> <section class="section"> <h2 class="section-title">Feature Importance</h2> <div class="card"> <p>Permutation importance is not supported for MultiModalPredictor in this tool. For tabular-only runs, this section shows permutation importance.</p> </div> </section> <section class="section"> <h2 class="section-title">Modalities & Inputs</h2> <div class="card"> <h3>Modalities & Inputs</h3> <p>This run used <b>MultiModalPredictor</b> (images + tabular).</p> <p><b>Label column:</b> target</p> <p><b>Image column:</b> image_path</p> <div><b>Tabular columns:</b> 15 <ul> <li>feature_1</li> <li>feature_2</li> <li>feature_3</li> <li>feature_4</li> <li>feature_5</li> <li>feature_6</li> <li>feature_7</li> <li>feature_8</li> <li>feature_9</li> <li>feature_10</li> <li>feature_11</li> <li>feature_12</li> <li>feature_13</li> <li>feature_14</li> <li>feature_15</li> </ul> </div> </div> </section> </div> <script> function showTab(id) { document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active')); document.querySelectorAll('.tab').forEach(el => el.classList.remove('active')); document.getElementById(id).classList.add('active'); document.querySelector(`.tab[onclick*="${id}"]`).classList.add('active'); } // Fixed random data for reproducibility const epochs = Array.from({length: 31}, (_, i) => i); const accuracy_train = [0.552, 0.568, 0.581, 0.595, 0.612, 0.628, 0.645, 0.662, 0.678, 0.692, 0.708, 0.722, 0.735, 0.748, 0.761, 0.773, 0.784, 0.795, 0.805, 0.814, 0.823, 0.831, 0.839, 0.846, 0.853, 0.859, 0.865, 0.870, 0.875, 0.880, 0.884]; const accuracy_val = [0.752, 0.768, 0.782, 0.795, 0.807, 0.818, 0.828, 0.837, 0.845, 0.852, 0.859, 0.865, 0.871, 0.876, 0.881, 0.885, 0.889, 0.893, 0.896, 0.899, 0.902, 0.905, 0.907, 0.909, 0.911, 0.913, 0.915, 0.917, 0.918, 0.920, 0.921]; const loss_train = [1.352, 1.285, 1.221, 1.158, 1.098, 1.041, 0.987, 0.936, 0.888, 0.842, 0.799, 0.758, 0.720, 0.684, 0.650, 0.618, 0.588, 0.560, 0.534, 0.510, 0.487, 0.466, 0.447, 0.429, 0.412, 0.397, 0.383, 0.370, 0.358, 0.347, 0.337]; const loss_val = [0.802, 0.765, 0.730, 0.697, 0.666, 0.637, 0.610, 0.585, 0.561, 0.539, 0.518, 0.499, 0.481, 0.464, 0.448, 0.433, 0.419, 0.406, 0.394, 0.383, 0.372, 0.362, 0.353, 0.345, 0.337, 0.330, 0.323, 0.317, 0.311, 0.306, 0.301]; // Wait for Plotly to load before creating plots function createPlots() { if (typeof Plotly === 'undefined') { console.log('Waiting for Plotly...'); setTimeout(createPlots, 100); return; } console.log('Plotly loaded, creating plots...'); // Learning Curves — Label Accuracy (with both training and validation) try { Plotly.newPlot('learning-curve-accuracy', [ { x: epochs, y: accuracy_train, type: 'scatter', mode: 'lines+markers', name: 'Training', line: { width: 3, color: '#1f77b4', shape: 'spline' }, marker: { size: 8, color: '#1f77b4' } }, { x: epochs, y: accuracy_val, type: 'scatter', mode: 'lines+markers', name: 'Validation', line: { width: 3, color: '#ff7f0e', shape: 'spline' }, marker: { size: 8, color: '#ff7f0e' } } ], { template: 'plotly_white', xaxis: { title: 'Epoch', gridcolor: '#e0e0e0', showgrid: true, zeroline: false }, yaxis: { title: 'Accuracy', gridcolor: '#e0e0e0', showgrid: true, zeroline: false, range: [0.5, 1.0] }, legend: { orientation: 'h', yanchor: 'bottom', y: 1.02, xanchor: 'right', x: 1.0 }, margin: { l: 60, r: 20, t: 40, b: 50 }, plot_bgcolor: 'white', paper_bgcolor: 'white' }); console.log('Accuracy plot created'); } catch(e) { console.error('Error creating accuracy plot:', e); } // Learning Curves — Label Loss (with both training and validation) try { Plotly.newPlot('learning-curve-loss', [ { x: epochs, y: loss_train, type: 'scatter', mode: 'lines+markers', name: 'Training Loss', line: { width: 3, color: '#1f77b4', shape: 'spline' }, marker: { size: 8, color: '#1f77b4' } }, { x: epochs, y: loss_val, type: 'scatter', mode: 'lines+markers', name: 'Validation Loss', line: { width: 3, color: '#ff7f0e', shape: 'spline' }, marker: { size: 8, color: '#ff7f0e' } } ], { template: 'plotly_white', xaxis: { title: 'Epoch', gridcolor: '#e0e0e0', showgrid: true, zeroline: false }, yaxis: { title: 'Loss', gridcolor: '#e0e0e0', showgrid: true, zeroline: false, range: [0.2, 1.4] }, legend: { orientation: 'h', yanchor: 'bottom', y: 1.02, xanchor: 'right', x: 1.0 }, margin: { l: 60, r: 20, t: 40, b: 50 }, plot_bgcolor: 'white', paper_bgcolor: 'white' }); console.log('Loss plot created'); } catch(e) { console.error('Error creating loss plot:', e); } // Threshold Plot (with fixed data matching the expected visualization) // Precision: starts low (~0.42), increases to peak (~0.95) around threshold 0.5, then drops sharply to 0 // Recall: starts at 1, stays at 1 until ~0.1, then decreases to 0 around 0.9 // F1: starts around 0.6, peaks around 0.5 at ~0.95, then drops to 0 const thresholds = Array.from({length: 101}, (_, i) => i / 100); // Generate precision values: low at start, peak around 0.5, drop to 0 const precision_vals = thresholds.map(t => { if (t <= 0.5) { return 0.42 + (t / 0.5) * 0.53; // 0.42 to 0.95 } else if (t <= 0.9) { return 0.95 - ((t - 0.5) / 0.4) * 0.95; // 0.95 to 0 } else { return 0; } }); // Generate recall values: starts at 1, stays at 1 until ~0.1, then decreases to 0 around 0.9 const recall_vals = thresholds.map(t => { if (t <= 0.1) { return 1.0; } else if (t <= 0.9) { return 1.0 - ((t - 0.1) / 0.8) * 1.0; // 1.0 to 0 } else { return 0; } }); // Calculate F1 from precision and recall const f1_vals = thresholds.map((t, i) => { const p = precision_vals[i]; const r = recall_vals[i]; if (p + r === 0) return 0; return 2 * (p * r) / (p + r); }); // Queue Rate: decreases linearly from 1 to 0 const queue_rate = thresholds.map(t => 1 - t); try { Plotly.newPlot('threshold-plot', [ { x: thresholds, y: precision_vals, type: 'scatter', mode: 'lines', name: 'Precision', line: { width: 3, color: '#1f77b4' } }, { x: thresholds, y: recall_vals, type: 'scatter', mode: 'lines', name: 'Recall', line: { width: 3, color: '#ff7f0e' } }, { x: thresholds, y: f1_vals, type: 'scatter', mode: 'lines', name: 'F1', line: { width: 3, color: '#2ca02c' } }, { x: thresholds, y: queue_rate, type: 'scatter', mode: 'lines', name: 'Queue Rate', line: { width: 2, color: '#808080', dash: 'dash' } } ], { template: 'plotly_white', xaxis: { title: 'Discrimination Threshold', gridcolor: '#e0e0e0', showgrid: true, zeroline: false }, yaxis: { title: 'Score', gridcolor: '#e0e0e0', showgrid: true, zeroline: false, range: [0, 1] }, legend: { orientation: 'h', yanchor: 'bottom', y: 1.02, xanchor: 'right', x: 1.0 }, margin: { l: 60, r: 20, t: 40, b: 50 }, plot_bgcolor: 'white', paper_bgcolor: 'white', shapes: [{ type: 'line', xref: 'x', yref: 'y', x0: 0.51, y0: 0, x1: 0.51, y1: 1, line: { color: 'black', width: 2, dash: 'dash' } }], annotations: [{ x: 0.51, y: 0.85, text: 't* = 0.51', showarrow: false, font: { size: 12, color: 'black' } }] }); console.log('Threshold plot created'); } catch(e) { console.error('Error creating threshold plot:', e); } // Confusion Matrix (matching imagelearner style with Blues colorscale) const cm_data = [[542, 78], [65, 515]]; const total = cm_data.flat().reduce((a, b) => a + b, 0); const labels = ['0', '1']; // Build annotations array with all white text const annotations = []; cm_data.forEach((row, i) => { row.forEach((val, j) => { const pct = ((val / total) * 100).toFixed(1); // All text is white const textColor = 'white'; // Count annotation (bold, bottom) annotations.push({ x: labels[j], y: labels[i], text: '<b>' + val + '</b>', showarrow: false, font: { color: textColor, size: 14 }, xanchor: 'center', yanchor: 'bottom', yshift: 2 }); // Percentage annotation (top) annotations.push({ x: labels[j], y: labels[i], text: pct + '%', showarrow: false, font: { color: textColor, size: 13 }, xanchor: 'center', yanchor: 'top', yshift: -2 }); }); }); try { Plotly.newPlot('confusion-matrix', [{ z: cm_data, x: labels, y: labels, type: 'heatmap', colorscale: 'Blues', showscale: true, colorbar: { title: 'Count' }, xgap: 2, ygap: 2, hovertemplate: 'True=%{y}<br>Pred=%{x}<br>Count=%{z}<extra></extra>', zmin: 0 }], { xaxis: { title: 'Predicted label', type: 'category' }, yaxis: { title: 'True label', type: 'category', autorange: 'reversed' }, margin: { l: 80, r: 20, t: 40, b: 80 }, template: 'plotly_white', plot_bgcolor: 'white', paper_bgcolor: 'white', annotations: annotations }); console.log('Confusion matrix created'); } catch(e) { console.error('Error creating confusion matrix:', e); } // Per-Class Metrics const classes = ['Class 0', 'Class 1']; const precision_per_class = [0.8929, 0.8685]; const recall_per_class = [0.8742, 0.8879]; const f1_per_class = [0.8835, 0.8781]; try { Plotly.newPlot('per-class-metrics', [ { x: classes, y: precision_per_class, type: 'bar', name: 'Precision', marker: { color: '#4CAF50' } }, { x: classes, y: recall_per_class, type: 'bar', name: 'Recall', marker: { color: '#2196F3' } }, { x: classes, y: f1_per_class, type: 'bar', name: 'F1', marker: { color: '#FF9800' } } ], { template: 'plotly_white', xaxis: { title: 'Class', gridcolor: '#e0e0e0', showgrid: true }, yaxis: { title: 'Score', gridcolor: '#e0e0e0', showgrid: true, range: [0, 1] }, barmode: 'group', legend: { orientation: 'h', yanchor: 'bottom', y: 1.02, xanchor: 'right', x: 1.0 }, margin: { l: 60, r: 20, t: 40, b: 50 }, plot_bgcolor: 'white', paper_bgcolor: 'white' }); console.log('Per-class metrics created'); } catch(e) { console.error('Error creating per-class metrics:', e); } // ROC Curve (with fixed data) const fpr = [0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.20,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.30,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.40,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.50,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.60,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.70,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.80,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.90,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.00]; const tpr = [0,0.12,0.23,0.33,0.42,0.50,0.57,0.63,0.69,0.74,0.78,0.82,0.85,0.88,0.90,0.92,0.94,0.95,0.96,0.97,0.98,0.985,0.99,0.992,0.994,0.996,0.997,0.998,0.999,0.9995,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]; const auc_score = 0.935; try { Plotly.newPlot('roc-curve', [ { x: [0, 1], y: [0, 1], type: 'scatter', mode: 'lines', name: 'Random (AUC = 0.50)', line: { dash: 'dash', color: 'gray', width: 2 } }, { x: fpr, y: tpr, type: 'scatter', mode: 'lines', name: `ROC Curve (AUC = ${auc_score.toFixed(3)})`, line: { width: 3, color: '#1f77b4' } } ], { template: 'plotly_white', xaxis: { title: 'False Positive Rate', gridcolor: '#e0e0e0', showgrid: true, zeroline: false, range: [0, 1] }, yaxis: { title: 'True Positive Rate', gridcolor: '#e0e0e0', showgrid: true, zeroline: false, range: [0, 1] }, legend: { orientation: 'h', yanchor: 'bottom', y: 1.02, xanchor: 'right', x: 1.0 }, margin: { l: 60, r: 20, t: 40, b: 50 }, plot_bgcolor: 'white', paper_bgcolor: 'white' }); console.log('ROC curve created'); } catch(e) { console.error('Error creating ROC curve:', e); } // Precision-Recall Curve (with fixed data) const recall_pr = [0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.10,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.20,0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.30,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.40,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.50,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.60,0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.70,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.80,0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.90,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1.00]; const precision_pr = [0.95,0.949,0.948,0.947,0.946,0.945,0.944,0.943,0.942,0.941,0.940,0.939,0.938,0.937,0.936,0.935,0.934,0.933,0.932,0.931,0.930,0.929,0.928,0.927,0.926,0.925,0.924,0.923,0.922,0.921,0.920,0.919,0.918,0.917,0.916,0.915,0.914,0.913,0.912,0.911,0.910,0.909,0.908,0.907,0.906,0.905,0.904,0.903,0.902,0.901,0.900,0.899,0.898,0.897,0.896,0.895,0.894,0.893,0.892,0.891,0.890,0.889,0.888,0.887,0.886,0.885,0.884,0.883,0.882,0.881,0.880,0.879,0.878,0.877,0.876,0.875,0.874,0.873,0.872,0.871,0.870,0.869,0.868,0.867,0.866,0.865,0.864,0.863,0.862,0.861,0.860,0.859,0.858,0.857,0.856,0.855,0.854,0.853,0.852,0.851,0.850]; const ap_score = 0.9234; try { Plotly.newPlot('pr-curve', [ { x: recall_pr, y: precision_pr, type: 'scatter', mode: 'lines', name: `Precision-Recall Curve (AP = ${ap_score.toFixed(4)})`, line: { width: 3, color: '#1f77b4' } } ], { template: 'plotly_white', xaxis: { title: 'Recall', gridcolor: '#e0e0e0', showgrid: true, zeroline: false, range: [0, 1] }, yaxis: { title: 'Precision', gridcolor: '#e0e0e0', showgrid: true, zeroline: false, range: [0.6, 1] }, legend: { orientation: 'h', yanchor: 'bottom', y: 1.02, xanchor: 'right', x: 1.0 }, margin: { l: 60, r: 20, t: 40, b: 50 }, plot_bgcolor: 'white', paper_bgcolor: 'white' }); console.log('PR curve created'); } catch(e) { console.error('Error creating PR curve:', e); } console.log('All plots created successfully!'); } // Start creating plots when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', createPlots); } else { createPlots(); } </script> </div> </body> </html>
