| <!doctype html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <title>Engine Sound Classifier</title> |
| <style> |
| :root { |
| color-scheme: light; |
| --page: #f9f9f7; |
| --surface-1: #fcfcfb; |
| --text-primary: #0b0b0b; |
| --text-secondary: #52514e; |
| --text-muted: #898781; |
| --grid: #e1e0d9; |
| --baseline: #c3c2b7; |
| --border: rgba(11,11,11,0.10); |
| --series-1: #2a78d6; |
| --series-1-wash: rgba(42,120,214,0.10); |
| --link: #1c5cab; |
| } |
| @media (prefers-color-scheme: dark) { |
| :root:where(:not([data-theme="light"])) { |
| color-scheme: dark; |
| --page: #0d0d0d; |
| --surface-1: #1a1a19; |
| --text-primary: #ffffff; |
| --text-secondary: #c3c2b7; |
| --text-muted: #898781; |
| --grid: #2c2c2a; |
| --baseline: #383835; |
| --border: rgba(255,255,255,0.10); |
| --series-1: #3987e5; |
| --series-1-wash: rgba(57,135,229,0.14); |
| --link: #86b6ef; |
| } |
| } |
| :root[data-theme="dark"] { |
| color-scheme: dark; |
| --page: #0d0d0d; |
| --surface-1: #1a1a19; |
| --text-primary: #ffffff; |
| --text-secondary: #c3c2b7; |
| --text-muted: #898781; |
| --grid: #2c2c2a; |
| --baseline: #383835; |
| --border: rgba(255,255,255,0.10); |
| --series-1: #3987e5; |
| --series-1-wash: rgba(57,135,229,0.14); |
| --link: #86b6ef; |
| } |
| |
| * { box-sizing: border-box; } |
| body { |
| margin: 0; |
| background: var(--page); |
| color: var(--text-primary); |
| font: 16px/1.55 system-ui, -apple-system, "Segoe UI", sans-serif; |
| } |
| main { |
| max-width: 760px; |
| margin: 0 auto; |
| padding: 48px 20px 80px; |
| } |
| h1 { font-size: 1.7rem; margin: 0 0 6px; } |
| h2 { font-size: 1.15rem; margin: 40px 0 12px; } |
| .tagline { color: var(--text-secondary); margin: 0 0 20px; } |
| .status { |
| display: inline-block; |
| font-size: 0.85rem; |
| color: var(--text-secondary); |
| background: var(--series-1-wash); |
| border: 1px solid var(--border); |
| border-radius: 6px; |
| padding: 4px 10px; |
| margin-bottom: 20px; |
| } |
| p { color: var(--text-secondary); } |
| a { color: var(--link); } |
| code { |
| background: var(--surface-1); |
| border: 1px solid var(--border); |
| border-radius: 4px; |
| padding: 1px 5px; |
| font-size: 0.9em; |
| } |
| |
| .card { |
| background: var(--surface-1); |
| border: 1px solid var(--border); |
| border-radius: 10px; |
| padding: 20px; |
| } |
| |
| .samples { display: grid; gap: 12px; } |
| .sample-row { |
| display: flex; |
| align-items: center; |
| gap: 14px; |
| flex-wrap: wrap; |
| } |
| .sample-label { min-width: 170px; font-size: 0.95rem; color: var(--text-primary); } |
| audio { flex: 1; min-width: 220px; height: 36px; } |
| |
| |
| .chart { padding: 4px 4px 0; } |
| .bar-row { |
| display: grid; |
| grid-template-columns: 90px 1fr 56px; |
| align-items: center; |
| gap: 10px; |
| height: 40px; |
| position: relative; |
| } |
| .bar-row + .bar-row { border-top: 1px solid var(--grid); } |
| .bar-cat { font-size: 0.9rem; color: var(--text-secondary); } |
| .bar-track { position: relative; height: 24px; } |
| .bar-fill { |
| position: absolute; |
| left: 0; top: 0; |
| height: 24px; |
| border-radius: 4px; |
| background: var(--series-1); |
| transition: filter 0.1s ease; |
| } |
| .bar-fill.best { background: var(--series-1); } |
| .bar-fill:hover { filter: brightness(1.08); } |
| .bar-value { font-size: 0.9rem; color: var(--text-primary); text-align: right; font-variant-numeric: tabular-nums; } |
| .chart-axis { |
| display: grid; |
| grid-template-columns: 90px 1fr 56px; |
| gap: 10px; |
| margin-top: 6px; |
| border-top: 1px solid var(--baseline); |
| padding-top: 4px; |
| } |
| .chart-axis span { font-size: 0.75rem; color: var(--text-muted); } |
| .chart-axis .ticks { position: relative; height: 14px; } |
| .chart-axis .ticks i { position: absolute; top: 0; font-style: normal; } |
| |
| .tooltip { |
| position: absolute; |
| pointer-events: none; |
| background: var(--text-primary); |
| color: var(--page); |
| font-size: 0.78rem; |
| padding: 5px 8px; |
| border-radius: 5px; |
| white-space: nowrap; |
| transform: translate(-50%, -130%); |
| opacity: 0; |
| transition: opacity 0.1s ease; |
| z-index: 5; |
| } |
| .bar-row:hover .tooltip { opacity: 1; } |
| |
| table.perf { |
| width: 100%; |
| border-collapse: collapse; |
| font-size: 0.88rem; |
| margin-top: 14px; |
| } |
| table.perf caption { text-align: left; color: var(--text-muted); font-size: 0.78rem; margin-bottom: 6px; } |
| table.perf th, table.perf td { |
| text-align: left; |
| padding: 6px 8px; |
| border-bottom: 1px solid var(--grid); |
| color: var(--text-secondary); |
| } |
| table.perf th { color: var(--text-primary); font-weight: 600; } |
| table.perf td.num, table.perf th.num { text-align: right; font-variant-numeric: tabular-nums; } |
| |
| ul.weak { color: var(--text-secondary); padding-left: 20px; } |
| ul.weak li { margin-bottom: 6px; } |
| |
| .links { display: flex; flex-wrap: wrap; gap: 10px 24px; margin-top: 8px; } |
| .links a { font-size: 0.95rem; } |
| |
| footer { |
| margin-top: 48px; |
| padding-top: 16px; |
| border-top: 1px solid var(--grid); |
| color: var(--text-muted); |
| font-size: 0.82rem; |
| } |
| </style> |
| </head> |
| <body> |
| <main> |
| <h1>Engine Sound Classifier</h1> |
| <p class="tagline"> |
| A fine-tuned <a href="https://github.com/qiuqiangkong/audioset_tagging_cnn" target="_blank" rel="noopener">PANNs CNN14</a> |
| (pretrained on AudioSet) that classifies short engine-audio clips into one of |
| 34 configurations — cylinder count, layout, and stroke type (e.g. <code>i4</code>, |
| <code>v8_cross</code>, <code>single_two_stroke</code>, <code>2_rotor</code>). |
| </p> |
| <span class="status">Early checkpoint · ~0.33 balanced accuracy · 34 classes</span> |
|
|
| <p> |
| This is a static, informational Space — it doesn't run the model. It exists |
| so you can hear a few labeled example clips and see how the model is doing |
| without needing to spin up compute. To actually run inference, download the |
| checkpoint from the model repo linked below. |
| </p> |
|
|
| <h2>Example clips</h2> |
| <div class="card samples"> |
| <div class="sample-row"> |
| <span class="sample-label"><code>i2_360</code></span> |
| <audio controls preload="none" src="audio/i2_360.wav"></audio> |
| </div> |
| <div class="sample-row"> |
| <span class="sample-label"><code>v2_45</code></span> |
| <audio controls preload="none" src="audio/v2_45.wav"></audio> |
| </div> |
| <div class="sample-row"> |
| <span class="sample-label"><code>single_two_stroke</code></span> |
| <audio controls preload="none" src="audio/single_two_stroke.wav"></audio> |
| </div> |
| </div> |
|
|
| <h2>Performance by run</h2> |
| <div class="card"> |
| <div class="chart" id="chart"> |
| <div class="bar-row"> |
| <span class="bar-cat">Run A</span> |
| <div class="bar-track"> |
| <span style="font-size: 0.82rem; color: var(--text-muted);">balanced accuracy not tracked this run (micro 0.380, overfit)</span> |
| </div> |
| <span class="bar-value">—</span> |
| </div> |
| <div class="bar-row"> |
| <span class="bar-cat">Run B</span> |
| <div class="bar-track"> |
| <div class="bar-fill" style="width: 74.25%"></div> |
| <div class="tooltip" style="left: 74.25%">0.297 balanced · 0.311 micro</div> |
| </div> |
| <span class="bar-value">0.297</span> |
| </div> |
| <div class="bar-row"> |
| <span class="bar-cat">Run C</span> |
| <div class="bar-track"> |
| <div class="bar-fill" style="width: 80.75%"></div> |
| <div class="tooltip" style="left: 80.75%">0.323 balanced · 0.343 micro</div> |
| </div> |
| <span class="bar-value">0.323</span> |
| </div> |
| <div class="bar-row"> |
| <span class="bar-cat">Run D</span> |
| <div class="bar-track"> |
| <div class="bar-fill best" style="width: 82.5%"></div> |
| <div class="tooltip" style="left: 82.5%">0.330 balanced · 0.376 micro (best)</div> |
| </div> |
| <span class="bar-value"><strong>0.330</strong></span> |
| </div> |
| <div class="chart-axis"> |
| <span></span> |
| <div class="ticks"> |
| <i style="left: 0%">0.0</i> |
| <i style="left: 50%">0.2</i> |
| <i style="right: 0%">0.4</i> |
| </div> |
| <span></span> |
| </div> |
| </div> |
| <table class="perf"> |
| <caption>Recording-level balanced accuracy is the headline metric; random guessing over 34 classes is ~0.03.</caption> |
| <thead> |
| <tr><th>Run</th><th>Change</th><th class="num">Balanced acc</th><th class="num">Micro acc</th></tr> |
| </thead> |
| <tbody> |
| <tr><td>A</td><td>baseline (no regularization)</td><td class="num">—</td><td class="num">0.380 (overfit)</td></tr> |
| <tr><td>B</td><td>+ SpecAugment / noise / mixup</td><td class="num">0.297</td><td class="num">0.311 (underfit)</td></tr> |
| <tr><td>C</td><td>fixed SpecAugment time-mask scale</td><td class="num">0.323</td><td class="num">0.343</td></tr> |
| <tr><td>D</td><td>+ softened class weights (counts⁻⁰·⁵)</td><td class="num"><strong>0.330</strong></td><td class="num"><strong>0.376</strong></td></tr> |
| </tbody> |
| </table> |
| </div> |
|
|
| <h2>Known weak spots</h2> |
| <ul class="weak"> |
| <li>Engines with many cylinders (8/12) are confused with close siblings far |
| more than 1–2 cylinder engines, which have more distinctive, widely-spaced |
| firing pulses.</li> |
| <li>A couple of classes (<code>v12</code>, <code>2_rotor</code>) remain |
| poorly calibrated even after two rounds of fixes.</li> |
| <li>Cylinder-family accuracy (does it at least get the cylinder count |
| right) is meaningfully higher than exact-class accuracy — most confusion |
| is between siblings in the same family, not wild misfires.</li> |
| </ul> |
|
|
| <h2>Links</h2> |
| <div class="links"> |
| <a href="https://huggingface.co/joakes90/engine_sound_cassifier" target="_blank" rel="noopener">Model repo (checkpoint + card)</a> |
| <a href="https://github.com/joakes90/auto_sound_train" target="_blank" rel="noopener">Training code + notebook (GitHub)</a> |
| <a href="https://github.com/joakes90/auto_sound_train/blob/master/FINDINGS.md" target="_blank" rel="noopener">Full diagnostic write-up</a> |
| </div> |
|
|
| <footer> |
| CC BY-SA 4.0. This Space is static — no inference runs here. |
| </footer> |
| </main> |
| </body> |
| </html> |
|
|