<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://min0219.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://min0219.github.io/" rel="alternate" type="text/html" /><updated>2025-02-27T23:31:03+09:00</updated><id>https://min0219.github.io/feed.xml</id><title type="html">MIN:D</title><subtitle>I am studying **Computer Science, Deep Learning**.</subtitle><author><name>SeokMin</name></author><entry><title type="html">[Pytorch] 02 - 자동미분(autograd)</title><link href="https://min0219.github.io/pytorch/Pytorch02/" rel="alternate" type="text/html" title="[Pytorch] 02 - 자동미분(autograd)" /><published>2025-02-27T00:00:00+09:00</published><updated>2025-02-27T00:00:00+09:00</updated><id>https://min0219.github.io/pytorch/Pytorch02</id><content type="html" xml:base="https://min0219.github.io/pytorch/Pytorch02/"><![CDATA[<p>본문에서는 Pytorch의 가장 중요한 기능 중 하나인 자동미분, 즉 Autograd에 대해 다룬다. Deep Neural Network(이하 DNN)에서 미분은 Back propagation을 위한 필수적인 개념이다. 이를 Pytorch에서 제공함으로써 DNN을 쉽게 구현할 수 있다.</p>

<h2 id="21---자동미분">2.1 - 자동미분</h2>

<p>pytorch에서 autograd는 tensor 단위로 실행된다. 이때, 역전파를 통해 계산된  gradient는 <strong>leaf tensor</strong>에만 저장된다.</p>

<ul>
  <li><strong>leaf tensor</strong> : tensor로 이루어진 연산 graph의 마지막에 위치한 tensor를 의미하며, 다른 tensor의 연산으로 생성되지 않은 tensor이다. 즉, 사용자가 명시적으로 정의한 tensor를 말한다. <code class="language-plaintext highlighter-rouge">requires_grad=True</code> 로 설정하여 gradient 계산을 허용한다.</li>
  <li>
    <p>즉, <code class="language-plaintext highlighter-rouge">x</code>라는 tensor를 정의하고 <code class="language-plaintext highlighter-rouge">y</code>는 <code class="language-plaintext highlighter-rouge">x**2</code> 라면 <code class="language-plaintext highlighter-rouge">y</code> 에 대한 <code class="language-plaintext highlighter-rouge">x</code> 의 gradient가 <code class="language-plaintext highlighter-rouge">x</code> 에 저장된다. 미분을 시행할 시에는 <code class="language-plaintext highlighter-rouge">y.backward()</code> 명령어를 통해 실행한다. 아래 code를 보면 이해가 수월할 것이다.</p>

    <hr />

    <p>(code)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">x</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mf">1.</span><span class="p">],</span> <span class="n">requires_grad</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
  <span class="n">y</span> <span class="o">=</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span>
  <span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">grad</span><span class="p">)</span>
  <span class="n">y</span><span class="p">.</span><span class="n">backward</span><span class="p">()</span> <span class="c1"># 미분 실행
</span>  <span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">grad</span><span class="p">)</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  None
  tensor([2.])
</code></pre></div>    </div>

    <p>위 code에서 <code class="language-plaintext highlighter-rouge">y.backward()</code> 실행 전에는 미분이 되지 않았기 때문에 <code class="language-plaintext highlighter-rouge">x.grad</code> 의 값이 <code class="language-plaintext highlighter-rouge">None</code> 인 것을 확인할 수 있다. 그러나 실행 후에는 <code class="language-plaintext highlighter-rouge">y</code> 를 미분한 <code class="language-plaintext highlighter-rouge">2x</code> 에 <code class="language-plaintext highlighter-rouge">x</code> 의 값인 1을 대입한 2가 나온다.</p>
  </li>
</ul>

<h2 id="22---미분-불가능">2.2 - 미분 불가능</h2>

<p>그렇다면 자동 미분은 모든 형태의 함수에 사용할 수 있을까? 답은 아니다. 수학에서의 미분이 그러하듯 자동 미분 또한 미분 가능한 함수에서만 적용 가능하다.</p>

<blockquote>
  <p>예시로, <strong>argmax</strong> 함수는 미분 불가능하다.  따라서 이를 실행한다면 error가 발생한다.</p>

</blockquote>

<hr />

<p>(code)</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mf">1.</span><span class="p">],</span> <span class="n">requires_grad</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span><span class="p">.</span><span class="n">argmax</span><span class="p">()</span>

<span class="n">y</span><span class="p">.</span><span class="n">backward</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">grad</span><span class="p">)</span>
</code></pre></div></div>

<p>(결과)</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
</code></pre></div></div>

<p>위 code의 결과는 RuntimeError로, 미분 불가능한 함수라는 이유를 볼 수 있다. 즉, 미분 불가능한 함수는 자동미분이 적용되지 않는다.</p>

<h2 id="23---non-leaf-tensor의-gradient-확인">2.3 - non leaf tensor의 gradient 확인</h2>

<p>위에서 gradient는 leaf tensor에만 저장된다고 설명하였다. 그렇다면 non-leaf tensor의 gradient를 저장하고 싶을 때에는 어떻게 해야 할까. <code class="language-plaintext highlighter-rouge">.retain_grad()</code> 를 사용하면 된다.</p>

<hr />

<p>(code)</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mf">1.</span><span class="p">],</span> <span class="n">requires_grad</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span>
<span class="n">y</span><span class="p">.</span><span class="n">retain_grad</span><span class="p">()</span>
<span class="n">z</span> <span class="o">=</span> <span class="mi">3</span><span class="o">*</span><span class="n">y</span>
<span class="n">z</span><span class="p">.</span><span class="n">backward</span><span class="p">()</span>

<span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">grad</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">y</span><span class="p">.</span><span class="n">grad</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">z</span><span class="p">.</span><span class="n">grad</span><span class="p">)</span>
</code></pre></div></div>

<p>(결과)</p>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tensor([6.])
tensor([3.])
None
</code></pre></div></div>

<p>위 결과에서 <code class="language-plaintext highlighter-rouge">y</code> 는 gradient가 존재하고, <code class="language-plaintext highlighter-rouge">z</code> 에는 gradient가 존재하지 않는다. 이는 <code class="language-plaintext highlighter-rouge">y</code> 에만 <code class="language-plaintext highlighter-rouge">.retain_grad()</code> 를 적용했기 때문이다.</p>

<h2 id="24---training-시-autograd">2.4 - training 시 autograd</h2>

<p>model을 training 시 또는 transfer learning에 이용할 때는 parameter를 update하면 안 된다. 이 때, 크게 세 가지 방법을 통해 gradient update를 막을 수 있다.</p>

<ol>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.requires_grad=False</code> 를 통해 gradient update를 <strong>중지</strong>한다.</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">x</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mf">1.</span><span class="p">],</span><span class="n">requires_grad</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
 <span class="n">y</span> <span class="o">=</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span>
    
 <span class="n">x</span><span class="p">.</span><span class="n">requires_grad</span><span class="o">=</span><span class="bp">False</span>
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.detach()</code> 를 통해 gradient를 <strong>중지</strong>한다.</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">x</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mf">1.</span><span class="p">],</span><span class="n">requires_grad</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
 <span class="n">y</span> <span class="o">=</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span>
    
 <span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="p">.</span><span class="n">detach</span><span class="p">()</span>
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.no_grad()</code> 를 통해 gradient를 <strong>일시중지</strong>한다.</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">x</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mf">1.</span><span class="p">],</span> <span class="n">requires_grad</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
 <span class="k">with</span> <span class="n">torch</span><span class="p">.</span><span class="n">no_grad</span><span class="p">():</span>
 	<span class="n">y</span><span class="o">=</span><span class="n">x</span><span class="o">**</span><span class="mi">2</span>
 <span class="n">y</span> <span class="o">=</span> <span class="n">x</span><span class="o">**</span><span class="mi">2</span>
</code></pre></div>    </div>
  </li>
</ol>]]></content><author><name>SeokMin</name></author><category term="Pytorch" /><summary type="html"><![CDATA[본문에서는 Pytorch의 가장 중요한 기능 중 하나인 자동미분, 즉 Autograd에 대해 다룬다. Deep Neural Network(이하 DNN)에서 미분은 Back propagation을 위한 필수적인 개념이다. 이를 Pytorch에서 제공함으로써 DNN을 쉽게 구현할 수 있다.]]></summary></entry><entry><title type="html">[Pytorch] 01 - Pytorch 기초 (Tensor)</title><link href="https://min0219.github.io/pytorch/Pytorch01/" rel="alternate" type="text/html" title="[Pytorch] 01 - Pytorch 기초 (Tensor)" /><published>2025-02-12T00:00:00+09:00</published><updated>2025-02-12T00:00:00+09:00</updated><id>https://min0219.github.io/pytorch/Pytorch01</id><content type="html" xml:base="https://min0219.github.io/pytorch/Pytorch01/"><![CDATA[<p><img src="/images/2025-02-12-Pytorch01/pytorch_logo.png" alt="pytorch_logo" /></p>

<p>본문에서는 Pytorch 사용을 위한 전반적인 내용들과 코드에 대한 설명을 다룬다.</p>

<p>특히, Tensor의 정의와 Tensor를 대상으로 하는 함수들에 대해 다룸으로써 딥러닝 및 머신러닝 구현에 필수적인 내용을 알아본다.</p>

<p>본문에서 작성한 명령어 중 <code class="language-plaintext highlighter-rouge">tensor.함수이름()</code> 의 <code class="language-plaintext highlighter-rouge">tensor</code> 는 정의된 Tensor 를 뜻하며, 일관성을 위해 통일하였다.</p>

<h2 id="11---tensor-정의">1.1 - Tensor 정의</h2>

<p>딥러닝에서 Tensor는 간단하게 행렬(matrix)의 집합이라고 정의할 수 있다. 특히, 주로 3 차원 이상의 배열의 집합을 Tensor라고 한다.</p>

<ul>
  <li><strong>Vector</strong> : 1d-tensor 라고도 표현한다.</li>
  <li><strong>Matrix</strong> : 2d-tensor 라고도 표현한다.</li>
</ul>

<p>Tensor의 정의는 Pytorch에서 <code class="language-plaintext highlighter-rouge">torch.tensor()</code> 함수를 통해 이루어진다.</p>

<p>이 함수를 통해 numpy의 array를 tensor로 변환할 수도 있다.</p>

<hr />

<p>(코드)</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">torch</span>
<span class="kn">import</span> <span class="nn">numpy</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">numpy</span><span class="p">.</span><span class="n">array</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="12---tensor-모양-차원">1.2 - Tensor 모양, 차원</h2>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.shape</code> : Tensor의 모양을 반환한다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]])</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">shape</span><span class="p">)</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  torch.Size([2, 3])
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.ndim</code> : Tensor의 차원 수를 반환한다.</p>

    <p>예를 들어, 2<em>3 행렬 같은 경우 2를, 2</em>3*4 tensor같은 경우 3을 반환한다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]])</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">ndim</span><span class="p">)</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  2
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.numel()</code> : Tensor의 성분 개수를 반환한다.</p>

    <p>Tensor 안의 모든 성분의 개수를 반환하는 함수이다. 이 함수는 특히 Network의 parameter 수를 파악할 때 유용하게 사용된다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]])</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">numel</span><span class="p">())</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  6
</code></pre></div>    </div>
  </li>
</ul>

<h2 id="13---indexing--slicing">1.3 - Indexing &amp; Slicing</h2>

<h3 id="indexing--slicing">Indexing &amp; slicing</h3>

<ul>
  <li>
    <p><strong>Indexing &amp; Slicing</strong> : Pytorch에서 Tensor의 indexing은 python에서 list의 indexing과 유사하다. 그러나 일부 차이점이 있으며, 이는 대규모 data를 다룰 때 편리한 기능을 제공한다.</p>

    <p><code class="language-plaintext highlighter-rouge">tensor[시작 : 마지막 전 : 간격]</code> 명령어를 통해 indexing 및 slicing을 진행한다. 이는 list의 그것과 동일하다. 그러나 아래 명령어들은 list와 차별화 된다.</p>

    <ul>
      <li><code class="language-plaintext highlighter-rouge">tensor[1,3]</code> : <code class="language-plaintext highlighter-rouge">tensor[1][3]</code> 과 같은 명령어이다.</li>
      <li><code class="language-plaintext highlighter-rouge">tensor[ : , 3]</code> : 모든 행의 3번째 열</li>
    </ul>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span>
      <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span>
      <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span>
      <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">9</span><span class="p">]</span>
  <span class="p">])</span>
    
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">])</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">[:,</span><span class="mi">2</span><span class="p">])</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor(6)
  tensor([3, 6, 9])
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="boolean-indexing">Boolean Indexing</h3>

