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.