Kaggle competition: Generative Dog Images
def truncated_normal(size, threshold=2.0, dtype=torch.float32, device='cpu'):
x = scipy.stats.truncnorm.rvs(-threshold, threshold, size=size)
 x = torch.from_numpy(x ).to(device, dtype)
 return x<define_variables>
batch_size = 32
def generate_eval_samples(generator, batch_size, latent_dim, num_classes):
latents = truncated_normal(( batch_size, latent_dim), dtype=torch.float32, device=device)
 labels = torch.randint(0, num_classes, size=(batch_size,), dtype=torch.long, device=device)
 with torch.no_grad() :
imgs =(generator(latents, labels)+ 1)/ 2
return imgs<split>
start = time()
repeat_breeds = 5
nrow = 15
split_size = 50
latent_dim = config['sample_latents']['latent_dim']
num_classes = config['sample_latents']['num_classes']
all_labels = torch.arange(num_classes, dtype=torch.long, device=device)
 all_labels = all_labels.repeat_interleave(repeat_breeds)
 labels_split = all_labels.split(split_size)
 imgs_list = []
for labels in labels_split:
batch_size = labels.size(0)
 latents = truncated_normal(( batch_size, latent_dim), threshold=1.5, dtype=torch.float32, device=device)
 with torch.no_grad() :
imgs =(netGE(latents, labels)+ 1)/ 2
imgs_list.append(imgs)
 all_imgs = torch.cat(imgs_list, dim=0)
 all_imgs = make_grid(all_imgs, nrow=nrow, normalize=False)
 all_imgs = all_imgs.mul_(255 ).add_(0.5 ).clamp_(0, 255 ).permute(1, 2, 0 ).to('cpu', torch.uint8 ).numpy()
