[DL4J] CNN

K-036

[목차]

(0) 환경 설정 : DL4J 개발 환경 설정 및 예제 설명

(1) Data Iterator : 사용하고자 하는 데이터를 DL4J 에서 사용가능한 형태로 변환하는 작업 개발 필요

• Canova: The Rosetta Stone of Vectorization (完)

(2) Net : 사용할 신경망의 형태가 어떤 것이 있는지 이해하고 선택, 활용 할 수 있어야 함
• Restricted Boltzmann machines (完)
• Convolutional nets
• Recursive autoencoders (完)
• Recurrent nets: Long Short-Term Memory (LSTM) (including bi-directional LSTMs)
• Deep-belief networks
• Denoising and Stacked Denoising autoencoders
• Deep autoencoders

(3) Activation : Weight + Bias 결과 다음 적용할 함수 결정 (예 : SigMoid : Chap1 에서 설명한 것)

• ReLU
• Leaky ReLU
• Tanh
• Sigmoid
• Hard Tanh
• Softmax
• Identity
• ELU: Exponential Linear Units
• Softsign
• Softplus

(4) Loss&Objective Functions : 일부 데이터를 누락함으로써 더 Robust 한 모델을 만들 수 있다.
• Reconstruction entropy
• Squared loss
• Mean squared error
• Multi-class cross entropy for classification
• Negative log likelihood
• RMSE_XENT

(5) Hyperparameters : 모든 Layer 에 공통적으로 적용되는 파라메터로 숙지 필요

• Dropout (random ommission of feature detectors to prevent overfitting)
• Sparsity (force activations of sparse/rare inputs)
• Adagrad (feature-specific learning-rate optimization)
• L1 and L2 regularization (weight decay)
• Weight transforms (useful for deep autoencoders)
• Probability distribution manipulation for initial weight generation
• Gradient normalization and clipping

(6) Event Listener & Result Anal : 분석 중간 발생하는 이벤트를 받아서 처리 및 결과에 대한 검증 및 비지니스 연동 등

※ DL 쪽은 자료가 거의 없는 편인데 드물게 잘 정리된 글을 찾아서 CNN 에 대해서는 (펌)글을 기반으로 작성함

1. Convolutional Neural Network (CNN): Introduction

DBN이 지금은 practical한 목적으로 거의 사용되지 않는 것과는 대조적으로, 1989년에 제안된 이 모델은 아직까지도 많이 쓰이는 deep network 모델이다.

특히 computer vision에 특화된 이 네트워크는 인간의 시신경 구조를 모방하여 인간이 vision 정보를 처리하는 것을 흉내낸 모형이다.

DBN은 overfitting issue를 initialization으로 해결하였지만, CNN은 overfitting issue를 모델 complexity를 줄이는 것으로 해결한다.

CNN은 convolution layer와 pooling layer라는 두 개의 핵심 구조를 가지고 있는데, 이 구조들이 model parameter 개수를 효율적으로

줄여주어 결론적으로 전체 model complexity가 감소하는 효과를 얻게 된다.

2. Convolutional Neural Network (CNN): Convolution Layer

먼저 convolution layer에 대해 설명해보자. Convolution layer를 설명하기 전에 먼저 convolution operation에 대해 알아보자.

Convolution이란 signal processing 분야에서 아주 많이 사용하는 operation으로, 다음과 같이 표현된다.

s(t)=(x∗w)(t)=∫x(a)w(t−a)da.

예를 들어 이 operation은 주어진 데이터 $x$에 filter $w$를 사용해 데이터를 처리할 때 사용된다.

이 operation을 적용한 간단한 예를 보자.

K-032

이렇듯 convolution은 어떤 filter를 사용하여 주어진 image의 적절한 feature를 뽑아내기 위해 사용했던 operation이다.

이때 $s(t)$를 데이터 $x$의 feature map이라고 부른다. Deep learning이 널리 사용되기 이전에는 다른 머신러닝

framework에 이미지를 input으로 넣고 처리하기 위해서는 먼저 filter를 고르고 그 filter로 image를 convolution하는

preprocessing을 거쳐서 적절한 feature map을 얻어낸 이후에 그것을 machine learning framework의 input으로 넣어

돌리는 방식을 사용했었다. 그렇기 때문에 이런 feature engineering이 전체 performance에 큰 영향을 미치는 경우가

