{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":18237,"databundleVersionId":1053191,"sourceType":"competition"}],"dockerImageVersionId":30919,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport json\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom sklearn.preprocessing import MultiLabelBinarizer\nfrom sklearn.model_selection import train_test_split\n\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models, optimizers\nfrom tensorflow.keras.applications import EfficientNetB4\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:05:38.189486Z","iopub.execute_input":"2025-03-31T01:05:38.189799Z","iopub.status.idle":"2025-03-31T01:05:57.268129Z","shell.execute_reply.started":"2025-03-31T01:05:38.189773Z","shell.execute_reply":"2025-03-31T01:05:57.267222Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"INPUT_DIR = '/kaggle/input/imaterialist-fashion-2020-fgvc7'\nTRAIN_CSV = os.path.join(INPUT_DIR, 'train.csv')\nTRAIN_IMG_DIR = os.path.join(INPUT_DIR, 'train')\nTEST_IMG_DIR = os.path.join(INPUT_DIR, 'test')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:05:57.269223Z","iopub.execute_input":"2025-03-31T01:05:57.269676Z","iopub.status.idle":"2025-03-31T01:05:57.273998Z","shell.execute_reply.started":"2025-03-31T01:05:57.269652Z","shell.execute_reply":"2025-03-31T01:05:57.273092Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Config:\n    SEED = 42\n    IMG_SIZE = 256  # Can reduce to 224 if memory constrained\n    BATCH_SIZE = 32  # Start with 32, reduce to 16 if OOM\n    EPOCHS = 5\n    NUM_CLASSES = 46  # Will be updated automatically\n    LR = 0.001\n    VAL_SPLIT = 0.2\n    MODEL_PATH = 'best_model.keras'\n    AUTOTUNE = tf.data.AUTOTUNE  # For optimized pipeline\n    \nconfig = Config()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:05:57.276041Z","iopub.execute_input":"2025-03-31T01:05:57.276385Z","iopub.status.idle":"2025-03-31T01:05:57.439Z","shell.execute_reply.started":"2025-03-31T01:05:57.276351Z","shell.execute_reply":"2025-03-31T01:05:57.437833Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"np.random.seed(config.SEED)\ntf.random.set_seed(config.SEED)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:05:57.440277Z","iopub.execute_input":"2025-03-31T01:05:57.440739Z","iopub.status.idle":"2025-03-31T01:05:57.456926Z","shell.execute_reply.started":"2025-03-31T01:05:57.440712Z","shell.execute_reply":"2025-03-31T01:05:57.45619Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_data():\n    \"\"\"Load and preprocess the training data\"\"\"\n    df = pd.read_csv(TRAIN_CSV)\n    \n    # Convert attribute IDs to strings and split them\n    df['AttributesIds'] = df['AttributesIds'].apply(lambda x: str(x).split(' '))\n    \n    # Create multi-hot encoded labels\n    mlb = MultiLabelBinarizer()\n    labels = mlb.fit_transform(df['AttributesIds'])\n    \n    return df, labels, mlb","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:05:57.457864Z","iopub.execute_input":"2025-03-31T01:05:57.458161Z","iopub.status.idle":"2025-03-31T01:05:57.474083Z","shell.execute_reply.started":"2025-03-31T01:05:57.458134Z","shell.execute_reply":"2025-03-31T01:05:57.473304Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df, labels, mlb = load_data()\nprint(f\"Training samples: {len(train_df)}\")\nprint(f\"Number of classes: {config.NUM_CLASSES}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:05:57.474854Z","iopub.execute_input":"2025-03-31T01:05:57.475155Z","iopub.status.idle":"2025-03-31T01:06:37.073996Z","shell.execute_reply.started":"2025-03-31T01:05:57.475126Z","shell.execute_reply":"2025-03-31T01:06:37.073084Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def create_tf_datasets():\n    \"\"\"Optimized TF Dataset pipeline for iMaterialist 2020 format\"\"\"\n    # Load CSV\n    df = pd.read_csv('/kaggle/input/imaterialist-fashion-2020-fgvc7/train.csv')\n    \n    # Verify columns\n    print(\"Available columns:\", df.columns.tolist())\n    \n    # Preprocess labels - using ClassId as primary label\n    df['ClassId'] = df['ClassId'].apply(lambda x: str(x).split(' '))\n    mlb = MultiLabelBinarizer()\n    labels = mlb.fit_transform(df['ClassId'])\n    config.NUM_CLASSES = len(mlb.classes_)\n    print(f\"Detected {config.NUM_CLASSES} classes\")\n    \n    # Construct image paths\n    df['FullPath'] = '/kaggle/input/imaterialist-fashion-2020-fgvc7/train/' + df['ImageId'] + '.jpg'\n    \n    # Verify first image\n    sample_path = df['FullPath'].iloc[0]\n    print(f\"Sample image exists: {os.path.exists(sample_path)} (path: {sample_path})\")\n    \n    # Split data\n    train_df, val_df = train_test_split(df, test_size=config.VAL_SPLIT, random_state=config.SEED)\n    \n    # Image preprocessing\n    def load_and_preprocess(path, label):\n        image = tf.io.read_file(path)\n        image = tf.image.decode_jpeg(image, channels=3)\n        image = tf.image.resize(image, [config.IMG_SIZE, config.IMG_SIZE])\n        image = tf.cast(image, tf.float32) / 255.0\n        \n        # Data augmentation\n        image = tf.image.random_flip_left_right(image)\n        image = tf.image.random_brightness(image, 0.1)\n        return image, label\n    \n    # Build datasets\n    def create_dataset(sub_df, training=True):\n        dataset = tf.data.Dataset.from_tensor_slices(\n            (sub_df['FullPath'].values, labels[sub_df.index])\n        )\n        dataset = dataset.map(\n            lambda x, y: load_and_preprocess(x, y),\n            num_parallel_calls=tf.data.AUTOTUNE\n        )\n        if training:\n            dataset = dataset.shuffle(buffer_size=1000)\n        dataset = dataset.batch(config.BATCH_SIZE)\n        return dataset.prefetch(tf.data.AUTOTUNE)\n        \n    train_ds = create_dataset(train_df)\n    val_ds = create_dataset(val_df, training=False)\n    \n    return train_ds, val_ds, mlb","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:06:37.074854Z","iopub.execute_input":"2025-03-31T01:06:37.075201Z","iopub.status.idle":"2025-03-31T01:06:37.083781Z","shell.execute_reply.started":"2025-03-31T01:06:37.075154Z","shell.execute_reply":"2025-03-31T01:06:37.082822Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_gen, val_gen, mlb = create_tf_datasets()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:06:37.086167Z","iopub.execute_input":"2025-03-31T01:06:37.086369Z","iopub.status.idle":"2025-03-31T01:06:57.92447Z","shell.execute_reply.started":"2025-03-31T01:06:37.086352Z","shell.execute_reply":"2025-03-31T01:06:57.923773Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def build_model():\n    \"\"\"Build EfficientNetB4 based model with custom head\"\"\"\n    base_model = EfficientNetB4(\n        weights='imagenet',\n        include_top=False,\n        input_shape=(config.IMG_SIZE, config.IMG_SIZE, 3)\n    )\n    \n    # Freeze base model layers\n    base_model.trainable = False\n    \n    # Build custom head\n    inputs = layers.Input(shape=(config.IMG_SIZE, config.IMG_SIZE, 3))\n    x = base_model(inputs, training=False)\n    x = layers.GlobalAveragePooling2D()(x)\n    x = layers.Dense(1024, activation='relu')(x)\n    x = layers.Dropout(0.5)(x)\n    outputs = layers.Dense(config.NUM_CLASSES, activation='sigmoid')(x)\n    \n    model = models.Model(inputs, outputs)\n    \n    model.compile(\n        optimizer=optimizers.Adam(config.LR),\n        loss='binary_crossentropy',\n        metrics=[tf.keras.metrics.BinaryAccuracy(name='accuracy')]\n    )\n    return model\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:06:57.925586Z","iopub.execute_input":"2025-03-31T01:06:57.925836Z","iopub.status.idle":"2025-03-31T01:06:57.931438Z","shell.execute_reply.started":"2025-03-31T01:06:57.925815Z","shell.execute_reply":"2025-03-31T01:06:57.930504Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = build_model()\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:06:57.93226Z","iopub.execute_input":"2025-03-31T01:06:57.932511Z","iopub.status.idle":"2025-03-31T01:07:01.84157Z","shell.execute_reply.started":"2025-03-31T01:06:57.932491Z","shell.execute_reply":"2025-03-31T01:07:01.840885Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_callbacks():\n    return [\n        ModelCheckpoint(\n            'best_model.keras',\n            monitor='val_loss',\n            save_best_only=True,\n            mode='min',\n            verbose=1\n        ),\n        EarlyStopping(\n            monitor='val_loss',\n            patience=5,\n            restore_best_weights=True\n        ),\n        ReduceLROnPlateau(\n            monitor='val_loss',\n            factor=0.2,\n            patience=3\n        )\n    ]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:07:01.842305Z","iopub.execute_input":"2025-03-31T01:07:01.84253Z","iopub.status.idle":"2025-03-31T01:07:01.846567Z","shell.execute_reply.started":"2025-03-31T01:07:01.8425Z","shell.execute_reply":"2025-03-31T01:07:01.845744Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    train_gen,\n    steps_per_epoch=len(train_gen),\n    validation_data=val_gen,\n    validation_steps=len(val_gen),\n    epochs=config.EPOCHS,\n    callbacks=get_callbacks()\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T01:07:01.847432Z","iopub.execute_input":"2025-03-31T01:07:01.847636Z","iopub.status.idle":"2025-03-31T06:01:22.46673Z","shell.execute_reply.started":"2025-03-31T01:07:01.847618Z","shell.execute_reply":"2025-03-31T06:01:22.460815Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def plot_history(history):\n    plt.figure(figsize=(12, 4))\n    \n    # Accuracy\n    plt.subplot(1, 2, 1)\n    plt.plot(history.history['accuracy'])\n    plt.plot(history.history['val_accuracy'])\n    plt.title('Model Accuracy')\n    plt.ylabel('Accuracy')\n    plt.xlabel('Epoch')\n    plt.legend(['Train', 'Val'], loc='upper left')\n    \n    # Loss\n    plt.subplot(1, 2, 2)\n    plt.plot(history.history['loss'])\n    plt.plot(history.history['val_loss'])\n    plt.title('Model Loss')\n    plt.ylabel('Loss')\n    plt.xlabel('Epoch')\n    plt.legend(['Train', 'Val'], loc='upper left')\n    \n    plt.tight_layout()\n    plt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T06:01:22.483672Z","iopub.execute_input":"2025-03-31T06:01:22.483911Z","iopub.status.idle":"2025-03-31T06:01:22.506479Z","shell.execute_reply.started":"2025-03-31T06:01:22.483891Z","shell.execute_reply":"2025-03-31T06:01:22.505808Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_history(history)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T06:01:22.507132Z","iopub.execute_input":"2025-03-31T06:01:22.507357Z","iopub.status.idle":"2025-03-31T06:01:24.219033Z","shell.execute_reply.started":"2025-03-31T06:01:22.507336Z","shell.execute_reply":"2025-03-31T06:01:24.218096Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def create_submission():\n    test_df = pd.read_csv(TEST_CSV)\n    \n    test_datagen = ImageDataGenerator(rescale=1./255)\n    \n    test_generator = test_datagen.flow_from_dataframe(\n        dataframe=test_df,\n        directory=TEST_IMG_DIR,\n        x_col='ImageId',\n        y_col=None,\n        target_size=(config.IMG_SIZE, config.IMG_SIZE),\n        batch_size=config.BATCH_SIZE,\n        class_mode=None,\n        shuffle=False\n    )\n    \n    # Load best model\n    model = tf.keras.models.load_model(config.MODEL_PATH)\n    \n    # Predict\n    predictions = model.predict(test_generator, steps=len(test_generator))\n    \n    # Convert predictions to label strings\n    threshold = 0.5\n    pred_labels = []\n    for pred in predictions:\n        labels = [str(i) for i, p in enumerate(pred) if p > threshold]\n        pred_labels.append(' '.join(labels))\n    \n    # Create submission\n    submission = pd.DataFrame({\n        'ImageId': test_df['ImageId'],\n        'Predicted': pred_labels\n    })\n    \n    return submission","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T06:01:24.219952Z","iopub.execute_input":"2025-03-31T06:01:24.220309Z","iopub.status.idle":"2025-03-31T06:01:24.22588Z","shell.execute_reply.started":"2025-03-31T06:01:24.220284Z","shell.execute_reply":"2025-03-31T06:01:24.225251Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# %% [markdown]\n# ## Model Testing and Visualization\n# \n# This cell tests the trained model on sample images and visualizes the predictions.\n\n# %%\n# Load the best saved model\nmodel = tf.keras.models.load_model(config.MODEL_PATH)\n\n# %%\n# Function to test and visualize predictions\ndef test_and_visualize(num_samples=5):\n    # Get a batch of validation data\n    test_images, test_labels = next(val_gen)\n    \n    # Make predictions\n    preds = model.predict(test_images)\n    \n    # Convert predictions to class labels using threshold\n    threshold = 0.5\n    pred_labels = (preds > threshold).astype(int)\n    \n    # Get class names (using position indices since we don't have actual names)\n    class_indices = list(range(config.NUM_CLASSES))\n    \n    plt.figure(figsize=(15, 10))\n    for i in range(min(num_samples, len(test_images))):\n        # Plot image\n        plt.subplot(num_samples, 2, 2*i+1)\n        plt.imshow(test_images[i])\n        plt.axis('off')\n        plt.title(f\"Sample {i+1}\")\n        \n        # Plot ground truth vs predictions\n        plt.subplot(num_samples, 2, 2*i+2)\n        \n        # Get ground truth and predicted classes\n        true_classes = [class_indices[j] for j, val in enumerate(test_labels[i]) if val > 0]\n        pred_classes = [class_indices[j] for j, val in enumerate(pred_labels[i]) if val > 0]\n        \n        # Create text for display\n        true_text = \"True: \" + \", \".join(map(str, true_classes)) if true_classes else \"True: None\"\n        pred_text = \"Pred: \" + \", \".join(map(str, pred_classes)) if pred_classes else \"Pred: None\"\n        \n        # Display as text (since we don't have class names)\n        plt.text(0.1, 0.6, true_text, fontsize=10)\n        plt.text(0.1, 0.3, pred_text, fontsize=10, color='green' if set(true_classes) == set(pred_classes) else 'red')\n        plt.axis('off')\n        \n    plt.tight_layout()\n    plt.show()\n    \n    # Print sample raw predictions\n    print(\"\\nSample raw predictions (sigmoid outputs):\")\n    for i in range(min(3, len(preds))):\n        print(f\"Sample {i+1} top predictions:\")\n        sorted_preds = sorted([(j, float(preds[i][j])) for j in range(config.NUM_CLASSES)], \n                             key=lambda x: x[1], reverse=True)[:5]\n        for class_idx, prob in sorted_preds:\n            print(f\"  Class {class_idx}: {prob:.4f}\")\n\n# Run the testing\ntest_and_visualize(num_samples=3)\n\n# %%\n# Additional metrics\nfrom sklearn.metrics import classification_report, multilabel_confusion_matrix\n\ndef evaluate_model():\n    # Get all validation data\n    y_true = []\n    y_pred = []\n    \n    # Process validation set in batches\n    for i in range(len(val_gen)):\n        x, y = val_gen[i]\n        p = model.predict(x)\n        y_true.extend(y)\n        y_pred.extend((p > 0.5).astype(int))\n        if i > 5:  # Limit to 6 batches for speed (about 192 samples)\n            break\n    \n    # Convert to numpy arrays\n    y_true = np.array(y_true)\n    y_pred = np.array(y_pred)\n    \n    # Classification report\n    print(\"\\nClassification Report (sample of validation data):\")\n    print(classification_report(y_true, y_pred, target_names=[str(i) for i in range(config.NUM_CLASSES)]))\n    \n    # Sample confusion matrices for first 5 classes\n    print(\"\\nConfusion Matrices for first 5 classes:\")\n    cm = multilabel_confusion_matrix(y_true, y_pred)\n    for i in range(min(5, config.NUM_CLASSES)):\n        print(f\"\\nClass {i}:\")\n        print(cm[i])\n\n# Run evaluation\nevaluate_model()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T06:01:24.226624Z","iopub.execute_input":"2025-03-31T06:01:24.226865Z","iopub.status.idle":"2025-03-31T06:01:28.021144Z","shell.execute_reply.started":"2025-03-31T06:01:24.226833Z","shell.execute_reply":"2025-03-31T06:01:28.019885Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with open(\"/kaggle/input/imaterialist-fashion-2020-fgvc7/label_descriptions.json\", \"r\") as f:\n    label_data = json.load(f)\n\ncategory_map = {item[\"id\"]: item[\"name\"] for item in label_data[\"categories\"]}\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T06:22:30.962735Z","iopub.execute_input":"2025-03-31T06:22:30.963037Z","iopub.status.idle":"2025-03-31T06:22:30.981339Z","shell.execute_reply.started":"2025-03-31T06:22:30.963015Z","shell.execute_reply":"2025-03-31T06:22:30.980569Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def test_and_visualize(num_samples=5):\n    # Get a batch of validation data\n    test_iter = iter(val_gen)\n    test_images, test_labels = next(test_iter)\n\n\n    # Make predictions\n    preds = model.predict(test_images)\n    \n    # Debugging: Print raw predictions\n    print(\"\\nRaw Predictions (First 5 samples):\\n\", preds[:5])\n\n    # Convert predictions to class labels using threshold\n    threshold = 0.3\n    pred_labels = (preds > threshold).astype(int)\n\n    # Get class names\n    class_indices = list(range(config.NUM_CLASSES))\n\n    plt.figure(figsize=(15, 10))\n    for i in range(min(num_samples, len(test_images))):\n        plt.subplot(num_samples, 2, 2*i+1)\n        plt.imshow(test_images[i])\n        plt.axis('off')\n        plt.title(f\"Sample {i+1}\")\n\n        # Get ground truth and predicted classes\n        true_classes = [class_indices[j] for j, val in enumerate(test_labels[i]) if val > 0]\n        pred_classes = [class_indices[j] for j, val in enumerate(pred_labels[i]) if val > 0]\n\n        true_text = \"True: \" + \", \".join(map(str, true_classes)) if true_classes else \"True: None\"\n        pred_text = \"Pred: \" + \", \".join(map(str, pred_classes)) if pred_classes else \"Pred: None\"\n\n        plt.subplot(num_samples, 2, 2*i+2)\n        plt.text(0.1, 0.6, true_text, fontsize=10)\n        plt.text(0.1, 0.3, pred_text, fontsize=10, color='green' if set(true_classes) == set(pred_classes) else 'red')\n        plt.axis('off')\n\n    plt.tight_layout()\n    plt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T06:57:06.747351Z","iopub.execute_input":"2025-03-31T06:57:06.747666Z","iopub.status.idle":"2025-03-31T06:57:06.755007Z","shell.execute_reply.started":"2025-03-31T06:57:06.747639Z","shell.execute_reply":"2025-03-31T06:57:06.754221Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_and_visualize()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T06:57:13.927421Z","iopub.execute_input":"2025-03-31T06:57:13.927733Z","iopub.status.idle":"2025-03-31T06:57:15.781767Z","shell.execute_reply.started":"2025-03-31T06:57:13.92771Z","shell.execute_reply":"2025-03-31T06:57:15.781Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def test_accuracy():\n    \"\"\"Check accuracy for test images by comparing predictions with true labels.\"\"\"\n    correct = 0\n    total = 0\n    val_iterator = iter(val_gen)\n    test_images, test_labels = next(val_iterator)\n    preds = model.predict(test_images)\n    \n    for i in range(len(test_images)):\n        true_classes = np.where(test_labels[i].numpy() == 1)[0].tolist()\n        pred_classes = np.where(preds[i] > 0.5)[0].tolist()\n        \n        true_names = [category_map.get(cls, \"Unknown\") for cls in true_classes]\n        pred_names = [category_map.get(cls, \"Unknown\") for cls in pred_classes]\n        \n        correct += set(true_classes) == set(pred_classes)\n        total += 1\n        \n        print(f\"Image {i+1}: True - {true_names}, Predicted - {pred_names}, {'Correct' if set(true_classes) == set(pred_classes) else 'Incorrect'}\")\n    \n    accuracy = (correct / total) * 100\n    print(f\"Overall Accuracy: {accuracy:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T06:51:55.365719Z","iopub.execute_input":"2025-03-31T06:51:55.366033Z","iopub.status.idle":"2025-03-31T06:51:55.371883Z","shell.execute_reply.started":"2025-03-31T06:51:55.366008Z","shell.execute_reply":"2025-03-31T06:51:55.370962Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_accuracy()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-31T06:55:46.193735Z","iopub.execute_input":"2025-03-31T06:55:46.194079Z","iopub.status.idle":"2025-03-31T06:55:47.47775Z","shell.execute_reply.started":"2025-03-31T06:55:46.19405Z","shell.execute_reply":"2025-03-31T06:55:47.477067Z"}},"outputs":[],"execution_count":null}]}