{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.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":130287,"databundleVersionId":15633993,"sourceType":"competition"}],"dockerImageVersionId":31260,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"#  1 — Install Dependencies","metadata":{}},{"cell_type":"code","source":"!pip install -q transformers sentencepiece\n\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:38:57.203606Z","iopub.execute_input":"2026-02-13T08:38:57.203863Z","iopub.status.idle":"2026-02-13T08:39:01.359633Z","shell.execute_reply.started":"2026-02-13T08:38:57.203842Z","shell.execute_reply":"2026-02-13T08:39:01.358636Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#  2 — Imports","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nfrom transformers import T5Tokenizer, T5EncoderModel\nfrom tqdm import tqdm\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:39:01.361291Z","iopub.execute_input":"2026-02-13T08:39:01.361602Z","iopub.status.idle":"2026-02-13T08:39:26.767624Z","shell.execute_reply.started":"2026-02-13T08:39:01.361560Z","shell.execute_reply":"2026-02-13T08:39:26.767069Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#  3 — Paths","metadata":{}},{"cell_type":"code","source":"DATA_PATH = \"/kaggle/input/motion-s-hierarchical-text-to-motion-generation-for-sign-language\"\n\ntrain_df = pd.read_csv(f\"{DATA_PATH}/train.csv\")\ntest_df = pd.read_csv(f\"{DATA_PATH}/test.csv\")\n\nprint(\"Train:\", train_df.shape)\nprint(\"Test:\", test_df.shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:39:26.768554Z","iopub.execute_input":"2026-02-13T08:39:26.769347Z","iopub.status.idle":"2026-02-13T08:39:27.297615Z","shell.execute_reply.started":"2026-02-13T08:39:26.769322Z","shell.execute_reply":"2026-02-13T08:39:27.296907Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 4 — Token Parser","metadata":{}},{"cell_type":"code","source":"def parse_tokens(s, seq_len=120):\n    if pd.isna(s):\n        return np.zeros(seq_len, dtype=int)\n\n    arr = np.array(list(map(int, s.split())))\n\n    if len(arr) > seq_len:\n        arr = arr[:seq_len]\n    else:\n        arr = np.pad(arr, (0, seq_len - len(arr)))\n\n    return arr\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:39:27.299146Z","iopub.execute_input":"2026-02-13T08:39:27.299454Z","iopub.status.idle":"2026-02-13T08:39:27.304375Z","shell.execute_reply.started":"2026-02-13T08:39:27.299422Z","shell.execute_reply":"2026-02-13T08:39:27.303543Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#  5 — Dataset Loader","metadata":{}},{"cell_type":"code","source":"class MotionDataset(Dataset):\n    def __init__(self, df, tokenizer, seq_len=120):\n        self.df = df\n        self.tokenizer = tokenizer\n        self.seq_len = seq_len\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n\n        tokens = self.tokenizer(\n            str(row[\"gloss\"]),\n            padding=\"max_length\",\n            truncation=True,\n            max_length=128,\n            return_tensors=\"pt\"\n        )\n\n        motion = parse_tokens(row[\"base_tokens\"], self.seq_len)\n\n        return {\n            \"input_ids\": tokens[\"input_ids\"].squeeze(0),\n            \"attention_mask\": tokens[\"attention_mask\"].squeeze(0),\n            \"motion\": torch.tensor(motion, dtype=torch.long)\n        }\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:39:27.305341Z","iopub.execute_input":"2026-02-13T08:39:27.305599Z","iopub.status.idle":"2026-02-13T08:39:27.325167Z","shell.execute_reply.started":"2026-02-13T08:39:27.305577Z","shell.execute_reply":"2026-02-13T08:39:27.324587Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 6 — Tokenizer & Loader","metadata":{}},{"cell_type":"code","source":"tokenizer = T5Tokenizer.from_pretrained(\"t5-small\")\n\ndataset = MotionDataset(train_df, tokenizer)\n\nloader = DataLoader(dataset, batch_size=16, shuffle=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:39:27.325866Z","iopub.execute_input":"2026-02-13T08:39:27.326099Z","iopub.status.idle":"2026-02-13T08:39:28.854994Z","shell.execute_reply.started":"2026-02-13T08:39:27.326079Z","shell.execute_reply":"2026-02-13T08:39:28.854400Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 7 — Lightweight Model","metadata":{}},{"cell_type":"code","source":"class LiteMotionGenerator(nn.Module):\n    def __init__(self, hidden=256):\n        super().__init__()\n\n        self.encoder = T5EncoderModel.from_pretrained(\"t5-small\")\n\n        for p in self.encoder.parameters():\n            p.requires_grad = False\n\n        self.text_proj = nn.Linear(512, hidden)\n\n        layer = nn.TransformerEncoderLayer(\n            d_model=hidden,\n            nhead=4,\n            dim_feedforward=hidden * 2,\n            batch_first=True,\n        )\n\n        self.transformer = nn.TransformerEncoder(layer, num_layers=2)\n\n        self.head = nn.Linear(hidden, 512)\n\n    def forward(self, ids, mask, seq_len):\n        with torch.no_grad():\n            enc = self.encoder(ids, attention_mask=mask).last_hidden_state\n\n        pooled = enc.mean(dim=1)\n\n        x = self.text_proj(pooled)\n        x = x.unsqueeze(1).repeat(1, seq_len, 1)\n\n        x = self.transformer(x)\n\n        logits = self.head(x)\n        return logits\n\n\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:39:28.855838Z","iopub.execute_input":"2026-02-13T08:39:28.856133Z","iopub.status.idle":"2026-02-13T08:39:28.862219Z","shell.execute_reply.started":"2026-02-13T08:39:28.856097Z","shell.execute_reply":"2026-02-13T08:39:28.861572Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 8 — Training Setup","metadata":{}},{"cell_type":"code","source":"device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\nmodel = LiteMotionGenerator().to(device)\n\noptimizer = torch.optim.AdamW(model.parameters(), lr=3e-4)\ncriterion = nn.CrossEntropyLoss(ignore_index=0)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:39:28.862886Z","iopub.execute_input":"2026-02-13T08:39:28.863182Z","iopub.status.idle":"2026-02-13T08:39:30.966672Z","shell.execute_reply.started":"2026-02-13T08:39:28.863151Z","shell.execute_reply":"2026-02-13T08:39:30.966078Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 9 — Training Loop","metadata":{}},{"cell_type":"code","source":"EPOCHS = 3\n\nfor epoch in range(EPOCHS):\n    model.train()\n    total_loss = 0\n\n    for batch in tqdm(loader):\n        ids = batch[\"input_ids\"].to(device)\n        mask = batch[\"attention_mask\"].to(device)\n        motion = batch[\"motion\"].to(device)\n\n        seq_len = motion.size(1)\n\n        logits = model(ids, mask, seq_len)\n\n        loss = criterion(\n            logits.reshape(-1, 512),\n            motion.reshape(-1)\n        )\n\n        optimizer.zero_grad()\n        loss.backward()\n\n        torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)\n        optimizer.step()\n\n        total_loss += loss.item()\n\n    print(f\"Epoch {epoch+1} Loss: {total_loss:.2f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:39:30.967558Z","iopub.execute_input":"2026-02-13T08:39:30.967829Z","iopub.status.idle":"2026-02-13T08:40:44.290462Z","shell.execute_reply.started":"2026-02-13T08:39:30.967803Z","shell.execute_reply":"2026-02-13T08:40:44.289723Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 10 — Test Dataset","metadata":{}},{"cell_type":"code","source":"class TestDataset(torch.utils.data.Dataset):\n    def __init__(self, df, tokenizer):\n        self.df = df\n        self.tokenizer = tokenizer\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n\n        tokens = tokenizer(\n            str(row[\"gloss\"]),\n            padding=\"max_length\",\n            truncation=True,\n            max_length=128,\n            return_tensors=\"pt\",\n        )\n\n        return {\n            \"id\": int(row[\"id\"]),\n            \"input_ids\": tokens[\"input_ids\"].squeeze(0),\n            \"attention_mask\": tokens[\"attention_mask\"].squeeze(0),\n        }\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:40:44.292619Z","iopub.execute_input":"2026-02-13T08:40:44.292839Z","iopub.status.idle":"2026-02-13T08:40:44.297994Z","shell.execute_reply.started":"2026-02-13T08:40:44.292818Z","shell.execute_reply":"2026-02-13T08:40:44.297433Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_dataset = TestDataset(test_df, tokenizer)\n\ntest_loader = torch.utils.data.DataLoader(\n    test_dataset,\n    batch_size=16,\n    shuffle=False\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:40:44.298907Z","iopub.execute_input":"2026-02-13T08:40:44.299145Z","iopub.status.idle":"2026-02-13T08:40:44.310371Z","shell.execute_reply.started":"2026-02-13T08:40:44.299124Z","shell.execute_reply":"2026-02-13T08:40:44.309768Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 11 — Inference","metadata":{}},{"cell_type":"code","source":"outputs = []\n\nmodel.eval()\n\nwith torch.no_grad():\n    for batch in tqdm(test_loader):\n        ids = batch[\"input_ids\"].to(device)\n        mask = batch[\"attention_mask\"].to(device)\n\n        logits = model(ids, mask, 120)\n        preds = logits.argmax(-1).cpu().numpy()\n\n        for i in range(len(batch[\"id\"])):\n            sid = int(batch[\"id\"][i])\n            seq = preds[i]\n\n            row = [sid]\n            for _ in range(6):\n                row.append(\" \".join(map(str, seq)))\n\n            outputs.append(row)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:40:44.311114Z","iopub.execute_input":"2026-02-13T08:40:44.311333Z","iopub.status.idle":"2026-02-13T08:40:49.198888Z","shell.execute_reply.started":"2026-02-13T08:40:44.311301Z","shell.execute_reply":"2026-02-13T08:40:49.198192Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 12 — Submission","metadata":{}},{"cell_type":"code","source":"test_df = pd.read_csv(\n    \"/kaggle/input/motion-s-hierarchical-text-to-motion-generation-for-sign-language/test.csv\"\n)\n\ntest_ids = test_df[\"id\"].values\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:40:49.199829Z","iopub.execute_input":"2026-02-13T08:40:49.200122Z","iopub.status.idle":"2026-02-13T08:40:49.212915Z","shell.execute_reply.started":"2026-02-13T08:40:49.200097Z","shell.execute_reply":"2026-02-13T08:40:49.212234Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = pd.DataFrame(outputs, columns=[\n    \"id\",\n    \"base_tokens\",\n    \"residual_1\",\n    \"residual_2\",\n    \"residual_3\",\n    \"residual_4\",\n    \"residual_5\",\n])\n\nsubmission = submission.set_index(\"id\")\nsubmission = submission.loc[test_ids].reset_index()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:40:49.213847Z","iopub.execute_input":"2026-02-13T08:40:49.214155Z","iopub.status.idle":"2026-02-13T08:40:49.228538Z","shell.execute_reply.started":"2026-02-13T08:40:49.214131Z","shell.execute_reply":"2026-02-13T08:40:49.227753Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission.to_csv(\"submission_final.csv\", index=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:40:49.229505Z","iopub.execute_input":"2026-02-13T08:40:49.229796Z","iopub.status.idle":"2026-02-13T08:40:49.435938Z","shell.execute_reply.started":"2026-02-13T08:40:49.229765Z","shell.execute_reply":"2026-02-13T08:40:49.435387Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(len(submission), len(test_ids))\nprint((submission[\"id\"].values == test_ids).all())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-13T08:40:49.436816Z","iopub.execute_input":"2026-02-13T08:40:49.437093Z","iopub.status.idle":"2026-02-13T08:40:49.441452Z","shell.execute_reply.started":"2026-02-13T08:40:49.437063Z","shell.execute_reply":"2026-02-13T08:40:49.440790Z"}},"outputs":[],"execution_count":null}]}