<ul>
  <li>
    <p><strong>Boolean Indexing</strong> : Pytorch는 tensor에 대해 boolean 연산을 지원한다.</p>

    <p>즉, boolean 연산을 통해 원하는 조건을 만족하는 요소들의 index 혹은 해당 요소들을 직접 얻을 수 있다.</p>

    <p>아래는 가장 기본이 되는 조건문을 통한  boolean indexing이다. 조건문을 만족하는 요소 혹은 boolean 값을 얻을 수 있다.</p>

    <ul>
      <li>
        <p><code class="language-plaintext highlighter-rouge">tensor == 10</code> : tensor의 각 요소에 대해 10과 같으면 True, 다르면 False 반환</p>

        <hr />

        <p>(코드)</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">])</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="o">==</span><span class="mi">3</span><span class="p">)</span>
</code></pre></div>        </div>

        <p>(결과)</p>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([False, False,  True, False, False, False])
</code></pre></div>        </div>
      </li>
      <li>
        <p><code class="language-plaintext highlighter-rouge">tensor[tensor==10]]</code> : tensor의 요소 중 10인 요소들만 return한다.</p>

        <hr />

        <p>(코드)</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">])</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">a</span><span class="o">==</span><span class="mi">3</span><span class="p">])</span>
</code></pre></div>        </div>

        <p>(결과)</p>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([3])
</code></pre></div>        </div>
      </li>
    </ul>

    <p>역으로, boolean 값을 통해 <code class="language-plaintext highlighter-rouge">True</code> 인 자리의 요소만 얻을 수 있다.</p>

    <ul>
      <li>
        <p><strong>같은 shape</strong>의 boolean tensor을 이용한 indexing</p>

        <hr />

        <p>(코드)</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">])</span>
  <span class="n">b</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">])</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">b</span><span class="p">])</span>
</code></pre></div>        </div>

        <p>(결과)</p>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([1, 4])
</code></pre></div>        </div>
      </li>
      <li>
        <p><strong>[행], [열]</strong>로 indexing : 아래 코드에서 첫 째 list는 행의 위치를, 두 번째 list는 열의 위치를 나타낸다. 따라서 1행과 4행의 두 번째 열에 해당되는 요소를 return 한다.</p>

        <hr />

        <p>(코드)</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span>
      <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">],[</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],[</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">]</span>
  <span class="p">])</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">[[</span><span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">True</span><span class="p">],</span> <span class="p">[</span><span class="bp">False</span><span class="p">,</span> <span class="bp">True</span><span class="p">]])</span>
</code></pre></div>        </div>

        <p>(결과)</p>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([2, 8])
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
</ul>

<h3 id="tensor로-indexing">Tensor로 Indexing</h3>

<ul>
  <li><strong>Tensor로 Indexing</strong> : 파이썬의 list indexing에서는 <code class="language-plaintext highlighter-rouge">[ ]</code> 안에 정수 혹은 <code class="language-plaintext highlighter-rouge">2:5</code> 와 같은 slices만 사용할 수 있다. 그러나 Pytorch의 Tensor에서는 <code class="language-plaintext highlighter-rouge">[ ]</code> 안에 tensor type 또한 사용 가능하며, 이를 통해 다양한 indexing이 가능하다.
    <ul>
      <li>
        <p><code class="language-plaintext highlighter-rouge">tensor[torch.tensor(1)]</code> : <code class="language-plaintext highlighter-rouge">tensor[1]</code> 과 동일하다.</p>

        <hr />

        <p>(코드)</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">])</span>
  <span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="mi">1</span><span class="p">)]</span>
  <span class="k">print</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
</code></pre></div>        </div>

        <p>(결과)</p>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor(2)
</code></pre></div>        </div>
      </li>
      <li>
        <p><code class="language-plaintext highlighter-rouge">tensor[torch.tensor([3,4,5,6])</code> : <code class="language-plaintext highlighter-rouge">tensor[3:7]</code> 과 동일하다.</p>

        <hr />

        <p>(코드)</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">])</span>
  <span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">])</span>
  <span class="k">print</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
</code></pre></div>        </div>

        <p>(결과)</p>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([4,5,6,7])
</code></pre></div>        </div>
      </li>
      <li>
        <p><code class="language-plaintext highlighter-rouge">tensor[torch.tensor([[1,1,1], [3,3,3]])]</code> : <code class="language-plaintext highlighter-rouge">tensor[1]</code>, <code class="language-plaintext highlighter-rouge">tensor[3]</code> 으로 2*3 행렬 생성한다.</p>

        <hr />

        <p>(코드)</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">])</span>
  <span class="n">b</span> <span class="o">=</span> <span class="n">a</span><span class="p">[</span><span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">]])</span>
  <span class="k">print</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
</code></pre></div>        </div>

        <p>(결과)</p>

        <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[2, 2, 2],
          [4, 4, 4]])
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
</ul>

<h2 id="14---pytorch의-여러-함수">1.4 - Pytorch의 여러 함수</h2>

<p>Pytorch에는 Tensor을 위한 여러 함수가 있다. 이 함수들은 Tensor를 이용한 여러 기능을 제공하고, 머신러닝 및 딥러닝 구현을 편리하게 한다.</p>

<h3 id="각종-수학-연산"><strong>각종 수학 연산</strong></h3>

<ul>
  <li>
    <p>각종 수학 연산  : tensor를 입력하면 각 요소에 해당 함수를 적용하여 tensor를 return한다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">abs</span><span class="p">(</span><span class="n">A</span><span class="p">))</span> <span class="c1">#절대값
</span>  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">sqrt</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">abs</span><span class="p">(</span><span class="n">A</span><span class="p">)))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">exp</span><span class="p">(</span><span class="n">A</span><span class="p">))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">log</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">abs</span><span class="p">(</span><span class="n">A</span><span class="p">)))</span>
    
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">log</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">exp</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="mi">1</span><span class="p">))))</span> <span class="c1">#torch 함수 내에는 torch.tensor가 input
</span>  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">log10</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="mi">10</span><span class="p">)))</span> <span class="c1">#1
</span>  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">log2</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="mi">2</span><span class="p">)))</span> <span class="c1">#1
</span>    
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">round</span><span class="p">(</span><span class="n">A</span><span class="p">))</span> <span class="c1">#반올림
</span>  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">round</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">decimals</span><span class="o">=</span><span class="mi">2</span><span class="p">))</span> <span class="c1">#소수점 둘째자리
</span>  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">floor</span><span class="p">(</span><span class="n">A</span><span class="p">))</span> <span class="c1">#내림
</span>  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">ceil</span><span class="p">(</span><span class="n">A</span><span class="p">))</span>  <span class="c1">#올림
</span>    
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">sin</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">pi</span><span class="o">/</span><span class="mi">6</span><span class="p">)))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">cos</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">pi</span><span class="o">/</span><span class="mi">3</span><span class="p">)))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">tan</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">pi</span><span class="o">/</span><span class="mi">4</span><span class="p">)))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">tanh</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="o">-</span><span class="mi">10</span><span class="p">)))</span>
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="tensor-생성함수">Tensor 생성함수</h3>

<ul>
  <li><code class="language-plaintext highlighter-rouge">torch.randn()</code> : Normal Distribution에서 random sampling한 tensor를 주어진 모양의 요소만큼 return한다.
    <ul>
      <li>이때, +n 을 통해 평균을 +n 할 수 있다.</li>
      <li>*n 을 통해 분산을 *n^2 할 수 있다.</li>
    </ul>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a1</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
  <span class="n">a2</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="o">+</span><span class="mi">10</span> <span class="c1">#평균을 10으로 바꿈
</span>  <span class="n">a3</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="o">*</span><span class="mi">10</span> <span class="c1">#분산을 100으로 바꿈
</span></code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[-0.9033,  0.0684, -1.4416],
          [ 0.4585, -0.6715, -0.5306],
          [-0.7244,  0.6607,  0.7440]])
            
  tensor([[10.0661, 10.6357,  9.0546],
          [ 9.7324, 11.3257, 11.1073],
          [10.3477,  9.5452,  9.4528]])
            
  tensor([[ -0.8509,   3.0854, -15.2621],
          [ -0.7088,   3.7370, -10.7181],
          [  0.4594, -13.4798, -14.3943]])
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">torch.randint(a, b, size=(c,d))</code> : a부터 b 미만의 임의의 <strong>정수로 이루어진</strong> c*d 모양의 tensor 생성한다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span> <span class="n">size</span><span class="o">=</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[3, 3, 4, 1],
          [2, 1, 5, 4],
          [6, 3, 1, 6]])
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="max-min-argmax-함수"><strong>max, min, argmax</strong> 함수</h3>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">torch.max(tensor, dim = n, keepdims=True)</code> : tensor를 dim=n으로 접는다. 예를 들어, dim=0이면 열 중 max 값을 구해 결과적으로 행으로 접게 된다. 이 때, keepdims를 True로 설정하면 원본의 차원을 그대로 유지한다.</p>

    <p>(<code class="language-plaintext highlighter-rouge">torch.min()</code> 도 동일)</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">max</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">dim</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">min</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">dim</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">max</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">dim</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">keepdims</span><span class="o">=</span><span class="bp">True</span><span class="p">))</span> 
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[ 0.2120,  1.0677,  0.8159, -0.0084],
          [ 1.7350,  0.3602, -0.4257,  0.7775],
          [-0.4390, -0.6274, -0.5100, -0.7316]])
            
  torch.return_types.max(
  values=tensor([1.7350, 1.0677, 0.8159, 0.7775]),
  indices=tensor([1, 0, 0, 1]))
    
  torch.return_types.max(
  values=tensor([ 1.0677,  1.7350, -0.4390]),
  indices=tensor([1, 0, 0]))
    
  torch.return_types.max(
  values=tensor([[1.7350, 1.0677, 0.8159, 0.7775]]),
  indices=tensor([[1, 0, 0, 1]]))
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">torch.argmax(tensor, dim=n)</code> : tensor의 요소 중 max 값의 index를 반환한다.</p>

    <p>이 때, dim=n 요소를 입력하면 dim=n으로 접는다. 예를  들어 dim=0이면 각 열에서 max 값의 index를 추출하여 반환하게 된다.</p>

    <blockquote>
      <p>주의할 점 : tensor의 차원이 2 이상일 때, dim=n 요소를 주지 않으면 가장 마지막 차원의 index가 반환된다.</p>

    </blockquote>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">argmax</span><span class="p">(</span><span class="n">a</span><span class="p">))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">argmax</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">dim</span><span class="o">=</span><span class="mi">0</span><span class="p">))</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[ 1.2001,  2.4138,  0.9824, -0.4469],
          [ 0.8022,  0.5243, -1.4808,  1.1072],
          [-0.6110, -0.8182, -0.7366,  0.0525]])
            
  tensor(1)
    
  tensor([0, 0, 0, 1])
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="sum-mean-std-함수">sum, mean, std 함수</h3>

<ul>
  <li><code class="language-plaintext highlighter-rouge">torch.sum(tensor, dim=n, keepdims=True)</code> : dim=n으로 쌓은 후 sum 연산을 한다. 예를 들어, 2차원 tensor에서 dim=1 로 설정하면 행 별로 더한다. 결과적으로, dim=n으로 접게 된다.
    <ul>
      <li>dim=n 없이 수행하면 모든 요소의 합이 return된다.</li>
      <li>keepdims=True로 설정하면 원본의 차원이 유지된다.</li>
    </ul>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">sum</span><span class="p">(</span><span class="n">a</span><span class="p">))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">dim</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="nb">sum</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">dim</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">keepdims</span><span class="o">=</span><span class="bp">True</span><span class="p">))</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[-0.4658,  1.1440,  0.1925,  0.8696],
          [-0.2410, -2.6269, -0.1082,  2.0504],
          [-2.3266, -0.0603,  1.0653, -0.2424]])
            
  tensor(-0.7494)
    
  tensor([ 1.7403, -0.9257, -1.5639])
    
  tensor([[ 1.7403],
          [-0.9257],
          [-1.5639]])
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">torch.mean(tensor, dim=n)</code> : dim=n을 기준으로 평균을 구한다. 결과적으로 dim=n으로 접게 된다.</p>

    <p>예를 들어, 3*4 모양의 tensor에서 dim=1을 설정하게 되면 각 행의 열 별로 평균을 구한다. 따라서 dim=1(열)로 접게 된다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">mean</span><span class="p">(</span><span class="n">a</span><span class="p">))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">mean</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">dim</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">mean</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">dim</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">keepdims</span><span class="o">=</span><span class="bp">True</span><span class="p">))</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[-0.4658,  1.1440,  0.1925,  0.8696],
          [-0.2410, -2.6269, -0.1082,  2.0504],
          [-2.3266, -0.0603,  1.0653, -0.2424]])
            
  tensor(-0.0624)
    
  tensor([ 0.4351, -0.2314, -0.3910])
    
  tensor([[ 0.4351],
          [-0.2314],
          [-0.3910]])
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">torch.std(tensor)</code> : tensor를 구성하는 요소들의 표준편차를 구하는 함수이다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">std</span><span class="p">(</span><span class="n">a</span><span class="p">))</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[-3.4415,  0.9005,  0.3959,  0.7047],
          [-0.9700,  0.0784, -0.4988,  0.7027],
          [ 1.7742, -0.8974,  0.0234, -0.9309]])
            
  tensor(1.3290)
