tutorial.md
ΠΡΠΈΠ²Π΅Ρ, Π΄Π»Ρ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ ΠΈ Π²Π΅ΡΡΠΈΠΎΠ½ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Π° ΠΎΠΏΡΡΠ½ΡΠ΅ DS ΡΠΎΡ ΡΠ°Π½ΡΡΡ Π²ΡΠ΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π² YAML ΠΈΠ»ΠΈ JSON ΡΠ°ΠΉΠ»Ρ. Catalyst ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ ΡΠ°ΠΊΠΎΠΉ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π» ΠΏΡΡΠΌΠΎ ΠΈΠ· ΠΊΠΎΡΠΎΠ±ΠΊΠΈ, Π² ΡΡΠΎΠΌ ΡΡΡΠΎΡΠΈΠ°Π»Π΅ Ρ ΠΏΠΎΠΊΠ°ΠΆΡ Π½Π° ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Segmentation tutorial, ΠΊΠ°ΠΊ ΠΎΠ±Π΅ΡΠ½ΡΡΡ Π΅Π³ΠΎ Π² Config API. Π ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΎΡΠ½ΠΎΠ²Ρ Π²ΠΎΠ·ΡΠΌΠ΅ΠΌ Segmentation tutorial ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎ ΡΠ°Π³ Π·Π° ΡΠ°Π³ΠΎΠΌ ΠΏΠ΅ΡΠ΅ΠΏΠΈΡΠ΅ΠΌ. Π‘Π½Π°ΡΠ°Π»Π° ΡΠ°Π·ΠΎΠ±ΡΠ΅ΠΌ jupyter-notebook Π½Π° ΡΠΎΡΡΠ°Π²Π½ΡΠ΅ ΡΠ°ΡΡΠΈ:
- ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ
- ΠΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΊΠ° Π΄Π°Π½Π½ΡΡ
- ΠΠ°Π³ΡΡΠ·ΠΊΠ° Π΄Π°Π½Π½ΡΡ Π² ΠΌΠΎΠ΄Π΅Π»Ρ
- ΠΠ±ΡΡΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠ΄Π΅Π»ΠΈ
- ΠΠ½Π°Π»ΠΈΠ· ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠ² ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ
- ΠΡΠ΅Π΄ΡΠΊΠ°Π·Π°Π½ΠΈΠ΅ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠ²
ΠΠ΅ΡΠ΅Π΄ ΡΠ΅ΠΌ, ΠΊΠ°ΠΊ Π½Π°ΡΠ°ΡΡ ΠΏΠΈΡΠ°ΡΡ ΠΊΠΎΠ΄, Π½Π°ΡΡΡΠΎΠΈΠΌ ΠΈ Π°ΠΊΡΠΈΠ²ΠΈΡΡΠ΅ΠΌ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΠΎΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΠ΅. ΠΠΎΡ Π·Π΄Π΅ΡΡ Π΅ΡΡΡ Π½Π΅Π±ΠΎΠ»ΡΡΠΎΠΉ ΡΡΡΠΎΡΠΈΠ°Π».
mkdir segmentation_tutorial
cd segmentation_tutorial
virtualenv venv
source venv/bin/activate
Π£ΡΡΠ°Π½ΠΎΠ²ΠΈΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΡΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ Π΄Π°Π½Π½ΡΠΌ ΡΡΡΠΎΡΠΈΠ°Π»ΠΎΠΌ
pip install albumentations # ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ Π°ΡΠ³ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠΌΠΈ
pip install -U catalyst # ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π΄Π»Ρ ΠΏΠΎΡΡΠΎΡΠΎΠ΅Π½ΠΈΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ
ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½ΠΎΠ²
pip install segmentation-models-pytorch # ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π² ΠΊΠΎΡΠΎΡΠΎΠΉ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡΡ Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΡ ΠΈ Π²Π΅ΡΠ° ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ Π½Π΅ΠΉΡΠΎΠ½Π½ΡΡ
ΡΠ΅ΡΠ΅ΠΉ Π΄Π»Ρ ΡΠ΅ΡΠ΅Π½ΠΈΡ Π·Π°Π΄Π°Ρ ΡΠ΅Π³ΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ
pip install ttach Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Ρ ΠΎΠ±Π΅ΡΡΠΊΠΎΠΉ Π΄Π»Ρ test-time Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΉ
ΠΠ»Ρ ΡΠΎΠ³ΠΎ ΡΡΠΎΠ±Ρ ΠΎΠ±ΡΡΠ°ΡΡ ΠΌΠΎΠ΄Π΅Π»Ρ Π² ΡΠ΅ΠΆΠΈΠΌΠ΅ fp16 Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΡ Apex.
git clone https://github.com/NVIDIA/apex
cd apex
pip install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" ./
ΠΠΎΡΠ»Π΅ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ Π½ΡΠΆΠ½ΡΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½Ρ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΈΡΡ Π΄Π°Π½Π½ΡΠ΅ Π΄Π»Ρ Π·Π°ΠΏΡΡΠΊΠ° ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Π°. Π‘ΡΠΎΠΈΡ ΠΎΡΠΌΠ΅ΡΠΈΡΡ, ΡΡΠΎ ΠΏΡΠΈ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ΅ Catalyst ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΡΡΡ bash ΡΡΠ½ΠΊΡΠΈΡ download-gdrive Π΄Π»Ρ Π·Π°Π³ΡΡΠ·ΠΊΠΈ Π΄Π°Π½Π½ΡΡ Ρ Π³ΡΠ³Π» Π΄ΠΈΡΠΊ, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ ΠΊΠ»ΡΡ. ΠΠ°Π½Π½ΡΠ΅ Π΄Π»Ρ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΡΡΡΠΎΡΠΈΠ°Π»Π° ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠ°ΡΠ°ΡΡ Π΄Π°Π½Π½ΡΠ΅ ΠΏΠΎ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌΡ ΠΊΠ»ΡΡΡ 1iYaNijLmzsrMlAdMoUEhhJuo-5bkeAuj. ΠΠ°ΠΏΠΈΡΠ΅ΠΌ bash-ΡΠΊΡΠΈΠΏΡ download_dataset.sh Π΄Π»Ρ ΡΠΊΠ°ΡΠΈΠ²Π°Π½ΠΈΡ Π΄Π°Π½Π½ΡΡ :
download-gdrive 1iYaNijLmzsrMlAdMoUEhhJuo-5bkeAuj segmentation_data.zip
mkdir data
unzip segmentation_data.zip &>/dev/null
mv segmentation_data/* data
rm segmentation_data.zip
ΠΈ Π·Π°ΠΏΡΡΡΠΈΠΌ
bash download_dataset.sh
ΠΠ»Ρ Π΄Π°Π»ΡΠ½Π΅ΠΉΡΠ΅ΠΉ ΡΠ°Π±ΠΎΡΡ Π½ΡΠΆΠ½ΠΎ ΡΡΠΎΡΠΌΠΈΡΠΎΠ²Π°ΡΡ Π΄Π²Π° csv ΡΠ°ΠΉΠ»Π° - ΠΎΠ΄ΠΈΠ½ Π΄Π»Ρ ΡΡΠ΅Π½ΠΈΡΠΎΠ²ΠΎΡΠ½ΠΎΠΉ Π²ΡΠ±ΠΎΡΠΊΠΈ, Π° Π΄ΡΡΠ³ΠΎΠΉ Π΄Π»Ρ ΡΠ΅ΡΡΠ°. Π csv ΡΠ°ΠΉΠ»Π΅ Π±ΡΠ΄Π΅Ρ Π΄Π²Π° ΡΡΠΎΠ»Π±ΡΠ° - ΠΎΠ΄ΠΈΠ½ Π΄Π»Ρ Ρ ΡΠ°Π½Π΅Π½ΠΈΡ ΠΏΡΡΠΈ ΠΊ ΠΊΠ°ΡΡΠΈΠ½ΠΊΠ΅, Π° Π΄ΡΡΠ³ΠΎΠΉ Π΄Π»Ρ ΠΏΡΡΠΈ ΠΊ ΠΌΠ°ΡΠΊΠ΅.
prepare_dataset.py
import pathlib
import pandas as pd
from sklearn import model_selection
def main(
datapath: str = "./data", valid_size: float = 0.2, random_state: int = 42
):
datapath = pathlib.Path(datapath)
dataframe = pd.DataFrame({
"image": sorted((datapath / "train").glob("*.jpg")),
"mask": sorted((datapath / "train_masks").glob("*.gif"))
})
df_train, df_valid = model_selection.train_test_split(
dataframe,
test_size=valid_size,
random_state=random_state,
shuffle=False
)
for source, mode in zip((df_train, df_valid), ("train", "valid")):
source.to_csv(datapath / f"dataset_{mode}.csv", index=False)
if __name__ == "__main__":
ΠΠΎΠ΄Π³ΠΎΡΠΎΠ²ΠΈΠΌ Π΄Π°Π½Π½ΡΠ΅:
python prepare_dataset.py --datapath=./data
ΠΠ°Π»Π΅Π΅ ΡΠΎΠ·Π΄Π°Π΄ΠΈΠΌ ΠΏΠ°ΠΏΠΊΡ src Π² ΠΊΠΎΡΠΎΡΠΎΠΉ Π½Π°Ρ ΠΎΠ΄ΡΡΡΡ ΡΠ°ΠΉΠ»Ρ Ρ ΠΊΠΎΠ΄ΠΎΠΌ ΡΠ°ΡΡΠ΅ΠΉ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Π°. Π ΠΏΠ°ΠΏΠΊΠ΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π½Π°Ρ ΠΎΠ΄ΠΈΡΡΡ 4 ΡΠ°ΠΉΠ»Π°: init.py, dataset.py, experiment.py, transforms.py.
- init.py - ΡΠ»ΡΠΆΠΈΡ Π΄Π»Ρ ΡΠΊΠ°Π·Π°Π½ΠΈΡ ΠΈΠ½ΡΠ΅ΡΠΏΡΠ΅ΡΠ°ΡΠΎΡΡ ΡΠΎΠ³ΠΎ, ΡΡΠΎ ΠΏΠ°ΠΏΠΊΠ° Π² ΠΊΠΎΡΠΎΡΠΎΠΉ ΠΎΠ½ Π»Π΅ΠΆΠΈΡ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΏΠΈΡΠΎΠ½-ΠΏΠ°ΠΊΠ΅ΡΠΎΠΌ ΠΈ Π² Π½Π΅ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΊΠ°ΡΡ ΠΌΠΎΠ΄ΡΠ»ΠΈ (ΡΠ°ΠΉΠ»Ρ). Π ΠΊΠ°ΡΠ°Π»ΠΈΡΡ ΠΌΠΈΡΠ΅ ΡΡΠΎΡ ΡΠ°ΠΉΠ» ΡΠ°ΠΊ ΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π΄Π»Ρ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΡ ΠΊΠ°ΡΡΠΎΠΌΠ½ΡΡ ΠΌΠΎΠ΄ΡΠ»Π΅ΠΉ Π² ΡΠ΅Π³ΠΈΡΡΡΠΈ. Π Π½Π΅ΠΌ Π½ΡΠΆΠ½ΠΎ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ ΡΠΊΠ°Π·Π°ΡΡ ΠΊΠ°ΠΊΠΎΠΉ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½Ρ ΠΈ ΡΠ°Π½Π½Π΅Ρ ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡ.
from .experiment import Experiment
from catalyst.dl import SupervisedRunner as Runner
- dataset.py - ΡΠ°ΠΉΠ» Π² ΠΊΠΎΡΠΎΡΠΎΠΌ ΠΏΡΠΎΠΏΠΈΡΡΠ²Π°Π΅ΡΡΡ ΠΊΠ»Π°ΡΡ dataset ΠΏΠΎ Π°Π½Π°Π»ΠΎΠ³ΠΈΠΈ Ρ ΠΊΠ»Π°ΡΡΠΎΠΌ dataset Π² ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»ΡΠ½ΠΎΠΌ ΡΡΡΠΎΡΠΈΠ°Π»Π΅
from typing import Callable, Dict, List
import numpy as np
import imageio
from torch.utils.data import Dataset
class SegmentationDataset(Dataset):
def __init__(self, list_data: List[Dict], dict_transform: Callable = None):
self.data = list_data
self.dict_transform = dict_transform
def __getitem__(self, index: int) -> Dict:
dict_ = self.data[index]
dict_ = {
"image": np.asarray(imageio.imread(dict_["image"], pilmode="RGB")),
"mask": np.asarray(imageio.imread(dict_["mask"]))}
if self.dict_transform is not None:
dict_ = self.dict_transform(**dict_)
return dict_
def __len__(self) -> int:
return len(self.data)
- Π experiment.py - ΡΠΎΠ΄Π΅ΡΠΆΠΈΡΡΡ ΠΊΠ»Π°ΡΡ Experiment, ΠΎΠ½ Π½Π°ΡΠ»Π΅Π΄ΡΠ΅ΡΡΡ ΠΎΡ ΠΊΠ»Π°ΡΡΠ° ConfigExperiment. ΠΠ°Π½Π½ΡΠΉ ΠΊΠ»Π°ΡΡ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ Π΄Π²Π° ΠΊΠ»Π°ΡΡΠ°: get_transforms - ΠΌΠ΅ΡΠΎΠ΄ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ Π°ΡΠ³ΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΎΠΏΠΈΡΠ°Π½Ρ Π² transform.py Π½Π° ΡΠ°Π·Π»ΠΈΡΠ½ΡΡ ΡΡΠ°ΠΏΠ°Ρ (Π’ΡΠ΅Π½ΠΈΡΠΎΠ²ΠΊΠ°, ΠΠ°Π»ΠΈΠ΄Π°ΡΠΈΡ, ΠΠ½ΡΠ΅ΡΠ΅Π½Ρ) get_datasets - ΠΌΠ΅ΡΠΎΠ΄, ΠΊΠΎΡΠΎΡΡΠΉ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΠ»ΠΎΠ²Π°ΡΡ {"image": ..., "mask":...} ΠΈΠ· ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΏΠΎΠ΄Π³ΠΎΡΠΎΠ²Π»Π΅Π½Π½ΡΡ csv ΡΠ°ΠΉΠ»ΠΎΠ².
import collections
import pandas as pd
from catalyst.dl import ConfigExperiment
from .dataset import SegmentationDataset
from .transforms import (
pre_transforms, post_transforms, hard_transform, Compose
)
class Experiment(ConfigExperiment):
@staticmethod
def get_transforms(
stage: str = None, mode: str = None, image_size: int = 256,
):
pre_transform_fn = pre_transforms(image_size=image_size)
if mode == "train":
post_transform_fn = Compose([
hard_transform(image_size=image_size),
post_transforms()
])
elif mode in ["valid", "infer"]:
post_transform_fn = post_transforms()
else:
raise NotImplementedError()
transform_fn = Compose([pre_transform_fn, post_transform_fn])
return transform_fn
def get_datasets(
self,
stage: str,
in_csv_train: str = None,
in_csv_valid: str = None,
image_size: int = 256,
):
datasets = collections.OrderedDict()
for source, mode in zip(
(in_csv_train, in_csv_valid), ("train", "valid")
):
dataframe = pd.read_csv(source)
datasets[mode] = SegmentationDataset(
dataframe.to_dict('records'),
dict_transform=self.get_transforms(
stage=stage, mode=mode, image_size=image_size
),
)
return datasets
- Π ΡΠ°ΠΉΠ»Π΅ transforms.py ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡΡ ΡΡΠ½ΠΊΡΠΈΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡΡ ΠΏΡΠ΅ΠΏΡΠΎΡΠ΅ΡΡΠΈΠ½Π³, Π°ΡΠ³ΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ ΠΈ ΠΏΠΎΡΡΠΏΡΠΎΡΠ΅ΡΡΠΈΠ½Π³ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΈΠΉ.
import cv2
from albumentations import (
Compose, LongestMaxSize, PadIfNeeded, Normalize, ShiftScaleRotate,
RandomGamma
)
from albumentations.pytorch import ToTensor
cv2.setNumThreads(0)
cv2.ocl.setUseOpenCL(False)
def pre_transforms(image_size=256):
return Compose([
LongestMaxSize(max_size=image_size),
PadIfNeeded(image_size, image_size, border_mode=cv2.BORDER_CONSTANT),
])
def post_transforms():
return Compose([Normalize(), ToTensor()])
def hard_transform(image_size=256):
return Compose([
ShiftScaleRotate(
shift_limit=0.1,
scale_limit=0.1,
rotate_limit=15,
border_mode=cv2.BORDER_REFLECT,
p=0.5
),
])
Π‘ΡΠΎΠΈΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎ ΡΠΏΠΎΠΌΡΠ½ΡΡΡ ΠΏΡΠΎ Registry. Π Catalyst ΡΠΆΠ΅ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ΠΎ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ, ΠΊΠΎΠ»Π±ΡΠΊΠΎΠ², Π»ΠΎΡΡΠΎΠ², ΠΎΠΏΡΠΈΠΌΠ°ΠΉΠ·Π΅ΡΠΎΠ². ΠΡΠ»ΠΈ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ Ρ
ΠΎΡΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠ²ΠΎΠΈ ΠΌΠΎΠ΄Π΅Π»ΠΈ, ΠΊΠΎΠ»Π±ΡΠΊΠΈ, Π»ΠΎΡΡΡ, ΠΎΠΏΡΠΈΠΌΠ°ΠΉΠ·Π΅ΡΡ ΠΎΠ½ ΠΌΠΎΠΆΠ΅Ρ ΡΠ°ΠΌΠΎΡΡΠΎΡΡΠ΅Π»ΡΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ ΠΈΡ
Π² Registry ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΠ»Π΅Π΄ΡΡΡΠ΅Π³ΠΎ API - Callback(SomeCallback)
, Model(MyModel)
, Criterion(GreatLoss)
, Optimizer(NewAwesomeOptimizer)
, registry.Scheduler(EvenScheduler)
. Π§ΡΠΎΠ±Ρ ΠΏΠΎΡΠΎΠΌ ΡΡΠΎ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π² Config.yml. Π ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΏΡΠΈΠΌΠ΅ΡΠ° ΡΠΎΠ·Π΄Π°Π΄ΠΈΠΌ ΠΌΠΎΠ΄Π΅Π»Ρ ΠΊΠ»Π°ΡΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ SimpleNet Π² ΡΠ°ΠΉΠ»Π΅ model.py
model.py
import torch.nn as nn
import torch.nn.functional as F
from catalyst.dl import reqistry
@registry.Model # ΠΡΠΎΡ Π΄Π΅ΠΊΠΎΡΠ°ΡΠΎΡ ΡΠ΅Π³ΠΈΡΡΡΡΠ΅Ρ ΠΌΠΎΠ΄Π΅Π»Ρ
class SimpleNet(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2D(2, 2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16 * 5 * 5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
ΠΠΎΡΠ»Π΅ ΡΡΠΎΠ³ΠΎ Π² ΠΏΠΎΠ»Π΅ model config ΡΠ°ΠΉΠ»Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΈΠΌΡ SimpleModel. ΠΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΠΏΠΎΠ»Π΅ΠΉ Π² config.yml ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ Π·Π΄Π΅ΡΡ https://github.com/catalyst-team/catalyst/tree/master/examples/configs. ΠΠ±ΡΠ°ΡΠ°Ρ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΡΡΠΎ Π² ΠΏΠΎΠ»Π΅ runner_params Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠ² Π΄Π»Ρ Π·Π°Π΄Π°ΡΠΈ ΡΠ΅Π³ΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ ΡΠΊΠ°Π·ΡΠ²Π°Π΅ΠΌ - input_key - "image", output_key - "logits".
ΠΠΎ Π΄Π°Π½Π½ΠΎΠΉ ΡΡΡΠ»ΠΊΠ΅ Π΄ΠΎΡΡΡΠΏΠ½ΠΎ ΠΏΠΎΠ»Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΠΏΠΎΠ»Π΅ΠΉ config ΠΠ° Π΅Π³ΠΎ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π½Π°ΠΏΠΈΡΠ΅ΠΌ config.yml, Π² ΠΊΠΎΡΠΎΡΠΎΠΌ ΡΠΊΠ°ΠΆΠ΅ΠΌ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΡΠ΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π΄Π»Ρ Π·Π°ΠΏΡΡΠΊΠ° ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ:
model_params:
model: ResnetFPNUnet
num_classes: 1
arch: resnet18
pretrained: True
args:
expdir: "src"
logdir: "logs"
runner_params: # OPTIONAL KEYWORD, params for Runner's init
input_key: "image"
output_key: "logits"
stages:
state_params:
main_metric: &reduce_metric dice
minimize_metric: False
data_params:
num_workers: 0
batch_size: 64
in_csv_train: "./data/dataset_train.csv"
in_csv_valid: "./data/dataset_valid.csv"
image_size : 256
criterion_params:
criterion: DiceLoss
stage1:
state_params:
num_epochs: 10
optimizer_params:
optimizer: Adam
lr: 0.001
weight_decay: 0.0003
scheduler_params:
scheduler: MultiStepLR
milestones: [10]
gamma: 0.3
callbacks_params:
loss_dice:
callback: CriterionCallback
input_key: mask
output_key: logits
prefix: &loss loss_dice
accuracy:
callback: DiceCallback
input_key: mask
output_key: logits
optimizer:
callback: OptimizerCallback
loss_key: *loss
scheduler:
callback: SchedulerCallback
reduce_metric: *reduce_metric
saver:
callback: CheckpointCallback
ΠΠΎΡΠ»Π΅ ΡΠ΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΡΡΡΠΈΡΡ ΠΏΡΠΎΡΠ΅ΡΡ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ:
catalyst-dl run --config=./config.yml --verbose
Π Π΅Π·ΡΠ»ΡΡΠ°ΡΡ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ tensorboard ΠΏΡΠΈ ΠΏΠΎΠΌΠΎΡΠΈ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΉ ΠΊΠΎΠΌΠΌΠ°Π½Π΄Ρ:
tensorboard --logdir ./logs
ΠΠΎΡΠ»Π΅ ΠΎΠ±ΡΡΠ΅Π½ΠΈΡ Π²Π΅ΡΠ° ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ Π² ./logs/checkpoints ΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΠΈΡ Π΄Π΅Π»Π°ΡΡ ΠΈΠ½ΡΠ΅ΡΠ΅Π½Ρ ΡΠΎΠ³Π»Π°ΡΠ½ΠΎ ΡΡΠΎΠΌΡ ΡΡΡΠΎΡΠΈΠ°Π»Ρ. ΠΠΎ Π΄Π»Ρ ΠΏΡΠΎΠ΄Π°ΠΊΡΠ΅Π½Π°, Ρ ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΡ Π΄ΡΡΠ³ΠΎΠΉ ΡΠΏΠΎΡΠΎΠ±, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ jit trace, ΡΡΠΎΠ±Ρ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π±ΠΈΠ½Π°ΡΠ½ΠΈΠΊ. ΠΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΡΠΊΠΎΡΠΈΡΡ ΠΈΠ½ΡΠ΅ΡΠ΅Π½Ρ ΠΈ Π·Π°Π³ΡΡΠΆΠ°ΡΡ ΠΌΠΎΠ΄Π΅Π»ΠΈ Π½Π° Π‘++. ΠΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅ ΠΎΠ± ΡΡΠΎΠΌ Π·Π΄Π΅ΡΡ. ΠΠ»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ ΡΠ΄Π΅Π»Π°ΡΡ trace, Π½ΡΠΆΠ½ΠΎ Π·Π°ΠΏΡΡΡΠΈΡΡ ΡΠ»Π΅Π΄ΡΡΡΡΡ ΠΊΠΎΠΌΠΌΠ°Π½Π΄Ρ:
catalyst-dl trace ./logs
Π ΠΏΠ°ΠΏΠΊΠ΅ logs/trace/ ΠΈ Π±ΡΠ΄ΡΡ Π½Π°Ρ ΠΎΠ΄ΠΈΡΡΡΡ Π²Π΅ΡΠ° ΠΌΠΎΠ΄Π΅Π»ΠΈ - traced-best-forward.pth. ΠΠ»Ρ ΠΈΠ½ΡΠ΅ΡΠ΅Π½ΡΠ° Π½Π°ΠΏΠΈΡΠ΅ΠΌ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ ΠΊΠ»Π°ΡΡ Π΄Π»Ρ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΈ ΠΌΠ΅ΡΠΎΠ΄Π° ΠΏΡΠ΅Π΄ΠΈΠΊΡ ΠΈ ΡΠΎΡ ΡΠ°Π½ΠΈΠΌ Π΅Π³ΠΎ Π² inference.py:
import numpy as np
import cv2
import torch.nn as nn
import torch
import os
from catalyst.dl import utils
from transforms import (pre_transforms, post_transforms, Compose)
class Predictor:
def __init__(self, model_path,image_size):
self.augmentation =Compose([pre_transforms(image_size=image_size),post_transforms()])
self.m = nn.Sigmoid()
self.model = utils.load_traced_model(model_path).cuda()
device_name = "cuda:0" if torch.cuda.is_available() else "cpu"
self.device = torch.device(device_name)
self.image_size = image_size
def predict(self, image,threshold):
augmented = self.augmentation(image=image)
inputs = augmented['image']
inputs = inputs.unsqueeze(0).to(self.device)
output = self.m(self.model(inputs)[0][0]).cpu().numpy()
probability = (output > threshold).astype(np.uint8)
return probability
ΠΠ»Ρ ΠΏΡΠ΅Π΄ΡΠΊΠ°Π·Π°Π½ΠΈΡ ΠΌΠ°ΡΠΎΠΊ ΠΊΠ°ΡΡΠΈΠ½ΠΎΠΊ Π·Π°ΠΏΠΈΡΠ΅ΠΌ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ ΡΠΊΡΠΈΠΏΡ ΠΈ ΡΠΎΡ ΡΠ°Π½ΠΈΠΌ Π΅Π³ΠΎ Π² CarSegmentation.py:
from inferens import Predictor
import argparse
import pandas as pd
import os
import cv2
import numpy as np
def Car_Segmenatation(path_in, path_out, path_model,threshold,image_size):
mask_predictor = RemoveBackground(path_model,image_size)
data = pd.DataFrame({"image":os.listdir(path_in)})
for image_file in data.iloc[:,0]:
image = cv2.resize(cv2.imread(os.path.join(path_in,image_file)), (image_size,image_size))
probability = mask_predictor.predict(image, threshold=0.5)
image[probability==0]=[255,255,255]
cv2.imwrite(os.path.join(path_out,image_file),image)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description = 'folders to files')
parser.add_argument('path_in', type=str, help='dir with image')
parser.add_argument('path_out', type=str, help='output dir')
parser.add_argument('path_model', type = str, help = 'path_model')
parser.add_argument('threshold', type = float, help = 'threshold')
parser.add_argument('image_size', type = int, help = 'image_size')
args = parser.parse_args()
Car_Segmenatation(args.path_in,args.path_out,args.path_model,args.threshold,args.image_size)
ΠΠ°ΠΏΡΡΡΠΈΠΌ ΡΠΊΡΠΈΠΏΡ
python CarSegmentation.py path_in,path_out,path_model,treshold, image_size
Π’Π°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ, ΠΏΠΎΠ»ΡΡΠΈΠ»ΠΎΡΡ ΡΠΎΠ·Π΄Π°ΡΡ ΠΏΠΎΠ»Π½ΠΎΡΠ΅Π½Π½ΡΠΉ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½ ΡΡΠ΅Π½ΠΈΡΠΎΠ²ΠΊΠΈ ΠΈ ΠΈΠ½ΡΠ΅ΡΠ΅Π½ΡΠ° Π±Π΅Π· ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ juputer notebook, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡΠΈΠΉ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ ΠΎΠ±ΡΡΠ΅Π½ΠΈΠ΅ ΠΌΠ΅Π½ΡΡ Π»ΠΈΡΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ config ΡΠ°ΠΉΠ»Π°. ΠΠΎΠ»Π½ΡΠΉ ΠΊΠΎΠ΄ ΡΡΠ΅Π½ΠΈΡΠΎΠ²ΠΊΠΈ ΠΈ ΠΈΠ½ΡΠ΅ΡΠ΅Π½ΡΠ° Π΄ΠΎΡΡΡΠΏΠ΅Π½ Π² ΡΡΠΎΠΌ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΈ.
ΠΡΡΠ°ΠΆΠ°Ρ Π±Π»Π°Π³ΠΎΠ΄Π°ΡΠ½ΠΎΡΡΡ ΠΠ²Π³Π΅Π½ΠΈΡ ΠΠ°ΡΠ°Π½Ρ, Π ΠΎΠΌΠ°Π½Ρ Π’Π΅Π·ΠΈΠΊΠΎΠ²Ρ, Π‘Π΅ΡΠ³Π΅Ρ ΠΠΎΠ»Π΅ΡΠ½ΠΈΠΊΠΎΠ²Ρ, ΠΠ»Π΅ΠΊΡΠ΅Ρ ΠΠ°Π·ΠΈΠ΅Π²Ρ Π·Π° ΠΏΠΎΠΌΠΎΡΡ ΠΏΡΠΈ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΠΈ ΡΡΠ°ΡΡΠΈ.