I am trying to understand the code in CycleGAN notebook and I have a few questions related to the customed ItemBase
, ItemList
defined in the notebook (see Code Snippet below for reference):

In
TargetTupleList.reconstrcut
, why the input tensor is transformed (i.e.t/2 + 0.5
) before feeding intoImageTuple
, while inImageTuple.__init__
,ImageTuple.data
is transformed back to originalt
(i.e.[1+2*img1.data,1+2*img2.data]
)? It seems strange to me to transform a tensor on one hand but undo the transform at the end. 
In
ImageTuple.apply_tfms
,tfms
is applied onself.img1
andself.img2
, which are instances offastai.vision.Image
. After that, whyself.data
is not updated accordingly? (in the way that you do inImageTuple.__init__,
i.e.self.data = 1+2*img.data
) 
Following up on Q2, does
ImageTuple.apply_tfms
actually apply ontorch.Tensor
orPIL.Image
? It seems to me thetfms
is applied ontorch.Tensor
, in contrary toPyTorch
practice where transforms is applied onPIL.Image
.
Code Snippet
class TargetTupleList(ItemList):
def reconstruct(self, t:Tensor):
if len(t.size()) == 0: return t
# Image input is tensor (C, H, W)  [01]
return ImageTuple(Image(t[0]/2+0.5),Image(t[1]/2+0.5))
class ImageTuple(ItemBase):
def __init__(self, img1, img2):
# img1, img2 = fastai.vision.image.Imagae
self.img1,self.img2 = img1,img2
# img.data is [0  1] tensor, converted to [0.5  0.5]
self.obj,self.data = (img1,img2),[1+2*img1.data,1+2*img2.data]
def apply_tfms(self, tfms, **kwargs):
self.img1 = self.img1.apply_tfms(tfms, **kwargs)
self.img2 = self.img2.apply_tfms(tfms, **kwargs)
return self