<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://angeloyeo.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://angeloyeo.github.io/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-04-09T04:07:14+00:00</updated><id>https://angeloyeo.github.io/feed.xml</id><title type="html">공돌이의 수학정리노트 (Angelo’s Math Notes)</title><subtitle>Your Site Description
</subtitle><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><entry xml:lang="ko"><title type="html">쿼드콥터의 동역학 모델링 (오일러-라그랑주 방정식 기반)</title><link href="https://angeloyeo.github.io/2026/03/16/Quadcopter_Dynamics_Modeling.html" rel="alternate" type="text/html" title="쿼드콥터의 동역학 모델링 (오일러-라그랑주 방정식 기반)" /><published>2026-03-16T00:00:00+00:00</published><updated>2026-03-16T00:00:00+00:00</updated><id>https://angeloyeo.github.io/2026/03/16/Quadcopter_Dynamics_Modeling</id><content type="html" xml:base="https://angeloyeo.github.io/2026/03/16/Quadcopter_Dynamics_Modeling.html"><![CDATA[<p>쿼드콥터는 어떻게 움직일까? 오일러-라그랑주로 풀어보는 동역학 모델링</p>

<p>쿼드콥터를 제어하려면 먼저 이 기체가 어떤 물리 법칙에 따라 움직이는지 알아야 합니다. 단순히 “모터를 돌리면 뜬다”를 넘어, “모터 속도를 얼마나 조절해야 내가 원하는 위치로 정확히 갈까?”를 계산하기 위한 <strong>수학적 설계도(모델)</strong>를 그려보는 과정입니다. 오늘은 Raffo 등의 논문[1]과 MATLAB Symbolic Math Toolbox의 문서[2]를  바탕으로 그 흐름을 따라가 보겠습니다.</p>

<h1 id="prerequisites">Prerequisites</h1>

<p>이 포스팅을 더 잘 이해하기 위해선 아래의 내용을 이해하고 오는 것이 좋습니다.</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2026/03/15/Euler_Lagrange.html">Euler-Lagrange 방정식 (변분법)</a></li>
</ul>

<h1 id="1-질문의-시작-쿼드콥터의-상태를-어떻게-정의할까">1. 질문의 시작: “쿼드콥터의 상태를 어떻게 정의할까?”</h1>

<p>모델링을 하려면 먼저 무엇을 관찰할지 정해야 한다. 우선 [1]의 논문에서 우리가 보고자하는 쿼드콥터의 geometry는 아래 [2]의 그림처럼 정의하고 있다.</p>

<p><img src="../pics/2026-03-16-Quadcopter_Dynamics_Modeling/pic1.png" alt="" /></p>

<p>쿼드콥터는 공간에서 자유롭게 움직이므로 <strong>6자유도</strong>를 가진다.</p>

<ul>
  <li><strong>위치 ($\xi$):</strong> 지구 기준에서 어디에 있는가? $(x, y, z)^T$.</li>
  <li><strong>자세 ($\eta$):</strong> 지구 기준에서 얼마나 기울어져 있는가? 롤, 피치, 요 $(\phi, \theta, \psi)^T$.</li>
</ul>

<p>여기에 각각의 속도까지 더하면 총 <strong>12개의 상태 변수</strong>가 우리 시스템의 주인공이 된다.</p>

\[(x, y, z, \phi, \theta, \psi, \dot x, \dot y, \dot z, \dot \phi, \dot \theta, \dot \psi)^T % 식 (1)\]

<p>추가로 쿼드콥터의 모션을 기술하기 위해 아래와 같이 파라미터들을 정의하도록 하자.</p>

<ul>
  <li>$U_1 = (u_1, u_2, u_3, u_4) = (\omega_1^2, \omega_2^2, \omega_3^2, \omega_4^2)$ 이는 각 로터의 각속도의 제곱을 의미한다. $U$를 사용한 것은 이것이 메인 제어 입력임을 나타내기 위함이기도 하다. 또, $U$의 방향은 기체에서의 $+z$ 방향이다. (이 포스팅에서는 기체의 등쪽을 $+z$ 성분으로 정의하고 있다.)</li>
  <li>$(I_{xx}, I_{yy}, I_{zz})$ 이는 body frame의 관성 행렬의 대각 성분을 의미한다.</li>
  <li>$(k,l,m,b,g)$는 각각 추력 계수, 무게 중심으로부터 로터까지의 거리, 쿼드콥터의 질량, 항력 계수, 그리고 중력을 의미한다.</li>
  <li>$f_\xi$는 4개의 프로펠러가 합쳐서 만들어내는 전체 추력과 공기 역학적 방해를 포함하는 병진력을 의미한다.</li>
  <li>$\tau_\eta$는 기체를 회전시키기 위해 각 모터의 속도 차이로 만들어내는 롤, 피치, 요 방향의 회전력을 의미한다.</li>
  <li>$\alpha_T = [A_x, A_y, A_z]^T$는 기체에 가해지는 다양한 항공역학적 힘을 나타낸다.</li>
</ul>

<p>또, 기체 좌표계($\mathscr{B}$)에서 관성 좌표계 ($\mathscr{I}$, 지구로도 생각할 수 있음)로 변환하기 위한 기본 회전 행렬(Elementary Rotation Matrices)을 정의하도록 하자. 오일러각 $\eta = (\phi, \theta, \psi)^T$에 대해 아래와 같이 정의할 수 있다.</p>

<ul>
  <li>$R_x(\phi)$: $x$축을 중심으로 롤(Roll) 각도만큼 회전하는 행렬</li>
</ul>

\[R_x(\phi) = \begin{bmatrix}
  1 &amp;&amp; 0 &amp;&amp; 0 \\ 
  0 &amp;&amp; \cos\phi &amp;&amp; -\sin\phi \\ 
  0 &amp;&amp; \sin\phi &amp;&amp; \cos\phi
\end{bmatrix}% 식 (2)\]

<ul>
  <li>$R_y(\theta)$: $y$ 축을 중심으로 피치(Pitch) 각도만큼 회전하는 행렬</li>
</ul>

\[R_y(\theta) = \begin{bmatrix}
  \cos\theta &amp;&amp; 0 &amp;&amp; \sin\theta \\ 
  0 &amp;&amp; 1 &amp;&amp; 0 \\ 
  -\sin\theta &amp;&amp; 0 &amp;&amp; \cos\theta
\end{bmatrix}% 식 (3)\]

<ul>
  <li>$R_z(\psi)$: $z$ 축을 중심으로 요(Yaw) 각도만큼 회전하는 행렬</li>
</ul>

\[R_z(\psi) = \begin{bmatrix}
  \cos\psi &amp;&amp; -\sin\psi &amp;&amp; 0 \\ 
  \sin\psi &amp;&amp; \cos\psi &amp;&amp; 0 \\ 
  0 &amp;&amp; 0 &amp;&amp; 1
\end{bmatrix}% 식 (4)\]

<p>이 세 개의 기본 회전 행렬을 이용해서 기체의 좌표계($\mathscr{B}$)에서 관성 좌표계 ($\mathscr{I}$)로 물리량을 (힘, 속도 등)을 변환할수 있다. 변환의 순서는 X, Y, Z 순서로 곱해져야 하므로 행렬의 오른쪽에 벡터가 붙는 것을 생각하면 변환 행렬은 거꾸로 ZYX 순으로 곱해두면 될 것이다.</p>

\[R_\mathscr{I}=R_z R_y R_x = \begin{bmatrix}
  \cos\psi &amp;&amp; -\sin\psi &amp;&amp; 0 \\ 
  \sin\psi &amp;&amp; \cos\psi &amp;&amp; 0 \\ 
  0 &amp;&amp; 0 &amp;&amp; 1
\end{bmatrix}\begin{bmatrix}
  \cos\theta &amp;&amp; 0 &amp;&amp; \sin\theta \\ 
  0 &amp;&amp; 1 &amp;&amp; 0 \\ 
  -\sin\theta &amp;&amp; 0 &amp;&amp; \cos\theta
\end{bmatrix}\begin{bmatrix}
  1 &amp;&amp; 0 &amp;&amp; 0 \\ 
  0 &amp;&amp; \cos\phi &amp;&amp; -\sin\phi \\ 
  0 &amp;&amp; \sin\phi &amp;&amp; \cos\phi
\end{bmatrix}\\
=\begin{bmatrix}
  C\psi C\theta &amp;&amp; C\psi S\theta S\phi - S\psi C\phi &amp;&amp; C\psi S\theta C\phi + S\psi S\phi \\ 
  S\psi C\theta &amp;&amp; S\psi S\theta S\phi + C\psi C\phi &amp;&amp; S\psi S\theta C\phi-C\psi S\phi \\ 
  -S\theta &amp;&amp; C\theta S\phi &amp;&amp; C\theta C\phi
\end{bmatrix}
% 식 (5)\]

<p>여기서 $C\cdot = \cos(\cdot)$이고 $S\cdot = \sin(\cdot)$이다. 예를 들어 기체의 속도 벡터 $v_\mathscr{B}$는 관성계에서의 속도 벡터 $v_\mathscr{I}$로 아래와 같이 변환할 수 있다.</p>

\[v_\mathscr{I}=R_\mathscr{I}\cdot v_\mathscr{B}% 식 (6)\]

<p>또, 프로펠러 회전을 통해 기체에 가하는 힘을 $\hat{f}=U_1^2$라고 하면 관성계에서 봤을 때 힘은 아래와 같이 생각해볼 수 있다.</p>

\[R_\mathscr{I}\hat{f}=R_\mathscr{I_{e_3}}U_1^2 % 식 (7)\]

<p>여기서 $R_\mathscr{I_{e_3}}$의 $e_3$은 z 축만 생각한다는 뜻이다. 여기에 여러가지 항공역학적 힘 $\alpha_T$도 함께 고려해주면 관성계에서 본 병진운동에 관한 힘을 아래와 같이 쓸 수 있다.</p>

\[f_\mathscr{\xi}=R_\mathscr{I}\hat{f}+\alpha_T % 식 (8)\]

<h1 id="2-오일러-라그랑주-방정식을-이용한-상태-방정식-유도">2. 오일러-라그랑주 방정식을 이용한 상태 방정식 유도</h1>

<p>보통 고전 역학에서는 $F=ma$를 쓰지만, 쿼드콥터처럼 축들이 복잡하게 얽혀 있는 시스템은 <strong>에너지</strong> 관점에서 접근하는 것이 훨씬 깔끔하다. <a href="https://angeloyeo.github.io/2026/03/15/Euler_Lagrange.html">Euler-Lagrange 방정식 (변분법)</a> 편에서 본 것 처럼 Euler-Lagrange 방정식은 라그랑지안 $L$을 정의할 수 있다면 (나중에 정의할 것임) 아래와 같은 관계로 표현할 수 있다.</p>

\[\frac{d}{dt}\left(\frac{\partial L}{\partial \dot q_i}\right)-\frac{\partial L}{\partial q_i}=Q_i % 식 (9)\]

<p>여기서 $Q_i$는 시스템의 일반화된 힘 (generalized force)이다. 그런데 분명 <a href="https://angeloyeo.github.io/2026/03/15/Euler_Lagrange.html">Euler-Lagrange 방정식 (변분법)</a> 편에서는 위 식의 우변이 항상 0이 되는 것 처럼 얘기했는데, 왜 0이 아니라 $Q_i$가 붙을까? 그것은 쿼드콥터가 작동하는 시스템은 가만히 내버려두는 보존계가 아니라 외부 힘(추력, 공기 저항, 토크 등)이 작용하는 비보존계이기 때문이다. 아무래도 우리가 모터를 돌려서 가만히 두면 떨어지는 쿼드콥터를 원하는 경로로 이동시켜야 하기 때문에 이런 가정을 하는 것은 굉장히 자연스럽다고 할 수 있다.</p>

<p>이제 이 원리를 따라 ‘에너지(라그랑지안, $L$)’를 먼저 구해보자.</p>

<h2 id="1-에너지-지도-그리기-라그랑지안-정의">(1) 에너지 지도 그리기 (라그랑지안 정의)</h2>

<p>라그랑지안($L$)은 <strong>운동 에너지($E_c$)에서 위치 에너지($E_p$)를 뺀 값</strong> 이다.</p>

<h3 id="병진-운동-에너지">병진 운동 에너지</h3>

<p>질량($m$)이 속도($\dot{\xi}$)로 이동할 때 생기는 에너지. 익히 알고 있는 $1/2mv^2$을 벡터 $\dot\xi$의 내적을 이용해서 쓰면</p>

\[E_{cTra}=\frac{1}{2}m\dot\xi^T\dot\xi % 식 (10)\]

<p>가 된다.</p>

<h3 id="회전-운동-에너지">회전 운동 에너지</h3>

<p>기체가 회전할 때 생기는 에너지.</p>

<p>쿼드콥터 기체 자체의 회전 운동 에너지는 기체 기준 각속도 ($\omega$)를 이용해 기술하면 아래와 같다.</p>

\[E_{cRot}=\frac{1}{2}\omega^TI\omega % 식 (11)\]

<p>여기서 $I$는 기체 프리엠이서 정의된 대각 관성 행렬이다.</p>

<p>하지만 우리는 시스템을 오일러각 $\eta$로 제어하고 싶을 것이다. (기체의 센서가 느끼는 각속도를 우리가 알고 있기 보다는 관성계에서 본 각도인 오일러각을 통해 생각하는 것이 더 자연스럽기 때문이다.) 그러므로 $\omega$를 $\dot\eta$로 변환시키기 위해 아래와 같은 관계를 활용할 수 있다.</p>

\[\dot\eta=W_\eta^{-1}\omega \\ \begin{bmatrix}\dot\phi\\ \dot\theta \\ \dot\psi\end{bmatrix}=\begin{bmatrix}1 &amp;&amp; \sin\psi \tan\theta &amp;&amp; \cos\phi \tan\theta \\ 0 &amp;&amp; \cos\phi &amp;&amp; -\sin\phi \\ 0 &amp;&amp; \sin\phi\sec\theta  &amp;&amp; \cos\phi \sec\theta\end{bmatrix}\begin{bmatrix}p \\q \\ r\end{bmatrix} % 식 (12)\]

<p>여기서 $\eta = [\phi, \theta, \psi]^T$이고 $\omega = [p, q, r]^T$이며, $p, q, r$은 각각 기체 고정 프레임에서의 각속도이다.</p>

<p>따라서,</p>

\[E_{cRot}=\frac{1}{2}(W_\eta \dot\eta)^TI(W_\eta\dot\eta)=\frac{1}{2}\dot\eta^T(W_\eta^TIW_\eta)\dot\eta % 식 (13)\]

<p>와 같이 회전 운동 에너지를 오일러각 $\eta$로 표현해줄 수 있으며, 이 때 괄호 안의 부분인 $W_\eta^TIW_\eta$를 새로운 관성 행렬 $J(\eta)$로 정의하여 쓰면</p>

\[\Rightarrow E_{cRot}=\frac{1}{2}\dot\eta^TJ\dot\eta % 식 (14)\]

<p>가 된다.</p>

<p>이때 중요한 점은 기체 내부 센서가 느끼는 회전($\omega$)을 우리가 관찰하는 각도 변화율($\dot{\eta}$)로 변환해 기술했다는 점이다. 또, 이를 위해 <strong>변환 행렬($W_\eta$)</strong> 을 사용해 지구 기준 관성 행렬($J$)을 만들었다는 점에 주목하도록 하자.</p>

<h3 id="위치-에너지">위치 에너지</h3>

<p>중력에 의해 높이($z$)에 따라 생기는 에너지</p>

\[E_P= mgz % 식 (15)\]

<h3 id="최종-라그랑지안">최종 라그랑지안</h3>

<p>최종적으로 라그랑지안은 운동에너지 $E_C$에서 포텐셜 에너지 $E_P$를 빼준 것과 같으며 아래와 같이 기술할 수 있다.</p>

\[L=E_{cTra}+E_{cRot}-E_P=\frac{1}{2}m\dot\xi^T\dot\xi+\frac{1}{2}\dot\eta^TJ\dot\eta-mgz % 식 (16)\]

<h2 id="2-병진-운동-도출---우리가-아는-그-fma">(2) 병진 운동 도출 - “우리가 아는 그 F=ma”</h2>

<p>이제 식 (16)를 위치($\xi$)에 대해 식 (9)의 오일러-라그랑주 미분을 수행하면 병진 운동이 어떠해야하는지 도출할 수 있다. 이 때 병진 운동이 말하는 것은 “기체의 높이를 변화시키는 건 무엇일까?” 라고도 할 수 있다. 식 (9)의 $q_i$에 위치 $\xi$를 대입해 주고, $Q$를 알짜힘 $f_\xi$로 생각해준다면 아래와 같이 식 (9)를 변형시킬 수 있다.</p>

\[\text{식 (9)}\Rightarrow \frac{d}{dt}\left(\frac{\partial L}{\partial \dot \xi}\right)-\frac{\partial L}{\partial \xi}=f_\xi % 식 (17)\]

<p>여기서 $f_\xi$는 4개의 프로펠러가 합쳐서 만들어내는 전체 추력과 공기 역학적 방해를 포함하는 병진력을 의미한다. 다만 참고문헌 [2]에서는 추력만 계산하고 있는데, 이는 참고문헌 [2]의 목적은 MPC 제어기 설계를 위한 목적이므로 불확실한 외란은 제거하고 확실한 물리량인 중력과 추력으로만 모델을 구성한 것으로 생각한다. 하여튼, 전개를 계속해보면,</p>

\[\Rightarrow \frac{d}{dt}m\dot{\xi}-(-mge_3)=f_\xi % 식 (18)\]

\[m\ddot{\xi}+mge_3=f_\xi % 식 (19)\]

<p>여기서 $e_3$은 z 방향 단위 벡터이다.</p>

<ul>
  <li>결과: $m\ddot{\xi} + mge_3= f_\xi  $.</li>
</ul>

<p>결과적으로 $F=ma$가 좀 복잡하게 써진 것을 얻었다고 볼 수 있다. 식 (8)을 참고하여 이를 $\xi$에 대해 풀어 써주면 아래와 같다.</p>

\[\begin{cases}
\ddot x = \frac{1}{m}\left(\cos\psi \sin \theta \cos \phi+\sin\psi\sin\phi\right)U_1 + \frac{A_x}{m}\\
\ddot y = \frac{1}{m}\left(\sin \psi \sin \theta \cos \phi - \cos \psi \sin \phi\right)U_1 + \frac{A_y}{m}\\
\ddot z = -g + \frac{1}{m}\left(\cos \theta \cos\phi\right)U_1 + \frac{A_z}{m}
\end{cases} % 식 (20)\]

<h2 id="3-회전-운동-도출---진짜-복잡한-건-지금부터">(3) 회전 운동 도출 - “진짜 복잡한 건 지금부터”</h2>

<p>이제 식 (16)를 자세($\eta$)에 대해 식 (9)의 오일러-라그랑주 미분을 수행한다. 여기서 쿼드콥터 모델링의 꽃인 <strong>관성항</strong>과 <strong>코리올리 항</strong>이 튀어나온다.</p>

\[\text{식 (9)} \Rightarrow \frac{d}{dt}\left(\frac{\partial L}{\partial \dot \eta}\right)-\frac{\partial L}{\partial \eta}=\tau_\eta % 식 (21)\]

<p>여기서 $\tau_\eta$는 기체를 회전시키기 위해 각 모터의 속도 차이로 만들어내는 롤, 피치, 요 방향의 회전력을 의미한다. 식 (21)을 부분적으로 전개해보면,</p>

\[\frac{d}{dt}\left(\frac{\partial L}{\partial \dot \eta}\right)=\frac{d}{dt}\left(J\dot\eta\right)=J(\eta)\ddot\eta+\dot J(\eta, \dot\eta)\dot\eta % 식 (22)\]

<p>이고</p>

\[\frac{\partial L}{\partial \eta}=\frac{1}{2}\frac{\partial}{\partial \eta}\left(\dot\eta^TJ(\eta)\dot\eta\right) % 식 (23)\]

<p>이다. 따라서, 식 (21)은 아래와 같이 쓸 수 있는 것이다.</p>

\[\text{식 (21)}\Rightarrow J(\eta)\ddot\eta+\dot J(\eta, \dot\eta)\dot\eta-\frac{1}{2}\frac{\partial}{\partial \eta}\left(\dot\eta^TJ(\eta)\dot\eta\right) % 식 (24)\]

<p>여기서 우변의 두 번째, 세 번째 항을 $\dot\eta$로 묶으면,</p>

\[\Rightarrow J(\eta)\ddot\eta+\left(\dot J(\eta, \dot\eta) - \frac{1}{2} \frac{\partial}{\partial \eta}\dot\eta^TJ(\eta)\right)\dot\eta % 식 (25)\]

<p>여기서 $J(\eta)$를 $M(\eta)$ 라고 참고문헌 [1]에서 바꿔서 써주고 있고, 큰 괄호로 묶인 것을 Coriolis matrix $C(\eta, \dot\eta)$로 쓰고 있다.</p>

\[\Rightarrow M(\eta)\ddot{\eta} + C(\eta, \dot{\eta})\dot{\eta} = \tau_\eta % 식 (26)\]

<ul>
  <li><strong>왜 $M(\eta)$ 인가? (관성 행렬):</strong> 에너지를 속도로 미분한 후 다시 시간으로 미분할 때 생긴다. 기체가 얼마나 회전에 저항하는지를 나타낸다.</li>
  <li><strong>왜 $C(\eta, \dot{\eta})$ 인가? (코리올리 행렬):</strong> 회전 관성이 각도에 따라 변하기 때문에 생긴다. 롤과 피치가 동시에 일어날 때 요(Yaw) 축에 영향을 주는 것과 같은 <strong>축 간의 간섭(자이로스코프 효과 등)</strong>을 수학적으로 담아낸 행렬이다.</li>
  <li><strong>우변 ($\tau_\eta$):</strong> 우리가 모터 속도 차이를 이용해 만들어낸 롤, 피치, 요 방향의 <strong>회전력(토크)</strong> 이다.</li>
</ul>

<p>이를 정리하면,</p>

\[\ddot\eta=M(\eta)^{-1}(\tau_\eta-C(\eta,\dot\eta)\dot\eta) % 식 (27)\]

<p>와 같이 정리할 수 있다.</p>

<h1 id="완성된-쿼드콥터의-지도">완성된 쿼드콥터의 지도</h1>

<p>위의 과정들을 거치면 드디어 12개의 미분 방정식으로 이루어진 <strong>상태 공간 방정식</strong>이 완성됩니다.</p>

<ol>
  <li><strong>위치 변화:</strong> 현재 속도에 의해 결정됨.</li>
  <li><strong>속도 변화:</strong> 기체의 기울기와 모터 추력($U_1$)에 의해 결정됨 (식 (20))</li>
  <li><strong>각도 변화:</strong> 현재 각속도에 의해 결정됨.</li>
  <li><strong>각속도 변화:</strong> 가해준 토크($\tau$)와 복잡한 회전 간섭($C$)을 관성($M$)으로 나눈 값에 의해 결정됨. (식 (27))</li>
</ol>

<p>상태 벡터는 12개의 성분이며 아래와 같이 쓸 수 있으며,</p>

\[X=[x_1, x_2, x_3, x_4, x_5, x_6, x_7, x_8, x_9, x_{10}, x_{11}, x_{12}]^T \\
 = [x,y,z,\phi,\theta,\psi,\dot x,\dot y, \dot z, \dot \phi, \dot\theta, \dot\phi]^T % 식 (28)\]

<p>최종적으로 상태 방정식은 아래와 같은 관계로 서술할 수 있다.</p>

\[\dot X (t)= \begin{bmatrix}
x_7 \\ x_8 \\ x_9 \\ x_{10} \\ x_{11} \\ x_{12} \\ 
\frac{1}{m}\left(\cos x_6 \sin x_5 \cos x_4+\sin x_6\sin x_4\right)U_1 + \frac{A_x}{m} \\
\frac{1}{m}\left(\sin x_6 \sin x_5 \cos x_4 - \cos x_6 \sin x_4\right)U_1 + \frac{A_y}{m} \\
-g + \frac{1}{m}\left(\cos x_5 \cos x_4\right)U_1 + \frac{A_z}{m}\\
M(\eta)^{-1}(\tau_\eta-C\dot\eta)
\end{bmatrix}\]

<p>이렇게 도출된 모델은 <strong>MPC(모델 예측 제어)</strong> 와 같은 고급 제어 알고리즘의 ‘엔진’이 되어, 쿼드콥터가 스스로 미래를 예측하며 비행할 수 있게 만든다.</p>

<h1 id="matlab을-이용한-상태-함수-구축과-jacobian-도출">MATLAB을 이용한 상태 함수 구축과 Jacobian 도출</h1>

<p>참고 문헌 [2]에서와 같이 지금까지의 내용은 MATLAB의 Symbolic Math Toolbox를 이용해서 상태 함수로 구축하는 것이 가능하며, 특히 손 쉽게 상태 함수의 Jacobian을 계산할 수 있다.</p>

<p>우선, $\eta$에 해당하는 롤, 피치, 요 각도를 정의하도록 하자.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>syms phi(t) theta(t) psi(t)

% Transformation matrix for angular velocities from inertial frame
% to body frame
W = [ 1,  0,        -sin(theta);
      0,  cos(phi),  cos(theta)*sin(phi);
      0, -sin(phi),  cos(theta)*cos(phi) ];

% Rotation matrix R_ZYX from body frame to inertial frame

function [Rz,Ry,Rx] = rotationMatrixEulerZYX(phi,theta,psi)
% Euler ZYX angles convention
    Rx = [ 1,           0,          0;
           0,           cos(phi),  -sin(phi);
           0,           sin(phi),   cos(phi) ];
    Ry = [ cos(theta),  0,          sin(theta);
           0,           1,          0;
          -sin(theta),  0,          cos(theta) ];
    Rz = [cos(psi),    -sin(psi),   0;
          sin(psi),     cos(psi),   0;
          0,            0,          1 ];
    if nargout == 3
        % Return rotation matrix per axes
        return;
    end
    % Return rotation matrix from body frame to inertial frame
    Rz = Rz*Ry*Rx;
end

R = rotationMatrixEulerZYX(phi,theta,psi);
</code></pre></div></div>

<p>그리고 관성 좌표계의 inertia matrix에 해당하는 $J$를 정의하도록 하자. 이는 식 (13)과 식 (14) 사이에서 언급한 것을 확인할 수 있다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% Create symbolic variables for diagonal elements of inertia matrix
syms Ixx Iyy Izz

% Inertial frame velocities from body fixed frames to inertial frame.
I = [Ixx, 0, 0; 0, Iyy, 0; 0, 0, Izz];
J = W.'*I*W;
</code></pre></div></div>

<p>이제 Coriolis matrix $C(\eta,\dot\eta)$를 정의하도록 하자. 이는 식 (25)와 식 (26) 사이에서 언급되었으며 다시 한번 쓰자면 아래와 같다.</p>

\[C(\eta,\dot\eta)=\frac{d}{dt}J-\frac{1}{2}\frac{\partial}{\partial \eta}(\dot\eta^TJ)\]

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% Coriolis matrix
dJ_dt = diff(J);
h_dot_J = [diff(phi,t), diff(theta,t), diff(psi,t)]*J;
grad_temp_h = transpose(jacobian(h_dot_J,[phi theta psi]));
C = dJ_dt - 1/2*grad_temp_h;
C = subsStateVars(C,t);
</code></pre></div></div>

<p>이제 몇 $\tau_\eta$와 전체 Thrust인 $U_1$을 정의하도록 하자. 아래 MATLAB 코드에서는 Thrust를 $T$로 썼다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% Define fixed parameters and control input
% k: lift constant
% l: distance between rotor and center of mass
% m: quadrotor mass
% b: drag constant
% g: gravity
% ui: squared angular velocity of rotor i as control input
syms k l m b g u1 u2 u3 u4

% Torques in the direction of phi, theta, psi
tau_beta = [l*k*(-u2+u4); l*k*(-u1+u3); b*(-u1+u2-u3+u4)];

% Total thrust
T = k*(u1+u2+u3+u4);
</code></pre></div></div>

<p>이렇게 하여 필요한 변수 정의들은 완료되었고, 본격적으로 state를 정의할 수 있게 된다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% Create symbolic functions for time-dependent positions
syms x(t) y(t) z(t)

% Create state variables consisting of positions, angles,
% and their derivatives
state = [x; y; z; phi; theta; psi; diff(x,t); diff(y,t); ...
    diff(z,t); diff(phi,t); diff(theta,t); diff(psi,t)];
state = subsStateVars(state,t);
</code></pre></div></div>

<p>또한, 식 (29)에서와 같이 상태 방정식을 정의하면 아래와 같다. 여기서 $\alpha_T$ 에 대한 고려는 없는 것을 알 수 있다. 이것은 MPC 제어기에 넣을 상태 방정식에 대해서는 기체 자체에 대한 모델링만 하는 것이 바람직하기 때문이다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>f = [ % Set time-derivative of the positions and angles
      state(7:12);

      % Equations for linear accelerations of the center of mass
      -g*[0;0;1] + R*[0;0;T]/m;

      % Euler–Lagrange equations for angular dynamics
      inv(J)*(tau_beta - C*state(10:12))
];

f = subsStateVars(f,t);
</code></pre></div></div>

<p>참고문헌 [2]에서는 파라미터 변수들에 특정 값들을 집어 넣어서 사용하고 있긴 하여 여기에도 적어둔다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% Replace fixed parameters with given values here
IxxVal = 1.2;
IyyVal = 1.2;
IzzVal = 2.3;
kVal = 1;
lVal = 0.25;
mVal = 2;
bVal = 0.2;
gVal = 9.81;

f = subs(f, [Ixx Iyy Izz k l m b g], ...
    [IxxVal IyyVal IzzVal kVal lVal mVal bVal gVal]);
f = simplify(f);
</code></pre></div></div>

<p>마지막으로 state의 Jacobian을 계산할 수 있게 된다. 이 부분이 Symbolic Math Toolbox를 이용하는 백미라고 할 수 있다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% Calculate Jacobians for nonlinear prediction model
A = jacobian(f,state);
control = [u1; u2; u3; u4];
B = jacobian(f,control);
</code></pre></div></div>

<p>그리고 이 state와 jacobian을 MATLAB Function으로 출력해준다. 이렇게 해주어서 추후 MPC 모델링에 그대로 가져다 쓸 수 있다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% Create QuadrotorStateFcn.m with current state and control
% vectors as inputs and the state time-derivative as outputs
matlabFunction(f,'File','QuadrotorStateFcn', ...
    'Vars',{state,control});

% Create QuadrotorStateJacobianFcn.m with current state and control
% vectors as inputs and the Jacobians of the state time-derivative
% as outputs
matlabFunction(A,B,'File','QuadrotorStateJacobianFcn', ...
    'Vars',{state,control});
</code></pre></div></div>

<p>이외 Helper 함수들은 아래에 적어둔다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>function stateExpr = subsStateVars(timeExpr,var)
    if nargin == 1 
        var = sym("t");
    end
    repDiff = @(ex) subsStateVarsDiff(ex,var);
    stateExpr = mapSymType(timeExpr,"diff",repDiff);
    repFun = @(ex) subsStateVarsFun(ex,var);
    stateExpr = mapSymType(stateExpr,"symfunOf",var,repFun);
    stateExpr = formula(stateExpr);
end

function newVar = subsStateVarsFun(funExpr,var)
    name = symFunType(funExpr);
    name = replace(name,"_Var","");
    stateVar = "_" + char(var);
    newVar = sym(name + stateVar);
end

function newVar = subsStateVarsDiff(diffExpr,var)
    if nargin == 1 
      var = sym("t");
    end
    c = children(diffExpr);
    if ~isSymType(c{1},"symfunOf",var)
      % not f(t)
      newVar = diffExpr;
      return;
    end
    if ~any([c{2:end}] == var)
      % not derivative wrt t only
      newVar = diffExpr;
      return;
    end
    name = symFunType(c{1});
    name = replace(name,"_Var","");
    extension = "_" + join(repelem("d",numel(c)-1),"") + "ot";
    stateVar = "_" + char(var);
    newVar = sym(name + extension + stateVar);
end
</code></pre></div></div>

<h1 id="마치며">마치며</h1>

<p>결국 쿼드콥터의 모델링은 <strong>“우리가 가해준 에너지($U_1, \tau$)가 어떻게 기체의 운동 에너지로 변환되는가”</strong> 를 추적하는 과정이었다. 수식은 복잡해 보이지만 그 바탕은 $F=ma$가 좀 더 복잡하게 써진 것이라고 볼 수 있다. 이렇게 구한 쿼드콥터의 동적 모델을 이용해서 다음 편에선 쿼드콥터의 MPC를 이해해보고자 한다.</p>

<h1 id="참고-문헌">참고 문헌</h1>

<ul>
  <li>[1] Raffo, G. V., et al. (2010). “An integral predictive/nonlinear H∞ control structure for a quadrotor helicopter.” Automatica.</li>
  <li>[2] Derive Quadrotor Dynamics for Nonlinear Model Predictive Control, MathWorks <a href="https://kr.mathworks.com/help/symbolic/derive-quadrotor-dynamics-for-nonlinearMPC.html">(link)</a></li>
</ul>]]></content><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><category term="변분법" /><category term="미분방정식" /><summary type="html"><![CDATA[쿼드콥터는 어떻게 움직일까? 오일러-라그랑주로 풀어보는 동역학 모델링 쿼드콥터를 제어하려면 먼저 이 기체가 어떤 물리 법칙에 따라 움직이는지 알아야 합니다. 단순히 “모터를 돌리면 뜬다”를 넘어, “모터 속도를 얼마나 조절해야 내가 원하는 위치로 정확히 갈까?”를 계산하기 위한 수학적 설계도(모델)를 그려보는 과정입니다. 오늘은 Raffo 등의 논문[1]과 MATLAB Symbolic Math Toolbox의 문서[2]를 바탕으로 그 흐름을 따라가 보겠습니다. Prerequisites 이 포스팅을 더 잘 이해하기 위해선 아래의 내용을 이해하고 오는 것이 좋습니다. Euler-Lagrange 방정식 (변분법) 1. 질문의 시작: “쿼드콥터의 상태를 어떻게 정의할까?” 모델링을 하려면 먼저 무엇을 관찰할지 정해야 한다. 우선 [1]의 논문에서 우리가 보고자하는 쿼드콥터의 geometry는 아래 [2]의 그림처럼 정의하고 있다. 쿼드콥터는 공간에서 자유롭게 움직이므로 6자유도를 가진다. 위치 ($\xi$): 지구 기준에서 어디에 있는가? $(x, y, z)^T$. 자세 ($\eta$): 지구 기준에서 얼마나 기울어져 있는가? 롤, 피치, 요 $(\phi, \theta, \psi)^T$. 여기에 각각의 속도까지 더하면 총 12개의 상태 변수가 우리 시스템의 주인공이 된다. \[(x, y, z, \phi, \theta, \psi, \dot x, \dot y, \dot z, \dot \phi, \dot \theta, \dot \psi)^T % 식 (1)\] 추가로 쿼드콥터의 모션을 기술하기 위해 아래와 같이 파라미터들을 정의하도록 하자. $U_1 = (u_1, u_2, u_3, u_4) = (\omega_1^2, \omega_2^2, \omega_3^2, \omega_4^2)$ 이는 각 로터의 각속도의 제곱을 의미한다. $U$를 사용한 것은 이것이 메인 제어 입력임을 나타내기 위함이기도 하다. 또, $U$의 방향은 기체에서의 $+z$ 방향이다. (이 포스팅에서는 기체의 등쪽을 $+z$ 성분으로 정의하고 있다.) $(I_{xx}, I_{yy}, I_{zz})$ 이는 body frame의 관성 행렬의 대각 성분을 의미한다. $(k,l,m,b,g)$는 각각 추력 계수, 무게 중심으로부터 로터까지의 거리, 쿼드콥터의 질량, 항력 계수, 그리고 중력을 의미한다. $f_\xi$는 4개의 프로펠러가 합쳐서 만들어내는 전체 추력과 공기 역학적 방해를 포함하는 병진력을 의미한다. $\tau_\eta$는 기체를 회전시키기 위해 각 모터의 속도 차이로 만들어내는 롤, 피치, 요 방향의 회전력을 의미한다. $\alpha_T = [A_x, A_y, A_z]^T$는 기체에 가해지는 다양한 항공역학적 힘을 나타낸다. 또, 기체 좌표계($\mathscr{B}$)에서 관성 좌표계 ($\mathscr{I}$, 지구로도 생각할 수 있음)로 변환하기 위한 기본 회전 행렬(Elementary Rotation Matrices)을 정의하도록 하자. 오일러각 $\eta = (\phi, \theta, \psi)^T$에 대해 아래와 같이 정의할 수 있다. $R_x(\phi)$: $x$축을 중심으로 롤(Roll) 각도만큼 회전하는 행렬 \[R_x(\phi) = \begin{bmatrix} 1 &amp;&amp; 0 &amp;&amp; 0 \\ 0 &amp;&amp; \cos\phi &amp;&amp; -\sin\phi \\ 0 &amp;&amp; \sin\phi &amp;&amp; \cos\phi \end{bmatrix}% 식 (2)\] $R_y(\theta)$: $y$ 축을 중심으로 피치(Pitch) 각도만큼 회전하는 행렬 \[R_y(\theta) = \begin{bmatrix} \cos\theta &amp;&amp; 0 &amp;&amp; \sin\theta \\ 0 &amp;&amp; 1 &amp;&amp; 0 \\ -\sin\theta &amp;&amp; 0 &amp;&amp; \cos\theta \end{bmatrix}% 식 (3)\] $R_z(\psi)$: $z$ 축을 중심으로 요(Yaw) 각도만큼 회전하는 행렬 \[R_z(\psi) = \begin{bmatrix} \cos\psi &amp;&amp; -\sin\psi &amp;&amp; 0 \\ \sin\psi &amp;&amp; \cos\psi &amp;&amp; 0 \\ 0 &amp;&amp; 0 &amp;&amp; 1 \end{bmatrix}% 식 (4)\] 이 세 개의 기본 회전 행렬을 이용해서 기체의 좌표계($\mathscr{B}$)에서 관성 좌표계 ($\mathscr{I}$)로 물리량을 (힘, 속도 등)을 변환할수 있다. 변환의 순서는 X, Y, Z 순서로 곱해져야 하므로 행렬의 오른쪽에 벡터가 붙는 것을 생각하면 변환 행렬은 거꾸로 ZYX 순으로 곱해두면 될 것이다. \[R_\mathscr{I}=R_z R_y R_x = \begin{bmatrix} \cos\psi &amp;&amp; -\sin\psi &amp;&amp; 0 \\ \sin\psi &amp;&amp; \cos\psi &amp;&amp; 0 \\ 0 &amp;&amp; 0 &amp;&amp; 1 \end{bmatrix}\begin{bmatrix} \cos\theta &amp;&amp; 0 &amp;&amp; \sin\theta \\ 0 &amp;&amp; 1 &amp;&amp; 0 \\ -\sin\theta &amp;&amp; 0 &amp;&amp; \cos\theta \end{bmatrix}\begin{bmatrix} 1 &amp;&amp; 0 &amp;&amp; 0 \\ 0 &amp;&amp; \cos\phi &amp;&amp; -\sin\phi \\ 0 &amp;&amp; \sin\phi &amp;&amp; \cos\phi \end{bmatrix}\\ =\begin{bmatrix} C\psi C\theta &amp;&amp; C\psi S\theta S\phi - S\psi C\phi &amp;&amp; C\psi S\theta C\phi + S\psi S\phi \\ S\psi C\theta &amp;&amp; S\psi S\theta S\phi + C\psi C\phi &amp;&amp; S\psi S\theta C\phi-C\psi S\phi \\ -S\theta &amp;&amp; C\theta S\phi &amp;&amp; C\theta C\phi \end{bmatrix} % 식 (5)\] 여기서 $C\cdot = \cos(\cdot)$이고 $S\cdot = \sin(\cdot)$이다. 예를 들어 기체의 속도 벡터 $v_\mathscr{B}$는 관성계에서의 속도 벡터 $v_\mathscr{I}$로 아래와 같이 변환할 수 있다. \[v_\mathscr{I}=R_\mathscr{I}\cdot v_\mathscr{B}% 식 (6)\] 또, 프로펠러 회전을 통해 기체에 가하는 힘을 $\hat{f}=U_1^2$라고 하면 관성계에서 봤을 때 힘은 아래와 같이 생각해볼 수 있다. \[R_\mathscr{I}\hat{f}=R_\mathscr{I_{e_3}}U_1^2 % 식 (7)\] 여기서 $R_\mathscr{I_{e_3}}$의 $e_3$은 z 축만 생각한다는 뜻이다. 여기에 여러가지 항공역학적 힘 $\alpha_T$도 함께 고려해주면 관성계에서 본 병진운동에 관한 힘을 아래와 같이 쓸 수 있다. \[f_\mathscr{\xi}=R_\mathscr{I}\hat{f}+\alpha_T % 식 (8)\] 2. 오일러-라그랑주 방정식을 이용한 상태 방정식 유도 보통 고전 역학에서는 $F=ma$를 쓰지만, 쿼드콥터처럼 축들이 복잡하게 얽혀 있는 시스템은 에너지 관점에서 접근하는 것이 훨씬 깔끔하다. Euler-Lagrange 방정식 (변분법) 편에서 본 것 처럼 Euler-Lagrange 방정식은 라그랑지안 $L$을 정의할 수 있다면 (나중에 정의할 것임) 아래와 같은 관계로 표현할 수 있다. \[\frac{d}{dt}\left(\frac{\partial L}{\partial \dot q_i}\right)-\frac{\partial L}{\partial q_i}=Q_i % 식 (9)\] 여기서 $Q_i$는 시스템의 일반화된 힘 (generalized force)이다. 그런데 분명 Euler-Lagrange 방정식 (변분법) 편에서는 위 식의 우변이 항상 0이 되는 것 처럼 얘기했는데, 왜 0이 아니라 $Q_i$가 붙을까? 그것은 쿼드콥터가 작동하는 시스템은 가만히 내버려두는 보존계가 아니라 외부 힘(추력, 공기 저항, 토크 등)이 작용하는 비보존계이기 때문이다. 아무래도 우리가 모터를 돌려서 가만히 두면 떨어지는 쿼드콥터를 원하는 경로로 이동시켜야 하기 때문에 이런 가정을 하는 것은 굉장히 자연스럽다고 할 수 있다. 이제 이 원리를 따라 ‘에너지(라그랑지안, $L$)’를 먼저 구해보자. (1) 에너지 지도 그리기 (라그랑지안 정의) 라그랑지안($L$)은 운동 에너지($E_c$)에서 위치 에너지($E_p$)를 뺀 값 이다. 병진 운동 에너지 질량($m$)이 속도($\dot{\xi}$)로 이동할 때 생기는 에너지. 익히 알고 있는 $1/2mv^2$을 벡터 $\dot\xi$의 내적을 이용해서 쓰면 \[E_{cTra}=\frac{1}{2}m\dot\xi^T\dot\xi % 식 (10)\] 가 된다. 회전 운동 에너지 기체가 회전할 때 생기는 에너지. 쿼드콥터 기체 자체의 회전 운동 에너지는 기체 기준 각속도 ($\omega$)를 이용해 기술하면 아래와 같다. \[E_{cRot}=\frac{1}{2}\omega^TI\omega % 식 (11)\] 여기서 $I$는 기체 프리엠이서 정의된 대각 관성 행렬이다. 하지만 우리는 시스템을 오일러각 $\eta$로 제어하고 싶을 것이다. (기체의 센서가 느끼는 각속도를 우리가 알고 있기 보다는 관성계에서 본 각도인 오일러각을 통해 생각하는 것이 더 자연스럽기 때문이다.) 그러므로 $\omega$를 $\dot\eta$로 변환시키기 위해 아래와 같은 관계를 활용할 수 있다. \[\dot\eta=W_\eta^{-1}\omega \\ \begin{bmatrix}\dot\phi\\ \dot\theta \\ \dot\psi\end{bmatrix}=\begin{bmatrix}1 &amp;&amp; \sin\psi \tan\theta &amp;&amp; \cos\phi \tan\theta \\ 0 &amp;&amp; \cos\phi &amp;&amp; -\sin\phi \\ 0 &amp;&amp; \sin\phi\sec\theta &amp;&amp; \cos\phi \sec\theta\end{bmatrix}\begin{bmatrix}p \\q \\ r\end{bmatrix} % 식 (12)\] 여기서 $\eta = [\phi, \theta, \psi]^T$이고 $\omega = [p, q, r]^T$이며, $p, q, r$은 각각 기체 고정 프레임에서의 각속도이다. 따라서, \[E_{cRot}=\frac{1}{2}(W_\eta \dot\eta)^TI(W_\eta\dot\eta)=\frac{1}{2}\dot\eta^T(W_\eta^TIW_\eta)\dot\eta % 식 (13)\] 와 같이 회전 운동 에너지를 오일러각 $\eta$로 표현해줄 수 있으며, 이 때 괄호 안의 부분인 $W_\eta^TIW_\eta$를 새로운 관성 행렬 $J(\eta)$로 정의하여 쓰면 \[\Rightarrow E_{cRot}=\frac{1}{2}\dot\eta^TJ\dot\eta % 식 (14)\] 가 된다. 이때 중요한 점은 기체 내부 센서가 느끼는 회전($\omega$)을 우리가 관찰하는 각도 변화율($\dot{\eta}$)로 변환해 기술했다는 점이다. 또, 이를 위해 변환 행렬($W_\eta$) 을 사용해 지구 기준 관성 행렬($J$)을 만들었다는 점에 주목하도록 하자. 위치 에너지 중력에 의해 높이($z$)에 따라 생기는 에너지 \[E_P= mgz % 식 (15)\] 최종 라그랑지안 최종적으로 라그랑지안은 운동에너지 $E_C$에서 포텐셜 에너지 $E_P$를 빼준 것과 같으며 아래와 같이 기술할 수 있다. \[L=E_{cTra}+E_{cRot}-E_P=\frac{1}{2}m\dot\xi^T\dot\xi+\frac{1}{2}\dot\eta^TJ\dot\eta-mgz % 식 (16)\] (2) 병진 운동 도출 - “우리가 아는 그 F=ma” 이제 식 (16)를 위치($\xi$)에 대해 식 (9)의 오일러-라그랑주 미분을 수행하면 병진 운동이 어떠해야하는지 도출할 수 있다. 이 때 병진 운동이 말하는 것은 “기체의 높이를 변화시키는 건 무엇일까?” 라고도 할 수 있다. 식 (9)의 $q_i$에 위치 $\xi$를 대입해 주고, $Q$를 알짜힘 $f_\xi$로 생각해준다면 아래와 같이 식 (9)를 변형시킬 수 있다. \[\text{식 (9)}\Rightarrow \frac{d}{dt}\left(\frac{\partial L}{\partial \dot \xi}\right)-\frac{\partial L}{\partial \xi}=f_\xi % 식 (17)\] 여기서 $f_\xi$는 4개의 프로펠러가 합쳐서 만들어내는 전체 추력과 공기 역학적 방해를 포함하는 병진력을 의미한다. 다만 참고문헌 [2]에서는 추력만 계산하고 있는데, 이는 참고문헌 [2]의 목적은 MPC 제어기 설계를 위한 목적이므로 불확실한 외란은 제거하고 확실한 물리량인 중력과 추력으로만 모델을 구성한 것으로 생각한다. 하여튼, 전개를 계속해보면, \[\Rightarrow \frac{d}{dt}m\dot{\xi}-(-mge_3)=f_\xi % 식 (18)\] \[m\ddot{\xi}+mge_3=f_\xi % 식 (19)\] 여기서 $e_3$은 z 방향 단위 벡터이다. 결과: $m\ddot{\xi} + mge_3= f_\xi $. 결과적으로 $F=ma$가 좀 복잡하게 써진 것을 얻었다고 볼 수 있다. 식 (8)을 참고하여 이를 $\xi$에 대해 풀어 써주면 아래와 같다. \[\begin{cases} \ddot x = \frac{1}{m}\left(\cos\psi \sin \theta \cos \phi+\sin\psi\sin\phi\right)U_1 + \frac{A_x}{m}\\ \ddot y = \frac{1}{m}\left(\sin \psi \sin \theta \cos \phi - \cos \psi \sin \phi\right)U_1 + \frac{A_y}{m}\\ \ddot z = -g + \frac{1}{m}\left(\cos \theta \cos\phi\right)U_1 + \frac{A_z}{m} \end{cases} % 식 (20)\] (3) 회전 운동 도출 - “진짜 복잡한 건 지금부터” 이제 식 (16)를 자세($\eta$)에 대해 식 (9)의 오일러-라그랑주 미분을 수행한다. 여기서 쿼드콥터 모델링의 꽃인 관성항과 코리올리 항이 튀어나온다. \[\text{식 (9)} \Rightarrow \frac{d}{dt}\left(\frac{\partial L}{\partial \dot \eta}\right)-\frac{\partial L}{\partial \eta}=\tau_\eta % 식 (21)\] 여기서 $\tau_\eta$는 기체를 회전시키기 위해 각 모터의 속도 차이로 만들어내는 롤, 피치, 요 방향의 회전력을 의미한다. 식 (21)을 부분적으로 전개해보면, \[\frac{d}{dt}\left(\frac{\partial L}{\partial \dot \eta}\right)=\frac{d}{dt}\left(J\dot\eta\right)=J(\eta)\ddot\eta+\dot J(\eta, \dot\eta)\dot\eta % 식 (22)\] 이고 \[\frac{\partial L}{\partial \eta}=\frac{1}{2}\frac{\partial}{\partial \eta}\left(\dot\eta^TJ(\eta)\dot\eta\right) % 식 (23)\] 이다. 따라서, 식 (21)은 아래와 같이 쓸 수 있는 것이다. \[\text{식 (21)}\Rightarrow J(\eta)\ddot\eta+\dot J(\eta, \dot\eta)\dot\eta-\frac{1}{2}\frac{\partial}{\partial \eta}\left(\dot\eta^TJ(\eta)\dot\eta\right) % 식 (24)\] 여기서 우변의 두 번째, 세 번째 항을 $\dot\eta$로 묶으면, \[\Rightarrow J(\eta)\ddot\eta+\left(\dot J(\eta, \dot\eta) - \frac{1}{2} \frac{\partial}{\partial \eta}\dot\eta^TJ(\eta)\right)\dot\eta % 식 (25)\] 여기서 $J(\eta)$를 $M(\eta)$ 라고 참고문헌 [1]에서 바꿔서 써주고 있고, 큰 괄호로 묶인 것을 Coriolis matrix $C(\eta, \dot\eta)$로 쓰고 있다. \[\Rightarrow M(\eta)\ddot{\eta} + C(\eta, \dot{\eta})\dot{\eta} = \tau_\eta % 식 (26)\] 왜 $M(\eta)$ 인가? (관성 행렬): 에너지를 속도로 미분한 후 다시 시간으로 미분할 때 생긴다. 기체가 얼마나 회전에 저항하는지를 나타낸다. 왜 $C(\eta, \dot{\eta})$ 인가? (코리올리 행렬): 회전 관성이 각도에 따라 변하기 때문에 생긴다. 롤과 피치가 동시에 일어날 때 요(Yaw) 축에 영향을 주는 것과 같은 축 간의 간섭(자이로스코프 효과 등)을 수학적으로 담아낸 행렬이다. 우변 ($\tau_\eta$): 우리가 모터 속도 차이를 이용해 만들어낸 롤, 피치, 요 방향의 회전력(토크) 이다. 이를 정리하면, \[\ddot\eta=M(\eta)^{-1}(\tau_\eta-C(\eta,\dot\eta)\dot\eta) % 식 (27)\] 와 같이 정리할 수 있다. 완성된 쿼드콥터의 지도 위의 과정들을 거치면 드디어 12개의 미분 방정식으로 이루어진 상태 공간 방정식이 완성됩니다. 위치 변화: 현재 속도에 의해 결정됨. 속도 변화: 기체의 기울기와 모터 추력($U_1$)에 의해 결정됨 (식 (20)) 각도 변화: 현재 각속도에 의해 결정됨. 각속도 변화: 가해준 토크($\tau$)와 복잡한 회전 간섭($C$)을 관성($M$)으로 나눈 값에 의해 결정됨. (식 (27)) 상태 벡터는 12개의 성분이며 아래와 같이 쓸 수 있으며, \[X=[x_1, x_2, x_3, x_4, x_5, x_6, x_7, x_8, x_9, x_{10}, x_{11}, x_{12}]^T \\ = [x,y,z,\phi,\theta,\psi,\dot x,\dot y, \dot z, \dot \phi, \dot\theta, \dot\phi]^T % 식 (28)\] 최종적으로 상태 방정식은 아래와 같은 관계로 서술할 수 있다. \[\dot X (t)= \begin{bmatrix} x_7 \\ x_8 \\ x_9 \\ x_{10} \\ x_{11} \\ x_{12} \\ \frac{1}{m}\left(\cos x_6 \sin x_5 \cos x_4+\sin x_6\sin x_4\right)U_1 + \frac{A_x}{m} \\ \frac{1}{m}\left(\sin x_6 \sin x_5 \cos x_4 - \cos x_6 \sin x_4\right)U_1 + \frac{A_y}{m} \\ -g + \frac{1}{m}\left(\cos x_5 \cos x_4\right)U_1 + \frac{A_z}{m}\\ M(\eta)^{-1}(\tau_\eta-C\dot\eta) \end{bmatrix}\] 이렇게 도출된 모델은 MPC(모델 예측 제어) 와 같은 고급 제어 알고리즘의 ‘엔진’이 되어, 쿼드콥터가 스스로 미래를 예측하며 비행할 수 있게 만든다. MATLAB을 이용한 상태 함수 구축과 Jacobian 도출 참고 문헌 [2]에서와 같이 지금까지의 내용은 MATLAB의 Symbolic Math Toolbox를 이용해서 상태 함수로 구축하는 것이 가능하며, 특히 손 쉽게 상태 함수의 Jacobian을 계산할 수 있다. 우선, $\eta$에 해당하는 롤, 피치, 요 각도를 정의하도록 하자. syms phi(t) theta(t) psi(t) % Transformation matrix for angular velocities from inertial frame % to body frame W = [ 1, 0, -sin(theta); 0, cos(phi), cos(theta)*sin(phi); 0, -sin(phi), cos(theta)*cos(phi) ]; % Rotation matrix R_ZYX from body frame to inertial frame function [Rz,Ry,Rx] = rotationMatrixEulerZYX(phi,theta,psi) % Euler ZYX angles convention Rx = [ 1, 0, 0; 0, cos(phi), -sin(phi); 0, sin(phi), cos(phi) ]; Ry = [ cos(theta), 0, sin(theta); 0, 1, 0; -sin(theta), 0, cos(theta) ]; Rz = [cos(psi), -sin(psi), 0; sin(psi), cos(psi), 0; 0, 0, 1 ]; if nargout == 3 % Return rotation matrix per axes return; end % Return rotation matrix from body frame to inertial frame Rz = Rz*Ry*Rx; end R = rotationMatrixEulerZYX(phi,theta,psi); 그리고 관성 좌표계의 inertia matrix에 해당하는 $J$를 정의하도록 하자. 이는 식 (13)과 식 (14) 사이에서 언급한 것을 확인할 수 있다. % Create symbolic variables for diagonal elements of inertia matrix syms Ixx Iyy Izz % Inertial frame velocities from body fixed frames to inertial frame. I = [Ixx, 0, 0; 0, Iyy, 0; 0, 0, Izz]; J = W.'*I*W; 이제 Coriolis matrix $C(\eta,\dot\eta)$를 정의하도록 하자. 이는 식 (25)와 식 (26) 사이에서 언급되었으며 다시 한번 쓰자면 아래와 같다. \[C(\eta,\dot\eta)=\frac{d}{dt}J-\frac{1}{2}\frac{\partial}{\partial \eta}(\dot\eta^TJ)\] % Coriolis matrix dJ_dt = diff(J); h_dot_J = [diff(phi,t), diff(theta,t), diff(psi,t)]*J; grad_temp_h = transpose(jacobian(h_dot_J,[phi theta psi])); C = dJ_dt - 1/2*grad_temp_h; C = subsStateVars(C,t); 이제 몇 $\tau_\eta$와 전체 Thrust인 $U_1$을 정의하도록 하자. 아래 MATLAB 코드에서는 Thrust를 $T$로 썼다. % Define fixed parameters and control input % k: lift constant % l: distance between rotor and center of mass % m: quadrotor mass % b: drag constant % g: gravity % ui: squared angular velocity of rotor i as control input syms k l m b g u1 u2 u3 u4 % Torques in the direction of phi, theta, psi tau_beta = [l*k*(-u2+u4); l*k*(-u1+u3); b*(-u1+u2-u3+u4)]; % Total thrust T = k*(u1+u2+u3+u4); 이렇게 하여 필요한 변수 정의들은 완료되었고, 본격적으로 state를 정의할 수 있게 된다. % Create symbolic functions for time-dependent positions syms x(t) y(t) z(t) % Create state variables consisting of positions, angles, % and their derivatives state = [x; y; z; phi; theta; psi; diff(x,t); diff(y,t); ... diff(z,t); diff(phi,t); diff(theta,t); diff(psi,t)]; state = subsStateVars(state,t); 또한, 식 (29)에서와 같이 상태 방정식을 정의하면 아래와 같다. 여기서 $\alpha_T$ 에 대한 고려는 없는 것을 알 수 있다. 이것은 MPC 제어기에 넣을 상태 방정식에 대해서는 기체 자체에 대한 모델링만 하는 것이 바람직하기 때문이다. f = [ % Set time-derivative of the positions and angles state(7:12); % Equations for linear accelerations of the center of mass -g*[0;0;1] + R*[0;0;T]/m; % Euler–Lagrange equations for angular dynamics inv(J)*(tau_beta - C*state(10:12)) ]; f = subsStateVars(f,t); 참고문헌 [2]에서는 파라미터 변수들에 특정 값들을 집어 넣어서 사용하고 있긴 하여 여기에도 적어둔다. % Replace fixed parameters with given values here IxxVal = 1.2; IyyVal = 1.2; IzzVal = 2.3; kVal = 1; lVal = 0.25; mVal = 2; bVal = 0.2; gVal = 9.81; f = subs(f, [Ixx Iyy Izz k l m b g], ... [IxxVal IyyVal IzzVal kVal lVal mVal bVal gVal]); f = simplify(f); 마지막으로 state의 Jacobian을 계산할 수 있게 된다. 이 부분이 Symbolic Math Toolbox를 이용하는 백미라고 할 수 있다. % Calculate Jacobians for nonlinear prediction model A = jacobian(f,state); control = [u1; u2; u3; u4]; B = jacobian(f,control); 그리고 이 state와 jacobian을 MATLAB Function으로 출력해준다. 이렇게 해주어서 추후 MPC 모델링에 그대로 가져다 쓸 수 있다. % Create QuadrotorStateFcn.m with current state and control % vectors as inputs and the state time-derivative as outputs matlabFunction(f,'File','QuadrotorStateFcn', ... 'Vars',{state,control}); % Create QuadrotorStateJacobianFcn.m with current state and control % vectors as inputs and the Jacobians of the state time-derivative % as outputs matlabFunction(A,B,'File','QuadrotorStateJacobianFcn', ... 'Vars',{state,control}); 이외 Helper 함수들은 아래에 적어둔다. function stateExpr = subsStateVars(timeExpr,var) if nargin == 1 var = sym("t"); end repDiff = @(ex) subsStateVarsDiff(ex,var); stateExpr = mapSymType(timeExpr,"diff",repDiff); repFun = @(ex) subsStateVarsFun(ex,var); stateExpr = mapSymType(stateExpr,"symfunOf",var,repFun); stateExpr = formula(stateExpr); end function newVar = subsStateVarsFun(funExpr,var) name = symFunType(funExpr); name = replace(name,"_Var",""); stateVar = "_" + char(var); newVar = sym(name + stateVar); end function newVar = subsStateVarsDiff(diffExpr,var) if nargin == 1 var = sym("t"); end c = children(diffExpr); if ~isSymType(c{1},"symfunOf",var) % not f(t) newVar = diffExpr; return; end if ~any([c{2:end}] == var) % not derivative wrt t only newVar = diffExpr; return; end name = symFunType(c{1}); name = replace(name,"_Var",""); extension = "_" + join(repelem("d",numel(c)-1),"") + "ot"; stateVar = "_" + char(var); newVar = sym(name + extension + stateVar); end 마치며 결국 쿼드콥터의 모델링은 “우리가 가해준 에너지($U_1, \tau$)가 어떻게 기체의 운동 에너지로 변환되는가” 를 추적하는 과정이었다. 수식은 복잡해 보이지만 그 바탕은 $F=ma$가 좀 더 복잡하게 써진 것이라고 볼 수 있다. 이렇게 구한 쿼드콥터의 동적 모델을 이용해서 다음 편에선 쿼드콥터의 MPC를 이해해보고자 한다. 참고 문헌 [1] Raffo, G. V., et al. (2010). “An integral predictive/nonlinear H∞ control structure for a quadrotor helicopter.” Automatica. [2] Derive Quadrotor Dynamics for Nonlinear Model Predictive Control, MathWorks (link)]]></summary></entry><entry xml:lang="ko"><title type="html">Euler-Lagrange 방정식 (변분법)</title><link href="https://angeloyeo.github.io/2026/03/15/Euler_Lagrange.html" rel="alternate" type="text/html" title="Euler-Lagrange 방정식 (변분법)" /><published>2026-03-15T00:00:00+00:00</published><updated>2026-03-15T00:00:00+00:00</updated><id>https://angeloyeo.github.io/2026/03/15/Euler_Lagrange</id><content type="html" xml:base="https://angeloyeo.github.io/2026/03/15/Euler_Lagrange.html"><![CDATA[<p>빛이 공기를 통과하다가 빛을 통과할 때 빛은 굴절 되어 들어갑니다. 매질에 따라 빛의 속도가 다르다보니 최단 시간으로 가기 위한 경로를 택한 것이라고 합니다. 이걸 페르마의 원리라고 하더라구요. 자연은 어떻게 최적의 경로를 찾는지 참으로 신기합니다. 이번 시간에는 수학적으로 최적의 경로를 찾는 방법 중 하나인 오일러 라그랑주 방정식에 대해 알아보겠습니다.</p>

<h1 id="1-도입-함수를-입력으로-받는-함수-범함수functional">1. 도입: 함수를 입력으로 받는 함수, ‘범함수(Functional)’</h1>

<p>우리는 보통 $y = f(x)$처럼 <strong>숫자</strong>를 넣으면 <strong>숫자</strong>가 나오는 함수에 익숙하다. 하지만 세상에는 조금 더 거대한 개념의 함수가 필요할 때가 있다.</p>

<p>예를 들어, “두 점 사이를 잇는 수많은 곡선 중 가장 짧은 것은 무엇인가?”라는 질문을 던져봅시다. 여기서 우리가 넣는 재료는 ‘숫자’가 아니라 <strong>‘곡선(함수) 그 자체’</strong> 이다. 그리고 그 결과값은 ‘곡선의 길이’라는 <strong>‘하나의 숫자’</strong>로 나온다.</p>

<p>이렇게 <strong>함수를 입력받아 실수 값을 내놓는 함수</strong>를 우리는 <strong>범함수(Functional)</strong> 라고 부른다. 범함수 $J$ 를 상정하여 아래처럼 표현해볼 수 있다.</p>

\[J[y] = \int_{x_1}^{x_2} L(x, y, y') dx\]

<p>여기서 $L$은 우리가 최적화하고 싶은 시스템의 상태를 담은 ‘알맹이’를 말하는 것이며 라그랑지안(Lagrangian)이라고 부른다.</p>

<p>(참고로 범함수의 개념은 <a href="https://angeloyeo.github.io/2020/09/09/row_vector_and_inner_product.html">행벡터의 의미와 벡터의 내적</a> 편에서도 다룬 적 있다. 행 벡터 자체가 범함수의 기능을 한다고 설명하였다. 혹시 궁금하다면 참고.)</p>

<h1 id="2-사고의-전환-정답-곡선이-이미-있다고-치자">2. 사고의 전환: “정답 곡선이 이미 있다고 치자”</h1>

<p>이제 우리의 목표는 범함수 $J$를 최소(혹은 최대)로 만드는 마법 같은 곡선 $y(x)$를 찾는 것이다. 여기서 변분법의 천재적인 <strong>사고 흐름</strong>이 시작된다.</p>

<p><strong>“만약 우리가 찾은 $y(x)$가 진짜 정답이라면, 그 옆으로 아주 살짝 비껴간 경로는 정답보다 효율이 떨어질 것이다.”</strong></p>

<p>이 아이디어를 수학적으로 구현하기 위해, 정답 곡선 $y(x)$에 아주 미세한 변동(Variation)인 $\eta(x)$를 섞어보자.</p>

<ul>
  <li><strong>새로운 경로:</strong> $Y(x) = y(x) + \epsilon \eta(x)$</li>
  <li>$\epsilon$은 조절 나사임. $\epsilon=0$이면 정답이고, 조금이라도 커지면 정답에서 벗어남.</li>
</ul>

<h1 id="3-오일러-라그랑주-방정식의-유도-과정">3. 오일러-라그랑주 방정식의 유도 과정</h1>

<p>우리가 가정한 $y(x)$가 정말 최적의 경로라면, $\epsilon = 0$일 때 $J(\epsilon)$은 극값을 가져야 한다. 즉, $\epsilon$에 대해 미분했을 때 $0$이 되어야 한다. (어차피 같은 말이잖아!? 라고 생각할 수 있지만, 전개를 따라가보면 전혀 다른 방식으로 같은 현상을 표현하게 된다는 것을 알 수 있다.)</p>

\[\left. \frac{dJ}{d\epsilon} \right|_{\epsilon=0} = 0\]

<p>이것이 바로 변분법의 핵심 원리이다. 이제 우리는 이 식을 풀기만 하면 된다.</p>

\[\frac{dJ}{d\epsilon} = \frac{d}{d\epsilon}\int_{x_1}^{x_2}  L(x, Y, Y') dx\]

<p>적분 기호 안으로 미분을 밀어 넣으면(라이프니츠 법칙), <strong>연쇄 법칙(Chain Rule)</strong> 에 의해 다음과 같이 전개된다.</p>

\[\Rightarrow\int_{x_1}^{x_2} \left( \frac{\partial L}{\partial Y} \frac{\partial Y}{\partial \epsilon} + \frac{\partial L}{\partial Y'} \frac{\partial Y'}{\partial \epsilon} \right) dx = 0\]

<p>위 식에서 변수 치환을 통해 $\frac{\partial Y}{\partial \epsilon}$과 $\frac{\partial Y’}{\partial \epsilon}$을 계산해 보자.</p>

<ul>
  <li>$Y = y + \epsilon \eta \implies \frac{\partial Y}{\partial \epsilon} = \eta(x)$</li>
  <li>$Y’ = y’ + \epsilon \eta’ \implies \frac{\partial Y’}{\partial \epsilon} = \eta’(x)$</li>
</ul>

<p>이를 대입하고, 우리가 찾고자 하는 $\epsilon=0$ 지점을 적용하면(즉, $Y \to y, Y’ \to y’$):</p>

\[\int_{x_1}^{x_2} \left( \frac{\partial L}{\partial y} \eta + \frac{\partial L}{\partial y'} \eta' \right) dx = 0\]

<p>두 번째 항에 있는 $\eta’(x)$를 $\eta(x)$로 바꾸기 위해 <strong>부분 적분</strong>($\int udv = uv - \int vdu$)을 수행하자.</p>

<ul>
  <li>$u = \frac{\partial L}{\partial y’}$, $dv = \eta’(x)dx$ 로 두면:</li>
</ul>

\[\int_{x_1}^{x_2} \frac{\partial L}{\partial y'} \eta'(x)  dx = \left[ \frac{\partial L}{\partial y'} \eta(x) \right]_{x_1}^{x_2} - \int_{x_1}^{x_2} \frac{d}{dx} \left( \frac{\partial L}{\partial y'} \right) \eta(x)  dx\]

<p>우리는 처음에 양 끝점을 고정했기 때문에 $\eta(x_1) = 0, \eta(x_2) = 0$이다. 따라서 대괄호 항($uv$ 파트)은 <strong>0이 되어 사라진다.</strong></p>

<p>이제 남은 항들을 다시 합쳐서 $\eta(x)$로 묶어주자.</p>

\[\int_{x_1}^{x_2} \left[ \frac{\partial L}{\partial y} - \frac{d}{dx} \left( \frac{\partial L}{\partial y'} \right) \right] \eta(x)  dx = 0\]

<p>이 식이 <strong>어떠한</strong> $\eta(x)$에 대해서도 항상 성립하려면, 적분 기호 안의 대괄호 값이 반드시 $0$이어야 한다. 이를 정리하여 오릴러 라그랑주 방정식 (Euler-Lagrange Equation)이라고 부른다.</p>

<p><strong>The Euler-Lagrange Equation:</strong></p>

\[\frac{\partial L}{\partial y} - \frac{d}{dx} \left( \frac{\partial L}{\partial y'} \right) = 0\]

<p>이 짧은 방정식이 바로 <strong>“전체적인(Global) 최적 경로를 찾기 위해, 곡선의 매 순간(Local)이 지켜야 할 물리 법칙”</strong> 을 말해준다.</p>

<hr />

<h1 id="4-예시">4. 예시</h1>

<p>$L$이 무엇인지, 그리고 오일러 라그랑주 방정식이 말하는 최소 작용의 원리 (principle of least action)이 무엇인지 좀 더 잘 이해하기 위해 예시를 들어보자.</p>

<p>$L$은 우리가 최적화하고 싶은 시스템의 상태를 담은 ‘알맹이’라고 말했다. 예를 들어 $x$ 방향으로 이동하고 있는 물체를 생각해보자. 이 경우 라그랑지안 $L$은 운동에너지에서 포텐셜 에너지를 빼준 것과 같다.</p>

\[L = \frac{1}{2}mv^2-U(x)\]

<p>이 $L$을 오일러 라그랑주 방정식에 넣으면 어떻게 될까? 식 (8)을 현재 겪고 있는 시간($t$)에 따른 위치 ($x$)의 변화로 바꿔 써주면 아래와 같다.</p>

\[\frac{d}{dt}\frac{\partial L}{\partial \dot x}=\frac{\partial L}{\partial x}\]

<p>식 (10)의 좌변에 있는 $\dot x$는 속도 $v$로 써줄 수 있으므로,</p>

\[\frac{\partial L}{\partial \dot x} = \frac{\partial L}{\partial v}=mv\]

<p>이다. 한편, 식 (10)의 우변을 보면,</p>

\[\frac{\partial L}{\partial x}=-U'(x)\]

<p>이므로 운동 에너지와 포텐셜 에너지 차에 관한 $L$에 대한 식은 아래와 같이 정리된다.</p>

\[\Rightarrow \frac{d}{dt}(mv)=-U'(x)\]

\[\Rightarrow m\frac{d}{dt}(v)=-U'(x)\]

<p>Potential의 negative gradient가 힘과 같으므로, 이 식은 바로 뉴턴 제 2법칙인 가속도의 법칙이며 소위 $F=ma$로 알고 있는 것과 같다.</p>

<h3 id="마치며">마치며</h3>

<p>변분법은 “결과가 최소가 되려면 과정이 어떠해야 하는가?”를 묻는 학문이다. 이 방정식 덕분에 우리는 뉴턴 역학을 에너지 관점에서 재해석할 수 있게 되었고, 오늘날 로봇의 복잡한 움직임을 제어하거나 인공지능의 오차를 줄이는 데까지 이 원리를 사용하고 있다.</p>]]></content><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><category term="변분법" /><category term="미분방정식" /><summary type="html"><![CDATA[빛이 공기를 통과하다가 빛을 통과할 때 빛은 굴절 되어 들어갑니다. 매질에 따라 빛의 속도가 다르다보니 최단 시간으로 가기 위한 경로를 택한 것이라고 합니다. 이걸 페르마의 원리라고 하더라구요. 자연은 어떻게 최적의 경로를 찾는지 참으로 신기합니다. 이번 시간에는 수학적으로 최적의 경로를 찾는 방법 중 하나인 오일러 라그랑주 방정식에 대해 알아보겠습니다. 1. 도입: 함수를 입력으로 받는 함수, ‘범함수(Functional)’ 우리는 보통 $y = f(x)$처럼 숫자를 넣으면 숫자가 나오는 함수에 익숙하다. 하지만 세상에는 조금 더 거대한 개념의 함수가 필요할 때가 있다. 예를 들어, “두 점 사이를 잇는 수많은 곡선 중 가장 짧은 것은 무엇인가?”라는 질문을 던져봅시다. 여기서 우리가 넣는 재료는 ‘숫자’가 아니라 ‘곡선(함수) 그 자체’ 이다. 그리고 그 결과값은 ‘곡선의 길이’라는 ‘하나의 숫자’로 나온다. 이렇게 함수를 입력받아 실수 값을 내놓는 함수를 우리는 범함수(Functional) 라고 부른다. 범함수 $J$ 를 상정하여 아래처럼 표현해볼 수 있다. \[J[y] = \int_{x_1}^{x_2} L(x, y, y') dx\] 여기서 $L$은 우리가 최적화하고 싶은 시스템의 상태를 담은 ‘알맹이’를 말하는 것이며 라그랑지안(Lagrangian)이라고 부른다. (참고로 범함수의 개념은 행벡터의 의미와 벡터의 내적 편에서도 다룬 적 있다. 행 벡터 자체가 범함수의 기능을 한다고 설명하였다. 혹시 궁금하다면 참고.) 2. 사고의 전환: “정답 곡선이 이미 있다고 치자” 이제 우리의 목표는 범함수 $J$를 최소(혹은 최대)로 만드는 마법 같은 곡선 $y(x)$를 찾는 것이다. 여기서 변분법의 천재적인 사고 흐름이 시작된다. “만약 우리가 찾은 $y(x)$가 진짜 정답이라면, 그 옆으로 아주 살짝 비껴간 경로는 정답보다 효율이 떨어질 것이다.” 이 아이디어를 수학적으로 구현하기 위해, 정답 곡선 $y(x)$에 아주 미세한 변동(Variation)인 $\eta(x)$를 섞어보자. 새로운 경로: $Y(x) = y(x) + \epsilon \eta(x)$ $\epsilon$은 조절 나사임. $\epsilon=0$이면 정답이고, 조금이라도 커지면 정답에서 벗어남. 3. 오일러-라그랑주 방정식의 유도 과정 우리가 가정한 $y(x)$가 정말 최적의 경로라면, $\epsilon = 0$일 때 $J(\epsilon)$은 극값을 가져야 한다. 즉, $\epsilon$에 대해 미분했을 때 $0$이 되어야 한다. (어차피 같은 말이잖아!? 라고 생각할 수 있지만, 전개를 따라가보면 전혀 다른 방식으로 같은 현상을 표현하게 된다는 것을 알 수 있다.) \[\left. \frac{dJ}{d\epsilon} \right|_{\epsilon=0} = 0\] 이것이 바로 변분법의 핵심 원리이다. 이제 우리는 이 식을 풀기만 하면 된다. \[\frac{dJ}{d\epsilon} = \frac{d}{d\epsilon}\int_{x_1}^{x_2} L(x, Y, Y') dx\] 적분 기호 안으로 미분을 밀어 넣으면(라이프니츠 법칙), 연쇄 법칙(Chain Rule) 에 의해 다음과 같이 전개된다. \[\Rightarrow\int_{x_1}^{x_2} \left( \frac{\partial L}{\partial Y} \frac{\partial Y}{\partial \epsilon} + \frac{\partial L}{\partial Y'} \frac{\partial Y'}{\partial \epsilon} \right) dx = 0\] 위 식에서 변수 치환을 통해 $\frac{\partial Y}{\partial \epsilon}$과 $\frac{\partial Y’}{\partial \epsilon}$을 계산해 보자. $Y = y + \epsilon \eta \implies \frac{\partial Y}{\partial \epsilon} = \eta(x)$ $Y’ = y’ + \epsilon \eta’ \implies \frac{\partial Y’}{\partial \epsilon} = \eta’(x)$ 이를 대입하고, 우리가 찾고자 하는 $\epsilon=0$ 지점을 적용하면(즉, $Y \to y, Y’ \to y’$): \[\int_{x_1}^{x_2} \left( \frac{\partial L}{\partial y} \eta + \frac{\partial L}{\partial y'} \eta' \right) dx = 0\] 두 번째 항에 있는 $\eta’(x)$를 $\eta(x)$로 바꾸기 위해 부분 적분($\int udv = uv - \int vdu$)을 수행하자. $u = \frac{\partial L}{\partial y’}$, $dv = \eta’(x)dx$ 로 두면: \[\int_{x_1}^{x_2} \frac{\partial L}{\partial y'} \eta'(x) dx = \left[ \frac{\partial L}{\partial y'} \eta(x) \right]_{x_1}^{x_2} - \int_{x_1}^{x_2} \frac{d}{dx} \left( \frac{\partial L}{\partial y'} \right) \eta(x) dx\] 우리는 처음에 양 끝점을 고정했기 때문에 $\eta(x_1) = 0, \eta(x_2) = 0$이다. 따라서 대괄호 항($uv$ 파트)은 0이 되어 사라진다. 이제 남은 항들을 다시 합쳐서 $\eta(x)$로 묶어주자. \[\int_{x_1}^{x_2} \left[ \frac{\partial L}{\partial y} - \frac{d}{dx} \left( \frac{\partial L}{\partial y'} \right) \right] \eta(x) dx = 0\] 이 식이 어떠한 $\eta(x)$에 대해서도 항상 성립하려면, 적분 기호 안의 대괄호 값이 반드시 $0$이어야 한다. 이를 정리하여 오릴러 라그랑주 방정식 (Euler-Lagrange Equation)이라고 부른다. The Euler-Lagrange Equation: \[\frac{\partial L}{\partial y} - \frac{d}{dx} \left( \frac{\partial L}{\partial y'} \right) = 0\] 이 짧은 방정식이 바로 “전체적인(Global) 최적 경로를 찾기 위해, 곡선의 매 순간(Local)이 지켜야 할 물리 법칙” 을 말해준다. 4. 예시 $L$이 무엇인지, 그리고 오일러 라그랑주 방정식이 말하는 최소 작용의 원리 (principle of least action)이 무엇인지 좀 더 잘 이해하기 위해 예시를 들어보자. $L$은 우리가 최적화하고 싶은 시스템의 상태를 담은 ‘알맹이’라고 말했다. 예를 들어 $x$ 방향으로 이동하고 있는 물체를 생각해보자. 이 경우 라그랑지안 $L$은 운동에너지에서 포텐셜 에너지를 빼준 것과 같다. \[L = \frac{1}{2}mv^2-U(x)\] 이 $L$을 오일러 라그랑주 방정식에 넣으면 어떻게 될까? 식 (8)을 현재 겪고 있는 시간($t$)에 따른 위치 ($x$)의 변화로 바꿔 써주면 아래와 같다. \[\frac{d}{dt}\frac{\partial L}{\partial \dot x}=\frac{\partial L}{\partial x}\] 식 (10)의 좌변에 있는 $\dot x$는 속도 $v$로 써줄 수 있으므로, \[\frac{\partial L}{\partial \dot x} = \frac{\partial L}{\partial v}=mv\] 이다. 한편, 식 (10)의 우변을 보면, \[\frac{\partial L}{\partial x}=-U'(x)\] 이므로 운동 에너지와 포텐셜 에너지 차에 관한 $L$에 대한 식은 아래와 같이 정리된다. \[\Rightarrow \frac{d}{dt}(mv)=-U'(x)\] \[\Rightarrow m\frac{d}{dt}(v)=-U'(x)\] Potential의 negative gradient가 힘과 같으므로, 이 식은 바로 뉴턴 제 2법칙인 가속도의 법칙이며 소위 $F=ma$로 알고 있는 것과 같다. 마치며 변분법은 “결과가 최소가 되려면 과정이 어떠해야 하는가?”를 묻는 학문이다. 이 방정식 덕분에 우리는 뉴턴 역학을 에너지 관점에서 재해석할 수 있게 되었고, 오늘날 로봇의 복잡한 움직임을 제어하거나 인공지능의 오차를 줄이는 데까지 이 원리를 사용하고 있다.]]></summary></entry><entry xml:lang="ko"><title type="html">Linear Quadratic Regulator (LQR)</title><link href="https://angeloyeo.github.io/2026/03/09/LQR.html" rel="alternate" type="text/html" title="Linear Quadratic Regulator (LQR)" /><published>2026-03-09T00:00:00+00:00</published><updated>2026-03-09T00:00:00+00:00</updated><id>https://angeloyeo.github.io/2026/03/09/LQR</id><content type="html" xml:base="https://angeloyeo.github.io/2026/03/09/LQR.html"><![CDATA[<h1 id="prerequisites">Prerequisites</h1>

<p>본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다.</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2026/03/08/Pole_Placing.html">극점 배치법을 활용한 선형 제어기 설계</a></li>
</ul>

<h1 id="극점-배치의-딜레마와-최적-제어-lqrlinear-quadratic-regulator의-우아한-해법">극점 배치의 딜레마와 최적 제어: LQR(Linear Quadratic Regulator)의 우아한 해법</h1>

<p><a href="https://angeloyeo.github.io/2026/03/08/Pole_Placing.html">지난 포스팅</a>에서 우리는 미분방정식으로 표현된 ‘도립 진자’ 시스템을 선형화하고, 상태 피드백($u = -\mathbf{K}\mathbf{x}$)을 통해 시스템 행렬의 고유값(Eigenvalue, 극점)을 원하는 위치로 옮기는 극점 배치(Pole Placement) 기법을 알아보았다.</p>

<p>불안정한 양수의 고유값을 좌반평면(음수)으로 옮기기만 하면 진자는 쓰러지지 않는다. 그런데 여기서 매우 근본적이고 철학적인 질문에 부딪힌다.</p>

<p>“그렇다면, 수많은 음수 위치 중에서 도대체 ‘어디에’ 극점을 두는 것이 가장 좋은가?”</p>

<p>오늘은 이 질문에 대한 제어 공학의 가장 우아하고 수학적인 해답, LQR (Linear Quadratic Regulator)에 대해 알아본다.</p>

<h2 id="1-사고의-시작-제어의-트레이드오프trade-off">1. 사고의 시작: 제어의 트레이드오프(Trade-off)</h2>

<p>극점을 설계할 때 우리는 필연적으로 딜레마에 빠진다.</p>

<ul>
  <li>극점을 원점에서 멀리 (예: -10, -20) 배치할 경우: 시스템은 번개처럼 빠르게 안정화된다. 하지만 이를 위해서는 초기에 엄청난 크기의 제어 입력 $u$(카트 모터의 힘)가 필요하다. 배터리가 순식간에 닳거나, 심하면 모터가 타버릴 수 있다.</li>
  <li>극점을 원점에 가깝게 (예: -0.1, -0.2) 배치할 경우: 에너지는 거의 들지 않는다. 하지만 카트가 너무 느릿느릿 움직여서, 목표 지점에 도달하기까지 세월아 네월아 시간이 걸린다.</li>
</ul>

<p>즉, ‘빠른 응답 속도(성능)’와 ‘적은 에너지 소모(비용)’ 사이에는 시소 같은 트레이드오프가 존재한다. 공학자들은 이 두 마리 토끼를 잡기 위해 고민했고, 이를 최적화(Optimization) 문제로 치환하기로 한다.</p>

<h2 id="2-수학적-모델링-비용-함수cost-function의-설계">2. 수학적 모델링: 비용 함수(Cost Function)의 설계</h2>

<p>이 딜레마를 선형대수학의 언어로 표현해 보자. 우리가 최소화하고 싶은 전체 “비용(Cost)” $J$를 다음과 같은 적분식으로 정의한다.</p>

\[J = \int_{0}^{\infty} \left(\mathbf{x}^T \mathbf{Q} \mathbf{x} + u^T R u\right) dt\]

<p>수식이 복잡해 보이지만, 선형대수학의 이차 형식(Quadratic Form)을 떠올리면 직관적으로 이해할 수 있다.</p>

<ul>
  <li>$\mathbf{x}^T \mathbf{Q} \mathbf{x}$ (상태 오차 페널티): 시스템의 상태 $\mathbf{x}$가 목표점(0)에서 멀어져 있을 때 부과되는 벌금이다. 여기서 행렬 $\mathbf{Q}$는 우리가 정하는 가중치다. 예를 들어, 카트의 위치보다 ‘진자의 각도’가 더 중요하다면 $\mathbf{Q}$ 행렬에서 각도에 해당하는 대각 원소의 값을 크게(예: 100) 주면 된다.</li>
  <li>$u^T R u$ (제어 에너지 페널티): 제어 입력 $u$를 많이 사용할 때 부과되는 벌금이다. 모터 전력이 비싸거나 한계가 있다면 $R$ 값을 크게(예: 10) 주고, 모터 성능이 남아돌아 에너지를 펑펑 써도 된다면 $R$ 값을 작게(예: 0.01) 주면 된다.</li>
</ul>

<p>이제 우리의 목표는 명확해졌다. “이 비용 함수 $J$의 값을 최소(Minimum)로 만드는 최적의 제어 이득 행렬 $\mathbf{K}$를 찾아라!”</p>

<h2 id="3-마법의-지팡이-lqr의-등장">3. 마법의 지팡이: LQR의 등장</h2>

<p>이 최적화 문제를 푸는 과정은 해석학적으로 꽤나 복잡하다(Riccati 미분방정식이라는 거대한 산을 넘어야 한다). 하지만 다행히도, 똑똑한 수학자와 공학자들이 이미 그 해답을 알고리즘으로 만들어 두었다.</p>

<p>우리가 할 일은 그저 시스템의 모델($\mathbf{A, B}$)과 우리가 중요하게 생각하는 가중치($\mathbf{Q}, R$)를 정해주는 것뿐이다. MATLAB에서는 단 한 줄의 코드로 이 복잡한 수학적 최적해를 구해준다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% 시스템 모델 (A, B)와 페널티 가중치 (Q, R)를 정의한 후
A = [0 1 0 0;
    0 -d/M b*m*g/M 0;
    0 0 0 1;
    0 -b*d/(M*L) -b*(m+M)*g/(M*L) 0];

B = [0; 1/M; 0; b*1/(M*L)];

Q = [1 0 0 0;
    0 1 0 0;
    0 0 10 0;
    0 0 0 100];

R = .001;

K = lqr(A, B, Q, R);
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">lqr</code>로 구한 K 값을 이용해 미분방정식을 풀어보면 아래와 같이 제어된 것을 알 수 있다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tspan = 0:.001:10;
x0 = [-1; 0; pi+.1; 0];  % initial condition 
wr = [1; 0; pi; 0];      % reference position
u=@(x)-K*(x - wr);       % control law
[t,x] = ode45(@(t,x)pendcart(x,m,M,L,g,d,u(x)),tspan,x0);
</code></pre></div></div>

<p align="center">
  <video width="100%" height="auto" autoplay="" muted="" controls="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-09-LQR/pendCartLQR.mp4" />
  </video>
</p>

<p>이 때, $A-KB$ 행렬의 고윳값을 보면 아래와 같은데,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt;&gt; eig(A-B*K)

ans =

 -32.4244 + 0.0000i
  -0.8752 + 0.8933i
  -0.8752 - 0.8933i
  -0.8731 + 0.0000i
</code></pre></div></div>

<p>일부 고윳값은 그 절대값의 크기가 크고 나머지는 상대적으로 작다. 아마도, 이 큰 값은 “R” 패널티를 아주 작게 만들었기 때문에 나왔을 수 있다. 제어 비용은 저렴하기 때문에 순간적으로 jerk를 주면서까지도 움직일 수 있게 만든 것이다.</p>

<p>이 때, 아래와 같이 이 큰 고윳값(-32.4244)의 고유벡터를 보면 두 번째, 네 번째 성분은 값이 좀 큰 것을 알 수 있는데, 이 말은 state vector의 두 번째 성분과 네 번째 성분(카트의 속도와 진자의 각속도)의 값이 Q와 R이 말하는 제약사항을 최대한 지키는데 중요한 역할을 했다는 것을 알 수 있다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt;&gt; [V, D] = eig(A-B*K); V(:,1)

ans =

    0.0275
   -0.8928
    0.0139
   -0.4494
</code></pre></div></div>

<p>결론적으로 <code class="language-plaintext highlighter-rouge">lqr</code> 명령어 하나가 내부적으로 최적화 연산을 수행하여, 가장 적은 에너지를 쓰면서도 가장 빠르게 시스템을 안정화하는 최적의 고유값 위치를 스스로 찾아내고, 그에 맞는 $\mathbf{K}$ 행렬을 뱉어낸다. 이름하여 Linear Quadratic Regulator (LQR) 이다.</p>

<ul>
  <li>Linear: 선형 제어기($u = -\mathbf{K}\mathbf{x}$)를 사용하고,</li>
  <li>Quadratic: 이차 형식($\mathbf{x}^T\mathbf{Q}\mathbf{x}$, $u^T R u$)으로 정의된 비용 함수를 최소화하며,</li>
  <li>Regulator: 시스템을 목표점(0)으로 수렴(안정화)시킨다는 뜻이다.</li>
</ul>

<h2 id="4-lqr의-직관적인-튜닝-과정">4. LQR의 직관적인 튜닝 과정</h2>

<p>극점 배치 방식에서는 “어느 위치(-1일까, -2일까?)가 물리적으로 좋은 위치인지” 알 길이 없어 막막했다. 하지만 LQR을 사용하면 튜닝이 매우 직관적으로 변한다.</p>

<ul>
  <li>진자가 자꾸 쓰러지려고 한다면? $\rightarrow$ $\mathbf{Q}$ 행렬에서 각도에 대한 페널티를 올린다. 알아서 더 공격적인 제어기가 튀어나온다.</li>
  <li>모터가 너무 덜덜 떨며 과부하가 걸린다면? $\rightarrow$ $R$ 값을 올려 제어 입력에 페널티를 준다. 알아서 움직임이 부드럽고 완만한 제어기로 바뀐다.</li>
</ul>

<p>우리는 더 이상 알 수 없는 복소평면 위의 극점 위치를 찍으며 헤맬 필요가 없다. “무엇을 더 아끼고 싶은가?”라는 직관적인 가중치만 조절하면, 선형대수학이 알아서 최적의 극점 위치를 역산해 준다.</p>

<h2 id="결론-진정한-공학적-어려움은-어디에-있는가">결론: 진정한 공학적 어려움은 어디에 있는가?</h2>

<p>영상 말미에서 강사인 Steve Brunton 교수는 매우 뼈있는 통찰을 던진다.
<em>“이 예제를 준비하면서 비선형 시스템을 모델링하고 선형화 행렬(A, B)을 수식으로 뽑아내는 데 수 시간이 걸렸습니다. 하지만 제어기(K)를 설계하는 데는 5분도 채 걸리지 않았죠.”</em></p>

<p>현대 제어 공학에서 수학적 툴(LQR 등)은 이미 완성되어 있다. 결국 현실 세계의 문제를 푸는 핵심은, 우리가 마주한 물리적 현상을 얼마나 정확하게 미분방정식과 선형 행렬($\mathbf{A, B}$)로 모델링해낼 수 있는가에 달려 있다.</p>

<p>정확한 시스템 모델 행렬과 선형대수학의 이차 형식, 그리고 <code class="language-plaintext highlighter-rouge">lqr</code> 함수 한 줄. 이것이 바로 불안정한 세상을 가장 효율적으로 통제하는 현대 제어의 우아한 마법이다.</p>

<h1 id="참고-문헌">참고 문헌</h1>

<ul>
  <li>[1] Data-Driven Science and Engineering: Machine Learning, Dynamical Systems, and Control; Steven L. Brunton and J. Nathan Kutz (link)[https://databookuw.com/]</li>
</ul>

<hr />

<p><em>본 포스팅은 워싱턴 대학교 Steve Brunton 교수의 ‘Control Bootcamp’ 유튜브 강의를 참고하여 작성되었습니다.</em></p>]]></content><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><category term="미분방정식" /><category term="선형대수학" /><category term="제어이론" /><summary type="html"><![CDATA[Prerequisites 본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다. 극점 배치법을 활용한 선형 제어기 설계 극점 배치의 딜레마와 최적 제어: LQR(Linear Quadratic Regulator)의 우아한 해법 지난 포스팅에서 우리는 미분방정식으로 표현된 ‘도립 진자’ 시스템을 선형화하고, 상태 피드백($u = -\mathbf{K}\mathbf{x}$)을 통해 시스템 행렬의 고유값(Eigenvalue, 극점)을 원하는 위치로 옮기는 극점 배치(Pole Placement) 기법을 알아보았다. 불안정한 양수의 고유값을 좌반평면(음수)으로 옮기기만 하면 진자는 쓰러지지 않는다. 그런데 여기서 매우 근본적이고 철학적인 질문에 부딪힌다. “그렇다면, 수많은 음수 위치 중에서 도대체 ‘어디에’ 극점을 두는 것이 가장 좋은가?” 오늘은 이 질문에 대한 제어 공학의 가장 우아하고 수학적인 해답, LQR (Linear Quadratic Regulator)에 대해 알아본다. 1. 사고의 시작: 제어의 트레이드오프(Trade-off) 극점을 설계할 때 우리는 필연적으로 딜레마에 빠진다. 극점을 원점에서 멀리 (예: -10, -20) 배치할 경우: 시스템은 번개처럼 빠르게 안정화된다. 하지만 이를 위해서는 초기에 엄청난 크기의 제어 입력 $u$(카트 모터의 힘)가 필요하다. 배터리가 순식간에 닳거나, 심하면 모터가 타버릴 수 있다. 극점을 원점에 가깝게 (예: -0.1, -0.2) 배치할 경우: 에너지는 거의 들지 않는다. 하지만 카트가 너무 느릿느릿 움직여서, 목표 지점에 도달하기까지 세월아 네월아 시간이 걸린다. 즉, ‘빠른 응답 속도(성능)’와 ‘적은 에너지 소모(비용)’ 사이에는 시소 같은 트레이드오프가 존재한다. 공학자들은 이 두 마리 토끼를 잡기 위해 고민했고, 이를 최적화(Optimization) 문제로 치환하기로 한다. 2. 수학적 모델링: 비용 함수(Cost Function)의 설계 이 딜레마를 선형대수학의 언어로 표현해 보자. 우리가 최소화하고 싶은 전체 “비용(Cost)” $J$를 다음과 같은 적분식으로 정의한다. \[J = \int_{0}^{\infty} \left(\mathbf{x}^T \mathbf{Q} \mathbf{x} + u^T R u\right) dt\] 수식이 복잡해 보이지만, 선형대수학의 이차 형식(Quadratic Form)을 떠올리면 직관적으로 이해할 수 있다. $\mathbf{x}^T \mathbf{Q} \mathbf{x}$ (상태 오차 페널티): 시스템의 상태 $\mathbf{x}$가 목표점(0)에서 멀어져 있을 때 부과되는 벌금이다. 여기서 행렬 $\mathbf{Q}$는 우리가 정하는 가중치다. 예를 들어, 카트의 위치보다 ‘진자의 각도’가 더 중요하다면 $\mathbf{Q}$ 행렬에서 각도에 해당하는 대각 원소의 값을 크게(예: 100) 주면 된다. $u^T R u$ (제어 에너지 페널티): 제어 입력 $u$를 많이 사용할 때 부과되는 벌금이다. 모터 전력이 비싸거나 한계가 있다면 $R$ 값을 크게(예: 10) 주고, 모터 성능이 남아돌아 에너지를 펑펑 써도 된다면 $R$ 값을 작게(예: 0.01) 주면 된다. 이제 우리의 목표는 명확해졌다. “이 비용 함수 $J$의 값을 최소(Minimum)로 만드는 최적의 제어 이득 행렬 $\mathbf{K}$를 찾아라!” 3. 마법의 지팡이: LQR의 등장 이 최적화 문제를 푸는 과정은 해석학적으로 꽤나 복잡하다(Riccati 미분방정식이라는 거대한 산을 넘어야 한다). 하지만 다행히도, 똑똑한 수학자와 공학자들이 이미 그 해답을 알고리즘으로 만들어 두었다. 우리가 할 일은 그저 시스템의 모델($\mathbf{A, B}$)과 우리가 중요하게 생각하는 가중치($\mathbf{Q}, R$)를 정해주는 것뿐이다. MATLAB에서는 단 한 줄의 코드로 이 복잡한 수학적 최적해를 구해준다. % 시스템 모델 (A, B)와 페널티 가중치 (Q, R)를 정의한 후 A = [0 1 0 0; 0 -d/M b*m*g/M 0; 0 0 0 1; 0 -b*d/(M*L) -b*(m+M)*g/(M*L) 0]; B = [0; 1/M; 0; b*1/(M*L)]; Q = [1 0 0 0; 0 1 0 0; 0 0 10 0; 0 0 0 100]; R = .001; K = lqr(A, B, Q, R); lqr로 구한 K 값을 이용해 미분방정식을 풀어보면 아래와 같이 제어된 것을 알 수 있다. tspan = 0:.001:10; x0 = [-1; 0; pi+.1; 0]; % initial condition wr = [1; 0; pi; 0]; % reference position u=@(x)-K*(x - wr); % control law [t,x] = ode45(@(t,x)pendcart(x,m,M,L,g,d,u(x)),tspan,x0); 이 때, $A-KB$ 행렬의 고윳값을 보면 아래와 같은데, &gt;&gt; eig(A-B*K) ans = -32.4244 + 0.0000i -0.8752 + 0.8933i -0.8752 - 0.8933i -0.8731 + 0.0000i 일부 고윳값은 그 절대값의 크기가 크고 나머지는 상대적으로 작다. 아마도, 이 큰 값은 “R” 패널티를 아주 작게 만들었기 때문에 나왔을 수 있다. 제어 비용은 저렴하기 때문에 순간적으로 jerk를 주면서까지도 움직일 수 있게 만든 것이다. 이 때, 아래와 같이 이 큰 고윳값(-32.4244)의 고유벡터를 보면 두 번째, 네 번째 성분은 값이 좀 큰 것을 알 수 있는데, 이 말은 state vector의 두 번째 성분과 네 번째 성분(카트의 속도와 진자의 각속도)의 값이 Q와 R이 말하는 제약사항을 최대한 지키는데 중요한 역할을 했다는 것을 알 수 있다. &gt;&gt; [V, D] = eig(A-B*K); V(:,1) ans = 0.0275 -0.8928 0.0139 -0.4494 결론적으로 lqr 명령어 하나가 내부적으로 최적화 연산을 수행하여, 가장 적은 에너지를 쓰면서도 가장 빠르게 시스템을 안정화하는 최적의 고유값 위치를 스스로 찾아내고, 그에 맞는 $\mathbf{K}$ 행렬을 뱉어낸다. 이름하여 Linear Quadratic Regulator (LQR) 이다. Linear: 선형 제어기($u = -\mathbf{K}\mathbf{x}$)를 사용하고, Quadratic: 이차 형식($\mathbf{x}^T\mathbf{Q}\mathbf{x}$, $u^T R u$)으로 정의된 비용 함수를 최소화하며, Regulator: 시스템을 목표점(0)으로 수렴(안정화)시킨다는 뜻이다. 4. LQR의 직관적인 튜닝 과정 극점 배치 방식에서는 “어느 위치(-1일까, -2일까?)가 물리적으로 좋은 위치인지” 알 길이 없어 막막했다. 하지만 LQR을 사용하면 튜닝이 매우 직관적으로 변한다. 진자가 자꾸 쓰러지려고 한다면? $\rightarrow$ $\mathbf{Q}$ 행렬에서 각도에 대한 페널티를 올린다. 알아서 더 공격적인 제어기가 튀어나온다. 모터가 너무 덜덜 떨며 과부하가 걸린다면? $\rightarrow$ $R$ 값을 올려 제어 입력에 페널티를 준다. 알아서 움직임이 부드럽고 완만한 제어기로 바뀐다. 우리는 더 이상 알 수 없는 복소평면 위의 극점 위치를 찍으며 헤맬 필요가 없다. “무엇을 더 아끼고 싶은가?”라는 직관적인 가중치만 조절하면, 선형대수학이 알아서 최적의 극점 위치를 역산해 준다. 결론: 진정한 공학적 어려움은 어디에 있는가? 영상 말미에서 강사인 Steve Brunton 교수는 매우 뼈있는 통찰을 던진다. “이 예제를 준비하면서 비선형 시스템을 모델링하고 선형화 행렬(A, B)을 수식으로 뽑아내는 데 수 시간이 걸렸습니다. 하지만 제어기(K)를 설계하는 데는 5분도 채 걸리지 않았죠.” 현대 제어 공학에서 수학적 툴(LQR 등)은 이미 완성되어 있다. 결국 현실 세계의 문제를 푸는 핵심은, 우리가 마주한 물리적 현상을 얼마나 정확하게 미분방정식과 선형 행렬($\mathbf{A, B}$)로 모델링해낼 수 있는가에 달려 있다. 정확한 시스템 모델 행렬과 선형대수학의 이차 형식, 그리고 lqr 함수 한 줄. 이것이 바로 불안정한 세상을 가장 효율적으로 통제하는 현대 제어의 우아한 마법이다. 참고 문헌 [1] Data-Driven Science and Engineering: Machine Learning, Dynamical Systems, and Control; Steven L. Brunton and J. Nathan Kutz (link)[https://databookuw.com/] 본 포스팅은 워싱턴 대학교 Steve Brunton 교수의 ‘Control Bootcamp’ 유튜브 강의를 참고하여 작성되었습니다.]]></summary></entry><entry xml:lang="ko"><title type="html">극점 배치법을 활용한 선형 제어기 설계</title><link href="https://angeloyeo.github.io/2026/03/08/Pole_Placing.html" rel="alternate" type="text/html" title="극점 배치법을 활용한 선형 제어기 설계" /><published>2026-03-08T00:00:00+00:00</published><updated>2026-03-08T00:00:00+00:00</updated><id>https://angeloyeo.github.io/2026/03/08/Pole_Placing</id><content type="html" xml:base="https://angeloyeo.github.io/2026/03/08/Pole_Placing.html"><![CDATA[<p align="center">
  <video width="100%" height="auto" loop="" autoplay="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-08-Pole_Placing/InvertedDoublePendulum.mp4" />
  </video>
  <br />
  극점 배치법을 이용한 이중도립진자의 제어. <br /> 모델 소스: <a href="https://kr.mathworks.com/help/sm/ug/inverted-double-pendulum-on-a-sliding-cart.html"> MathWorks Simscape Multibody 문서 </a>
</p>

<h1 id="prerequisites">Prerequisites</h1>

<p>본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다.</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2021/05/05/ODE_and_natural_number_e.html">자연상수 e와 제차 미분방정식</a></li>
  <li><a href="https://angeloyeo.github.io/2021/05/25/nonhomogeneous_equation.html">비제차 미분방정식의 의미</a></li>
  <li><a href="https://angeloyeo.github.io/2019/07/17/eigen_vector.html">고윳값과 고유벡터</a></li>
  <li><a href="https://angeloyeo.github.io/2020/07/24/Jacobian.html">자코비안(Jacobian) 행렬의 기하학적 의미</a></li>
  <li><a href="https://angeloyeo.github.io/2019/08/12/Laplace_transform.html">라플라스 변환(Laplace transform)</a></li>
</ul>

<p>제어의 뿌리가 선형대수학과 미분방정식이라는걸 알 수 있는 prerequisite 이네요. 선형대수학과 미분방정식이 제어 공학과 어떻게 완벽하게 맞물려 돌아가는지, 그 아름다운 연결고리를 듬뿍 담아 블로그 포스팅을 작성해 보았습니다.</p>

<h1 id="미분방정식과-선형대수학으로-거꾸로-선-진자-세우기-극점-배치pole-placement의-마법">미분방정식과 선형대수학으로 ‘거꾸로 선 진자’ 세우기: 극점 배치(Pole Placement)의 마법</h1>

<p>학부 시절, 우리는 미분방정식을 풀고 행렬의 고유값(Eigenvalue)을 계산하며 이런 의문을 품곤 했을 것이다. <em>“도대체 이 복잡한 수학을 현실 어디에 써먹는 걸까?”</em></p>

<p>오늘은 그 질문에 대한 가장 짜릿한 대답 중 하나를 소개하려고 한다. 바로 <strong>제어 공학(Control Engineering)</strong>이다. 카트 위에 위태롭게 서 있는 막대기를 쓰러지지 않게 세우는 <strong>‘도립 진자(Inverted Pendulum)’</strong> 시스템을 통해, 우리가 배운 수학이 어떻게 물리적 세상을 지배하는지 알아보자.</p>

<p>이번 파트에서는 제어에 대한 지식보다는 우리가 잘 아는 선형대수학과 미분방정식의 기초에 기반하여 “극점 배치” 제어 기법에 대해서 알아볼 것이다.</p>

<hr />

<h2 id="1-물리-현상을-수학의-언어로-미분방정식과-상태state">1. 물리 현상을 수학의 언어로: 미분방정식과 상태(State)</h2>

<p align="center">
  <img width="50%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-08-Pole_Placing/pic1.png" />
  <br />
  그림 1. 카트 + 도립 진자 문제. 그림 출처: 참고 문헌 [1]의 Figure 8.12
</p>

<p>우리의 목표는 카트(Cart)를 좌우로 움직여서 그 위에 얹혀 있는 진자(Pendulum)가 쓰러지지 않게 수직($\theta = \pi$)으로 세우는 것이다.</p>

<p>먼저 이 시스템을 뉴턴의 역학 법칙으로 풀어내면, 위치와 각도의 2계 미분(가속도)이 포함된 복잡한 <strong>비선형 연립 미분방정식</strong>이 등장한다.</p>

<p>여기서 제어공학은 첫 번째 수학적 기교를 부린다. 고계 미분방정식을 다루기 쉽게 만들기 위해, 변수들을 1차 미분 형태로 쪼개어 하나의 <strong>벡터(Vector)</strong>로 묶을 수 있다.</p>

<p>카트의 위치($x$), 속도($\dot{x}$), 진자의 각도($\theta$), 각속도($\dot{\theta}$)를 원소로 하는 4차원 벡터 $\mathbf{x}$를 정의하고 이를 <strong>상태 벡터(State Vector)</strong>라고 부르자.</p>

\[\mathbf{x} = \begin{bmatrix} x \\ \dot{x} \\ \theta \\ \dot{\theta} \end{bmatrix} % 식(1)\]

<p><strong>“제어(control)”</strong> 의 이름에서 알 수 있듯이 우리는 외부 입력을 통해서 시스템의 상태를 조정할 수 있다. <a href="https://angeloyeo.github.io/2021/05/25/nonhomogeneous_equation.html">비제차 미분방정식의 의미</a> 편에서 본 것 처럼, 외부 입력 $u$가 포함된 비제차 미분방정식을 아래와 같이 표현할 수 있을 것이다.</p>

\[\dot{\mathbf{x}} = f(\mathbf{x}, u) % 식 (2)\]

<p><em>(여기서 $u$가 우리가 카트에 가하는 ‘힘’, 즉 제어 입력이며, 함수 $f$는 비선형 함수일 수 있다.)</em></p>

<p>이제 시스템의 움직임은 4차원 공간 안에서 점이 이동하는 궤적으로 추상화되었다고 수학적으로 이해할 수 있다. 참고로 식 (2)에 대한 구체적인 nonlinear dynamics는 아래와 같다.</p>

\[\dot{x} = v % 식 (3)\]

\[\dot{v} = \frac{-m^2L^2g\cos\theta + mL^2(mL\omega^2\sin\theta-\delta v)+mL^2u}{mL^2\left(M+m(1-\cos^2\theta\right))} % 식 (4)\]

\[\dot{\theta} = \omega % 식 (5)\]

\[\dot{\omega} = \frac{(m+M)mgL\sin\theta-mL\cos\theta(mL\omega^2\sin\theta-\delta v)+mL(\cos\theta) u}{mL^2(M+m(1-\cos^2\theta))} % 식 (6)\]

<p>여기서 $x$는 카트의 위치, $v$는 카트의 속도, $\theta$는 진자의 각도, $\omega$는 진자의 각속도, $m$은 진자의 무게, $M$은 카트의 무게, $L$은 진자의 팔 길이, $g$는 중력 가속도, $\delta$는 friction damping 계수, 그리고 $u$는 카트에 작용하는 제어 힘이다.</p>

<p>MATLAB으로 이 nonlinear dynamics를 쓰면 아래와 같다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>function dx=pendcart(x,m,M,L,g,d,u)
Sx= sin(x(3));
Cx= cos(x(3));
D =m*L*L*(M+m*(1-Cxˆ2));
dx(1,1)=x(2);
dx(2,1)=(1/D)*(-mˆ2*Lˆ2*g*Cx*Sx+m*Lˆ2*(m*L*x(4)ˆ2*Sx-d*x(2)))+m*L*L*(1/D)*u;
dx(3,1)=x(4);
dx(4,1)=(1/D)*((m+M)*m*g*L*Sx-m*L*Cx*(m*L*x(4)ˆ2*Sx-d*x(2)))-m*L*Cx*(1/D)*u;
</code></pre></div></div>

<p>이 시스템을 아무런 입력 없이 ode45로 풀면 아래와 같이 진자가 흔들리면서 마찰 계수 $\delta$에 의해 서서히 멈추는 결과를 확인할 수 있다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>m = 1;
M = 5;
L = 2;
g = -10;
d = 1;
tspan = 0:.001:30;
y0 = [0; 0; 0; 0];
[t, y] = ode45(@(t,y) pendcart(y, m, M, L, g, d, 0), tspan, y0);
</code></pre></div></div>

<p align="center">
  <video width="100%" height="auto" loop="" autoplay="" controls="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-08-Pole_Placing/pendCartNoInpupt.mp4" />
  </video>
</p>

<h2 id="2-비선형의-벽을-넘다-jacobian과-선형화">2. 비선형의 벽을 넘다: Jacobian과 선형화</h2>

<p>하지만 $f(\mathbf{x}, u)$는 삼각함수($\sin\theta, \cos\theta$)가 난무하는 비선형 함수이다. 지금까지의 논의처럼 선형 시스템에 비해 비선형 시스템(혹은 미분방정식)은 해석적인 해를 구하기도, 다루기도 너무 어렵다.</p>

<p>여기서 <strong>선형대수학의 다변수 미분, 즉 <a href="https://angeloyeo.github.io/2020/07/24/Jacobian.html">자코비안(Jacobian)</a></strong> 이 구원투수로 등장한다. 우리는 진자가 꼿꼿이 서 있는 목표 상태(Fixed Point) 근처에서 이 비선형 방정식을 테일러 전개하여 <strong>선형화(Linearization)</strong> 할 수 있다. 그 결과, 다음과 같은 아름다운 <strong>상태 공간 방정식(State-Space Equation)</strong> 을 얻게 된다.</p>

\[\dot{\mathbf{x}} = \mathbf{A}\mathbf{x} + \mathbf{B}u % 식 (7)\]

<ul>
  <li><strong>$\mathbf{A}$ (4x4 시스템 행렬):</strong> 시스템 자체의 물리적 특성(질량, 길이, 마찰 등)을 담고 있는 행렬</li>
  <li><strong>$\mathbf{B}$ (4x1 입력 행렬):</strong> 우리가 가하는 힘 $u$가 4개의 상태 변수에 각각 얼마나 영향을 미치는지를 나타내는 벡터</li>
</ul>

<p>Fixed Point는 진자가 완전 내려가 있거나 ($\theta = 0$) 혹은 똑바로 서 있는 경우($\theta = \pi$)이며, 이때 카트의 속도와 진자의 각속도는 모두 0인 상태($v=\omega=0$)이다. 카트의 위치는 어디에 있던지 상관 없으므로 $x$는 free variable이다. 구체적으로 선형화된 식인 식 (7)을 써보자면 아래와 같다.</p>

\[\frac{d}{dt}\begin{bmatrix}x_1\\x_2\\x_3\\x_4\end{bmatrix}
= \begin{bmatrix}
   0 &amp;&amp; 1 &amp;&amp; 0 &amp;&amp; 0 
\\ 0 &amp;&amp; \frac{-\delta}{M} &amp;&amp; b\frac{mg}{M} &amp;&amp; 0 
\\ 0 &amp;&amp; 0 &amp;&amp; 0 &amp;&amp; 1
\\ 0 &amp;&amp; -b\frac{\delta}{ML} &amp;&amp; -b\frac{(m+M)g}{ML} &amp;&amp; 0 \end{bmatrix}\begin{bmatrix}x_1\\x_2\\x_3\\x_4\end{bmatrix}+\begin{bmatrix}0\\\frac{1}{M}\\0\\b\frac{1}{ML}\end{bmatrix}u\text{, for }\begin{bmatrix}x_1\\x_2\\x_3\\x_4\end{bmatrix}=\begin{bmatrix}x\\v\\\theta\\\omega\end{bmatrix}\]

<p>여기서 $b=1$는 진자가 똑바로 서있는 경우의 fixed point를 상정하며, $b=-1$은 진자가 완전 내려가 있는 상태를 상정한다.</p>

<p>이 내용을 MATLAB으로 옮기면 아래와 같다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>m =1; M=5; L=2; g=-10; d=1;
b =1; %Pendulumup(b=1)
A = [0 1 0 0;
  0 -d/M b*m*g/M 0;
  0 0 0 1;
  0 -b*d/(M*L) -b*(m+M)*g/(M*L) 0];

B =[0; 1/M; 0; b*1/(M*L)];
</code></pre></div></div>

<p>이제 복잡한 미분방정식이 <strong>행렬의 곱셈</strong>이라는 선형대수학의 영역으로 완벽하게 넘어왔다.</p>

<h2 id="3-진자는-왜-쓰러지는가-해solution와-eigenvalue">3. 진자는 왜 쓰러지는가?: 해(Solution)와 Eigenvalue</h2>

\[\dot{\mathbf{x}} = \mathbf{A}\mathbf{x}\]

<p>외부 입력($u=0$)이 없을 때, 이 1계 선형 미분방정식의 일반해는 어떻게 될까? 미분방정식 시간에 배웠듯, 해는 행렬 $\mathbf{A}$의 <strong>고유값(Eigenvalue, $\lambda$)</strong>과 <strong>고유벡터(Eigenvector, $\mathbf{v}$)</strong>의 선형 결합으로 나타난다.</p>

\[\mathbf{x}(t) = c_1 e^{\lambda_1 t}\mathbf{v}_1 + c_2 e^{\lambda_2 t}\mathbf{v}_2 + c_3 e^{\lambda_3 t}\mathbf{v}_3 + c_4 e^{\lambda_4 t}\mathbf{v}_4\]

<p>이 수식을 물리적으로 해석해 보자. 만약 고유값 $\lambda$ 중 단 하나라도 <strong>실수부가 양수(Positive)</strong>라면 어떻게 될까? 시간이 지남에 따라 $e^{\lambda t}$ 항이 무한대로 발산해버린다.</p>

<p>실제로 이 시스템의 행렬 $\mathbf{A}$의 Eigenvalue를 구해보면 양수 값이 존재한다. 진자가 목표점(수직)에서 아주 조금만 벗어나도 기하급수적으로 오차가 커지며 <strong>쓰러진다(발산한다)</strong>는 물리적 직관이, 선형대수학의 고유값을 통해 완벽하게 증명되는 순간이다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt;&gt; lambda = eig(A)
lambda =
  0
  -2.4311
  -0.2336
  2.4648
</code></pre></div></div>

<h2 id="4-우리가-이-시스템을-지배할-수-있을까-가제어성controllability과-span">4. 우리가 이 시스템을 지배할 수 있을까?: 가제어성(Controllability)과 Span</h2>

<p>그렇다면 힘 $u$를 적절히 주면 이 발산을 막을 수 있을까? 제어를 시작하기 전에, 선형대수학의 <strong>기저(Basis)</strong>와 <strong>생성(Span)</strong> 개념을 빌려 이 시스템이 제어 가능한지(Controllable) 확인해야 한다.</p>

<p>입력 $\mathbf{B}$가 행렬 $\mathbf{A}$와 상호작용하며 상태 공간을 얼마나 휘저을 수 있는지 나타내는 행렬을 <strong>가제어성 행렬(Controllability Matrix)</strong>이라고 한다.</p>

\[\mathcal{C} = [\mathbf{B} \quad \mathbf{A}\mathbf{B} \quad \mathbf{A}^2\mathbf{B} \quad \mathbf{A}^3\mathbf{B}]\]

<p>이 4x4 행렬의 <strong>Rank(계수)가 4</strong>라면, 이 열벡터들이 4차원 상태 공간 전체를 <strong>Span(생성)</strong>한다는 뜻이다. 즉, 카트에 가하는 힘 $u$ 하나만으로 4개의 상태 변수(위치, 속도, 각도, 각속도)를 모두 우리가 원하는 곳으로 보낼 수 있다는 수학적 보증 수표이다. 다행히 이 시스템은 Rank가 4로 나온다!</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt;&gt; rank(ctrb(A,B))
ans =
  4
</code></pre></div></div>

<h2 id="5-시스템을-해킹하다-극점-배치-pole-placing">5. 시스템을 해킹하다: 극점 배치 (Pole Placing)</h2>

<p>이제 이 포스팅의 하이라이트이자, 제어의 마술인 <strong>극점 배치(Pole Placing)</strong>를 진행해보자.</p>

<p>우리는 시스템이 불안정하다는 것(Eigenvalue가 양수임)을 알았다. 그렇다면 <strong>행렬 $\mathbf{A}$ 자체를 뜯어고칠 수는 없을까?</strong> 현재 상태 $\mathbf{x}$를 실시간으로 측정하여, 제어 입력 $u$를 다음과 같이 상태 벡터의 선형 결합으로 만들어 봅시다. 이를 <strong>상태 피드백(State Feedback)</strong>이라고 한다.</p>

\[u = -\mathbf{K}\mathbf{x}\]

<p>(여기서 $\mathbf{K}$는 1x4 이득 행렬이다.)</p>

<p>이 식을 원래 방정식에 대입해 볼까?</p>

\[\dot{\mathbf{x}} = \mathbf{A}\mathbf{x} + \mathbf{B}(-\mathbf{K}\mathbf{x})\]

\[\dot{\mathbf{x}} = (\mathbf{A} - \mathbf{B}\mathbf{K})\mathbf{x}\]

<p>놀라운 일이 벌어졌다! 원래 시스템 행렬 $\mathbf{A}$가, 우리의 제어기 $\mathbf{K}$가 포함된 <strong>새로운 행렬 $(\mathbf{A} - \mathbf{B}\mathbf{K})$로 바뀌었다.</strong> 제어공학에서 고유값(Eigenvalue)을 부르는 다른 이름이 바로 <strong>극점(Pole)</strong>이다. <strong>Pole Placing(극점 배치)</strong>란, 우리가 설계할 행렬 $\mathbf{K}$의 값들을 조절하여, <strong>새로운 행렬 $(\mathbf{A} - \mathbf{B}\mathbf{K})$의 Eigenvalue들을 우리가 원하는 위치(음수 방향)로 강제로 이동시키는 기술</strong>을 말한다.</p>

<h2 id="6-eigenvalue-위치에-따른-시뮬레이션-결과">6. Eigenvalue 위치에 따른 시뮬레이션 결과</h2>

<p>MATLAB과 같은 툴을 이용하면 $\mathbf{K}$를 구하는 것은 <code class="language-plaintext highlighter-rouge">place</code> 함수 한 줄이면 끝난다. Eigenvalue(Pole)를 복소평면의 좌반평면(음수)으로 옮기면 시스템은 무조건 안정화(수렴)된다. 하지만 <strong>어디로</strong> 옮기느냐에 따라 물리적 거동이 완전히 달라진다.</p>

<p><strong>원점에 가까운 음수 (예: -0.1, -0.2):</strong></p>
<ul>
  <li>$e^{-0.1t}$처럼 천천히 0으로 수렴한다.</li>
  <li><strong>결과:</strong> 카트가 목표 지점으로 매우 느릿느릿 이동하며, 진자도 천천히 중심을 잡는다. 부드럽지만 답답하다.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>p = [-.3; -.4; -.5; -.6]; % just barely good

K = place(A, B, p);

tspan = 0:.001:10;
y0 = [0; 0; 0; 0];
[t, y] = ode45(@(t,y) pendcart(y, m, M, L, g, d, -K*(y-[4;0;0;0])), tspan, y0);
end
</code></pre></div></div>

<p align="center">
  <video width="100%" height="auto" autoplay="" muted="" controls="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-08-Pole_Placing/pendCartPolePlaced.mp4" />
  </video>
</p>

<p><strong>더 먼 음수 (예: -1.0, -2.0):</strong></p>
<ul>
  <li>$e^{-2.0t}$처럼 빠르게 0으로 수렴한다.</li>
  <li><strong>결과:</strong> 카트가 날렵하고 공격적으로 움직여 목표 지점에 딱 멈춰 선다. 훌륭한 제어 성능을 보인다.
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>p = [-1; -2; -3; -4];
</code></pre></div>    </div>
  </li>
</ul>

<p align="center">
  <video width="100%" height="auto" autoplay="" muted="" controls="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-08-Pole_Placing/pendCartPolePlaced2.mp4" />
  </video>
</p>

<p><strong>극단적인 음수 (예: -5.0 이하):</strong></p>
<ul>
  <li>이론적으로는 수렴 속도가 엄청나게 빨라서 극단적으로 큰 크기의 음수일 수록 좋다고 생각할 수 있다.</li>
  <li><strong>결과:</strong> 실제로는 문제가 생긴다. 행렬 $\mathbf{K}$의 값이 너무 커져서, 초기 오차를 잡기 위해 카트 모터에 비현실적으로 거대한 힘($u$)을 요구하게 된다. 움직임이 너무 거칠어지고(Jerky), 선형화 범위를 벗어나 비선형성 때문에 시스템이 붕괴할 수도 있다.</li>
</ul>

<h2 id="마무리하며">마무리하며</h2>

<p>정리해보면, <strong>제어란 “시스템의 미분방정식을 지배하는 행렬의 Eigenvalue를, 선형대수학의 조작을 통해 원하는 위치(Pole)로 옮겨 심는 작업”</strong>이다.</p>

<p>칠판 위에서만 존재하던 미분방정식의 $e^{\lambda t}$ 수식이, 위태로운 진자를 똑바로 세우고 자율주행차를 차선 안에 유지시키는 물리적인 힘으로 치환되는 과정. 이것이 바로 선형대수학과 미분방정식을 배운 우리가 제어 공학에 매력을 느낄 수밖에 없는 이유이다.</p>

<p>하지만 마지막에 보았듯, 무작정 고유값을 멀리 보낸다고 능사는 아니다. “제어 에너지를 적게 쓰면서도 가장 빠르게 안정화되는 <strong>최적의 Eigenvalue 위치</strong>는 어디일까?”
이 질문에 대한 해답이 바로 다음 포스팅에서 다룰 <strong>LQR (Linear Quadratic Regulator)</strong> 최적 제어이다.</p>

<h1 id="참고-문헌">참고 문헌</h1>

<ul>
  <li>[1] Data-Driven Science and Engineering: Machine Learning, Dynamical Systems, and Control, Steven L. Brunton and J. Nathan Kutz (link)[https://databookuw.com/]</li>
</ul>

<hr />

<p><em>본 포스팅은 워싱턴 대학교 Steve Brunton 교수의 ‘Control Bootcamp’ 유튜브 강의를 참고하여 작성되었습니다.</em></p>]]></content><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><category term="미분방정식" /><category term="선형대수학" /><category term="제어이론" /><summary type="html"><![CDATA[극점 배치법을 이용한 이중도립진자의 제어. 모델 소스: MathWorks Simscape Multibody 문서 Prerequisites 본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다. 자연상수 e와 제차 미분방정식 비제차 미분방정식의 의미 고윳값과 고유벡터 자코비안(Jacobian) 행렬의 기하학적 의미 라플라스 변환(Laplace transform) 제어의 뿌리가 선형대수학과 미분방정식이라는걸 알 수 있는 prerequisite 이네요. 선형대수학과 미분방정식이 제어 공학과 어떻게 완벽하게 맞물려 돌아가는지, 그 아름다운 연결고리를 듬뿍 담아 블로그 포스팅을 작성해 보았습니다. 미분방정식과 선형대수학으로 ‘거꾸로 선 진자’ 세우기: 극점 배치(Pole Placement)의 마법 학부 시절, 우리는 미분방정식을 풀고 행렬의 고유값(Eigenvalue)을 계산하며 이런 의문을 품곤 했을 것이다. “도대체 이 복잡한 수학을 현실 어디에 써먹는 걸까?” 오늘은 그 질문에 대한 가장 짜릿한 대답 중 하나를 소개하려고 한다. 바로 제어 공학(Control Engineering)이다. 카트 위에 위태롭게 서 있는 막대기를 쓰러지지 않게 세우는 ‘도립 진자(Inverted Pendulum)’ 시스템을 통해, 우리가 배운 수학이 어떻게 물리적 세상을 지배하는지 알아보자. 이번 파트에서는 제어에 대한 지식보다는 우리가 잘 아는 선형대수학과 미분방정식의 기초에 기반하여 “극점 배치” 제어 기법에 대해서 알아볼 것이다. 1. 물리 현상을 수학의 언어로: 미분방정식과 상태(State) 그림 1. 카트 + 도립 진자 문제. 그림 출처: 참고 문헌 [1]의 Figure 8.12 우리의 목표는 카트(Cart)를 좌우로 움직여서 그 위에 얹혀 있는 진자(Pendulum)가 쓰러지지 않게 수직($\theta = \pi$)으로 세우는 것이다. 먼저 이 시스템을 뉴턴의 역학 법칙으로 풀어내면, 위치와 각도의 2계 미분(가속도)이 포함된 복잡한 비선형 연립 미분방정식이 등장한다. 여기서 제어공학은 첫 번째 수학적 기교를 부린다. 고계 미분방정식을 다루기 쉽게 만들기 위해, 변수들을 1차 미분 형태로 쪼개어 하나의 벡터(Vector)로 묶을 수 있다. 카트의 위치($x$), 속도($\dot{x}$), 진자의 각도($\theta$), 각속도($\dot{\theta}$)를 원소로 하는 4차원 벡터 $\mathbf{x}$를 정의하고 이를 상태 벡터(State Vector)라고 부르자. \[\mathbf{x} = \begin{bmatrix} x \\ \dot{x} \\ \theta \\ \dot{\theta} \end{bmatrix} % 식(1)\] “제어(control)” 의 이름에서 알 수 있듯이 우리는 외부 입력을 통해서 시스템의 상태를 조정할 수 있다. 비제차 미분방정식의 의미 편에서 본 것 처럼, 외부 입력 $u$가 포함된 비제차 미분방정식을 아래와 같이 표현할 수 있을 것이다. \[\dot{\mathbf{x}} = f(\mathbf{x}, u) % 식 (2)\] (여기서 $u$가 우리가 카트에 가하는 ‘힘’, 즉 제어 입력이며, 함수 $f$는 비선형 함수일 수 있다.) 이제 시스템의 움직임은 4차원 공간 안에서 점이 이동하는 궤적으로 추상화되었다고 수학적으로 이해할 수 있다. 참고로 식 (2)에 대한 구체적인 nonlinear dynamics는 아래와 같다. \[\dot{x} = v % 식 (3)\] \[\dot{v} = \frac{-m^2L^2g\cos\theta + mL^2(mL\omega^2\sin\theta-\delta v)+mL^2u}{mL^2\left(M+m(1-\cos^2\theta\right))} % 식 (4)\] \[\dot{\theta} = \omega % 식 (5)\] \[\dot{\omega} = \frac{(m+M)mgL\sin\theta-mL\cos\theta(mL\omega^2\sin\theta-\delta v)+mL(\cos\theta) u}{mL^2(M+m(1-\cos^2\theta))} % 식 (6)\] 여기서 $x$는 카트의 위치, $v$는 카트의 속도, $\theta$는 진자의 각도, $\omega$는 진자의 각속도, $m$은 진자의 무게, $M$은 카트의 무게, $L$은 진자의 팔 길이, $g$는 중력 가속도, $\delta$는 friction damping 계수, 그리고 $u$는 카트에 작용하는 제어 힘이다. MATLAB으로 이 nonlinear dynamics를 쓰면 아래와 같다. function dx=pendcart(x,m,M,L,g,d,u) Sx= sin(x(3)); Cx= cos(x(3)); D =m*L*L*(M+m*(1-Cxˆ2)); dx(1,1)=x(2); dx(2,1)=(1/D)*(-mˆ2*Lˆ2*g*Cx*Sx+m*Lˆ2*(m*L*x(4)ˆ2*Sx-d*x(2)))+m*L*L*(1/D)*u; dx(3,1)=x(4); dx(4,1)=(1/D)*((m+M)*m*g*L*Sx-m*L*Cx*(m*L*x(4)ˆ2*Sx-d*x(2)))-m*L*Cx*(1/D)*u; 이 시스템을 아무런 입력 없이 ode45로 풀면 아래와 같이 진자가 흔들리면서 마찰 계수 $\delta$에 의해 서서히 멈추는 결과를 확인할 수 있다. m = 1; M = 5; L = 2; g = -10; d = 1; tspan = 0:.001:30; y0 = [0; 0; 0; 0]; [t, y] = ode45(@(t,y) pendcart(y, m, M, L, g, d, 0), tspan, y0); 2. 비선형의 벽을 넘다: Jacobian과 선형화 하지만 $f(\mathbf{x}, u)$는 삼각함수($\sin\theta, \cos\theta$)가 난무하는 비선형 함수이다. 지금까지의 논의처럼 선형 시스템에 비해 비선형 시스템(혹은 미분방정식)은 해석적인 해를 구하기도, 다루기도 너무 어렵다. 여기서 선형대수학의 다변수 미분, 즉 자코비안(Jacobian) 이 구원투수로 등장한다. 우리는 진자가 꼿꼿이 서 있는 목표 상태(Fixed Point) 근처에서 이 비선형 방정식을 테일러 전개하여 선형화(Linearization) 할 수 있다. 그 결과, 다음과 같은 아름다운 상태 공간 방정식(State-Space Equation) 을 얻게 된다. \[\dot{\mathbf{x}} = \mathbf{A}\mathbf{x} + \mathbf{B}u % 식 (7)\] $\mathbf{A}$ (4x4 시스템 행렬): 시스템 자체의 물리적 특성(질량, 길이, 마찰 등)을 담고 있는 행렬 $\mathbf{B}$ (4x1 입력 행렬): 우리가 가하는 힘 $u$가 4개의 상태 변수에 각각 얼마나 영향을 미치는지를 나타내는 벡터 Fixed Point는 진자가 완전 내려가 있거나 ($\theta = 0$) 혹은 똑바로 서 있는 경우($\theta = \pi$)이며, 이때 카트의 속도와 진자의 각속도는 모두 0인 상태($v=\omega=0$)이다. 카트의 위치는 어디에 있던지 상관 없으므로 $x$는 free variable이다. 구체적으로 선형화된 식인 식 (7)을 써보자면 아래와 같다. \[\frac{d}{dt}\begin{bmatrix}x_1\\x_2\\x_3\\x_4\end{bmatrix} = \begin{bmatrix} 0 &amp;&amp; 1 &amp;&amp; 0 &amp;&amp; 0 \\ 0 &amp;&amp; \frac{-\delta}{M} &amp;&amp; b\frac{mg}{M} &amp;&amp; 0 \\ 0 &amp;&amp; 0 &amp;&amp; 0 &amp;&amp; 1 \\ 0 &amp;&amp; -b\frac{\delta}{ML} &amp;&amp; -b\frac{(m+M)g}{ML} &amp;&amp; 0 \end{bmatrix}\begin{bmatrix}x_1\\x_2\\x_3\\x_4\end{bmatrix}+\begin{bmatrix}0\\\frac{1}{M}\\0\\b\frac{1}{ML}\end{bmatrix}u\text{, for }\begin{bmatrix}x_1\\x_2\\x_3\\x_4\end{bmatrix}=\begin{bmatrix}x\\v\\\theta\\\omega\end{bmatrix}\] 여기서 $b=1$는 진자가 똑바로 서있는 경우의 fixed point를 상정하며, $b=-1$은 진자가 완전 내려가 있는 상태를 상정한다. 이 내용을 MATLAB으로 옮기면 아래와 같다. m =1; M=5; L=2; g=-10; d=1; b =1; %Pendulumup(b=1) A = [0 1 0 0; 0 -d/M b*m*g/M 0; 0 0 0 1; 0 -b*d/(M*L) -b*(m+M)*g/(M*L) 0]; B =[0; 1/M; 0; b*1/(M*L)]; 이제 복잡한 미분방정식이 행렬의 곱셈이라는 선형대수학의 영역으로 완벽하게 넘어왔다. 3. 진자는 왜 쓰러지는가?: 해(Solution)와 Eigenvalue \[\dot{\mathbf{x}} = \mathbf{A}\mathbf{x}\] 외부 입력($u=0$)이 없을 때, 이 1계 선형 미분방정식의 일반해는 어떻게 될까? 미분방정식 시간에 배웠듯, 해는 행렬 $\mathbf{A}$의 고유값(Eigenvalue, $\lambda$)과 고유벡터(Eigenvector, $\mathbf{v}$)의 선형 결합으로 나타난다. \[\mathbf{x}(t) = c_1 e^{\lambda_1 t}\mathbf{v}_1 + c_2 e^{\lambda_2 t}\mathbf{v}_2 + c_3 e^{\lambda_3 t}\mathbf{v}_3 + c_4 e^{\lambda_4 t}\mathbf{v}_4\] 이 수식을 물리적으로 해석해 보자. 만약 고유값 $\lambda$ 중 단 하나라도 실수부가 양수(Positive)라면 어떻게 될까? 시간이 지남에 따라 $e^{\lambda t}$ 항이 무한대로 발산해버린다. 실제로 이 시스템의 행렬 $\mathbf{A}$의 Eigenvalue를 구해보면 양수 값이 존재한다. 진자가 목표점(수직)에서 아주 조금만 벗어나도 기하급수적으로 오차가 커지며 쓰러진다(발산한다)는 물리적 직관이, 선형대수학의 고유값을 통해 완벽하게 증명되는 순간이다. &gt;&gt; lambda = eig(A) lambda = 0 -2.4311 -0.2336 2.4648 4. 우리가 이 시스템을 지배할 수 있을까?: 가제어성(Controllability)과 Span 그렇다면 힘 $u$를 적절히 주면 이 발산을 막을 수 있을까? 제어를 시작하기 전에, 선형대수학의 기저(Basis)와 생성(Span) 개념을 빌려 이 시스템이 제어 가능한지(Controllable) 확인해야 한다. 입력 $\mathbf{B}$가 행렬 $\mathbf{A}$와 상호작용하며 상태 공간을 얼마나 휘저을 수 있는지 나타내는 행렬을 가제어성 행렬(Controllability Matrix)이라고 한다. \[\mathcal{C} = [\mathbf{B} \quad \mathbf{A}\mathbf{B} \quad \mathbf{A}^2\mathbf{B} \quad \mathbf{A}^3\mathbf{B}]\] 이 4x4 행렬의 Rank(계수)가 4라면, 이 열벡터들이 4차원 상태 공간 전체를 Span(생성)한다는 뜻이다. 즉, 카트에 가하는 힘 $u$ 하나만으로 4개의 상태 변수(위치, 속도, 각도, 각속도)를 모두 우리가 원하는 곳으로 보낼 수 있다는 수학적 보증 수표이다. 다행히 이 시스템은 Rank가 4로 나온다! &gt;&gt; rank(ctrb(A,B)) ans = 4 5. 시스템을 해킹하다: 극점 배치 (Pole Placing) 이제 이 포스팅의 하이라이트이자, 제어의 마술인 극점 배치(Pole Placing)를 진행해보자. 우리는 시스템이 불안정하다는 것(Eigenvalue가 양수임)을 알았다. 그렇다면 행렬 $\mathbf{A}$ 자체를 뜯어고칠 수는 없을까? 현재 상태 $\mathbf{x}$를 실시간으로 측정하여, 제어 입력 $u$를 다음과 같이 상태 벡터의 선형 결합으로 만들어 봅시다. 이를 상태 피드백(State Feedback)이라고 한다. \[u = -\mathbf{K}\mathbf{x}\] (여기서 $\mathbf{K}$는 1x4 이득 행렬이다.) 이 식을 원래 방정식에 대입해 볼까? \[\dot{\mathbf{x}} = \mathbf{A}\mathbf{x} + \mathbf{B}(-\mathbf{K}\mathbf{x})\] \[\dot{\mathbf{x}} = (\mathbf{A} - \mathbf{B}\mathbf{K})\mathbf{x}\] 놀라운 일이 벌어졌다! 원래 시스템 행렬 $\mathbf{A}$가, 우리의 제어기 $\mathbf{K}$가 포함된 새로운 행렬 $(\mathbf{A} - \mathbf{B}\mathbf{K})$로 바뀌었다. 제어공학에서 고유값(Eigenvalue)을 부르는 다른 이름이 바로 극점(Pole)이다. Pole Placing(극점 배치)란, 우리가 설계할 행렬 $\mathbf{K}$의 값들을 조절하여, 새로운 행렬 $(\mathbf{A} - \mathbf{B}\mathbf{K})$의 Eigenvalue들을 우리가 원하는 위치(음수 방향)로 강제로 이동시키는 기술을 말한다. 6. Eigenvalue 위치에 따른 시뮬레이션 결과 MATLAB과 같은 툴을 이용하면 $\mathbf{K}$를 구하는 것은 place 함수 한 줄이면 끝난다. Eigenvalue(Pole)를 복소평면의 좌반평면(음수)으로 옮기면 시스템은 무조건 안정화(수렴)된다. 하지만 어디로 옮기느냐에 따라 물리적 거동이 완전히 달라진다. 원점에 가까운 음수 (예: -0.1, -0.2): $e^{-0.1t}$처럼 천천히 0으로 수렴한다. 결과: 카트가 목표 지점으로 매우 느릿느릿 이동하며, 진자도 천천히 중심을 잡는다. 부드럽지만 답답하다. p = [-.3; -.4; -.5; -.6]; % just barely good K = place(A, B, p); tspan = 0:.001:10; y0 = [0; 0; 0; 0]; [t, y] = ode45(@(t,y) pendcart(y, m, M, L, g, d, -K*(y-[4;0;0;0])), tspan, y0); end 더 먼 음수 (예: -1.0, -2.0): $e^{-2.0t}$처럼 빠르게 0으로 수렴한다. 결과: 카트가 날렵하고 공격적으로 움직여 목표 지점에 딱 멈춰 선다. 훌륭한 제어 성능을 보인다. p = [-1; -2; -3; -4]; 극단적인 음수 (예: -5.0 이하): 이론적으로는 수렴 속도가 엄청나게 빨라서 극단적으로 큰 크기의 음수일 수록 좋다고 생각할 수 있다. 결과: 실제로는 문제가 생긴다. 행렬 $\mathbf{K}$의 값이 너무 커져서, 초기 오차를 잡기 위해 카트 모터에 비현실적으로 거대한 힘($u$)을 요구하게 된다. 움직임이 너무 거칠어지고(Jerky), 선형화 범위를 벗어나 비선형성 때문에 시스템이 붕괴할 수도 있다. 마무리하며 정리해보면, 제어란 “시스템의 미분방정식을 지배하는 행렬의 Eigenvalue를, 선형대수학의 조작을 통해 원하는 위치(Pole)로 옮겨 심는 작업”이다. 칠판 위에서만 존재하던 미분방정식의 $e^{\lambda t}$ 수식이, 위태로운 진자를 똑바로 세우고 자율주행차를 차선 안에 유지시키는 물리적인 힘으로 치환되는 과정. 이것이 바로 선형대수학과 미분방정식을 배운 우리가 제어 공학에 매력을 느낄 수밖에 없는 이유이다. 하지만 마지막에 보았듯, 무작정 고유값을 멀리 보낸다고 능사는 아니다. “제어 에너지를 적게 쓰면서도 가장 빠르게 안정화되는 최적의 Eigenvalue 위치는 어디일까?” 이 질문에 대한 해답이 바로 다음 포스팅에서 다룰 LQR (Linear Quadratic Regulator) 최적 제어이다. 참고 문헌 [1] Data-Driven Science and Engineering: Machine Learning, Dynamical Systems, and Control, Steven L. Brunton and J. Nathan Kutz (link)[https://databookuw.com/] 본 포스팅은 워싱턴 대학교 Steve Brunton 교수의 ‘Control Bootcamp’ 유튜브 강의를 참고하여 작성되었습니다.]]></summary></entry><entry xml:lang="ko"><title type="html">미분대수방정식(DAE)</title><link href="https://angeloyeo.github.io/2026/03/03/DAE.html" rel="alternate" type="text/html" title="미분대수방정식(DAE)" /><published>2026-03-03T00:00:00+00:00</published><updated>2026-03-03T00:00:00+00:00</updated><id>https://angeloyeo.github.io/2026/03/03/DAE</id><content type="html" xml:base="https://angeloyeo.github.io/2026/03/03/DAE.html"><![CDATA[<h1 id="prerequisites">Prerequisites</h1>

<p>본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다.</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2021/04/30/direction_fields.html">방향장과 오일러 방법</a></li>
  <li><a href="https://angeloyeo.github.io/2021/05/12/phase_plane.html">위상 평면</a></li>
  <li><a href="https://angeloyeo.github.io/2026/03/02/ODE_implicit_solvers.html">ODE 암시적 솔버 (implicit solvers)</a></li>
  <li><a href="https://angeloyeo.github.io/2020/09/30/SVM.html">라그랑주 승수에 대한 이해 (SVM 편의 챕터 2)</a></li>
</ul>

<h1 id="들어가면서">들어가면서</h1>

<p>PSPICE나 Simscape 같은 물리 시뮬레이션 소프트웨어를 사용해본 적이 있는가? 공대생이라면 학부 시절 한번쯤은 써봤을 수도 있는 소프트웨어가 아닐까 한다만, 생긴건 아래와 같이 블록으로 표현되는 소자들을 선으로 연결해주면 물리 시뮬레이션을 수행해주는 기능을 한다. 아래 그림은 Simscape의 예시인데, 왼쪽에 보이는 Mass-Spring-Damper 모델을 가운데에 보이는 모델처럼 표현할 수 있다.</p>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-03-DAE/pic1.png" />
  <br />
  그림 1. Mass-Spring-Damper 문제를 Simscape 모델로 푸는 예시
</p>

<p>이런 물리 모델링/시뮬레이션은 볼수록 신기하다. 그저 블록을 연결할 뿐인데 물리 모델링을 해준다니? Mass-Spring-Damper 모델이야 학부 저학년때도 배우는 단순한 모델이니까 그렇다쳐도, 꽤 복잡한 물리 현상들까지도 척척 풀어주는 걸 보면 이 개발자들은 신(God)인가 싶다.</p>

<p>알아보니 이런 물리 모델링/시뮬레이션 소프트웨어의 뒷면에는 대수방정식(Differential Algebraic Systems of Equation)이라는 수학적 이론이 포함되어 있다고 했다. 몇 년동안 이게 뭔지 이해하지 못하다가 드디어 약간 알것만 같아 휘뚜루마뚜루 정리해본다.</p>

<h1 id="ode-vs-dae">ODE vs. DAE</h1>

<p>비유적으로 설명하면 ODE는 방향장 혹은 위상 평면을 따라 달리는 자유로운 강아지라면, DAE는 제약 사항을 가지고 움직이는 기찻길 위의 기차같은 것이다. (이 비유는 “제약사항”에 주목해야 함.) 즉, DAE가 말하는 것은</p>

<ul>
  <li><strong>D (Differential, 미분): “어떻게 변화하는가?”</strong>
시간에 따른 상태의 변화량($\dot{x}$)을 나타낸다. 가속도, 속도, 전류의 변화 등 시스템의 <strong>동특성(Dynamics)</strong>을 담당한다.</li>
  <li><strong>A (Algebraic, 대수): “어떤 규칙을 따르는가?”</strong>
미분항이 없는 방정식으로, 시스템이 반드시 지켜야 하는 제약 조건(Constraints)이나 보존 법칙을 의미한다. “실의 길이는 일정해야 한다”, “한 노드에서 전류의 합은 0이다” 같은 물리적 약속이다.</li>
</ul>

<p>결국 DAE는 “물리적인 변화(D)를 하되, 정해진 규칙(A)을 반드시 지키며 움직여라”라는 명령을 담은 방정식 체계라고 할 수 있다.</p>

<p>좋은 설명이지만 정확한 이해를 위해 우선 두 방정식의 정의부터 다시 한번 출발해보자. 상미분방정식(Ordinary Differential Equation, ODE)과 대수방정식 (Differential Algebraic Systems of Equations, DAE)의 수학적 정의부터 한번 파헤쳐보자.</p>

<h2 id="ode-상미분-방정식">ODE (상미분 방정식)</h2>

<p>수학적으로 <strong>Explicit(명시적)</strong> 형태를 띈다. $n$차 ODE는 항상 1차 연립 방정식으로 변환 가능하며, 벡터 필드 위에서 상태가 어떻게 변할지 직접 가르쳐준다.</p>

\[\dot{\mathbf{x}}(t) = \mathbf{f}(t, \mathbf{x}(t)) % 식 (1)\]

<ul>
  <li><strong>특징:</strong> 모든 변수의 변화율($\dot{\mathbf{x}}$)이 정의되어 있다.</li>
  <li><strong>기하학적 의미:</strong> 상태 공간의 모든 지점에서 ‘어디로 가야 할지’ 화살표가 그려져 있는 상태이다.</li>
</ul>

<p>이는 <a href="https://angeloyeo.github.io/2021/04/30/direction_fields.html">방향장과 오일러 방법</a> 편이나 <a href="https://angeloyeo.github.io/2021/05/12/phase_plane.html">위상 평면</a> 편에서도 다룬 것 처럼, 미분 방정식을 푼다는 것은 (쉽게 설명하자면) 방향장 혹은 위상 평면 위에 한 점이 있고, 그 점이 미분 계수로 표현되는 주변과의 관계를 통해 다음 점이 어디로 이동할지를 결정하는 것과 같다는 것이다.</p>

<p align="center">
  <img width="300" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2021-05-12-phase_plane/pic4.png" />
  <br />
  그림 2. (2, -1)이라는 점으로부터 시작해 위상평면 상의 기울기를 따라 스텝사이즈 $\Delta t = 0.5$ 만큼씩 이동하여 나타내는 솔루션 (출처: 위상평면 편)
</p>

<h2 id="dae-미분-대수-방정식">DAE (미분 대수 방정식)</h2>

<p>미분 방정식에 <strong>Implicit(암시적)</strong> 제약 조건이 추가된 형태이다. 가장 일반적인 형태는 아래와 같은 형태이다.</p>

\[\dot{\mathbf{x}}= \mathbf{f}(t, \mathbf{x}, \mathbf{z}) \\ \mathbf{0} = \mathbf{g}(t, \mathbf{x}, \mathbf{z}) % 식 (2)\]

<ul>
  <li>특징: $\mathbf{x}$는 미분 변수(Differential variable)이고, $\mathbf{z}$는 대수 변수(Algebraic variable)이다. $\mathbf{z}$는 미분식이 없어서 어떻게 변할지 바로 알 수 없고, 아래의 제약 조건 $\mathbf{g}=0$을 만족하는 값으로 결정되어야 한다.</li>
  <li>기하학적 의미: 상태 공간 전체를 움직이는 게 아니라, $\mathbf{g}(\mathbf{x}, \mathbf{z})=0$이라는 매니폴드(Manifold, 곡면) 위에서만 움직여야 한다.</li>
</ul>

<p>처음보면 좀 당황스러울 수 있지만 차근히 생각해보자. 우선 식 (2)의 첫번째 식 $\dot{\mathbf{x}} = \mathbf{f}(t, \mathbf{x}, \mathbf{z})$은 아무튼간에 변수 $z$가 추가된 미분방정식이라 생각할 수 있다. 그리고 두 번째 식 $\mathbf{0} = \mathbf{g}(t, \mathbf{x}, \mathbf{z})$은 $x$를 미분한 미분계수가 없는 식이라는 것이 핵심이다. 미분계수가 없는 식을 “Algebraic Equation”이라고 부르는 것이고, 이것을 “대수 규칙”이라고 볼 수 있다. 물리적인 제약사항을 표시하기 위해 존재한다.</p>

<p>이런게 왜 필요할까? 예를 들어서 생각해보자.</p>

<h2 id="rc-회로의-ode-풀이와-dae-풀이">RC 회로의 ODE 풀이와 DAE 풀이</h2>

<p>RC 회로를 푸는 것을 보면 ODE와 DAE의 차이를 쉽게 알 수 있다. 뿐만 아니라 왜 DAE가 SPICE 소프트웨어나 Simscape 같은 블록 조합의 모델링에 유용한지도 이해할 수 있다.</p>

<p>여기서는 저항 하나에 캐패시터 하나가 직렬로 나열된 회로를 생각하고자 한다.</p>

<p>ODE는 흔히 사용하는 explicit solver인 <a href="https://www.mathworks.com/help/matlab/ref/ode45.html">ode45</a>를 사용하고 DAE는 제약 조건(미분계수가 없는 식)을 포함하여 <a href="https://www.mathworks.com/help/matlab/ref/ode15s.html">ode15s</a>로 풀어볼 수 있다.</p>

<h3 id="ode-풀이">ODE 풀이</h3>

<p>ODE의 풀이는 구성요소 전체를 아우르는 모델을 수식으로 합치는 과정을 포함한다. 키르히호프 전압 법칙을 써서 $V_{in}=IR+\frac{Q}{C}$를 만들고, $I=\frac{dQ}{dt}$임을 이용하면 하나의 미분방정식으로 모델링할 수 있다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%% --- [Case 1] ODE 방식 (커패시터 전압 Vc 기반) ---
% C * dVc/dt = I = (Vin - Vc) / R
% dVc/dt = (Vin - Vc) / (R*C)
f_ode = @(t, Vc) (Vin - Vc) / (R * C);
[t_ode, V_ode] = ode45(f_ode, tspan, 0); % 초기 전압 0V
</code></pre></div></div>

<h3 id="dae-풀이">DAE 풀이</h3>

<p>DAE는 각 소자들(저항, 캐패시터)의 물리 법칙을 나열하고, 제약사항인 대수 법칙을 작성해준다. 저항의 법칙은 $V=IR$이고 캐패시터는 $I=C\frac{dV_C}{dt}$이다. 두 소자 사이를 연결하는 법칙은 키르히호프의 전압 법칙 $V_{in}-V_R-V_C=0$이다. 즉, SPICE나 Simscape에서 블록을 연결하는 것 처럼 각 소자들의 지배방정식을 나열해주고 전체를 관통하는 대수방정식으로 (domain의) 제약사항을 기술해준다. 대수방정식은 SPICE나 Simscape에서는 물리 모델링 블록들을 선으로 연결하는 행위에 해당한다고 볼 수 있다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>%% --- [Case 2] DAE 방식 (소자 식 나열: 비인과적 모델링) ---
% 상태 변수 Y = [Vr; Vc; I]
% 1. Vr - I*R = 0          (저항의 법칙 - 대수)
% 2. C * Vc' = I           (커패시터의 법칙 - 미분)
% 3. Vin - Vr - Vc = 0     (KVL 연결 법칙 - 대수)

% Mass Matrix: 미분항이 있는 Vc(2번 변수)만 1, 나머지는 0
M = [0 0 0; 
     0 C 0; 
     0 0 0];

f_dae = @(t, Y) [
    Y(1) - Y(3)*R;         % 식 1: Vr = I * R
    Y(3);                  % 식 2: C*Vc' = I (M 행렬에 의해 C가 곱해짐)
    Vin - Y(1) - Y(2)      % 식 3: Vin - Vr - Vc = 0
];

opts = odeset('Mass', M, 'MassSingular', 'yes');
% 초기값: [Vr; Vc; I] = [5; 0; 5/100]
y0 = [Vin; 0; Vin/R];

[t_dae, y_dae] = ode15s(f_dae, tspan, y0, opts);
</code></pre></div></div>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-03-DAE/pic3.png" />
  <br />
  그림 3. RC회로에 대한 ODE 모델링과 DAE 모델링
</p>

<h2 id="진자-운동-pendulum의-ode-풀이와-dae-풀이">진자 운동 (Pendulum)의 ODE 풀이와 DAE 풀이</h2>

<p>위 RC 회로 모델링으로 ODE와 DAE의 모델링 철학을 이해했다면 이번에는 좀 더 어려운 예제를 풀어보고자 한다. 이 예제는 앞선 RC 회로 모델링에 비해서는 좀 더 어려운데, 굳이 가져온 이유는 DAE를 풀 때 필요한 index의 개념과 라그랑즈 승수($\lambda$)에 대해 설명하기 위함이다. 따라서, index나 제약 사항을 기술하는 라그랑주 승수대해 따라올 필요가 없는 경우 과감히 스킵해도 괜찮다.</p>

<h3 id="dae의-index-인덱스-개념에-대해서">DAE의 “Index (인덱스)” 개념에 대해서</h3>

<p>아래의 ODE와 DAE의 예제를 풀 때 인덱스 (Index)의 개념이 필요해 개념 정리를 할 필요가 있다.  Index는 DAE를 ODE로 바꾸기 위해 제약 조건을 몇 번 미분해야 하는지를 나타내는 척도이다. Index가 0인 방정식은 일반 상미분방정식을 나타내고, 대수 방정식을 한 번 미분하면 상미분방정식으로 표현되는 상태를 Index 1, 최소 두 번 미분해야 상미분 방정식으로 나타낼 수 있는 대수 방정식의 index는 2가 되는 것이다.</p>

<h3 id="ode-풀이-1">ODE 풀이</h3>

<p>우선 각도 $\theta$만 이용해서 ODE 방식으로 푸는 경우이다. 상태 변수는 $[\theta, \dot{\theta}]$로 놓고 풀 수 있을 것이다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% --- ODE Solver (ode45) ---
L = 1; g = 9.81;
f_ode = @(t, y) [y(2); -(g/L)*sin(y(1))]; % y(1)=theta, y(2)=dot_theta

[t_ode, y_ode] = ode45(f_ode, [0 5], [pi/4; 0]); % 45도에서 시작
</code></pre></div></div>

<h3 id="dae-풀이-1">DAE 풀이</h3>

<p>이번엔 같은 문제를 DAE로 풀어보자. 제약 조건으로 줄 대수 방정식(algebraic equation)은</p>

\[x^2+y^2=L^2 % 식 (3)\]

<p>으로 줄 수 있다. 이 조건을 풀어서 설명해보자면 진자를 달고 있는 끈이 “강체”(rigid body)이고 그 길이는 항상 $L$이라는 제약조건인 것이다.</p>

<p>그런데, MATLAB에서 ode15s로 DAE를 풀기 위해서는 식(3)과 같은 형태로는 index 3의 수준에서는 바로 풀 수 없고, 제약 조건을 딱 한번만 미분하면 미분방정식 형태로 바꿀 수 있는 수준인 index 1까지 미분해서 제공해야한다. 즉, 위치에 관한 물리적 제약을 가속도 수준까지 풀어서 줘야한다. 그러기 위해선 이 제약 조건을 “장력”의 관점에서 다시 풀어서 생각해볼 필요가 있다. 식 (3)의 물리적 의미에 따라 무슨 일이 있어도 끈의 길이를 “L”로 맞추려면 pendulum이 $(x, y)$ 위치에 있을 때 $(x, y)$ 벡터의 방향에 $\lambda$만큼 비례하는 힘 (장력)을 준다는 것이다.</p>

<p align="center">
  <img width="300" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-03-DAE/pic4.png" />
  <br />
  그림 4. 진자에 작용하는 장력(tension)과 중력(gravity)
</p>

<p>따라서, 장력 벡터 $T$를 이렇게 정의할 수 있다.</p>

\[\vec{t} = (\lambda x, \lambda y) % 식 (4)\]

<p>여기서 $\lambda$는 <a href="https://angeloyeo.github.io/2020/09/30/SVM.html">라그랑주 승수</a> (링크의 챕터 2)이며 시간에 따라 변하는 변수이다. 우리의 솔버 <a href="https://www.mathworks.com/help/matlab/ref/ode15s.html">ode15s</a>는 이 $\lambda$ 변수를 포함해서 문제를 풀어주게 된다.</p>

<p>이제 식 (3)을 미분해가면서 최소 한번만 미분해주면 대수 방정식을 미분방정식으로 만들 수 있게 바꿔보자. (미분이 필요한 최소한의 값을 지표로 index 라고 하며, 이 경우 index를 3을 1로 만드는 것이다.)</p>

<p>우선 식 (3)의 위치 제약 식을 미분하면 아래와 같다.</p>

\[\frac{d}{dt}(x^2+y^2) = \frac{d}{dt}(L^2) % 식 (5)\]

\[\Rightarrow 2x\dot{x}+2y\dot{y}=0 % 식 (6)\]

\[\Rightarrow xu+yu=0 % 식 (7)\]

<p>여기서 $\dot{x}=u, \dot{y}=v$이다. 식 (7)을 한번 더 미분하면,</p>

\[\frac{d}{dt}(xu+yv)=0 % 식 (8)\]

\[\Rightarrow \dot{x}u+x\dot{u}+\dot{y}v+y\dot{v}=0 % 식 (9)\]

\[\Rightarrow u^2+x\dot{u}+v^2+y\dot{v}=0 % 식 (10)\]

<p>그림 4에서 볼 수 있는 장력과 중력의 힘들을 이용해 x 방향에 작용하는 힘과 y 방향으로 작용하는 힘들을 각각 계산해서 $F=ma$ 형태로 묶어보면,</p>

\[\dot{u}=\frac{\lambda x}{m} % 식 (11)\]

\[\dot{v}=\frac{\lambda y-mg}{m} % 식 (12)\]

<p>식 (11), (12)를 식 (10)에 대입하면 아래와 같은 식을 얻을 수 있다.</p>

\[u^2+x\frac{\lambda x}{m}+v^2+y\frac{\lambda y -mg}{m}=0 %식 (13)\]

<p>상태변수는 $[x, y, u, v, \lambda]$ 총 5개이고 여기서 $\lambda$는 제약 조건을 유지하기 위한 힘 혹은 장력에 관한 라그랑주 승수이다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>% --- DAE Solver (ode15s) ---
m = 1; L = 1; g = 9.81;

% Mass Matrix
M = diag([1 1 1 1 0]); 

f_dae = @(t, Y) [
    Y(3);                               % x' = u
    Y(4);                               % y' = v
    Y(5)*Y(1)/m;                        % u' = (lambda * x)/m
    (Y(5)*Y(2) - m*g)/m;                % v' = (lambda * y - mg)/m
    % Index-1 제약 조건: 가속도 수준 (x*u' + y*v' + u^2 + v^2 = 0)
    % 여기에 u'과 v' 자리에 위의 식들을 대입하여 정리한 형태입니다.
    Y(3)^2 + (Y(1)*(Y(5)*Y(1)/m)+ Y(4)^2 + Y(2)*((Y(5)*Y(2) - m*g)/m) )
];

opts = odeset('Mass', M, 'MassSingular', 'yes');
y0 = [sin(pi/4); -cos(pi/4); 0; 0; 0]; 

[t_dae, y_dae] = ode15s(f_dae, [0 5], y0, opts);
</code></pre></div></div>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-03-DAE/pic5.png" />
  <br />
  그림 5. ODE와 DAE의 풀이는 거의 일치하는 것을 알 수 있다.
</p>

<h3 id="numerical-drift">Numerical Drift</h3>

<p>그런데, 그림 5의 진자 운동의 ODE와 DAE의 풀이를 time span을 늘려서 5초까지가 아니라 10초까지로 늘려서 시뮬레이션해보면 ODE와 DAE의 차이가 벌어지는 것을 알 수 있다.</p>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-03-DAE/pic6.png" />
  <br />
  그림 6. 대수방정식의 index를 낮춰 해를 구하면 numerical drift가 발생할 수 있다.
</p>

<p>그림 6에서와 같이 5초 이후로는 계속해서 에러가 누적되는데, 이러한 에러가 발생하는 이유는 대수방정식 제약사항을 index 3에서 index 1로 낮춰 관리했기 때문이다. 즉, 우리가 궁극적으로 보고 싶은 것은 진자가 L이라는 길이의 실 위서 그 길이를 지키며 잘 있는지 궁금했지만 ode15s 솔버가 지키고자 하는 조건은 가속도가 특정 식을 만족하도록 $\lambda$에 적절한 값을 찾는 것이었기 때문이다.</p>

<h1 id="그래서-simscape나-pspice에서는">그래서, Simscape나 PSPICE에서는?</h1>

<p>지금까지 우리는 물리 현상을 모델링 및 시뮬레이션 하기 위해 미분방정식을 세우거나, 대수방정식이 포함된 연립 미분방정식을 풀면서 의미롤 고찰했다. 하지만 실제 산업 현장에서 수천 개의 부품이 얽힌 시스템을 매번 이렇게 수동으로 모델링하는 것은 불가능에 가깝다. 여기서 물리 모델링 소프트웨어의 진가가 드러난다.</p>

<h2 id="1-비인과적-모델링-acausal-modeling의-실현">1. 비인과적 모델링 (Acausal Modeling)의 실현</h2>

<p>우리가 MATLAB 코드를 짤 때 <code class="language-plaintext highlighter-rouge">f_dae</code>에 식을 나열했던 것처럼, PSPICE나 Simscape는 사용자가 블록을 선으로 연결하는 행위 자체를 <strong>대수 방정식($\mathbf{0} = \mathbf{g}$)</strong>의 생성으로 간주한다.</p>

<ul>
  <li>저항 블록을 갖다 놓으면 $V=IR$이 추가된다.</li>
  <li>두 블록을 선으로 이으면 그 지점의 전압이 같다는 제약($V_1 = V_2$)과 전류의 합이 0이라는 제약($\sum I = 0$)이 자동으로 수식 시스템에 편입된다.
이것이 바로 입력과 출력을 미리 정하지 않아도 되는 <strong>비인과적 모델링</strong>의 핵심이다.</li>
</ul>

<p>비인과적 모델링이 중요한 것은 물리현상을 모델링할 때에는 특정 현상이 인과적인 경우가 드물기 때문이다. 예를 들어, 두 기어가 맞물려 돌아가는 것은 하나의 기어가 다른 기어를 움직이는 인과 관계를 가지기 때문인가? 아니면 그 반대로 작동하는 것인가? 기어는 서로 맞물려 돌아가기 때문에 비인과적 관계를 가진다.</p>

<h2 id="2-자동-index-reduction">2. 자동 Index Reduction</h2>

<p>우리가 진자 문제에서 Index 3 식을 Index 1으로 바꾸기 위해 손으로 두 번 미분했던 과정을 기억하는가? Simscape 엔진은 (정확한 작동 원리는 모르지만, 유저 입장에서 봤을 때) 이 과정을 자동으로 수행해준다. 사용자가 어떤 복잡한 구속 조건을 걸더라도, 솔버가 풀 수 있는 최적의 형태로 수식을 알아서 변형(여기선 Reduction) 해준다.</p>

<h2 id="3-수치적-오차의-강건한-보정">3. 수치적 오차의 강건한 보정</h2>

<p>우리가 직접 짠 DAE 코드에서 주기가 미세하게 어긋났던 이유는 가속도 제약만 지키다 보니 위치 제약이 조금씩 풀렸기 때문이다. 구체적으로 공개된 정보는 없지만 Simscape는 이와 같은 오차를 막기 위한 transient initialization이나 transient solving 알고리즘을 이용해 결과를 보정한다 [2]. 덕분에 장시간 시뮬레이션에서도 에너지가 보존되고 물리적 일관성이 유지된다.</p>

<p>좋아. 지금까지의 논의를 종합해서, Simscape 시뮬레이션의 안정성과 솔버의 철학을 다루는 핵심 챕터를 작성해 보았다. 이 내용은 단순한 사용법을 넘어 <strong>“왜 내 모델이 터지는가?”</strong>에 대한 본질적인 답을 제시해 줄 것이다.</p>

<h1 id="시뮬레이션의-사투-stiff-문제와-솔버의-선택">시뮬레이션의 사투: Stiff 문제와 솔버의 선택</h1>

<p>지금까지 DAE와 물리 시뮬레이션 소프트웨어에서의 사용에 대해 약간 알아보았다. 이와 관련하여 예를 들어 Simscape를 사용할 때 자주 발생하는 솔버가 “터져버리는” 문제에 대해서도 잠깐 생각해보자.</p>

<p>Simscape 모델을 돌리다 보면 “솔버가 스텝 사이즈를 줄이다가 멈췄습니다”라거나 “수렴에 실패했습니다”라는 에러를 자주 만난다. 이는 우리가 푸는 물리 모델이 수학적으로 <strong>Stiff</strong>하기 때문에 발생하는 현상이다. (Stiff를 “경직성”이라고도 번역하는 것 같은데 한글 용어가 익숙치 않아서 그냥 Stiff로 쓰겠다.)</p>

<h2 id="stiff-문제-억울하게-천천히-가야-하는-상태">Stiff 문제: “억울하게” 천천히 가야 하는 상태</h2>

<p>Simscape 모델을 돌리다 보면 왜 자꾸 “스텝 사이즈를 줄이다가 멈췄다”는 에러가 날까? 보통 ‘Stiff(경직성) 문제’라고 하면 해가 급격히 변하는 구간을 떠올리기 쉽다. 그런데 <strong>이렇게 생각해보자.</strong> 해가 급격히 변할 때 스텝을 줄이는 건 너무나 당연한 일이다. 변화가 빠르니까 세밀하게 관찰해야 하기 때문이다. 그걸 ‘경직되었다’고 표현하는 건 좀 이상하지 않은가?</p>

<p>실제로 <a href="https://kr.mathworks.com/help/matlab/ref/ode15s.htm">MathWorks의 ode15s 솔버의 문서</a>를 뒤져보고 나서야 무릎을 탁 쳤다. 진짜 Stiff의 본질은 <strong>“해는 전반적으로 완만하게 변하고 있는데, 시스템 내부에 숨어 있는 민감한 성분 때문에 억지로 기어가야 하는 상태”</strong>를 말하는 것이었다. 다시 말해 Stiff하다는 건, 시스템의 ‘가장 빠른 성분’에 발목이 잡힌 상태다.</p>

<ul>
  <li><strong>사고의 전환:</strong> 겉으로는 평온해 보이는 평지인데, 사실 발밑에 아주 예민한 지뢰(빠른 고유값)가 깔려 있는 상황이다. <code class="language-plaintext highlighter-rouge">ode45</code> 같은 일반적인 <strong>Explicit(명시적)</strong> 솔버는 이 지뢰를 밟지 않으려고 아주 조심조심(작은 스텝) 이동하다가 결국 지쳐서 포기해버린다. 아니면 잠깐 방심해서 스텝을 크게 딛는 순간, 지뢰가 터지면서 시스템의 에너지가 무한대로 발산하며 시뮬레이션이 ‘폭발’해버리기도 한다.</li>
  <li><strong>Simscape는 왜 더 심할까?</strong> 우리가 앞에서 다룬 식 (2)의 대수 방정식($g=0$) 성분 때문이다. “그 즉시” 평형을 맞춰야 한다는 제약은 물리적으로 변화 속도가 ‘무한대’인 성분과 같다. 이 녀석들이 시스템 도처에 지뢰를 깔아놓으니, Simscape 모델은 태생적으로 Stiff할 수밖에 없다.</li>
</ul>

<p>그래서 우리는 <code class="language-plaintext highlighter-rouge">ode15s</code> 같은 <strong>Implicit 솔버</strong>를 써야 한다. 이런 종류의 솔버는 단순히 현재 기울기로 앞을 예측하는 게 아니라, <strong>미래의 지점이 평형을 이루는지 미리 방정식을 풀어서 확인</strong>하고 이동한다. 덕분에 발밑에 지뢰가 깔려 있어도 수치적으로 폭발하지 않고 안정적으로 큰 걸음을 내디딜 수 있는 것이다.</p>

<h2 id="수렴-실패-네-모델은-물리적으로-말이-안-돼">수렴 실패: “네 모델은 물리적으로 말이 안 돼!”</h2>

<p>자, 이제 솔버까지 잘 골랐는데 이번엔 “수렴 실패(Convergence Error)”라는 메시지가 우리를 괴롭힌다. 이건 또 왜 그럴까? Implicit 솔버가 다음 지점을 찾는 방식은 일종의 ‘정답 맞히기 게임’이다. 이때 사용하는 도구가 바로 <strong>Newton-Raphson(NR) 반복법</strong>이다.</p>

<p>솔버는 스스로에게 이런 질문을 던진다.
<em>“이 지점에서 전류의 합이 0인가? 알짜힘은 0인가?”</em> 이 질문에 대한 오차를 <strong>잔차(Residual)</strong>라고 부르는데, 이 잔차가 0이 될 때까지 계속해서 계산을 반복한다. 즉, <strong>물리 법칙을 완벽히 만족하는 평형 상태</strong>를 찾아가는 과정이다.</p>

<p>그런데 여기서 시뮬레이션이 터지는 진짜 이유가 나온다.</p>

<ul>
  <li><strong>물리적 불연속성과 에너지 점프:</strong> 만약 내가 모델을 설계할 때, 물체가 딱딱한 벽을 순식간에 뚫고 지나가야 하거나 에너지가 찰나의 순간에 점프해야 하도록 만들었다면? 혹은 인덕터 두 개를 직렬로 연결해서 전류가 부딪히게 만들었다면 어떻게 될까?</li>
  <li><strong>솔버의 절규:</strong> 솔버는 NR 반복을 수천 번 돌려도 잔차를 0으로 만드는 해를 찾을 수 없다. 물리적으로 그런 상태는 존재할 수 없기 때문이다! 잔차가 줄어들지 않고 요동치거나 엉뚱한 곳으로 튀어버린다.</li>
</ul>

<p>결국 수렴 실패라는 건, 솔버가 나에게 보내는 마지막 경고이다. <strong>“아무리 계산해봐도 네가 만든 상황은 물리 법칙상 해가 존재할 수 없어!”</strong>라고 말이다. 결국 에러를 고치는 건 솔버 옵션을 만지는 게 아니라, 내 모델의 물리적 개연성에 문제가 있지는 않은지, 에너지 흐름이 너무 급격하게 변하는 구간은 없는지 다시 검토하는 것에서 시작해야 한다는 것을 깨달았다.</p>

<h2 id="dae는-안-풀리는-문제가-있는데-ode로는-풀릴까요">“DAE는 안 풀리는 문제가 있는데, ODE로는 풀릴까요?”</h2>

<p>한 구독자분께서 아주 날카로운 질문을 던져주셨다.</p>

<blockquote>
  <p><em>“DAE 솔버가 물리 법칙을 만족하지 못해서 해를 못 찾는다면… 수식을 잘 정리해서 ODE로 만들면 돌아갈까요? DAE로는 안 풀리는 문제가 ODE로는 풀릴 수 있나요?”</em></p>
</blockquote>

<p>이 질문을 듣고 나도 잠시 멈춰서 생각에 빠졌다. <strong>“돌아가는 것”과 “정답인 것”의 차이</strong>를 고민해 볼 수 있는 아주 본질적인 질문이기 때문이다. 꼭 이 답변이 정답은 아닐 수 있겠지만 내 사고의 과정을 따라 답을 적어본다.</p>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-03-DAE/pic7.png" />
  <br />
  그림 7. 철저한 원칙주의로 물리적 모순에 멈춰서는 DAE와, 수치적 오차를 감수하며 유연하게 해를 찾아가는 ODE의 대비 (Google 나노바나나 이용하여 그림 제작함.)
</p>

<h3 id="1-dae-솔버의-결벽증">1) DAE 솔버의 ‘결벽증’</h3>

<p>우선 Simscape 같은 DAE 솔버의 성격을 이해해야 한다. 앞에서 말했듯 얘네는 Newton-Raphson 반복을 통해 제약 조건을 엄격하게 체크한다.</p>

<p><strong>이렇게 생각해보자.</strong> DAE 솔버는 <strong>“기찻길 위를 달리는 기차”</strong>다. 철로가 0.1mm라도 어긋나 있으면 기차는 탈선할 위험을 감수하지 않고 그 자리에 즉시 멈춰버린다.
<em>“전류의 합이 0이 아니잖아? 난 이대로는 단 한 발자국도 못 가!”</em> 이런 결벽증 때문에 물리적으로 아주 미세하게 모순되는 지점(불연속적인 에너지 점프 등)만 만나도 솔버는 “수렴 실패”를 선언하고 파업에 들어간다.</p>

<h3 id="2-ode-솔버의-무던함">2) ODE 솔버의 ‘무던함’</h3>

<p>반면, 수식을 열심히 정리해서 ODE 형태로 만들면 상황이 묘하게 달라진다. <strong>ODE는 제약 조건을 이미 수식 안에 녹여버렸기 때문에</strong>, 솔버 입장에서는 실시간으로 감시해야 할 ‘대수 방정식’이라는 감옥이 사라진 셈이다.</p>

<p>ODE 솔버는 앞서 비유한 것 처럼 <strong>“지도를 들고 초원을 달리는 강아지”</strong>와 같다. 강아지는 지도가 좀 잘못 그려져 있어도, 혹은 앞에 작은 웅덩이가 있어도 일단 앞발을 내디딘다. 수치적 오차가 발생하더라도 미분 계수라는 ‘경향성’을 따라 적분하며 다음 지점으로 어떻게든 넘어간다.</p>

<h3 id="3-돌아는-가는데-그게-진짜일까">3) 돌아는 가는데, 그게 ‘진짜’일까?</h3>

<p>그래서 질문에 대한 답을 내리자면 이렇다. <strong>“ODE로 바꾸면 돌아갈 수는 있다. 하지만 그 결과가 물리적으로 맞다는 보장은 없다.”</strong></p>

<p>DAE 솔버가 멈췄던 지점에서 ODE 솔버는 수치적 오차를 내며 억지로 뚫고 지나갈 것이다. 시뮬레이션은 끝까지 완료되겠지만, 데이터를 뜯어보면 에너지가 보존되지 않거나 물리 법칙을 무시하고 값이 튀어버린 ‘가짜 결과’일 가능성이 높다.</p>

<h3 id="4-결론-dae의-멈춤은-경고다">4) 결론: DAE의 멈춤은 ‘경고’다</h3>

<p>결국 <strong>“DAE로는 안 풀리는데 ODE로는 풀리는 상황”</strong>은 솔버의 성능 차이가 아니라, <strong>솔버가 물리 법칙을 대하는 태도의 차이</strong>에서 온다.</p>

<p>DAE 솔버가 까다롭게 구는 이유는 우리가 만든 가상 세계가 현실의 물리 법칙을 완벽히 대변하게 만들기 위해서다. 만약 DAE가 해를 찾지 못하고 멈췄다면, ODE로 우회할 수도 있겠지만 <strong>“내 모델의 물리적 구조 어디에 모순이 숨어 있는가”</strong>를 들여다볼 필요도 있다.</p>

<h1 id="마치며">마치며</h1>

<p>대수방정식에 대해서 오랫동안 궁금했는데, 이번 포스팅을 계기로 약간의 궁금증이 해소되었다. 물리 모델링을 수행할 때 블록을 불러들이는 것과 블록들을 선으로 연결하는 행위의 뒷면에는 이처럼 놀라운 계산들이 숨어있었다는게 알아보면서도 놀라울 따름이다. 물리 모델링의 백스테이지에 대해 궁금했던 나같은 사람들에게 도움이 되었으면 좋겠다.</p>

<h1 id="참고-문헌">참고 문헌</h1>

<ul>
  <li>[1] <a href="https://www.mathworks.com/help/matlab/math/solve-differential-algebraic-equations-daes.html">Solve Differential Algebraic Equations (DAEs)</a></li>
  <li>[2] <a href="https://www.mathworks.com/help/simscape/ug/how-simscape-simulation-works.html">How Simscape Simulation Works</a></li>
  <li>[3] <a href="https://kr.mathworks.com/help/matlab/ref/ode15s.html?s_tid=srchtitle_support_results_1_ode15s#bu4aoye">ode15s - 경직성(stiff) ODE 풀기 예제</a></li>
</ul>]]></content><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><category term="미분방정식" /><category term="선형대수학" /><summary type="html"><![CDATA[Prerequisites 본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다. 방향장과 오일러 방법 위상 평면 ODE 암시적 솔버 (implicit solvers) 라그랑주 승수에 대한 이해 (SVM 편의 챕터 2) 들어가면서 PSPICE나 Simscape 같은 물리 시뮬레이션 소프트웨어를 사용해본 적이 있는가? 공대생이라면 학부 시절 한번쯤은 써봤을 수도 있는 소프트웨어가 아닐까 한다만, 생긴건 아래와 같이 블록으로 표현되는 소자들을 선으로 연결해주면 물리 시뮬레이션을 수행해주는 기능을 한다. 아래 그림은 Simscape의 예시인데, 왼쪽에 보이는 Mass-Spring-Damper 모델을 가운데에 보이는 모델처럼 표현할 수 있다. 그림 1. Mass-Spring-Damper 문제를 Simscape 모델로 푸는 예시 이런 물리 모델링/시뮬레이션은 볼수록 신기하다. 그저 블록을 연결할 뿐인데 물리 모델링을 해준다니? Mass-Spring-Damper 모델이야 학부 저학년때도 배우는 단순한 모델이니까 그렇다쳐도, 꽤 복잡한 물리 현상들까지도 척척 풀어주는 걸 보면 이 개발자들은 신(God)인가 싶다. 알아보니 이런 물리 모델링/시뮬레이션 소프트웨어의 뒷면에는 대수방정식(Differential Algebraic Systems of Equation)이라는 수학적 이론이 포함되어 있다고 했다. 몇 년동안 이게 뭔지 이해하지 못하다가 드디어 약간 알것만 같아 휘뚜루마뚜루 정리해본다. ODE vs. DAE 비유적으로 설명하면 ODE는 방향장 혹은 위상 평면을 따라 달리는 자유로운 강아지라면, DAE는 제약 사항을 가지고 움직이는 기찻길 위의 기차같은 것이다. (이 비유는 “제약사항”에 주목해야 함.) 즉, DAE가 말하는 것은 D (Differential, 미분): “어떻게 변화하는가?” 시간에 따른 상태의 변화량($\dot{x}$)을 나타낸다. 가속도, 속도, 전류의 변화 등 시스템의 동특성(Dynamics)을 담당한다. A (Algebraic, 대수): “어떤 규칙을 따르는가?” 미분항이 없는 방정식으로, 시스템이 반드시 지켜야 하는 제약 조건(Constraints)이나 보존 법칙을 의미한다. “실의 길이는 일정해야 한다”, “한 노드에서 전류의 합은 0이다” 같은 물리적 약속이다. 결국 DAE는 “물리적인 변화(D)를 하되, 정해진 규칙(A)을 반드시 지키며 움직여라”라는 명령을 담은 방정식 체계라고 할 수 있다. 좋은 설명이지만 정확한 이해를 위해 우선 두 방정식의 정의부터 다시 한번 출발해보자. 상미분방정식(Ordinary Differential Equation, ODE)과 대수방정식 (Differential Algebraic Systems of Equations, DAE)의 수학적 정의부터 한번 파헤쳐보자. ODE (상미분 방정식) 수학적으로 Explicit(명시적) 형태를 띈다. $n$차 ODE는 항상 1차 연립 방정식으로 변환 가능하며, 벡터 필드 위에서 상태가 어떻게 변할지 직접 가르쳐준다. \[\dot{\mathbf{x}}(t) = \mathbf{f}(t, \mathbf{x}(t)) % 식 (1)\] 특징: 모든 변수의 변화율($\dot{\mathbf{x}}$)이 정의되어 있다. 기하학적 의미: 상태 공간의 모든 지점에서 ‘어디로 가야 할지’ 화살표가 그려져 있는 상태이다. 이는 방향장과 오일러 방법 편이나 위상 평면 편에서도 다룬 것 처럼, 미분 방정식을 푼다는 것은 (쉽게 설명하자면) 방향장 혹은 위상 평면 위에 한 점이 있고, 그 점이 미분 계수로 표현되는 주변과의 관계를 통해 다음 점이 어디로 이동할지를 결정하는 것과 같다는 것이다. 그림 2. (2, -1)이라는 점으로부터 시작해 위상평면 상의 기울기를 따라 스텝사이즈 $\Delta t = 0.5$ 만큼씩 이동하여 나타내는 솔루션 (출처: 위상평면 편) DAE (미분 대수 방정식) 미분 방정식에 Implicit(암시적) 제약 조건이 추가된 형태이다. 가장 일반적인 형태는 아래와 같은 형태이다. \[\dot{\mathbf{x}}= \mathbf{f}(t, \mathbf{x}, \mathbf{z}) \\ \mathbf{0} = \mathbf{g}(t, \mathbf{x}, \mathbf{z}) % 식 (2)\] 특징: $\mathbf{x}$는 미분 변수(Differential variable)이고, $\mathbf{z}$는 대수 변수(Algebraic variable)이다. $\mathbf{z}$는 미분식이 없어서 어떻게 변할지 바로 알 수 없고, 아래의 제약 조건 $\mathbf{g}=0$을 만족하는 값으로 결정되어야 한다. 기하학적 의미: 상태 공간 전체를 움직이는 게 아니라, $\mathbf{g}(\mathbf{x}, \mathbf{z})=0$이라는 매니폴드(Manifold, 곡면) 위에서만 움직여야 한다. 처음보면 좀 당황스러울 수 있지만 차근히 생각해보자. 우선 식 (2)의 첫번째 식 $\dot{\mathbf{x}} = \mathbf{f}(t, \mathbf{x}, \mathbf{z})$은 아무튼간에 변수 $z$가 추가된 미분방정식이라 생각할 수 있다. 그리고 두 번째 식 $\mathbf{0} = \mathbf{g}(t, \mathbf{x}, \mathbf{z})$은 $x$를 미분한 미분계수가 없는 식이라는 것이 핵심이다. 미분계수가 없는 식을 “Algebraic Equation”이라고 부르는 것이고, 이것을 “대수 규칙”이라고 볼 수 있다. 물리적인 제약사항을 표시하기 위해 존재한다. 이런게 왜 필요할까? 예를 들어서 생각해보자. RC 회로의 ODE 풀이와 DAE 풀이 RC 회로를 푸는 것을 보면 ODE와 DAE의 차이를 쉽게 알 수 있다. 뿐만 아니라 왜 DAE가 SPICE 소프트웨어나 Simscape 같은 블록 조합의 모델링에 유용한지도 이해할 수 있다. 여기서는 저항 하나에 캐패시터 하나가 직렬로 나열된 회로를 생각하고자 한다. ODE는 흔히 사용하는 explicit solver인 ode45를 사용하고 DAE는 제약 조건(미분계수가 없는 식)을 포함하여 ode15s로 풀어볼 수 있다. ODE 풀이 ODE의 풀이는 구성요소 전체를 아우르는 모델을 수식으로 합치는 과정을 포함한다. 키르히호프 전압 법칙을 써서 $V_{in}=IR+\frac{Q}{C}$를 만들고, $I=\frac{dQ}{dt}$임을 이용하면 하나의 미분방정식으로 모델링할 수 있다. %% --- [Case 1] ODE 방식 (커패시터 전압 Vc 기반) --- % C * dVc/dt = I = (Vin - Vc) / R % dVc/dt = (Vin - Vc) / (R*C) f_ode = @(t, Vc) (Vin - Vc) / (R * C); [t_ode, V_ode] = ode45(f_ode, tspan, 0); % 초기 전압 0V DAE 풀이 DAE는 각 소자들(저항, 캐패시터)의 물리 법칙을 나열하고, 제약사항인 대수 법칙을 작성해준다. 저항의 법칙은 $V=IR$이고 캐패시터는 $I=C\frac{dV_C}{dt}$이다. 두 소자 사이를 연결하는 법칙은 키르히호프의 전압 법칙 $V_{in}-V_R-V_C=0$이다. 즉, SPICE나 Simscape에서 블록을 연결하는 것 처럼 각 소자들의 지배방정식을 나열해주고 전체를 관통하는 대수방정식으로 (domain의) 제약사항을 기술해준다. 대수방정식은 SPICE나 Simscape에서는 물리 모델링 블록들을 선으로 연결하는 행위에 해당한다고 볼 수 있다. %% --- [Case 2] DAE 방식 (소자 식 나열: 비인과적 모델링) --- % 상태 변수 Y = [Vr; Vc; I] % 1. Vr - I*R = 0 (저항의 법칙 - 대수) % 2. C * Vc' = I (커패시터의 법칙 - 미분) % 3. Vin - Vr - Vc = 0 (KVL 연결 법칙 - 대수) % Mass Matrix: 미분항이 있는 Vc(2번 변수)만 1, 나머지는 0 M = [0 0 0; 0 C 0; 0 0 0]; f_dae = @(t, Y) [ Y(1) - Y(3)*R; % 식 1: Vr = I * R Y(3); % 식 2: C*Vc' = I (M 행렬에 의해 C가 곱해짐) Vin - Y(1) - Y(2) % 식 3: Vin - Vr - Vc = 0 ]; opts = odeset('Mass', M, 'MassSingular', 'yes'); % 초기값: [Vr; Vc; I] = [5; 0; 5/100] y0 = [Vin; 0; Vin/R]; [t_dae, y_dae] = ode15s(f_dae, tspan, y0, opts); 그림 3. RC회로에 대한 ODE 모델링과 DAE 모델링 진자 운동 (Pendulum)의 ODE 풀이와 DAE 풀이 위 RC 회로 모델링으로 ODE와 DAE의 모델링 철학을 이해했다면 이번에는 좀 더 어려운 예제를 풀어보고자 한다. 이 예제는 앞선 RC 회로 모델링에 비해서는 좀 더 어려운데, 굳이 가져온 이유는 DAE를 풀 때 필요한 index의 개념과 라그랑즈 승수($\lambda$)에 대해 설명하기 위함이다. 따라서, index나 제약 사항을 기술하는 라그랑주 승수대해 따라올 필요가 없는 경우 과감히 스킵해도 괜찮다. DAE의 “Index (인덱스)” 개념에 대해서 아래의 ODE와 DAE의 예제를 풀 때 인덱스 (Index)의 개념이 필요해 개념 정리를 할 필요가 있다. Index는 DAE를 ODE로 바꾸기 위해 제약 조건을 몇 번 미분해야 하는지를 나타내는 척도이다. Index가 0인 방정식은 일반 상미분방정식을 나타내고, 대수 방정식을 한 번 미분하면 상미분방정식으로 표현되는 상태를 Index 1, 최소 두 번 미분해야 상미분 방정식으로 나타낼 수 있는 대수 방정식의 index는 2가 되는 것이다. ODE 풀이 우선 각도 $\theta$만 이용해서 ODE 방식으로 푸는 경우이다. 상태 변수는 $[\theta, \dot{\theta}]$로 놓고 풀 수 있을 것이다. % --- ODE Solver (ode45) --- L = 1; g = 9.81; f_ode = @(t, y) [y(2); -(g/L)*sin(y(1))]; % y(1)=theta, y(2)=dot_theta [t_ode, y_ode] = ode45(f_ode, [0 5], [pi/4; 0]); % 45도에서 시작 DAE 풀이 이번엔 같은 문제를 DAE로 풀어보자. 제약 조건으로 줄 대수 방정식(algebraic equation)은 \[x^2+y^2=L^2 % 식 (3)\] 으로 줄 수 있다. 이 조건을 풀어서 설명해보자면 진자를 달고 있는 끈이 “강체”(rigid body)이고 그 길이는 항상 $L$이라는 제약조건인 것이다. 그런데, MATLAB에서 ode15s로 DAE를 풀기 위해서는 식(3)과 같은 형태로는 index 3의 수준에서는 바로 풀 수 없고, 제약 조건을 딱 한번만 미분하면 미분방정식 형태로 바꿀 수 있는 수준인 index 1까지 미분해서 제공해야한다. 즉, 위치에 관한 물리적 제약을 가속도 수준까지 풀어서 줘야한다. 그러기 위해선 이 제약 조건을 “장력”의 관점에서 다시 풀어서 생각해볼 필요가 있다. 식 (3)의 물리적 의미에 따라 무슨 일이 있어도 끈의 길이를 “L”로 맞추려면 pendulum이 $(x, y)$ 위치에 있을 때 $(x, y)$ 벡터의 방향에 $\lambda$만큼 비례하는 힘 (장력)을 준다는 것이다. 그림 4. 진자에 작용하는 장력(tension)과 중력(gravity) 따라서, 장력 벡터 $T$를 이렇게 정의할 수 있다. \[\vec{t} = (\lambda x, \lambda y) % 식 (4)\] 여기서 $\lambda$는 라그랑주 승수 (링크의 챕터 2)이며 시간에 따라 변하는 변수이다. 우리의 솔버 ode15s는 이 $\lambda$ 변수를 포함해서 문제를 풀어주게 된다. 이제 식 (3)을 미분해가면서 최소 한번만 미분해주면 대수 방정식을 미분방정식으로 만들 수 있게 바꿔보자. (미분이 필요한 최소한의 값을 지표로 index 라고 하며, 이 경우 index를 3을 1로 만드는 것이다.) 우선 식 (3)의 위치 제약 식을 미분하면 아래와 같다. \[\frac{d}{dt}(x^2+y^2) = \frac{d}{dt}(L^2) % 식 (5)\] \[\Rightarrow 2x\dot{x}+2y\dot{y}=0 % 식 (6)\] \[\Rightarrow xu+yu=0 % 식 (7)\] 여기서 $\dot{x}=u, \dot{y}=v$이다. 식 (7)을 한번 더 미분하면, \[\frac{d}{dt}(xu+yv)=0 % 식 (8)\] \[\Rightarrow \dot{x}u+x\dot{u}+\dot{y}v+y\dot{v}=0 % 식 (9)\] \[\Rightarrow u^2+x\dot{u}+v^2+y\dot{v}=0 % 식 (10)\] 그림 4에서 볼 수 있는 장력과 중력의 힘들을 이용해 x 방향에 작용하는 힘과 y 방향으로 작용하는 힘들을 각각 계산해서 $F=ma$ 형태로 묶어보면, \[\dot{u}=\frac{\lambda x}{m} % 식 (11)\] \[\dot{v}=\frac{\lambda y-mg}{m} % 식 (12)\] 식 (11), (12)를 식 (10)에 대입하면 아래와 같은 식을 얻을 수 있다. \[u^2+x\frac{\lambda x}{m}+v^2+y\frac{\lambda y -mg}{m}=0 %식 (13)\] 상태변수는 $[x, y, u, v, \lambda]$ 총 5개이고 여기서 $\lambda$는 제약 조건을 유지하기 위한 힘 혹은 장력에 관한 라그랑주 승수이다. % --- DAE Solver (ode15s) --- m = 1; L = 1; g = 9.81; % Mass Matrix M = diag([1 1 1 1 0]); f_dae = @(t, Y) [ Y(3); % x' = u Y(4); % y' = v Y(5)*Y(1)/m; % u' = (lambda * x)/m (Y(5)*Y(2) - m*g)/m; % v' = (lambda * y - mg)/m % Index-1 제약 조건: 가속도 수준 (x*u' + y*v' + u^2 + v^2 = 0) % 여기에 u'과 v' 자리에 위의 식들을 대입하여 정리한 형태입니다. Y(3)^2 + (Y(1)*(Y(5)*Y(1)/m)+ Y(4)^2 + Y(2)*((Y(5)*Y(2) - m*g)/m) ) ]; opts = odeset('Mass', M, 'MassSingular', 'yes'); y0 = [sin(pi/4); -cos(pi/4); 0; 0; 0]; [t_dae, y_dae] = ode15s(f_dae, [0 5], y0, opts); 그림 5. ODE와 DAE의 풀이는 거의 일치하는 것을 알 수 있다. Numerical Drift 그런데, 그림 5의 진자 운동의 ODE와 DAE의 풀이를 time span을 늘려서 5초까지가 아니라 10초까지로 늘려서 시뮬레이션해보면 ODE와 DAE의 차이가 벌어지는 것을 알 수 있다. 그림 6. 대수방정식의 index를 낮춰 해를 구하면 numerical drift가 발생할 수 있다. 그림 6에서와 같이 5초 이후로는 계속해서 에러가 누적되는데, 이러한 에러가 발생하는 이유는 대수방정식 제약사항을 index 3에서 index 1로 낮춰 관리했기 때문이다. 즉, 우리가 궁극적으로 보고 싶은 것은 진자가 L이라는 길이의 실 위서 그 길이를 지키며 잘 있는지 궁금했지만 ode15s 솔버가 지키고자 하는 조건은 가속도가 특정 식을 만족하도록 $\lambda$에 적절한 값을 찾는 것이었기 때문이다. 그래서, Simscape나 PSPICE에서는? 지금까지 우리는 물리 현상을 모델링 및 시뮬레이션 하기 위해 미분방정식을 세우거나, 대수방정식이 포함된 연립 미분방정식을 풀면서 의미롤 고찰했다. 하지만 실제 산업 현장에서 수천 개의 부품이 얽힌 시스템을 매번 이렇게 수동으로 모델링하는 것은 불가능에 가깝다. 여기서 물리 모델링 소프트웨어의 진가가 드러난다. 1. 비인과적 모델링 (Acausal Modeling)의 실현 우리가 MATLAB 코드를 짤 때 f_dae에 식을 나열했던 것처럼, PSPICE나 Simscape는 사용자가 블록을 선으로 연결하는 행위 자체를 대수 방정식($\mathbf{0} = \mathbf{g}$)의 생성으로 간주한다. 저항 블록을 갖다 놓으면 $V=IR$이 추가된다. 두 블록을 선으로 이으면 그 지점의 전압이 같다는 제약($V_1 = V_2$)과 전류의 합이 0이라는 제약($\sum I = 0$)이 자동으로 수식 시스템에 편입된다. 이것이 바로 입력과 출력을 미리 정하지 않아도 되는 비인과적 모델링의 핵심이다. 비인과적 모델링이 중요한 것은 물리현상을 모델링할 때에는 특정 현상이 인과적인 경우가 드물기 때문이다. 예를 들어, 두 기어가 맞물려 돌아가는 것은 하나의 기어가 다른 기어를 움직이는 인과 관계를 가지기 때문인가? 아니면 그 반대로 작동하는 것인가? 기어는 서로 맞물려 돌아가기 때문에 비인과적 관계를 가진다. 2. 자동 Index Reduction 우리가 진자 문제에서 Index 3 식을 Index 1으로 바꾸기 위해 손으로 두 번 미분했던 과정을 기억하는가? Simscape 엔진은 (정확한 작동 원리는 모르지만, 유저 입장에서 봤을 때) 이 과정을 자동으로 수행해준다. 사용자가 어떤 복잡한 구속 조건을 걸더라도, 솔버가 풀 수 있는 최적의 형태로 수식을 알아서 변형(여기선 Reduction) 해준다. 3. 수치적 오차의 강건한 보정 우리가 직접 짠 DAE 코드에서 주기가 미세하게 어긋났던 이유는 가속도 제약만 지키다 보니 위치 제약이 조금씩 풀렸기 때문이다. 구체적으로 공개된 정보는 없지만 Simscape는 이와 같은 오차를 막기 위한 transient initialization이나 transient solving 알고리즘을 이용해 결과를 보정한다 [2]. 덕분에 장시간 시뮬레이션에서도 에너지가 보존되고 물리적 일관성이 유지된다. 좋아. 지금까지의 논의를 종합해서, Simscape 시뮬레이션의 안정성과 솔버의 철학을 다루는 핵심 챕터를 작성해 보았다. 이 내용은 단순한 사용법을 넘어 “왜 내 모델이 터지는가?”에 대한 본질적인 답을 제시해 줄 것이다. 시뮬레이션의 사투: Stiff 문제와 솔버의 선택 지금까지 DAE와 물리 시뮬레이션 소프트웨어에서의 사용에 대해 약간 알아보았다. 이와 관련하여 예를 들어 Simscape를 사용할 때 자주 발생하는 솔버가 “터져버리는” 문제에 대해서도 잠깐 생각해보자. Simscape 모델을 돌리다 보면 “솔버가 스텝 사이즈를 줄이다가 멈췄습니다”라거나 “수렴에 실패했습니다”라는 에러를 자주 만난다. 이는 우리가 푸는 물리 모델이 수학적으로 Stiff하기 때문에 발생하는 현상이다. (Stiff를 “경직성”이라고도 번역하는 것 같은데 한글 용어가 익숙치 않아서 그냥 Stiff로 쓰겠다.) Stiff 문제: “억울하게” 천천히 가야 하는 상태 Simscape 모델을 돌리다 보면 왜 자꾸 “스텝 사이즈를 줄이다가 멈췄다”는 에러가 날까? 보통 ‘Stiff(경직성) 문제’라고 하면 해가 급격히 변하는 구간을 떠올리기 쉽다. 그런데 이렇게 생각해보자. 해가 급격히 변할 때 스텝을 줄이는 건 너무나 당연한 일이다. 변화가 빠르니까 세밀하게 관찰해야 하기 때문이다. 그걸 ‘경직되었다’고 표현하는 건 좀 이상하지 않은가? 실제로 MathWorks의 ode15s 솔버의 문서를 뒤져보고 나서야 무릎을 탁 쳤다. 진짜 Stiff의 본질은 “해는 전반적으로 완만하게 변하고 있는데, 시스템 내부에 숨어 있는 민감한 성분 때문에 억지로 기어가야 하는 상태”를 말하는 것이었다. 다시 말해 Stiff하다는 건, 시스템의 ‘가장 빠른 성분’에 발목이 잡힌 상태다. 사고의 전환: 겉으로는 평온해 보이는 평지인데, 사실 발밑에 아주 예민한 지뢰(빠른 고유값)가 깔려 있는 상황이다. ode45 같은 일반적인 Explicit(명시적) 솔버는 이 지뢰를 밟지 않으려고 아주 조심조심(작은 스텝) 이동하다가 결국 지쳐서 포기해버린다. 아니면 잠깐 방심해서 스텝을 크게 딛는 순간, 지뢰가 터지면서 시스템의 에너지가 무한대로 발산하며 시뮬레이션이 ‘폭발’해버리기도 한다. Simscape는 왜 더 심할까? 우리가 앞에서 다룬 식 (2)의 대수 방정식($g=0$) 성분 때문이다. “그 즉시” 평형을 맞춰야 한다는 제약은 물리적으로 변화 속도가 ‘무한대’인 성분과 같다. 이 녀석들이 시스템 도처에 지뢰를 깔아놓으니, Simscape 모델은 태생적으로 Stiff할 수밖에 없다. 그래서 우리는 ode15s 같은 Implicit 솔버를 써야 한다. 이런 종류의 솔버는 단순히 현재 기울기로 앞을 예측하는 게 아니라, 미래의 지점이 평형을 이루는지 미리 방정식을 풀어서 확인하고 이동한다. 덕분에 발밑에 지뢰가 깔려 있어도 수치적으로 폭발하지 않고 안정적으로 큰 걸음을 내디딜 수 있는 것이다. 수렴 실패: “네 모델은 물리적으로 말이 안 돼!” 자, 이제 솔버까지 잘 골랐는데 이번엔 “수렴 실패(Convergence Error)”라는 메시지가 우리를 괴롭힌다. 이건 또 왜 그럴까? Implicit 솔버가 다음 지점을 찾는 방식은 일종의 ‘정답 맞히기 게임’이다. 이때 사용하는 도구가 바로 Newton-Raphson(NR) 반복법이다. 솔버는 스스로에게 이런 질문을 던진다. “이 지점에서 전류의 합이 0인가? 알짜힘은 0인가?” 이 질문에 대한 오차를 잔차(Residual)라고 부르는데, 이 잔차가 0이 될 때까지 계속해서 계산을 반복한다. 즉, 물리 법칙을 완벽히 만족하는 평형 상태를 찾아가는 과정이다. 그런데 여기서 시뮬레이션이 터지는 진짜 이유가 나온다. 물리적 불연속성과 에너지 점프: 만약 내가 모델을 설계할 때, 물체가 딱딱한 벽을 순식간에 뚫고 지나가야 하거나 에너지가 찰나의 순간에 점프해야 하도록 만들었다면? 혹은 인덕터 두 개를 직렬로 연결해서 전류가 부딪히게 만들었다면 어떻게 될까? 솔버의 절규: 솔버는 NR 반복을 수천 번 돌려도 잔차를 0으로 만드는 해를 찾을 수 없다. 물리적으로 그런 상태는 존재할 수 없기 때문이다! 잔차가 줄어들지 않고 요동치거나 엉뚱한 곳으로 튀어버린다. 결국 수렴 실패라는 건, 솔버가 나에게 보내는 마지막 경고이다. “아무리 계산해봐도 네가 만든 상황은 물리 법칙상 해가 존재할 수 없어!”라고 말이다. 결국 에러를 고치는 건 솔버 옵션을 만지는 게 아니라, 내 모델의 물리적 개연성에 문제가 있지는 않은지, 에너지 흐름이 너무 급격하게 변하는 구간은 없는지 다시 검토하는 것에서 시작해야 한다는 것을 깨달았다. “DAE는 안 풀리는 문제가 있는데, ODE로는 풀릴까요?” 한 구독자분께서 아주 날카로운 질문을 던져주셨다. “DAE 솔버가 물리 법칙을 만족하지 못해서 해를 못 찾는다면… 수식을 잘 정리해서 ODE로 만들면 돌아갈까요? DAE로는 안 풀리는 문제가 ODE로는 풀릴 수 있나요?” 이 질문을 듣고 나도 잠시 멈춰서 생각에 빠졌다. “돌아가는 것”과 “정답인 것”의 차이를 고민해 볼 수 있는 아주 본질적인 질문이기 때문이다. 꼭 이 답변이 정답은 아닐 수 있겠지만 내 사고의 과정을 따라 답을 적어본다. 그림 7. 철저한 원칙주의로 물리적 모순에 멈춰서는 DAE와, 수치적 오차를 감수하며 유연하게 해를 찾아가는 ODE의 대비 (Google 나노바나나 이용하여 그림 제작함.) 1) DAE 솔버의 ‘결벽증’ 우선 Simscape 같은 DAE 솔버의 성격을 이해해야 한다. 앞에서 말했듯 얘네는 Newton-Raphson 반복을 통해 제약 조건을 엄격하게 체크한다. 이렇게 생각해보자. DAE 솔버는 “기찻길 위를 달리는 기차”다. 철로가 0.1mm라도 어긋나 있으면 기차는 탈선할 위험을 감수하지 않고 그 자리에 즉시 멈춰버린다. “전류의 합이 0이 아니잖아? 난 이대로는 단 한 발자국도 못 가!” 이런 결벽증 때문에 물리적으로 아주 미세하게 모순되는 지점(불연속적인 에너지 점프 등)만 만나도 솔버는 “수렴 실패”를 선언하고 파업에 들어간다. 2) ODE 솔버의 ‘무던함’ 반면, 수식을 열심히 정리해서 ODE 형태로 만들면 상황이 묘하게 달라진다. ODE는 제약 조건을 이미 수식 안에 녹여버렸기 때문에, 솔버 입장에서는 실시간으로 감시해야 할 ‘대수 방정식’이라는 감옥이 사라진 셈이다. ODE 솔버는 앞서 비유한 것 처럼 “지도를 들고 초원을 달리는 강아지”와 같다. 강아지는 지도가 좀 잘못 그려져 있어도, 혹은 앞에 작은 웅덩이가 있어도 일단 앞발을 내디딘다. 수치적 오차가 발생하더라도 미분 계수라는 ‘경향성’을 따라 적분하며 다음 지점으로 어떻게든 넘어간다. 3) 돌아는 가는데, 그게 ‘진짜’일까? 그래서 질문에 대한 답을 내리자면 이렇다. “ODE로 바꾸면 돌아갈 수는 있다. 하지만 그 결과가 물리적으로 맞다는 보장은 없다.” DAE 솔버가 멈췄던 지점에서 ODE 솔버는 수치적 오차를 내며 억지로 뚫고 지나갈 것이다. 시뮬레이션은 끝까지 완료되겠지만, 데이터를 뜯어보면 에너지가 보존되지 않거나 물리 법칙을 무시하고 값이 튀어버린 ‘가짜 결과’일 가능성이 높다. 4) 결론: DAE의 멈춤은 ‘경고’다 결국 “DAE로는 안 풀리는데 ODE로는 풀리는 상황”은 솔버의 성능 차이가 아니라, 솔버가 물리 법칙을 대하는 태도의 차이에서 온다. DAE 솔버가 까다롭게 구는 이유는 우리가 만든 가상 세계가 현실의 물리 법칙을 완벽히 대변하게 만들기 위해서다. 만약 DAE가 해를 찾지 못하고 멈췄다면, ODE로 우회할 수도 있겠지만 “내 모델의 물리적 구조 어디에 모순이 숨어 있는가”를 들여다볼 필요도 있다. 마치며 대수방정식에 대해서 오랫동안 궁금했는데, 이번 포스팅을 계기로 약간의 궁금증이 해소되었다. 물리 모델링을 수행할 때 블록을 불러들이는 것과 블록들을 선으로 연결하는 행위의 뒷면에는 이처럼 놀라운 계산들이 숨어있었다는게 알아보면서도 놀라울 따름이다. 물리 모델링의 백스테이지에 대해 궁금했던 나같은 사람들에게 도움이 되었으면 좋겠다. 참고 문헌 [1] Solve Differential Algebraic Equations (DAEs) [2] How Simscape Simulation Works [3] ode15s - 경직성(stiff) ODE 풀기 예제]]></summary></entry><entry xml:lang="ko"><title type="html">ODE 암시적 솔버 (implicit solvers)</title><link href="https://angeloyeo.github.io/2026/03/02/ODE_implicit_solvers.html" rel="alternate" type="text/html" title="ODE 암시적 솔버 (implicit solvers)" /><published>2026-03-02T00:00:00+00:00</published><updated>2026-03-02T00:00:00+00:00</updated><id>https://angeloyeo.github.io/2026/03/02/ODE_implicit_solvers</id><content type="html" xml:base="https://angeloyeo.github.io/2026/03/02/ODE_implicit_solvers.html"><![CDATA[<h1 id="prerequisites">Prerequisites</h1>

<p>본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다.</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2021/04/30/direction_fields.html">방향장과 오일러 방법</a></li>
</ul>

<p>물리 시뮬레이션의 성능을 결정짓는 핵심 엔진인 Implicit Solver(암시적 솔버)와 Newton-Raphson(NR) 방법의 관계를 정리해 본다. Simscape나 <code class="language-plaintext highlighter-rouge">ode15s</code>가 왜 Stiff한 문제에서 강력한지, 그 내부 수학적 원리를 코드로 풀어서 설명한다.</p>

<h1 id="솔버의-두-얼굴-forward-euler-vs-backward-euler">솔버의 두 얼굴: Forward Euler vs. Backward Euler</h1>

<p>우선 컴퓨터가 ODE를 이산화해서 푸는 방법에 대해 먼저 이해해보자. 아주 기초적인 1차, 1계 미분방정식의 예로부터 시작해보자.</p>

\[\frac{dx}{dt}=f(t, x) % 식 (1)\]

<p>식 (1)은 1차, 1계 미분방정식인데 이 식을 이해하는 방법은 크게 두 가지이다. 우선 미분 계수를 좌변에 모두 몰아넣고, 우변에는 $t$와 $x$로 구성된 다항식을 몰아넣은 것으로 보는 것이다. 생긴것 그대로 이해하는 것이라고 할 수 있다. 두 번째 방법은 좌변과 우변을 뒤집어서 생각해본 것으로 모든 $(t,x)$에 기울기 $dx/dt$가 정의되어 있다고 이해하는 것이다.</p>

<p>예를 들어 $dx/dt=x$의 경우 아래와 같이 모든 $(t, x)$에 아래와 같이 기울기가 세로축의 $x$의 값에 비례하는 기울기가 정의되어 있는 것을 알 수 있다. 그림 1과 같은 것을 “방향장 (direction field)”라고 부른다.</p>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-02-ODE_implicit_solvers/pic1.png" />
  <br />
  그림 1. 미분 방정식 dx/dt=x 의 방향장
</p>

<p>이렇듯 방향장을 생각해볼 수 있다면, 우리가 점을 하나 놓기만 하면 그 앞뒤의 값들을 그 점이 놓인 기울기를 가지고 예측할 수 있다는 것을 생각해볼 수 있다.</p>

<p align="center">
  <video width="100%" height="auto" loop="" autoplay="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-02-ODE_implicit_solvers/vid1.mp4" />
  </video>
  <br />
  그림 2. 방향장 위에 점을 하나 놓으면 그 점 앞뒤의 값들을 예측해볼 수 있다.
</p>

<p>미분방정식은 수식을 전개해가면서 풀 수도 있지만 그림 2에서와 같이 초기값과 그 전후의 관계를 통해서 수치적으로 푸는 것도 가능하다. 이처럼 수치적으로 미분 방정식 $\dot{x} = f(x)$을 풀기 위해서는 연속적인 시간을 잘게 쪼개는 ‘이산화(Discretization)’ 과정이 필요하다. 즉, 하나의 이어진 선으로 볼 게 아니라 앞 뒤 점들을 찾는 과정으로 생각해보자.</p>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-02-ODE_implicit_solvers/pic3.png" />
  <br />
  그림 3. 미분 방정식 (예:dx/dt=x) 의 방향장에서 초기값의 전후 값을 이산적으로 찾을 수 있다.
</p>

<p>앞 뒤 점의 $x$가 무엇인지 결정하는 방법은 크게 explicit 방법과 implicit 방법으로 나눌 수 있다.</p>

<h2 id="1-explicit-solver-대표적으로-forward-euler">1. Explicit Solver (대표적으로 Forward Euler)</h2>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-02-ODE_implicit_solvers/pic4.png" />
  <br />
  그림 4. Explicit solver가 초기값 전후의 값을 찾아가는 방법
</p>

<p>가장 직관적인 방법이다. 현재 지점($x_n$)에서의 기울기를 보고 다음 지점($x_{n+1}$)을 결정한다.</p>

\[x_{n+1} = x_n + h \cdot f(x_n)\]

<p>그림 4에서 처럼 초기값이 놓여지면 그 초기값의 변화율 관계를 통해 다음 값을 찾는다. 우리는 $f(t, x)$에 대응하는 모든 기울기 혹은 변화율을 알고 있으므로 이와 같은 계산이 가능하다.</p>

<ul>
  <li>장점: 계산이 매우 빠르고 단순하다. 우변에 모르는 값($x_{n+1}$)이 없기 때문에 바로 답이 나온다.</li>
  <li>단점: 시스템이 급격히 변하는(Stiff) 구간에서 보폭($h$)을 조금만 크게 가져가도 궤도를 이탈하며 결과가 폭발(발산)한다. 소위 ‘눈 감고 뛰는 것’과 비슷하다.</li>
</ul>

<h2 id="2-implicit-solver-대표적으로-backward-euler">2. Implicit Solver (대표적으로 Backward Euler)</h2>

<p>Implicit Solver는 Explicit Solver가 했던 일에서 추가 확인을 거친다.</p>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-02-ODE_implicit_solvers/pic5.png" />
  <br />
  그림 5. Implicit Solver는 다음 스텝의 값이 지금까지의 경향과 얼마나 일치하는지도 확인한다.
</p>

<p>다시 말해, 후방 오일러는 내가 도착할 미래 지점($x_{n+1}$)에서의 기울기를 미리 참조한다.</p>

\[x_{n+1} = x_n + h \cdot f(x_{n+1})\]

<p>이 때 $x_{n+1}$ 값은 Explicit solver가 했던 것 처럼 한번 구한 것을 초기값으로 쓰고 그 이후에 Error가 적어질 수 있도록 내부적으로 Newton-Raphson 방법 등을 활용한다. 에러가 특정 기준보다 작아지거나 반복회수를 초과하면 추가 확인을 마치거나 할 수 있다.</p>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-02-ODE_implicit_solvers/pic6.png" />
  <br />
  그림 6. Implicit Solver의 작업 흐름도
</p>

<ul>
  <li>특징: 식의 양변에 모두 $x_{n+1}$이 들어있다. 즉, $x_{n+1}$을 구하기 위해선 방정식을 다시 풀어야 하는 ‘암시적(Implicit)’ 구조다.</li>
  <li>장점: 수학적으로 매우 안정적이다. 미래의 기울기를 미리 반영하기 때문에 보폭을 크게 가져가도 궤도를 크게 벗어나지 않는다.</li>
</ul>

<h1 id="왜-explicit-솔버는-한계가-있는가">왜 Explicit 솔버는 한계가 있는가?</h1>

<p>우리가 흔히 쓰는 <code class="language-plaintext highlighter-rouge">ode45</code> 같은 현시적(Explicit) 솔버는 현재 위치의 기울기만 보고 다음 발걸음을 뗀다. 하지만 시스템이 급격하게 변하는 ‘Stiff’한 구간에 들어서면, 조금만 보폭($h$)을 크게 가져가도 궤도를 이탈하여 결과값이 발산해버린다.</p>

<p>이를 해결하기 위해 등장한 것이 암시적(Implicit) 솔버다. 이 솔버는 단순히 현재를 보는 게 아니라, “내가 도착할 다음 지점에서도 물리 법칙이 성립하는가?”를 확인하며 나아간다.</p>

<hr />

<h2 id="1-암시적-솔버의-핵심-잔차-식g">1. 암시적 솔버의 핵심: 잔차 식(G)</h2>

<p>미분 방정식 $\dot{x} = f(x)$를 풀 때, 후방 오일러(Backward Euler) 방식은 다음과 같은 식을 세운다.</p>

\[x_{n+1} = x_n + h \cdot f(x_{n+1})\]

<p>여기서 우변에 우리가 구하려는 미래의 값 $x_{n+1}$이 들어있다는 점이 핵심이다. 이 식을 만족하는 $x_{n+1}$을 찾기 위해 모든 항을 한쪽으로 몰아 잔차 식(Residual) $G$를 정의한다.</p>

\[G(x_{n+1}) = \underbrace{(x_{n+1} - x_n)}_{\text{현재 상황; 실제 변화량}} - \underbrace{h \cdot f(x_{n+1})}_{\text{이상적인 상황; 물리 법칙}}\]

<h3 id="물리-법칙-위반-성적표란-무엇인가">‘물리 법칙 위반 성적표’란 무엇인가?</h3>

<p>이 잔차 식 $G$는 현재 우리가 추측한 $x_{n+1}$이 자연의 법칙을 얼마나 잘 따르고 있는지를 보여주는 성적표와 같다. 식의 의미를 공학적으로 뜯어보면 다음과 같다.</p>

<ul>
  <li>현실 (Left): 내가 계산기로 두드려보니 전압이 $x_n$에서 $x_{n+1}$로 변했다. 즉, $(x_{n+1} - x_n)$만큼 실제로 이동했다는 뜻이다.</li>
  <li>이상 (Right): 물리 법칙($f$)에 $x_{n+1}$을 대입해 보니 “이 지점에선 이 정도 속도로 움직여야 해”라고 명령한다. 여기에 시간 $h$를 곱한 $h \cdot f(x_{n+1})$은 물리 법칙이 정해준 ‘규정 이동 거리’가 된다.</li>
</ul>

<p>만약 우리가 찾은 $x_{n+1}$이 정답이라면, [내가 실제로 이동한 거리]와 [물리가 가라고 명령한 거리]가 정확히 일치해야 한다.</p>

<ul>
  <li>$G = 0$ 이면: “성적표 만점!” 자연의 법칙과 완벽하게 일치하는 다음 상태를 찾은 것이다.</li>
  <li>$G \neq 0$ 이면: “규정 위반!” 물리는 이만큼 가라고 했는데, 내 계산 값은 저만큼 가 버렸다. 그 차이($G$)가 바로 오차이며, 솔버는 이 위반 점수를 0점으로 만들기 위해 값을 끊임없이 수정한다.</li>
</ul>

<p>결국, Simscape가 시뮬레이션 중에 “수렴(Convergence)에 실패했다”는 메시지를 띄우는 것은, 이 성적표의 오차 $G$를 도저히 0으로 만들 수 없는 물리적 모순이 모델 안에 있다는 뜻이다.</p>

<h2 id="2-수학적-지우개-newton-raphson-nr">2. 수학적 지우개: Newton-Raphson (NR)</h2>

<p>잔차 $G$를 0으로 만들기 위해 사용하는 가장 강력한 도구가 바로 Newton-Raphson(NR) 반복법이다. 단순히 무작위로 값을 대입하며 정답을 찍는 게 아니라, 현재 위치에서 자코비안(Jacobian, $J$)이라는 수학적 나침반을 보고 정답($G=0$)을 향해 최단 거리로 전진한다.</p>

<h3 id="자코비안j-정답을-향한-내비게이션">자코비안(J): 정답을 향한 내비게이션</h3>

<p>자코비안은 “내가 추측값($x$)을 아주 살짝 바꿨을 때, 물리 위반 성적표($G$)가 얼마나 예민하게 변하는가?”를 나타내는 지표다.</p>

<ul>
  <li>수학적 정의: $J = \frac{dG}{dx_{n+1}} = 1 - h \cdot \frac{df}{dx_{n+1}}$</li>
  <li>공학적 의미: 현재 안갯속(비선형 시스템)에 갇혀 있을 때, 발밑의 경사도(기울기)를 확인하여 “어느 방향으로 얼마만큼 가야 평지(정답)에 도달할지”를 알려주는 가이드라인이다.</li>
</ul>

<h3 id="업데이트">업데이트</h3>

\[x_{new} = x_{old} - \frac{G}{J}\]

<p>이 식은 NR의 핵심 알고리즘으로, 다음과 같은 논리 구조를 가진다.</p>

<ol>
  <li>위반 점수($G$)가 크면: “정답에서 멀리 떨어져 있구나!” $\rightarrow$ 더 많이 이동한다.</li>
  <li>기울기($J$)가 가파르면: “조금만 움직여도 점수가 팍팍 변하네?” $\rightarrow$ 신중하게 조금만 이동한다.</li>
</ol>

<p>이 두 값을 조합한 <code class="language-plaintext highlighter-rouge">step = G / J</code>만큼 현재 값을 수정해 나가면, 놀랍게도 단 몇 번의 반복(Iteration)만으로 오차 $G$는 순식간에 0에 수렴하게 된다.</p>

<h3 id="implicit-솔버가-보폭h을-키울-수-있는-비결">Implicit 솔버가 ‘보폭(h)’을 키울 수 있는 비결</h3>

<p>Explicit 솔버(Forward Euler)가 한 번의 계산으로 끝내는 ‘단거리 달리기’라면, NR을 사용하는 Implicit 솔버는 “예측하고, 검토하고, 수정하는” 과정을 거치는 ‘정밀 타격’과 같다.</p>

<ul>
  <li>Self-Correction: 설령 보폭($h$)을 크게 가져가서 첫 추측이 빗나가더라도, NR 루프가 잔차($G$)를 확인하며 정답 궤도로 끊임없이 수정해 준다.</li>
  <li>Numerical Stability: 이 ‘자기 수정 능력’ 덕분에 시스템이 딱딱하게(Stiff) 굳어 있는 구간에서도 수치적 폭주 없이 안정적으로 해를 찾아낼 수 있는 것이다.</li>
</ul>

<h2 id="3-matlab으로-구현하는-implicit-solver">3. MATLAB으로 구현하는 Implicit Solver</h2>

<p>다음은 $f(x) = x^2 - x^3$라는 Stiff한 시스템을 직접 구현한 코드이다. Newton-Raphson 루프가 어떻게 작동하는지 주목해 보자.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>clear; clc; close all;

%% 1. 파라미터 및 시스템 설정
% f(x) = x^2 - x^3
% dx/dt가 x=1 부근에서 매우 민감하게 변하는 Stiff 특성
t_end = 200; 
x0 = 0.01; % 초기값 (0.01에서 시작해 1로 수렴하는 과정 관찰)

f = @(t, x) x^2 - x^3; % dx/dt = f 임. 
% 자코비안 (NR을 위한 미분값): df/dx = 2*x - 3*x^2
dfdx = @(x) 2*x - 3*x^2;

%% 2. MATLAB 내장 솔버 (Variable-step)
% ode45: Explicit (이 문제에서 스텝을 아주 잘게 쪼개야 함)
[t45, x45] = ode45(f, [0 t_end], x0);

% ode15s: Implicit (Stiff한 구간을 성큼성큼 넘어감)
[t15s, x15s] = ode15s(f, [0 t_end], x0);

%% 3. 수동 구현: Implicit Euler (Fixed-step, Newton-Raphson)
h = 0.5; % 매우 큰 고정 스텝 (Explicit였다면 수치 오류가 날 수 있는 크기)
t_manual = 0:h:t_end;
x_manual = zeros(size(t_manual));
x_manual(1) = x0;

for n = 1:length(t_manual)-1
    xc_now = x_manual(n);
    xc_next = xc_now; % 초기 추정값
    
    % Newton-Raphson Iteration
    for iter = 1:20
        % 잔차 G(x_next) = x_next - x_now - h * f(x_next) = 0
        G = xc_next - xc_now - h * (xc_next^2 - xc_next^3);
        
        % 자코비안 J = dG/dx_next = 1 - h * df/dx
        J = 1 - h * dfdx(xc_next);
        
        step = G / J;
        xc_next = xc_next - step;
        
        if abs(step) &lt; 1e-8, break; end
    end
    x_manual(n+1) = xc_next;
end

%% 4. 결과 비교 시각화
figure('Color', 'w', 'Position', [100, 100, 900, 550]);

subplot(2,1,1);
plot(t45, x45, 'g-', 'LineWidth', 2); hold on;
plot(t15s, x15s, 'b--', 'LineWidth', 2);
plot(t_manual, x_manual, 'ro', 'MarkerSize', 4);
grid on;
ylabel('x', 'FontSize', 11);
title(['Solver Comparison: f(x) = x^2 - x^3 (x_0 = ', num2str(x0), ')'], 'FontSize', 13);
legend({'ode45 (Explicit)', 'ode15s (Implicit)', 'Manual Implicit (NR)'}, 'Location', 'southeast');

% 스텝 사이즈 비교 (솔버가 얼마나 고생하는지 시각화)
subplot(2,1,2);
stem(t45(1:end-1), diff(t45), 'g', 'Marker', 'none'); hold on;
stem(t15s(1:end-1), diff(t15s), 'b', 'Marker', 'none');
set(gca, 'YScale', 'log'); % 로그 스케일로 스텝 크기 차이 강조
grid on;
ylabel('Step Size (log scale)', 'FontSize', 11);
xlabel('Time (s)', 'FontSize', 11);
legend({'ode45 steps', 'ode15s steps'});

fprintf('--- Solver Statistics ---\n');
fprintf('ode45  Total Steps: %d\n', length(t45));
fprintf('ode15s Total Steps: %d\n', length(t15s));
fprintf('Manual (h=%g) Steps: %d\n', h, length(t_manual));
</code></pre></div></div>

<p>결과적으로 step의 개수는 아래와 같다.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>--- Solver Statistics ---
ode45  Total Steps: 157
ode15s Total Steps: 50
Manual (h=0.5) Steps: 401
</code></pre></div></div>

<p align="center">
  <img width="100%" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2026-03-02-ODE_implicit_solvers/pic7.png" />
  <br />
  그림 7. ode45, ode15s와 함께 수동으로 구현한 implicit solver의 결과 비교
</p>

<h2 id="결론-왜-우리는-이-원리를-알아야-하는가">결론: 왜 우리는 이 원리를 알아야 하는가?</h2>

<p>Simscape나 Simulink의 <code class="language-plaintext highlighter-rouge">ode15s</code> 솔버를 쓸 때 내부적으로 일어나는 일이 바로 이 ‘예측과 수정’의 반복이다.</p>

<ol>
  <li>시스템이 Stiff(강성)해지면 일반 솔버는 보폭을 줄이느라 느려지지만, Implicit 솔버는 NR 덕분에 큰 보폭으로도 정확한 정답을 찾아간다.</li>
  <li>시뮬레이션 중 ‘Convergence Error’가 발생한다면, 위 코드의 NR 루프에서 잔차 $G$를 0으로 만드는 데 실패했다는 뜻이다.</li>
  <li>이 원리를 이해하면 모델링 단계에서 불필요한 불연속성을 제거하거나 솔버 설정을 튜닝하는 데 엄청난 통찰을 얻을 수 있다.</li>
</ol>

<p>결국 고성능 시뮬레이션은 수학적 신뢰와 계산 효율성 사이의 줄타기이며, 그 중심에는 Newton-Raphson이라는 견고한 다리가 놓여 있다.</p>

<p>이 블로그 포스팅이 엔지니어들에게 도움이 되길 바란다.</p>]]></content><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><category term="미분방정식" /><summary type="html"><![CDATA[Prerequisites 본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다. 방향장과 오일러 방법 물리 시뮬레이션의 성능을 결정짓는 핵심 엔진인 Implicit Solver(암시적 솔버)와 Newton-Raphson(NR) 방법의 관계를 정리해 본다. Simscape나 ode15s가 왜 Stiff한 문제에서 강력한지, 그 내부 수학적 원리를 코드로 풀어서 설명한다. 솔버의 두 얼굴: Forward Euler vs. Backward Euler 우선 컴퓨터가 ODE를 이산화해서 푸는 방법에 대해 먼저 이해해보자. 아주 기초적인 1차, 1계 미분방정식의 예로부터 시작해보자. \[\frac{dx}{dt}=f(t, x) % 식 (1)\] 식 (1)은 1차, 1계 미분방정식인데 이 식을 이해하는 방법은 크게 두 가지이다. 우선 미분 계수를 좌변에 모두 몰아넣고, 우변에는 $t$와 $x$로 구성된 다항식을 몰아넣은 것으로 보는 것이다. 생긴것 그대로 이해하는 것이라고 할 수 있다. 두 번째 방법은 좌변과 우변을 뒤집어서 생각해본 것으로 모든 $(t,x)$에 기울기 $dx/dt$가 정의되어 있다고 이해하는 것이다. 예를 들어 $dx/dt=x$의 경우 아래와 같이 모든 $(t, x)$에 아래와 같이 기울기가 세로축의 $x$의 값에 비례하는 기울기가 정의되어 있는 것을 알 수 있다. 그림 1과 같은 것을 “방향장 (direction field)”라고 부른다. 그림 1. 미분 방정식 dx/dt=x 의 방향장 이렇듯 방향장을 생각해볼 수 있다면, 우리가 점을 하나 놓기만 하면 그 앞뒤의 값들을 그 점이 놓인 기울기를 가지고 예측할 수 있다는 것을 생각해볼 수 있다. 그림 2. 방향장 위에 점을 하나 놓으면 그 점 앞뒤의 값들을 예측해볼 수 있다. 미분방정식은 수식을 전개해가면서 풀 수도 있지만 그림 2에서와 같이 초기값과 그 전후의 관계를 통해서 수치적으로 푸는 것도 가능하다. 이처럼 수치적으로 미분 방정식 $\dot{x} = f(x)$을 풀기 위해서는 연속적인 시간을 잘게 쪼개는 ‘이산화(Discretization)’ 과정이 필요하다. 즉, 하나의 이어진 선으로 볼 게 아니라 앞 뒤 점들을 찾는 과정으로 생각해보자. 그림 3. 미분 방정식 (예:dx/dt=x) 의 방향장에서 초기값의 전후 값을 이산적으로 찾을 수 있다. 앞 뒤 점의 $x$가 무엇인지 결정하는 방법은 크게 explicit 방법과 implicit 방법으로 나눌 수 있다. 1. Explicit Solver (대표적으로 Forward Euler) 그림 4. Explicit solver가 초기값 전후의 값을 찾아가는 방법 가장 직관적인 방법이다. 현재 지점($x_n$)에서의 기울기를 보고 다음 지점($x_{n+1}$)을 결정한다. \[x_{n+1} = x_n + h \cdot f(x_n)\] 그림 4에서 처럼 초기값이 놓여지면 그 초기값의 변화율 관계를 통해 다음 값을 찾는다. 우리는 $f(t, x)$에 대응하는 모든 기울기 혹은 변화율을 알고 있으므로 이와 같은 계산이 가능하다. 장점: 계산이 매우 빠르고 단순하다. 우변에 모르는 값($x_{n+1}$)이 없기 때문에 바로 답이 나온다. 단점: 시스템이 급격히 변하는(Stiff) 구간에서 보폭($h$)을 조금만 크게 가져가도 궤도를 이탈하며 결과가 폭발(발산)한다. 소위 ‘눈 감고 뛰는 것’과 비슷하다. 2. Implicit Solver (대표적으로 Backward Euler) Implicit Solver는 Explicit Solver가 했던 일에서 추가 확인을 거친다. 그림 5. Implicit Solver는 다음 스텝의 값이 지금까지의 경향과 얼마나 일치하는지도 확인한다. 다시 말해, 후방 오일러는 내가 도착할 미래 지점($x_{n+1}$)에서의 기울기를 미리 참조한다. \[x_{n+1} = x_n + h \cdot f(x_{n+1})\] 이 때 $x_{n+1}$ 값은 Explicit solver가 했던 것 처럼 한번 구한 것을 초기값으로 쓰고 그 이후에 Error가 적어질 수 있도록 내부적으로 Newton-Raphson 방법 등을 활용한다. 에러가 특정 기준보다 작아지거나 반복회수를 초과하면 추가 확인을 마치거나 할 수 있다. 그림 6. Implicit Solver의 작업 흐름도 특징: 식의 양변에 모두 $x_{n+1}$이 들어있다. 즉, $x_{n+1}$을 구하기 위해선 방정식을 다시 풀어야 하는 ‘암시적(Implicit)’ 구조다. 장점: 수학적으로 매우 안정적이다. 미래의 기울기를 미리 반영하기 때문에 보폭을 크게 가져가도 궤도를 크게 벗어나지 않는다. 왜 Explicit 솔버는 한계가 있는가? 우리가 흔히 쓰는 ode45 같은 현시적(Explicit) 솔버는 현재 위치의 기울기만 보고 다음 발걸음을 뗀다. 하지만 시스템이 급격하게 변하는 ‘Stiff’한 구간에 들어서면, 조금만 보폭($h$)을 크게 가져가도 궤도를 이탈하여 결과값이 발산해버린다. 이를 해결하기 위해 등장한 것이 암시적(Implicit) 솔버다. 이 솔버는 단순히 현재를 보는 게 아니라, “내가 도착할 다음 지점에서도 물리 법칙이 성립하는가?”를 확인하며 나아간다. 1. 암시적 솔버의 핵심: 잔차 식(G) 미분 방정식 $\dot{x} = f(x)$를 풀 때, 후방 오일러(Backward Euler) 방식은 다음과 같은 식을 세운다. \[x_{n+1} = x_n + h \cdot f(x_{n+1})\] 여기서 우변에 우리가 구하려는 미래의 값 $x_{n+1}$이 들어있다는 점이 핵심이다. 이 식을 만족하는 $x_{n+1}$을 찾기 위해 모든 항을 한쪽으로 몰아 잔차 식(Residual) $G$를 정의한다. \[G(x_{n+1}) = \underbrace{(x_{n+1} - x_n)}_{\text{현재 상황; 실제 변화량}} - \underbrace{h \cdot f(x_{n+1})}_{\text{이상적인 상황; 물리 법칙}}\] ‘물리 법칙 위반 성적표’란 무엇인가? 이 잔차 식 $G$는 현재 우리가 추측한 $x_{n+1}$이 자연의 법칙을 얼마나 잘 따르고 있는지를 보여주는 성적표와 같다. 식의 의미를 공학적으로 뜯어보면 다음과 같다. 현실 (Left): 내가 계산기로 두드려보니 전압이 $x_n$에서 $x_{n+1}$로 변했다. 즉, $(x_{n+1} - x_n)$만큼 실제로 이동했다는 뜻이다. 이상 (Right): 물리 법칙($f$)에 $x_{n+1}$을 대입해 보니 “이 지점에선 이 정도 속도로 움직여야 해”라고 명령한다. 여기에 시간 $h$를 곱한 $h \cdot f(x_{n+1})$은 물리 법칙이 정해준 ‘규정 이동 거리’가 된다. 만약 우리가 찾은 $x_{n+1}$이 정답이라면, [내가 실제로 이동한 거리]와 [물리가 가라고 명령한 거리]가 정확히 일치해야 한다. $G = 0$ 이면: “성적표 만점!” 자연의 법칙과 완벽하게 일치하는 다음 상태를 찾은 것이다. $G \neq 0$ 이면: “규정 위반!” 물리는 이만큼 가라고 했는데, 내 계산 값은 저만큼 가 버렸다. 그 차이($G$)가 바로 오차이며, 솔버는 이 위반 점수를 0점으로 만들기 위해 값을 끊임없이 수정한다. 결국, Simscape가 시뮬레이션 중에 “수렴(Convergence)에 실패했다”는 메시지를 띄우는 것은, 이 성적표의 오차 $G$를 도저히 0으로 만들 수 없는 물리적 모순이 모델 안에 있다는 뜻이다. 2. 수학적 지우개: Newton-Raphson (NR) 잔차 $G$를 0으로 만들기 위해 사용하는 가장 강력한 도구가 바로 Newton-Raphson(NR) 반복법이다. 단순히 무작위로 값을 대입하며 정답을 찍는 게 아니라, 현재 위치에서 자코비안(Jacobian, $J$)이라는 수학적 나침반을 보고 정답($G=0$)을 향해 최단 거리로 전진한다. 자코비안(J): 정답을 향한 내비게이션 자코비안은 “내가 추측값($x$)을 아주 살짝 바꿨을 때, 물리 위반 성적표($G$)가 얼마나 예민하게 변하는가?”를 나타내는 지표다. 수학적 정의: $J = \frac{dG}{dx_{n+1}} = 1 - h \cdot \frac{df}{dx_{n+1}}$ 공학적 의미: 현재 안갯속(비선형 시스템)에 갇혀 있을 때, 발밑의 경사도(기울기)를 확인하여 “어느 방향으로 얼마만큼 가야 평지(정답)에 도달할지”를 알려주는 가이드라인이다. 업데이트 \[x_{new} = x_{old} - \frac{G}{J}\] 이 식은 NR의 핵심 알고리즘으로, 다음과 같은 논리 구조를 가진다. 위반 점수($G$)가 크면: “정답에서 멀리 떨어져 있구나!” $\rightarrow$ 더 많이 이동한다. 기울기($J$)가 가파르면: “조금만 움직여도 점수가 팍팍 변하네?” $\rightarrow$ 신중하게 조금만 이동한다. 이 두 값을 조합한 step = G / J만큼 현재 값을 수정해 나가면, 놀랍게도 단 몇 번의 반복(Iteration)만으로 오차 $G$는 순식간에 0에 수렴하게 된다. Implicit 솔버가 ‘보폭(h)’을 키울 수 있는 비결 Explicit 솔버(Forward Euler)가 한 번의 계산으로 끝내는 ‘단거리 달리기’라면, NR을 사용하는 Implicit 솔버는 “예측하고, 검토하고, 수정하는” 과정을 거치는 ‘정밀 타격’과 같다. Self-Correction: 설령 보폭($h$)을 크게 가져가서 첫 추측이 빗나가더라도, NR 루프가 잔차($G$)를 확인하며 정답 궤도로 끊임없이 수정해 준다. Numerical Stability: 이 ‘자기 수정 능력’ 덕분에 시스템이 딱딱하게(Stiff) 굳어 있는 구간에서도 수치적 폭주 없이 안정적으로 해를 찾아낼 수 있는 것이다. 3. MATLAB으로 구현하는 Implicit Solver 다음은 $f(x) = x^2 - x^3$라는 Stiff한 시스템을 직접 구현한 코드이다. Newton-Raphson 루프가 어떻게 작동하는지 주목해 보자. clear; clc; close all; %% 1. 파라미터 및 시스템 설정 % f(x) = x^2 - x^3 % dx/dt가 x=1 부근에서 매우 민감하게 변하는 Stiff 특성 t_end = 200; x0 = 0.01; % 초기값 (0.01에서 시작해 1로 수렴하는 과정 관찰) f = @(t, x) x^2 - x^3; % dx/dt = f 임. % 자코비안 (NR을 위한 미분값): df/dx = 2*x - 3*x^2 dfdx = @(x) 2*x - 3*x^2; %% 2. MATLAB 내장 솔버 (Variable-step) % ode45: Explicit (이 문제에서 스텝을 아주 잘게 쪼개야 함) [t45, x45] = ode45(f, [0 t_end], x0); % ode15s: Implicit (Stiff한 구간을 성큼성큼 넘어감) [t15s, x15s] = ode15s(f, [0 t_end], x0); %% 3. 수동 구현: Implicit Euler (Fixed-step, Newton-Raphson) h = 0.5; % 매우 큰 고정 스텝 (Explicit였다면 수치 오류가 날 수 있는 크기) t_manual = 0:h:t_end; x_manual = zeros(size(t_manual)); x_manual(1) = x0; for n = 1:length(t_manual)-1 xc_now = x_manual(n); xc_next = xc_now; % 초기 추정값 % Newton-Raphson Iteration for iter = 1:20 % 잔차 G(x_next) = x_next - x_now - h * f(x_next) = 0 G = xc_next - xc_now - h * (xc_next^2 - xc_next^3); % 자코비안 J = dG/dx_next = 1 - h * df/dx J = 1 - h * dfdx(xc_next); step = G / J; xc_next = xc_next - step; if abs(step) &lt; 1e-8, break; end end x_manual(n+1) = xc_next; end %% 4. 결과 비교 시각화 figure('Color', 'w', 'Position', [100, 100, 900, 550]); subplot(2,1,1); plot(t45, x45, 'g-', 'LineWidth', 2); hold on; plot(t15s, x15s, 'b--', 'LineWidth', 2); plot(t_manual, x_manual, 'ro', 'MarkerSize', 4); grid on; ylabel('x', 'FontSize', 11); title(['Solver Comparison: f(x) = x^2 - x^3 (x_0 = ', num2str(x0), ')'], 'FontSize', 13); legend({'ode45 (Explicit)', 'ode15s (Implicit)', 'Manual Implicit (NR)'}, 'Location', 'southeast'); % 스텝 사이즈 비교 (솔버가 얼마나 고생하는지 시각화) subplot(2,1,2); stem(t45(1:end-1), diff(t45), 'g', 'Marker', 'none'); hold on; stem(t15s(1:end-1), diff(t15s), 'b', 'Marker', 'none'); set(gca, 'YScale', 'log'); % 로그 스케일로 스텝 크기 차이 강조 grid on; ylabel('Step Size (log scale)', 'FontSize', 11); xlabel('Time (s)', 'FontSize', 11); legend({'ode45 steps', 'ode15s steps'}); fprintf('--- Solver Statistics ---\n'); fprintf('ode45 Total Steps: %d\n', length(t45)); fprintf('ode15s Total Steps: %d\n', length(t15s)); fprintf('Manual (h=%g) Steps: %d\n', h, length(t_manual)); 결과적으로 step의 개수는 아래와 같다. --- Solver Statistics --- ode45 Total Steps: 157 ode15s Total Steps: 50 Manual (h=0.5) Steps: 401 그림 7. ode45, ode15s와 함께 수동으로 구현한 implicit solver의 결과 비교 결론: 왜 우리는 이 원리를 알아야 하는가? Simscape나 Simulink의 ode15s 솔버를 쓸 때 내부적으로 일어나는 일이 바로 이 ‘예측과 수정’의 반복이다. 시스템이 Stiff(강성)해지면 일반 솔버는 보폭을 줄이느라 느려지지만, Implicit 솔버는 NR 덕분에 큰 보폭으로도 정확한 정답을 찾아간다. 시뮬레이션 중 ‘Convergence Error’가 발생한다면, 위 코드의 NR 루프에서 잔차 $G$를 0으로 만드는 데 실패했다는 뜻이다. 이 원리를 이해하면 모델링 단계에서 불필요한 불연속성을 제거하거나 솔버 설정을 튜닝하는 데 엄청난 통찰을 얻을 수 있다. 결국 고성능 시뮬레이션은 수학적 신뢰와 계산 효율성 사이의 줄타기이며, 그 중심에는 Newton-Raphson이라는 견고한 다리가 놓여 있다. 이 블로그 포스팅이 엔지니어들에게 도움이 되길 바란다.]]></summary></entry><entry xml:lang="ko"><title type="html">아핀 변환 (Affine Transformation)</title><link href="https://angeloyeo.github.io/2024/06/28/Affine_Transformation.html" rel="alternate" type="text/html" title="아핀 변환 (Affine Transformation)" /><published>2024-06-28T00:00:00+00:00</published><updated>2024-06-28T00:00:00+00:00</updated><id>https://angeloyeo.github.io/2024/06/28/Affine_Transformation</id><content type="html" xml:base="https://angeloyeo.github.io/2024/06/28/Affine_Transformation.html"><![CDATA[<p align="center"><iframe src="https://angeloyeo.github.io/p5/2024-06-28-Affine_Transformation/" width="400" height="400" frameborder="0"></iframe></p>

<p>행렬을 이용해 물체를 평행이동 시켜주는 변환은 수학적으로 어떻게 기술될 수 있을까?</p>

<h1 id="prerequisites">Prerequisites</h1>

<p>본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다.</p>
<ul>
  <li><a href="https://angeloyeo.github.io/2020/09/07/basic_vector_operation.html">벡터의 기본 연산(상수배, 덧셈)</a></li>
  <li><a href="https://angeloyeo.github.io/2019/07/15/Matrix_as_Linear_Transformation.html">행렬과 선형변환</a></li>
</ul>

<h1 id="복습">복습</h1>

<p>벡터란 공간 상의 한 점으로 생각할 수 있다고 했다. 벡터를 표현할 때 위치와 방향성을 모두 고려하여 화살표로 나타낼 수도 있지만, 수 많은 벡터를 한번에 표시하기에는 너무 복잡해질 수 있으므로 위치만 표시하기도 한다.</p>

<p align="center">
  <video width="600" height="auto" loop="" autoplay="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2024-06-28-Affine_Transformation/vector2dot.mp4" />
  </video>
  <br />
  그림 1. 벡터는 화살표로 표시하기도 하지만 점으로 표시할 수 있다.
</p>

<p>만약 2차원 평면 상에 표시된 점들을 pixel로 생각한다면 벡터들의 나열을 그림으로 대체해 생각할 수도 있을 것이다.</p>

<h2 id="2차원-공간에서의-선형-변환">2차원 공간에서의 선형 변환</h2>

<p><a href="https://angeloyeo.github.io/2019/07/15/Matrix_as_Linear_Transformation.html">행렬과 선형변환</a> 편에서 배운 것 처럼 행렬은 하나의 선형 변환으로 표현할 수 있다. 그림에 선형 변환을 적용하면 기하학적으로 사진의 형태가 변형되기 때문이 기하 변환(geometric transformations)이라고도 부른다. 대표적인 변환들은 아래와 같다.</p>

<h3 id="scaling-2d">Scaling (2D)</h3>

\[\begin{bmatrix}2 &amp; 0\\ 0&amp; 1\end{bmatrix} % 식 (1)\]

<p align="center">
  <video width="300" height="auto" loop="" autoplay="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2024-06-28-Affine_Transformation/2d_scaling.mp4" />
  </video>
  <br />
  그림 2. 2차원 공간의 scaling 변환
</p>

<h3 id="shear-2d">Shear (2D)</h3>

\[\begin{bmatrix}2 &amp; 1\\ 1&amp; 2\end{bmatrix} % 식 (2)\]

<p align="center">
  <video width="300" height="auto" loop="" autoplay="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2024-06-28-Affine_Transformation/2d_shear.mp4" />
  </video>
  <br />
  그림 3. 2차원 공간의 shear 변환
</p>

<h3 id="rotation-2d">Rotation (2D)</h3>

\[\begin{bmatrix}\cos(\pi/3) &amp; -\sin(\pi/3)\\ \sin(\pi/3)&amp; \cos(\pi/3)\end{bmatrix} % 식 (3)\]

<p align="center">
  <video width="300" height="auto" loop="" autoplay="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2024-06-28-Affine_Transformation/2d_rotation.mp4" />
  </video>
  <br />
  그림 4. 2차원 공간의 Rotation 변환
</p>

<h3 id="permutation-2d">Permutation (2D)</h3>

\[\begin{bmatrix}0 &amp; 1\\ 1&amp; 0\end{bmatrix} % 식 (4)\]

<p align="center">
  <video width="300" height="auto" loop="" autoplay="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2024-06-28-Affine_Transformation/2d_permutation.mp4" />
  </video>
  <br />
  그림 5. 2차원 공간의 Permutation 변환
</p>

<h2 id="3차원-공간에서의-선형-변환">3차원 공간에서의 선형 변환</h2>

<p>선형 변환은 비단 2차원에만 해당하는 것이 아니며, 3차원에서도 적용할 수 있다. 아래는 3x3 행렬을 이용해 표현한 3차원 공간 상에서의 변환이다.</p>

<h3 id="scaling-3d">Scaling (3D)</h3>

\[\begin{bmatrix}2 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 \\ 0&amp; 0&amp;1\end{bmatrix}% 식 (5)\]

<p align="center">
  <video width="300" height="auto" loop="" autoplay="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2024-06-28-Affine_Transformation/3d_scaling.mp4" />
  </video>
  <br />
  그림 6. 3차원 공간의 scaling 변환
</p>

<h3 id="shear-3d">Shear (3D)</h3>

\[\begin{bmatrix}2 &amp; 1 &amp; 0 \\ 1&amp; 2 &amp; 0 \\ 0&amp; 0&amp;1\end{bmatrix}% 식 (6)\]

<p align="center">
  <video width="300" height="auto" loop="" autoplay="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2024-06-28-Affine_Transformation/3d_shear.mp4" />
  </video>
  <br />
  그림 7. 3차원 공간의 Shear 변환
</p>

<h3 id="rotation-3d">rotation (3D)</h3>

\[\begin{bmatrix}\cos(\pi/3) &amp; -\sin(\pi/3) &amp; 0 \\ \sin(\pi/3)&amp; \cos(\pi/3) &amp; 0 \\ 0 &amp; 0 &amp; 1\end{bmatrix} % 식 (7)\]

<p align="center">
  <video width="300" height="auto" loop="" autoplay="" muted="">
    <source src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2024-06-28-Affine_Transformation/3d_rotation.mp4" />
  </video>
  <br />
  그림 8. 3차원 공간의 Rotation 변환
</p>

<p>이 외에도 3차원 선형 변환이 동작하는 방식은 다양하므로 본 글의 맨 위에 있는 데모 애플릿을 이용해 3차원 선형 변환을 수행해보도록 하자.</p>

<h1 id="아핀-변환-affine-transform">아핀 변환 (Affine Transform)</h1>

<h2 id="평행이동을-하기-위해선-덧셈이-필요해">평행이동을 하기 위해선 덧셈이 필요해</h2>

<p>2차원 혹은 3차원에서의 변화에서 알 수 있는 점 중 하나는 나열되어 있는 변환들만으로는 평행이동을 표현하지 못한다는 것이다. 쉽게 말해, 그림을 상하좌우로 옮길 방법은 없어 보인다는 점이다. 그 이유는 일반적인 행렬의 곱만으로는 벡터 간의 덧셈을 표현할 수 없기 때문이다. 그러니까, 평행이동을 표현해주기 위해선 아래와 같이 덧셈 연산이 필요함을 생각할 수 있다.</p>

\[\begin{bmatrix}x_{new} \\ y_{new} \end{bmatrix}

=\begin{bmatrix}A_{11} &amp; A_{12} \\ A_{21} &amp; A_{22}\end{bmatrix}

\begin{bmatrix}x \\ y\end{bmatrix} + \begin{bmatrix}b_1 \\ b_2\end{bmatrix} % 식 (8)\]

<p>위 식에서는 $\begin{bmatrix} x &amp; y\end{bmatrix}^T$ 벡터에 선형변환을 적용한 뒤 $x$ 축으로 $b_1$, $y$ 축으로 $b_2$ 만큼 이동시키는 것을 알 수 있다. 참고로 수학에서 평행이동을 시켜주는 양을 “bias”라고도 표현하기도 하므로 $b$라는 알파벳을 활용했다.</p>

<h2 id="행렬-하나만으로-평행이동을-표현하기-위한-방법">행렬 하나만으로 평행이동을 표현하기 위한 방법</h2>

<p>그런데, 만약 2차원 평면 상에 표현하는 벡터에 “bias”에 해당하는 차원을 하나 더 추가해주면 편리하게도 행렬의 곱셈 하나만으로 평행이동을 함께 표현할 수 있게 된다. 글로만 설명하면 무슨 말인지 이해하기 어려울 수 있기 때문에 수식을 같이 곁들이자면 아래와 같다.</p>

\[\begin{bmatrix}x_{new} \\ y_{new} \\ 1\end{bmatrix}

=\begin{bmatrix}A_{11} &amp; A_{12} &amp; b_1 \\ A_{21} &amp; A_{22} &amp; b_2 \\ 0 &amp; 0 &amp; 1\end{bmatrix}

\begin{bmatrix}x \\ y \\ 1\end{bmatrix} % 식 (9)\]

<p>즉, 식 (9)에서 벡터의 세 번째 차원은 실제로는 사용하지 않고 “bias 계산의 편의를 위해” 숫자 1로 도입하고 중간에 곱해지는 행렬도 $b_1$, $b_2$ 값을 오른쪽에 더 붙이고, 3행에는 [0, 0, 1]을 넣어 3x3 행렬을 구성하면 된다는 것이다.</p>

<p>이런 식으로 방향과 크기 뿐만 아니라 위치를 함께 포함하는 변환을 아핀 변환 (Affine transformation)이라고 부른다. 또, 식 (9)에서처럼 기존의 N 차원 벡터에 차원 하나를 덧붙여 표시하는 좌표계를 동차 좌표계(homogeneous coordinates)라고 부른다.</p>

<h2 id="아핀-변환의-실체">아핀 변환의 실체</h2>

<p>아핀 변환을 처음 배웠을 때에는 다소 의아한 점이 많았다. 식 (8)의 비선형변환을 식 (9)와 같이 차원을 하나 늘려줌으로써 선형 변환처럼 서술할 수 있다는 것이 “교묘한 트릭”처럼 느껴졌다.</p>

<p>즉, <a href="https://angeloyeo.github.io/2019/07/15/Matrix_as_Linear_Transformation.html">행렬과 선형변환</a>에서 배운 것 처럼 선형변환은 원점을 보존해야 하는데, 아핀 변환의 존재는 내가 알고 있는 지식이 부실한 기반인냥 나를 기만하는 것 같기도 했다.</p>

<p>계산만 보면 차원을 하나 더 늘렸을 때 평행이동을 수학적으로 서술할 수 있다는 것은 알겠으나, 그렇다면 하나 더 늘린 차원은 어디에 존재한다는 말인가? 또, 하나 더 붙였던 차원은 그냥 떼버리는 것 처럼 사용하는데 아핀 변환은 선형변환의 관점에서는 이해할 수 없는 것일까? 속된말로 “야매” 수학일까? 아니면 충분히 실용적이기 때문에 사람들에게서 받아들여지고 있는 내용인 것일까? 등의 생각으로 정리가 어려웠다.</p>

<p>하지만, 아핀 변환은 한 차원 높은 좌표계에서의 선형 변환이 어떻게 일어나는지 생각할 수 있다면 그 정체를 이해할 수 있으며, 기존의 “선형 변환은 원점을 보존한다”는 지식도 그 기반을 단단하게 다질 수 있게 된다. 아래는 맨 위의 데모를 조감도로 본 것이다. 1행 3열의 값을 바꿔보면 무슨 일이 일어나는지 생각해보자.</p>

<p align="center"><iframe src="https://angeloyeo.github.io/p5/2024-06-28-Affine_Transformation_birdeye/" width="400" height="400" frameborder="0"></iframe></p>

<p>1행 3열의 값을 양으로 변화시키면 3차원 공간에서는 정육면체 윗면이 오른쪽으로 밀리게 되지만, 조감도로 투영해보면 사진이 오른쪽으로 이동하는 것과 같은 효과를 가져오게 된다.</p>

<p align="center">
  <img width="300" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2024-06-28-Affine_Transformation/birdeyeview1.png" />
  <br />
  그림 9. 3차원 공간에서 1행 3열의 원소값 변화는 조감도로 보면 x축 상에서 평행이동해준 것과 같은 효과를 보인다.
</p>

<p>마찬가지 방법으로 2행 3열의 원소값을 변화시키면 y축에서 평행이동하는 것과 같은 효과를 가져오게 된다.</p>

<p>즉, 아핀 변환에서 작용하는 행렬은 역시 원점을 보존해주는 변환임을 알 수 있으며, 추가된 하나의 차원에서 높이가 1인 지점에서의 변화를 관찰하여 2차원 평면에 투영하는 것과 같다는 것을 알 수 있다.</p>]]></content><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><category term="선형대수학" /><summary type="html"><![CDATA[행렬을 이용해 물체를 평행이동 시켜주는 변환은 수학적으로 어떻게 기술될 수 있을까? Prerequisites 본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다. 벡터의 기본 연산(상수배, 덧셈) 행렬과 선형변환 복습 벡터란 공간 상의 한 점으로 생각할 수 있다고 했다. 벡터를 표현할 때 위치와 방향성을 모두 고려하여 화살표로 나타낼 수도 있지만, 수 많은 벡터를 한번에 표시하기에는 너무 복잡해질 수 있으므로 위치만 표시하기도 한다. 그림 1. 벡터는 화살표로 표시하기도 하지만 점으로 표시할 수 있다. 만약 2차원 평면 상에 표시된 점들을 pixel로 생각한다면 벡터들의 나열을 그림으로 대체해 생각할 수도 있을 것이다. 2차원 공간에서의 선형 변환 행렬과 선형변환 편에서 배운 것 처럼 행렬은 하나의 선형 변환으로 표현할 수 있다. 그림에 선형 변환을 적용하면 기하학적으로 사진의 형태가 변형되기 때문이 기하 변환(geometric transformations)이라고도 부른다. 대표적인 변환들은 아래와 같다. Scaling (2D) \[\begin{bmatrix}2 &amp; 0\\ 0&amp; 1\end{bmatrix} % 식 (1)\] 그림 2. 2차원 공간의 scaling 변환 Shear (2D) \[\begin{bmatrix}2 &amp; 1\\ 1&amp; 2\end{bmatrix} % 식 (2)\] 그림 3. 2차원 공간의 shear 변환 Rotation (2D) \[\begin{bmatrix}\cos(\pi/3) &amp; -\sin(\pi/3)\\ \sin(\pi/3)&amp; \cos(\pi/3)\end{bmatrix} % 식 (3)\] 그림 4. 2차원 공간의 Rotation 변환 Permutation (2D) \[\begin{bmatrix}0 &amp; 1\\ 1&amp; 0\end{bmatrix} % 식 (4)\] 그림 5. 2차원 공간의 Permutation 변환 3차원 공간에서의 선형 변환 선형 변환은 비단 2차원에만 해당하는 것이 아니며, 3차원에서도 적용할 수 있다. 아래는 3x3 행렬을 이용해 표현한 3차원 공간 상에서의 변환이다. Scaling (3D) \[\begin{bmatrix}2 &amp; 0 &amp; 0 \\ 0 &amp; 1 &amp; 0 \\ 0&amp; 0&amp;1\end{bmatrix}% 식 (5)\] 그림 6. 3차원 공간의 scaling 변환 Shear (3D) \[\begin{bmatrix}2 &amp; 1 &amp; 0 \\ 1&amp; 2 &amp; 0 \\ 0&amp; 0&amp;1\end{bmatrix}% 식 (6)\] 그림 7. 3차원 공간의 Shear 변환 rotation (3D) \[\begin{bmatrix}\cos(\pi/3) &amp; -\sin(\pi/3) &amp; 0 \\ \sin(\pi/3)&amp; \cos(\pi/3) &amp; 0 \\ 0 &amp; 0 &amp; 1\end{bmatrix} % 식 (7)\] 그림 8. 3차원 공간의 Rotation 변환 이 외에도 3차원 선형 변환이 동작하는 방식은 다양하므로 본 글의 맨 위에 있는 데모 애플릿을 이용해 3차원 선형 변환을 수행해보도록 하자. 아핀 변환 (Affine Transform) 평행이동을 하기 위해선 덧셈이 필요해 2차원 혹은 3차원에서의 변화에서 알 수 있는 점 중 하나는 나열되어 있는 변환들만으로는 평행이동을 표현하지 못한다는 것이다. 쉽게 말해, 그림을 상하좌우로 옮길 방법은 없어 보인다는 점이다. 그 이유는 일반적인 행렬의 곱만으로는 벡터 간의 덧셈을 표현할 수 없기 때문이다. 그러니까, 평행이동을 표현해주기 위해선 아래와 같이 덧셈 연산이 필요함을 생각할 수 있다. \[\begin{bmatrix}x_{new} \\ y_{new} \end{bmatrix} =\begin{bmatrix}A_{11} &amp; A_{12} \\ A_{21} &amp; A_{22}\end{bmatrix} \begin{bmatrix}x \\ y\end{bmatrix} + \begin{bmatrix}b_1 \\ b_2\end{bmatrix} % 식 (8)\] 위 식에서는 $\begin{bmatrix} x &amp; y\end{bmatrix}^T$ 벡터에 선형변환을 적용한 뒤 $x$ 축으로 $b_1$, $y$ 축으로 $b_2$ 만큼 이동시키는 것을 알 수 있다. 참고로 수학에서 평행이동을 시켜주는 양을 “bias”라고도 표현하기도 하므로 $b$라는 알파벳을 활용했다. 행렬 하나만으로 평행이동을 표현하기 위한 방법 그런데, 만약 2차원 평면 상에 표현하는 벡터에 “bias”에 해당하는 차원을 하나 더 추가해주면 편리하게도 행렬의 곱셈 하나만으로 평행이동을 함께 표현할 수 있게 된다. 글로만 설명하면 무슨 말인지 이해하기 어려울 수 있기 때문에 수식을 같이 곁들이자면 아래와 같다. \[\begin{bmatrix}x_{new} \\ y_{new} \\ 1\end{bmatrix} =\begin{bmatrix}A_{11} &amp; A_{12} &amp; b_1 \\ A_{21} &amp; A_{22} &amp; b_2 \\ 0 &amp; 0 &amp; 1\end{bmatrix} \begin{bmatrix}x \\ y \\ 1\end{bmatrix} % 식 (9)\] 즉, 식 (9)에서 벡터의 세 번째 차원은 실제로는 사용하지 않고 “bias 계산의 편의를 위해” 숫자 1로 도입하고 중간에 곱해지는 행렬도 $b_1$, $b_2$ 값을 오른쪽에 더 붙이고, 3행에는 [0, 0, 1]을 넣어 3x3 행렬을 구성하면 된다는 것이다. 이런 식으로 방향과 크기 뿐만 아니라 위치를 함께 포함하는 변환을 아핀 변환 (Affine transformation)이라고 부른다. 또, 식 (9)에서처럼 기존의 N 차원 벡터에 차원 하나를 덧붙여 표시하는 좌표계를 동차 좌표계(homogeneous coordinates)라고 부른다. 아핀 변환의 실체 아핀 변환을 처음 배웠을 때에는 다소 의아한 점이 많았다. 식 (8)의 비선형변환을 식 (9)와 같이 차원을 하나 늘려줌으로써 선형 변환처럼 서술할 수 있다는 것이 “교묘한 트릭”처럼 느껴졌다. 즉, 행렬과 선형변환에서 배운 것 처럼 선형변환은 원점을 보존해야 하는데, 아핀 변환의 존재는 내가 알고 있는 지식이 부실한 기반인냥 나를 기만하는 것 같기도 했다. 계산만 보면 차원을 하나 더 늘렸을 때 평행이동을 수학적으로 서술할 수 있다는 것은 알겠으나, 그렇다면 하나 더 늘린 차원은 어디에 존재한다는 말인가? 또, 하나 더 붙였던 차원은 그냥 떼버리는 것 처럼 사용하는데 아핀 변환은 선형변환의 관점에서는 이해할 수 없는 것일까? 속된말로 “야매” 수학일까? 아니면 충분히 실용적이기 때문에 사람들에게서 받아들여지고 있는 내용인 것일까? 등의 생각으로 정리가 어려웠다. 하지만, 아핀 변환은 한 차원 높은 좌표계에서의 선형 변환이 어떻게 일어나는지 생각할 수 있다면 그 정체를 이해할 수 있으며, 기존의 “선형 변환은 원점을 보존한다”는 지식도 그 기반을 단단하게 다질 수 있게 된다. 아래는 맨 위의 데모를 조감도로 본 것이다. 1행 3열의 값을 바꿔보면 무슨 일이 일어나는지 생각해보자. 1행 3열의 값을 양으로 변화시키면 3차원 공간에서는 정육면체 윗면이 오른쪽으로 밀리게 되지만, 조감도로 투영해보면 사진이 오른쪽으로 이동하는 것과 같은 효과를 가져오게 된다. 그림 9. 3차원 공간에서 1행 3열의 원소값 변화는 조감도로 보면 x축 상에서 평행이동해준 것과 같은 효과를 보인다. 마찬가지 방법으로 2행 3열의 원소값을 변화시키면 y축에서 평행이동하는 것과 같은 효과를 가져오게 된다. 즉, 아핀 변환에서 작용하는 행렬은 역시 원점을 보존해주는 변환임을 알 수 있으며, 추가된 하나의 차원에서 높이가 1인 지점에서의 변화를 관찰하여 2차원 평면에 투영하는 것과 같다는 것을 알 수 있다.]]></summary></entry><entry xml:lang="ko"><title type="html">마할라노비스 거리</title><link href="https://angeloyeo.github.io/2022/09/28/Mahalanobis_distance.html" rel="alternate" type="text/html" title="마할라노비스 거리" /><published>2022-09-28T00:00:00+00:00</published><updated>2022-09-28T00:00:00+00:00</updated><id>https://angeloyeo.github.io/2022/09/28/Mahalanobis_distance</id><content type="html" xml:base="https://angeloyeo.github.io/2022/09/28/Mahalanobis_distance.html"><![CDATA[<p align="center"><iframe src="https://angeloyeo.github.io/p5/2022-09-28-Mahalanobis_distance/" width="650" height="520" frameborder="0"></iframe></p>

<p>※ 본 포스팅에서는 벡터의 기본 방향을 “행벡터”로 보고 작성하였습니다. 이에 대한 더 자세한 설명은 첫 꼭지 “행벡터를 기본 방향으로 하는 데이터 표현” 챕터를 읽어주십시오.</p>

<h1 id="prerequisites">Prerequisites</h1>

<p>본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다.</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2019/07/15/Matrix_as_Linear_Transformation.html">행렬과 선형변환</a></li>
</ul>

<p>공분산 행렬에 대한 더 친절한 설명이 필요한 경우 아래의 포스트를 확인하십시오.</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2019/07/27/PCA.html">주성분 분석(PCA)</a></li>
</ul>

<h1 id="행벡터를-기본-방향으로-하는-데이터-표현">행벡터를 기본 방향으로 하는 데이터 표현</h1>

<p>수학에서 벡터를 표현할 때 열벡터를 기본 방향으로 보는 것이 더 통용되는 방법이다. 다시 말해, 임의의 $n$ 차원 벡터 $x$는 다음과 같이 표현하는 것이 일반적이다.</p>

\[\vec{x}=\begin{bmatrix}x_1 \\ x_2 \\ \vdots \\x_n\end{bmatrix} % 식 (1)\]

<p>이 경우 행렬은 벡터의 왼쪽으로 들어가야 한다. 임의의 $n\times n$ 차원의 행렬 $A$와 $n$ 차원 열벡터 $x$의 곱은 다음과 같이 표현된다.</p>

\[Ax % 식 (2)\]

<p>또한, 열벡터 간의 내적은 전치 연산을 이용해 다음과 같이 쓸 수 있다. 임의의 $n$ 차원 벡터 $\vec x$와 $\vec y$에 대해,</p>

\[dot(\vec x, \vec y)=\vec x^T\vec y % 식 (3)\]

<p>그런데, 데이터 사이언스에서는 이유는 알 수 없으나 보통 데이터 하나를 행벡터로 취급해서 사용한다. 즉, 임의의 $d$ 차원 벡터 $x$는 다음과 같이 쓴다.</p>

\[\vec{x}=\begin{bmatrix}x_1 &amp; x_2 &amp; \cdots &amp; x_d\end{bmatrix}% 식 (4)\]

<p>이렇게 되면 행렬은 벡터의 오른쪽으로 와야 한다. 임의의 $d\times d$ 차원 행렬 $R$과 $d$ 차원 행벡터 $x$의 곱은 아래와 같이 쓸 수 있다.</p>

\[x R % 식 (5)\]

<p>또한, 행벡터 간의 내적은 마찬가지로 전치연산을 이용하나 전치 연산이 붙는 벡터는 오른쪽에 있는 것이다. 다시 말해, 임의의 $d$ 차원 행벡터 $\vec x$와 $\vec y$에 대해,</p>

\[dot(\vec x, \vec y)=\vec x \vec y^T % 식 (6)\]

<p>가 된다.</p>

<p>더 나아가 데이터 사이언스에서는 표본의 수가 $n$이고 특징(feature)의 수가 $d$라고 했을 때 데이터 셋 $\mathcal D$를 $n\times d$ 차원 행렬로 두는 것이 일반적이다. 즉, 표본 데이터가 더 추가 된다면 하나의 행이 더 늘어나는 것이다. 다시 말해 하나의 데이터를 “행벡터”로 취급하는 것이다.</p>

<p>본 포스팅에서는 벡터의 기본 방향이 “행벡터”로 설정되었다.</p>

<h1 id="맥락을-고려한-상대적인-거리">맥락을 고려한 상대적인 거리</h1>

<p>아래와 같이 두 벡터 $\vec x$와 $\vec y$를 생각해보자.</p>

<p align="center">
  <img width="600" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic2.png" />
  <br />
  그림 1. 공간 상의 두 벡터 간의 거리는 벡터의 내적을 이용해 계산할 수 있다.
</p>

<p>여기서 임의의 점 $\vec x$와 $\vec y$ 까지의 유클리드 거리를 계산하려면 어떤 식을 사용해야 할까? 두 벡터의 차와 내적을 이용해 계산할 수 있다. 이와 같은 거리를 유클리드 거리(Euclidean distance)라고 부른다.</p>

\[d_E = \sqrt{(\vec x-\vec y)(\vec x-\vec y)^T} % 식 (7)\]

<p>그런데 두 벡터 $\vec x$와 $\vec y$ 만을 생각하는 것이 아니라, 주변에 다른 데이터들을 고려한다면 두 점 사이의 거리는 항상 절대적인 거리를 사용해도 되는것일지 고민해보아야 한다.</p>

<p align="center">
  <img width="600" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic3.png" />
  <br />
  그림 2. 다른 데이터들의 맥락을 고려한 두 점 사이의 거리는 다르게 계산되어야 할 수도 있다.
</p>

<p>위 그림을 보면 (a)는 파란색 데이터의 분포에서 상당히 벗어나있는 점들이라는 것을 알 수 있다. 반면에 (b)는 파란색 데이터의 분포에서 상대적으로 덜 벗어난 곳에 위치해있다. 즉, 다른 데이터들의 분포의 “맥락”을 고려하면 그림 2의 (a)에 있는 두 벡터 $\vec x$와 $\vec y$ 간의 거리가 그림 (b)에 있는 두 벡터 간의 거리보다 더 멀다고 볼 수도 있는 것이다.</p>

<p>“맥락”이라는 모호한 표현을 조금 더 수학적으로 표현하면 “표준편차”라고도 할 수 있겠다. 만약 데이터의 분포를 정규분포의 형태라고 가정할 수 있다면 정규분포의 표준 편차의 성질을 이용해 다음과 같이 평균(중심)으로부터 1, 2, 3 표준편차 만큼 떨어진 곳에 68, 95, 99.7%만큼의 데이터가 들어온다는 사실을 이용해보자.</p>

<p align="center">
  <img width="600" src="https://upload.wikimedia.org/wikipedia/commons/2/22/Empirical_rule_histogram.svg" />
 <br />
 그림 3. 정규 분포에서 중심으로부터 1, 2, 3 표준편차 만큼 멀어질 때 얼마만큼의 데이터가 포함되는가? (68–95–99.7 rule)
</p>

<p>다시 말해, 아래의 그림과 같이 표준편차를 기준삼아 표준편차 등고선을 표시할 수 있다. 그리고 이 등고선이 “맥락을 고려한” 거리의 지표가 되는 것이다.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic6.png" />
 <br />
 그림 4. 평균으로부터 68, 95, 99.7% 등 표준편차 만큼 떨어진 거리를 등고선으로 표시한 그림
</p>

<p>그리고 정규 분포 대신 표준 정규분포를 사용할 수 있는 것 처럼 그림 4의 (b)에 있는 타원의 형태를 그림 4의 (a)에 있는 단위원으로 축소시킨다면 “맥락” 즉, 표준 편차를 정규화 시킬 수 있다. 아래의 그림 5와 같이 표준편차 1, 2, 3 등에 해당하는 곳에 새로운 축을 고려한 뒤에 벡터 공간을 변형해 타원을 단위원 모양으로 다시 되돌려보자.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic7.png" />
 <br />
 그림 5. 데이터의 "맥락"의 표현과 "맥락"을 "정규화" 하기 위한 데이터(벡터) 공간의 변형
</p>

<p>이 과정은 이 포스팅의 가장 위에 있는 애플릿에서 수행하는 일이다. 아래의 그림 6의 왼쪽을 보자. 주어진 데이터의 “맥락”을 고려했을 때 주황색 점들보다는 노란색 점들이 더 먼 거리라고 판단해주어야 한다. 이것은 맥락을 생각한 채로 유클리드 거리를 계산해야 하므로 복잡한 일이다. 그런데, 그림 6의 오른쪽과 같이 “맥락”을 정규화시키면 단순히 유클리드 거리만 계산한 결과로도 노란색 점들 간의 거리가 더 멀다. “정규화” 과정에서 이미 주어진 데이터에 대한 “맥락”을 고려시켜 기존의 데이터(벡터) 공간을 변형시켰기 때문이다.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic8.png" />
 <br />
 그림 6. "맥락"을 정규화 시키고나서 측정한 유클리드 거리는 이미 맥락을 고려한 거리가 된다.
</p>

<p>주어진 데이터들의 분포를 통해 맥락을 조사하고, 이를 정규화 한 뒤에 유클리드 거리를 계산하는 것이 마할라노비스(Mahalanobis) 거리이다.</p>

\[d_M = \sqrt{(\vec x-\vec y)\Sigma^{-1}(\vec x-\vec y)^T} % 식 (8)\]

<p>벡터 공간의 변형은 행렬로 표현할 수 있다. 특히, 데이터의 “맥락”을 표현하는 행렬은 공분산 행렬($\Sigma$)과 관련되어 있고, 그것을 다시 돌려 놓기 위한 행렬은 공분산 행렬의 역행렬($\Sigma^{-1}$)과 관련되어 있다. 지금부터는 수식적으로 데이터의 “맥락”을 파악하는 방법을 이해해보자. 또, “맥락”의 “정규화”를 수행하는 방법을 더 자세하게 다루어 보자.</p>

<h1 id="공분산-행렬과-그-역행렬의-의미">공분산 행렬과 그 역행렬의 의미</h1>

<h2 id="iid-정규분포-샘플-대한-기초적인-이해">iid 정규분포 샘플 대한 기초적인 이해</h2>

<p>데이터의 구조에 대해 이해하기에 앞서 우선 iid(independent and identically distributed) 정규 분포 샘플의 성질에 대해 이해할 필요가 있다. 용어는 어려워 보이지만 차근히 들여다보면 어려울 것이 하나도 없다. iid는 랜덤 데이터 샘플을 추출해내는 가장 단순한 방법론 중 하나이다.</p>

<p>iid를 풀어서 설명하자면 다음과 같은 가정(assumption)이다</p>

<ul>
  <li>추출된 데이터는 독립적으로 추출되었다.</li>
  <li>추출된 데이터는 모두 동일한 확률 분포에서 추출되었다.</li>
</ul>

<p>또, 여기서 추출된 확률 분포가 정규 분포라고 가정할 수 있다면 추출된 샘플은 “indenepdent and identically distributed normal random variables다” 라고 말 할 수 있는 것이다.</p>

<p>이번에는 $Z\in\mathbb{R}^{n\times d}$ 와 같이 여러개의 iid normal randon variables $z_1, \cdots ,z_d$를 좌우로 쌓아보자. 특히, 계산의 편의를 위해 표준 정규분포를 가정하자.</p>

\[Z =\begin{bmatrix} | &amp; | &amp; &amp; |\\ z_1 &amp; z_2 &amp; \cdots &amp; z_d\\ | &amp; | &amp; &amp; |\end{bmatrix} % 식 (9)\]

\[\text{where } z_1, z_2, \cdots, z_d \text{ are i.i.d. normal random variables with mean 0 and variance 1}\notag\]

<p>표준 정규분포에서 추출한 샘플들이므로 아래의 사실을 확인할 수 있다. 추출한 분포의 평균이 0이라는 점을 생각하면,</p>

\[\mathbb{E}\left[z_i\right]=0 \text{ for } i = 1, 2, \cdots, d % 식 (10)\]

<p>이다.</p>

<p>또한 추출한 분포의 분산이 1이라는 것을 생각하여 아래에 대해서도 생각해보자.</p>

\[\mathbb{E}\left[Z^TZ\right]

= \mathbb{E}\left [\begin{bmatrix}
  z_1^T z_1 &amp; z_1^T z_2 &amp; \cdots &amp; z_1^Tz_d \\ 
  z_2^T z_1 &amp; z_2^T z_2 &amp; \cdots &amp; z_2^T z_d \\
  \vdots    &amp; \vdots    &amp; \ddots &amp; \vdots \\
  z_d^T z_1 &amp; z_d^T z_2 &amp; \cdots &amp; z_d^Tz_d
  \end{bmatrix}\right ] % 식 (11)\]

<p>여기서 $i=1,2,\cdots, d$에 대해 $\mathbb{E}\left[z_i^T z_i \right]$는 분산 $1$이 $n$ 개 더해진 것과 같으므로 $\mathbb{E}\left[z_i^T z_i \right]=n$이다. 또, $z_i$는 독립적으로 추출되었으므로 서로 다른 $i$와 $j$에 대해 $\mathbb E \left[z_i^T z_j \right]=0$ 이다.</p>

<p>따라서 식 (11)은</p>

\[식 (11) \Rightarrow \begin{bmatrix}
  n &amp; 0 &amp; \cdots &amp; 0 \\ 
  0 &amp; n &amp; \cdots &amp; 0 \\
  \vdots    &amp; \vdots    &amp; \ddots &amp; \vdots \\
  0 &amp; 0 &amp; \cdots &amp; n
  \end{bmatrix} = n I % 식 (12)\]

<p>와 같다. 여기서 $I$는 $d\times d$ 차원의 단위행렬이다.</p>

<h2 id="주어진-데이터를-이해하는-또-다른-방법">주어진 데이터를 이해하는 또 다른 방법</h2>

<p>화성에 사는 외계인 중 1000명을 임의로 선별해 키와 몸무게를 조사했고 이것을 표로 나타내보았다. 놀랍게도 평균키는 10cm이고 평균 몸무게는 8kg이었다고 한다. 표로 정리해보면 대략 아래와 같았다고 하자.</p>

<p align="center">
  <img width="300" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic_table1.png" />
 <br />
 그림 8. 화성 외계인들의 키와 몸무게를 정리한 표 (4번 외계인까지만 반올림하여 표시함)
</p>

<p>1000명 외계인들의 키와 몸무게 데이터는 <a href="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/alien_height_weight.csv">여기</a>서 받을 수 있다.</p>

<p>키와 몸무게를 정리한 데이터를 $\mathcal D$라고 하자. 또, 표본이 된 외계인의 수를 $n$이라고 하고 키와 몸무게와 같은 특징의 숫자를 $d$라고 하면 $\mathcal D$는 다음과 같은 행렬이라고도 볼 수 있다.</p>

\[\mathcal D\in\mathbb{R}^{n\times d} % 식 (13)\]

<p>이번에는 임의의 1000명 외계인의 키와 몸무게라는 데이터를 이용했지만 어떤 데이터든지 분포를 확인할 수 있다. “새로운” 관점에서 데이터 분포를 이해해보기 위해 데이터셋의 각 feature 별 평균값을 모두 0으로 이동시키자. 그리고 feature 별 평균값이 모두 0인 새로운 데이터를 데이터 $X$로 보자.</p>

<p>$\mathcal D$와 $X$의 분포를 그려보면 다음과 같다.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic_move_distribution.png" />
 <br />
 그림 9. 화성 외계인들의 키와 몸무게 데이터의 분포
</p>

<p>이제 우리는 데이터 $X$를 다음과 같이 “새롭게” 이해해보자. $X$는 원시 데이터 $Z$가 있으며 이것이 선형변환된 결과물이라고 보는 것이다. 여기서 선형변환 $R$ 행렬이 $Z$의 오른쪽에 붙는 것은 식 (5)에서 보여준 것과 같이 벡터의 기본 방향을 행벡터로 보기 때문이다.</p>

\[X = ZR % 식 (14)\]

\[\text{ where }Z \in \mathbb{R}^{n\times d} \text{ and } R \in \mathbb{R}^{d\times d}\notag\]

<p>그리고 $Z$의 모든 열은 iid(independent and identically distributed) 표준 정규분포에서부터 추출한 데이터셋이라고 보자.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic10.png" />
 <br />
 그림 10. 주어진 데이터를 일부 수정한 $X$를 원시 형태의 데이터 $Z$로부터 선형변환 된 결과로 보자.
</p>

<p>이제부터 feature 간의 닮음을 조사하자. feature의 닮음을 조사한다면 데이터의 “맥락” 혹은 형태 구조를 파악할 수 있다. 왜냐하면, 가령, feature 1과 feature 2가 많이 닮아있다면 서로 상관관계가 높은 것을 의미하기 때문이다.이를 위해 $X^TX$를 계산하자. $X^TX$는 $d\times d$ 차원을 가지게 될 것인데, 이는 feature들 간의 내적을 표현한 것임을 알 수 있다. 만약 $XX^T$를 계산한다면 이것은 데이터들 간의 닮음을 파악한 것임을 예상할 수 있다. $X^TX$를 계산하는 과정을 아래 그림에서 확인해보자.</p>

<p align="center">
  <img width="500" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2019-07-27_PCA/XTX.png" />
  <br />
  그림 11. 공분산 행렬을 계산하기 위해 각 데이터 특징들의 변동이 서로 얼마나 닮았는지 계산하는 과정.
</p>

<p>여기서 다시 한번 식 (14)을 이용해보면,</p>

\[X^TX=(ZR)^TZR=R^TZ^TZR=R^T(Z^TZ)R % 식 (15)\]

<p>여기서 식 (12)에 따라,</p>

\[X^TX \approx R^T(nI)R=nR^TR % 식 (16)\]

<p>가 성립하게 된다. 여기서 “$\approx$”를 쓴 것은 실제 데이터에서는 기댓값과 정확히 같은 값이 나오지 않기 때문에 사용하였다. 그리고 아래와 같은 사실을 확인할 수 있다.</p>

\[R^TR\approx \frac{1}{n}X^TX % 식 (17)\]

<p>결국 식 (17)이 의미하는 것은 무엇인가? 식 (17)은 데이터 $X$의 형태 구조 혹은 데이터의 “맥락”를 얻기 위한 방법이다. 이것은 원시 형태의 $Z$를 주어진 데이터 $X$ 로 변환하기 위한 선형변환 $R$에 대한 $R^TR$와 거의 같다. 그리고 식 (17)의 형태 구조를 표현하는 행렬을 공분산 행렬이라고 부른다. 여기서는 공분산 행렬을 $\Sigma$라고 쓰도록 하자.</p>

\[\Sigma = \frac{1}{n}X^TX % 식 (18)\]

<p>참고로 $n$ 대신 $n-1$로 나누는 방법도 있다. $n$ 대신 $n-1$로 나누어 얻게 되는 공분산 행렬은 표본 공분산 행렬이라고 한다.</p>

<p>공분산 행렬은 데이터 셋 전체의 전반적 구조에 대해 설명하기에 용이한 방법이며 특히 다변수 정규 분포와 밀접한 관련이 있다. 만약 feature 가 두 개인 데이터셋이 2변수 정규 분포를 따른다고 하면 크게 아래와 같은 세 종류 중 하나의 형태를 따른다고 볼 수 있다.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/types_of_bivariate_gaussian.png" />
 <br />
 그림 12. 가장 대표적인 세 가지 형태의 2변수 정규 분포
</p>

<p>공분산 행렬의 각 원소가 뜻하는 바는 각 feature들의 분산 혹은 공분산이다. 다시 말해, 그림 12와 같이 feature가 2개인 경우 1번 feature와 2번 feature가 각각 x 축 방향, y 축 방향으로 얼마나 데이터들이 퍼져서 분포하는지, 그리고 1번, 2번 feature가 얼마나 함께 변하는지를 나타내는 것이다.</p>

<p align="center">
  <img width="400" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/meaning_of_cov_mtx.png" />
 <br />
 그림 13. 공분산 행렬의 각 원소가 의미하는 것
</p>

<h2 id="역행렬과-맥락의-정규화">역행렬과 맥락의 정규화</h2>

<p>주어진 임의의 데이터를 $x$라고 하고 이의 원시 형태를 $z$라고 했을 때, 식 (14)에 따르면 주어진 데이터의 “맥락”을 원시 데이터의 형태로 되돌려 놓기 위해선 아래와 같이 수행하여 가능하다는 것을 알 수 있다.</p>

\[z=xR^{-1}\]

<p>여기서 역행렬을 이용한 선형변환은 주어진 선형변환 $R$에 의해 변환된 벡터 공간을 원래 형태로 돌려 놓는 것이다. 즉 그림 10에서 왼쪽으로부터 오른쪽으로 변하는 과정이 원래의 선형 변환 $R$이 수행해주는 변환이라고 하면, 역변환인 $R^{-1}$은 그림 10의 오른족에서 왼쪽으로의 변환이라고 볼 수 있는 것이다.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/inverse_of_pic10.png" />
 <br />
 그림 14. 행렬 R과 그 역행렬이 의미하는 선형 변환
</p>

<p>여기서, 식 (7)을 적용해 원시 데이터의 벡터 공간에서 원점과의 거리 $d_z$를 구하면 다음과 같다.</p>

\[d_z=\sqrt{zz^T}=\sqrt{(xR^{-1})(xR^{-1})^T}\]

\[=\sqrt{xR^{-1}(R^{-1})^Tx^T}=\sqrt{x(R^TR)^{-1}x^T}=\sqrt{x\Sigma^{-1}x^T}\]

<p>여기서 $\Sigma$는 주어진 전체 데이터 행렬의 공분산행렬이다.</p>

<p>만약 위와 같은 과정을 임의의 벡터 $x$와 $y$ 사이의 거리에 대해 수행한다고 하면 아래와 같이 식을 수정할 수 있으며 이것은 원래 언급했던 마할라노비스 거리와 같다.</p>

\[\Rightarrow \sqrt{(x-y)\Sigma^{-1}(x-y)^T}\]

<h1 id="등고선과-주축-고윳값-고유벡터">등고선과 주축: 고윳값, 고유벡터</h1>

<p>※ 마지막 챕터는 다소 심화된 내용이며 꼭 이해하지 않아도 마할라노비스의 큰 의미를 이해하는데에는 문제 없습니다.</p>

<p>※ 아래의 내용을 더 잘 이해하기 위해선 아래의 내용을 이해하고 오는 것이 좋습니다.</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2019/07/17/eigen_vector.html">고윳값과 고유벡터</a></li>
  <li><a href="https://angeloyeo.github.io/2020/11/19/eigen_decomposition.html">고윳값 분해</a></li>
</ul>

<p>이번에는 그림 3, 4 에서 소개한 바와 같이 데이터의 “맥락”을 파악하기 위한 표준 편차와 “등고선” 애기를 더 해보도록 하자. 마할라노비스 거리를 이해하는데 있어서 “등고선” 얘기는 아주 중요한 핵심 중 하나이다.</p>

<p>우선, 그림 12을 다시 살펴보자. 그림 12는 2변수 정규 분포가 가질 수 있는 대표적인 세 가지 분포 형태를 나타낸 그림이다. 그런데, 분포의 형태가 꼭 이렇게 세 가지 뿐일까? 아마 그렇지 않을 것이다. 분포의 모양이 얼마나 회전했는지, 얼마나 늘어져있는지 두 가지를 가지고 표현한다면 무수하게 많은 분포의 형태가 나올 것이라는 것을 알 수 있다. 다시 말해, 다변수 정규분포로 표현할 수 있는 임의의 분포는 표준 정규 분포를 늘리고 회전해서 얻어낼 수 있다고도 볼 수 있는 것이다.</p>

<p>주어진 선형변환을 얼마나 회전했는지와 얼마나 늘어났는지로 표현하는 방법은 바로 <a href="https://angeloyeo.github.io/2020/11/19/eigen_decomposition.html">고윳값 분해</a>이다. 그리고 회전한 양은 그림 5의 오른쪽에서 보여주는 새로운 축의 방향을 나타내 줄 것이고 늘어난 양은 새로운 축들의 눈금 한 칸의 길이를 나타내 줄 것이다. 또한, <a href="https://angeloyeo.github.io/2020/11/19/eigen_decomposition.html">고윳값 분해</a> 편에서 논의한 것 처럼 회전 방향은 고유벡터로, 늘어난 양은 고윳값으로 표현될 것이다.</p>

<p>공분산 행렬을 다음과 같이 고윳값 분해해보자.</p>

\[\Sigma = Q\Lambda Q^{-1}=Q\Lambda Q^T\]

<p>여기서 공분산 행렬은 항상 대칭행렬이므로 $Q^{-1}$은 $Q^T$로 쓸 수 있다는 점을 이용해 $Q^{-1}$ 을 $Q^T$로 대체했다.</p>

<p>여기서 $Q$와 $\Lambda$는 각각 고유벡터, 고윳값을 가지고 있는 행렬이다.</p>

<p>예를 들어 그림 12의 첫 번째 그림에 있는 공분산 행렬을 고윳값 분해하면 다음과 같은 결과를 얻을 수 있다.</p>

\[\begin{bmatrix}1 &amp; 0.5\\0.5 &amp; 1.5\end{bmatrix}=\begin{bmatrix}-0.8507 &amp; 0.5257 \\ 0.5257 &amp; 0.8507\end{bmatrix}\begin{bmatrix}0.6910 &amp; 0 \\ 0 &amp; 1.8090\end{bmatrix}\begin{bmatrix}-0.8507 &amp; 0.5257 \\ 0.5257 &amp; 0.8507\end{bmatrix}^T\]

<p>그리고 $Q$의 각 열은 얼마만큼 표준 정규 분포를 회전했는지에 관한 정보를 보여주며, 좀 더 정확하게는 주성분(principal component, PC)의 방향을 나타내준다. 또, $\Lambda$의 대각성분들은 각 주성분 방향으로 얼마만큼 분포가 늘어져있는지를 보여준다. 아래의 그림 15를 참고하여 더 시각적으로 이해해보자.</p>

<p align="center">
  <img width="600" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/principal_axis.png" />
 <br />
 그림 15. 공분산 행렬의 고윳값 분해 결과는 표준 정규 분포를 얼마나 늘리고 회전했는지를 벡터로 표현해줄 수 있게 해준다. 여기서 $\sigma_1$과 $\sigma_2$는 각각 PC1과 PC2가 늘어난 정도를 의미한다.
</p>

<p>이 결과를 다시 한번 설명하자면 그림 3에서 그림 5까지의 내용을 더 수학적으로 표현해준 것과 같다. $Q$의 주성분 방향은 표준편차를 계산할 가장 대표적인 방향 두 가지가 되는 것이며, $\Lambda$의 대각성분은 다시 말해 주성분 방향으로의 표준편차를 의미하게 된다.</p>

<p>따라서, 주축 상에 있는 데이터들을 중심으로 마할라노비스 거리를 이해한다면 (혹은 데이터들을 주축에 정사영 시키는 경우를 가정한다면) 주축을 원래의 xy 축으로 역 회전시키고 $\Lambda$로부터 얻은 표준편차 값으로 나눠주어 정규화시킨 거리를 의미한다고도 볼 수 있는 것이다.</p>

<p align="center">
<iframe width="560" height="315" src="https://www.youtube.com/embed/afLiJWeeqmY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</p>]]></content><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><category term="선형대수학" /><category term="통계학" /><summary type="html"><![CDATA[※ 본 포스팅에서는 벡터의 기본 방향을 “행벡터”로 보고 작성하였습니다. 이에 대한 더 자세한 설명은 첫 꼭지 “행벡터를 기본 방향으로 하는 데이터 표현” 챕터를 읽어주십시오. Prerequisites 본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다. 행렬과 선형변환 공분산 행렬에 대한 더 친절한 설명이 필요한 경우 아래의 포스트를 확인하십시오. 주성분 분석(PCA) 행벡터를 기본 방향으로 하는 데이터 표현 수학에서 벡터를 표현할 때 열벡터를 기본 방향으로 보는 것이 더 통용되는 방법이다. 다시 말해, 임의의 $n$ 차원 벡터 $x$는 다음과 같이 표현하는 것이 일반적이다. \[\vec{x}=\begin{bmatrix}x_1 \\ x_2 \\ \vdots \\x_n\end{bmatrix} % 식 (1)\] 이 경우 행렬은 벡터의 왼쪽으로 들어가야 한다. 임의의 $n\times n$ 차원의 행렬 $A$와 $n$ 차원 열벡터 $x$의 곱은 다음과 같이 표현된다. \[Ax % 식 (2)\] 또한, 열벡터 간의 내적은 전치 연산을 이용해 다음과 같이 쓸 수 있다. 임의의 $n$ 차원 벡터 $\vec x$와 $\vec y$에 대해, \[dot(\vec x, \vec y)=\vec x^T\vec y % 식 (3)\] 그런데, 데이터 사이언스에서는 이유는 알 수 없으나 보통 데이터 하나를 행벡터로 취급해서 사용한다. 즉, 임의의 $d$ 차원 벡터 $x$는 다음과 같이 쓴다. \[\vec{x}=\begin{bmatrix}x_1 &amp; x_2 &amp; \cdots &amp; x_d\end{bmatrix}% 식 (4)\] 이렇게 되면 행렬은 벡터의 오른쪽으로 와야 한다. 임의의 $d\times d$ 차원 행렬 $R$과 $d$ 차원 행벡터 $x$의 곱은 아래와 같이 쓸 수 있다. \[x R % 식 (5)\] 또한, 행벡터 간의 내적은 마찬가지로 전치연산을 이용하나 전치 연산이 붙는 벡터는 오른쪽에 있는 것이다. 다시 말해, 임의의 $d$ 차원 행벡터 $\vec x$와 $\vec y$에 대해, \[dot(\vec x, \vec y)=\vec x \vec y^T % 식 (6)\] 가 된다. 더 나아가 데이터 사이언스에서는 표본의 수가 $n$이고 특징(feature)의 수가 $d$라고 했을 때 데이터 셋 $\mathcal D$를 $n\times d$ 차원 행렬로 두는 것이 일반적이다. 즉, 표본 데이터가 더 추가 된다면 하나의 행이 더 늘어나는 것이다. 다시 말해 하나의 데이터를 “행벡터”로 취급하는 것이다. 본 포스팅에서는 벡터의 기본 방향이 “행벡터”로 설정되었다. 맥락을 고려한 상대적인 거리 아래와 같이 두 벡터 $\vec x$와 $\vec y$를 생각해보자. 그림 1. 공간 상의 두 벡터 간의 거리는 벡터의 내적을 이용해 계산할 수 있다. 여기서 임의의 점 $\vec x$와 $\vec y$ 까지의 유클리드 거리를 계산하려면 어떤 식을 사용해야 할까? 두 벡터의 차와 내적을 이용해 계산할 수 있다. 이와 같은 거리를 유클리드 거리(Euclidean distance)라고 부른다. \[d_E = \sqrt{(\vec x-\vec y)(\vec x-\vec y)^T} % 식 (7)\] 그런데 두 벡터 $\vec x$와 $\vec y$ 만을 생각하는 것이 아니라, 주변에 다른 데이터들을 고려한다면 두 점 사이의 거리는 항상 절대적인 거리를 사용해도 되는것일지 고민해보아야 한다. 그림 2. 다른 데이터들의 맥락을 고려한 두 점 사이의 거리는 다르게 계산되어야 할 수도 있다. 위 그림을 보면 (a)는 파란색 데이터의 분포에서 상당히 벗어나있는 점들이라는 것을 알 수 있다. 반면에 (b)는 파란색 데이터의 분포에서 상대적으로 덜 벗어난 곳에 위치해있다. 즉, 다른 데이터들의 분포의 “맥락”을 고려하면 그림 2의 (a)에 있는 두 벡터 $\vec x$와 $\vec y$ 간의 거리가 그림 (b)에 있는 두 벡터 간의 거리보다 더 멀다고 볼 수도 있는 것이다. “맥락”이라는 모호한 표현을 조금 더 수학적으로 표현하면 “표준편차”라고도 할 수 있겠다. 만약 데이터의 분포를 정규분포의 형태라고 가정할 수 있다면 정규분포의 표준 편차의 성질을 이용해 다음과 같이 평균(중심)으로부터 1, 2, 3 표준편차 만큼 떨어진 곳에 68, 95, 99.7%만큼의 데이터가 들어온다는 사실을 이용해보자. 그림 3. 정규 분포에서 중심으로부터 1, 2, 3 표준편차 만큼 멀어질 때 얼마만큼의 데이터가 포함되는가? (68–95–99.7 rule) 다시 말해, 아래의 그림과 같이 표준편차를 기준삼아 표준편차 등고선을 표시할 수 있다. 그리고 이 등고선이 “맥락을 고려한” 거리의 지표가 되는 것이다. 그림 4. 평균으로부터 68, 95, 99.7% 등 표준편차 만큼 떨어진 거리를 등고선으로 표시한 그림 그리고 정규 분포 대신 표준 정규분포를 사용할 수 있는 것 처럼 그림 4의 (b)에 있는 타원의 형태를 그림 4의 (a)에 있는 단위원으로 축소시킨다면 “맥락” 즉, 표준 편차를 정규화 시킬 수 있다. 아래의 그림 5와 같이 표준편차 1, 2, 3 등에 해당하는 곳에 새로운 축을 고려한 뒤에 벡터 공간을 변형해 타원을 단위원 모양으로 다시 되돌려보자. 그림 5. 데이터의 "맥락"의 표현과 "맥락"을 "정규화" 하기 위한 데이터(벡터) 공간의 변형 이 과정은 이 포스팅의 가장 위에 있는 애플릿에서 수행하는 일이다. 아래의 그림 6의 왼쪽을 보자. 주어진 데이터의 “맥락”을 고려했을 때 주황색 점들보다는 노란색 점들이 더 먼 거리라고 판단해주어야 한다. 이것은 맥락을 생각한 채로 유클리드 거리를 계산해야 하므로 복잡한 일이다. 그런데, 그림 6의 오른쪽과 같이 “맥락”을 정규화시키면 단순히 유클리드 거리만 계산한 결과로도 노란색 점들 간의 거리가 더 멀다. “정규화” 과정에서 이미 주어진 데이터에 대한 “맥락”을 고려시켜 기존의 데이터(벡터) 공간을 변형시켰기 때문이다. 그림 6. "맥락"을 정규화 시키고나서 측정한 유클리드 거리는 이미 맥락을 고려한 거리가 된다. 주어진 데이터들의 분포를 통해 맥락을 조사하고, 이를 정규화 한 뒤에 유클리드 거리를 계산하는 것이 마할라노비스(Mahalanobis) 거리이다. \[d_M = \sqrt{(\vec x-\vec y)\Sigma^{-1}(\vec x-\vec y)^T} % 식 (8)\] 벡터 공간의 변형은 행렬로 표현할 수 있다. 특히, 데이터의 “맥락”을 표현하는 행렬은 공분산 행렬($\Sigma$)과 관련되어 있고, 그것을 다시 돌려 놓기 위한 행렬은 공분산 행렬의 역행렬($\Sigma^{-1}$)과 관련되어 있다. 지금부터는 수식적으로 데이터의 “맥락”을 파악하는 방법을 이해해보자. 또, “맥락”의 “정규화”를 수행하는 방법을 더 자세하게 다루어 보자. 공분산 행렬과 그 역행렬의 의미 iid 정규분포 샘플 대한 기초적인 이해 데이터의 구조에 대해 이해하기에 앞서 우선 iid(independent and identically distributed) 정규 분포 샘플의 성질에 대해 이해할 필요가 있다. 용어는 어려워 보이지만 차근히 들여다보면 어려울 것이 하나도 없다. iid는 랜덤 데이터 샘플을 추출해내는 가장 단순한 방법론 중 하나이다. iid를 풀어서 설명하자면 다음과 같은 가정(assumption)이다 추출된 데이터는 독립적으로 추출되었다. 추출된 데이터는 모두 동일한 확률 분포에서 추출되었다. 또, 여기서 추출된 확률 분포가 정규 분포라고 가정할 수 있다면 추출된 샘플은 “indenepdent and identically distributed normal random variables다” 라고 말 할 수 있는 것이다. 이번에는 $Z\in\mathbb{R}^{n\times d}$ 와 같이 여러개의 iid normal randon variables $z_1, \cdots ,z_d$를 좌우로 쌓아보자. 특히, 계산의 편의를 위해 표준 정규분포를 가정하자. \[Z =\begin{bmatrix} | &amp; | &amp; &amp; |\\ z_1 &amp; z_2 &amp; \cdots &amp; z_d\\ | &amp; | &amp; &amp; |\end{bmatrix} % 식 (9)\] \[\text{where } z_1, z_2, \cdots, z_d \text{ are i.i.d. normal random variables with mean 0 and variance 1}\notag\] 표준 정규분포에서 추출한 샘플들이므로 아래의 사실을 확인할 수 있다. 추출한 분포의 평균이 0이라는 점을 생각하면, \[\mathbb{E}\left[z_i\right]=0 \text{ for } i = 1, 2, \cdots, d % 식 (10)\] 이다. 또한 추출한 분포의 분산이 1이라는 것을 생각하여 아래에 대해서도 생각해보자. \[\mathbb{E}\left[Z^TZ\right] = \mathbb{E}\left [\begin{bmatrix} z_1^T z_1 &amp; z_1^T z_2 &amp; \cdots &amp; z_1^Tz_d \\ z_2^T z_1 &amp; z_2^T z_2 &amp; \cdots &amp; z_2^T z_d \\ \vdots &amp; \vdots &amp; \ddots &amp; \vdots \\ z_d^T z_1 &amp; z_d^T z_2 &amp; \cdots &amp; z_d^Tz_d \end{bmatrix}\right ] % 식 (11)\] 여기서 $i=1,2,\cdots, d$에 대해 $\mathbb{E}\left[z_i^T z_i \right]$는 분산 $1$이 $n$ 개 더해진 것과 같으므로 $\mathbb{E}\left[z_i^T z_i \right]=n$이다. 또, $z_i$는 독립적으로 추출되었으므로 서로 다른 $i$와 $j$에 대해 $\mathbb E \left[z_i^T z_j \right]=0$ 이다. 따라서 식 (11)은 \[식 (11) \Rightarrow \begin{bmatrix} n &amp; 0 &amp; \cdots &amp; 0 \\ 0 &amp; n &amp; \cdots &amp; 0 \\ \vdots &amp; \vdots &amp; \ddots &amp; \vdots \\ 0 &amp; 0 &amp; \cdots &amp; n \end{bmatrix} = n I % 식 (12)\] 와 같다. 여기서 $I$는 $d\times d$ 차원의 단위행렬이다. 주어진 데이터를 이해하는 또 다른 방법 화성에 사는 외계인 중 1000명을 임의로 선별해 키와 몸무게를 조사했고 이것을 표로 나타내보았다. 놀랍게도 평균키는 10cm이고 평균 몸무게는 8kg이었다고 한다. 표로 정리해보면 대략 아래와 같았다고 하자. 그림 8. 화성 외계인들의 키와 몸무게를 정리한 표 (4번 외계인까지만 반올림하여 표시함) 1000명 외계인들의 키와 몸무게 데이터는 여기서 받을 수 있다. 키와 몸무게를 정리한 데이터를 $\mathcal D$라고 하자. 또, 표본이 된 외계인의 수를 $n$이라고 하고 키와 몸무게와 같은 특징의 숫자를 $d$라고 하면 $\mathcal D$는 다음과 같은 행렬이라고도 볼 수 있다. \[\mathcal D\in\mathbb{R}^{n\times d} % 식 (13)\] 이번에는 임의의 1000명 외계인의 키와 몸무게라는 데이터를 이용했지만 어떤 데이터든지 분포를 확인할 수 있다. “새로운” 관점에서 데이터 분포를 이해해보기 위해 데이터셋의 각 feature 별 평균값을 모두 0으로 이동시키자. 그리고 feature 별 평균값이 모두 0인 새로운 데이터를 데이터 $X$로 보자. $\mathcal D$와 $X$의 분포를 그려보면 다음과 같다. 그림 9. 화성 외계인들의 키와 몸무게 데이터의 분포 이제 우리는 데이터 $X$를 다음과 같이 “새롭게” 이해해보자. $X$는 원시 데이터 $Z$가 있으며 이것이 선형변환된 결과물이라고 보는 것이다. 여기서 선형변환 $R$ 행렬이 $Z$의 오른쪽에 붙는 것은 식 (5)에서 보여준 것과 같이 벡터의 기본 방향을 행벡터로 보기 때문이다. \[X = ZR % 식 (14)\] \[\text{ where }Z \in \mathbb{R}^{n\times d} \text{ and } R \in \mathbb{R}^{d\times d}\notag\] 그리고 $Z$의 모든 열은 iid(independent and identically distributed) 표준 정규분포에서부터 추출한 데이터셋이라고 보자. 그림 10. 주어진 데이터를 일부 수정한 $X$를 원시 형태의 데이터 $Z$로부터 선형변환 된 결과로 보자. 이제부터 feature 간의 닮음을 조사하자. feature의 닮음을 조사한다면 데이터의 “맥락” 혹은 형태 구조를 파악할 수 있다. 왜냐하면, 가령, feature 1과 feature 2가 많이 닮아있다면 서로 상관관계가 높은 것을 의미하기 때문이다.이를 위해 $X^TX$를 계산하자. $X^TX$는 $d\times d$ 차원을 가지게 될 것인데, 이는 feature들 간의 내적을 표현한 것임을 알 수 있다. 만약 $XX^T$를 계산한다면 이것은 데이터들 간의 닮음을 파악한 것임을 예상할 수 있다. $X^TX$를 계산하는 과정을 아래 그림에서 확인해보자. 그림 11. 공분산 행렬을 계산하기 위해 각 데이터 특징들의 변동이 서로 얼마나 닮았는지 계산하는 과정. 여기서 다시 한번 식 (14)을 이용해보면, \[X^TX=(ZR)^TZR=R^TZ^TZR=R^T(Z^TZ)R % 식 (15)\] 여기서 식 (12)에 따라, \[X^TX \approx R^T(nI)R=nR^TR % 식 (16)\] 가 성립하게 된다. 여기서 “$\approx$”를 쓴 것은 실제 데이터에서는 기댓값과 정확히 같은 값이 나오지 않기 때문에 사용하였다. 그리고 아래와 같은 사실을 확인할 수 있다. \[R^TR\approx \frac{1}{n}X^TX % 식 (17)\] 결국 식 (17)이 의미하는 것은 무엇인가? 식 (17)은 데이터 $X$의 형태 구조 혹은 데이터의 “맥락”를 얻기 위한 방법이다. 이것은 원시 형태의 $Z$를 주어진 데이터 $X$ 로 변환하기 위한 선형변환 $R$에 대한 $R^TR$와 거의 같다. 그리고 식 (17)의 형태 구조를 표현하는 행렬을 공분산 행렬이라고 부른다. 여기서는 공분산 행렬을 $\Sigma$라고 쓰도록 하자. \[\Sigma = \frac{1}{n}X^TX % 식 (18)\] 참고로 $n$ 대신 $n-1$로 나누는 방법도 있다. $n$ 대신 $n-1$로 나누어 얻게 되는 공분산 행렬은 표본 공분산 행렬이라고 한다. 공분산 행렬은 데이터 셋 전체의 전반적 구조에 대해 설명하기에 용이한 방법이며 특히 다변수 정규 분포와 밀접한 관련이 있다. 만약 feature 가 두 개인 데이터셋이 2변수 정규 분포를 따른다고 하면 크게 아래와 같은 세 종류 중 하나의 형태를 따른다고 볼 수 있다. 그림 12. 가장 대표적인 세 가지 형태의 2변수 정규 분포 공분산 행렬의 각 원소가 뜻하는 바는 각 feature들의 분산 혹은 공분산이다. 다시 말해, 그림 12와 같이 feature가 2개인 경우 1번 feature와 2번 feature가 각각 x 축 방향, y 축 방향으로 얼마나 데이터들이 퍼져서 분포하는지, 그리고 1번, 2번 feature가 얼마나 함께 변하는지를 나타내는 것이다. 그림 13. 공분산 행렬의 각 원소가 의미하는 것 역행렬과 맥락의 정규화 주어진 임의의 데이터를 $x$라고 하고 이의 원시 형태를 $z$라고 했을 때, 식 (14)에 따르면 주어진 데이터의 “맥락”을 원시 데이터의 형태로 되돌려 놓기 위해선 아래와 같이 수행하여 가능하다는 것을 알 수 있다. \[z=xR^{-1}\] 여기서 역행렬을 이용한 선형변환은 주어진 선형변환 $R$에 의해 변환된 벡터 공간을 원래 형태로 돌려 놓는 것이다. 즉 그림 10에서 왼쪽으로부터 오른쪽으로 변하는 과정이 원래의 선형 변환 $R$이 수행해주는 변환이라고 하면, 역변환인 $R^{-1}$은 그림 10의 오른족에서 왼쪽으로의 변환이라고 볼 수 있는 것이다. 그림 14. 행렬 R과 그 역행렬이 의미하는 선형 변환 여기서, 식 (7)을 적용해 원시 데이터의 벡터 공간에서 원점과의 거리 $d_z$를 구하면 다음과 같다. \[d_z=\sqrt{zz^T}=\sqrt{(xR^{-1})(xR^{-1})^T}\] \[=\sqrt{xR^{-1}(R^{-1})^Tx^T}=\sqrt{x(R^TR)^{-1}x^T}=\sqrt{x\Sigma^{-1}x^T}\] 여기서 $\Sigma$는 주어진 전체 데이터 행렬의 공분산행렬이다. 만약 위와 같은 과정을 임의의 벡터 $x$와 $y$ 사이의 거리에 대해 수행한다고 하면 아래와 같이 식을 수정할 수 있으며 이것은 원래 언급했던 마할라노비스 거리와 같다. \[\Rightarrow \sqrt{(x-y)\Sigma^{-1}(x-y)^T}\] 등고선과 주축: 고윳값, 고유벡터 ※ 마지막 챕터는 다소 심화된 내용이며 꼭 이해하지 않아도 마할라노비스의 큰 의미를 이해하는데에는 문제 없습니다. ※ 아래의 내용을 더 잘 이해하기 위해선 아래의 내용을 이해하고 오는 것이 좋습니다. 고윳값과 고유벡터 고윳값 분해 이번에는 그림 3, 4 에서 소개한 바와 같이 데이터의 “맥락”을 파악하기 위한 표준 편차와 “등고선” 애기를 더 해보도록 하자. 마할라노비스 거리를 이해하는데 있어서 “등고선” 얘기는 아주 중요한 핵심 중 하나이다. 우선, 그림 12을 다시 살펴보자. 그림 12는 2변수 정규 분포가 가질 수 있는 대표적인 세 가지 분포 형태를 나타낸 그림이다. 그런데, 분포의 형태가 꼭 이렇게 세 가지 뿐일까? 아마 그렇지 않을 것이다. 분포의 모양이 얼마나 회전했는지, 얼마나 늘어져있는지 두 가지를 가지고 표현한다면 무수하게 많은 분포의 형태가 나올 것이라는 것을 알 수 있다. 다시 말해, 다변수 정규분포로 표현할 수 있는 임의의 분포는 표준 정규 분포를 늘리고 회전해서 얻어낼 수 있다고도 볼 수 있는 것이다. 주어진 선형변환을 얼마나 회전했는지와 얼마나 늘어났는지로 표현하는 방법은 바로 고윳값 분해이다. 그리고 회전한 양은 그림 5의 오른쪽에서 보여주는 새로운 축의 방향을 나타내 줄 것이고 늘어난 양은 새로운 축들의 눈금 한 칸의 길이를 나타내 줄 것이다. 또한, 고윳값 분해 편에서 논의한 것 처럼 회전 방향은 고유벡터로, 늘어난 양은 고윳값으로 표현될 것이다. 공분산 행렬을 다음과 같이 고윳값 분해해보자. \[\Sigma = Q\Lambda Q^{-1}=Q\Lambda Q^T\] 여기서 공분산 행렬은 항상 대칭행렬이므로 $Q^{-1}$은 $Q^T$로 쓸 수 있다는 점을 이용해 $Q^{-1}$ 을 $Q^T$로 대체했다. 여기서 $Q$와 $\Lambda$는 각각 고유벡터, 고윳값을 가지고 있는 행렬이다. 예를 들어 그림 12의 첫 번째 그림에 있는 공분산 행렬을 고윳값 분해하면 다음과 같은 결과를 얻을 수 있다. \[\begin{bmatrix}1 &amp; 0.5\\0.5 &amp; 1.5\end{bmatrix}=\begin{bmatrix}-0.8507 &amp; 0.5257 \\ 0.5257 &amp; 0.8507\end{bmatrix}\begin{bmatrix}0.6910 &amp; 0 \\ 0 &amp; 1.8090\end{bmatrix}\begin{bmatrix}-0.8507 &amp; 0.5257 \\ 0.5257 &amp; 0.8507\end{bmatrix}^T\] 그리고 $Q$의 각 열은 얼마만큼 표준 정규 분포를 회전했는지에 관한 정보를 보여주며, 좀 더 정확하게는 주성분(principal component, PC)의 방향을 나타내준다. 또, $\Lambda$의 대각성분들은 각 주성분 방향으로 얼마만큼 분포가 늘어져있는지를 보여준다. 아래의 그림 15를 참고하여 더 시각적으로 이해해보자. 그림 15. 공분산 행렬의 고윳값 분해 결과는 표준 정규 분포를 얼마나 늘리고 회전했는지를 벡터로 표현해줄 수 있게 해준다. 여기서 $\sigma_1$과 $\sigma_2$는 각각 PC1과 PC2가 늘어난 정도를 의미한다. 이 결과를 다시 한번 설명하자면 그림 3에서 그림 5까지의 내용을 더 수학적으로 표현해준 것과 같다. $Q$의 주성분 방향은 표준편차를 계산할 가장 대표적인 방향 두 가지가 되는 것이며, $\Lambda$의 대각성분은 다시 말해 주성분 방향으로의 표준편차를 의미하게 된다. 따라서, 주축 상에 있는 데이터들을 중심으로 마할라노비스 거리를 이해한다면 (혹은 데이터들을 주축에 정사영 시키는 경우를 가정한다면) 주축을 원래의 xy 축으로 역 회전시키고 $\Lambda$로부터 얻은 표준편차 값으로 나눠주어 정규화시킨 거리를 의미한다고도 볼 수 있는 것이다.]]></summary></entry><entry xml:lang="en"><title type="html">Mahalanobis Distance</title><link href="https://angeloyeo.github.io/2022/09/28/Mahalanobis_distance_en.html" rel="alternate" type="text/html" title="Mahalanobis Distance" /><published>2022-09-28T00:00:00+00:00</published><updated>2022-09-28T00:00:00+00:00</updated><id>https://angeloyeo.github.io/2022/09/28/Mahalanobis_distance_en</id><content type="html" xml:base="https://angeloyeo.github.io/2022/09/28/Mahalanobis_distance_en.html"><![CDATA[<p align="center"><iframe src="https://angeloyeo.github.io/p5/2022-09-28-Mahalanobis_distance/" width="650" height="520" frameborder="0"></iframe></p>

<p>※ In this post, vectors are represented using “row vectors” as the default direction. For more detailed explanation of this, please refer to the first section “Data representation using row vectors”.</p>

<h1 id="prerequisites">Prerequisites</h1>

<p>To better understand this post, it is recommended that you be familiar with the following content:</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2019/07/15/Matrix_as_Linear_Transformation_en.html">Matrix and Linear Transformations</a></li>
</ul>

<p>If you need a more detailed explanation of the covariance matrix, please refer to the following post:</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2019/07/27/PCA_en.html">Principal Component Analysis (PCA)</a></li>
</ul>

<h1 id="data-representation-using-row-vectors">Data representation using row vectors</h1>

<p>In mathematics, it is more common to view column vectors as the default direction when representing vectors. In other words, a vector $x$ of arbitrary dimension $n$ is usually represented as follows.</p>

\[\vec{x}=\begin{bmatrix}x_1 \\ x_2 \\ \vdots \\x_n\end{bmatrix} % Equation (1)\]

<p>In this case, the matrix must go to the left of the vector. The product of an arbitrary $n\times n$ dimensional matrix $A$ and an $n$ dimensional column vector $x$ is represented as follows.</p>

\[Ax % Equation (2)\]

<p>Furthermore, the dot product between column vectors can be expressed using the transpose operator as follows. For any $n$-dimensional vectors $\vec{x}$ and $\vec{y}$,</p>

\[dot(\vec x, \vec y)=\vec x^T\vec y % Equation (3)\]

<p>However, in data science, for some reason unknown, a single data point is usually treated as a row vector and used. In other words, an arbitrary $d$-dimensional vector $x$ is represented as follows.</p>

\[\vec{x}=\begin{bmatrix}x_1 &amp; x_2 &amp; \cdots &amp; x_d\end{bmatrix}% Equation (4)\]

<p>In this case, the matrix must go to the right of the vector. The product of an arbitrary $d\times d$ dimensional matrix $R$ and an $d$-dimensional row vector $x$ can be written as follows.</p>

\[x R % Equation (5)\]

<p>Furthermore, the dot product between row vectors also uses the transpose operation, but the transposed vector is on the right. In other words, for any $d$-dimensional row vectors $\vec{x}$ and $\vec{y}$,</p>

\[dot(\vec x, \vec y)=\vec x \vec y^T % Equation (6)\]

<p>Going further, in data science, it is common to have a data set $\mathcal D$ with $n$ samples and $d$ features represented as an $n\times d$ dimensional matrix. In other words, if more sample data is added, one row is added. In other words, each data point is treated as a “row vector.”</p>

<p>In this post, the default direction of vectors is set to “row vectors.”</p>

<h1 id="contextual-relative-distance">Contextual relative distance</h1>

<p>Consider two vectors $\vec x$ and $\vec y$ as shown below.</p>

<p align="center">
  <img width="600" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic2.png" />
  <br />
  Figure 1. The distance between two vectors in space can be calculated using the dot product of the vectors.
</p>

<p>What formula should be used to calculate the Euclidean distance between an arbitrary point $\vec x$ and $\vec y$? The distance can be calculated using the difference and dot product of the two vectors. This distance is called the Euclidean distance.</p>

\[d_E = \sqrt{(\vec x-\vec y)(\vec x-\vec y)^T} % Equation (7)\]

<p>However, if we consider other data points in the vicinity, we may need to reconsider whether to use an absolute distance between two points.</p>

<p align="center">
  <img width="600" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic3.png" />
  <br />
  Figure 2. The distance between two points, taking into account the context of other data points, may need to be calculated differently.
</p>

<p>In the above figure, (a) can be seen as points that are quite away from the distribution of blue data, while (b) is in a relatively less deviated location from the distribution. In other words, considering the “context” of other data points, the distance between the two vectors in Figure 2 (a) may be farther than the distance between the two vectors in Figure 2 (b).</p>

<p>The ambiguous expression “context” can be expressed more mathematically as “standard deviation.” If we can assume that the data is in the form of a normal distribution, we can use the properties of the standard deviation of a normal distribution to see that there is 68, 95, and 99.7% of the data coming in at a distance of 1, 2, and 3 standard deviations away from the mean (center).</p>

<p align="center">
  <img width="600" src="https://upload.wikimedia.org/wikipedia/commons/2/22/Empirical_rule_histogram.svg" />
  <br />
  Figure 3. How much data is included when moving 1, 2, and 3 standard deviations away from the center in a normal distribution? (68–95–99.7 rule)
</p>

<p>In other words, standard deviation contours can be displayed based on the standard deviation, as in the figure below. And these contours become indicators of “contextual” distance.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic6.png" />
 <br />
 Figure 4. A contour that represents the distance from the mean in standard deviation units of 68, 95, and 99.7%
</p>

<p>And by reducing the ellipsoidal shape in (b) of figure 4 to a unit circle as in (a) of figure 4, we can normalize the standard deviation that represents the “context” of the data. Let’s take a look at the transformation of the vector space using new axes corresponding to standard deviations 1, 2, 3, etc. as shown in figure 5 below.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic7_en.png" />
 <br />
 Figure 5. Representation of the "context" of the data and transformation of the data (vector) space to "normalize" the "context"
</p>

<p>This process is performed in the applet at the top of this post. Let’s look at the left of Figure 6. When considering the “context” of the given data, we should judge that the yellow points are farther away than the orange points. This is a complicated task as the Euclidean distance must be calculated while considering the “context”. However, if we normalize the “context” as in the right of Figure 6, the distance between the yellow points is already considered as farther away by simply calculating the Euclidean distance. This is because the original data (vector) space was transformed while taking into account the “context” of the given data in the process of “normalizing” the “context”.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic8_en.png" />
 <br />
 Figure 6. The Euclidean distance measured after "normalizing" the "context" already becomes a distance that takes into account the "context".
</p>

<p>Investigating the “context” through the distribution of the given data and normalizing it before calculating the Euclidean distance is the Mahalanobis distance.</p>

\[d_M = \sqrt{(\vec x-\vec y)\Sigma^{-1}(\vec x-\vec y)^T} % Equation (8)\]

<p>The transformation of the vector space can be represented by a matrix. Specifically, the matrix that represents the “context” of the data is related to the covariance matrix, and the matrix that rotates it back is related to the inverse matrix of the covariance matrix. From now on, let’s try to understand how to grasp the “context” of the data mathematically. Also, let’s examine how to perform “normalization” of the “context” in more detail.</p>

<h1 id="the-meaning-of-the-covariance-matrix-and-its-inverse-matrix">The Meaning of the Covariance Matrix and its Inverse Matrix</h1>

<h2 id="basic-understanding-of-iid-gaussian-distribution-samples">Basic Understanding of iid Gaussian Distribution Samples</h2>

<p>Before understanding the structure of the data, we first need to understand the properties of iid (independent and identically distributed) normal distribution samples. Although the terminology may seem difficult, there is nothing difficult once we look at it carefully. iid is one of the simplest methodologies for extracting random data samples.</p>

<p>To explain iid, let’s break it down into the following assumptions:</p>

<ul>
  <li>The extracted data is independently extracted.</li>
  <li>The extracted data is extracted from the same probability distribution.</li>
</ul>

<p>Furthermore, assuming that the probability distribution extracted here is a normal distribution, the extracted samples can be expressed as “independent and identically distributed normal random variables.”</p>

<p>This time, let’s stack multiple iid normal random variables $z_1, \cdots, z_d$ side by side as $Z\in\mathbb{R}^{n\times d}$. In particular, for convenience of calculation, assume a standard normal distribution.</p>

\[Z =\begin{bmatrix} | &amp; | &amp; &amp; |\\ z_1 &amp; z_2 &amp; \cdots &amp; z_d\\ | &amp; | &amp; &amp; |\end{bmatrix} % Equation (9)\]

\[\text{where } z_1, z_2, \cdots, z_d \text{ are i.i.d. normal random variables with mean 0 and variance 1}\notag\]

<p>As we have extracted samples from a standard normal distribution, we can confirm the following. Since the mean of the extracted distribution is 0,</p>

\[\mathbb{E}[z_i]=0 \text{ for } i = 1, 2, \cdots, d % Equation (10)\]

<p>Moreover, let’s also consider the following given that the variance of the extracted distribution is 1.</p>

\[\mathbb{E}\left[Z^TZ\right]

= \mathbb{E}\left [\begin{bmatrix}
  z_1^T z_1 &amp; z_1^T z_2 &amp; \cdots &amp; z_1^Tz_d \\ 
  z_2^T z_1 &amp; z_2^T z_2 &amp; \cdots &amp; z_2^T z_d \\
  \vdots    &amp; \vdots    &amp; \ddots &amp; \vdots \\
  z_d^T z_1 &amp; z_d^T z_2 &amp; \cdots &amp; z_d^Tz_d
  \end{bmatrix}\right ] % 식 (11)\]

<p>Here, for $i=1,2,\cdots, d$, $\mathbb{E}\left[z_i^T z_i\right]$ is equal to the sum of $n$ variances of 1, so $\mathbb{E}\left[z_i^T z_i\right]=n$. Furthermore, since $z_i$ is extracted independently, for different $i$ and $j$, $\mathbb E \left[z_i^T z_j \right]=0$.</p>

<p>Therefore, equation (11) can be represented as</p>

\[\text{Equation (11)} \Rightarrow \begin{bmatrix}
  n &amp; 0 &amp; \cdots &amp; 0 \\ 
  0 &amp; n &amp; \cdots &amp; 0 \\
  \vdots    &amp; \vdots    &amp; \ddots &amp; \vdots \\
  0 &amp; 0 &amp; \cdots &amp; n
  \end{bmatrix} = n I\]

<p>Here, $I$ is a unit matrix of dimensions $d \times d$.</p>

<h2 id="another-way-to-understand-the-given-data">Another way to understand the given data</h2>

<p>Suppose that 1,000 aliens living on Mars were randomly selected and their height and weight were measured. Amazingly, the average height was 10cm and the average weight was 8kg. Suppose that the data is arranged in a table, which roughly looks like the following.</p>

<p align="center">
  <img width="300" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic_table1.png" />
 <br />
 Figure 8. Table summarizing the height and weight of aliens on Mars (rounding up to the 4th alien)
</p>

<p>The height and weight data of 1,000 aliens can be found <a href="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/alien_height_weight.csv">here</a>.</p>

<p>Let’s call the data that arranges the height and weight $\mathcal D$. Also, if the number of aliens sampled is denoted as $n$, and the number of features such as height and weight is represented as $d$, then $\mathcal D$ can also be viewed as the following matrix.</p>

\[\mathcal D\in\mathbb{R}^{n\times d}\]

<p>Although the data used this time was the height and weight of random 1000 aliens, it is possible to examine the distribution of any data. In order to understand the data distribution from a “new” perspective, let’s move all feature-wise mean values of the dataset to zero. Then, let’s view the new data, for which feature-wise mean values are zero, as data $X$.</p>

<p>If we plot the distributions of $\mathcal D$ and $X$, it is shown as below.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic_move_distribution_en.png" />
 <br />
 Figure 9. Distribution of height and weight data of aliens on Mars
</p>

<p>Now let’s try to understand the data $X$ as a result of linear transformation of raw data $Z$. Here, the reason why the linear transformation matrix $R$ is attached to the right of $Z$ is because we can see the basic direction of the vector as a row vector, as shown in equation (5).</p>

\[X = ZR % Equation (14)\]

\[\text{where }Z \in \mathbb{R}^{n\times d} \text{ and } R \in \mathbb{R}^{d\times d}\notag\]

<p>Let’s assume that all columns of $Z$ are datasets extracted from the standard normal distribution of iid (independent and identically distributed).</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/pic10_en.png" />
 <br />
 Figure 10. Understand the given data as $X$ modified from raw data $Z$ linear transformed.
</p>

<p>From now on, let’s investigate the similarity between features. By investigating the similarity between features, we can understand the “context” or structural form of the data. That’s because, for example, if feature 1 and feature 2 are very similar, it means that they are highly correlated with each other. To do this, let’s calculate $X^TX$. $X^TX$ will have dimensions of $d \times d$, and it represents the inner product between features. If we calculate $XX^T$, we can expect that this will indicate the similarity between the data. Let’s see the process of calculating $X^TX$ in the figure below.</p>

<p align="center">
  <img width="500" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2019-07-27_PCA/XTX.png" />
  <br />
  Figure 11. The process of calculating how similar each data feature is in order to compute the covariance matrix.
</p>

<p>Here, using Equation (14) again, we have:</p>

\[X^TX = (ZR)^TZR = R^TZ^TZR = R^T(Z^TZ)R % Equation (15)\]

<p>Here, according to Equation (12),</p>

\[X^TX \approx R^T(nI)R = nR^TR % Equation (16)\]

<p>is established. Here, we used “$\approx$” because in actual data, the exact value of the expected value may not come out. And we can confirm the following fact:</p>

\[R^TR \approx \frac{1}{n}X^TX % Equation (17)\]

<p>What does equation (17) mean in the end? Equation (17) is a way of obtaining the “context” of the data of $X$ or the structural form of the data. This is almost identical to $R^TR$ for the linear transformation $R$ to transform the raw form $Z$ into the given data $X$. And the matrix that expresses the structural form of the equation (17) is called the covariance matrix. Let’s use $\Sigma $ to represent the covariance matrix here.</p>

\[\Sigma = \frac{1}{n}X^TX % 식 (18)\]

<p>Note that there is also a way to divide by $n-1$ instead of $n$. The resulting covariance matrix obtained by dividing by $n-1$ instead of $n$ is called the sample covariance matrix. The covariance matrix is a useful way to describe the overall structure of the entire dataset and is especially closely related to multivariate normal distribution. If a dataset with two features follows a bivariate normal distribution, as in Figure 12, it can be said to follow one of the three major patterns below.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/types_of_bivariate_gaussian.png" />
 <br />
 Figure 12. The three most representative forms of bivariate normal distributions.
</p>

<p>Each element of the covariance matrix represents the variance or covariance of each feature. In other words, in the case of two features as in Figure 12, it represents how much data is scattered in the x-axis and y-axis for each feature, as well as how much variation is together between the first and second features.</p>

<p align="center">
  <img width="400" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/meaning_of_cov_mtx_en.png" />
 <br />
 Figure 13. What each element of the covariance matrix represents.
</p>

<h2 id="inverse-matrix-and-normalization-of-context">Inverse matrix and normalization of context</h2>

<p>If the given arbitrary data is denoted as $x$ and its primitive form is denoted as $z$, then according to Equation (14), it can be seen that it is possible to restore the “context” of the given data to the form of primitive data by performing the following:</p>

\[z=xR^{-1}\]

<p>Here, the linear transformation using the inverse matrix is a method of restoring the vector space transformed by the given linear transformation $R$ to its original form. That is, if the process of changing from left to right in Figure 10 is the transformation performed by the original linear transformation $R$, the inverse transformation $R^{-1}$ can be seen as the transformation from right to left in Figure 10.</p>

<p align="center">
  <img width="800" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/inverse_of_pic10_en.png" />
 <br />
 Figure 14. Linear transformation represented by matrix R and its inverse transformation.
</p>

<p>Using Equation (7), we can calculate the distance $d_z$ between the origin and the primitive data vector space as follows:</p>

\[d_z=\sqrt{zz^T}=\sqrt{(xR^{-1})(xR^{-1})^T}\]

\[=\sqrt{xR^{-1}(R^{-1})^Tx^T}=\sqrt{x(R^TR)^{-1}x^T}=\sqrt{x\Sigma^{-1}x^T}\]

<p>Here, $\Sigma$ is the covariance matrix of the entire given dataset.</p>

<p>If we perform the same process as above for the distance between arbitrary vectors $x$ and $y$, we can modify the equation as follows, and this is the same as the Mahalanobis distance mentioned earlier:</p>

\[\Rightarrow \sqrt{(x-y)\Sigma^{-1}(x-y)^T}\]

<h1 id="contour-lines-and-principal-axes-eigenvalues-eigenvectors">Contour lines and Principal Axes: Eigenvalues, Eigenvectors</h1>

<p>※ The last chapter is somewhat advanced, and it is not necessary to understand it to understand the meaning of Mahalanobis.</p>

<p>※ To better understand the following content, it is recommended to understand the following:</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2019/07/17/eigen_vector_en.html">Eigenvalues and Eigenvectors</a></li>
  <li><a href="https://angeloyeo.github.io/2020/11/19/eigen_decomposition_en.html">Eigen Decomposition</a></li>
</ul>

<p>Now let’s add the standard deviation and “contour lines” to understand the “context” of the data, as introduced in Figures 3 and 4. Talking about “contour lines” is one of the most important cores in understanding Mahalanobis distance.</p>

<p>First, let’s take another look at Figure 12. Figure 12 shows three representative forms of bivariate normal distributions that can be found. However, are these three shapes the only possible shapes for the distribution? Probably not. If we express the shape of the distribution with the two factors being how much it has rotated and how much it has been stretched, we can see that there will be countless shapes of the distribution. In other words, any distribution that can be represented by a multivariate normal distribution can be obtained by stretching and rotating a standard normal distribution.</p>

<p>The method of expressing how much the given linear transformation has rotated and how much it has been stretched is called <a href="https://angeloyeo.github.io/2020/11/19/eigen_decomposition_en.html">eigenvalue decomposition</a>. The amount of rotation will indicate the direction of the new axis shown on the right in Figure 5, and the amount of stretching will indicate the length of one scale on the new axes. In addition, as discussed in the article on <a href="https://angeloyeo.github.io/2020/11/19/eigen_decomposition_en.html">eigen decomposition</a>, the rotation direction is represented by eigenvectors and the amount of stretching is represented by eigenvalues.</p>

<p>Let’s try to eigen-decompose the covariance matrix as follows:</p>

\[\Sigma = Q\Lambda Q^{-1}=Q\Lambda Q^T\]

<p>Here, since the covariance matrix is always a symmetric matrix, we can replace $Q^{-1}$ with $Q^T$.</p>

<p>Here, $Q$ and $\Lambda$ are matrices with eigenvectors and eigenvalues, respectively.</p>

<p>For example, if we eigen-decompose the covariance matrix of the first image in Figure 12, we can get the following result:</p>

\[\begin{bmatrix}1 &amp; 0.5\\0.5 &amp; 1.5\end{bmatrix}=\begin{bmatrix}-0.8507 &amp; 0.5257 \\ 0.5257 &amp; 0.8507\end{bmatrix}\begin{bmatrix}0.6910 &amp; 0 \\ 0 &amp; 1.8090\end{bmatrix}\begin{bmatrix}-0.8507 &amp; 0.5257 \\ 0.5257 &amp; 0.8507\end{bmatrix}^T\]

<p>And each column of $Q$ shows how much the standard normal distribution has been rotated, or more precisely, indicates the direction of the principal components (PCs). In addition, the diagonal elements of $\Lambda$ show how much the distribution has been stretched in each principal component direction. Refer to Figure 15 to understand this more visually.</p>

<p align="center">
  <img width="600" src="https://raw.githubusercontent.com/angeloyeo/angeloyeo.github.io/master/pics/2022-09-28-Mahalanobis_distance/principal_axis.png" />
  <br />
  Figure 15. The eigenvalue decomposition of the covariance matrix allows us to represent how much the standard normal distribution has been stretched and rotated as a vector. Here, $\sigma_1$ and $\sigma_2$ represent how much PC1 and PC2 have been stretched, respectively.
</p>

<p>To explain this result again, it is a more mathematical representation of the content from Figure 3 to Figure 5. The principal component directions of $Q$ are the two most representative directions for calculating standard deviation, and the diagonal elements of $\Lambda$ indicate the standard deviation in the principal component direction, in other words.</p>

<p>Therefore, if we understand the Mahalanobis distance based on the data on the principal axis (or assume that we project the data onto the principal axis), we can consider the distance as a normalized distance by rotating the principal axis back to the original xy axis and dividing by the standard deviation value obtained from $\Lambda$.</p>]]></content><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><category term="Linear_Algebra" /><category term="Statistics" /><summary type="html"><![CDATA[※ In this post, vectors are represented using “row vectors” as the default direction. For more detailed explanation of this, please refer to the first section “Data representation using row vectors”. Prerequisites To better understand this post, it is recommended that you be familiar with the following content: Matrix and Linear Transformations If you need a more detailed explanation of the covariance matrix, please refer to the following post: Principal Component Analysis (PCA) Data representation using row vectors In mathematics, it is more common to view column vectors as the default direction when representing vectors. In other words, a vector $x$ of arbitrary dimension $n$ is usually represented as follows. \[\vec{x}=\begin{bmatrix}x_1 \\ x_2 \\ \vdots \\x_n\end{bmatrix} % Equation (1)\] In this case, the matrix must go to the left of the vector. The product of an arbitrary $n\times n$ dimensional matrix $A$ and an $n$ dimensional column vector $x$ is represented as follows. \[Ax % Equation (2)\] Furthermore, the dot product between column vectors can be expressed using the transpose operator as follows. For any $n$-dimensional vectors $\vec{x}$ and $\vec{y}$, \[dot(\vec x, \vec y)=\vec x^T\vec y % Equation (3)\] However, in data science, for some reason unknown, a single data point is usually treated as a row vector and used. In other words, an arbitrary $d$-dimensional vector $x$ is represented as follows. \[\vec{x}=\begin{bmatrix}x_1 &amp; x_2 &amp; \cdots &amp; x_d\end{bmatrix}% Equation (4)\] In this case, the matrix must go to the right of the vector. The product of an arbitrary $d\times d$ dimensional matrix $R$ and an $d$-dimensional row vector $x$ can be written as follows. \[x R % Equation (5)\] Furthermore, the dot product between row vectors also uses the transpose operation, but the transposed vector is on the right. In other words, for any $d$-dimensional row vectors $\vec{x}$ and $\vec{y}$, \[dot(\vec x, \vec y)=\vec x \vec y^T % Equation (6)\] Going further, in data science, it is common to have a data set $\mathcal D$ with $n$ samples and $d$ features represented as an $n\times d$ dimensional matrix. In other words, if more sample data is added, one row is added. In other words, each data point is treated as a “row vector.” In this post, the default direction of vectors is set to “row vectors.” Contextual relative distance Consider two vectors $\vec x$ and $\vec y$ as shown below. Figure 1. The distance between two vectors in space can be calculated using the dot product of the vectors. What formula should be used to calculate the Euclidean distance between an arbitrary point $\vec x$ and $\vec y$? The distance can be calculated using the difference and dot product of the two vectors. This distance is called the Euclidean distance. \[d_E = \sqrt{(\vec x-\vec y)(\vec x-\vec y)^T} % Equation (7)\] However, if we consider other data points in the vicinity, we may need to reconsider whether to use an absolute distance between two points. Figure 2. The distance between two points, taking into account the context of other data points, may need to be calculated differently. In the above figure, (a) can be seen as points that are quite away from the distribution of blue data, while (b) is in a relatively less deviated location from the distribution. In other words, considering the “context” of other data points, the distance between the two vectors in Figure 2 (a) may be farther than the distance between the two vectors in Figure 2 (b). The ambiguous expression “context” can be expressed more mathematically as “standard deviation.” If we can assume that the data is in the form of a normal distribution, we can use the properties of the standard deviation of a normal distribution to see that there is 68, 95, and 99.7% of the data coming in at a distance of 1, 2, and 3 standard deviations away from the mean (center). Figure 3. How much data is included when moving 1, 2, and 3 standard deviations away from the center in a normal distribution? (68–95–99.7 rule) In other words, standard deviation contours can be displayed based on the standard deviation, as in the figure below. And these contours become indicators of “contextual” distance. Figure 4. A contour that represents the distance from the mean in standard deviation units of 68, 95, and 99.7% And by reducing the ellipsoidal shape in (b) of figure 4 to a unit circle as in (a) of figure 4, we can normalize the standard deviation that represents the “context” of the data. Let’s take a look at the transformation of the vector space using new axes corresponding to standard deviations 1, 2, 3, etc. as shown in figure 5 below. Figure 5. Representation of the "context" of the data and transformation of the data (vector) space to "normalize" the "context" This process is performed in the applet at the top of this post. Let’s look at the left of Figure 6. When considering the “context” of the given data, we should judge that the yellow points are farther away than the orange points. This is a complicated task as the Euclidean distance must be calculated while considering the “context”. However, if we normalize the “context” as in the right of Figure 6, the distance between the yellow points is already considered as farther away by simply calculating the Euclidean distance. This is because the original data (vector) space was transformed while taking into account the “context” of the given data in the process of “normalizing” the “context”. Figure 6. The Euclidean distance measured after "normalizing" the "context" already becomes a distance that takes into account the "context". Investigating the “context” through the distribution of the given data and normalizing it before calculating the Euclidean distance is the Mahalanobis distance. \[d_M = \sqrt{(\vec x-\vec y)\Sigma^{-1}(\vec x-\vec y)^T} % Equation (8)\] The transformation of the vector space can be represented by a matrix. Specifically, the matrix that represents the “context” of the data is related to the covariance matrix, and the matrix that rotates it back is related to the inverse matrix of the covariance matrix. From now on, let’s try to understand how to grasp the “context” of the data mathematically. Also, let’s examine how to perform “normalization” of the “context” in more detail. The Meaning of the Covariance Matrix and its Inverse Matrix Basic Understanding of iid Gaussian Distribution Samples Before understanding the structure of the data, we first need to understand the properties of iid (independent and identically distributed) normal distribution samples. Although the terminology may seem difficult, there is nothing difficult once we look at it carefully. iid is one of the simplest methodologies for extracting random data samples. To explain iid, let’s break it down into the following assumptions: The extracted data is independently extracted. The extracted data is extracted from the same probability distribution. Furthermore, assuming that the probability distribution extracted here is a normal distribution, the extracted samples can be expressed as “independent and identically distributed normal random variables.” This time, let’s stack multiple iid normal random variables $z_1, \cdots, z_d$ side by side as $Z\in\mathbb{R}^{n\times d}$. In particular, for convenience of calculation, assume a standard normal distribution. \[Z =\begin{bmatrix} | &amp; | &amp; &amp; |\\ z_1 &amp; z_2 &amp; \cdots &amp; z_d\\ | &amp; | &amp; &amp; |\end{bmatrix} % Equation (9)\] \[\text{where } z_1, z_2, \cdots, z_d \text{ are i.i.d. normal random variables with mean 0 and variance 1}\notag\] As we have extracted samples from a standard normal distribution, we can confirm the following. Since the mean of the extracted distribution is 0, \[\mathbb{E}[z_i]=0 \text{ for } i = 1, 2, \cdots, d % Equation (10)\] Moreover, let’s also consider the following given that the variance of the extracted distribution is 1. \[\mathbb{E}\left[Z^TZ\right] = \mathbb{E}\left [\begin{bmatrix} z_1^T z_1 &amp; z_1^T z_2 &amp; \cdots &amp; z_1^Tz_d \\ z_2^T z_1 &amp; z_2^T z_2 &amp; \cdots &amp; z_2^T z_d \\ \vdots &amp; \vdots &amp; \ddots &amp; \vdots \\ z_d^T z_1 &amp; z_d^T z_2 &amp; \cdots &amp; z_d^Tz_d \end{bmatrix}\right ] % 식 (11)\] Here, for $i=1,2,\cdots, d$, $\mathbb{E}\left[z_i^T z_i\right]$ is equal to the sum of $n$ variances of 1, so $\mathbb{E}\left[z_i^T z_i\right]=n$. Furthermore, since $z_i$ is extracted independently, for different $i$ and $j$, $\mathbb E \left[z_i^T z_j \right]=0$. Therefore, equation (11) can be represented as \[\text{Equation (11)} \Rightarrow \begin{bmatrix} n &amp; 0 &amp; \cdots &amp; 0 \\ 0 &amp; n &amp; \cdots &amp; 0 \\ \vdots &amp; \vdots &amp; \ddots &amp; \vdots \\ 0 &amp; 0 &amp; \cdots &amp; n \end{bmatrix} = n I\] Here, $I$ is a unit matrix of dimensions $d \times d$. Another way to understand the given data Suppose that 1,000 aliens living on Mars were randomly selected and their height and weight were measured. Amazingly, the average height was 10cm and the average weight was 8kg. Suppose that the data is arranged in a table, which roughly looks like the following. Figure 8. Table summarizing the height and weight of aliens on Mars (rounding up to the 4th alien) The height and weight data of 1,000 aliens can be found here. Let’s call the data that arranges the height and weight $\mathcal D$. Also, if the number of aliens sampled is denoted as $n$, and the number of features such as height and weight is represented as $d$, then $\mathcal D$ can also be viewed as the following matrix. \[\mathcal D\in\mathbb{R}^{n\times d}\] Although the data used this time was the height and weight of random 1000 aliens, it is possible to examine the distribution of any data. In order to understand the data distribution from a “new” perspective, let’s move all feature-wise mean values of the dataset to zero. Then, let’s view the new data, for which feature-wise mean values are zero, as data $X$. If we plot the distributions of $\mathcal D$ and $X$, it is shown as below. Figure 9. Distribution of height and weight data of aliens on Mars Now let’s try to understand the data $X$ as a result of linear transformation of raw data $Z$. Here, the reason why the linear transformation matrix $R$ is attached to the right of $Z$ is because we can see the basic direction of the vector as a row vector, as shown in equation (5). \[X = ZR % Equation (14)\] \[\text{where }Z \in \mathbb{R}^{n\times d} \text{ and } R \in \mathbb{R}^{d\times d}\notag\] Let’s assume that all columns of $Z$ are datasets extracted from the standard normal distribution of iid (independent and identically distributed). Figure 10. Understand the given data as $X$ modified from raw data $Z$ linear transformed. From now on, let’s investigate the similarity between features. By investigating the similarity between features, we can understand the “context” or structural form of the data. That’s because, for example, if feature 1 and feature 2 are very similar, it means that they are highly correlated with each other. To do this, let’s calculate $X^TX$. $X^TX$ will have dimensions of $d \times d$, and it represents the inner product between features. If we calculate $XX^T$, we can expect that this will indicate the similarity between the data. Let’s see the process of calculating $X^TX$ in the figure below. Figure 11. The process of calculating how similar each data feature is in order to compute the covariance matrix. Here, using Equation (14) again, we have: \[X^TX = (ZR)^TZR = R^TZ^TZR = R^T(Z^TZ)R % Equation (15)\] Here, according to Equation (12), \[X^TX \approx R^T(nI)R = nR^TR % Equation (16)\] is established. Here, we used “$\approx$” because in actual data, the exact value of the expected value may not come out. And we can confirm the following fact: \[R^TR \approx \frac{1}{n}X^TX % Equation (17)\] What does equation (17) mean in the end? Equation (17) is a way of obtaining the “context” of the data of $X$ or the structural form of the data. This is almost identical to $R^TR$ for the linear transformation $R$ to transform the raw form $Z$ into the given data $X$. And the matrix that expresses the structural form of the equation (17) is called the covariance matrix. Let’s use $\Sigma $ to represent the covariance matrix here. \[\Sigma = \frac{1}{n}X^TX % 식 (18)\] Note that there is also a way to divide by $n-1$ instead of $n$. The resulting covariance matrix obtained by dividing by $n-1$ instead of $n$ is called the sample covariance matrix. The covariance matrix is a useful way to describe the overall structure of the entire dataset and is especially closely related to multivariate normal distribution. If a dataset with two features follows a bivariate normal distribution, as in Figure 12, it can be said to follow one of the three major patterns below. Figure 12. The three most representative forms of bivariate normal distributions. Each element of the covariance matrix represents the variance or covariance of each feature. In other words, in the case of two features as in Figure 12, it represents how much data is scattered in the x-axis and y-axis for each feature, as well as how much variation is together between the first and second features. Figure 13. What each element of the covariance matrix represents. Inverse matrix and normalization of context If the given arbitrary data is denoted as $x$ and its primitive form is denoted as $z$, then according to Equation (14), it can be seen that it is possible to restore the “context” of the given data to the form of primitive data by performing the following: \[z=xR^{-1}\] Here, the linear transformation using the inverse matrix is a method of restoring the vector space transformed by the given linear transformation $R$ to its original form. That is, if the process of changing from left to right in Figure 10 is the transformation performed by the original linear transformation $R$, the inverse transformation $R^{-1}$ can be seen as the transformation from right to left in Figure 10. Figure 14. Linear transformation represented by matrix R and its inverse transformation. Using Equation (7), we can calculate the distance $d_z$ between the origin and the primitive data vector space as follows: \[d_z=\sqrt{zz^T}=\sqrt{(xR^{-1})(xR^{-1})^T}\] \[=\sqrt{xR^{-1}(R^{-1})^Tx^T}=\sqrt{x(R^TR)^{-1}x^T}=\sqrt{x\Sigma^{-1}x^T}\] Here, $\Sigma$ is the covariance matrix of the entire given dataset. If we perform the same process as above for the distance between arbitrary vectors $x$ and $y$, we can modify the equation as follows, and this is the same as the Mahalanobis distance mentioned earlier: \[\Rightarrow \sqrt{(x-y)\Sigma^{-1}(x-y)^T}\] Contour lines and Principal Axes: Eigenvalues, Eigenvectors ※ The last chapter is somewhat advanced, and it is not necessary to understand it to understand the meaning of Mahalanobis. ※ To better understand the following content, it is recommended to understand the following: Eigenvalues and Eigenvectors Eigen Decomposition Now let’s add the standard deviation and “contour lines” to understand the “context” of the data, as introduced in Figures 3 and 4. Talking about “contour lines” is one of the most important cores in understanding Mahalanobis distance. First, let’s take another look at Figure 12. Figure 12 shows three representative forms of bivariate normal distributions that can be found. However, are these three shapes the only possible shapes for the distribution? Probably not. If we express the shape of the distribution with the two factors being how much it has rotated and how much it has been stretched, we can see that there will be countless shapes of the distribution. In other words, any distribution that can be represented by a multivariate normal distribution can be obtained by stretching and rotating a standard normal distribution. The method of expressing how much the given linear transformation has rotated and how much it has been stretched is called eigenvalue decomposition. The amount of rotation will indicate the direction of the new axis shown on the right in Figure 5, and the amount of stretching will indicate the length of one scale on the new axes. In addition, as discussed in the article on eigen decomposition, the rotation direction is represented by eigenvectors and the amount of stretching is represented by eigenvalues. Let’s try to eigen-decompose the covariance matrix as follows: \[\Sigma = Q\Lambda Q^{-1}=Q\Lambda Q^T\] Here, since the covariance matrix is always a symmetric matrix, we can replace $Q^{-1}$ with $Q^T$. Here, $Q$ and $\Lambda$ are matrices with eigenvectors and eigenvalues, respectively. For example, if we eigen-decompose the covariance matrix of the first image in Figure 12, we can get the following result: \[\begin{bmatrix}1 &amp; 0.5\\0.5 &amp; 1.5\end{bmatrix}=\begin{bmatrix}-0.8507 &amp; 0.5257 \\ 0.5257 &amp; 0.8507\end{bmatrix}\begin{bmatrix}0.6910 &amp; 0 \\ 0 &amp; 1.8090\end{bmatrix}\begin{bmatrix}-0.8507 &amp; 0.5257 \\ 0.5257 &amp; 0.8507\end{bmatrix}^T\] And each column of $Q$ shows how much the standard normal distribution has been rotated, or more precisely, indicates the direction of the principal components (PCs). In addition, the diagonal elements of $\Lambda$ show how much the distribution has been stretched in each principal component direction. Refer to Figure 15 to understand this more visually. Figure 15. The eigenvalue decomposition of the covariance matrix allows us to represent how much the standard normal distribution has been stretched and rotated as a vector. Here, $\sigma_1$ and $\sigma_2$ represent how much PC1 and PC2 have been stretched, respectively. To explain this result again, it is a more mathematical representation of the content from Figure 3 to Figure 5. The principal component directions of $Q$ are the two most representative directions for calculating standard deviation, and the diagonal elements of $\Lambda$ indicate the standard deviation in the principal component direction, in other words. Therefore, if we understand the Mahalanobis distance based on the data on the principal axis (or assume that we project the data onto the principal axis), we can consider the distance as a normalized distance by rotating the principal axis back to the original xy axis and dividing by the standard deviation value obtained from $\Lambda$.]]></summary></entry><entry xml:lang="ko"><title type="html">체르노프 유계(Chernoff Bound)</title><link href="https://angeloyeo.github.io/2022/09/13/Chernoff_Bound.html" rel="alternate" type="text/html" title="체르노프 유계(Chernoff Bound)" /><published>2022-09-13T00:00:00+00:00</published><updated>2022-09-13T00:00:00+00:00</updated><id>https://angeloyeo.github.io/2022/09/13/Chernoff_Bound</id><content type="html" xml:base="https://angeloyeo.github.io/2022/09/13/Chernoff_Bound.html"><![CDATA[<h1 id="prerequisites">prerequisites</h1>

<p>본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다.</p>

<ul>
  <li><a href="https://angeloyeo.github.io/2022/09/12/Markov_Chebyshev_Inequality.html">마르코프 부등식과 체비셰프 부등식</a></li>
</ul>

<h1 id="증명">증명</h1>

<p>Chernoff 부등식은 Lower-tail 버전과 Upper-tail 버전의 형태가 다르다. 아래에서는 증명 과정을 소개하고자 한다.</p>

<h2 id="lower-tail-chernoff-bound">Lower-Tail Chernoff Bound</h2>

<p>$X$가 $N$ 개의 독립적인 랜덤변수의 합이라고 하자. 또, 이때 이 랜덤 변수들은 베르누이 분포를 따르며 $p_i$의 확률로 1의 값을 갖는다고 하자.</p>

\[X = \sum_{i=1}^{N}X_i\]

<p>이 때, 임의의 $\delta\in (0, 1)$에 대해 다음이 성립한다.</p>

\[P(X \lt (1-\delta)E[X]) \lt e^{-E[X]\cdot \delta^2/2}\]

<p>여기서 $e$는 자연로그의 밑이다.</p>

<p>(증명)</p>

<p>우선 아래의 부등식이 성립한다는 것을 증명하자.</p>

\[P(X \lt (1-\delta) E[X]) \lt \left(\frac{e^{-\delta}}{(1-\delta)^{(1-\delta)}}\right)^{E[X]}\]

<p>이를 증명하기 위해 임의의 매개변수 $t&gt;0$을 도입하자. 이 $t$를 이용해 우리는 $X$에 대한 식을 $e^{-tX}$에 대한 식으로 변환할 것이다. 이 방법은 적률생성함수(moment generating function)을 활용하는 원리와 유사하게 볼 수 있는데, 원래의 $X$ domain에서 풀기 어려운 문제를 매개변수 $t$ 도메인으로 옮겨 문제를 상대적으로 쉽게 풀기 위함이라고 볼 수도 있다.</p>

<p>식 (3)을 증명하기 위해 <a href="https://angeloyeo.github.io/2022/09/12/Markov_Chebyshev_Inequality.html">마르코프 부등식</a>의 식을 $X$ 대신 $e^{-tX}$에 맞춰 수정하자. 원래의 마르코프 부등식은 아래와 같다.</p>

\[P(X\lt \alpha) \leq \frac{E[X]}{\alpha}\]

<p>여기서 우변을 바꿔주면,</p>

\[P(X\lt\alpha) \leq \frac{E[e^{-tX}]}{e^{-t\alpha}}\]

<p>가 된다.</p>

<p>식 (5)를 식 (2)의 좌변에 맞춰 적용하면 결과는 아래와 같다. 여기서 $\alpha = (1-\delta)E[X]$이므로,</p>

\[\Rightarrow P(X\lt (1-\delta)E[X]) \leq \frac{E[e^{-tX}]}{e^{-t(1-\delta)E[X]}}\]

<p>이 성립한다. 또 $X$를 구성하고 있는 $X_i$ 들은 독립적으로 발생한 사건이다. 위 식의 우변의 분자를 보면,</p>

\[E[e^{-tX}]=E[e^{-t\cdot\sum_{i}X_i}]=E[e^{-t(X_1+X_2+\cdots+X_N)}]\notag\]

\[=E[e^{-tX_1}\cdot e^{-tX_2}\cdot e^{-tX_3}\cdot \cdots \cdot e^{-t X_N}]\]

<p>과 같이 쓸 수 있는데, 독립 랜덤 변수의 곱의 기댓값은 기댓값들의 곱이므로 위 식은 아래와 같이 고쳐쓸 수 있다.</p>

\[\Rightarrow E[e^{-tX_1}\cdot e^{-tX_2}\cdots e^{-tX_N}]=\prod_{i=1}^{N}E[e^{-tX_i}]\]

<p>위 식의 $E[e^{-tX_i}]$를 자세히 보면 베르누이 분포를 따르는 시행 $X_i$에 대한 변환식 $e^{-tX_i}$의 기댓값임을 알 수 있다. $X_i$는 $(1-p_i)$ 혹은 $p_i$의 확률로 0 또는 1의 값을 가지므로 $X_i$의 기댓값은</p>

\[E[X_i] = (1-p_i)\cdot 0 + p_i \cdot 1 = p_i\]

<p>이며, $e^{-tX_i}$의 기댓값은</p>

\[E[e^{-tX_i}]=(1-p_i)e^{-t\cdot 0}+p_i e^{-t\cdot 1}\notag\]

\[=1-p_i + p_i e^{-t}=1+p_i(e^{-t}-1)\notag\]

\[= 1+E[X_i](e^{-t}-1)\]

<p>임을 알 수 있다. 또한 위 식의 마지막 결과물은 $\exp(E[X_i]\cdot(e^{-t}-1))$의 테일러 급수 두 항과 일치한다는 점을 고려하면 다음이 성립함을 알 수 있다.</p>

\[E[e^{-tX_i}]=1+E[X_i](e^{-t}-1) \lt e^{E[X_i](e^{-t}-1)}\]

<p>식 (11)을 식 (8)에 다시 대입하면,</p>

\[\prod_{i=1}^{N}E[e^{-tX_i}]\lt\prod_{i=1}^{N}e^{E[X_i](e^{-t}-1)}\]

<p>이 성립하게 됨을 알 수 있는데, 위 식의 우변을 또 다시 쓰면,</p>

\[\prod_{i=1}^{N}\exp(E[X_i](e^{-t}-1))=\exp\left(\sum_{i=1}^{N}E[X_i]\cdot (e^{-t}-1)\right)\notag\]

\[=\exp\left(E[X](e^{-t}-1)\right)\]

<p>이다. 따라서 식 (13)의 결과를 식 (6)에 대입하면 아래와 같은 식을 얻을 수 있다.</p>

\[P(X&lt;(1-\delta)E[X]) \leq \frac{\exp\left(E[X](e^{-t}-1)\right)}{\exp\left(-t(1-\delta)E[X]\right)}\]

<p>위 식은 어떤 $t&gt;0$에 대해서라도 성립하는 식이다. 이제는 식 (14)가 최대한 tight한 boundary에 대해 성립할 수 있도록 식 (14)의 최소값을 내주는 $t=t^\ast$ 값을 찾자. 이 과정은 식 (14)를 미분하고 미분한 값이 $0$이 되는 $t^\ast$를 찾음으로써 해결할 수 있다.</p>

<p>식 (14)의 우변에 지수법칙을 적용하여 한줄로 쓰면 다음과 같다.</p>

\[\exp(E[X](e^{-t}-1)+t(1-\delta)E[X])\]

<p>이를 조금만 더 정리하고 $f(t)$라고 이름 붙이자.</p>

\[f(t) = \exp\left(E[X]e^{-t}-E[X]+tE[X]-t\delta E[X]\right)\notag\]

\[=\exp\left(E[X](e^{-t}+t-t\delta -1)\right)\]

<p>이제 $f(t)$를 $t$에 대해 미분하면,</p>

\[f'(t) = \exp\left(E[X](e^{-t}+t-t\delta -1)\right)(E[X])(e^{-t}+1-\delta)\]

<p>임을 알 수 있다. 식 (17)에서 맨 앞의 $\exp()$ 함수는 항상 양수이며 $E[X]$ 역시 양수이다. 따라서, 가장 오른쪽의 괄호 안의 값만 0이 되도록 하면 $t=t^\ast$를 찾을 수 있다.</p>

<p>따라서,</p>

\[e^{-t}+1-\delta = 0\]

<p>을 만족하는 $t=t^\ast$는</p>

\[t=t^\ast = \ln\left(\frac{1}{1-\delta}\right)\]

<p>이다.</p>

<p>식 (19)를 식 (14)에 대입하면 식 (3)을 얻을 수 있게 된다. 식 (19)를 식 (14)에 대입하면,</p>

\[\Rightarrow P(X&lt;(1-\delta) E[X])\leq 
  \frac{\exp\left(E[X]\left(e^{-\ln\left(1/(1-\delta)\right)}-1\right)\right)}{\exp\left(-\ln(1/(1-\delta))(1-\delta)E[X]\right)}\]

<p>여기서 우변만 보면 다음과 같다.</p>

\[\text{(우변)}\Rightarrow \frac{\exp(E[X](1-\delta -1))}{\exp(-(1-\delta)E[X]\ln\left(1/(1-\delta)\right))}\]

\[=\frac{\exp(E[X](-\delta))}{\exp(\ln(1-\delta)^{(1-\delta E[X])})}=\frac{\exp(-\delta E[X])}{(1-\delta)^{(1-\delta)E[X]}}\]

\[=\left(\frac{e^{-\delta}}{(1-\delta)^{(1-\delta)}}\right)^{E[X]}\]

<p>한편,</p>

\[\ln(1-x)=-x-\frac{x^2}{2}-\frac{x^3}{3}\cdots = -\sum_{i=1}^{N}\frac{x^n}{n}\]

<p>이므로,</p>

\[(1-\delta)\ln(1-\delta) = - (1-\delta)\delta - (1-\delta)\frac{\delta^2}{2}\cdots\notag\]

\[=-\delta+\delta^2-\frac{\delta^2}{2}+\frac{\delta^3}{2}\cdots\notag\]

\[=-\delta+\delta^2/2+\cdots\]

<p>과 같다. 따라서</p>

\[(1-\delta)\ln(1-\delta) \gt -\delta +\frac{\delta^2}{2}\]

<p>가 성립하며 로그의 성질에 따라</p>

\[(1-\delta)^{(1-\delta)}\gt\exp\left(-\delta + \frac{\delta^2}{2}\right)\]

<p>가 성립함을 알 수 있다.</p>

<p>따라서, 식 (27)을 식(23)에 대입하면,</p>

\[\left(\frac{e^{-\delta}}{(1-\delta)^{(1-\delta)}}\right)^{E[X]}\lt \left(\frac{e^{-\delta}}{e^{(-\delta+\delta^2/2)}}\right)^{E[X]}\]

\[\Rightarrow \left(\frac{e^{-\delta}}{(1-\delta)^{(1-\delta)}}\right)^{E[X]}\lt \left(e^{-\delta^2/2}\right)^{E[X]}\]

<p>이다. 따라서, 이 결과를 식 (20)과 식 (23)에 대입하면,</p>

\[\Rightarrow P(X\lt (1-\delta)E[X])\lt \exp(-E[X]\delta^2/2)\]

<p>이다.</p>

<p>(증명 끝)</p>

<h2 id="upper-tail-chernoff-bound">Upper-Tail Chernoff Bound</h2>

<p>Upper-Tail 부분에 대한 증명은 Lower-tail에 대한 증명과 거의 유사한 방식으로 진행된다. 따라서 Upper-tail에 대한 증명은 더 빠르게 진행되며 빠르게 넘어간 부분은 Lower-tail 파트 증명에서 참고하기 바란다. 식 (1)과 같은 랜덤변수 $X$에 대해 임의의 $\delta\in(0, 1)$<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>을 선정하면 다음이 성립한다.</p>

\[P(X\gt(1+\delta)E[X]) \lt e^{-E[X]\cdot \delta^2/3}\]

<p>여기서 $e$는 자연로그의 밑이다.</p>

<p>(증명)</p>

<p>Lower-tail에 대한 증명에서와 마찬가지로 아래를 증명하는 것이 첫 스텝이다.</p>

\[P(X\gt(1+\delta)E[X]) \lt \left(\frac{e^\delta}{(1+\delta)^{(1+\delta)}}\right)^{E[X]}\]

<p>이 때 $t&gt;0$인 매개변수를 도입하고 $X$에 대한 식은 $e^tX$에 대한 식으로 바꾸자. 식 (32)의 좌변 정보를 이용하여 마르코프 부등식을 적용하면 아래와 같은 식을 얻을 수 있다.</p>

\[P(X\gt(1+\delta)E[X]) \leq \frac{E[e^{tX}]}{e^{t(1+\delta)E[X]}}\]

<p>식 (1)의 $X$의 정의에 따라 식 (33) 우변의 분자만 따로 떼서 생각하면 다음과 같이 쓸 수도 있다는 것을 알 수 있다.</p>

\[E[e^{tX}]=E[e^{t\sum_i X_i}]=E\left[\prod_{i=1}^{N}e^{tX_i}\right]=\prod_{i=1}^{N}E[e^{tX_i}]\]

<p>이다.</p>

<p>한편, $X_i$는 베르누이 시행이므로, 식 (9)가 성립하고, $e^{tX_i}$의 기댓값은 다음과 같다.</p>

\[E[e^{tX_i}]=(1-p_i)e^{t\cdot 0}+p_i e^{t\cdot 1}=1-p_i+p_ie^t\notag\]

\[=1+p_i(e^t-1)=1+E[X_i](e^t-1)\]

<p>또, 식 (35)의 마지막 식은 $\exp(1+E[X_i]\cdot(e^t-1))$의 테일러 급수 첫 두항과 일치한다. 즉,</p>

\[\exp(x) = 1+\frac{x}{1!}+\frac{x^2}{2}+\cdots\]

<p>이므로 $\exp(E[X_i]\cdot(e^t-1))$은</p>

\[\exp(E[X_i]\cdot(e^t-1))=1+E[X_i](e^t-1)+\frac{1}{2!}(E[X_i](e^t-1))^2+\cdots \notag\]

\[\gt 1+E[X_i](e^t-1)\]

<p>이다. 따라서, 식 (34)에서의 마지막 결과값에 대해 다음과 같이 정리할 수 있다.</p>

\[\prod_{i=1}^{N}E[e^{tX_i}]=\prod_{i=1}^{N}(1+E[X](e^t-1))&lt;\prod_{i=1}^{N}\exp(E[X_i](e^t-1))\]

<p>한편,</p>

\[\prod_{i=1}^{N}\exp(E[X_i](e^t-1))=\exp\left(E\left[\sum_{i=1}^{N}X_i\right](e^t-1)\right)=\exp(E[X](e^t-1))\]

<p>이므로 위 결과를 식 (33)에 대입하면,</p>

\[P(X\gt(1+\delta)E[X])\leq \frac{\exp(E[X](e^t-1))}{e^{t(1+\delta)E[X]}}\]

<p>임을 알 수 있다. Lower-tail boundary에서와 마찬가지로 식 (40)의 우변을 미분하여, 미분 계수를 0으로 만들어줄 수 있는 가장 tight한 $t=t^\ast$를 찾으면 다음과 같다.</p>

\[t^\ast=\ln(1+\delta)\]

<p>식 (41)을 식 (40)에 대입하면 식 (32)를 얻을 수 있게 된다.</p>

\[P(X\gt(1+\delta)E[X]) \leq \frac{\exp(E[X](e^{\ln(1+\delta)}-1))}{\exp((1+\delta)E[X]\ln(1+\delta))}\]

\[\Rightarrow P(X\gt(1+\delta)E[X]) \leq \frac{\exp(E[X]\delta)}{(1+\delta)^{(1+\delta)E[X]}}\]

\[\Rightarrow P(X\gt(1+\delta)E[X]) \leq \left(\frac{e^\delta}{(1+\delta)^{(1+\delta)}}\right)^{E[X]}\]

<p>식 (44)로부터 식 (31)을 증명하기 위해선 아래의 수식이 사실인지 확인하면 된다.</p>

\[\frac{e^\delta}{(1+\delta)^{(1+\delta)}}&lt;e^{-\mu^2/3}\]

<p>식 (45)의 양변에 로그를 취하면 아래와 같은 식을 얻을 수 있다.</p>

\[f(\delta) = \delta - (1+\delta)\ln (1+\delta) + \frac{\delta^2}{3}&lt; 0\]

<p>$f(\delta)$의 미분계수를 구하면 아래와 같다.</p>

\[f'(\delta) = 1-\frac{1+\delta}{1+\delta}-\ln(1+\delta)+\frac{2}{3}\delta = -\ln(1+\delta)+\frac{2}{3}\delta\]

\[f''(\delta) = - \frac{1}{1+\delta}+\frac{2}{3}\]

<p>여기서 2계 도함수로부터 알 수 있는 것은 아래와 같다.</p>

\[\begin{cases}f''(\delta)\lt 0\text{ for } 0\leq \delta \lt 1/2 \\ f''(\delta) &gt; 0 \text{ for } \delta &gt;1/2\end{cases}\]

<p>다시 말해, $f’(\delta)$는 $(0,1)$ 구간에서 처음에는 감소하다가 증가하게 되는 형태를 띈다는 것이다. 또한, 1계 도함수 식을 보면 $f’(0)=0$이고 $f’(1)\lt 0$이라는 사실이다. 따라서, $(0,1)$ 구간에서 $f’(\delta)\lt 0$이라는 사실을 알 수 있다. 마지막으로 $f(0)=0$이므로 $(0,1)$ 구간에서 $f(\delta)$는 항상 음수임을 알 수 있다.</p>

<p>그러므로, 식 (46)은 사실임을 알 수 있고 식 (31) 또한 성립하는 것이다.</p>

<p>(증명 끝)</p>

<h1 id="reference">Reference</h1>

<ul>
  <li>Outlier Analysis (2nd e.d), Charu C. Aggarwal, Springer</li>
  <li>Probability and Computing (2nd e.d.), Michael Mitzenmacher and Eli Upfal, Cambridge University Press</li>
</ul>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>책 Outlier Analysis (Charu C. Aggarwal)에서는 (0, 2e-1)의 범위에서 성립하는 Chernoff Bound를 보여주고 있으나 아직까지 어떻게 증명해야 하는지 잘 모르겠다. 그래서 다른 교과서에서 소개하고 있는 (0, 1) 바운드에 대한 Chernoff Bound를 소개한다. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Angelo Yeo</name><email>angeloyeo@gmail.com</email></author><category term="통계학" /><summary type="html"><![CDATA[prerequisites 본 포스트를 잘 이해하기 위해선 아래의 내용에 대해 알고 오는 것이 좋습니다. 마르코프 부등식과 체비셰프 부등식 증명 Chernoff 부등식은 Lower-tail 버전과 Upper-tail 버전의 형태가 다르다. 아래에서는 증명 과정을 소개하고자 한다. Lower-Tail Chernoff Bound $X$가 $N$ 개의 독립적인 랜덤변수의 합이라고 하자. 또, 이때 이 랜덤 변수들은 베르누이 분포를 따르며 $p_i$의 확률로 1의 값을 갖는다고 하자. \[X = \sum_{i=1}^{N}X_i\] 이 때, 임의의 $\delta\in (0, 1)$에 대해 다음이 성립한다. \[P(X \lt (1-\delta)E[X]) \lt e^{-E[X]\cdot \delta^2/2}\] 여기서 $e$는 자연로그의 밑이다. (증명) 우선 아래의 부등식이 성립한다는 것을 증명하자. \[P(X \lt (1-\delta) E[X]) \lt \left(\frac{e^{-\delta}}{(1-\delta)^{(1-\delta)}}\right)^{E[X]}\] 이를 증명하기 위해 임의의 매개변수 $t&gt;0$을 도입하자. 이 $t$를 이용해 우리는 $X$에 대한 식을 $e^{-tX}$에 대한 식으로 변환할 것이다. 이 방법은 적률생성함수(moment generating function)을 활용하는 원리와 유사하게 볼 수 있는데, 원래의 $X$ domain에서 풀기 어려운 문제를 매개변수 $t$ 도메인으로 옮겨 문제를 상대적으로 쉽게 풀기 위함이라고 볼 수도 있다. 식 (3)을 증명하기 위해 마르코프 부등식의 식을 $X$ 대신 $e^{-tX}$에 맞춰 수정하자. 원래의 마르코프 부등식은 아래와 같다. \[P(X\lt \alpha) \leq \frac{E[X]}{\alpha}\] 여기서 우변을 바꿔주면, \[P(X\lt\alpha) \leq \frac{E[e^{-tX}]}{e^{-t\alpha}}\] 가 된다. 식 (5)를 식 (2)의 좌변에 맞춰 적용하면 결과는 아래와 같다. 여기서 $\alpha = (1-\delta)E[X]$이므로, \[\Rightarrow P(X\lt (1-\delta)E[X]) \leq \frac{E[e^{-tX}]}{e^{-t(1-\delta)E[X]}}\] 이 성립한다. 또 $X$를 구성하고 있는 $X_i$ 들은 독립적으로 발생한 사건이다. 위 식의 우변의 분자를 보면, \[E[e^{-tX}]=E[e^{-t\cdot\sum_{i}X_i}]=E[e^{-t(X_1+X_2+\cdots+X_N)}]\notag\] \[=E[e^{-tX_1}\cdot e^{-tX_2}\cdot e^{-tX_3}\cdot \cdots \cdot e^{-t X_N}]\] 과 같이 쓸 수 있는데, 독립 랜덤 변수의 곱의 기댓값은 기댓값들의 곱이므로 위 식은 아래와 같이 고쳐쓸 수 있다. \[\Rightarrow E[e^{-tX_1}\cdot e^{-tX_2}\cdots e^{-tX_N}]=\prod_{i=1}^{N}E[e^{-tX_i}]\] 위 식의 $E[e^{-tX_i}]$를 자세히 보면 베르누이 분포를 따르는 시행 $X_i$에 대한 변환식 $e^{-tX_i}$의 기댓값임을 알 수 있다. $X_i$는 $(1-p_i)$ 혹은 $p_i$의 확률로 0 또는 1의 값을 가지므로 $X_i$의 기댓값은 \[E[X_i] = (1-p_i)\cdot 0 + p_i \cdot 1 = p_i\] 이며, $e^{-tX_i}$의 기댓값은 \[E[e^{-tX_i}]=(1-p_i)e^{-t\cdot 0}+p_i e^{-t\cdot 1}\notag\] \[=1-p_i + p_i e^{-t}=1+p_i(e^{-t}-1)\notag\] \[= 1+E[X_i](e^{-t}-1)\] 임을 알 수 있다. 또한 위 식의 마지막 결과물은 $\exp(E[X_i]\cdot(e^{-t}-1))$의 테일러 급수 두 항과 일치한다는 점을 고려하면 다음이 성립함을 알 수 있다. \[E[e^{-tX_i}]=1+E[X_i](e^{-t}-1) \lt e^{E[X_i](e^{-t}-1)}\] 식 (11)을 식 (8)에 다시 대입하면, \[\prod_{i=1}^{N}E[e^{-tX_i}]\lt\prod_{i=1}^{N}e^{E[X_i](e^{-t}-1)}\] 이 성립하게 됨을 알 수 있는데, 위 식의 우변을 또 다시 쓰면, \[\prod_{i=1}^{N}\exp(E[X_i](e^{-t}-1))=\exp\left(\sum_{i=1}^{N}E[X_i]\cdot (e^{-t}-1)\right)\notag\] \[=\exp\left(E[X](e^{-t}-1)\right)\] 이다. 따라서 식 (13)의 결과를 식 (6)에 대입하면 아래와 같은 식을 얻을 수 있다. \[P(X&lt;(1-\delta)E[X]) \leq \frac{\exp\left(E[X](e^{-t}-1)\right)}{\exp\left(-t(1-\delta)E[X]\right)}\] 위 식은 어떤 $t&gt;0$에 대해서라도 성립하는 식이다. 이제는 식 (14)가 최대한 tight한 boundary에 대해 성립할 수 있도록 식 (14)의 최소값을 내주는 $t=t^\ast$ 값을 찾자. 이 과정은 식 (14)를 미분하고 미분한 값이 $0$이 되는 $t^\ast$를 찾음으로써 해결할 수 있다. 식 (14)의 우변에 지수법칙을 적용하여 한줄로 쓰면 다음과 같다. \[\exp(E[X](e^{-t}-1)+t(1-\delta)E[X])\] 이를 조금만 더 정리하고 $f(t)$라고 이름 붙이자. \[f(t) = \exp\left(E[X]e^{-t}-E[X]+tE[X]-t\delta E[X]\right)\notag\] \[=\exp\left(E[X](e^{-t}+t-t\delta -1)\right)\] 이제 $f(t)$를 $t$에 대해 미분하면, \[f'(t) = \exp\left(E[X](e^{-t}+t-t\delta -1)\right)(E[X])(e^{-t}+1-\delta)\] 임을 알 수 있다. 식 (17)에서 맨 앞의 $\exp()$ 함수는 항상 양수이며 $E[X]$ 역시 양수이다. 따라서, 가장 오른쪽의 괄호 안의 값만 0이 되도록 하면 $t=t^\ast$를 찾을 수 있다. 따라서, \[e^{-t}+1-\delta = 0\] 을 만족하는 $t=t^\ast$는 \[t=t^\ast = \ln\left(\frac{1}{1-\delta}\right)\] 이다. 식 (19)를 식 (14)에 대입하면 식 (3)을 얻을 수 있게 된다. 식 (19)를 식 (14)에 대입하면, \[\Rightarrow P(X&lt;(1-\delta) E[X])\leq \frac{\exp\left(E[X]\left(e^{-\ln\left(1/(1-\delta)\right)}-1\right)\right)}{\exp\left(-\ln(1/(1-\delta))(1-\delta)E[X]\right)}\] 여기서 우변만 보면 다음과 같다. \[\text{(우변)}\Rightarrow \frac{\exp(E[X](1-\delta -1))}{\exp(-(1-\delta)E[X]\ln\left(1/(1-\delta)\right))}\] \[=\frac{\exp(E[X](-\delta))}{\exp(\ln(1-\delta)^{(1-\delta E[X])})}=\frac{\exp(-\delta E[X])}{(1-\delta)^{(1-\delta)E[X]}}\] \[=\left(\frac{e^{-\delta}}{(1-\delta)^{(1-\delta)}}\right)^{E[X]}\] 한편, \[\ln(1-x)=-x-\frac{x^2}{2}-\frac{x^3}{3}\cdots = -\sum_{i=1}^{N}\frac{x^n}{n}\] 이므로, \[(1-\delta)\ln(1-\delta) = - (1-\delta)\delta - (1-\delta)\frac{\delta^2}{2}\cdots\notag\] \[=-\delta+\delta^2-\frac{\delta^2}{2}+\frac{\delta^3}{2}\cdots\notag\] \[=-\delta+\delta^2/2+\cdots\] 과 같다. 따라서 \[(1-\delta)\ln(1-\delta) \gt -\delta +\frac{\delta^2}{2}\] 가 성립하며 로그의 성질에 따라 \[(1-\delta)^{(1-\delta)}\gt\exp\left(-\delta + \frac{\delta^2}{2}\right)\] 가 성립함을 알 수 있다. 따라서, 식 (27)을 식(23)에 대입하면, \[\left(\frac{e^{-\delta}}{(1-\delta)^{(1-\delta)}}\right)^{E[X]}\lt \left(\frac{e^{-\delta}}{e^{(-\delta+\delta^2/2)}}\right)^{E[X]}\] \[\Rightarrow \left(\frac{e^{-\delta}}{(1-\delta)^{(1-\delta)}}\right)^{E[X]}\lt \left(e^{-\delta^2/2}\right)^{E[X]}\] 이다. 따라서, 이 결과를 식 (20)과 식 (23)에 대입하면, \[\Rightarrow P(X\lt (1-\delta)E[X])\lt \exp(-E[X]\delta^2/2)\] 이다. (증명 끝) Upper-Tail Chernoff Bound Upper-Tail 부분에 대한 증명은 Lower-tail에 대한 증명과 거의 유사한 방식으로 진행된다. 따라서 Upper-tail에 대한 증명은 더 빠르게 진행되며 빠르게 넘어간 부분은 Lower-tail 파트 증명에서 참고하기 바란다. 식 (1)과 같은 랜덤변수 $X$에 대해 임의의 $\delta\in(0, 1)$1을 선정하면 다음이 성립한다. \[P(X\gt(1+\delta)E[X]) \lt e^{-E[X]\cdot \delta^2/3}\] 여기서 $e$는 자연로그의 밑이다. (증명) Lower-tail에 대한 증명에서와 마찬가지로 아래를 증명하는 것이 첫 스텝이다. \[P(X\gt(1+\delta)E[X]) \lt \left(\frac{e^\delta}{(1+\delta)^{(1+\delta)}}\right)^{E[X]}\] 이 때 $t&gt;0$인 매개변수를 도입하고 $X$에 대한 식은 $e^tX$에 대한 식으로 바꾸자. 식 (32)의 좌변 정보를 이용하여 마르코프 부등식을 적용하면 아래와 같은 식을 얻을 수 있다. \[P(X\gt(1+\delta)E[X]) \leq \frac{E[e^{tX}]}{e^{t(1+\delta)E[X]}}\] 식 (1)의 $X$의 정의에 따라 식 (33) 우변의 분자만 따로 떼서 생각하면 다음과 같이 쓸 수도 있다는 것을 알 수 있다. \[E[e^{tX}]=E[e^{t\sum_i X_i}]=E\left[\prod_{i=1}^{N}e^{tX_i}\right]=\prod_{i=1}^{N}E[e^{tX_i}]\] 이다. 한편, $X_i$는 베르누이 시행이므로, 식 (9)가 성립하고, $e^{tX_i}$의 기댓값은 다음과 같다. \[E[e^{tX_i}]=(1-p_i)e^{t\cdot 0}+p_i e^{t\cdot 1}=1-p_i+p_ie^t\notag\] \[=1+p_i(e^t-1)=1+E[X_i](e^t-1)\] 또, 식 (35)의 마지막 식은 $\exp(1+E[X_i]\cdot(e^t-1))$의 테일러 급수 첫 두항과 일치한다. 즉, \[\exp(x) = 1+\frac{x}{1!}+\frac{x^2}{2}+\cdots\] 이므로 $\exp(E[X_i]\cdot(e^t-1))$은 \[\exp(E[X_i]\cdot(e^t-1))=1+E[X_i](e^t-1)+\frac{1}{2!}(E[X_i](e^t-1))^2+\cdots \notag\] \[\gt 1+E[X_i](e^t-1)\] 이다. 따라서, 식 (34)에서의 마지막 결과값에 대해 다음과 같이 정리할 수 있다. \[\prod_{i=1}^{N}E[e^{tX_i}]=\prod_{i=1}^{N}(1+E[X](e^t-1))&lt;\prod_{i=1}^{N}\exp(E[X_i](e^t-1))\] 한편, \[\prod_{i=1}^{N}\exp(E[X_i](e^t-1))=\exp\left(E\left[\sum_{i=1}^{N}X_i\right](e^t-1)\right)=\exp(E[X](e^t-1))\] 이므로 위 결과를 식 (33)에 대입하면, \[P(X\gt(1+\delta)E[X])\leq \frac{\exp(E[X](e^t-1))}{e^{t(1+\delta)E[X]}}\] 임을 알 수 있다. Lower-tail boundary에서와 마찬가지로 식 (40)의 우변을 미분하여, 미분 계수를 0으로 만들어줄 수 있는 가장 tight한 $t=t^\ast$를 찾으면 다음과 같다. \[t^\ast=\ln(1+\delta)\] 식 (41)을 식 (40)에 대입하면 식 (32)를 얻을 수 있게 된다. \[P(X\gt(1+\delta)E[X]) \leq \frac{\exp(E[X](e^{\ln(1+\delta)}-1))}{\exp((1+\delta)E[X]\ln(1+\delta))}\] \[\Rightarrow P(X\gt(1+\delta)E[X]) \leq \frac{\exp(E[X]\delta)}{(1+\delta)^{(1+\delta)E[X]}}\] \[\Rightarrow P(X\gt(1+\delta)E[X]) \leq \left(\frac{e^\delta}{(1+\delta)^{(1+\delta)}}\right)^{E[X]}\] 식 (44)로부터 식 (31)을 증명하기 위해선 아래의 수식이 사실인지 확인하면 된다. \[\frac{e^\delta}{(1+\delta)^{(1+\delta)}}&lt;e^{-\mu^2/3}\] 식 (45)의 양변에 로그를 취하면 아래와 같은 식을 얻을 수 있다. \[f(\delta) = \delta - (1+\delta)\ln (1+\delta) + \frac{\delta^2}{3}&lt; 0\] $f(\delta)$의 미분계수를 구하면 아래와 같다. \[f'(\delta) = 1-\frac{1+\delta}{1+\delta}-\ln(1+\delta)+\frac{2}{3}\delta = -\ln(1+\delta)+\frac{2}{3}\delta\] \[f''(\delta) = - \frac{1}{1+\delta}+\frac{2}{3}\] 여기서 2계 도함수로부터 알 수 있는 것은 아래와 같다. \[\begin{cases}f''(\delta)\lt 0\text{ for } 0\leq \delta \lt 1/2 \\ f''(\delta) &gt; 0 \text{ for } \delta &gt;1/2\end{cases}\] 다시 말해, $f’(\delta)$는 $(0,1)$ 구간에서 처음에는 감소하다가 증가하게 되는 형태를 띈다는 것이다. 또한, 1계 도함수 식을 보면 $f’(0)=0$이고 $f’(1)\lt 0$이라는 사실이다. 따라서, $(0,1)$ 구간에서 $f’(\delta)\lt 0$이라는 사실을 알 수 있다. 마지막으로 $f(0)=0$이므로 $(0,1)$ 구간에서 $f(\delta)$는 항상 음수임을 알 수 있다. 그러므로, 식 (46)은 사실임을 알 수 있고 식 (31) 또한 성립하는 것이다. (증명 끝) Reference Outlier Analysis (2nd e.d), Charu C. Aggarwal, Springer Probability and Computing (2nd e.d.), Michael Mitzenmacher and Eli Upfal, Cambridge University Press 책 Outlier Analysis (Charu C. Aggarwal)에서는 (0, 2e-1)의 범위에서 성립하는 Chernoff Bound를 보여주고 있으나 아직까지 어떻게 증명해야 하는지 잘 모르겠다. 그래서 다른 교과서에서 소개하고 있는 (0, 1) 바운드에 대한 Chernoff Bound를 소개한다. &#8617;]]></summary></entry></feed>