<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko-KR"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://winterbloooom.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://winterbloooom.github.io/" rel="alternate" type="text/html" hreflang="ko-KR" /><updated>2026-07-23T09:51:23+09:00</updated><id>https://winterbloooom.github.io/feed.xml</id><title type="html">winterbloooom</title><subtitle>로보틱스·컴퓨터비전·딥러닝 공부 기록. winterbloooom (한은기)의 개인 기술 블로그.</subtitle><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><entry><title type="html">[HPE] Human Pose Representations &amp;amp; Approaches (Models)</title><link href="https://winterbloooom.github.io/hpe_approach/" rel="alternate" type="text/html" title="[HPE] Human Pose Representations &amp;amp; Approaches (Models)" /><published>2023-02-21T00:00:00+09:00</published><updated>2023-02-21T00:00:00+09:00</updated><id>https://winterbloooom.github.io/hpe_approach</id><content type="html" xml:base="https://winterbloooom.github.io/hpe_approach/"><![CDATA[<div id="inserted-box">
    <div class="notice-text"><p>HPE 시리즈는 현재 필자가 연구(공부)하는 주제로, 이와 관련된 이론 및 논문들을 소개할 예정입니다.</p></div>
</div>

<h1 id="representations">Representations</h1>

<p>HPE task는 곧 관절(keypoints)의 위치를 찾는 일이라고 했다. 따라서 이 관절을 표현하는 방식(representation)에 따라 HPE 모델을 구분하기도 한다. 대표적으로 ‘Regression based’ 방식과 ‘Heatmap based’ 방식이 존재하며, 각각 관절 좌표를 직접 추론하거나 확률분포(히트맵)을 이용해 찾는다.</p>

<h2 id="regression-based">Regression based</h2>

<p>우리의 직관처럼, 이미지 내에서 사람 관절의 좌표를 바로 찾아내는 방식이다. 특정 관절의 좌표를 𝒫_𝑖 (𝑥, 𝑦) 라고 나타내면 이 값을 사진 상에서 보이는 모든 관절에 대해 찾아낸다. 좌표의 ‘순서가 있는 튜플(ordered tuples)이라고 보면 된다.</p>

<p>모델은 예측값과 정답값(Ground Truth, 이하 ‘GT’) 간의 차이, 즉 두 좌표 간 거리를 최소화하는 방향으로 학습한다.</p>

<p>Heatmap based 방식에 비해 비교적 정확도가 낮다고 알려졌으나, 그와는 반대로 모델 중간에 미분이 불가능한 단계(non-differentiable steps)가 적고 종단간 프레임워크(end-to-end framework)에 통합하기 더 쉽다는 장점도 있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/229352767-d56ebdd5-3069-4886-b01d-e90832ac801b.png" width="70%" />
<figcaption>Fig1. Example of regression based representation</figcaption>
</figure>

<h2 id="heatmap-based">Heatmap based</h2>

<p>하나의 관절 당 하나의 히트맵(heatmap 혹은 confidence map, probability distribution)을 만든다. 관절이 위치할 확률이 높은 픽셀일 수록 높은 값을 부여하며, 추론 시에는 히트맵에서 가장 높은 값을 같는 위치를 관절의 위치라고 예측한다.</p>

<p>Regression based 보다는 비교적 높은 정확도를 가진다고 알려져 있다. 반면 히트맵을 만들고 처리하는 과정에서 종종 휴리스틱한(heuristic) 처리를 사용하고, 따로 예측한 관절 정보들을 묶는(grouping) 등 추가적이거나 미분 불가능한 과정이 필요할 때가 많다. 따라서 종단간 학습에 통합하기 어려운 경우가 있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/229352808-1f263db5-1d5f-4cf9-bd7f-db50a8232d84.png" width="70%" />
<figcaption>Fig2. Example of heatmap based representation</figcaption>
</figure>

<hr />

<h1 id="approaches">Approaches</h1>

<h2 id="classical-approaches">Classical Approaches</h2>

<p>초기 HPE에서는 ‘사람이 만들어낸(hand-crafted)’ 특징(features)를 사용해왔다. 예를 들자면 edges, contours, HOG(Histogram of Oriented Gradients) 등이 있다. 또한 사람을 pictorial 구조, 즉 각 부분을 변형 가능한(deformable) 형태로 이은 구조로 나타냈다. 쉽게 말하면 어릴 적 그리던 ‘졸라맨’ 형식이다. 머리, 몸통, 종아리, 허벅지 등을 각 부분으로 구분하고 잇는 것이다.</p>

<p>하지만 단점이 많았다. 일단, 일반화 성능(generalization performances)가 낮았다. 각 파트를 정확히 인식하기에 해당 features가 적합하지 않았다. 특히 사진 상에서 사람의 신체 일부가 가려지거나(occlusion), 잘리거나(truncation), 다양한 자세로 있을 때 정확하게 자세를 추정하지 못하였다. 그렇다 보니 대규모 데이터셋에서 데이터의 다양성을 학습하기에 충분하지 못하였다.</p>

<h2 id="deep-learning-based-approaches">Deep Learning-based Approaches</h2>

<p>다른 task들이 그렇듯, HPE 역시 딥러닝의 등장으로 새로운 국면을 맞는다. 빅데이터와 심층신경망(DNN, Deep Neural Network)의 우수한 표현력 (representation capability), 하드웨어의 성능 향상을 배경으로 딥러닝 연구가 활발히 진행되었다.</p>

<p>2014년에 DeepPose 모델이 HPE에서 합성곱신경망(CNN, Convolutional Neural Network)을 처음으로 채택한 뒤 딥러닝을 활용한 모델이 속속들이 발전하기 시작했다.</p>

<p>연구(모델)은 크게 Single-person PE와 Multi-person PE로 나눌 수 있다. 단어 그대로 전자는 사진(혹은 영역)에 사람 한 명만 존재하여 한 명에 대해서만 PE를 수행한다. 반면 후자의 경우 여러 사람의 자세를 동시에 추정해야 하는 모델이다.</p>

<p>최근에는 Multi-person PE이 연구의 주를 이루며, 이 글에서도 해당 모델들을 다룰 예정이다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/229352886-d1d4cefa-3325-45e9-b68a-869bbfd6f651.png" width="70%" />
<figcaption>Fig3</figcaption>
</figure>

<hr />

<h1 id="multi-person-pose-estimation">Multi-person Pose Estimation</h1>

<p>Multi-person PE는 다시 Two-stage 와 Single-stage method로 나뉜다. 직관적으로, 전자는 PE를 두 단계에 걸쳐 수행하고, 후자는 한 단계만에 수행한다. Two-stage는 다시 Top-down 방식과 Bottom-up 방식으로 나뉜다. 아래선 이들의 특징과 장단점을 알아본다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/229352915-aebf746a-1277-4c2a-8971-63068f0d27fe.png" />
<figcaption>Fig4. Example of heatmap based representation</figcaption>
</figure>

<h2 id="two-stage-methods">Two-stage Methods</h2>

<p>사람의 자세를 두 개의 단계에 걸쳐 추정한다. 각 단계에서 무엇을 수행하는가에 따라 Top-down과 Bottom-up 방식으로 나뉜다. 두 번의 단계를 거치기 때문에 비교적 정확도가 높다고 알려져 있다. 그러나 이는 곧 연산 시간과 비용이 높다는 단점도 된다.</p>

<h3 id="top-down">Top-down</h3>

<p>첫 번째 단계로, 객체 탐지(object detection) 모델을 이용해 사진에서 사람을 모두 찾는다. 두 번째 단계에서 각 bounding box, 즉 각 사람 한 명 한 명에 대해 Single-person PE 모델을 적용해 자세를 추정한다.</p>

<p>Top-down methods는 각 사람(인스턴스)를 구분할 수 있다. 객체 인식을 통해 사람을 먼저 찾아내고, 서로 bounding box로 구분되니 당연한 이야기이다. 이것이 왜 장점인가 하면, 어떤 관절이 누구에게 속하는지가 명확하기 때문이다. (뒤에서 이야기 하겠지만, Bottom-up 방식은 여기서 문제가 발생한다.)</p>

<p>구현도 비교적 쉽다. Top-down은 쉽게 말하면 Object detector + Single-person PE 의 조합이다. 따라서 기존의 객체 탐지 모델과 기존의 Single-person PE 모델을 연결하면 된다.</p>

<p>Top-down은 정확도가 굉장히 높다고 알려져 있다. 현재 발행되는 논문의 실험 결과표를 보면 높은 정확도를 자랑하는 baselines는 Top-down 방식이 많고, 공개된 지 비교적 오래 된 모델이라 하더라도 아직까지 비교 대상이 될 정도이다.</p>

<p>단점도 분명 존재한다. 일단, PE의 성능이 사람 객체 탐지기의 성능에 좌우된다. Top-down은 예측한 bounding box 내에서 관절의 위치를 찾기 때문에, 사람을 제대로 탐지하지 못하면 - 예를 들면 상반신만 찾는다던가, 아예 사람을 탐지하지 못한다던가 - 당연히 그 속에서 관절도 잘 못 찾는다.</p>

<p>또 하나의 치명적 단점은, 연산 비용이 크고 추론 시간이 길다는 것이다. 사람 객체 탐지기가 분리되어 있을 뿐만 아니라, 사진 내 사람의 수 만큼 Single-person PE 모델을 작동해야 한다. 즉, 사람의 수에 비례해 연산의 비용과 시간이 증가한다. 따라서 Top-down 방식은 빠른 속도가 중요한 realtime 적용이 힘들고 사람이 많은 장면에 대해서는 더더욱 속도를 기대하기 힘들다.</p>

<p>Top-down 방식은 비교적 이른 시기(2016 ~ 2018)에 많이 제안되었다. 대표적으로 StackedHourglass(2016), RMPE(2017), Mask R-CNN(2017), CPN(2018), HRNet(2019),  SimpleBaseline(2018) 등이 있다.</p>

<h3 id="bottom-up">Bottom-up</h3>

<p>Top-down과는 반대다. 첫 번째 단계에서, 사람 구분 없이 사진 내에 보이는 모든 관절을 다 찾는다. 두 번째 단계에선, 첫 번째 단계에서 찾아 둔 관절을 각 사람에게 배분(혹은 묶기(grouping)이라고도 표현함)한다. Top-down이 사람-관절 순이라면 Bottom-up은  관절-사람 순인 것이다.</p>

<p>장단점 또한 Top-down과는 반대다. 우선, Bottom-up은 Top-down에 비해 이미지 내 사람 수에 영향을 덜 받는다. 사람이 몇 명이든 관절의 위치만 먼저 다 찾기 때문이다. 하여 비교적 사람이 많은 이미지(crowded scenes)에서 보다 잘 작동한다. Top-down보다 속도가 빠르고 파이프라인이 단순하기도 하다.</p>

<p>어려운 것은 관절을 찾고 난 뒤의 단계이다. 찾아낸 관절을 각 사람에게 배분하는, 즉 그룹핑(grouping)하고 보다 정교하게 다듬는(refinement) 과정에 휴리스틱하거나 수작업을 요하는(hand-crafted) 기법이 많이 들어간다. 또한 사람이 겹쳐 있을 땐 그 과정이 더 어렵다. 앞서 1장의 Fig8처럼 사진 상으로 두 사람이 거의 겹쳐 있을 때 이 어깨가 누구의 어깨인지, 이 팔꿈치가 누구의 팔꿈치인지 구분하는 게 힘들단 뜻이다.</p>

<p>Bottom-up 방식은 Top-down의 느린 속도를 개선해야 한다는 의견 하에 속속 제안되었는데, 대표적으로는 OpenPose(2017), Associated Embedding(2017), PersonLab(2018), HigherHRNet(2020) 등이 있다.</p>

<h2 id="single-stage-methods">Single-stage Methods</h2>

<p>이름에서도 알 수 있듯이 이미지로부터 한 번에 사람의 포즈를 추정하는 방식이다. Object detection task에서도 Two-stage 모델들이 - 정확은 하지만 - 느리고 구조가 복잡함을 꼬집으며 Single-stage 모델들이 생겨났다. YOLO (You Only Look Once)가 대표적일 것이다. HPE에서도 마찬가지로 Two-stage 모델들의 한계를 보완하기 위하여 Single-stage 모델들이 제안되고 있다.</p>

<p>일단 단계가 분할되지 않은 만큼 파이프라인은 보다 간단해졌고, 그래서 종단간 학습이 가능한 프레임워크로 구현하는 것이 더 쉬워졌다고 한다.</p>

<p>그러나 단계가 간소해진 만큼 정교함이 떨어질 수도 있고, 이를 보완하기 위한 후처리 방식(e.g., Non-Maximum Suppression)이 필요하기도 하다.</p>

<p>최근 제안되는 모델들은 거의 Single-stage methods이다. 예시로는 CenterNet(2019), SPM(2019), DirectPose(2019), Point-set Anchors(2020), FCPose(2021) 등이 있다.</p>

<hr />

<h1 id="참고-end-to-end-learning">참고: End-to-End Learning</h1>

<p>우리말로는 ‘종단간 학습’이라고도 한다. 단어 그대로 ‘끝과 끝 간의’라는 뜻으로, 데이터의 입력부터 모델의 추론 결과 출력까지 부차 네트워크/프레임워크가 없이 한 번에 이루어지는 것을 말한다.</p>

<p>예를 들어, 카메라로 사람의 신분을 확인해 출입 허가 여부를 결정하는 시스템이 있다 하면, 카메라 영상에서 사람의 얼굴을 찾아내는 네트워크가 하나, 그 얼굴만 잘라 신원을 확인하는 네트워크가 하나 있다. 그렇다면 이는 네트워크가 나뉜 것이므로 종단간이 아니다. 반면 카메라 영상에서 바로 사람의 신원을 찾아낸다면 이는 종단간이라 할 수 있다.</p>

<p>End-to-end 방식은 사람의 선입견(preconceptions) 없이 네트워크가 자체적으로 데이터로부터 학습을 할 수 있다. 즉, ‘이렇게 데이터를 봐’라고 알려주지 않고, 알고리즘이 자신이 원하는 표현법을 알아서 학습하여 입력출력 매핑 함수를 찾아낸다. 예를 들어, 음성 인식에서 언어학자들이 만들어낸 음소(phonemes)라는 개념을 찾는 게 아니라, 네트워크가 알아서 특징을 찾아 학습하는 것이다. 또한 중간요소를 적게 설계해도 되기 때문에 작업 단순화가 가능해진다.</p>

<p>물론 단점도 분명하게 존재한다. 대표적으로는, 입력에서 바로 출력으로 가는’충분한’ 데이터셋이 필요하다. 예를 들어 이미지에서 사람 얼굴을 찾는 데이터셋이 있고, 얼굴만 나오게 잘린 이미지에서 사람의 신분을 찾는 데이터셋이 따로 있다면, 이는 입력에서 바로 출력을 낼 종단간 학습에 사용하기 힘들다. 이 경우는 차라리 두 개의 네트워크로 나누어 따로 학습하는 것이 더 성능이 좋을 수 있다.</p>

<p>따라서, 해결하려는 문제가 무엇인지 파악하고, 입력출력의 충분한 데이터를 확보할 수 있을 때 사용하는 것이 좋다.</p>

<hr />

<h1 id="references">References</h1>

<div id="inserted-box">
    <div class="notice-text"><p>HPE 시리즈에서 사용하는 모든 레퍼런스는 한꺼번에 <a href="/hpe_ref/">[HPE] Human Pose Estimation References</a>에 모아두었다.</p></div>
</div>

<ul>
  <li><span style="background-color: #C5D3F6">[survey2020(1)]</span> Munea, Tewodros Legesse, et al. “The progress of human pose estimation: A survey and taxonomy of models applied in 2D human pose estimation.” <em>IEEE Access</em> 8 (2020): 133330-133348.</li>
  <li><span style="background-color: #C5D3F6">[survey(2022)]</span> Lan, Gongjin, et al. “Vision-Based Human Pose Estimation via Deep Learning: A Survey.” <em>IEEE Transactions on Human-Machine Systems</em> (2022).</li>
  <li>DeepLearningAI (Andrew Ng), “<a href="https://www.youtube.com/watch?v=ImUoubi_t7s">What is end-to-end deep learning? (C3W2L09)</a>”</li>
  <li>DeepLearningAI (Andrew Ng), “<a href="https://www.youtube.com/watch?v=l_-CUyEx_x4">Whether to Use End-To-End Deep Learning (C3W2L10)</a>”</li>
</ul>]]></content><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><category term="AI" /><category term="Computer Vision" /><category term="Deep Learning" /><category term="Computer Vision" /><category term="Human Pose Estimation" /><summary type="html"><![CDATA[Representations of Human Pose and Approaches of HPE]]></summary></entry><entry><title type="html">[HPE] Human Pose Estimation Task 소개: Introduction, Application, Challenges</title><link href="https://winterbloooom.github.io/hpe_task/" rel="alternate" type="text/html" title="[HPE] Human Pose Estimation Task 소개: Introduction, Application, Challenges" /><published>2023-02-15T00:00:00+09:00</published><updated>2023-02-15T00:00:00+09:00</updated><id>https://winterbloooom.github.io/hpe_task</id><content type="html" xml:base="https://winterbloooom.github.io/hpe_task/"><![CDATA[<div id="inserted-box">
    <div class="notice-text"><p>HPE 시리즈는 현재 필자가 연구(공부)하는 주제로, 이와 관련된 이론 및 논문들을 소개할 예정입니다.</p></div>
</div>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/218929973-7ad98a62-8830-4265-a0bf-d672f5712eba.png" />
<figcaption>Kaiming He et al, "Mask R-CNN", ICCV 2017</figcaption>
</figure>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/218930869-05532411-3169-41a4-bb1f-b0c8f5274d67.png" />
<figcaption>Zhe Cao et al, "Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields", CVPR 2017</figcaption>
</figure>

<h1 id="introduction-of-hpe-task">Introduction of HPE Task</h1>

<p><span style="background-color: #C5D3F6">Human Pose Estimation</span>은 말 그대로 사람의 자세를 추정하는 일이다. 축약해 HPE라고 부른다.</p>

<p>다른 말로는 <span style="background-color: #C5D3F6">Keypoint Detection</span>이라고도 한다. 자세를 추정할 때 각 관절(joint, part) 위치를 찾는데, 이때 이 joint나 part를 keypoint(키포인트)라고 하기 때문이다. 위 사진들은 각 관절을 선으로 연결해놓았지만, 실질적으로 이 task를 수행할 때는 관절 위치만 찾으면 된다.</p>

<div id="def-box">
<div class="def-title">자주 사용하는 용어 정리</div>
<div style="line-height: 1.6rem">

    <ul>
      <li>Human Pose Estimation (abbr. ‘HPE’ 혹은 ‘PE’) : 사람의 자세를 추정하는 일을 말한다.</li>
      <li>Keypoint (abbr. ‘kpt’) : 키포인트. 관절(joint)을 말한다.</li>
      <li>Instance : 인스턴스. 각 사람 하나를 말한다. 자세를 추정할 때 각 사람별로 정확한 관절들을 찾아내야 한다.</li>
    </ul>

  </div>
</div>

<p>HPE는 <span style="background-color: #C5D3F6">주어진 사진 혹은 비디오에서 그 안에 있는 모든 사람들의 관절(e.g. 팔꿈치, 손목 등)의 위치를 정확히 탐지한다.</span></p>

<hr />

<h1 id="application">Application</h1>

<p>HPE는 사람의 이해(human understanding)에 중요한 역할을 한다. HPE 자체도 연구 분야이지만, HPE를 활용한 다른 task나 활용 분야가 매우 많다.</p>

<p>대표적으로 <span style="background-color: #C5D3F6">행동 분석(action analysis), 보행자 추적(pedestrain tracking) 및 re-identification, Human-Computer Interaction(HCI), 게임, 의료 활용, 스포츠 분석, 애니메이션 및 CGI, VR 및 AR 등</span>에 사용된다. 및에선 구체적 몇 가지 사례를 들어본다.</p>

<h2 id="animation-cgi-vr--ar">Animation, CGI, VR &amp; AR</h2>

<p>오래된 애니메이션 영화를 떠올려보면, 영화를 제작하기 위해서는 프레임 단위로 직접 그림을 그려 영상을 완성했다. 이는 비용도 많이 들고 시간도 많이 소모된다.</p>

<p>그러나 HPE은 해당 작업을 크게 바꿔놓았다. 사람(performer)의 움직임을 캐릭터로 전이(transfer)시켜서 애니메이션을 만드는 것이다. 이는 가상현실(Virtual Reality)나 증강현실(Augmented Reality)에도 유용하여, HPE에서 얻은 골격(skeleton) 정보로부터 3D 애니메이션을 만들어낼 수도 있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/218938535-71535484-f47f-46cd-bb43-9d138796beb0.png" width="50%" />
<figcaption>Dong-Hyun Hwang et al, "Lightweight 3D Human Pose Estimation Network Training Using Teacher-Student Learning", WACV 2020</figcaption>
</figure>

<p>영화 및 드라마 산업에서 CGI(Computer Generated Imagery, 컴퓨터 생성 이미지)는 매우 자주 쓰이지만 굉장히 비싼 작업이다. 마블(Marvel) 사의 어벤저스(Avergers) 시리즈만 보아도 거의 대부분이 CG라 해도 과언이 아니다. 제작 과정을 담은 비디오를 보면, 배우들이 특별 수트나 마스크를 작용해 움직임을 포착한다. HPE를 더 이용하면 2D에서도 키포인트를 추출해 3D 렌더링을 시킬 수도 있다.</p>

<h2 id="sports">Sports</h2>

<p>스포츠에서 경기를 분석할 때 주로 사진이나 비디오를 찍어 천천히 돌려보면서 자세, 전략 등을 분석하곤 한다. 그러나 이를 HPE와 결합하면 자동적으로 자세와 움직임 분석이 가능하고 더 나아가 적당한 개선 방향도 제시할 수 있다. 상대 선수의 강점과 약점을 분석하기도 용이하다.</p>

<p>시범자(instructor)와 학습자(learner)의 자세를 비교해 어딜 어떻게 교정해야 하는지도 알 수 있으며, 범용적 어플리케이션으로 만든다면 전문 선수나 트레이너가 아니더라도 분석을 할 수 있고 분석을 받을 수 있다.</p>

<p>골프, 테니스, 요가 등 다양한 운동 종목에 이미 적용이 시작되고 있다. 아래 GIF는 AI 요가 앱인 Zenia의 예이다. 카메라를 통해 사용자의 자세를 탐지하고, 정확한 자세로 교정해준다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/218943469-355cea85-1d0e-483d-be85-aa761e59bd49.gif" width="60%" />
<figcaption>Zenia Instagram</figcaption>
</figure>

<p>아래는 골프 자세 교정을 위한 논문의 예시이다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/218949733-3ef35379-8bbd-4241-a11c-142d2e00aa83.png" width="70%" />
<figcaption>"Accurate and efficient 3D human pose estimation algorithm using single depth images for pose analysis in golf", CVPR 2017</figcaption>
</figure>

<p>이러한 분석은 전문 선수와 일반인의 스포츠 중 부상을 방지하는 효과를 가져올 수 있다.</p>

<h2 id="human-computer-interactionhci">Human-Computer Interaction(HCI)</h2>

<p>전통적 HCI 기술은 직접 만질 수 있는 기기나 인터페이스를 통해 이루어졌다. 예를 들자면 마우스나 키보드, 터치스크린 등이다. 그러나 HPE를 적용한다면 접촉 없이도 카메라를 통해 조종이 가능해진다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/218944786-7ef7480c-1578-4f79-a825-b6fffe392e4e.png" width="70%" />
<figcaption>Spider-Man: Far from Home(2019)</figcaption>
</figure>

<p>아이언맨이나 스파이더맨 등의 영화를 보면 허공에서 손을 움직여 기기를 작동시키는 등의 일을 한다. 이 작업은 사람의 손가락 움직임을 탐지하는 것에서 시작한다.</p>

<p>이는 영화 속 기술만은 아니다. 예술과 게임, 가상현실에 이미 적용이 되고 있다. 아래 사진과 같이 Microsoft Kinect 를 활용해 게임을 할 수 있다. 상호작용하는 게임 경험을 제공하는 것이다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/218946195-eb97276c-05ca-434e-82d2-70d265e51706.png" width="70%" />
<figcaption>yahoo finance, "The rise and fall of Kinect: Why Microsoft gave up on its most promising product"</figcaption>
</figure>

<h2 id="medical--clinical-applications">Medical &amp; Clinical Applications</h2>

<p>환자나 노인의 경우 보호자가 항시 주시하고 있을 순 없는데, 이때 HPE 기술을 활용해 모니터링을 실시할 수 있다. 혹은 재활 치료에도 도움이 될 수 있는데, 이는 위에서 소개한 스포츠 코칭과 상당히 유사하게 작동한다.</p>

<p>혹은 아이의 움직임 분석에 사용할 수도 있다. 아이가 근육, 관절, 신경계 등 신체 문제를 가지고 있을 때 움직임에 이상을 보인다. 이러한 아이의 성장 행동, 물리적 발달 과정을 분석할 수 있다. 의료 지식이 없는 부모가 해당 기술을 통해 아이의 움직임으로부터 미묘한 이상(anomalies)을 알아내 의사에게 적절한 치료를 받도록 한다.</p>

<h2 id="그-외">그 외</h2>

<p>위에서 열거한 예시는 일부일 뿐이다.</p>

<p>자율주행, ADAS(advanced driver assistance systems)에서도 HPE는 유용하여, 차량에 탑승한 운전자나 동승자의 움직임을 알 수도 있고, 보행자의 움직임을 추적할 수도 있다.</p>

<p>스마트 관제 시스템(surveillance system)은 노인 모니터링을 통해 위험한 활동에 경고를 해주거나, 건설 인부들의 위험 행동을 모니터링 할 수 있다.</p>

<p>전체 자세 뿐만 아니라 손이나 얼굴 등 세부 포즈 추정 분야도 존재한다. 일례로 팔과 손가락 탐지를 통해 수화를 분석할 수 있다.</p>

<hr />

<h1 id="challenges">Challenges</h1>