</code></pre></div>    </div>
  </li>
</ul>

<h2 id="15---tensor-연산">1.5 - Tensor 연산</h2>

<h3 id="tensor-변환">Tensor 변환</h3>

<p>선형대수학에서 행렬을 다룰 때 가장 중요한 연산 중 하나가 전치(Transpose) 이다. Pytorch에도 전치를 지원하며, 이를 확장한 개념인 차원의 변환 또한 지원한다.</p>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.reshape(shape)</code> : 원본 tensor를 원하는 shape으로 변환하는 함수이다. 이 때, 마지막 차원부터 요소를 채우면서 변환한다.</p>

    <blockquote>
      <p>이때, shape에 (4,-1)과 같이 대입하면 행의 수는 4, 열의 수는 알아서 변환하게 된다. 예를 들어, tensor의 요소 수가 20개이면 (4,5) shape의 tensor가 생성된다.
   따라서 (1,-1) 을 대입하면 2차원 행 벡터, (-1, 1) 을 대입하면 2차원 열 벡터가 생성된다.</p>

    </blockquote>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">reshape</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">reshape</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">).</span><span class="n">shape</span><span class="p">)</span> <span class="c1"># (4,5) shape의 tensor 자동 생성
</span></code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 
  				 11, 12, 13, 14, 15, 16, 17, 18, 19])
            
  tensor([[ 0,  1,  2,  3,  4],
          [ 5,  6,  7,  8,  9],
          [10, 11, 12, 13, 14],
          [15, 16, 17, 18, 19]])
    
  torch.Size([4, 5])
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.transpose(a,b)</code> : dim=a 와 dim=b 가 바뀐다. 이 때, 이 함수는 두 개의 차원만 바꿀 수 있다.</p>

    <p>예를 들어, <code class="language-plaintext highlighter-rouge">tensor.transpose(0,2)</code> 는 dim=0과 dim=2를 바꾼다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">transpose</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">).</span><span class="n">shape</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">transpose</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">))</span>
</code></pre></div>    </div>

    <p>(결과 : dim=0과 dim=2가 바뀐 것을 확인할 수 있음)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[[-1.1991,  0.3728,  0.2659, -0.2742],
           [-0.9017, -0.1994,  0.7568,  1.8734],
           [-0.6094, -0.1875, -0.9871,  0.0358]],
    
          [[-1.6260,  0.5890,  0.5562, -1.1465],
           [-0.4583,  0.5209,  0.2618, -1.1267],
           [ 1.0217,  2.1956,  0.4245,  0.4243]]])
    
  torch.Size([4, 3, 2])
    
  tensor([[[-1.1991, -1.6260],
           [-0.9017, -0.4583],
           [-0.6094,  1.0217]],
    
          [[ 0.3728,  0.5890],
           [-0.1994,  0.5209],
           [-0.1875,  2.1956]],
    
          [[ 0.2659,  0.5562],
           [ 0.7568,  0.2618],
           [-0.9871,  0.4245]],
    
          [[-0.2742, -1.1465],
           [ 1.8734, -1.1267],
           [ 0.0358,  0.4243]]])
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.permute(0,2,1)</code> : 위의 transpose 함수는 두 차원만 바꿀 수 있었다. 그러나 permute 함수는 두 개 이상의 차원을 바꿀 수 있도록 한다.</p>

    <p>예로, (0,2,1) 의 숫자는 각각 원본 tensor의 차원의 index를 의미하며 원본의 (0,1,2) 번째 차원을 (0,2,1) 순서대로 바꾸라는 뜻이다. 즉, 이 예시에는 2 번째 차원과 1 번째 차원을 바꾸게 된다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">permute</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">).</span><span class="n">shape</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">permute</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">))</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[[ 0.1425, -0.4132,  0.9183, -1.1303],
           [-1.3723, -0.5931, -0.9790,  0.0322],
           [-0.3236,  0.7203, -0.9767, -0.1053]],
    
          [[-1.1121, -2.2002, -1.3496,  0.1428],
           [-0.1689, -0.9300, -2.0065, -0.0144],
           [ 0.4352,  1.2080,  1.7478,  2.1088]]])
    
  torch.Size([2, 4, 3])
    
  tensor([[[ 0.1425, -1.3723, -0.3236],
           [-0.4132, -0.5931,  0.7203],
           [ 0.9183, -0.9790, -0.9767],
           [-1.1303,  0.0322, -0.1053]],
    
          [[-1.1121, -0.1689,  0.4352],
           [-2.2002, -0.9300,  1.2080],
           [-1.3496, -2.0065,  1.7478],
           [ 0.1428, -0.0144,  2.1088]]])
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="tensor-차원-축소확장">Tensor 차원 축소/확장</h3>

<p>상황에 따라 필요 없는 차원을 줄이거나 늘려야 할 수 있다. 이럴 때를 위해 아래의 함수를 사용한다.</p>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.squeeze()</code> : 유효하지 않은 차원을 줄이는 함수이다. 즉, size가 1인 차원을 없애 유효한 shape을 만들어준다.</p>

    <p>예를 들어, (1,1,2,3) shape의 tensor를 squeeze한다면 그 결과로 (2,3) shape의 tensor를 얻을 수 있다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">shape</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">squeeze</span><span class="p">().</span><span class="n">shape</span><span class="p">)</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  torch.Size([1, 1, 2, 3])
  torch.Size([2, 3])
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">tensor.unsqueeze(dim=n)</code> : 원하는 위치에 차원을 늘리는 함수이다.</p>

    <p>예를 들어, (2,3) shape의 tensor의 dim=1에 unsqueeze한다면 그 결과로 (2,1,3) shape의 tensor를 얻을 수 있다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">shape</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">unsqueeze</span><span class="p">(</span><span class="n">dim</span><span class="o">=</span><span class="mi">1</span><span class="p">).</span><span class="n">shape</span><span class="p">)</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  torch.Size([2, 3])
  torch.Size([2, 1, 3])
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="tensor-병합">Tensor 병합</h3>

<p>딥러닝 학습 데이터를 이용할 때, 두 dataset을 합치거나 feature와 label을 합치는 등의 여러 상황에서 tensor를 병합해야 한다. 이럴 때 사용할 수 있는 함수가 아래 함수들이다.</p>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">torch.vstack([a,b])</code> : dim=<strong>0</strong> 에 a와 b를 쌓는다.</p>

    <p>예를 들어, 두 tensor a와 b가 각각 2<em>3 shape일 때 dim=0에 쌓으면 4</em>3 shape의 tensor를 얻는다. 즉, 2차원인 경우 수직 방향(vertical)으로 쌓기 때문에 vstack이다.</p>

    <blockquote>
      <p>그러나 2차원 이상에서는 수직으로 쌓는다는 개념보다는 dim=0에 쌓는다는 개념이 적용하기 쉽다.</p>

    </blockquote>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
  <span class="n">b</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
    
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">vstack</span><span class="p">([</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">]))</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[-0.0438, -1.0970, -1.9101],
          [-0.1366, -2.3687, -1.7195]])
  tensor([[ 1.5016, -1.1989, -0.6355],
          [-0.3517,  0.5741,  0.2791]])
    
  tensor([[-0.0438, -1.0970, -1.9101],
          [-0.1366, -2.3687, -1.7195],
          [ 1.5016, -1.1989, -0.6355],
          [-0.3517,  0.5741,  0.2791]])
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">torch.hstack([a,b])</code> : dim=<strong>1</strong> 에 a와 b를 쌓는다.</p>

    <p>예를 들어, 두 tensor a와 b가 각각 2<em>3 shape일 때 dim=1에 쌓으면 2</em>6 shape의 tensor를 얻는다. 즉, 2차원인 경우 수평 방향(horizontal)으로 쌓기 때문에 hstack이다.</p>

    <blockquote>
      <p>그러나 2차원 이상에서는 수평으로 쌓는다는 개념보다는 dim=1에 쌓는다는 개념이 적용하기 쉽다.</p>

    </blockquote>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
  <span class="n">b</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
    
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">hstack</span><span class="p">([</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">]))</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[-0.8676, -0.7816,  0.2995],
          [-2.2452, -1.0152, -1.6314]])
  tensor([[ 0.1893,  0.2046,  0.7424],
          [-0.8871, -0.5741,  0.2163]])
    
  tensor([[-0.8676, -0.7816,  0.2995,  0.1893,  0.2046,  0.7424],
          [-2.2452, -1.0152, -1.6314, -0.8871, -0.5741,  0.2163]])
</code></pre></div>    </div>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">torch.cat([a,b], dim=n)</code> : dim=<strong>n</strong> 에 a와 b를 쌓는다.</p>

    <blockquote>
      <p>위 <code class="language-plaintext highlighter-rouge">vstack</code> 과 <code class="language-plaintext highlighter-rouge">hstack</code> 에서 설명했듯 tensor의 차원이 3 이상일 때는 세로, 가로 개념이 불분명해지기 때문에 <code class="language-plaintext highlighter-rouge">cat</code> 을 사용하는 것이 도움이 된다.</p>

    </blockquote>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
  <span class="n">b</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
    
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">cat</span><span class="p">([</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">],</span> <span class="n">dim</span><span class="o">=</span><span class="mi">0</span><span class="p">).</span><span class="n">shape</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">cat</span><span class="p">([</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">],</span> <span class="n">dim</span><span class="o">=</span><span class="mi">1</span><span class="p">).</span><span class="n">shape</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">cat</span><span class="p">([</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">],</span> <span class="n">dim</span><span class="o">=</span><span class="mi">2</span><span class="p">).</span><span class="n">shape</span><span class="p">)</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  torch.Size([4, 3, 4])
  torch.Size([2, 6, 4])
  torch.Size([2, 3, 8])
</code></pre></div>    </div>
  </li>
</ul>

<h3 id="행렬-곱">행렬 곱</h3>

<p>Pytorch에서 tensor끼리의 곱은 크게 두 가지로 나눌 수 있다. 바로 Element-wise 곱과 Matrix 곱이다.</p>

<ul>
  <li>
    <p><strong>Element-wise 곱</strong> : <code class="language-plaintext highlighter-rouge">*</code> 연산자와 <code class="language-plaintext highlighter-rouge">mul()</code> 함수를 통해 수행한다. element-wise 곱이란 동일 위치에 있는 원소끼리의 곱을 뜻한다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span>
      <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span>
      <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
  <span class="p">])</span>
  <span class="n">b</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span>
      <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span>
      <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">]</span>
  <span class="p">])</span>
    
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="o">*</span><span class="n">b</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">mul</span><span class="p">(</span><span class="n">b</span><span class="p">))</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[ 5, 12],
          [21, 32]])
  tensor([[ 5, 12],
          [21, 32]])
</code></pre></div>    </div>
  </li>
  <li>
    <p><strong>Matrix 곱</strong> : <code class="language-plaintext highlighter-rouge">@</code> 연산자와 <code class="language-plaintext highlighter-rouge">matmul()</code> 함수를 통해 수행한다.</p>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span>
      <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span>
      <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
  <span class="p">])</span>
  <span class="n">b</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">([</span>
      <span class="p">[</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">],</span>
      <span class="p">[</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">]</span>
  <span class="p">])</span>
    
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="o">@</span><span class="n">b</span><span class="p">)</span>
  <span class="k">print</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">matmul</span><span class="p">(</span><span class="n">b</span><span class="p">))</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  tensor([[19, 22],
          [43, 50]])
  tensor([[19, 22],
          [43, 50]])
