<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>son-dan-ha.log</title>
        <link>https://velog.io/</link>
        <description>hustle</description>
        <lastBuildDate>Fri, 20 Mar 2026 11:43:43 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>son-dan-ha.log</title>
            <url>https://velog.velcdn.com/images/son-dan-ha/profile/6137db7d-5102-4a97-acf4-c5ea381a2767/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. son-dan-ha.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/son-dan-ha" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[프로젝트 경험을 바탕으로 다시 짠 학습 방향과 생존 전략]]></title>
            <link>https://velog.io/@son-dan-ha/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B2%BD%ED%97%98%EC%9D%84-%EB%B0%94%ED%83%95%EC%9C%BC%EB%A1%9C-%EB%8B%A4%EC%8B%9C-%EC%A7%A0-%ED%95%99%EC%8A%B5-%EB%B0%A9%ED%96%A5%EA%B3%BC-%EC%83%9D%EC%A1%B4-%EC%A0%84%EB%9E%B5</link>
            <guid>https://velog.io/@son-dan-ha/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B2%BD%ED%97%98%EC%9D%84-%EB%B0%94%ED%83%95%EC%9C%BC%EB%A1%9C-%EB%8B%A4%EC%8B%9C-%EC%A7%A0-%ED%95%99%EC%8A%B5-%EB%B0%A9%ED%96%A5%EA%B3%BC-%EC%83%9D%EC%A1%B4-%EC%A0%84%EB%9E%B5</guid>
            <pubDate>Fri, 20 Mar 2026 11:43:43 GMT</pubDate>
            <description><![CDATA[<p>최근 기술 뉴스들을 접하며 <strong>&#39;명세(Spec)&#39;의 중요성과 AI 에이전트 시대의 개발 방식</strong>에 대해 깊이 고민하게 되었다. ai의 지속적인 발전으로 다양한 ai의 도움을 받아 웹 개발을 이어오고 있지만, 효율적인 결과물 뒤에 숨은 본질적인 한계와 마주하는 지점들이 생겨났다. </p>
<p>그동안 진행했던 여러 프로젝트의 <strong>성패를 복기</strong>해 보니, 결국 중요한 것은 코드를 짜는 행위 그 자체보다 <strong>문제를 정의하고 구조화하는 능력</strong>이었다. 급변하는 환경 속에서 단순한 도구 활용을 넘어, 나만의 경쟁력을 확보하기 위한 <u>학습 방향과 생존 전략</u>을 정리해 본다.</p>
<br>

<hr>
<h2 id="1-바이브-코딩의-편리함과-그-이면의-한계">1. 바이브 코딩의 편리함과 그 이면의 한계</h2>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/c9b4c525-6881-4dcc-96eb-75bc4125307b/image.png" alt=""></p>
<p>최근 Gemini(Antigravity)를 활용해 웹 개발을 진행하며 이른바 <strong>&#39;바이브 코딩(Vibe Coding)&#39;</strong> 방식을 유지해 왔다. 자연어 명령만으로 즉각적인 결과물을 도출하는 경험은 비전공자로서 개발 진입 장벽을 낮추는 데 효과적이었다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/a1b62ce2-ba8b-4831-a214-8cc11de10a0f/image.png" alt=""></p>
<p>하지만 프로젝트가 계속 진행될수록 <strong>머릿속의 구현 방향</strong>을 AI가 이해할 수 있는 &#39;<strong>명확한 언어</strong>&#39;나 &#39;<strong>명세(Spec)</strong>&#39;로 <u>치환하지 못하는</u> 상황이 잦아졌다. 내가 선택한 <strong>코드 구조의 타당성</strong>을 스스로 <u>검증할 능력이 부족</u>하다는 점은, AI 기술이 발전할수록 오히려 도태될 수 있다는 불안감으로 이어졌다.</p>
<p><br> <br> </p>
<hr>
<h2 id="2-프로젝트-경험으로-재확인한-도메인-지식의-가치">2. 프로젝트 경험으로 재확인한 도메인 지식의 가치</h2>
<p>이러한 혼란 속에서 이정표가 된 것은 과거 프로젝트들의 <strong>상반된 결과</strong>였다. 현재 진행 중인 학원 웹 개발 프로젝트는 <strong>실제 현장</strong>의 비즈니스 프로세스를 깊이 파악한 덕분에 <strong>개발 목표가 명확</strong>했고 AI와의 협업 효율도 높았다.</p>
<p>반면, <a href="https://github.com/Sondanha/ai-review-sales-advisor">신한은행 카드 데이터 공모전</a> 당시에는 자영업 생태계라는 &#39;<strong>도메인</strong>&#39;에 대한 이해가 부족한 상태에서 기술로만 접근하려다 보니 <u>기획의 부실함</u>을 피할 수 없었다. </p>
<p><a href="https://github.com/Sondanha/Phishing-Insight">보이스피싱 방지 프로젝트</a> 역시 해당 범죄 패턴과 <strong>AI 기술의 메커니즘</strong>을 꿰뚫어 보지 못하면 <u>실질적인 개발이 불가능함</u>을 체감하게 했다.</p>
<p><br> <br> </p>
<hr>
<h2 id="3-기술과-도메인의-결합을-위한-3가지-학습-로드맵">3. 기술과 도메인의 결합을 위한 3가지 학습 로드맵</h2>
<p>개발이란 결국 도메인 지식과 기술적 이해도가 맞물려 돌아가는 과정이다. 전공자 수준의 기초 문법 암기에 매몰되기보다, <strong>생산성을 유지</strong>하며 <strong>전문성을 확보</strong>하기 위해 다음과 같은 세 가지 학습 영역을 설정했다.</p>
<ul>
<li><p><strong>AI 기술 이론:</strong> 새로운 모델이나 논문(AI 분야)이 발표되었을 때 그 원리를 이해하고 흐름을 따라갈 수 있는 수준의 독해력을 갖춘다.</p>
</li>
<li><p><strong>엔지니어링 메커니즘:</strong> 코드는 AI가 작성하더라도 전체 서비스의 흐름과 데이터 구조는 직접 설계할 수 있도록 시스템 아키텍처를 공부한다.</p>
</li>
<li><p><strong>도메인 전문성:</strong> 경영학 전공을 살려 &#39;금융&#39; 분야를 핵심 도메인으로 정했다. 금융 비즈니스의 문제를 AI가 해결 가능한 명세로 전환하는 능력을 키우는 것이 목표다.</p>
</li>
</ul>
<p><br> <br> </p>
<hr>
<h2 id="4-마치며">4. 마치며</h2>
<h3 id="환경-변화에-적응하는-개발자가-되고자">환경 변화에 적응하는 개발자가 되고자...</h3>
<p>지금의 &#39;바이브 코딩&#39; 역시 언젠가 지나갈 트렌드일지 모른다. 결국 나에게 중요한 목표는 특정 도구에 의존하는 것이 아니라, 급변하는 외부 환경 속에서 새로운 기회를 발견하고 그에 맞춰 적응할 수 있는 개발자가 되는 것이다.</p>
<p>단순히 코드를 생성하는 수준을 넘어, 도메인에 대한 깊은 이해와 설계 능력을 바탕으로 실질적인 목적을 달성하고 수익을 창출하는 개발자가 되고자 한다. </p>
<p>그 과정에서 겪는 시행착오와 논리적인 사고의 흐름을 해당 시리즈에 기록하며, 앞으로의 변화에도 유연하게 대처하는 사람이 되고 싶다.</p>
<p><br> <br> </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Improved Balanced Classification with Theoretically Grounded Loss Functions 논문리뷰]]></title>
            <link>https://velog.io/@son-dan-ha/Improved-Balanced-Classification-with-Theoretically-Grounded-Loss-Functions-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0</link>
            <guid>https://velog.io/@son-dan-ha/Improved-Balanced-Classification-with-Theoretically-Grounded-Loss-Functions-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0</guid>
            <pubDate>Sun, 15 Feb 2026 07:22:38 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/4ed2e3c5-7ef0-4814-a900-1024489e788a/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/5ca83ec5-a88d-4d66-a883-a99b198049a0/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/5021a858-8c44-469e-8390-5f57832b3784/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/7213fd46-317d-4c63-8a5c-2017f80e8d2b/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/cf5e688d-8f37-4e18-8358-bd49a72350f1/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/861d3d52-dd70-4e7b-b4b2-f6d382949a02/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/fbcc9cc2-161a-49dd-8c9a-177893b0c7f2/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/cb6f80fb-9d96-4207-834e-c86ae502bbc1/image.jpg" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Attention Is All You Need 논문리뷰]]></title>
            <link>https://velog.io/@son-dan-ha/Attention-Is-All-You-Need-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0</link>
            <guid>https://velog.io/@son-dan-ha/Attention-Is-All-You-Need-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0</guid>
            <pubDate>Mon, 02 Feb 2026 13:31:00 GMT</pubDate>
            <description><![CDATA[<h1 id="들어가며">들어가며...</h1>
<p>오늘날 llm의 기준이 되는 트랜스포머에 대해 알아보자. </p>
<p><br><br></p>
<hr>
<h1 id="1-rnns과-cnns의-한계">1. RNNs과 CNNs의 한계</h1>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/77cd5a40-ebbe-434a-a4b1-a451d5507389/image.jpg" alt=""></p>
<p><br><br></p>
<h1 id="2-attention-매커니즘">2. Attention 매커니즘</h1>
<h2 id="2-1-단어-임베딩과-문맥">2-1. 단어 임베딩과 문맥</h2>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/370cb3d5-adc2-4f26-9d33-1461595e869b/image.jpg" alt=""></p>
<h2 id="2-2-토큰화와-패딩">2-2. 토큰화와 패딩</h2>
<p><br><br></p>
<h2 id="2-3-멀티헤드-어텐션">2-3. 멀티헤드 어텐션</h2>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/f364d4b5-0763-44a9-b457-60e4de30a8cc/image.jpg" alt=""></p>
<p><br><br></p>
<h2 id="2-4-셀프-어텐션">2-4. 셀프 어텐션</h2>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/a864a6c1-98b5-4c49-b769-2b0e71a9dee9/image.jpg" alt=""></p>
<p><br><br></p>
<h2 id="2-5-헤드-결합">2-5. 헤드 결합</h2>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/c72386d7-9534-4670-a2a1-3b795b75189a/image.jpg" alt=""></p>
<p><br><br></p>
<h2 id="2-6-쿼리-키-값">2-6. 쿼리, 키, 값</h2>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/990bb906-ac24-4fe4-9480-682b2f7a9282/image.jpg" alt=""></p>
<p><br><br></p>
<h2 id="2-7-어텐션-스코어">2-7. 어텐션 스코어</h2>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/a28a4d69-e86e-4be9-80b9-635b1cff4abb/image.jpg" alt=""></p>
<h2 id="2-8-문장-길이와-배치-처리">2-8. 문장 길이와 배치 처리</h2>
<p><br><br></p>
<h1 id="3-트랜스포머-아키텍쳐">3. 트랜스포머 아키텍쳐</h1>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/50c6f405-4bee-48d8-868b-0382aaf33477/image.jpg" alt=""></p>
<p><br><br></p>
<h1 id="4-포지셔널-인코딩">4. 포지셔널 인코딩</h1>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/98d313b7-65eb-451b-affc-51739c9dcfe2/image.jpg" alt=""></p>
<p><br><br></p>
<h1 id="5-잔차연결과-레이어-정규화">5. 잔차연결과 레이어 정규화</h1>
<h2 id="5-1-레이어-정규화">5-1. 레이어 정규화</h2>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/afb34178-f1d0-4d1b-9394-47691ca1d39a/image.jpg" alt=""></p>
<p><br><br></p>
<h2 id="5-2-피드포워드-네트워크">5-2. 피드포워드 네트워크</h2>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/6cc3cd37-fcfb-451d-a04f-51ba6e99086e/image.jpg" alt=""></p>
<h2 id="5-3-잔차-연결">5-3. 잔차 연결</h2>
<p><br><br><br><br></p>
<hr>
<h1 id="마치며">마치며...</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[정렬 문제 풀이]]></title>
            <link>https://velog.io/@son-dan-ha/%EC%A0%95%EB%A0%AC-%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@son-dan-ha/%EC%A0%95%EB%A0%AC-%EB%AC%B8%EC%A0%9C-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Mon, 26 Jan 2026 13:26:21 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42746">가장 큰 수</a></p>
<blockquote>
<ul>
<li>0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수 </li>
</ul>
</blockquote>
<ul>
<li>주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 수는 6210</li>
<li>0 또는 양의 정수가 담긴 배열 numbers가 매개변수로 주어질 때, 순서를 재배치하여 만들 수 있는 가장 큰 수를 문자열로 바꾸어 return</li>
</ul>
<br>


<h2 id="첫-번째-풀이">첫 번째 풀이</h2>
<pre><code class="language-python">def solution(numbers):
    N = len(numbers)
    str_list = [str(i) for i in numbers]
    str_list.sort(reverse=True)

    for i, s in enumerate(str_list):
        if i == N-1:
            break
        if str_list[i+1] in s and len(str_list[i+1])&lt;len(s):
            if int(s[len(str_list[i+1]):][0]) &lt; int(str_list[i+1][0]):
                    str_list[i], str_list[i+1] = str_list[i+1], str_list[i]

    return &#39;&#39;.join(str_list)</code></pre>
<p>런타임 에러가 발생했다. 추측하기로는 <code>str_list[i], str_list[i+1] = str_list[i+1], str_list[i]</code> 해당 문법의 시간복잡도가 문제라고 생각이 들었다. </p>
<br>

<h2 id="두-번째-풀이">두 번째 풀이</h2>
<pre><code class="language-python">from collections import deque

def solution(numbers):
    numbers.sort()
    str_list = [str(i) for i in numbers]
    match_digits = []
    for s in str_list:
        if len(s) == 1: 
            match_digits.append((s+&quot;000&quot;, s))
        elif len(s) == 2: 
            match_digits.append((s+&quot;00&quot;, s))
        elif len(s) == 3: 
            match_digits.append((s+&quot;0&quot;, s))

    m = sorted(match_digits, key=lambda x :x[0], reverse=True)
    return &#39;&#39;.join([i[1] for i in m])</code></pre>
<pre><code class="language-python">import functools

def cmpare(a, b):
    t1 = str(a) + str(b)
    t2 = str(b) + str(a)
    return (int(t1) &gt; int(t2)) - (int(t1) &lt; int(t2))

def solution(number):
    sorted_num = sorted(number, key = functools.cmp_to_key(lambda a, b : compare(a,b)), reverse=True)

answer = &#39;&#39;.join(str(x) for x in sorted_num)
return &#39;0&#39; if in(answer) == 0 else answer</code></pre>
<pre><code class="language-python">def solution(N, num_list):
    str_list = [str(i) for i in num_list].sort()
    for i in range(0, N):
        if str_list[i+1] in str_list[i]:
            if int(str_list[i][len(str_list[i])-1:][0])&gt;int(str_list[i+1][0]):
                str_list[i], str_list[i+1] = str_list[i+1], str_list[i]
    return int(&#39;&#39;.join(str_list))</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[웨비나 후기] npm 공급망 공격과 AI 모델 보안, 서비스 운영 관점에서 정리]]></title>
            <link>https://velog.io/@son-dan-ha/%EC%9B%A8%EB%B9%84%EB%82%98-%ED%9B%84%EA%B8%B0-npm-%EA%B3%B5%EA%B8%89%EB%A7%9D-%EA%B3%B5%EA%B2%A9%EA%B3%BC-AI-%EB%AA%A8%EB%8D%B8-%EB%B3%B4%EC%95%88-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%9A%B4%EC%98%81-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@son-dan-ha/%EC%9B%A8%EB%B9%84%EB%82%98-%ED%9B%84%EA%B8%B0-npm-%EA%B3%B5%EA%B8%89%EB%A7%9D-%EA%B3%B5%EA%B2%A9%EA%B3%BC-AI-%EB%AA%A8%EB%8D%B8-%EB%B3%B4%EC%95%88-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%9A%B4%EC%98%81-%EA%B4%80%EC%A0%90%EC%97%90%EC%84%9C-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 21 Jan 2026 15:19:30 GMT</pubDate>
            <description><![CDATA[<h1 id="들어가며">들어가며</h1>
<br>

<p>오늘 <a href="https://event-us.kr/grometric/event/117958">그로밋업 웨비나</a>를 들었다. 이번 웨비나는 <strong>Sonatype Nexus Repository를 중심으로</strong>, npm 오픈소스 공급망 공격 사례와 함께 <strong>Hugging Face 기반 오픈소스 AI 모델의 보안 취약점</strong>을 다루는 내용이었다.</p>
<p>웨비나를 듣게 된 계기는 단순하다. 작년 12월부터 본격적으로 시작한 프로젝트 CRATE에서 백엔드를 담당하고 있다. 현재는 AWS 배포 단계지만, MVP 이후에는 <strong>AI 기능을 포함한 서비스 확장</strong>을 계획하고 있고, 그 시점부터는 “기능 구현만 잘하면 된다”는 태도로는 운영이 불가능하다고 느꼈기 때문이다.</p>
<p>보안 쪽은 솔직히 아는 게 거의 없다. 다만 요즘은 개발자의 역할이 프론트엔드나 백엔드에만 국한되지 않고, <strong>배포·운영·인프라·보안까지 전반적인 맥락을 이해해야 한다</strong>는 이야기를 자주 듣는다. 특히 주니어에게도 이런 관점이 요구된다는 점에서, 지금부터라도 감을 잡아두는 게 필요하다고 생각했다.</p>
<p><br><br></p>
<hr>
<h1 id="오픈소스-공급망의-취약성">오픈소스 공급망의 취약성</h1>
<h2 id="1-npm-중심의-오픈소스-생태계">1. npm 중심의 오픈소스 생태계</h2>
<p>현대 웹 서비스는 오픈소스 의존성 위에서 돌아간다. npm 생태계는 편리하지만, 그만큼 <strong>공급망 공격의 표적</strong>이 되기 쉽다.</p>
<ul>
<li><code>npm install</code> 한 번</li>
<li>그 순간, 외부 코드가 내부 파이프라인으로 바로 유입됨</li>
<li>검증이 없다면 악성 코드도 같이 들어온다</li>
</ul>
<p>즉, 개발 편의성과 보안 리스크가 동시에 커진 구조다.</p>
<br>

<h2 id="2-위협의-두-가지-유형">2. 위협의 두 가지 유형</h2>
<h3 id="2-1-악성코드malware-위협">2-1. 악성코드(Malware) 위협</h3>
<p>문제의 핵심은 <strong>패키지 유입 단계에서의 검증 부재</strong>다. 패키지에 대한 신뢰가 “작성자” 기준으로만 형성되어 있고, 개발자는 별 의심 없이 install 한다. 이때 CI/CD, 내부 네트워크까지 전파 가능하다.</p>
<br>

<h4 id="사례-1-debug--chalk-패키지-하이재킹"><strong>사례 1. debug / chalk 패키지 하이재킹</strong></h4>
<ul>
<li>사회공학 기법을 이용한 MFA 위장</li>
<li>정상 패키지 유지보수자의 계정 탈취</li>
<li>업데이트를 통해 악성 코드 유입</li>
</ul>
<br>

<h4 id="사례-2-shai-hulud-20-캠페인"><strong>사례 2. Shai-Hulud 2.0 캠페인</strong></h4>
<ul>
<li>단순 해킹이 아니라 <strong>APT(지능형 지속 공격)</strong></li>
<li><code>bun</code> 런타임을 설치해 실행</li>
<li>자가 지속 사이클을 가진 <strong>APT + Worm 구조</strong></li>
</ul>
<br>

<p>Worm의 동작 방식은 꽤 충격적이었다.</p>
<ul>
<li>저장소 순회</li>
<li>새로운 레포 생성</li>
<li>GitHub Actions 워크플로 등록</li>
<li>자동 확산</li>
</ul>
<p>개발자의 실수 한 번이 조직 전체로 번지는 구조다.</p>
<p><br><br></p>
<h3 id="2-2-내부-취약점vulnerability">2-2. 내부 취약점(Vulnerability)</h3>
<p>외부 공격이 아니어도 문제는 터진다.</p>
<h4 id="사례-react2shell"><strong>사례. React2Shell</strong></h4>
<ul>
<li>사용자 계정 정보나 엔드포인트 노출 없이 공격 가능</li>
<li>CVSS 10.0 (최고 위험도)</li>
</ul>
<blockquote>
<p>&lt;공격 시나리오&gt;
역직렬화 취약점 악용 
→ attacker가 victim 환경 접근 
→ <code>.env</code> 확인 
→ 파일 생성·삭제 가능</p>
</blockquote>
<p>랜섬웨어였다면 서비스는 끝이다.</p>
<p><br><br></p>
<h2 id="왜-수동-검증만으로는-부족한가">왜 수동 검증만으로는 부족한가</h2>
<p>이쯤 되면 이런 생각이 든다.</p>
<blockquote>
<p>“리뷰 잘하고, 조심하면 되는 거 아닌가?”</p>
</blockquote>
<p>현실은 다르다.</p>
<ul>
<li>의존성 트리는 너무 깊다</li>
<li>모든 패키지 코드를 사람이 검토하는 건 불가능</li>
<li>사고 이후 패치는 이미 늦다</li>
</ul>
<p><strong>Reactive(사후 대응)</strong>가 아니라 <strong>Proactive(반입 전 차단)</strong>로 전략을 바꿔야 한다.</p>
<br>


<h2 id="nexus가-제안하는-자동화-방어-전략">Nexus가 제안하는 자동화 방어 전략</h2>
<p>웨비나에서는 Nexus 기반의 <strong>중앙 통제</strong> 접근을 소개했다.</p>
<ul>
<li>모든 개발·배포 트래픽 중앙화</li>
<li>문제 패키지 즉시 차단</li>
<li>검증된 버전만 캐싱</li>
<li>개발자는 “안전한 npm”만 보게 됨</li>
</ul>
<p>개발 경험은 유지하면서, 리스크만 줄이는 방식이다.</p>
<p><br><br></p>
<hr>
<h1 id="ai-시대의-새로운-공급망-hugging-face">AI 시대의 새로운 공급망: Hugging Face</h1>
<p>Hugging Face는 말 그대로 <strong>AI의 GitHub</strong>다.</p>
<ul>
<li>Models: 초대형 바이너리</li>
<li>Datasets</li>
<li>Spaces: ML 앱 호스팅 환경</li>
</ul>
<p>문제는, 이 모든 것이 <strong>신뢰 기반 공유</strong>라는 점이다.</p>
<br>

<h2 id="owasp-llm-top-10">OWASP LLM Top 10</h2>
<p>OWASP는 LLM 기반 서비스를 운영할 때 발생할 수 있는 주요 보안 위협을 Top 10 형태로 정리했다. 전통적인 웹 보안이 “입력 → 코드 실행” 문제였다면, LLM 보안은 입력 → 추론 → 행동 문제에 가깝다.</p>
<h4 id="1-prompt-injection">1. Prompt Injection</h4>
<ul>
<li>사용자 입력을 통해 시스템 프롬프트나 정책을 우회·조작하는 공격.</li>
<li>LLM이 지켜야 할 규칙 자체가 무너진다.</li>
</ul>
<h4 id="2-insecure-output-handling">2. Insecure Output Handling</h4>
<ul>
<li>LLM의 출력을 검증 없이 코드 실행, 렌더링, API 입력으로 사용하는 문제.</li>
<li>XSS, 명령 실행, 권한 상승으로 이어질 수 있다.</li>
</ul>
<h4 id="3-training-data-poisoning">3. Training Data Poisoning</h4>
<ul>
<li>학습 데이터에 악성 또는 편향된 데이터를 주입해 모델의 행동을 왜곡하는 공격.</li>
<li>모델은 정상처럼 보이지만 결과는 신뢰할 수 없게 된다.</li>
</ul>
<h4 id="4-model-denial-of-service-dos">4. Model Denial of Service (DoS)</h4>
<ul>
<li>과도하게 긴 입력, 반복 호출 등으로 추론 자원을 고갈시키는 공격.</li>
<li>서비스 장애와 비용 폭증을 동시에 유발한다.</li>
</ul>
<h4 id="5-supply-chain-vulnerabilities">5. Supply Chain Vulnerabilities</h4>
<ul>
<li>모델, 라이브러리, 파이프라인 자체가 공격 지점이 되는 문제.</li>
<li>npm 공급망 공격과 동일한 구조를 AI 영역에서 그대로 가진다.</li>
</ul>
<h4 id="6-sensitive-information-disclosure">6. Sensitive Information Disclosure</h4>
<ul>
<li>프롬프트, 응답, 로그를 통해 개인정보, 인증 정보, 내부 데이터가 유출되는 문제.</li>
<li>의도하지 않은 데이터 회상이 주요 원인이다.</li>
</ul>
<h4 id="7-insecure-plugin--tool-design">7. Insecure Plugin / Tool Design</h4>
<ul>
<li>LLM이 사용하는 플러그인·툴의 권한이 과도하게 설계된 경우.</li>
<li>모델이 공격자의 의도대로 시스템 자원을 조작할 수 있다.</li>
</ul>
<h4 id="8-excessive-agency">8. Excessive Agency</h4>
<ul>
<li>LLM에 지나치게 많은 자율성과 실행 권한을 부여한 경우.</li>
<li>검증 없는 API 호출, 파일 조작, 외부 요청이 발생할 수 있다.</li>
</ul>
<h4 id="9-overreliance-on-llm">9. Overreliance on LLM</h4>
<ul>
<li>LLM의 출력을 검증 없이 신뢰하는 문제.</li>
<li>그럴듯한 오류가 시스템 의사결정으로 이어진다.</li>
</ul>
<h4 id="10-model-theft">10. Model Theft</h4>
<ul>
<li>API 호출, 프롬프트 조합 등을 통해 모델의 동작을 추론·복제하는 공격.</li>
<li>모델 자체가 자산인 경우 치명적이다.</li>
</ul>
<p><br><br></p>
<h2 id="세-가지-핵심-과제">세 가지 핵심 과제</h2>
<h3 id="1-인프라-문제">1. 인프라 문제</h3>
<ul>
<li>대용량 모델 다운로드 병목</li>
<li>CI 환경에서 반복 다운로드</li>
<li>속도와 안정성 모두 문제</li>
</ul>
<br>

<h3 id="2-거버넌스-문제">2. 거버넌스 문제</h3>
<ul>
<li>Open source 모델</li>
<li>Fine-tuning</li>
<li>내부 데이터 결합</li>
</ul>
<blockquote>
<p>이 과정에서 <strong>AI Mutation</strong>이 발생한다. 원본 모델의 학습 데이터와 리스크를 알 수 없는 상태로 변형된다.</p>
</blockquote>
<br>

<h3 id="3-악성-모델-반입">3. 악성 모델 반입</h3>
<ul>
<li>Pickle 역직렬화 구조 자체의 결함</li>
<li>모델 파일 자체가 공격 벡터가 될 수 있음</li>
</ul>
<blockquote>
<p>코드가 아닌 것처럼 취급되던 모델 파일이, 실제로는 실행 가능한 공격 벡터가 될 수 있다.</p>
</blockquote>
<p><br><br></p>
<h2 id="ai-보안의-해법-npm과-같은-접근">AI 보안의 해법: npm과 같은 접근</h2>
<p>해결책은 의외로 단순하다.</p>
<ul>
<li>Hugging Face 접근을 프록시화</li>
<li>로컬 캐싱</li>
<li>검증된 모델만 내부 반입</li>
</ul>
<p>AI/ML 개발은 <strong>모델</strong>을 가져오고, <strong>튜닝</strong>하고, <strong>다시 학습</strong>하는 반복 과정이다. 한 번의 검증으로 끝나지 않는다.</p>
<br>

<h2 id="aibom이라는-개념">AIBOM이라는 개념</h2>
<p>여기서 등장한 개념이 <strong>AIBOM</strong>이다. AI 시스템 전용 SBOM이라고 보면 된다.</p>
<p>포함 요소:</p>
<ul>
<li>알고리즘</li>
<li>의존성</li>
<li>인프라</li>
<li>데이터 소스</li>
<li>메타데이터</li>
</ul>
<p>AI를 “코드”가 아니라 <strong>시스템 전체</strong>로 관리하자는 관점이다.</p>
<p><br><br></p>
<hr>
<h1 id="마무리하며">마무리하며</h1>
<p>이번 웨비나를 통해 느낀 건, AI 보안은 “나중에 고려할 문제”가 아니라 <strong>모델을 쓰기로 결정하는 순간부터 함께 따라오는 전제</strong>라는 점이었다. 앞으로 Hugging Face에 모델을 올리며 AI에 대한 이해를 넓혀갈 계획이고, 동시에 현재 프로젝트에 <strong>실제 모델 도입을 고려하는 입장</strong>이기 때문에 성능이나 정확도뿐만 아니라 <strong>보안과 운영 관점</strong>도 함께 생각해야 한다고 느꼈다.</p>
<p>지금은 NestJS 기반으로 백엔드를 빠르게 만들어가며 이른바 ‘바이브 코딩’을 하고 있지만,<br>AI 기능을 서비스에 포함시키는 순간부터는 모델의 출처, 학습 데이터, 실행 권한, 공급망 구조 같은 요소들이 곧바로 운영 리스크로 이어진다는 점을 의식하게 됐다.</p>
<p>이번 정리는 보안을 깊이 알기 위한 기록이라기보다는, <strong>실제로 운영하는 AI 서비스를 만들기 위한 출발점</strong>에 가깝다.</p>
<p><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DeepSeek-OCR: Contextual Optical Compression 논문리뷰]]></title>
            <link>https://velog.io/@son-dan-ha/DeepSeek-OCR-Contextual-Optical-Compression-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0</link>
            <guid>https://velog.io/@son-dan-ha/DeepSeek-OCR-Contextual-Optical-Compression-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0</guid>
            <pubDate>Tue, 20 Jan 2026 14:43:16 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/a53de6ed-9442-4538-88a5-1cdd07ac2c65/image.png" alt=""></p>
<h1 id="1-introduction">1. Introduction</h1>
<p>DeepSeek-OCR 논문은 기존 <strong>OCR 및 VLM 기반</strong> 문서 이해 모델들이 <strong>시각 토큰 수</strong>가 과도하게 많다는 문제의식에서 출발한다. 고해상도 문서 이미지를 그대로 토큰화하면, 모델은 불필요한 시각 정보까지 처리해야 하고 이는 곧 <u>비용 증가</u>와 <u>추론 지연</u>으로 이어진다.</p>
<p>저자들은 이 문제를 단순히 “모델을 더 크게” 혹은 “토큰을 줄이자”로 접근하지 않는다. 대신, <strong>문맥적으로 중요한 시각 정보만 남기고 나머지는 압축</strong>할 수 있지 않을까? 라는 질문을 던진다.</p>
<p>이 부분을 읽으면서 나는 기존 OCR 파이프라인이 사실상 <strong>이미지 → 텍스트 변환</strong>에만 집중해 왔고, 이미지 자체를 정보 압축의 대상으로 본 <strong>시각은 상대적으로 적었다</strong>는 점을 다시 생각하게 됐다.</p>
<p><br><br></p>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[이진 탐색 트리(BST)]]></title>
            <link>https://velog.io/@son-dan-ha/%EC%9D%B4%EC%A7%84-%ED%83%90%EC%83%89-%ED%8A%B8%EB%A6%ACBST</link>
            <guid>https://velog.io/@son-dan-ha/%EC%9D%B4%EC%A7%84-%ED%83%90%EC%83%89-%ED%8A%B8%EB%A6%ACBST</guid>
            <pubDate>Thu, 01 Jan 2026 07:10:51 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/0ee1df61-989c-4725-92e8-390edefed723/image.png" alt=""></p>
<h1 id="트리tree">트리(Tree)</h1>
<p>트리(Tree) 자료구조는 그래프(Graph)의 한 형태로 이해할 수 있다. 데이터 간의 <u>계층적 관계</u>를 표현하며, <u>사이클이 존재하지 않는</u> 구조를 가진다. 그래프에서는 일반적으로 <strong>노드(Node)</strong>와 <strong>간선(Edge)</strong>라는 표현을 사용하지만, 트리에서는 주로 <strong>정점(Vertex)</strong>과 <strong>간선(Edge)</strong> 또는 부모(Parent)와 자식(Child)이라는 관계 용어가 함께 사용된다.</p>
<p><strong>루트(Root)</strong>를 기준으로 위계가 명확하게 구성되며, 어떤 노드든 단 하나의 부모만을 갖는 것이 특징이다. 또한 특정 노드를 기준으로 분리했을 때 그 자체로 또 하나의 트리가 되는 성질을 가진다<strong>(서브트리)</strong>.</p>
<br>

<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/01ae1fba-d8f5-4ece-8bfa-56bb554641a3/image.png" alt=""></p>
<p><br><br></p>
<h2 id="이진-트리binary-tree">이진 트리(Binary Tree)</h2>
<p>이진 트리(Binary Tree)는 각 노드가 <strong>최대 두 개의 자식 노드</strong>를 가지는 트리 구조를 의미한다. 왼쪽(Left)과 오른쪽(Right) 자식으로 구분되며, 트리 자료구조에서 가장 기본적인 형태이다.</p>
<p>이진 트리와 관련해 자주 등장하는 개념이 두 가지 있다.</p>
<ul>
<li><p><strong>포화 이진트리(Full Binary Tree)</strong>
모든 노드가 자식 노드를 0개 또는 2개만 가지는 구조를 말한다.</p>
</li>
<li><p><strong>완전 이진트리(Complete Binary Tree)</strong>
노드가 <strong>위에서 아래</strong>, 그리고 <strong>왼쪽부터 오른쪽 순으로</strong> 빈틈 없이 채워진 구조를 의미한다.
단, 마지막 레벨은 완전히 채워지지 않아도 된다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/26cce63d-dc50-4de8-b481-09248cf26689/image.png" alt=""></p>
<p>이러한 기본 개념을 토대로 다음 단계에서는 <strong>이진 탐색 트리(Binary Search Tree)</strong>의 구조와 특징을 살펴본다.</p>
<p><br><br></p>
<h1 id="이진-탐색-트리bst">이진 탐색 트리(BST)</h1>
<p>BST는 이진 트리 구조에 정렬 규칙이 적용된 형태이다. 왼쪽 자식(L), 오른쪽 자식(R), 부모(V) 필드를 가진다. 각각의 키들은 이진 검색 트리의 특성을 만족한 상태로 저장된다. </p>
<h2 id="bst-특성">BST 특성</h2>
<p>임의의 노드 x에 대해</p>
<ul>
<li><p>x의 왼쪽 서브트리에 있는 모든 노드 y:
  <code>y.value &lt; x.value</code></p>
</li>
<li><p>x의 오른쪽 서브트리에 있는 모든 노드 y:
  <code>y.value &gt; x.value</code></p>
</li>
</ul>
<p>탐색 기준 (L &lt; V &lt; R)이 명확하다. </p>
<pre><code>      10
    /   \
   5     20
  / \    /
 1   7  15</code></pre><br>

<h2 id="중위-순회inorder-traversal와-정렬">중위 순회(Inorder Traversal)와 정렬</h2>
<p>BST의 모든 값을 오름차순으로 정렬된 순서대로 출력하기 위해 중위 트리 순회를 활용할 수 있다. </p>
<pre><code class="language-python">import sys
input = sys.stdin.readline

# BST 노드 정의
class Node:
    # 인스턴스가 가질 수 있는 속성을 제한
    __slots__ = (&#39;v&#39;, &#39;l&#39;, &#39;r&#39;)

    def __init__(self, v):
        self.v = v    # 노드
        self.l = None # 왼쪽
        self.r = None # 오른쪽

# BST 삽입 연산
def insert(root, v):
    # 루트가 없으면 새 노드 생성
    if root is None:
        return Node(v)

    # 값 비교 후 왼/오른쪽으로 재귀 삽입
    if v &lt; root.v:
        root.l = insert(root.l, v)
    else:
        root.r = insert(root.r, v)
    return root

# 중위 순회(Inorder)
def inorder(n, res):
    if n is None:
        return
    inorder(n.l, res)   # 왼쪽 서브트리 탐색
    res.append(n.v)     # 루트 방문
    inorder(n.r, res)   # 오른쪽 서브트리 탐색

# 입력: N개의 값으로 BST 구성
N = int(input().strip())
arr = list(map(int, input().split()))

root = None
for val in arr:
    root = insert(root, val)

# 중위 순회 결과 수집
res = []
inorder(root, res)

# 리스트 언패킹 출력 → 1 2 3 5 7
print(*res)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ch_02] 7. 경사하강법의 의미와 식]]></title>
            <link>https://velog.io/@son-dan-ha/Ch02-7.-%EA%B2%BD%EC%82%AC%ED%95%98%EA%B0%95%EB%B2%95%EC%9D%98-%EC%9D%98%EB%AF%B8%EC%99%80-%EC%8B%9D</link>
            <guid>https://velog.io/@son-dan-ha/Ch02-7.-%EA%B2%BD%EC%82%AC%ED%95%98%EA%B0%95%EB%B2%95%EC%9D%98-%EC%9D%98%EB%AF%B8%EC%99%80-%EC%8B%9D</guid>
            <pubDate>Sat, 15 Nov 2025 14:42:21 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/58ccac3b-b3d7-4298-99c1-056527ecf06e/image.png" alt=""></p>
