<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>so_oni_on.log</title>
        <link>https://velog.io/</link>
        <description>베풀기 위해 더 많이 공부하고 성장하기 ᓚᘏᗢ: 공부 정리용</description>
        <lastBuildDate>Wed, 15 Apr 2026 12:03:43 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>so_oni_on.log</title>
            <url>https://velog.velcdn.com/images/so_oni_on/profile/330621a2-90e9-40c5-9254-e14091bfadf3/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. so_oni_on.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/so_oni_on" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[논문 리뷰] Graph-constrained Reasoning: Faithful Reasoning on Knowledge Graphs with
Large Language Models]]></title>
            <link>https://velog.io/@so_oni_on/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Graph-constrained-Reasoning-Faithful-Reasoning-on-Knowledge-Graphs-withLarge-Language-Models</link>
            <guid>https://velog.io/@so_oni_on/%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0-Graph-constrained-Reasoning-Faithful-Reasoning-on-Knowledge-Graphs-withLarge-Language-Models</guid>
            <pubDate>Wed, 15 Apr 2026 12:03:43 GMT</pubDate>
            <description><![CDATA[<p>미완성본</p>
<p>본 논문은 ICML 2025 포스터 발표로 소개된 논문으로, 대형 언어모델과 지식 그래프를 결합하여 추론의 신뢰성을 높인 연구를 다룬다.</p>
<h2 id="1-background">1. Background</h2>
<p>LLM은 뛰어난 추론 능력을 가지고 있다. 하지만 모델의 활용도가 높아질수록 환각(Hallucination) 현상에 대한 경각심 또한 커지고 있다. 이때 언어 모델의 환각이란, 사실과 다르거나 논리적이지 않은 잘못된 추론을 하는 현상을 말한다.</p>
<p>이를 해결하기 위해 최근들어 KG (Knoledge Graph, 지식 그래프)의 활용과 관련 연구들이 활발히 진행되고 있다. 하지만 방대한 지식 그래프에서 정확한 정보를 검색해오거나 효율적으로 탐색하는 데에는 여전히 한계가 있다.</p>
<h2 id="2-preliminary">2. Preliminary</h2>
<p>따라서 본 저자들은 이를 해결하기 위해 &#39;Graph-Constrained Reasoning, GCR)&#39;이라는 그래프 제약 추론 프레임워크를 제안한다.
이를 좀 더 자세히 알기 위해서는 기존의 KG 기반 LLM 추론 방식에 대해 짚고 넘어가고자 한다.</p>
<h3 id="a-related-work">a. Related Work</h3>
<ul>
<li><strong>Retrieval-based (e.g., RoG--Linhao Luo et al, 2024)</strong>: 외부 Retriever로 KG에서 관련 사실을 검색해서 LLM 입력에 넣는 방식. 
하지만 Retriever이 부정확하거나 그래프 구조를 반영하지 못하며, KG 밖의 경로를 생성할 수 있다는 취약점이 있다. </li>
<li><strong>Agent-based (e.g., ToG--Jiashou Sun et al, 2023)</strong>: LLM을 에이전트처럼 활용해 KG를 반복적으로 탐색해 추론 경로를 찾는 방식.
하지만 LLM이 KG와 여러 번 상호작용해야 돼, 비용과 지연 문제에 취약하다. </li>
</ul>
<p>하지만 대표적인 KG 기반 추론 방식인 RoG조차 KG를 기반으로 추론할 때 33%의 환각 반응이 관찰된다고 한다. 그 중 18%는 형식 오류(Format Error), 15%는 KG에 존재하지 않는 관계를 지어내는 <strong>관계 오류(Relation Error)</strong>로 나타났다.
$\to$ 이 점이 본 논문의 직접적인 동기이다. <img src="https://velog.velcdn.com/images/so_oni_on/post/7a668094-0d39-436a-ad67-644e2f710259/image.png" alt=""></p>
<p>위의 방식들을 적용해 KG를 활용한 질의 응답 추론 해결 문제가 활발히 진행됨.</p>
<p>따라서 KG-constrained Zero-hallucination를 도입하고자 한다. 이는 지식 그래프 제약 기반으로 하여 환각을 줄이는 방식이다. 지식 그래프 안의 사실들은 대개 검증되었단 점을 활용해(Nguyen et al., 2024), LLM 추론의 신뢰성을 평가하는 믿을 수 있는 출처가 된다. 따라서 LLM이 생성한 추론 경로가 지식 그래프 내에 fully grounded 해야되며, 이를 통해 추론 과정이 실제 사실과 정확히 일치하도록 보장하는 방식을 본 논문에서 적용하려는 것이다. </p>
<h3 id="b-cot">b. CoT</h3>
<p>CoT는 Chain-of-thought의 약어로, &quot;답을 바로 내는 것이 아닌, 추론 과정 z를 먼저 생성하라.&quot;는 것이다. 
수식으로 나타냈을 때는 아래와 같다.
<img src="https://velog.velcdn.com/images/so_oni_on/post/47a62d33-7c00-4bae-bde8-3f1d6586d89a/image.png" alt=""></p>
<ul>
<li>$\theta$: LLM 파라미터</li>
<li>$z$: 추론 과정</li>
<li>$z_i$: i번째 추론 단계 (토큰)</li>
<li>$q$: 입력 질문</li>
<li>$a$: 최종 답안</li>
</ul>
<p>상세하게 보기 위해서 예시를 들겠다. 우선 KG의 트리플렛이 아래와 같이 정의가 된다.
<img src="https://velog.velcdn.com/images/so_oni_on/post/c348f971-4c5b-4caa-978e-5984a0308432/image.png" alt="">
가령
<img src="https://velog.velcdn.com/images/so_oni_on/post/ad57a2a9-328e-42da-ab48-30b0cfec6cd5/image.png" alt="">
<img src="https://velog.velcdn.com/images/so_oni_on/post/4b0df688-b215-4cb5-a832-3bb53af73a44/image.png" alt=""> 이런 관계가 있다고 하면, &quot;Alice는 Bob이랑 결혼을 하는데, Bob은 Charlie의 아버지이다.&quot; 그럼 &quot;Alice는 Charlie의 어머니이기도 하다.&quot;라는 추론 또한 가능해진다.
이러한 과정이 Chain of Though, CoT이다. 
위의 식과 연결해서 생각해보면, &quot;Alice의 아들은?&quot;이라는 쿼리가 주어졌을 때, $z_1$생성($P_\theta(z_1|q)$) 할 때는 &#39;Alice는 Bob과 결혼&#39;이라는 노드와 관계를 통해 할 수 있다. 이후 $z_2$ 생성($P_\theta(z_2|q, z_1)$), &quot;Bob은 Charlie의 아버지&quot;를 참조한....</p>
<p>그러면 결론적으로 $z$는 토큰 단위 auto-regressive한 생성을 하게 되고 위의 식이 성립한다. </p>
<hr>
<h2 id="3-methodology">3. Methodology</h2>
<p>효율성에도 불구하고 LLM의 추론 능력을 높이기 위해 &#39;생각의 사슬(Chain-of-Thought, CoT)&#39;을 많이 쓰지만, 이는 단어를 한 단계씩 예측하며(Autoregressively) 문장을 잇는 방식이라 오류가 누적되면 결국 &#39;환각(Hallucination)&#39;으로 이어진다. 
따라서 이 &quot;KG를 참조하되 디코딩 과정에서 문제가 발생하는 이 문제점&quot;을 신뢰성있는 추론이 가능하도록 하기 위해 본 저자들은 KG-enhanced Reasoning 기법을 활용한 방법론을 제안하였다. KG-enhanced Reasoning란 말 그대로 KG의 지식 구조를 사용하되, LLM의 추론 성능을 향상시키는 방법이다. 
이는 아래와 같이 정의될 수 있으며, 일반적으로 KG의 추론 경로 $w_z$를 찾는 과정이다. 
<img src="https://velog.velcdn.com/images/so_oni_on/post/69d7861e-6c5c-43a5-8ecb-928bb46fb093/image.png" alt="">
이를 위해서 앞서 Preliminary에서 소개한 &#39;Retrieval-based&#39;와 &#39;Agent-based&#39; 패러다임이 사용되었지만 각각 한계점이 존재했다.</p>
<ul>
<li>Retrieval-based Paradigm: RAG처럼 외부 검색기를 사용하여 경로를 찾아오지만 검색기의 성능에 의존하는 단점이 있다. 따라서 검색기가 엉뚱한 추론 경로를 가져오면 LLM 또한 엉뚱한 응답만 생성한다.</li>
<li>Agent-based Paradigm: LLM에게 지식 그래프 내부를 탐색하도록 시키는 방법이나, 모델이 매 턴마다 생각하고 움직여야하므로 computing resource가 많이 들고, 결정적으로 너무 느리다는 단점이 있다.</li>
</ul>
<p>따라서 검색 기반(Retrieval)이나 에이전트(Agent) 기반 방식의 한계점을 극복하고자, 이 논문은 아예 LLM이 텍스트를 생성하는 디코딩 과정 자체에 지식 그래프(KG)를 직접 밀어 넣는 <strong>그래프 제약 추론(GCR)</strong>이라는 새로운 패러다임을 제안한다. </p>
<p>GCR의 작동 방식은 아래와 같다.</p>
<h3 id="1-entity-추출--bfs-경로-수집">1. Entity 추출 + BFS 경로 수집</h3>
<p>질문 $q$에서 topic entity $e_q$를 추출하고, $\mathcal{G}$ 위에서 최대 $L$-hop BFS를 수행해 모든 경로 집합 $W_z$를 수집한다. 
$\mathcal{W}_z=BFS(\mathcal{G}, \mathcal{E}_q, L)$</p>
<blockquote>
<h4 id="bfs-algorithm"><strong>BFS Algorithm</strong></h4>
<p>BFS(Breadth-First Search)는 그래프나 트리 구조에서 데이터를 탐색할 때 사용하는 대표적인 알고리즘이다. 직관적으로 말하자면 <strong>&quot;나랑 제일 가까운 이웃부터 다 확인하고, 그 다음 멀리 있는 애들로 넘어가는 방식&quot;</strong>이다. 깊게 파고들기 전에 얕고 넓게 훑는다고 해서 &#39;너비 우선&#39;이라고 부른다.
<img src="https://velog.velcdn.com/images/so_oni_on/post/bb04bc58-d835-4442-aa41-2ca22dd03e15/image.png" alt="">
<strong>1. BFS가 작동하는 원리 (물수제비 파문)</strong>
호수에 돌을 던지면 물결이 동심원을 그리며 퍼져나가는 것을 생각하면 이해하기 쉽다.
&amp;nbsp&amp;nbsp&amp;nbsp <strong>1) 시작점 (Topic Entity):</strong> 질문에서 찾은 핵심 단어 (예: <code>Justin Bieber</code>)가 호수에 던진 돌맹이, 즉 시작점(루트 노드)이 됨. 이것이 0-hop.
&amp;nbsp&amp;nbsp&amp;nbsp <strong>2) 가장 가까운 이웃 (1-hop):</strong> 0-hop 노드와 선 (Edge, 논문에서는 Relation)으로 직접 연결된 모든 노드를 싹 다 방문. (예: <code>저스틴 비버의 엄마, 아빠, 출생지</code>)
&amp;nbsp&amp;nbsp&amp;nbsp <strong>3) 그 다음 이웃 (2-hop):</strong> 1-hop에서 찾은 노드들과 연결된 또 다른 노드들을 방문합니다. (예: <code>엄마의 직업, 아빠의 다른 자녀(Jaxon Bieber)</code>)
&amp;nbsp&amp;nbsp&amp;nbsp <strong>4) 반복:</strong> 우리가 미리 정해둔 깊이, 즉 최대 $L$-hop에 도달할 때까지 이 과정을 물결처럼 넓혀가며 반복합니다.</p>
</blockquote>
<hr>
<blockquote>
</blockquote>
<p><strong>2. 구현 (큐, Queue)</strong>
이 &#39;넓게 퍼지는&#39; 순서를 헷갈리지 않고 기억하기 위해 BFS는 보통 <strong>큐(Queue, 대기열)</strong>라는 자료구조를 사용한다. (First In First Out; FIFO)
<code>여담으로 미국식 영어에서는 사람이 서는 줄이 line이지만, 영국식 영어에서는 사람이 서는 줄을 queue라고 한다. 이를 연상하면 자료 구조도 쉽다.</code></p>
<blockquote>
</blockquote>
<p>&amp;nbsp&amp;nbsp&amp;nbsp <strong>1)</strong> 대기열에 먼저 시작점(Justin Bieber)을 넣는다.
&amp;nbsp&amp;nbsp&amp;nbsp <strong>2)</strong> 대기열에서 하나를 꺼내고, 그와 연결된 이웃들(엄마, 아빠)을 대기열 맨 뒤에 줄을 세운다.
&amp;nbsp&amp;nbsp&amp;nbsp <strong>3)</strong> 다시 대기열 맨 앞에서 하나를 꺼내고(엄마), 엄마의 이웃들을 또 맨 뒤에 줄 세운다.
&amp;nbsp&amp;nbsp&amp;nbsp <strong>4)</strong> 이렇게 줄 서 있는 순서대로 차곡차곡 처리하면, 자연스럽게 거리가 가까운 1-hop 노드들부터 먼저 다 꺼내보고 나서 2-hop 노드들을 꺼내보게 된다.</p>
<blockquote>
</blockquote>
<hr>
<blockquote>
</blockquote>
<p><strong>3. 논문에서 BFS를 선택한 이유 (Why BFS?)</strong>
저자들은 빠짐없는 그래프 탐색을 위해 해당 알고리즘을 사용하였다고 밝혔다.
논문의 목적은 LLM이 정답을 놓치지 않도록 지식 그래프 안에서 유효한 모든 추론 경로($W_z$)를 긁어오는 것이다. BFS는 주변부터 층층이 샅샅이 뒤지기 때문에, 지정된 거리($L$-hop) 내에 있는 관련 지식을 절대 놓치지 않는다는 강력한 장점이 있다.</p>
<p>논문은 BFS를 기본으로 썼지만, random walk 등 다른 그래프 탐색 알고리즘으로도 대체 가능하다고 명시한다. BFS를 선택한 이유는 층위별로 모든 경로를 놓치지 않기 위해서라고 밝혔다.</p>
<h3 id="2-자연어-문장화-path-formatting">2. 자연어 문장화 (Path Formatting)</h3>
<p>이후 아래의 템플릿을 활용해 수집된 경로를 자연어 문장 형태로 변환한다. 이 과정을 통해 LLM이 처리하는 방식은 텍스트 방식으로 KG를 바꿔주기 때문에, KG의 구조적 정보를 LLM이 인식할 수 있는 형태로 직렬화 하는 과정이 본 과정에 해당한다. 
$\rightarrow$ 결과: 
<img src="https://velog.velcdn.com/images/so_oni_on/post/559a211b-7c86-49e3-870c-5407e0531e0f/image.png" alt=""></p>
<p>e.g., <code>&quot;[엔티티1] [관계1] [엔티티2] [관계2] [엔티티3]&quot;
→ &quot;Justin Bieber people.person.parents Jeremy Bieber people.person.children Jaxon Bieber&quot;</code></p>
<h3 id="3-토크나이징">3. 토크나이징</h3>
<p>포맷팅된 문장들을 KG-specialized LLM의 토크나이저로 분할해 토큰 시퀀스 $T_z$를 만든다.
이때 중요한 문제는 _같은 엔티티 이름이라도 tokenizer에 따라 다른 토큰으로 분할될 수 있다_는 점이다. 가령 <code>&quot;Jeremy Bieber&quot;</code>가 <code>[&quot;Jeremy&quot;, &quot; Bie&quot;, &quot;ber&quot;]</code>로 분할될 수 있다. KG-Trie는 이 토큰 수준에서 구성되기 때문에, Trie의 각 노드는 KG 엔티티/관계 단위가 아니라 토크나이저 토큰 단위이다. 
이것이 논문이 &quot;LLM의 토크나이저와 결합&quot;이라고 강조하는 이유이다.</p>
<h3 id="4-trie-구성">4. Trie 구성</h3>
<p>$C_{\mathcal{G}}=Trie(T_z)$
토큰 시퀀스들을 Trie에 삽입하고, 이후 디코딩 시 $C_{\mathcal{G}}$가 제약으로 사용된다. (즉 $C_{\mathcal{G}}$에 주어진 정보 내부에서만 LLM이 답변을 생성하도록)</p>
<p>따라서 전반적인 과정은 아래와 같은 수식으로 정의가 된다.
<img src="https://velog.velcdn.com/images/so_oni_on/post/20773c92-b3a1-4798-a670-977136545009/image.png" alt=""></p>
<p>위와 같이 각 질문 엔티티에 대해 KG-Trie를 설계함으로써, 그래프 순회를 비싸게 할 필요없이 $O(|\mathcal{W}_z|))$의 효율적인 constant time이 정의가 된다. 게다가 KG-Trie는 이미 구조화된 그래프를 로드해서 오면 되는 구조이기 때문에 KG만 있다면 본 방법론을 적용하는 것은 효율적인 그래프 기반 검색 방식이라 본 저자들은 주장한다.</p>
<p>지금까지가 KG를 <strong>&quot;어떻게 사용할 것인가&quot;</strong>에 대한 문제였다면, 아래는 LLM을 활용해 KG 기반 지식을 <strong>&quot;어떻게 디코딩할 것인가&quot;</strong>의 문제이다!</p>
<h3 id="5-graph-constraied-decoding">5. Graph-constraied Decoding</h3>
<p>아래의 6번 수식은 토큰 생성을 위한 디코딩 시 수식이며, 7번 수식은 마스킹 함수 정의 수식이다.
<img src="https://velog.velcdn.com/images/so_oni_on/post/7b7a3304-d5d3-4427-a851-4f4d355c4b4e/image.png" alt=""></p>
<p>지금까지 생성된 토큰 시퀀스 $w_{z_{1:i}}$가 KG-Trie의 어떤 유효한 경로의 접두사로 존재하면 이 토큰은 허용(1), 아니면 확률을 0으로 만들어 원천 차단시키고자 하는 방식이다.</p>
<p>매 토큰 생성 단계에서 위의 과정을 수행함으로써, 현재 생성중인 prefix를 KG-Trie에서 조회하고, Trie에서 현재 prefix의 다음으로 올 수 있는 유효 토큰 집합을 추출한다. LLM의 전체 vocab.에서 이 유효 토큰 집합에 속하지 않는 토큰들의 logit을 $-\infin$으로 설정하여, softmax 적용 이후의 그 토큰들의 확률은 0이 되도록 한다.</p>
<p>이 과정이 Beam Search와 결합되어 여러 개의 KG-grounded 경로와 가설 답변이 생성된다. </p>
<p>더 나아가, Agent-based 방식과 같이 KG의 경로를 완벽히 참조한다면 Agent-based와 제안 방법론인 GCR이 무엇이 다른지 의문이 들 것이다. Appendix B.2에 따르면, KG-Trie 조회는 $O(|\mathcal{W}_x|)$ 상수 시간으로, agent-based 방법이 매 스텝마다 KG와의 상호작용을 해야해서 쿼리 당 수백초가 걸리는 반면, GCR은 이미 구축된 Trie를 &quot;단순 조회&quot;한다는 점에서 추론 시간이 극적으로 짧아진다고 언급한다.</p>
<blockquote>
<h4 id="appendix-b-kg-trie-construction">Appendix B. KG-Trie Construction</h4>
<p>본 부록 절에서는 시공간 복잡도 문제를 구체적으로 어떤 방식을 통해 해결하였는지를 다룬다.</p>
</blockquote>
<ul>
<li><strong>B.1. Construction Strategies</strong>
KG-Trie 설계에 있어서 두 가지 방식이 있다.<ul>
<li><strong>On-demand 모드</strong>: 질문이 들어올 때마다 해당 질문의 topic entity에 대해 즉석해서 Trie를 구성하는 방식이다. 전처리 시간이 없으며 메모리 효율적이고, 실시간 응용에 적합하다는 장점이 있다.</li>
<li><strong>Offline pre-computation 모드</strong>: 자주 등장하는 엔티티들의 KG-Trie를 미리 구축하여 캐싱하는 방식이다. 자주 쓰는 엔티티는 반복 구축 비용을 절약할 수 있으며, 논문이 언급하는 캐싱 전략이 바로 해당 전략이다. <blockquote>
<br></blockquote>
</li>
</ul>
</li>
<li><strong>B.2. Time and Space Complexity Analysis</strong>
Trie 구축:<ul>
<li><strong>시간</strong>: $O(|W_z| \cdot L \cdot |T|)$ — 경로 수 × hop 수 × 토큰 길이</li>
<li><strong>공간</strong>: $O(|W_z| \cdot L \cdot |T|)$ — 같은 prefix를 공유하므로 실제로는 더 적음<blockquote>
</blockquote>
따라서 디코딩 시 조회를 할 때는 토큰 당 $O(1)$의 복잡도가 발생한다. (Prefix 조회가 Trie에서는 constant time)
<img src="https://velog.velcdn.com/images/so_oni_on/post/56d7588f-b36a-4b1f-a75f-cedcc7c9b805/image.png" alt="">
$\rightarrow L=2$가 최적점이며, $L=3, 4$는 Trie 크기가 급증하나 성능 향상이 미미하단 것을 확인할 수 있다.</li>
</ul>
</li>
<li><strong>B.3. Strategies for Optimizing Efficiency</strong><ul>
<li><strong>엔티티 캐싱</strong>: hub node (degree가 큰 엔티티)는 KG-Trie가 매우 커짐. 이 엔티티들의 Trie를 미리 캐싱해두면 반복 구축 비용 절약 가능하다.</li>
<li><strong>Path pruning</strong>: BFS로 수집된 경로 중 질문과 관련성이 낮은 경로를 미리 필터링해 Trie 크기를 줄이는 방향도 언급한다.</li>
</ul>
</li>
</ul>
<h3 id="6-graph-inductive-reasoning">6. Graph Inductive Reasoning</h3>
<p>이후, KG-specialized LLM이 beam search로 KK
K개의 경로와 가설 답변 쌍을 생성한다.</p>
<p>${(w_z^{(1)},\hat{a}{(1)}),(w_z^{(2)},\hat{a}{(2)}),…,(w_z^{(K)},\hat{a}^{(K)})}$</p>
<p>이것을 general LLM에 전부 입력해 귀납적 추론으로 최종 답변을 도출하고, 이 부분이 FiD (Fusion-in-Decoder) 방식과 유사하다. 단일 경로만 쓰는게 아닌, 여러 경로의 다양성을 한 번에 활용해서 더 robust한 답변을 내는 방식이다.</p>
<p>따라서 최종적으로 정리하면 다음과 같다.
본 방법론 적용을 위해서는 LLM이 두 번 호출되어야하며, KG-specialized LLM과 General LLM이 필요하다. 각각은 경량화된 모델과 GPT-4o같은 강력한 모델을 사용하였다고 밝힌다.</p>
<p>//이거 표로 바꿔야됨
KG-specialized LLMGeneral LLM크기경량 (LLaMA 3.1 8B)강력 (GPT-4o)역할KG-Trie 제약 하에서 경로 탐색여러 경로 종합해 최종 답변학습Instruction tuning 필요추가 학습 없음 (plug-and-play)</p>
<hr>
<h2 id="result--analysis">Result &amp; Analysis</h2>
<p>본 방법론은 학습이 필요없는 디코딩 차원에서 LLM에게 제약을 걸어 불필요한 답안 생성을 막고 효율적인 KG 참조를 하여 최종 모델 정확도 성능을 올리는 것을 목표로 한다.
해당 방법론 적용을 통해 본 저자들은 다음과 같은 Research Questions 관점에서 결과를 해석하고자 한다.</p>
<blockquote>
<p><strong>Research Questions in GCR</strong></p>
</blockquote>
<ul>
<li><strong>RQ1: Reasoning Performance and Efficiency</strong>
메인 결과표 분석과 함께 제거 실험을 적용하여 본 방법론을 적용했을 때 효율성과 최종 정확도에 있어 어떤 수치적 변화가 있는지 확인하고자 한다. </li>
<li><strong>RQ2: Hallucination Elimination and Faithful
Reasoning</strong>
정성적 분석을 통해 실제 환각 현상이 얼마나 제거가 됐고, 얼마나 신뢰성있는 답변이 출력됐는지 Case study를 통해 확인하고자 한다.</li>
<li><strong>RQ3: Zero-shot Generalizability to Unseen KGs</strong>
새로운 KG 데이터셋을 적용하여, 본 방법론을 Zero-shot 방식으로 적용했을 때 얼마나 도메인 의존적인지?를 확인하기 위해 일반화 성능을 검증하고자 한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/3b5f0208-eec3-403e-96d7-72de947dea11/image.png" alt="">
메인 결과표이다.
또한 KG는 노드들이 이제 엔티티별로 묶여있으니까 Hop의 개념이 중요하다. 몇 개 노드까지 살펴볼건지 -&gt; 이게 출력에 참고할 정보가 되니까 출력의 질과도 직접적인 관계가 있다. 그래서 Appendix F의 추가 실험 결과에 따르면, 
<img src="https://velog.velcdn.com/images/so_oni_on/post/7d1056ff-b7fd-413b-b221-2cb72b9dcbe5/image.png" alt="">
$L=2$가 WebQSP와 CWQ 모두에서 최적. $L=1$은 너무 짧아 answer entity에 도달 못하는 경우가 많은 반면, $L=3$ 이상은 성능 향상이 미미하고 Trie 크기만 커지는 것을 확인할 수 있다.</p>
<p>또한 Reasoning on Graph (RoG) 방법론과 비교했을 때, beam search로 $K$개 경로를 생성하고, general LLM이 통합할 때 $K$가 클수록 성능이 오르는 경향을 확인할 수 있었다. (단, $K$가 너무 크면 general LLM의 context 길이 제한에 걸림.)</p>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/ac4fdd93-23ec-499e-9946-fb286e768c7d/image.png" alt="">
Table 16에 따르면, 4-hop 이상의 복잡한 질문(CWQ 데이터셋)에서도 GCR은 강한 성능을 보임. agent-based 방법이 긴 hop에서 비용이 폭발하는 것과 대조되는 결과를 확인할 수 있었다. </p>
<p>하지만 생성된 reasoning path가 논리적으로 일관성 있는지를 분석하는 과정에서, KG-Trie 제약 덕분에 경로 자체의 사실성은 보장된다는 긍정적인 면이 있지만, 경로가 질문에 &quot;논리적으로 관련이 있는지&quot;는 별개의 문제라고 본 저자들은 밝힌다. 저자들은 이러한 실패가 주로 다음 두 가지 요인에서 비롯된다고 분석하였다.
<img src="https://velog.velcdn.com/images/so_oni_on/post/c1936489-1311-41f7-b48f-b8d75c168860/image.png" alt=""></p>
<ul>
<li><strong>KG 불완정성</strong>: KG에 필요한 사실이 아예 없어서 Trie에 올바른 경로가 포함되지 않는 경우</li>
<li><strong>Topic Entity 추출 성능</strong>: Topic Entity 추출이 애초에 잘못되어 엉뚱한 엔티티에서 BFS가 시작되는 경우</li>
</ul>
<hr>
<h2 id="conclusion">Conclusion</h2>
<p>따라서 위의 정량/정성적인 결과를 고려해보았을 때, 본 논문의 저자들은 해당 제안 방법론인 GCR의 한계점을 아래와 같이 정의한다.</p>
<h3 id="1-kg-constrained-zero-hallucination의-정의-범위의-모호성"><strong>1. KG-constrained zero-hallucination의 정의 범위의 모호성</strong></h3>
<p>KG 안에 경로가 존재한다는 것이 곧 정답으로 이어진다는 보장을 할 수 없다. 이 이유는 직전에 설명했던 내용과 같이 KG의 정밀성과 완전성에 의존하는 방법론임을 밝힌다.</p>
<h3 id="2-kg의-불완정성"><strong>2. KG의 불완정성</strong></h3>
<p>필요한 사실이 KG에 없으면 Trie에 올바른 경로가 기재되지 못하고, GCR 방법을 적용해도 답을 하지 못한다. 따라서 구조적 의존성과 한계를 지닌다.</p>
<h3 id="3-hub-node에서의-trie-폭발"><strong>3. Hub node에서의 Trie 폭발</strong></h3>
<p>Degree가 매우 높은 엔티티는 $L-hop BFS$에서 경로 수가 기하급수적으로 증가한다. 이를 캐싱으로 미리 해결하고자 하지만 근본적인 해결책이 되지 못한다고 밝힌다.</p>
<h3 id="4-api-사용-비용"><strong>4. API 사용 비용</strong></h3>
<p>두 LLM 사용 비용
KG-specialized LLM + general LLM(GPT-4o)을 동시에 쓰는 구조라 API 비용이 올라갑니다. 단일 모델 통합이 future work라고 밝힌다.</p>
<hr>
<p>디코딩 단에서 모델의 환각 현상을 억제하려는 연구도 기존에 많았고, KG를 활용한 LLM의 신뢰성 향상 시도는 많았지만, KG를 LLM의 생성 제약으로 통합하는 프레임워크가 기존에 없었다는 점에서 큰 기술적 기여도가 있었다.
더 나아가, Zero Hallucination을 구조적으로 달성하고, 캐싱 전략을 활용해 agent-based 방법 대비 속도가 수백 배 빠르며, unseen KG에 대한 일반화 성능까지 검증을 거쳤다는 점에서 실용적 기여 또한 있는 논문이라 생각된다.</p>
<p>💡 저스틴 비버 예시로 이해하는 &#39;접두사 압축(Trie)&#39;앞선 BFS 단계에서 저스틴 비버에 대한 3개의 지식 경로를 찾았고, 이를 토큰으로 쪼갰다고 가정해 봅시다.
<code>[&quot;Justin&quot;, &quot; Bieber&quot;]</code>
경로 A: <code>[&quot;Justin&quot;, &quot; Bieber&quot;, &quot; parents&quot;, &quot; Jeremy&quot;, &quot; Bieber&quot;, &quot; children&quot;, &quot; Jaxon&quot;, &quot; Bieber&quot;]</code>
경로 B: <code>[&quot;Justin&quot;, &quot; Bieber&quot;, &quot; parents&quot;, &quot; Jeremy&quot;, &quot; Bieber&quot;, &quot; children&quot;, &quot; Jazmyn&quot;, &quot; Bieber&quot;]</code>
경로 C: <code>[&quot;Justin&quot;, &quot; Bieber&quot;, &quot; spouse&quot;, &quot; Hailey&quot;, &quot; Bieber&quot;]</code></p>
<p>[압축 전: 일반적인 저장 방식]</p>
<p>보통은 저 3개의 긴 문장을 따로따로 다 저장합니다. 메모리도 많이 차지하고, 나중에 LLM이 &quot;다음에 올 단어가 뭐지?&quot; 하고 찾을 때마다 처음부터 끝까지 다 뒤져봐야 해서 매우 느립니다.</p>
<p>[압축 후: Trie(접두사 트리) 방식]경로 A와 B를 잘 보세요. 처음 시작부터 &quot; children&quot; 토큰까지 앞부분(접두사)이 100% 똑같습니다. 경로 C 역시 두 번째 토큰인 &quot; Bieber&quot;까지는 앞부분이 똑같습니다.그래서 트라이(Trie)는 이 겹치는 앞부분을 <strong>하나의 굵은 나무 기둥(공통 접두사)</strong>으로 합쳐버립니다.뿌리에서 출발해 Justin $\rightarrow$ Bieber 까지는 하나의 길로 갑니다.여기서 spouse 길과 parents 길로 가지가 나뉩니다(Branch).parents 길을 따라 Jeremy $\rightarrow$ Bieber $\rightarrow$ children 까지 다시 쭉 하나의 길로 갑니다.그리고 마지막에 Jaxon과 Jazmyn으로 다시 한번 가지가 나뉩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[지식 그래프 설계 기초 (개념적)]]></title>
            <link>https://velog.io/@so_oni_on/%EC%A7%80%EC%8B%9D-%EA%B7%B8%EB%9E%98%ED%94%84-%EC%84%A4%EA%B3%84-%EA%B8%B0%EC%B4%88-%EA%B0%9C%EB%85%90%EC%A0%81</link>
            <guid>https://velog.io/@so_oni_on/%EC%A7%80%EC%8B%9D-%EA%B7%B8%EB%9E%98%ED%94%84-%EC%84%A4%EA%B3%84-%EA%B8%B0%EC%B4%88-%EA%B0%9C%EB%85%90%EC%A0%81</guid>
            <pubDate>Mon, 30 Mar 2026 12:29:34 GMT</pubDate>
            <description><![CDATA[<h2 id="1-preliminary">1. Preliminary</h2>
<p>2024년 이후 LLM(대형 언어 모델)이 고도화됨에 따라, 사람들은 단순한 성능을 넘어 자원의 효율성과 환각(Hallucination) 현상 해결에 집중하기 시작했다. 이는 데이터 업데이트 시 모델 전체를 재학습시키는 막대한 비용 부담과, 정확한 근거 없이 그럴듯한 오답을 내놓는 생성형 AI의 고질적인 문제에서 비롯되었다.</p>
<p>이러한 한계를 극복하기 위해 <strong>RAG(Retrieval-Augmented Generation)</strong>와 같은 &quot;검색 기반 데이터 증진&quot; 기술이 대두되었다. 아마  AI를 공부하는 사람이라면 무조건 들어봤을 것이다. 
이 과정에서 단순히 텍스트 조각을 찾는 것을 넘어, 데이터 간의 유기적인 관계를 파악할 수 있는 데이터 형태가 주목받았는데, 그것이 바로 <strong>지식그래프(Knowledge Graph)</strong>이다.</p>
<p>🤠</p>
<p><strong>지식그래프(Knowledge Graph, KG)</strong>는 현대 AI와 빅데이터 시대의 핵심 기술로, 구글 검색 엔진부터 기업용 데이터 분석까지 이미 우리 일상 곳곳에서 널리 쓰이게 되었다. </p>
<h3 id="a-지식그래프의-정의와-모양">a. 지식그래프의 정의와 모양</h3>
<p>지식그래프는 이름 그대로 지식을 <strong>&#39;거미줄(Graph)&#39;</strong>처럼 엉켜 있는 형태로 표현한 것이다. 단순히 개별적인 데이터를 나열하는 것이 아니라, 데이터 사이의 <strong>&#39;관계&#39;</strong>를 촘촘하게 엮어져 있다.</p>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/0a33f3bf-b11e-4384-8b87-9a9c4405fdbf/image.png" alt=""></p>
<p>학술적으로 <strong>지식그래프 모델링</strong>이란, 지식을 효율적으로 저장하고 검색(Querying)하며, 새로운 정보를 찾아내기(Reasoning) 위해 그래프 형태로 구조화하고 표현하는 일련의 과정을 의미한다.</p>
<blockquote>
<p>** 🕸️ 지식 그래프의 구성:**</p>
</blockquote>
<ul>
<li><strong>노드(Nodes/Entities):</strong> 사람, 제품, 장소와 같은 실세계의 객체.</li>
<li><strong>엣지(Edges/Relations):</strong> 객체들 사이를 잇는 관계.</li>
<li><strong>레이블(Labels):</strong> 사람이 읽을 수 있고 기계가 식별할 수 있는 의미 있는 이름.</li>
</ul>
<p>이러한 형식의 지식 그래프를 사용할 때의 장점은 무엇일까? 
지식그래프는 전통적인 데이터베이스와 비교했을 때 다음과 같은 독보적인 강점을 가진다.</p>
<table>
<thead>
<tr>
<th align="left">주요 장점</th>
<th align="left">상세 설명</th>
<th align="left">기대 효과</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>의미적 명확성</strong> (Semantic Meaning)</td>
<td align="left">데이터의 맥락과 의미를 강조하여 해석 가능성을 극대화함</td>
<td align="left">기계가 데이터의 &#39;진짜 의미&#39;를 이해</td>
</tr>
<tr>
<td align="left"><strong>강력한 연결 및 추론</strong> (Reasoning)</td>
<td align="left">흩어진 데이터를 연결하여 숨겨진 관계를 논리적으로 찾아냄</td>
<td align="left">지능형 추천 및 의사결정 지원</td>
</tr>
<tr>
<td align="left"><strong>유연한 구조</strong> (Flexible Schema)</td>
<td align="left">고정된 틀이 없어 새로운 데이터나 관계를 추가하기가 매우 용이함</td>
<td align="left">변화하는 비즈니스 환경에 빠르게 대응</td>
</tr>
<tr>
<td align="left"><strong>다중 관계 표현</strong> (Multi-relational)</td>
<td align="left">엔티티 사이에 수많은 종류의 복잡한 관계를 동시에 정의 가능</td>
<td align="left">현실 세계의 복잡성을 그대로 반영</td>
</tr>
<tr>
<td align="left"><br></td>
<td align="left"></td>
<td align="left"></td>
</tr>
</tbody></table>
<h3 id="b-지식-그래프의-데이터-기저web-documents-vs-semantic-web-documents">b. 지식 그래프의 데이터 기저(Web Documents vs. Semantic Web Documents)</h3>
<p>지식그래프가 단순히 연결된 데이터를 넘어 &#39;지능&#39;을 갖게 되는 이유는 데이터를 웹상에서 기계가 해석할 수 있는 표준 규격으로 구현하기 때문이다.</p>
<pre><code># 이때 지능을 갖는다는 표현은 곧 &#39;사람이 일일이 가르쳐주지 않아도 
기계가 규칙과 맥락을 통해 스스로 정보를 판단하고 연결할 수 있는 구조가 되었다.&#39;는 뜻이다.
조금 더 자세한 내용은 아래에서 다시 설명하도록 하겠다.</code></pre><h4 id="web-documents-traditional-web">Web Documents (Traditional Web)</h4>
<ul>
<li>사람 중심으로 디자인되었음.</li>
<li>주로 HTML의 형식으로 작성됨.</li>
<li>텍스트, 이미지, 링크 등의 <strong>Presentation과 Layout에 집중적</strong>임.</li>
<li>의미가 &quot;암시적(Implicit)&quot;이며, 기계가 이해할 수 없는 형태로 나타있음.<pre><code>  웹 페이지에 &quot;Apple&quot;이라는 단어가 있을 때, 이 단어가 과일인지 기업인지 기계는 명확히 구분이 어려움.</code></pre></li>
</ul>
<h4 id="semantic-web-documents">Semantic Web Documents</h4>
<ul>
<li>사람과 기계 모두가 이해할 수 있도록 설계됨.</li>
<li>RDF, RDFS, OWL과 같은 표준을 사용.</li>
<li>데이터의 &quot;명시적인 의미(Semantics)&quot;에 집중적임.</li>
<li>의미가 구조화되어 있으며, <strong>기계가 읽을 수 있음 (Machine-readable)</strong>.</li>
</ul>
<p><code>(Apple, type, Company)</code> 또는 <code>(Apple, type, Fruit)</code>와 같이 관계를 명시하여 혼동을 방지
<br>
가령 기존의 Web Documents가 Wikipidia라면 Semantic Web Documents는 WikiData 데이터 형태인 것이다. </p>
<blockquote>
<p>🍰 <strong>Semantic Web Layer Cake (계층 구조)</strong>
시맨틱 웹은 아래에서 위로 쌓이는 기술 계층으로 구성된다.</p>
</blockquote>
<ul>
<li><strong>기초:</strong> URI/Unicode (식별 및 문자) </li>
<li><strong>구조화:</strong> XML, RDF, RDFS (데이터 모델 및 스키마) </li>
<li><strong>논리 및 추론:</strong> OWL (온톨로지), Rules, Logic, Proof </li>
<li><strong>보안 및 신뢰:</strong> Digital Signature, Encryption, Trust </li>
<li><strong>인터페이스:</strong> SPARQL (쿼리 언어) 
<img src="https://velog.velcdn.com/images/so_oni_on/post/48da3b1f-0037-410f-88af-610fa18c521b/image.png" alt=""></li>
</ul>
<hr>
<h2 id="2-knowledge-graph-kg-modeling">2. Knowledge Graph (KG) Modeling</h2>
<p>그렇다면 Knowledge Graph란?</p>
<p>지식을 그래프 형태로 &quot;구조화 (Structuring), 표현 (Representing), 그리고 조직화 (Organizing)&quot;하는 프로세스</p>
<p>이는 효율적인 저장, 쿼리(Querying, 데이터 검색 및 질의), 그리고 <strong>추론 (Reasoning)</strong>을 가능하게 하기 위함이다.</p>
<p>핵심 구성요소는 아래와 같다.</p>
<blockquote>
<ul>
<li><strong>노드(Nodes/Entities):</strong> 사람, 제품 등 실세계의 객체.</li>
</ul>
</blockquote>
<ul>
<li><strong>엣지(Edges/Relations):</strong> 엔티티 간의 관계.</li>
<li><strong>레이블(Labels):</strong> 기계와 사람이 식별할 수 있는 의미 있는 식별자.</li>
</ul>
<p>이 데이터 구조의 특징은 다중 관계성(Multi-relational), 유연한 스키마, 그리고 의미적 명확성이 또렷하다.</p>
<hr>
<h2 id="3-key-of-kg">3. KEY of KG</h2>
<h3 id="resource-description-framework-rdf">Resource Description Framework (RDF)</h3>
<p>RDF는 웹상의 정보를 표현하기 위해 W3C에서 표준화한 모델이다.</p>
<ul>
<li>** RDF 데이터 모델: Triple (트리플)</li>
<li><em>데이터를 표현하는 기본 단위로, 아래의 세 부분으로 구성된다.
   *</em>1. Subject (주어):** 관계의 주체.
   <strong>2. Predicate (술어):</strong> 주어와 목적어 사이의 관계/속성.
   <strong>3. Object (목적어):</strong> 관계의 대상 또는 값.
<code>예시: Alice(Subject) --hasFriend(Predicate)--&gt; Bob(Object)</code> </li>
</ul>
<p><strong>식별자: URI, URL, IRI</strong></p>
<ul>
<li><strong>URI (Uniform Resource Identifier):</strong> 웹상의 리소스를 고유하게 식별합니다. 주어, 술어, 목적어 위치에 모두 올 수 있다.</li>
<li><strong>URL (Uniform Resource Locator):</strong> URI의 일종으로, 리소스에 접근하는 방법(프로토콜)까지 명시한다.</li>
<li><strong>IRI (Internationalized Resource Identifier):</strong> URI를 확장하여 전 세계의 다양한 언어(Unicode) 문자를 지원한다.</li>
</ul>
<hr>
<h2 id="4-types-of-rdf-node">4. Types of RDF Node</h2>
<p>RDF 그래프를 구성하는 노드는 세 가지 유형이 있다.</p>
<table>
<thead>
<tr>
<th align="left">노드 유형</th>
<th align="left">의미 및 특징</th>
<th align="left">트리플 내 위치 (Triple Position)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>URI (IRI) Node</strong></td>
<td align="left">리소스를 고유하게 식별하는 글로벌 식별자</td>
<td align="left"><strong>주어, 술어, 목적어</strong> 모두 가능</td>
</tr>
<tr>
<td align="left"><strong>Literal Node</strong></td>
<td align="left">텍스트, 숫자, 날짜 등 실제 데이터 값</td>
<td align="left"><strong>목적어(Object)</strong> 위치만 가능</td>
</tr>
<tr>
<td align="left"><strong>Blank Node</strong></td>
<td align="left">고유 식별자가 없는 익명 리소스</td>
<td align="left"><strong>주어(Subject)</strong> 또는 <strong>목적어(Object)</strong> 가능</td>
</tr>
</tbody></table>
<hr>
<h2 id="5-rdf-syntaxes--serialization-구문-및-직렬화">5. RDF Syntaxes &amp; Serialization (구문 및 직렬화)</h2>
<p>RDF 데이터를 컴퓨터 파일 형태로 저장하고 전송하는 방식들이다.</p>
<ul>
<li><strong>XML:</strong> XML 도구들을 활용할 수 있으나 사람이 읽기 어려움.</li>
<li><strong>N-Triples:</strong> 한 줄에 하나의 트리플만 작성하는 단순한 구조이다. 대용량 데이터 덤프에 표준적으로 사용되나 가독성은 낮다.</li>
<li><strong>Turtle (Terse RDF Triple Language):</strong> N-Triples보다 압축된 형태로, 사람이 읽기 가장 좋은 형식이다. 이때, 접두사(Prefix)를 통해 긴 URI를 줄여 쓸 수 있다.</li>
<li><strong>JSON-LD:</strong> JSON 형식을 사용하여 웹 개발자가 다루기 쉽다.</li>
<li><strong>RDFa:</strong> HTML 페이지 내에 RDF 데이터를 직접 삽입할 수 있게 해준다.</li>
</ul>
<hr>
<h2 id="6-지식-그래프-구축-후-작동-방식">6. 지식 그래프 구축 후 작동 방식</h2>
<p>앞서 Preliminary부분에서 말한 바와 같이, 지식그래프가 단순히 연결된 데이터를 넘어 &#39;지능&#39;을 갖게 되는 이유는 데이터를 웹상에서 기계가 해석할 수 있는 <strong>표준 규격(RDF, OWL 등)</strong>으로 구현했기 때문이다. 이렇게 구축된 지식그래프는 다음과 같은 방식으로 지능적으로 작동한다.</p>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/2df576b5-478f-413b-b318-193c563f8f82/image.png" alt=""></p>
<p><strong>1. 단순 연결을 넘어선 &#39;논리적 추론&#39; (Reasoning)</strong>
일반적인 데이터베이스는 우리가 입력한 데이터만 찾아줍니다. 하지만 지식그래프는 명시적으로 적어주지 않은 사실도 기계가 스스로 찾아낼 수 있다. 
<code>예시: A는 B의 아버지다와 B는 C의 아버지다라는 데이터를 넣으면, 기계가 논리 규칙을 통해 A는 C의 할아버지다라는 새로운 지식을 스스로 도출한다.</code>
이러한 자동화된 추론(Automated Reasoning) 능력 활용이 가능해진다. </p>
<p><strong>2. 데이터 스스로가 가진 &#39;자기 설명력&#39; (Semantic Meaning)</strong>
기존 웹 문서(HTML)는 기계 입장에서 그저 &#39;글자 뭉치&#39;이다. 하지만 시맨틱 웹 표준(RDF)을 따르면 데이터에 &#39;의미&#39;가 뒤따라 붙는다. </p>
<ul>
<li><strong>기존 웹:</strong> &quot;Apple&quot; → 단순 텍스트.</li>
<li><strong>지식그래프:</strong> Apple + type: Company → 기계가 이 데이터는 &#39;먹는 과일&#39;이 아니라 &#39;IT 기업&#39;임을 명확히 인지하고 그에 맞는 연관 정보를 연결한다. 
이는 데이터가 스스로의 정체를 기계에게 설명할 수 있는 체계(Ontology)를 갖췄기 때문이다. </li>
</ul>
<p><strong>3. 유연한 확장을 통한 &#39;맥락 이해&#39; (Context)</strong>
지식그래프는 <strong>다중 관계(Multi-relational)</strong>를 지원하며 틀이 정해져 있지 않다. </p>
<ul>
<li>새로운 데이터가 들어올 때마다 기존 거미줄에 계속 이어 붙일 수 있어, 데이터가 쌓일수록 정보 간의 거대한 <strong>맥락(Context)</strong>이 형성된다. </li>
<li>기계가 특정 단어 하나만 보는 게 아닌, 그 단어와 연결된 거대한 관계망 전체를 훑으며 결과를 내놓기 때문에 훨씬 지능적인 답변(Intelligent search)이 가능해진다.</li>
</ul>
<hr>
<h2 id="정리하며">정리하며</h2>
<p>효과적인 지식그래프 구축을 위해서는 단순한 데이터 수집을 넘어, 기계가 추론할 수 있는 논리적인 모델링이 필수적이다. 
이러한 작동 방식 덕분에 지식그래프는 LLM의 할루시네이션을 억제하고, 정교한 RAG 시스템을 구축하는 데 있어 필수적인 &#39;지식의 뼈대&#39; 역할을 수행하게 된다.</p>
<p>하지만 사실상 민간 차원에서 지식그래프를 구축하기에는 <strong>모델링 부재 시 데이터가 오도(Misleading)될 위험</strong>과 <strong>대규모 분산 데이터 관리 및 전문 인력 확보에 따른 비용 과다</strong>라는 점들이 있어 실질적으로 불가능에 가깝다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[효율적인 학습을 위한 경량화 방법]]></title>
            <link>https://velog.io/@so_oni_on/%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-%ED%95%99%EC%8A%B5%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B2%BD%EB%9F%89%ED%99%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@so_oni_on/%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-%ED%95%99%EC%8A%B5%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B2%BD%EB%9F%89%ED%99%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Mon, 09 Mar 2026 12:25:31 GMT</pubDate>
            <description><![CDATA[<p>OOM, Out of Memory 오류는 제한된 환경에서 학습을 하다보면 가장 쉽게 마주할 오류일 것이다.</p>
<pre><code>torch.OutOfMemoryError: CUDA out of memory. Tried to allocate XX GiB. GPU has a total capacity of XX GiB of which XX MiB is free. Including non-PyTorch memory, this process has XX GiB memory in use. Of the allocated memory XX GiB is allocated by PyTorch, and XX MiB is reserved by PyTorch but unallocated. If reserved but unallocated memory is large try setting PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True to avoid fragmentation.  See documentation for Memory Management  
</code></pre><p>오늘의 포스트는 이를 해결하기 위한 LLM 학습에서의 핵심적인 경량화 방법에 대해 정리해둔 포스트다.</p>
<hr>
<h2 id="quantization-양자화">Quantization (양자화)</h2>
<p>제일 직접적인 메모리 절감 기법으로, 모델 로드할 경우 아래와 같은 코드 설정으로 쉽게 설정할 수 있다.</p>
<pre><code class="language-python">from transformers import BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
        load_in_4bit=True,
        bnb_4bit_quant_type=&quot;nf4&quot;,
        bnb_4bit_use_double_quant=True,
        bnb_4bit_compute_dtype=torch.bfloat16 if torch.cuda.is_bf16_supported() else torch.float16,
    )    </code></pre>
<p>기본적으로 BitsAndBytes는 모델의 가중치를 16비트나 32비트가 아닌 4 혹은 8비트 수준으로 압축해서 로드하도록 돕는 패키지다. 이를 통해 모델이 차지하는 VRAM을 절반 가까이 줄일 수 있다.
(Documentation ref. <a href="https://huggingface.co/docs/bitsandbytes/en/index">https://huggingface.co/docs/bitsandbytes/en/index</a>)
<img src="https://velog.velcdn.com/images/so_oni_on/post/81508a0c-bfc9-4fce-baad-445b50b30395/image.png" alt=""></p>
<p>그럼 <code>BitsAndBytesConfig</code> 내부의 각 주요 인자들에 대해 더 자세히 알아보도록 하자.</p>
<ul>
<li><code>load_in_8bit (or) load_in_4bit</code>: 
모델을 4비트로 로드할지 8비트로 로드할지를 결정하는 스위치이다. 4비트 기준, 기존 16비트(자세한건 모델 카드 확인필요) 대비 메모리를 약 4배를 아껴주는 셈이다. </li>
<li><code>bnb_4bit_quant_type=&quot;nf4&quot;</code>: 
핵심적인 부분이다. 일반적인 4비트(fp4)볻가 가중치의 정규분포를 훨씬 더 잘 반영하는 &#39;NormalFloat4&#39; 방식을 사용하도록 해준다. 이는 모델을 압축하여 로드하는 방식 중, 가장 적은 정보 손실을 유도해준다.
가중치가 0 근처에 몰려있는 통계적 특성을 활용한 &#39;정보 이론적 최적&#39; 양자화 방식인 것이다.</li>
<li><code>bnb_4bit_compute_dtype</code>: 
저장은 4비트로 하되, 계산을 얼마로 진행할지를 결정하는 부분이다. <code>bfloat16</code>으로 설정하면 계산의 정확도를 높이면서도 속도를 챙길 수 있게 해준다. </li>
<li><code>bnb_4bit_use_double_quant</code>:
양자화를 위해 필요한 상수값들마저 한 번 더 양자화하는 기술이다. double!! 모델이 커질수록 이 역할이 더 효과적이게 된다.</li>
</ul>
<blockquote>
<p>💁 <strong>이때 <code>bnb_8bit_...</code> 등의 인자는 없는데 그 이유는 단순하다!</strong>
8비트 양자화는 BitsAndBytes 초기에 구현되어 옵션이 단순하기 때문이다. 반면 4비트 QLoRA는 나중에 구현되었으며, 나오면서 NF4, 이중 양자화등 모델의 로드와 학습에 사용되는 메모리를 작게 줄이되 정보 손실량도 줄이는 정교한 양자화 기법이 함께 구현되었기 때문에 4비트 전용 인자들이 더 많다고 한다. </p>
</blockquote>
<h2 id="peftlora-low-rank-adaptation">PEFT/LoRA (Low-Rank Adaptation)</h2>
<p>이는 모델 전체를 학습시키는 것이 아니라 일부 파라미터만 학습시키는 방식이다. </p>
<pre><code class="language-python">from peft import LoraConfig

peft_config = LoraConfig(
        r=LORA_R,
        lora_alpha=LORA_ALPHA,
        lora_dropout=LORA_DROPOUT,
        target_modules=[&quot;q_proj&quot;, &quot;k_proj&quot;, &quot;v_proj&quot;, &quot;o_proj&quot;, &quot;gate_proj&quot;, &quot;up_proj&quot;, &quot;down_proj&quot;],
        task_type=&quot;CAUSAL_LM&quot;
    )</code></pre>
<blockquote>
<p>사실 난 처음에 Quantization 기법 중 하나가 LoRA인 줄 알았다 ^^;;;......
<del>저만 이랬나요?^^;;</del>..
💡 <strong>Quantization과 PEFT/LoRA</strong>
직관적으로 이야기했을 때 </p>
</blockquote>
<ul>
<li>Quantization은 &#39;모델을 로드하는 가장 초기 레벨에서의 사용&#39;</li>
<li>PEFT/LoRA는 &#39;모델을 학습시킬 방식&#39;<blockquote>
</blockquote>
이다. 따라서 모델을 저비트로 로드하는데 모델 파라미터 또한 윗부분의 일부만 학습하는 방식이 바로 QLoRA인 것이다.</li>
</ul>
<h2 id="flash-attention-2">Flash Attention 2</h2>
<p>Transformer의 핵심 연산인 Attention 메커니즘을 수학적으로 더 최적화하여 연산 속도를 높이고 메모리 사용량은 확! 줄인 최신 기술이다. 특히 긴 문장을 처리할 때 효과적이다.</p>
<p>조금 더 디테일하게 설명하자면, 이 기술은 속도 향상을 <strong>&quot;메모리 읽기/쓰기 횟수&quot;</strong>를 줄이는 방식으로 구현하였다.</p>
<ul>
<li>원리: 
기존 어텐션이 $N$ x $X$ 크기의 큰 맵을 통째로 GPU 메모리에 올렸다면, Flash Attention2는 이를 더 작은 타일 단위로 쪼개어 SRAM 단위에서 계산하는 방식이다.
수식적으로는 기존 어텐션 메커니즘과 Flash Attention2는 동일하지만($Q$ x $K^T$), 메모리 병목을 줄여서 실제 속도가 훨씬 빨라지는 방식이다. </li>
<li><em>따라서 수학적 연산량은 여전히 $O(N^2)$이지만, 메모리에 적재하는 공간 복잡도를 $O(N)$으로 줄여서 병목을 해결한 방식인 것이다.*</em></li>
<li>효과:
메모리 사용량이 문장 길이에 따라 기하급수적으로 늘어나는 것이 아닌 선형적으로 늘어나는 것이다.</li>
</ul>
<h2 id="gradient-checkpointing">Gradient Checkpointing</h2>
<ul>
<li>원리:
Backpropagation를 위해 모든 중간 연산값(Activation)을 저장하는 대신 일부만 저장하고 나머지는 필요할 때 다시 계산하는 방식이다. </li>
<li>Trade-off:
사실 이 방식을 쓰면 계산 시간이 약 20~30% 정도 늘어난다. 이론적으로 역전파를 한 번 할 때마다 Forward 연산을 한 번 더 해야하기 때문이다.(그럼 보통 전체 연산의 1/3 정도가 추가) 메모리를 아끼는 대신 VRAM 점유율을 낮추기 위해 저장하지 않고 버린 Activation들을 Recompute하는 방식이기 때문이다. </li>
</ul>
<hr>
<p>위의 내용들을 <code>main.py</code>에 적용한다고 했을 때, 최종적으로 아래의 형태를 기본적으로 따른다.
모델을 불러올 때 Quantization 여부를 <code>quntization_config</code>을 통해 앞서 선언한 저비트 로딩 방식을 적용하며, <code>attn_implementation</code>을 통해 flash attnetion2를 연산 방식으로 지정해주면 된다.
이후 학습에 들어가기 전에 앞서 선언해둔 모델을 어떻게 학습할지 </p>
<pre><code class="language-python">from peft import get_peft_model
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(
        args.model_path,
        config=cfg,
        quantization_config=bnb_config,
        trust_remote_code=model_config.trust_remote_code, # True, False
        torch_dtype=torch.float16,
        attn_implementation=&quot;flash_attention_2&quot;,
        device_map=&quot;auto&quot;, 
    )

...

model = get_peft_model(model, peft_config)</code></pre>
<hr>
<h3 id="note">Note</h3>
<h4 id="--torchcudaempty_cache">- torch.cuda.empty_cache()</h4>
<p>이는 메모리 파편화(Fragmentation)를 막아서 VRAM을 좀 더 알뜰하게 쓰기 위함이다. 메모리를 OS에 반환했다가 나중에 다시 필요해지면, OS한테 새로 빌려오는 과정(Overhead)이 추가됨. 그래서 학습 속도가 살짝 버벅일 수 있다는 게 핵심이다. 연산 중간에 남발하기보다는, 큰 단계가 끝나고 메모리를 한 번 정리해야 할 때 적재적소에 배치하는 게 중요하다.</p>
<h4 id="--unsloth-라이브러리-활용">- Unsloth 라이브러리 활용</h4>
<p>일반 BitsAndBytes 패키지보다 훨씬 최적화된 커널을 사용한다. Manual Backpropagation(역전파 수동 구현)을 통해 중복 연산을 제거하도록 구현되기도 하여, 학습 속도가 2배 이상 빨라지고 VRAM도 40% 가량 아껴주는 역할을 한다. </p>
<h4 id="--deepspeed">- DeepSpeed</h4>
<p>이것도 flash attn2랑 함께 자주 상호보완적으로 잘 사용된다. DeepSpeed로 모델을 쪼개고? flash attn2로 연산을 최적화하는 방식이다. DeepSpeed은 모델의 데이터를 Sharding해서 저장하는 방식이다. 쉽게 말해서 Optimizer States나 모델 가중치를 여러 GPU에 분산해 쪼개서 저장하는 방식이다. 
flash attn2가 GPU 내부에서 연산 자체를 최적화하는 방법이라면, 이는 여러대의 GPU를 쓰거나 ZeRO(Zero Redundancy Optimizer) 기술이 적용해서 모델의 Optimizer States, Gradients를 쪼개서 저장하는 시스템 분산 최적화 도구이다.</p>
<blockquote>
<ul>
<li><strong>DeepSpeed:</strong> 개별 GPU의 연산을 효율화
개별 GPU 내부에서 어텐션 연산(SRAM-HBM 이동)을 효율화하는 기술.</li>
</ul>
</blockquote>
<ul>
<li><strong>Flash Attention:</strong> GPUs의 전반적 분산을 관리
여러 대의 GPU들 사이에 모델 상태(Weights, Gradients, Optimizer States)를 분산(Sharding)해서 관리하는 기술.<blockquote>
<hr>
<p>🧠 즉 Flash Attention2는 GPU 내부적으로 효율화하는 방식이고, DeepSpeed는 GPU끼리 매니징하는 역할이라고 생각하면 될 것 같다.</p>
</blockquote>
</li>
</ul>
<hr>
<p>개인적으로 이 외에도 만약 강화학습과 같은 여러 rollouts를 만들어야하는 경우, 하나의 배치에 completions를 올리지 않고 Mini-batch를 직접 구현해서 Backpropagation하는 등의 방법을 사용하기도 한다. (대신!! shape을 꼼꼼히 잘 찍어봐야된다. &lt;&lt; 매우 중요....)</p>
<p>위의 내용들을 효과적으로 사용하기 위해서는 본인이 사용하는 GPU 및 쿠다 버전 등을 디테일하게 확인하고 알맞는 버전을 사용하는 것 또한 중요하다.
한정된 메모리에서 진행하는 연구 환경에서는 위와 같은 내용들이 무조건 !! 도움이 될 것이다.</p>
<p>그럼 오늘 포스트 끝~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Multi-Policy Agent의 메모리 효율화]]></title>
            <link>https://velog.io/@so_oni_on/Multi-Policy-Agent%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%ED%9A%A8%EC%9C%A8%ED%99%94</link>
            <guid>https://velog.io/@so_oni_on/Multi-Policy-Agent%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%ED%9A%A8%EC%9C%A8%ED%99%94</guid>
            <pubDate>Wed, 25 Feb 2026 15:00:58 GMT</pubDate>
            <description><![CDATA[<p>오늘의 포스트는 리뷰가 아닌 내 연구에 대한 기본적 초석을 다지기 위해 간략히 정리하는 노트이다.
요즘 에이전트 태스크를 여럿 peaking을 해봤는데 적용 가능 분야가 무궁무진하고, 연구 잠재성도 엄청난 것 같아 흥미롭게 살펴보고 있는 분야 중 하나이다.
최근 다양한 에이전트 태스크를 탐색하며 깨달은 것은, 에이전트는 단순히 명령을 수행하는 도구를 넘어 이제는 자율적인 의사결정 system으로 자리잡기 시작했다는 점이다.</p>
<p>특히 에이전트가 장기적인 태스크를 수행하기 위해서는 단순히 &#39;추론 능력&#39;이 좋은 것을 넘어, <strong>&#39;메모리&#39;를 얼마나 효율적으로 다루느냐</strong>가 아키텍쳐의 핵심이 된다.</p>
<p>따라서 오늘의 글은 에이전트 연구에 대한 근본적인 나의 문제점들과 나만의 해답, 
그리고 현재 호기심이 생긴 <strong>&#39;Multi-Policy 환경에서의 메모리 최적화 전략&#39;</strong>을 정리해보고자 한다.</p>
<hr>
<p>이를 위해서는 우선 Agent (에이전트) 환경에 대한 정의를 확실히 하고 넘어가야 할 것 같다.</p>
<h2 id="⚓️-들어가기에-앞서">⚓️ 들어가기에 앞서</h2>
<p>내가 처음 연구 분야에서의 &quot;에이전트&quot; 필드를 접할 때 들었던 의문점은 아래와 같다.</p>
<blockquote>
<ul>
<li><strong>MoE (Mixture of Experts)와 Agents의 차이점은 무엇인가?</strong></li>
</ul>
</blockquote>
<ul>
<li><strong>단순 API 호출로 배포된 모델의 지식을 사용하는 거라면, 
연구 논문을 낼 때 수많은 실험을 진행할텐데 그럼 API 사용료가 너무 많이 낭비되지 않나?</strong></li>
</ul>
<p>이 두 가지였다. 
특히, 자연어를 공부하는 나로서는 ACL 2025에도 Agent 연구가 수도 없이 많았으며, NeurIPS와 같은 CS의 제너럴한 분야를 모두 다루는 정상급 학회에서도 에이전트를 활용한 연구가 Accept 되었기에 더욱 궁금증이 생겼다.</p>
<p>러프한 공부를 통한 이 의문에 대한 나의 답변은 아래와 같이 정리할 수 있었다.</p>
<blockquote>
<h3 id="moe-vs-agents"><strong>MoE vs. Agents</strong></h3>
</blockquote>
<ul>
<li><strong><em>MoE</em>:</strong> 
모델 내부의 가중치 수준에서 Static Routing이 일어난다. 
<img src="https://velog.velcdn.com/images/so_oni_on/post/6642aa40-9807-4ac9-88ba-82510264b772/image.png" alt="">
$\to$ 이때, Static Routing이란?
입력 토큰이 들어오면 Gating 네트워크가 즉각적으로 어떤 Expert(FFN)에게 보낼지 결정한다. 즉, _아키텍처에 종속된 효율화 방식_이다.
조금 더 자세히 설명하자면, 입력 토큰 $x$가 들어오면, 이 토큰을 어떤 Expert에게 전달할지 결정하는 매우 작은 Linear Layer를 &#39;Router (Gating Network)&#39;라 부른다. 이는 보통 토큰에 대한 가중행렬값의 Top-K에 Softmax를 적용한 확률분포값이다.<blockquote>
<p>$$
G(x)=Softmax(TopK(x \cdot W_{gate}))
$$
이후, 우리가 흔히 아는 Transformer의 FFN 블록으로 보내져서 보통 GELU와 같은 활성화 함수와 Linear Layer로 구성되어 각 태스크에 Specialized된(가중치 학습된) Experts의 출력을 뽑을 수 있다.</p>
<p>$$
E_i(x)=\sigma(x W_{i, in}) W_{i, out}
$$
즉, 단순히 &#39;아키텍처 종속&#39;을 넘어, <strong>&quot;학습된 가중치가 고정된 상태에서 토큰의 특징값에 따라 기계적으로 분기된다.&quot;</strong> 추론 시점에 모델이 스스로 &quot;이번엔 다른 전문가를 써볼까?&quot;라고 &#39;의사결정&#39;을 하는 것이 아닌, 입력값에 따른 연산 결과이다.</p>
</blockquote>
</li>
<li>*<em><em>Agents</em>: *</em>
모델 외부의 시스템 수준에서 작동한다.
모델이 Action을 취하고, 환경(Environment)으로부터 Feedback을 받아 다음 행동을 결정하는 루프를 가진다. MoE가 &#39;누구에게 물어볼까&#39;를 고민한다면, 에이전트는 &#39;어떤 도구로 이 환경을 바꿀까&#39;를 고민한다.<blockquote>
</blockquote>
따라서 MoE가 모델 내부에 물리적으로 분리된 여러 가중치 집합(Experts) 중 최적의 연산 경로를 선택하는 &#39;내부적 최적화&#39;라면, 에이전트는 모델의 추론 능력을 엔진으로 삼아 외부 피드백 및 도구와 결합하여 최적의 행동 시퀀스를 설계하는 &#39;시스템적 지능&#39;이라 할 수 있다. 
<br>💡 추가로, 최근에는 여러 LLM Agents의 응답을 합성하는 <strong>&#39;Mixture of Agent (MoA)&#39;</strong> 연구도 활발하나, 이는 시스템적인 앙상블에 가까운 수준이다. 
에이전트 연구의 본질적인 내용은 단발성 응답을 넘어선 &#39;순차적 의사결정(Sequential Decision Making)&#39;을 통해, 환경의 변화에 유연하게 대응하며 목표를 달성하는 &#39;최적 전략(Policy)&#39; 확보에 있다.<blockquote>
<hr>
</blockquote>
<h3 id="연구에서의-api-비용과-연구의-학술적-가치에-대한-의문"><strong>연구에서의 API 비용과 연구의 학술적 가치에 대한 의문</strong></h3>
API 활용이 필수적인 해당 연구 분야의 연구 논문들을 읽어봤을 때, &#39;실험을 위해 많은 시도를 했을 것인데 돈이 깨나 많이 들었겠다..&#39;와 같은 생각을 한건.. 나만 한 생각이 아닐거라 믿는다. 또한 &#39;단순 API 호출 연구가 어떻게 정상급 학회에 갈까?&#39;라는 의문도 있었다.<br>
하지만, 최근 많은 SOTA 에이전트 연구 (e.g., Reflexion, Voyager) 논문을 읽어본 결과, 연구적 가치는 단순히 많은 성능좋은 모델들의 API 호출 및 사용에서 끝나는 것이 아닌 아래의 두 가지가 주요하게 작용하는 것 같다.</li>
<li><strong>호출을 유도하는 프롬프트 엔지니어링 및 논리 구조</strong></li>
<li><strong>피드백을 학습 데이터로 효과적으로 전환시키는 알고리즘</strong><blockquote>
<p>가령 <strong>Reflextion (Shinn et al., 2024)</strong>의 경우, 모델이 내놓은 결과에 대해 &#39;Self-Reflection&#39; 루프를 돌려, 실패 시 모델이 스스로 본인이 왜 틀렸는지를 Verbal Feedback을 하고, 이를 다음 시도의 Context로 삽입하여 성능을 비약적으로 높인 알고리즘을 제시했다. 
<strong>Voyager (Wang et al., 2023)</strong>의 경우, _Skill Library_라는 개념을 도입해, 마인크래프트와 같은 환경에서 수행한 성공적인 Action을 Vector DB에 저장했다가 유사한 상황이 오면 이를 다시 Retrival하여 학습 없이도 복잡한 태스크를 수행한 알고리즘을 제시했다.</p>
<p>특히 최근에는 LLaMA4나 Phi-4와 같은 고성능 Open-Weights 모델의 배포로, 로컬 서버에서도 높은 학회 수준의 연구가 가능한 것 같다.</p>
</blockquote>
</li>
</ul>
<hr>
<h2 id="💾-kv-cache-optimization-for-long-term-reasoning">💾 KV-Cache Optimization for Long-term Reasoning</h2>
<p>에이전트의 사고 과정(e.g., CoT)이 길어질수록 KV-Cache는 기하급수적으로 커질 것이다. 이를 해결하기 위해 아키텍처 차원에서의 접근이 필요하다.
해당 문제 해결을 위해 가장 쉽고 익숙하게 생각해낼 수 있는 것이 KV-Cache라 생각된다. </p>
<p>추론 과정에서 생성되는 모든 토큰은 완전히 동일한 가치를 가지지 않을 것이다. 가령 아무리 같은 토큰이어도 맥락과 세부적인 문장의 순서 등에 따라 가치가 변할 것이기 때문이다.</p>
<p>따라서 캐시 내부를 확인하며 동적으로 메모리를 Pruning하는 아래의 기법들이 주목할 만하다.</p>
<blockquote>
<h4 id="streamingllm-h2o">StreamingLLM, H2O</h4>
</blockquote>
<ul>
<li>*StreamingLLM (Xiao et al., 2023): *
&quot;Attention Sink&quot; 개념을 도입하여, 문장의 아주 초기 토큰들이 전체 어텐션 안정성에 기여도가 높음을 밝혀냈다.</li>
<li>*H2O (Zhang et al., 2024): *
누적 어텐션 스코어가 높은 Heavy Hitter 토큰들만 유지하고 나머지는 Eviction(제거)하여 캐시를 압축한다.</li>
</ul>
<blockquote>
<h4 id="snapkv-optimizing-kv-cache-for-long-content">SnapKV (Optimizing KV-Cache for Long Content)</h4>
<p>에이전트가 긴 문서를 읽을 때, Attention 맵의 클러스터링을 통해 &quot;중요한 정보가 밀집된 구간&quot;만 캐시에 남기고 나머지는 버리는 방식이다. H2O가 토큰 단위라면 해당 SnapKV는 특정 레이어와 헤드에 맞춰 더 정교하게 캐시를 압축하는 방식이다.</p>
</blockquote>
<p>혹은 실시간으로 KV-Cache 내의 중요도를 계산하는 기법도 존재한다. </p>
<blockquote>
<h4 id="quest-query-aware-kv-cache-pruning">Quest (Query-Aware KV-Cache Pruning)</h4>
<p>현재 들어온 Query에 따라 실시간으로 에이전트는 단계마다 목표를 바꿔야한다. 이는 이전 단계에서 중요했던 캐시는 현재 단계에서는 불필요한 정보가 될 수 있다는 뜻이다. 이를 동적으로 해결하기 위해 KV-Cache 내를 모니터링하며 Pruning하는 방식이다.</p>
</blockquote>
<p>특히, 강화학습 분야에 적용할 경우 Multi-Policy 환경에서는 각 정책이 중요하게 여기는 Features가 다르므로, 정책별 맞춤형 캐시 전략이 필수적일 것이다.</p>
<h2 id="📑-agent-memory-management--retrival-utility">📑 Agent Memory Management &amp; Retrival Utility</h2>
<p>단순히 &quot;DB에서 꺼내오는 것&quot;이 아닌, 다양한 에이전트가 제한된 Context Window를 어떻게 효율적으로 관리하는지 또한 관건이다. 따라서 이를 다루기 위한 &quot;시스템적 메모리 관리 기법&quot;이 존재한다.</p>
<p>이때 제일 먼저 생각이 든 기법은 Self-RAG였다.</p>
<blockquote>
<h4 id="self-rag-self-reflective-retrieval-asai-et-al-2024">Self-RAG (Self-Reflective Retrieval; Asai et al., 2024)</h4>
<p>무조건 검색을 하는 것이 아닌, &#39;모델이 스스로 &quot;지금 검색이 필요한 시기인지&quot;를 판별<code>IsRel 토큰 생성 등</code>하고, 검색된 결과의 신뢰도를 평가하는 방식이다.
이는 불필요한 Retrieval API 호출을 줄여 Latency와 비용을 낮췄다.</p>
</blockquote>
<hr>
<p>짧은 내용이지만 내 호기심에 대해 공통적으로 초석이 되는 위 내용들을 기반으로 내 생각을 좀 더 정리할 수 있었다.
결국 현재로서 내가 나아가야 할 방향은 &quot;멀티 정책 에이전트가 어떻게 하면 각자의 전략에 맞는 최적의 정보를 캐싱하고, 과거의 성공/실패 경험을 벡터 공간에서 효과적으로 인출하여 전략을 수정할 것인가?&quot;이다.</p>
<p>즉, 개별 모델의 내부적 연구와 더불어 앞으로 어떻게 이미 최고 성능을 보이는 모델의 API를 &quot;효율적으로&quot; 사용할지에 대한 고민 또한 계속 해봐야될 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[논문리뷰] Probing the Geometry of Truth: Consistency and Generalization of Truth
Directions in LLMs Across Logical Transformations and Question
Answering Tasks]]></title>
            <link>https://velog.io/@so_oni_on/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-Probing-the-Geometry-of-Truth-Consistency-and-Generalization-of-TruthDirections-in-LLMs-Across-Logical-Transformations-and-QuestionAnswering-Tasks</link>
            <guid>https://velog.io/@so_oni_on/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0-Probing-the-Geometry-of-Truth-Consistency-and-Generalization-of-TruthDirections-in-LLMs-Across-Logical-Transformations-and-QuestionAnswering-Tasks</guid>
            <pubDate>Mon, 12 Jan 2026 06:02:35 GMT</pubDate>
            <description><![CDATA[<p>요즘 Cross Lingual Generalization에도 관심이 생겨 가볍게 읽어본 논문이었는데, 가벼운 학습만으로 효과를 입증했고 심지어 LLM 학습이 아닌 회귀 분석? 수준의 머신러닝 학습만으로 ACL Findings에 기재된 논문이라는 점에서 흥미로워 가져와봤다. </p>
<p>우선 이를 위한 선행 연구인 &quot;The Geometry of Truth: Emergent Linear Structure in LLM Representations of True/False Datasets&quot;에 대해 설명하겠다. 해당 논문을 이해하면 오늘 포스팅에서 주되게 다루고자 하는 &quot;Probing the Geometry of Truth: Consistency and Generalization of Truth Directions in LLMs Across Logical Transformations and Question Answering Tasks&quot;를 정말 쉽게 이해할 수 있을 것이기에 조금 자세히 소개하도록 하겠다.</p>
<h2 id="the-geometry-of-truth-emergent-linear-structure-in-llm-representations-of-truefalse-datasets">The Geometry of Truth: Emergent Linear Structure in LLM Representations of True/False Datasets</h2>
<p><strong>Author: Samuel Marks, Max Tegmark</strong>
<strong>Accepted at COLM 2024</strong>
<a href="https://openreview.net/forum?id=aajyHYjjsk">https://openreview.net/forum?id=aajyHYjjsk</a>
(github: <a href="https://github.com/saprmarks/geometry-of-truth">https://github.com/saprmarks/geometry-of-truth</a>)</p>
<p>본 논문에서는 LLM이 좋은 능력을 가졌지만, 때로는 자신이 알고있는 사실과 다른 거짓 정보를 출력하는 &quot;환각 현상&quot;을 문제로 삼는다.
연구진들은 &#39;모델이 내부적으로 참과 거짓을 실제로 구분하고 있을까?/할 수 있을까?&#39;에 대해 의문을 제기하며 시작된다.
또한, 실제로 모델이 내부적으로 참과 거짓을 구분한다면, 그 정보는 어디에 어떤 형태로 저장되어 있을지를 규명하고자 한다.</p>
<p>연구진들은 노이즈를 줄이기위해 매우 단순하고 객관적인 데이터셋을 사용하여 실제로 모델이 참/거짓을 구분하는지, 그 떄의 Activation을 확인하고자 하였다.
실험에 사용된 데이터셋은 &#39;도시 위치&#39;, &#39;스페인어-영어 번역&#39;, &#39;숫자 크기 비교&#39;와 같은 단순하고 명확한 문제들을 대상으로 <strong>기본 사실</strong>과 <strong>논리 변환 과정</strong>, 그리고 <strong>비교군</strong>으로 구성되어있다.</p>
<ul>
<li><strong>기본 사실:</strong> <code>e.g., 파리는 프랑스에 있다. (cities), 2는 1보다 크다. (larger_than)</code></li>
<li><strong>논리 변환:</strong> 위 문장에 &#39;not&#39;을 붙인 부정문, 그리고 &#39;and&#39;나 &#39;or&#39;로 연결된 복합 문장
  <code>e.g., neg_cities, conj, disj</code></li>
<li><strong>비교군 (likely):</strong> 사실 여부와 관계없이 단순히 그럴듯한 문장들을 비교하여, 모델이 &#39;확률&#39;이 아닌 진짜 정답(진실)을 찾는지 검증. 문장의 확률값과 진실 여부가 강한 음의 상관관계를 가지는 문장을 의미한다.
  <code>e.g., &#39;Paris in not in...&#39;이라는 문장이 주어졌을 때, &#39;Paris&#39;와 &#39;France&#39;는 함께 있는 경우가 많았기에 관성적으로 France를 출력하고자 함. 하지만 이는 문장 전체를 고려하였을 때는 틀린 문장임.</code>
  이러한 관계성을 가진 문장을 뜻한다.</li>
</ul>
<p>이러한 데이터를 사용함으로써, 연구진들은 단순히 모델이 정답을 맞히는 능력을 측정하는 것을 넘어, 모델 내부에서 &#39;통합된 진실의 표현(Unified Representation of Truth)&#39;이 있는지를 확인하고자 하였다.</p>
<p>우선 연구진들은 모델의 레이어들과 토큰들 중 어디에 &quot;진실&quot; 정보가 저장되는지를 먼저 확인하고자 하였다. 
그래서 참인 문장의 내부 활성값을 거짓인 문장에 Patching해보며 모델의 답변이(TRUE/FALSE) 바뀌는 지점을 찾았다.
<img src="https://velog.velcdn.com/images/so_oni_on/post/39e7ef3a-a918-484b-938c-a620e9ab6292/image.png" alt="">
즉 Figure 2의 (a)그룹의 주어인 Chicago/Toronto에 대한 정보를 담는 초기 레이어는 유사한 확률비를 가진다. (b)그룹에서는 문장의 마지막 토큰과 마침표 위치의 중간 레이어로, 혼합된 색상을 확인할 수 있다. 이는 여기서 문장 전체의 진실 여부가 결정됨을 나타낸다. 즉 해당 그룹이 문장 전체의 진실성 정보를 저장하는 추상적인 상태로 가정되는 것이다. (c)그룹은 최종 출력을 결정하는 출력층 직전의 단계로, 모델의 예측을 직접적으로 인코딩하는 상태이다. 이 위치의 활성값에 디코딩 헤드를 적용하면 바로 &quot;TRUE&quot;, &quot;FALSE&quot;와 같은 토큰 Logit이 나타난다.
따라서 연구진들은 이후 모든 분석에서 (b)그룹의 활성값을 사용하여 진실 벡터를 연구하였다.</p>
<p>이후, 활성화된 레이어들을 기반으로 문장의 참/거짓을 구분한 결과를 PCA로 시각화하였을 때는 아래와 같은 결과를 얻을 수 있었다.</p>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/021e6ad9-d4ee-4cf5-b801-2d8398d08e2c/image.png" alt="">
<img src="https://velog.velcdn.com/images/so_oni_on/post/964042e1-312d-46aa-8969-4e19617fd572/image.png" alt="">
연구진들은 PCA(주성분 분석) 결과, 실제로 기하학적 유의미한 결과를 얻었다.
특히 Figure 3에서도 확인할 수 있듯, &quot;eighty&quot;라는 특정 단어의 포함 여부 등 표면적 특성에 따라 활성화 값이 뭉친 다른 소형 모델들과 다르게 70B의 모델 내부에서 참과 거짓 문장들이 매우 명확히 구분된 것을 확인할 수 있다. 이는 모델이 커지면서 더욱 추상화를 잘 함을 뜻한다. (70B 모델의 모든 fields의 데이터셋에 대한 PCA 결과는 figure 1에서 확인할 수 있다.)
또한 초기 레이어에서는 긍정문과 부정문이 반대로 정렬되다가, 레이어가 진행될수록 추상화가 진행되며 하나의 진실 축으로 합쳐지는 경향을 확인할 수 있었다.
이는 모델의 고차원 활성화 공간 안에서 &#39;진실&#39;로 향하는 특정 벡터 방향이 존재함을 뜻한다. 즉, 모델은 단순히 언어의 통계학적 확률을 계산하는 게 아닌, &#39;참/거짓&#39;의 개념을 기하학적인 위치로 구분하고 있음을 시인한다.</p>
<p>연구진들은 이와같이 모델이 내부적으로 참/거짓이 나눠지는 것을 확인한 뒤, <strong>Mass-Mean Probing</strong> 기법을 적용하였다. 기존의 로지스틱 회귀 때는 다른 Features로 인한 간섭 때문에 &#39;진실&#39; 방향을 정확히 찾지 못할 때가 많으나, 본 기법을 적용함으로써 단순히 참인 문장들의 평균 위치(Centroid)와 거짓인 문장들의 Centroid를 통해 방향 벡터 $\theta_{mm}$를 구하는 방식이다. LR은 두 데이터를 가장 잘 나누는 경계면을 찾으려다보니, 진실과 상관없지만 참/거짓 데이터 사이에 우연히 섞여있는 다른 특징의 간섭을 받게된다. 반면 MM Probing은 단순 Centroid의 차를 활용하기에 이러한 간섭에 더욱 강하고 모델의 출력에 더 직접적인 원인이 되는 방향을 찾는다.
<img src="https://velog.velcdn.com/images/so_oni_on/post/b7e1bbfa-2980-49d2-a77b-7d595128dcdc/image.png" alt="">
이는 복잡한 최적화 과정이 필요 없으면서도, 모델의 내부 의사 결정에 더 Causal한 영향을 주는 방향을 정확히 찾아내는 방법이다. </p>
<p>주요 실험 결과는 다음과 같다:
<img src="https://velog.velcdn.com/images/so_oni_on/post/3c804ccc-4801-4917-a8b6-fcf42cb374a1/image.png" alt="">
본 표는 NIE(Normalized Indirect Effect, 정규화된 간접 효과)라는 지표를 제시한다. 이는 모델의 내부 활성값에 우리가 찾은 진실 벡터를 더하거나 뺐을 때, 모델의 최종 답변이 얼마나 바뀌었는지를 수치화한 표이다. 범위는 확률 값이 아닌, 평균적인 확신의 강도를 비교한 상대적인 비율을 나타낸다. 이때 0은 개입이 전혀 효과 없었음을 의미하고, 1은 진실 벡터 개입만으로 모델이 판단한 참/거짓 방향을 바꾸게 된 것을 의미한다. NIE가 계산되는 방식은 아래와 같다.</p>
<p>$NIE=\frac{개입 후 변화량}{평소 참/거짓의 평균적 확신의 차이}$
따라서, 만약 NIE가 1.00이라면 개입을 통해 모델이 느끼는 확신이 정상적인 참 문장을 볼 때의 평균값과 똑같아졌다는 뜻이다. </p>
<p>각 train dataset에 대해 probe 방식에 따른 수치가 기재되어있다. 여기서 인상깊은 점은 LR의 NIE가 MM에 비해 낮게 나타나는 경우가 많다는 점이다. 이 이뉴는 앞서 언급한 것과 같이 LR은 단순히 참/거짓 데이터셋을 가장 잘 나누는 벽을 찾을 뿐이며, 그래서 진실과 상관없이 데이터셋에 섞여 있는 다른 특징을 진실로 오해하여 벡터를 생성할 확률이 높기 때문일 것이라 주장한다. 반면 MM Probing은 평균값의 차이를 이용해 진실이라는 핵심 특징의 centroid를 활용하기 때문에 모델의 이성적(?) 판단에 더욱 직접적인 영향을 줄 것이라 해석한다. </p>
<p>특히 흥미로운 부분은 연구진들이 세운 가설에 대해 <strong>대표적으로 증명이 가능한 사례</strong>가 있었다는 점이다.
앞서 살펴본 Likely 문장들에 대해, 만약 모델이 단순 확률값에 의해 출력을 낸다면 무수히 접했을 &#39;Paris&#39;와 &#39;France&#39;가 함께 있는 문장에 대해서 확률이 높은 문장은 모델 내부에서 무조건 &#39;참&#39;인 것처럼 보여야 할 것이다. 하지만 실제 실험 결과에서는 앞서 제시한 예시와 같이 &#39;Paris is not in....&#39;와 같이 관성적 특징에 의하여 문장이 특정 단어로 완성될 확률은 매우 높지만, 실제로 거짓인 likely 문장들을 대상으로 조사해본 결과, 모델 내부의 진실 벡터는 정확히 거짓을 가리키고 있었다. 문장의 확률과 진실 벡터 사이의 상관계수가 -0.63<del>-0.89 사이로 나타난 것을 보아, 이는 확률과 진실이 서로 반대 방향으로 움직임을 수치적으로 증명한 셈이다.
~</del>알고보면... 모델은 자기가 거짓말을 한다는 것도.. 다 인지할지도.....~~</p>
<p>이러한 결과들로 본 연구진은 가설 및 실험 결과를 아래와 같이 해석한다:</p>
<ul>
<li><strong>Emergent Property</strong>
위의 결과와 같은 명확한 &#39;진실의 직선&#39; 구조는 모델의 크기가 커질수록 더 또렷하게 나타나며, 모델이 똑똑해질수록 &quot;진실&quot;이라는 추상적인 개념을 잘 형성함을 확인할 수 있었다.</li>
<li><strong>Transferability</strong>
다양한 데이터셋을 변형한 결과에서도 실제로 올바른 정답 벡터를 출력하였다. 이는 모델이 특정 주제에 국한되지 않은 범용적인 진실 탐지기를 내부적으로 가지고 있음을 시사한다.</li>
<li><strong>Causal Intervention</strong>
&quot;2+2=5&quot;라는 문장을 처리할 때, 보통은 너무 단순한 문제이기 때문에 모델이 틀릴 확률이 거의 없는 것으로 가정하였다. 하지만 모델 내부의 &#39;진실 방향&#39; 값을 연구진들이 인위적으로 개입하여 직접 올렸을 때, 모델은 평소대로라면 거짓이라고 판단했을 문장을 진실로 믿고 답변하기 시작했으며, 이는 연구진들이 가설을 세우고 주장한 &quot;진실 방향&quot;이 모델의 판단에 직접적인 영향을 준다는 것을 증명하였다.</li>
</ul>
<p>따라서 본 연구진들은 모델이 내부적으로 가설이나 Input이 거짓임을 알아챌지언정, 거짓을 진술하는 경우가 있기 때문에 이를 해결하기 위해 내부적으로 &#39;Mass-Mean Probing&#39; 기법으로 추출한 기하학적인 근거인 참/거짓 방향 벡터를 참고하여 실제 판단 근거에 도움을 받는 것을 가능하도록 하였다.</p>
<hr>
<h2 id="probing-the-geometry-of-truth-consistency-and-generalization-of-truth-directions-in-llms-across-logical-transformations-and-question-answering-tasks">Probing the Geometry of Truth: Consistency and Generalization of Truth Directions in LLMs Across Logical Transformations and Question Answering Tasks</h2>
<p><strong>Author: Yuntai Bao, Xuhong Zhang, Tianyu Du, Xinkui Zhao, Zhengwen Feng, Hao Peng, Jianwei Yin</strong>
<strong>Accepted at ACL 2024 Findings</strong>
<a href="https://aclanthology.org/2025.findings-acl.38/">https://aclanthology.org/2025.findings-acl.38/</a>
(github: <a href="https://github.com/colored-dye/truthfulness_probe_generalization">https://github.com/colored-dye/truthfulness_probe_generalization</a>)</p>
<p>해당 논문은 앞서 살펴본 Marks &amp; Tegmark의 기초적인 이론을 더 복잡한 추론 환경에 적용할 때 마주하게 되는 실현 가능성의 한계를 극복하고자 하였다. 앞의 논문을 이해하였다면, 더 나아가 본 논문을 읽을 때는 아래의 4가지 포인트들을 주되게 살펴보아야한다.
앞의 논문 Marks &amp; Tegmark의 논문과 본 논문을 계속 비교할 예정이기에, 이하 &#39;선행 연구&#39;로 대체하겠다. 앞으로 언급되는 &#39;선행 연구&#39;는 모두 Marks &amp; Tegmark의 <strong><em>&#39;The Geometry of Truth: Emergent Linear Structure in LLM Representations of True/False Datasets&#39;</em></strong>을 일컫는다.</p>
<p><strong>1. 논리적 일관성</strong>
앞서 선행 연구는 부정문을 넣었을 때, 레이어에 따라 진실 벡터가 Orthogonal하거나 반대 방향으로 회전하는 현상을 발견하였다. 이를 심화시켜 본 논문에서는 단순히 not을 붙힌 수준의 단순 부정이아닌 &#39;A가 B가 아니란 것은 거짓이다.&#39;와 같은 이중 부정이나 보다 다양한 논리적 변형을 주었을 때, 모델 내부의 진실 나침반이 흔들리지 않고 일관된 방향을 가리키는지 확인한다.
더 나아가, 기존 연구들이 Parametric Knowledge에 집중했다면, 본 연구는 Contextual Knowledge와 복잡한 논리 구조에서의 일반화까지 다룬다.</p>
<p><strong>2. 단순 구문에서 태스크로의 확장 (Statement $\to$ QA)</strong>
선행 연구는 단순 구문에 대한 학습 및 테스트를 진행하였다. 자주 나온 예시인 &quot;파리는 프랑스에 있다&quot;와 같은 평서문(Statement)가 그 예시이다. 본 논문은 실제 사용자가 &quot;파리는 프랑스에 있나요?&quot;와 같은 실질적 질문을 던졌을 때, 평서문 데이터셋으로 학습시킨 진실 탐지기(Probe)가 QA 태스크에서도 답변의 진실성을 정확히 판별할 수 있는지를 Zero-shot Generalization을 중점적으로 다룬다.</p>
<p><strong>3. 모델 간의 범용성 (Cross-Model Generalization)</strong>
선행 연구보다 훨씬 다양한 모델 종류를 도입시켜 서로 다른 아키텍쳐와 학습 데이터를 가진 모델들 사이에서도 &#39;Geometric Structure of Truth&#39;가 공통적으로 나타나는지를 확인하고자 하였다. 따라서 만약 범모델적으로 공통된 진실 벡터가 존재한다면, 본 접근법은 어떤 모델에나 적용할 수 있는 범용적 AI 진실 탐지를 할 수 있기 때문이다.</p>
<p><strong>4. 강건성 및 아첨 현상 규명</strong>
실제로 사용자가 &quot;파리는 이집트에 있어. 그렇지?&quot;와 같은 진실 요구에 편향된 질문을 던졌을 때, 모델은 겉으로 사용자의 말에 동의하는 경향이 관찰되어왔다. 이런 경우, 내부의 진실 벡터가 실제로 어떤 벡터를 가리키는지 규명하고자 한다.</p>
<hr>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/7b13957f-60f0-4ce2-9671-9b7ac8efbeb7/image.png" alt=""></p>
<p>본 연구는 선행 연구와 유사하나, 더욱 넓은 범위에서의 학습 및 테스트를 진행하는 것이 차이점이다. </p>
<h3 id="a-summary-of-probes-and-data-논문의-3절">A. Summary of Probes and Data (논문의 3절)</h3>
<p>본 논문에서 사용하는 이진 프로브의 정식화는 다음과 같다. 모델의 $l$번째 레이어, 마지막 토큰 위치의 representation인 $h_{-1}^{(l)}$를 사용한다. 이는 Causal Attention의 효과로 이전의 모든 정보를 함축하고 있기 때문에 가능하다.</p>
<blockquote>
<h4 id="프로브의-종류">프로브의 종류</h4>
<p><strong>1. Geometry-oriented Probe:</strong> 진실 방향 가설에 기반하여 초평면을 찾는다.
&ensp;&ensp;&ensp; - SVM (Support Vector Machine): 마진을 최대화하는 방식으로 분리벽을 찾음
&ensp;&ensp;&ensp; - MM (Mass-Mean): 참/거짓 활성화 값의 평균 차이를 방향으로 사용
<strong>2. Statistics-based Probe:</strong> 기하학 구조와 무관하게 정답 확률을 극대화한다.
&ensp;&ensp;&ensp; - LR (Logistic Regression): 가장 일반적인 베이스라인
&ensp;&ensp;&ensp; - MLP (Multi-Layer Perceptron): 비선형 방식</p>
</blockquote>
<h3 id="b-experiments">B. Experiments</h3>
<h4 id="b1-레이어-선택-layer-selection">B.1 레이어 선택 (Layer Selection)</h4>
<ul>
<li>_클래스 간 분산($S_B$)_을 _클래스 내 분산($S_W$)_으로 나눈 비율이 가장 높은 레이어를 최적의 레이어로 선택<blockquote>
<p>해당 방식은 통계학에서 사용되는 분별력의 지표로, 어느 레이어에서 참과 거짓이 제일 안섞였는지를 찾는 수학적 기준이라 함!</p>
<ul>
<li><strong>클래스 간 분산 (Between-class Variance, $S_B$)</strong>
참인 문장들의 Centroid (중심점, 평균 위치)와 거짓인 문장들의 Centroid가 얼마나 멀리 떨어져 있는가를 나타냄. 이 값이 클수록 두 집단은 서로 멀리 있는 것임.</li>
<li><strong>클래스 내 분산 (Within-class Variance, $S_W$)</strong>
참 혹은 거짓인 각자의 데이터들끼리 얼마나 뭉쳐있는지를 나타냄. 이 값이 작을수록 집단 내부가 흩어지지 않고 조밀하게 모여있음을 뜻함.</li>
</ul>
<hr>
<p>따라서 $\frac{S_B}{S_W}$을 하여 비율을 구함으로써, 단순히 클래스 간의 분산만 커서는(멀리 떨어져서는) 내부적인 응집력이 없을 경우엔 좋은 분리 결과물을 낸 레이어가 아니므로 &#39;각자 클래스끼리의 응집력이 좋으면서도 서로 간의 클래스가 뚜렷하게 구분되도록&#39; 판별한 레이어를 찾고자 함.
&ensp;&ensp;&ensp; <strong>$\to$</strong> 모든 레이어에 대해 Probe를 만들면 자원이 너무 많이 들기 때문에 분산 비율 분석을 통해 이미 뚜렷하게 잘 나눠지는 레이어에 대해서만 활성화값을 집중적으로 탐구하기 위함임.</p>
</blockquote>
</li>
<li>A실험 결과, Llama-3.1-8B의 경우 12번 레이어가 최적으로 나타났다고 한다. 반명 7B 이하의 Llama 모델에서는 특정 도메인에만 피크가 나타나는 등의 일관성 부족 문제가 있었다고 한다.
<img src="https://velog.velcdn.com/images/so_oni_on/post/3f0e9211-5ebc-434b-a2cd-b7faeab3dba3/image.png" alt=""></li>
</ul>
<h4 id="b2-무작위-모델-실험">B.2 무작위 모델 실험</h4>
<p>저자들은 본 절에서 &quot;앞선 과정에서 찾은 진실 벡터가 실제로 모델 내부에 위치한건지, 혹은 Probe가 생성해낸 것인지&quot;를 규명하고자 하였다. 이를 위해 Llama-3.1-8B 모델을 두 가지 버전으로 준비하였다. </p>
<ul>
<li>Pretrained (사전 학습된 모델): 수많은 텍스트로 &quot;진실&quot;의 개념을 학습한 모델</li>
<li>Randomized (무작위 초기화 모델): 가중치를 무작위로 섞어, 지능이 보장되지 않은 모델
이 두 모델의 12번 레이어에서 활성값을 뽑아 동일한 프로브(LR, MLP, MM, SVM)를 각각 적용하였다.</li>
</ul>
<p>이때 Probe의 성능을 AUROC로 측정하였는데, 사전 학습 모델의 경우 모든 Probe에서 1.0을 기록한 것으로 보아 모델이 참/거짓을 완벽히 분리함을 뒷받침하였으며, 가중치를 무작위로 초기화한 모델에서는 AUROC가 0.5 근처로 나왔다고 한다. 이는 진실 방향이 프로브가 억지로 생성한 것이 아닌, 모델의 사전 학습 과정에서 자연스럽게 형성된 구조임을 증명한다.</p>
<p>본 과정에서 사용한 Probe 지표인 AUROC에 대한 설명은 다음과 같다. </p>
<ul>
<li>*<em>AUROC *</em>
모델이 참인 데이터를 거짓인 데이터보다 더 높은 확률로 판단하는지를 측정하는 지표이다.</li>
</ul>
<p>0.5면 무작위 추측과 같고, 1.0에 가까울수록 모델이 참과 거짓을 완벽하게 가린다는 뜻이다.</p>
<blockquote>
<p>이때, AUROC와 AUPRC가 내게는 생소했기에 개념적으로 헷갈렸었다.
두 지표의 가장 큰 차이는 클래스 불균형에 얼마나 예민한가에 따라 나뉜다.</p>
</blockquote>
<ul>
<li><strong>AUROC</strong>
False Positive외 반응과 True Positiv의 균형을 보고, 클래스 비율이 변해도 점수가 잘 안변하는 불변성이 특징이라고 한다.
클래스 비율이 비슷하거나 모델의 전반적인 분류 능력 자체가 궁금할 때 사용하는 지표라고 한다.</li>
<li><strong>AUPRC</strong>
Precision($$)과 Recall($$)을 고려한다. 즉, 데이터가 희소한 경우, 희소한 클래스가 얼마나 잘 찾아내는지 훨씬 엄격하게 평가하기 위함이라고 한다. 따라서 희소한 데이터를 다룰 때 주되게 사용한다고 한다.<blockquote>
<h4 id="💡-그렇다면-왜-본-논문은-auroc를-사용했을까">💡 그렇다면 왜 본 논문은 AUROC를 사용했을까?</h4>
<p>본 연구에서 사용한 데이터셋은 연구진들이 의도적으로 참/거짓 비율을 1:1로 맞춘 데이터였다. 가령 긍정문이 있으면 그에 대응하는 부정문을 세트로 만들어 레이블을 반전시켰기 때문이다.</p>
</blockquote>
<figure><img src="https://velog.velcdn.com/images/so_oni_on/post/1667cac4-746b-4df3-b0e2-a65724437606/image.png" width="50%"><img src="https://velog.velcdn.com/images/so_oni_on/post/e90fb422-d5d2-4b2f-918c-967110bd6e8c/image.png" width="30%"></figure>
>
> 또한, 본 논문은 "희귀한 클래스를 탐지하고자"하는 것이 목적이 아닌, "모델 내부에서 참/거짓의 기하학적 특징 탐지"를 확인하고자 하였기에 threshold가 상관 없이 두 집단이 얼마나 잘 분리되는지를 측정할 수 있는 AUROC를 쓴 것으로 해석할 수 있다. 

</li>
</ul>
<h4 id="c-진실-방향의-일관성-부정문-일반화">C. 진실 방향의 일관성 (부정문 일반화)</h4>
<p>긍정문으로 Probes를 학습시킨 이후, 동일한 지식의 부정문에서도 테스트한 결과, 모델의 자체 성능이 높을수록 일반화 성능이 비례하게 상승함을 확인할 수 있었다.<img src="https://velog.velcdn.com/images/so_oni_on/post/89dc6d94-c92b-450e-8fc7-ee9675554481/image.png" alt="">
또한, 저자들이 사용한 단순한 선형 Probes가 모델 내부에 실제로 존재하는 정보를 Faithful Reflection하고 있음을 증명할 수 있었다. 이때 Zhou et al. (2024)의 &#39;Weak-to-Strong Explanation&#39;을 차용했는데, 이는 보통 똑똑한 모델의 내부를 읽으려면 아주 복잡한 도구가 필요할 것 같지만, 실제 실험 결과 선형 회귀나 SVM와 같은 단순한 프로브가 모델의 참/거짓을 잘 구분해내었다고 한다. 이는 모델이 이미 내부적으로 참/거짓을 직선 하나만으로 구분할 수 있을만큼 명확히 구분함을 시인하는 개념적 정립이다.
따라서 본 저자들이 직접 실험해보았을 때도 Llama-2-7B 모델보다 Llama-3.1-70B-Instruct 모델에서 훨씬 더 일반화된 좋은 성능을 낸 것으로 보아, 모델이 똑똑해질수록 실제로 진실의 개념이 더 일관되게 정리된다는 것을 증명하였다. </p>
<h4 id="d-이진-논리-변환">D. 이진 논리 변환</h4>
<p>또한 본 연구에서는 합성문 일반화 검증 과정도 거쳤는데, Atomic Statement로 학습한 프로브가 &#39;and&#39;나 &#39;or&#39;로 연결된 복합문의 참/거짓도 잘 맞춘 것을 확인하였다. 
(다만 Llama-3.1-8B의 경우, &#39;and&#39;보다 &#39;or&#39;의 진실성을 해석하는 데에 더 큰 어려움을 겪는 경향이 포착되었음을 밝혔다.)</p>
<h4 id="e-질의응답">E. 질의응답</h4>
<p>이후 사실적 평서문들로만 학습된 Probes를 MMLU(전문 지식)와 TriviaQA(상식)에 적용하여 단일 Statement 구조에서 더 확장되어 &#39;대답&#39;을 만들어야되는 질의응답 태스크까지도 이 Probe의 적용이 유효한지 검증하고자 하였다. 
결과적으로 Few-shot 예시가 주어질수록 정확도가 향상되었으며, 예시가 틀린 내용이더라도 Probe의 판단 성능은 크게 저하되지 않았음을 Figure 5, 6을 통해 설명한다. 
이때 </p>
<ul>
<li>Zero-shot: 예시 없이 바로 질문한 경우</li>
<li>TTTTT: 5개의 정답 예시를 포함</li>
<li>TTFFF: 2개의 정답과 3개의 오답을 의도적으로 섞어 Probe가 혼란스러운 문맥 속에서 얼마나 강건하게 진실을 탐지하는지 확인하기 위함
<img src="https://velog.velcdn.com/images/so_oni_on/post/641cfed9-c09e-4925-9364-52b228ff201c/image.png" alt="">
<img src="https://velog.velcdn.com/images/so_oni_on/post/08096dbf-fbde-49ef-b86a-eb56a91bcafb/image.png" alt="">
이는 Probes가 문맥 전체의 참/거짓보다 최종 질문-답변 쌍의 진실성에 집중한다고 해석된다. 특히 SVM Probe가 가장 우수한 Callibration 성능을 보였다.</li>
</ul>
<p>이때 사용한 지표는 아래의 세 지표이다.</p>
<ul>
<li><strong>AUROC (Area Under ROC Curve)</strong></li>
<li><strong>Expected Calibration Error (ECE)</strong>
  $ECE=\frac{1}{N}\sum_{i=1}^{N}|y_i-x_i|$
  모델이 내뱉는 확률값이 실제 정확도와 얼마나 일치하는지를 측정하는 지표이다.
  데이터를 예측 확신도(Confidence)에 따라 10개의 Bins로 나눈 후, 각 구간 내의 평균 확신도와 Accuracy의 차이를 계산하는 방식으로 측정한다. 이후 각 구간 내의 평균 확신도와 실제 Accuracy의 차이를 계산한 후, 이 차이들의 MAE를 구하는 것이 최종 지표이다.
  <code>가령, 모델이 어떤 답변에 대해 90% 확률로 참이라는 답변을 했다면, 실제로 그 답변들 중 90%가 정답이어야 좋은 모델이다. 값이 0에 가까울수록 모델이 자신의 실력을 과신/과소평가 하지 않고 정직하게 표현함을 뜻한다. (Lower is Preferred)</code></li>
<li><strong>Brier Score (BS)</strong>
  $BS=\frac{1}{N}\sum_{i=1}^{N}(p_i-y_1)^2$
  정확도와 Calibration 성능을 모두 담고 있는 지표로, {(예측 확률)-(실제 레이블)}^2의 평균이다.
  가령 정답이 1(True)인데 모델이 0.9라 예측했다면 MSE는 $(1-0.9)^2=0.01$이지만, $0.1$으로 예측했다면 $(1-0.1)^2=0.81$로 보다 큰 페널티를 받게된다. 따라서 이진 환경에서의 baseline 지표는 아무런 지식 없이 무조건 $0.5$라 대답하는 모델의 BS는 $0.25$가 된다. 
  <del>즉, 최소!! 0.5는 넘어야 본인의 답변에 대한 확신을 갖는다고 해석할 수 있다.</del>
  <code>따라서 본 지표 또한 낮을수록 모델이 정답에 가까운 높은 확률을 부여했다는 의미로, 예측의 품질이 높음을 의미한다. (Lower is Preferred)</code></li>
</ul>
<h4 id="f-문맥적-지식">F. 문맥적 지식</h4>
<p>모델의 Parametic 지식이 아닌, 주어진 본문 내용에 기반한 참/거짓도 프로브가 탐지할 수 있음을 확인한다. 이는 Probe가 &#39;사실 관계&#39;뿐만 아니라 &#39;문맥적 충실성&#39;까지 일반화할 수 있음을 시사한다.
이는 두 가지 주요 태스크를 대상으로 진행하였다.</p>
<ul>
<li>In-context QA: SciQ 및 BoolQ 데이터셋</li>
<li>Abstractive Summarization: XSum 데이터셋과 할루시네이션 주석 데이터를 사용하여 본문과 맞지 않는 오답 요약을 구분하도록 하였다.</li>
</ul>
<p>이때 각 데이터셋에 대한 few-shot 개수나 설정은 모두 상이하였다. (너무 다양해서 자세한 내용은 논문 참고)</p>
<p>본 저자들은 해당 실험 검증을 통해 단순히 사실적 평서문으로 학습된 Probe가 문맥 기반 QA와 요약 태스크에서도 진실 여부를 잘 구별할 수 있는 <strong>&#39;일반화 성능&#39;</strong>을 검증하였다. 더 나아가 이는 진실성의 기하학적 구조가 기억이나 문맥과 같은 지식의 출처와 관계없이 일관되게 나타남을 시사한다.
다만, 일부 데이터셋에서는 few-shot 예시를 주면 정확도는 올라가지만 ECE 성능은 오히려 나빠지는 현상을 관찰할 수 있었다고 한다. 연구진들은 이를 Probe가 자신의 예측을 Overconfidence하기 때문이라 분석하였다. </p>
<h4 id="g-선택적-질의-응답">G. 선택적 질의 응답</h4>
<p>최종적으로, 연구진들은 앞선 실험들을 통해 평서문으로 학습된 Probes도 QA Tasks에서 높은 정확도와 보정 성능을 보이는 것을 확인할 수 있었으며, 이를 바탕으로 모델이 생성한 여러 개의 답변 후보 중 정답만 골라내는 &quot;Filtering&quot;을 할 수 있을지 마지막 검증을 진행하고자 하였다.
이는 Kadavath et al. (2022)의 연구와 유사하나, 해당 연구에서 진행한 &#39;언어적 피드백&#39; 대신, &#39;모델 내부의 활성화 값(Internal Representations)&#39;를 직접 사용한다는 점에서 근본적으로 차별성이 있다. 이를 위해 Llama-3.1-8B 모델과 TriviaQA를 활용하여, 각 질문에 대해 Unit Temperature를 설정하고 20개의 답변들을 샘플링하였다. 
Probe는 앞선 실험 과정 중 제일 분류 정확도와 보정 성능이 뛰어났던 SVM를 활용하였으며, Probe가 해당 답변을 True라고 예측할 확률이 $50% (P&gt;0.5)$를 넘는 경우에만 최종 답변 후보로 선택하도록 설계하였다. 
<img src="https://velog.velcdn.com/images/so_oni_on/post/1cc1bf8b-52a5-4681-b3b1-418794026ca5/image.png" alt="">
실험 결과, Probe를 이용한 필터링이 모델의 최종 성능을 유의미하게 향상시켰음을 확인할 수 있다. Pass@20의 정확도는 $55.29%$에 불과하였지만, 필터링 후 정확도는 $64.06%$로 약 $9%p$가 향상한 것을 확인할 수 있었다. 이때 Probe의 &#39;True&#39; 분류 비율은 $80.26%$이었다.
이는 아무런 조치 없이 답변을 냈을 때보다 내부적으로 Probe를 거쳤을 때 정답률이 오른 것으로 보아, Truthness Probe가 LLM에서 샘플링된 답변 중 거짓 답변을 효과적으로 필터링하는 도구로 활용될 수 있음을 시사한다.</p>
<h3 id="c-conclusion">C. Conclusion</h3>
<p>결론적으로, 본 연구는 LLM 내부의 진실 표현에 대한 주요 증거를 제시하며 마무리된다.</p>
<ul>
<li><p><strong>지능과 진실의 관계성</strong>
실험 초반에서 PCA를 통해 보인 Truth Direction은 지능이 낮은 모델이 아닌, 충분히 능력있는 LLM에서 눈에 띄게 관찰됨을 확인하였다.</p>
</li>
<li><p><strong>단순한 선형 도구의 활용</strong>
위와 같은 진실성의 방향은 복잡한 알고리즘 없이도 Simple Linear Probes를 통해 효과적으로 식별될 수 있다.</p>
</li>
<li><p><strong>강력한 일반화 성능</strong>
Atomic Statement 만으로 학습된 Probe가 논리적 변환, Few-shot 질의 응답, 문맥적 진실성 등 다양한 영역으로도 일반화가 잘 이루어졌음을 입증한다.</p>
</li>
<li><p><strong>잠재 지식 인출</strong>
단순한 Anchor Data 만으로도 모델 내부의 진실 방향을 찾을 수 있다는 점은 LLM 내부에 숨겨진 Latent Knowlege를 끌어내는 데 큰 가능성을 시사한다.</p>
</li>
</ul>
<p>또한, 앞서 소개한 세 주요 지표를 사용함으로써 위 네 가지의 시사점을 뒷받침하기 위해 AUROC로 모델의 &#39;판별력&#39;을 평가하며, ECE와 BS로 그 판별력을 바탕으로 도출된 확률값이 실제 적용에서 얼마나 Reliable한지 검증하고자 사용한 것으로 해석된다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL기초] Softmax의 성질과 관련된 마스크 행렬의 덧셈]]></title>
            <link>https://velog.io/@so_oni_on/DL%EA%B8%B0%EC%B4%88-Softmax%EC%9D%98-%EC%84%B1%EC%A7%88%EA%B3%BC-%EA%B4%80%EB%A0%A8%EB%90%9C-%EB%A7%88%EC%8A%A4%ED%81%AC-%ED%96%89%EB%A0%AC%EC%9D%98-%EB%8D%A7%EC%85%88</link>
            <guid>https://velog.io/@so_oni_on/DL%EA%B8%B0%EC%B4%88-Softmax%EC%9D%98-%EC%84%B1%EC%A7%88%EA%B3%BC-%EA%B4%80%EB%A0%A8%EB%90%9C-%EB%A7%88%EC%8A%A4%ED%81%AC-%ED%96%89%EB%A0%AC%EC%9D%98-%EB%8D%A7%EC%85%88</guid>
            <pubDate>Mon, 13 Oct 2025 05:11:49 GMT</pubDate>
            <description><![CDATA[<p>들어가기에 앞서, 기본적인 어텐션 연산에 대한 설명은 해당 포스트에서 하지 않겠다!
대신... 공부를 하다가 간과했던 부분이 알고보니 꽤 재밌는 내용이어서 가지고 왔다! 사실 제발 아무도 안봤으면 좋겠다. 지금 당장은 글로 정리가 좀 덜된 것 같아서 부끄럽슨.. </p>
<p>...</p>
<p>이어가겠기니?</p>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/7fcab87e-1024-45b2-b7ef-50d2140932e7/image.png" alt=""></p>
<p>기본적인 Attention 연산의 식은 다음과 같다:<img src="https://velog.velcdn.com/images/so_oni_on/post/ceac2d94-33c3-4ccd-9c4c-3ddaa0465e21/image.png" alt="">
이때,</p>
<ul>
<li><p><strong>$QK^T$: Attention Score</strong></p>
<ul>
<li><strong>shape: $(B, L_Q, L_K)$</strong>
두 시퀀스 사이의 연관도  </li>
</ul>
</li>
<li><p><strong>$softmax(\frac{QK^T}{\sqrt{d_k}}+M)$: Attention Weight</strong></p>
<ul>
<li><strong>shape: $(B, L_Q, L_K)$</strong>
어텐션 스코어의 확률적 분포
이때, <code>[PAD]</code>토큰이 있는 경우나 Causal하게 다음 토큰을 예측하도록 할 경우, 이를 마스크 처리를 해야된다. 그 마스크에 대한 정보가 $M$에 담겨져있다. 아래서 더 자세히 설명하겠다.</li>
</ul>
</li>
<li><p><strong>$softmax(\frac{QK^T}{\sqrt{d_k}}+M)V$: Attention Output</strong></p>
<ul>
<li><strong>shape: $(B, L_Q, d_v)$</strong>
최종적인 어텐션 스코어의 행렬. 이때 $d_v$열에는 Key와 Value의 압축된 정보가 포함되어 있다.</li>
</ul>
</li>
</ul>
<p>이렇게 두 개의 시퀀스의 연관도를 측정하는 Attention 연산이 진행된다.</p>
<p>오늘 이야기할 내용은 특히 $Attention~ Weight$를 계산할 때 <code>[PAD]</code>토큰이나 Causal 마스킹 처리를 할 때 어떻게 마스킹 행렬을 적용하고, 연산이 되는지에 대한 내용이다.</p>
<hr>
<p>기본적으로 Mask 행렬은 아래와 같은 형식이다. 이 행렬은 하나씩 $-\infin$이 줄어드는 것과 마지막 행의 마스크 값이 모두 0인 것으로 보아, Causal Masking에 대한 예시이다.</p>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/18228120-620f-46cb-9e66-33609e8c9821/image.png" alt=""> [출처] <a href="https://gmongaras.medium.com/how-do-self-attention-masks-work-72ed9382510f">https://gmongaras.medium.com/how-do-self-attention-masks-work-72ed9382510f</a></p>
<p>$Attention~Weight$ 식에서도 알 수 있듯, 우리는 Scale된 Attention Score에 해당 Mask 행렬을 더한 후, 확률 분포값인 Attention Weight로 변환하는 연산을 수행한다.
이때 생각해봐야될 것은 크게 세 가지가 있다.</p>
<blockquote>
</blockquote>
<h3 id="1-마스킹을-하는-이유와-원리"><strong>1. 마스킹을 하는 이유와 원리</strong></h3>
<p>패딩 마스킹의 목표는 모델이 의미없는 패딩 토큰이나 참조하면 안되는 토큰에 일절 <strong><em>주의(Attention)를 주지 않게 하기 위해</em></strong> 해당 토큰의 최종 Attention Weight를 0으로 만드는 것이다.
Attention Weight가 0임은 곧 각 토큰간의 연관성, 예측 확률이 낮아도 된다는 뜻이기 때문이다.<br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$Attention~Weight = softmax(Score) ⟹ 0$<br></p>
<h3 id="2-softmax의-성질"><strong>2. $Softmax$의 성질</strong></h3>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/e36d03bb-ba7d-4b1d-9097-b25f6e5d94f0/image.png" alt=""> [출처] <a href="https://botpenguin.com/glossary/softmax-function">https://botpenguin.com/glossary/softmax-function</a>
Softmax는 그룹 내 확률을 확률 분포로 만들어주는 정규화 과정에 적용되는 내용이다. $(0, 1)$사이의 열린 구간의 확률값으로 출력값이 완전히 0이거나 1이 되진 못하며, 1에 매우 가까운 출력값을 갖는다.
또한, Softmax는 <em>양수/음수로 나누어 증폭/감소 시키는 것이 아닌, <strong>가장 큰 값을 다른 값보다 훨씬 더 높게 증폭시키고, 상대적으로 작은 값들은 모두 0에 가깝게 낮추는 역할</strong>_을 한다.
<br>Softmax 함수의 출력인 $P_i$가 0이 되기 위한 입력인 $(Score, Logit~z_i)$의 조건은 다음과 같다.<br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$\lim\limits</em>{z_i→-\infin}softmax(z)<em>i=\lim\limits</em>{z_i→-\infin}\frac{e^{z_i}}{\sum_{j}e^{z_j}}≈\frac{0}{\sum e^{z_j}}=0$<br>
따라서, Softmax의 출력을 0으로 만들기 위해서는 입력 점수 $Z_i$를 반드시 $-\infin$로 만들어야된다. 주어진 점수 분포들의 합을 1로 만드는 확률적 분포로 정규화 시키는 것이 이 과정의 의의이다.
<br>여기서 일차원적으로 생각할 수 있는 내용은 <del>..</del>....
<em><del>사실 내가 한..</del></em>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>- 0을 곱하는 것도 유효하지 않니</strong>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>- $-\infin$을 곱하는 것도 유효하지 않니</strong>
였다.
<br></p>
<h3 id="3-지수함수exponential-function의-성질"><strong>3. 지수함수(Exponential Function)의 성질</strong></h3>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/3bdccddd-14ff-4b9d-94b9-55ba58bbea4b/image.png" alt=""> [출처] <a href="https://en.wikipedia.org/wiki/Exponential_function">https://en.wikipedia.org/wiki/Exponential_function</a>
지수함수는 입력값을 $(-\infin, \infin)$를 열린 구간으로 가지며, 출력값은 (0, $\infin$)을 갖는다. 0으로는 닿을 수 없다. 해당 함수는 입력값이 0일때, 1이라는 완전한 양수의 값을 가진다. 위의 Softmax성질과 이 지수함수의 성질을 함께 살펴보면, 왜 Scaled Attention Score에 Mask 행렬을 <strong>&quot;더하는 지&quot;</strong> 확실히 알 수 있다. <br></p>
<ul>
<li><strong>Scaled Attention Score에 0을 곱할 경우</strong>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;제일 멍청한 생각이었다.. 이렇게 되면 Softmax의 입력은 0이 될 것이고, $\frac{e^0}{\sum e^{z_j}}$의 양수 출력값을 가진다. 결론적으로 양수 가중치가 된다. <br>
Softmax의 핵심은 총합이 1인 확률 분포를 만드는 것이다. 유효한 토큰들에 비해서 패딩 토큰이 아무리 작은 양수의 값을 가져 정규화로 약간의 무시가 된다고 해도, 패딩 토큰이 <strong>무의미하게 전체 주의력의 일부를 강제로 가져가도록 허용</strong>하게 되는 것이다. 이로 인해 유효한 토큰들 사이의 상대적인 주의력 분배가 미세하게 왜곡될 위험이 있다는 것이다......<br></li>
<li><strong>Scaled Attention Score에 $-\infin$을 곱핧 경우</strong>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;쩝 이 또한 멍청한 생각이었다. Attention Score가 모두 양수라는 보장이 어디있나? 이미 음수로 나온 &quot;정말 관계 없는&quot; 토큰을 되려 증폭시키고, 확률 분포로 변환할 때는 주의해야되는 토큰들만을 모두 배제해버리는 역효과가 나는 상황이었다.</li>
</ul>
<p>이렇듯 <code>[PAD]</code> 토큰이 있을 때나 Causal한 생성을 목적으로 하여 마스킹을 해야되는 경우, 주의해야되는 토큰에서 완전히 배제해야되기 때문에 마스킹 행렬을 더해주는 방식으로 이를 돕는다. </p>
<p>아<del>~ 나는 이 섬세한 하나하나가 너무 신기했는데 나만 신기했다면 ~</del> 
ㅠㅠ
공부 더 열심히 해야겠은..
명작은 역시 뭘 파도파도 계속 나오는 것 같다.....</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RL] GRPO와 PPO]]></title>
            <link>https://velog.io/@so_oni_on/RL-GRPO%EC%99%80-PPO</link>
            <guid>https://velog.io/@so_oni_on/RL-GRPO%EC%99%80-PPO</guid>
            <pubDate>Sun, 05 Oct 2025 06:25:14 GMT</pubDate>
            <description><![CDATA[<p>오늘은 시간이 없으니 GRPO와 PPO에 대해 공부한 내용을 개념/수식적으로 간략히 정리하는 글을 작성하겠다.</p>
<p>오늘은 추석 전날이기 때문... ~</p>
<p>우선은~~ 기본적인 개념적 강화학습과 Markov Decision Process(MDP)에 대한 내용을 알고있다고 가정하겠다.</p>
<p>간략히 설명하자면 <strong>MDP</strong>는 <em>Agent가 Environment과 상호작용하는 과정을 수학적으로 모델링한 것</em>으로, 아래와 같은 다섯 가지 요소로 구성된 튜플 형식이다.</p>
<p>$MDP = (S, A, P, R, \lambda)$</p>
<p><strong>1. 상태 집합 ($S$: States)</strong>
Agent가 처해질 수 있는 모든 가능한 상황의 집합 (e.g., 로봇 센서 값 등)
<strong>2. 행동 집합 ($A$: Actions)</strong>
Agent가 각 State에서 취할 수 있는 모든 가능한 행동의 집합 (e.g., 왼쪽으로 이동, 오른쪽으로 이동, 점프 등)
<strong>3. 상태 전이 확률 ($P$: Transition Probability)</strong>
Agent가 특정 State $s$에서 행동 $a$를 취했을 때, 다음 상태인 $s&#39;$로 이동할 확률
$P(s&#39;|s, a) = P(S_{t+1}=s&#39;|S_t=s, A_t=a)$
이때, 다음 상태 $s&#39;$가 현재 상태인 $s$와 행동 $a$에만 의존하며, 과거의 상태에는 영향을 받지 않는다는 가정을 Markov Property에 근거한 수식임
<strong>4. 보상 함수 ($R$: Reward Function)</strong>
Agent가 상태 $s$에서 행동 $a$를 취하고, 새로운 상태인 $s&#39;$로 전이했을 때 받게되는 즉각적인 Scalar 값
$R(s, a, s&#39;)$
<strong>5. 감가율 ($\lambda$: Discount Factor)</strong>
미래에 받을 보상의 가치를 현재 시점에서 얼마나 할인하여 평가할지 결정하는 값으로, $0\le\lambda\le1$의 범위를 갖는다.
이때, $\lambda가 1에 가까울수록 먼 미래의 보상도 중요하게 여기는 것이다.
<del>ㅠㅠ.. 여담이지만.. 이거 처음에 잘못된 기술 블로그를 봐서 할인율로 해석하는 줄 알았다는 사실... 부끄럽듭니다.... 다들 검수도 안하고 GPT 복붙하는건 너무한거 아닙니까....</del></p>
<p>아무뜬 이 다섯 요소를 바탕으로 강화학습이 정의되며, 여기서 중요한 <strong>Policy</strong>는 상태 $s$에서 Agent가 어떤 행동 $a$를 취할지를 결정하는 규칙이다.
이를 기반으로 학습이 진행된다.</p>
<ul>
<li>Polcy 정의 수식
$\pi(a|s)=P(A_t=a|S_t=s)$
즉, 이 정책은 상태 $s$에서 행동 $a$를 취할 <strong>확률 분포</strong>이다.</li>
</ul>
<h1 id="ppo">PPO</h1>
<h3 id="proximal-policy-optimization">Proximal Policy Optimization</h3>
<p>: 정책 경사(Policy Gradient) 기반의 강화 학습 알고리즘 중 제일 일반적이고 보편적인 알고리즘</p>
<ul>
<li>기본 PPO 수식:
<img src="https://velog.velcdn.com/images/so_oni_on/post/1cd339bb-6027-4692-b6f8-557068ff6bd8/image.png" alt=""></li>
</ul>
<p><strong>1. 정책경사(Policy Gradient)?</strong>
PPO는 Agent의 행동을 결정하는 정책 $\pi$를 직접 최적화하여 누적 보상 Cumulative Reward를 최대화하는 것을 목표로 한다.</p>
<p><strong>2. 안정적 업데이트</strong>
이 PPO 알고리즘이 일반적으로 많이 사용되는 강화학습 알고리즘인 이유는 기존의 TRPO의 내용을 기반으로 하지만 구현이 훨씬 간단하며 안정적인 업데이트가 가능하다는 장점이 있기 때문이다.
이 알고리즘은 정책을 업데이트 할 때, 이전 정책($\pi_{old}$)과 현재 정책($\pi_{theta}$) 간의 차이가 너무 커지는 것을 KL divergence로 방지하는 역할을 한다.</p>
<blockquote>
<p>♨️ <strong>KL Divergence</strong>
정책 업데이트 폭을 제한하여 안정성을 확보하는 도구로, 일반적으로는 PPO의 목적함수에 KL Divergence를 포함하진 않으나, 아래의 Clipping을 사용하여 정책 비율($r_t(\theta)$를 일정 범위 내로 제한한다.</p>
</blockquote>
<p><strong>3. 클리핑 목적 함수(Clipped Surrogate Objective)</strong>
PPO는 정책 비율($\frac{\pi_{\theta}(a|s)}{\pi_{\theta_{old}}(a|s)}$)을 일정 범위($[1-\epsilon, 1+\epsilon]$)로 Clipping하여 정책이 급격히 변화하는 것을 막고, 안정적인 학습을 할 수 있도록 유도한다. </p>
<p>이는 복잡한 KL Divergence의 제약을 우회하면서도 그 효과를 얻는 방법이다. </p>
<p><strong>4. 어드밴티지 추정(Advantage Estimation)</strong>
정책 업데이트에서 사용되는 이점(Advantage) 함수($\hat{A}_t$)는 특정 상태 $s$에서 취한 행동 $a$ 이 평균적인 행동보다 얼마나 더 좋았는지를 나타내는 함수이다.</p>
<ul>
<li><strong>Advantage Function 수식:</strong>
($Q(s, a)-V(s)$)</li>
</ul>
<p>이때, PPO에서는 일반적으로 <strong>가치 함수(Value Function, Critic)</strong> $V(s)$를 별도로 학습해서 이점 추정의 베이스라인으로 사용한다.</p>
<hr>
<h1 id="grpo">GRPO</h1>
<h3 id="group-relative-policy-optimization">Group Relative Policy Optimization</h3>
<p>GRPO는 주로 LLM의 정렬(Alignment)과 같은 특정 환경에서 PPO의 단점을 보완하기 위해 제안된 알고리즘이다.
GRPO는 PPO와 동일하게 정책을 최적화하지만, Advantage Estimation 방식에서 차이점이 있다.</p>
<ul>
<li>기본 GRPO 수식:
<img src="https://velog.velcdn.com/images/so_oni_on/post/e21155fb-33d5-4941-8b1b-30d474e00325/image.png" alt=""></li>
</ul>
<p>이렇듯 GRPO는 PPO와 마찬가지로 정책의 안정적인 업데이트를 위해 KL Divergence 페널티 항을 목적 함수에 포함하는 것이 일반적이다.</p>
<p>좀 더 간략히 수식으로 작성하자면 GRPO의 목적 함수는 다음과 같다.</p>
<p>$\max\limits_{\theta}[\hat{\mathbb{E}}<em>t[L^{Policy}(\theta)]-\lambda</em>{KL}\hat{\mathbb{E}}<em>t[KL[\pi</em>{\theta_{old}}(⋅|s_t), \pi_{\theta}(⋅|s_t)]]]$</p>
<p>이때,</p>
<ul>
<li>$L^{Policy}(\theta)$: GRPO가 새롭게 정의한 이점을 사용하는 정책 목적 함수</li>
<li>$\lambda_{KL}[⋅]$: PPO와 동일하게 정책의 변화를 제어하는 KL Divergence 페널티 항</li>
</ul>
<h2 id="ppogrpo의-핵심-차이점">PPO/GRPO의 핵심 차이점</h2>
<ul>
<li><strong>Critic Network 제거</strong>:
GRPO는 PPO와 다르게 별도의 <strong><em>Critic(가치 함수)</em></strong> 네트워크를 학습하지 않는다.</li>
<li><strong>Group-based Advantage Estimation(그룹 기반 이점 추정)</strong>:
하나의 상태($s$)에 대해 현재 정책($\pi_{\theta}$)으로부터 여러 개의 응답(행동($a$) 그룹)을 샘플링하고, <strong><em>그룹 내의 보상을 상호 비교</em></strong>하여 상대적인 이점(<em>Relative Advantage</em>)를 계산한다.<ul>
<li><strong>기존 Advantage 수식:</strong>
  $\hat{A}_i=\frac{r_i-mean(r)}{std(r)}$(정규화된 보상)
  이 그룹 기반 상대 보상이 <strong>$\hat{A}_t$</strong>의 역할을 대체한다.<blockquote>
<p>따라서, GRPO의 이점 함수 $\hat{A}_i$는 다음과 같은 <strong>그룹 보상 $r$에 대한 정규화로 정의됨.</strong></p>
<ul>
<li>수식: 
$\hat{A}<em>t=\frac{r_i-mean(r)}{std(r)+\epsilon</em>{floor}}$
<br>이에 대한 의의는 다음과 같다.
 <strong>- Critic 불필요:</strong> 
Critic, $V(s)$가 없으므로 $V(s)$를 학습하는 데 필요한 추가적인 신경망과 메모리가 필요 없다. 따라서 LLM처럼 모델 크기가 매우 클 때 <strong>자원 효율성</strong>이 극대화됨.<br></li>
</ul>
</blockquote>
</li>
<li><em>- 안정적인 베이스라인:*</em>
PPO에서 $V(s)$는 학습되는 값으로, 불안정하거나 노이즈가 많을 수 있다. 
하지만 GRPO는 샘플링된 그룹의 통계랑을 기준으로 삼기 때문에 보다 적은 범위이므로, <strong>안정적이고 On-Policy에 기반한 베이스라인을 사용</strong>하게 됨.<br>
<strong>- LLM의 Alignment에 최적화:</strong>
RLHF와 같은 LLM 정렬 환경에서는 <strong>최종 출력 시퀀스에 대해서만</strong> 보상($r_i$)이 주어지는 경우가 많음. 
하지만 GRPO는 이 최종 보상을 토큰 단위 이점($\hat{A}_t$)으로 역전파할 때, GAE 대신 이 정규화된 상대 보상을 모든 토큰에 동일하게 적용하여, 학습을 보다 효율적이고 효과적으로 만듦.</li>
</ul>
</li>
</ul>
<p>즉 <del>~ PPO가 가치 네트워크를 _학습_해서 <strong>절대적인 기준선</strong>을 설정한다면, GRPO는 <strong><em>샘플링된 그룹의 평균을 상대적인 기준선</em></strong>으로 설정하여 이점 함수를 계산하는 방식이다.....
~</del>처음에 이걸 알고 너무 신기해서 멍때림.. 멍~~..~~</p>
<hr>
<p>오늘의 한마디..
<strong>모든 것은... 이전 사건의 확률에 기반한다.....
확률... 확률...... 확률........</strong>
<img src="blob:https://velog.io/38756b42-eece-4cc3-8804-3ac7a7f8b618" alt="업로드중.."></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AI를 하는데 Slicing을 모른다고?;;]]></title>
            <link>https://velog.io/@so_oni_on/AI%EB%A5%BC-%ED%95%98%EB%8A%94%EB%8D%B0-Slicing%EC%9D%84-%EB%AA%A8%EB%A5%B8%EB%8B%A4%EA%B3%A0</link>
            <guid>https://velog.io/@so_oni_on/AI%EB%A5%BC-%ED%95%98%EB%8A%94%EB%8D%B0-Slicing%EC%9D%84-%EB%AA%A8%EB%A5%B8%EB%8B%A4%EA%B3%A0</guid>
            <pubDate>Sat, 20 Sep 2025 16:40:32 GMT</pubDate>
            <description><![CDATA[<h2 id="개요">개요</h2>
<p>Slicing은 Python과 Pytorch같은 라이브러리에서 배열이나 텐서의 &quot;특정 부분&quot;을 선택하는 방식임.
따라서, 특히 Logit 계산을 해서 정확한 input이나 loss 등의 입력을 통한 DL 학습에 필수적인 요소이다!!!</p>
<p><strong>헷갈리면 절대 안됨 그러면 그냥 죽음 뿐.</strong>
학습을 잘못된 방식으로 하는 것이기 때문이다. ....</p>
<hr>
<h2 id="기본-슬라이싱-문법">기본 슬라이싱 문법</h2>
<pre><code>[start:stop:step]</code></pre><ul>
<li><code>start</code> : 슬라이싱을 시작할 인덱스(범위에 포함됨)</li>
<li><code>stop</code>: 슬라이싱을 종료할 인덱스(범위에 포함되지 않음)</li>
<li><code>step</code>: 슬라이싱할 때 건너뛸 간격</li>
</ul>
<p>위의 값들을 생략하면 다음과 같은 &#39;기본값&#39;으로 들어가게 된다.</p>
<ul>
<li><code>start</code>: 0</li>
<li><code>stop</code>: 마지막 인덱스</li>
<li><code>step</code>: 1</li>
</ul>
<table>
<thead>
<tr>
<th>syntax</th>
<th>의미</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td><code>[n:]</code></td>
<td>n부터 끝까지</td>
<td>[2:]는 2번 인덱스부터 끝까지</td>
</tr>
<tr>
<td><code>[:n]</code></td>
<td>처음부터 n-1까지</td>
<td>[:3]은 0, 1, 2번 인덱스까지</td>
</tr>
<tr>
<td><code>[-n:]</code></td>
<td>뒤에서 n개</td>
<td>[:-2]는 뒤에서 2개</td>
</tr>
<tr>
<td><code>[:-n]</code></td>
<td>뒤에서 -n개를 제외한 전부</td>
<td>[:-1]는 마지막 하나를 제외한 전부</td>
</tr>
<tr>
<td><code>[::n]</code></td>
<td>n간격으로</td>
<td>[::2]는 2칸씩 건너뛰며</td>
</tr>
<tr>
<td><code>[::-1]</code></td>
<td>뒤집기</td>
<td>전체를 뒤집음</td>
</tr>
<tr>
<td>---</td>
<td></td>
<td></td>
</tr>
<tr>
<td>## 다차원 배열 슬라이싱</td>
<td></td>
<td></td>
</tr>
<tr>
<td>PyTorch같은 DL 라이브러리에서는 다차원 텐서에 대한 슬라이싱이 필요할 때가 있음.</td>
<td></td>
<td></td>
</tr>
<tr>
<td>따라서 각 차원마다 별도로 슬라이싱 조건을 지정할 수 있음!</td>
<td></td>
<td></td>
</tr>
<tr>
<td>- <code>[dim1, dim2, ...]</code> 형식으로 각 차원에 대해 슬라이싱 규칙을 지정</td>
<td></td>
<td></td>
</tr>
<tr>
<td>- <code>:</code>: 해당 차원 전체를 선택</td>
<td></td>
<td></td>
</tr>
<tr>
<td>- <code>...</code>(Ellipsis): 여러 개의 <code>:</code>를 축약한 표현이라 함.</td>
<td></td>
<td></td>
</tr>
<tr>
<td>e.g.,) <code>x[...,-1]</code>은 마지막 차원의 마지막 요소를 의미하되, 앞선 모든 차원 또한 그대로 유지</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p>아래의 예시에서의 모든 전제는 <code>my_tensor.shape</code>이<code>(batch_size, sequence_length, feature_dim)</code>이라고 가정하겠다.</p>
<table>
<thead>
<tr>
<th>슬라이싱</th>
<th>의미</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td><code>tensor[:, :, -1]</code></td>
<td>모든 batches, 모든 sequence length에 대해 마지막 feature를 선택</td>
<td></td>
</tr>
<tr>
<td><code>tensor[:, -1, :]</code></td>
<td>모든 batches에 대해 마지막 sequence token의 모든 features를 선택</td>
<td>문장 분류에서 마지막 단어의 임베딩 선택</td>
</tr>
<tr>
<td><code>tensor[0, :, :]</code></td>
<td>첫 번째 batch에 대해 모든 데이터를 선택</td>
<td>첫 번째 문장 전체를 선택</td>
</tr>
<tr>
<td><code>tensor[:, :5, :]</code></td>
<td>모든 batches에 대해 첫 5번 째 토큰만 선택</td>
<td>문장의 앞부분만 사용</td>
</tr>
<tr>
<td><code>tensor[:, -1]</code></td>
<td><code>my_tensor[:, -1:, :]</code>와 동일 <br> → 마지막 차원 <code>:</code>가 생략됨<br><br>즉, 모든 batches에 대해 마지막 sequence token의 모든 featuers를 선택</td>
<td></td>
</tr>
</tbody></table>
<blockquote>
<h3 id="슬라이싱과-viewcontiguous">슬라이싱과 <code>.view()</code>/<code>.contiguous()</code></h3>
<p>슬라이싱은 원본 tensor의 view를 반환함.
이 &#39;뷰(view)&#39;는 원본 메모리를 공유해서 빠르나, 메모리가 <strong>불연속적</strong>일 수 있음.</p>
</blockquote>
<ul>
<li><code>contiguous()</code>: 슬라이싱으로 인해 불연속적이게 된 tensor를 메모리 상에 연속적으로 배치된 새로운 tensor로 만듦
  → <code>reshape</code>나 <code>view</code>를 사용하기 전에 <code>contiguous()</code>를 호출하면 잠재적 오류를 방지할 수 있음.</li>
<li><code>view()</code>: 메모리상 연속적인 tensor에만 사용이 가능함. <code>reshape</code>보다 빠르지만 여전히 제약이 있음.</li>
<li><code>reshape()</code>: tensor의 연속성 여부에 관계없이 작동.
  → 필요한 경우, 메모리를 복사<strong><del>*</del></strong>하므로 <code>view</code>보다 느릴 수 있음
<br>+) 가끔 성능 최적화를 위해 <code>.contiguous().view()</code><strong>~~\</strong>~~**를 사용할 때도 있음 </li>
</ul>
<blockquote>
<p><strong><del>*</del> 메모리 복사와 속도 관련 문제에 대한 의미</strong>
tensor의 경우, <code>reshape()</code>을 사용했을 때 tensor의 데이터가 슬라이싱 후(After)와 같은 상황에서 메모리에서 연속적으로 저장되어있지 않으면, PyTorch는 자동으로 그 데이터를 메모리의 빈 공간에 연속적으로 재배열(contiguous)하며, 복사본을 만듦.
→ 새로운 tensor는 더 이상 원본 tensor와 메모리를 공유하지 않음
<br>
<strong>~~\</strong>~~ <code>.contiguous().view()</code>를 사용하는 이유**
<strong>성능과 안정성</strong>을 확보하기 위함임.
대개, <code>view()</code>가 <code>reshape()</code>보다 일반적으로 위의 이유들로 빠르기 때문에, 
→ <code>view()</code>를 사용하고 싶지만 tensor가 연속적인지 확실하지 않은 경우 방어적인 코딩을 하기 좋은 문법<br>
가령 슬라이싱 연산 후, 새로운 tensor가 생성되는게 아닌 원본 tensor의 특정 부분을 가리키는 view를 만들기 때문에 이 과정에서 메모리 주소가 불연속적이게 될 수 있음.<br>
<strong>결론적으로, <code>contiguous().view()</code>는 불연속적 tensor을 <code>view()</code> 연산이 가능한 연속적 tensor로 변환하고, 빠르고 효율적 <code>view()</code>연산의 장점을 활용하여 <em>코드의 안정성을 높일 수 있음</em>.</strong></p>
</blockquote>
<p>끗 <del>.</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Cross-Encoder vs. Bi-Encoder]]></title>
            <link>https://velog.io/@so_oni_on/Cross-Encoder-vs.-Bi-Encoder</link>
            <guid>https://velog.io/@so_oni_on/Cross-Encoder-vs.-Bi-Encoder</guid>
            <pubDate>Sat, 23 Aug 2025 16:11:29 GMT</pubDate>
            <description><![CDATA[<p>기초를 잘 다집시다 🥺😅
..
<del><em>(Dear myself..)</em></del>
<img src="https://velog.velcdn.com/images/so_oni_on/post/94248f42-13f4-4e44-8ed7-9d307b2585f9/image.png" alt=""></p>
<p>기본적으로 어떤 내용일까?</p>
<p>언어 모델 중 하나인 &quot;BERT&quot;에 사용되는 기본적인 내용으로, 언어 모델에 관심이 있고, 특히 NLU 과정에 대해 공부하고자 하는 학생이라면 꼭 알고 넘어가야되는 내용이다.</p>
<p>언어 모델에는 대개 input을 받아들이는 부분인 Encoder가 있다.
따라서, Encoder는 간단히 말해 &quot;텍스트를 숫자로 이루어진 벡터로 변환하여 모델이 이해할 수 있도록 하는 역할&quot;을 한다.
이를테면, 자연어를 컴퓨터가 처리할 수 있는 형태로 <strong>번역</strong>하는 과정일 것이다.</p>
<p>이름만 봐도 직관적으로 알 수 있듯, 
Single Encoder(Cross Encoder)는 Encoder가 하나 있다. 즉 input도 <strong>&quot;하나&quot;</strong>여야된다.
그에 반해, Dual Encoder(Bi Encoer)는 Encoder가 두 개로, input도 <strong>&quot;두 개&quot;</strong> 들어간다. </p>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/2b1f9a76-ce88-4a52-8524-cfe74da65d65/image.png" alt=""></p>
<p>조금 더 깊게 알아보겠다.</p>
<p>*<em>공통 전제: *</em></p>
<ul>
<li>두 문장이 주어진다. (이를 각각 &#39;문장 A&#39;, &#39;문장 B&#39;로 칭하겠다.)</li>
<li>해당 두 문장을 _비교_하기 위해 언어 모델에 입력을 넣는다.</li>
</ul>
<hr>
<h2 id="cross-encodersingle-encoder">Cross Encoder(Single Encoder)</h2>
<p>두 문장을 <strong>동시에</strong> Transformer Network에 전달한다.
입력 문장 쌍의 유사성을 나타내는 [0~1] 사이의 출력 값을 먼저 생성한다.
이때, 두 개의 문장을 모델에 넣어 내부에서 문장 간의 &quot;문장 간 관계&quot;를 파악한다. </p>
<ul>
<li><p><strong>입력:</strong> 문장 A, 문장 B를 하나의 입력으로 결합하여 입력
  ‣ 이후, 모델 내부에서 두 문장 간의 interaction을 직접적으로 학습하여 유사도를 계산</p>
</li>
<li><p><strong>장점:</strong> </p>
<ul>
<li>높은 정확도
: 문장 A와 문장 B가 함께 입력되므로, 문장 간의 관계와 맥락을 깊이 있게 파악할 수 있음</li>
<li>적은 정보 손실
: 문장이 변형되지 않은 상태에서 비교하기 때문에 단어 간의 미묘한 관계나 문맥적 손실이 최소화된다.</li>
</ul>
</li>
<li><p><strong>단점:</strong></p>
<ul>
<li>느린 속도
: 가령 100개의 문장이 있다면, $$_{100}C_2$$의 연산을 모두 수행(Dual Encoder는 각 개별적인 input이 들어가므로, 단순 비교, 즉 100회만 진행)</li>
</ul>
</li>
</ul>
<blockquote>
<p><em>🦾 <strong>Note!</strong></em>
이때, 문장 쌍을 구성하는 방식은 크게 다음과 같다:</p>
</blockquote>
<ul>
<li>pairwise</li>
<li>triplet
  : 두 문장뿐만 아닌, &#39;positive pair(긍정쌍)&#39;, &#39;negative pair(부정쌍)&#39;, <strong>&#39;anchor(기준 문장)&#39;</strong>을 고려한다. &#39;기준 문장&#39;과 &#39;긍정쌍&#39;은 최대한 거리적으로 가깝게, &#39;부정쌍&#39;과는 거리적으로 멀게하는 방식이다.
  거리적으로 가까움은 곧 &#39;의미적 유사도&#39;를 의미하기 때문이다.</li>
</ul>
<hr>
<h2 id="bi-encoderdual-encoder">Bi Encoder(Dual Encoder)</h2>
<p>두 문장, A와 B를 비교하기 위해 각각 독립적으로 두 개의 Encoder에 입력하여 개별적인 문장 임베딩을 생성한다. 이후, 생성된 두 벡터$$(u, v)$$에 대해 Cosine Similarity를 계산하여 두 문장의 유사도를 판단한다.</p>
<ul>
<li><strong>장점:</strong><ul>
<li>빠른 연산 처리
: 각 문장들을 임베딩 해둔 다음, 독립적으로 각 문장을 단순 벡터 연산으로 처리(효율성 측면에서 굉장히 좋음)<br>- 확장성
: 미리 계산된 임베딩을 cache 등에 저장하고 검색에 활용하는 등 다양한 적용 방식이 있다.</li>
</ul>
</li>
<li><strong>단점:</strong><ul>
<li>상대적 정확도 저하
: 두 문장을 독립적으로 처리하기에, 문장 간의 상호작용을 직접적으로 고려하지 못한다. 따라서 임베딩 과정에서의 정보 손실 위험이 있으며, 임베딩 모델의 성능에 따라 최종 성능이 달라지는 경우도 다소 있다. </li>
</ul>
</li>
</ul>
<hr>
<p>아래부터는 대략적인 적용 가능 분야의 예시이다.
...
<br>
해당 개념은 굉장히 기본적인 내용이기에 다양한 접근법의 초석이 되기도 한다.
특히, Reranker 기반 모델 학습을 위해 자주 사용된다.</p>
<p>Reranker 또한 n개의 문장을 비교하여 어떤 기준에 따라 재순위화를 하는 과정이니 문장 간의 비교가 필수적이다. 초기 검색 결과를 바탕으로 문장 간의 Relavant를 더 정확하게 평가하여 재순위화를 하는 과정이기 때문이다.</p>
<p>대개 Encoder 종류에 따른 tradeoff가 명확히 존재하기 때문에 Reranking Task에서는 다음과 같은 문제가 있다.
가령, 하나의 입력에 대해 문장 5개를 비교해야하는 상황에서 각각의 문장을 Cross Encoder로 $$_5C_2$$ 연산을 하도록 할지(입력 하나에 10번의 연산이지만, input이 수천개인 경우나 6개 이상의 후보가 있다면 연산 속도는 명확히 차이날 것이다.), 더 많은 문장을 효율적으로 비교하기 위해 Bi Encoder로 비교를 하게 할지가 관건이다.</p>
<hr>
<p>추가로... 요즘 흥미로운 분야가 정말 다양한데,</p>
<ul>
<li>모델 최적화 및 경량화</li>
<li>언어 임베딩</li>
<li>강화학습</li>
</ul>
<p>이렇게 세 가지다..
근데 벌써 방학이 다 끝나간다~
이번 8월 마지막 주, 공부해온 내용들을 기반으로 정리도 할겸 많은 업데이트를 해보도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RLHF] DPO(Direct Preference Optimization) 정리]]></title>
            <link>https://velog.io/@so_oni_on/RLHF-DPODirect-Preference-Optimization-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@so_oni_on/RLHF-DPODirect-Preference-Optimization-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 15 Jul 2025 20:05:19 GMT</pubDate>
            <description><![CDATA[<h1 id="개요">개요</h1>
<p>RLHF(Reinforcement Learning from Human Feedback)은 인간의 피드백을 바탕으로 언어 모델을 최적화시키는 대표적인 방식이다. 이때, 학습 방식은 크게 두 가지로 나눌 수 있는데,</p>
<h4 id="--보상-모델-기반-접근reward-model-basedbr">- 보상 모델 기반 접근(Reward Model Based)<br></h4>
<ul>
<li>인간 피드백 데이터를 이용해 보상 모델(Reward Model)을 학습한 뒤, 이를 기반으로 PPO(Proximal Policy Optimization)등의 강화학습 기법을 적용해 언어 모델을 튜닝<h4 id="--보상-모델이-없는-직접-최적화-접근">- 보상 모델이 없는 직접 최적화 접근</h4>
</li>
<li>Reward Model을 따로 학습하지 않고, <strong>인간 선호쌍(Preferred vs. Dispreferred)만을 이용</strong>해 직접 모델 최적화</li>
</ul>
<p>으로 나눌 수 있다.</p>
<p>이번 포스팅에서 알아볼 Direct Preference Optimization(이하 DPO) 학습 방식은 명시적이 듯, 두 번째 방식에 해당되며, <strong>&#39;직접적으로 선호도를 학습하는 최적화 기법&#39;</strong>이다. </p>
<p>이러한 학습 방식이 제안된 배경은 다음과 같다:
기존의 RLHF에서는 보상 모델을 만들고, Proximal Policy Optimization(PPO)와 같은 알고리즘으로 fine-tuning을 진행하였음.
이때,</p>
<ul>
<li>Reward Model을 별도로 학습해야하므로 _<strong>Train Pipeline이 복잡</strong>_하다.</li>
<li>PPO는 _<strong>안정성 이슈와 구현 복잡성이 존재</strong>_한다. </li>
<li><em><strong>Reward Model 자체의 Bias가 LLM의 최종 출력에 예측 불가한 왜곡을 줄 가능성이 있다.</strong></em></li>
</ul>
<p>이러한 문제점을 해결하기 위해, DPO는</p>
<h4 id="--보상모델-없이-직접-llm-fine-tuning">- 보상모델 없이 직접 LLM Fine-tuning</h4>
<h4 id="--최적화-관점에서-보다-단순하고-수렴이-안정적">- 최적화 관점에서 보다 단순하고 수렴이 안정적</h4>
<p>이라는 개선점을 보이는 학습 방식이다.</p>
<blockquote>
<h3 id="💁-배경-지식-한-입-작지만-큰-한-입">💁 배경 지식 한 입.... 작지만 큰... 한 입....</h3>
</blockquote>
<h3 id="강화학습과-rlhf">강화학습과 RLHF</h3>
<h3 id="-강화학습reinforcement-learning-rl">* 강화학습(Reinforcement Learning, RL)</h3>
<p>Agent가 Environment와 상호작용하며 Reward를 최대화하는 행동을 학습하는 방식
이때, Agent는 학습 주체, Environment는 상호작용 대상으로 생각하면 쉽다.
(좀 더 쉬운 이해를 위해 아래에서 예시를 적용하겠다.)
이는 보상 신호를 최대화하는 정책(Policy)을 학습하는 것으로, 좋은 행동(Reward를 받는 행동)은 강화되며, 그렇지 않은 행동은 억제되는 식의 학습 방식이다.<br></p>
<h3 id="-rlhfreinforcement-learning-from-human-feedback">* RLHF(Reinforcement Learning from Human Feedback)</h3>
<p>RL의 한 분야로, Environment의 Reward 대신 Human Feedback(Preference)을 이용해 Agent를 튜닝
e.g.,) <em>LLM Tuning</em>
    인간이 A, B 두 응답 중 어떤 것이 더 좋은지 평가 → 이를 기반으로 보상 모델(RM)을 학습
    이후 PPO 등을 사용해 LLM을 fine-tuning
    (대표 사례) ChatGPT</p>
<blockquote>
<blockquote>
<h4 id="rl-example">[RL Example]</h4>
</blockquote>
</blockquote>
<ul>
<li>Agent: 학습 주체 (예: 로봇, AI, 아이)</li>
<li>Environment: Agent가 상호작용하는 외부 시스템 (예: 게임, 교실)</li>
<li>State: 현재 환경의 상태 정보 (예: 지금이 수학 시간인지 국어 시간인지)</li>
<li>Action: Agent가 선택할 수 있는 행동들 (예: 손들기, 조용히 있기)</li>
<li>Reward: 행동 결과로 받는 수치적 피드백 (예: 칭찬, 점수)</li>
</ul>
<p><strong>즉, RL은 환경 보상 기반이며 RLHF는 인간의 주관적 평가를 보상처럼 사용</strong></p>
<blockquote>
<h3 id="-ppoproximal-policy-optimization">* PPO(Proximal Policy Optimization)</h3>
<p>OpenAI에서 제안한 정책 기반 RL 알고리즘으로, 기존 Policy를 너무 급격히 바꾸지 않도록 하여 학습 안정성과 효율성을 동시에 확보한 방식</p>
</blockquote>
<ul>
<li><strong>주요 내용</strong><ul>
<li>KL-divergence 또는 clip function을 사용해 policy update 제한</li>
<li>너무 급격한 정책 변화를 방지하여 안정적인 학습을 유도<br></li>
</ul>
</li>
<li><strong>Loss Function</strong>
$\mathcal{L}^{\text{CLIP}}(\theta) = \mathbb{E}_t \left[ \min\left( r_t(\theta) \hat{A}_t, \text{clip}(r_t(\theta), 1 - \epsilon, 1 + \epsilon) \hat{A}_t \right) \right]$<ul>
<li>$r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{\text{old}}}(a_t|s_t)}$: 정책 비율</li>
<li>$\hat{A}_t$: Advantage function (이 행동이 얼마나 좋은지)</li>
<li>$clip$: 정책이 급격히 바뀌는 것을 억제(비율이 $[1−ε, 1+ε]$ 범위를 넘지 않도록 제한)<br></li>
</ul>
</li>
<li><strong>장점</strong><ul>
<li>학습이 안정적이고 구현이 비교적 간단</li>
<li>많은 RL 적용 분야에서 기본 선택지로 사용됨(범용성 Good~)</li>
</ul>
</li>
</ul>
<hr>
<h1 id="목적">목적</h1>
<p>LLM에 인간의 선호도를 반영한 응답 생성을 직접 최적화하기 위함이다.
PPO보다 더 안정적이고 간단하며, 효율적인 학습을 가능하게 함.</p>
<hr>
<h1 id="핵심-아이디어">핵심 아이디어</h1>
<p><strong>한 줄 요약: *<em>사용자 또는 평가자가 *</em>선호하는 응답(A)</strong>와 <strong>그렇지 않은 응답(B)</strong>이 있을 때, 모델이 <em>A를 더 높은 확률로 생성하도록 학습</em>하는 방식</p>
<p>DPO는 (입력 x, 선호 응답 y, 비선호 응답 y-)의 삼중쌍을 사용한다.
즉, 사용자 또는 평가자가 응답 A를 B보다 선호한다고 판단할 경우, 모델은 A를 더 높은 확률로 생성하도록 학습하는 방식이다.
이를 위해, DPO는 아래와 같은 loss를 최소화한다.</p>
<blockquote>
<h3 id="loss-function"><em>Loss Function:</em></h3>
<p>$\mathcal{L}{\text{DPO}} = -\log \frac{e^{\beta \cdot \log \pi\theta(y_{\text{preferred}} | x)}}{e^{\beta \cdot \log \pi_\theta(y_{\text{preferred}} | x)} + e^{\beta \cdot \log \pi_\theta(y_{\text{dispreferred}} | x)}}$<br>
이때, </p>
</blockquote>
<ul>
<li>$\pi_\theta(y|x)$: 현재 모델이 입력 x에 대해 출력 y를 생성할 확률</li>
<li>$y_+, y_-$: 선호, 비선호 응답</li>
<li>$\beta$는 <code>temp</code> Hyper-Parmeter으로, 선택성(sharpness)을 조절</li>
</ul>
<p>이 식은 로지스틱 회귀(Logistic Regression) 기반 확률 모델과 유사한 식 형태를 가지며, 선호 응답이 더 높은 확률을 가지도록 모델을 업데이트하는 방향으로 학습된다.</p>
<h2 id="-장점">‣ 장점</h2>
<ul>
<li>별도의 보상 모델이 불필요</li>
<li>PPO보다 안정적이고 Implementation이 간단함</li>
<li>높은 Alignment 성능(GPT류 모델의 fine-tuning에 많이 사용됨</li>
</ul>
<hr>
<h1 id="평가-지표">평가 지표</h1>
<h2 id="정량적-평가지표quantitative-metrics">정량적 평가지표(Quantitative Metrics)</h2>
<p><strong>1. Win Rate/Preference Accuracy</strong>
평가자 혹은 GPT가 생성된 응답 A와 B 중 선호하는 답변을 투표
DPO로 학습한 모델의 응답이 기존 SFT나 모델보다 더 많이 선택되면 우수한 성능으로 판단</p>
<blockquote>
<p> <strong>평가 방식:</strong>
    •    각 질문에 대해 SFT, PPO, DPO 등 여러 모델의 응답을 생성
    •    평가자 또는 GPT-4가 어떤 응답을 더 선호하는지 선택
    •    DPO 응답이 더 많이 선택된 비율 = Win rate</p>
</blockquote>
<p><strong>2. Pairwise Accuracy/Agreement Rate</strong></p>
<ul>
<li>학습에 사용된 선호쌍 데이터셋에 대해,<ul>
<li>DPO 모델이 선호 응답(y&#39;)을 더 높은 Log-prob로 생성하는지를 평가
→ log π(y⁺|x) &gt; log π(y⁻|x) 여부를 통해 preference alignment 측정<blockquote>
<p><strong>수식:</strong>
$\text{Accuracy} = \frac{1}{N} \sum_{i=1}^{N} \mathbb{1}\left[ \log \pi(y_+|x) &gt; \log \pi(y_-|x) \right]$</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<p><strong>3. Language Quality Metrics</strong>
보통은 직접 평가가 아니지만, 생성 텍스트 퀄리티도 참고하기도 함
    - BLEU, ROUGE
    - BERTScore, BLEURT
    - Toxicity Score: 응답이 공격/차별적 표현을 포함하는지 확인하기 위함</p>
<h2 id="정성적-평가지표quailitative-evaluation">정성적 평가지표(Quailitative Evaluation)</h2>
<p><strong>1. GPT-4 등 LLM 기반 평가자 사용</strong>
사람 대신 GPT-4에게 각 응답에 대해 다음 기준을 평가하게 함:</p>
<blockquote>
<ul>
<li>Helpfulness (도움이 되는가?)</li>
</ul>
</blockquote>
<ul>
<li>Relevance (질문과 관련 있는가?)</li>
<li>Correctness (사실 기반인가?)</li>
<li>Harmlessness (독성/편향이 없는가?)</li>
</ul>
<p><strong>2. Human Evaluation</strong></p>
<ul>
<li>실제 사람에게 응답쌍을 보여주고 더 나은 응답을 고르게 함</li>
<li>비용과 시간은 많이 들지만, 신뢰도는 가장 높음</li>
</ul>
<hr>
<h1 id="구현">구현</h1>
<pre><code class="language-python">from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments
from trl import DPOTrainer
from datasets import load_dataset  
import torch

# 1. Load model &amp; tokenizer
model_name = &quot;meta-llama/Llama-2-7b-hf&quot;  # HuggingFace Model
tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=True)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.bfloat16,  # 혼합정밀도 가속
    device_map=&quot;auto&quot;
)

# 2. Define TrainingArguments
training_args = TrainingArguments(
    output_dir=&quot;./dpo-checkpoints&quot;,
    per_device_train_batch_size=2,
    per_device_eval_batch_size=2,
    gradient_accumulation_steps=8,
    num_train_epochs=3,
    learning_rate=5e-6,
    logging_dir=&quot;./logs&quot;,
    logging_steps=10,
    save_strategy=&quot;epoch&quot;,
    eval_strategy=&quot;steps&quot;, 
    eval_steps=100,
    report_to=&quot;wandb&quot;,
)

# 3. Define triplet dataset: (prompt, chosen, rejected)
# Must be a HuggingFace `Dataset` object with columns: prompt, chosen, rejected
from datasets import Dataset

triplet_data = [
    {
        &quot;prompt&quot;: &quot;Explain the theory of relativity.&quot;,
        &quot;chosen&quot;: &quot;The theory of relativity, developed by Einstein, includes the special and general theories...&quot;,
        &quot;rejected&quot;: &quot;Relativity is when things are related, like people in a family.&quot;
    },
    ...
]

triplet_dataset = Dataset.from_list(triplet_data)

# 4. Initialize DPOTrainer
dpo_trainer = DPOTrainer(
    model=model,
    tokenizer=tokenizer,
    args=training_args,
    beta=0.1,  # temp: sharpness of preference
    train_dataset=triplet_dataset
)

# 5. Start training
dpo_trainer.train()</code></pre>
<p>이때, </p>
<ul>
<li><strong>beta 값 조정이 학습 sharpness에 큰 영향을 줌</strong>
  • $\beta$가 클수록 “선호 응답과 비선호 응답 간 log 확률 차이를 더 크게 반영” → sharper decision boundary
  • 일반적으로 0.1 ~ 0.5 사이에서 튜닝
  • 낮추면 더 부드러운 학습, 높이면 강한 선호 반영</li>
<li><strong>데이터는 반드시 “Preferred vs. Dispreferred” Response 구조여야 함</strong></li>
<li><strong>triplet_dataset 주의</strong>
  •    반드시 prompt, chosen, rejected 세 개의 열(column) 필요
  •    문자열 말고 tokenized 형태를 넣으면 충돌 발생 가능 → tokenizer는 trainer가 내부에서 처리</li>
</ul>
<h3 id="추론-시">추론 시,</h3>
<pre><code class="language-python">from transformers import pipeline
pipe = pipeline(&quot;text-generation&quot;, model=&quot;./final-dpo-model&quot;, tokenizer=tokenizer)
pipe(&quot;Why is the sky blue?&quot;, max_new_tokens=50)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Metrics] Perplexity]]></title>
            <link>https://velog.io/@so_oni_on/Metrics-Perplexity</link>
            <guid>https://velog.io/@so_oni_on/Metrics-Perplexity</guid>
            <pubDate>Sat, 05 Jul 2025 20:35:50 GMT</pubDate>
            <description><![CDATA[<h1 id="perplexity혼란도란">Perplexity(혼란도)란?</h1>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/58746161-4cfa-484d-b1b1-7f25716e2d8d/image.png" alt=""></p>
<p>언어 모델의 <strong>예측 성능</strong>을 수치화하는 지표로, 모델이 주어진 문장을 얼마나 “잘 예측하는지”를 나타냄  </p>
<blockquote>
<ul>
<li><strong>값이 낮을수록</strong> 모델이 문장을 더 잘 예측한다는 의미  </li>
</ul>
</blockquote>
<ul>
<li>확률론적으로는 “평균 지수화된 음의 로그우도”로 정의되며,  </li>
<li>직관적으로는 “모델이 매 토큰마다 선택해야 할 후보지의 개수(분기수)”를 의미합니다.</li>
</ul>
<hr>
<h2 id="1-정의-및-수식">1. 정의 및 수식</h2>
<p>문장 $$W = w_1, w_2, \dots, w_N$$에 대한 $$perplexity ( \mathrm{PPL}(W) )$$는 다음과 같다:</p>
<p>$$
\mathrm{PPL}(W) 
= \exp\Bigl(-\frac{1}{N} \sum_{i=1}^{N} \log P(w_i \mid w_{&lt;i})\Bigr)
$$
이때, </p>
<ul>
<li>$(N)$: 전체 토큰 수  </li>
<li>$(P(w_i \mid w_{&lt;i}))$: 언어 모델이 토큰 $(w_i)$를 앞선 문맥 $(w_{&lt;i})$로부터 예측한 확률  </li>
<li>음의 로그우도(Negative Log-Likelihood)를 평균 낸 후, 지수화(exp)한 형태</li>
</ul>
<hr>
<h2 id="2-수식-유도">2. 수식 유도</h2>
<h3 id="1-cross-entropy">1. Cross-Entropy</h3>
<p>   $$
   H(W) 
   = -\frac{1}{N} \sum_{i=1}^{N} \log P(w_i \mid w_{&lt;i})
   $$</p>
<h3 id="2-perplexity">2. Perplexity</h3>
<p>   $$
   \mathrm{PPL}(W) = \exp\bigl(H(W)\bigr)
   = \exp\Bigl(-\tfrac{1}{N}\sum_{i=1}^N \log P(w_i\mid w_{&lt;i})\Bigr)
   $$</p>
<hr>
<h2 id="3-해석">3. 해석</h2>
<ul>
<li><strong>지수화된 교차엔트로피</strong>이므로,<br>$$
\mathrm{PPL} = b
$$
라면 모델은 매 토큰마다 <strong>평균 (b)개의 후보</strong> 중에서 정답을 골라내는 셈입니다.  <blockquote>
<p>e.g., Perplexity가 10이면, 매 단어마다 모델이 약 10가지 후보 중 하나를 맞추는 성능임</p>
</blockquote>
</li>
</ul>
<hr>
<h2 id="4-한국어-적용-시-유의사항">4. 한국어 적용 시 유의사항</h2>
<ul>
<li><strong>한국어 전용 토크나이저 &amp; 모델</strong> 사용  <ul>
<li>형태소 기반이나 SentencePiece 토크나이저로 사전 처리된 모델 필요  </li>
<li>예: <code>skt/kogpt2-base-v2</code>, <code>beomi/KcELECTRA-base</code> 등</li>
</ul>
</li>
</ul>
<ul>
<li><strong>절대값 vs. 상대값</strong>  <ul>
<li>서로 다른 토크나이저·모델 간 절대 perplexity 비교는 부적절  </li>
<li>같은 모델 내에서 <strong>AI 생성 문장 vs. 인간 문장</strong> 비교용으로 사용</li>
</ul>
</li>
</ul>
<hr>
<h2 id="5-perplexity-gap">5. Perplexity Gap</h2>
<p>두 언어 모델 간 차이를 피처로 활용할 때는 다음과 같이 정의한다:</p>
<p>$$
\Delta \mathrm{PPL} = \mathrm{PPL}<em>{\text{simpleLM}}(W) ;-; \mathrm{PPL}</em>{\text{gptLM}}(W)
$$</p>
<ul>
<li>GPT 계열 대형 모델에 친화적인 텍스트는 $$(\mathrm{PPL}_{\text{gptLM}})$$이 낮아짐</li>
<li>단순 LM 대비 격차인 $$(\Delta \mathrm{PPL})$$가 크게 나타나는 경향을 이용</li>
</ul>
<hr>
<h2 id="6-계산-예시-python">6. 계산 예시 (Python)</h2>
<pre><code class="language-python">import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

model_name = &quot;skt/kogpt2-base-v2&quot;
tokenizer = AutoTokenizer.from_pretrained(model_name)
model     = AutoModelForCausalLM.from_pretrained(model_name).eval().to(&quot;cuda&quot;)

def perplexity(text: str) -&gt; float:
    enc = tokenizer(text, return_tensors=&quot;pt&quot;).to(&quot;cuda&quot;)
    with torch.no_grad():
        output = model(**enc, labels=enc.input_ids)
        loss = output.loss  # 평균 NLL
    return torch.exp(loss).item()

text = &quot;공부가 너무너무 하기싫은데 해야지 어쩌겠어!&quot;
print(&quot;Perplexity:&quot;, perplexity(text))
</code></pre>
<p>  라면 모델은 매 토큰마다 <strong>평균 (b)개의 후보</strong> 중에서 정답을 골라내는 셈!  </p>
<ul>
<li>예: Perplexity가 10이면, 매 단어마다 모델이 약 10가지 후보 중 하나를 맞추는 성능.</li>
</ul>
<hr>
<h2 id="7-결론">7. 결론</h2>
<blockquote>
<ul>
<li><strong>Perplexity는 언어 모델의 토큰별 예측 난도를 측정하는 평가 지표</strong></li>
</ul>
</blockquote>
<ul>
<li><strong>지표가 낮을 수록 더욱 유창하다는 뜻</strong></li>
<li><strong>각 언어에 맞게 전용 모델로 임베딩 후 진행해야 됨</strong></li>
<li><strong>대개 Perplexity Gap을 Custom Style Metric Feature로 결합하면 분류 성능이 향상</strong></li>
</ul>
<p>그럼.. 이만....
<img src="https://velog.velcdn.com/images/so_oni_on/post/97ff9d7a-a1bf-4088-8ec4-fd382aa528d9/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[LoRA] 하이퍼파라미터 정리]]></title>
            <link>https://velog.io/@so_oni_on/LoRA-%ED%95%98%EC%9D%B4%ED%8D%BC%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@so_oni_on/LoRA-%ED%95%98%EC%9D%B4%ED%8D%BC%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sun, 29 Jun 2025 10:23:56 GMT</pubDate>
            <description><![CDATA[<h1 id="1-lora-개요">1. LoRA 개요</h1>
<p>LoRA는 대형 언어 모델(LLM)의 일부 선형 변환 레이어에 “저용량 어댑터”를 추가하여, 모델 파라미터를 거의 건드리지 않으면서 새로운 태스크로 미세 조정(fine-tuning)할 수 있는 기술입니다.</p>
<ul>
<li><strong>장점:</strong> 전체 모델을 재학습·저장할 필요 없이, 어댑터(작은 행렬)만 저장 → 빠른 실험, 경량 배포</li>
<li><strong>핵심 아이디어:</strong> 원본 가중치 $$W$$를 아래의 <strong><em>A</em></strong> 형태로 두되, <strong><em>B</em></strong>로 Low-Rank 행렬 분해해서 학습 파라미터 수를 대폭 줄임<h4 id="p-aligncenter-a-w--w--delta-w-p"><p align="center"> (A) $$W’ = W + \Delta W$$ </p></h4>
<h4 id="p-aligncenter-b-delta-w--a-bt-p"><p align="center"> (B) $$\Delta W = A B^T$$ </p></h4>
<p align="center">
<img src="https://velog.velcdn.com/images/so_oni_on/post/3bba2b62-19cb-40d1-b5da-117e5d8e7011/image.png"/>
<그림1.> LoRA Matrix Multiplication
</p> 

</li>
</ul>
<hr>
<h1 id="2-주요-하이퍼파라미터">2. 주요 하이퍼파라미터</h1>
<h2 id="각-파라미터----역할">각 파라미터    역할</h2>
<ul>
<li><p><em><strong>r (rank)</strong></em>: 어댑터 행렬 $$A\in \mathbb{R}^{d\times r}$$, $$B\in\mathbb{R}^{d\times r}$$의 랭크 (내부차원)</p>
</li>
<li><p><strong><em>α (alpha)</em></strong>: 학습 시 $$\Delta W$$의 스케일링 인자. 학습률 보정용 스케일 팩터</p>
</li>
<li><p><em><strong>dropout</strong></em>: LoRA 어댑터의 드롭아웃 비율. 과적합 방지를 위해 어댑터 활성화 일부를 무작위 차단</p>
<p>이때, rank와 alpha는 2/4, 4/8과 같은 형태로 주로 조정하며, dropout은 0.00~0...
이유: </p>
</li>
</ul>
<h2 id="21-r-rank">2.1. r (Rank)</h2>
<ul>
<li><strong>정의:</strong> LoRA가 원본 가중치에 더하는 추가 저랭크 행렬의 내적 차원</li>
<li><strong>공식:</strong> $$\Delta W = \alpha \cdot A B^T$$, 
이때,</li>
</ul>
<h4 id="p-aligncenter-a-mathbbrdtimes-r-p"><p align="center"> A: $$\mathbb{R}^{d\times r}$$ </p></h4>
<h4 id="p-aligncenter-b-mathbbrdtimes-r-p"><p align="center"> B: $$\mathbb{R}^{d\times r}$$ </p></h4>
<ul>
<li><strong>총 학습 파라미터 수</strong>: $$2 \times d \times r$$</li>
<li><strong>효과</strong>:<ul>
<li>r↑ → 표현 용량 증가 → <em>더 복잡한 태스크 학습 가능</em></li>
<li>r↓ → 파라미터 절감(up to $$1/r$$) → 속도 및 메모리 효율 좋아짐</li>
</ul>
</li>
<li><strong>일반적 설정 범위</strong>:<ul>
<li><strong><em>소규모 태스크(문법 교정, 요약)</em></strong> → r=4~8</li>
<li><em><strong>중규모 태스크(요약+질의응답)</strong></em> → r=16~32</li>
<li>데이터·컴퓨팅 여유가 충분하면 r=64까지 실험</li>
</ul>
</li>
</ul>
<h2 id="22-α-alpha">2.2. α (Alpha)</h2>
<ul>
<li><p><strong>정의</strong>: LoRA로 학습된 $$\Delta W$$를 스케일하는 하이퍼파라미터</p>
</li>
<li><p><strong>작동 원리</strong>:</p>
<h4 id="p-aligncenter-w--w--fracalphar--a-bt-p"><p align="center"> $$W’ = W + \frac{\alpha}{r} , A B^T$$ </P></h4>
<h4 id="p-aligncenterorp"><p align="center">or</p></h4>
<h4 id="p-aligncenteralpha-times-a-bt-p"><p align="center">$$\alpha \times (A B^T)$$ </p></h4>
<p>형태로 구현</p>
</li>
<li><p><strong>이유</strong>: 랭크 r를 늘리면 $$|A B^T|$$가 커지므로, 학습 안정화를 위해 $$\frac{\alpha}{r}$$ 스케일링</p>
</li>
<li><p><strong>추천 값</strong>:</p>
<ul>
<li>보통 $$α = 16$$ (default)</li>
<li>$$r$$이 작으면 $$α$$를 작게 $$(&lt; 16)$$ 유지, $$r$$이 크면 $$α$$를 키워 실효 학습률 유지<pre><code>e.g.,) r=4 α=8, r=16 α=32</code></pre></li>
</ul>
</li>
</ul>
<h2 id="23-dropout">2.3. dropout</h2>
<ul>
<li><strong>정의</strong>: 어댑터가 학습 중 무작위로 일부 뉴런을 비활성화하는 비율</li>
<li><strong>역할</strong>:<ul>
<li>과적합(overfit) 방지</li>
<li>다양한 어댑터 조합 학습 유도 → 일반화 성능 ↑</li>
</ul>
</li>
<li><strong>추천 범위</strong>:<ul>
<li>데이터 적을 때 → 0.1‒0.2 (과적합 위험↑)</li>
<li>데이터 많거나 태스크 단순 → 0.0‒0.05</li>
</ul>
</li>
<li><strong>사용 예시</strong>:</li>
</ul>
<pre><code>LoraConfig(
  r=8,
  lora_alpha=16,
  lora_dropout=0.1,  # 10% 확률로 어댑터 비활성화
  target_modules=[...],
  task_type=&quot;CAUSAL_LM&quot;,
)</code></pre><hr>
<h1 id="3-하이퍼파라미터-튜닝-팁">3. 하이퍼파라미터 튜닝 팁</h1>
<ol>
<li>먼저 r 실험<ul>
<li>작은 r (4, 8) → 학습 속도 빠름</li>
<li>성능 모니터링하며 r 증가</li>
</ul>
</li>
<li>α로 학습률 보정<ul>
<li>r이 증가할 때 α를 선형 비례로 증가시켜 안정적 학습</li>
</ul>
</li>
<li>dropout으로 과적합 제어<ul>
<li>validation loss가 train loss보다 크게 차이날 때 dropout↑</li>
</ul>
</li>
<li>조합 전략<ul>
<li>r=8, α=16, dropout=0.05부터 시작</li>
<li>최종 모델 성능에 따라 하나씩 조정</li>
</ul>
</li>
</ol>
<hr>
<h1 id="4-시각화-예시">4. 시각화 예시</h1>
<table>
<thead>
<tr>
<th>조합</th>
<th>파라미터 수 절감량</th>
<th>기대 성능</th>
<th>메모리 사용량</th>
</tr>
</thead>
<tbody><tr>
<td>$$r=4, α=8, dropout=0.1$$</td>
<td>99.95%↓</td>
<td>중간</td>
<td>낮음</td>
</tr>
<tr>
<td>$$r=8, α=16, dropout=0.05$$</td>
<td>99.9%↓</td>
<td>우수</td>
<td>보통</td>
</tr>
<tr>
<td>$$r=16, α=32, dropout=0.0$$</td>
<td>99.8%↓</td>
<td>최고</td>
<td>높음</td>
</tr>
</tbody></table>
<hr>
<h1 id="5-결론">5. 결론</h1>
<p>LoRA 하이퍼파라미터는</p>
<ul>
<li><em><strong>r</strong></em>: 모델 적응력 ↔ 파라미터 효율</li>
<li><em><strong>α</strong></em>: 학습 안정화 스케일링</li>
<li><strong><em>dropout</em></strong>: 일반화 제어</li>
</ul>
<p>이 세 가지를 순차적·단계적으로 튜닝하면, 적은 비용으로도 원하는 태스크에서 최적 성능을 얻을 수 있다.</p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[RAG] Simple RAG]]></title>
            <link>https://velog.io/@so_oni_on/RAG-Simple-RAG</link>
            <guid>https://velog.io/@so_oni_on/RAG-Simple-RAG</guid>
            <pubDate>Sat, 28 Jun 2025 08:34:49 GMT</pubDate>
            <description><![CDATA[<h1 id="rag">RAG</h1>
<blockquote>
<h3 id="🔎-retrieval-augmented-generation검색-기반-증강-생성-방식">🔎 Retrieval-Augmented Generation(검색 기반 증강 생성 방식)</h3>
</blockquote>
<p>RAG는 검색 기반 증강 생성 방식이다.
이는 모델 파라미터(Parametric Memory)와 외부 지식 베이스(Non-Parametric Memory)를 결합하여, 질의 시점에 관련 문서를 검색하여 Language Model(이하 LM)으로 응답을 생성하는 방식을 통합적으로 수행하는 프레임워크이다.</p>
<p>Retriever&amp;Generator을 활용한 Jointly Fine-tune(즉, Full Fine-tuning)과 비교하여 보았을 때, 
해당 기술의 장점은 다음과 같다.:</p>
<ul>
<li><strong>자원의 제약이 덜하다.</strong></li>
<li>LM의 <strong>Hallucination(환각) 문제를 완화</strong>한다.</li>
<li>추가 지식 업데이트 시, 전체 모델을 다시 훈련시키지 않고 검색 인덱스만 교체하면 <strong>최신 정보를 효과적으로 쉽게 반영</strong>한다. </li>
</ul>
<p>RAG는 단순히 문서를 잘게 쪼개어 프롬프트에 붙여 쓰는 것을 넘어, Retriever과 Generator 두 개의 모듈을 통해 End-to-End로 진행하는 아키텍쳐를 제공한다. </p>
<p>NLP에서의 RAG 기법을 처음 제안한 논문인 &#39;Retrieval-Augmented Generation for
Knowledge-Intensive NLP Tasks&#39;의 아키텍처도는 다음과 같다.</p>
<p align="center">
  <img src="https://velog.velcdn.com/images/so_oni_on/post/134a4172-2adf-416c-9695-8723b1498ef9/image.png" alt="RAG Architecture in Firstly Propsed Paper"/>
  그림1. RAG 논문 제안 구조도
</p> 
<p align="center">
  <img src="https://velog.velcdn.com/images/so_oni_on/post/dd00f2fc-2070-4d3f-943b-debd1c4d735e/image.png" alt="Simple RAG Architecture"/>
  그림2. 간략화된 Simple RAG 구조도
</p> 

<p>RAG 기술은 LM Full Fine-tuning을 위한 고도화된 지식은 필요하지 않으나, 전반적인 LM에 대한 이해는 필요한 분야이다.</p>
<ul>
<li><strong>Retriever(검색기): 문서에 대해 벡터화 및 임베딩으로 효과적인 검색을 도움</strong><ul>
<li>역할: 문서에 대한 벡터 인덱스 구축
→ Encoder-Only 사용(e.g., BERT, DPR)</li>
</ul>
</li>
<li><strong>Generator(생성기): 쿼리에 대한 응답을 만들기 위해 Retrieval 결과를 기반으로 응답 생성</strong><ul>
<li>역할: 쿼리와 관련된 문서 기반 응답 생성
→ Encoder-Decoder Model: 입력과 검색 결과를 한 번에 인코딩한 후, 디코더가 생성을 진행(e.g., T5, BART)
→ Decoder-Only Model: Retrieval 결과를 prompt 맨 앞에 붙여 응답 생성(e.g., GPT 계열 모델)</li>
</ul>
</li>
</ul>
<p>해당 포스트는 전반적인 RAG에 대한 내용은 아니므로 RAG의 세부적인 기법들에 대해서는 언급하지 않을 예정이며, 추후 전반적 RAG에 대한 공부 내용도 게시할 예정이다. 
다만, 해당 포스트는 RAG의 많은 기법들 중, 기본 RAG에 대한 플로우를 제시한 후 Proposition RAG에 사용되는 Propositional Chunking을 중심적으로 공부한 내용을 진행할 예정이다. </p>
<hr>
<h2 id="rag-flow">RAG Flow</h2>
<blockquote>
</blockquote>
<p><strong>1. 문서 준비</strong>
(e.g., pdf, docx, txt 등의 형식)
<strong>2. 문서 Parsing 및 Chunking</strong>
(e.g., Chunking by Line, Chunking by Grammatical Structures..)
<strong>3. 임베딩(Vector Embedding)</strong>
<strong>4. Retrieval</strong>
    - <em>Top-k</em>: FAISS의 코사인 유사도 기반 상위 근거 문장 선택
    - <em>Re-Ranking</em>: Cross-Encoder나 BM25 후처리
    - <em>Chain-of-Retrieval</em>: 1차 검색 → 2차 맥락 확장 검색
    - <em>graphRAG/KG</em>: 규칙 간 관계를 Knowledge Graph(지식 그래프)로 저장 후 활용
<strong>5. 답변을 위한 근거 후보 Selection</strong>
    - <em>Evidence Scoring</em>: 유사도+정확도 가중합 방식<del><em>(현재 프로젝트에서는 아마 이거 사용할 예정)</em></del>
<strong>6. LM Train (Fine-Tuning)</strong>
<strong>7. LM Inference</strong></p>
<hr>
<p>(수정 중)</p>
<hr>
<p>여담으로... 나는 Retriving이라는 말은 한국어로 하면 &#39;검색&#39;이지만.. 단순한 searching의 돋보기 아이콘이 아니라 뭐랄까 모든 문서를 샅샅이 훑으며 관련된 문서를 찾는 그런 그림이 생각이 난다..
전체 문서 네트워크에서 의미 기반으로 연관 문서를 수색하는..... 그런.. 느낌... 
근데 그런 아이콘이 잘 없어서 gpt로 생성을 해봤다 ^.^..    </p>
<p align="center">
  <img src="https://velog.velcdn.com/images/so_oni_on/post/95398a50-42cd-408f-bb1b-fd5e090c64a7/image.png" alt="Generated RAG Icon"/>
  내가 만들었슨
</p>

<hr>
<h3 id="출처">출처</h3>
<ul>
<li>그림1, RAG 논문 제안 구조도: Lewis et al., Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks, NeuralPS 2020(<a href="https://arxiv.org/pdf/2005.11401">https://arxiv.org/pdf/2005.11401</a>)</li>
<li>그림2, 간략화된 Simple RAG 구조도: <a href="https://www.bentoml.com/blog/building-rag-with-open-source-and-custom-ai-models">https://www.bentoml.com/blog/building-rag-with-open-source-and-custom-ai-models</a></li>
<li><a href="https://medium.com/@med.el.harchaoui/rag-evaluation-metrics-explained-a-complete-guide-dbd7a3b571a8">https://medium.com/@med.el.harchaoui/rag-evaluation-metrics-explained-a-complete-guide-dbd7a3b571a8</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Screen 관련 Command 정리]]></title>
            <link>https://velog.io/@so_oni_on/Screen-%EA%B4%80%EB%A0%A8-Command-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@so_oni_on/Screen-%EA%B4%80%EB%A0%A8-Command-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 26 Jun 2025 08:16:25 GMT</pubDate>
            <description><![CDATA[<h2 id="1-명령어">1. 명령어</h2>
<ul>
<li><pre><code>screen -S &lt;session_name&gt;</code></pre><session_name> 으로 새 세션 생성 및 진입</li>
</ul>
<ul>
<li><pre><code>screen -ls</code></pre>실행 중인 screen 세션 목록 확인<ul>
<li><pre><code>screen -r &lt;session_name&gt;</code></pre>분리(detached)된 <session_name> 세션에 재접속</li>
</ul>
</li>
<li><pre><code>screen -d -r &lt;session_name&gt;</code></pre><session_name> 세션을 강제로 분리했다가 재접속</li>
<li><pre><code>screen -x &lt;session_name&gt;</code></pre>동일한 세션에 다중 접속(공유)</li>
<li><pre><code>screen -S &lt;session_name&gt; -X quit</code></pre><session_name> 세션 강제 종료</li>
</ul>
<h2 id="2-특이사항">2. 특이사항</h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[Unsloth 설치 문제 Trouble Shooting]]></title>
            <link>https://velog.io/@so_oni_on/Unsloth-%EC%84%A4%EC%B9%98-%EB%AC%B8%EC%A0%9C-Trouble-Shooting</link>
            <guid>https://velog.io/@so_oni_on/Unsloth-%EC%84%A4%EC%B9%98-%EB%AC%B8%EC%A0%9C-Trouble-Shooting</guid>
            <pubDate>Tue, 24 Jun 2025 09:59:21 GMT</pubDate>
            <description><![CDATA[<p>내가 처한 문제 상황과 오류 코드는 다음과 같았다.</p>
<blockquote>
<h3 id="♨️-문제-상황">♨️ 문제 상황</h3>
<p>Unsloth을 활용한 학습 및 추론이 필요한 상황이었으나, 환경 설정 과정에서 Unsloth이 환경 버전과 안맞아 문제 발생</p>
</blockquote>
<h3 id="🤯-오류-코드">🤯 오류 코드</h3>
<pre><code>ImportError: cannot import name &#39;has_triton&#39; from &#39;torch._inductor.utils&#39;</code></pre><p>(기준 2025.06.)</p>
<h3 id="1-torch-외-다양한-라이브러리-다운그래이드">1. Torch 외 다양한 라이브러리 다운그래이드</h3>
<pre><code>pip install torch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 --index-url https://download.pytorch.org/whl/cu118</code></pre><p>실패 !!!
하지만 진짜 Unsloth을 꼭 필요한 상황이어서 포기할 수가 없었다....</p>
<p>하지만..... 나도 진짜 생전 처음보는 오류코드였슨..~
해당 오류에 대한 글은 구글링을 해도 내용이 크게 없길래 절망하였지만. 해결하였다. !!!!</p>
<p>아래의 순차적으로 적용해보길 바란다.</p>
<h3 id="2-해결-코드">2. 해결 코드</h3>
<pre><code># 현재 환경에서 완전 제거
pip uninstall unsloth triton torch torchvision torchaudio -y

# Triton 먼저 설치
pip install triton

# PyTorch 재설치 (CUDA 11.8 기준)
pip install torch==2.1.0 torchvision==0.16.0 torchaudio==2.1.0 --index-url https://download.pytorch.org/whl/cu118

# Unsloth 설치
pip install &quot;unsloth[colab-new] @ git+https://github.com/unslothai/unsloth.git&quot;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Trouble-Shooting] dlib Installation Error(dlib 설치 오류)]]></title>
            <link>https://velog.io/@so_oni_on/Trouble-Shooting-dlib-Installation-Errordlib-%EC%84%A4%EC%B9%98-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@so_oni_on/Trouble-Shooting-dlib-Installation-Errordlib-%EC%84%A4%EC%B9%98-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Sat, 15 Mar 2025 16:35:20 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/so_oni_on/post/269f6d8d-e1ee-4974-89fc-f4755c95b28d/image.png" alt=""></p>
<p>이런 오류는 한 번쯤은 만나게된다. </p>
<p>[해결방법]</p>
<ol>
<li>기존의 cmake 삭제 및 재설치<pre><code>pip install cmake==3.25.2
pip install dlib==19.24.2</code></pre></li>
</ol>
<p>파이팅 <del>.</del>!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[코랩 런타임 유지 꿀팁]]></title>
            <link>https://velog.io/@so_oni_on/%EC%BD%94%EB%9E%A9-%EB%9F%B0%ED%83%80%EC%9E%84-%EC%9C%A0%EC%A7%80-%EA%BF%80%ED%8C%81</link>
            <guid>https://velog.io/@so_oni_on/%EC%BD%94%EB%9E%A9-%EB%9F%B0%ED%83%80%EC%9E%84-%EC%9C%A0%EC%A7%80-%EA%BF%80%ED%8C%81</guid>
            <pubDate>Thu, 30 Jan 2025 02:27:46 GMT</pubDate>
            <description><![CDATA[<p>코랩으로 오랜 시간(내 기준.. 4시간 이상)의 학습을 돌릴 땐 창을 닫으면 안되며, 켜진 창을 계속 터치해줘야된다는 불편함이 있었다.
코랩은 일정 시간동안 화면이 켜져있다해도, 움직임이 없으면 런타임이 끊기는 것 같았다.</p>
<p>이번 미국에서 비효율의 끝판왕인 나를 보더니 다른 팀원 오빠가 12시간동안 코랩 런타임을 유지하는 방법을 알려줬다.</p>
<p>코랩 노트북에서 f12를 누르고 console 창에서 아래의 코드를 입력하면 된다.</p>
<pre><code>function ClickConnect(){
console.log(&quot;Working&quot;); 
document.querySelector(&quot;colab-toolbar-button#connect&quot;).click() 
}setInterval(ClickConnect, 1800000)</code></pre><p>너무 편하잖아 <del>.</del>,,
서버 못쓰고 코랩 노트북으로 해야될 때 꿀팁인 것 같다!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Transformer를 활용한 텍스트 생성 방식]]></title>
            <link>https://velog.io/@so_oni_on/Transformer%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%83%9D%EC%84%B1-%EB%B0%A9%EC%8B%9D</link>
            <guid>https://velog.io/@so_oni_on/Transformer%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%83%9D%EC%84%B1-%EB%B0%A9%EC%8B%9D</guid>
            <pubDate>Wed, 24 Jul 2024 09:04:13 GMT</pubDate>
            <description><![CDATA[<h3 id="들어가면서">들어가면서.....</h3>
<p>트랜스포머는 유명한 Encoder-Decoder 구조의 모델임 ㅇㅇ
헤헷
디코딩 전략은 &#39;텍스트 생성 과정&#39;에서 중요한 역할을 함
앞서 다른 포스팅에서 설명했지만! 짧게 다시 해당 내용을 설명하자면</p>
<h4 id="encoder">Encoder</h4>
<p><strong>입력 Sequence를 받고 이를 고차원 벡터 표현으로 변환</strong>
여러 개의 Encoder Layers로 구성
Transformer에서는 한 개의 Head인 구조도 있지만 일반적으로 Multi-Head Attention Mechanism과 순전파(Feed-Forward Neural Network)로 이뤄짐
모든 단어와 단어간의 관계를 학습!해서 context의 정보를 capture함
읽어내는 역할</p>
<h4 id="decoder">Decoder</h4>
<p><strong>Encoder에서 전달받은 벡터를 기반으로 출력 Sequence를 생성</strong>
여러 개의 Decoder Layers로 인코더와 겉보기에는 유사한 구조!
하지만 이전에 생성된 출력 단어를 입력으로 받아들이며 <strong><em>Masked Attention</em></strong>을 통해 뒤에 나올 단어를 보지 못하도록 설계됨
생성해내는 영역
-&gt; 각 단계에서 이전에 생성된 단어를 참고해 다음 단어를 예측</p>
<p>그럼 본격적으로 들어가보자!</p>
<h1 id="1-greedy-encoding">1. Greedy Encoding</h1>
<p>매 단계에서 제일 높은 확률을 가진 단어를 선택하여 텍스트 생성</p>
<blockquote>
<p>Pros &amp; Cons
*<em>Pros - *</em> Simple 그리고 Fast~
*<em>Cons - *</em> 항상 Optimal한지 보장불가. 적은 다양성 </p>
</blockquote>
<h1 id="2-beam-search">2. Beam Search</h1>
<p>여러 후보를 동시에 고려하여 가장 가능성이 높은 후보들을 유지합니다. &quot;beam width&quot;라는 매개변수를 설정하여 동시에 고려할 후보의 수를 결정</p>
<blockquote>
<p>Pros &amp; Cons
*<em>Pros - *</em> Simple 그리고 Fast~
*<em>Cons - *</em> 항상 Optimal한지 보장불가. 적은 다양성 </p>
</blockquote>
<h1 id="3-sampling">3. Sampling</h1>
<blockquote>
<p>Pros &amp; Cons
*<em>Pros - *</em> Simple 그리고 Fast~
*<em>Cons - *</em> 항상 Optimal한지 보장불가. 적은 다양성 </p>
</blockquote>
<h1 id="4-top-k-sampling">4. Top-K Sampling</h1>
<blockquote>
<p>Pros &amp; Cons
*<em>Pros - *</em> Simple 그리고 Fast~
*<em>Cons - *</em> 항상 Optimal한지 보장불가. 적은 다양성 </p>
</blockquote>
<h1 id="5-top-pnucleus-sampling">5. Top-P(Nucleus) Sampling</h1>
<p>Beam Search와 샘플링 기법을 결합한 방법 
매 단계에서 Top-k 후보를 유지하면서 비트리기적 탐색을 진행</p>
<blockquote>
<p>Pros &amp; Cons
*<em>Pros - *</em> Simple 그리고 Fast~
*<em>Cons - *</em> 항상 Optimal한지 보장불가. 적은 다양성 </p>
</blockquote>
<h1 id="6-강화-학습reinforcement-learning-기반-디코딩">6. 강화 학습(Reinforcement Learning) 기반 디코딩</h1>
<p>User Feedback 혹은 &#39;특정 목표&#39;에 기반하여 텍스트 생성을 최적화
<strong>보상 신호</strong>를 사용하여 모델이 더 나은 결과를 생성하도록 학습</p>
<blockquote>
<p>보상 신호란?</p>
</blockquote>
<blockquote>
<p>Pros &amp; Cons
*<em>Pros - *</em> 특정 목표에 맞춘 최적화가 가능
*<em>Cons - *</em> 구현이 복잡하고 학습 과정이 길어질 수 있음 </p>
</blockquote>
<hr>
<h3 id="cf">cf)</h3>
<h1 id="reranking"><em>Reranking</em></h1>
<blockquote>
<p>Pros &amp; Cons
*<em>Pros - *</em> Simple 그리고 Fast~
*<em>Cons - *</em> 항상 Optimal한지 보장불가. 적은 다양성 </p>
</blockquote>
<p>-
참고) <a href="https://littlefoxdiary.tistory.com/46">https://littlefoxdiary.tistory.com/46</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL, NLP] Seq2Seq]]></title>
            <link>https://velog.io/@so_oni_on/DL-NLP-Seq2Seq</link>
            <guid>https://velog.io/@so_oni_on/DL-NLP-Seq2Seq</guid>
            <pubDate>Tue, 16 Jul 2024 19:16:15 GMT</pubDate>
            <description><![CDATA[<h1 id="1-sequence-to-sequenceseq2seq-learning">1. Sequence-to-Sequence(Seq2Seq) Learning</h1>
<p>간단히 말해 Sequence를 input-output, 순차적으로 처리하는 것 
<strong>추천 논문: Sutskever et al., 2014 / Cho et al., 2014</strong>
<strong>추천 페이지: Alamar(Attention)</strong></p>
<h2 id="기본-구조">기본 구조</h2>
<h3 id="input-items의-sequence를-받는-모델각-아이템의-일련의-순서">Input: Items의 Sequence를 받는 모델(&#39;각 아이템&#39;의 &#39;일련의 순서&#39;)</h3>
<p>Items의 Sequence는 단어, 캐릭터, 사진의 특징 등이 될 수 있음</p>
<h3 id="output-items의-sequence를-또-다른another-결과물출력로-나타내는-것">Output: Items의 Sequence를 또 다른(another) 결과물(출력)로 나타내는 것</h3>
<p>ex) <img src="https://velog.velcdn.com/images/so_oni_on/post/2d85e131-ae5a-4d01-bc46-69687a937ddd/image.png" alt="">
→ 이런 식으로 나름대로의 방식을 거쳐? 새로운 어떤 출력을 만들어 냄
여기서 주의해야될 점은 input이 세 개일 때 output도 꼭 세 개로 나오는 RNN 모델과는 달리 Input이 세 개여도 Seq2Seq 모델을 거친다면 해당 모델만의 방식으로 Ouput을 4개 혹은 그 이상이하를 출력할 수도 있다는 점!</p>
<p><em>그래서 자주 그리고 많이 사용되는 것이 Machine Translation Model</em>
<em>I(1) am(2) a(3) student(4) » Je(1) suis(2) étudiante(3)</em></p>
<h2 id="핵심-아이디어-및-아키텍처">핵심 아이디어 및 아키텍처</h2>
<h3 id="--encoder">- Encoder</h3>
<h4 id="입력된-정보를-어떻게-저장-및-처리할-것이냐">입력된 정보를 어떻게 &#39;저장&#39; 및 &#39;처리&#39;할 것이냐</h4>
<p>각각의 Input Sequence의 Item을 process 시키고 그 Items가 가진 정보들을 컴파일해서 하나의 벡터로 재정의하는 역할
→ Context Vector
모든 정보들에 대한 Context Vector를 생성하면 Encoder가 Decoder에게 해당 Context Vector를 넘겨줌</p>
<h3 id="--decoder">- Decoder</h3>
<h4 id="encoder에서-압축-입력된-정보를-어떻게-풀어서-반환내놓을-것이냐">Encoder에서 압축 입력된 정보를 어떻게 풀어서 반환(내놓을) 것이냐</h4>
<p>Encoder에서 받은 내용을 Item by Item으로 시퀀스를 출력</p>
<h3 id="그렇다면">그렇다면!!!</h3>
<h4 id="encoder-decoder는-어떤-아키텍쳐를-기반으로-작용할까">Encoder-Decoder는 어떤 아키텍쳐를 기반으로 작용할까?</h4>
<p><strong>제일 기본은 기본 중의 기본 RNN을 사용</strong>
해당 글에서도 RNN을 사용하는 Seq2Seq을 전제하고 설명하겠다
RNN 정리는..... 추가로 할 수 있다면 하겠음
<del><em>불가능이란 없다!!!</em></del></p>
<p>각각의 Hidden State가 업데이트되면서 가장 마지막, 최종의 Hidden State가 Context Vector로 Encoder에서 다 들어오면 Decoder에서 출력으로 작용
RNN의 매커니즘을 잘 생각하며 이해해야됨!! 앞의 Hidden State에서의 결과물이 다음으로 전달되며 업데이트, 쉽게말해 각 Hidden State가 순차적으로 업데이트 및 누적되며 최종 Hidden State가 만들어지며 그걸 통해 Context Vector가 만들어지고 Decoder으로 출력이 만들어짐</p>
<h3 id="but">But!!!</h3>
<p>여기서 생길 수 있는 문제점!!! <strong><em>Gradient Vanishing....!!</em></strong>
간단히 설명하자면 첫 번째 단어는 처음엔 1의 가중치를 가지지만 뒤로 갈수록 쪼개지고 더 쪼개어진다. 그렇다면 문장이 길어졌을 때, 첫 단어의 의미가 소실될 수도 있다는 말이다.
이 점을 어느정도 완화 및 보완하기 위해 LSTM이나 GRU가 나왔지만...</p>
<h4 id="완벽한-기술이란-없는-법">완벽한 기술이란... 없는 법.....</h4>
<h2 id="attention">Attention</h2>
<p>따라서 최근에 Attention<del>이라는 개념을 차용한다
~</del>Attention이 나온지 좀 됐는데 당시 엄!청!나!게! 센세이셔널했다고 ..!!~~</p>
<p>원래라면 Context Vector 자체는 긴 Sequence에 대해서 취약한 점이 많았지만 Attention은 Input Sequence의 Item 중에 특히 주목하고 싶은 부분들에 추가 가중치를 줄 수 있게 연구자가 설정할 수 있도록한다.
<strong>- Bahadanau Attention</strong>
<strong>- Luong Attention</strong>
이렇게 두 가지의 Attention 모델이 있는데 실제 실험결과에 따르면 두 개의 결과가 눈에 띄게 다르진 않았다고 함
따라서 우선 전반적인 Attention을 활용한 Seq2Seq에 대해 설명하겠다</p>
<h3 id="attention-in-seq2seq">Attention in Seq2Seq</h3>
<h4 id="✨차이점-더이상-encoder에-들어가는-sequence의-최종-hidden-state-뿐만-아닌-전반적인-state의-정보를-다-decoder로-넘겨줌✨">✨차이점: 더이상 Encoder에 들어가는 Sequence의 최종 Hidden State &#39;뿐만 아닌&#39; <em>전반적인 State의 정보를 다 Decoder로 넘겨줌!</em>✨</h4>
<p>ㄴ Decoding이 수행되는 과정에서 특히 더 필요한 Hidden State를 입맛에 맞게 골라 서로 다른 가중치를 부여해 활용 가능
예를 들어,
I am a student에서 제일 중요한 부분은 무엇일까? I도 아닌, am도 아닌, &#39;Student&#39;이다! 지금 이 문장이 단순한 문장이어서 그렇지 더 긴 문장 혹은 더 복잡한 정보를 가진 Sequence를 기계 번역 혹은 학습을 시킬 때 이는 매우매우 효율적이고 중요한 작용을 할 것이다!
그래서 Attention in Seq2Seq을 활용한다면 Je(I) 혹은 suis(am)은 연하게, 즉, 크게 중요하지 않게 표시가 될 것이고 <strong>&#39;étudiante&#39;</strong>(Student)는 진하게 표현 될 것이다.</p>
<p>위의 내용은 Encoder쪽의 관점이 더 부여되었다.</p>
<p>이제 Decoder의 관점에서의 Attention in Seq2Seq Learning을 공부해보겠다.
원래의 경우, 아무리 Gradient Vanishing이 완화된 LSTM이나 GRU의 경우라도 최종 Hidden State가 속한 단어가 제일 큰 가중치를 가진다는 것이 전제이자 문제이다.
하지만 Attention은 각 Hidden State에 대해 Score(가중치라 생각해도 될 듯?!)를 부여한 후 입력 신호의 총합을 출력 신호로 변환하는 함수인 Activation Function(활성화 함수), Softmax를 적용
활성화 함수로 구해진 총합으로 하나의 Weighted Vector를 생성 → Context Vector가 되고 해당 내용을 Decoder에서 Output을 만드는 정보로 사용되게 함!!
<br>
실제 Decoder로 넘어갈 때는 Hidden State Vector와 마지막에 생성된 Context Vector가 concat을 하고 사용함(이어 붙이는 그 concat 마자요)
<br>
말이 장황한데 다시 더 간략히 정리해보겠다.</p>
<blockquote>
<p><strong>Step1.</strong> Encoder에서 Sequence를 받은 다음 가중치를 더할 단어를 선정 후, Score 부여
<strong>Step2.</strong> Hidden State에 대해 부여된 Score을 Softmaxed Score로 Weighted Vector 생성(이는 Context Vector로 작용)
<strong>Step3.</strong> 생성된 Context Vector와 Hidden State Vector를 Concatenate(Tensor 크기 변화 있음)
<strong>Step4.</strong> Decoder로 넘어가서 출력 생성</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/ed6fb7d3-3fbe-4821-ba31-0573b058f833/image.png" alt="">
조금 더 자세히 말하자면 원래 모든 Sequence의 시작과 끝을 알리는 Flag같은 존재가 &lt;bos&gt; 혹은 &lt;sos&gt;, 그리고 &lt;eos&gt; 이런 식으로 있다. 아마 해당 Heatmap에서 있는 &lt;end&gt;가 저 &lt;eos&gt;를 뜻하는게 아닐까 유추해본다.</p>
<h1 id="2-transformer">2. Transformer</h1>
<p>..
<img src="https://velog.velcdn.com/images/so_oni_on/post/f24abd6f-ddd4-4f70-aa7e-8910b6b1d606/image.png" alt="">
다음 포스팅에서.....
.........
..............
<img src="https://velog.velcdn.com/images/so_oni_on/post/412247f8-46e9-46bf-85d0-f9a7db047f90/image.png" alt=""></p>
<hr>
<h3 id="결론">결론:</h3>
<p>Tensor 공부를 게을리 하지 말았어야한다..
머릿속에서 빠르게 돌아가지 않는 이상.......</p>
<p><img src="https://velog.velcdn.com/images/so_oni_on/post/4e5d0bd9-7b4c-40c6-96d8-693aeb855525/image.png" alt=""></p>
<p>직접 코딩 실습을 하며 느낀 점이기도 하다.
Pretrained 모델을 사용하기엔 문제가 덜할 수 있지만 진짜 공부해보고싶고 파고들고싶다면 이 내용은 정말 새 발의 피일 것이다.
더 깊게 공부해보고싶다면~ 논문 추천 ㅋㅋ..</p>
<p><br><br></p>
<p>*<em>참고 자료: *</em>
<a href="https://youtu.be/0lgWzluKq1k?feature=shared">https://youtu.be/0lgWzluKq1k?feature=shared</a> 외 ISNLP 출처의 스터디 자료</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[딥러닝/DeepLearning] Seq2Seq(1)]]></title>
            <link>https://velog.io/@so_oni_on/%EB%94%A5%EB%9F%AC%EB%8B%9DDeepLearning-Seq2Seq1</link>
            <guid>https://velog.io/@so_oni_on/%EB%94%A5%EB%9F%AC%EB%8B%9DDeepLearning-Seq2Seq1</guid>
            <pubDate>Tue, 09 Jul 2024 11:01:24 GMT</pubDate>
            <description><![CDATA[<h1 id="seq2seq">Seq2Seq!</h1>
<p>너무나도 어려운 모델이다
모든 공부가 그렇겠지만 겉보기엔 단순히 RNN이랑 같네~ 했는데 내가 잘못 이해했던 것이었다.</p>
<p>Sequence-to-Sequence
말 그대로 순차 데이터를 입력으로 사용하고 순차 데이터도 출력으로 생성하는 기계 학습 모델
관련 수업을 어제 들었는데 나에게는 새롭게 다가오는 말이 있었다.
<strong><em>AI에게는 &#39;생성&#39;도 &#39;분류&#39;이다.</em></strong>
맞는 말이더라 하하 싱기하다</p>
<p>Seq2Seq 모델은 Neural Network, 특히 Recurrent-Neural-Network(RNN)을 활용해 문제를 해결
해당 아키텍처는 NLP작업을 위한 &#39;기본 프레임워크&#39; ㄱ=...로 크게 &#39;Encoder&#39;와 &#39;Decoder&#39; 두 개의 모듈로 구성됨</p>
<blockquote>
<h3 id="✍🏻-encoder인코더">✍🏻 Encoder(인코더)</h3>
<p>입력 시퀀스를 처리 및 고정된 크기로 Context Vector에서 정보를 탐지
Source 문장을 입력받음</p>
</blockquote>
<ul>
<li>Architecture:</li>
</ul>
<ol>
<li>입력 시퀀스를 인코더에 넣음</li>
<li>인코더가 신경망을 사용하는 입력 시퀀스의 각 요소들을 처리
→ 해당 과정을 통해 인코더는 <ul>
<li>&#39;내부상태&#39; 유지</li>
<li>Context Vector역할을 하는 최종 은닉 상태로 작동</li>
<li><em>(Context Vector: 전체 입력 시퀀스의 압축된 상태를 캡슐화한 것이며 입력 시퀀스의 시멘틱한 의미나 주요 정보들을 탐지)*</em>
이런 인코더의 최종 은닉층은 Context Vector를 인코더에서 디코더로 전달<br>
### 🖨️ Decoder(디코더)
Encoder 블록과 유사하지만 Encoder로부터 받은 Context Vector를 점진적으로 출력 시퀀스를 생성
Target 문장을 생성</li>
</ul>
</li>
</ol>
<p><strong>Initial Hidden State로써, Encoder의 Last Word의 &#39;Hidden State&#39;를 입력 받음</strong>
또한 현재 Token을 입력받아 다음 Token을 예측하도록 학습
→ 전의 단어를 기준으로 다음 단어를 예측/추론하는 형식<br>
<strong><em>What if, 앞의 단어가 없는 &#39;문장의 시작&#39;에서는?!</em></strong>
&emsp;&emsp;»     문장의 시작을 알리는 <bos>로 문장의 시작을 선언
&emsp;&emsp;»     문장의 끝을 선언하는 <eos>가 다음 단어로 예측/추론될 때까지 학습 및 수행
 이런 흐름으로 decoder가 수행됨</p>
<ul>
<li>Architecture:</li>
</ul>
<ol>
<li>훈련 단계에서 Decoder는 Context Vector랑 출력하고자하는 출력 시퀀스 둘 다 받음</li>
<li>추론과정에서 이전에 생성된 자체 출력을 후속 단계의 입력으로 사용</li>
</ol>
<p>전반적인 Seq2Seq의 아키텍쳐
<img src="https://velog.velcdn.com/images/so_oni_on/post/dac0d7cd-4c2d-47b3-8f09-10b33bf38271/image.png" alt=""></p>
<p>이러한 Seq2Seq 모델은 RNN을 기본 셀으로 사용하지만 Source와 Target의 단어수가 항상 일치할 수 없는 점과, 나라마다 어순이 다르다는 점을 보완할 수 있는 모델이다.
예를 들어, I(1) am(2) a(3) Student(4).(5)와 Je(1) suis(2) étudiante(3).(4)는 같은 &#39;저는 학생입니다&#39;의 의미를 가지나, 단어의 수가 다르다.
이러한 문제가 발생하는 이유는 다음과 같은 RNN의 특징 때문이라 볼 수 있다.</p>
<blockquote>
<p>RNN은 순차적으로 입력되고 출력된다.
RNN은 input과 output의 1:1 대응을 가진다.
  <img src="https://velog.velcdn.com/images/so_oni_on/post/67aa6ab2-e02a-4075-919b-d3d5e029ed1a/image.png" alt="">
  <img src="https://velog.velcdn.com/images/so_oni_on/post/4ee6a546-daa5-4ad8-abdd-3289b3d39f7a/image.png" alt=""></p>
</blockquote>
<p>다만 내가 헷갈렸던 것은 Tensor를 이동시키는..? 연결시키는..? 그 작업이 머릿속에서 잘 발생하지 않았다.. 많은 노력을 해야될 것으로 예상..
  근데 문제는 이거 헷갈리면 LM head에 누가 들어가고 input이 누구고 다음으로 나와야되는 output의 tensor가 어떻게되고 이게 계속 헷갈리더라.. 아... </p>
<h3 id="🌄-요약">🌄 요약</h3>
<ul>
<li>RNN(혹은 Transformer, GRU 등을 사용) 셀을 활용하는 해당 Seq2Seq 모델은 특히 번역 모델에서 흔히 사용하며 또한 반복되는 형태를 가지고있다.</li>
<li>RNN의 특징 상, 4개의 input이 들어가면 4개의 output이 나와야하지만 번역을 하며 발생하는 언어간의 차이로 1:1대응이 안되는 문제점을 보완할 수 있는 모델<ul>
<li>시작할 때는 <bos> (beginning of sentence)가 꼭 있어야되며 마무리 할 때는 <eos> (end of sentence)가 추론 될 때까지 추론을 진행한다.</li>
</ul>
</li>
<li>Seq2Seq은 학습 단계에서 Teacher Forcing(교사 강제)을 활용함(AtoZ로 다 알려주며 훈련)</li>
<li>Seq2Seq은 학습 완료 후의 단계에서는 출력을 생성하기 위해 학습된 내용을 바탕으로 Inference(추론)를 수행함</li>
</ul>
<blockquote>
<h3 id="✨-to-do-💪🏻">✨ To-Do 💪🏻</h3>
</blockquote>
<ul>
<li><input disabled="" type="checkbox"> LM head에 대한 소개</li>
<li><input disabled="" type="checkbox"> 코드를 활용한 Seq2Seq 구현 방식</li>
<li><input disabled="" type="checkbox"> Auto-Regressive에 대한 설명 </li>
<li><input disabled="" type="checkbox"> 관련 논문(<a href="https://arxiv.org/pdf/1409.3215">https://arxiv.org/pdf/1409.3215</a>) 읽고 더 전문적인 내용으로 정리</li>
<li><input disabled="" type="checkbox"> 조교님한테 첫 번째로 통과받기 ㅡ,,ㅡ</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>