많았다. 어떤 filter를 선택할 것이며, 얼마나 많은 filter를 고를 것인지 등의 영역은 feature engineering의 영역이고,

이론적인 영역이 아니기 때문에 machine learning 분야에서는 큰 관심을 두는 분야는 아니었다. 데이터는 잘

처리되었다고 가정하고 그 데이터를 사용해 어떤 좋은 알고리즘을 개발하느냐가 그 동안 머신러닝 framework들의

아이디어였다면, CNN의 핵심 아이디어는 preprocessing이 실제 performance에 크게 영향을 미치니까,

아예 이 preprocessing을 가장 잘해주는, 가장 좋은 feature map을 뽑아주는 convolution filter를 learning하는

모델을 만들어버리자는 것이다.최대한 작은 complexity를 가지면서 우수한 filter를 표현하기 위한 CNN의 핵심

아이디어는 다음 세 가지이다: sparse interactions (혹은 sparse weight라고도 한다), parameter sharing

(혹은 tied wieght라고도 한다), equivariant representations. 즉, CNN은 layer와 layer간에 모든 connection을

연결하는 대신 일부만 연결하고 (sparse weight), 그리고 그 weight들을 각각 다른 random variable로 취급하여

따로 update하는 대신 특정 weight group들은 weight 값이 항상 같도록 parameter를 share한다 (parameter sharing).

그리고 앞의 아이디어를 잘 활용하여 shift 등의 transform에 대해서 equivariant한 (자세한 내용은 밑에서 설명한다)

representation을 learning하도록 모델을 구성한다.Sparse weight를 사용하게 되면 모든 가능한 connection을

사용하는 것 보다 훨씬 적은 표현형을 learning하게 된다는 단점이 있지만, 반대로 model의 complexity가 낮아진다는

장점이 존재한다. CNN은 vision과 관련된 task를 수행하도록 design된 network라는 것은 이미 언급한바 있다.

이런 vision 데이터를 처리하는 task를 하게 될 경우에는 주어진 input의 dimension에 비해 실제 필요한 feature의

dimension은 극히 적다는 domain knowledge를 우리는 이미 가지고 있다. 즉 input인 이미지의 경우 픽셀 값이 적으면

몇 백에서 많으면 몇 백만에 이를 정도로 dimension이 엄청나게 높지만, 우리가 필요한 ‘feature’는 그 중에서도 극히

일부 영역, 이를테면 edge detection 등의 그에 비해 훨씬 적은 dimension으로 표현 가능하기 때문에 최대한 parameter를

줄여서 더 효율적인 feature map을 뽑아내기 위하여 weight를 sparse하게 사용한다. 이를 그림으로 표현하면 아래와 같다.

K-033

이 그림은 같은 output $s_3$에 영향을 주는 edge들과 input node를 표현한 그림이다. 왼쪽은 가능한 connection이 전부 있는 것이 아니라

그 일부만 존재하고, $s_3$에 영향을 주는 input이 $x_2, x_3, x_4$ 뿐이지만 오른쪽은 모든 가능한 connection이 있어서 model parameter의

개수가 크게 차이나고 모든 input이 $s_3$에 영향을 주는 것을 알 수 있다. 실제 image 데이터를 처리하기에는 왼쪽 모델이 조금 더 나은데

, 그 이유는 한 feature를 결정하기 위해서 모든 image 정보가 필요한 것이 아니라, image의 일부분만 필요하기 때문이다. 예를 들어 내가

face segmentation, 즉 얼굴 사진에서 눈 코 입 등을 찾아내는 task를 수행한다고 하면, 주어진 사진에서 ‘눈’이 어디인지 표현하기 위해서

모든 이미지가 다 필요한 것이 아니라 눈 주변의 local한 데이터만 필요할 것이라고 유추할 수 있다. 오른쪽 그림은 필요하지 않은

배경까지 모두 고려하여 눈에 대한 정보를 찾는 셈이고, 왼쪽 그림은 local한 정보만을 주고 눈에 대한 정보를 처리하게 하는 것이다.

따라서 vision task를 처리하기에는 적절한 sparse weight가 더 효율적인 모델이라는 것을 알 수 있다. 때문에 CNN의 convolution layer는

hidden node 하나가 image의 local한 patch와 연결되어있는 형태로 되어있다. 예를 들어 한 hidden node 마다 image의 3 by 3 patch만을

연결하는 방식이다. 그림으로 표현하면 아래와 같은 식이다.

K-034

여기에서 subsampling은 일단 나중에 설명하도록 하고 (subsampling part가 pooling layer에 해당한다) 가장 왼쪽의 image data의 일부분에

해당하는 patch만 다음 hidden layer의 한 unit에 연결하는 것이다. 이런 식으로 네트워크를 만들게 되면, patch size에 따라 다음

feature map의 size가 결정될 것이다. 예를 들어 100 by 100 이미지에서 5 by 5 patch를 사용해 convolution layer를 구축할 경우,

이 layer의 feature map은 96 by 96이 될 것이다.

CNN은 이런 sparse weight에 parameter sharing을 또 더하여 vision task에 최적화된 network를 learning하게 된다. Parameter를

share하게 되면 그러지 않는 것과 비교하여 보다 적은 parameter만을 가지게 되므로 model의 complexity가 줄어드는 효과가 있을 뿐

아니라, 각각의 patch마다 따로 필터를 learning하는 대신, 모든 patch에 동일한 필터를 적용하도록 강제하는 효과가 있다. CNN은 아래

그림과 같이 각각의 hidden node들이 같은 location에 대해 같은 weight를 가지도록 설정하여 모든 hidden node들이 각각 다른 patch에

대해 같은 filter를 처리하는 것과 같은 형태로 모델을 디자인한다.

K-035

위 그림에서 같은 색으로 칠해진 edge는 서로 같은 weight를 가진다. 위 그림에서 볼 수 있듯, CNN은 fully connected layer를 가지지 않고,

그 sparse한 weight들에서도 서로 weight를 공유하도록 설정되어있다. 그렇지 않은 네트워크와 비교해보면 다음과 같다.

K-036

각각의 그림에서 검은색으로 연결된 edge들은 서로 같은 parameter를 가진다. 즉, 왼쪽은 한 번에 5개의 edge가 같은 weight를 가지지만,

오른쪽은 하나의 parameter로 한 개의 edge만 표현할 수 있다. 이렇게 표현하게 되면 convolution layer operation이 간단한 matrix multiplication으로

주어지게 되어 gradient를 계산하기 한 층 더 수월해진다는 장점도 존재한다. 자세한 내용은 algorithm 쪽에서 다루도록 하자.

마지막으로 equivalent representations는 위와 같은 sparse weight와 tied weight를 어떤 특정한 형태로 효율적으로 배치하게 되었을 때, 주어진

input의 변화에 대해 output이 변화하는 방식이 equivariant해지는 현상을 의미한다 (equivalent가 아니다). 예를 들어 function $f$가 function $g$와

equivariant하다는 의미는, $f(g(x)) = g(f(x))$인 경우를 말한다. 이미지 처리를 예로 들면 $g$는 임의의 linear transform이라고 할 수 있다. Shift, rotate,

scale등의 image에 대한 transform들이 그것인데, 우리는 같은 이미지가 돌아가거나 움직이거나 살짝 scale되더라도 그 이미지가 어떤 이미지인지 잘

판별할 수 있지만, 컴퓨터에게는 그런 transform이 픽셀 값이 완전히 바뀌는 결과를 낳기 때문에 어떤 정보인지 판별하기 어려운 것이다. 그런데 만약

우리가 어떤 transform $g$에 대해 equivariant representation을 만들어내는 network $f$를 만들 수 있다면, input이 shift되거나 rotate되더라도 항상 적절한

representation을 가지도록 할 수 있을 것이다. (실제 CNN은 shift에만 equivariant하다.)

즉, 앞에서 shared parameter가 각각의 patch에 대해 같은 filter를 처리하는 것 처럼 설정하였기 때문에, 만약 image가 shift되더라도 feature map의 형태가

크게 뒤틀리는 것이 아니라, feature map도 image와 함께 shift되는 형태를 보이게 될 것이다.

그런데 실제로는 한 image에 한 개의 filter가 아니라 여러 개의 filter가 필요할 수도 있다. 앞에서 설명한 convolution layer는 한 개의 convolution filter를 표현할

뿐이지만, 실제로는 이런 convolution filter가 한 개가 아니라 여러 개 만든 다음 그 값들을 concate하여 feature map을 표현해야할 수도 있다. 그렇기 때문에

