Commit 4c627a3d authored by insun park's avatar insun park
Browse files

docs: 머신러닝 및 딥러닝 파트에 모델 종류, 과적합 및 평가 지표 추가

parent c384e1fe
# Part 2: 파이썬 핵심 문법 마스터하기
**⬅️ 이전 시간: [Part 1: AI 개발 환경 완벽 구축 가이드](../01_ai_development_environment/part_1_ai_development_environment.md)**
**➡️ 다음 시간: [Part 3: 파이썬 컬렉션, 더 깊게 이해하기](../03_python_collections/part_3_python_collections.md)**
---
## 1. 학습 목표 (Learning Objectives)
이번 파트가 끝나면, 여러분은 다음을 할 수 있게 됩니다.
- 변수를 선언하고 숫자, 문자열, 불리언 등 기본 자료형을 활용할 수 있습니다.
- [리스트](./glossary.md#리스트-list), [튜플](./glossary.md#튜플-tuple), [딕셔너리](./glossary.md#딕셔너리-dictionary), 셋의 차이점을 이해하고 상황에 맞게 선택하여 사용할 수 있습니다.
- `if`, `for`, `while` 등 제어문을 사용하여 코드의 실행 흐름을 제어할 수 있습니다.
- 코드의 재사용성을 높이는 [함수](./glossary.md#함수-function)를 직접 정의하고, [매개변수](./glossary.md#매개변수-parameter와-인자-argument)[반환 값](./glossary.md#반환-값-return-value)을 활용할 수 있습니다.
- [리스트 컴프리헨션](./glossary.md#리스트-컴프리헨션-list-comprehension)과 같은 파이썬다운(Pythonic) 코드를 작성할 수 있습니다.
## 2. 핵심 키워드 (Keywords)
`변수(Variable)`, `[자료형(Data Type)](./glossary.md#자료구조-data-structure)`, `[리스트(List)](./glossary.md#리스트-list)`, `[튜플(Tuple)](./glossary.md#튜플-tuple)`, `[딕셔너리(Dictionary)](./glossary.md#딕셔너리-dictionary)`, `셋(Set)`, `제어문(Control Flow)`, `[들여쓰기(Indentation)](./glossary.md#들여쓰기-indentation)`, `[함수(Function)](./glossary.md#함수-function)`
## 3. 왜 파이썬 문법이 중요할까요? (Introduction)
AI 개발의 세계에 오신 것을 환영합니다! 파이썬은 AI와 데이터 과학 분야에서 가장 사랑받는 언어입니다. 문법이 간결하고 사람의 생각과 비슷해서, 복잡한 AI 모델의 로직을 직관적으로 표현할 수 있습니다. 이번 주차에는 앞으로 우리가 만들 모든 AI 서비스의 뼈대가 될 파이썬의 가장 핵심적인 문법들을 하나씩 정복해나갑니다. **단순히 문법을 배우는 것을 넘어, 각 문법이 실제 AI 개발 과정에서 어떻게 데이터를 다루고 모델을 조작하는 데 사용되는지**에 초점을 맞출 것입니다.
> [!TIP]
> 이 파트의 모든 코드 예제는 아래 링크의 파이썬 파일에서 직접 실행하고 수정해볼 수 있습니다.
> **실행 가능한 소스 코드: [`part_2_3_python_syntax_collections.py`](../../source_code/part_2_3_python_syntax_collections.py)**
---
## 4. 모든 것의 시작, 변수와 자료형
> **🎯 1일차 목표:** 변수(Variable)를 사용해 데이터를 저장하고, 파이썬의 기본 데이터 종류(자료형)를 이해합니다.
### 4.1. 변수(Variable): 데이터에 이름표 붙이기
<a href="./glossary.md#변수-variable">변수(Variable)</a>는 숫자, 글자 같은 데이터를 저장하는 '상자'입니다. `age = 30` 이라는 코드는, `30`이라는 데이터를 `age`라는 이름의 상자에 넣는다는 뜻입니다. 이제부터 우리는 `age`라는 이름만 부르면 컴퓨터가 알아서 `30`이라는 값을 찾아줍니다.
```python
my_name = "파이" # 문자열 (String)
my_age = 20 # 정수 (Integer)
pi = 3.14 # 실수 (Float)
is_student = True # 불리언 (Boolean)
print(f"안녕하세요, 제 이름은 {my_name}이고 나이는 {my_age}살입니다.")
```
### 4.2. 기본 자료형(Data Types)
파이썬은 데이터의 종류를 구분하며, 이를 <a href="./glossary.md#자료구조-data-structure">자료형</a>이라고 합니다.
- **정수 (Integer)**: `1`, `100`, `-5` 같이 소수점이 없는 숫자.
- **실수 (Float)**: `3.14`, `-0.5` 같이 소수점이 있는 숫자.
- **문자열 (String)****: `"안녕하세요"`, `'Python'` 같이 따옴표로 감싼 글자들.
- **<a href="./glossary.md#boolean">불리언 (Boolean)</a>**: `True` 또는 `False`. 조건의 참/거짓을 나타냅니다.
---
## 5. 여러 데이터를 담는 그릇 (1): 리스트와 튜플
> **🎯 2일차 목표:** 순서가 있는 데이터 묶음인 [리스트(List)](./glossary.md#리스트-list)와 변경이 불가능한 [튜플(Tuple)](./glossary.md#튜플-tuple)을 다루고, [리스트 컴프리헨션](./glossary.md#리스트-컴프리헨션-list-comprehension)으로 파이썬다운 코드를 작성합니다.
### 5.1. 리스트(List): 순서가 있고 변경 가능한 만능 주머니
- 여러 값을 순서대로 저장하는 **변경 가능한** <a href="./glossary.md#자료구조-data-structure">자료구조</a>입니다. (`[]` 사용)
```python
fruits = ["apple", "banana", "cherry"]
fruits[1] = "blueberry" # 값 변경
fruits.append("strawberry") # 요소 추가
print(f"최종 리스트: {fruits}")
```
### 5.2. 파이썬다운 코드: 리스트 컴프리헨션 (List Comprehension)
`for` 반복문을 한 줄로 간결하게 표현하여 새로운 리스트를 만드는 방법입니다. 단순히 코드를 짧게 만드는 기술을 넘어, 대용량 데이터를 빠르고 효율적으로 가공하기 위한 **전문가의 코드 작성 방식**입니다. AI 모델에 입력될 대량의 데이터를 필터링하거나 특정 형태로 변환할 때 매우 유용하게 사용됩니다.
```python
# 0부터 9까지의 숫자 중 짝수만 제곱하여 리스트 만들기
squares = [i**2 for i in range(10) if i % 2 == 0]
print(f"짝수의 제곱 리스트: {squares}") # [0, 4, 16, 36, 64]
```
### 5.3. 튜플(Tuple): 순서가 있지만 변경 불가능한 금고
- 여러 값을 순서대로 저장하는 **변경 불가능한** <a href="./glossary.md#자료구조-data-structure">자료구조</a>입니다. (`()` 사용)
- 한 번 만들어지면 내용을 바꿀 수 없어 안정성이 중요할 때 (e.g., 함수의 반환 값, 좌표) 사용됩니다.
```python
point = (10, 20)
# point[0] = 15 #! TypeError 발생
```
---
## 6. 여러 데이터를 담는 그릇 (2): 딕셔너리와 셋
> **🎯 3일차 목표:** `Key:Value` 쌍으로 데이터를 저장하는 [딕셔너리(Dictionary)](./glossary.md#딕셔너리-dictionary)와 중복을 허용하지 않는 셋(Set)을 다룹니다.
### 6.1. 딕셔너리(Dictionary): 의미를 부여한 데이터 관리법
- `Key:Value` 쌍으로 데이터를 저장하며, 순서보다 '의미(Key)'를 통해 값을 찾는 데 특화된 <a href="./glossary.md#자료구조-data-structure">자료구조</a>입니다. (`{}` 사용)
- AI 개발에서는 모델의 성능에 영향을 주는 다양한 **하이퍼파라미터(e.g., `{'learning_rate': 0.01, 'epochs': 100}`)** 를 관리하거나, 웹 API로부터 받은 **JSON 형식의 데이터를 다룰 때** 핵심적인 역할을 합니다.
```python
user = {"name": "앨리스", "age": 30}
user['email'] = "alice@example.com" # 데이터 추가/변경
print(f"이름: {user['name']}, 이메일: {user.get('email')}")
```
### 6.2. 셋(Set): 중복을 제거하고 관계를 파악하는 도구
- **중복을 허용하지 않는** 순서 없는 데이터의 모음입니다. (`{}` 사용)
- 데이터의 중복 제거, 그룹 간의 합집합, 교집합 등을 구할 때 유용한 <a href="./glossary.md#set">자료구조</a>입니다.
```python
unique_numbers = {1, 2, 3, 2, 1, 4}
print(f"중복이 제거된 집합: {unique_numbers}") # {1, 2, 3, 4}
set_a = {1, 2, 3}
set_b = {3, 4, 5}
print(f"교집합: {set_a & set_b}") # {3}
```
---
## 7. 코드의 흐름 제어하기
> **🎯 4일차 목표:** `if`, `for`, `while` 제어문을 사용하여 조건과 반복에 따라 코드의 흐름을 제어합니다.
### 7.1. 파이썬의 상징: 들여쓰기(Indentation)
파이썬은 **[들여쓰기](./glossary.md#들여쓰기-indentation)(스페이스 4칸)**로 코드의 소속을 구분하는 '문법'입니다. `if`, `for` 등에 속한 코드들은 반드시 들여쓰기를 해야 합니다.
### 7.2. `if-elif-else`: 조건에 따라 움직이기
```python
score = 85
if score >= 90: grade = "A"
elif score >= 80: grade = "B"
else: grade = "F"
print(f"학점: {grade}")
```
### 7.3. `for`: 순서대로 반복하기
리스트, 튜플, 문자열 등 순회 가능한 객체의 요소를 하나씩 순회합니다. `enumerate`를 사용하면 인덱스와 값을 함께 얻을 수 있습니다.
```python
fruits = ["apple", "banana", "cherry"]
for idx, fruit in enumerate(fruits):
print(f"{idx+1}번째 과일: {fruit}")
```
### 7.4. `while`: 조건이 만족하는 동안 반복하기
주어진 조건이 `True`인 동안 코드를 계속해서 반복합니다. 조건이 언젠가 `False`가 되도록 만들지 않으면 '무한 루프'에 빠지므로 주의해야 합니다.
```python
count = 3
while count > 0:
print(f"카운트 다운: {count}")
count -= 1 # 이 줄이 없으면 무한 루프!
print("발사!")
```
---
## 8. 코드를 재사용하는 마법, 함수
> **🎯 5일차 목표:** 반복되는 코드를 `[함수(Function)](./glossary.md#함수-function)`로 묶어 재사용하고, 함수의 입력([매개변수](./glossary.md#매개변수-parameter와-인자-argument))과 출력([반환 값](./glossary.md#반환-값-return-value))을 이해합니다.
### 8.1. 함수(Function): 나만의 데이터 처리 레시피
[함수](./glossary.md#함수-function)는 특정 작업을 수행하는 코드 묶음에 이름을 붙인 **'재사용 가능한 레시피'**입니다. 특히 AI 개발에서 함수는 **'데이터 전처리기'** 와 같습니다. 입력(매개변수)으로 원본 데이터를 받고, 특정 방식(알고리즘)으로 가공하여 깨끗하게 정제된 데이터(반환 값)를 출력하는 과정은 AI 모델 학습의 가장 기본적인 단계입니다. `def` 키워드로 나만의 데이터 처리 레시피를 만들어보세요.
### 8.2. 입력(매개변수)과 출력(반환 값)
- **[매개변수(Parameter)](./glossary.md#매개변수-parameter와-인자-argument):** 함수에 전달하는 재료(입력 값).
- **[`return`](./glossary.md#반환-값-return-value):** 함수가 작업을 마친 후 돌려주는 결과물(출력 값).
```python
def add(a, b):
result = a + b
return result
# 함수 호출 및 결과 저장
sum_result = add(5, 3)
print(f"5 + 3 = {sum_result}")
```
함수를 잘 사용하면 복잡한 문제를 여러 개의 간단한 함수로 나누어 해결할 수 있어, 훨씬 체계적인 프로그래밍이 가능해집니다.
---
## 9. 직접 해보기 (Hands-on Lab)
이번 주에 배운 내용을 바탕으로 다음 함수들을 직접 완성해보세요.
**문제 1: 학점 계산기 함수**
- 학생의 점수(0~100)를 매개변수로 받아 학점을 반환하는 `get_grade` 함수를 `if-elif-else`를 사용하여 만들어보세요.
- 90점 이상: "A", 80점 이상: "B", 70점 이상: "C", 70점 미만: "F"
**문제 2: 리스트에서 특정 단어 개수 세기**
- 과일 이름 리스트와 특정 과일 이름을 매개변수로 받아, 리스트 안에 그 과일이 몇 번 나타나는지 `for`문을 사용해 세고 개수를 반환하는 `count_word` 함수를 만들어보세요.
**문제 3: 구구단 출력 함수**
- 숫자를 하나 매개변수로 받아 해당 숫자의 구구단을 `while`문을 사용하여 출력하는 `multiplication_table` 함수를 만들어보세요. (이 함수는 값을 반환할 필요가 없습니다.)
## 10. 되짚어보기 (Summary)
이번 주차에 우리는 파이썬의 가장 기본적인 구성 요소들을 배웠습니다.
- **변수와 자료형**: 데이터를 저장하고(변수), 데이터의 종류(숫자, 문자열, 불리언)를 구분했습니다.
- **자료구조**: 여러 데이터를 담는 그릇인 리스트, 튜플, 딕셔너리, 셋을 익혔습니다.
- **제어문**: `if`, `for`, `while`을 통해 코드의 흐름을 제어하는 방법을 배웠습니다.
- **함수**: `def`를 사용해 반복되는 코드를 재사용 가능한 블록으로 만들었습니다.
이 핵심 문법들은 앞으로 우리가 만들 모든 AI 서비스의 뼈대가 될 것입니다.
## 11. 더 깊이 알아보기 (Further Reading)
- [파이썬 공식 튜토리얼: 자료구조 (리스트, 튜플, 셋, 딕셔너리)](https://docs.python.org/ko/3/tutorial/datastructures.html)
- [파이썬 공식 튜토리얼: 제어 흐름 도구 (if, for, while)](https://docs.python.org/ko/3/tutorial/controlflow.html)
- [파이썬 공식 튜토리얼: 함수 정의하기](https://docs.python.org/ko/3/tutorial/controlflow.html#defining-functions)
\ No newline at end of file
# Part 4: 객체 지향 프로그래밍 (OOP) 마스터하기
**⬅️ 이전 시간: [Part 3: 파이썬 컬렉션 심화](../03_python_collections/part_3_python_collections.md)**
**➡️ 다음 시간: [Part 5: AI 핵심 라이브러리](../05_ai_core_libraries/part_5_ai_core_libraries.md)**
---
## 1. 학습 목표 (Learning Objectives)
이번 파트가 끝나면, 여러분은 다음을 할 수 있게 됩니다.
- 클래스(설계도)를 정의하고, 그로부터 고유한 속성과 행동을 가진 객체(제품)를 생성할 수 있습니다.
- 상속을 통해 기존 클래스의 기능을 재사용하고, 메서드 오버라이딩으로 기능을 확장/변경할 수 있습니다.
- 다형성을 활용하여 유연하고 확장성 높은 코드를 작성할 수 있습니다.
- 캡슐화로 데이터를 안전하게 보호하고, 추상화로 클래스의 필수 기능을 강제할 수 있습니다.
- 현실 세계의 문제를 객체들 간의 상호작용으로 모델링하여 체계적인 프로그램을 설계할 수 있습니다.
## 2. 핵심 키워드 (Keywords)
`[클래스(Class)](./glossary.md#클래스-class)`, `[객체(Object)](./glossary.md#객체-object)`, `[상속(Inheritance)](./glossary.md#상속-inheritance)`, `[다형성(Polymorphism)](./glossary.md#다형성-polymorphism)`, `[캡슐화(Encapsulation)](./glossary.md#캡슐화-encapsulation)`, `[추상화(Abstraction)](./glossary.md#추상화-abstraction)`, `[@dataclass](./glossary.md#dataclass)`, `[super()](./glossary.md#super)`, `[매직 메서드(Magic Methods)](./glossary.md#매직-메서드-magic-methods)`
## 3. OOP와 함께 '붕어빵 비즈니스' 시작하기 (Introduction)
지금까지 우리는 프로그래밍의 '재료'를 다듬는 법을 익혔습니다. 이번 주차에는 이 재료들을 조합하여 '요리'를 하는 법, 즉 더 크고 체계적인 프로그램을 만드는 **[객체 지향 프로그래밍(OOP)](./glossary.md#객체-지향-프로그래밍-object-oriented-programming-oop)** 패러다임을 학습합니다.
**이번 파트의 최종 목표는 `model = RandomForestClassifier()` 라는 AI 코드 한 줄을 완벽하게 이해하는 것입니다.**
Scikit-learn, PyTorch, TensorFlow 등 세상의 모든 AI 라이브러리는 OOP를 기반으로 설계되었습니다. 따라서 OOP를 이해하는 것은 단순히 프로그래밍 기술을 하나 더 배우는 것이 아니라, **AI 개발자로서 라이브러리의 구조를 꿰뚫어 보고 자유자재로 활용하기 위한 필수 관문**입니다.
> **💡 핵심 비유: OOP는 '붕어빵 비즈니스'입니다**
> OOP의 모든 개념을 '붕어빵 장사'에 빗대어 이해해 봅시다!
> - **클래스(Class)**: 붕어빵을 만드는 **'붕어빵 틀'**
> - **객체(Object)**: 붕어빵 틀에서 찍어낸 **'붕어빵'** 하나하나
> - **속성(Attribute)**: 붕어빵의 '팥', '슈크림' 같은 **'속재료'**
> - **메서드(Method)**: 붕어빵 틀의 **'굽기()', '뒤집기()'** 같은 **'행동'**
> [!TIP]
> 본 파트의 모든 예제 코드는 `../../source_code/part_4_object_oriented_programming.py` 파일에서 직접 실행해볼 수 있습니다.
---
## 4. 클래스와 객체: 붕어빵 틀과 붕어빵
> **🎯 1일차 목표:** 클래스(Class)와 객체(Object)의 개념을 이해하고, `__init__`과 `self`를 사용하여 객체의 고유한 상태를 만듭니다.
- **클래스(Class)**: 객체를 만들기 위한 **'설계도'** 또는 '붕어빵 틀'.
- **객체(Object)**: 클래스로부터 생성된 **'실체'** 또는 '팥 붕어빵', '슈크림 붕어빵'.
> [!IMPORTANT]
> ### AI 라이브러리와 클래스 & 객체
> `model = RandomForestClassifier()` 코드를 OOP 관점에서 해부해 봅시다.
> - **`RandomForestClassifier`**: 머신러닝 모델의 기능(데이터 학습, 예측 등)이 정의된 **클래스(설계도)**입니다.
> - **`model`**: 설계도로부터 막 생성된 **객체(실체)**입니다. 이 객체는 이제 자신만의 데이터와 상태를 가질 수 있습니다.
> - **`model.fit(X, y)`**: `model` 객체가 가진 기능, 즉 **메서드(행동)**를 호출하여 모델을 학습시킵니다.
> - **`model.feature_importances_`**: 학습이 끝난 후 `model` 객체 내부에 저장된 결과, 즉 **속성(상태)**을 확인합니다.
>
> 이처럼 AI 라이브러리를 사용한다는 것은 **'클래스를 가져와, 객체를 만들고, 그 객체의 메서드와 속성을 활용하는 과정'** 그 자체입니다.
```python
from dataclasses import dataclass
@dataclass # __init__, __repr__ 등 반복적인 코드를 자동 생성
class Bungeoppang:
# --- 속성 (붕어빵의 속재료) ---
flavor: str
price: int = 1000 # 기본값 설정
# --- 메서드 (붕어빵 틀의 행동) ---
def sell(self):
print(f"{self.flavor} 붕어빵을 {self.price}원에 판매합니다.")
# --- 객체 생성 (붕어빵 틀로 붕어빵을 찍어냄) ---
red_bean_bpp = Bungeoppang("팥")
shu_cream_bpp = Bungeoppang("슈크림", price=1200)
# --- 메서드 호출 (붕어빵 판매) ---
red_bean_bpp.sell() # "팥 붕어빵을 1000원에 판매합니다."
shu_cream_bpp.sell() # "슈크림 붕어빵을 1200원에 판매합니다."
```
> **`__init__`과 `self`**: `@dataclass`가 자동으로 만들어주는 `__init__`은 붕어빵 틀에 반죽과 **앙금(`flavor`, `price`)**을 넣는 과정입니다. `self`는 지금 만들어지고 있는 **'바로 그 붕어빵'** 자신을 가리키는 대명사로, 붕어빵들이 서로의 앙금을 헷갈리지 않게 해줍니다.
---
## 5. 상속: 새로운 맛의 붕어빵 출시하기
> **🎯 2일차 목표:** 상속으로 코드 중복을 줄이고, 메서드 오버라이딩과 `super()`로 기능을 확장합니다.
**상속(Inheritance)**은 '기본 붕어빵 틀'을 물려받아 '피자 붕어빵 틀' 같은 신제품을 만드는 것입니다.
> [!TIP]
> **AI 모델링과 상속**
> PyTorch 같은 딥러닝 프레임워크에서 나만의 모델을 만들 때, 우리는 항상 `torch.nn.Module` 이라는 클래스를 **상속**받습니다. 이는 PyTorch가 제공하는 학습, 최적화 등 모델의 핵심 기능들은 그대로 물려받되, 모델의 구조를 정의하는 `forward()` 메서드만 **재정의(Overriding)**하여 나만의 신경망을 만들기 위함입니다. 상속은 이처럼 AI 라이브러리의 기능을 확장하는 핵심 도구입니다.
```python
@dataclass
class PizzaBungeoppang(Bungeoppang): # Bungeoppang 클래스를 상속
topping: str
# --- 메서드 오버라이딩(Method Overriding) ---
# 부모의 sell() 메서드를 신제품에 맞게 재정의
def sell(self):
print(f"'{self.topping}' 토핑이 올라간 {self.flavor} 피자 붕어빵을 {self.price}원에 판매합니다!")
# super() 사용 예시
@dataclass
class PremiumBungeoppang(Bungeoppang):
origin: str
def __post_init__(self):
# super()는 부모 클래스를 의미. 부모의 기능을 확장할 때 사용.
# 여기서는 Bungeoppang의 속성을 그대로 쓰되, 가격만 500원 인상
self.price += 500
```
> **메서드 오버라이딩과 `super()`**: 기본 붕어빵의 판매 방식(`sell`)을 피자 붕어빵에 맞게 바꾸는 것이 **오버라이딩**입니다. 프리미엄 붕어빵을 만들 때, 기존 가격 정책에 추가 금액만 더하는 것처럼 부모의 기능을 그대로 활용하며 확장할 때 **`super()`**를 사용합니다.
---
## 6. 다형성과 캡슐화: 유연하고 안전한 비즈니스
> **🎯 3일차 목표:** 다형성(Polymorphism)으로 코드의 유연성을 높이고, 캡슐화(Encapsulation)로 데이터를 안전하게 보호합니다.
- **다형성(Polymorphism)**: "주문하신 것 나왔습니다!" 라는 **동일한 요청(`sell()`)**에 대해, 대상 객체가 '팥 붕어빵'이냐 '피자 붕어빵'이냐에 따라 **다른 결과가 나오는 것**입니다. 코드의 유연성을 크게 높여줍니다.
- **캡슐화(Encapsulation)**: 붕어빵 맛의 핵심인 **'반죽의 비밀 레시피(`__secret_recipe`)'**를 외부에서 함부로 바꾸지 못하게 숨기고, 정해진 방법으로만 접근하게 하여 데이터를 보호하는 것입니다.
```python
class BungeoppangFactory:
def __init__(self, initial_flour_kg):
self.__flour_kg = initial_flour_kg # 밀가루 재고(비밀 데이터)
def get_stock(self): # 데이터를 확인하는 정해진 통로 (getter)
return self.__flour_kg
def add_flour(self, amount): # 데이터를 변경하는 정해진 통로 (setter)
if amount > 0: self.__flour_kg += amount
factory = BungeoppangFactory(100)
# factory.__flour_kg = 999 #! 직접 수정 불가 (AttributeError)
factory.add_flour(20) # 정해진 방법으로만 수정 가능
print(f"현재 밀가루 재고: {factory.get_stock()}kg")
```
---
## 7. 추상화와 매직 메서드: 비즈니스 규칙과 마법
> **🎯 4일차 목표:** 추상화로 클래스의 필수 기능을 강제하고, 매직 메서드로 파이썬 내장 기능을 커스터마이징합니다.
- **추상화(Abstraction)**: 프랜차이즈 본사에서 "모든 가맹점은 반드시 **'굽기()' 기능을 스스로 구현해야 한다**"는 '운영 매뉴얼'을 만들어 규칙을 강제하는 것입니다.
- **매직 메서드(Magic Methods)**: `print(붕어빵)`을 했을 때 예쁜 설명이 나오게 하거나(`__str__`), `붕어빵1 + 붕어빵2` 처럼 객체 간의 연산을 정의하는 등, 파이썬의 내장 기능을 우리 객체에 맞게 만드는 마법입니다.
```python
from abc import ABC, abstractmethod
class FranchiseManual(ABC): # 추상 클래스
@abstractmethod # 추상 메서드
def bake(self): pass
class MyStore(FranchiseManual): # 가맹점
def bake(self): # '굽기' 규칙을 반드시 구현해야 함
print("우리 가게만의 방식으로 붕어빵을 굽습니다.")
# --- 매직 메서드 예시 ---
# Bungeoppang 클래스에 아래 메서드를 추가했다고 가정
# def __str__(self): return f"{self.flavor} 붕어빵"
# def __eq__(self, other): return self.flavor == other.flavor
bpp1 = Bungeoppang("팥")
print(bpp1) # __str__ 호출 -> "팥 붕어빵"
bpp2 = Bungeoppang("팥")
print(bpp1 == bpp2) # __eq__ 호출 -> True
```
---
## 8. 직접 해보기 (Hands-on Lab)
### 문제 1: 온라인 서점 시스템 모델링
- `Book`(책), `Member`(회원), `Order`(주문) 클래스를 `dataclass`를 사용하여 정의하고, 회원이 여러 권의 책을 주문하는 시나리오를 코드로 구현하세요.
**요구사항:**
- **`Book`**: `isbn`, `title`, `price` 속성
- **`Member`**: `member_id`, `name` 속성
- **`Order`**: `member`(`Member` 객체), `books`(`Book` 객체 리스트) 속성 및 `total_price()` (총 가격 계산) 메서드
### 문제 2: 게임 캐릭터 클래스 만들기
- 기본 `Character` 클래스와 이를 상속받는 `Warrior`, `Wizard` 클래스를 만드세요.
**요구사항:**
- **`Character`**: `name`, `hp`, `power` 속성 및 `attack(other)` 메서드
- **`Warrior`**: `attack` 메서드를 오버라이딩하여, 20% 확률로 2배의 데미지를 입히도록 수정
- **`Wizard`**: `attack` 메서드를 오버라이딩하고, `super()`를 사용하여 부모의 공격을 먼저 실행한 뒤, 자신의 `hp`를 회복하는 기능 추가
---
## 9. 되짚어보기 (Summary)
이번 주차에는 '붕어빵 비즈니스'를 통해 객체 지향 프로그래밍(OOP)을 배웠습니다.
- **클래스와 객체**: '붕어빵 틀'과 '붕어빵'으로 설계도와 실체를 구분했습니다.
- **상속**: '기본 틀'을 물려받아 '신제품 틀'을 만들며 코드 재사용성을 높였습니다.
- **다형성**: "주문하신 것 나왔습니다!" 라는 동일한 요청에 여러 종류의 붕어빵이 나갈 수 있는 유연성을 배웠습니다.
- **캡슐화와 추상화**: '비밀 레시피'를 보호하고(캡슐화), '프랜차이즈 매뉴얼'로 필수 기능을 강제(추상화)했습니다.
OOP는 복잡한 AI 라이브러리의 구조를 이해하고, 더 크고 체계적인 프로그램을 만드는 핵심 열쇠입니다.
## 10. 더 깊이 알아보기 (Further Reading)
- [파이썬 공식 튜토리얼: 클래스](https://docs.python.org/ko/3/tutorial/classes.html)
- [Real Python: Object-Oriented Programming (OOP) in Python 3](https://realpython.com/python3-object-oriented-programming/)
\ No newline at end of file
...@@ -76,6 +76,22 @@ plt.show() ...@@ -76,6 +76,22 @@ plt.show()
--- ---
## 4.5. 머신러닝의 종류: 어떤 문제를 풀고 싶은가?
본격적으로 모델을 만들기 전에, 머신러닝이 해결할 수 있는 문제의 종류를 이해하는 것은 매우 중요합니다. 머신러닝은 크게 **지도학습, 비지도학습, 강화학습** 세 가지로 나뉩니다.
| 학습 유형 | 핵심 아이디어 | 대표적인 예시 | 주요 알고리즘 |
| :--- | :--- | :--- | :--- |
| **지도학습<br>(Supervised)** | **'정답'이 있는 데이터**로 학습 | 스팸 메일 분류, 집값 예측, 이미지 분류 (개/고양이) | 선형 회귀, 로지스틱 회귀, SVM, 결정 트리, 랜덤 포레스트 |
| **비지도학습<br>(Unsupervised)** | **'정답'이 없는 데이터**에서 패턴 발견 | 고객 그룹 분석, 토픽 모델링, 이상 탐지 | K-평균 군집, 주성분 분석(PCA) |
| **강화학습<br>(Reinforcement)** | **'보상'**을 최대화하는 행동을 학습 | 알파고(바둑), 자율주행, 로봇 제어 | Q-러닝, SARSA, DQN |
![머신러닝 종류](https://i.imgur.com/8aE5E9U.png)
이번 파트에서는 이 중에서 가장 널리 사용되고 산업적으로도 중요한 **지도학습**에 집중하여, '정답'이 주어진 데이터를 통해 미래를 예측하는 모델을 만드는 방법을 깊이 있게 다룰 것입니다.
---
## 5. Scikit-learn으로 첫 머신러닝 모델 만들기 ## 5. Scikit-learn으로 첫 머신러닝 모델 만들기
> **🎯 3-4일차 목표:** Scikit-learn을 사용하여 머신러닝의 기본 프로세스(학습, 예측, 평가)를 이해합니다. > **🎯 3-4일차 목표:** Scikit-learn을 사용하여 머신러닝의 기본 프로세스(학습, 예측, 평가)를 이해합니다.
...@@ -89,7 +105,23 @@ plt.show() ...@@ -89,7 +105,23 @@ plt.show()
> >
> 훈련 데이터로만 반복해서 시험 보면 100점이 나오겠지만, 진짜 실력이라고 할 수 없겠죠? 그래서 우리는 훈련/테스트 데이터를 엄격히 분리하여 모델의 **일반화 성능**(처음 보는 데이터에 대한 예측 능력)을 측정합니다. > 훈련 데이터로만 반복해서 시험 보면 100점이 나오겠지만, 진짜 실력이라고 할 수 없겠죠? 그래서 우리는 훈련/테스트 데이터를 엄격히 분리하여 모델의 **일반화 성능**(처음 보는 데이터에 대한 예측 능력)을 측정합니다.
### 5-2. Scikit-learn 기본 4단계 프로세스 ### 5-2. 핵심 개념: 과적합, 과소적합, 그리고 편향-분산 트레이드오프
모델을 훈련시킬 때 가장 흔하게 마주치는 문제는 **과적합(Overfitting)****과소적합(Underfitting)**입니다.
- **과소적합 (Underfitting)**: 모델이 너무 단순해서 데이터의 내재된 패턴을 제대로 학습하지 못하는 상태입니다. **훈련 데이터에서도 성능이 낮고, 테스트 데이터에서도 성능이 낮은** 특징을 보입니다. (비유: 시험 범위의 절반만 공부한 학생)
- **과적합 (Overfitting)**: 모델이 훈련 데이터에만 너무 과도하게 맞춰져, 노이즈나 특정 패턴까지 전부 외워버린 상태입니다. **훈련 데이터에서는 성능이 매우 높지만, 새로운 테스트 데이터에서는 성능이 급격히 떨어지는** 특징을 보입니다. (비유: 모의고사 족보만 달달 외워, 새로운 유형의 수능 문제에 대처하지 못하는 학생)
이 두 문제는 **모델의 복잡도(Model Complexity)**와 깊은 관련이 있으며, 이를 **편향-분산 트레이드오프(Bias-Variance Tradeoff)** 라고 부릅니다.
![Bias-Variance Tradeoff](https://i.imgur.com/2s42p4s.png)
- **편향 (Bias)**: 모델이 실제 관계와 얼마나 다른지를 나타냅니다. 편향이 높으면 모델이 너무 단순하여 과소적합 경향을 보입니다.
- **분산 (Variance)**: 데이터의 작은 변화에 모델이 얼마나 민감하게 변하는지를 나타냅니다. 분산이 높으면 모델이 너무 복잡하여 과적합 경향을 보입니다.
우리의 목표는 **편향과 분산이 모두 낮은, 즉 전체 오류가 최소가 되는 '최적의 균형점(Optimal Balance)'**을 찾는 것입니다.
### 5-3. Scikit-learn 기본 4단계 프로세스
Scikit-learn은 다음과 같은 통일된 인터페이스를 제공하여 누구나 쉽게 머신러닝 모델을 만들 수 있게 해줍니다. Scikit-learn은 다음과 같은 통일된 인터페이스를 제공하여 누구나 쉽게 머신러닝 모델을 만들 수 있게 해줍니다.
1. **모델 객체 생성**: `model = ModelName()` 1. **모델 객체 생성**: `model = ModelName()`
...@@ -124,7 +156,7 @@ accuracy = accuracy_score(y_test, predictions) ...@@ -124,7 +156,7 @@ accuracy = accuracy_score(y_test, predictions)
print(f"정확도: {accuracy:.4f}") print(f"정확도: {accuracy:.4f}")
``` ```
### 5-3. 모델 성능을 높이는 데이터 전처리 ### 5-4. 모델 성능을 높이는 데이터 전처리
모델의 성능은 알고리즘만큼이나 **'데이터의 품질'**에 크게 좌우됩니다. "Garbage In, Garbage Out" (쓰레기를 넣으면 쓰레기가 나온다) 라는 말이 있을 정도입니다. 모델의 성능은 알고리즘만큼이나 **'데이터의 품질'**에 크게 좌우됩니다. "Garbage In, Garbage Out" (쓰레기를 넣으면 쓰레기가 나온다) 라는 말이 있을 정도입니다.
- **피처 스케일링(Feature Scaling)**: 변수들의 단위를 맞춰줍니다. (예: 키(cm)와 몸무게(kg) -> 0~1 사이 값으로 표준화) - **피처 스케일링(Feature Scaling)**: 변수들의 단위를 맞춰줍니다. (예: 키(cm)와 몸무게(kg) -> 0~1 사이 값으로 표준화)
...@@ -146,7 +178,52 @@ scaled_minmax = scaler_minmax.fit_transform(data) ...@@ -146,7 +178,52 @@ scaled_minmax = scaler_minmax.fit_transform(data)
print("\nMinMaxScaler 결과:\n", scaled_minmax) print("\nMinMaxScaler 결과:\n", scaled_minmax)
``` ```
### 5-4. 심화: 어떤 모델을 언제 사용해야 할까? (Model Selection Guide) ### 5-5. 모델 상세 평가: 정확도를 넘어서
모델의 성능을 단순히 '정확도(Accuracy)' 하나만으로 평가하는 것은 때로는 위험할 수 있습니다. 특히 데이터가 불균형할 때(예: 스팸 메일 1%, 정상 메일 99%)는 더욱 그렇습니다.
#### 혼동 행렬 (Confusion Matrix)
모델의 예측이 얼마나 헷갈렸는지(confused)를 보여주는 표입니다.
- **TN (True Negative)**: 음성(Negative)을 음성으로 올바르게 예측
- **FP (False Positive)**: 음성(Negative)을 양성(Positive)으로 잘못 예측 (Type I Error)
- **FN (False Negative)**: 양성(Positive)을 음성(Negative)으로 잘못 예측 (Type II Error)
- **TP (True Positive)**: 양성(Positive)을 양성으로 올바르게 예측
![Confusion Matrix](https://i.imgur.com/A4EGF24.png)
#### 정밀도, 재현율, F1-Score
- **정밀도 (Precision)** = `TP / (TP + FP)`
- 모델이 "양성"이라고 예측한 것들 중, 실제로 양성이었던 것의 비율입니다.
- **"스팸이라고 예측한 메일 중, 진짜 스팸은 얼마나 되는가?"**
- FP(정상 메일을 스팸으로 처리)를 낮추는 것이 중요할 때 사용합니다. (예: 유튜브 키즈 콘텐츠 필터링)
- **재현율 (Recall)** = `TP / (TP + FN)`
- 실제 양성인 것들 중, 모델이 양성으로 예측한 것의 비율입니다.
- **"실제 암 환자 중, 모델이 암이라고 진단한 비율은 얼마인가?"**
- FN(암 환자를 정상으로 진단)을 낮추는 것이 중요할 때 사용합니다. (예: 의료 진단, 금융 사기 탐지)
- **F1-Score** = `2 * (Precision * Recall) / (Precision + Recall)`
- 정밀도와 재현율의 조화 평균입니다. 두 지표가 모두 중요할 때 사용하며, 데이터가 불균형할 때 정확도보다 훨씬 신뢰할 수 있는 지표입니다.
```python
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score
# ... (이전 코드에서 predictions, y_test가 생성되었다고 가정) ...
# 혼동 행렬
conf_matrix = confusion_matrix(y_test, predictions)
print("Confusion Matrix:\n", conf_matrix)
# 정밀도, 재현율, F1-점수
precision = precision_score(y_test, predictions, average='macro') # 다중 클래스일 경우 average 지정
recall = recall_score(y_test, predictions, average='macro')
f1 = f1_score(y_test, predictions, average='macro')
print(f"Precision: {precision:.4f}")
print(f"Recall: {recall:.4f}")
print(f"F1 Score: {f1:.4f}")
```
### 5-6. 심화: 어떤 모델을 언제 사용해야 할까? (Model Selection Guide)
Scikit-learn에는 수많은 머신러닝 모델이 존재합니다. 문제의 종류, 데이터의 특성, 그리고 우리가 추구하는 목표(성능, 해석 가능성, 속도 등)에 따라 최적의 모델은 달라집니다. 여기서는 가장 대표적인 **분류(Classification)** 모델 몇 가지를 비교하고, 언제 어떤 모델을 선택하는 것이 좋은지에 대한 가이드라인을 제시합니다. Scikit-learn에는 수많은 머신러닝 모델이 존재합니다. 문제의 종류, 데이터의 특성, 그리고 우리가 추구하는 목표(성능, 해석 가능성, 속도 등)에 따라 최적의 모델은 달라집니다. 여기서는 가장 대표적인 **분류(Classification)** 모델 몇 가지를 비교하고, 언제 어떤 모델을 선택하는 것이 좋은지에 대한 가이드라인을 제시합니다.
...@@ -165,7 +242,41 @@ Scikit-learn에는 수많은 머신러닝 모델이 존재합니다. 문제의 ...@@ -165,7 +242,41 @@ Scikit-learn에는 수많은 머신러닝 모델이 존재합니다. 문제의
이 가이드는 시작점일 뿐이며, 최고의 모델을 찾는 유일한 방법은 **직접 여러 모델을 실험해보고, 교차 검증(Cross-validation)을 통해 성능을 객관적으로 평가하는 것**입니다. 이 가이드는 시작점일 뿐이며, 최고의 모델을 찾는 유일한 방법은 **직접 여러 모델을 실험해보고, 교차 검증(Cross-validation)을 통해 성능을 객관적으로 평가하는 것**입니다.
### 5-5. 실제 기업 적용 사례 (Real-world Enterprise Use Cases) ### 5-7. 핵심 개념: 교차 검증 (Cross-Validation)
우리가 데이터를 훈련/테스트 세트로 한 번 나누는 것은 마치 모의고사를 딱 한 번만 보고 수능 점수를 예측하는 것과 같습니다. 이 분할이 어떻게 되었는지에 따라 성능이 우연히 좋거나 나쁘게 나올 수 있습니다.
**교차 검증(Cross-Validation)**은 이 문제를 해결하기 위해 데이터를 여러 번 다른 방식으로 나누어 학습과 평가를 반복하는 방법입니다. 가장 널리 쓰이는 방법은 **K-겹 교차 검증(K-Fold Cross-Validation)**입니다.
1. 전체 데이터를 K개의 '겹(Fold)'으로 나눕니다.
2. 첫 번째 겹을 테스트 데이터로 사용하고, 나머지 K-1개 겹을 훈련 데이터로 사용하여 모델을 학습하고 평가합니다.
3. 두 번째 겹을 테스트 데이터로 사용하고, 나머지를 훈련 데이터로 사용하여 다시 학습하고 평가합니다.
4. 이 과정을 K번 반복하여, K개의 성능 점수를 얻습니다.
5. 최종적으로 이 K개의 점수를 평균내어 모델의 일반화된 성능을 추정합니다.
![K-Fold Cross Validation](https://i.imgur.com/0K3jTf7.png)
> **💡 장점:**
> - 데이터를 더 효율적으로 사용하며, 모델의 성능을 훨씬 더 안정적이고 신뢰성 있게 평가할 수 있습니다.
> - 특정 데이터 분할에 따른 성능 변동의 위험을 줄여줍니다.
```python
from sklearn.model_selection import cross_val_score
# 모델 생성
model = DecisionTreeClassifier(random_state=42)
# 5-겹 교차 검증 수행
# cv=5 : 5개의 폴드로 나눔
# scoring='accuracy' : 평가 지표로 정확도 사용
scores = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy')
print(f"교차 검증 점수: {scores}")
print(f"평균 정확도: {scores.mean():.4f} (+/- {scores.std() * 2:.4f})")
```
### 5-8. 실제 기업 적용 사례 (Real-world Enterprise Use Cases)
우리가 배운 머신러닝 기술은 단순히 학문적인 개념에 머무르지 않고, 오늘날 수많은 글로벌 기업들의 핵심 서비스를 구동하는 엔진이 되고 있습니다. 몇 가지 대표적인 사례를 통해 머신러닝이 실제로 어떻게 가치를 창출하는지 살펴보겠습니다. 우리가 배운 머신러닝 기술은 단순히 학문적인 개념에 머무르지 않고, 오늘날 수많은 글로벌 기업들의 핵심 서비스를 구동하는 엔진이 되고 있습니다. 몇 가지 대표적인 사례를 통해 머신러닝이 실제로 어떻게 가치를 창출하는지 살펴보겠습니다.
...@@ -182,23 +293,6 @@ Scikit-learn에는 수많은 머신러닝 모델이 존재합니다. 문제의 ...@@ -182,23 +293,6 @@ Scikit-learn에는 수많은 머신러닝 모델이 존재합니다. 문제의
--- ---
## 6. 연습 문제: 타이타닉 생존자 예측
> **🎯 5일차 목표:** 데이터 전처리, 시각화, 모델링, 평가의 전 과정을 종합하여 문제를 해결합니다.
고전적인 '타이타닉' 데이터셋을 사용하여, 어떤 승객이 생존했을지 예측하는 모델을 만들어 봅시다.
### 문제:
1. Seaborn에서 `titanic` 데이터셋을 불러옵니다.
2. 간단한 탐색적 데이터 분석(EDA)을 수행하세요. (`survived``pclass`, `sex` 간의 관계를 막대 그래프로 시각화)
3. 모델링에 사용할 특성(`features`)으로 `pclass`, `sex`, `age`, `sibsp`, `parch`, `fare`를, 타겟(`target`)으로 `survived`를 선택하세요.
4. 결측치가 있는 `age` 열을 `age` 열의 **중앙값(median)**으로 채워주세요.
5. `sex` 열의 문자열('male', 'female')을 숫자(0, 1)로 변환해주세요.
6. 데이터를 훈련/테스트 세트로 분리하고 `StandardScaler`를 적용하여 스케일링하세요.
7. `DecisionTreeClassifier`로 모델을 학습시키고, 테스트 데이터에 대한 **정확도**를 계산하세요.
---
## 7. 심화 토론: 무엇이 잘못될 수 있을까? ## 7. 심화 토론: 무엇이 잘못될 수 있을까?
Scikit-learn을 사용하면 몇 줄의 코드로 쉽게 모델을 만들 수 있지만, 그 과정에는 수많은 함정이 존재합니다. "동작하는" 코드를 넘어 "올바른" 코드를 작성하기 위해 다음 주제들에 대해 함께 토론해보세요. Scikit-learn을 사용하면 몇 줄의 코드로 쉽게 모델을 만들 수 있지만, 그 과정에는 수많은 함정이 존재합니다. "동작하는" 코드를 넘어 "올바른" 코드를 작성하기 위해 다음 주제들에 대해 함께 토론해보세요.
...@@ -206,22 +300,16 @@ Scikit-learn을 사용하면 몇 줄의 코드로 쉽게 모델을 만들 수 ...@@ -206,22 +300,16 @@ Scikit-learn을 사용하면 몇 줄의 코드로 쉽게 모델을 만들 수
1. **전처리 순서가 초래한 데이터 누수(Data Leakage)** 1. **전처리 순서가 초래한 데이터 누수(Data Leakage)**
- **상황**: 한 동료가 효율성을 위해 전체 데이터셋 `X`에 대해 `StandardScaler`를 먼저 적용(`fit_transform`)한 후, 그 결과를 `train_test_split`으로 나누어 모델을 학습시켰습니다. 코드는 오류 없이 잘 동작했고, 테스트 정확도도 꽤 높게 나왔습니다. - **상황**: 한 동료가 효율성을 위해 전체 데이터셋 `X`에 대해 `StandardScaler`를 먼저 적용(`fit_transform`)한 후, 그 결과를 `train_test_split`으로 나누어 모델을 학습시켰습니다. 코드는 오류 없이 잘 동작했고, 테스트 정확도도 꽤 높게 나왔습니다.
- **토론**: - **토론**:
- 이 접근 방식의 무엇이 치명적인 실수일까요? 테스트셋의 정보가 훈련 과정에 어떻게 "누수"되었을까요? - 이 접근 방식의 무엇이 치명적인 실수일까요? 테스트셋의 정보가 훈련 과정에 어떻게 "누수"되었을까요? (힌트: `fit` 메소드는 데이터의 평균과 표준편차를 계산합니다.)
- 피처 스케일링과 같은 전처리 단계를 올바르게 적용하는 파이프라인은 어떤 순서로 구성되어야 할까요? 왜 그 순서가 중요한가요? - 피처 스케일링과 같은 전처리 단계를 올바르게 적용하는 파이프라인은 어떤 순서로 구성되어야 할까요? 왜 그 순서가 중요한가요?
2. **99% 정확도의 함정: 불균형 데이터 문제** 2. **"완벽한" 테스트 점수에 대한 의심**
- **상황**: 어떤 희귀병(전체 환자의 1%)을 예측하는 분류 모델을 만들었습니다. 테스트셋에서 99%의 정확도(Accuracy)를 달성했다고 팀에 보고하자, 한 선임 개발자가 결과에 우려를 표했습니다.
- **토론**:
- 왜 99%의 정확도가 이 상황에서는 매우 나쁜 성능 지표일 수 있을까요? 만약 모델이 무조건 "정상"이라고만 예측한다면, 그 모델의 정확도는 몇 %가 될까요?
- 이처럼 데이터 클래스가 심하게 불균형할 때, 정확도 대신 사용해야 할 더 나은 평가 지표는 무엇이 있을까요? 혼동 행렬(Confusion Matrix), 정밀도(Precision), 재현율(Recall), F1-점수(F1-score)는 각각 어떤 정보를 우리에게 알려주나요?
3. **"완벽한" 테스트 점수에 대한 의심**
- **상황**: 타이타닉 생존자 예측 문제를 해결하기 위해 여러 모델과 특성을 조합해본 결과, 마침내 제공된 테스트셋에 대해 100%의 정확도를 달성했습니다. - **상황**: 타이타닉 생존자 예측 문제를 해결하기 위해 여러 모델과 특성을 조합해본 결과, 마침내 제공된 테스트셋에 대해 100%의 정확도를 달성했습니다.
- **토론**: - **토론**:
- 이 결과를 기뻐해야 할까요, 아니면 의심해야 할까요? "완벽한" 점수가 나올 수 있는 잠재적인 원인들은 무엇일까요? (예: 데이터 누수, 너무 작거나 대표성이 없는 테스트셋, 특정 테스트셋에 대한 과적합 등) - 이 결과를 기뻐해야 할까요, 아니면 의심해야 할까요? "완벽한" 점수가 나올 수 있는 잠재적인 원인들은 무엇일까요? (예: 타겟 변수가 특성에 포함됨, 테스트셋이 너무 작거나 대표성이 없, 특정 테스트셋에 대한 과적합 등)
- 실제 서비스를 만든다고 가정할 때, 왜 최종 성능 검증을 위해 단 한 번만 사용하는 별도의 "검증(validation) 데이터셋"을 따로 떼어놓는 것이 중요한지 토론해보세요. - 실제 서비스를 만든다고 가정할 때, 왜 최종 성능 검증을 위해 단 한 번만 사용하는 별도의 "검증(validation) 데이터셋"을 따로 떼어놓는 것이 중요한지 토론해보세요.
4. **특성 중요도(Feature Importance)의 섣부른 해석** 3. **특성 중요도(Feature Importance)의 섣부른 해석**
- **상황**: 고객 이탈 예측을 위해 만든 랜덤 포레스트 모델이 '월 청구요금'을 가장 중요한 특성으로 지목했습니다. 이 결과를 보고, 마케팅팀은 모든 고객의 요금을 인하하는 캠페인을 기획하려 합니다. - **상황**: 고객 이탈 예측을 위해 만든 랜덤 포레스트 모델이 '월 청구요금'을 가장 중요한 특성으로 지목했습니다. 이 결과를 보고, 마케팅팀은 모든 고객의 요금을 인하하는 캠페인을 기획하려 합니다.
- **토론**: - **토론**:
- 이러한 의사 결정이 왜 섣부른 판단일 수 있을까요? 랜덤 포레스트는 특성 중요도를 어떤 방식으로 계산하나요? - 이러한 의사 결정이 왜 섣부른 판단일 수 있을까요? 랜덤 포레스트는 특성 중요도를 어떤 방식으로 계산하나요?
...@@ -253,7 +341,7 @@ Scikit-learn을 사용하면 몇 줄의 코드로 쉽게 모델을 만들 수 ...@@ -253,7 +341,7 @@ Scikit-learn을 사용하면 몇 줄의 코드로 쉽게 모델을 만들 수
``` ```
- **`fit_transform()`은 훈련 데이터에만 사용하고, `transform()`은 테스트 데이터에 사용하라는 말이 무슨 뜻인가요?** - **`fit_transform()`은 훈련 데이터에만 사용하고, `transform()`은 테스트 데이터에 사용하라는 말이 무슨 뜻인가요?**
- `fit()`은 데이터로부터 스케일링에 필요한 정보(e.g., 평균, 표준편차, 최소/최대값)를 '학습'하는 과정입니다. `transform()`은 학습된 정보를 바탕으로 데이터를 변환합니다. `fit_transform()`은 이 두 과정을 한 번에 수행합니다. 테스트 데이터는 '미래의 데이터'를 의미하므로, 훈련 데이터에서 학습한 '규칙'을 그대로 적용해야 합니다. 따라서 테스트 데이터에는 `fit()`을 다시 사용하지 않고, 훈련 데이터로 `fit()`한 스케일러를 사용하여 `transform()`만 적용해야 합니다. - `fit()`은 데이터로부터 스케일링에 필요한 정보(e.g., 평균, 표준편차, 최소/최대값)를 '학습'하는 과정입니다. `transform()`은 학습된 정보를 바탕으로 데이터를 변환합니다. `fit_transform()`은 이 두 과정을 한 번에 수행합니다. 테스트 데이터는 '미래의 데이터'를 의미하므로, 훈련 데이터로 `fit()`한 스케일러를 사용하여 `transform()`만 적용해야 합니다.
- **모델의 성능이 너무 낮게 나오나요?** - **모델의 성능이 너무 낮게 나오나요?**
- 여러 가능성이 있습니다. - 여러 가능성이 있습니다.
......
...@@ -27,6 +27,19 @@ ...@@ -27,6 +27,19 @@
> - **Scikit-learn**: '트럭', '비행기'처럼 이미 완성된 모델을 가져와 사용하는 **'완성품 장난감'**과 같습니다. 사용하기 편리하고 대부분의 정형 데이터 문제에 효과적입니다. > - **Scikit-learn**: '트럭', '비행기'처럼 이미 완성된 모델을 가져와 사용하는 **'완성품 장난감'**과 같습니다. 사용하기 편리하고 대부분의 정형 데이터 문제에 효과적입니다.
> - **PyTorch**: 다양한 모양의 **'레고 블록'**을 제공하여, 사용자가 원하는 어떤 복잡한 구조(신경망)라도 직접 조립할 수 있게 해줍니다. 이미지, 텍스트 등 비정형 데이터를 다루는 딥러닝에 필수적이며, 연구와 산업 현장에서 가장 널리 쓰이는 도구 중 하나입니다. > - **PyTorch**: 다양한 모양의 **'레고 블록'**을 제공하여, 사용자가 원하는 어떤 복잡한 구조(신경망)라도 직접 조립할 수 있게 해줍니다. 이미지, 텍스트 등 비정형 데이터를 다루는 딥러닝에 필수적이며, 연구와 산업 현장에서 가장 널리 쓰이는 도구 중 하나입니다.
### 3.1. 왜 딥러닝인가? 머신러닝의 한계와 표현 학습
그렇다면 왜 Scikit-learn의 편리한 모델들을 두고, 굳이 복잡하게 신경망을 직접 조립해야 할까요? 이는 전통적인 머신러닝이 **비정형 데이터(이미지, 텍스트, 음성 등)**를 다루는 데 명확한 한계를 가지고 있기 때문입니다.
- **전통적인 머신러닝의 한계: 수동 특징 공학 (Manual Feature Engineering)**
- 머신러닝 모델이 좋은 성능을 내기 위해서는, 데이터의 특성을 잘 나타내는 '특징(Feature)'을 사람이 직접 설계하고 추출해야 했습니다. 예를 들어, 고양이 사진을 분류하기 위해 '귀가 뾰족한가?', '수염이 있는가?'와 같은 특징을 코드로 구현해야 했습니다. 이 과정은 매우 어렵고, 많은 시간과 도메인 지식이 필요하며, 데이터가 복잡해질수록 사실상 불가능에 가깝습니다.
- **딥러닝의 혁신: 표현 학습 (Representation Learning)**
- 딥러닝은 이 **특징 추출 과정을 자동화**합니다. 개발자는 모델의 큰 구조만 설계하고 데이터를 보여주기만 하면, 모델이 데이터로부터 직접 문제 해결에 필요한 특징들을 **스스로 학습**합니다. 이것이 바로 **표현 학습**입니다.
- 딥러닝 모델의 '깊은(deep)' 여러 계층들은, 데이터의 원초적인 형태(픽셀, 단어)로부터 시작하여 점차 더 복잡하고 추상적인 특징(선 -> 형태 -> 객체)을 학습해 나갑니다.
![ML vs DL](https://i.imgur.com/x0G3R9a.png)
> [!TIP] > [!TIP]
> 본 파트의 모든 예제 코드는 `../../source_code/part_7_deep_learning.py` 파일에서 직접 실행하고 수정해볼 수 있습니다. > 본 파트의 모든 예제 코드는 `../../source_code/part_7_deep_learning.py` 파일에서 직접 실행하고 수정해볼 수 있습니다.
...@@ -96,7 +109,24 @@ print(model) ...@@ -96,7 +109,24 @@ print(model)
> >
> > **🎯 3-4일차 목표:** 손실 함수, 옵티마이저의 개념을 이해하고 전체 학습 루프를 구현합니다. > > **🎯 3-4일차 목표:** 손실 함수, 옵티마이저의 개념을 이해하고 전체 학습 루프를 구현합니다.
> >
> ### 5-1. 모델의 예측을 어떻게 평가할까? (손실 함수) > ### 5-1. 모델은 어떻게 학습하는가: 경사 하강법과 옵티마이저
>
> 딥러닝 학습의 목표는 손실 함수가 만든 '손실 지형(Loss Landscape)'의 가장 낮은 지점을 찾아가는 것입니다. 이 과정은 마치 안개 속에서 산을 내려오는 등산가와 같습니다.
>
> - **경사 하강법 (Gradient Descent)**: 등산가는 현재 위치에서 **경사가 가장 가파른 방향(Gradient)**을 따라 한 걸음씩 내려갑니다. 이 과정을 반복하면 결국 계곡의 가장 낮은 지점(최소 손실)에 도달할 수 있습니다. 여기서 '경사(Gradient)'가 바로 `loss.backward()`를 통해 계산되는 미분값입니다.
>
> - **옵티마이저 (Optimizer)**: '한 걸음'을 어떻게 내디딜지 결정하는 전략입니다.
> - 얼마나 큰 보폭으로 내려갈지 (**학습률, Learning Rate**)
> - 이전 걸음을 얼마나 참조할지 (**모멘텀, Momentum**)
> - 각 파라미터마다 보폭을 다르게 할지 등을 결정합니다.
>
> **대표적인 옵티마이저**
> - **SGD (Stochastic Gradient Descent)**: 가장 기본적인 경사 하강법. 한 번에 하나의 데이터(또는 작은 배치)를 보고 파라미터를 업데이트합니다.
> - **Adam (Adaptive Moment Estimation)**: SGD에 모멘텀과 적응적 학습률 개념을 더한, 현재 가장 널리 사용되는 안정적이고 성능 좋은 옵티마이저입니다. 대부분의 경우 Adam으로 시작하는 것이 좋습니다.
>
> ![Gradient Descent](https://i.imgur.com/sSgG4fV.gif)
>
> ### 5-2. 모델의 예측을 어떻게 평가할까? (손실 함수)
> >
> 훌륭한 모델을 만들기 위해서는, 현재 모델이 얼마나 '잘하고' 또는 '못하고' 있는지를 측정할 객관적인 '평가 지표'가 필요합니다. 이 역할을 하는 것이 바로 **손실 함수(Loss Function)** 입니다. > 훌륭한 모델을 만들기 위해서는, 현재 모델이 얼마나 '잘하고' 또는 '못하고' 있는지를 측정할 객관적인 '평가 지표'가 필요합니다. 이 역할을 하는 것이 바로 **손실 함수(Loss Function)** 입니다.
> >
...@@ -125,19 +155,20 @@ print(model) ...@@ -125,19 +155,20 @@ print(model)
> - 예측 A (잘 맞춤): `[0.9, 0.05, 0.05]` -> 낮은 손실(Loss) > - 예측 A (잘 맞춤): `[0.9, 0.05, 0.05]` -> 낮은 손실(Loss)
> - 예측 B (못 맞춤): `[0.1, 0.8, 0.1]` -> 높은 손실(Loss) > - 예측 B (못 맞춤): `[0.1, 0.8, 0.1]` -> 높은 손실(Loss)
> >
> ### 5-2. 핵심 프로세스: 학습 루프(Training Loop) > ### 5-3. 핵심 프로세스: 학습 루프(Training Loop)
> 딥러닝 모델 학습은 '에포크(Epoch)'라는 단위로 반복됩니다. 1 에포크는 전체 훈련 데이터를 한 번 모두 사용하는 것을 의미하며, 학습은 다음 4단계로 이루어집니다. > 딥러닝 모델 학습은 '에포크(Epoch)'라는 단위로 반복됩니다. 1 에포크는 전체 훈련 데이터를 한 번 모두 사용하는 것을 의미하며, 학습은 다음 4단계로 이루어집니다.
> >
> 1. **`model(inputs)`**: 모델에 입력을 넣어 예측값(`outputs`)을 계산합니다 (**순전파**). > 1. **`model(inputs)`**: 모델에 입력을 넣어 예측값(`outputs`)을 계산합니다 (**순전파**).
> 2. **`loss = criterion(outputs, labels)`**: 예측값과 실제 정답을 비교하여 오차(`loss`)를 계산합니다. > 2. **`loss = criterion(outputs, labels)`**: 예측값과 실제 정답을 비교하여 오차(`loss`)를 계산합니다.
> 3. **`loss.backward()`**: 계산된 오차를 기반으로, 각 파라미터가 오차에 얼마나 기여했는지 미분값을 계산합니다 (**역전파**). > 3. **`optimizer.zero_grad()`**: 이전 스텝의 기울기 값을 초기화합니다. (이걸 해주지 않으면 기울기가 계속 누적됩니다.)
> 4. **`optimizer.step()`**: 계산된 미분값을 바탕으로 모델의 파라미터를 업데이트하여 오차를 줄이는 방향으로 나아갑니다. > 4. **`loss.backward()`**: 계산된 오차를 기반으로, 각 파라미터가 오차에 얼마나 기여했는지 미분값을 계산합니다 (**역전파**).
> 5. **`optimizer.step()`**: 계산된 미분값을 바탕으로 모델의 파라미터를 업데이트하여 오차를 줄이는 방향으로 나아갑니다.
> >
> > **💡 순전파와 역전파** > > **💡 순전파와 역전파 (Forward & Backward Propagation)**
> > - **순전파 (Forward)**: 내가 만든 레시피로 요리를 해서(모델 예측) 손님에게 내놓는 과정. > > - **순전파 (Forward)**: 내가 만든 레시피로 요리를 해서(모델 예측) 손님에게 내놓는 과정.
> > - **역전파 (Backward)**: 손님의 피드백("너무 짜요!")을 듣고, 소금을 얼마나 넣었는지, 간장을 얼마나 넣었는지 원인을 거슬러 올라가 분석하는 과정. `optimizer.step()`은 이 분석을 바탕으로 다음 요리에서는 소금을 덜 넣는 행동입니다. > > - **역전파 (Backward)**: 손님의 피드백("너무 짜요!")을 듣고, 소금을 얼마나 넣었는지, 간장을 얼마나 넣었는지 원인을 **연쇄 법칙(Chain Rule)**에 따라 거슬러 올라가 각 재료(파라미터)의 '책임'을 계산하는 과정. `optimizer.step()`은 이 분석을 바탕으로 다음 요리에서는 소금을 덜 넣는 행동입니다.
> >
> ### 5-3. 학습, 검증, 그리고 추론 (Training, Validation, and Inference) > ### 5-4. 학습, 검증, 그리고 추론 (Training, Validation, and Inference)
> >
> 딥러닝 모델의 생명주기는 크게 '학습', '검증', '추론' 세 단계로 나뉩니다. > 딥러닝 모델의 생명주기는 크게 '학습', '검증', '추론' 세 단계로 나뉩니다.
> >
...@@ -145,6 +176,28 @@ print(model) ...@@ -145,6 +176,28 @@ print(model)
> - **검증 (Validation)**: 학습 과정 중에 모델이 얼마나 잘 학습되고 있는지, 과적합(Overfitting)은 발생하지 않는지 확인하기 위한 단계입니다. 학습에 사용되지 않은 `validation_loader` 데이터로 모델의 성능을 주기적으로 평가합니다. 이 평가 결과를 바탕으로 학습률(Learning Rate)을 조절하거나 학습을 조기 종료하는 등의 결정을 내립니다. > - **검증 (Validation)**: 학습 과정 중에 모델이 얼마나 잘 학습되고 있는지, 과적합(Overfitting)은 발생하지 않는지 확인하기 위한 단계입니다. 학습에 사용되지 않은 `validation_loader` 데이터로 모델의 성능을 주기적으로 평가합니다. 이 평가 결과를 바탕으로 학습률(Learning Rate)을 조절하거나 학습을 조기 종료하는 등의 결정을 내립니다.
> - **추론 (Inference)**: 학습이 완료된 모델을 사용하여 새로운 데이터에 대한 예측을 수행하는 단계입니다. 이 단계에서는 더 이상 모델의 가중치를 업데이트하지 않으므로, 역전파나 옵티마이저가 필요 없습니다. `torch.no_grad()` 컨텍스트 안에서 실행하여 메모리 사용량을 줄이고 계산 속도를 높이는 것이 일반적입니다. 서비스 배포 환경에서 모델이 사용되는 단계가 바로 추론입니다. > - **추론 (Inference)**: 학습이 완료된 모델을 사용하여 새로운 데이터에 대한 예측을 수행하는 단계입니다. 이 단계에서는 더 이상 모델의 가중치를 업데이트하지 않으므로, 역전파나 옵티마이저가 필요 없습니다. `torch.no_grad()` 컨텍스트 안에서 실행하여 메모리 사용량을 줄이고 계산 속도를 높이는 것이 일반적입니다. 서비스 배포 환경에서 모델이 사용되는 단계가 바로 추론입니다.
> >
> ### 5-5. 딥러닝 모델의 과적합 방지 기술 (Regularization)
>
> 딥러닝 모델은 파라미터가 매우 많기 때문에, 머신러닝 모델보다 과적합(Overfitting)의 위험이 훨씬 더 큽니다. 모델이 훈련 데이터에만 과도하게 최적화되는 것을 막고, 일반화 성능을 높이기 위해 다양한 정규화(Regularization) 기법이 사용됩니다.
>
> - **드롭아웃 (Dropout)**
> - **원리**: 훈련 과정에서 각 뉴런을 정해진 확률(e.g., p=0.5)로 무작위로 '비활성화'시킵니다. 매번 다른 구성의 더 작은 네트워크를 학습시키는 효과를 줍니다.
> - **효과**: 특정 뉴런에 과도하게 의존하는 것을 방지하고, 모델이 더 강건한(robust) 특징을 학습하도록 강제합니다. (비유: 팀 프로젝트에서 매번 몇몇 팀원이 무작위로 결석하여, 남은 사람들만으로 과제를 해결하게 만들어 개개인의 역량을 키우는 것)
> - **구현**: `nn.Dropout(p=0.5)`
>
> - **배치 정규화 (Batch Normalization)**
> - **원리**: 각 레이어의 입력 분포를 평균 0, 분산 1로 정규화하여, 학습 과정에서 각 층의 입력 분포가 심하게 변동하는 **내부 공변량 변화(Internal Covariate Shift)** 문제를 완화합니다.
> - **효과**:
> - **학습 속도 향상**: 그래디언트 흐름을 원활하게 하여 학습을 안정시키고 속도를 높입니다.
> - **규제 효과**: 미니배치의 통계량에 따라 출력이 조금씩 달라지므로, 약간의 노이즈를 추가하는 효과가 있어 드롭아웃과 유사한 규제 역할을 합니다.
> - **초기값 민감도 감소**: 초기 가중치 설정에 덜 민감해집니다.
> - **구현**: `nn.BatchNorm1d`, `nn.BatchNorm2d`
>
> > [!IMPORTANT]
> > `model.train()`과 `model.eval()` 모드를 반드시 전환해주어야 합니다.
> > - `model.train()`: 드롭아웃과 배치 정규화를 **활성화**합니다.
> > - `model.eval()`: 드롭아웃과 배치 정규화를 **비활성화**하고, 학습 과정에서 계산해둔 전체 데이터의 통계량을 사용하여 일관된 출력을 보장합니다. 검증 및 추론 시에는 반드시 `eval()` 모드를 사용해야 합니다.
>
> --- > ---
> >
> ## 연습 문제: MNIST 손글씨 분류 > ## 연습 문제: MNIST 손글씨 분류
...@@ -195,21 +248,29 @@ print(model) ...@@ -195,21 +248,29 @@ print(model)
> optimizer = torch.optim.Adam(model.parameters(), lr=0.001) > optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
> >
> # 4. 학습 루프 구현 > # 4. 학습 루프 구현
> # model.train() 모드 설정
> # for epoch ... > # for epoch ...
> # for i, (images, labels) in enumerate(train_loader): > # for i, (images, labels) in enumerate(train_loader):
> # - images, labels를 device로 이동 > # - images, labels를 device로 이동
> # - 옵티마이저 그래디언트 초기화
> # - 순전파, 손실 계산, 역전파, 파라미터 업데이트 코드 작성 > # - 순전파, 손실 계산, 역전파, 파라미터 업데이트 코드 작성
> #
> # 5. 평가 루프 구현
> # model.eval() 모드 설정
> # with torch.no_grad():
> # for images, labels in test_loader:
> # - 정확도 계산 코드 작성
> >
> ### 6-1. 심화: 주요 CNN 아키텍처의 발전사 > ### 6-1. 심화: 주요 CNN 아키텍처의 발전사
> 간단한 CNN 모델을 직접 만들어본 지금, 딥러닝 역사에 한 획을 그은 주요 CNN 아키텍처들이 어떻게 발전해왔는지 살펴보는 것은 매우 의미 있는 일입니다. 각 모델이 어떤 문제를 해결하려 했고, 어떤 아이디어를 제시했는지 이해하면 더 깊이 있는 모델을 설계하는 데 도움이 될 것입니다. > 간단한 CNN 모델을 직접 만들어본 지금, 딥러닝 역사에 한 획을 그은 주요 CNN 아키텍처들이 어떻게 발전해왔는지 살펴보는 것은 매우 의미 있는 일입니다. 각 모델이 어떤 문제를 해결하려 했고, 어떤 아이디어를 제시했는지 이해하면 더 깊이 있는 모델을 설계하는 데 도움이 될 것입니다.
> >
> | 모델명 | 발표 연도 | 주요 특징 및 기여 | 주요 사용처 및 선택 가이드 | | 모델명 | 발표 연도 | 주요 특징 및 기여 | 주요 사용처 및 선택 가이드 |
> |---|---|---|---| |---|---|---|---|
> | **LeNet-5** | 1998 | LeCun 교수가 제안. 최초의 성공적인 CNN. `Conv`-`Pool`-`Conv`-`Pool`-`FC` 구조의 기반을 마련. | **학습용/기본 CNN 구조 이해**: CNN의 기본 동작 원리를 학습하고 간단한 분류 문제를 해결할 때 좋습니다. 현대적인 문제에 직접 사용하기에는 성능이 부족합니다. | | **LeNet-5** | 1998 | LeCun 교수가 제안. 최초의 성공적인 CNN. `Conv`-`Pool`-`Conv`-`Pool`-`FC` 구조의 기반을 마련. | **학습용/기본 CNN 구조 이해**: CNN의 기본 동작 원리를 학습하고 간단한 분류 문제를 해결할 때 좋습니다. 현대적인 문제에 직접 사용하기에는 성능이 부족합니다. |
> | **AlexNet** | 2012 | 이미지넷(ILSVRC) 챌린지에서 압도적 성능으로 우승하며 **딥러닝의 부흥**을 이끌었다. **ReLU**, **Dropout**, **GPU 활용** 등 현재까지도 널리 쓰이는 기법들을 대거 도입했다. | **성능 개선의 출발점**: LeNet보다 복잡한 문제에 적용 가능. 딥러닝 모델의 성능을 어떻게 개선하는지에 대한 아이디어(활성화 함수, 규제)를 얻고 싶을 때 분석해볼 만합니다. | | **AlexNet** | 2012 | 이미지넷(ILSVRC) 챌린지에서 압도적 성능으로 우승하며 **딥러닝의 부흥**을 이끌었다. **ReLU**, **Dropout**, **GPU 활용** 등 현재까지도 널리 쓰이는 기법들을 대거 도입했다. | **성능 개선의 출발점**: LeNet보다 복잡한 문제에 적용 가능. 딥러닝 모델의 성능을 어떻게 개선하는지에 대한 아이디어(활성화 함수, 규제)를 얻고 싶을 때 분석해볼 만합니다. |
> | **VGGNet** | 2014 | **3x3의 작은 커널**을 여러 겹 깊게 쌓는 단순하지만 효과적인 구조를 제시. 깊이(Depth)가 성능에 미치는 영향을 증명했다. | **전이 학습(Transfer Learning)의 베이스라인**: 구조가 단순하고 특징 추출 능력이 우수하여, 사전 훈련된 모델을 다른 이미지 문제에 적용하는 전이 학습의 베이스라인으로 널리 사용됩니다. | | **VGGNet** | 2014 | **3x3의 작은 커널**을 여러 겹 깊게 쌓는 단순하지만 효과적인 구조를 제시. 깊이(Depth)가 성능에 미치는 영향을 증명했다. | **전이 학습(Transfer Learning)의 베이스라인**: 구조가 단순하고 특징 추출 능력이 우수하여, 사전 훈련된 모델을 다른 이미지 문제에 적용하는 전이 학습의 베이스라인으로 널리 사용됩니다. |
> | **GoogLeNet** | 2014 | **인셉션 모듈(Inception Module)**을 도입하여, 여러 크기의 커널을 병렬로 사용함으로써 연산 효율성과 성능을 동시에 잡았다. **파라미터 수를 줄이는 데** 집중했다. | **연산량/메모리가 제한된 환경**: 모바일 기기나 임베디드 시스템처럼 계산 비용에 민감한 환경에서 높은 성능을 내야 할 때 우선적으로 고려됩니다. | | **GoogLeNet** | 2014 | **인셉션 모듈(Inception Module)**을 도입하여, 여러 크기의 커널을 병렬로 사용함으로써 연산 효율성과 성능을 동시에 잡았다. **파라미터 수를 줄이는 데** 집중했다. | **연산량/메모리가 제한된 환경**: 모바일 기기나 임베디드 시스템처럼 계산 비용에 민감한 환경에서 높은 성능을 내야 할 때 우선적으로 고려됩니다. |
> | **ResNet** | 2015 | **잔차 학습(Residual Learning)**과 **스킵 연결(Skip Connection)**이라는 혁신적인 아이디어로 100층이 넘는 **매우 깊은 신경망**의 학습을 가능하게 했다. **Vanishing Gradient 문제를 해결**하며 딥러닝의 한계를 돌파했다. | **대부분의 컴퓨터 비전 문제의 표준**: 현재까지도 이미지 분류, 객체 탐지, 세그멘테이션 등 다양한 컴퓨터 비전 문제에서 매우 강력한 '기본/표준' 모델로 사용됩니다. | | **ResNet** | 2015 | **잔차 학습(Residual Learning)****스킵 연결(Skip Connection)**이라는 혁신적인 아이디어로 100층이 넘는 **매우 깊은 신경망**의 학습을 가능하게 했다. **Vanishing Gradient 문제를 해결**하며 딥러닝의 한계를 돌파했다. | **대부분의 컴퓨터 비전 문제의 표준**: 현재까지도 이미지 분류, 객체 탐지, 세그멘테이션 등 다양한 컴퓨터 비전 문제에서 매우 강력한 '기본/표준' 모델로 사용됩니다. |
> >
> #### 1. LeNet-5: CNN의 서막 > #### 1. LeNet-5: CNN의 서막
> - Yann LeCun 교수가 제안한 모델로, 현대적인 CNN 구조(합성곱 층과 풀링 층의 반복, 마지막에 완전 연결 계층)의 청사진을 제시했습니다. 당시에는 손글씨 숫자 인식과 같은 제한된 문제에서 큰 성공을 거두었습니다. > - Yann LeCun 교수가 제안한 모델로, 현대적인 CNN 구조(합성곱 층과 풀링 층의 반복, 마지막에 완전 연결 계층)의 청사진을 제시했습니다. 당시에는 손글씨 숫자 인식과 같은 제한된 문제에서 큰 성공을 거두었습니다.
...@@ -346,9 +407,8 @@ class WineNet(nn.Module): ...@@ -346,9 +407,8 @@ class WineNet(nn.Module):
# 3. 모델, 손실함수, 옵티마이저 설정 # 3. 모델, 손실함수, 옵티마이저 설정
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
input_features = X_train.shape[1] model = WineNet(input_features=X_train.shape[1]).to(device)
model = WineNet(input_features).to(device) criterion = nn.BCEWithLogitsLoss()
criterion = nn.BCEWithLogitsLoss() # Sigmoid + BCELoss
optimizer = torch.optim.Adam(model.parameters(), lr=0.001) optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 4. 학습 루프 # 4. 학습 루프
...@@ -421,10 +481,10 @@ with torch.no_grad(): ...@@ -421,10 +481,10 @@ with torch.no_grad():
- **학습률(Learning Rate)**이 너무 높거나 낮을 수 있습니다. 너무 높으면 최적점을 지나쳐 발산하고, 너무 낮으면 학습이 매우 느리거나 지역 최적점(Local Minima)에 갇힐 수 있습니다. 옵티마이저의 `lr` 값을 조절해보세요. - **학습률(Learning Rate)**이 너무 높거나 낮을 수 있습니다. 너무 높으면 최적점을 지나쳐 발산하고, 너무 낮으면 학습이 매우 느리거나 지역 최적점(Local Minima)에 갇힐 수 있습니다. 옵티마이저의 `lr` 값을 조절해보세요.
- 데이터에 문제가 있을 수도 있습니다. 입력 데이터와 레이블이 제대로 매칭되었는지, 데이터 정규화가 올바르게 적용되었는지 확인해보세요. - 데이터에 문제가 있을 수도 있습니다. 입력 데이터와 레이블이 제대로 매칭되었는지, 데이터 정규화가 올바르게 적용되었는지 확인해보세요.
- **GPU를 사용하고 있는데도 `CUDA out of memory` 오류가 발생하나요?** - **GPU를 사용하고 있는데도 `CUDA out of memory` 오류가 발생하나요?**
- GPU 메모리보다 큰 모델이나 데이터를 올리려고 할 때 발생합니다. **배치 사이즈(Batch Size)**를 줄이는 것이 가장 일반적인 해결책입니다. 그래도 문제가 해결되지 않는다면, 모델의 파라미터 수를 줄이거나(더 얕은 모델 사용), 이미지의 해상도를 낮추는 방법을 고려할 수 있습니다. - GPU 메모리보다 큰 모델이나 데이터를 올리려고 할 때 발생합니다. **배치 사이즈(Batch Size)**를 줄이는 것이 가장 일반적인 해결책입니다. 그래도 문제가 해결되지 않는다면, 모델의 파라미터 수를 줄이거나(더 얕은 모델 사용), 이미지의 해상도를 낮추는 방법을 고려할 수 있습니다.
- **`model.eval()`과 `torch.no_grad()`는 왜 사용해야 하나요?** - **`model.eval()`과 `torch.no_grad()`는 왜 사용해야 하나요?**
- **`model.eval()`**: 모델을 평가(evaluation/inference) 모드로 전환합니다. 이는 드롭아웃(Dropout)이나 배치 정규화(Batch Normalization)와 같이 훈련 때와 평가 때 다르게 동작해야 하는 레이어들을 올바르게 설정해주는 역할을 합니다. - **`model.eval()`**: 모델을 평가(evaluation/inference) 모드로 전환합니다. 이는 드롭아웃(Dropout)이나 배치 정규화(Batch Normalization)와 같이 훈련 때와 평가 때 다르게 동작해야 하는 레이어들을 올바르게 설정해주는 역할을 합니다.
- **`torch.no_grad()`**: 이 컨텍스트 블록 안에서는 그래디언트 계산을 수행하지 않도록 하여, 불필요한 메모리 사용을 막고 계산 속도를 높여줍니다. 모델 평가나 추론 시에는 역전파가 필요 없으므로 반드시 사용해주는 것이 좋습니다. - **`torch.no_grad()`**: 이 컨텍스트 블록 안에서는 그래디언트 계산을 수행하지 않도록 하여, 불필요한 메모리 사용을 막고 계산 속도를 높이는 것이 일반적입니다. 모델 평가나 추론 시에는 역전파가 필요 없으므로 반드시 사용해주는 것이 좋습니다.
더 자세한 문제 해결 가이드나 다른 동료들이 겪은 문제에 대한 해결책이 궁금하다면, 아래 문서를 참고해주세요. 더 자세한 문제 해결 가이드나 다른 동료들이 겪은 문제에 대한 해결책이 궁금하다면, 아래 문서를 참고해주세요.
...@@ -465,7 +525,7 @@ with torch.no_grad(): ...@@ -465,7 +525,7 @@ with torch.no_grad():
- **[CS231n: Convolutional Neural Networks for Visual Recognition](https://cs231n.github.io/)**: 스탠포드 대학의 전설적인 컴퓨터 비전 강의. CNN의 원리와 응용에 대해 가장 깊이 있게 배우고 싶다면 강력히 추천합니다. - **[CS231n: Convolutional Neural Networks for Visual Recognition](https://cs231n.github.io/)**: 스탠포드 대학의 전설적인 컴퓨터 비전 강의. CNN의 원리와 응용에 대해 가장 깊이 있게 배우고 싶다면 강력히 추천합니다.
- **[Attention Is All You Need (논문)](https://arxiv.org/abs/1706.03762)**: 현대 딥러닝의 흐름을 바꾼 Transformer 모델을 제안한 논문. `part_7.2`를 학습하기 전에 한번쯤 읽어보는 것을 권장합니다. - **[Attention Is All You Need (논문)](https://arxiv.org/abs/1706.03762)**: 현대 딥러닝의 흐름을 바꾼 Transformer 모델을 제안한 논문. `part_7.2`를 학습하기 전에 한번쯤 읽어보는 것을 권장합니다.
- **[3Blue1Brown: 신경망 영상 시리즈](https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi)**: 역전파(Backpropagation)와 같은 딥러닝의 핵심 수학 개념을 세상에서 가장 직관적인 시각 자료로 설명해줍니다. - **[3Blue1Brown: 신경망 영상 시리즈](https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi)**: 역전파(Backpropagation)와 같은 딥러닝의 핵심 수학 개념을 세상에서 가장 직관적인 시각 자료로 설명해줍니다.
- **[A Comprehensive Guide to Convolutional Neural Networks](https://towardsdatascience.com/a-comprehensive-guide-to-convolutional-neural-networks-the-eli5-way-3bd2b1164a53)**: CNN의 기본 개념부터 주요 아키텍처까지 시각 자료와 함께 친절하게 설명는 아티클입니다. - **[A Comprehensive Guide to Convolutional Neural Networks](https://towardsdatascience.com/a-comprehensive-guide-to-convolutional-neural-networks-the-eli5-way-3bd2b1164a53)**: CNN의 기본 개념부터 주요 아키텍처까지 시각 자료와 함께 친절하게 설명해주는 아티클입니다.
--- ---
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment