{"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":9988,"databundleVersionId":868324,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":5328625,"sourceType":"kernelVersion"}],"dockerImageVersionId":30886,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.models as models\nfrom torchvision.models import resnet34 \nfrom torchvision import transforms\nfrom torch.utils.data import Dataset, DataLoader\nimport pandas as pd\nimport numpy as np\nimport os\nfrom PIL import Image\nfrom tqdm import tqdm\nfrom sklearn.model_selection import train_test_split\nimport torch.nn.functional as F\nimport matplotlib.pyplot as plt\nimport random","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:16.642412Z","iopub.execute_input":"2025-07-22T05:42:16.642629Z","iopub.status.idle":"2025-07-22T05:42:23.200897Z","shell.execute_reply.started":"2025-07-22T05:42:16.642607Z","shell.execute_reply":"2025-07-22T05:42:23.199986Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"PATH = './'\nTRAIN = '../input/airbus-ship-detection/train_v2'\nTEST = '../input/airbus-ship-detection/test_v2'\nSEGMENTATION = '../input/airbus-ship-detection/train_ship_segmentations_v2.csv'\nPRETREINED = '../input/fine-tuning-resnet34-on-ship-detection/models/Resnet34_lable_256_1.h5'\nexclude_list = ['6384c3e78.jpg','13703f040.jpg', '14715c06d.jpg',  '33e0ff2d5.jpg',\n                '4d4e09f2a.jpg', '877691df8.jpg', '8b909bb20.jpg', 'a8d99130e.jpg', \n                'ad55c3143.jpg', 'c8260c541.jpg', 'd6c7f17c7.jpg', 'dc3e7c901.jpg',\n                'e44dffe88.jpg', 'ef87bad36.jpg', 'f083256d8.jpg']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:23.201827Z","iopub.execute_input":"2025-07-22T05:42:23.202246Z","iopub.status.idle":"2025-07-22T05:42:23.206327Z","shell.execute_reply.started":"2025-07-22T05:42:23.202224Z","shell.execute_reply":"2025-07-22T05:42:23.205571Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"nw = 2\narch = resnet34","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:23.207245Z","iopub.execute_input":"2025-07-22T05:42:23.207581Z","iopub.status.idle":"2025-07-22T05:42:23.233512Z","shell.execute_reply.started":"2025-07-22T05:42:23.207544Z","shell.execute_reply":"2025-07-22T05:42:23.232839Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_names = [i for i in os.listdir(TRAIN)]\ntest_names = [i for i in os.listdir(TEST)]\n\nfor i in exclude_list:\n    if(i in train_names): train_names.remove(i)\n    if(i in test_names): test_names.remove(i)\n\ntrain_n, val_n = train_test_split(train_names, test_size=0.05, random_state=42)\nsegmentation_df = pd.read_csv(os.path.join(PATH, SEGMENTATION)).set_index('ImageId')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:23.234329Z","iopub.execute_input":"2025-07-22T05:42:23.234548Z","iopub.status.idle":"2025-07-22T05:42:26.066269Z","shell.execute_reply.started":"2025-07-22T05:42:23.234529Z","shell.execute_reply":"2025-07-22T05:42:26.065564Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def cut_empty(names):\n    return [name for name in names if(type(segmentation_df.loc[name]['EncodedPixels']) != float)]\n    \ntr_n_cut = cut_empty(train_n)\nval_n_cut = cut_empty(val_n)\nprint(len(tr_n_cut),len(val_n_cut))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:26.067057Z","iopub.execute_input":"2025-07-22T05:42:26.067301Z","iopub.status.idle":"2025-07-22T05:42:32.840428Z","shell.execute_reply.started":"2025-07-22T05:42:26.067269Z","shell.execute_reply":"2025-07-22T05:42:32.839558Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_mask(img_id, df):\n    shape=(768,768)\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    masks = df.loc[img_id]['EncodedPixels']\n    if(type(masks) == float): return img.reshape(shape) \n    if(type(masks) == str): masks = [masks]\n    for mask in masks:      \n        s = mask.split()\n        for i in range(len(s)//2): \n            start = int(s[2*i]) - 1 \n            length = int(s[2*i + 1]) \n            img[start:start+length] = 1\n    return img.reshape(shape).T ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:32.843139Z","iopub.execute_input":"2025-07-22T05:42:32.843369Z","iopub.status.idle":"2025-07-22T05:42:32.848128Z","shell.execute_reply.started":"2025-07-22T05:42:32.843350Z","shell.execute_reply":"2025-07-22T05:42:32.847398Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"image_transform = transforms.Compose([\n    transforms.Resize((256,256), interpolation=Image.BILINEAR),\n    transforms.ToTensor()\n])\n\nmask_transform = transforms.Compose([\n    transforms.Resize((256,256), interpolation=Image.NEAREST),\n    transforms.ToTensor(),\n    transforms.Lambda(lambda x: (x>0).float())\n])\n\ntest_transform = transforms.Compose([\n    transforms.Resize((256, 256)),  \n    transforms.ToTensor(),  \n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  \n])\n\nclass ShipDataset(Dataset):\n    def __init__(self, fnames, path, segmentation_df, transform=None, mask_transform=None,is_test=False):\n        self.fnames = fnames \n        self.path = path \n        self.segmentation_df = segmentation_df\n        self.transform = transform \n        self.mask_transform = mask_transform \n        self.is_test = is_test\n\n    def __len__(self):\n        return len(self.fnames)\n\n    def __getitem__(self, idx): \n        img_name = self.fnames[idx]\n        img_path = os.path.join(self.path, img_name)\n\n        img = Image.open(img_path).convert('RGB')\n   \n        if self.transform:\n            img = self.transform(img)\n\n        if self.is_test:\n            return img, img_name\n\n        if self.segmentation_df is None:\n            mask = np.zeros((768,768), dtype=np.uint8) \n        else:\n            mask = get_mask(img_name, self.segmentation_df) \n            \n        #print(\"До трансформаций:\", np.unique(mask))\n        mask = Image.fromarray(mask) \n        if self.mask_transform:\n            mask = self.mask_transform(mask)\n        #print(\"После трансформаций:\", mask.min(), mask.max())\n            \n        if mask.ndim == 3 and mask.shape[0] == 1:\n            mask = mask.squeeze()\n\n        return img, mask","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:32.849673Z","iopub.execute_input":"2025-07-22T05:42:32.849953Z","iopub.status.idle":"2025-07-22T05:42:32.870794Z","shell.execute_reply.started":"2025-07-22T05:42:32.849929Z","shell.execute_reply":"2025-07-22T05:42:32.870121Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_data(sz, bs, image_transform=None, mask_transform=None):\n    train_names = train_n if (len(tr_n_cut) % bs == 0) else train_n[:-(len(tr_n_cut) % bs)] # Обрезаем неполный батч\n    val_names = val_n_cut\n\n    train_dataset = ShipDataset(fnames=tr_n_cut, path=TRAIN, segmentation_df=segmentation_df, transform=image_transform, mask_transform=mask_transform)\n    val_dataset = ShipDataset(fnames=val_n_cut, path=TRAIN, segmentation_df=segmentation_df, transform=image_transform, mask_transform=mask_transform)\n\n    train_loader = DataLoader(train_dataset, batch_size=bs, shuffle=True, num_workers=nw)\n    val_loader = DataLoader(val_dataset, batch_size=bs, shuffle=False, num_workers=nw)\n\n    return train_loader, val_loader","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:32.871578Z","iopub.execute_input":"2025-07-22T05:42:32.871800Z","iopub.status.idle":"2025-07-22T05:42:32.890772Z","shell.execute_reply.started":"2025-07-22T05:42:32.871781Z","shell.execute_reply":"2025-07-22T05:42:32.890200Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_base(cut=8):\n    base_model = models.resnet34(pretrained=False)    \n    layers = list(base_model.children())[:cut]\n    return nn.Sequential(*layers)\n\ndef load_pretrained(model, path):\n    weights = torch.load(path, map_location=torch.device('cpu'))\n    model.load_state_dict(weights, strict=False)\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:32.891596Z","iopub.execute_input":"2025-07-22T05:42:32.891894Z","iopub.status.idle":"2025-07-22T05:42:32.906444Z","shell.execute_reply.started":"2025-07-22T05:42:32.891846Z","shell.execute_reply":"2025-07-22T05:42:32.905837Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class UnetBlock(nn.Module):\n\n    def __init__(self, up_in, x_in, n_out):\n        super().__init__()\n\n        up_out = x_out = n_out//2\n        self.tr_conv = nn.ConvTranspose2d(up_in, up_out, 2, stride=2) \n        self.x_conv = nn.Conv2d(x_in, x_out, 1) \n        self.bn = nn.BatchNorm2d(n_out)\n\n    def forward(self, up_p,x_p):\n        up_p = self.tr_conv(up_p) \n        x_p = self.x_conv(x_p) \n        cat_p = torch.cat([up_p, x_p], dim=1) \n        return self.bn(F.relu(cat_p)) \n\n\nclass SaveFeatures():\n    features = None\n    def __init__(self, m): \n        self.hook = m.register_forward_hook(self.hook_fn) \n    def hook_fn(self, module, input, output):\n        self.features = output\n    def remove(self):\n        self.hook.remove \n\nclass Unet34(nn.Module):\n        def __init__(self, rn):\n            super().__init__()\n            self.rn = rn \n            self.sfs = [SaveFeatures(rn[i]) for i in [2,4,5,6]] \n    \n            self.up1 = UnetBlock(512,256,256)\n            self.up2 = UnetBlock(256,128,256)\n            self.up3 = UnetBlock(256,64,256)\n            self.up4 = UnetBlock(256,64,256)\n            self.up5 = nn.ConvTranspose2d(256, 1, 2, stride=2)\n\n        def forward(self, x):\n            x = F.relu(self.rn(x)) \n            x = self.up1(x, self.sfs[3].features)\n            x = self.up2(x, self.sfs[2].features)\n            x = self.up3(x, self.sfs[1].features)\n            x = self.up4(x, self.sfs[0].features)\n            \n            x = self.up5(x)\n            return x[:,0]\n\n        def close(self):\n            for sf in self.sfs: sf.remove()       ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:32.907115Z","iopub.execute_input":"2025-07-22T05:42:32.907353Z","iopub.status.idle":"2025-07-22T05:42:32.917624Z","shell.execute_reply.started":"2025-07-22T05:42:32.907333Z","shell.execute_reply":"2025-07-22T05:42:32.917042Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def dice_loss(input, target):\n\n    input = torch.sigmoid(input)\n    smooth = 1.0 \n\n    iflat = input.view(-1)\n    tflat = target.view(-1)\n\n    intersection = (iflat*tflat).sum()\n\n    return ((2.0 * intersection + smooth) / (iflat.sum() + tflat.sum() + smooth))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:32.918568Z","iopub.execute_input":"2025-07-22T05:42:32.918920Z","iopub.status.idle":"2025-07-22T05:42:32.936685Z","shell.execute_reply.started":"2025-07-22T05:42:32.918837Z","shell.execute_reply":"2025-07-22T05:42:32.936020Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class FocalLoss(nn.Module):\n    def __init__(self, gamma):\n        super().__init__()\n        self.gamma = gamma \n    def forward(self, input, target): \n        if not(target.size() == input.size()): \n            raise ValueError('Target size ({}) must be the same sa input size ({})'.format(target.size(), input.size()))\n\n        max_val = (-input).clamp(min=0)\n        loss = input - input*target+max_val+((-max_val).exp() + (-input - max_val).exp()).log()\n        invporbs = F.logsigmoid(-input*(target*2.0-1.0))\n        loss = (invporbs*self.gamma).exp()*loss\n        return loss.mean()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:32.937495Z","iopub.execute_input":"2025-07-22T05:42:32.937764Z","iopub.status.idle":"2025-07-22T05:42:32.953702Z","shell.execute_reply.started":"2025-07-22T05:42:32.937735Z","shell.execute_reply":"2025-07-22T05:42:32.952916Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class MixedLoss(nn.Module):\n        def __init__(self, alpha, gamma):\n            super().__init__()\n            self.alpha = alpha \n            self.focal = FocalLoss(gamma) \n        \n        \n        def forward(self, input, target):\n            loss = self.alpha*self.focal(input, target) - torch.log(dice_loss(input, target))\n            return loss.mean()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:32.954535Z","iopub.execute_input":"2025-07-22T05:42:32.954821Z","iopub.status.idle":"2025-07-22T05:42:32.971402Z","shell.execute_reply.started":"2025-07-22T05:42:32.954793Z","shell.execute_reply":"2025-07-22T05:42:32.970707Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def dice(pred, targs):\n    pred = (pred > 0).float()\n    return 2.0*(pred*targs).sum()/((pred+targs).sum()+1.0)\n\ndef Iou(pred, targs):\n    pred = (pred > 0).float()\n    intersection = (pred*targs).sum()\n    return intersection / ((pred+targs).sum() - intersection + 1.0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:32.972138Z","iopub.execute_input":"2025-07-22T05:42:32.972403Z","iopub.status.idle":"2025-07-22T05:42:32.985175Z","shell.execute_reply.started":"2025-07-22T05:42:32.972376Z","shell.execute_reply":"2025-07-22T05:42:32.984354Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = Unet34(get_base()).to(device)\nmodel = load_pretrained(model, PRETREINED)\nsz = 256\nbs = 64\ntrain_loader, val_loader = get_data(sz, bs, image_transform=image_transform, mask_transform=mask_transform)\n\nfor image, mask in train_loader:\n    print(mask.max(), mask.min())\n    break\nfor img, mask in train_loader:\n    plt.imshow(mask[0].cpu().numpy(), cmap='gray')\n    plt.show()\n    img = img[0].cpu().numpy().transpose((1,2,0))\n    #img = (img*255).astype(np.uint8)\n    plt.imshow(img)\n    plt.show()\n    break\n    \ncriterion = MixedLoss(10.0, 2.0)\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-7)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:32.985900Z","iopub.execute_input":"2025-07-22T05:42:32.986126Z","iopub.status.idle":"2025-07-22T05:42:40.405773Z","shell.execute_reply.started":"2025-07-22T05:42:32.986107Z","shell.execute_reply":"2025-07-22T05:42:40.404663Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"weights = torch.load(PRETREINED, map_location='cpu')\n\nrenamed_weights = {f\"rn.{k}\": v for k, v in weights.items()}\n\nmissing, unexpected = model.load_state_dict(renamed_weights, strict=False)\n\nprint(\"🔍 Не загружены (missing):\")\nfor key in missing:\n    print(\"  -\", key)\n\nprint(\"\\n❗ Лишние (unexpected):\")\nfor key in unexpected:\n    print(\"  -\", key)\n\nmodel_dict = model.state_dict()\nfiltered_weights = {k: v for k, v in renamed_weights.items() if k in model_dict and v.size() == model_dict[k].size()}\n\nmodel_dict.update(filtered_weights)\nmodel.load_state_dict(model_dict)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:40.406716Z","iopub.execute_input":"2025-07-22T05:42:40.406993Z","iopub.status.idle":"2025-07-22T05:42:40.551027Z","shell.execute_reply.started":"2025-07-22T05:42:40.406971Z","shell.execute_reply":"2025-07-22T05:42:40.550228Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(list(renamed_weights.keys())[:10])  \nprint([k for k, _ in model.named_parameters()][:10])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:40.551743Z","iopub.execute_input":"2025-07-22T05:42:40.551997Z","iopub.status.idle":"2025-07-22T05:42:40.556984Z","shell.execute_reply.started":"2025-07-22T05:42:40.551976Z","shell.execute_reply":"2025-07-22T05:42:40.556187Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train(model, train_loader, val_loader, criterion, optimizer, epochs):\n    for epoch in range(epochs):\n        model.train()\n        running_loss = 0.0\n\n        train_loader_tqdm = tqdm(train_loader, desc=f'Epoch {epoch+1}/{epochs}', leave=True)\n\n        for images, masks in train_loader_tqdm:\n            images, masks = images.to(device), masks.to(device)\n\n            optimizer.zero_grad()\n            outputs = model(images)\n            loss = criterion(outputs, masks)\n            loss.backward()\n            optimizer.step()\n\n            running_loss += loss.item()\n\n        print(f'Epoch [{epoch+1}/{epochs}], Loss: {running_loss / len(train_loader):.4f}')\n\n        validate(model, val_loader, criterion)\n\ndef validate(model, val_loader, criterion):\n    model.eval()\n    mix_loss = 0.0\n    dice_score = 0.0\n    iou_score = 0.0\n\n    with torch.no_grad():\n        for images, masks in val_loader:\n            images, masks = images.to(device), masks.to(device)\n            outputs = model(images)\n            \n            loss = criterion(outputs, masks)\n            mix_loss += loss.item()\n            dice_score += dice(outputs, masks).item()\n            iou_score += Iou(outputs, masks).item()\n\n    avg_mix_loss = mix_loss / len(val_loader)  \n    avg_dice = dice_score / len(val_loader)\n    avg_iou = iou_score / len(val_loader)\n    \n    print(f'Validation Loss: {avg_mix_loss:.4f}, Dice: {avg_dice:.4f}, IoU: {avg_iou:.4f}')\n    \n    return avg_mix_loss, avg_dice, avg_iou\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:40.558028Z","iopub.execute_input":"2025-07-22T05:42:40.558320Z","iopub.status.idle":"2025-07-22T05:42:40.574779Z","shell.execute_reply.started":"2025-07-22T05:42:40.558290Z","shell.execute_reply":"2025-07-22T05:42:40.573938Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# for param in model.encoder[:1].parameters():# Замораживаем самые первые слои\n#     param.requires_grad = False\n\ntrain(model, train_loader, val_loader, criterion, optimizer, epochs=60)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:42:40.575573Z","iopub.execute_input":"2025-07-22T05:42:40.575781Z","iopub.status.idle":"2025-07-22T05:44:12.698933Z","shell.execute_reply.started":"2025-07-22T05:42:40.575751Z","shell.execute_reply":"2025-07-22T05:44:12.696647Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"torch.save(model, '/kaggle/working/trained_model.pth')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.699525Z","iopub.status.idle":"2025-07-22T05:44:12.699787Z","shell.execute_reply":"2025-07-22T05:44:12.699682Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#model = torch.load('/kaggle/working/trained_model.pth')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.700607Z","iopub.status.idle":"2025-07-22T05:44:12.701109Z","shell.execute_reply":"2025-07-22T05:44:12.700929Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!ls /kaggle/working/","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.702055Z","iopub.status.idle":"2025-07-22T05:44:12.702402Z","shell.execute_reply":"2025-07-22T05:44:12.702260Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def Show_images(x, yp, yt):\n    columns = 3\n    rows = min(bs,8)\n    fig = plt.figure(figsize=(columns*4, rows*4))\n    for i in range(rows):\n        # Перестановка размерностей для отображения: (C, H, W) -> (H, W, C)\n        img_x = x[i].permute(1, 2, 0).cpu().numpy() if x[i].dim() == 3 else x[i].cpu().numpy()\n        img_yp = yp[i].permute(1, 2, 0).cpu().numpy() if yp[i].dim() == 3 else yp[i].cpu().numpy()\n        img_yt = yt[i].permute(1, 2, 0).cpu().numpy() if yt[i].dim() == 3 else yt[i].cpu().numpy()\n        \n        fig.add_subplot(rows, columns, 3 * i + 1)\n        plt.axis('off')\n        plt.imshow(img_x)\n        plt.title('Input')\n\n        fig.add_subplot(rows, columns, 3 * i + 2)\n        plt.axis('off')\n        plt.imshow(img_yp)\n        plt.title('Prediction')\n\n        fig.add_subplot(rows, columns, 3 * i + 3)\n        plt.axis('off')\n        plt.imshow(img_yt)\n        plt.title('Ground Truth')\n\n    plt.tight_layout()\n    plt.show()\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.703421Z","iopub.status.idle":"2025-07-22T05:44:12.703807Z","shell.execute_reply":"2025-07-22T05:44:12.703631Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\nx, y = next(iter(val_loader))\nx = x.to(device)\ny = y.to(device)\nwith torch.no_grad():\n    yp = torch.sigmoid(model(x))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.704786Z","iopub.status.idle":"2025-07-22T05:44:12.705201Z","shell.execute_reply":"2025-07-22T05:44:12.705029Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def denormalize(tensor, mean, std):\n    if tensor.ndimension() != 4:\n        raise ValueError(f\"Ожидается тензор размерности (B, C, H, W), но получено {tensor.shape}\")\n\n    device = tensor.device\n\n    if tensor.is_sparse:\n        tensor = tensor.to_dense()\n\n    mean = torch.as_tensor(mean, device=device).view(1, -1, 1, 1)\n    std = torch.as_tensor(std, device=device).view(1, -1, 1, 1)\n\n    denorm = tensor * std + mean\n    denorm = torch.clamp(denorm, 0, 1)\n\n    return denorm","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.705963Z","iopub.status.idle":"2025-07-22T05:44:12.706359Z","shell.execute_reply":"2025-07-22T05:44:12.706190Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mean = [0.485, 0.456, 0.406]  \nstd = [0.229, 0.224, 0.225]\n\nxt = denormalize(x, mean, std)\nprint(f\"Denormalized tensor shape: {xt.shape}\")\n\nShow_images(xt, y, yp)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.707360Z","iopub.status.idle":"2025-07-22T05:44:12.707764Z","shell.execute_reply":"2025-07-22T05:44:12.707577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"subset_fnames = random.sample(test_names, 100)\ntest_dataset = ShipDataset(fnames=subset_fnames, path=TEST, segmentation_df=None, transform=test_transform, is_test=True)\ntest_loader = DataLoader(test_dataset, batch_size=bs, shuffle=False, num_workers=nw)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.708533Z","iopub.status.idle":"2025-07-22T05:44:12.708949Z","shell.execute_reply":"2025-07-22T05:44:12.708767Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def encode_mask(mask, shape=(768, 768)):\n    if mask.shape != shape:        \n        mask = np.array(Image.fromarray(mask).resize(shape))  \n    #print(f\"Resizing mask from {mask.shape} to {shape}\")\n    pixels = mask.T.flatten() \n    \n    if len(pixels) != shape[0] * shape[1]:\n        print(f\"Warning: Unexpected mask shape {mask.shape}. Expected shape: {shape}\")\n    \n    pixels = np.concatenate([pixels, [0]])  # Только один 0 в конце, без добавления лишнего 0 в начале\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    \n    if len(runs) % 2 != 0:\n        runs = np.concatenate([runs, [runs[-1]]])\n    \n    runs[1::2] -= runs[::2]  \n    \n    return ' '.join(str(x) for x in runs)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.710049Z","iopub.status.idle":"2025-07-22T05:44:12.710425Z","shell.execute_reply":"2025-07-22T05:44:12.710262Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\nship_list_dict = []\n\nfor inputs, img_names in test_loader:\n    inputs = inputs.to(device)  \n\n    with torch.no_grad():  \n        outputs = model(inputs)  \n    \n    pred_masks = torch.sigmoid(outputs).cpu().numpy()\n\n    for idx, img_name in enumerate(img_names):\n        mask = pred_masks[idx]  \n        mask = (mask > 0.5).astype(np.uint8)\n        encoded_pixels = encode_mask(mask)  \n        ship_list_dict.append({'ImageId': img_name, 'EncodedPixels': encoded_pixels})\n\npred_df = pd.DataFrame(ship_list_dict)\npred_df.to_csv('submission.csv', index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.711325Z","iopub.status.idle":"2025-07-22T05:44:12.711684Z","shell.execute_reply":"2025-07-22T05:44:12.711525Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if 'model' in locals() and model is not None:\n    model.close()\n    print(\"Хуки модели успешно удалены, ресурсы освобождены.\")\n    del model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.712433Z","iopub.status.idle":"2025-07-22T05:44:12.712797Z","shell.execute_reply":"2025-07-22T05:44:12.712639Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"path_to_images = '/kaggle/working/'\nfiles = os.listdir(path_to_images)\nprint(\"Содержимое папки:\", files)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-22T05:44:12.713680Z","iopub.status.idle":"2025-07-22T05:44:12.714076Z","shell.execute_reply":"2025-07-22T05:44:12.713905Z"}},"outputs":[],"execution_count":null}]}