Kaggle competition: Deepfake Detection Challenge
<SOS> metric: LogLoss Kaggle data source: deepfake-detection-challenge<save_to_csv>
!pip install.. /input/facenet-pytorch-vggface2/facenet_pytorch-2.0.1-py3-none-any.whl
!mkdir -p /root/.cache/torch/checkpoints/
!cp.. /input/facenet-pytorch-vggface2/20180402-114759-vggface2-logits.pth /root/.cache/torch/checkpoints/vggface2_DG3kwML46X.pt
!cp.. /input/facenet-pytorch-vggface2/20180402-114759-vggface2-features.pth /root/.cache/torch/checkpoints/vggface2_G5aNV2VSMn.pt
if BUILD95:
plt.hist(oof,bins=100)
 plt.ylim(( 0,5000))
plt.title('XGB OOF')
 plt.show()
X_train['oof'] = oof
X_train.reset_index(inplace=True)
 X_train[['TransactionID','oof']].to_csv('oof_xgb_95.csv')
 X_train.set_index('TransactionID',drop=True,inplace=True)
 else: X_train['oof'] = 0<save_to_csv>
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
if BUILD95:
sample_submission = pd.read_csv('.. /input/ieee-fraud-detection/sample_submission.csv')
 sample_submission.isFraud = preds
sample_submission.to_csv('sub_xgb_95.csv',index=False)
 plt.hist(sample_submission.isFraud,bins=100)
 plt.ylim(( 0,5000))
plt.title('XGB95 Submission')
 plt.show()<data_type_conversions>
submission_path = '.. /input/deepfake-detection-challenge/sample_submission.csv'
train_video_path = '.. /input/deepfake-detection-challenge/train_sample_videos'
test_video_path = '.. /input/deepfake-detection-challenge/test_videos'
X_train['day'] = X_train.TransactionDT /(24*60*60)
 X_train['uid'] = X_train.card1_addr1.astype(str)+'_'+np.floor(X_train.day-X_train.D1 ).astype(str)
 X_test['day'] = X_test.TransactionDT /(24*60*60)
 X_test['uid'] = X_test.card1_addr1.astype(str)+'_'+np.floor(X_test.day-X_test.D1 ).astype(str )<categorify>
list_train = glob(os.path.join(train_video_path, '*.mp4'))
print(f'Sum video in train: {len(list_train)}' )
%%time
encode_FE(X_train,X_test,['uid'])
 encode_AG(['TransactionAmt','D4','D9','D10','D15'],['uid'],['mean','std'],fillna=True,usena=True)
 encode_AG(['C'+str(x)for x in range(1,15)if x!=3],['uid'],['mean'],X_train,X_test,fillna=True,usena=True)
 encode_AG(['M'+str(x)for x in range(1,10)],['uid'],['mean'],fillna=True,usena=True)
 encode_AG2(['P_emaildomain','dist1','DT_M','id_02','cents'], ['uid'], train_df=X_train, test_df=X_test)
 encode_AG(['C14'],['uid'],['std'],X_train,X_test,fillna=True,usena=True)
 encode_AG2(['C13','V314'], ['uid'], train_df=X_train, test_df=X_test)
 encode_AG2(['V127','V136','V309','V307','V320'], ['uid'], train_df=X_train, test_df=X_test)
 X_train['outsider15'] =(np.abs(X_train.D1-X_train.D15)>3 ).astype('int8')
 X_test['outsider15'] =(np.abs(X_test.D1-X_test.D15)>3 ).astype('int8')
 print('outsider15' )<drop_column>
list_test = glob(os.path.join(test_video_path, '*.mp4'))
print(f'Sum video in test: {len(list_test)}' )
cols = list(X_train.columns)
 cols.remove('TransactionDT')
 for c in ['D6','D7','D8','D9','D12','D13','D14']:
cols.remove(c)
 for c in ['oof','DT_M','day','uid']:
cols.remove(c)
 for c in ['C3','M5','id_08','id_33']:
cols.remove(c)
 for c in ['card4','id_07','id_14','id_21','id_30','id_32','id_34']:
cols.remove(c)
 for c in ['id_'+str(x)for x in range(22,28)]:
cols.remove(c )<prepare_x_and_y>
train_json = glob(os.path.join(train_video_path, '*.json'))
with open(train_json[0], 'rt')as file:
train = json.load(file)
 train_df = pd.DataFrame()