plt.figure(figsize=(2*nrow, 2*(num_classes*repeat_breeds)//nrow))
plt.imshow(all_imgs);<define_variables>
def seed_everything(seed=42):
random.seed(seed)
 os.environ['PYTHONHASHSEED'] = str(seed)
 np.random.seed(seed)
 torch.manual_seed(seed)
 torch.cuda.manual_seed(seed)
 torch.backends.cudnn.deterministic = True
seed_everything()
ComputeLB = False
DogsOnly = False
ROOT = '.. /input/generative-dog-images/'
if not ComputeLB: ROOT = '.. /input/'
IMAGES = os.listdir(ROOT + 'all-dogs/all-dogs/')
 breeds = os.listdir(ROOT + 'annotation/Annotation/')
 idxIn = 0; namesIn = []
imagesIn = np.zeros(( 25000,64,64,3))
if DogsOnly:
for breed in breeds:
for dog in os.listdir(ROOT+'annotation/Annotation/'+breed):
try: img = Image.open(ROOT+'all-dogs/all-dogs/'+dog+'.jpg')
 except: continue
tree = ET.parse(ROOT+'annotation/Annotation/'+breed+'/'+dog)
 root = tree.getroot()
objects = root.findall('object')
 for o in objects:
bndbox = o.find('bndbox')
 xmin = int(bndbox.find('xmin' ).text)
 ymin = int(bndbox.find('ymin' ).text)
 xmax = int(bndbox.find('xmax' ).text)
 ymax = int(bndbox.find('ymax' ).text)
 w = np.min(( xmax - xmin, ymax - ymin))
w = xmax - xmin
h = ymax - ymin
l = max([w,h])
 if w > h:
ymin = ymin - int(( l-h)/2)
 else:
xmin = xmin - int(( l-w)/2)
 bbox =(xmin, ymin , xmin + l, ymin + l)
 img2 = img.crop(bbox)
 img2 = img2.resize(( 64,64), Image.ANTIALIAS)
 imagesIn[idxIn,:,:,:] = np.asarray(img2)
 namesIn.append(breed)
 idxIn += 1
else:
IMAGES = np.sort(IMAGES)
 np.random.seed(57)
 x = np.random.choice(np.arange(20579),10000, replace=False)
 np.random.seed(None)
 for k in range(len(x)) :
img = Image.open(ROOT + 'all-dogs/all-dogs/' + IMAGES[x[k]])
 w = img.size[0]; h = img.size[1];
if False:
w2 = 100; h2 = int(h/(w/100))
a = 18; b = 0
else:
a=0; b=0
if w<h:
if w/h <= 0.74:
img = img.resize(( 400,300), Image.ANTIALIAS)
 w = img.size[0]; h = img.size[1];
w2 = 64; h2 = int(( 64/w)*h)
 b =(h2-64)//2
if w/h >0.74:
w2 = 73; h2 = int(( 73/w)*h)
 b = 0; a = 0
else:
if h/w <= 0.74:
img = img.resize(( 300,400), Image.ANTIALIAS)
 w = img.size[0]; h = img.size[1];
h2 = 64; w2 = int(( 64/h)*w)
 a =(w2-64)//2
if h/w >0.74:
h2 = 73; w2 = int(( 73/h)*w)
 b = 0; a = 0
img = img.resize(( w2,h2), Image.ANTIALIAS)
 img = img.crop(( 0+a, 0+b, 64+a, 64+b))
img = ImageOps.mirror(img)
 imagesIn[idxIn,:,:,:] = np.asarray(img)
 namesIn.append(IMAGES[x[k]])
 idxIn += 1
y = np.random.randint(0,idxIn,25)
 for k in range(5):
plt.figure(figsize=(15,3))
for j in range(5):
plt.subplot(1,5,j+1)
 img = Image.fromarray(imagesIn[y[k*5+j],:,:,:].astype('uint8'))
plt.axis('off')
 if not DogsOnly: plt.title(namesIn[y[k*5+j]],fontsize=11)
 else: plt.title(namesIn[y[k*5+j]].split('-')[1],fontsize=11)
 plt.imshow(img)
 plt.show() 
<import_modules>
class DataGenerator(Dataset):
def __init__(self, directory, transform=None, n_samples=np.inf):
self.directory = directory
self.transform = transform
self.n_samples = n_samples
self.samples = self._load_subfolders_images(directory)
 if len(self.samples)== 0:
raise RuntimeError("Found 0 files in subfolders of: {}".format(directory))
def _load_subfolders_images(self, root):
IMG_EXTENSIONS =(
 '.jpg', '.jpeg', '.png', '.ppm', '.bmp', '.pgm', '.tif', '.tiff', '.webp')
 aug_pipeline = iaa.Sequential([
iaa.ContrastNormalization(( 1.0, 1.3)) ,
iaa.Affine(scale=(1.0, 1.2)) ,
iaa.Sometimes(0.5, iaa.Sharpen(alpha=(0, 0.1), lightness=(1, 1.2))),
])
 def is_valid_file(x):
return torchvision.datasets.folder.has_file_allowed_extension(x, IMG_EXTENSIONS)
 required_transforms = torchvision.transforms.Compose([
torchvision.transforms.Resize(64),
torchvision.transforms.CenterCrop(64),
])
 imgs = []
paths = []
for root, _, fnames in sorted(os.walk(root)) :
for fname in sorted(fnames)[:min(self.n_samples, 999999999999999)]:
path = os.path.join(root, fname)
 paths.append(path)
 for path in tqdm(paths):
if is_valid_file(path):
img = dset.folder.default_loader(path)
 annotation_basename = os.path.splitext(os.path.basename(path)) [0]
annotation_dirname = next(
 dirname for dirname in os.listdir('.. /input/annotation/Annotation/')if
dirname.startswith(annotation_basename.split('_')[0]))
annotation_filename = os.path.join('.. /input/annotation/Annotation/',
annotation_dirname, annotation_basename)
 tree = ET.parse(annotation_filename)
 root = tree.getroot()
objects = root.findall('object')
 for o in objects:
bndbox = o.find('bndbox')
 xmin = int(bndbox.find('xmin' ).text)
 ymin = int(bndbox.find('ymin' ).text)
 xmax = int(bndbox.find('xmax' ).text)
 ymax = int(bndbox.find('ymax' ).text)
 w = np.min(( xmax - xmin, ymax - ymin))
bbox =(xmin, ymin, xmin+w, ymin+w)
 object_img = required_transforms(img.crop(bbox))
imgs.append(object_img)
 if np.random.randint(0, 2)== 0:
aug_img = Image.fromarray(aug_pipeline.augment_image(np.array(object_img)))
 imgs.append(aug_img)
 return imgs
def __getitem__(self, index):
sample = self.samples[index]
if self.transform is not None:
sample = self.transform(sample)
 return np.asarray(sample)
 def __len__(self):
return len(self.samples)
from keras.models import Model
from keras.layers import Input, Dense, Conv2D, Reshape, Flatten, concatenate
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import LearningRateScheduler
from keras.optimizers import SGD, Adam<choose_model_class>
%%time
database = '.. /input/all-dogs/all-dogs/'
transform = transforms.Compose([transforms.RandomRotation(5),
transforms.RandomHorizontalFlip(p=0.2),
transforms.ToTensor() ,
transforms.Normalize(( 0.5, 0.5, 0.5),(0.5, 0.5, 0.5)) ])
 train_data = DataGenerator(database, transform=transform,n_samples=25000)
 train_loader = torch.utils.data.DataLoader(train_data, shuffle=True,batch_size=batch_size, num_workers = 4)
 print(len(train_loader))
def define_discriminator(in_shape=(28,28,1)) :
	model = Sequential()
	
	model.add(Conv2D(128,(3,3), strides=(2,2), padding='same', input_shape=in_shape))
	model.add(LeakyReLU(alpha=0.2))
	
	model.add(Conv2D(128,(3,3), strides=(2,2), padding='same'))
	model.add(LeakyReLU(alpha=0.2))
	
	model.add(Flatten())
 	model.add(Dropout(0.4))
	model.add(Dense(1, activation='sigmoid'))
	
	opt = Adam(lr=0.0002, beta_1=0.5)
 	model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
 	return model<categorify>
class PixelwiseNorm(nn.Module):
def __init__(self):
super(PixelwiseNorm, self ).__init__()
def forward(self, x, alpha=1e-8):

 y = x.pow(2.).mean(dim=1, keepdim=True ).add(alpha ).sqrt()
y = x / y
return y
def define_discriminator(in_shape=(28,28,1), n_classes=10):
	
	in_label = Input(shape=(1,))
	
	li = Embedding(n_classes, 50 )(in_label)
 	
	n_nodes = in_shape[0] * in_shape[1]
	li = Dense(n_nodes )(li)
 	
	li = Reshape(( in_shape[0], in_shape[1], 1))(li)
 	
	in_image = Input(shape=in_shape)
 	
	merge = Concatenate()([in_image, li])
 	
	fe = Conv2D(128,(3,3), strides=(2,2), padding='same' )(merge)
 	fe = LeakyReLU(alpha=0.2 )(fe)
 	
	fe = Conv2D(128,(3,3), strides=(2,2), padding='same' )(fe)
 	fe = LeakyReLU(alpha=0.2 )(fe)
 	
	fe = Flatten()(fe)
 	
	fe = Dropout(0.4 )(fe)
 	
	out_layer = Dense(1, activation='sigmoid' )(fe)
 	
	model = Model([in_image, in_label], out_layer)
 	
	opt = Adam(lr=0.0002, beta_1=0.5)
 	model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'])
 	return model<define_search_model>
class MinibatchStdDev(th.nn.Module):

 def __init__(self):

 super(MinibatchStdDev, self ).__init__()
def forward(self, x, alpha=1e-8):

 batch_size, _, height, width = x.shape
y = x - x.mean(dim=0, keepdim=True)
 y = th.sqrt(y.pow(2.).mean(dim=0, keepdim=False)+ alpha)
 y = y.mean().view(1, 1, 1, 1)
 y = y.repeat(batch_size,1, height, width)
 y = th.cat([x, y], 1)
 return y
<train_model><EOS> 
patchsize = 16
class Generator(nn.Module):
def __init__(self, nz, nfeats, nchannels):
super(Generator, self ).__init__()
ksize = 4
self.conv1 = spectral_norm(nn.ConvTranspose2d(nz, nfeats * 8, ksize, 1, 0, bias=False))
self.conv2 = spectral_norm(nn.ConvTranspose2d(nfeats * 8, nfeats * 8, ksize, 2, 1, bias=False))
self.conv3 = spectral_norm(nn.ConvTranspose2d(nfeats * 8, nfeats * 4, ksize, 2, 1, bias=False))
self.conv4 = spectral_norm(nn.ConvTranspose2d(nfeats * 4, nfeats * 2, ksize, 2, 1, bias=False))
self.conv5 = spectral_norm(nn.ConvTranspose2d(nfeats * 2, nfeats, ksize, 2, 1, bias=False))
self.conv6 = spectral_norm(nn.ConvTranspose2d(nfeats, nchannels, 3, 1, 1, bias=False))
self.pixnorm = PixelwiseNorm()
def forward(self, x):
x = F.leaky_relu(self.conv1(x))
x = F.leaky_relu(self.conv2(x))
x = self.pixnorm(x)
 x = F.leaky_relu(self.conv3(x))
x = self.pixnorm(x)
 x = F.leaky_relu(self.conv4(x))
x = self.pixnorm(x)
 x = F.leaky_relu(self.conv5(x))
x = self.pixnorm(x)
 x = torch.tanh(self.conv6(x))
return x
class Discriminator(nn.Module):
def __init__(self, nchannels, nfeats):
super(Discriminator, self ).__init__()
self.conv1 = nn.Conv2d(nchannels, nfeats, 4, 2, 1, bias=False)
 self.conv2 = spectral_norm(nn.Conv2d(nfeats, nfeats * 2, 4, 2, 1, bias=False))
self.bn2 = nn.BatchNorm2d(nfeats * 2)
 self.conv3 = spectral_norm(nn.Conv2d(nfeats * 2, nfeats * 4, 4, 2, 1, bias=False))
self.bn3 = nn.BatchNorm2d(nfeats * 4)
 self.conv4 = spectral_norm(nn.Conv2d(nfeats * 4, nfeats * 8, 4, 2, 1, bias=False))
self.bn4 = nn.MaxPool2d(2)
 self.batch_discriminator = MinibatchStdDev()
self.pixnorm = PixelwiseNorm()
self.conv5 = spectral_norm(nn.Conv2d(nfeats * 8 +1, patchsize, 2, 1, 0, bias=False))
def forward(self, x):
x = F.leaky_relu(self.conv1(x), 0.2)
 x = F.leaky_relu(self.bn2(self.conv2(x)) , 0.2)
 x = F.leaky_relu(self.bn3(self.conv3(x)) , 0.2)
 x = F.leaky_relu(self.bn4(self.conv4(x)) , 0.2)
 x = self.batch_discriminator(x)
 x = torch.sigmoid(self.conv5(x))
return x.view(-1, 1)
 device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 lr = 0.0001
lr_d = 0.0003
beta1 = 0.5
epochs = 1600
nz = 196
netG = Generator(nz, 64, 3 ).to(device)
 netD = Discriminator(3, 64 ).to(device)
 criterion = nn.BCELoss()
optimizerD = optim.Adam(netD.parameters() , lr=lr_d, betas=(beta1, 0.999))
optimizerG = optim.Adam(netG.parameters() , lr=lr, betas=(beta1, 0.999))
lr_schedulerG = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(optimizerG,
T_0=epochs//200, eta_min=0.00005)
 lr_schedulerD = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(optimizerD,
T_0=epochs//200, eta_min=0.00005)
 fixed_noise = torch.randn(25, nz, 1, 1, device=device)
 batch_size = train_loader.batch_size
step = 0
for epoch in range(epochs):
for ii,(real_images)in tqdm(enumerate(train_loader), total=len(train_loader)) :
end = time()
if(end - start)> 25000 :
break
if step % 20 == 0:
real_label = 0.0
fake_label = 0.7
else:
real_label = 0.7
fake_label = 0.0
netD.zero_grad()
real_images = real_images.to(device)
 batch_size = real_images.size(0)
 labels = torch.full(( batch_size, patchsize), real_label, device=device ).view(-1, 1)+ np.random.uniform(-0.1, 0.1)
 output = netD(real_images)
 errD_real = criterion(output, labels)
 errD_real.backward()
D_x = output.mean().item()
noise = torch.randn(batch_size, nz, 1, 1, device=device)
 fake = netG(noise)
 labels.fill_(fake_label)+ np.random.uniform(0, 0.2)
 output = netD(fake.detach())
 errD_fake = criterion(output, labels)
 errD_fake.backward()
D_G_z1 = output.mean().item()
errD = errD_real + errD_fake
optimizerD.step()
netG.zero_grad()
labels.fill_(real_label)
 output = netD(fake)
 errG = criterion(output, labels)
 errG.backward()
D_G_z2 = output.mean().item()
optimizerG.step()
if step % 500 == 0:
print('[%d/%d][%d/%d] Loss_D: %.4f Loss_G: %.4f D(x): %.4f D(G(z)) : %.4f / %.4f'
%(epoch + 1, epochs, ii, len(train_loader),
errD.item() , errG.item() , D_x, D_G_z1, D_G_z2))
valid_image = netG(fixed_noise)
 step += 1
lr_schedulerG.step(epoch)
 lr_schedulerD.step(epoch)
 if epoch % 5 == 0:
show_generated_img()
def truncated_normal(size, threshold=1):
values = truncnorm.rvs(-threshold, threshold, size=size)
 return values
if not os.path.exists('.. /output_images'):
os.mkdir('.. /output_images')
 im_batch_size = 100
n_images=10000
for i_batch in range(0, n_images, im_batch_size):
z = truncated_normal(( im_batch_size, nz, 1, 1), threshold=1)
 gen_z = torch.from_numpy(z ).float().to(device)
 gen_images = netG(gen_z)
 images = gen_images.to("cpu" ).clone().detach()
images = images.numpy().transpose(0, 2, 3, 1)
 for i_image in range(gen_images.size(0)) :
save_image(( gen_images[i_image, :, :, :] +1.0)/2.0, os.path.join('.. /output_images', f'image_{i_batch+i_image:05d}.png'))
shutil.make_archive('images', 'zip', '.. /output_images' )