{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"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":"gpu","dataSources":[{"sourceId":87323,"databundleVersionId":9934427,"sourceType":"competition"}],"dockerImageVersionId":30840,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install autogluon","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-19T13:47:04.437708Z","iopub.execute_input":"2025-01-19T13:47:04.438061Z","iopub.status.idle":"2025-01-19T13:47:49.280162Z","shell.execute_reply.started":"2025-01-19T13:47:04.438030Z","shell.execute_reply":"2025-01-19T13:47:49.279251Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport autogluon.multimodal as agmm\nimport torch\nfrom sklearn.model_selection import train_test_split\nimport os\nfrom tqdm.auto import tqdm\nimport gc\nfrom sklearn.metrics import classification_report, confusion_matrix\nimport logging\nimport warnings\nfrom typing import Dict, Tuple, Optional\n\nclass Config:\n    \"\"\"Configuration class with model and training parameters\"\"\"\n    # Paths\n    BASE_PATH = '/kaggle/input/cidaut-ai-fake-scene-classification-2024'\n    TRAIN_PATH = os.path.join(BASE_PATH, 'Train')\n    TEST_PATH = os.path.join(BASE_PATH, 'Test')\n    OUTPUT_PATH = '.'\n    \n    # Model parameters\n    SEED = 42\n    VAL_SIZE = 0.2\n    \n    # Enhanced AutoGluon configuration\n    HYPERPARAMETERS = {\n    'model': {\n        'names': ['timm_image'],\n        'dropout_rate': 0.2,\n        'timm_image': {\n            'checkpoint_name': 'convnext_xlarge_384_in22ft1k',  # Changed to ConvNeXt\n            'use_pretrained': True,\n            'freeze_backbone': False\n        }\n    },\n    'optimization': {\n        'learning_rate': 5e-5,    # More conservative\n        'weight_decay': 1e-2,     # Stronger regularization\n        'max_epochs': 15,         # Reduced to prevent overfitting\n        'label_smoothing': 0.01,  # Minimal smoothing\n        'loss_function': 'binary_cross_entropy',  # Simpler loss\n        'optimizer': 'adamw',\n        'lr_scheduler': 'cosine',\n        'warmup_epochs': 1\n    },\n    'data': {\n        'image_size': 384,        # More memory efficient\n        'augmentation': {\n            'random_resized_crop': True,\n            'random_horizontal_flip': 0.5,\n            'color_jitter': 0.1,  # Minimal color augmentation\n            # Removed complex augmentations\n        },\n        'batch_size': 8\n    }\n}\ndef setup_logging():\n    \"\"\"Configure logging settings\"\"\"\n    logging.basicConfig(\n        level=logging.INFO,\n        format='%(asctime)s - %(levelname)s - %(message)s',\n        handlers=[\n            logging.StreamHandler(),\n            logging.FileHandler('training.log')\n        ]\n    )\n\ndef seed_everything(seed: int) -> None:\n    \"\"\"Set random seeds for reproducibility\"\"\"\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    \nclass ImageClassifier:\n    def __init__(self, config: Config):\n        self.config = config\n        setup_logging()\n        seed_everything(config.SEED)\n        self.logger = logging.getLogger(__name__)\n        self.setup_data()\n        \n    def setup_data(self) -> None:\n        \"\"\"Load and prepare data with error handling\"\"\"\n        self.logger.info(\"Loading data...\")\n        try:\n            self.train = pd.read_csv(os.path.join(self.config.BASE_PATH, 'train.csv'))\n            self.test = pd.read_csv(os.path.join(self.config.BASE_PATH, 'sample_submission.csv'))\n            self.sub = pd.read_csv(os.path.join(self.config.BASE_PATH, 'sample_submission.csv'))\n            \n            # Validate data\n            required_columns = {'image', 'label'}\n            if not required_columns.issubset(self.train.columns):\n                raise ValueError(f\"Training data missing required columns: {required_columns}\")\n            \n            # Add full paths with validation\n            self.train['image'] = self.train['image'].apply(\n                lambda x: os.path.join(self.config.TRAIN_PATH, x)\n            )\n            self.test['image'] = self.test['image'].apply(\n                lambda x: os.path.join(self.config.TEST_PATH, x)\n            )\n            \n            # Validate image paths\n            missing_train = [f for f in self.train['image'] if not os.path.exists(f)]\n            if missing_train:\n                self.logger.warning(f\"Missing {len(missing_train)} training images\")\n            \n            # Create stratified validation split\n            self.train_data, self.val_data = train_test_split(\n                self.train, \n                test_size=self.config.VAL_SIZE,\n                random_state=self.config.SEED,\n                stratify=self.train['label']\n            )\n            \n            self.logger.info(f\"Train size: {len(self.train_data)}, Validation size: {len(self.val_data)}\")\n            \n        except Exception as e:\n            self.logger.error(f\"Error in data setup: {str(e)}\")\n            raise\n            \n    def train_model(self) -> None:\n        \"\"\"Train the model with validation and metrics tracking\"\"\"\n        self.logger.info(\"Training model...\")\n        \n        # Clear GPU memory\n        torch.cuda.empty_cache()\n        gc.collect()\n        \n        try:\n            # Initialize predictor with binary classification\n            self.predictor = agmm.MultiModalPredictor(\n                label='label',\n                path=os.path.join(self.config.OUTPUT_PATH, 'modelnxz497'),\n                problem_type='binary'  # Changed from 'multiclass' to 'binary'\n            )\n            \n            # Train with validation\n            with warnings.catch_warnings():\n                warnings.simplefilter(\"ignore\")\n                self.predictor.fit(\n                    train_data=self.train_data,\n                    tuning_data=self.val_data,\n                    hyperparameters=self.config.HYPERPARAMETERS,\n                    time_limit=7200  # 2 hour time limit\n                )\n            \n            # Evaluate on validation set\n            val_predictions = self.predictor.predict(self.val_data)\n            val_proba = self.predictor.predict_proba(self.val_data)\n            \n            # Generate detailed metrics\n            report = classification_report(\n                self.val_data['label'], \n                val_predictions,\n                output_dict=True\n            )\n            \n            self.logger.info(\"\\nValidation Results:\")\n            self.logger.info(f\"\\nClassification Report:\\n{pd.DataFrame(report).T}\")\n            \n            # Save validation predictions for analysis\n            val_results = pd.DataFrame({\n                'true_label': self.val_data['label'],\n                'predicted_label': val_predictions\n            })\n            val_results.to_csv('validation_results.csv', index=False)\n            \n        except Exception as e:\n            self.logger.error(f\"Error in model training: {str(e)}\")\n            raise\n            \n    def predict(self) -> None:\n        \"\"\"Generate and save predictions with error handling\"\"\"\n        self.logger.info(\"Generating predictions...\")\n        try:\n            predictions = self.predictor.predict(self.test)\n            probabilities = self.predictor.predict_proba(self.test)\n            \n            # Create submission file with probabilities\n            self.sub['label'] = predictions\n            for i, col in enumerate(probabilities.columns):\n                self.sub[f'prob_{col}'] = probabilities.iloc[:, i]\n            \n            submission_path = os.path.join(self.config.OUTPUT_PATH, 'submissionuv19x.csv')\n            self.sub.to_csv(submission_path, index=False)\n            \n            # Log prediction distribution\n            value_counts = pd.Series(predictions).value_counts()\n            self.logger.info(\"\\nPrediction Distribution:\")\n            for label, count in value_counts.items():\n                self.logger.info(f\"{label}: {count} ({count/len(predictions)*100:.2f}%)\")\n                \n        except Exception as e:\n            self.logger.error(f\"Error in prediction: {str(e)}\")\n            raise\n    \n    def run(self) -> None:\n        \"\"\"Run the complete pipeline with timing\"\"\"\n        try:\n            start_time = pd.Timestamp.now()\n            self.logger.info(f\"Starting pipeline at {start_time}\")\n            \n            self.train_model()\n            self.predict()\n            \n            end_time = pd.Timestamp.now()\n            duration = end_time - start_time\n            self.logger.info(f\"Pipeline completed in {duration}\")\n            \n        except Exception as e:\n            self.logger.error(f\"Pipeline failed: {str(e)}\")\n            raise\n\nif __name__ == \"__main__\":\n    classifier = ImageClassifier(Config)\n    classifier.run()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-19T15:42:05.254447Z","iopub.execute_input":"2025-01-19T15:42:05.254818Z","iopub.status.idle":"2025-01-19T16:10:43.219259Z","shell.execute_reply.started":"2025-01-19T15:42:05.254788Z","shell.execute_reply":"2025-01-19T16:10:43.218343Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!rm -rf /kaggle/working/*","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-19T15:41:57.280789Z","iopub.execute_input":"2025-01-19T15:41:57.281136Z","iopub.status.idle":"2025-01-19T15:41:57.654311Z","shell.execute_reply.started":"2025-01-19T15:41:57.281110Z","shell.execute_reply":"2025-01-19T15:41:57.653138Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport torch\ntorch.cuda.empty_cache()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-19T13:46:05.144235Z","iopub.execute_input":"2025-01-19T13:46:05.144512Z","iopub.status.idle":"2025-01-19T13:46:08.141512Z","shell.execute_reply.started":"2025-01-19T13:46:05.144489Z","shell.execute_reply":"2025-01-19T13:46:08.140637Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"30 epochs -9418\n40 epochs -9392\n35 epochs -","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-19T13:42:26.061864Z","iopub.execute_input":"2025-01-19T13:42:26.062140Z","iopub.status.idle":"2025-01-19T13:42:26.067378Z","shell.execute_reply.started":"2025-01-19T13:42:26.062118Z","shell.execute_reply":"2025-01-19T13:42:26.066314Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}