관련 글

https://sacko.tistory.com/19

 

문과생도 이해하는 딥러닝 (3) - 오차 역전파, 경사하강법

2017/09/27 - 문과생도 이해하는 딥러닝 (1) - 퍼셉트론 Perceptron 2017/10/18 - 문과생도 이해하는 딥러닝 (2) - 신경망 Neural Network 이전 시간까지 신경망이 무엇인지 어떻게 생긴 것인지 작동원리 등을 살..

sacko.tistory.com

http://jaejunyoo.blogspot.com/2017/01/backpropagation.html

 

Backpropagation 설명 예제와 함께 완전히 이해하기

쉽게 설명하는 기계학습(machine learning) 개념, 역전파(backpropagation) 예제와 함께 완전히 이해하기

jaejunyoo.blogspot.com

https://www.linkedin.com/pulse/gradient-descent-backpropagation-ken-chen

 

Gradient Descent and Backpropagation

In previous articles, I have referred to the concepts of gradient descent and backpropagation for many times. But I did not give the details and implementations of them (the truth is, I didn't know these either.

www.linkedin.com

 

As we know, the loss function is a function of weights and biases. So, its gradient can be calculated by taking its derivative with respect to the weights and the biases, so that we know how much each variable contributes to the total error. However, since the relationship between the weights and the biases in the different layers is sort of iterated and accumulated, it is not an easy task to calculate the gradients with respect to them. And this is where backpropagation comes to the rescue!

If I was asked to describe backpropagation algorithm in one sentence, it would be: propagating the total error backward through the connections in the network layer by layer, calculate the contribution (gradient) of each weight and bias to the total error in every layer, then use gradient descent algorithm to optimize the weights and biases, and eventually minimize the total error of the neural network.

'딥러닝 > 이론 관련' 카테고리의 다른 글

딥러닝 파라미터 최적화 용어 정리  (0) 2018.05.14

깔끔하게 파이토치 모델을 C++ 완성된 애플리케이션에 넣어 사용하는 방법을 정리하는 글이다

개발 환경은 다음과 같다

OS: Ubuntu 16.04

Pytorch 1.0

CMAKE 3.13.3

libtorch cpu버전

C++편집기: Dev C++

우선 새 폴더를 만들어 CMakeLists.txt와 Cpp 소스코드를 만든다


CMakeLists.txt:

cmake_minimum_required(VERSION 3.0 FATAL_ERROR)

project(custom_ops)


find_package(Torch REQUIRED)


add_executable(example-app example-app.cpp)

target_link_libraries(example-app "${TORCH_LIBRARIES}")

set_property(TARGET example-app PROPERTY CXX_STANDARD 11)



C++ 코드:


C++ 코드는, 실행시 모델 경로를 같이 전달하면 확인 후 load하며 잘 load가 되었다면 cout을 통해 ok를 출력하는 코드이다

두 파일이 있는 폴더에 새폴더를 만들어 build로 이름짓고 폴더로 들어가 터미널을 실행한다


그리고 CMAKE를 만드는 명령어들을 실행한다


cmake -S '소스코드있는 경로' -DCMAKE_PREFIX_PATH='libtorch 경로'

make

순서대로 입력 후 빌드가 성공적으로 끝나면 ./example-app '모델경로' 명령어로 완성된 애플리케이션을 실행하낟

ok가 출력되면 성공



이제 실제 load한 모델에 인풋값을 통과시켜보는 작업을 한다

C++ 코드를 아래와 같이 수정한다

이때 자신이 사용하는 모델의 인풋 shape에 맞게 inputs을 생성해준다

터미널로 돌아가 

make

./example-app '모델경로'

순서대로 명령어를 실행하면 된다 

그 결과 아래와 같은 결과를 얻었다. 


드디어 cmake 파일을 빌드하는데 성공했다

이거땜에 얼마나 많은 시간을 날리고 낭비했는지 ..ㅂㄷㅂㄷ


결론은 파이토치 튜토리얼에 나오것을 그대로 따라하면 안된다


일단 cmake가 버전업되면서 명령어가 바뀌었다

또한, libtorch를 cuda버전이 아닌 cpu버전으로 하니까 성공했다


빌드명령어는 cmake -S '소스코드있는 경로' -DCMAKE_PREFIX_PATH='cpu버전 libtorch폴더의 경로'


이렇게하면 빌드가 되고

이후에 make 명령어를 입력하면 exe파일을 만들어준다


아 그리고 그 사이 우분투로 OS를 바꿔 환경은 16.04, python 3.6, pytorch 1.0, cuda 9.0, libcudnn 7.4.2.24-1 이 되었다

(단 libtorch는 언급한대로 cpu 버전이다)

터미널에 출력 결과는 다음과 같다


***@******:~/example-app/build$ cmake -S ~/example-app -DCMAKE_PREFIX_PATH=~/libtorch-cpu/libtorch

-- The C compiler identification is GNU 5.4.0

-- The CXX compiler identification is GNU 5.4.0

-- Check for working C compiler: /usr/bin/cc

-- Check for working C compiler: /usr/bin/cc -- works

-- Detecting C compiler ABI info

-- Detecting C compiler ABI info - done

-- Detecting C compile features

-- Detecting C compile features - done

-- Check for working CXX compiler: /usr/bin/c++

-- Check for working CXX compiler: /usr/bin/c++ -- works

-- Detecting CXX compiler ABI info

-- Detecting CXX compiler ABI info - done

-- Detecting CXX compile features

-- Detecting CXX compile features - done

-- Looking for pthread.h

-- Looking for pthread.h - found

-- Looking for pthread_create

-- Looking for pthread_create - not found

-- Looking for pthread_create in pthreads

-- Looking for pthread_create in pthreads - not found

-- Looking for pthread_create in pthread

-- Looking for pthread_create in pthread - found

-- Found Threads: TRUE  

-- Found torch: /home/lab/libtorch-cpu/libtorch/lib/libtorch.so  

-- Configuring done

-- Generating done

-- Build files have been written to: /home/lab/example-app/build

***@******:~/example-app/build$ make

Scanning dependencies of target example-app

[ 50%] Building CXX object CMakeFiles/example-app.dir/example-app.cpp.o

[100%] Linking CXX executable example-app

[100%] Built target example-app



우선 C++(VS)에서 LibTorch를 쓰기위해 몇가지 설치,설정을 해야한다


참고링크: https://zhuanlan.zhihu.com/p/52806730


VS2017이 필요하고 Cmake는 3.0 이상의 버전으로 설치한다


설치는 https://cmake.org/download/ 에서 

Windows win64-x64 ZIPcmake-3.13.2-win64-x64.zip

를 다운받아서 설치하였다.

다운받아서 압축 푼 뒤 bin폴더 경로를 시스템 환경 변수에 설치하면 된다

제대로 설치되었는지 확인은 cmd에서 cmake --version 명령어를 입력해보면 된다. 아래와 같이 잘 설치된것을 확인하면 끝


C:\Users\10127>cmake --version

cmake version 3.13.2


또한, 현재 타입 변경에 대해 narrow conversion 문제가 있다 아래 관련 링크

https://github.com/pytorch/pytorch/pull/15333



공식홈페이지 튜토리얼 정리글입니다

https://pytorch.org/tutorials/advanced/cpp_export.html



STEP 1: 파이토치 모델을 Torch script로 컨버팅

 Torch Script 을 이용해서 파이토치모델을 C++에서 불러올 수 있는데 여기엔 두가지 방법이 있습니다.


첫번째는 tracing 이라고 불리는 것으로 예제 인풋을 이용해서 그 인풋이 모델을 통과하면서 변화과정을 기록하는 것으로 사용 방법(control flow)이 제한적인 모델들에 적합한 방법

두번째는 모델에 소위 '주석'을 달아 Torch scrip 컴파일러가 직접적으로 파싱하고 컴파일할 수 있도록 하는 방법으로 위 Torch Script 링크를 누르면 자세한 방법이 나옴



Converting to Torch Script via Tracing

torch.jit.trace 함수에 모델 인스턴스와 예제 인풋값을 전달해주면 됨. 이러면 torch.jit.ScriptModule 오브젝트가 생성되며 모듈의 forward 메소드를 추적함

import torch
import torchvision

# An instance of your model.
model = torchvision.models.resnet18()

# An example input you would normally provide to your model's forward() method.
example = torch.rand(1, 3, 224, 224)

# Use torch.jit.trace to generate a torch.jit.ScriptModule via tracing.
traced_script_module = torch.jit.trace(model, example)

trace된 ScriptModule은 이제 일반적인 파이토치 모듈로 사용가능

In[1]: output = traced_script_module(torch.ones(1, 3, 224, 224))
In[2]: output[0, :5]
Out[2]: tensor([-0.2698, -0.0381,  0.4023, -0.3010, -0.0448], grad_fn=<SliceBackward>)


Converting to Torch Script via Annotation

만약 모델이 특별한 형태나 흐름을 갖고있다면, Torch Script에 직접 기록하고 주석 달기를 원할 수 있다. 예를들어 모델이 아래와 같은 구조라면

import torch

class MyModule(torch.nn.Module):
    def __init__(self, N, M):
        super(MyModule, self).__init__()
        self.weight = torch.nn.Parameter(torch.rand(N, M))

    def forward(self, input):
        if input.sum() > 0:
          output = self.weight.mv(input)
        else:
          output = self.weight + input
        return output

이 모듈의 forward 함수는 인풋에 따라 다른 흐름을 보이기 때문에 tracing에 알맞지 않음. 따라서 torch.jit.ScriptModule 에 부분집합을 만들고 @torch.jit.script_method 주석을 forward 메소드에 추가하는 방법을 ScriptModule로 컨버팅함

import torch

class MyModule(torch.jit.ScriptModule):
    def __init__(self, N, M):
        super(MyModule, self).__init__()
        self.weight = torch.nn.Parameter(torch.rand(N, M))

    @torch.jit.script_method
    def forward(self, input):
        if input.sum() > 0:
          output = self.weight.mv(input)
        else:
          output = self.weight + input
        return output

my_script_module = MyModule()

MyModule 오브젝트를 만들면 바로 ScriptModule 인스턴스를 만들어줌 




STEP 2: Script Module을 파일로 쓰기


아래의 명령어를 이용해 파일로 저장하면, 파이썬에 의존하지안고 C++에서 모델을 사용 가능함

traced_script_module.save("model.pt")

파이썬파트 여기까지가 끝


STEP 3: C++에서 Script Module 불러오기


LibTorch라는 파이토치 C++ API를 이용해서 불러와야 함. CMake와 LibTorch를 이용해서 모델을 불러와 이용하는 간단한 예제를 만들것


모델 불러오는 코드

#include <torch/script.h> // One-stop header.

#include <iostream>
#include <memory>

int main(int argc, const char* argv[]) {
  if (argc != 2) {
    std::cerr << "usage: example-app <path-to-exported-script-module>\n";
    return -1;
  }

  // Deserialize the ScriptModule from a file using torch::jit::load().
  std::shared_ptr<torch::jit::script::Module> module = torch::jit::load(argv[1]);

  assert(module != nullptr);
  std::cout << "ok\n";
}

파일 불러와 sharedpoint로 받고(C++에서의 torch.jit.ScriptModule) null 포인터인지 확인하는 코드임



Depending on LibTorch and Building the Application

위 코드가 example-app.cpp라는 스크립트에 적혀있다고 할때 CMakeLists.txt는 다음과 같음

cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(custom_ops)

find_package(Torch REQUIRED)

add_executable(example-app example-app.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}")
set_property(TARGET example-app PROPERTY CXX_STANDARD 11)

마지막으로 필요한것은 LibTorch distribution이다.  download page 에서 최신버전 다운 가능함

받아서 압축 풀면 아래와 같음

libtorch/
  bin/
  include/
  lib/
  share/

lib/ 폴더는 공유 라이브러리 포함

include/ 폴더는 헤더파일 포함

share/ 폴더는 위에 find_package 명령어를 실행하기위한 필요한 CMake configuration을 포함


예제 경로가 다음과 같을때:

example-app/
  CMakeLists.txt
  example-app.cpp

다음의 명령어들을 실행하여 애플리케이션을 빌드함

mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch ..
make

/path/to/libtorch 는 LibTorch distribution을 압축 푼 풀 경로여야함. 만약 잘 됐다면 아래와 같아야함

root@4b5a67132e81:/example-app# mkdir build
root@4b5a67132e81:/example-app# cd build
root@4b5a67132e81:/example-app/build# cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /example-app/build
root@4b5a67132e81:/example-app/build# make
Scanning dependencies of target example-app
[ 50%] Building CXX object CMakeFiles/example-app.dir/example-app.cpp.o
[100%] Linking CXX executable example-app
[100%] Built target example-app

ResNet18모델을 성공적으로 만들었다면 아래와 같은 메세지가 뜸

root@4b5a67132e81:/example-app/build# ./example-app model.pt
ok


STEP 4: Executing the script module in C++

명령어 조금만 넣으면 바로 실행 가능 아래의 코드를 main() 함수에 추가

// Create a vector of inputs.
std::vector<torch::jit::IValue> inputs;
inputs.push_back(torch::ones({1, 3, 224, 224}));

// Execute the model and turn its output into a tensor.
at::Tensor output = module->forward(inputs).toTensor();

std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';

모델의 인풋과 아웃풋은 IValue 타입이다 이후 forward 를 실행하고 텐서로 변환함

마지막줄은, 아웃풋의 처음 5개만 출력하는 것







관련 링크

https://www.degruyter.com/downloadpdf/j/itms.2017.20.issue-1/itms-2017-0003/itms-2017-0003.pdf

https://stats.stackexchange.com/questions/164876/tradeoff-batch-size-vs-number-of-iterations-to-train-a-neural-network

http://forums.fast.ai/t/batch-size-effect-on-validation-accuracy/413

https://www.quora.com/Intuitively-how-does-mini-batch-size-affect-the-performance-of-stochastic-gradient-descent

http://goodtogreate.tistory.com/entry/Batch-%ED%81%AC%EA%B8%B0%EC%9D%98-%EA%B2%B0%EC%A0%95-%EB%B0%A9%EB%B2%95

https://blog.lunit.io/2018/08/03/batch-size-in-deep-learning/



1. "Impact of Training Set Batch Size on the Performance of Convolutional Neural Networks for Diverse Datasets" 에 따르면(VIII 결론 부분)


CNN의 퍼포먼스를 늘리는 문제(image recognition의 정확도)에 있어서 CNN 파라미터 중 배치사이즈는 치명적인(crucial) 영향력을 갖고 있다


이 값이 높을수록 인식 정확도가 높아진다. 반면 계산 양이 많아진다


대략 200부터 다양한 크기의 배치사이즈가 적절하다고 말하고있다.



2. From Nitish Shirish Keskar, Dheevatsa Mudigere, Jorge Nocedal, Mikhail Smelyanskiy, Ping Tak Peter Tang. On Large-Batch Training for Deep Learning: Generalization Gap and Sharp Minima. https://arxiv.org/abs/1609.04836  에 내용


large-batch 에서 generalization이 부족한데 그 이유는 sharp minimizers로 수렴하는 경향 때문이라고 한다.


이런 minimizer들은 


2f(x)


의 eigenvalue가 큰 양수인 특징이 있다고 한다. 반면 flat minimizer들은 그게 작은 양수 값들임


그들의 관찰에 의하면 large-batch의 딥러닝들은 주로 sharp minima에 빠지는 경우가 많당



그리고 Ian Goodfellow가 '왜 그래디언트 계산할때 모든 트레이닝셋을 쓰지않는지 즉 미니배치를 왜쓰는지'에 대해 답변하길


러닝레이트(learning rate)는 코스트 함수(cost function)가 얼마나 굽어져있는지(curved) 등에 의해 제한된다. gradient descent가 코스트 함수의 linear approximation을 만든 것을 생각할때 기울기를 보고 아래쪽으로 움직이지. 만약에 코스트 함수가 상당히(highly) non-linear하면(즉 highly curved) 그 근사치(approximation)이 충분히 좋지 않아 lr이 작아야 안전하다.


미니배치에 m개를 넣으면 시공간 복잡도가 각각 O(m)이다. 하지만 O(sqrt(m))으로 줄일수있다(이부분 의역)

다른말로, 미니배치에 더 많은 예시를 넣게 되면 약해진 미미한(diminishing marginal) 결과를 얻는다


또한 전체 트레이닝 셋을 다 쓴다고해서 정확한 기울기값을 알수있는게 아니다. 데이터 분포에 영향받기 때문에 기대값을 갖게될수밖에 없다.




그밖에 

http://goodtogreate.tistory.com/entry/Batch-%ED%81%AC%EA%B8%B0%EC%9D%98-%EA%B2%B0%EC%A0%95-%EB%B0%A9%EB%B2%95

https://blog.lunit.io/2018/08/03/batch-size-in-deep-learning/


위 두 글에서도 잘 정리가 되어있는데 한국어이니 여기에 정리는 안하고 나중에 필요하면 다시 읽어볼것이다



근데 결론이 좀 어렵다. 

패키지 설치명령어모음.txt

OS: windows 10 x64

python: 3.6.x

cuda: 9.1


이 글에서 복사하면 출처가 남으니 첨부파일 다운받아 사용하시면됩니다



conda create -n pytorch python=3.6

conda install pytorch cuda91 -c pytorch



conda install -c anaconda cython



"pip install torchvision"


pip install numpy - 있다고나옴

pip install matplotlib


pip install numpy-1.14.3+mkl-cp36-cp36m-win_amd64.whl

pip install scipy-1.1.0-cp36-cp36m-win_amd64.whl


conda install -c conda-forge opencv

참고: http://busterworld.tistory.com/59?category=663469



OS: windows 10 x64

python: 3.6.x

cuda: 9.1


Anaconda environment에서 설치할때


conda install pytorch cuda91 -c pytorch 
pip3 install torchvision


이렇게 명령어를 입력하라고 나오는데 혹시 토치비전에서 에러나는 경우


pip install torchvision 으로 입력하면 잘된당

코드:



결과:



설명(https://pytorch.org/docs/stable/_modules/torch/nn/functional.html)


텐서의 각 행이나 열을 정규화할 수 있다. 위 코드에서 a의 경우 3*4 텐서인데 


dim=0을 파라미터로 할 경우 첫번째 dimension 즉 column을 정규화하고


dim=1으로 할 경우 두번째 dimension 즉 row를 정규화 한다

'딥러닝 > 백과사전' 카테고리의 다른 글

백과사전 카테고리  (0) 2018.06.20

연구하면서 언제든 다시 필요할만한 각종 스킬들,정보들 정리해놓는 곳

'딥러닝 > 백과사전' 카테고리의 다른 글

텐서 정규화(normalize)하기  (0) 2018.06.20

+ Recent posts