<h2 id="occlusion--truncation">Occlusion &amp; Truncation</h2>

<p>여타 컴퓨터 비전 task에서 공통적으로 골머리를 앓는 것이 <span style="background-color: #C5D3F6">occlusion, 즉 가려짐 문제</span>이다. 3차원 정보가 없을 땐 오직 2차원 평면에서만 추론을 수행해야 하는데, 한 물체가 다른 물체에 가려져 있으면 가려진 부분은 추론이 힘들기 때문이다.</p>

<p>HPE 역시 마찬가지다. 이미지에서 두 사람의 일부가 겹쳐있다고 생각해보자. A의 손목이 B에 의해 가려졌다면 A의 손목은 이미지에서 보이지 않으므로 정확한 위치를 찾는 것이 힘들어진다. 즉 Reconstruction ambiguity를 발생시킨다. 특히 이 문제는 사람이 많은 상황(crowd)에서 빈번하고 심각하게 발생한다.</p>

<p>아래 사진처럼 앞 사람이 뒷 사람의 몸통을 거의 다 가리고 있을 때 뒷 사람의 정확한 관절 위치를 예측하기란 매우 어렵다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/219265164-aa3c0d83-4cd2-4544-9dde-389593cd5de8.jpg" width="50%" />
<figcaption>Image from CrowdPose dataset</figcaption>
</figure>

<p>가려짐 뿐만 아니라 잘림(truncation)도 문제다. 상반신만 나온 사진에서 억지로 발목을 찾으려 하면 문제가 된다.</p>

<h2 id="multiple-people-crowd-scenes">Multiple people, Crowd Scenes</h2>

<p><span style="background-color: #C5D3F6">이미지 내에는 여러 명의 사람이 존재하며, 정확히 몇 명이 존재하는지도 알지 못한다.</span> 그럼에도 그들 모두를 탐지해야 한다. 뿐만 아니라 그들의 크기와 위치도 제각각이다.</p>

<p>현존하는 모델들은 매우 좋은 성능을 보여주고는 있으나, 군중(crowd) 상황에서 성능이 급격하게 떨어진다. 다수의 사람이 참여하는 게임 혹은 스포츠 분석에서는 사람의 수에 관계 없이 강인상 성능을 가지는 모델이 필요하다. 하여 최근 논문들은 군중 상황을 담은 데이터셋(e.g. CrowdPose dataset)을 통해 성능 검증을 추가적으로 수행하고 있기도 하다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/219264363-5c44f265-3a28-479b-9921-ccc2158938fd.jpg" width="60%" />
<figcaption>Image from CrowdPose dataset</figcaption>
</figure>

<h2 id="interactions-between-people">Interactions between people</h2>

<p>사진 속 사람들은 물체 혹은 다른 사람들과 상호작용을 한다. 악수나 포옹, 운동 등 우리 일상을 상기해보자. 이러한 상호작용으로 인해 사진에서 보았을 땐 사람 간의 접촉이나 가려짐(occlusion)이 발생한다. HPE에서 특히 문제가 되는 가려짐 역시 사람이 많거나 가까운 상호작용이 발생할 때 빈번하게 나타난다(mutual occlusion). <span style="background-color: #C5D3F6">사람 간의 상호작용</span>이 있는 사진은 공간적 추론을 매우 복잡하게 만든다. 각 사람의 신체 부위를 나누고 할당하기(Part association)가 어려우며, 연산 복잡도가 증가한다.</p>

<h2 id="runtime-complexity">Runtime complexity</h2>

<p>이미지 내 사람이 많은 것은 정확도에만 영향을 주는 것이 아니다. 특히 문제가 되는 부분은 연산 시간(inference time)이다.</p>

<p><span style="background-color: #C5D3F6">연산 시간은 이미지 내 사람의 수에 비례해 증가한다.</span> 뒤에 이어질 포스팅에서 자세히 설명하겠지만, two-stage 방법들은 어떤 모델을 쓰든 추가적 단계가 필요한데 이 단계들이 사람 수에 따라 연산을 증가시킨다.</p>

<p>사람을 탐지하고 개별적 바운딩박스에서 HPE를 수행하는 Top-down methods는, 탐지 단계(detection)도 필요할 뿐더러 사람의 수만큼 HPE를 수행해야 한다. 만약 이미지 내 사람이 100명이면 100번 개별적 HPE를 수행해야 하는 것이다.</p>

<p>모든 관절들을 다 탐지한 뒤 개개인의 관절 주인을 찾아주는 Bottom-up methods는, 키포인트 간의 유사도 값을 계산하고 이를 매칭 알고리즘으로 그룹핑(grouping)해야 한다. 만약 이미지 내 사람이 100명이고 탐지된 관절 개수가 1,000개라면 각 1,000개를 100명에게 나눠주는(그룹핑) 작업이 필요한 것이다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/219264852-cf2769cd-7a0b-4623-be6e-fdb87583fe43.png" width="90%" />
<figcaption>Zheng, C. et al, "Deep learning-based human pose estimation: A survey," arXiv (2020)</figcaption>
</figure>

<p>이러한 복잡성은 HPE를 <span style="background-color: #C5D3F6">실시간으로 작동하게 하는(realtime inference) 데 큰 걸림돌이 되고 있으며, 리소스가 제한된(resource-limited) 디바이스에서 수행이 힘든 이유</span>가 된다.</p>

<h2 id="efficiency">Efficiency</h2>

<p>앞 내용과 이어지는 주제다. HPE는 연산 비용이 높은 task이다. 그래서 추론 지연(inference delay)도 빈번하게 발생한다. 따라서 모바일 디바이스, 임베디드 디바이스로의 탑재가 힘들다. 그래서 정확도를 높이려는 시도 뿐만 아니라, 가볍고 효율적인 신경망을 디자인하려는 시도가 계속되고 있다.</p>

<h2 id="wide-diversity-of-human-body">Wide diversity of human body</h2>

<p>추론을 해야 하는 사진은 깔끔한 배경이 아닌 잔디밭, 교실, 집, 쇼핑몰 등 다양한 환경이 있을 수 있고, 흐린 날이나 비가 오는 날, 자외선이 심한 날, 인공 조명 아래 등 조명 조건(illumination conditions)도 다를 수 있다. 이미지 자체에 흐려짐(blur)가 발생하거나 초점이 사라질(defocus) 수도 있다. 이런 다양한 상황들은 HPE 뿐만 아니라 다른 컴퓨터 비전 task에서도 문제가 되는 부분이다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/219263207-a2d39e03-4779-4128-a01f-059ce8821198.jpg" width="60%" />
<figcaption>Image froom CrowdPose dataset</figcaption>
</figure>

<p>뿐만 아니라 HPE에서 처리해야 하는 사람에겐 더 많은 어려움이 있다.</p>

<p>일단, 사진 내 <span style="background-color: #C5D3F6">사람은 다양한 의상을 입고 있다</span>. 예를 들어, 펑퍼짐한 의상이나 풍성한 치마일 경우 정확한 관절 위치를 찾기 힘들다.</p>

<p>또한 <span style="background-color: #C5D3F6">사람의 몸은 매우 큰 자유도(high degree of freedom)을 가지고 있어 변형 가능성이 매우 높다(high deformable)</span>. 쉽게 말해, 관절을 자유자재로 움직여 셀 수 없이 다양한 포즈를 가질 수 있단 의미이다. 리듬체조를 떠올려 보자. 사람이 어떻게 저렇게 몸을 만드나 싶을 정도로 기괴한 자세도 가능하다. 따라서 정해진 몇 가지 템플릿으로 추정하는 일은 불가하며, 그래서 추론 복잡성도 그에 따라 증가한단 의미다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/219249548-839a5802-6891-425f-81bd-25f4f985d025.jpg" width="60%" />
<figcaption>Image by Katie Bush from Unsplash</figcaption>
</figure>

<h2 id="biased-dataset">Biased dataset</h2>

<p>신경망을 학습시키기 위해선 데이터셋이 필요하다. 물론 HPE를 위한 다양한 데이터셋이 존재하나, 데이터셋에도 HPE가 넘어야 할 산이 있다.</p>

<p>일단, 흔하지 않게 발생하는 자세가 잘 없다. 서 있거나 앉아 있는 일상적 상황이 대다수이고, 상공에서 낙하하는 자세나 복잡한 자세는 데이터셋에 많이 없다.</p>

<p>이런 <span style="background-color: #C5D3F6">편향된 데이터셋(biased dataset)은 불균형적 학습 문제(imbalanced learning problem)</span>를 야기한다. 그럼 모델은 희귀한 상황에 대한 대처를 학습하지 못하고, 실제 적용 시에 큰 에러가 발생할 수 있다.</p>

<p>3차원으로 가면 상황은 더 심각해진다. 단순한 annotation을 수행하면 되는 2차원과는 다르게, 정확한 공간 정보가 필요한 <span style="background-color: #C5D3F6">3차원 데이터셋을 만들기 위해서는 다양한 시점에서 본 카메라(multi-view cameras)나 신체 부작 센서들(IMU 등)을 갖춘 실험실 환경이 필요</span>하다. 따라서 야외 환경에 대한 3차원 데이터셋이 거의 전무하고 있다 해도 불완전하다. 불완전한 데이터셋으로 학습한 모델은 잘 작동하지 못하므로, 3차원 HPE의 실제 적용은 요원한 일이 된다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/219263040-59f96942-b929-4168-bc88-7fb0cd2522e3.png" width="80%" />
<figcaption>CMU Panoptic Studio</figcaption>
</figure>

<p>물론 semi-supervised learning(준지도학습) 등을 활용하거나 합성 데이터셋(synthetic dataset)을 이용하는 방법도 존재는 하지만, 여전히 일정량의 데이터셋이 필요하거나 전이학습(transfer learning)이 제대로 이루어지지 않는 한계가 있다.</p>

<h2 id="3d-hpe">3D HPE</h2>

<p>앞서 꼬집은 것처럼, 3차원 HPE는 데이터셋 자체도 불완전해 <span style="background-color: #C5D3F6">야외 환경에서 특히 작동이 힘들다</span>. 뿐만 아니라 추론해야 할 정보도 많아서 edge-device에서 실시간 추론이 잘 안되는 것도 문제다.</p>

<p>따라서 깊이(depth) 정보를 추가적으로 얻어 HPE에 사용하는 등 다양한 시도가 수행되고 있으며, 3D HPE를 빠르고 효율적으로 해내는 것도 추후의 과제다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/219263854-0946df1b-998e-4b1a-8f2d-961a643bea04.png" width="90%" />
<figcaption>Xiao, Yabo, et al. "AdaptivePose++: A Powerful Single-Stage Network for Multi-Person Pose Regression." arXiv(2022)</figcaption>
</figure>

<hr />

<h1 id="references">References</h1>

<div id="inserted-box">
    <div class="notice-text"><p>HPE 시리즈에서 사용하는 모든 레퍼런스는 한꺼번에 <a href="/hpe_ref/">[HPE] Human Pose Estimation References</a>에 모아두었다.</p></div>
</div>

<ul>
  <li><span style="background-color: #C5D3F6">[PETR(2022)]</span> Shi, Dahu, et al. “End-to-end multi-person pose estimation with transformers.” <em>Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition</em>. 2022.</li>
  <li><span style="background-color: #C5D3F6">[SPM(2019)]</span> Nie, Xuecheng, et al. “Single-stage multi-person pose machines.” <em>Proceedings of the IEEE/CVF international conference on computer vision</em>. 2019.</li>
  <li><span style="background-color: #C5D3F6">[CMU-Pose(2017)]</span> Cao, Zhe, et al. “Realtime multi-person 2d pose estimation using part affinity fields.” <em>Proceedings of the IEEE conference on computer vision and pattern recognition</em>. 2017.</li>
  <li><span style="background-color: #C5D3F6">[HRNet(2019)]</span> Sun, Ke, et al. “Deep high-resolution representation learning for human pose estimation.” <em>Proceedings of the IEEE/CVF conference on computer vision and pattern recognition</em>. 2019.</li>
  <li><span style="background-color: #C5D3F6">[survey2020(1)]</span> Munea, Tewodros Legesse, et al. “The progress of human pose estimation: A survey and taxonomy of models applied in 2D human pose estimation.” <em>IEEE Access</em> 8 (2020): 133330-133348.</li>
  <li><span style="background-color: #C5D3F6">[survey(2022)]</span> Lan, Gongjin, et al. “Vision-Based Human Pose Estimation via Deep Learning: A Survey.” <em>IEEE Transactions on Human-Machine Systems</em> (2022).</li>
  <li><span style="background-color: #C5D3F6">[v7labs-HPE]</span> <a href="https://www.v7labs.com/blog/human-pose-estimation-guide">A Comprehensive Guide to Human Pose Estimation</a></li>
</ul>]]></content><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><category term="AI" /><category term="Computer Vision" /><category term="Deep Learning" /><category term="Computer Vision" /><category term="Human Pose Estimation" /><summary type="html"><![CDATA[Human Pose Estimation task introduction, applications, and challenges]]></summary></entry><entry><title type="html">[HPE] Human Pose Estimation References</title><link href="https://winterbloooom.github.io/hpe_ref/" rel="alternate" type="text/html" title="[HPE] Human Pose Estimation References" /><published>2023-02-14T00:00:00+09:00</published><updated>2023-02-14T00:00:00+09:00</updated><id>https://winterbloooom.github.io/hpe_ref</id><content type="html" xml:base="https://winterbloooom.github.io/hpe_ref/"><![CDATA[<div id="inserted-box">
    <div class="notice-text"><p>해당 포스트는 HPE Series의 모든 레퍼런스를 모아놓았습니다. (<strong>Last Update: 2023.02.23.</strong>)</p></div>
</div>

<h1 id="논문">논문</h1>

<h2 id="hpe">HPE</h2>

<p><span style="background-color: #C5D3F6">[DeepPose(2014)]</span> Toshev, Alexander, and Christian Szegedy. “Deeppose: Human pose estimation via deep neural networks.” <em>Proceedings of the IEEE conference on computer vision and pattern recognition</em>. 2014.</p>

<p><span style="background-color: #C5D3F6">[ConvNet(2015)]</span> Tompson, Jonathan, et al. “Efficient object localization using convolutional networks.” <em>Proceedings of the IEEE conference on computer vision and pattern recognition</em>. 2015.</p>

<p><span style="background-color: #C5D3F6">[CPM(2016)]</span> Wei, Shih-En, et al. “Convolutional pose machines.” <em>Proceedings of the IEEE conference on Computer Vision and Pattern Recognition</em>. 2016.</p>

<p><span style="background-color: #C5D3F6">[DeepCut(2016)]</span> Insafutdinov, Eldar, et al. “Deepercut: A deeper, stronger, and faster multi-person pose estimation model.” <em>Computer Vision–ECCV 2016: 14th European Conference, Amsterdam, The Netherlands, October 11-14, 2016, Proceedings, Part VI 14</em>
. Springer International Publishing, 2016.</p>

<p><span style="background-color: #C5D3F6">[StackedHourglass(2016)]</span> Newell, Alejandro, Kaiyu Yang, and Jia Deng. “Stacked hourglass networks for human pose estimation.” <em>Computer Vision–ECCV 2016: 14th European Conference, Amsterdam, The Netherlands, October 11-14, 2016, Proceedings, Part VIII 14</em>. Springer International Publishing, 2016.</p>

<p><span style="background-color: #C5D3F6">[CMU-Pose(2017)]</span> Cao, Zhe, et al. “Realtime multi-person 2d pose estimation using part affinity fields.” <em>Proceedings of the IEEE conference on computer vision and pattern recognition</em>. 2017.</p>

<p><span style="background-color: #C5D3F6">[AssociatedEmbedding(2017)]</span> Newell, Alejandro, Zhiao Huang, and Jia Deng. “Associative embedding: End-to-end learning for joint detection and grouping.” <em>Advances in neural information processing systems</em> 30 (2017).</p>

<p><span style="background-color: #C5D3F6">[RMPE(2017)]</span> Fang, Hao-Shu, et al. “Rmpe: Regional multi-person pose estimation.” <em>Proceedings of the IEEE international conference on computer vision</em>. 2017.</p>

<p><span style="background-color: #C5D3F6">[MaskR-CNN(2017)]</span> He, Kaiming, et al. “Mask r-cnn.” <em>Proceedings of the IEEE international conference on computer vision</em>. 2017.</p>

<p><span style="background-color: #C5D3F6">[CPN(2018)]</span> Chen, Yilun, et al. “Cascaded pyramid network for multi-person pose estimation.” <em>Proceedings of the IEEE conference on computer vision and pattern recognition</em>. 2018.</p>

<p><span style="background-color: #C5D3F6">[PersonLab(2018)]</span> Papandreou, George, et al. “Personlab: Person pose estimation and instance segmentation with a bottom-up, part-based, geometric embedding model.” <em>Proceedings of the European conference on computer vision (ECCV)</em>. 2018.</p>

<p><span style="background-color: #C5D3F6">[SimpleBaseline(2018)]</span> Xiao, Bin, Haiping Wu, and Yichen Wei. “Simple baselines for human pose estimation and tracking.” <em>Proceedings of the European conference on computer vision (ECCV)</em>. 2018.</p>

<p><span style="background-color: #C5D3F6">[OpenPose(2019)]</span> Cao, Zhe, et al. “OpenPose: Realtime Multi-Person 2D Pose Estimation Using Part Affinity Fields.” <em>IEEE Transactions on Pattern Analysis and Machine Intelligence</em> 43.1 (2019): 172-186.</p>

<p><span style="background-color: #C5D3F6">[PifPaf(2019)]</span> Kreiss, Sven, Lorenzo Bertoni, and Alexandre Alahi. “Pifpaf: Composite fields for human pose estimation.” <em>Proceedings of the IEEE/CVF conference on computer vision and pattern recognition</em>. 2019.</p>

<p><span style="background-color: #C5D3F6">[SPM(2019)]</span> Nie, Xuecheng, et al. “Single-stage multi-person pose machines.” <em>Proceedings of the IEEE/CVF international conference on computer vision</em>. 2019.</p>

<p><span style="background-color: #C5D3F6">[HRNet(2019)]</span> Sun, Ke, et al. “Deep high-resolution representation learning for human pose estimation.” <em>Proceedings of the IEEE/CVF conference on computer vision and pattern recognition</em>. 2019.</p>

<p><span style="background-color: #C5D3F6">[DirectPose(2019)]</span> Tian, Zhi, Hao Chen, and Chunhua Shen. “Directpose: Direct end-to-end multi-person pose estimation.” <em>arXiv preprint arXiv:1911.07451</em> (2019).</p>

<p><span style="background-color: #C5D3F6">[HigherHRNet(2020)]</span> Cheng, Bowen, et al. “Higherhrnet: Scale-aware representation learning for bottom-up human pose estimation.” <em>Proceedings of the IEEE/CVF conference on computer vision and pattern recognition</em>. 2020.</p>

<p><span style="background-color: #C5D3F6">[survey2020(1)]</span> Munea, Tewodros Legesse, et al. “The progress of human pose estimation: A survey and taxonomy of models applied in 2D human pose estimation.” <em>IEEE Access</em> 8 (2020): 133330-133348.</p>

<p><span style="background-color: #C5D3F6">[Point-setAnchors(2020)]</span> Wei, Fangyun, et al. “Point-set anchors for object detection, instance segmentation and pose estimation.” <em>Computer Vision–ECCV 2020: 16th European Conference, Glasgow, UK, August 23–28, 2020, Proceedings, Part X 16</em>. Springer International Publishing, 2020.</p>

<p><span style="background-color: #C5D3F6">[PRTR(2021)]</span> Li, Ke, et al. “Pose recognition with cascade transformers.” <em>Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition</em>. 2021.</p>

<p><span style="background-color: #C5D3F6">[TFPose(2021)]</span> Mao, Weian, et al. “Tfpose: Direct human pose estimation with transformers.” <em>arXiv preprint arXiv:2103.15320</em> (2021).</p>

<p><span style="background-color: #C5D3F6">[PRTR(2021)]</span> Li, Ke, et al. “Pose recognition with cascade transformers.” <em>Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition</em>. 2021.</p>

<p><span style="background-color: #C5D3F6">[InsPose(2021)]</span> Shi, Dahu, et al. “Inspose: instance-aware networks for single-stage multi-person pose estimation.” <em>Proceedings of the 29th ACM International Conference on Multimedia</em>. 2021.</p>

<p><span style="background-color: #C5D3F6">[FCPose(2021)]</span> Mao, Weian, et al. “Fcpose: Fully convolutional multi-person pose estimation with dynamic instance-aware convolutions.” <em>Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition</em>. 2021.</p>

<p><span style="background-color: #C5D3F6">[PoseDet(2021)]</span> Tian, Chenyu, et al. “Posedet: fast multi-person pose estimation using pose embedding.” <em>2021 16th IEEE International Conference on Automatic Face and Gesture Recognition (FG 2021)</em>. IEEE, 2021.</p>

<p><span style="background-color: #C5D3F6">[PETR(2022)]</span> Shi, Dahu, et al. “End-to-end multi-person pose estimation with transformers.” <em>Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition</em>. 2022.</p>

<p><span style="background-color: #C5D3F6">[survey(2022)]</span> Lan, Gongjin, et al. “Vision-Based Human Pose Estimation via Deep Learning: A Survey.” <em>IEEE Transactions on Human-Machine Systems</em> (2022).</p>

<p><span style="background-color: #C5D3F6">[AdaptivePose(2022)]</span> Xiao, Yabo, et al. “Adaptivepose: Human parts as adaptive points.” <em>Proceedings of the AAAI Conference on Artificial Intelligence</em>. Vol. 36. No. 3. 2022.</p>

<hr />

<h2 id="others">Others</h2>

<p><span style="background-color: #C5D3F6">[Transformer(2017)]</span> Vaswani, Ashish, et al. “Attention is all you need.” <em>Advances in neural information processing systems</em> 30 (2017).</p>

<p><span style="background-color: #C5D3F6">[CenterNet(2019)]</span> Zhou, Xingyi, Dequan Wang, and Philipp Krähenbühl. “Objects as points.” <em>arXiv preprint arXiv:1904.07850</em> (2019).</p>

<p><span style="background-color: #C5D3F6">[DETR(2020)]</span> Carion, Nicolas, et al. “End-to-end object detection with transformers.” <em>Computer Vision–ECCV 2020: 16th European Conference, Glasgow, UK, August 23–28, 2020, Proceedings, Part I 16</em>. Springer International Publishing, 2020.</p>

<p><span style="background-color: #C5D3F6">[DeformableDETR(2020)]</span> Zhu, Xizhou, et al. “Deformable detr: Deformable transformers for end-to-end object detection.” <em>arXiv preprint</em> arXiv:2010.04159 (2020).</p>

<p><span style="background-color: #C5D3F6">[SwinTransformer(2021)]</span> Liu, Ze, et al. “Swin transformer: Hierarchical vision transformer using shifted windows.” <em>Proceedings of the IEEE/CVF international conference on computer vision</em>. 2021.</p>

<hr />

<h1 id="datasets">Datasets</h1>
<ul>
  <li><span style="background-color: #C5D3F6">[LSP]</span> Leeds Sports Pose
    <ul>
      <li><a href="http://www.bmva.org/bmvc/2010/conference/paper12/paper12.pdf">Paper: Clustered Pose and Nonlinear Appearance Models for Human Pose Estimation</a></li>
      <li><a href="https://paperswithcode.com/dataset/lsp">paperswithcode</a></li>
      <li><a href="https://dbcollection.readthedocs.io/en/latest/datasets/leeds_sports_pose.html">dbcollection</a></li>
    </ul>
  </li>
  <li><span style="background-color: #C5D3F6">[LSPe]</span> Leeds Sports Pose Extended
    <ul>
      <li><a href="https://dbcollection.readthedocs.io/en/latest/datasets/leeds_sports_pose_extended.html">dbcollection</a></li>
    </ul>
  </li>
  <li><span style="background-color: #C5D3F6">[FLIC]</span> Frames Labeled In Cinema
    <ul>
      <li><a href="https://openaccess.thecvf.com/content_cvpr_2013/papers/Sapp_MODEC_Multimodal_Decomposable_2013_CVPR_paper.pdf">Paper: MODEC: Multimodal Decomposable Models for Human Pose Estimation</a></li>
      <li><a href="https://paperswithcode.com/dataset/flic">paperswithcode</a></li>
      <li><a href="https://dbcollection.readthedocs.io/en/latest/datasets/flic.html">dbcollection</a></li>
    </ul>
  </li>
  <li><span style="background-color: #C5D3F6">[PASCAL VOC]</span> PASCAL VOC (PASCAL Visual Object Classes Challenge)
    <ul>
      <li><a href="http://host.robots.ox.ac.uk/pascal/VOC/index.html">Official Homepage</a></li>
      <li><a href="https://arxiv.org/pdf/2012.07131v2.pdf">Paper: Location-aware Single Image Reflection Removal</a></li>
      <li><a href="https://paperswithcode.com/dataset/pascal-voc">paperswithcode</a></li>
      <li><a href="https://dbcollection.readthedocs.io/en/latest/datasets/pascal_voc2012.html">dbcollection</a></li>
    </ul>
  </li>
  <li><span style="background-color: #C5D3F6">[MS-COCO Keypoint Detection]</span> Microsoft Common Objects in Context
    <ul>
      <li><a href="https://cocodataset.org/#keypoints-2020">Official Homepage</a></li>
      <li><a href="https://arxiv.org/pdf/1405.0312v3.pdf">Paper: Microsoft COCO: Common Objects in Context</a></li>
      <li><a href="https://paperswithcode.com/dataset/coco">paperswithcode</a></li>
      <li><a href="https://dbcollection.readthedocs.io/en/latest/datasets/coco.html">dbcollection</a></li>
    </ul>
  </li>
  <li><span style="background-color: #C5D3F6">[MPII]</span> Max Planck Institute for Informatics
    <ul>
      <li><a href="http://human-pose.mpi-inf.mpg.de/">Official Homepage</a></li>
      <li><a href="https://openaccess.thecvf.com/content_cvpr_2014/papers/Andriluka_2D_Human_Pose_2014_CVPR_paper.pdf">Paper: 2D Human Pose Estimation: New Benchmark and State of the Art Analysis</a></li>
      <li><a href="https://paperswithcode.com/dataset/mpii">paperswithcode</a></li>
      <li><a href="https://dbcollection.readthedocs.io/en/latest/datasets/mpii_pose.html">dbcollection</a></li>
    </ul>
  </li>
  <li><span style="background-color: #C5D3F6">[CrowdPose]</span>
    <ul>
      <li><a href="https://github.com/Jeff-sjtu/CrowdPose">Official GitHub</a></li>
      <li><a href="https://arxiv.org/abs/1812.00324">Paper: CrowdPose: Efficient Crowded Scenes Pose Estimation and A New Benchmark</a></li>
      <li><a href="https://paperswithcode.com/dataset/crowdpose">paperswithcode</a></li>
    </ul>
  </li>
