BLOG

Apache MXNet에서 사전 트레이닝된 모델을 사용해 보세요.
작성일: 2018-05-24

해당 블로그 포스트에서는 Apache MXNet에서 미리 트레이닝된 여러 모델을 사용하는 방법을 보여 드리겠습니다. 왜 여러 모델을 시험해보고 싶을까요? 단지 최고의 정확도를 가진 제품을 선택하는 건 어떨까요? 추후에 블로그 게시물에서 볼 수 있듯이 이러한 모델이 동일한 데이터 세트에서 교육되고 최대 정확도를 위해 최적화 되었더라도 특정 이미지에서 약간 다르게 작동합니다. 또한 예측 속도가 달라질 수 있으며 이는 많은 응용 프로그램에서 중요한 요소입니다. 몇 가지 사전 모델을 시도함으로써 비즈니스 문제를 해결하는 데 적합한 모델을 찾을 수 있습니다.

 

우선 세개의 이미지 구분 모델을 Apache MXNet model zoo.로부터 다운로드 받으세요.

 

 

각 모델에 대해 두 개의 파일을 다운로드 해야 합니다.

 

  • 신경망의 JSON 정의를 포함하는 심볼 파일 : 레이어, 연결, 활성화 함수 등
  • 가중치 파일은 모든 연결 가중치 및 바이어스, AKA 매개 변수에 대한 값을 저장하며, 훈련 단계에서 네트워크에 의해 학습됩니다.

 

# MacOS users can easily install ‘wget’ with Homebrew: ‘brew install wget’

!wget http://data.dmlc.ml/models/imagenet/vgg/vgg16-symbol.json -O vgg16-symbol.json

!wget http://data.dmlc.ml/models/imagenet/vgg/vgg16-0000.params -O vgg16-0000.params

!wget http://data.dmlc.ml/models/imagenet/inception-bn/Inception-BN-symbol.json -O Inception-BN-symbol.json

!wget http://data.dmlc.ml/models/imagenet/inception-bn/Inception-BN-0126.params -O Inception-BN-0000.params

!wget http://data.dmlc.ml/models/imagenet/resnet/152-layers/resnet-152-symbol.json -O resnet-152-symbol.json

!wget http://data.dmlc.ml/models/imagenet/resnet/152-layers/resnet-152-0000.params -O resnet-152-0000.params

!wget http://data.dmlc.ml/models/imagenet/synset.txt -O synset.txt

 

VGG-16 심볼 파일의 첫 번째 줄을 살펴 보겠습니다. 입력 레이어 ( ‘데이터’)의 정의, 첫 번째 회선 레이어의 가중치 및 바이어스를 볼 수 있습니다. 회선 연산 ( ‘conv1_1’)과 정류 선형 유닛 활성화 함수 ( ‘relu1_1’)가 정의됩니다.

 

!head -48 vgg16symbol.json

 

세 가지 모델 모두 1,000 개 범주로 분류된 120 만 개 이상의 개체 및 동물 사진을 포함하는 ImageNet 데이터 세트에서 사전 교육을 받았습니다. synset.txt 파일에서 카테고리를 볼 수 있습니다.

 

!head -10 synset.txt

import mxnet as mx

import numpy as np

import cv2, sys, time   # You can easily install OpenCV with ‘pip install cv2’

from collections import namedtuple

from IPython.core.display import Image, display

 

print(“MXNet version: %s”  % mx.__version__)

 

이제 모델을 로드해 봅시다.

먼저 파일에서 가중치와 모델 설명을 로드 해야합니다. MXNet은 이를 체크 포인트라고 부릅니다. 각 훈련이 끝난 후에 가중치를 저장하는 것이 좋습니다. 교육이 완료되면 교육 로그를 보고 최고의 시점, 즉 가장 높은 유효성 검사 정확도를 갖는 가중치를 선택할 수 있습니다. 그것이 마지막이 아닐 가능성이 매우 높습니다!

 

로드가 완료된 후 심볼 객체와 가중치, AKA 모델 매개 변수를 가져옵니다. 그런 다음 새 모듈을 만들고 이를 입력 심볼에 지정합니다. 모델을 실행할 내용을 선택할 수 있습니다. 기본 동작은 CPU 내용을 사용하는 것입니다. 여기에는 두 가지 이유가 있습니다.

 

  • 우선,이 기능을 사용하면 컴퓨터에 GPU가 장착되어 있지 않아도 노트북을 테스트 할 수 있습니다.
  • 둘째, 단일 이미지를 예측할 예정이며 특정 성능 요구사항이 없습니다. 최상의 처리량으로 대량의 이미지를 예측하려는 프로덕션 응용 프로그램의 경우 GPU가 반드시 필요합니다.

 

