I am trying to build a Siamese Network for Humpback Whale Identification simulating Alex Fitts’s work.
I have rewritten his code for his fastai version is a little bit old ( v1.0.39 ) and not compatible with the latest version so far ( v1.0.51 ).
But when I have just defined my custom dataset, trying to load the data, an error occured:
class SiamImage(ItemBase):
def __init__(self, img1, img2):
self.img1, self.img2 = img1, img2
self.obj, self.data = (img1, img2), [img1.data, img2.data]
def apply_tfms(self, tfms, *args, **kwargs):
self.img1 = self.img1.apply_tfms(tfms, *args, **kwargs)
self.img2 = self.img2.apply_tfms(tfms, *args, **kwargs)
self.data = [self.img1.data, self.img2.data]
return self
def __repr__(self):
return f'{self.__class__.__name__} {self.img1.shape, self.img2.shape}'
def to_one(self):
return Image(torch.cat(self.data, dim=2))
class SiamImageList(ImageList):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def __len__(self):
return len(self.items)
def get(self, i):
# 0 for match and 1 for dismatch
target = (i >= len(self.items)//2)
img1 = super().get(i)
whaleImgs = self.inner_df.Image.values
whaleIds = self.inner_df.Id.values
img1Id = whaleIds[i]
img2Name = ''
if target == 0:
img2Name = np.random.choice(whaleImgs[whaleIds == img1Id])
else:
img2Name = np.random.choice(whaleImgs[whaleIds != img1Id])
img2 = super().open(self.path/img2Name)
return SiamImage(img1, img2)
def reconstruct(self, t):
return SiamImage(t[0], t[1])
def show_xys(self, xs, ys, figsize:Tuple[int,int]=(9,5), **kwargs):
rows = int(math.sqrt(len(xs)))
fig, axs = plt.subplots(rows,rows,figsize=figsize)
for i, ax in enumerate(axs.flatten() if rows > 1 else [axs]):
xs[i].to_one().show(ax=ax, y=ys[i], **kwargs)
plt.tight_layout()
data = (SiamImageList.from_df(df=train, path='../input/train', cols='Image')
.split_by_rand_pct(0.2)
.label_from_df(cols='target')
.transform(get_transforms(), size=224)
.databunch(bs=8)
.normalize(imagenet_stats))
data.show_batch()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-14-53e0711f0b1c> in <module>()
41 .normalize(imagenet_stats))
42
---> 43 data.show_batch()
/opt/conda/lib/python3.6/site-packages/fastai/basic_data.py in show_batch(self, rows, ds_type, reverse, **kwargs)
183 def show_batch(self, rows:int=5, ds_type:DatasetType=DatasetType.Train, reverse:bool=False, **kwargs)->None:
184 "Show a batch of data in `ds_type` on a few `rows`."
--> 185 x,y = self.one_batch(ds_type, True, True)
186 if reverse: x,y = x.flip(0),y.flip(0)
187 n_items = rows **2 if self.train_ds.x._square_show else rows
/opt/conda/lib/python3.6/site-packages/fastai/basic_data.py in one_batch(self, ds_type, detach, denorm, cpu)
166 w = self.num_workers
167 self.num_workers = 0
--> 168 try: x,y = next(iter(dl))
169 finally: self.num_workers = w
170 if detach: x,y = to_detach(x,cpu=cpu),to_detach(y,cpu=cpu)
/opt/conda/lib/python3.6/site-packages/fastai/basic_data.py in __iter__(self)
73 def __iter__(self):
74 "Process and returns items from `DataLoader`."
---> 75 for b in self.dl: yield self.proc_batch(b)
76
77 @classmethod
/opt/conda/lib/python3.6/site-packages/fastai/basic_data.py in proc_batch(self, b)
68 "Process batch `b` of `TensorImage`."
69 b = to_device(b, self.device)
---> 70 for f in listify(self.tfms): b = f(b)
71 return b
72
/opt/conda/lib/python3.6/site-packages/fastai/vision/data.py in _normalize_batch(b, mean, std, do_x, do_y)
64 "`b` = `x`,`y` - normalize `x` array of imgs and `do_y` optionally `y`."
65 x,y = b
---> 66 mean,std = mean.to(x.device),std.to(x.device)
67 if do_x: x = normalize(x,mean,std)
68 if do_y and len(y.shape) == 4: y = normalize(y,mean,std)
AttributeError: 'list' object has no attribute 'device'
What’s wrong with my code? My full code can be found on gist.