<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>dhlee-note</title>
    <link>https://dhlee-note.tistory.com/</link>
    <description>AI&amp;middot;ML 정리 노트</description>
    <language>ko</language>
    <pubDate>Thu, 28 May 2026 15:05:50 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>dhlee-note</managingEditor>
    <item>
      <title>Verbalized Sampling: How to Mitigate Mode Collapse and Unlock LLM Diversity 논문 리뷰</title>
      <link>https://dhlee-note.tistory.com/entry/Verbalized-Sampling-How-to-Mitigate-Mode-Collapse-and-Unlock-LLM-Diversity-%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;본 논문은 2025년 Stanford 대학교에서 발표한 &quot;Verbalized Sampling: How to Mitigate Mode Collapse and Unlock LLM Diversity&quot; 논문 입니다. 한국어로 번역하면 &quot;언어적 샘플링: 모드 붕괴를 완화하고 LLM 다양성을 확보하는 방법&quot; 입니다. 제목에서 알 수 있듯이 LLM 답변의 다양성이 감소되는 문제에 대한 원인과 학습 없이 이를 해결하는 방법에 대한 내용에 담고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Paper&lt;/b&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://arxiv.org/abs/2510.01171&quot;&gt;https://arxiv.org/abs/2510.01171&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767931292916&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Verbalized Sampling: How to Mitigate Mode Collapse and Unlock LLM Diversity&quot; data-og-description=&quot;Post-training alignment often reduces LLM diversity, leading to a phenomenon known as mode collapse. Unlike prior work that attributes this effect to algorithmic limitations, we identify a fundamental, pervasive data-level driver: typicality bias in prefer&quot; data-og-host=&quot;arxiv.org&quot; data-og-source-url=&quot;https://arxiv.org/abs/2510.01171&quot; data-og-url=&quot;https://arxiv.org/abs/2510.01171v3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/tDLhv/hyZQ3QRpZ1/laINqREuPTF0x92q6tpAn1/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/WzfVc/hyZQYPza5K/kfgaR4nhWXFKrLeK1xtijK/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2510.01171&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://arxiv.org/abs/2510.01171&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/tDLhv/hyZQ3QRpZ1/laINqREuPTF0x92q6tpAn1/img.png?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/WzfVc/hyZQYPza5K/kfgaR4nhWXFKrLeK1xtijK/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Verbalized Sampling: How to Mitigate Mode Collapse and Unlock LLM Diversity&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Post-training alignment often reduces LLM diversity, leading to a phenomenon known as mode collapse. Unlike prior work that attributes this effect to algorithmic limitations, we identify a fundamental, pervasive data-level driver: typicality bias in prefer&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;arxiv.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Website&lt;/b&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.verbalized-sampling.com&quot;&gt;https://www.verbalized-sampling.com&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767931295573&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Verbalized Sampling&quot; data-og-description=&quot;Mitigate Mode Collapse and Unlock LLM Diversity&quot; data-og-host=&quot;www.verbalized-sampling.com&quot; data-og-source-url=&quot;https://www.verbalized-sampling.com&quot; data-og-url=&quot;https://www.verbalized-sampling.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/SQkGa/hyZQ7yXNqy/hrA3OJxxI55JbXj2Z0mpFK/img.jpg?width=2291&amp;amp;height=1180&amp;amp;face=0_0_2291_1180,https://scrap.kakaocdn.net/dn/mh2YI/hyZPDLzAam/nqY7t3JAVvouTuNqbgvwwk/img.jpg?width=2291&amp;amp;height=1180&amp;amp;face=0_0_2291_1180&quot;&gt;&lt;a href=&quot;https://www.verbalized-sampling.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.verbalized-sampling.com&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/SQkGa/hyZQ7yXNqy/hrA3OJxxI55JbXj2Z0mpFK/img.jpg?width=2291&amp;amp;height=1180&amp;amp;face=0_0_2291_1180,https://scrap.kakaocdn.net/dn/mh2YI/hyZPDLzAam/nqY7t3JAVvouTuNqbgvwwk/img.jpg?width=2291&amp;amp;height=1180&amp;amp;face=0_0_2291_1180');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Verbalized Sampling&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Mitigate Mode Collapse and Unlock LLM Diversity&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.verbalized-sampling.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Blog&lt;/b&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://simonucl.notion.site/verbalized-sampling&quot;&gt;https://simonucl.notion.site/verbalized-sampling&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767931297770&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Verbalized Sampling: How to Mitigate Mode Collapse and Unlock LLM Diversity | Notion&quot; data-og-description=&quot;Jiayi Zhang*&amp;sup1;, Simon Yu*&amp;sup1;, Derek Chong*&amp;sup2;, Anthony Sicilia&amp;sup3;,&quot; data-og-host=&quot;simonucl.notion.site&quot; data-og-source-url=&quot;https://simonucl.notion.site/verbalized-sampling&quot; data-og-url=&quot;https://simonucl.notion.site/Verbalized-Sampling-How-to-Mitigate-Mode-Collapse-and-Unlock-LLM-Diversity-28bc4f17675780228ff5fc949260de55&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lq9m8/hyZRjkf1Q6/yaxkCjaTXMJ5tlqaZOa9vK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/OT5W7/hyZPJdXdGP/hREDxDjkkL7jtGP7sCYhIk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://simonucl.notion.site/verbalized-sampling&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://simonucl.notion.site/verbalized-sampling&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lq9m8/hyZRjkf1Q6/yaxkCjaTXMJ5tlqaZOa9vK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/OT5W7/hyZPJdXdGP/hREDxDjkkL7jtGP7sCYhIk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Verbalized Sampling: How to Mitigate Mode Collapse and Unlock LLM Diversity | Notion&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Jiayi Zhang*&amp;sup1;, Simon Yu*&amp;sup1;, Derek Chong*&amp;sup2;, Anthony Sicilia&amp;sup3;,&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;simonucl.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Code&lt;/b&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/CHATS-lab/verbalized-sampling&quot;&gt;https://github.com/CHATS-lab/verbalized-sampling&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1767931299933&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - CHATS-lab/verbalized-sampling: Verbalized Sampling, a training-free prompting strategy to mitigate mode collapse in LLM&quot; data-og-description=&quot;Verbalized Sampling, a training-free prompting strategy to mitigate mode collapse in LLMs by requesting responses with probabilities. Achieves 2-3x diversity improvement while maintaining quality. ...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/CHATS-lab/verbalized-sampling&quot; data-og-url=&quot;https://github.com/CHATS-lab/verbalized-sampling&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bzpx5T/hyZQUdPNWD/aHSViiMK3CbNlOZtSxCh71/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/d0bMAc/hyZQJ4txEi/6rKa8vUJHOHnKzLG62sxO0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/CHATS-lab/verbalized-sampling&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/CHATS-lab/verbalized-sampling&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bzpx5T/hyZQUdPNWD/aHSViiMK3CbNlOZtSxCh71/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/d0bMAc/hyZQJ4txEi/6rKa8vUJHOHnKzLG62sxO0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - CHATS-lab/verbalized-sampling: Verbalized Sampling, a training-free prompting strategy to mitigate mode collapse in LLM&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Verbalized Sampling, a training-free prompting strategy to mitigate mode collapse in LLMs by requesting responses with probabilities. Achieves 2-3x diversity improvement while maintaining quality. ...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style1&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;연구 배경 및 목적&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대규모 언어모델(LLM)은 사전학습 단계에서는 다양한 표현을 생성할 수 있지만, RLHF와 같은 사후 정렬(post-training alignment)을 거치면서 출력이 몇 가지 전형적인 답변으로 수렴하는 모드 붕괴(mode collapse) 문제가 발생한다. 이는 창의적 글쓰기, 사회적 시뮬레이션, 설문&amp;middot;합성 데이터 생성 등 다양성이 핵심인 과제의 성능을 구조적으로 제한한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 연구는 주로 보상모델의 한계나 최적화 알고리즘 문제로 원인을 설명해 왔다. 본 논문의 목적은 다음 두 가지이다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;모드 붕괴의 근본 원인이 알고리즘이 아니라 &amp;lsquo;&lt;b&gt;선호 데이터 자체&lt;/b&gt;&amp;rsquo;에 있음을 규명&lt;/li&gt;
