<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sujikim-hattoo.log</title>
        <link>https://velog.io/</link>
        <description>˗ˋˏ 그럼에도 불구하고  ˎˊ˗</description>
        <lastBuildDate>Tue, 21 Oct 2025 14:15:29 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sujikim-hattoo.log</title>
            <url>https://velog.velcdn.com/images/sujikim-hattoo/profile/a366372b-cf6d-47aa-a9c0-b24caba0319e/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sujikim-hattoo.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sujikim-hattoo" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[논문] 캔들차트에 대한 비전 트랜스포머(ViT)의 예측 성공률은?]]></title>
            <link>https://velog.io/@sujikim-hattoo/%EB%85%BC%EB%AC%B8-%EC%BA%94%EB%93%A4%EC%B0%A8%ED%8A%B8%EC%97%90-%EB%8C%80%ED%95%9C-%EB%B9%84%EC%A0%84-%ED%8A%B8%EB%9E%9C%EC%8A%A4%ED%8F%AC%EB%A8%B8ViT%EC%9D%98-%EC%98%88%EC%B8%A1-%EC%84%B1%EA%B3%B5%EB%A5%A0%EC%9D%80</link>
            <guid>https://velog.io/@sujikim-hattoo/%EB%85%BC%EB%AC%B8-%EC%BA%94%EB%93%A4%EC%B0%A8%ED%8A%B8%EC%97%90-%EB%8C%80%ED%95%9C-%EB%B9%84%EC%A0%84-%ED%8A%B8%EB%9E%9C%EC%8A%A4%ED%8F%AC%EB%A8%B8ViT%EC%9D%98-%EC%98%88%EC%B8%A1-%EC%84%B1%EA%B3%B5%EB%A5%A0%EC%9D%80</guid>
            <pubDate>Tue, 21 Oct 2025 14:15:29 GMT</pubDate>
            <description><![CDATA[<h2 id="공부-목적">공부 목적</h2>
<p>차트를 보다보면
이거 수많은 차트 이미지 딥러닝 모델에 학습시키면 사람이 일일이 공부할 필요도 없지 않을까?라는 생각이 들어 찾아봄</p>
<pre><code>논문 정보
제목: Learning Predictive Candlestick Patterns: Vision Transformer Approach

저자/연도: Stanford Vision Lab, 2025

내용: 캔들차트 이미지를 Vision Transformer(ViT)에 학습시켜 단기 가격 예측 성공률 91% 달성.

특징: 인간 트레이더의 ‘시각적 직관’을 딥러닝 모델로 시각화함.

출처: CVPR Proceedings</code></pre><ul>
<li><a href="https://cs231n.stanford.edu/2025/papers/text_file_840597081-LaTeXAuthor_Guidelines_for_CVPR_Proceedings__1_-2.pdf">논문 링크 바로가기</a></li>
<li>아래 글은 Moonlight &amp; ChatGPT을 이용하여 공부한 내용을 작성. </li>
</ul>
<hr>
<hr>
<h2 id="0-개요">0. 개요</h2>
<ul>
<li>연구 배경<ul>
<li>주식 시장에서 가격 변동 예측은 매우 중요</li>
<li>이 가격 변동을 예측하는데 기술적 분석이 많이 활용됨. 그 중에서도 캔들차트가 대표적.</li>
</ul>
</li>
<li>기존 접근 한계<ul>
<li>이 캔들차트로만 미래 가격을 신뢰성 있게 예측할 수 있는지에 대한 논란은 여전히 많다. (<em>이 차트 패턴이 정말 예측 정보를 담고 있는 게 맞을까...?</em>)</li>
<li>기존 연구들은 통계쩍 지표나 시계열 모델을 이용한 수치 데이터 분석 위주. 패턴 자체를 학습한 연구는 거의 이루어지지 X.</li>
</ul>
</li>
<li>연구 목적<ul>
<li>Vision Transformer(ViT)모델 사용 -&gt; 캔들차트 이미지로부터 주가 변동 패턴 학습 및 예측 검증[이미지 기반 예측]</li>
</ul>
</li>
<li>연구 아이디어(2가지)<ul>
<li>가격 예측을 위한 분류</li>
<li>자기 지도 학습</li>
</ul>
</li>
</ul>
<p>** 트랜스포머가 캔들차트 시각적 패턴 속에서 진짜 예측 신호를 학습할 수 있을까..?? **</p>
<hr>
<h2 id="1-introduction-소개">1. Introduction 소개</h2>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/638dcd34-2a98-458d-b9c0-c508acb1879e/image.png" alt="">
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/4b92da45-1312-45fa-a7a4-c6f9a12d7096/image.png" alt="">
<a href="https://data.krx.co.kr/contents/MDC/MDI/mdiLoader/index.cmd?menuId=MDC0201020203">삼성전자 캔들차트 출처</a></p>
<ul>
<li><p>캔들차트(Candlestick chart)</p>
<ul>
<li>정의: 18세기 일본의 쌀 상인이 개발한 기법. 현재까지도 다양한 자산 가격 변동을 시각적으로 표현하는데 사용됨.</li>
<li>구성<ul>
<li>Open(시가)</li>
<li>High(고가)</li>
<li>Low(저가)</li>
<li>Close(종가)</li>
</ul>
</li>
<li>여론<ul>
<li>🙂: 시장 심리나 가격 추세 예측 가능!</li>
<li>🙁: 흠...이 차트만으로 미래 가격을 예측하기에는 무리...</li>
</ul>
</li>
<li>기존의 연구(2. 에서 계속)<ul>
<li>기존의 연구들도 캔들 차트를 수집 방법, 정의, 양에 따라 서로 다른 결과를 내놓음.</li>
</ul>
</li>
</ul>
</li>
<li><p>연구 배경(기술) 및 연구 방법</p>
<ul>
<li>¹ViT 등장: 딥러닝 기반의 컴퓨터 비전 기술이 발전하면서 이미지 데이터를 다루는 <strong>Vision Transformer(ViT)</strong>가 등장.</li>
</ul>
</li>
<li><p>연구방법</p>
<ul>
<li>1st. Multi-class classification을 통해  캔들 차트 이미지 입력 -&gt; 미래 가격 움직임(상승 or 하락 or 유지) 직접 예측하도록 모델 학습</li>
<li>2nd. 자기지도학습(Self-supervised learning) 기법인 Masked Autoencoders(MAE)를 결합해 이미지 일부 가리고(Masked) 나머지 정보를 복원하도록 학습 -&gt; 라벨이 없어도 시각적 패턴을 스스로 학습한 뒤에 실제로 가격을 예측해보며 파인튜닝으로 성능 비교
(단, 두 ViT모델은 동일한 데이터셋과 동일한 학습조건-epoch 수로 훈련됨)</li>
</ul>
</li>
</ul>
<pre><code>¹ViT: 이미지에도 텍스트 Transformer 구조를 적용. 전체이미지는 문장, 패치는 단어로 취급.
-&gt; 이미지 전체 문맥(패치 간 관계)을 Transformer의 Self-Attention으로 학습. </code></pre><hr>
<h2 id="2-literature-review-문헌-연구">2. Literature Review 문헌 연구</h2>
<ul>
<li>(앞에서도 언급했듯) 캔들차트 이미지를 활용한 컴퓨터 비전 기반 분석 연구는 매우 희소(sparse)한 상태!</li>
<li>기존 연구들은 수치형 OHLC 데이터 이용한 시계열 분석에 집중(캔들차트 시각적 정보는 시계열 데이터보다 구조적으로 불안정하기 때문)(있더라도 여러 모델 간의 성능 비교 or 패턴 감지하는 객체 탐지 연구 정도만) -&gt; 이미지 자체로 가격 예측을 시도하는 이번 연구가 굉장히 이례적이고 독창적임</li>
</ul>
<blockquote>
<p>🤔이미지 처리 관련 분석 기술은 많았어도 왜 그동안 이미지 기반 캔들차트 분석 연구가 없었을까?</p>
</blockquote>
<ul>
<li>주식 종목과 차트 기준(틱, 분봉, 일봉, 주봉 등)마다 패턴이 크게 달라져서 모델이 특징을 잡기 어려워해 연구 결과도 다르고 예측 일관성을 유지하는 게 어려워서...?</li>
</ul>
<hr>
<h2 id="3-dataset-데이터셋">3. Dataset 데이터셋</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>상세 내용</th>
</tr>
</thead>
<tbody><tr>
<td><strong>데이터 수집 기간</strong></td>
<td>2020년 1월 ~ 2025년 6월 (정규 시장 시간 09:30 ~ 16:00만 포함)</td>
</tr>
<tr>
<td><strong>데이터 출처 및 자산 범위</strong></td>
<td>Polygon.io API를 이용한 5분봉 OHLC 데이터. 지수 펀드, 개별 주식, 레버리지 ETF를 포함한 총 10종의 미국 주식 자산 사용.</td>
</tr>
<tr>
<td><strong>스냅샷 구성</strong></td>
<td>총 50,000개의 224x224 이미지. 각 스냅샷은 ¹연속된 30개의 5분봉(약 2.5시간)에 헤당하는 데이터로 구성</td>
</tr>
<tr>
<td><strong>예측 목표 및 라벨링 기준</strong></td>
<td>스냅샷 시점으로부터 ²25분 후의 종가를 기준으로 3가지 클래스 라벨링:<br>• <strong>Up:</strong> 0.5% 초과 상승<br>• <strong>Down:</strong> -0.5% 미만 하락<br>• <strong>Flat:</strong> 그 외 (-0.5% ~ 0.5% 사이)</td>
</tr>
<tr>
<td><strong>클래스 불균형 및 분포</strong></td>
<td>Flat:Up:Down = 80:10:10의 불균형 분포를 그대로 사용.</td>
</tr>
<tr>
<td><strong>데이터 분할 비율</strong></td>
<td>Train:Validation:Test = 70:15:15</td>
</tr>
<tr>
<td><strong>이미지 전처리</strong></td>
<td><code>mplfinance</code> 라이브러리 이용해 캔들차트 이미지 생성. 모델이 시각적 패턴에만 집중하도록 축, 격자, 텍스트 등은 제거. (* 상승: 녹색, 하락: 빨간색)</td>
</tr>
</tbody></table>
<pre><code>¹왜 &#39;연속적&#39;인 스냅샷이 필요할까?
-&gt; 실제 트레이딩에서도 끊기지 않고 연속된 시간의 패턴을 보고 판단. 
이 논문에서도 끊기지 않는(intraday) 연속 구간 입력을 사용하면 모델 가격 움직임의 맥락을 놓치지 않을 수 있어서

²왜 25분후를 예측시점으로 설정했을까?
-&gt; 논문에서 구체적인 근거는 제시 되지 않았지만 25분을 단기 예측의 최적점이라고 본 것 아닐까?
너무 짧으면 변동 폭이 작아 의미있는 패턴 잡기 어렵고 반대로 너무 길면 외부 요인의 영향이 커져 딱 캔들패턴만의 힘을 검증하기 어렵기 때문에 </code></pre><hr>
<h2 id="4-methods-방법">4. Methods 방법</h2>
<ul>
<li>다중 클래스 이미지 분류로 접근<ul>
<li>입력: 캔들스틱 차트 이미지. ¹I ∈ R^(H×W ×3)</li>
<li>출력: 미래 가격 움직임이 세 가지 클래스(Down/Flat/Up)중 어느 하나에 속할 확률 분포</li>
<li>모델: ²Vistion Transformer (ViT) -&gt; CNN보다 전역적 흐름을 더 잘 포착함.</li>
</ul>
</li>
</ul>
<pre><code> ¹I ∈ R^(H×W ×3)의 의미?
    -&gt; 이미지는 실수(real numbers)로 구성된 3차원 텐서임. 높이 x 너비 x RGB 채널 수. 
    캔들 색상(초록/빨강)을 구분하기 위해 컬러 이미지 처리가 필요

 &gt; ²ViT와 기존 CNN(합성곱 신경망) 성능 차이?
    -&gt; CNN: 이미지 전체를 필터로 스캔. 합성곱 연산. 지역적 특징 추출. 계층적으로 전역 측징 구축
    vs ViT: 이미지 전체를 패치로 나누어 시퀀스 처리 + 모든 패치 쌍 간의 중요도 학습. Self-Attention. 전역적 특징 추출. </code></pre><h3 id="41-vision-transformer-architecture-vit-비전-트랜스포머-구조">4.1. Vision Transformer Architecture ViT 비전 트랜스포머 구조</h3>
<h4 id="기본-아키텍처-¹vit-tiny">기본 아키텍처: ¹ViT-Tiny</h4>
<ul>
<li>입력 이미지를 겹치지 않는 패치(patch) 단위로 ²분할</li>
<li>입력 크기: 224×224 픽셀 크기의 컬러 이미지(RGB=3채널)</li>
<li>패치 크기: 16×16 픽셀</li>
<li>패치 개수 N =(224/16)×(224/16)=196</li>
</ul>
<p>=&gt; 한 이미지는 196개의 패치로 나눠지게 된다.</p>
<pre><code>¹ ViT-Tiny 기본 하이퍼파라미터 정보
-&gt; 인코더 블록수(L): 12, 임베딩 차원(D): 192, MSA 헤드 수(H): 3
² 패치로 왜 잘라내는 걸까? 
-&gt; 문장을 분석하려면 단어로 쪼개어 분석하는 것처럼 픽셀 대신 패치 단위로 잘게 쪼개어 Transformer 구조를 그대로 쓰기 위함! </code></pre><h4 id="1단계-이미지를-패치로-나누기">1단계: 이미지를 패치로 나누기</h4>
<ul>
<li>각 패치 
$$
x_p \in \mathbb{R}^{P^2 \cdot 3}
$$
입력 이미지 크기: 224 x 224 픽셀. 패치 단위의 RGB 벡터로 변환</li>
<li>Flatten 과정 거쳐 1차원 시퀀스로 정렬(하나의 패치 크기가 16x16x3 = 768, 즉 길이가 768인 1차원 벡터로 flatten 됨)</li>
</ul>
<h4 id="2단계-패치를-벡터로-바꾸기">2단계: 패치를 벡터로 바꾸기</h4>
<ul>
<li>각 패치를 입력 정규화를 위해 ¹선형 투영을 통해 192차원 ²임베딩 벡터로 변환(아래는 선형 투영 식)
$$
³E \in \mathbb{R}^{(P^2 \cdot 3) \times d}
$$</li>
</ul>
<pre><code> ¹선형 투영(Linear Projection)을 꼭 해야할까?
 -&gt; 트랜스포머 자체가 입력 차원이 일정해야 작동함. 지금 패치는 단순 일렬로 나열된 값의 개수나 너무 ㅁ낳고 
패치마다 정보량이 다르기 때문에 공통 차원인 d=192, 192차원으로 줄여서 다루기 쉽게 만드는 것!

 ²임베딩이란?
    -&gt; 고차원 입력을 밀집된 벡터 공간으로 변환

 ³E: 학습 가능한 가중치 행렬. 패치를 새로운 표현공간으로 옮겨주는 역할</code></pre><h4 id="3단계-시퀀스-구성">3단계: 시퀀스 구성</h4>
<ul>
<li>192차원의 임베딩 벡터로 변환 후(like 192개의 단어가 생긴 셈)</li>
<li>트랜스포머 기본<ul>
<li>순서가 있는 데이터를 학습 -&gt; 패치들 순서 알려줘야[위치 임베딩] </li>
<li>출력은 보통 문장의 대표 &#39;요약 벡터&#39; -&gt; 클래스 토큰이라는 특별한 벡터를 앞에 붙여. 이 벡터가 모델이 이미지의 전체 의미를 요약하도록 학습(= CNN global pooling)</li>
</ul>
</li>
</ul>
<ul>
<li><p>트랜스포머 최종 입력:
$$
z_0 = [x_{\text{class}}; x_p^1 E; x_p^2 E; \ldots; x_p^N E] + E_{\text{pos}}
$$</p>
<ul>
<li>x_class: 이미지 전체 대표 요약 담당</li>
<li>x_p^iE : i번째 패치의 임베딩 벡터</li>
<li>E_pos: 각 패치의 위치 정보를</li>
</ul>
</li>
</ul>
<h4 id="4단계-트랜스포머-인코더-통과">4단계: 트랜스포머 인코더 통과</h4>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/2272f3f6-7ec4-4f6e-9392-6393d181461a/image.png" alt="">
<a href="https://wikidocs.net/images/page/164842/Fig_24.png">사진 출처</a></p>
<p>인코더 블록은 12개의 블록(Layer)로 쌓여있고 각 블록의 구성은 다음과 같음</p>
<ul>
<li>MSA(Multi-Head Self-Attention) -&gt; 패치 간 관계를 여러 관점에서 학습</li>
<li>MLP(Multi-Layer Perceptron) -&gt; 각 토큰 특징을 비선형적으로 확장</li>
<li>LN(Layer Normalization) -&gt; 학습 안정화</li>
<li>잔차 연결(Residual Connection) 적용 -&gt; 기존 정보 보존 및 그라디언트 소실 방지</li>
</ul>
<p>=&gt; 위 과정을 거치면 맨 앞의 클래스 토큰( x_class)이 전체 이미지 특징을 요약한 벡터로 변함. 이 벡터가 분류기에 입력되어 최종적으로 이미지 레이블 예측 가능!</p>
<blockquote>
<p>ViT 프로세스 요약
: 이미지를 패치 단위로 분할 -&gt; 각 패치를 토큰처럼 임베딩 &amp; Trasnformer 인코더로 처리  -&gt; 이미지 내 지역적/전역적 관계를 동시에 학습</p>
</blockquote>
<h3 id="42--training-strategies-훈련-전략">4.2.  Training Strategies 훈련 전략</h3>
<h4 id="전이학습-활용">전이학습 활용</h4>
<ul>
<li>사전 학습된 가중치 사용: ImageNet-1k 데이터셋으로 미리 학습된 ViT가중치를 초기값으로 사용.<ul>
<li>(참고) ImageNet-1k은 자연 이미지 기반이지만 기본적인 시각적 패턴(윤곽선, 형태 , 질감 등)을 이미 학습했기 떄문에 차트 데이터에도 적용 가능</li>
</ul>
</li>
</ul>
<h4 id="첫-번째-접근방식-vit--분류층-추가">첫 번째 접근방식: ViT + 분류층 추가</h4>
<ul>
<li>입력: 캔들 차트 RGB 이미지</li>
<li>구조: ViT 클래스 토큰을 선형 분류층(Linear Classifier)에 연결해 세 가지 클래스 확률 계산(아래는 계산식)
  <img src="https://velog.velcdn.com/images/sujikim-hattoo/post/a23f5ef5-7f0a-429b-a835-9971d4b10130/image.png" alt=""></li>
<li>출력: 미래 가격 움직임이 3개 클래스(Up/Flat/Down) 중 하나일 확률</li>
<li>학습: 손실함수 통해 예측값과 실제 라벨값 차이를 줄여 =&gt; 의미있는 시각적 표현 학습할 수 있또록</li>
</ul>
<h3 id="43-self-supervised-pretraining-with-masked-autoencoders-mae를-이용한-자기-지도-학습">4.3. Self-Supervised Pretraining with Masked Autoencoders MAE를 이용한 자기 지도 학습</h3>
<h4 id="두-번째-접근-maemasked-autoencoder-기반-자기지도-학습">두 번째 접근: MAE(MAsked Autoencoder) 기반 자기지도 학습</h4>
<ul>
<li>라벨 없이 학습(¹Self-supervised): 차트 이미지 일부(75%)를 ²랜덤으로 가리고 나머지 ³25%만 보고 원래 이미지 복원하도록)</li>
<li>구조<ul>
<li>Encoder 𝑓_𝜃: 보이는 패치들만 ViT 구조로 처리</li>
<li>⁴Decoder 𝑔_𝜙: 인코딩된 표현 바탕 -&gt; 마스크된 패치들에 대해 서만 재구성 손실을 ⁵계산하여 전체 이미지 복원(⁶가벼운 구조 사용)(아래는 재구성 손실 계산식)
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/be8a50f1-13ec-4f18-86fe-1e2244b8d9e6/image.png" alt=""></li>
</ul>
</li>
</ul>
<p>=&gt; 캔들스틱 로컬(캔들 간 관계) + 글로벌(전체 추세) 패턴 동시 학습 가능 &amp; 더 깊은 시각적 이해</p>
<pre><code>¹ 직접적인 분류 목표 x: 이건 Up이야, Down이야 맞히는 게 목표 x -&gt; 가려진 이미지 복원해서 내부 패턴 잘 이해해라. 정답 레벨 없음 = Self-supervised learning

² 랜덤으로 가린다
-&gt; 패치 인덱스를 무작위로 섞어 상위 N(1-m)개의 패치만 남긴다. 특정 위치에 의존하지 않으면서 일부만 사용하겠다는 뜻. (N=100. m=0.75면 25개의 패치만 남긴다는 뜻)
³ 여기서는 남은 25% 패치만 인코더에 입력 -&gt; 이 일부만 보고 전체 그림 유추
⁴ 디코더 입력 형태
-&gt; 인코더 출력 + 마스크 토큰 함께 입력받음. 단순 복원용이어서 경량 구조 사용
⁵ 손실 함수 계산 = 숨겨진 부분(마스크) 얼마나 잘 맞췄는지만 확인 
⁶ 표현을 학습하는 것이 중요한 MAE의 인코더와 달리 디코더는 단순 복원용이기에 굳이 복잡할 필요 x. 학습 효율 향상과 계산 비용 절감 위함. 
</code></pre><h3 id="44-구현-세부사항-implementation-details">4.4. 구현 세부사항 Implementation Details</h3>
<ul>
<li>안정적인 학습 설정<ul>
<li>과적합 방지 -&gt; ²AdamW ¹옵티마이저 + ³weight decay λ = 0.05) 사용</li>
</ul>
</li>
<li>최소한의 데이터 증강<ul>
<li>⁴수평 이동만 적용</li>
</ul>
</li>
<li>정규화<ul>
<li>사전 학습 모델(ImageNet)과 입력 데이터 분포 맞추기 위해</li>
<li>입력 이미지 픽셀값을 평균 &amp; 표준편차로 ⁵정규화</li>
</ul>
</li>
</ul>
<pre><code>¹ 옵티마이저: 모델 학습할 때, 손실을 최소화하도록 가중치를 조정하는 알고리즘. 얼마나, 어떤 방향으로 조정할지 결정.
² AdamW은 기존 Adam보다 정규화 효과가 더 강함(AdamW는 가중치 감쇠를 별도로 적용 -&gt; 과적합 방지에 더 효과적)
³ 가중치 감쇠
-&gt; 가중치 값이 과도하게 커지는 것을 막아 입력 변화에 덜 민감하고 일반화된 학습 유도
⁴ 수평 이동을 하면 동일한 패턴을 다양한 시점에서 학습하게함.(e.g, Day1~Day5, Day2~Day6..) =&gt; 모델이 특정 날짜 위치에 과도하게 의존하지 않도록 과적합 완화.
⁵ 정규화: &lt;모델 학습 전 입력 데이터 전처리 단계&gt;에서 입력 데이터(입력 이미지 픽셀 값) 분포를 모델 학습 분포와 일정하게 맞추는 과정. (xᵢⱼ - mean) / std

