为何fastai中手动构建的字典与ColumnarModelData实例行为不同并报错?
问题原因解析:ColumnarModelData vs 手动字典在fastai中的差异
你碰到的这个问题其实是Python里类实例和普通字典的本质区别导致的,咱们一步步拆解来看:
1. 两种创建方式的核心差异
当你用ColumnarModelData()生成md时,得到的是一个**ColumnarModelData类的实例对象**——它的属性(比如path、trn_dl这些)是通过**点语法(.)来访问的;而你手动写的是个普通Python字典,字典的键值对只能用方括号语法([])**来获取。
用ColumnarModelData创建的实例
md = ColumnarModelData(PATH, ColumnarDataset.from_data_frame(trn_df, cat_flds=cat_vars, y=trn_y), ColumnarDataset.from_data_frame(val_df, cat_flds=cat_vars, y=val_y), bs=128, test_ds=test_ds) vars(md)
输出结果:
{'path': 'data/rossmann/', 'test_dl': <fastai.dataloader.DataLoader at 0x112c93d68>, 'trn_dl': <fastai.dataloader.DataLoader at 0x112c93e80>, 'val_dl': <fastai.dataloader.DataLoader at 0x112c93a20>}
这里vars(md)只是把实例内部的属性字典打印出来,但md本身是个正经的类实例,支持md.path、md.trn_dl这种点语法访问。
手动构建的普通字典
md = {'path':PATH, 'test_dl':DataLoader(test_ds, batch_size=128, shuffle=False, num_workers=1), 'trn_dl':DataLoader(trn_df, batch_size=128, shuffle=False, num_workers=1), 'val_dl':DataLoader(val_df, batch_size=128*2, shuffle=False, num_workers=1)} md
输出结果:
{'path': 'data/rossmann/', 'test_dl': <fastai.dataloader.DataLoader at 0x1c20e9cc88>, 'trn_dl': <fastai.dataloader.DataLoader at 0x1c20d5f8d0>, 'val_dl': <fastai.dataloader.DataLoader at 0x1c20d5f320>}
这个md就是个普通字典,只能用md['path']来拿值,完全不支持点语法访问属性。
2. 报错的直接原因
StructuredLearner的内部代码里,是用点语法来访问传入的md对象的属性的(比如md.path)。当你把普通字典传进去时,字典根本没有这种访问方式,自然就会抛出错误:
AttributeError: 'dict' object has no attribute 'path'
说白了就是:
ColumnarModelData实例:md.path→ 合法,能正确拿到值- 普通字典:
md.path→ 非法,字典没有path这个属性,得用md['path']
3. 手动构建替代方案
如果不想用ColumnarModelData,又要让md能被StructuredLearner正常使用,可以用types.SimpleNamespace快速创建一个支持点语法的对象:
from types import SimpleNamespace md = SimpleNamespace( path=PATH, test_dl=DataLoader(test_ds, batch_size=128, shuffle=False, num_workers=1), trn_dl=DataLoader(trn_df, batch_size=128, shuffle=False, num_workers=1), val_dl=DataLoader(val_df, batch_size=128*2, shuffle=False, num_workers=1) )
这样md.path就能正常访问,传入StructuredLearner也不会报错了。
内容的提问来源于stack exchange,提问作者conv3d
相关产品推荐
相关产品推荐