</ul>

<hr />

<h1 id="webpage">Webpage</h1>

<p><span style="background-color: #C5D3F6">[v7labs-HPE]</span> <a href="https://www.v7labs.com/blog/human-pose-estimation-guide">A Comprehensive Guide to Human Pose Estimation</a></p>]]></content><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><category term="AI" /><category term="Computer Vision" /><category term="Deep Learning" /><category term="Computer Vision" /><category term="Human Pose Estimation" /><summary type="html"><![CDATA[References of Human Pose Estimation Posting Series]]></summary></entry><entry><title type="html">Mathematics for Machine Learning 6.3장: 합/곱의 규칙, 베이즈 정리</title><link href="https://winterbloooom.github.io/math4ml_ch6_3/" rel="alternate" type="text/html" title="Mathematics for Machine Learning 6.3장: 합/곱의 규칙, 베이즈 정리" /><published>2023-02-04T00:00:00+09:00</published><updated>2023-02-04T00:00:00+09:00</updated><id>https://winterbloooom.github.io/math4ml_ch6_3</id><content type="html" xml:base="https://winterbloooom.github.io/math4ml_ch6_3/"><![CDATA[<div id="inserted-box">
    <div class="notice-text"><p>이 내용은 책 <a href="https://mml-book.github.io/book/mml-book.pdf">Mathematics for machine learning(Marc Peter Deisenroth et al.)</a>을 기반으로 하고 있습니다.</p></div>
</div>

<h1 id="63-sum-rule-product-rule-and-bayes-theorem">6.3. Sum Rule, Product Rule, and Bayes’ Theorem</h1>

<h2 id="sum-rule">Sum Rule</h2>

<p>확률 이론에서 합의 규칙(sum rule)이란, 어떤 확률변수의 상태들의 집합을 더하면(적분하면) 확률이 된다는 것이다.</p>

\[p(\boldsymbol{x}) = 
\begin{cases}
  \sum \limits_{\boldsymbol{y} \in \mathcal{y}} p(\boldsymbol{x, y}) &amp; \mathrm{if} \ \boldsymbol{y} \ \mathrm{is \ discrete} \\
  \int_{\mathcal{y}} p(\boldsymbol{x, y}) d \boldsymbol{y} &amp; \mathrm{if} \ \boldsymbol{y} \ \mathrm{is \ continuous}
\end{cases} \tag{1}\]

<p>위 식에서 $\mathcal{y}$ 는 확률변수 Y의 target space의 상태들을 말한다.</p>

<p>합의 규칙을 다른 말로는 ‘marginalization property’라고도 부른다. 주변 확률을 합으로 나타낼 수 있기 때문이다. 이는 아래의 설명에서 이해할 수 있다.</p>

<p>합의 규칙은 결합 분포를 주변 분포와 연결시키기도 한다. 2종류 이상의 확률 변수를 가진 결합 분포가 있다 할 때, 합의 규칙은 어떤 확률 변수의 부분집합에도 적용될 수 있다. 그 결과가 하나 이상의 확률 변수의 주변 분포가 된다. 식으로 표현하자면, $\boldsymbol{x} = [x_1, \cdots, x_D]^T$ 가 있을 때 marginal(주변 확률)은 아래와 같이 얻는다. 즉, $x_i$를 제외하고 모든 확률 변수에 대해 더하는 합의 규칙을 반복적으로 적용한다.</p>

\[p(x_i) = \int p(x_1, \cdots, x_D) d\boldsymbol{x}_{\backslash i}\]

<div id="inserted-box">
    <div class="notice-text"><p>$\backslash i$ 는 $i$ 를 제외하고 전부라는 뜻이다. (all except $i$ )</p></div>
</div>

<p>조금 더 친숙한 형태로 바꿔보자면, 주변 분포의 정의 상, 확률 변수 X와 Y가 있을 때 $X=x_i$ 일 확률은 가능한 모든 Y의 경우의 수 $Y=y_1, \cdots, y_L$ 를 다 합한 형태다.</p>

\[p(X=x_i) = \sum \limits_{j=1}^L p(X=x_i, Y=y_i)\]

<p>좌변은 주변확률인데 우변은 결합 확률이다. 그래서 주변 분포와 결합 분포를 연결한다고 표현한 것이다.</p>

<h2 id="product-rule">Product Rule</h2>

<p>합의 규칙이 ‘주변 분포’와 결합 분포를 연결시켰다면, 곱의 규칙은 ‘조건부 분포’와 결합 분포를 연결시킨다.</p>

\[\begin{aligned}
  p(\boldsymbol{x, y}) = &amp;p(\boldsymbol{y \vert x}) p(\boldsymbol{x}) = p(\boldsymbol{x \vert y}) p(\boldsymbol{y}) \\
  &amp;\left( \because p(\boldsymbol{y \vert x}) p(\boldsymbol{x}) = \cfrac{p(\boldsymbol{x, y})}{p(\boldsymbol{x})} p(\boldsymbol{x}) \right)
\end{aligned} \tag{2}\]

<p>따라서, 두 확률 변수의 결합 분포 $p(\boldsymbol{x, y})$ 는 서로 다른 두 분포 $p(\boldsymbol{y \vert x}) \ , \ p(\boldsymbol{x})$ 의 곱으로 분해될 수 있다. 하나는 첫 번째 확률 변수의 주변 분포 $p(\boldsymbol{x})$ 이고, 다른 하나는 첫 번째 확률변수가 주어졌을 때 두 번째 확률변수의 조건부 분포 $p(\boldsymbol{y \vert x})$ 이다. 결합 분포는 확률 변수의 순서에 관계가 없으니 위처럼 두 가지의 분해 경우가 나타난다.</p>

<h2 id="bayes-therom">Bayes’ Therom</h2>

<h3 id="바탕-지식">바탕 지식</h3>

<p>사과 한 알이 있고, 사과를 딴 곳이 영주, 안동, 청송, 예천, 안동, 문경 등이 있다고 하자. 아래와 같은 두 가지 조건부 확률을 고려해본다.</p>

<table>
  <thead>
    <tr>
      <th>사후 확률(posterior)</th>
      <th>우도(likelihood, 가능도)</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$P(안동\vert 사과)$</td>
      <td>$P(사과 \vert 안동)$</td>
    </tr>
    <tr>
      <td>사과를 딴 곳이 안동일 확률</td>
      <td>안동에서 이 사과를 땄을 확률</td>
    </tr>
  </tbody>
</table>

<p>사과가 어디서 재배되었을지 알아내기 위해서 최대 우도 추정(Maximum Likehood Estimation, MLE) 혹은 최대 사후 확률(Maximum A Posteriori, MAP) 추정 방식을 사용할 수 있다.</p>

<ul>
  <li>최대 우도 추정(Maximum Likehood Estimation, MLE)
    <ul>
      <li>말 그대로 우도가 최대인 것을 찾는다.</li>
      <li>$P(사과 \vert 안동), P(사과 \vert 영주), P(사과 \vert 청송), \cdots$ 등 가능한 모든 원산지에 대해 거기서 이 사과를 땄을 확률 모두를 구하고, 그 중에서 최대 우도를 갖는 원산지를 택한다.</li>
    </ul>
  </li>
  <li>최대 사후 확률(Maximum A Posteriori, MAP)
    <ul>
      <li>말 그대로 사후 확률이 가장 높은 것을 찾는다.</li>
      <li>$P(안동\vert 사과), P(영주\vert 사과), P(청송\vert 사과), \cdots$ 등 이 사과를 땄을 모든 원산지의 확률을 구하고, 그 중에서 최대 사후 확률을 갖는 원산지를 택한다.</li>
    </ul>
  </li>
</ul>

<p>베이즈 정리는 사후 확률 $P(안동\vert 사과)$ 를 구할 수 있게 한다.</p>

<div id="inserted-box">
    <div class="notice-text"><p>이런 문제를 풀 때 둘 중에 정확한 방법을 꼽자면 최대 사후 확률이라고 한다. 사과를 두고 그게 어디서 난 건지를 맞추는 게 문제의 본질에 가깝기 때문이다. 상식적으로. 더구나 최대 우도 추정의 경우 모든 사전 확률이 같다는, 즉 $P(안동)=P(영주)=P(청송)=\cdots$ 라서 모든 지역에서 사과가 동일하게 생산된다거나 품질이나 모양이 다 같다는 가정 하에 근사적 해를 구하는 느낌이다.</p></div>
</div>

<div id="inserted-box">
    <div class="notice-text"><p>머신러닝의 예로 들어보자면, ‘이 사진의 물체’(아까 전의 [사과])가 ‘컵’/’접시’/’물병’(아까 전의 [안동, 청송, 영주])일 확률이다.</p></div>
</div>

<h3 id="수식">수식</h3>

<p>머신러닝과 베이즈 통계학에서는, 우리가 관찰해온 어떤 확률 변수들이 주어졌을 때, 아직 관찰하지 않은(latent) 확률 변수들을 추론하고 싶다.</p>

<p>베이즈 정리(규칙, 법칙)는 아래와 같은 식이다.</p>

\[\underbrace{p(\boldsymbol{x \vert y})}_{\mathrm{posterior}} = \cfrac{\overbrace{p(\boldsymbol{y \vert x})}^{\mathrm{likelihood}} \ \overbrace{p(\boldsymbol{x})}^{\mathrm{prior}}} {\underbrace{p(\boldsymbol{y})}_{\mathrm{evidence}}}
\tag{3}\]

<p>위 베이즈 정리 식(3)은 곱의 규칙 식(2)에서 만들어낼 수 있다.</p>

\[p(\boldsymbol{y \vert x}) p(\boldsymbol{x}) = p(\boldsymbol{x \vert y}) p(\boldsymbol{y})
\iff p(\boldsymbol{y \vert x}) = \cfrac{p(\boldsymbol{x \vert y}) p(\boldsymbol{y})}{p(\boldsymbol{x})}\]

<p>식 자체가 아닌 의미론적으로 다가가보자.</p>

<p>관측하지 않은 확률변수 $\boldsymbol{x}$ 에 대한 사전 지식 $p(\boldsymbol{x})$ (‘prior’)가 있고, 또다른 확률변수 $y$와의 관계 $p(\boldsymbol{y \vert x})$ (‘likelihood’)를 알고 있다고 하자. 이는 관측할 수 있는 값이다. 이 상태에서 $\boldsymbol{y}$ (‘evidence’)를 관측하고, 베이즈 정리를 통해 $\boldsymbol{y}$ 의 관측값이 주어졌을 때의 $\boldsymbol{x}$에 대한 결론 $p(\boldsymbol{x \vert y})$ (‘posterior’) 을 이끌어낼 수 있다.</p>

<p>말이 어려우니 아까 사과의 원산지 예시를 다시 사용하겠다. 위 베이즈 정리 식(3)에 따르면</p>

\[P(안동\vert 사과) = \cfrac{P(사과 \vert 안동) \ P(안동)}{P(사과)}\]

<p>이다.</p>

<h3 id="posterior-term">Posterior term</h3>

<p>사후확률 $P(안동\vert 사과)$ 는 이 사과가 수확되었는데(관측, 사건 발생) 얘가 특정 지역인 ‘안동’에서 생산되었을 확률이다. 머신러닝에서 보자면 관측이 된(발생이 된) ‘이 사건’이 ‘이 특정 모델/시스템’에서 발생했을 확률이다.</p>

<p>교재에 따른 표현으로는, $\boldsymbol{y}$ 라는 관측을 했고, 그 때 $\boldsymbol{x}$ 에 대해 무엇을 알고 있는지를 나타낸다. 베이즈 통계학에서 관심을 가지는 양이다.</p>

<h3 id="prior-term">Prior term</h3>

<p>$P(안동), P(청송), \cdots$ 는 각 지역 고유의 확률값이다. 사과를 고려하기 전에, 각 지역에 대해 가지고 있는 사전 지식이다. 각 지역에서 사과 생산량이 얼마나 되는지 등을 예로 들 수 있겠다. 머신러닝에서 보자면 시스템/모델(여러 ‘클래스(라벨)’의 집합이라고 보면 쉽다)에 대한 사전 확률로, 남녀의 구성비($P(남자), P(여자)$) 라던지 연령 분포($P(노인), P(어린이)$) 등이 되겠다.</p>

<p>교재에 따른 표현으로는, Prior인 $p(\boldsymbol{x})$는 어느 데이터를 관측하기 전에 관측하지 않은(latent) 확률변수 $\boldsymbol{x}$ 의 주관적(subjective) 사전 지식(prior knowledge)을 요약하고 있다. 모든 $\boldsymbol{x}$ 에 대해 pdf, pmf가 0이 아니기만 하면 그 어떤 prior도 선택 가능하다.</p>

<h3 id="likelihood-term">Likelihood term</h3>

<p>앞선 사과의 예에서 보았듯이, 우도인 $P(사과 \vert 안동)$ 은 안동에서 이 사과가 나올 확률이다. 머신러닝에서 보자면 이 모델에서 이 데이터(관측값)가 나올 확률이다.</p>

<p>교재에 따르면, Likelihood(우도, 또는 measurement model)인 $p(\boldsymbol{y \vert x})$ 는 $\boldsymbol{x, y}$가 어떻게 관련되어 있는지를 말한다. 우리가 잠재 변수(latent variable) $\boldsymbol{x}$ 를 알고 있다면(prior), 데이터 $\boldsymbol{y}$ 의 확률이 $p(\boldsymbol{y \vert x})$ 이다. $p(\boldsymbol{y \vert x})$ 는 $\boldsymbol{y}$ 에서의 분포이지, $\boldsymbol{x}$ 에서의 분포는 아니다.</p>

<p>읽을 때는 ‘$\boldsymbol{x}$ 가 주어졌을 때의 $\boldsymbol{y}$ 의 확률’ 혹은 ‘$\boldsymbol{y}$ 가 주어졌을 때의 $\boldsymbol{x}$ 의 우도’ 라고 한다.</p>

<h3 id="evidence-term">Evidence term</h3>

<p>P(사과) 는 고정된 상수값(양, quantity)이다. Evidence 혹은 주변 가능도(marginal likelihood) $p(\boldsymbol{y})$ 라 하며, 아래와 같이 계산할 수 있다.</p>

\[\begin{aligned}
  p(\boldsymbol{y}) 
  := &amp;\int p(\boldsymbol{y \vert x}) p(\boldsymbol{x}) d\boldsymbol{x} \\
  = &amp;\mathbb{E}_{X}[p(\boldsymbol{y \vert x}) ] 
  \quad \left( \because \mathbb{E}_{X}[f(\boldsymbol{x})] = \int f(\boldsymbol{x})p(\boldsymbol{x}) d\boldsymbol{x} \right)
\end{aligned}
\tag(4)\]

<p>위 정의는 식(3)의 분자를 잠재변수 $\boldsymbol{x}$ 에 대해 적분하는 형태이다. 따라서 주변 가능도는 $\boldsymbol{x}$ 에 대해 독립적이고, 사후확률 $p(\boldsymbol{x \vert y})$ 가 정규화(normalized)되어 있음을 보장한다.</p>

<p>사과의 예로 보자면 $P(사과) = P(사과 \vert 안동)P(안동) + P(사과 \vert 청송)P(청송) + P(사과 \vert 영주)P(영주) + \cdots$ 로 계산할 수 있고, 베이즈 정리 식은</p>

\[\cfrac{P(사과 \vert 안동)P(안동)}{P(사과 \vert 안동)P(안동) + P(사과 \vert 청송)P(청송) + P(사과 \vert 영주)P(영주) + \cdots}\]

<p>으로 해석할 수 있다.</p>

<p>또한 주변 우도는 우도의 예측값(expected likehood)으로도 볼 수 있다. 위 (4)의 두 번째 줄의 식에 따라 사전확률에 대한 예측(expectation, $\mathbb{E}[\cdot]$) 을 사용하기 때문이다.</p>

<p>베이즈 정리는 가능도로부터 주어진 $\boldsymbol{x, y}$ 간의 관계를 뒤집을 수 있게 하기도 한다. 그래서 종종 베이즈 정리를 ‘probabilistic inverse’ 라고도 한다.</p>

<hr />

<h1 id="추가-참고-자료">추가 참고 자료</h1>

<ul>
  <li>다크프로그래머, “<a href="https://darkpgmr.tistory.com/119">베이지언 확률(Bayesian Probability)</a>”
    <ul>
      <li>Pure/Naive/Semi-Naive Bayesian</li>
    </ul>
  </li>
  <li>다크프로그래머, “<a href="https://darkpgmr.tistory.com/62">베이즈 정리, ML과 MAP, 그리고 영상처리</a>”
    <ul>
      <li>영상처리에 베이즈 정리의 활용</li>
    </ul>
  </li>