</code></pre><h3 id="45-interpretability-analysis-해석-분석">4.5. Interpretability Analysis 해석 분석</h3>
<h4 id="mae-학습한-잠재표현-안-패턴들-분석">MAE 학습한 잠재표현 안 패턴들 분석</h4>
<ul>
<li>클러스터링 분석 <ul>
<li>1st. 트랜스포터 인코더 통과 뒤 클래스 토큰에서 피처 벡터 추출</li>
<li>2nd. K-means clustering 적용(k=20)해 비슷한 패턴 샘플들 그룹화</li>
<li>3rd. 각 군집 안 실제 정답 분포 확인 -&gt; 모델의 일관성 평가 &#39;비슷한 차트 이미지 모델이 같은 방향으로 잘 예측하고 있는가?&#39;<ul>
<li>클러스터 순도 P_c 계산-&gt; 각 군집에서 가장 많이 등장한 클래스 비율</li>
<li>e.g., 어떤 군집 대부분 샘플을 상승으로 예측 -&gt; p_c 값 매우 높게. 일관된 패턴 포착 잘하고 있음.</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="5-experiments-실험">5. Experiments 실험</h2>
<h3 id="51-baselines-기준-모델">5.1. Baselines 기준 모델</h3>
<ul>
<li>MAE 기반 접근법 성능 확인 위해 두 가지 금융 예측 모델 사용</li>
<li>1) ¹RSI Statisticlcal Strategy(전통적 통계적 RSI 전략)<ul>
<li>²개념: 일정 기간 동안 가격 상승폭과 하락폭 비교 -&gt; 주가의 과매수/과매도 상태 판단. 주가 추세 전환 가능성 탐지하는데 사용</li>
<li>예시: RSI 값 낮아(높아) 과매도(과매수) 상태-&gt; Up(Down) 예측(중간 값 근처라면 Flat으로 분류)</li>
</ul>
</li>
<li>2) ³RNN with ⁴LSTM(시계열 기반 순환신경망)<ul>
<li>구성: 3개의 은닉층(128, 64, 32 유닛) 사용 &amp; ⁵dropout rate: 0.2 &amp; 활성화 함수: tanh</li>
</ul>
</li>
</ul>
<pre><code>¹ RSI: Relative Strength Index, 상대적 강도 지수, 심리와 과열 정도 지표. 최근 며칠동안 주가를 비교해서 지금 주가가 너무 올랐는지(과매수) 아니면 너무 떨어졌는지(과매도) 판단하는 지표. 오른 날이 많으면 RSI값은 높아지고, 반대로 주가가 내린 날이 많으면 RSI값은 낮아짐.
² (구체적) RSI 값이 낮다(높다) -&gt; 최근에 주가가 너무 많이 낮아진(높아진) 상태 = 과매도(과매수) 상태 =&gt; 곧 반등(하락)할 수 있다는 신호로 해석
³ RNN: Recurrent Neural Network. 계열 데이터 다루는 대표적인 딥러닝 모델. e.g, 주가, 온도, 음악, 문장 등 -&gt; 이전 단계 정보를 다음 단계로 전달하며 기억을 유지하며 &#39;앞에서 본 걸 기억하고 다음을 예측하는 모델&#39;
⁴ LSTM이 무엇인가요?: Long Short-Term Memory. 기억 셀(cell) 구조를 추가해 RNN이 오래된 정보는 잊어버린다는 단점을 개선한 업그레이드 버전.
⁵ dropout: 과적합 막는 방법. 일부 뉴런을 무작위로 꺼서(=0으로 만들어서) 모델이 한 가지 패턴에 너무 의존하지 않게 만드는 장치.</code></pre><h3 id="52-results-결과">5.2. Results 결과</h3>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/d2f8228b-a09b-4538-8e0a-2590a769eb06/image.png" alt=""></p>
<ul>
<li>Vit-MAE Clustered 모델의 독보적 성능<ul>
<li>전통적인 시계열 분석 / 단순 ViT 모델 대비 가장 높은 예측 정확도</li>
<li>보합(Flat) 상태 비율은 실제 데이터 분포와 가장 유사하게 예측(0.86)</li>
</ul>
</li>
</ul>
<hr>
<h2 id="6-conclusion-결론">6. Conclusion 결론</h2>
<h4 id="기존-rnn-모델이나-기술적-지표보다-vision-transformer가-캔들스틱-차트로부터-주가-단기-변동을-높은-정확도로-예측할-수-있음을-보여준다">기존 RNN 모델이나 기술적 지표보다 Vision Transformer가 캔들스틱 차트로부터 주가 단기 변동을 높은 정확도로 예측할 수 있음을 보여준다.</h4>
<p>** Key Points**</p>
<ul>
<li>기술적 분석의 데이터 타당성<ul>
<li>캔들스틱 차트 패턴 안에는 실제로 주가 변동을 예측하는 데도움이 되는 &#39;신호&#39;가 존재함이 증명됨. -&gt; 기술적 분석이 단순한 감이 아니라 통계적 타당성을 가질 수 있음을 시사</li>
</ul>
</li>
<li>자기 지도학습(MAE) 효과<ul>
<li>MAE 복원 과정에서 시각정 특징 더 깊게 이해 &amp; 유사한 패턴끼리 잘 묶이는 클러스터링 가능 -&gt; 기존 다중 분류 모델보다 예측력 크게 향상</li>
</ul>
</li>
</ul>
<h3 id="61-limitations-한계">6.1. Limitations 한계</h3>
<ul>
<li>특정 시장/주식 한정:<ul>
<li>정상적인 시장 상황 &amp; 유동성 높은 주식(Liquid stock)에만 한정 -&gt; 비정상적인 시장상황(e.g, 금융 위기 등)이거나 유동성 높은 주식에서는 모델 성능 저하 가능</li>
</ul>
</li>
<li>정보 제한<ul>
<li>오직 캔들스틱의 시각적 정보(OHLC 데이터)만 사용</li>
<li>¹거래량(volume)이나 ²기본적 데이터(fundamental data)를 통합 X -&gt; 주식 움직임 예측은 가능하지만 이유는 설명 못 함.</li>
</ul>
</li>
<li>단기 예측(intraday) 한계<ul>
<li>30개의 캔들(총 2.5시간)로 구성된 스냅샷 분석 + 25분 후의 가격 변동 예측에 초점 -&gt; 장기간 패턴 탐구에는 한계 o</li>
</ul>
</li>
<li>제일 중요한 것<ul>
<li><strong>편향된 방향성 예측</strong> -&gt; 상승/하락보다 보합(Flat) 예측을 가장 잘함. 실제 트레이딩에서는 상승/하락 방향 예측 필수 -&gt; 실제 트레이딩 시스템에 적용하기에는 가장 중요한 한계로 작용</li>
</ul>
</li>
</ul>
<pre><code>¹거래량: 시장의 관심도나 강도 나타내는 지표
²기본적 데이터: 기업 재무상태, 산업 동향 등</code></pre><h3 id="62-future-work-후속-연구">6.2. Future Work 후속 연구</h3>
<ul>
<li>멀티모달 모델로 확장 -&gt; 감정(sentiment) 데이터 결합해 시장 심리까지 반영할 예정</li>
<li>다양한 자산군에 대한 실험(e.g, 외환, 암호화폐, 원자재 등)을 통해 다양한 시장에서의 모델 검증</li>
<li>실시간 거래 시스템 개발 -&gt; 리스크 관리 로직 통합되도록</li>
<li>장기 패턴 탐구 -&gt; 일봉/주봉 차트 등 장기간 패턴도 탐구해 단기 예측 중심 모델의 한계 보완해볼 것</li>
</ul>
<hr>
<hr>
<blockquote>
<p>😊느낀점:
기존 자연어 처리 분야에서 사용되던 ViT 딥러닝 모델을 이용해 캔들스틱 차트 이미지에서 단기적으로 주가 변동을 예측하는 유효한 신호가 포착될 수 있음을 실험으로 증명한 글이다. 나도 그동안 &#39;직관&#39; &#39;감&#39;으로만 여기던 기술적 분석이 어느정도 데이터적으로 타당성을 가질 수 있음을 깨달았고 많은 모델 중에서도 MAE와 같은 자기 지도 학습 전략이 노이즈를 극복하고 최적의 학습 효과를 내는데 중요한 열쇠임을 알 수 있었다. 아직까지는(내가 아는 선에서) AI가 주가를 완벽하게 예측할 수 없다고 알고있지만 위 향후 현구에서 언급되었듯 다양한 정보를 통합하고 장기 예측 패턴도 계속해서 연구한다면 ViT가 금융 시장 분석에 있어 중요하게 자리매김하지 않을까 생각한다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NLP] 자연어 처리의 첫 단계, 토큰화와 BPE에 대해 알아보자]]></title>
            <link>https://velog.io/@sujikim-hattoo/NLP-%EC%9E%90%EC%97%B0%EC%96%B4-%EC%B2%98%EB%A6%AC%EC%9D%98-%EC%B2%AB-%EB%8B%A8%EA%B3%84-%ED%86%A0%ED%81%B0%ED%99%94%EC%99%80-BPE%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@sujikim-hattoo/NLP-%EC%9E%90%EC%97%B0%EC%96%B4-%EC%B2%98%EB%A6%AC%EC%9D%98-%EC%B2%AB-%EB%8B%A8%EA%B3%84-%ED%86%A0%ED%81%B0%ED%99%94%EC%99%80-BPE%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Fri, 03 Oct 2025 07:18:09 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 글은 Do it! BERT와 GPT로 배우는 자연어 처리: 트랜스포머 핵심 원리와 허깅페이스 패키지 활용법 &lt;2장 문장을 작은 단위로 쪼개기&gt;를 읽고 공부하며 작성한 내용입니다.</p>
</blockquote>
<p>기계를 공부하는 사람이
기계를 가장 잘 이해하기 위해 기계를 부품으로 분해하듯,</p>
<p>자연어 처리를 본격적으로 시작하기 전에
컴퓨터가 문장 또는 문서를 잘 이해할 수 있도록 작은 단위로 나누는 과정이 필요하다,
이를 NLP에서는 <strong>토큰화(tokenization)</strong> 라고 부른다.</p>
<hr>
<h1 id="tokenization-토큰화">Tokenization 토큰화</h1>
<ul>
<li><p>정의: 문장을 토큰(token) 시퀀스로 나누는 과정. 최신 NLP 모델(e.g,트랜스포머 모델)의 기본 입력 형태도 이 &#39;토큰 시퀀스&#39;임</p>
</li>
<li><p>방법: 토크나이저(tokenizer)라는 프로그램이 토큰화 수행 e.g, 한국어 형태소 분석기인 은전한닢(Mecab), 꼬꼬마(Kkma) 등</p>
</li>
<li><p>종류</p>
<ul>
<li><p>단어(어절) 단위 토큰화(Word-level)</p>
<ul>
<li>장점: 공백 기준 분리 가능해 구현 간단<ul>
<li>단점: 어휘 집합(vocabulary) 크기가 매우 커져 학습 효율 저하 발생 가능
e.g, 갔었어, 갔었지, 갔었어요, 갔었는데요 등 -&gt; 사실상 같은 의미지만 모두 다른 토큰으로 처리됨. 이를 해결하기 위해 &#39;갔었&#39; 같은 의미있는 단위로 나누는 형태소 분석을 사용하기도</li>
</ul>
</li>
</ul>
</li>
<li><p>문자 단위 토큰화(Character-level)</p>
<ul>
<li>장점: 한글 표현 가능 글자 수 (11,172개) + 영어, 숫자 포함해도 어휘 집합 크기 엄청 크지 않음. 신조어나 미등록 토큰(Out-of-Vocabulary, OOV) 문제에서도 자유로움<ul>
<li>단점: 각 문자가 독립적인 의미 가지기 어려움 -&gt; 문맥 파악 힘듦 &amp; 토큰 시퀀스 길어져 모델 성능 떨어질 수도</li>
</ul>
</li>
</ul>
</li>
<li><p>서브워드subword 단위 토큰화(Subword-level)</p>
<ul>
<li>장점: 단어 단위와 문자 단위 장점 절충. 대표적인 기법이 바로 <strong>바이트 페어 인코딩(Byte Pair Encoding, BPE), WordPiece, SentencePiece</strong></li>
<li>효과: 의미 단어 잘 포착 가능, OOV 문제 완화, 어휘 집합 크기 문제 줄이기 가능</li>
</ul>
</li>
</ul>
</li>
<li><p><code>unhappiness</code> 토큰화 예시(위 토큰화 종류)</p>
<ul>
<li>단어(어절) 단위 토큰화: <code>&quot;unhappiness&quot;</code> 단어 전체를 하나의 토큰으로 취급</li>
<li>문자 단위 토큰화: <code>&quot;u&quot;, &quot;n&quot;, &quot;h&quot;, &quot;a&quot;, &quot;p&quot;, &quot;p&quot;, &quot;i&quot;, &quot;n&quot;, &quot;e&quot;, &quot;s&quot;, &quot;s&quot;</code></li>
<li>서브워드 단위 토큰화: <code>&quot;un&quot;, &quot;happi&quot;, &quot;ness&quot;</code></li>
</ul>
</li>
</ul>
<hr>
<h1 id="bpebyte-pair-encoding-바이트-페어-인코딩">BPE(Byte Pair Encoding, 바이트 페어 인코딩)</h1>
<h3 id="역사-및-정의">역사 및 정의</h3>
<ul>
<li>1994년 제안된 데이터 압축 알고리즘에서 시작.</li>
<li>가장 자주 등장하는 문자열 쌍을 점진적으로 병합 &amp; 새로운 기호(토큰)로 치환 -&gt; 사전 크기와 시퀀스 길이 균형 맞춤</li>
<li>NLP에서는 이 원리를 변형 -&gt; 자주 등장하는 글자/부분 문자열 합쳐 서브워드 단위 어휘집합 구축할 때 활용</li>
</ul>
<h3 id="예시">예시</h3>
<p>e.g, <code>abccbaaabcbcbaaa</code> </p>
<ul>
<li>가장 자주 등장한(4번)<code>aa</code>를 <code>Z</code>로 병합: <code>abccbZabcbcbZa</code></li>
<li>가장 자주 등장한(3번) <code>bc</code>와 <code>cb</code>중에 알파벳 순으로 <code>bc</code>를 <code>Y</code>로 병합: <code>aYcbZaYYbZa</code></li>
<li>가장 자주 등장한(2번) <code>aY</code>, <code>bZ</code>, <code>Za</code>중에 마찬가지로 알파벳 순으로 <code>aY</code>를 <code>X</code>로 병합: <code>XcbZXYbZa</code></li>
<li>가장 자주 등장한(2번) <code>bZ</code>를 <code>W</code>로 병합: <code>XcWXYWa</code></li>
</ul>
<p>=&gt; 결과적으로 어휘 집합 크기가 3개(<code>a, b, c</code>)에서 7개(<code>a, b, c, W, X, Y, Z</code>)로 늘어났지만 데이터 길이(시퀀스 실이)는 16에서 7로 줄었다.<strong>효율적</strong></p>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td><strong>장점</strong></td>
<td>- 새로운 단어(OOV)도 서브워드로 분해 가능<br>- 어휘 집합 크기를 원하는 만큼 조절 가능</td>
<td><em>unbelievableness</em> → <code>[&quot;un&quot;,&quot;believ&quot;,&quot;able&quot;,&quot;ness&quot;]</code></td>
</tr>
<tr>
<td><strong>단점</strong></td>
<td>- 의미 단위가 항상 깔끔하지 않음<br>- 초기 말뭉치 데이터에 따라 결과 달라짐</td>
<td><em>running</em> → 기대: <code>[&quot;run&quot;,&quot;ing&quot;]</code> 실제: <code>[&quot;runn&quot;,&quot;ing&quot;]</code></td>
</tr>
</tbody></table>
<h3 id="bpe-어휘-집합-구축">BPE 어휘 집합 구축</h3>
<ul>
<li><p>정의: 자주 등장하는 문자열 쌍 병합 -&gt; 새로운 서브워드 만들고 어휘집합에 추가(원하는 어휘 집합 크기가 될 때까지 반복)</p>
</li>
<li><p>구축 과정: </p>
<ul>
<li>step1.텍스트를 프리토크나이즈(pre-tokenize) (보통 공백 기준)</li>
<li>step2.모든 단어를 글자 단위로 분리</li>
<li>step3.자주 등장하는 바이그램(bigram, 연속된 두 글자) 쌍을 찾음</li>
<li>step4.그 쌍을 병합(merge)하여 새로운 토큰으로 추가</li>
<li>step5. 원하는 어휘집합 크기가 될 때까지 반복(집합 크기vocab size는 사람이 직접 정할 수 있음)</li>
</ul>
</li>
</ul>
<h3 id="bpe-토큰화">BPE 토큰화</h3>
<ul>
<li><p>정의: 위에서 구축된 BPE 어휘집합을 기준으로, 새로운 문장을 가장 긴 서브워드 단위로 분해하는 과정.</p>
</li>
<li><p>절차</p>
<ul>
<li>step1. 공백 단위로 프리토크나이즈</li>
<li>step2. 단어를 글자 단위로 쪼갠 후, BPE 병합 우선순위 적용</li>
<li>step3. 병합된 토큰이 어휘집합에 있는지 확인</li>
<li>step4. 더 이상 병합할 게 없으면 종료
(참고: 어휘집합에 없는 경우 <code>&lt;unk&gt;</code>로 처리)</li>
</ul>
</li>
</ul>
<h2 id="참고-워드피스wordpiece와-비교">(참고) 워드피스(WordPiece)와 비교</h2>
<ul>
<li><p>공통점: 자주 등장하는 문자열을 &#39;토큰&#39;으로 인식</p>
</li>
<li><p>차이점: </p>
<ul>
<li><p>어휘 구축 기준</p>
<ul>
<li>BPE: 단순 빈도 기반(가장 자주 등장한 쌍 병합)</li>
<li>WordPiece: 말뭉치의 우도(likelihood) 최대화 -&gt; 등장 확률 기반 </li>
</ul>
</li>
<li><p>(허깅페이스 tokenizers) 토큰화 수행 방식</p>
<ul>
<li>BPE: 병합 우선순위대로 반복해서 병합 후 최종 확인</li>
<li>WordPiece: 주어진 어휘 집합만 보고 가장 긴 매칭 서브워드 찾아 분리.</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>방식</th>
<th>토큰화 결과</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td><strong>BPE</strong></td>
<td><code>[&quot;un&quot;, &quot;happy&quot;, &quot;ness&quot;]</code></td>
<td>- 가장 <strong>자주 등장하는 문자열 쌍</strong>을 병합<br>- 규칙 단순, 빠르고 효율적</td>
</tr>
<tr>
<td><strong>WordPiece</strong></td>
<td><code>[&quot;un&quot;, &quot;happi&quot;, &quot;ness&quot;]</code></td>
<td>- <strong>문장 확률(likelihood)</strong>을 높이는 병합 선택<br>- 확률 계산을 통해 더 적절한 분리 가능</td>
</tr>
</tbody></table>
</li>
</ul>
<hr>
<h1 id="bpe-gpt--bert코드-코랩-실습">BPE GPT &amp; BERT코드 (코랩 실습)</h1>
<ul>
<li>코드 실습은 크게 세단계로 나뉜다. 1. 어휘집합 구축 -&gt; 2. 토큰화 -&gt; 3. 토크나이저</li>
</ul>
<h3 id="1-어휘집합-구축">1. 어휘집합 구축</h3>
<ul>
<li><p>목적: NSMC데이터로 GPT/BERT용 어휘집합 만들기</p>
</li>
<li><p>과정: </p>
<ul>
<li>Korpora 라이브러리 데이터 다운로드</li>
<li>BBPE 어휘집합 구축 -&gt; vocab.json, merges.txt 생성</li>
<li>Wordpiece 어휘집합 구축 -&gt; vocab.txt 생성</li>
<li>구글 드라이브에 저장</li>
</ul>
</li>
</ul>
<h3 id="2-토큰화">2. 토큰화</h3>
<ul>
<li>목적: 저장된 어휘집합 -&gt; 문장 모델 입력값 변환</li>
</ul>
<h3 id="3-토크나이저-프로세스">3. 토크나이저 프로세스</h3>
<ul>
<li><p>공통: 토크나이저 선언 -&gt; 문장 토큰화 -&gt; batch 입력 생성(padding, truncation, max_length 등)</p>
</li>
<li><p>3.1. GPT 토크나이저</p>
<ul>
<li>방식: BBPE(바이트 레벨)</li>
<li>출력: <code>input_ids</code>, <code>attention_mask</code></li>
</ul>
</li>
</ul>
<ul>
<li><p>3.2. BERT 토크나이저</p>
<ul>
<li>방식: WordPiece</li>
<li>출력: <code>input_ids</code>, <code>attention_mask</code>, <code>token_type_ids</code></li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NLP] 자연어 처리 기초 내용 정리(Do it! BERT와 GPT로 배우는 자연어 처리 1장을 읽고)]]></title>
            <link>https://velog.io/@sujikim-hattoo/NLP-%EC%9E%90%EC%97%B0%EC%96%B4-%EC%B2%98%EB%A6%AC-%EA%B8%B0%EC%B4%88-%EC%9A%A9%EC%96%B4-100%EC%84%A0-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@sujikim-hattoo/NLP-%EC%9E%90%EC%97%B0%EC%96%B4-%EC%B2%98%EB%A6%AC-%EA%B8%B0%EC%B4%88-%EC%9A%A9%EC%96%B4-100%EC%84%A0-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 01 Oct 2025 12:01:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 글은 Do it! BERT와 GPT로 배우는 자연어 처리: 트랜스포머 핵심 원리와 허깅페이스 패키지 활용법 &lt;1장 처음 만나는 자연어 처리&gt;를 읽고 공부하며 작성한 내용입니다.</p>
