午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

零基礎(chǔ)入門語義分割-地表建筑物識別

 風(fēng)聲之家 2022-07-23 發(fā)布于江蘇

原創(chuàng) 我是一個(gè)小萌新 地理信息系統(tǒng)與氣候 2022-07-22 22:52 發(fā)表于北京

收錄于合集

#Python59
#天池1
#學(xué)習(xí)學(xué)習(xí)91

下天上的首場比賽開始了首播地的新人啟動(dòng)表。

圖片

結(jié)果不咋的。。沒有排名。。

圖片

不過不重要,慢慢學(xué)。下面是代碼部分。

1.導(dǎo)入相關(guān)包

import numpy as np
import pandas as pd
import pathlib, sys, os, random, time
import numba, cv2, gc
from tqdm import tqdm_notebook
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
from tqdm.notebook import tqdm
import albumentations as A
import rasterio
from rasterio.windows import Window
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.utils.data as D
import torchvision
from torchvision import transforms as T

重要幾個(gè)的包:

  • tqdm:顯示條
  • 數(shù)據(jù)增強(qiáng):數(shù)據(jù)增強(qiáng)
  • torch 相關(guān):pytorch的內(nèi)核
  • numpy和pandas:熊貓的包

2.數(shù)據(jù)編碼和解碼

本題學(xué)員需要完成個(gè)人作品表格,需要學(xué)員完成個(gè)人作品表格,并為學(xué)員提供個(gè)人作品,并為學(xué)員提供個(gè)人作品。

圖片編碼后的標(biāo)簽數(shù)據(jù)如下所示:

釋義張圖片的每一行,是第一張圖片的名字,后面跟每張圖片機(jī)構(gòu)的像元號

其編碼和偽裝:

def rle_encode(im):
    '''
    im: numpy array, 1 - mask, 0 - background
    Returns run length as string formated
    '
''
    pixels = im.flatten(order = 'F')
    pixels = np.concatenate([[0], pixels, [0]])
    runs = np.where(pixels[1:] != pixels[:-1])[0] + 1
    runs[1::2] -= runs[::2]
    return ' '.join(str(x) for x in runs)

def rle_decode(mask_rle, shape=(512, 512)):
    '''
    mask_rle: run-length as string formated (start length)
    shape: (height,width) of array to return 
    Returns numpy array, 1 - mask, 0 - background

    '
''
    s = mask_rle.split()
    starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]
    starts -= 1
    ends = starts + lengths
    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)
    for lo, hi in zip(starts, ends):
        img[lo:hi] = 1
    return img.reshape(shape, order='F')

3.定義Dataset類

寫過,數(shù)據(jù)集類是我們讀取數(shù)據(jù)的關(guān)鍵,我們會(huì)在定義中讀取數(shù)據(jù)以及一些類前面的:

