Code reading


(sergii makarevych) #1

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?


Fast.ai library usage in the projects
(Anand Saha) #2

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.


(Jeremy Howard) #3

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.


(Hiromi Suenaga) #4

A kind of silly question but what does “tfms” stand for?


(satish) #5

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


(Sanyam Bhutani) #6

@sermakarevich
I can help with the Markdown if you want


(Jeremy Howard) #7

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


(Hiromi Suenaga) #8

I see it now! Thank you :slight_smile:


(sergii makarevych) #9

@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.


(James Requa) #10

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


(Hannan Ali) #11

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:


(Jeremy Howard) #12

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


(Anand Saha) #13

This was instant gratification! Very convenient tool indeed.


(Abi Komma) #14

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.


(sergii makarevych) #15

Here they are

data.test_dl.dataset.fnames


(Abi Komma) #16

Thank you!


(Jeremy Howard) #17

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


(Vikrant Behal) #18

Thanks! Keep sharing.


(Vikrant Behal) #19

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


(Vikrant Behal) #20

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?