</code></pre></div>    </div>

    <hr />

    <p>matrix 곱을 할 때 이런 의문이 생길 수 있다. 3차원 이상의 tensor 끼리의 곱은 어떻게 될까?</p>

    <p>이에 대한 답은 간단하다. 바로 마지막 두 차원의 matrix 곱으로 결정된다.</p>

    <blockquote>
      <p>예를 들어, a가 (12,8,3,4) shape의 tensor, b가 (12,8,4,7) shape의 tensor라면 두 tensor의 matrix 곱은 (12,8,3,7) shape의 tensor가 결과로 나온다.</p>

    </blockquote>

    <hr />

    <p>(코드)</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">a</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
  <span class="n">b</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">randn</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">7</span><span class="p">)</span>
  <span class="k">print</span><span class="p">((</span><span class="n">a</span><span class="o">@</span><span class="n">b</span><span class="p">).</span><span class="n">shape</span><span class="p">)</span>
</code></pre></div>    </div>

    <p>(결과)</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  torch.Size([12, 8, 3, 7])
</code></pre></div>    </div>
  </li>
</ul>]]></content><author><name>SeokMin</name></author><category term="Pytorch" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">[Github Pages] Notion to Github pages 변환 시의 주의사항</title><link href="https://min0219.github.io/etc/ETC01/" rel="alternate" type="text/html" title="[Github Pages] Notion to Github pages 변환 시의 주의사항" /><published>2025-02-03T00:00:00+09:00</published><updated>2025-02-03T00:00:00+09:00</updated><id>https://min0219.github.io/etc/ETC01</id><content type="html" xml:base="https://min0219.github.io/etc/ETC01/"><![CDATA[<p>블로그 플랫폼을 Github pages로 결정한 데에는 markdown을 지원한다는 이유가 가장 컸다.</p>

<p>다른 블로그 플랫폼 또한 매력적인 기능들을 지원한다. 특히 개발자들이 많이 이용하는 tistory나 velog 같은 경우에는 블로그 커스터마이징과 글쓰기가 편하지만, 주로 사용하는 문서 작성 서비스가 Notion이기에 markdown을 지원하는 Github pages로 결정하였다.</p>

<p>따라서 Github pages의 게시물 작성 시에 Notion에서 작성한 글을 markdown 파일로 export 한 후에 해당 파일을 Github pages에 복사한다. 그러나 이 과정에서 Notion과 Github pages 간의 latex 엔진의 차이 때문인지 Notion에서 편집했던 형식이 Github pages에서는 깨지는 모습을 보였다.</p>

<p><mark style="background-color: #fbf3db">따라서 이 글을 통해 Notion의 글을 Github pages에 올리는 과정에서 발생하는 오류와 그 해결방법을 정리하여 향후 게시물 관리를 원활히 하고자 한다.</mark>(Github pages를 사용함에 따라 발견되는 오류를 이 게시물에 계속하여 추가할 예정이다.)</p>

<h2 id="1-latex-오류">1. latex 오류</h2>

<h3 id="11----오류">1.1 - <code class="language-plaintext highlighter-rouge">|</code> 오류</h3>

<figure style="display: block; text-align: left;">
  <img src="https://min0219.github.io/images/2025-02-03-ETC01/image.png" />
  <figcaption>Notion에서 정상적으로 출력된 결과</figcaption>
</figure>

<figure style="display: block; text-align: left;">
  <img src="https://min0219.github.io/images/2025-02-03-ETC01/image 1.png" />
  <figcaption>Github pages에서 오류가 발생한 결과</figcaption>
</figure>

<p>위 사진은 Notion에서는 잘 출력되던 latex 수식이 Github pages에서는 오류가 발생한 것을 보여준다. 해당 오류는 <code class="language-plaintext highlighter-rouge">|</code> 문자를 latex 수식에서 사용 시 발생하며, 해결 방법은 <code class="language-plaintext highlighter-rouge">\mid</code> 명령어를 사용하는 것이다.</p>

<p>아래와 같이 사용하면 된다.</p>

<div class="language-latex highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- Conditional probability<span class="p">$</span><span class="nb">P</span><span class="o">(</span><span class="nb">A|B</span><span class="o">)</span><span class="p">$</span> : 사건 <span class="p">$</span><span class="nb">B</span><span class="p">$</span>가 일어났다는 조건 아래 사건 <span class="p">$</span><span class="nb">A</span><span class="p">$</span>의 확률
</code></pre></div></div>

<div class="language-latex highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- Conditional probability <span class="p">$</span><span class="nb"> P</span><span class="o">(</span><span class="nb">A</span><span class="nv">\mid</span><span class="nb"> B</span><span class="o">)</span><span class="nb"> </span><span class="p">$</span> : 사건 <span class="p">$</span><span class="nb"> B </span><span class="p">$</span>가 일어났다는 조건 아래 사건 <span class="p">$</span><span class="nb"> A </span><span class="p">$</span>의 확률
</code></pre></div></div>

<h3 id="12---argmax-오류">1.2 - <code class="language-plaintext highlighter-rouge">\argmax</code> 오류</h3>

<figure style="display: block; text-align: left;">
  <img src="https://min0219.github.io/images/2025-02-03-ETC01/image 2.png" />
  <figcaption>Notion에서 정상적으로 출력된 결과</figcaption>
</figure>

<figure style="display: block; text-align: left;">
  <img src="https://min0219.github.io/images/2025-02-03-ETC01/image 3.png" />
  <figcaption>Github pages에서 오류가 발생한 결과</figcaption>
</figure>

<p>위 사진은 Notion에서는 잘 출력되던 latex 수식에 Github pages에서는 오류가 발생하는 것을 보여준다. 해당 오류는 <code class="language-plaintext highlighter-rouge">\argmax</code> 명령어를 latex 수식에서 그냥 사용 시 발생하며, 해결방법은 아래와 같이 latex 수식 시작 시에 <code class="language-plaintext highlighter-rouge">\DeclareMathOperator*{\argmax}{arg\,max}</code> 명령어를 작성해주면 된다. 이 명령어를 한 번만 작성해주면 이후 해당 게시물에서는 <code class="language-plaintext highlighter-rouge">\argmax</code> 를 오류 없이 사용할 수 있다. (물론 다른 게시물 작성 시에는 다시 작성해야 한다.)</p>

<p>아래와 같이 사용한다.</p>

<div class="language-latex highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">$$</span><span class="nb">
</span><span class="nv">\theta</span><span class="p">_{</span><span class="nb">MLE</span><span class="p">}</span><span class="nb"> </span><span class="o">=</span><span class="nb"> </span><span class="nv">\argmax\limits</span><span class="p">_{</span><span class="nv">\theta</span><span class="p">}</span><span class="nb">P</span><span class="o">(</span><span class="nb">X|</span><span class="nv">\theta</span><span class="o">)</span><span class="nb">
</span><span class="p">$$</span>
</code></pre></div></div>

<div class="language-latex highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">$$</span><span class="nb">
</span><span class="nv">\DeclareMathOperator</span><span class="o">*</span><span class="p">{</span><span class="nv">\argmax</span><span class="p">}{</span><span class="nb">arg</span><span class="nv">\,</span><span class="nb">max</span><span class="p">}</span><span class="nb">
</span><span class="nv">\theta</span><span class="p">_{</span><span class="nb">MLE</span><span class="p">}</span><span class="nb"> </span><span class="o">=</span><span class="nb"> </span><span class="nv">\argmax\limits</span><span class="p">_{</span><span class="nv">\theta</span><span class="p">}</span><span class="nb">P</span><span class="o">(</span><span class="nb">X</span><span class="nv">\mid</span><span class="nb"> </span><span class="nv">\theta</span><span class="o">)</span><span class="nb">
</span><span class="p">$$</span>
</code></pre></div></div>]]></content><author><name>SeokMin</name></author><category term="ETC" /><summary type="html"><![CDATA[블로그 플랫폼을 Github pages로 결정한 데에는 markdown을 지원한다는 이유가 가장 컸다.]]></summary></entry><entry><title type="html">[Generative Models] 03-Transformations of Random Variable</title><link href="https://min0219.github.io/generative-models/GM03/" rel="alternate" type="text/html" title="[Generative Models] 03-Transformations of Random Variable" /><published>2025-01-21T00:00:00+09:00</published><updated>2025-01-21T00:00:00+09:00</updated><id>https://min0219.github.io/generative-models/GM03</id><content type="html" xml:base="https://min0219.github.io/generative-models/GM03/"><![CDATA[<h2 id="1-transform-for-discrete-random-variable">1. Transform for Discrete Random Variable</h2>

<h3 id="11---probability-mass-functions">1.1 - Probability Mass Functions</h3>

<ul>
  <li>
    <p>Probability Mass Functions(=PMF, 확률 질량 함수) : discrete random variable이 특정값을 가질 확률을 나타내는 함수</p>

\[f_X(x) = P(X=x)\]

    <p>위 식은 확률 변수 $X$가 sample $x$를 가질 확률을 나타내는 pmf이다.</p>
  </li>
</ul>

<h3 id="12---transform-for-discrete-rv">1.2 - Transform for Discrete R.V.</h3>

<ul>
  <li>
    <p>Transform for Discrete R.V. : random variable $X$를 함수 $f(x)=y$를 이용하여 $Y$로 변환할 때, $Y$의 pmf를 구하는 방법이다.</p>

    <p>이 때, $X$가 discrete random variable이라면 함수 $f(x)=y$를 만족하는 모든 $x$에 대한 확률을 단순히 합해서 $y$의 pmf를 구할 수 있다.</p>

\[\begin{align*} P_y(Y=y)&amp;=\sum_{x:f(x)=y}P_x(x) \\ &amp;=P_x(f^{-1}(y)) \end{align*}\]
  </li>
</ul>

<h2 id="2-transform-for-continuous-random-variable">2. Transform for Continuous Random Variable</h2>

<h3 id="21---probability-density-functions">2.1 - Probability Density Functions</h3>

<ul>
  <li>
    <p>Probability Density Functions(=PDF, 확률 밀도 함수) : countinuous random variable이 특정 값을 가질 확률을 나타내는 함수이다.</p>

    <p>그러나 PMF와 같이 정확한 sample $X=x$에서의 확률을 정의할 수 없다. 따라서 아래의 성질을 가진다.</p>

\[\begin{align*}\mathbb{P}_X(x) &amp;= \int_{-\infty}^x P_X(t)dt \;\Longrightarrow P_X(x)=\frac{d\mathbb{P}_X}{dx}\\ \Pr(X=x)&amp;=0\\ \Pr(a&lt;X&lt;b) &amp;= \int_a^b P_X(t)dt \end{align*}\]
  </li>
</ul>

<h3 id="22---transform-for-continuous-rv">2.2 - Transform for Continuous R.V.</h3>

<ul>
  <li>
    <p>Transform for Continuous R.V. : random variable $X$를 함수 $f(x)=y$를 이용하여 $Y$로 변환할 때, $Y$의 pdf를 구하는 방법이다.</p>

    <blockquote>
      <p>이 때, $f:X\rightarrow Y$는 $X$와 $Y$ 사이에 일대일 대응 관계가 성립해야 한다. 즉, $f^{-1}:Y\rightarrow X$가 존재해야 한다.</p>

    </blockquote>

\[\begin{align*} P_y(y)=P_x(x) \left\vert \frac{dx}{dy}\right\vert &amp;= P_x(x) \left\vert \frac{dy}{dx}\right\vert^{-1}\\pf)\;P_y(y) = \frac{d}{dy}\mathbb{P}_y(y)&amp;=\frac{d}{dy}\mathbb{P}_x(f^{-1}(y)) \\&amp;=\frac{dx}{dy}\frac{d}{dx}\mathbb{P}_x(f^{-1}(y)) \\&amp;=\frac{dx}{dy}P_x(f^{-1}(y))\\ &amp;=\left\vert\frac{dx}{dy}\right\vert P_x(f^{-1}(y)) \end{align*}\]
  </li>
</ul>