</ul>]]></content><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><category term="Math" /><category term="Math for ML" /><category term="Math" /><category term="Machine Learning" /><summary type="html"><![CDATA[Probability and Distributions - Sum Rule, Product Rule, and Bayes' Theorem]]></summary></entry><entry><title type="html">Algorithms 4장: Paths in graphs</title><link href="https://winterbloooom.github.io/algorithms_ch4/" rel="alternate" type="text/html" title="Algorithms 4장: Paths in graphs" /><published>2023-02-04T00:00:00+09:00</published><updated>2023-02-04T00:00:00+09:00</updated><id>https://winterbloooom.github.io/algorithms_ch4</id><content type="html" xml:base="https://winterbloooom.github.io/algorithms_ch4/"><![CDATA[<div id="inserted-box">
    <div class="notice-text"><p>이 내용은 책 <a href="http://algorithmics.lsi.upc.edu/docs/Dasgupta-Papadimitriou-Vazirani.pdf">Algorithms(Sanjoy Dasgupta et al.)</a>을 기반으로 하고 있습니다.</p></div>
</div>

<h1 id="41-거리distances">4.1. 거리(Distances)</h1>

<p>DFS로는 (1) 특정 시작점으로부터 닿을 수 있는 모든 노드를 구하기 (2) 그 노드들의 경로(path) 구하기(search tree로 나타낼 수 있음) 가 가능했다. 그러나 이렇게 구한 경로는 가장 경제적인, 쉽게 말해 최단경로는 아니다.</p>

<p>이번 4장에서는 주로 그래프에서 최단 경로(shortest path)를 찾는 방법을 알아본다.</p>

<p>경로의 <strong>길이(lengths)</strong>는 그래프에서 서로 다른 노드가 얼마나 떨어져있는지를 의미하는 양이다. 두 노드 간의 <strong>거리(distance)</strong>는 그 중에서도 가장 짧은 경로의 길이를 말한다.</p>

<hr />

<h1 id="42-너비-우선-탐색breadth-first-search">4.2. 너비 우선 탐색(Breadth-first search)</h1>

<h2 id="bfs-알고리즘">BFS 알고리즘</h2>

<p>특정 노드 s를 레이어 1번, s로부터 거리가 2인 노드들을 레이어 2번, … 라고 한다면, 이를 활용해 s에서 다른 노드들까지의 거리를 계산할 땐 레이어 단위로 진행할 수 있다. 즉, 어떤 특정 시간에 d번 레이어의 노드들을 모두 알고 있다면 d+1번 레이어는 d번 레이어의 이웃(연결된 노드)를 조사함으로써 알 수 있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216764130-cd32d2d6-7b2d-4d2d-b3db-6242279a568b.png" width="60%" />
<figcaption>Fig. 1 맨 위부터 1, 2, 3번 레이어로 나눌 수 있다.</figcaption>
</figure>

<p><strong>BFS(Breadth-first search, 너비 우선 탐색)</strong>은 이런 원리를 이용한 그래프 탐색법이다. 같은 거리의, 즉 같은 깊이의 노드들을 우선적으로 탐색한다.</p>

<ul>
  <li>시작 노드 s를 거리 0으로 해서 큐 Q에 넣는다. (큐 초기화)</li>
  <li>거리 d = 1, 2, 3, …에 대해 큐 Q가 오직 거리가 d인 노드들(시작 노드로부터 그들의 거리가 d로 모두 같은)만 가지고 있을 때가 있다. 즉, 큐 안에는 하나의 레이어에 속한 노드들만 존재한다.</li>
  <li>이 노드들이 큐의 front에서 꺼내져 처리될 때, 아직 탐색하지 못한 이웃 노드들(거리가 d+1. 다음 레이어에 속한 노드들)이 큐의 end로 삽입된다.</li>
</ul>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216764182-b65665d7-2290-43fc-a8ec-54492465907c.png" width="90%" />
<figcaption>Fig. 2 BFS</figcaption>
</figure>

<p>위 의사코드에서 볼 수 있듯이 처음에는 모든 거리를 무한으로 초기화한 뒤, 시작 노드를 거리 0으로 초기화하고, 큐에 넣는다. 반복문 안에서는 큐의 요소 하나를 뽑아(거리가 d라 하면), 그와 연결되었으며 아직 탐색되지 않은 모든 노드들(바로 연결되어 있으니 거리가 d+1일 것임)을 큐에 넣고, 그들의 거리를 업데이트한다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216764407-9d71fcd3-9e2a-44db-88e9-a1b0be4220ee.png" width="60%" />
<figcaption>Fig. 3 BFS 예시</figcaption>
</figure>

<p>BFS로 만들어진 트리는 위 사진과 같은데, 각 층은 시작노드로부터 거리가 같고 이는 최단 거리에 해당한다. 즉, 이 트리는 <strong>최단 경로 트리(shortest path tree)</strong>이다.</p>

<h2 id="bfs의-정확도-검증correctness">BFS의 정확도 검증(correctness)</h2>

<p>각 거리 d = 0, 1, 2, …에 대해 다음과 같은 세 가지가 만족되는 순간이 존재해야 BFS가 정확히 작동한 것이다.</p>

<ul>
  <li>시작 노드로부터 거리 d 이하의 모든 노드는 본인들의 올바른 거리가 계산되어 있다</li>
  <li>그 외의 모든 노드들은 거리가 ∞로 설정되어 있다.</li>
  <li>큐 안에는 거리가 d인 노드들만 있다.</li>
</ul>

<p>계속 언급했지만, 위와 같은 순간은 ‘이전 레이어와 바로 연결된(이웃) 모든 노드들이 전부 큐에 들어가 있는’ 상태로, 이제부터 큐에서 노드들을 꺼내 알고리즘을 다시 반복한다면 그때부턴 d+1 번째 레이어가 된다.</p>

<h2 id="bfs의-효율성efficiency">BFS의 효율성(efficiency)</h2>

<p>DFS와 같은 이유로 BFS도 선형 시간 $O(\vert V \vert + \vert E \vert)$ 을 갖는다.</p>

<p>각 노드는 큐에 한 번만 들어갔다가 나오므로 $2 \vert V \vert$ 번의 큐 연산을 하고, 반복문을 돌며 각 간선은 대해 무향 그래프는 한 번, 유향 그래프는 두 번씩 사용되어 $O(\vert E \vert)$ 시간이 걸리기 때문이다.</p>

<h2 id="dfs-vs-bfs">DFS vs BFS</h2>

<table>
  <thead>
    <tr>
      <th>DFS</th>
      <th>BFS</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>깊이 우선 탐색</td>
      <td>너비 우선 탐색</td>
    </tr>
    <tr>
      <td>stack 이용</td>
      <td>queue 이용</td>
    </tr>
    <tr>
      <td>deeper &amp; narrow</td>
      <td>broader &amp; shallow</td>
    </tr>
    <tr>
      <td>실제로 가까운 두 노드가 DFS 결과 멀리 돌아갈 수도 있음</td>
      <td>두 노드 간의 최단거리를 찾음. 거리가 가까운 순서대로 방문함</td>
    </tr>
    <tr>
      <td>더이상 방문할 노드가 없을 때 뒤로 다시 돌아감. Connected component를 다 돌았으면 다른 노드에서 재시작.</td>
      <td>다시 시작 안함. 시작 노드로부터 닿지 않는 노드는 무시</td>
    </tr>
  </tbody>
</table>

<hr />

<h1 id="43-간선의-길이length">4.3. 간선의 길이(length)</h1>

<p>지금까지는 간선의 길이가 모두 동일하다고 가정했으나, 실제 문제들은 그렇지 않은 경우가 더 많으며 심지어는 음수 길이의 간선도 존재한다.</p>

<p>간선 $e \in E$ 의 길이를 $l_e$ 라고 표현하며, 다르게는 간선 $e=(u, v)$ 일 때 그 길이를 $l(u, v)$ 혹은 $l_{uv}$ 라고도 할 수 있다.</p>

<p>간선의 길이는 물리적 길이라기 보단, 상황에 따라 어떠한 양이 부과된다고 본다. (e.g. 도시 간 이동하는 데 드는 비용)</p>

<hr />

<h1 id="44-다익스트라-알고리즘dijkstras-algorithm">4.4. 다익스트라 알고리즘(Dijkstra’s algorithm)</h1>

<h2 id="bfs의-변형">BFS의 변형</h2>

<h3 id="간선의-길이까지-고려하는-bfs">간선의 길이까지 고려하는 BFS</h3>

<p>간선의 길이가 양의 정수라고 가정하자. 다양한 길이의 간선으로 이루어진 그래프 G를 손쉽게 처리하기 위한 방법이 있다. 각 간선을 단위 길이만큼으로 자르고 그 사이에 dummy node를 넣어 새 그래프 G’을 만드는 것이다. 마치 4km 떨어진 지점까지 1km마다 휴게소를 설치하는 느낌이라 보면 된다.</p>

<p>즉 새로운 그래프 G’은 모든 간선 $e=(u, v) \in E$ 을 길이가 1인 간선 $l_e$로 바꾸고 $u, v$ 사이에 dummy node $l_e - 1$ 개를 넣어 만든다. 그럼 이제부턴 G’에 위에서 본 BFS를 그대로 적용해 거리들을 계산할 수 있게 된다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216766069-1024767f-4f78-4f60-9f11-9d0835f99532.png" width="60%" />
<figcaption>Fig. 4 dummy node를 사용해 G' 만들기</figcaption>
</figure>

<h3 id="alarm-clock-algorithm">Alarm clock algorithm</h3>

<p>그러나 역시 문제는 발생한다. 만약 간선이 매우 길어서 두 노드 사이에 dummy node가 매우 많아진다면, 쓸데없는 dummy node를 거쳐가는데 많은 시간을 쏟게 된다. 그래서 <strong>알람 시계 알고리즘</strong> 을 고안했다. ‘진짜 노드’에 도착할 때마다 알람을 켜고 경우에 따라 그 거리를 갱신하는 것이다.</p>

<ul>
  <li>시작 노드 s의 알람 시계 시간을 0으로 설정한다.</li>
  <li>더 알람이 울리지 않을 때까지(모든 노드를 방문할 때까지) 아래 과정을 반복한다. 어떤 노드 u가 시간 $T$에 알람이 울렸다고(도착했다고) 하면
    <ul>
      <li>s부터 u까지 거리는 $T$이다.</li>
      <li>u와 바로 연결된(이웃) 노드 v 각각에 대하여
        <ul>
          <li>v의 알람이 아직 울리지 않았다면(아직 방문 전이라면) v의 시간을 $T+l(u, v)$로 설정한다. 이 말인 즉, s와 v가 직접적으로 연결되어 있지 않거나, 다른 노드들을 거쳐 s와 경로가 나오더라도 이미 이것이 최단경로라는 뜻이다. 최단경로가 아니었다면 $T$ 이전에 v에 도착해알람이 울렸을테니 말이다.</li>
          <li>v의 알람이 $T+l(u, v)$보다 늦게 울린다면 더 작은 수인 $T+l(u, v)$ 로 그대로 둔다. 위와 같은 원리로, 다른 경로로도 v에 닿을 수는 있지만 그건 더 돌아가는 길이라 최단 경로는 아니란 뜻이다.</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216766202-ea64ef08-c617-475e-83bd-cfe9d0c0bb78.png" width="60%" />
<figcaption>Fig. 5 alarm clock algorithm example</figcaption>
</figure>

<p>Fig 5를 예를 들어보자. 시작 노드를 S라 하면,</p>

<ol>
  <li>S의 시간은 0이다.</li>
  <li>그 다음으론 가장 먼저 A가 울린다. A의 시간은 100이다.</li>
  <li>다음엔 A와 연결된 B가 울린다. B의 시간은 100 (A가 울린 시간) + 50 (A에서 B까지 거리) = 150이다.</li>
  <li>이후에 S에서 출발한 신호가 B에 도착해 시간 200에 알람이 울려도 150보다 늦다. 그러니 최단 경로는 S-B가 아니라 S-A-B이다.</li>
</ol>

<h3 id="다익스트라-알고리즘">다익스트라 알고리즘</h3>

<p><strong>다익스트라 알고리즘</strong>은, 위의 알람 시계 알고리즘을 적용하되 그 데이터 구조로 우선순위 큐(priority queue)을 사용하는 최단 경로 찾기 알고리즘이다.</p>

<p>우선순위 큐는 보통 heap(힙)으로 구현되며, 다익스트라 알고리즘에서 아래와 같은 조건을 만족한다.</p>

<ul>
  <li>저마다의 키 값(알람 시간)을 가진 노드들을 가지고 있다.</li>
  <li>다음 4가지 연산을 지원한다.
    <ul>
      <li>Insert: 큐에 요소 추가. 알람을 설정하는 역할</li>
      <li>Decrease-key: 특정 요소의 키 값을 감소시킴. 이 역시 알람을 설정하는 역할.</li>
      <li>Delete-min: 키 값이 최소인 요소를 리턴하고 큐에서 삭제. 다음에 어느 알람이 울릴지 결정. (알람이 울린다 = 큐에서 나간다)</li>
      <li>Make-queue: 키 값이 있는 주어진 요소들에 대해 우선순위 큐를 만듦.</li>
    </ul>
  </li>
</ul>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216767144-77963fe8-a785-45b3-b21e-de75faca297a.png" width="70%" />
<figcaption>Fig. 6 Dijkstra's Algorithm</figcaption>
</figure>

<p>위 의사코드를 자세히 살펴보자.</p>

<p><code class="language-plaintext highlighter-rouge">dist(u)</code> 는 노드 u의 알람 시간을 설정한다. 초기에는 모두 ∞으로한다. 이는 아직 결정된 시간이 없음(노드 간 거리 모름)을 의미한다.</p>

<p>최소 거리를 갱신하는 조건으로는 <code class="language-plaintext highlighter-rouge">dist(v) &gt; dist(u) + l(u, v)</code> 인데, 이는 이전에 알람 시계 알고리즘에서 보았듯이 v까지 오는데 ‘내가 이전에 알고 있던 경로보다, u를 거쳐 가는 것이 더 빠른 경로’임을 말한다.</p>

<p><code class="language-plaintext highlighter-rouge">prev</code> 라는 특별한 배열이 존재하는데, 이는 각 노드의 직전 노드를 저장하고 있다. 각 노드 간의 최단 경로를 발견할 때마다 <code class="language-plaintext highlighter-rouge">prev</code>를 갱신하며, 최종적인 <code class="language-plaintext highlighter-rouge">prev</code>를 거꾸로 따라 올라가다보면(back-pointers) 최단 경로를 얻을 수 있다.</p>

<p>이렇게 보면 알겠지만, 다익스트라 알고리즘은 일반 큐가 아닌 우선순위 큐를 사용해서 간선의 길이를 고려한다는 점을 빼면 그냥 BFS다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216768476-2d547560-21c9-4ca9-a137-79e7c792d60f.jpg" width="80%" />
<figcaption>Fig. 7 Dijkstra's Algorithm Example</figcaption>
</figure>

<hr />

<h2 id="최단경로를-계산하는-다른-형태">최단경로를 계산하는 다른 형태</h2>

<p>최단경로를 계산하기 위해 이러한 전략을 세운다. ‘시작 노드 s에서부터 인접한 노드들로 영역 R을 확장해나간다. R 내부의 노드들은 거리와 최단경로를 알고 있다.’</p>

<p>시작 노드로부터 현재 위치한 노드까지 최단경로는 하나의 간선(single edge)를 계속 연장해나간 형태라 볼 수 있는데, 같은 원리로 현재 노드에서 인접한 노드로 이 간선을 연장해 계속해서 최단경로를 찾을 수 있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216769339-b63f1ece-826e-4718-9411-9a24afeff26d.png" width="60%" />
<figcaption>Fig. 8 Single-edge extensions of known shortest paths</figcaption>
</figure>

<p>이를 의사코드로 나타내면 아래와 같다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216769398-804c43ae-5192-4131-9062-ff4406c0277e.png" width="70%" />
<figcaption>Fig. 9 The shortest path</figcaption>
</figure>

<p>Fig 7의 예시를 적용해보면, R은 {A}, {A, C}, {A, C, B}, {A, C, B, D}, {A, C, B, D, E}로 확장된다. 위 알고리즘에 우선순위 큐 연산을 포함하면 결국 또다시 다익스트라 알고리즘이 된다.</p>

<p>귀납법(induction)으로 위 알고리즘을 증명하자. while문의 끝에선 매번 다음의 조건을 만족한다.</p>

<ul>
  <li>영역 R의 모든 노드들은 시작 노드 s로부터 거리가 d 이하이고, R 밖의 노드들은 d 이상이다.</li>
  <li>모든 노드 u에 대해 <code class="language-plaintext highlighter-rouge">dist(u)</code>는 s로부터 u까지의 최단 경로의 길이를 말하며, 중간 노드들은 R에 있어야 한다.</li>
</ul>

<hr />

<h2 id="running-time">Running time</h2>

<p>다익스트라는 BFS와 구조적으로 동일하지만, 다익스트라에 사용되는 우선순위 큐 연산이 BFS에 사용되는 큐 연산보다 더 오랜 시간이 걸린다. $\vert V \vert$ 번의 <code class="language-plaintext highlighter-rouge">deletemin</code>과 $\vert V \vert + \vert E \vert$ 번의 <code class="language-plaintext highlighter-rouge">insert</code>, <code class="language-plaintext highlighter-rouge">decresekey</code> 연산이 필요하다.</p>

<p>이러한 소요 시간들은 어떻게 구현하는가에 따라 달라진다. 구체적으로는 우선순위 큐를 배열, binary heap, $d$-ary heap, Fibonacci heap 등 어떤 힙으로 만드느냐가 중요해진다.</p>

<hr />

<h1 id="45-우선순위-큐의-구현">4.5. 우선순위 큐의 구현</h1>

<p>다익스트라 알고리즘의 실행시간은 우선순위 큐의 구현 방식에 따라 크게 좌우된다고 했다. 아래는 여러가지 구현 방식과 그 시간을 정리한 내용이다.</p>

<table>
  <thead>
    <tr>
      <th>구현 방식</th>
      <th><code class="language-plaintext highlighter-rouge">deleteMin</code></th>
      <th><code class="language-plaintext highlighter-rouge">insert</code>/<code class="language-plaintext highlighter-rouge">decreaseKey</code></th>
      <th>$\vert V \vert \times$ <code class="language-plaintext highlighter-rouge">deleteMin</code> + $(\vert V \vert + \vert E \vert ) \times$ <code class="language-plaintext highlighter-rouge">insert</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>array</td>
      <td>$O(\vert V \vert)$</td>
      <td>$O(1)$</td>
      <td>$O(\vert V \vert ^2)$</td>
    </tr>
    <tr>
      <td>binary heap</td>
      <td>$O(\log \vert V \vert)$</td>
      <td>$O(\log \vert V \vert)$</td>
      <td>$O \left((\vert V \vert + \vert E \vert ) \log \vert V \vert \right)$</td>
    </tr>
    <tr>
      <td>d-ary heap</td>
      <td>$O \left( \cfrac{d \log \vert V \vert}{\log d} \right)$</td>
      <td>$O \left( \cfrac{\log \vert V \vert}{\log d} \right)$</td>
      <td>$O \left( \left(\vert V \vert \cdot d + \vert E \vert \right) \cfrac{\log \vert V \vert}{\log d} \right)$</td>
    </tr>
    <tr>
      <td>fibonacci heap</td>
      <td>$O(\log \vert V \vert)$</td>
      <td>$O(1)$ (amortized)</td>
      <td>$O \left(\vert V \vert  \log \vert V \vert + \vert E \vert\right)$</td>
    </tr>
  </tbody>
</table>

<p>TODO amortized time
https://woogyun.tistory.com/245</p>

<div id="inserted-box">
    <div class="notice-text"><p>피보나치 힙은 효율성이 매우 높긴 하지만 구현이 까다로워 실제론 잘 사용하지 않는다고 한다.</p></div>
</div>

<p>어떤 구현 방법이 좋을지는 그래프가 sparse한지(간선 수가 적음) 또는 dense한지(간선 수가 많음)에 따라 달라진다. 모든 그래프에 대해 $\vert E \vert \le \vert V \vert^2$ 이다.</p>

<div id="inserted-box">
    <div class="notice-text"><p>아래에선 $\vert V \vert$ 와 n을 때에 따라 섞어 사용했다. 둘 다 해당 자료형 내의 노드(요소) 개수라는 같은 의미로 사용했다.</p></div>
</div>

<h2 id="array">Array</h2>

<p>가능한 모든 요소들의 키값의 순서 없는(unordered) 배열로서 우선순위 큐를 구현할 수 있다. 처음엔 모두 ∞로 시작한다. 다익스트라 알고리즘을 예로 들면, 배열은 그래프 노드들의 키 값을 원소로 같는다.</p>

<p><code class="language-plaintext highlighter-rouge">insert</code> 와 <code class="language-plaintext highlighter-rouge">decreaseKey</code> 연산은 빠르다. 단순히 특정 위치(노드)의 키값을 바꾸면 되기에 $O(1)$ 시간만에 가능하다. (배열의 인덱스를 써서 찾는다던지?)</p>

<p>반면 <code class="language-plaintext highlighter-rouge">deleteMin</code> 은 리스트 전체를 순회하며 가장 작은 키값을 찾아야 하므로 선형 시간이 소요된다.</p>

<p>배열은 그래프가 $\Omega(\vert V \vert^2)$ 일 때 빠르게 동작한다.</p>

<h2 id="binary-heap">Binary heap</h2>

<p>이진 힙의 원소들은 완전 이진 트리(complete binary tree, 각 레벨이 왼쪽에서 오른쪽으로 채워지며 이전 레벨이 다 차야 다음 레벨에 넣을 수 있음) 형식으로 저장된다. 또한 부모의 키값은 자식의 키값 이하여야 한다. 그래서 루트 노드가 제일 작은 값을 같는다. 아래 Fig 10의 (a)를 보면 알 수 있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216824602-e9c10f61-63b4-437e-a837-745a1bf2b4eb.png" width="70%" />
<figcaption>Fig. 10 Binary heap Example</figcaption>
</figure>

<p><code class="language-plaintext highlighter-rouge">insert</code> 연산은 (1) 트리의 제일 끝에 새 요소를 붙이고(Fig10-b) (2) 올바른 위치를 찾을 때까지 부모 노드를 타고 올라간다(bubble up)(Fig10-c,d). 부모 노드보다 본인이 작으면 부모와 자신의 위치를 바꾼다. 따라서 자리 교체(swap)은 최대 ‘트리의 높이’ $\lfloor \log_2 n \rfloor$ 번 진행될 수도 있다.</p>

<p><code class="language-plaintext highlighter-rouge">deleteMin</code> 연산은 (1) 루트 값을 리턴하고 (2) 루트 노드를 힙에서 제거한 뒤(Fig10-e) (3) 트리의 가장 마지막 노드를 루트에 가져다놓는다.(Fig10-f) (4) 그리고 적당한 자리를 찾을 때까지 자식 노드들을 타고 내려간다(sift down)(Fig10-g,h). 자식 둘 중에 작은 값보다 본인이 크면, 작은 값의 자식과 본인의 자리를 바꾼다. 따라서 이 과정은 $O(\log n)$ 만큼 시간이 걸린다.</p>

<p>$\vert E \vert \le \cfrac{\vert V \vert ^2}{\log \vert V \vert}$ 일 때라면 binary heap을 쓰는 게 빠르다.</p>

<p>완전 이진 트리는 배열로 표현할 수 있다. 트리의 각 행(level) 별로 왼쪽에서 오른쪽으로 저장하면 된다(row by row). Fig10-a의 예를 들자면 {3, 10, 5, 11, 12, 6, 8, 15, 20, 13}이다. 층 별로 노드의 개수가 1, 2, 4, 8, …로 정해져 있으므로 노드의 위치를 찾기는 매우 쉽다. j 번째 노드의 부모는 $\lfloor \cfrac{j}{2} \rfloor$ 에 있고, 자식은 2j와 2j+1이다.</p>

<h2 id="d-ary-heap">d-ary heap</h2>

<p>binary heap의 일반화 형태로서, binary heap처럼 2개가 아닌 d개의 자식 노드를 갖는다. 즉, d=2일 때 binary heap이다. 자식 노드를 d개로 늘림으로써 트리의 높이는 당연히 줄어든다. 높이는 $\Theta(\log_d n) = \Theta \left( \cfrac{\log n}{\log d} \right)$ 이다.</p>

<p>높이에 따라 횟수가 달라지는 <code class="language-plaintext highlighter-rouge">insert</code> 연산은 그래서 $\Theta (\log d)$ 배씩 줄어들고, 반면에 새로운 루트 노드를 찾기 위해 아래서부터 올라가야하는 <code class="language-plaintext highlighter-rouge">deleteMin</code> 연산은 d개씩의 자식들과 비교하는 과정을 거쳐야 하기에 더 오랜 시간 $O(d\log_d n)$ 씩 걸린다.</p>

<p>최적의 실행시간은 그래프가 $d \approx \cfrac{\vert E \vert}{\vert V \vert}$ 일 때로, 힙의 degree를 그래프의 평균 degree와 같을 때이다.</p>

<p>$\vert E \vert = O(\vert V \vert)$ 로 그래프가 sparse할 때는 실행시간이 $O(\vert V \vert \log \vert V \vert)$ 로, binary heap 만큼 좋다.</p>

<p>반면 $\vert E \vert = \Omega(\vert V \vert ^2)$ 으로 그래프가 dense할 때는 실행시간이 $O(\vert V \vert ^2)$ 로, 연결 리스트만큼 좋다.</p>

<p>$\vert E \vert = \vert V \vert ^{1 + \delta}$ 로 중간 정도의 밀집도를 가진 그래프라면 실행시간이 $O(\vert E \vert )$ 로 선형적이다.</p>

<p>d-ary heap 역시 배열로 표현할 수 있다. j번 노드는 부모는 $\lceil \frac{j-1}{d}\rceil$ , 자식은 ${ (j-1)d + 2, \cdots, \min {n, (j-1)d + d + 1 } }$ 이다.</p>

<hr />

<h1 id="46-음수-간선이-있을-때-최단-경로">4.6. 음수 간선이 있을 때 최단 경로</h1>

<h2 id="음수-간선">음수 간선</h2>

<p>다익스트라 알고리즘은 음수 간선을 가질 때 최단 경로를 보장하지 못한다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216956345-4f23c995-4be7-487b-be01-ed75cc3b03ab.png" width="40%" />
<figcaption>Fig. 11 Dijkstra's algorithm on negative edges</figcaption>
</figure>

<p>위 그림을 살펴보자. B에서 A로 가는 데 음수 간선 (-2)가 있다. S-A 경로로 가면 3이고 S-B로 가면 4이기에 다익스트라 알고리즘에 의하면 사실상 더 짧은 경로인 S-B-A (비용: 4+(-2)=2)를 발견하기도 전에 S-A가 최단 경로라고 하고 만다.</p>

<p>이 현상에 기인하는 원인은 <code class="language-plaintext highlighter-rouge">update</code> 함수에 있다. 다익스트라 알고리즘에서 <code class="language-plaintext highlighter-rouge">dist</code> 값, 즉 각 노드의 거리 값은 항상 정확하거나 그것보다 큰 값을 갖는다. 처음엔 무한대로 시작했다가 간선들을 따라 업데이트된다.</p>

\[\mathrm{dist}(v) = \min \{ \mathrm{dist}(v), \mathrm{dist}(u) + l(u, v) \}\]

<p>위 업데이트 식을 생각해보면, 노드가 가질 수 있는 거리값은 $u$ 혹은 $u + l(u, v)$ 보다 클 순 없다.</p>

<p>이를 해결하기 위한 방법을 생각해보자.</p>]]></content><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><category term="Programming" /><category term="Algorithm" /><category term="Algorithm" /><summary type="html"><![CDATA[그래프에서 최단경로 찾기, BFS, Dijkstra's algorithm, Priority Queue]]></summary></entry><entry><title type="html">[Paper Review] DepthFormer 논문 리뷰 (Monocular Depth Estimation)</title><link href="https://winterbloooom.github.io/depthformer/" rel="alternate" type="text/html" title="[Paper Review] DepthFormer 논문 리뷰 (Monocular Depth Estimation)" /><published>2023-02-03T00:00:00+09:00</published><updated>2023-02-03T00:00:00+09:00</updated><id>https://winterbloooom.github.io/depthformer</id><content type="html" xml:base="https://winterbloooom.github.io/depthformer/"><![CDATA[<h1 id="들어가며">들어가며</h1>

<p>지난해 7월, 몇 편의 ‘단안 카메라 깊이 추정(monocular depth estimation)’ 논문을 읽고 프로젝트를 진행한 바 있었다. (<a href="https://winterbloooom.github.io/ai/computer%20vision/2022/07/15/depth_estimation.html">[Paper Review] Monocular Depth Estimation 논문 모음</a>)</p>

<p>그 논문들을 자세히 다시 읽어보며 정리하였고, 오늘 포스팅은 그 중 첫 번째 정리 내용이다.</p>

<p>2022년 발표된 모델(프레임워크)로, 이름은 <strong>DepthFormer</strong>이다. 가장 큰 특징으로는, 이미지의 특징을 추출하기 위한 인코더로 <strong>Transformer와 Convolutional Layer를 각각의 브랜치로 사용</strong>했다는 점, 그리고 디코더로 가기 전에 <strong>Neck 모듈을 따로 만들어 두 브랜치에서 나온 특징을 한 번 가공해 조합</strong>했다는 점이다.</p>

<div id="inserted-box">
    <div class="notice-text"><p>논문 원문: <a href="https://arxiv.org/abs/2203.14211">DepthFormer: Exploiting Long-Range Correlation and Local Information for Accurate Monocular Depth Estimation</a></p></div>
</div>

<h2 id="main-contributions">Main contributions</h2>

<ul>
  <li>이미지에서 특징을 추출하는 인코더에 2개의 브랜치를 사용했다. 하나는 long-range correlation을 추출하는 트랜스포머 브랜치, 다른 하나는 local information을 보존하는 합성곱 브랜치이다.</li>
  <li>HAHI 모듈을 만들었다. Element-wise interaction으로 특징(feature)을 향상시키고, set-to-set translation 방식으로 서로 다른 특징 간의 유사도를 모델링한다.</li>
  <li>이렇게 디자인한 DepthFormer를 KITTI, NYU, SUN RGB-D 데이터셋에서 검증했으며, SOTA 모델을 넘어서는 좋은 성능을 보였다.</li>
</ul>

<hr />

<h1 id="task-소개-depth-estimation">Task 소개: Depth Estimation</h1>

<p>먼저, 이 논문이 다루려는 주제부터 살펴보자.</p>

<p>하나의 표현으로 정리하면, ‘<strong>monocular depth estimation</strong>’, 한국말로는 단안 카메라에서의 깊이 추정이다.</p>

<p>‘단안 카메라’라는 표현은 그저 ‘이미지 한 장’이라고 봐도 무방하다. 양안 카메라의 경우 같은 시점에 촬영한 왼쪽과 오른쪽 이미지가 있기 때문에, 한 쪽을 모델의 입력용으로, 다른 쪽을 모델의 출력과 비교할 결과용으로 사용할 수 있다. 그러면 굳이 지도학습(supervised learning)이 아니어도 된다. 하지만 여기선 양안 카메라가 아닌, 지도학습을 이용한 단안 카메라에서의 깊이 추정을 다룬다.</p>

<p>‘깊이 추정’은 RGB 이미지 각 픽셀에서의 깊이(거리)를 계산해내는 것을 말한다. 카메라로부터 카메라가 찍은 해당 픽셀 위치의 실제 공간 속 지점까지 얼마나 멀리 떨어져있느냐의 문제다.</p>

<p>3차원 공간을 2차원 평면으로 투영하는 기계가 카메라다. 따라서 LiDAR와 같은 센서완 다르게, 카메라는 애초에 깊이 정보가 없다. (깊이 카메라(Depth Camera)를 사용하지 않는 이상 말이다) 그 기본적 원리를 넘어서려니, 이 task가 상당히 어려운 것이다.</p>

<p>구체적으로 말하자면, 깊이를 추정할 만한 단서(cue)도 부족하고 크기(scale)도 모호하다. 크기가 모호하단 말은, 아래 사진처럼 2차원으로 투영되면서 서로 다른 물체도 같은 크기로 보일 수도 있는 등의 일을 말한다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/215421561-99d10aee-98a8-4305-849e-b93752f0ddd1.png" width="60%" />
<figcaption>이미지 출처: <a href="http://eyehearteye.me/depth.html">Depth Estimation: Basics and Intuition</a></figcaption>
</figure>

<p>반사(reflective)되거나 투명한(translucent) 재질이 있다면 그것도 깊이 추정이 힘들다.</p>

<hr />

<h1 id="관련-이론-및-연구">관련 이론 및 연구</h1>

<h2 id="단안-깊이-추정-모델">단안 깊이 추정 모델</h2>

<p>이 논문에서는 같은 task를 다루는 관련 모델로 DPT(2021), Adabins(2021), Transdepth(2021)를 간단히 소개했다.</p>

<ul>
  <li>DPT (2021) : Visual Transformer (이하 “ViT”)를 인코더로 사용했으며, 대규모 깊이 추정 데이터셋으로 사전 학습(pre-train) 시켰다.</li>
  <li>Adabins (2021) : Adaptive bins를 입력 장면에 따라 동적으로 바뀌도록 했다. (bin은 일정한 간격으로 이해하면 된다. 그 값(범위)을 고정시키지 않고 유동적으로 하겠단 얘기다.) 또한 고해상도의 mini-ViT를 디코더 뒤에 추가했다.</li>
  <li>Transdepth (2021) : 트랜스포머(Transformer)가 지역적(local) 정보를 잃지 않도록 했으며, multi-level features(주로 모델의 서로 다른 층에서 나온 서로 다른 크기의 피처맵을 말함)을 합칠 수 있는 attention gate decoder를 제시했다.</li>
</ul>

<h2 id="인코더-디코더-구조">인코더-디코더 구조</h2>

<p><strong>인코더는 주로 입력 데이터에서 특징을 추출하는 과정</strong>을 말하는데, 대표적 특징 추출기인 EfficientNet(2019), ResNet(2016), DenseNet(2017)을 이용해 표현(representations)를 학습시킨다.</p>

<p>디코더는 주로 연속적인 합성곱과 업샘플링 연산으로 이루어져 있어, 인코더에서 나온 특징들(features)을 합친다(aggregate). 깊이 추정의 경우, 모델을 거치는 동안 달라진 공간적 해상도(쉽게 말해 피처맵의 크기)를 입력과 같도록 복원하고, 깊이를 추정하는 단계를 포함한다.</p>

<p>이 논문에서는 <strong>인코더를 두 개의 브랜치로 나누어 하나는 트랜스포머를 다른 하나는 합성곱층을 넣어두었다</strong>. 이 인코더를 핵심적으로 다룬다. 반면 디코더는 특별한 점 없이 표준적 디코더를 사용해 깊이 추정 결과를 만들어낸다.</p>

<h2 id="neck-module">Neck Module</h2>

<p>딥러닝에서 Neck은 주로 ‘입력 데이터를 특성맵으로 바꾸는 단계’와 ‘모델의 출력을 생성하는(예측을 수행하는) 단계’의 사이에 위치하는 모듈을 일컫는다.</p>

<p>위 인코더-디코더 구조로 보면, <strong>인코더 후 &amp; 디코더 전</strong>이라 할 수 있다. Neck에서 특징을 향상시킨다(enhance). <strong>출력을 만들어내기에, 혹은 처리하기에 더 좋은 상태로 가공한단 말이다.</strong></p>

<p>이 논문에서 핵심적으로 제안하고 있는 또다른 요소가 이 Neck 부분이다. 뒤에서 보겠지만 HAHI라고 이름 붙인 모듈을 제안한다.</p>

<h2 id="트랜스포머-네트워크">트랜스포머 네트워크</h2>

<p><strong>어텐션 레이어</strong>를 이용한 네트워크로, 컴퓨터 비전 분야에서 널리 쓰이는 중이다. 처음엔 자연어 처리를 위해 만들어졌으나, ViT 등을 시작으로 비전 분야에 들어오기 시작했다.</p>

<p>CNN은 필터가 위치한 그 부분만을 본다는 단점이 있다. 수용 영역(Receptive field)에 어쩔 수 없는 제한이 있다는 뜻이다. 반면, 트랜스포머는 self-attention을 통해 <strong>이미지 전체를 다 보고 각 부분과의 관계를 구할 수 있다.</strong></p>

<p>이 논문에서는 인코더에 트랜스포머를 활용해 이미지 데이터에서 (픽셀 위치로) <strong>서로 멀리 떨어진 곳과의 상관관계(long-range correlations)를 모델링</strong>하고자 한다.</p>

<hr />

<h1 id="주요-아이디어">주요 아이디어</h1>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216499513-f6a13933-7814-4739-a1b5-11339d714e37.png" width="80%" />
<figcaption>간단하게 나타낸 DepthFormer 구조</figcaption>
</figure>

<h2 id="long-range-correlation">long-range correlation</h2>

<p>이 논문의 저자들은 주장하길, 정확한 깊이 추정을 위해서는 ‘long-range correlation’이 필수적이라고 한다. 주구장창 나오는 이 long-range correlation이란 단어의 뜻을 조금 더 자세히 설명하겠다.</p>

<p>CNN의 주를 이루는 합성곱 연산(convolutional operator)은 필터(커널) 크기만큼 이미지 특정 부분을 가지고 필터와 곱해 하나의 픽셀값으로 만들어낸다. 이 필터가 이미지 전체를 돌아다니며 하나의 결과(다음 특성맵)을 만들어낸다.</p>

<p>여기서 합성곱층의 한계가 드러나는데, 그건 ‘이미지의 국소적 부분만 본다’이다. 예를 들어 필터가 9 x 9 크기라고 하면 서로 붙어있는 81개의 픽셀만 보고, 그 다음엔 또 서로 붙어있는 81개의 픽셀만 본다. 즉, 이미지의 조금씩만 떼어 보기 때문에 좌상단의 픽셀들과 우하단의 픽셀들은 서로 그 연관성을 계산해낼 수가 없다.</p>

<p>아래 그림으로 살펴보자. 9칸 짜리 주황색 박스는 그 다음 맵에선 한 칸으로 표시된다. 다르게 말하면, 한 칸이 보는 것은 이전 맵의 9칸 뿐이다. 맨 마지막 초록색 한 칸을 역으로 input 쪽으로 따라가보면, 저 한 칸이 이미지 전체 범위를 담기 위해서는 무려 3번의 합성곱 연산을 거쳐야한다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216513692-2d3b5942-c3e9-407f-9917-0fe261595b2d.png" width="80%" />
<figcaption>이미지 출처: Deep Learning for Computer Vision (Michigan University, Justin Johnson)</figcaption>
</figure>

<p>지금은 예시이니 이렇게 적은 단계이지, 실제 이미지는 몇 천 개의 픽셀을 포함하고 있다. 최종 출력맵의 각 칸이 입력 이미지의 전체적인 이미지를 보기 위해서는 모델이 매우 깊어져야 하는데, 이는 그리 현실적이진 않다.</p>

<p>실제로 저자들의 실험 결과를 보면, <strong>합성곱 연산의 제한된 수용 영역(receptive fields) 때문에 몇몇 물체들의 깊이 정확도가 떨어지는 현상</strong>이 발생한다.</p>

<p><img src="https://user-images.githubusercontent.com/69252153/216500603-2e473b99-0ea5-423a-884e-0fedef91b7da.png" alt="" /></p>

<p>저자들이 트랜스포머를 들여온 이유가 여기 있다. Self-attention의 경우 한 픽셀과 이미지 내 다른 모든 픽셀 간의 관계를 계산하기 때문에, <strong>이미지에서 멀리 떨어진 픽셀까지 서로의 관계 계산이 가능</strong>하다. 그말인 즉, 이미지 전체를 고려한단 뜻이다. Global receptive fields를 가진다고 표현할 수도 있겠다. 물체 단위로 보자면, 물체들 간의 거리적 관계 단위까지 넓게 보겠단 뜻이다.</p>

<p>위 사진에서 보면 Transformer 그림에서 화살표가 바깥으로 쭉쭉 뻗어나가는 것을 볼 수 있다. 이걸 Long-range correlation을 고려한다고 말하는 것이다.</p>

<h2 id="two-branches-in-encoder">two branches in encoder</h2>

<p>하지만 트랜스포머라고 해서 장점만 있는 건 아니다.</p>

<p>국소적 정보를 본다는 CNN의 단점은 트랜스포머와는 대비되는 CNN의 장점이기도 하고, 여전히 필요하다. 예를 들다면, 한 물체의 일관성(consistency)를 보기 위해선 국소적 정보가 필요하다. 이렇게 <strong>세세하게 보아야 하는 경우에는 합성곱 연산이 필요하다.</strong></p>

<p>반면 <strong>트랜스포머는 CNN과 달리 국소적 정보를 모델링하기엔 공간적 귀납 편향(inductive bias)가 부족</strong>하다. 이 어려운 말이 무슨 말인고, 잠깐만 들여다보겠다.</p>

<p>딥러닝을 공부할 때, 편향(bias)는 ‘어떤 방향으로 움직여주는(틀어주는)’ 느낌으로 다가온다. 그 느낌을 그대로 살려 ‘귀납 편향’은, 이 모델의 일반화 성능(보지 못한 데이터로도 좋은 결과를 내기)을 높이기 위해 ‘추가적 가정’을 주어 귀납적 추론을 하게 만드는 것이다.</p>

<p>CNN과 FCN(Fully Connective Network)를 비교해보자. FCN은 한 층의 뉴런이 다른 층의 모든 뉴런과 연결되어, 모든 입력이 모든 출력에 영향을 줄 수 있다. 그래서 ‘귀납 편향이 약하다’고 한다. 트랜스포머가 전체적인 관계를 보기 때문에, FCN과같이 귀납 편향이 약한 편이라 할 수 있는 것이다.</p>

<p>반면 CNN은 필터의 크기만큼의 픽셀들만 계산에 참여해 그들끼리는 강한 관계를 갖는다. 반대로 필터가 겹치지 않는 픽셀들 간에는 관계가 약하게 형성된다. 그래서 ‘귀납 편향을 갖는다’고 한다.(‘locality, translation invariance’) 또한 그래서 가까이 있는 픽셀 간의 국소적 관계에는 CNN이 그 특징을 잘 뽑아낼 수 있다.</p>

<p>다시 깊이 추정으로 돌아오자. 가까이 있는 물체는 크게 보이고 질감(texture)도 잘 보인다. 트랜스포머는 이미지를 패치 단위로 자르기 때문에 이 큰 물체는 여러 개의 패치로 잘릴 것이고, 이렇게 되면 이들의 디테일이 patch-wise 연산에서 사라질 위험이 크다.</p>

<p>국소적 정보는 <strong>일관적이고 날카로운(sharp, 사진상으로 깊이 추정이 모호하게 뭉개지지 않는) 추정 결과</strong>를 얻는 데 중요하다. 아래 그림에서 보다시피, 가운데 사진에선(다른 모델) 물체의 가장자리 부분이 뭉개지는 현상이 발생한다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216500727-55bd4c8a-5c5b-4a54-8acc-da80c4ad0e94.png" width="60%" />
</figure>

<p>따라서 이 논문에서는 <strong>트랜스포머 브랜치만 사용하는 것이 아니라, 합성곱 브랜치(CNN)도 인코더에 사용했다. 트랜스포머로는 전역적 정보를, CNN으로는 국소적 정보를 보겠단 의도이다.</strong></p>

<p>위 사진에서 Convolution 쪽 이미지를 보면 확대한 사진 안쪽으로 화살표가 향하고 있다. 의미상 이것을 국소적 정보를 본다고 말하는 것이다.</p>

<h2 id="neck-module-1">Neck module</h2>

<p>인코더에서는 트랜스포머와 CNN 각각에서 나온 특징맵이 있다. <strong>이들은 다른 브랜치에서 나왔기에 서로 종류가 다른 특징들</strong>이며, 단순히 합해서 디코더에 넣는 건 그리 좋은 선택이 아니라 한다.(서로 집중해서 뽑은 특징이 다르니까)</p>

<p>그래서 인코더와 디코더 사이에 Neck 역할을 하는 HAHI(Hirarchical Aggregation and Heterogeneous Interaction) 모듈을 만들어 넣음으로써, 트랜스포머의 특징은 좀 더 잘 쓰일 수 있게 향상시키고, 합성곱에서 나온 특징은 트랜스포머 특징과 잘 어우러질 수 있게끔 만든다.</p>

<p>이 길고도 어려운 모듈의 이름은 뒷부분에서 자세히 풀어내겠다. 지금은 역할만 알고 있자.</p>

<hr />

<h1 id="depthformer의-상세-구조">DepthFormer의 상세 구조</h1>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216500086-9cff6b8f-8949-461f-a91f-e2f71155cad5.png" />
<figcaption>DepthFormer의 상세 구조</figcaption>
</figure>

<hr />

<h1 id="encoder-feature-extraction">Encoder: Feature Extraction</h1>

<p>인코더는 입력 데이터인 이미지에서 특징을 추출하는 역할을 한다. 이 논문에서는 인코더를 두 개의 브랜치로 나눴는데, 하나는 트랜스포머 브랜치(Transformer branch), 다른 하나는 합성곱 브랜치(convolutional branch)이다.</p>

<p>트랜스포머 브랜치는 long-range correlation을 갖기 위해 어텐션 기법을 사용해 전역적 context를 모델링한다. 다만 트랜스포머가 공간적 귀납 편향이 부족한 탓에 국소적 정보(local information)를 놓칠 수 있기에, 이를 보완하고자 합성곱 브랜치를 추가적으로 사용하는 것이다. 이렇게 두 브랜치를 사용해서 깊이 추정의 정확도를 올리고자 한다.</p>

<p>위 모델 그림에서 파란색 박스가 트랜스포머 브랜치, 주황색 박스가 합성곱 브랜치에 해당한다.</p>

<h2 id="transformer-branch">Transformer Branch</h2>

<p>구체적인 트랜스포머 브랜치의 작동 과정을 알아보겠다.</p>

<p><strong>① 패치 분할 모듈(patch partition module)을 이용해 이미지 $I$ 를 겹치지 않는 패치들로 자른다.</strong></p>

<p>이때 각 패치의 초기 특징 표현(feature representation)은 RGB 픽셀값의 concatenation인 집합의 형태다.</p>

<p><strong>② 선형 임베딩 레이어(Linear embedding layer)를 통해 첫 특징 표현을 임의의 차원으로 투영(project) 시킨다.</strong></p>

<p>이렇게 투영된 벡터가 트랜스포머의 첫 번째 레이어의 입력으로 사용된다. 즉, 트랜스포머에 넣기 위해 일정 차원으로 특징 벡터들의 차원을 조정한단 뜻이다. 이렇게 만들어진 벡터를 $\boldsymbol{z}^0$라 표기한다.</p>

<p><strong>③ $L$ 개의 트랜스포머 레이어를 거치며 특징을 뽑아낸다.</strong></p>

<p>각 레이어는 [Layer Normalization(LN) → Multi-head self-attention(MSA) 모듈 → Residual Connection] → [Layer Normalization(LN) → Mlti-layer perceptron(MLP) → Residual Connection] 의 구성으로 이루어져 있다. 따라서 특정 레이어 $l$ 의 MSA 모듈 출력인 특징 벡터를 $\hat{\boldsymbol{z}}^l$ 이라 하고, MLP의 출력 특징 벡터를  $\boldsymbol{z}^l$ 하면 그 과정을 아래 수식으로 표현할 수 있다.</p>

\[\begin{align}
  \hat{\boldsymbol{z}}^l &amp;= MSA(LN(\boldsymbol{z}^{l-1})) + \boldsymbol{z}^{l-1} \\
  \boldsymbol{z}^l &amp;= MLP(LN(\hat{\boldsymbol{z}}^{l-1})) + \hat{\boldsymbol{z}}^{l-1}
\end{align}\]

<p>식 (1), (2)의 두 번째 항(더해주는 항)이 residual connection에 해당한다. 또한 ${l-1}$ 첨자에서도 알 수 있듯이, 이전 레이어의 출력을 지금 레이어의 입력으로 쓰고 있음을 확인할 수 있다.</p>

<p>DPT의 경우 트랜스포머로 ViT를 사용한데 반해, 이 논문의 DepthFormer에서는 Swin Transformer를 사용했다. 보다 계층적 특징들을 사용해 정확도를 향상시키고, 연산 복잡도를 낮추기 위함이다. 이 논문에서 제시한 swin transformer의 특징은 아래와 같으며, 필자가 설명을 붙였다.</p>

<ul>
  <li>local attention mechanism
    <ul>
      <li>기존의 self-attention은 한 패치와 다른 모든 패치들과 모두 한 번씩 연산을 진행한다. 이렇게 되면 연산의 비용이 크게 증가한다.</li>
      <li>따라서 일정한 window(영역)를 정해 그 안에서의 패치들만 서로 연산을 한다.</li>
      <li>예를 들어 이미지 전체에 16개의 패치가 있고, 이미지를 4개의 윈도우로 나눈다면, 하나의 윈도우에는 4개의 패치가 있다. 그럼 1개의 패치와 다른 15개의 패치 간의 어텐션을 수행하는 게 아니라, 비교하려는 패치가 속한 윈도우에 있는 나머지 3개의 패치와의 어텐션만 수행한다.</li>
    </ul>
  </li>
</ul>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216512803-0bb436a1-b47c-4fe2-a33d-e4975dc86fda.png" width="50%" />
</figure>

<ul>
  <li>shifted window scheme
    <ul>
      <li>윈도우 위치와 크기가 고정되어 있으면, 전체적 관계를 볼 수 있다는 어텐션의 장점이 퇴색된다. 따라서 이 윈도우를 섞어주는 과정을 추가해 각 패치들이 전역적 정보를 가질 수 있도록 만든다.</li>
    </ul>
  </li>
</ul>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216512838-aab3a7aa-2350-4c21-a263-f12304473701.png" width="50%" />
</figure>

<ul>
  <li>patch merging strategy
    <ul>
      <li>patch merging(패치를 합친다)은 사실상 patch partitioning(패치를 나눈다)과 같은 맥락이다. 매 swin transformer block 뒤에 merging 단계가 붙는데, 트랜스포머 블럭의 결과로 얻어진 피처맵을 이리저리 변환시키겠단 의미로 이해했다.</li>
      <li>기존의 이미지 $H \times W \times C$ 를 몇 개의 픽셀을 가진 패치 $H_p \times W_p \times C$ 로 분할해서 텐서를 다시 만든다($\frac{H}{H_p} \times \frac{W}{W_p} \times (H_p \cdot W_p \cdot C)$)는 뜻이다.</li>
    </ul>
  </li>
</ul>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216512869-4128fa52-eda6-4360-9843-a681747285c6.png" width="70%" />
</figure>

<p><strong>④ 브랜치의 최종 출력을 생성한다.</strong></p>

<p>DPT에서 사용한 방식처럼, 이 논문에서는 N개의 트랜스포머 레이어에서 나온 피처맵을 샘플링하고 합쳐서 트랜스포머 브랜치의 최종 출력(transformaer feature) $\boldsymbol{F} = {f^n }^N_{n=1}$ 으로 만든다. 각 피처맵은 $f^n \in \mathbb{R}^{C_n \times H_n \times W_n}$ 형태이다.</p>

<p><strong>이 내용을 주지한 채 위 모델 그림을 다시 보자!!!</strong></p>

<h2 id="convolutional-branch">Convolutional Branch</h2>

<p>합성곱 브랜치는 기본적인 ResNet 인코더를 사용한다. 그러나 특이한 점은 ResNet 전체가 아닌, 첫 번째 블럭(‘레이어’가 아니라, conv layer와 residual connection까지 있는 ‘부분’)만 사용한다. 논문에 의하면, 너무 깊은 층을 쌓게 되면 합성곱 연산이 계속되며 연속적인 곱 연산을 하게 되고, 결국 저차원 특징들이 없어지기 때문이다. 물론 블럭을 하나만 쓰기 때문에 연산이 금방 끝나기도 한다.</p>

<p>합성곱 브랜치의 최종 출력(convolution feature)은 $\boldsymbol{G} \in \mathbb{R}^{C_g \times H_g \times W_g}$ 이다.</p>

<hr />

<h1 id="neck-hahi-module">Neck: HAHI Module</h1>

<p>인코더에서 두 개의 브랜치를 사용하는 건 좋지만, 전역적 특징과 국소적 특징 간의 연결성은 부족하다. 이를 그대로 late fusion해서 디코더에 넣는다면 디코더에서 특징을 합치기에(feature aggregation) 충분치 않다. 그래서 둘 사이의 차이를 이어주고자, 혹은 두 브랜치의 좋은 점만 사용하고자, 디코더 전에 모듈 하나를 추가했다. 그것의 이름을 Hirarchical Aggregation and Heterogeneous Interaction(HAHI) Module 이라 한다. 모델 그림에서 초록색 박스에 해당한다.</p>

<p>Element-wise한 상호작용(interaction)을 통해 트랜스포머에서 나온 특징을 향상시키고, 트랜스포머의 피처와 CNN의 피처 간의 affinity(유사, 친근, 유연)를 모델링한다. 이는 set-to-set translation 방식으로 이루어진다.</p>

<p>구체적으로, HAHI 모듈은 그 이름을 둘로 나누어 이해할 수 있고, 그대로 구조가 된다.</p>

<ul>
  <li><strong>Hierarchical Aggregation</strong> : <strong>Self-attention Module</strong> for <strong>Feature Enhancement</strong>
    <ul>
      <li><strong>트랜스포머 피처</strong>의 계층적 레이어의 특징 개선(enhance)한다.</li>
      <li>트랜스포머 브랜치는 Swin Transformer를 사용해 여러 계층(multi-level) 특징맵을 얻었다. 그래서 ‘Hierarchical’이란 표현을 썼다.</li>
      <li>이러한 게층적 피처맵을 합쳐서 self-attention을 수행한다. Self-attention은 데이터 내부의 것들끼리의 관계를 파악하기 때문에 논문에서 ‘element-wise interation’ 방식라고 부른 것이다.</li>
    </ul>
  </li>
  <li><strong>Heterogeneous Interaction</strong> : <strong>Cross-attention Module</strong> for <strong>Affinity Modeling</strong> :
    <ul>
      <li>인코더에서는 두 개의 출력이 나온다. 하나는 트랜스포머 특징, 또 하나는 합성곱 특징이다. 이들은 같다고 말할 수 없는, 그러니까 이종(異種, 다른 종류)의 특징이다.</li>
      <li>따라서 이종의 특징끼리 상호작용 시켜 affinity(유사)를 모델링해서 두 특징을 보다 잘 쓰겠단 의도이다.</li>
      <li>둘을 상호작용 시키는 방식으로 Cross-attention을 수행한다. Cross-attention은 쿼리를 만든 데이터(여기서는 합성곱 브랜치의 특징)와는 다른 데이터(여기서는 트랜스포머 브랜치의 특징) 간의 관계를 계산하는 것이므로, 이를 ‘set-to-set translation’ 방식이라 부른 것이다.</li>
    </ul>
  </li>
</ul>

<p><img src="https://user-images.githubusercontent.com/69252153/216501008-6a9adec0-e6db-4d90-b580-762cef052b09.png" alt="image" /></p>

<p>그림이 좀 무섭게 생기긴 했는데, 아래 설명을 읽어보면 알겠지만 그냥 행렬을 폈다 서로 곱했다 합쳤다하는 연산들이다.</p>

<p>어텐션(gobal attention)의 단점은, 한 픽셀과 다른 모든 픽셀을 비교하기 때문에 그 연산의 비용(메모리 차지)가 매우 크다. 따라서 이를 보완하기 위해 HAHI 모듈 내 어텐션은 Deformable-DETR에서 제시한 deformable attention 기법을 채택했다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216510477-04157902-ca27-4dee-ab22-645be7478b6e.png" width="90%" />
<figcaption>Deformable Attention의 작동 원리</figcaption>
</figure>

<p>위 그림은 multi-head deformable attention을 간략화한 그림이다.</p>

<p>간단히만 말하자면 한 픽셀과 다른 모든 픽셀들을 다 엮어보는 기존의 어텐션과는 다르게, ‘레퍼런스 포인트(회색 피처맵에서 주황색 네모)’로부터 ‘오프셋(그림 가운데의 화살표 벡터들)’만큼 떨어진 ‘샘플링 포인트들(레퍼런스 포인트에서 오프셋만큼 움직인 네모들)’만 보겠다는 뜻이다.</p>

<p>이때 레퍼런스 점에서 얼마만큼 움직일지 정하는 ‘샘플링 오프셋’과 뽑힌 점들에 곱해줄 ‘어텐션 가중치’는 쿼리 피처을 선형 모델에 태워 만들어낸다. 즉, 학습 가능한 형태(learnable)이다.</p>

<p>이렇게 되면 이미지의 해상도가 높아지거나 판단해야 하는 이미지가 많아질수록 기존의 어텐션보다는 확연히 적은 연산이 수행되어 부담이 줄어든다.</p>

<h2 id="feature-enhancement">Feature Enhancement</h2>

<p>트랜스포머 브랜치에서 나온 계층적(여러 크기의) 특징맵들 $\boldsymbol{F} = {f^n }^N_{n=1}$ 를 향상시키고자 한다. Swin Transfomer에서 특징을 뽑아냈기 때문에 각 피처맵들은 서로 다른 크기와 채널수를 갖는다. 즉, multi-level이다.</p>

<p>이러한 multi-level 특징맵을 처리하기 위해 기존 방식들은 downsampling을 수행했으나, 이는 정보의 손실을 일으킬 수 있다. 그래서 본 논문에서는 아래의 방식으로 처리해 feature enhancement를 진행한다.</p>

<p><strong>① 1X1 합성곱을 통해 계층적 특성맵들을 같은 채널 $C_h$ 로 맞춘다.</strong></p>

<p>이 과정이 끝난 상태를 $\boldsymbol{F}<em>h = {f^n_h }^N</em>{n=1}$ 로 표기한다.</p>

<p><strong>② 특성맵을 unfold(flatten + concatenation) 해서 2차원의 행렬 $X$ 로 만든다.</strong></p>

<p>즉, X의 각 행은 특성맵들의 한 픽셀을 나타내는 $C_h$ 차원의 특징 벡터이다.</p>

<p><strong>③ $X$를 선형 투영(linear projection)해 Query, Key, Value를 만든다.</strong></p>

<p>$\boldsymbol{P}_Q, \boldsymbol{P}_K, \boldsymbol{P}_V$ 를 쿼리, 키, 밸류 각각의 선형 투영을 하는 행렬이라고 했을 때, $\boldsymbol{Q} = X\boldsymbol{P}_Q, \boldsymbol{K} = X\boldsymbol{P}_K, \boldsymbol{V} = X\boldsymbol{P}_V$ 로 쿼리와 키, 밸류를 만들 수 있다.</p>

<p><strong>④ deformable self-attention으로 피처를 향상시켜 $\hat{\boldsymbol{X}}$ 로 만든다.</strong></p>

<p>key sampling vector 몇 개로 제한해서 그것에 대해서만 어텐션을 수행하는 방식이다. 몇 개의 key 점이 그 장면의 구조를 나타내기 때문에, 깊이 추정에선 deformable attention이 유용하게 쓰일 수 있다.</p>

<p>구체적인 어텐션 수식은 아래와 같다. $x_q \in \boldsymbol{Q}, x_v \in \boldsymbol{V}$ 이며, $p_q$ 는 쿼리 벡터 $x_q$ 의 위치, $A_{qk}$ 는 쿼리에서 선형 투영으로 만든 어텐션 가중치, $\triangle p_{qk}$ 는 쿼리에서 선형 투영으로 만든 k 번째 샘플링 포인트의 오프셋이다.</p>

\[\mathrm{DeformAttn}(x_q, x_v, p_q) = \sum \limits_{k \in \Omega_k} A_{qk} \cdot x_v (p_q + \triangle p_{qk})\]

<p>어떤 계층(level)에서 만들어진 특성맵인지를 표시하기 위해 hierarchical embedding을 추가했다.</p>

<div id="inserted-box">
    <div class="notice-text"><p>Transformer, ViT 등 트랜스포머 모델에서는 패치 단위로 잘라 연산하기 때문에 위치 정보가 없다. 따라서 positional encoding으로 위치 정보를 함께 인코딩해 레이어의 입력으로 넣는다. 위 hierarchical embedding도 같은 의미로 이해하면 된다. 어떤 층에서 왔는지를 명시하기 위해 더해주는 값이라고 생각하면 된다.</p></div>
</div>

<p><strong>⑤ $\hat{\boldsymbol{X}}$ 를 fold(split + reshape) 해서 다시 원래의 해상도(크기)로 복원한다.</strong></p>

<p>아까 합쳐서 어텐션을 수행했으니, 이젠 그걸 다시 나누는 작업인 것이다. 입력과 동일한 크기로 복원한다 생각하면 된다. 이를 $\boldsymbol{F}_{enh}$ 라 표기한다.</p>

<p><strong>⑥ channel 별로 $\boldsymbol{F}_{enh}$ 와 $\boldsymbol{F}$ 를 concatenate해 합치고, 1X1 합성곱 연산을 거친다.</strong></p>

<p>이렇게 되면 진짜 최종적인 ‘향상된 특징’ $\boldsymbol{F}<em>o = {f^n_o }^N</em>{n=1}$ 를 얻는다.</p>

<h2 id="affinity-modeling">Affinity Modeling</h2>

<p>affinity modeling을 위해 합성곱 브랜치에서 만들어낸 피처맵 $\boldsymbol{G}$를 입력으로 받는다.</p>

<p><strong>① 1X1 합성곱 연산으로 $\boldsymbol{G}$ 을 $C_h$ 차원으로 투영한다.</strong> 이를 $\boldsymbol{G}_h$ 라 표기한다.</p>

<p><strong>② $\boldsymbol{G}_h$ 를 2차원의 쿼리 행렬 $\boldsymbol{Q}$로 펼친다.</strong></p>

<p><strong>③ Cross-attention을 수행해 affinity를 모델링한다.</strong></p>

<p>앞선 <a href="#feature-enhancement">트랜스포머 특징의 가공</a>처럼, $\boldsymbol{K, V}$ 처럼 $\hat{X}$ 를 적용해 cross-attention을 한다.</p>

<p>본인의 데이터 안에서 서로서로의 연관성을 만들어내는 self-attention과는 달리, cross-attention은 서로 다른 것끼리의 연관성을 만들어낸다. 트랜스포머 특징 가공 시에는 그래서 self-attention을 수행해 자기내들 안에서 특징을 가공했다면, affinity modeling의 목적은 트랜스포머와 CNN 브랜치에서 나온 특징들을 잘 섞는 것이기 때문에 cross-attention을 사용했다. 즉, CNN 특징을 기준으로 트랜스포머 특징과의 관계를 계산한다고 보면 된다.</p>

<p>여기서도 메모리 효율을 위하여 deformable attention 방식으로 진행한다. 레퍼런스 포인트 위치인 $p_q$ 가 affinity query embedding으로부터 학습 가능한 선형 투영과 시그모이드 함수를 통해 동적으로 예측된다. (가중치를 업데이트하는 신경망 하나를 거쳐 만들어낸단 소리다.) 이렇게 만들어낸 특징을 attentive representation, $\boldsymbol{G}_{att}$ 라고 적는다.</p>

<p><strong>④ $\boldsymbol{G}_{att}$ 을 원래 해상도로 reshape해 복원해놓는다.</strong></p>

<p><strong>⑤ $\boldsymbol{G}_{att}$ 와 $\boldsymbol{G}$ 를 채널별로(channel-wise) 합치고(concatenation), 1X1 합성곱 연산으로 최종 결과인 $\boldsymbol{G}_o$ 를 만든다.</strong></p>

<p>위와 같은 과정을 통해 HAHI 모듈의 두 번째 결과물이 만들어지는 것이다. Affinity modeling 과정을 통해 트랜스포머와 CNN 브랜치 간의 피처의 상호작용을 담아낼 수 있다.</p>

<hr />

<h1 id="decoder-optimization">Decoder, Optimization</h1>

<p>HAHI 모듈의 출력 $\boldsymbol{F}_o, \boldsymbol{G}_o$ 은 디코더로 넘어가 본격적인 깊이 추정을 해낸다. 디코더는 특별한 디자인 없이 기본적인 모델을 사용했으며, 이는 연속적인 up convolution layer로 이루어져 있다. 모델 그림에서 우측 회색 테두리 박스에 해당한다.</p>

<p>네트워크의 최적화를 위한 손실 함수는 아래와 같이 생겼다. 여기서 $h_i = \log \hat{d}_i - \log d_i$ 로, 예측값에서 정답값을 뺀 값을 말한다. $T$ 는 (정답이 존재하는) 픽셀의 개수이다. 상수계수는 $\lambda=0.85, \alpha=10$ 으로 설정했다.</p>

\[\mathcal{L}_{pixel} = \alpha \sqrt{\cfrac{1}{T} \sum \limits_i h_i^2 - \cfrac{\lambda}{T^2} \left( \sum \limits_i h_i \right)^2}\]

<p>식을 나름대로 해석해보자면, 오차의 제곱의 합을 평균낸 것에서, 오차의 합을 제곱해 평균낸(정확하진 않음) 느낌이다. 마치 분산($Var(X) = E[X^2] - E[X]^2$)이 떠오른다.</p>

<hr />

<h1 id="experiments">Experiments</h1>

<div id="inserted-box">
    <div class="notice-text"><p>Implementation Detail은 생략하겠다. 어떤 GPU를 썼고 어떤 최적화를 썼는지는 이 논문으로 실험을 하지 않을 이상 굳이….</p></div>
</div>

<h2 id="dataset">Dataset</h2>

<p>실험에서는 아래와 같이 3 종류의 데이터셋을 사용했으며, 각각의 주요 특징과 이 논문에서의 사용 방향을 기술해두었다.</p>

<ul>
  <li><strong>KITTI</strong>
    <ul>
      <li>자율주행 연구에서 빈번하게 사용되는 데이터셋이다. 양안 카메라와 3차원 라이다 데이터가 제공된다.</li>
      <li>Standard Eigen training/test split 을 따라, 이 논문의 저자들은 2만 6천 개의 왼쪽 이미지(양안 카메라의 왼쪽)를 훈련에 사용했으며, 697개를 테스트에 사용했다.</li>
      <li>평가(eval) 시에는 예측된 깊이추정맵을 crop &amp; upsampling 해 원래 사진의 해상도와 맞췄다. 이는 기존 연구 방식을 따른 것이다.</li>
      <li>온라인 벤치마크에 깊이 추정을 시험할 때는 official benchmark split을 사용했다. 7만 2천 개의 학습 데이터, 6만 개의 검증 데이터, 500개의 테스트 데이터를 사용했다.</li>
    </ul>
  </li>
</ul>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216501684-615b231f-f90c-48bf-8d02-f6aadf1ab31a.png" width="50%" />
</figure>

<ul>
  <li><strong>NYU-Depth-v2</strong>
    <ul>
      <li>야외 데이터셋인 KITTI완 다르게 실내 사진을 가진 데이터셋이다.</li>
      <li>5만 개로 학습을 진행했다.</li>
      <li>결과로 나오는 깊이추정맵은 데이터셋의 이미지 크기의 절반(640 x 480 → 320 x 240)이고 최대 10m까지만 추정이 가능하다. 이 결과를 정답과 비교하기 위해, 해상도를 정답과 맞추려 2배로 upsampling한다.</li>
      <li>평가(eval) 시에는 center-cropping한 깊이추정맵을 사용했다. 이는 기존 연구 방식을 따른 것이다.</li>
      <li>만들어낸 깊이추정맵을 가지고 다시 3차원 공간을 생성해낸 실험도 진행했다. 즉, 실제 공간과 유사할수록 깊이를 잘 추정한 것이다. (상당히 재밌는 실험인 것 같다 😆)</li>
    </ul>
  </li>
</ul>

<p><img src="https://user-images.githubusercontent.com/69252153/216501221-3d38729c-11ce-4c46-aa43-b987ba8907e8.png" alt="image" /></p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216501413-8d3aeaf1-6e31-40ff-8696-5d66b8b5486e.png" width="50%" />
</figure>

<ul>
  <li><strong>SUN RGB-D</strong>
    <ul>
      <li>이 역시 실내 데이터셋이다. 이 논문에서는 일반화 성능을 검증하기 위해 사용했다.</li>
      <li>NYU 데이터셋으로 사전 학습된 모델을 5,050 개의 이미지에 교차검증했다. 평가(eval)에만 사용하고, 모델을 학습시키는 데는 사용하지 않았다.</li>
      <li>추정할 수 있는 최대 깊이는 10m이다.</li>
    </ul>
  </li>
</ul>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216501850-4de6a623-a0df-40e1-9234-b5b2bf5fb562.png" width="50%" />
</figure>

<h2 id="metrics">Metrics</h2>

<p>깊이 추정에는 다양한 측정 방식이 존재한다. 아래엔 이 논문에서 사용한 측도들을 나타냈다. 높을수록 추정이 잘 됨을 나타내는 지표들은 ↑표시, 반대로 낮을수록 좋은 지표들은 ↓표시 하겠다.</p>

<p>1~6번은 NYU, KITTI Eigen Split, SUN RGB-D 에 사용했으며, 7~10번은 online KITTI benchmark 에 사용했다.</p>

<p>자세한 설명은 <a href="https://winterbloooom.github.io/ai/computer%20vision/2022/07/15/depth_estimation.html#evaluation-metrics">이전 포스트</a>에서 찾아볼 수 있다.</p>

<ul>
  <li>Accuracy Under the Threshold ↑ : 오차가 $thr = \alpha^{t} (t=1,2,3,\ \alpha=1.25)$ 이내인 픽셀의 비율 $\delta_1, \delta_2, \delta_3$</li>
</ul>

\[\% \ \mathrm{of} \ y_p\ \mathrm{s.t.}\ \max(\frac{y_p}{y_p^*}, \frac{y_p^*}{y_p}) = \delta &lt; thr\]

<ul>
  <li>AbsRel ↓ (Mean Absolute Relative Error) : 오차의 평균. 상대 오차 파악.</li>
</ul>

\[\frac{1}{N} \sum \limits_{i=1} ^N \frac{ \left| y_i - y_i^* \right|}{y_i^*}\]

<ul>
  <li>SqRel ↓ (Mean Squared Relative Error) : 차이의 제곱을 평균. 상대 오차 파악.</li>
</ul>

\[\frac{1}{N} \sum \limits_{i=1} ^N \frac{ || y_i - y_i^* || ^2}{y_i^*}\]

<ul>
  <li>RMSE ↓ (Root Mean Squared Error) : 차이의 제곱의 평균의 제곱근</li>
</ul>

\[\sqrt{\frac{1}{N} \sum^{N} \limits_{i=1} \left( y_i - y^*_i\right) ^2}\]

<ul>
  <li>RMSElog ↓ (Root Mean Squared Log Error) : RMSE에 log에서 비교한 것</li>
</ul>

\[\sqrt{\frac{1}{N} \sum^{N} \limits_{i=1} \left( \log y_i - \log y^*_i\right) ^2}\]

<ul>
  <li>log10 ↓ (Mean log10 Error) : log 차이를 평균</li>
</ul>

\[\log_{10} = \frac{1}{N} \sum \limits_{i=1} ^N \left| \log_{10} y_i^* - \log_{10} y_i\right|\]

<ul>
  <li>SILog ↓ (Scale-Invariant Log-arithmic Error) : scale과 무관하게 두 점 간의 오차를 계산하기 위하여 고안됨.</li>
</ul>

\[\begin{aligned}
  &amp;\alpha \left( y, y^{*} \right) = \frac{1}{n} \sum \limits_{i=1} ^N \left( \log y_i^{*} - \log y_i \right) \\
  &amp;d_i = \log y_i - \log y_i^* \\
  &amp;\frac{1}{2N} \sum \limits_{i=1} ^N \left( \log y_i - \log y_i^* + \alpha \left( y, y^* \right) \right) ^2 \\
  &amp;\frac{1}{n} \sum \limits_{i=1} ^N d_i^2 - \frac{1}{n^2} \left( \sum  \limits_{i=1} ^N d_i\right) ^2
\end{aligned}\]

<ul>
  <li>absErrorRel ↓ (Percentage of AbsRel)</li>
  <li>sqErrorRel ↓ (Percentage of SqRel)</li>
  <li>iRMSE ↓ (Root Mean Squared Error of the Inverse Depth)</li>
</ul>

<h2 id="sota-와-비교">SOTA 와 비교</h2>

<p>깊이 추정 task에서는 평가를 진행할 때 주로 깊이의 범위(range)를 나눈다. 가까운 거리의 물체와 먼 거리의 물체의 정확도를 구분해서 보겠다는 의도이다. 0-20m, 20-60m, 60-80m로 나누어두었다.</p>

<p>비교의 기준으로 삼는 모델은 Adabins로 했다. NYU-Depth-v2에서 Ababind보다 물체의 경계를 보다 선명하게 잡아냈고, 교차검증을 실시간 SUN RGB-D에선 매우 어두운 이미지에서도 정확한 깊이 추정을 했다고 한다.</p>

<p>비교 사진은 데이터셋 소개에서 이미 보였다.</p>

<h2 id="ablation-study">Ablation Study</h2>

<p>NYU, KITTI 데이터셋으로 진행한 ablation study 중 몇 가지만 추려 보겠다.</p>

<ul>
  <li><strong>주요 요소들의 효과 검증하기</strong>: Resnet-50, Swin Transformer를 백본으로 삼고, 여기에 (1) HAHI 모듈과 (2) 합성곱 브랜치, (3) 더 큰 사전 학습 데이터 이 세 가지에 대해 사용 여부를 비교해가며 성능을 살펴보았다.</li>
  <li><strong>합성곱 브랜치의 구조</strong>
    <ul>
      <li>앞선 설명에서, 합성곱 브랜치는 층을 깊게 쌓지 않고 오직 하나의 블럭만 사용한다고 했다.</li>
      <li>Ablation study 에서 실제 실험 결과가 나오는데, 블럭을 계속 추가할수록 성능이 나빠졌다.</li>
      <li>그 이유를 저자들이 추측하기를, CNN의 연속적인 합성곱 연산을 계속하면 저차원의 특징들이 없어지고, 공간적 해상도가 낮아지면서 세세한(fine-grained) 정보가 버려지기 때문이라고 한다.</li>
      <li>그래서 해당 논문에선 블럭을 하나만 사용함으로써 중요한 국소적 정보들은 유지하면서도 복잡도를 낮춤으로써 정확도를 최적화했다.</li>
    </ul>
  </li>
  <li><strong>HAHI 모듈의 효과</strong>
    <ul>
      <li>앞서 보았듯, HAHI 모듈은 트랜스포머 특징에 deformable self-attention(DSA)를, 합성곱 특징에 deformable cross-attention(DCA)를 적용했다. 이 효과를 검증하기 위한 실험이다.</li>
      <li>Multi-level DSA (계층적 피처에 대한 DSA) 가 하나의 계층만 가진 피처를 사용할 때보다 성능이 좋았다.</li>
      <li>Multi-level의 DSA와 DCA를 함께 사용했을 때 성능이 좋다. 둘 모두가 있어야 이종 간의 상호작용이 일어난다. 즉, 이종의 특징 간에는 불일치(discrepancy)가 많기에, 이를 보완해주는 작업이 필요하다.</li>
    </ul>
  </li>
</ul>

<hr />

<h1 id="정리">정리</h1>

<p>맨 처음 main contribution 내용에 살을 붙여 정리한다. (나름의 비결이랄까.)</p>

<ul>
  <li>이미지에서 특징을 추출하는 인코더에 2개의 브랜치를 사용했다.
    <ul>
      <li>하나는 long-range correlation을 추출하는 트랜스포머 브랜치이다. Swin Transformer을 사용해 여러 계층의 특징맵(multi-level features)을 얻는다(계층적(hierarchical) 특징맵)</li>
      <li>다른 하나는 local information을 보존하는 합성곱 브랜치이다. Residual block 하나만 사용해 저차원 특징을 보존하고 연산 부하를 줄인다.</li>
    </ul>
  </li>
  <li>HAHI 모듈을 만들었다.
    <ul>
      <li>두 개의 브랜치는 서로 독립되어 있어 이들을 late fusion 방식으로 합치면 디코더에서 feature aggregation하기 충분히 좋지 않다.</li>
      <li>트랜스포머 브랜치에서 나온 다층의 특징들은 self-attenton, 즉 element-wise interaction으로 향상시킨다.</li>
      <li>합성곱 브랜치에서 나온 특징들은 cross-attention, 즉 set-to-set translation 방식으로 서로 브랜치 간의  특징 유사도를 모델링한다. (이종(heterogeneous) 상호작용)</li>
      <li>모듈에 사용한 어텐션들은 deformable 방식을 사용해 연산 부하를 줄인다.</li>
    </ul>
  </li>
  <li>DepthFormer를 KITTI, NYU, SUN RGB-D 데이터셋에서 검증했으며, SOTA 모델을 넘어서는 좋은 성능을 보였다.</li>
</ul>

<hr />

<h1 id="추가-참고-자료">추가 참고 자료</h1>

<ul>
  <li>VISION HONG, <a href="https://visionhong.tistory.com/31">[논문리뷰] Swin Transformer</a></li>
  <li>re-code-cord, <a href="https://re-code-cord.tistory.com/entry/Inductive-Bias%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C">Inductive Bias란 무엇일까?</a></li>
  <li><a href="https://arxiv.org/abs/2005.12872">End-to-End Object Detection with Transformers</a>
    <ul>
      <li>Deformable Attention을 제시한 DETR 모델</li>
    </ul>
  </li>
</ul>]]></content><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><category term="AI" /><category term="Computer Vision" /><category term="Deep Learning" /><category term="paper Review" /><category term="Computer Vision" /><category term="Depth Estimation" /><summary type="html"><![CDATA[DepthFormer: Exploiting Long-Range Correlation and Local Information for Accurate Monocular Depth Estimation (2022)]]></summary></entry><entry><title type="html">Algorithms 2장: Divide and Conquer</title><link href="https://winterbloooom.github.io/algorithms_ch2/" rel="alternate" type="text/html" title="Algorithms 2장: Divide and Conquer" /><published>2023-02-03T00:00:00+09:00</published><updated>2023-02-03T00:00:00+09:00</updated><id>https://winterbloooom.github.io/algorithms_ch2</id><content type="html" xml:base="https://winterbloooom.github.io/algorithms_ch2/"><![CDATA[<div id="inserted-box">
    <div class="notice-text"><p>이 내용은 책 <a href="http://algorithmics.lsi.upc.edu/docs/Dasgupta-Papadimitriou-Vazirani.pdf">Algorithms(Sanjoy Dasgupta et al.)</a>을 기반으로 하고 있습니다.</p></div>