<h1 id="경사하강법의-원리">경사하강법의 원리</h1>
<p><br><br></p>
<h1 id="근사식과-내적의-관계">근사식과 내적의 관계</h1>
<p><br><br></p>
<h1 id="내적의-최솟값">내적의 최솟값</h1>
<p><br><br></p>
<h1 id="이변수-함수">이변수 함수</h1>
<p><br><br></p>
<h1 id="다변수-함수">다변수 함수</h1>
<p><br><br></p>
<h1 id="델-연산자">델 연산자</h1>
<p><br><br></p>
<h1 id="n의-의미">n의 의미</h1>
<br>
<br>]]></description>
        </item>
        <item>
            <title><![CDATA[[Ch_02] 6. 연쇄법칙과 근사식]]></title>
            <link>https://velog.io/@son-dan-ha/Ch02-6.-%EC%97%B0%EC%87%84%EB%B2%95%EC%B9%99%EA%B3%BC-%EA%B7%BC%EC%82%AC%EC%8B%9D</link>
            <guid>https://velog.io/@son-dan-ha/Ch02-6.-%EC%97%B0%EC%87%84%EB%B2%95%EC%B9%99%EA%B3%BC-%EA%B7%BC%EC%82%AC%EC%8B%9D</guid>
            <pubDate>Mon, 03 Nov 2025 06:30:52 GMT</pubDate>
            <description><![CDATA[<h1 id="합성함수">합성함수</h1>
<h1 id="연쇄법칙">연쇄법칙</h1>
<h2 id="1-일변수-함수">1. 일변수 함수</h2>
<h2 id="2-다변수-함수">2. 다변수 함수</h2>
<hr>
<h1 id="근사식">근사식</h1>
<h2 id="1-일변수-함수-1">1. 일변수 함수</h2>
<h2 id="2-다변수-함수-1">2. 다변수 함수</h2>
<h2 id="3-근사식의-벡터표현">3. 근사식의 벡터표현</h2>
<h2 id="4-테일러-급수">4. 테일러 급수</h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ch_02] 5. 미분과 편미분]]></title>
            <link>https://velog.io/@son-dan-ha/Ch02-5.-%EB%AF%B8%EB%B6%84%EA%B3%BC-%ED%8E%B8%EB%AF%B8%EB%B6%84</link>
            <guid>https://velog.io/@son-dan-ha/Ch02-5.-%EB%AF%B8%EB%B6%84%EA%B3%BC-%ED%8E%B8%EB%AF%B8%EB%B6%84</guid>
            <pubDate>Sun, 02 Nov 2025 07:40:28 GMT</pubDate>
            <description><![CDATA[<h1 id="미분의-기본">미분의 기본</h1>
<h2 id="1-미분의-정의">1. 미분의 정의</h2>
<p><strong>도함수</strong>는 어떤 함수 안에 포함된 값 각각이 0에 가까워지는 극한값(미분계수)를 구하는 함수를 말한다. 아래는 $y=f(x)$에 대한 도함수 $f&#39;(x)$의 정의다.</p>
<br>

<p>$$
f&#39;(x) = \lim_{\Delta x \to 0} \frac{f(x+\Delta x) - f(x)}{\Delta x}
$$</p>
<p>$\Delta x$는 변화량을 나타낸다. </p>
<br>
아래 2가지 예시를 통해 직접 도함수를 구해보자. 


<ol>
<li>$f(x)=5x+1$<br>

</li>
</ol>
<p>$$
f&#39;(x) = \lim_{\Delta x \to 0} \frac{5(x+\Delta x)+1 - (5x+1)}{\Delta x}
$$</p>
<p>$$
= \lim_{\Delta x \to 0} \frac{5\Delta x}{\Delta x}=\lim_{\Delta x \to 0}5=5
$$</p>
<br>

<ol start="2">
<li>$f(x)=x^2-x$</li>
</ol>
<br>

<p>$$
f&#39;(x)=\lim_{\Delta x \to 0}\frac{(x+\Delta x)^2-(x+\Delta x)-(x^2-x)}{\Delta x}
$$</p>
<p>$$
=\lim_{\Delta x \to 0}\frac{x^2+2x\Delta x+(\Delta x)^2 - x - \Delta x - x^2 + x}{\Delta x}
$$</p>
<p>$$
=\lim_{\Delta x \to 0}\frac{2x\Delta x+(\Delta x)^2-\Delta x}{\Delta x}
=\lim_{\Delta x \to 0}(2x+\Delta x-1)=2x-1
$$</p>
<br>

<p>도함수를 구한다는 것은 <strong>함수를 미분한다</strong>는 것과 같은 말이다. 또한 1번과 2번처럼 값을 계산할 수 있다면 <strong>미분 가능</strong>하다고 한다.</p>
<p>또한 $f(x)$를 그래프로 그렸을 때 도함수 $f&#39;(x)$는 <strong>접선의 기울기</strong>를 표현한다.</p>
<br>

<h3 id="신경망-도함수-계산">신경망 도함수 계산</h3>
<p>신경망에서 도함수를 계산할 때는 아래 공식을 사용한다.</p>
<p>$$
(c)&#39;=0
\qquad
(x)&#39;=1
\qquad
(x^2)&#39;=2x
\qquad
(e^{x})&#39;=e^x
\qquad
(e^{-x})&#39;=-e^{-x}
$$</p>
<p><br><br></p>
<h2 id="2-미분-기호">2. 미분 기호</h2>
<p>지금까지 도함수를 극한 개념으로 정의했지만 <strong>분수</strong>로도 정의할 수 있다. </p>
<p>$$
f&#39;(x)=\frac{dy}{dx}
$$</p>
<br>

<p>아래 식은 두 점을 연결한 직선의 기울기를 나타낸다. 
$$
\frac{\Delta y}{\Delta x}
$$
이는 함수의 평균 변화율을 의미한다. 이 변화량 $Δx$를 0으로 보내면,
$$
\lim_{\Delta x \to 0} \frac{\Delta y}{\Delta x}
$$
이를 계산한 값이 순간 변화율, 즉 도함수이다.</p>
<p><br><br></p>
<h2 id="3-미분의-성질">3. 미분의 성질</h2>
<h3 id="미분의-선형성">미분의 선형성</h3>
<p>미분의 선형성은 <strong>오차역전파법</strong>의 기반이 되는 개념이다. (<a href="https://velog.io/@son-dan-ha/Ch02-2.-%EC%88%98%EC%97%B4%EA%B3%BC-%EC%8B%9C%EA%B7%B8%EB%A7%88-%EA%B8%B0%ED%98%B8">선형성은 여기에서 확인</a>) 아래의 두 개의 공식을 기억하자.</p>
<ol>
<li><p>함수 합의 미분은 각 함수를 미분한 합과 같다.
$$
[f(x)+g(x)]&#39;=f&#39;(x)+g&#39;(x)
$$</p>
</li>
<li><p>상수를 곱한 함수의 미분은 미분한 함수에 상수를 곱한 것과 같다.
$$
[cf(x)]&#39;=cf&#39;(x)
$$</p>
</li>
</ol>
<br>

<p>이 공식을 사용하여 함수를 미분해보자. 
<br></p>
<ol>
<li>$f(x)=(2-x)^2$</li>
</ol>
<br>

<p>$$
f(x)&#39;=(4-4x+x^2)&#39;=4&#39;-(4x)&#39;+(x^2)&#39;=-4+2x
$$</p>
<br>

<ol start="2">
<li>$f(x)=1+e^{-x}$<br>

</li>
</ol>
<p>$$
f(x)&#39;=(1+e^{-x})&#39;=1&#39;+(e^{-x})&#39;=-e^{-x}
$$</p>
<ul>
<li>다음 장 <a href="">연쇄법칙</a> 에서 $(e^{-x})&#39;=-e^{-x}$을 증명해본다.</li>
</ul>
<p><br><br></p>
<h2 id="4-분수-함수-미분">4. 분수 함수 미분</h2>
<p>$$
\left( \frac{1}{f(x)} \right)&#39; = -,\frac{f&#39;(x)}{[f(x)]^{2}}
$$</p>
<p>위의 공식을 활용하면,
$$
\left(\frac{f(x)}{g(x)} \right)&#39;= \left(f(x)\cdot\frac{1}{g(x)} \right)&#39;
$$
$$
= \frac{f&#39;(x)g(x) - f(x)g&#39;(x)}{[,g(x),]^2}
$$</p>
<br>

<h3 id="시그모이드-함수-미분">시그모이드 함수 미분</h3>
<p>활성화 함수인 시그모이드 함수는 다음과 같다.
$$
\sigma(x)=\frac{1}{1+e^{-x}}
$$</p>
<p>이후 공부할 <strong>경사하강법</strong>에서 시그모이드 함수를 미분한다. 그때 활용할 것이 시그모이드 함수의 <strong>도함수</strong>를 구하는 간단한 식이다. </p>
<p>$$
\sigma&#39;(x)=\sigma(x)(1-\sigma(x))
$$</p>
<br>

<p>이 식이 성립하는 과정은 <strong>분수의 미분 공식</strong>을 활용하여 아래와 같이 계산할 수 있다. </p>
<p>$$
\sigma&#39;(x)=-\frac{(1+e^{-x})&#39;}{(1+e^{-x})^2}=\frac{e^{-x}}{(1+e^{-x})^2}
$$</p>
<p>$$
=\frac{1+e^{-x}-1}{(1+e^{-x})^2}=\frac{1}{1+e^{-x}}-\frac{1}{(1+e^{-x})^2}
$$</p>
<p>$$
=\sigma(x)-\sigma(x)^2=\sigma(x)(1-\sigma(x))
$$</p>
<p><br><br></p>
<h2 id="4-최솟값의-필요조건">4. 최솟값의 필요조건</h2>
<p>함수 $f(x)$가 $x=a$에서 최솟값을 가지면 $f&#39;(a)=0$이다. 즉, $f&#39;(a)=0$ 은 $f(x)$가 $x=a$에서 최솟값이 되기 위한 <strong>필요조건</strong>이다.</p>
<p>중요한 것은 $f&#39;(a)=0$ 이라고 해서 <u>항상 최솟값인 것은 아니</u>라는 것이다. 아래 그림을 통해 이를 더 직관적으로 이해할 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/179afa46-ad61-40be-a508-dde996a55470/image.png" alt=""></p>
<br>

<hr>
<h1 id="편미분의-기본">편미분의 기본</h1>
<p>지금까지 미분에서는 독립변수가 하나인 함수를 다뤘다. 그러나 신경망에서는 <strong>다변수 함수</strong>를 다룬다. <a href="https://velog.io/@son-dan-ha/Ch02-1.-%EC%8B%A0%EA%B2%BD%EB%A7%9D%EC%9D%98-%ED%95%84%EC%88%98-%ED%95%A8%EC%88%98">독립변수와 종속변수</a> 여기에서 언급한 독립변수가 2개 이상인 경우를 다변수 함수라고 한다. </p>
<p>변수 $x$를 독립변수로 하는 함수를 $f(x)$로 했다. 변수 $x_1, x_2, ... ,x_n$을 독립변수로 하는 다변수 함수는 $f(x_1, x_2, ... ,x_n)$로 표현하도록 한다. </p>
<br>

<h2 id="1-편미분">1. 편미분</h2>
<p>다변수 함수를 미분하려면 어떤 변수를 미분할지 명시해야 한다. 이처럼 특정 변수에 대해 미분하는 것을 편미분(partial derivative)이라고 한다. 편미분 기호는 $\partial x$를 사용한다. </p>
<p>변수 $x, y$에 대한 함수 $z=f(x,y)$ 예로 편미분을 해보자. <strong>$x$에 관한 편미분</strong>은 변수 $x$를 미분하고 $y$를 상수 취급하는 것이고, 반대로 <strong>$y$에 관한 편미분</strong>은 $y$를 미분하고 $x$를 상수 취급한다.</p>
<p>$x$에 관한 편미분
$$
\frac{\partial z}{\partial x} = \frac{\partial f(x,y)}{\partial x}= \lim_{\Delta x \to 0} \frac{f(x+\Delta x,,y) - f(x,,y)}{\Delta x}
$$</p>
<p>$y$에 관한 편미분</p>
<p>$$
\frac{\partial z}{\partial y}
= \frac{\partial f(x,y)}{\partial y}
= \lim_{\Delta y \to 0} \frac{f(x,,y+\Delta y) - f(x,,y)}{\Delta y}
$$</p>
<br>

<p>뉴런의 선형결합 $z=wx+b$ 에 대해 각 독립변수를 편미분할 수 있다.</p>
<p>$$
\frac{\partial z}{\partial x} = w
\qquad
\frac{\partial z}{\partial w} = x
\qquad
\frac{\partial z}{\partial b} = 1
$$</p>
<p><br><br></p>
<h2 id="2-다변수-함수-최솟값의-필요조건">2. 다변수 함수 최솟값의 필요조건</h2>
<p>앞서 일변수 함수 f(x)에 대해 최솟값의 필요조건은 도함수가 0이 되는 것이었다. 다변수 함수도 마찬가지다. </p>
<p>2개의 변수가 있는 $z=f(x,y)$ 함수가 최솟값이 되는 필요조건은 다음과 같다.</p>
<p>$$
\frac{\partial f}{\partial x} = 0
\qquad
\frac{\partial f}{\partial y} = 0
$$</p>
<br>

<p>$z=x^2+y^2$의 최솟값의 필요조건을 구해보자. </p>
<p>$x, y$에 관해 각각 편미분하면,</p>
<p>$$
\frac{\partial z}{\partial x} = 2x
\qquad
\frac{\partial z}{\partial y} = 2y
$$</p>
<p>$x=0, y=0$ 은 함수가 최솟값을 갖기 위한 필요조건이다. 또한 $z=x^2 +y^2 ≥0$ 이므로 $z=0$ 이 최솟값이 되며, 이 값은 $(0,0)$ 에서만 성립한다. 따라서 $x=0, y=0$은 함수가 최솟값을 갖는 <strong>필요충분조건</strong>이다.</p>
<p>그래프에서 이를 확인할 수 있다.</p>
<br>

<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/4ac291b2-78cc-4650-b547-3ae0e9fa2216/image.png" alt=""></p>
<p><br><br></p>
<hr>
<h1 id="lagrange-multiplier-method">Lagrange multiplier method</h1>
<p>라그랑주 승수법(Lagrange multiplier method)이란 <strong>제약</strong>이 있는 상태에서의 <strong>극값(최댓값·최솟값)</strong>을 찾는 방법이다. 다변수 함수 $f(x_1,x_2,…,x_n)$에 대해, 제약식 $g(x_1,x_2,…,x_n)=k$를 만족하는 점들 중에서 f를 최대, 최소로 만드는 점을 구하고 싶을 때 사용한다. </p>
<p>우선 등산 경로 <strong>예시</strong>를 통해 <strong>라그랑주 승수의 상황</strong>을 이해해보도록 하자. 예시에는 <a href="https://youtu.be/lmD9p6J_-TA?si=H9GSO2fDNdZol3vD">해당 영상</a>을 참고했다.</p>
<br>

<h2 id="등산-경로">등산 경로</h2>
<p>이변수함수 $f(x,y)=4-x^2-2y^2$를 <strong>산의 높이</strong>로 보고, <strong>등산 경로</strong>를 $g(x,y)=2(x-1)^2-10y+6=0$ 로 둔다. ($f$의 level curve는 색상이 달라지는 지점으로 표현했다.)</p>
<br>

<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/38dd8266-856b-4a26-ac94-9b94a575ce48/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/54d5f852-67d3-4146-b947-d97202407f0e/image.png" alt=""></p>
<br>

<p>아래처럼 $f$와 $g$가 만나는 부분을 경로로 볼 수 있다. 이 경로를 따라 올라갔을 때 <strong>최고 높이</strong>는 어떻게 구할 수 있을까? level curve는 타원의 중심으로 갈수록 높은 곳이라는 성질을 갖는다. 따라서 <u>가장 안쪽의 level curve과 경로가 접하는 부분</u>이 경로에서의 <strong>최고 높이</strong>로 볼 수 있다.</p>
<br>

<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/d60167ab-7ca1-48c3-958c-387a873bf177/image.png" alt="">
<img src="https://velog.velcdn.com/images/son-dan-ha/post/6195789e-6ee2-47a1-b325-eb5e4959bc8f/image.png" alt=""></p>
<br>

<p>접점에서는 $∇f$와 $∇g$가 <strong>비례(평행)</strong>해야 한다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/3dcf2670-e7b1-468f-be9b-460acc0da10b/image.png" alt=""></p>
<br>

<h2 id="정의와-조건">정의와 조건</h2>
<p>등산 경로 예시를 통해 대략적인 <strong>상황</strong>은 이해되었을 것이다. 그렇다면 이 <u>접선은 어떻게 구하는가?</u>
<br></p>
<p>삼변수함수 $S:g(x,y,z)=k$와 $S$ 위의 점 $P(x_0, y_0, z_0)$를 지나는 임의의 curve $C$가 있다. 점 $P$에서의 접평면에서 수직이 되는 벡터 $∇F(P)$가 있다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/c1589a5a-bd5b-4c88-9ac7-8000eda42fcc/image.png" alt=""></p>
<ul>
<li>$f(x,y,z)$는 $P$에서 극값을 가진다.</li>
<li>$C$ : $\vec r(t)=⟨x(t),y(t),z(t)⟩$</li>
<li>$P$ : $\vec r(t_0)=⟨x_0, y_0, z_0⟩$</li>
</ul>
<p>$x(t),y(t),z(t)$을 함수 $f$에 대입해보면 $t$에 대한 일변수함수 $h(t):=f(⟨x(t),y(t),z(t))$가 된다. 이는 곡선 $C$ 위에서의 함수 $f$의 값이다.</p>
<p>$f$는 $P$에서 극값을 가지므로 $h(t)$는 $t_0$에서 극값을 갖는다. </p>
<p>$$
0=h&#39;(t_0)\</p>
<p>$$</p>
<p>(작성중)</p>
<br>

<h3 id="정리">정리</h3>
<p>이제 다시 정리해보면, $g(x,y)=k$와 접하는 $f(x,y)=c$ 에서 최소(최대) $c$를 찾아야 한다. $∇f$와 $∇g$ 가 평행하면 된다.</p>
<div style="display:flex; gap:10px;">
  <img src="https://velog.velcdn.com/images/son-dan-ha/post/825d2e44-cd5a-43ec-8645-9476e18077c5/image.png" style="width:50%;">
  <img src="https://velog.velcdn.com/images/son-dan-ha/post/27bd4772-4717-4c0c-9849-1266dd1f72fa/image.png" style="width:50%;">
</div>

<p>(a) 다음 식을 동시에 만족하는 $x,y,z,λ$ (라그랑주 승수 $λ$)를 모두 찾는다.</p>
<p>$$
∇f(x,y,z)=λ∇g(x,y,z)\
g(x,y,z)=k
$$</p>
<p>(b) 후보 점에서 f 값을 비교한다. (a)에서 구한 모든 점 $(x,y,z)$에 대해 $f(x,y,z)$ 값을 계산하여 그 중 가장 큰 값은 최대값, 가장 작은 값은 최소값이다.</p>
<p>(작성중)</p>
<p><br><br></p>
<hr>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://youtu.be/lmD9p6J_-TA?si=H9GSO2fDNdZol3vD">Lagrange Multiplier Method 라그랑주 승수법</a></li>
<li><a href="https://youtu.be/WQUQrMLDZxo?si=20V8L1oinQqJU5Vf">라그랑스 승수법 이해하기</a></li>
</ul>
<p><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ch_02] 4. 행렬]]></title>
            <link>https://velog.io/@son-dan-ha/Ch02-4.-%ED%96%89%EB%A0%AC</link>
            <guid>https://velog.io/@son-dan-ha/Ch02-4.-%ED%96%89%EB%A0%AC</guid>
            <pubDate>Sat, 01 Nov 2025 11:21:08 GMT</pubDate>
            <description><![CDATA[<h1 id="행렬이란">행렬이란?</h1>
<p>행렬은 가로와 세로 형태로 수 혹은 식을 나열한 것이다. 이때 가로줄을 행, 세로줄을 열이라고 한다. </p>
<p>$m$행 $n$열의 행렬 $a_{mn}$은 아래와 같이 표현한다. </p>
<p>$$
A =
\begin{bmatrix}
a_{11} &amp; a_{12} &amp; \cdots &amp; a_{1n} \
a_{21} &amp; a_{22} &amp; \cdots &amp; a_{2n} \
\vdots &amp; \vdots &amp; \ddots &amp; \vdots \
a_{m1} &amp; a_{m2} &amp; \cdots &amp; a_{mn}
\end{bmatrix}
$$</p>
<p>$a_{ij}$는 $i$행 $j$열에 위치하는 값(성분)이다.  </p>
<br>

<h2 id="단위행렬">단위행렬</h2>
<p>행과 열의 수가 같은 행렬을 <strong>정사각행렬</strong>이라고 하고, 성분 $a_{ij}(i=j)$이 1이고 다른 성분이 0인 정사각행렬을 <strong>단위행렬 $E$</strong>라고 한다.</p>
<p>$$
E =
\begin{bmatrix}
1 &amp; 0 &amp; 0 \
0 &amp; 1 &amp; 0 \
0 &amp; 0 &amp; 1 
\end{bmatrix}
$$</p>
<br>

<h2 id="행렬의-상등">행렬의 상등</h2>
<p>두 행렬 $A$, $B$에 대해서 대응하는 성분이 같은 경우 상등이라고 한다. </p>
<p>$$
A =
\begin{bmatrix}
5 &amp; 2 \
3 &amp; 1 
\end{bmatrix},</p>
<p>B =
\begin{bmatrix}
5 &amp; 2 \
3 &amp; 1
\end{bmatrix}
$$</p>
<p><br><br></p>
<hr>
<h1 id="행렬의-연산">행렬의 연산</h1>
<h2 id="합과-차">합과 차</h2>
<p>두 행렬 $A$, $B$에 대한 </p>
<p>$$
A =
\begin{bmatrix}
a_{11} &amp; a_{12}\
a_{21} &amp; a_{22}\
\end{bmatrix},
B =
\begin{bmatrix}
b_{11} &amp; b_{12}\
b_{21} &amp; b_{22}\
\end{bmatrix}
$$</p>
<br>

<p>합 $A+B$, 차 $A-B$는 같은 위치 성분끼리의 합과 차이며, 상수배 $3A$는 각 성분에 해당 상수(3)를 곱한 것이다. </p>
<p>$$
A+B = 
\begin{bmatrix}
a_{11} + b_{11} &amp; a_{12} + b_{12} \
a_{21} + b_{21} &amp; a_{22} + b_{22}
\end{bmatrix}
$$</p>
<p>$$
A-B = 
\begin{bmatrix}
a_{11} - b_{11} &amp; a_{12} - b_{12} \
a_{21} - b_{21} &amp; a_{22} - b_{22}
\end{bmatrix}
$$</p>
<p>$$
3A = 
\begin{bmatrix}
3\cdot a_{11} &amp; 3\cdot a_{12}\
3\cdot a_{21} &amp; 3\cdot a_{22}\
\end{bmatrix}
$$</p>
<br>

<h2 id="행렬곱">행렬곱</h2>
<p>두 행렬 $A$, $B$의 행렬곱 $AB$는 $A$의 $i$행을 행벡터로 $B$의 $j$열을 열벡터로 생각했을 때, 형벡터와 열벡터의 내적을 $i$행 $j$열의 성분으로 하는 행렬이다. 
<br></p>
<p>$$
AB =
\begin{bmatrix}
a_{11}b_{11} + a_{12}b_{21} &amp; a_{11}b_{12} + a_{12}b_{22} \
a_{21}b_{11} + a_{22}b_{21} &amp; a_{21}b_{12} + a_{22}b_{22}
\end{bmatrix}
$$</p>
<p>$$
BA =
\begin{bmatrix}
b_{11}a_{11} + b_{12}a_{21} &amp; b_{11}a_{12} + b_{12}a_{22} \
b_{21}a_{11} + b_{22}a_{21} &amp; b_{21}a_{12} + b_{22}a_{22}
\end{bmatrix}
$$</p>
<p>행렬 곱셈에는 교환법칙이 성립하지 않는다는 것을 알 수 있다. ($AB\neq BA$)</p>
<br>

<p>다만, 행렬곱이 가능한 단위행렬과의 행렬곱은 교환법칙이 성립한다. 
($AE = EA = A$)</p>
<br>


<p>$$
A =
\begin{bmatrix}
a_{11} &amp; a_{12} \
a_{21} &amp; a_{22}
\end{bmatrix},
\quad
E =
\begin{bmatrix}
1 &amp; 0 \
0 &amp; 1
\end{bmatrix}
$$</p>
<p>$$
EA =
\begin{bmatrix}
1 \cdot a_{11} + 0 \cdot a_{21} &amp; 1 \cdot a_{12} + 0 \cdot a_{22} \
0 \cdot a_{11} + 1 \cdot a_{21} &amp; 0 \cdot a_{12} + 1 \cdot a_{22}
\end{bmatrix}
= \begin{bmatrix}
a_{11} &amp; a_{12} \
a_{21} &amp; a_{22}
\end{bmatrix}
= A
$$</p>
<p>$$
AE =
\begin{bmatrix}
a_{11} \cdot 1 + a_{12} \cdot 0 &amp; a_{11} \cdot 0 + a_{12} \cdot 1 \
a_{21} \cdot 1 + a_{22} \cdot 0 &amp; a_{21} \cdot 0 + a_{22} \cdot 1
\end{bmatrix}
= \begin{bmatrix}
a_{11} &amp; a_{12} \
a_{21} &amp; a_{22}
\end{bmatrix}
= A
$$</p>
<br>

<h3 id="행렬곱-성립-조건">행렬곱 성립 조건</h3>
<p>행렬곱이 가능한 조건은 <strong>앞 행렬의 열 수 = 뒤 행렬의 행 수</strong>이다. </p>
<p>$A_{m×n}\cdot B_{p×q}$ 일 때, $n=p$를 만족하면 된다. 이때 결과 행렬의 크기는 $(m×q)$가 된다.</p>
<br>

<p>$$
A =
\begin{bmatrix}
2 &amp; 1 &amp; 3 \
4 &amp; 2 &amp; 5
\end{bmatrix},
\quad
B = \begin{bmatrix}
1 &amp; 4 \
3 &amp; 2 \
2 &amp; 1
\end{bmatrix}
$$</p>
<p>$$
C = AB
=\begin{bmatrix}
2\cdot1 + 1\cdot3 + 3\cdot2 &amp; 2\cdot4 + 1\cdot2 + 3\cdot1 \
4\cdot1 + 2\cdot3 + 5\cdot2 &amp; 4\cdot4 + 2\cdot2 + 5\cdot1
\end{bmatrix}
$$</p>
<br>

<h2 id="아다마르-곱hadamard-product">아다마르 곱(Hadamard product)</h2>
<p>아다마르 곱 ($A \circ B$)은 같은 열과 행 수를 같는 행렬에 대해 <strong>같은 위치의 성분</strong>을 곱한 것을 말한다. </p>
<p>$$
A \circ B =
\begin{bmatrix}
a_{11} &amp; a_{12} \
a_{21} &amp; a_{22}
\end{bmatrix}
\circ
\begin{bmatrix}
b_{11} &amp; b_{12} \
b_{21} &amp; b_{22}
\end{bmatrix}
= \begin{bmatrix}
a_{11}b_{11} &amp; a_{12}b_{12} \
a_{21}b_{21} &amp; a_{22}b_{22}
\end{bmatrix}
$$</p>
<p><br><br></p>
<hr>
<h1 id="행렬식det">행렬식(det)</h1>
<p>$\det A$는 정사각행렬 $A$가 공간의 <strong>부피를 얼마나(크기)·어떻게(방향)</strong> 바꾸는지를 나타내는 한 숫자다.</p>
<p>(작성중)</p>
<p><br><br></p>
<hr>
<h1 id="전치행렬">전치행렬</h1>
<p>전치행렬(transposed matrix)란 행렬 A의 i행 j열의 값을 j행 i열로 바꿔 얻은 행렬을 말한다. $A^T, \quad A^{\mathrm{T}}, \quad A&#39;, \quad {}^{t}!A$ 모두 전치행렬의 표기다. 이 책에서는 $A^T$를 사용한다. </p>
<br>

<p>$$
A =
\begin{bmatrix}
a_{11} &amp; a_{12} \
a_{21} &amp; a_{22}
\end{bmatrix}
= \begin{bmatrix}
2 &amp; 7 \
1 &amp; 8
\end{bmatrix}
$$</p>
<p>$$
A^T =
\begin{bmatrix}
a_{11} &amp; a_{21} \
a_{12} &amp; a_{22}
\end{bmatrix}
= \begin{bmatrix}
2 &amp; 1 \
7 &amp; 8
\end{bmatrix}
$$</p>
<br>

<h2 id="전치행렬의-성질">전치행렬의 성질</h2>
<p>행렬 $A$에 대한 전치행렬 $A^T$에 대한 <strong>전치 정의</strong> $(A^T)<em>{ij} = a</em>{ji}$</p>
<p><br><br></p>
<h3 id="1-att--a">1. $(A^T)^T = A$</h3>
<p>행렬 $A=[a_{ij}]$의 전치 $A^T$는 $(A^T)<em>{ij} = a</em>{ji}$이다. $(A^T)<em>{ij}$에 전치를 한번 더 취하면 $((A^T)^T)</em>{ij}=(A^T)_{ji}$가 된다. </p>
<p>전치 정의를 따르면 $(A^T)<em>{ji} = a</em>{ij}$이므로 $((A^T)^T)<em>{ij}=a</em>{ij}$이다. 모든 i, j에 대해 성립하므로 $(A^T)^T = A$</p>
<p><br><br></p>
<h3 id="2-a--bt--at--bt">2. $(A + B)^T = A^T + B^T$</h3>
<p>$A, B$는 같은 크기의 행렬이라 가정한다. 전치 정의에 따라 $(A + B)^T = A^T + B^T$에 대해 다음과 같이 좌변, 우변을 나눌 수 있다.</p>
<p>좌변 성분은
$$
((A+B)^T)<em>{ij}=(A+B)</em>{ji}=a_{ji}+b_{ji}
$$</p>
<p>우변 성분은</p>
<p>$$
(A^T+B^T)<em>{ij}=(A^T)</em>{ij}+(B^T)<em>{ij}=a</em>{ji}+b_{ji}
$$</p>
<p>모든 i,j에 대해 좌변성분 = 우변성분이 성립하므로 $(A + B)^T = A^T + B^T$</p>
<p><br><br></p>
<h3 id="3-kat--kat-quad-k-in-mathbbr">3. $(kA)^T = kA^T \quad (k \in \mathbb{R})$</h3>
<p>좌변 성분은
$$
( (kA)^T )<em>{ij} = (kA)</em>{ji} = k\cdot a_{ji}
$$</p>
<p>우변 성분은
$$
(kA^T)<em>{ij} = k\cdot (A)</em>{ij} = k\cdot a_{ji}
$$</p>
<br>


<blockquote>
<h4 id="전치의-선형성">전치의 선형성</h4>
<p>2번의 $(A + B)^T = A^T + B^T$와 3번의 $(kA)^T = kA^T \quad (k \in \mathbb{R})$로 전치는 <strong>선형성</strong>을 가진 연산이다. (앞서 수열에서 선형성을 알아본 바 있음)</p>
</blockquote>
<br>


<h3 id="4-abt--bt-at">4. $(AB)^T = B^T A^T$</h3>
<p>$A$는 $m\times n$, $B$는 $n\times p$의 행렬이라 가정한다. 전치 정의는 위와 같고, 행렬곱 성분은 $(AB)<em>{ji}=\sum</em>{k=1}^{n}a_{jk}b_{kj}$일 때, </p>
<p>좌변 성분은
$$
((AB)^T)<em>{ij}
= (AB)</em>{ji}
= \sum_{k=1}^{n} a_{jk}, b_{ki}
$$</p>
<p>우변 성분은
$$
(B^T A^T)<em>{ij}
= \sum</em>{k=1}^{n} (B^T)<em>{ik} (A^T)</em>{kj}
= \sum_{k=1}^{n} b_{ki}, a_{jk}
$$</p>
<p><br><br></p>
<h3 id="5-정사각행렬">5. 정사각행렬</h3>
<blockquote>
<p>$A$가 <strong>정사각행렬</strong>이면 $A$ 와 $A^T$는 같은 고윳값을 가진다.</p>
</blockquote>
<br>

<h4 id="고윳값이란">고윳값이란?</h4>
<p>어떤 특별한 방향의 벡터는 방향은 안 바뀌고 크기만 변한다. 그 벡터를 고유벡터(eigenvector) $v$라고 하며, 벡터의 크기가 변하는 비율을 고윳값(eigenvalue) $λ$이라고 한다. 고윳값은 스칼라다. </p>
<p>$$
Av=λv
$$</p>
<p>$A$가 $v$를 변환해도 방향은 그대로, 크기만 $λ$배 된다.</p>
<p>고윳값 $λ$를 구하기 위한 과정이다.</p>
<p>$$
Av=λv \
Av-λv=0 \
v(A-λI)=0
$$</p>
<p>이때, 단위행렬 $I$가 붙는 이유는 λv 는 “벡터 $v$를 $λ$배 한 것이므로, 행렬 형태로 쓰려면 $λIv$ 로 표현한다. </p>
<br>

<h4 id="특성다항식이란">특성다항식이란?</h4>
<p>$v(A-λI)=0$에서 $v\neq0$ 이 되려면 $det(A-λI)=0$ 이는 λ에 대한 다항식 형태가 되고 이것을 <strong>특성다항식(characteristic polynomial)</strong>이라고 한다.</p>
<p>$$
pA(λ)=det(λI−A)
$$</p>
<br>

<h4 id="증명">증명</h4>
<p>정사각행렬 $A$의 특성다항식을 $pA(λ)=det(λI−A)$라고 할 때, </p>
<p>전치의 분배 ($(X-Y)^T=X^T-Y^T$ , $(λI)^T=λI$)를 이용하면,</p>
<p>$$
p_{A^T}(\lambda)
= \det(\lambda I - A^T)
= \det!\big((\lambda I - A)^T\big)
$$</p>
<p>전치와 행렬식의 성질 $det(X^T)=det(X)$ 을 이용하면,</p>
<p>$$
\det!\big((\lambda I - A)^T\big)
= det(\lambda I - A)
= p_A(\lambda)
$$</p>
<p>따라서 $A$와 $A^T$의 특성다항식이 같아 고윳값이 동일하다.</p>
<p><br><br></p>
<h3 id="6-대칭행렬">6. 대칭행렬</h3>
<blockquote>
<p>$A$가 <strong>대칭행렬</strong>이면 $A^T = A$</p>
</blockquote>
<p>(작성중)</p>
<p><br><br></p>
<h3 id="7-반대칭행렬">7. 반대칭행렬</h3>
<blockquote>
<p>$A$가 <strong>반대칭행렬</strong>이면 $A^T = -A$</p>
</blockquote>
<p>(작성중)</p>
<p><br><br></p>
<h3 id="8-가역">8. 가역</h3>
<blockquote>
<p>$A$가 <strong>가역</strong>이면 $(A^{-1})^T = (A^T)^{-1}$</p>
</blockquote>
<p>(작성중)</p>
<p><br><br></p>
<h3 id="9-내적-관련">9. 내적 관련</h3>
<p>$$
(x^T y) = (y^T x)
$$</p>
<p>(작성중)</p>
<p><br><br></p>
<h3 id="10-랭크-보존">10. 랭크 보존</h3>
<p>$$
\operatorname{rank}(A) = \operatorname{rank}(A^T)
$$</p>
<p>(작성중)</p>
<p><br><br></p>
<hr>
<h1 id="reference">Reference</h1>
<ul>
<li>알기 쉬운 선형대수 (12판). Howard Anton , Chris Rorres , Anton Kaul. 한티에듀, 2021</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ch_02] 3. 벡터]]></title>
            <link>https://velog.io/@son-dan-ha/Ch02-3.-%EB%B2%A1%ED%84%B0</link>
            <guid>https://velog.io/@son-dan-ha/Ch02-3.-%EB%B2%A1%ED%84%B0</guid>
            <pubDate>Wed, 29 Oct 2025 06:07:54 GMT</pubDate>
            <description><![CDATA[<h1 id="1-유향선분이란">1. 유향선분이란?</h1>
<p>유향선분(directed segment)은 <strong>방향</strong>을 갖는 선분(line segment)을 말한다.</p>
<p>시작점이 A이며 종점이 B인 유향선분 AB가 있다고 할 때, 유향선분의 <strong>속성</strong>은 아래와 같다.</p>
<ul>
<li>점 A의 위치</li>
<li>B에 관한 방향</li>
<li>AB의 크기(길이)</li>
</ul>
<br>


<hr>
<h1 id="2-벡터란">2. 벡터란?</h1>
<p>벡터(vector)는 방향과 크기를 추상화한 양이다. 유향선분 AB의 대표 벡터를 $\overrightarrow{AB}$ 혹은 $\vec{a}$ 혹은 굵은 문자 $\boldsymbol{a}$ 등으로 표현한다. </p>
<br>

<h2 id="2-1-벡터의-성분-표시">2-1. 벡터의 성분 표시</h2>
<p>벡터는 다음과 같이 화살표선으로 그려지는데, 이를 좌표 평면에 배치하여 표현할 수 있다. 시작점을 원점에 놓고 <strong>종점의 좌표</strong>로 벡터를 나타내는 것을 <strong>벡터의 성분 표시</strong>라고 한다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/dbed9eb0-bee8-4da8-8ece-dac884d34c54/image.png" alt=""></p>
<p>이때 벡터의 성분 표시는 종점의 좌표인  $(a_1, a_2)$</p>
<br>


<h2 id="2-2-벡터의-크기">2-2. 벡터의 크기</h2>
<p>벡터를 나타내는 화살표선의 길이를 벡터의 크기라고 한다.  $\vec{a}$의 크기는 $|\vec{a}|=\sqrt{{a_1}^2+{a_2}^2}$ 이다.</p>
<p><br><br></p>
<hr>
<h1 id="3-벡터의-내적">3. 벡터의 내적</h1>
<p>벡터를 곱할 때는 크기와 방향을 고려해야 한다. 벡터의 내적이란 크기(스칼라)만을 고려한 벡터의 곱셈을 말한다. $\vec{a}$, $\vec{b}$ 의 내적은 $\vec{a}\cdot\vec{b}$이다. </p>
<p>$$
\vec{a}\cdot\vec{b}=|\vec{a}||\vec{b}|\cos\theta
$$</p>
<p>$\theta$는 $\vec{a}$, $\vec{b}$가 구성하는 각도다.</p>
<br>


<h2 id="3-1-코시-슈바르츠-부등식">3-1. 코시-슈바르츠 부등식</h2>
<p>$\cos\theta$는 $-1\le\cos\theta\le1$의 범위를 같는다. 여기에 벡터의 크기 $|\vec{a}||\vec{b}|$를 대입하면,</p>
<p>$$
-|\vec{a}||\vec{b}|\le|\vec{a}||\vec{b}|\cos\theta\le|\vec{a}||\vec{b}|
$$</p>
<p>$|\vec{a}||\vec{b}|\cos\theta=\vec{a}\cdot\vec{b}$ (벡터의 내적) 이므로,</p>
<p>$$
-|\vec{a}||\vec{b}|\le\vec{a}\cdot\vec{b}\le|\vec{a}||\vec{b}|
$$</p>
<p>이 성립니다. 이를 코시-슈바르츠 부등식이라고 한다. </p>
<br>

<p>내적이란 <strong>두 벡터가 어느정도로 같은 방향을 향하</strong>고 있는가다. 코시-슈바르츠 부등식에서 알 수 있는 3가지가 있다.</p>
<ol>
<li>두 벡터가 반대 방향일 때 내적은 최솟값을 갖는다.</li>
<li>두 벡터가 평행하지 않을 때 내적은 반대 방향일 때와 평행일 때의 중간값이다.</li>
<li>두 벡터가 평행할 때 내적의 최댓값을 갖는다.</li>
</ol>
<p>즉, 두 벡터가 <strong>같은 방향</strong>을 향할수록 <strong>내적은 커</strong>진다. </p>
<br>

<h2 id="3-2-내적의-성분-표시">3-2. 내적의 성분 표시</h2>
<p>앞서 <strong>벡터의 성분 표시</strong>를 $\vec{a}=(a_1,a_2)$ 로 나타냈다. 이를 내적의 성분 표시로 표현하면 아래와 같다.</p>
<p>$$
\vec{a}\cdot\vec{b}=a_1b_1+a_2b_2
$$</p>
<p>3차원이라면, 
$$
\vec{a}\cdot\vec{b}=a_1b_1+a_2b_2+a_3b_3
$$</p>
<br>

<p>$\vec{a}=(2,3,2), \vec{b}=(5,1,-1)$ 경우,</p>
<p>$$
\vec{a}\cdot\vec{b}=2\cdot5+3\cdot1+2\cdot(-1)=17
$$</p>
<p><br><br></p>
<hr>
<h1 id="4-벡터의-일반화">4. 벡터의 일반화</h1>
<p>지금까지는 2,3차원의 벡터를 살펴보았다. 2,3차원의 벡터의 성질을 수만 차원의 벡터로 확장할 수 있다. 따라서 신경망의 경사하강법에서 벡터를 사용하게 된다. </p>
<br>

<p>이제 n차원의 벡터를 살펴보도록 한다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/a71e0720-a795-40c5-8463-4f2b5e43d640/image.png" alt=""></p>
<p>위와 같은 신경망이 있을 때 가중 입력 $z=w_1x_1+w_2x_2+...+w_nx_n+b$이다. </p>
<p>이 가중 입력 $z$를 벡터로 간주하여 다뤄보자. </p>
<p>입력 $x$와 가중치 $w$를 벡터의 성분으로 표시하면,</p>
<p>$$
\vec{x}=(x_1,x_2,...,x_n)
, 
\vec{w}=(w_1,w_2,...,w_n)
$$</p>
<p>$z$를 내적 형태로 바꾸면, </p>
<p>$$
z= \vec{w}\cdot\vec{x}+b
$$</p>
<br>

<h2 id="4-1-텐서tensor">4-1. 텐서(tensor)</h2>
<p>텐서(tensor)란 물리학의 <strong>변형력 텐서</strong>를 수학적으로 추상화한 것이다. 벡터의 개념을 확장한 것으로 동일한 성질의 <strong>벡터를 행렬로 표기</strong>한다. </p>
<p><strong>응력</strong>이란 외부에서 힘을 가하면 그 힘을 내부에서 버티려고 생기는 힘 혹은 면적을 말한다. </p>
<p>$$
\sigma=\frac{A}{F}
$$</p>
<p>$\sigma$ : 응력 (stress)
$F$ : 힘이 작용하는 단면적 (area)
$A$ : 물체에 작용하는 외력 (force)</p>
<br>
변형력 텐서란 응력을 수학적으로 표현한 2차 텐서다. 외부 힘이 가해지는 경우 물체 내부에서는 힘의 방향과 면의 방향(법선)에서 두 방향을 모두 가져야 하기에 2차 텐서가 필요하다. 

<p>참고로 변형력 텐서는 3x3의 행렬인데, 이는 3차원 공간에서의 3개의 면과 3개의 힘 방향을 모두 표현한다. </p>
<br>

<p>$$
\boldsymbol{\sigma} =
\begin{bmatrix}
\sigma_{xx} &amp; \sigma_{xy} &amp; \sigma_{xz} \
\sigma_{yx} &amp; \sigma_{yy} &amp; \sigma_{yz} \
\sigma_{zx} &amp; \sigma_{zy} &amp; \sigma_{zz}
\end{bmatrix}
$$</p>
<p><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ch_02] 2. 수열과 시그마 기호]]></title>
            <link>https://velog.io/@son-dan-ha/Ch02-2.-%EC%88%98%EC%97%B4%EA%B3%BC-%EC%8B%9C%EA%B7%B8%EB%A7%88-%EA%B8%B0%ED%98%B8</link>
            <guid>https://velog.io/@son-dan-ha/Ch02-2.-%EC%88%98%EC%97%B4%EA%B3%BC-%EC%8B%9C%EA%B7%B8%EB%A7%88-%EA%B8%B0%ED%98%B8</guid>
            <pubDate>Wed, 29 Oct 2025 04:26:29 GMT</pubDate>
            <description><![CDATA[<h1 id="수열">수열</h1>
<p>수열은 숫자의 열을 의미하며 숫자 하나를 <strong>항</strong>이라고 한다. 수열은 유한개 항을 갖는 <strong>유한 수열</strong>과 무한개 항 수를 갖는 <strong>무한 수열</strong>이 있다.</p>
<br>

<h2 id="수열의-일반항">수열의 일반항</h2>
<p>수열의 n번째 항을 $a_n$ 같이 표현하고 n을 이용한 식으로 나타낸 것을 <strong>수열의 일반항</strong>이라고 한다. </p>
<p>만약 짝수 2, 4, 6, 8 등으로 구성된 수열이 있다면 수열의 일반항은 $a_n=2n$ 처럼 표현할 수 있다. </p>
<p>신경망에서는 유닛의 가중 입력(z)와 출력을 수열로 간주한다. $l$층의 $j$번째 유닛의 출력값은 $a_{j}^{l}$ 처럼 표현한다.</p>
<p><br><br></p>
<h1 id="점화식">점화식</h1>
<p>수열의 점화식이란 수열 $a_n$을 $a_1$과 $a_n$, $a_{n+1}$의 관계식으로 표현한 것을 말한다. </p>
<p>아래는 피보나치 수열 $F_n$을 점화식으로 표현한 것이다.
$$
\begin{cases}
F_0 = 0, \
F_1 = 1, \
F_n = F_{n-1} + F_{n-2} \quad (n \ge 2)
\end{cases}
$$</p>
<br>

<h2 id="연립-점화식">연립 점화식</h2>
<p>수열 $a_n$과 $b_n$ 등 여러 수열에 대해 관계식으로 연결한 것은 <strong>연립 점화식</strong>이라고 한다. </p>
<p>앞서 유닛의 가중 입력과 출력을 수열로 간주한다고 했다. 각각의 유닛의 출력값을 각각의 수열로 본다면 연립 점화식 표현가능하다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/71846a7a-1c24-413f-a731-4bec7d1cce5e/image.png" alt=""></p>
<p>신경망의 일부가 다음과 같을 때 세번째 층의 출력은 두번째 층의 출력을 입력 신호로 받는다. 이 관계를 연립 점화식으로 표현하면 아래와 같다. </p>
<p>$$
a_{3}^{1} = a(\mathbf{w}<em>{11}^{3} \mathbf{a}</em>{1}^{2}+\mathbf{w}<em>{12}^{3} \mathbf{a}</em>{2}^{2}+\mathbf{w}<em>{13}^{3} \mathbf{a}</em>{3}^{2} + b_{1}^{3})
$$</p>
<p>$$
a_{3}^{2} = a(\mathbf{w}<em>{21}^{3} \mathbf{a}</em>{1}^{2}+\mathbf{w}<em>{22}^{3} \mathbf{a}</em>{2}^{2}+\mathbf{w}<em>{23}^{3} \mathbf{a}</em>{3}^{2} + b_{1}^{3})
$$ </p>
<br>

<p>신경망에서 <strong>오차역전파법</strong>은 이러한 점화식을 응용한다. 컴퓨터는 점화식 계산에 강점이 있다. 따라서 오차역전파법에 이러한 컴퓨터의 점화식 계산 방법이 유용하게 사용된다.</p>
<p><br><br></p>
<h1 id="시그마-기호">시그마 기호</h1>
<p>시그마 기호를 사용하면 <strong>수열의 합</strong>을 간결하게 표현할 수 있다. </p>
<p>$$
a_{3}^{1}
= a!\left( \sum_{j=1}^{3} w_{1j}^{3} , a_{j}^{2} + b_{1}^{3} \right)
$$</p>
<br>


<h2 id="시그마의-선형성">시그마의 선형성</h2>
<p><strong>선형성</strong>이란 서로 대응하는 두 값의 변화가 어떤 비례 관계를 갖는 규칙으로 표현할 수있는 성질을 말한다.</p>
<p>시그마의 선형성으로 아래와 같은 관게가 성립된다.</p>
<p>$$
\sum_{k=1}^{n} (a_k + b_k) = \sum_{k=1}^{n} a_k +  \sum_{k=1}^{n} b_k
$$</p>
<p>$$
\sum_{k=1}^{n} c\cdot a_k = c\sum_{k=1}^{n} a_k 
$$</p>
<br>

<p>$2n+1$의 합을 시그마 기호로 아래와 같이 표현 가능하다.</p>
<p>$$
\sum_{k=1}^{n} (2k+1) = 2\sum_{k=1}^{n} k + \sum_{k=1}^{n} 1 =  2\cdot\frac{n(n-1)}{2}+n
$$</p>
<p><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ch_02] 1. 신경망의 필수 함수]]></title>
            <link>https://velog.io/@son-dan-ha/Ch02-1.-%EC%8B%A0%EA%B2%BD%EB%A7%9D%EC%9D%98-%ED%95%84%EC%88%98-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@son-dan-ha/Ch02-1.-%EC%8B%A0%EA%B2%BD%EB%A7%9D%EC%9D%98-%ED%95%84%EC%88%98-%ED%95%A8%EC%88%98</guid>
            <pubDate>Mon, 27 Oct 2025 17:00:59 GMT</pubDate>
            <description><![CDATA[<p>두번째 장에서는 신경망을 위한 수학 기초를 복습한다. 우선 필수 함수를 가볍게 살펴보자.</p>
<h1 id="1차-함수">1차 함수</h1>
<p>1차 함수는 직선이다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/bb0c2ac1-37b1-4605-aa29-77fc7a37815a/image.png" alt=""></p>
<h2 id="1-절편과-기울기">1. 절편과 기울기</h2>
<p><u>좌표평면에서 그래프가 축과 만나는 지점</u>을 <strong>절편</strong>이라고 한다. $y=x+1$에서 x절편은 -1, y절편은 1이다. </p>
<p><strong>기울기</strong>는 <u>x값의 변화량에 대한 y값의 변화량</u>을 말한다. 1차 함수는 그 변화량이 어느 지점에서든 일정하다. $y=x+1$ 의 기울기는 1이다. ($\frac{dy}{dx}=1$)</p>
<p>딥러닝에서 <strong>gradient</strong>(경사)가 바로 기울기다. <strong>경사 하강법</strong>을 공부할 때 자세히 알아보도록 하자. </p>
<br>

<h2 id="2-독립변수와-종속변수">2. 독립변수와 종속변수</h2>
<p>$y=x+1$에서 변수는 $y, x$로 두 종류가 있다. $x$가 주어졌을 때 $y$가 결정되는 관계라면 x를 <strong>독립변수</strong>, y를 <strong>종속변수</strong>라고 한다. </p>
<h3 id="초평면hyperplane">초평면(hyperplane)</h3>
<p>독립변수는 $y=ax_1+bx_2+c$처럼 여러 개일 수 있다. ($a\neq0, b\neq0$) 딥러닝에서는 x를 특징(feature)으로 본다. 보통 하나 이상의 특징이 있으므로 여러 개의 독립변수가 있는 상황이 일반적이다. </p>
<p>앞서 1차 함수를 직선이라고 했지만, 독립변수가 n개인 1차 함수는 기하학적 공간에서 ‘초평면(hyperplane)’으로 표현된다.
예를 들어 독립변수가 1개일 때는 2차원 공간의 직선, 독립변수가 2개일 때는 3차원 공간의 평면이 된다. 이것을 일반화하면 n개의 독립변수를 가진 함수는 (n+1)차원 공간에서 초평면이 된다.</p>
<p>아래는 3차원의 공간에서 평면으로 표현된 $z=x+y$ 그래프다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/230688d2-191d-4f87-b218-41f59c793ff1/image.png" alt=""></p>
<p>초평면은 <strong>분류(Classification)</strong>에서 <strong>결정경계(boundary)</strong>가 된다는 것을 알고 있으면 된다. </p>
<br>

<h2 id="3-가중입력-z">3. 가중입력 $z$</h2>
<p>앞서 신경망에서는 뉴닛이 받는 가중 입력 $z$가 1차 함수 관계 $z=w_1x_1+w_2x_2+w_3x_3+b$ 로 표현되었다. </p>
<p>가중치 $w$와 편향 $b$를 상수 파라미터라고 보면 가중 입력 $z$는 $x_1, x_2,x_3$와 1차 함수 관계이다.</p>
<p><br><br></p>
<hr>
<h1 id="2차-함수">2차 함수</h1>
<p>2차 함수는 포물선이다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/1125ea1f-af5e-4ea9-b8ae-c16ea6e089a7/image.png" alt=""></p>
<h2 id="1-최솟값과-최댓값">1. 최솟값과 최댓값</h2>
<p>2차 함수는 최솟값과 최댓값을 갖는다는 특징이 있다. $y=x^2-1$ 처럼 최대차항이 양수라면 최솟값이 존재하고 $y=-x^2+1$ 처럼 음수라면 최댓값이 존재한다.</p>
<h3 id="최소제곱법">최소제곱법</h3>
<p>2차 함수의 최솟값은 딥러닝에서 최소 제곱법의 기본이 된다. 최소제곱법은 “<strong>오차 제곱합</strong>”이라는 2차 함수를 만들고,
그 함수의 최솟값을 찾는 과정을 말한다. 신경망에서는 <strong>최적화</strong> 과정을 생각하면 된다. </p>
<br>

<h2 id="2-hypersurface">2. hypersurface</h2>
<p>2차 함수는 독립변수가 여러 개일 때 hypersurface가 된다. 1차 함수가 고차원 공간에서 초평면을 만든다면, 2차 함수는 그에 대응되는 곡면(포물면)을 만든다.</p>
<p>아래는 3차원 공간에서 곡면으로 표현된 $z=x^2+y^2-2$ 그래프다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/d04da4d0-dcb3-4882-8fa8-3a2d33b8d6e0/image.png" alt=""></p>
<p><br><br></p>
<hr>
<h1 id="지수함수">지수함수</h1>
<p>지수함수는 $y=a^x$ ($a$는 1이 아닌 양의 상수) 형태를 갖는다. 이때 $a$를 <strong>밑(base)</strong>이라고 하며 딥러닝에서는 $a$ 값으로 주로 자연상수 $e$가 들어간다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/0f671e80-b24c-40d4-a3d3-686623da5a45/image.png" alt=""></p>
<br>

<h2 id="1-자연상수-e">1. 자연상수 $e$</h2>
<p>자연상수 $e$는 딥러닝의 지수적 표현에서 매우 자주 등장하는 상수이다. 이 값은 단순한 2.718... 인 숫자가 아니라, <strong>특정 수열의 극한</strong>으로 정의된다. </p>
<p>아래에서는</p>
<p>$$
a_n=(1+\frac{1}{n})^n
$$</p>
<p>라는 수열이 <strong>단조수렴</strong>함을 보이고, 그 <strong>극한값</strong>이 $e$가 됨을 확인한다. </p>
<p>수열이 수렴하기 위해서는 두 가지를 만족해야 한다.</p>
<ol>
<li>단조 (monotonic)</li>
<li>유계 (bounded)</li>
</ol>
<br>

<h3 id="수열-a_n-단조-증가-증명">수열 $a_n$ 단조 증가 증명</h3>
<h4 id="보조부등식-x-1">보조부등식 ($x&gt;-1$)</h4>
<p>$$
\ln(1+x)\ge\frac{x}{1+x}
$$ </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/3a1b172c-c104-499c-b65d-c2b281adf557/image.png" alt=""></p>
<p>$\ln x$는 오목(concave)함수다. 오목 함수는 항상 접선보다 아래에 있으며, 평균기울기 ≥ 순간기울기 라는 특징을 가진다. </p>
<p>$\frac{f(x)-f(0)}{x}\ge f&#39;(x)$ 에서 $f(x)=\ln(1+x)$ 라면,</p>
<p>$$
\frac{\ln(1+x)-\ln 1}{x}\ge \frac{1}{1+x}
$$</p>
<p>$$
\frac{\ln(1+x)}{x}\ge \frac{1}{1+x}
$$</p>
<p>$$
\ln(1+x)\ge \frac{x}{1+x}
$$ 
으로 해당 보조부등식을 활용할 수 있다.</p>
<br>

<h4 id="단조-증가-증명">단조 증가 증명</h4>
<p>$a_n = \left(1+\frac{1}{n}\right)^n$에 양변 로그, </p>
<p>$$
\ln a_n = n \ln\left(1+\frac{1}{n}\right)
$$</p>
<p>1의 보조부등식에서 $x=\frac{1}{m}$ 라면,</p>
<p>$$
\ln\left(1+\frac{1}{m}\right) \ge \frac{1}{m+1}
$$</p>
<p>이제 $\ln a_{n+1} - \ln a_n&gt; 0$ 를 보조부등식을 활용하여 증명하면 된다.</p>
<p>$$
\ln a_{n+1} = (n+1)\ln\left(1+\frac{1}{n+1}\right)\ge \frac{n+1}{n+2}
$$</p>
<p>$$
\ln a_{n} = n\ln\left(1+\frac{1}{n}\right)\ge \frac{n}{n+1}
$$</p>
<p>구하고자 하는 값 $\ln a_{n+1} - \ln a_n$은 각각의 하한값을 뺀 값보다는 클 것이므로  </p>
<p>$$
\ln a_{n+1} - \ln a_n \ge \frac{n+1}{n+2} - \frac{n}{n+1}
$$ </p>
<p>$$
\frac{n+1}{n+2} - \frac{n}{n+1}= \frac{1}{(n+1)(n+2)} &gt; 0
$$</p>
<p>$$
\ln a_{n+1} - \ln a_n &gt; 0
$$</p>
<br>

<h3 id="수열-a_n-유계상한-증명">수열 $a_n$ 유계(상한) 증명</h3>
<p>위에서 $a_n$이 단조 증가함을 확인했다. 이제 $a_n$ 어떤 값보다 항상 작다는 사실을 확인하자.</p>
<p>$a_n$을 전개하면, 
$$
\left(1+\frac{1}{n}\right)^n = \sum_{k=0}^{n} \binom{n}{k}\frac{1}{n^k}
$$</p>
<p>$$
\binom{n}{k}=\frac{n(n−1)⋯(n−k+1)}{k!}\le \frac{n^k}{k!}
$$ 
임을 활용해</p>
<p>$$
\sum_{k=0}^{n} \binom{n}{k}\frac{1}{n^k} \le \sum_{k=0}^{n} \frac{n^k}{k!}\cdot \frac{1}{n^k}
= \sum_{k=0}^{n} \frac{1}{k!}
$$</p>
<p>$$
a_n \le \sum_{k=0}^{n} \frac{1}{k!}
$$</p>
<p>$$
\sum_{k=0}^{n} \frac{1}{k!} &lt; \sum_{k=0}^{\infty} \frac{1}{k!} = e
$$
따라서, 
$$
a_n &lt; e
$$</p>
<br>

<h3 id="수열-a_n의-극한값">수열 $a_n$의 극한값</h3>
<p>$a_n$은 단조 증가하고 위로 유계이므로 단조수렴정리에 의해 극한이 존재한다. 그 극한값을 자연상수 $e$라고 정의한다.</p>
<p>수열의 극한을 $L$ 이라고 하면,</p>
<p>$$
L = \lim_{n\to\infty} \left(1+\frac{1}{n}\right)^n
$$</p>
<p>$$
\ln L
= \lim_{n\to\infty} n \ln\left(1+\frac{1}{n}\right)
= \lim_{n\to\infty} \frac{\ln\left(1+\frac{1}{n}\right)}{1/n}
$$
이때 $\frac{0}{0}$ 꼴이므로 
$$
\ln L = \lim_{x\to 0} \frac{\ln(1+x)}{x} = 1
$$</p>
<p>$$
L=e
$$</p>
<br>

<h3 id="결론">결론</h3>
<p>$$
e = \lim_{n\to\infty} \left(1+\frac{1}{n}\right)^n
$$</p>
<p>이 과정을 통해 자연상수 $e$는 “단지 2.718...” 이 아니라
특정 수열이 단조 증가하며 유계 내에서 수렴해 얻어지는 값임을 알 수 있다. </p>
<p><br><br></p>
<h2 id="2-시그모이드-함수">2. 시그모이드 함수</h2>
<p>해당 시리즈에서는 활성화 함수로 시그모이드 함수를 사용한다.</p>
<p>$$
\sigma(x) = \frac{1}{1+e^{-x}} = \frac{1}{1+exp(-x)}
$$</p>
<p>시그모이드 함수는 자연상수를 포함하는 지수함수를 분모로 갖는 함수이다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/d12c0714-9f7b-4dff-8ae7-f0142b453bc9/image.png" alt=""></p>
<p>시그모이드함수는 <strong>단위 계단 함수</strong>(선형 응답 함수)와는 다르게 함수값이 <u>0과 1 사이</u>로 확률을 계산할 수 있고 어디서나 <u>미분가능</u>하다. </p>
<p>각각의 모델(신경망)에 적합한 활성화 함수를 사용하므로 시그모이드 함수 이외의 매우 다양한 활성화 함수가 존재한다. 대표적으로는 ReLU(렐루)와 Tanh(하이퍼볼릭 탄젠트), Softmax(소프트맥스) 등이 있다. </p>
<p><br><br></p>
<hr>
<h1 id="확률밀도-함수">확률밀도 함수</h1>
<p>신경망은 결국 컴퓨터가 연산한다. 따라서 모델을 동작시킬 때 <u>가중치와 편향의 초깃값을 설정</u>해야 한다. 주로 초깃값에는 <strong>정규분포를 따르는</strong> 난수를 넣는다. 이 경우 성능이 더 좋다고 한다.</p>
<p>정규분포란 확률밀도함수를 따르는 확률분포를 말한다. </p>
<p>확률분포에는 이산형 변수로 구성된 이산확률분포와 연속형 변수로 구성된 연속확률분포가 있다. 그 값이 연속적이면 분포표로 확인하지 않고 그래프로 표현한다. 그것이 확률밀도함수다. 확률밀도 함수 $f(x)$는 아래와 같다. </p>
<p>$$
f_X(x) =
\frac{1}{\sqrt{2\pi}\sigma}
\exp!\left(
    -\frac{(x-\mu)^2}{2\sigma^2}
\right)
$$</p>
<p><br><br></p>
<hr>
<h1 id="reference">Reference</h1>
<ul>
<li>자연상수 e : <a href="https://youtu.be/z1xeFi5N5go?si=exA38Z-Sy4ZATQtW">https://youtu.be/z1xeFi5N5go?si=exA38Z-Sy4ZATQtW</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[RNN (Recurrent Neural Network)]]></title>
            <link>https://velog.io/@son-dan-ha/RNN-Recurrent-Neural-Network</link>
            <guid>https://velog.io/@son-dan-ha/RNN-Recurrent-Neural-Network</guid>
            <pubDate>Thu, 11 Sep 2025 06:19:57 GMT</pubDate>
            <description><![CDATA[<h1 id="들어가며">들어가며...</h1>
<p>요즘은 Vanilla RNN을 직접 쓰는 경우가 거의 없다. 긴 의존 관계를 제대로 학습하지 못하고, 역전파 과정에서 기울기가 소실·폭발하는 문제까지 안고 있기 때문이다. 대신 Transformer가 사실상 모든 시퀀스 처리 문제의 표준으로 자리 잡았다.</p>
<p>그럼에도 RNN을 건너뛰어버리면 Transformer가 왜 혁신이었는지 맥락을 놓치기 쉽다. 은닉 상태를 이용해 과거 정보를 이어가는 순환 신경망의 발상은 이후 LSTM, GRU 같은 변형 모델로 이어졌고, 결국 Transformer의 아이디어와도 비교되는 출발점이 된다.</p>
<p>이번 글에서는 우선 <strong>기본 RNN</strong>의 구조와 동작 방식을 살펴본다. 이를 통해 순환 구조의 장단점을 이해하고, 이어질 글에서 LSTM과 GRU를 다루며 Transformer가 왜 필요했는지를 더 분명히 드러내고자 한다.</p>
<br>

<hr>
<h1 id="state-space-model-as-rnn">State-Space Model as RNN</h1>
<p>State-Space Model의 관점에서 RNN을 이해해보자. </p>
<h2 id="first-order-system">First Order System</h2>
<h4 id="1-x_tfx_t-1">1. $x_t=f(x_{t-1})$</h4>
<p>현재 시간의 상태가 이전 시간의 상태와 관련이 있다고 가정한다. </p>
<ul>
<li>$x$ : 상태 (시세, 날씨, 점수)</li>
<li>$t$ : 시간 </li>
<li>$x_t$ : t일 때의 상태</li>
</ul>
<p>이 시스템은 외부 입력 없이 자기 혼자서 돌아가는 <strong>autonomous system</strong> 이다.</p>
<br>


<h4 id="2-x_tfx_t-1-u_t">2. $x_t=f(x_{t-1}, u_t)$</h4>
<p>현재 시간의 상태 $x_t$가 이전 시간의 상태 $x_{t-1}$와 현재의 입력$u_t$에 관련이 있다고 가정한다.</p>
<ul>
<li>$x$ : 상태</li>
<li>$u$ : 입력 </li>
</ul>
<br>


<h2 id="state-space-model">State-Space Model</h2>
<p>1차원 시스템의 모형 $x_t=f(x_{t-1}, u_t)$ 에서 $x_t$의 관측 가능성을 따져보자.</p>
<p>모든 시간 t에서 모든 상태 $x_t$</p>
<p>ANN과의 가장 큰 차이는 시간에 따라 변화하는 Weight를 공유한다는 것이다.</p>
<hr>
<h1 id="시퀀스-데이터란">시퀀스 데이터란?</h1>
<p>시퀀스 데이터(sequence data)는 순서가 중요한 데이터를 말한다.</p>
<ul>
<li>텍스트: 단어의 순서에 따라 문장의 의미가 달라짐</li>
<li>음성: 시간 축에 따라 신호가 이어짐</li>
<li>주가·날씨 같은 시계열 데이터: 앞뒤 맥락에 따라 패턴이 정해짐</li>
<li>영상: 프레임이 순서대로 쌓여야 의미가 유지됨</li>
</ul>
<p>일반적인 MLP는 입력을 독립적으로 처리하기 때문에 이런 순서를 직접 고려하지 못한다. 반면 RNN은 은닉 상태를 통해 이전 시점의 정보를 현재로 전달하여 순서와 맥락을 학습할 수 있다.</p>
<h2 id="rnn-아키텍처-유형">RNN 아키텍처 유형</h2>
<p>RNN은 시퀀스를 어떻게 입력·출력하느냐에 따라 네 가지 대표 구조로 나뉜다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/4fc5574c-3dc0-4576-b557-710cc1bcd681/image.png" alt=""></p>
<hr>
<h1 id="rnn">RNN</h1>
<p>RNN은 Recurrent Neural Network로 순환 신경망을 말한다. 이는 시게열이나 연속적인 데이터를 다룰 때 사용된다. CNN이나 MLP 등 다른 신경망의 경우는 입력을 한번 처리하고 끝난다. 즉 현재 입력만 보고 예측하는 여타 신경망과는 다르게 RNN의 경우 과거의 정보를 기억하여 다음 계산에 반영하는 구조를 갖는다. 이는 자연어와 같이 데이터의 순서가 중요한 경우 적절하게 사용될 수 있다. 다만 Vanilla RNN의 경우는 Long-Term Dependency(장기 의존성) 문제를 갖는다. 이를 극복하기 위해 LSTM, GRU가 나오게 되었다.</p>
<p>RNN은 어떻게 과거의 정보를 반영할까? RNN의 구조를 간단히 알아보며 RNN의 동작 원리와 학습 과정에서의 장기 의존성 문제의 발생 원인을 이해해보도록 하자.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/fa8f6d23-3f3f-4940-9fba-81fff140a065/image.png" alt=""></p>
<br>

<hr>
<h2 id="long-term-dependency">Long-Term Dependency</h2>
<br>

<p>RNN의 동작 원리를 살펴보면, 왜 장기 의존성 문제가 발생하는지 이해할 수 있다.  </p>
<p>은닉 상태의 업데이트 수식은 다음과 같다.  </p>
<p>$$h_t = \tanh(W_h h_{t-1} + W_x x_t + b)$$  </p>
<p>여기서 $h_t$는 이전 은닉 상태 $h_{t-1}$을 거쳐 반복적으로 계산된다. 즉, 은닉 상태는 본질적으로 순환 구조(루프)를 갖는다.  </p>
<br>

<p>이제 출력 손실 $L$에 대한 과거 은닉 상태의 기여도를 따져보자.  </p>
<p>그래디언트 $\frac{\partial L}{\partial h_{t-k}}$는 체인 룰에 따라 시점마다 곱해지며 전달된다. 결국 반복적으로 같은 행렬 곱이 누적된다는 뜻이다.  </p>
<p>곱의 누적을 아래처럼 표현할 수 있다. </p>
<p>$$\frac{\partial L}{\partial h_t}
\cdot \prod_{i=1}^{k} \frac{\partial h_{t-i+1}}{\partial h_{t-i}}=\frac{\partial L}{\partial h_{t-k}}
= \frac{\partial L}{\partial h_t}
\cdot \frac{\partial h_t}{\partial h_{t-1}}
\cdot \frac{\partial h_{t-1}}{\partial h_{t-2}}
\cdots
\frac{\partial h_{t-k+1}}{\partial h_{t-k}}$$  </p>
<br>

<p>이와 같이 곱셈이 누적되는 구조에서는 항의 크기가 1보다 작으면 곱이 점점 0으로 수렴하여 <strong>그래디언트 소실</strong>(Gradient Exploding) 문제가 발생하고, 1보다 크면 기하급수적으로 커져 <strong>그래디언트 폭발</strong>(Gradient Exploding)이 일어난다.</p>
<br>

<hr>
<h2 id="rnn-모델과-이미지-분류">RNN 모델과 이미지 분류</h2>
<p>이미지 분류 문제에서 CNN은 공간적 구조를 직접 반영하기 때문에 가장 우수한 성능을 낸다. 하지만 작은 이미지를 다루는 경우라면 MLP나 RNN도 충분히 적용할 수 있다. 일반적인 MLP는 평탄화된 픽셀만을 독립적으로 처리하기 때문에 공간 정보를 활용하지 못한다. 반면 RNN은 입력을 순차적으로 처리하면서 은닉 상태에 이전 시점의 정보를 저장할 수 있다는 특징이 있다.</p>
<p>따라서 64×64 이미지를 행 단위로 잘라 순차적으로 입력하면, CNN처럼 명시적으로 공간 구조를 반영하지 못하더라도 RNN은 “행의 순서”를 기억함으로써 어느 정도 공간적 맥락을 학습할 수 있다. 이 덕분에 RNN은 단순 MLP보다 이미지 분류 성능에서 더 나은 결과를 낼 수 있다.</p>
<br>

<h3 id="rnn-model">RNN Model</h3>
<p>PyTorch로 간단한 다층 RNN 분류기를 정의해보았다. </p>
<pre><code class="language-python">class RNNModel(nn.Module):
    def __init__(self, input_dim, hidden_dim, layer_dim, output_dim):
        super().__init__()
        self.hidden_dim = hidden_dim      # 각 시점 은닉벡터의 차원 크기
        self.layer_dim  = layer_dim       # RNN 층 수(스택 개수)

        # 내부 파라미터(W_ih, W_hh, b_ih, b_hh)는 self.rnn 안에 자동 등록됨
        self.rnn = nn.RNN(
            input_size=input_dim,     # 입력 벡터 크기
            hidden_size=hidden_dim,   # 은닉 상태 차원
            num_layers=layer_dim,     # RNN을 몇 층 쌓을지
            batch_first=True          # 입력 차원 순서: (배치, 시퀀스 길이, 특성)
        )
        # 마지막 은닉 벡터를 원하는 출력 차원으로 바꿔주는 역할
        self.fc = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):

        # rnn은 시작할 때 초기 은닉 상태(h0)이 필요하기에 0으로 채움
        # h0 : (num_layers, batch, hidden_dim)
        # 매 forward마다 0으로 초기화. 상태를 이어가고 싶으면 이전 hn을 넘겨도 됨.
        batch_size = x.size(0)
        h0 = torch.zeros(self.layer_dim, batch_size, self.hidden_dim, device=x.device) 

        # out: 모든 시점의 은닉 상태 (batch, seq_len, hidden_dim)
        # hn : 각 층의 마지막 시점 은닉 상태 (num_layers, batch, hidden_dim)
        out, hn = self.rnn(x, h0)

        # many-to-one: 마지막 시점의 은닉 상태만 뽑아옴 (many-to-one 구조)
        last_hidden = out[:, -1, :]       # (batch, hidden_dim)

        # 마지막 은닉 상태 → 선형층 → 최종 예측 결과 (예: 클래스 확률 전 단계 값)
        logits = self.fc(last_hidden)     # (batch, output_dim)
        return logits</code></pre>
<br>

<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/ec9a6a80-824f-4938-b102-2bf5bfd73729/image.png" alt=""></p>
<br>

<hr>
<h1 id="정리하며">정리하며</h1>
<p>RNN은 시퀀스를 처리하기 위한 기본적인 순환 구조로, 입력을 따라가며 은닉 상태를 갱신하고 마지막 은닉 상태를 통해 최종 출력을 만들어낸다. 하지만 은닉 상태를 반복적으로 곱해가며 전달하는 과정에서 그래디언트 소실이나 폭발이 일어나, 긴 시퀀스의 정보를 효과적으로 학습하지 못한다는 한계가 있다.  </p>
<br>


<h2 id="다음-글에서는">다음 글에서는...</h2>
<p>이 문제를 해결하기 위해 등장한 구조가 바로 <strong>LSTM(Long Short-Term Memory)</strong>과 <strong>GRU(Gated Recurrent Unit)</strong>다. 다음 글에서는 이 두 모델의 아이디어와 구조를 비교하며, 어떻게 RNN의 단점을 극복했는지 살펴보겠다.</p>
<br> 

<hr>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://youtu.be/Hn3GHHOXKCE?si=bo89KeHwBkcy9MOI">https://youtu.be/Hn3GHHOXKCE?si=bo89KeHwBkcy9MOI</a></li>
<li><a href="https://youtu.be/Gafjk7_w1i8?si=d7yy5al1o2Oc4-1u">https://youtu.be/Gafjk7_w1i8?si=d7yy5al1o2Oc4-1u</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[토큰화와 벡터화]]></title>
            <link>https://velog.io/@son-dan-ha/%ED%86%A0%ED%81%B0%ED%99%94%EC%99%80-%EB%B2%A1%ED%84%B0%ED%99%94</link>
            <guid>https://velog.io/@son-dan-ha/%ED%86%A0%ED%81%B0%ED%99%94%EC%99%80-%EB%B2%A1%ED%84%B0%ED%99%94</guid>
            <pubDate>Fri, 22 Aug 2025 13:52:38 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>자연어는 인간이 일상적으로 사용하는 언어다. 이런 자연어를 이해하고 처리하는 것을 자연어 처리 NLP 라고 한다. 자연어 처리를 통해 텍스트, 음성 분석과 번역, 요약, 감정 분석 등이 가능하다. 자연어 처리의 기본이 되는 개념 두가지, 토큰화와 벡터화를 알아보도록 하자</p>
</blockquote>
<br>

<h1 id="tokenization">Tokenization</h1>
<p>토큰화는 텍스트를 나누는 과정이다. 텍스트 데이터를 처리하기 위해 문장을 의미있는 단어로 나누게 되는데, 그 단위는 다양하다. 언어별로 형태가 다르기 때문에 이에 따른 토큰화 방법을 잘 설정해야 한다. </p>
<h2 id="언어별-토큰화">언어별 토큰화</h2>
<p>영어의 경우는 단어로 띄어쓰기가 되어 있지만 한국어는 조사가 붙어 있다. &quot;I like apple&quot;은 띄어쓰기를 기준으로 텍스트를 나누면 각각이 최소 단위의 의미를 가지고 있다. </p>
<p>같은 의미의 문장 &quot;나는 사과를 좋아한다&quot;는 띄어쓰기만으로는 의미상의 분류가 어렵다. &quot;나는&quot;은 다시  명사 &quot;나&quot; 와 조사 &quot;-는&quot; 으로 나뉠 수 있다. 따라서 한국어와 같은 공백만으로 분류가 명확하지 않은 언어에서는 <strong>형태소 분석기</strong>를 사용하여 토큰화 작업을 한다.</p>
<h2 id="문장-토큰화">문장 토큰화</h2>
<p>문장 토큰화는 텍스트를 <strong>문장 단위</strong>로 나누는 과정으로 보통 문장 부호를 기준으로 구분한다. 그러나 소수점 등 <strong>문장이 아닌 곳</strong>에 문장 부호가 사용된 경우가 있다. 이를 걸러 내야 하기 때문에 문장 토큰화에도 모델과 규칙이 필요하다. 한국어에는 KSS가 있다. </p>
<h2 id="정수-인코딩">정수 인코딩</h2>
<p>컴퓨터는 우리의 언어를 이해할 수 없다. 따라서 컴퓨터가 이해할 수 있는 형태로 언어를 변환할 필요가 있다. </p>
<p>정수 인코딩은 언어를 모델이 이해 가능한 숫자 형태로 변환하는 과정이다. 문장을 토큰화해서 단어, 서브워드, 문자 단위로 나눠 각 토큰에 고유한 정수 ID를 부여한다. 해당 문장은 숫자 시퀀스로 표현될 수 있다. </p>
<br>


<h3 id="keras의-tokenizer">keras의 Tokenizer</h3>
<p>keras의 Tokenizer는 기본적으로 <strong>공백 단위</strong>의 토크화와 일부 특수문자를 제거하는 <strong>단순 전처리</strong>를 지원한다. </p>
<br>

<p>문장을 숫자 시퀀스로 표현해보자.</p>
<pre><code class="language-python"># 문장 토근화
text = &quot;나는 사과를 좋아한다&quot;

tokenizer = Tokenizer() 
# 인덱스 학습을 시킨다.
tokenizer.fit_on_texts([text]) 

# 텍스트를 시퀀스로 반환한다
sequences = tokenizer.texts_to_sequences([text]) 
sequences # [[1, 2, 3]]

# 단어를 key로 인덱스를 value 로 출력
word_index = tokenizer.word_index
word_index # {&#39;나는&#39;: 1, &#39;사과를&#39;: 2, &#39;좋아한다&#39;: 3}</code></pre>
<br>

<p>문서에서 단어 빈도수를 세보자.</p>
<pre><code class="language-python">docs = [
        &#39;원 핫 인코딩은 고차원의 희소 벡터&#39;,
        &#39;워드 임베딩은 저차원의 밀집 벡터&#39;,
        &#39;워드 임베딩을 사용하면 언어적 의미 학습이 가능&#39;,
       ]

tokenizer = Tokenizer() 
tokenizer.fit_on_texts(docs) </code></pre>
<pre><code class="language-python"># 단어 카운트
tokenizer.word_counts
# &quot;벡터&quot;와 &quot;워드&quot;는 2이고 나머지는 1

# 문장 카운트
tokenizer.document_count # 3

# 각 단어가 몇개의 문장에 포함되었는지 카운트
tokenizer.word_docs 
# &quot;벡터&quot;와 &quot;워드&quot;는 2이고 나머지는 1

#각 단어에 매겨진 인덱스 값
tokenizer.word_index
# 고유한 단어에 인덱스 값이 매핑됨

# 인덱스 값으로 구성된 숫자 시퀀스
sequences = tokenizer.texts_to_sequences(docs)
sequences 
# [[3, 4, 5, 6, 7, 1], 
#  [2, 8, 9, 10, 1], 
#  [2, 11, 12, 13, 14, 15, 16]]

# 가장 긴 문장 길이에 맞춰 패딩된 시퀀스
max_len = max([len(i) for i in sequences]) 
padded_sequences = pad_sequences(sequences, max_len)</code></pre>
<br>

<h2 id="padding">Padding</h2>
<p>패딩은 NLP나 시계열 모델에서 길이가 다른 시퀀스를 빈 곳에 0을 채워 길이를 맞춘다. 아래는 패딩된 시퀀스 <code>padded_sequences</code> 다. 길이를 맞추기 위해 빈 곳에는 0이 들어갔다. </p>
<pre><code>array([[ 0,  3,  4,  5,  6,  7,  1],
       [ 0,  0,  2,  8,  9, 10,  1],
       [ 2, 11, 12, 13, 14, 15, 16]], dtype=int32)</code></pre><p>Sequential을 사용하여 아래처럼 한번에 구할 수 있다. Keras의 Tokenizer는 단어 인덱스를 1부터 시작하기 때문에, 인덱스 0은 패딩 값으로 예약된다. 그래서 <code>input_dim</code>에 1을 더했다. </p>
<ul>
<li>input_dim: 단어 사전 크기 + 1</li>
<li>output_dim: 각 단어를 벡터로 변환할 차원 크기</li>
</ul>
<pre><code class="language-python"># 모델을 순차적으로 층을 쌓는 구조로 정의
model = Sequential()

word_index = tokenizer.word_index

# 임베딩 층 추가
model.add(Embedding(input_dim=len(word_index) + 1, output_dim=max_len+1))

# 출력 벡터 반환 (패딩된 입력 시퀀스 예측)
model.predict(padded_sequences)</code></pre>
<br>

<p>결과 벡터는 아래와 같다.</p>
<pre><code>array([[[-0.00857245,  0.02472864,  0.00420759, -0.03509233,
         -0.00070393, -0.02817063, -0.00813448,  0.02640537],
        [ 0.04682406, -0.03670243,  0.01014663,  ...]], 
        ...
         [[ 0.02936871, ... 0.03133484,  0.01352866]]],
      dtype=float32)</code></pre><br>

<hr>
<h1 id="용어">용어</h1>
<h2 id="vocabulary">Vocabulary</h2>
<p>단어 사전(Vocabulary)은 고유한 토큰을 모아 인덱스를 매핑한 집합을 말한다. 이는 텍스트를 정수 시퀀스로 변환하는 기준이 된다. 위에서 <code>model.predict(padded_sequences)</code> 했던 구조와 같다. </p>
<ul>
<li>NLP 모델들은 각각의 Vocabulary를 끼고 있다.</li>
<li>NLP 모델이 단순하다는 것은 Vocabulary 또한 단순하게 만들어졌다는 것</li>
<li>LLM 같은 복잡하고 거대한 모델은 Vocabulary도 매우 복잡하게 벡터화</li>
</ul>
<h3 id="oov">OOV</h3>
<p>모델이 학습할 때 단어 사전에 없는 단어가 들어온다면 해당 단어는 정수 인코딩이나 임베딩으로 변환할 수 없다. 이 과정에서 발생하는 문제를 OOV(Out-Of-Vocabulary)라고 한다. </p>
<p>이를 해결하기 위해 OOV 전용 토큰으로 처리하거나 단어를 더 작게 쪼개는 방법 등을 사용한다.</p>
<br>

<hr>
<h1 id="벡터화">벡터화</h1>
<p>언어는 단어 간의 <strong>의미적 관계</strong>가 존재한다. 모델에도 이런 관계가 반영되게 해야 한다. 벡터화는 텍스트 데이터의 <strong>특징을 수치적으로 표현</strong>하여 벡터 공간에서 단어 간의 관계를 나타낸다. </p>
<p><strong>벡터화 기법</strong>에는 BOW, TF-IDF, Word Embedding, Transformer 기반 임베딩 등이 있으며, 여기에서는 가장 기초적인 BOW와 TF-IDF 기법을 알아본다.</p>
<h2 id="one-hot-encoding">One-Hot Encoding</h2>
<ul>
<li>고차원의 희소 벡터로 표현하는 기법</li>
</ul>
<p>원-핫 인코딩은 vocabulary에 있는 단어들을 고유한 숫자 벡터로 표현한다. 이는 단어간 의미적 관계를 반영하는 기법이 아니다. 
원-핫 인코딩은 대부분의 값이 0인 벡터인 <strong>Sparse Vector(희소 벡터)</strong> 가 자주 나타나 메모리 낭비를 초래한다. Word Embedding 기법은 이러한 단점을 해결한다.</p>
<br>


<h2 id="word-embedding">Word Embedding</h2>
<ul>
<li>저차원의 밀집 벡터로 표현하는 기법</li>
<li>BOW와 TF-IDF가 있다.</li>
</ul>
<h3 id="bag-of-words">Bag of Words</h3>
<p>BOW은 컴퓨터는 숫자만 알아듣기 때문에 단어의 입력 순서 즉, 문맥은 중요하지 않다는 가정으로 시작한다. 가방안에 문장의 모든 단어를 넣어 섞고 꺼내면 해당 단어의 빈도수를 알 수 있다. </p>
<p>문장의 구조나 의미를 파악하기 위해서는 단어의 빈도수만으로는 정보가 부족하다. 이러한 단점을 보완한 확장 기법으로 TF-IDF가 있다. </p>
<h3 id="tf-idf">TF-IDF</h3>
<p>DTM(Document-Term Matrix)은 여러 문서를 행으로 두고, Vocabulary에 포함된 단어를 열로 두어 빈도를 수치로 표현한 문서-단어 행렬이다. 각 칸에는 단어 빈도나 TF-IDF 값 등이 들어가고 문서를 수치화하여 분류, 군집, 주제 모델링에 활용할 수 있다.</p>
<br>

<ul>
<li>TF : 특정 문서에서 해당 단어가 얼마나 자주 등장하는지</li>
<li>IDF : 해당 단어가 다른 문서들에 얼마나 흔하게 등장하는지</li>
</ul>
<br>

<p>$TF(t, d)=\frac{문서 d에서 단어 t가 등장한 횟수}{문서 d에 등장한 모든 단어의 수}$</p>
<p>$IDF(t, D)=log(\frac{총 문서의 개수}{단어 t를 포함하는 문서의 수})$</p>
<p>$TF-IDF(t, d, D) = TF(t,d)\times IDF(t, D)$</p>
<br>

<p>특정 문서에서 자주 등장하면서 다른 문서에서는 잘 나타나지 않는 단어일수록 TF-IDF 값이 높아진다.</p>
<br>

<h3 id="sklearn의-countvectorizer-tfidfvectorizer">sklearn의 CountVectorizer, TfidfVectorizer</h3>
<p>sklearn의 CountVectorizer와 TfidfVectorizer를 사용하여 DTM과 TF-IDF를 구현해보자.</p>
<pre><code class="language-python"># 말뭉치 데이터
corpus = [
    &quot;Hey, I&#39;m Dana!&quot;,
    &quot;I love cats.&quot;,
    &quot;Cats are super cute!&quot;,
]

# CountVectorizer 객체 생성
vector = CountVectorizer()

# 코퍼스로부터 각 단어의 등장 빈도수를 기록 (Bag-of-Words 방식)
vector.fit_transform(corpus).toarray()
&#39;&#39;&#39;
array([[0, 0, 0, 1, 1, 0, 0],
       [0, 1, 0, 0, 0, 1, 0],
       [1, 1, 1, 0, 0, 0, 1]])
&#39;&#39;&#39;

# TF-IDF 벡터화 객체 생성
tfidfv = TfidfVectorizer().fit(corpus)

# 코퍼스를 TF-IDF 방식으로 벡터화
tfidfv.transform(corpus).toarray()
&#39;&#39;&#39;
array([[0. , 0. , 0. , 0.70710678, 0.70710678,
        0. , 0. ],
       [0., 0.60534851, 0. , 0. , 0. ,
        0.79596054, 0.],
       [0.52863461, 0.40204024, 0.52863461, 0. , 0., 0. , 0.52863461]])
&#39;&#39;&#39;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[파이썬의 combinations]]></title>
            <link>https://velog.io/@son-dan-ha/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%9D%98-combinations</link>
            <guid>https://velog.io/@son-dan-ha/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%9D%98-combinations</guid>
            <pubDate>Mon, 11 Aug 2025 06:53:40 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>해시 알고리즘에 속하는 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/42578">의상</a> 문제를 해결하는 과정이다. 이 문제를 통해 파이썬의 3가지 모듈을 새롭게 알게 되었다. 또한 조합 원리로 문제를 해결하는 아이디어를 얻을 수 있었다. 
이 포스트는 조합 아이디어에 대한 간단한 정리와 파이썬의 모듈에서 combinations(), reduce(), mul의 활용 방법과 내부 동작 원리를 알아본다.</p>
</blockquote>
<br>


<h1 id="문제-풀이">문제 풀이</h1>
<p>해당 문제는 조합을 구하는 문제라고 생각했다. 따라서 주어진 매개변수를 Counter를 활용해 가공 후 <strong>조합을 구현</strong>하려고 했다. 그러나 조합 구현에는 제어 흐름과 인덱스를 증가하고 정렬하는 것이 중요하다. 완벽하게 구현하는 데에는 어려움이 있으므로 이미 만들어진 모듈을 활용하는 것은 에러 없는 코드를 작성하기 위한 좋은 방법이라 생각한다.</p>
<br>

<h2 id="내가-작성한-풀이">내가 작성한 풀이</h2>
<p>문제 <strong>조건에 맞는 모든 경우</strong>를 찾아내는 것이 목적이었다. 그러나 많은 케이스에서 정답을 내지 못했다. </p>
<pre><code class="language-python">from collections import Counter
from functools import reduce

def solution(clothes):
    answer = 0
    values = list(Counter([i[1] for i in clothes]).values())
    N = len(values)

    # 조합을 직접 구현하려 함 -&gt; 다양한 문제점
    for i in range(1,N+1):

        # 문제에만 맞춘 분기로 인해 확장성과 가독성 떨어짐
        if i == 1: 
            answer+= sum(values)

        elif i == 2: # 2C2, 3C2, 4C2
            for idx, v in enumerate(values):
                n = idx +1
                while n &lt;= N-1:
                    answer += v*values[n]
                    n += 1

        elif i == 3: 
            if N == 3: # 3C3
                # 람다 사용으로 가독성이 떨어짐
                answer += reduce(lambda x,y:x*y, values)

            elif N == 4: # 4C3
                for i in range(N):
                    l = values # 얉은 복사 -&gt; 원본 훼손
                    l.pop(i)
                    answer += reduce(lambda x,y:x*y, l)

        elif i == 4: # 4C4
            answer += reduce(lambda x,y:x*y, values)

    return answer</code></pre>
<br>

<h2 id="모듈을-활용한-풀이">모듈을 활용한 풀이</h2>
<p>조합을 구현하려 했던 코드는 많은 <strong>논리적 오류</strong>와 <strong>문법적 오류</strong>를 가지고 있다. 따라서 <strong>조합 모듈</strong>을 사용한 위와 같은 구조의 개선된 코드를 찾아 보았다.</p>
<pre><code class="language-python">from collections import Counter
from itertools import combinations
from functools import reduce 
from operator import mul # lambda 대신 사용 

def solution(clothes):
    answer = 0
    values = list(Counter([i[1] for i in clothes]).values())
    N = len(values)

    # 모듈을 통해 조합 함수를 사용
    for r in range(1, N + 1):
        # combinations(이터러블한 객체, r개 조합)
        # comb는 r개 종류를 선택하는 조합의 경우
        for comb in combinations(values, r):
            answer += reduce(mul, comb)

    return answer</code></pre>
<p>itertools 모듈의 combinations 함수를 사용했더니 복잡했던 코드가 간결하게 정리되었다. 다만 해당 코드는 시간복잡도에 걸렸다. 내가 위에서 작성한 코드의 구성과 똑같이 조합을 <strong>1개부터 N개까지 모두 구해서 곱을 누적하는 방식</strong>이다. 조합의 경우는 N이 늘어날 수록 그 결과 값이 급격하게 증가한다. 이는 코드가 동작할 때 연산량의 증가로 이어진다. </p>
<h3 id="조합의-시간복잡도">조합의 시간복잡도</h3>
<p>$\sum_{r=1}^{N}(_nC_r)\times{r}=O(2^N\cdot{N})$</p>
<br>

<h2 id="조합-원리를-활용한-풀이">조합 원리를 활용한 풀이</h2>
<p>문제를 해결하는 아이디어가 중요했다. 조합을 구하는 공식을 사용할 경우 위처럼 증가하는 연산량으로 인해 <strong>시간복잡도에서 문제</strong>가 생겼다. </p>
<p>문제를 다시 살펴보면 <strong>거의 모든 경우</strong>를 구하지만 아무것도 선택하지 않는 경우(의상을 한개도 선택하지 않는 경우)는 <strong>제외</strong>한다. </p>
<p>많은 경우가 예상될 때 제외하는 조건이 구하기 쉬운 경우(전체 경우보다 훨씬 적은 경우)에는 <strong>여사건</strong>을 이용할 수 있다.</p>
<h3 id="여사건">여사건</h3>
<p>여사건은 어떤 사건이 일어나지 않을 경우를 말한다. 간단하게 개념을 설명하면 표본공간이 S 일때, 여사건 $\overline{A}$는 다음과 같다. </p>
<p>$$\overline{A}=S−A$$</p>
<p>이를 문제에 적용 시키면, 전체 경우의 수는 0개를 선택하는 경우부터 전체를 하나씩 선택하는 경우다. </p>
<p>따라서 종류가 n개 있을 때, 각 종류마다의 개수를 $X_i$라고 한다면, </p>
<ul>
<li>전체 경우의 수 = $(x_1+1)\times(x_2+1)···(x_i+1)···(x_n-1+1)\times(x_n+1)$</li>
<li>해당 종류를 선택하지 않는 경우 (+1) + 선택하는 경우($X$)</li>
</ul>
<p>여기서 여사건은 모든 종류를 선택하지 않는 경우 1가지로 최종 경우의 수는 </p>
<p>$\sum_{i=1}^{n}(x_i+1)-1$</p>
<br>

<p>코드로는<code>reduce(mul,[i+1 for i in values])</code> 처럼 작성 가능하다. 곱의 법칙을 이용하므로 mul 함수를 사용하였는데, lambda를 사용하여 <code>reduce(lambda x,y: x*y,[i+1 for i in values])</code> 처럼 작성할 수도 있다.</p>
<h3 id="최종-코드">최종 코드</h3>
<pre><code class="language-python">from collections import Counter
from functools import reduce
from operator import mul  

def solution(clothes):
    # 의상 종류별 개수 세기
    values = list(Counter([i[1] for i in clothes]).values())

    # 여사건 계산: 전체 경우의 수 - 아무것도 안입는 경우    
    return reduce(mul,[i+1 for i in values]) - 1</code></pre>
<br>
<br>

<hr>
<h1 id="combinations"><code>combinations()</code></h1>
<p>조합을 직접 활용하려고 했을 때, 시간 초과가 났다. 고등교육 과정에서의 조합까지만 알고 있기에 파이썬에서 구현된 조합은 어떤 구조일지 알아보자. </p>
<br>

<p>combinations은 itertools 안에 들어있다. </p>
<p><code>from itertools import combinations</code> </p>
<p>따라서 파이썬에서 조합을 사용하기 위해서는 다음과 같이 모듈을 가져온다.</p>
<h2 id="itertools">itertools</h2>
<p>조합은 <code>itertools</code> 모듈에 포함되어 있다. itertools 모듈은 이름 그대로 iterable한 객체에서 사용할 수 있는 도구(함수)를 제공한다. 특히 반복되는 계산에서 유용하게 사용 가능하다. itertools의 모든 함수는 lazy evaluation(지연 평가)를 사용한다. </p>
<br> 

<p>combinations 외의 itertools의 함수 몇가지</p>
<ul>
<li><code>itertools.count(start=0, step=1)</code> : 증가하는 값을 무한히 생성</li>
<li><code>itertools.cycle(iterable)</code> : 순서대로 무한히 반복 ( [1,2,3] -&gt; 1,2,3,1,2,3,1 ... )</li>
<li><code>itertools.repeat(object[, times])</code></li>
<li><code>itertools.chain(*iterables)</code> : 이터러블하면, 자료형에 관계없이 모두 연결</li>
</ul>
<br> 

<h3 id="lazy-evaluation">lazy evaluation</h3>
<p>지연 평가란 <strong>필요할 때마다</strong> 값을 계산하는 이터레이터를 반환한다는 의미다. 파이썬에서 이터레이터나 제너레이터와 같은 객체들은 지연 평가 방식을 따른다. 이 방식은 메모리 사용과 계산 비용을 줄인다. <code>next()</code> 함수가 호출될 때마다 하나씩 계산하여 반환하는 구조를 갖는다. </p>
<br> 

<h2 id="동작-원리">동작 원리</h2>
<blockquote>
<p>참고: 앞으로의 파이썬 내부 동작 원리는 CPython 기준으로 작성됨.</p>
</blockquote>
<ul>
<li>컴파일: <code>.py</code> -&gt; <code>.pyc</code></li>
<li>실행 방식: 바이트코드 인터프리터(C로 작성)가 한 줄씩 실행</li>
</ul>
<br>

<p><code>itertools</code>는 <strong>C</strong>로 구현되어 있다. 아래 예시는 공식 문서에서 제공하는 파이썬으로 작성한 개념적 <strong>유사 코드</strong>로, 실제 구현은 아니다.</p>
<pre><code class="language-python">def combinations(iterable, r):
    pool = tuple(iterable) # 이터레이터를 입력받아 튜플로 저장
    n = len(pool) 

    if r &gt; n: # 조합을 구할 수 없는 경우
        return

    indices = list(range(r)) # 인덱스 리스트 생성

    # 첫번째 조합 반환
    yield tuple(pool[i] for i in indices)

    while True: # 조합 모두 찾기

        for i in reversed(range(r)): 
            # 다음 조합을 생성할 수 있다면 계속 (while 종료 x)
            if indices[i] != i + n - r: 
                break 

        else: # break 없이 정상적으로 끝났을 경우 (for-else)
            return # 조합 찾기 끝

        indices[i] += 1

        for j in range(i+1, r):
            indices[j] = indices[j-1] + 1

        # 지연 평가 방식으로 조합 튜플 반환    
        yield tuple(pool[i] for i in indices)</code></pre>
<h3 id="yield와-return">yield와 return</h3>
<ul>
<li><code>return</code>은 함수를 <strong>종료</strong>하고 <strong>값을 반환</strong>한다. </li>
<li><code>yield</code>는 함수가 <strong>종료되지 않고</strong> 상태를 유지하며, 여러 값을 순차적으로 반환하며 최종 값은 <strong>제너레이터 객체</strong>가 된다. <code>next()</code> 호출로 <strong>값을 하나씩 전달</strong>하게 된다.</li>
</ul>
<br>

<hr>
<h1 id="reduce"><code>reduce()</code></h1>
<p><code>from functools import reduce</code></p>
<p>reduce은 functools 안에 들어있다. functools 모듈은 <strong>고차 함수</strong> 및 <strong>함수형 도구</strong>들을 제공한다. </p>
<p><code>functools.reduce(function, iterable[, initializer])</code></p>
<p>reduce는 function에 대해서 iterable에 누적 적용할 수 있게 한다. 문제에서는 리스트 내의 요소를 차례로 곱하여 누적하는 연산을 진행했다. </p>
<blockquote>
<p><code>reduce(mul, [5, 3, 6, 8])</code>
리스트에서 5와 3을 꺼내 mul 함수에 적용. → $5\times3$
리스트에서 다음 값 6을 꺼내 앞 연산에서 mul 함수를 적용함 (곱을 누적) → $5\times3\times6$
이를 계속 반복 → $5\times3\times6\times8$
return 되는 값은 <code>5*3*6*8</code></p>
</blockquote>
<br>

<hr>
<h1 id="mul"><code>mul</code></h1>
<p><code>from operator import mul</code></p>
<p>mul은 operator 안에 들어있다. operator 모듈은 파이썬의 <strong>내장 연산자를 함수 형태</strong>로 제공한다. 보통 함수의 이름은 특수 메서드에서 앞뒤 밑줄을 뺀 형태를 갖는다. </p>
<ul>
<li>산술/수학 연산자 : <code>add</code>, <code>sub</code>, <code>mul</code>, ...</li>
<li>비트 연산자 : <code>and_</code>, <code>or_</code>, <code>xor</code>, ...</li>
<li>논리/비교 : <code>lt</code>, <code>le</code>, <code>eq</code>, ...</li>
<li>...</li>
</ul>
<p>해당 모듈의 특징은 내장 연산자를 함수 형태로 제공하므로 <code>operator.mul</code>은 <strong>내장 곱셈 연산</strong>을 그대로 <strong>호출</strong>하는 wrapper로 이해하면 된다.</p>
<h2 id="동작-원리-1">동작 원리</h2>
<h3 id="메서드-디스패치">메서드 디스패치</h3>
<p>메서드가 호출될 때 실제로 실행될 메서드를 결정하는 과정을 메서드 디스패치라고 한다. 메서드 디스패치에는 컴파일 과정에서 결정되는 <strong>정적 디스패치</strong>와 런타임 과정에서 결정되는 <strong>동적 디스패치</strong>가 있다. </p>
<p>정적 타입의 언어가 아닌 파이썬은 <strong>런타임</strong>에 피연산자의 <strong>타입을 확인</strong>하고 그 타입이 제공하는 <strong>연산을 찾아 호출</strong>하는 방식을 갖는다. (코드 작성 시점에 타입이 확정되는 것이 아님)</p>
<p>mul은 좌, 우, 제자리 순서로 판단한다. <code>a*b</code>를 받는다면 <code>a.__mul__(b)</code> 호출하는데, 이때 <code>NotImplemented</code>(예외 X) 라면 <code>b.__rmul__(a)</code>를 호출하고 둘다 불가능하면 <code>TypeError</code>가 난다. </p>
<pre><code class="language-python">class Box:
    def __init__(self, v): 
        # 인스턴스 속성 정의. (단일 숫자만 담음)
        self.v = v

    def __repr__(self):
        return f&quot;{self.v}&quot;

    # a * b  → a.__mul__(b) 
    # 먼저 호출되는 왼쪽 연산자
    def __mul__(self, other): 
        if isinstance(other, (int, float)):
            return Box(self.v * other)

        # NotImplemented는 반사 호출 유도에 쓰이는 신호값
        # 인터프리터가 반사 연산(__r*__) 자동 폴백
        # 여기서는 __rmul__
        return NotImplemented 

    # 반사 곱: 
    # a * b 에서 a.__mul__(b) 가 NotImplemented
    # → b.__rmul__(a)    
    def __rmul__(self, other): # 우
        if isinstance(other, (int, float)):
            return Box(other * self.v)
        return NotImplemented

    # a *= b  → 우선 a.__imul__(b) 를 시도
    # self 내부 상태를 바꾸고 self 반환
    def __imul__(self, other):            
        if isinstance(other, (int, float)):
            self.v *= other # 제자리 갱신(in-place)
            return self # 제자리 연산은 보통 self를 돌려줌                  

        # NotImplemented 반환 
        # → 일반 곱으로 폴백되어 a = a * b 수행
        return NotImplemented</code></pre>
<pre><code class="language-python">b = Box(10)
print(b * 3) # 30
print(3 * b) # 30

b *= 2
print(b) # 20</code></pre>
<p>구조를 보면 알겠지만 사실상 mul 등의 여러 연산 함수는 기본 <strong>내장 함수</strong> <code>*</code> 등을 사용하는 것과 <strong>동일</strong>하다. 단지 함수 형태로 호출한다는 특징을 갖는다. 이런 형태의 장점은 성능상의 이득이 아닌 <strong>함수형 유틸과의 결합성</strong>에 있다. 문제에서 활용할 때에도 함수형 도구인 <code>reduce()</code> 와 결합되어 사용되었다. <strong>함수형 프로그래밍</strong>에 유용하게 사용될 수 있겠다.</p>
<br>

<hr>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://docs.python.org/3/library/itertools.html#itertools.combinations">itertools - combinations</a></li>
<li><a href="https://docs.python.org/3/library/functools.html#functools.reduce">functools - reduce</a></li>
<li><a href="https://docs.python.org/3/library/functools.html#functools.reduce">operator - mul</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Deep Residual Learning for Image Recognition 논문리뷰]]></title>
            <link>https://velog.io/@son-dan-ha/Deep-Residual-Learning-for-Image-Recognition-%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0</link>
            <guid>https://velog.io/@son-dan-ha/Deep-Residual-Learning-for-Image-Recognition-%EB%85%BC%EB%AC%B8-%EB%A6%AC%EB%B7%B0</guid>
            <pubDate>Fri, 08 Aug 2025 13:01:20 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/26f1bc59-9f72-4e0c-b420-423c1406a9b8/image.png" alt=""></p>
<h1 id="1-introduction">1. Introduction</h1>
<p>ResNet 논문은 기존의 딥러닝 모델이 네트워크 깊이가 깊어질수록 오히려 정확도가 떨어지는 현상, 즉 <strong>degradation problem</strong>을 관찰하며 시작된다. 이는 단순히 overfitting의 문제가 아닌, <strong>optimization의 어려움</strong>에서 비롯된다고 저자는 주장한다. 깊은 네트워크는 이론적으로 더 높은 표현 능력을 가질 수 있지만, 실제 학습에서는 gradient vanishing, 학습 불안정 등의 이유로 성능 저하가 발생한다.</p>
<p>이 논문을 읽는 동안 나는 먼저 &quot;gradient 소실과 폭발&quot;의 메커니즘을 다시 짚어보았고, **역전파(backpropagation)**와 <strong>SGD의 수렴 특성</strong>이 깊은 네트워크에서 어떤 방식으로 제한되는지 학습했다. 또한, **정규화된 초기화 기법(He initialization)**과 <strong>Batch Normalization</strong>이 이러한 문제를 어느 정도 완화시킬 수는 있지만, <strong>근본적인 해결책은 아니었다는 점</strong>도 확인했다.</p>
<br>

<hr>
<h1 id="2-related-work">2. Related Work</h1>
<p>기존의 깊은 신경망들은 네트워크 깊이를 늘릴수록 **학습 오류(training error)**가 증가하는 문제가 있었다. 이는 더 깊은 네트워크가 단순히 더 많은 파라미터를 가진다는 것과는 별개로, <strong>최적화의 어려움</strong>을 반영한다.</p>
<p>대표적인 선행 연구로는 <strong>Highway Networks</strong>와 <strong>FitNet</strong>이 있으며, 이들은 중간 층 supervision 또는 gate를 활용해 정보 흐름을 조절하려 했다. 하지만 ResNet은 이보다 더 단순하면서도 효과적인 방법인 <strong>identity shortcut connection</strong>을 제안한다.</p>
<br>

<hr>
<h1 id="3-deep-residual-learning">3. Deep Residual Learning</h1>
<h2 id="residual-learning의-기본-아이디어">Residual Learning의 기본 아이디어</h2>
<p>기존의 딥러닝 구조는 각 블록이 **입력 $x$**로부터 직접적으로 원하는 출력 $H(x)$를 학습하도록 한다. 하지만 ResNet은 이를 다음과 같이 재정의한다:</p>
<p>$$
H(x) = F(x) + x
$$</p>
<p>여기서:</p>
<ul>
<li>$H(x)$: 우리가 실제로 학습하고자 하는 mapping</li>
<li>$F(x) = H(x) - x$: 학습할 <strong>잔차 함수(residual function)</strong></li>
<li>$x$: identity connection을 통해 shortcut으로 전달되는 입력</li>
</ul>
<p>이 구조는 학습이 어려운 전체 함수를 학습하는 대신, **입력과 출력의 차이(잔차)**를 학습하는 방식이다. 실제로 많은 경우 $H(x)$는 입력 $x$와 유사하므로, $F(x)$가 <strong>0에 가까운 작은 값</strong>이면 충분한 경우가 많다.</p>
<p>이 구조 덕분에 역전파 시 gradient가 shortcut을 따라 <strong>더 깊은 층까지 효과적으로 전달될 수 있어</strong>, <strong>vanishing gradient 문제</strong>가 완화된다.</p>
<br>

<h2 id="수식-정리">수식 정리</h2>
<p>Residual Block 내부 연산은 다음과 같다:</p>
<p>$$
y = F(x, {W_i}) + x
$$</p>
<ul>
<li>$F(x, {W_i})$: 두 개 이상의 weight layer를 포함한 비선형 transformation</li>
<li>$x$: identity shortcut connection</li>
<li>$y$: 블록의 출력</li>
</ul>
<p>만약 차원이 다르면 $x$를 projection (예: 1x1 conv)으로 바꿔주어 합 연산이 가능하게 만든다.</p>
<br>

<hr>
<h1 id="4-identity-mapping-by-shortcuts">4. Identity Mapping by Shortcuts</h1>
<p>이 섹션에서는 identity shortcut이 학습을 얼마나 <strong>단순화</strong>시키는지를 설명한다.</p>
<p>이 구조는 추가적인 파라미터 없이도 기존의 네트워크보다 훨씬 더 깊은 구조(최대 152 layers)를 학습할 수 있게 해주며, 이는 <strong>plain network 대비 명확한 성능 향상</strong>으로 이어졌다.</p>
<p>또한, 저자들은 학습을 단순히 “깊게 만드는 것”이 아니라, 학습이 실제로 <strong>이뤄지는지</strong>를 강조하며, residual 구조가 <strong>효율적인 정보 흐름</strong>을 제공한다는 점을 수치 실험과 함께 제시한다.</p>
<br>

<hr>
<h1 id="5-experiments">5. Experiments</h1>
<p>ResNet은 ImageNet 분류 과제에서 가장 높은 성능을 기록했다. 특히, <strong>ResNet-152</strong>는 <strong>plain network</strong>보다도 더 낮은 error rate을 기록했으며, top-5 error는 3.57%로, <strong>ILSVRC 2015 classification task 1위</strong> 성능이었다.</p>
<p>또한, ResNet은 CIFAR-10에서도 실험되었고, 적은 파라미터 수에도 불구하고 더 깊은 구조가 더 나은 일반화 성능을 보였다. 이는 Residual Learning이 단순히 깊이에 대한 방어 수단을 넘어서, <strong>일반화 성능까지 확보하는 학습 구조</strong>임을 보여준다.</p>
<br>

<hr>
<h2 id="내-실험-추가-resnet18-vs-simplecnn-on-cifar-10">내 실험 추가: ResNet18 vs SimpleCNN on CIFAR-10</h2>
<p>코랩에서 직접 CIFAR-10 데이터셋을 사용하여 <strong>ResNet18</strong>과 내가 만든 <strong>SimpleCNN</strong>을 비교 실험했다. </p>
<p><a href="https://colab.research.google.com/drive/1RKJEh-K5PtJSHHfajd_2v9Fe59qPGNMz#scrollTo=Y1Mm9mXRGokY">코랩 실습</a></p>
<br>

<p>다음은 각 모델의 학습 및 테스트 정확도 변화이다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/53f0c9c5-05cc-47cf-9dd7-dba620b16cef/image.png" alt=""><img src="https://velog.velcdn.com/images/son-dan-ha/post/912c33b9-112b-40f0-9faa-0be6f9ebaaab/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/265a38dd-f987-4e59-b349-1356ba96e2ac/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/52b8425c-b915-4b2e-917d-6304ff139e29/image.png" alt=""></p>
<p>→ 실험 결과, <strong>ResNet18이 단순 CNN 대비 훨씬 더 빠르게 수렴하고, 일반화 성능(테스트 정확도)도 높게 유지</strong>함을 확인했다. 이는 residual 구조의 학습 안정성과 효율성을 직접 체감한 경험이었다.</p>
<br>

<hr>
<h2 id="6-마무리-및-개인적인-관점">6. 마무리 및 개인적인 관점</h2>
<p>ResNet 논문은 단순한 구조 제안 이상의 가치가 있었다. 이 논문을 읽으면서, 나는 등장하는 개념 하나하나를 따로 정리하면서 전체 구조를 이해하는 방식으로 접근했다. 단축 연결, 잔차 학습, 수렴 안정화, gradient 흐름 등은 모두 <strong>딥러닝이 왜 잘 작동하는지를 설명해주는 단서</strong>들이었다.</p>
<br>

<p>이번 리뷰를 작성하면서 다음과 같은 개념들은 아직 명확하게 이해되지 않아 추후 학습할 주제로 메모를 남긴다:</p>
<ol>
<li><strong>Pre-activation Residual Block</strong>의 구체적 수식 및 동작 원리</li>
<li><strong>Gradient flow가 수렴에 미치는 영향</strong>의 수치적 분석</li>
<li><strong>ResNet이 왜 optimization landscape을 smoother하게 만드는지</strong>에 대한 이론적 근거</li>
<li><strong>BatchNorm과 shortcut connection이 상호작용하는 방식</strong></li>
</ol>
<br>


<h3 id="마치며">마치며</h3>
<p>앞으로도 논문을 단순히 읽는 것을 넘어서, <strong>배경 지식 → 개념 학습 → 수식 분석 → 전체 흐름 이해</strong>라는 내 방식대로 꾸준히 확장해가고자 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ch_01] 신경망의 동작 방식]]></title>
            <link>https://velog.io/@son-dan-ha/Ch01-%EC%8B%A0%EA%B2%BD%EB%A7%9D%EC%9D%98-%EB%8F%99%EC%9E%91-%EB%B0%A9%EC%8B%9D</link>
            <guid>https://velog.io/@son-dan-ha/Ch01-%EC%8B%A0%EA%B2%BD%EB%A7%9D%EC%9D%98-%EB%8F%99%EC%9E%91-%EB%B0%A9%EC%8B%9D</guid>
            <pubDate>Sun, 03 Aug 2025 04:51:17 GMT</pubDate>
            <description><![CDATA[<h1 id="neural-networtknn">Neural Networtk(NN)</h1>
<p> 인공 신경망은 생물학적 신경망을 모방한다. 생물학에서는 뇌의 신경세포를 뉴런이라 하는데, 이 뉴런의 작용을 수학적으로 추상화하여 네트워크로 표현한 것이 <strong>신경망</strong>이다.</p>
<br>


<h1 id="1-생물학적-뉴런">1. 생물학적 뉴런</h1>
<p>신경망이라는 단어에서 알 수 있듯 뉴런은 서로 <strong>네트워크(망)</strong>을 이룬다. 뉴런은 서로 <strong>신호</strong>를 받거나 보내며 <strong>정보</strong>를 처리한다. </p>
<p>뉴런은 크게 축삭, 신경세포체, 수상돌기, 시냅스로 구성된다. 뉴런에 신호가 입력되면 신경세포체가 신호를 합하여 해당 합이 임곗값 보다 클 때에는 <strong>다른 뉴런에 신호를 보내고</strong> 작다면 보내지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/f33aa80c-abd6-4f72-9abc-b2b233b2a524/image.png" alt=""></p>
<br>


<hr>
<h1 id="2-뉴런-활동의-수학적-표현">2. 뉴런 활동의 수학적 표현</h1>
<p><strong>뉴런의 활동</strong>, 즉 <strong>반응 구조</strong>를 수학으로 표현할 수 있다. </p>
<br>

<h2 id="입력-신호">입력 신호</h2>
<p>$\sum_{i=1}^{n} (x_i\cdot w_i)$</p>
<ul>
<li>각각의 뉴런 : $x_i$, 가중치 : $w_i$</li>
</ul>
<br>

<h2 id="임계값-theta">임계값 $\theta$</h2>
<p>임계값 $\theta$에 따라 <strong>출력 신호</strong>가 있는 경우와 없는 경우로 구분된다.</p>
<p>$\begin{cases}:\sum_{i=1}^{n} (x_i\cdot w_i) &lt; \theta  \quad(y=0)\:\sum_{i=1}^{n} (x_i\cdot w_i) \geqq  \theta\quad(y=1)\end{cases}$</p>
<br>

<h2 id="반응-조건-그래프">반응 조건 그래프</h2>
<p>출력값을 0과 1로 본다면 <strong>반응 조건 그래프</strong>는 다음과 같은 모습을 갖는다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/e57b24ab-06b8-4153-aa4d-a0f2fb54bbd1/image.png" alt=""></p>
<br>


<h3 id="단위-계단-함수-unit-step-function">단위 계단 함수 (unit step function)</h3>
<p>해당 그래프를 <strong>함수</strong>로 일반화할 때, 이를 <strong>단위 계단 함수</strong> $u(z)$라고 한다. </p>
<p>$u(z)=\begin{cases}:0  :(z&lt;0)\ :1  :(z\geqq0)\end{cases}$</p>
<br>

<h3 id="반응-조건에-관한-식">반응 조건에 관한 식</h3>
<p>$z=\sum_{i=1}^{n} (x_i\cdot w_i)-\theta$ </p>
<p>$y=u(z)$</p>
<p>$y=u(\sum_{i=1}^{n} (x_i\cdot w_i)-\theta)$</p>
<p><br><br></p>
<hr>
<h1 id="3-활성화-함수activation-function">3. 활성화 함수(Activation Function)</h1>
<p>해당 책에서는 뉴런을 생물학적 뉴런과 구별하기 위해 인공적 뉴런을 유닛(unit)이라 칭하므로 앞으로 유닛과 뉴런을 구분하여 사용한다.</p>
<p>앞서 뉴런의 출력 신호는 0과 1밖에 없었다. 유닛은 0, 1로 표현하지 않아도 된다. </p>
<p>함수 $a$로 출력 신호를 수학적으로 일반화할 수 있다. 활성화 함수(전달 함수)를 사용자 정의 함수 $y=a(z)$로 설정할 수 있겠다.</p>
<br>

<h2 id="뉴런과-유닛의-차이점">뉴런과 유닛의 차이점</h2>
<h3 id="1-활성화-함수">1. 활성화 함수</h3>
<ul>
<li>뉴런 : 단위 계단 함수 $u(z)$</li>
<li>유닛 : 시그모이드 함수 $\sigma(z)$ 등..</li>
</ul>
<blockquote>
<p>활성화 함수에는 많은 종류가 있다. 함수의 종류마다의 장단점이 있기에 현재는 ReLU 함수가 주로 사용된다. 
이 책에서는 계산의 간편함을 위해 활성화 함수로 시그모이드 함수를 사용한다.</p>
</blockquote>
<br>

<h3 id="2-출력값-y">2. 출력값 $y$</h3>
<ul>
<li>뉴런 : 0,1</li>
<li>유닛 : 활성화 함수를 사용할 수 있는 임의의 수</li>
</ul>
<br>    

<h3 id="3-출력-신호-해석">3. 출력 신호 해석</h3>
<ul>
<li>뉴런 : 반응 여부</li>
<li>유닛 : 흥분도, 반응도, 활성도(activation)</li>
</ul>
<p><br><br></p>
<h2 id="시그모이드-함수">시그모이드 함수</h2>
<p>단위 계단 함수와의 가장 큰 차이는 시그모이드 함수는 <strong>미분 가능</strong>하며 <strong>0과 1사이의 임의의 수</strong>로 표현 가능하다.</p>
<p>(시그모이드 그래프 삽입) </p>
<p>1에 가까우면 유닛의 흥분도(반응도)가 높다고 하고(민감), 0에 가까우면 유닛의 흥분도가 낮다(둔감)고 본다.</p>
<p><br><br></p>
<h2 id="편향bias">편향(bias)</h2>
<p>뉴런의 신호 출력 여부를 결정하는 임계값 $\theta$을 <strong>치환한 값</strong>을 편향(bias)으로 설정한다. </p>
<p>$b = - \theta$</p>
<p>$z=\sum_{i=1}^{n} (x_i\cdot w_i)+b$</p>
<p>$y=a(\sum_{i=1}^{n} (x_i\cdot w_i)+b)$</p>
<p><br><br></p>
<hr>
<h1 id="4-신경망이란">4. 신경망이란?</h1>
<p>신경망은 뉴런의 네트워크로 구성된다면, 유닛을 네트워크로 구성하면 인공 신경망을 만들 수 있다. </p>
<p>신경망은 크게 3개의 <strong>layer(층)</strong>로 나눌 수 있다. <strong>입력층</strong>, <strong>은닉층(중간층)</strong>, <strong>출력층</strong> 이다. 입력층은 입력 정보를 가져오고, 은닉층은 연산 결과를 전달하며 정보를 처리한다. 출력층은 최종 결과를 출력한다.</p>
<br>

<p>해당 책에서는 신경망 중 <strong>필기체 숫자를 식별</strong>하는 신경망을 예로 설명하고 있다. 해당 신경망을 기준으로 신경망의 개념과 구조를 이해해보자. (해당 신경망은 입력층의 유닛 전부가 중간층의 유닛으로 신호를 보내는 <strong>완전 연결 계층</strong> 구조를 가진다.) </p>
<blockquote>
<p>필기체 숫자 식별 신경망</p>
</blockquote>
<ul>
<li>4x3 크기의 픽셀</li>
<li>64개 흑백 학습 데이터</li>
<li>숫자 0과 1을 식별</li>
</ul>
<br>

<h2 id="입력층input-layer">입력층(input layer)</h2>
<p>총 12개의 픽셀이 12개의 입력층에 전달된다. 입력층의 유닛은 입력과 출력이 동일하다. 항등함수를 사용해 $a(z)=z$로 표현할 수 있다.
<br></p>
<h2 id="출력층output-layer">출력층(output layer)</h2>
<p>숫자 0과 1을 식별하려면 0에 반응하는 유닛과 1에 반응하는 유닛이 필요하다. 따라서 출력층은 2개의 유닛으로 구성된다. 
<br></p>
<h2 id="은닉층hidden-layer">은닉층(hidden layer)</h2>
<p>은닉층에서는 입력된 이미지의 특징을 추출한다. 은닉층이 몇개의 층으로 구성되고 몇개의 유닛으로 구성되는지는 아래에서 알아보자. </p>
<p><br><br></p>
<hr>
<h1 id="5-신경망의-구조">5. 신경망의 구조</h1>
<p>해당 책에서는 <strong>은닉층의 특징 추출</strong>을 추상화하기 위해 악마 조직의 정보망으로 예시를 든다. </p>
<p>우선 악마들은 입력층, 은닉층, 출력층으로 3개의 위계로 표현할 수 있다. 입력층의 악마는 <strong>부하 악마</strong>로 픽셀 수에 맞게 총 12명이 있다. 부하 악마는 0과 1로 입력 신호를 3명의 <strong>숨은 악마</strong>에게 전달한다. 이 숨은 악마는 은닉층으로 볼 수 있다. </p>
<p>앞서 은닉층의 역할이 특징 추출이라 했다. 따라서 숨은 악마는 각각 자신이 <u>선호하는 패턴(특징)</u>을 가지고 있다. <strong>출력층의 악마</strong>도 각각 선호하는 악마가 있다. 각각의 유닛에서 전달받는 신호는 이러한 선호에 따라 강하게 혹은 약하게 전달된다. 또한 각각의 악마는 <u>개성(마음의 편향)</u>이 있어 선호하지 않은 신호에 대해서는 걸러내게 된다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/3fa4b8e6-758e-4839-957a-e6b3fe275a15/image.png" alt=""></p>
<br>


<h2 id="가중치와-편향">가중치와 편향</h2>
<p>악마는 선호에 따른 관계가 있고 이는 <strong>유닛의 가중치</strong>로 비유할 수 있다. A 악마는 부하 악마 4, 7을 선호하기에 A로 가는 4와 7의 <strong>신호는 크</strong>다. 이를 <strong>가중치가 크다</strong>고 말할 수 있다. 
<br></p>
<ol>
<li>악마 사이의 관계 <ul>
<li>관계가 좋으면 가중치가 크다.</li>
<li>관계가 나쁘면 가중치가 작다.</li>
</ul>
</li>
</ol>
<ol start="2">
<li>악마의 개성<ul>
<li>선호하지 않는 부하의 신호는 편향으로 걸러낸다.</li>
</ul>
</li>
</ol>
<br>

<h2 id="숨은-악마의-수">숨은 악마의 수</h2>
<p>신경망의 구조와 동작 방식을 악마의 네트워크로 비유했다. 흑백의 3X4 픽셀을 기준으로 0과 1을 분류하는 작업을 기준으로 했다. </p>
<p>이때 의문을 가질 수 있는 부분은 악마의 수에 대해서다. 픽셀의 개수에 맞춰 부하 악마의 수는 12개인 것은 받아들일 수 있다. 하지만 숨은 악마는 왜 3명인가? 이는 0과 1을 식별하는 패턴을 3가지로 두었기 때문이다. </p>
<p>사실 이 패턴에 따른 예측에 정확성에 대해서는 답에 따른 결과를 확인해야 알 수 있다. 이 과정에 대해서는 다음 장에서 수치적인 계산으로 알아보겠다.</p>
<p><br><br></p>
<hr>
<h1 id="6-신경망의-학습">6. 신경망의 학습</h1>
<p>신경망은 스스로 학습하는 알고리즘을 가졌다. 학습을 통해 파라미터를 결정할 수 있다. 신경망의 파라미터 결정 방법에는 크게 지도학습과 비지도 학습으로 나눌 수 있다. (참고 : <a href="https://velog.io/@son-dan-ha/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EA%B8%B0%EC%B4%88-%EC%A2%85%EB%A5%98">머신러닝 종류</a>)</p>
<p>지도학습이란 학습데이터를 가지고 가중치와 편향을 결정한다. 지도학습에서 신경망은 다음과 같은 방법으로 학습니다. 예측값과 정답 사시의 오차를 계산하여 이 호차들의 합이 최소가 되는 가중치와 편향을 결정한다. 이는 모델의 최적화라고도 한다. </p>
<p>오차의 총합을 결정하는 다양한 방식이 있다. 이 책에서는 <strong>제곱오차</strong>를 활용한다.</p>
<ul>
<li>제곱오차 = 비용함수 = $C_r$</li>
</ul>
<p>제곱오차의 합을 최소화하여 파라미터를 결정하는 방법을 <strong>최소제곱법</strong>이라고 한다.</p>
<p><br><br></p>
<hr>
<h1 id="마무리">마무리</h1>
<p>신경망의 구조를 설명하기 위해 악마의 네트워크로 비유해보았다. 인공신경망의 레이어(입력-은닉-출력)와 가중치와 편향이 신경망의 전체적 구조에서 어떤 의미를 갖는지 추상적으로 이해하는데에 도움이 되었다. </p>
<p>다음 장에서는 수치적 계산을 통해 신경망의 학습을 알아본다. 추상적 이해와 더불어 수학적 수식으로 그 과정을 살펴본다면 딥러닝에 대한 이해의 레이어가 한 층 더 쌓일 것이다.</p>
<br>







































]]></description>
        </item>
        <item>
            <title><![CDATA[인공지능의 개념과 종류]]></title>
            <link>https://velog.io/@son-dan-ha/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EA%B8%B0%EC%B4%88-%EC%A2%85%EB%A5%98</link>
            <guid>https://velog.io/@son-dan-ha/%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EA%B8%B0%EC%B4%88-%EC%A2%85%EB%A5%98</guid>
            <pubDate>Tue, 29 Jul 2025 08:44:51 GMT</pubDate>
            <description><![CDATA[<br>

<h1 id="인공지능ai">인공지능(AI)</h1>
<p>인공지능이란 <strong>문제를 해결</strong>함에 있어 마치 <strong>인간처럼</strong> 컴퓨터나 기계가 동작하도록 하는 것이다. </p>
<p>인공지능과 함께 머신러닝과 딥러닝 또한 들어봤을 것이다. AI는 <strong>두 개념을 포괄</strong>한다. 그리고 머신러닝 또한 딥러닝을 포괄하는 개념이다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/a5af5133-60e2-4655-81f9-616fcd55e353/image.png" alt=""></p>
<br>

<p>이 페이지에서는 머신러닝에 대해 알아볼 것이지만 머신러닝과 딥러닝의 차이는 이해하고 있을 필요가 있다. </p>
<br>

<h2 id="규칙-기반과-머신러닝-기반">규칙 기반과 머신러닝 기반</h2>
<p><strong>문제를 해결</strong>하는데, 왜 컴퓨터를 학습시켜 사용할까? 오히려 인간인 우리가 더 쉽게 할 수 있지 않는가 하는 의문이 생길 수 있다. </p>
<p>이에 대해서 다음 두가지를 비교하면 좋다. 바로 <strong>규칙 기반</strong>으로 문제를 해결하는 경우와 <strong>머신러닝 기반</strong>으로 문제를 해결하는 경우다. </p>
<br>

<p><strong>스팸 필터링</strong>하는 상황을 생각해보자.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/0a1238bf-15ba-4efa-8db4-58a2b979c7ca/image.png" alt=""></p>
<h3 id="두-방법의-차이">두 방법의 차이</h3>
<p>머신러닝의 경우 규칙 기반 알고리즘과는 다르게 <strong>여러 인자를 동시에 고려</strong>할 수 있고, 이에 따라 <strong>더 많은 유형의 스팸 분류</strong>를 기대할 수 있다.</p>
<h3 id="규칙-기반의-문제점">규칙 기반의 문제점</h3>
<ul>
<li>전문가의 지식이 규칙의 집합으로서 표현할 수 있는가?</li>
<li>스팸의 유형이 다양해질수록 규칙이 복잡해지는데, 과정 알고리즘화할 수 있는가?</li>
<li>스팸 유형이 빠르게 변화함에 따라 갱신된 규칙을 신속하게 적용할 수 있는가? </li>
</ul>
<p>규칙 기반의 알고리즘이 갖는 문제점을 머신러닝으로 해결할 수 있다. </p>
<p>그렇다고 머신러닝도 <u>문제가 없는 것은 아니다.</u></p>
<h3 id="머신러닝의-문제점">머신러닝의 문제점</h3>
<ul>
<li>정교한 학습을 위해서는 많은 양의 데이터가 필요하다.</li>
<li>대량의 계산을 위한 고성능의 컴퓨팅이 필요하다.</li>
</ul>
<br>

<p>인간의 규칙 기반 문제점을 해결할 수 있는 머신러닝은 각광을 받기까지 꽤 오랜 시간이 걸렸다. 그 원인으로는 <strong>컴퓨터 성능의 한계</strong> 때문으로도 볼 수 있다.</p>
<p>하지만 지금은 어떠한가? 많은 양의 데이터를 다루는 <strong>빅데이터</strong>가 등장하고 <strong>고성능의 컴퓨팅</strong> 파워와 알고리즘이 나왔다. </p>
<p>이런한 변화는 머신러닝의 급격한 성장으로 이어졌다.</p>
<br>

<h2 id="딥러닝과-머신러닝의-차이점">딥러닝과 머신러닝의 차이점</h2>
<p>딥러닝에 관한 포스트도 다룰 예정이기에 간단하게만 비교하겠다. </p>
<p>머신러닝, 딥러닝 모두 인공지능 안에 있는 개념이지만 의미적으로 보면 <strong>딥러닝이 인공지능과 더욱 가깝다</strong>고 할 수 있다.</p>
<p>머신러닝은 <strong>규칙 기반의 예측 방법론</strong>이다. 인공 지능에서 말하는 &quot;<strong>지능</strong>&quot;과의 큰 관련은 없다. </p>
<p>딥러닝은 <strong>인공 신경망(ANN)</strong>을 사용한다는 점에서 인공지능과 더욱 가깝다고 말할 수 있다. 인공 신경망이란 인간의 생물학적 신경망을 본딴 개념이다. </p>
<ul>
<li>인공 신경망(ANN)에 대한 내용은 여기서 확인</li>
</ul>
<br>
<br>

<hr>
<h1 id="머신러닝의-종류">머신러닝의 종류</h1>
<p>머신러닝의 종류는 <strong>학습 방법</strong>으로 구분할 수 있다. 학습 유형으로는 크게 두 가지로 나뉘는데, <strong>지도학습</strong>과 <strong>비지도학습</strong>이다. 원어(Supervised)에 가깝게 감독과 비감독이라고도 말한다.</p>
<p>지도학습은 정답이 <strong>있는</strong> 경우를 비지도학습은 정답이 <strong>없는</strong> 경우를 다룬다.</p>
<br>

<h2 id="지도학습supervised-learning">지도학습(Supervised Learning)</h2>
<p>지도학습은 입력 데이터 $X$와 타겟값 $y$를 알고 있는 데이터 학습이다. 지도학습에서는 $X$, $y$ 관계를 모델링하여 새로운 데이터에 대한 타겟값 예측 $\hat{y}$ 에 사용하게 된다. </p>
<p>$$
X → Model → \hat{y}
$$</p>
<br>

<p>함수로는 $y=f(X)$ 처럼 표현할 수 있고, 이때 $f$ 는 모델이다. </p>
<ul>
<li>AI에서 <strong>모델</strong>은 주어진 데이터를 학습하여 패턴과 규칙을 찾아내고, 새로운 데이터에 대해 예측이나 결정을 내리는 <strong>수학적 구조</strong> 또는 <strong>알고리즘</strong>을 말한다.</li>
</ul>
<br>

<p>지도학습에서는 $y$ 값의 형태에 따라 <strong>분류</strong>와 <strong>회귀</strong>로 나눈다. </p>
<ol>
<li><p>이산형 변수 (discrete variable)
 → 분류 (Classification)</p>
</li>
<li><p>연속형 변수(continous variable)
 → 회귀 (Regression)</p>
</li>
</ol>
<br>

<h3 id="1-분류classification">1. 분류(classification)</h3>
<p>타겟값 $y$ 가 <strong>이산형 변수</strong>라는 말은 특정한 값(유한정)을 가진다는 말이다. </p>
<p>개와 고양이를 구분하는 문제, 스팸 메일을 구분한는 문제, 얼굴 인식, 제품이 불량한지 조기 판단하는 경우 모두 <strong>분류 유형</strong>에 속한다. 이 예시 모두 개 아니면 고양이, 스팸 아니면 스팸이 아닌 매일, A 인간의 얼굴 아니면 B 혹은 C 인간의 얼굴 등 모두 특정한 값을 분류하는 문제다.</p>
<br>

<p>수많은 데이터가 $X_1$과 $X_2$의 특징을 가지고 있으며, 각각의 데이터는 $Y$ 라는 클래스(정답)를 가지고 있다. 이 데이터를 공간상에 표현하면 다음과 같이 위치하게 될 것이다. </p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/3d89f9a2-8dc0-4a64-8e5e-a3824111ca67/image.png" alt=""></p>
<h4 id="a-이진-분류binary-classification">a. 이진 분류(Binary Classification)</h4>
<p>이진 분류는 <strong>타겟값이 두 가지</strong>인 경우다.</p>
<p>예를 들어,</p>
<ul>
<li>스팸 / 정상 메일</li>
<li>합격 / 불합격</li>
<li>질병 있음 / 없음</li>
</ul>
<p>처럼 <strong>결과가 둘 중 하나</strong>로 나뉘는 문제다.</p>
<p>모델은 각 데이터가 특정 클래스에 속할 확률을 계산하고, 임계값(threshold)을 기준으로 클래스를 결정한다.</p>
<br>

<p>이진분류 함수는 아래와 같은 형태를 갖는다.</p>
<p>$$
\hat{y} =
\begin{cases}
1 &amp; \text{if } P(y=1 \mid X) &gt; 0.5 \
0 &amp; \text{otherwise}
\end{cases}
$$</p>
<br>

<h4 id="b-다중-클래스-분류">b. 다중 클래스 분류</h4>
<p><strong>타겟값이 세 개 이상</strong>인 경우다.</p>
<p>예를 들어,</p>
<ul>
<li>숫자 0~9 인식</li>
<li>고양이 / 강아지 / 새</li>
<li>제품 A / B / C 등급</li>
</ul>
<p>이진 분류보다 복잡하며, <strong>각 클래스에 대한 확률</strong>을 계산하고 가장 높은 값을 선택한다.</p>
<br>

<h3 id="2-회귀regression">2. 회귀(Regression)</h3>
<p>회귀는 타겟값이 <strong>연속형 변수</strong>일 때 사용한다.</p>
<p>집값 예측, 매출 예측 온도 예측처럼 <strong>결과가 실수 값</strong>으로 표현되는 문제다.</p>
<p>회귀는 보통 다음과 같은 형태로 표현된다.</p>
<p>$$
y=f(X)+ϵ
$$
여기서 $f(X)$는 모델이며 ϵ는 오차이다. </p>
<p>대표적인 <strong>평가 지표</strong>로는 MSE, RMSE, MAE 등이 있다.</p>
<br>

<hr>
<h2 id="비지도학습unsupervised-learning">비지도학습(Unsupervised Learning)</h2>
<p>비지도학습은 정답이 없는 데이터를 다룬다.
즉, $y$ 가 없다. 모델은 <strong>데이터의 구조나 패턴</strong> 자체를 찾는 것이 목적이다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/0f58b9d3-c450-44b2-957d-c7ff031c2b62/image.png" alt=""></p>
<h3 id="클러스터링clustering">클러스터링(Clustering)</h3>
<p>클러스터링은 <strong>비슷한 데이터끼리 묶는</strong> 방법이다. 예를 들어 고객을 소비 패턴에 따라 그룹화하거나 뉴스의 기사를 주제별로 분류, 유전자 데이터를 군집화하는 등의 작업에 클러스터링을 활용한다. <u>정답은 없</u>지만, <strong>데이터 내부의 유사성</strong>을 기준으로 그룹을 만든다.</p>
<p>대표적인 알고리즘으로는 <strong>K-means</strong>, <strong>Hierarchical Clustering</strong>, <strong>DBSCAN</strong> 등이 있다.</p>
<br>

<hr>
<h1 id="강화학습reinforcement-learning">강화학습(Reinforcement Learning)</h1>
<p>강화학습은 <strong>행동을 통해 보상을 최대화</strong>하는 학습 방식이다. 위의 학습과는 꽤 다른 형태를 가지고 있다. 우선 강화학습을 이해하기 위해서는 아래 <strong>4가지 구성 요소</strong>가 있음을 알아야 한다.</p>
<ul>
<li>Agent (행동 주체)</li>
<li>Environment (환경)</li>
<li>Action (행동)</li>
<li>Reward (보상)</li>
</ul>
<p><strong>에이전트</strong>는 <strong>환경</strong>에서 <strong>행동</strong>하고, <strong>보상</strong>을 받으며 점점 더 <u>좋은 전략을 학습</u>한다.</p>
<p>게임 AI, 로봇 제어, 자율주행 등에 활용된다. 최근의 트랜드로 볼 수 있다. 추후 <strong>피지컬 AI</strong>를 다루며 강화학습에 대해 더 깊게 이해하는 시간을 가져보겠다.</p>
<br>

<hr>
<h2 id="기타-유형">기타 유형</h2>
<h3 id="반지도-학습semi−supervised-learning">반지도 학습(Semi−Supervised Learning)</h3>
<p><strong>일부</strong> 데이터만 정답이 있고, 나머지는 <strong>없는</strong> 경우다. <strong>라벨링 비용</strong>이 비싼 상황에서 자주 사용된다.</p>
<br>


<h3 id="자기-지도-학습self−supervised-learning">자기 지도 학습(Self−Supervised Learning)</h3>
<p><strong>데이터 자체에서 정답을 만들어</strong> 학습하는 방식이다. 최근 <strong>대형 언어 모델(LLM)</strong>이 사용하는 핵심 방식으로 </p>
<ul>
<li>문장의 다음 단어 예측</li>
<li>이미지 일부 가리고 맞추기</li>
</ul>
<p>등이 자기 지도 학습을 말한다. <a href="https://velog.io/@son-dan-ha/Attention-Is-All-You-Need-%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0">Transformer 논문리뷰</a>에서도 이 개념을 다루었다. </p>
<br>

<h3 id="온라인-학습onlinelearning">온라인 학습(OnlineLearning)</h3>
<p>데이터가 <strong>실시간</strong>으로 들어오는 환경에서 모델을 지속적으로 <strong>업데이트</strong>하는 방식이다.</p>
<p>금융 거래 탐지, 추천 시스템 등에 사용된다.</p>
<br>


<h3 id="트랜스퍼-러닝transferlearning">트랜스퍼 러닝(TransferLearning)</h3>
<p><u>이미 학습된</u> 모델을 재사용하는 방식이다.</p>
<p>예를 들어, ImageNet으로 학습된 모델을 <u>내 데이터에 맞게</u> <strong>재학습(fine-tuning)</strong>한다.</p>
<p><strong>적은 데이터</strong>로도 <strong>높은 성능</strong>을 낼 수 있다는 장점이 있다.</p>
<br>

<hr>
<h1 id="머신러닝-프로세스">머신러닝 프로세스</h1>
<p>머신러닝은 단순히 모델만 학습하는 것이 아니다.
<strong>하나의 흐름</strong>으로 이해해야 한다.</p>
<ol>
<li>문제 정의</li>
<li>데이터 수집</li>
<li>데이터 전처리</li>
<li>모델 선택</li>
<li>학습</li>
<li>평가</li>
<li>개선 및 배포</li>
</ol>
<p>이 과정은 <strong>한 번</strong>으로 끝나지 않는다. 모델을 개선하기 위해 <strong>반복</strong>한다.</p>
<p><img src="https://velog.velcdn.com/images/son-dan-ha/post/e127ca7f-134b-4897-b685-64dfebb8d126/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>