<h2 id="3-inverse-transform-sampling">3. Inverse Transform Sampling</h2>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">Inverse Transform Sampling</code> : uniform distribution으로부터 내가 알고 싶은 분포를 random sampling이 가능하도록 바꿔주는 방법이다. 이 때, Sampling이란 특정 분포를 따르는 random sample(표본, 확률변수 값)을 생성하는 것이다.</p>

    <p>PDF, CDF를 통해서는 sampling이 불가능하다. sampling을 통해 얻고자 하는 것은 PDF 또는 CDF의 x축에 있는 확률변수 $X$인데, PDF와 CDF는 확률변수 $X$가 특정한 값일 때의 확률을 나타내기 때문이다. 따라서 확률을 넣었을 때 $X$가 나오도록 하는 <strong>역함수</strong>가 필요하다.</p>
  </li>
  <li>
    <p>Inverse Transform의 단계</p>
    <ol>
      <li>구하고자 하는 분포의 CDF(Cumulative distribution function)을 구한다.</li>
      <li>CDF의 역함수를 구한다.</li>
      <li>CDF의 역함수에 uniform distribution의 값을 대입하여 random sample 생성한다.</li>
    </ol>

    <blockquote>
      <p>CDF를 사용하는 이유 : CDF는 monotonically increasing function(단조 증가 함수)이고, 따라서 역함수가 존재하기 때문이다.</p>

    </blockquote>
  </li>
</ul>

<h2 id="4-transformation--monotonic-function-invertibility">4. Transformation : monotonic function, invertibility</h2>

<ul>
  <li>Invertibility : 함수 $f$의 역함수 $f^{-1}$가 존재하기 위해서는 $f$가 <strong>bijective(일대일대응)</strong> function이여야 한다. ⇒ 함수 $f$는 strictly increasing / strictly monotone
    <ul>
      <li>Monotonically increasing function : $x\le y, then \;f(x)\le f(y)$</li>
      <li>Strictly increasing function : $x&lt; y, then \;f(x)&lt; f(y)$</li>
    </ul>
  </li>
</ul>

<h2 id="5-jacobian-matrix">5. Jacobian Matrix</h2>

<ul>
  <li>$f : R^n \rightarrow R^m$</li>
</ul>

<p><img src="https://min0219.github.io/images/2025-01-21-GM03/Untitled.png" alt="Untitled" style="zoom: 50%;" /></p>

<h2 id="6-central-limit-theorem">6. Central Limit Theorem</h2>

<ul>
  <li>
    <p>Central Limit Theorem(중심 극한 정리) : 평균 $\mu$, 분산 $\sigma^2$인 population(모집단)에서 크기가 $n$인 random samples $(X_1,X_2,\dots,X_n)$의 평균인 $\bar{X}$의 분포는 $n\rightarrow \infty$일 때, $N(\mu,\frac{\sigma^2}{n})$에 근사하고, $Z=\frac{\bar{X}-\mu}{\sigma_{\bar{X}}}, \sigma_{\bar{X}}=\frac{\sigma}{\sqrt{n}}$의 분포는 Normal distribution $N(0,1)$에 근사한다.</p>

    <p><img src="https://min0219.github.io/images/2025-01-21-GM03/Untitled 1.png" alt="Untitled 1" style="zoom: 33%;" /></p>
  </li>
</ul>]]></content><author><name>SeokMin</name></author><category term="Generative-Models" /><summary type="html"><![CDATA[1. Transform for Discrete Random Variable]]></summary></entry><entry><title type="html">[Generative Models] 04-Variational Auto Encoder(VAE)</title><link href="https://min0219.github.io/generative-models/GM04/" rel="alternate" type="text/html" title="[Generative Models] 04-Variational Auto Encoder(VAE)" /><published>2025-01-21T00:00:00+09:00</published><updated>2025-01-21T00:00:00+09:00</updated><id>https://min0219.github.io/generative-models/GM04</id><content type="html" xml:base="https://min0219.github.io/generative-models/GM04/"><![CDATA[<h2 id="1-notation">1. Notation</h2>

<table>
  <thead>
    <tr>
      <th>Symbol</th>
      <th>Mean</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>$D$</td>
      <td>$n$개의 data sample을 가진 dataset, $D = {x^1, x^2,…, x^n}$</td>
    </tr>
    <tr>
      <td>$x^i$</td>
      <td>각 data point는 $d$차원의 vector이다. $x^i = [x_1^i, x_2^i,…, x_d^i]$</td>
    </tr>
    <tr>
      <td>$x$</td>
      <td>dataset $D$에 속한 한 data sample, $x\in D$</td>
    </tr>
    <tr>
      <td>$x’, \hat{x}$</td>
      <td>$x$의 reconstructed version(생성된 sample)</td>
    </tr>
    <tr>
      <td>$\tilde{x}$</td>
      <td>$x$의 corrupted version</td>
    </tr>
    <tr>
      <td>$z$</td>
      <td>bottleneck layer의 결과인 compressed code<strong>(latent vector)</strong></td>
    </tr>
    <tr>
      <td>$a_j^l$</td>
      <td>$l$번째 layer의 $j$번째 neuron의 activation function</td>
    </tr>
    <tr>
      <td>$g_{\phi}()$</td>
      <td>$\phi$로 parameterized된 <strong>encoding</strong> function</td>
    </tr>
    <tr>
      <td>$f_{\theta}()$</td>
      <td>$\theta$로 parameterized된 <strong>decoding</strong> function</td>
    </tr>
    <tr>
      <td>$q_{\phi}(z\mid x)$</td>
      <td><strong>probabilistic encoder</strong>로, estimated <strong>posterior</strong> probability function이다.</td>
    </tr>
    <tr>
      <td>$p_{\theta}(x\mid z)$</td>
      <td>probabilistic decoder로, 주어진 $z$(latent vector)를 이용해 $x$(true data)를 생성할 <strong>likelihood</strong>이다.</td>
    </tr>
  </tbody>
</table>

<h2 id="2-latent-variable-model">2. Latent variable model</h2>

<h3 id="21---latent-variable">2.1 - latent variable</h3>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">latent variable</code>(잠재 변수)는 구성 개념(Construct)이 직접적으로 관찰되거나 측정되지 않는 변수를 의미한다.</p>

    <p>→ latent variable 자체로 전체 통계량을 측정하는 것은 불가능하기 때문에 observed variable(관측 변수)에 의해 간접적으로 통계 측정(수학적 modelling)을 수행해 추론한다.</p>

    <ul>
      <li><strong>hidden variables</strong> :  물리적으로는 측정될 수 있으나 실질적으로 측정되지 않는 경우의 latent variables를 hidden variables라고 한다.</li>
      <li>hypothetical variables : data 구조, 범주, 행동, 정신 상태 등의 추상적 개념의 latent variables.</li>
    </ul>
  </li>
</ul>

<h3 id="22---latent-variable-model">2.2 - Latent variable model</h3>

<ul>
  <li>
    <p>보편적인 Latent variable model : latent variable을 <code class="language-plaintext highlighter-rouge">unsupervised</code> manner로 학습하기 위해 neural network를 이용한다. 이 때, latent space $z$의 차원은 data $x$보다 축소되는데, feature가 의미있는 요소만 capture하기 위해서이다.</p>

    <p>일반적인 연속 분포에 대해 latent variable model은 아래 그림과 같이 두 distribution의 곱의 integral으로 나타난다.</p>

    <p><img src="https://min0219.github.io/images/2025-01-21-GM04/bc33d67a-8d47-4212-b61d-2d5dce58b0af.png" alt="bc33d67a-8d47-4212-b61d-2d5dce58b0af" /></p>

    <p>$p(x)$는 복잡한 분포이고, $p(z)$와 $p(x\mid z)$는 Gaussian 분포와 같은 쉬운 분포를 사용한다. 이 때, $p(x\mid z)$의 mean과 variance는 $z$의 어떤 neural network function이고, 학습 가능하다.</p>

    <p>→ $p(x)$는 복잡한 분포이기 때문에 이를 학습하는 것은 어렵다. 따라서 간단한 2개의 분포의 composition으로 나타내서 modelling problem을 보다 쉽게 만든다.</p>
  </li>
</ul>

<h2 id="3-variational-auto-encoder">3. Variational Auto Encoder</h2>

<h3 id="31---auto-encoderae">3.1 - Auto-Encoder(AE)</h3>

<ul>
  <li>Auto-Encoder : unlabeled training data로부터 저차원의 feature representation을 학습하 위한 <code class="language-plaintext highlighter-rouge">Unsupervised approach</code> 이다. 따라서 Encoder를 학습하는 것이 AE의 목적이다.
    <ul>
      <li>latent space $z$에 대한 가정이 없다.</li>
      <li>reconstruction error로 L2 loss function을 사용한다.</li>
      <li>training 과정에서 label이 사용되지 않는다.</li>
      <li>
        <p>large, unlabeled dataset을 small, labeled dataset으로 transfer한다.</p>

        <p><img src="https://min0219.github.io/images/2025-01-21-GM04/Untitled.png" alt="Untitled" /></p>
      </li>
    </ul>
  </li>
  <li>
    <p>Auto-Encoder는 data generation이 불가능하다.</p>

    <p>⇒ latent space $z$에 대한 가정이 없고, $p(z)$의 exact distribution에 대해 알지 못하기 때문에 $p(z)$로부터 sample을 생성할 수 없다.</p>
  </li>
</ul>

<h3 id="32---variational-auto-encodervae">3.2 - Variational Auto-Encoder(VAE)</h3>

<ul>
  <li>
    <p><strong>Variational Auto-Encoder</strong> : generative model의 한 종류로, input data $x$로부터 latent vector $z$를 sampling하여 input data와 비슷한 output data $x’$을 만드는 것을 목표로 한다.</p>

    <p><img src="https://min0219.github.io/images/2025-01-21-GM04/Untitled 1.png" alt="Untitled 1" /></p>

    <ul>
      <li>
        <p><strong>Encoder</strong> 과정 : $q_{\phi}(z\mid x)$</p>

        <p>latent vector $z$를 $p(z)$(=Prior)에서 sampling하는 대신, $x$와 최대한 비슷한 data를 생성하고자 이상적인 확률 분포인 $p_{\theta}(z\mid x)$(=Posterior)에서 sampling하고자 한다.</p>

        <p>그러나 $p_{\theta}(z\mid x)$를 모르기 때문에 <strong>Variational Inference</strong>를 이용하여 $q_{\phi}(z\mid x)$를 추정한다. 이후, 이 분포에서 $z$를 sampling한다.</p>

        <blockquote>
          <p><code class="language-plaintext highlighter-rouge">Variational Inference</code> : $q_{\phi}(z\mid x)$를 가정하고 이 분포의 parameter $\phi$를 학습시켜 이상적 확률 분포에 Approximation하는 방법이다. 이때, $q_{\phi}$는 정규분포라고 가정한다.</p>

        </blockquote>
      </li>
      <li>
        <p><strong>Decoder</strong> 과정 : $p_{\theta}(x\mid z)$</p>

        <p>Encoder로부터 sampling된 latent variable $z$를 입력하여 original data $x$와 비슷한 reconstructed data $x’$을 생성한다. Decoder는 이 둘의 차이를 최소화하는 $p_{\theta}(x\mid z)$를 모델링한다.</p>
      </li>
    </ul>
  </li>
  <li><strong>VAE의 training 과정</strong>
    <ol>
      <li>model과 data에 대해 maximum likelihood가 되는 parameter를 찾고, parameter를 maximum likelihood estimation을 통해 update한다.</li>
      <li>
        <p>log값을 취해 log-likelihood로 식을 바꿔준다. 이 때, $z$는 <code class="language-plaintext highlighter-rouge">intractable</code>하기 때문에 적분이 불가능하다. 따라서 log-likelihood 대신에 <code class="language-plaintext highlighter-rouge">expected log-likelihood</code>를 <strong>maximize</strong>한다.</p>