실제로 CNN model은 한 개의 convolution layer가 아니라 아래와 같이 여러 개의 convolution layer가 결합된 꼴을 하고 있다. 참고로 공식적으로는 각각의

layer 혹은 filter를 kernel이라 하고, 그 kernel들이 모여있는 것을 한 layer로 부른다.

K-037

[Sampling 을 더 쉽게 설명할 수 있는 이미지가 있어 첨부]

K-041

3. Convolutional Neural Network (CNN): Pooling Layer

Convolution Layer만 여러 개 연결하여 deep network를 구성하는 것도 가능하지만, 실제로는 더 dimension이 낮은 feature map을 얻기 위하여

subsampling이라는 것을 하게 된다. 앞에서 예로 들었던 것처럼 100 by 100 이미지에 5 by 5 convoltion patch size를 가지는 convolution layer를

연결할 경우 feature map의 size는 96 by 96이 되는데, 사실 이 96 by 96 feature map은 서로 매우 highly correlated 되어있는 값이 것이다.

특히 서로 이웃해있을수록 겹치는 영역이 많기 때문에 거의 비슷한 값을 가질 것이라고 예상할 수 있다. 아래 그림을 보자.

K-034

이미 앞에서 나왔던 그림이지만 설명을 위하여 다시 가져왔다. Pooling layer는 convolution layer의 feature map을 조금 더 줄여주는 역할을 한다

. 전체 feature map을 그대로 들고가는 대신, 예를 들어 96 by 96 image feature map을 2 by 2 patch들로 쪼개는 것이다. 이렇게 할 경우 총 48 by 48 개의

output이 생기게 될텐데, subsampling이라는 것은 각각의 2 by 2 patch는 max, average 등의 operation을 행하는 것을 의미한다. 보통 max operation을

사용하고, 이 경우 간단하게 max pooling을 사용한다 라고 이야기 한다. 가끔 average pooling을 사용하는 경우도 있지만 보통 classification을 위한

모델들은 max pooling을 사용하니 참고하면 좋을 것 같다.

CNN은 이렇게 convolution layer와 pooling layer가 결합된 형태로 deep 하게 구성이 된다. 개인적으로 아래 그림이

CNN의 convolution layer와 max pooling layer를 잘 표현하는 그림이라고 생각한다.

K-039

[Max Pool을 더 간단하게 설명할 수 있는 그림이 있어서 추가 첨부 ]

K-042

4. Convolutional Neural Network (CNN): Backpropagation

CNN의 기본 model은 알았으니 이제 이 network의 parameter를 어떻게 learning해야할지 알아보자. 기본적인 update algorithm은 이전 글에서 설명했던

backpropagation algorithm을 사용한다.

먼저 간단한 max pooling layer 부터 살펴보자. Pooling layer는 아래 p by q size의 patch 중에서 max 값을 선택하는 layer이다. 때문에 이를 수식으로 표현해보면

다음과 같이 쓸 수 있다. $(x,y)$는 pooling layer feature map의 x,y좌표를 나타내고, ($h_l$은 l번째 layer의 hidden variable들)

hl+1(x,y)=maxa−p≤a≤a+p,b−q≤b≤b+q(hl(x+a,y+b))

Parameter는 없으므로 $\frac{\partial h_{l+1} }{\partial h_{l}}$만 계산하면 된다. 이 경우 주어진 $(x,y)$가 만약 max pooling을 통해 선택된 값이라면 값을

그대로 passing하고, 만약 선택되지 않은 값이라면 0을 할당하면 된다.

Convolution layer는 operation이 꽤 복잡한데, 먼저 아래 그림을 보자.

K-040

이때 l+1 번째 layer 중에서 i 번째 convolution filter의 x,y 좌표 값은 아래와 같이 표현된다. 아래 conv layer의 kernel은 m 개, 위 conv layer의 kernel은 n개 라고 해보자.

hl+1(i,x,y)=∑j=1m∑a=1p∑b=1qhl(j,x+a,y+b)∗w(i,n;a,b)

값이 좀 많이 복잡하긴 한데, 미분 값을 계산해보면, parameter의 gradient는 $\frac{E}{\partial w} = \sum_x \sum_y \frac{E}{h_{l+1} } (x,y) h_l (x,y)$와 같이 바로 전

