{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport cv2\nimport pandas as pd\nimport os\nimport glob\nimport matplotlib.pyplot as plt\nimport tqdm\nimport gc\nimport torch.optim as optim\nimport copy\nimport albumentations as A","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-08-02T12:57:49.856376Z","iopub.execute_input":"2022-08-02T12:57:49.857063Z","iopub.status.idle":"2022-08-02T12:57:49.862354Z","shell.execute_reply.started":"2022-08-02T12:57:49.857026Z","shell.execute_reply":"2022-08-02T12:57:49.861241Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#一些用到的配置信息\n# The Configuration to be used later.\nclass CFG:\n    img_size    = [768,768]\n    lr          = 0.0003\n    epoch       = 100\n    batch_size  = 6\n    trainning   = False #控制训练和测试的变量（Control trainning or test.）\n    remaining_epoch = 15\n","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:49.881472Z","iopub.execute_input":"2022-08-02T12:57:49.882273Z","iopub.status.idle":"2022-08-02T12:57:49.887859Z","shell.execute_reply.started":"2022-08-02T12:57:49.882235Z","shell.execute_reply":"2022-08-02T12:57:49.886800Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def mask2rle(img):\n    '''\n    img: numpy array, 1 - mask, 0 - background\n    Returns run length as string formated\n    '''\n    pixels= img.T.flatten()\n    pixels = np.concatenate([[0], pixels, [0]])\n    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1\n    runs[1::2] -= runs[::2]\n    return ' '.join(str(x) for x in runs)\n\n\ndef rle2mask(mask_rle, shape=(3000,3000)):\n    '''\n    mask_rle: run-length as string formated (start length)\n    shape: (width,height) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n    '''\n    s = mask_rle.split()\n    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0::2], s[1::2])]\n    starts -= 1\n    ends = starts + lengths\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    for lo, hi in zip(starts, ends):\n        img[lo:hi] = 1\n    return img.reshape(shape).T\n","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:49.915768Z","iopub.execute_input":"2022-08-02T12:57:49.916031Z","iopub.status.idle":"2022-08-02T12:57:49.924677Z","shell.execute_reply.started":"2022-08-02T12:57:49.916007Z","shell.execute_reply":"2022-08-02T12:57:49.923419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 将csv中加入图片的位置","metadata":{}},{"cell_type":"code","source":"# 在csv文件中添加图片的路径信息\n# Adding the path information to the csv file.\ndef get_img_name(img_path):\n    '''\n    Get the image name from path.\n    '''\n    file_name = os.path.split(img_path)[1]\n    name = file_name.split('.')[0]\n    return int(name)\n    \nroot_path = f'../input/hubmap-organ-segmentation'\n\ntrain_csv_path = f'../input/hubmap-organ-segmentation/train.csv'\ntest_csv_path = f'../input/hubmap-organ-segmentation/test.csv'\n\nif CFG.trainning:\n    img_path = os.path.join(root_path,'train_images','*.tiff')\n    info_csv = pd.read_csv(train_csv_path)    \nelse:\n    img_path = os.path.join(root_path,'test_images','*.tiff')\n    info_csv = pd.read_csv(test_csv_path)  \n    \nall_img_path = glob.glob(img_path)\n\nimg_names = [ get_img_name(path) for path in all_img_path]\n\npath_pd = pd.DataFrame({'id':img_names,'path':all_img_path})\n# get_img_name(all_img_path[0])\npath_pd.head()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:49.951197Z","iopub.execute_input":"2022-08-02T12:57:49.953194Z","iopub.status.idle":"2022-08-02T12:57:49.971115Z","shell.execute_reply.started":"2022-08-02T12:57:49.953159Z","shell.execute_reply":"2022-08-02T12:57:49.970155Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_info = pd.merge(info_csv,path_pd,on = 'id')\ndel info_csv,path_pd\ndata_info.head()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:49.986926Z","iopub.execute_input":"2022-08-02T12:57:49.987593Z","iopub.status.idle":"2022-08-02T12:57:50.006520Z","shell.execute_reply.started":"2022-08-02T12:57:49.987550Z","shell.execute_reply":"2022-08-02T12:57:50.005605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#编写需要用到的transform\ntransform = {'train': A.Compose([A.Resize(*CFG.img_size,interpolation=cv2.INTER_LINEAR),\n                       A.HorizontalFlip(p =0.5),\n                       A.VerticalFlip(p=0.5),\n                       A.HueSaturationValue(p=0.7),\n                       A.ShiftScaleRotate(shift_limit = 0.02,scale_limit=(0.1, 0.6),rotate_limit = 90,p = 0.5),\n                       A.ElasticTransform(p=0.1, alpha=90, sigma=120 * 0.05, \n                          alpha_affine=120 * 0.03),\n                       A.GridDistortion(p=0.25)\n                       ],\n                       p=1),\n    'test':A.Compose([A.Resize(*CFG.img_size,interpolation = cv2.INTER_LINEAR)],p=1)\n}","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:50.015998Z","iopub.execute_input":"2022-08-02T12:57:50.016783Z","iopub.status.idle":"2022-08-02T12:57:50.024189Z","shell.execute_reply.started":"2022-08-02T12:57:50.016746Z","shell.execute_reply":"2022-08-02T12:57:50.023040Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 首先对要处理的数据进行一个可视化","metadata":{}},{"cell_type":"code","source":"# 首先可视化一下要处理的图像.\n# Displays the picture to be processed.\nif CFG.trainning:\n    # len(all_annotation_path)\n    index = 22\n    img = cv2.imread(data_info['path'][index])\n    # cv2.imshow('',img)\n    mask = rle2mask(data_info['rle'][index],(3000,3000))\n\n    transformed = transform['train'](image = img, mask = mask)\n    img,mask = transformed['image'],transformed['mask']\n    mask = 255*mask\n    mask = cv2.cvtColor(mask,cv2.COLOR_GRAY2RGB)\n    print(mask.shape)\n    mask[:,:,2] = 255\n    # np.set_printoptions(threshold=np.nan)\n    \n    add_mask = cv2.addWeighted(img,0.7,mask,0.25,0)\n\n    figure = plt.figure(figsize=(8,8))\n    plt.imshow(img)\n    figure = plt.figure(figsize=(8,8))\n    plt.imshow(mask)\n    figure = plt.figure(figsize=(8,8))\n    plt.imshow(add_mask)\n","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:50.043826Z","iopub.execute_input":"2022-08-02T12:57:50.044102Z","iopub.status.idle":"2022-08-02T12:57:50.051510Z","shell.execute_reply.started":"2022-08-02T12:57:50.044077Z","shell.execute_reply":"2022-08-02T12:57:50.050550Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 下面就是使用pytorch编写Dataset和网络的结构","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset,DataLoader","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:50.071782Z","iopub.execute_input":"2022-08-02T12:57:50.072329Z","iopub.status.idle":"2022-08-02T12:57:50.077282Z","shell.execute_reply.started":"2022-08-02T12:57:50.072292Z","shell.execute_reply":"2022-08-02T12:57:50.076367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#编写dataset\nclass my_dataset(Dataset):\n    def __init__(self,df,transform = None,trainning = True):\n        super(my_dataset,self).__init__()\n        self.df = df\n        self.transform = transform\n        self.trainning = trainning\n        \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self,index):\n        img_path = self.df['path'][index]\n        img = cv2.imread(img_path,1)\n        height,width = self.df['img_height'][index],self.df['img_width'][index]\n        if self.trainning:\n    #         print(img.shape)\n            \n            mask = rle2mask(self.df['rle'][index],(height,width))\n\n            if self.transform:\n                transformed = self.transform(image = img,mask = mask)\n                img,mask = transformed['image'],transformed['mask']\n            img = torch.tensor(img).permute(2,0,1).to(torch.float32)\n            mask = torch.tensor(mask).to(torch.float32)\n            return img,mask.unsqueeze(0)\n        else:\n            if self.transform:\n                img = self.transform(image = img)['image']\n            return torch.tensor(img).permute(2,0,1).to(torch.float32),height,width\n            ","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:50.101437Z","iopub.execute_input":"2022-08-02T12:57:50.101826Z","iopub.status.idle":"2022-08-02T12:57:50.113266Z","shell.execute_reply.started":"2022-08-02T12:57:50.101799Z","shell.execute_reply":"2022-08-02T12:57:50.112345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sys\nimport os\nsys.path.append(r'../input/segmentation-models-pytorch/segmentation_models.pytorch-master')\nsys.path.append(r'../input/efficientnet-pytorch/EfficientNet-PyTorch-master')\nsys.path.append(r'../input/timm-pytorch-image-models/pytorch-image-models-master')\nsys.path.append(r'../input/pretrainedmodels/pretrainedmodels-0.7.4')\nimport segmentation_models_pytorch as smp\nimport torch.nn.functional as F\n\nif CFG.trainning:\n    model = smp.Unet(\n\n            encoder_name= 'efficientnet-b0', # choose encoder, e.g. mobilenet_v2 or efficientnet-b7\n            encoder_weights=\"imagenet\",    \n            in_channels=3,               \n            classes=1,       \n            activation=None,\n        )\nelse:\n    model = smp.Unet(\n            encoder_name= 'efficientnet-b0', # choose encoder, e.g. mobilenet_v2 or efficientnet-b7\n            encoder_weights= None,     \n            in_channels=3,               \n            classes=1,        \n            activation = 'sigmoid',\n        )\n    \n    model_path = r'../input/saved-model-4/eary_stopiong.pth'\n    model.load_state_dict(torch.load(model_path))\n    ","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:50.149326Z","iopub.execute_input":"2022-08-02T12:57:50.150317Z","iopub.status.idle":"2022-08-02T12:57:50.380831Z","shell.execute_reply.started":"2022-08-02T12:57:50.150279Z","shell.execute_reply":"2022-08-02T12:57:50.379714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 定义需要使用的损失函数\n# choose the loss function and define the evalution function.\nDice_Loss = smp.losses.DiceLoss(mode = 'binary')\nTuersky = smp.losses.TverskyLoss(mode = 'binary')\nBCE_loss = smp.losses.SoftBCEWithLogitsLoss()\n\ndef get_dice_coefficient(output,target):\n    output,target = output.detach(),target.detach()\n    assert output.size(0) == target.size(0)\n    bs = output.size(0)\n    output = F.logsigmoid(output).exp().view(bs,1,-1)\n    output = output>0.5\n    target = target.view(bs,1,-1)\n    \n    intersection = torch.sum(output*target,dim = (1,2))\n    dice_coe = (2*intersection)/torch.sum(output+target,dim = (1,2))\n    return dice_coe.mean()\n\ndef criterion(predicts,masks):\n    return 0.5*BCE_loss(predicts,masks) + 0.5*Tuersky(predicts,masks)","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:50.383571Z","iopub.execute_input":"2022-08-02T12:57:50.383967Z","iopub.status.idle":"2022-08-02T12:57:50.392161Z","shell.execute_reply.started":"2022-08-02T12:57:50.383928Z","shell.execute_reply":"2022-08-02T12:57:50.391172Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#下面就是训练网络\ndef train_one_epoch(model,optimizer,dataloader,device):\n    model.train()\n    running_loss  = 0.0\n    pbar = tqdm.tqdm(enumerate(dataloader),total = len(dataloader),desc = 'Train')\n    for setp,(images,masks) in pbar:\n        images = images.to(device)\n        masks = masks.to(device)\n        \n        predicts = model(images)\n        optimizer.zero_grad()\n        \n        loss = criterion(predicts,masks)\n        loss.backward()\n        \n        optimizer.step()\n        running_loss += loss.detach().cpu()\n    \n    epoch_loss  = running_loss/len(dataloader)\n    gc.collect()\n    return epoch_loss\n\n\ndef valid(model,dataloader,device):\n    model.eval()\n    all_loss  = 0.0\n    all_scores = 0.0\n    pbar = tqdm.tqdm(enumerate(dataloader),total = len(dataloader),desc = 'Valid')\n    with torch.no_grad():\n        for step,(images,masks) in pbar:\n            images = images.to(device)\n            masks = masks.to(device)\n            predicts  = model(images)\n            batch_loss = criterion(predicts,masks)\n            all_loss += batch_loss.detach().cpu()\n            batch_score = get_dice_coefficient(predicts,masks).detach().cpu()\n            all_scores += batch_score\n    \n    return all_scores/len(dataloader),all_loss/len(dataloader)\n","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:50.393945Z","iopub.execute_input":"2022-08-02T12:57:50.394608Z","iopub.status.idle":"2022-08-02T12:57:50.405637Z","shell.execute_reply.started":"2022-08-02T12:57:50.394572Z","shell.execute_reply":"2022-08-02T12:57:50.404659Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = 'cuda' if torch.cuda.is_available() else 'cpu'\nif CFG.trainning:\n    # 分两步来训练神经网络，第一步，将数据划分为训练数据和验证数据，使用训练数据来训练网络，使用验证数据来挑选模型。\n    # 第二步，加载第一步训练好的模型，并使用所有的数据来接着训练网络，当验证集的损失满足一定要求时停止训练。\n    # Train the network in two steps. Split the data into training and validation sets in the first step, and use the training set for training and the validation set for validating.\n    # All the data are combined to retrain the model in the second step and stop training when the validation loss satisfies a certain condition.\n    data_length =  len(data_info)\n    train_data = data_info[:int(0.9*data_length)]\n    valid_data = data_info[int(0.9*data_length):]\n    valid_data.reset_index(drop=True, inplace=True)\n    train_data.reset_index(drop=True, inplace=True)\n\n    fusion_dataset = my_dataset(data_info,transform['train'])\n    train_dataset = my_dataset(train_data,transform['train'])\n    valid_dataset = my_dataset(valid_data,transform['test'])\n\n    \n    train_loader = DataLoader(train_dataset,batch_size =CFG.batch_size,shuffle = True)\n    valid_loader = DataLoader(valid_dataset,batch_size =CFG.batch_size,shuffle = False)\n    fusion_loader = DataLoader(fusion_dataset,batch_size= CFG.batch_size,shuffle=True)\n    \n    optimizer = optim.Adam(model.parameters(),lr = CFG.lr)\n    gc.collect()\n\n    model.to(device)\n    best_score = 0.0\n    best_model = copy.deepcopy(model.state_dict())\n    best_optim = copy.deepcopy(optimizer.state_dict())\n    mini_loss = None\n    remaining_epoch = CFG.remaining_epoch\n    for e in range(CFG.epoch):\n        print('Epoch:',e)\n        train_loss = train_one_epoch(model,optimizer,train_loader,device)\n        dice_score,valid_loss = valid(model,valid_loader,device)\n        print('Train loss:{:.3}--Valid loss:{:.3}--Valid score:{:.3}--Remaining epoch{:3}'.format(train_loss,valid_loss,dice_score,remaining_epoch))\n        \n        if mini_loss is None or train_loss < mini_loss:\n            mini_loss = train_loss\n\n        if dice_score > best_score:\n            best_score = dice_score\n            remaining_epoch = CFG.remaining_epoch\n            best_model = copy.deepcopy(model.state_dict())\n            best_optim = copy.deepcopy(optimizer.state_dict())\n\n        remaining_epoch -=1\n        if remaining_epoch <=0:\n            PATH = r'step_one.pth'\n            torch.save(model.state_dict(),PATH)\n            break\n            \n    print('Early stoping! Using all the data to retrain the network!')\n    model.load_state_dict(best_model)\n    optimizer.load_state_dict(best_optim)\n    for e in range(CFG.epoch):\n        train_loss = train_one_epoch(model,optimizer,fusion_loader,device)\n        dice_score,valid_loss = valid(model,valid_loader,device)\n        print('Train loss:{:.3}--Valid loss:{:.3}--Valid score:{:.3}'.format(train_loss,valid_loss,dice_score))\n        if valid_loss <= mini_loss:\n            PATH = r'eary_stopiong.pth'\n            torch.save(model.state_dict(),PATH)\n            print('Model saved!')\n            break\n    gc.collect()\n\nelse:\n    test_dataset = my_dataset(data_info,transform['test'],trainning = CFG.trainning)\n    test_dataloader = DataLoader(test_dataset,batch_size = CFG.batch_size,shuffle = False)\n    model.to(device)\n    model.eval()\n    result = []\n    scale = {'height':[],'width':[]}\n    with torch.no_grad():\n        for img,height,width in tqdm.tqdm(test_dataloader,total  = len(test_dataloader), desc = 'test'):\n            img = img.to(device)\n            predict = model(img)\n            \n            scale['height'].extend(height)\n            scale['width'].extend(width)\n            result.extend(predict.cpu().numpy())","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:50.408555Z","iopub.execute_input":"2022-08-02T12:57:50.409131Z","iopub.status.idle":"2022-08-02T12:57:50.680832Z","shell.execute_reply.started":"2022-08-02T12:57:50.409072Z","shell.execute_reply":"2022-08-02T12:57:50.679834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"result = np.array(result)\nprint(result.shape)\nrle = []\nfor i,img in enumerate(result):\n    mask = cv2.resize(img.squeeze(),(int(scale['width'][i]),int(scale['height'][i])),fx = 1,fy = 1,interpolation = cv2.INTER_LINEAR)\n    mask  = np.where(mask>0.5,1,0)\n    rle.append(mask2rle(mask))","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:50.682225Z","iopub.execute_input":"2022-08-02T12:57:50.683194Z","iopub.status.idle":"2022-08-02T12:57:50.791615Z","shell.execute_reply.started":"2022-08-02T12:57:50.683153Z","shell.execute_reply":"2022-08-02T12:57:50.790561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(data_info['id'].values.tolist())\nsub_info = {'id':data_info['id'].values,'rle':rle}\n\nsubmission = pd.DataFrame(sub_info)\n# # type(data_info['id'])\n# # data_info['id'].values\nsample = pd.read_csv(r'../input/hubmap-organ-segmentation/sample_submission.csv')\ndel sample['rle']\n# print(sample.head())\nsubmission = sample.merge(submission,on = 'id')\nsubmission.to_csv('submission.csv',index = False)\n# submission.head()","metadata":{"execution":{"iopub.status.busy":"2022-08-02T12:57:50.793007Z","iopub.execute_input":"2022-08-02T12:57:50.793620Z","iopub.status.idle":"2022-08-02T12:57:50.813914Z","shell.execute_reply.started":"2022-08-02T12:57:50.793581Z","shell.execute_reply":"2022-08-02T12:57:50.813065Z"},"trusted":true},"execution_count":null,"outputs":[]}]}