\[\DeclareMathOperator*{\argmax}{arg\,max}
 \begin{align*} &amp;the\,\,model: p_{\theta}(x)\\&amp;the\,\,data: D=\{x_1,x_2,x_3,\dots,x_n\} \\ &amp;maximum\,\,likelihood\,\,fit:\\ &amp;\theta\leftarrow \underset{\theta}{\argmax}\,p_{\theta}(x)\quad(x_i:independent) \\ &amp;\,\,\,\,=\underset{\theta}{\argmax}\,\prod_i p_{\theta}(x_i)\\ &amp;\,\,\,\,=\underset{\theta}{\argmax}\,\log\prod_i p_{\theta}(x_i)\quad (log-likelihood)\\ &amp;\,\,\,\,=\underset{\theta}{\argmax}\,\frac{1}{N} \log\prod_i p_{\theta}(x_i)\quad(\div N)\\&amp;\,\,\,\,=\underset{\theta}{\argmax}\,\frac{1}{N}\sum_i \log p_{\theta}(x_i) \\ &amp;이\,때,\,p_{\theta}(x_i)=\int p(x_i\mid z)p(z)dz\,\leftarrow z\,\,is\,\,intractable \end{align*}\]
      </li>
      <li>
        <p>$z$가 무엇인지 모르기 때문에 $p_{\theta}(z\mid x_i)$를 이용해 주어진 $x_i$에 대해 가장 그럴듯한 $z$를 찾아 joint probability를 maximize한다. 실제 사용 시에는 $x$의 일부를 sampling하여 적용한다.</p>

        <p>$p_{\theta}(z\mid x_i)$를 구하는 것을 probabilistic inference라고 하는데, 어떤 $z$가 $x_i$로 가는지 inferring한다. VAE에서는 training data $x$의 분포와 최대한 가까운 데이터를 생성하기 위해서 $p_{\theta}(z\mid x_i)$를 구한다.</p>

\[\begin{align*}&amp;expected\;log-likelihood: \\&amp;\theta\leftarrow \underset{\theta}{\argmax}\,\frac{1}{N}\sum_i \log p_{\theta}(x_i)\\&amp;\;\;=\underset{\theta}{\argmax}\,\mathbb{E}_{x\sim p_{\theta}(x)}[\log p_{\theta}(x)] \\ &amp;\;\;=\underset{\theta}{\argmax} \,\mathbb{E}_{z\sim p_{\theta}(z\mid x)}[\log p_{\theta}(x)] \end{align*}\]
      </li>
      <li>
        <p>실제 $p_{\theta}(z\mid x_i)$의 분포를 모르기 때문에 다른 분포를 이용해 approximate한다. 예를 들어, 각 $x_i$마다 각각의 mean, variance를 이용해 만든 새 분포 $q_{\phi}(z\mid x_i)$를 사용해 $p_{\theta}(z\mid x_i)$를 estimate(추정)한다. 이 때, $q_{\phi}(z\mid x_i)$는 정규분포로 가정한다. 정규분포로 가정한 이유는, 정규분포끼리는 KL-Divergence를 계산하기 쉽기 때문이다.</p>

\[\begin{align*}&amp;\theta\leftarrow \underset{\theta}{\argmax} \,\mathbb{E}_{z\sim p_{\theta}(z\mid x)}[\log p_{\theta}(x)]\\ &amp;\;\;\,= \underset{\theta}{\argmax} \,\mathbb{E}_{z\sim q_{\phi}(z\mid x)}[\log p_{\theta}(x)]\\&amp;q_{\phi}(z\mid x)\sim N(\mu_i, \sigma_i^2I) \end{align*}\]
      </li>
      <li>
        <p>따라서, $\log p_{\theta}(x)$를 $E_{q_{\phi}(z\mid x)}[\log p_{\theta}(x)]$로 나타낼 수 있다. 이 때, <strong>bayes’ theorem</strong>에 의해 이 식을 [아래]와 같이 변형할 수 있다. 결과적으로 두 개의 expected log-likelihood로 나타나는데, 각각 ELBO(Evidence Lower Bound)와 $q_{\phi}$와 $p_{\theta}$에 대한 KL-Divergence이다.</p>

        <blockquote>
          <p>$Bayes \;Theorem : p_{\theta}(z\mid x)=\frac{p_{\theta}(x,z)}{p_{\theta}(x)}, \;\therefore p_{\theta}(x)=\frac{p_{\theta}(x,z)}{p_{\theta}(z\mid x)}$</p>

        </blockquote>

        <p><img src="https://min0219.github.io/images/2025-01-21-GM04/Untitled 2.png" alt="Untitled 2" /></p>
      </li>
      <li>
        <p>이 때, ELBO에 대해 식을 정리하면 아래와 같은 식을 얻을 수 있는데, KL-Divergence는 항상 양수이므로 <strong>ELBO는 log-likelihood $\log \,p_{\theta}(x)$의 lower bound</strong>임을 알 수 있다. 따라서 <strong>ELBO를 maximize함으로써 likelihood 또한 maximize</strong>할 수 있다.</p>

        <p><img src="https://min0219.github.io/images/2025-01-21-GM04/Untitled 3.png" alt="Untitled 3" style="zoom:50%;" /></p>
      </li>
      <li>ELBO를 변형하여 아래와 같이 두 개의 term으로 분리할 수 있다.
        <ul>
          <li>
            <p>$-E_{z \sim q_{\phi}( z \mid x)} \left [ \log p_{ \theta }(x \mid z) \right]$ , <code class="language-plaintext highlighter-rouge">Reconstruction Error</code> : $q_{\phi}(z\mid x)$에서 sampling한 $z$에 대해 log-likelihood를 maximize하는 것이 목표이고, 이 때 Reconstruction Error를 minimize할 수 있다.</p>

            <p>이 error가 가진 의미는 VAE가 생성한 $x’$이 input data $x$와 얼마나 가까운지를 의미하고, VAE의 목표를 잘 달성하도록 한다.</p>
          </li>
          <li>
            <p>$D_{KL}\left( {q_{\phi}(z\mid x)} \Vert{p_{\theta}(z)}\right)$, <code class="language-plaintext highlighter-rouge">Regularization Error</code> : posterior $q_{\phi}(z\mid x)$와 prior $p_{\theta}(z)$ (=Standard Normal Distribution) 간의 KL-divergence이다. 따라서 둘이 비슷할 수록 작아진다.</p>

            <p>이 error가 가진 의미는 Encoder가 출력하는 latent variable $z$의 분포를 Standard Normal Distribution에 가깝게 유지하도록 제약을 가해 Overfitting을 방지하고 latent space를 잘 구조화하여 일반화 능력을 향상시키도록 한다.</p>
          </li>
        </ul>

\[\begin{align*} \mathcal{L}_{\theta,\phi}(x) &amp;=\mathbb{E}_{q_{\phi}(z\mid x)}\left [\log\frac{p_{\theta}(x,z)}{q_{\phi}(z\mid x)}\right]\\ &amp;=\mathbb{E}_{q_{\phi}(z\mid x)} \left [\log p_{\theta}(x,z) - q_{\phi}(z\mid x) \right]\\&amp;= \mathbb{E}_{q_{\phi}(z\mid x)} \left[ \log p_{\theta}(x,z)-\log p_{\theta}(z)+\log{p_{\theta}(z)} - q_{\phi}(z\mid x) \right] \\ &amp;=\mathbb{E}_{q_{\phi}(z\mid x)} \left [\log p_{\theta}(x\mid z) \right] - \mathbb{E}_{q_{\phi}(z\mid x)}\left[ \log \frac{q_{\phi}(z\mid x)}{p_{\theta}(z)}\right]\\ &amp;=\mathbb{E}_{z \sim q_{\phi}(z\mid x)} \left [\log p_{\theta}(x\mid z) \right] - D_{KL}\left( {q_{\phi}(z\mid x)} \Vert{p_{\theta}(z)}\right) \end{align*}\]
      </li>
    </ol>
  </li>
  <li>
    <p><strong>Reparametrization Trick</strong></p>

    <p>training을 할 때, 위에서 구한 VAE의 parameter $\theta,\phi$를 Stochastic Gradient-based optimization을 통해 update를 해야한다. 그러나 아래의 식에서 볼 수 있듯이 $\phi$는 gradient를 구하기 어렵다.</p>

    <p>따라서 $z$를 $q_{\phi}(z\mid x)$에서 직접 sampling하지 않고, $\epsilon$을 sampling하여 $z=u_{\phi}(x)+\Sigma_{\phi}(x)\times\epsilon$ 을 구한다. 이를 reparametrization trick이라고 한다.</p>
  </li>
</ul>

<h2 id="a-appendix">A. appendix</h2>

<h3 id="a1---gaussian-distributionterm">A.1 - Gaussian Distribution(term)</h3>

<ul>
  <li>$x\sim N(0,1)$ : 확률분포 X가 평균이 0, 표준편차가 1일 때</li>
  <li>$x\sim N(0,I)$ : $I$는 단위 행렬으로, 주대각선의 원소가 모두 1이고 나머지는 0인 정사각 행렬이다. 따라서 $x_1, x_2,\dots,x_n$이 독립이고 모두 $N(0,1)$일 때를 뜻한다.</li>
</ul>

<h3 id="a2---monte-carlo-sampling">A.2 - Monte Carlo Sampling</h3>

<ul>
  <li>Monte Carlo Sampling : 반복된 random sampling을 이용해 함수의 값을 근사하는 알고리즘이다.
    <ul>
      <li>조건 : (independent and identically distribution=i.i.d.), 독립적이고 같은 확률 분포를 가지는 distribution
        <ul>
          <li>독립적(independent) : 각 사건이 다른 사건에 영향을 주지 않는다.</li>
          <li>같은 확률 분포(identically) : 주사위 굴리기처럼 각 확률이 동일함을 의미한다.</li>
        </ul>
      </li>
    </ul>

    <p><img src="https://min0219.github.io/images/2025-01-21-GM04/Untitled 3-1737450083489-8.png" alt="Untitled 3" style="zoom: 50%;" /></p>

    <p>⇒ 확률 변수가 상호독립적일때, 모두 동일한 확률 분포를 가진다면 기대값을 random하게 뽑은 N개 sample의 평균과 유사하다. (N이 커질수록 더욱 유사해진다.</p>
  </li>
</ul>

<h3 id="a3---entropy">A.3 - Entropy</h3>

<ul>
  <li>Entropy : [2.2-Latent variable model]의 식에서는 log probability의 expectation의 음수를 뜻하며, <strong>불확실성</strong>을 의미한다.
    <ul>
      <li>Entropy의 정의 : $H(p)=-E_{x\sim p(x)}[log\,p(x)]$</li>
    </ul>

    <p><img src="https://min0219.github.io/images/2025-01-21-GM04/Untitled 4.png" alt="Untitled 4" /></p>

    <ul>
      <li>H(p)에서 만약 p가 uniform distribution이라면 모든 확률이 같아 불확실성이 최대이고, entropy도 최대이다.</li>
      <li>반면, p가 one-hot distribution과 같이 어느 한 가지의 확률이 1, 나머지가 0인 경우에는 반드시 특정한 결과가 나오기 때문에 불확실하지 않다. 따라서 entropy는 최소이다.</li>
    </ul>

    <blockquote>
      <p>따라서 Entropy는 random variable이 얼마나 random한지를 나타낸다.</p>

    </blockquote>
  </li>
</ul>

<h3 id="a4---kl-divergence">A.4 - KL-Divergence</h3>

<ul>
  <li>KL-Divergence : 두 분포가 얼마나 차이나는지를 나타내는 값이다. 어떤 이상적인 분포에 대해, 그 분포를 근사하는 다른 분포를 사용해 sampling을 한다면 발생할 수 있는 정보 entropy 차이를 계산한다. KL-Divergence의 정의는 아래와 같다.
    <ul>
      <li>
        <p>Discrete distribution &amp; Continuous distribution :</p>

\[D_{KL}(p\mid \mid q)=E_{x\sim p(x)}\left(log\frac{p(x)}{q(x)}\right)=\sum\limits_{k=1}^Kp_klog\frac{p_k}{q_k} \\= \int p(x)\,log\frac{p(x)}{q(x)}\,dx = H(p,q) - H(p)\]

        <p>위 식에서 p는 실제 분포, q는 추정한 분포를 의미한다. 위의 식에서 p와 q가 유사할수록 KL-Divergence의 값은 작아지게 된다. 따라서 딥러닝에서 model의 KL-Divergence가 <strong>작아지도록</strong> 학습을 진행하게 된다.</p>
      </li>
    </ul>
  </li>
  <li>KL-Divergence의 특징
    <ul>
      <li>
        <p>$KL(p\mid \mid q)\ge 0$ : KL-Divergence는 <strong>항상 0 이상</strong>이다. 직관적으로, KL-Divergence는 Cross-entropy에서 entropy를 뺀 값이다. 이 때, Cross-entropy의 lower bound는 entropy이기 때문에, 즉 q가 p가 될 때 최솟값인 H(p)를 가져 KL-Divergence가 0이 된다. 이는 직관적인 방법으로, 수학적으로 증명하기 위해서는 Jensen’s Inequality를 이용하면 된다.</p>

        <blockquote>
          <p>Jensen’s inequality : $log\,E(y)\geq E(log\,y)$</p>

        </blockquote>

\[KL(p\mid\mid q)=−∫p(x)\log{\frac{q(x)}{p(x)}}dx≥−\log ∫p(x)\frac{q(x)}{p(x)}dx= -\log ∫q(x)dx = -\log 1 = 0 \\ \therefore KL(p\mid\mid q) \ge 0\]
      </li>
      <li>
        <p>$KL(p\mid \mid q)\ne KL(q\mid \mid p)$ : KL-Divergence는 <strong>거리 개념이 아니다</strong>. 따라서 비대칭적이다. 수학적 증명은 아래와 같다.</p>

\[KL(p\mid\mid q) = H(p,q) - H(p) \\
   \neq H(q, p) - H(q) = KL(q\mid\mid p)
  \\
   \therefore KL(p\mid\mid q) \neq KL(q\mid\mid p)\]
      </li>
    </ul>
  </li>
</ul>]]></content><author><name>SeokMin</name></author><category term="Generative-Models" /><summary type="html"><![CDATA[1. Notation]]></summary></entry><entry><title type="html">[Generative Models] 05-Normalizing Flows</title><link href="https://min0219.github.io/generative-models/GM05/" rel="alternate" type="text/html" title="[Generative Models] 05-Normalizing Flows" /><published>2025-01-21T00:00:00+09:00</published><updated>2025-01-21T00:00:00+09:00</updated><id>https://min0219.github.io/generative-models/GM05</id><content type="html" xml:base="https://min0219.github.io/generative-models/GM05/"><![CDATA[<h2 id="수정중입니다">수정중입니다.</h2>]]></content><author><name>SeokMin</name></author><category term="Generative-Models" /><summary type="html"><![CDATA[수정중입니다.]]></summary></entry><entry><title type="html">[Generative Models] 02-Generative Models for Discrete data</title><link href="https://min0219.github.io/generative-models/GM02/" rel="alternate" type="text/html" title="[Generative Models] 02-Generative Models for Discrete data" /><published>2025-01-15T00:00:00+09:00</published><updated>2025-01-15T00:00:00+09:00</updated><id>https://min0219.github.io/generative-models/GM02</id><content type="html" xml:base="https://min0219.github.io/generative-models/GM02/"><![CDATA[<h2 id="1-parametric-models-vs-nonparametric-models">1. Parametric models vs. Nonparametric models</h2>

