<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hye0n_w00.log</title>
        <link>https://velog.io/</link>
        <description>학생</description>
        <lastBuildDate>Fri, 05 Sep 2025 03:59:55 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hye0n_w00.log</title>
            <url>https://velog.velcdn.com/images/hye0n_w00/profile/463bc59f-a2d3-4cac-8258-9da1a5686517/image.gif</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hye0n_w00.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hye0n_w00" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[PPO]]></title>
            <link>https://velog.io/@hye0n_w00/PPO</link>
            <guid>https://velog.io/@hye0n_w00/PPO</guid>
            <pubDate>Fri, 05 Sep 2025 03:59:55 GMT</pubDate>
            <description><![CDATA[<h1 id="ppoproximal-policy-optimization">PPO(Proximal Policy Optimization)</h1>
<blockquote>
</blockquote>
<p>현재 Policy를 가능한 빠르게 향상시키되, 성능이 발산 해버릴 정도로 너무 Policy가 급격하게 바뀌는 것을 억제
<img src="https://velog.velcdn.com/images/hye0n_w00/post/85a557ce-7e28-4802-a387-ebf534c65249/image.png" alt=""></p>
<blockquote>
</blockquote>
<h2 id="ppo-구조">PPO 구조</h2>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/929dc0b1-7ef3-4971-9b9d-4268cadb8763/image.png" alt=""></p>
<h4 id="초록선">초록선</h4>
<ul>
<li>상호작용: 현재 정책을 따르는 Actor (πθ)가 환경과 직접 상호작용하여 경험 데이터를 수집합니다.</li>
<li>데이터 생성: 특정 상태(st)에서 행동(at)을 수행하고, 그 결과로 보상(rt)과 다음 상태(st+1)를 관측합니다.</li>
<li>데이터 저장: 이 경험의 궤적(trajectory)은 Rollout Buffer라는 임시 저장 공간에 보관됩니다. 저장되는 정보는 다음과 같습니다.<ul>
<li>(상태, 행동, 보상, 다음 상태, 행동 확률)</li>
<li>(s t,a t,r t,s t+1,πθ(at∣st))</li>
</ul>
</li>
</ul>
<h4 id="advantage-계산-critic-활용">Advantage 계산 (Critic 활용)</h4>
<ul>
<li>Advantage(A^t)의 정의: 현재 상태(s t)에서 특정 행동(a t)을 하는 것이 평균적으로 얼마나 더 좋은지를 나타내는 지표</li>
<li>Critic(V ϕ )의 역할: 상태의 가치(Value)를 예측하는 신경망으로, Advantage를 계산하는 데 핵심적인 역할</li>
<li>Advantage 추정: Critic을 활용한 간단한 Advantage 추정식
<img src="https://velog.velcdn.com/images/hye0n_w00/post/141ab11f-0e45-4c3c-b659-4fd6d4da7cb8/image.png" alt="">
즉, Advantage는 <strong>실제 얻은 보상과 예측 가치를 통해 계산된 값(Target)</strong>과 현재 상태의 가치 예측치 사이의 차이(TD-Error)를 의미하며, 행동의 좋고 나쁨을 판단하는 기준</li>
</ul>
<h4 id="actor-정책-업데이트--ppo의-핵심">Actor (정책) 업데이트 — PPO의 핵심</h4>
<ul>
<li>Actor는 Advantage(A^ t)를 사용하여 &quot;좋았던 행동&quot;의 확률은 높이고 &quot;나빴던 행동&quot;의 확률은 낮추도록 정책(π θ)을 업데이트합니다.</li>
<li>확률 비율(Probability Ratio) 계산<ul>
<li>업데이트하려는 새 정책(π θ)과 데이터를 수집했던 과거 정책(π old) 사이의 비율을 계산합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/d2ff676d-2a40-4431-b37f-52fdaa77dfb2/image.png" alt=""></li>
</ul>
</li>
<li>Clipped Surrogate Objective 함수<ul>
<li>PPO는 정책이 한 번에 너무 크게 변하는 것을 막기 위해 Clipped Surrogate Objective라는 독창적인 목적 함수를 사용합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/ff13eb90-9839-4148-bcfc-ad82ecc118a5/image.png" alt=""></li>
</ul>
</li>
</ul>
<h4 id="critic-가치-함수-업데이트">Critic (가치 함수) 업데이트</h4>
<ul>
<li>손실 함수: 예측한 가치와 실제 보상에 기반한 목표값(Target) 사이의 <strong>평균 제곱 오차(Mean Squared Error, MSE)</strong>를 최소화하는 방향으로 업데이트합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/fbf40bb0-602e-4002-9768-941a4956fbb7/image.png" alt=""></li>
</ul>
<h2 id="surrogate-objective-대리-목적-함수">Surrogate Objective (대리 목적 함수)</h2>
<p>어떻게 하면 데이터를 재사용해서 효율적으로 학습할 수 있을까?
<img src="https://velog.velcdn.com/images/hye0n_w00/post/e702c1a7-2aac-4b91-8597-23b13a1e736e/image.png" alt="">
𝜌𝜋𝜃(𝑠): 현재 정책 𝜋𝜃를 따를 때 상태 𝑠를 방문할 확률(상태 방문 빈도)
πθ(a∣s): 상태 S에서 행동 a를 할 확률
Aπθ(s,a): 상태 S에서 행동 a를 했을 때, 평균적인 행동보다 얼마나 좋은지(Advantage)
-&gt; 정책을 따르면 얼마나 좋은 행동을 자주 하는가</p>
<ul>
<li>문제점<ul>
<li>𝜌𝜋𝜃(𝑠)는 현재 정책에 의존</li>
<li>정책이 조금만 업데이트 되어도 상태 방문 빈도가 바뀜</li>
<li>따라서 매번 새 데이터를 수집해야만 𝐽(𝜋𝜃)를 계산할 수 있음 → 데이터 비효율적
<img src="https://velog.velcdn.com/images/hye0n_w00/post/cd2f178f-669a-4f8e-90be-3ca496ed0a52/image.png" alt=""></li>
<li>핵심 차이: </li>
<li>𝜌𝜋𝜃(𝑠)→ 𝜌𝜋𝑜𝑙𝑑(𝑠)로 변경</li>
<li>즉, 현재 정책의 상태 방문 분포 대신 이전 정책에서 수집한 분포를 사용</li>
</ul>
</li>
</ul>
<h2 id="importance-sampling">Importance Sampling</h2>
<ul>
<li>우리는 과거 정책 𝜋𝑜𝑙𝑑으로 수집한 데이터 (𝑠,𝑎)를 사용해 새로운 정책 𝜋𝜃를 학습하고 싶다.하지만 𝜋𝑜𝑙𝑑 분포로 얻은 데이터와 𝜋𝜃 분포가 다르기 때문에 그대로 사용할 수 없다.</li>
<li><blockquote>
<p>차이를 보정
<img src="https://velog.velcdn.com/images/hye0n_w00/post/5db54d28-73aa-49a9-8fee-eb83ab285cd9/image.png" alt="">
<img src="https://velog.velcdn.com/images/hye0n_w00/post/bf486187-6ea3-4358-af49-9e806d831abf/image.png" alt=""></p>
</blockquote>
</li>
</ul>
<h2 id="gaegeneralized-advantage-estimation">GAE(Generalized Advantage Estimation)</h2>
<p>PPO의 Actor는 Advantage 𝐴^𝑡를 보고 학습한다.</p>
<ul>
<li>Advantage를 추정하는 기존 두 가지 방법은 극단적:<ul>
<li>Monte Carlo: Low Bias, High Variance → 정확하지만 불안정
<img src="https://velog.velcdn.com/images/hye0n_w00/post/9db78674-cd7b-4f84-ace4-2d92d44ce118/image.png" alt=""></li>
<li>TD(1-step): High Bias, Low Variance → 안정적이지만 부정확
<img src="https://velog.velcdn.com/images/hye0n_w00/post/376871d4-b46a-4afc-a631-8b44de3b281a/image.png" alt=""></li>
</ul>
</li>
</ul>
<p>∴ Advantage를 TD error(δ)의 지수 가중합으로 정의
<img src="https://velog.velcdn.com/images/hye0n_w00/post/913be5cf-99d5-451b-9228-9cc8fe54b542/image.png" alt=""></p>
<p>δ t: 현재 시점의 TD error (안정적이지만 근시안적).
δ t+1: 다음 시점의 TD error.
γ: 미래 보상에 대한 할인율(discount factor)로, 원래 강화학습에 있던 개념입니다.
λ: GAE에서 새로 도입된 파라미터로, 미래의 TD error들을 얼마나 신뢰할지를 결정하는 가중치입니다. 이것이 GAE의 핵심입니다.</p>
<h4 id="λ-람다의-역할">λ (람다)의 역할</h4>
<p>Bias–Variance Trade-off를 조절하는 핵심 파라미터</p>
<ul>
<li>λ=0: TD 방식과 동일 → High Bias, Low Variance</li>
<li>λ=1: Monte Carlo 방식과 동일 → Low Bias, High Variance</li>
<li>0&lt;λ&lt;1: 두 방식의 절충점</li>
</ul>
<h2 id="ppo-argorithm">PPO Argorithm</h2>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/dabb5f26-d58e-4307-b3e5-bb4c1ac9c58c/image.png" alt=""></p>
<blockquote>
</blockquote>
<p>[루프 개요]</p>
<blockquote>
</blockquote>
<ul>
<li>for iteration = 1.. : 학습 전체 반복<blockquote>
</blockquote>
[1) 데이터 수집 &amp; 가공]<blockquote>
</blockquote>
</li>
<li><ol>
<li>정책 고정: π_old 로 고정</li>
</ol>
</li>
<li><ol start="2">
<li>롤아웃: N actors로 T 스텝 실행 → 버퍼에 (s_t, a_t, r_t, s_{t+1}, log π_old(a_t|s_t), V(s_t)) 저장</li>
</ol>
</li>
<li><ol start="3">
<li>GAE로 Advantage 계산
δ<em>t = r_t + γV(s</em>{t+1}) − V(s_t)
Â<em>t = Σ (γλ)^l δ</em>{t+l}
Return: R_t = Â_t + V(s_t)<blockquote>
</blockquote>
[2) 학습(최적화)]</li>
</ol>
</li>
<li><ol start="4">
<li>K epochs · 미니배치 M으로 여러 번 재사용</li>
</ol>
</li>
<li><ol start="5">
<li>확률비율 (Importance Ratio)
r_t(θ) = π_θ(a_t|s_t) / π_old(a_t|s_t)</li>
</ol>
</li>
<li><ol start="6">
<li>클리핑 목적함수 (Actor)
L^CLIP(θ) = E_t[min(r_t(θ)Â_t, clip(r_t(θ), 1−ε, 1+ε)Â_t)]</li>
</ol>
</li>
<li><ol start="7">
<li>가치함수 손실 (Critic)
L_v(ϕ) = E_t[(V_ϕ(s_t) − R_t)^2]</li>
</ol>
</li>
<li><ol start="8">
<li>(선택) 엔트로피 보너스: 탐색 강화
최종 손실 = −L^CLIP(θ) + c_v L_v(ϕ) − c_e E[H(π_θ(·|s))]</li>
</ol>
</li>
<li><ol start="9">
<li>파라미터 업데이트: θ, ϕ 경사하강<blockquote>
</blockquote>
[3) 정책 교체]<blockquote>
</blockquote>
</li>
</ol>
</li>
<li><ol start="10">
<li>θ_old ← θ 로 갱신하고 다음 iteration 진행
[전체 흐름]
Rollout(π_old 고정) → GAE로 Â_t, R_t 계산 → K epochs·미니배치로 L^CLIP 최대화 &amp; Value MSE 최소화 → θ_old 갱신 → 반복<blockquote>
</blockquote>
[핵심 포인트]</li>
</ol>
</li>
<li>Importance Sampling: 과거 데이터로 현재 정책 학습 가능</li>
<li>Clipping: 과도한 업데이트 억제 (안정성)</li>
<li>GAE(λ): Bias–Variance 절충으로 견고한 Advantage</li>
<li>Epoch 재사용: 데이터 효율성 상승<blockquote>
</blockquote>
</li>
</ul>
<h4 id="ppo-정책-기반">PPO (정책 기반):</h4>
<p>&#39;어떻게 행동할지&#39;에 대한 정책(전략) 자체를 직접 학습합니다. 현재 자신의 전략으로만 데이터를 수집하고 학습하는 On-policy 방식을 사용하므로 데이터 효율성은 다소 낮지만, 연속적인 행동 제어 등 복잡한 문제에 강점을 보입니다.</p>
<h4 id="q-러닝-가치-기반">Q-러닝 (가치 기반):</h4>
<p>&#39;각 행동이 얼마나 좋은지&#39;에 대한 <strong>가치(점수표)</strong>를 학습합니다. 과거의 낡은 데이터를 포함해 어떤 정책이 만든 데이터든 학습에 사용할 수 있는 Off-policy 방식을 사용합니다. 이 덕분에 데이터 효율성이 매우 높지만, 주로 단순하고 정해진 행동을 하는 문제에 사용됩니다.</p>
<ul>
<li>On-policy (온폴리시): 현재 정책이 생성한 데이터로만 학습하는 방식입니다. (예: PPO)</li>
<li>Off-policy (오프폴리시): 과거 또는 다른 정책이 생성한 데이터를 포함하여 모든 데이터를 학습에 사용하는 방식입니다. (예: Q-러닝)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[MARL]]></title>
            <link>https://velog.io/@hye0n_w00/MARL</link>
            <guid>https://velog.io/@hye0n_w00/MARL</guid>
            <pubDate>Fri, 05 Sep 2025 01:01:13 GMT</pubDate>
            <description><![CDATA[<h1 id="multi-agent-reinforcement-learningmarl">Multi-Agent Reinforcement Learning(MARL)</h1>
<blockquote>
</blockquote>
<p>다수의 에이전트(Agent)가 하나의 환경에서 상호작용하며 동시에 학습하는 강화학습
협력(Collaboration), 경쟁(Competition), 공존(Coexistence) 등의 다양한 상호작용을 기반으로 복잡한 문제 해결</p>
<blockquote>
</blockquote>
<h2 id="싱글-에이전트-rl에서-marl로의-전환">싱글 에이전트 RL에서 MARL로의 전환</h2>
<p>단일 에이전트 RL은 하나의 에이전트가 마르코프 결정 과정(Markov Decision Process, MDP)으로 모델링된 환경과 상호 작용하며 최적의 정책을 학습하는 것을 목표로 합니다. MDP는 환경의 역학이 에이전트의 행동과 현재 상태에만 의존한다고 가정하는 &#39;마르코프 성질&#39;을 기반으로 하며, 이 때문에 환경은 에이전트에게 정적(stationary)으로 간주됩니다.   </p>
<p>그러나 MARL에서는 여러 에이전트가 동시에 행동하고 학습하며 서로 영향을 미치기 때문에, 환경의 역학이 더 이상 단일 에이전트의 관점에서 정적이지 않습니다. 한 에이전트의 최적 정책은 다른 에이전트들의 변화하는 정책에 따라 끊임없이 바뀝니다. 이러한 근본적인 패러다임의 변화는 MARL이 단일 에이전트 RL의 단순한 확장이 아님을 의미하며, 고유한 이론적 및 실용적 난제를 야기합니다.</p>
<h2 id="marl의-근본적인-난제들-싱글-에이전트와-다른-점">MARL의 근본적인 난제들: 싱글 에이전트와 다른 점</h2>
<ul>
<li>환경의 비정상성</li>
<li>신용 할당 문제</li>
<li>부분적 관찰 가능성 및 분산 실행<h2 id="marl-environment">MARL environment</h2>
</li>
<li>Cooperative MARL: 전체 팀의 보상 극대화를 목표로 공동 학습</li>
<li>Competitive MARL: 에이전트 간 보상이 상충하거나 제로섬 환경</li>
</ul>
<h2 id="구성요소">구성요소</h2>
<ul>
<li>Agent: 독립적으로 관찰하고 행동하는 학습자&lt; 로봇, 드론, 차량 등  &gt;</li>
<li>Shared Environment: 에이전트들이 상호작용하는 공간    &lt;시뮬레이션, 실세계 공간&gt;</li>
<li>Reward Function: 개별/공동 목표 기반 보상 함수    &lt;공동 목표 vs 개인 목표&gt;</li>
<li>Communication Protocol: 에이전트 간 정보 공유 방식    &lt;메시지 패싱, 블랙보드 방식&gt;</li>
</ul>
<h2 id="주요-알고리즘">주요 알고리즘</h2>
<ul>
<li>MADDPG (Multi-Agent DDPG): 정책과 비정책 플레이어 분리 학습    &lt;continuous action에 적합&gt;</li>
<li>QMIX:    중앙집중형 학습 + 분산 실행 구조    &lt;합성 가능한 Q-function&gt;</li>
<li>COMA:    정책 기여도를 기반으로 한 Actor-Critic 구조    &lt;협력 강화에 유리&gt;</li>
<li>MAPPO:    PPO를 다중 에이전트에 확장한 버전    &lt;안정성 + 샘플 효율 높음&gt;</li>
</ul>
<h2 id="참고-논문">참고 논문</h2>
<h3 id="markov-games-as-a-framework-for-multi-agent-reinforcement-learning">Markov Games as a Framework for Multi-Agent Reinforcement Learning</h3>
<blockquote>
</blockquote>
<h4 id="마르코프-게임markov-games-공식화">마르코프 게임(Markov Games) 공식화</h4>
<p>리트먼은 여러 에이전트가 동시에 행동하고 보상을 받는 시스템을 모델링하기 위해, MDP에 N개의 에이전트, 공동 행동 공간(A_1 ×... × A_N), 그리고 N개의 보상 함수(R_1,..., R_N)를 추가했습니다. 이 모델은 에이전트가 협력하거나 경쟁하는 다양한 시나리오를 포괄적으로 설명하는 데 사용될 수 있습니다.   </p>
<blockquote>
</blockquote>
<h4 id="minimax-q-학습-알고리즘">minimax-Q 학습 알고리즘</h4>
<p>이 논문은 제로섬 마르코프 게임(Zero-sum Markov Games), 즉 한 에이전트의 이득이 다른 에이전트의 손실이 되는 환경에서 작동하는 minimax-Q 학습 알고리즘을 제안했습니다. 이 알고리즘은 에이전트들이 상대방의 최적 행동을 고려하여 자신의 최적 전략을 찾는 내쉬 균형(Nash equilibrium)에 수렴함을 이론적으로 증명했습니다.</p>
<blockquote>
</blockquote>
<p> 이 논문은 다중 에이전트 시스템을 단일 에이전트의 MDP 확장으로 보는 것이 아니라, 상호작용하는 합리적 주체들의 집합으로 보는 관점을 확립했습니다.</p>
<h3 id="learning-to-communicate-with-deep-multi-agent-reinforcement-learning">Learning to communicate with deep multi-agent reinforcement learning</h3>
<blockquote>
</blockquote>
<h4 id="학습된-통신-프로토콜">학습된 통신 프로토콜</h4>
<p>이 연구는 에이전트들이 서로 명시적인 메시지를 주고받는 통신 채널을 도입했습니다. 각 에이전트는 자신의 관찰 내용을 기반으로 인코딩된 메시지를 생성하고, 이 메시지는 다른 에이전트들의 입력으로 활용됩니다. 중요한 것은 이 메시지의 내용이나 구조가 미리 정해져 있지 않고, 오직 공동 보상을 극대화하는 방향으로 학습 과정에서 자연스럽게 발현된다는 점입니다. 이처럼 자율적으로 형성되는 통신 프로토콜을 &quot;학습된 통신 프로토콜&quot;(Learned Communication Protocols)이라고 합니다.   </p>
<blockquote>
</blockquote>
<h4 id="분산형-에이전트와-명시적-커뮤니케이션-채널">분산형 에이전트와 명시적 커뮤니케이션 채널</h4>
<p>이 논문에서 제안된 아키텍처는 분산형 에이전트들이 상호작용하지만, 학습된 통신 모듈을 통해 서로 정보를 공유하여 협력을 이끌어내는 방법을 보여줍니다. 이는 순수하게 독립적으로 학습하는 방식의 한계를 극복하고, 정보 공유가 필요한 복잡한 협력 문제에서 뛰어난 성능을 보였습니다</p>
<blockquote>
</blockquote>
<p>MARL에서 통신이 가진 잠재력과 한계</p>
<h3 id="multi-agent-actor-critic-for-mixed-cooperative-competitive-environments">Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments</h3>
<blockquote>
</blockquote>
<p>MADDPG(Multi-Agent Deep Deterministic Policy Gradient)라는 알고리즘과 CTDE(Centralized Training with Decentralized Execution)라는 강력한 패러다임을 제안</p>
<blockquote>
</blockquote>
<h4 id="ctde-패러다임">CTDE 패러다임</h4>
<p>이 패러다임은 학습 단계에서는 중앙 집중식 접근법을 사용하지만, 실제 실행 단계에서는 분산형 접근법을 사용합니다. 구체적으로, 학습 시에는 모든 에이전트의 행동과 전체 환경 상태를 관찰할 수 있는 중앙 집중식 비평가(critic)가 학습에 참여하여 안정적인 학습 신호를 제공합니다. 반면, 실행 시에는 각 에이전트의 행위자(actor)가 오직 자신의 국소적인 관찰만을 사용하여 행동을 결정합니다. 이 방식은 학습의 안정성을 보장하면서도 현실 세계의 분산형 시스템 요구 사항을 충족하는 독창적인 해결책입니다.   </p>
<blockquote>
</blockquote>
<h4 id="maddpg-알고리즘">MADDPG 알고리즘</h4>
<p>이 논문은 단일 에이전트 DDPG(Deep Deterministic Policy Gradient)를 기반으로 MADDPG 알고리즘을 제안했습니다. 각 에이전트는 독립적인 행위자 네트워크를 가지며, 모든 에이전트의 행동과 상태 정보를 입력으로 받는 중앙 집중식 비평가 네트워크를 통해 학습합니다. 이 접근법은 협력과 경쟁이 혼합된 환경에서 여러 에이전트가 복잡한 조정 전략을 효과적으로 학습할 수 있도록 합니다. 이는 드론 군집 제어(swarm drones)나 모바일 애드혹 네트워크(MANETs)와 같은 실제 응용 분야에서 성공적으로 활용되었습니다.</p>
<blockquote>
</blockquote>
<p>CTDE 패러다임이 훨씬 효과적이고 안정적인 성능을 보임</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Poisson Process]]></title>
            <link>https://velog.io/@hye0n_w00/Poisson-Process</link>
            <guid>https://velog.io/@hye0n_w00/Poisson-Process</guid>
            <pubDate>Tue, 12 Aug 2025 05:21:40 GMT</pubDate>
            <description><![CDATA[<h2 id="이항-분포-binomial-distribution의-기본-개념과-한계">이항 분포 (Binomial Distribution)의 기본 개념과 한계</h2>
<p>이항 분포는 정해진 횟수(n)의 독립적인 시행에서 성공 확률이 p로 일정한 사건의 <strong>성공 횟수(k)</strong>를 나타내는 확률 분포입니다.</p>
<p>예를 들어, &quot;사과 10개를 상자에 담을 때, 각 사과가 썩었을 확률이 10%라고 할 때, 썩은 사과가 3개 나올 확률&quot; 같은 문제를 푸는 데 사용됩니다.</p>
<ul>
<li>시행 횟수 (n): 10번 (사과를 담는 행위)</li>
<li>성공 확률 (p): 0.1 (사과가 썩었을 확률)</li>
<li>성공 횟수 (k): 3번 (썩은 사과가 3개)</li>
</ul>
<p>이항 분포의 확률 질량 함수(PMF)는 다음과 같습니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/90ed223e-78c7-4ecd-9b37-6b8827052577/image.png" alt=""></p>
<h3 id="이항-분포의-결정적-한계-n을-알-수-없는-경우">이항 분포의 결정적 한계: &#39;n&#39;을 알 수 없는 경우</h3>
<ul>
<li>1시간 동안 한 웹사이트에 방문하는 사람의 수</li>
<li>책 한 페이지에 있는 오타의 개수</li>
<li>1년 동안 특정 지역에서 발생하는 교통사고 건수</li>
<li>콜센터에 10분 동안 걸려오는 전화의 수</li>
</ul>
<p>이런 문제들은 이항 분포로 모델링하기 매우 어렵습니다. 왜냐하면 시행 횟수 n을 정의하기가 애매하거나 불가능에 가깝기 때문입니다.</p>
<p>예를 들어, &#39;1시간 동안의 웹사이트 방문자 수&#39; 문제를 생각해 봅시다.</p>
<ul>
<li><p><strong>시행 횟수 (n)</strong>를 무엇으로 잡아야 할까요? 1시간을 1초 단위로 쪼개서 n=3600으로 해야 할까요? 아니면 0.1초 단위로 쪼개서 n=36000으로 해야 할까요? n은 잠재적으로 무한대에 가까워집니다.</p>
</li>
<li><p><strong>성공 확률 (p)</strong>는 어떻게 될까요? n이 무한대에 가까워진다면, 각 아주 짧은 순간에 방문자가 발생할 확률 p는 0에 극도로 가까워질 것입니다.</p>
</li>
</ul>
<p>이처럼 n은 매우 크고 (n→∞), p는 매우 작은 (p→0) 상황에서 이항 분포는 실용성을 잃게 됩니다. 계산이 불가능할 뿐만 아니라, n과 p를 특정하는 것 자체가 무의미해집니다.</p>
<h2 id="푸아송-분포-poisson-distribution의-등장-한계의-극복">푸아송 분포 (Poisson Distribution)의 등장: 한계의 극복</h2>
<p>이러한 이항 분포의 한계를 극복하기 위해 등장한 것이 바로 푸아송 분포입니다. 푸아송 분포는 n과 p를 개별적으로 다루는 대신, 이 둘의 곱인 <strong>평균 발생 횟수(λ)</strong>라는 새로운 개념을 도입합니다.</p>
<blockquote>
</blockquote>
<p>λ=n×p</p>
<blockquote>
</blockquote>
<p>여기서 λ(람다)는 주어진 단위 시간 또는 단위 공간에서 어떤 사건이 평균적으로 발생하는 횟수를 의미합니다.</p>
<h3 id="수학적-유도-이항-분포에서-푸아송-분포로">수학적 유도: 이항 분포에서 푸아송 분포로</h3>
<p>푸아송 분포는 사실 이항 분포의 특별한 극한 경우(special limiting case)입니다. 즉, n이 무한대로 가고 p가 0으로 갈 때, 이항 분포는 푸아송 분포에 수렴합니다.</p>
<blockquote>
</blockquote>
<ol>
<li>시작점: 이항 분포의 확률 질량 함수
<img src="https://velog.velcdn.com/images/hye0n_w00/post/59655f46-73de-4831-970d-bdd8377b3494/image.png" alt=""><blockquote>
</blockquote>
</li>
<li>p=λ/n 치환
n이 매우 크고 p가 매우 작으므로, 평균 λ=np는 일정한 값을 유지한다고 가정하고 p=λ/n으로 식을 바꿉니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/4a81426b-1495-4ef4-94a5-c31583dcc929/image.png" alt=""><blockquote>
</blockquote>
</li>
<li>n→∞ 극한 취하기
<img src="https://velog.velcdn.com/images/hye0n_w00/post/7156b465-c74b-43a5-bca4-6e4d78277112/image.png" alt=""><blockquote>
</blockquote>
</li>
<li>항들을 조합하여 정리하기
<img src="https://velog.velcdn.com/images/hye0n_w00/post/d7d8dd6a-82b6-461e-b6dd-61d3ced20d0d/image.png" alt="">
<img src="https://velog.velcdn.com/images/hye0n_w00/post/e8ada6c9-cb29-4649-a949-f73b72b16c55/image.png" alt=""><blockquote>
</blockquote>
</li>
</ol>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/c9a0899c-6a86-4d72-97ad-c8fccce22062/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Learning from Noise: Enhancing DNNs for Event-Based Vision through
Controlled Noise Injection]]></title>
            <link>https://velog.io/@hye0n_w00/Learning-from-Noise-Enhancing-DNNs-for-Event-Based-Vision-throughControlled-Noise-Injection</link>
            <guid>https://velog.io/@hye0n_w00/Learning-from-Noise-Enhancing-DNNs-for-Event-Based-Vision-throughControlled-Noise-Injection</guid>
            <pubDate>Tue, 12 Aug 2025 01:24:44 GMT</pubDate>
            <description><![CDATA[<h2 id="요약">요약</h2>
<ul>
<li><p>무엇인가?: 전처리 단계가 아니라, 딥러닝 모델을 훈련(Training)시키는 시점에 실시간으로 적용되는 데이터 증강(Data Augmentation) 방식입니다. </p>
</li>
<li><p>어떻게 사용하나?:</p>
<ol>
<li><p>&#39;깨끗한 원본 데이터셋&#39;을 준비합니다.</p>
</li>
<li><p>모델 훈련을 시작하면, 데이터를 불러올 때마다 매번 0Hz ~ 5Hz 사이의 노이즈 강도를 무작위로 새로 뽑습니다. </p>
</li>
<li><p>그렇게 즉석에서 생성된, 매번 다른 강도의 노이즈가 섞인 데이터를 모델에게 보여주며 훈련시킵니다.</p>
</li>
</ol>
</li>
</ul>
<ul>
<li><p>장점 (논문에 따르면): 모델이 다양한 노이즈 환경을 골고루 학습하기 때문에, 어떤 강도의 노이즈가 들어와도 안정적으로 높은 성능을 내는 &#39;만능형&#39; 모델이 됩니다. </p>
</li>
<li><p>단점: 구현이 더 복잡합니다. 전처리 스크립트가 아닌, PyTorch나 TensorFlow 같은 딥러닝 프레임워크의 훈련 파이프라인(예: DataLoader)에 직접 노이즈 생성 로직을 통합해야 합니다.</p>
</li>
</ul>
<h2 id="abstract--introduction">Abstract &amp; Introduction</h2>
<h3 id="1-배경-이벤트-카메라의-잠재력과-근본적-한계">1. 배경: 이벤트 카메라의 잠재력과 근본적 한계</h3>
<p>이벤트 카메라는 뉴로모픽 카메라라고도 불리며, 높은 시간 해상도, 낮은 지연 시간, 에너지 효율성 덕분에 기존 프레임 기반 카메라의 강력한 대안으로 주목받고 있습니다. 이 카메라는 각 픽셀의 밝기 변화를 독립적으로 감지하는 독특한 방식으로 작동하여 , 로봇 공학, 자율 주행, 빠르게 움직이는 객체 추적과 같은 동적 시나리오에서 시각 정보를 효율적으로 수집합니다.</p>
<p>하지만 원본 이벤트 데이터는 환경적 방해와 하드웨어의 불완전성으로 인해 노이즈와 아티팩트에 매우 취약합니다. 특히 노이즈의 강도는 관찰되는 장면의 밝기나 센서 온도 같은 작동 조건에 따라 계속 변동하기 때문에 , 이벤트 데이터를 처리하는 알고리즘은 이러한 노이즈 변화에 대한 견고성을 갖추는 것이 필수적입니다.</p>
<h3 id="2-기존-해결책의-문제점">2. 기존 해결책의 문제점</h3>
<p>현재 이벤트 데이터 처리에는 CNN, SNN, ViT, GCN 등 다양한 딥러닝 모델이 널리 사용되고 있으며 , 노이즈가 모델 성능에 부정적인 영향을 미친다는 것은 명백합니다. 이 문제를 해결하기 위해 전통적으로 필터링 알고리즘이 사용되어 왔습니다.</p>
<p>그러나 필터링은 근본적인 한계를 가집니다. 각 필터링 알고리즘은 노이즈를 제거하는 과정에서 필연적으로 실제 중요한 이벤트 데이터의 일부까지 제거하게 되며 , 이는 결과적으로 처리 알고리즘의 전체적인 효율성을 감소시킬 수 있습니다.</p>
<h3 id="3-제안된-해결책-노이즈-주입-훈련">3. 제안된 해결책: &#39;노이즈 주입 훈련&#39;</h3>
<p>본 논문은 기존 필터링 방식의 대안으로 <strong>&#39;노이즈 주입(Noise-Injection) 훈련&#39;</strong>이라는 새로운 데이터 증강 방법을 제안합니다. 이는 훈련 데이터에 제어된 노이즈를 의도적으로 주입하여 , 모델이 노이즈에 강한 표현(representation)을 스스로 학습하게 만드는 접근법입니다. 이를 통해 모델의 일반화 성능과 실제 환경 조건에 대한 견고성을 향상시키는 것을 목표로 합니다.</p>
<h3 id="4-샷-노이즈의-활용과-핵심-원리">4. &#39;샷 노이즈&#39;의 활용과 핵심 원리</h3>
<p>이 연구에서 활용하는 &#39;샷 노이즈(shot noise)&#39;는 다음과 같은 특징을 가집니다.</p>
<ul>
<li><p>정의: 센서의 광수용체나 회로에서 발생하는 무작위적인 전기적 변동으로 인해, 실제 밝기 변화가 없음에도 이벤트가 생성되는 하드웨어 수준의 노이즈입니다.</p>
</li>
<li><p>시뮬레이션: 이 노이즈는 수학적으로 &#39;푸아송 과정(Poisson process)&#39;으로 모델링할 수 있으며 , 본 연구에서는 이를 근사하는 베르누이 시행을 통해 노이즈를 시뮬레이션합니다.</p>
</li>
<li><p>&#39;다양한 강도&#39;의 의미: 훈련 시, 모든 데이터에 동일한 양의 노이즈를 추가하는 것이 아니라, 각 훈련 샘플마다 무작위로 다른 강도의 노이즈를 주입합니다. 이를 통해 모델은 노이즈가 거의 없는 상태부터 매우 심한 상태까지 넓은 범위의 환경을 학습하여, 실제 예측 불가능한 노이즈 변화에 대한 안정성을 크게 높일 수 있습니다.</p>
</li>
</ul>
<h3 id="5-검증-및-주요-기여">5. 검증 및 주요 기여</h3>
<p>제안된 방법의 효과를 입증하기 위해 광범위한 실험을 수행했습니다.</p>
<ul>
<li><p>실험 환경: N-Caltech101, N-Cars, Mini N-ImageNet 데이터셋을 사용했으며 , CNN, SNN, ViT, GCN 등 여러 대표적인 네트워크 아키텍처에 적용하여 평가했습니다.</p>
</li>
<li><p>실험 결과: &#39;노이즈 주입 훈련&#39; 전략은 다양한 노이즈 강도 범위에서 안정적인 성능을 보였고, 기존 필터링 기술을 일관되게 능가했으며, 가장 높은 평균 분류 정확도를 달성했습니다. 이는 제안된 방법이 기존 필터링을 대체할 수 있는 효과적인 대안임을 시사합니다.</p>
</li>
</ul>
<p>본 논문의 주요 기여는 다음과 같습니다.</p>
<ul>
<li><p>다양한 강도의 샷 노이즈를 주입하여 신경망 성능에 대한 노이즈의 영향을 줄이는 새로운 이벤트 데이터 증강 방법을 제안했습니다.</p>
</li>
<li><p>분류 작업에서 여러 신경망 아키텍처에 대한 노이즈의 효과와, 제안된 증강 기법 적용 후의 성능 개선을 분석했습니다.</p>
</li>
<li><p>3가지 최신 필터링 방법의 영향을 조사하고, 이를 제안된 훈련 방법과 결합했을 때의 효과를 평가했습니다.</p>
</li>
</ul>
<h2 id="related-work">Related Work</h2>
<h3 id="이벤트-노이즈-필터링-event-noise-filtration">이벤트 노이즈 필터링 (Event Noise Filtration)</h3>
<p>이벤트 데이터에 포함된 노이즈를 제거하기 위한 다양한 접근법</p>
<ul>
<li><p>상관관계 기반 필터링: 가장 대중적인 방법 중 하나는 이벤트 간의 시공간적 상관관계를 이용하는 것입니다.</p>
<ul>
<li>최근접 이웃(Nearest-Neighbour) 방법: 지정된 시간 창 내에서 주변에 다른 활동(이벤트)이 없는 고립된 이벤트를 노이즈로 간주하고 제거하는 방식입니다.</li>
</ul>
</li>
<li><p>신경망 기반 필터링: 딥러닝 모델을 사용하여 이벤트가 실제 신호인지 노이즈인지를 직접 분류하는 방식입니다.</p>
<ul>
<li>EDnCNN: 3개의 합성곱 레이어와 2개의 완전 연결 레이어로 구성된 CNN 모델을 이용해 노이즈를 식별하고 제거하는 가장 대표적인 방법입니다. 이 연구는 각 픽셀의 이벤트 발생 확률을 평가하여 노이즈 가능성을 추정하는 메커니즘도 제안했습니다.</li>
</ul>
</li>
<li><p>스파이킹 신경망(SNN) 기반 필터링: 이벤트 카메라와 작동 방식이 유사한 SNN을 활용하는 방법도 주목받고 있습니다.</p>
<ul>
<li>ex) 뉴로모픽 프로세서인 IBM TrueNorth에 구현된 네트워크는 &#39;불응기(refractory period)&#39;를 도입하여 특정 픽셀의 연속적인 노이즈 발생을 막고, 주변 이벤트와의 동시 발생 여부를 검증하여 노이즈를 걸러냅니다.</li>
</ul>
</li>
</ul>
<h3 id="이벤트-기반-분류-event-based-classification">이벤트 기반 분류 (Event-based Classification)</h3>
<p>이벤트 데이터를 활용한 분류 작업에서의 다양한 딥러닝 아키텍처</p>
<ul>
<li><p>CNN (합성곱 신경망): 엣지나 텍스처 같은 지역적 특징 추출에 강점을 보여 가장 널리 사용되는 해결책 중 하나입니다.</p>
<ul>
<li>비동기적인 이벤트 스트림을 CNN이 처리 가능한 그리드(grid) 형태로 변환하거나 , 이미지와 유사한 형태로 먼저 학습시킨 후 비동기 버전으로 조정하는 연구들이 진행되었습니다.</li>
</ul>
</li>
<li><p>ViT (비전 트랜스포머): 셀프 어텐션 메커니즘을 통해 이미지의 전역적인 맥락과 패턴을 효과적으로 포착합니다.</p>
<ul>
<li>이벤트가 발생한 픽셀만으로 패치를 구성하는 Event Transformer(EvT)나, 이벤트의 시공간적 속성을 보존하도록 설계된 3-방향 어텐션 메커니즘 등이 제안되었습니다.</li>
</ul>
</li>
<li><p>SNN (스파이킹 신경망): 이벤트 데이터 처리의 효율성 덕분에 인기를 얻고 있습니다.</p>
</li>
<li><p>GCN (그래프 합성곱 신경망): 이벤트 데이터의 불규칙하고 희소한(sparse) 특성을 처리하기에 적합하여 유망한 접근법으로 평가됩니다.</p>
<ul>
<li>새로운 이벤트에 대한 효율적인 업데이트 규칙을 적용하거나(AEGNN) , 계산 복잡성을 줄이기 위해 이벤트를 대표적인 <strong>복셀(voxel)로 그룹화(복셀화)</strong>하여 전처리하는 전략 등이 사용됩니다.</li>
</ul>
</li>
</ul>
<h3 id="이벤트-데이터-증강-event-data-augmentation">이벤트 데이터 증강 (Event Data Augmentation)</h3>
<p>머신러닝 모델의 일반화 성능을 높이기 위해 훈련 데이터를 인위적으로 늘리는 데이터 증강 기법 또한 이벤트 데이터에 맞게 발전해왔습니다.</p>
<ul>
<li><p>전통적 기법의 적용: 이미지의 이동, 회전, 크기 조절과 같은 기하학적 변환을 이벤트의 좌표에 적용하여 새로운 이벤트 스트림을 생성하는 방식으로 쉽게 활용될 수 있습니다.</p>
</li>
<li><p>이벤트 특화 기법:</p>
<ul>
<li>EventMix: 여러 이벤트 스트림을 하나의 훈련 샘플로 혼합합니다.</li>
<li>EventDrop: 의도적으로 이벤트의 일부를 무작위로 제거하여 모델이 불완전한 데이터에도 강건해지도록 훈련시킵니다.</li>
<li>EventRPG: SNN이 판단한 이벤트의 &#39;중요도(saliency)&#39; 정보를 활용해 덜 중요한 이벤트를 선별적으로 제거하거나 섞는 지능적인 방식을 사용합니다.</li>
</ul>
</li>
</ul>
<h2 id="method">Method</h2>
<h3 id="이벤트-데이터와-노이즈-생성">이벤트 데이터와 노이즈 생성</h3>
<ul>
<li><strong>이벤트 데이터의 기본 원리</strong>: 이벤트 카메라는 각 픽셀이 독립적으로 빛의 밝기 변화를 감지합니다. 변화량이 설정된 임계값을 넘으면, 해당 픽셀의 <strong>좌표(x, y), 발생 시각(t), 변화의 방향(극성, p)</strong>을 담은 하나의 이벤트가 생성됩니다. 이 과정 덕분에 카메라는 높은 시간 해상도를 가진 희소한(sparse) 데이터 스트림을 만들어냅니다. </li>
</ul>
<ul>
<li>노이즈의 종류와 모델링:<ul>
<li><strong>샷 노이즈(Shot Noise)</strong>: 센서 회로의 무작위적인 변동으로 인해 발생하는 노이즈로, 수학적으로 <strong>푸아송 과정(Poisson Process)</strong>을 통해 효과적으로 모델링할 수 있습니다. </li>
<li>본 연구의 노이즈 생성 방법: 본 연구에서는 푸아송 과정을 베르누이 시행(Bernoulli trials) 시퀀스로 근사하여 노이즈를 생성합니다. </li>
</ul>
</li>
</ul>
<blockquote>
<ol>
<li>시간을 아주 짧은 간격(Δt)으로 나눕니다. </li>
<li>각 시간 간격마다, 특정 확률(P)에 따라 노이즈 이벤트의 발생 여부를 결정합니다. </li>
<li>이벤트가 발생하기로 결정되면, 노이즈가 나타날 픽셀의 좌표는 무작위로 선택됩니다. 이 방식은 정밀한 노이즈 강도 조절이 가능하여, 녹화된 실제 노이즈를 사용하는 방법의 한계(제어의 어려움, 오염 가능성)를 극복합니다. </li>
</ol>
</blockquote>
<p>Δt= 1/λ⋅N⋅D</p>
<blockquote>
</blockquote>
<p>P=λ⋅Δt= 1/N⋅D≪1</p>
<h3 id="이벤트-노이즈-필터링무엇과-비교">이벤트 노이즈 필터링(무엇과 비교)</h3>
<p>본 연구에서는 제안된 방법의 성능을 비교하기 위해 3가지 최신 필터링 알고리즘을 사용했습니다. </p>
<ul>
<li><strong>NN (최근접 이웃)</strong>: 특정 공간(3x3 윈도우)과 시간 윈도우 내에 이웃 이벤트가 없는 고립된 이벤트를 노이즈로 보고 제거하는 간단한 규칙 기반 필터입니다. </li>
<li><strong>EDnCNN (이벤트 노이즈 제거 CNN)</strong>: 딥러닝을 이용하는 방식으로, 특정 이벤트 주변(25x25 영역) 픽셀들의 최근 활동 이력(마지막 양수/음수 이벤트 발생 시각)을 분석하여 해당 이벤트가 노이즈인지 아닌지를 분류합니다. </li>
<li><strong>DIF (거리 기반 보간 필터)</strong>: 저사양 임베디드 시스템에 적합한 효율적인 필터입니다. 센서 영역을 여러 하위 영역으로 나누고, 주변 영역의 이벤트 발생 흐름을 바탕으로 특정 위치의 &#39;정상적인&#39; 이벤트 타임스탬프를 예측(보간)합니다. 실제 이벤트의 타임스탬프가 이 예측값과 크게 다르면 노이즈로 간주하여 제거합니다. </li>
</ul>
<h3 id="노이즈-주입-데이터-증강">노이즈 주입 데이터 증강</h3>
<p>노이즈를 훈련에 활용하는 두 가지 전략을 비교 조사했습니다. </p>
<ol>
<li><strong>고정 강도 노이즈 훈련</strong>: 모든 훈련 데이터에 항상 동일한, 고정된 수준의 노이즈를 추가하여 모델을 훈련시키는 방식입니다. </li>
<li><strong>가변 강도 노이즈 훈련 (본 논문의 제안 방법)</strong>: 각 훈련 데이터를 불러올 때마다 매번 다른 강도의 노이즈를 무작위로 주입합니다. 때로는 노이즈가 없기도 합니다. 이 방식은 데이터 증강의 한 형태로, 모델이 다양한 노이즈 환경에 적응하도록 만듭니다. </li>
</ol>
<h3 id="모델-아키텍처-및-이벤트-표현실험-대상">모델 아키텍처 및 이벤트 표현(실험 대상)</h3>
<p>연구 결과의 보편성을 확인하기 위해 4가지 다른 종류의 딥러닝 아키텍처를 사용했습니다.  각 모델은 이벤트 데이터를 처리하기 위해 고유한&#39;이벤트 표현&#39; 방식을 사용합니다.</p>
<ul>
<li><p>CNN (합성곱 신경망)</p>
<ul>
<li>아키텍처: ResNet18을 기반으로 합니다. </li>
<li>이벤트 표현: &#39;이벤트 카운트 이미지&#39;. 양수/음수 극성별로 이벤트 수를 세어 2개 채널을 가진 이미지 형태로 만듭니다. </li>
</ul>
</li>
<li><p>ViT (비전 트랜스포머)</p>
<ul>
<li>아키텍처: MaxViT를 기반으로 합니다. </li>
<li>이벤트 표현: &#39;복셀 그리드&#39;. 시간을 T개의 구간으로 나누고, 각 구간마다 &#39;이벤트 카운트 이미지&#39;를 만들어 총 2T개의 채널을 가진 텐서 형태로 만듭니다. </li>
</ul>
</li>
<li><p>SNN (스파이킹 신경망)</p>
<ul>
<li>아키텍처: ResNet18 기반에 SNN 고유의 뉴런(Integrate-and-Fire)을 적용했습니다. </li>
<li>이벤트 표현: &#39;이벤트 스파이크 텐서&#39;. 시간을 T개의 구간으로 나누어 4차원 텐서(T×2×W×H)를 생성합니다. </li>
</ul>
</li>
<li><p>GCN (그래프 합성곱 신경망)</p>
<ul>
<li>아키텍처: GCN ResNet을 기반으로 하며, SplineConv를 사용합니다. </li>
<li>이벤트 표현: &#39;복셀 그래프&#39;. 계산 복잡성을 줄이기 위해, 시공간을 작은 복셀로 나누고 각 복셀 내의 이벤트들을 하나의 대표 노드로 그룹화하여 그래프를 만듭니다. </li>
</ul>
</li>
</ul>
<h3 id="데이터셋">데이터셋</h3>
<p>분류 작업 성능 평가를 위해 3가지 데이터셋을 사용했습니다. </p>
<ul>
<li>N-Caltech101: 101개 카테고리, 240x180 해상도를 가진 데이터셋입니다. </li>
<li>N-Cars: 2개 카테고리, 120x100 해상도를 가진 실제 환경 데이터셋입니다. </li>
<li>Mini N-ImageNet: 100개 카테고리, 640x480 해상도를 가진 데이터셋입니다. <ul>
<li>N-Caltech101과 Mini N-ImageNet은 모니터에 이미지를 띄우고 이벤트 카메라로 촬영하여 제작되었습니다. </li>
</ul>
</li>
</ul>
<h3 id="구현-세부사항">구현 세부사항</h3>
<ul>
<li>소프트웨어: PyTorch를 기본 환경으로 사용했으며, GCN과 SNN은 각각 PyTorch Geometric, SpikingJelly 라이브러리를 활용했습니다. </li>
<li>주요 파라미터: ViT/SNN의 시간 스텝(T)은 10으로 설정했고, 데이터셋에 따라 50ms 또는 100ms의 이벤트 윈도우를 사용했습니다. </li>
<li>훈련 파라미터: AdamW 옵티마이저를 사용했으며, 학습률은 1e-4, 가중치 감쇠는 1e-4로 설정했습니다.</li>
<li>NVIDIA GH200 및 A100 GPU로 최대 100 에포크까지 훈련했습니다. </li>
<li>필터 파라미터: 비교 실험에 사용된 NN, DIF, EDnCNN 필터들은 각각 논문에 명시된 표준 설정값을 따랐습니다. </li>
</ul>
<h2 id="4-experiments-and-results">4. Experiments and Results</h2>
<p>본 연구의 핵심 목표는 다양한 노이즈 환경에서 딥러닝 모델의 성능을 안정적으로 유지하는 최적의 훈련 방법을 찾는 것입니다. 이를 위해, 제안하는 &#39;노이즈 주입(Noise-injection)&#39; 훈련법의 우수성을 입증하고자 다음과 같이 4가지 다른 방식으로 모델을 훈련시켜 성능을 비교했습니다.</p>
<ul>
<li>Original: 깨끗한 원본 데이터로 훈련한 기준 모델.</li>
<li>Filtered: 전통적인 방식대로, 노이즈를 사전에 제거한 데이터로 훈련한 모델.</li>
<li>Noise=1Hz/px: 특정 노이즈(1Hz/px) 환경에만 특화시킨 &#39;전문가&#39; 모델.</li>
<li>Noise-injection (제안 방법): 다양한 강도의 노이즈를 무작위로 주입하며 훈련시킨 &#39;만능&#39; 모델.</li>
</ul>
<p>이렇게 훈련된 4가지 모델을 ①필터링 없는 환경과 ②필터링을 적용한 환경, 두 가지 시나리오에서 테스트하여 성능을 종합적으로 평가했습니다.</p>
<h3 id="필터링-없는-환경에서의-성능">필터링 없는 환경에서의 성능</h3>
<ul>
<li><p>정성적 결과 
모델이 노이즈 속에서 객체를 어떻게 인식하는지를 시각적으로 분석한 결과, 제안 방법의 압도적인 우수성이 드러났습니다</p>
<ul>
<li>표준 훈련 모델 (w/o): 노이즈가 강해지자 객체에 대한 초점을 완전히 잃고, 엉뚱한 배경을 보거나 활성화가 사라졌습니다.</li>
<li>필터링 적용 모델 (NN): 표준 모델보다는 더 오래 버텼지만, 결국 심한 노이즈에서는 객체를 놓쳤습니다.</li>
<li>제안 방법 (Ours): 노이즈가 가장 극심한 상황(5 Hz)에서도 전혀 흔들림 없이 객체의 특징을 정확하고 안정적으로 포착했습니다.</li>
</ul>
</li>
<li><p>정량적 결과
그래프의 수치적 결과 또한 시각적 분석과 일치했습니다.</p>
</li>
</ul>
<ul>
<li>CNN, ViT, SNN 모델: 제안 방법(Noise-injection, 빨간색 선)은 노이즈 강도가 높아져도 가장 높고 안정적인 정확도를 유지했습니다. 반면 다른 방법들은 노이즈에 매우 취약하여 성능이 급격히 하락했습니다.</li>
<li>Noise=1Hz/px 모델(초록색 선)은 자신이 훈련된 1Hz/px 환경 근처에서만 성능이 잠깐 향상될 뿐, 다른 환경에서는 성능이 매우 저조하여 일반화 능력이 부족함을 보였습니다.</li>
</ul>
<h3 id="필터링-적용-시-성능">필터링 적용 시 성능</h3>
<ul>
<li><p>정량적 결과 
Noise-injection 방법이 거의 모든 모델과 데이터셋 조합에서 가장 높은 평균 정확도를 달성하여 최고의 접근법임을 다시 한번 입증했습니다.</p>
</li>
<li><p>필터링과의 상호작용</p>
<ul>
<li>CNN, ViT, SNN 모델: 매우 흥미롭게도, Noise-injection으로 훈련된 이 모델들에 테스트 시 필터를 추가로 적용했더니 오히려 성능이 저하되었습니다.</li>
<li>이는 EDnCNN 같은 필터가 너무 공격적으로 작동하여 노이즈뿐만 아니라 실제 중요한 이벤트 데이터까지 과도하게 제거하기 때문입니다(그림 3의 낮은 TPR). 즉, 제안 방법으로 훈련된 모델은 이미 노이즈 처리 능력을 내재하고 있어, 외부 필터링이 불필요하거나 오히려 해가 될 수 있음을 시사합니다.</li>
</ul>
</li>
</ul>
<h3 id="주요-예외-gcn-아키텍처">주요 예외: GCN 아키텍처</h3>
<ul>
<li><p>차이점: GCN은 다른 모델들과 달리 Noise-injection으로 훈련해도 노이즈가 강해지면 성능이 점진적으로 감소했습니다. 이는 GCN의 구조상 입력 이벤트 수가 많아지면 그래프 표현이 복잡해지기 때문으로 분석됩니다.</p>
</li>
<li><p>공통점: 그럼에도 불구하고, GCN에서도 Noise-injection이 다른 모든 훈련법보다 일관되게 가장 높은 성능을 보였습니다.</p>
</li>
<li><p>특이점: GCN은 다른 모델과 달리, Noise-injection 훈련과 추가적인 필터링(NN, DIF)을 결합했을 때 성능이 더욱 향상되는 유일한 아키텍처였습니다.</p>
</li>
</ul>
<h2 id="토의-한계-및-결론">토의, 한계 및 결론</h2>
<h3 id="핵심-결론-및-장점">핵심 결론 및 장점</h3>
<ul>
<li><p>효과 입증: 정량적, 정성적 분석을 통해 제안된 Noise-injection 방법이 노이즈가 많은 이벤트 데이터 분류에 매우 효과적임을 확인했습니다.</p>
</li>
<li><p>최고 성능 달성: 이 방법으로 훈련된 모델들은 실험에 사용된 모든 아키텍처와 데이터셋에서 가장 높은 평균 분류 정확도를 달성했습니다.</p>
</li>
<li><p>정보 보존: 가장 큰 장점은 공격적인 필터링 방법이 종종 제거해버리는 핵심 이벤트 정보를 보존하는 능력입니다. 과도한 이벤트 제거는 분류 성능을 떨어뜨리지만, </p>
</li>
<li><p>Noise-injection은 다양한 노이즈에 노출시켜 모델 자체의 견고성을 키웁니다.</p>
</li>
<li><p>필터링의 대안: 이 방법은 신경망에 데이터를 입력하기 전 거치는 필터링 과정의 효과적인 대안이 될 수 있으며 , 다양한 환경에서 신경망의 효율을 높여 비전 시스템의 성능을 크게 향상시킬 잠재력이 있습니다.</p>
</li>
<li><p>확장 가능성: 비록 분류 작업에 국한되어 실험했지만, 객체 탐지와 같은 다른 신경망 기반 작업에도 긍정적인 영향을 미칠 것으로 기대됩니다.</p>
</li>
</ul>
<h3 id="한계-및-트레이드오프">한계 및 트레이드오프</h3>
<ul>
<li><p>필터링의 여전한 필요성: 제안된 방법이 필터링을 완전히 불필요하게 만드는 것은 아닙니다. 데이터 필터링은 처리할 이벤트의 수를 줄여 데이터 전송률, 저장 공간, 전력 소비, 계산 요구량을 낮추는 실용적인 이점이 여전히 존재합니다.</p>
</li>
<li><p>GCN 모델의 한계: 그래프 기반 신경망(GCN)에서는 제안 방법을 사용해도 노이즈가 증가함에 따라 성능이 점진적으로 감소하는 한계가 관찰되었습니다. GCN의 경우, 제안 방법에 적절한 필터링 기술(예: NN 필터)을 결합하면 성능을 더욱 향상시킬 수 있습니다.</p>
</li>
<li><p>성능 트레이드오프: Noise-injection 방법은 노이즈 환경에 대한 견고성을 크게 높이는 대신, 노이즈가 전혀 없는 이상적인 환경에서는 아주 약간의 정확도 감소를 보일 수 있습니다. 이는 폭넓은 안정성을 얻기 위한 자연스러운 성능 절충(trade-off)으로 해석할 수 있습니다.</p>
</li>
</ul>
<h3 id="향후-연구-방향">향후 연구 방향</h3>
<ul>
<li>다른 유형의 노이즈를 탐구하고, 제안된 방법을 기존 필터링 기술과 통합하여 성능을 더욱 개선할 계획입니다.</li>
<li>노이즈로 훈련한 모델과 그렇지 않은 모델 간에 지식 전달(knowledge transfer) 기술을 적용하는 방안을 모색할 것입니다.</li>
<li>GCN과 같이 그래프 기반 네트워크에서 관찰된 문제를 해결하는 데 집중할 예정입니다.</li>
</ul>
<h2 id="addidional-part">Addidional part</h2>
<h3 id="detection-results">Detection results</h3>
<ul>
<li><p>실험 목적:</p>
<ul>
<li>제안된 &#39;Noise-injection&#39; 방법이 분류(classification)보다 더 복잡한 작업인 객체 탐지(object detection)에서도 효과가 있는지 검증하기 위해 진행되었습니다. </li>
</ul>
</li>
<li><p>실험 방법:</p>
<ul>
<li>N-Caltech101 데이터셋을 사용했으며, 분류 실험과 동일한 CNN, ViT 모델을 탐지 헤드(YOLOX)와 결합하여 사용했습니다. </li>
<li>4가지 훈련 방식(Original, Filtered, Noise=1Hz, Noise-injection)을 동일하게 비교했으며, 성능은 <strong>mAP(mean Average Precision)</strong>로 측정했습니다. </li>
</ul>
</li>
<li><p>핵심 결과:</p>
<ul>
<li><p>안정적인 성능: 제안된 방법(Noise-injection)은 노이즈 강도가 높아져도 가장 안정적이고 높은 탐지 성능을 보였습니다. 다른 방법들은 노이즈에 따라 성능이 급격히 저하되었습니다. </p>
</li>
<li><p>필터링 적용 시에도 우위: 테스트 데이터에 필터를 적용하여 다른 방법들의 성능을 보강해주어도, 제안된 방법이 여전히 최고의 결과를 달성했습니다. </p>
</li>
</ul>
</li>
</ul>
<h3 id="ablation-over-different-filter-parameters">Ablation over different filter parameters</h3>
<ul>
<li><p>실험 목적:</p>
<ul>
<li>&quot;기존 필터링 방법의 설정을 최적의 상태로 완벽하게 조절하더라도, 제안된 Noise-injection 방법이 여전히 더 우수한가?&quot;라는 질문에 답하기 위해 진행되었습니다.</li>
</ul>
</li>
<li><p>핵심 결과:</p>
<ul>
<li><p>완벽한 필터는 없음: 필터의 내부 설정값(Threshold)을 조절해 본 결과, 진짜 이벤트 보존율(TPR)과 노이즈 통과율(FPR) 사이에는 근본적인 트레이드오프 관계가 있어, 모든 노이즈를 완벽하게 제거하는 최적의 설정값은 존재하지 않음이 확인되었습니다.</p>
</li>
<li><p>제안 방법의 압도적 우위: 가장 중요한 발견으로, Filtered 데이터로 훈련된 전통적인 모델이 자신에게 가장 유리한 최적의 설정값을 사용했을 때조차, Noise-injection으로 훈련된 모델의 성능을 단 한 번도 뛰어넘지 못했습니다.</p>
</li>
<li><p>필터링이 오히려 방해: Noise-injection으로 훈련된 모델은 필터링을 약하게 할수록(즉, 이벤트를 덜 제거할수록) 오히려 성능이 더 좋아지는 경향을 보였습니다. 이는 모델 자체가 노이즈 처리 능력을 갖추었기 때문에, 과도한 필터링은 오히려 해가 될 수 있음을 의미합니다.</p>
</li>
</ul>
</li>
</ul>
<h3 id="real-noise-analysis">Real Noise Analysis</h3>
<ul>
<li><p>실험 목적
이 실험의 핵심 목표는 <strong>&quot;인공적으로 생성된 노이즈로 훈련시킨 제안 방법이, 실제 카메라에서 발생하는 &#39;진짜 노이즈&#39; 환경에서도 효과적인지&quot;</strong>를 검증하는 것입니다.</p>
</li>
<li><p>실험 방법</p>
<ul>
<li><p>실제 이벤트 카메라로 변화가 없는 정적인 장면을 촬영하여 &#39;순수 노이즈&#39; 데이터를 수집했습니다.</p>
</li>
<li><p>이 진짜 노이즈를 N-Caltech101 테스트 데이터에 섞은 후, 이전에 인공 노이즈로 훈련된 4가지 종류의 모델(CNN, ViT, SNN, GCN) 성능을 평가했습니다.</p>
</li>
</ul>
</li>
<li><p>핵심 결과</p>
<ul>
<li><p>제안된 Noise-injection 방법은 실제 노이즈 환경에서도 CNN, ViT, SNN 모델에 걸쳐 일관되게 가장 우수하고 안정적인 성능을 보였습니다.</p>
</li>
<li><p>ViT 모델의 경우, 노이즈가 매우 약할 때는 Filtered 방식이 근소하게(약 0.5%) 앞섰으나, 노이즈가 강해지자 제안 방법이 명확하고 상당한 우위를 보였습니다.</p>
</li>
<li><p>GCN 모델에서도 제안 방법은 Original 및 Filtered 모델보다 월등히 뛰어난 성능을 기록했습니다.</p>
</li>
</ul>
</li>
</ul>
<h3 id="timing-results">Timing Results</h3>
<ul>
<li><p>필터링의 비용: 필터링은 노이즈를 줄여주지만, 시스템의 전체 처리 시간을 늘리는 추가적인 전처리 단계입니다.</p>
</li>
<li><p>처리 속도 비교: 각 필터의 처리 속도를 분석한 결과, EDnCNN은 고성능 GPU를 사용했음에도 불구하고 다른 CPU 기반 필터(NN, DIF)보다 처리 속도가 현저히 느려 실시간 시스템에 적용하기 어렵다는 점이 확인되었습니다.((알고리즘 vs. 딥러닝)이 달라 실험 환경과 처리 속도에서 큰 차이를 보인 것입니다.)</p>
</li>
<li><p>필터링의 한계: NN과 DIF 필터 역시 최신 이벤트 센서의 데이터 생성 속도를 따라가기에는 상대적으로 느린 수준이며, 이를 해결하려면 FPGA 같은 별도의 하드웨어 가속이 필요합니다.</p>
</li>
<li><p>제안 방법의 이점: 결론적으로, 제안된 Noise-injection 방법은 이러한 전처리 필터 단계가 전혀 필요 없으므로, 추가적인 계산 자원이나 지연 시간 없이 임베디드 시스템에서 자원을 효율적으로 활용할 수 있는 중요한 이점이 있습니다.</p>
</li>
</ul>
<h3 id="detailed-results">Detailed Results</h3>
<ul>
<li><p>상세 수치 결과 (표 5, 6, 7, 8)</p>
<ul>
<li>핵심 내용: 4가지 훈련 방식(Original, Filtered, Noise=1Hz, Noise-injection)의 성능을 비교해 보면, 제안 방법(Noise-injection, 표 8)이 다른 모든 방식에 비해 모든 노이즈 구간에서 일관되게 가장 높고 안정적인 정확도를 기록했음을 수치로 명확히 보여줍니다.</li>
</ul>
</li>
<li><p>상세 시각 자료 (그림 8, 9)</p>
<ul>
<li>핵심 내용: 표준 방법으로 훈련된 모델은 노이즈가 심해지면 객체에 대한 초점을 잃고 활성화가 흩어지는 반면, 제안된 방법(Our)으로 훈련된 모델은 가장 극심한 노이즈 환경에서도 객체에만 안정적으로 집중하는 일관된 패턴을 보여줍니다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[LogLLM: Log-based Anomaly Detection Using Large Language Models]]></title>
            <link>https://velog.io/@hye0n_w00/LogLLM-Log-based-Anomaly-Detection-Using-Large-Language-Models</link>
            <guid>https://velog.io/@hye0n_w00/LogLLM-Log-based-Anomaly-Detection-Using-Large-Language-Models</guid>
            <pubDate>Thu, 24 Jul 2025 04:24:01 GMT</pubDate>
            <description><![CDATA[<p>최근 대규모 언어 모델(LLM)을 활용한 방법들이 등장했지만, 이들 역시 다음과 같은 문제점을 가집니다:</p>
<ul>
<li>프롬프트 엔지니어링 기반 방법: LLM의 내장된 지식에만 의존하여 특정 데이터셋에서는 성능이 떨어집니다.</li>
<li>미세 조정 기반 방법: LLM을 특정 데이터에 맞게 조정하지만, 의미 이해가 제한적이거나 메모리 초과 같은 기술적 문제에 부딪힙니다.</li>
</ul>
<p>이 논문은 대규모 언어 모델(LLM)을 활용하여 소프트웨어 시스템 로그에서 이상 징후를 탐지하는 새로운 프레임워크인 &#39;LogLLM&#39;을 제안합니다. 기존의 딥러닝 방법들은 자연어로 구성된 로그 데이터의 의미적 정보(semantic information)를 효과적으로 포착하는 데 어려움을 겪었지만, LogLLM은 이 문제를 해결하고자 합니다.</p>
<h2 id="주요-특징-및-아키텍처">주요 특징 및 아키텍처</h2>
<ol>
<li>듀얼 LLM 아키텍처: 이 연구는 로그 기반 이상 탐지를 위해 인코더 기반 LLM(BERT)과 디코더 기반 LLM(Llama)을 동시에 활용한 첫 시도입니다. <ul>
<li>BERT (인코더): 각 로그 메시지를 개별적으로 분석하여 의미적 정보를 담은 벡터(semantic vector)를 추출하는 역할을 합니다. </li>
<li>Llama (디코더): BERT가 추출한 로그 시퀀스 전체의 벡터를 입력받아, 해당 시퀀스가 &#39;정상&#39;인지 &#39;비정상&#39;인지를 분류합니다. </li>
</ul>
</li>
<li>프로젝터 (Projector): BERT와 Llama는 서로 다른 벡터 공간을 사용하기 때문에, 이 둘을 연결하기 위한 &#39;프로젝터&#39;라는 선형 계층을 도입했습니다. 프로젝터는 BERT가 생성한 의미 벡터를 Llama가 이해할 수 있는 토큰 임베딩 벡터로 변환하여 두 모델 간의 의미적 일관성을 보장합니다. </li>
<li>간소화된 전처리: 전통적인 방법들이 로그 템플릿을 추출하기 위해 로그 파서(log parser)를 사용하는 것과 달리, LogLLM은 정규 표현식(regular expressions)을 사용하여 로그 메시지 내의 동적 파라미터(IP 주소, 디렉터리 경로 등)를 &lt;*&gt;와 같은 일관된 토큰으로 대체합니다. 이 방식은 파서의 오류 가능성을 줄이고 전체 프로세스를 간소화합니다. </li>
<li>독창적인 3단계 훈련 절차: 모델의 성능과 적응성을 극대화하기 위해 다음과 같은 3단계 훈련 절차를 제안했습니다. <ul>
<li>1단계: Llama가 &quot;이 시퀀스는 정상/비정상입니다&quot;와 같은 정해진 답변 형식을 학습하도록 미세 조정(fine-tuning)합니다. </li>
<li>2단계: BERT와 프로젝터로 구성된 임베더(embedder)를 훈련하여, 각 로그 메시지를 Llama가 가장 잘 이해할 수 있는 임베딩으로 변환하도록 합니다. </li>
<li>3단계: 모델의 모든 구성 요소(BERT, 프로젝터, Llama)를 통합하여 전체적으로 미세 조정함으로써 일관되고 정확한 성능을 확보합니다. </li>
</ul>
</li>
</ol>
<h2 id="logllm-처리-과정-요약">LogLLM 처리 과정 요약</h2>
<ol>
<li><p>전처리 단계</p>
<ul>
<li>원본 로그 시퀀스에 포함된 IP 주소나 숫자처럼 계속 변하는 값들을 정규 표현식을 사용하여 &lt;*&gt;와 같은 일관된 토큰으로 변경합니다.</li>
</ul>
</li>
<li><p>임베딩 단계 (의미 벡터 추출)</p>
<ul>
<li>BERT가 전처리된 각 로그 메시지를 분석하여 문맥적 의미가 담긴 벡터로 변환합니다.</li>
<li><strong>프로젝터(Projector)</strong>가 BERT가 만든 벡터를 Llama가 이해할 수 있는 형태의 벡터로 조정하는 다리 역할을 합니다.</li>
</ul>
</li>
<li><p>프롬프트 구성 및 최종 분류 단계</p>
<ul>
<li>로그의 의미 벡터들 앞뒤에 &quot;다음은 시스템 로그 시퀀스입니다:&quot;와 같은  안내 문장과 &quot;이 시퀀스는 정상인가요, 비정상인가요?&quot;와 같은 질문을 벡터 형태로 조합하여 Llama에게 보낼 하나의 완전한 프롬프트(질문서)를 구성합니다.</li>
<li>최종적으로 Llama가 이 프롬프트를 전체적으로 이해하고, 해당 로그 시퀀스가 정상인지 비정상인지 판단하는 답변을 생성합니다.</li>
</ul>
</li>
</ol>
<h2 id="실험-및-결과">실험 및 결과</h2>
<p>LogLLM의 성능을 검증하기 위해 HDFS, BGL, Liberty, Thunderbird 등 4개의 공개 데이터셋을 대상으로 광범위한 실험을 수행했습니다. </p>
<ul>
<li><p>성능: LogLLM은 실험에 사용된 모든 데이터셋에서 기존의 최신 기술(state-of-the-art)들을 능가하는 가장 높은 F1점수를 기록했습니다. 특히 기존 최고 성능 모델인 NeuralLog보다 평균적으로 6.6% 더 높은 F1 점수를 달성하며 그 효과성을 입증했습니다. </p>
</li>
<li><p>안정성: LogLLM은 오탐(false alarm)을 낮게 유지하면서도 이상 징후를 놓치지 않는, 즉 정밀도(Precision)와 재현율(Recall) 사이의 균형을 잘 맞추는 모습을 보였습니다. </p>
</li>
<li><p>전처리 및 아키텍처의 효과: 실험을 통해 정규 표현식을 사용한 전처리 방식이 다른 방식(로그 파서 사용 등)보다 우수함을 확인했습니다. 또한, BERT와 프로젝터로 구성된 임베더를 사용하는 것이 단순히 로그 전체를 Llama에 직접 입력하는 것보다 메모리 문제를 피하고 성능을 향상시키는 데 필수적임을 증명했습니다. </p>
</li>
<li><p>훈련 절차의 중요성: 3단계 훈련 절차 중 어느 한 단계라도 생략하면 성능이 저하되었으며, 특히 1단계(Llama 답변 형식 학습)를 건너뛰었을 때 성능이 가장 크게 하락했습니다.  이는 제안된 훈련 절차의 각 단계가 모델 최적화에 필수적임을 보여줍니다.</p>
</li>
<li><p>계산 비용: LogLLM은 최고의 성능을 보였지만, 모델의 규모가 큰 만큼 다른 방법들에 비해 훈련 시간이 가장 오래 걸렸습니다. </p>
</li>
</ul>
<h2 id="결론">결론</h2>
<p>LogLLM은 인코더와 디코더 LLM을 결합하고, 이 둘을 효과적으로 연결하는 프로젝터를 도입하였으며, 독창적인 3단계 훈련 절차를 통해 로그 데이터의 의미적 정보를 깊이 있게 이해하고 이상 징후를 매우 정확하게 탐지하는 새로운 프레임워크입니다. 실험 결과는 LogLLM이 기존 방법들보다 월등한 성능을 보임을 명확히 입증했습니다.</p>
<h2 id="추가-지식">추가 지식</h2>
<h4 id="bert-bidirectional-encoder-representations-from-transformers">BERT (Bidirectional Encoder Representations from Transformers)</h4>
<p>BERT는 구글이 개발한 언어 모델로, 문장의 전체 문맥을 파악하여 의미를 이해하는 데 특화되어 있습니다. 이름의 &#39;Bidirectional(양방향)&#39;이 가장 큰 특징입니다.</p>
<ul>
<li><p>작동 방식: BERT는 문장을 처음부터 끝까지 한 번에 읽습니다. 특정 단어의 의미를 파악하기 위해 그 단어의 앞뒤에 있는 모든 단어를 동시에 고려합니다. 이는 마치 우리가 문장에서 빈칸에 들어갈 단어를 맞힐 때 문장 전체를 읽고 추론하는 것과 같습니다.</p>
</li>
<li><p>구조 (인코더): BERT는 트랜스포머(Transformer) 아키텍처의 인코더(Encoder) 부분만을 사용합니다. 인코더는 입력된 텍스트의 의미를 압축하여 풍부한 정보가 담긴 숫자 벡터(vector)로 만드는 역할을 합니다.</p>
</li>
</ul>
<h4 id="llama-large-language-model-meta-ai">Llama (Large Language Model Meta AI)</h4>
<p>Llama는 메타(구 페이스북)가 개발한 언어 모델로, 주어진 내용을 바탕으로 다음 내용을 자연스럽게 생성하는 데 특화되어 있습니다.</p>
<p>작동 방식: Llama는 이전에 나온 단어들을 기반으로 다음에 올 단어를 예측하는 방식으로 작동합니다. 마치 스마트폰의 자동 완성 기능처럼, &quot;고양이가 소파 위에...&quot;라고 입력하면 &quot;앉았습니다.&quot;라는 단어를 예측하여 문장을 이어 나갑니다.</p>
<p>구조 (디코더): Llama는 트랜스포머 아키텍처의 디코더(Decoder) 부분만을 사용합니다. 디코더는 주어진 정보를 바탕으로 새로운 텍스트를 순차적으로 생성하는 역할을 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Large language models can be zero-shot anomaly detectors for time series?]]></title>
            <link>https://velog.io/@hye0n_w00/Large-language-models-can-be-zero-shot-anomaly-detectors-for-time-series</link>
            <guid>https://velog.io/@hye0n_w00/Large-language-models-can-be-zero-shot-anomaly-detectors-for-time-series</guid>
            <pubDate>Thu, 24 Jul 2025 02:12:08 GMT</pubDate>
            <description><![CDATA[<p>이 논문은 &quot;SIGLLM&quot;이라는 새로운 프레임워크를 통해 대규모 언어 모델(LLM)을 시계열 데이터의 이상 징후를 별도의 학습 없이(zero-shot) detection 하는 연구를 제시합니다. 연구진은 시계열 데이터를 텍스트로 변환하여 LLM이 처리할 수 있도록 하는 모듈을 개발했으며, 이를 통해 두 가지 주요 탐지 방법을 제안하고 평가했습니다. </p>
<p>두 가지 핵심 접근법은 다음과 같습니다:</p>
<ul>
<li><p>PROMPTER: LLM에게 직접적으로 시계열 데이터 내의 이상 징후를 찾아달라고 요청하는 프롬프트 기반 방식입니다. </p>
</li>
<li><p>DETECTOR: LLM의 시계열 예측 능력을 활용하는 방식입니다. 모델이 예측한 값과 실제 값의 차이(오차)를 분석하여 그 차이가 큰 부분을 이상 징후로 판단합니다. </p>
</li>
</ul>
<p>11개의 다양한 데이터셋을 대상으로 GPT-3.5와 MISTRAL 모델을 사용하여 실험한 결과, 예측 기반의 DETECTOR 방식이 직접 질문하는 PROMPTER 방식보다 F1 점수 기준으로 135% 더 뛰어난 성능을 보였습니다. 이는 PROMPTER 방식이 잘못된 탐지(false positives)가 많은 경향이 있기 때문입니다. 
DETECTOR 방식은 비록 데이터의 전체적인 추세는 완벽히 예측하지 못하더라도, 결과적으로 실제 이상 징후를 매우 정확하게 찾아냅니다. 이에 반대로  PROMPTER 방식은 일부 이상 징후를 찾기는 하지만, 실수가 너무 많아(오탐지가 높음) 신뢰하기 어렵다는 것을 보여줍니다.</p>
<p>주요 연구 결과는 다음과 같습니다:</p>
<ul>
<li>LLM 기반의 이상 탐지 모델은 기존의 단순 이동 평균(Moving Average) 기준 모델보다 향상된 성능을 보였으며, 트랜스포머 기반의 이상 탐지 모델(Anomaly Transformer)보다도 우수한 결과를 나타냈습니다.</li>
<li>하지만, 현재 가장 발전된 딥러닝 기반 이상 탐지 모델(State-of-the-art deep learning models)과 비교했을 때는 LLM의 성능이 약 30% 뒤처지는 것으로 나타나 여전히 성능 차이가 존재합니다. </li>
<li>실용성 측면에서, LLM을 활용하는 방식은 별도의 학습이 필요 없다는 장점이 있지만, 응답을 받기까지의 대기 시간(latency)이 길다는 단점이 있습니다. </li>
</ul>
<h2 id="llm-활용의-실용성-장점과-단점">LLM 활용의 실용성: 장점과 단점</h2>
<p>장점: 별도의 학습 불필요 (Zero-shot)
단점: 긴 응답 대기 시간 (Latency)</p>
<ul>
<li><p>실행 시간: 논문의 실험 결과에 따르면, DETECTOR(Mistral 모델 사용) 방식은 신호 하나를 처리하는 데 평균 약 2.1시간이 걸렸고, PROMPTER(GPT-3.5 모델 사용) 방식은 평균 약 1.1시간이 소요되었습니다. 이는 1시간 이내에 학습을 마치는 일반적인 딥러닝 모델보다도 훨씬 긴 시간입니다.</p>
<h2 id="시계열-텍스트-변환-time-series-to-text-conversion">시계열-텍스트 변환 (Time-series-to-text conversion)</h2>
<p>LLM은 기본적으로 텍스트 데이터를 처리하도록 설계되었기 때문에, 숫자 데이터인 시계열을 직접 입력할 수 없습니다. SIGLLM은 다음과 같은 네 단계의 변환 과정을 거쳐 시계열 데이터를 LLM에 입력 가능한 텍스트로 만듭니다:</p>
</li>
<li><p>스케일링 (Scaling): 시계열 데이터의 모든 값을 양수로 만들기 위해 최솟값을 빼주는 방식을 사용합니다. 이를 통해 음수 부호(&#39;-&#39;)를 처리할 필요가 없어 토큰 사용을 줄이고 계산 효율성을 높입니다.</p>
</li>
<li><p>양자화 (Quantization): 무한한 실수 값을 LLM이 처리할 수 있는 유한한 정수 값으로 변환합니다. 소수점 이하 값을 반올림하여 정수로 만들어 토큰 낭비를 막습니다.</p>
</li>
<li><p>롤링 윈도우 (Rolling windows): LLM이 한 번에 처리할 수 있는 입력 길이(context length)에는 제한이 있으므로, 긴 시계열 데이터를 일정한 크기의 여러 조각(window)으로 나눕니다.</p>
</li>
<li><p>토큰화 (Tokenization): 숫자들을 개별 숫자로 인식하도록 처리합니다. 예를 들어 GPT 모델의 경우, &#39;2345&#39;를 하나의 덩어리로 인식하는 경향이 있는데, 이를 &#39;2 3 4 5&#39;와 같이 숫자 사이에 공백을 삽입하여 각 숫자를 별개의 토큰으로 인식하게 만듭니다.</p>
</li>
</ul>
<h2 id="1-llm-기반-이상-탐지-모델">1. LLM 기반 이상 탐지 모델</h2>
<p>이 연구에서 제안하는 모델로, 사전 학습된 LLM을 별도의 추가 학습(fine-tuning) 없이 이상 탐지에 바로 활용하는 것이 특징입니다. SIGLLM 프레임워크를 통해 시계열 데이터를 텍스트로 변환한 뒤, &#39;PROMPTER&#39;나 &#39;DETECTOR&#39; 방식으로 이상 징후를 탐지합니다. 이 모델의 가장 큰 장점은 Zero-shot 학습, 즉 특정 데이터에 대한 사전 학습 없이도 문제를 해결할 수 있다는 점입니다.</p>
<h2 id="2-단순-이동-평균-moving-average-기준-모델">2. 단순 이동 평균 (Moving Average) 기준 모델</h2>
<p>이는 고전적인 통계 기반 방법 중 하나입니다. 특정 기간 동안의 데이터 값들의 평균을 계산하고, 이 평균에서 크게 벗어나는 값을 이상 징후로 판단하는 간단한 방식입니다. 연구에서는 이 모델을 성능 비교를 위한 <strong>기본 기준선(Baseline)</strong>으로 사용했습니다.</p>
<h2 id="3-트랜스포머-기반-이상-탐지-모델-anomaly-transformer-at">3. 트랜스포머 기반 이상 탐지 모델 (Anomaly Transformer, AT)</h2>
<p>트랜스포머 아키텍처를 시계열 이상 탐지에 직접 적용한 모델입니다. 트랜스포머의 핵심인 <strong>어텐션 메커니즘(attention mechanism)</strong>을 활용하여 시계열 데이터 내의 시간적 연관성을 학습합니다. Anomaly Transformer는 특정 시점과 이전 시점들 간의 연관성 점수를 계산하고, 이 점수가 낮은(즉, 연관성이 적은) 부분을 이상 징후로 판단하는 방식으로 작동합니다.</p>
<h2 id="4-딥러닝-기반-이상-탐지-모델-state-of-the-art-deep-learning-models">4. 딥러닝 기반 이상 탐지 모델 (State-of-the-art deep learning models)</h2>
<p>현재 가장 성능이 우수하다고 알려진 딥러닝 모델들을 의미합니다. 이 논문에서는 여러 딥러닝 모델을 비교 대상으로 사용했으며, 주로 예측 기반(forecasting-based) 또는 재구성 기반(reconstruction-based) 모델로 나뉩니다.</p>
<ul>
<li><p>LSTM DT (Long Short-Term Memory with Dynamic Thresholding): LSTM 모델을 사용하여 시계열을 예측하고, 예측 오차에 동적 임계값을 적용하여 이상 징후를 탐지하는 예측 기반 모델입니다.</p>
</li>
<li><p>AER (Auto-encoder with Regression): 오토인코더를 이용한 재구성과 회귀를 통한 예측을 결합한 하이브리드 모델입니다. 이 연구에서 비교된 딥러닝 모델 중 가장 우수한 성능을 보였습니다.</p>
</li>
<li><p>VAE (Variational AutoEncoders), TadGAN (Time series anomaly detection using GANs): 각각 변이형 오토인코더와 생성적 적대 신경망(GAN)을 사용하여 정상 데이터를 학습하고, 입력된 데이터가 정상 데이터의 패턴과 얼마나 다른지를 측정(재구성 오차)하여 이상 징후를 탐지하는 재구성 기반 모델들입니다.</p>
</li>
</ul>
<h2 id="트랜스포머-기반-모델보다-성능이-좋은-이유">트랜스포머 기반 모델보다 성능이 좋은 이유:</h2>
<p>LLM은 방대한 양의 텍스트 데이터를 통해 복잡하고 다양한 패턴을 사전 학습한 상태입니다. 이 능력 덕분에 시계열 데이터를 텍스트로 변환했을 때, 데이터 내의 미묘한 문맥적 이상 징후를 더 잘 포착할 수 있습니다. 반면, Anomaly Transformer와 같은 특정 목적의 트랜스포머 모델은 해당 데이터셋에만 국한된 학습을 하므로, LLM처럼 광범위한 패턴 이해 능력을 갖추기 어렵습니다. 논문에서도 LLM 기반의 DETECTOR 방식이 Anomaly Transformer보다 7개 데이터셋에서 더 나은 성능을 보였다고 언급합니다.</p>
<h2 id="딥러닝-모델보다-성능이-낮은-이유">딥러닝 모델보다 성능이 낮은 이유:</h2>
<ul>
<li>제한된 컨텍스트 길이 (Limited Context Length): LLM은 한 번에 처리할 수 있는 데이터의 길이가 제한적입니다. 이 때문에 긴 시계열 데이터를 여러 개의 작은 조각(rolling windows)으로 나누어 처리해야 합니다. 이 과정에서 시계열 전체의 장기적인 패턴이나 추세(trend)를 놓치기 쉽습니다. 예를 들어, 논문의 한 예시에서는 LLM 예측이 데이터의 전반적인 상승 추세를 제대로 포착하지 못했습니다.</li>
<li>데이터 처리의 비효율성: 시계열 데이터를 텍스트로 변환하고, 다시 여러 조각으로 나누는 과정 자체가 비효율적이고 비용이 많이 듭니다. 이로 인해 전체적인 데이터의 특성을 온전히 학습하기 어렵습니다. 반면, AER이나 LSTM DT와 같은 딥러닝 모델들은 시계열 데이터 처리에 최적화되어 있어 데이터의 전체적인 특성을 더 효과적으로 학습할 수 있습니다.</li>
<li>부정확한 탐지: PROMPTER 방식의 경우, 이상 징후가 아닌데도 이상 징후로 판단하는 오탐지(false alarm)가 많아 전체적인 정밀도를 떨어뜨립니다.</li>
</ul>
<h2 id="딥러닝-모델보다-성능을-높이기-위한-개선-방안">딥러닝 모델보다 성능을 높이기 위한 개선 방안</h2>
<p>논문에서는 LLM 기반 모델의 성능을 딥러닝 수준으로 끌어올리기 위한 몇 가지 개선 방향을 제시하고 있습니다.</p>
<ul>
<li><p>후처리(Post-processing) 전략 강화:</p>
<ul>
<li>오탐지 필터링 개선: PROMPTER 방식의 가장 큰 문제인 오탐지를 줄이기 위한 정교한 필터링 전략이 필요합니다. 예를 들어, 단순히 빈도수에 기반한 필터링 대신, LLM이 특정 값을 생성할 때의 로그 확률(log probabilities)을 신뢰도 점수로 활용하여 확신이 낮은 예측을 걸러내는 방법을 탐색할 수 있습니다.</li>
<li>정교한 오차 함수(Error Function) 탐색: DETECTOR 방식에서는 예측값과 실제값의 차이를 계산하는 오차 함수가 핵심입니다. 현재는 단순한 절대 오차나 제곱 오차를 사용했지만 , 데이터의 특성에 맞는 더 복잡하고 정교한 오차 함수를 개발하여 이상 징후를 더 명확하게 드러내는 연구가 필요합니다.</li>
</ul>
</li>
<li><p>컨텍스트 처리 능력 향상:</p>
<ul>
<li>LLM 기술이 발전함에 따라 더 긴 컨텍스트를 처리할 수 있는 모델들이 계속 등장하고 있습니다. 이러한 차세대 LLM을 활용하면 시계열 데이터를 자르지 않고 전체를 한 번에 처리하여 장기적인 패턴을 학습할 수 있게 되어 성능이 크게 향상될 수 있습니다.</li>
</ul>
</li>
<li><p>다변량 시계열 데이터로의 확장:</p>
<ul>
<li>현재 프레임워크는 하나의 변수만 처리하는 단변량(univariate) 시계열에 맞춰져 있습니다. 여러 변수 간의 상호작용에서 이상 징후가 발생하는 다변량(multivariate) 시계열 데이터를 처리할 수 있도록 프레임워크를 확장하는 연구가 필요합니다. 이를 통해 더 복잡하고 실제적인 문제에 적용할 수 있을 것입니다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Machine Learning(05.신경망)]]></title>
            <link>https://velog.io/@hye0n_w00/Machine-Learning05.%EC%8B%A0%EA%B2%BD%EB%A7%9D</link>
            <guid>https://velog.io/@hye0n_w00/Machine-Learning05.%EC%8B%A0%EA%B2%BD%EB%A7%9D</guid>
            <pubDate>Tue, 22 Jul 2025 05:56:18 GMT</pubDate>
            <description><![CDATA[<p>&quot; 신경망이란, 적응성이 있는 단순 단위로 구성된 광범위하고 서로 연결된 네트워크다. 이 조직은 현실 세계 사물에 대한 생물 신경계통의 상호작용을 모방할 수 있다.&quot;</p>
<h1 id="51-뉴런-모델">5.1 뉴런 모델</h1>
<h3 id="mcculloch-and-pitts-neuron">McCulloch and pitts neuron</h3>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/6d716ff0-d24c-4608-8c37-d660c2e53394/image.png" alt=""></p>
<ul>
<li>가장 이상적인 활성화 함수
<img src="https://velog.velcdn.com/images/hye0n_w00/post/09eab2f8-80c7-48a8-bee0-9bbe471b88ab/image.png" alt=""></li>
<li>불연속성이라는 특성을 보안한 함수(sigmoid function == Squasing function)
<img src="https://velog.velcdn.com/images/hye0n_w00/post/cd02dd4c-513d-4917-9547-bae8f68a7c12/image.png" alt=""></li>
</ul>
<h1 id="52-퍼셉트론과-다층-네트워크">5.2 퍼셉트론과 다층 네트워크</h1>
<h3 id="perceptron">Perceptron</h3>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/9e9744ff-88b5-4c04-99ca-3efb4982cf10/image.png" alt="">
두 개의 뉴런으로 구성되어 입력층이 외부 입력 신호를 받은 후 출력층으로 전달하는 구조
출력층은 M-P neuron으로 구성</p>
<h3 id="단층-퍼셉트론-single-layer-perceptron">단층 퍼셉트론 (Single-Layer Perceptron)</h3>
<p>단층 퍼셉트론은 AND, OR, NAND와 같은 논리 연산을 계산할 수 있는 신경망의 가장 기본적인 형태입니다. 그 구조는 다음과 같은 수식으로 표현됩니다.</p>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/4eb84aba-ae83-4295-9330-34125a5bd308/image.png" alt=""></p>
<ul>
<li><p>학습 과정:</p>
<ul>
<li>퍼셉트론은 훈련 데이터를 통해 가중치(w)와 임계값(θ)을 학습합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/9d0ac902-c67b-4bd0-bd9f-8e3ede49c48b/image.png" alt="">
만약 퍼셉트론의 예측(y^)이 실제 값(y)과 일치하면 가중치에 변화가 없고, 예측이 틀리면 가중치가 조정됩니다.</li>
</ul>
</li>
<li><p>한계:
단층 퍼셉트론은 선형적으로 분리가 가능한 문제만 해결할 수 있습니다. 예를 들어 XOR 문제와 같이 선형적으로 분리할 수 없는 문제는 해결할 수 없습니다. 이는 단층 퍼셉트론이 오직 하나의 층(입력층과 출력층)만으로 구성되어 있기 때문이며, 이로 인해 학습 능력이 매우 제한적입니다.</p>
</li>
</ul>
<h3 id="다층-순방향-신경망-multi-layer-feedforward-neural-networks">다층 순방향 신경망 (Multi-Layer Feedforward Neural Networks)</h3>
<p>단층 퍼셉트론의 한계를 극복하기 위해 제안된 구조가 다층 순방향 신경망입니다. 이는 여러 층의 뉴런을 겹겹이 쌓은 구조입니다.</p>
<ul>
<li>구조적 특징:<ul>
<li>겹층 구조: 입력층, 하나 이상의 은닉층(Hidden Layer), 그리고 출력층으로 구성됩니다.</li>
<li>순방향 연결: 각 층의 뉴런은 다음 층의 뉴런과만 연결됩니다. 같은 층의 뉴런끼리는 연결되어 있지 않으며, 층을 뛰어넘는 연결도 없습니다.</li>
<li>기능성 뉴런: 입력층은 단순히 외부 입력을 받는 역할만 하며, 실제 신호 처리와 학습은 은닉층과 출력층의 기능성 뉴런들이 담당합니다.</li>
<li>단일 은닉층 신경망: 은닉층이 하나만 있는 구조를 &#39;Neural Networks with a Single Hidden Layer&#39;라고 부릅니다.</li>
</ul>
</li>
</ul>
<p>다중 은닉층 신경망: 두 개 이상의 은닉층을 가진 구조도 가능하며, 이는 더 복잡한 문제 해결에 사용됩니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/380b7896-6cd7-4928-b52f-1f67ff5f75c5/image.png" alt=""></p>
<ul>
<li>학습 과정:<ul>
<li>다층 순방향 신경망은 훈련 데이터를 통해 학습을 진행합니다. 학습의 핵심은 <strong>뉴런 간의 연결 가중치(w)</strong>와 <strong>각 기능성 뉴런의 임계값(θ)</strong>을 조절하는 것입니다. 즉, 신경망의 학습 능력은 이 가중치와 임계값에 내재되어 있습니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/4af46c3f-d218-40b4-9cd2-15802772db6d/image.png" alt=""></li>
</ul>
</li>
</ul>
<h1 id="53-오차-역전파-알고리즘">5.3 오차 역전파 알고리즘</h1>
<p>역전파 알고리즘은 Input과 Output을 알고 있는 상태에서 신경망을 학습시키는 방법입니다. 역전파 알고리즘을 적용하기 이전에 MLP에 대해 다음과 같이 정의합니다.</p>
<ul>
<li>초기 가중치 값은 랜덤으로 주어짐</li>
<li>각각의 노드는 하나의 퍼셉트론으로 생각함. 즉 노드를 지나칠 때마다 활성 함수를 적용하며, 활성화 함수를 적용하기 이전을 net, 이후를 out이라 함.</li>
<li>다음 레이어의 계산에는 out값을 사용하며, 마지막 out이 output이 됨.</li>
<li>활성화 함수로 시그모이드 함수를 사용함.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/8e41d246-d93e-4fed-9a6d-3f27d0f8489d/image.png" alt=""></p>
<h3 id="1-기본-원리-경사-하강법-gradient-descent">1. 기본 원리: 경사 하강법 (Gradient Descent)</h3>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/08645f05-8a57-49c1-8f07-703cbb005a01/image.png" alt=""></p>
<p>각각 가중치가 2개일때 (w1,w2), 오차 E를 도식화하면 위와 같은데, y=0,w1=0,w2=0일 때 E가 최소화됩니다.</p>
<p>따라서 오차 E를 모든 가중치들에 대한 방정식으로 본다면, 우리가 해야할 것은 가중치 w를 수정해 E가 최소가 되도록 만드는 것이며, 이를 위해 경사하강법(Graident Descent)라는 최적화 알고리즘을 사용합니다. 그 기본 원리는 기울기가 낮은 쪽으로 연속적으로 이속시켜 값이 최소가 되는 점인 극값에 다다르게 하는 것이라고 볼 수 있습니다.</p>
<p>이를 위해 오차 E를 미분하는 과정이 필요한데, 모든 가중치가 오차에 영향을 미치고 있으므로 E를 각각의 가중치로 편미분해야 합니다. 다층 신경망은 각 계층이 연결되어 있어 Output에 가까운 미분 과정에서 사용되는 값이 Output에서 먼쪽의 미분과정에 사용됩니다. 따라서 Output과 가까운 쪽의 미분을 먼저 진행하게 되며 그렇기 때문에 Back Propagation이라고 불립니다.</p>
<ul>
<li><p>오차 함수
<img src="https://velog.velcdn.com/images/hye0n_w00/post/b7075878-ed84-4016-96de-f97b181464bd/image.png" alt=""></p>
<ul>
<li>의미: k번째 데이터에 대한 모델의 <strong>예측값(ŷ)</strong>과 실제 정답(y) 사이의 차이(오차)를 측정합니다. 이 오차 E_k를 최소화하는 것이 목표입니다.</li>
</ul>
</li>
<li><p>가중치 업데이트 규칙
<img src="https://velog.velcdn.com/images/hye0n_w00/post/5b4639f9-29f3-4d78-9a56-1ce9d1d77338/image.png" alt=""></p>
<ul>
<li><p>Δw_hj: 가중치 w_hj를 얼마나 변경할지를 나타내는 업데이트 양</p>
</li>
<li><p>η (에타): 학습률(learning rate). 얼마나 큰 폭으로 가중치를 수정할지 결정하는 값.</p>
</li>
<li><p>∂E_k / ∂w_hj: 오차 함수 E_k를 가중치 w_hj에 대해 편미분한 값. 즉, <strong>&quot;이 가중치를 조금 바꿨을 때 최종 오차가 얼마나 변하는가?&quot;</strong>를 나타내는 기울기입니다.</p>
</li>
<li><p>의미: 오차를 줄이는 방향(기울기의 반대 방향, -)으로 학습률(η)만큼 가중치를 업데이트하라는 뜻입니다.</p>
</li>
</ul>
</li>
</ul>
<h3 id="2-출력층output-layer-가중치-업데이트">2. 출력층(Output Layer) 가중치 업데이트</h3>
<p>출력층 뉴런 j와 은닉층 뉴런 h를 연결하는 가중치 w_hj를 업데이트하는 공식입니다.</p>
<ul>
<li><p>기울기 계산 
<img src="https://velog.velcdn.com/images/hye0n_w00/post/528fac15-e8ce-4d87-a01e-8870fd4a2e37/image.png" alt=""></p>
<ul>
<li><p>의미: w_hj가 변하면 → 은닉층의 출력(β_j)이 변하고 → 최종 예측값(ŷ)이 변하고 → 최종 오차(E_k)가 변하는 과정을 연쇄적으로 미분한 것입니다.</p>
</li>
<li><p>우리는 w_hj(은닉층 h → 출력층 j 가중치)가 최종 오차 E_k에 미치는 영향을 알고 싶습니다. 하지만 둘은 직접 연결되어 있지 않아 한 번에 계산할 수 없습니다. 그래서 <strong>연쇄 법칙(Chain Rule)</strong>을 이용해 중간 단계들을 연결하여 계산하는 것입니다.</p>
</li>
<li><p>∂βⱼ / ∂w_hj: <strong>가중치 w_hj</strong>가 변하면 → <strong>출력 뉴런 j의 입력 합 βⱼ</strong>는 얼마나 변할까?</p>
<ul>
<li>βⱼ는 은닉층의 출력 b_h와 가중치 w_hj의 곱(w_hj * b_h)을 포함하므로, 이 미분값은 <strong>b_h</strong>가 됩니다.</li>
</ul>
</li>
<li><p>∂ŷⱼᵏ / ∂βⱼ: <strong>입력 합 βⱼ</strong>가 변하면 → <strong>최종 예측값 ŷⱼᵏ</strong>는 얼마나 변할까?</p>
<ul>
<li>이는 활성화 함수(시그모이드)의 미분입니다. f&#39;(z) = f(z)(1-f(z)) 이므로, 이 값은 <strong>ŷⱼᵏ(1-ŷⱼᵏ)</strong>가 됩니다.</li>
</ul>
</li>
<li><p>∂Eₖ / ∂ŷⱼᵏ: <strong>예측값 ŷⱼᵏ</strong>이 변하면 → <strong>최종 오차 Eₖ</strong>는 얼마나 변할까?</p>
<ul>
<li>오차 함수 Eₖ = ½(yⱼᵏ - ŷⱼᵏ)²를 ŷⱼᵏ에 대해 미분하면 <strong>-(yⱼᵏ - ŷⱼᵏ)</strong>가 됩니다.</li>
</ul>
</li>
</ul>
</li>
<li><p>출력층의 오차항
위의 연쇄 법칙 중, 오차에 직접적으로 관련된 뒷부분 두 개를 곱해서 정리한 것입니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/7ca92bab-4d39-4e54-8f36-feac239a264e/image.png" alt=""></p>
<ul>
<li><p>(yⱼᵏ - ŷⱼᵏ): 실제 정답과 예측값의 차이. 즉, 얼마나 틀렸는가?</p>
</li>
<li><p>ŷⱼᵏ(1-ŷⱼᵏ): 시그모이드 미분값. 예측이 0.5에 가까울수록(가장 애매한 지점) 미분값이 커집니다. 즉, 뉴런이 얼마나 변화에 민감한 상태인가?</p>
</li>
<li><p>최종 가중치 업데이트
<img src="https://velog.velcdn.com/images/hye0n_w00/post/f1ae78ef-7bb4-43a8-b3f7-c8344db6551b/image.png" alt=""></p>
<ul>
<li>의미: 은닉층 h의 출력값(b_h)이 클수록, 그리고 출력층 j의 오차(g_j)가 클수록 가중치 w_hj를 더 많이 수정하라는 뜻입니다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="3-은닉층hidden-layer-가중치-업데이트">3. 은닉층(Hidden Layer) 가중치 업데이트</h3>
<p>이것이 바로 오차의 역전파입니다. 은닉 뉴런 h의 오차 eₕ는 자신이 신호를 보냈던 모든 출력 뉴런들의 오차(gⱼ)를 다시 돌려받아 계산합니다.</p>
<ul>
<li>오차항 계산
<img src="https://velog.velcdn.com/images/hye0n_w00/post/041ceb4d-f4dd-4c6d-b1e6-5527185f1f1c/image.png" alt=""></li>
</ul>
<ol>
<li><p>Σ w_hj g_j: 뉴런 h와 연결된 모든 출력 뉴런 j들로부터 각각의 오차(gⱼ)를 연결 가중치(w_hj)만큼 곱해서 전달받아 모두 더합니다. 이것이 바로 출력층의 오차(g)가 은닉층으로 거꾸로 전파(w_hj를 타고)되는 과정입니다.</p>
</li>
<li><p>bₕ(1-bₕ): 은닉 뉴런 h 자신이 얼마나 변화에 민감한 상태인지(시그모이드 미분값)를 곱해줍니다.</p>
</li>
</ol>
<h3 id="pseudo-code">Pseudo Code</h3>
<pre><code>for training_repeat
  for training_sets

        // 가중치로 net, out 계산 
        forward pass              

        //output 레이어에서 시작해 input + 1 레이어로
        for i = output layer -&gt; i = input layer + 1     
            for all nodes in layer i
                set delta

            //layer i와 i-1 사이에 있는 가중치 갱신
              for all weights between layer i and layer i-1  
                update weight    </code></pre><h1 id="54-글로벌-미니멈과-로컬-미니멈">5.4 글로벌 미니멈과 로컬 미니멈</h1>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/ff7eb8e5-300e-44c0-b330-3f5e0cf085b3/image.png" alt=""></p>
<h3 id="로컬-미니멈-문제란">로컬 미니멈 문제란?</h3>
<p>경사 하강법은 마치 눈을 가리고 산을 내려가는 것과 같습니다. 현재 위치에서 경사가 가장 낮은 방향으로 한 걸음씩 내려가다 보면 어느새 계곡의 가장 낮은 지점에 도착하게 됩니다.</p>
<p>문제는, 내가 도착한 계곡(로컬 미니멈)이 이 산 전체에서 가장 낮은 지점(글로벌 미니멈)이라는 보장이 없다는 것입니다. 더 깊은 계곡이 옆에 있는데도, 일단 한 계곡의 바닥에 도착하면 경사가 0이 되어 움직임을 멈추게 됩니다. 이것이 바로 <strong>&#39;로컬 미니멈 함정&#39;</strong>입니다.</p>
<ul>
<li>담금질 기법 (Simulated Annealing)    <ul>
<li>확률적으로 <strong>나쁜 선택(오르막)</strong>을 허용하여 현재의 계곡을 탈출</li>
</ul>
</li>
<li>확률적 경사 하강법 (SGD)<ul>
<li>기울기 계산에 노이즈를 추가하여 비틀거리며 함정에서 탈출</li>
</ul>
</li>
</ul>
<h1 id="55-기타-신경망">5.5 기타 신경망</h1>
<h3 id="rbf-radial-basis-function-신경망">RBF (Radial Basis Function) 신경망</h3>
<ul>
<li><p><strong>&quot;중심점(Center)으로부터의 거리가 가까울수록 크게 활성화된다&quot;</strong>는 개념을 이용하는 신경망입니다. 주로 함수 근사(function approximation)나 분류 문제에 사용됩니다.</p>
</li>
<li><p>작동 원리:</p>
<ol>
<li>은닉층(Hidden Layer): 각 뉴런이 하나의 &#39;중심점&#39; 또는 &#39;프로토타입&#39; 데이터 포인트를 가집니다. 활성화 함수로 가우시안 함수(종 모양 곡선) 같은 <strong>방사 기저 함수(RBF)</strong>를 사용합니다. 입력 데이터가 특정 뉴런의 중심점과 가까우면 해당 뉴런은 강하게 활성화(높은 값 출력)되고, 멀어지면 약하게 활성화됩니다.</li>
<li>출력층(Output Layer): 은닉층 뉴런들의 활성화 값들을 선형적으로 조합하여 최종 결과를 예측합니다.</li>
</ol>
</li>
</ul>
<h3 id="art-adaptive-resonance-theory-신경망">ART (Adaptive Resonance Theory) 신경망</h3>
<ul>
<li><p>&quot;새로운 것을 배우면서 기존의 지식을 잊지 않는&quot; 인간의 학습 방식을 모방한 비지도 학습(Unsupervised Learning) 클러스터링 알고리즘입니다.</p>
</li>
<li><p>작동 원리:</p>
<ol>
<li><p>입력 데이터가 들어오면, 기존에 생성된 클러스터(뉴런)들과의 유사도를 비교합니다.</p>
</li>
<li><p>만약 특정 클러스터와 충분히 유사하다면(설정된 경계 파라미터(Vigilance Parameter) 기준을 넘으면), 해당 클러스터에 데이터를 포함시키고 클러스터 정보를 업데이트합니다.</p>
</li>
<li><p>만약 어떤 기존 클러스터와도 충분히 유사하지 않다면, 새로운 클러스터를 생성하여 데이터를 할당합니다.</p>
</li>
</ol>
</li>
</ul>
<h3 id="som-self-organizing-map-신경망">SOM (Self-Organizing Map) 신경망</h3>
<ul>
<li><p>고차원의 데이터를 저차원(주로 2차원)의 격자(Grid) 위에 지도를 만들 듯 시각화하는 비지도 학습 알고리즘입니다. </p>
</li>
<li><p>작동 원리:</p>
<ol>
<li>입력 데이터와 가장 유사한 가중치를 가진 뉴런(노드)을 2차원 격자 위에서 찾습니다. 이 뉴런을 <strong>BMU(Best Matching Unit)</strong>라고 합니다.</li>
<li>BMU의 가중치를 입력 데이터와 더 비슷해지도록 업데이트합니다.</li>
<li>가장 중요한 특징으로, BMU뿐만 아니라 그 주변의 이웃 뉴런들도 함께, 하지만 더 약한 강도로 업데이트합니다.</li>
</ol>
</li>
</ul>
<h3 id="중첩된-상호연관-신경망-hopfield-network">중첩된 상호연관 신경망 (Hopfield Network)</h3>
<ul>
<li><p><strong>연관 메모리(Associative Memory)</strong>처럼 동작하는 순환 신경망(RNN)의 한 종류입니다. 뇌가 불완전한 정보로부터 전체 정보를 기억해내는 방식을 모방합니다.</p>
</li>
<li><p>작동 원리:</p>
<ol>
<li>모든 뉴런이 다른 모든 뉴런과 상호 연결된 구조를 가집니다.</li>
<li>네트워크에 특정 패턴(메모리)들을 저장하면, 이는 네트워크의 안정된 상태(에너지 함수의 최저점)가 됩니다.</li>
<li>노이즈가 섞이거나 일부가 손상된 불완전한 패턴을 입력으로 주면, 뉴런들의 상태가 상호작용을 통해 동적으로 변하다가 가장 가까운(유사한) 원본 메모리 상태로 수렴합니다.</li>
</ol>
</li>
</ul>
<h3 id="엘만-네트워크-elman-network">엘만 네트워크 (Elman Network)</h3>
<ul>
<li><p>순환 신경망(RNN)의 초기 형태로, 단기 기억을 통해 순서가 있는 데이터를 처리합니다.</p>
</li>
<li><p>작동 원리:</p>
<ol>
<li>기본적인 다층 퍼셉트론 구조에 특별한 연결이 추가됩니다.</li>
<li>은닉층의 이전 타임스텝(t-1)에서의 출력값을 <strong>컨텍스트 유닛(Context Unit)</strong>이라는 곳에 복사해 두었다가, 다음 타임스텝(t)에서 입력 데이터와 함께 은닉층의 입력으로 다시 사용합니다.</li>
<li>이 피드백 루프를 통해 네트워크는 바로 직전의 상태를 기억하고 현재의 예측에 반영할 수 있습니다.</li>
</ol>
</li>
</ul>
<h3 id="볼츠만-머신-boltzmann-machine">볼츠만 머신 (Boltzmann Machine)</h3>
<ul>
<li><p>통계 물리학의 개념을 도입한 확률적인(Stochastic) 생성 모델입니다. 네트워크의 상태가 확률적으로 결정됩니다.</p>
</li>
<li><p>작동 원리:</p>
<ol>
<li>뉴런들이 &#39;켜짐(1)&#39; 또는 &#39;꺼짐(0)&#39; 상태를 확률적으로 가집니다.</li>
<li>네트워크의 전체 상태에 대한 &#39;에너지&#39; 함수를 정의하고, 에너지가 낮을수록 해당 상태가 나타날 확률이 높도록 설계됩니다.</li>
<li>학습을 통해 데이터의 확률 분포 자체를 학습하려고 시도합니다</li>
</ol>
</li>
</ul>
<h4 id="추가">추가</h4>
<ul>
<li>RNN은 시퀀스의 각 요소를 처리할 때마다, 예측 결과와 함께 <strong>은닉 상태(Hidden State)</strong>라는 &#39;메모리&#39;를 출력합니다. 이 은닉 상태는 다음 요소가 입력될 때, 새로운 입력 데이터와 함께 다시 네트워크로 들어가 현재까지의 문맥 정보를 전달하는 역할을 합니다.</li>
</ul>
<h1 id="56-딥러닝">5.6 딥러닝</h1>
<h3 id="dbn-deep-belief-network-심층-신뢰-신경망">DBN (Deep Belief Network, 심층 신뢰 신경망)</h3>
<p>&quot;깊은 신경망을 어떻게 똑똑하게 초기화할까?&quot; 라는 문제를 해결한, 딥러닝 초기의 획기적인 모델입니다.</p>
<ul>
<li><p>핵심 아이디어: 전체 신경망을 한 번에 학습시키지 않고, 한 층씩 차근차근, 정답 없이(비지도 학습) 미리 훈련시켜 가중치를 좋은 출발점에 놓는 것입니다.</p>
</li>
<li><p>구조: <strong>제한된 볼츠만 머신(RBM)</strong>을 여러 개 쌓아 올린 형태입니다.</p>
</li>
<li><p>학습 과정 (2단계):</p>
<ol>
<li><p>사전학습 (Pre-training): RBM을 한 층씩 쌓아 올리며 데이터의 저수준 특징부터 고수준 특징까지 비지도 방식으로 학습합니다. 이 과정을 통해 가중치들이 데이터의 구조를 이미 잘 파악한 &quot;똑똑한&quot; 초기값을 갖게 됩니다.</p>
</li>
<li><p>파인튜닝 (Fine-tuning): 사전학습이 끝난 전체 네트워크의 맨 위에 출력층을 추가하고, <strong>정답이 있는 데이터(지도 학습)</strong>와 역전파 알고리즘을 이용해 전체 가중치를 목표에 맞게 미세 조정합니다.</p>
</li>
</ol>
</li>
</ul>
<p>&#39;비지도 사전학습 + 지도 파인튜닝&#39; 전략을 통해, 과거의 가장 큰 난제였던 기울기 소실(Vanishing Gradient) 문제를 해결하고 깊은 신경망의 학습을 가능하게 한 역사적으로 매우 중요한 모델입니다.</p>
<h2 id="rnn-recurrent-neural-network-순환-신경망">RNN (Recurrent Neural Network, 순환 신경망)</h2>
<p>&quot;순서가 있는 데이터&quot; (예: 문장, 시계열 데이터)를 처리하기 위해 설계된, <strong>&#39;기억&#39;</strong>을 가진 신경망입니다.</p>
<ul>
<li><p>핵심 아이디어: 네트워크 내부에 <strong>순환하는 루프(Loop)</strong>를 만들어, 이전 단계의 정보를 현재 단계의 예측에 반영합니다.</p>
</li>
<li><p>구조: 각 시점의 예측 결과를 계산할 때, 현재의 입력 데이터뿐만 아니라 이전 시점의 정보를 요약한 <strong>은닉 상태(Hidden State)</strong>를 함께 입력으로 사용합니다. 이 은닉 상태가 바로 RNN의 &#39;메모리&#39; 역할을 합니다.</p>
</li>
<li><p>작동 방식:</p>
<ol>
<li>첫 번째 단어(입력)를 처리하고 결과와 함께 <strong>첫 번째 기억(은닉 상태)</strong>을 만듭니다.</li>
<li>두 번째 단어를 처리할 때는, 두 번째 단어와 첫 번째 기억을 함께 고려하여 결과와 두 번째 기억을 만듭니다.</li>
<li>이 과정을 시퀀스의 끝까지 반복하며, 과거의 정보를 계속 누적하여 현재의 예측에 활용합니다.</li>
</ol>
</li>
</ul>
<p><strong>&#39;메모리(은닉 상태)&#39;</strong>를 통해 과거의 정보를 현재로 전달하는 순환 구조를 가진 신경망으로, 문장 번역, 음성 인식 등 순차적인 데이터를 다루는 데 필수적입니다. (단, 긴 시퀀스의 기억을 잘 못하는 단점이 있어 이를 보완한 LSTM, GRU가 널리 쓰입니다.)</p>
<h2 id="cnn-convolutional-neural-network-합성곱-신경망">CNN (Convolutional Neural Network, 합성곱 신경망)</h2>
<p>이미지 인식에 혁명을 가져온, &#39;가중치 공유&#39; 개념을 사용하는 시각 정보 처리에 특화된 신경망입니다.</p>
<ul>
<li><p>핵심 아이디어: 이미지의 특정 패턴(예: 고양이 귀)은 이미지의 어느 위치에 있든 같은 방법으로 찾을 수 있다는 점에 착안, 하나의 필터(Filter)를 이미지 전체에 공유하여 사용합니다.</p>
</li>
<li><p>구조: [합성곱 계층 → 풀링 계층] 구조를 여러 겹으로 쌓아 만듭니다.</p>
<ul>
<li><p>합성곱(Convolution) 계층: 특정 패턴(선, 모서리, 질감 등)을 감지하는 작은 <strong>필터(커널)</strong>가 이미지 위를 훑고 지나가며 <strong>특성 맵(Feature Map)</strong>을 만듭니다. 이 필터의 가중치가 이미지 전체에서 공유됩니다.</p>
</li>
<li><p>풀링(Pooling) 계층: 특성 맵의 크기를 줄여(Downsampling) 계산량을 줄이고, 위치 변화에 좀 더 둔감한(강건한) 특징을 추출합니다.</p>
</li>
</ul>
</li>
<li><p>작동 방식: 초기 계층에서는 선이나 모서리 같은 단순한 특징을, 깊은 계층으로 갈수록 눈, 코, 입과 같은 더 복잡하고 추상적인 특징을 학습하여 최종적으로 이미지를 분류합니다.</p>
</li>
</ul>
<p><strong>&#39;필터(커널)&#39;</strong>를 이미지 전체에 <strong>공유(가중치 공유)</strong>하여, 위치에 상관없이 효율적으로 시각적 패턴을 찾아내는 신경망입니다. 파라미터 수를 획기적으로 줄이면서 이미지 인식 성능을 극대화했습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Machine Learning(04.의사결정 트리)]]></title>
            <link>https://velog.io/@hye0n_w00/Machine-Learning04.%EC%9D%98%EC%82%AC%EA%B2%B0%EC%A0%95-%ED%8A%B8%EB%A6%AC</link>
            <guid>https://velog.io/@hye0n_w00/Machine-Learning04.%EC%9D%98%EC%82%AC%EA%B2%B0%EC%A0%95-%ED%8A%B8%EB%A6%AC</guid>
            <pubDate>Mon, 14 Jul 2025 06:33:59 GMT</pubDate>
            <description><![CDATA[<h1 id="41-기본-프로세스">4.1 기본 프로세스</h1>
<h3 id="의사결정-트리-기본-알고리즘">의사결정 트리 기본 알고리즘</h3>
<p>입력:</p>
<ul>
<li>훈련 세트 D = {(x₁, y₁), (x₂, y₂), ..., (xₘ, yₘ)};</li>
<li>속성 집합 A = {a₁, a₂, ..., a_d}</li>
</ul>
<p>과정: 
함수 TreeGenerate(D, A)
1: node를 생성;</p>
<p>2: if D의 샘플이 모두 클래스 C에 속할 경우 then =&gt; 완벽히 분류</p>
<p>  3: node를 C 클래스의 단말 노드로 표기 후 return;</p>
<p>4: end if</p>
<p>5: if A = ∅ OR D의 샘플이 A에서 동일할 경우 then</p>
<p>  6: node를 터미널 노드로 표기하고, 해당 클래스를 D에서 샘플 중 수가 가장 많은 클래스로 표기 후 return; =&gt; 더이상 나눌 수 없는경우</p>
<p>7: end if</p>
<p>8: A에서 최적의 분할 속성 a*를 선택; =&gt; 최적의 속성 선택</p>
<p>9: for a<em>의 매 값 a</em>ᵛ do</p>
<p> 10: node를 위해 하나의 가지를 생성; D에서 a<em>의 속성값이 a</em>ᵛ인 샘플을 D_v라 할 때</p>
<p> 11: if D_v = 0 then</p>
<p>  12: 가지를 단말 노드로 표기하고, 클래스를 D에서 샘플 수가 가장 많은 클래스로 표기</p>
<p> 13: else</p>
<p>  14: TreeGenerate(D_v, A \ {a*})가 반환한 노드로 가지를 표기</p>
<p> 15: end if</p>
<p>16: end for</p>
<h3 id="알고리즘-설명">알고리즘 설명</h3>
<blockquote>
</blockquote>
<p>이 알고리즘은 <strong>재귀(Recursion)</strong>를 이용해 의사결정 트리를 만드는 과정을 설명합니다. &quot;데이터를 가장 잘 나눌 수 있는 질문은 무엇인가?&quot;를 반복적으로 찾아가며 나무를 성장시키는 분할 정복(Divide and Conquer) 전략을 사용합니다.</p>
<blockquote>
</blockquote>
<h4 id="1-재귀의-종료-조건-나무가-성장을-멈추는-경우">1. 재귀의 종료 조건: 나무가 성장을 멈추는 경우</h4>
<p>더 이상 데이터를 나누지 않고, 현재 노드를 최종 결정(답변)을 내리는 <strong>단말 노드(Leaf Node)</strong>로 만드는 세 가지 조건이 있습니다.</p>
<blockquote>
</blockquote>
<ul>
<li>조건 1 (완벽하게 분류됨): 현재 노드에 모인 데이터들이 모두 같은 클래스일 때. 이미 분류가 끝났으므로 더 이상 질문할 필요가 없습니다.<blockquote>
</blockquote>
</li>
<li>조건 2 (더 이상 나눌 수 없음): 질문할 속성이 다 떨어졌거나, 남은 데이터들의 속성값이 모두 똑같아 나눌 기준이 없을 때. 어쩔 수 없이 멈추고, 현재 모인 데이터 중 <strong>가장 많은 쪽(다수결)</strong>을 예측 결과로 정합니다.<blockquote>
</blockquote>
</li>
<li>조건 3 (분할 후 데이터 없음): 최적의 속성으로 데이터를 나눴는데, 특정 가지에 해당하는 데이터가 하나도 없을 때. 이 경우에도 나누기 전 데이터의 다수결을 따라 예측 결과를 정합니다.<blockquote>
</blockquote>
<h4 id="2-재귀-단계-나무가-자라는-과정">2. 재귀 단계: 나무가 자라는 과정</h4>
위의 멈춤 조건에 해당하지 않으면, 다음과 같이 데이터를 나누어 트리를 성장시킵니다.<blockquote>
</blockquote>
</li>
<li>최적의 속성 선택 (가장 중요한 단계): 현재 데이터 그룹을 가장 잘 나눌 수 있는 <strong>하나의 질문(최적의 분할 속성 a*)</strong>을 선택합니다. 예를 들어 &#39;색상&#39;, &#39;모양&#39;, &#39;크기&#39; 중 &#39;색상&#39;으로 나누는 것이 가장 효과적이라고 판단하는 것입니다.<blockquote>
</blockquote>
</li>
<li>데이터 분할 및 재귀 호출:<ol>
<li>선택된 속성(&#39;색상&#39;)의 각 값(&#39;빨강&#39;, &#39;파랑&#39; 등)에 대해 새로운 가지를 만듭니다.</li>
<li>&#39;빨강&#39; 가지에는 빨간색 데이터들만 모으고, &#39;파랑&#39; 가지에는 파란색 데이터들만 모읍니다.</li>
<li>나누어진 각 데이터 그룹에 대해, 다시 TreeGenerate 함수를 호출하여 이 과정을 처음부터 반복합니다.</li>
</ol>
</li>
</ul>
<h1 id="42-분할-선택">4.2 분할 선택</h1>
<h2 id="421-정보-이득">4.2.1 정보 이득</h2>
<h3 id="1-정보-엔트로피-information-entropy---불순도-측정하기">1. 정보 엔트로피 (Information Entropy) - 불순도 측정하기</h3>
<p>먼저 데이터가 얼마나 &quot;지저분하게&quot; 섞여 있는지, 즉 불순도(impurity) 또는 <strong>불확실성(uncertainty)</strong>을 측정해야 합니다. 이 측정 도구가 바로 정보 엔트로피입니다.</p>
<ul>
<li>엔트로피가 높다: 여러 클래스가 비슷하게 섞여 있어 예측하기 어렵다 (불순도 높음). (예: 예/아니오가 50:50으로 섞인 경우)</li>
<li>엔트로피가 낮다: 한쪽 클래스가 대부분이라 예측하기 쉽다 (순도 높음). (예: 99%가 &#39;예&#39;인 경우)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/4a661a21-e93c-4df0-abf8-361ea27ce239/image.png" alt=""></p>
<h3 id="2-정보-이득-information-gain---어떤-질문이-가장-좋은가">2. 정보 이득 (Information Gain) - 어떤 질문이 가장 좋은가?</h3>
<p>정보 이득은 특정 속성(질문)으로 데이터를 나누었을 때, 엔트로피(불순도)가 얼마나 많이 줄어들었는지를 나타내는 값입니다. 당연히 정보 이득이 가장 큰 속성이 가장 좋은 질문(분할 기준)이 됩니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/91f96f59-f717-4ea8-a2bd-ae100bae14d7/image.png" alt=""></p>
<h3 id="3-최적의-분할-속성-a-선택">3. 최적의 분할 속성 a* 선택</h3>
<p>의사결정 트리 알고리즘 8단계의 최적의 분할 속성 a<em>를 선택하는 과정은 바로 이 정보 이득을 이용합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/e443ec4f-f5b4-46ed-8d7f-6f709cccee3b/image.png" alt="">
이 식은 &quot;모든 속성 a에 대해 정보 이득 Gain(D, a)을 각각 계산하고, 그 값이 *</em>최대(max)*<em>가 되게 하는 속성 a를 a</em>로 선택하라&quot;는 의미입니다.</p>
<h2 id="422-정보-이득율">4.2.2 정보 이득율</h2>
<h3 id="1-정보-이득의-문제점">1. 정보 이득의 문제점</h3>
<p>정보 이득은 값(종류)이 많은 속성을 편애하는 경향이 있습니다.</p>
<p>예를 들어 &#39;학번&#39;이라는 속성이 있다고 해봅시다. 학생마다 학번이 다르므로, 이 속성으로 데이터를 나누면 모든 그룹의 순도가 100%가 되어 정보 이득이 매우 높게 계산됩니다. 하지만 &#39;학번&#39;은 전혀 유용한 분류 기준이 아닙니다.</p>
<h3 id="2-해결책-정보-이득률-gain-ratio">2. 해결책: 정보 이득률 (Gain Ratio)</h3>
<p>정보 이득률은 이러한 편향을 바로잡기 위해 패널티를 도입합니다.</p>
<h4 id="고유값-intrinsic-value-iva">고유값 (Intrinsic Value, IV(a))</h4>
<p>이 패널티의 역할을 하는 것이 바로 <strong>고유값(IV)</strong>입니다. 고유값은 속성 자체가 얼마나 다양한 값을 갖는지, 즉 속성의 &quot;복잡성&quot;을 측정합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/5d8945ce-e2bb-483b-b2a0-8ca2cc255ed1/image.png" alt=""></p>
<ul>
<li>이 식은 정보 엔트로피 식과 형태가 똑같습니다. 단지 클래스 비율 대신, 속성값의 비율을 사용합니다.</li>
<li>속성값의 종류가 많을수록 (예: &#39;학번&#39;), 고유값(IV)은 커집니다.</li>
<li>속성값의 종류가 적을수록 (예: &#39;성별&#39;), 고유값(IV)은 작아집니다.</li>
</ul>
<h4 id="정보-이득률-gain-ratio-공식">정보 이득률 (Gain Ratio) 공식</h4>
<p>정보 이득률은 정보 이득을 이 고유값으로 나누어 계산합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/dcaee3ad-9272-4127-aa1f-92a70563d3c1/image.png" alt=""></p>
<ul>
<li>작동 원리: &#39;학번&#39;처럼 값의 종류가 많은 속성은 정보 이득(Gain)이 높게 나오더라도, 패널티인 고유값(IV) 역시 매우 커집니다. 결국 분모가 커져서 전체 정보 이득률(Gain Ratio) 값은 낮아지게 됩니다.</li>
</ul>
<h2 id="423-지니계수">4.2.3 지니계수</h2>
<p>지니 계수(Gini Index)는 데이터의 <strong>불순도(Impurity)</strong>를 측정하는 지표로, CART 의사결정 트리에서 분할 속성을 선택하는 기준으로 사용됩니다.</p>
<p>지니 계수는 <strong>&quot;데이터 집합에서 무작위로 두 개의 샘플을 뽑았을 때, 두 샘플이 서로 다른 클래스에 속할 확률&quot;</strong>을 의미합니다. 이 값이 낮을수록 데이터의 순도가 높다고 판단합니다.</p>
<h3 id="지니-값-gini-value">지니 값 (Gini Value)</h3>
<p>한 데이터 집합 D의 불순도를 계산하는 식입니다.</p>
<p>Gini(D) 공식
<img src="https://velog.velcdn.com/images/hye0n_w00/post/e5754791-f351-48df-9174-2105ffaa4e08/image.png" alt="">
&quot;1 - (같은 클래스를 두 번 연속 뽑을 확률)&quot;을 의미하며, 이것이 바로 &quot;다른 클래스를 뽑을 확률&quot;이 됩니다.</p>
<h3 id="지니-지수-gini-index">지니 지수 (Gini Index)</h3>
<p>속성 a로 데이터를 분할했을 때의 불순도를 나타내는 지표입니다. 정보 이득과 달리, 지니 지수는 가장 작은 값을 갖는 속성을 최적의 분할 기준으로 선택합니다.</p>
<p>Gini_index(D, a) 공식
<img src="https://velog.velcdn.com/images/hye0n_w00/post/ee282e27-9eb2-49bd-b9f6-412df7ccf56d/image.png" alt=""></p>
<h1 id="43-가지치기-pruning-과적합-방지-전략">4.3 가지치기 (Pruning): 과적합 방지 전략</h1>
<p>의사결정 트리를 아무런 제한 없이 끝까지 성장시키면, 훈련 데이터의 아주 사소한 특징이나 노이즈까지 모두 학습하여 과적합이 발생합니다. 이는 새로운 데이터에 대한 예측 성능을 떨어뜨립니다.</p>
<p>가지치기는 이렇게 불필요하게 복잡해진 나무의 가지를 잘라내어 모델을 더 단순하고 일반적인 형태로 만드는 과정입니다. 마치 정원사가 무성한 나뭇가지를 쳐내어 나무를 더 건강하게 만드는 것과 같습니다.</p>
<h3 id="1-사전-가지치기-pre-pruning">1. 사전 가지치기 (Pre-pruning)</h3>
<ul>
<li><p>개념: 나무가 완전히 성장하기 전에, 특정 조건에 도달하면 성장을 미리 멈추는 방식입니다.</p>
</li>
<li><p>동작 방식: 트리의 노드를 분할하기 전에, 분할의 이득을 평가합니다.</p>
<ul>
<li>예를 들어, 현재 노드를 분할했을 때 검증 세트(Validation Set)에서의 정확도가 향상되지 않으면 분할을 멈추고 해당 노드를 리프 노드(단말 노드)로 만듭니다.</li>
</ul>
</li>
<li><p>장점:
트리를 끝까지 만들지 않으므로 학습 속도가 빠릅니다.</p>
</li>
<li><p>단점:
&#39;탐욕적인(Greedy)&#39; 접근법입니다. 지금 당장은 분할의 이득이 없어 보여도, 한 단계 더 깊이 분할하면 성능이 크게 향상될 수 있는 가능성을 놓칠 수 있습니다. 즉, 섣부른 판단으로 나무의 성장을 너무 일찍 멈출 위험이 있습니다.</p>
</li>
</ul>
<h3 id="2-사후-가지치기-post-pruning">2. 사후 가지치기 (Post-pruning)</h3>
<ul>
<li><p>개념: 일단 트리를 최대한 끝까지 성장시킨 후, 불필요한 가지를 아래에서부터 위로 올라오며 잘라내는 방식입니다.</p>
</li>
<li><p>동작 방식:</p>
<ol>
<li>가장 아래쪽의 노드부터 검토하여, 특정 노드 아래의 하위 트리 전체를 하나의 리프 노드로 대체했을 때 검증 세트에서의 정확도가 향상되는지 확인합니다.</li>
<li>정확도가 향상되거나 거의 유지된다면, 과감하게 해당 하위 트리를 잘라내고 리프 노드로 만듭니다.</li>
<li>이 과정을 점차 위쪽 노드로 올라오며 반복합니다.</li>
</ol>
</li>
<li><p>장점:
모든 가능한 분할을 고려한 뒤에 가지치기를 하므로, 일반적으로 사전 가지치기보다 더 좋은 성능의 모델을 만듭니다.</p>
</li>
<li><p>단점:
일단 트리를 끝까지 만들어야 하므로 학습 시간이 오래 걸리고 계산량이 많습니다.</p>
<h1 id="44-연속값과-결측값">4.4 연속값과 결측값</h1>
</li>
</ul>
<h2 id="441-연속값">4.4.1 연속값</h2>
<ul>
<li>처리 문제 상황
&#39;밀도&#39; 값은 0.243, 0.245, 0.351 등 무수히 많을 수 있습니다. 이 모든 값에 대해 가지를 만들 수는 없습니다.</li>
<li>해결책: 이분법 (Bi-partition)
C4.5 알고리즘에서 사용하는 방법으로, 연속값을 <strong>하나의 분할점(cut-off point) t</strong>를 기준으로 두 개의 구간으로 나누는 것입니다. (예: &quot;밀도 ≤ t인가?&quot; 라는 이진 질문으로 바꿈)</li>
</ul>
<h3 id="어떻게-최적의-분할점-t를-찾을까">어떻게 최적의 분할점 t를 찾을까?</h3>
<h4 id="1단계-모든-후보-분할점-찾기">1단계: 모든 후보 분할점 찾기</h4>
<ul>
<li>해당 속성(예: &#39;밀도&#39;)의 모든 값들을 크기 순으로 정렬합니다. {a¹, a², ..., aⁿ}</li>
<li>인접한 두 값의 중간 지점들을 모두 후보 분할점으로 정합니다.</li>
<li>후보 분할점 집합 Tₐ 공식:
<img src="https://velog.velcdn.com/images/hye0n_w00/post/b8a30b28-2461-4cc1-8ab3-983c96f05810/image.png" alt=""></li>
</ul>
<h4 id="2단계-정보-이득이-최대가-되는-분할점-선택">2단계: 정보 이득이 최대가 되는 분할점 선택</h4>
<ul>
<li>각각의 후보 분할점 t에 대해, 데이터 D를 ≤ t인 그룹과 &gt; t인 그룹으로 나누고 정보 이득(Information Gain)을 계산합니다.</li>
<li>특정 분할점 t에 대한 정보 이득 공식
<img src="https://velog.velcdn.com/images/hye0n_w00/post/9279991e-c8b7-4796-af2a-a058bdf60613/image.png" alt=""></li>
<li>계산된 정보 이득 값들 중 가장 큰 값을 해당 연속 속성 a의 최종 정보 이득으로 선택합니다.</li>
<li>연속 속성 a의 최종 정보 이득 공식
<img src="https://velog.velcdn.com/images/hye0n_w00/post/1ad15ca1-8bb9-4185-933b-d47a73f1bd62/image.png" alt=""></li>
</ul>
<h2 id="442-결측값-처리">4.4.2 결측값 처리</h2>
<h3 id="문제-1-속성값이-결측된-상황에서-어떻게-분할-속성을-선택할-것인가">문제 1: 속성값이 결측된 상황에서 어떻게 분할 속성을 선택할 것인가?</h3>
<ul>
<li>아이디어: 특정 속성에 결측값이 없는 데이터만 가지고 정보 이득을 계산한 뒤, 전체 데이터에서 해당 속성값이 존재하는 데이터의 비율을 곱하여 최종 정보 이득을 구합니다.</li>
</ul>
<p>1단계: 데이터셋 분리</p>
<ul>
<li>D: 현재 노드의 전체 훈련 데이터셋</li>
<li>D̃: 전체 D 중에서, 우리가 지금 평가하려는 속성 a에 결측값이 없는 데이터들의 부분집합.</li>
</ul>
<p>2단계: 가중치(비율) ρ 계산</p>
<ul>
<li>ρ (로): 전체 데이터 중 속성 a의 값이 실제로 존재하는 데이터의 비율입니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/4453cce2-9d3a-4b5b-aa6e-66b2f61432fa/image.png" alt=""></li>
</ul>
<p>3단계: 정보 이득 계산</p>
<ul>
<li>먼저, 결측값이 없는 데이터 D̃에 대해서만 표준 정보 이득 공식을 사용하여 Gain(D̃, a)를 계산합니다.</li>
<li>최종적으로, 위에서 구한 비율 ρ를 곱하여 가중치를 부여합니다.</li>
</ul>
<p>결측값을 고려한 정보 이득 공식
<img src="https://velog.velcdn.com/images/hye0n_w00/post/13e77183-c5d3-45aa-833a-855499accfef/image.png" alt=""></p>
<h1 id="45-다변량-의사결정-트리">4.5 다변량 의사결정 트리</h1>
<h3 id="기존-의사결정-트리와의-차이점">기존 의사결정 트리와의 차이점</h3>
<ul>
<li>일반 의사결정 트리 (Univariate): 각 노드에서 단 하나의 속성에 대한 질문을 합니다. (예: &quot;색깔이 빨간색인가?&quot; 또는 &quot;밀도가 0.6보다 큰가?&quot;)<ul>
<li>이로 인해 만들어지는 결정 경계는 항상 축에 평행한(axis-parallel) 직선, 즉 계단 모양이 됩니다.</li>
</ul>
</li>
<li>다변량 의사결정 트리 (Multivariate): 각 노드에서 여러 속성의 선형 결합에 대한 질문을 합니다. (예: &quot;(0.7 x 밀도) + (0.3 x 당도)가 0.8보다 큰가?&quot;)<ul>
<li>이로 인해 만들어지는 결정 경계는 축에 평행하지 않은 사선(oblique) 형태가 될 수 있습니다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Machine Learning(03.선형 모델)]]></title>
            <link>https://velog.io/@hye0n_w00/Machine-Learning03.%EC%84%A0%ED%98%95-%EB%AA%A8%EB%8D%B8</link>
            <guid>https://velog.io/@hye0n_w00/Machine-Learning03.%EC%84%A0%ED%98%95-%EB%AA%A8%EB%8D%B8</guid>
            <pubDate>Mon, 14 Jul 2025 00:45:33 GMT</pubDate>
            <description><![CDATA[<h1 id="31-선형-모델-linear-model">3.1 선형 모델 (Linear Model)</h1>
<p>선형 모델은 입력 데이터의 특성(feature)들에 가중치(weight)를 곱한 값들을 모두 더해 예측 결과를 만들어내는 가장 단순하고 직관적인 모델입니다. 특성과 예측 결과 사이에 직선적인 관계가 있다고 가정하죠.
ex) f잘 익은 수박(x) = 0.2색 + 0.5x꼭지모양 + 0.3x소리 +1</p>
<ul>
<li><p>기본 식:
<img src="https://velog.velcdn.com/images/hye0n_w00/post/48733a5a-5473-4e89-a31f-e6c41e6fcb68/image.png" alt=""></p>
</li>
<li><p>벡터 식:
<img src="https://velog.velcdn.com/images/hye0n_w00/post/b60dcec5-0d6d-4e80-8482-d1534d50eba7/image.png" alt=""></p>
</li>
<li><p>비선형 모델 (Non-linear Model)
현실 세계의 복잡한 데이터는 단순한 직선 관계만으로 설명하기 어렵습니다. 비선형 모델은 이러한 복잡한 관계를 학습하기 위해 선형 모델을 기반으로 확장된 개념을 사용합니다.</p>
<ul>
<li>선형 모델을 여러 개 쌓거나(층) 데이터를 더 높은 차원으로 보내 비선형적인 관계를 표현할 수 있도록 만듭니다.</li>
</ul>
</li>
</ul>
<h1 id="32-선형-회귀">3.2 선형 회귀</h1>
<h3 id="선형-회귀의-목표와-기본-모델">선형 회귀의 목표와 기본 모델</h3>
<p>선형 회귀의 목표는 데이터의 특성(feature)과 결과(target) 사이의 선형(직선) 관계를 가장 잘 나타내는 모델을 찾는 것입니다.</p>
<p>기본 가정: 입력 특성 x와 결과 y 사이에는 y ≈ wx + b 와 같은 직선 관계가 존재한다.</p>
<h3 id="2-비용-함수와-최소제곱법">2. 비용 함수와 최소제곱법</h3>
<p>가장 좋은 직선, 즉 최적의 w와 b를 찾기 위해, 모델의 예측값과 실제 정답의 차이인 <strong>오차(Error)</strong>를 측정하고 이를 최소화해야 합니다.</p>
<ul>
<li>비용 함수 (Cost Function): 오차를 측정하는 기준으로, 회귀 문제에서는 주로 <strong>평균제곱 오차(Mean Squared Error, MSE)</strong>를 사용합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/57273985-4bda-477e-9e56-49bc10d3f50a/image.png" alt=""></li>
<li>최소제곱법 (Least Squares Method): 위 비용 함수(오차의 제곱 합)를 최소화하는 w와 b를 찾는 방법입니다. 수학적으로는 비용 함수의 기울기가 0이 되는 지점을 찾는 것과 같습니다.</li>
</ul>
<h3 id="평균제곱-오차를-최소화-하는것의-기하학적-의미">평균제곱 오차를 최소화 하는것의 기하학적 의미</h3>
<ul>
<li>유클리드 거리 (Euclidean distance): 우리가 흔히 아는 두 점 사이의 직선거리입니다.</li>
<li>MSE 최소화: 2차원 그래프 상에 데이터 점(yᵢ)들이 흩어져 있을 때, 우리가 그린 직선(f(xᵢ) = wxᵢ + b)까지의 수직 거리들의 제곱의 합이 최소가 되는 w(기울기)와 b(y절편)를 찾는 것과 같습니다.</li>
</ul>
<h3 id="최적의-해-구하기-closed-form-solution">최적의 해 구하기 (Closed-form Solution)</h3>
<h4 id="ew-b--σyᵢ---wxᵢ---b²">E(w, b) = Σ(yᵢ - wxᵢ - b)²</h4>
<p>w와 b의 해를 찾는 것은 위의 식을 최소화 하는 과정 입니다.</p>
<p>비용 함수를 각 파라미터(w, b)에 대해 <strong>편미분(partial differentiation)</strong>한 값이 0이 되는 지점을 연립방정식으로 풀면, 최적의 해를 구하는 공식을 유도할 수 있습니다. 이를 <strong>닫힌 해(closed-form solution)</strong>라고 합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/3cdbbe3a-7c90-4ed4-ad63-7016f80d902a/image.png" alt=""></p>
<p>식 B를 이용해서 아래 식 구하기
<img src="https://velog.velcdn.com/images/hye0n_w00/post/9b482a67-631c-4abf-a7d6-fdbbe4ad00ce/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/dcd737b9-ae97-410e-a1b2-835c52f5cd5a/image.png" alt=""></p>
<ul>
<li>비용 함수를 w에 대해 편미분
<img src="https://velog.velcdn.com/images/hye0n_w00/post/feba2198-7dc5-49ab-9b29-f8d0771e1e0e/image.png" alt=""></li>
<li>비용 함수를 b에 대해 편미분
<img src="https://velog.velcdn.com/images/hye0n_w00/post/1a00875f-6cbd-4a74-b9dd-9b4baf3955f5/image.png" alt=""></li>
</ul>
<ul>
<li>특성이 하나일 때:<ul>
<li>최적의 기울기 w:
<img src="https://velog.velcdn.com/images/hye0n_w00/post/44cb045d-71be-48ba-9833-15234f6298ee/image.png" alt=""></li>
<li>x의 평균값
<img src="https://velog.velcdn.com/images/hye0n_w00/post/0d55a2ef-8726-4995-8045-ece2cc90232f/image.png" alt=""></li>
</ul>
</li>
</ul>
<ul>
<li>최적의 편향 b:
<img src="https://velog.velcdn.com/images/hye0n_w00/post/1089eab4-6ee3-4088-ad7f-094762a19ab2/image.png" alt="">
(여기서 x̄, ȳ는 각각 x와 y의 평균을 의미합니다.)</li>
</ul>
<ul>
<li><p>특성이 여러 개일 때 (다변량): 행렬을 사용하여 더 간결하게 표현하고 계산합니다.</p>
<ul>
<li>최적 파라미터 벡터 ŵ (w와 b를 합친 벡터):
<img src="https://velog.velcdn.com/images/hye0n_w00/post/3a34f24e-8d42-4804-82fc-4e8770a4a0e1/image.png" alt=""></li>
<li>데이터 행렬 X
<img src="https://velog.velcdn.com/images/hye0n_w00/post/1445de3d-b3e1-4ea0-a38d-005002c3b845/image.png" alt=""></li>
<li>종속 변수 벡터 y
<img src="https://velog.velcdn.com/images/hye0n_w00/post/85590b71-21f6-43ba-97e6-5778cd10e249/image.png" alt=""></li>
<li><img src="https://velog.velcdn.com/images/hye0n_w00/post/57276f1b-6e40-4039-bf43-f5f4f088f57c/image.png" alt=""></li>
<li>비용 함수의 편미분 (Gradient)
<img src="https://velog.velcdn.com/images/hye0n_w00/post/6ae2581d-e265-43f9-9f43-b3efa66b963c/image.png" alt=""></li>
<li>기울기를 0으로 설정하고 정리
<img src="https://velog.velcdn.com/images/hye0n_w00/post/630bbd3c-0471-4d3b-a6d0-cda3e45d54a3/image.png" alt=""></li>
<li>최정 예측 모델
<img src="https://velog.velcdn.com/images/hye0n_w00/post/20d9f79d-2811-459d-b259-ea2472eb6888/image.png" alt="">
실제로 XᵀX가 풀랭크일 확률은 낮기 때문에 Regularization 필요</li>
</ul>
</li>
<li><p>데이터가 직선이 아니라면 단순한 선형 모델은 데이터를 잘 예측할 수 없습니다. 이 상황에서는 아래의 식을 사용합니다.(어려운 곡선 문제를 직선문제로 바꿔서 해결하는 로그-선형 회귀)</p>
<ul>
<li>y ≈ e^(wᵀx + b)</li>
<li>ln(y) ≈ wᵀx + b</li>
</ul>
</li>
</ul>
<h1 id="33-로지스틱-회귀">3.3 로지스틱 회귀</h1>
<p>선형 모델을 사용하여 분류(Classification) 문제를 해결하는 대표적인 방법.</p>
<p>이전의 선형 회귀가 집값이나 시험 점수 같은 숫자를 예측했다면, 로지스틱 회귀는 &quot;이 메일이 스팸일까, 아닐까?&quot; 또는 &quot;이 고객이 구독할까, 안 할까?&quot;처럼 두 가지 선택지 중 하나를 결정하는 확률을 예측합니다.</p>
<ul>
<li><p>선형 회귀의 한계
단순 선형 회귀의 예측값(wx+b)은 음의 무한대부터 양의 무한대까지 모든 숫자가 될 수 있습니다. 하지만 우리가 원하는 것은 확률, 즉 0과 1 사이의 값입니다. 선형 회귀의 결과를 확률로 해석하기는 어렵습니다.</p>
</li>
<li><p>해결책: 시그모이드 함수 (Sigmoid Function)
이 문제를 해결하기 위해 시그모이드(Sigmoid) 함수라는 비선형 함수를 사용합니다. 이 함수는 어떤 값이든 0과 1 사이의 값으로 &quot;찌그러뜨리는&quot; 특징을 가집니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/fcca556d-71bc-4f08-b163-816d5802453b/image.png" alt=""></p>
<ul>
<li>z 자리에 선형 회귀의 예측값(wᵀx + b)이 들어갑니다.</li>
</ul>
</li>
<li><p>로짓 변환
로짓 변환 (Logit Transformation): 식을 wᵀx + b에 대해 정리하면 다음과 같이 됩니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/578644e6-8e05-4da7-853b-3f0543fef053/image.png" alt=""></p>
</li>
</ul>
<ul>
<li>의미:<ul>
<li>y는 &quot;성공할 확률&quot;입니다.</li>
<li>1-y는 &quot;실패할 확률&quot;입니다.</li>
<li>y / (1-y)는 <strong>오즈(Odds)</strong>라고 부르며, 성공 확률이 실패 확률보다 몇 배나 높은지를 나타냅</li>
</ul>
</li>
</ul>
<h3 id="최대우도법-maximum-likelihood-estimation-mle">최대우도법 (Maximum Likelihood Estimation, MLE)</h3>
<p>선형 회귀는 오차를 최소화하는 방식으로 최적의 해를 찾았습니다. 하지만 분류 문제인 로지스틱 회귀에서는 다른 접근법이 더 효과적입니다.</p>
<ul>
<li><p>최대우도법이란?
&quot;우리가 가진 데이터가 나타날 확률(Likelihood)을 가장 높게 만들어주는 최적의 파라미터(w, b)를 찾자&quot;는 통계적인 방법입니다.</p>
</li>
<li><p>ℓ(w, b) = Σ ln p(yᵢ | xᵢ; w, b)
이 식은 &quot;모든 데이터에 대해, 모델이 실제 정답 yᵢ를 예측할 로그 확률의 총합&quot;을 의미하며, 우리는 이 값을 최대로 만드는 w와 b를 찾고 싶습니다.</p>
</li>
</ul>
<h3 id="경사-하강법gradient-descent">경사 하강법(Gradient Descent)</h3>
<p>손실 함수는 볼록 함수입니다. 즉, 아래 그림처럼 밥그릇 모양이어서 최저점(Global Minimum)이 단 하나만 존재합니다. 이 최저점을 찾아가는 방법이 바로 경사 하강법입니다.</p>
<p>베타(β)는 가중치 벡터 w와 편향 b를 하나의 벡터로 합친 통합 파라미터 벡터입니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/ad2ca49f-ceb0-4d29-864b-9d5576dbe284/image.png" alt=""></p>
<ul>
<li><p>1차 도함수 (Gradient, 기울기)
<img src="https://velog.velcdn.com/images/hye0n_w00/post/ae34e2de-578a-4379-b738-f87100c83bd5/image.png" alt="">
이 기울기 값을 경사 상승법(Gradient Ascent) 또는 <strong>경사 하강법(Gradient Descent)</strong>에 사용하여, β를 최적의 값으로 점진적으로 업데이트해 나갑니다.</p>
</li>
<li><p>2차 도함수 (Hessian, 곡률)
<img src="https://velog.velcdn.com/images/hye0n_w00/post/233164e9-e4f8-4055-85fa-69a183d50d51/image.png" alt="">
뉴턴 방법(Newton&#39;s Method)과 같은 더 발전된 최적화 알고리즘은 이 2차 도함수(곡률) 정보까지 활용하여, 단순한 경사 하강법보다 훨씬 빠르게 최적의 해를 찾아낼 수 있습니다.</p>
</li>
</ul>
<h1 id="34-선형-판별-분석linear-discriminant-analysis-lda">3.4 선형 판별 분석(Linear Discriminant Analysis, LDA)</h1>
<p>대표적인 분류(Classification) 알고리즘이자, 차원 축소(Dimensionality Reduction) 기법
목표:  &quot;클래스 간 분산은 최대화, 클래스 내 분산은 최소화&quot; 하는 최적의 투영 축 w를 찾는 것</p>
<ul>
<li><p>μ₀, μ₁ : 각 클래스(0과 1)에 속한 데이터들의 평균(중심점)</p>
</li>
<li><p>Σ₀, Σ₁ : 각 클래스 데이터들이 얼마나 퍼져있는지를 나타내는 공분산 행렬</p>
</li>
<li><p>w : 우리가 찾고 싶은 투영 축(projection axis)</p>
</li>
<li><p>LDA의 두 가지 목표를 하나의 식으로 합칩니다.</p>
<ul>
<li>분자 (최대화 대상): 클래스 간 거리. w라는 축에 투영된 두 클래스 중심점(wᵀμ₀, wᵀμ₁) 사이의 거리입니다. 거리가 클수록 좋으므로 분자에 놓습니다.</li>
<li>분자 ≈ (wᵀμ₀ - wᵀμ₁)²</li>
<li>분모 (최소화 대상): 클래스 내 분산. w축에 투영된 각 클래스 데이터들의 퍼짐 정도(wᵀΣ₀w, wᵀΣ₁w)입니다. 퍼짐 정도가 작을수록 좋으므로 분모에 놓습니다.</li>
<li>분모 = wᵀΣ₀w + wᵀΣ₁w</li>
</ul>
</li>
</ul>
<h4 id="클래스-내-산포-행렬-within-class-scatter-matrix">클래스 내 산포 행렬, Within-class scatter matrix</h4>
<ul>
<li>S_w = Σ₀ + Σ₁</li>
<li>S_w는 모든 클래스 내부의 분산을 합친 것입니다.</li>
</ul>
<h4 id="클래스-간-산포-행렬-between-class-scatter-matrix">클래스 간 산포 행렬, Between-class scatter matrix</h4>
<ul>
<li>S_b = (μ₀ - μ₁)(μ₀ - μ₁)ᵀ</li>
<li>S_b는 두 클래스 평균 사이의 거리를 나타냅니다.</li>
</ul>
<ul>
<li>최종 목표 함수(일반화된 레일리 몫 (Generalized Rayleigh Quotient)<ul>
<li>J(w) = (wᵀS_b w) / (wᵀS_w w)</li>
</ul>
</li>
</ul>
<h4 id="라그랑주-승수법을-통한-해법">라그랑주 승수법을 통한 해법</h4>
<ul>
<li>최대화할 함수 (f): f(w) = wᵀS_b w (클래스 간 분산)</li>
<li>제약 조건 함수 (g): g(w) = wᵀS_w w = 1 (클래스 내 분산)</li>
</ul>
<p>라그랑주 승수법에 따르면, f(w)가 최대가 되는 지점에서는 f(w)의 기울기와 g(w)의 기울기가 평행해야 합니다.</p>
<ul>
<li>f(w)의 기울기: ∇f(w) = 2S_b w</li>
<li>g(w)의 기울기: ∇g(w) = 2S_w w</li>
</ul>
<p>두 벡터가 평행하다는 것은, 한 벡터가 다른 벡터의 상수배와 같다는 의미입니다. 여기서 그 상수를 λ (람다), 즉 라그랑주 승수라고 부릅니다.</p>
<ul>
<li>f(w)의 기울기 = λ * g(w)의 기울기</li>
<li>2S_b w = λ * (2S_w w)</li>
<li>S_b w = λS_w w
<img src="https://velog.velcdn.com/images/hye0n_w00/post/41b0c405-96e0-42b1-8319-f0ee83a0cbb3/image.png" alt="">
위의 식은 일단 두 클래스의 <strong>평균(중심점)을 잇는 방향 (μ₀ - μ₁)</strong>을 기본으로 하고,
각 클래스 내부의 퍼짐 정도(S_w)를 고려하여 그 방향을 <strong>보정(S_w⁻¹를 곱함)</strong>해준 것입니다.</li>
</ul>
<h3 id="lda-vs-로지스틱-회귀-logistic-regression">LDA vs 로지스틱 회귀 (Logistic Regression)</h3>
<ul>
<li><p>공통점: 두 모델 모두 분류를 위한 선형 결정 경계를 만듭니다.</p>
</li>
<li><p>차이점: LDA는 데이터가 특정 확률 분포(가우시안 분포)를 따른다고 가정하는 <strong>생성 모델(Generative Model)</strong>인 반면, 로지스틱 회귀는 데이터의 분포를 가정하지 않고 결정 경계 자체를 찾는 <strong>판별 모델(Discriminative Model)</strong>입니다. LDA의 가정이 잘 맞으면 더 좋은 성능을 보일 수 있습니다.</p>
</li>
</ul>
<h3 id="다중-클래스-lda-multi-class-lda">다중 클래스 LDA (Multi-class LDA)</h3>
<ul>
<li><p>클래스 내 산포 행렬 S_w
<img src="https://velog.velcdn.com/images/hye0n_w00/post/9004edf7-c7d6-4e4c-a759-e738c9b0cd9c/image.png" alt=""></p>
</li>
<li><p>클래스 간 산포 행렬 S_b
<img src="https://velog.velcdn.com/images/hye0n_w00/post/b585d321-b11b-41e2-8933-d036d18c3234/image.png" alt=""></p>
</li>
<li><p>목표: K개의 클래스를 가장 잘 분리하는 최적의 (K-1)차원 공간을 찾습니다.</p>
</li>
<li><p>방법: 고유값 문제를 풀어 클래스 분리 능력이 가장 뛰어난 <strong>K-1개의 축(고유벡터)</strong>을 선택합니다.</p>
</li>
<li><p>결과: 분류와 차원 축소를 동시에 수행하여, 복잡한 고차원 데이터를 다루기 쉬운 저차원 데이터로 압축합니다.</p>
</li>
</ul>
<h1 id="35-다중-분류-학습">3.5 다중 분류 학습</h1>
<h3 id="분해법과-앙상블ensemble">분해법과 앙상블(Ensemble)</h3>
<ul>
<li>분해법의 과정:<ol>
<li>하나의 다중 클래스 문제를 여러 개의 이진 분류 문제로 나눕니다.</li>
<li>나눠진 각 문제에 대해 별도의 이진 분류기를 훈련시킵니다. (여러 명의 전문가를 만듦)</li>
<li>새로운 데이터가 들어오면, 훈련된 모든 이진 분류기들에게 예측을 시킨 후, 그 결과를 종합하여(앙상블) 최종 결정을 내립니다.</li>
</ol>
</li>
</ul>
<h3 id="분해-전략-decomposition-strategies">분해 전략 (Decomposition Strategies)</h3>
<h4 id="1-일대일-one-vs-one-ovo">1. 일대일 (One-vs-One, OvO)</h4>
<p>N개의 클래스가 있다면, 가능한 모든 <strong>클래스 쌍(pair)</strong>에 대해 분류기를 만듭니다. 총 N(N-1)/2개의 분류기를 만듭니다.</p>
<ul>
<li><p>예시 (A, B, C 세 클래스):</p>
<ul>
<li>분류기 1: A vs B</li>
<li>분류기 2: A vs C</li>
<li>분류기 3: B vs C</li>
</ul>
</li>
<li><p>예측: 새로운 데이터에 대해 모든 분류기들이 &#39;투표&#39;를 합니다. 예를 들어 분류기 1은 &quot;A&quot;, 분류기 2는 &quot;A&quot;, 분류기 3은 &quot;B&quot;라고 예측했다면, A가 2표, B가 1표를 얻어 최종 결과는 A가 됩니다.</p>
</li>
</ul>
<h4 id="2-일대다-one-vs-rest-ovr">2. 일대다 (One-vs-Rest, OvR)</h4>
<p>N개의 클래스가 있다면, N개의 분류기를 만듭니다. 각 분류기는 <strong>&quot;자기 클래스 vs 나머지 전부&quot;</strong>를 구분하도록 학습합니다.</p>
<ul>
<li><p>예시 (A, B, C 세 클래스):</p>
<ul>
<li>분류기 1: A (양성) vs {B, C} (음성)</li>
<li>분류기 2: B (양성) vs {A, C} (음성)</li>
<li>분류기 3: C (양성) vs {A, B} (음성)</li>
</ul>
</li>
<li><p>예측: 새로운 데이터에 대해 세 분류기 모두를 실행시켜, 가장 높은 확신(확률) 점수를 보인 분류기의 클래스를 최종 결과로 선택합니다.</p>
</li>
</ul>
<h4 id="3-다대다-many-vs-many-mvm와-ecoc">3. 다대다 (Many-vs-Many, MvM)와 ECOC</h4>
<p>가장 발전된 형태로, 여러 클래스를 두 개의 그룹으로 무작위로 나누어 학습시키는 방식입니다. 대표적인 예가 <strong>오류 수정 출력 코드(Error-Correcting Output Codes, ECOC)</strong>입니다.</p>
<ul>
<li><p>핵심 아이디어: 각 클래스마다 고유한 <strong>&quot;바코드(Codeword)&quot;</strong>를 부여하고, 분류기들의 예측 결과를 조합하여 어떤 클래스의 바코드와 가장 비슷한지 찾는 방식입니다.</p>
</li>
<li><p>코딩 행렬 (Coding Matrix): 이 과정을 설계하는 표입니다.</p>
<ul>
<li>행: 클래스 (A, B, C, D)</li>
<li>열: 이진 분류기 (f₁, f₂, f₃, f₄)</li>
<li>값: +1(양성 클래스로 사용), -1(음성 클래스로 사용), 0(이 학습에는 불참)
<img src="https://velog.velcdn.com/images/hye0n_w00/post/c7f279b8-ef11-4ba0-a778-fdcfd35ffd7b/image.png" alt=""></li>
</ul>
</li>
</ul>
<h1 id="36-클래스-불균형-문제">3.6 클래스 불균형 문제</h1>
<p>한 클래스의 데이터는 엄청나게 많은데, 다른 클래스의 데이터는 극소수인 경우를 말합니다.</p>
<ul>
<li><p>예시: 신용카드 사기 탐지 (99.9% 정상 거래 vs 0.1% 사기 거래), 희귀병 진단, 공장 불량품 검출 등.</p>
</li>
<li><p>문제점: 이런 데이터로 모델을 학습시키면, 모델은 정확도를 높이기 위해 그냥 다수 클래스(정상)라고만 예측하는 &quot;게으른&quot; 모델이 되기 쉽습니다. 정작 중요한 소수 클래스(사기)는 거의 탐지하지 못하게 됩니다.</p>
</li>
</ul>
<h3 id="1-언더샘플링-undersampling">1. 언더샘플링 (Undersampling)</h3>
<p>방법: 다수 클래스의 데이터 수를 줄여서 소수 클래스의 수와 비슷하게 맞추는 방법입니다. 예를 들어 정상 거래 10,000개, 사기 거래 100개가 있다면, 정상 거래 데이터 중 100개만 무작위로 뽑아서 100:100으로 균형을 맞춥니다.</p>
<p>단점: 다수 클래스의 데이터가 대량으로 버려지므로, 중요한 정보가 손실될 수 있습니다.</p>
<p>언더샘플링 + 앙상블: 정보 손실을 줄이기 위해, 다수 클래스에서 여러 번 다르게 샘플링하여 여러 개의 균형 잡힌 데이터셋을 만듭니다. 그리고 각 데이터셋으로 별도의 모델을 학습시킨 후, 그 모델들의 예측을 종합(앙상블)하는 방식을 사용합니다.</p>
<h3 id="2-오버샘플링-oversampling">2. 오버샘플링 (Oversampling)</h3>
<p>방법: 소수 클래스의 데이터 수를 늘려서 다수 클래스의 수와 비슷하게 맞추는 방법입니다.</p>
<p>단순한 방법: 소수 클래스의 데이터를 그대로 복제하여 수를 늘립니다. (단점: 과적합 위험)</p>
<p>SMOTE (Synthetic Minority Over-sampling Technique): 단순 복제를 개선한 기법입니다. 소수 클래스의 데이터들 사이의 공간에 가상의 새로운 데이터(Synthetic Data)를 생성하여 데이터 수를 늘립니다.</p>
<p>원리: 소수 클래스 데이터 A와 그 주변의 가까운 데이터 B를 선택한 후, A와 B를 잇는 선 위의 어딘가에 새로운 점 C를 생성합니다.</p>
<p>장점: 단순 복제보다 과적합 위험이 적고, 모델이 더 일반화된 패턴을 학습하도록 돕습니다.</p>
<h3 id="3-임계값-이동-threshold-moving">3. 임계값 이동 (Threshold Moving)</h3>
<p>방법: 데이터 자체는 건드리지 않고, 모델의 &quot;판단 기준&quot;을 바꾸는 방법입니다.</p>
<p>원리: 로지스틱 회귀는 보통 예측 확률이 50%(임계값 0.5)를 넘으면 양성(Positive)으로 판단합니다. 하지만 불균형 데이터에서는 소수 클래스의 예측 확률이 낮게 나오는 경향이 있습니다.</p>
<p>해결책: 이 임계값을 0.5에서 0.2나 0.1처럼 대폭 낮춥니다. 이제 모델이 &quot;사기일 확률이 20%만 돼도 일단 사기라고 의심해!&quot;라고 더 민감하게 판단하도록 기준을 바꾸는 것입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Dynamic Vision Sensors for Human Activity Recognition]]></title>
            <link>https://velog.io/@hye0n_w00/Dynamic-Vision-Sensors-for-Human-Activity-Recognition1</link>
            <guid>https://velog.io/@hye0n_w00/Dynamic-Vision-Sensors-for-Human-Activity-Recognition1</guid>
            <pubDate>Thu, 10 Jul 2025 02:39:28 GMT</pubDate>
            <description><![CDATA[<h2 id="abstract">abstract</h2>
<ul>
<li><p>DVS란?
일반 카메라와 달리, 영상 전체를 촬영하는 것이 아니라 움직임이 있는 부분만을 감지하여 데이터를 기록하는 저전력, 고효율 카메라입니다.</p>
</li>
<li><p>연구 방법
연구팀은 DVS가 포착한 움직임 데이터로 <strong>&#39;모션 맵(Motion Map)&#39;</strong>이라는 특징을 만들고, 이를 기존의 움직임 분석 기술인 <strong>&#39;모션 경계 히스토그램(MBH)&#39;</strong>과 결합했습니다.</p>
</li>
<li><p>가장 중요한 결과
DVS는 일반 비디오보다 훨씬 적은 양의 데이터(희소한 정보)만 사용함에도 불구하고, 일반 비디오와 비슷한 수준의 높은 행동 인식 성능을 보였습니다. 이는 DVS가 웨어러블 기기 등에서 매우 유용하게 쓰일 수 있음을 의미합니다.</p>
</li>
</ul>
<h2 id="introduction">Introduction</h2>
<ul>
<li><p>문제 제기: 기존 카메라는 움직임이 없어도 모든 장면을 계속 찍기 때문에 전력과 메모리 낭비가 심합니다.</p>
</li>
<li><p>대안 제시: 이 논문은 &#39;동적 비전 센서(DVS)&#39;를 대안으로 제시합니다. DVS는 사람의 눈처럼 움직임이 있을 때만 데이터를 기록하는 저전력/고효율 카메라입니다.</p>
</li>
<li><p>연구 목표: 이 DVS를 사용하여 사람의 행동이나 제스처를 인식하는 방법을 개발하는 것입니다.</p>
</li>
<li><p>연구 방법: DVS가 만든 움직임 데이터로 &#39;모션 맵&#39;을 만들고, &#39;Bag of Visual Words&#39; 기법을 이용해 핵심 특징을 추출했습니다. 여기에 다른 기술(MBH)을 더해 성능을 더욱 높였습니다.</p>
</li>
<li><p>핵심 결과: DVS는 데이터 양이 훨씬 적음에도 불구하고, 기존 비디오와 비슷한 수준의 높은 행동 인식 성능을 보여주었습니다. 이는 DVS의 잠재력이 매우 크다는 것을 시사합니다.</p>
</li>
</ul>
<h2 id="11-related-work">1.1 Related work</h2>
<ul>
<li>전통적인 방식 vs. 딥러닝 방식
전통적으로 행동 인식은 영상에서 움직임이나 모양에 대한 특징(MHI, HOF, MBH 등)을 추출하고, 이를 기계(SVM 등)에 학습시키는 방식으로 이루어졌습니다. 하지만 이 방식은 카메라 움직임에 취약하거나 DVS 센서처럼 색상, 배경 정보가 없는 데이터에는 적용하기 어려운 단점이 있습니다.</li>
</ul>
<p>최근에는 딥러닝(CNN, LSTM 등)을 사용해 컴퓨터가 스스로 특징을 학습하게 하는 방식이 주류가 되었습니다. 특히 2-스트림 CNN은 영상의 <strong>정지 이미지(모양 정보)</strong>와 <strong>움직임 정보(광학 흐름)</strong>를 각각 별도의 신경망으로 학습시켜 합치는 방식으로 높은 성능을 보여줍니다.</p>
<ul>
<li>이 논문의 접근 방식
이 논문은 최신 딥러닝처럼 복잡한 모델을 사용하는 대신, DVS가 제공하는 핵심 정보(움직임과 모양)에 집중합니다.</li>
</ul>
<p>간단한 모양 기반 특징과 움직임 기반 특징을 <strong>&#39;융합(fusion)&#39;</strong>하는 직관적이고 쉬운 방법을 제안하며, 이 방법만으로도 충분히 좋은 성능을 낼 수 있다는 점을 강조합니다.</p>
<h2 id="2-dvs-based-activity-recognition">2. DVS Based Activity Recognition</h2>
<h3 id="1단계-dvs-데이터를-모션-맵으로-변환">1단계: DVS 데이터를 &#39;모션 맵&#39;으로 변환</h3>
<p>DVS에서 실시간으로 출력되는 (x, y, 시간) 형태의 이벤트 데이터를 바로 분석하기 어렵기 때문에, 컴퓨터가 이해하기 쉬운 세 장의 2D 이미지로 요약합니다.</p>
<ol>
<li><p>3D 비디오 생성: DVS 이벤트들을 짧은 시간 간격으로 묶어 30fps 비디오(3D 데이터 덩어리)를 만듭니다.</p>
</li>
<li><p>2D 투영 (압축): 이 3D 데이터를 각기 다른 축 방향으로 압축(평균)하여 세 종류의 2D 모션 맵을 생성합니다.</p>
<ul>
<li>x-y 맵: 시간 축으로 압축. 비디오 전체 시간 동안 어디에서 움직임이 발생했는지 보여줍니다. (객체의 평균 자세)</li>
<li>x-t 맵: 세로 축으로 압축. 시간의 흐름에 따른 객체의 수평 움직임 패턴을 보여줍니다.</li>
<li>y-t 맵: 가로 축으로 압축. 시간의 흐름에 따른 객체의 수직 움직임 패턴을 보여줍니다.</li>
</ul>
</li>
</ol>
<h3 id="2단계-특징-추출-및-융합을-통한-행동-인식">2단계: 특징 추출 및 융합을 통한 행동 인식</h3>
<p>모션 맵이 생성되면, 전통적인 컴퓨터 비전 파이프라인(Bag of Features)을 통해 행동을 분류하고, 성능을 극대화하기 위해 두 번의 융합을 거칩니다.</p>
<ol>
<li><p>1차 융합 (모션 맵 내부):</p>
<ul>
<li><p>세 종류의 모션 맵 각각에서 SURF 알고리즘으로 특징점을 추출합니다.</p>
</li>
<li><p>k-평균 클러스터링을 이용해 이 특징점들로 &#39;시각 단어 사전&#39;을 만듭니다.</p>
</li>
<li><p>각 맵을 이 사전을 기준으로 &#39;단어 빈도수 통계&#39;(BoF 히스토그램)로 변환합니다.</p>
</li>
<li><p>이렇게 만들어진 세 개의 히스토그램을 하나로 합쳐 모양과 움직임 정보를 모두 담은 1차 특징을 완성합니다.</p>
</li>
</ul>
</li>
<li><p>2차 융합 (외부 기술 결합):</p>
<ul>
<li><p>1차 융합으로 만든 &#39;모션 맵 특징&#39;에, 완전히 다른 방식으로 움직임을 분석하는 최첨단 기술 MBH의 특징을 추가로 결합합니다.</p>
</li>
<li><p>이유: 모션 맵은 단순히 이벤트의 평균(0차 통계)을 보는 반면, MBH는 움직임의 변화율(2차 통계)을 계산합니다. 서로 다른 관점의 정보를 제공하므로, 둘을 합치면 서로의 단점을 보완하여 훨씬 더 정확한 분석이 가능합니다.</p>
</li>
</ul>
</li>
<li><p>최종 분류:</p>
<ul>
<li>이렇게 완성된 최종 특징 데이터를 SVM 분류기에 학습시켜 특정 행동(예: 손 흔들기, 발 차기 등)을 예측하게 합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/b7c935dc-f10c-4fde-ae4b-d659dd8f83e3/image.png" alt=""></li>
</ul>
</li>
</ol>
<h3 id="example-of-figure">example of figure</h3>
<h4 id="1단계-surf로-특징점-추출하기">1단계: SURF로 특징점 추출하기</h4>
<p>먼저, 가지고 있는 모든 훈련용 이미지(고양이 사진 10장, 바퀴 사진 10장)에 SURF를 적용해 특징점을 찾습니다.</p>
<ul>
<li>고양이 얼굴 이미지에서는 😺:<ul>
<li>뾰족한 귀 끝, 동그란 눈동자, 코의 모양, 수염 가닥 같은 부분들이 <strong>특징점(keypoint)</strong>으로 추출됩니다.</li>
</ul>
</li>
<li>자동차 바퀴 이미지에서는 🚗:<ul>
<li>바퀴살의 직선 부분, 볼트의 육각형 모양, 타이어의 무늬 같은 부분들이 특징점으로 추출됩니다.</li>
</ul>
</li>
</ul>
<p>이 단계가 끝나면, 우리는 수많은 특징점 &#39;조각&#39;들의 모음을 갖게 됩니다.</p>
<h4 id="2단계-k-means로-시각적-단어-사전-만들기">2단계: K-Means로 &#39;시각적 단어 사전&#39; 만들기</h4>
<p>추출된 모든 특징점 조각들을 K-Means에 입력하여 비슷한 것들끼리 묶어 그룹을 만듭니다. 여기서는 4개의 그룹(K=4)으로 묶어 보겠습니다.</p>
<ul>
<li>그룹 1: 뾰족한 &#39;귀&#39; 모양의 특징점들이 모두 한 그룹으로 묶입니다. 👉 시각적 단어 1: &quot;귀 모양&quot;</li>
<li>그룹 2: 동그란 &#39;눈&#39;이나 &#39;코&#39; 모양의 특징점들이 묶입니다. 👉 시각적 단어 2: &quot;동그란 모양&quot;</li>
<li>그룹 3: 길고 곧은 &#39;바퀴살&#39; 모양의 특징점들이 묶입니다. 👉 시각적 단어 3: &quot;직선 모양&quot;</li>
<li>그룹 4: &#39;볼트&#39; 같은 육각형 모양의 특징점들이 묶입니다. 👉 시각적 단어 4: &quot;육각 모양&quot;</li>
</ul>
<p>이제 우리는 4개의 단어로 구성된 <strong>&#39;시각적 단어 사전&#39;</strong>을 갖게 되었습니다. {귀 모양, 동그란 모양, 직선 모양, 육각 모양}</p>
<h4 id="3단계-bovw로-이미지를-특징-벡터로-변환하기">3단계: BoVW로 이미지를 특징 벡터로 변환하기</h4>
<p>새로운 이미지가 주어졌을 때, 이 이미지를 단어 사전으로 요약합니다.</p>
<h5 id="예시-1-새로운-고양이-사진이-입력될-경우">예시 1: 새로운 고양이 사진이 입력될 경우</h5>
<ol>
<li><p>새 고양이 사진에서 SURF로 특징점을 찾습니다.</p>
</li>
<li><p>찾아낸 각 특징점이 우리 사전에 있는 4개의 단어 중 무엇과 가장 닮았는지 확인하고 빈도수를 셉니다.</p>
<ul>
<li>&quot;귀 모양&quot;: 18번 나타남</li>
<li>&quot;동그란 모양&quot;: 32번 나타남</li>
<li>&quot;직선 모양&quot;: 2번 나타남 (배경의 노이즈)</li>
<li>&quot;육각 모양&quot;: 1번 나타남 (배경의 노이즈)</li>
</ul>
</li>
<li><p>이 고양이 이미지는 최종적으로 [18, 32, 2, 1] 이라는 1차원 특징 벡터로 변환됩니다.</p>
</li>
</ol>
<h5 id="예시-2-새로운-자동차-바퀴-사진이-입력될-경우">예시 2: 새로운 자동차 바퀴 사진이 입력될 경우</h5>
<p>같은 과정을 거치면 [1, 3, 25, 20] 과 같은 벡터가 나올 것입니다.</p>
<h4 id="4단계-분류하기">4단계: 분류하기</h4>
<p>분류기(SVM 등)는 [18, 32, 2, 1]처럼 첫 두 숫자가 큰 벡터는 &#39;고양이&#39;라고 학습하고, [1, 3, 25, 20]처럼 뒤 두 숫자가 큰 벡터는 &#39;자동차 바퀴&#39;라고 학습합니다.</p>
<h2 id="3-datasets">3. Datasets</h2>
<h3 id="1-ucf11-데이터셋-공개-벤치마크">1. UCF11 데이터셋 (공개 벤치마크)</h3>
<ul>
<li><p>데이터 특징: 기존의 유명한 행동 인식 데이터셋인 UCF11을 DVS 버전으로 변환한 데이터입니다.</p>
<ul>
<li><p>생성 방식: 원본 비디오를 모니터로 재생하고, 그 화면을 DAViS240C라는 DVS 센서로 다시 촬영하여 만들었습니다.</p>
</li>
<li><p>한계 및 의의: 이 방식 때문에 시간 해상도는 원본 비디오(약 30fps) 수준으로 제한되지만, DVS 센서 고유의 노이즈 특성을 담고 있어 실험에 사용하기에 충분합니다.</p>
</li>
</ul>
</li>
<li><p>클래스 (종류): 농구 슛, 자전거 타기, 다이빙, 골프 스윙 등 총 11개의 행동으로 구성됩니다.</p>
</li>
<li><p>성능 검증 방식: 데이터를 25개 그룹으로 나누어, 하나씩 제외하며 테스트하는 LOO(Leave-One-Out) 교차 검증을 사용합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/1ac2c59b-dc2a-4dfb-8de3-f011d119fa98/image.png" alt=""></p>
</li>
</ul>
<h3 id="2-dvs-제스처-데이터셋-자체-제작">2. DVS 제스처 데이터셋 (자체 제작)</h3>
<ul>
<li><p>데이터 특징: 연구팀이 DVS128 센서를 이용해 직접 촬영하고 제작한 데이터입니다.</p>
</li>
<li><p>클래스 (종류): 왼쪽/오른쪽 쓸기, 시계 방향/반대 방향 회전 등 총 10개의 손 제스처로 구성됩니다.</p>
<ul>
<li>12명의 피실험자가 각 제스처를 10번씩 반복하여 총 1200개의 데이터를 확보했습니다.</li>
</ul>
</li>
<li><p>성능 검증 방식: 12명의 피실험자를 기준으로 한 명씩 제외하며 테스트하는 12-겹 교차 검증을 사용합니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/49daea78-308a-41d8-87ab-93a9c08482dc/image.png" alt=""></p>
</li>
</ul>
<h3 id="모션-맵-분석을-통한-핵심-관찰">모션 맵 분석을 통한 핵심 관찰</h3>
<p>생성된 모션 맵을 분석한 결과, 각 행동은 모션 맵 위에 <strong>고유한 시각적 패턴(지문)</strong>을 남기는 것으로 확인되었습니다.</p>
<ul>
<li><p>x-y 맵: 행동의 평균적인 모양과 자세를 보여줍니다.</p>
</li>
<li><p>x-t, y-t 맵: 행동의 시간에 따른 리듬과 동적인 패턴을 보여줍니다.</p>
<ul>
<li>(예시) &#39;그네 타기&#39;는 y-t 맵에 강이 굽이치는 듯한 물결 모양을, &#39;트램펄린 점프&#39;는 x-t 맵에 규칙적인 상하 스파이크 모양을 나타냈습니다.</li>
</ul>
</li>
</ul>
<h2 id="4feature-extraction-and-classification">4.Feature Extraction and classification</h2>
<p>이 연구는 행동 인식을 위해 <strong>기존의 우수한 기술(밀집 궤적)</strong>과 자체 제안한 기술(모션 맵) 두 가지를 모두 평가하고 활용합니다.</p>
<h3 id="1-기존-기술-평가-밀집-궤적dense-trajectories-기반">1. 기존 기술 평가: 밀집 궤적(Dense Trajectories) 기반</h3>
<p>기존의 유명한 특징 기술자인 HoG, HOF, MBH의 성능을 평가하기 위한 과정입니다.</p>
<h4 id="1단계-궤적-추출">1단계: 궤적 추출</h4>
<ul>
<li>밀집 궤적: 비디오 화면에 수많은 점을 빽빽하게 찍은 후, 15프레임 동안 각 점들의 이동 경로를 추적하여 수많은 짧은 &#39;움직임 궤적&#39;을 확보합니다.</li>
</ul>
<h4 id="2단계-특징-계산">2단계: 특징 계산</h4>
<ul>
<li><p>볼륨 및 셀 분할: 각 궤적을 중심으로 32x32x15 픽셀 크기의 3D 비디오 덩어리(볼륨)를 설정하고, 이를 다시 2x2x3개의 더 작은 셀(Cell)로 나눕니다.</p>
</li>
<li><p>기술자 계산: 12개의 각 셀 내부에서 HoG, HOF, MBH 특징을 각각 계산합니다.</p>
<ul>
<li>HoG/MBH: 8방향 정보 사용 → 96차원 특징 (12셀 x 8방향)</li>
<li>HOF: 9방향 정보 사용 → 108차원 특징 (12셀 x 9방향)</li>
<li>MBH (수평/수직): 수평(x)과 수직(y) 움직임을 별도로 분석 → 192차원 특징 (96차원 x 2)</li>
</ul>
</li>
</ul>
<h4 id="3단계-bofbag-of-features-모델링-및-분류">3단계: BoF(Bag of Features) 모델링 및 분류</h4>
<ul>
<li><p>특징 샘플링: 비디오당 약 50만 개의 방대한 궤적이 생성되므로, 계산 효율을 위해 각 훈련 비디오에서 무작위로 10만 개의 궤적을 공정하게 샘플링합니다.</p>
</li>
<li><p>사전(Codebook) 생성: 샘플링된 특징들을 k-평균 클러스터링하여, 500개의 대표 &#39;시각 단어&#39;로 구성된 사전을 만듭니다.</p>
</li>
<li><p>히스토그램 변환: 이 사전을 기준으로 각 비디오를 500차원의 특징 통계(히스토그램)로 변환합니다.</p>
</li>
<li><p>분류기 학습: 최종적으로 L2 정규화를 거친 히스토그램 데이터를 SVM 분류기에 학습시킵니다.</p>
</li>
</ul>
<h3 id="2-제안-기술-평가-모션-맵motion-maps-기반">2. 제안 기술 평가: 모션 맵(Motion Maps) 기반</h3>
<p>논문에서 자체적으로 제안한 <strong>모션 맵(x-y, x-t, y-t)</strong>에 대해서도 위와 동일한 Bag of Features 방식을 적용합니다.</p>
<p>사전 크기: 동일하게 500차원의 코드북을 사용합니다.</p>
<p>구현: 이 과정은 MATLAB의 내장 함수(bagOfFeatures)를 활용했습니다.</p>
<h3 id="최종-분류-전략">최종 분류 전략</h3>
<p>다중 클래스 인식: 11개의 행동을 구별하기 위해 일대다(One-vs-all) 방식의 선형 SVM을 사용합니다.</p>
<p>성능 검증: 모든 기술자들의 성능은 LOO(Leave-One-Out) 교차 검증 방식을 통해 객관적으로 평가되며, 그 결과는 다음 섹션에서 제시됩니다.</p>
<h2 id="5-experimental-results">5. Experimental Results</h2>
<ul>
<li><p>DVS의 가능성 확인: 논문에서 제안한 모션 맵은 배경 정보가 없는 깔끔한 DVS 데이터에서 더 높은 성능을 보였습니다. 반면, 기존 기술인 HoG/HOF는 모든 정보가 다 있는 원본 비디오에서 더 강한 모습을 보였습니다. 이는 모션 맵이 DVS 데이터에 최적화된 기술임을 증명합니다.</p>
</li>
<li><p>최고의 조합 발견: 여러 특징들을 조합해 본 결과, <strong>모션 맵 + MBH</strong>를 융합했을 때 가장 높은 행동 인식 성능을 기록했습니다. 이는 두 기술이 서로 다른 관점에서 움직임을 분석하여 부족한 부분을 완벽하게 보완해주기 때문입니다.</p>
</li>
<li><p>성능 격차 해소 (핵심 결론): DVS 데이터는 정보량이 훨씬 적음에도 불구하고, 모션 맵 + MBH 융합 방법을 사용하자 기존의 컬러 비디오와 거의 대등한 수준의 성능을 달성했습니다.</p>
</li>
<li><p>결론적으로, 이 실험은 DVS 데이터가 정보량의 한계에도 불구하고 올바른 분석 방법만 적용하면 기존 비디오를 대체할 수 있을 만큼 강력한 잠재력을 가졌다는 것을 증명합니다.</p>
</li>
</ul>
<h2 id="conclusion-and-future-work">Conclusion and Future Work</h2>
<h3 id="결론">결론</h3>
<ul>
<li><p>핵심 성과: DVS 데이터에 최적화된 &#39;모션 맵&#39; 기술을 제안했으며, 이를 기존의 강력한 기술인 &#39;MBH&#39;와 융합하여 최고의 성능을 달성했습니다.</p>
</li>
<li><p>성능 증명: 정보량이 훨씬 적은 DVS 데이터를 사용했음에도 불구하고, 제안된 방법은 기존의 컬러 비디오(RGB)와 거의 동등한 수준의 행동 인식 성능을 보였습니다.</p>
</li>
<li><p>최종 결론: DVS는 색상이나 질감 정보가 없다는 한계가 있지만, 사용 가능한 정보만으로도 충분히 유용합니다. 따라서 저전력, 고속 환경에서는 기존 카메라를 효율적으로 대체할 수 있는 강력한 대안입니다.</p>
</li>
</ul>
<h3 id="향후-연구">향후 연구</h3>
<ul>
<li><p>BoF 모델 개선: 현재의 Bag-of-Features 모델은 특징들의 &#39;위치&#39; 정보를 무시하는 단점이 있습니다. 향후에는 특징 간의 공간적 관계를 고려하는 &#39;공간적 상호상관도(Spatial Correlogram)&#39; 같은 기법을 도입하여 성능을 개선할 수 있습니다.</p>
</li>
<li><p>DVS 전용 추적 기술 개발: 현재 사용되는 &#39;밀집 궤적&#39; 기술은 DVS의 노이즈까지 특징으로 잘못 감지하는 문제가 있습니다. 이 문제를 근본적으로 해결하기 위해, 노이즈는 걸러내고 실제 움직임만 정확하게 찾아 추적하는 DVS에 특화된 새로운 추적 기술을 개발해야 합니다. 이것이 DVS 기반 행동 인식 기술을 한 단계 더 발전시키는 핵심 과제입니다.</p>
<ul>
<li><p>해결책 (DVS 전용 추적 기술): DVS 데이터의 특성을 처음부터 이해하는 새로운 추적 기술이 필요합니다.</p>
<ul>
<li>작동 방식:</li>
</ul>
<ol>
<li>먼저 DVS 이벤트 스트림에서 무작위로 흩어져 있는 노이즈 점들은 걸러냅니다.</li>
<li>의미 있는 덩어리를 이루며 함께 움직이는 &#39;진짜 객체&#39;의 이벤트들만 식별합니다.</li>
<li>오직 이렇게 식별된 &#39;진짜&#39; 움직임에 대해서만 궤적을 추적합니다.</li>
</ol>
</li>
</ul>
</li>
</ul>
<h2 id="상세-내용">상세 내용</h2>
<h3 id="1-모션-맵-motion-map-상세-설명">1. 모션 맵 (Motion Map) 상세 설명</h3>
<p>모션 맵은 DVS 센서에서 나오는 불규칙한 (x, y, 시간) 형태의 이벤트 데이터를, 컴퓨터가 분석하기 쉬운 세 장의 의미 있는 2D 이미지로 요약하는 기술입니다. 3차원 시공간에 흩어져 있는 움직임의 점들을 서로 다른 각도에서 눌러 만든 &#39;그림자&#39;라고 생각할 수 있습니다.</p>
<h4 id="①-x-y-맵-움직임의-공간-분포도-어디서">① x-y 맵: 움직임의 공간 분포도 (어디서?)</h4>
<p>생성 방식: 3D 데이터 덩어리를 시간(t) 축 방향에서 압축합니다.</p>
<p>의미: 비디오 전체 시간 동안 어디에서 움직임이 가장 많이 발생했는지를 보여주는 <strong>히트맵(Heatmap)</strong>과 같습니다. 객체가 움직인 전체 공간적 궤적과 평균적인 자세를 나타내며, MHI(움직임 이력 이미지)와 유사한 역할을 합니다.</p>
<h4 id="②-x-t-맵-수평-움직임의-타임라인-수평적으로-어떻게">② x-t 맵: 수평 움직임의 타임라인 (수평적으로 어떻게?)</h4>
<p>생성 방식: 3D 데이터 덩어리를 세로(y) 축 방향에서 압축합니다.</p>
<p>의미: 가로축은 공간(x), 세로축은 시간(t)인 2D 이미지입니다. 시간이 흐름에 따라 객체의 수평(좌우) 위치가 어떻게 변했는지를 보여줍니다. 예를 들어, 왼쪽에서 오른쪽으로 일정한 속도로 움직였다면 이 맵에는 대각선 패턴이 나타납니다.</p>
<h4 id="③-y-t-맵-수직-움직임의-타임라인-수직적으로-어떻게">③ y-t 맵: 수직 움직임의 타임라인 (수직적으로 어떻게?)</h4>
<p>생성 방식: 3D 데이터 덩어리를 가로(x) 축 방향에서 압축합니다.</p>
<p>의미: 가로축은 공간(y), 세로축은 시간(t)인 2D 이미지입니다. 시간이 흐름에 따라 객체의 수직(상하) 위치가 어떻게 변했는지를 보여줍니다. 예를 들어, 위아래로 손을 흔드는 동작은 이 맵에 물결(sine wave) 모양의 패턴을 만듭니다.</p>
<p>결론적으로, 이 세 장의 모션 맵은 하나의 복잡한 시공간 움직임을 <strong>&#39;공간적 분포&#39;, &#39;수평적 리듬&#39;, &#39;수직적 리듬&#39;</strong>이라는 세 가지 단순하지만 핵심적인 관점으로 분해하여, 컴퓨터가 행동의 패턴을 쉽게 학습하도록 돕습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Machine Learning(02.모델 평가 및 선택)]]></title>
            <link>https://velog.io/@hye0n_w00/Machine-Learning02.%EB%AA%A8%EB%8D%B8-%ED%8F%89%EA%B0%80-%EB%B0%8F-%EC%84%A0%ED%83%9D</link>
            <guid>https://velog.io/@hye0n_w00/Machine-Learning02.%EB%AA%A8%EB%8D%B8-%ED%8F%89%EA%B0%80-%EB%B0%8F-%EC%84%A0%ED%83%9D</guid>
            <pubDate>Sat, 05 Jul 2025 08:24:30 GMT</pubDate>
            <description><![CDATA[<h1 id="21-경험-오차-및-과적합">2.1 경험 오차 및 과적합</h1>
<h3 id="오차율과-정확도-모델-성능의-기본-척도">오차율과 정확도: 모델 성능의 기본 척도</h3>
<ul>
<li>오차율(Error Rate): 분류 모델이 잘못 예측한 샘플의 비율입니다. 예를 들어, 100개의 샘플 중 10개를 잘못 분류했다면 오차율은 10%입니다.</li>
<li>정확도(Accuracy): 분류 모델이 올바르게 예측한 샘플의 비율입니다. 위 예시에서 정확도는 90%가 됩니다. 정확도는 1 - 오차율로 계산할 수 있습니다.</li>
</ul>
<h3 id="훈련-오차와-일반화-오차-모델의-진짜-실력">훈련 오차와 일반화 오차: 모델의 진짜 실력</h3>
<ul>
<li>훈련 오차(Training Error) 또는 경험 오차(Empirical Error): 모델이 <strong>학습 데이터(Training Data)</strong>에서 보여주는 오차입니다. 즉, 모델이 이미 학습한 문제지에 대해 얼마나 좋은 점수를 받는지를 나타냅니다.</li>
<li>일반화 오차(Generalization Error): 모델이 새로운 데이터(Test Data), 즉 학습 과정에서 보지 못했던 데이터에 대해 보여주는 오차입니다. 머신러닝의 목표는 이 일반화 오차를 최소화하는 모델을 찾는 것입니다. 훈련 오차가 아무리 낮아도 일반화 오차가 높다면 그 모델은 실전에서 쓸모가 없습니다.</li>
</ul>
<h3 id="과적합과-과소적합-모델-학습의-딜레마">과적합과 과소적합: 모델 학습의 딜레마</h3>
<ul>
<li><p>과적합(Overfitting): 모델이 학습 데이터에 너무 깊게 파고들어 데이터의 특성뿐만 아니라 노이즈까지 학습해버린 상태를 말합니다. 이 경우 훈련 오차는 매우 낮지만 일반화 오차는 높게 나타납니다. 과적합은 머신러닝에서 피하기 어렵고 해결하기 까다로운 주요 문제 중 하나입니다. 마치 시험공부를 할 때 족보만 달달 외워 응용 문제를 전혀 풀지 못하는 것과 같습니다.</p>
</li>
<li><p>과소적합(Underfitting): 모델이 학습 데이터의 패턴을 충분히 학습하지 못한 상태입니다. 이 경우 훈련 오차와 일반화 오차 모두 높게 나타납니다. 모델이 너무 단순해서 데이터의 복잡한 관계를 파악하지 못하는 것이 원인입니다.</p>
</li>
</ul>
<h3 id="모델-선택-최적의-알고리즘과-파라미터-찾기">모델 선택: 최적의 알고리즘과 파라미터 찾기</h3>
<p>이러한 문제들을 해결하고 일반화 성능이 가장 좋은 모델을 찾는 과정을 <strong>모델 선택(Model Selection)</strong>이라고 합니다. 모델 선택은 크게 두 가지로 나눌 수 있습니다.</p>
<ul>
<li>학습 알고리즘 선택: 어떤 종류의 알고리즘(예: 결정 트리, 서포트 벡터 머신, 딥러닝 등)을 사용할지 선택하는 것입니다.</li>
<li>파라미터 선택: 선택한 알고리즘의 세부 설정을 조정하는 것입니다. 예를 들어, 결정 트리에서는 <strong>가지치기(Pruning)</strong>를 통해 과적합을 방지할 수 있고, 딥러닝에서는 에포크(Epoch) 수를 늘려 과소적합을 해결할 수 있습니다.</li>
</ul>
<h1 id="22-모델-성능-평가-방법">2.2 모델 성능 평가 방법</h1>
<h3 id="1-홀드아웃-hold-out">1. 홀드아웃 (Hold-out)</h3>
<ul>
<li>전체 데이터를 <strong>훈련 세트(Training Set)</strong>와 테스트 세트(Test Set), 두 개로 분리합니다.</li>
<li>: 훈련 세트로 모델을 학습시킨 후, 모델이 한 번도 보지 못한 테스트 세트로 성능을 평가합니다. (보통 7:3 또는 8:2 비율로 나눕니다.)</li>
<li>단점: 데이터가 어떻게 나뉘었는지에 따라 평가 결과가 크게 달라질 수 있습니다. 예를 들어, 우연히 쉬운 데이터만 테스트 세트에 몰리면 모델 성능이 실제보다 좋게 평가될 수 있습니다.</li>
</ul>
<h4 id="층화-추출법-stratified-sampling">층화 추출법 (Stratified Sampling)</h4>
<ul>
<li>홀드아웃의 단점을 보완하기 위한 방법입니다. 데이터의 클래스(정답) 비율을 원래 데이터셋과 동일하게 유지하면서 데이터를 나누는 방식입니다.<ul>
<li>예시: 1000개의 데이터 중 &#39;정상&#39;이 900개, &#39;불량&#39;이 100개(9:1 비율) 있다면, 7:3으로 나눌 때 훈련 세트에도 9:1 비율(정상 630, 불량 70), 테스트 세트에도 9:1 비율(정상 270, 불량 30)이 되도록 추출합니다. 이렇게 하면 데이터 쏠림 현상을 방지하여 더 안정적인 평가가 가능합니다.</li>
</ul>
</li>
</ul>
<h3 id="2-교차-검증-cross-validation">2. 교차 검증 (Cross-Validation)</h3>
<ul>
<li><p>데이터를 한 번만 나누는 홀드아웃 방식의 불안정성을 개선한 방법입니다. 모든 데이터가 한 번씩은 테스트에 사용되도록 하여 더 신뢰도 높은 평가 결과를 얻습니다.</p>
</li>
<li><p>k-폴드 교차 검증 (k-Fold Cross-Validation): 가장 널리 쓰이는 방식입니다.</p>
</li>
<li><p>첫 번째 폴드를 테스트 세트로 사용하고, 나머지 k-1개 폴드를 훈련 세트로 사용해 모델을 학습하고 평가합니다.</p>
</li>
<li><p>이번엔 두 번째 폴드를 테스트 세트로, 나머지를 훈련 세트로 사용해 평가합니다. 이 과정을 k번 반복하여 k개의 평가 점수를 얻고, 이 점수들의 평균을 최종 성능으로 삼습니다.</p>
</li>
<li><p>장점: 모든 데이터를 평가에 활용하므로 평가 결과가 안정적이고 신뢰도가 높습니다.</p>
<ul>
<li>LOOCV (Leave-One-Out Cross-Validation)
교차 검증의 아주 특별한 경우입니다. 데이터 샘플의 개수(n)만큼 폴드를 나누는 것(k=n) 입니다.
과정: 전체 데이터(n개) 중 단 1개의 샘플만 테스트 세트로 사용하고, 나머지 n-1개를 훈련 세트로 사용합니다. 이 과정을 모든 샘플에 대해 한 번씩, 즉 n번 반복합니다.
장점: 데이터셋의 편향이 거의 없는, 매우 정확한 성능 추정치를 얻을 수 있습니다.
단점: 데이터 개수만큼 모델을 훈련해야 하므로 데이터가 조금만 커져도 계산 비용이 엄청나게 커져 현실적으로 사용하기 어렵습니다.</li>
</ul>
</li>
</ul>
<h3 id="3-부트스트래핑-bootstrapping">3. 부트스트래핑 (Bootstrapping)</h3>
<ul>
<li>데이터가 적을 때 유용하게 사용할 수 있는 평가 방법입니다.<ul>
<li>과정:
전체 데이터셋(n개)에서 랜덤으로 1개의 샘플을 뽑아 새로운 데이터셋에 추가합니다. 이때 뽑았던 샘플은 다시 원래 데이터셋에 집어넣습니다. (복원)
이 과정을 n번 반복하여 원본과 크기가 같은 새로운 부트스트랩 데이터셋을 만듭니다. (이 데이터셋에는 중복된 샘플이 포함될 수 있습니다.)
이 부트스트랩 데이터셋을 훈련 세트로 사용합니다.
이때 한 번도 뽑히지 않은 샘플들(약 36.8%)이 있는데, 이를 OOB(Out-of-Bag) 샘플이라고 부르며 테스트 세트로 활용합니다.</li>
</ul>
</li>
</ul>
<p>특징: 교차 검증과 달리 훈련 세트와 테스트 세트가 나뉘지 않고, 데이터의 분포를 추정하거나 모델 성능의 안정성을 확인할 때 주로 사용됩니다.</p>
<h3 id="🛠️-파라미터-튜닝과-최종-모델-선택">🛠️ 파라미터 튜닝과 최종 모델 선택</h3>
<p>이제 모델을 &#39;어떻게&#39; 만들지 결정하는 과정입니다. 여기서 파라미터와 검증 세트의 개념이 중요합니다.</p>
<h3 id="파라미터란-parameters">파라미터란? (Parameters)</h3>
<ul>
<li><p>모델의 파라미터는 크게 두 종류로 나뉩니다.</p>
<ul>
<li><p>모델 파라미터 (Model Parameters)
정의: 모델이 훈련 데이터로부터 스스로 학습하는 값입니다.
예시: 선형 회귀의 기울기(W)와 절편(b), 딥러닝 모델의 수많은 가중치(Weights)들.
우리가 직접 설정하는 값이 아니라, 모델이 학습 과정에서 최적의 값을 찾아냅니다.</p>
</li>
<li><p>하이퍼파라미터 (Hyperparameters)
정의: 모델이 학습하기 전에 사용자가 직접 설정해주는 값입니다. 모델이 학습하는 방법을 제어하는 설정값이라고 생각하면 쉽습니다. &#39;알고리즘 파라미터&#39;라고도 부릅니다.
예시: 학습률(Learning Rate), 결정 트리의 최대 깊이, k-폴드 교차 검증에서의 k값, k-최근접 이웃(KNN) 알고리즘의 이웃 수 k 등.
최적의 하이퍼파라미터를 찾는 과정을 하이퍼파라미터 튜닝이라고 합니다.</p>
</li>
</ul>
</li>
</ul>
<h3 id="검증-세트-validation-set란">검증 세트 (Validation Set)란?</h3>
<ul>
<li><p>최적의 하이퍼파라미터를 찾으려면, 여러 하이퍼파라미터 조합으로 모델을 만들어보고 어떤 조합의 성능이 가장 좋은지 평가해야 합니다. 이때 어떤 데이터로 평가해야 할까요?</p>
<ul>
<li><p>훈련 세트? (X): 훈련 세트로 평가하면 무조건 모델을 복잡하게 만드는 하이퍼파라미터가 좋게 평가됩니다(과적합).</p>
</li>
<li><p>테스트 세트? (X): 절대 안 됩니다. 테스트 세트는 우리 모델의 최종 성적을 매기는 &#39;수능 시험지&#39;와 같습니다. 수능 시험지로 모의고사를 계속 보면서 공부하면, 결국 그 시험지에만 잘하는 모델이 되어 진짜 실력을 측정할 수 없게 됩니다. 이를 &#39;테스트 세트 정보 누수(Data Leakage)&#39; 라고 합니다.</p>
</li>
</ul>
</li>
</ul>
<p>그래서 우리는 <strong>검증 세트(Validation Set)</strong>라는 &#39;모의고사 시험지&#39;를 따로 만듭니다.</p>
<p>최종 모델 선택 과정
데이터 분리: 전체 데이터를 훈련 세트, 검증 세트, 테스트 세트 세 부분으로 나눕니다. (예: 6:2:2)</p>
<p>하이퍼파라미터 튜닝:
다양한 하이퍼파라미터 조합(예: 학습률 0.1, 0.01, 0.001)을 준비합니다.
각 조합에 대해 훈련 세트로 모델을 학습시키고, 검증 세트로 성능을 평가합니다.
최적 하이퍼파라미터 선택: 검증 세트에서 가장 높은 성능을 보인 하이퍼파라미터 조합을 선택합니다.</p>
<h1 id="23-모델-성능-측정">2.3 모델 성능 측정</h1>
<p>모델 평가는 크게 회귀(값을 예측)와 분류(카테고리를 예측)로 나뉩니다.</p>
<h3 id="회귀-모델의-성능-측정">회귀 모델의 성능 측정</h3>
<p>평균 제곱 오차 (Mean Squared Error, MSE)
실제 정답과 모델이 예측한 값의 차이를 제곱하여 평균을 낸 값입니다. 예측값이 정답에서 얼마나 떨어져 있는지를 나타내는 가장 기본적인 지표입니다.</p>
<h3 id="분류-모델의-성능-측정">분류 모델의 성능 측정</h3>
<p>분류 모델의 평가는 &#39;그래서 뭘 잘 맞췄고, 뭘 어떻게 틀렸는가&#39;를 세세하게 따지는 것에서 시작합니다.</p>
<h4 id="1-혼동-행렬-confusion-matrix-모든-평가의-시작">1. 혼동 행렬 (Confusion Matrix): 모든 평가의 시작</h4>
<p>이진 분류(Yes/No) 문제에서 모델의 예측 결과를 4가지 상황으로 요약한 표입니다.
<img src="https://velog.velcdn.com/images/hye0n_w00/post/0aae83ad-f073-4437-af6c-0efa05db3151/image.png" alt=""></p>
<h3 id="2-정밀도precision와-재현율recall">2. 정밀도(Precision)와 재현율(Recall)</h3>
<ul>
<li><p>정밀도 (Precision): 모델이 &quot;Positive&quot;라고 예측한 것들 중에서, 실제로 Positive인 것의 비율.</p>
<ul>
<li>의미: &quot;이 모델이 암이라고 진단하면, 얼마나 믿을만한가?&quot;</li>
</ul>
</li>
<li><p>재현율 (Recall): 실제 &quot;Positive&quot;인 것들 중에서, 모델이 Positive라고 예측해낸 것의 비율.</p>
<ul>
<li>의미: &quot;실제 암 환자들 중에서, 모델이 얼마나 놓치지 않고 찾아냈는가?&quot;</li>
</ul>
</li>
<li><p>정밀도-재현율 트레이드오프 (Trade-off)
둘은 반비례 관계를 가집니다. 모델이 Positive라고 예측하는 기준(Threshold)을 낮추면 더 많은 것을 Positive로 예측하므로 재현율은 올라가지만, 그만큼 잘못 예측(FP)하는 것도 많아져 정밀도는 떨어집니다.</p>
</li>
</ul>
<h3 id="3-종합-평가-지표-및-시각화">3. 종합 평가 지표 및 시각화</h3>
<p>정밀도와 재현율은 한쪽만 보기 어려우므로, 이를 종합적으로 보는 지표들이 필요합니다.</p>
<ul>
<li><p>P-R 곡선 (Precision-Recall Curve)
모델의 예측 기준(Threshold)을 계속 바꾸면서 정밀도와 재현율이 어떻게 변하는지를 그린 그래프입니다. 곡선이 오른쪽 위(정밀도=1, 재현율=1)에 가까울수록 좋은 모델입니다.</p>
</li>
<li><p>F1 점수 (F1 Score)
정밀도와 재현율의 조화 평균입니다. 두 지표가 모두 중요할 때, 하나의 숫자로 모델 성능을 평가하기 위해 사용합니다.</p>
</li>
<li><p>ROC 곡선 (Receiver Operating Characteristic Curve)
모델의 예측 기준을 바꾸면서 <strong>재현율(TPR)</strong>과 <strong>&quot;가짜 양성 비율(FPR)&quot;</strong>의 관계를 그린 그래프입니다.</p>
<ul>
<li><p>TPR (True Positive Rate): 재현율과 동일합니다. 
fracTPTP+FN</p>
</li>
<li><p>FPR (False Positive Rate): 실제 Negative 중에서 Positive로 잘못 예측한 비율. 
fracFPFP+TN</p>
</li>
</ul>
</li>
<li><p>AUC (Area Under the Curve)
ROC 곡선 아래의 면적입니다. 0.5(랜덤 모델) ~ 1(완벽한 모델) 사이의 값을 가지며, AUC 값이 클수록 모델의 전반적인 성능이 좋다고 평가합니다. 모델이 Positive와 Negative 샘플을 얼마나 잘 구별하는지를 나타내는 종합적인 지표입니다.</p>
</li>
</ul>
<h1 id="24-비교-검증">2.4 비교 검증</h1>
<p>비교 검증은 모델 간의 성능 차이가 우연에 의한 것인지, 아니면 통계적으로 의미 있는 차이인지 수학적으로 확인하는 과정입니다. 모든 검정은 p-value가 기준치(보통 0.05)보다 작으면 <strong>&quot;두 모델(들)의 성능에 유의미한 차이가 있다&quot;</strong>고 결론 내립니다.</p>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/252143aa-86d2-4e06-919c-93cfa8236ed5/image.png" alt=""></p>
<ul>
<li><p>두 모델만 비교할 때: 교차 검증 t-검정이 일반적입니다. 두 모델의 예측 결과가 어떻게 다른지에 집중하고 싶다면 맥니마 검정을 사용합니다.</p>
</li>
<li><p>세 개 이상의 모델을 비교할 때: 먼저 프리드먼 검정을 돌려 &quot;모델들 간에 전반적으로 성능 차이가 있는가?&quot;를 확인합니다. 여기서 &#39;차이가 있다&#39;는 결론이 나오면, 네메니 사후 검정을 추가로 실시하여 구체적으로 &#39;어떤 모델&#39;과 &#39;어떤 모델&#39;이 차이가 나는지 찾아냅니다.</p>
<h1 id="25-편향과-분산">2.5 편향과 분산</h1>
<p>모델의 일반화 오차(Generalization Error)는 크게 편향(Bias), 분산(Variance), 그리고 줄일 수 없는 오류(Irreducible Error) 세 가지로 분해할 수 있습니다. 이 중 편향과 분산을 이해하는 것은 모델의 과적합, 과소적합을 파악하고 제어하는 데 매우 중요합니다.</p>
</li>
</ul>
<h3 id="편향-bias">편향 (Bias)</h3>
<p>정의: 모델이 학습 데이터에 내재된 실제 관계를 얼마나 잘 파악하는지를 나타냅니다. 편향이 높다는 것은 모델이 너무 단순해서 데이터의 복잡한 패턴을 제대로 학습하지 못하고, 예측값들이 실제 정답과 전반적으로 멀리 떨어져 있음을 의미합니다.</p>
<h3 id="분산-variance">분산 (Variance)</h3>
<p>정의: 훈련 데이터가 조금만 바뀌어도 모델의 예측이 얼마나 민감하게 변하는지를 나타냅니다. 분산이 높다는 것은 모델이 훈련 데이터의 특정 패턴뿐만 아니라 노이즈까지 과하게 학습하여, 새로운 데이터에 대한 예측이 매우 불안정하고 일관성이 없음을 의미합니다.</p>
<h3 id="편향-분산-트레이드오프-bias-variance-trade-off">편향-분산 트레이드오프 (Bias-Variance Trade-off)</h3>
<p>편향과 분산은 일반적으로 한쪽이 낮아지면 다른 쪽이 높아지는 상충 관계(Trade-off)에 있습니다.</p>
<ul>
<li><p>모델이 단순해지면 (복잡도 감소):
데이터의 미세한 변화에 덜 민감해져 분산은 감소합니다.
하지만 데이터의 전체적인 패턴을 놓칠 가능성이 커져 편향은 증가합니다.</p>
</li>
<li><p>모델이 복잡해지면 (복잡도 증가):
데이터의 복잡한 패턴을 잘 잡아내어 편향은 감소합니다.
하지만 데이터의 노이즈까지 학습하게 되어 분산은 증가합니다.</p>
</li>
</ul>
<p>머신러닝의 목표는 이 트레이드오프 관계를 이해하고, 총오차(Total Error) = 편향² + 분산 + 줄일 수 없는 오류를 최소화하는 최적의 모델 복잡도, 즉 <strong>&quot;Sweet Spot&quot;</strong>을 찾는 것입니다. 이는 과소적합과 과적합 사이의 균형을 맞추는 것과 같습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C Programming Study_6]]></title>
            <link>https://velog.io/@hye0n_w00/C-Programming-Study6</link>
            <guid>https://velog.io/@hye0n_w00/C-Programming-Study6</guid>
            <pubDate>Thu, 29 May 2025 07:38:56 GMT</pubDate>
            <description><![CDATA[<h1 id="기말고사-대비-문제">기말고사 대비 문제</h1>
<h2 id="1-함수-관련-문제">1. 함수 관련 문제</h2>
<h3 id="문제-1">문제 1</h3>
<p>사용자로부터 두 개의 정수와 연산자(+, -, *, /)를 입력받아 연산 결과를 출력하는 함수를 작성하시오.</p>
<p>함수 이름은 calculate로 하며, 입력은 두 정수와 문자(연산자)이고, 반환형은 double이다.</p>
<p>나누기 연산 시 두 번째 정수가 0이면 에러 메시지를 출력하고 0을 반환한다.</p>
<p>main 함수에서는 결과를 출력하시오.</p>
<h3 id="문제-2">문제 2</h3>
<p>재귀 함수를 이용해 주어진 정수 n까지의 합을 구하는 프로그램을 작성하시오.</p>
<p>함수 이름은 recursiveSum이며, 입력은 정수 n, 반환값은 int.</p>
<p>예를 들어 n=5일 때 1+2+3+4+5 = 15를 반환해야 한다.</p>
<h3 id="문제-3">문제 3</h3>
<p>입력한 문자열이 팰린드롬(앞에서 읽으나 뒤에서 읽으나 같은 문자열)인지 검사하는 함수를 작성하시오.</p>
<p>함수 이름은 isPalindrome이며, 입력은 문자열(char 배열), 반환형은 int(0 또는 1).</p>
<p>main 함수에서 문자열을 입력받아 결과를 출력하시오.</p>
<h2 id="2-배열-관련-문제">2. 배열 관련 문제</h2>
<h3 id="문제-4">문제 4</h3>
<p>사용자가 입력한 10개의 정수를 배열에 저장한 후, 배열에서 최대값과 최소값을 찾아 출력하는 프로그램을 작성하시오.</p>
<h3 id="문제-5">문제 5</h3>
<p>2차원 배열 3x3에 1부터 9까지 숫자를 저장한 후, 다음과 같이 대각선 합을 구하는 코드를 작성하시오.</p>
<p>main 함수에서 2차원 배열 초기화</p>
<p>함수 diagonalSum을 만들어서 대각선의 합을 반환하도록 구현</p>
<h2 id="3-포인터-관련-문제">3. 포인터 관련 문제</h2>
<h3 id="문제-6">문제 6</h3>
<p>두 개의 정수를 입력받아 포인터를 이용하여 두 값의 위치를 바꾸는 함수를 작성하시오.</p>
<p>함수 이름은 swap이며, 입력은 두 개의 int* (포인터)이다.</p>
<p>main 함수에서 값을 입력받고 함수 호출 후 결과 출력</p>
<h3 id="문제-7">문제 7</h3>
<p>사용자가 입력한 문자열을 포인터 연산을 이용해 역순으로 출력하는 프로그램을 작성하시오.</p>
<p>문자열의 길이는 최대 100자.</p>
<p>포인터만 사용하여 문자열을 역순 출력할 것.</p>
<h3 id="문제-8">문제 8</h3>
<p>포인터 배열을 사용하여 세 개의 문자열(예: &quot;Apple&quot;, &quot;Banana&quot;, &quot;Cherry&quot;)을 저장하고, 이를 출력하는 프로그램을 작성하시오.</p>
<p>각 문자열은 문자 배열로 저장할 것</p>
<p>포인터 배열을 통해 각 문자열을 출력</p>
<p><a href="https://band-collar-06a.notion.site/C-1a8cf133eeae80569d27d60489d8bb1e">기말 대비 자료 모음</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C Programming Study_5(Assignment)]]></title>
            <link>https://velog.io/@hye0n_w00/C-Programming-Study5Assignment</link>
            <guid>https://velog.io/@hye0n_w00/C-Programming-Study5Assignment</guid>
            <pubDate>Wed, 21 May 2025 04:08:23 GMT</pubDate>
            <description><![CDATA[<h1 id="백준-코드-과제">백준 코드 과제</h1>
<h3 id="1--------11720----숫자의-합">1.        11720    숫자의 합</h3>
<h3 id="2--------9046----복호화">2.        9046    복호화</h3>
<h3 id="3--------10798----세로-읽기">3.        10798    세로 읽기</h3>
<h3 id="4--------1157----단어-공부">4.        1157    단어 공부</h3>
<h3 id="5--------4659----비밀번호-발음하기">5.        4659    비밀번호 발음하기</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[C Programming Study_4]]></title>
            <link>https://velog.io/@hye0n_w00/C-Programming-Study4</link>
            <guid>https://velog.io/@hye0n_w00/C-Programming-Study4</guid>
            <pubDate>Thu, 01 May 2025 08:48:25 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-포인터pointer-완전-정복">📌 포인터(Pointer) 완전 정복</h1>
<h2 id="1-포인터란">1. 포인터란?</h2>
<p>포인터란 다른 변수의 주소를 저장하는 변수입니다. 즉, 포인터는 &quot;값&quot;이 아닌 &quot;주소&quot;를 가리킵니다.</p>
<pre><code>int a = 10;
int *p = &amp;a; // p는 변수 a의 주소를 저장함</code></pre><h3 id="🔍-설명">🔍 설명</h3>
<blockquote>
</blockquote>
<p>a는 정수형 변수
&amp;a는 변수 a의 주소를 의미
*p는 포인터가 가리키는 주소에 저장된 값을 의미 (역참조)</p>
<blockquote>
</blockquote>
<h2 id="2-포인터-선언과-초기화">2. 포인터 선언과 초기화</h2>
<pre><code>int num = 100;
int *ptr = &amp;num;

printf(&quot;num의 값: %d\n&quot;, num);      // 100
printf(&quot;ptr이 가리키는 값: %d\n&quot;, *ptr); // 100
printf(&quot;ptr의 주소값: %p\n&quot;, ptr);   // num의 주소
</code></pre><h2 id="3-포인터와-배열">3. 포인터와 배열</h2>
<p>포인터는 배열과 밀접한 관계가 있습니다.</p>
<pre><code>int arr[3] = {1, 2, 3};
int *p = arr;

printf(&quot;%d\n&quot;, *p);     // 1
printf(&quot;%d\n&quot;, *(p+1)); // 2
</code></pre><h3 id="🔍-핵심-포인트">🔍 핵심 포인트</h3>
<p>배열 이름 arr 자체가 첫 번째 요소의 주소 (&amp;arr[0])로 작동</p>
<p>*(p + i)는 arr[i]와 동일</p>
<h2 id="4-포인터와-함수-call-by-reference">4. 포인터와 함수 (Call by Reference)</h2>
<pre><code>void swap(int *x, int *y) {
    int temp = *x;
    *x = *y;
    *y = temp;
}

int main() {
    int a = 5, b = 10;
    swap(&amp;a, &amp;b);
    printf(&quot;a = %d, b = %d\n&quot;, a, b); // a = 10, b = 5
}
</code></pre><h3 id="🔄-왜-이렇게-사용하나요">🔄 왜 이렇게 사용하나요?</h3>
<p>포인터를 통해 함수 내에서 원본 값을 바꿀 수 있음 (참조에 의한 호출)</p>
<h2 id="5-이중-포인터-double-pointer">5. 이중 포인터 (Double Pointer)</h2>
<pre><code>int val = 20;
int *p = &amp;val;
int **pp = &amp;p;

printf(&quot;%d\n&quot;, **pp); // 20
</code></pre><h3 id="🎯-사용-예시">🎯 사용 예시</h3>
<p>동적 메모리 할당 시 메모리의 주소를 함수에서 반환하려면 이중 포인터가 필요함</p>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

void allocateMemory(int **ptr) {
    *ptr = (int *)malloc(sizeof(int)); // 메모리 할당
    if (*ptr != NULL) {
        **ptr = 1234; // 값 저장
    }
}

int main() {
    int *p = NULL;
    allocateMemory(&amp;p); // 포인터의 주소 전달 (이중 포인터 사용)

    if (p != NULL) {
        printf(&quot;할당된 메모리의 값: %d\n&quot;, *p); // 1234 출력
        free(p); // 메모리 해제
    }

    return 0;
}
</code></pre><h2 id="6-동적-메모리-할당과-포인터-malloc-free">6. 동적 메모리 할당과 포인터 (malloc, free)</h2>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

int main() {
    int *p = (int *)malloc(sizeof(int));
    *p = 42;
    printf(&quot;%d\n&quot;, *p);
    free(p);
}
</code></pre><h3 id="⚠️-주의">⚠️ 주의</h3>
<p>malloc은 힙 영역에 메모리 공간을 동적으로 할당</p>
<p>사용이 끝난 후 반드시 free로 해제해야 메모리 누수 방지 가능</p>
<h2 id="7-포인터와-문자열">7. 포인터와 문자열</h2>
<pre><code>char *str = &quot;Hello&quot;;
printf(&quot;%c\n&quot;, *str);     // &#39;H&#39;
printf(&quot;%s\n&quot;, str);      // &quot;Hello&quot;
</code></pre><h2 id="8-포인터-배열-vs-배열-포인터">8. 포인터 배열 vs 배열 포인터</h2>
<pre><code>char *ptrs[3]; // 포인터들의 배열
int (*ptr)[3]; // 정수 배열을 가리키는 포인터
</code></pre><p>int <em>p[3] ==&gt; int를 가리키는 포인터 3개
int (</em>p)[3] ==&gt; int 3개짜리 배열 1개를 가리키는 포인터</p>
<pre><code>int arr[5];
int *p = arr;

sizeof(arr); // 20 (5 * sizeof(int))
sizeof(p);   // 4 or 8 (포인터 크기, 시스템 의존)
</code></pre><p>배열은 고정 크기를 가지지만 포인터는 주소만 참조</p>
<p>배열의 이름은 포인터처럼 쓰일 수 있으나 완전히 동일하지는 않음</p>
<h2 id="9-💡-구조체와-포인터">9. 💡 구조체와 포인터</h2>
<pre><code>struct Point {
    int x, y;
};

struct Point p = {1, 2};
struct Point *ptr = &amp;p;

printf(&quot;%d\n&quot;, ptr-&gt;x); // 1
</code></pre><h3 id="구조체-사용이-좋은-예시">구조체 사용이 좋은 예시</h3>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

struct Student {
    int id;
    char name[20];
    float grade;
};

void printStudent(struct Student s) {
    printf(&quot;학번: %d\n&quot;, s.id);
    printf(&quot;이름: %s\n&quot;, s.name);
    printf(&quot;성적: %.2f\n&quot;, s.grade);
}

int main() {
    struct Student s1;

    s1.id = 2023202042;
    strcpy(s1.name, &quot;김현우&quot;);
    s1.grade = 93.5;

    printStudent(s1);

    return 0;
}
</code></pre><h3 id="확장-가능성-예시">확장 가능성 예시</h3>
<pre><code>struct Student students[3]; // 여러 학생 저장 가능
struct Student *sp = &amp;s1;   // 구조체 포인터로 접근
printf(&quot;%s\n&quot;, sp-&gt;name);   // -&gt; 연산자 사용
</code></pre><h2 id="10-🧨-dangling-pointer-댕글링-포인터">10. 🧨 Dangling Pointer (댕글링 포인터)</h2>
<pre><code>int *p;

{
    int a = 10;
    p = &amp;a;
} // a는 여기서 소멸됨

printf(&quot;%d\n&quot;, *p); // 잘못된 접근 → 정의되지 않은 동작
</code></pre><p>스코프 밖으로 나간 지역변수의 주소를 사용하면 댕글링 포인터</p>
<p>free() 후에도 해당 포인터를 계속 사용하면 동일한 문제가 발생</p>
<h2 id="실습-코드">실습 코드</h2>
<h3 id="✅-예제-1-포인터를-이용한-값-변경">✅ 예제 1: 포인터를 이용한 값 변경</h3>
<p>정수형 변수 하나를 선언하고, 해당 변수의 주소를 포인터에 저장합니다. 이후 포인터를 통해 변수의 값을 변경합니다. 포인터를 통해 변수의 값을 읽고 쓸 수 있다는 개념을 익히는 데 초점을 둡니다.</p>
<p>요구 사항:</p>
<blockquote>
</blockquote>
<p>변수 a에 값 10을 저장
포인터 p에 a의 주소 저장
*p를 통해 a의 값을 20으로 변경
변경 전후의 a 값 출력</p>
<blockquote>
</blockquote>
<h3 id="✅-예제-2-배열과-포인터-연산">✅ 예제 2: 배열과 포인터 연산</h3>
<p>정수형 배열을 선언한 뒤, 배열 이름을 포인터처럼 사용해 배열 요소에 접근합니다. 포인터 산술 연산(p + i)을 사용하여 각 요소에 접근하며 출력합니다.</p>
<p>요구 사항:</p>
<blockquote>
</blockquote>
<p>정수 배열 arr에 1, 2, 3 저장
포인터 p를 arr로 초기화
반복문을 사용하여 *(p + i)로 배열 요소 출력</p>
<blockquote>
</blockquote>
<h3 id="✅-예제-3-개선-포인터를-이용한-최대값-교환-함수">✅ 예제 3 (개선): 포인터를 이용한 최대값 교환 함수</h3>
<p>세 개의 정수 중 가장 큰 값을 첫 번째 변수에 저장되도록 포인터를 활용하여 reorder_max_first() 함수를 작성합니다. 단순한 swap보다 논리적 분기가 포함되며, 포인터로 다수의 값을 비교/수정하는 패턴을 학습합니다.</p>
<p>요구 사항:</p>
<blockquote>
</blockquote>
<p>int *a, *b, *c를 인자로 받아
세 변수 중 가장 큰 값을 *a에 위치시키고 나머지 두 값은 그대로 둠
예: a=3, b=7, c=5 → a=7, b=3, c=5
main() 함수에서 세 변수의 주소를 전달
함수 호출 전/후 세 값 출력</p>
<blockquote>
</blockquote>
<h3 id="✅-예제-4-개선-구조체-배열과-포인터로-학생-검색하기">✅ 예제 4 (개선): 구조체 배열과 포인터로 학생 검색하기</h3>
<p>학생 5명의 정보를 구조체 배열로 저장하고, 학생의 ID로 검색했을 때 해당 학생의 이름과 점수를 출력하는 프로그램입니다. 포인터 연산을 통해 구조체 배열을 탐색하며, 포인터와 배열, 구조체의 결합을 학습합니다.</p>
<p>요구 사항:</p>
<blockquote>
</blockquote>
<p>struct Student { int id; char name[20]; float grade; }
5명의 정보를 구조체 배열에 저장
ID를 입력받고, 포인터를 사용해 배열을 선형 탐색
일치하는 학생이 있으면 이름과 성적 출력, 없으면 &quot;찾을 수 없음&quot;</p>
<blockquote>
</blockquote>
<h3 id="✅-예제-5-개선-동적-2차원-배열-생성-및-평균-계산">✅ 예제 5 (개선): 동적 2차원 배열 생성 및 평균 계산</h3>
<p>사용자에게 행과 열의 개수를 입력받아, malloc()을 사용해 동적으로 2차원 배열을 생성합니다. 각 원소를 사용자에게 입력받고, 평균을 계산한 뒤, 메모리를 해제합니다. 중첩 포인터 int **matrix를 이용한 메모리 할당/접근 패턴을 학습합니다.</p>
<p>요구 사항:</p>
<blockquote>
</blockquote>
<p>사용자로부터 행(row), 열(col) 수 입력받기
int **matrix를 사용해 2차원 배열 동적 생성
각 원소 입력받아 저장
전체 평균 계산 및 출력
free()로 모든 동적 메모리 해제</p>
<blockquote>
</blockquote>
<h3 id="✅-예제-6-개선-이중-포인터로-문자열-배열-관리">✅ 예제 6 (개선): 이중 포인터로 문자열 배열 관리</h3>
<p>char **words를 사용해 문자열 3개를 저장하는 프로그램을 작성합니다. 각 문자열을 malloc()으로 동적 할당한 뒤 내용을 복사하고, 모든 문자열을 출력합니다. 이중 포인터를 통해 다수의 문자열을 동적으로 처리하는 패턴을 학습합니다.</p>
<p>요구 사항:</p>
<blockquote>
</blockquote>
<p>char **words를 선언하여 문자열 3개 저장
각 문자열 공간을 malloc()으로 확보하고, strcpy()로 값 복사
반복문으로 문자열 전체 출력
free()로 각 문자열 및 words 자체 해제</p>
<blockquote>
</blockquote>
<h3 id="과제">과제</h3>
<h4 id="✅-1-과제-설명-포스기-프로그램-만들기">✅ [1] 과제 설명: 포스기 프로그램 만들기</h4>
<h4 id="📝-과제-목적">📝 과제 목적</h4>
<p>구조체, 포인터, 배열, 동적 메모리 할당, 함수 호출 시 포인터 전달 등의 개념을 실전 문제에 종합적으로 적용할 수 있는지 평가합니다.</p>
<h4 id="📋-문제-설명">📋 문제 설명</h4>
<p>당신은 편의점 포스기 소프트웨어를 개발 중입니다. 사용자는 여러 상품을 입력하고 결제를 진행할 수 있어야 합니다. 아래의 조건을 만족하는 프로그램을 작성하세요.</p>
<h4 id="📌-요구-사항">📌 요구 사항</h4>
<p>상품 구조체 정의
struct Item 구조체는 다음 멤버를 포함합니다:</p>
<blockquote>
</blockquote>
<p>char name[30] : 상품 이름
int price : 가격
int quantity : 수량</p>
<blockquote>
</blockquote>
<h4 id="동적-메모리-할당">동적 메모리 할당</h4>
<p>사용자에게 구매할 상품 개수(N)를 입력받고, 동적으로 구조체 배열을 할당하여 상품 정보를 입력받습니다.</p>
<h4 id="총액-계산-함수">총액 계산 함수</h4>
<p>int calculateTotal(struct Item *items, int count) 함수를 작성하여, 총 결제 금액을 계산합니다.</p>
<h4 id="출력-함수">출력 함수</h4>
<p>void printReceipt(struct Item *items, int count) 함수를 작성하여 아래와 같은 형태로 영수증을 출력합니다.</p>
<blockquote>
</blockquote>
<p>--- 영수증 ---</p>
<ol>
<li>콜라       x2 = 3000원</li>
<li>과자       x1 = 1500원
총액: 4500원<blockquote>
</blockquote>
</li>
</ol>
<h4 id="메모리-해제-필수">메모리 해제 필수</h4>
<p>malloc을 사용한 만큼 free()를 사용해 동적 메모리를 모두 해제하세요.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C Programming Study_3]]></title>
            <link>https://velog.io/@hye0n_w00/C-Programming-Study3</link>
            <guid>https://velog.io/@hye0n_w00/C-Programming-Study3</guid>
            <pubDate>Wed, 02 Apr 2025 13:14:38 GMT</pubDate>
            <description><![CDATA[<h1 id="c-programming-study_3">C Programming Study_3</h1>
<h2 id="배열--문자열">배열 &amp; 문자열</h2>
<h3 id="1-1차원-배열">1. 1차원 배열</h3>
<h4 id="11-배열-선언">1.1 배열 선언</h4>
<ul>
<li>배열은 같은 데이터 타입의 여러 값을 하나의 변수에 저장할 수 있는 자료형입니다.</li>
<li>배열을 선언할 때, 배열의 크기는 고정되어야 하며, 선언된 크기만큼 메모리를 할당합니다.</li>
</ul>
<p>예시코드:</p>
<pre><code>int arr[5];  // 5개의 정수를 저장할 수 있는 배열</code></pre><h4 id="12-배열-초기화">1.2 배열 초기화</h4>
<ul>
<li>배열을 선언하면서 초기값을 지정할 수 있습니다. 초기값이 없으면 배열에는 쓰레기 값이 저장됩니다.</li>
</ul>
<p>예시코드</p>
<pre><code>int arr[5] = {1, 2, 3, 4, 5};  // 배열을 선언하고 초기화</code></pre><ul>
<li>배열의 일부만 초기화하면, 나머지 요소는 0으로 초기화됩니다.</li>
</ul>
<h4 id="13-배열-순회">1.3 배열 순회</h4>
<p>배열에 저장된 모든 값을 반복문을 사용하여 순차적으로 접근할 수 있습니다.</p>
<p>예시코드</p>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    // char str[6] = &quot;Hello&quot;;
    for (int i = 0; i &lt; 5; i++) {
        printf(&quot;%d &quot;, arr[i]);  // 배열의 값을 출력
    }

    return 0;
}</code></pre><h3 id="2-다차원-배열">2. 다차원 배열</h3>
<h4 id="21-2차원-배열">2.1 2차원 배열</h4>
<p>2차원 배열은 행과 열을 가지며, 행렬처럼 데이터를 저장할 수 있습니다.</p>
<p>예시코드</p>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int arr[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    for (int i = 0; i &lt; 3; i++) {
        for (int j = 0; j &lt; 3; j++) {
            printf(&quot;%d &quot;, arr[i][j]);  // 2차원 배열 순회
        }
        printf(&quot;\n&quot;);
    }

    return 0;
}</code></pre><h4 id="22-다차원-배열의-메모리">2.2 다차원 배열의 메모리</h4>
<ul>
<li>다차원 배열은 연속적인 메모리 블록에 저장됩니다. 즉, 2D 배열의 요소들은 메모리 상에서 연속적으로 저장됩니다.</li>
</ul>
<h3 id="3-배열과-포인터">3. 배열과 포인터</h3>
<ul>
<li>3.1 배열 이름과 포인터
배열의 이름은 배열의 첫 번째 요소의 주소를 가리키는 포인터와 같습니다</li>
</ul>
<p>예시코드</p>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int arr[3] = {1, 2, 3};

    // 배열 이름은 첫 번째 요소의 주소를 가리킴
    printf(&quot;배열의 첫 번째 요소 주소: %p\n&quot;, arr);
    printf(&quot;배열의 첫 번째 요소: %d\n&quot;, *arr);  // 포인터를 사용한 접근

    return 0;
}</code></pre><h4 id="32-포인터로-배열-순회">3.2 포인터로 배열 순회</h4>
<p>포인터를 이용해 배열을 순회할 수도 있습니다.</p>
<p>예시코드</p>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int *ptr = arr;  // 배열의 첫 번째 요소를 가리키는 포인터

    for (int i = 0; i &lt; 5; i++) {
        printf(&quot;%d &quot;, *(ptr + i));  // 포인터를 이용한 배열 접근
    }

    return 0;
}</code></pre><h3 id="4-동적-배열">4. 동적 배열</h3>
<h4 id="41-동적-메모리-할당">4.1 동적 메모리 할당</h4>
<ul>
<li>동적 메모리 할당은 malloc() 또는 calloc() 함수를 사용하여 실행 시간에 배열의 크기를 동적으로 할당할 수 있습니다.</li>
<li>동적 할당은 프로그램 실행 중에 메모리를 효율적으로 사용할 수 있도록 해줍니다.</li>
</ul>
<p>예시코드(malloc)</p>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

int main() {
    int *arr;
    int n;

    printf(&quot;배열의 크기를 입력하세요: &quot;);
    scanf(&quot;%d&quot;, &amp;n);

    // 동적으로 메모리 할당
    arr = (int *)malloc(n * sizeof(int));

    if (arr == NULL) {
        printf(&quot;메모리 할당 실패\n&quot;);
        return 1;
    }

    // 배열 값 입력받기
    for (int i = 0; i &lt; n; i++) {
        printf(&quot;arr[%d] = &quot;, i);
        scanf(&quot;%d&quot;, &amp;arr[i]);
    }

    // 배열 출력
    for (int i = 0; i &lt; n; i++) {
        printf(&quot;%d &quot;, arr[i]);
    }

    // 동적으로 할당된 메모리 해제
    free(arr);

    return 0;
}
</code></pre><h4 id="42-동적-배열과-포인터">4.2 동적 배열과 포인터</h4>
<ul>
<li>동적 메모리 할당을 사용할 때, 메모리는 포인터 변수를 사용하여 관리합니다.</li>
<li>malloc() 함수는 지정된 크기만큼 메모리를 할당하고, 그 메모리의 첫 번째 주소를 반환합니다.</li>
<li>메모리 할당이 성공하면 그 주소를 포인터에 저장하고, 작업이 끝나면 free() 함수를 사용해 할당된 메모리를 해제합니다.</li>
</ul>
<h4 id="43-calloc-함수">4.3 calloc() 함수</h4>
<ul>
<li>malloc()과 비슷하지만, calloc()은 메모리를 초기화하며 할당합니다. 즉, 모든 값이 0으로 설정됩니다.</li>
</ul>
<p>예시코드</p>
<pre><code>arr = (int *)calloc(n, sizeof(int));  // 메모리 할당과 동시에 0으로 초기화
</code></pre><h4 id="44-realloc-함수">4.4 realloc() 함수</h4>
<ul>
<li>realloc() 함수는 동적으로 할당된 메모리 크기를 변경할 때 사용됩니다. malloc() 또는 calloc()으로 할당된 메모리 블록의 크기를 변경할 수 있습니다.</li>
<li>realloc()은 현재 할당된 메모리 크기를 변경하고, 그 결과로 새로 할당된 메모리 블록의 주소를 반환합니다.</li>
<li>만약 메모리 크기를 줄이는 경우, 반환된 주소는 원래 주소와 동일할 수 있습니다.</li>
<li>realloc()은 메모리 재할당이 실패할 경우 NULL을 반환하므로, 반환값을 체크하는 것이 중요합니다.</li>
</ul>
<p>예시코드(realloc)</p>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

int main() {
    int *arr;
    int n;

    printf(&quot;배열의 크기를 입력하세요: &quot;);
    scanf(&quot;%d&quot;, &amp;n);

    // 동적 메모리 할당
    arr = (int *)malloc(n * sizeof(int));

    if (arr == NULL) {
        printf(&quot;메모리 할당 실패\n&quot;);
        return 1;
    }

    // 배열 값 입력 받기
    for (int i = 0; i &lt; n; i++) {
        printf(&quot;arr[%d] = &quot;, i);
        scanf(&quot;%d&quot;, &amp;arr[i]);
    }

    // 배열 크기 확장 (크기를 2배로 증가)
    printf(&quot;배열 크기를 두 배로 확장합니다.\n&quot;);
    arr = (int *)realloc(arr, 2 * n * sizeof(int));  // 배열 크기 변경

    if (arr == NULL) {
        printf(&quot;메모리 재할당 실패\n&quot;);
        return 1;
    }

    // 새로운 배열의 값 입력 받기
    for (int i = n; i &lt; 2 * n; i++) {
        printf(&quot;arr[%d] = &quot;, i);
        scanf(&quot;%d&quot;, &amp;arr[i]);
    }

    // 배열 값 출력
    for (int i = 0; i &lt; 2 * n; i++) {
        printf(&quot;%d &quot;, arr[i]);
    }

    // 동적 메모리 해제
    free(arr);

    return 0;
}</code></pre><h3 id="5-추가내용">5. 추가내용</h3>
<h4 id="51-배열의-크기-계산-sizeof">5.1 배열의 크기 계산 (sizeof)</h4>
<ul>
<li>배열의 크기를 계산할 때는 sizeof 연산자를 사용하여 배열이 차지하는 메모리 크기를 구할 수 있습니다. 이를 통해 배열의 크기를 동적으로 처리할 수 있습니다.<pre><code>int arr[5];
printf(&quot;배열의 크기: %zu\n&quot;, sizeof(arr));  // 배열의 전체 크기
printf(&quot;배열의 원소 개수: %zu\n&quot;, sizeof(arr) / sizeof(arr[0]));  // 배열 원소의 개수</code></pre></li>
</ul>
<h4 id="52-배열을-함수로-전달하기">5.2 배열을 함수로 전달하기</h4>
<ul>
<li>배열을 함수에 전달할 때는 배열의 첫 번째 요소의 주소만 전달되므로, 배열의 크기를 함께 전달하거나 배열 크기 정보를 저장하는 방법을 사용해야 합니다.</li>
</ul>
<p>예시코드</p>
<pre><code>#include &lt;stdio.h&gt;

void printArray(int arr[], int size) {
    for (int i = 0; i &lt; size; i++) {
        printf(&quot;%d &quot;, arr[i]);
    }
    printf(&quot;\n&quot;);
}

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    printArray(arr, 5);  // 배열과 크기를 함수로 전달
    return 0;
}
</code></pre><h2 id="6문자열">6.문자열</h2>
<h3 id="6-문자열의-기본">6. 문자열의 기본</h3>
<h4 id="61-문자열-선언">6.1 문자열 선언</h4>
<ul>
<li>문자열은 char 배열로 선언합니다.</li>
<li>문자열은 마지막에 널 문자(&#39;\0&#39;)가 자동으로 추가되어 문자열의 끝을 나타냅니다.</li>
</ul>
<p>예시코드</p>
<pre><code>char str[6] = &quot;Hello&quot;;  // 배열 크기 6, 마지막 &#39;\0&#39; 포함</code></pre><ul>
<li>문자열의 크기는 널 문자 &#39;\0&#39;을 포함해야 합니다.</li>
</ul>
<h3 id="7-문자열-함수">7. 문자열 함수</h3>
<h4 id="71-strlen-함수">7.1 strlen() 함수</h4>
<ul>
<li>strlen() 함수는 문자열의 길이를 반환합니다.</li>
<li>널 문자(&#39;\0&#39;)는 제외하고 길이를 계산합니다.</li>
</ul>
<p>예시코드</p>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

int main() {
    char str[] = &quot;Hello&quot;;
    printf(&quot;문자열 길이: %zu\n&quot;, strlen(str));  // 5
    return 0;
}</code></pre><h4 id="72-strcmp-함수">7.2 strcmp() 함수</h4>
<ul>
<li>strcmp() 함수는 두 문자열을 비교하여 결과를 반환합니다.<ul>
<li>0: 두 문자열이 동일</li>
<li>음수: 첫 번째 문자열이 작음</li>
<li>양수: 첫 번째 문자열이 큼</li>
</ul>
</li>
</ul>
<p>예시코드</p>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

int main() {
    char str1[] = &quot;apple&quot;;
    char str2[] = &quot;banana&quot;;

    int result = strcmp(str1, str2);
    if (result == 0) {
        printf(&quot;두 문자열은 같습니다.\n&quot;);
    } else if (result &lt; 0) {
        printf(&quot;%s는 %s보다 작습니다.\n&quot;, str1, str2);
    } else {
        printf(&quot;%s는 %s보다 큽니다.\n&quot;, str1, str2);
    }

    return 0;
}</code></pre><h4 id="73-strcpy-함수">7.3 strcpy() 함수</h4>
<ul>
<li>strcpy() 함수는 하나의 문자열을 다른 문자열에 복사합니다.</li>
<li>대상 문자열의 크기를 확인하고, 이를 초과하는 복사는 방지해야 합니다.</li>
</ul>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

int main() {
    char str1[20], str2[] = &quot;Hello, World!&quot;;

    strcpy(str1, str2);  // str2를 str1에 복사
    printf(&quot;str1: %s\n&quot;, str1);  // &quot;Hello, World!&quot;

    return 0;
}</code></pre><h4 id="74-strcat-함수">7.4 strcat() 함수</h4>
<ul>
<li>strcat() 함수는 두 문자열을 이어붙이는 함수입니다.</li>
<li>대상 문자열에 문자열을 추가합니다.</li>
</ul>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

int main() {
    char str1[20] = &quot;Hello, &quot;;
    char str2[] = &quot;World!&quot;;

    strcat(str1, str2);  // str2를 str1 뒤에 이어 붙임
    printf(&quot;str1: %s\n&quot;, str1);  // &quot;Hello, World!&quot;

    return 0;
}</code></pre><h3 id="8-문자열-입력-및-출력">8. 문자열 입력 및 출력</h3>
<h3 id="81-gets-vs-fgets">8.1 gets() vs fgets()</h3>
<ul>
<li>gets()는 버퍼 오버플로우 위험이 있어 사용하지 않도록 권장합니다.</li>
<li>대신, fgets()를 사용하여 안전하게 문자열을 입력받습니다.</li>
</ul>
<p>예시코드(fgets)</p>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    char str[100];

    printf(&quot;문자열을 입력하세요: &quot;);
    fgets(str, sizeof(str), stdin);  // 안전하게 문자열 입력받기

    printf(&quot;입력한 문자열: %s\n&quot;, str);

    return 0;
}</code></pre><ul>
<li>fgets()는 버퍼 크기를 지정하여 입력을 제한하고, 입력의 끝에서 널 문자 \0을 자동으로 추가합니다.</li>
</ul>
<pre><code>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

int main() {
    char *str;
    int size = 50;

    str = (char *)malloc(size * sizeof(char));
    if (str == NULL) {
        printf(&quot;메모리 할당 실패\n&quot;);
        return 1;
    }

    // 문자열 입력 받기
    printf(&quot;문자열을 입력하세요: &quot;);
    fgets(str, size, stdin);

    // 문자열 크기 재할당
    size += 50;  // 새로운 크기
    str = (char *)realloc(str, size * sizeof(char));

    printf(&quot;입력한 문자열: %s\n&quot;, str);

    // 동적 메모리 해제
    free(str);

    return 0;
}
</code></pre><h4 id="82-fgets와-scanf의-차이점">8.2 fgets()와 scanf()의 차이점</h4>
<ul>
<li>fgets() 함수<ul>
<li>fgets()는 새로운 줄 문자(\n)도 포함하여 입력을 받습니다</li>
<li>널 문자(\0)를 자동으로 추가하여, 문자열의 끝을 나타냅니다.<pre><code>#include &lt;stdio.h&gt;
</code></pre></li>
</ul>
</li>
</ul>
<p>int main() {
    char str[100];</p>
<pre><code>// 사용자로부터 문자열을 입력받음
printf(&quot;문자열을 입력하세요: &quot;);
fgets(str, sizeof(str), stdin);  // 문자열을 한 줄 입력받기

printf(&quot;입력한 문자열: %s\n&quot;, str);

return 0;</code></pre><p>}</p>
<pre><code>
- scanf() 함수
  - scanf()는 기본적으로 공백, 탭, 새 줄 문자를 구분자로 사용하여 입력을 받습니다.
  - 즉, scanf()는 공백 문자(&#39; &#39;, &#39;\n&#39;, &#39;\t&#39;)를 입력 구분자로 간주하기 때문에 공백이 포함된 문자열을 입력받을 수 없습니다.
  - 문자열을 입력받을 때 scanf()는 공백을 구분자로 처리하기 때문에, 공백이 포함된 문자열을 제대로 처리할 수 없습니다.
</code></pre><p>#include &lt;stdio.h&gt;</p>
<p>int main() {
    char str[100];</p>
<pre><code>// 사용자로부터 문자열을 입력받음
printf(&quot;문자열을 입력하세요: &quot;);
scanf(&quot;%99[^\n]&quot;, str);  // 개행문자를 기준으로 입력받기

printf(&quot;입력한 문자열: %s\n&quot;, str);

return 0;</code></pre><p>}</p>
<pre><code>



### 9. 과제
&gt;
#### 1. 배열과 문자열을 이용한 회문 판별
- 문제 설명:
  - 사용자로부터 문자열을 입력받고, 해당 문자열이 회문(palindrome)인지 판별하는 프로그램을 작성하세요.
  - 회문이란, 앞에서 읽으나 뒤에서 읽으나 같은 문자열을 의미합니다.
  - 문자열은 공백을 제외하고 비교해야 하며, 대소문자는 구분하지 않습니다.
- 예시 입력</code></pre><p> madam</p>
<pre><code>- 예시 출력</code></pre><p>입력한 문자열은 회문입니다.</p>
<pre><code>
&gt;
#### 2. 문자열에서 중복 문자 제거
- 문제 설명:
  - 사용자로부터 문자열을 입력받고, 해당 문자열에서 중복된 문자를 제거하는 프로그램을 작성하세요.
  - 중복 문자가 있을 경우 첫 번째로 나타나는 문자만 남기고 나머지는 제거합니다.
- 예시 입력</code></pre><p> programming</p>
<pre><code>- 예시 출력</code></pre><p>progamin</p>
<pre><code>

&gt;
#### 3. 두 문자열 합치기 (동적 메모리 사용)
- 문제 설명:
  - 사용자로부터 두 문자열을 입력받고, 두 문자열을 합쳐서 새로운 문자열을 동적으로 할당한 메모리에 저장한 후 출력하는 프로그램을 작성하세요.
  - 동적 메모리 할당(malloc)을 사용하여 새로운 문자열을 저장하고, free()로 메모리를 해제합니다.
- 예시 입력</code></pre><p>Hello
World</p>
<pre><code>- 예시 출력</code></pre><p>HelloWorld</p>
<pre><code>
&gt;
#### 4. 
- 문제 설명:
  - 사용자에게 두 개의 문자열을 입력받고, 두 문자열을 합친 후 알파벳 순서대로 정렬한 뒤, 중복된 문자를 제거하는 프로그램을 작성하세요. 이때, 동적 메모리 할당을 사용하여 입력받은 문자열을 처리합니다. 그리고 동적 메모리 할당을 해제해야 합니다.
- 제약 조건:
  - 문자열의 길이는 최대 1000자입니다.
  - 입력 받은 두 문자열의 길이가 각각 1000자 이하입니다.
  - 입력 받은 문자열은 공백을 포함할 수 있으며, 공백도 문자로 취급합니다
- 예시 입력</code></pre><p>apple
banana</p>
<pre><code>- 예시 출력</code></pre><p>알파벳 순서대로 정렬된 문자열: abelnop
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C Programming Study_2]]></title>
            <link>https://velog.io/@hye0n_w00/C-Programming-Study2</link>
            <guid>https://velog.io/@hye0n_w00/C-Programming-Study2</guid>
            <pubDate>Tue, 25 Mar 2025 06:18:55 GMT</pubDate>
            <description><![CDATA[<h1 id="c-programming-study_2">C Programming Study_2</h1>
<h2 id="연산자--조건문">연산자 &amp; 조건문</h2>
<h3 id="1-연산자">1. 연산자</h3>
<p>1.1 산술 연산자
산술 연산자는 기본적인 수학 연산을 수행합니다.</p>
<blockquote>
</blockquote>
<p>+: 더하기
-: 빼기
*: 곱하기
/: 나누기
%: 나머지</p>
<blockquote>
</blockquote>
<h4 id="예시-코드">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int a = 10, b = 3;
    printf(&quot;덧셈: %d\n&quot;, a + b);
    printf(&quot;뺄셈: %d\n&quot;, a - b);
    printf(&quot;곱셈: %d\n&quot;, a * b);
    printf(&quot;나누기: %d\n&quot;, a / b);
    printf(&quot;나머지: %d\n&quot;, a % b);
    return 0;
}
</code></pre><p>1.2 관계 연산자
관계 연산자는 두 값을 비교하여 결과를 true(1) 또는 false(0)로 반환합니다.</p>
<blockquote>
</blockquote>
<p>==: 같음
!=: 다름</p>
<blockquote>
<p>: 큼
&lt;: 작음
=: 크거나 같음
&lt;=: 작거나 같음</p>
</blockquote>
<h4 id="예시-코드-1">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int a = 10, b = 5;
    printf(&quot;a == b: %d\n&quot;, a == b);
    printf(&quot;a != b: %d\n&quot;, a != b);
    printf(&quot;a &gt; b: %d\n&quot;, a &gt; b);
    return 0;
}
</code></pre><p>1.3 논리 연산자
논리 연산자는 주로 조건문에서 사용되며, 두 조건을 결합하거나 부정합니다.</p>
<blockquote>
</blockquote>
<p>&amp;&amp;: AND
||: OR
!: NOT</p>
<blockquote>
</blockquote>
<h4 id="예시-코드-2">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int a = 10, b = 5;
    if (a &gt; 5 &amp;&amp; b &lt; 10) {
        printf(&quot;둘 다 참입니다.\n&quot;);
    }
    if (a &gt; 5 || b &gt; 10) {
        printf(&quot;하나라도 참입니다.\n&quot;);
    }
    if (!(a &lt; 5)) {
        printf(&quot;a는 5보다 큽니다.\n&quot;);
    }
    return 0;
}
</code></pre><h3 id="2-조건문">2. 조건문</h3>
<p>2.1 if, else, else if 문</p>
<blockquote>
</blockquote>
<p>if: 조건이 참이면 코드 블록 실행
else: 조건이 거짓이면 코드 블록 실행
else if: 다른 조건들을 차례대로 확인</p>
<blockquote>
</blockquote>
<h4 id="예시-코드-3">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int score;
    printf(&quot;점수를 입력하세요: &quot;);
    scanf(&quot;%d&quot;, &amp;score);

    if (score &gt;= 90) {
        printf(&quot;A학점\n&quot;);
    } else if (score &gt;= 80) {
        printf(&quot;B학점\n&quot;);
    } else if (score &gt;= 70) {
        printf(&quot;C학점\n&quot;);
    } else {
        printf(&quot;F학점\n&quot;);
    }
    return 0;
}
</code></pre><p>2.2 switch 문
switch 문은 여러 개의 조건을 비교할 때 유용합니다.</p>
<h4 id="예시-코드-4">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int menu;
    printf(&quot;메뉴를 선택하세요 (1: 시작, 2: 종료): &quot;);
    scanf(&quot;%d&quot;, &amp;menu);

    switch(menu) {
        case 1:
            printf(&quot;시작합니다.\n&quot;);
            break;
        case 2:
            printf(&quot;종료합니다.\n&quot;);
            break;
        default:
            printf(&quot;잘못된 입력입니다.\n&quot;);
    }
    return 0;
}
</code></pre><h2 id="반복문">반복문</h2>
<h3 id="1-반복문의-종류">1. 반복문의 종류</h3>
<p>1.1 for 반복문
for 문은 반복 횟수가 정해져 있을 때 유용합니다.</p>
<pre><code>for (초기화; 조건; 증감) {
    // 반복할 코드
}
</code></pre><h4 id="예시-코드-5">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    for (int i = 1; i &lt;= 5; i++) {
        printf(&quot;i: %d\n&quot;, i);
    }
    return 0;
}
</code></pre><p>1.2 while 반복문
while 문은 조건이 참일 때 계속 반복합니다.</p>
<pre><code>while (조건) {
    // 반복할 코드
}
</code></pre><h4 id="예시-코드-6">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int i = 1;
    while (i &lt;= 5) {
        printf(&quot;i: %d\n&quot;, i);
        i++;
    }
    return 0;
}
</code></pre><p>1.3 do-while 반복문
do-while 문은 적어도 한 번은 실행된 후 조건을 확인하고 반복 여부를 결정합니다.</p>
<pre><code>do {
    // 반복할 코드
} while (조건);
</code></pre><h4 id="예시-코드-7">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    int i = 1;
    do {
        printf(&quot;i: %d\n&quot;, i);
        i++;
    } while (i &lt;= 5);
    return 0;
}
</code></pre><h3 id="중첩-반복문">중첩 반복문</h3>
<p>반복문 안에 또 다른 반복문을 사용하는 방법</p>
<h4 id="예시-코드-8">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    for (int i = 1; i &lt;= 3; i++) {
        for (int j = 1; j &lt;= 3; j++) {
            printf(&quot;i: %d, j: %d\n&quot;, i, j);
        }
    }
    return 0;
}
</code></pre><h3 id="3-break-continue-사용법">3. break, continue 사용법</h3>
<p>3.1 break
break는 반복문을 즉시 종료시킵니다.</p>
<h4 id="예시-코드-9">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    for (int i = 1; i &lt;= 10; i++) {
        if (i == 5) {
            break;  // i가 5일 때 반복문 종료
        }
        printf(&quot;i: %d\n&quot;, i);
    }
    return 0;
}
</code></pre><p>3.2 continue
continue는 반복문 내에서 나머지 코드를 건너뛰고 다음 반복을 시작합니다.</p>
<h4 id="예시-코드-10">예시 코드:</h4>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    for (int i = 1; i &lt;= 5; i++) {
        if (i == 3) {
            continue;  // i가 3일 때는 출력하지 않고 다음 반복으로 넘어감
        }
        printf(&quot;i: %d\n&quot;, i);
    }
    return 0;
}
</code></pre><h2 id="4-과제">4. 과제</h2>
<blockquote>
</blockquote>
<ol>
<li>점수 → 학점 계산기<blockquote>
</blockquote>
</li>
</ol>
<ul>
<li>사용자로부터 점수를 입력받고, 해당 점수에 맞는 학점을 출력하는 프로그램을 작성하세요.<blockquote>
</blockquote>
</li>
<li>점수는 0~100 사이의 값이어야 하며, 조건은 아래와 같습니다.<blockquote>
</blockquote>
</li>
<li>90점 이상: A</li>
<li>80점 이상 90점 미만: B</li>
<li>70점 이상 80점 미만: C</li>
<li>60점 이상 70점 미만: D</li>
<li>60점 미만: F<blockquote>
</blockquote>
</li>
</ul>
<blockquote>
</blockquote>
<p>2.구구단 출력 프로그램</p>
<blockquote>
</blockquote>
<ul>
<li>구구단을 출력하는 프로그램을 추가했습니다. 사용자가 원하는 구구단을 출력하는 방식으로 진행할 수 있습니다.<blockquote>
</blockquote>
</li>
</ul>
<blockquote>
</blockquote>
<ol start="3">
<li>별찍기 <blockquote>
</blockquote>
</li>
<li>1 별 피라미드 출력</li>
</ol>
<ul>
<li>주어진 숫자만큼의 행을 출력하는 별 피라미드를 작성하세요.<blockquote>
</blockquote>
</li>
<li>예를 들어, 입력 값이 5일 때 출력은 다음과 같습니다:<blockquote>
</blockquote>
<pre><code>  *
 ***