그런 다음 입력 된 심볼을 입력 데이터에 바인딩합니다. 이 이름은 네트워크의 입력 레이어에있는 이름이기 때문에 ‘데이터’라고 해야 합니다.(JSON 파일의 처음 몇 줄을 기억하십시오).

 

마지막으로 ‘데이터’의 모양을 1 x 3 x 224 x 224로 정의합니다. 224 x 224 ‘는 이미지 해상도입니다. 모델이 훈련된 방식입니다. 3은 채널 수 : 빨강, 초록, 파랑 ​​(순서대로)입니다. 1은 배치 크기입니다. 한 번에 하나의 이미지를 예측합니다.

 

def loadModel(modelname, gpu=False):

        sym, arg_params, aux_params = mx.model.load_checkpoint(modelname, 0)

        arg_params[‘prob_label’] = mx.nd.array([0])

        arg_params[‘softmax_label’] = mx.nd.array([0])

        if gpu:

            mod = mx.mod.Module(symbol=sym, context=mx.gpu(0))

        else:

            mod = mx.mod.Module(symbol=sym)

        mod.bind(for_training=False, data_shapes=[(‘data’, (1,3,224,224))])

        mod.set_params(arg_params, aux_params)

        return mod

 

또한 synset.txt 파일에 저장된 1,000 개의 카테고리를 로드해야 합니다. 예측 시간에 실제 설명이 필요합니다.

 

def loadCategories():

        synsetfile = open(‘synset.txt’, ‘r’)

        synsets = []

        for l in synsetfile:

                synsets.append(l.rstrip())

        return synsets

   

synsets = loadCategories()

print(synsets[:10])

 

이제 파일에서 이미지를 로드하는 함수를 작성해 보겠습니다. 이 모델은 하나의 224 x 224 이미지의 빨강, 녹색 및 파랑 채널을 보유하고 있는 4 차원 NDArray 모델을 기대합니다. 우리는 OpenCV 라이브러리를 사용하여 입력 이미지에서 이 NDArray를 빌드할 것입니다.

 

다음 단계가 있습니다.

 

  • 이미지 읽기 : 이것은 이미지 높이, 이미지 너비 및 3과 같은 형태로 배열을 반환합니다. 3 개의 채널이 BGR 순서 (파란색, 녹색, 빨간색)로 표시됩니다.
  • 이미지를 RGB (빨강, 초록, 파랑)로 변환하십시오.
  • 이미지를 224 x 224 크기로 조정하십시오.
  • 이미지 높이, 이미지 너비, 3에서 3, 이미지 높이, 이미지 폭에서 배열의 모양을 변경하십시오.
  • 네 번째 차원을 추가하고 NDArray를 작성하십시오.

 

def prepareNDArray(filename):

        img = cv2.imread(filename)

        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        img = cv2.resize(img, (224, 224,))

        img = np.swapaxes(img, 0, 2)

        img = np.swapaxes(img, 1, 2)

        img = img[np.newaxis, :]

        array = mx.nd.array(img)

        print(array.shape)

        return array

 

이제 예측 관련된 정보를 돌봅시다.우리 매개 변수는 이미지, 모델, 범주 목록 및 반환하려는 최상위 범주 수입니다.

 

모듈 객체는 데이터를 일괄적으로  배치에 있는 모델에 공급해야 한다는 것을 기억하십시오. 이를 수행하는 일반적인 방법은 데이터 반복자를 사용하는 것입니다. 여기서는 단일 이미지를 예측하기를 원하므로 데이터 반복기를 사용할 수는 있겠지만 과장될 수도 있습니다. 대신 ‘데이터’ 속성이 참조 될 때 입력 NDArray를 반환하여 가짜 반복자로 작동하는 배치라는 이름의 Tuple을 만들어 보겠습니다.

 

이미지가 전달된 후 모델은 훈련된 1,000 개의 범주에 해당하는 1,000 개의 확률을 갖는 NDArray를 출력합니다. 일괄 처리 크기가 1이므로 NDArray에는 한 줄만 있습니다.

 

이것을 squeeze ()를 사용하여 배열로 바꾸어봅시다. 그런 다음, argsort ()를 사용하여, 우리는 내림차순으로 정렬된 이 확률의 인덱스를 보유하는 두 번째 배열을 생성합니다. 마지막으로 최상위 n 개의 범주와 그 설명을 반환합니다.

 