&lt;li&gt;&lt;b&gt;추가 학습 없이(inference-time) 모드 붕괴를 완화&lt;/b&gt;할 수 있는 실용적 방법 제안&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1896&quot; data-origin-height=&quot;1112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8DN3f/dJMcadgnrDn/4fQXkv3PymeP9RKI54MXE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8DN3f/dJMcadgnrDn/4fQXkv3PymeP9RKI54MXE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8DN3f/dJMcadgnrDn/4fQXkv3PymeP9RKI54MXE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8DN3f%2FdJMcadgnrDn%2F4fQXkv3PymeP9RKI54MXE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1896&quot; height=&quot;1112&quot; data-origin-width=&quot;1896&quot; data-origin-height=&quot;1112&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;관련 연구&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(1) 모드 붕괴와 정렬&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선행 연구들은 정렬된 모델이 베이스 모델보다 출력 다양성이 크게 감소함을 실증했다. 다수 연구는 단일 보상모델의 대표성 부족, RLHF의 KL-정규화가 다수 취향을 증폭시키는 구조 등 알고리즘적 요인에 초점을 맞췄다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(2) 다양성 향상 기법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 접근은 크게 세 부류다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;학습 기반 방법&lt;/b&gt;: 추가 정렬이나 특수 목적 학습 (비용 큼)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;디코딩 기법&lt;/b&gt;: temperature, top-p, mirostat 등 (모델&amp;middot;접근 제한)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프롬프트 기법&lt;/b&gt;: 리스트 생성, 창의성 지시 등 (경험적&amp;middot;휴리스틱)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문은 기존 방법을 대체하기보다는, 왜 이런 기법이 근본적으로 한계가 있는지 설명할 수 있는 데이터 중심 관점을 제시한다는 점에서 차별적이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;제안 방안&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(1)&amp;nbsp;핵심&amp;nbsp;원인:&amp;nbsp;Typicality&amp;nbsp;Bias&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저자들은 인간 선호 데이터에 전형성 편향(typicality bias)이 존재한다고 주장한다. 이는 인지심리학에서 잘 알려진 현상으로, 인간 평가자는 익숙하고, 예측 가능하며, 처리하기 쉬운(textually fluent) 응답을 더 좋은 답변으로 평가하는 경향이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를&amp;nbsp;수식화하면,&amp;nbsp;실제&amp;nbsp;과제&amp;nbsp;품질과&amp;nbsp;무관하게&amp;nbsp;베이스&amp;nbsp;모델에서&amp;nbsp;확률이&amp;nbsp;높은(전형적인)&amp;nbsp;응답이&amp;nbsp;보상에서&amp;nbsp;유리해진다.&amp;nbsp;이&amp;nbsp;효과는&amp;nbsp;보상모델이&amp;nbsp;완벽해도&amp;nbsp;제거되지&amp;nbsp;않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(2)&amp;nbsp;이론적&amp;nbsp;결과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RLHF 목적함수에 typicality bias가 포함되면, 최적 정책은 베이스 모델 분포를 온도 감소(샤프닝)한 형태가 된다.&lt;br /&gt;특히 여러 답변이 동일하게 &amp;lsquo;정답&amp;rsquo;인 상황(창의적 과제)에서는 전형성 편향이 사실상의 타이브레이커로 작동해 단일 모드로 수렴한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(3)&amp;nbsp;해결책:&amp;nbsp;&lt;b&gt;Verbalized&amp;nbsp;Sampling&amp;nbsp;(VS)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;1408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m5qNP/dJMcajnliQ9/ecLkdEQ3N2xA1oSjJx5IO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m5qNP/dJMcajnliQ9/ecLkdEQ3N2xA1oSjJx5IO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m5qNP/dJMcajnliQ9/ecLkdEQ3N2xA1oSjJx5IO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm5qNP%2FdJMcajnliQ9%2FecLkdEQ3N2xA1oSjJx5IO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;414&quot; height=&quot;424&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;1408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저자들은&amp;nbsp;학습을&amp;nbsp;바꾸지&amp;nbsp;않고&amp;nbsp;프롬프트&amp;nbsp;자체를&amp;nbsp;바꾸는&amp;nbsp;방법을&amp;nbsp;제안한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;기존&lt;/b&gt;: &amp;ldquo;커피에 대한 농담 하나 말해줘&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;VS&lt;/b&gt;: &amp;ldquo;커피에 대한 농담 5개와 각 농담의 확률을 함께 제시해줘&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 &lt;b&gt;모델은 단일 답변의 최빈값(mode)이 아니라, 사전학습 중 학습한 분포 자체를 &amp;lsquo;설명하도록&amp;rsquo; 강제&lt;/b&gt;된다. 저자들은 이를 &lt;b&gt;분포 수준 프롬프트(distribution-level prompt)&lt;/b&gt;라고 부른다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2708&quot; data-origin-height=&quot;1528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cga9MS/dJMcadUYaSW/ThbIKkhAREPZcKfkJ42DQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cga9MS/dJMcadUYaSW/ThbIKkhAREPZcKfkJ42DQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cga9MS/dJMcadUYaSW/ThbIKkhAREPZcKfkJ42DQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcga9MS%2FdJMcadUYaSW%2FThbIKkhAREPZcKfkJ42DQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2708&quot; height=&quot;1528&quot; data-origin-width=&quot;2708&quot; data-origin-height=&quot;1528&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실험&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저자들은 VS를 다양한 과제와 모델에서 평가했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실험 과제&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;창의적 글쓰기&lt;/b&gt;: 시, 이야기, 농담&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대화 시뮬레이션&lt;/b&gt;: 기부 설득 대화&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Open-ended QA&lt;/b&gt;: 정답이 여러 개인 질문&lt;/li&gt;
&lt;li&gt;&lt;b&gt;합성 데이터 생성&lt;/b&gt;: 수학 문제 생성 후 downstream 성능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;비교 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 프롬프트 방식으로 비교를 했다. 실제 실험에서 사용된 전체 프롬프트는 &lt;b&gt;논문의 Appendix I.2&lt;/b&gt;에 나와있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Direct prompting&lt;/li&gt;
&lt;li&gt;Chain-of-Thought&lt;/li&gt;
&lt;li&gt;리스트 생성&lt;/li&gt;
&lt;li&gt;멀티턴 프롬프트&lt;/li&gt;
&lt;li&gt;VS (Standard / CoT / Multi 변형)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;평가 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 창의적 글쓰기 (Creative Writing: 시&amp;middot;이야기&amp;middot;농담)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) 다양성(Diversity) 평가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 가지 축으로 측정합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;의미적 다양성 (Semantic Diversity)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 응답을 임베딩(예: OpenAI text-embedding-3-small)으로 변환&lt;/li&gt;
&lt;li&gt;모든 응답 쌍의 평균 코사인 유사도 $ \bar{s} $ 계산&lt;/li&gt;
&lt;li&gt;$\text{Diversity}&amp;nbsp;=&amp;nbsp;1&amp;nbsp;-&amp;nbsp;\bar{s}$&amp;nbsp;(백분율로 보고)&lt;/li&gt;
&lt;li&gt;음수 유사도는 0으로 클리핑&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;어휘적 다양성 (Lexical Diversity)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ROUGE-L 사용&lt;br /&gt;$$ \mathrm{ROUGE}\text{-}L&amp;nbsp;=&amp;nbsp;&lt;br /&gt;\frac{(1+\beta^2)\,\frac{\mathrm{LCS}(c,r)}{|c|}\,\frac{\mathrm{LCS}(c,r)}{|r|}}&lt;br /&gt;{\frac{\mathrm{LCS}(c,r)}{|r|}+\beta^2 \frac{\mathrm{LCS}(c,r)}{|c|}} $$&lt;/li&gt;
&lt;li&gt;점수가 낮을수록 다양성이 높음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) 품질(Quality) 평가&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LLM 심판 평가 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시/이야기: Creative Writing v3 루브릭&lt;/li&gt;
&lt;li&gt;농담: HumorBench 루브릭&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;심판 모델: Claude-3.7-Sonnet&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3) 인간 평가(Human Study)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Prolific 참여자 사용&lt;/li&gt;
&lt;li&gt;4점 Likert 척도(매우 유사 &amp;harr; 매우 상이)&lt;/li&gt;
&lt;li&gt;과제별 다양성 정의(플롯&amp;middot;스타일&amp;middot;펀치라인 등) 제공&lt;/li&gt;
&lt;li&gt;평가자 간 일치도(ICC) 보고&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 대화 시뮬레이션 (Dialogue Simulation: 설득 대화)&lt;br /&gt;(1) 행동 결과 정합성 (Donation Amount)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KS 검정(Kolmogorov&amp;ndash;Smirnov test)&amp;rarr; 모델 분포 vs 인간 분포&lt;/li&gt;
&lt;li&gt;L1 거리&amp;rarr; 각 대화별 기부 금액 차이&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) 언어적 정합성 (Linguistic Alignment)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Distinct-1 / 2 / 3: n-그램 다양성&lt;/li&gt;
&lt;li&gt;의미적 다양성: 대화 내 응답 임베딩 기반&lt;/li&gt;
&lt;li&gt;가독성(Readability): Flesch&amp;ndash;Kincaid Grade Level&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 오픈엔디드 QA (Enumerative Open-Ended QA)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다수의 정답이 존재하는 질문(예: &amp;ldquo;미국 주 이름 말해줘&amp;rdquo;)에 대한 평가입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KL Divergence
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;생성된 답변 분포 vs 사전학습 코퍼스(RedPajama) 기준 분포&lt;/li&gt;
&lt;li&gt;낮을수록 이상적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Coverage-N
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;N개 샘플 중 서로 다른 정답의 비율&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Precision
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;생성된 답변 중 정답 비율&lt;/li&gt;
&lt;li&gt;다양성 증가가 정확도를 해치지 않는지 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 합성 데이터 생성 (Synthetic Data Generation)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) 간접 평가 (Downstream Performance)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LLM으로 생성한 수학 문제 1,000개로 소형 모델 SFT&lt;/li&gt;
&lt;li&gt;평가 벤치마크
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MATH500&lt;/li&gt;
&lt;li&gt;OlympiadBench&lt;/li&gt;
&lt;li&gt;Minerva Math&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;지표: 정답 정확도(Accuracy)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 합성 데이터의 &amp;ldquo;좋음/나쁨&amp;rdquo;을 후속 성능 향상 여부로 판단&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 통계적 검증&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대부분의 비교에서 단측 t-test 수행&lt;/li&gt;
&lt;li&gt;유의수준: p &amp;lt; 0.05 / 0.01 / 0.001 표기&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결과&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;1722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q9xFh/dJMcacIABpI/0k0d0k8ezRSkwQQRgrB0DK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q9xFh/dJMcacIABpI/0k0d0k8ezRSkwQQRgrB0DK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q9xFh/dJMcacIABpI/0k0d0k8ezRSkwQQRgrB0DK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ9xFh%2FdJMcacIABpI%2F0k0d0k8ezRSkwQQRgrB0DK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1366&quot; height=&quot;1722&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;1722&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;1342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bk7FYf/dJMcabpmix8/dz31sVeyRTh62a9HDFqLSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bk7FYf/dJMcabpmix8/dz31sVeyRTh62a9HDFqLSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bk7FYf/dJMcabpmix8/dz31sVeyRTh62a9HDFqLSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbk7FYf%2FdJMcabpmix8%2Fdz31sVeyRTh62a9HDFqLSK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;382&quot; height=&quot;466&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;1342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2734&quot; data-origin-height=&quot;1364&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ae1xf/dJMcad1Jw90/kULLFXXNDtYpKO9qQNHS01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ae1xf/dJMcad1Jw90/kULLFXXNDtYpKO9qQNHS01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ae1xf/dJMcad1Jw90/kULLFXXNDtYpKO9qQNHS01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAe1xf%2FdJMcad1Jw90%2FkULLFXXNDtYpKO9qQNHS01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2734&quot; height=&quot;1364&quot; data-origin-width=&quot;2734&quot; data-origin-height=&quot;1364&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2734&quot; data-origin-height=&quot;1364&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAzKOw/dJMcaiIK0Cz/vWLktaSVKle0o5iVATdmKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAzKOw/dJMcaiIK0Cz/vWLktaSVKle0o5iVATdmKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAzKOw/dJMcaiIK0Cz/vWLktaSVKle0o5iVATdmKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAzKOw%2FdJMcaiIK0Cz%2FvWLktaSVKle0o5iVATdmKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2734&quot; height=&quot;1364&quot; data-origin-width=&quot;2734&quot; data-origin-height=&quot;1364&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3242&quot; data-origin-height=&quot;1242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSA1Hx/dJMcahpARPn/sIxKjrjzyYu0MWcV8d4drK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSA1Hx/dJMcahpARPn/sIxKjrjzyYu0MWcV8d4drK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSA1Hx/dJMcahpARPn/sIxKjrjzyYu0MWcV8d4drK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSA1Hx%2FdJMcahpARPn%2FsIxKjrjzyYu0MWcV8d4drK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3242&quot; height=&quot;1242&quot; data-origin-width=&quot;3242&quot; data-origin-height=&quot;1242&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(1) 다양성 - Figure 4, 7&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;VS는 창의적 글쓰기에서 다양성을 1.6&amp;ndash;2.1배 향상&lt;/li&gt;
&lt;li&gt;정렬 단계가 깊어질수록(특히 RLHF 이후) 기존 프롬프트는 급격히 붕괴, VS는 베이스 모델 다양성의 약 67% 유지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(2) 품질 및 정확성 - Figure 4, 9&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다양성 증가에도 불구하고 품질 저하 없음&lt;/li&gt;
&lt;li&gt;Open-ended QA에서 정확도는 거의 동일, 분포는 훨씬 현실적&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(3) 인간 유사성 - Figure 8&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대화 시뮬레이션에서 VS는 기부 금액 분포와 언어 스타일 모두 인간 분포에 더 근접&lt;/li&gt;
&lt;li&gt;일부 대형 모델은 전용 파인튜닝 모델과 동등하거나 상회&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(4) 확장 효과 - Figure 4, Table 4&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모델이 클수록 VS 효과가 더 큼&lt;/li&gt;
&lt;li&gt;합성 데이터 다양성 증가 &amp;rarr; 수학 다운스트림 성능 유의미한 개선&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 논문은 모드 붕괴를 &amp;ldquo;학습이 잘못되었다&amp;rdquo;는 문제가 아니라, &amp;ldquo;인간 선호 데이터의 구조적 편향&amp;rdquo; 문제로 재정의한다. 이를 통해 다음을 보여준다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모드 붕괴는 피하기 어려운 데이터 수준 현상&lt;/li&gt;
&lt;li&gt;정렬된 모델도 잠재적으로는 여전히 풍부한 다양성을 내재&lt;/li&gt;
&lt;li&gt;Verbalized Sampling은 추가 학습 없이 이 다양성을 실질적으로 회복&lt;/li&gt;
&lt;li&gt;품질&amp;middot;안전성을 해치지 않으면서 다양성&amp;ndash;품질 트레이드오프를 개선&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 본 연구는 LLM 정렬의 한계를 설명하는 새로운 이론적 렌즈와, 현업에서 즉시 활용 가능한 간단하지만 강력한 추론 시점 해법을 동시에 제공한다.&lt;/p&gt;</description>
      <category>Papers</category>
      <category>ai</category>
      <category>Large Language Model</category>
      <category>llm</category>
      <category>Prompt Engineering</category>
      <category>Typicality Bias</category>
      <category>Verbalized Sampling</category>
      <category>대규모언어모델</category>
      <category>인공지능</category>
      <category>프롬프트엔지니어링</category>
      <author>dhlee-note</author>
      <guid isPermaLink="true">https://dhlee-note.tistory.com/26</guid>
      <comments>https://dhlee-note.tistory.com/entry/Verbalized-Sampling-How-to-Mitigate-Mode-Collapse-and-Unlock-LLM-Diversity-%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0#entry26comment</comments>
      <pubDate>Fri, 9 Jan 2026 14:53:13 +0900</pubDate>
    </item>
    <item>
      <title>ROUGE 스코어: 요약/생성 모델 평가 지표</title>
      <link>https://dhlee-note.tistory.com/entry/%E3%85%87%E3%85%87</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;텍스트&amp;nbsp;요약이나&amp;nbsp;생성&amp;nbsp;모델을&amp;nbsp;평가할&amp;nbsp;때&amp;nbsp;가장&amp;nbsp;자주&amp;nbsp;등장하는&amp;nbsp;지표가&amp;nbsp;ROUGE(Recall-Oriented&amp;nbsp;Understudy&amp;nbsp;for&amp;nbsp;Gisting&amp;nbsp;Evaluation)입니다.&amp;nbsp;이름&amp;nbsp;그대로&amp;nbsp;&amp;ldquo;정답(레퍼런스)과&amp;nbsp;비교했을&amp;nbsp;때&amp;nbsp;얼마나&amp;nbsp;잘&amp;nbsp;겹치는가&amp;rdquo;를&amp;nbsp;n-그램(연속된&amp;nbsp;단어/토큰&amp;nbsp;묶음)&amp;nbsp;기반으로&amp;nbsp;측정합니다.&amp;nbsp;직관적이고&amp;nbsp;구현이&amp;nbsp;쉬워&amp;nbsp;널리&amp;nbsp;쓰이지만,&amp;nbsp;해석을&amp;nbsp;잘못하면&amp;nbsp;성능을&amp;nbsp;과대/과소평가하기도&amp;nbsp;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;ROUGE는 무엇을 측정하나?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROUGE는 기본적으로 모델 출력(candidate) 과 사람이 만든 정답 요약(reference) 사이의 겹침(overlap) 을 측정합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;겹침이 많다 &amp;rarr; 정답과 비슷한 표현을 많이 썼다&lt;/li&gt;
