{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 2_training_oxford-pet_ddp(Distributed Data Parallel)\n", "---\n", "\n", "본 모듈에서는 Amzaon SageMaker API을 효과적으로 이용하기 위해 multigpu-distributed 학습을 위한 PyTorch 프레임워크 기반 모델 훈련을 수행해 봅니다." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "tags": [] }, "outputs": [], "source": [ "install_needed = True\n", "# install_needed = False" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "installing deps and restarting kernel\n" ] } ], "source": [ "import sys\n", "import IPython\n", "\n", "if install_needed:\n", " print(\"installing deps and restarting kernel\")\n", " !{sys.executable} -m pip install --upgrade pip --quiet\n", " !{sys.executable} -m pip install -U wget split-folders --quiet\n", " IPython.Application.instance().kernel.do_shutdown(True)" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## 1. Sagemaker notebook 설명\n", "
Sagemaker notebook은 완전 관리형 서비스로 컨테이너 기반으로 구성되어 있습니다. 사용자가 직접 컨테이너를 볼 수 없지만, 내부적으로는 아래와 같은 원리로 동작합니다.
\n", "학습과 추론을 하는 hosting 서비스는 각각 다른 컨테이너 환경에서 수행할 수 있으며, 쉽게 다량으로 컨테이너 환경을 확장할 수 있으므로 다량의 학습과 hosting이 동시에 가능합니다. \n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sagemaker 학습에 필요한 기본적인 package를 import 합니다.
\n", "boto3는 HTTP API 호출을 숨기는 편한 추상화 모델을 가지고 있고, Amazon EC2 인스턴스 및 S3 버켓과 같은 AWS 리소스와 동작하는 파이선 클래스를 제공합니다.
\n", "sagemaker python sdk는 Amazon SageMaker에서 기계 학습 모델을 교육 및 배포하기 위한 오픈 소스 라이브러리입니다.
" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "tags": [] }, "outputs": [], "source": [ "import os\n", "import sagemaker\n", "from pathlib import Path\n", "from time import strftime\n", "\n", "sagemaker_session = sagemaker.Session()\n", "\n", "bucket = sagemaker_session.default_bucket()\n", "role = sagemaker.get_execution_role()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "'2.169.0'" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sagemaker.__version__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Dataset 소개 및 split 후 S3 upload하기\n", "이번 학습에 사용할 이미지 데이터는 Oxford-IIIT Pet Dataset 입니다. Oxford-IIIT Pet Dataset은 37개 다른 종의 개와 고양이 이미지를 각각 200장 씩 제공하고 있으며, Ground Truth 또한 Classification, Object Detection, Segmentation와 관련된 모든 정보가 있으나, 이번 학습에서는 37개 class에 대해 일부 이미지로 Classification 문제를 해결하기 위해 학습을 진행할 예정입니다.
\n", "이미지 파일을 학습하기 위해 SageMaker Notebook 환경으로 upload를 합니다. 폴더 구조는 아래와 같은 형태로 구성되어야 합니다.
\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", " image_path/class1/Aimage_1\n", "
\n", " Aimage_2
\n", " ...
\n", " Aimage_N
\n", " image_path/class2/Bimage_1
\n", " Bimage_2
\n", " ...
\n", " Bimage_M
\n", "
SageMaker 학습을 위해 train/val로 분리한 폴더를 S3내 이전에 지정한 bucket 내 prefix 하위 폴더로 upload합니다.
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Uploading the data to S3\n", "We are going to use the `sagemaker.Session.upload_data` function to upload our datasets to an S3 location. The return value inputs identifies the location -- we will use later when we start the training job.\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "tags": [] }, "outputs": [], "source": [ "def make_dir(img_path, delete=True):\n", " import shutil, os\n", " try:\n", " if not os.path.exists(img_path):\n", " os.makedirs(img_path)\n", " else:\n", " if delete:\n", " shutil.rmtree(img_path)\n", " except OSError:\n", " print(\"Error\")" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "tags": [] }, "outputs": [], "source": [ "!rm -rf dataset/oxford_dataset" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "tags": [] }, "outputs": [], "source": [ "rawimg_path = 'dataset/oxford_dataset/raw'\n", "dataset_path = 'dataset/oxford_dataset/dataset'\n", "output_dir = 'dataset/oxford_dataset/output'\n", "\n", "make_dir(rawimg_path)\n", "make_dir(dataset_path)\n", "make_dir(output_dir)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "tags": [] }, "outputs": [], "source": [ "if not (os.path.isfile(\"images.tar.gz\") and tarfile.is_tarfile(\"images.tar.gz\")):\n", " wget.download('https://www.robots.ox.ac.uk/~vgg/data/pets/data/images.tar.gz')\n", "tar = tarfile.open(\"images.tar.gz\")\n", "tar.extractall(path=rawimg_path)\n", "tar.close()" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "tags": [] }, "outputs": [], "source": [ "import cv2\n", "import os\n", "import glob\n", "import wget\n", "import tarfile\n", "import splitfolders\n", "import numpy as np\n", "import shutil\n", "\n", "def checkImage(path):\n", " try:\n", " with open(path, 'rb') as f:\n", " data = f.read()\n", " f.seek(-2,2)\n", " value = f.read()\n", "\n", " encoded_img = np.frombuffer(data, dtype = np.uint8)\n", " img_cv = cv2.imdecode(encoded_img, cv2.IMREAD_COLOR)\n", " if img_cv.shape[0]>0 and value == b'\\xff\\xd9':\n", " return True\n", " except:\n", " return False" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "tags": [] }, "outputs": [], "source": [ "corrupt_img = ['Egyptian_Mau_14.jpg','Egyptian_Mau_139.jpg','Egyptian_Mau_145.jpg','Egyptian_Mau_156.jpg',\n", " 'Egyptian_Mau_167.jpg','Egyptian_Mau_177.jpg','Egyptian_Mau_186.jpg','Egyptian_Mau_191.jpg',\n", " 'Abyssinian_5.jpg','Abyssinian_34.jpg','chihuahua_121.jpg','beagle_116.jpg']" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "scrolled": true, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dataset/oxford_dataset/raw/images/Egyptian_Mau_191.jpg\n", "dataset/oxford_dataset/raw/images/Abyssinian_100.mat\n", "dataset/oxford_dataset/raw/images/Abyssinian_102.mat\n", "dataset/oxford_dataset/raw/images/Egyptian_Mau_14.jpg\n", "dataset/oxford_dataset/raw/images/Egyptian_Mau_156.jpg\n", "dataset/oxford_dataset/raw/images/Egyptian_Mau_139.jpg\n", "dataset/oxford_dataset/raw/images/Egyptian_Mau_167.jpg\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Corrupt JPEG data: premature end of data segment\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "dataset/oxford_dataset/raw/images/beagle_116.jpg\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Corrupt JPEG data: 240 extraneous bytes before marker 0xd9\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "dataset/oxford_dataset/raw/images/chihuahua_121.jpg\n", "dataset/oxford_dataset/raw/images/Egyptian_Mau_138.jpg\n", "dataset/oxford_dataset/raw/images/Abyssinian_34.jpg\n", "dataset/oxford_dataset/raw/images/Abyssinian_101.mat\n", "dataset/oxford_dataset/raw/images/Egyptian_Mau_177.jpg\n", "dataset/oxford_dataset/raw/images/Egyptian_Mau_145.jpg\n", "dataset/oxford_dataset/raw/images/Egyptian_Mau_186.jpg\n", "dataset/oxford_dataset/raw/images/Abyssinian_5.jpg\n" ] } ], "source": [ "file_dir = os.path.join(rawimg_path, 'images')\n", "\n", "for file_path in glob.glob(file_dir + \"/*\"):\n", " filename = file_path.split(\"/\")[4]\n", " if checkImage(file_path) and filename not in corrupt_img:\n", " dir_name = filename.split(\"_\")\n", " dir_name.pop()\n", " dir_name = \"_\".join(dir_name)\n", " dir_path = os.path.join(output_dir, dir_name)\n", " make_dir(dir_path, False)\n", " target_name = os.path.join(dir_path, filename)\n", " shutil.copyfile(file_path, target_name)\n", " else:\n", " print(file_path)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Copying files: 7377 files [00:01, 4977.55 files/s]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Note: AWS CLI version 2, the latest major version of the AWS CLI, is now stable and recommended for general use. For more information, see the AWS CLI version 2 installation instructions at: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html\n", "\n", "usage: aws [options]