ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Cross-Image Relational Knowledge Distillation for Semantic Segmentation 코드 실행 및 리뷰 - (1)
    Study/Paper 2024. 12. 12. 17:40

    본 리뷰는 CVPR 2022년에 나온  Cross-Image Relational Knowledge Distillation for Semantic Segmentation 논문에 대한 official code인 https://github.com/winycg/CIRKD 를 참고하여 작성되었다.

     

    사용 환경은 ubuntu 20.04, 3090GPU 1ea 이다.

     

    먼저 환경 세팅과 inference 실행까지를 (1)에서 다루고, (2)에서 코드의 상세한 리뷰를 진행한다.

    더보기

    전체 구조

    CIRKD
    ├── dataset
    │   ├── ade20k.py
    │   ├── camvid.py
    │   ├── cityscapes.py
    │   ├── coco_stuff_164k.py
    │   ├── list
    │   │   ├── CamVid
    │   │   │   ├── camvid_test_list.txt
    │   │   │   ├── camvid_train_list.txt
    │   │   │   ├── camvid_trainval_list.txt
    │   │   │   └── camvid_val_list.txt
    │   │   ├── cityscapes
    │   │   │   ├── test.lst
    │   │   │   ├── train++.lst
    │   │   │   ├── train+.lst
    │   │   │   ├── train.lst
    │   │   │   ├── trainval.lst
    │   │   │   └── val.lst
    │   │   ├── coco_stuff_164k
    │   │   │   ├── coco_stuff_164k_train.txt
    │   │   │   └── coco_stuff_164k_val.txt
    │   │   └── voc
    │   │       ├── train_aug.txt
    │   │       └── val.txt
    │   ├── __pycache__
    │   │   ├── ade20k.cpython-38.pyc
    │   │   ├── camvid.cpython-38.pyc
    │   │   ├── cityscapes.cpython-38.pyc
    │   │   ├── coco_stuff_164k.cpython-38.pyc
    │   │   ├── datasets.cpython-38.pyc
    │   │   ├── datasets.cpython-39.pyc
    │   │   └── voc.cpython-38.pyc
    │   └── voc.py
    ├── eval.py
    ├── eval_segformer.py
    ├── figures
    │   ├── 000000025394.jpg
    │   ├── 000000025394.png
    │   ├── 2007_000033.jpg
    │   ├── 2007_000033.png
    │   ├── ADE_val_00000053.jpg
    │   ├── ADE_val_00000053.png
    │   ├── frankfurt_000000_000576_gtFine_labelIds.png
    │   └── frankfurt_000000_000576_leftImg8bit.png
    ├── losses
    │   ├── adv.py
    │   ├── at.py
    │   ├── cirkd_memory.py
    │   ├── cirkd_mini_batch.py
    │   ├── cwd.py
    │   ├── dsd.py
    │   ├── fitnet.py
    │   ├── ifvd.py
    │   ├── __init__.py
    │   ├── kd.py
    │   ├── __pycache__
    │   │   ├── adv.cpython-38.pyc
    │   │   ├── at.cpython-38.pyc
    │   │   ├── cirkd_memory.cpython-38.pyc
    │   │   ├── cirkd_mini_batch.cpython-38.pyc
    │   │   ├── cwd.cpython-38.pyc
    │   │   ├── dsd.cpython-38.pyc
    │   │   ├── fitnet.cpython-38.pyc
    │   │   ├── ifvd.cpython-38.pyc
    │   │   ├── __init__.cpython-38.pyc
    │   │   ├── kd.cpython-38.pyc
    │   │   ├── loss.cpython-38.pyc
    │   │   ├── memory_loss.cpython-38.pyc
    │   │   ├── skd.cpython-38.pyc
    │   │   └── task.cpython-38.pyc
    │   ├── references.md
    │   ├── skd.py
    │   └── task.py
    ├── models
    │   ├── base_models
    │   │   ├── hrnet.py
    │   │   ├── __init__.py
    │   │   ├── mobilenetv2.py
    │   │   ├── __pycache__
    │   │   │   ├── __init__.cpython-38.pyc
    │   │   │   ├── mobilenetv2.cpython-38.pyc
    │   │   │   ├── resnet.cpython-38.pyc
    │   │   │   └── resnetv1b.cpython-38.pyc
    │   │   └── resnet.py
    │   ├── deeplabv3_mobile.py
    │   ├── deeplabv3.py
    │   ├── __init__.py
    │   ├── model_zoo.py
    │   ├── psp_mobile.py
    │   ├── pspnet.py
    │   ├── __pycache__
    │   │   ├── bisenet.cpython-38.pyc
    │   │   ├── cgnet.cpython-38.pyc
    │   │   ├── danet.cpython-38.pyc
    │   │   ├── deeplabv3.cpython-38.pyc
    │   │   ├── deeplabv3_mobile.cpython-38.pyc
    │   │   ├── deeplabv3_plus.cpython-38.pyc
    │   │   ├── denseaspp.cpython-38.pyc
    │   │   ├── dfanet.cpython-38.pyc
    │   │   ├── dunet.cpython-38.pyc
    │   │   ├── encnet.cpython-38.pyc
    │   │   ├── enet.cpython-38.pyc
    │   │   ├── espnet.cpython-38.pyc
    │   │   ├── fcn.cpython-38.pyc
    │   │   ├── fcnv2.cpython-38.pyc
    │   │   ├── icnet.cpython-38.pyc
    │   │   ├── __init__.cpython-38.pyc
    │   │   ├── lednet.cpython-38.pyc
    │   │   ├── model_zoo.cpython-38.pyc
    │   │   ├── ocnet.cpython-38.pyc
    │   │   ├── psanet.cpython-38.pyc
    │   │   ├── psp_mobile.cpython-38.pyc
    │   │   ├── pspnet.cpython-38.pyc
    │   │   ├── segbase.cpython-38.pyc
    │   │   └── segformer.cpython-38.pyc
    │   ├── segbase.py
    │   └── segformer.py
    ├── README.md
    ├── test.py
    ├── train_baseline.py
    ├── train_baseline_segformer.py
    ├── train_cirkd.py
    ├── train_cirkd_segformer.py
    ├── train_kd.py
    ├── train_kd_segformer.py
    ├── train_scripts
    │   ├── test_cityscapes.sh
    │   ├── train_baseline
    │   │   ├── ade20k
    │   │   │   ├── deeplabv3_res101.sh
    │   │   │   └── deeplabv3_res18.sh
    │   │   ├── camvid
    │   │   │   ├── deeplabv3_res101.sh
    │   │   │   ├── deeplabv3_res18.sh
    │   │   │   └── pspnet_res18.sh
    │   │   ├── citys
    │   │   │   ├── deeplabv3_mbv2.sh
    │   │   │   ├── deeplabv3_res101.sh
    │   │   │   ├── deeplabv3_res18.sh
    │   │   │   ├── pspnet_res18.sh
    │   │   │   ├── segformer_mit_b0.sh
    │   │   │   └── segformer_mit_b4.sh
    │   │   ├── coco_stuff_164k
    │   │   │   ├── deeplabv3_res101.sh
    │   │   │   └── deeplabv3_res18.sh
    │   │   └── voc
    │   │       ├── deeplabv3_res101.sh
    │   │       ├── deeplabv3_res18.sh
    │   │       └── pspnet_res18.sh
    │   ├── train_cirkd
    │   │   ├── ade20k
    │   │   │   └── deeplabv3_res18.sh
    │   │   ├── camvid
    │   │   │   ├── deeplabv3_res18.sh
    │   │   │   └── pspnet_res18.sh
    │   │   ├── citys
    │   │   │   ├── deeplabv3_mbv2.sh
    │   │   │   ├── deeplabv3_res18.sh
    │   │   │   ├── pspnet_res18.sh
    │   │   │   └── segformer_mit_b0.sh
    │   │   ├── coco_stuff_164k
    │   │   │   └── deeplabv3_res18.sh
    │   │   └── voc
    │   │       ├── deeplabv3_res18.sh
    │   │       └── pspnet_res18.sh
    │   ├── train_kd
    │   │   ├── train_at.sh
    │   │   ├── train_cwd.sh
    │   │   ├── train_dsd.sh
    │   │   ├── train_fitnet.sh
    │   │   ├── train_ifvd.sh
    │   │   └── train_skd.sh
    │   └── visualize
    │       ├── ade20k.sh
    │       ├── cityscapes.sh
    │       ├── coco_stuff_164k.sh
    │       └── pascal_voc.sh
    ├── tsne
    │   ├── save_embeddings.py
    │   ├── tsne.sh
    │   └── tsne_visual.py
    └── utils
        ├── distributed.py
        ├── flops.py
        ├── __init__.py
        ├── logger.py
        ├── __pycache__
        │   ├── distributed.cpython-38.pyc
        │   ├── distributed.cpython-39.pyc
        │   ├── flops.cpython-38.pyc
        │   ├── __init__.cpython-38.pyc
        │   ├── __init__.cpython-39.pyc
        │   ├── logger.cpython-38.pyc
        │   ├── logger.cpython-39.pyc
        │   ├── sagan.cpython-38.pyc
        │   ├── score.cpython-38.pyc
        │   ├── score.cpython-39.pyc
        │   └── visualize.cpython-38.pyc
        ├── sagan.py
        ├── score.py
        └── visualize.py
    
    32 directories, 169 files

     

    전체 구조를 보면서 파악하기는 어렵기 때문에 tree -L 1 -C 옵션을 사용해서 깊이 1로 출력해보았다.

     

    tree -L 1 -C

     

    먼저 Readme 파일 내용대로 환경 세팅을 하고 실행을 해보자. 아나콘다를 권장하고 있지만, 우분투와 cuda를 맞춰주기 위해서 도커파일을 작성하여 빌드해보았다.

     

    맞추어야 하는 환경은 다음과 같다.

    이를 위해 다음과 같이 도커 파일을 작성하고, 이미지로 만든 후 빌드하였다.

     

    # Use Ubuntu 18.04 as the base image
    # https://gitlab.com/nvidia/container-images/cuda/blob/master/doc/supported-tags.md
    FROM nvidia/cuda:11.1.1-cudnn8-devel-ubuntu18.04
    
    # Set the environment variables
    ENV DEBIAN_FRONTEND=noninteractive
    
    # 사용자 정의 UID
    ARG USER_ID=1000
    ARG USER_NAME=사용자계정작성부분
    RUN useradd -m --no-log-init --system --uid ${USER_ID} ${USER_NAME} && \
        echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
    
    # Install dependencies
    RUN apt-get update && apt-get install -y --no-install-recommends \
        software-properties-common && \
        add-apt-repository ppa:deadsnakes/ppa && \
        apt-get update && apt-get install -y --no-install-recommends \
        python3.8 \
        python3.8-dev \
        python3.8-distutils \
        python3-pip \
        python3-opencv \
        wget \
        git \
        curl \
        ca-certificates \
        libnccl2=2.8.4-1+cuda11.1 \
        libnccl-dev=2.8.4-1+cuda11.1 && \
        apt-get clean && \
        rm -rf /var/lib/apt/lists/*
    
    RUN ln -sf /usr/bin/python3.8 /usr/bin/python && \
        ln -sf /usr/bin/python3.8 /usr/bin/python3
    # Install PyTorch 1.8.0 with CUDA 11.1
    RUN python3.8 -m pip install --upgrade pip \
        && pip install torch==1.8.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cu111
    
    # Set the working directory
    USER ${USER_NAME}
    WORKDIR /home/${USER_NAME}/Desktop/project/kd/CIRKD
    
    # CUDA 경로 설정
    ENV CUDA_HOME=/usr/local/cuda-11.1
    ENV PATH=$CUDA_HOME/bin:$PATH
    ENV LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH
    ENV PATH="/home/${USER_NAME}/.local/bin:${PATH}"
    
    # Default command
    CMD ["/bin/bash"]

     

    사용자계정작성부분으로 표기된 부분은 개인정보라서 지웠으니 사용할 때에는 본인 계정을 작성하면 된다. 또한 WORKDIR의 경우에도 각자의 디렉토리 주소가 다르기 때문에 수정하여 사용해야 한다.

     

    명령어는 [docker build -t cirkd:1.0 -f Dockerfile .]  를 사용하였고 성공적으로 이미지로 빌드하였다.

    또한 [docker run -it --gpus all -v $(pwd):$(pwd) --name cirkd_container cirkd:1.0] 를 통해 모든 gpu를 사용하고, volume 연결을 현재의 주소와 연결한 컨테이너를 만들어 실행시켰다.

     

    그 후 추가적으로 라이브러리 설치를 진행했다.

    pip install timm==0.3.2 mmcv-full==1.2.7 opencv-python==4.5.1.48

     

    이렇게 환경 세팅을 완료했으니, pretrained된 모델 백본과 데이터를 넣어주는 일만 남았다.

     

    여기서 문제가 생긴다. CNN 백본들은 구글드라이브에 올려져있지만 Transformer 백본들은 바이두에 올라가있어서 다운로드할 때 바이두 계정이 필요하다. 하지만 바이두 계정이 없다.

     

    그냥 바이두 계정이 아니라 바이두 클라우드 계정이 필요하기 때문에 https://login.bce.baidu.com/?lang=en 반드시 여기서 sign up을 진행한다. 예전엔 불가능했다는데 현재 (24.12.12) 시점에서는 한국 휴대폰 번호로 가입이 가능하므로 번호를 넣고 가입을 진행하여 모델을 다운로드 받자.

     

    내부적으로 BaiduNetdisk를 깔고 실행해서 바이두로 로그인한 후에 다운로드받는 형태로 되어있다. 따로 추가적으로 앱을 폰에 깔거나 하지 않아도 된다.

     

     

    위의 화면처럼 다운로드를 진행하고 각 파일을 위치에 맞게 넣어준다.

    어느 위치에 넣어야 하는지 readme파일에서 지정되어있지 않으므로 하나하나 찾아서 수행해주어야 한다.

     

    모든 pretrained 모델을 담을 폴더를 하나 생성해준 후에 models/base_models에 들어가서 주소값을 바꾸어주도록 하자.

     

    mobilenetv2.py 파일의 204번째 줄에서 아래의 pretrained 주소를 바꾸어준다.

    net = get_mobilenet_v2(pretrained='/home/users/chuanguang.yang/winycg/seg_job/semantic-segmentation-pytorch/pretrained_backbones/mobilenetv2-imagenet.pth', norm_layer=nn.BatchNorm2d).cuda()

     

     

     

     

     

    다음으로는 데이터셋을 준비해야 한다. 여기서는 Cityscapes만 사용하여 테스트한다. Cityscapes 데이터셋은 https://www.cityscapes-dataset.com/register/ 여기서 등록 후 다운로드 할 수 있다.

     

     

    해당 리스트를 하나씩 채운 후 등록한 후 메일로 인증까지 완료하면 다운로드가 가능하다.

     

    leftImg8bit_trainvaltest.zip (11GB) [md5] 을 다운로드한다. 해당 데이터셋의 설명으로 5000개의 이미지가 제공된다고 작성되어있다.

     

    다운로드한 데이터를 데이터 폴더 안에 넣고, eval.py 파일 실행을 위해 train_scripts/train_baseline/citys/deeplabv3_res18.sh 파일을 실행해보았다. 이때 pretrained 파일을 다운로드 하여 폴더에 넣었고, sh 파일 내부의 내용 또한 다음과 같이 변경하였다.

     

      CUDA_VISIBLE_DEVICES=0 \
      python -m torch.distributed.launch --nproc_per_node=4 eval.py \
      --model deeplabv3 \
      --backbone resnet18 \
      --data /home/knuvi/Desktop/project/kd/CIRKD/dataset/cityscapes/ \
      --save-dir /home/knuvi/Desktop/project/kd/CIRKD/results \
      --pretrained /home/knuvi/Desktop/project/kd/CIRKD/pretrained/deeplabv3_resnet101_citys_best_model.pth

     

     

    지금까지 환경 세팅과 inference 수행에 대해 다루어보았다. 

    자세한 코드 리뷰를 여기에서 이어서 진행해보도록 하겠다.

Designed by Tistory.