{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":85517,"databundleVersionId":9677541,"sourceType":"competition"},{"sourceId":9897845,"sourceType":"datasetVersion","datasetId":6079802},{"sourceId":9898029,"sourceType":"datasetVersion","datasetId":6079939},{"sourceId":9898220,"sourceType":"datasetVersion","datasetId":6080080},{"sourceId":9899368,"sourceType":"datasetVersion","datasetId":6080894},{"sourceId":9899689,"sourceType":"datasetVersion","datasetId":6081121},{"sourceId":9899720,"sourceType":"datasetVersion","datasetId":6081141}],"dockerImageVersionId":30787,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset,DataLoader\nimport torchvision.transforms as transforms\nimport torchvision.datasets as datasets\nfrom tqdm import tqdm\nimport torch.nn.functional as F\nfrom torch.optim.lr_scheduler import OneCycleLR\nimport pickle \nimport csv\nfrom torchvision.transforms import ToPILImage\nimport torch\nimport numpy as np\nimport pandas as pd\nimport csv\n\ntorch.manual_seed(42)\ntorch.cuda.manual_seed(42)\ntorch.cuda.manual_seed_all(42)\n\ntorch.backends.cudnn.deterministic = True\ntorch.backends.cudnn.benchmark = True\n\nclass StochasticDepthBasicBlock(torch.jit.ScriptModule):\n    expansion = 1\n\n    def __init__(self, p, in_channels, out_channels, stride=1):\n        super().__init__()\n        self.p = p\n        \n        # Added PReLU instead of ReLU\n        self.residual = nn.Sequential(\n            nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False),\n            nn.BatchNorm2d(out_channels),\n            nn.PReLU(),\n            nn.Conv2d(out_channels, out_channels * self.expansion, kernel_size=3, padding=1, bias=False),\n            nn.BatchNorm2d(out_channels * self.expansion)\n        )\n\n        # Added SE block\n        self.se = SEBlock(out_channels * self.expansion)\n        \n        self.shortcut = nn.Sequential()\n        if stride != 1 or in_channels != out_channels * self.expansion:\n            self.shortcut = nn.Sequential(\n                nn.Conv2d(in_channels, out_channels * self.expansion, kernel_size=1, stride=stride, bias=False),\n                nn.BatchNorm2d(out_channels * self.expansion)\n            )\n        \n        # Added dropout for regularization\n        self.dropout = nn.Dropout2d(0.3)\n\n    def survival(self):\n        return torch.bernoulli(torch.tensor(self.p).float())\n\n    @torch.jit.script_method\n    def forward(self, x):\n        identity = self.shortcut(x)\n        \n        if self.training:\n            if self.survival():\n                out = self.residual(x)\n                out = self.se(out)\n                out = self.dropout(out)\n                out = out + identity\n            else:\n                out = identity\n        else:\n            out = self.residual(x) * self.p\n            out = self.se(out)\n            out = out + identity\n            \n        return F.relu(out)\n\nclass SEBlock(nn.Module):\n    def __init__(self, channel, reduction=16):\n        super().__init__()\n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n        self.fc = nn.Sequential(\n            nn.Linear(channel, channel // reduction, bias=False),\n            nn.ReLU(inplace=True),\n            nn.Linear(channel // reduction, channel, bias=False),\n            nn.Sigmoid()\n        )\n\n    def forward(self, x):\n        b, c, _, _ = x.size()\n        y = self.avg_pool(x).view(b, c)\n        y = self.fc(y).view(b, c, 1, 1)\n        return x * y.expand_as(x)\n\n# Cauchy Loss Implementation\nclass CauchyLoss(nn.Module):\n    def __init__(self, gamma=1, reduction='mean'):\n        super().__init__()\n        self.gamma = gamma\n        self.reduction = reduction\n\n    def forward(self, inputs, targets):\n        # Compute cross-entropy loss\n        ce_loss = F.cross_entropy(inputs, targets, reduction='none')\n        \n        # Apply the Cauchy function: log(1 + (loss / gamma)^2)\n        cauchy_loss = torch.log(1 + (ce_loss / self.gamma) ** 2)\n        \n        if self.reduction == 'mean':\n            return cauchy_loss.mean()\n        elif self.reduction == 'sum':\n            return cauchy_loss.sum()\n        else:\n            return cauchy_loss\n\n# Label Smoothing Cross Entropy Loss\nclass LabelSmoothingCrossEntropy(nn.Module):\n    def __init__(self, epsilon=0.1):\n        super().__init__()\n        self.epsilon = epsilon\n        self.log_softmax = nn.LogSoftmax(dim=-1)\n    \n    def forward(self, preds, target):\n        n_classes = preds.size(-1)\n        log_preds = self.log_softmax(preds)\n        loss = -log_preds.sum(dim=-1).mean()\n        nll = F.nll_loss(log_preds, target, reduction='mean')\n        return (1 - self.epsilon) * nll + self.epsilon * (loss / n_classes)\n\n# Combo Loss with Cauchy Loss\nclass ComboLoss(nn.Module):\n    def __init__(self, alpha=0.5, beta=0.5, gamma=1):\n        super().__init__()\n        self.alpha = alpha\n        self.beta = beta\n        self.cauchy = CauchyLoss(gamma=gamma)  # Replacing FocalLoss with CauchyLoss\n        self.label_smoothing = LabelSmoothingCrossEntropy()\n    \n    def forward(self, inputs, targets):\n        cauchy_loss = self.cauchy(inputs, targets)\n        smooth_loss = self.label_smoothing(inputs, targets)\n        return self.alpha * cauchy_loss + self.beta * smooth_loss\n\n# Confidence Aware Combo Loss with Cauchy Loss\nclass ConfidenceAwareComboLoss(nn.Module):\n    def __init__(self, alpha=0.5, beta=0.5, gamma=1, confidence_penalty=0.1):\n        super().__init__()\n        self.combo_loss = ComboLoss(alpha, beta, gamma)  # Using updated ComboLoss with CauchyLoss\n        self.confidence_penalty = confidence_penalty\n    \n    def forward(self, logits, targets):\n        combo_loss = self.combo_loss(logits, targets)\n        \n        # Confidence penalty\n        probs = F.softmax(logits, dim=1)\n        confidence = probs.gather(1, targets.unsqueeze(1)).squeeze()\n        confidence_penalty = -self.confidence_penalty * torch.log(confidence)\n        \n        return combo_loss + confidence_penalty.mean()\n\ndef train_model(model, train_loader, test_loader, epochs=300, device=\"cuda\"):\n    # Use the new ComboLoss\n    criterion = ConfidenceAwareComboLoss()\n    \n    optimizer = torch.optim.AdamW(\n        model.parameters(),\n        lr=0.001,\n        weight_decay=0.05\n    )\n    \n    scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs)\n\n    scaler = torch.cuda.amp.GradScaler()\n    \n    model = model.to(device)\n    best_acc = 0.0\n    patience = 20\n    early_stopping_counter = 0\n\n    for epoch in range(epochs):\n        model.train()\n        train_loss, correct, total = 0, 0, 0\n\n        # Progress bar for training\n        with tqdm(total=len(train_loader), desc=f\"Epoch {epoch + 1}/{epochs} (Training)\", unit='batch') as pbar:\n            for inputs, targets in train_loader:\n                inputs, targets = inputs.to(device), targets.to(device)\n                \n                with torch.cuda.amp.autocast():\n                    outputs = model(inputs)\n                    loss = criterion(outputs, targets)\n\n                optimizer.zero_grad()\n                scaler.scale(loss).backward()\n                scaler.step(optimizer)\n                scaler.update()\n\n                train_loss += loss.item()\n                _, predicted = outputs.max(1)\n                total += targets.size(0)\n                correct += predicted.eq(targets).sum().item()\n\n                pbar.set_postfix({\"Loss\": f\"{train_loss / (pbar.n + 1):.3f}\", \"Acc\": f\"{100. * correct / total:.2f}%\"})\n                pbar.update(1)\n\n        if epoch > 200:\n            torch.save(model.state_dict(), f'model_epoch_{epoch+1}.pth')\n\n        scheduler.step()\n\n        train_acc = 100. * correct / total\n        print(f'Epoch {epoch+1}/{epochs}: Train Loss: {train_loss/len(train_loader):.3f}, Train Acc: {train_acc:.3f}%')\n\n# The rest of the code (StochasticDepthResNet, main function, etc.) remains the same\nclass StochasticDepthResNet(nn.Module):\n    def __init__(self, block, num_blocks, num_classes=100, p_l=0.5):\n        super(StochasticDepthResNet, self).__init__()\n        self.in_channels = 64\n        \n        # Calculate linear decay survival probabilities\n        self.num_blocks = sum(num_blocks)\n        self.layer_positions = []\n        current_position = 0\n        for stage_blocks in num_blocks:\n            for _ in range(stage_blocks):\n                self.layer_positions.append(current_position)\n                current_position += 1\n        \n        # Initial convolution\n        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)\n        self.bn1 = nn.BatchNorm2d(64)\n        self.relu = nn.PReLU()  # Changed to PReLU\n        \n        # ResNet stages\n        self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1, p_l=p_l)\n        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2, p_l=p_l)\n        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2, p_l=p_l)\n        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2, p_l=p_l)\n        \n        # Final classification layer\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.fc = nn.Linear(512 * block.expansion, num_classes)\n        \n        # Initialize weights\n        for m in self.modules():\n            if isinstance(m, nn.Conv2d):\n                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')\n            elif isinstance(m, nn.BatchNorm2d):\n                nn.init.constant_(m.weight, 1)\n                nn.init.constant_(m.bias, 0)\n\n    def _make_layer(self, block, out_channels, num_blocks, stride, p_l):\n        strides = [stride] + [1]*(num_blocks-1)\n        layers = []\n        \n        for i, stride in enumerate(strides):\n            # Calculate survival probability for this layer\n            layer_position = self.layer_positions[len(layers)]\n            p_i = 1 - (layer_position / self.num_blocks) * (1 - p_l)\n            \n            layers.append(\n                block(p_i, self.in_channels, out_channels, stride)\n            )\n            self.in_channels = out_channels * block.expansion\n            \n        return nn.Sequential(*layers)\n\n    def forward(self, x):\n        # Initial convolution\n        out = self.relu(self.bn1(self.conv1(x)))\n        \n        # ResNet stages\n        out = self.layer1(out)\n        out = self.layer2(out)\n        out = self.layer3(out)\n        out = self.layer4(out)\n        \n        # Classification\n        out = self.avgpool(out)\n        out = torch.flatten(out, 1)\n        out = self.fc(out)\n        \n        return out\n\ndef stochastic_depth_resnet18(num_classes=100, p_l=0.5):\n    \"\"\"\n    Create a ResNet-18 model with stochastic depth\n    Args:\n        num_classes: number of output classes\n        p_l: target survival probability for the last layer\n    \"\"\"\n    return StochasticDepthResNet(StochasticDepthBasicBlock, [2, 2, 2, 2], \n                                num_classes=num_classes, p_l=p_l)\n\ndef stochastic_depth_resnet34(num_classes=100, p_l=0.5):\n    \"\"\"\n    Create a ResNet-34 model with stochastic depth\n    Args:\n        num_classes: number of output classes\n        p_l: target survival probability for the last layer\n    \"\"\"\n    return StochasticDepthResNet(StochasticDepthBasicBlock, [3, 4, 6, 3], \n                                num_classes=num_classes, p_l=p_l)\n\nclass CIFAR100Dataset(Dataset):\n    def __init__(self, file_path, transform = None):\n        with open(file_path, 'rb') as f:\n            self.data = pickle.load(f)\n            self.transform = transform\n            self.to_pil = ToPILImage()\n            \n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        image, label = self.data[idx]\n        if self.transform != None:\n            image = self.to_pil(image)\n            image = self.transform(image)\n        return image, label\n\n# Enhanced data augmentation\ntrain_transform = transforms.Compose([\n    transforms.RandomCrop(32, padding=4),\n    transforms.RandomHorizontalFlip(),\n    transforms.AutoAugment(transforms.AutoAugmentPolicy.CIFAR10),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.5071, 0.4867, 0.4408], std=[0.2675, 0.2565, 0.2761]),\n    transforms.RandomErasing(p=0.3)\n])\n\ntest_transform = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.5071, 0.4867, 0.4408], std=[0.2675, 0.2565, 0.2761])\n])\n\n# Increased batch size\nbatch_size = 128\n\ntrain_dataset = CIFAR100Dataset('/kaggle/input/col-774-a-3/train.pkl', train_transform)\ntest_dataset = CIFAR100Dataset('/kaggle/input/col-774-a-3/test.pkl', test_transform)\n\ntrain_loader = DataLoader(\n    train_dataset, \n    batch_size=batch_size, \n    shuffle=True, \n    num_workers=4,\n    pin_memory=True\n)\n\ntest_loader = DataLoader(\n    test_dataset, \n    batch_size=batch_size, \n    shuffle=False, \n    num_workers=4,\n    pin_memory=True\n)\n\nimport torch\nimport numpy as np\nimport pandas as pd\nimport csv\nfrom scipy import stats\n\ndef get_optimal_threshold(probs,class_id):\n    # Calculate distribution statistics\n    mean = np.mean(probs)\n    median = np.median(probs)\n    q75, q25 = np.percentile(probs, [75, 25])\n    iqr = q75 - q25\n    # Calculate skewness\n    skewness = stats.skew(probs)\n    print(class_id,f\"q25: {q25:.4f}, q75: {q75:.4f}, skewness: {skewness:.4f}, median: {median:.4f}\")\n\n    # Determine threshold based on distribution characteristics\n    if skewness > 1: \n        threshold = max(0.5, q25)  \n    elif skewness <= -2.5:\n        sorted_probs = np.sort(probs)\n        if len(sorted_probs) >= 185:\n            threshold = sorted_probs[-185]\n        else:\n            threshold = 1\n    elif skewness <= -2 and skewness > -2.5:\n        sorted_probs = np.sort(probs)\n        if len(sorted_probs) >= 150:\n            threshold = sorted_probs[-150]\n        else:\n            threshold = 1\n    elif skewness <= -1.9 and skewness > -2 :\n        sorted_probs = np.sort(probs)\n        if len(sorted_probs) >= 100:\n            threshold = sorted_probs[-100]\n        else:\n            threshold = 1\n    elif skewness >= -1.9 and skewness <= -1.0:\n        sorted_probs = np.sort(probs)\n        if len(sorted_probs) >= 20:\n            threshold = sorted_probs[-20]\n        else:\n            threshold = 1\n        threshold = 0.9781\n    elif -1.0 < skewness <= 0:\n        if median > 0.81:\n            # Function that peaks around 0.5 for skewness closer to -0.5\n            # Quadratic function that's flatter around -1 and rises more steeply towards -0.5\n            normalized_skewness = (skewness + 0.69) / 0.69  # Maps -1 to 0 and -0.5 to 1\n            threshold = 0.9 * (normalized_skewness ** 2)\n            #threshold = 0.86*skewness + 0.86\n        else:\n            # Function that starts low and peaks around 0.8 for skewness closer to 0\n            normalized_skewness = (skewness + 0.5) / 0.5  # Maps -0.5 to 0 and 0 to 1\n            #threshold = 0.8 * (1 - np.cos(normalized_skewness * np.pi / 2))\n            threshold = 0.86*skewness + 0.86\n        threshold = 0.9781\n    else:  # Relatively balanced distribution (0 < skewness <= 1)\n        if mean > 0.7:  # Generally high probabilities\n            threshold = 0.5\n        elif mean < 0.5:  # Generally low probabilities\n            threshold = 0.5\n        else:  # Moderate probabilities\n            threshold = 0.5\n        threshold = 0.9781\n    print(f\"Calculated threshold: {threshold:.4f}\")\n    return threshold\n\nimport torch\nimport numpy as np\nimport pandas as pd\nimport csv\n\n# Assuming the `stochastic_depth_resnet18` model is already defined elsewhere\nmodel = stochastic_depth_resnet18()\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\n\n# Load the pre-trained model\nmodel.load_state_dict(torch.load(\"/kaggle/input/requirement/model_epoch_275 (5).pth\"))\n\nmain_predictions = []\ntest_id_array = []\nmax_prob_array = []\npredictions = []\nclass_probabilities = {i: [] for i in range(100)}  # Store probabilities for each class\n\nmodel.eval()\nnot_pred_count = 0\ntest_loss, test_correct, test_total = 0, 0, 0\n\n# Evaluation loop\nwith torch.no_grad():\n    for (images, test_ids) in test_loader:\n        images = images.to(device)\n\n        outputs = model(images)\n        outputs = outputs.squeeze()\n\n        # Get probabilities via softmax and then the predicted class and max probability\n        probs = torch.softmax(outputs, dim=1)\n        max_probs, preds = torch.max(probs, 1)\n        #print(\"preds\",preds)\n        preds = preds.cpu().numpy()\n        main_pred = preds.copy()\n        max_probs = max_probs.cpu().numpy()\n\n        # Track class probabilities\n        for i, pred_class in enumerate(preds):\n            class_probabilities[pred_class].append(max_probs[i])\n\n        test_id_array.extend(test_ids)\n        max_prob_array.extend(max_probs)\n        main_predictions.extend(main_pred)\n\nprint(not_pred_count)\nprint(\"Predictions done\")\n\n# Preparing the answer array with ID, predicted label, and predicted probability\nanswer_array = [[\"ID\", \"Predicted_label\", \"Predicted_prob\"]]\n\n# Determine optimal thresholds for each class\nclass_thresholds = {}\n# for class_id, probs in class_probabilities.items():\n#     class_thresholds[class_id] = get_optimal_threshold(probs,class_id)\n#     class_thresholds[class_id] = 0.9781\n\nfor class_id, probs in class_probabilities.items():\n    class_thresholds[class_id] = 0.9781  # Default threshold\n    class_thresholds[class_id] = get_optimal_threshold(probs,class_id)\n    # Count elements with probability greater than 0.9781\n    count_above_threshold = sum(p > 0.9781 for p in probs)\n    # If more than 100 elements are above 0.9781, find new threshold\n    # if count_above_threshold > 100:\n    #     # Sort probabilities in descending order and get the 100th highest probability\n    #     sorted_probs = sorted(probs, reverse=True)\n    #     new_threshold = sorted_probs[99]  # 100th highest probability\n    #     class_thresholds[class_id] = new_threshold\n    # if count_above_threshold <= 15 and count_above_threshold > 10:\n    #     # Sort probabilities in descending order and get the 100th highest probability\n    #     new_threshold = 1\n    #     class_thresholds[class_id] = new_threshold\n\n# Apply dynamic thresholds and prepare the answer array based on them\ncount_47 = 0\nfor i in range(len(test_id_array)):\n    pred_class = main_predictions[i]\n    pred_prob = max_prob_array[i]\n    threshold = class_thresholds[pred_class]\n    #print(\"pred_class\",pred_class)\n    if pred_prob >= threshold:\n        final_pred = pred_class\n    else:\n        final_pred = -1\n\n    # if pred_class == 47:\n    #     final_pred = -1\n    #     count_47+=1\n    \n    answer_array.append([test_id_array[i].item(), final_pred, pred_prob])\nprint(\"COUNT 47 IS:\",count_47)\nprobs_array = answer_array[1:]  # Exclude header for processing\n\n# Convert to numpy array for easier handling\nprobs_array = np.array(probs_array)\n\n# Remove the constant 0.5 thresholding and rely entirely on dynamic thresholds\n# Update class labels and apply a maximum count per class\nclass_labels = probs_array[:, 1].astype(int)\nunique_labels, counts = np.unique(class_labels, return_counts=True)\n\nfor label, count in zip(unique_labels, counts):\n    if count > 200 and label != -1:  # Limit to 200 predictions per class\n        class_indices = np.where(class_labels == label)[0]\n        sorted_indices = class_indices[np.argsort(probs_array[class_indices][:, 2].astype(float))[::-1]]\n        for idx in sorted_indices[200:]:\n            probs_array[idx, 1] = -1\n\n# Output class label counts after filtering\nclass_labels = probs_array[:, 1].astype(int)\nunique_labels, counts = np.unique(class_labels, return_counts=True)\nfor label, count in zip(unique_labels, counts):\n    print(f\"Class {label}: {count} examples\")\n\n# Final predictions\npred_done = 0\nfor i in range(probs_array.shape[0]):\n    predictions.append(probs_array[i][1])\n    if probs_array[i][1] != -1:\n        pred_done += 1\n\nprint(pred_done)\nprint(20000 - pred_done)\n\n# Save prediction probabilities to 'pred_probs.csv'\nwith open('pred_probs.csv', mode='w', newline='') as file:\n    writer = csv.writer(file)\n    writer.writerows(answer_array)\n\n# Save submission predictions to 'submission.csv'\nanswer_array = [[\"ID\", \"Predicted_label\"]]\n\nfor i in range(len(test_id_array)):\n    answer_array.append([test_id_array[i].item(), predictions[i]])\n\nwith open('submission.csv', mode='w', newline='') as file:\n    writer = csv.writer(file)\n    writer.writerows(answer_array)\n\n# Function to calculate classwise accuracy\ndef calculate_classwise_accuracy(df, pred_col):\n    \"\"\"Calculate accuracy for each class.\"\"\"\n    accuracy_dict = {}\n    grouped = df.groupby(pred_col)\n\n    for name, group in grouped:\n        accuracy = (group['Label'] == group[pred_col]).sum() / len(group)\n        accuracy_dict[name] = accuracy\n\n    return accuracy_dict\n\n# Custom metric score function\ndef score(solution: pd.DataFrame, submission: pd.DataFrame, id_column_name: str, accuracy_threshold: float = 0.99, gamma: float = 5.0) -> float:\n    \"\"\"\n    Custom metric to evaluate model performance.\n    \n    Returns the overall performance score based on correct classifications for high and low accuracy classes.\n    \"\"\"\n    # Ensure ID columns have the same data type (int64 in this case)\n    solution[id_column_name] = solution[id_column_name].astype(int)\n    submission[id_column_name] = submission[id_column_name].astype(int)\n    \n    # Merge solution and submission DataFrames using the ID column.\n    filtered_df = pd.merge(solution, submission, on=id_column_name)\n\n    # Assuming 'Label' comes from solution and 'Predicted_label' comes from submission\n    filtered_df = filtered_df[['Label', 'Predicted_label']]\n\n    # Exclude rows with -1 predictions\n    filtered_df = filtered_df[filtered_df['Predicted_label'] != -1]\n    \n    all_classes = list(range(100))  # Assuming classes are from 0 to 99\n    sum_of_correctly_classified_high_accuracy = 0\n    sum_of_correctly_classified_low_accuracy = 0\n    \n    # Calculate accuracy per class\n    accuracy_per_class = calculate_classwise_accuracy(filtered_df, 'Predicted_label')\n\n    for cls in all_classes:\n        total = len(filtered_df[filtered_df['Predicted_label'] == cls])\n        correct = (filtered_df[filtered_df['Predicted_label'] == cls]['Predicted_label'] == filtered_df[filtered_df['Predicted_label'] == cls]['Label']).sum()\n        class_accuracy = accuracy_per_class.get(cls, 0.0)\n\n        if class_accuracy >= accuracy_threshold:\n            sum_of_correctly_classified_high_accuracy += total\n            print(cls,\"plus\",total,correct)\n        else:\n            sum_of_correctly_classified_low_accuracy += total\n            print(cls,\"minus\",total,correct,-gamma*total)\n\n\n\n    # Calculate final score\n    final_score = sum_of_correctly_classified_high_accuracy - gamma * sum_of_correctly_classified_low_accuracy\n    print(\"Finally\\n\")\n    print(sum_of_correctly_classified_high_accuracy, -gamma*sum_of_correctly_classified_low_accuracy)\n    return float(final_score)\n\n# Loading the true labels from test_label.txt\ntrue_labels = []\nwith open('/kaggle/input/requirement/test_label.txt', 'r') as file:\n    for line in file:\n        true_labels.append(int(line.strip()))\n\n# Create DataFrame from true labels\ntest_ids = [i for i in range(len(true_labels))]\nsolution_df = pd.DataFrame({\n    'ID': test_ids,\n    'Label': true_labels\n})\n\n# Create DataFrame from predictions\nsubmission_df = pd.DataFrame({\n    'ID': test_id_array,  # List of test IDs from your code\n    'Predicted_label': predictions  # Your model's predicted labels\n})\n\n# Calculate final score\nfinal_score = score(solution_df, submission_df, 'ID')\n\n# Print the final score\nprint(f\"Final Score: {final_score:.4f}\")\n\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-11-14T01:48:07.092456Z","iopub.execute_input":"2024-11-14T01:48:07.092877Z","iopub.status.idle":"2024-11-14T01:48:22.925066Z","shell.execute_reply.started":"2024-11-14T01:48:07.092835Z","shell.execute_reply":"2024-11-14T01:48:22.923831Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}