<h3 id="11---model-parameter매개변수">1.1 - model parameter(매개변수)</h3>

<ul>
  <li>model parameter : model 내부에 있고, data에서 값을 추정할 수 있는 구성 변수이다. 학습을 통해 update한다.</li>
</ul>

<h3 id="12---parametric-model모수적-모형">1.2 - Parametric model(모수적 모형)</h3>

<ul>
  <li>Parametric model : model이 <strong>고정된 개수</strong>의 <strong>parameter</strong>를 가지고, data가 특정 distribution을 따른다고 가정한다.
    <ul>
      <li>장점 : 효율적이다.(빠르게 사용할 수 있다.)</li>
      <li>단점 : data distribution의 본질에 대한 더 강한 가정을 만들기 때문에 덜 유연하다. 따라서 간단한 문제를 푸는 데 더 적합하다.</li>
      <li>ex) linear regression, logistic regression, Naive Bayes, Ridge regression, SVM(w/o kernel or linear kernel), Polynomial regression</li>
    </ul>
  </li>
</ul>

<h3 id="13---nonparametric-model비모수적-모형">1.3 - Nonparametric model(비모수적 모형)</h3>

<ul>
  <li>Nonparametric model : model이 training data에 따라 <strong>parameter의 개수</strong>가 <strong>증가</strong>하고, data가 특정 distribution을 따른다는 가정이 없다.
    <ul>
      <li>장점 : data가 특정 distribution을 따른다는 가정이 없어 유연하고, complex pattern을 파악할 수 있다.</li>
      <li>단점 :  속도가 느린 경우가 많고(=비싸다), 더 많은 data를 필요로 하는 경우가 있다(=poor scalability).</li>
      <li>ex) KNNs, Kernel regression, Kernel density estimation, Decision Tree, RF, SVM(w/ nonlinear kernel)</li>
    </ul>
  </li>
</ul>

<h2 id="2-probability">2. Probability</h2>

<h3 id="21---random-variable확률-변수">2.1 - Random Variable(확률 변수)</h3>

<ul>
  <li>
    <p>Random variable : 불확실성(uncertainty)을 가질 수 있는 세계의 일부 측면(aspect), 즉 확률에 따라 변하는 값이다. (e.g. R=Is it raining?)</p>

    <p>보다 엄밀히 말하면 확률실험을 했을 때 발생할 수 있는 결과(possible outcomes, $\Omega$)를 실수값(measurable space, $E$​)로 대응시키는 함수이다.</p>

\[X : \Omega \rightarrow E\]

    <ul>
      <li>Random variable은 알파벳 대문자로 쓰인다. (e.g. $X$)</li>
      <li>Random variable은 domain이 있다. (e.g. R in {true, false})</li>
    </ul>

    <blockquote>
      <p>Random variable은 <strong>measurable function</strong>이다.</p>
    </blockquote>
  </li>
  <li>Probability distribution : random variable의 모든 값과 그에 대응하는 확률들이 이루는 distribution
    <ul>
      <li>discrete random variable의 distribution은 table로 나타난다.</li>
      <li>확률은 scalar이다.</li>
      <li>$\forall x,\; P(X=x)\geq 0 \;and\; \sum\limits_x P(X=x)=1$</li>
    </ul>
  </li>
  <li>Probability function : random variable에 의해 정의된 실수를 확률에 대응시키는 함수</li>
</ul>

<h3 id="22---joint-distribution">2.2 - Joint Distribution</h3>

<ul>
  <li>Joint Distribution : 두 개 이상의 random variable의 set을 실수에 대응시킨다.
    <ul>
      <li>
        <p>$P(x_1,x_2,\dots,x_n)\ge0 \;and\; \sum\limits_{(x_1,x_2,\dots,x_n)}P(x_1,x_2,\dots,x_n)=1$</p>

        <p><img src="https://min0219.github.io/images/2025-01-15-GM02/Untitled.png" alt="Untitled" style="zoom: 40%;" /></p>
      </li>
    </ul>
  </li>
  <li>Probabilistic Model(확률 모델)은 관심 변수에 대한 joint distribution이다.
    <ul>
      <li>모든 분포에 대해 다 구하는 것은 비현실적이다.</li>
    </ul>
  </li>
</ul>

<h3 id="23---event사건">2.3 - Event(사건)</h3>

<ul>
  <li>outcome : 모든 변수에 대한 joint assignment, $(x_1,x_2,\dots,x_n)$</li>
  <li>Event($E$) : outcome들의 set, 표본공간의 subset이다.
    <ul>
      <li>$P(E)=\sum\limits_{(x_1,x_2,\dots,x_n)\in E}P(x_1,x_2,\dots,x_n)$</li>
    </ul>
  </li>
</ul>

<h3 id="24---marginal-distribution">2.4 - Marginal distribution</h3>

<ul>
  <li>
    <p>Marginalization(Summing out) : Collapsed row들을 더하여 없앤다.</p>

\[P(X_1=x_1) = \sum \limits_{x_2}P(X_1=x_1,\,X_2=x_2)\]
  </li>
  <li>
    <p>Marginal Distribution : variable을 제거한 sub-table이다.</p>

    <p><img src="https://min0219.github.io/images/2025-01-15-GM02/e5069633-e21c-4a85-941c-8846b99fcfb0.png" alt="e5069633-e21c-4a85-941c-8846b99fcfb0" style="zoom:80%;" /></p>
  </li>
</ul>

<h3 id="25---conditional-probability">2.5 - Conditional probability</h3>

<ul>
  <li>
    <p>Conditional probability $ P(A\mid B) $ : 사건 $ B $가 일어났다는 조건 아래 사건 $ A $의 확률</p>

\[P(A\mid B) = \frac{P(A,B)}{P(B)}\]

    <p><img src="https://min0219.github.io/images/2025-01-15-GM02/Untitled 1-1736934874043-4.png" alt="Untitled 1" style="zoom: 50%;" /></p>
  </li>
  <li>
    <p>Normalization Trick : 전체 Conditional Distribution을 얻기 위한 과정</p>

    <ol>
      <li>주어진 Evidence와 대응하는 joint probability들을 선택</li>
      <li>
        <p>Normalize (합을 1로 만든다.)</p>

        <p><img src="https://min0219.github.io/images/2025-01-15-GM02/Untitled 2.png" alt="Untitled 2" /></p>
      </li>
    </ol>
  </li>
</ul>

<h3 id="26---probabilistic-inference확률적-추론">2.6 - Probabilistic Inference(확률적 추론)</h3>

<ul>
  <li>
    <p>Probabilistic Inference : 다른 known probabilities로부터 원하는 hidden variable의 확률(belief)를 계산하는 방법이다. (e.g. joint로부터 conditional)</p>

    <p>ex) observable evidence(물웅덩이)를 보고 hidden variable(비)의 확률을  알아내는 것</p>
  </li>
  <li>
    <p>Inference by Enumeration(열거) : probability table이 있다고 가정할 때, 알고 있는 evidence 중 원하는 사건을 선택한다. 이후 hidden variable을 없애기 위해 Marginalization한 후, Normalize한다.</p>

    <ul>
      <li>
        <p>ex) $P(W=sun\mid winter,hot)$ 구하기</p>

        <p><img src="https://min0219.github.io/images/2025-01-15-GM02/Untitled 3.png" alt="Untitled 3" style="zoom:80%;" /></p>

        <ol>
          <li>evidence (winter, hot)에 해당되는 row만 선택한다.</li>
          <li>hidden variable이 없으니 바로 normalization한다.
  ⇒ $P(sun\mid winter,hot)=0.1/0.15=0.67$</li>
        </ol>
      </li>
    </ul>
  </li>
</ul>

<h3 id="27---product-rule">2.7 - Product rule</h3>

<ul>
  <li>
    <p>Product rule : Conditional probability와 marginal probability의 확률을 곱하면 joint probability이다.</p>

\[P(x,y) = P(x\mid y)P(y)\; \Longleftrightarrow \;P(x\mid y)=\frac{P(x,y)}{P(y)}\]
  </li>
</ul>

<h3 id="28---chain-rule">2.8 - Chain rule</h3>

<ul>
  <li>
    <p>Chain rule : Product rule을 일반화한 것이다.</p>

    <p><img src="https://min0219.github.io/images/2025-01-15-GM02/Untitled 4.png" alt="Untitled 4" /></p>
  </li>
</ul>

<h3 id="29---bayes-theorem">2.9 - Bayes Theorem</h3>
<ul>
  <li>
    <p>Bayes Theorem : event $e$가 원인이고, data $D$가 결과일 때, $P(e\mid D)$, 즉 $D$가 관측되었을 때 $e$가 일어날 확률을 추론할 수 있게 하는 식이다.</p>

    <p>Bayes Theorem을 통해 data가 관측되기 전의 prior값이 data가 주어지면서 어떻게 변하는지 계산할 수 있다. 따라서 기존의 data에 새로운 data를 반영해 최종 결과를 얻을 수 있다.</p>

    <p>ex) e = “나는 감기에 걸렸다.” /  D = “콧물”, “기침”, “발열”</p>

\[P(e\mid D)=\frac{P(D\mid e)P(e)}{P(D)}\quad (e:cause\, \cdot\,event , D:effect)\]

    <ul>
      <li>$P(e\mid D)$, <code class="language-plaintext highlighter-rouge">Posterior(**사후 확률**)</code> : data D가 관측된 후 갱신된 event E의 확률</li>
      <li>$P(e)$, <code class="language-plaintext highlighter-rouge">Prior(**사전확률**)</code> : data D가 관측되기 전에 가지고 있던 event E의 확률(이미 알고 있음). 대부분의 문제에서 함수의 본 모습을 파악하는 것이 어렵다. 따라서 미리 분포를 가정한다.</li>
      <li>$P(D\mid e)$, <code class="language-plaintext highlighter-rouge">Likelihood(**가능도**)</code> : event E가 발생한 경우 관측치 D를 얻을 확률</li>
      <li>$P(D)$, <code class="language-plaintext highlighter-rouge">Evidence, Marginal probability(**증거**)</code> : D의 확률, normalizing constant</li>
    </ul>
  </li>
</ul>

<h2 id="3-mle-vs-map">3. MLE vs. MAP</h2>