</div>

<h1 id="divide-and-conquer-분할정복법">Divide and Conquer (분할정복법)</h1>

<p>이름에서도 알 수 있듯이, 문제를 작은 문제로 ‘분할’해서 해결하는 방식이다.</p>

<ol>
  <li>같은 유형의 더 작은 부분문제(sub-problem)으로 분할한다.</li>
  <li>재귀적으로 부분문제를 해결한다. 부분문제가 해결 가능할 때 해결하며, 이는 주로 재귀의 끝이 된다.</li>
  <li>부분문제들의 해답을 적절히 결합한다.</li>
</ol>

<hr />

<h1 id="21-곱셈">2.1. 곱셈</h1>

<p>$n$ 비트 정수인 $x, y$를 곱하는 문제를 푼다고 하자. 주요 아이디어는, $n$ 비트를 $n/2$ 비트의 두 개의 수로 나누어 곱한다는 것이다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/222937737-7b0d812a-d301-42ab-bae5-24e5cacfc134.png" />
<figcaption>곱셈 알고리즘</figcaption>
</figure>

<ul>
  <li>2의 거듭제곱 곱셈(파란 원): 왼쪽 shift 연산 ➡ 선형시간</li>
  <li>덧셈(초록 원): 선형시간</li>
  <li>$n/2$ 비트 곱셈 4개(주황 사각형): 4번의 재귀호출이 필요한 또다른 곱샘. 즉, 더 작은 문제에 해당</li>
