I need to run an inference pipeline which uses a fastai (v2) resnet18 binary classifier model along with a few pure pytorch models. The pytorch models were trained with different pre-processing steps. I am trying to use a single dataloader to read the files just once and prepare different tensors for the various models.
I have the following code for batch inference with the fastai model:
from fastai.vision.all import * learn = load_learner('export.pkl') learn.model.to('cuda:0') # sample_files is a list of file paths test_dl = learn.dls.test_dl(sample_files) preds, _ = learn.get_preds(dl=test_dl) print(preds)
and this outputs:
tensor([[0.8155, 0.1845], [0.9797, 0.0203], [0.9990, 0.0010], [0.7240, 0.2760], [0.1400, 0.8600], [0.9983, 0.0017], [0.4284, 0.5716], [0.8841, 0.1159]])
I am trying to now extract the pytorch model out of this fastai learner and write my own data loader.
The fastai model was built with the following data block:
dblock = DataBlock(blocks=(ImageBlock, CategoryBlock), get_items=get_image_files, get_y=parent_label, splitter=GrandparentSplitter(), item_tfms=Resize(img_size))
The only preprocessing done during training is the resize.
I wrote the following custom data loader to do the same pre-processing done during training i.e. just resize:
import cv2 from torch.utils.data import Dataset, DataLoader class ImageDataset(Dataset): def __init__(self, file_paths, img_size): self.file_paths = file_paths self.img_size = img_size def __getitem__(self, index): fpath = self.file_paths[index] img = cv2.imread(str(fpath)) img = cv2.resize(img, (self.img_size, self.img_size), interpolation=cv2.INTER_AREA) # transpose (height, width, channels) to (channels, height, width) img = img.transpose(2,0,1) return img def __len__(self): return len(self.file_paths)
And then this to do the inference:
import torch.nn.functional as F dataset = ImageDataset(sample_files, img_size=480) loader = DataLoader(dataset, batch_size=32, num_workers=3) with torch.no_grad(): for batch in loader: batch = batch.float().to('cuda:0') preds = learn.model(batch) print(preds) preds = F.softmax(preds, dim=-1) print(preds)
However, this gives the following output:
tensor([[ 128.9455, -1014.5818], [ 159.4461, -971.7758], [ 212.9348, -918.6669], [ 99.4558, -1047.9894], [ 108.8564, -1011.8091], [ 109.2117, -1040.3489], [ 134.9720, -1035.7109], [ 127.0243, -997.6915]], device='cuda:0') tensor([[1., 0.], [1., 0.], [1., 0.], [1., 0.], [1., 0.], [1., 0.], [1., 0.], [1., 0.]], device='cuda:0')
I was hoping to see the same probabilities as above. I am not sure why I am getting a mismatch between the two. Appreciate your feedback. Thank you.