ParthGoyal974 commited on
Commit
f275200
1 Parent(s): 518f367

Upload 2 files

Browse files
Files changed (2) hide show
  1. Documentation.txt +54 -0
  2. Final Model.ipynb +392 -0
Documentation.txt ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Image Classifier Documentation
2
+
3
+ ## Introduction
4
+
5
+ This documentation outlines the steps involved in building and training an image classifier using TensorFlow. The classifier is designed to classify images into two categories: "pepe" and "not pepe". The classifier is trained using a dataset consisting of images of both categories.
6
+
7
+ ## Requirements
8
+
9
+ - TensorFlow
10
+ - OpenCV (cv2)
11
+ - Matplotlib
12
+ - NumPy
13
+ - imghdr
14
+ - scikit-learn (for evaluation metrics)
15
+
16
+ ## Data Collection and Preprocessing
17
+
18
+ 1. **Data Augmentation**: The dataset is augmented using the `ImageDataGenerator` from TensorFlow's `preprocessing.image` module. Augmentation techniques include rotation, shifting, shearing, zooming, and flipping.
19
+
20
+ 2. **Data Validation**: Images are validated for compatibility with the dataset. Images with extensions other than JPEG, JPG, BMP, and PNG are removed. Corrupted images are removed from the dataset.
21
+
22
+ 3. **Data Loading**: The augmented dataset is loaded using `tf.keras.utils.image_dataset_from_directory`. This function creates a TensorFlow dataset from image files arranged in directories corresponding to class labels.
23
+
24
+ 4. **Data Splitting**: The dataset is split into training, validation, and test sets using TensorFlow's dataset manipulation functions.
25
+
26
+ ## Model Architecture
27
+
28
+ The image classifier model consists of several layers:
29
+
30
+ - Input Layer: Accepts images of size 256x256 pixels with 3 color channels.
31
+ - Convolutional Layers: Three sets of convolutional layers with batch normalization and max-pooling.
32
+ - Flatten Layer: Flattens the output from convolutional layers.
33
+ - Dense Layers: Two dense layers with ReLU activation.
34
+ - Output Layer: Dense layer with a sigmoid activation function for binary classification.
35
+
36
+ ## Model Training
37
+
38
+ The model is compiled using the Adam optimizer with a specified learning rate and binary cross-entropy loss function. Training is performed for a fixed number of epochs, with validation data used to monitor model performance and prevent overfitting.
39
+
40
+ ## Evaluation Metrics
41
+
42
+ - **Precision**: Precision is calculated as the ratio of true positives to the sum of true positives and false positives. It measures the accuracy of positive predictions.
43
+ - **Recall**: Recall is calculated as the ratio of true positives to the sum of true positives and false negatives. It measures the ability of the model to identify positive instances.
44
+ - **Binary Accuracy**: Binary accuracy calculates the accuracy of binary predictions.
45
+
46
+ The F1 score, which is the harmonic mean of precision and recall, is also calculated as an evaluation metric.
47
+
48
+ ## Test Loss and Visualization
49
+
50
+ The test loss and additional evaluation metrics are computed using the trained model on the test dataset. The loss curves (training loss and validation loss) are plotted to visualize the model's performance during training.
51
+
52
+ ## Conclusion
53
+
54
+ This documentation provides an overview of the image classifier built using TensorFlow. It outlines the steps involved in data collection, preprocessing, model architecture, training, and evaluation. By following these steps, users can train and evaluate their own image classifiers for various applications.
Final Model.ipynb ADDED
@@ -0,0 +1,392 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "85dcc51c",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "import tensorflow as tf\n",
11
+ "import os\n",
12
+ "import cv2\n",
13
+ "import imghdr\n",
14
+ "import numpy as np\n",
15
+ "from matplotlib import pyplot as plt"
16
+ ]
17
+ },
18
+ {
19
+ "cell_type": "code",
20
+ "execution_count": null,
21
+ "id": "945cdd4c",
22
+ "metadata": {},
23
+ "outputs": [],
24
+ "source": [
25
+ "#To create augmented dataset and store it locally\n",
26
+ "#DONOT RUN THIS NOW THAT THE AUGMENTED DATASET HAS ALREADY BEEN CREATED\n",
27
+ "ans=input(\"Are you sure you want to run this(y/n): \")\n",
28
+ "if(ans==\"y\"): \n",
29
+ " from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
30
+ " datagen = ImageDataGenerator(\n",
31
+ " rotation_range=45, \n",
32
+ " width_shift_range=0.2, \n",
33
+ " height_shift_range=0.2,\n",
34
+ " shear_range=0.2,\n",
35
+ " zoom_range=0.2,\n",
36
+ " horizontal_flip=True,\n",
37
+ " fill_mode='nearest')\n",
38
+ "\n",
39
+ " i = 0\n",
40
+ " for batch in datagen.flow_from_directory(directory=\"pepe_folder\", \n",
41
+ " batch_size=20, \n",
42
+ " target_size=(256, 256),\n",
43
+ " color_mode=\"rgb\",\n",
44
+ " save_to_dir=r'data\\aug_pepe', \n",
45
+ " save_prefix='aug', \n",
46
+ " save_format='png'):\n",
47
+ " i += 1\n",
48
+ " if i > 60:\n",
49
+ " break\n",
50
+ "\n",
51
+ " i = 0\n",
52
+ " for batch in datagen.flow_from_directory(directory=\"notpepe_folder\", \n",
53
+ " batch_size=20, \n",
54
+ " target_size=(256, 256),\n",
55
+ " color_mode=\"rgb\",\n",
56
+ " save_to_dir=r'data\\aug_notpepe', \n",
57
+ " save_prefix='aug', \n",
58
+ " save_format='png'):\n",
59
+ " i += 1\n",
60
+ " if i > 60:\n",
61
+ " break"
62
+ ]
63
+ },
64
+ {
65
+ "cell_type": "code",
66
+ "execution_count": null,
67
+ "id": "b27e514f",
68
+ "metadata": {},
69
+ "outputs": [],
70
+ "source": [
71
+ "#to retrieve augmented dataset and remove corrupted files from it\n",
72
+ "data_dir = 'data' \n",
73
+ "image_exts = ['jpeg','jpg', 'bmp', 'png']\n",
74
+ "for image_class in os.listdir(data_dir): \n",
75
+ " for image in os.listdir(os.path.join(data_dir, image_class)):\n",
76
+ " image_path = os.path.join(data_dir, image_class, image)\n",
77
+ " try: \n",
78
+ " img = cv2.imread(image_path)\n",
79
+ " tip = imghdr.what(image_path)\n",
80
+ " if tip not in image_exts: \n",
81
+ " print('Image not in ext list {}'.format(image_path))\n",
82
+ " os.remove(image_path)\n",
83
+ " except Exception as e: \n",
84
+ " print('Issue with image {}'.format(image_path))"
85
+ ]
86
+ },
87
+ {
88
+ "cell_type": "code",
89
+ "execution_count": null,
90
+ "id": "75b52f06",
91
+ "metadata": {},
92
+ "outputs": [],
93
+ "source": [
94
+ "predata = tf.keras.utils.image_dataset_from_directory('data')"
95
+ ]
96
+ },
97
+ {
98
+ "cell_type": "code",
99
+ "execution_count": null,
100
+ "id": "e1d8486d",
101
+ "metadata": {},
102
+ "outputs": [],
103
+ "source": [
104
+ "data_iterator = predata.as_numpy_iterator()\n",
105
+ "batch = data_iterator.next()"
106
+ ]
107
+ },
108
+ {
109
+ "cell_type": "code",
110
+ "execution_count": null,
111
+ "id": "81675bd7",
112
+ "metadata": {},
113
+ "outputs": [],
114
+ "source": [
115
+ "#to view a sample batch and verify the labels\n",
116
+ "fig, ax = plt.subplots(ncols=4, figsize=(20,20))\n",
117
+ "for idx, img in enumerate(batch[0][:4]):\n",
118
+ " ax[idx].imshow(img.astype(int))\n",
119
+ " ax[idx].title.set_text(batch[1][idx])\n"
120
+ ]
121
+ },
122
+ {
123
+ "cell_type": "code",
124
+ "execution_count": null,
125
+ "id": "e55af779",
126
+ "metadata": {},
127
+ "outputs": [],
128
+ "source": [
129
+ "#scaling the images\n",
130
+ "data = predata.map(lambda x,y: (x/255, y))"
131
+ ]
132
+ },
133
+ {
134
+ "cell_type": "code",
135
+ "execution_count": null,
136
+ "id": "91ca596a",
137
+ "metadata": {},
138
+ "outputs": [],
139
+ "source": [
140
+ "#splitting the dataset into training, validation and testing\n",
141
+ "train_size = int(len(data)*.7)\n",
142
+ "val_size = int(len(data)*.2)+1\n",
143
+ "test_size = int(len(data)*.1)\n",
144
+ "train = data.take(train_size)\n",
145
+ "val = data.skip(train_size).take(val_size)\n",
146
+ "test = data.skip(train_size+val_size).take(test_size)"
147
+ ]
148
+ },
149
+ {
150
+ "cell_type": "code",
151
+ "execution_count": null,
152
+ "id": "75fd8b96",
153
+ "metadata": {},
154
+ "outputs": [],
155
+ "source": [
156
+ "from tensorflow.keras.models import Sequential\n",
157
+ "from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten,BatchNormalization,Input"
158
+ ]
159
+ },
160
+ {
161
+ "cell_type": "code",
162
+ "execution_count": null,
163
+ "id": "f2eb4c6d",
164
+ "metadata": {},
165
+ "outputs": [],
166
+ "source": [
167
+ "#building the model architecture\n",
168
+ "model = Sequential()\n",
169
+ "model.add(Input(shape=(256, 256, 3)))\n",
170
+ "model.add(Conv2D(16, (3, 3), strides=1, activation='relu'))\n",
171
+ "model.add(BatchNormalization())\n",
172
+ "model.add(MaxPooling2D())\n",
173
+ "\n",
174
+ "model.add(Conv2D(32, (3, 3), strides=1, activation='relu'))\n",
175
+ "model.add(BatchNormalization())\n",
176
+ "model.add(MaxPooling2D())\n",
177
+ "\n",
178
+ "model.add(Conv2D(16, (3, 3), strides=1, activation='relu'))\n",
179
+ "model.add(MaxPooling2D())\n",
180
+ "\n",
181
+ "model.add(Flatten())\n",
182
+ "model.add(Dense(256, activation='relu'))\n",
183
+ "model.add(Dense(1, activation='sigmoid'))\n",
184
+ "\n",
185
+ "from tensorflow.keras.optimizers import Adam\n",
186
+ "\n",
187
+ "learning_rate = 0.0006\n",
188
+ "optimizer = Adam(learning_rate=learning_rate)\n",
189
+ "\n",
190
+ "model.compile(optimizer=optimizer, loss=tf.losses.BinaryCrossentropy(), metrics=['accuracy'])"
191
+ ]
192
+ },
193
+ {
194
+ "cell_type": "code",
195
+ "execution_count": null,
196
+ "id": "7c639b2c",
197
+ "metadata": {},
198
+ "outputs": [],
199
+ "source": [
200
+ "#to view the model summary\n",
201
+ "model.summary()"
202
+ ]
203
+ },
204
+ {
205
+ "cell_type": "code",
206
+ "execution_count": null,
207
+ "id": "99a49621",
208
+ "metadata": {},
209
+ "outputs": [],
210
+ "source": [
211
+ "#saving logs\n",
212
+ "logdir='logs'\n",
213
+ "tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=logdir)"
214
+ ]
215
+ },
216
+ {
217
+ "cell_type": "code",
218
+ "execution_count": null,
219
+ "id": "5c550f6f",
220
+ "metadata": {},
221
+ "outputs": [],
222
+ "source": [
223
+ "hist = model.fit(train, epochs=10, validation_data=val, callbacks=[tensorboard_callback])\n"
224
+ ]
225
+ },
226
+ {
227
+ "cell_type": "code",
228
+ "execution_count": null,
229
+ "id": "d19ccb13",
230
+ "metadata": {},
231
+ "outputs": [],
232
+ "source": [
233
+ "from tensorflow.keras.metrics import Precision, Recall, BinaryAccuracy"
234
+ ]
235
+ },
236
+ {
237
+ "cell_type": "code",
238
+ "execution_count": null,
239
+ "id": "d6237387",
240
+ "metadata": {},
241
+ "outputs": [],
242
+ "source": [
243
+ "#calculating precision, recall and binary accuracy\n",
244
+ "pre = Precision()\n",
245
+ "re = Recall()\n",
246
+ "acc = BinaryAccuracy()\n",
247
+ "for batch in test.as_numpy_iterator(): \n",
248
+ " X, y = batch\n",
249
+ " yhat = model.predict(X)\n",
250
+ " pre.update_state(y, yhat)\n",
251
+ " re.update_state(y, yhat)\n",
252
+ " acc.update_state(y, yhat)\n",
253
+ "print(pre.result(), re.result(), acc.result())"
254
+ ]
255
+ },
256
+ {
257
+ "cell_type": "code",
258
+ "execution_count": null,
259
+ "id": "2db17093",
260
+ "metadata": {},
261
+ "outputs": [],
262
+ "source": [
263
+ "#calculating the F1 score and test accuracy\n",
264
+ "from sklearn.metrics import f1_score\n",
265
+ "test_images = []\n",
266
+ "test_labels = []\n",
267
+ "\n",
268
+ "for image, label in test:\n",
269
+ " test_images.append(image)\n",
270
+ " test_labels.append(label)\n",
271
+ "\n",
272
+ "test_images = tf.concat(test_images, axis=0)\n",
273
+ "test_labels = tf.concat(test_labels, axis=0)\n",
274
+ "\n",
275
+ "\n",
276
+ "y_pred = model.predict(test_images)\n",
277
+ "y_pred_binary = (y_pred > 0.5).astype(int) \n",
278
+ "y_true = test_labels \n",
279
+ "\n",
280
+ "\n",
281
+ "f1 = f1_score(y_true, y_pred_binary)\n",
282
+ "\n",
283
+ "print(\"F1 Score:\", f1)\n",
284
+ "test_loss = model.evaluate(test)\n",
285
+ "print(\"Test Loss:\", test_loss)"
286
+ ]
287
+ },
288
+ {
289
+ "cell_type": "code",
290
+ "execution_count": null,
291
+ "id": "b937369d",
292
+ "metadata": {},
293
+ "outputs": [],
294
+ "source": [
295
+ "#plotting the losses\n",
296
+ "fig = plt.figure()\n",
297
+ "plt.plot(hist.history['loss'], color='teal', label='Training Loss')\n",
298
+ "plt.plot(hist.history['val_loss'], color='orange', label='Validation Loss')\n",
299
+ "\n",
300
+ "\n",
301
+ "plt.axhline(y=test_loss[0], color='red', linestyle='--', label='Test Loss')\n",
302
+ "\n",
303
+ "fig.suptitle('Loss', fontsize=20)\n",
304
+ "plt.legend(loc=\"upper left\")\n",
305
+ "plt.show()"
306
+ ]
307
+ },
308
+ {
309
+ "cell_type": "code",
310
+ "execution_count": null,
311
+ "id": "618e8ed4",
312
+ "metadata": {},
313
+ "outputs": [],
314
+ "source": [
315
+ "for i in range(13):\n",
316
+ " img = cv2.imread(f\"C:/Users/91896/Desktop/not/OIP ({i}).jpeg\")\n",
317
+ " plt.imshow(img)\n",
318
+ " resize = tf.image.resize(img, (256,256))\n",
319
+ " plt.imshow(resize.numpy().astype(int))\n",
320
+ " plt.show()\n",
321
+ " yhat = model.predict(np.expand_dims(resize/255, 0))\n",
322
+ " yhat\n",
323
+ " if yhat > 0.5: \n",
324
+ " print(f'Pepe Found')\n",
325
+ " else:\n",
326
+ " print(f'Pepe Not Found')"
327
+ ]
328
+ },
329
+ {
330
+ "cell_type": "code",
331
+ "execution_count": 1,
332
+ "id": "a453a1ec",
333
+ "metadata": {},
334
+ "outputs": [
335
+ {
336
+ "ename": "NameError",
337
+ "evalue": "name 'model' is not defined",
338
+ "output_type": "error",
339
+ "traceback": [
340
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
341
+ "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",
342
+ "Cell \u001b[1;32mIn[1], line 4\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtensorflow\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mkeras\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodels\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m load_model\n\u001b[0;32m 3\u001b[0m \u001b[38;5;66;03m# Saving the model\u001b[39;00m\n\u001b[1;32m----> 4\u001b[0m model\u001b[38;5;241m.\u001b[39msave(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mimageclassifier.keras\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
343
+ "\u001b[1;31mNameError\u001b[0m: name 'model' is not defined"
344
+ ]
345
+ }
346
+ ],
347
+ "source": [
348
+ "from tensorflow.keras.models import load_model\n",
349
+ "\n",
350
+ "# Saving the model\n",
351
+ "model.save('imageclassifier.keras')"
352
+ ]
353
+ },
354
+ {
355
+ "cell_type": "code",
356
+ "execution_count": null,
357
+ "id": "9df6180d",
358
+ "metadata": {},
359
+ "outputs": [],
360
+ "source": []
361
+ },
362
+ {
363
+ "cell_type": "code",
364
+ "execution_count": null,
365
+ "id": "aaac6285",
366
+ "metadata": {},
367
+ "outputs": [],
368
+ "source": []
369
+ }
370
+ ],
371
+ "metadata": {
372
+ "kernelspec": {
373
+ "display_name": "Python 3 (ipykernel)",
374
+ "language": "python",
375
+ "name": "python3"
376
+ },
377
+ "language_info": {
378
+ "codemirror_mode": {
379
+ "name": "ipython",
380
+ "version": 3
381
+ },
382
+ "file_extension": ".py",
383
+ "mimetype": "text/x-python",
384
+ "name": "python",
385
+ "nbconvert_exporter": "python",
386
+ "pygments_lexer": "ipython3",
387
+ "version": "3.11.4"
388
+ }
389
+ },
390
+ "nbformat": 4,
391
+ "nbformat_minor": 5
392
+ }