sycod
commited on
Commit
·
0fe2514
1
Parent(s):
fc06865
start EfficientNetV2M
Browse files- EDA.ipynb +262 -310
- README.md +2 -3
- config.yaml +3 -1
- src/load_data.py +69 -26
EDA.ipynb
CHANGED
@@ -16,14 +16,13 @@
|
|
16 |
" - [🚧 Image exploration](#toc3_3_) \n",
|
17 |
"- [Data preprocessing](#toc4_) \n",
|
18 |
"- [🦄🦄 CHECKPOINT 🦄🦄](#toc5_) \n",
|
19 |
-
"- [
|
20 |
-
"- [
|
21 |
-
"
|
22 |
-
"- [
|
23 |
-
" - [Prepare
|
24 |
-
" - [
|
25 |
-
" - [
|
26 |
-
" - [Random Baseline](#toc8_4_) \n",
|
27 |
"\n",
|
28 |
"<!-- vscode-jupyter-toc-config\n",
|
29 |
"\tnumbering=false\n",
|
@@ -71,25 +70,25 @@
|
|
71 |
"text": [
|
72 |
"/Users/julmat/Documents/hugging_face/frugal_cviz/.venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
|
73 |
" from .autonotebook import tqdm as notebook_tqdm\n",
|
74 |
-
"[codecarbon WARNING @
|
75 |
-
"[codecarbon INFO @
|
76 |
-
"[codecarbon INFO @
|
77 |
-
"[codecarbon WARNING @
|
78 |
" Mac OS and ARM processor detected: Please enable PowerMetrics sudo to measure CPU\n",
|
79 |
"\n",
|
80 |
-
"[codecarbon INFO @
|
81 |
-
"[codecarbon INFO @
|
82 |
-
"[codecarbon INFO @
|
83 |
-
"[codecarbon INFO @
|
84 |
-
"[codecarbon INFO @
|
85 |
-
"[codecarbon INFO @
|
86 |
-
"[codecarbon INFO @
|
87 |
-
"[codecarbon INFO @
|
88 |
-
"[codecarbon INFO @
|
89 |
-
"[codecarbon INFO @
|
90 |
-
"[codecarbon INFO @
|
91 |
-
"[codecarbon INFO @
|
92 |
-
"[codecarbon INFO @
|
93 |
]
|
94 |
}
|
95 |
],
|
@@ -106,8 +105,8 @@
|
|
106 |
"\n",
|
107 |
"# ML\n",
|
108 |
"from keras import Model\n",
|
109 |
-
"from keras.applications import EfficientNetB0\n",
|
110 |
-
"from keras.layers import Flatten, Dense\n",
|
111 |
"from keras.metrics import Precision, Recall\n",
|
112 |
"from keras.optimizers import AdamW\n",
|
113 |
"from keras.utils import image_dataset_from_directory\n",
|
@@ -126,7 +125,7 @@
|
|
126 |
"from tasks.image import parse_boxes, compute_iou, compute_max_iou\n",
|
127 |
"\n",
|
128 |
"\n",
|
129 |
-
"# Logging
|
130 |
"logger = logging.getLogger()\n",
|
131 |
"logger.setLevel(logging.INFO)"
|
132 |
]
|
@@ -149,7 +148,9 @@
|
|
149 |
" cfg = yaml.safe_load(f)\n",
|
150 |
"# Data\n",
|
151 |
"OUTPUT_DIR = cfg[\"data_root_dir\"]\n",
|
152 |
-
"
|
|
|
|
|
153 |
"REPO_ID = cfg[\"repo_id\"]\n",
|
154 |
"SPLIT_SIZE = cfg[\"split_size\"]\n",
|
155 |
"RDM_SEED = cfg[\"rdm_seed\"]\n",
|
@@ -1858,16 +1859,14 @@
|
|
1858 |
"metadata": {},
|
1859 |
"outputs": [
|
1860 |
{
|
1861 |
-
"name": "
|
1862 |
"output_type": "stream",
|
1863 |
"text": [
|
1864 |
-
"
|
1865 |
-
"Wall time: 17.5 s\n"
|
1866 |
]
|
1867 |
}
|
1868 |
],
|
1869 |
"source": [
|
1870 |
-
"%%time\n",
|
1871 |
"df_format = format_data_keras(df_clean.copy())"
|
1872 |
]
|
1873 |
},
|
@@ -1880,6 +1879,15 @@
|
|
1880 |
"- update dataframe"
|
1881 |
]
|
1882 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1883 |
{
|
1884 |
"cell_type": "code",
|
1885 |
"execution_count": 13,
|
@@ -1889,34 +1897,12 @@
|
|
1889 |
"name": "stderr",
|
1890 |
"output_type": "stream",
|
1891 |
"text": [
|
1892 |
-
"INFO:root
|
1893 |
-
"INFO:root:⚙️ Transforming 16025 images...\n",
|
1894 |
-
"INFO:root:✅ Transformed 3802 images with blur_img\n",
|
1895 |
-
"INFO:root:✅ Transformed 3802 images with flip_img\n",
|
1896 |
-
"INFO:root:✅ Transformed 3802 images with blur_flip_img\n",
|
1897 |
-
"INFO:root:✅ Transformed 3802 images with eq_img\n",
|
1898 |
-
"INFO:root:✅ Transformed 817 images with 180_img\n",
|
1899 |
-
"INFO:root:⚙️ Processing val split...\n",
|
1900 |
-
"INFO:root:⚙️ Transforming 2571 images...\n",
|
1901 |
-
"INFO:root:✅ Transformed 764 images with blur_img\n",
|
1902 |
-
"INFO:root:✅ Transformed 764 images with flip_img\n",
|
1903 |
-
"INFO:root:✅ Transformed 764 images with blur_flip_img\n",
|
1904 |
-
"INFO:root:✅ Transformed 279 images with eq_img\n",
|
1905 |
-
"INFO:root:✅ Transformed 0 images with 180_img\n"
|
1906 |
-
]
|
1907 |
-
},
|
1908 |
-
{
|
1909 |
-
"name": "stdout",
|
1910 |
-
"output_type": "stream",
|
1911 |
-
"text": [
|
1912 |
-
"CPU times: user 3min 54s, sys: 15.9 s, total: 4min 10s\n",
|
1913 |
-
"Wall time: 4min 19s\n"
|
1914 |
]
|
1915 |
}
|
1916 |
],
|
1917 |
"source": [
|
1918 |
-
"
|
1919 |
-
"df_aug = oversample_class(df_format.copy())"
|
1920 |
]
|
1921 |
},
|
1922 |
{
|
@@ -1928,7 +1914,7 @@
|
|
1928 |
},
|
1929 |
{
|
1930 |
"cell_type": "code",
|
1931 |
-
"execution_count":
|
1932 |
"metadata": {},
|
1933 |
"outputs": [
|
1934 |
{
|
@@ -2841,21 +2827,23 @@
|
|
2841 |
"cell_type": "markdown",
|
2842 |
"metadata": {},
|
2843 |
"source": [
|
2844 |
-
"
|
2845 |
]
|
2846 |
},
|
2847 |
{
|
2848 |
-
"cell_type": "
|
|
|
2849 |
"metadata": {},
|
|
|
2850 |
"source": [
|
2851 |
-
"
|
2852 |
]
|
2853 |
},
|
2854 |
{
|
2855 |
"cell_type": "markdown",
|
2856 |
"metadata": {},
|
2857 |
"source": [
|
2858 |
-
"
|
2859 |
]
|
2860 |
},
|
2861 |
{
|
@@ -2864,68 +2852,96 @@
|
|
2864 |
"metadata": {},
|
2865 |
"outputs": [
|
2866 |
{
|
2867 |
-
"
|
2868 |
-
"evalue": "name 'stop' is not defined",
|
2869 |
-
|
2870 |
-
|
2871 |
-
|
2872 |
-
|
2873 |
-
|
2874 |
-
|
2875 |
-
]
|
2876 |
}
|
2877 |
],
|
2878 |
"source": [
|
2879 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2880 |
]
|
2881 |
},
|
2882 |
{
|
2883 |
"cell_type": "markdown",
|
2884 |
"metadata": {},
|
2885 |
"source": [
|
2886 |
-
"# <a id='
|
2887 |
]
|
2888 |
},
|
2889 |
{
|
2890 |
"cell_type": "markdown",
|
2891 |
"metadata": {},
|
2892 |
"source": [
|
2893 |
-
"## <a id='
|
2894 |
]
|
2895 |
},
|
2896 |
{
|
2897 |
"cell_type": "markdown",
|
2898 |
"metadata": {},
|
2899 |
"source": [
|
2900 |
-
"# <a id='
|
2901 |
"\n",
|
2902 |
"- https://paperswithcode.com/sota/image-classification-on-imagenet\n",
|
2903 |
-
"- https://keras.io/api/applications/efficientnet_v2/#efficientnetv2m-function"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2904 |
]
|
2905 |
},
|
2906 |
{
|
2907 |
"cell_type": "code",
|
2908 |
-
"execution_count":
|
2909 |
"metadata": {},
|
2910 |
-
"outputs": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2911 |
"source": [
|
2912 |
-
"
|
2913 |
-
"\n",
|
2914 |
-
"# model = EfficientNetV2M("
|
2915 |
]
|
2916 |
},
|
2917 |
{
|
2918 |
"cell_type": "code",
|
2919 |
-
"execution_count":
|
2920 |
"metadata": {},
|
2921 |
"outputs": [],
|
2922 |
"source": [
|
2923 |
"# Model config\n",
|
2924 |
-
"model_name = \"
|
2925 |
"input_size = (224, 224)\n",
|
2926 |
-
"batch_size =
|
2927 |
-
"n_epochs = 100\n",
|
2928 |
"optimizer = AdamW(learning_rate=0.0002, weight_decay=0.05)\n",
|
|
|
|
|
|
|
|
|
|
|
2929 |
"loss = \"binary_crossentropy\"\n",
|
2930 |
"metrics = [\"accuracy\", Precision(), Recall()]\n",
|
2931 |
"# metrics = [\"accuracy\", Precision(), Recall(), \"f1_score\"]\n",
|
@@ -2945,97 +2961,22 @@
|
|
2945 |
"cell_type": "markdown",
|
2946 |
"metadata": {},
|
2947 |
"source": [
|
2948 |
-
"## <a id='
|
2949 |
-
]
|
2950 |
-
},
|
2951 |
-
{
|
2952 |
-
"cell_type": "markdown",
|
2953 |
-
"metadata": {},
|
2954 |
-
"source": [
|
2955 |
-
"Create datasets from local images and labels"
|
2956 |
-
]
|
2957 |
-
},
|
2958 |
-
{
|
2959 |
-
"cell_type": "code",
|
2960 |
-
"execution_count": 184,
|
2961 |
-
"metadata": {},
|
2962 |
-
"outputs": [
|
2963 |
-
{
|
2964 |
-
"name": "stdout",
|
2965 |
-
"output_type": "stream",
|
2966 |
-
"text": [
|
2967 |
-
"Train dataset:\n",
|
2968 |
-
"Found 23629 files belonging to 2 classes.\n",
|
2969 |
-
"\n",
|
2970 |
-
"Val dataset:\n",
|
2971 |
-
"Found 4099 files belonging to 2 classes.\n",
|
2972 |
-
"\n",
|
2973 |
-
"Test dataset:\n",
|
2974 |
-
"Found 5908 files belonging to 2 classes.\n"
|
2975 |
-
]
|
2976 |
-
}
|
2977 |
-
],
|
2978 |
-
"source": [
|
2979 |
-
"# Prepare for outputs\n",
|
2980 |
-
"os.makedirs(MODELS_ROOT_DIR, exist_ok=True)\n",
|
2981 |
-
"y = df[\"label\"]\n",
|
2982 |
-
"X = df[\"uri\"]\n",
|
2983 |
-
"\n",
|
2984 |
-
"# Create datasets\n",
|
2985 |
-
"print(\"Train dataset:\")\n",
|
2986 |
-
"train_ds = image_dataset_from_directory(\n",
|
2987 |
-
" train_dir,\n",
|
2988 |
-
" labels=\"inferred\", # class names upon folders structure\n",
|
2989 |
-
" label_mode=\"int\", # integer encoding\n",
|
2990 |
-
" shuffle=True, # shuffle images\n",
|
2991 |
-
" seed=42, # random seed\n",
|
2992 |
-
" image_size=input_size, # automatic resizing\n",
|
2993 |
-
" batch_size=batch_size, # tensor shape[0]\n",
|
2994 |
-
")\n",
|
2995 |
-
"\n",
|
2996 |
-
"print(\"\\nVal dataset:\")\n",
|
2997 |
-
"val_ds = image_dataset_from_directory(\n",
|
2998 |
-
" val_dir,\n",
|
2999 |
-
" labels=\"inferred\", # class names upon folders structure\n",
|
3000 |
-
" label_mode=\"int\", # integer encoding\n",
|
3001 |
-
" shuffle=True, # shuffle images\n",
|
3002 |
-
" seed=42, # random seed\n",
|
3003 |
-
" image_size=input_size, # automatic resizing\n",
|
3004 |
-
" batch_size=batch_size, # tensor shape[0]\n",
|
3005 |
-
")\n",
|
3006 |
-
"\n",
|
3007 |
-
"print(\"\\nTest dataset:\")\n",
|
3008 |
-
"test_ds = image_dataset_from_directory(\n",
|
3009 |
-
" test_dir,\n",
|
3010 |
-
" labels=\"inferred\", # class names upon folders structure\n",
|
3011 |
-
" label_mode=\"int\", # integer encoding\n",
|
3012 |
-
" shuffle=False, # do not shuffle images\n",
|
3013 |
-
" seed=42, # random seed\n",
|
3014 |
-
" image_size=input_size, # automatic resizing\n",
|
3015 |
-
" batch_size=batch_size, # tensor shape[0]\n",
|
3016 |
-
")"
|
3017 |
-
]
|
3018 |
-
},
|
3019 |
-
{
|
3020 |
-
"cell_type": "markdown",
|
3021 |
-
"metadata": {},
|
3022 |
-
"source": [
|
3023 |
-
"## <a id='toc8_2_'></a>[Prepare model](#toc0_)"
|
3024 |
]
|
3025 |
},
|
3026 |
{
|
3027 |
"cell_type": "code",
|
3028 |
-
"execution_count":
|
3029 |
"metadata": {},
|
3030 |
"outputs": [
|
3031 |
{
|
3032 |
"data": {
|
3033 |
"text/html": [
|
3034 |
-
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"
|
3035 |
"</pre>\n"
|
3036 |
],
|
3037 |
"text/plain": [
|
3038 |
-
"\u001b[1mModel: \"
|
3039 |
]
|
3040 |
},
|
3041 |
"metadata": {},
|
@@ -3044,31 +2985,33 @@
|
|
3044 |
{
|
3045 |
"data": {
|
3046 |
"text/html": [
|
3047 |
-
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"
|
3048 |
-
"┃<span style=\"font-weight: bold\"> Layer (type)
|
3049 |
-
"
|
3050 |
-
"│
|
3051 |
-
"
|
3052 |
-
"│
|
3053 |
-
"
|
3054 |
-
"
|
3055 |
-
"
|
3056 |
-
"
|
3057 |
-
"
|
|
|
3058 |
"</pre>\n"
|
3059 |
],
|
3060 |
"text/plain": [
|
3061 |
-
"
|
3062 |
-
"┃\u001b[1m \u001b[0m\u001b[1mLayer (type)
|
3063 |
-
"
|
3064 |
-
"│
|
3065 |
-
"
|
3066 |
-
"│
|
3067 |
-
"
|
3068 |
-
"
|
3069 |
-
"
|
3070 |
-
"
|
3071 |
-
"
|
|
|
3072 |
]
|
3073 |
},
|
3074 |
"metadata": {},
|
@@ -3077,11 +3020,11 @@
|
|
3077 |
{
|
3078 |
"data": {
|
3079 |
"text/html": [
|
3080 |
-
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">
|
3081 |
"</pre>\n"
|
3082 |
],
|
3083 |
"text/plain": [
|
3084 |
-
"\u001b[1m Total params: \u001b[0m\u001b[38;5;
|
3085 |
]
|
3086 |
},
|
3087 |
"metadata": {},
|
@@ -3103,11 +3046,11 @@
|
|
3103 |
{
|
3104 |
"data": {
|
3105 |
"text/html": [
|
3106 |
-
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">
|
3107 |
"</pre>\n"
|
3108 |
],
|
3109 |
"text/plain": [
|
3110 |
-
"\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;
|
3111 |
]
|
3112 |
},
|
3113 |
"metadata": {},
|
@@ -3116,176 +3059,152 @@
|
|
3116 |
],
|
3117 |
"source": [
|
3118 |
"# Load pre-trained model without top layers\n",
|
3119 |
-
"
|
3120 |
" weights=\"imagenet\", # pre-trained weights\n",
|
3121 |
" include_top=False, # no dense layer\n",
|
3122 |
-
" input_shape=(input_size[0], input_size[1], 3), # input shape
|
3123 |
")\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3124 |
"# Create explicit input layer\n",
|
3125 |
"inputs = tf.keras.Input(shape=(input_size[0], input_size[1], 3))\n",
|
3126 |
-
"# add data augmentation\n",
|
3127 |
-
"# augmented = ConditionalAugmentation(rate=0.4)(inputs)\n",
|
3128 |
-
"# x = model(augmented)\n",
|
3129 |
-
"x = model(inputs)\n",
|
3130 |
"\n",
|
|
|
|
|
|
|
|
|
3131 |
"# Flatten output\n",
|
3132 |
"x = Flatten()(x)\n",
|
3133 |
-
"# For feature extraction only\n",
|
3134 |
-
"for layer in model.layers:\n",
|
3135 |
-
" layer.trainable = False\n",
|
3136 |
"# New FC layer for binary classification\n",
|
3137 |
"predictions = Dense(1, activation=\"sigmoid\")(x)\n",
|
|
|
3138 |
"# Define new model\n",
|
3139 |
-
"
|
|
|
3140 |
"# Display model summary\n",
|
3141 |
-
"
|
3142 |
]
|
3143 |
},
|
3144 |
{
|
3145 |
"cell_type": "markdown",
|
3146 |
"metadata": {},
|
3147 |
"source": [
|
3148 |
-
"## <a id='
|
3149 |
]
|
3150 |
},
|
3151 |
{
|
3152 |
"cell_type": "markdown",
|
3153 |
"metadata": {},
|
3154 |
"source": [
|
3155 |
-
"
|
3156 |
]
|
3157 |
},
|
3158 |
{
|
3159 |
"cell_type": "code",
|
3160 |
-
"execution_count":
|
3161 |
"metadata": {},
|
3162 |
"outputs": [
|
3163 |
-
{
|
3164 |
-
"name": "stderr",
|
3165 |
-
"output_type": "stream",
|
3166 |
-
"text": [
|
3167 |
-
"INFO:root:⚙️ compiling\n",
|
3168 |
-
"INFO:root:🛎️ declaring callbacks\n",
|
3169 |
-
"INFO:root:💪 starting training\n"
|
3170 |
-
]
|
3171 |
-
},
|
3172 |
-
{
|
3173 |
-
"name": "stdout",
|
3174 |
-
"output_type": "stream",
|
3175 |
-
"text": [
|
3176 |
-
"Epoch 1/100\n",
|
3177 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m406s\u001b[0m 815ms/step - accuracy: 0.8178 - loss: 0.4710 - precision_3: 0.8521 - recall_3: 0.9467 - val_accuracy: 0.7821 - val_loss: 0.5143 - val_precision_3: 0.8256 - val_recall_3: 0.9283\n",
|
3178 |
-
"Epoch 2/100\n",
|
3179 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m398s\u001b[0m 808ms/step - accuracy: 0.8334 - loss: 0.4258 - precision_3: 0.8697 - recall_3: 0.9422 - val_accuracy: 0.8046 - val_loss: 0.5463 - val_precision_3: 0.8188 - val_recall_3: 0.9757\n",
|
3180 |
-
"Epoch 3/100\n",
|
3181 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m394s\u001b[0m 799ms/step - accuracy: 0.8461 - loss: 0.4060 - precision_3: 0.8763 - recall_3: 0.9506 - val_accuracy: 0.7590 - val_loss: 0.6189 - val_precision_3: 0.8438 - val_recall_3: 0.8636\n",
|
3182 |
-
"Epoch 4/100\n",
|
3183 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m383s\u001b[0m 776ms/step - accuracy: 0.8472 - loss: 0.3938 - precision_3: 0.8793 - recall_3: 0.9476 - val_accuracy: 0.7785 - val_loss: 0.5448 - val_precision_3: 0.8263 - val_recall_3: 0.9214\n",
|
3184 |
-
"Epoch 5/100\n",
|
3185 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m361s\u001b[0m 733ms/step - accuracy: 0.8579 - loss: 0.3752 - precision_3: 0.8865 - recall_3: 0.9524 - val_accuracy: 0.7856 - val_loss: 0.6732 - val_precision_3: 0.8133 - val_recall_3: 0.9559\n",
|
3186 |
-
"Epoch 6/100\n",
|
3187 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m368s\u001b[0m 747ms/step - accuracy: 0.8504 - loss: 0.3840 - precision_3: 0.8866 - recall_3: 0.9417 - val_accuracy: 0.8104 - val_loss: 0.5844 - val_precision_3: 0.8233 - val_recall_3: 0.9766\n",
|
3188 |
-
"Epoch 7/100\n",
|
3189 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m366s\u001b[0m 743ms/step - accuracy: 0.8543 - loss: 0.3848 - precision_3: 0.8870 - recall_3: 0.9468 - val_accuracy: 0.7868 - val_loss: 0.6400 - val_precision_3: 0.8209 - val_recall_3: 0.9439\n",
|
3190 |
-
"Epoch 8/100\n",
|
3191 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m359s\u001b[0m 728ms/step - accuracy: 0.8572 - loss: 0.3700 - precision_3: 0.8884 - recall_3: 0.9486 - val_accuracy: 0.7965 - val_loss: 0.5693 - val_precision_3: 0.8252 - val_recall_3: 0.9514\n",
|
3192 |
-
"Epoch 9/100\n",
|
3193 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m363s\u001b[0m 737ms/step - accuracy: 0.8564 - loss: 0.3684 - precision_3: 0.8890 - recall_3: 0.9467 - val_accuracy: 0.7939 - val_loss: 0.6147 - val_precision_3: 0.8341 - val_recall_3: 0.9319\n",
|
3194 |
-
"Epoch 10/100\n",
|
3195 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m369s\u001b[0m 749ms/step - accuracy: 0.8603 - loss: 0.3629 - precision_3: 0.8904 - recall_3: 0.9500 - val_accuracy: 0.8026 - val_loss: 0.5798 - val_precision_3: 0.8311 - val_recall_3: 0.9505\n",
|
3196 |
-
"Epoch 11/100\n",
|
3197 |
-
"\u001b[1m493/493\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m368s\u001b[0m 746ms/step - accuracy: 0.8634 - loss: 0.3589 - precision_3: 0.8931 - recall_3: 0.9507 - val_accuracy: 0.7573 - val_loss: 0.6606 - val_precision_3: 0.8164 - val_recall_3: 0.9052\n"
|
3198 |
-
]
|
3199 |
-
},
|
3200 |
-
{
|
3201 |
-
"name": "stderr",
|
3202 |
-
"output_type": "stream",
|
3203 |
-
"text": [
|
3204 |
-
"INFO:root:🧐 evaluating model\n"
|
3205 |
-
]
|
3206 |
-
},
|
3207 |
-
{
|
3208 |
-
"name": "stdout",
|
3209 |
-
"output_type": "stream",
|
3210 |
-
"text": [
|
3211 |
-
"\u001b[1m124/124\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m72s\u001b[0m 579ms/step - accuracy: 0.6824 - loss: 0.8199 - precision_3: 0.6028 - recall_3: 0.7630\n",
|
3212 |
-
"\u001b[1m124/124\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m74s\u001b[0m 586ms/step\n"
|
3213 |
-
]
|
3214 |
-
},
|
3215 |
-
{
|
3216 |
-
"name": "stderr",
|
3217 |
-
"output_type": "stream",
|
3218 |
-
"text": [
|
3219 |
-
"INFO:root:📈 plotting results\n"
|
3220 |
-
]
|
3221 |
-
},
|
3222 |
{
|
3223 |
"name": "stdout",
|
3224 |
"output_type": "stream",
|
3225 |
"text": [
|
3226 |
-
"
|
|
|
3227 |
"\n",
|
3228 |
-
"
|
3229 |
-
"
|
3230 |
"\n",
|
3231 |
-
"
|
3232 |
-
"
|
3233 |
-
"weighted avg 0.03 0.16 0.05 5908\n",
|
3234 |
-
"\n"
|
3235 |
]
|
3236 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3237 |
{
|
3238 |
"name": "stderr",
|
3239 |
"output_type": "stream",
|
3240 |
"text": [
|
3241 |
-
"
|
3242 |
-
"
|
3243 |
-
"\n"
|
3244 |
-
"Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
|
3245 |
-
"\n",
|
3246 |
-
"/Users/julmat/Documents/hugging_face/frugal_cviz/.venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning:\n",
|
3247 |
-
"\n",
|
3248 |
-
"Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
|
3249 |
-
"\n",
|
3250 |
-
"/Users/julmat/Documents/hugging_face/frugal_cviz/.venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning:\n",
|
3251 |
-
"\n",
|
3252 |
-
"Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
|
3253 |
-
"\n",
|
3254 |
-
"/Users/julmat/Documents/hugging_face/frugal_cviz/.venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning:\n",
|
3255 |
-
"\n",
|
3256 |
-
"Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
|
3257 |
-
"\n",
|
3258 |
-
"/Users/julmat/Documents/hugging_face/frugal_cviz/.venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning:\n",
|
3259 |
-
"\n",
|
3260 |
-
"Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
|
3261 |
-
"\n",
|
3262 |
-
"/Users/julmat/Documents/hugging_face/frugal_cviz/.venv/lib/python3.12/site-packages/sklearn/metrics/_classification.py:1565: UndefinedMetricWarning:\n",
|
3263 |
-
"\n",
|
3264 |
-
"Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
|
3265 |
-
"\n"
|
3266 |
]
|
3267 |
},
|
3268 |
{
|
3269 |
-
"
|
3270 |
-
"image/png": "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",
|
3271 |
-
"text/plain": [
|
3272 |
-
"<Figure size 600x400 with 2 Axes>"
|
3273 |
-
]
|
3274 |
-
},
|
3275 |
-
"metadata": {},
|
3276 |
-
"output_type": "display_data"
|
3277 |
-
},
|
3278 |
-
{
|
3279 |
-
"name": "stderr",
|
3280 |
"output_type": "stream",
|
3281 |
"text": [
|
3282 |
-
"
|
|
|
3283 |
]
|
3284 |
}
|
3285 |
],
|
3286 |
"source": [
|
3287 |
"model_trained, history = eval_pretrained_model(\n",
|
3288 |
-
" model=
|
3289 |
" train_ds=train_ds,\n",
|
3290 |
" val_ds=val_ds,\n",
|
3291 |
" test_ds=test_ds,\n",
|
@@ -3366,7 +3285,7 @@
|
|
3366 |
"cell_type": "markdown",
|
3367 |
"metadata": {},
|
3368 |
"source": [
|
3369 |
-
"## <a id='
|
3370 |
]
|
3371 |
},
|
3372 |
{
|
@@ -3389,6 +3308,39 @@
|
|
3389 |
"tracker.start_task(\"inference\")"
|
3390 |
]
|
3391 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3392 |
{
|
3393 |
"cell_type": "code",
|
3394 |
"execution_count": 11,
|
|
|
16 |
" - [🚧 Image exploration](#toc3_3_) \n",
|
17 |
"- [Data preprocessing](#toc4_) \n",
|
18 |
"- [🦄🦄 CHECKPOINT 🦄🦄](#toc5_) \n",
|
19 |
+
"- [Model Training](#toc6_) \n",
|
20 |
+
" - [Load configuration](#toc6_1_) \n",
|
21 |
+
"- [🚧 MODEL CHOICE](#toc7_) \n",
|
22 |
+
" - [Prepare data](#toc7_1_) \n",
|
23 |
+
" - [Prepare model](#toc7_2_) \n",
|
24 |
+
" - [Training](#toc7_3_) \n",
|
25 |
+
" - [Random Baseline](#toc7_4_) \n",
|
|
|
26 |
"\n",
|
27 |
"<!-- vscode-jupyter-toc-config\n",
|
28 |
"\tnumbering=false\n",
|
|
|
70 |
"text": [
|
71 |
"/Users/julmat/Documents/hugging_face/frugal_cviz/.venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
|
72 |
" from .autonotebook import tqdm as notebook_tqdm\n",
|
73 |
+
"[codecarbon WARNING @ 23:01:31] Multiple instances of codecarbon are allowed to run at the same time.\n",
|
74 |
+
"[codecarbon INFO @ 23:01:31] [setup] RAM Tracking...\n",
|
75 |
+
"[codecarbon INFO @ 23:01:31] [setup] CPU Tracking...\n",
|
76 |
+
"[codecarbon WARNING @ 23:01:31] No CPU tracking mode found. Falling back on CPU constant mode. \n",
|
77 |
" Mac OS and ARM processor detected: Please enable PowerMetrics sudo to measure CPU\n",
|
78 |
"\n",
|
79 |
+
"[codecarbon INFO @ 23:01:31] CPU Model on constant consumption mode: Apple M1\n",
|
80 |
+
"[codecarbon INFO @ 23:01:31] [setup] GPU Tracking...\n",
|
81 |
+
"[codecarbon INFO @ 23:01:31] No GPU found.\n",
|
82 |
+
"[codecarbon INFO @ 23:01:31] >>> Tracker's metadata:\n",
|
83 |
+
"[codecarbon INFO @ 23:01:31] Platform system: macOS-15.2-arm64-arm-64bit\n",
|
84 |
+
"[codecarbon INFO @ 23:01:31] Python version: 3.12.7\n",
|
85 |
+
"[codecarbon INFO @ 23:01:31] CodeCarbon version: 2.8.3\n",
|
86 |
+
"[codecarbon INFO @ 23:01:31] Available RAM : 16.000 GB\n",
|
87 |
+
"[codecarbon INFO @ 23:01:31] CPU count: 8\n",
|
88 |
+
"[codecarbon INFO @ 23:01:31] CPU model: Apple M1\n",
|
89 |
+
"[codecarbon INFO @ 23:01:31] GPU count: None\n",
|
90 |
+
"[codecarbon INFO @ 23:01:31] GPU model: None\n",
|
91 |
+
"[codecarbon INFO @ 23:01:34] Saving emissions data to file /Users/julmat/Documents/hugging_face/frugal_cviz/emissions.csv\n"
|
92 |
]
|
93 |
}
|
94 |
],
|
|
|
105 |
"\n",
|
106 |
"# ML\n",
|
107 |
"from keras import Model\n",
|
108 |
+
"from keras.applications import EfficientNetB0, EfficientNetV2M\n",
|
109 |
+
"from keras.layers import Flatten, Dense, Dropout\n",
|
110 |
"from keras.metrics import Precision, Recall\n",
|
111 |
"from keras.optimizers import AdamW\n",
|
112 |
"from keras.utils import image_dataset_from_directory\n",
|
|
|
125 |
"from tasks.image import parse_boxes, compute_iou, compute_max_iou\n",
|
126 |
"\n",
|
127 |
"\n",
|
128 |
+
"# Logging outputs config (DEBUG < INFO)\n",
|
129 |
"logger = logging.getLogger()\n",
|
130 |
"logger.setLevel(logging.INFO)"
|
131 |
]
|
|
|
148 |
" cfg = yaml.safe_load(f)\n",
|
149 |
"# Data\n",
|
150 |
"OUTPUT_DIR = cfg[\"data_root_dir\"]\n",
|
151 |
+
"DB_RAW_INFO_URI = os.path.join(OUTPUT_DIR, cfg[\"db_raw_info_uri\"])\n",
|
152 |
+
"DB_KERAS_INFO_URI = os.path.join(OUTPUT_DIR, cfg[\"db_keras_info_uri\"])\n",
|
153 |
+
"DB_AUG_INFO_URI = os.path.join(OUTPUT_DIR, cfg[\"db_aug_info_uri\"])\n",
|
154 |
"REPO_ID = cfg[\"repo_id\"]\n",
|
155 |
"SPLIT_SIZE = cfg[\"split_size\"]\n",
|
156 |
"RDM_SEED = cfg[\"rdm_seed\"]\n",
|
|
|
1859 |
"metadata": {},
|
1860 |
"outputs": [
|
1861 |
{
|
1862 |
+
"name": "stderr",
|
1863 |
"output_type": "stream",
|
1864 |
"text": [
|
1865 |
+
"INFO:root:data/data_keras_info.csv already exists: data already formatted\n"
|
|
|
1866 |
]
|
1867 |
}
|
1868 |
],
|
1869 |
"source": [
|
|
|
1870 |
"df_format = format_data_keras(df_clean.copy())"
|
1871 |
]
|
1872 |
},
|
|
|
1879 |
"- update dataframe"
|
1880 |
]
|
1881 |
},
|
1882 |
+
{
|
1883 |
+
"cell_type": "markdown",
|
1884 |
+
"metadata": {},
|
1885 |
+
"source": [
|
1886 |
+
"> 💡 Much better... but a quality balance issue just appeared: \"no_smoke\" images are often blured, flipped, equalized or rotated whereas \"smoke\" images are not.\n",
|
1887 |
+
"\n",
|
1888 |
+
"👉 Following algorithm will oversample and balance classes quality, by applying the same amount of image for the other class"
|
1889 |
+
]
|
1890 |
+
},
|
1891 |
{
|
1892 |
"cell_type": "code",
|
1893 |
"execution_count": 13,
|
|
|
1897 |
"name": "stderr",
|
1898 |
"output_type": "stream",
|
1899 |
"text": [
|
1900 |
+
"INFO:root:data/data_aug_info.csv already exists: data already formatted\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1901 |
]
|
1902 |
}
|
1903 |
],
|
1904 |
"source": [
|
1905 |
+
"df_aug = oversample_class(df_format)"
|
|
|
1906 |
]
|
1907 |
},
|
1908 |
{
|
|
|
1914 |
},
|
1915 |
{
|
1916 |
"cell_type": "code",
|
1917 |
+
"execution_count": 14,
|
1918 |
"metadata": {},
|
1919 |
"outputs": [
|
1920 |
{
|
|
|
2827 |
"cell_type": "markdown",
|
2828 |
"metadata": {},
|
2829 |
"source": [
|
2830 |
+
"Keep last dataframe as model basis"
|
2831 |
]
|
2832 |
},
|
2833 |
{
|
2834 |
+
"cell_type": "code",
|
2835 |
+
"execution_count": 15,
|
2836 |
"metadata": {},
|
2837 |
+
"outputs": [],
|
2838 |
"source": [
|
2839 |
+
"df = df_aug.copy()"
|
2840 |
]
|
2841 |
},
|
2842 |
{
|
2843 |
"cell_type": "markdown",
|
2844 |
"metadata": {},
|
2845 |
"source": [
|
2846 |
+
"New splits distribution"
|
2847 |
]
|
2848 |
},
|
2849 |
{
|
|
|
2852 |
"metadata": {},
|
2853 |
"outputs": [
|
2854 |
{
|
2855 |
+
"data": {
|
2856 |
+
"image/png": "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",
|
2857 |
+
"text/plain": [
|
2858 |
+
"<Figure size 640x480 with 1 Axes>"
|
2859 |
+
]
|
2860 |
+
},
|
2861 |
+
"metadata": {},
|
2862 |
+
"output_type": "display_data"
|
|
|
2863 |
}
|
2864 |
],
|
2865 |
"source": [
|
2866 |
+
"labels_distr = df.split.value_counts()\n",
|
2867 |
+
"\n",
|
2868 |
+
"plt.pie(\n",
|
2869 |
+
" labels_distr,\n",
|
2870 |
+
" labels=labels_distr.index,\n",
|
2871 |
+
" autopct=make_autopct(labels_distr),\n",
|
2872 |
+
")\n",
|
2873 |
+
"plt.show()"
|
2874 |
]
|
2875 |
},
|
2876 |
{
|
2877 |
"cell_type": "markdown",
|
2878 |
"metadata": {},
|
2879 |
"source": [
|
2880 |
+
"# <a id='toc6_'></a>[Model Training](#toc0_)"
|
2881 |
]
|
2882 |
},
|
2883 |
{
|
2884 |
"cell_type": "markdown",
|
2885 |
"metadata": {},
|
2886 |
"source": [
|
2887 |
+
"## <a id='toc6_1_'></a>[Load configuration](#toc0_)"
|
2888 |
]
|
2889 |
},
|
2890 |
{
|
2891 |
"cell_type": "markdown",
|
2892 |
"metadata": {},
|
2893 |
"source": [
|
2894 |
+
"# <a id='toc7_'></a>[🚧 MODEL CHOICE](#toc0_)\n",
|
2895 |
"\n",
|
2896 |
"- https://paperswithcode.com/sota/image-classification-on-imagenet\n",
|
2897 |
+
"- https://keras.io/api/applications/efficientnet_v2/#efficientnetv2m-function\n",
|
2898 |
+
"- [ViTForImageClassification](https://huggingface.co/docs/transformers/main/en/model_doc/vit)"
|
2899 |
+
]
|
2900 |
+
},
|
2901 |
+
{
|
2902 |
+
"cell_type": "markdown",
|
2903 |
+
"metadata": {},
|
2904 |
+
"source": [
|
2905 |
+
"# <a id='toc5_'></a>[🦄🦄 CHECKPOINT 🦄🦄](#toc0_)"
|
2906 |
]
|
2907 |
},
|
2908 |
{
|
2909 |
"cell_type": "code",
|
2910 |
+
"execution_count": 17,
|
2911 |
"metadata": {},
|
2912 |
+
"outputs": [
|
2913 |
+
{
|
2914 |
+
"ename": "NameError",
|
2915 |
+
"evalue": "name 'stop' is not defined",
|
2916 |
+
"output_type": "error",
|
2917 |
+
"traceback": [
|
2918 |
+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
2919 |
+
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
|
2920 |
+
"Cell \u001b[0;32mIn[17], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mstop\u001b[49m\n",
|
2921 |
+
"\u001b[0;31mNameError\u001b[0m: name 'stop' is not defined"
|
2922 |
+
]
|
2923 |
+
}
|
2924 |
+
],
|
2925 |
"source": [
|
2926 |
+
"stop"
|
|
|
|
|
2927 |
]
|
2928 |
},
|
2929 |
{
|
2930 |
"cell_type": "code",
|
2931 |
+
"execution_count": 18,
|
2932 |
"metadata": {},
|
2933 |
"outputs": [],
|
2934 |
"source": [
|
2935 |
"# Model config\n",
|
2936 |
+
"model_name = \"EfficientNetV2M\"\n",
|
2937 |
"input_size = (224, 224)\n",
|
2938 |
+
"batch_size = 32\n",
|
|
|
2939 |
"optimizer = AdamW(learning_rate=0.0002, weight_decay=0.05)\n",
|
2940 |
+
"# model_name = \"EfficientNetB0\"\n",
|
2941 |
+
"# input_size = (224, 224)\n",
|
2942 |
+
"# batch_size = 48\n",
|
2943 |
+
"# optimizer = AdamW(learning_rate=0.0002, weight_decay=0.05)\n",
|
2944 |
+
"n_epochs = 100\n",
|
2945 |
"loss = \"binary_crossentropy\"\n",
|
2946 |
"metrics = [\"accuracy\", Precision(), Recall()]\n",
|
2947 |
"# metrics = [\"accuracy\", Precision(), Recall(), \"f1_score\"]\n",
|
|
|
2961 |
"cell_type": "markdown",
|
2962 |
"metadata": {},
|
2963 |
"source": [
|
2964 |
+
"## <a id='toc7_2_'></a>[Prepare model](#toc0_)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2965 |
]
|
2966 |
},
|
2967 |
{
|
2968 |
"cell_type": "code",
|
2969 |
+
"execution_count": 19,
|
2970 |
"metadata": {},
|
2971 |
"outputs": [
|
2972 |
{
|
2973 |
"data": {
|
2974 |
"text/html": [
|
2975 |
+
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"functional\"</span>\n",
|
2976 |
"</pre>\n"
|
2977 |
],
|
2978 |
"text/plain": [
|
2979 |
+
"\u001b[1mModel: \"functional\"\u001b[0m\n"
|
2980 |
]
|
2981 |
},
|
2982 |
"metadata": {},
|
|
|
2985 |
{
|
2986 |
"data": {
|
2987 |
"text/html": [
|
2988 |
+
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━┓\n",
|
2989 |
+
"┃<span style=\"font-weight: bold\"> Layer (type) </span>┃<span style=\"font-weight: bold\"> Output Shape </span>┃<span style=\"font-weight: bold\"> Param # </span>┃<span style=\"font-weight: bold\"> Trai… </span>┃\n",
|
2990 |
+
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━┩\n",
|
2991 |
+
"│ input_layer_1 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">InputLayer</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">224</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">224</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">3</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ <span style=\"font-weight: bold\">-</span> │\n",
|
2992 |
+
"├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n",
|
2993 |
+
"│ efficientnetv2-m │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">7</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">7</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">1280</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">53,150,388</span> │ <span style=\"color: #ff0000; text-decoration-color: #ff0000; font-weight: bold\">N</span> │\n",
|
2994 |
+
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Functional</span>) │ │ │ │\n",
|
2995 |
+
"├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n",
|
2996 |
+
"│ flatten (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Flatten</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">62720</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │ <span style=\"font-weight: bold\">-</span> │\n",
|
2997 |
+
"├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n",
|
2998 |
+
"│ dense (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">1</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">62,721</span> │ <span style=\"color: #00af00; text-decoration-color: #00af00; font-weight: bold\">Y</span> │\n",
|
2999 |
+
"└─────────────────────────────┴───────────────────────┴────────────┴───────┘\n",
|
3000 |
"</pre>\n"
|
3001 |
],
|
3002 |
"text/plain": [
|
3003 |
+
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━┓\n",
|
3004 |
+
"┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mTrai…\u001b[0m\u001b[1m \u001b[0m┃\n",
|
3005 |
+
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━┩\n",
|
3006 |
+
"│ input_layer_1 (\u001b[38;5;33mInputLayer\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m224\u001b[0m, \u001b[38;5;34m224\u001b[0m, \u001b[38;5;34m3\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ \u001b[1m-\u001b[0m │\n",
|
3007 |
+
"├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n",
|
3008 |
+
"│ efficientnetv2-m │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m7\u001b[0m, \u001b[38;5;34m7\u001b[0m, \u001b[38;5;34m1280\u001b[0m) │ \u001b[38;5;34m53,150,388\u001b[0m │ \u001b[1;91mN\u001b[0m │\n",
|
3009 |
+
"│ (\u001b[38;5;33mFunctional\u001b[0m) │ �� │ │\n",
|
3010 |
+
"├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n",
|
3011 |
+
"│ flatten (\u001b[38;5;33mFlatten\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m62720\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │ \u001b[1m-\u001b[0m │\n",
|
3012 |
+
"├─────────────────────────────┼───────────────────────┼────────────┼───────┤\n",
|
3013 |
+
"│ dense (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1\u001b[0m) │ \u001b[38;5;34m62,721\u001b[0m │ \u001b[1;38;5;34mY\u001b[0m │\n",
|
3014 |
+
"└─────────────────────────────┴───────────────────────┴────────────┴───────┘\n"
|
3015 |
]
|
3016 |
},
|
3017 |
"metadata": {},
|
|
|
3020 |
{
|
3021 |
"data": {
|
3022 |
"text/html": [
|
3023 |
+
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">53,213,109</span> (202.99 MB)\n",
|
3024 |
"</pre>\n"
|
3025 |
],
|
3026 |
"text/plain": [
|
3027 |
+
"\u001b[1m Total params: \u001b[0m\u001b[38;5;34m53,213,109\u001b[0m (202.99 MB)\n"
|
3028 |
]
|
3029 |
},
|
3030 |
"metadata": {},
|
|
|
3046 |
{
|
3047 |
"data": {
|
3048 |
"text/html": [
|
3049 |
+
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">53,150,388</span> (202.75 MB)\n",
|
3050 |
"</pre>\n"
|
3051 |
],
|
3052 |
"text/plain": [
|
3053 |
+
"\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m53,150,388\u001b[0m (202.75 MB)\n"
|
3054 |
]
|
3055 |
},
|
3056 |
"metadata": {},
|
|
|
3059 |
],
|
3060 |
"source": [
|
3061 |
"# Load pre-trained model without top layers\n",
|
3062 |
+
"base_model = EfficientNetV2M(\n",
|
3063 |
" weights=\"imagenet\", # pre-trained weights\n",
|
3064 |
" include_top=False, # no dense layer\n",
|
3065 |
+
" input_shape=(input_size[0], input_size[1], 3), # input shape,\n",
|
3066 |
")\n",
|
3067 |
+
"\n",
|
3068 |
+
"# For feature extraction\n",
|
3069 |
+
"base_model.trainable = False\n",
|
3070 |
+
"# # For partial fine-tuning: freeze bottom layers\n",
|
3071 |
+
"# for layer in base_model.layers[:735]:\n",
|
3072 |
+
"# layer.trainable = False\n",
|
3073 |
+
"\n",
|
3074 |
"# Create explicit input layer\n",
|
3075 |
"inputs = tf.keras.Input(shape=(input_size[0], input_size[1], 3))\n",
|
|
|
|
|
|
|
|
|
3076 |
"\n",
|
3077 |
+
"x = base_model(inputs)\n",
|
3078 |
+
"\n",
|
3079 |
+
"# # Dropout for regularization\n",
|
3080 |
+
"# x = Dropout(0.2)(x)\n",
|
3081 |
"# Flatten output\n",
|
3082 |
"x = Flatten()(x)\n",
|
|
|
|
|
|
|
3083 |
"# New FC layer for binary classification\n",
|
3084 |
"predictions = Dense(1, activation=\"sigmoid\")(x)\n",
|
3085 |
+
"\n",
|
3086 |
"# Define new model\n",
|
3087 |
+
"model_ready = Model(inputs=inputs, outputs=predictions)\n",
|
3088 |
+
"\n",
|
3089 |
"# Display model summary\n",
|
3090 |
+
"model_ready.summary(show_trainable=True)"
|
3091 |
]
|
3092 |
},
|
3093 |
{
|
3094 |
"cell_type": "markdown",
|
3095 |
"metadata": {},
|
3096 |
"source": [
|
3097 |
+
"## <a id='toc7_1_'></a>[Prepare data](#toc0_)"
|
3098 |
]
|
3099 |
},
|
3100 |
{
|
3101 |
"cell_type": "markdown",
|
3102 |
"metadata": {},
|
3103 |
"source": [
|
3104 |
+
"Create datasets from local images and labels"
|
3105 |
]
|
3106 |
},
|
3107 |
{
|
3108 |
"cell_type": "code",
|
3109 |
+
"execution_count": 20,
|
3110 |
"metadata": {},
|
3111 |
"outputs": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3112 |
{
|
3113 |
"name": "stdout",
|
3114 |
"output_type": "stream",
|
3115 |
"text": [
|
3116 |
+
"Train dataset:\n",
|
3117 |
+
"Found 39654 files belonging to 2 classes.\n",
|
3118 |
"\n",
|
3119 |
+
"Val dataset:\n",
|
3120 |
+
"Found 6670 files belonging to 2 classes.\n",
|
3121 |
"\n",
|
3122 |
+
"Test dataset:\n",
|
3123 |
+
"Found 5908 files belonging to 2 classes.\n"
|
|
|
|
|
3124 |
]
|
3125 |
+
}
|
3126 |
+
],
|
3127 |
+
"source": [
|
3128 |
+
"# Prepare for outputs\n",
|
3129 |
+
"os.makedirs(MODELS_ROOT_DIR, exist_ok=True)\n",
|
3130 |
+
"y = df[\"label\"]\n",
|
3131 |
+
"X = df[\"uri\"]\n",
|
3132 |
+
"\n",
|
3133 |
+
"# Create datasets\n",
|
3134 |
+
"print(\"Train dataset:\")\n",
|
3135 |
+
"train_ds = image_dataset_from_directory(\n",
|
3136 |
+
" train_dir,\n",
|
3137 |
+
" labels=\"inferred\", # class names upon folders structure\n",
|
3138 |
+
" label_mode=\"int\", # integer encoding\n",
|
3139 |
+
" shuffle=True, # shuffle images\n",
|
3140 |
+
" seed=42, # random seed\n",
|
3141 |
+
" image_size=input_size, # automatic resizing\n",
|
3142 |
+
" batch_size=batch_size, # tensor shape[0]\n",
|
3143 |
+
")\n",
|
3144 |
+
"\n",
|
3145 |
+
"print(\"\\nVal dataset:\")\n",
|
3146 |
+
"val_ds = image_dataset_from_directory(\n",
|
3147 |
+
" val_dir,\n",
|
3148 |
+
" labels=\"inferred\", # class names upon folders structure\n",
|
3149 |
+
" label_mode=\"int\", # integer encoding\n",
|
3150 |
+
" shuffle=True, # shuffle images\n",
|
3151 |
+
" seed=42, # random seed\n",
|
3152 |
+
" image_size=input_size, # automatic resizing\n",
|
3153 |
+
" batch_size=batch_size, # tensor shape[0]\n",
|
3154 |
+
")\n",
|
3155 |
+
"\n",
|
3156 |
+
"print(\"\\nTest dataset:\")\n",
|
3157 |
+
"test_ds = image_dataset_from_directory(\n",
|
3158 |
+
" test_dir,\n",
|
3159 |
+
" labels=\"inferred\", # class names upon folders structure\n",
|
3160 |
+
" label_mode=\"int\", # integer encoding\n",
|
3161 |
+
" shuffle=False, # do not shuffle images\n",
|
3162 |
+
" seed=42, # random seed\n",
|
3163 |
+
" image_size=input_size, # automatic resizing\n",
|
3164 |
+
" batch_size=batch_size, # tensor shape[0]\n",
|
3165 |
+
")"
|
3166 |
+
]
|
3167 |
+
},
|
3168 |
+
{
|
3169 |
+
"cell_type": "markdown",
|
3170 |
+
"metadata": {},
|
3171 |
+
"source": [
|
3172 |
+
"## <a id='toc7_3_'></a>[Training](#toc0_)"
|
3173 |
+
]
|
3174 |
+
},
|
3175 |
+
{
|
3176 |
+
"cell_type": "markdown",
|
3177 |
+
"metadata": {},
|
3178 |
+
"source": [
|
3179 |
+
"Follow with : `tensorboard --logdir models/EfficientNetB0/runs`"
|
3180 |
+
]
|
3181 |
+
},
|
3182 |
+
{
|
3183 |
+
"cell_type": "code",
|
3184 |
+
"execution_count": 101,
|
3185 |
+
"metadata": {},
|
3186 |
+
"outputs": [
|
3187 |
{
|
3188 |
"name": "stderr",
|
3189 |
"output_type": "stream",
|
3190 |
"text": [
|
3191 |
+
"INFO:root:⚙️ compiling\n",
|
3192 |
+
"INFO:root:🛎️ declaring callbacks\n",
|
3193 |
+
"INFO:root:💪 starting training\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3194 |
]
|
3195 |
},
|
3196 |
{
|
3197 |
+
"name": "stdout",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3198 |
"output_type": "stream",
|
3199 |
"text": [
|
3200 |
+
"Epoch 1/100\n",
|
3201 |
+
"\u001b[1m 7/1240\u001b[0m \u001b[37m━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[1m36:58\u001b[0m 2s/step - accuracy: 0.4936 - loss: 0.8204 - precision: 0.5297 - recall: 0.5054"
|
3202 |
]
|
3203 |
}
|
3204 |
],
|
3205 |
"source": [
|
3206 |
"model_trained, history = eval_pretrained_model(\n",
|
3207 |
+
" model=model_ready,\n",
|
3208 |
" train_ds=train_ds,\n",
|
3209 |
" val_ds=val_ds,\n",
|
3210 |
" test_ds=test_ds,\n",
|
|
|
3285 |
"cell_type": "markdown",
|
3286 |
"metadata": {},
|
3287 |
"source": [
|
3288 |
+
"## <a id='toc7_4_'></a>[Random Baseline](#toc0_)"
|
3289 |
]
|
3290 |
},
|
3291 |
{
|
|
|
3308 |
"tracker.start_task(\"inference\")"
|
3309 |
]
|
3310 |
},
|
3311 |
+
{
|
3312 |
+
"cell_type": "markdown",
|
3313 |
+
"metadata": {},
|
3314 |
+
"source": [
|
3315 |
+
"# 🚧 INFERENCE"
|
3316 |
+
]
|
3317 |
+
},
|
3318 |
+
{
|
3319 |
+
"cell_type": "code",
|
3320 |
+
"execution_count": null,
|
3321 |
+
"metadata": {},
|
3322 |
+
"outputs": [],
|
3323 |
+
"source": [
|
3324 |
+
"# import keras\n",
|
3325 |
+
"# from keras.applications.resnet50 import ResNet50\n",
|
3326 |
+
"# from keras.applications.resnet50 import preprocess_input, decode_predictions\n",
|
3327 |
+
"# import numpy as np\n",
|
3328 |
+
"\n",
|
3329 |
+
"# model = ResNet50(weights='imagenet')\n",
|
3330 |
+
"\n",
|
3331 |
+
"# img_path = 'elephant.jpg'\n",
|
3332 |
+
"# img = keras.utils.load_img(img_path, target_size=(224, 224))\n",
|
3333 |
+
"# x = keras.utils.img_to_array(img)\n",
|
3334 |
+
"# x = np.expand_dims(x, axis=0)\n",
|
3335 |
+
"# x = preprocess_input(x)\n",
|
3336 |
+
"\n",
|
3337 |
+
"# preds = model.predict(x)\n",
|
3338 |
+
"# # decode the results into a list of tuples (class, description, probability)\n",
|
3339 |
+
"# # (one such list for each sample in the batch)\n",
|
3340 |
+
"# print('Predicted:', decode_predictions(preds, top=3)[0])\n",
|
3341 |
+
"# # Predicted: [(u'n02504013', u'Indian_elephant', 0.82658225), (u'n01871265', u'tusker', 0.1122357), (u'n02504458', u'African_elephant', 0.061040461)]\n"
|
3342 |
+
]
|
3343 |
+
},
|
3344 |
{
|
3345 |
"cell_type": "code",
|
3346 |
"execution_count": 11,
|
README.md
CHANGED
@@ -12,11 +12,10 @@ datasets:
|
|
12 |
|
13 |
# 🚧 TODO
|
14 |
|
15 |
-
- 👉
|
16 |
-
- réduire **n_epochs**
|
17 |
- voir répartition partenaires, caméras, temporalité, annotations
|
18 |
- métriques : **matrice de confusion** complète
|
19 |
-
- décrire
|
20 |
- tester plusieurs pré-entraînements (est-ce que charger un modèle pré-entraîné ImageNet aide vraiment ?)
|
21 |
- tester si amélioration inférence avec et sans égalisation
|
22 |
- voir répartition physique des annotations sur l'image
|
|
|
12 |
|
13 |
# 🚧 TODO
|
14 |
|
15 |
+
- 👉 tester EfficientNetV2M
|
|
|
16 |
- voir répartition partenaires, caméras, temporalité, annotations
|
17 |
- métriques : **matrice de confusion** complète
|
18 |
+
- décrire **erreurs de types et conséquences**
|
19 |
- tester plusieurs pré-entraînements (est-ce que charger un modèle pré-entraîné ImageNet aide vraiment ?)
|
20 |
- tester si amélioration inférence avec et sans égalisation
|
21 |
- voir répartition physique des annotations sur l'image
|
config.yaml
CHANGED
@@ -7,7 +7,9 @@ rdm_seed: 42
|
|
7 |
data_root_dir: "data"
|
8 |
raw_data_dir: "raw"
|
9 |
clr_hf_cache_script_abs_path: './src/clear_hf_cache.sh'
|
10 |
-
|
|
|
|
|
11 |
|
12 |
# Models
|
13 |
models_common:
|
|
|
7 |
data_root_dir: "data"
|
8 |
raw_data_dir: "raw"
|
9 |
clr_hf_cache_script_abs_path: './src/clear_hf_cache.sh'
|
10 |
+
db_raw_info_uri: "data_raw_info.csv"
|
11 |
+
db_keras_info_uri: "data_keras_info.csv"
|
12 |
+
db_aug_info_uri: "data_aug_info.csv"
|
13 |
|
14 |
# Models
|
15 |
models_common:
|
src/load_data.py
CHANGED
@@ -6,13 +6,14 @@ import os
|
|
6 |
import pandas as pd
|
7 |
from PIL import Image, ImageOps, ImageEnhance, ImageFilter
|
8 |
import shutil
|
|
|
9 |
import subprocess
|
10 |
import yaml
|
11 |
|
12 |
|
13 |
-
# Logging
|
14 |
logger = logging.getLogger()
|
15 |
-
logger.setLevel(logging.
|
16 |
|
17 |
# local config
|
18 |
with open("config.yaml", "r") as f:
|
@@ -23,7 +24,9 @@ RDM_SEED = cfg["rdm_seed"]
|
|
23 |
OUTPUT_DIR = cfg["data_root_dir"]
|
24 |
RAW_DATA_DIR = os.path.join(OUTPUT_DIR, cfg["raw_data_dir"])
|
25 |
CLR_CACHE_SCRIPT = cfg["clr_hf_cache_script_abs_path"]
|
26 |
-
|
|
|
|
|
27 |
|
28 |
|
29 |
# Save in Ultralytics format
|
@@ -81,8 +84,8 @@ def load_raw_data():
|
|
81 |
"""Main function for downloading, splitting and formatting data"""
|
82 |
|
83 |
# Check if data information already exists before eventually loading model
|
84 |
-
if os.path.exists(
|
85 |
-
df = pd.read_csv(
|
86 |
return df
|
87 |
|
88 |
# Load data
|
@@ -116,7 +119,7 @@ def load_raw_data():
|
|
116 |
df_train_4 = create_df(ds_train[18000:], "train", RAW_DATA_DIR)
|
117 |
df_val = create_df(ds_val, "val", RAW_DATA_DIR)
|
118 |
df_test = create_df(ds_test, "test", RAW_DATA_DIR)
|
119 |
-
# Save as one
|
120 |
df = pd.concat(
|
121 |
[df_train_1, df_train_2, df_train_3, df_train_4, df_val, df_test],
|
122 |
axis=0,
|
@@ -144,7 +147,8 @@ def load_raw_data():
|
|
144 |
],
|
145 |
]
|
146 |
# Save as CSV
|
147 |
-
|
|
|
148 |
df.to_csv(f)
|
149 |
|
150 |
# Clear HF default cache folder after it is done (6GB)
|
@@ -173,12 +177,14 @@ def format_data_keras(df):
|
|
173 |
logging.warning(f"{OUTPUT_DIR} doesn't exist: (re)load data first")
|
174 |
return df
|
175 |
|
176 |
-
# Create Keras parent folder
|
177 |
-
keras_dir = os.path.join(OUTPUT_DIR, "keras")
|
178 |
# Check if data already exists
|
179 |
-
if os.path.exists(
|
180 |
-
logging.info(f"{
|
|
|
181 |
return df
|
|
|
|
|
|
|
182 |
os.makedirs(keras_dir, exist_ok=True)
|
183 |
# Create splits folders
|
184 |
for split in df.split.unique():
|
@@ -199,11 +205,16 @@ def format_data_keras(df):
|
|
199 |
df.drop(columns="uri", inplace=True)
|
200 |
df.rename(columns={"uri_dest": "uri"}, inplace=True)
|
201 |
|
|
|
|
|
|
|
|
|
|
|
202 |
return df
|
203 |
|
204 |
|
205 |
-
def add_data_aug(aug_name, df_sample,
|
206 |
-
"""Add data augmentation
|
207 |
# Rename images and update URI
|
208 |
df_sample.loc[:, "name"] += f"_DA-{aug_name[:-4]}"
|
209 |
df_sample.rename(columns={'uri': 'input_uri'}, inplace=True)
|
@@ -225,25 +236,32 @@ def add_data_aug(aug_name, df_sample, df_aug):
|
|
225 |
img_aug = img.rotate(180)
|
226 |
else:
|
227 |
logging.warn("Wrong data augmentation name: passing")
|
228 |
-
return
|
229 |
|
230 |
img_aug.save(row['uri'])
|
|
|
|
|
231 |
|
232 |
-
# Add to dataframe
|
233 |
df_sample.drop(columns='input_uri', inplace=True)
|
234 |
-
result = pd.concat([df_aug, df_sample], axis=0, ignore_index=True)
|
235 |
|
236 |
-
logging.
|
237 |
|
238 |
-
return
|
239 |
|
240 |
|
241 |
def oversample_class(df):
|
242 |
"""Oversample an under-represented class"""
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
count_df = df.groupby(["split", "label"]).size().reset_index(name="count")
|
244 |
count_df = count_df.loc[count_df["split"] != "test"]
|
245 |
|
246 |
df_aug = df.copy()
|
|
|
247 |
|
248 |
for split in count_df.split.unique():
|
249 |
logging.info(f"⚙️ Processing {split} split...")
|
@@ -251,27 +269,52 @@ def oversample_class(df):
|
|
251 |
# Minimum label
|
252 |
idxmin = _["count"].idxmin()
|
253 |
min_row = _.loc[idxmin, :]
|
254 |
-
min_label = min_row["label"]
|
255 |
min_count = min_row["count"]
|
|
|
256 |
# Maximum label
|
257 |
idxmax = _["count"].idxmax()
|
258 |
max_row = _.loc[idxmax, :]
|
259 |
max_count = max_row["count"]
|
|
|
260 |
# Needed labels
|
261 |
need = max_count - min_count
|
262 |
|
263 |
-
logging.info(f"
|
|
|
264 |
|
265 |
# Loop over augmentation techniques until need is covered
|
266 |
for aug_name in ["blur_img", "flip_img", "blur_flip_img", "eq_img", "180_img"]:
|
267 |
-
|
268 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
269 |
|
270 |
-
|
271 |
-
|
|
|
|
|
272 |
|
273 |
-
|
274 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
|
276 |
return df_aug
|
277 |
|
|
|
6 |
import pandas as pd
|
7 |
from PIL import Image, ImageOps, ImageEnhance, ImageFilter
|
8 |
import shutil
|
9 |
+
from sklearn.model_selection import train_test_split
|
10 |
import subprocess
|
11 |
import yaml
|
12 |
|
13 |
|
14 |
+
# Logging outputs config (DEBUG < INFO)
|
15 |
logger = logging.getLogger()
|
16 |
+
logger.setLevel(logging.DEBUG)
|
17 |
|
18 |
# local config
|
19 |
with open("config.yaml", "r") as f:
|
|
|
24 |
OUTPUT_DIR = cfg["data_root_dir"]
|
25 |
RAW_DATA_DIR = os.path.join(OUTPUT_DIR, cfg["raw_data_dir"])
|
26 |
CLR_CACHE_SCRIPT = cfg["clr_hf_cache_script_abs_path"]
|
27 |
+
DB_RAW_INFO_URI = os.path.join(OUTPUT_DIR, cfg["db_raw_info_uri"])
|
28 |
+
DB_KERAS_INFO_URI = os.path.join(OUTPUT_DIR, cfg["db_keras_info_uri"])
|
29 |
+
DB_AUG_INFO_URI = os.path.join(OUTPUT_DIR, cfg["db_aug_info_uri"])
|
30 |
|
31 |
|
32 |
# Save in Ultralytics format
|
|
|
84 |
"""Main function for downloading, splitting and formatting data"""
|
85 |
|
86 |
# Check if data information already exists before eventually loading model
|
87 |
+
if os.path.exists(DB_RAW_INFO_URI):
|
88 |
+
df = pd.read_csv(DB_RAW_INFO_URI, index_col=0)
|
89 |
return df
|
90 |
|
91 |
# Load data
|
|
|
119 |
df_train_4 = create_df(ds_train[18000:], "train", RAW_DATA_DIR)
|
120 |
df_val = create_df(ds_val, "val", RAW_DATA_DIR)
|
121 |
df_test = create_df(ds_test, "test", RAW_DATA_DIR)
|
122 |
+
# Save as one dataframe
|
123 |
df = pd.concat(
|
124 |
[df_train_1, df_train_2, df_train_3, df_train_4, df_val, df_test],
|
125 |
axis=0,
|
|
|
147 |
],
|
148 |
]
|
149 |
# Save as CSV
|
150 |
+
logging.info(f"Dataframe saved in: {DB_RAW_INFO_URI}")
|
151 |
+
with open(DB_RAW_INFO_URI, "wb") as f:
|
152 |
df.to_csv(f)
|
153 |
|
154 |
# Clear HF default cache folder after it is done (6GB)
|
|
|
177 |
logging.warning(f"{OUTPUT_DIR} doesn't exist: (re)load data first")
|
178 |
return df
|
179 |
|
|
|
|
|
180 |
# Check if data already exists
|
181 |
+
if os.path.exists(DB_KERAS_INFO_URI):
|
182 |
+
logging.info(f"{DB_KERAS_INFO_URI} already exists: data already formatted")
|
183 |
+
df = pd.read_csv(DB_KERAS_INFO_URI, index_col=0)
|
184 |
return df
|
185 |
+
|
186 |
+
# Create Keras parent folder
|
187 |
+
keras_dir = os.path.join(OUTPUT_DIR, "keras")
|
188 |
os.makedirs(keras_dir, exist_ok=True)
|
189 |
# Create splits folders
|
190 |
for split in df.split.unique():
|
|
|
205 |
df.drop(columns="uri", inplace=True)
|
206 |
df.rename(columns={"uri_dest": "uri"}, inplace=True)
|
207 |
|
208 |
+
# Save as CSV
|
209 |
+
logging.info(f"Dataframe saved in: {DB_KERAS_INFO_URI}")
|
210 |
+
with open(DB_KERAS_INFO_URI, "wb") as f:
|
211 |
+
df.to_csv(f)
|
212 |
+
|
213 |
return df
|
214 |
|
215 |
|
216 |
+
def add_data_aug(aug_name, df_sample, replace=False):
|
217 |
+
"""Add data augmentation to a ataframe sample"""
|
218 |
# Rename images and update URI
|
219 |
df_sample.loc[:, "name"] += f"_DA-{aug_name[:-4]}"
|
220 |
df_sample.rename(columns={'uri': 'input_uri'}, inplace=True)
|
|
|
236 |
img_aug = img.rotate(180)
|
237 |
else:
|
238 |
logging.warn("Wrong data augmentation name: passing")
|
239 |
+
return None
|
240 |
|
241 |
img_aug.save(row['uri'])
|
242 |
+
if replace:
|
243 |
+
os.remove(row['input_uri'])
|
244 |
|
|
|
245 |
df_sample.drop(columns='input_uri', inplace=True)
|
|
|
246 |
|
247 |
+
logging.debug(f"\t✅ Transformed {len(df_sample)} images with {aug_name} (replace={replace})")
|
248 |
|
249 |
+
return df_sample
|
250 |
|
251 |
|
252 |
def oversample_class(df):
|
253 |
"""Oversample an under-represented class"""
|
254 |
+
# Check if data already exists
|
255 |
+
if os.path.exists(DB_AUG_INFO_URI):
|
256 |
+
logging.info(f"{DB_AUG_INFO_URI} already exists: data already formatted")
|
257 |
+
df = pd.read_csv(DB_AUG_INFO_URI, index_col=0)
|
258 |
+
return df
|
259 |
+
|
260 |
count_df = df.groupby(["split", "label"]).size().reset_index(name="count")
|
261 |
count_df = count_df.loc[count_df["split"] != "test"]
|
262 |
|
263 |
df_aug = df.copy()
|
264 |
+
df_aug.loc[:, "augmented"] = False
|
265 |
|
266 |
for split in count_df.split.unique():
|
267 |
logging.info(f"⚙️ Processing {split} split...")
|
|
|
269 |
# Minimum label
|
270 |
idxmin = _["count"].idxmin()
|
271 |
min_row = _.loc[idxmin, :]
|
|
|
272 |
min_count = min_row["count"]
|
273 |
+
min_label = min_row["label"]
|
274 |
# Maximum label
|
275 |
idxmax = _["count"].idxmax()
|
276 |
max_row = _.loc[idxmax, :]
|
277 |
max_count = max_row["count"]
|
278 |
+
max_label = max_row["label"]
|
279 |
# Needed labels
|
280 |
need = max_count - min_count
|
281 |
|
282 |
+
logging.info(f"Min class count = {min_count} ; Max class count = {max_count}")
|
283 |
+
logging.info(f"⚙️ Transforming {need} images...\n")
|
284 |
|
285 |
# Loop over augmentation techniques until need is covered
|
286 |
for aug_name in ["blur_img", "flip_img", "blur_flip_img", "eq_img", "180_img"]:
|
287 |
+
logging.info(f"\tApplying {aug_name[:-4]}")
|
288 |
+
if need <= 0:
|
289 |
+
break
|
290 |
+
|
291 |
+
# Prepare data samples to apply image transformation
|
292 |
+
df_sample_min = df.loc[(df["split"] == split) & (df["label"] == min_label)].iloc[:need].copy()
|
293 |
+
|
294 |
+
df_sample_max_full = df_aug.loc[(df_aug["split"] == split) & (df_aug["label"] == max_label) & (df_aug["augmented"] == False)].copy()
|
295 |
+
_, df_sample_max = train_test_split(df_sample_max_full, test_size=len(df_sample_min), random_state=RDM_SEED)
|
296 |
+
df_aug = df_aug[~df_aug['uri'].isin(df_sample_max['uri'])]
|
297 |
|
298 |
+
# Apply data augmentation for smaller class
|
299 |
+
df_sample_min_transf = add_data_aug(aug_name, df_sample_min)
|
300 |
+
if df_sample_min_transf is not None:
|
301 |
+
df_aug = pd.concat([df_aug, df_sample_min_transf], axis=0, ignore_index=True)
|
302 |
|
303 |
+
# Apply data quality balance by samely transforming most frequent class
|
304 |
+
df_sample_max_transf = add_data_aug(aug_name, df_sample_max, replace=True)
|
305 |
+
df_sample_max_transf.loc[:, "augmented"] = True
|
306 |
+
df_aug = pd.concat([df_aug, df_sample_max_transf], axis=0, ignore_index=True)
|
307 |
+
|
308 |
+
need -= len(df_sample_min_transf)
|
309 |
+
|
310 |
+
df_aug.drop(columns='augmented', inplace=True)
|
311 |
+
|
312 |
+
logging.info(f"Augmented dataframe shape = {df_aug.shape}\n")
|
313 |
+
|
314 |
+
# Save as CSV
|
315 |
+
logging.info(f"Dataframe saved in: {DB_AUG_INFO_URI}")
|
316 |
+
with open(DB_AUG_INFO_URI, "wb") as f:
|
317 |
+
df_aug.to_csv(f)
|
318 |
|
319 |
return df_aug
|
320 |
|