Kaggle competition: ALASKA2 Image Steganalysis
<SOS> metric: WeightedAUC Kaggle data source: alaska2-image-steganalysis<feature_engineering>
!pip install -q efficientnet_pytorch
Compose, HorizontalFlip, CLAHE, HueSaturationValue,
RandomBrightness, RandomContrast, RandomGamma, OneOf, Resize,
ToFloat, ShiftScaleRotate, GridDistortion, ElasticTransform, JpegCompression, HueSaturationValue,
RGBShift, RandomBrightness, RandomContrast, Blur, MotionBlur, MedianBlur, GaussNoise, CenterCrop,
IAAAdditiveGaussianNoise, GaussNoise, OpticalDistortion, RandomSizedCrop, VerticalFlip 
)
new_data['release_date']=new_data['release_date'].fillna('3/20/01' )<feature_engineering>
seed = 42
print(f'setting everything to seed {seed}')
 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
new_data['release_year']=pd.to_datetime(new_data['release_date'] ).dt.year
new_data['release_month']=pd.to_datetime(new_data['release_date'] ).dt.month
new_data['release_day']=pd.to_datetime(new_data['release_date'] ).dt.day
new_data['release_dayofweek'] = pd.to_datetime(new_data['release_date'] ).dt.dayofweek
new_data['release_quarter'] = pd.to_datetime(new_data['release_date'] ).dt.quarter<feature_engineering>
data_dir = '.. /input/alaska2-image-steganalysis'
folder_names = ['JMiPOD/', 'JUNIWARD/', 'UERD/']
class_names = ['Normal', 'JMiPOD_75', 'JMiPOD_90', 'JMiPOD_95',
'JUNIWARD_75', 'JUNIWARD_90', 'JUNIWARD_95',
'UERD_75', 'UERD_90', 'UERD_95']
class_labels = { name: i for i, name in enumerate(class_names)}
new_data['release_year'].loc[new_data['release_year']>=2018]-=100<drop_column>
train_df = pd.read_csv('.. /input/alaska2trainvalsplit/alaska2_train_df.csv')
 val_df = pd.read_csv('.. /input/alaska2trainvalsplit/alaska2_val_df.csv')
 print(train_df.sample(10))
train_df.Label.hist()
plt.title('Distribution of Classes' )
new_data=new_data.drop('release_date',axis=1 )<define_variables>
class Alaska2Dataset(Dataset):
def __init__(self, df, augmentations=None):
self.data = df
self.augment = augmentations
def __len__(self):
return len(self.data)
 def __getitem__(self, idx):
fn, label = self.data.loc[idx]
im = cv2.imread(fn)[:, :, ::-1]
if self.augment:
im = self.augment(image=im)
 return im, label
img_size = 512
AUGMENTATIONS_TRAIN = Compose([
VerticalFlip(p=0.5),
HorizontalFlip(p=0.5),
ToFloat(max_value=255),
ToTensor()
], p=1)
 AUGMENTATIONS_TEST = Compose([
ToFloat(max_value=255),
ToTensor()
], p=1)
weiji=[1929,1930,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1950,1951,1952,1953,1961,1962,1963,1964,1965,1966,1967,1968,1969,1971,1973,1974,1975,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,
1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2007,2008,2009,2010,2011]<feature_engineering>
temp_df = train_df.sample(64 ).reset_index(drop=True)
 train_dataset = Alaska2Dataset(temp_df, augmentations=AUGMENTATIONS_TEST)
 batch_size = 64
num_workers = 0
temp_loader = torch.utils.data.DataLoader(train_dataset,
batch_size=batch_size,
num_workers=num_workers, shuffle=False)
 images, labels = next(iter(temp_loader))
images = images['image'].permute(0, 2, 3, 1)
 max_images = 64
grid_width = 16
grid_height = int(max_images / grid_width)
 fig, axs = plt.subplots(grid_height, grid_width,
figsize=(grid_width+1, grid_height+1))
for i,(im, label)in enumerate(zip(images, labels)) :
ax = axs[int(i / grid_width), i % grid_width]
ax.imshow(im.squeeze())
 ax.set_title(str(label.item()))
ax.axis('off')
 plt.suptitle("0: No Hidden Message, 1: JMiPOD, 2: JUNIWARD, 3:UERD")
 plt.show()
