os.chdir('/home/mskang/hyeokjong/cancer/2018/task1/ISIC2018_Task1-2_Training_Input')
train_inputs_list = os.listdir('/home/mskang/hyeokjong/cancer/2018/task1/ISIC2018_Task1-2_Training_Input')
train_inputs_list.remove('ATTRIBUTION.txt')
train_inputs_list.remove('LICENSE.txt')
# len(train_inputs_list)
for i in tqdm(range(len(train_inputs_list))):
os.chdir('/home/mskang/hyeokjong/cancer/2018/task1/ISIC2018_Task1-2_Training_Input')
img = Image.open(train_inputs_list[i])
imgArray = np.array(img)
a,b,_ = imgArray.shape
if a >= b:
z = np.zeros(( a, (a-b)//2 , 3))
con = np.concatenate( [z,imgArray,z], axis=1)
else:
z = np.zeros(((b-a)//2 , b , 3))
con = np.concatenate( [z,imgArray,z], axis=0)
con = con.astype('uint8')
padded_image = Image.fromarray(con)
os.chdir('/home/mskang/hyeokjong/cancer/2018/task1/train_input_pad')
padded_image.save('padded_' + train_inputs_list[i] + '.jpg')
이유는 그냥 대충 Resize하면 되겠지 하고 했던게 잘못이다.
class custom_dataset(Dataset):
def __init__(self, inputs_dir , targets_dir, transform = None):
self.inputs_dir = inputs_dir
self.inputs_list = os.listdir(inputs_dir)
self.targets_dir = targets_dir
self.targets_list = os.listdir(targets_dir)
self.transform = transform
def __len__(self):
return len(self.inputs_list)
def __getitem__(self,idx):
os.chdir(self.inputs_dir)
input_image = Image.open(self.inputs_list[idx])
os.chdir(self.targets_dir)
target_image = Image.open(self.targets_list[idx])
if self.transform:
input_image_tensor = self.transform(input_image)
target_image_tensor = self.transform(target_image)
return ( input_image_tensor ,target_image_tensor)
path_train_inputs = '/home/mskang/hyeokjong/cancer/2018/task1/train_input_pad'
path_train_targets = '/home/mskang/hyeokjong/cancer/2018/task1/train_targets_pad'
train_dataset = custom_dataset(path_train_inputs, path_train_targets )
train_transformation = transforms.Compose([transforms.Resize(4),
transforms.RandomHorizontalFlip(),
transforms.ToTensor()])
train_dataset.transform = train_transformation
batch_size = 2
train_dl = DataLoader(train_dataset, batch_size, shuffle=True,
num_workers=4, pin_memory=True)
for i,j in train_dl:
inputs,targets = i,j
break
inputs.shape
---------------------------
torch.Size([2, 3, 4, 4])
targets.shape
---------------------------
torch.Size([2, 1, 4, 4])
targets
---------------------------
tensor([[[[0.0000, 0.0157, 0.0196, 0.0000],
[0.0314, 0.4510, 0.4784, 0.0157],
[0.0471, 0.4314, 0.4000, 0.0196],
[0.0000, 0.0000, 0.0000, 0.0000]]],
[[[0.0000, 0.0000, 0.0000, 0.0000],
[0.0000, 0.0314, 0.0588, 0.0000],
[0.0000, 0.0471, 0.0824, 0.0000],
[0.0000, 0.0000, 0.0000, 0.0000]]]])
Resize의 방법에도 엄청 많은 종류가 있고 위와같이 Resize를 수행하면 매끄럽게 계산되어 float이 생겨버린다.
위 code를 보면
Custom_dataset
에서 transform을 대응 가능하게 해 놨는데 직접 해보니 dataset에서 transform을 하나 .transform
으로 변환을 찍어주나 속도차이가 없다.(생각해보면 둘이 완전 같은거 같다)
즉, target은 transforms.Resize()
를 사용하면 안된다는 것이다.
그럼 어느정도의 해결책이 보이는데 위의 code처럼 .transform
으로 해버리면 input과 target이 같은 transform을 적용하니 애초에 dataset class
에서 각기 다른 transform을 적용하면 될거 같다는 생각이 들었다.
torch.nn.functional.interpolate(input, size=None, scale_factor=None, mode='nearest', align_corners=None, recompute_scale_factor=None)
에서 mode
조정
물론 첫번째가 계산이 빠르다.
추가적으로 custom collate_fn를 생각해 봐야하는게 극단적으로 다른 size의 image이면 같은 model을 사용하는것이 안좋고 따라서 reize해주는것이 맞다고 본다.
다만 비율 유지의 문제가 있다.
대부분의 code들이 class 부분에서 transform을 진행 하던데 이 이유인거 같다.
해결법은 다음과 같다.
1. pytorch 내장 torch.nn.functional.interpolate
, torch.nn.Upsample
두개가 있다.
2. https://pytorch.org/vision/stable/transforms.html 를 보면
torchvision.transforms.Resize(size, interpolation=<InterpolationMode.BILINEAR: 'bilinear'>, max_size=None, antialias=None)
에서 mode를 지정할 수 있다.
3. custom transformation class를 만들면 된다.
즉, transforms.Compose( [ ] ) 안에 원소로 들어가야 하는것들이 class임을 알 수 있다.
2번이 제일 편하다.
Loss와 마찬가지로 function과 class두개가 있는데 class가 상속받아 custom하기 편하다.
torch가 이런부분은 잘만든거 같다.
https://stackoverflow.com/questions/23853632/which-kind-of-interpolation-best-for-resizing-image
어떠한 interpolation이 좋은가?
ㅅㄱㅁㄴ래그 dksdp sjgdmaus ekfmrp ehlsmsep?\