// tech blog · ecology × technology

아직 궁금한게
너무 많다

생태학을 중심으로, 수학 · 물리학 · 머신러닝 · 공간정보가 교차하는 지점을 탐구합니다. 자연을 데이터와 코드로 이해하는 기술 블로그.

🌿 Ecology 🗺️ Geospatial 🧠 Data Science ∑ Fundamentals
~/about.json
{
  "blog": "아직 궁금한게 너무 많다",
  "bio": "자연을 알고 싶은 사람",
  "core": "Ecology",
  "fields": [
    "GIS", "RS", "ML/DL",
    "Math", "Physics"
  ],
  "status": "exploring"
}

SpeciesNet #3: 데이터의 시선으로 바라보는 헤라클레스장수풍뎅이

안녕하세요:) SpeciesNet 시리즈의 세 번째 포스팅입니다. 지난 글에서는 카메라 트랩 이미지를 모델에 넣고 "멧돼지 0.92", "사슴과 0.98"같은 결과를 직접 뽑아봤습니다. 그런데 컴퓨터는 이 사진을 대체 어떻게 알아본 걸까요?

 

이번 글에서는 그 과정을 하나씩 뜯어보겠습니다. 오늘 살펴볼 질문은 다음과 같습니다.

1. 컴퓨터는 사진을 어떻게 인식할까?

2. 신경망은 어떻게 꼬인 다차원 공간을 비틀고 접어서 정답을 찾아낼까?

3. SpeciesNet 파이프라인은 어떻게 생겼을까?


이미지와 텐서(Tensor): 컴퓨터는 사진을 숫자로 본다

아래 사진을 보겠습니다. 우리 눈에는 검은색의 광택이 나는 거대한 가슴뿔과, 멋들어진 올리브빛이 감도는 노란 딱지날개를 가진 '헤라클레스장수풍뎅이'가 보입니다. 카리브해의 도미니카연방과 과들루프 섬에 서식하는 세계에서 가장 큰 장수풍뎅이이자 정말 멋진 곤충이죠:) 배경에 깔린 나무 부스러기들도 자연스럽게 눈에 들어옵니다. 하지만 컴퓨터에게 이 사진은 거대한 숫자 배열일 뿐입니다.

 

"Dynastes hercules" by TOUROULT Julien / CC BY 4.0

 

Letterbox: 직사각형을 정사각형으로

우리가 직사각형 사진을 입력하면, MegaDetector(YOLOv5x6)와 같은 객체 탐지 모델은 먼저 Letterbox라는 전처리 과정을 거칩니다. [5] 예를 들어, 2045 x 1357 해상도의 사진이 들어오면, 비율을 유지한 채 1280 x 1280 크기의 정사각형 틀 안에 맞게 축소합니다. 그리고 남은 위아래 빈 공간은 회색(114, 114, 114) 픽셀로 채워 넣습니다(Padding).

 

이 과정을 거치면 어떤 비율의 사진이든 원래 형태를 보존한 채, 정확히 1280 x 1280개의 픽셀 격자로 변환됩니다.

 

한 픽셀 = 세 개의 숫자

이 격자 위의 픽셀 하나는 R, G, B 세 개의 밝기 숫자(0~255:어두움~밝음)를 차례대로 담고 있는 열벡터(Column Vector)로 표현됩니다. 조금 더 엄밀히 보면 R, G, B는 색상 공간을 구성하는 세 개의 독립적인 축입니다.

$$\text{Pixel} = \begin{bmatrix} R \\ G \\ B \end{bmatrix}$$

 

Tensor: 숫자를 담는 다차원 상자

픽셀 하나가 숫자 3개짜리 배열(벡터)라면, 이런 픽셀이 1280 x 1280개나 모여 있는 '사진 전체'는 어떤 구조일까요? 여기서 딥러닝의 핵심 용어인 텐서가 등장합니다. 텐서라는 이름이 왠지 어렵게 들릴 수 있지만, 딥러닝에서는 아주 단순하게 생각해도 좋습니다. 텐서는 그저 숫자들을 가지런히 모아둔 다차원 배열입니다. 이 배열은 데이터가 나열된 방향, 즉 축(Axis)이 몇 개냐에 따라 모양이 달라집니다.

 