del images
gc.collect()
for i in weiji:
new_data['is_'+str(i)]=new_data['release_year'].apply(lambda x:1 if x==i else 0 )<feature_engineering>
train_dataset = Alaska2Dataset(temp_df, augmentations=AUGMENTATIONS_TRAIN)
 batch_size = 64
num_workers = 0
temp_loader = torch.utils.data.DataLoader(train_dataset,
batch_size=batch_size,
num_workers=num_workers, shuffle=False)
 images, labels = next(iter(temp_loader))
images = images['image'].permute(0, 2, 3, 1)
 max_images = 64
grid_width = 16
grid_height = int(max_images / grid_width)
 fig, axs = plt.subplots(grid_height, grid_width,
figsize=(grid_width+1, grid_height+1))
for i,(im, label)in enumerate(zip(images, labels)) :
ax = axs[int(i / grid_width), i % grid_width]
ax.imshow(im.squeeze())
 ax.set_title(str(label.item()))
ax.axis('off')
 plt.suptitle("0: No Hidden Message, 1: JMiPOD, 2: JUNIWARD, 3:UERD")
 plt.show()
del images, temp_df
gc.collect()
new_data['homepage_fact']=new_data['homepage'].apply(lambda x: 0 if x is np.nan else 1 )<feature_engineering>
class Net(nn.Module):
def __init__(self, num_classes):
super().__init__()
self.model = EfficientNet.from_pretrained('efficientnet-b0')
 self.dense_output = nn.Linear(1280, num_classes)
 def forward(self, x):
feat = self.model.extract_features(x)
 feat = F.avg_pool2d(feat, feat.size() [2:] ).reshape(-1, 1280)
 return self.dense_output(feat )
new_data['homepage_end']=new_data[new_data['homepage'].notna() ]['homepage'].str.findall(r'\.( [a-z]+ )(?:\/|$)' ).apply(lambda x:x[0])
 new_data['homepage_end'].head()<data_type_conversions>
batch_size = 8
num_workers = 8
train_dataset = Alaska2Dataset(train_df, augmentations=AUGMENTATIONS_TRAIN)
 valid_dataset = Alaska2Dataset(val_df.sample(1000 ).reset_index(drop=True), augmentations=AUGMENTATIONS_TEST)
 train_loader = torch.utils.data.DataLoader(train_dataset,
batch_size=batch_size,
num_workers=num_workers,
shuffle=True)
 valid_loader = torch.utils.data.DataLoader(valid_dataset,
batch_size=batch_size*2,
num_workers=num_workers,
shuffle=False)
 device = 'cuda'
model = Net(num_classes=len(class_labels)).to(device)
 model.load_state_dict(torch.load('.. /input/alaska-model-weights/epoch_4_val_loss_7.0_auc_0.831.pth'))
dones = 5
optimizer = torch.optim.AdamW(model.parameters() , lr=1e-4 )
new_data['homepage_end']=new_data['homepage_end'].fillna('unknow' )<categorify>
def alaska_weighted_auc(y_true, y_valid):
tpr_thresholds = [0.0, 0.4, 1.0]
weights = [2, 1]
fpr, tpr, thresholds = metrics.roc_curve(y_true, y_valid, pos_label=1)
 areas = np.array(tpr_thresholds[1:])- np.array(tpr_thresholds[:-1])
 normalization = np.dot(areas, weights)
 competition_metric = 0
for idx, weight in enumerate(weights):
y_min = tpr_thresholds[idx]
y_max = tpr_thresholds[idx + 1]
mask =(y_min < tpr)&(tpr < y_max)
 x_padding = np.linspace(fpr[mask][-1], 1, 100)
 x = np.concatenate([fpr[mask], x_padding])
 y = np.concatenate([tpr[mask], [y_max] * len(x_padding)])
 y = y - y_min
score = metrics.auc(x, y)
 submetric = score * weight
best_subscore =(y_max - y_min)* weight
competition_metric += submetric
return competition_metric / normalization
page=pd.get_dummies(new_data['homepage_end'])
 page.head()<drop_column>
criterion = torch.nn.CrossEntropyLoss()
num_epochs = 5
train_loss, val_loss = [], []
for epoch in range(num_epochs):
print('Epoch {}/{}'.format(epoch, num_epochs - 1))
print('-' * 10)
 model.train()