</blockquote>
<hr>
<h2 id="natural-language-processing">Natural Language Processing</h2>
<ul>
<li>정의: 사람이 사용하는 언어(자연어)를 컴퓨터가 이해하고 처리하도록 만드는 기술</li>
<li>활용: 번역기, 유튜브 자막, 챗봇, 검색 엔진 등</li>
</ul>
<p>여기서 중요한 질문
<strong>“컴퓨터가 언어를 이해한다는 것은 무엇을 의미할까?”</strong></p>
<hr>
<h2 id="computers-understand-human-languages">Computers understand human languages.</h2>
<ul>
<li>컴퓨터가 인간처럼 언어의 의미를 이해한다.(X)</li>
<li>컴퓨터는 입력된 문장을 계산을 통해 확률로 처리한다.(O)</li>
</ul>
<p>예를 들어 “나는 행복하다”라는 문장을 입력 -&gt; 모델은 이 문장이 <strong>긍정일 확률 0.9, 중립일 확률 0.1</strong>과 같은 식으로 출력. 즉, 이해라기보다는 확률 계산에 가까움.</p>
<hr>
<h2 id="nlp-model">NLP Model</h2>
<ul>
<li>정의: 특정 입력값(문장이나 문서 형태의 자연어)을 받아 해당 입력이 특정 범주에 속할 확률을 반환하는 함수.</li>
<li>예시: 감성 분석 모델 -&gt; 하나의 문장을 입력받아 긍정, 부정, 중립 범주에 속할 확률을 출력</li>
</ul>
<hr>
<h2 id="basic-terms-in-nlp-models">Basic terms in NLP Models</h2>
<p>자연어 처리 모델이 동작하기 위해서는 <strong>학습 과정</strong>이 필요</p>
<ul>
<li><strong>레이블(Label)</strong>: 학습 데이터의 정답. 예) “나는 행복하다” -&gt; &quot;긍정&quot; 라벨링(labeling)</li>
<li><strong>학습(Learn)</strong>: 모델이 데이터 패턴을 익히는 과정.</li>
<li><strong>업데이트(Update)</strong>: 모델이 예측한 값과 정답의 차이를 줄여가는 과정.</li>
<li><strong>트레인(Train)</strong>: 학습과 업데이트를 반복하는 전체 과정.</li>
<li><strong>후처리(Post-processing)</strong>: 모델이 출력한 확률값을 사람이 이해할 수 있는 언어(자연어)로 바꿔주는 단계.</li>
</ul>
<hr>
<h2 id="deep-learning-in-nlp">Deep Learning in NLP</h2>
<p>딥러닝: 인간의 뇌 구조를 본뜬 인공 신경망을 깊고 촘촘하게 쌓아 올려 -&gt; 모델이 데이터 패턴을 스스로 학습하도록 하는 방법</p>
<p>자연어 처리 분야에서는 특히 <strong>트랜스포머(Transformer) 기반 모델</strong>이 많이 쓰임. 
트랜스포머 모델 예시</p>
<ul>
<li><strong>BERT</strong>: 양방향 문맥을 이해. 빈칸 채우기 같은 태스크에 강함</li>
<li><strong>GPT</strong>: 순방향 문맥을 이해. 다음 단어 예측하기 같은 태스크에 강함. 문장 생성에 활용됨.</li>
</ul>
<hr>
<h2 id="transfer-learning-in-nlp">Transfer Learning in NLP</h2>
<p>자연어 처리 모델은 보통 <strong>트랜스퍼 러닝</strong> 방식 사용.</p>
<ul>
<li>트랜스퍼 러닝이란? 한 번 학습한 지식을 다른 과제에 재활용하는 기법</li>
</ul>
<h3 id="upstream-task-사전-학습">Upstream Task (사전 학습)</h3>
<ul>
<li><p>대규모 말뭉치로 문맥을 이해하게 만드는 기본 훈련 단계</p>
<ul>
<li>BERT 계열: 빈칸 채우기(마스크 언어 모델)</li>
<li>GPT 계열: 다음 단어 맞히기</li>
</ul>
</li>
</ul>
<h3 id="downstream-task-실제-활용">Downstream Task (실제 활용)</h3>
<ul>
<li><p>실생활 속 구체적인 과제들...</p>
<ul>
<li>문서 분류: 리뷰가 긍정/부정인지 판별</li>
<li>자연어 추론: 두 문장이 모순인지, 참인지, 중립인지 판별</li>
<li>개체명 인식: 문장에서 “서울”은 장소, “이순신”은 인물처럼 범주 구분</li>
<li>질의응답: 질문과 지문을 입력받아 정답 추출</li>
<li>문장 생성: 번역, 요약, 대화 생성 등</li>
</ul>
</li>
<li><p>다운스트림 태스크 수행 전략</p>
<ul>
<li><p><strong>파인튜닝(Fine-tuning)</strong>: 모델 전체를 새로운 데이터에 맞게 다시 학습</p>
</li>
<li><p><strong>프롬프트 튜닝(Prompt tuning)</strong>: 모델 일부만 업데이트</p>
</li>
<li><p><strong>인컨텍스트 러닝(In-context learning)</strong>: 모델을 업데이트하지 않고 예시만 제공</p>
<ul>
<li><p>제로샷: 예시 없이 수행</p>
</li>
<li><p>원샷: 예시 1개만 제공</p>
</li>
<li><p>퓨샷: 예시 몇 개 제공</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="7steps-how-nlp-models-learn">(7Steps) How NLP Models Learn</h2>
<p>자연어 처리 모델을 실제로 학습할 때는 다음과 같은 흐름을 따름</p>
<ol>
<li><strong>설정값 정의</strong>: 하이퍼파라미터, 러닝레이트, 배치 크기 등</li>
<li><strong>데이터 준비</strong>: 학습/평가용 데이터셋 다운로드</li>
<li><strong>사전 학습 모델 불러오기</strong>: 허깅페이스 트랜스포머 등</li>
<li><strong>토크나이저 준비</strong>: 문장을 토큰 단위로 변환</li>
<li><strong>데이터 로더 준비</strong>: 데이터를 배치 단위로 모델에 전달</li>
<li><strong>태스크 정의</strong>: 분류, 질의응답 등 목적에 맞는 태스크 지정</li>
<li><strong>모델 학습</strong>: 설정한 조건으로 트레이너를 통해 학습 수행</li>
</ol>
<p>위 과정을 요리에 비유하면 아래와 같다..</p>
<ol>
<li>설정값 정의 = 요리 레시피 정하기</li>
<li>데이터 준비 = 재료 사오기</li>
<li>사전 학습 모델 불러오기 = 반조리 식품 꺼내오기</li>
<li>토크나이저 준비 = 재료 손질하기</li>
<li>데이터 로더 준비 = 재료를 일정량씩 덜어내어 (배치 단위)한 접시씩 올려놓기</li>
<li>태스크 정의 = 요리 방식 결정하기</li>
<li>모델 학습 = 실제 요리하기 </li>
</ol>
<hr>
<h2 id="conclusion">Conclusion</h2>
<p>번역기, 챗봇, 추천 시스템, 그리고 계속해서 주목받고 있는 생성형 AI까지 모두 자연어 처리 모델 위에서 돌아가고 있다. </p>
<p>처음 공부할 때는 
큰 그림(업스트림 → 다운스트림)을 먼저 이해하고, 
그 안에서 세부 개념(BERT, GPT, 파인튜닝 등)을 차근차근 익히는 것이 중요해보인다.</p>
<p>기초는 이정도로 공부하고
앞으로 조금 더 심화 개념을 공부해보도록 한다..<del>!</del>!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[주식 차트 분석하며 단타 테크닉 정리하기 - 상따편(상한가 따라잡기)]]></title>
            <link>https://velog.io/@sujikim-hattoo/%EC%B0%A8%ED%8A%B8-%EB%B6%84%EC%84%9D%ED%95%98%EB%A9%B0-%EB%8B%A8%ED%83%80-%ED%85%8C%ED%81%AC%EB%8B%89-%EC%A0%95%EB%A6%AC%ED%95%98%EA%B8%B0-%EC%83%81%EB%94%B0%ED%8E%B8%EC%83%81%ED%95%9C%EA%B0%80-%EB%94%B0%EB%9D%BC%EC%9E%A1%EA%B8%B0</link>
            <guid>https://velog.io/@sujikim-hattoo/%EC%B0%A8%ED%8A%B8-%EB%B6%84%EC%84%9D%ED%95%98%EB%A9%B0-%EB%8B%A8%ED%83%80-%ED%85%8C%ED%81%AC%EB%8B%89-%EC%A0%95%EB%A6%AC%ED%95%98%EA%B8%B0-%EC%83%81%EB%94%B0%ED%8E%B8%EC%83%81%ED%95%9C%EA%B0%80-%EB%94%B0%EB%9D%BC%EC%9E%A1%EA%B8%B0</guid>
            <pubDate>Wed, 17 Sep 2025 10:03:26 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 글은 주식 투자를 처음 시작하며 공부한 내용을 정리한 것입니다. 내용에 오류가 있을 수 있으며, 특정 종목에 대한 투자 권유가 아닙니다. 모든 투자 판단과 결과에 대한 책임은 오직 본인에게 있으니, 충분한 학습과 분석을 통해 신중하게 투자하시기를 바랍니다. </p>