</ul>

<p>우리가 해결해야 할 것은 주황 사각형인 $n/2$ 비트 곱셈 4개이다. 따라서 $n$ 비트의 입력에 대해 수행시간은</p>

\[T(n) = \underbrace{4 T \left( \frac{n}{2} \right)}_{\text{4번의 재귀호출}} + \underbrace{O(n)}_{\text{합치기(덧셈, 곱셈)}}\]

<p>위의 방식대로이면 작은 문제인 작은 곱셈을 총 4번 수행해야 한다. 하지만 아래와 같은 ‘가우스 방법’을 이용하면 3개로 줄일 수 있다.</p>

\[x_L y_R + x_R y_L = (x_L + x_R)(y_L + y_R) - x_L y_L - x_R y_R\]

<p>그럼 곱셈 (A) 식은</p>

\[2^n {\color{Orange}x_L y_L} + 2^{\frac{n}{2}} \left \lbrace {\color{Orange} (x_L + x_R)(y_L + y_R)} - x_L y_L - {\color{Orange} x_R y_R} \right \rbrace + x_R y_R\]

<p>위처럼 주황색으로 표시된 3개 부분만 곱하면 된다. 따라서 상수 인자가 4에서 3으로 개선되는 아래와 같은 시간이 걸린다.</p>

\[T(n) = \underbrace{3 T \left( \frac{n}{2} \right)}_{\text{3번의 재귀호출}} + \underbrace{O(n)}_{\text{합치기(덧셈, 곱셈)}}\]

<figure>
<img src="https://user-images.githubusercontent.com/69252153/222937869-1fc9e98d-4c7b-460e-8401-bbb6df2cb53c.png" width="70%" />
<figcaption>곱셈 알고리즘</figcaption>
</figure>

<p>분할 정복 문제는 트리로 나타낼 수있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/222937994-32ef429e-7be1-426b-9672-d5eba0656451.png" width="70%" />
<figcaption>재귀 트리</figcaption>
</figure>

<ul>
  <li>초기 크기인 size $n$ 의 문제를 0단계</li>
  <li>분기 계수(branching factor): 나뉘는 작은 문제의 개수. 여기선 3개의 곱셈 재귀로 나뉘므로, 분기 계수가 3</li>
  <li>한 단계가 내려갈 때마다(분할) 문제의 크기가 $1/2$ 씩 줄어든다.</li>
  <li>트리의 높이(level)인 $\log _2 n$ 번째에서(잎) 부분문제의 크기가 1이 되며 재귀가 종료된다.</li>
  <li>깊이가 $k$ 에서
    <ul>
      <li>부분 문제의 크기: $\cfrac{n}{2^k}$</li>
      <li>부분 문제의 개수: $3^k$</li>
      <li>소비되는 시간: $3^k \cdot O \left( \cfrac{n}{2^k} \right) = \left(\cfrac{3}{2} \right)^k \cdot O(n)$</li>
    </ul>
  </li>
  <li>전체 수행시간: 약 $O(n^{\log _2 3}) = O(n^{1.59})$</li>
</ul>

<hr />

<h1 id="22-분할정복의-점화식">2.2. 분할정복의 점화식</h1>

<h2 id="문제-해결-방식">문제 해결 방식</h2>
<p>분할정복 문제를 일반화하면 아래와 같다.</p>

<ul>
  <li>크기가 $n$ 인 문제를 풀 때,</li>
  <li>크기가 $n/b$ 인 $a$ 개(‘분기 계수’)의 부분문제를 재귀적으로 풀고(부분 문제의 크기가 재귀의 각 단계에서 $1/b$로 줄어듦),</li>
  <li>이들의 해답을 $O(n^d)$ 시간으로 결합해 해결한다.</li>
</ul>

<h2 id="재귀-트리">재귀 트리</h2>

<p>앞서 살펴본 듯이, 분할정복법은 재귀트리로 나타낼 수 있으며, 아래 그림은 그 일반화 버전이다.</p>

<p><img src="https://user-images.githubusercontent.com/69252153/222906840-59ade3f3-fec3-4fdf-8987-8ac6211f7334.png" alt="image" /></p>

<ul>
  <li>$\log _b n$ 단계가 잎이다. 이때 기저 조건(base case)에 도달하며, 이것이 재귀 트리의 높이이다.</li>
  <li>$k$ 번째 단계에서 크기가 $\cfrac{n}{b^k}$ 인 $a^k$ 개의 부분 문재가 존재한다.</li>
  <li>따라서 전체 작업은 $a^k \times O \left(\cfrac{n}{b^k} \right) = O(n^d) \left( \cfrac{a}{b^d} \right)^k$ 이다.</li>
</ul>

<h2 id="시간복잡도">시간복잡도</h2>

<p>전체 작업이 $a^k \times O \left(\cfrac{n}{b^k} \right) = O(n^d) \left( \cfrac{a}{b^d} \right)^k$ 라는 점에서 케이스 별로 정리가 가능하다.</p>

<p>$k$ 가 루트인 0에서 $\log _b n$으로 가며 $r = \cfrac{a}{b^d}$ 의 등비급수를 이룬다. Big-O 표기법에서 급수의 합을 구할 수 있으며, 공비 $r$에 따라 아래와 같은 경우의 수를 나눌 수 있다.</p>

<table>
  <tbody>
    <tr>
      <td>$r &lt; 1$</td>
      <td>급수 ⬆</td>
      <td>급수의 합 = 첫 번째 항 $O(n^d)$</td>
    </tr>
    <tr>
      <td>$r &gt; 1$</td>
      <td>급수 ⬇</td>
      <td>급수의 합 = 마지막 항 $O(n^{\log _b a})$ (🌱)</td>
    </tr>
    <tr>
      <td>$r = 1$</td>
      <td> </td>
      <td>모든 $O(log n)$항은 $O(n^d)$와 같음</td>
    </tr>
  </tbody>
</table>

<p>(🌱) $n^d \left( \cfrac{a}{b^d} \right)^{\log _b n} = n^d \cfrac{a^{\log _b n}}{(b^{\log _b n})^d} = a^{\log _b n} = a^{(\log _a n)(\log _b a)} = n^{\log _b a}$</p>

<h2 id="수행시간">수행시간</h2>

