Skip to content

Commit 661ea4e

Browse files
authored
Merge pull request #61 from edumgt/copilot/enhance-docs-with-tensorflow
docs: supplement TensorFlow/TensorBoard/Keras/KoNLPy/마르코프체인/LSTM 텍스트 생성 내용 보완
2 parents 5be10c1 + 4d499ea commit 661ea4e

3 files changed

Lines changed: 426 additions & 0 deletions

File tree

docs/03.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,92 @@ RNN, LSTM, Transformer는 각각 **기억하는 범위와 방식**이 다릅니
240240
`model="nn"` 으로 실행하면 응답에 `nn_viz` 가 함께 들어와 뉴런 연결 그림을 그릴 수 있습니다.
241241

242242
즉, 현재 웹앱이 RNN/LSTM/Transformer를 직접 학습하진 않아도, **시계열에서는 순서를 지키는 처리**를 가장 먼저 실천하고 있습니다.
243+
244+
---
245+
246+
## LSTM 텍스트 생성: 시계열 모델을 언어에 적용하기
247+
248+
LSTM은 주가 시계열뿐 아니라 **텍스트(문자·단어 시퀀스)** 에도 그대로 적용할 수 있습니다.
249+
문자 하나하나를 시점(time step)으로 보면, LSTM이 앞 문자들의 패턴을 기억하며 다음 문자를 예측합니다.
250+
251+
### 문자 단위 LSTM 언어 모델
252+
253+
```python
254+
from tensorflow import keras
255+
import numpy as np
256+
257+
# 텍스트를 40글자씩 잘라 입력, 41번째 글자가 정답
258+
SEQ_LEN = 40
259+
step = 3
260+
261+
# 문자 → 정수 인덱스 변환
262+
chars = sorted(set(text))
263+
char2id = {c: i for i, c in enumerate(chars)}
264+
265+
sequences, next_chars = [], []
266+
for i in range(0, len(text) - SEQ_LEN, step):
267+
sequences.append(text[i:i + SEQ_LEN])
268+
next_chars.append(text[i + SEQ_LEN])
269+
270+
# one-hot 인코딩
271+
X = np.zeros((len(sequences), SEQ_LEN, len(chars)), dtype=np.float32)
272+
y = np.zeros((len(sequences), len(chars)), dtype=np.float32)
273+
for i, seq in enumerate(sequences):
274+
for t, c in enumerate(seq):
275+
X[i, t, char2id[c]] = 1
276+
y[i, char2id[next_chars[i]]] = 1
277+
278+
# LSTM 모델 정의
279+
model = keras.Sequential([
280+
keras.layers.LSTM(128, input_shape=(SEQ_LEN, len(chars))),
281+
keras.layers.Dense(len(chars), activation='softmax')
282+
])
283+
model.compile(optimizer='adam', loss='categorical_crossentropy')
284+
model.fit(X, y, batch_size=128, epochs=20)
285+
```
286+
287+
### Temperature 샘플링: 창의성 조절
288+
289+
학습된 모델로 문장을 생성할 때 **temperature**를 조절하면 생성 스타일이 달라집니다.
290+
291+
```python
292+
def sample(preds, temperature=1.0):
293+
"""확률 분포에서 다음 문자를 샘플링"""
294+
preds = np.asarray(preds).astype('float64')
295+
preds = np.log(preds) / temperature # temperature로 분포 조절
296+
exp_preds = np.exp(preds)
297+
preds = exp_preds / np.sum(exp_preds)
298+
return np.random.choice(len(preds), p=preds)
299+
```
300+
301+
| temperature 값 | 생성 특성 | 쉬운 비유 |
302+
|---|---|---|
303+
| 0.2 (낮음) | 가장 확률 높은 문자를 자주 선택 → 반복적·안전한 문장 | 모범 답안만 쓰는 학생 |
304+
| 1.0 (기본) | 학습된 확률 분포 그대로 샘플링 | 보통 작성 |
305+
| 1.5 (높음) | 낮은 확률 문자도 자주 선택 → 창의적·불규칙한 문장 | 자유롭게 창작하는 작가 |
306+
307+
### 주가 예측에 연결하면
308+
309+
LSTM 텍스트 생성의 원리를 주가 시계열에 그대로 연결할 수 있습니다.
310+
311+
| 텍스트 생성 | 주가 예측 |
312+
|---|---|
313+
| 앞 40개 문자 → 다음 문자 예측 | 앞 20일 가격·거래량 → 다음 날 등락 예측 |
314+
| 문자 어휘 사전 (one-hot) | 종가·거래량·RSI 등 특성 벡터 |
315+
| temperature로 다양성 조절 | 임계값(threshold)으로 신호 민감도 조절 |
316+
| 에폭별 생성 문장 품질 변화 관찰 | 에폭별 검증 손실 변화로 학습 수렴 확인 |
317+
318+
### LSTM 텍스트 생성 흐름
319+
320+
```mermaid
321+
flowchart TD
322+
A["소설 텍스트\n(BEXX0003.txt)"] --> B["문자 단위 슬라이딩 윈도우\n40글자 → 41번째 글자"]
323+
B --> C["One-Hot 인코딩\n문자 → 벡터"]
324+
C --> D["LSTM 학습\n순서 기억 + 다음 문자 확률 출력"]
325+
D --> E["Temperature 샘플링\n다음 문자 선택"]
326+
E --> F["문자를 이어붙여\n새 문장 생성"]
327+
F --> G["에폭마다 temperature 0.2/0.5/1.0/1.2로\n생성 문장 비교 관찰"]
328+
```
329+
330+
> **핵심 포인트**: LSTM은 주가처럼 숫자 시퀀스뿐 아니라 텍스트 시퀀스에도 적용됩니다.
331+
> "앞 시점들을 기억해 다음 값을 예측한다"는 원리는 동일하며, 입력·출력 형태만 달라집니다.

