v4:Two-stage cascade (WNet)

This commit is contained in:
2026-06-16 17:47:20 +08:00
parent daf3d68247
commit 11fea3d054
13 changed files with 154 additions and 55 deletions

View File

@@ -56,7 +56,8 @@
<div class="vers">
<button class="ver-btn" data-v="v1" data-i18n="btn_v1"></button>
<button class="ver-btn" data-v="v2" data-i18n="btn_v2"></button>
<button class="ver-btn" data-v="v3" data-i18n="btn_v3" disabled></button>
<button class="ver-btn" data-v="v3" data-i18n="btn_v3"></button>
<button class="ver-btn" data-v="v4" data-i18n="btn_v4"></button>
</div>
<div class="notice" id="verNotice"></div>
<div class="metricbar">
@@ -97,18 +98,19 @@ const T = {
title: "Predicting Wireless Coverage with Deep Learning",
subtitle: "A U-Net predicts a base station's signal coverage across a city — running live in your browser. Switch between model versions to see how it improved.",
ver_h: "Model version",
btn_v1: "v1 · baseline", btn_v2: "v2 · distance fix", btn_v3: "v3 · soon",
m_error: "RMSE on unseen cities",
btn_v1: "v1 · baseline", btn_v2: "v2 · distance fix", btn_v3: "v3 · checkerboard fix", btn_v4: "v4 · WNet refine",
m_error: "RMSE on held-out cities",
notice_v1: "Baseline (2-channel input: buildings + transmitter). Known issue: coverage cuts off in a square around the transmitter — the far field stays blank because the network can't propagate the source that far.",
notice_v2: "Adds a distance-to-transmitter input channel (3-channel). Fixed: the square cutoff — coverage now spans the whole map, with far-field rays and distant building shadows. Known issue: faint checkerboard texture in smooth areas, from transposed-convolution upsampling.",
notice_v3: "In progress. Replaces transposed-convolution upsampling with resize-convolution to remove the checkerboard texture. Not yet available.",
notice_v3: "Replaces transposed-convolution upsampling with resize-convolution. Fixed: the checkerboard texture — smooth regions are clean. Known issue: along a long unobstructed corridor the far-field beam fades before reaching the edge — a residual receptive-field limit.",
notice_v4: "Two cascaded U-Nets — a coarse predictor feeds a refiner. Because the refiner's input already contains a global coverage estimate, every pixel gets long-range context (a larger effective receptive field). Fixed: the fading corridor — coverage stays bright to the edge. Lowest error of all four versions.",
demo_h: "Try it yourself",
select_label: "City layout:", click_hint: "Click the map to place a transmitter.",
input_title: "City map — click to place transmitter", output_title: "Predicted coverage",
legend_weak: "weak", legend_strong: "strong",
how_h: "How it works",
how_p: "The model takes the building layout and the transmitter location as image channels and outputs a coverage heatmap, learned from the public RadioMapSeer dataset (5.9 GHz urban propagation). It was given no propagation equations — it learned signal falloff and building shadowing from data. The model runs entirely in your browser via ONNX Runtime Web; nothing is sent to a server.",
footer: "Dataset: RadioMapSeer (Yapar et al., 2022), CC BY 4.0. Independent portfolio project. Error reported on held-out test cities.",
footer: "Dataset: RadioMapSeer (Yapar et al., 2022), CC BY 4.0. Independent portfolio project. Errors are on held-out cities the model never trained on.",
st_loading: "Loading model…", st_ready: "Pick a layout and click to place a transmitter.",
st_running: "Running inference…",
st_done: (ms) => "Predicted in " + ms + " ms. Click again to move the transmitter.",
@@ -116,37 +118,39 @@ const T = {
},
zh: {
title: "基于深度学习的无线信号覆盖预测",
subtitle: "一个 U-Net 在你的浏览器中实时预测基站的信号覆盖。切换不同模型版本看看它是如何一步步改进的。",
subtitle: "一个 U-Net 在你的浏览器中实时预测基站的信号覆盖。切换不同模型版本,看看它是如何一步步改进的。",
ver_h: "模型版本",
btn_v1: "v1 · 基线", btn_v2: "v2 · 距离修复", btn_v3: "v3 · 即将推出",
m_error: "未见城市上的 RMSE",
notice_v1: "基线模型2 通道输入建筑 + 发射机。已知问题覆盖在发射机周围呈方形截断——远场为空白因为网络无法将信号源的影响传播到远处。",
notice_v2: "新增「到发射机的距离」输入通道3 通道。已修复方形截断——覆盖现已贯穿整张地图远场射线与远处建筑阴影都能呈现。已知问题平滑区域出现轻微棋盘格纹理来自转置卷积上采样。",
notice_v3: "开发中。用 resize 卷积替换转置卷积上采样,以消除棋盘格纹理。暂未上线。",
btn_v1: "v1 · 基线", btn_v2: "v2 · 距离修复", btn_v3: "v3 · 棋盘格修复", btn_v4: "v4 · WNet 精修",
m_error: "留出城市上的 RMSE",
notice_v1: "基线模型(2 通道输入:建筑 + 发射机)。已知问题:覆盖在发射机周围呈方形截断——远场为空白,因为网络无法将信号源的影响传播到远处。",
notice_v2: "新增「到发射机的距离」输入通道(3 通道)。已修复:方形截断——覆盖现已贯穿整张地图,远场射线与远处建筑阴影都能呈现。已知问题:平滑区域出现轻微棋盘格纹理,来自转置卷积上采样。",
notice_v3: "用 resize 卷积(双线性上采样 + 卷积)替换转置卷积。已修复:棋盘格纹理消失,平滑区域变得干净。已知问题:在无遮挡的长走廊中,远场光束在到达边缘前逐渐变暗——残留的感受野限制。",
notice_v4: "两个级联 U-Net——粗预测网络的输出送入精修网络。由于精修网络的输入已包含一张全局覆盖估计,每个像素都获得了长程上下文(更大的有效感受野)。已修复:长走廊衰减,覆盖一直明亮延伸到边缘。四个版本中误差最低。",
demo_h: "在线体验",
select_label: "城市布局", click_hint: "点击地图以放置发射机。",
select_label: "城市布局:", click_hint: "点击地图以放置发射机。",
input_title: "城市地图——点击放置发射机", output_title: "预测覆盖",
legend_weak: "弱", legend_strong: "强",
how_h: "实现原理",
how_p: "模型以建筑布局和发射机位置作为图像通道输入输出覆盖热力图训练自公开的 RadioMapSeer 数据集5.9 GHz 城市传播。它没有被告知任何传播公式完全从数据中学会了信号衰减与建筑遮蔽。模型通过 ONNX Runtime Web 完全在你的浏览器中运行,不会向服务器发送任何数据。",
footer: "数据集RadioMapSeerYapar 等2022CC BY 4.0 许可。独立作品集项目。误差基于留出的测试城市。",
how_p: "模型以建筑布局和发射机位置作为图像通道输入,输出覆盖热力图,训练自公开的 RadioMapSeer 数据集(5.9 GHz 城市传播)。它没有被告知任何传播公式,完全从数据中学会了信号衰减与建筑遮蔽。模型通过 ONNX Runtime Web 完全在你的浏览器中运行,不向服务器发送任何数据。",
footer: "数据集:RadioMapSeer(Yapar 等,2022),CC BY 4.0 许可。独立作品集项目。误差基于模型从未训练过的留出城市。",
st_loading: "正在加载模型…", st_ready: "选择布局并点击放置发射机。",
st_running: "正在推理…",
st_done: (ms) => "推理完成用时 " + ms + " 毫秒。再次点击可移动发射机。",
st_error: (m) => "错误" + m
st_done: (ms) => "推理完成,用时 " + ms + " 毫秒。再次点击可移动发射机。",
st_error: (m) => "错误:" + m
}
};
const VERSIONS = {
v1: { model: "radio_unet_v1.onnx", channels: 2, available: true },
v2: { model: "radio_unet_v2.onnx", channels: 3, available: true },
v3: { model: "radio_unet_v3.onnx", channels: 3, available: false },
v3: { model: "radio_unet_v3.onnx", channels: 3, available: true },
v4: { model: "radio_unet_v4.onnx", channels: 3, available: true },
};
const METRICS = { v1: "0.052", v2: "0.034", v3: "" };
const METRICS = { v1: "0.052", v2: "0.034", v3: "0.030", v4: "0.021" };
const SIZE = 256;
let currentLang = (navigator.language || "en").toLowerCase().startsWith("zh") ? "zh" : "en";
let activeVersion = "v2";
let activeVersion = "v4";
const sessions = {};
let buildings = null, txRC = null;
@@ -221,7 +225,7 @@ function buildInput(){
input.set(buildings, 0); // channel 0: buildings
const [r,c] = txRC;
input[SIZE*SIZE + r*SIZE + c] = 1.0; // channel 1: transmitter
if (ch === 3){ // channel 2: distance to Tx (v2/v3)
if (ch === 3){ // channel 2: distance to Tx (v2/v3/v4)
const off = 2*SIZE*SIZE, norm = Math.SQRT2 * SIZE;
for(let yy=0; yy<SIZE; yy++)
for(let xx=0; xx<SIZE; xx++)