linhduongtuan / Tuberculosis_ChestXray_Classifier

Classification for chest X ray images of tuberculosis using PyTorch, Timm, and modified EfficientNet family. This repo is implemented to our paper Detection of tuberculosis from chest X-ray images: Boosting the performance with vision transformer and transfer learning" published on ESWA
Apache License 2.0
29 stars 18 forks source link

Weights #2

Open ieee8023 opened 1 year ago

ieee8023 commented 1 year ago

Hello, can you provide the weights of a trained model? I'd like to add this as a pre-trained model in the https://github.com/mlmed/torchxrayvision library.

linhduongtuan commented 1 year ago

Dear Dr. Cohen, Here are my trained weights for my custom models. https://github.com/linhduongtuan/Tuberculosis_ChestXray_Classifier/releases Linh

On Jan 4, 2023, at 2:10, Joseph Paul Cohen PhD @.***> wrote:

Hello, can you provide the weights of a trained model? I'd like to add this as a pre-trained model in the https://github.com/mlmed/torchxrayvision library.

— Reply to this email directly, view it on GitHub https://github.com/linhduongtuan/Tuberculosis_ChestXray_Classifier/issues/2, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFKZ27F3WMFDX342H5RAZRDWQR2SNANCNFSM6AAAAAATP773NM. You are receiving this because you are subscribed to this thread.

ieee8023 commented 1 year ago

Linh, Can you confirm that I am loading this model correctly? The output has 1000 classes but I think it should have 2 or 3. I followed this code: https://github.com/linhduongtuan/Tuberculosis_ChestXray_Classifier/blob/master/Notebooks/Tuberculosis_CXR_EfficientNet_B1.ipynb

I had to change the fc4 shape to 128, 3 in order to load the weights EfficientNet_B1_240.pth so that would imply 3 output classes. In the notebook is was 128, 2. But also it seems that the model.fc is not being used at all. In the training loop it uses the default forward function which I believe just uses the .classifier linear layer that was not changed. Can you confirm how things should be loaded here? If possible create a complete script which takes in an input image and outputs the probability of TB? This way I can confirm my implementation matches.

import torchvision
import torchxrayvision as xrv
import skimage
import timm
import torch
import torch.nn as nn
from collections import OrderedDict
from timm.models.layers.activations import Swish

model = timm.create_model('efficientnet_b1', pretrained=True, drop_rate=0.2)

fc = nn.Sequential(OrderedDict([
    ('fc1', nn.Linear(2048, 1000, bias=True)),
    ('BN1', nn.BatchNorm2d(1000, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)),
    ('dropout1', nn.Dropout(0.7)),
    ('fc2', nn.Linear(1000, 512)),
    ('BN2', nn.BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)),
    ('swish1', Swish()),
    ('dropout2', nn.Dropout(0.5)),
    ('fc3', nn.Linear(512, 128)),
    ('BN3', nn.BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)),
    ('swish2', Swish()),
    ('fc4', nn.Linear(128, 3)),
    ('output', nn.Softmax(dim=1))
]))
# connect base model (EfficientNet_B0) with modified classifier layer
model.fc= fc

weights = torch.load("../torchxrayvision/baseline_models/linhduongtuan/EfficientNet_B1_240.pth", map_location=torch.device('cpu'))

model.load_state_dict(weights['model_state_dict'])

### read image
img = skimage.io.imread('../tests/00027426_000.png')
img = xrv.datasets.normalize(img, 255)[None, :, :]

transform = torchvision.transforms.Compose([xrv.datasets.XRayCenterCrop(),
                                            xrv.datasets.XRayResizer(224)])

img = transform(img)
img = torch.from_numpy(img).unsqueeze(0)

# Add fake color channels
img = img.repeat(1,3,1,1)

model(img).shape.  # outputs torch.Size([1, 1000])
linhduongtuan commented 1 year ago