*****
*******</code></pre></li>
</ul>
<hr>
<pre><code>&gt;
3.2 가운데가 뚫린 피라미드
&gt;
- 역 피라미드 모양으로 별을 출력하는 코드입니다.
&gt;
- 예를 들어, 5행을 출력하려면 다음과 같습니다:
&gt;</code></pre><pre><code>*</code></pre><ul>
<li>*<ul>
<li>*</li>
<li>*</li>
</ul>
</li>
</ul>
<hr>
<pre><code>&gt;
3.3 모래시계 출력
- 주어진 숫자만큼의 행을 출력하는 모래시계 모양을 출력하세요.
&gt;
- 예를 들어, 입력 값이 5일 때 출력은 다음과 같습니다:
&gt;</code></pre><hr>
<hr>
<hr>
<hr>
<pre><code>*</code></pre><hr>
<hr>
<hr>
<hr>
<pre><code>&gt;

&gt;
4. 1부터 N까지의 숫자 합 구하기
&gt;
- 사용자로부터 정수 N을 입력받고, 1부터 N까지의 모든 짝수와 홀수의 합을 각각 구하는 프로그램을 작성하세요.
- 예를 들어, N이 10이면, 짝수의 합은 2 + 4 + 6 + 8 + 10, 홀수의 합은 1 + 3 + 5 + 7 + 9입니다.
&gt;