&lt;li&gt;겹침이 적다 &amp;rarr; 정답과 표현이 다르거나, 핵심을 놓쳤을 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 ROUGE는 &amp;ldquo;의미가 맞는가&amp;rdquo;보다는 &amp;ldquo;표현이 얼마나 비슷한가&amp;rdquo;에 더 가깝습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;가장 많이 쓰는 ROUGE 종류&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) ROUGE-1&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단어(토큰) 1개짜리 n-그램 겹침&lt;/li&gt;
&lt;li&gt;핵심 단어를 얼마나 포함했는지에 민감&lt;/li&gt;
&lt;li&gt;요약 품질을 &amp;ldquo;대략적으로&amp;rdquo; 보기 좋지만, 문장 구조나 흐름은 잘 못 봅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) ROUGE-2&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2-그램(연속된 두 단어/토큰) 겹침&lt;/li&gt;
&lt;li&gt;ROUGE-1보다 문장/표현의 유사성을 더 엄격히 봄&lt;/li&gt;
&lt;li&gt;하지만 한 단어만 달라도 2-그램이 깨져 점수가 크게 흔들릴 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) ROUGE-L&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최장 공통 부분수열(LCS) 기반&lt;/li&gt;
&lt;li&gt;단어가 완전히 연속되지 않아도, 순서가 비슷하면 점수가 나옵니다.&lt;/li&gt;
&lt;li&gt;요약에서 &amp;ldquo;문장 흐름/순서&amp;rdquo;를 어느 정도 반영하고 싶을 때 자주 씁니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;수식 설명&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;후보 요약(모델 출력): $ C $&lt;/li&gt;
&lt;li&gt;참조 요약(정답): $ R $&lt;/li&gt;
&lt;li&gt;$ G_n(T) $: 텍스트 T에서의 모든 n-그램 멀티셋(multiset)&lt;/li&gt;
&lt;li&gt;$ \text{count}_{G}(g) $: 멀티셋 G에서 n-그램 g의 등장 횟수&lt;/li&gt;
&lt;li&gt;중복 등장(같은 n-그램 여러 번)은 카운트로 반영됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) ROUGE-1 / ROUGE-2&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROUGE-1은 n=1 (유니그램), ROUGE-2는 n=2 (바이그램)일 뿐 구조는 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) 겹치는 n-그램 수(클리핑된 overlap)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ \text{Overlap}_n(C,R)&lt;br /&gt;= \sum_{g \in G_n(R)} \min\big(\text{count}_{G_n(C)}(g),\ \text{count}_{G_n(R)}(g)\big) $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 $ \min(\cdot) $ &amp;ldquo;클리핑(clipping)&amp;rdquo;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후보가 어떤 n-그램을 과도하게 반복해도, 참조에 있는 횟수 이상으로는 겹침으로 인정되지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) Recall / Precision / F1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ \text{ROUGE-}n_{\text{recall}} = \frac{\text{Overlap}_n(C,R)}{\sum_{g \in G_n(R)} \text{count}_{G_n(R)}(g)} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ \text{ROUGE-}n_{\text{precision}} = \frac{\text{Overlap}_n(C,R)}{\sum_{g \in G_n(C)} \text{count}_{G_n(C)}(g)} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ \text{ROUGE-}n_{F1} = \frac{2 \cdot \text{ROUGE-}n_{\text{precision}} \cdot \text{ROUGE-}n_{\text{recall}}}{\text{ROUGE-}n_{\text{precision}} + \text{ROUGE-}n_{\text{recall}}} $$&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ROUGE-1: 위 식에서 n=1&lt;/li&gt;
&lt;li&gt;ROUGE-2: 위 식에서 n=2&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무/논문에서 &amp;ldquo;ROUGE-1/2&amp;rdquo;라고만 쓰면 보통 F1을 의미하는 경우가 많지만, 반드시 표기(Recall/Precision/F1)를 확인하는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) ROUGE-L (LCS: 최장 공통 부분수열 기반)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROUGE-L은 n-그램 대신, 두 시퀀스(단어/토큰)의 최장 공통 부분수열 길이를 사용합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$ LCS(C,R) $: C와 R의 최장 공통 부분수열(Longest Common Subsequence)&lt;/li&gt;
&lt;li&gt;$ \text{LCS_len}(C,R) $: 그 길이&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) Recall / Precision&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ R_{LCS} = \frac{\text{LCS_len}(C,R)}{|R|}&lt;br /&gt;\qquad&lt;br /&gt;P_{LCS} = \frac{\text{LCS_len}(C,R)}{|C|} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 |R|, |C|는 각각 토큰(또는 단어) 길이입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) F-Measure (일반화된 $ F_\beta $)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROUGE-L은 흔히 $ \beta $를 사용해 Recall을 더 강조한 $ F_\beta $ 형태로 결합합니다.&lt;br /&gt;&lt;br /&gt;$$ \text{ROUGE-L}&lt;br /&gt;=&amp;nbsp;F_{\beta}&lt;br /&gt;= \frac{(1+\beta^2)\, P_{LCS}\, R_{LCS}}{R_{LCS} + \beta^2 P_{LCS}} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ \beta &amp;gt; 1 $이면 Recall 비중이 더 커집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 구현은 $ \beta = \frac{P_{LCS}}{R_{LCS}} $ 같은 내부 규칙을 쓰거나, 고정값(예: 1.2)을 쓰는 등 라이브러리/설정에 따라 다를 수 있습니다. 따라서 사용한 구현체의 정의를 확인해야 합니다.&lt;/p&gt;</description>
      <category>AI</category>
      <category>Rouge</category>
      <category>ROUGE score</category>
      <category>ROUGE-1</category>
      <category>ROUGE-2</category>
      <category>ROUGE-L</category>
      <category>생성모델평가</category>
      <category>요약모델평가</category>
      <category>평가지표</category>
      <author>dhlee-note</author>
      <guid isPermaLink="true">https://dhlee-note.tistory.com/25</guid>
      <comments>https://dhlee-note.tistory.com/entry/%E3%85%87%E3%85%87#entry25comment</comments>
      <pubDate>Tue, 9 Dec 2025 11:10:17 +0900</pubDate>
    </item>
    <item>
      <title>트리(Tree)와 그래프(Graph)의 차이점 비교</title>
      <link>https://dhlee-note.tistory.com/entry/%ED%8A%B8%EB%A6%ACTree%EC%99%80-%EA%B7%B8%EB%9E%98%ED%94%84Graph%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EB%B9%84%EA%B5%90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;트리(Tree)와 그래프(Graph)는 &lt;b&gt;모두 정점(Vertex)과 간선(Edge)으로 구성&lt;/b&gt;된 자료구조이지만, &lt;span&gt;구조적 규칙과 사용 목적에 큰 차이점&lt;/span&gt;이 있습니다. 크게 5가지로 구분해서 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 구조적 제약의 존재 여부&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;트리&lt;/b&gt;: 제약이 많은 구조
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반드시 &lt;b&gt;하나의 루트(root)&lt;/b&gt;가 존재함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사이클이 존재할 수 없음&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;부모는 하나만&lt;/b&gt;&lt;/span&gt; 가질 수 있음&lt;/li&gt;
&lt;li&gt;연결 구조가 &lt;b&gt;계층적(hierarchical)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그래프&lt;/b&gt;: 제약이 거의 없는 구조
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;루트가 존재할 필요 없음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사이클이 있을 수도 있고 없을 수도 있음&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;한 정점에 &lt;/span&gt;&lt;b&gt;여러 부모 또는 여러 간선 연결 가능&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;구조가 &lt;span&gt;&lt;b&gt;네트워크 형태&lt;/b&gt;&lt;/span&gt;로 자유로움&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 연결 방향&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;트리&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보통 &lt;b&gt;방향성이 있는 구조(부모 &amp;rarr; 자식)&lt;/b&gt;로 취급됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그래프&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;방향 그래프(Directed)&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; 또는 &lt;/span&gt;&lt;b&gt;무방향 그래프(Undirected)&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; 모두 가능함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. 경로의 유일성&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;트리&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;두 정점 사이의 경로는 &lt;b&gt;항상 하나&lt;/b&gt;뿐임&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그래프&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;두 정점 사이에 &lt;/span&gt;&lt;b&gt;여러 경로가 존재할 수 있음&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;심지어 사이클로 인해 무한히 순환할 수도 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4. 정점&amp;middot;간선 수의 관계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;트리&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;항상 간선 수 = 정점 수 - 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그래프&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정점 수에 대해 간선 수에는 제한이 없음&lt;/li&gt;
&lt;li&gt;적어도 0개부터&lt;/li&gt;
&lt;li&gt;최대 N(N-1)개(방향 그래프 기준)까지 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5. 사용 목적&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;트리&lt;/b&gt;: 계층 구조 표현에 적합
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일 시스템&lt;/li&gt;
&lt;li&gt;조직도&lt;/li&gt;
&lt;li&gt;이진 탐색 트리(BST)&lt;/li&gt;
&lt;li&gt;힙(Heap)&lt;/li&gt;
&lt;li&gt;트라이(Trie)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그래프&lt;/b&gt;: 복잡한 관계를 표현하는 데 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크 연결&lt;/li&gt;
&lt;li&gt;SNS 친구 관계&lt;/li&gt;
&lt;li&gt;지도 경로 탐색&lt;/li&gt;
&lt;li&gt;최단 거리 알고리즘&lt;/li&gt;
&lt;li&gt;추천 시스템&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 다음과 같습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;트리(Tree)&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;그래프(Graph)&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;사이클&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;없음&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;있을 수 있음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;루트&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;반드시 존재&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;없어도 됨&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;부모 관계&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;부모 1개&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;여러 개 가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;목적&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;계층 구조 표현&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;복잡한 연결 관계 표현&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;경로 수&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;두 정점 간 경로 1개&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;여러 개 가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;&lt;span&gt;간선 수&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;N-1&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;제약 없음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS</category>
      <category>graph</category>
      <category>tree</category>
      <category>그래프</category>
      <category>그래프자료구조</category>
      <category>그래프트리차이</category>
      <category>알고리즘</category>
      <category>자료구조</category>
      <category>컴퓨터공학</category>
      <category>트리</category>
      <category>트리자료구조</category>
      <author>dhlee-note</author>
      <guid isPermaLink="true">https://dhlee-note.tistory.com/24</guid>
      <comments>https://dhlee-note.tistory.com/entry/%ED%8A%B8%EB%A6%ACTree%EC%99%80-%EA%B7%B8%EB%9E%98%ED%94%84Graph%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EB%B9%84%EA%B5%90#entry24comment</comments>
      <pubDate>Sun, 7 Dec 2025 18:39:31 +0900</pubDate>
    </item>
    <item>
      <title>그래프(Graph) 자료구조 개념 정리 + Python 구현</title>
      <link>https://dhlee-note.tistory.com/entry/%EA%B7%B8%EB%9E%98%ED%94%84Graph-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%84%A4%EB%AA%85-%EB%B0%8F-Python-%EC%98%88%EC%A0%9C-%EC%BD%94%EB%93%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;그래프(Graph)는 현실 세계의 다양한 관계를 표현할 수 있는 강력한 자료구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SNS 친구 관계, 도로 지도, 네트워크 연결 구조 등 우리 주변의 수많은 시스템이 그래프로 모델링될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 그래프의 개념과 핵심 용어, 그리고 간단한 예제를 중심으로 그래프에 대해서 설명하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;그래프(Graph)란 무엇인가?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프는 노드(Node, 정점 Vertex)와 간선(Edge)으로 구성된 자료구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리가 계층 구조를 표현하는 것이라면, 그래프는 &lt;span&gt;&lt;b&gt;복잡한 연결 관계&lt;/b&gt;&lt;/span&gt;를 표현하기 위한 구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프는 다음과 같은 특징을 가집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;노드와 노드가 간선으로 연결되어 있음&lt;/li&gt;