우리의 1280 x 1280 컬러 사진은 Red, Green, Blue 3장의 면이 겹쳐져 있는 형태입니다. 따라서 채널(C), 세로(H), 가로(W)라는 3개의 축이 필요하므로 $(3, 1280, 1280)$의 크기를 가진 3차원 텐서가 됩니다.

Shape: (3, 1280, 1280)
        │    │      └─ 가로(Width): 1280 픽셀
        │    └──────── 세로(Height): 1280 픽셀
        └───────────── 채널(Channel): R, G, B 3개

 

컴퓨터 비전 실무자들은 이 숫자 세 개만 보고도 "아, 3 채널짜리 1280x1280 컬러 사진이 들어왔구나"라고 즉시 파악합니다. 모델은 이 약 491만 개(3x1280x1280)의 숫자를 읽고 헤라클레스장수풍뎅이라는 답을 내놓는 겁니다. 참고로 (C, H, W) 순서는 PyTorch가 기본으로 사용하는 텐서 포맷입니다. 이 시리즈에서 모든 shape은 Pytorch 기준으로 표기하겠습니다.

 

데이터의 관점에서 이 사진 데이터는 실수($\mathbb{R}$) 원소를 가진 다차원 공간의 집합으로 표기됩니다. 입력 이미지 텐서 $\mathbf{X}$는 다음과 같이 정의할 수 있습니다.

$$\mathbf{X} \in \mathbb{R}^{C \times H\times W}$$

여기서 $H, W$는 물리적 픽셀이 배치된 공간 차원(Spatial Dimension)을, $C$는 각 지점의 정보(색상 또는 특징)를 담는 특징 차원(Feature Dimension)을 의미합니다.

 

채널의 의미는 진화한다

여기서 아주 중요한 개념 하나만 짚고 넘어가겠습니다. 지금 단계에서 채널은 단순한 색상(R, G, B)을 의미하지만, 사진이 모델 내부의 깊은 층(Layer)으로 들어갈수록 채널의 의미는 완전히 달라집니다.

단계 채널 수 각 채널의 의미
입력 이미지 3 R, G, B 색상
Backbone 초기 층 80 가장자리, 질감 (저수준 시각 특징)
Backbone 마지막 층 1280 뿔, 다리 형태 (고수준 의미 특징)

입력 단계에서 "채널 = 색상의 종류(3)"였던 것이, 모델 내부에서는 "채널 = 특징의 종류(1280)"로 진화합니다. Shape에서 C가 3에서 80, 1280으로 늘어난다는 것은, 모델이 사진을 색깔로만 보지 않고 점점 더 풍부한 특징(Feature)을 기준으로 세상을 바라보기 시작했다는 의미입니다.

 

딥러닝 모델의 핵심 패턴은 항상 이렇습니다. "공간 해상도(H, W)는 줄어들고, 채널 수(C)는 늘어난다." 처음의 거대한 RGB 픽셀 덩어리가 층을 거치며 공간 차원은 압축되고 특징 차원은 확장되며, 1280가지의 의미 있는 추상적 정보로 투영(Projection)되는 것입니다. 이 변환을 주도하는 '합성곱(Convolution)'의 마법은 4부에서 자세히 뜯어보겠습니다.

 

정규화(Normalization): 숫자들을 0과 1 사이로 누르기

마지막으로, 모델이 이 텐서를 삼키기 직전에 거치는 필수 전처리 과정이 있습니다. 바로 0~255 사이인 픽셀 값들을 모두 255로 나누는 정규화입니다.

$$x_{\text{norm}} = \frac{x}{255}$$

 

예컨대 짙은 올리브색 픽셀인 [85, 107, 47] 은 [0.333, 0.420, 0.184]로 작아집니다. 왜 멀쩡한 숫자를 굳이 0~1 사이로 찌그러뜨릴까요? 크게 세 가지 이유가 있습니다.

 

1. 숫자 폭주 방지 : 255 같은 큰 숫자들은 수십 개의 신경망 층을 통과하며 계속 곱해집니다. 자칫 숫자가 무한대로 폭발하거나 0으로 사라져 버릴 수 있습니다(기울기 폭발/소실). 0~1 범위로 눌러놓으면 이 위험이 크게 줄어듭니다.