&gt;
5. 숫자 맞추기 게임
&gt;
- 컴퓨터가 1부터 100까지의 랜덤 숫자를 생성합니다.
- 사용자에게 숫자를 입력받고, 맞춘 숫자를 출력할 때까지 반복문을 사용하여 숫자를 맞추는 게임을 작성하세요.
- 숫자 맞추기 게임에서, 각 입력에 대해 &quot;작다&quot;, &quot;크다&quot;를 출력하여, 사용자가 목표 숫자를 찾도록 유도합니다.
- 목표 숫자는 컴퓨터가 랜덤으로 생성한 값이며, 반복문과 조건문을 사용해 숫자를 맞출 때까지 계속 입력을 받습니다.
&gt;
random에 관한 코드입니다.
&gt;</code></pre><p>#include &lt;stdlib.h&gt;
#include &lt;time.h&gt;
int main() {
    int randomNum, guess, attempts = 0;
    // 난수 생성 초기화
    srand(time(NULL));
    randomNum = rand() % 100 + 1;  // 1~100 사이의 랜덤 숫자 생성
    printf(&quot;1부터 100까지의 숫자 중 하나를 맞춰보세요.\n&quot;);
    return 0;
}</p>
<pre><code>&gt;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[C Programming Study_1]]></title>
            <link>https://velog.io/@hye0n_w00/C-Programming-Study1</link>
            <guid>https://velog.io/@hye0n_w00/C-Programming-Study1</guid>
            <pubDate>Wed, 19 Mar 2025 23:21:41 GMT</pubDate>
            <description><![CDATA[<h1 id="1intro">1.Intro</h1>
<h2 id="visual-studio-다운로드-및-사용-방법">Visual Studio 다운로드 및 사용 방법</h2>
<ol>
<li>Visual Studio 설치 홈페이지에 들어갑니다</li>
</ol>
<ul>
<li>visualstudio.microsoft.com/ko/</li>
</ul>
<ol start="2">
<li><p>[VisualStudio 다운로드]에 마우스를 이동한 후 [Community 2019]를 클릭하여 설치 파일을 다운로드합니다. 
<img src="https://velog.velcdn.com/images/hye0n_w00/post/8584bdbf-b0d0-4f3c-9522-77e96e8aab13/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hye0n_w00/post/eb0335d4-ced3-4925-b9ce-6cb3a74792fd/image.png" alt=""></p>
</li>
<li><p>설치가 완료되면 다음과 같은 창이 뜹니다. C++를 사용한 데스크톱 개발을 눌러주시고 설치를 눌러줍니다.</p>
</li>
<li><p>로그인 또는 나중에 로그인하기 이후 &#39;개발 설정&#39;, &#39;색 테마 선택&#39;을 선택 해주신 후 [Visual Studio 시작]을 클릭합니다.</p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hye0n_w00/post/64640fbf-99c1-4fc0-bf02-22a9050793b6/image.png" alt=""></p>
</li>
</ol>
<h2 id="visual-studio-사용-방법">Visual Studio 사용 방법</h2>
<h3 id="새-프로젝트-만들기">새 프로젝트 만들기</h3>
<ol>
<li>Visual Studio를 실행합니다.</li>
<li>&#39;새 프로젝트 만들기&#39;를 클릭합니다.</li>
<li>프로젝트 유형 선택 화면에서 &#39;C#&#39;을 선택합니다.</li>
<li>&#39;다음&#39;을 클릭합니다.</li>
<li>프로젝트 이름을 입력합니다 (예: &quot;HelloWorld&quot;).</li>
<li>프로젝트를 저장할 위치를 선택합니다.</li>
<li>&#39;만들기&#39;를 클릭합니다.</li>
</ol>
<h2 id="c언어-기본">C언어 기본</h2>
<h3 id="1-코드-기본-구조">1. 코드 기본 구조</h3>
<ul>
<li>#include &lt;stdio.h&gt;<ul>
<li>C언어에서 #include는 외부 라이브러리를 포함시키는 역할</li>
<li>stdio.h는 표준 입출력 함수들이 정의된 라이브러리 (예: printf, scanf)</li>
</ul>
</li>
</ul>
<pre><code>#include &lt;stdio.h&gt;

int main() {
    printf(&quot;Hello, World!\n&quot;);  // 출력문
    return 0;
}</code></pre><h3 id="2-main-함수">2. main 함수</h3>
<ul>
<li>모든 C 프로그램은 main() 함수에서 시작</li>
<li>void main(): C에서 가장 기본적인 시작 지점 (후에 int main()도 사용)</li>
</ul>
<h3 id="3-세미콜론">3. 세미콜론(;)</h3>
<ul>
<li>세미콜론은 C언어에서 명령문의 끝을 나타냄</li>
<li>예: printf(&quot;Hello, World!\n&quot;);</li>
</ul>
<h3 id="4-주석comments">4. 주석(Comments)</h3>
<ul>
<li>코드에 설명을 추가하는 방법</li>
<li>한 줄 주석: //</li>
<li>여러 줄 주석: /* */</li>
</ul>
<pre><code>// 한 줄 주석입니다.
printf(&quot;Hello&quot;);  // 이 부분은 출력문
/*
  여러 줄 주석
*/
</code></pre><h2 id="상수-const">상수 (Const)</h2>
<h3 id="상수란">상수란?</h3>
<ul>
<li><strong>상수(Constant)</strong>는 값이 한 번 설정되면 변경되지 않는 변수입니다.</li>
<li>코드에서 변하지 않는 값을 설정할 때 사용합니다.</li>
</ul>
<h3 id="상수-선언-방법">상수 선언 방법</h3>
<ul>
<li>const 키워드를 사용하여 선언합니다.<pre><code>#include &lt;stdio.h&gt;
</code></pre></li>
</ul>
<p>int main() {
    const int MAX = 100;  // 상수 MAX 선언
    printf(&quot;최대 값: %d\n&quot;, MAX);</p>
<pre><code>// MAX = 200;  // 오류 발생: 상수는 값을 변경할 수 없습니다.

return 0;</code></pre><p>}</p>
<pre><code>
## 변수와 변수 선언
### 1. 변수란?
- 변수는 데이터를 저장하는 공간
- 값이 변할 수 있는 메모리 공간

### 2. 변수 선언
- 변수 선언 시 데이터의 자료형을 먼저 적고 변수 이름을 지정
- 예시:
  - int x; (정수형 변수)
  - float y; (소수점 있는 숫자 저장)
  - char z; (문자 저장)

### 3. 변수 규칙
- **알파벳, 숫자, 밑줄(_)**로만 구성 가능
- 숫자는 첫 문자로 올 수 없음 (1x는 불가능)
- 예약어(예: int, if, while 등) 사용 불가
- 대소문자를 구분 (x와 X는 다름)
</code></pre><p>int age = 25;
float height = 175.5;
char grade = &#39;A&#39;;</p>
<pre><code>

## 자료형(Data Types)
1. 기본 자료형
- int: 정수형 (예: 1, 10, -5 등)
- float: 실수형 (소수점 숫자, 예: 3.14, -2.5 등)
- char: 문자형 (단일 문자, 예: &#39;a&#39;, &#39;B&#39;, &#39;3&#39; 등)
- double: 더 정밀한 실수형 (float보다 더 많은 자릿수를 제공)


2. 자료형 예시</code></pre><p>int number = 10;      // 정수형
float pi = 3.14;      // 실수형
char letter = &#39;A&#39;;    // 문자형
double precise = 3.1415926535;  // 고정 소수점 실수형</p>
<pre><code>
3. 자료형 크기
- int: 보통 4바이트
- float: 보통 4바이트
- char: 1바이트
- double: 8바이트

char &lt; int &lt; long &lt; float &lt; double &lt; long double</code></pre><p>void main() {
    printf(&quot;int : %d&quot;, sizeof(int));
    printf(&quot;float : %d&quot;, sizeof(float));
    printf(&quot;double : %d&quot;, sizeof(double));
    printf(&quot;char : %d&quot;, sizeof(char));
}</p>
<pre><code>
## 형변환(Type Casting)
### 형변환이란?
- 형변환은 하나의 데이터 타입을 다른 데이터 타입으로 변환하는 과정입니다.
- 암시적 형변환(자동 변환)과 명시적 형변환(강제 변환)으로 나눠집니다.

### 암시적 형변환 예시:
- C 컴파일러가 자동으로 타입을 변환할 때 발생하는 형변환입니다.</code></pre><p>int a = 5;
float b = 2.5;
float result = a + b;  // int와 float의 덧셈 -&gt; 자동으로 a가 float로 변환됨
printf(&quot;결과: %.2f\n&quot;, result);</p>
<pre><code>
### 명시적 형변환 (강제 형변환) 예시:
- 필요한 경우, 타입을 강제로 변환할 때 사용합니다. (타입)을 사용하여 형변환합니다.
</code></pre><p>float a = 3.14;
int b = (int)a;  // float을 int로 강제 형변환
printf(&quot;형변환 결과: %d\n&quot;, b);  // 출력: 3</p>
<pre><code>
## 입출력 함수

### 1. printf 함수
화면에 데이터를 출력하는 함수
예시:</code></pre><p>printf(&quot;Hello, World!\n&quot;);  // 문자열 출력
printf(&quot;Age: %d\n&quot;, age);    // 정수 출력
printf(&quot;Height: %.2f\n&quot;, height);  // 소수점 출력</p>
<pre><code>

### 2. scanf 함수
사용자로부터 입력을 받을 때 사용
예시:</code></pre><p>int age;
scanf(&quot;%d&quot;, &amp;age);  // 사용자로부터 정수 입력 받기</p>
<pre><code>%d: 정수 입력, %f: 실수 입력, %c: 문자 입력, %s: 문자열 입력

#### scanf 사용 시 주소에 대한 설명
- scanf 함수에서 입력받은 값을 저장할 변수의 주소를 넘겨야 합니다.
- 문자열을 입력받을 때는 이미 배열의 이름이 그 자체로 주소를 가리키므로, &amp;를 붙이지 않습니다.
- 하지만 정수형 변수는 주소를 명시적으로 넘겨줘야 하기 때문에 **&amp;**를 붙여야 합니다.

## 연산자 
### 1. 산술 연산자
- +, -, *, /, % </code></pre><p>int sum = 5 + 3;  // 덧셈
int diff = 5 - 3;  // 뺄셈
int product = 5 * 3;  // 곱셈
int quotient = 5 / 3;  // 나눗셈
int remainder = 5 % 3;  // 나머지</p>
<pre><code>
## 실습
### 실습 1: 나이와 이름 출력하기
- 사용자로부터 이름과 나이를 입력받고, 이를 출력하는 프로그램</code></pre><p>#include &lt;stdio.h&gt;</p>
<p>int main() {
    ???? name[50];  // 이름을 저장할 변수
    int age;        // 나이를 저장할 변수</p>
<pre><code>// 사용자로부터 이름과 나이 입력 받기
printf(&quot;이름을 입력하세요: &quot;);
scanf(&quot;%?&quot;, name);
printf(&quot;나이를 입력하세요: &quot;);
scanf(&quot;%?&quot;, &amp;age);

// 입력 받은 값 출력
printf(&quot;안녕하세요, %?님! 나이는 %?살입니다.\n&quot;, name, age);

return 0;</code></pre><p>}</p>
<pre><code>
### 실습 2: 간단한 계산기 만들기
- 두 숫자를 입력받고, 덧셈, 뺄셈, 곱셈, 나눗셈 결과를 출력하는 프로그램

</code></pre><p>#include &lt;stdio.h&gt;</p>
<p>int main() {
    float num1, num2;  // 두 숫자를 저장할 변수</p>
<pre><code>// 사용자로부터 두 숫자 입력 받기
printf(&quot;첫 번째 숫자를 입력하세요: &quot;);
scanf(&quot;%?&quot;, &amp;num1);
printf(&quot;두 번째 숫자를 입력하세요: &quot;);
scanf(&quot;%?&quot;, &amp;num2);

// 계산 및 출력
printf(&quot;덧셈 결과: %.?\n&quot;, num1 + num2);
printf(&quot;뺄셈 결과: %.?\n&quot;, num1 - num2);
printf(&quot;곱셈 결과: %.?\n&quot;, num1 * num2);

return 0;</code></pre><p>}</p>
<pre><code>
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[C Programming Study Curriculum]]></title>
            <link>https://velog.io/@hye0n_w00/C-Programming-Study-Curriculum</link>
            <guid>https://velog.io/@hye0n_w00/C-Programming-Study-Curriculum</guid>
            <pubDate>Tue, 11 Mar 2025 05:29:37 GMT</pubDate>
            <description><![CDATA[<h1 id="c프로그래밍-스터디-커리큘럼-10주">C프로그래밍 스터디 커리큘럼 (10주)</h1>
<h3 id="1주차-오리엔테이션--개발환경-세팅">1주차: 오리엔테이션 &amp; 개발환경 세팅</h3>
<p>스터디 소개 및 방향
C언어란? 왜 배울까?
컴파일러 설치 (Visual Studio)
Hello, World! 첫 코드 typing</p>
<h3 id="2주차-변수-자료형-입출력">2주차: 변수, 자료형, 입출력</h3>
<p>기본 자료형 (int, float, char, double)
printf, scanf 사용법
상수와 형변환
실습: 나이 입력 → 생년 계산</p>
<h3 id="3주차-연산자--조건문">3주차: 연산자 &amp; 조건문</h3>
<p>산술 / 관계 / 논리 연산자
if, else, else if, switch 문
실습: 점수 → 학점 계산기, 메뉴 고르기</p>
<h3 id="4주차-반복문-for-while-do-while">4주차: 반복문 (for, while, do-while)</h3>
<p>반복문의 구조와 차이
중첩 반복문
break, continue 사용법
실습: 구구단, 피라미드 출력, 숫자 합 구하기</p>
<h3 id="5주차-배열--문자열">5주차: 배열 &amp; 문자열</h3>
<p>1차원 배열 선언, 초기화, 순회
문자열 처리 (char 배열, gets, fgets, strlen, strcmp)
실습: 문자열 비교, 이름 입력 받아 출력</p>
<h3 id="6주차-함수">6주차: 함수</h3>
<p>함수 정의 / 선언 / 호출
매개변수, 반환값
지역변수와 전역변수
실습: 계산기 함수 분리, 최대값 찾기</p>
<h3 id="7주차-포인터-기초">7주차: 포인터 기초</h3>
<p>주소와 포인터 변수
*, &amp; 연산자
배열과 포인터의 관계
실습: 변수 값 바꾸기, 포인터로 배열 순회</p>
<h3 id="8주차-구조체">8주차: 구조체</h3>
<p>구조체 선언 및 초기화
구조체 배열
구조체 포인터
실습: 학생 정보(이름, 학번, 점수) 저장 및 출력</p>
<h3 id="9주차-파일-입출력">9주차: 파일 입출력</h3>
<p>fopen, fclose, fprintf, fscanf, fgets, fputs
텍스트 파일 읽고 쓰기
실습: 학생 점수 저장 파일 만들기, 불러오기</p>
<h3 id="10주차-최종-미니-프로젝트--코드-리뷰">10주차: 최종 미니 프로젝트 &amp; 코드 리뷰</h3>
<p>간단한 미니 프로젝트 예시:
학생 성적 관리 프로그램
ATM 기계 시뮬레이션
전화번호부
개인 or 팀 프로젝트로 구현
코드 발표 및 피드백</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Contextual Transformer Networks for Visual Recognition_3]]></title>
            <link>https://velog.io/@hye0n_w00/Contextual-Transformer-Networks-for-Visual-Recognition3</link>
            <guid>https://velog.io/@hye0n_w00/Contextual-Transformer-Networks-for-Visual-Recognition3</guid>
            <pubDate>Tue, 25 Feb 2025 00:41:53 GMT</pubDate>
            <description><![CDATA[<h1 id="contextual-transformer-networks-for-visual-recognition_3">Contextual Transformer Networks for Visual Recognition_3</h1>
<h2 id="4-experiments">4 EXPERIMENTS</h2>
<p>📌 ImageNet에서 CoTNet 이미지 인식 실험 정리</p>
<h3 id="1️⃣-실험-개요">1️⃣ 실험 개요</h3>
<p>✅ 데이터셋: ImageNet</p>
<ul>
<li>1,000개 클래스(Class)</li>
<li>128만 개 학습 이미지 (Training Images)</li>
<li>50,000개 검증 이미지 (Validation Images)</li>
<li>✅ 평가 방식: Top-1 &amp; Top-5 정확도 측정</li>
<li>Top-1 정확도: 모델이 예측한 1순위 클래스가 정답과 일치할 확률</li>
<li>Top-5 정확도: 모델이 예측한 상위 5개 클래스 중 하나라도 정답이 포함될 확률</li>
</ul>
<p>✅ 학습 방식: 기본 학습 설정(Default Setup) vs. 고급 학습 설정(Advanced Setup)</p>
<ul>
<li>기본 학습 (Default Training Setup) → 기존 CNN 모델(ResNet, ResNeXt, SENet 등)에서 사용한 전통적인 방식</li>
<li>고급 학습 (Advanced Training Setup) → 최신 백본(ResNeSt, EfficientNet 등)과의 공정한 비교를 위한 강화된 학습 설정</li>
</ul>
<h3 id="2️⃣-기본-학습-설정-default-training-setup">2️⃣ 기본 학습 설정 (Default Training Setup)</h3>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/ea671236-de34-4682-b3d3-d6129163bb06/image.png" alt=""></p>
<p>✅ 기존 CNN(ResNet, ResNeXt, SENet 등)에서 사용한 표준적인 학습 방식</p>
<ul>
<li>네트워크를 약 100 Epoch 동안 학습</li>
<li>기본적인 데이터 전처리(Preprocessing)만 수행</li>
</ul>
<p>✅ 기본 이미지 전처리 (Standard Image Preprocessing)</p>
<ol>
<li>입력 이미지는 224×224 크기로 크롭(Crop, 자르기)</li>
<li>랜덤 크롭(Random Crop) → 다양한 위치에서 자름</li>
<li>수평 뒤집기(Horizontal Flip) → 50% 확률로 좌우 반전
추가적인 데이터 증강(Augmentation) 없음</li>
</ol>
<p>✅ 기본 하이퍼파라미터 설정</p>
<ul>
<li>End-to-End 학습(처음부터 끝까지 한꺼번에 학습하는 방식)</li>
<li>SGD(확률적 경사 하강법) + 모멘텀 0.9 적용 (더 빠르고 안정적인 학습)<ul>
<li>Momentum: 학습할 때, 이전 업데이트 방향을 일부 유지하여 학습을 더 빠르고 부드럽게 진행하는 방법</li>
</ul>
</li>
<li>라벨 스무딩(Label Smoothing) 0.1 적용 (모델의 과적합 방지)</li>
<li>배치 크기(Batch Size) = 512<ul>
<li>8개의 GPU를 사용하여 병렬 학습(Parallel Training)</li>
<li>병렬 학습을 하면 더 큰 배치 크기를 사용할 수 있어 학습 속도 향상</li>
</ul>
</li>
</ul>
<p>✅ 학습률 스케줄링 (Learning Rate Scheduling)</p>
<ul>
<li>첫 5 Epoch 동안 학습률을 0에서 0.1× 256/B 까지 선형적으로 증가 (Warm-up)</li>
<li>이후 Cosine Schedule을 사용하여 점진적으로 학습률 감소</li>
</ul>
<p>✅ 지수 이동 평균 (Exponential Moving Average, EMA) 적용</p>
<ul>
<li>가중치 0.9999를 사용하여 학습 중 모델을 점진적으로 업데이트</li>
</ul>
<h3 id="3️⃣-고급-학습-설정-advanced-training-setup">3️⃣ 고급 학습 설정 (Advanced Training Setup)</h3>
<p>✅ 최신 백본(ResNeSt, EfficientNet, LambdaNetworks 등)과 공정한 비교를 위해 강화된 학습 설정 적용
✅ 350 Epoch까지 학습 (기본 설정 대비 3.5배 더 많은 Epoch 진행)
✅ 향상된 데이터 증강 &amp; 정규화 적용
✅ 추가된 데이터 증강 기법 (Data Augmentation)</p>
<ul>
<li>RandAugment → 다양한 데이터 변형 적용</li>
<li>Mixup → 두 개의 이미지를 섞어서 학습</li>
</ul>
<p>✅ 추가된 정규화 기법 (Regularization)</p>
<ul>
<li>Dropout 적용 → 일부 뉴런을 무작위로 비활성화하여 과적합 방지</li>
<li>DropConnect 적용 → 가중치 일부를 무작위로 비활성화하여 일반화 성능 향상</li>
</ul>
<h3 id="📌-최종-정리">📌 최종 정리</h3>
<p>✅ ImageNet 데이터셋에서 CoTNet을 학습하여 성능 검증
✅ 기본 학습(Default Setup)에서는 기존 CNN 모델과 동일한 조건에서 실험 진행 (100 Epoch, 기본 데이터 증강 적용)
✅ 고급 학습(Advanced Setup)에서는 최신 모델들과 비교하기 위해 350 Epoch + 추가적인 데이터 증강(Augmentation) 및 정규화(Regularization) 적용
✅ CoTNet은 기존 CNN뿐만 아니라 최신 백본 모델(ResNeSt, EfficientNet)과도 비교 가능하도록 학습됨</p>
<h2 id="performance-comparison-성능-비교">Performance Comparison (성능 비교)</h2>
<p> ImageNet 데이터셋에서 기존 최신 비전 백본들과 CoTNet을 비교한 성능 결과를 제시한다.
비교 실험은 두 가지 학습 설정(Default Training Setup, Advanced Training Setup)에서 수행되었다.</p>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/0964730a-53bc-46e7-8e1f-fb9185c4ba2e/image.png" alt=""></p>
<h3 id="기본-학습-설정-default-training-setup-성능-비교">기본 학습 설정 (Default Training Setup) 성능 비교</h3>
<p>✅ CoTNet-50 &amp; CoTNeXt-50은 기존 CNN 백본(ResNet-50, ResNeXt-50)보다 높은 정확도를 기록
✅ SE-ResNeXt-50, LambdaResNet-50과 같은 최신 백본보다도 성능이 우수
✅ FLOPs(연산량)가 적으면서도 높은 성능을 유지 → 효율적인 모델
✅ EMA 적용(CoTNeXt-50*) 시 성능이 더욱 향상됨</p>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/d28a1200-1ec6-466d-856c-60e00f68dc6f/image.png" alt=""></p>
<h3 id="table-4-고급-학습-설정-advanced-training-setup-성능-비교">Table 4: 고급 학습 설정 (Advanced Training Setup) 성능 비교</h3>
<p>✅ 고급 학습 설정에서도 CoTNet 계열(SE-CoTNetD-50, SE-CoTNetD-101)이 기존 ResNet, ResNeXt보다 성능이 우수
✅ EfficientNet, Swin Transformer와 같은 최신 백본과 비교해도 성능이 더 뛰어남
✅ Transformer 계열(Swin, XCiT)은 성능은 좋지만 연산량(FLOPs)이 높아 속도가 느림 → CoTNet은 연산 효율성까지 뛰어남</p>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/126fde70-5509-412d-a988-fa06278e2aaf/image.png" alt=""></p>
<h3 id="table-5-cot-블록의-문맥-정보-활용-방식에-따른-성능-비교">Table 5: CoT 블록의 문맥 정보 활용 방식에 따른 성능 비교</h3>
<p>✅ 정적 문맥 정보(Static Context)만 사용할 경우 정확도가 낮음
✅ 동적 문맥 정보(Dynamic Context)만 사용해도 성능이 향상됨
✅ 정적+동적 문맥 정보를 직접 결합(Concatenate)하는 방식이 가장 효과적
✅ 즉, CoT 블록에서 문맥 정보를 최적화하여 적용한 것이 CoTNet의 높은 성능을 만드는 핵심 요인!</p>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/8f98ed14-f5af-4c64-8280-a7649e023c17/image.png" alt=""></p>
<h3 id="fig-3-기본-학습-설정에서-추론-속도-vs-정확도-비교">Fig. 3: 기본 학습 설정에서 추론 속도 vs. 정확도 비교</h3>
<p>✅ SE-CoTNetD-50, SE-CoTNetD-101이 가장 높은 정확도를 기록하면서도 추론 시간이 빠름
✅ ResNet-50, ResNet-101은 추론 속도는 빠르지만 정확도가 낮음
✅ LambdaResNet, SAN19 등의 최신 모델보다도 CoTNet 계열의 성능이 우수</p>
<p>📌 즉, CoTNet 계열(SE-CoTNetD-50, SE-CoTNetD-101)이 기존 ResNet, ResNeXt보다 성능이 더 뛰어나고, 최신 백본(LambdaResNet, SAN19)보다도 높은 정확도를 기록함! 🚀</p>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/37b13682-355c-4109-96a2-9a960ca1cee3/image.png" alt=""></p>
<h3 id="fig-4-고급-학습-설정에서-추론-속도-vs-정확도-비교">Fig. 4: 고급 학습 설정에서 추론 속도 vs. 정확도 비교</h3>
<p>✅ SE-CoTNetD-152(320)가 최고 정확도(84.6%)를 기록하며 기존 모델들을 압도
✅ Swin Transformer, XCiT 등 최신 Transformer 모델보다도 정확도가 높음
✅ ResNet-50, ResNeXt-50 등 기존 CNN 모델들은 빠른 추론 속도를 보이지만 정확도가 낮음</p>
<p>📌 즉, CoTNet 계열이 기존 CNN보다 높은 성능을 기록하면서도 연산 효율성을 유지함! 🚀</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Contextual Transformer Networks for Visual Recognition_2]]></title>
            <link>https://velog.io/@hye0n_w00/Contextual-Transformer-Networks-for-Visual-Recognition1</link>
            <guid>https://velog.io/@hye0n_w00/Contextual-Transformer-Networks-for-Visual-Recognition1</guid>
            <pubDate>Mon, 17 Feb 2025 12:25:19 GMT</pubDate>
            <description><![CDATA[<h1 id="2-relatedwork">2. RELATEDWORK</h1>
<h2 id="📌-21-컨볼루션-네트워크convnet-정리">📌 2.1 컨볼루션 네트워크(ConvNet) 정리</h2>
<h3 id="1-convnet의-발전-과정">1. ConvNet의 발전 과정</h3>
<p>✅ 초기 모델들은 층을 깊게 쌓는 방식으로 성능을 향상</p>
<p>AlexNet (8층) → VGG (16층) → GoogleNet (22층) → ResNet (152층)
✅ 이후, ConvNet 아키텍처의 성능을 강화하기 위해 다양한 혁신적인 기법들 등장 </p>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/fb84b180-6aed-41ba-91fe-8baf32223607/image.png" alt=""></p>
<h2 id="📌-22-비전컴퓨터-비전에서의-자체-어텐션self-attention-in-vision-정리">📌 2.2 비전(컴퓨터 비전)에서의 자체-어텐션(Self-Attention in Vision) 정리</h2>
<h3 id="1-자체-어텐션이-비전에-적용된-배경">1. 자체-어텐션이 비전에 적용된 배경</h3>
<p>Transformer의 자체-어텐션(Self-Attention)이 NLP 분야에서 뛰어난 성과를 거두면서,
연구 커뮤니티는 이를 컴퓨터 비전(CV)에도 적용하려는 시도를 시작함.
자체-어텐션의 원래 목적: NLP에서 장거리 의존성(Long-Range Dependency)을 학습하는 것.
비전에서의 적용 방식: 이미지의 서로 다른 공간적 위치에 대해 자체-어텐션을 수행.</p>
<h3 id="2-비전에서의-자체-어텐션-적용-방식--연구-흐름">2. 비전에서의 자체-어텐션 적용 방식 &amp; 연구 흐름</h3>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/15f320bf-fd68-4f17-bd90-422837f65673/image.png" alt=""></p>
<h3 id="3-주요-결론">3. 주요 결론</h3>
<p>✅ 초기에는 CNN 기반 모델에 자체-어텐션을 추가하는 방식이 많았음.
✅ 점차적으로 순수 Transformer 기반 모델(ViT, DETR)이 등장하면서 CNN을 대체하는 연구로 발전.
✅ Swin Transformer, Twins Transformer, XCA와 같은 연구들은 연산량 최적화 &amp; 성능 향상을 목표로 개선됨.
✅ 최근에는 CNN 없이 Transformer만으로 강력한 시각적 표현 학습이 가능해지는 방향으로 연구가 진행 중.</p>
<h2 id="📌-23-summary">📌 2.3 Summary</h2>
<p>우리는 비전 백본(Vision Backbone) 아키텍처 설계를 위해 자체-어텐션(Self-Attention)을 탐구하는 것에 초점을 맞춘다.</p>
<p>대부분의 기존 기술들은 전통적인 자체-어텐션을 직접 활용하지만, 이웃한 키들 간의 풍부한 문맥(Context)을 명확하게 모델링하는 것을 간과한다.</p>
<p>반면, 우리의 Contextual Transformer(CoT) 블록은 키들 간의 문맥 추출(Context Mining)과 피처 맵(Feature Map) 상의 자체-어텐션(Self-Attention) 학습을 하나의 아키텍처로 통합하면서도, 적절한 파라미터 예산(Parameter Budget) 을 유지할 수 있도록 설계되었다.</p>
<h1 id="3-ourapproach">3. OURAPPROACH</h1>
<h2 id="1-cot-블록의-개념">1. CoT 블록의 개념</h2>
<ul>
<li><p>기존 Transformer의 자체-어텐션(Self-Attention) 은 각 쿼리(Query)와 개별 키(Key) 간의 관계만 고려함.</p>
</li>
<li><p>하지만 이웃한 키들 간의 문맥적 정보(Contextual Information)를 충분히 활용하지 못하는 한계가 있음.</p>
</li>
<li><p>CoT 블록은 자체-어텐션 학습을 강화하기 위해 문맥적 정보까지 반영하여 네트워크의 표현력을 향상시킴.</p>
<h3 id="cot-블록의-특징">CoT 블록의 특징</h3>
<p>✅ 기존 3×3 컨볼루션을 CoT 블록으로 대체하여 CNN 구조를 유지하면서도 Transformer의 장점을 활용 가능
✅ 이를 통해 Contextual Transformer Networks(CoTNet &amp; CoTNeXt) 를 제안</p>
</li>
<li><p>CoTNet: ResNet 기반</p>
</li>
<li><p>CoTNeXt: ResNeXt 기반 </p>
</li>
</ul>
<h2 id="31-multi-head-self-attention-in-vision-backbones">3.1 Multi-Head Self-Attention in Vision Backbones</h2>
<p>CoT 블록에서 확장 가능한 다중 헤드 자체-어텐션(Multi-Head Self-Attention) 을 사용하며, 기존 Transformer와 차별화된 문맥 정보(Contextual Information) 학습 방식을 적용한다.</p>
<h3 id="📌-1-self-attention-block-conventional-self-attention">📌 (1) Self-Attention Block (Conventional Self-Attention)</h3>
<p>✅ 기존 Transformer에서 사용되는 전형적인 자체-어텐션(Self-Attention) 방식
✅ 쿼리(Query), 키(Key), 값(Value)를 생성하고, Softmax를 이용하여 어텐션 행렬을 학습
✅ 전역(Global) 관계를 학습할 수 있지만, 키(Key)들 간의 문맥 정보(Context)는 활용하지 않음</p>
<h4 id="🔹-기존-self-attention의-연산-과정">🔹 기존 Self-Attention의 연산 과정</h4>
<ul>
<li><p>(1) 쿼리(Q), 키(K), 값(V) 변환</p>
<ul>
<li>입력 2D 피처 맵 X (크기: H×W×C)</li>
<li>1×1 컨볼루션을 사용하여 쿼리(Q), 키(K), 값(V)로 변환
<img src="https://velog.velcdn.com/images/hye0n_w00/post/c15f1859-c588-4997-8593-9495e955c953/image.png" alt=""></li>
</ul>
</li>
<li><p>(2) 지역적 관계 행렬(Local Relation Matrix) 생성
로컬 </p>
<ul>
<li>k×k 그리드에서 쿼리-키 간 관계를 측정</li>
<li>각 쿼리는 주변 키들과 비교하여 문맥 정보 학습
<img src="https://velog.velcdn.com/images/hye0n_w00/post/e7e623bb-dc78-44fe-ae50-7a3b8b000f68/image.png" alt=""><ul>
<li>Ch: 헤드(Head) 개수</li>
<li>⊛: 로컬 행렬 곱셈(Local Matrix Multiplication)</li>
<li>R(i): 각 공간적 위치 i 에서의 k×k×Ch 차원의 벡터</li>
</ul>
</li>
</ul>
</li>
<li><p>(3) 위치 정보(Position Information) 추가</p>
<ul>
<li>기존 Transformer에는 위치 정보가 부족 → 상대적 위치 임베딩(Relative Position Embedding) 추가</li>
<li>기존 관계 행렬에 위치 정보 P 를 추가하여 보강
<img src="https://velog.velcdn.com/images/hye0n_w00/post/35af2fa9-c9fb-4844-8562-ec54a2da1508/image.png" alt=""><ul>
<li>그리드 내 위치 정보 반영</li>
<li>모든 헤드(Ch)에서 공유됨</li>
</ul>
</li>
</ul>
</li>
<li><p>(4) 어텐션 가중치(Attention Weights) 계산</p>
<ul>
<li>어텐션 행렬을 얻기 위해 Softmax 정규화 수  행</li>
<li>k×k 크기의 로컬(Local) 어텐션 행렬 생성
<img src="https://velog.velcdn.com/images/hye0n_w00/post/4d4db46f-0125-4aeb-8e0c-6756f89a942a/image.png" alt=""></li>
</ul>
</li>
<li><p>(5) 최종 출력 계산</p>
<ul>
<li>값(Value)V 와 어텐션 행렬 A 를 곱하여 최종 출력 생성
<img src="https://velog.velcdn.com/images/hye0n_w00/post/831f450a-7bd6-4406-ad4a-09825b7dbb0c/image.png" alt=""><ul>
<li>각 헤드의 결과를 종합하여 최종 출력 Y 를 생성</li>
<li>최종 출력 Y 는 모든 헤드에서 집계된 피처 맵을 연결(Concatenation)하여 생성</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="📌-2-cot-block-contextual-transformer-block">📌 (2) CoT Block (Contextual Transformer Block)</h3>
<p>✅ Self-Attention을 개선하여, 키(Key)들 간의 문맥 정보(Context)를 활용할 수 있도록 설계된 블록
✅ 키(Key) 자체를 문맥화(Contextualized)하여 활용하며, Softmax 없이 어텐션 행렬을 학습
✅ CNN과 Transformer의 장점을 결합한 하이브리드 모델</p>
<h4 id="🔹-cot-블록의-연산-과정">🔹 CoT 블록의 연산 과정</h4>
<ul>
<li><p>(1) 정적 문맥 표현(Static Context Representation) K1생성</p>
<ul>
<li>입력 2D 피처 맵 X (크기: H×W×C)</li>
<li>기존 Self-Attention에서는 1×1 컨볼루션을 사용하여 키(Key)를 변환하지만,</li>
<li>CoT 블록에서는 k×k 컨볼루션을 사용하여 주변 문맥을 포함한 키(Key) K1을 생성</li>
<li>K1은 한 번 학습되면 변하지 않는 &quot;정적 문맥 표현&quot;</li>
</ul>
</li>
<li><p>(2) 어텐션 행렬 A 생성</p>
<ul>
<li>쿼리(Query)와 문맥화된 키(Key) K1를 결합(Concat)하여 어텐션 학습
<img src="https://velog.velcdn.com/images/hye0n_w00/post/3e830c5f-9d2c-4096-bd37-1f0f6f9c8dfa/image.png" alt=""><ul>
<li>첫 번째 컨볼루션 𝑊𝑢는 ReLU 활성화 함수 적용 (비선형 변환)</li>
<li>두 번째 컨볼루션 𝑊𝑑는 활성화 함수 없이 출력 (최종 어텐션 행렬 생성)</li>
<li>Softmax 없이 자체 학습</li>
</ul>
</li>
</ul>
</li>
<li><p>(3) 동적 문맥 표현(Dynamic Context Representation) 𝐾2생성</p>
<ul>
<li>문맥화된 어텐션 행렬 𝐴를 이용하여 값(Value) 𝑉를 종합(Aggregation)
<img src="https://velog.velcdn.com/images/hye0n_w00/post/6156c7df-a674-47ae-bf40-aa8e0a4fc5b1/image.png" alt=""><ul>
<li>기존 Self-Attention과 다르게, 어텐션 행렬에 문맥 정보가 포함됨</li>
</ul>
</li>
</ul>
</li>
<li><p>(4) 최종 출력 𝑌생성</p>
<ul>
<li>정적 문맥 𝐾1과 동적 문맥 𝐾2를 결합하여 최종 출력 생성</li>
<li>글로벌 평균 풀링(GAP)과 소프트 어텐션을 활용하여 최적의 출력을 생성</li>
</ul>
</li>
</ul>
<h2 id="구조적-차이-self-attention-vs-cot-block">구조적 차이: Self-Attention vs. CoT Block</h2>
<h3 id="a-기존-self-attention-block-conventional-self-attention">(a) 기존 Self-Attention Block (Conventional Self-Attention)</h3>
<ul>
<li><p>쿼리(Query), 키(Key), 값(Value) 생성 → 1×1 컨볼루션 사용</p>
</li>
<li><p>쿼리-키(Q⋅K^T ) 비교 후 Softmax 적용</p>
</li>
<li><p>값(Value) V 와 어텐션 행렬 곱해서 최종 출력 생성</p>
</li>
<li><p>기존 CNN과 다르게 전역(전체) 관계 학습 가능</p>
</li>
<li><p>하지만 키(Key)들 간의 문맥 정보를 학습하지 않음!</p>
</li>
<li><p>📌 한계:
 ❌ 각 키(Key)는 독립적으로 사용됨 → 주변 문맥 정보 반영 ❌
❌ Softmax 연산이 필요 → 연산량 증가
❌ CNN처럼 지역적(Local) 관계를 반영하는 능력이 부족
Self-Attention에서는 &quot;Position + Query&quot; 연산을 통해 위치 정보를 보완하지만, 여전히 키(Key)들 간의 문맥 정보(Context)는 학습하지 않음!</p>
</li>
</ul>
<h3 id="b-cot-block-contextual-transformer-block">(b) CoT Block (Contextual Transformer Block)</h3>
<ul>
<li><p>쿼리(Query), 키(Key), 값(Value) 생성 → 기존과 다르게 키(Key) 변환 시 k×k 컨볼루션 사용</p>
</li>
<li><p>쿼리(Query)와 키(Key) 결합 (Concat) 후 1×1 컨볼루션을 거쳐 어텐션 행렬 생성</p>
</li>
<li><p>Softmax 없이 문맥 기반 학습을 수행</p>
</li>
<li><p>어텐션 행렬 δ 와 값(Value) V 곱한 후, 원래 키(Key) 정보까지 반영하여 최종 Fusion 수행</p>
</li>
<li><p>📌 개선점:
✅ 키(Key)들 간의 문맥 정보 학습 가능 → 기존 Self-Attention 대비 문맥 반영 O
✅ Softmax 연산 없이 자체 학습 가능 → 연산량 감소
✅ CNN과 유사하게 지역적(Local) 관계를 학습 → 더 자연스러운 특징 표현 가능</p>
</li>
</ul>
<h2 id="contextual-transformer-networks-문맥적-transformer-네트워크-정리">Contextual Transformer Networks (문맥적 Transformer 네트워크) 정리</h2>
<p>✅ CoT 블록은 기존 CNN의 표준 컨볼루션을 대체할 수 있는 Self-Attention 기반의 빌딩 블록
✅ 이를 활용하여 ResNet 및 ResNeXt 같은 기존 CNN 모델을 문맥화된(Self-Attention 기반) 비전 백본으로 강화 가능
✅ CoT 블록을 적용하더라도, 전체적인 파라미터 수와 FLOPs(연산량)를 크게 증가시키지 않도록 설계됨
✅ Table 1 &amp; Table 2에서 ResNet-50과 ResNeXt-50을 기반으로 한 CoTNet-50 및 CoTNeXt-50의 구조를 확인할 수 있음
✅ CoTNet은 ResNet-101과 같은 더 깊은 네트워크에도 확장 가능</p>
<h3 id="📌-resnet-50-vs-cotnet-50--resnext-50-vs-cotnext-50-표-정리-및-비교-분석">📌 ResNet-50 vs. CoTNet-50 &amp; ResNeXt-50 vs. CoTNeXt-50 (표 정리 및 비교 분석)</h3>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/d525bf58-55d6-4ae1-ae8f-0f15c60a626f/image.png" alt=""></p>
<h4 id="📌-1-table-1-resnet-50-vs-cotnet-50">📌 1. Table 1: ResNet-50 vs. CoTNet-50</h4>
<ul>
<li>기존 ResNet-50의 모든 3×3 컨볼루션(스테이지 res2, res3, res4, res5)을 CoT 블록으로 직접 교체하여 구축됨.</li>
<li>CoT 블록은 기존 3×3 컨볼루션과 연산량(Computational Cost)이 유사하므로, CoTNet-50은 ResNet-50과 거의 동일한(혹은 약간 더 적은) 파라미터 수 및 FLOPs를 가짐.</li>
<li>즉, 기존 ResNet-50보다 연산량은 거의 동일하면서도, 문맥 정보를 활용한 성능 향상을 기대할 수 있음!</li>
</ul>
<h4 id="📌-2-table-2-resnext-50-vs-cotnext-50">📌 2. Table 2: ResNeXt-50 vs. CoTNeXt-50</h4>
<ul>
<li>ResNeXt-50의 그룹 컨볼루션(Grouped Convolutions)에서 모든 3×3 컨볼루션을 CoT 블록으로 교체하여 구축됨.</li>
<li>그룹 컨볼루션(Grouped Convolution)의 특징:<ul>
<li>그룹 개수(C 값)가 증가할수록, 각 컨볼루션 커널의 깊이(depth)가 감소 → 연산량이 줄어듦.</li>
<li>ResNeXt-50에서는 그룹 컨볼루션을 활용하여 계산 비용을 C 배 줄일 수 있음.</li>
</ul>
</li>
<li>이를 감안하여, CoTNeXt-50에서는 입력 특징 맵의 크기를 32×4d에서 2×48d로 조정하여,
ResNeXt-50과 유사한 수준의 파라미터 수 및 FLOPs를 유지하도록 설계됨.</li>
</ul>
<h2 id="connections-with-previous-vision-backbones">Connections With Previous Vision Backbones</h2>
<h3 id="blueprint-separable-convolution">Blueprint Separable Convolution</h3>
<p>✅ 1×1 포인트와이즈 + k×k 깊이별 컨볼루션을 활용하여 채널 축소
✅ CoT 블록과 유사한 구조를 가짐
✅ 채널 공유 전략(Channel Sharing Strategy)을 사용하여 효율성 증가</p>
<h3 id="dynamic-region-aware-convolution">Dynamic Region-Aware Convolution</h3>
<p>✅ 1×1 컨볼루션을 사용하여 지역적 특징을 학습
✅ CoT 블록과 유사하게 로컬 어텐션 행렬을 동적으로 생성
✅ 하지만 CoT 블록은 문맥화된 키(Contextualized Key)와 쿼리(Query) 간의 상호작용을 더 적극적으로 활용</p>
<h3 id="bottleneck-transformer">Bottleneck Transformer</h3>
<p>✅ ResNet 기반 CNN에서 Self-Attention을 추가하는 구조
✅ 하지만 연산량이 높아, 네트워크 일부(최종 세 개의 3×3 컨볼루션)만 Transformer 블록으로 변경 가능
✅ 반면 CoT 블록은 네트워크 전체에서 3×3 컨볼루션을 대체 가능
✅ CoT 블록은 입력 키(Key) 간의 문맥을 활용하여 Self-Attention 학습을 더욱 강화</p>
<p><img src="https://velog.velcdn.com/images/hye0n_w00/post/8008b149-c44e-4664-ae40-6303c5042897/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>