</blockquote>
<p>(아래 내용은 책 &lt;주식 단타로 매일매일 벌어봤어?&gt; 3장 &#39;단타 고수들의 트레이딩 테크닉&#39; 중 1) 상한가 따라잡기(상따) - 상한가 유형분석 (p.128~p.138)을 참고하여 작성되었습니다.)</p>
<h2 id="상한가-따라잡기란"><strong>상한가 따라잡기란?</strong></h2>
<p>한 종목 주가가 상승할 때, 당일 최고가를 의미. 이 상한가를 따라잡아 매수하는 것을 의미. </p>
<h2 id="상한가-따라잡기를-하는-이유는"><strong>상한가 따라잡기를 하는 이유는?</strong></h2>
<p>다음 날 장 시작할 때 시초가 갭상승과 추가적인 주가 상승을 노리는 것
.
.
.
상한가 따라잡기 유형에는 크게 4가지가 있다.</p>
<p>1) 장대 양봉
2) T자
3) 아래꼬리형
4) 점한상가</p>
<pre><code>*상한가에 진입했을 때 같이 매수하는 것이 일반적이나 최근에는 조금 더 일찍 매수하기도!
**상한가가 풀리는 경우가 자주 발생하며, 풀린 후에는 주가가 급락할 수 있다...
-&gt; 그래서 시간 외 거래 흐름까지 파악해야하는데 그럴 시간적 여유가 없는 직장인에게는 권장되지 않는 매매법이라고 한다..!</code></pre><hr>
<h1 id="1-장대양봉형">1. 장대양봉형</h1>
<h3 id="의미">의미</h3>
<p>시가 대비 종가가 크게 상승하여 몸통이 상하로 길~~게 나타나는 양봉 캔들을 의미</p>
<h3 id="차트-분석">차트 분석</h3>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/846bbace-3500-4468-950d-2d85d82afcdb/image.png" alt=""></p>
<p>-&gt; 2025/09/15(월) 농심 홀딩스는 12일 금요일 종가보다 낮은 시가로 출발했지만 장중 강한 매수세가 유입되어 당일 종하는 상한가(30.0%)로 마감되며 &#39;종가 상한가&#39;를 기록함.</p>
<h1 id="2-십자형도지형">2. 십자형(도지형)</h1>
<h3 id="의미-1">의미</h3>
<p>시가 &amp; 종가 거의 같은 패턴 -&gt; 캔들 몸통이 거의 없는 십자(十) 모양의 패턴</p>
<h3 id="차트-분석-1">차트 분석</h3>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/3d7f1187-561a-46bb-a303-e17a82884423/image.png" alt=""></p>
<p>탑코미디어는 2025/09/15(월) 일봉 차트에서 十자의 모습을 나타내므로 장중 큰 병동을 겪지만 시가와 종가가 거의 같은 가격으로 마감된 것을 볼 수 있다. 이렇게 장중 변동성이 큰 종목은 다음 날에도 변동성이 클 수 있다.(하락 추세 끝 or 상승 추세 중 -&gt; 상승 가능성 ㅇ / 상승 추세 끝 -&gt; 하락 가능성 ㅇ)</p>
<p>십자형 말고도 <strong>T자형</strong>이 있다.</p>
<ul>
<li>의미: 시가 &amp; 종가 &amp; 고가 모두 거의 같은 패턴(하락 추세 끝 -&gt; 망치형 캔들, 상승 가능성 ㅇ / 상승 추세 끝 -&gt; 교수형 캔들, 하락 가능성 ㅇ)</li>
</ul>
<h1 id="3-아래꼬리형">3. 아래꼬리형</h1>
<h3 id="의미-2">의미</h3>
<p>주가가 장 초반에 하락하나 강력한 매수세가 유입되어 상승 반전에 성공하는 패턴.</p>
<h3 id="차트-분석-2">차트 분석</h3>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/57c347e7-9e96-4608-b986-96d495e3a651/image.png" alt="">
흠... 사실 이 내용이 내가 책 내용을 잘못 이해하고 있는 건지 AI 검토 내용이랑 좀 다르게 나온다.</p>
<p>나는 n개월을 기준(지금 보면 8, 9월)으로 전체 추세가 긴 꼬리라고 생각했는데 AI(Gemini 2.5 Flash)는 당일 장중 분봉 데이터를 통해 확인하는 것이 가장 정확하다고 한다...일봉 차트로는 큰 그림을 확인하는 정도! 그러면 저 오른쪽 차크에서 09/17 09:00~09:30 까지봐도 아래꼬리형 패턴이 나타난다고 할 수 있겠다...!</p>
<p>어쨌든 큰 그림 먼저 살펴보면 빌리언스는 시가가 높게 시작했으나 주가가 하락하면서 점점 상승 추세를 보이고 있다.이렇게 시가가 높을 때는 추격 매수보다는 하락을 기다려 눌림을 공략하는 게 더 효과적이라고 한다. 오른쪽 차트를 보면 2025/09/16에도 상한가를 진입했지만 계속해서 지렁이 패턴이 만들어지면서 상한가가 계속 풀리는 모습이 보였다. 다음날 시가에서도 이 지렁이 패턴 계속 나타나지만 이후에는 고가가 크게 상승하고 있는 모습을 보이고 있다..!</p>
<ul>
<li>눌림목 매매란? 상승추세중인 주가에서 &#39;일시적&#39;으로 하락하는 구간노려 저점매수하는 전략. (상승중-일시적 하락-저점매수. 이때 잠시 하락하는 그 지점을 &#39;눌림목&#39;이라고 함. 상대적으로 낮은 가격에 진입 가능)(근데 일시적이 아닌 <em>추세 하락</em>의 시작일 수도...껄껄 </li>
<li><blockquote>
<p>이때 확인해야 할 것이 거래량이 급감하는지? 중요한 지지선을 이탈하는지? 
이런 경우를 위해 손절가 정해두어야) </p>
</blockquote>
</li>
</ul>
<h1 id="4-점상한가형">4. 점상한가형</h1>
<h3 id="의미-3">의미</h3>
<p>시가 &amp; 종가 &amp; 고가 &amp; 저가 모두 상한가로 형성. 
즉, 아침 9시(시가)부터 장 마감시간(종가)까지 한 번도 상한가를 이탈하지않고 종일 상한가를 유지하는 패턴(——— 이렇게 곧은 가로선 모양)</p>
<h3 id="차트-분석-3">차트 분석</h3>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/f7b45ae2-0c89-4acc-aca1-f9f1778fbfb5/image.png" alt="">
일봉 차트에서 캔들 위, 아래 꼬리가 전혀없다...! 완벽한 점상한가형.
이러한 종목은 다음 날에도 상승하는 가능성이 높아 최대한 보유하는 것이 좋다고 하는데....그런데.... 
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/b7ce8875-9987-4f9f-84d3-d54c80ede851/image.png" alt=""></p>
<p>(후후...역시나 매수 추세가 강해서 그런지 주문을 넣어도 체결이 쉽지 않은 상황 
-&gt; 약간 높은 가격으로 매수 정정을 해도 매수 체결이 안되어 결국 취소함...! = 진입하기 매우 어려운 패턴)</p>
<h1 id="캔들-분석의-위험과-의의">캔들 분석의 위험과 의의</h1>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/aaefb4b2-0c74-4062-953c-506a88e0a26c/image.png" alt="">
What people usually say...<em>&#39;캔들 분석, 추세, 차트만 보고 주식하는 것을 사람들이 <strong>위험</strong>해ㅐㅐ!!!</em> 라고 하는 것을 들어본 적이 있다...</p>
<p>그 이유를 당장 위 차트에서도 알 수 있다.
와이랩 종목 차트 곳곳에 T자형 캔들이 나타나지만, 어떤 경우에는 상승하고 어떤 경우에는 하락하는 등 전혀 다른 추세를 보인다. 즉 똑같은 모양의 캔들이라도 나타나는 위치나 시장 상황에 따라 의미가 충.분.히 달라질 수 있다는 뜻이다.</p>
<p>따라서 캔들 분석은 매매를 결정하는 <strong>수많은 근거 중 하나</strong>로 생각해야지 이것만을 유일한 근거로 삼고 매매하면... 
큰 손실을 초래할 수 있다....⊙﹏⊙∥</p>
<p>물론, 캔들 분석은 주식 투자를 처음 시작하는 (나같은) 주린이들에게는 정말 재밌고 쉽게 다가갈 수 있는 지표임은 분명하다 
(오오! 빨강!! 오오 T자!!!!) </p>
<blockquote>
<p>그러니 <strong>이 캔들 (일봉) 차트를 볼 때는 분봉 차트, 시장 시황, 기업 이슈등 다양한 매매 근거를 함께 분석하여 최적의 선택을 하는 것이 중요</strong>하다!!</p>
</blockquote>
<p>(난 앞으로 캔들 공부를 조금 더 해볼 것이다 껄껄 φ(゜▽゜*)♪)</p>
<hr>
<hr>
<p>참고:
양선호, 『주식 단타로 매일매일 벌어봤어? - 주린이를 위한 실전 단타 입문서』, 넥서스, 2022.
<a href="https://y-daily.tistory.com/16">주식 차트 보는 법 및 용어정리 1</a>
<a href="https://m.blog.naver.com/dnwnaka7/222623647252">주식 차트 보는 법 및 용어정리 2</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(ing) 비전공자인 내가 주식 자동 매매 프로그램을 만들기까지(2) - 첫 번째 매매 전략(이동평균선)]]></title>
            <link>https://velog.io/@sujikim-hattoo/ing-%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EC%9D%B8-%EB%82%B4%EA%B0%80-%EC%A3%BC%EC%8B%9D-%EC%9E%90%EB%8F%99-%EB%A7%A4%EB%A7%A4-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0%EA%B9%8C%EC%A7%802-%EC%B2%AB-%EB%B2%88%EC%A7%B8-%EB%A7%A4%EB%A7%A4-%EC%A0%84%EB%9E%B5%EC%9D%B4%EB%8F%99%ED%8F%89%EA%B7%A0%EC%84%A0</link>
            <guid>https://velog.io/@sujikim-hattoo/ing-%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EC%9D%B8-%EB%82%B4%EA%B0%80-%EC%A3%BC%EC%8B%9D-%EC%9E%90%EB%8F%99-%EB%A7%A4%EB%A7%A4-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0%EA%B9%8C%EC%A7%802-%EC%B2%AB-%EB%B2%88%EC%A7%B8-%EB%A7%A4%EB%A7%A4-%EC%A0%84%EB%9E%B5%EC%9D%B4%EB%8F%99%ED%8F%89%EA%B7%A0%EC%84%A0</guid>
            <pubDate>Sun, 14 Sep 2025 11:29:06 GMT</pubDate>
            <description><![CDATA[<p>이제 네트워크 흐름도 이해하고 API를 어떻게 호출하여 데이터를 어떻게 끌고 올지에 대해서도 공부를 마쳤다. 이제 정말 본격적으로 <strong>투자</strong>에 대해 배워볼 시간이다.</p>
<p>투자에서 제일 중요한 것은 시드머니(자본금)과 테크닉(전략)이라고 생각한다. 그 중에서도 &#39;이해&#39;하고 투자하는 것이 중요하니 이 테크닉(전략)의 중요성은 더 말하지 않아도 되겠다.</p>
<p>이 투자 전략을 세우고 나서 자동 매매 프로그램을 만들때 주요 프로세스는 아래와 같다.</p>
<pre><code>    전략 선택 -&gt; 전략 이해 및 코드 구현 -&gt; 백테스트</code></pre><p>여기서 백테스트는 실전에 투입되기 전 과거 데이터로 내가 구현한 전략이 얼마나 정확한지 테스트하는 것이다.
(마치 머신러닝에서 쓰이는 <code>val_data</code>처럼)</p>
<p>아래 글도 마찬가지로</p>
<ul>
<li>어떤 전략을 선택했는지</li>
<li>그 전략에 대한 이해와 코드로 어떻게 구현할 수 있는지</li>
<li>마지막으로 백테스트를 구현하는 것까지
자세하게 적어보았다.</li>
</ul>
<p>그럼 가 보 자 고 !</p>
<pre><code>두다다다다다다다
두다다다다다다다
　(∩`・ω・)  ~ ♪
＿/_ミつ/￣￣￣/
　　＼/＿＿＿/</code></pre><hr>
<hr>
<p>주식의 <strong>주요 투자 전략</strong>에는 아래와 같이 정말 다양하게 있다.</p>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/d4a70c39-f7de-49be-adf8-28a8c23bdb57/image.png" alt=""></p>
<p>-&gt; 이 중에서 초보자도 알기 쉽고 가장 많은 신뢰를 받는 지표이자 전략은 바로 <strong>이동 평균선</strong></p>
<blockquote>
<p>이동 평균선은 여러 가지 기술적 지표 중에서 가장 많은 사람들이 사용하는 것 중의 하나다.
— 양선호, 『주식 단타로 매일매일 벌어봤어?』, 넥서스, 2022, p.62</p>
</blockquote>
<p>이동 평균선의 장점</p>
<ul>
<li>단순함: 계산이 다른 전략에 비해 간단하고 직관적</li>
<li>시각화 용이: 글이아닌 차트로 보기 쉬움</li>
<li>구현 난이도: 코딩하기 쉬운 편에 속함</li>
</ul>
<p>나같은 초보가 첫 번째 투자전략으로 선택할 때는 <strong>이동평균선</strong>이 더할나위 없이 좋은 선택...!</p>
<hr>
<h1 id="1이동-평균선">1.이동 평균선</h1>
<h2 id="11-정의">1.1. 정의</h2>
<p>: Simple Moving Average(줄여서 SMA).이전 데이터로 평균을 내 추세를 통해 신호를 판단하는 후행성 지표. SMAn은 이전 n개의 값을 평균 낸 값을 그래프로 그린 것을 의미.(n이 클수록 전반적인 흐름을 알 수 있고, 작을수록 주가 그래프에 가까워진다.)</p>
<h3 id="기본-코드">기본 코드</h3>
<p>자 그러면 단기 변동성과 단기 추세 파악에 주로 사용되는 <code>SMA5</code>을 코드로 어떻게 나타낼 수 있을까?</p>
<p>일단 이전 글 파일 구조에 이어서 <code>strategies</code> 라는 이름의 디렉토리를 새로 만들어 그 안에 <code>moving_avg.py</code> 파이썬 파일을 만들어주었다.</p>
<pre><code>    AutomatedTrading/
├── access_token.txt 
├── auth.py                    # 토큰 발급 (공통)
├── market_data.py            # 데이터 수집 (공통)
├── strategies/
   ├── moving_average.py     # 이동평균선 전략</code></pre><p>*참고: 기간에 따른 대표적인 추세 전환 지표로는<code>SMA20</code>(중세) 그리고 <code>SMA60</code>과 <code>SMA120</code>(장기)이 활용된다.</p>
<h2 id="12-개념-이해">1.2. 개념 이해</h2>
<p>: 쉽게 이야기하면 상승 또는 하락 추세에서 현재 단기 이동평균선이 중장기 이동평균선과 비교해 어떠한 흐름을 띠고 어떻게 치고 내리는지 그 흐름에 따라 주식을 매수할 것인지 매도할 것인지 결정하는 것이다.</p>
<p> 보다 자세하게 이동평균선을 이해하고 싶으면 아래 링크에서 확인할 수 있다.
     - <a href="https://www.imfnsec.com/systemtrade/st02090602.jsp#:~:text=%EC%B6%94%EC%84%B8%EC%97%90%EC%84%9C%EB%8A%94%20%EB%8B%A4%EC%9D%8C%EA%B3%BC%20%EA%B0%99%EB%8B%A4.-,%EC%83%81%EC%8A%B9%20%EC%B6%94%EC%84%B8%EC%97%90%EC%84%9C%EC%9D%98%20%ED%88%AC%EC%9E%90%20%EC%A0%84%EB%9E%B5,-%EB%A7%A4%EC%9E%85%20%EC%8B%A0%ED%98%B8%0A%EB%8B%A8%EA%B8%B0">상승 추세에서의 투자 전략(iM증권)</a>
    - <a href="https://www.imfnsec.com/systemtrade/st02090602.jsp#:~:text=%EA%B2%83%EC%9D%B4%20%ED%98%84%EB%AA%85%ED%95%9C%20%ED%8C%90%EB%8B%A8%EC%9D%B4%EB%8B%A4.-,%ED%95%98%EB%9D%BD%20%EC%B6%94%EC%84%B8%EC%97%90%EC%84%9C%EC%9D%98%20%ED%88%AC%EC%9E%90%20%EC%A0%84%EB%9E%B5,-%EB%A7%A4%EB%8F%84%20%EC%8B%A0%ED%98%B8%0A%EB%8B%A8%EA%B8%B0">하락 추세에서의 투자 전략(iM증권)</a></p>
<h3 id="중요-용어">중요 용어</h3>
<p> : 전반적인 추세와 단기 이동평균선이 중장기 이동평균선을 어떻게 치고 올라가는지(내려가는지)도 중요한데 특히 추세 신호의 전환을 파악하는데 폭넓게 사용되고 있는 개념이 바로 <strong>골든 크로스 &amp; 데드 크로스</strong> 이다.</p>
<ul>
<li><p>⬆️ 골든 크로스: 강세 전환. 단기 이동 평균선이 장기 이동 평균선을 아래에서 위로 급속하게 뚫고 올라가는 상황. 
실전일 때는 욕심부리다가 꼭대기 놓칠 수 있으니 슬슬 매도 준비해야 함.</p>
</li>
<li><p>⬇️ 데드 크로스: 약세 전환. 단기 이동 평균선이 장기 이동 평균선을 위에서 아래로 급속하게 뚫고 올라가는 상황. </p>
<blockquote>
<p>Q. 골든 크로스는 상승 추세를 의미하니 매수를 해야하고 데드 크로스는 하락 추세를 의미하니 매도를 해야하는 게 맞나요?
A. 그것이 기본원리지만 이동평균선은 <strong>후행성 지표</strong>인 만큼 이미 신호가 늦은 것일 수도 있다. 따라서 한 박자 빠르게 생각하고 활용하는 것 또한 필요하다. 자세한 내용은 아래 표를 참고하자.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/b062176c-0c74-4cef-bc0e-f2734b78007f/image.png" alt=""></p>
<p>=&gt; 결론적으로 둘 다 맞는 전략이다. 트레이더의 성향과 목적에 따라 선택하곤 한다. 단 이번 글은 자동 매매 프로그램의 <em>기초를 다지는 단계</em>이기 때문에 <code>상승 추세일 때는 매수 &amp; 하락 추세 일때는 매도</code> 이 기본 로직으로 프로그램을 만들어본다.</p>
</li>
</ul>
<h2 id="13-코드-구현">1.3. 코드 구현</h2>
<p>: 정말 이 매매 전략이 천차만별이다. 나는 전략의 기준도 잘 모르기에 코드잇 강의에 적힌 의사코드(pseudo code)를 참고해 프로그램을 작성해보기로 했다.</p>
<h3 id="131-초기-구현과-문제점-파악">1.3.1 초기 구현과 문제점 파악</h3>
<p><strong>&lt;초기 계획&gt;</strong></p>
<ul>
<li>sma5(단기), sma20(중기), sma60(장기)로 나누어 각 기간별 가격 데이터 리스트 생성</li>
<li>리스트 비교를 통한 매매 신호 생성 (단기 vs 중기, 중기 vs 장기, 단기 vs 장기)</li>
</ul>
<p><strong>&lt;발견된 문제점들&gt;</strong></p>
<ul>
<li>투자/경제 개념 측면<ul>
<li>분봉 데이터 활용 시 SMA5 = 최근 5개 분봉 평균 (5일이 아님)</li>
<li>스캘핑 vs 데이트레이딩 개념 혼동</li>
<li>모의투자 API에서 일봉 데이터 미지원</li>
</ul>
</li>
<li>코드 구조 측면<ul>
<li>market_data.py 변수 미정의 상태에서 참조 시도</li>
<li>API 문자열 데이터의 숫자 변환 누락</li>
<li>candles[:20]으로는 SMA60 계산 불가</li>
<li>매매 신호 생성 로직 미숙</li>
</ul>
</li>
</ul>
<h3 id="132-문제-해결-과정">1.3.2 문제 해결 과정</h3>
<ul>
<li><p>데이터 연동 및 타입 변환 문제</p>
<pre><code>내용: 과거 가격 데이터로 이동평균 계산하는데 일일이 코드를 지정해야함 
분석: 과거 가격 데이터를 리스트로 만들어 moving_average.py로 넘기는 코드 누락
해결: market_data.py에 strategies용 함수(get_historical_prices)를 만들어 API 문자열 데이터를 숫자로 변환 후 넘겨주기 가능</code></pre></li>
<li><p>SMA 단일 지표 한계</p>
<pre><code>내용: SMA만으로는 급격한 가격 변동에 늦은 반응, 단조로운 신호 생성
분석: 단순이동평균은 모든 데이터에 동일 가중치 부여로 최신 변화 반영 지연
해결: EMA(지수이동평균) 추가 구현으로 최신 데이터에 높은 가중치 부여, SMA/EMA 선택 가능한 통합 함수 개발</code></pre></li>
<li><p>파라미터 관리 및 확장성 관련</p>
<pre><code>내용: 스캘핑/데이트레이딩 구분 없이 하드코딩된 설정, 모의투자 API 제약사항 미반영
분석: 시간 프레임별 전략 차이 고려 부족, 일봉 데이터 미지원으로 데이트레이딩 테스트 불가
해결: config.py 생성으로 전략별 설정 분리, 사용 불가능한 기능은 available: False로 표시하여 향후 확장 대비</code></pre></li>
</ul>
<h3 id="133-최종-구현-결과">1.3.3 최종 구현 결과</h3>
<p>핵심 개선사항:</p>
<p>EMA 구현으로 급격한 가격 변동 대응력 향상
모듈화를 통한 코드 재사용성 확보
설정 파일 분리로 전략 관리 체계화
if <strong>name</strong> == &quot;<strong>main</strong>&quot; 패턴으로 직접 실행/import 구분</p>
<p>최종 파일 구조:
AutomatedTrading/
├── config.py              # 전략별 설정 관리
├── market_data.py         # 데이터 수집 (공통)
├── strategies/
    └── moving_average.py  # SMA/EMA 통합 전략
이렇게 문제 발견 → 분석 → 해결 과정을 순서대로 정리하면 단순한 코드 나열이 아닌 문제 해결 능력을 보여주는 기술 블로그가 됩니다.</p>
<h2 id="14-백테스트">1.4. 백테스트</h2>
<ul>
<li><strong>백테스트</strong>란? 과거 데이터로 매매 전략을 &#39;시뮬레이션&#39;하는 것</li>
<li><strong>백테스트 흐름</strong>: 과거 데이터 -&gt; 매매 신호 생성 -&gt; 가상 거래 =&gt; 수익률 계산</li>
</ul>
<h3 id="141-백테스트-문제-해결-과정">1.4.1 백테스트 문제 해결 과정</h3>
<ul>
<li><p>파일 경로 및 모듈 import 이슈</p>
<pre><code>내용: strategies 폴더 내 파일에서 상위 디렉토리 토큰 파일 접근 불가
분석: 실행 위치에 따른 상대경로 차이로 FileNotFoundError 발생  
해결: os.path.join(&#39;..&#39;, &#39;access_token.txt&#39;) 및 동적 경로 설정 구현</code></pre></li>
<li><p>API 연속 조회 무한루프 위험</p>
<pre><code>내용: 데이터 수집 중 프로그램 응답 없음
분석: 30개 제한 API에서 연속 조회 시 종료 조건 부족
해결: max_requests 제한과 디버깅 메시지 추가로 안전장치 구현</code></pre></li>
<li><p>횡보장에서의 의미없는 신호</p>
<pre><code>내용: 모든 이동평균값이 동일하여 HOLD 신호만 발생
분석: 장마감 시간대 데이터로 주가 변동성 부족
해결: 매개변수 조정(3, 8)</code></pre></li>
</ul>
<h3 id="142-백테스트-최종-구조">1.4.2. 백테스트 최종 구조</h3>
<pre><code>&quot;&quot;&quot;
백테스트란?
정의: 과거 데이터로 매매 전략을 &#39;시뮬레이션&#39;하는 것
흐름: 과거 데이터 -&gt; 매매 신호 생성 -&gt; 가상 거래 =&gt; 수익률 계산

&lt;주요 함수별 역할&gt;
backtest_strategy()
- 초기 자금 100만원, 신호마다 execute_trade() 호출, 거래기록 trades 리스트에 저장 후 최종 자산 &amp; 수익률 계산
execute_trade()
- BUY: 현금으로 주식 최대한 매수
- SELL: 보유 주식 전량 매도
- HOLD: 아무것도 안함
calculate_performance()
- 거래 기록 분석 -&gt; 성과지표 계산(승률, 손익비, 총 손익, 최대 연속 손실)
calculate_max_consecutive_loss():
- 연속 손실 계산
&quot;&quot;&quot;


from strategies.moving_average import generate_signals
from market_data import get_historical_prices

def backtest_strategy(initial_money, signals):
    &quot;&quot;&quot;

    :param initial_money: 초기 자금
    :param signals: moving_average.py에서 나온 매매 신호들
    :return: 최종 자산, 수익률, 거래내역

    매매 신호 받아 수익률 계산하는 메인 함수
    &quot;&quot;&quot;
   ...

def execute_trade(signal, current_cash, current_stocks, stock_price):
    &quot;&quot;&quot;
    개별 거래 실행 함수(매수/매도)
    :param signal: BUY -&gt; 현금으로 주식 최대한 매수, SELL -&gt; 보유 주식 전량 매도
    :param current_cash:
    :param current_stocks:
    :param stock_price:
    :return:
    &quot;&quot;&quot;
  ...

def calculate_performance(trades):
    &quot;&quot;&quot;
    거래 결과 성과 분석
    :param trades: 총 수익률, 승률(=이익 거래 / 전체 거래), 손익비(=평균 이익 / 평균 손실), 최대 손실(연속 손실의 최대값)
    :return:
    &quot;&quot;&quot;
 ...


def calculate_max_consecutive_loss(profits):
    &quot;&quot;&quot;최대 연속 손실 계산&quot;&quot;&quot;


if __name__ == &quot;__main__&quot;:
    # 삼성전자(005930) 데이터로 테스트 -&gt; 변동성 작아 SK하이닉스(000660)로 교체
    stock_code = &quot;000660&quot;
    prices = get_historical_prices(stock_code, &quot;minute&quot;, 100)

    print(f&quot;전체 가격 데이터: {prices}&quot;)
    print(f&quot;가격 변동 범위: {min(prices)} ~ {max(prices)}&quot;)

    if prices:
        print(f&quot;수집된 데이터 개수: {len(prices)}&quot;)  # 추가
        print(f&quot;첫 5개 가격: {prices[:5]}&quot;)  # 추가

        # SMA 백테스트
        print(&quot;=== SMA 백테스트 ===&quot;)
        sma_signals = generate_signals(prices, &quot;SMA&quot;, 3, 8)  # 더 민감하게

        print(f&quot;생성된 SMA 신호 개수: {len(sma_signals) if sma_signals else 0}&quot;)  # 추가
        if sma_signals:
            print(f&quot;첫 3개 신호: {sma_signals[:3]}&quot;)  # 추가
            print(f&quot;전체 SMA 신호들:&quot;)
            for i, signal in enumerate(sma_signals):
                print(f&quot;{i + 1}: {signal[&#39;signal&#39;]} - SMA3: {signal[&#39;SMA3&#39;]:.1f}, SMA8: {signal[&#39;SMA8&#39;]:.1f}&quot;)

        if sma_signals:
            final_value, return_rate, trades = backtest_strategy(1000000, sma_signals)
            performance = calculate_performance(trades)

            print(f&quot;최종 자산: {final_value:,}원&quot;)
            print(f&quot;수익률: {return_rate:.2f}%&quot;)
            print(f&quot;성과: {performance}&quot;)

        # EMA 백테스트
        print(&quot;\n=== EMA 백테스트 ===&quot;)
        ema_signals = generate_signals(prices, &quot;EMA&quot;, 3, 8)

        if ema_signals:
            final_value, return_rate, trades = backtest_strategy(1000000, ema_signals)
            performance = calculate_performance(trades)

            print(f&quot;최종 자산: {final_value:,}원&quot;)
            print(f&quot;수익률: {return_rate:.2f}%&quot;)
            print(f&quot;성과: {performance}&quot;)
    else:
        print(&quot;데이터 수집 실패&quot;)

</code></pre><h2 id="15-시각화">1.5. 시각화</h2>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/3b48e134-1b09-4edb-9d2d-52a16e8bbbb8/image.png" alt=""></p>
<p>현재 SMA 3 vs 8 전략으로 삼성전자 데이터 분석 결과:</p>
<ul>
<li>주가 패턴: 횡보 후 상승, 일시 하락, 재상승</li>
<li>신호 발생: 18번째 지점 SELL(데드크로스), 29번째 지점 BUY(골든크로스)</li>
<li>전략 한계: 후행성으로 인한 늦은 신호 발생 (최저점에서 매도, 상승 후 매수)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[비전공자인 내가 주식 자동 매매 프로그램을 만들기까지(2) - 제작 준비(2)(한국투자증권 API)]]></title>
            <link>https://velog.io/@sujikim-hattoo/%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EC%9D%B8-%EB%82%B4%EA%B0%80-%EC%A3%BC%EC%8B%9D-%EC%9E%90%EB%8F%99-%EB%A7%A4%EB%A7%A4-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0%EA%B9%8C%EC%A7%802-%EC%A0%9C%EC%9E%91-%EC%A4%80%EB%B9%842%ED%95%9C%EA%B5%AD%ED%88%AC%EC%9E%90%EC%A6%9D%EA%B6%8C-API</link>
            <guid>https://velog.io/@sujikim-hattoo/%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EC%9D%B8-%EB%82%B4%EA%B0%80-%EC%A3%BC%EC%8B%9D-%EC%9E%90%EB%8F%99-%EB%A7%A4%EB%A7%A4-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0%EA%B9%8C%EC%A7%802-%EC%A0%9C%EC%9E%91-%EC%A4%80%EB%B9%842%ED%95%9C%EA%B5%AD%ED%88%AC%EC%9E%90%EC%A6%9D%EA%B6%8C-API</guid>
            <pubDate>Fri, 05 Sep 2025 14:58:10 GMT</pubDate>
            <description><![CDATA[<p>이번 글에서는
<strong>1. (무작정) 한국투자증권 API 코드 예제
2. API 개념 설명
3. API 흐름(실제 한국투자증권 API 코드 구현)</strong>
순으로 공부를 해볼 것이다...!</p>
<p>왜 코드 예제를 무작정 먼저 하냐면, 
코드를 먼저 보고 나면 이 API를 활용한 주식 자동 매매 프로그램의 전체적인 숲을 먼저 볼 수 있기 때문이다.</p>
<p>어려워보여도 괜찮다! 
어차피 실제 구현은 <strong>3. API 흐름</strong>에서 제대로 할 것이고, 
지금은 그냥 한 줄씩 <em>&#39;아하 이때는 이런 코드가 쓰이는구나~&#39;</em>하고 가볍게 읽고 넘어가도 좋다. (●ˇ∀ˇ●)bb</p>
<p>그럼 이제 가보자고!!!</p>
<hr>
<hr>
<h1 id="1-무작정-한국투자증권-api-코드-예제"><strong>1. (무작정) 한국투자증권 API 코드 예제</strong></h1>
<p>자, 이제 한국투자증권의 API를 받아오는 기본 코드를 한번 작성해보자! </p>
<p>이전 글에서 공부한 대로
<code>기본 설정 &gt; REQUESTS &gt; RESPONSE</code> 순으로 코드를 적어보자.</p>
<pre><code>&lt;상황&gt;
: 삼성전자 주가 데이터를 조회(GET)해서 10주를 매수해보는 것으로(POST)</code></pre><h2 id="기본설정">기본설정</h2>
<p>: HTTPS 통신의 기본인 <code>requests</code>를 불러오고 
수많은 클라이언트 중에 &#39;나&#39;를 구별할 수 있는<code>key</code>,<code>secret</code>, <code>token</code> 등도 정의한다.</p>
<pre><code>import requests

# 한국투자증권 API 기본 설정
BASE_URL = &quot;https://openapi.koreainvestment.com:9443&quot;
app_key = &quot;YOUR_APP_KEY&quot;
app_secret = &quot;YOUR_APP_SECRET&quot;
access_token = &quot;YOUR_ACCESS_TOKEN&quot;</code></pre><blockquote>
<p>Q1. key vs secret vs token 차이
A1. key로 기본 신원을 확인하고 secret으로 본인이 진짜 맞는지 확인하고 본인이 맞으면 실제 API 사용 권한인 token을 받는다.</p>
</blockquote>
<blockquote>
<p>Q2. <code>URL</code>에서 <code>9443</code>의 의미는?
A2. 포트 번호를 의미. 포트 번호란 한 서버 컴퓨터에서 서비스를 구분하는 번호로 아파트의 &#39;호수&#39;같은 개념. <code>29443</code>은 모의 투자 포트 번호를 의미. 참고로 알고있으면 좋은 포트 번호들은 아래에!</p>
</blockquote>
<ul>
<li>80: HTTP웹사이트(기본값)</li>
<li>443: HTTPS 웹사이트(기본값)</li>
<li>3306: MySQL 데이터베이스</li>
<li>8080: 개발용 웹서버</li>
</ul>
<h2 id="request">REQUEST</h2>
<p>: REQUEST에는 크게 GET 요청과 POST요청이 있다. 
이 프로젝트에서 GET 요청은 주가나 잔고 등의 데이터를 조회할 때 필요하며 POST 요청은 매수/매도 주문 등의 데이터를 보낼 때 필요하다. 
각 메소드 별로 <code>RESPONSE</code>도 같이 적어본다.</p>
<h3 id="get">GET</h3>
<p>먼저 <code>GET</code>부터 작성해보자</p>
<pre><code># GET: 삼성전자주가 조회
# try: 조회 시도해보는데 except Exception as e: 에러가 나오는 경우도 예외처리 해줘야 함

try:
    # 현재 주가 조회 API 엔드포인트
    price_url = f&quot;{BASE_URL}/uapi/domestic-stock/v1/quotations/inquire-price&quot;  

    # 쿼리 파라미터(삼성전자: 005930)
    params = {
        &quot;fid_cond_mrkt_div_code&quot;: &quot;J&quot;,  # 시장 구분 (J: 주식)
        &quot;fid_input_iscd&quot;: &quot;005930&quot;  # 종목코드(삼성전자)  
   }

   # GET 요청: 서버에서 주가 데이터 가져오기
   # res는 서버의 응답을 의미
   res = requests.get(price_url, headers=headers, params=params)

   # 응답 상태 확인
   if res.status_code == 200:  # 왜 200이야??
       data = res.json()
    current_price = data[&#39;output&#39;][&#39;stck_prpr&#39;]  # 현재가
    change_rate = data[&#39;output&#39;][&#39;prdy_ctrt&#39;]  # 전일대비 등락률
    print(f&quot;삼성전자 현재가: {current_price}원&quot;)
    print(f&quot;전일대비: {change_rate} %&quot;)
  else:
      print(f&quot;주가 조회 실패: {res.status_code}&quot;)

except Exception as e:
    print(f&quot;주가 조회 에러: {e}&quot;)
</code></pre><blockquote>
<p>Q1. <code>price_url</code>에서 엔드포인트란?
A1. 엔드포인트란 <code>server</code>에서 특정 기능을 담당하는 주소를 의미. <code>/quotations/inquire-price</code>는 주가를 조회해주는 곳을 의미</p>
</blockquote>
<blockquote>
<p>Q2. 쿼리 파라미터에서 <code>J</code>란? 
A2. 한국투자증권에서 임의로 정한 코드이다.
    - J: 주식(JSTOCK)
    - F: 선물(FUTURES)
    - O: 옵션(OPTIONS)</p>
</blockquote>
<blockquote>
<p>Q3. 쿼리 파라미터에서 <code>fid</code>와 <code>isce</code>의 의미?
A3. 한국투자증권 API에서 사용하는 약어
    - FID: Field ID(어떤 필드인지 구분)
    - ISCD: Issue Code(종목 코드 의미)</p>
</blockquote>
<blockquote>
<p>Q4. <code>res.status_code</code>가 200인 이유
A4. HTTP 상태를 나타내는 국제 표준 코드
    - 200 = OK(성공)
    - 404 = Not Found(페이지 없음)
    - 500 = Server Error(서버 오류)</p>
</blockquote>
<h3 id="post">POST</h3>
<p>그리고 이제 <code>POST</code> 요청도 작성해보자</p>
<pre><code># POST: 삼성전자 매수 주문
# GET과 마찬가지로 try-except으로 구성
try:
    # 매수 주문 API 엔드포인트
    # 엔드포인트란? 
    order_url = f&quot;{BASE_URL}/uapi/domestic-stock/v1/trading/order-cash&quot;

    # POST 요청용 헤더(거래 ID 추가)
    order_headers = headers.copy()
    order_headers[&quot;tr_id&quot;] = &quot;VTTC0802U&quot;  # 매수 거래 ID

    # 주문 데이터(JSON 바디 내용)
    order_data = {
        &quot;CANO&quot;: &quot;계좌번호 앞 8자리&quot;
        &quot;ACNT_PRDT_CD&quot;: &quot;01&quot;,  # 계좌상품코드
        &quot;PDNO&quot;: &quot;005930&quot;,  # 삼성전자 종목코드
        &quot;ORD_DVSN&quot;: &quot;01&quot;,  # 주문구분(01: 시장가)
        &quot;ORD_QTY&quot;: &quot;10&quot;,  # 주문수량 10주
        &quot;ORD_UNPR&quot;: &quot;0&quot;  # 주문단가(시장가이므로 0)
    }

   # POST 요청: 서버에 매수 주문 데이터 보내기
   res = requests.post(order_url, headers=order_headers, json=order_data)

  # 응답 상태 확인
  if res.status_code == 200:
      data = res.json()
    # rt_cd: 한국투자증권 API 결과코드
    if data[&#39;rt_cd&#39;] == &#39;0&#39;:  # 성공
        order_no = data[&#39;output&#39;][&#39;ODNO&#39;]
        print(f&quot;매수 주문 성공!&quot;)
        print(f&quot;주문번호: {order_no}&quot;)
        print(f&quot;삼성전자 10주 시장가 매수 주문 완료&quot;)
   else:
           print(f&quot;주문 실패: {data[&#39;msg1&#39;]}&quot;)
 else:
    print(f&quot;주문 요청 실패: {res.status_code}&quot;)
except Exception as e:
    print(f&quot;매수 주문 에러: {e}&quot;)
</code></pre><blockquote>
<p>Q1. <code>ORD_DVSN</code>이 <code>01</code>인 이유
A1. 한국투자증권 API 주문 구분 코드이다.
    - 01: 시장가(현재 시세로 즉시 거래)
    - 02: 지정가(내가 원하는 가격으로 주문)
    - 03: 조건부 지정가
    - 05: 장전 시간외</p>
</blockquote>
<blockquote>
<p>Q2. <code>ORD_UNPR</code>이 0인 이유
 A2. 시장가는 지금 시세가 얼마든 상관없이 &#39;즉시&#39; 사는 것이기에 지정가와 달리 가격을 지정하지 않는다. 따라서 0을 입력한다.</p>
</blockquote>
<hr>
<h1 id="2-api-개념"><strong>2. API 개념</strong></h1>
<p>이렇게 우리는 어떻게 한국투자증권 API를 이용해 삼성전자 주가를 조회하고 매수까지 할지에 대해 전체 코드 흐름을 간단하게 알아보았다. 
숲을 살펴보았으니 이제 이 API라는 나무에 대해 본격적으로 알아볼 시간!</p>
<h2 id="api-개념">API 개념</h2>
<p>API는
<em>Application Programming Interface</em>의 약자로, 프로그램들의 접점이 되는 것을 의미한다. 
예를 들어 여행 블로그 서비스를 출시하고 싶은데 지도를 구현하는 것이 힘드니까 Google Maps API를 쓰는 것이 나의 여행블로그 서비스와 Google Maps 간의 접점을 만드는 것이다.</p>
<h2 id="한국투자증권-api">한국투자증권 API</h2>
<h3 id="api-문서">API 문서</h3>
<p>이 API를 어떻게 활용할 수 있는지에 대해서는 파이썬 DOCS와 마찬가지로 API 문서에서 확인할 수 있다. 
<a href="https://apiportal.koreainvestment.com/apiservice-summary">한국투자증권의 API문서</a>를 확인해보니</p>
<ul>
<li>시세 조회 -&gt; <code>GET</code> </li>
<li>주문 -&gt; <code>POST</code></li>
<li>잔고 조회 및 체결 내역 조회 -&gt; <code>GET</code> 방식으로 진행하는 것을 볼 수 있다.</li>
</ul>
<hr>
<h1 id="3-api-흐름"><strong>3. API 흐름</strong></h1>
<p>그러면 이 API를 실제로 어떻게 사용할 수 있는지에 대해서는 일종의 작업이 필요하다. 자세한 내용은 아래와 같다.</p>
<ul>
<li><strong>step1. 계좌 개설</strong></li>
<li><strong>step2. 개발자로 등록</strong></li>
<li><strong>step3. <code>Access Token</code> 발급</strong></li>
<li><strong>step4. 코드로 API <code>REQUEST</code> 보내기</strong></li>
</ul>
<p>자, 이제 단계별로 살펴보자.</p>
<h2 id="step1-계좌-개설">Step1. 계좌 개설</h2>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/a3696d1f-b1c0-4040-abac-3c34f8f975ef/image.png" alt="">
모바일 앱으로 회원가입을 진행했다. 앱에서 추천하는 대로 <code>ISA + 국내/해외주식 + CMA</code> 계좌로 개설했다. 
개설하려니 계좌 종류도 선택하라고 해서
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/c2541069-5fe1-4384-b930-1611de369e08/image.png" alt="">
위 내용을 참고하여 필자는 투자 초보이므로 안전하게 <strong>RP형</strong>으로 선택 완료!(계좌종류는 API와 전혀 상관이 없다고 한다.)</p>
<p>일반 은행 계좌 개설과 달리 <strong>투자 계좌</strong>라서 그런지 위험성을 엄청 강조하고 그만큼 설문도 많아서 시간이 더 많이 드는 것 같았다.
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/c3281a6a-8574-4835-aa19-d0a1ae1a9489/image.png" alt="">
회원가입하고 로그인하고 계좌개설까지 다 마쳤는데 
알고 보니 1년 전에 가입해둔 계좌가 하나 있었다...처음이 아니었네 (머쓱🙄)</p>
<p><strong>자동 매매 연결 계좌</strong>는 실제 계좌 아니면 모의 투자 계좌로 설정 가능한데
자동 매매인 만큼 예기치 못한 리스크가 크고 투자 감각을 익히기 위해서 
모의 투자 계좌를 만들기로 했다. </p>
<p><code>트레이딩 탭 &gt; 모의투자 안내 &gt; 신청/재도전</code> 에서 <strong>모의 투자 계좌</strong>를 만들고 
이때 리그 구분은 <code>국내 주식 1000만원 + 해외주식</code>과 <code>선물옵션</code>을 선택하고 금액과 기간은 기존에 설정되어 있는대로 진행했다. </p>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/8734978f-bf27-47f6-ba96-128cc3746d92/image.png" alt="">
(모의투자 계좌 개설 완료!)</p>
<h2 id="step2-개발자로-등록">Step2. 개발자로 등록</h2>
<ul>
<li>목적: <code>app key</code>와 <code>app secret</code>을 발급받기 위함.</li>
</ul>
<p>드디어 개발자 등록 단계이다...!
<code>트레이딩 탭 &gt; OpenAPI &gt; KIS Developers &gt; KIS Developers 서비스 신청/조회</code>
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/86064652-85fe-4f8a-80a2-49df4c311a9b/image.png" alt="">
(나중에 실전 투자 계좌도 따로 추가할 수 있으니 일단 모의 투자 계좌만 신청)</p>
<p>엇.. 근데 아까 모의 투자 계좌를 3개 만들었었는데(<code>상시대회 국내주식</code>, <code>상시대회 해외주식</code>, <code>상시대회 선물옵션</code>)
해외 취업을 원하지만 일단 기초 감각을 키우고 국내에서 경력을 쌓아야 하기에 
<code>상시대회 국내주식</code> 모의 계좌로 API 신청했다.
(KIS 개발자 신청하는데 &#39;토큰이 존재하지 않습니다.&#39;라는 오류창이 떴다. 단순 오류였고 새로운 탭에서 신청하니까 잘 됐다.)</p>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/59662feb-ebe7-48b8-b781-b4a0b7d0476e/image.png" alt="">
개발자 신청 완료!</p>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/462444cd-4097-46a1-a235-50488df1ff7f/image.png" alt="">
<strong>[중요] 앱키와 시크릿키는 절대 유출 및 도용되지 않도록 주의해야한다!!!</strong></p>
<p>이제 Step3부터는 실제 한국 투자 증권의 API들을 불러올 것이다.</p>
<h2 id="step3-access-token-발급">Step3. <code>Access Token</code> 발급</h2>
<ul>
<li>목적: <code>app key</code>(앱키)와 <code>app secret</code>(시크릿키)을 제시하면 한국투자증권은 자사 API를 쓸 수 있는 하루용 <code>Access Token</code>을 발급해준다.</li>
</ul>
<p><a href="https://apiportal.koreainvestment.com/apiservice-apiservice?/oauth2/tokenP">API문서 중 접근토큰발급</a> 관련이다. 
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/7b2db980-492c-43c2-a058-0c52014ebcd1/image.png" alt="">
<code>기본 정보 - 요청(Header &amp; Body) - 응답(Header &amp; Body) - 예시</code>로 구성되어 있다. 
요청할 때 Body에서 <code>appkey</code>와 <code>appsecret</code>을 제시하면 
응답 Body에서 <code>access_token</code> 토큰과 관련된 정보들을 제공한다.
확실히 처음에 코드 예제로 먼저 살펴본 내용이라 낯익은 단어들이 많아 이해하기 쉽다...!♪(´▽｀)</p>
<h3 id="api의-기본-호출-구조">API의 기본 호출 구조</h3>
<pre><code>API 호출의 기본 구조:
1. requests 모듈 import
2. API를 불러오기 위한 기본 정보(BASE_URL, APPKEY, APPSECRET, ACCESS_TOKEN 등) 정리 =&gt;신원확인  
3. url 설정(실전 or 모의 Domain)
4. headers = 서버에게 알려주는 내용
5. body = 서버에게 알려줄 때 함께 보낼 데이터 내용
6. try-except = 오류 처리 (네트워크 문제, 서버 오류 등)후 결과 출력</code></pre><p>(참고: HTTP 메소드에는 <code>GET</code>, <code>POST</code>외에도 많지만 대부분의 증권 API 메소드가 <code>GET</code>, <code>POST</code> 위주라서 이 둘을 중심으로 정리한 내용)</p>
<p>위 내용을 참고해서 접근토큰발급 API 코드를 작성해보자. 
함수 형식으로 정리하는 게 접근성과 보편성이 좋다고 해서<code>def</code>함수 키워드를 이용해 적어볼 것이다.</p>
<p>전체적인 파일 구조는 이러하다</p>
<pre><code>AutomatedTrading/
├── auth.py
├── market_data.py
└── (auth.py 실행 후) access_token.txt  (토큰 문자열이 저장된 파일)</code></pre><p>처음에는 코드잇 예제 코드처럼 딕셔너리 구조로 간단하게 코드를 작성하려고 했지만
코드 안정성(예외처리)과 재사용성(여러 번 호출 될 수 있음) 측면에서 
<strong>함수로 정의하고 토큰은 파일로 저장</strong>하는 방식이 더 적합하다고 판단했다. 
(이 파일 저장방식이 실무에서도 많이 사용된다고 하기도 하고..!)</p>
<p>따라서 최종코드는 아래와 같다.</p>
<h4 id="authpy"><strong>&lt;<code>auth.py</code>&gt;</strong></h4>
<pre><code># 이 파일은 한국 투자증권 &#39;접근토큰발급&#39;을 어떻게 발급받는지에 대한 실제 코드이다.
# 파일 저장 방식으로 구성

import requests

# 한국투자증권 기본 설정
BASE_URL = &quot;https://openapivts.koreainvestment.com:29443&quot;  # 모의 투자 Domain
APPKEY = &quot;비밀1&quot;
APPSECRET = &quot;비밀2&quot;

# 접근 토큰을 발급받아 파일로 저장
def get_access_token():
    url = f&quot;{BASE_URL}/oauth2/tokenP&quot;

    headers = {&quot;Content-Type&quot;: &quot;application/json&quot;}
    body = {
        &quot;grant_type&quot;: &quot;client_credentials&quot;,
        &quot;appkey&quot;: APPKEY,
        &quot;appsecret&quot;: APPSECRET
    }

    try:
        res = requests.post(url, headers=headers, json=body)

        if res.status_code == 200:
            data = res.json()
            access_token = data.get(&#39;access_token&#39;)

            if access_token:
                # 토큰을 텍스트 파일로 저장
                with open(&#39;access_token.txt&#39;, &#39;w&#39;) as f:
                    f.write(access_token)

                print(f&quot;=== 토큰 발급 및 저장 성공 ===&quot;)
                print(f&quot;토큰: {access_token[:10]}...(이하 생략)&quot;)
                return access_token
            else:
                print(f&quot;=== 토큰 발급 실패: 응답에 토큰이 없음 ===&quot;)
                return None
        else:
            print(f&quot;=== 요청 실패: {res.status_code} ===&quot;)
            return None

    except Exception as e:
        print(f&quot;오류 발생: {e}&quot;)
        return None

# auth.py을 실행했을 때만 토큰 발급
if __name__ == &quot;__main__&quot;:
    get_access_token()</code></pre><p>(마지막 <code>if __name__ == &quot;__main__&quot;:</code> 코드에 대한 설명은 다음 Step4.에서 자세하게 다룬다.)</p>
<p>사실 여기서 한 발 더 나아가면 </p>
<ul>
<li><code>res.status_code</code>를 다양하게 나누어 예외처리를 하거나(e.g. <code>400: 요청 오류</code>, <code>401: 인증 실패</code> 등) </li>
<li><code>except</code>의 경우의 수를 다양하게 처리 해주는 게 더 나으나(e.g., <code>except requests.exceptions.Timeout: 요청시간 초과</code>, <code>except requests.exceptions.ConnectionError: 연결 오류</code> 등) </li>
</ul>
<p>지금은 최소한의 필수 코드만 구현하는 데 집중했다 :&gt;</p>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/d374280c-05cd-4268-8db7-57187288254f/image.png" alt=""></p>
<h2 id="step4-코드로-api-request-보내기">Step4. 코드로 API <code>REQUEST</code> 보내기</h2>
<ul>
<li>이제 API 문서에 적힌 내용대로 다양한 기능을 쓸 수 있다(e.g, 삼성 전자 현재가 데이터 받아오기, 잔고 조회, 주식 거래 내역 등)</li>
</ul>
<p>이번에 해볼 것은 <a href="https://apiportal.koreainvestment.com/apiservice-apiservice?/uapi/domestic-stock/v1/quotations/inquire-time-itemchartprice">[국내주식] 기본 시세 &gt; 주식당일분봉조회</a> 이다.</p>
<p>접근 토큰 발급 API 파일보다 내용이 훨씬 많지만 차근차근 작성해보자  (๑•̀ㅂ•́)و✧</p>
<p>코드 흐름은 다음과 같다.</p>
<pre><code>step1. def load_token(): 으로 access_token.txt에 저장된 토큰 불러오기 
step2. def get_stock_price(stock_code):로 주식당일 분봉 조회하기
step3. 전체 코드 실행</code></pre><h4 id="market_datapy"><strong>&lt;<code>market_data.py</code>&gt;</strong></h4>
<p>의 최종 코드는 두 버전으로 나누었다.</p>
<ul>
<li><strong>Clean ver.</strong>에는 코드를 이해하는 데 최소한의 주석만 남겨놓았고</li>
<li><strong>Full ver.</strong>에는 코드를 공부하면서 기록한 모든 주석 내용을 포함했다. </li>
</ul>
<ul>
<li>먼저 <strong>Clean ver.</strong><pre><code># 이 파일은 한국 투자증권 &#39;주식당일분봉조회&#39; API를 어떻게 발급받는지에 대한 코드이다.
# Method: GET
import requests
</code></pre></li>
</ul>
<h1 id="한국투자증권-기본-설정">한국투자증권 기본 설정</h1>
<p>BASE_URL = &quot;<a href="https://openapivts.koreainvestment.com:29443&quot;">https://openapivts.koreainvestment.com:29443&quot;</a>
APPKEY = &quot;비밀1&quot;
APPSECRET = &quot;비밀2&quot;</p>
<h1 id="저장된-토큰-파일-읽어오는-함수">저장된 토큰 파일 읽어오는 함수</h1>
<p>def load_token():
    print(&quot;토큰 읽어오는 중 ...&quot;)
    try:
        with open(&#39;access_token.txt&#39;, &#39;r&#39;) as f:
            token = f.read().strip()
        return token
    except FileNotFoundError:
        print(&quot;토큰 파일이 없습니다. auth.py 먼저 실행하세요!&quot;)
        return None
    except Exception as e:
        print(f&quot;토큰 읽기 오류: {e}&quot;)
        return None</p>
<h1 id="주식-분봉-데이터-조회하는-함수">주식 분봉 데이터 조회하는 함수</h1>
<p>def get_stock_price(stock_code):
    print(&quot;get_stock_price 함수 시작&quot;)</p>
<pre><code># 저장된 토큰 불러오기
access_token = load_token()
if not access_token:
    print(&quot;토큰 없어서 함수 종료~&quot;)
    return

print(&quot;저장된 토큰 확인 완료&quot;)
# 기본 정보 URL
url = f&quot;{BASE_URL}/uapi/domestic-stock/v1/quotations/inquire-time-itemchartprice&quot;

# REQUEST 부분
headers = {
    &quot;content-type&quot;: &quot;application/json; charset=utf-8&quot;,
    &quot;authorization&quot;: f&quot;Bearer {access_token}&quot;,
    &quot;appkey&quot;: APPKEY,
    &quot;appsecret&quot;: APPSECRET,
    &quot;tr_id&quot;: &quot;FHKST03010200&quot;,  
    &quot;custtype&quot;: &quot;P&quot; ,
}

params = {
    &quot;FID_COND_MRKT_DIV_CODE&quot;: &quot;J&quot;,
    &quot;FID_INPUT_ISCD&quot;: stock_code, 
    &quot;FID_INPUT_HOUR_1&quot;: &quot;100000&quot;, 
    &quot;FID_PW_DATA_INCU_YN&quot;: &quot;Y&quot;,  
    &quot;FID_ETC_CLS_CODE&quot;: &quot;00&quot; 
}

try:
    res = requests.get(url, headers=headers, params=params)
    # 응답 상태 확인
    if res.status_code == 200:
        print(f&quot;응답 상태 코드: {res.status_code}&quot;)
        data = res.json()

        # 응답 구조
        if data.get(&#39;rt_cd&#39;) == &#39;0&#39;:  # 한투 API 성공코드
            # output1: 종목 현재 상태(Object)
            stock_info = data.get(&#39;output1&#39;, {})
            stock_name = stock_info.get(&#39;hts_kor_isnm&#39;, &#39;N/A&#39;)  # 종목명
            current_price = stock_info.get(&#39;stck_prpr&#39;, &#39;N/A&#39;)  # 현재가
            current_rate = stock_info.get(&#39;prdy_ctrt&#39;, &#39;N/A&#39;)  # 등락률

            print(f&quot;=== {stock_name} 현재 정보 ===&quot;)
            print(f&quot;현재가: {current_price}원, 등락률: {current_rate}%&quot;)

            # output2: 분봉 데이터(Object Array)
            candles = data.get(&#39;output2&#39;, [])

            if candles:
                print(f&quot;=== {stock_name} 분봉 데이터 ===&quot;)
                for i, candle in enumerate(candles[:5]):
                    date = candle.get(&#39;stck_bsop_date&#39;, &#39;N/A&#39;)  # 주식 영업일자
                    time = candle.get(&#39;stck_cntg_hour&#39;, &#39;N/A&#39;)  # 주식 체결시간
                    price = candle.get(&#39;stck_prpr&#39;, &#39;N/A&#39;)  # 주식 현재가
                    volume = candle.get(&#39;cntg_vol&#39;, &#39;N/A&#39;)  # 체결 거래량
                    print(f&quot;{i+1}.{date}{time} - 가격: {price}원, 거래량: {volume}&quot;)
            else:
               print(&quot;분봉 데이터가 없습니다.&quot;)
        else:
           print(f&quot;API 오류: {data.get(&#39;msg1&#39;, &#39;알 수 없는 오류&#39;)}&quot;)
    else:  
       print(f&quot;HTTP 요청 실패: {res.status_code}&quot;)
       print(f&quot;에러 내용: {res.text}&quot;)

except Exception as e:  
   print(f&quot;요청 중 네트워크/코드 오류 발생: {e}&quot;)</code></pre><p>if <strong>name</strong> == &quot;<strong>main</strong>&quot;:
    print(&quot;프로그램 시작&quot;)
    get_stock_price(&quot;005930&quot;)
    print(&quot;프로그램 종료&quot;)</p>
<pre><code>- 그 다음 **Full ver.**</code></pre><h1 id="이-파일은-한국-투자증권-주식당일분봉조회-api를-어떻게-발급받는지에-대한-코드이다">이 파일은 한국 투자증권 &#39;주식당일분봉조회&#39; API를 어떻게 발급받는지에 대한 코드이다.</h1>
<h1 id="method-get">Method: GET</h1>
<p>import requests</p>
<h1 id="한국투자증권-기본-설정-1">한국투자증권 기본 설정</h1>
<p>BASE_URL = &quot;<a href="https://openapivts.koreainvestment.com:29443&quot;">https://openapivts.koreainvestment.com:29443&quot;</a>
APPKEY = &quot;비밀1&quot;
APPSECRET = &quot;비밀2&quot;</p>
<h1 id="저장된-토큰-파일-읽어오는-함수-1">저장된 토큰 파일 읽어오는 함수</h1>
<p>def load_token():
    print(&quot;토큰 읽어오는 중 ...&quot;)
    try:
        with open(&#39;access_token.txt&#39;, &#39;r&#39;) as f:
            token = f.read().strip()
        return token
    except FileNotFoundError:
        print(&quot;토큰 파일이 없습니다. auth.py 먼저 실행하세요!&quot;)
        return None
    except Exception as e:
        print(f&quot;토큰 읽기 오류: {e}&quot;)
        return None</p>
<h1 id="주식-분봉-데이터-조회하는-함수-1">주식 분봉 데이터 조회하는 함수</h1>
<p>def get_stock_price(stock_code):
    print(&quot;get_stock_price 함수 시작&quot;)</p>
<pre><code># 저장된 토큰 불러오기
access_token = load_token()
if not access_token:
    print(&quot;토큰 없어서 함수 종료~&quot;)
    return

print(&quot;저장된 토큰 확인 완료&quot;)
# 기본 정보 URL
url = f&quot;{BASE_URL}/uapi/domestic-stock/v1/quotations/inquire-time-itemchartprice&quot;

# REQUEST 부분
headers = {
    &quot;content-type&quot;: &quot;application/json; charset=utf-8&quot;,
    &quot;authorization&quot;: f&quot;Bearer {access_token}&quot;,
    &quot;appkey&quot;: APPKEY,
    &quot;appsecret&quot;: APPSECRET,
    # &quot;personalseckey&quot;: , # 선택사항 - 개인키 없으면 생략
    &quot;tr_id&quot;: &quot;FHKST03010200&quot;,  # transaction 거래 식별자_당일 분봉조회 API 고유코드
    # &quot;tr_cont&quot;: , # 연속조회 - 처음엔 공백
    &quot;custtype&quot;: &quot;P&quot; ,
    # 아래 항목들은 모의 투자에서 보통 생략 가능
    # &quot;seq_no&quot;: ,
    # &quot;mac_address&quot;: ,
    # &quot;phone_number&quot;: ,
    # &quot;ip_addr&quot;:,
    # &quot;gt_uid&quot;
}

# GET 요청에서는 POST와 달리 데이터를 URL의 쿼리 파라미터로 전송
params = {
    &quot;FID_COND_MRKT_DIV_CODE&quot;: &quot;J&quot;,  # Field ID 국내주식
    &quot;FID_INPUT_ISCD&quot;: stock_code, # Issue Code 종목코드
    &quot;FID_INPUT_HOUR_1&quot;: &quot;100000&quot;, # 조회할 시간(HHMMSS): 9시 1분~10시 00분까지
    &quot;FID_PW_DATA_INCU_YN&quot;: &quot;Y&quot;,  # Previous Data Include
    &quot;FID_ETC_CLS_CODE&quot;: &quot;00&quot;  # Et Cetera Class 기타 구분 코드. 기본값 00
}</code></pre><h1 id="codeit">Codeit</h1>
<h1 id="짧고-간단하나-안정성이-매우-중요한-실무에서-이러한-코드는-사용-x">짧고 간단하나 안정성이 매우 중요한 실무에서 이러한 코드는 사용 x</h1>
<h1 id="try">try:</h1>
<h1 id="res--requestsgeturl-headersheaders-paramsparams">res = requests.get(url, headers=headers, params=params)</h1>
<h1 id="data--resjson">data = res.json()</h1>
<h1 id="printdataoutput1hts_kor_isnm---hts-한글-종목명">print(data[&quot;output1&quot;][&quot;hts_kor_isnm&quot;])  # HTS 한글 종목명</h1>
<h1 id="for-item-in-dataoutput2">for item in data[&quot;output2&quot;]:</h1>
<h1 id="printf시간-itemstck_bsop_date-itemstck_cntg_hour-가격itemstck_prpr">print(f&quot;시간: {item[&#39;stck_bsop_date&#39;]} {item[&#39;stck_cntg_hour&#39;]} 가격:{item[&#39;stck_prpr&#39;]}&quot;)</h1>
<h1 id="except-exception-as-e">except Exception as e:</h1>
<h1 id="printe">print(e)</h1>
<pre><code>try:
    res = requests.get(url, headers=headers, params=params)
    # 응답 상태 확인
    if res.status_code == 200:
        print(f&quot;응답 상태 코드: {res.status_code}&quot;)
        data = res.json()

        # 응답 구조
        if data.get(&#39;rt_cd&#39;) == &#39;0&#39;:  # 한투 API 성공코드
            # output1: 종목 현재 상태(Object)
            stock_info = data.get(&#39;output1&#39;, {})
            stock_name = stock_info.get(&#39;hts_kor_isnm&#39;, &#39;N/A&#39;)  # 종목명
            current_price = stock_info.get(&#39;stck_prpr&#39;, &#39;N/A&#39;)  # 현재가
            current_rate = stock_info.get(&#39;prdy_ctrt&#39;, &#39;N/A&#39;)  # 등락률

            print(f&quot;=== {stock_name} 현재 정보 ===&quot;)
            print(f&quot;현재가: {current_price}원, 등락률: {current_rate}%&quot;)

            # output2: 분봉 데이터(Object Array)
            candles = data.get(&#39;output2&#39;, [])

            if candles:
                print(f&quot;=== {stock_name} 분봉 데이터 ===&quot;)
                for i, candle in enumerate(candles[:5]):
                    date = candle.get(&#39;stck_bsop_date&#39;, &#39;N/A&#39;)  # 주식 영업일자
                    time = candle.get(&#39;stck_cntg_hour&#39;, &#39;N/A&#39;)  # 주식 체결시간
                    price = candle.get(&#39;stck_prpr&#39;, &#39;N/A&#39;)  # 주식 현재가
                    volume = candle.get(&#39;cntg_vol&#39;, &#39;N/A&#39;)  # 체결 거래량
                    print(f&quot;{i+1}.{date}{time} - 가격: {price}원, 거래량: {volume}&quot;)
            else:
               print(&quot;분봉 데이터가 없습니다.&quot;)
        else:
           print(f&quot;API 오류: {data.get(&#39;msg1&#39;, &#39;알 수 없는 오류&#39;)}&quot;)
    else:  # 통신 o 정보 전달 x
       print(f&quot;HTTP 요청 실패: {res.status_code}&quot;)
       print(f&quot;에러 내용: {res.text}&quot;)

except Exception as e:  # 통신 x
   print(f&quot;요청 중 네트워크/코드 오류 발생: {e}&quot;)</code></pre><p>if <strong>name</strong> == &quot;<strong>main</strong>&quot;:
    print(&quot;프로그램 시작&quot;)
    get_stock_price(&quot;005930&quot;)  # 만약 종목을 바꾸고 싶으면  이 get_stock_price 파라미터 숫자만 바꿔주면 됨!
    print(&quot;프로그램 종료&quot;)</p>
<pre><code>![](https://velog.velcdn.com/images/sujikim-hattoo/post/240306b3-0419-4386-ba44-8b22e338b58b/image.png)

&gt; 여기서 `if __name__ == &quot;__main__&quot;`란?
: 파이썬의 관례적인 코드 패턴으로 해당 파일을 &#39;직접 &#39;실행할 때만 동작하게 한다(일종의 제어 목적). 이 문구가 없으면 다른 파일에서 `import`할 때 원하지 않는 코드가 자동 실행되어 문제가 발생한다.

&gt; e.g., </code></pre><h1 id="market_datapy-if문-없이-작성">market_data.py (if문 없이 작성)</h1>
<p>def get_stock_price(code):
    # API 호출 로직
get_stock_price(&quot;035720&quot;)  # 카카오 조회하는 것으로 코드 설정</p>
<h1 id="--------">--------</h1>
<h1 id="mainpy에서">main.py에서</h1>
<p>import market_data  # 이 순간 카카오 API 자동 호출됨
market_data.get_stock_price(&quot;005930&quot;)  # 삼성전자 조회</p>
<pre><code>
결과: 카카오 API + 삼성전자 API 총 2번 호출
문제점: 불필요한 API 호출(시간 지연), API 서버 부하 증가 등

---
---
</code></pre><p>╭ ◜◝ ͡ ◜◝ ͡ ◜◝ ͡ ◜◝ ╮
  후... 드디어 다했다..!
╰ ◟◞ ͜ ◟ ͜ ◟◞ ͜ ◟ ͜ ◟◞◟◞╯
⠀⠀⠀⠀O
⠀⠀⠀⠀⠀°
〃o　 ()＿()
‎⊂⌒ （´ ^ ﻌ ^）
  ヽ_っ＿/￣￣￣/
　 　 ＼/＿＿＿/</p>
<pre><code>API 공부는 처음이라 코드를 작성하고 공부하는데 생각보다 많은 시간이 걸렸지만...
Claude 덕분에 전반적으로 코드를 보다 빨리 이해할 수 있었다.
다음에는 투자의 꽃, 투자 전략에 대해 다뤄보겠뜨아!!!

</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[비전공자가 Python으로 주식 자동 매매 프로그램을 만들기까지(2) - 제작 준비(1)(네트워크 공부)]]></title>
            <link>https://velog.io/@sujikim-hattoo/%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EC%9D%B8-%EB%82%B4%EA%B0%80-%EC%A3%BC%EC%8B%9D-%EC%9E%90%EB%8F%99-%EB%A7%A4%EB%A7%A4-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0%EA%B9%8C%EC%A7%802-%EC%A0%9C%EC%9E%91-%EC%A4%80%EB%B9%841%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B3%B5%EB%B6%80</link>
            <guid>https://velog.io/@sujikim-hattoo/%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EC%9D%B8-%EB%82%B4%EA%B0%80-%EC%A3%BC%EC%8B%9D-%EC%9E%90%EB%8F%99-%EB%A7%A4%EB%A7%A4-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0%EA%B9%8C%EC%A7%802-%EC%A0%9C%EC%9E%91-%EC%A4%80%EB%B9%841%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B3%B5%EB%B6%80</guid>
            <pubDate>Wed, 03 Sep 2025 03:15:39 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>아래 내용은 코드잇의 &#39;Python 프로젝트: 주식 자동 매매&#39; 토픽을 공부하며 작성한 내용입니다. 
토픽 링크: <a href="https://www.codeit.kr/topics/project-python-automated-trading">https://www.codeit.kr/topics/project-python-automated-trading</a></p>
</blockquote>
<p>흠...
주식을 자동으로 매매하는 프로그램을 만들기 위해서는 무엇이 필요할까?</p>
<p>주식에 대해 아무것도 모르는 사람이라도 주식을 사기 위해서는 해당 회사의 &#39;데이터&#39;가 필요하다는 것은 알고 있다! 
그 회사의 전날 주가는 어떠했고, 그동안의 주가 흐름은 어땠으며... 등 말이다.</p>
<p>그렇다면 이러한 투자 관련 정보들을 가져올 수 있는 <strong>데이터 원천</strong>이 있어야 프로그래밍을 할 수 있을 텐데...!</p>
<hr>
<p>자, 먼저 그곳이 어디든 우리가 어떠한 데이터를 흔히 &#39;끌어올&#39; 때는 <strong>API</strong>라는 것을 쓴다. AI 기능을 사용하고 싶을 때 ChatGPT API를 쓰는 것처럼 이 API 개념을 이해하고 잘 활용하기 위해서는 필수적으로 이해해야 하는 것이 있다. </p>
<p>바로 <strong>인터넷의 기본 작동 방식!</strong></p>
<h1 id="인터넷">인터넷</h1>
<p>일단 인터넷이란 무엇일까?
퍼플렉시티에게 물어봤다.</p>
<pre><code>Q. Internet 어원
A. 인터넷(Internet)은 서로 다른 네트워크들을 연결하는 기술 개념에서 유래된 말로, ‘네트워크의 네트워크’를 지향하는 의도에서 처음 명명되었다는 점이 특징입니다 </code></pre><p>그렇다! 서로 다른 네트워크들을 연결한다는 것인데...</p>
<p>그렇다면 누구와 누구를 연결하는 것이고 왜 연결하는 것일까?
이것을 이해하기 위해서는 인터넷의 핵심 멤버를 알아야 한다.</p>
<h1 id="인터넷의-핵심-구성요소-서버-클라이언트-그리고-http">인터넷의 핵심 구성요소: 서버, 클라이언트 그리고 HTTP</h1>
<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/4136101e-6996-44b9-8d84-45ffd276ab7f/image.png" alt="">
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/4230c6e3-af64-44d8-84af-a3ebcf393001/image.png" alt=""></p>
<h2 id="서버">서버</h2>
<p>: 정보를 주는 쪽.</p>
<h2 id="클라이언트">클라이언트</h2>
<p>: 정보를 요청해 정보를 받는 쪽.</p>
<p>-&gt; 여기서 정보는 <strong>&#39;데이터&#39;</strong>이다. 즉, 클라이언트가 서버에게 특정 &#39;데이터&#39;를 요청하면 서버는 클라이언트에게 &#39;데이터&#39;를 제공하는 아주 단순한 구조이다!
예를 들어 내가 노트북을 켜고 유튜브에서 &#39;스캘핑&#39;영상을 검색했을 때 서버-클라이언트 흐름은 다음과 같다.</p>
<pre><code>[클라이언트] 내 노트북 브라우저
     ↓ (HTTP 요청)
&quot;youtube.com에서 &#39;스캘핑&#39; 영상 목록 주세요&quot;
     ↓
[서버] 유튜브 서버
     ↓ (HTTP 응답)  
&quot;스캘핑 관련 영상 데이터 (제목, 썸네일, URL 등)&quot;
     ↓
[클라이언트] 내 노트북에서 영상 목록 화면에 표시</code></pre><p>이렇게 표현하니 얼마나 이해하기 쉬운가!</p>
<p>그런데 컴퓨터끼리도 이렇게 서로 &#39;한국어&#39;로 친근하게 </p>
<ul>
<li>컴퓨터 1: <em>목록 주세요!</em></li>
<li>컴퓨터 2: <em>네네 목록 여기 있어요..~~</em>
할 수는 없지 않을까...?</li>
</ul>
<p>그래서 등장한 것이 바로 <strong>HTTP</strong></p>
<h2 id="http">HTTP</h2>
<p>: 인터넷에서 컴퓨터끼리 대화하는 언어이자 소통방식. 흔히 URL 가장 앞에 <code>https://</code>가 쓰이는 이유가 있는 것이다...!</p>
<p>이 HTTP를 써서 
클라이언트는 서버에게 데이터 요청, 즉 <strong>Request</strong>를 하고
서버는 클라이언트의 요청을 받아 데이터 제공, 즉 <strong>Response</strong>를 할 수 있는 것이다.</p>
<p>자 이렇게 서버-클라이언트의 대화를 실제로 확인할 수 있는 방법이 있다.</p>
<pre><code>Windows: F12 키
macOS: Cmd + Option + I</code></pre><p>Network 탭&gt; 아래 Name에 아무거나 클릭하면
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/487b3f95-c322-41bc-a7f8-2202ef315093/image.png" alt="">
(잘 모르겠지만 일단 개인정보 관련되어 보이는 건 다 지워봤다...)</p>
<p>Headers탭에는 크게
<strong>1) General
2) Response Headers
3) Request Headers</strong>
로 구성되어있는 것을 볼 수 있다.</p>
<p>각 목차별 눈여겨 볼 것들과 간단한 설명도 같이 적어보자면
<strong>1) General</strong></p>
<ul>
<li>Request URL(요청하는 구체적인 주소. <code>https://</code> 뒤에 붙는 경로와 쿼리 파라미터가 포함됨)</li>
<li>Request Method(요청하는 방법을 의미. e.g., GET: 데이터 가져와, POST: 데이터 보내줄게 등)</li>
</ul>
<p><strong>2) Response Headers</strong></p>
<ul>
<li>Content-Type(<code>application/json</code> 으로 되어있는데 그렇다. 데이터는 모두 JSON 형태로 받아온다.)<blockquote>
<p>Q. JSON형태란?
A. HTTP에서 쓰이는 표준 데이터 형식을 의미하며 여러개의 중괄호로 구성된 딕셔너리 형식으로 되어있다.</p>
</blockquote>
</li>
</ul>
<p><strong>3) Request Headers</strong></p>
<ul>
<li>Content-Type(마찬가지로 <code>application/json</code>으로 되어있다.)</li>
</ul>
<p>그래서 위 정보들로 서버-클라이언트 정보 흐름을 조금 더 구체화해본다면 ...</p>
<pre><code>[클라이언트] 내 노트북 브라우저
     ↓ (HTTP Request)
&quot;youtube.com에서 &#39;스캘핑&#39; 영상 목록 주세요&quot; (GET 메소드)
     ↓
[서버] 유튜브 서버
     ↓ (HTTP Response)  
&quot;스캘핑 관련 영상 데이터 (제목, 썸네일, URL 등)&quot;
(Header: 응답 정보 / Body: JSON 형태로 작성된 스캘핑 관련 영상 데이터)
     ↓
[클라이언트] 내 노트북에서 영상 목록 화면에 표시</code></pre><p>이 정도로 네트워크에 대한 기본 지식을 쌓았으면 
본격적으로 코딩을 해볼 차례!(다음 글에서 계속됩니다!) </p>
<pre><code>두다다다다다다다
　(∩`・ω・)
＿/_ミつ/￣￣￣/
　　＼/＿＿＿/</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] mAP은 무엇이고 어디어디에서 쓰일까?]]></title>
            <link>https://velog.io/@sujikim-hattoo/DL-mAP%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EA%B3%A0-%EC%96%B4%EB%94%94%EC%96%B4%EB%94%94%EC%97%90%EC%84%9C-%EC%93%B0%EC%9D%BC%EA%B9%8C</link>
            <guid>https://velog.io/@sujikim-hattoo/DL-mAP%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EA%B3%A0-%EC%96%B4%EB%94%94%EC%96%B4%EB%94%94%EC%97%90%EC%84%9C-%EC%93%B0%EC%9D%BC%EA%B9%8C</guid>
            <pubDate>Sun, 31 Aug 2025 23:58:55 GMT</pubDate>
            <description><![CDATA[<p><a href="https://velog.io/@sujikim-hattoo/DL-YOLO-%EB%AA%A8%EB%8D%B8%EC%9D%80-%EB%8C%80%EC%B2%B4-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C%EC%A3%BC%EC%9A%94-%ED%8A%B9%EC%A7%95%EA%B3%BC-%EC%9E%A5%EC%A0%90-%EC%9C%84%EC%A3%BC">https://velog.io/@sujikim-hattoo/DL-YOLO-모델은-대체-무엇일까주요-특징과-장점-위주</a></p>
<p>위 링크에서 YOLO의 장점 내용을 설명할 때 잠깐 언급되었던 컴퓨터 비전의 &#39;mAP&#39;..에 대해 알아보자..!</p>
<hr>
<h3 id="정의">정의</h3>
<p>: <strong>mAP(mean Average Precision)</strong>는 객체 감지 모델의 성능을 측정하는 대표 지표</p>
<h2 id="계산-과정">계산 과정</h2>
<p>Step1. IoU기준 설정(예측 박스와 실제 박스 겹침 정도. 보통 0.5 이상)
Step2. class별 AP 계산(e.g., 자동차, 사람, 강아지 등 각 클래스 마다 정확도 측정)
Step3. 전체 평균(모든 class의 AP 평균내어 하나의 mAP 점수 도출)</p>
<blockquote>
<p>mAP는 단순한 정밀도의 평균이다 (x)
mAP는 Precision-Recall 곡선의 면적이다 (o)</p>
</blockquote>
<p><code>* AP란? Average Precision의 줄임말로 각 class별로 Precision-Recall 곡선 아래 면적을 계산한 값</code>
<code>** Precision-Recall 곡선이란? 모델이 얼마나 정확하게 예측했는지(Precision)와 실제 객체를 얼마나 빠뜨리지 않고 찾았는지(Recall)을 나타내는 두 지표. 이 두 지표의 관계를 그래프로 나타낸 곡선</code></p>
<h3 id="객체-인식에서의-활용">객체 인식에서의 활용:</h3>
<p> mAP 특징</p>
<ul>
<li>종합 평가 지표(정확도와 재현율 모두 고려)</li>
<li>클래스 균형(모든 객체 클래스 성능 공평하게 평가함)</li>
<li>비교 가능(서로 다른 모델 간 객관적 성능 비교 가능)</li>
<li>임계값 독립적(특정 임계값 의존x. 안정적o)</li>
</ul>
<p>그 결과!</p>
<ul>
<li>거의 모든 객체 감지 모델(e.g., YOLO, R-CNN, SSD 등)등에서 mAP로 성능 비교</li>
<li>대표 데이터셋(e.g., PASCAL VOC, COCO 등)에서도 공식 평가 지표로 사용</li>
</ul>
<blockquote>
<p>한 줄 요약
: mAP는 객체 감지 모델 성능을 측정하는 대표 펴가지표로 정확하고 안정적이기에 대부분의 객제 감지 모델과 데이터셋에서도 사용된다</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] YOLO 모델은 대체 무엇일까(주요 특징과 장점 위주)]]></title>
            <link>https://velog.io/@sujikim-hattoo/DL-YOLO-%EB%AA%A8%EB%8D%B8%EC%9D%80-%EB%8C%80%EC%B2%B4-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C%EC%A3%BC%EC%9A%94-%ED%8A%B9%EC%A7%95%EA%B3%BC-%EC%9E%A5%EC%A0%90-%EC%9C%84%EC%A3%BC</link>
            <guid>https://velog.io/@sujikim-hattoo/DL-YOLO-%EB%AA%A8%EB%8D%B8%EC%9D%80-%EB%8C%80%EC%B2%B4-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C%EC%A3%BC%EC%9A%94-%ED%8A%B9%EC%A7%95%EA%B3%BC-%EC%9E%A5%EC%A0%90-%EC%9C%84%EC%A3%BC</guid>
            <pubDate>Sun, 31 Aug 2025 15:30:56 GMT</pubDate>
            <description><![CDATA[<p>You only live once라는 의미로 익숙하지만
딥러닝에서 이 단어는 완전히 다른 의미로 쓰인다.</p>
<h3 id="you-only-look-once"><strong>You Only Look Once</strong></h3>
<p>한 번밖에 볼 수 없다 즉, 단 한 번만 보면 된다는 뜻의 모델.
과연 이 모델이 뜻하는 &#39;단 한번&#39;이란 무엇일까?</p>
<hr>
<h3 id="역사">역사</h3>
<ul>
<li>먼저 이 YOLO는 2015년 JosephRedmon과 Ali Farhadi가 개발한 Darknet 프레임워크에서 처음 소개되었다. 지금은 2025년 2월에 출시된 YOLOv12가 최신 버전이며 계속해서 발전해왔다.</li>
</ul>
<h3 id="정의">정의</h3>
<ul>
<li>객체 감지(Object Detection)분야의 대표적인 모델로,&#39;실시간(real-time)&#39; 감지가 주목적이다. 실시간으로 객체 위치를 찾고(Localization) + 동시에 그것이 무엇인지 분류하는(Classification) 작업이 실시간으로 이루어진다는 것이다.</li>
</ul>
<h3 id="작동-방식">작동 방식</h3>
<ul>
<li>바로 여기서 <strong>단 한 번의 순전파</strong>로 모든 작업을 완료한다. 전체 이미지를 <strong>한 번에</strong>처리하여 위치 감지와 분류를 동시에 수행하는 한 단계의 작업
&lt;-&gt; R-CNN: 이미지에서 관심 영역(RoI)을 먼저 찾은 뒤 그 다음 각 영역마다 분류 작업을 수행하는 두 단계의 작업</li>
</ul>
<h3 id="특징">특징</h3>
<ul>
<li>전체 이미지에 <strong>단일 신경망 적용</strong> </li>
<li><blockquote>
<p>신경망 예측을 위해 <strong>단 한 번의</strong> 전방 전파 통과만 필요 &lt;-&gt; R-CNN: 단일 이미지 <strong>수천 번의</strong> 통과 필요</p>
</blockquote>
</li>
<li>실시간 처리능력 -&gt; 빠르게 지나가는 차량 감지 / 교통 패턴 분석/산불 위험 감지/동물 식별/위험 행동 모니터링 등 다양한 분야에서 활용됨</li>
</ul>
<h3 id="장점">장점</h3>
<ul>
<li><p>빠름 -&gt; 초당 수십 프레임의 비디오 처리가 가능해서 실시간 추적에도 유용하다.</p>
</li>
<li><p>지속적인 정확도 향상 -&gt; 버전업마다 개선 중(e.g., YOLO11은 YOLOv8m대비 22% 적은 파라미터로 더 높은 mAP 달성)
<code>mAP란? mean Average Precision의 줄임말로 객체 감지 정확도를 측정하는 대표 지표를 의미</code></p>
</li>
<li><p>우수한 접근성 -&gt; 오픈소스여서 접근성과 활용성이 뛰어나고 간단한 API로도 쉽게 사용이 가능하다.</p>
</li>
</ul>
<blockquote>
<p>한 줄 정리
: YOLO 는 단 한번의 순전파로 실시간 객체 감지 분야에 혁신을 가져와 이미지의 처리 속도와 정확도를 높였습니다.</p>
</blockquote>
<hr>
<hr>
<p>참고
<a href="https://en.wikipedia.org/wiki/You_Only_Look_Once#cite_note-:2-1">https://en.wikipedia.org/wiki/You_Only_Look_Once#cite_note-:2-1</a>
<a href="https://blog.roboflow.com/guide-to-yolo-models/">https://blog.roboflow.com/guide-to-yolo-models/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[비전공자가 Python으로 주식 자동 매매 프로그램을 만들기까지(1) - 프로그램 제작 배경]]></title>
            <link>https://velog.io/@sujikim-hattoo/%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EC%9D%B8-%EB%82%B4%EA%B0%80-AI-%EC%A3%BC%EC%8B%9D-%EB%B3%B4%EC%A1%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0%EA%B9%8C%EC%A7%801-%EB%AA%A9%ED%91%9C-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@sujikim-hattoo/%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EC%9D%B8-%EB%82%B4%EA%B0%80-AI-%EC%A3%BC%EC%8B%9D-%EB%B3%B4%EC%A1%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0%EA%B9%8C%EC%A7%801-%EB%AA%A9%ED%91%9C-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Sat, 30 Aug 2025 07:17:59 GMT</pubDate>
            <description><![CDATA[<p><a href="https://youtu.be/QZV8p3sWfeM?feature=shared">https://youtu.be/QZV8p3sWfeM?feature=shared</a>
위 영상으로 단타를 &#39;하고 싶다&#39;라는 것이 생겼고</p>
<p><a href="https://youtu.be/VLiTTQtQcr4?feature=shared">https://youtu.be/VLiTTQtQcr4?feature=shared</a>
위 영상으로 &#39;어? 스캘핑? 재밌어보이는데?&#39;라는 생각이 생겼다.</p>
<p>어떤 것이든 오래 길게 끄는 것을 싫어하는 나로서는
장투보다는
<strong>단타와 스캘핑</strong>이 제일 잘 맞는 것 같았다.
(물론 한 번도 해본 적은 없다. 끌끌)</p>
<p>그런데 문제가 있다.
바로
.
.
.
<strong>나는 주식에 대해 &#39;아무것도&#39; 모른다는 것!</strong></p>
<p>대차대조표가 대변과 차변으로 이루어져 있다.
대변은 부채이고 차변은 자산?자본?이고
또..ROI가 중요하다는 것..?</p>
<p>자산과 자본의 차이도 제대로 설명하지 못하는 사람인데
갑자기 그런 생각이 들었다.</p>
<p>투자에도 코딩에도 관심있으니 한번 만들어보는 게 좋지 않겠어..?</p>
<p>항상 내가 프로그래밍 공부에 뛰어들 때마다 주변의 업계(?)선배들이 <strong>일단 뭐라도 만들어봐</strong>라고 했으니,,!</p>
<p>이렇게 나의 프로젝트는 시작됐다.
주식과 프로그래밍
어느 하나 제대로 모르는 비전공자인
내가! 주식 자동 매매 프로그램을 만들게 되었다는 것
( •̀ ω •́ )✧</p>
<hr>
<p>먼저 AI한테 자문을 구해보았다.
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/a167f645-2ef1-45eb-8ae4-a82449bc4a4b/image.png" alt="">
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/df9b2fd0-e9ec-4a80-94f2-6648ee54abe7/image.png" alt=""></p>
<p>(노란색: 내가 &#39;최소한으로&#39; 공부해야하는 것)
(빨간색: 개인 AI 자동 매매 프로그램 개발의 한계 &amp; 스캘핑/단타의 단점)</p>
<p>=&gt; 한 마디로 비전공자 혼자 주식 자동 매매 프로그램을 만들기까지
시간과 노력이 너무 많이 들고
들인 투자 대비 결과도 매우 불확실하다는 것...╯︿╰</p>
<hr>
<p> 일단 지금은 완성도 높은 자동 매매 로직(실시간 매매 및 리스크 관리까지 해주는...)구축보다는
 <strong>투자 판단 보조</strong> 목적으로 분석하고 추천해주는 툴을 만드는 것이 좋아보인다.</p>
<p> 전체적인 프로그램을 만들기 전에 앞서서 
 책이나 강의를 보고 한번 슈슉 만들어보는 게 좋겠다고 생각하던 찰나 코드잇에서 아래와 같은 강의를 발견하게 되었다!
 <a href="https://www.codeit.kr/topics/project-python-automated-trading">https://www.codeit.kr/topics/project-python-automated-trading</a>
 <img src="https://velog.velcdn.com/images/sujikim-hattoo/post/958574eb-0496-4ccf-9a03-6398afdc0887/image.png" alt=""></p>
<p>오오 원래의 목표대로 주식 자동 매매 프로그래밍을 한 번 해볼 수 있으니 모르는 개념도 공부하며 전체적인 프로그래밍 흐름도 파악하기에 좋아보였다. ( ￣▽￣)bb
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/bccebf0f-6ab4-4f01-b732-7b68aa7e833e/image.png" alt=""></p>
<p>그래서 위 목차대로 일단 한 번 공부해보기로
도전!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Why] 왜 이미지를 모델에 입력할 때 리사이징과 정규화가 필요할까?]]></title>
            <link>https://velog.io/@sujikim-hattoo/Why-%EC%99%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80%EB%A5%BC-%EB%AA%A8%EB%8D%B8%EC%97%90-%EC%9E%85%EB%A0%A5%ED%95%A0-%EB%95%8C-%EB%A6%AC%EC%82%AC%EC%9D%B4%EC%A7%95%EA%B3%BC-%EC%A0%95%EA%B7%9C%ED%99%94%EA%B0%80-%ED%95%84%EC%9A%94%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@sujikim-hattoo/Why-%EC%99%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80%EB%A5%BC-%EB%AA%A8%EB%8D%B8%EC%97%90-%EC%9E%85%EB%A0%A5%ED%95%A0-%EB%95%8C-%EB%A6%AC%EC%82%AC%EC%9D%B4%EC%A7%95%EA%B3%BC-%EC%A0%95%EA%B7%9C%ED%99%94%EA%B0%80-%ED%95%84%EC%9A%94%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Sun, 24 Aug 2025 23:53:07 GMT</pubDate>
            <description><![CDATA[<p>머신러닝에서 데이터를 넣을 때 <code>df.describe()</code>로 데이터 분포를 확인하고 이상치를 제거하는 등의 과정을 <strong>전처리</strong>라고 하였다.</p>
<p>딥러닝, 특히 이미지 모델에서는 이러한 전처리가 필요 없을까?</p>
<p>...</p>
<p>있다! 이미지 모델 전처리 과정은 크게 다음과 같이 진행된다.</p>
<blockquote>
<p>이미지 로드 -&gt; (선택) Gray scale =&gt; 이미지 리사이징 -&gt; 이미지 정규화 -&gt; 이미지 노이즈 처리 -&gt; 이미지 정규화</p>
</blockquote>
<p>그 중에서도 이미지 크기와 처리 면에서 중요하게 다뤄지는 <strong>리사이징(Resizing)</strong>과 <strong>정규화(Normalization)</strong>.</p>
<p><strong>&#39;왜&#39;</strong> 위 두 과정이 모델에 이미지 입력전 필요한지 살펴보겠다.</p>
<p>(* 실험환경: 코랩)
(** 실험 이미지 <a href="https://pixabay.com/ko/photos/%EC%9E%90%EC%97%B0-%EB%82%98%EB%AC%B4-rgb-%EA%B5%AC%EB%A6%84-6888085/">출처</a>) </p>
<hr>
<h2 id="1-리사이징resizing">1. 리사이징(Resizing)</h2>
<ul>
<li><p>뜻:크기를 축소하거나 이미지 크기를 통일시키는 것</p>
</li>
<li><p>이유:</p>
<ul>
<li>리사이징 전: 이미지 크기가 크면 그만큼 GPU 메모리를 많이 차지.(변수량 많아져 처리속도가 많인  느려짐)</li>
<li>리사이징 후: <em>같은 크기</em>가 되어 한 번에 여러 이미지 처리 가능 &amp; <em>작은 크기</em>일수록 빠른 연산 가능
=&gt; 이미지 처리 양과 속도에 영향
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/5c3288a0-e500-420a-b693-e4dfecfcbf51/image.png" alt=""></li>
</ul>
</li>
</ul>
<ul>
<li><p>방법
  1) 픽셀 단위</p>
<ul>
<li>단순:<code>cv2.resize(image,(width, height))</code></li>
<li>보간: <code>cv2.resize(image, (width, height))</code>, <code>interpolation=cv2.INTER_AREA)</code>(각 픽셀에 연결지점을 어떻게 연결시켜줄지)</li>
</ul>
<p>2) 이미지 높낮이: 실제 이미지 배열에 직접 접근</p>
<ul>
<li>x,y,width,height 지정 -&gt; <code>image_resized[y:y+height, x:x+width]</code> </li>
</ul>
</li>
</ul>
<blockquote>
<p>Q. cv2. 란?
  A. OpenCV(Open Source Computer Vision Library)의 파이썬 버전으로 이미지 처리를 위한 가장 널리 사용되는 라이브러리이다. 이미지를 BGR(Blue-Green-Red)순으로 읽는다.</p>
</blockquote>
<blockquote>
<p>Q. 사이즈는 어떻게 결정?
  A. 보통 input 이미지 크기에 맞춰 결정(e.g. ResNet 224x224, YOLO 608x608 등)</p>
</blockquote>
<blockquote>
<p>Q. 사이즈를 줄이는 과정에서 정보 손실이 일어나지 않는지?<br>A. 일어난다. 하지만 &#39;핵심 특징&#39;만 추출하는 것이 목표이므로 적절한 크기 조정으로 조정해도 괜찮다. (여기서 핵심특징 예시는?)</p>
</blockquote>
<ul>
<li>기대 효과: 계산 속도 상승, 성능 개선
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/cbf041b7-47b3-4735-84e3-ee3df27b78b8/image.png" alt=""></li>
</ul>
<hr>
<h2 id="2-정규화normalization">2. 정규화(Normalization)</h2>
<ul>
<li><p>뜻: 픽셀 값의 범위를 일정하게 맞춰주는 것</p>
</li>
<li><p>이유</p>
<ul>
<li><p>정규화 전: 픽셀 값 범위는 0~255. 이 큰 값들이 모델 학습에 방해</p>
</li>
<li><p>정규화 후: 픽셀 값 범위를 작게 하여 경사하강법이 안정적으로 동작하게 하고 적절한 분포로 활성화 함수가 효과적으로 작동하게 한다. 결과적으로는 학습 속도 향상!
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/2483d0ae-8941-4a25-b6ef-9f01c04390dd/image.png" alt="">  </p>
<blockquote>
<p>Q. 정규화를 하면 픽셀값 범위를 줄이는 것인데 이미지 변화가 생기는 것은 아닌지?
A. 
<img src="https://velog.velcdn.com/images/sujikim-hattoo/post/58819ade-5b2c-4caf-b89b-0a6d7d9bf170/image.png" alt="">
=&gt; 정규화는 정보 손실 없이 학습 최적화를 위해 단순히 숫자 범위만 바꾸는 과정.(like 온도를 섭씨 -&gt; 화씨로 바꾸는 것 처럼. 실제 의미는 동일한 것!)</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<ul>
<li>방법<ul>
<li>&lt;밝기와 대비가 다양한 이미지&gt; Min-Max 정규화<ul>
<li>&lt;단순한 전처리, Grayscale 이미지&gt; Mean 정규화</li>
<li>&lt;Scale에 민감한 모델&gt; Z-score 정규화</li>
<li>&lt;수치가 큰 이미지 데이터&gt; Decimal 정규화</li>
</ul>
</li>
<li>&lt;이미지 유사도 분석이나 클러스터링&gt; L2 정규화</li>
<li>&lt;이상치가 많은 데이터&gt; Robust 정규화<ul>
<li>기대 효과: 더 빠르고 안정적인 수렴</li>
</ul>
</li>
</ul>
</li>
</ul>
<blockquote>
<p>기술 면접 대비 한 줄 요약: <strong>리사이징</strong>은 이미지 크기를 통일 &amp; 메모리 절약 =&gt; 더 효율적인 배치 처리 가능하게 함
/ <strong>정규화</strong>는 픽셀값 범위를 조정 -&gt; 모델 학습을 안정화하고 수렴 속도를 높임</p>
</blockquote>
<hr>
<hr>
<p> <strong>참고</strong>
 <a href="https://pastryofjsmath.tistory.com/36">이미지 전처리 - 리사이징1</a>
 <a href="https://pastryofjsmath.tistory.com/37">이미지 전처리 - 리사이징2</a>
 <a href="https://j-linux-journal.tistory.com/73">이미지 전처리 - 정규화</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] (누구나 이해하는)이미지 분류 혼동행렬과 핵심 평가지표 5가지]]></title>
            <link>https://velog.io/@sujikim-hattoo/DL-%EB%88%84%EA%B5%AC%EB%82%98-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%B6%84%EB%A5%98-%ED%98%BC%EB%8F%99%ED%96%89%EB%A0%AC%EA%B3%BC-%ED%95%B5%EC%8B%AC-%ED%8F%89%EA%B0%80%EC%A7%80%ED%91%9C-5%EA%B0%80%EC%A7%80</link>
            <guid>https://velog.io/@sujikim-hattoo/DL-%EB%88%84%EA%B5%AC%EB%82%98-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%B6%84%EB%A5%98-%ED%98%BC%EB%8F%99%ED%96%89%EB%A0%AC%EA%B3%BC-%ED%95%B5%EC%8B%AC-%ED%8F%89%EA%B0%80%EC%A7%80%ED%91%9C-5%EA%B0%80%EC%A7%80</guid>
            <pubDate>Fri, 22 Aug 2025 03:39:13 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/e06a72f0-a8af-4294-a41f-b57f978e8cac/image.png" alt=""></p>
