{"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":113366,"databundleVersionId":13605326,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom pylab import rcParams\nfrom wordcloud import WordCloud\nimport re\nimport warnings\n\nimport torch\nfrom torch.utils.data import DataLoader, TensorDataset\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score\n\nfrom transformers import AutoTokenizer, AutoModelForSequenceClassification\nfrom torch.optim import AdamW\n\n# To avoid warnings\nwarnings.filterwarnings('ignore')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:55:58.802822Z","iopub.execute_input":"2025-09-16T10:55:58.803223Z","iopub.status.idle":"2025-09-16T10:56:13.504111Z","shell.execute_reply.started":"2025-09-16T10:55:58.803188Z","shell.execute_reply":"2025-09-16T10:56:13.503052Z"}},"outputs":[],"execution_count":1},{"cell_type":"code","source":"Base_path = \"/kaggle/input/comments-classification/Dataset\"\ntrain_path = \"/kaggle/input/comments-classification/Dataset/train.csv\"\ntest_path = \"/kaggle/input/comments-classification/Dataset/test.csv\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:56:13.505691Z","iopub.execute_input":"2025-09-16T10:56:13.506312Z","iopub.status.idle":"2025-09-16T10:56:13.511509Z","shell.execute_reply.started":"2025-09-16T10:56:13.506279Z","shell.execute_reply":"2025-09-16T10:56:13.510141Z"}},"outputs":[],"execution_count":2},{"cell_type":"code","source":"train = pd.read_csv(f\"{train_path}\")\ntest = pd.read_csv(f\"{test_path}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:56:13.51248Z","iopub.execute_input":"2025-09-16T10:56:13.513084Z","iopub.status.idle":"2025-09-16T10:56:17.428745Z","shell.execute_reply.started":"2025-09-16T10:56:13.513052Z","shell.execute_reply":"2025-09-16T10:56:17.42783Z"}},"outputs":[],"execution_count":3},{"cell_type":"code","source":"total_samples = len(train)\nprint(\"Total samples:\", total_samples)\n\n# Percentage of class 0\ncount_0 = (train['psychotic_depression'] == 0).sum()\npercent_0 = (count_0 / total_samples) * 100\nprint(f\"Percentage of 0: {percent_0:.2f}%\")\n\n# Percentage of class 1\ncount_1 = (train['psychotic_depression'] == 1).sum()\npercent_1 = (count_1 / total_samples) * 100\nprint(f\"Percentage of 1: {percent_1:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:56:17.430815Z","iopub.execute_input":"2025-09-16T10:56:17.43107Z","iopub.status.idle":"2025-09-16T10:56:17.449212Z","shell.execute_reply.started":"2025-09-16T10:56:17.43105Z","shell.execute_reply":"2025-09-16T10:56:17.448375Z"}},"outputs":[{"name":"stdout","text":"Total samples: 159571\nPercentage of 0: 90.42%\nPercentage of 1: 9.58%\n","output_type":"stream"}],"execution_count":4},{"cell_type":"code","source":"# Clean data first\ntrain = train[train['comment_text'].notnull()]\ntrain = train[train['comment_text'].str.strip() != ''].reset_index(drop=True)\n\n# Separate minority and majority class\nminority_df = train[train['psychotic_depression'] == 1]\nmajority_df = train[train['psychotic_depression'] == 0]\n\n# Sample randomly from majority\nmajority_sampled_df = majority_df.sample(n=25000, random_state=42)\n\n# Combine minority and sampled majority\ntrain_sampled = pd.concat([minority_df, majority_sampled_df]).reset_index(drop=True)\n\nprint(f\"Minority class count: {minority_df.shape[0]}\")\nprint(f\"Majority class sampled count: {majority_sampled_df.shape[0]}\")\nprint(f\"Final sampled dataset shape: {train_sampled.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:56:17.450357Z","iopub.execute_input":"2025-09-16T10:56:17.450751Z","iopub.status.idle":"2025-09-16T10:56:17.668446Z","shell.execute_reply.started":"2025-09-16T10:56:17.45072Z","shell.execute_reply":"2025-09-16T10:56:17.66752Z"}},"outputs":[{"name":"stdout","text":"Minority class count: 15294\nMajority class sampled count: 25000\nFinal sampled dataset shape: (40294, 3)\n","output_type":"stream"}],"execution_count":5},{"cell_type":"code","source":"train_texts, test_texts, train_labels, test_labels = train_test_split(\n    train_sampled['comment_text'],    \n    train_sampled.iloc[:, 2:],          \n    test_size=0.25,\n    random_state=42                 \n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:56:17.669765Z","iopub.execute_input":"2025-09-16T10:56:17.670116Z","iopub.status.idle":"2025-09-16T10:56:17.685061Z","shell.execute_reply.started":"2025-09-16T10:56:17.67006Z","shell.execute_reply":"2025-09-16T10:56:17.684145Z"}},"outputs":[],"execution_count":6},{"cell_type":"code","source":"def simple_clean(text):\n    text = re.sub(r'<.*?>', '', text)            \n    text = re.sub(r'\\s+', ' ', text).strip()     \n    return text\n\ntrain_texts = train_texts.apply(simple_clean).reset_index(drop=True)\ntest_texts = test_texts.apply(simple_clean).reset_index(drop=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:56:17.686168Z","iopub.execute_input":"2025-09-16T10:56:17.686529Z","iopub.status.idle":"2025-09-16T10:56:18.678293Z","shell.execute_reply.started":"2025-09-16T10:56:17.68648Z","shell.execute_reply":"2025-09-16T10:56:18.677404Z"}},"outputs":[],"execution_count":7},{"cell_type":"code","source":"text_lengths = train_texts.apply(lambda x: len(x.split()))\nprint(f\"Mean length: {text_lengths.mean()}\")\nprint(f\"Median length: {text_lengths.median()}\")\nprint(f\"Max length: {text_lengths.max()}\")\nprint(f\"Min length: {text_lengths.min()}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:56:18.679329Z","iopub.execute_input":"2025-09-16T10:56:18.67967Z","iopub.status.idle":"2025-09-16T10:56:18.798976Z","shell.execute_reply.started":"2025-09-16T10:56:18.679641Z","shell.execute_reply":"2025-09-16T10:56:18.798139Z"}},"outputs":[{"name":"stdout","text":"Mean length: 62.268034414295165\nMedian length: 31.0\nMax length: 1403\nMin length: 0\n","output_type":"stream"}],"execution_count":8},{"cell_type":"code","source":"import nltk\nnltk.download('stopwords')\nfrom nltk.corpus import stopwords\n\nstop_words = set(stopwords.words('english'))\n\ndef remove_stopwords(text):\n    words = text.split()\n    filtered_words = [word for word in words if word.lower() not in stop_words]\n    return ' '.join(filtered_words)\n\ntrain_texts_cleaned = [remove_stopwords(text) for text in train_texts]\ntest_texts_cleaned = [remove_stopwords(text) for text in test_texts]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:56:18.799998Z","iopub.execute_input":"2025-09-16T10:56:18.800826Z","iopub.status.idle":"2025-09-16T10:56:20.441579Z","shell.execute_reply.started":"2025-09-16T10:56:18.80079Z","shell.execute_reply":"2025-09-16T10:56:20.440643Z"}},"outputs":[{"name":"stderr","text":"[nltk_data] Downloading package stopwords to /usr/share/nltk_data...\n[nltk_data]   Package stopwords is already up-to-date!\n","output_type":"stream"}],"execution_count":9},{"cell_type":"code","source":"tokenizer = AutoTokenizer.from_pretrained('bert-base-cased')\nnum_labels = train_labels.shape[1]\n\ntrain_encodings = tokenizer(\n    train_texts_cleaned,\n    truncation=True,\n    padding=True,\n)\n\ntest_encodings = tokenizer(\n    test_texts_cleaned,\n    truncation=True,\n    padding=True,\n)\n\nmodel = AutoModelForSequenceClassification.from_pretrained(\n    'bert-base-cased',\n    num_labels=num_labels,\n    problem_type=\"multi_label_classification\"\n)\n\ndevice = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\nmodel.to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:56:20.44405Z","iopub.execute_input":"2025-09-16T10:56:20.444432Z","iopub.status.idle":"2025-09-16T10:57:01.495924Z","shell.execute_reply.started":"2025-09-16T10:56:20.444401Z","shell.execute_reply":"2025-09-16T10:57:01.49508Z"}},"outputs":[{"output_type":"display_data","data":{"text/plain":"tokenizer_config.json:   0%|          | 0.00/49.0 [00:00<?, ?B/s]","application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"2247c9e6d7d144f99c6021a77bb4b359"}},"metadata":{}},{"output_type":"display_data","data":{"text/plain":"config.json:   0%|          | 0.00/570 [00:00<?, ?B/s]","application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"90cca31d1b05444f9ad2f24d74fa320b"}},"metadata":{}},{"output_type":"display_data","data":{"text/plain":"vocab.txt:   0%|          | 0.00/213k [00:00<?, ?B/s]","application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"7ca06794e0d14ab394a21185885606fb"}},"metadata":{}},{"output_type":"display_data","data":{"text/plain":"tokenizer.json:   0%|          | 0.00/436k [00:00<?, ?B/s]","application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"e170d683e51b45f18aaedd977d69140b"}},"metadata":{}},{"name":"stderr","text":"2025-09-16 10:56:39.856991: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\nWARNING: All log messages before absl::InitializeLog() is called are written to STDERR\nE0000 00:00:1758020200.229399      36 cuda_dnn.cc:8310] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\nE0000 00:00:1758020200.336389      36 cuda_blas.cc:1418] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n","output_type":"stream"},{"output_type":"display_data","data":{"text/plain":"model.safetensors:   0%|          | 0.00/436M [00:00<?, ?B/s]","application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"73826a9bff4c493ea85c6b5b611a8494"}},"metadata":{}},{"name":"stderr","text":"Some weights of BertForSequenceClassification were not initialized from the model checkpoint at bert-base-cased and are newly initialized: ['classifier.bias', 'classifier.weight']\nYou should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n","output_type":"stream"},{"execution_count":10,"output_type":"execute_result","data":{"text/plain":"BertForSequenceClassification(\n  (bert): BertModel(\n    (embeddings): BertEmbeddings(\n      (word_embeddings): Embedding(28996, 768, padding_idx=0)\n      (position_embeddings): Embedding(512, 768)\n      (token_type_embeddings): Embedding(2, 768)\n      (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n      (dropout): Dropout(p=0.1, inplace=False)\n    )\n    (encoder): BertEncoder(\n      (layer): ModuleList(\n        (0-11): 12 x BertLayer(\n          (attention): BertAttention(\n            (self): BertSdpaSelfAttention(\n              (query): Linear(in_features=768, out_features=768, bias=True)\n              (key): Linear(in_features=768, out_features=768, bias=True)\n              (value): Linear(in_features=768, out_features=768, bias=True)\n              (dropout): Dropout(p=0.1, inplace=False)\n            )\n            (output): BertSelfOutput(\n              (dense): Linear(in_features=768, out_features=768, bias=True)\n              (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n              (dropout): Dropout(p=0.1, inplace=False)\n            )\n          )\n          (intermediate): BertIntermediate(\n            (dense): Linear(in_features=768, out_features=3072, bias=True)\n            (intermediate_act_fn): GELUActivation()\n          )\n          (output): BertOutput(\n            (dense): Linear(in_features=3072, out_features=768, bias=True)\n            (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n            (dropout): Dropout(p=0.1, inplace=False)\n          )\n        )\n      )\n    )\n    (pooler): BertPooler(\n      (dense): Linear(in_features=768, out_features=768, bias=True)\n      (activation): Tanh()\n    )\n  )\n  (dropout): Dropout(p=0.1, inplace=False)\n  (classifier): Linear(in_features=768, out_features=1, bias=True)\n)"},"metadata":{}}],"execution_count":10},{"cell_type":"code","source":"def prepare_data(texts, labels, tokenizer, max_length=256):\n    encoded = tokenizer(\n        texts.tolist(),\n        padding='max_length',\n        truncation=True,\n        max_length=max_length,\n        return_tensors='pt'\n    )\n\n    input_ids = encoded['input_ids']\n    attention_mask = encoded['attention_mask']\n    labels = torch.tensor(labels.values, dtype=torch.float32)\n\n    return input_ids, attention_mask, labels\n\n\nclass ToxicCommentsDataset(torch.utils.data.Dataset):\n    def __init__(self, input_ids, attention_mask, labels):\n        self.input_ids = input_ids\n        self.attention_mask = attention_mask\n        self.labels = labels\n\n    def __len__(self):\n        return len(self.input_ids)\n\n    def __getitem__(self, idx):\n        return {\n            'input_ids': self.input_ids[idx],\n            'attention_mask': self.attention_mask[idx],\n            'labels': self.labels[idx]\n        }\n\n\n# Prepare datasets\ntrain_input_ids, train_attention_mask, train_labels = prepare_data(train_texts, train_labels, tokenizer)\ntest_input_ids, test_attention_mask, test_labels = prepare_data(test_texts, test_labels, tokenizer)\n\ntrain_dataset = ToxicCommentsDataset(train_input_ids, train_attention_mask, train_labels)\ntest_dataset = ToxicCommentsDataset(test_input_ids, test_attention_mask, test_labels)\n\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\ntest_loader = DataLoader(test_dataset, batch_size=32)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:57:01.49674Z","iopub.execute_input":"2025-09-16T10:57:01.49726Z","iopub.status.idle":"2025-09-16T10:57:15.478252Z","shell.execute_reply.started":"2025-09-16T10:57:01.497239Z","shell.execute_reply":"2025-09-16T10:57:15.477352Z"}},"outputs":[],"execution_count":11},{"cell_type":"code","source":"optimizer = AdamW(model.parameters(), lr=5e-5)\nloss_fn = torch.nn.BCEWithLogitsLoss()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:57:15.479198Z","iopub.execute_input":"2025-09-16T10:57:15.479462Z","iopub.status.idle":"2025-09-16T10:57:15.484816Z","shell.execute_reply.started":"2025-09-16T10:57:15.479429Z","shell.execute_reply":"2025-09-16T10:57:15.484044Z"}},"outputs":[],"execution_count":12},{"cell_type":"code","source":"from tqdm import tqdm\nfrom sklearn.metrics import f1_score\n\nepochs = 3\n\nfor epoch in range(epochs):\n    print(f\"\\nEpoch {epoch + 1}/{epochs}\")\n\n    # Training\n    model.train()\n    train_loop = tqdm(train_loader, desc=\"Training\", leave=False)\n    \n    for batch in train_loop:\n        optimizer.zero_grad()\n        \n        input_ids = batch['input_ids'].to(device)\n        attention_mask = batch['attention_mask'].to(device)\n        labels = batch['labels'].to(device)\n\n        outputs = model(input_ids, attention_mask=attention_mask)\n        logits = outputs.logits\n\n        loss = loss_fn(logits, labels)\n        loss.backward()\n        optimizer.step()\n        \n        train_loop.set_postfix(loss=loss.item())\n\n    print(f\"Epoch {epoch + 1} training finished.\")\n\n    # Evaluation\n    model.eval()\n    all_preds, all_labels = [], []\n    val_loop = tqdm(test_loader, desc=\"Validation\", leave=False)\n    \n    with torch.no_grad():\n        for batch in val_loop:\n            input_ids = batch['input_ids'].to(device)\n            attention_mask = batch['attention_mask'].to(device)\n            labels = batch['labels'].to(device)\n\n            outputs = model(input_ids, attention_mask=attention_mask)\n            logits = outputs.logits\n            preds = torch.sigmoid(logits).cpu().numpy()  # Sigmoid activation for probabilities\n\n            all_preds.extend(preds)\n            all_labels.extend(labels.cpu().numpy())\n\n    # Binarize predictions at threshold 0.5\n    all_preds = np.array(all_preds) >= 0.5\n    f1 = f1_score(all_labels, all_preds, average='micro')\n\n    print(f\"Validation F1 (micro) after epoch {epoch + 1}: {f1:.4f}\")\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T10:57:15.485694Z","iopub.execute_input":"2025-09-16T10:57:15.48596Z","iopub.status.idle":"2025-09-16T12:09:55.363905Z","shell.execute_reply.started":"2025-09-16T10:57:15.485931Z","shell.execute_reply":"2025-09-16T12:09:55.363131Z"}},"outputs":[{"name":"stdout","text":"\nEpoch 1/3\n","output_type":"stream"},{"name":"stderr","text":"                                                                        \r","output_type":"stream"},{"name":"stdout","text":"Epoch 1 training finished.\n","output_type":"stream"},{"name":"stderr","text":"                                                             \r","output_type":"stream"},{"name":"stdout","text":"Validation F1 (micro) after epoch 1: 0.9305\n\nEpoch 2/3\n","output_type":"stream"},{"name":"stderr","text":"                                                                         \r","output_type":"stream"},{"name":"stdout","text":"Epoch 2 training finished.\n","output_type":"stream"},{"name":"stderr","text":"                                                             \r","output_type":"stream"},{"name":"stdout","text":"Validation F1 (micro) after epoch 2: 0.9346\n\nEpoch 3/3\n","output_type":"stream"},{"name":"stderr","text":"                                                                          \r","output_type":"stream"},{"name":"stdout","text":"Epoch 3 training finished.\n","output_type":"stream"},{"name":"stderr","text":"                                                             ","output_type":"stream"},{"name":"stdout","text":"Validation F1 (micro) after epoch 3: 0.9337\n","output_type":"stream"},{"name":"stderr","text":"\r","output_type":"stream"}],"execution_count":13},{"cell_type":"code","source":"from sklearn.metrics import classification_report, confusion_matrix\nimport seaborn as sns\n\nprint(\"\\nClassification Report:\")\nprint(classification_report(all_labels, all_preds))\n\n# Compute and plot confusion matrix\ncm = confusion_matrix(all_labels, all_preds)\nplt.figure(figsize=(8,6))\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues')\nplt.xlabel('Predicted')\nplt.ylabel('Actual')\nplt.title(f'Confusion Matrix - Epoch {epoch+1}')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T12:09:55.36468Z","iopub.execute_input":"2025-09-16T12:09:55.364968Z","iopub.status.idle":"2025-09-16T12:09:55.882999Z","shell.execute_reply.started":"2025-09-16T12:09:55.364943Z","shell.execute_reply":"2025-09-16T12:09:55.882216Z"}},"outputs":[{"name":"stdout","text":"\nClassification Report:\n              precision    recall  f1-score   support\n\n         0.0       0.94      0.95      0.95      6229\n         1.0       0.92      0.90      0.91      3845\n\n    accuracy                           0.93     10074\n   macro avg       0.93      0.93      0.93     10074\nweighted avg       0.93      0.93      0.93     10074\n\n","output_type":"stream"},{"output_type":"display_data","data":{"text/plain":"<Figure size 800x600 with 2 Axes>","image/png":"iVBORw0KGgoAAAANSUhEUgAAApIAAAIjCAYAAACwHvu2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABJ/0lEQVR4nO3deVhV1f7H8c8B4YCMTkypOJVKmVOmZGreTDI0Tb1lk1ha2UVLcMoGp0q6ljmm1rXCW5qZlZXkgJqaSWkWZZbmVFQKTimKCgr794c/zvWIJqw4gp736z7neWLvddZee6f3fu9nrb2wWZZlCQAAACghj7IeAAAAAC5NFJIAAAAwQiEJAAAAIxSSAAAAMEIhCQAAACMUkgAAADBCIQkAAAAjFJIAAAAwQiEJAAAAIxSSQBnatm2bOnbsqKCgINlsNi1cuLBU+//ll19ks9mUnJxcqv1eym666SbddNNNZT2McqlWrVrq3LlzWQ8DwCWEQhJub8eOHXrkkUdUp04d+fj4KDAwUK1bt9bkyZN1/Phxl147Li5OmzZt0vPPP6+33npL1113nUuvdzH16dNHNptNgYGB53yO27Ztk81mk81m00svvVTi/nfv3q3Ro0crPT29FEZ7cdSqVctxz2d/br311rIe3t+WkJCgZs2aqXLlyqpYsaIaNmyo0aNH6+jRo2U9NAAuUqGsBwCUpZSUFP3zn/+U3W5X7969dc011ygvL09r167V0KFDtXnzZr322msuufbx48eVlpamp556SgMGDHDJNSIjI3X8+HF5eXm5pP8LqVChgo4dO6ZPPvlEd955p9O5OXPmyMfHRydOnDDqe/fu3RozZoxq1aqlJk2aFPt7y5YtM7peaWnSpIkGDx5c5HhEREQZjKZ0bdiwQW3atNEDDzwgHx8fffvtt3rhhRe0fPlyrVmzRh4eZBfA5YZCEm5r165d6tWrlyIjI7Vy5UqFh4c7zsXHx2v79u1KSUlx2fX37dsnSQoODnbZNWw2m3x8fFzW/4XY7Xa1bt1a77zzTpFCcu7cuYqNjdX7779/UcZy7NgxVaxYUd7e3hfleudzxRVX6L777ivTMbjK2rVrixyrW7euhgwZovXr16tVq1ZlMCoArsT/PYTbGj9+vI4eParXX3/dqYgsVK9ePT3++OOOn0+dOqVnn31WdevWld1uV61atfTkk08qNzfX6XuF68zWrl2r66+/Xj4+PqpTp47++9//OtqMHj1akZGRkqShQ4fKZrOpVq1akk5PCRf+85lGjx4tm83mdCw1NVU33nijgoOD5e/vr/r16+vJJ590nD/fGsmVK1eqTZs28vPzU3BwsLp27aqffvrpnNfbvn27+vTpo+DgYAUFBemBBx7QsWPHzv9gz3LPPfdo8eLFOnTokOPYhg0btG3bNt1zzz1F2h88eFBDhgxRo0aN5O/vr8DAQHXq1Enfffedo82qVavUokULSdIDDzzgmB4uvM+bbrpJ11xzjTZu3Ki2bduqYsWKjudy9hrJuLg4+fj4FLn/mJgYVapUSbt37y72vZaWPn36yN/fXzt37lRMTIz8/PwUERGhsWPHyrIsp7Y5OTkaPHiwatSoIbvdrvr16+ull14q0k6S3n77bV1//fWqWLGiKlWqpLZt254zof2rP7slVfhn+cx//wAuHxSScFuffPKJ6tSpoxtuuKFY7fv166eRI0eqWbNmmjhxotq1a6ekpCT16tWrSNvt27erZ8+euuWWWzRhwgRVqlRJffr00ebNmyVJ3bt318SJEyVJd999t9566y1NmjSpROPfvHmzOnfurNzcXI0dO1YTJkzQ7bffri+++OIvv7d8+XLFxMRo7969Gj16tBITE7Vu3Tq1bt1av/zyS5H2d955p44cOaKkpCTdeeedSk5O1pgxY4o9zu7du8tms+mDDz5wHJs7d64aNGigZs2aFWm/c+dOLVy4UJ07d9bLL7+soUOHatOmTWrXrp2jqGvYsKHGjh0rSXr44Yf11ltv6a233lLbtm0d/Rw4cECdOnVSkyZNNGnSJLVv3/6c45s8ebKqVaumuLg45efnS5JeffVVLVu2TFOnTi31KeeTJ09q//79RT5nryPNz8/XrbfeqtDQUI0fP17NmzfXqFGjNGrUKEcby7J0++23a+LEibr11lv18ssvq379+ho6dKgSExOd+hszZozuv/9+eXl5aezYsRozZoxq1KihlStXOrW70J/dCzl16pT279+v3bt3a9myZXr66acVEBCg66+/3vCJASjXLMANHT582JJkde3atVjt09PTLUlWv379nI4PGTLEkmStXLnScSwyMtKSZK1Zs8ZxbO/evZbdbrcGDx7sOLZr1y5LkvXiiy869RkXF2dFRkYWGcOoUaOsM//KTpw4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\n"},"metadata":{}}],"execution_count":14},{"cell_type":"code","source":"def simple_clean(text):\n    text = re.sub(r'<.*?>', '', text)            \n    text = re.sub(r'\\s+', ' ', text).strip()     \n    return text\n\ntest_texts_1 = test_texts.apply(simple_clean).reset_index(drop=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T12:09:55.883795Z","iopub.execute_input":"2025-09-16T12:09:55.884062Z","iopub.status.idle":"2025-09-16T12:09:56.123424Z","shell.execute_reply.started":"2025-09-16T12:09:55.884038Z","shell.execute_reply":"2025-09-16T12:09:56.122242Z"}},"outputs":[],"execution_count":15},{"cell_type":"code","source":"from transformers import AutoTokenizer, AutoModelForSequenceClassification\n\n# Save model and tokenizer\nmodel.save_pretrained('saved_model/')\ntokenizer.save_pretrained('saved_model/')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T12:11:10.186331Z","iopub.execute_input":"2025-09-16T12:11:10.187168Z","iopub.status.idle":"2025-09-16T12:11:11.20698Z","shell.execute_reply.started":"2025-09-16T12:11:10.187132Z","shell.execute_reply":"2025-09-16T12:11:11.206281Z"}},"outputs":[{"execution_count":17,"output_type":"execute_result","data":{"text/plain":"('saved_model/tokenizer_config.json',\n 'saved_model/special_tokens_map.json',\n 'saved_model/vocab.txt',\n 'saved_model/added_tokens.json',\n 'saved_model/tokenizer.json')"},"metadata":{}}],"execution_count":17},{"cell_type":"code","source":"test_texts_1 = test['comment_text'].astype(str).tolist()  # ensures all entries are strings\n\ntest_encodings = tokenizer(\n    test_texts_1,  # correct list\n    truncation=True,\n    padding=True,   # optional, usually needed\n    return_tensors=\"pt\"  # if using PyTorch\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T12:11:17.48449Z","iopub.execute_input":"2025-09-16T12:11:17.484795Z","iopub.status.idle":"2025-09-16T12:12:35.614304Z","shell.execute_reply.started":"2025-09-16T12:11:17.484771Z","shell.execute_reply":"2025-09-16T12:12:35.613665Z"}},"outputs":[],"execution_count":18},{"cell_type":"code","source":"class TestDataset(torch.utils.data.Dataset):\n    def __init__(self, encodings):\n        self.encodings = encodings\n\n    def __len__(self):\n        return len(self.encodings['input_ids'])\n\n    def __getitem__(self, idx):\n        return {\n            'input_ids': self.encodings['input_ids'][idx],\n            'attention_mask': self.encodings['attention_mask'][idx]\n        }\n\ntest_dataset = TestDataset(test_encodings)\ntest_loader = DataLoader(test_dataset, batch_size=128)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T12:13:23.82076Z","iopub.execute_input":"2025-09-16T12:13:23.821375Z","iopub.status.idle":"2025-09-16T12:13:23.826261Z","shell.execute_reply.started":"2025-09-16T12:13:23.821351Z","shell.execute_reply":"2025-09-16T12:13:23.825497Z"}},"outputs":[],"execution_count":22},{"cell_type":"code","source":"from tqdm import tqdm\n\nmodel.eval()\nall_preds = []\n\nwith torch.no_grad():\n    for batch in tqdm(test_loader, desc=\"Evaluating\"):\n        input_ids = batch['input_ids'].to(device)\n        attention_mask = batch['attention_mask'].to(device)\n\n        outputs = model(input_ids, attention_mask=attention_mask)\n        logits = outputs.logits\n\n        probs = torch.sigmoid(logits).cpu().numpy()  # Get probabilities (0 to 1)\n        all_preds.extend(probs)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T12:13:25.917036Z","iopub.execute_input":"2025-09-16T12:13:25.917352Z","iopub.status.idle":"2025-09-16T13:35:47.768754Z","shell.execute_reply.started":"2025-09-16T12:13:25.917332Z","shell.execute_reply":"2025-09-16T13:35:47.768077Z"}},"outputs":[{"name":"stderr","text":"Evaluating: 100%|██████████| 1197/1197 [1:22:21<00:00,  4.13s/it]\n","output_type":"stream"}],"execution_count":23},{"cell_type":"code","source":"all_preds = np.array(all_preds) >= 0.5  # Convert probs to binary labels\n\nsubmission = pd.DataFrame({\n    \"ID\": test['id'],\n    \"psychotic_depression\": all_preds[:, 0]  # If multiple labels, select the correct column(s)\n})\n\nsubmission.to_csv(\"/kaggle/working/submission.csv\", index=False)\nprint(\"Submission file saved!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-16T13:35:47.770079Z","iopub.execute_input":"2025-09-16T13:35:47.770537Z","iopub.status.idle":"2025-09-16T13:35:48.004038Z","shell.execute_reply.started":"2025-09-16T13:35:47.770518Z","shell.execute_reply":"2025-09-16T13:35:48.003327Z"}},"outputs":[{"name":"stdout","text":"Submission file saved!\n","output_type":"stream"}],"execution_count":24}]}