{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":3649,"databundleVersionId":46718,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## INTRODUCTION\n* This project implements a deep learning solution for multi-class image classification using the CIFAR-10 dataset.\n* The goal is to classify images into 10 different categories using transfer learning with ResNet50 architecture, demonstrating the power of pre-trained models for computer vision tasks.\n\n### DATASET OVERVIEW:\n- CIFAR-10 dataset with 10 distinct object classes\n- 50,000 training images and 10,000 test images\n- Image size: 32x32 pixels with RGB channels\n- Classes: airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck\n- Real-world application: General object recognition systems\n\n### METHODOLOGY:\n1. Data extraction and exploration from ZIP file\n2. Label processing and encoding\n3. Image data loading and preprocessing\n4. Transfer learning with ResNet50 pre-trained model\n5. Model architecture design with upsampling layers\n6. Training with validation monitoring\n7. Performance evaluation and visualization\n8. Predictive system implementation","metadata":{}},{"cell_type":"markdown","source":"## Import required libraries","metadata":{}},{"cell_type":"code","source":"import os\nimport zipfile\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nimport cv2\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nfrom sklearn.model_selection import train_test_split\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import Sequential, layers, models\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten, BatchNormalization, UpSampling2D\nfrom tensorflow.keras.applications.resnet50 import ResNet50, preprocess_input\nfrom tensorflow.keras import optimizers\nimport pickle","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:22:58.430120Z","iopub.execute_input":"2025-08-28T18:22:58.430420Z","iopub.status.idle":"2025-08-28T18:23:17.549930Z","shell.execute_reply.started":"2025-08-28T18:22:58.430397Z","shell.execute_reply":"2025-08-28T18:23:17.549385Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Data extraction and setup","metadata":{}},{"cell_type":"code","source":"def load_cifar10_batch(file_path):\n    \"\"\"\n    Load a single CIFAR-10 batch file\n    \n    Parameters:\n    file_path (str): Path to the batch file\n    \n    Returns:\n    tuple: (images, labels) arrays\n    \"\"\"\n    with open(file_path, 'rb') as f:\n        batch = pickle.load(f, encoding='bytes')\n    \n    # Extract images and labels\n    images = batch[b'data']\n    labels = batch[b'labels']\n    \n    # Reshape images from flat array to 32x32x3\n    images = images.reshape(-1, 3, 32, 32)\n    # Convert from channels-first to channels-last format\n    images = images.transpose(0, 2, 3, 1)\n    \n    return images, labels","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:23:17.551201Z","iopub.execute_input":"2025-08-28T18:23:17.551715Z","iopub.status.idle":"2025-08-28T18:23:17.556735Z","shell.execute_reply.started":"2025-08-28T18:23:17.551695Z","shell.execute_reply":"2025-08-28T18:23:17.555977Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def extract_7z_files():\n    \"\"\"\n    Extract 7z files if they exist and load CIFAR-10 data\n    \n    Returns:\n    tuple: (X_train, y_train, X_test, y_test) or None if failed\n    \"\"\"\n    print(f\"\\nLOADING CIFAR-10 FROM KAGGLE\")\n    print(\"-\" * 30)\n    \n    try:\n        # Check available files\n        available_files = os.listdir(KAGGLE_INPUT_PATH)\n        print(f\"Available files: {available_files}\")\n        \n        # Try to use TensorFlow's built-in CIFAR-10 dataset as fallback\n        # This is more reliable on Kaggle\n        print(\"Loading CIFAR-10 using TensorFlow datasets...\")\n        \n        (X_train, y_train), (X_test, y_test) = tf.keras.datasets.cifar10.load_data()\n        \n        # Flatten labels (they come as [[0], [1], ...] format)\n        y_train = y_train.flatten()\n        y_test = y_test.flatten()\n        \n        print(f\"Training data loaded: {X_train.shape}\")\n        print(f\"Training labels: {y_train.shape}\")\n        print(f\"Test data loaded: {X_test.shape}\")\n        print(f\"Test labels: {y_test.shape}\")\n        \n        return X_train, y_train, X_test, y_test\n        \n    except Exception as e:\n        print(f\"Error loading CIFAR-10: {e}\")\n        return None, None, None, None\n\ndef load_and_explore_labels():\n    \"\"\"\n    Load and explore the CIFAR-10 labels using standard mapping\n    \n    Returns:\n    dict: Label dictionary mapping names to indices\n    \"\"\"\n    print(f\"\\nSETTING UP CIFAR-10 LABELS\")\n    print(\"-\" * 30)\n    \n    # CIFAR-10 standard label mapping\n    labels_dict = {\n        'airplane': 0, 'automobile': 1, 'bird': 2, 'cat': 3, 'deer': 4,\n        'dog': 5, 'frog': 6, 'horse': 7, 'ship': 8, 'truck': 9\n    }\n    \n    # Reverse mapping for getting names from indices\n    class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', \n                   'dog', 'frog', 'horse', 'ship', 'truck']\n    \n    print(f\"CIFAR-10 class mapping:\")\n    for name, idx in labels_dict.items():\n        print(f\"   - {idx}: {name}\")\n    \n    return labels_dict, class_names","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:23:17.557621Z","iopub.execute_input":"2025-08-28T18:23:17.557856Z","iopub.status.idle":"2025-08-28T18:23:17.594016Z","shell.execute_reply.started":"2025-08-28T18:23:17.557837Z","shell.execute_reply":"2025-08-28T18:23:17.593525Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Data paths configuration","metadata":{}},{"cell_type":"code","source":"KAGGLE_INPUT_PATH = '/kaggle/input/cifar-10'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:23:17.595413Z","iopub.execute_input":"2025-08-28T18:23:17.595586Z","iopub.status.idle":"2025-08-28T18:23:17.616898Z","shell.execute_reply.started":"2025-08-28T18:23:17.595571Z","shell.execute_reply":"2025-08-28T18:23:17.616292Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"🔍 Environment: Kaggle\")\nprint(f\"🔍 Input path: {KAGGLE_INPUT_PATH}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:23:17.617545Z","iopub.execute_input":"2025-08-28T18:23:17.617701Z","iopub.status.idle":"2025-08-28T18:23:17.638897Z","shell.execute_reply.started":"2025-08-28T18:23:17.617687Z","shell.execute_reply":"2025-08-28T18:23:17.638408Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Load CIFAR-10 data","metadata":{}},{"cell_type":"code","source":"X_train, y_train, X_test, y_test = extract_7z_files()\n\nif X_train is not None:\n    print(f\"\\nCIFAR-10 DATA LOADED SUCCESSFULLY\")\n    print(\"-\" * 30)\n    print(f\"Training images: {X_train.shape}\")\n    print(f\"Training labels: {y_train.shape}\")\n    print(f\"Test images: {X_test.shape}\")\n    print(f\"Test labels: {y_test.shape}\")\n    \n    # Load label mappings\n    labels_dict, class_names = load_and_explore_labels()\n    \n    # Show data distribution\n    unique_labels, counts = np.unique(y_train, return_counts=True)\n    print(f\"\\nTraining data distribution:\")\n    for label, count in zip(unique_labels, counts):\n        print(f\"   - {class_names[label]}: {count} images\")\n        \nelse:\n    print(f\"\\nCREATING SAMPLE DATA\")\n    print(\"-\" * 30)\n    print(\"Using synthetic CIFAR-10 like data for demonstration...\")\n    \n    # Create sample data that matches CIFAR-10 structure\n    X_train = np.random.randint(0, 255, (10000, 32, 32, 3), dtype=np.uint8)\n    y_train = np.random.randint(0, 10, 10000)\n    X_test = np.random.randint(0, 255, (2000, 32, 32, 3), dtype=np.uint8)\n    y_test = np.random.randint(0, 10, 2000)\n    \n    labels_dict, class_names = load_and_explore_labels()\n    print(f\"Sample data created: Train {X_train.shape}, Test {X_test.shape}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:23:17.639625Z","iopub.execute_input":"2025-08-28T18:23:17.639820Z","iopub.status.idle":"2025-08-28T18:23:21.742693Z","shell.execute_reply.started":"2025-08-28T18:23:17.639796Z","shell.execute_reply":"2025-08-28T18:23:21.742060Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Data preprocessing","metadata":{}},{"cell_type":"code","source":"print(f\"\\nDATA PREPROCESSING\")\nprint(\"-\" * 30)\n\n# للتدريب السريع على Kaggle، استخدم عينة من البيانات\nSAMPLE_SIZE = 10000  # يمكنك تغيير هذا الرقم حسب الحاجة\nif len(X_train) > SAMPLE_SIZE:\n    # أخذ عينة عشوائية متوازنة\n    indices = []\n    for class_idx in range(10):\n        class_indices = np.where(y_train == class_idx)[0]\n        selected_indices = np.random.choice(class_indices, min(SAMPLE_SIZE//10, len(class_indices)), replace=False)\n        indices.extend(selected_indices)\n    \n    indices = np.array(indices)\n    np.random.shuffle(indices)\n    \n    X_train = X_train[indices]\n    y_train = y_train[indices]\n    \n    print(f\"Using sample of {len(X_train)} training images for faster training\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:23:21.743427Z","iopub.execute_input":"2025-08-28T18:23:21.743668Z","iopub.status.idle":"2025-08-28T18:23:21.759536Z","shell.execute_reply.started":"2025-08-28T18:23:21.743643Z","shell.execute_reply":"2025-08-28T18:23:21.758921Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Normalize pixel values to 0-1 range","metadata":{}},{"cell_type":"code","source":"X_train_scaled = X_train.astype('float32') / 255.0\nX_test_scaled = X_test.astype('float32') / 255.0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:23:21.760384Z","iopub.execute_input":"2025-08-28T18:23:21.760705Z","iopub.status.idle":"2025-08-28T18:23:21.903719Z","shell.execute_reply.started":"2025-08-28T18:23:21.760685Z","shell.execute_reply":"2025-08-28T18:23:21.903099Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Build transfer learning model with ResNet50","metadata":{}},{"cell_type":"code","source":"def create_transfer_learning_model(input_shape=(32, 32, 3), num_classes=10):\n    \"\"\"\n    Create transfer learning model using ResNet50\n    \n    Parameters:\n    input_shape (tuple): Shape of input images\n    num_classes (int): Number of output classes\n    \n    Returns:\n    keras.Sequential: Compiled transfer learning model\n    \"\"\"\n    print(f\"\\nBUILDING TRANSFER LEARNING MODEL\")\n    print(\"-\" * 30)\n    \n    # Load pre-trained ResNet50 (without top layers)\n    base_model = ResNet50(\n        weights='imagenet',\n        include_top=False,\n        input_shape=(256, 256, 3)  # ResNet50 requires larger input\n    )\n    \n    print(f\"ResNet50 base model loaded\")\n    print(f\"Base model parameters: {base_model.count_params():,}\")\n    \n    # Freeze base model layers\n    base_model.trainable = False\n    \n    # Build complete model\n    model = models.Sequential([\n        # Upsampling layers to match ResNet50 input requirements\n        UpSampling2D((2, 2), input_shape=input_shape),  # 32x32 -> 64x64\n        UpSampling2D((2, 2)),                          # 64x64 -> 128x128\n        UpSampling2D((2, 2)),                          # 128x128 -> 256x256\n        \n        # Pre-trained ResNet50 base\n        base_model,\n        \n        # Custom classification head\n        Flatten(),\n        BatchNormalization(),\n        Dense(128, activation='relu'),\n        Dropout(0.5),\n        BatchNormalization(),\n        Dense(64, activation='relu'),\n        Dropout(0.5),\n        BatchNormalization(),\n        Dense(num_classes, activation='softmax')\n    ])\n    \n    # Compile model with lower learning rate for transfer learning\n    model.compile(\n        optimizer=optimizers.RMSprop(learning_rate=2e-5),\n        loss='sparse_categorical_crossentropy',\n        metrics=['accuracy']\n    )\n    \n    print(f\"Transfer learning model created\")\n    print(f\"Total parameters: {model.count_params():,}\")\n    print(f\"Trainable parameters: {np.sum([tf.keras.backend.count_params(p) for p in model.non_trainable_weights]):,}\")\n    \n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:23:21.904407Z","iopub.execute_input":"2025-08-28T18:23:21.904598Z","iopub.status.idle":"2025-08-28T18:23:21.911178Z","shell.execute_reply.started":"2025-08-28T18:23:21.904583Z","shell.execute_reply":"2025-08-28T18:23:21.910466Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Create and train the model","metadata":{}},{"cell_type":"code","source":"model = create_transfer_learning_model()\n\nprint(f\"\\nTRAINING TRANSFER LEARNING MODEL\")\nprint(\"-\" * 30)\n\n# Train the model\nhistory = model.fit(\n    X_train_scaled, y_train,\n    epochs=10,\n    validation_split=0.1,\n    batch_size=32,\n    verbose=1\n)\n\nprint(f\"Transfer learning model training completed\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:23:21.913035Z","iopub.execute_input":"2025-08-28T18:23:21.913423Z","iopub.status.idle":"2025-08-28T18:29:06.313150Z","shell.execute_reply.started":"2025-08-28T18:23:21.913408Z","shell.execute_reply":"2025-08-28T18:29:06.312591Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Model evaluation and visualization","metadata":{}},{"cell_type":"code","source":"test_loss, test_accuracy = model.evaluate(X_test_scaled, y_test, verbose=0)\n\nprint(f\"Test Accuracy: {test_accuracy:.4f} ({test_accuracy*100:.2f}%)\")\nprint(f\"Test Loss: {test_loss:.4f}\")\n\n# Get training history\nfinal_train_accuracy = history.history['accuracy'][-1]\nfinal_val_accuracy = history.history['val_accuracy'][-1]\n\nprint(f\"Final Training Accuracy: {final_train_accuracy:.4f}\")\nprint(f\"Final Validation Accuracy: {final_val_accuracy:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:29:06.313926Z","iopub.execute_input":"2025-08-28T18:29:06.314151Z","iopub.status.idle":"2025-08-28T18:29:39.257202Z","shell.execute_reply.started":"2025-08-28T18:29:06.314133Z","shell.execute_reply":"2025-08-28T18:29:39.256455Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create training plots\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5))\n\n# Loss plot\nax1.plot(history.history['loss'], label='Training Loss', linewidth=2)\nax1.plot(history.history['val_loss'], label='Validation Loss', linewidth=2)\nax1.set_title('Model Loss Progress', fontsize=14, fontweight='bold')\nax1.set_xlabel('Epoch')\nax1.set_ylabel('Loss')\nax1.legend()\nax1.grid(True, alpha=0.3)\n\n# Accuracy plot\nax2.plot(history.history['accuracy'], label='Training Accuracy', linewidth=2)\nax2.plot(history.history['val_accuracy'], label='Validation Accuracy', linewidth=2)\nax2.set_title('Model Accuracy Progress', fontsize=14, fontweight='bold')\nax2.set_xlabel('Epoch')\nax2.set_ylabel('Accuracy')\nax2.legend()\nax2.grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:29:39.258073Z","iopub.execute_input":"2025-08-28T18:29:39.258396Z","iopub.status.idle":"2025-08-28T18:29:39.847305Z","shell.execute_reply.started":"2025-08-28T18:29:39.258378Z","shell.execute_reply":"2025-08-28T18:29:39.846632Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Display sample predictions","metadata":{}},{"cell_type":"code","source":"fig, axes = plt.subplots(2, 5, figsize=(15, 8))\naxes = axes.ravel()\n\n# Get predictions for first 10 test images\nsample_predictions = model.predict(X_test_scaled[:10], verbose=0)\npredicted_classes = np.argmax(sample_predictions, axis=1)\nconfidences = np.max(sample_predictions, axis=1)\n\nfor i in range(10):\n    axes[i].imshow(X_test[i])\n    axes[i].set_title(\n        f'True: {class_names[y_test[i]]}\\n'\n        f'Pred: {class_names[predicted_classes[i]]}\\n'\n        f'Conf: {confidences[i]:.2f}',\n        fontsize=10\n    )\n    axes[i].axis('off')\n    \n    # Add border color based on correctness\n    if predicted_classes[i] == y_test[i]:\n        axes[i].add_patch(plt.Rectangle((0, 0), 32, 32, fill=False, edgecolor='green', lw=3))\n    else:\n        axes[i].add_patch(plt.Rectangle((0, 0), 32, 32, fill=False, edgecolor='red', lw=3))\n\nplt.suptitle('Sample Predictions (Green=Correct, Red=Incorrect)', fontsize=16, fontweight='bold')\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:29:39.848166Z","iopub.execute_input":"2025-08-28T18:29:39.848793Z","iopub.status.idle":"2025-08-28T18:29:47.090151Z","shell.execute_reply.started":"2025-08-28T18:29:39.848767Z","shell.execute_reply":"2025-08-28T18:29:47.089494Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Prediction function","metadata":{}},{"cell_type":"code","source":"def predict_cifar10_class(model, image_array, class_names):\n    \"\"\"\n    Predict CIFAR-10 class for a single image\n    \n    Parameters:\n    model: Trained transfer learning model\n    image_array: Input image as numpy array (32x32x3)\n    class_names: List of class names\n    \n    Returns:\n    tuple: Prediction result and confidence\n    \"\"\"\n    try:\n        # Preprocess the image\n        if len(image_array.shape) == 3:\n            image_array = np.expand_dims(image_array, axis=0)\n        \n        # Normalize\n        image_processed = image_array.astype('float32') / 255.0\n        \n        # Make prediction\n        predictions = model.predict(image_processed, verbose=0)\n        predicted_class = np.argmax(predictions[0])\n        confidence = np.max(predictions[0])\n        predicted_class_name = class_names[predicted_class]\n        \n        return predicted_class, predicted_class_name, confidence\n        \n    except Exception as e:\n        return None, f\"Error: {e}\", 0.0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:29:47.091090Z","iopub.execute_input":"2025-08-28T18:29:47.091412Z","iopub.status.idle":"2025-08-28T18:29:47.096476Z","shell.execute_reply.started":"2025-08-28T18:29:47.091386Z","shell.execute_reply":"2025-08-28T18:29:47.095914Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Test prediction system","metadata":{}},{"cell_type":"code","source":"if len(X_test) > 0:\n    sample_idx = 0\n    sample_image = X_test[sample_idx]\n    actual_class = y_test[sample_idx]\n    \n    pred_class, pred_name, confidence = predict_cifar10_class(model, sample_image, class_names)\n    actual_name = class_names[actual_class]\n    \n    print(f\"Sample Prediction Results:\")\n    print(f\"  Actual class: {actual_class} ({actual_name})\")\n    print(f\"  Predicted class: {pred_class} ({pred_name})\")\n    print(f\"  Confidence: {confidence:.4f} ({confidence*100:.2f}%)\")\n    print(f\"  Result: {'Correct' if pred_class == actual_class else 'Incorrect'}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:29:47.097208Z","iopub.execute_input":"2025-08-28T18:29:47.097468Z","iopub.status.idle":"2025-08-28T18:29:53.114393Z","shell.execute_reply.started":"2025-08-28T18:29:47.097451Z","shell.execute_reply":"2025-08-28T18:29:53.113752Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Show model architecture summary","metadata":{}},{"cell_type":"code","source":"print(f\"\\nMODEL ARCHITECTURE SUMMARY\")\nprint(\"-\" * 30)\nmodel.summary()\n\n# Calculate accuracy per class\ny_pred_all = model.predict(X_test_scaled, verbose=0)\ny_pred_classes = np.argmax(y_pred_all, axis=1)\n\nprint(f\"\\nPER-CLASS ACCURACY\")\nprint(\"-\" * 30)\nfor i, class_name in enumerate(class_names):\n    class_mask = y_test == i\n    if np.sum(class_mask) > 0:\n        class_accuracy = np.mean(y_pred_classes[class_mask] == y_test[class_mask])\n        print(f\"  {class_name}: {class_accuracy:.4f} ({class_accuracy*100:.2f}%)\")\n\nprint(f\"\\nCIFAR-10 Classification System Ready!\")\nprint(f\"Model can classify images into 10 categories\")\nprint(f\"Classes: {', '.join(class_names)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-28T18:29:53.115398Z","iopub.execute_input":"2025-08-28T18:29:53.115690Z","iopub.status.idle":"2025-08-28T18:30:26.361884Z","shell.execute_reply.started":"2025-08-28T18:29:53.115664Z","shell.execute_reply":"2025-08-28T18:30:26.361244Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## CONCLUSION\n* This project successfully demonstrates the power of transfer learning for\nmulti-class image classification using the CIFAR-10 dataset. The ResNet50-based\nmodel with upsampling layers achieved reliable performance in classifying images\ninto 10 distinct object categories, showcasing how pre-trained networks can be\nadapted for specific classification tasks.\n\n* The implementation highlights advanced deep learning concepts including transfer\nlearning, feature extraction, and model fine-tuning. The use of upsampling layers\nto bridge the gap between CIFAR-10's small image size and ResNet50's input\nrequirements demonstrates practical problem-solving in computer vision.\n\n* This approach has wide applications in object recognition systems, automated\ncontent categorization, and visual search engines where accurate multi-class\nclassification is essential for system functionality and user experience.","metadata":{}}]}