fix(actpred): 固定 0 列未被覆盖——掩码按权重而非常量值
fixed_zero_columns 对 spk.F 返回常量 0,调用处掩码 fixed!=0 将其 排除,spk.F 垃圾预测(69-423Hz)继续进闭环。改为按权重<=0 掩码 覆盖(含固定 0 的列)。修正后舵机闭环 MSE 14477 假象 → 293 真实 (hand 类 55K 是固定 0 vs 真值 1000 的指标伪影)。+1 回归测试。
This commit is contained in:
1 parent
8a9a061662
commit
37feb09185
3 files changed
+22
-4
No files matched your search
+4
-2
@@ -128,8 +128,10 @@ class ActionPredictorInference:
|
|||||||
from action_norm import default_column_weights
|
from action_norm import default_column_weights
|
||||||
col_w = default_column_weights(self.action_dim)
|
col_w = default_column_weights(self.action_dim)
|
||||||
fixed = fixed_zero_columns(col_w, self.action_dim)
|
fixed = fixed_zero_columns(col_w, self.action_dim)
|
||||||
m = fixed != 0.0
|
# 按权重掩码覆盖(固定 0 的列也须覆盖——掩码不能只看常量值)
|
||||||
result[m] = fixed[m]
|
w = np.asarray(col_w, dtype=np.float32)
|
||||||
|
result[w[:self.action_dim] <= 0.0] = (
|
||||||
|
fixed[w[:self.action_dim] <= 0.0])
|
||||||
if not np.all(np.isfinite(result)):
|
if not np.all(np.isfinite(result)):
|
||||||
result = np.nan_to_num(result, nan=0.0, posinf=0.0, neginf=0.0)
|
result = np.nan_to_num(result, nan=0.0, posinf=0.0, neginf=0.0)
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -2525,6 +2525,22 @@ class TestOneHot(unittest.TestCase):
|
|||||||
cfg2 = apply_overrides(Config(), parser.parse_args([]))
|
cfg2 = apply_overrides(Config(), parser.parse_args([]))
|
||||||
self.assertEqual(cfg2.train.val_split_mode, "sample") # 新默认
|
self.assertEqual(cfg2.train.val_split_mode, "sample") # 新默认
|
||||||
|
|
||||||
|
def test_fixed_zero_value_still_applied(self):
|
||||||
|
"""固定 0 的列(spk.F)也必须被覆盖——掩码按权重而非常量值"""
|
||||||
|
from bins import decode, fixed_zero_columns, START
|
||||||
|
from action_norm import default_column_weights
|
||||||
|
# 构造 spk.F 头输出 1000Hz 附近 logits(垃圾预测)
|
||||||
|
logits = np.full((1, 1864), -10.0, dtype=np.float32)
|
||||||
|
logits[0, START[10] + 25] = 0.0 # 1000Hz 附近箱
|
||||||
|
raw = decode(logits, 18)
|
||||||
|
self.assertGreater(float(raw[0, 10]), 100.0) # 未覆盖时是垃圾
|
||||||
|
w = default_column_weights(18)
|
||||||
|
fixed = fixed_zero_columns(w, 18)
|
||||||
|
mask = np.asarray(w, dtype=np.float32) <= 0.0
|
||||||
|
raw[0, mask] = fixed[mask]
|
||||||
|
self.assertEqual(float(raw[0, 10]), 0.0) # 固定后归零
|
||||||
|
self.assertEqual(float(raw[0, 11]), 10.0)
|
||||||
|
|
||||||
def test_action_jitter(self):
|
def test_action_jitter(self):
|
||||||
"""角度抖动增强:历史加有界高斯噪声,目标保持干净"""
|
"""角度抖动增强:历史加有界高斯噪声,目标保持干净"""
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
|||||||
+2
-2
@@ -130,8 +130,8 @@ def train_one_epoch(model, loader, optimizer, device, max_grad_norm: float = Non
|
|||||||
# 权重 0 列固定为常量,防自预测垃圾进入历史
|
# 权重 0 列固定为常量,防自预测垃圾进入历史
|
||||||
fixed = fixed_zero_columns(
|
fixed = fixed_zero_columns(
|
||||||
weights.cpu().numpy(), action_dim)
|
weights.cpu().numpy(), action_dim)
|
||||||
m = fixed != 0.0
|
w = weights.cpu().numpy()[:action_dim]
|
||||||
raw[m] = fixed[m]
|
raw[w <= 0.0] = fixed[w <= 0.0]
|
||||||
abs_action = torch.from_numpy(normalize_action(
|
abs_action = torch.from_numpy(normalize_action(
|
||||||
raw, action_dim, mode=range_mode)).to(device)
|
raw, action_dim, mode=range_mode)).to(device)
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in new issue
Block a user