train_df['file'] = train.keys()
label = [i['label'] for i in train.values() if isinstance(i, dict)]
train_df['label'] = label
split = [i['split'] for i in train.values() if isinstance(i, dict)]
train_df['split'] = split
original = [i['original'] for i in train.values() if isinstance(i, dict)]
train_df['original'] = original
train_df['original'] = train_df['original'].fillna(train_df['file'])
 train_df.head()
idxT = X_train.index[:3*len(X_train)//4]
idxV = X_train.index[3*len(X_train)//4:] 
<train_model>
original_same = train_df.pivot_table(values=['file'], columns=['label'], index=['original'], fill_value=0, aggfunc='count')
 original_same = original_same[(original_same[('file', 'FAKE')] != 0)&(original_same[('file', 'REAL')] != 0)]
print(f'Number of file having both FAKE and REAL: {len(original_same)}')
 original_same
if BUILD96:
clf = xgb.XGBClassifier(
 n_estimators=2000,
max_depth=12,
learning_rate=0.02,
subsample=0.8,
colsample_bytree=0.4,
missing=-1,
eval_metric='auc',
tree_method='gpu_hist' 
)
 h = clf.fit(X_train.loc[idxT,cols], y_train[idxT],
eval_set=[(X_train.loc[idxV,cols],y_train[idxV])],
verbose=50, early_stopping_rounds=100 )<train_on_grid>
train_df['label'] = train_df['label'].apply(lambda x: 1 if x=='FAKE' else 0 )
if BUILD96:
oof = np.zeros(len(X_train))
preds = np.zeros(len(X_test))
skf = GroupKFold(n_splits=6)
 for i,(idxT, idxV)in enumerate(skf.split(X_train, y_train, groups=X_train['DT_M'])) :
month = X_train.iloc[idxV]['DT_M'].iloc[0]
print('Fold',i,'withholding month',month)
 print(' rows of train =',len(idxT),'rows of holdout =',len(idxV))
clf = xgb.XGBClassifier(
 n_estimators=5000,
max_depth=12,
learning_rate=0.02,
subsample=0.8,
colsample_bytree=0.4,
missing=-1,
eval_metric='auc',
tree_method='gpu_hist' 
)
 h = clf.fit(X_train[cols].iloc[idxT], y_train.iloc[idxT],
eval_set=[(X_train[cols].iloc[idxV],y_train.iloc[idxV])],
verbose=100, early_stopping_rounds=200)
 oof[idxV] += clf.predict_proba(X_train[cols].iloc[idxV])[:,1]
preds += clf.predict_proba(X_test[cols])[:,1]/skf.n_splits
del h, clf
x=gc.collect()
print('
print('XGB96 OOF CV=',roc_auc_score(y_train,oof))<save_to_csv>
def transfer(label):
if label==0:
return "real"
else:
return "fake"
def display_mtcnn(number_frame=3, number_video=2):
fake_real = original_same[(original_same[('file', 'FAKE')] == 1)&(original_same[('file', 'REAL')] == 1)].index.tolist()
original_images = random.sample(fake_real, number_video)
 for original_image in original_images:
real_video = train_df[(train_df['label']==0)&(train_df['original']==original_image)]['file'].values[0]
fake_video = train_df[(train_df['label']==1)&(train_df['original']==original_image)]['file'].values[0]
if(real_video in os.listdir(train_video_path)) and(fake_video in os.listdir(train_video_path)) :
real_path = os.path.join(train_video_path, real_video)
 fake_path = os.path.join(train_video_path, fake_video)
 fig, axes = plt.subplots(number_frame, 2, figsize=(20, 20))
for ind, path in enumerate([real_path, fake_path]):
cap = cv2.VideoCapture(path)
 frame_index = 0
ax_ix = 0
while True:
ret, frame = cap.read()
if cv2.waitKey(1)& 0xFF == 27:
break
if ret:
if frame_index%24==0:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
 frame = Image.fromarray(frame)
 boxes, scores = box_mtcnn(frame, False)
 box = boxes[scores.argmax() ]
frame_crop = frame.crop(box)
 boxes, scores, landmarks = box_mtcnn(frame_crop)
 if landmarks is not None:
landmark = landmarks[scores.argmax() ]
axes[ax_ix, ind].scatter(landmark[:, 0], landmark[:, 1], c='red', s=8)
 axes[ax_ix, ind].imshow(frame_crop)
 axes[ax_ix, ind].xaxis.set_visible(False)
 axes[ax_ix, ind].yaxis.set_visible(False)
 axes[ax_ix, ind].set_title(f'Frame: {frame_index}_{transfer(ind)}')
 fig.tight_layout()
ax_ix += 1
if ax_ix == number_frame:
break
else:
break
frame_index+=1
fig.suptitle(original_image, color='b', size=20, y=1)
 display_mtcnn(number_frame=3, number_video=3 )
if BUILD96:
plt.hist(oof,bins=100)
 plt.ylim(( 0,5000))
plt.title('XGB OOF')
 plt.show()
X_train['oof'] = oof
X_train.reset_index(inplace=True)
 X_train[['TransactionID','oof']].to_csv('oof_xgb_96.csv')
 X_train.set_index('TransactionID',drop=True,inplace=True )<save_to_csv>
class VideoDataset(Dataset):
def __init__(self, df, path_video, num_frame=5, is_train=True):
super(VideoDataset, self ).__init__()
self.df = df
self.num_frame = num_frame
self.is_train = is_train
self.path_video = path_video
index_list = deque()
for index in tqdm(range(len(self.df))):
video_name = self.df.loc[index, 'file']
video_path = os.path.join(self.path_video, video_name)
 if self.landmark_mtcnn(video_path)is not None:
index_list.append(index)
 index_list = list(index_list)
 self.df = self.df[self.df.index.isin(index_list)]
self.df.reset_index(inplace=True, drop=True)
 def __len__(self):
return len(self.df)
 def __getitem__(self, idx):
video_name = self.df.loc[idx, 'file']
video_path = os.path.join(self.path_video, video_name)
 list_landmark = self.landmark_mtcnn(video_path)
 if self.is_train:
label = self.df.loc[idx, 'label']
return torch.from_numpy(list_landmark), torch.tensor(label, dtype=torch.float)
 else:
return video_name, torch.from_numpy(list_landmark)
 def landmark_mtcnn(self, video_path):
cap = cv2.VideoCapture(video_path)
 frame_index = 0
list_landmark = deque()
while len(list_landmark)< 10*self.num_frame:
ret, frame = cap.read()
if cv2.waitKey(1)& 0xFF == 27:
break
if ret:
if frame_index % 24 == 0:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
 frame = Image.fromarray(frame)
 boxes, scores, landmarks = box_mtcnn(frame)
 if scores[0]:
index_max = np.argmax(scores)
 landmark = landmarks[index_max]
list_landmark.extend(landmark.flatten())
 else:
break
frame_index+=1
list_landmark = list(list_landmark)
 if len(list_landmark)== 10*self.num_frame:
list_landmark = np.array(list_landmark ).reshape(self.num_frame, 10)
 return list_landmark
return None
dataset = VideoDataset(train_df, train_video_path )
if BUILD96:
sample_submission = pd.read_csv('.. /input/ieee-fraud-detection/sample_submission.csv')
 sample_submission.isFraud = preds
sample_submission.to_csv('sub_xgb_96.csv',index=False)
 plt.hist(sample_submission.isFraud,bins=100)
 plt.ylim(( 0,5000))
plt.title('XGB96 Submission')
 plt.show()<load_from_csv>
test_size = 0.2
index_split = int(len(dataset)*test_size)
 list_index =(list(range(len(dataset))))
random.shuffle(list_index)
 train_idx = list_index[index_split:]
val_idx = list_index[:index_split]
train_dataset = Subset(dataset, train_idx)
 val_dataset = Subset(dataset, val_idx)
 train_ld = DataLoader(train_dataset, batch_size=8, shuffle=True)
 val_ld = DataLoader(val_dataset, batch_size=8, shuffle=True )
X_test['isFraud'] = sample_submission.isFraud.values
X_train['isFraud'] = y_train.values
comb = pd.concat([X_train[['isFraud']],X_test[['isFraud']]],axis=0)
 uids = pd.read_csv('/kaggle/input/ieee-submissions-and-uids/uids_v4_no_multiuid_cleaning.. csv',usecols=['TransactionID','uid'] ).rename({'uid':'uid2'},axis=1)
 comb = comb.merge(uids,on='TransactionID',how='left')
 mp = comb.groupby('uid2' ).isFraud.agg(['mean'])
 comb.loc[comb.uid2>0,'isFraud'] = comb.loc[comb.uid2>0].uid2.map(mp['mean'])
 uids = pd.read_csv('/kaggle/input/ieee-submissions-and-uids/uids_v1_no_multiuid_cleaning.csv',usecols=['TransactionID','uid'] ).rename({'uid':'uid3'},axis=1)
 comb = comb.merge(uids,on='TransactionID',how='left')
 mp = comb.groupby('uid3' ).isFraud.agg(['mean'])
 comb.loc[comb.uid3>0,'isFraud'] = comb.loc[comb.uid3>0].uid3.map(mp['mean'])
 sample_submission.isFraud = comb.iloc[len(X_train):].isFraud.values
sample_submission.to_csv('sub_xgb_96_PP.csv',index=False )<import_modules>
class swish(Module):
def __init__(self):
super(swish, self ).__init__()
self.sigmoid = nn.Sigmoid()
def forward(self, x):
return x*self.sigmoid(x)
 class small_model(Module):
def __init__(self, num_class=1):
super(small_model, self ).__init__()
self.conv = nn.Sequential(nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(32),
nn.ReLU(inplace=True),
nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, kernel_size=1, stride=1, padding=0),
nn.BatchNorm2d(64),
nn.Dropout(0.2))
self.fc = nn.Sequential(nn.Linear(64*10*5, 128),
nn.ReLU(inplace=True),
nn.BatchNorm1d(128),
nn.Dropout(0.2),
nn.Linear(128, num_class),
nn.Sigmoid())
 def forward(self, x):
x = self.conv(x)
 x = torch.flatten(x, 1)
 x = self.fc(x)
 return x
model = small_model().to(device)
 model.eval()
<import_modules><EOS> 
class Trainer(object):
def __init__(self, model):
self.model = model
self.creation = nn.MSELoss()
self.optimizer = optim.AdamW([
{'params': model.conv.parameters() , 'lr': 1e-4},
{'params': model.fc.parameters() , 'lr': 1e-3}], lr=0.001)
 self.scheduler = ReduceLROnPlateau(self.optimizer, mode='min', factor=0.15)
 def train_process(self, train_ld, val_ld, epochs):
score_max = 0
check_step = 0
loss_min = 1
check_number = 13
self.model.train()
for epoch in range(epochs):
train_loss, val_loss = 0, 0
for crop, label in tqdm(train_ld):
crop = crop.unsqueeze(1)
 crop, label = crop.float().to(device), label.to(device)
 self.optimizer.zero_grad()
output = self.model(crop ).squeeze(1)
 loss = self.creation(output, label)
 loss.backward()
self.optimizer.step()
self.scheduler.step(train_loss)
 train_loss += loss.item()
del crop, label
train_loss = train_loss/len(train_ld)
 torch.cuda.empty_cache()
gc.collect()
self.model.eval()
val_score = 0
with torch.no_grad() :
for crop, label in tqdm(val_ld):
crop = crop.unsqueeze(1)
 crop, label = crop.float().to(device), label.to(device)
 output = self.model(crop ).squeeze(1)
 loss = self.creation(output, label)
 val_loss += loss.item()
val_score += torch.sum(( output>0.5 ).float() == label ).item() /len(label)
 val_loss = val_loss/len(val_ld)
 val_score = val_score/len(val_ld)
 self.scheduler.step(val_loss)
 if val_score > score_max:
print(f'Epoch: {epoch}, train loss: {train_loss:.5f}, val_loss: {val_loss:.5f}.
 Validation score increased from {score_max:.5f} to {val_score:.5f}')
 score_max = val_score
loss_min = val_loss
torch.save(self.model.state_dict() , 'model.pth')
 print('Saving model!')
 check_step = 0
elif val_score == score_max:
if val_loss < loss_min:
print(f'Epoch: {epoch}, train loss: {train_loss:.5f}, val_loss: {val_loss:.5f}, val_score: {val_score:.5f}.
 Validation loss decreased from {loss_min:.5f} to {val_loss:.5f}')
 loss_min = val_loss
torch.save(self.model.state_dict() , 'model.pth')
 print('Saving model!')
 check_step = 0
else:
check_step += 1
print(f'Epoch: {epoch}, train loss: {train_loss:.5f}, val_loss: {val_loss:.5f}, val_score: {val_score:.5f}.
 Model not improve in {str(check_step)} step')
 if check_step > check_number:
print('Stop trainning!')
 break
else:
check_step += 1
print(f'Epoch: {epoch}, train loss: {train_loss:.5f}, val_loss: {val_loss:.5f}.
 Validation score not increased from {val_score:.5f} in {str(check_step)} step')
 if check_step > check_number:
print('Stop trainning!')
 break
trainer = Trainer(model)
 trainer.train_process(train_ld=train_ld, val_ld=val_ld, epochs=20 )