2. 학습 안정성 : 모델의 가중치를 업데이트하는 최적화 알고리즘(Optimizer)은 입력 값의 범위가 좁고 균일할 때 훨씬 빠르고 안정적으로 길을 찾습니다.

3. 공정한 출발선 : R, G, B 채널 모두 같은 0~1 범위에 놓이게 되므로, 어느 한 색상이 튀어서 결과에 부당하게 큰 영향을 미치는 것을 막아줍니다.

 

참고: 진짜 텐서 vs 딥러닝 텐서

위 설명처럼 딥러닝에서의 텐서는 단순히 다차원 배열(Multi-dimensional Array) 구조를 뜻합니다. 하지만 수학과 물리학에서 말하는 텐서는 "좌표계가 바뀌어도 일정한 변환 규칙을 따르는 다중선형사상(multilinear map)"이라는 훨씬 복잡한 개념입니다. 같은 이름이지만 깊이가 전혀 다르죠... 컴퓨터 과학에서는 이 텐서의 다차원 데이터를 담는 구조라는 특징만 빌려와 실용적으로 사용하고 있습니다.


딥러닝의 최소 단위: 퍼셉트론(Perceptron)

이제 헤라클레스장수풍뎅이 사진은 0~1 사이의 숫자로 압축된 약 491만 개의 숫자 더미, 즉 텐서가 되어 모델 입구에 섰습니다. 그렇다면 모델은 이 거대한 숫자 배열 속에서 대체 어떻게 거대한 가슴뿔이나 노란 딱지날개 같은 특징을 알아채는 걸까요?

 

그 비밀은 이 숫자들을 건네받아 계산을 수행하는 딥러닝의 가장 작은 연산 단위, 뉴런(Neuron)에 있습니다.

 

딥러닝의 역사는 인간의 뇌를 모방하려는 시도에서 시작되었습니다. 뇌의 기본 단위인 신경세포(뉴런)는 여러 뉴런들로부터 전기 신호를 받아, 그 합이 일정 임계값을 넘으면 다음 뉴런으로 신호를 전달합니다.

 

https://en.wikipedia.org/wiki/Neuron

 

1943년 McCulloch와 Pitts가 제안하고 [1] 1957년 Rosenblatt이 이를 실제로 구현하며 최초의 인공신경인 퍼셉트론이 탄생했습니다. [2] 퍼셉트론이 텐서 안의 숫자들을 받아 처리하는 과정은 세 단계로 나뉩니다.

 

1. 가중합(Weighted Sum) : 공간의 변환

가장 먼저, 입력된 데이터 텐서 $\mathbf{x}$에 가중치 행렬 $\mathbf{W}$를 곱하고 편향 $\mathbf{b}$를 더해줍니다. 이것이 뉴런의 첫 번째 핵심 연산입니다.

$$\mathbf{z} = \mathbf{W}\mathbf{x} + \mathbf{b}$$

이 연산은 단순한 산술 계산을 넘어, 수학적으로 아핀 변환(Affine Transformation)과 본질적으로 같습니다. 행렬 $\mathbf{W}$를 곱해 원본 데이터가 있던 공간을 회전 및 확대/축소하고(선형변환), 편향 $\mathbf{b}$를 더해 공간의 기준점을 이동시킴으로써 모델이 패턴을 찾기 쉬운 새로운 공간으로 변환하는 과정입니다.

 

2. 활성화(Activation) : 넘길 것인가, 차단할 것인가

가중합 연산의 결과인 $\mathbf{z}$는 본질적으로 선형적인 결괏값입니다. 직선만으로는 복잡한 자연계의 패턴을 구분하는 데 한계가 있으므로, 모델에 비선형성(non-linearity)을 부여하기 위해 활성화 함수 $f$를 통과시켜 최종 출력 $\mathbf{y}$를 만듭니다.

$$\mathbf{y} = f(\mathbf{z})$$

가장 널리 쓰이는 활성화 함수는 ReLU(Rectified Linear Unit)입니다. [4]

$$\text{ReLU}(\mathbf{z}) = \max(0, \mathbf{z})$$

 

- $z > 0$이면: 그대로 통과

- $z \leq 0$이면: 0으로 차단

 

