0

This is from the fastai library. So this function call:

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)

Gives this result:

{'path': 'data/rossmann/',
 'test_dl': <fastai.dataloader.DataLoader at 0x112c93d68>,
 'trn_dl': <fastai.dataloader.DataLoader at 0x112c93e80>,
 'val_dl': <fastai.dataloader.DataLoader at 0x112c93a20>}

But I can build the same result by doing:

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

Which gives:

{'path': 'data/rossmann/',
 'test_dl': <fastai.dataloader.DataLoader at 0x1c20e9cc88>,
 'trn_dl': <fastai.dataloader.DataLoader at 0x1c20d5f8d0>,
 'val_dl': <fastai.dataloader.DataLoader at 0x1c20d5f320>}

However they behave very differently when trying to use them in other functions. As in:

m = StructuredLearner(md, StructuredModel(to_gpu(model)), opt_fn=optim.Adam)

This runs fine when I use the initial method of md = ColumnarModelData() but does not work when I build it on my own, gives this error:

AttributeError: 'dict' object has no attribute 'path'

What exactly is going wrong here?

conv3d
  • 2,668
  • 6
  • 25
  • 45
  • can you add what library you are using? – Zev Jun 01 '18 at 18:10
  • @Zev added library to question: fastai – conv3d Jun 01 '18 at 18:12
  • You are aware that you only see "part" of the object that you get returned - depending on when/how you print you get either its `__str__()` or its `__repr__()` printed. It could entail Lots of other things that are not printed but used by the other funcions you mention that do not work with your "reconstructed" result-dict. – Patrick Artner Jun 01 '18 at 18:27
  • `md` and `vars(md)` are not the same thing. – Alex Hall Jun 01 '18 at 18:30
  • @AlexHall so how do I convert `md` to make it have the same `vars(md)`? – conv3d Jun 01 '18 at 18:38
  • What is wrong with the `ColumnarModelData` constructor? – Alex Hall Jun 01 '18 at 18:40
  • @AlexHall I want to know exactly what goes into the construction of all of the classes so I am breaking it all out for a better understanding of the process. – conv3d Jun 01 '18 at 18:44
  • @PatrickArtner ok, so how can I tell which 'parts' each function call is requesting when it gets fed in? i.e. how can I tell what "part" the `StructuredLearner(md, StructuredModel(to_gpu(model)), opt_fn=optim.Adam)` call wants from the `md` object? – conv3d Jun 01 '18 at 18:45
  • 1
    It wants the `path` attribute, which `md` has. `vars(md)` produces a dictionary where those attributes become keys/values which are separate and different. `vars(md)['path']` exists, not `vars(md).path`. – Alex Hall Jun 01 '18 at 18:49

1 Answers1

1

You are converting a class to a dictionary using var(md) but md is an instance of a class rather than a dictionary. Classes can access their attributes using dot notation (for example md.path) but dictionaries cannot.

If you look at the Learner class (which StructuredLearner inherits from) you'll see these two lines:

self.data_,self.models,self.metrics = data,models,metrics
self.models_path = models_name if os.path.isabs(models_name) else os.path.join(self.data.path, models_name)

The key parts of that are:

self.data = data

and

self.data.path

So you can see it is trying to access the data (md) using dot notation.

If you really want to convert your dict to a class you can follow this: https://codeyarns.com/2017/02/27/how-to-convert-python-dict-to-class-object-with-fields/

or

Convert nested Python dict to object?

I'd recommend reading the docs, reading the library's code and creating your own small projects rather than trying to break something that is designed to work together into parts however it is up to you to figure out how you learn best.

Zev
  • 3,423
  • 1
  • 20
  • 41
  • This is very helpful. It also helps me understand OOP better because until now I have just defined functions and used them directly, no objects. – conv3d Jun 01 '18 at 19:27