import numpy as np
import matplotlib.pyplot as plt
def step_function1(x):
if x <= 0:
return 0
else x > 0:
return 1
def step_function2(x):
y = x > 0
return y.astype(np.int)
임계치를 기준으로 출력해주는 함수이며, Perceptron algorithm에서 Activation function으로 사용한다.
다중 분류 문제 같은 문제에서 다중 출력이 불가하다.
신경 세포의 전달 방법을 묘사한 기법이며, 출력되는 결과값이 갖는 정보가 희석된다는 단점이 존재한다.
Linear Function
$$ h(x) = cx \quad(c: 상수) $$
Linear Function
def Linearfunction(x, c):
return c*x
장점
다중 출력이 가능하다.
단점
역전파 (Backpropagation) 사용이 불가하다.
역전파는 활성화 함수를 미분하여 이것을 이용해서 손실값을 줄이기 위한 과정이다. 선형함수의 미분값은 상수이기에 입력값과 상관없는 결과를 얻는다.
은닉층을 무시하고 얻을 수 있는 정보를 제한한다.
활성화 함수를 여러 층을 통하여 얻고자 하는 것은 필요한 정보를 얻기 위함이다. 선형 함수를 여러번 사용하는 것은 마지막에 선형 함수를 한번 쓰는것과 같다. \( h(x) = cx \) 일 때, \( h(h(h(x))) = c'x \) 이기 때문이다.
실제로, 양자화 과정은 \( [\alpha, \beta]\)의 범위를 벗어난 \(x\) 를 가질 가능성이 있으며, 양자화 된 값 \(x_q\) 또한 \( [\alpha, \beta]\)의 범위를 벗어난다.
Integer type이 INTb 및 \( (alpha_q, \beta_q) = (-2^{b-1}, 2^{b-1} -1) \) 또는 unsigned UINTb \( (\alpha_q, \beta_q) = (0,2^b -1)\) 인 경우 유형 정밀도가 범위를 벗어난 값을 클리핑 한다.
Layer fusions : 레이어들을 하나로 묶어주는 단계 :Conv-BatchNorm-ReLU 가 가장 많이 사용되고 있는 layer fusions 이다.
Formula Definition : 양자화를 할 때 사용하는 수식을 정의 : Floating point type ☞ Integer point type (Float32 to Int8) , Quantization : Integer point type ☞ Floating point type (Int8 to Float32) , Dequantization
HW Deployment : Depending on the hardware (Calibration)
Dataset Calibration : 가중치를 변경하기 위한 파라미터를 데이터셋을 이용하여 계산한다.
Weight Conversion : 가중치를 Floating point type에서 Integer point type으로 변환한다.
Dequantization : 추론을 통하여 얻은 결과값을 역 양자화를 통해서 다시 Floating point type으로 변경함.
Layer fusions
JINSOL KIM blog 참조 https://gaussian37.github.io/
빨간색은 첫번째 Layer , 파란색은 두번째 Layer를 뜻한다.
첫 줄은 각각 떨어져 있는 Layer들은 Conv2D, BatchNorm, ReLU 3항목 각각 Quantization 적용을 의미한다.
둘째 줄은 Conv2D-BatchNorm-ReLU 한꺼번에 Quantization 적용을 의미한다.
모든 Layer에 Quantization을 적용하지 않는 이유
양자화 횟수를 감소 시키면, 추론 시간과 정밀도와 재현율을 개선할 수 있다.
횟수를 대폭 줄이면 양자화 목적이 사라질 수 있기에 어떤 부분을 Layer Fusions을 할 지를 연구해야 한다.
신경망 정수형 양자화 종류
신경망 양자화에는 3가지 종류가 있다.
Integer Quantization
Dynamic Quantization
Static Quantization
Static Quantization 과 Quantization aware training은 위 항목 중 가장 빠르기 때문에 가장 흔하게 볼 수 있다.
Quantization Modes
Data Requirements
Inference Latency
Inference Accuracy Loss
Dynamic Quantization
None
Usually Faster
Smallest
Static Quantization
Unlabled
Fastest
Smaller
Quantization Aware Training
Labeled
Fastest
Smallest
출처 : Lei Mao blog
Dynamic Quantization
Dynamic Quantization을 사용하는 신경망 추론에서는 최대한 많은 integer ops를 사용한다.
가중치는 런타임 이전에 정수로 양자화 되었다.
Output or Activation Tensor : 부동소수점 텐서 :: Scales 과 Zero points 를 모르기 때문
부동소수점 텐서를 구하면 /( (\alpha, \beta)\)를 찾을 수 있다.
tensor의 경우 Scale과 zero point를 계산하고 런타임 동안 부동소수점 텐서를 동적 정수 텐서로 양자화 한다.
예를 들면, Matrix Multiplication in Dynamic Quantization 의 경우 \(X_q\)를 이용하여 \(Y_{q,i,j}\) 대신 부동 소수점인 \(Y_{i,j}\)를 계산한다.
shape : 각 차원의 크기 (h, w) Gray scale or (h, w, 3) Color → (h,w,n) : n 값이 2이면 graysclae , 3이면 color 라고 생각해도 문제 없다.
size : 전체 원소 개수
dtype : 원소의 데이터 타입. 영상 데이터는 unit8
OpenCV 영상 데이터 자료형과 Numpy 자료형
OpenCV 자료형
Numpy 자료형
구분
cv2.CV_8U
numpy.uint8
8비트 부호없는 정수
cv2.CV_8S
numpy.int8
8비트 부호있는 정수
cv2.CV_16U
numpy.uint16
16비트 부호없는 정수
cv2.CV_16S
numpy.int816
16비트 부호있는 정수
cv2.CV_32S
numpy.int32
32비트 부호있는 정수
cv2.CV_32F
numpy.float32
32비트 부동소수형
cv2.CV_64F
numpy.float64
64비트 부동소수형
cv2.CV_16F
numpy.float16
16비트 부동소수형
그레이스케일 영상 : cv2.CV_8UC1 → numpy.uint8, shape = (h, w)
컬러 영상 : cv2.CV_8UC3 → numpy.uint8, shape = (h, w, 3)
영상의 속성 참조 예제 코드
img1 = cv2.imread('cat.bmp', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('cat.bmp', cv2.IMREAD_COLOR)
print('type(img1):', type(img1)) # type(img1): <class 'numpy.ndarray'>
print('img1.shape:', img1.shape) # img1.shape: (480, 640)
print('img2.shape:', img2.shape) # img2.shape: (480, 640, 3)
print('img2.dtype:', img2.dtype) # img2.dtype: uint8
h, w = img2.shape[:2] # h: 480, w: 640
print('img2 size: {} x {}'.format(w, h))
if len(img1.shape) == 2:
print('img1 is a grayscale image')
elif len(img1.shape) == 3:
print('img1 is a truecolor image')
img1 = cv2.imread('cat.bmp', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('cat.bmp', cv2.IMREAD_COLOR)
for y in range(h):
for x in range(w):
img1[y, x] = 255
img2[y, x] = [0, 0, 255] #for문은 절대 사용 금지
# img1[:,:] = 255
# img2[:,:] = (0, 0, 255)
Rich feature hierarchies for accurate object detection and semantic segmentation
R-CNN : Object detection algorithm
입력 이미지에 Selective Search 알고리즘을 적용하여 박스 추출한다. ( = 2,000 ea)
모든 박스를 227 x 227 크기로 리사이즈 한다.
미리 학습시킨 데이터를 (Image Net) 통하여 CNN을 통과시켜 4096 특징 벡터를 추출한다.
추출된 벡터로 각각의 클래스마다 학습시켜놓은 SVM Classifier를 통과 시킨다.
Bounding box regression을 적용하여 Box 위치를 조정한다.
ImageNet : 대규모(large-scale) 데이터 셋
Selective serach algorithm
주변 픽셀간 유사도를 기준으로 오브젝트가 있을 법한 영역만 찾는 방법이다. ( = region proposal)
Region proposal
주어진 이미지에서 물체가 있을법한 위치를 찾는 것.
Selective search는 주변 픽셀간의 유사도를 기준으로 세그멘테이션을 생성하고, 이를 기준으로 물체가 있을법한 Box를 추론한다.
Feature extraction
미리 ImageNet으로 학습된 CNN을 가져와서 Object detection 용 데이터셋으로 Fine tuning 한 뒤 Selective search 결과로 뽑힌 이미지들로부터 특징 벡터를 추출한다.
Fine tuning : CNN 층에서 추출된 벡터로 SVM 분류 학습을 시켜서 얻은 mAP 을 비교하는 것
mAP (mean average precision)
합성곱 신경망의 모델 성능 평가를 할 때 mAP을 이용한다.
Precision-recall 곡선과 Average Precision은 CV에서 Object dection 알고리즘 성능 평가를 위해 사용.
1. 2개의 알고리즘이 존재한다고 가정한다. 2. 첫번째 알고리즘은 사람 인식 검출율이 99% 이지만, 한장당 10건 정도의 오검출이 발생한다. 3. 두번째 알고리즘은 사람 인식 검출율이 50% 이지만, 오검출이 미발생한다. → 성능 평가를 위해서는 검출율과 정확도를 동시에 고려해야 한다.
Classification
CNN을 통해 추출한 벡터를 가지고 각각의 클래스를 SVM Classifier 학습.
주어진 벡터를 놓고 해당 물체가 맞는지 아닌지를 구분하는 Classifier 모델을 학습시키는 것.
이미 학습된 CNN Classifier을 두고 왜 SVM을 별도로 학습 시킬까?
CNN Classifier를 쓰는 것이 SVM을 사용할 때보다 mAP 성능이 4%정도 낮아진다. 이것은 아마도 fine tuning 과정에서 물체의 위치 정보가 유실되고 무작위로 추출된 샘플을 학습하여 발생한것으로 보인다. (일부 저자들의 의견) → SVM을 붙여서 학습시키는 기법은 현재 사용되지 않음.
Bounding box regression
물체 위치를 찾고, 물체 종류를 판별할 수 있는 Classification 모델을 학습 시켜서 찾아낸 박스 위치를 교정해줘서 성능을 끌어올리게 하는 행위이다.
Box 표기법
$$ P^i=(P^i_x,P^i_y,P^i_w,P^i_h) $$
Ground Truth에 해당하는 Box 표기법
$$ G = (G_x,G_y,G_w,G_h) $$
-. x, y는 점이기 때문에 이미지의 크기에 상관없이 위치만 이동시켜주면 된다.
-. 너비와 높이는 이미지의 크기에 비례하여 조정해야 함.
-. 위 두가지 특성을 반영하여 P를 이동시키는 함수의 식을 작성하면 아래와 같다.
$$ G_x = P_wdx(P)+Px $$
$$ G_y = P_hdy(P)+Py $$
$$ G_w = P_wexp(dw(P) $$
$$ G_h=P_hexp(dh(P)) $$
우리가 학습을 통해서 얻고자 하는 함수는 'd 함수' 다
저자들은 이 d 함수를 구하기 위해 CNN을 통과할 때 pool5 레이어에서 얻어낸 특징 벡터를 사용하고, 함수에 학습 가능한 웨이트 벡터를 주어 계산한다.
Image는 2차원 데이터고, 2차원 데이터를 1차원 벡터로 평활화하여 신경망 모델에 학습시켜야 한다.
CNN의 특징은 Image Size를 줄이면서, 특징을 나타내는 이미지들을 추출 해낼 수 있다.
FC Layer에 도달하기 전까지 평활화 과정 없이 이미지 정보를 효과적으로 유지하며, 특징 픽셀들을 추출한다. 위 과정에서 인접한픽셀과의 관계를 효과적으로 인식 할 수 있고, 이미지의 특징을 모으거나 강화할 수 있다
CNN 주요 개념
정사각형 행렬 모양의 Filter가 이미지를 순회하며 Convolution을 계산한다.
계산 결과를 이용하여 Feature map을 만든다.
Feature map을 모아 한 이미지에서 활성화된 픽셀만을 모은 Activation map을 만든다.
위 3가지 과정을Convolution Layer라고 한다.
Convolution layer의 shape는 Filter 크기, Stride, Padding 등에 영향을 받는다.
출력된 Convolution layer를 또 하나의 입력 데이터로 삼아, Pooling 과정을 거친다.
위 두 과정을 반복하면이미지의 크기는 줄어들고, 채널이 늘어난다.
이미지 데이터에 대한 이해
우리가 눈으로 보는 컬러 이미지는 RGB 공간에 저장된다. (RED, GREEN, BLUE)
흑백 이미지라면, 이미지는 RGB 공간이 아닌, Gray scale 공간에 저장된다.
Pixel 값은 흰색의 강도를 나타낸다.
작을수록 검은색에 가깝고, 클수록 흰색에 가까움
이미지가 어떤 색 공간에 저장되는지에 따라 이미지의 depth가 달라진다.
RGB 공간의 경우 이미지 depth는 " 3 "
Gray scale 공간의 경우 " 1 "
이미지를 하나의 depth 별로 쪼개어 나타냈을때 각 한장의 이미지를 채널이라고 함.
입력 데이터
CNN 신경망에 입력되는 데이터는 (Height, Width, Channel) 형태의 이미지다.
만약 CNN 신경망에 이미지 1장이 입력된다고 가정하면, 28 x 28 픽셀의 컬러 이미지라면, 해당 입력 데이터의 shape는 (28, 28, 3) 이고, 흑백 이미지라면 (28, 28, 1)이 된다.
Convolution Layer
1. Filter ( = Kernel)
이미지의 특징을 뽑아낼 거름망 역할을 수행한다.
2차원 정사각 행렬 형태이다.
자신의 크기 만큼 이미지를 확대하고, 해당하는 부분만 확인한다.
해당하는 영역의 값들을 하나의 값으로 뽑아내기 위해, 합성곱 연산 수행한다.
Neural Network에서 Weight(가중치)라고 판단하면 된다.
처음에는 임의의 값을 부여한 뒤, 학습을 통해 적절한 filter 값을 찾음
2. Channel
Convolution을 구성하는 레이어의 수를 의미한다.
처음에는 이미지의 depth (color, gray 여부) 이지만, 이후에는 필터의 개수가 된다.
이미지는 입력층을 지나 Convolution Layer를 지날 때 마다 값이 달라진다.
3. Convolution (합성곱)
Gray Scale의 픽셀값으로 나타내면 아래와 같다.
Filter를 가지고 합성곱 연산을 아래와 같이 수행해본다.
4. Stride (보폭)
Filter가 Convolution 연산을 수행하기 위해 이동하는 양.
Filter가 지정된 Stride만큼 오른쪽으로, 위에서 아래로 이동한다.
5. Feature map
필터 설정한다.
같은 값을 갖는 필터를 이용하여 입력된 이미지 데이터 탐색한다.
필터가 계산하는 합성곱 연산 결과를 2차원 행렬에 저장한다.
위 합성곱을 수행하면, 필터 가중치에 해당하는 이미지 특징들이 추출된다.
아래와 같이 “ 5 “ 를 나타내는 이미지에서 맨 위 가로 부분을 뽑아서 인식하고 싶다면 가로로 배열되어 있는 성분을 강조하는 3 x 3 크기의 필터를 적용할 수 있다.
숫자가 없는 부분의 픽셀 값은 모두 0이라 하여, Convolution을 수행하면 오른쪽과 같이 기존 이미지에 비해 가로 성분이 강조된 Featured map이 출력된다.
Feature map에서 한변의 길이가 중요하다. ⇒ 한변의 길이가 정수가 되도록 Stride를 설정하는 것이 중요함.
5 x 5 이미지, 3 x 3 필터, 1 보폭 : Feature Map 사이즈 3 x 3
5 x 5 이미지, 3 x 3 필터, 2 보폭 : Feature Map 사이즈 2 x 2
5. Padding
위와 같이 필터를 적용해서 작업을 계속 하면, 이미지 사이즈가 작아지게 된다.
이미지 사이즈가 작아지면 데이터 손실이 발생한다.
이를 방지하기 위해 이미지 레이어 외부에 일정한 값의 레이어를 덧덴다. ⇒ 일반적으로 상하좌우 같은 크기의 값을 갖는 0을 덧대는 패딩을 사용함.
패딩 효과
Convolution Layer 출력 데이터 크기가 과도하게 축소되는걸 방지한다.
Neural Network가 이미지 외곽을 인지할 수 있다.
Activation Map
Feature map 각 픽셀에 대해 활성화 함수를 적용한 결과
Convolution Layer 최종 출력 결과
일반적으로 ReLU 함수 사용
Pooling Layer
Convolution Layer 출력인 Activation Map의 크기를 줄이는 과정
Activation Map에 인접한 부분에서 일정한 기준에 따라 픽셀 하나의 값을 뽑는다
일정한 크기의 커널을 두고 Activation map을 슬라이딩 하며 가장 큰 값(Max Pooling)혹은 가장 작은 값(Min Pooling) 혹은 평균값(Average Pooling)을 뽑는다
Pooling 커널이 슬라이딩하는 것은 [Filter ( = Kernel)]가 움직이는 것과 같은 원리이므로, 해당 커널 역시 Stride가 있다.
Kernel size : 2 x 2 , Stride : 2 일 때 Pooling 종류에 따라 Activation Map 변화
커널 영역에서 상관성이 가장 높다고 판단하여MAX POOLING을 제일 많이 사용
단점 : 데이터 손실
장점 : 연산량, 메모리 사용 ↓, 과적합 (Overfitting) 방지 및 데이터 특정 부분이 변형되어도 동일한 결과 출력
Fully Connected Layer
위와 같은 과정이 반복되면 기존 이미지는 추상화되어 특징들만 남게 된다.
이런 결과를 평탄화(flatten)하여, 1차원 벡터로 Fully Connected Layer에 전달한다.
Fully Connected Layer가 하는일
활성화 함수를 적용하여 원하는 작업을 수행한 뒤, 최종 결과 추출
Optimizer는 Convolution Layer와 Fully Connected Layer의 가중치에 오류들을 역전파하며 각 가중치들을 조정해 나간다.
Model Architecture
3차원 이미지로 R,G,B 채널로 구성
4 x 4 필터 적용 depth : 3 (RGB 공간에 존재) ⇒ shape (4, 4, 3)
필터는 12개의 값으로 구성된 육면체이다.
이 상태에서 합성곱 연산을 하기 때문에 12개의 값을 모두 더한것이 Feture map 한칸에 저장됨.
Stride 값은 2 이고, 패딩을 적용 안하면 Feature map 한 변의 길이는 9 가 된다.
이제 이미지에 각각 다른 필터 6개를 적용한다고 하자. 6개의 서로 다른 특징들을 추출하겠다는 의미다.
예컨대 하나의 필터는 고양이의 귀를, 하나는 고양이의 눈을, 또 다른 하나는 고양이 수염을 인식하는 방식이다.
서로 다른 부분을 추출하므로 각각의 필터가 가지고 있는 가중치는 모두 다르다.
그렇다면 6개의 필터를 활용해 Convolution을 적용한 결과로 모두 9x9짜리의 Feature Map 6개를 결과로 얻게 된다.
각각의 Feature Map에 ReLU 활성화 함수를 적용하여 Activation Map을 만든다.
따라서 Convolution Layer에서 얻게 되는 데이터의 shape은 (9, 9, 6)이 된다.
위의 과정을 통해 Convolution 출력 레이어의 최종 결과의 채널은 필터의 개수와 같아 진다는 것을 알 수 있다.
특히 위에서 말했듯 필터가 추출하고 싶은 이미지 특징을 나타낸다는 점을 고려한다면, 추출하고 싶은 특징의 수를 설정한 뒤, 이것을 모두 필터로 설정해 버리면 된다.
그 결과, Convolution Layer의 채널 수로 추출하고자 하는 특성의 수 만큼을 가지게 된다.
위의 Activation Map에 커널 사이즈를 3 x 3, stride를 2로 하여 Max Pooling을 적용하자.
그러면 각각의 Activation Map이 3 x 3 사이즈로 축소된다.
이렇게 모든 Convolution과 Pooling의 과정을 거친 후, 모든 데이터를 평활화한다.
그러면 (3, 3, 6) shape의 데이터가 (54, ) shape의 1차원 벡터가 된다.
이 벡터를 Fully Connected Layer에 주입하고, 활성화 함수로 Sigmoid 함수를 사용하여 이진 분류 문제를 풀면 되는 것이다.
한 장의 이미지를 주입할 때 CNN 모델의 아키텍쳐는 위와 같다.
이제 위와 같은 이미지가 여러 장 있다면, 데이터의 shape이 4차원이 될 것이다.
기존의 3차원 구조에 이미지의 개수가 한 차원으로 더 추가되는 것이다. 다음 실습에서 살펴 볼 Tensorflow에서는 이미지 데이터를 (입력 이미지 개수, 이미지 높이, 이미지 너비, 채널 수), 즉, (Num, Height, Width, Channels)로 표현한다.
차원이 한 차원 더 더해지는 것일 뿐, 뒤의 과정은 동일하다.
이렇게 여러 장의 이미지에 Convolution과 Pooling을 여러 번 적용하고(여러 층을 만든다는 의미이다.), 학습을 통해 특징을 추출해낸 뒤 Fully Connected Layer에 주입하여 원하는 작업을 수행하는 것이 CNN 알고리즘의 원리이다.