Dear Dr. Cohen, These trained weights have been performed since 2020-2021. So I don’t remember exactly how many number of classes with every dataset I used for the weights. The worst case I made a mistake is set num_classes=1000. However, most probably I set 'num_classes=3’ for either (Normal vs TB vs Other pneumonia) or (Normal vs Covid-19 vs other Pneumonia), or num_classes=4 for Normal vs Covid-19 vs TB vs other pneumonia, or num_classes=5 for Normal vs Covid-19 vs TB vs Other Pneumonia vs Not normal nor Opacity.

In general, 3-catagory, 4-category and 5-caterogy problems are still worked well using my modified classifier. For instance, the overall accuracy for 5-category classification achieves ~ 87%. If using only a pure backbone, models are not able to classify every lesion type such as Covid-19 vs TB vs other pneumonia.

I would suggest that you can train my proposed models again using your own datasets to test further performance.

Sincerely Linh

On Jan 7, 2023, at 7:58, Joseph Paul Cohen PhD @.***> wrote:

Linh, Can you confirm that I am loading this model correctly? The output has 1000 classes but I think it should have 2 or 3. I followed this code: https://github.com/linhduongtuan/Tuberculosis_ChestXray_Classifier/blob/master/Notebooks/Tuberculosis_CXR_EfficientNet_B1.ipynb

I had to change the fc4 shape to 128, 3 in order to load the weights EfficientNet_B1_240.pth so that would imply 3 output classes. In the notebook is was 128, 2. But also it seems that the model.fc is not being used at all. In the training loop it uses the default forward function which I believe just uses the .classifier linear layer that was not changed. Can you confirm how things should be loaded here? If possible create a complete script which takes in an input image and outputs the probability of TB? This way I can confirm my implementation matches.

import torchvision import torchxrayvision as xrv import skimage import timm import torch import torch.nn as nn from collections import OrderedDict from timm.models.layers.activations import Swish

model = timm.create_model('efficientnet_b1', pretrained=True, drop_rate=0.2)

fc = nn.Sequential(OrderedDict([ ('fc1', nn.Linear(2048, 1000, bias=True)), ('BN1', nn.BatchNorm2d(1000, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)), ('dropout1', nn.Dropout(0.7)), ('fc2', nn.Linear(1000, 512)), ('BN2', nn.BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)), ('swish1', Swish()), ('dropout2', nn.Dropout(0.5)), ('fc3', nn.Linear(512, 128)), ('BN3', nn.BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)), ('swish2', Swish()), ('fc4', nn.Linear(128, 3)), ('output', nn.Softmax(dim=1)) ]))

connect base model (EfficientNet_B0) with modified classifier layer

model.fc= fc

weights = torch.load("../torchxrayvision/baseline_models/linhduongtuan/EfficientNet_B1_240.pth", map_location=torch.device('cpu'))

model.load_state_dict(w['model_state_dict'])

read image

img = skimage.io.imread('../tests/00027426_000.png') img = xrv.datasets.normalize(img, 255)[None, :, :]

transform = torchvision.transforms.Compose([xrv.datasets.XRayCenterCrop(), xrv.datasets.XRayResizer(224)])

img = transform(img) img = torch.from_numpy(img).unsqueeze(0)

Add fake color channels

img = img.repeat(1,3,1,1)

model(img).shape. # outputs torch.Size([1, 1000]) — Reply to this email directly, view it on GitHub https://github.com/linhduongtuan/Tuberculosis_ChestXray_Classifier/issues/2#issuecomment-1374321204, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFKZ27GFISF6DF2YL3LKUZDWRC5RVANCNFSM6AAAAAATP773NM. You are receiving this because you commented.

ieee8023 commented 1 year ago

Is there a way you can create a working example running with the pre-trained weights? Specifically naming the output predictions so I don't mess them up. My goal is to add your model so that other researchers can compare against the exact models you used.

linhduongtuan commented 1 year ago

Unfortunately, I did have a correct strategy to name my trained weights. Now it seems to be no way to know what they are, except for I have to manually inference every weight with regarding to dataset. Sorry for the inconvenience. Linh