놀랍도록 단순하지만, 이 "음수를 잘라내는" 동작이 직선만으로 풀 수 없던 복잡한 문제를 풀 수 있게 만듭니다. 실무적으로 단일 뉴런 하나는 "내가 찾는 패턴(예: 뿔의 윤곽선)이 감지되면 신호를 강하게 통과시키고, 아니면 0으로 스위치를 끄는" 탐지기 역할을 수행합니다.

참고로 YOLOv5는 ReLU 대신 이를 부드럽게 개선한 SiLU를 사용합니다.

 

3. 출력 : 다음 뉴런으로 전달한다

활성화 함수를 통과한 값 $\mathbf{y}$가 이 퍼셉트론의 최종 출력입니다. 이 값은 곧바로 다음 층의 뉴런에게 입력으로 전달됩니다.

 


뉴런을 쌓으면: 다층 퍼셉트론(MLP)

퍼셉트론 하나의 구조를 이해했다면, 자연스러운 질문이 생깁니다. 뉴런을 여러 개 연결하면 어떻게 될까요? 먼저 중요한 함정 하나를 짚고 넘어가겠습니다. 활성화 함수 없이 선형 변환만 여러 층 쌓으면 어떻게 될까요?

 

레이어를 100개 쌓아도 결국 선형 변환 한 번을 거친 것과 동일합니다. 깊이가 아무 의미가 없어지는 것이죠. 활성화 함수가 없으면 아무리 깊은 신경망도 퍼셉트론 하나와 같습니다.

 

XOR: 직선 하나로는 풀 수 없다

비선형 활성화 함수가 왜 필수인지, 가장 단순한 예제로 보겠습니다. XOR은 "두 입력이 서로 다를 때만 1을 출력"하는 논리 연산입니다.

$x_1$ $x_2$ XOR
0 0 0
1 1 0
0 1 1
1 0 1

 

이 네 점을 2D 평면에 찍으면, XOR=0(파란 점)은 대각선 한쪽에, XOR=1(빨간 점)은 반대 대각선에 놓입니다. 어떤 직선을 그어도 두 그룹을 동시에 나눌 수 없습니다.

단일 퍼셉트론은 이 문제를 풀 수 없습니다. 1969년 Minsky와 Papert가 이 한계를 명확히 증명했고, 이것이 AI 연구의 첫 번째 겨울을 불러올 만큼 근본적인 문제였습니다. [3]

 

은닉층의 비밀: 공간 변환 (비틀고 접어서 잘라내기)

단일 퍼셉트론(직선)의 한계를 극복하는 해결책은 뉴런을 여러 층 쌓는 것입니다. 그런데 은닉층을 추가한다는 게 정확히 무슨 의미일까요? 단순히 연산을 더 하는 게 아닙니다. 우리가 입력한 491만 차원의 사진 데이터 속에는 풍뎅이의 특징과 배경의 나무 부스러기 특징들이 마치 구겨진 색종이 뭉치처럼 복잡하게 뭉쳐 있습니다. 의미 있는 특징만을 다음 층으로 넘기려면, 모델은 이 구겨진 공간 속에 명확한 구분선을 그어 풍뎅이와 배경을 분리해야 합니다. 하지만 직선(단일 뉴런)만으로느 구겨진 종이를 한 번에 자를 수 없습니다. 그래서 은닉층의 가중치 행렬들은 데이터 공간 자체를 마구 비틀어 당기고, 활성화 함수(ReLU)로 불필요한 영역을 0으로 꽉 접어 누르는 작업을 반복합니다. 즉, 구겨져 있던 공간을 요리조리 펼쳐서, 마지막 층에 도달했을 때는 단순한 직선 하나로도 "이건 풍뎅이!" 하고 싹둑 잘라낼 수 있는 상태로 재배열하는 것입니다.

 

 

(위 애니메이션을 보면, 은닉층은 세 단계로 작동합니다.)

1. $\mathbf{W}\mathbf{x}$ : 행렬이 격자 전체를 변형합니다. 뒤섞여 있던 점들의 상대적인 위치가 달라집니다.

2. ReLU : 음수 영역을 0으로 접습니다. 0이 된 뉴런은 이 입력에 대해 아무 신호도 보내지 않습니다(비활성).

3. 새로운 공간 : 변환이 끝난 공간에서는 직선 하나로 두 그룹을 나눌 수 있게 됩니다.

 

