{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":102335,"databundleVersionId":12518947,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":243905479,"sourceType":"kernelVersion"}],"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Behavior Lightning 3DCNN: Submit(InetOff)\n","metadata":{"papermill":{"duration":0.003895,"end_time":"2023-06-30T09:39:19.33539","exception":false,"start_time":"2023-06-30T09:39:19.331495","status":"completed"},"tags":[]}},{"cell_type":"code","source":"!grep -v \"nvidia-\" /kaggle/input/download-lightning2/requirements.txt > requirements_no_cuda.txt\n\n!pip install --no-index --find-links /kaggle/input/download-lightning2/offline_packages/ -r requirements_no_cuda.txt --no-deps","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#available internet off\nimport pytorch_lightning as L\nfrom pytorch_lightning import LightningDataModule\nfrom pytorch_lightning import LightningModule\nfrom pytorch_lightning import Trainer\nfrom pytorch_lightning import seed_everything\nfrom pytorch_lightning.callbacks import ModelCheckpoint, EarlyStopping\nfrom pytorch_lightning.loggers import TensorBoardLogger, WandbLogger","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"    !pip install --upgrade pip\n    !pip install lightning ","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.811535Z","iopub.status.idle":"2025-06-03T05:21:19.811872Z","shell.execute_reply.started":"2025-06-03T05:21:19.811704Z","shell.execute_reply":"2025-06-03T05:21:19.811718Z"}}},{"cell_type":"code","source":"import os\nimport random\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import random_split\nfrom torch.utils.data import DataLoader, Dataset, Subset\nfrom torch.utils.data import random_split, SubsetRandomSampler\nfrom torchvision import datasets, transforms, models \nfrom torchvision.datasets import ImageFolder\nfrom torchvision.transforms import ToTensor\nfrom torchvision.utils import make_grid\n\n'''\n#the latest environement\n#not available internet off\nimport lightning.pytorch as L\nfrom lightning.pytorch import LightningDataModule\nfrom lightning.pytorch import LightningModule\nfrom lightning.pytorch import Trainer\n'''\n\nimport matplotlib.pyplot as plt\n%matplotlib inline\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report\nfrom PIL import Image","metadata":{"papermill":{"duration":13.262195,"end_time":"2023-06-30T09:39:32.607264","exception":false,"start_time":"2023-06-30T09:39:19.345069","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.812535Z","iopub.status.idle":"2025-06-03T05:21:19.812749Z","shell.execute_reply.started":"2025-06-03T05:21:19.812648Z","shell.execute_reply":"2025-06-03T05:21:19.812658Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train=pd.read_csv('/kaggle/input/cmi-detect-behavior-with-sensor-data/train.csv')\nprint(len(train))\n\nM=list(range(len(train)))\nrandom.shuffle(M)\ntrain=train.iloc[M[0:10000]]\ntrain=train.reset_index(drop=True)\n\ndisplay(train)\ndisplay(train.info())\ntrain=train.fillna(0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.814159Z","iopub.status.idle":"2025-06-03T05:21:19.814394Z","shell.execute_reply.started":"2025-06-03T05:21:19.81428Z","shell.execute_reply":"2025-06-03T05:21:19.814291Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TEST=pd.read_csv('/kaggle/input/cmi-detect-behavior-with-sensor-data/test.csv')\nTEST=TEST.fillna(0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.815059Z","iopub.status.idle":"2025-06-03T05:21:19.815362Z","shell.execute_reply.started":"2025-06-03T05:21:19.815196Z","shell.execute_reply":"2025-06-03T05:21:19.81521Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class_names = sorted(train['gesture'].unique().tolist())\nprint(len(class_names))\nprint(class_names)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.816613Z","iopub.status.idle":"2025-06-03T05:21:19.816837Z","shell.execute_reply.started":"2025-06-03T05:21:19.816727Z","shell.execute_reply":"2025-06-03T05:21:19.816735Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"N=list(range(len(class_names)))\nnormal_mapping=dict(zip(class_names,N)) \nreverse_mapping=dict(zip(N,class_names))       \ntrain['gesture']=train['gesture'].map(normal_mapping)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.81769Z","iopub.status.idle":"2025-06-03T05:21:19.817933Z","shell.execute_reply.started":"2025-06-03T05:21:19.817817Z","shell.execute_reply":"2025-06-03T05:21:19.817829Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!mkdir train\n!mkdir test","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.819288Z","iopub.status.idle":"2025-06-03T05:21:19.819743Z","shell.execute_reply.started":"2025-06-03T05:21:19.819562Z","shell.execute_reply":"2025-06-03T05:21:19.819576Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def create_path_label_list(df):\n    path_label_list = []\n    for _, row in df.iterrows():\n        npi = row.iloc[21:].to_numpy().reshape(5,8,8)\n        name = row.iloc[0]\n        path = './train/'+name+'.npy'        \n        np.save(path,npi)\n        label = row['gesture']\n        path_label_list.append((path, label))\n    return path_label_list\n\npath_label = create_path_label_list(train)\nprint(path_label[0:3])","metadata":{"papermill":{"duration":0.299275,"end_time":"2023-06-30T09:39:32.987661","exception":false,"start_time":"2023-06-30T09:39:32.688386","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.820595Z","iopub.status.idle":"2025-06-03T05:21:19.820885Z","shell.execute_reply.started":"2025-06-03T05:21:19.820753Z","shell.execute_reply":"2025-06-03T05:21:19.820768Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def TEST_create_path_label_list(df):\n    path_label_list = []\n    for _, row in df.iterrows():\n        npi = row.iloc[16:].to_numpy().reshape(5,8,8)\n        name = row.iloc[0]\n        path = './test/'+name+'.npy'        \n        np.save(path,npi)\n        label = 0\n        path_label_list.append((path, label))\n    return path_label_list\n\nTEST_path_label = TEST_create_path_label_list(TEST)\nprint(TEST_path_label[0:3])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.821686Z","iopub.status.idle":"2025-06-03T05:21:19.821944Z","shell.execute_reply.started":"2025-06-03T05:21:19.821833Z","shell.execute_reply":"2025-06-03T05:21:19.821845Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CustomDataset(torch.utils.data.Dataset):\n    def __init__(self, path_label, transform=None):\n        # path_label should be a list of tuples containing (data_path, label)\n        self.path_label = path_label\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.path_label)\n\n    def __getitem__(self, idx):\n        # Load data and get label\n        rgb = np.load(self.path_label[idx][0],allow_pickle=True)  # Load data from path\n        rgb = rgb.astype('uint8')  # Or torch.FloatTensor\n        label = self.path_label[idx][1]  # Get the label\n        \n        if self.transform:\n            rgb = self.transform(rgb)\n\n        return rgb, torch.tensor(label, dtype=torch.long) \n        \n###------------------------------------------------------------------------","metadata":{"papermill":{"duration":0.014251,"end_time":"2023-06-30T09:39:33.032042","exception":false,"start_time":"2023-06-30T09:39:33.017791","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.823098Z","iopub.status.idle":"2025-06-03T05:21:19.823762Z","shell.execute_reply.started":"2025-06-03T05:21:19.823574Z","shell.execute_reply":"2025-06-03T05:21:19.823592Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Resize3D:\n    def __init__(self, size):  # size = (D_new, H_new, W_new)\n        self.size = size\n\n    def __call__(self, img):\n        # Check if the input is a NumPy array or a tensor\n        if isinstance(img, np.ndarray):\n            img_tensor = torch.from_numpy(img).float()\n        elif isinstance(img, torch.Tensor):\n            img_tensor = img.float()\n        else:\n            raise TypeError(\"Input must be either numpy.ndarray or torch.Tensor\")\n        \n        # Convert shape from (D, H, W) to (1, 1, D, H, W)\n        img_tensor = img_tensor.unsqueeze(0).unsqueeze(0)\n        \n        # Apply 3D resizing\n        resized = F.interpolate(\n            img_tensor,\n            size=self.size,\n            mode='trilinear',\n            align_corners=False\n        )\n        \n        # Convert shape back from (1, 1, D_new, H_new, W_new) to (D_new, H_new, W_new)\n        return resized.squeeze(0).squeeze(0)\n\n###------------------------------------------------------------------------","metadata":{"papermill":{"duration":0.014251,"end_time":"2023-06-30T09:39:33.032042","exception":false,"start_time":"2023-06-30T09:39:33.017791","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.824711Z","iopub.status.idle":"2025-06-03T05:21:19.824969Z","shell.execute_reply.started":"2025-06-03T05:21:19.824847Z","shell.execute_reply":"2025-06-03T05:21:19.82486Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DataModule(LightningDataModule):\n    def __init__(self, path_label, batch_size=1, test_path_label=None, num_workers=4):\n        super().__init__()\n        self.path_label = path_label\n        self.test_path_label = test_path_label\n        self.batch_size = batch_size\n        self.num_workers = num_workers\n        \n        # Transformations for 3D data (example normalization for grayscale medical images)\n        self.transform = transforms.Compose([\n            transforms.ToTensor(),\n            Resize3D((32, 32, 32)),  # (Depth, Height, Width)(125, 128, 128)\n            transforms.Normalize(mean=[0.5], std=[0.5])  # For single-channel data\n        ])\n\n    def setup(self, stage=None):\n        if stage == 'test':\n            self.test_dataset = CustomDataset(self.test_path_label, self.transform)\n            \n        elif stage == 'fit' or stage is None:\n            full_dataset = CustomDataset(self.path_label, self.transform)\n            \n            # Random split (shuffling is recommended)\n            train_size = int(0.8 * len(full_dataset))\n            val_size = len(full_dataset) - train_size\n            self.train_dataset, self.val_dataset = random_split(\n                full_dataset, \n                [train_size, val_size],\n                generator=torch.Generator().manual_seed(42)  # Ensures reproducibility\n            )\n\n    def train_dataloader(self):\n        return DataLoader(\n            self.train_dataset,\n            batch_size=self.batch_size,\n            shuffle=True,\n            num_workers=self.num_workers,\n            pin_memory=True  # Enable when using GPU\n        )\n\n    def val_dataloader(self):\n        return DataLoader(\n            self.val_dataset,\n            batch_size=self.batch_size,\n            num_workers=self.num_workers\n        )\n\n    def test_dataloader(self):\n        return DataLoader(\n            self.test_dataset,\n            batch_size=self.batch_size,\n            num_workers=self.num_workers\n        )\n\n    def configure_optimizers(self):\n        optimizer = torch.optim.Adam(self.parameters(), lr=0.001)\n        return optimizer","metadata":{"papermill":{"duration":0.014251,"end_time":"2023-06-30T09:39:33.032042","exception":false,"start_time":"2023-06-30T09:39:33.017791","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.826127Z","iopub.status.idle":"2025-06-03T05:21:19.826404Z","shell.execute_reply.started":"2025-06-03T05:21:19.82625Z","shell.execute_reply":"2025-06-03T05:21:19.826263Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Conv3DNetwork(LightningModule):\n    def __init__(self, in_channels=1, num_classes=len(class_names)):\n        super().__init__()\n        self.conv_layers = nn.Sequential(\n            nn.Conv3d(in_channels, 16, 3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool3d(2),  # (1,32,32,32) → (16,16,16,16)\n            nn.Conv3d(16, 32, 3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool3d(2)   # (16,16,16,16) → (32,8,8,8)\n        )\n        self.gap = nn.AdaptiveAvgPool3d(1)  # (32,1,1,1)\n        self.fc = nn.Linear(32, num_classes)  # Input has 32 channels\n\n    def forward(self, x):\n        # Check input shape (batch, channels, depth, height, width)\n        if x.dim() == 4:  # If the channel dimension is missing\n            x = x.unsqueeze(1)  # (b,d,h,w) → (b,1,d,h,w)\n        \n        x = self.conv_layers(x)\n        #print(f\"Conv out: {x.shape}\")  # Should be [batch, 32, 8, 8, 8]\n        x = self.gap(x)\n        x = x.view(x.size(0), x.size(1))  # [batch, channels]\n        return F.log_softmax(self.fc(x), dim=1)\n    \n    def configure_optimizers(self):\n        optimizer = torch.optim.Adam(self.parameters(), lr=0.001)\n        return optimizer\n\n    def training_step(self, train_batch, batch_idx):\n        try:\n            X, y = train_batch[0], train_batch[1]  # Get the first two elements\n        except (IndexError, TypeError) as e:\n            raise ValueError(f\"Unexpected batch format: {type(train_batch)}\") from e\n        \n        y_hat = self(X)  # Forward pass\n        loss = F.cross_entropy(y_hat, y)  # Compute loss\n        pred = y_hat.argmax(dim=1, keepdim=True)  # Get predicted classes\n        acc = pred.eq(y.view_as(pred)).sum().item() / y.shape[0]  # Compute accuracy\n        self.log(\"train_loss\", loss, prog_bar=True)\n        self.log(\"train_acc\", acc, prog_bar=True)\n        return loss\n    \n    def validation_step(self, val_batch, batch_idx):\n        X, y = val_batch[0], val_batch[1]  # Explicit indexing\n        y_hat = self(X)\n        loss = F.cross_entropy(y_hat, y)\n        pred = y_hat.argmax(dim=1, keepdim=True)\n        acc = pred.eq(y.view_as(pred)).sum().item() / y.shape[0]\n        self.log(\"val_loss\", loss, prog_bar=True)\n        self.log(\"val_acc\", acc, prog_bar=True)\n    \n    def test_step(self, test_batch, batch_idx):\n        X, y = test_batch[0], test_batch[1]\n        y_hat = self(X)\n        loss = F.cross_entropy(y_hat, y)\n        pred = y_hat.argmax(dim=1, keepdim=True)\n        acc = pred.eq(y.view_as(pred)).sum().item() / y.shape[0]\n        self.log(\"test_loss\", loss)\n        self.log(\"test_acc\", acc)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.827373Z","iopub.status.idle":"2025-06-03T05:21:19.827606Z","shell.execute_reply.started":"2025-06-03T05:21:19.827504Z","shell.execute_reply":"2025-06-03T05:21:19.827513Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"datamodule = DataModule(path_label=path_label, test_path_label=TEST_path_label)\ndatamodule.setup(stage=None)\nmodel = Conv3DNetwork()\ntrainer = L.Trainer(max_epochs=10)\ntrainer.fit(model, datamodule)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.828839Z","iopub.status.idle":"2025-06-03T05:21:19.829165Z","shell.execute_reply.started":"2025-06-03T05:21:19.828984Z","shell.execute_reply":"2025-06-03T05:21:19.828997Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_loader = datamodule.val_dataloader()\ntrainer.validate(dataloaders=val_loader)","metadata":{"papermill":{"duration":959.542695,"end_time":"2023-06-30T09:55:32.61869","exception":false,"start_time":"2023-06-30T09:39:33.075995","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.830662Z","iopub.status.idle":"2025-06-03T05:21:19.830932Z","shell.execute_reply.started":"2025-06-03T05:21:19.830812Z","shell.execute_reply":"2025-06-03T05:21:19.830825Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cpu\")   #\"cuda:0\"\n\nmodel.eval()\ny_true=[]\ny_pred=[]\nwith torch.no_grad():\n    for val_data in datamodule.val_dataloader():\n        val_images, val_labels = val_data[0].to(device), val_data[1].to(device)\n        pred = model(val_images).argmax(dim=1)\n        for i in range(len(pred)):\n            y_true.append(val_labels[i].item())\n            y_pred.append(pred[i].item())\n\nprint(classification_report(y_true, y_pred, target_names=class_names, labels=list(range(len(class_names))), digits=4))","metadata":{"papermill":{"duration":5.368379,"end_time":"2023-06-30T09:55:39.113208","exception":false,"start_time":"2023-06-30T09:55:33.744829","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.831627Z","iopub.status.idle":"2025-06-03T05:21:19.831891Z","shell.execute_reply.started":"2025-06-03T05:21:19.83178Z","shell.execute_reply":"2025-06-03T05:21:19.831792Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"datamodule.setup(stage='test')","metadata":{"papermill":{"duration":0.008862,"end_time":"2023-06-30T09:55:39.131596","exception":false,"start_time":"2023-06-30T09:55:39.122734","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2025-06-03T05:21:19.832759Z","iopub.status.idle":"2025-06-03T05:21:19.833001Z","shell.execute_reply.started":"2025-06-03T05:21:19.8329Z","shell.execute_reply":"2025-06-03T05:21:19.832909Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\ny_true=[]\ny_pred=[]\nwith torch.no_grad():\n    for test_data in datamodule.test_dataloader():\n        test_images, test_labels =test_data[0].to(device), test_data[1].to(device)\n        pred = model(test_images).argmax(dim=1)\n        for i in range(len(pred)):\n            y_true.append(test_labels[i].item())\n            y_pred.append(pred[i].item())","metadata":{"papermill":{"duration":0.009079,"end_time":"2023-06-30T09:55:39.150422","exception":false,"start_time":"2023-06-30T09:55:39.141343","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2025-06-03T05:21:19.833856Z","iopub.status.idle":"2025-06-03T05:21:19.83409Z","shell.execute_reply.started":"2025-06-03T05:21:19.833965Z","shell.execute_reply":"2025-06-03T05:21:19.833973Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TEST['gesture']=y_pred\nTEST['gesture']=TEST['gesture'].map(reverse_mapping)\ndisplay(TEST[['row_id','gesture']])\nsubmit=TEST[['row_id','gesture']]\n#submit.to_csv('submission.csv',index=False)","metadata":{"execution":{"iopub.status.busy":"2025-06-03T05:21:19.834958Z","iopub.status.idle":"2025-06-03T05:21:19.835788Z","shell.execute_reply.started":"2025-06-03T05:21:19.835603Z","shell.execute_reply":"2025-06-03T05:21:19.835619Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!rm -rf train","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"---","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport polars as pl\nimport kaggle_evaluation.cmi_inference_server","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.836629Z","iopub.status.idle":"2025-06-03T05:21:19.836873Z","shell.execute_reply.started":"2025-06-03T05:21:19.836761Z","shell.execute_reply":"2025-06-03T05:21:19.836771Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# preprocess one sequence\ndef preprocess_sequence(seq_df: pd.DataFrame) -> np.ndarray:\n    data = seq_df.iloc[:,16:].to_numpy()\n    data = data.reshape(-1, 1, 5*8, 8)  \n    return data.astype(\"float32\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def predict(sequence: pl.DataFrame, demographics: pl.DataFrame) -> str:\n    model.eval()\n    arr = preprocess_sequence(sequence.to_pandas())\n    x = torch.from_numpy(arr).transpose(0,1).unsqueeze(0)  \n    logits = model(x)\n    idx = logits.argmax(1).item()\n    \n    return str(reverse_mapping[idx])","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"inference_server = kaggle_evaluation.cmi_inference_server.CMIInferenceServer(predict)\nif os.getenv('KAGGLE_IS_COMPETITION_RERUN'):\n    inference_server.serve()\nelse:\n    inference_server.run_local_gateway(\n        data_paths=(\n            '/kaggle/input/cmi-detect-behavior-with-sensor-data/test.csv',\n            '/kaggle/input/cmi-detect-behavior-with-sensor-data/test_demographics.csv',\n        )\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T05:21:19.838998Z","iopub.status.idle":"2025-06-03T05:21:19.839319Z","shell.execute_reply.started":"2025-06-03T05:21:19.839163Z","shell.execute_reply":"2025-06-03T05:21:19.839177Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sub = pd.read_parquet('submission.parquet')\ndisplay(sub)","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}