def predict(filename, model, categories, n):

        array = prepareNDArray(filename)

        Batch = namedtuple(‘Batch’, [‘data’])

        t1 = time.time()

        model.forward(Batch([array]))

        prob = model.get_outputs()[0].asnumpy()

        t2 = time.time()

        print(“Predicted in %.2f microseconds” % (t2-t1))

        prob = np.squeeze(prob)

        sortedprobindex = np.argsort(prob)[::-1]

       

        topn = []

        for i in sortedprobindex[0:n]:

                topn.append((prob[i], categories[i]))

        return topn

 

이제 모든 걸 합쳐봅니다. 3개 모드 로드해 봅시다.

 

gpu = False

vgg16 = loadModel(“vgg16”, gpu)

resnet152 = loadModel(“resnet-152”, gpu)

inceptionv3 = loadModel(“Inception-BN”, gpu)

categories = loadCategories()

 

이미지를 구분하기 전에, ‘.params’파일에서 방금 로드한 VGG-16 매개 변수 중 일부를 자세히 살펴 보겠습니다. 먼저 모든 레이어의 이름을 인쇄해 봅시다.

 

params = vgg16.get_params()

 

layers = []

for layer in params[0].keys():

    layers.append(layer)

   

layers.sort()   

print(layers)

 

각 계층에 대해 우리는 두 가지 구성 요소인 가중치와 바이어스를 봅니다. 가중치를 세면 16 개의 레이어가 있음을 알 수 있습니다. 13 개의 회선 레이어와 3 개의 완전히 연결된 레이어입니다. 이제 이 모델이 VGG-16으로 불리는 이유를 알았습니다.

 

이제 마지막으로 완전히 연결된 레이어의 가중치를 인쇄해 봅시다.

 

print(params[0][‘fc8_weight’])

 

이 행렬의 모양을 알아 차렸나요? 1000 × 4096입니다. 이 레이어에는 1,000 개의 뉴런이 있습니다. 각 뉴런은 특정 범주에 속하는 이미지의 확률을 저장합니다. 각 뉴런은 또한 이전 계층의 모든 4,096 개의 뉴런 ( ‘fc7’)과 완전히 연결됩니다.

OK, 이제 충분합니다! 이 모델을 사용하여 우리 자신의 이미지를 분류합시다.

 

!wget http://jsimon-public.s3.amazonaws.com/violin.jpg -O violin.jpg

image = “violin.jpg”

 

display(Image(filename=image))

 

topn = 5

print(“*** VGG16”)

print(predict(image,vgg16,categories,topn))

print(“*** ResNet-152”)

print(predict(image,resnet152,categories,topn))

print(“*** Inception v3”)

print(predict(image,inceptionv3,categories,topn))

 

이번에는 GPU 내용을 사용하여 다시 해봅시다.

 

gpu = True

vgg16 = loadModel(“vgg16”, gpu)

resnet152 = loadModel(“resnet-152”, gpu)

inceptionv3 = loadModel(“Inception-BN”, gpu)

 

print(“*** VGG16”)

print(predict(image,vgg16,categories,topn))

print(“*** ResNet-152”)

print(predict(image,resnet152,categories,topn))

print(“*** Inception v3”)

print(predict(image,inceptionv3,categories,topn))

 

참고 : GPU 지원에 대한 오류가 발생하면 컴퓨터 또는 인스턴스에 GPU가 없거나 GPU 지원 (USE_CUDA = 1)으로 빌드되지 않은 MXNet 버전을 사용 중입니다.

 

다음은 GPU를 지원하는 소스에서 MXNet을 빌드하는 방법입니다. 또는 미리 빌드된 버전을 설치할 수도 있습니다.

 

성능의 차이는 15 배에서 20 배 사이에서 상당히 두드러집니다. 동시에 여러 이미지를 예측한다면 GPU 아키텍처의 방대한 병렬성으로 인해 그 격차가 더욱 커질 것입니다.

 

이제 자신의 이미지를 시험해 볼 시간입니다. 이 노트북과 같은 폴더에 파일을 복사하고 위의 셀에서 파일 이름을 업데이트 한 다음 predict () 호출을 다시 실행하십시오.

 

사전 트레이닝된 모델들과 함께 즐거운 시간 보내세요!

 

원문 URL: https://aws.amazon.com/ko/blogs/machine-learning/use-pre-trained-models-with-apache-mxnet/

** 메가존 TechBlog는 AWS BLOG 영문 게재글중에서 한국 사용자들에게 유용한 정보 및 콘텐츠를 우선적으로 번역하여 내부 엔지니어 검수를 받아서, 정기적으로 게재하고 있습니다. 추가로 번역및 게재를 희망하는 글에 대해서 관리자에게 메일 또는 SNS페이지에 댓글을 남겨주시면, 우선적으로 번역해서 전달해드리도록 하겠습니다.