뒤섞여 있던 공간이 펼쳐지면서 분리 가능한 구조로 재배열되는 것, 이것이 은닉층이 하는 일의 본질입니다. 이렇게 입력층과 출력층 사이에 하나 이상의 은닉층(Hidden Layer)을 가진 구조를 다층 퍼셉트론(Multi-Layer Perceptron, MLP)이라고 합니다. 은닉층이 여러 개인 경우를 특별히 심층 신경망(Deep Neural Network, DNN)이라 부르며, 이것이 딥러닝(Deep Learning)이라는 이름의 유래입니다.

 

한계점과 진짜 파이프라인의 등장(CNN)

이것이 다층 퍼셉트론(MLP)이 꼬인 공간을 펴서 데이터를 분류하는 수학적 본질입니다. 하지만 우리가 다루는 이미지 데이터에서는 치명적인 문제가 하나 발생합니다.

 

우리의 입력 텐서는 (3, 1280, 1280), 즉 491만 개의 숫자입니다. 앞서 픽셀 하나를 숫자 3개짜리 벡터라고 설명했었죠? 전통적인 다층 퍼셉트론(MLP)은 이렇게 가로, 세로가 있는 입체적인 텐서를 그대로 받아들일 수 없습니다. 오직 1차원 배열(1D Tensor), 즉 거대한 단일 벡터 하나만 입력으로 받을 수 있습니다.

 

따라서 사진을 넣으려면 $3 \times 1280 \times 1280$의 블록 구조를 전부 허물고, 491만 개의 숫자를 한 줄로 길게 이어 붙여야 합니다(Flatten). 이 변환은 다음과 같이 표기됩니다.

$$\mathbf{x} = \text{Flatten}(\mathbf{X}) \quad (\mathbf{X} \in \mathbb{R}^{3 \times 1280 \times 1280} \rightarrow \mathbf{x} \in \mathbb{R}^{4915200})$$

이 순간, 독립적인 차원들의 구조를 나타내던 곱셈 기호($\times$)는 사라지고, 사진 한 장은 491만 차원 공간($\mathbb{R}^{4915200}$)에 찍힌 거대한 '단 하나의 점(벡터)'으로 취급됩니다.

 

문제는 이 과정에서 가로, 세로라는 물리적 공간($H, W$)의 개념이 완전히 파괴된다는 것입니다. '어떤 픽셀이 누구 옆에 있는지'에 대한 위치 정보는 물론이고, 하나로 묶여있던 픽셀의 R, G, B 세트마저 길게 펴지면서 이산가족처럼 뿔뿔이 흩어져버립니다. 모델은 "헤라클레스장수풍뎅이가 사진 중앙에 있다"는 공간적 맥락을 완전히 잃어버리게 되는 것이죠.

 

이 공간의 파괴를 막기 위해 사용하는 기술이 다음 포스팅에서 다룰 합성곱 신경망(CNN)입니다. 실제 객체 탐지 모델은 데이터를 무식하게 펴지 않고, 텐서의 구조($C \times H \times W$)를 영리하게 유지하며 특징을 추출하는 파이프라인을 가집니다.

  • 특징의 탄생($C$의 확장) : 색상 채널은 소멸하고, 대신 그 자리에 "뿔의 형태인가?", "등 딱지의 질감은 매끄러운가?"를 묻는 수백 개의 고차원적인 특징 공간(Feature Space)이 채워집니다.
  • 공간의 보존($H$, $W$의 압축) : 공간은 사라지지 않습니다. 대신 해상도만 줄어들며, 미세한 픽셀 위치에서 거시적인 맥락을 파악하는 공간으로 압축됩니다.

SpeciesNet 파이프라인 조감도

2부에서 우리는 이 파이프라인을 사진을 넣으면 결과가 나오는 사용자의 시선으로 봤습니다. 이제 같은 파이프라인을 데이터의 시선으로 다시 봅니다. 헤라클레스장수풍뎅이 사진이 숫자 배열로 바뀌고, 수백 개의 층을 통과하며, 최종적으로 하나의 종 이름이 되기까지 텐서가 겪는 여정을 따라가 보겠습니다.

 

전체 Shape 변환 한눈에 보기

 

아래 흐름을 머릿속에 넣어두고 세부 단계를 읽으면 훨씬 잘 들어옵니다.