&lt;li&gt;순환(Cycle)이 존재할 수 있음&lt;/li&gt;
&lt;li&gt;데이터 간의 관계를 표현하는 데 매우 적합함&lt;/li&gt;
&lt;li&gt;방향성이 있을 수도 있고 없을 수도 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;그래프의 기본 용어&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프를 이해하기 위해 자주 등장하는 용어들을 먼저 정리해보겠습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;정점(Vertex)&lt;/b&gt;: 그래프에서 점을 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;간선(Edge): &lt;/b&gt;정점과 정점을 연결하는 선입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인접(Adjacency): &lt;/b&gt;두 정점이 간선으로 직접 연결되어 있는 관계입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;차수(Degree): &lt;/b&gt;정점에 연결된 간선의 개수입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;무방향 그래프:&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; 연결된 간선 수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;방향 그래프:&lt;/b&gt;&lt;/span&gt; 진입 차수(In-degree) / 진출 차수(Out-degree)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;경로(Path): &lt;/b&gt;정점을 따라 이동하는 흐름입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사이클(Cycle): &lt;/b&gt;시작 정점과 끝 정점이 동일한 순환 구조입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;그래프의 종류&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프는 여러 형태로 구분될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 무방향 그래프(Undirected Graph): &lt;/b&gt;간선에 방향이 없는 그래프입니다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;A &amp;mdash; B &amp;mdash; C&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 방향 그래프(Directed Graph)&lt;/b&gt;: 간선이 특정 방향을 가지는 그래프입니다.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;A &amp;rarr; B &amp;rarr; C&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 가중치 그래프(Weighted Graph)&lt;/b&gt;: 간선에 비용(Weight)이 있는 그래프입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;A &amp;mdash;5&amp;mdash; B &amp;mdash;7&amp;mdash; C&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4.&amp;nbsp;연결 그래프 / 비연결 그래프&lt;/b&gt;: 모든 정점이 이어져 있으면 연결 그래프입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 사이클 존재 여부&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사이클이 있는 그래프&lt;/li&gt;
&lt;li&gt;무사이클 그래프(DAG, Directed Acyclic Graph)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;그래프 구현 방식&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프는 컴퓨터에서 보통 두 가지 방식으로 표현합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 인접 리스트(Adjacency List)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 정점에 연결된 정점들의 목록을 저장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 효율이 좋고, 대부분의 알고리즘에서 많이 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 인접 행렬(Adjacency Matrix)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정점 수 N일 때 N&amp;times;N 행렬로 연결 여부를 저장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정점 수가 많을수록 메모리 사용량이 커지지만, 두 정점의 연결 여부를 O(1)에 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;파이썬(Python) 예제 코드&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 인접 리스트 예제&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D'],
    'C': ['A'],
    'D': ['B']
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 그래프 탐색: DFS &amp;amp; BFS&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;# DFS
def dfs(graph, start, visited=None):
    if visited is None:
        visited = []
    visited.append(start)
    for node in graph[start]:
        if node not in visited:
            dfs(graph, node, visited)
    return visited

# BFS
from collections import deque

def bfs(graph, start):
    visited = []
    queue = deque([start])
    
    while queue:
        node = queue.popleft()
        if node not in visited:
            visited.append(node)
            queue.extend(graph[node])
    return visited


print(&quot;DFS:&quot;, dfs(graph, 'A'))
print(&quot;BFS:&quot;, bfs(graph, 'A'))&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;DFS: ['A', 'B', 'D', 'C']
BFS: ['A', 'B', 'C', 'D']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프는 &lt;span&gt;&lt;b&gt;경로 찾기, 최단 거리 계산, 사이클 탐지&lt;/b&gt;&lt;/span&gt; 등 다양한 알고리즘의 기반이 되는 자료구조입니다. 특히 &lt;b&gt;DFS(깊이 우선 탐색)&lt;/b&gt;와 &lt;b&gt;BFS(너비 우선 탐색)&lt;/b&gt;은 그래프 문제 해결의 핵심이므로 반드시 익혀두어야 합니다. 또한 직접 그림을 그려보며 정점과 간선의 연결 관계를 시각적으로 이해하면 학습 속도를 크게 높일 수 있습니다. 그래프는 문제 난이도와 유형이 매우 다양하기 때문에 기초 개념을 탄탄하게 다져두는 것이 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프는 현실 세계의 복잡한 관계를 그대로 표현할 수 있는 강력한 구조입니다. 방향성, 가중치, 사이클 여부 등 다양한 조건을 통해 문제를 정의할 수 있으며, 이를 잘 이해하면 &lt;span&gt;&lt;b&gt;최단 경로 알고리즘, 네트워크 분석, 경로 탐색 문제&lt;/b&gt;&lt;/span&gt; 등 여러 분야의 문제를 자연스럽게 해결할 수 있습니다. 자료구조와 알고리즘의 핵심 개념이니 꾸준히 연습과 예제를 통해 익혀두는 것을 추천드립니다.&lt;/p&gt;</description>
      <category>CS</category>
      <category>graph</category>
      <category>python</category>
      <category>그래프</category>
      <category>그래프개념</category>
      <category>그래프예제</category>
      <category>그래프자료구조</category>
      <category>알고리즘</category>
      <category>자료구조</category>
      <category>컴퓨터공학</category>
      <category>파이썬</category>
      <author>dhlee-note</author>
      <guid isPermaLink="true">https://dhlee-note.tistory.com/23</guid>
      <comments>https://dhlee-note.tistory.com/entry/%EA%B7%B8%EB%9E%98%ED%94%84Graph-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%84%A4%EB%AA%85-%EB%B0%8F-Python-%EC%98%88%EC%A0%9C-%EC%BD%94%EB%93%9C#entry23comment</comments>
      <pubDate>Sun, 7 Dec 2025 18:27:00 +0900</pubDate>
    </item>
    <item>
      <title>트리(Tree) 자료구조 개념 정리 + Python 구현</title>
      <link>https://dhlee-note.tistory.com/entry/%ED%8A%B8%EB%A6%ACTree-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%84%A4%EB%AA%85-%EB%B0%8F-Python-%EC%98%88%EC%A0%9C-%EC%BD%94%EB%93%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;자료구조를 공부할 때 반드시 등장하는 구조가 바로 트리(Tree)입니다. 트리는 계층 구조를 표현하기 위해 사용되며, 그래프의 한 형태이기도 합니다. 파일 시스템, 데이터베이스 인덱스, 조직도 등 여러 곳에서 활용되는 매우 중요한 개념입니다. 오늘은 트리의 핵심 개념과 기본 용어, 그리고 대표적인 예제를 중심으로 설명해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;트리(Tree)란 무엇인가?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리는 노드(Node)와 간선(Edge)으로 이루어진 비선형 자료구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 배열이나 연결 리스트처럼 순차적으로 이어지는 구조가 아니라, &lt;span&gt;&lt;b&gt;계층적이며 부모-자식 관계를 가진 구조&lt;/b&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리는 다음과 같은 특징을 가집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 최상위 노드를 루트(root)라고 부릅니다.&lt;/li&gt;
&lt;li&gt;각 노드는 0개 이상의 자식 노드를 가질 수 있습니다.&lt;/li&gt;
&lt;li&gt;사이클이 존재하지 않습니다.&lt;/li&gt;
&lt;li&gt;계층 구조를 표현할 때 적합합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기본 용어 정리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리를 이해하기 위해서는 몇 가지 기본 용어를 알아야 합니다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;루트(Root)&lt;/b&gt;: 트리의 가장 위에 위치한 노드입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;부모(Parent) / 자식(Child): &lt;/b&gt;노드는 하나의 부모를 가지며, 여러 개의 자식을 가질 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;형제(Sibling): &lt;/b&gt;같은 부모를 가진 노드들입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리프(Leaf): &lt;/b&gt;자식이 없는 노드입니다. 트리의 끝에 위치합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서브트리(Subtree): &lt;/b&gt;트리의 일부가 또 하나의 트리 형태를 이루는 구조입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;높이(Height): &lt;/b&gt;트리의 최대 깊이를 의미합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시각적으로 살펴보면 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765098514660&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        A (Root)
       / \
      B   C
     / \   \
    D   E   F (Leaf)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;트리의 중요성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리는 여러 알고리즘과 구조의 기반이 됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;이진 탐색 트리(Binary Search Tree)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;힙(Heap)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;트라이(Trie)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;AVL 트리, 레드-블랙 트리&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;B-Tree, B+Tree (DB 인덱스 제작)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 실제 사용 예는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;운영체제의 &lt;span&gt;&lt;b&gt;파일 시스템&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;회사의 &lt;span&gt;&lt;b&gt;조직도&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;HTML 태그의 &lt;span&gt;&lt;b&gt;DOM 구조&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;데이터베이스의 &lt;/span&gt;&lt;b&gt;검색 및 정렬 구조&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;트리의 종류&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리는 다양한 형태로 확장될 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;이진 트리(Binary Tree)&lt;/b&gt;: 각 노드가 최대 두 개의 자식을 가지는 트리입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이진 탐색 트리(BST): &lt;/b&gt;왼쪽 자식 &amp;lt; 부모 &amp;lt; 오른쪽 자식 규칙을 따르는 트리입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;균형 이진 트리(AVL, Red-Black Tree): &lt;/b&gt;트리가 한쪽으로 치우치지 않도록 자동으로 균형을 맞추는 구조입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;힙(Heap): &lt;/b&gt;최댓값 또는 최솟값을 빠르게 찾기 위한 완전 이진 트리입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;트라이(Trie): &lt;/b&gt;문자열 탐색을 위해 특화된 트리 구조입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;파이썬(Python) 예제 코드&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 가장 기본적인 트리 구조를 표현하는 간단한 예제입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765098631901&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Node:
    def __init__(self, value):
        self.value = value
        self.children = []

    def add_child(self, node):
        self.children.append(node)


# 트리 구성 예시
root = Node(&quot;A&quot;)
node_b = Node(&quot;B&quot;)
node_c = Node(&quot;C&quot;)
node_d = Node(&quot;D&quot;)
node_e = Node(&quot;E&quot;)

root.add_child(node_b)
root.add_child(node_c)
node_b.add_child(node_d)
node_b.add_child(node_e)

# 출력 예시 (단순 구조 출력)
def print_tree(node, level=0):
    print(&quot;  &quot; * level + node.value)
    for child in node.children:
        print_tree(child, level + 1)