running_loss = 0
tk0 = tqdm(train_loader, total=int(len(train_loader)))
 for im, labels in tk0:
inputs = im["image"].to(device, dtype=torch.float)
 labels = labels.to(device, dtype=torch.long)
 optimizer.zero_grad()
outputs = model(inputs)
 loss = criterion(outputs, labels)
 loss.backward()
optimizer.step()
running_loss += loss.item()
tk0.set_postfix(loss=(loss.item()))
epoch_loss = running_loss /(len(train_loader)/batch_size)
 train_loss.append(epoch_loss)
 print('Training Loss: {:.8f}'.format(epoch_loss))
tk1 = tqdm(valid_loader, total=int(len(valid_loader)))
 model.eval()
running_loss = 0
y, preds = [], []
with torch.no_grad() :
for(im, labels)in tk1:
inputs = im["image"].to(device, dtype=torch.float)
 labels = labels.to(device, dtype=torch.long)
 outputs = model(inputs)
 loss = criterion(outputs, labels)
 y.extend(labels.cpu().numpy().astype(int))
preds.extend(F.softmax(outputs, 1 ).cpu().numpy())
 running_loss += loss.item()
tk1.set_postfix(loss=(loss.item()))
epoch_loss = running_loss /(len(valid_loader)/batch_size)
 val_loss.append(epoch_loss)
 preds = np.array(preds)
 y = np.array(y)
 labels = preds.argmax(1)
 for class_label in np.unique(y):
idx = y == class_label
acc =(labels[idx] == y[idx] ).astype(np.float ).mean() *100
print('accuracy for class', class_names[class_label], 'is', acc)
 acc =(labels == y ).mean() *100
new_preds = np.zeros(( len(preds),))
temp = preds[labels != 0, 1:]
new_preds[labels != 0] = temp.sum(1)
 new_preds[labels == 0] = 1 - preds[labels == 0, 0]
y = np.array(y)
 y[y != 0] = 1
auc_score = alaska_weighted_auc(y, new_preds)
 print(
 f'Val Loss: {epoch_loss:.3}, Weighted AUC:{auc_score:.3}, Acc: {acc:.3}')
 torch.save(model.state_dict() ,
f"epoch_{epoch+dones}_val_loss_{epoch_loss:.3}_auc_{auc_score:.3}.pth")
new_data=new_data.drop('homepage',axis=1 )<drop_column>
class Alaska2TestDataset(Dataset):
def __init__(self, df, augmentations=None):
self.data = df
self.augment = augmentations
def __len__(self):
return len(self.data)
 def __getitem__(self, idx):
fn = self.data.loc[idx][0]
im = cv2.imread(fn)[:, :, ::-1]
if self.augment:
im = self.augment(image=im)
 return im
test_filenames = sorted(glob(f"{data_dir}/Test/*.jpg"))
test_df = pd.DataFrame({'ImageFileName': list(
 test_filenames)}, columns=['ImageFileName'])
 batch_size = 16
num_workers = 4
test_dataset = Alaska2TestDataset(test_df, augmentations=AUGMENTATIONS_TEST)
 test_loader = torch.utils.data.DataLoader(test_dataset,
batch_size=batch_size,
num_workers=num_workers,
shuffle=False,
drop_last=False )
<feature_engineering><EOS> 
model.eval()
preds = []
tk0 = tqdm(test_loader)
 with torch.no_grad() :
for i, im in enumerate(tk0):
inputs = im["image"].to(device)
 im = inputs.flip(2)
 outputs = model(im)
 im = inputs.flip(3)
 outputs =(0.25*outputs + 0.25*model(im))
outputs =(outputs + 0.5*model(inputs))
preds.extend(F.softmax(outputs, 1 ).cpu().numpy())
 preds = np.array(preds)
 labels = preds.argmax(1)
 new_preds = np.zeros(( len(preds),))
new_preds[labels != 0] = preds[labels != 0, 1:].sum(1)
 new_preds[labels == 0] = 1 - preds[labels == 0, 0]
test_df['Id'] = test_df['ImageFileName'].apply(lambda x: x.split(os.sep)[-1])
 test_df['Label'] = new_preds
test_df = test_df.drop('ImageFileName', axis=1)
 test_df.to_csv('submission_eb0.csv', index=False)
 print(test_df.head() )