<p>여러분은 지금 X-ray 이미지로 폐렴인지 아니면 정상인지 분류 작업을 진행하고 있습니다. </p>
<p>이전에 이미지의 노이즈를 최소화하는 작업의 평가 함수는 단순한 오차 계산이었다면의료 이미지 분류 작업은 생명과 직결되어 있어서 단순한 오차 값으로 계산을 할 수가 없는데요.</p>
<p>그러기 위해 알아야 할 핵심 개념이 바로 혼동행렬과 핵심 평가 지표입니다</p>
<hr>
<h1 id="혼동행렬">혼동행렬</h1>
<p>모든 평가의 기본인 <strong>Consufion Matrix(혼동행렬)</strong>은 다음과 같이 생겼습니다.</p>
<table>
<thead>
<tr>
<th></th>
<th></th>
<th>&lt;실제&gt;</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>&lt;예측&gt;</td>
<td>기준</td>
<td>정상</td>
<td>폐렴</td>
</tr>
<tr>
<td></td>
<td>정상</td>
<td>90</td>
<td>10</td>
</tr>
<tr>
<td></td>
<td>폐렴</td>
<td>5</td>
<td>95</td>
</tr>
</tbody></table>
<p>혼동행렬의 기본 용어 4가지를 정리해보면 다음과 같습니다!</p>
<ul>
<li><strong>TP (True Positive)</strong>: 폐렴을 폐렴으로 맞춤 = 95개</li>
<li><strong>TN (True Negative)</strong>: 정상을 정상으로 맞춤 = 90개  </li>
<li><strong>FP (False Positive)</strong>: 정상을 폐렴으로 잘못 진단 = 5개 (1종 오류)</li>
<li><strong>FN (False Negative)</strong>: 폐렴을 정상으로 잘못 진단 = 10개 (2종 오류) ⚠️ 위험!</li>
</ul>
<p>표를 용어들로 채워본다면 아래와 같겠네요!</p>
<table>
<thead>
<tr>
<th></th>
<th></th>
<th>&lt;실제&gt;</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>&lt;예측&gt;</td>
<td>기준</td>
<td>정상</td>
<td>폐렴</td>
</tr>
<tr>
<td></td>
<td>정상</td>
<td>TN</td>
<td>FN</td>
</tr>
<tr>
<td></td>
<td>폐렴</td>
<td>FP</td>
<td>TP</td>
</tr>
</tbody></table>
<hr>
<h2 id="핵심-평가지표5가지">핵심 평가지표(5가지)</h2>
<p>그리고 이 혼동행렬을 통해 아래와 같이 주요 평가지표들을 계산하는 것이 더욱 중요합니다. 주요 평가 지표 5가지의 정의와 계산하는 방식에 대해 차례대로 알아보겠습니다!</p>
<h3 id="1-accuracy-정확도">1. <strong>Accuracy (정확도)</strong></h3>
<ul>
<li>의미: 전체 예측 중 맞춘 비율</li>
<li>공식: (TP + TN) / (TP + TN + FP + FN) = 총 사람수를 True합(정상은 정상으로, 폐렴은 폐렴으로 예측한 수)으로 나눠</li>
<li>예시: (95 + 90) / (95 + 90 + 5 + 10) = 185/200 = 92.5%</li>
<li>문제점: 데이터 불균형 시 잘못된 신호 줄 수 있음</li>
</ul>
<h3 id="2-precision-정밀도">2. <strong>Precision (정밀도)</strong></h3>
<ul>
<li>의미: 폐렴이라고 예측한 것 중에서 실제로 폐렴인 비율</li>
<li>공식: TP / (TP + FP)  = 폐렴으로 예측하고 또 실제 폐렴이기도 한 사람 수를 모델이 폐렴으로 예측한 총 사람 수로 나눠 </li>
<li>예시: 95 / (95 + 5) = 95%</li>
<li>해석: 모델이 폐렴이라고 하면 95% 확률로 진짜 폐렴</li>
</ul>
<h3 id="3-recall-재현율-sensitivity">3. <strong>Recall (재현율, Sensitivity)</strong></h3>
<ul>
<li>의미: 실제 폐렴 환자 중에서 모델이 폐렴이라고 예측한 비율  </li>
<li>공식: TP / (TP + FN) = 폐렴으로 예측하고 또 실제 폐렴이기도 한 사람 수를 총 실제 폐렴 환자 수로 나눠</li>
<li>예시: 95 / (95 + 10) = 90.5%</li>
<li>해석: 폐렴 환자 100명 중 약 90명을 찾아냄</li>
<li>의료에서 중요: 놓치면 안 되는 질병일 때 핵심!</li>
</ul>
<h3 id="4-f1-score">4. <strong>F1-Score</strong></h3>
<ul>
<li>의미: 2.Precision과 3.Recall의 조화평균</li>
<li>공식: 2 × (Precision × Recall) / (Precision + Recall)</li>
<li>예시: 2 × (0.95 × 0.905) / (0.95 + 0.905) = 92.7%</li>
<li>특징: 두 지표 균형을 맞추고 싶을 때 사용</li>
</ul>
<h3 id="5-specificity-특이도">5. <strong>Specificity (특이도)</strong></h3>
<ul>
<li>의미: 실제 정상인 중에서 모델이 정상으로 판단한 비율. 위 다른 4가지 지표들에 비해 크게 중요하게 다뤄지지는 않음</li>
<li>공식: TN / (TN + FP)</li>
<li>예시: 90 / (90 + 5) = 94.7%</li>
<li>해석: 정상인 100명 중 95명을 정상으로 판단</li>
</ul>
<hr>
<h2 id="평가지표-해석">평가지표 해석</h2>
<p>위 평가 지표를 토대로 결과를 정리해보면 아래와 같습니다.</p>
<p>📊 평가 지표:
• Accuracy: 185/200 = 92.5% &quot;전체적으로 잘 맞춤&quot;
• Precision: 95/100 = 95% &quot;폐렴이라고 하면 대부분 맞음&quot;<br>• Recall: 95/105 = 90.5% &quot;폐렴 환자 10명을 놓쳤음&quot; ⚠️
• F1-Score: 92.7% &quot;전반적으로 균형잡힌 성능&quot;</p>
<hr>
<h2 id="내용-정리">내용 정리</h2>
<p>실제 의료현장에서는 어떤 케이스가 제일 위험할까요...?
바로</p>
<blockquote>
<p>실제 폐렴환자를 정상으로 오진하는 것</p>
</blockquote>
<p>입니다..!</p>
<p>그렇기 때문에 평가지표 중에서도 </p>
<blockquote>
<p>Recall</p>
</blockquote>
<p>이 가장 중요하다고 할 수 있죠.</p>
<p>-&gt; 의료 이미지 분류 모델에서는 <strong>Recall</strong>을 최대한 높여 FN을 줄이는 것이 중요하고 Recall과 트레이드 오프 관계인 <strong>Precision</strong>은 조금 낮아져도 괜찮습니다 :)</p>
<p>(c.f. Recall과 Precision 사이의 트레이드 오프 관계가 생기는 이유는 조금이라도 이상하면 다 폐렴으로 진단해야 높아지는 Recall값과 보다 폐렴 진단 기준을 엄격하게 조정해야 높아지는 Precision 값의 성격은 서로 다르기 때문입니다. 어려운 말로 임계값 조정이 Recall과 Precision 값에 서로 반대 영향을 주기 때문이라고 정리할 수 있습니다.) </p>
<p>그래서 실제 의료 AI 모델링을 할 때는 다음과 같은 기준을 세우는 것을 권장합니다</p>
<ul>
<li>Recall 95% 이상(최우선)</li>
<li>Precision 80% 이상</li>
<li>(가능하면 전체적인 Accuracy도 높이는 방향으로)</li>
</ul>
<p>Recall을 높이려면 임계값 조정이나 클래스 가중치 설정이 필요하고 손실함수에서 FN(False Negative; 폐렴인데 정상으로 예측)에 더 큰 페널티를 주는 것도 효과적이겠죠! 이번 글은 전체적인 개념 설명이기때문에 방법론은 이쯤에서 마무리 하겠습니다. </p>
<p>중요한 점은 의료 AI 분야에서는 <strong>놓치는 것</strong>이 잘못 찾는 것보다 훨<del>~</del>씬 더 위험하다는 점!!을 항상 염두에 두어야합니다!!!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] Application and sturcture of Autoencoder 오토 인코더 적용 및 구조]]></title>
            <link>https://velog.io/@sujikim-hattoo/DL-Application-and-sturcture-of-Autoencoder-%EC%98%A4%ED%86%A0-%EC%9D%B8%EC%BD%94%EB%8D%94-%EC%A0%81%EC%9A%A9-%EB%B0%8F-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@sujikim-hattoo/DL-Application-and-sturcture-of-Autoencoder-%EC%98%A4%ED%86%A0-%EC%9D%B8%EC%BD%94%EB%8D%94-%EC%A0%81%EC%9A%A9-%EB%B0%8F-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Mon, 18 Aug 2025 00:00:17 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/4a9aa6f1-23a4-454f-86a0-3cb0692d3887/image.png" alt=""></p>