class TianChiDataset(D.Dataset):
    def __init__(self, paths, rles, transform, test_mode=False):
        self.paths = paths
        self.rles = rles
        self.transform = transform
        self.test_mode = test_mode
        
        self.len = len(paths)
        self.as_tensor = T.Compose([
            T.ToPILImage(),
            T.Resize(IMAGE_SIZE),
            T.ToTensor(),
            T.Normalize([0.625, 0.448, 0.688],
                        [0.131, 0.177, 0.101]),
        ])
        
    # get data operation
    def __getitem__(self, index):
        img = cv2.imread(self.paths[index])
        if not self.test_mode:
            mask = rle_decode(self.rles[index])
            augments = self.transform(image=img, mask=mask)
            return self.as_tensor(augments['image']), augments['mask'][None]
        else:
            return self.as_tensor(img), ''        
    
    def __len__(self):
        """
        Total number of samples in the dataset
        "
""
        return self.len

上面定義了一個(gè)繼承Pytorch中Dataset的TianChiDataset類。我們先來測試一下。

查看數(shù)據(jù)的編碼和處理是否正確:

train_mask = pd.read_csv('./train_mask.csv', sep='\t', names=['name''mask']) # 改路徑
train_mask['name'] = train_mask['name'].apply(lambda x: './train/' + x)

img = cv2.imread(train_mask['name'].iloc[0])
mask = rle_decode(train_mask['mask'].iloc[0])

print(rle_encode(mask) == train_mask['mask'].iloc[0])

如果輸出為真則沒有問題。

定義一些參數(shù)和數(shù)據(jù)增強(qiáng)的方式:

EPOCHES = 20
BATCH_SIZE = 8
IMAGE_SIZE = 256
DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu' 

trfm = A.Compose([
    A.Resize(IMAGE_SIZE, IMAGE_SIZE),
    A.HorizontalFlip(p=0.5),
    A.VerticalFlip(p=0.5),
    A.RandomRotate90(),
])

實(shí)例化TianChiDataset類

dataset = TianChiDataset(
    train_mask['name'].values,
    train_mask['mask'].fillna('').values,
    trfm, False
)

以及獲取訓(xùn)練數(shù)據(jù)的第一張圖片標(biāo)簽看下:

image, mask = dataset[0]
plt.figure(figsize=(16,8))
plt.subplot(121)
plt.imshow(mask[0], cmap='gray')
plt.subplot(122)
plt.imshow(image[0]);
圖片

4.定義DataLoader

劃分訓(xùn)練集、測試集,并生成DataLoader實(shí)例:

valid_idx, train_idx = [], []
for i in range(len(dataset)):
    if i % 7 == 0:
        valid_idx.append(i)
#     else:
    elif i % 7 == 1:
        train_idx.append(i)
        
train_ds = D.Subset(dataset, train_idx)
valid_ds = D.Subset(dataset, valid_idx)

# define training and validation data loaders
loader = D.DataLoader(
    train_ds, batch_size=BATCH_SIZE, shuffle=True, num_workers=0)

vloader = D.DataLoader(
    valid_ds, batch_size=BATCH_SIZE, shuffle=False, num_workers=0)

5.定義/加載模型

這里我們用的是我們已經(jīng)能夠設(shè)置好的模型,所以最初直接加載torchfcn_resnet50,所以:

def get_model():
    model = torchvision.models.segmentation.fcn_resnet50(True)
    
#     pth = torch.load("../input/pretrain-coco-weights-pytorch/fcn_resnet50_coco-1167a1af.pth")
#     for key in ["aux_classifier.0.weight", "aux_classifier.1.weight", "aux_classifier.1.bias", "aux_classifier.1.running_mean", "aux_classifier.1.running_var", "aux_classifier.1.num_batches_tracked", "aux_classifier.4.weight", "aux_classifier.4.bias"]:
#         del pth[key]
    
    model.classifier[4] = nn.Conv2d(512, 1, kernel_size=(1, 1), stride=(1, 1))
    return model

6.損失函數(shù)和優(yōu)化器

@torch.no_grad()
def validation(model, loader, loss_fn):
    losses = []
    model.eval()
    for image, target in loader:
        image, target = image.to(DEVICE), target.float().to(DEVICE)
        output = model(image)['out']
        loss = loss_fn(output, target)
        losses.append(loss.item())
        
    return np.array(losses).mean()
model = get_model()
model.to(DEVICE);

optimizer = torch.optim.AdamW(model.parameters(),
                  lr=1e-4, weight_decay=1e-3)

class SoftDiceLoss(nn.Module):
    def __init__(self, smooth=1., dims=(-2,-1)):

        super(SoftDiceLoss, self).__init__()
        self.smooth = smooth
        self.dims = dims
    
    def forward(self, x, y):
        tp = (x * y).sum(self.dims)
        fp = (x * (1 - y)).sum(self.dims)
        fn = ((1 - x) * y).sum(self.dims)
        
        dc = (2 * tp + self.smooth) / (2 * tp + fp + fn + self.smooth)
        dc = dc.mean()
        return 1 - dc
    
bce_fn = nn.BCEWithLogitsLoss()
dice_fn = SoftDiceLoss()

def loss_fn(y_pred, y_true):
    bce = bce_fn(y_pred, y_true)
    dice = dice_fn(y_pred.sigmoid(), y_true)
    return 0.8*bce+ 0.2*dice

7.訓(xùn)練并保存最佳模型

到現(xiàn)在我們就可以訓(xùn)練模型了,然后我們最好的了:

header = r'''
        Train | Valid
Epoch |  Loss |  Loss | Time, m
'
''
#          Epoch         metrics            time
raw_line = '{:6d}' + '\u2502{:7.3f}'*2 + '\u2502{:6.2f}'
print(header)

EPOCHES = 5
best_loss = 10
for epoch in range(1, EPOCHES+1):
    losses = []
    start_time = time.time()
    model.train()
    for image, target in tqdm_notebook(loader):
        
        image, target = image.to(DEVICE), target.float().to(DEVICE)
        optimizer.zero_grad()
        output = model(image)['out']
        loss = loss_fn(output, target)
        loss.backward()
        optimizer.step()
        losses.append(loss.item())
        # print(loss.item())
        
    vloss = validation(model, vloader, loss_fn)
    print(raw_line.format(epoch, np.array(losses).mean(), vloss,
                              (time.time()-start_time)/60**1))
    losses = []
    
    if vloss < best_loss:
        best_loss = vloss
        torch.save(model.state_dict(), 'model_best.pth')

8.加載模型及預(yù)測結(jié)果

上面已經(jīng)訓(xùn)練了最好的模型,然后我們只加載模型(也就是驗(yàn)證集的數(shù)據(jù))就可以了。

加載模型

model.load_state_dict(torch.load("./model_best.pth"))

定義數(shù)據(jù)的操作并進(jìn)行預(yù)測

trfm = T.Compose([
    T.ToPILImage(),
    T.Resize(IMAGE_SIZE),
    T.ToTensor(),
    T.Normalize([0.625, 0.448, 0.688],
                [0.131, 0.177, 0.101]),
])

subm = []

test_mask = pd.read_csv('./test_a_samplesubmit.csv', sep='\t', names=['name''mask'])
test_mask['name'] = test_mask['name'].apply(lambda x: './test_a/' + x)

for idx, name in enumerate(tqdm_notebook(test_mask['name'].iloc[:])):
    image = cv2.imread(name)
    image = trfm(image)
    with torch.no_grad():
        image = image.to(DEVICE)[None]
        score = model(image)['out'][0][0]
        score_sigmoid = score.sigmoid().cpu().numpy()
        score_sigmoid = (score_sigmoid > 0.5).astype(np.uint8)
        score_sigmoid = cv2.resize(score_sigmoid, (512, 512))

        
        # break
    subm.append([name.split('/')[-1], rle_encode(score_sigmoid)])

保存預(yù)測結(jié)果

subm = pd.DataFrame(subm)
subm.to_csv('./tmp.csv', index=None, header=None, sep='\t')

選看一下:

plt.figure(figsize=(16,8))
plt.subplot(121)
plt.imshow(rle_decode(subm[1].fillna('').iloc[0]), cmap='gray')
plt.subplot(122)
plt.imshow(cv2.imread('./test_a/' + subm[0].iloc[0]));
圖片

差強(qiáng)人意。。。怪不得沒有效果。。不過我沒有調(diào)參,只是在本機(jī)跑了一個(gè)丹丹。明天優(yōu)化,開始煉制。

圖片

參考

【1】官方:aliyunTT6.https://tianchi.com/notebook-ai/detail?spm=517.170ali2.6.67.177c940ali488
【2】網(wǎng):https://tianchi.yun.com/competition/entrance/531872/信息

收錄于合集#python 

 59

下一篇【小白學(xué)深度學(xué)習(xí)-37】新建python虛擬環(huán)境的常用方法

喜歡這個(gè)內(nèi)容的人還喜歡

設(shè)計(jì)師收藏夾

不喜歡

確定

  • 不看這個(gè)公眾號

陳迪策

不喜歡

確定

  • 不看這個(gè)公眾號

壹方舍

不喜歡

確定

  • 不看這個(gè)公眾號

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多