<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Archive</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Thu, 27 Jul 2023 12:02:23 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. Archive. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jiwon-km" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[#1] LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS]]></title>
            <link>https://velog.io/@jiwon-km/1-LORA-LOW-RANK-ADAPTATION-OF-LARGE-LANGUAGE-MODELS</link>
            <guid>https://velog.io/@jiwon-km/1-LORA-LOW-RANK-ADAPTATION-OF-LARGE-LANGUAGE-MODELS</guid>
            <pubDate>Thu, 27 Jul 2023 12:02:23 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>영상을 보고 정리해보는 LoRA ~
🔆 Low-rank Adaptation == LoRA</p>
</blockquote>
<h3 id="key-idea">KEY IDEA</h3>
<ul>
<li>PEFT의 기술 중 하나이다.</li>
<li>어떻게 효율적으로 파라미터 수를 줄이며 파인튜닝을 진행하게 되냐면, 원래 모델의 가중치들은 동결하고 <strong>low-rank를 갖는 행렬</strong>들을 새로 정의하여 그 행렬의 파라미터들만 업데이트하도록 한다.</li>
</ul>
<h3 id="intuition">INTUITION</h3>
<ul>
<li>일반적으로 가중치 행렬은 full-rank를 갖지만, 어떤 특정 태스크에서는 사전 훈련된 모델의 웨이트 행렬이 낮은 “intrinsic rank”를 갖는다는 연구(<a href="https://arxiv.org/abs/2012.13255">Aghajanyan et al. (2020)</a>)가 있었다.</li>
<li>따라서 이러한 사전 연구에 기반하여, LoRA 논문에서는 가중치에 대한 업데이트도 어댑테이션 과정에서 low-rank를 갖는다고 가정한다. </li>
</ul>
  <details>
  <summary>😲 랭크가 뭔데요?</summary>
  <div markdown="1">

<ul>
<li><p>행렬에서 rank란,행렬의 열 벡터들이 서로 독립적인 벡터의 개수를 의미한다. 즉, 선형적으로 독립인 열 벡터의 최대 수를 의미한다.</p>
<ul>
<li>예를 들면, 5x5 행렬이 있다고 가정하자. 만약 이 행렬의 랭크가 1이라면 모든 열 벡터가 하나의 리니어 컴비네이션으로 표현될 수 있다. 만약 랭크가 5라면, 모든 열 벡터는 선형 독립이다. </li>
</ul>
</li>
<li><p>즉, 랭크가 낮을 수록 행렬의 정보가 중복되거나 불필요하다는 것을 의미한다. 따라서 랭크가 낮다면, 행렬의 차원을 줄일 수도 있다는 것을 의미한다. </p>
</div>
</details>

</li>
</ul>
<details>
  <summary>🤓 수학적 설명 w/예시 </summary>
  <div markdown="1">


<ul>
<li><a href="https://www.youtube.com/watch?v=PXWYUTMt-AU">https://www.youtube.com/watch?v=PXWYUTMt-AU</a> 이 영상에서 설명하는 내용이다.</li>
</ul>
<ul>
<li><p>간단한 예시를 통해, 행렬이 낮은 랭크 값을 가진다면, low-rank를 가진 행렬로 분해함으로서 차원도 축소하고 정보도 그대로 가져갈 수 있다는 것을 확인해볼 수 있다.</p>
</li>
<li><p>랭크가 2, 그리고 차원이 10x10인 행렬을 하나 초기화하자.</p>
</li>
<li><p>그 다음 특이값 분해를 통해 행렬을 U,S,V로 분해할 수 있다. 그 다음 U@S는 행렬 b, V는 행렬 a로 표현할 수 있다.</p>
</li>
<li><p>그 다음, 원본 행렬과 행렬 b,a의 행렬곱의 결과에 임의의 연산(e.g., 웨이트 곱하고 바이어스 더하기)을 수행해주면, 두 출력이 동일함을 확인할 수 있다.</p>
</li>
<li><p>즉, 행렬의 랭크를 이용하여 더 낮은 행렬로 쪼갤 수 있고, 이는 원래 행렬의 중요한 정보도 그대로 포착할 수 있다.</p>
<ul>
<li>(코드 셀 추가할 예정)</li>
</ul>
</li>
</ul>
  </div>
  </details>