1단계: Detector (MegaDetector v5)

사진 속 어디에 동물이 있는가?

역할과 구조는 2부에서 다뤘습니다. 여기서는 내부에서 텐서가 어떻게 흘러가는지에 집중합니다.

    • 입력 : (3, 1280, 1280) - 원본 사진
    • Backbone(4부) : 특징을 추출하는 눈 (3, 1280, 1280) > (1280, 40, 40)으로 압축
    • Neck(4부) : 다중 스케일 특징을 합치는 다리, 큰 동물도 작은 동물도 놓치지 않게
    • Head(5부) : "여기에 뭐가 있다"고 결정하는 판단부 > 바운딩 박스 좌표 + 확신도
    • 출력: 크롭 된 동물 영역 이미지

Backbone은 앞서 본 레이어 쌓기의 구체적인 구현입니다. 공간 해상도를 줄이면서 채널을 늘려 "이 위치에 어떤 특징이 있는가"를 요약합니다. Neck은 여러 해상도의 특징 맵을 섞어서 크기가 다른 동물을 모두 잡을 수 있게 합니다. Head는 최종적으로 "이 칸에 동물이 있다/없다"를 판단합니다. 각 구성 요소의 내부 메커니즘(합성곱, 풀링, FPN 등)은 4부에서, 판단 기준(앵커, 손실 함수, NMS)은 5부에서 본격적으로 뜯어봅니다.

 

2단계: Classifier(SpeciesNet)

잘라낸 이 동물이 무슨 종인가?

  • 입력 : 크롭된 동물 이미지 (3, H, W)
  • EfficientNet(6부) : Detector의 Backbone과 같은 역할이지만 "종 구분에 특화된 특징"을 추출 > (512, ) 특징 벡터 [6]
  • 분류 Head(6부) : 1280차원 특징 벡터 > softmax > 확률 분포
  • 출력 : "헤라클레스장수풍뎅이: 0.94"

3단계: Ensemble(앙상블)

Detector와 Classifier의 결과를 종합하고, 지리적 정보(Geofence)를 더해 최종 판정을 내립니다.

  • 입력: 바운딩 박스 + 확신도 + 종별 확률 분포 + GPS/국가 정보
  • Geofence: 2부에서 'config.yaml'에 설정했던 'country: KOR"이 바로 이 단계에서 사용됩니다.
  • 출력: 최종 종 판정("Dynastes hercules: 0.94")

"이 사진은 한국에서 찍혔는데, 도미니카연방의 야생의 헤라클레스 장수풍뎅이일리가 없잖아!"라는 상식적인 판단을 수행합니다.

 

지금까지 본 파이프라인은 이미 학습이 끝난 모델이 사진 한 장을 처리하는 추론 과정입니다. 텐서가 층을 통과하며 숫자가 바뀌는 것은 봤지만, 모델이 애초에 이 판단 능력을 갖추게 됐는지는 아직 다루지 않았습니다. 순전파, 손실 계산, 역전파, 가중치 업데이트 등 학습이 실제로 어떻게 일어나는지는 5부에서 다룹니다. 4부에서는 먼저 Backbone이 특징을 어떻게 추출하는지, 합성곱이란 무엇인지를 살펴봅니다.

 

References

[1]  W. S. McCulloch and W. Pitts, "A logical calculus of the ideas immanent in nervous activity," The Bulletin of Mathematical Biophysics, vol. 5, no. 4, pp. 115–133, 1943.
[2]  F. Rosenblatt, "The perceptron: a probabilistic model for information storage and organization in the brain," Psychological Review, vol. 65, no. 6, pp. 386–408, 1958.
[3]  M. Minsky and S. Papert, Perceptrons: An Introduction to Computational Geometry, MIT Press, 1969.
[4]  V. Nair and G. E. Hinton, "Rectified linear units improve restricted boltzmann machines," in Proceedings of the 27th International Conference on Machine Learning (ICML), pp. 807–814, 2010.
[5]  S. Beery, D. Morris, and S. Yang, "Efficient pipeline for camera trap image review," arXiv preprint arXiv:1907.06772, 2019.
[6]  M. Tan and Q. V. Le, "EfficientNet: Rethinking model scaling for convolutional neural networks," in International Conference on Machine Learning (ICML), pp. 6105–6114, 2019.