docs/07.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,143 @@ outputs = model(**inputs)
258258
```
259259

260260
> BERT는 `transformers` 라이브러리와 PyTorch가 필요합니다. 가벼운 실습은 `chapter113`의 TF-IDF 기반 코드를 먼저 사용해 보세요.
261+
262+
---
263+
264+
## KoNLPy: 한국어 형태소 분석 라이브러리
265+
266+
**KoNLPy**(Korean NLP in Python)는 한국어 자연어 처리를 위한 파이썬 라이브러리입니다.
267+
한국어는 조사·어미가 단어에 붙어 변형되는 교착어라서, 영어처럼 공백으로 단순하게 나눌 수 없습니다.
268+
KoNLPy는 이런 한국어 특성을 다루는 **형태소 분석기**를 한 곳에 모아 제공합니다.
269+
270+
### 대표 형태소 분석기
271+
272+
| 분석기 | 특징 | 활용 상황 |
273+
|---|---|---|
274+
| **Okt** (Open Korean Text) | 속도가 빠르고 SNS·비정형 텍스트에 강함 | 뉴스 댓글, 주식 커뮤니티 텍스트 분석 |
275+
| **Kkma** (꼬꼬마) | 정밀도가 높고 학술적 텍스트 분석에 강함 | 논문, 공문서, 정밀 분류 |
276+
| **Mecab** | 속도가 가장 빠르고 대용량 처리에 유리 | 대규모 코퍼스 전처리 |
277+
278+
### Okt 기본 사용 예시
279+
280+
```python
281+
from konlpy.tag import Okt
282+
283+
okt = Okt()
284+
285+
sentence = "삼성전자 주가가 오늘 크게 올랐습니다."
286+
287+
# 형태소 분리
288+
morphs = okt.morphs(sentence)
289+
# → ['삼성전자', '주가', '가', '오늘', '크게', '올랐습니다', '.']
290+
291+
# 품사 태깅 (형태소 + 품사)
292+
pos = okt.pos(sentence)
293+
# → [('삼성전자', 'Noun'), ('주가', 'Noun'), ('가', 'Josa'),
294+
# ('오늘', 'Noun'), ('크게', 'Adverb'), ('올랐습니다', 'Verb'), ('.', 'Punctuation')]
295+
296+
# 명사만 추출
297+
nouns = okt.nouns(sentence)
298+
# → ['삼성전자', '주가', '오늘']
299+
```
300+
301+
### 주식 뉴스 분석에 활용하면
302+
303+
```python
304+
from konlpy.tag import Okt
305+
from collections import Counter
306+
307+
okt = Okt()
308+
news = "반도체 수출이 증가하며 삼성전자와 SK하이닉스 주가가 동반 상승했습니다."
309+
310+
# 명사만 추출해 키워드 분석
311+
nouns = okt.nouns(news)
312+
keyword_count = Counter(nouns)
313+
# → Counter({'삼성전자': 1, '반도체': 1, '수출': 1, '주가': 1, ...})
314+
```
315+
316+
> **핵심 포인트**: KoNLPy는 한국어 텍스트를 의미 단위(형태소)로 쪼개는 도구입니다.
317+
> 뉴스, 공시, 커뮤니티 글에서 **핵심 키워드를 추출**하거나 **BoW(단어 가방) 벡터**를 만들 때 첫 번째 전처리 단계로 사용됩니다.
318+
319+
### KoNLPy 처리 흐름
320+
321+
```mermaid
322+
flowchart TD
323+
A["한국어 텍스트 입력\n'삼성전자 주가가 올랐습니다'"] --> B["형태소 분석\nOkt.pos()"]
324+
B --> C["형태소 + 품사 목록\n[('삼성전자','Noun'), ('주가','Noun'), ...]"]
325+
C --> D["명사/동사 필터링\n불필요한 조사·어미 제거"]
326+
D --> E["정제된 키워드 목록\n['삼성전자', '주가', '상승']"]
327+
E --> F["단어 빈도 계산 또는\nWord2Vec / TF-IDF 입력"]
328+
```
329+
330+
---
331+
332+
## 마르코프체인(Markov Chain): 통계 기반 텍스트 생성
333+
334+
**마르코프체인**은 신경망 없이 **현재 상태만 보고 다음 상태를 확률적으로 예측**하는 통계 모델입니다.
335+
텍스트 생성에서는 "앞 단어(들)가 주어졌을 때, 다음 단어가 무엇일 확률이 높은가?"를 학습한 뒤 문장을 만들어냅니다.
336+
337+
### 직관적인 이해
338+
339+
| 방식 | 기억 범위 | 예시 |
340+
|---|---|---|
341+
| 1-gram (Unigram) | 이전 상태 0개 | 단어를 완전 무작위 선택 |
342+
| 2-gram (Bigram) | 이전 단어 1개 | "삼성" 다음엔 "전자"가 자주 옴 |
343+
| 3-gram (Trigram) | 이전 단어 2개 | "삼성전자 주가" 다음엔 "상승"이 자주 옴 |
344+
345+
```python
346+
import random
347+
from collections import defaultdict
348+
from konlpy.tag import Okt
349+
350+
okt = Okt()
351+
352+
def build_markov_chain(text, n=3):
353+
"""n-gram 마르코프체인 딕셔너리 구축"""
354+
tokens = okt.pos(text) # 형태소 + 품사 분리
355+
chain = defaultdict(list)
356+
for i in range(len(tokens) - n):
357+
key = tuple(tokens[i:i+n]) # n개 토큰을 키로 사용
358+
chain[key].append(tokens[i+n]) # 다음 토큰을 값으로 저장
359+
return chain
360+
361+
def generate_text(chain, n=3, length=20):
362+
"""마르코프체인으로 문장 생성"""
363+
start = random.choice(list(chain.keys()))
364+
result = list(start)
365+
for _ in range(length):
366+
key = tuple(result[-n:])
367+
if key not in chain:
368+
break
369+
next_token = random.choice(chain[key])
370+
result.append(next_token)
371+
return "".join([word for word, _ in result])
372+
```
373+
374+
### 마르코프체인 vs LSTM 비교
375+
376+
| 비교 항목 | 마르코프체인 | LSTM |
377+
|---|---|---|
378+
| 학습 방식 | 통계(빈도 카운팅) | 신경망(역전파 학습) |
379+
| 문맥 범위 | 고정 n개 이전 토큰만 | 긴 시퀀스 전체를 기억 |
380+
| 계산 비용 | 매우 낮음 | 높음(GPU 권장) |
381+
| 생성 품질 | 어색한 문장 빈도가 높음 | 더 자연스러운 문장 생성 |
382+
| 해석 가능성 | 높음(빈도 테이블로 확인 가능) | 낮음(블랙박스) |
383+
| 활용 | 빠른 프로토타입, 교육 목적 | 실제 언어모델, 챗봇 등 |
384+
385+
### 주식 투자에 연결하면
386+
387+
마르코프체인의 "이전 상태 → 다음 상태 확률" 구조는 주가 흐름에도 적용할 수 있습니다.
388+
389+
```
390+
상승 → 상승 : 55%
391+
상승 → 하락 : 45%
392+
하락 → 상승 : 42%
393+
하락 → 하락 : 58%
394+
```
395+
396+
이렇게 만들어 두면 "오늘 상승했을 때 내일 또 상승할 확률"을 간단하게 추정할 수 있습니다.
397+
(단, 실제 주가는 이보다 훨씬 복잡한 요인이 작용하므로 단독 활용은 주의가 필요합니다.)
398+
399+
> **핵심 포인트**: 마르코프체인은 신경망 이전 방식의 텍스트·시퀀스 생성 모델입니다.
400+
> LSTM이나 Transformer보다 단순하지만 계산 비용이 낮고 원리가 명확해, NLP 입문 실습과 빠른 프로토타입에 자주 사용됩니다.

0 commit comments

Comments
 (0)