<p>앞서 ‘문제 해결 방식’에서 정의한 내용을 바탕으로 수행 시간은 아래와 같이 일반화할 수 있다.</p>

\[T(n) = a T \left( \left \lceil \frac{n}{2} \right \rceil \right) + O(n^d)\]

<p>예를 들면 곱셈 알고리즘과 이진 탐색을 아래와 같이 정리할 수 있다.</p>

<table>
  <thead>
    <tr>
      <th>알고리즘</th>
      <th>a</th>
      <th>b</th>
      <th>d</th>
      <th>시간</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>곱셈 알고리즘</td>
      <td>3</td>
      <td>2</td>
      <td>1</td>
      <td>$T(n) = 3 \cdot T \left( \left \lceil \frac{n}{2} \right \rceil \right) + O(n)$</td>
    </tr>
    <tr>
      <td>이진탐색</td>
      <td>1</td>
      <td>2</td>
      <td>0</td>
      <td>$T(n) = 1 \cdot T \left( \left \lceil \frac{n}{2} \right \rceil \right) + O(1) = O(\log n)$</td>
    </tr>
  </tbody>
</table>

<p>수행 시간을 쉽게 구할 수 있는 방법을 ‘마스터 정리’라고 한다.</p>

<div id="def-box">
<div class="def-title">마스터 정리</div>
<p>

$a \gt 0, b \gt 1, d \ge 0$ 이고, $T(n) = a T \left( \left \lceil \frac{n}{2} \right \rceil \right) + O(n^d)$ 이면,

$$
T(n) =
\begin{cases}
    O \left( n^d \right) &amp; \text{if }d &gt; \log _b a \\
    O \left( n^d \log n \right) &amp; \text{if }d = \log _b a \\
    O \left( n^{\log_b a} \right) &amp; \text{if }d &lt; \log _b a
\end{cases}
$$

</p>
</div>

<p>위 정리에 따르면 이진 탐색은 두 번째, 곱셈은 세 번째 식에 해당한다.</p>

<hr />

<h1 id="23-merge-sort-병합-정렬">2.3. Merge Sort (병합 정렬)</h1>

<p>병합 정렬(<code class="language-plaintext highlighter-rouge">mergesort</code>)은, ‘절반씩 나누어 재귀적으로 정렬하고 병합(<code class="language-plaintext highlighter-rouge">merge</code>)하는’ 알고리즘이다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/222908244-6508cf4c-8fc1-4352-a2e9-99eded86a7db.png" />
<figcaption>mergesort 알고리즘</figcaption>
</figure>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/222908487-ace4dada-7ef8-4fd6-83cc-de019efb99fa.png" />
<figcaption>mergesort 알고리즘 예시</figcaption>
</figure>

<p>여기서 병합(<code class="language-plaintext highlighter-rouge">merge</code>)은 정렬된 두 배열이 있을 때 <code class="language-plaintext highlighter-rouge">x</code>과 <code class="language-plaintext highlighter-rouge">y</code> 요소 중 앞에서부터 작은 것을 먼저 택하고, 남은 것들 중에서 다시 택하는 과정을 반복한다. 따라서 앞에서부터 차근차근 하나씩 보기 때문에, 선형 수행시간이 걸린다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/222908274-6dde19b0-b407-4098-9ae3-3cbc35fec89e.png" />
<figcaption>merge 알고리즘</figcaption>
</figure>

<p>위 의사코드와 예시 사진 등에서 볼 수 있듯이, 재귀는 원소가 하나가 될 때까지 시작하지 않는다. 이때 <code class="language-plaintext highlighter-rouge">mergesort</code>를 아래와 같이 queue를 사용해 구현이 가능하다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/222908544-7cc79ba4-dfdb-4cec-b077-257e3cd0d1c6.png" />
<figcaption>iterative-mergesort 알고리즘</figcaption>
</figure>

<p>TODO 그림</p>

<h2 id="정렬의-하한-n-log-n">정렬의 하한 $n \log n$</h2>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/222908900-9dfbd1cb-10ef-4435-8c5f-16d419ae6db1.png" />
<figcaption>세 개의 수를 정렬하는 예시</figcaption>
</figure>

<p>정렬을 이진트리로 나타내면, 잎의 개수는 $n!$ 개이다. 이는 n개의 숫자를 일렬로 나열하는 순열의 개수이기 때문이다. 따라서 $\Omega (n \log n)$ 만큼의 비교가 필요하다.</p>

<p>트리의 깊이는 최악의 시간복잡도이다. 깊이가 $d$ 인 이진 트리의 잎은 $2^d$ 개이고, 깊이는 최소 $\log (n!)$ 이다.</p>

<p>$\log(n!) \ge c \cdot n \log n$ 임이 알려져 있다. ($\because n! \ge (n/2)^{n/2}$). 따라서 병합정렬의 경우 $O(n \log n)$ 복잡도가 최적임을 알 수 있다.</p>

<hr />

<h1 id="24-median-중앙값">2.4. Median (중앙값)</h1>

<h2 id="중앙값-찾기와-선택-문제">중앙값 찾기와 선택 문제</h2>

<p>중앙값은 원소의 50번째 백분위수로, 원소들 중 절반은 중앙값보다 작고 절반은 중앙값보다 크다.</p>

<p>중앙값을 찾기 위해 ‘모든 원소를 정렬해’ 찾아도 되긴 하지만, 실질적으로 중앙값만 구한다고 하면 이는 $O(n \log n)$ 만 걸려 관심 없는 원소까지 굳이 정렬까지 하는 셈이 된다. 따라서, 중앙값 찾기는 ‘정렬(sorting)’이 아닌 ‘선택(selection)’ 문제로 접근하는 게 낫다.</p>

<p>선택 문제를 일반화 하면 아래와 같다.</p>

<ul>
  <li>Input: 숫자 리스트 $S$, 정수 $k$</li>
  <li>Output: $S$ 에서 $k$ 번째로 작은 원소</li>
</ul>

<h2 id="선택을-위한-무작위-분할정복-알고리즘">선택을 위한 무작위 분할정복 알고리즘</h2>

<p>임의의 숫자 $v$ 에 대해</p>

\[S = \underbrace{S_L}_{\text{v보다 작음}} + \underbrace{S_V}_{\text{v와 같음}} + \underbrace{S_R}_{\text{v보다 큼}}\]

<p>로 나타낸다면, $S$를 $S_L, S_V, S_R$ 로 나누는 데 선형 시간이 걸린다.</p>

<p>여기서는 $v = 5, \vert S_L \vert = 3, \vert S_V \vert = 2$ 일 때 8번째로 작은 원소를 찾는다고 해보자. 그럼 앞의 5개는 이미 작기 때문에 $S_R$ 에서 3번째로 작은 원소를 찾으면 그것이 8번째로 작은 값이다. 즉 $\mathrm{selection}(S, 8) = \mathrm{selection}(S_R, 3)$</p>

<p>이를 정리하면, 선택 문제는 아래와 같이 작은 문제로 나눌 수 있다.</p>

\[\mathrm{selection}(S, k) = 
\begin{cases}
    \mathrm{selection}(S_L, k) &amp; k \le \vert S_L \vert \\
    v &amp; \vert S_L \vert \lt k \le (\vert S_L \vert + \vert S_V \vert) \\
    \mathrm{selection}(S_R, k - \vert S_L \vert - \vert S_V \vert) &amp; k \gt (\vert S_L \vert + \vert S_V \vert) \\
\end{cases}\]

<p>부분 리스트에서 재귀를 수행한단 뜻이다. 이렇게 문제를 해결할 때, 살펴야 하는 원소의 개수는 $\vert S \vert$ 에서 $\max {\vert S_L \vert , \vert S_R \vert}$ 로 줄어든다!</p>

<h2 id="시간-복잡도">시간 복잡도</h2>

<ul>
  <li>최악: 가장 크거나 가장 작은 $v$를 선택
    <ul>
      <li>$\vert S_R \vert = 0$ 또는 $\vert S_L \vert = 0$ 가 됨</li>
      <li>매번 재귀를 할 때마다 문제의 크기가 1씩만 줄어듦</li>
      <li>$n + (n-1) + \cdots + \frac{n}{2} = O(n^2)$</li>
    </ul>
  </li>
  <li>최선: 중앙값인 $v$를 선택
    <ul>
      <li>$\vert S_R \vert, \vert S_L \vert \approx \vert S \vert$</li>
      <li>따라서 선형 시간이 걸림. $T(n) = T(n/2) + O(n) \rightarrow O(n)$</li>
    </ul>
  </li>
</ul>

<p>되도록이면 $v$가 25~75분위수일 때가 좋다. 이 경우 $\vert S_R \vert, \vert S_L \vert$ 이 많아야 3/4 크기이기 때문에 배열이 크게 감소한다. 50%의 비율로 좋은 시간 복잡도를 가질 수 있다. 평균적으로, 2번을 연산했을 때 3/4로 문제가 줄어든다.</p>

<p>따라서 점화식은 아래와 같다.</p>

\[T(n) \le \underbrace{T \left( \cfrac{3}{4} n \right)}_{\text{크기가 } \frac{3}{4} n \text{인 문제}} + \underbrace{O(n)}_{\text{크기를 } \frac{3}{4} n \text{ 이하로 줄이는 시간}}\]

<p>최종적으로 선형시간인 $O(n)$ 이 걸린다.</p>

<hr />

<h1 id="25-행렬의-곱셈">2.5. 행렬의 곱셈</h1>

<p>기본적으로 행렬 곱을 하려면 $X_{n \times n} \times Y_{n \times n} = Z_{n \times n}$ 일 때, 계산할 항목이 $n^2$ 개이고 각 계산은 $O(n)$ 시간이 걸리므로, 총 $O(n^3)$ 이 걸린다.</p>

<p>위 문제를 분할정복법을 이용해 해결해볼 수 있다. 각 배열을 $n/2 \times n/2$ 크기의 작은 배열로 나눈다.</p>

\[XY = 
\begin{bmatrix}
    A &amp; B \\ C &amp; D
\end{bmatrix}
\begin{bmatrix}
    E &amp; F \\ G &amp; H
\end{bmatrix}
=
\begin{bmatrix}
    AE + BG &amp; AF + BH \\ CE + DG &amp; CF + DH
\end{bmatrix}\]

<p>이렇게 되면, 시간 복잡도는 $T(n) = 8T(n/2) + O(n^3)$으로, 여전히 $O(n^3)$ 으로 발전이 없어 보인다. 하지만 아래와 같은 방식을 사용하면, 부분문제를 8개가 아닌 7개로 줄일 수 있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/222915644-cb8838cb-dd68-48b9-b101-c684940117c2.png" width="60%" />
<figcaption>세 개의 수를 정렬하는 예시</figcaption>
</figure>

<p>그럼 시간은</p>

\[T(n) = 7T(n/2) + O(n^2) \rightarrow O(n^{log _2 7 \approx 2.81})\]]]></content><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><category term="Programming" /><category term="Algorithm" /><category term="Algorithm" /><summary type="html"><![CDATA[Master's Theory, Integer and Matrix Multiplication, Merge Sort, Median]]></summary></entry><entry><title type="html">Algorithms 3장: Decompositions of graphs</title><link href="https://winterbloooom.github.io/algorithms_ch3/" rel="alternate" type="text/html" title="Algorithms 3장: Decompositions of graphs" /><published>2023-02-03T00:00:00+09:00</published><updated>2023-02-03T00:00:00+09:00</updated><id>https://winterbloooom.github.io/algorithms_ch3</id><content type="html" xml:base="https://winterbloooom.github.io/algorithms_ch3/"><![CDATA[<h1 id="31-graph">3.1. Graph</h1>

<p>그래프와 그 요소를 표기하는 방식은 아래와 같다.</p>

<ul>
  <li>그래프 $G = (V, E)$ : $V$는 노드(정점(Vetrices)), $E$는 노드들을 잇는 에지(간선(edges))</li>
  <li>무향 간선 $e = {x, y}$, 유향 간선 $e = (x, y)$ 혹은 $x \rightarrow y$</li>
</ul>

<p>그래프를 표현하는 방식은 두 가지가 있다.</p>

<ul>
  <li><span style="color: #1565C0; background: #BBDEFB"><strong>인접행렬(Adjacency matrix)</strong></span>
    <ul>
      <li>무향 그래프라면 symmetric matrix이다.</li>
      <li>
\[a_{ij}=\begin{cases}1 &amp; (v_i \text{ 와 } v_j \text{간 간선 존재}) \\ 0 &amp; (\text{otherwise}) \end{cases}\]
      </li>
      <li>한 번의 메모리 접근으로 간선 존재 유무를 파악할 수 있다. 배열 [x, y] 혹은 [y, x]를 보면 되기 때문이다.</li>
      <li>$O(n^2)$ 공간이 필요한데, 그래프 내 간선이 적다면 공간의 낭비가 크다. 행렬이 대부분이 0으로 채워진다.</li>
    </ul>
  </li>
  <li><span style="color: #1565C0; background: #BBDEFB"><strong>인접리스트</strong></span>
    <ul>
      <li>리스트의 크기는 간선 수에 비례한다</li>
      <li>$\vert V \vert$ 개의 연결리스트가 존재한다. 따라서 전체 공간은 $O(\vert E \vert)$ 이다.</li>
      <li>간선의 조사는 상수 시간이 걸리지 않는다.</li>
      <li>대신 이웃 순환은 쉽다. 한 노드에 연결된 리스트 요소 따라가면 되니까.</li>
      <li>무향 그래프라면 대칭 구조다. $u$ 리스트에 $v$가 있고, 그 반대도 마찬가지.</li>
    </ul>
  </li>
</ul>

<p><img src="https://user-images.githubusercontent.com/69252153/223089447-80d25b65-f2ea-414c-9865-3f4b07ad0e19.png" alt="image" /></p>

<p>그래프의 상황에 따라 표현법을 선택하는 게 좋다.</p>

<ul>
  <li>Dense Graph: $\vert E \vert \fallingdotseq \vert V \vert ^2$</li>
  <li>Sparse Graph: $\vert E \vert \fallingdotseq \vert V \vert$</li>
</ul>

<hr />

<h1 id="32-무향-그래프의-dfs">3.2. 무향 그래프의 DFS</h1>

<p><code class="language-plaintext highlighter-rouge">explore(G, v)</code> 함수는 특정 노드로부터 닿을 수 있는 모든 노드를 탐색한다. 이는 스택이나 재귀로 구현 가능하다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/223090186-d2c75785-d3f4-4776-98f7-9747788b36e5.png" width="80%" />
<figcaption>explore() 알고리즘</figcaption>
</figure>

<p><code class="language-plaintext highlighter-rouge">explore</code> 의 방문 결과를 아래와 같이 트리로 나타낼 수 있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/223092318-82152763-8b86-4b97-9f2a-332d7c7813f8.png" width="70%" />
<figcaption>방문 결과 트리</figcaption>
</figure>

<h2 id="depth-first-search">Depth First Search</h2>

<p><span style="color: #1565C0; background: #BBDEFB"><strong>깊이 우선 탐색(Depth First Search, DFS)</strong></span>는 전체 그래프를 순회할 때까지 <code class="language-plaintext highlighter-rouge">explore(G, v)</code>를 반복한다. 이는 트리가 여러 개 모인 forest를 형성한다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/223094549-5549e090-a28f-4007-95ab-3b566c77a0a2.png" width="60%" />
<figcaption>DFS</figcaption>
</figure>

<p>한 정점 당 아래의 복잡도를 가진다.</p>

<ul>
  <li>$O(\vert V \vert)$: 방문 지점을 표시하고(<code class="language-plaintext highlighter-rouge">visited(v)</code>) <code class="language-plaintext highlighter-rouge">previsit(v)</code>, <code class="language-plaintext highlighter-rouge">postvisit(v)</code> 하기</li>
  <li>$O(\vert E \vert)$: 인접 간선의 루프를 찾는다. 간선 당 2번이다. $e = {x, y}$ 에서 $x \rightarrow y$ 한 번, $y \rightarrow x$ 한 번.</li>
</ul>

<p>따라서 $O(\vert V \vert + \vert E \vert)$ 이다.</p>

<h2 id="무향그래프에서-connectivity">무향그래프에서 Connectivity</h2>

<ul>
  <li><span style="color: #1565C0; background: #BBDEFB"><strong>연결(Connected)</strong></span>: 무향 그래프에선 모든 노드 쌍의 경로가 있을 때를 말한다.</li>
  <li><span style="color: #1565C0; background: #BBDEFB"><strong>연결 영역(connected components, subgraph)</strong></span>: <code class="language-plaintext highlighter-rouge">explore()</code>가 되는 부분을 말한다.</li>
</ul>

<p>따라서 DFS로 그래프의 연결 여부를 검사할 수 있다. 각 노드 $v$에 <code class="language-plaintext highlighter-rouge">explore</code> 호출 시마다 <code class="language-plaintext highlighter-rouge">ccum[v]</code> 정수를 할당해 연결 성분이 있는지 표시한다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>procedure previsit(v)
------------------------
ccnum[v] = cc
</code></pre></div></div>

<h2 id="카운터clock">카운터(Clock)</h2>

<p>처음 해당 노드를 발견했을 때(<code class="language-plaintext highlighter-rouge">previsit</code>)와 마지막으로 떠나갈 때(<code class="language-plaintext highlighter-rouge">postvisit</code>) 순서(시점)을 기록한다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>procedure previsit(v)
------------------------
pre[v] = clock
clock = clock + 1
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>procedure postvisit(v)
------------------------
post[v] = clock
clock = clock + 1
</code></pre></div></div>

<p>[pre, post]는 해당 정점이 스택에 들어오고 나간 시간, 즉 머문 시간이고, 스택은 First In Last Out (선입후출) 구조이다. 때문에 두 간격 [ pre (u), post (u)]와 [ pre (v), post (v)]는 서로 독립되어 있거나, 하나가 다른 하나를 포함한다.</p>

<hr />

<h1 id="33-유향그래프의-dfs">3.3. 유향그래프의 DFS</h1>

<p>특별하게 사용되는 용어들을 정리한다.</p>

<ul>
  <li>root: 트리의 시작 지점</li>
  <li>desendent: 어떤 노드로부터 뻗어나온 노드들</li>
  <li>ancestor: 해당 노드가 기원한 노드들</li>
  <li>parent: 해당 노드의 바로 직전 노드 (내가 기원한 노드)</li>
  <li>child: 해당 노드의 바로 직후 노드 (나로부터 뻗어나간 노드)</li>
</ul>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/223099788-9adc941c-1306-481b-ba48-9dacc6bcaed1.png" width="50%" />
<figcaption>DFS Tree</figcaption>
</figure>

<ul>
  <li>Tree edge: DFS forest의 일부</li>
  <li>Forward edge: 자식이 아닌 자손에게 이어짐</li>
  <li>Back edge: 부모가 아닌 조상에게 이어짐</li>
  <li>Cross edge: 자손도 조상도 아닌 노드에게 이어짐</li>
</ul>

<h2 id="directed-acyclic-graph">Directed Acyclic Graph</h2>

<p>유향 그래프는 DFS가 back edge가 있을 때만 순환(cycle)을 갖는다.</p>

<p><span style="color: #1565C0; background: #BBDEFB"><strong>유향 비순환 그래프(Directed Acyclic Graph, DAG)</strong></span>는</p>

<ul>
  <li>한 번의 DFS로 선형 시간에 acyclicity를 조사할 수 있다.</li>
  <li>선형화(linearize)(또는 위상정렬(topologically sort, 순서대로 배열))이 가능하다.
    <ul>
      <li><code class="language-plaintext highlighter-rouge">post</code> 숫자가 감소하도록 정렬하면 된다.</li>
      <li>가장 높은 <code class="language-plaintext highlighter-rouge">post</code>(‘source’)에서 가장 낮은 <code class="language-plaintext highlighter-rouge">post</code>(‘sink’) 순으로.</li>
    </ul>
  </li>
  <li>즉 모든 간선은 가장 낮은 <code class="language-plaintext highlighter-rouge">post</code>의 노드로 이어진다.</li>
</ul>

<hr />

<h1 id="34-strongly-connected-components">3.4. Strongly Connected Components</h1>
<h2 id="유향-그래프의-연결성connectivity">유향 그래프의 연결성(Connectivity)</h2>

<p>유향 그래프의 경우, 양 방향으로 path가 있어야 두 노드가 연결되었다(connected)고 한다.</p>

<p><span style="color: #1565C0; background: #BBDEFB"><strong>Strongly Connected Components(강한 연결 성분)</strong></span>는 meta node로 줄일 수 있다. <span style="color: #1565C0; background: #BBDEFB"><strong>Meta graph</strong></span>는 DAG이다.</p>

<p>따라서 모든 유향 그래프는 유향 그래프의 강한 성분들의 DAG이다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/223101365-2706f2a1-d72d-4150-80ae-c32f064abed0.png" width="80%" />
<figcaption>(a) 강한 연결 성분, (b) Meta graph</figcaption>
</figure>

<p>그래서 유향 그래프의 연결구조를 두 계층으로 나눌 수 있다. 최상위 DAG가 하나 있고, DAG의 노드 하나하나는 완전한(full fledged) 강한 연결성분이다.</p>

<h2 id="유향-그래프를-강한-연결-성분으로-분해하기">유향 그래프를 강한 연결 성분으로 분해하기</h2>

<p>DFS를 이용해 선형시간에 유향 그래프를 강한 연결 성분으로 분해할 수 있다.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">explore</code>의 서브루틴이 $u$에서 시작할 때, $u$에서 갈 수 있는 모든 노드를 방문하면 서브루틴이 종료된다.
    <ul>
      <li>e.g., 메타 그래프의 끝점(=강한 연결 성분의 끝점) 내 노드에서 호출하면 meta node를 순회하고 종료한다.</li>
    </ul>
  </li>
  <li>DFS에서 가장 높은 <code class="language-plaintext highlighter-rouge">post</code>의 노드는 메타 그래프의 끝점(=강한 연결 성분의 끝점)의 source이다.</li>
  <li>$C$, $C’$ 이 메타 그래프의 끝점(=강한 연결 성분의 끝점)이고, $C$ 내의 노드에서 $C’$ 내의 노드로 간선이 있다면, $C$ 내 가장 높은 <code class="language-plaintext highlighter-rouge">post</code> &gt;  $C’$ 내 가장 높은 <code class="language-plaintext highlighter-rouge">post</code>
    <ul>
      <li>메타 그래프의 끝점(=강한 연결 성분의 끝점)의 가장 높은 <code class="language-plaintext highlighter-rouge">post</code>를 감소시키는 순서로 배열하면, 강한 연결 성분을 선형화시킬 수 있다.</li>
    </ul>
  </li>
</ul>]]></content><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><category term="Programming" /><category term="Algorithm" /><category term="Algorithm" /><summary type="html"><![CDATA[Introduction of Graph, DFS, Strongly Connected Components]]></summary></entry><entry><title type="html">Mathematics for Machine Learning 6.2장: 확률과 분포 - 이산/연속 확률</title><link href="https://winterbloooom.github.io/math4ml_ch6_2/" rel="alternate" type="text/html" title="Mathematics for Machine Learning 6.2장: 확률과 분포 - 이산/연속 확률" /><published>2023-01-31T00:00:00+09:00</published><updated>2023-01-31T00:00:00+09:00</updated><id>https://winterbloooom.github.io/math4ml_ch6_2</id><content type="html" xml:base="https://winterbloooom.github.io/math4ml_ch6_2/"><![CDATA[<div id="inserted-box">
    <div class="notice-text"><p>이 내용은 책 <a href="https://mml-book.github.io/book/mml-book.pdf">Mathematics for machine learning(Marc Peter Deisenroth et al.)</a>을 기반으로 하고 있습니다.</p></div>
</div>

<h1 id="62-discrete-and-continuous-probabilities">6.2. Discrete and Continuous Probabilities</h1>

<table>
  <thead>
    <tr>
      <th>Probability Mass Function(pmf)</th>
      <th>Cumulative Distribution Function(cdf)</th>
    </tr>
    <tr>
      <th>확률 질량 함수</th>
      <th>누적 분포 함수</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Target space $\mathcal{T}$ 가 이산적임</td>
      <td>Target space $\mathcal{T}$ 가 연속적임</td>
    </tr>
    <tr>
      <td>확률 변수 X가 특정 값 $x \in \mathcal{T}$ 을 가짐</td>
      <td>확률 변수 X가 범위 $a \le x \le b$ 로 나타남</td>
    </tr>
    <tr>
      <td>$P(X=x)$</td>
      <td>$P(a\le X \le b)$ or $P(X \le x)$</td>
    </tr>
  </tbody>
</table>

<table>
  <thead>
    <tr>
      <th>Univariate Distribution</th>
      <th>Multivariate Distribution</th>
    </tr>
    <tr>
      <th>일변량 분포</th>
      <th>다변량 분포</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>하나의 확률 변수 $x$ 에 대한 분포</td>
      <td>여러 확률 변수 $\boldsymbol{x}$ 에 대한 분포</td>
    </tr>
  </tbody>
</table>

<hr />

<h2 id="이산-확률-discrete-probabilities">이산 확률 (Discrete Probabilities)</h2>

<p>앞서 본 표대로 Target space $\mathcal{T}$ 가 이산적일 때에 해당한다.</p>