print_tree(root)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1765098642724&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;A
  B
    D
    E
  C&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리를 학습할 때는 몇 가지 중요한 포인트를 함께 기억하는 것이 좋습니다. 트리는 &lt;span&gt;&lt;b&gt;재귀(Recursion)&lt;/b&gt;&lt;/span&gt; 개념과 깊게 연결되어 있기 때문에, 재귀 호출 방식에 익숙해질수록 트리 구조를 이해하기가 훨씬 쉽습니다. 또한 &lt;span&gt;&lt;b&gt;DFS(깊이 우선 탐색)&lt;/b&gt;&lt;/span&gt;, BFS(너비 우선 탐색)과 같은 탐색 기법을 함께 공부하면 트리의 동작 방식을 보다 명확하게 파악할 수 있습니다. 무엇보다도 직접 트리를 손으로 그려보며 구조를 시각적으로 이해하는 학습법이 큰 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리는 자료구조의 기초이자 다양한 알고리즘의 기반이 되는 매우 중요한 구조입니다. 계층적 데이터를 표현할 때 널리 사용되며, 코딩 테스트나 개발 실무에서도 자주 등장합니다. 트리를 잘 이해하면 &lt;span&gt;&lt;b&gt;검색, 탐색, 정렬 구조가 동작하는 원리&lt;/b&gt;&lt;/span&gt;까지 자연스럽게 익힐 수 있어 이후의 알고리즘 학습에도 크게 도움이 됩니다.&lt;/p&gt;</description>
      <category>CS</category>
      <category>python</category>
      <category>tree</category>
      <category>데이터구조</category>
      <category>알고리즘</category>
      <category>자료구조</category>
      <category>컴퓨터공학</category>
      <category>트리</category>
      <category>트리개념</category>
      <category>트리예제</category>
      <category>트리자료구조</category>
      <author>dhlee-note</author>
      <guid isPermaLink="true">https://dhlee-note.tistory.com/22</guid>
      <comments>https://dhlee-note.tistory.com/entry/%ED%8A%B8%EB%A6%ACTree-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%84%A4%EB%AA%85-%EB%B0%8F-Python-%EC%98%88%EC%A0%9C-%EC%BD%94%EB%93%9C#entry22comment</comments>
      <pubDate>Sun, 7 Dec 2025 18:16:04 +0900</pubDate>
    </item>
    <item>
      <title>퀵 정렬(Quick Sort) 개념 및 동작 과정 + Python 예제 코드</title>
      <link>https://dhlee-note.tistory.com/entry/%ED%80%B5-%EC%A0%95%EB%A0%ACQuick-Sort-%EC%84%A4%EB%AA%85</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;정렬 알고리즘 중 가장 자주 언급되는 방식이 바로 퀵 정렬(Quick Sort)입니다. 평균적으로 매우 빠른 성능을 보이며, 분할 정복(Divide and Conquer) 전략을 기반으로 동작하는 대표적인 알고리즘입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;퀵 정렬(Quick Sort)이란?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퀵 정렬은 &lt;span&gt;&lt;b&gt;피벗(Pivot)&lt;/b&gt;&lt;/span&gt; 이라고 불리는 기준 값을 중심으로 데이터를 두 그룹으로 나누고, 그 그룹에 대해 재귀적으로 정렬을 수행하는 알고리즘입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퀵 정렬은 다음과 같은 특징을 가지고 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;평균 시간 복잡도&lt;/b&gt;: O(n log n)&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;최악 시간 복잡도&lt;/b&gt;: O(n&amp;sup2;)&lt;/span&gt; (피벗을 잘못 선택할 경우)&lt;/li&gt;
&lt;li&gt;&lt;span&gt;제자리(in-place) 정렬&lt;/span&gt;로 추가적인 메모리가 많이 필요하지 않음&lt;/li&gt;
&lt;li&gt;실제 개발 환경에서 매우 많이 사용되는 효율적인 정렬 기법&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;동작 방식&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퀵 정렬의 핵심 개념은 다음 세 가지입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 피벗(Pivot) 선택&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열에서 하나의 값을 피벗으로 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 쉬운 방법은 &lt;span&gt;&lt;b&gt;첫 번째 값&lt;/b&gt;&lt;/span&gt; 또는 &lt;span&gt;&lt;b&gt;마지막 값&lt;/b&gt;&lt;/span&gt;을 피벗으로 사용하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 분할(Partition)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피벗을 기준으로 &lt;span&gt;&lt;b&gt;피벗보다 작은 값&lt;/b&gt;&lt;/span&gt;과 &lt;span&gt;&lt;b&gt;피벗보다 큰 값&lt;/b&gt;&lt;/span&gt;으로 배열을 나눕니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 재귀 호출&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피벗을 기준으로 분리된 두 부분 배열을 각각 다시 퀵 정렬합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정을 반복하면 전체 배열이 정렬됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;동작 예시&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1765097885479&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[5, 3, 8, 4, 2, 7, 1, 6]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1단계: 피벗 선택&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 첫 번째 값 &lt;span&gt;&lt;b&gt;5&lt;/b&gt;&lt;/span&gt;를 피벗으로 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2단계: 피벗보다 작은 값 / 큰 값 분리&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;작은 값: &lt;/span&gt;[3, 4, 2, 1]&lt;/li&gt;
&lt;li&gt;&lt;span&gt;큰 값: &lt;/span&gt;[8, 7, 6]&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765097923578&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[작은 값들] + [피벗] + [큰 값들]
[3, 4, 2, 1] + [5] + [8, 7, 6]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3단계: 재귀적으로 정렬&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 부분 배열에 다시 퀵 정렬을 적용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;파이썬(Python) 예제 코드&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 가장 기본적인 방식의 퀵 정렬 예제 코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765097970507&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def quick_sort(arr):
    if len(arr) &amp;lt;= 1:
        return arr
    
    pivot = arr[0]
    left = [x for x in arr[1:] if x &amp;lt; pivot]
    right = [x for x in arr[1:] if x &amp;gt;= pivot]
    
    return quick_sort(left) + [pivot] + quick_sort(right)

data = [5, 3, 8, 4, 2, 7, 1, 6]
print(quick_sort(data))&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1765097980950&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[1, 2, 3, 4, 5, 6, 7, 8]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;퀵 정렬을 잘 사용하기 위한 팁&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;피벗 선택 전략&lt;/b&gt;&lt;/span&gt;이 성능에 큰 영향을 미칩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보톤 &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;중앙값(median) 선택, &lt;/span&gt;무작위 피벗(random pivot) 선택 등이 자주 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 거의 정렬된 경우에는 퀵 정렬의 성능이 떨어질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이럴 때는 &lt;/span&gt;&lt;b&gt;삽입 정렬과 혼합한 하이브리드 방식&lt;/b&gt;&lt;span&gt;이 좋습니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>CS</category>
      <category>python</category>
      <category>quicksort</category>
      <category>분할정복</category>
      <category>알고리즘</category>
      <category>자료구조</category>
      <category>정렬 알고리즘</category>
      <category>코딩</category>
      <category>퀵정렬</category>
      <category>파이썬</category>
      <category>프로그래밍</category>
      <author>dhlee-note</author>
      <guid isPermaLink="true">https://dhlee-note.tistory.com/21</guid>
      <comments>https://dhlee-note.tistory.com/entry/%ED%80%B5-%EC%A0%95%EB%A0%ACQuick-Sort-%EC%84%A4%EB%AA%85#entry21comment</comments>
      <pubDate>Sun, 7 Dec 2025 18:03:19 +0900</pubDate>
    </item>
    <item>
      <title>코딩 테스트에서 자주 사용하는 Python 내장 함수 및 라이브러리</title>
      <link>https://dhlee-note.tistory.com/entry/%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%97%90%EC%84%9C-%EC%9E%90%EC%A3%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-Python-%EB%82%B4%EC%9E%A5-%ED%95%A8%EC%88%98-%EB%B0%8F-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. collection.Counter&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;collection.Counter&lt;span style=&quot;background-color: #ffffff; color: #0a0a0a; text-align: start;&quot;&gt;는 파이썬에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;해시 가능한 객체들의 개수를 세어 딕셔너리 형태로 저장하는 컬렉션 클래스&lt;span style=&quot;background-color: #ffffff; color: #0a0a0a; text-align: start;&quot;&gt;입니다. 각 요소는 키가 되고 그 요소의 출현 횟수가 값이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1765856005159&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import Counter

# 리스트, 문자열 또는 다른 이터러블 객체를 Counter에 전달합니다.
data = ['사과', '바나나', '사과', '오렌지', '바나나', '사과']

# Counter 객체 생성
count = Counter(data)

# 결과 출력
print(count)