layer의 pixel값에 대해 gradient 값을 곱한 것을 전부 더한 형태로 구할 수 있고, $\frac{E}{\partial h_l} $은 weight w로 이전 layer의 gradient를 convolution한 것들을 전부

더한 것과 같은 결과를 얻게 된다.

CNN의 모든 operation들은 단순 연산이 많고 branch가 없기 때문에 core가 많고, 모든 core가 하나의 operation pointer를 공유하는 GPU를 사용해 효율적으로 parallization하기

좋다. 보통 CNN은 caffe라는 C++ library를 사용해 learning하기 때문에 위에서 언급한 알고리즘을 실제로 구현할 일은 많지 않을 것 같다.

5. Convolutional Neural Network (CNN) DL4J Sample Code

ConvolutionLayer -> SubSamplingLayer -> DenseLayer -> OutputLayer 순서로 Layer 를 구성한 것을 볼수 있다. 왜 이렇게 Layer 를 구성하였는지는 위와 같은 Smapling 과 Pooling

과정을 수행하기 위해서이다. 다른 Layer 간의 통신을 위해서는 전처리를 지정하는 것이 표준이지만, 대부분의 경우 자동으로 전처리를 해준다고 한다.

결국 이미지와 동일한 사이즈의 특징점은 1, 아닌것은 0과 같은 형태의 OutPut Matrix 가 구성될 것 같다.

public class LenetMnistExample {
    private static final Logger log = LoggerFactory.getLogger(LenetMnistExample.class);

    public static void main(String[] args) throws Exception {
        int nChannels = 1;
        int outputNum = 10;
        int batchSize = 1000;
        int nEpochs = 10;
        int iterations = 1;
        int seed = 123;

        log.info("Load data....");
        DataSetIterator mnistTrain = new MnistDataSetIterator(batchSize,true,12345);
        DataSetIterator mnistTest = new MnistDataSetIterator(batchSize,false,12345);

        log.info("Build model....");
        MultiLayerConfiguration.Builder builder = new NeuralNetConfiguration.Builder()
                .seed(seed)
                .iterations(iterations)
                .regularization(true).l2(0.0005)
                .learningRate(0.01)
                .weightInit(WeightInit.XAVIER)
                .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
                .updater(Updater.NESTEROVS).momentum(0.9)
                .list(4)
                .layer(0, new ConvolutionLayer.Builder(5, 5)
                        .nIn(nChannels)
                        .stride(1, 1)
                        .nOut(20).dropOut(0.5)
                        .activation("relu")
                        .build())
                .layer(1, new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX)
                        .kernelSize(2,2)
                        .stride(2,2)
                        .build())
                .layer(2, new DenseLayer.Builder().activation("relu")
                        .nOut(500).build())
                .layer(3, new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
                        .nOut(outputNum)
                        .activation("softmax")
                        .build())
                .backprop(true).pretrain(false);
        new ConvolutionLayerSetup(builder,28,28,1);

        MultiLayerConfiguration conf = builder.build();
        MultiLayerNetwork model = new MultiLayerNetwork(conf);
        model.init();


        log.info("Train model....");
        model.setListeners(new ScoreIterationListener(1));
        for( int i=0; i<nEpochs; i++ ) {
            model.fit(mnistTrain);
            log.info("*** Completed epoch {} ***", i);

            log.info("Evaluate model....");
            Evaluation eval = new Evaluation(outputNum);
            while(mnistTest.hasNext()){
                DataSet ds = mnistTest.next();
                INDArray output = model.output(ds.getFeatureMatrix());
                eval.eval(ds.getLabels(), output);
            }
            log.info(eval.stats());
            mnistTest.reset();
        }
        log.info("****************Example finished********************");
    }
}

 

1 thought on “[DL4J] CNN

  1. Greetings! I am similarly a guide. Thank you for creating such an worthwhile message. Being from Coalburg , has equipped me with a great idea on what is needed to fly to Springville. All Of Us will continue to come and pay a visit to your blog to better understand where to go once we get to suwanee. Make sure you keep on writing and offer us your thinking on Walla Walla University (WA). Hope to see you later on at the future job fair at FedEx Corporation. Bye.

Leave a Reply

Your email address will not be published. Required fields are marked *