Code reading

Hey All.
I found it useful for myself to write some notes when I read the code. Especially this is useful when the code structure is not that simple and you cant keep it in your had after one-two readings. When doing notes I preserve the structure of code, leave TBD when I think I can read this part of code later, put some examples, etc. This helps me to easily recall the structure of code and processing flow so I thought maybe this might be helpful for someone else.

First function in Lecture 1 looks simple:
data = ImageClassifierData.from_paths(PATH, tfms=tfms_from_model(resnet34, sz))

But this what happens behind the scene:

  • ImageClassifierData - nested class with ImageData which is nested class with ModelData

    • parameters:
      • PATH - just a path to folder with images
      • tfms_from_model (transforms) contains a model and a batch size
        • selects mean and std based on model type (inception_4, inceptionresnet_2) vs (others) to path into Normalize / Denormalize
        • returns train and validation image_gen (image generators - TBD)
    • method from_paths:
      • calls folder_source function for train and valid (tuples of shape[0] == 3 )
        • calls read_dirs function
          • iglob - returns relative paths that match a pattern
          • returns list of
            • relative paths from PATH to all files in dirs (ā€˜train/valid/cats/cat.980.jpgā€™)
            • classes of files (upper level folder`s name)
            • list of all classes [dogs, cats]
        • creates dictionary with classes mapping into numerical values
        • converts files classes into numerical values
        • returns
          • relative paths (ā€˜train/valid/cats/cat.980.jpgā€™)
          • classes of files in numerical format
          • list of all classes [dogs, cats]
      • calls read_dir for test folder
      • calls get_ds (get dataset) method
        • process train/valid/test sets with train and valid image generators (we get from tfms_from_model, 2 processing for each set). train image_gen contains additional params: tfms=aug_tfms, max_zoom=max_zoom which valid image_gen does not have
        • processing function is class FilesIndexArrayDataset - returns only number of classes with get_c method
        • takes as input FilesArrayDataset - init takes fnames, y, transform, path
          • returns class name with get_y
          • returns y.shape[1] with get_c method - is it correct?
        • takes as input FilesDataset class
          • can return len of y, batch size
          • get_x method
            • opens i-th filename (created by folder_source)
            • converts into np.float32 and /255.
            • resize_imgs method calls resize_imgs function (TBD)
            • denorm method calls transform.denorm(np.rollaxis(arr,1,4)) (TBD)
        • takes as input BaseDataset (TBD)
        • takes as input Dataset class (TBD)
        • returns datasets (list with):
          • train processed with train image_gen
          • train processed with valid image_gen
          • valid processed with train image_gen
          • valid processed with valid image_gen
          • test processed with train image_gen
          • test processed with valid image_gen
      • returns
        • path,
        • datasets,
        • batch size,
        • num_workers (default value 4 defined in method from_paths)
        • number of classes

Next line ConvLearner.pretrained(resnet34, data, precompute=True)

  • ConvLearner nested class with Learner
    • method pretrained creates a model with class ConvnetBuilder
      • cut_model - by default select 8 layers for resnet*
      • adds two layers AdaptiveConcatPool2d(), Flatten()
      • creates top_model = nn.Sequential(*layers)
      • calls get_fc_layers method to create fc layers
        • iterates through xtra_fc (extra fully connected layers), default value is [512]
        • calls create_fc_layer
          • adds BatchNorm1d with ni = num_features = layers[-1] *2
          • adds nn.Dropout(p=p) where p default is [0.25 ,0.5]
          • adds Linear(in_features=ni, out_features=nf) where nf - number of output nodes defined by xtra_fc, default 512
          • ads nn.ReLU
          • adds Sigmoid or Softmax final function based on self.is_multi (param in init)
          • if task is regression (self.is_reg) removes final Sigmoid/Softmax and ads one more cycle through create_fc_layer
          • calls apply_init on fc_model - most probably initialise some weights for fc_layers
          • finally does self.model=nn.Sequential(*(layers+fc_layers)).cuda()

Also it is interesting to hear how professional Python programmers read the code. Do you do any notes, or you can just read it once and draw a scheme of the code?

36 Likes

Hi @sermakarevich, to browse source code of libraries and projects, I have setup OpenGrok on my machine. From the site:

OpenGrok is a fast and usable source code search and cross reference engine. It helps you search, cross-reference and navigate your source tree. It can understand various program file formats and version control histories like Mercurial, Git, SCCS, RCS, CVS, Subversion, Teamware, ClearCase, Perforce, Monotone and Bazaar. In other words it lets you grok (profoundly understand) source code and is developed in the open, hence the name OpenGrok. It is written in Java.

Once installed, and once your project is indexed, you can browse the source code with ease via browser.

I found this open portal to browse libreoffice source code using OpenGrok:
https://opengrok.libreoffice.org/xref/libcdr/src/lib/CDRDocument.cpp
(click on a function call and it take you to itā€™s definition)

Git it a try.

ā€“

5 Likes

You can also browse code on Github using Sourcegraph: https://chrome.google.com/webstore/detail/sourcegraph-for-github/dgjhfomjieaadpoljlnidmbgkdffpack?hl=en

@sermakarevich those notes look quite helpful - any chance you could turn them into markdown here on the forum? Itā€™s a little hard to read the screenshot, and not searchable.

15 Likes

A kind of silly question but what does ā€œtfmsā€ stand for?

2 Likes

I was typing the same question. Also Why the Sz is 224? I believe that is the width and height of the image

@sermakarevich
I can help with the Markdown if you want

1 Like

Not silly at all - it stands for ā€œtransformsā€. i.e. anything that transforms the input images in some way. See for example https://medium.com/towards-data-science/image-augmentation-for-deep-learning-histogram-equalization-a71387f609b2

3 Likes

I see it now! Thank you :slight_smile:

@jeremy done!

@satish860 thats resnet model`s picture width/height parameter. For inception I assume should be 299.

Thanks for your kind offer @init_27. I did not know forum can read Markdown format.

1 Like

Just saw this other option on product hunt yesterday as well. Insight.io - letā€™s you navigate Github like its your IDE.

3 Likes

I am using Visual Studio Code and it also has abilities similar to the OpenGrok, Visual Studio Code is particularly popular in javascript land and makes navigating through source code much easier. Havenā€™t tried it out, but this grokking feature should work for Python too :slight_smile:

Yup, most modern editors will handle this nicely. The web-based ones can be easier for new users, I think.

1 Like

This was instant gratification! Very convenient tool indeed.

ā€“

2 Likes

Is there a way to retrieve the actual file names of the images we make predictions on in the validation dataā€¦

For example, I want to get the list of all the filenames where the model made a mistake. Not able to figure out the fastai lib on how to get that info.

Explore data.val_ds function. Donā€™t think it is storing the file nameā€¦

The reason this is important to me is that I am trying lesson1 on my own dataset and I have a bunch of other meta-data associated with the file-names.

Here they are

data.test_dl.dataset.fnames

2 Likes

Thank you!

BTW a slight shortcut is to use trn_ds instead of trn_dl.dataset (they both refer to the same thing).

2 Likes

Thanks! Keep sharing.

Thanks for askingā€¦ This gives me the confidence to ask more questions which I had categorized as obvious (but alien to me) or silly.

Were you able to try sourcegraph? I added the extension and watched a youtube for usage. Restarted Chrome but git remains same? Am I missing any configuration?