<h3 id="method">METHOD</h3>
<ul>
<li>예를 들면, 우리가 잘 아는 트랜스포머는 인코더/디코더가 있고 각각은 self-attention과 feedforward를 포함하고 있는 구조이다. </li>
<li>사전 학습을 진행하면 이 네트워크들의 웨이트가 업데이트 될 것이다.
<img src="https://velog.velcdn.com/images/jiwon-km/post/3ec6f75f-9609-497e-b8d5-c2adeb23d0c4/image.png" alt=""></li>
</ul>
<ul>
<li>이 때, LoRA는 이러한 원래 모델의 파라미터들을 동결하고, 파인튜닝 과정에서 원래 모델의 가중치는 그대로 두고, low-rank decomposition 행렬 쌍을 추가로 주입하게 된다. </li>
<li>이 때 주입되는 행렬들은 원래 모델의 웨이트 행렬과 차원이 같도록 설정한다. (추후 웨이트 행렬을 만들어야 하니까!)</li>
</ul>
<p>절차를 살펴보면 다음과 같다. </p>
<ol>
<li><p>원래 모델의 파라미터들을 고정한다. 원래 모델의 웨이트에 대해서는 오직 read만 수행하며, 백프로파게이션 등을 수행하지 않는다.
<img src="https://velog.velcdn.com/images/jiwon-km/post/1e1005ec-2708-40af-9a7a-d6ab31cb07ab/image.png" alt=""></p>
</li>
<li><p>동일한 지도 학습 프로세스를 사용하여 한 쌍의 low-rank decomposition 행렬을 주입하고, 훈련한다 (사진 상에서는 2~3 step)
<img src="https://velog.velcdn.com/images/jiwon-km/post/055607f0-e007-48ea-8bb6-9fdab1812769/image.png" alt=""></p>
</li>
<li><p>인퍼런스 과정에서는, 한 쌍의 행렬을 곱하여, 고정해두었던 원래 모델의 파라미터와 같은 크기의 행렬을 만든다음, 두 행렬을 더하여 업데이트한다.
<img src="https://velog.velcdn.com/images/jiwon-km/post/9644e391-9743-4b19-a502-c978c647f827/image.png" alt=""></p>
</li>
</ol>
<ul>
<li>추가로, 피드포워드 네트워크에서도 LoRA가 적용될 수도 있지만, 보통은 위의 예시처럼 셀프어텐션 레이어세만 적용되는 경우가 많다고 한다.<ul>
<li>대부분의 파라미터가 셀프어텐션 레이어에 존재하기 때문이다.</li>
</ul>
</li>
</ul>
<h3 id="장점">장점</h3>
<ul>
<li>full-finetune 과정에서 요구하는 것보다 훨씬 적은 파라미터를 사용한다. </li>
<li>그만큼 저장공간도 덜 필요하게 되고, </li>
<li>백프로파게이션 속도도 빨라지게 된다. </li>
<li>또한, 적은 연산량을 가지고도 full-finetune 기법과 비견할 만한 성능을 낼 수 있다 (논문 실험 섹션에 정리되어 있음).</li>
</ul>
<ul>
<li>실제 사용하는 입장에서는, 연산량이 기존 LLM의 15~20%로 줄어들기 때문에, 단일 GPU에서도 학습할 수 있다.</li>
</ul>
<p>웨이트 파라미터에 대해서 자세히 보게 되면, 영상에서는 예를 들어 설명하고 있다.
만약 Attention is All You Need 논문에서 사용한 트랜스포머 아키텍처를 사용하고, rank는 8로 설정한다고 가정해보자.
<img src="https://velog.velcdn.com/images/jiwon-km/post/6edd5a06-d1cc-4c47-8e86-3d30cf8cdc77/image.png" alt=""></p>
<ul>
<li>위와 같이 원래는 $$d<em>k = 512</em>64 = 32,768$$ 의 파라미터가 필요하지만, 랭크가 8인 LoRA에서는 두두 쌍의 행렬들이 각각 $$r<em>k=8</em>64=512$$, $$d<em>r=512</em>8=4,096$$의 파라미터가 필요하기 때문에 도합 4,608개의 파라미터만 사용하면 된다.
=&gt; 즉, 파라미터 수를 86%나 감소시킬 수 있다!</li>
</ul>
<p>또한, 태스크를 여러개 수행하는 상황에서도, full-finetuning을 사용했을 때 처럼 개별 태스크에 대한 모델을 각각 정의할 것이 아니라, LoRA 매트릭스 값만 업데이트 해주면 되니, 메모리 측면에서 상당히 효율적이다. 
<img src="https://velog.velcdn.com/images/jiwon-km/post/f733b878-7f8d-45c9-9696-209661fad574/image.png" alt=""></p>
<h3 id="한계">한계</h3>
<ul>
<li><p>low-rank approximation process에서 모델 성능에 영향을 미칠 수 있는 정보 손실이 일어날 수 있다. 연산량과 성능의 트레이드 오프  ..</p>
</li>
<li><p>논문의 실험 파트에서도 볼 수 있듯, 랭크를 얼마로 설정하냐가 성능에 큰 영향을 끼친다. 따라서 랭크 값을 잘 설정하는 것이 중요하다. </p>
</li>
</ul>
<h3 id="코드">코드</h3>
<p><a href="https://github.com/microsoft/LoRA">👉 github link</a> : 마이크로 소프트에서 제공하는 오피셜 코드</p>
<ul>
<li>토치의 <code>nn.Linear, nn.Embedding, nn.Conv2d</code>을 대체할 수 있는 클래스들을 <code>loralib/</code>에서 각각 제공하고 있다. </li>
<li>여기에 추가로 일부 Attention qkv 프로젝션 구현과 같이 단일 <code>nn.Linear</code>가 둘 이상의 레이어를 나타내는 경우를 위하여 <code>nn.MergedLinear</code>도 제공하고 있다.</li>
</ul>
<ul>
<li><code>class Embedding(nn.Embedding, LoRALayer)</code> : PyTorch의 <code>nn.Embedding</code> 모듈을 상속받아 LoRA 레이어를 추가한 클래스를 대표로 살펴보면 다음과 같다.</li>
</ul>
<pre><code class="language-python">class Embedding(nn.Embedding, LoRALayer):
    # LoRA implemented in a dense layer
    def __init__(
        self,
        num_embeddings: int,
        embedding_dim: int,
        r: int = 0,
        lora_alpha: int = 1,
        merge_weights: bool = True,
        **kwargs
    ):
        nn.Embedding.__init__(self, num_embeddings, embedding_dim, **kwargs)
        LoRALayer.__init__(self, r=r, lora_alpha=lora_alpha, lora_dropout=0,
                           merge_weights=merge_weights)

        # Actual trainable parameters
        # LoRA 레이어에 대한 학습 가능한 가중치(한 쌍의 low-rank 분해 행렬) 를 초기화 함
        if r &gt; 0:
            self.lora_A = nn.Parameter(self.weight.new_zeros((r, num_embeddings)))
            self.lora_B = nn.Parameter(self.weight.new_zeros((embedding_dim, r)))
            self.scaling = self.lora_alpha / self.r
            # Freezing the pre-trained weight matrix
            self.weight.requires_grad = False
        self.reset_parameters()

    def reset_parameters(self):
        # 임베딩 레이어의 가중치를 초기화
        nn.Embedding.reset_parameters(self)
        if hasattr(self, &#39;lora_A&#39;):
            # initialize A the same way as the default for nn.Linear and B to zero
            nn.init.zeros_(self.lora_A)
            nn.init.normal_(self.lora_B)

    def train(self, mode: bool = True):
        nn.Embedding.train(self, mode)
        if mode:
            if self.merge_weights and self.merged:
                # Make sure that the weights are not merged
                if self.r &gt; 0:
                    self.weight.data -= (self.lora_B @ self.lora_A).transpose(0, 1) * self.scaling
                self.merged = False
        else:
            if self.merge_weights and not self.merged:
                # Merge the weights and mark it
                if self.r &gt; 0:
                    self.weight.data += (self.lora_B @ self.lora_A).transpose(0, 1) * self.scaling
                self.merged = True

    def forward(self, x: torch.Tensor):
        if self.r &gt; 0 and not self.merged:
            result = nn.Embedding.forward(self, x)
            after_A = F.embedding(
                x, self.lora_A.transpose(0, 1), self.padding_idx, self.max_norm,
                self.norm_type, self.scale_grad_by_freq, self.sparse
            )
            result += (after_A @ self.lora_B.transpose(0, 1)) * self.scaling
            return result
        else:
            return nn.Embedding.forward(self, x)</code></pre>
<ul>
<li>먼저 학습가능한 두 쌍의 low-rank 분해 행렬 lora_A와 lora_B을 입력받은 차원 관련 파라미터에 맞게 초기화한다.</li>
<li><code>reset_parameters</code> : 행렬 lora_A와 lora_B을 초기화한다. 이 때, 논문과 동일하게 0과 가우시안 분포로 초기화한다.<ul>
<li>$$d<em>k$$ 의 웨이트를 분해하여 $$r</em>k = (r, num_embeddings)$$과 $$d*r = (embedding_dim, r)$$ 의 크기를 갖는 행렬로 쪼갠다.</li>
</ul>
</li>
<li><code>train</code> : 파라미터(mode, merged)에 따라서, weight를 업데이트 하거나 복원을 한다.<ul>
<li>웨이트를 계산하는 것 자체는, <code>self.weight.data += (self.lora_B @ self.lora_A).transpose(0, 1) * self.scaling</code> 이렇게 표현된다. 행렬 곱을 하고 scaling을 해준 다음, 원래 웨이트와 더한다. 간단.</li>
</ul>
</li>
<li><code>forward</code> : 입력이 들어오면 임베딩을 넘겨주는 포워드 패스 연산을 정의하고 있다. <ul>
<li>만약에 파인튜닝이 완료되지 않은 경우에는 (if문), <code>nn.Embedding.forward(self, x)</code>를 통해 기존의 임베딩 레이어를 사용하여 result를 계산한다. </li>
<li>그 다음, <code>F.embedding</code>을 통해 입력 x와 self.lora_A (파인튜닝된 파라미터)의 임베딩 결과인 after_A를 계산한다.</li>
<li>마지막으로, 위의 결과와 self.lora_B을 행렬곱하여 최종 아웃풋을 뽑아내게 된다. </li>
</ul>
</li>
</ul>
<hr>
<h3 id="reference">Reference</h3>
<ul>
<li><a href="https://arxiv.org/abs/2106.09685">Paper(arxiv)</a></li>
<li><a href="https://www.coursera.org/learn/generative-ai-with-llms/lecture/NZOVw/peft-techniques-1-lora">코세라 강의</a> : 모든 이미지와 전반적인 설명을 가져왔다.</li>
<li><a href="https://www.youtube.com/watch?v=PXWYUTMt-AU">Youtube 영상</a> : 이해를 도와주는 좋은 영상</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[OpenCV error] contours data type = 17 is not supported]]></title>
            <link>https://velog.io/@jiwon-km/OpenCV-error-contours-data-type-17-is-not-supported</link>
            <guid>https://velog.io/@jiwon-km/OpenCV-error-contours-data-type-17-is-not-supported</guid>
            <pubDate>Thu, 11 May 2023 09:49:56 GMT</pubDate>
            <description><![CDATA[<h2 id="problem">Problem</h2>
<p>세그멘테이션 작업을 위해 이미지 마스크를 만들기 위해 아래와 같이 cv.drawContours()를 아래와 같이 사용하고 있었다.</p>
<pre><code>cv.drawContours(background, [cnt], 0, (R, G, B), 2)</code></pre><p>그런데 특정 컨투어([cnt]) 몇 개에서만 아래와 같은 오류가 발생했다.</p>
<pre><code>Traceback (most recent call last):
  File &quot;masking_image.py&quot;, line 175, in &lt;module&gt;
    Scene_Mask_Generation(file_list, args.png_dir, args.save_dir)
  File &quot;masking_image.py&quot;, line 126, in Scene_Mask_Generation
    cv.drawContours(background, [cnt], 0, (R, G, B), 2)
cv2.error: OpenCV(4.5.2) :-1: error: (-5:Bad argument) in function &#39;drawContours&#39;
&gt; Overload resolution failed:
&gt;  - contours data type = 17 is not supported
&gt;  - Expected Ptr&lt;cv::UMat&gt; for argument &#39;contours&#39; </code></pre><p>컨투어를 확인해보니 모두 동일한 2D array 였는데! 
왜 특정 컨투어만 안되는지 모르겠어서 해결 방법을 찾아봤다. 대강 <code>contours data type = 17 is not supported</code> 이게 타입 오류라는 것 같기는 했다.</p>
<hr>
<h2 id="solve">Solve</h2>
<pre><code>cnt = np.int32(cnt) #를 추가해주자!</code></pre><p>cnt를 넣어주기 전에, np.array의 int32 타입으로 변경해주니 해결됐다. 궁금해서 오류났을 때 dtype을 찍어보니 object 형이었다. 
다만 모든 cnt 자체는 <code>cv.cvtColor() -&gt; cv.threshold() -&gt; cv.findContours</code> 의 과정을 거쳐 추출한건데, 왜 어떤 cnt는 정수형으로 뽑히고, 어떤 cnt는 object형으로 뽑혔는지 모르겠다.</p>
<p>하지만 형변환을 통해서 해결할 수 있다는 결론...</p>
<p>끝.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Story Generation] AESOP: Abstract Encoding of Stories, Objects, and Pictures (ICCV, 2021)]]></title>
            <link>https://velog.io/@jiwon-km/Story-Generation-AESOP-Abstract-Encoding-of-Stories-Objects-and-Pictures-ICCV-2021</link>
            <guid>https://velog.io/@jiwon-km/Story-Generation-AESOP-Abstract-Encoding-of-Stories-Objects-and-Pictures-ICCV-2021</guid>
            <pubDate>Wed, 17 Aug 2022 04:00:46 GMT</pubDate>
            <description><![CDATA[<p>Ravi, H., Kafle, K., Cohen, S., Brandt, J., &amp; Kapadia, M. (2021). AESOP: Abstract Encoding of Stories, Objects, and Pictures. In Proceedings of the IEEE/CVF International Conference on Computer Vision (pp. 2052-2063).</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/fbc02adf-3fa8-4067-b0ba-f1d05229f5ec/image.png" alt=""></p>
<blockquote>
<p>   &quot;Examples are the best precept&quot; - Aesop, The Two Crabs</p>
</blockquote>
<hr>
<h3 id="contribution">CONTRIBUTION</h3>
<ol>
<li>새로운 visual storytelling 데이터셋 <strong>AESOP</strong>을 제안. (➕ 코드 및 데이터셋 모두 공개)</li>
<li>새로운 story comprehension 태스크 제안, a novel generalized story comprehension framework</li>
</ol>
<p><br/><br/></p>
<h3 id="다른-논문들과의-차별점-">다른 논문들과의 차별점 ?</h3>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/c1642cbf-15a6-4cfc-b056-35f0750968b5/image.png" alt="">
이 논문의 차별점이자, 강점은 어떤 것이 있는지 먼저 살펴보고 넘어가려고 한다.</p>
<ol>
<li>이 논문이 제안하고 있는 데이터셋은, 앞서 살펴본 두 논문과 달리 이미지 도메인이 <strong>클립아트</strong>이다. 위의 예시에서 확인해볼 수 있는데, 우리가 익히 보던 사진 Image Sequence가 아닌, 애니메이션과 같은 클립아트로 구성이 되어있다.</li>
<li>또한 앞서 살펴본 연구들은 이미지 인코더 -&gt; 텍스트 디코더를 거쳐서 다음에 올 텍스트를 생성하는 태스크를 수행했지만, 이 논문은 <strong>텍스트와 이미지 모두 생성</strong>하는 태스크를 해결한다. 이는 이미지가 아닌 클립아트를 사용했기 때문에 이미지 생성이 수월하게 가능했던 것으로 보인다.</li>
</ol>
<!--기존의 스토리텔링 연구에서 통상적으로 이미지 시퀀스의 생성 태스크는 대부분 후보군 중에서 다음에 올 이미지를 서치하는 -->

<!--

---
### MOTIVATION : 기존 연구의 한계
1. 데이터셋의 한계
visual story datasets은 coherence와 diversity가 부족하다.
2. 태스크의 한계
understanding of vision and language task는 factual description >> narrative
connecting text to image >> forming a coherent narrative
스토리 작성자가 visual input을 제어할 수 없는 상태에서 image sequence에 대한 텍스트 생성 → 실현 가능한(’feasible’) 텍스트만을 생성
-->


<hr>
<h2 id="aesop-dataset">AESOP DATASET</h2>
<h3 id="principles">principles</h3>
<ol>
<li>Creativity Over Perception ➡️ 데이터셋을 생성할 때, visual과 textual part 모두 생성하도록 함. </li>
<li>Causal and Coherent Narratives ➡️ 장르와 타이틀을 제약조건으로 사용</li>
<li>Constrained World Knowledge ➡️ real-world image가 아닌 clip-art image (단순화) 사용</li>
</ol>
<h3 id="data-acquisition-setup">data acquisition setup</h3>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/b9eb7fda-ac3f-4b2a-9627-ada9f8c3570f/image.png" alt=""></p>
<ul>
<li><p>하나의 스토리는 대응하는 visual panel, text panel 쌍 3개로 이루어진다.</p>
</li>
<li><p><a href="https://visualqa.org/">VQA dataset</a> 기반, drag and drop interface 사용. 바로 위에 예시가 있다.</p>
</li>
<li><p>그러나 VQA와 달리 오브젝트 수를 확장했으며 + 배경 종류를 추가했다. (부엌, 해변) </p>
<ul>
<li>다양한 연령, 성별, 인종의 팔다리 변형 가능한 20명의 인간 캐릭터 + 움직이는 동물 9마리 + 고정포즈 동물 30마리</li>
<li>48개의 large object + 60개의 small object</li>
<li>인물은 고정된 이름 있음
<img src="https://velog.velcdn.com/images/jiwon-km/post/82875fb5-2217-43b0-8038-48db7edb5f9e/image.png" alt=""></li>
</ul>
</li>
<li><p>free title and theme (미리 정의된 후보군 중 선택)</p>
</li>
<li><p>7,062 stories ➡️ 21,186 abstract visual scenes, and text</p>
</li>
</ul>
<br/>

<p>최종적으로 구축한 데이터셋의 예시는 아래와 같다. 
<img src="https://velog.velcdn.com/images/jiwon-km/post/ce156c19-d43b-4fc5-b8f5-a5c9f9372260/image.png" alt="that&#39;s my boy!"></p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/9daf5383-a963-4a1c-9656-c957d088214b/image.png" alt="에스파는 나야 둘이 될 순 없어"></p>
<p>기존 이미지 기반 데이터셋들은 기본적으로 존재하는 이미지에 텍스트를 덧입히는 것이기 때문에, *&quot;쿵푸마스터보이가 불량배들에게 일격을 가하는 상황&quot;*에 대한 이미지가 없다면 그러한 스토리를 생성할 수 없다. 
그런데 이렇게 추상적인 클립아트로는 원하는 상황을 직접 생성할 수 있다. 이러한 점에 있어서 저자들은 creativity dataset이라고 강조한다.</p>
<h3 id="aesop-vs-others">AESOP Vs. Others</h3>
<p>저자들은 본인들이 제안하는 데이터셋이, 기존 데이터셋에 비하여 diversity &amp; coherence and causality 측면에서 더 좋다고 주장한다. 
<img src="https://velog.velcdn.com/images/jiwon-km/post/134f744f-16fe-4200-bed3-46f444ec637d/image.png" alt=""></p>
<hr>
<h2 id="aesop-model">AESOP Model</h2>
<p>이 모델이 이야기의 narrative를 잘 이해했는지를 어떻게 평가할까? 저자들은 이를 시작된 이야기를 계속하고, <strong>끝낼 수 있는</strong> 능력으로 평가했다. </p>
<p>위의 능력을 갖춘 모델을 만들기 위해 저자들은 두 가지 타입의 Assistant를 제안했다.</p>
<ol>
<li>Assistant Illustrator : generating the missing visual panel.</li>
<li>Assistant Writer : : generating the missing text panel.</li>
</ol>
<p>이어서 각각의 Assistant를 구성하기 위한 Abstract Visual Representation, Encoder, Decoder를 자세하게 살펴보려고 한다.</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/073d7f89-adf1-497f-b4d3-a752a92e73cc/image.png" alt=""></p>
<h3 id="1-abstract-visual-representation">1. Abstract Visual Representation</h3>
<p>전술했듯, 이 연구는 기존 연구와 달리 <strong>클립아트 이미지</strong>를 사용했다. 따라서 이러한 점을 고려하여 저자들은 새로운 Representation을 제안하게 된다.
구체적인 아이디어는, 이미지를 인코딩 할 때 기존의 방법들처럼 이미지를 <strong>픽셀 단위</strong>로 인식하는 것이 아니라, <strong>오브젝트 단위</strong>로 인식하게 된다. 구체적인 과정은 아래와 같다.</p>
<ul>
<li><p>각 visual token을 인코딩하는 과정에서 object state는 {what the object is, where it is placed, how it is placed}에 대한 정보를 담게 된다.</p>
</li>
<li><p>Visual panel은 다음과 같이 표현되며 $V = [v_0, v_1, ..., v_nmax]$, 패널을 구성하는 각 Object Representation은 $v_i$ : $(o_i, x_i, y_i, z_i, filp_i, pose_i, expr_i)$ 로 표현된다.</p>
</li>
<li><p>구체적으로 오브젝트의 종류, 위치, 포즈 등의 정보는 아래와 같이 인코딩된다. 
<img src="https://velog.velcdn.com/images/jiwon-km/post/6183349d-195c-4694-9b7d-0ac7deed78b7/image.png" alt=""></p>
<blockquote>
</blockquote>
<p>$o_i$ : object identifier
$x_i$, $y_i$ : location of the center of the object in the panel
$z_i$ : size of the object
$filp_i$ : whether the object is facing left or right
$pose_i$ : pose 
$expr_i$ : one of the nine possible expressions for human clip-arts</p>
</li>
</ul>
<h3 id="2-story-encoder">2. Story Encoder</h3>
<ul>
<li>$[V^1, V^2, V^3]$ : the sequence of visual panels</li>
<li>$[S^1, S^2, S^3]$ : the sequence of text panels</li>
</ul>
<p>위에서 정의한 각각의 패널, 그리고 패널간의 관계를 인코딩 하기 위해 총 세 개의 인코더를 사용한다.</p>
<ul>
<li>즉, story encoder : (1) visual, (2) text, and (3) cross-modal encoder.<ul>
<li>visual and text encoder : Bidirectional GRUs.</li>
<li>cross-modal encoder : encoded representation(text, visual) 간의 cross modal attention 수행</li>
</ul>
</li>
</ul>
<h3 id="3-panel-decoder">3. Panel Decoder</h3>
<p><strong>1. visual panel</strong></p>
<ul>
<li>masked visual panel 을 생성하는 문제 ➡️ 다음 시퀀스 $V$를 예측하는 문제<ul>
<li>두 개의 GRU(for tracking <strong>seqeunce of object</strong> and <strong>state of the visual panel</strong>)를 사용했다.<ul>
<li>각 GRU의 hidden state는 visual and text encoders의 final hidden states로 초기화</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>각 타임스텝 t에서, <strong>object decoder</strong>는 {지금까지 예측된 object의 상태와, object에 대한 attention과, input의 word representations}을 결합하여, <strong>current object</strong>를 예측</p>
</li>
<li><p>그 후, object decoder가 예측한 object와 current state를 사용해서, <strong>current object의 attribute</strong>를 예측</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/d1e3dd91-9eed-4ddd-ba88-d6ef44cc0bfb/image.png" alt=""></p>
<ul>
<li>Output : 33-dim vector(20 pose + 9 expression + $x_i$, $y_i$, $z_i$, $flip_i$)</li>
</ul>
</li>
</ul>
<!--    - where attributes($x_i$, $y_i$)는 0과 1사이로 표현, pose and expression classification는 softmax.-->

<p><strong>2. text panel</strong></p>
<ul>
<li>위의 첫 번째 단계에서 사용했던 <strong>object decoder</strong>와 동일한 구조의 디코더를 사용했다. vocabulary size 만 수정해서 사용했음.</li>
<li>regular Maximum Likelihood objective를 사용하여 학습됨.</li>
<li>inference는 nucleus sampling(Top-p)을 사용.</li>
</ul>
<hr>
<h3 id="baseline">Baseline</h3>
<p>저자들이 하고자 하는 태스크와 직접적으로 비교할 만한 기존 연구가 없었기 때문에, 아래의 방법이나 모델의 ablated version과 비교를 진행했다.</p>
<table>
<thead>
<tr>
<th>baseline</th>
<th>전략</th>
<th>description</th>
</tr>
</thead>
<tbody><tr>
<td>Repeat</td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 단순하게 반복하자! &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>Visual panel 생성에만 사용. 보통 visual panel sequence를 보게 되면, 배경이나 등장 인물 같은 major part는 거의 바뀌지 않는 반면, 인물의 표정이나 포즈 같은 아주 minor part만 변하게 된다. 이러한 점에서, 저자들은 그냥 전 단계의 패널을 그대로 가져오는 방법을 베이스라인으로 사용했다! 텍스트의 경우는 이미지와 다르게 크게 변하기 때문에, text panel에는 사용하지 않았다.</td>
</tr>
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Unimodal&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>우리가 일반적으로 생성하는 story generation model</td>
<td>Visual unimodal model. cross modal encoder와, text attention decoder 사용. (GPT-2 기반)</td>
</tr>
<tr>
<td>One-to-One</td>
<td>하나의 modality만 보자!</td>
<td>story context없이, visual panel-&gt; visualen panel, text panel -&gt; text panel 생성.</td>
</tr>
<tr>
<td>Pixel Model</td>
<td>Abstract visual Representation 하지 말자!</td>
<td>visual representation을 Resnet-18 w/ visual attention module.</td>
</tr>
<tr>
<td>Human Baseline</td>
<td>사람이 하자!</td>
<td></td>
</tr>
</tbody></table>
<!--

- **Repeat : 단순하게 반복하자.**
Visual panel 생성에만 사용. 보통 visual panel sequence를 보게 되면, 배경이나 등장 인물 같은 major part는 거의 바뀌지 않는 반면, 인물의 표정이나 포즈 같은 아주 minor part만 변하게 된다. 이러한 점에서, 저자들은 그냥 전 단계의 패널을 그대로 가져오는 방법을 베이스라인으로 사용했다! 텍스트의 경우는 이미지와 다르게 크게 변하기 때문에, text panel에는 사용하지 않았다.
- **Unimodal : 우리가 일반적으로 생성하는 story generation model.**
Visual unimodal model. cross modal encoder와, text attention decoder 사용. (GPT-2 기반)
- **One-to-One : 하나의 modality만 보자!**
story context없이, visual panel-> visualen panel, text panel -> text panel 생성.
- **Pixel Model : Abstract visual Representation 하지 말자!**
visual representation을 Resnet-18 w/ visual attention module.
- **Human Baseline : 사람이 하자!**

-->

<hr>
<h2 id="evaluation--result">Evaluation &amp; Result</h2>
<h3 id="1-automatic-metric">1. Automatic metric</h3>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/f7455a76-f6c6-4d81-9b80-6217e72539dc/image.png" alt=""></p>
<p><strong>1. Assistant Illustration</strong></p>
<ul>
<li>Repeat이 모든 모델, 심지어 사람보다도 더 좋은 성능을 보임. <ul>
<li>이유를 분석해보니, 스토리의 80%는 배경이 바뀌지 않았다. 또한 오브젝트 포지션과 attribute도 바뀌지 않았기 때문.</li>
</ul>
</li>
</ul>
<p><strong>2. Assistant Writer</strong></p>
<ul>
<li>👍 BLEU와 ROUGE-L에서 좋은 성능<ul>
<li>누락된 캐릭터 없이 다 반영이 되었기 때문.</li>
</ul>
</li>
<li>👎 반면, METEOR과 CIDEr에서 그닥인 성능...<ul>
<li>그만큼 시각적 정보와 관련이 있으면서도, 일관된 내러티브 생성이 어렵다! </li>
</ul>
</li>
</ul>
<h3 id="2-human-evaluation">2. Human Evaluation</h3>
<ol>
<li>Coherent : 생성된 콘텐츠가 이전의 콘텐츠와 일관성이 있는지?</li>
<li>Relevant : 생성된 콘텐츠가 이전 콘텐츠와 관련이 있는지?</li>
<li>Meaningful : 생성된 콘텐츠가 합리적인지?</li>
</ol>
<p><strong>1. Assistant Illustration</strong>
<img src="https://velog.velcdn.com/images/jiwon-km/post/2103e2aa-517c-4396-8661-a8ae1b47b65c/image.png" alt=""></p>
<ul>
<li>위의 auto-metric에서 좋은 성능을 보인 repeat보다, human-evaluation이 훨씬 좋은 스코어를 기록. </li>
<li>전반적으로, 인간 보다는 제안 모델의 성능이 좋지 않음을 알 수 있다.</li>
<li>🤔 그런데, 왜 proposed-repeat은 하지 않았을까? ... 사실 unimodal보다 성능이 좋았던 것은 repeat인데... </li>
</ul>
<p><strong>2. Assistant Writer</strong>
<img src="https://velog.velcdn.com/images/jiwon-km/post/8abc4de9-256c-405f-a7d5-2b773dec9fcd/image.png" alt=""></p>
<ul>
<li>Assistant Writer 모드에 대해서도 유저스터디를 진행했는데, 결과는 좋지 않았기 때문인지, 본문에는 없고 supplymentary에서만 확인할 수 있다.</li>
<li>결과적으로는, 인간과 GPT가 모두 제안 모델보다 훨씬! 성능이 좋았다.<ul>
<li>상대적으로 작은 데이터 세트에서 처음부터 모델로 언어 모델링을 학습하는 것이 어렵기 때문이며, 또 제안 모델의 경우 문법적으로 잘못된 텍스트를 생성하여서 선호도가 떨어졌다고 이유를 분석했다.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="discussion--remark">Discussion &amp; Remark</h3>
<ul>
<li>Model Limitations and Future Work</li>
<li>Inadequancies of Automatic Metric</li>
<li>Complexity of AESOP</li>
<li>Further possibilities w/ AESOP</li>
</ul>
<hr>
<h3 id="link">Link</h3>
<ul>
<li><a href="https://github.com/adobe-research/aesop">깃허브 링크</a></li>
<li><a href="https://openaccess.thecvf.com/content/ICCV2021/supplemental/Ravi_AESOP_Abstract_Encoding_ICCV_2021_supplemental.pdf">supplementary</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[A Character-Centric Neural Model for Automated Story Generation (AAAI, 2020)]]></title>
            <link>https://velog.io/@jiwon-km/A-Character-Centric-Neural-Model-for-Automated-Story-Generation</link>
            <guid>https://velog.io/@jiwon-km/A-Character-Centric-Neural-Model-for-Automated-Story-Generation</guid>
            <pubDate>Wed, 27 Jul 2022 04:01:03 GMT</pubDate>
            <description><![CDATA[<p>Liu, D., Li, J., Yu, M. H., Huang, Z., Liu, G., Zhao, D., &amp; Yan, R. (2020, April). A character-centric neural model for automated story generation. In Proceedings of the AAAI Conference on Artificial Intelligence (Vol. 34, No. 02, pp. 1725-1732).</p>
<h2 id="들어가기-전">들어가기 전</h2>
<blockquote>
<p>제목에서도 알 수 있다! 이 논문의 핵심은, 스토리 생성에 있어서 <strong>캐릭터</strong>를 고려하는 것이다.</p>
</blockquote>
<p>지금까지 읽었던 논문은, 기본적으로 프롬프트나 스토리라인등을 이용하여 스토리를 생성하는 그런 내용이었다. 이제부터 2주간 읽을 논문들은 거기에 어떠한 <strong>제약조건</strong>이 들어가게 된다고 한다. 내가 읽은 논문의 경우는 <strong>캐릭터</strong>가 바로 이 제약조건의 역할을 한다.</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/70b7b28e-be2d-4a6a-9bfc-0a9ce49b0b78/image.JPG" alt=""></p>
<p>정말 세상에는 이렇게나 다양한 개성을 가진 캐릭터들이 무수히 많이 존재하는데, 캐릭터들을 조건으로 하여 스토리를 만들면 스토리 개연성이나, 입체성에 있어서 훨씬 더 좋은 스토리를 만들 수 있을 것 같다는 생각이 들었다. 그러면 캐릭터의 설정을 어떻게 잘 임베딩해서, 어떤 식으로 생성 과정에 포함시킬 수 있는지 중점으로 읽어보려고 했다.</p>
<hr>
<h2 id="abstract">Abstract</h2>
<p>Story generation에 있어서의 맹점은, 일관된 캐릭터와 상관관계가 있는 연속적인 플롯으로 구성된 스토리를 만드는 것이며, 최근에는 variational autoencoder, generative adversarial network, convolutional sequence to sequence model 같은 다양한 최신 모델들을 기반으로 story generation이 이루어지고 있다.</p>
<p>그런데, 기존 모델은 설명가능성과 일관성(explainability and consistency)의 측면에서, 이야기 <strong>장르의 속성</strong>과 <strong>사전지식</strong>을 거의 고려하지 않았다. 따라서 저자들은 이러한 갭을 메우기 위해서, character-centric neural storytelling model을 제안한다. 즉, 캐릭터를 중심으로 이야기를 생성하겠다는 의미다. 
그렇다면 이걸 어떻게 가능하게 하냐? 생성될 스토리의 각 부분을 주어진 (1)캐릭터와 (2)컨텍스트에 의해 결정하도록 했다.</p>
<p>한 마디로 요약하자면, 기존 스토리텔링 연구의 문제점은 설명가능성과 일관성이 부족했다는 것이고, 이를 캐릭터 정보와, 플롯과 캐릭터간의 관계(즉, 컨텍스트)를 명시적으로 캡처하여 해결하겠다는 의미이다.</p>
<h2 id="introduction">Introduction</h2>
<p>저자들은 Story generation task가 🔥new hotspot🔥이라고 이야기한다. 그러면서, Story generation은 예전의 hand-craft 방식에서 최근의 NN기반 방식까지, 모델링적인 측면에서 크게 발전하고 있으나 아직까지 해결하지 못한 두 가지의 문제점을 꼽는다. 바로, <strong>설명가능성과 일관성(explainability and consistency)</strong>이다.</p>
<!--- 문제를 하나씩 보자면, 먼저 기본적으로 story generation은 블랙박스 문제이기 때문에 설명가능성이 부족하다는 문제가 있다. 
- 또한 long-range dependency와 아주 정교한 플롯을 만들지 못한다는 문제가 있으므로, 일관성이 부족하다는 문제 역시 존재한다.-->


<p>기존의 스토리 생성 방법은, 단순하게 long document를 생성하거나 혹은 long-range dependency를 해결해보고자 이 long document를 multi-stage로 분할하여 document를 생성하곤 했다. 
아주 보편적인 프레임워크는 먼저 neural language model을 사용해서 키워드, 스켈레톤, 프롬프트 같은 intermediate representations을 생성하고, 이에 대한 문장을 생성하는 또 다른 neural language model을 사용하게 된다. 우리가 여태껏 읽어왔던 논문들이 이러한 맥락이었다. 이러한 접근 방식으로 train dataset으로 부터 구문이나 어휘는 잘 포착할 수 있다. </p>
<ol>
<li><p>그러나🤔, 어떤 모델링 캐릭터나 플롯은 잘 학습할 수 없다. 이렇게 되면 생성되는 스토리 자체는 그럴 듯 하지만, 전혀 관련 없는 플롯과 캐릭터로 구성될 수 있는 위험이 있다. 왜 이런 스토리가 생성이 된거지? 왜 이 캐릭터가 이런 행동을 한거지?에 대한 해답을 찾기 어렵다는 의미같다.</p>
</li>
<li><p>또 다른 문제로는, 기존의 방식으로는 의미 수준의 일관성만을 보았다. 이 말인 즉슨, 주제의 일관성을 보거나, 문장 간의 일관성 만을 고려했다. 당연히 캐릭터 일관성 등은 고려하지 않았다.</p>
</li>
</ol>
<br/>

<hr>
<p>이러한 문제를 저자들은 스토리 장르의 관점에서 해결하고자 한다. 바로바로 <strong>캐릭터의 등장</strong>이다.
<img src="" alt=""></p>
<p align="center">
    <img src="https://velog.velcdn.com/images/jiwon-km/post/57148f93-283f-4975-b32c-66f83a4203af/image.png">    
</p>
<p align="center" size="x-small"> 스토리 생성에 캐릭터의 등장이라.. </p>
<br/>


<p>캐릭터의 신뢰도를 높이기 위해서는 캐릭터 모델링이 도움이 된다는 사전 연구가 있기 때문에, 저자들은 스토리 생성 네트워크를 캐릭터 모델링과 결합한다.</p>
<p>즉, 이야기에 어떤 일관된 캐릭터를 할당하게 된다. 그러면 스토리 생성 프로세스는 그러한 컨텍스트 환경에서 주어진 <strong>캐릭터의 일련의 행동</strong>을 선택하는 것으로 치환된다. 결과적으로 생성된 스토리는, 캐릭터와 컨텍스트를 명시적으로 연관시키기 때문에 전체 스토리의 설명성이 올라가게 된다. 추가로, 주어진 캐릭터는 스토리 생성 과정의 각 단계에서 <strong>액션 선택 작업</strong>을 안내하여 캐릭터의 일관성을 높인다.</p>
<details>
<summary>앗. 혹시 멘탈헬스팀이신가요?</summary>
<div markdown="1">

<p>추가적으로, 이러한 전략은 dialogue systems에서도 동일하게 성능(화자 일관성 향상)에 도움이 된다는 <a href="%5Bhttps://aclanthology.org/P16-1094/%5D">사전 연구 (Li et al. 2016)</a> 가 있었다 . 자세히 보지는 않았지만, 대화 시스템에 페르소나 개념이 들어간 연구 같은데 인용수도 상당히 많아서... 이미 아실 것 같지만, 그래도 대화 시스템 연구하시는 분들께 참고하시라고 링크를 남긴다 케케.</p>
</div>
</details>


<p><br/> <br/></p>
<hr>
<h2 id="이-논문에서는">이 논문에서는..</h2>
<p>따라서 앞서 내용을 종합하여서, 본 논문에서는 <strong>character-centric neural storytelling model</strong>을 제안한다. 
이 모델은 캐릭터 임베딩을 통해 캐릭터를 인코딩하여 이를 활용해 스토리를 생성의 가이드로 사용한다.</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/6f401ac9-3b97-4efe-9470-9a08d076abb1/image.png" alt=""></p>
<p>먼저 입력으로는, 타이틀과 캐릭터가 인풋으로 들어가게 된다. 모델에는 세 가지 구성요소가 포함되어있다. 바로 바로 character, situation, action이다. 정리해보면 다음과 같다.</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/b6731cf7-9854-468a-b083-69931a86cacf/image.png" alt=""></p>
<!--과정을 미리 보자면, 개별 캐릭터를 **(1) 성격 특성, (2) 캐릭터가 다른 상황에서 어떤 액션을 취하는지?** 에 대해서 표현하게 된다. 이 과정에서 캐릭터와 **컨텍스트**의 상호작용이 활발하게 이루어진다. -->

<hr>
<h2 id="method">Method</h2>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/666bb5e5-ec98-401b-83da-4b3dc23ea90e/image.png" alt=""></p>
<p>Overview를 보면 위와 같다. 그림을 보면 알 수 있듯 이 모델은 크게 두 단계로 구성되어있다.</p>
<ol>
<li><strong>Action Prediction</strong> : 각 단계에서 현재 상황(Context)에 대한 캐릭터의 반응(Predicted Action)을 결정한다.</li>
<li><strong>Sentence Generation</strong> : 캐릭터 임베딩 + 예측 동작 + 상황 정보를 통합하여 완전한 문장(Generated Sentence)을 생성한다.</li>
</ol>
<p>즉, 액션은 각 단계에서 주어진 캐릭터에 의해 결정되기 때문에, 이는 전반적으로 설명가능성과 일관성을 향상시킨다고 볼 수 있다. 저자들은 이러한 계층적인 generation framework을 통해 전 과정에서 fine-grained control을 가능하게 한다고 한다.</p>
<h3 id="1-problem-formulation-notation">1. Problem formulation, notation</h3>
<p>기본적으로 기존 storytelling models의 셋팅을 따랐다. sentence-by-sentence 방법으로 생성된다. (이전에 생성된 문장이 다음 문장을 위한 입력으로 들어간다.)</p>
<ul>
<li>INPUT. 타이틀은 $$T = {t_1, t_2, ... , t_m}$$, 캐릭터 임베딩은 $$C = {c_1, c_2, ... , c_p}$$은 학습 단계에서 학습되며, 다음 스토리를 생성하기 위한 입력으로 모델에 들어가게 된다.</li>
<li>OUTPUT. 스토리는 $$Y = {y_1, y_2, ... , y_n}$$으로 모델의 아웃풋이며, $$y_i = {w_{i,1}, w_{i,2}, ... , w_{i,l}}$$은 생성된 스토리의 n개의 문장 중에서 i번째 문장을 의미하며, $$wi,j$$는 i번째 문장의 j번째 단어를 의미한다.</li>
</ul>
<h3 id="2-character-embedding">2. Character Embedding</h3>
<p>각각의 캐릭터를 임베딩으로 표현하는 단계이다. </p>
<p>사전 연구 <a href="https://aclanthology.org/P13-1035.pdf">(Bamman, O’Connor, and Smith 2013)</a>와 <a href="https://worksheets.codalab.org/rest/bundles/0x953afe5537074b4b9cd3c57e08e2d865/contents/blob/StanfordDependenciesManual.pdf">(De Marneffe and Manning 2008)</a>에 기반해서, 각 캐릭터의 Related verbs(관련 동사)와, Attributes(속성)을 추출한다. Related verbs의 경우는 캐릭터가 에이전트인 경우 agent냐 patient에 따라 각각 agent verbs, patient verbs를 추출한다. Attributes의 경우, 형용사나 형용사 수식어이다.</p>
<p>이러한 word representation은, 평균값을 계산하여 single representation으로 표현되게 된다. 각 추출값의 평균을 계산했으므로, 이를 캐릭터 임베딩을 초기화하는 데 사용한다. $$N$$는 총 추출된 단어의 수를 의미한다.</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/43cb835f-f598-4c1b-b134-764dced04d3a/image.png" alt=""></p>
<p>캐릭터 임베딩은, 캐릭터의 행동 결정에 영향을 미치는 캐릭터의 속성을 인코딩한다고 볼 수 있다. 이 때 캐릭터의 속성이란 그 캐릭터의 성격, 직업, 감정, 성별, 나이 등을 의미한다. 캐릭터 임베딩 $$C$$는 이제 소개할 action predictor와 the sentence generator의 훈련 과정에서 모두 학습되게 된다.</p>
<!--앞선 1번 수식의 초기화 이후, 저자들이 제안하는 모델은 훈련을 통해 앞선 캐릭터의 속성 중 일부 속성에 대해 캐릭터를 클러스터링하게 된다. 또한, -->


<p>추가로, 여기서는 언급되지 않았지만 이 캐릭터 임베딩의 행동에 대한 ground truth가 있다. 그런데 자세한 설명은 없다.😥 Related verbs(관련 동사)가 gt가 아닐까 추측..</p>
<h3 id="3-action-predictor">3. Action Predictor</h3>
<p>저자들이 제안하는 모델의 중심은 캐릭터이다. 따라서 이 논문에서 이야기하는 이야기의 전반적인 전개는, 현재의 상황(컨텍스트)를 기반으로, 캐릭터가 수행하는 건전하고, 믿을 만한 (sound and believable) 행동을 예측하는 것이라고 치환할 수 있다.</p>
<p>따라서 새로운 임베딩, 컨텍스트 임베딩이 등장하게 된다. 컨텍스트 임베딩은 스토리 세계에서 캐릭터를 둘러 싼 현재 환경 정보와 상황을 나타낸다. 각 타입 스텝 t에서, 컨텍스트 임베딩 $$S_i$$는 현재 문장$$y_i$$과, 전 타임스텝의 컨텍스트 임베딩 $$S_{i-1}$$에 기반하여, bi-LSTM에 의해 계산된다.
<img src="https://velog.velcdn.com/images/jiwon-km/post/273d2c97-f74a-473b-b5f6-86c3cb57a675/image.png" alt="">
각각 -&gt;와 &lt;-는 포워드와 백워드 히든 벡터를 의미한다. </p>
<p>이렇게 컨텍스트 임베딩이 끝나면, 캐릭터는 다음 컨텍스트에서 어떤 행동을 하게 될지 결정하게 된다. 여기서 앞서 뽑았던 캐릭터 임베딩은 캐릭터가 이 상황에 대해 어떻게 행동할지에 대한 정보를 가져오게 된다. 
최종적으로 캐릭터가 수행하게 될 행동에 대한 확률은 캐릭터 임베딩과 컨텍스트 임베딩의 컨캣을 multilayer perceptron (MLP)에 통과시켜서 결정된다. 바로 아래 수식이다.</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/8113de6e-019d-4e73-a31b-98346080e94d/image.png" alt="">
최종 확률 값인 $$V_i$$가 바로 캐릭터가 다음 타임 스텝 i에서 어떠한 행동을 하게 될지를 나타내는 것이다. </p>
<p>학습 과정을 보자면, 시간 단계 i에 대하여 캐릭터 임베딩 C에 대한 ground truth $$V_i$$가 주어지기 때문에 negative log probability 를 최소화하는 방식으로 학습이 된다.</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/17b5ba76-6670-4d35-8366-87f2c2106f6d/image.png" alt=""></p>
<hr>
<p>학습이 끝나면, 이제 이 모델은 다음 액션을 예측할 수 있게 된다. 또한 이러한 예측은 모든 캐릭터에 있어 일반화가 가능하다. 즉, 캐릭터가 훈련에 사용된 스토리 코퍼스에서 어떠한 상황을 한 번도 경험하지 못하더라도, 어떤 행동을 할 것인지 추론할 수 있다. 당연히 코퍼스에서 모든 캐릭터의 행동을 커버할 수 없기 때문에 이런 일반화 능력은 아주아주 중요하다. 구체적으로는 어떻게 하냐고 물어보신다면 대답해드리는게 인지상정.</p>
<p>이 모델은 어떤 특정 상황에 대한 행동 선택을 기반으로 캐릭터 representations을 학습해서, 유사한 행동 스타일을 보이는 캐릭터들은 임베딩 상에서 가까운 영역에 위치하도록 한다. 이렇게 되면 모델의 <strong>일반화</strong> 성능이 또 향상되게 된다.</p>
<p>예를 들어보자면, 직업이 경찰이고, 임베딩 공간에 가깝게 위치한 캐릭터 i,j를 가정해보자. 훈련데이터에는 이러한 스토리가 있었다.</p>
<blockquote>
<p>경찰 i은 군중을 향해 총을 쏘는 남자가 있다는 무전을 받고 달려가서 그 남자를 체포했다.</p>
</blockquote>
<p>그렇다면, j는 동일한 상황을 경험하지 않았더라도 i와 유사한 캐릭터 임베딩으로 인하여 j도 범인을 체포한다는 행동을 할 가능성이 높아지게 된다! </p>
<p>정리하자면, 캐릭터 임베딩의 일반화 능력으로 인해서, 캐릭터가 익숙하지 않은, 새로운 상황에서 자신의 특성에 맞는 행동을 할 수 있도록 도와준다.</p>
<h3 id="4-sentence-generator">4. Sentence Generator</h3>
<p>전술했듯, 스토리는 sentence by sentence 방식으로 생성된다. 저자들은 이 스토리 생성 문제를, 수행할 행동 $$V_i$$, 캐릭터 임베딩 $$C$$, 컨텍스트 임베딩(현재 상황) $$S_i$$에 기반하여 문장을 생성하는 조건부 생성 문제로 포뮬레이션한다.</p>
<p>인코더와 디코더 모두 one-layer bi-LSTM networks를 사용한다. 먼저 field separator token &lt; EOS &gt; 와 &lt; EOT &gt; 사이에 $$S_i$$, title $$T$$, action $$V_i$$를 컨캣해서 넣고, 이를 bi-LSTM을 통해 저차원 벡터 $$h_s$$로 인코딩한다.</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/3d9088a4-b05c-4cab-b8e7-3a13b9771d13/image.png" alt=""></p>
<p>다음으로 디코더는 앞서 인코더의 출력인 $$h_s$$와 캐릭터 임베딩 $$C$$을 통해 sentence condition을 생성하게 된다. 디코더의 각 타임 스텝마다 hidden units을 얻게 되는데, 이는 이전 타임스텝의 hidden state $$h_{i-1}$$와, 현 타임스텝의 워드 임베딩 $$e_i$$, 캐릭터 임베딩 $$C$$를 통해 계산하게 된다. 
<img src="https://velog.velcdn.com/images/jiwon-km/post/3763c812-ef84-487b-be81-f1c40602fb88/image.png" alt=""></p>
<p>훈련 과정을 보게 되면, 타겟 문장 $$y_i$$을 예측할 때, seq2seq 모델은 훈련셋에 있는 문장의 negative log probability 를 최소화하도록 훈련된다.</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/91a37672-3003-48f3-9443-364cb8aec12d/image.png" alt=""></p>
<hr>
<p>이 문장 생성 단계에서 캐릭터 임베딩을 통합하는 것도 중요하다. 왜냐하면, 액션 외에도 하나의 완전한 문장을 형성하기 위해서는 수많은 정보(형용사, 부사, 목적어...)가 필요하기 때문이다. 
예를 들어서, 캐릭터 i가 농구선수이고, 예측된 액션은 play라고 하자. 캐릭터 임베딩을 고려하면, 우리 모델은 스팀게임이나, 비디오 같은 목적어 대신 농구를 목적어로 생성하게 된다.</p>
<p>또한, 캐릭터 임베딩은 논문에서 내내 강조하는 설명가능성과 일관성을 향상시킨다. 또 예를 들어 보자.</p>
<blockquote>
<p>캐릭터 i는 신생아이고, 이 아이는 불행하게도 위험에 직면했을 때 우는(cry) 것 밖에는 할 수 없다. </p>
</blockquote>
<p>Maximum Likelihood Estimation 기반의 기존 모델들은 스토리 코퍼스의 일반적인 패턴을 기억하는 경향이 있다. 즉, 스코리 코퍼스에서 위험한 상황에서 같이 자주 발생하는 &quot;run away&quot;같은 단어를 예측하게 된다. 그러나, 우리 모델은 캐릭터를 명시적으로 고려한다는 중요한 차이점이 있다. 따라서 모델은 캐릭터의 속성(나이, 성별, 성격...)과 일치하는 적절한 액션을 선택하도록 한다.</p>
<hr>
<h3 id="training-strategy">Training Strategy</h3>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/30727222-6754-4484-beff-74406a9bd6a9/image.png" alt="">
목적함수이다. 첫 번째 로스는 action predictor, 두 번째는 Sentence generator를 각각 표현한다. 앞에 하이퍼 파라미터로 중요도를 조절하게 된다. 논문 실험 셋팅에서는 각각 1과 0.8을 사용했다.</p>
<p>공식 implementation이 있다고 논문에 링크가 명시되어 있어서 들어가봤더니 이제 비공개다.. 속았다. 하지만 혹시 몰라 <a href="https://github.com/liudany/character-centric">링크</a>는 남겨둔다.</p>
<hr>
<h3 id="experiment">Experiment</h3>
<h4 id="dataset">Dataset</h4>
<p>Wikipedia에서 추출한 영화 줄거리 요약 코퍼스를 사용했다. 영화는 아니지만, 대 인기 만화 겸 애니메이션 JoJo&#39;s Bizarre Adventure의 위키피디아 Plot 항목에 가보면 이러한 설명이 있다.</p>
<blockquote>
<p>In late 19th-century England, Jonathan Joestar, the <strong>young son</strong> of a wealthy landowner, meets his new adopted brother <strong>Dio Brando</strong>, who loathes him and plans to usurp him as heir to the Joestar family. When Dio&#39;s attempts are thwarted, he transforms himself into a vampire using an ancient Stone Mask and destroys the Joestar estate. Jonathan <strong>embarks</strong> on a journey, meets new allies, and <strong>masters</strong> the Hamon (波紋, &quot;Ripple&quot;) martial arts technique to stop Dio, who has made world domination his new goal.</p>
</blockquote>
<p><strong>Dio</strong>같은 인물, <strong>young son</strong> 같은 연령과 성별 정보, <strong>embarks</strong>나 <strong>masters</strong>같은 action등의 인물에 대한 암시적인 설명과, 전체적인 스토리의 사건에 대한 간결한 요약이 포함되어있다. </p>
<p>저자들이 사용한 데이터셋으로 돌아와서, 데이터셋은 42,306개의 스토리를 포함한다. 스토리 길이의 중간값과 평균은 각각 176단어와 310단어이다. 각 문장에는 평균 16개의 단어가 있다. 토큰화를 위해 모든 문자를 소문자로 변환하여 사용했다. vocabulary 구성은, 50,000개로 설정했으며 포함되지 못한 2.06%의 단어는 &lt; unk &gt; 로 대체하였다. 스토리의 제목은 각 영화의 제목을 사용하였다.</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/50cc1594-5d31-4842-8d69-ec1bae6650d7/image.png" alt=""></p>
<p>데이터셋의 예시는 다음과같다. 전처리는 수행하기 전 raw 데이터같다. </p>
<p>코퍼스에서 구조와 implicit 정보를 뽑아내기 위해서 Stanford CoreNLP library를 사용했다. 문장 분할이나 pruning은 (Martin et al. 2018)의 연구를 참고하였다(세정님 첫 번째 발표). 전치사구는 제거하고, 접속사를 기준으로 문장을 분리했다. 코퍼스를 모델의 입력으로 사용하기 위해, related verbs attributes을 추출했다.</p>
<hr>
<h4 id="baseline">Baseline</h4>
<p>베이스라인으로는 non-character-based model을 사용했다.</p>
<ul>
<li><strong>Conditional Language Model(C-LM)</strong></li>
<li><strong>Seq2Seq with Attention(Vanilla-Seq2Seq)</strong></li>
<li><strong>Incremental Seq2Seq with Attention(Incre-Seq2Seq)</strong></li>
<li><strong>Plan-and-write</strong> (민지님이 지난 주 발표해주신 논문)</li>
<li><strong>Event Representation</strong> (세정님이 두 번째로 발표해주신 논문)</li>
<li><strong>Hierarchical Convolution Sequence Model (Hierarchi-cal)</strong> (이 논문은 강지원님께서 발표해주셨던 논문의 저자들의 바로 전 논문)</li>
</ul>
<h4 id="evaluation">Evaluation</h4>
<p>저자들이 사용한 메트릭은 다음과 같다.</p>
<ul>
<li><strong>BLEU</strong></li>
<li><strong>Perplexity</strong></li>
<li><strong>Human Evaluation</strong> : 세 가지 측면으로 평가하였다. (1) explainability, (2)character-believability, (3) fluency
<img src="https://velog.velcdn.com/images/jiwon-km/post/c6670b13-be35-441c-a3a7-16c000b42096/image.png" alt="">
5명의 평가자가 1부터 4까지 스코어링을 진행했다. 각 모델이 생성한 100개의 스토리를 랜덤으로 선정하여 실험을 진행했다. 마지막으로 평가 항목 3개의 평균을 계산하여 마지막 overall performance를 계산하였다.</li>
</ul>
<hr>
<h3 id="result">Result</h3>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/4a098ff4-8f95-4a75-be71-681d5b4af7d2/image.png" alt=""></p>
<p>전반적으로 다른 state-of-the-art story generation method보다, 제안하는 Character-centric의 성능이 좋다.</p>
<ul>
<li>먼저 <strong>C-LM</strong>를 보면, Perplexity가 상당히 높다. 이는 RNN 기반의 모델이 처리하기에 코퍼스 길이가 너무 길었기 때문이라고 분석했다.</li>
<li>바로 그 아래 <strong>seq2seq</strong> 모델과 비교해보면, Character-centric은 모든 seq2seq 모델보다도 성능이 좋다. 이는 캐릭터 임베딩과 액션 프레딕션의 효과라고 하는데, 아래 ablation study에서 자세히 볼 예정이다.</li>
<li>그 아래 <strong>Plan-and-write</strong> 같은 경우는, 키워드 시퀀스를 조건으로 하는 언어 모델을 사용해서 단어간 로컬 관계에 초점을 맞추는데, 키워드 보다 캐릭터에 초점을 맞추는 편이 모든 메트릭에서 더 좋았다.</li>
<li><strong>Event representation</strong> 모델은 이벤트 시퀀스를 생성하고 이벤트를 자연어 문장으로 변환하기 때문에 이벤트와 문장 간의 글로벌 정보를 더 잘 캡처할 수 있다.
Event representation 모델과 우리 모델은 성능에 아주 큰 차이는 없지만, 우리 모델은 캐릭터 관점에서 이야기를 생성하는 반면 Event 모델은 semantic intermediate representations에 중점을 둔다는 차이점이 있다.</li>
<li>마지막으로, <strong>Hierarchical</strong> 모델은 long-range dependencies를 캡처할 수 있는 모델 퓨전과, 셀프 어텐션을 사용한다. 결과를 보면, Hierarchical 모델이 BLEU-1, perplexity와 fluency에서 가장 성능이 좋다 ...!</li>
</ul>
<p>human evaluation의 경우, Character-centric 모델은 consistency and character believability 항목에서 최고 점수를 받았다.</p>
<hr>
<h3 id="ablation-study">Ablation Study</h3>
<h4 id="the-effect-of-character-embedding">The Effect of Character Embedding</h4>
<p>캐릭터 임베딩의 효과를 보기 위해 non-character model에 대한 실험을 수행했다.
<img src="https://velog.velcdn.com/images/jiwon-km/post/6baeda9a-dfcc-42c5-a414-9f7e0a240a28/image.png" alt=""></p>
<p><strong>Character embeddings improves character-consistency in generated stories.</strong>
캐릭터 중심 모델이, 비 캐릭터 모델보다 낮은 ppl score를 보인다. human evaluation에서는 제안한 모델은 character-belivebality 에서 성능이 더 좋다. 즉, 캐릭터 임베딩은 캐릭터 일관성을 향상시킬 수 있다.</p>
<p><strong>Character embeddings enhances the explainability of stories.</strong>
설명 가능성은 캐릭터 일관성과 상관관계가 있을 수 밖에 없다. 일관된 캐릭터는 이야기를 합리적으로 만들기 때문이다. 표를 보면 제안 모델의 explainability가 높다. 즉, character-guided stories는 더 좋은 설명 가능성을 갖는다!</p>
<p><strong>Characters are clustered along some of there traits in the embedding space.</strong>
전술했듯, 캐릭터 임베딩은 스토리 생성에서 행동을 예측하며 학습되기 때문에, 행동 스타일을 포착할 수 잇다. 그래서 훈련 후 캐릭터 임베딩을 찍어보면 앞서 나온 그림을 다시 보면 되는데...</p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/666bb5e5-ec98-401b-83da-4b3dc23ea90e/image.png" alt=""></p>
<p>유사한 캐릭터는 유사한 임베딩을 갖는다!. 하지만 이 예시가 전부고, 진짜로 훈련 이후 임베딩에 대한 피겨는 없다😅</p>
<h4 id="the-effect-of-action-prediction">The Effect of Action Prediction</h4>
<p>두 번째 ablation study~. 이 모델은 2 stage이므로 Action Prediction 모듈을 빼고 진행해서 이 AP 모듈의 성능을 확인해보았다. 성능 표를 보면 전반적으로 이 액션 예측 모듈이 성능에 기여하는 것을 확인할 수 있다.</p>
<p><strong>Action predictor reduces the difficulty of sentence generation.</strong>
AP 모듈의 유무에 따라 perplexity가 크게 변하는 것을 확인할 수 있다. 즉, 주어진 캐릭터의 향후 액션을 예측하는 것이 상당히 도움이 되는 유용한 정보이고, 문장 생성을 더 유창하고 정확하게 만든다는 것을 의미한다.</p>
<p><strong>Action predictor explicitly gives character guidance to story generation process.</strong>
explanibility을 보면 확인할 수 있다. 이러한 explicit action prediction을 통해서, 이 모델은 이야기 생성을 변화하는 컨텍스트에 대한 캐릭터의 생각과 반응으로 간주하여, 이야기에 합리적인 동기를 부여한다.</p>
<hr>
<h3 id="case-study">Case Study</h3>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/76b3f100-028b-4eaf-a322-7dc99740ea78/image.png" alt="">
➡️ (1) 폴리스맨 chan의 냉철 냉혹 리벤지 스토리, (2) 마이클이 힘든 일을 겪다가 결국 이혼하는 이야기.</p>
<p>읽어보면, 좀 급전개에 말이 안되는 부분이 있지만 적어도 캐릭터의 행동에 대한 부분은 자연스럽다. 타이틀과 전반적인 스토리도 잘 매칭이 된다. </p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/dd756e31-3187-4962-bf1b-05253078398d/image.png" alt=""></p>
<p>이 예시는 bad case이다. 제목은 너무 재밌어보이는데 안타깝다. 
읽어보면 내용을 제대로 파악할 수 없을 뿐더러, 이야기를 이끄는 <strong>주 캐릭터</strong>가 없다. Kota인지 Prabhakaran인지, 혹은 교사인지, 누가 주인공인지 알 수가 없다. 더 심각한 점은, 스토리가 진행될수록 에러가 누적되어서 더 스토리가 이상해진다. 이러한 문제를 해결하기 위해서 저자들은 multi-character action module을 도입할 수 있다고 이야기한다. 이러면 캐릭터간의 상호 액션을 컨트롤 할 수 있게 된다.</p>
<hr>
<h3 id="마무리하며">마무리하며</h3>
<p>지금까지 캐릭터에, 캐릭터에 의한, 캐릭터를 위한, Character-centric model에 대해 살펴보았다. 
모델은 크게 action prediction과 sentence generation 단계로 진행되며, 캐릭터 임베딩을 학습하며 컨텍스트와 캐릭터에 기반하여 스토리를 생성하게 된다. 이러한 모델은 이 당시 스토리 생성 SOTA 모델과 비교하여 경쟁력있는 성능을 보여주었다.</p>
<p>다만 코드를 볼 수 없으니 훈련 과정이나 데이터 형태들이 아주 명확하게 이해되지는 않는다 😭 ...</p>
<hr>
<blockquote>
<h3 id="reference">Reference</h3>
<p><a href="https://ojs.aaai.org/index.php/AAAI/article/download/5536/5392">https://ojs.aaai.org/index.php/AAAI/article/download/5536/5392</a>
<a href="https://en.wikipedia.org/wiki/JoJo%27s_Bizarre_Adventure">https://en.wikipedia.org/wiki/JoJo%27s_Bizarre_Adventure</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CV Study] WEEK04- Swin Transformer: Hierarchical Vision Transformer using Shifted Windows]]></title>
            <link>https://velog.io/@jiwon-km/CV-Study-WEEK04-Swin-Transformer-Hierarchical-Vision-Transformer-using-Shifted-Windows</link>
            <guid>https://velog.io/@jiwon-km/CV-Study-WEEK04-Swin-Transformer-Hierarchical-Vision-Transformer-using-Shifted-Windows</guid>
            <pubDate>Wed, 13 Jul 2022 06:01:00 GMT</pubDate>
            <description><![CDATA[<p>!youtube[2lZvuU_IIMA]
논문 설명을 잘 해주신 영상이 있어서, 이 영상을 주로 참고하여 정리해보았다. 목차 역시 영상의 순서를 따라가보려고 한다!</p>
<hr>
<h3 id="들어가기-전">들어가기 전</h3>
<p>2주차에 진행했던 ViT를 읽고, 그 후속연구에 대해서 공부하기로 했다. 참고로 ViT가 2020년 10월에 발표되었고, 그 이후 2021년 3월에 이 Swin Transformer 논문이 발표되었다. 지금까지도 Swin Transformer을 기반으로 논문이 아주 활발하게 발표되고 있다. 잠깐 찾아보니 medical image를 도메인으로 하는 swin-unet도 있고 그렇다.</p>
<hr>
<h3 id="1-purpose">1. Purpose</h3>
<h4 id="vit의-한계">ViT의 한계</h4>
<ol>
<li>한정된 태스크 문제 : ViT 모델은 오직 <strong>분류 문제</strong>를 해결하기 위해 설계되었다.</li>
<li>이미지 도메인의 문제 : 다음은 도메인에 대한 문제가 있다. ViT는 텍스트 도메인에서 사용되었던 트랜스포머 구조를 그대로 가져와서 사용한다. 거의 수정을 하지 않는 것을 목표로 했기 때문에, 이미지 도메인을 위한 특성이 담겼다고 보기 어렵다.</li>
<li>연산량 : 연산량의 문제도 있다. ViT에서는 텍스트 토큰 대신 이미지 패치가 들어가게 되는데, 패치마다 self-attention을 수행하므로, 이미지의 패치(토큰)수가 증가할 수록 연산량이 quadratic하게 증가한다. </li>
</ol>
<h4 id="purpose-of-swin-transformer">Purpose of Swin Transformer</h4>
<p>Swin Transformer는 당연히, 위에서 언급한 ViT의 한계를 극복하기 위해 설계되었다.</p>
<ul>
<li>분류 태스크에만 한정되지 않은, 다양한 목적의 backbone으로 사용될 수 있도록 하자!</li>
<li>Transformer 구조에 이미지 도메인만의 특성을 반영해보자!</li>
<li>더 적은 연산량으로 계산하자!</li>
</ul>
<hr>
<h3 id="2-notation">2. Notation</h3>
<ul>
<li>$$M$$ : Window size (patch 개수를 기준으로 count)</li>
<li>$$n$$ : Window 개수 </li>
<li>$$N$$ : 이미지의 patch 개수</li>
</ul>
<hr>
<h3 id="3-background">3. Background</h3>
<ul>
<li><a href="https://arxiv.org/abs/2010.11929">ViT</a>에 대한 사전 이해가 필요하다. 그러나 우리는 2주차에 보고 넘어갔으니 model overview만 남기고 생략..</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/14099498-ea0b-45ee-b433-2eb1e2a8e3b2/image.png" alt=""></p>
<hr>
<h3 id="4-solution">4. Solution</h3>
<ul>
<li>기존 ViT와는 다르게, <strong>이미지 도메인의 특성</strong>을 고려한다. 그렇다면 이미지의 특성은 어떤 것이 있는지 보면, 두 가지로 정리할 수 있다.<ul>
<li>high resolution of pixels (높은 해상도)</li>
<li>large variations in the scale of visual entities (물체의 다양한 크기) </li>
</ul>
</li>
</ul>
<h4 id="1-local-window">1. Local Window</h4>
<ul>
<li>따라서 저자들은, 모델에 <em>Local Window</em>를 적용하는 방법을 제안한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/0c893316-d403-4336-9cbc-e1876ba44a8f/image.png" alt=""></p>
<ul>
<li>거두절미하고 figure를 보면, ViT와 Swin Trainsformer의 차이점과, Swin Trainsformer에 적용된 윈도우가 어떤 것인지 직관적으로 이해할 수 있다. </li>
<li>또한, Swin Trainsformer의 서로 다른 윈도우 크기를 갖는 Hierarchical 구조 역시 한 눈에 파악할 수 있다.<ul>
<li>{low-level에 각각 4개의 패치로 구성된 윈도우 내에서 각각 어텐션 진행 -&gt; 다음 레이어로 넘어가서 패치를 합쳐서 새로운 윈도우 구성, 그 내에서 어텐션 진행 ...} 의 반복<ul>
<li>이것이 바로 Shifted WINdow! </li>
</ul>
</li>
<li>즉, 각 계층마다 다른 해상도의 결과값을 얻을 수 있다. (각 레이어마다 보는 윈도우의 크기가 다르니까!) </li>
<li>이러한 특성으로 인해, segmentation이나 detection 등 다양한 태스크에도 적용 가능한 backbone 형태의 모델이라고 할 수 있다고 한다.</li>
<li>이 때, 두 모델 모두 classification을 하게 되는데, 차이점은 [cls] token을 사용하는 ViT와는 달리, Swin의 경우 [cls] token을 사용하지 않고, 그 대신 token들의 mean을 사용한다.</li>
</ul>
</li>
</ul>
<h4 id="2-low-complexity">2. Low Complexity</h4>
<ul>
<li>Swin은 ViT보다 complexity도 적다.</li>
<li>ViT처럼 패치마다 self-attention을 하는 것이 아니라, 윈도우 내에서 self-attention을 수행하기 때문인듯?</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/b7b1ffee-8b30-4cab-a17f-5436c8c2a89c/image.png" alt=""></p>
<!--W-MSA : (Window Multi-head Self Attention)
논문의 수식을 보면, .. 추가설명 필요., Appendix에 있음.-->


<hr>
<h3 id="5-method">5. Method</h3>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/7df1b043-edba-4b59-96cc-a8cbfbf8ff31/image.png" alt=""></p>
<p>크게 두 가지의 구조, 네 가지의 스테이지로 구성되어있다.</p>
<h4 id="patch-merging">Patch Merging</h4>
<ul>
<li>각각 다음 스테이지로 넘어가는 과정에서, Patch Merging이 이루어진다. 각 스테이지가 진행됨에 따라 해상도를 줄여주는 역할을 수행.</li>
<li>주변 이웃 패치의 정보를 가져와서, 하나의 차원으로 축소해주는 과정. <ul>
<li>주변에 있는 2x2 사이즈로 이웃 패치 정보를 가져와서 하나의 차원으로 reduction하는 과정을 의미. </li>
<li>먼저, 하나의 패치가 C-dim이라면, 4C-dim으로 변환. 그 다음 linear production을 통해 2C-dim으로 reduction.</li>
</ul>
</li>
</ul>
<ul>
<li><p>이러한 reduction을 &quot;왜&quot; 수행하는지에 대한 구체적인 설명은 논문에 없음. </p>
<ul>
<li><p>참고한 동영상에 따르면, stage를 반복해나가면서 merging을 통해 reduction 없이 concat만 하게 되면, 차원이 엄청 커지기 때문에 이를 방지하기 위해 진행하지 않았나 추측함.</p>
</li>
<li><p>또, feature들의 결과를 서로 섞어주는 역할을 수행하게 된다.</p>
</li>
<li><p>Code :</p>
<pre><code class="language-python"> class PatchMerging(nn.Module):
  r&quot;&quot;&quot; Patch Merging Layer.
  Args:
      input_resolution (tuple[int]): Resolution of input feature.
      dim (int): Number of input channels.
      norm_layer (nn.Module, optional): Normalization layer.  Default: nn.LayerNorm
  &quot;&quot;&quot;

  def __init__(self, input_resolution, dim, norm_layer=nn.LayerNorm):
      super().__init__()
      self.input_resolution = input_resolution
      self.dim = dim
      self.reduction = nn.Linear(4 * dim, 2 * dim, bias=False)
      self.norm = norm_layer(4 * dim)

  def forward(self, x):
      &quot;&quot;&quot;
      x: B, H*W, C
      &quot;&quot;&quot;
      H, W = self.input_resolution
      B, L, C = x.shape
      assert L == H * W, &quot;input feature has wrong size&quot;
      assert H % 2 == 0 and W % 2 == 0, f&quot;x size ({H}*{W}) are not even.&quot;

      # 입력 이미지는 높이 H와 폭 W의 크기를 갖도록 reshape
      x = x.view(B, H, W, C) 

      # 입력의 벡터화, 네 부분으로 나누게 된다. H/2 W/2이므로, 각 벡터는 입력의 1/4.
      x0 = x[:, 0::2, 0::2, :]  # B H/2 W/2 C
      x1 = x[:, 1::2, 0::2, :]  # B H/2 W/2 C
      x2 = x[:, 0::2, 1::2, :]  # B H/2 W/2 C
      x3 = x[:, 1::2, 1::2, :]  # B H/2 W/2 C

      # 4개의 벡터 concat, 4개의 벡터이므로 채널은 4*C
      x = torch.cat([x0, x1, x2, x3], -1)  # B H/2 W/2 4*C
      x = x.view(B, -1, 4 * C)  # B H/2*W/2 4*C

      #  linear production을 통해 4C-dim -&gt; 2C-dim으로 reduction
      x = self.norm(x)
      x = self.reduction(x)

      return x

  def extra_repr(self) -&gt; str:
      return f&quot;input_resolution={self.input_resolution}, dim={self.dim}&quot;

  def flops(self):
      H, W = self.input_resolution
      flops = H * W * self.dim
      flops += (H // 2) * (W // 2) * 4 * self.dim * 2 * self.dim
      return flops</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<h4 id="swin-transformer-block">Swin Transformer Block</h4>
<ul>
<li>(b)에서 자세한 figure를 볼 수 있다. 왼쪽과 오른쪽은 연속적으로 이어진 구성이고, (a)의 각 스테이지 아래의 <em>X</em>는, (b)의 페어가 적용된 횟수를 의미함. </li>
<li>첫 번째 Swin Transformer Block에서의 MSA은, W-MSA(Window Multi-head Self Attention)라고 하며, 두 번째에서는 SW-MSA(Shifted Window Multi-head Self Attention)라고 함.</li>
<li>또 Efficient batch Computation, Relative Position Bias, Cyclic Shift and Attention Mask 등의 detail도 있는데 아래에서 추가로 설명할 예정.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/6d45be19-3ba8-4587-bba1-981ae12fe6fa/image.png" alt=""></p>
<ol>
<li><p>W-MSA(Window Multi-head Self Attention)</p>
<ul>
<li><p>Local Window 내부에서의 Self attention</p>
</li>
<li><p>이미지에 포함된 윈도우 내에서 각각, 독립적으로 별도로 self-attention을 진행하는 방법. </p>
</li>
<li><p>self-attention의 횟수는 local 윈도우의 개수.</p>
<p>이 때, 이미지 하나에 대해서만 attention을 적용하는 것이 아닌 윈도우 단위로 attention을 $$n$$번 적용해야 하기 때문에, 연산이 더 많아지게 된다. 이런 연산량을 해결하기 위하여 등장한 것이 <strong>Efficient batch Computation</strong>이다.</p>
</li>
<li><p><em>(1) Efficient batch Computation*</em> </p>
</li>
<li><p>$$n$$개의 윈도우를 배치와 같은 차원으로 합쳐서, 한 번에 병렬적으로 연산하는 방법이다.</p>
</li>
<li><p>반복해서 연산을 하는 것이 아닌, 병렬 처리를 통해 빠르게 계산!</p>
</li>
<li><p><em>(2) Relative Position Bias*</em>는</p>
</li>
<li><p>두 축마다, Relative Position의 범위가 $$[-M+1, M-1]$$ 로 이루어짐</p>
</li>
<li><p>Bias Matrix $$\hat{(B)}$$은 $$\mathbb{R}^{(2M-1)*(2M-1)}$$ 차원으로 구성이 되어있음.
<img src="https://velog.velcdn.com/images/jiwon-km/post/f09cee34-24a3-47f1-a276-69fcbb7dc2d6/image.png" alt=""></p>
</li>
<li><p>이 수식에서 $$B$$는 $$\hat{(B)}$$에서 값을 가져와서 사용하게 됨.</p>
</li>
<li><p>그렇다! ViT에서 NLP처럼 넣어주던 position embedding은 절대 좌표를 앞에 더해주는 식이었는데, 저자들은 그러한 pos embed보다 이 상대적인 position을 더해주는 것이 더 좋다고 이야기한다.</p>
<details>
<summary>더 자세히..</summary>
<div markdown="1">
</li>
<li><p>그래서 이게 무슨 의미인가? 영상에서 소개한 예시를 통해 이해해보자.
<img src="https://velog.velcdn.com/images/jiwon-km/post/330ba8a1-50c3-4796-bc9d-3657db059b3a/image.png" alt=""></p>
<ul>
<li>예시에서 윈도우 사이즈 $$n$$은 3. x축과 y축을 기준으로 서로 다른 기준을 두어 Relative position을 나타낼 수 있다고 함.</li>
<li>먼저, x축 기준으로 생각해보면 각 x축에 대해 서로 다른 색으로 표시가 됨. 먼저 1에 대해서 보면, 자기 자신과의 거리는 0. 1과 2에 대해서도 같은 축에 있기 때문에 거리가 0. 그런데 1과 4를 보게 되면 다음 축에 존재하기 때문에 거리가 -1, 1과 7은 거리가 -2.</li>
<li>y축을 기준으로 보면, 자기 자신과는 0. 그러나 1과 2를 보게 되면 다른 축에 있기 때문에 거리가 -1... 이런 식으로 거리마다 값(bias)를 확인할 수 있음.</li>
<li>이렇게 구성된 각각의 axis matrix에 대해, 각각 {$$M -1$$}을 더해주게 됨. 이는 즉, 음수가 포함된 범위를 인덱스로 사용하기 위해 0부터 시작되게 하기 위함.</li>
<li>그 다음은, x축의 모든 element에 대해, {$$2M-1$$} 값을 곱해주게 됨.</li>
<li>그 다음 axis matrix들을 더해주게 되면, 최종적으로 relative position index matrix를 얻게 됩니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/bcfa47d9-9e6a-4685-b824-80d1774c9a78/image.png" alt=""></p>
<ul>
<li><p>max value가 24인 이유는, $$\hat{(B)}$$의 차원이 $$\mathbb{R}^{(2M-1)<em>(2M-1)}$$ 였는데, $$2M-1 = 2</em>3-1 = 5$$ 이기 때문에 $$5*5 = 25$$ 이기 때문이다.</p>
</li>
<li><p>그 다음 $$\hat{(B)}$$으로 부터 $$B$$ 값을 얻고, 이를 Q@K를 스케일링 한 값에 더하여 소프트맥스 통과하고, V를 곱해주는 것이 수식4에 대한 설명이다.</p>
</li>
<li><p>결론적으로, 이 논문에서는 Relative Position Bias를 사용하여서, 보다 적은 파라미터로, 넓은 범위의 Relative Position을 학습할 수 있다고 이야기한다.</p>
</li>
</ul>
</div>
</details>
<br>
</li>
<li><p>어쨋든 Code:</p>
<pre><code class="language-python">class WindowAttention(nn.Module):
r&quot;&quot;&quot; Window based multi-head self attention (W-MSA) module with relative position bias.
It supports both of shifted and non-shifted window.
Args:
    dim (int): Number of input channels.
    window_size (tuple[int]): The height and width of the window.
    num_heads (int): Number of attention heads.
    qkv_bias (bool, optional):  If True, add a learnable bias to query, key, value. Default: True
    qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set
    attn_drop (float, optional): Dropout ratio of attention weight. Default: 0.0
    proj_drop (float, optional): Dropout ratio of output. Default: 0.0
&quot;&quot;&quot;

def __init__(self, dim, window_size, num_heads, qkv_bias=True, qk_scale=None, attn_drop=0., proj_drop=0.):

    super().__init__()
    self.dim = dim
    self.window_size = window_size  # Wh, Ww
    self.num_heads = num_heads
    head_dim = dim // num_heads
    self.scale = qk_scale or head_dim ** -0.5

    # define a parameter table of relative position bias
    self.relative_position_bias_table = nn.Parameter(
        torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), num_heads))  # 2*Wh-1 * 2*Ww-1, nH

    # get pair-wise relative position index for each token inside the window
    coords_h = torch.arange(self.window_size[0])
    coords_w = torch.arange(self.window_size[1])
    coords = torch.stack(torch.meshgrid([coords_h, coords_w]))  # 2, Wh, Ww
    coords_flatten = torch.flatten(coords, 1)  # 2, Wh*Ww
    relative_coords = coords_flatten[:,
    :, None] - coords_flatten[:, None, :]  # 2, Wh*Ww, Wh*Ww
    relative_coords = relative_coords.permute(1, 2, 0).contiguous()  # Wh*Ww, Wh*Ww, 2
    relative_coords[:, :, 0] += self.window_size[0] - 1  # shift to start from 0
    relative_coords[:, :, 1] += self.window_size[1] - 1
    relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1
    relative_position_index = relative_coords.sum(-1)  # Wh*Ww, Wh*Ww
    self.register_buffer(&quot;relative_position_index&quot;, relative_position_index)

    self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
    self.attn_drop = nn.Dropout(attn_drop)
    self.proj = nn.Linear(dim, dim)
    self.proj_drop = nn.Dropout(proj_drop)

    trunc_normal_(self.relative_position_bias_table, std=.02)
    self.softmax = nn.Softmax(dim=-1)

def forward(self, x, mask=None):
    &quot;&quot;&quot;
    Args:
        x: input features with shape of (num_windows*B, N, C)
        mask: (0/-inf) mask with shape of (num_windows, Wh*Ww, Wh*Ww) or None
    &quot;&quot;&quot;
    B_, N, C = x.shape
    qkv = self.qkv(x).reshape(B_, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
    q, k, v = qkv[0], qkv[1], qkv[2]  # make torchscript happy (cannot use tensor as tuple)

    q = q * self.scale
    attn = (q @ k.transpose(-2, -1))

    relative_position_bias = self.relative_position_bias_table[self.relative_position_index.view(-1)].view(
        self.window_size[0] * self.window_size[1], self.window_size[0] * self.window_size[1], -1)  # Wh*Ww,Wh*Ww,nH
    relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous()  # nH, Wh*Ww, Wh*Ww
    attn = attn + relative_position_bias.unsqueeze(0)

    if mask is not None:
        nW = mask.shape[0]
        attn = attn.view(B_ // nW, nW, self.num_heads, N, N) + mask.unsqueeze(1).unsqueeze(0)
        attn = attn.view(-1, self.num_heads, N, N)
        attn = self.softmax(attn)
    else:
        attn = self.softmax(attn)

    attn = self.attn_drop(attn)

    x = (attn @ v).transpose(1, 2).reshape(B_, N, C)
    x = self.proj(x)
    x = self.proj_drop(x)
    return x

def extra_repr(self) -&gt; str:
    return f&#39;dim={self.dim}, window_size={self.window_size}, num_heads={self.num_heads}&#39;

def flops(self, N):
    # calculate flops for 1 window with token length of N
    flops = 0
    # qkv = self.qkv(x)
    flops += N * self.dim * 3 * self.dim
    # attn = (q @ k.transpose(-2, -1))
    flops += self.num_heads * N * (self.dim // self.num_heads) * N
    #  x = (attn @ v)
    flops += self.num_heads * N * N * (self.dim // self.num_heads)
    # x = self.proj(x)
    flops += N * self.dim * self.dim
    return flops
</code></pre>
</li>
</ul>
</li>
<li><p>SW-MSA(Shifted Window Multi-head Self Attention)</p>
<ul>
<li>Goal : W-MSA 적용 이후, Local Window 간의 Self attention을 적용하자.</li>
<li>연결되어있지 않았던 부분에 대하여 윈도우가 적용되었음을 확인할 수 있음.</li>
<li>layer l+1 그림을 보면, window의 개수가 처음에 비하여 가로 세로 하나씩 더 증가한 것을 확인할 수 있다. 2*2개에서 3*3개로 늘어났다!</li>
<li>따라서, 윈도우의 개수가 증가하여 연산이 비효율적으로 이루어지게 된다.</li>
<li>이를 해결하기 위하여 제안한 방식이 <strong>Cyclic Shift and Attention Mask</strong>, 이를 통해 W-MSA와 동일한 윈도우 개수를 사용하게 된다.
<img src="https://velog.velcdn.com/images/jiwon-km/post/21348bdb-3805-4540-a571-66a3b81c9efa/image.png" alt=""></li>
<li>cyclic shift : window_size//2만큼 우측 하단으로 shift하고, ABC 구역에 mask를 씌워서 self-attention이 이루어지지 않도록 한다. (반대쪽 경계에 있는 애들과는 att. 계산 하지 않기 위해서!)</li>
<li>같은 색의 블록은 cyclic shift되고, mask를 적용하여 각각 self-attention이 진행되는데, 4개의 윈도우를 사용하여, local 윈도우 간 attnetion을 계산하게 된다.</li>
<li>최종적으로 마지막 결과를 reverse로 적용하여, 원래 이미지로 복원한다.</li>
<li>여기서의 attention mask는 수식 4의 bias를 더해준 값에 더해지게 된다. 따라서 m2*m2의 차원을 가져야 한다.
<img src="https://velog.velcdn.com/images/jiwon-km/post/f73071fc-f67d-4828-a120-e0bf24d905c4/image.png" alt=""></li>
<li>영상에서는 att. amsk를 찍어보았을 때 다음과 같이 나타나는 것을 확인할 수 있었다고 한다.</li>
<li><img src="https://velog.velcdn.com/images/jiwon-km/post/eb9ed235-7220-4aff-be31-aa2646c243f4/image.png" alt=""></li>
<li>이런 식으로 self-attention이 이루어지고 있다!...</li>
</ul>
</li>
</ol>
<pre><code class="language-python">class SwinTransformer(nn.Module):
    def __init__(self, img_size=224, patch_size=4, in_chans=3, num_classes=1000,
                 embed_dim=96, depths=[2, 2, 6, 2], num_heads=[3, 6, 12, 24],
                 window_size=7, mlp_ratio=4., qkv_bias=True, qk_scale=None,
                 drop_rate=0., attn_drop_rate=0., drop_path_rate=0.1,
                 norm_layer=nn.LayerNorm, ape=False, patch_norm=True,
                 use_checkpoint=False, fused_window_process=False, **kwargs):
        super().__init__()

        self.num_classes = num_classes
        self.num_layers = len(depths)
        self.embed_dim = embed_dim
        self.ape = ape
        self.patch_norm = patch_norm
        self.num_features = int(embed_dim * 2 ** (self.num_layers - 1))
        self.mlp_ratio = mlp_ratio

        # split image into non-overlapping patches
        self.patch_embed = PatchEmbed(
            img_size=img_size, patch_size=patch_size, in_chans=in_chans, embed_dim=embed_dim,
            norm_layer=norm_layer if self.patch_norm else None)
        num_patches = self.patch_embed.num_patches
        patches_resolution = self.patch_embed.patches_resolution
        self.patches_resolution = patches_resolution

        self.pos_drop = nn.Dropout(p=drop_rate)

        # stochastic depth
        dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))]  # stochastic depth decay rule

        # build layers
        self.layers = nn.ModuleList()
        for i_layer in range(self.num_layers):
            # BasicLayer = A basic Swin Transformer layer for one stage.
            layer = BasicLayer(dim=int(embed_dim * 2 ** i_layer),
                               input_resolution=(patches_resolution[0] // (2 ** i_layer),
                                                 patches_resolution[1] // (2 ** i_layer)),
                               depth=depths[i_layer],
                               num_heads=num_heads[i_layer],
                               window_size=window_size,
                               mlp_ratio=self.mlp_ratio,
                               qkv_bias=qkv_bias, qk_scale=qk_scale,
                               drop=drop_rate, attn_drop=attn_drop_rate,
                               drop_path=dpr[sum(depths[:i_layer]):sum(depths[:i_layer + 1])],
                               norm_layer=norm_layer,
                               downsample=PatchMerging if (i_layer &lt; self.num_layers - 1) else None,
                               use_checkpoint=use_checkpoint,
                               fused_window_process=fused_window_process)
            self.layers.append(layer)

        self.norm = norm_layer(self.num_features)
        self.avgpool = nn.AdaptiveAvgPool1d(1)
        self.head = nn.Linear(self.num_features, num_classes) if num_classes &gt; 0 else nn.Identity()

        self.apply(self._init_weights)

    def _init_weights(self, m):
        if isinstance(m, nn.Linear):
            trunc_normal_(m.weight, std=.02)
            if isinstance(m, nn.Linear) and m.bias is not None:
                nn.init.constant_(m.bias, 0)
        elif isinstance(m, nn.LayerNorm):
            nn.init.constant_(m.bias, 0)
            nn.init.constant_(m.weight, 1.0)

    @torch.jit.ignore
    def no_weight_decay(self):
        return {&#39;absolute_pos_embed&#39;}

    @torch.jit.ignore
    def no_weight_decay_keywords(self):
        return {&#39;relative_position_bias_table&#39;}

    def forward_features(self, x):
        x = self.patch_embed(x)
        x = self.pos_drop(x)

        for layer in self.layers:
            x = layer(x)

        x = self.norm(x)  # B L C
        x = self.avgpool(x.transpose(1, 2))  # B C 1
        x = torch.flatten(x, 1)
        return x

    def forward(self, x):
        x = self.forward_features(x)
        x = self.head(x)
        return x

    def flops(self):
        flops = 0
        flops += self.patch_embed.flops()
        for i, layer in enumerate(self.layers):
            flops += layer.flops()
        flops += self.num_features * self.patches_resolution[0] * self.patches_resolution[1] // (2 ** self.num_layers)
        flops += self.num_features * self.num_classes
        return flops</code></pre>
<hr>
<h3 id="7-experiments">7. Experiments</h3>
<p>Method 끝 ! 실험으로 가자 케케</p>
<h4 id="architecture-variants">Architecture Variants.</h4>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/9f2fb0ae-a8a0-418f-85f3-d0911b9ea0a5/image.png" alt=""></p>
<ul>
<li>supplement의 테이블을 가져왔다. 기본적으로 input은 [224*224*3] 를 사용하였고 윈도우 사이즈는 7이다. 뒤 실험에서 input이 [384*384*3]인 경우도 있는데, 이 때는 윈도우 사이즈를 12를 사용했다고 한다.</li>
</ul>
<h4 id="experiments-settings">Experiments settings.</h4>
<ul>
<li><strong>Image Classification</strong>에 ImageNet-1K, <strong>Object Detection</strong>에 COCO 2017, 마지막으로 <strong>Semantic Segmentation</strong>에 ADE20K을 사용. 모두 동일하게 pre-trained에는 ImageNet-22K를 사용했음.</li>
<li>추가로, 저자들은 다양한 augmentation과 regulazation이 필요하다고 함. ViT에서도 이야기했지만, inductive bias가 적기 때문에...!</li>
<li>ViT에서 중요했던 repeated aug.와 EMA는 더 이상 성능에 큰 영향을 주지 못함. </li>
<li>optimizer로는 다른 최근 연구에서 사용하는 AdamW를 채택.</li>
</ul>
<h4 id="그-외에도">그 외에도..</h4>
<ul>
<li>Relative Positional Bias 여부,</li>
<li>Shifted Window 여부,</li>
<li>Window 적용 방법에 따른 속도 비교,</li>
<li>Sliding Window와 Shifted Window에 따른 실험 등을 진행했다.</li>
</ul>
<ul>
<li>Baseline으로는 CNN계열과 ViT 계열(ViT, DeiT) 모두를 사용하였다.<ul>
<li>DeiT는 ViT보다 더 적은 데이터로, Knowledge distillation과 regulazation을 통해 성능을 향상시킨 모델.</li>
</ul>
</li>
</ul>
<hr>
<h4 id="classification">Classification</h4>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/458da445-8ffd-4e49-bfa3-feee96d3d816/image.png" alt=""></p>
<ol>
<li>ImageNet-1K<ul>
<li>성능은 비슷하나, 성능과 학습 속도의 trade-off가 더 작음.</li>
</ul>
</li>
<li>ImageNet-22K<ul>
<li>더 적은 파라미터로 좋은 성능.</li>
</ul>
</li>
</ol>
<ul>
<li>왜 그럴까? 발표자의 생각으로는, ViT는 Local Window 개념이 없어서 Inductive bias가 더 적다. 따라서 사전학습 데이터의 양이 중요함.</li>
</ul>
<h4 id="object-detection">Object Detection</h4>
<ol>
<li>Frameworks 기준</li>
<li>backbone 기준</li>
</ol>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/48f64c98-4b25-425f-ae47-10ead32da047/image.png" alt=""></p>
<h4 id="semantic-segmentation">Semantic Segmentation</h4>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/d3fbc97b-f862-45ac-9033-b087aa8c3a54/image.png" alt=""></p>
<ul>
<li>적은 파라미터로 좋은 성능.</li>
</ul>
<hr>
<h3 id="ablation-study">Ablation Study</h3>
<h4 id="shifted-window">Shifted Window</h4>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/02bb94ee-ecfd-428b-a318-0381c425490f/image.png" alt=""></p>
<ul>
<li>윈도우 간 관계를 학습하는 것이 Detection과 Segmentation 성능 향상에 도움이 된다.</li>
</ul>
<h4 id="relative-positional-bias">Relative Positional Bias</h4>
<ul>
<li>semantic seg.에 큰 도움이 된다.</li>
<li>dense prediction에 직접적인 기여를 하기 때문...!</li>
</ul>
<h4 id="window-적용-방법에-따른-속도-비교">Window 적용 방법에 따른 속도 비교</h4>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/818f0066-d83e-44a0-b1d7-060f6c156032/image.png" alt=""></p>
<ul>
<li>첫 행과 마지막 행 비교해보면 속도 차이가 엄청나다 ..</li>
</ul>
<h4 id="sliding-window와-shifted-window">Sliding Window와 Shifted Window</h4>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/0af34f15-b408-429b-9388-e3f35723c3ea/image.png" alt=""></p>
<ul>
<li>더 빠른 속도로 동일한 성능.</li>
</ul>
<hr>
<h3 id="7-conclusion">7. Conclusion</h3>
<h4 id="모델-구조">모델 구조</h4>
<ul>
<li>local window를 적용하여, inductive bias를 주입</li>
<li>patch merging을 통해, 계층 구조 형성</li>
</ul>
<h4 id="contribution">Contribution</h4>
<ul>
<li>이미지 특성 고려</li>
<li>다양한 vision task</li>
<li>더 적은 computation complexity</li>
</ul>
<hr>
<h3 id="code">Code</h3>
<p>MS에서 제공하는 <a href="https://github.com/microsoft/Swin-Transformer">official code</a>가 있다.</p>
<hr>
<h3 id="후기">후기</h3>
<ul>
<li>어떤 연구를 진행해볼수 있을까? </li>
</ul>
<blockquote>
<h3 id="reference-🔥">Reference 🔥</h3>
<p><a href="https://youtu.be/2lZvuU_IIMA">https://youtu.be/2lZvuU_IIMA</a>
<a href="https://github.com/microsoft/Swin-Transformer">https://github.com/microsoft/Swin-Transformer</a>
<a href="https://greeksharifa.github.io/computer%20vision/2021/12/14/Swin-Transformer/">https://greeksharifa.github.io/computer%20vision/2021/12/14/Swin-Transformer/</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Story Generation] Paper Review : A Corpus and Cloze Evaluation for Deeper Understanding of Commonsense Stories]]></title>
            <link>https://velog.io/@jiwon-km/Story-Generation-Paper-Review-A-Corpus-and-Cloze-Evaluation-for-Deeper-Understanding-of-Commonsense-Stories</link>
            <guid>https://velog.io/@jiwon-km/Story-Generation-Paper-Review-A-Corpus-and-Cloze-Evaluation-for-Deeper-Understanding-of-Commonsense-Stories</guid>
            <pubDate>Wed, 06 Jul 2022 04:00:07 GMT</pubDate>
            <description><![CDATA[<!--**'논문을 읽는다'. '제대로 설명도 한다'.** *'둘 다'* 해내야 하는 게 *'스터디'*의 힘든 점이지. 
각오는 되어있나? 나는 안되어있다.-->

<hr>
<p>2016년 NAACL에 발표된 <a href="https://arxiv.org/pdf/1604.01696.pdf">&quot;A Corpus and Cloze Evaluation for Deeper Understanding of Commonsense Stories&quot;</a> 를 정리한 글입니다. 현 시점을 기준으로 107회 인용된 논문입니다.</p>
<hr>
<h2 id="정리">정리</h2>
<ul>
<li>논문에서 등장하는 핵심 개념인 <strong>Commonsense</strong>와, 논문의 contribution인 <strong>Story Cloze Test</strong>와 <strong>ROCStories</strong>를 중심으로 읽자!<ul>
<li>이 논문은 우리가 하고자 하는 Story Generation을 직접적으로 다루지는 않지만, generation의 전제인 <strong>Story Understanding</strong>을 이야기하고 있기 때문에, 저자들이 이야기하는 네러티브에서 꼭 필요한 <strong>Commonsense</strong>와, 이를 잘 반영하고 있는 데이터셋은 어떻게 만들었고, 이를 평가할 수 있는 테스트는 어떻게 구성을 했는지에 집중하여 보면 좋을 듯 합니다.</li>
</ul>
</li>
</ul>
<h3 id="1-commonsense">1. Commonsense</h3>
<ul>
<li>commensense를 표현하고 학습하는 것은 deep-language understading에 있어서 기초적이면서도 중요하고, 또 어려운 문제!<ul>
<li>논문에서 이야기하는 commensense는, <strong>이벤트(events) 간의 인과관계 및 시간관계(causal and temporal relationships)</strong>을 의미한다고 보면 될 듯.</li>
</ul>
</li>
<li>이러한 commensense의 이해는 NLP 커뮤니티에서 많은 주목을 받았지만, <strong>적절한 evaluation framework의 부재</strong>로 인하여 연구가 많이 진행되지 않았음.</li>
<li>이러한 문제점에서 기인하여, 아래에서 소개할 논문의 두 가지 contributions이 등장하게 됨. <br/>

</li>
</ul>
<h3 id="2-rocstories">2. ROCStories</h3>
<ul>
<li>논문에서 제안하는 새로운 <strong>데이터셋</strong>!</li>
<li>daily events 사이의 인과적, 시간적인 상식적인 관계(commonsense relations)를 포함</li>
<li>story generation에도 사용할 수 있는 일상생활의 이야기<br/>

</li>
</ul>
<h3 id="3-story-cloze-test">3. Story Cloze Test</h3>
<ul>
<li>논문에서 제안하는 새로운 <strong>평가 방식</strong></li>
<li><strong>Story Cloze Test</strong> : story understanding과 script learning을 평가</li>
<li>네 문장의 스토리가 주어지면, 이어서 이야기의 올바른 결말을 선택하는지? 에 대한 평가</li>
<li>이를 위해 5 문장으로 구성된 50,000개의 상식적인 이야기 <strong>ROCStories</strong> 데이터셋을 제안 <br/>


</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/cb8bda91-ce31-4205-82de-448a33547f4b/image.png" alt=""></p>
<p>그러면 논문리딩! 해볼까요</p>
<hr>
<h2 id="introduction">Introduction</h2>
<h3 id="story-understading">Story Understading</h3>
<ul>
<li>Story를 이해한다는 것은 유구한 역사의, 어려운 태스크라고 할수 있습니다. 여기서 <strong>story</strong>라고 한다면, <strong>narrative를 갖는 텍스트</strong>를 의미합니다.</li>
<li>Story Understading 혹은 generation에서 가장 큰 챌린지는 <strong>narrative events의 해석에 대한 commonsense knowledge를 갖는 것</strong>입니다.<ul>
<li>그렇다면, 일상의 이벤트에 대한 commonsense knowledge를 model에 어떻게 부여할까? 하는 궁금증이 생기게 되죠.</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li>이러한 Story Understading의 학습 과정에서 가장 중요한 것은, 학습 프로세스를 주도하는 Corpus라고 할 수 있습니다.</li>
<li>기존에 이루어졌던 Story Understading은 <strong>Script learning</strong>에 많은 비중을 두었습니다.<ul>
<li>script : 정형화된 이벤트에 대한 구조화된 knowledge 표현.</li>
</ul>
</li>
<li>그러나, 스크립트를 매뉴얼하게 만드는 것은 time-consuming한 문제입니다.<!--따라서 자동적으로 생성되는 스크립트가 필요함.-->


</li>
</ul>
<!--- 기존 연구 : (1) unsupervised learning of 'narrative chains' (2) event schemas.-->

<ul>
<li>따라서 저자들은 가장 먼저, 이벤트 간 <em>시간적이고 인과적 관계</em>, 즉 commensence를 갖는 코퍼스에 집중했습니다. -&gt; commensence는 스토리의 coherence에 있어 중요한 요소이기 때문.</li>
</ul>
<ul>
<li>저자들은 이러한 코퍼스 구축을 위해 다양한 텍스트를 찾아보다가, 일상 블로그 포스팅이 commonsense causal information을 포함하고 있는 좋은 source라는 것을 발견했습니다.<ul>
<li>그러나 블로그 포스팅은 noisy 하다는 문제점 有 (= 즉, 유용한 정보를 찾기 힘들다는 것.) 아래는 블로그 포스팅의 예시인데, 약간 의식의 흐름 같기도 합니다. 저자들은 이러한 서술을 noisy하다고 표현함.<blockquote>
<p>“I had an interesting day in the studio today. It was so interesting that I took pictures along the way to describe it to you. Sometimes I like to read an autobiography/ biography to discover how someone got from there to here.....how they started, how they traveled in mind and spirit, what made them who they are now. Well, today, my work was a little like that.”
&lt;복잡한 snippets의 corpus example&gt;</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<ul>
<li>이처럼 복잡하고 noisy한 코퍼스에서 commonsense knowledge를 얻는 것은 challenging language understanding.</li>
<li><blockquote>
<p>따라서, 이러한 내러티브의 단순화된 버전(simplified version)이 필요함.</p>
</blockquote>
</li>
</ul>
<ul>
<li>저자들은 commonsense를 포함하고 있는 새로운 코퍼스를 제안<ul>
<li>이벤트 간 스테레오타입의 인과관계 및 시간 관계를 포함하고 있는 50k high quality five-sentence stories를 수집</li>
<li>careful prompt design &amp; multiple phases of quality control</li>
<li>application : (1) commonsense narrative schemas 학습 (2) story generation 모델 학습</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><p>또 다른 문제도 존재합니다. 바로 이러한 스크립트에 대한 evaluation framework가 부족하다는 것입니다.</p>
</li>
<li><p>기존 evaluation framework - <a href="https://nlp.stanford.edu/pubs/narrative-chains08.pdf">Narrative Cloze Test</a>는 일련의 이벤트가 주어지면, held-out 이벤트를 예측하는 시스템입니다.</p>
<ul>
<li><p>예를 들어, missing event를 포함하고 있는 case를 가정해봅시다.</p>
<p>{X threw, pulled X, told X, ???, X completed}</p>
</li>
<li><p>기존 연구는 이 특정 테스트에 최적화되어, commonsense를 학습하는 것이 아닌, 얕은 기술(shallow techniques)로 좋은 성능을 레포팅하는 것을 학습한다는 한계가 존재.</p>
</li>
</ul>
</li>
</ul>
<ul>
<li>그래서 저자들은 <strong>Story Cloze Test</strong>를 제안했습니다.</li>
<li>이 테스트는, 다음의 이벤트를 예측하는 것이 아니라, 주어진 스토리를 완결하기 위하여 마지막 문장을 선택하는 태스크를 해결하게 됩니다.</li>
</ul>
<ul>
<li>또, Story Cloze Test를 다루기 위해서 다양한 실험을 진행했습니다.</li>
<li>실험 결과는 랜덤 혹은 constant-choose의 성능을 뛰어넘기 위해서는, 스토리의 풍부한 semantic representation과 깊은 수준의 semantic space 모델링이 필요하다는 것을 의미합니다.</li>
</ul>
<!--이게 대체 뭔소리냐?-->

<!--

---
## Related Work

### [Unsupervised Learning of Narrative Event Chains](https://nlp.stanford.edu/pubs/narrative-chains08.pdf)
- narrative chains을 제안
    - narrative chains  : '주역(protagonist)'을 공유하는 narrative events의 부분 집합
    - narrative events : 이벤트(verb)의 튜플. 

---
이게 대체 뭔소리냐?-->

<hr>
<h2 id="a-corpus-of-short-commonsense-stories">A Corpus of Short Commonsense Stories</h2>
<h3 id="goal-of-new-corpus">Goal of New Corpus</h3>
<p>저자들이 제시하는 새로운 코퍼스의 목적은 아래와 같습니다.</p>
<blockquote>
<ol>
<li>The corpus contains a variety of commonsense causal and temporal relations between everyday events. This enables learning narrative structure across a range of events, as opposed to a single domain or genre.<ol start="2">
<li>The corpus is a high quality collection of non-fictional daily short life stories, which can be used for training rich coherent story-telling models</li>
</ol>
</li>
</ol>
</blockquote>
<p>정리하자면, </p>
<ol>
<li>코퍼스는 일상 이벤트 간의 인과와 시간적 관계의 <strong>commonsense</strong>를 포함해야 한다.
 -&gt; 하나의 도메인이나 장르에 국한되지 않고, 다양한 구조를 갖는 이벤트의 내러티브를 학습할 수 있음.</li>
<li>코퍼스는 <strong>일상</strong>의 high quality 스토리를 포함한다.
 -&gt; 풍부하고 일관된 스토리텔링 모델을 훈련할 때 사용될 수 있음.</li>
</ol>
<ul>
<li><p>Definition of narrative or story : anything which is told in the form of a causally (logically) linked set of events involving some shared characters.
= 어떤 공통된 인물이 포함된, 인과적으로(혹은 논리적으로) 연결된 일련의 이벤트 형태로 이야기되는 모든 것.</p>
</li>
<li><p>저자들은 드라마틱한 사건에 초점을 맞추는 것이 아니라, 일상에서 일어나는 인과적으로 의미가 있는 사건들에 주목하게 됩니다.</p>
</li>
</ul>
<hr>
<h3 id="data-collection-methodology">Data Collection Methodology</h3>
<ul>
<li>데이터셋 구축을 위해서 AMT(Amazon Mechanical Turk)를 통해 크라우드 소싱을 진행했습니다.<ul>
<li>크라우드 소서들에게 총 5개의 novel five-sentence stories를 작성하도록 함.</li>
<li>다양성 및 규모 확보<ul>
<li>이 때, 주제를 명시하는 것보다 크라우드 소서들이 생각하는 주제를 아무거나 택하여 스토리를 작성하도록 했을 때 더 좋은 결과를 얻음.</li>
</ul>
</li>
</ul>
</li>
</ul>
<br/>

<p>데이터셋의 instruction과 constraints에 대해서 이야기를 해보자면,</p>
<ul>
<li><p>데이터셋의 key property는 다음과 같습니다. :  the story should read like a coherent story, with a specific <strong>beginning and ending</strong>, where <strong>something happens</strong> in between.</p>
</li>
<li><p>또한, 스토리 생성 이후에 3명의 감독관들이 manual check를 통해, 일정 수준 이상의 (1) 일관성을 갖지 않거나, (2) 허구성을 띄거나, (3) 공격적인 스토리의 개수를 카운팅하게 됩니다.</p>
<ul>
<li>이러한 기준에 의거하여, 3명의 감독관이 모두 동의한 경우만 스토리를 채택하게 됩니다.</li>
</ul>
</li>
</ul>
<br/>

<p>구체적으로, 저자들이 crowd worker에게 제시한 instruction과 constraints는 아래와 같습니다.
<img src="https://velog.velcdn.com/images/jiwon-km/post/5d30d63d-837f-41ef-91b6-8afeedef5432/image.png" alt=""></p>
<ul>
<li>추가로, 한 문장은 70자 이내로 제한</li>
<li>이야기의 제목도 따로 작성하도록 함</li>
<li>또, 인용문, 속어, 비속어 사용 금지 !</li>
</ul>
<p>위의 instruction을 잘 준수한 문장은 아래와 같이 narrative chain을 형성하게 됩니다.</p>
<blockquote>
<p><strong>예시 문장)</strong> Bill thought he was a great basketball player. He challenged Sam to a friendly game. Sam agreed. Sam started to practice really hard. Eventually Sam beat Bill by 40 points.
*<em>narrative chain) *</em> X challenge Y ➯ Y agree play ➯ Y practice ➯ Y beat X</p>
</blockquote>
<ul>
<li><p>품질 검증을 위해서는 AMT의 qualification test를 이용했습니다.</p>
</li>
<li><p>데이터셋은 <a href="http://cs.rochester.edu/nlp/rocstories">여기서</a> 확인해볼 수 있습니다!</p>
</li>
</ul>
<hr>
<h3 id="statistics-of-new-corpus">Statistics of New Corpus</h3>
<p>다음은 수집한 데이터셋에 대한 통계 분석 파트입니다.</p>
<p><strong>1. Number of Tokens</strong></p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/e94890e1-8d53-477d-b1c9-c2384b6f0279/image.png" alt=""></p>
<ul>
<li>첫 문장은 캐릭터나 첫 설정을 소개하기 때문에 아무래도 짧은 경향이 있습니다.</li>
<li>마지막 문장일수록, 토큰의 길이가 커지는 경향성도 있습니다.<ul>
<li>근데 이 보라색은 뭘까?</li>
</ul>
</li>
</ul>
<p><strong>2. Crowdsourcing Effort</strong></p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/74dd4f91-cefd-4649-aa4b-0552e413a1d9/image.png" alt=""></p>
<ul>
<li>crowdsourcing woker에 대한 통계 자료 입니다.</li>
</ul>
<p><strong>3. Distribution of the most frequent 50 events</strong></p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/8f40428b-67bf-4ae0-9222-fbd934d864f2/image.png" alt=""></p>
<ul>
<li>event는 <a href="https://dl.acm.org/doi/pdf/10.1145/219717.219748">WordNet</a> 에서 정의한 것을 가져와서 사용함.</li>
<li>가장 많이 발생하는 이벤트인 <em>go</em> 와 <em>get</em>은 모두 전체 이벤트에서 1% 정도를 차지함 -&gt; 따라서, 제안하는 데이터셋에서 발생하는 이벤트의 <strong>다양성</strong>을 확인할 수 있습니다.</li>
</ul>
<p><strong>4. n-gram of story titles</strong></p>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/9497305e-882f-4117-8068-5a178b4cc8aa/image.png" alt=""></p>
<ul>
<li>radial path는 n-gram sequence를 의미.</li>
<li>토큰 개수의 평균은 9.8, 중간값은 10이며, n을 5로 설정했습니다.</li>
<li>데이터셋이 다양한 주제를 포함하고 있음을 확인할 수 있습니다.</li>
<li>풀 버전을 공개한다고 했는데, <a href="https://www.cs.rochester.edu/nlp/rocstories/viz/">알려준 사이트</a>에 들어가보니 볼 수 없었다 ..</li>
</ul>
<hr>
<h3 id="temporal-analysis">Temporal Analysis</h3>
<ul>
<li>저자들은 시간 분석을 강조하고 있습니다. 이벤트를 시간순으로 정렬한다는 것은, 즉 <strong>스토리에 대한 완벽한 서술적 이해의 전제</strong>이기 때문입니다.</li>
<li>저자들은 총 두 가지의 관점에서 이벤트의 시간순 정렬의 특성에 대하여 분석을 진행했습니다.</li>
</ul>
<h4 id="1-shuffling-experiment">1. Shuffling Experiment</h4>
<ul>
<li>Do the sentences follow the real-world temporal order of events? 라는 질문에서 시작하게 됩니다.</li>
<li>하나의 스토리에서 5개의 문장의 순서를 랜덤으로 섞고, 크라우드 소싱 참가자들에게 이를 시간순으로 배열하도록 했습니다.</li>
<li>데이터셋은 좋은 스토리를 포함하는 <em>Good-Stories_50</em> 과, 랜덤으로 선택된 <em>Random-Stories_50</em>, 두 가지 타입으로 구성됨.</li>
</ul>
<br/>

<ul>
<li><p>결과는 아래와 같습니다. 1행의 경우, 5명의 crowdsourcing woker의 과반수 합의를 최종 결과로 본 경우. 2행은 크라우드 워커 각각의 결정을 최종 결과로 본 경우 (5*50 = 200). 
<img src="https://velog.velcdn.com/images/jiwon-km/post/4af950a2-4603-42dd-bc72-15ff46fcf762/image.png" alt=""></p>
</li>
<li><p><em>Good-Stories_50</em> 의 경우, 높은 정확도로 시간순 정렬이 되는 것을 확인할 수 있음. </p>
</li>
<li><p>전체 스토리 데이터셋에는, 사람들이 순서를 추론하는 데 도움이 되는 &#39;first&#39;, &#39;then&#39;과 같은 부사들이 거의 없었기 때문에 저자들은 성공적인 정렬 원인을 추가로 분석해봤습니다.</p>
<ul>
<li><ol>
<li>상식적인 (commonsensical) 이벤트 사이의 시간 및 인과관계 (즉, 내러티브 스키마)</li>
</ol>
</li>
<li><ol start="2">
<li>자연스러운 이야기 전개 방식. (예를 들면, 소개에서 시작하여 이야기를 종결하는 방식)<ul>
<li>특히 이 이야기 전개 방식은, 첫 문장과 마지막 문장은 비교적 잘 정렬되는 것을 확인할 수 있는 표 4행의 결과로 뒷받침됨.</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<h4 id="2-timeml-annotation">2. TimeML Annotation</h4>
<ul>
<li>왜 했나요? TimeML 기반 분석은, 코퍼스에 포함된 이벤트의 시간적 측면에 대한 통찰력을 제공해주기 때문입니다.</li>
<li>TimeML은 뭔가요 ?  이벤트 및 시간 표현에 대한 마크업 언어.</li>
</ul>
<ul>
<li>저자들은 20개의 스토리 샘플을 추출하고, <a href="%EB%A7%81%ED%81%AC~">단순화된 TimeML</a> 기반 전문가 어노테이션 진행했습니다.</li>
<li>그 결과, 주석이 달린 모든 시간적 링크(TLINK)중 62%는 &#39;before&#39;이었고, 10%는 &#39;simultaneous&#39; 였음. </li>
<li>또한, 텍스트 순서가 실제 이벤트 순서를 반영하는지 확인하기 위해 문장 순서와 TimeML 순서를 비교해봄. 그 결과, 55%만 일치하였음.</li>
<li>즉, 이야기의 시간 및 인과관계에 대한 포괄적인 연구는, 이벤트 사이의 복잡한 commonsense를 잘 파악해야 한다는 것이겠죠..</li>
</ul>
 <!--즉, 이러한 이야기의 시간적 및 인과적 측면에 대한 보다 포괄적인 연구는, 상식적 사건 사이의 시간적 관계뿐 아니라 인과 관계를 포괄하는 특정 의미론적 주석 프레임워크를 정의해야 합니다.-->

<hr>
<h3 id="a-new-evaluation-framework">A New Evaluation Framework</h3>
<p>그래서, 저자들은 이 모델이 스토리의 commonsense를 잘 파악했는지를 판단할 수 있는 새로운 프레임워크를 제안하게 됩니다.</p>
<h4 id="background">Background</h4>
<ul>
<li>Cloze Test는 문장에서 임의의 단어를 제거하고 시스템이 공백을 채우도록 시도함으로써 언어 능력에 대한 시스템(또는 인간)을 평가하는 데 사용되는, 오래된 역사의 테스트입니다.</li>
</ul>
<ul>
<li>기존에도, Narrative Cloze Test라는 스크립트를 평가하기 위한 프레임워크가 존재했음<ul>
<li>앞서 이야기했지만, 어떤 이벤트 시퀀스가 주어졌을 때 누락된 이벤트에 대한 <strong>랭크</strong>를 생성하는 시스템</li>
<li>Goal : Narrative knowledge 평가</li>
<li>그러나, narrative knowledge learning이 잘 설명되지 않는다는 문제 발생<ul>
<li>예를 들면, 단순한 빈도 기반의 예측이 가장 높은 성능을 보임.</li>
</ul>
</li>
</ul>
</li>
<li>따라서, 스토리의 이해를 평가할 수 있는 더 좋은 방법이 필요함!</li>
</ul>
<h4 id="story-cloze-test">Story Cloze Test</h4>
<ul>
<li>저자들이 제안하는 새로운 test입니다.</li>
<li>4개의 문장으로 구성된 <em>context<em>가 제공되고, 그 다음 두 개의 엔딩이 제시됨 -앞선 context를 entailing하는 *right ending</em>와, contradicting하는 *wrong ending</em>.</li>
<li>따라서 앞선 네 문장의 <em>context</em>를 보고, 이어서 등장하게 될 right ending를 선택하는 task. 예시는 아래와 같습니다.
<img src="https://velog.velcdn.com/images/jiwon-km/post/4f5e9066-0c69-48db-acdd-1f6793f6ccd4/image.png" alt=""></li>
<li>저자들은 이러한 test가 story understanding이 정말 잘 이루어졌는지 평가하는 프레임워크라고 이야기하며, 우리가 관심있는 story generation 등에도 응용할 수 있다고 이야기함.<ul>
<li>예를 들면, 스토리 생성 모델이 생성한 두 개의 엔딩에 대한 log-likelihoods 계산을 통해 좋은 스토리를 생성할 수 있음.</li>
</ul>
</li>
</ul>
<h4 id="data-collection-methodology-1">Data Collection Methodology</h4>
<ul>
<li>위 테스트를 위해서는, 태스크에 적합한 데이터셋을 만들어 주는 작업이 선행되어야 합니다.</li>
<li>저자들은 앞서 구축한 ROCStories Corpus에서 랜덤으로 13,500개의 샘플을 추출하게 됩니다.</li>
<li>그 다음, AMT worker에게 앞선 4개의 문장만을 제시하고, 각각의 스토리마다 right ending과 wrong ending을 작성하도록 했습니다. </li>
</ul>
<h4 id="quality-control">Quality Control</h4>
<ul>
<li><p>저자들은 생성한 데이터셋에 대한 2-step Quality Control을 진행
  *<em>1. Qualification Test: *</em></p>
<pre><code>worker들은 ending writing 과정에서 두 개의 조건을 만족해야 했는데, **(1) 엔딩에는 적어도 앞서 등장한 인물 한 명 이상을 공유해야 함. (2) 엔딩 문장은 그 문장 자체만으로도 현실적이여야 하고, 합리적이야 함.** 모든 worker들은 이 두 가지 조건을 만족했는지 여부를 선택하도록 하는 qualification test를 진행했음.</code></pre><p>  <strong>2. Human Verification</strong></p>
<pre><code>**2-1.** 13,500샘플에 대한 2개의 엔딩을 만들었으므로, 13,500*2 = 27,000개의 full-five stories를 생성.
**2-2.** 하나의 문장마다, 3명의 crowd workers에게 다섯 개의 문장으로 구성된 스토리가 **의미있고 일관됐는지**에 대한 척도를 {-1,0,1}로 측정하도록 함. 
**2-3.** 3명의 workers들이 만장일치로 1과 0의 레이팅을 준 케이스만 선정함.</code></pre> <!-- 1은 뭘까?-->
<br/>
</li>
<li><p>최종적으로 3,742개의 테스트 케이스가 생성됨. 최종 테스트 케이스에 대한 통계는 아래에 있습니다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/91b093a3-ff4a-459f-a0cc-cb76e2fc71f3/image.png" alt=""></p>
<hr>
<h3 id="story-cloze-test-model">Story Cloze Test Model</h3>
<p>저자들이 제안한 Story Cloze Test는 네러티브에 대한 이해 없이, shallow한 접근 방식으로는 좋은 성능을 낼 수 없다고 합니다.
이를 뒷받침하기 위해, 섹션 5는 이러한 shallow 접근법에 대한 다양한 실험을 진행해보고, 결론적으로 결과가 좋지 않음을 이야기하는 내용입니다. 실험을 조금 많이 진행했습니다 ..</p>
<p><strong>1. Frequency</strong></p>
<ul>
<li><p>context를 고려하지 않은 baseline.</p>
</li>
<li><p>예를 들어 이러한 두 문장이 있다고 가정해보자.</p>
<blockquote>
<p>He was mad after he won. 
He was cheerful after he won.</p>
</blockquote>
<ul>
<li>앞의 문장은 실제로 발생할 가능성이 적은 문장임.</li>
</ul>
</li>
<li><p>Frequency baseline은 문장에서 semantic roles과 함께 메인 이벤트인 동사의 <strong>구글의 검색 엔진 조회수가 더 높은 케이스</strong>를 선택하게 됩니다.</p>
</li>
<li><p>semantic roles은 ‘I*poison(독을 주입?)*flowers’ vs ‘I*nourish(키우다)*flowers’ 이런 것을 의미한다고 합니다.</p>
</li>
<li><p>TRIPS semantic parser 사용.</p>
</li>
</ul>
<p><strong>2. N-gram Overlap</strong></p>
<ul>
<li>간단하게, context와 더 많은 n-gram을 공유하는 엔딩을 선택. </li>
<li>여기서는 4-gram overlap을 계산하는 Smoothed-BLEU Score를 사용.</li>
</ul>
<p><strong>3. GenSim: Average Word2Vec</strong></p>
<ul>
<li>Context의 word2vec 임베딩과 각 엔딩의 임베딩을 계산하여, 임베딩이 더 가까운 문장을 선택.</li>
<li>이 베이스라인은 semantic similarity을 고려하기 때문에, 위의 n-gram overlap보다 조금 더 좋은 베이스라인임.</li>
</ul>
<p><strong>4. Sentiment-Full</strong></p>
<ul>
<li>Context의 average sentiment와 일치하는 엔딩을 선택하였음.</li>
<li>이 당시 SOTA였던 Manning의 모델을 사용함. (감정을 1~5의 digit으로 표현)</li>
</ul>
<p><strong>5. Sentiment-Last</strong></p>
<ul>
<li>위와 동일하게 sentiment digit을 사용했지만, context 전체가 아니라 <em>Last</em> context의 average sentiment와 일치하는 엔딩을 선택하였음.</li>
</ul>
<p><strong>6. Skip-thoughts Model</strong></p>
<ul>
<li>3번과 비슷한데, 임베딩 방식이 달라짐. 임베딩으로는 Skip-thougts&#39; Sentence2Vec 임베딩(Kiros et al.,2015)을 사용했음.<ul>
<li>Skip-thougts&#39; Sentence2Vec : 11,000권 이상의 book corpus로 학슴됨. </li>
</ul>
</li>
</ul>
<p><strong>7. Narrative Chains-AP</strong></p>
<ul>
<li>Chambers and Jurafsky(2008)의 사전 연구를 기반으로 하는, 일련의 내러티브 이벤트 학습에 대한 표준 접근 방식.</li>
<li>이 모델에서 이벤트는 a verb and a typed dependency로 표현됨. coreferring entity를 기준으로 최소 2번이상 발생하는 이벤트 페어에 대한 PMI 계산. PMI 점수를 기준으로 높은 엔딩을 결과로 선택하게 됨.</li>
<li>이벤트 페어는 Associate Press (AP) portion of the English Gigaword Corpus를 기준으로 학습됨.<blockquote>
<p>Pointwise mutual information (PMI) : a real-number score produced by a pointwise mutual information measure (that ranks the statistical dependence between two random variables). 값이 0이면 상호 영향을 미치지 않는, 독립 관계 </p>
</blockquote>
</li>
</ul>
<p><strong>8. Narrative Chains-Stories</strong></p>
<ul>
<li>위와 동일하지만, ROCStories에서 학습됨.</li>
</ul>
<p><strong>9. Deep Structured Semantic Model</strong></p>
<ul>
<li>Huang et al., (2013)의 연구에서 제안된 모델을 사용.</li>
<li>두 개의 임베딩을 사용 : 1) context로만 구성 2) context와 다섯 번째 문장으로 구성.</li>
<li>따라서, 각각의 임베딩을 학습하기 위한 두 개의 개별 뉴럴 네트워크를 구성.</li>
<li>각각 두개의 레이어로 구성, 히든 레이어의 차원은 1000, 임베딩 벡터 차원은 300.</li>
<li>코사인 유사도를 기준으로, 가장 가까운 엔딩을 선택!</li>
</ul>
<p>이 외에도 추가적으로 그냥 랜덤으로 선택하는 경우와, 사람이 평가한 결과를 추가하여 총 11번의 실험을 진행했다.</p>
<h4 id="결과">결과!</h4>
<p><img src="https://velog.velcdn.com/images/jiwon-km/post/50b58bb8-2262-49d6-b3b5-5b46cf27aa59/image.png" alt=""></p>
<ul>
<li><p>NN을 사용한 DSMM의 Test 성능이 가장 좋다. 그러나 랜덤으로 선택한 경우보다 겨우 7.2%만 높은 것을 확인할 수 있음.</p>
</li>
<li><p>이러한 결과는, 이벤트 기반의 언어 모델들은 이러한 태스크에 충분하지 않음을 의미.</p>
</li>
<li><p>예를 들면, 종종 스토리의 마지막 엔딩은 ‘Bill was highly unprepared’ or ‘He had to go to a homeless shelter’ 등이 있을 수 있음.</p>
<ul>
<li>그런데 이런 경우, 이벤트 기반 언어 모델은, &#39;was-object&#39;나, &#39;go-to&#39;와 같은 동사나 구문 관계만 봄.</li>
<li>즉, <em>going to a homeless shelter</em>와, <em>same as going to the beach</em>는 같은 경우로 판단됨.</li>
</ul>
</li>
<li><p>결론적으로, 이는 내러티브에서는 <strong>이벤트에 대한 더 풍부한 의미론적 표현의 해석</strong>이 필요함을 시사함. 따라서 저자들은 많은 연구자들이 이 테스트에 참여해보는 것을 권장하며 이 섹션을 마무리하고 있다.. </p>
</li>
</ul>
<hr>
<h3 id="그렇다면-실제로-story-cloze-test는-진행되고-있나요">그렇다면 실제로 Story Cloze Test는 진행되고 있나요?</h3>
<p>네! 진행되고 있습니다! 
최근까지도 활발하게 많은 연구 팀들이 evaluation에 참가하고 있고, 결과는 여기 <a href="https://competitions.codalab.org/competitions/15333">리더보드</a>에서 확인해볼 수 있다.
<img src="https://velog.velcdn.com/images/jiwon-km/post/b8d572dd-10e6-45f5-ac43-0862a01680c7/image.png" alt="">
The End is Never임을 알 수 있다 ...
<img src="https://velog.velcdn.com/images/jiwon-km/post/ade20e24-cf78-4207-968e-f1d103f7fe46/image.png" alt="">
실제로 테스트에 참가하고 있는 팀들의 결과도 확인할 수 있으며, 회색 바를 통해 지금까지도 꾸준히 submissions이 이루어지고 있는 것을 확인할 수 있다. 
심지어! 2022년 6월에는 타이기록이 달성되었음을 확인할 수도 있다. 우리도 로그인 후 competition에 참여할 수도 있지만, 자세히 보지는 않았다. 관심 있는 분들은 자세하게 살펴보시길..</p>
<hr>
<h3 id="후기">후기</h3>
<ul>
<li>돈이 꽤나 많이 들었겠다 .</li>
<li>2016년 논문인데, Competition이나 test set도 비교적 유지관리가 잘 되고 있는 듯 하다.</li>
<li>ROC 어쩌고 데이터셋 만들 때 일상의 데이터셋이 목적이라고 했는데.. 실제 데이터셋 만들 때 그런 제약조건이 있었나? 누가 막 중세시대 이야기 하고 이런거는 필터링됐을까 ..??..</li>
<li>2저자가 미국 해군사관학교 소속이다. 어라 탑..건..?</li>
</ul>
<hr>
<h4 id="reference">Reference</h4>
<blockquote>
<p>Paper : <a href="https://arxiv.org/pdf/1604.01696.pdf">https://arxiv.org/pdf/1604.01696.pdf</a>
<a href="https://competitions.codalab.org/competitions/15333">https://competitions.codalab.org/competitions/15333</a></p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>