# 특정 요소의 개수 확인
print(f&quot;'사과'의 개수: {count['사과']}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1765856024371&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Counter({'사과': 3, '바나나': 2, '오렌지': 1})
'사과'의 개수: 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. sort와 sorted&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;list.sort(): 리스트 객체 자체를 제자리에서 정렬하며(in-place), 반환 값은 None입니다. 원본 리스트의 순서가 바뀝니다.&lt;/li&gt;
&lt;li&gt;sorted(): 이터러블한 객체를 정렬한 후 새로운 정렬된 리스트를 반환합니다. 원본 객체는 변경되지 않습니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1765856114523&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fruits = ['grape', 'blueberry', 'apple', 'banana']

# list.sort() (제자리 정렬)
fruits.sort()
print(f&quot;sort() 후: {fruits}&quot;)

# sorted() (새로운 리스트 반환)
data = (5, 2, 8, 1, 9)
sorted_data = sorted(data)
print(f&quot;sorted() 후 (원본 튜플): {data}&quot;)
print(f&quot;sorted() 후 (새 리스트): {sorted_data}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. lamba&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lambda는 한 줄로 간단한 함수를 정의할 때 사용되는 익명 함수 생성 키워드입니다. sort나 sorted의 key 매개변수와 함께 자주 사용됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765856161691&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

# lambda를 사용하여 나이(튜플의 세 번째 요소, 인덱스 2) 기준 정렬
# sorted 함수는 key 매개변수에 함수를 받아 각 요소에 적용한 후 그 반환값으로 정렬합니다.
sorted_students = sorted(students, key=lambda student: student[2])

print(f&quot;나이 기준 정렬: {sorted_students}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4. functools.cmp_to_key&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;functools.cmp_to_key는&amp;nbsp;두&amp;nbsp;개의&amp;nbsp;인자를&amp;nbsp;받아&amp;nbsp;비교&amp;nbsp;결과를&amp;nbsp;반환하는&amp;nbsp;기존&amp;nbsp;스타일의&amp;nbsp;비교&amp;nbsp;함수(comparator,&amp;nbsp;예:&amp;nbsp;a&amp;nbsp;&amp;gt;&amp;nbsp;b이면&amp;nbsp;양수&amp;nbsp;반환)를&amp;nbsp;최신&amp;nbsp;파이썬의&amp;nbsp;key&amp;nbsp;매개변수가&amp;nbsp;요구하는&amp;nbsp;함수로&amp;nbsp;변환해&amp;nbsp;줍니다.&amp;nbsp;파이썬&amp;nbsp;3에서&amp;nbsp;비교&amp;nbsp;함수가&amp;nbsp;key&amp;nbsp;함수로&amp;nbsp;대체되면서&amp;nbsp;하위&amp;nbsp;호환성을&amp;nbsp;위해&amp;nbsp;제공됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765856228307&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import functools

def compare_len(a, b):
    &quot;&quot;&quot;
    문자열 길이를 기준으로 비교하는 함수
    a가 b보다 길면 양수, 같으면 0, 짧으면 음수 반환
    &quot;&quot;&quot;
    if len(a) &amp;lt; len(b):
        return -1
    elif len(a) &amp;gt; len(b):
        return 1
    else:
        return 0

words = ['apple', 'kiwi', 'banana', 'fig']

# cmp_to_key를 사용하여 비교 함수를 key 함수로 변환
sorted_words = sorted(words, key=functools.cmp_to_key(compare_len))

print(f&quot;길이 기준 정렬 (cmp_to_key 사용): {sorted_words}&quot;)

# 참고: 동일한 기능을 key=len 으로 더 간단하게 구현할 수 있습니다.
sorted_words_simple = sorted(words, key=len)
print(f&quot;길이 기준 정렬 (key=len 사용): {sorted_words_simple}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5. zip&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;zip은 여러 개의 이터러블 객체들을 인자로 받아 각 이터러블의 동일한 인덱스에 있는 요소들을 묶어 튜플 형태로 반환하는 이터레이터를 생성합니다. 길이가 가장 짧은 이터러블의 길이에 맞춰 요소 묶기가 종료됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765856289813&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
jobs = ['Engineer', 'Manager', 'Designer', 'CEO'] # 더 긴 리스트

# zip으로 묶기 (가장 짧은 리스트인 ages 기준 3개만 묶임)
zipped_data = zip(names, ages, jobs)

# zip 객체는 이터레이터이므로 리스트로 변환하여 확인
print(f&quot;zip 결과: {list(zipped_data)}&quot;)

# zip 결과로 딕셔너리 만들기
names_short = ['Alice', 'Bob']
ages_short = [25, 30]
print(f&quot;zip으로 딕셔너리 생성: {dict(zip(names_short, ages_short))}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;6. map&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;map은&amp;nbsp;첫&amp;nbsp;번째&amp;nbsp;인자로&amp;nbsp;함수를,&amp;nbsp;두&amp;nbsp;번째&amp;nbsp;인자로&amp;nbsp;이터러블&amp;nbsp;객체를&amp;nbsp;받아&amp;nbsp;해당&amp;nbsp;이터러블의&amp;nbsp;모든&amp;nbsp;요소에&amp;nbsp;함수를&amp;nbsp;적용한&amp;nbsp;결과들을&amp;nbsp;반환하는&amp;nbsp;이터레이터를&amp;nbsp;생성합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1765856324153&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 각 숫자를 제곱하는 함수
def square(n):
    return n * n

numbers = [1, 2, 3, 4, 5]

# map 함수 사용: 리스트의 모든 요소에 square 함수 적용
mapped_data = map(square, numbers)

# map 객체는 이터레이터이므로 리스트로 변환하여 확인
print(f&quot;map 결과 (제곱): {list(mapped_data)}&quot;)

# lambda를 사용하여 간단한 변환도 가능
string_numbers = ['10', '20', '30']
# 각 문자열을 정수로 변환
int_numbers = list(map(lambda s: int(s) + 1, string_numbers))
print(f&quot;map 결과 (문자열-&amp;gt;정수+1): {int_numbers}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;7. min, max&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;min: 전달된 인자들 또는 이터러블 객체 내에서 가장 작은(최소) 값을 반환합니다. 문자열이나 사용자 정의 객체의 경우, 사전 순서나 정의된 비교 기준에 따라 동작하며, key 매개변수를 사용해 비교 기준을 지정할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1765856390461&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 여러 개의 인자 중에서 최솟값 찾기
result_args = min(10, 5, 20, 3, 50)
print(f&quot;인자 중 최솟값: {result_args}&quot;)

# 리스트(이터러블)에서 최솟값 찾기
numbers =
result_list = min(numbers)
print(f&quot;리스트 내 최솟값: {result_list}&quot;)

# key 매개변수 사용 (문자열 길이 기준 최솟값)
words = ['apple', 'fig', 'banana', 'kiwi']
# 길이가 가장 짧은 'fig' 또는 'kiwi' 중 사전순으로 빠른 'fig' 반환
result_key = min(words, key=len)
print(f&quot;길이 기준 최솟값: {result_key}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;max: 전달된 인자들 또는 이터러블 객체 내에서 가장 큰(최대) 값을 반환합니다. min 함수와 마찬가지로 key 매개변수를 사용하여 비교 기준을 지정할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1765856412620&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 여러 개의 인자 중에서 최댓값 찾기
result_args = max(10, 5, 20, 3, 50)
print(f&quot;인자 중 최댓값: {result_args}&quot;)

# 리스트(이터러블)에서 최댓값 찾기
numbers =
result_list = max(numbers)
print(f&quot;리스트 내 최댓값: {result_list}&quot;)

# key 매개변수 사용 (문자열 길이 기준 최댓값)
words = ['apple', 'fig', 'banana', 'kiwi']
# 길이가 가장 긴 'banana' 반환
result_key = max(words, key=len)
print(f&quot;길이 기준 최댓값: {result_key}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;8. 조합 문제: itertools.permutations&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;itertools.permutations는&amp;nbsp;이터러블(예:&amp;nbsp;리스트,&amp;nbsp;문자열)에서&amp;nbsp;r개의&amp;nbsp;항목을&amp;nbsp;선택하여&amp;nbsp;가능한&amp;nbsp;모든&amp;nbsp;순서쌍(순열)을&amp;nbsp;생성하는&amp;nbsp;이터레이터를&amp;nbsp;반환합니다.&amp;nbsp;순서가&amp;nbsp;중요할&amp;nbsp;때(예:&amp;nbsp;비밀번호&amp;nbsp;경우의&amp;nbsp;수&amp;nbsp;계산&amp;nbsp;등)&amp;nbsp;사용되며,&amp;nbsp;r을&amp;nbsp;지정하지&amp;nbsp;않으면&amp;nbsp;이터러블의&amp;nbsp;모든&amp;nbsp;요소를&amp;nbsp;사용한&amp;nbsp;순열을&amp;nbsp;만듭니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765856549719&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import itertools

# 리스트에서 3개의 요소를 사용하여 모든 순열 생성
data = [1, 2, 3]
all_permutations = itertools.permutations(data)

print(f&quot;모든 순열 (r=None): {list(all_permutations)}&quot;)

print(&quot;-&quot; * 20)

# 리스트에서 2개의 요소를 선택하여 순열 생성
data_chars = ['A', 'B', 'C', 'D']
permutations_r2 = itertools.permutations(data_chars, 2)

print(f&quot;2개 선택 순열 (r=2): {list(permutations_r2)}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1765856562788&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;모든 순열 (r=None): [(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
--------------------
2개 선택 순열 (r=2): [('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'A'), ('B', 'C'), ('B', 'D'), ('C', 'A'), ('C', 'B'), ('C', 'D'), ('D', 'A'), ('D', 'B'), ('D', 'C')]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;9. 큐 문제: collection.deque의 append, popleft&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;collections.deque는 양방향에서 빠르게 추가 및 제거가 가능한 자료구조입니다. append와 popleft 메서드를 통해 덱의 양쪽 끝을 효율적으로 관리할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;append: deque의 오른쪽 끝(rear)에 새로운 요소를 추가합니다. 일반 리스트의 append()와 동일하게 동작하며, O(1) 시간 복잡도를 가집니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;popleft: deque의 왼쪽 끝(front)에 있는 요소를 제거하고 해당 요소를 반환합니다. 이 작업 역시 O(1) 시간 복잡도를 가지므로, 선입선출(FIFO) 큐를 구현할 때 매우 효율적입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1765856693455&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import deque

# deque 객체 생성
dq = deque()

print(f&quot;초기 덱: {dq}&quot;)

# append 예시: 오른쪽에 요소 추가
dq.append('A')
dq.append('B')
dq.append('C')
print(f&quot;append 후 덱: {dq}&quot;)

# popleft 예시: 왼쪽에서 요소 제거 및 반환
item1 = dq.popleft()
print(f&quot;popleft로 제거된 항목: {item1}&quot;)
print(f&quot;popleft 후 덱: {dq}&quot;)

item2 = dq.popleft()
print(f&quot;popleft로 제거된 항목: {item2}&quot;)
print(f&quot;popleft 후 덱: {dq}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1765856706066&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;초기 덱: deque([])
append 후 덱: deque(['A', 'B', 'C'])
popleft로 제거된 항목: A
popleft 후 덱: deque(['B', 'C'])
popleft로 제거된 항목: B
popleft 후 덱: deque(['C'])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;10. any와 all&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;any와 all은 파이썬의 내장 함수로, 이터러블(iterable) 객체의 요소들이 특정 조건을 만족하는지 여부를 확인할 때 사용됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;any: 이터러블 내의 최소한 하나의 요소라도 참(True)으로 평가되면 True를 반환하며, 모든 요소가 거짓일 때만 False를 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1765856781998&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 숫자 리스트 (0은 False로 평가됨)
numbers =

# 0이 아닌 값이 하나라도 있으므로 True 반환
result_any_true = any(numbers)
print(f&quot;any({numbers}): {result_any_true}&quot;)

# 모든 요소가 0 또는 빈 값인 경우 (모두 False)
empty_list =
result_any_false = any(empty_list)
print(f&quot;any({empty_list}): {result_any_false}&quot;)

# 조건식을 map/제너레이터와 함께 사용
# 10보다 큰 수가 하나라도 있는지 확인
result_condition = any(num &amp;gt; 10 for num in numbers)
print(f&quot;any(num &amp;gt; 10 for num in numbers): {result_condition}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;all: 이터러블 내의 모든 요소가 참(True)으로 평가될 때만 True를 반환하며, 하나의 요소라도 거짓이면 False를 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1765856798761&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 예시 코드

# 모든 요소가 참인 리스트
true_list =
result_all_true = all(true_list)
print(f&quot;all({true_list}): {result_all_true}&quot;)

# 하나라도 거짓(False)인 요소가 있는 리스트
mixed_list = [True, False, True, True]
result_all_false = all(mixed_list)
print(f&quot;all({mixed_list}): {result_all_false}&quot;)

# 조건식을 map/제너레이터와 함께 사용
# 모든 수가 5보다 큰지 확인
numbers =
result_condition = all(num &amp;gt; 5 for num in numbers)
print(f&quot;all(num &amp;gt; 5 for num in numbers): {result_condition}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;11. 최소 힙 문제: heapq의 heapify, heappop, heappush&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;heapq 모듈은 파이썬에서 힙(heap) 자료구조, 특히 최소 힙(min-heap)을 구현할 때 사용되는 표준 라이브러리입니다. heapify, heappush, heappop은 힙의 핵심 연산을 수행하는 함수입니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;heapify: 기존에 요소들이 들어있는 일반 리스트를 인플레이스(in-place) 방식으로 최소 힙 구조로 변환합니다. O(n) 시간 복잡도로 리스트를 힙 속성이 만족되도록 재정렬합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;heappush: 힙에 새로운 요소를 효율적으로 삽입합니다. 삽입 후에도 힙 속성을 유지하도록 자동으로 요소를 재배치하며, O(log n) 시간 복잡도를 가집니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;heappop: 힙에서 가장 작은(최소) 요소를 제거하고 반환합니다. 루트(root) 노드를 제거한 후, 나머지 요소들을 재정렬하여 힙 속성을 유지하며, O(log n) 시간 복잡도를 가집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1765856946282&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import heapq

# 1. heapify 예시: 일반 리스트를 힙으로 변환
data =
heapq.heapify(data)
print(f&quot;heapify 후 힙: {data}&quot;)

# 2. heappush 예시: 새로운 요소 삽입
heapq.heappush(data, 1)
print(f&quot;heappush(1) 후 힙: {data}&quot;)
heapq.heappush(data, 100)
print(f&quot;heappush(100) 후 힙: {data}&quot;)

# 3. heappop 예시: 가장 작은 요소 제거 및 반환
min_item1 = heapq.heappop(data)
print(f&quot;heappop으로 제거된 최소값: {min_item1}&quot;)
print(f&quot;heappop 후 힙: {data}&quot;)

min_item2 = heapq.heappop(data)
print(f&quot;heappop으로 제거된 최소값: {min_item2}&quot;)
print(f&quot;heappop 후 힙: {data}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1765856955750&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;heapify 후 힙: [1, 2, 4, 8, 3, 9, 7]
heappush(1) 후 힙: [1, 1, 4, 8, 3, 9, 7, 2]
heappush(100) 후 힙: [1, 1, 4, 8, 3, 9, 7, 2, 100]
heappop으로 제거된 최소값: 1
heappop 후 힙: [1, 2, 4, 8, 3, 9, 7, 100]
heappop으로 제거된 최소값: 1
heappop 후 힙: [2, 3, 4, 8, 100, 9, 7]&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Development</category>
      <category>python</category>
      <category>python 내장 함수</category>
      <category>python 라이브러리</category>
      <category>알고리즘</category>
      <category>자료구조</category>
      <category>취업준비</category>
      <category>코딩</category>
      <category>코딩테스트</category>
      <category>코테</category>
      <category>파이썬</category>
      <author>dhlee-note</author>
      <guid isPermaLink="true">https://dhlee-note.tistory.com/20</guid>
      <comments>https://dhlee-note.tistory.com/entry/%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%97%90%EC%84%9C-%EC%9E%90%EC%A3%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-Python-%EB%82%B4%EC%9E%A5-%ED%95%A8%EC%88%98-%EB%B0%8F-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC#entry20comment</comments>
      <pubDate>Sun, 7 Dec 2025 17:52:48 +0900</pubDate>
    </item>
    <item>
      <title>LangChain Expression Language(LCEL) 사용 방법 및 예시</title>
      <link>https://dhlee-note.tistory.com/entry/LangChain-Expression-LanguageLCEL</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;LangChain Expression Language(LCEL)은 LangChain에서 여러 컴포넌트(prompt, LLM, 파서, 후처리 함수 등)를 &amp;ldquo;파이프(pipe)&amp;rdquo; 형태로 간결하게 연결해 주는 표현 방식입니다. 2023년 하반기부터 LangChain에서 체인(chain) 구성 방식에서 LCEL을 활용하는 경향이 커지고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 LCEL의 주요 개념과 예제에 대해서 정리해보도록 하겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주요 개념&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Runnable&lt;/b&gt;: 입력(input)을 받아 출력(output)을 내는 구성 요소&lt;/li&gt;
&lt;li&gt;&lt;b&gt;RunnableSequence&lt;/b&gt;: 여러 Runnable을 직렬(sequence) 로 연결한 것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;RunnableLambda&lt;/b&gt;: 단순한 Python 함수를 Runnable로 감싸서 파이프에서 쓸 수 있게 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;RunnableParallel&lt;/b&gt;: 여러 Runnable을 병렬(parallel)으로 실행하고, 결과를 병합(예: 딕셔너리 구조)해서 넘김&lt;/li&gt;
&lt;li&gt;&lt;b&gt;RunnablePassthrough&lt;/b&gt;: 현재 입력 값을 &amp;ldquo;넘겨주는(pass through)&amp;rdquo; 역할. 병렬 구조에서 입력을 일부 다음 단계에서도 쓰고 싶을 때 유용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;| 연산자 (파이프)&lt;/b&gt;: Runnable들을 직렬(sequence)로 연결. 입력 &amp;rarr; 컴포넌트1 &amp;rarr; 컴포넌트2 &amp;rarr; &amp;hellip; &amp;rarr; 출력 흐름이 생김&lt;/li&gt;
&lt;li&gt;&lt;b&gt;invoke / batch / stream&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;invoke(input) : 단일 입력에 대해 동기(synchronous) 실행&lt;/li&gt;
&lt;li&gt;batch([input1, input2, &amp;hellip;]) : 여러 입력을 한 번에 처리&lt;/li&gt;
&lt;li&gt;stream(input) : 출력이&amp;nbsp;길거나&amp;nbsp;점진적으로&amp;nbsp;생성되는&amp;nbsp;경우&amp;nbsp;청크&amp;nbsp;단위로&amp;nbsp;결과&amp;nbsp;반환&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;예제 및 실행 결과&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Runnable&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LCEL에서&amp;nbsp;모든&amp;nbsp;구성&amp;nbsp;요소는&amp;nbsp;Runnable&amp;nbsp;인터페이스를&amp;nbsp;따릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 예제 코드에 등장하는 prompt, llm, parser 모두 Runnable입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1758447265635&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from dotenv import load_dotenv
import os
import openai

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

load_dotenv()
openai.api_key = os.getenv(&quot;OPENAI_API_KEY&quot;)

# Runnable 예시: Prompt, LLM, Parser 모두 Runnable
prompt = ChatPromptTemplate.from_template(&quot;Translate to English: {text}&quot;)
llm = ChatOpenAI(model=&quot;gpt-3.5-turbo&quot;)
parser = StrOutputParser()

# 체인 구성
chain = prompt | llm | parser

print(chain.invoke({&quot;text&quot;: &quot;안녕하세요&quot;}))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1758449052174&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Hello&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;RunnableSequence&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RunnableSequence는 여러 Runnable을 직렬(sequence) 로 연결하는 방법을 코드로 직접 정의하는 방식입니다.&lt;br /&gt;보통은 a | b | c 같은 파이프(|) 연산자를 더 자주 쓰지만, 내부적으로는 RunnableSequence를 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예제 코드를 RunnableSequence로 변경하면 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1758448202287&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from dotenv import load_dotenv
import os
import openai

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.runnables import RunnableSequence

load_dotenv()
openai.api_key = os.getenv(&quot;OPENAI_API_KEY&quot;)

# Runnable 예시: Prompt, LLM, Parser 모두 Runnable
prompt = ChatPromptTemplate.from_template(&quot;Translate to English: {text}&quot;)
llm = ChatOpenAI(model=&quot;gpt-3.5-turbo&quot;)
parser = StrOutputParser()

# RunnableSequence로 체인 구성
chain = RunnableSequence(first=prompt, last=llm | parser)

# 실행
print(chain.invoke({&quot;text&quot;: &quot;안녕하세요&quot;}))&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1758449127291&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Hello&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;RunnableLambda&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접&amp;nbsp;만든&amp;nbsp;Python&amp;nbsp;함수를&amp;nbsp;LCEL&amp;nbsp;파이프라인에&amp;nbsp;포함하려면&amp;nbsp;RunnableLambda를&amp;nbsp;씁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반&amp;nbsp;Python&amp;nbsp;함수를&amp;nbsp;체인&amp;nbsp;속에&amp;nbsp;넣을&amp;nbsp;때&amp;nbsp;유용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1758447399985&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from langchain_core.runnables import RunnableLambda

# 간단한 함수
def double_number(x: int) -&amp;gt; int:
    return x * 2

# Runnable로 감싸기
double = RunnableLambda(double_number)

print(double.invoke(5))&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1758449161741&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;10&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;RunnableParallel&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러&amp;nbsp;Runnable을&amp;nbsp;동시에&amp;nbsp;실행하고,&amp;nbsp;결과를&amp;nbsp;딕셔너리&amp;nbsp;형태로&amp;nbsp;모아줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력값을&amp;nbsp;동시에&amp;nbsp;여러&amp;nbsp;방식으로&amp;nbsp;가공하고&amp;nbsp;싶을&amp;nbsp;때&amp;nbsp;사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1758447490473&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from langchain_core.runnables import RunnableParallel, RunnableLambda

# 간단한 Runnable 두 개
add_one = RunnableLambda(lambda x: x + 1)
square = RunnableLambda(lambda x: x * x)

# 병렬 실행: 같은 입력 x에 대해 add_one과 square 동시에 실행
parallel = RunnableParallel({
    &quot;plus_one&quot;: add_one,
    &quot;squared&quot;: square
})

print(parallel.invoke(3))&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1758449185207&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{'plus_one': 4, 'squared': 9}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RunnableParallel를 사용하지 않고 병렬적으로 사용하는 방법도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1758447883986&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from langchain_core.runnables import RunnableParallel, RunnableLambda

# 간단한 Runnable 두 개
add_one = RunnableLambda(lambda x: x + 1)
square = RunnableLambda(lambda x: x * x)

# 병렬 실행: 같은 입력 x에 대해 add_one과 square 동시에 실행
parallel = {
    &quot;plus_one&quot;: add_one,
    &quot;squared&quot;: square
}

print(parallel.invoke(3))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;RunnablePassthrough&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력 dict 전체를 출력으로 보존합니다.&lt;br /&gt;특히 병렬 실행할 때, 원본 입력을 결과에 같이 포함시키고 싶을 때 자주 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1758447617352&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from langchain_core.runnables import RunnablePassthrough, RunnableParallel, RunnableLambda

# 입력값을 두 배로 만드는 Runnable
double = RunnableLambda(lambda x: x * 2)

# 원본 입력과 가공된 값을 모두 반환
chain = RunnableParallel({
    &quot;original&quot;: RunnablePassthrough(),
    &quot;doubled&quot;: double
})

print(chain.invoke(7))&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주의 사항&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;입출력 형태(shape) 주의&lt;/b&gt;&lt;br /&gt;각&amp;nbsp;Runnable이&amp;nbsp;어떤&amp;nbsp;입력을&amp;nbsp;받고&amp;nbsp;어떤&amp;nbsp;출력을&amp;nbsp;내는지&amp;nbsp;명확히&amp;nbsp;해야&amp;nbsp;downstream&amp;nbsp;에러를&amp;nbsp;줄일&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;타입 힌트나 input_schema, output_schema를 활용하면 안정성이 높아집니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;병렬 작업 시 비용/지연 고려&lt;/b&gt;&lt;br /&gt;병렬 실행은 네트워크 호출 수를 늘리므로 latency 증가나 rate limit 문제를 유발할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스트리밍 지원 여부 확인&lt;/b&gt;&lt;br /&gt;.stream()/.astream() 사용 시, 모델이 스트리밍을 지원하는지 확인해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;비동기 실행&lt;/b&gt;&lt;br /&gt;서버 환경에서는 .ainvoke(), .abatch() 같은 비동기 메서드를 적극 활용하는 것이 좋습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;디버깅 &amp;amp; 추적&lt;br /&gt;&lt;/b&gt;간단히는 RunnableLambda(lambda x: print(x) or x) 같은 방식으로 중간 출력 로깅이 가능합니다.&lt;br /&gt;본격적인 추적은 LangSmith 같은 툴과 연동해 각 단계의 입력/출력을 살펴보는 것이 좋습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;조건 분기 / Fallback&lt;/b&gt;&lt;br /&gt;LCEL은&amp;nbsp;조건에&amp;nbsp;따라&amp;nbsp;다른&amp;nbsp;체인을&amp;nbsp;실행하거나,&amp;nbsp;실패&amp;nbsp;시&amp;nbsp;대체&amp;nbsp;경로(fallback)를&amp;nbsp;두는&amp;nbsp;방식도&amp;nbsp;지원합니다.&lt;br /&gt;(예: 입력이 영어면 그대로 출력, 아니면 번역 LLM 호출)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;버전 호환성&lt;/b&gt;&lt;br /&gt;LCEL API는 langchain-core 버전별로 일부 차이가 있을 수 있으므로, 공식 문서의 Cheat Sheet 를 반드시 참고하세요.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>Development</category>
      <category>ai</category>
      <category>LangChain</category>
      <category>LangChain Expression Language</category>
      <category>lcel</category>
      <category>llm</category>
      <category>python</category>
      <category>랭체인</category>
      <category>생성형AI</category>
      <category>인공지능</category>
      <category>파이썬</category>
      <author>dhlee-note</author>
      <guid isPermaLink="true">https://dhlee-note.tistory.com/19</guid>
      <comments>https://dhlee-note.tistory.com/entry/LangChain-Expression-LanguageLCEL#entry19comment</comments>
      <pubDate>Sun, 7 Dec 2025 17:49:42 +0900</pubDate>
    </item>
    <item>
      <title>베이지안 정리(Bayes' theorem)</title>
      <link>https://dhlee-note.tistory.com/entry/%EB%B2%A0%EC%9D%B4%EC%A7%80%EC%95%88-%EC%A0%95%EB%A6%ACBayes-theorem</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;베이지안 정리(Bayes' theorem)는 사전 확률(prior)을 관찰된 데이터 정보를 반영해 사후 확률(posterior)로 갱신하는 규칙입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ P(A\mid B)=\frac{P(B\mid A)P(A)}{P(B)} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;$ P(A \mid B) $: &lt;/span&gt;&lt;span&gt;사건 &lt;/span&gt;B가 일어났다는 정보를 알고 있을 때, A가 일어났을 확률(사후 확률)&lt;/li&gt;
&lt;li&gt;&lt;span&gt;$ P(B \mid A) $: &lt;/span&gt;&lt;span&gt;A가 참일 때 B가 관측될 &lt;/span&gt;가능도(우도, likelihood)&lt;/li&gt;
&lt;li&gt;&lt;span&gt;$ P(A) $:&lt;/span&gt; 관측하기 전에 A가 일어날 것으로 믿는 &lt;span&gt;A에 대한 &lt;/span&gt;사전 확률(prior)&lt;/li&gt;
&lt;li&gt;&lt;span&gt;$ P(B) $:&lt;/span&gt; &lt;span&gt;B가 관측될 전체 확률&lt;/span&gt;&lt;span&gt;로, 사후 확률이 전체적으로 1이 되도록 만드는 역할을 함(evidence, 정규화 상수)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span&gt;예제&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 질병의 발병률(사전 확률)은 1% (=0.01)이며, 검사 특성은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;민감도(sensitivity): 질병이 있으면 양성 &amp;rarr; $ P(+ \mid \text{Disease}) = 0.99 $&lt;/li&gt;
&lt;li&gt;위양성률(false positive rate)&lt;span&gt;: 질병이 없는데 양성 &amp;rarr; $ &lt;/span&gt;&lt;span&gt;P(+ \mid \text{No\ Disease}) = 0.05 $&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 알고 싶은 값은 $ &lt;span&gt;P(\text{Disease} \mid +) $ 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;즉, &lt;/span&gt;검사에서 양성이 나왔을 때 실제로 질병일 확률을 알아내야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 베이지안 정리 적용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;베이지안 정리에 따르면, 다은과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;$$ P(\text{Disease} \mid +)= \frac{P(+ \mid \text{Disease}) \, P(\text{Disease})}{P(+)} $$&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사전 확률(prior): $ &lt;span&gt;P(\text{Disease}) = 0.01 $&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;우도(likelihood): $ &lt;span&gt;P(+ \mid \text{Disease}) = 0.99 $&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Evidence 계산: &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;양성이 나올 전체 확률&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;P(+)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양성(+)이 나올 수 있는 경우는 두 가지 입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;질병이 있는데 양성: $ &lt;span&gt;0.01 \times 0.99 $&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;질병이 없는데 양성(위양성): $ &lt;span&gt;0.99 \times 0.05 $&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 전체 양성 확률은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;$$ P(+) = 0.01 \cdot 0.99 + 0.99 \cdot 0.05 $$&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 두 번째 항이 더 큰 이유는 질병이 없을 확률(99%)이 매우 높기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 희귀한 질병에서는 위양성이 전체 결과에 큰 비중을 차지합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 사후 확률 계산&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 베이지안 정리에 대입을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;$$ P(\text{Disease}\mid +) = \frac{0.99 \times 0.01}{0.01 \times 0.99 + 0.99 \times 0.05} $$&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수치를 정리하면 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;분자: &lt;/span&gt;&lt;span&gt;0.0099&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Evidence: 약 &lt;/span&gt;&lt;span&gt;0.0594&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 검사에서 양성이 나왔을 때 실제 질병일 확률은 약 16.7% 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;$$ P(\text{Disease}\mid +) \approx \frac{0.0099}{0.0594} \approx 0.1667 $$&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &amp;ldquo;99% 정확한 검사&amp;rdquo;라고 해도, 질병의 발병률이 매우 낮다면 양성 결과가 나온 사람의 대부분은 실제 환자가 아닐 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 베이지안 정리가 실생활에서 왜 중요한지를 잘 보여주는 대표적인 사례입니다.&lt;/p&gt;</description>
      <category>AI</category>
      <category>ai</category>
      <category>BayesianTheorem</category>
      <category>BayesTheorem</category>
      <category>Deeplearning</category>
      <category>MachineLearning</category>
      <category>딥러닝</category>
      <category>머신러닝</category>
      <category>베이즈 정리</category>
      <category>베이지안 정리</category>
      <category>인공지능</category>
      <author>dhlee-note</author>
      <guid isPermaLink="true">https://dhlee-note.tistory.com/18</guid>
      <comments>https://dhlee-note.tistory.com/entry/%EB%B2%A0%EC%9D%B4%EC%A7%80%EC%95%88-%EC%A0%95%EB%A6%ACBayes-theorem#entry18comment</comments>
      <pubDate>Sun, 7 Dec 2025 17:38:05 +0900</pubDate>
    </item>
    <item>
      <title>주성분 분석(PCA, Principal Component Analysis)</title>
      <link>https://dhlee-note.tistory.com/entry/%EC%A3%BC%EC%84%B1%EB%B6%84-%EB%B6%84%EC%84%9DPCA-Principal-Component-Analysis</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 분석과 머신러닝을 하다 보면 공통적으로 마주치는 문제가 있습니다.&lt;br /&gt;바로 차원의 저주(Curse of Dimensionality)입니다.&lt;br /&gt;특징(Feature)의 수가 많아질수록 모델의 계산 복잡도는 증가하고, 시각화와 해석 또한 어려워집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하는 대표적인 방법이 바로 주성분 분석(PCA, Principal Component Analysis)입니다.&lt;br /&gt;PCA는&amp;nbsp;원본&amp;nbsp;데이터의&amp;nbsp;정보를&amp;nbsp;최대한&amp;nbsp;유지하면서&amp;nbsp;차원을&amp;nbsp;축소해 주는&amp;nbsp;강력한&amp;nbsp;기법으로,&amp;nbsp;데이터&amp;nbsp;전처리와&amp;nbsp;탐색적&amp;nbsp;분석&amp;nbsp;과정에서&amp;nbsp;매우&amp;nbsp;자주&amp;nbsp;활용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PCA란?&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bm5eON/dJMcaa4OUY1/gkPkg7jMKHssjOf8z8Hv41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bm5eON/dJMcaa4OUY1/gkPkg7jMKHssjOf8z8Hv41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bm5eON/dJMcaa4OUY1/gkPkg7jMKHssjOf8z8Hv41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbm5eON%2FdJMcaa4OUY1%2FgkPkg7jMKHssjOf8z8Hv41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2560&quot; height=&quot;1164&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PCA는 고차원 데이터를 보다 적은 차원으로 투영(projection)하여 데이터의 분산을 가장 크게 보존하는 새로운 축(주성분, Principal Components)을 찾는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 말해:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원본 특징들이 서로 상관관계가 있다면 &amp;rarr; PCA는 이를 서로 직교하는(orthogonal) 새 축으로 변환한다.&lt;/li&gt;
&lt;li&gt;변환된 축을 따라 데이터를 재표현하면 &amp;rarr; 더 적은 차원으로도 데이터 특성을 잘 유지할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 정보 손실은 최소화하면서 차원을 최대한 줄이는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PCA의 장점&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;데이터 압축&lt;br /&gt;차원이&amp;nbsp;매우&amp;nbsp;큰&amp;nbsp;데이터(예:&amp;nbsp;이미지,&amp;nbsp;유전자&amp;nbsp;데이터)를&amp;nbsp;다룰&amp;nbsp;때&amp;nbsp;유리합니다.&lt;br /&gt;적은&amp;nbsp;개수의&amp;nbsp;특징만으로도&amp;nbsp;전체&amp;nbsp;데이터를&amp;nbsp;효과적으로&amp;nbsp;표현할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/li&gt;
&lt;li&gt;시각화&lt;br /&gt;고차원&amp;nbsp;데이터를&amp;nbsp;2D,&amp;nbsp;3D&amp;nbsp;공간으로&amp;nbsp;축소하면&amp;nbsp;데이터의&amp;nbsp;구조를&amp;nbsp;시각적으로&amp;nbsp;이해하기&amp;nbsp;쉬워집니다.&lt;br /&gt;예:&amp;nbsp;MNIST&amp;nbsp;숫자&amp;nbsp;이미지&amp;nbsp;&amp;rarr;&amp;nbsp;PCA&amp;nbsp;적용&amp;nbsp;&amp;rarr;&amp;nbsp;2D&amp;nbsp;산점도&amp;nbsp;시각화&lt;/li&gt;
&lt;li&gt;노이즈 제거&lt;br /&gt;분산이 거의 없는 성분들은 실제 정보보다는 노이즈일 가능성이 높습니다.&lt;br /&gt;이를 제거하면 더 명확한 패턴을 얻을 수 있습니다. &lt;/li&gt;
&lt;li&gt;모델 학습 성능 향상&lt;br /&gt;고차원&amp;nbsp;데이터는&amp;nbsp;과적합을&amp;nbsp;유발하기&amp;nbsp;쉽습니다.&lt;br /&gt;PCA로&amp;nbsp;차원을&amp;nbsp;줄이면&amp;nbsp;모델의&amp;nbsp;일반화&amp;nbsp;성능이&amp;nbsp;향상되는&amp;nbsp;경우가&amp;nbsp;많습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PCA의 동작 과정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 데이터 표준화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특징의 스케일이 다르면 PCA 결과가 왜곡될 수 있으므로 평균 0, 분산 1로 표준화합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 공분산 행렬 계산&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특징 간 상관관계를 나타내는 공분산 행렬을 만듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 고유값(Eigenvalue)과 고유벡터(Eigenvector) 계산&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고유값: 해당 성분이 설명하는 &amp;lsquo;분산의 크기&amp;rsquo;&lt;/li&gt;
&lt;li&gt;고유벡터: 새로운 좌표축(주성분)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4. 고유값이 큰 순으로 주성분을 정렬&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분산을 많이 보존하는 축부터 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;5. 선택된 주성분으로 데이터 변환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 데이터를 주성분 축으로 투영하여 새로운 표현을 얻습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PCA 결과 해석 방법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 설명 분산 비율(Explained Variance Ratio)&lt;/p&gt;
&lt;p data-end=&quot;1672&quot; data-start=&quot;1639&quot; data-ke-size=&quot;size16&quot;&gt;각 주성분이 데이터의 변동성을 얼마나 설명하는지 보여줍니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 37.2094%; height: 130px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; text-align: center;&quot;&gt;주성분&lt;/td&gt;
&lt;td style=&quot;height: 21px; text-align: center;&quot;&gt;설명 분산 비율&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px; text-align: center;&quot;&gt;PC1&lt;/td&gt;
&lt;td style=&quot;height: 17px; text-align: center;&quot;&gt;70%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px; text-align: center;&quot;&gt;PC2&lt;/td&gt;
&lt;td style=&quot;height: 17px; text-align: center;&quot;&gt;20%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px; text-align: center;&quot;&gt;PC3&lt;/td&gt;
&lt;td style=&quot;height: 17px; text-align: center;&quot;&gt;5%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-end=&quot;1850&quot; data-start=&quot;1807&quot; data-ke-size=&quot;size16&quot;&gt;&amp;rarr; PC1 + PC2 만으로 전체 정보의 90%를 설명할 수 있다는 의미입니다.&lt;/p&gt;
&lt;p data-end=&quot;1850&quot; data-start=&quot;1807&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1850&quot; data-start=&quot;1807&quot; data-ke-size=&quot;size18&quot;&gt;2. Scree Plot (스크리 플롯)&lt;/p&gt;
&lt;p data-end=&quot;1850&quot; data-start=&quot;1807&quot; data-ke-size=&quot;size16&quot;&gt;고유값을 큰 순서대로 표시한 그래프입니다.&lt;br /&gt;일반적으로 그래프에서 꺾이는 지점(Elbow Point)까지의 성분을 선택합니다.&lt;/p&gt;
&lt;p data-end=&quot;1850&quot; data-start=&quot;1807&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PCA 예제 (Python, Scikit-Learn)&lt;/h4&gt;
&lt;pre class=&quot;haskell&quot;&gt;&lt;code&gt;from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

# 1. 데이터 로드
data = load_iris()
X = data.data

# 2. 표준화
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 3. PCA 변환 (2차원)
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)

# 4. 시각화
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=data.target)
plt.xlabel(&quot;PC1&quot;)
plt.ylabel(&quot;PC2&quot;)
plt.title(&quot;PCA on Iris Dataset&quot;)
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PCA의 한계점&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 선형성 가정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PCA는&amp;nbsp;선형&amp;nbsp;관계만&amp;nbsp;고려합니다.&lt;br /&gt;비선형&amp;nbsp;구조는&amp;nbsp;제대로&amp;nbsp;포착하지&amp;nbsp;못합니다.&lt;br /&gt;&amp;rarr; 대안: Kernel PCA, t-SNE, UMAP&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 해석이 어려움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주성분은 원본 특징의 선형 조합이기 때문에 &amp;ldquo;PC1 값이 높다는 건 어떤 의미인가?&amp;rdquo; 같은 질문에 명확히 답하기 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 스케일에 민감&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표준화를&amp;nbsp;하지&amp;nbsp;않으면&amp;nbsp;PCA&amp;nbsp;결과가&amp;nbsp;크게&amp;nbsp;왜곡됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;PCA 활용 사례&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 차원이 너무 크고 시각화가 필요할 때&lt;/li&gt;
&lt;li&gt;상관관계가 높은 변수가 많을 때&lt;/li&gt;
&lt;li&gt;노이즈를 줄이고 데이터 패턴을 더 선명하게 보고 싶을 때&lt;/li&gt;
&lt;li&gt;모델 학습 속도를 높이거나 과적합을 줄이고 싶을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2960&quot; data-start=&quot;2912&quot; data-ke-size=&quot;size16&quot;&gt;딥러닝이나 이미지 분석에서도 PCA는 전처리 또는 특징 추출 단계에서 널리 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PCA는 단순하면서도 매우 강력한 차원 축소 기법입니다.&lt;br /&gt;데이터의 구조를 파악하고, 모델의 성능을 높이고, 시각화와 노이즈 제거까지 가능한 다재다능한 도구죠.&lt;/p&gt;
&lt;p data-end=&quot;3137&quot; data-start=&quot;3073&quot; data-ke-size=&quot;size16&quot;&gt;차원이 많은 데이터를 다루고 있다면, PCA를 한 번 적용해 보는 것만으로도 새로운 통찰을 얻을 수 있을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI</category>
      <category>Machine Learning</category>
      <category>pca</category>
      <category>PrincipalComponentAnalysis</category>
      <category>고차원데이터</category>
      <category>데이터분석</category>
      <category>데이터전처리</category>
      <category>머신러닝</category>
      <category>주성분 분석</category>
      <category>차원의 저주</category>
      <category>차원축소</category>
      <author>dhlee-note</author>
      <guid isPermaLink="true">https://dhlee-note.tistory.com/17</guid>
      <comments>https://dhlee-note.tistory.com/entry/%EC%A3%BC%EC%84%B1%EB%B6%84-%EB%B6%84%EC%84%9DPCA-Principal-Component-Analysis#entry17comment</comments>
      <pubDate>Tue, 2 Dec 2025 15:00:33 +0900</pubDate>
    </item>
  </channel>
</rss>