# LAB 19 · 新域:捷径反转与少标签适配 按问题继续 源域捷径、目标域反转、少标签适配与同预算scratch 对应课堂(1 页) 可先阅读已有结果,再决定是否运行。重算时请核对各节记录的数据、参数、环境与日期。 **学习路径:** [表示怎样迁移到新任务](/course/study/readout-transfer.html) 这是[CLS 06](https://deepnote.com/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/c0645a4db6e04188ab5b119e87c53bed)的新域支路:**到新环境变差,与迁移不如从头训练,是同一句话吗?** 先预测两维线索中哪一维会失效,再读源域、目标域直接使用、32标签适配与同预算scratch四项评价。分别算“适配相对直接使用”和“迁移相对scratch”的差值;它们回答不同问题。 你的产出是用这两个差值写两句范围明确的判断。输入是解析线索,模型确实训练,但不是照片实验。[P24](/course/pages/l3-r2-p24.html)及[新域与负迁移](/course/blocks/environment-shift-versus-negative-transfer.html)保留上下文;需要真实图像的参数适配时接[LAB 02](https://deepnote.com/project/38755e4e-23f6-4f5f-8c68-8a2e4114b1c1/notebook/4bd450d54870432db91c80a4df563b8e)。 [此段独立阅读](/course/notebook-blocks/d066bd38245d4d849bd1b05e2cf09b01.html)展开完整实现代码 ``` # Writable ephemeral workspace for detached readonly cloud runs. import os, tempfile os.chdir(tempfile.mkdtemp(prefix='lec03_lab22_')) import numpy as np def data(seed,n,environment): r=np.random.default_rng(seed); y=r.integers(0,2,n); sign=2*y-1 x=np.c_[sign+r.normal(0,1.,n),environment*sign+r.normal(0,.15,n),np.ones(n)] return x,y def train(x,y,w,steps,lr=.1,l2=.01): w=w.copy() for _ in range(steps): p=1/(1+np.exp(-np.clip(x@w,-30,30))); w-=lr*(x.T@(p-y)/len(y)+l2*np.r_[w[:2],0]) return w def acc(w,d): x,y=d; return float(((x@w>=0)==y).mean()) source=data(220,512,1); source_test=data(221,512,1); adapt=data(222,32,-1); target_test=data(223,512,-1) w=train(*source,np.zeros(3),500); adapted=train(*adapt,w,150); scratch=train(*adapt,np.zeros(3),150) print('source-trained weights stable/spurious/bias',w.round(3).tolist()) result={'source_holdout':acc(w,source_test),'target_zero_shot':acc(w,target_test),'target_adapt32':acc(adapted,target_test),'target_scratch32':acc(scratch,target_test)} print(result); print('adaptation gain over zero-shot',round(result['target_adapt32']-result['target_zero_shot'],4),'transfer advantage vs scratch',round(result['target_adapt32']-result['target_scratch32'],4)) print('test seeds 221/223 never used by optimizer; adaptation seed222 only') ``` [此段独立阅读](/course/notebook-blocks/57aeca83ffea4a7c9f6d46529f58fa18.html) ## 已完成的基准运行 以下是本轮本地独立 Python 进程的实际标准输出,云端执行另行记录。 ``` source-trained weights stable/spurious/bias [1.009, 2.7, 0.0] {'source_holdout': 1.0, 'target_zero_shot': 0.076171875, 'target_adapt32': 0.9921875, 'target_scratch32': 1.0} adaptation gain over zero-shot 0.916 transfer advantage vs scratch -0.0078 test seeds 221/223 never used by optimizer; adaptation seed222 only ``` 目标域零样本下降来自我们显式翻转的相关线索;这不是对现实部署原因的自动诊断。适配收益与迁移相对从零的收益不同,结果表分别报告两者。只把adapt样本数32改为8,重新生成相同环境的独立训练样本,观察方差;多种子评价时保留预先固定的测试种子,不挑最好一次。若背景在所有训练环境都相同方向相关,仅凭随机划分无法知道哪维稳定;增加环境多样性与领域知识是不同干预。[WILDS](https://wilds.stanford.edu/)提供真实分布变化基准;本例是自制可控反例。 [此段独立阅读](/course/notebook-blocks/781073c3fc214fd6b23ae0a54a479e1d.html) ## 旧版热身(历史参考) 旧版热身仅保留为历史参考,不参与当前基准运行;当前解释与计算以上方完整实验为准。 #### 展开查看旧版代码(仅展示,不执行) ``` train=[('grass','cow')]*8+[('water','duck')]*8; test=[('water','cow')]*4+[('grass','duck')]*4 def bg_rule(bg):return 'cow' if bg=='grass' else 'duck' print('train acc',sum(bg_rule(x)==y for x,y in train)/len(train)); print('environment-shift acc',sum(bg_rule(x)==y for x,y in test)/len(test)) ``` [此段独立阅读](/course/notebook-blocks/b8f620816c50450aa37772c7ee9ebfb1.html)