<p>MLE와 MAP는 probability model을 이용하여 parameter $\theta$를 추정하는 방법이다. 두 방법 모두 full distribution을 구하지 않고 single estimate를 계산한다. (Full distribution을 구하는 것은 Generative model)</p>

<p>두 방법 모두 아래의 Bayes Theorem을 기반으로 하는데, 목적은 둘 다 <strong>posterior</strong> probability인 $P(\theta\mid X)$을 <strong>maximize</strong>하는 것이다.</p>

\[P(\theta\mid X) = \frac{P(X\mid \theta)P(\theta)}{P(X)}\]

<h3 id="31---mlemaximum-liklihood-estimation">3.1 - MLE(Maximum Liklihood Estimation)</h3>
<ul>
  <li>MLE : <code class="language-plaintext highlighter-rouge">Likelihood</code> $P(X\mid \theta)$를 최대로 만드는 $\theta$를 찾는 방법이다. 아래 식에서 볼 수 있듯이 MLE는 Likelihood에 비례하기 때문에 prior distribution이 나쁠 때 사용하는 것이 좋다.</li>
</ul>

\[\DeclareMathOperator*{\argmax}{arg\,max}
\theta_{MLE} = \argmax\limits_{\theta}P(X\mid \theta)\]

<h3 id="32---mapmaximum-a-posteriori">3.2 - MAP(Maximum A Posteriori)</h3>
<ul>
  <li>MAP : <code class="language-plaintext highlighter-rouge">Posterior</code> $P(\theta \mid X)$를 최대로 만드는 $\theta$를 찾는 방법이다. 과정은 아래와 같고, prior와 Likelihood에 비례한다는 것을 알 수 있다. 따라서 MAP은 prior probability$P(\theta)$가 잘 주어졌을 때 사용해야 한다.</li>
</ul>

\[\begin{align*}\theta_{MAP} &amp;= \argmax\limits_{\theta}P(\theta\mid X)=\argmax\limits_{\theta}\frac{P(X\mid \theta)P(\theta)}{P(X)}\\&amp;=\argmax\limits_{\theta} P(X\mid \theta)P(\theta) \quad\quad\quad\quad\quad\, (P(X) \;무시)\\ &amp;= \argmax\limits_{\theta}[\log P(X\mid \theta)+\log P(\theta)]\quad (log를\;취함)\end{align*}\]

<h2 id="4-naive-bayes-classifier">4. Naive Bayes Classifier</h2>

<h3 id="41---naive-bayes-classifier">4.1 - Naive Bayes Classifier</h3>

<ul>
  <li>Naive Bayes Classifier : set of feature$(X_1,X_2,\dots,X_k)$가 있을 때, 이를 set of classes${c_j}$ 중 most likely class로 분류하는 <a href="https://www.notion.so/Chapter2-Generative-Models-for-Discrete-data-e08b08daa5df4203866b25aa23ff7653?pvs=21">Bayes Theorem</a> 기반 Classifier(class에 속할 확률을 계산한다).
    <ul>
      <li>
        <p><strong><code class="language-plaintext highlighter-rouge">Conditionally Independent</code></strong> : Naive Bayes Classifier은 class에 대해 각 feature들이 모두 conditionally independent하다는 가정 하에 확률 계산을 단순화한다.</p>

        <p>⇒ Naive 하다.</p>

        <blockquote>
          <p>조건이 되는 별개의 확률변수 $Z$에 대한 $X,Y$의 조건부확률이 $Z$에 대한 $X$, $Z$에 대한 $Y$의 조건부확률의 곱과 같은 것을 말한다. 이 때, $X$와 $Y$가 $Z$에 대해 Conditionally Independent라고 한다.</p>
        </blockquote>

\[Conditionally\;Independent, X⫫Y\mid Z  \\
  \begin{align*}\forall x,y,z:P(x,y\mid z)&amp;=P(x\mid z)P(y\mid z)\\&amp;=P(x\mid z)P(y\mid x,z) \\ 
  \forall x,y,z:P(x\mid z,y)&amp;=P(x\mid z) \\ 
  \forall x,y,z:P(y\mid z,x)&amp;=P(y\mid z) \end{align*}\]
      </li>
    </ul>
  </li>
</ul>

<h3 id="42---naive-bayes-classifier-과정">4.2 - Naive Bayes Classifier 과정</h3>

<ol>
  <li>
    <p>class $c_j$와 feature $X_i$의 joint probability는 $P(X_1,\dots,X_K,c_j)$이다. class에 대해 각 feature는 conditionally independent하기 때문에 아래와 같이 유도할 수 있다.</p>

\[P(X,c_j)=P(X_1,\dots,X_k\mid c_j)P(c_j)=P(c_j)\prod_{i=1}^k P(X_i\mid c_j) \\ 
 \Rightarrow P(c_j\mid X_1,\dots,X_k)=\frac{P(X_1,\dots,X_k\mid c_j)P(c_j)}{P(X_1,\dots,X_k)}\]

    <ul>
      <li>$P(c_j)$ : prior probability</li>
      <li>$P(X_i\mid c_j)$ : conditional probability</li>
    </ul>
  </li>
  <li>
    <p>이 때, $P(X_1,\dots,X_k)$는 모든 class에 대해 동일하기 때문에, 무시할 수 있다. 따라서 최적의 $c_j$를 선택하기 위해 $P(X_1,\dots,X_k\mid c_j)P(c_j)$를 maximize하는 $c_j$를 선택하면 된다.</p>

\[\begin{align*} c_j &amp;\leftarrow \argmax\limits_{c_j} P(X_1,\dots,X_k\mid c_j)P(c_j)\\ 
 &amp;=\argmax\limits_{c_j} P(c_j)\prod_{i=1}^k P(X_i\mid c_j) \end{align*}\]

    <ul>
      <li>$P(c_j)=\frac{N_d(c_j)}{N_d}$        ($N_d$ : # of docs / $N_d(c_j)$ : # of docs in class $c_j$)</li>
      <li>$P(X_i\mid c_j)=\frac{N_d(X_i,c_j)}{N_d(c_j)}$     ($N_d(X_i,c_j)$ : # of docs with $X_i$ in class $c_j$)</li>
    </ul>
  </li>
</ol>

<h3 id="43---naive-bayes-classifier-장단점">4.3 - Naive Bayes Classifier 장단점</h3>

<ul>
  <li>장점
    <ul>
      <li><strong>Simple and Fast</strong> : class에 대한 term frequency data에만 의존, 반복 없이 training dataset을 한번만 통과한다.</li>
      <li><strong>Compact Model</strong> : 크기는 feature와 class의 개수에 비례한다.</li>
      <li><strong>Very well-behaved numerically</strong> : term의 weight은 해당 term의 frequency에만 의존한다.</li>
      <li><strong>Can work very well with sparse data</strong> : dependent term의 조합이 rare한 data에서 잘 작동함.</li>
    </ul>
  </li>
  <li>단점
    <ul>
      <li><strong>Subject to error and bias</strong> : term의 확률이 독립적이지 못할 때 오류 및 bias 발생</li>
      <li><strong>Can’t model patterns in data</strong></li>
      <li><strong>Typically not as accurate</strong> : 위와 같은 이유로 정확성이 다른 방법보다 떨어진다.</li>
    </ul>
  </li>
</ul>]]></content><author><name>SeokMin</name></author><category term="Generative-Models" /><summary type="html"><![CDATA[1. Parametric models vs. Nonparametric models]]></summary></entry><entry><title type="html">[Generative Models] 01-Intro</title><link href="https://min0219.github.io/generative-models/GM01/" rel="alternate" type="text/html" title="[Generative Models] 01-Intro" /><published>2025-01-14T00:00:00+09:00</published><updated>2025-01-14T00:00:00+09:00</updated><id>https://min0219.github.io/generative-models/GM01</id><content type="html" xml:base="https://min0219.github.io/generative-models/GM01/"><![CDATA[<h2 id="1-generative-model의-종류">1. Generative Model의 종류</h2>

<p><img src="https://min0219.github.io/images/2025-01-14-GM01/Untitled-1736839481822-1.png" alt="Untitled" /></p>

<ol>
  <li><strong>GAN(Generative Adversarial Networks)</strong> : GAN은 unsupervised learning problem인 data generation을 supervised problem으로 modelling하는 smart solution을 제공한다.</li>
  <li><strong>VAE(Variational AutoEncoder)</strong> : VAE는 Evidence Lower Bound(ELBO)를 최대화하여 data의 log-likelihood를 inexplicitly 최적화한다.</li>
  <li><strong>Flow-based models</strong> : Flow-based model은 일련의 가역(invertable) 변환에 의해 구성된다. 위의 두 model과 달리 data distribution p(x)를 explicitly(명시적으로) 학습하므로 loss function은 단순히 negative log-likelihood이다.</li>
  <li><strong>Diffusion Models</strong> : data에 noise를 조금씩 더해가거나 noise로부터 조금씩 복원해가는 과정을 통해 data를 생성하는 model이다.</li>
</ol>

<h2 id="2-generative-models-vs-discriminative-models">2. Generative Models vs. Discriminative Models</h2>
<h3 id="21---classification">2.1 - Classification</h3>
<p>Classification을 하는 경우 위의 사진과 같이 $X$의 데이터마다 labeled class $Y$가 있다. 따라서 목적은 $P(Y|X)$를 maximize하는 $Y$를 찾는 것이다. 즉, $X$가 주어졌을 때의 Posterior 함수를 최대화시키는 것이다.</p>

<p><img src="https://min0219.github.io/images/2025-01-14-GM01/Untitled 1-1736839516071-3.png" alt="Untitled 1" /></p>

<h3 id="22---generative-models생성-모델">2.2 - Generative Models(생성 모델)</h3>
<p>Generative Model의 경우 위의 Classification 문제에서 각 Class 별로 가지는 likelihood인 $P(X|Y)$와 Prior distribution인 $P(Y)$를 이용하여 Data $X$와 Class $Y$ 둘의 joint probability를 modelling한다. 이 model을 이용해 새로운 data가 어느 class인지 결정한다. Generative Model은 label이 없을 경우 joint probability $P(X,Y)$ 또는 $P(X)$를 capture한다.</p>

<p>이 때, joint probability를 학습하여 기존 Data를 생성하는 model을 만들었기 때문에 Generative Model이라고 한다. <mark style="background-color: #fbf3db">Generative Model은 말 그대로 sample dataset을 생성할 수 있다.</mark></p>

<blockquote>
  <p>대표적으로 GAN, VAE, Flow-based Model, Diffusion Model이 있다.</p>
</blockquote>

<h3 id="23---discriminative-models판별-모델">2.3 - Discriminative Models(판별 모델)</h3>
<p>Discriminative Model은 바로 $P(Y|X)$를 학습시켜 학습된 parameter를 직접 이용하여 class를 결정한다. 따라서 Discriminative Model이라 부른다. Data $X$의 class $Y$를 잘 구분하는 decision boundary를 학습하는 것이 목표이다.</p>

<blockquote>
  <p>대표적으로 linear regression, logistic regression이 있다.</p>
</blockquote>

<ul>
  <li>
    <p>아래 그래프는 두 model의 특징과 차이를 잘 보여준다.</p>

    <p><img src="https://min0219.github.io/images/2025-01-14-GM01/Untitled 2-1736839537342-5.png" alt="Untitled 2" /></p>
  </li>
</ul>

<h2 id="3-applications-of-generative-models">3. Applications of generative models</h2>
<ul>
  <li><strong>Content Generation</strong> : 이미지, 영상 등의 생성</li>
  <li><strong>Data Augmentation(data 증강)</strong> : data의 핵심 feature는 간직한 채, noise를 더하여 dataset을 확장하는 방법이다. 따라서 적은 수의 data로 여러 data를 얻을 수 있다.</li>
  <li><strong>Anomoly Detection(이상 탐지)</strong> : data 안에서 anomaly, outlier, abnormal과 같이 예상하지 못한 data pattern을 찾아내는 것이다.</li>
  <li><strong>Representation learning</strong> : data만 제공하면 data로부터 핵심 정보를 추출하고, 이를 기계 스스로 배우는 학습 과정이다.</li>
  <li><strong>Inverse Problem</strong> : 결과로부터 원인을 계산하는 문제이다.</li>
</ul>]]></content><author><name>SeokMin</name></author><category term="Generative-Models" /><summary type="html"><![CDATA[1. Generative Model의 종류]]></summary></entry></feed>