\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Data generators\n",
+ "train_datagen = ImageDataGenerator(\n",
+ " rescale=1./255,\n",
+ " rotation_range=30,\n",
+ " shear_range=0.3,\n",
+ " zoom_range=0.3,\n",
+ " horizontal_flip=True,\n",
+ " fill_mode='nearest'\n",
+ ")\n",
+ "\n",
+ "validation_datagen = ImageDataGenerator(rescale=1./255)\n",
+ "\n",
+ "train_generator = train_datagen.flow_from_directory(\n",
+ " train_data_dir,\n",
+ " color_mode='grayscale',\n",
+ " target_size=(48, 48),\n",
+ " batch_size=32,\n",
+ " class_mode='categorical',\n",
+ " shuffle=True\n",
+ ")\n",
+ "\n",
+ "validation_generator = validation_datagen.flow_from_directory(\n",
+ " validation_data_dir,\n",
+ " color_mode='grayscale',\n",
+ " target_size=(48, 48),\n",
+ " batch_size=32,\n",
+ " class_mode='categorical',\n",
+ " shuffle=True\n",
+ ")\n",
+ "\n",
+ "# Print generator information\n",
+ "print(\"Train Generator:\", train_generator)\n",
+ "print(\"Validation Generator:\", validation_generator)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "c:\\Users\\HomePC\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\keras\\src\\layers\\convolutional\\base_conv.py:107: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.\n",
+ " super().__init__(activity_regularizer=activity_regularizer, **kwargs)\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "Model: \"sequential_3\"\n",
+ "
\n"
+ ],
+ "text/plain": [
+ "\u001b[1mModel: \"sequential_3\"\u001b[0m\n"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
+ "┃ Layer (type) ┃ Output Shape ┃ Param # ┃\n",
+ "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
+ "│ conv2d_12 (Conv2D) │ (None, 46, 46, 64) │ 640 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ batch_normalization_12 │ (None, 46, 46, 64) │ 256 │\n",
+ "│ (BatchNormalization) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ leaky_re_lu_12 (LeakyReLU) │ (None, 46, 46, 64) │ 0 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ conv2d_13 (Conv2D) │ (None, 44, 44, 128) │ 73,856 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ batch_normalization_13 │ (None, 44, 44, 128) │ 512 │\n",
+ "│ (BatchNormalization) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ leaky_re_lu_13 (LeakyReLU) │ (None, 44, 44, 128) │ 0 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ max_pooling2d_9 (MaxPooling2D) │ (None, 22, 22, 128) │ 0 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ spatial_dropout2d_9 │ (None, 22, 22, 128) │ 0 │\n",
+ "│ (SpatialDropout2D) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ conv2d_14 (Conv2D) │ (None, 20, 20, 256) │ 295,168 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ batch_normalization_14 │ (None, 20, 20, 256) │ 1,024 │\n",
+ "│ (BatchNormalization) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ leaky_re_lu_14 (LeakyReLU) │ (None, 20, 20, 256) │ 0 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ max_pooling2d_10 (MaxPooling2D) │ (None, 10, 10, 256) │ 0 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ spatial_dropout2d_10 │ (None, 10, 10, 256) │ 0 │\n",
+ "│ (SpatialDropout2D) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ conv2d_15 (Conv2D) │ (None, 8, 8, 512) │ 1,180,160 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ batch_normalization_15 │ (None, 8, 8, 512) │ 2,048 │\n",
+ "│ (BatchNormalization) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ leaky_re_lu_15 (LeakyReLU) │ (None, 8, 8, 512) │ 0 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ max_pooling2d_11 (MaxPooling2D) │ (None, 4, 4, 512) │ 0 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ spatial_dropout2d_11 │ (None, 4, 4, 512) │ 0 │\n",
+ "│ (SpatialDropout2D) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ flatten_3 (Flatten) │ (None, 8192) │ 0 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ dense_6 (Dense) │ (None, 512) │ 4,194,816 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ dropout_3 (Dropout) │ (None, 512) │ 0 │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ dense_7 (Dense) │ (None, 7) │ 3,591 │\n",
+ "└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
+ "
\n"
+ ],
+ "text/plain": [
+ "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
+ "┃\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┃\n",
+ "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
+ "│ conv2d_12 (\u001b[38;5;33mConv2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m46\u001b[0m, \u001b[38;5;34m46\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m640\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ batch_normalization_12 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m46\u001b[0m, \u001b[38;5;34m46\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m256\u001b[0m │\n",
+ "│ (\u001b[38;5;33mBatchNormalization\u001b[0m) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ leaky_re_lu_12 (\u001b[38;5;33mLeakyReLU\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m46\u001b[0m, \u001b[38;5;34m46\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ conv2d_13 (\u001b[38;5;33mConv2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m44\u001b[0m, \u001b[38;5;34m44\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m73,856\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ batch_normalization_13 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m44\u001b[0m, \u001b[38;5;34m44\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m512\u001b[0m │\n",
+ "│ (\u001b[38;5;33mBatchNormalization\u001b[0m) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ leaky_re_lu_13 (\u001b[38;5;33mLeakyReLU\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m44\u001b[0m, \u001b[38;5;34m44\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ max_pooling2d_9 (\u001b[38;5;33mMaxPooling2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m22\u001b[0m, \u001b[38;5;34m22\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ spatial_dropout2d_9 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m22\u001b[0m, \u001b[38;5;34m22\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "│ (\u001b[38;5;33mSpatialDropout2D\u001b[0m) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ conv2d_14 (\u001b[38;5;33mConv2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m20\u001b[0m, \u001b[38;5;34m20\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m295,168\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ batch_normalization_14 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m20\u001b[0m, \u001b[38;5;34m20\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m1,024\u001b[0m │\n",
+ "│ (\u001b[38;5;33mBatchNormalization\u001b[0m) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ leaky_re_lu_14 (\u001b[38;5;33mLeakyReLU\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m20\u001b[0m, \u001b[38;5;34m20\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ max_pooling2d_10 (\u001b[38;5;33mMaxPooling2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m10\u001b[0m, \u001b[38;5;34m10\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ spatial_dropout2d_10 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m10\u001b[0m, \u001b[38;5;34m10\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "│ (\u001b[38;5;33mSpatialDropout2D\u001b[0m) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ conv2d_15 (\u001b[38;5;33mConv2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m8\u001b[0m, \u001b[38;5;34m8\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m1,180,160\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ batch_normalization_15 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m8\u001b[0m, \u001b[38;5;34m8\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m2,048\u001b[0m │\n",
+ "│ (\u001b[38;5;33mBatchNormalization\u001b[0m) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ leaky_re_lu_15 (\u001b[38;5;33mLeakyReLU\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m8\u001b[0m, \u001b[38;5;34m8\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ max_pooling2d_11 (\u001b[38;5;33mMaxPooling2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m4\u001b[0m, \u001b[38;5;34m4\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ spatial_dropout2d_11 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m4\u001b[0m, \u001b[38;5;34m4\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "│ (\u001b[38;5;33mSpatialDropout2D\u001b[0m) │ │ │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ flatten_3 (\u001b[38;5;33mFlatten\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m8192\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ dense_6 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m4,194,816\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ dropout_3 (\u001b[38;5;33mDropout\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
+ "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+ "│ dense_7 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m7\u001b[0m) │ \u001b[38;5;34m3,591\u001b[0m │\n",
+ "└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ " Total params: 5,752,071 (21.94 MB)\n",
+ "
\n"
+ ],
+ "text/plain": [
+ "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m5,752,071\u001b[0m (21.94 MB)\n"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ " Trainable params: 5,750,151 (21.94 MB)\n",
+ "
\n"
+ ],
+ "text/plain": [
+ "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m5,750,151\u001b[0m (21.94 MB)\n"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ " Non-trainable params: 1,920 (7.50 KB)\n",
+ "
\n"
+ ],
+ "text/plain": [
+ "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m1,920\u001b[0m (7.50 KB)\n"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "None\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Model definition\n",
+ "model = Sequential()\n",
+ "model.add(Conv2D(64, kernel_size=(3, 3), kernel_regularizer=l2(0.01), input_shape=(48, 48, 1)))\n",
+ "model.add(BatchNormalization())\n",
+ "model.add(LeakyReLU())\n",
+ "model.add(Conv2D(128, kernel_size=(3, 3), kernel_regularizer=l2(0.01)))\n",
+ "model.add(BatchNormalization())\n",
+ "model.add(LeakyReLU())\n",
+ "model.add(MaxPooling2D(pool_size=(2, 2)))\n",
+ "model.add(SpatialDropout2D(0.3))\n",
+ "\n",
+ "model.add(Conv2D(256, kernel_size=(3, 3), kernel_regularizer=l2(0.01)))\n",
+ "model.add(BatchNormalization())\n",
+ "model.add(LeakyReLU())\n",
+ "model.add(MaxPooling2D(pool_size=(2, 2)))\n",
+ "model.add(SpatialDropout2D(0.4))\n",
+ "\n",
+ "model.add(Conv2D(512, kernel_size=(3, 3), kernel_regularizer=l2(0.01)))\n",
+ "model.add(BatchNormalization())\n",
+ "model.add(LeakyReLU())\n",
+ "model.add(MaxPooling2D(pool_size=(2, 2)))\n",
+ "model.add(SpatialDropout2D(0.5))\n",
+ "\n",
+ "model.add(Flatten())\n",
+ "model.add(Dense(512, activation='relu', kernel_regularizer=l2(0.01)))\n",
+ "model.add(Dropout(0.5))\n",
+ "model.add(Dense(7, activation='softmax'))\n",
+ "\n",
+ "nadam = tf.keras.optimizers.Nadam(learning_rate=0.001)\n",
+ "model.compile(optimizer=nadam, loss='categorical_crossentropy', metrics=['accuracy'])\n",
+ "\n",
+ "# Print model summary\n",
+ "print(model.summary())\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Number of training images: 28709\n",
+ "Number of testing images: 7178\n"
+ ]
+ }
+ ],
+ "source": [
+ "\n",
+ "# Count number of images in train and test directories\n",
+ "def count_images(directory):\n",
+ " count = 0\n",
+ " for root, dirs, files in os.walk(directory):\n",
+ " count += len(files)\n",
+ " return count\n",
+ "\n",
+ "num_train_imgs = count_images(train_data_dir)\n",
+ "num_test_imgs = count_images(validation_data_dir)\n",
+ "\n",
+ "print(\"Number of training images:\", num_train_imgs)\n",
+ "print(\"Number of testing images:\", num_test_imgs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Adjust steps per epoch\n",
+ "steps_per_epoch_train = num_train_imgs // 32 \n",
+ "steps_per_epoch_test = num_test_imgs // 32 \n",
+ "\n",
+ "# Learning rate scheduling\n",
+ "reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=5, min_lr=1e-6, verbose=1)\n",
+ "\n",
+ "# Model checkpoint to save the best weights only\n",
+ "checkpoint = tf.keras.callbacks.ModelCheckpoint('best.weights.h5', monitor='val_accuracy', save_best_only=True, mode='max', verbose=1, save_weights_only=True)\n",
+ "\n",
+ "\n",
+ "epochs = 25"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Training the model\n",
+ "try:\n",
+ " history = model.fit(train_generator,\n",
+ " steps_per_epoch=steps_per_epoch_train,\n",
+ " epochs=epochs,\n",
+ " validation_data=validation_generator,\n",
+ " validation_steps=steps_per_epoch_test,\n",
+ " callbacks=[reduce_lr,checkpoint])\n",
+ "except Exception as e:\n",
+ " print(\"An error occurred during training:\", e)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Load the best weights\n",
+ "model.load_weights('best.weights.h5')\n",
+ "\n",
+ "# Save the entire model to HDF5 format\n",
+ "model.save('best_model.h5')"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.4"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 000000000..cfd0cb10d
Binary files /dev/null and b/requirements.txt differ