<pre><code> This writing is provided in English first, followed by Korean.
이 글은 영어 -&gt; 한국어 순으로 작성되어 있습니다.</code></pre><p><strong>An Autoencoder</strong></p>
<ul>
<li>an unsupervised neural network </li>
<li>that learns to compress (encode) data into a low-dimensional representation </li>
<li>and then reconstruct (decode) it back to its original form. - Its primary goal is to learn the most essential features of the data, captured in a compressed &quot;latent space.&quot;</li>
</ul>
<hr>
<h2 id="1-introduction"><strong>1. Introduction</strong></h2>
<h3 id="11-definition"><strong>1.1. Definition</strong></h3>
<p>An <strong>Autoencoder</strong> is an unsupervised neural network that learns to compress (encode) data into a low-dimensional representation and then reconstruct (decode) it back to its original form. Its primary goal is to learn the most essential features of the data, captured in a compressed &quot;latent space,&quot; by training the network to reconstruct its own input.</p>
<h3 id="12-types"><strong>1.2. Types</strong></h3>
<p>Autoencoders come in several variations, each with unique constraints and use cases:</p>
<ul>
<li><strong>Undercomplete Autoencoders</strong>: The simplest form, where the bottleneck layer is smaller than the input, forcing the network to learn the most salient features for dimensionality reduction.</li>
<li><strong>Regularized Autoencoders</strong>: A broader class that uses regularization techniques to prevent overfitting and learn more robust features. This includes the types below.</li>
<li><strong>Sparse Autoencoders (SAEs)</strong>: Constrains the number of neurons that can be active at one time. This allows the network to have a large capacity while forcing it to learn specific features with different nodes.</li>
<li><strong>Denoising Autoencoders</strong>: Trained to reconstruct a clean, original input from a partially corrupted version. This forces the model to learn robust features and ignore noise.</li>
<li><strong>Contractive Autoencoders</strong>: Designed to be insensitive to small variations in the input data, encouraging the model to learn features that capture the underlying structure rather than minor details.</li>
<li><strong>Variational Autoencoders (VAEs)</strong>: Learns the parameters of a probability distribution representing the data. This makes it a generative model, capable of creating new data samples by sampling from this distribution.</li>
</ul>
<h3 id="13-structures"><strong>1.3. Structures</strong></h3>
<p>The structure of an autoencoder is composed of two main parts: the Encoder and the Decoder.</p>
<h4 id="encoder"><strong>Encoder</strong></h4>
<p>The <strong>Encoder&#39;s</strong> job is to <strong>compress</strong> the input data. It takes the high-dimensional input (like an image) and passes it through a series of layers that progressively reduce the dimensions. The final output is a compact, low-dimensional representation, often called the <strong>bottleneck</strong> or <strong>latent representation</strong>.</p>
<h4 id="decoder"><strong>Decoder</strong></h4>
<p>The <strong>Decoder&#39;s</strong> job is to <strong>reconstruct</strong> the original data from the compressed representation. It takes the low-dimensional output from the encoder and passes it through a series of layers that progressively increase the dimensions, aiming to recreate the input as accurately as possible.</p>
<h4 id="comparison-encoder-vs-decoder"><strong>Comparison: Encoder vs. Decoder</strong></h4>
<table>
<thead>
<tr>
<th align="left">Feature</th>
<th align="left"><strong>Encoder</strong></th>
<th align="left"><strong>Decoder</strong></th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>Purpose</strong></td>
<td align="left">Compresses data into a latent representation.</td>
<td align="left">Reconstructs data from the latent representation.</td>
</tr>
<tr>
<td align="left"><strong>Architecture</strong></td>
<td align="left">The number of neurons decreases with each layer.</td>
<td align="left">The number of neurons increases with each layer.</td>
</tr>
<tr>
<td align="left"><strong>Input &amp; Output</strong></td>
<td align="left"><strong>Input:</strong> Original Data&lt;br&gt;<strong>Output:</strong> Latent Representation</td>
<td align="left"><strong>Input:</strong> Latent Representation&lt;br&gt;<strong>Output:</strong> Reconstructed Data</td>
</tr>
</tbody></table>
<hr>
<h2 id="2-application"><strong>2. Application</strong></h2>
<p>Autoencoders are well-suited for tasks that benefit from learning the underlying structure of data in an unsupervised manner.</p>
<h3 id="21-dimensionality-reduction"><strong>2.1. Dimensionality Reduction</strong></h3>
<p>By learning a compressed representation, autoencoders can be used to reduce the number of features in a dataset. This is useful for <strong>data visualization</strong> and can <strong>improve the performance</strong> of other models.</p>
<h3 id="22-image-and-audio-denoising"><strong>2.2. Image and Audio Denoising</strong></h3>
<p>An autoencoder can be trained on clean data and then used to clean up noisy inputs. It reconstructs a clean version from a corrupted input, effectively <strong>filtering out the noise</strong>.</p>
<h3 id="23-generative-tasks"><strong>2.3. Generative Tasks</strong></h3>
<p>Variational Autoencoders (VAEs) can <strong>generate new data</strong>. By sampling points from the learned latent space, the decoder can create new, plausible data samples that resemble the original training data.</p>
<h3 id="24-anomaly-detection-and-facial-recognition"><strong>2.4. Anomaly Detection and Facial Recognition</strong></h3>
<p>Autoencoders are excellent for detecting outliers. Trained only on &quot;normal&quot; data, they produce a <strong>high reconstruction error</strong> for anomalous inputs, signaling a deviation. This can be used for fraud detection or confirming a genuine match.</p>
<hr>
<h2 id="1-개요"><strong>1. 개요</strong></h2>
<h3 id="11-정의"><strong>1.1. 정의</strong></h3>
<p><strong>오토인코더(Autoencoder)</strong></p>
<ul>
<li>데이터를 저차원 표현으로 압축(인코딩)하고</li>
<li>다시 원본 형태로 복원(디코딩)하도록 학습하는 비지도 학습 신경망. </li>
<li>스스로 자기 자신의 입력을 재구성하고 압축된 <em>잠재 공간</em>에 데이터의 가장 본질적인(essential) 특징을 학습하는 것을 주요 목표로 함.</li>
</ul>
<h3 id="12-종류"><strong>1.2. 종류</strong></h3>
<p>데이터 조건과 환경 등에 맞추어 여러 버전의 오토인코더가 있음.</p>
<ul>
<li><strong>과소완전 오토인코더 (Undercomplete Autoencoders)</strong>: 가장 단순한 형태. 병목 계층이 입력보다 작아 네트워크가 차원 축소를 위해 가장 두드러진 특징을 학습하도록 강제함.</li>
<li><strong>정규화 오토인코더 (Regularized Autoencoders)</strong>: 과적합을 방지하고 더 강한 특징을 학습하기 위해 정규화 기법을 사용. 더 넓은 범위이며 아래 오토인코더들 포함</li>
<li><strong>희소 오토인코더 (Sparse Autoencoders)</strong>: 한 번에 활성화될 수 있는 뉴런의 수를 제한. =&gt; 네트워크가 큰 용량을 가지면서도 다른 노드로 특정 특징을 학습하도록 강제함.</li>
<li><strong>잡음 제거 오토인코더 (Denoising Autoencoders)</strong>: 부분적으로 손상된 입력으로부터 깨끗한 원본 입력을 재구성하도록 학습됨. 이는 모델이 강건한(robust) 특징을 배우고 노이즈를 무시하도록 강제함.</li>
<li><strong>축소 오토인코더 (Contractive Autoencoders)</strong>: 입력 데이터의 작은 변화에 둔감하도록 설계 =&gt; 모델이 사소한 디테일보다 근본적인 구조를 포착하는 특징을 학습하도록 함.</li>
<li><strong>변이형 오토인코더 (Variational Autoencoders)</strong>: 데이터를 나타내는 확률 분포의 매개변수를 학습 =&gt; 잠재 공간 분포에서 샘플링하여 (새로운 데이터를 생성할 수 있는) 생성 모델이 됨.</li>
</ul>
<h3 id="13-구조"><strong>1.3. 구조</strong></h3>
<p>오토인코더의 구조는 인코더와 디코더, 두 가지 주요 부분으로 구성됨.</p>
<h4 id="인코더-encoder"><strong>인코더 (Encoder)</strong></h4>
<p>입력 데이터를 <strong>압축</strong>하는 역할. 고차원 입력을 받아 점진적으로 차원을 축소하는 신경망 층을 통과시킴. 최종 출력은 데이터의 압축된 저차원 표현이며, <strong>병목(bottleneck)</strong> 또는 <strong>잠재 표현(latent representation)</strong> 이라 말함.</p>
<h4 id="디코더-decoder"><strong>디코더 (Decoder)</strong></h4>
<p>압축된 표현으로부터 원본 데이터를 <strong>복원</strong>하는 역할. 인코더의 저차원 출력을 받아 점진적으로 차원을 확대하는 신경망 층을 통과시켜, 가능한 한 원본 입력과 가깝게 재구성하는 것을 목표로 함.</p>
<h4 id="비교-인코더-vs-디코더"><strong>비교: 인코더 vs. 디코더</strong></h4>
<table>
<thead>
<tr>
<th align="left">특징</th>
<th align="left"><strong>인코더</strong></th>
<th align="left"><strong>디코더</strong></th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>목적</strong></td>
<td align="left">데이터를 잠재 표현으로 압축</td>
<td align="left">잠재 표현으로부터 데이터 복원</td>
</tr>
<tr>
<td align="left"><strong>구조</strong></td>
<td align="left">신경망 층이 진행될수록 뉴런 수 감소</td>
<td align="left">신경망 층이 진행될수록 뉴런 수 증가</td>
</tr>
<tr>
<td align="left"><strong>입력 &amp; 출력</strong></td>
<td align="left"><strong>입력:</strong> 원본 데이터 <strong>출력:</strong> 잠재 표현</td>
<td align="left"><strong>입력:</strong> 잠재 표현 <strong>출력:</strong> 복원된 데이터</td>
</tr>
</tbody></table>
<hr>
<h2 id="2-적용-분야"><strong>2. 적용 분야</strong></h2>
<p>오토인코더는 비지도 방식으로 데이터의 <em>근본적인 구조</em>를 학습하는 것이 유용한 작업에 매우 적합함.</p>
<h3 id="21-차원-축소"><strong>2.1. 차원 축소</strong></h3>
<p>데이터의 압축된 표현을 학습하여 데이터셋의 특징 수를 줄이는 데 사용. <strong>데이터 시각화</strong>에 유용하며 다른 모델의 <strong>성능을 향상</strong>시킬 수 있음.</p>
<h3 id="22-이미지-및-오디오-노이즈-제거"><strong>2.2. 이미지 및 오디오 노이즈 제거</strong></h3>
<p>깨끗한 데이터로 학습시킨 후 노이즈가 낀 입력을 정리하는 데 사용. 손상된 입력으로부터 깨끗한 버전을 재구성하여 효과적으로 <strong>노이즈를 필터링함</strong>.</p>
<h3 id="23-생성"><strong>2.3. 생성</strong></h3>
<p>변이형 오토인코더(VAE)는 <strong>새로운 데이터를 생성</strong>할 수 있음. 학습된 잠재 공간에서 포인트를 샘플링하여, 디코더가 원본 학습 데이터와 유사한 새로운 데이터를 만들어 냄.</p>
<h3 id="24-이상-탐지-및-얼굴-인식"><strong>2.4. 이상 탐지 및 얼굴 인식</strong></h3>
<p>이상치를 탐지하는 데 탁월함. &quot;정상&quot; 데이터로만 학습되어 비정상적 입력에 대해 <strong>높은 재구성 오류</strong>를 생성하며, 이는 편차를 나타내는 신호가 됨. 사기 탐지나 진위 여부 확인에 사용될 수 있음.</p>
<hr>
<hr>
<p>Reference
<a href="https://en.wikipedia.org/wiki/File:Autoencoder_schema.png">Image</a>
<a href="https://www.ibm.com/think/topics/autoencoder">https://www.ibm.com/think/topics/autoencoder</a>
<a href="https://en.wikipedia.org/wiki/Autoencoder">https://en.wikipedia.org/wiki/Autoencoder</a>
<a href="https://www.v7labs.com/blog/autoencoders-guide">https://www.v7labs.com/blog/autoencoders-guide</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] CNN_layers CNN레이어]]></title>
            <link>https://velog.io/@sujikim-hattoo/DL-CNNlayers-CNN%EB%A0%88%EC%9D%B4%EC%96%B4</link>
            <guid>https://velog.io/@sujikim-hattoo/DL-CNNlayers-CNN%EB%A0%88%EC%9D%B4%EC%96%B4</guid>
            <pubDate>Sun, 17 Aug 2025 15:07:00 GMT</pubDate>
            <description><![CDATA[<pre><code> This writing is provided in English first, followed by Korean.
이 글은 영어 -&gt; 한국어 순으로 작성되어 있습니다.</code></pre><p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/792d94da-98e3-4293-91c5-bfcde144ccb9/image.png" alt=""></p>
<h3 id="1-input-layer">1. Input Layer</h3>
<ul>
<li>Role: Accepts the raw pixel values of an image, typically represented as a matrix of (height x width x color channels).</li>
</ul>
<h3 id="2-convolutional-layers">2. Convolutional layers</h3>
<ul>
<li>Role: These are the core building blocks of a CNN. They use &#39;kernels&#39; (or filters) to convolve the input, extracting key features like edges, corners, and textures. The result is then passed to the next layer.</li>
<li>Benefit: They can extract essential features while preserving the spatial relationships between pixels.s</li>
</ul>
<h3 id="3-activation-function">3. Activation Function</h3>
<ul>
<li>Role: Introduces non-linearity to the model. This allows the network to learn more complex patterns, which improves calculation effectiveness and accuracy.</li>
</ul>
<h3 id="4-pooling-layers">4. Pooling layers</h3>
<ul>
<li>Role: Reduce the spatial dimensions (width and height) of the feature maps while retaining the most important information.</li>
<li>Benefit: This decreases the computational load, helps mitigate overfitting, and improves the model&#39;s generalization ability.</li>
<li>Types:<pre><code>  - Max Pooling: Selects the maximum value from each patch of the feature map.
  - Average Pooling: Calculates the average value from each patch of the feature map.</code></pre></li>
</ul>
<h3 id="5-fully-connected-layers">5. Fully Connected Layers</h3>
<ul>
<li>Role: Connects every neuron from the previous layer to every neuron in the current layer. This layer takes the high-level features extracted by the previous layers and uses them to make the final classification decisions.</li>
</ul>
<h3 id="6-output-layer">6. Output Layer</h3>
<ul>
<li>Role: Generates the final output of the network, such as a probability distribution for classification tasks, based on the features learned throughout the network.</li>
</ul>
<hr>
<h3 id="1-입력층-input-layer">1. 입력층 (Input Layer)</h3>
<ul>
<li>역할: 이미지의 원본 픽셀 값(색상 채널 x 높이 x 너비 x 깊이 )을 받는 곳</li>
</ul>
<h3 id="2-합성곱층-convolutional-layers">2. 합성곱층 (Convolutional Layers)</h3>
<ul>
<li><p>역할: CNN의 핵심 구성 요소. &#39;커널&#39; 또는 &#39;필터&#39;를 사용 -&gt; 입력 데이터에 대한 합성곱 연산 -&gt; 특징(feature) 추출 및 결과를 다음 계층으로 전달.</p>
</li>
<li><p>장점: 이미지의 공간적 구조를 유지하면서 핵심 특징을 효과적으로 추출 가능</p>
</li>
</ul>
<h3 id="3-활성화-함수-activation-function">3. 활성화 함수 (Activation Function)</h3>
<ul>
<li>역할: 모델에 비선형성(non-linearity) 추가 -&gt; 계산 효율성과 정확도 높임. 이를 통해 더 복잡한 패턴을 학습 가능.</li>
</ul>
<h3 id="4-풀링층-pooling-layers">4. 풀링층 (Pooling Layers)</h3>
<ul>
<li><p>역할: 특징 맵(feature map)의 필수 정보는 유지 + 차원(주로 가로, 세로)을 축소</p>
</li>
<li><p>장점: 계산량 줄이기 &amp; 과적합(overfitting) 방지 &amp; 모델 일반화 성능 향상</p>
</li>
<li><p>종류:</p>
<ul>
<li>최대 풀링 (Max Pooling): 특정 영역에서 가장 큰 값을 선택</li>
<li>평균 풀링 (Average Pooling): 특정 영역 값들의 평균을 계산하여 선택</li>
</ul>
</li>
</ul>
<h3 id="5-완전-연결-계층-fully-connected-layers">5. 완전 연결 계층 (Fully Connected Layers)</h3>
<ul>
<li>역할: 이전 계층의 모든 뉴런을 다음 계층의 모든 뉴런에 연결하여 최종적인 결정을 내림</li>
</ul>
<h3 id="6-출력층-output-layer">6. 출력층 (Output Layer)</h3>
<ul>
<li>역할: 학습된 특징들을 바탕으로 최종 예측 값이나 분류 결과를 생성</li>
</ul>
<hr>
<hr>
<p>Reference 참고
<a href="https://images.app.goo.gl/Rtf1xmaVMmLaBTZNA">Image Reference 이미지 출처</a>
<a href="https://www.ibm.com/think/topics/convolutional-neural-networks">https://www.ibm.com/think/topics/convolutional-neural-networks</a>
<a href="https://blog.lukmaanias.com/2024/12/18/convolutional-neural-networks-cnn-an-in-depth-exploration/">https://blog.lukmaanias.com/2024/12/18/convolutional-neural-networks-cnn-an-in-depth-exploration/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] Pytorch Tensor vs Numpy Array]]></title>
            <link>https://velog.io/@sujikim-hattoo/DL-Pytorch-Tensor-vs-Numpy-Array</link>
            <guid>https://velog.io/@sujikim-hattoo/DL-Pytorch-Tensor-vs-Numpy-Array</guid>
            <pubDate>Sun, 10 Aug 2025 23:35:59 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/649f9319-43c0-498c-ac17-373f65d95003/image.png" alt=""></p>
<pre><code>* The following content is written in English, then in Korean.
* 아래 글은 영어 -&gt; 한국어 순으로 작성되어 있습니다.</code></pre><h2 id="1-definition">1. Definition</h2>
<h3 id="11-pytorch-tensor">1.1 PyTorch Tensor</h3>
<ul>
<li><code>import torch; torch.tensor()</code></li>
<li>The fundamental data structure in PyTorch.</li>
<li>An n-dimensional array optimized for deep learning operations.</li>
<li>Primary Use: Building and training deep learning models.</li>
</ul>
<h3 id="12-numpy-array">1.2 NumPy Array</h3>
<ul>
<li><code>import numpy as np; np.array()</code></li>
<li>The fundamental data structure for numerical computing in Python.</li>
<li>An n-dimensional array for general-purpose scientific computation.</li>
<li>Primary Use: Scientific computing (data analysis, linear algebra, etc.).</li>
</ul>
<h2 id="2-comparison">2. Comparison</h2>
<h3 id="21-common-points">2.1 Common Points</h3>
<ul>
<li>Represent n-dimensional numerical data.</li>
<li>Homogeneous (store elements of a single data type).</li>
<li>Easily converted between each other (<code>.numpy()</code>, <code>torch.from_numpy()</code>).</li>
</ul>
<h3 id="22-differences">2.2 Differences</h3>
<ul>
<li><strong>Hardware Acceleration (GPU Usage):</strong><ul>
<li>Tensor: Optimized for GPU operations (accelerates deep learning).<ul>
<li>Array: Limited to CPU operations.</li>
</ul>
</li>
</ul>
</li>
<li><strong>Automatic Differentiation:</strong><ul>
<li>Tensor: Built-in <code>autograd</code> engine (essential for training neural networks).</li>
<li>Array: No built-in autograd functionality.</li>
</ul>
</li>
<li><strong>Ecosystem Integration:</strong><ul>
<li>Tensor: Integrated with the PyTorch ecosystem (e.g., <code>torch.nn</code>, optimizers).</li>
<li>Array: Integrated with the scientific computing ecosystem (e.g., Scikit-learn, Pandas).</li>
</ul>
</li>
</ul>
<h2 id="3-conclusion">3. Conclusion</h2>
<p>Use PyTorch Tensors for deep learning models and GPU-accelerated tasks; use NumPy Arrays for general-purpose scientific computing and data analysis.</p>
<hr>
<h2 id="1-정의">1. 정의</h2>
<h3 id="11-pytorch-tensor-1">1.1 PyTorch Tensor</h3>
<ul>
<li><code>import torch; torch.tensor()</code></li>
<li>파이토치의 기본 데이터 구조.</li>
<li>딥러닝 연산에 최적화된 N차원 배열.</li>
<li>주로 딥러닝 모델 구축 및 훈련에 사용</li>
</ul>
<h3 id="12-numpy-array-1">1.2 NumPy Array</h3>
<ul>
<li><code>import numpy as np; np.array()</code></li>
<li>파이썬 수치 연산의 기본 데이터 구조.</li>
<li>범용 과학 계산을 위한 N차원 배열.</li>
<li>주로 계산 과학(scientific computic - 데이터 분석, 선형대수 등)에 사용</li>
</ul>
<h2 id="2-비교">2. 비교</h2>
<h3 id="21-공통점">2.1 공통점</h3>
<ul>
<li>N차원 수치 데이터 표현.</li>
<li>동일한 데이터 타입만 저장 (Homogeneous).</li>
<li>상호 변환 용이 (<code>.numpy()</code>, <code>torch.from_numpy()</code>).</li>
</ul>
<h3 id="22-차이점">2.2 차이점</h3>
<ul>
<li><strong>하드웨어 가속 (GPU 사용 여부):</strong><ul>
<li>Tensor: CPU 연산도 가능하지만 GPU 연산도 가능(GPU 연산에 최적화 -&gt; 딥러닝 가속).</li>
<li>Array: CPU 연산에 제한됨.</li>
</ul>
</li>
<li><strong>자동 미분:</strong><ul>
<li>Tensor: 자동 미분 기능(<code>autograd</code>) 내장 (신경망 학습에 필수).</li>
<li>Array: 자동 미분 기능 없음.</li>
</ul>
</li>
<li><strong>생태계:</strong><ul>
<li>Tensor: PyTorch 생태계와 연결 (<code>torch.nn</code>, 옵티마이저 등).</li>
<li>Array: Scientific 생태계와 연결 (Scikit-learn, Pandas 등).</li>
</ul>
</li>
</ul>
<h2 id="3-결론">3. 결론</h2>
<ul>
<li>딥러닝 모델과 GPU 가속 작업 -&gt; PyTorch Tensor</li>
<li>일반적인 Sceintific computing 및 데이터 분석 -&gt; NumPy Array를 사용</li>
</ul>
<hr>
<hr>
<p>Reference Link 참고 링크
<a href="https://www.kaggle.com/code/amirmotefaker/pytorch-vs-numpy">https://www.kaggle.com/code/amirmotefaker/pytorch-vs-numpy</a>
<a href="https://www.geeksforgeeks.org/deep-learning/pytorch-tensor-vs-numpy-array/">https://www.geeksforgeeks.org/deep-learning/pytorch-tensor-vs-numpy-array/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DL] PyTorch vs. Tensorflow]]></title>
            <link>https://velog.io/@sujikim-hattoo/DL-PyTorch-vs.-Tensorflow</link>
            <guid>https://velog.io/@sujikim-hattoo/DL-PyTorch-vs.-Tensorflow</guid>
            <pubDate>Sun, 10 Aug 2025 16:00:43 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/03d1452e-ae6c-44fb-84df-dd11b266bb46/image.png" alt=""></p>
<pre><code>* The following content is written in English, then in Korean.
* 아래 글은 영어 -&gt; 한국어 순으로 작성되어 있습니다.</code></pre><h2 id="1-basic-information">1. Basic Information</h2>
<h3 id="11-pytorch">1.1 PyTorch</h3>
<ul>
<li>Developed by: Meta (formerly Facebook)</li>
<li>Keywords: Pythonic, Dynamic Graph (Define-by-Run), Intuitive, Flexible</li>
<li>Usage: Strong in research, experimentation, and education.</li>
</ul>
<h3 id="12-tensorflow">1.2 TensorFlow</h3>
<ul>
<li>Developed by: Google</li>
<li>Keywords: End-to-end Platform, Static Graph (Define-and-Run), Deployment &amp; Scalability</li>
<li>Usage: Strong in large-scale production and real-world services.</li>
</ul>
<h2 id="2-comparison">2. Comparison</h2>
<h3 id="21-common-points">2.1 Common Points</h3>
<ul>
<li>Basic Unit: Tensor</li>
<li>Purpose: Open-source frameworks for ML/DL.</li>
<li>Modern Trend: Both are evolving to support features from the other, closing the gap between them.</li>
</ul>
<h3 id="22-differences">2.2 Differences</h3>
<ul>
<li><p><strong>Computational Graph &amp; Debugging</strong>:</p>
<ul>
<li>PyTorch: Uses a Dynamic Graph (Define-by-Run). This allows for more intuitive, Python-style coding and makes debugging significantly easier.</li>
<li>TensorFlow: Uses a Static Graph (Define-and-Run), which is optimized for performance and deployment.(Since TF 2.x, Eager Execution has been the default, enabling intuitive coding similar to PyTorch)</li>
</ul>
</li>
<li><p><strong>Ecosystem &amp; Deployment</strong>:</p>
<ul>
<li>PyTorch: Strong presence in the research community, with an ecosystem for production that is expanding rapidly.</li>
<li>TensorFlow: Holds an advantage in production, possessing a mature and comprehensive suite of deployment tools (TensorFlow Serving, TFX, TF Lite).</li>
</ul>
</li>
</ul>
<h2 id="3-conclusion-which-one-is-better">3. Conclusion: Which one is better?</h2>
<p>There is no absolute winner; the choice depends on the project&#39;s primary goal.</p>
<ul>
<li>For Research &amp; Flexibility → PyTorch is often preferred for its intuitive coding and easy debugging.</li>
<li>For Production &amp; Scalability → TensorFlow is often chosen for its mature deployment tools and ecosystem.</li>
</ul>
<p>As an AI engineer, understanding the core concepts of both is a major advantage :&gt;</p>
<hr>
<hr>
<h2 id="1-기본-정보">1. 기본 정보</h2>
<h3 id="11-pytorch-파이토치">1.1 PyTorch (파이토치)</h3>
<ul>
<li>개발사: Meta (구 페이스북)</li>
<li>키워드: Pythonic(파이썬다운), 동적 그래프 (Define-by-Run), 직관적, 유연함</li>
<li>주요 용도: 연구, 실험, 교육 분야에서 강세</li>
</ul>
<h3 id="12-tensorflow-텐서플로우">1.2 TensorFlow (텐서플로우)</h3>
<ul>
<li>개발사: Google (구글)</li>
<li>키워드: End-to-End 플랫폼, 정적 그래프 (Define-and-Run), 배포 및 확장성</li>
<li>주요 용도: 대규모 상용 서비스 및 실제 프로덕션 환경에서 강세</li>
</ul>
<h2 id="2-비교">2. 비교</h2>
<h3 id="21-공통점">2.1 공통점</h3>
<ul>
<li>기본 단위: 텐서(Tensor)</li>
<li>목적: 오픈소스 머신러닝/딥러닝 프레임워크</li>
<li>최신 경향: 서로의 장점을 흡수하며 두 프레임워크 간의 격차가 줄어드는 추세</li>
</ul>
<h3 id="22-차이점">2.2 차이점</h3>
<ul>
<li><p><strong>계산 그래프와 디버깅</strong>:</p>
<ul>
<li>PyTorch: 동적 그래프 (Define-by-Run) 방식. 코드가 직관적이고 파이썬 문법과 유사해 디버깅이 매우 쉬움.</li>
<li>TensorFlow: 정적 그래프 (Define-and-Run) 방식. 성능 및 배포에 최적화.(TF 2.x부터 즉시 실행하는 것이 기본이 되어 PyTorch처럼 직관적인 코딩이 가능하게 됨..!)</li>
</ul>
</li>
<li><p><strong>생태계와 배포</strong>:</p>
<ul>
<li>PyTorch: 연구 커뮤니티 중심으로 강하며, 프로덕션을 위한 생태계가 빠르게 확장되고 있음.</li>
<li>TensorFlow: 프로덕션(상용화) 환경에서 강점을 가지며, 성숙하고 종합적인 배포 도구(TensorFlow Serving, TFX, TF Lite 등)를 보유함.</li>
</ul>
</li>
</ul>
<h2 id="3-결론-그래서-어떤-것을-선택해야-하는가">3. 결론: 그래서 어떤 것을 선택해야 하는가?</h2>
<p>절대적인 승자는 없다! 프로젝트 핵심 목표에 따라 선택은 달라진다.</p>
<ul>
<li>연구 및 유연성 → PyTorch: 직관적인 코드와 쉬운 디버깅으로 선호됨.</li>
<li>프로덕션 및 확장성 → TensorFlow: 성숙한 배포 도구와 생태계로 선호됨.</li>
</ul>
<p>결론적으로 AI 엔지니어가 되려면 두 프레임워크의 핵심 개념을 모두 이해하고 다룰 줄 아는 것이 중요합니다 :&gt;</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[LeetCode #1] Two Sum: From O(n²) to O(n) with a Dictionary]]></title>
            <link>https://velog.io/@sujikim-hattoo/LeetCode-1-Two-Sum-From-On-to-On-with-a-Dictionary</link>
            <guid>https://velog.io/@sujikim-hattoo/LeetCode-1-Two-Sum-From-On-to-On-with-a-Dictionary</guid>
            <pubDate>Sat, 09 Aug 2025 09:15:29 GMT</pubDate>
            <description><![CDATA[<h3 id="first-try">First try</h3>
<ul>
<li>Insitnct: Simply check every possible pair of numeber in the list. I used two nested <code>for</code> loops to accomplish this.</li>
</ul>
<pre><code>class Solution:
    def twoSum(self, nums: List[int], target: int) -&gt; List[int]:
        ans = []

        for i, num1 in enumerate(nums):
            for j, num2 in enumerate(nums):
                if i &lt; j and num1 + num2 == target:
                    ans.append(i)
                    ans.append(j)

        return ans</code></pre><p><img src="https://velog.velcdn.com/images/sujikim-hattoo/post/b068e00e-3a3d-4a33-814c-e525851846d6/image.png" alt=""></p>
<p>Problem: The two nested loops result in a time complexity of O(n^2). This is because for every element, the inner loop has to scan the entire list again, making it very slow for large inputs.</p>
<h3 id="second-try">Second try</h3>
<ul>
<li><p>Instinct: My next thought was to avoid the inner loop. For each number, I could calculate its complement (target - num) and then use Python&#39;s in and .index() to check if it exists in the list. </p>
<pre><code>class Solution:
  def twoSum(self, nums: List[int], target: int) -&gt; List[int]:
      ans = []

      for i, num in enumerate(nums):
          if ((target - num) in nums) and (nums.index(target-num) &gt; i) :
              ans.append(i)
              ans.append(nums.index(target-num))

      return ans
</code></pre></li>
</ul>
<pre><code>
Problem: `.index(value)` always find the *first* occurrence of `value` in the list &amp; still doesn&#39;t solve time complexity problem

### Third try
- Instinct:  Instead of a list, I used a `dictionary` to store the numbers I&#39;d already seen.

&gt; Q. Why `dictionary` is better than `list` in terms of `time complexity?`

&gt; A. There is difference between `dictionary` and `list` about *how they store and retrieve data.* 
- `dictionary` : Use a &#39;direct lookup&#39; system using a key (Hashing, O(1)) (e.g. using a book&#39;s index to find a topic in a book)
- `list`: Use a &#39;search every item&#39; system(Linear scan, O(n)) (e.g. reading a book page-by-page to do same thing)
</code></pre><p>class Solution:
    def twoSum(self, nums: List[int], target: int) -&gt; List[int]:
        for i, num in enumerate(nums):
            if num not in seen_numbers.keys():
                seen_numbers[target-num] = i
            elif num in seen_numbers.keys():
                result.append(seen_numbers[num])
                result.append(i)</p>
<pre><code>    return result</code></pre><pre><code>Finally it passed!


Problem: But it doesn&#39;t look clean and practical, and I finally realized I missed hint by reading the problem&#39;s description carefully:
&gt; You may assume that each input would have exactly one solution,


### Fourth try
- Instinct: I can return immediately after finding the *first* valid pair, which simplifies the logic.
</code></pre><p>class Solution:
    def twoSum(self, nums: List[int], target: int) -&gt; List[int]:
        seen_numbers = {}</p>
<pre><code>    for i, num in enumerate(nums):
        if num in seen_numbers:
            return [seen_numbers[num], i]
        else:
            new_element = target - num
            seen_numbers[new_element] = i</code></pre><pre><code>
![](https://velog.velcdn.com/images/sujikim-hattoo/post/24551b06-409d-457f-87f8-8305af205531/image.png)


---
### **Conclusion:** 
This process taught me that I was initially a bit confused about the practical application of a `dictionary` and the importance of edge cases. It&#39;s crucial to consider edge cases, but first of all, it&#39;s essential to *focus on the problem&#39;s definition and constraints.*</code></pre>]]></description>
        </item>
    </channel>
</rss>