Spaces:
Build error
Build error
=
commited on
Commit
·
783053f
1
Parent(s):
036d892
adding app to hugging face
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .vscode/settings.json +14 -0
- app.py +122 -0
- data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/config.json +32 -0
- data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/optimizer.pt +3 -0
- data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/pytorch_model.bin +3 -0
- data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/rng_state.pth +3 -0
- data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/scaler.pt +3 -0
- data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/scheduler.pt +3 -0
- data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/trainer_state.json +64 -0
- data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/training_args.bin +3 -0
- fake-face-detection/fake_face_detection.egg-info/PKG-INFO +6 -0
- fake-face-detection/fake_face_detection.egg-info/SOURCES.txt +12 -0
- fake-face-detection/fake_face_detection.egg-info/dependency_links.txt +1 -0
- fake-face-detection/fake_face_detection.egg-info/top_level.txt +1 -0
- fake-face-detection/fake_face_detection/__init__.py +0 -0
- fake-face-detection/fake_face_detection/__pycache__/__init__.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/data/__init__.py +0 -0
- fake-face-detection/fake_face_detection/data/__pycache__/__init__.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/data/__pycache__/collator.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/data/__pycache__/fake_face_dataset.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/data/collator.py +33 -0
- fake-face-detection/fake_face_detection/data/fake_face_dataset.py +62 -0
- fake-face-detection/fake_face_detection/metrics/__init__.py +0 -0
- fake-face-detection/fake_face_detection/metrics/__pycache__/__init__.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/metrics/__pycache__/compute_metrics.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/metrics/__pycache__/make_predictions.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/metrics/compute_metrics.py +33 -0
- fake-face-detection/fake_face_detection/metrics/make_predictions.py +147 -0
- fake-face-detection/fake_face_detection/optimization/__init__.py +0 -0
- fake-face-detection/fake_face_detection/optimization/__pycache__/__init__.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/optimization/__pycache__/bayesian_optimization.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/optimization/__pycache__/fake_face_bayesian_optimization.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/optimization/bayesian_optimization.py +78 -0
- fake-face-detection/fake_face_detection/optimization/fake_face_bayesian_optimization.py +165 -0
- fake-face-detection/fake_face_detection/trainers/__init__.py +0 -0
- fake-face-detection/fake_face_detection/trainers/__pycache__/__init__.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/trainers/__pycache__/custom_trainer.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/trainers/custom_trainer.py +27 -0
- fake-face-detection/fake_face_detection/trainers/custom_trainer_v1.txt +0 -0
- fake-face-detection/fake_face_detection/trainers/search_train.py +73 -0
- fake-face-detection/fake_face_detection/utils/__pycache__/acquisitions.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/utils/__pycache__/compute_weights.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/utils/__pycache__/generation.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/utils/__pycache__/sampling.cpython-310.pyc +0 -0
- fake-face-detection/fake_face_detection/utils/acquisitions.py +36 -0
- fake-face-detection/fake_face_detection/utils/compute_weights.py +21 -0
- fake-face-detection/fake_face_detection/utils/display_pil.py +43 -0
- fake-face-detection/fake_face_detection/utils/downscale_image.py +46 -0
- fake-face-detection/fake_face_detection/utils/generation.py +28 -0
- fake-face-detection/fake_face_detection/utils/get_patches.py +35 -0
.vscode/settings.json
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"python.defaultInterpreterPath": "C:\\Users\\Oumar Kane\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\pytorch1-HleOW5am-py3.10\\Scripts\\python.exe",
|
3 |
+
"python.terminal.activateEnvironment": true,
|
4 |
+
"terminal.integrated.defaultProfile.windows": "Command Prompt",
|
5 |
+
"files.autoSave": "afterDelay",
|
6 |
+
"files.autoSaveDelay": 1000,
|
7 |
+
"cSpell.words": [
|
8 |
+
"hyperparameters",
|
9 |
+
"photoshed",
|
10 |
+
"photoshep",
|
11 |
+
"photoshop",
|
12 |
+
"photoshopped"
|
13 |
+
]
|
14 |
+
}
|
app.py
ADDED
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from transformers import ViTForImageClassification, ViTFeatureExtractor
|
2 |
+
from fake_face_detection.metrics.make_predictions import get_attention
|
3 |
+
from torchvision import transforms
|
4 |
+
import streamlit as st
|
5 |
+
from PIL import Image
|
6 |
+
import numpy as np
|
7 |
+
import pickle
|
8 |
+
import torch
|
9 |
+
import cv2
|
10 |
+
|
11 |
+
# set the color of the header
|
12 |
+
def header(text):
|
13 |
+
st.markdown(f"<h1 style = 'color: #4B4453; text-align: center'>{text}</h1>", unsafe_allow_html=True)
|
14 |
+
st.markdown("""---""")
|
15 |
+
|
16 |
+
# initialize the size
|
17 |
+
size = (224, 224)
|
18 |
+
|
19 |
+
# let us add a header
|
20 |
+
header("FAKE AND REAL FACE DETECTION")
|
21 |
+
|
22 |
+
# let us add an expander to write some description of the application
|
23 |
+
expander = st.expander('Description', expanded=True)
|
24 |
+
|
25 |
+
with expander:
|
26 |
+
st.write('''This is a long text lorem ipsum dolor''')
|
27 |
+
|
28 |
+
# let us initialize two columns
|
29 |
+
left, mid, right = st.columns(3)
|
30 |
+
|
31 |
+
# the following function will load the model (must be in cache)
|
32 |
+
@st.cache_resource
|
33 |
+
def get_model():
|
34 |
+
|
35 |
+
# let us load the image characteristics
|
36 |
+
with open('data/extractions/fake_real_dict.txt', 'rb') as f:
|
37 |
+
|
38 |
+
depick = pickle.Unpickler(f)
|
39 |
+
|
40 |
+
characs = depick.load()
|
41 |
+
|
42 |
+
# define the model name
|
43 |
+
model_name = 'google/vit-base-patch16-224-in21k'
|
44 |
+
|
45 |
+
# recuperate the model
|
46 |
+
model = ViTForImageClassification.from_pretrained(
|
47 |
+
'data\checkpoints\model_2yW4AcqNIb6zLKNIb6zLK',
|
48 |
+
num_labels = len(characs['ids']),
|
49 |
+
id2label = {name: key for key, name in characs['ids'].items()},
|
50 |
+
label2id = characs['ids']
|
51 |
+
)
|
52 |
+
|
53 |
+
# recuperate the feature_extractor
|
54 |
+
feature_extractor = ViTFeatureExtractor(model_name)
|
55 |
+
|
56 |
+
return model, feature_extractor
|
57 |
+
|
58 |
+
# let us add a file uploader
|
59 |
+
st.subheader("Choose an image to inspect")
|
60 |
+
file = st.file_uploader("", type='jpg')
|
61 |
+
|
62 |
+
# if the file is correctly uploaded make the next processes
|
63 |
+
if file is not None:
|
64 |
+
|
65 |
+
# convert the file to an opencv image
|
66 |
+
file_bytes = np.asarray(bytearray(file.read()), dtype=np.uint8)
|
67 |
+
|
68 |
+
opencv_image = cv2.imdecode(file_bytes, 1)
|
69 |
+
|
70 |
+
# resize the image
|
71 |
+
opencv_image = cv2.resize(opencv_image, size)
|
72 |
+
|
73 |
+
# Let us display the image
|
74 |
+
left.header("Loaded image")
|
75 |
+
|
76 |
+
left.image(opencv_image, channels='BGR')
|
77 |
+
|
78 |
+
left.markdown("""---""")
|
79 |
+
|
80 |
+
if left.button("SUBMIT"):
|
81 |
+
|
82 |
+
# Let us convert the image format to 'RGB'
|
83 |
+
image = cv2.cvtColor(opencv_image, cv2.COLOR_BGR2RGB)
|
84 |
+
|
85 |
+
# Let us convert from opencv image to pil image
|
86 |
+
image = Image.fromarray(image)
|
87 |
+
|
88 |
+
with torch.no_grad():
|
89 |
+
|
90 |
+
# Recuperate the model and the feature extractor
|
91 |
+
model, feature_extractor = get_model()
|
92 |
+
|
93 |
+
# Change to evaluation mode
|
94 |
+
_ = model.eval()
|
95 |
+
|
96 |
+
# Apply transformation on the image
|
97 |
+
image_ = feature_extractor(image, return_tensors = 'pt')
|
98 |
+
|
99 |
+
# # Recuperate output from the model
|
100 |
+
outputs = model(image_['pixel_values'], output_attentions = True)
|
101 |
+
|
102 |
+
# Recuperate the predictions
|
103 |
+
predictions = torch.argmax(outputs.logits, axis = -1)
|
104 |
+
|
105 |
+
# Write the prediction to the middle
|
106 |
+
mid.markdown(f"<h2 style='text-align: center; padding: 2cm; color: black; background-color: orange; border: darkorange solid 0.3px; box-shadow: 0.2px 0.2px 0.6px 0.1px gray'>{model.config.id2label[predictions[0].item()]}</h2>", unsafe_allow_html=True)
|
107 |
+
|
108 |
+
# Let us recuperate the attention
|
109 |
+
attention = outputs.attentions[-1][0]
|
110 |
+
|
111 |
+
# Let us recuperate the attention image
|
112 |
+
attention_image = get_attention(image, attention, size = (224, 224), patch_size = (14, 14))
|
113 |
+
|
114 |
+
# Let us transform the attention image to a opencv image
|
115 |
+
attention_image = cv2.cvtColor(attention_image.astype('float32'), cv2.COLOR_RGB2BGR)
|
116 |
+
|
117 |
+
# Let us display the attention image
|
118 |
+
right.header("Attention")
|
119 |
+
|
120 |
+
right.image(attention_image, channels='BGR')
|
121 |
+
|
122 |
+
right.markdown("""---""")
|
data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/config.json
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"_name_or_path": "google/vit-base-patch16-224-in21k",
|
3 |
+
"architectures": [
|
4 |
+
"ViTForImageClassification"
|
5 |
+
],
|
6 |
+
"attention_probs_dropout_prob": 0.0,
|
7 |
+
"encoder_stride": 16,
|
8 |
+
"hidden_act": "gelu",
|
9 |
+
"hidden_dropout_prob": 0.0,
|
10 |
+
"hidden_size": 768,
|
11 |
+
"id2label": {
|
12 |
+
"0": "fake",
|
13 |
+
"1": "real"
|
14 |
+
},
|
15 |
+
"image_size": 224,
|
16 |
+
"initializer_range": 0.02,
|
17 |
+
"intermediate_size": 3072,
|
18 |
+
"label2id": {
|
19 |
+
"fake": 0,
|
20 |
+
"real": 1
|
21 |
+
},
|
22 |
+
"layer_norm_eps": 1e-12,
|
23 |
+
"model_type": "vit",
|
24 |
+
"num_attention_heads": 12,
|
25 |
+
"num_channels": 3,
|
26 |
+
"num_hidden_layers": 12,
|
27 |
+
"patch_size": 16,
|
28 |
+
"problem_type": "single_label_classification",
|
29 |
+
"qkv_bias": true,
|
30 |
+
"torch_dtype": "float32",
|
31 |
+
"transformers_version": "4.28.1"
|
32 |
+
}
|
data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/optimizer.pt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:2db8a17d7b7b6fb8c5b9ca808dfbd68977ee3eb53721a36287e69b2b0ca9a600
|
3 |
+
size 686518917
|
data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/pytorch_model.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:5f62ac6440dfa6ddd0737da7788da4569a54b1d0d8cc027ce7f623e6db55b05b
|
3 |
+
size 343268717
|
data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/rng_state.pth
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f6f8978ea188121d9fecb3f115bfdfa2c5cad2a9b0c1d0a104dddd3e07af89f6
|
3 |
+
size 14575
|
data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/scaler.pt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:7cefe4c84c26da8b0778281baf520dd6d4b41a18ea28fd317c86c1f2b76d30fb
|
3 |
+
size 557
|
data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/scheduler.pt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:ea1d89fe668b9776e02fd071e17549ee7882e574b4efb0629a6d930572aab462
|
3 |
+
size 627
|
data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/trainer_state.json
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"best_metric": 0.6927365064620972,
|
3 |
+
"best_model_checkpoint": "data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK\\checkpoint-1500",
|
4 |
+
"epoch": 1.710376282782212,
|
5 |
+
"global_step": 1500,
|
6 |
+
"is_hyper_param_search": false,
|
7 |
+
"is_local_process_zero": true,
|
8 |
+
"is_world_process_zero": true,
|
9 |
+
"log_history": [
|
10 |
+
{
|
11 |
+
"epoch": 0.57,
|
12 |
+
"learning_rate": 0.00012064414686134504,
|
13 |
+
"loss": 0.6945,
|
14 |
+
"step": 500
|
15 |
+
},
|
16 |
+
{
|
17 |
+
"epoch": 0.57,
|
18 |
+
"eval_accuracy": 0.5081081081081081,
|
19 |
+
"eval_f1": 0.38095238095238093,
|
20 |
+
"eval_loss": 0.6931825280189514,
|
21 |
+
"eval_runtime": 6.1462,
|
22 |
+
"eval_samples_per_second": 30.1,
|
23 |
+
"eval_steps_per_second": 3.905,
|
24 |
+
"step": 500
|
25 |
+
},
|
26 |
+
{
|
27 |
+
"epoch": 1.14,
|
28 |
+
"learning_rate": 0.00010514828346782865,
|
29 |
+
"loss": 0.6937,
|
30 |
+
"step": 1000
|
31 |
+
},
|
32 |
+
{
|
33 |
+
"epoch": 1.14,
|
34 |
+
"eval_accuracy": 0.4702702702702703,
|
35 |
+
"eval_f1": 0.0,
|
36 |
+
"eval_loss": 0.6942673325538635,
|
37 |
+
"eval_runtime": 11.0225,
|
38 |
+
"eval_samples_per_second": 16.784,
|
39 |
+
"eval_steps_per_second": 2.177,
|
40 |
+
"step": 1000
|
41 |
+
},
|
42 |
+
{
|
43 |
+
"epoch": 1.71,
|
44 |
+
"learning_rate": 8.962136623985633e-05,
|
45 |
+
"loss": 0.6936,
|
46 |
+
"step": 1500
|
47 |
+
},
|
48 |
+
{
|
49 |
+
"epoch": 1.71,
|
50 |
+
"eval_accuracy": 0.5297297297297298,
|
51 |
+
"eval_f1": 0.6925795053003534,
|
52 |
+
"eval_loss": 0.6927365064620972,
|
53 |
+
"eval_runtime": 6.7463,
|
54 |
+
"eval_samples_per_second": 27.423,
|
55 |
+
"eval_steps_per_second": 3.558,
|
56 |
+
"step": 1500
|
57 |
+
}
|
58 |
+
],
|
59 |
+
"max_steps": 4385,
|
60 |
+
"num_train_epochs": 5,
|
61 |
+
"total_flos": 2.323984768541614e+17,
|
62 |
+
"trial_name": null,
|
63 |
+
"trial_params": null
|
64 |
+
}
|
data/checkpoints/model_2yW4AcqNIb6zLKNIb6zLK/checkpoint-1500/training_args.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f595feb7a87c355b9cc6060e25a6fe727190de55b96c20541d829a9c3b0fe7af
|
3 |
+
size 3643
|
fake-face-detection/fake_face_detection.egg-info/PKG-INFO
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.1
|
2 |
+
Name: fake-face-detection
|
3 |
+
Version: 0.0.1
|
4 |
+
Summary: This package contains the main functions and classes used to achieve the project of detecting if a face's image is true or not.
|
5 |
+
Author: Oumar Kane
|
6 |
+
Author-email: [email protected]
|
fake-face-detection/fake_face_detection.egg-info/SOURCES.txt
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
setup.py
|
2 |
+
fake_face_detection/__init__.py
|
3 |
+
fake_face_detection.egg-info/PKG-INFO
|
4 |
+
fake_face_detection.egg-info/SOURCES.txt
|
5 |
+
fake_face_detection.egg-info/dependency_links.txt
|
6 |
+
fake_face_detection.egg-info/top_level.txt
|
7 |
+
fake_face_detection/optimization/__init__.py
|
8 |
+
fake_face_detection/optimization/bayesian_optimization.py
|
9 |
+
fake_face_detection/utils/acquisitions.py
|
10 |
+
fake_face_detection/utils/compute_weights.py
|
11 |
+
fake_face_detection/utils/generation.py
|
12 |
+
fake_face_detection/utils/sampling.py
|
fake-face-detection/fake_face_detection.egg-info/dependency_links.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
|
fake-face-detection/fake_face_detection.egg-info/top_level.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
fake_face_detection
|
fake-face-detection/fake_face_detection/__init__.py
ADDED
File without changes
|
fake-face-detection/fake_face_detection/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (262 Bytes). View file
|
|
fake-face-detection/fake_face_detection/data/__init__.py
ADDED
File without changes
|
fake-face-detection/fake_face_detection/data/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (267 Bytes). View file
|
|
fake-face-detection/fake_face_detection/data/__pycache__/collator.cpython-310.pyc
ADDED
Binary file (939 Bytes). View file
|
|
fake-face-detection/fake_face_detection/data/__pycache__/fake_face_dataset.cpython-310.pyc
ADDED
Binary file (1.7 kB). View file
|
|
fake-face-detection/fake_face_detection/data/collator.py
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
import torch
|
3 |
+
import numpy as np
|
4 |
+
|
5 |
+
def fake_face_collator(batch):
|
6 |
+
"""The data collator for training vision transformer models on fake and real face dataset
|
7 |
+
|
8 |
+
Args:
|
9 |
+
batch (list): A dictionary containing the pixel values and the labels
|
10 |
+
|
11 |
+
Returns:
|
12 |
+
dict: The final dictionary
|
13 |
+
"""
|
14 |
+
|
15 |
+
new_batch = {
|
16 |
+
'pixel_values': [],
|
17 |
+
'labels': []
|
18 |
+
}
|
19 |
+
|
20 |
+
for x in batch:
|
21 |
+
|
22 |
+
pixel_values = torch.from_numpy(x['pixel_values'][0]) if isinstance(x['pixel_values'][0], np.ndarray) \
|
23 |
+
else x['pixel_values'][0]
|
24 |
+
|
25 |
+
new_batch['pixel_values'].append(pixel_values)
|
26 |
+
|
27 |
+
new_batch['labels'].append(torch.tensor(x['labels']))
|
28 |
+
|
29 |
+
new_batch['pixel_values'] = torch.stack(new_batch['pixel_values'])
|
30 |
+
|
31 |
+
new_batch['labels'] = torch.stack(new_batch['labels'])
|
32 |
+
|
33 |
+
return new_batch
|
fake-face-detection/fake_face_detection/data/fake_face_dataset.py
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from fake_face_detection.utils.compute_weights import compute_weights
|
3 |
+
from torch.utils.data import Dataset
|
4 |
+
from PIL import Image
|
5 |
+
from glob import glob
|
6 |
+
import torch
|
7 |
+
import os
|
8 |
+
|
9 |
+
class FakeFaceDetectionDataset(Dataset):
|
10 |
+
|
11 |
+
def __init__(self, fake_path: str, real_path: str, id_map: dict, transformer, **transformer_kwargs):
|
12 |
+
|
13 |
+
# let us load the images
|
14 |
+
self.fake_images = glob(os.path.join(fake_path, "*"))
|
15 |
+
|
16 |
+
self.real_images = glob(os.path.join(real_path, "*"))
|
17 |
+
|
18 |
+
self.images = self.fake_images + self.real_images
|
19 |
+
|
20 |
+
# let us recuperate the labels
|
21 |
+
self.fake_labels = [int(id_map['fake'])] * len(self.fake_images)
|
22 |
+
|
23 |
+
self.real_labels = [int(id_map['real'])] * len(self.real_images)
|
24 |
+
|
25 |
+
self.labels = self.fake_labels + self.real_labels
|
26 |
+
|
27 |
+
# let us recuperate the weights
|
28 |
+
self.weights = torch.from_numpy(compute_weights(self.labels))
|
29 |
+
|
30 |
+
# let us recuperate the transformer
|
31 |
+
self.transformer = transformer
|
32 |
+
|
33 |
+
# let us recuperate the length
|
34 |
+
self.length = len(self.labels)
|
35 |
+
|
36 |
+
# let us recuperate the transformer kwargs
|
37 |
+
self.transformer_kwargs = transformer_kwargs
|
38 |
+
|
39 |
+
def __getitem__(self, index):
|
40 |
+
|
41 |
+
# let us recuperate an image
|
42 |
+
image = self.images[index]
|
43 |
+
|
44 |
+
with Image.open(image) as img:
|
45 |
+
|
46 |
+
# let us recuperate a label
|
47 |
+
label = self.labels[index]
|
48 |
+
|
49 |
+
# let us add a transformation on the images
|
50 |
+
if self.transformer:
|
51 |
+
|
52 |
+
image = self.transformer(img, **self.transformer_kwargs)
|
53 |
+
|
54 |
+
# let us add the label inside the obtained dictionary
|
55 |
+
image['labels'] = label
|
56 |
+
|
57 |
+
return image
|
58 |
+
|
59 |
+
def __len__(self):
|
60 |
+
|
61 |
+
return self.length
|
62 |
+
|
fake-face-detection/fake_face_detection/metrics/__init__.py
ADDED
File without changes
|
fake-face-detection/fake_face_detection/metrics/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (270 Bytes). View file
|
|
fake-face-detection/fake_face_detection/metrics/__pycache__/compute_metrics.cpython-310.pyc
ADDED
Binary file (825 Bytes). View file
|
|
fake-face-detection/fake_face_detection/metrics/__pycache__/make_predictions.cpython-310.pyc
ADDED
Binary file (3.35 kB). View file
|
|
fake-face-detection/fake_face_detection/metrics/compute_metrics.py
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
import numpy as np
|
3 |
+
import evaluate
|
4 |
+
|
5 |
+
metrics = {
|
6 |
+
'f1': evaluate.load('f1'),
|
7 |
+
'accuracy': evaluate.load('accuracy'),
|
8 |
+
'roc_auc': evaluate.load('roc_auc', 'multiclass')
|
9 |
+
}
|
10 |
+
|
11 |
+
def compute_metrics(p): # some part was got from https://huggingface.co/blog/fine-tune-vit
|
12 |
+
|
13 |
+
predictions, label_ids = p
|
14 |
+
|
15 |
+
metric = metrics['accuracy'].compute(predictions = np.argmax(predictions, axis = 1), references=label_ids)
|
16 |
+
|
17 |
+
f1_score = metrics['f1'].compute(predictions=np.argmax(predictions, axis = 1), references=label_ids)
|
18 |
+
|
19 |
+
metric.update(f1_score)
|
20 |
+
|
21 |
+
try:
|
22 |
+
|
23 |
+
auc = metrics['roc_auc'].compute(prediction_scores=predictions, references=label_ids)
|
24 |
+
|
25 |
+
metric.update(auc)
|
26 |
+
|
27 |
+
except:
|
28 |
+
|
29 |
+
pass
|
30 |
+
|
31 |
+
return metric
|
32 |
+
|
33 |
+
|
fake-face-detection/fake_face_detection/metrics/make_predictions.py
ADDED
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from fake_face_detection.data.fake_face_dataset import FakeFaceDetectionDataset
|
3 |
+
from fake_face_detection.metrics.compute_metrics import compute_metrics
|
4 |
+
from torch.utils.tensorboard import SummaryWriter
|
5 |
+
from PIL.JpegImagePlugin import JpegImageFile
|
6 |
+
from torch.utils.data import DataLoader
|
7 |
+
from torch.nn import functional as F
|
8 |
+
from torchvision import transforms
|
9 |
+
import matplotlib.pyplot as plt
|
10 |
+
from glob import glob
|
11 |
+
from PIL import Image
|
12 |
+
from typing import *
|
13 |
+
import pandas as pd
|
14 |
+
from math import *
|
15 |
+
import numpy as np
|
16 |
+
import torch
|
17 |
+
import os
|
18 |
+
|
19 |
+
def get_attention(image: Union[str, JpegImageFile], attention: torch.Tensor, size: tuple, patch_size: tuple):
|
20 |
+
|
21 |
+
# recuperate the image as a numpy array
|
22 |
+
if isinstance(image, str):
|
23 |
+
|
24 |
+
with Image.open(image) as img:
|
25 |
+
|
26 |
+
img = np.array(transforms.Resize(size)(img))
|
27 |
+
|
28 |
+
else:
|
29 |
+
|
30 |
+
img = np.array(transforms.Resize(size)(image))
|
31 |
+
|
32 |
+
# recuperate the attention provided by the last patch (notice that we eliminate 1 because of the +1 added by the convolutation layer)
|
33 |
+
attention = attention[:, -1, 1:]
|
34 |
+
|
35 |
+
# calculate the mean attention
|
36 |
+
attention = attention.mean(axis = 0)
|
37 |
+
|
38 |
+
# let us reshape transform the image to a numpy array
|
39 |
+
|
40 |
+
# calculate the scale factor
|
41 |
+
scale_factor = size[0] * size[1] / (patch_size[0] * patch_size[1])
|
42 |
+
|
43 |
+
# rescale the attention with the nearest scaler
|
44 |
+
attention = F.interpolate(attention.reshape(1, 1, -1), scale_factor=scale_factor,
|
45 |
+
mode='nearest')
|
46 |
+
|
47 |
+
# let us reshape the attention to the right size
|
48 |
+
attention = attention.reshape(size[0], size[1], 1)
|
49 |
+
|
50 |
+
# recuperate the result
|
51 |
+
attention_image = img / 255 * attention.numpy()
|
52 |
+
|
53 |
+
return attention_image
|
54 |
+
|
55 |
+
|
56 |
+
def make_predictions(test_dataset: FakeFaceDetectionDataset,
|
57 |
+
model,
|
58 |
+
log_dir: str = "fake_face_logs",
|
59 |
+
tag: str = "Attentions",
|
60 |
+
batch_size: int = 3,
|
61 |
+
size: tuple = (224, 224),
|
62 |
+
patch_size: tuple = (14, 14),
|
63 |
+
figsize: tuple = (24, 24)):
|
64 |
+
|
65 |
+
with torch.no_grad():
|
66 |
+
|
67 |
+
_ = model.eval()
|
68 |
+
|
69 |
+
# initialize the logger
|
70 |
+
writer = SummaryWriter(os.path.join(log_dir, "attentions"))
|
71 |
+
|
72 |
+
# let us recuperate the images and labels
|
73 |
+
images = test_dataset.images
|
74 |
+
|
75 |
+
labels = test_dataset.labels
|
76 |
+
|
77 |
+
# let us initialize the predictions
|
78 |
+
predictions = {'attentions': [], 'predictions': [], 'true_labels': labels, 'predicted_labels': []}
|
79 |
+
|
80 |
+
# let us initialize the dataloader
|
81 |
+
test_dataloader = DataLoader(test_dataset, batch_size=batch_size)
|
82 |
+
|
83 |
+
# get the loss
|
84 |
+
loss = 0
|
85 |
+
|
86 |
+
for data in test_dataloader:
|
87 |
+
|
88 |
+
# recuperate the pixel values
|
89 |
+
pixel_values = data['pixel_values'][0].cuda()
|
90 |
+
|
91 |
+
# recuperate the labels
|
92 |
+
labels_ = data['labels'].cuda()
|
93 |
+
|
94 |
+
# # recuperate the outputs
|
95 |
+
outputs = model(pixel_values, labels = labels_, output_attentions = True)
|
96 |
+
|
97 |
+
# recuperate the predictions
|
98 |
+
predictions['predictions'].append(torch.softmax(outputs.logits.detach().cpu(), axis = -1).numpy())
|
99 |
+
|
100 |
+
# recuperate the attentions of the last encoder layer
|
101 |
+
predictions['attentions'].append(outputs.attentions[-1].detach().cpu())
|
102 |
+
|
103 |
+
# add the loss
|
104 |
+
loss += outputs.loss.detach().cpu().item()
|
105 |
+
|
106 |
+
predictions['predictions'] = np.concatenate(predictions['predictions'], axis = 0)
|
107 |
+
|
108 |
+
predictions['attentions'] = torch.concatenate(predictions['attentions'], axis = 0)
|
109 |
+
|
110 |
+
predictions['predicted_labels'] = np.argmax(predictions['predictions'], axis = -1).tolist()
|
111 |
+
|
112 |
+
# let us calculate the metrics
|
113 |
+
metrics = compute_metrics((predictions['predictions'], np.array(predictions['true_labels'])))
|
114 |
+
metrics['loss'] = loss / len(test_dataloader)
|
115 |
+
|
116 |
+
# for each image we will visualize his attention
|
117 |
+
nrows = ceil(sqrt(len(images)))
|
118 |
+
|
119 |
+
fig, axes = plt.subplots(nrows=nrows, ncols=nrows, figsize = figsize)
|
120 |
+
|
121 |
+
axes = axes.flat
|
122 |
+
|
123 |
+
for i in range(len(images)):
|
124 |
+
|
125 |
+
attention_image = get_attention(images[i], predictions['attentions'][i], size, patch_size)
|
126 |
+
|
127 |
+
axes[i].imshow(attention_image)
|
128 |
+
|
129 |
+
axes[i].set_title(f'Image {i + 1}')
|
130 |
+
|
131 |
+
axes[i].axis('off')
|
132 |
+
|
133 |
+
fig.tight_layout()
|
134 |
+
|
135 |
+
[fig.delaxes(axes[i]) for i in range(len(images), nrows * nrows)]
|
136 |
+
|
137 |
+
writer.add_figure(tag, fig)
|
138 |
+
|
139 |
+
# let us remove the predictions and the attentions
|
140 |
+
del predictions['predictions']
|
141 |
+
del predictions['attentions']
|
142 |
+
|
143 |
+
# let us recuperate the metrics and the predictions
|
144 |
+
return pd.DataFrame(predictions), metrics
|
145 |
+
|
146 |
+
|
147 |
+
|
fake-face-detection/fake_face_detection/optimization/__init__.py
ADDED
File without changes
|
fake-face-detection/fake_face_detection/optimization/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (275 Bytes). View file
|
|
fake-face-detection/fake_face_detection/optimization/__pycache__/bayesian_optimization.cpython-310.pyc
ADDED
Binary file (2.78 kB). View file
|
|
fake-face-detection/fake_face_detection/optimization/__pycache__/fake_face_bayesian_optimization.cpython-310.pyc
ADDED
Binary file (4.49 kB). View file
|
|
fake-face-detection/fake_face_detection/optimization/bayesian_optimization.py
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fake_face_detection.utils.generation import PI_generate_sample as generate_sample
|
2 |
+
from fake_face_detection.utils.acquisitions import PI_acquisition as acquisition
|
3 |
+
from fake_face_detection.utils.sampling import get_random_samples
|
4 |
+
from sklearn.gaussian_process import GaussianProcessRegressor
|
5 |
+
from typing import *
|
6 |
+
import pandas as pd
|
7 |
+
import numpy as np
|
8 |
+
|
9 |
+
class SimpleBayesianOptimization:
|
10 |
+
|
11 |
+
def __init__(self, objective: Callable, search_spaces: dict, maximize: bool = True):
|
12 |
+
|
13 |
+
# recuperate the optimization strategy
|
14 |
+
self.maximize = maximize
|
15 |
+
|
16 |
+
# recuperate random sample
|
17 |
+
sample = get_random_samples(search_spaces)
|
18 |
+
|
19 |
+
# initialize the search spaces
|
20 |
+
self.search_spaces = search_spaces
|
21 |
+
|
22 |
+
# initialize the objective function
|
23 |
+
self.objective = objective
|
24 |
+
|
25 |
+
# calculate the first score
|
26 |
+
score = objective(sample)
|
27 |
+
|
28 |
+
# initialize the model
|
29 |
+
self.model = GaussianProcessRegressor()
|
30 |
+
|
31 |
+
# initialize the input data
|
32 |
+
self.data = [list(sample.values())]
|
33 |
+
|
34 |
+
# initialize the scores
|
35 |
+
self.scores = [[score]]
|
36 |
+
|
37 |
+
# fit the model with the input data and the target
|
38 |
+
self.model.fit(self.data, self.scores)
|
39 |
+
|
40 |
+
def optimize(self, n_trials: int = 50, n_tests: int = 100):
|
41 |
+
"""Finding the best hyperparameters with the Bayesian Optimization
|
42 |
+
|
43 |
+
Args:
|
44 |
+
n_trials (int, optional): The number of trials. Defaults to 50.
|
45 |
+
n_tests (int, optional): The number of random samples to test for each trial. Defaults to 100.
|
46 |
+
"""
|
47 |
+
# let us make multiple trials in order to find the best params
|
48 |
+
for _ in range(n_trials):
|
49 |
+
|
50 |
+
# let us generate new samples with the acquisition and the surrogate functions
|
51 |
+
new_sample = generate_sample(self.data, self.model, self.search_spaces, n_tests, maximize = self.maximize)
|
52 |
+
sample = {key: new_sample[i] for i, key in enumerate(self.search_spaces)}
|
53 |
+
|
54 |
+
# let us recuperate a new score from the new sample
|
55 |
+
new_score = self.objective(sample)
|
56 |
+
|
57 |
+
# let us add the new sample, target and score to their lists
|
58 |
+
self.data.append(new_sample)
|
59 |
+
|
60 |
+
self.scores.append([new_score])
|
61 |
+
|
62 |
+
# let us train again the model
|
63 |
+
self.model.fit(self.data, self.scores)
|
64 |
+
|
65 |
+
def get_results(self):
|
66 |
+
"""Recuperate the generated samples and the scores
|
67 |
+
|
68 |
+
Returns:
|
69 |
+
pd.DataFrame: A data frame containing the results
|
70 |
+
"""
|
71 |
+
# let us return the results as a data frame
|
72 |
+
data = {key: np.array(self.data, dtype = object)[:, i] for i, key in enumerate(self.search_spaces)}
|
73 |
+
|
74 |
+
data.update({'score': np.array(self.scores)[:, 0]})
|
75 |
+
|
76 |
+
return pd.DataFrame(data)
|
77 |
+
|
78 |
+
|
fake-face-detection/fake_face_detection/optimization/fake_face_bayesian_optimization.py
ADDED
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fake_face_detection.utils.generation import PI_generate_sample as generate_sample
|
2 |
+
from fake_face_detection.utils.acquisitions import PI_acquisition as acquisition
|
3 |
+
from fake_face_detection.utils.sampling import get_random_samples
|
4 |
+
from sklearn.gaussian_process import GaussianProcessRegressor
|
5 |
+
from functools import partial
|
6 |
+
from typing import *
|
7 |
+
import pandas as pd
|
8 |
+
import numpy as np
|
9 |
+
import string
|
10 |
+
import random
|
11 |
+
import pickle
|
12 |
+
import os
|
13 |
+
|
14 |
+
letters = string.ascii_letters + string.digits
|
15 |
+
|
16 |
+
class SimpleBayesianOptimizationForFakeReal:
|
17 |
+
|
18 |
+
def __init__(self, objective: Callable, search_spaces: dict, maximize: bool = True, random_kwargs: dict = {}, kwargs: dict = {}, checkpoint: str = "data/trials/checkpoint.txt"):
|
19 |
+
|
20 |
+
# recuperate the optimization strategy
|
21 |
+
self.maximize = maximize
|
22 |
+
|
23 |
+
# checkpoint where the data and score will be saved
|
24 |
+
self.checkpoint = checkpoint
|
25 |
+
|
26 |
+
# initialize the search spaces
|
27 |
+
self.search_spaces = search_spaces
|
28 |
+
|
29 |
+
# recuperate the random kwargs
|
30 |
+
self.random_kwargs = random_kwargs
|
31 |
+
|
32 |
+
# initialize the objective function
|
33 |
+
self.objective = objective
|
34 |
+
|
35 |
+
# initialize the kwargs
|
36 |
+
self.kwargs = kwargs
|
37 |
+
|
38 |
+
# initialize the model
|
39 |
+
self.model = GaussianProcessRegressor()
|
40 |
+
|
41 |
+
# initialize the random kwargs with a random values
|
42 |
+
random_kwargs = {key: value + ''.join(random.choice(letters) for i in range(7)) for key, value in self.random_kwargs.items()}
|
43 |
+
|
44 |
+
# add random kwargs to the kwargs
|
45 |
+
self.kwargs.update(random_kwargs)
|
46 |
+
|
47 |
+
# recuperate random sample
|
48 |
+
config = get_random_samples(search_spaces)
|
49 |
+
|
50 |
+
if os.path.exists(self.checkpoint):
|
51 |
+
|
52 |
+
with open(self.checkpoint, 'rb') as f:
|
53 |
+
|
54 |
+
pickler = pickle.Unpickler(f)
|
55 |
+
|
56 |
+
self.checkpoint = pickler.load()
|
57 |
+
|
58 |
+
self.data = self.checkpoint['data']
|
59 |
+
|
60 |
+
self.scores = self.checkpoint['scores']
|
61 |
+
|
62 |
+
self.model = self.checkpoint['model']
|
63 |
+
|
64 |
+
self.current_trial = self.checkpoint['trial']
|
65 |
+
|
66 |
+
print(f"Checkpoint loaded at trial {self.current_trial}")
|
67 |
+
|
68 |
+
else:
|
69 |
+
|
70 |
+
# add config to kwargs
|
71 |
+
self.kwargs['config'] = config
|
72 |
+
|
73 |
+
# calculate the first score
|
74 |
+
score = self.objective(**self.kwargs)
|
75 |
+
|
76 |
+
# initialize the input data
|
77 |
+
self.data = [list(config.values())]
|
78 |
+
|
79 |
+
# initialize the scores
|
80 |
+
self.scores = [[score]]
|
81 |
+
|
82 |
+
# fit the model with the input data and the target
|
83 |
+
self.model.fit(self.data, self.scores)
|
84 |
+
|
85 |
+
# initialize the number of trials to zero
|
86 |
+
self.current_trial = 0
|
87 |
+
|
88 |
+
with open(self.checkpoint, 'wb') as f:
|
89 |
+
|
90 |
+
pickler = pickle.Pickler(f)
|
91 |
+
|
92 |
+
checkpoint = {
|
93 |
+
'data': self.data,
|
94 |
+
'scores': self.scores,
|
95 |
+
'model': self.model,
|
96 |
+
'trial': self.current_trial
|
97 |
+
}
|
98 |
+
|
99 |
+
pickler.dump(checkpoint)
|
100 |
+
|
101 |
+
def optimize(self, n_trials: int = 50, n_tests: int = 100):
|
102 |
+
"""Finding the best hyperparameters with the Bayesian Optimization
|
103 |
+
|
104 |
+
Args:
|
105 |
+
n_trials (int, optional): The number of trials. Defaults to 50.
|
106 |
+
n_tests (int, optional): The number of random samples to test for each trial. Defaults to 100.
|
107 |
+
"""
|
108 |
+
|
109 |
+
# let us make multiple trials in order to find the best params
|
110 |
+
for trial in range(self.current_trial + 1, self.current_trial + n_trials + 1):
|
111 |
+
|
112 |
+
# let us generate new samples with the acquisition and the surrogate functions
|
113 |
+
new_sample = generate_sample(self.data, self.model, self.search_spaces, n_tests, maximize = self.maximize)
|
114 |
+
config = {key: new_sample[i] for i, key in enumerate(self.search_spaces)}
|
115 |
+
|
116 |
+
# initialize the random kwargs with a random values
|
117 |
+
random_kwargs = {key: value + ''.join(random.choice(letters) for i in range(7)) for key, value in self.random_kwargs.items()}
|
118 |
+
|
119 |
+
# add random kwargs to the kwargs
|
120 |
+
self.kwargs.update(random_kwargs)
|
121 |
+
|
122 |
+
# add config to kwargs
|
123 |
+
self.kwargs['config'] = config
|
124 |
+
|
125 |
+
# calculate the first score
|
126 |
+
new_score = self.objective(**self.kwargs)
|
127 |
+
|
128 |
+
# let us add the new sample, target and score to their lists
|
129 |
+
self.data.append(new_sample)
|
130 |
+
|
131 |
+
self.scores.append([new_score])
|
132 |
+
|
133 |
+
# let us train again the model
|
134 |
+
self.model.fit(self.data, self.scores)
|
135 |
+
|
136 |
+
# recuperate the current trial
|
137 |
+
self.current_trial = trial
|
138 |
+
|
139 |
+
with open(self.checkpoint, 'wb') as f:
|
140 |
+
|
141 |
+
pickler = pickle.Pickler(f)
|
142 |
+
|
143 |
+
checkpoint = {
|
144 |
+
'data': self.data,
|
145 |
+
'scores': self.scores,
|
146 |
+
'model': self.model,
|
147 |
+
'trial': self.current_trial
|
148 |
+
}
|
149 |
+
|
150 |
+
pickler.dump(checkpoint)
|
151 |
+
|
152 |
+
def get_results(self):
|
153 |
+
"""Recuperate the generated samples and the scores
|
154 |
+
|
155 |
+
Returns:
|
156 |
+
pd.DataFrame: A data frame containing the results
|
157 |
+
"""
|
158 |
+
# let us return the results as a data frame
|
159 |
+
data = {key: np.array(self.data, dtype = object)[:, i] for i, key in enumerate(self.search_spaces)}
|
160 |
+
|
161 |
+
data.update({'score': np.array(self.scores)[:, 0]})
|
162 |
+
|
163 |
+
return pd.DataFrame(data)
|
164 |
+
|
165 |
+
|
fake-face-detection/fake_face_detection/trainers/__init__.py
ADDED
File without changes
|
fake-face-detection/fake_face_detection/trainers/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (271 Bytes). View file
|
|
fake-face-detection/fake_face_detection/trainers/__pycache__/custom_trainer.cpython-310.pyc
ADDED
Binary file (1.11 kB). View file
|
|
fake-face-detection/fake_face_detection/trainers/custom_trainer.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from transformers import Trainer
|
3 |
+
import torch
|
4 |
+
|
5 |
+
def get_custom_trainer(weights: torch.Tensor):
|
6 |
+
|
7 |
+
class CustomTrainer(Trainer): # got from https://huggingface.co/docs/transformers/main_classes/trainer
|
8 |
+
|
9 |
+
def compute_loss(self, model, inputs, return_outputs=False):
|
10 |
+
|
11 |
+
# recuperate labels
|
12 |
+
labels = inputs.get("labels")
|
13 |
+
|
14 |
+
# forward pass
|
15 |
+
outputs = model(**inputs)
|
16 |
+
|
17 |
+
# recuperate logits
|
18 |
+
logits = outputs.get("logits")
|
19 |
+
|
20 |
+
# compute custom loss (passing the weights)
|
21 |
+
loss_fct = nn.CrossEntropyLoss(weight=weights)
|
22 |
+
|
23 |
+
loss = loss_fct(logits.view(-1, self.model.config.num_labels), labels.view(-1))
|
24 |
+
|
25 |
+
return (loss, outputs) if return_outputs else loss
|
26 |
+
|
27 |
+
return CustomTrainer
|
fake-face-detection/fake_face_detection/trainers/custom_trainer_v1.txt
ADDED
File without changes
|
fake-face-detection/fake_face_detection/trainers/search_train.py
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from fake_face_detection.metrics.compute_metrics import compute_metrics
|
3 |
+
from fake_face_detection.data.collator import fake_face_collator
|
4 |
+
from transformers import Trainer, TrainingArguments
|
5 |
+
from torch.utils.tensorboard import SummaryWriter
|
6 |
+
from torch import nn
|
7 |
+
from typing import *
|
8 |
+
import numpy as np
|
9 |
+
import json
|
10 |
+
import os
|
11 |
+
|
12 |
+
def train(epochs: int, output_dir: str, config: dict, model: nn.Module, trainer, get_datasets: Callable, log_dir: str = "fake_face_logs", metric = 'accuracy'):
|
13 |
+
|
14 |
+
print("------------------------- Beginning of training")
|
15 |
+
|
16 |
+
# reformat the config integer type
|
17 |
+
for key, value in config.items():
|
18 |
+
|
19 |
+
if isinstance(value, np.int32): config[key] = int(value)
|
20 |
+
|
21 |
+
pretty = json.dumps(config, indent = 4)
|
22 |
+
|
23 |
+
print(f"Current Config: \n {pretty}")
|
24 |
+
|
25 |
+
# recuperate the dataset
|
26 |
+
train_dataset, test_dataset = get_datasets(config['h_flip_p'], config['v_flip_p'], config['gray_scale_p'], config['rotation'])
|
27 |
+
|
28 |
+
# initialize the arguments of the training
|
29 |
+
training_args = TrainingArguments(output_dir,
|
30 |
+
per_device_train_batch_size=config['batch_size'],
|
31 |
+
evaluation_strategy='steps',
|
32 |
+
save_strategy='steps',
|
33 |
+
logging_strategy='steps',
|
34 |
+
num_train_epochs=epochs,
|
35 |
+
fp16=True,
|
36 |
+
save_total_limit=2,
|
37 |
+
remove_unused_columns=True,
|
38 |
+
push_to_hub=False,
|
39 |
+
logging_dir=os.path.join(log_dir, os.path.basename(output_dir)),
|
40 |
+
load_best_model_at_end=True,
|
41 |
+
learning_rate=config['lr'],
|
42 |
+
weight_decay=config['weight_decay']
|
43 |
+
)
|
44 |
+
|
45 |
+
# train the model
|
46 |
+
trainer_ = trainer(
|
47 |
+
model = model,
|
48 |
+
args = training_args,
|
49 |
+
data_collator = fake_face_collator,
|
50 |
+
compute_metrics = compute_metrics,
|
51 |
+
train_dataset = train_dataset,
|
52 |
+
eval_dataset = test_dataset
|
53 |
+
)
|
54 |
+
|
55 |
+
# train the model
|
56 |
+
trainer_.train()
|
57 |
+
|
58 |
+
# evaluate the model and recuperate metrics
|
59 |
+
metrics = trainer_.evaluate(test_dataset)
|
60 |
+
|
61 |
+
# add metrics and config to the hyperparameter panel of tensorboard
|
62 |
+
with SummaryWriter(os.path.join(log_dir, 'hparams')) as logger:
|
63 |
+
|
64 |
+
logger.add_hparams(
|
65 |
+
config, metrics
|
66 |
+
)
|
67 |
+
|
68 |
+
print(metrics)
|
69 |
+
|
70 |
+
print("------------------------- End of training")
|
71 |
+
# recuperate the metric to evaluate
|
72 |
+
return metrics[f'eval_{metric}']
|
73 |
+
|
fake-face-detection/fake_face_detection/utils/__pycache__/acquisitions.cpython-310.pyc
ADDED
Binary file (1.21 kB). View file
|
|
fake-face-detection/fake_face_detection/utils/__pycache__/compute_weights.cpython-310.pyc
ADDED
Binary file (815 Bytes). View file
|
|
fake-face-detection/fake_face_detection/utils/__pycache__/generation.cpython-310.pyc
ADDED
Binary file (1.55 kB). View file
|
|
fake-face-detection/fake_face_detection/utils/__pycache__/sampling.cpython-310.pyc
ADDED
Binary file (1.99 kB). View file
|
|
fake-face-detection/fake_face_detection/utils/acquisitions.py
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sklearn.gaussian_process import GaussianProcessRegressor
|
2 |
+
from scipy.stats import norm
|
3 |
+
from typing import *
|
4 |
+
|
5 |
+
def PI_acquisition(X: List, X_prime: List, model: GaussianProcessRegressor, maximize: bool = True):
|
6 |
+
"""Acquisition function for bayesian optimization using probability of improvement
|
7 |
+
|
8 |
+
Args:
|
9 |
+
X (List): A list containing the input data
|
10 |
+
X_prime (List): A list containing the generate samples
|
11 |
+
model (GaussianProcessRegressor): The gaussian model to use
|
12 |
+
maximize (bool, optional): A boolean value indicating the optimization objective. Defaults to True.
|
13 |
+
|
14 |
+
Returns:
|
15 |
+
List: A list containing the probabilities
|
16 |
+
"""
|
17 |
+
|
18 |
+
# let us predict the means for the input data
|
19 |
+
mu = model.predict(X)
|
20 |
+
|
21 |
+
# let us calculate the means and standard deviation for the random samples
|
22 |
+
mu_e, std_e = model.predict(X_prime, return_std=True)
|
23 |
+
|
24 |
+
if not maximize:
|
25 |
+
|
26 |
+
mu = -mu
|
27 |
+
|
28 |
+
mu_e = -mu_e
|
29 |
+
|
30 |
+
# let us take the best mean
|
31 |
+
mu_best = max(mu)
|
32 |
+
|
33 |
+
# let us calculate the probability of improvement
|
34 |
+
probs = norm.cdf((mu_e - mu_best) / std_e)
|
35 |
+
|
36 |
+
return probs
|
fake-face-detection/fake_face_detection/utils/compute_weights.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sklearn.utils as skl
|
2 |
+
from typing import *
|
3 |
+
import numpy as np
|
4 |
+
|
5 |
+
def compute_weights(samples: List[int]):
|
6 |
+
"""Compute the weights with the 'balanced' method
|
7 |
+
|
8 |
+
Args:
|
9 |
+
samples (List[int]): The samples: A list of integers
|
10 |
+
|
11 |
+
Returns:
|
12 |
+
numpy.ndarray: A array containing the weights
|
13 |
+
"""
|
14 |
+
|
15 |
+
# get unique classes
|
16 |
+
classes = np.unique(samples)
|
17 |
+
|
18 |
+
# calculate the weights with the balanced method
|
19 |
+
weights = skl.class_weight.compute_class_weight('balanced', classes=classes, y = samples)
|
20 |
+
|
21 |
+
return weights
|
fake-face-detection/fake_face_detection/utils/display_pil.py
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from PIL.JpegImagePlugin import JpegImageFile
|
2 |
+
from PIL import ImageDraw
|
3 |
+
from PIL import Image
|
4 |
+
from typing import *
|
5 |
+
|
6 |
+
def display(images: List[JpegImageFile], labels: List[str], w: int = 300, h: int = 200, left_color: str = "white", right_color: str = "white"):
|
7 |
+
"""Display a dual image
|
8 |
+
|
9 |
+
Args:
|
10 |
+
images (List[JpegImageFile]): A list containing two images
|
11 |
+
labels (List[str]): The labels of the images
|
12 |
+
w (int, optional): The width. Defaults to 300.
|
13 |
+
h (int, optional): The height. Defaults to 200.
|
14 |
+
left_color (str, optional): The color of left label. Defaults to "white".
|
15 |
+
right_color (str, optional): The color of the right label. Defaults to "white".
|
16 |
+
|
17 |
+
Returns:
|
18 |
+
PIL.Image: A pillow image
|
19 |
+
"""
|
20 |
+
|
21 |
+
# define a grid
|
22 |
+
grid = Image.new('RGB', size=(w, h))
|
23 |
+
|
24 |
+
# draw the grid
|
25 |
+
draw = ImageDraw.Draw(grid, mode='RGB')
|
26 |
+
|
27 |
+
# define the second box
|
28 |
+
box = (w // 2, 0)
|
29 |
+
|
30 |
+
# define the size of the images
|
31 |
+
size = (w // 2, h)
|
32 |
+
|
33 |
+
# add images to the grid
|
34 |
+
grid.paste(images[0].resize(size))
|
35 |
+
|
36 |
+
grid.paste(images[1].resize(size), box = box)
|
37 |
+
|
38 |
+
# draw labels
|
39 |
+
draw.text((0, 0), labels[0], fill=left_color)
|
40 |
+
|
41 |
+
draw.text(box, labels[1], fill=right_color)
|
42 |
+
|
43 |
+
return grid
|
fake-face-detection/fake_face_detection/utils/downscale_image.py
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from PIL.JpegImagePlugin import JpegImageFile
|
3 |
+
from PIL import Image
|
4 |
+
from math import *
|
5 |
+
import numpy as np
|
6 |
+
import itertools
|
7 |
+
|
8 |
+
def downscale_image(image: JpegImageFile, size: tuple = (224, 224)):
|
9 |
+
|
10 |
+
assert image.size[0] % size[0] == 0 and image.size[1] % size[1] == 0
|
11 |
+
|
12 |
+
# get box size
|
13 |
+
height, width = int(image.size[0] / size[0]), int(image.size[1] / size[1])
|
14 |
+
|
15 |
+
print(f"Height and width of each box: {(height, width)}")
|
16 |
+
|
17 |
+
# we will concatenate the patches over the height axis (axis 0)
|
18 |
+
patches = []
|
19 |
+
|
20 |
+
for j in range(0, size[1] * width, width):
|
21 |
+
|
22 |
+
# we must recuperate each width division in order to concatenate the results (on axis 1)
|
23 |
+
h_div = []
|
24 |
+
|
25 |
+
for i in range(0, size[0] * height, height):
|
26 |
+
|
27 |
+
box = (j, i, j + width, i + height)
|
28 |
+
|
29 |
+
current_box = image.crop(box)
|
30 |
+
|
31 |
+
# let us convert the box to a numpy array and calculate the mean
|
32 |
+
current_box = np.array(current_box).mean(axis = (0, 1))[np.newaxis, np.newaxis, :]
|
33 |
+
|
34 |
+
# add to h_div
|
35 |
+
h_div.append(current_box)
|
36 |
+
|
37 |
+
# concatenate over width axis
|
38 |
+
patches.append(np.concatenate(h_div, axis = 0))
|
39 |
+
|
40 |
+
# concatenate over the height axis and transform to a pillow image
|
41 |
+
image = Image.fromarray(np.uint8(np.concatenate(patches, axis = 1)))
|
42 |
+
|
43 |
+
return image
|
44 |
+
|
45 |
+
|
46 |
+
|
fake-face-detection/fake_face_detection/utils/generation.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fake_face_detection.utils.acquisitions import PI_acquisition
|
2 |
+
from fake_face_detection.utils.sampling import get_random_samples
|
3 |
+
from sklearn.gaussian_process import GaussianProcessRegressor
|
4 |
+
from typing import *
|
5 |
+
import numpy as np
|
6 |
+
|
7 |
+
def PI_generate_sample(X: Iterable, model: GaussianProcessRegressor, search_spaces: dict, n_tests: int = 100, maximize: bool = True):
|
8 |
+
"""Generate new samples with the probability of improvement
|
9 |
+
|
10 |
+
Args:
|
11 |
+
X (Iterable): The list of input data
|
12 |
+
model (GaussianProcessRegressor): The model to train
|
13 |
+
search_spaces (dict): The search spaces
|
14 |
+
n_tests (int, optional): The number of random samples to test. Defaults to 100.
|
15 |
+
maximize (bool, optional): The optimization strategy. If maximize == True -> maximize, else -> minimize. Defaults to True.
|
16 |
+
|
17 |
+
Returns:
|
18 |
+
List: The new sample
|
19 |
+
"""
|
20 |
+
|
21 |
+
# let us create random samples
|
22 |
+
X_prime = [list(get_random_samples(search_spaces).values()) for i in range(n_tests)]
|
23 |
+
|
24 |
+
# let us recuperate the probabilities from the acquisition function
|
25 |
+
probs = PI_acquisition(X, X_prime, model, maximize = maximize)
|
26 |
+
|
27 |
+
# let us return the best sample
|
28 |
+
return X_prime[np.argmax(probs)]
|
fake-face-detection/fake_face_detection/utils/get_patches.py
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
from PIL.JpegImagePlugin import JpegImageFile
|
3 |
+
from math import *
|
4 |
+
import itertools
|
5 |
+
|
6 |
+
def get_patches(image: JpegImageFile, n_patches: int):
|
7 |
+
|
8 |
+
# get height and width of the image
|
9 |
+
height, width = image.size
|
10 |
+
|
11 |
+
# let us calculate the number of divisions to make to the width and height of the image
|
12 |
+
n_patch = int(sqrt(n_patches))
|
13 |
+
|
14 |
+
patch_h = int(height / n_patch) # notice that the height must be divisible by the number of divisions
|
15 |
+
|
16 |
+
patch_w = int(width / n_patch) # notice that the width must be divisible by the number of divisions
|
17 |
+
|
18 |
+
print(f"Height and width of each patch: {(patch_h, patch_w)}")
|
19 |
+
|
20 |
+
# we will find the first coordinates of the boxes with product function of itertools
|
21 |
+
first_coordinates = list(itertools.product(range(0, patch_h * n_patch, patch_h),
|
22 |
+
range(0, patch_w * n_patch, patch_w)))
|
23 |
+
|
24 |
+
patches = []
|
25 |
+
|
26 |
+
for pos1, pos2 in first_coordinates:
|
27 |
+
|
28 |
+
box = (pos2, pos1, pos2 + patch_w, pos1 + patch_h)
|
29 |
+
|
30 |
+
patches.append(image.crop(box))
|
31 |
+
|
32 |
+
return patches
|
33 |
+
|
34 |
+
|
35 |
+
|