<p>이산 확률 분포의 ‘확률 질량 함수(Probability Mass Function(pmf)’는 아래와 같이 표로 쉽게 알아볼 수 있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216227760-e29e08a1-311f-41ed-8a5d-bc5a0c7896b9.jpg" width="70%" />
<figcaption>Fig. 1</figcaption>
</figure>

<p>위 표에서 $n_{ij}$ 는 각 상태 $x_i, y_i$ 에 해당하는 사건의 개수(횟수)이며, 모든 사건의 전체 개수를 $N$ 이라 표시한다. 위 그림에서 $N=15$ 이다. $c_i$ 는 $i$ 번째 열의 각각의 빈도를 모두 더한 것, 쉽게 말하자면 그 열의 합을 말하고, 같은 원리로 $r_j$는 그 행의 합을 말한다. 위 사진을 예시로 하면 아래와 같이 계산한다.</p>

\[\begin{aligned}
  c_i &amp;= \sum \limits_{j=1}^3 n_{ij} \\
  r_j &amp;= \sum \limits_{i=1}^5 n_{ij}
\end{aligned}\]

<h3 id="결합-확률joint-probability">결합 확률(Joint Probability)</h3>

<p>두 값을 결합적으로 고려해 한 값을 내는 확률이다. Fig.1에서는 특정 한 칸을 나타내며, 수학적으로는 각 확률변수가 가진 target space의 Cartesian product으로 구할 수 있다.</p>

\[P(X=x_i, Y=y_i) = \cfrac{n_{ij}}{N}\]

<p>위 식을 예로 들어보자면, 특정 $x_i, y_i$가 동시에 일어날 확률이라 생각하면 된다. 식에서도 알 수 있듯이, 결합 확률은 양 사건의 교집합의 확률이다. 즉 $P(X=x_i, Y=y_i) = P(X=x_i \cap Y=y_i)$ 인 것이다.</p>

<p>특정 x, y에 대한 확률은 $p(x, y)$라 표기한다. 이렇게 표기하면 마치 x, y를 입력으로 받아 어떤 실수값을 돌려주는 함수처럼 보인다. 즉, 확률을 함수처럼 여길 수 있다.</p>

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216227850-16656a79-9767-4207-bc15-662aab428aad.jpg" width="70%" />
<figcaption>Fig. 2</figcaption>
</figure>

<h3 id="주변-확률marginal-probability">주변 확률(Marginal Probability)</h3>

<p>어떤 확률 변수의 특정 값일 확률을 ‘다른 확률 변수들의 값과는 무관하게’ 구한다. 즉, 내가 알아보고 싶은 확률변수만의 확률로 나타낸다. 그러므로 X, Y 중에 Y와 무관하게 $X=x$ 일 확률만 알고 싶다면 표기는 $p(x)$라고 한다. $p(x)$ 에 따라 분포된 확률변수 X 임을 나타내고 싶다면 $X \sim p(x)$ 라고 표기한다.</p>

<p>그 정의를 곱씹어보면, 주변확률은 각 열 혹은 각 행의 합을 전체 개수로 나누어준 값이다.</p>

\[\begin{aligned}
  P(X=x_i) &amp;= \cfrac{c_i}{N} = \cfrac{\sum \limits_{i=1}^3 n_{ij}}{N} \\
  P(Y=y_j) &amp;= \cfrac{r_i}{N} = \cfrac{\sum \limits_{i=1}^5 n_{ij}}{N}
\end{aligned}\]

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216228073-3c09387e-8048-4fd2-9270-70ddb780894b.jpg" />
<figcaption>Fig. 3</figcaption>
</figure>

<h3 id="조건부-확률conditional-probability">조건부 확률(Conditional Probability)</h3>

<p>한 확률변수가 특정 값일 때의 다른 확률 변수의 특정 값을 구하고 싶다면, 그건 조건부 확률이다. 결합 확률과 차이는, 조건부 확률은 한 확률 변수에 대한 값이 ‘조건’으로 들어가 제한을 둔다는 점이다.</p>

<p>예를 들어 $X=x$일 때의 $Y=y$ 일 확률을 구하고 싶다면 $p(y \vert x)$ 로 표기한다. 그림을 이용해 수식으로 생각해보면, 조건부 확률은 특정 행/열에 대한 특정 칸의 비율이다.</p>

\[\begin{aligned}
  P(X=x_i \vert Y=y_j) &amp;= \cfrac{n_{ij}}{r_i} \\
  P(Y=y_j \vert X=x_i) &amp;= \cfrac{n_{ij}}{c_i}
\end{aligned}\]

<figure>
<img src="https://user-images.githubusercontent.com/69252153/216228160-8d5357c9-0f6d-4a2f-bbd7-a16dd311de77.jpg" />
<figcaption>Fig. 4</figcaption>
</figure>

<h3 id="categorical-variables">Categorical Variables</h3>

<p>머신러닝에선 이산 확률 분포를 ‘카테고리형 변수’로 이용한다. 즉 변수를 순서가 없는 유한 집합으로 본다. 예를 들자면, 각 사람의 연봉을 예측할 때 대학 학위 종류를 본다던지, 손글씨 인식을 할 때 알파벳의 종류를 본다던지 등이다.</p>

<p>또는 유한 개의 개수를 가진 연속 분포와 결합한 확률 모델을 만들 때 이산 분포를 사용하기도 한다. 이는 11장(Density Estimation with Gaussian Mixture Models)에서 계속된다.</p>

<hr />

<h2 id="연속-확률-continuous-probabilities">연속 확률 (Continuous Probabilities)</h2>

<p>연속 확룰에서 다루는 확률 변수는 실수값 확률 변수, 즉 $\mathbb{R}$ 위의 간격이 target space가 된다.</p>

<p>용어 ‘measure(측도)’란, 집합의 크기(size)를 말한다. 이산 공간(discrete spaces)에서는 요소의 개수를 세서 구할 수 있다(cardinality). 그 밖에도 $\mathbb{R}$ 의 간격의 길이 혹은 $\mathbb{R}^d$ 의 영역의 부피를 일컫는 등 역시 measure이다.</p>

<div id="inserted-box">
    <div class="notice-text"><p>보렐 집합(Borel set)은 열린 집합에서 가산 합집합, 가산 교집합, 차집합 연산을 유한번 반복해 만들 수 있는 집합(집합 연산이 가능하고 topology를 가진 집합)을 말한다. 보렐 집한인 이들을 ‘보렐 시그마 대수(Borel σ-algebra)’를 따른다고 말한다. 이 책에서는 보렐 시그마 대수에 대응하는 실수값 확률 변수를 다룬다.</p></div>
</div>

<p>$\mathbb{R}^D$ 에서의 값을 가지는 확률 변수를 실수값 확률 변수의 벡터로 사용한다.</p>

<div id="def-box">
<div class="def-title">확률 밀도 함수(Probability Density Function, pdf)</div>
<p>

아래의 조건을 만족하는 함수 $f: \mathbb{R}^D \rightarrow \mathbb{R}$ 을 말한다.

* $\forall \boldsymbol{x} \in \mathbb{R}^D : f(\boldsymbol{x}) \ge 0$
* 적분이 가능하고(존재하고) 그 값이 1 ($\int_{\mathbb{R}^D}f(\boldsymbol{x})d\boldsymbol{x} = 1$)

</p>
</div>

<p>이산 확률 변수의 확률 질량 함수(pdf)에 대해선 적분 대신 합($\sigma$)로 한다. 여긴 연속 확률 변수라 적분이다.</p>

<p>특정 범위에서의 확률은 $P(a \le X \le b) = \int_a^b f(x) dx$ 로 나타낸다. (‘확률 변수 X의 법칙/분포’)</p>

<p>주의할 것은, 연속 확률 변수의 확률은 특정 값 하나에서의 확률은 0이라는 점이다. 즉 $P(X=x) = 0$ 이다. 이는 적분 식 시작과 끝에 같은 값을 넣어보면($a=b$) 수긍이 된다.</p>

<div id="def-box">
<div class="def-title">누적 분포 함수(Cumulative Distribution Function, cdf)</div>
<p>

다변수 실수값 확률 변수에 대한 분포 함수이다. 상태는 벡터 $\boldsymbol{x} \in \mathbb{R}^D$ 로 나타난다.

$$
\begin{align}
  F_{X}(\boldsymbol{x})
  &amp;= P(X_1 \le x_1, X_2 \le x_2, \cdots, X_D \le x_D) \\
  &amp;= \int_{-\infty}^{x_1} \cdots \int_{-\infty}^{x_D} f(z_1, \cdots, z_d) dz_1 \cdots dz_D
\end{align}
$$

이때 $X = [X_1, \cdots, X_D]^T$ , $\boldsymbol{x} = [x_1, \cdots, x_D]^T$ 이다.
</p>
</div>

<p>위 정의에서 (1)번 식이 의미하는 바는, 각 변수 $X_i$가 특정값 $x_i$ 보다 작거나 같을 때의 확률이란 뜻이다. (2)번 식은 누적 분포 함수를 확률 밀도 함수의 적분으로 본 표현이다.</p>

<p>지금까지 pmf, pdf, cdf 세 함수를 봤는데, 이를 정리해보자.</p>

<table>
  <thead>
    <tr>
      <th>Type</th>
      <th>Point probability</th>
      <th>Interval Probability</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Discrete</td>
      <td>$P(X=x)$ pmf</td>
      <td>X</td>
    </tr>
    <tr>
      <td>Continuous</td>
      <td>$p(x)$ pdf</td>
      <td>$P(X \le x)$ cdf</td>
    </tr>
  </tbody>
</table>

<hr />

<h2 id="이산--연속-분포의-차이">이산 / 연속 분포의 차이</h2>

<p>기본적으로, 확률은 양수이며 모든 확률의 합은 1이 된다고 했다. 이산 확률 변수의 경우, 그 규칙을 따를 때 각 상태의 확률은 0에서 1 사이의 값을 갖게 된다. 그러나 연속 확률 변수에 대해 정규화(normalization)은 꼭 밀도값이 1보다 작거나 같진 않다.</p>

<p><img src="https://user-images.githubusercontent.com/69252153/216298221-c8ace446-005f-4005-8faa-b7a8a45d2705.png" alt="image" /></p>

<p>위 사진은 균일 분포(Uniform distribution)을 나타냈다. 균일 분포란, 각 상태가 똑같이 일어난다는 것을 말한다.</p>

<p>이산 확률 변수 Z에 대해 상태는 $z = -1.1, 0.3, 1.5$ 이고 각 확률은 $P(Z=-1.1)=P(Z=0.3)=P(Z=1.5)=\frac{1}{3}$로 같다.</p>

<p>연속 확률 변수 X가 범위 $0.9 \le X \le 1.6$ 에서 정의된다고 하자. 이산 확률 변수와는 다르게 각 위치에서 y좌표는 그림 (b)처럼 1보다 클 수도 있다. 다만 적분 시 1이 된다는 것만 지키면 된다. 그 말인 즉, 균일 분포의 위 예시를 들어보자면, $\int_{0.9}^{1.6}p(x)dx=1, p(x)=\frac{1}{0.7}$ 이다.</p>]]></content><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><category term="Math" /><category term="Math for ML" /><category term="Math" /><category term="Machine Learning" /><summary type="html"><![CDATA[Probability and Distributions - Discrete and Continuous Probabilities]]></summary></entry><entry><title type="html">Mathematics for Machine Learning 7.2장: 최적화 - 제한된 최적화와 라그랑주 승수</title><link href="https://winterbloooom.github.io/math4ml_ch7_2/" rel="alternate" type="text/html" title="Mathematics for Machine Learning 7.2장: 최적화 - 제한된 최적화와 라그랑주 승수" /><published>2023-01-30T00:00:00+09:00</published><updated>2023-01-30T00:00:00+09:00</updated><id>https://winterbloooom.github.io/math4ml_ch7_2</id><content type="html" xml:base="https://winterbloooom.github.io/math4ml_ch7_2/"><![CDATA[<div id="inserted-box">
    <div class="notice-text"><p>이 내용은 책 <a href="https://mml-book.github.io/book/mml-book.pdf">Mathematics for machine learning(Marc Peter Deisenroth et al.)</a>을 기반으로 하고 있습니다.</p></div>
</div>

<h1 id="72-constrained-optimization-and-lagrange-multipliers">7.2. Constrained Optimization and Lagrange Multipliers</h1>

<h2 id="constrained-optimization-problem">Constrained Optimization Problem</h2>

<p>7.1장에서 보았던 최적화 문제는 단순히 함수의 최솟값을 찾는 문제였다. 이번 장에서는 제약(constraints)이 추가된 문제를 볼 것이다.</p>

<p>최소화하려는 함수 $f: \mathbb{R}^D \rightarrow \mathbb{R}$ 과 문제 $\min_x f(\boldsymbol{x})$은 동일하다. 거기에 $i = 1, \cdots, m$ 에 대한 실숫값 함수 $g_i: \mathbb{R}^D \rightarrow \mathbb{R}$을 제한으로 걸게 된다.</p>

\[\begin{aligned} 
  \min_x \quad &amp;f(\boldsymbol{x}) \\
  \mathrm{subject \ to} \quad  &amp;g_i(\boldsymbol{x}) \le 0 \quad \mathrm{for \ all} \quad i = 1, \cdots, m
\end{aligned} \tag{1}\]

<p>여기서 $f, g_i$는 non-convex라 하겠다. 두 함수가 convex인 경우는 다음 장에서 본다.</p>

<h2 id="lagrangian">Lagrangian</h2>

<p>위와 같은 ‘제한된 최적화 문제’를 ‘제한 없는(Unconstrained)’ 문제로 풀기 위한 방법 중 하나는 지시 함수(Indicator function)을 사용하는 것이다.</p>

<p>무한한 계단 함수(step func.) $\boldsymbol{1}(z)$ 를 아래와 같이 정의할 때</p>

\[\boldsymbol{1}(z) = \begin{cases} 0 &amp; (z \le 0) \\ \infty &amp; (z &gt; 0) \end{cases}\]

<p>지시 함수는</p>

\[J(\boldsymbol{x}) = f(\boldsymbol{x}) + \sum \limits_{i=1}^m \boldsymbol{1}(g_i(\boldsymbol{x}))\]

<p>로 한다. 게단 함수를 위와 같이 정의해 지시함수에 포함함으로써, 제약(constraint)가 충족되지 않았을 땐 무한($\infty$)의 패널티를 부과하는 원리다.</p>

<p>물론 위와 같은 방법으로 동일한 해를 찾을 수는 있겠지만, 무한 계단 함수는 constraint problem과 마찬가지로 최적화가 어렵다. 그래서 도입한 것이 라그랑주 승수(Larange multipliers)이다.</p>

<p>라그랑주 승수의 주된 아이디어는 ‘계단 함수를 선형함수로 대체한다’이다.</p>

<p>Constrained Optimization Problem인 식 (1)을 라그랑주와 결함할 때, 라그랑즈 승수 $\lambda_i \ge 0$ 을 도입한다. 이 라그랑주 승수는 각각의 제한 부등식(inequality constraint) $g_i(\boldsymbol{x}) \le 0$와 대응한다. 따라서</p>

\[\mathfrak{L}(\boldsymbol{x, \lambda}) = f(\boldsymbol{x}) + \sum \limits_{i=1}^m \lambda_i g_i(\boldsymbol{x}) = f(\boldsymbol{x}) + \boldsymbol{\lambda}^T \boldsymbol{g}(\boldsymbol{x})\]

<p>이다. 특히 마지막 식에선 모든 제약조건 $g_i(\boldsymbol{x})$를 하나의 벡터 $\boldsymbol{g}$로, 모든 라즈랑주 승수를 하나의 벡터 $\boldsymbol{\lambda}$ 로 나타냈다.</p>

<h2 id="lagrangian-duality상대성">Lagrangian Duality(상대성)</h2>

<p>최적화에서 상대성(duality)이란, 한 변수의 집합 $\boldsymbol{x}$ 의 최적화 문제를 다른 변수의 집합 $\boldsymbol{\lambda}$ 의 최적화 문제로 전환하는 것을 말한다. 여기서 변환 이전 변수를 Primal variables, 이후 변수를 Dual variables라고 한다.</p>

<p>상대성을 다루는 두 가지 방법을 알아볼 것이며, 그 중 첫번째인 Lagrangian Duality는 지금, 다른 하나인 Legendre-Fenchel(르장드르-펜첼) duality는 다음 장에서 볼 예정이다.</p>

<div id="def-box">
<div class="def-title">Primal Problem</div>
<p>

primal variables $x$ 에 대응하는 primal problem은 아래와 같이 정의한다.

$$
\begin{aligned} 
  \min_x \quad &amp;f(\boldsymbol{x}) \\
  \mathrm{subject \ to} \quad  &amp;g_i(\boldsymbol{x}) \le 0 \quad \mathrm{for \ all} \quad i = 1, \cdots, m
\end{aligned}
$$
</p>
</div>

<div id="def-box">
<div class="def-title">Lagrangian Dual Problem</div>
<p>

Dual variables $\boldsymbol{\lambda}$ 에 대해 Lagrangian Dual Problem은 아래와 같이 정의한다.

$$
\begin{aligned} 
  \max_{\boldsymbol{\lambda} \in \mathbb{R}^m} \quad &amp;\mathfrak{D}(\boldsymbol{\lambda}) \\
  (&amp;\mathfrak{D}(\boldsymbol{\lambda}) = \min_{\boldsymbol{x} \in \mathbb{R}^d} \mathfrak{L}(\boldsymbol{x, \lambda})) \\
  \mathrm{subject \ to} \quad  &amp;\boldsymbol{\lambda} \ge \boldsymbol{0}
\end{aligned}
$$
</p>
</div>

<p>$\mathfrak{D}(\boldsymbol{\lambda})$ 은 dual object function이다. Primal Problem을 이해하기 위해 두 가지 개념을 짚고 넘어간다.</p>

<h3 id="minimax-inequality">Minimax Inequality</h3>

<p>두 인자를 가진 임의의 함수 $\varphi(\boldsymbol{x}, \boldsymbol{y})$ 에 대해, maximin은 minimax 보다 작다. 이를 식으로 나타내면 아래와 같다.</p>

\[\max_{\boldsymbol{y}} \min_{\boldsymbol{x}} \varphi(\boldsymbol{x, y}) \le  \min_{\boldsymbol{x}} \max_{\boldsymbol{y}} \varphi(\boldsymbol{x, y}) \tag{2}\]

<p>식 (2)는 아래와 같은 부등식 (3)을 이용해 증명할 수 있다.</p>

\[\mathrm{For \ all \ \boldsymbol{x, y}} \quad \min_{\boldsymbol{x}} \varphi(\boldsymbol{x, y}) \le \max_{\boldsymbol{y}} \varphi(\boldsymbol{x, y}) \tag{3}\]

<p>식 (3)은 식 (2)의 양변 안쪽 항에 해당한다. 따라서 식 (2)의 좌변은 직관적으로 보자면 ‘최소 중에서 최대로’, 우변은 ‘최대 중에서 최소로’의 뜻이 된다.</p>

<h3 id="weak-duality">Weak Duality</h3>

<p>앞서 본 Minimax imequality 식(2)를 활용해, ‘primal values나 항상 dual values 보다 크거나 같음’을 말한다.</p>

<p>앞서 ‘제한된 최적화 문제’를 ‘제한 없는(Unconstrained)’ 문제로 풀기 위한 방법으로 지시함수 $J(\boldsymbol{x})$ 를 사용하는 방법을 논한 바 있었다. 또한 라그랑주를 활용한 방법도 보았다. 두 방법의 차이는 지시 함수를 선형 함수로 바꾸는 것이었다. 그러므로, $\lambda \ge 0$ 일 때 라그랑주 $\mathfrak{L}(\boldsymbol{x, \lambda})$ 는 $J(\boldsymbol{x})$ 의 하한(lower bound, 하계(아래로 유계)) 다. 이를 바꾸어 말하면 $\boldsymbol{\lambda}$에 대한 $\mathfrak{L}(\boldsymbol{x, \lambda})$ 의 최댓값을 아래와 같이 표현할 수 있다.</p>

\[J(\boldsymbol{x}) = \max_{\boldsymbol{\lambda} \ge 0}\mathfrak{L}(\boldsymbol{x, \lambda})\]

<p>애초 최적화 문제는 $J(\boldsymbol{x})$ 를 최소화하는 것이었으므로</p>

\[\min_{\boldsymbol{x} \in \mathbb{R}^d} \max_{\boldsymbol{\lambda} \ge 0}\mathfrak{L}(\boldsymbol{x, \lambda})\]

<p>로 나타낼 수 있고, minimax inequality(식 (2))를 적용하면</p>

\[\min_{\boldsymbol{x} \in \mathbb{R}^d} \max_{\boldsymbol{\lambda} \ge 0} \mathfrak{L}(\boldsymbol{x, \lambda}) \ge \max_{\boldsymbol{\lambda} \ge 0} \min_{\boldsymbol{x} \in \mathbb{R}^d} \mathfrak{L}(\boldsymbol{x, \lambda})
\tag{4}\]

<p>이다. 이것이 weak duality이다. 참고로 우변의 $\mathfrak{L}(\boldsymbol{x, \lambda})$ 은 앞서 정의했듯 dual object function $\mathfrak{D}(\boldsymbol{\lambda})$ 이다.</p>

<p>우변의 안쪽 항을 살펴보자. 제약조건(constraints)가 있었던 본래 최적화 문제와는 다르게, $\min_{\boldsymbol{x} \in \mathbb{R}^d} \mathfrak{L}(\boldsymbol{x, \lambda})$ 은 주어진 값 $\boldsymbol{\lambda}$ 에 대한 제약이 없는 최적화 문제가 된다. 이 $\min_{\boldsymbol{x} \in \mathbb{R}^d} \mathfrak{L}(\boldsymbol{x, \lambda})$ 문제의 풀이가 쉽다면, 전체적 문제 역시 풀기 쉬워진다.</p>

<p>정말 그럴지, Lagrangian Dual Problem을 다시 상기해보자.</p>

\[\begin{aligned} 
  \max_{\boldsymbol{\lambda} \in \mathbb{R}^m} \quad &amp;\mathfrak{D}(\boldsymbol{\lambda}) \qquad  (\mathfrak{D}(\boldsymbol{\lambda}) = \min_{\boldsymbol{x} \in \mathbb{R}^d} \mathfrak{L}(\boldsymbol{x, \lambda})) \\
  \mathrm{subject \ to} \quad  &amp;\boldsymbol{\lambda} \ge \boldsymbol{0}
\end{aligned}\]

<p>위 최적화 문제에서 $\mathfrak{L}(\boldsymbol{x, \lambda})$ 는 $\boldsymbol{\lambda}$ 에 대한 어파인(affine) 이었다. 따라서 $\min_{\boldsymbol{x} \in \mathbb{R}^d} \mathfrak{L}(\boldsymbol{x, \lambda})$ 는 점 별로(pointwise) $\boldsymbol{\lambda}$ 에 대한 어파인 함수의 최솟값인 셈이다. 또한 $\mathfrak{D}(\boldsymbol{\lambda})$ 은 $f, g_i$가 convex하지 않더라도 concave(위로 오목한)하다.</p>

<div id="inserted-box">
    <div class="notice-text"><p>Affine Function(어파인 함수)는 $f(x_1, \cdots, x_n) = A_1 x_1 + \cdots + A_n x_n + b$ 형태로 이루어진 함수를 말한다.</p></div>
</div>

<div id="inserted-box">
    <div class="notice-text"><p>Convex는 아래로 볼록, Concave는 위로 볼록한 형태를 가진다. <img src="https://user-images.githubusercontent.com/69252153/215407696-434b305c-ba9a-448e-b878-8cebc2059843.png" /></p></div>
</div>

<p>Weak Duality (식 (4)) 우변의 바깥 문제( $\lambda$ 에 대한 maximum, 즉 $\max_{\boldsymbol{\lambda} \ge 0} \min_{\boldsymbol{x} \in \mathbb{R}^d} \mathfrak{L}(\boldsymbol{x, \lambda})$ ) 시야를 넓여보자. 그 말인 즉슨, 위로 오목한 형태의 concave 함수의 최댓값을 찾겠단 소린데, 극대점은 하나로 분명하다. 따라서 찾기도 쉽고 연산도 효율적이다. 즉, 최적화 문제 풀이가 보다 쉬워진다.</p>

<p>만약 함수 $f(\cdot)$ 과 $g_i(\cdot)$ 이 미분 가능한 함수라면, Lagrange dual problem을 쉽게 찾을 수 있다. x에 대한 Lagrangian을 미분하고, 미분(differential)을 0으로 둔 뒤 최적값(optimal value)를 찾으면 된다. 두 함수가 convex일 때의 구체적 예시는 차차 다룰 예정이다.</p>

<hr />

<h2 id="equality-constraints">Equality Constraints</h2>

<p>이번장 초반에 다루었던 제약 조건이 있는 최적화 문제는 아래와 같았다.</p>

\[\begin{aligned} 
  \min_x \quad &amp;f(\boldsymbol{x}) \\
  \mathrm{subject \ to} \quad  &amp;g_i(\boldsymbol{x}) \le 0 \quad \mathrm{for \ all} \quad i = 1, \cdots, m
\end{aligned} \tag{1}\]

<p>Inequality constraints $g_i(\boldsymbol{x})$ 을 포함하고 있는 식 (1)에, equality constraints $h_j(\boldsymbol{x})$를 추가해 아래와 같이 문제를 나타내자.</p>

\[\begin{aligned} 
  \min_x \quad &amp;f(\boldsymbol{x}) \\
  \mathrm{subject \ to} \quad  &amp;g_i(\boldsymbol{x}) \le 0 \quad \mathrm{for \ all} \quad i = 1, \cdots, m \\
  &amp;h_j(\boldsymbol{x}) = 0 \quad \mathrm{for \ all} \quad j = 1, \cdots, n
\end{aligned} \tag{5}\]

<p>Equality constraints 을 두 개의 Inequality constraints 로 바꿔 모델링할 수 있다. 다시 말해, 각 equality constraints $h_j(\boldsymbol{x}) = 0$ 에 대해 두 개의 constraint $h_j(\boldsymbol{x}) \le 0$ ,  $h_j(\boldsymbol{x}) \ge 0$ 로 바꾸는 것이다. 그럼 결과적으로 라그랑주 승수가 unconstrained가 된다.</p>

<p>따라서, 식(5)의 Inequality constraints에 대응하는 라그랑주 승수를 음이 아니도록(non-negative) 제한했고(constrain),  Equality constraints에 대응하는 라그랑주 승수는 제약이 없도록 했다(unconstrained).</p>]]></content><author><name>EunGi Han</name><email>winterbloooom@gmail.com</email></author><category term="Math" /><category term="Math for ML" /><category term="Math" /><category term="Machine Learning" /><summary type="html"><![CDATA[Continuous Optimization - Constrained Optimization and Lagrange Multipliers]]></summary></entry></feed>