diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3c1a2fb..d0bef37 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,27 +1,39 @@ -## 원칙 -**1 문제 1 PR** -- 하나의 카테고리에서 한 개의 문제를 PR 해주세요. +| **⚠ PR 템플릿은 수정하지 말아주세요!**
**🔥 [PR 작성 규칙](https://github.com/boostcamp-ai-tech-4/ai-tech-interview/discussions/182#discussion-4321560)을 준수하지 않는 PR은 거절됩니다. 꼭 읽어주세요.**| +| :--- | -**Merge 기준** -- 미적으로 나아졌을 경우 -- 답변이 개선된 경우 -## 제목 -**[카테고리] 번호** +## 🔎 What is this PR? -아래 여덟가지 카테고리 중 하나를 선택하고 수정하려는 문제 번호를 적어주세요. -- Statistics/Math -- Machine Learning -- Deep Learning -- Python -- Network -- Operating System -- Data Structure -- Algorithm +### 분야 -`e.g. [Machine Learning] 12번` +> **`필수` 수정하려는 답변의 분야를 선택해주세요. 이외 수정사항은 기타를 선택하시고 오른쪽에 추가 설명 부탁드립니다.** -## 본문 -해당 문제에서 **어디** 부분인지를 표시해주고, **어떻게** 수정했는지 **이유**와 함께 적어주세요. +- [ ] 통계/수학 +- [ ] 머신러닝 +- [ ] 딥러닝 +- [ ] 파이썬 +- [ ] 네트워크 +- [ ] 운영체제 +- [ ] 자료구조 +- [ ] 알고리즘 +- [ ] 기타: +### 수정 내용 +> **`필수` 어떻게 수정하셨는지 자세히 작성 부탁드립니다.** + +### 참고 자료 + +> **`선택` 수정 시 참고한 문서가 있다면 링크 작성 부탁드립니다.** + +## ✅ PR Checklists + +> **`필수` 아래 체크리스트 확인 부탁드립니다. 모두 체크된 PR만 확인 가능합니다.** + +- [ ] [PR 작성 규칙](https://github.com/boostcamp-ai-tech-4/ai-tech-interview/discussions/182)을 준수하셨나요? + - [ ] **"1문제 1PR" 원칙**을 준수하셨나요? + - [ ] PR 템플릿에 맞춰서 PR을 작성하셨나요? + - [ ] PR 제목은 "[분야] 수정내용"로 되어있나요? (분야는 **한글 명칭**만 가능 ex. 딥러닝, 머신러닝) + - [ ] PR이 **1미적으로 나아졌을 경우 2답변이 개선된 경우** 두 가지 중 하나에 해당되나요? + - [ ] LaTeX 문법을 준수하셨나요? (참고: [GitHub 수식 기능 공지](https://github.blog/2022-05-19-math-support-in-markdown/)) +- [ ] upstream 레포의 최신 브랜치와 동일한 main 브랜치에서 분기하여 수정하셨나요? diff --git a/.gitignore b/.gitignore index 496ee2c..6b0c856 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,78 @@ -.DS_Store \ No newline at end of file +# Created by https://www.toptal.com/developers/gitignore/api/windows,macos,linux +# Edit at https://www.toptal.com/developers/gitignore?templates=windows,macos,linux + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/windows,macos,linux diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 0000000..4947924 --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,49 @@ +pull_request_rules: + - name: Assign yourself and request reviews automatically + conditions: + - -merged + - -closed + - base=main + actions: + assign: + add_users: + - CoodingPenguin + request_reviews: + users: + - CoodingPenguin + label: + add: + - "💬 feedback" + + - name: Automatic merge on approval + conditions: + - -closed + - -merged + - "#approved-reviews-by>=1" + - "#changes-requested-reviews-by=0" + - base=main + actions: + merge: + method: merge + + - name: Add conflict label + conditions: + - -closed + - -merged + - conflict + actions: + comment: + message: "@{{author}} Conflict 해결이 필요합니다!😥 cc. @CoodingPenguin" + label: + add: + - "❗ conflict" + + - name: Remove conflict label + conditions: + - -closed + - -merged + - -conflict + actions: + label: + remove: + - "❗ conflict" diff --git a/LICENSE b/LICENSE index 964ba2e..8ec92b6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 boostcamp-ai-tech-4 +Copyright (c) 2021 boost-devs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index eca9b3d..3ca79fa 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,44 @@ -## 📌 현재 레포 개선 중에 있습니다. 조금만 기다려주세요🙏 -## 👉 [면접 레포 개선하기](https://github.com/boostcamp-ai-tech-4/ai-tech-interview/projects/2) +![](logo.png) + +
+ Hits + forks + stars + pr + license +
--- -
- logo -
- - forks - stars - pr - license -
+## Notice -## [👉 Discussions](https://github.com/boostcamp-ai-tech-4/ai-tech-interview/discussions) +> [!TIP] +> 이동 중에도 면접 준비하고 싶다면, @LearningnRunning 님이 만든 [AI Tech Interview 연습하기](https://ai-tech-interview.streamlit.app/)를 이용해보세요! -스터디 방식, 스터디 기록, QnA는 모두 Discussions에서 작성됩니다! +> [!WARNING] +> PR 요청 시 [작성 규칙](https://github.com/boost-devs/ai-tech-interview/discussions/182)을 준수해주세요. **준수하지 않을 시 해당 PR은 거절될 수 있습니다.** ---- - -## Table of Contents - -- [Part 1. Data Science](#part-1-data-science) - - [Statistics/Math](#-statisticsmath) - - [Machine Learning](#-machine-learning) - - [Deep Learning](#-deep-learning) -- [Part 2. Language](#part-2-language) - - [Python](#-python) -- [Part 3. CS](#part-3-cs) - - [Network](#-network) - - [Operating System](#%EF%B8%8F-operating-system) - - [Data Structure](#-data-structure) - - [Algorithm](#-algorithm) -- [References](#references) +- 피드백은 [Pull Request를 통한 피드백 요청 방법](https://github.com/boost-devs/ai-tech-interview/discussions/181)을 참고하여 Pull Request로 보내주세요. + - Pull Request 작성 규칙은 [여기](https://github.com/boost-devs/ai-tech-interview/discussions/182)를 참고해주세요. +- GitHub 외에 [GitBook 사이트](https://boostdevs.gitbook.io/ai-tech-interview/)로도 보실 수 있습니다. + - ~~하지만 Latex 문법이 달라 다른 웹사이트로 마이그레이션 예정입니다.~~ 시간될 때 마이그레이션 예정입니다..🥲 +- 궁금한 점이 있거나 공유하고 싶은 팁이 있으시면 [Discussion](https://github.com/boost-devs/ai-tech-interview/discussions/)을 활용해주세요. + - 커뮤니티 활성화는 언제든지 환영입니다! +- 면접 레포 개선 프로젝트 진행 상황은 [여기](https://github.com/boost-devs/ai-tech-interview/projects/2)를 확인해주세요. + - [공지](https://github.com/boost-devs/ai-tech-interview/discussions/184)에서 말씀드린 것처럼 진행이 더딜 수 있습니다. --- -## Part 1. Data Science +## Interview Questions -### [📈 Statistics/Math](./answers/1-statistics-math.md) +
+📈 통계/수학 -- 고유값(eigen value)와 고유벡터(eigen vector)에 대해 설명해주세요. 그리고 왜 중요할까요? -- 샘플링(Sampling)과 리샘플링(Resampling)에 대해 설명해주세요. 리샘플링은 무슨 장점이 있을까요? -- 확률 모형과 확률 변수는 무엇일까요? -- 누적 분포 함수와 확률 밀도 함수는 무엇일까요? 수식과 함께 표현해주세요. -- 조건부 확률은 무엇일까요? +- 고유값(eigen value)와 고유벡터(eigen vector)이 무엇이고 왜 중요한지 설명해주세요. +- 샘플링(Sampling)과 리샘플링(Resampling)이 무엇이고 리샘플링의 장점을 말씀해주세요. +- 확률 모형과 확률 변수는 무엇인가요? +- 누적 분포 함수와 확률 밀도 함수는 무엇인가요? 수식과 함께 표현해주세요. +- 조건부 확률은 무엇인가요? - 공분산과 상관계수는 무엇일까요? 수식과 함께 표현해주세요. - 신뢰 구간의 정의는 무엇인가요? - p-value를 모르는 사람에게 설명한다면 어떻게 설명하실 건가요? @@ -66,15 +60,14 @@ - 베르누이 분포 / 이항 분포 / 카테고리 분포 / 다항 분포 / 가우시안 정규 분포 / t 분포 / 카이제곱 분포 / F 분포 / 베타 분포 / 감마 분포에 대해 설명해주세요. 그리고 분포 간의 연관성도 설명해주세요. - 출장을 위해 비행기를 타려고 합니다. 당신은 우산을 가져가야 하는지 알고 싶어 출장지에 사는 친구 3명에게 무작위로 전화를 하고 비가 오는 경우를 독립적으로 질문해주세요. 각 친구는 2/3로 진실을 말하고 1/3으로 거짓을 말합니다. 3명의 친구가 모두 "그렇습니다. 비가 내리고 있습니다"라고 말했습니다. 실제로 비가 내릴 확률은 얼마입니까? -목차로 돌아가기 - -
+
-### [🤖 Machine Learning](./answers/2-machine-learning.md) +
+🤖 머신러닝 - 알고 있는 metric에 대해 설명해주세요. (ex. RMSE, MAE, recall, precision ...) - 정규화를 왜 해야할까요? 정규화의 방법은 무엇이 있나요? -- Local Minima와 Global Minima에 대해 설명해주세요. +- Local Minima와 Global Minimum에 대해 설명해주세요. - 차원의 저주에 대해 설명해주세요. - dimension reduction기법으로 보통 어떤 것들이 있나요? - PCA는 차원 축소 기법이면서, 데이터 압축 기법이기도 하고, 노이즈 제거기법이기도 합니다. 왜 그런지 설명해주실 수 있나요? @@ -102,11 +95,10 @@ - 스팸 필터에 로지스틱 리그레션을 많이 사용하는 이유는 무엇일까요? - OLS(ordinary least squre) regression의 공식은 무엇인가요? -목차로 돌아가기 +
-
- -### [🧠 Deep Learning](./answers/3-deep-learning.md) +
+🧠 딥러닝 - 딥러닝은 무엇인가요? 딥러닝과 머신러닝의 차이는? - Cost Function과 Activation Function은 무엇인가요? @@ -155,13 +147,10 @@ - GPU를 두개 다 쓰고 싶다. 방법은? - 학습시 필요한 GPU 메모리는 어떻게 계산하는가? -목차로 돌아가기 - ---- +
-## Part 2. Language - -### [🐍 Python](./answers/4-python.md) +
+🐍 파이썬 - What is the difference between list and tuples in Python? - What are the key features of Python? @@ -235,13 +224,10 @@ - What is object interning? - What is @classmethod, @staticmethod, @property? -목차로 돌아가기 +
---- - -## Part 3. CS - -### [🌐 Network](./answers/5-network.md) +
+🌐 네트워크 - TCP/IP의 각 계층을 설명해주세요. - OSI 7계층와 TCP/IP 계층의 차이를 설명해주세요. @@ -276,11 +262,10 @@ - client와 server의 차이점을 설명해주세요. - delay, timing(jitter), throughput 차이를 설명해주세요. -목차로 돌아가기 - -
+
-### [🖥️ Operating System](./answers/6-operating-system.md) +
+🖥️ 운영체제 - 프로세스와 스레드의 차이(Process vs Thread)를 알려주세요. - 멀티 프로세스 대신 멀티 스레드를 사용하는 이유를 설명해주세요. @@ -298,11 +283,10 @@ - Context Switching이 무엇인지 설명하고 과정을 나열해주세요. - Swapping에 대해 설명해주세요. -목차로 돌아가기 +
-
- -### [🗂 Data Structure](./answers/7-data-structure.md) +
+🗂 자료구조 - linked list - single linked list @@ -324,11 +308,10 @@ - red-black tree - b+ tree -목차로 돌아가기 - -
+
-### [🔻 Algorithm](./answers/8-algorithm.md) +
+🔻 알고리즘 - 시간, 공간 복잡도 - Sort Algorithm @@ -355,7 +338,15 @@ - Union-find - Topological sort -목차로 돌아가기 +
+ +--- + +## Contributors + + + + --- diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 0000000..aea8bc4 --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,15 @@ +# Table of contents + +- [Notice](README.md) + +## 🧑💻 INTERVIEW + +- [Statistics/Math](answers/1-statistics-math.md) +- [Machine Learning](answers/2-machine-learning.md) +- [Deep Learning](answers/3-deep-learning.md) +- [Python](answers/4-python.md) +- [Network](answers/5-network.md) +- [Operating System](answers/6-operating-system.md) +- [Data Structure](answers/7-data-structure.md) +- [Algorithm](answers/8-algorithm.md) + diff --git a/answers/1-statistics-math.md b/answers/1-statistics-math.md index 0ca042a..1ba0822 100644 --- a/answers/1-statistics-math.md +++ b/answers/1-statistics-math.md @@ -1,18 +1,12 @@ -
-

📈 Statistics/Math 📈

-
- -> 질문은 [zzsza님의 Datascience-Interview-Questions](https://github.com/zzsza/Datascience-Interview-Questions)를 참고하였습니다. - ---- +> **📌 질문은 [zzsza님의 Datascience-Interview-Questions](https://github.com/zzsza/Datascience-Interview-Questions)를 참고하였습니다.** ## Table of Contents -- [고유값(eigen value)와 고유벡터(eigen vector)에 대해 설명해주세요. 그리고 왜 중요할까요?](#1) -- [샘플링(Sampling)과 리샘플링(Resampling)에 대해 설명해주세요. 리샘플링은 무슨 장점이 있을까요?](#2) -- [확률 모형과 확률 변수는 무엇일까요?](#3) -- [누적 분포 함수와 확률 밀도 함수는 무엇일까요? 수식과 함께 표현해주세요.](#4) -- [조건부 확률은 무엇일까요?](#5) +- [고유값(eigen value)와 고유벡터(eigen vector)이 무엇이고 왜 중요한지 설명해주세요.](#1) +- [샘플링(Sampling)과 리샘플링(Resampling)이 무엇이고 리샘플링의 장점을 말씀해주세요.](#2) +- [확률 모형과 확률 변수는 무엇인가요?](#3) +- [누적 분포 함수와 확률 밀도 함수는 무엇인가요? 수식과 함께 표현해주세요.](#4) +- [조건부 확률은 무엇인가요?](#5) - [공분산과 상관계수는 무엇일까요? 수식과 함께 표현해주세요.](#6) - [신뢰 구간의 정의는 무엇인가요?](#7) - [p-value를 모르는 사람에게 설명한다면 어떻게 설명하실 건가요?](#8) @@ -38,30 +32,21 @@ ## #1 -#### 고유값(eigen value)와 고유벡터(eigen vector)에 대해 설명해주세요. 그리고 왜 중요할까요? +### 고유값(eigen value)와 고유벡터(eigen vector)이 무엇이고 왜 중요한지 설명해주세요. -정방행렬 A (n x n) 는 임의의 벡터 x (n x 1) 의 방향과 크기를 변화시킬 수 있다. +정방행렬 $(n \times n)$인 $A$는 임의의 벡터 $(n \times 1)$인 $x$의 방향과 크기를 변화시킬 수 있다. -수많은 벡터 x 중 어떤 벡터들은 A 에 의해 선형 변환되었을 때에도 원래 벡터와 평행한 경우가 있다. **이렇듯 Ax 가 원래 x 에 상수 (람다) 를 곱한 것과 같을 때의 x 를 고유 벡터, 람다를 고유값이라 한다.** +수많은 벡터 $x$중 어떤 벡터들은 $A$에 의해 선형 변환되었을 때에도 원래 벡터와 평행한 경우가 있다. **이렇듯 $Ax$가 원래 $x$에 상수 $\lambda$를 곱한 것과 같을 때의 $x$를 고유 벡터, 람다를 고유값이라 한다.** -> 공식 - - - - +$$ -
+아래처럼 $x_1$은 $A$에 의해 변환되었음에도 $x_1$과 평행하다. 따라서 $x_1$은 고유벡터이다. -아래처럼 x1 은 A 에 의해 변환되었음에도 x1 과 평행하다. 따라서 x1 은 고유벡터이다. +![고유벡터](./img/1-statistics-math/eigen-vector.png) -
- -
-
- -고유값과 고유벡터를 통해 A 를 고유값과 고유벡터들로 분해하는 **고유값 분해** (eigen decomposition), 정방행렬 뿐만 아닌 m x n 행렬도 분해할 수 있는 **특이값 분해** (SVD), 데이터들을 차원 축소시킬 때 가장 원래 의미를 잘 보존시키는 **주성분 분석** (PCA) 등에 활용할 수 있으므로 중요하다. +고유값과 고유벡터를 통해 $A$를 고유값과 고유벡터들로 분해하는 **고유값 분해(eigen decomposition)**, 정방행렬 뿐만 아닌 $m \times n$행렬도 분해할 수 있는 **특이값 분해(SVD)**, 데이터들을 차원 축소시킬 때 가장 원래 의미를 잘 보존시키는 **주성분 분석(PCA)** 등에 활용할 수 있으므로 중요하다. #### References @@ -74,7 +59,7 @@ $$ --> ## #2 -#### 샘플링(Sampling)과 리샘플링(Resampling)에 대해 설명해주세요. 리샘플링은 무슨 장점이 있을까요? +### 샘플링(Sampling)과 리샘플링(Resampling)이 무엇이고 리샘플링의 장점을 말씀해주세요. 샘플링이란 **표본추출**을 의미하는 것으로, 모집단 전체에 대한 추정치(estimate)를 얻기 위해 임의의 sample을 뽑아내는 것이다. 모집단 전체에 대한 조사는 불가능하기 때문에 sample을 이용하여 모집단에 대한 추론(inference)을 하게되는 것이다. @@ -99,15 +84,15 @@ $$ --> ## #3 -#### 확률 모형과 확률 변수는 무엇일까요? +### 확률 모형과 확률 변수는 무엇인가요? **확률변수(Random Variable)** 란, 표본 공간의 각 단위 사건에 실수 값을 부여하는 변수이다. 확률변수는 어떠한 함수로 해석할 수 있으므로 `대문자 X`라고 표기한다. 무작위(Random) 실험을 했을 때, 특정 확률로 발생하는 각각의 결과를 수치적 값으로 표현하는 변수라고 할 수 있다. -또한 확률 변수에는 `이산확률변수`, `연속확률변수` 두가지 경우가 있다. `이산확률변수`는 확률변수 X가 취할 수 있는 값이 유한하기 떄문에 셀 수 있는 확률변수이다. 반면에 `연속확률변수`는 어떠한 두 수 사이에 반드시 다른 수가 존재하는, 셀 수 없는 범위의 확률변수를 가지는 경우에 사용된다. +또한 확률 변수에는 `이산확률변수`, `연속확률변수` 두가지 경우가 있다. `이산확률변수`는 확률변수 $X$가 취할 수 있는 값이 유한하기 떄문에 셀 수 있는 확률변수이다. 반면에 `연속확률변수`는 어떠한 두 수 사이에 반드시 다른 수가 존재하는, 셀 수 없는 범위의 확률변수를 가지는 경우에 사용된다. 주사위 굴리기 예제를 생각해보자. -``` +```text 일단 주사위를 굴리는 상황은 어떤 수가 나올지 모르므로, 확률상황이다. "주사위를 굴렸을 때 나오는 값"을 확률변수 X라고 할 수 있다. 1~6이 표본공간이 되고, 셀 수 있으므로 이산확률변수가 된다. @@ -116,15 +101,13 @@ P(X=1)와 같은 식으로 표현하고, 이는 "주사위를 굴렸을 때, 1 **확률모형(Probability Model)** 이란 확률변수를 이용하여 데이터의 분포를 수학적으로 정의한 모형이다. 데이터 분포를 묘사하기 위해서 사용된다. -보통 `확률 분포 함수(probability distribution function)` 또는 `확률 밀도 함수(probability density function)`를 주로 사용하며, 이때 함수의 계수를 분포의 모수(parameter)라고 부른다. +보통 **확률 분포 함수(probability distribution function)** 또는 확률 밀도 함수(probability density function)를 주로 사용하며, 이때 함수의 계수를 분포의 모수(parameter)라고 부른다. **확률분포(Probability Distribution)** 란 표본공간에 정의된 확률을 이용하여 확률변수의 값 또는 영역에 대한 확률을 표현한 것이다. 예를 들어 가장 널리 쓰이는 확률 모형의 하나인 `가우시안 정규 분포(Gaussian normal distribution)`는 다음과 같은 수식으로 확률 밀도 함수를 정의한다. - - - +$$ +N(x ; \mu, \sigma) = \frac{1}{\sigma \sqrt{2 \pi}} e^{-\frac{(x- \mu)^2}{2 \sigma^2}} +$$ 다음과 같은 함수들이 확률모형에 포함될 수 있다. (자세한 내용은 [확률통계 기초용어 - EG 공간](https://kongdols-room.tistory.com/131) 참고) @@ -132,9 +115,9 @@ $$ --> - 확률밀도함수(PDF, Probability Density Function) - 연속형 - 누적분포함수(CDF, Cumulative Distribution Function) -✔︎ 추가적으로 **확률 통계의 기초 용어**를 정리하면 다음과 같다. (주사위 굴리기 예제 사용) +추가적으로 **확률 통계의 기초 용어**를 정리하면 다음과 같다. (주사위 굴리기 예제 사용) -``` +```text - 실험(Experiment)은 하나의 행위가 하나 이상의 결과를 도출하는 것에 대한 과정 혹은 절차를 나타낸다. - 예시) 주사위를 던진다. - 결과(Outcome)는 어떤 실험에 의해 발생 가능한 결과이다. 특정 실험의 가능한 결과들은 각각 유일(unique)하다. 한번의 실험을 시행했을 때, 단 하나의 outcome만을 나타낸다. @@ -158,39 +141,27 @@ $$ --> ## #4 -#### 누적 분포 함수와 확률 밀도 함수는 무엇일까요? 수식과 함께 표현해주세요. +### 누적 분포 함수와 확률 밀도 함수는 무엇인가요? 수식과 함께 표현해주세요. -확률 변수 가 임의의 실수 집합 에 포함되는 사건의 확률이 다음과 같이 어떤 음이 아닌 함수 의 적분으로 주어진다고 하자. +확률 변수 $X$가 임의의 실수 집합 $B$에 포함되는 사건의 확률이 다음과 같이 어떤 음이 아닌 함수 $f$의 적분으로 주어진다고 하자. - - - +$$ -
+이 때의 $X$를 연속확률변수라고 하며, 함수 $f(x)$를 확률 밀도 함수(Probability Density Function, PDF)라고 한다. 단, 실수 집합 $B$가 실수 전체일 경우 실수 전체에 대한 확률밀도함수의 적분은 1을 만족해야 한다. -이 때의 를 연속확률변수라고 하며, 함수 를 `확률 밀도 함수(Probability Density Function, PDF)`라고 한다. 단, 실수 집합 가 실수 전체일 경우 실수 전체에 대한 확률밀도함수의 적분은 1을 만족해야 한다. - - - - - -
+$$ -`누적 분포 함수(Cumulative Distribution Function, CDF)`는 확률변수가 특정 값보다 작거나 같을 확률을 나타내는 함수이다. 특정 값을 라고 할 때, 누적 분포 함수는 다음과 같이 나타낼 수 있다. +누적 분포 함수(Cumulative Distribution Function, CDF)는 확률변수가 특정 값보다 작거나 같을 확률을 나타내는 함수이다. 특정 값을 $a$라고 할 때, 누적 분포 함수는 다음과 같이 나타낼 수 있다. - - - - -
+$$ -확률 밀도 함수와 누적 분포 함수는 `미분과 적분의 관계`를 갖는다. 확률 밀도 함수를 음의 무한대에서 특정값 까지 적분을 하면, 에 대한 누적 분포 함수를 얻을 수 있다. 반대로 누적 분포 함수를 미분하면 확률 밀도 함수를 얻을 수 있다. +확률 밀도 함수와 누적 분포 함수는 **미분과 적분의 관계**를 갖는다. 확률 밀도 함수를 음의 무한대에서 특정값 $a$까지 적분을 하면, $a$에 대한 누적 분포 함수를 얻을 수 있다. 반대로 누적 분포 함수를 미분하면 확률 밀도 함수를 얻을 수 있다. #### References @@ -201,25 +172,22 @@ $$ --> ## #5 -#### 조건부 확률은 무엇일까요? +### 조건부 확률은 무엇인가요? -조건부 확률은 사건 A 가 일어났다는 전제 하에 사건 B 가 일어날 확률이다. 이는 P(B|A) = P(B∩A) / P(A) 로 표현 가능하다. 조건부 확률은 베이즈 정리와도 이어지며, 조건부 확률을 이용한 가장 유명한 문제는 [몬티홀 문제](https://terms.naver.com/entry.naver?docId=3569086&cid=58944&categoryId=58970)가 있다. +조건부 확률은 사건 $A$가 일어났다는 전제 하에 사건 $B$가 일어날 확률이다. 이는 $P(B|A) = P(B \cap A) / P(A)$로 표현 가능하다. 조건부 확률은 **베이즈 정리**와도 이어지며, 조건부 확률을 이용한 가장 유명한 문제는 [몬티홀 문제](https://terms.naver.com/entry.naver?docId=3569086&cid=58944&categoryId=58970)가 있다. > **베이즈 정리** -베이즈 정리를 통해 가능도와 Evidence를 바탕으로 사전확률을 사후확률로 업데이트한다. +베이즈 정리를 통해 가능도(Likelihood)와 증거(Evidence)를 바탕으로 사전확률을 사후확률로 업데이트한다. -
- -
-
+![베이즈 정리](./img/1-statistics-math/probability.png) -- : 새로 관찰되는 데이터 -- : 모델에서 계산하고 싶어하는 모수 (가설) -- 사후확률 : 데이터를 관찰했을 때, 이 가설이 성립할 확률 (데이터 관찰 이후 측정하기 때문에 사후확률) -- 사전확률 : 가설에 대해 사전에 세운 확률 (데이터 관측 이후 사후확률이 사전확률이 된다.) -- 가능도 : 현재 주어진 모수 (가정) 에서 이 데이터가 관찰될 가능성 -- Evidence : 데이터 전체의 분포 +- $D$: 새로 관찰되는 데이터 +- $\theta$: 모델에서 계산하고 싶어하는 모수 (가설) +- 사후확률(Posterior): 데이터를 관찰했을 때, 이 가설이 성립할 확률 (데이터 관찰 이후 측정하기 때문에 사후확률) +- 사전확률(Prior): 가설에 대해 사전에 세운 확률 (데이터 관측 이후 사후확률이 사전확률이 된다.) +- 가능도(Likelihood): 현재 주어진 모수 (가정) 에서 이 데이터가 관찰될 가능성 +- 증거(Evidence): 데이터 전체의 분포 #### References @@ -230,17 +198,13 @@ $$ --> ## #6 -#### 공분산과 상관계수는 무엇일까요? 수식과 함께 표현해주세요. +### 공분산과 상관계수는 무엇일까요? 수식과 함께 표현해주세요. 공분산은 확률변수 X의 편차(평균으로부터 얼마나 떨어져 있는지)와 확률변수 Y의 편차를 곱한 것의 평균값이다. - - - - -
+$$ 공분산은 두 변수 간에 양의 상관관계가 있는지, 음의 상관관계가 있는지 정도를 알려준다. 하지만 상관관계가 얼마나 큰지는 제대로 반영하지 못한다. @@ -248,13 +212,9 @@ $$ --> 상관계수는 확률변수의 절대적 크기에 영향을 받지 않도록 공분산을 단위화시킨 것이다. 즉, 공분산에 각 확률변수의 분산을 나눠주었다. - - - - -
+$$ 상관계수는 양의 상관관계가 있는지 음의 상관관계가 있는지 알려줄 뿐만 아니라, 그 상관성이 얼마나 큰지도 알려준다. 1 또는 -1에 가까울수록 상관성이 큰 것이고, 0에 가까울수록 상관성이 작은 것이다. @@ -267,24 +227,21 @@ $$ --> ## #7 -#### 신뢰 구간의 정의는 무엇인가요? +### 신뢰 구간의 정의는 무엇인가요? -구간 추정에서 `모수가 a 에서 b 사이에 있을 것으로 추정(신뢰구간)`하고 `그 확률(%, 신뢰수준)`을 구한다. +구간 추정에서 모수가 a 에서 b 사이에 있을 것으로 추정(신뢰구간)하고 그 확률(%, 신뢰수준)을 구한다. -
- -
-
+![신뢰수준과 신뢰구간](./img/1-statistics-math/confidence-level.png) **신뢰구간(Confidence Interval)** 은 모집단의 모수(parameter)가 위치해 있을 것으로 신뢰할 수 있는 구간이다. 모수가 어느 범위 안에 있는지를 확률적으로 보여주는 방법이라고 할 수 있다. 신뢰구간을 구하는 이유는 모수의 신뢰성을 가늠하기 위함이다. -추가적으로, 신뢰구간에 대한 정확한 해석은 `모평균을 포함할 확률이 95%가 되는 구간`이 아닌, `같은 방법으로 100번 표본을 추출했을 때, 함께 계산되는 100개의 신뢰구간 중 모평균을 포함한 신뢰구간들의 숫자가 95개정도 된다`라고 해야한다. 왜냐면, `모평균은 이미 정해져 있는 값`이므로 전자의 해석을 사용할 수 없기 때문이다. +추가적으로, 신뢰구간에 대한 정확한 해석은 모평균을 포함할 확률이 95%가 되는 구간이 아닌, 같은 방법으로 100번 표본을 추출했을 때, 함께 계산되는 100개의 신뢰구간 중 모평균을 포함한 신뢰구간들의 숫자가 95개정도 된다라고 해야한다. 왜냐면, 모평균은 이미 정해져 있는 값이므로 전자의 해석을 사용할 수 없기 때문이다. **신뢰수준**은 방법의 정확도, 참값을 구하기 위한 작업을 많이 반복했을 때, 참값이 특정 범위에 있는 비율이다. -**모수(parameter)** 는 모집단의 특성을 보여주는 값이다. 예를들어, 평균, 분산 등의 고정인 값이 있을 수 있다. +**모수(Parameter)** 는 모집단의 특성을 보여주는 값이다. 예를들어, 평균, 분산 등의 고정인 값이 있을 수 있다. #### References @@ -296,13 +253,13 @@ $$ --> ## #8 -#### p-value를 모르는 사람에게 설명한다면 어떻게 설명하실 건가요? +### p-value를 모르는 사람에게 설명한다면 어떻게 설명하실 건가요? -`p-value`를 알기 위해서는 먼저 1종 오류를 알아야 한다. 여기서 1종 오류란 "귀무가설이 참인데 기각한 경우"을 말한다. 귀무가설이란 기존의 주장을 말하며, 이와 반대로 새로운 주장을 대립가설이라고 한다. +p-value를 알기 위해서는 먼저 1종 오류를 알아야 한다. 여기서 1종 오류란 **귀무가설이 참인데 기각한 경우**을 말한다. 귀무가설이란 기존의 주장을 말하며, 이와 반대로 새로운 주장을 대립가설이라고 한다. 예를 들어, 어느 제약회사에서 치료약 A를 개발했다. 기존에는 치료약 A가 없었으므로 귀무가설은 "치료약 A가 효과가 없다"라고 설정한다. 반대로 대립가설은 "치료약 A는 효과가 있다"로 설정한다. 회사에서는 검정을 한 결과, 귀무가설을 기각하고 대립가설을 채택했다. 치료약 A는 판매되었고 높은 매출을 기록했다. 그런데 알고보니 치료약 A가 효과가 없다는 것이 밝혀졌다. 참인 귀무가설을 기각했기에 이는 1종 오류가 일어났다고 볼 수 있다. -다시 돌아와서 `p-value`는 1종 오류를 범할 확률을 말한다. 예를 들어, p-value가 5%라면, 100번 중 5번 1종 오류가 발생한다는 말이다. 검정을 할 때는 유의 수준 를 정하는데, 이것이 1종 오류의 상한선이 된다. 그래서 유의 수준보다 p-value가 작다면 실험의 오류가 상한선보다 작으므로 귀무가설을 기각하고 대립가설을 채택한다. 만약 크다면 상한선을 넘었으므로 귀무가설을 채택한다. +다시 돌아와서 p-value는 **1종 오류를 범할 확률**을 말한다. 예를 들어, p-value가 5%라면, 100번 중 5번 1종 오류가 발생한다는 말이다. 검정을 할 때는 유의 수준 $\alpha$를 정하는데, 이것이 1종 오류의 상한선이 된다. 그래서 유의 수준보다 p-value가 작다면 실험의 오류가 상한선보다 작으므로 귀무가설을 기각하고 대립가설을 채택한다. 만약 크다면 상한선을 넘었으므로 귀무가설을 채택한다. #### References @@ -315,22 +272,21 @@ $$ --> ## #9 -#### R square의 의미는 무엇인가요? +### R square의 의미는 무엇인가요? -결정계수 (R square) 는 선형 회귀 모델에서 데이터에 대해 회귀선이 얼마나 잘 설명하는지에 대한 설명력을 의미한다. 결정계수는 0~1 의 값을 가질 수 있고, 만약 값이 1 이라면 회귀선으로 모든 데이터를 다 설명할 수 있다고 이해할 수 있다. +결정계수(R square)는 선형 회귀 모델에서 데이터에 대해 회귀선이 얼마나 잘 설명하는지에 대한 설명력을 의미한다. 결정계수는 0~1 의 값을 가질 수 있고, 만약 값이 1 이라면 회귀선으로 모든 데이터를 다 설명할 수 있다고 이해할 수 있다. 참고로 결정계수는 다음의 식으로 구할 수 있다. -> - -SSE = sum((추정값-관측값 평균)^2), -SST = sum((관측값-관측값 평균)^2), -SSR = sum((관측값-추정값)^2) +$$ +R^2 = SSE/SST = 1 - SSR/SST +$$ -- 관측값 : 실제 데이터의 값, -- 추정값 : 회귀 모델을 통해 나온 값. +- SSE(**E**xplained **S**um of **S**quares) = $\sum(\text{추정값 - 관측값 평균})^2$ +- SST(**T**otal **S**um of **S**quares) = $\sum(\text{관측값 - 관측값 평균})^2$ +- SSR(**R**esidual **S**um of **S**quares) = $SSR = \sum(\text{관측값 - 추정값})^2$ -회귀 모델의 성능을 평가하는 방법은 결정계수 외에도 MAE, MSE, RMSE 가 있다. +관측값은 실제 데이터의 값을 말하며, 추정값은 회귀 모델을 통해 나온 값을 말한다. 회귀 모델의 성능을 평가하는 방법은 결정계수 외에도 MAE, MSE, RMSE 가 있다. #### References @@ -342,14 +298,14 @@ SSR = sum((관측값-추정값)^2) ## #10 -#### 평균(mean)과 중앙값(median)중에 어떤 케이스에서 뭐를 써야할까요? +### 평균(mean)과 중앙값(median)중에 어떤 케이스에서 뭐를 써야할까요? -- 평균(mean): 모든 관측값의 합을 자료의 개수로 나눈 것 -- 중앙값(median): 전체 관측값을 크기 순서로 배열했을 때 가운데 위치하는 값 +- `평균(mean)`: 모든 관측값의 합을 자료의 개수로 나눈 것 +- `중앙값(median)`: 전체 관측값을 크기 순서로 배열했을 때 가운데 위치하는 값 -평균은 전체 관측값이 골고루 반영되므로 대표값으로서 가치가 있다. 평균 근처에 표본이 몰려 있는 상황에서 대표값으로 유용하지만 극단적인 값에 영향을 많이 받는다. +평균은 전체 관측값이 골고루 반영되므로 대표값으로서 가치가 있다. 평균 근처에 **표본이 몰려 있는 상황에서 대표값으로 유용**하지만 극단적인 값에 영향을 많이 받는다. -중앙값에서는 관측값을 크기 순서로 배열할 때 관측값의 위치가 중요하고, 가운데 위치한 관측값 이외의 관측값들의 크기는 중요하지 않다. 따라서 평균과는 달리 중앙값은 관측값들의 변화에 민감하지 않고 특히 아주 큰 관측값이나 아주 작은 관측값(즉, outlier)에 영향을 받지 않는다. 중앙값이 유용한 경우는 표본의 편차, 혹은 왜곡이 심하게 나타나는 경우이다. +중앙값에서는 관측값을 크기 순서로 배열할 때 관측값의 위치가 중요하고, 가운데 위치한 관측값 이외의 관측값들의 크기는 중요하지 않다. 따라서 평균과는 달리 중앙값은 관측값들의 변화에 민감하지 않고 특히 아주 큰 관측값이나 아주 작은 관측값(즉, outlier)에 영향을 받지 않는다. 중앙값이 유용한 경우는 **표본의 편차, 혹은 왜곡이 심하게 나타나는 경우**이다. #### References @@ -360,10 +316,9 @@ SSR = sum((관측값-추정값)^2) ## #11 -#### 중심극한정리는 왜 유용한걸까요? +### 중심극한정리는 왜 유용한걸까요? -**중심극한정리**란 크기가 n인 표본추출(30개 이상)이 무수히 많이 수행되면(최소 100회 이상을 의미), 표본 평균의 분포가 정규분포에 수렴한다는 것이다. -중심극한정리가 유용한 이유는 모집단의 형태가 어떻든지 간에 상관없이 표본 평균의 분포가 정규분포를 따르기 때문이다. +**중심극한정리**란 크기가 n인 표본추출(30개 이상)이 무수히 많이 수행되면(최소 100회 이상을 의미), 표본 평균의 분포가 정규분포에 수렴한다는 것이다. 중심극한정리가 유용한 이유는 **모집단의 형태가 어떻든지 간에 상관없이 표본 평균의 분포가 정규분포를 따르기 때문**이다. #### References @@ -373,23 +328,17 @@ SSR = sum((관측값-추정값)^2) ## #12 -#### 엔트로피(Entropy)에 대해 설명해주세요. 가능하면 정보이득(Information Gain)도요. +### 엔트로피(Entropy)에 대해 설명해주세요. 가능하면 정보이득(Information Gain)도요. -> 엔트로피는 entropy로, 정보이득은 information gain으로 모두 영어로 표기합니다. +**엔트로피**는 주어진 데이터의 혼잡도를 의미하며, 엔트로피는 다음과 같이 데이터가 어떤 클래스에 속할 확률에 대한 기댓값으로 표현할 수 있다. -`entropy`는 주어진 데이터의 혼잡도를 의미하며, entropy는 다음과 같이 데이터가 어떤 클래스에 속할 확률에 대한 기댓값으로 표현할 수 있다. - - - - - -
+$$ -entropy는 데이터가 서로 다른 클래스에 속하면 높고, 같은 클래스에 속하면 낮다. 다시 말하면 각각의 데이터가 특정 클래스에 속할 확률이 높고 나머지 클래스에 속할 확률이 낮다면 entropy가 낮고, 모든 각각의 클래스에 속할 확률이 비슷하다면 entropy는 높다. +엔트로피는 데이터가 서로 다른 클래스에 속하면 높고, 같은 클래스에 속하면 낮다. 다시 말하면 각각의 데이터가 특정 클래스에 속할 확률이 높고 나머지 클래스에 속할 확률이 낮다면 엔트로피가 낮고, 모든 각각의 클래스에 속할 확률이 비슷하다면 엔트로피는 높다. -`information gain`은 데이터가 어떤 클래스에 속할 확률이 커짐에 따라 정보를 잘 얻게되는 것을 말하며, 감소되는 entropy 양을 의미한다. 수식으로는 기존 시스템의 엔트로피에서 현재 엔트로피를 뺀 값으로 표현된다. 의사결정트리는 가지를 칠 때 이 값을 사용하여 가지를 친다. 이 때 어떤 데이터를 두 집합으로 나누었을 때 두 집합의 information gain이 크도록, entropy는 작아지도록 분할을 한다. +**정보이득**은 데이터가 어떤 클래스에 속할 확률이 커짐에 따라 정보를 잘 얻게되는 것을 말하며, 감소되는 엔트로피 양을 의미한다. 수식으로는 기존 시스템의 엔트로피에서 현재 엔트로피를 뺀 값으로 표현된다. 의사결정트리는 가지를 칠 때 이 값을 사용하여 가지를 친다. 이 때 어떤 데이터를 두 집합으로 나누었을 때 두 집합의 정보이득이 크도록, 엔트로피는 작아지도록 분할을 한다. #### References @@ -401,13 +350,13 @@ entropy는 데이터가 서로 다른 클래스에 속하면 높고, 같은 클 ## #13 -#### 어떨 때 모수적 방법론을 쓸 수 있고, 어떨 때 비모수적 방법론을 쓸 수 있나요? +### 어떨 때 모수적 방법론을 쓸 수 있고, 어떨 때 비모수적 방법론을 쓸 수 있나요? -표본의 통계량 (평균, 표준편차 등) 을 통해 모집단의 모수 (모평균, 모표준편차 등) 를 추정하는 방법을 통계적 추론이라고 한다. +표본의 통계량(평균, 표준편차 등)을 통해 모집단의 모수(모평균, 모표준편차 등)를 추정하는 방법을 통계적 추론이라고 한다. -모집단이 어떤 분포를 따른다는 가정 하에 통계적 추론을 하는 방법을 모수적 방법이라 하는데, 표본의 수가 30개 이상일 때 중심극한 정리에 의해 정규분포를 따르므로 모수적 방법론을 사용한다. +모집단이 어떤 분포를 따른다는 가정 하에 통계적 추론을 하는 방법을 모수적 방법이라 하는데, 표본의 수가 30개 이상일 때 중심극한 정리에 의해 정규분포를 따르므로 **모수적 방법론**을 사용한다. -반대로, 모집단의 분포를 가정하지 않는 비모수적 방법은, 표본의 수가 30개 미만이거나 정규성 검정에서 정규 분포를 따르지 않는다고 증명되는 경우 비모수적 방법론을 사용한다. +반대로, 모집단의 분포를 가정하지 않는 비모수적 방법은, 표본의 수가 30개 미만이거나 정규성 검정에서 정규 분포를 따르지 않는다고 증명되는 경우 **비모수적 방법론**을 사용한다. #### References @@ -417,10 +366,11 @@ entropy는 데이터가 서로 다른 클래스에 속하면 높고, 같은 클 ## #14 -#### "likelihood"와 "probability"의 차이는 무엇일까요? +### "likelihood"와 "probability"의 차이는 무엇일까요? -- 확률(Probability): 어떤 시행(trial, experiment)에서 특정 결과(sample)가 나올 가능성. 즉, **시행 전 모든 경우의 수의 가능성은 정해져 있으며 그 총합은 1(100%)이다.** -- 가능도(Likelihood): 어떤 시행(trial, experiment)을 충분히 수행한 뒤 그 결과(sample)를 토대로 경우의 수의 가능성을 도출하는 것. 아무리 충분히 수행해도 어디까지나 추론(inference)이기 때문에 **가능성의 합이 1이 되지 않을수도 있다.** +확률(Probability)은 어떤 시행(trial)에서 특정 결과(sample)가 나올 가능성을 말한다. 즉, 시행 전 모든 경우의 수의 가능성은 정해져 있으며 그 총합은 1(100%)이다. + +가능도(Likelihood)은 어떤 시행(trial)을 충분히 수행한 뒤 그 결과(sample)를 토대로 경우의 수의 가능성을 도출하는 것을 말한다. 아무리 충분히 수행해도 어디까지나 추론(inference)이기 때문에 가능성의 합이 1이 되지 않을수도 있다. PDF(probability density function)에서는 **확률변수**를 변수로 보기 때문에 총합이 1이지만, likelihood function에서는 **분포의 모수**를 변수로 보기 때문에 총합이 1이 되지 않을수도 있다. @@ -432,19 +382,23 @@ PDF(probability density function)에서는 **확률변수**를 변수로 보기 ## #15 -#### 통계에서 사용되는 bootstrap의 의미는 무엇인가요. +### 통계에서 사용되는 bootstrap의 의미는 무엇인가요. -**부트스트랩(Bootstrap)** 은 가설검증을 하거나 metric을 계산하기 전에 random sampling을 적용하는 방법이다. -모수의 분포를 추정하는 방법 중 하나는, 현재 가진 표본에서 추가적으로 표본을 복원추출하고 각 표본에 대한 통계량을 다시 계산하는 것이다. +**부트스트랩(Bootstrap)** 은 가설검증을 하거나 metric을 계산하기 전에 random sampling을 적용하는 방법이다. 모수의 분포를 추정하는 방법 중 하나는, 현재 가진 표본에서 추가적으로 표본을 복원추출하고 각 표본에 대한 통계량을 다시 계산하는 것이다. 부트스트랩이 여기에 해당하며, 여러번의 무작위 추출을 통해, 평균의 신뢰구간을 구할 수 있다. + 200개로만 통계량을 구하는 것이 아니라 200개를 기준으로 복원 추출하여 새로운 통계량을 구하는 것을 예시로 들 수 있다. -**(참고)** 머신러닝에서의 bootstrap은 아래와 같이 해석될 수 있다. +> **머신러닝에서 부트스트램의 의미** -- 랜덤 샘플링을 통해 train data를 늘리는 방법 -- 여러 모델을 학습시켜, 추론(inference) 결과의 평균을 사용하는 방법(앙상블) +머신러닝에서 부트스트랩은 아래와 같이 해석될 수 있다. -> 복원추출(Sampling with replacement)이란 확률을 구할 때, 추출했던 것을 원래대로 돌려놓고 다시 추출하는 방법 +- 랜덤 샘플링을 통해 학습 데이터를 늘리는 방법 +- 여러 모델을 학습시켜 추론 결과의 평균을 사용하는 방법(=앙상블) + +> **복원추출이란?** + +복원추출(Sampling with replacement)이란 확률을 구할 때, 추출했던 것을 원래대로 돌려놓고 다시 추출하는 방법을 말한다. #### References @@ -456,11 +410,11 @@ PDF(probability density function)에서는 **확률변수**를 변수로 보기 ## #16 -#### 모수가 매우 적은 (수십개 이하) 케이스의 경우 어떤 방식으로 예측 모델을 수립할 수 있을까요? +### 모수가 매우 적은 (수십개 이하) 케이스의 경우 어떤 방식으로 예측 모델을 수립할 수 있을까요? -> 모수는 모집단의 수가 아닌, 평균, 표준편차 등의 모집단의 특징을 말합니다. 여기서는 모집단의 수로 잘못 쓰인 것으로 보이며, 데이터가 적은 경우라 가정하고 답변을 작성하였습니다. +> _모수는 모집단의 수가 아닌, 평균, 표준편차 등의 모집단의 특징을 말합니다. 여기서는 모집단의 수로 잘못 쓰인 것으로 보이며, 데이터가 적은 경우라 가정하고 답변을 작성하였습니다._ -표본이 매우 작은 경우 표본평균의 분포가 정규분포를 따른다고 가정할 수 없으므로 비모수적 방법을 채택하여 예측 모델을 수립할 수 있다. 하지만 중심극한정리에 의해 표본의 크기가 30보다 클 경우 표본평균이 정규분포를 따른다고 가정할 수 있으므로, 이 경우에는 모수적 방법을 사용한다. +표본이 매우 작은 경우 표본평균의 분포가 정규분포를 따른다고 가정할 수 없으므로 **비모수적 방법**을 채택하여 예측 모델을 수립할 수 있다. 하지만 중심극한정리에 의해 표본의 크기가 30보다 클 경우 표본평균이 정규분포를 따른다고 가정할 수 있으므로, 이 경우에는 모수적 방법을 사용한다. #### References @@ -472,7 +426,7 @@ PDF(probability density function)에서는 **확률변수**를 변수로 보기 ## #17 -#### 베이지안과 프리퀀티스트 간의 입장차이를 설명해주실 수 있나요? +### 베이지안과 프리퀀티스트 간의 입장차이를 설명해주실 수 있나요? 베이지안은 사건의 확률을 바라볼 때, 사전 확률을 미리 염두해두고 사건의 발생에 따라 베이즈 정리로 사후 확률을 구해 다시 사전 확률을 업데이트시킨다. 즉, 베이지안은 **과거의 사건이 현재 사건에 영향을 끼친다는 입장**을 가지고 있다. @@ -486,19 +440,16 @@ PDF(probability density function)에서는 **확률변수**를 변수로 보기 ## #18 -#### 검정력(statistical power)은 무엇일까요? +### 검정력(statistical power)은 무엇일까요? -| | 귀무가설 H0 참 | 귀무가설 H0 거짓 | +| | 귀무가설 H0 참 | 귀무가설 H0 거짓 | | :--------------: | :------------: | :--------------------: | | 귀무가설 H0 채택 | 옳은 결정(1-α) | 제 2종 오류(β) | | 귀무가설 H0 기각 | 제 1종 오류(α) | 옳은 결정(1-β), 검정력 | 검정력은 대립가설 H1이 참인 경우 귀무가설 H0를 기각(대립가설 H1을 채택)할 확률이다. -
- -
-
+![검정력](./img/1-statistics-math/hypothesis.png) #### References @@ -510,29 +461,25 @@ PDF(probability density function)에서는 **확률변수**를 변수로 보기 ## #19 -#### missing value가 있을 경우 채워야 할까요? 그 이유는 무엇인가요? +### missing value가 있을 경우 채워야 할까요? 그 이유는 무엇인가요? missing value를 처리하는 방법에는 크게 4가지가 있다. -1. 그대로 놔두기: 누락된 데이터를 그대로 놔두는 방법이다. -2. 삭제하기: 누락된 데이터를 제거하는 방법이다. 그러나 중요한 정보를 가진 데이터를 잃을 위험이 있다. -3. 특정 값으로 채우기: 0, 빈번한 값, 지정한 상수값으로 채우기 -4. 예측하여 채우기: K-means, 평균값, 중앙값으로 대체하는 것 +1. `그대로 놔두기`: 누락된 데이터를 그대로 놔두는 방법이다. +2. `삭제하기`: 누락된 데이터를 제거하는 방법이다. 그러나 중요한 정보를 가진 데이터를 잃을 위험이 있다. +3. `특정 값으로 채우기`: 0, 빈번한 값, 지정한 상수값으로 채우기 +4. `예측하여 채우기`: K-means, 평균값, 중앙값으로 대체하는 것 1번 방법을 사용하여, 데이터가 누락된 채로 놔둔다고 가정하자. 일부 xgboost같은 알고리즘은 결측값을 고려하여 잘 학습한다. -그러나 `결측치를 처리하는 로직이 없는 알고리즘(ex. sklearn의 LinearRegression)은 누락된 데이터 때문에 엉망이 될 수 있다.` +그러나 **결측치를 처리하는 로직이 없는 알고리즘(ex. sklearn의 LinearRegression)은 누락된 데이터 때문에 엉망이 될 수 있다.** 따라서 결측치를 처리해주어야한다. -2번 방법을 사용하여, 누락된 데이터를 제거한다고 해보자. -제거하는 방법은 가장 쉬운 방법이다. -그러나 만약 100명 중 한명의 특징(feature)이 누락된 상태이므로, 해당 특징을 전부 삭제한다면 중요한 특성을 잃어버리는 결과를 초래하게 된다. +2번 방법을 사용하여, 누락된 데이터를 제거한다고 해보자. 제거하는 방법은 가장 쉬운 방법이다. 그러나 만약 100명 중 한명의 특징(feature)이 누락된 상태이므로, 해당 특징을 전부 삭제한다면 중요한 특성을 잃어버리는 결과를 초래하게 된다. -3번, 4번 방법을 사용하여 결측치를 채운다고 해보자. -결측치를 채움으로서, 중요한 정보를 잃지않고 특성을 유지할 수 있다. -그러나 만약 100명 중 99명의 특징이 누락된 상태라고 한다면, 해당 특징을 어떠한 값으로 채우는 행위가 무의미할 것이다. +3번, 4번 방법을 사용하여 결측치를 채운다고 해보자. 결측치를 채움으로서, 중요한 정보를 잃지않고 특성을 유지할 수 있다. 그러나 만약 100명 중 99명의 특징이 누락된 상태라고 한다면, 해당 특징을 어떠한 값으로 채우는 행위가 무의미할 것이다. -따라서 `결측치 상태나 비율, 어떤 모델을 사용할 것인지`에 따라서 결측치 대응 방법이 달라질 수 있다. +따라서 **결측치 상태나 비율, 어떤 모델을 사용할 것인지**에 따라서 결측치 대응 방법이 달라질 수 있다. #### References @@ -542,13 +489,13 @@ missing value를 처리하는 방법에는 크게 4가지가 있다. ## #20 -#### 아웃라이어의 판단하는 기준은 무엇인가요? +### 아웃라이어의 판단하는 기준은 무엇인가요? -`이상치(outlier)`는 전체 데이터의 패턴에서 벗어난 이상한 값을 가진 데이터를 말한다. 이상치는 모델의 성능에 영향을 미치므로 이를 탐지하는 것은 정말 중요하다. +이상치(outlier)는 전체 데이터의 패턴에서 벗어난 이상한 값을 가진 데이터를 말한다. 이상치는 모델의 성능에 영향을 미치므로 이를 탐지하는 것은 정말 중요하다. -이상치를 탐지하는 방법 중 하나로 IQR(Inter Quantile Range) 기법이 있다. IQR 기법을 사용하기 위해서는 우선 데이터를 오름차순으로 정렬하고 25%, 50%, 75%, 100%로 4등분을 한다. 이 75% 지점과 25% 지점의 값의 차이를 IQR이라고 한다. 이 IQR에 1.5를 곱한 값을 75% 지점의 값에 더하여 최대값을, 25% 지점의 값에서 빼서 최소값을 계산한다. 이 때 최소값보다 작거나 최대값보다 큰 값을 이상치라고 판단한다. +이상치를 탐지하는 방법 중 하나로 **IQR(Inter Quantile Range) 기법**이 있다. IQR 기법을 사용하기 위해서는 우선 데이터를 오름차순으로 정렬하고 25%, 50%, 75%, 100%로 4등분을 한다. 이 75% 지점과 25% 지점의 값의 차이를 IQR이라고 한다. 이 IQR에 1.5를 곱한 값을 75% 지점의 값에 더하여 최대값을, 25% 지점의 값에서 빼서 최소값을 계산한다. 이 때 최소값보다 작거나 최대값보다 큰 값을 이상치라고 판단한다. -또 다른 탐지 방법으로는 Z-score를 계산하는 방식이 있다. Z-score는 데이터가 평균에서 얼마나 떨어져 있는지를 나타내는 지표로, 임계값을 설정하여 Z-score이 이 값보다 크다면 이상치로 판단한다. 하지만 Z-score 방식은 데이터가 가우시안 분포를 따른다고 가정하기 때문에 데이터가 가우시안 분포가 아닐 경우 별도의 변환이 필요하다. +또 다른 탐지 방법으로는 **Z-score를 계산하는 방식**이 있다. Z-score는 데이터가 평균에서 얼마나 떨어져 있는지를 나타내는 지표로, 임계값을 설정하여 Z-score이 이 값보다 크다면 이상치로 판단한다. 하지만 Z-score 방식은 데이터가 가우시안 분포를 따른다고 가정하기 때문에 데이터가 가우시안 분포가 아닐 경우 별도의 변환이 필요하다. #### References @@ -560,14 +507,13 @@ missing value를 처리하는 방법에는 크게 4가지가 있다. ## #21 -#### 필요한 표본의 크기를 어떻게 계산합니까? +### 필요한 표본의 크기를 어떻게 계산합니까? -먼저 **모집단의 크기 : N** 을 구하고, **신뢰수준 : z** 와 **오차범위 : e** 를 얼마로 할지 선정하여 표본의 크기를 구할 수 있다. +먼저 **모집단의 크기 $N$** 을 구하고, **신뢰수준 $z$** 와 **오차범위 $e$** 를 얼마로 할지 선정하여 표본의 크기를 구할 수 있다. -
- -
-
+$$ +\frac{\frac{z^2 \times p(1-p)}{e^2}}{1 + (\frac{z^2 \times p(1-p)}{e^2 N})} +$$ 참고로 신뢰수준은 표본추출을 반복했을 때 얼마나 그 결과를 신뢰할 수 있는지에 대한 정도로 95% 를 주로 사용한다. @@ -582,38 +528,21 @@ missing value를 처리하는 방법에는 크게 4가지가 있다. ## #22 -#### Bias를 통제하는 방법은 무엇입니까? +### Bias를 통제하는 방법은 무엇입니까? -
- -
-
+![언더피팅과 오버피팅](./img/1-statistics-math/underfit-right-overfit.png) -Bias는 데이터 내에 있는 모든 정보를 고려하지 않음으로 인해, 지속적으로 잘못된 것들을 학습하는 경향을 의미한다. 이는 underfitting과 관계되어 있다. +편향(Bias)는 데이터 내에 있는 모든 정보를 고려하지 않음으로 인해, 지속적으로 잘못된 것들을 학습하는 경향을 의미한다. 이는 언더피팅(Underfitting)과 관계되어 있다. -반대로 Variance는 데이터 내에 있는 에러나 노이즈까지 잘 잡아내는 highly flexible models에 데이터를 fitting 시킴으로써, 실제 현상과 관계 없는 random한 것들까지 학습하는 알고리즘의 경향을 의미한다. 이는 overfitting과 관계되어 있다. +반대로 분산(Variance)는 데이터 내에 있는 에러나 노이즈까지 잘 잡아내는 highly flexible models에 데이터를 피팅시킴으로써, 실제 현상과 관계 없는 랜덤한 것들까지 학습하는 알고리즘의 경향을 의미한다. 이는 오버피팅(Overfitting)과 관계되어 있다. -
- -
-
+![편향과 분산](./img/1-statistics-math/variance-bias.png) 편향(Bias)과 분산(Variance)은 한 쪽이 증가하면 다른 한 쪽이 감소하고, 한쪽이 감소하면 다른 한쪽이 증가하는 tradeoff 관계를 가진다. -
- -
-
- -Bias를 통제하기 위한 방법으로는 +![편향과 분산의 트레이드오프 관계](./img/1-statistics-math/bias-variance-tradeoff.png) -- (neuron이나 계층의 갯수 같은) 모델의 크기 증가 -- 오류평가시 얻은 지식을 기반으로 입력 특성 수정 -- 정규화 -- 모델 구조를 수정 -- 학습 데이터 추가 - -등의 방법이 있다. +**Bias를 통제하기 위한 방법**으로는 뉴런이나 계층의 개수가 같은 모델의 크기 증가, 오류평가시 얻은 지식을 기반으로 입력 특성 수정, 정규화, 모델 구조를 수정, 학습 데이터 추가 등의 방법이 있다. #### References @@ -625,25 +554,25 @@ Bias를 통제하기 위한 방법으로는 ## #23 -#### 로그 함수는 어떤 경우 유용합니까? 사례를 들어 설명해주세요. +### 로그 함수는 어떤 경우 유용합니까? 사례를 들어 설명해주세요. + +우선 **단위 수가 너무 큰 값들을 바로 회귀분석 할 경우 결과를 왜곡할 우려가 있으므로 이를 방지하기 위해 사용**된다. -아래와 같은 경우에 로그함수가 유용하다. +예를들어, 나이와 재산보유액의 관계를 회귀분석으로 푼다고 했을 때, 재산보유액의 숫자가 굉장히 클 수 있다. +재산보유액에 로그를 취할 경우, 데이터의 왜도와 첨도를 줄일 수 있어 정규성이 높아지는 효과를 얻는다. -1. 단위 수가 너무 큰 값들을 바로 회귀분석 할 경우, 결과를 왜곡할 우려가 있으므로 이를 방지하기 위해 사용된다. - ``` - 예를들어, 나이와 재산보유액의 관계를 회귀분석으로 푼다고 했을 때, 재산보유액의 숫자가 굉장히 클 수 있다. - 재산보유액에 로그를 취할 경우, 데이터의 왜도와 첨도를 줄일 수 있어 정규성이 높아지는 효과를 얻는다. - ``` -2. 비선형관계의 데이터를 선형으로 만들기 위해 사용된다. - ``` - 예를들어, 기하급수적으로 늘어나는 제곱 형식의 그래프에 자연로그를 취하면 그 관계가 직선(선형)이 된다. - ``` +또한 **비선형관계의 데이터를 선형으로 만들기 위해** 사용된다. -> (주의) log 함수는 0~1 사이에서는 음수값을 가지므로, log(1+x)와 같은 방법으로 처리해주어야한다. +예를들어, 기하급수적으로 늘어나는 제곱 형식의 그래프에 자연로그를 취하면 그 관계가 직선(선형)이 된다. -- 추가내용) 왜도(skewness)와 첨도(Kurtosis) - - 왜도는 데이터가 한쪽으로 치우친 정도이다. - - 첨도는 분포가 얼마나 뾰족한지를 나타내는 정도이다. +> **로그함수 주의사항** + +로그 함수는 0~1 사이에서는 음수값을 가지므로, $log(1+x)$와 같은 방법으로 처리해주어야한다. + +> **왜도(skewness)와 첨도(Kurtosis)** + +- 왜도는 데이터가 한쪽으로 치우친 정도이다. +- 첨도는 분포가 얼마나 뾰족한지를 나타내는 정도이다. #### References @@ -653,9 +582,9 @@ Bias를 통제하기 위한 방법으로는 ## #24 -#### 베르누이 분포 / 이항 분포 / 카테고리 분포 / 다항 분포 / 가우시안 정규 분포 / t 분포 / 카이제곱 분포 / F 분포 / 베타 분포 / 감마 분포에 대해 설명해주세요. +### 베르누이 분포, 이항 분포, 카테고리 분포, 다항 분포, 가우시안 정규 분포, t 분포, 카이제곱 분포, F 분포, 베타 분포, 감마 분포에 대해 설명해주세요. -- [answer/statistics-math-distribution.md](https://github.com/boostcamp-ai-tech-4/ai-tech-interview/blob/main/answers/statistics-math.md) 참고 +- [answer/statistics-math-distribution.md](./statistics-math-distribution.md) 참고 (TODO: 추후 수정) @@ -663,32 +592,25 @@ Bias를 통제하기 위한 방법으로는 ## #25 -#### 출장을 위해 비행기를 타려고 합니다. 당신은 우산을 가져가야 하는지 알고 싶어 출장지에 사는 친구 3명에게 무작위로 전화를 하고 비가 오는 경우를 독립적으로 질문했습니다. 각 친구는 2/3로 진실을 말하고 1/3으로 거짓을 말합니다. 3명의 친구가 모두 "그렇습니다. 비가 내리고 있습니다"라고 말했습니다. 실제로 비가 내릴 확률은 얼마입니까? - -(TODO: 추후 수정) +### 출장을 위해 비행기를 타려고 합니다. 당신은 우산을 가져가야 하는지 알고 싶어 출장지에 사는 친구 3명에게 무작위로 전화를 하고 비가 오는 경우를 독립적으로 질문했습니다. 각 친구는 2/3로 진실을 말하고 1/3으로 거짓을 말합니다. 3명의 친구가 모두 "그렇습니다. 비가 내리고 있습니다"라고 말했습니다. 실제로 비가 내릴 확률은 얼마입니까? -**1. 확률 구하기** +![확률 구하는 방법 시각화](./img/1-statistics-math/facebook-probability.png) -![image](https://user-images.githubusercontent.com/59533593/149618708-671adb6f-c7ff-4823-98f1-fc84cc18c15b.png) +출장지에 비가 내릴 때 $p,ドル 내리지 않을 때를 1ドル-p$라고 하자. 출장지에 비가 내리는데( $p$ ) 모든 친구가 비가 내린다라고 한다면 모든 친구가 진실을 말하는 것( $\frac{8}{27}$ )이다. 이 경우 확률은 $\frac{8p}{27}$이다. -- 출장지에 비가 내릴 때 p, 내리지 않을 때를 1-p라고 한다. -- `출장지에 비가 내리는데(p)` 모든 친구가 비가 내린다라고 한다면 `모든 친구가 진실을 말하는 것(8/27)`이다. 이 경우 확률은 `8p/27`이다. -- `출장지가 비가 내리지 않는데(1-p)` 모든 친구가 비가 내린다라고 한다면 `모든 친구가 거짓을 말하는 것(1/27)`이다. 이 경우 확률은 `(1-p)/27이`다. +출장지가 비가 내리지 않는데( $(1-p)$ ) 모든 친구가 비가 내린다라고 한다면 모든 친구가 거짓을 말하는 것( $\frac{1}{27}$ )이다. 이 경우 확률은 $\frac{(1-p)}{27}$이다. -**2. 베이즈 법칙 사용** - -![image](https://user-images.githubusercontent.com/59533593/149618731-9275ed7b-09d7-4d78-b969-89ac4ef8699f.png) +![베이즈 법칙 적용](./img/1-statistics-math/facebook-bayes-rule.png) 위에서 계산한 확률을 위의 식에 대입하고 식을 정리하면 아래와 같다. -![image](https://user-images.githubusercontent.com/59533593/149619105-6b584842-003d-46d3-8173-2857b61459ac.png) +$$ +Pr(raining | Yes) = \frac{\frac{8p}{27}}{\frac{8p}{27} + \frac{(1-p)}{27}} = \frac{8p}{8p + (1-p)} = \frac{8p}{7p+1} +$$ 만약 출장지에 비가 올 확률이 25%라면 실제로 출장지에 비가 내릴 확률은 약 72.7%이다. #### References -- 문제 출처 : [페이스북 데이터 사이언스 직무 인터뷰 - glassdoor](https://www.glassdoor.com/Interview/You-re-about-to-get-on-a-plane-to-Seattle-You-want-to-know-if-you-should-bring-an-umbrella-You-call-3-random-friends-of-y-QTN_519262.htm) - -- 정답 및 이미지 출처 : [Solving Facebook's raining in Seattle interview question - Youtube](https://www.youtube.com/watch?v=NM91QI2uUqI) - ---- +- [페이스북 데이터 사이언스 직무 인터뷰 - glassdoor](https://www.glassdoor.com/Interview/You-re-about-to-get-on-a-plane-to-Seattle-You-want-to-know-if-you-should-bring-an-umbrella-You-call-3-random-friends-of-y-QTN_519262.htm) +- [Solving Facebook's raining in Seattle interview question - Youtube](https://www.youtube.com/watch?v=NM91QI2uUqI) diff --git a/answers/2-machine-learning.md b/answers/2-machine-learning.md index c1c37db..3b7b4fb 100644 --- a/answers/2-machine-learning.md +++ b/answers/2-machine-learning.md @@ -1,16 +1,10 @@ -
-

🤖 Machine Learning 🤖

-
- -> 질문은 [zzsza님의 Datascience-Interview-Questions](https://github.com/zzsza/Datascience-Interview-Questions)를 참고하였습니다. - ---- +> **📌 질문은 [zzsza님의 Datascience-Interview-Questions](https://github.com/zzsza/Datascience-Interview-Questions)를 참고하였습니다.** ## Table of Contents - [알고 있는 metric에 대해 설명해주세요. (ex. RMSE, MAE, recall, precision ...)](#1) - [정규화를 왜 해야할까요? 정규화의 방법은 무엇이 있나요?](#2) -- [Local Minima와 Global Minima에 대해 설명해주세요.](#3) +- [Local Minima와 Global Minimum에 대해 설명해주세요.](#3) - [차원의 저주에 대해 설명해주세요.](#4) - [dimension reduction 기법으로 보통 어떤 것들이 있나요?](#5) - [PCA는 차원 축소 기법이면서, 데이터 압축 기법이기도 하고, 노이즈 제거기법이기도 합니다. 왜 그런지 설명해주실 수 있나요?](#6) @@ -44,7 +38,7 @@ #### 알고 있는 metric에 대해 설명해주세요. (ex. RMSE, MAE, recall, precision ...) -평가지표(metric)을 크게 `분류를 위한 평가지표`와 `회귀를 위한 평가지표`로 나눌 수 있다. +평가지표(metric)을 크게 **분류를 위한 평가지표**와 **회귀를 위한 평가지표**로 나눌 수 있다. --- @@ -52,45 +46,35 @@ > **정확도(accuracy)** -`정확도`는 모델의 예측이 얼마나 정확한지를 의미한다. 정확도는 (예측 결과가 동일한 데이터 개수)/(전체 예측 데이터 개수)로 계산할 수 있다. 하지만 라벨 불균형이 있는 데이터에서 정확도를 사용하면 안 된다. 예를 들면, 0과 1의 비율이 9:1인 데이터가 있다고 했을 때, 모두 0으로 예측하면 정확도가 90%가 나올 것이다. 이는 잘못된 판단이므로 정확한 판단을 위해서는 다른 지표를 사용해야 한다. +정확도는 **모델의 예측이 얼마나 정확한지**를 의미한다. 정확도는 (예측 결과가 동일한 데이터 개수)/(전체 예측 데이터 개수)로 계산할 수 있다. 하지만 라벨 불균형이 있는 데이터에서 정확도를 사용하면 안 된다. 예를 들면, 0과 1의 비율이 9:1인 데이터가 있다고 했을 때, 모두 0으로 예측하면 정확도가 90%가 나올 것이다. 이는 잘못된 판단이므로 정확한 판단을 위해서는 다른 지표를 사용해야 한다. > **오차 행렬(confusion matrix)** -
- -
+![오차 행렬](./img/2-machine-learning/confusion-matrix.png) -
- -`오차 행렬`은 모델이 예측을 하면서 얼마나 헷갈리고 있는지를 보여주는 지표이다. 주로 이진 분류에서 많이 사용하며 이진 분류에 대한 오차 행렬은 위의 그림처럼 같이 나타낼 수 있다. True Positive는 긍정으로 예측을 했는데 실제로 긍정인 경우를, False Positive는 긍정으로 예측했는데 실제로 부정인 경우를, False Negative는 부정으로 예측했는데 실제로 긍정인 경우를, True Negative는 부정으로 예측했는데 실제로 부정인 경우를 말한다. 위의 값을 바탕으로 모델이 어떤 오류를 발생시켰는지를 살펴볼 수 있다. +오차 행렬은 **모델이 예측을 하면서 얼마나 헷갈리고 있는지를 보여주는 지표**이다. 주로 이진 분류에서 많이 사용하며 이진 분류에 대한 오차 행렬은 위의 그림처럼 같이 나타낼 수 있다. True Positive는 긍정으로 예측을 했는데 실제로 긍정인 경우를, False Positive는 긍정으로 예측했는데 실제로 부정인 경우를, False Negative는 부정으로 예측했는데 실제로 긍정인 경우를, True Negative는 부정으로 예측했는데 실제로 부정인 경우를 말한다. 위의 값을 바탕으로 모델이 어떤 오류를 발생시켰는지를 살펴볼 수 있다. 참고로 정확도는 (TN + TP) / (TN + FP + FN + TP)로 계산할 수 있다. > **정밀도(precision), 재현율(recall)** -정밀도와 재현율은 긍정 데이터 예측 성능에 초점을 맞춘 평가지표이다. `정밀도`란 예측을 긍정으로 한 데이터 중 실제로 긍정인 비율을 말하며, `재현율`은 실제로 긍정인 데이터 중 긍정으로 예측한 비율을 말한다. 오차 행렬을 기준으로 정밀도는 TP / (FP + TP)으로, 재현율은 TP / (FN + TP)으로 계산할 수 있다. +정밀도와 재현율은 **긍정 데이터 예측 성능에 초점을 맞춘 평가지표**이다. 정밀도란 **예측을 긍정으로 한 데이터 중 실제로 긍정인 비율**을 말하며, 재현율은 **실제로 긍정인 데이터 중 긍정으로 예측한 비율**을 말한다. 오차 행렬을 기준으로 정밀도는 TP / (FP + TP)으로, 재현율은 TP / (FN + TP)으로 계산할 수 있다. -정밀도와 재현율은 트레이드오프 관계를 갖는다. 정밀도는 FP를, 재현율은 FN을 낮춤으로써 긍정 예측의 성능을 높인다. 이 같은 특성 때문에 정밀도가 높아지면 재현율은 낮아지고 재현율이 높아지면 정밀도는 낮아진다. 가장 좋은 경우는 두 지표 다 적절히 높은 경우이다. +정밀도와 재현율은 **트레이드오프 관계**를 갖는다. 정밀도는 FP를, 재현율은 FN을 낮춤으로써 긍정 예측의 성능을 높인다. 이 같은 특성 때문에 정밀도가 높아지면 재현율은 낮아지고 재현율이 높아지면 정밀도는 낮아진다. 가장 좋은 경우는 두 지표 다 적절히 높은 경우이다. > **F1-Score** -정밀도와 재현율 한 쪽에 치우치지 않고 둘 다 균형을 이루는 것을 나타낸 것이 `F1-Score`이다. F1-Score는 정밀도와 재현율의 조화평균으로 계산할 수 있다. +**정밀도와 재현율 한 쪽에 치우치지 않고 둘 다 균형을 이루는 것**을 나타낸 것이 `F1-Score`이다. F1-Score는 정밀도와 재현율의 조화평균으로 계산할 수 있다. - - - +$$ > **ROC-AUC** -
- -
- -
+![ROC AUC](./img/2-machine-learning/roc-curve.png) -`ROC`는 FPR(False Positive Rate)가 변할 때 TPR(True Positive Rate)가 어떻게 변하는지를 나타내는 곡선을 말한다. 여기서 FPR이란 FP / (FP + TN)이고, TPR은 TP / (FN + TP)으로 재현율을 말한다. 그럼 어떻게 FPR을 움직일까? 바로 분류 결정 임계값을 변경함으로써 움직일 수 있다. FPR이 0이 되려면 임계값을 1로 설정하면 된다. 그럼 긍정의 기준이 높으니 모두 부정으로 예측될 것이다. 반대로 1이 되려면 임계값을 0으로 설정하여 모두 긍정으로 예측시키면 된다. 이렇게 임계값을 움직이면서 나오는 FPR과 TPR을 각각 x와 y 좌표로 두고 그린 곡선이 ROC이다. +ROC는 **FPR(False Positive Rate)가 변할 때 TPR(True Positive Rate)가 어떻게 변하는지를 나타내는 곡선**을 말한다. 여기서 FPR이란 FP / (FP + TN)이고, TPR은 TP / (FN + TP)으로 재현율을 말한다. 그럼 어떻게 FPR을 움직일까? 바로 분류 결정 임계값을 변경함으로써 움직일 수 있다. FPR이 0이 되려면 임계값을 1로 설정하면 된다. 그럼 긍정의 기준이 높으니 모두 부정으로 예측될 것이다. 반대로 1이 되려면 임계값을 0으로 설정하여 모두 긍정으로 예측시키면 된다. 이렇게 임계값을 움직이면서 나오는 FPR과 TPR을 각각 x와 y 좌표로 두고 그린 곡선이 ROC이다. AUC는 ROC 곡선의 넓이를 말한다. AUC가 높을수록 즉, AUC가 왼쪽 위로 휘어질수록 좋은 성능이 나온다고 판단한다. 즉, TPR이 높고 FPR이 낮을수록 예측 오류는 낮아지기 때문에 성능이 잘 나온다 볼 수 있다. @@ -98,39 +82,31 @@ AUC는 ROC 곡선의 넓이를 말한다. AUC가 높을수록 즉, AUC가 왼쪽 마지막으로 **회귀 작업**에 적용할 수 있는 평가지표를 살펴보자. -`MAE(Mean Absolute Error)`는 예측값과 정답값 사이의 차이의 절대값의 평균을 말한다. +MAE(Mean Absolute Error)는 **예측값과 정답값 사이의 차이의 절대값의 평균**을 말한다. - +$$ - +MSE(Mean Squared Error)는 **예측값과 정답값 사이의 차이의 제곱의 평균**을 말하며, MAE와 달리 제곱을 했기 때문에 이상치에 민감하다. -`MSE(Mean Squared Error)`는 예측값과 정답값 사이의 차이의 제곱의 평균을 말하며, MAE와 달리 제곱을 했기 때문에 이상치에 민감하다. - - - - +$$ -`RMSE(Root Mean Squared Error)`는 MSE에 루트를 씌운 값을 말한다. +RMSE(Root Mean Squared Error)는 **MSE에 루트를 씌운 값**을 말한다. - - - +$$ -`RMSLE(Root Mean Squared Logarithmic Error)`는 RMSE와 비슷하나 예측값과 정답값에 각각 로그를 씌워 계산을 한다. +RMSLE(Root Mean Squared Logarithmic Error)는 RMSE와 비슷하나 **예측값과 정답값에 각각 로그를 씌워 계산**을 한다. - +$$ - - -`R Squared`는 분산을 기반으로 예측 성능을 평가하는 지표를 말한다. 정답값의 분산 대비 예측값의 분산 비율을 지표로 하며, 1에 가까울수록 정확도가 높다. +R Squared는 **분산을 기반으로 예측 성능을 평가하는 지표**를 말한다. 정답값의 분산 대비 예측값의 분산 비율을 지표로 하며, 1에 가까울수록 정확도가 높다. #### References @@ -146,9 +122,9 @@ $$ --> #### 정규화를 왜 해야할까요? 정규화의 방법은 무엇이 있나요? -`정규화`는 개별 피처의 크기를 모두 똑같은 단위로 변경하는 것을 말한다. 정규화를 하는 이유는 피처의 스케일이 심하게 차이가 나는 경우 값이 큰 피처가 더 중요하게 여겨질 수 있기 때문이다. 이를 막기 위해 피처 모두 동일한 스케일로 반영되도록 하는 것이 정규화이다. +정규화는 **개별 피처의 크기를 모두 똑같은 단위로 변경하는 것**을 말한다. 정규화를 하는 이유는 **피처의 스케일이 심하게 차이가 나는 경우 값이 큰 피처가 더 중요하게 여겨질 수 있기 때문**이다. 이를 막기 위해 피처 모두 동일한 스케일로 반영되도록 하는 것이 정규화이다. -정규화하는 방법으로는 대표적으로 두 가지가 존재한다. 첫 번째 정규화 방법은 최소-최대 정규화(min-max normalization)으로 각 피처의 최소값을 0, 최대값을 1로 두고 변환하는 방법이다. 값을 로, 최소값을 , 최대값을 로 둘 때, 정규화된 값은 으로 계산할 수 있다. 두 번째 정규화 방법으로 Z-점수 정규화(z-score normalization)이 있다. 이 방법은 각 피처의 표준편차와 평균으로 값을 정규화시킨다. 정규화된 값은 로 계산할 수 있다. +정규화하는 방법으로는 대표적으로 두 가지가 존재한다. 첫 번째 정규화 방법은 최소-최대 정규화(min-max normalization)으로 각 피처의 최소값을 0, 최대값을 1로 두고 변환하는 방법이다. 값을 $x$로, 최소값을 $min,ドル 최대값을 $max$로 둘 때, 정규화된 값은 $\frac{x - min}{max - min}$으로 계산할 수 있다. 두 번째 정규화 방법으로 Z-점수 정규화(z-score normalization)이 있다. 이 방법은 각 피처의 표준편차와 평균으로 값을 정규화시킨다. 정규화된 값은 $\frac{x - mean}{std}$로 계산할 수 있다. #### References @@ -159,15 +135,11 @@ $$ --> ## #3 -#### Local Minima와 Global Minima에 대해 설명해주세요. - -
- -
+#### Local Minima와 Global Minimum에 대해 설명해주세요. -
+![Maxima와 Minima](./img/2-machine-learning/local-minima-global-minima.png) -비용 함수(cost function)에서의 `Global Minima`는 에러가 최소화되는 즉, 우리가 찾고자 하는 지점을 말하며, `Local Minima`는 에러가 최소가 될 수 있는 후보가 되는 지점 중 Global Minima를 뺀 지점을 말한다. Local Minima는 자칫 에러가 **최소화되는 지점을 찾았다고 착각**할 수 있기에 함정에 비유할 수 있다. 이를 해결하기 위해 Momentum과 같은 최적화 알고리즘을 사용하거나 학습률(learning rate)를 잘 조절하여 Local Minima에서 벗어날 수 있다. +비용 함수(cost function)에서의 **Global Minimum**은 에러가 최소화되는 즉, 우리가 찾고자 하는 지점을 말하며, **Local Minima**는 에러가 최소가 될 수 있는 후보가 되는 지점 중 Global Minimum을 뺀 지점을 말한다. Local Minima는 자칫 에러가 **최소화되는 지점을 찾았다고 착각**할 수 있기에 함정에 비유할 수 있다. 이를 해결하기 위해 Momentum과 같은 최적화 알고리즘을 사용하거나 학습률(learning rate)를 잘 조절하여 Local Minima에서 벗어날 수 있다. #### References @@ -180,11 +152,9 @@ $$ --> #### 차원의 저주에 대해 설명해주세요. -
- -
+![차원의 저주](./img/2-machine-learning/curse-of-dimensionality.png) -`차원의 저주란 데이터 차원이 증가할수록 해당 공간의 크기가 기하급수적으로 증가하여 데이터 간 거리가 기하급수적으로 멀어지고 희소한 구조를 갖게 되는 현상을 말한다. 이를 해결하기 위해서는 차원을 증가시킨만큼 더 많은 데이터를 추가하거나 PCA, LDA, LLE, MDS와 같은 차원 축소 알고리즘으로 차원을 줄여 해결할 수 있다. +차원의 저주란 **데이터 차원이 증가할수록 해당 공간의 크기가 기하급수적으로 증가하여 데이터 간 거리가 기하급수적으로 멀어지고 희소한 구조를 갖게 되는 현상**을 말한다. 이를 해결하기 위해서는 차원을 증가시킨만큼 더 많은 데이터를 추가하거나 PCA, LDA, LLE, MDS와 같은 차원 축소 알고리즘으로 차원을 줄여 해결할 수 있다. #### References @@ -198,7 +168,7 @@ $$ --> #### dimension reduction 기법으로 보통 어떤 것들이 있나요? -차원 축소는 `피처 선택(feature selection)`과 `피처 추출(feature extraction)`으로 나눌 수 있다. 우선 피처 선택은 특정 피처에 종속성이 강한 불필요한 피처는 제거하고 데이터의 특징을 잘 표현하는 주요 피처만 선택하는 것을 말한다. 반면 피처 추출은 기존 피처를 저차원의 피처로 압축하여, 피처를 함축적으로 잘 설명할 수 있도록 저차원으로 매핑하는 것을 말한다. 대표적인 피처 추출 알고리즘으로 PCA, SVD, NMF, LDA 등이 있다. +차원 축소는 피처 선택(feature selection)피처 추출(feature extraction)으로 나눌 수 있다. 우선 피처 선택은 특정 피처에 종속성이 강한 불필요한 피처는 제거하고 데이터의 특징을 잘 표현하는 주요 피처만 선택하는 것을 말한다. 반면 피처 추출은 기존 피처를 저차원의 피처로 압축하여, 피처를 함축적으로 잘 설명할 수 있도록 저차원으로 매핑하는 것을 말한다. 대표적인 피처 추출 알고리즘으로 PCA, SVD, NMF, LDA 등이 있다. #### References @@ -210,7 +180,7 @@ $$ --> #### PCA는 차원 축소 기법이면서, 데이터 압축 기법이기도 하고, 노이즈 제거기법이기도 합니다. 왜 그런지 설명해주실 수 있나요? -`PCA(Principle Component Analysis)`는 입력 데이터의 공분산 행렬을 기반으로 고유벡터를 생성하고 이렇게 구한 고유 벡터에 입력 데이터를 선형 변환하여 차원을 축소하는 방법이다. 차원은 곧 입력 데이터의 피처를 뜻하므로 데이터 압축 기법으로 볼 수도 있다. +PCA(Principle Component Analysis)는 **입력 데이터의 공분산 행렬을 기반으로 고유벡터를 생성하고 이렇게 구한 고유 벡터에 입력 데이터를 선형 변환하여 차원을 축소하는 방법**이다. 차원은 곧 입력 데이터의 피처를 뜻하므로 데이터 압축 기법으로 볼 수도 있다. 또한 PCA는 고유값이 가장 큰, 즉 데이터의 분산이 가장 큰 순으로 주성분 벡터를 추출하는데, 가장 나중에 뽑힌 벡터보다 가장 먼저 뽑힌 벡터가 데이터를 더 잘 설명할 수 있기 때문에 노이즈 제거 기법이라고도 불린다. @@ -247,41 +217,29 @@ $$ --> #### Markov Chain을 고등학생에게 설명하려면 어떤 방식이 제일 좋을까요? -> 마코프 체인(Markov Chain) - -마코프 성질(Markov Property)을 지닌 이산 확률 과정(Discrete-time Stochastic Pross) +> **마코프 체인(Markov Chain)** -> 마코프 성질(Markov Property) +마코프 체인이란 마코프 성질을 지닌 이산 확률 과정(Discrete-time Stochastic Process)을 말한다. -n+1회의 상태(state)는 오직 n회에서의 상태, 혹은 그 이전 일정 기간의 상태에만 영향을 받는 것을 의미한다. 예를 들면 동전 던지기는 독립 시행이기 때문에 n번째의 상태가 앞이던지 뒤이던지 간에 n+1번째 상태에 영향을 주지 않는다. 하지만 1차 마코프 체인은 n번째 상태가 n+1번째 상태를 결정하는데에 영향을 미친다. (시간 t에서의 관측은 단지 최근 r개의 관측에만 의존한다는 가정을 하고 그 가정하에서 성립) +> **마코프 성질(Markov Property)** -
- -
+$n+1$회의 상태(state)는 오직 $n$회에서의 상태, 혹은 그 이전 일정 기간의 상태에만 영향을 받는 것을 의미한다. 예를 들면 동전 던지기는 독립 시행이기 때문에 $n$번째의 상태가 앞이던지 뒤이던지 간에 $n+1$번째 상태에 영향을 주지 않는다. 하지만 1차 마코프 체인은 $n$번째 상태가 $n+1$번째 상태를 결정하는데에 영향을 미친다. (시간 $t$에서의 관측은 단지 최근 $r$개의 관측에만 의존한다는 가정을 하고 그 가정하에서 성립한다.) -
+![마코프 체인](./img/2-machine-learning/markov-chain.png) -정리하면 마코프 체인은 확률변수(random variable)가 어떤 상태(state)에 도달할 확률이 오직 바로 이전 시점의 상태(state)에 달려 있는 경우를 가리킨다. +정리하면 마코프 체인은 **확률변수(random variable)가 어떤 상태(state)에 도달할 확률이 오직 바로 이전 시점의 상태(state)에 달려 있는 경우**를 가리킨다. -예를 들어 오늘의 날씨가 어제의 날씨에만 의존하면 1차 마코프 체인, 이틀 전까지의 날씨에만 의존하면 2차 마코프 체인이다. +예를 들어, 오늘의 날씨가 어제의 날씨에만 의존하면 1차 마코프 체인, 이틀 전까지의 날씨에만 의존하면 2차 마코프 체인이다. -> 마코프 모델 +> **마코프 모델(Markov Model)** -마코프 모델은 위의 가정하에 확률적 모델을 만든 것으로써, 가장 먼저 각 상태를 정의하게 된다. 상태(state)는 로 정의하고, m개의 상태가 존재하게 되는 것이다. 그 다음은 상태 전이 확률(State transition Probability)을 정의할 수 있다. 상태 전이 확률이란 각 상태에서 각 상태로 이동할 확률을 말한다. 상태 전이 확률 는 상태 에서 상태 로 이동할 확률을 의미한다. 아래의 식은 상태 전이 확률을 식으로 나타낸 것과 그 아래는 확률의 기본 정의에 의한 상태 전이 확률의 조건이다. +마코프 **모델은 위의 가정하에 확률적 모델을 만든 것으로써 가장 먼저 각 상태를 정의**하게 된다. 상태(state)는 $V = v_1, ... , v_m$로 정의하고, m개의 상태가 존재하게 되는 것이다. 그 다음은 상태 전이 확률(State transition Probability)을 정의할 수 있다. 상태 전이 확률이란 각 상태에서 각 상태로 이동할 확률을 말한다. 상태 전이 확률 $a_{ij}$는 상태 $v_i$에서 상태 $v_j$로 이동할 확률을 의미한다. 아래의 식은 상태 전이 확률을 식으로 나타낸 것과 그 아래는 확률의 기본 정의에 의한 상태 전이 확률의 조건이다. -
- -
- -
+![상태 전이 확률](./img/2-machine-learning/state-transition-probability.png) 그리고 상태와 상태 전이 확률을 정리하여 상태 전이도(state transition diagram)으로도 표현할 수 있다. -
- -
- -
+![상태 전이도](./img/2-machine-learning/state-transition-diagram.png) #### References @@ -295,34 +253,27 @@ n+1회의 상태(state)는 오직 n회에서의 상태, 혹은 그 이전 일정 #### 텍스트 더미에서 주제를 추출해야 합니다. 어떤 방식으로 접근해 나가시겠나요? -> 잠재 디리클레 할당(Latent Dirichlet Allocation, LDA) +> **잠재 디리클레 할당(Latent Dirichlet Allocation, LDA)** -- 문서의 집합에서 토픽을 찾아내는 프로세스를 뜻하는 토픽 모델링의 대표적인 알고리즘 -- LDA는 **문서들은 토픽들의 혼합으로 구성되어져 있으며, 토픽들은 확률 분포에 기반하여 단어들을 생성한다**고 가정 -- 데이터가 주어지면 LDA는 토픽을 문서가 생성되던 과정을 역추적 -- LDA는 각 문서의 **토픽 분포**와 **각 토픽 내의 단어 분포**를 추정 +잠재 디리클레 할당(LDA)이란 **문서의 집합에서 토픽을 찾아내는 프로세스를 뜻하는 토픽 모델링의 대표적인 알고리즘**을 말한다. LDA는 "문서들은 토픽들의 혼합으로 구성되어져 있으며, 토픽들은 확률 분포에 기반하여 단어들을 생성한다"고 가정하며, 데이터가 주어지면 LDA는 토픽을 문서가 생성되던 과정을 역추적한다. -> LDA 예시 +예를 들어, 다음과 같은 예시 문장 3개가 있다고 가정하자. +```text 문서1 : 저는 사과랑 바나나를 먹어요 - 문서2 : 우리는 귀여운 강아지가 좋아요 - 문서3 : 저의 깜찍하고 귀여운 강아지가 바나나를 먹어요 +``` -**<각 문서의 토픽 분포>** - -문서1 : 토픽 A 100% - -문서2 : 토픽 B 100% +LDA를 통해 각 문서의 **토픽 분포**와 **각 토픽 내의 단어 분포**를 추정할 수 있다. -문서3 : 토픽 B 60%, 토픽 A 40% - -**<각 토픽의 단어 분포>** - -토픽A : **사과 20%, 바나나 40%, 먹어요 40%**, 귀여운 0%, 강아지 0%, 깜찍하고 0%, 좋아요 0% - -토픽B : 사과 0%, 바나나 0%, 먹어요 0%, **귀여운 33%, 강아지 33%, 깜찍하고 16%, 좋아요 16%** +- **각 문서의 토픽 분포** + - 문서1 : 토픽 A 100% + - 문서2 : 토픽 B 100% + - 문서3 : 토픽 B 60%, 토픽 A 40% +- **각 토픽의 단어 분포** + - 토픽A : 사과 20%, 바나나 40%, 먹어요 40%, 귀여운 0%, 강아지 0%, 깜찍하고 0%, 좋아요 0% + - 토픽B : 사과 0%, 바나나 0%, 먹어요 0%, 귀여운 33%, 강아지 33%, 깜찍하고 16%, 좋아요 16% LDA는 토픽의 제목을 정해주지 않지만, 이 시점에서 알고리즘의 사용자는 위 결과로부터 두 토픽이 각각 과일에 대한 토픽과 강아지에 대한 토픽이라고 판단해볼 수 있다. @@ -338,58 +289,40 @@ LDA는 토픽의 제목을 정해주지 않지만, 이 시점에서 알고리즘 #### SVM은 왜 반대로 차원을 확장시키는 방식으로 동작할까요? SVM은 왜 좋을까요? -> SVM(Support Vector Machine) - -- SVM은 데이터가 사상된 공간에서 **경계로 표현**되며, 공간상에 존재하는 **여러 경계 중 가장 큰 폭을 가진 경계를 찾는다.** - -
- -
+SVM(Support Vector Machine)은 데이터가 사상된 공간에서 **경계로 표현**되며, 공간상에 존재하는 **여러 경계 중 가장 큰 폭을 가진 경계를 찾는다.** -
+![SVM](./img/2-machine-learning/svm.png) -- : 결정 경계 -- : plus-plane -- : minus-plane +- $B_1$: 결정 경계 +- $b_{11}$: plus-plane +- $b_{12}$: minus-plane -> Margin +SVM의 장단점은 다음과 같다. -- Margin은 plus-plane과 minus-plane 사이의 거리를 의미하며, **최적의 결정 경계는 margin을 최대화**한다. - -- SVM은 선형 분류뿐만 아니라 **비선형 분류**에도 사용되는데, 비선형 분류에서는 입력자료를 다차원 공간상으로 맵핑할 때 커널 트릭(kernel trick)을 사용하기도 한다. - - 원공간(Input Space)의 데이터를 선형분류가 가능한 고차원 공간(Feature Space)으로 매핑한 뒤 두 범주를 분류하는 초평면을 찾는다. (Kernel-SVM) +| 장점 | 단점 | +| ------------------------------------------------- | --------------------------------------------------------------------- | +| 분류와 회귀에 모두 사용할 수 있다. | 데이터 전처리와 매개변수 설정에 따라 정확도가 달라질 수 있다. | +| 신경망 기법에 비해 과적합 정도가 낮다. | 예측이 어떻게 이루어지는지에 대한 이해와 모델에 대한 해석이 어렵다. | +| 예측의 정확도가 높다. | 대용량 데이터에 대한 모델 구축 시 속도가 느리며,메모리 할당량이 크다. | +| 저차원과 고차원 데이터에 대해서 모두 잘 작동한다. | | -
- -
+> **마진(Margin)** -
+마진(Margin)은 plus-plane과 minus-plane 사이의 거리를 의미하며, **최적의 결정 경계는 마진을 최대화**한다. -
- -
+SVM은 선형 분류뿐만 아니라 **비선형 분류**에도 사용되는데, 비선형 분류에서는 입력자료를 다차원 공간상으로 맵핑할 때 커널 트릭(kernel trick)을 사용하기도 한다. 원공간(Input Space)의 데이터를 선형분류가 가능한 고차원 공간(Feature Space)으로 매핑한 뒤 두 범주를 분류하는 초평면을 찾는다. (Kernel-SVM) -
+![](./img/2-machine-learning/input-space-and-feature-space.png) -> 커널 트릭(kernel trick) +![](./img/2-machine-learning/kernel-svm.png) -- 커널 함수를 이용하여 차원 공간(low dimensional space)을 고차원 공간(high dimensional space)으로 매핑해주는 작업 -- 커널 함수의 종류 +> **커널 트릭(Kernel Trick)** -
- -
+커널 함수를 이용하여 **차원 공간(low dimensional space)을 고차원 공간(high dimensional space)으로 매핑해주는 작업**을 커널트릭이라 한다. -
+커널 함수의 종류는 다음과 같다. -> SVM의 장단점 - -| 장점 | 단점 | -| ------------------------------------------------- | --------------------------------------------------------------------- | -| 분류와 회귀에 모두 사용할 수 있다. | 데이터 전처리와 매개변수 설정에 따라 정확도가 달라질 수 있다. | -| 신경망 기법에 비해 과적합 정도가 낮다. | 예측이 어떻게 이루어지는지에 대한 이해와 모델에 대한 해석이 어렵다. | -| 예측의 정확도가 높다. | 대용량 데이터에 대한 모델 구축 시 속도가 느리며,메모리 할당량이 크다. | -| 저차원과 고차원 데이터에 대해서 모두 잘 작동한다. | | +![커널 함수의 종류](./img/2-machine-learning/kernel-function.png) #### References @@ -406,11 +339,9 @@ LDA는 토픽의 제목을 정해주지 않지만, 이 시점에서 알고리즘 #### 다른 좋은 머신 러닝 대비, 오래된 기법인 나이브 베이즈(naive bayes)의 장점을 옹호해보세요. -> 나이브 베이즈(Naïve Bayes Classification) - 데이터에서 변수들에 대한 **조건부 독립을 가정**하는 알고리즘으로 클래스에 대한 사전 정보와 데이터로부터 추출된 정보를 결합하고, 베이즈 정리(Bayes Theorem)를 이용하여 어떤 데이터가 특정 클래스에 속하는지 분류하는 알고리즘이다. -> 나이브 베이즈의 장단점 +나이브 베이즈의 장단점은 다음과 같다. | 장점 | 단점 | | -------------------------------------------------------------------------- | ---------------------------------------------------------------------- | @@ -431,52 +362,33 @@ LDA는 토픽의 제목을 정해주지 않지만, 이 시점에서 알고리즘 #### 회귀 / 분류시 알맞은 metric은 무엇일까? -[#1. 알고 있는 metric에 대해 설명해주세요. (ex. RMSE, MAE, recall, precision ...)](#1) 참고 - -**회귀** - -> (결정계수, Coefficient of determination) - -- 결정계수는 독립변수의 개수가 많아질수록 결정계수가 1에 가까워진다. -- 회귀모형이 높은 결정계수를 갖는다면 실제로 모형이 설명력이 높은 것인지 단순히 독립변수의 개수가 많은 것인지 알기 어려워 결정계수를 신뢰할 수 없게 되는 문제가 발생한다. - -
- -
- -
- -> (수정된 결정계수, adjusted coefficient of determination) - -- 결정계수의 문제를 해결하기 위해 표본의 크기(n)와 독립변수의 수(p)를 고려하여 수정된 결정계수를 계산한다. - -
- -
+[#1](#1) 답변을 참고해주세요. 해당 답변에서 서술하지 않은 지표만 추가로 설명합니다. -
+> **회귀** -**분류** +$$ +R^2 = \frac{\sum (\hat{y}_l - \bar{y})}{\sum (y_i - \bar{y})^2} +$$ -> Log Loss/Binary Crossentropy +결정계수(Coefficient of determination)는 (회귀선에 의해 설명되는 변동)/(전체 변동)을 말하며, 독립변수의 개수가 많아질수록 결정계수가 1에 가까워진다. 회귀모형이 높은 결정계수를 갖는다면 실제로 모형이 설명력이 높은 것인지 단순히 독립변수의 개수가 많은 것인지 알기 어려워 결정계수를 신뢰할 수 없게 되는 문제가 발생한다. -- 이진 분류에서의 metric으로 사용된다. +$$ +adj R^2 = 1 - \frac{n - 1}{(n - p - 1)(1 - R^2)} +$$ -
- -
+수정된 결정계수는 결정계수의 문제를 해결하기 위해 표본의 크기(n)와 독립변수의 수(p)를 고려하여 수정된 결정계수를 계산한다. -
+> **분류** -> Categorical Crossentropy +$$ - (y - \log (p))) + (1 - y) \log (1-p) $$ -- 분류해야할 class가 3개 이상인 multiclass 분류에서의 metric으로 사용된다. +Log Loss 혹은 Binary Crossentropy는 이진 분류에서의 지표로 사용된다. -
- -
+$$ +LogarithmicLoss = - \frac{1}{N} \sum^N_{i=1} \sum^M_{j=1} y_{ij} * \log (p_{ij}) +$$ -
+Categorical Crossentropy는 분류해야할 클래스가 3개 이상인 멀티 클래스 분류에서의 지표로 사용된다. #### References @@ -491,45 +403,35 @@ LDA는 토픽의 제목을 정해주지 않지만, 이 시점에서 알고리즘 #### Association Rule의 Support, Confidence, Lift에 대해 설명해주세요. -> 연관규칙분석(Association Analysis) +연관규칙분석(Association Analysis)은 흔히 장바구니 분석(Market Basket Analysis) 또는 서열분석(Sequence Analysis)이라고 불린다. 기업의 데이터베이스에서 상품의 구매, 서비스 등 **일련의 거래 또는 사건들 간의 규칙을 발견하기 위해 적용**하며, 연관성 분석의 평가 지표로는 Support, Confidence, Lift를 사용한다. -- 연관성 분석은 흔히 장바구니 분석(Market Basket Analysis) 또는 서열분석(Sequence Analysis)이라고 불린다. -- 기업의 데이터베이스에서 상품의 구매, 서비스 등 일련의 거래 또는 사건들 간의 규칙을 발견하기 위해 적용한다. -- 연관성 분석의 평가 지표로는 Support, Confidence, Lift를 사용한다. +> **Support(지지도)** -1. Support(지지도) +전체 거래 중 항목 A와 항목 B를 동시에 포함하는 거래의 비율로 정의한다. -- 전체 거래 중 항목 A와 항목 B를 동시에 포함하는 거래의 비율로 정의한다. +$$ +지지도 = P(A \cap B) = \frac{A와 B가 동시에 포함된 거래수}{전체 거래수} = \frac{A \cap B}{전체} +$$ -
- -
+> **Confidence(신뢰도)** -
+항목 A를 포함한 거래 중에서 항목 A와 항목 B가 같이 포함될 확률이다. 연관성의 정도를 파악할 수 있다. -2. Confidence(신뢰도) +$$ +신뢰도 = \frac{P(A \cap B)}{P(A)} = \frac{A와 B가 동시에 포함된 거래수}{A를 포함하는 거래수} = \frac{지지도}{P(A)} +$$ -- 항목 A를 포함한 거래 중에서 항목 A와 항목 B가 같이 포함될 확률이다. 연관성의 정도를 파악할 수 있다. +> **Lift(향상도)** -
- -
+A가 구매되지 않았을 때 품목 B의 구매확률에 비해 A가 구매됐을 때 품목 B의 구매확률의 증가 비이다. 연관규칙 A→B는 품목 A와 품목 B의 구매가 서로 관련이 없는 경우에 향상도가 1이 된다. -
+$$ +향상도 = \frac{P(B | A)}{P(B)} = \frac{P(A \cap B)}{P(A)P(B)} = \frac{A와 B가 동시에 포함된 거래수}{A를 포함하는 거래수 \times B를 포함하는 거래수} = \frac{신뢰도}{P(B)} +$$ -3. Lift(향상도) - -- A가 구매되지 않았을 때 품목 B의 구매확률에 비해 A가 구매됐을 때 품목 B의 구매확률의 증가 비이다. 연관규칙 A→B는 품목 A와 품목 B의 구매가 서로 관련이 없는 경우에 향상도가 1이 된다. - -
- -
- -
- -> 예시 +--- -연관규칙 X:{계란, 맥주} → Y:{기저귀} 에 대해 +에를 들어 어떤 슈퍼마켓에서 5명의 고객에 의해 발생된 5($N = 5$)건의 거래를 가지고, 연관규칙 X:{계란, 맥주} → Y:{기저귀}에 대해 살펴보자. | Customer
ID | Transaction
ID | Items | | :------------: | :---------------: | :------------------------------------: | @@ -539,18 +441,11 @@ LDA는 토픽의 제목을 정해주지 않지만, 이 시점에서 알고리즘 | 4811 | no.4 | 계란, 우유, 맥주, 기저귀 | | 8091 | no.5 | 계란, 우유, 맥주, 콜라 | -- (전체 transaction 개수) - -- +$$ P(Y) = \frac{n(Y)}{N} = \frac{n \\{ no.2, no.3, no.4 \\} }{N} = \frac{3}{5} = 0.6 $$ -- 지지도(Support) - - -- 신뢰도(Confidence) - - -- 향상도(Lift) - +- 지지도(Support) = $s(X→Y) = \frac{n(X\cup Y)}{N} = \frac{n \\{ no.2, no.4 \\} }{N} = \frac{2}{5} = 0.4$ +- 신뢰도(Confidence) = $c(X→Y) = \frac{n(X\cup Y)}{n(X)} = \frac{n \\{ no.2, no.4 \\} }{n \\{ no.2, no.4, no.5 \\} } = \frac{2}{3} = 0.6667$ +- 향상도(Lift) = $Lift(X→Y) = \frac{c(X→Y)}{s(Y)} = \frac{0.6667}{0.6} = 1.1111$ #### References @@ -565,52 +460,60 @@ LDA는 토픽의 제목을 정해주지 않지만, 이 시점에서 알고리즘 > **Newton's Method** -- 방정식 의 해를 근사적으로 찾을 때 사용되는 방법 -- 현재 x값에서 접선을 그리고 접선이 x축과 만나는 지점으로 x를 이동시켜 가면서 점진적으로 해를 찾는 방법 -- 초기값을 잘 주면 금방 해를 찾을 수 있지만 잘못 주면 시간이 오래 걸리거나 아예 해를 찾지 못할 수 있다. - -
- -
+함수 $f$의 2차 테일러 근사(quadratic approximation)은 다음과 같다. -
+$$ +f(y)\approx f(x)+\nabla f(x)^T(y-x)+\frac{1}{2}(y-x)^T\nabla^2f(x)(y-x), +\\ +f_{approx}(y)=f(x)+\nabla f(x)^T(y-x)+\frac{1}{2}(y-x)^T\nabla^2f(x)(y-x) +$$ -Newton's method를 수식화하면 아무 값이나 초기값 에서 시작해서 다음 수식에 따라 수렴할 때까지 계속 x를 이동시켜 나가는 것이다. +여기서 $y$는 다음 스텝의 $x$ 값인 $x^+$이다. 또한 quadratic approximation을 $f_{approx}$로 정한다. - +이 $f_{approx}$ 즉, quadratic approximation을 최소로 만드는 입력 $y$를 찾으려 한다. 이때 $f_{approx}$는 convex이므로 위 식의 gradient를 0으로 만드는 입력 $y$가 $f_{approx}$를 최소로 만들 것이다. 이 결과가 Newton’s method에서의 step update 식이 된다. 아래 식의 미분은 $y$에 대한 미분 임을 기억하자. - - -
- -종료 조건은 x 값의 변화가 거의 없을 때까지이다. 즉, 이 매우 작은 값이면 Newton's method를 종료하고 이 해, 즉 이라고 생각하는 것이다. +$$ +\nabla f_{approx}(y)=\nabla f(x)+\frac{1}{2}\left((\nabla^2f(x))^T(y-x)+(y-x)^T\nabla^2f(x)\right) +\\ +=\nabla f(x)+\nabla^2f(x)(y-x)\qquad\qquad\qquad +\\ += 0,\qquad\qquad\qquad\qquad\qquad\qquad\qquad\quad\;,円 +\\ +\Leftrightarrow y=x-(\nabla^2f(x))^{-1}\nabla f(x)\qquad\qquad\; +$$ > **Gradient Descent** -
- -
+Gradient descent에서는 함수 $f$의 2차 테일러 근사항을 사용하고, 2차 항의 경우 실제 2차 미분 결과가 아닌, 정방행렬(identity matrix)과 이를 $t$로 나눈 값으로 가정한다. + +$$ +f(y)\approx f(x)+\nabla f(x)^T(y-x)+\frac{1}{2t}\parallel y-x\parallel^2_2, +\\ +f_{approx}(y)=f(x)+\nabla f(x)^T(y-x)+\frac{1}{2t}\parallel y-x\parallel^2_2 +$$ -
+Newton’s method와 동일하게 위 근사식의 gradient가 0인 $y$ 값, 즉 $x^+$를 정할 수 있다. -- 가 0이 되는 점을 찾는 방법 -- 미분하여 극소점을 찾아가는 방법 (local minimum에 빠질수도 있다는 문제점이 있다) -- 모든 차원과 모든 공간에서 적용이 가능 +$$ +\nabla f(y)=\nabla f(x)+\frac{1}{t}(y-x), +\\ +=0,\qquad\qquad\; +\\ +\Leftrightarrow y=x-t\nabla f(x) +$$ -Gradient Descent 방법은 그레디언트의 특성을 이용하여 어떤 비용함수의 값을 최소화시키기 위한 파라미터 값을 아래와 같이 점진적으로 찾는 방법이다. +> **Newton's method**와 **Gradient descent**의 step에 따른 수렴 방향 비교 - + - +- 파랑: Newton's method +- 검정: Gradient descent -
+Gradient descent는 2차 미분항을 정방행렬에 상수가 곱해진 값으로 가정하고 gradient를 계산하기 때문에, 등고선(contour)의 접선 방향에 수직하게(perpendicular) 수렴함을 확인할 수 있고, Newton’s method에 비해 느린 수렴 속도를 보인다. #### References +- [14-01-01 Newton's method interpretation - 모두를 위한 컨벡스 최적화](https://convex-optimization-for-all.github.io/contents/chapter14/2021/03/26/14_01_01_newton_method_interpretation/) - [뉴턴법/뉴턴-랩슨법의 이해와 활용(Newton's method) - 다크 프로그래머](https://darkpgmr.tistory.com/58) - [Gradient Descent 탐색 방법 - 다크 프로그래머](https://darkpgmr.tistory.com/133) - [4주차\_#2. 최적화 기법중 Newton's Method와 Gradient Descent 방법을 설명하세요. - 내가 보려고 만든 공간](https://astralworld58.tistory.com/86) @@ -626,7 +529,8 @@ $$ --> 머신러닝적 접근방법은 모델의 **예측 성공률**을 높이는게 목적이다. 따라서 모델의 신뢰도나 정교한 가정보다는 다양한 피쳐를 사용하여 (오버피팅을 감안하더라도) 높은 예측률을 달성하고자 한다. -통계적 접근방법은 분포와 가정을 통해 **신뢰 가능하고 정교한** 모델을 만드는게 목적이다. +통계적 접근방법은 분포와 가정을 통해 **신뢰 가능하고 정교한** 모델을 만드는게 목적이다. + 따라서 모형을 복잡하지 않고 단순하게 만들고, 어떤 피쳐가 어떤 원인을 주는지 알 수 있도록 한다. #### References @@ -642,9 +546,7 @@ $$ --> 딥러닝 이전의 인공신경망은 선형적으로만 회귀, 분류를 수행하기 때문에 레이어를 깊게 쌓지 못했고, 때문에 XOR 문제 같은 복잡한 문제를 풀지 못하는 문제점이 있었다. -
- -
+![XOR 문제](./img/2-machine-learning/xor.png) 하지만 시그모이드와 같은 비선형 함수를 선형 모델에 추가하여 XOR 문제를 해결하고, 편미분 체인룰을 사용한 오차역전파 방법으로 모델을 업데이트할 수 있게 되면서 레이어를 깊게 쌓은 딥러닝 인공신경망이 발전하였다. @@ -680,11 +582,7 @@ ROC 커브는 **이진분류 모델의 성능**을 나타내는 지표이다. 모델이 참이라고 예측하는 경우는 **FPR** (False Positive Rate, 실제 값이 거짓일 때) 과 **TPR** (True Positive Rate, 실제 값이 참일 때) 두 경우로 나뉜다. FPR 과 TPR 을 그래프에서 x 축, y 축으로 동시에 표현한 ROC 커브를 통해 모델이 얼마나 옳은 값을 잘 예측하는지 알 수 있게 된다. -
- -
- -
+![ROC 커브](./img/2-machine-learning/roc.png) ROC 커브가 좌상단과 가까운 경우 좋은 모델이라고 판단할 수 있다. 모델이 FPR 은 낮게, TPR 은 높게 예측하기 때문이다. @@ -718,11 +616,11 @@ ROC 커브가 좌상단과 가까운 경우 좋은 모델이라고 판단할 수 K-means 는 특성이 비슷한 데이터를 같은 그룹으로 묶어주는 클러스터링 알고리즘으로, k 개의 군집 개수를 정하고 군집의 중심점을 예측하여 각 데이터와 거리를 비교한 후 군집을 결정한다. -K-means 알고리즘의 단점은 다음과 같다. +**K-means 알고리즘의 단점**은 다음과 같다. -1. K 를 몇 개로 설정하냐에 따라 성능이 달라진다. -2. K 개 군집의 중심점을 예측하여야 하는데, 어디를 중심점으로 두냐에 따라 성능이 달라진다. -3. 데이터가 잘 모여있는 경우에 효과적이지, 노이즈가 많은 경우 효과적이지 않다. +- K 를 몇 개로 설정하냐에 따라 성능이 달라진다. +- K 개 군집의 중심점을 예측하여야 하는데, 어디를 중심점으로 두냐에 따라 성능이 달라진다. +- 데이터가 잘 모여있는 경우에 효과적이지, 노이즈가 많은 경우 효과적이지 않다. #### References @@ -742,55 +640,45 @@ K-means 알고리즘의 단점은 다음과 같다. 모델의 피쳐값이 줄어듦에 따라 특정 피쳐가 너무 큰 값을 갖지 않게 되면서 오버피팅을 방지할 수 있게 된다. -`L1 정규화 (라쏘 회귀)` +> **L1 정규화 (라쏘 회귀)** + L1 정규화는 특정 피쳐의 값이 매우 낮은 경우 (아웃라이어) 0에 수렴되는 특징이 있다. 특정 피쳐가 0이 되어 사라지는 것은 **feature selection** 과 동일하다고 볼 수 있다. -
- -
+$$ +Cost = \sum^N_{i=0} (y_i - \sum^M_{j=0} x_{ij}W_j)^2 + \lambda \sum^M_{j=0} |W_j| +$$ -
+> **L2 정규화 (릿지 회귀)** -`L2 정규화 (릿지 회귀)` L2 정규화는 특정 웨이트의 값이 매우 낮아도 0에 수렴되지는 않고 가까워지는 특징이 있다. 이는 L1 정규화에 비해 강하지 않게 정규화를 실행하여 항상 선형 모델에 일반화 효과를 줄 수 있다. -
- -
+$$ +Cost = \sum^N_{i=0} (y_i - \sum^M_{j=0} x_{ij}W_j)^2 + \lambda \sum^M_{j=0} W_j^2 +$$ -
- -loss 식에 람다 \* 모델의 웨이트에 대한 L1 or L2 norm 을 더해줌으로써 모델의 일반화가 가능해진다. +loss 식에 람다 모델의 웨이트에 대한 L1 or L2 norm 을 더해줌으로써 모델의 일반화가 가능해진다. loss 는 데이터 값과 추정 값의 차이로 모델은 loss 를 최소화하는 방향으로 학습하는데, L1 or L2 정규화를 사용하면 loss 가 웨이트의 크기만큼 커지기 때문에 데이터 값에 예측 값이 fit 해지지 않기 때문이다. > **Norm** -norm 은 벡터의 크기를 나타내는 것으로 L1 norm 은 벡터의 절댓값 크기를 나타내고, L2 norm 은 직선 거리 (제곱의 루트) 를 나타낸다. +Norm은 벡터의 크기를 나타내는 것으로 L1 Norm은 벡터의 절댓값 크기를 나타내고, L2 Norm은 직선 거리 (제곱의 루트) 를 나타낸다. -
- -
+![Norm](./img/2-machine-learning/norm.png) -
- 위 그림에서 초록선은 L2 norm 을 의미하고, 나머지 선은 L1 norm 을 의미한다. -- L1 loss - -
- -
+- **L1 loss** -
+$$ +L1LossFunction = \sum^n_{i=1} |y_{true} - y_{predicted}| +$$ - L2 loss -
- -
- -
+$$ +L2LossFunction = \sum^n_{i=1} (y_{true} - y_{predicted})^2 +$$ #### References @@ -819,26 +707,18 @@ norm 은 벡터의 크기를 나타내는 것으로 L1 norm 은 벡터의 절댓 - K-겹 교차검증(K-fold Cross Validation) - 계층별 k-겹 교차검증(Stratified K-Fold Cross Validation) -> **홀드아웃 교차검증** 방법은 일정한 비율의 validation 데이터셋 하나를 지정하여 검증 데이터셋으로 사용하는 것이다. 홀드아웃 교차검증을 사용하는 경우, 두가지 문제점이 존재한다. -> -> 1. validation 데이터셋으로 지정된 부분의 데이터가 학습셋으로 사용되지 않는다는 문제 -> 2. validation 데이터셋에 편향되도록 모델을 조정하게 된다는 문제 -> 이를 해결하기 위해 k-겹 교차검증이 등장했다. - -> **k-겹 교차검증** 방법은 train 데이터를 k개의 fold로 나누어, 그 중 하나의 fold를 validation 데이터셋으로 삼아 검증하는 방법을 k번 반복하여, 그 평균을 결과로서 사용하는 방법이다. -> 그러나 k-겹 교차검증 방법은 랜덤하게 validation 데이터셋을 지정하게 되므로, 편향된 데이터로 이뤄진 폴드가 생성될 수 있다는 단점이 있다. 이를 해결하기 위해서 계층별 k-겹 교차검증 방법이 등장했다. +> **홀드 아웃 교차검증** -> **계층별 k-겹 교차검증** 방법은 k-겹 교차검증 방법에서 fold를 나눌때, 랜덤하게 fold를 지정하는 것이 아닌, 각 클래스별 비율을 고려하여 fold를 구성하는 방법이다. +홀드아웃 교차검증방법은 일정한 비율의 validation 데이터셋 하나를 지정하여 검증 데이터셋으로 사용하는 것이다. 홀드아웃 교차검증을 사용하는 경우, 두가지 문제점이 존재한다. -
- -
+1. validation 데이터셋으로 지정된 부분의 데이터가 학습셋으로 사용되지 않는다는 문제 +2. validation 데이터셋에 편향되도록 모델을 조정하게 된다는 문제 -
+이를 해결하기 위해 k-겹 교차검증이 등장했다. -さんかく K-Fold 교차검증 +> **k-겹 교차검증** -교차검증 방법 중, 대표적인 `K-Fold 교차검증`의 세부적인 동작방법은 아래와 같다. +k-겹 교차검증 방법은 train 데이터를 k개의 fold로 나누어, 그 중 하나의 fold를 validation 데이터셋으로 삼아 검증하는 방법을 k번 반복하여, 그 평균을 결과로서 사용하는 방법이다. 세부적인 동작방법은 다음과 같다. 1. train 데이터셋을 k개의 fold로 나누고, 그 중 하나를 validation 데이터셋으로 지정한다. 2. validation 데이터셋을 제외한 나머지 폴드들을 train 데이터셋으로 사용하여 모델을 학습한다. @@ -846,8 +726,16 @@ norm 은 벡터의 크기를 나타내는 것으로 L1 norm 은 벡터의 절댓 4. 모델을 초기화한 후, 기존 validation 데이터셋이 아닌 다른 fold를 validation 데이터셋으로 지정하고, 2번 과정부터 다시 수행한다. 5. 모든 fold들이 한번씩 validation 데이터셋으로 사용된 후에는, 저장해둔 검증결과의 평균을 내어, 그것을 최종 validation 결과로 사용한다. -추가) 왜 test 데이터셋 만으로 검증하면 안될까? -모든 train 데이터셋을 학습하고, test 데이터셋으로 검증한 결과를 확인한다고 하자. 개발자는 test 데이터셋 점수를 높이기 위해, test 데이터셋에 편향되도록 모델을 튜닝하게 될 것이다. 그러나 중요한 것은 test 데이터셋에 대한 정확도를 높이는 것 뿐만아니라, 모델의 일반적인 정확도를 높이는 것이다. 어떤 데이터가 들어와도 일정하게 높은 정확도를 보여주는 모델이 좋은 모델이라 할 수 있으므로, validation 데이터셋과 test 데이터셋을 분리하여 검증하는 과정을 통해, 모델을 일반화시켜야 한다. +그러나 k-겹 교차검증 방법은 랜덤하게 validation 데이터셋을 지정하게 되므로, 편향된 데이터로 이뤄진 폴드가 생성될 수 있다는 단점이 있다. 이를 해결하기 위해서 계층별 k-겹 교차검증 방법이 등장했다. + +> **계층별 k-겹 교차검증** + +계층별 k-겹 교차검증 방법은 k-겹 교차검증 방법에서 fold를 나눌때, 랜덤하게 fold를 지정하는 것이 아닌, 각 클래스별 비율을 고려하여 fold를 구성하는 방법이다. + +![계층별 k-겹 교차검증](./img/2-machine-learning/stratified-kfold.png) + +> **💡 왜 test 데이터셋 만으로 검증하면 안될까?** +> 모든 train 데이터셋을 학습하고, test 데이터셋으로 검증한 결과를 확인한다고 하자. 개발자는 test 데이터셋 점수를 높이기 위해, test 데이터셋에 편향되도록 모델을 튜닝하게 될 것이다. 그러나 중요한 것은 test 데이터셋에 대한 정확도를 높이는 것 뿐만아니라, 모델의 일반적인 정확도를 높이는 것이다. 어떤 데이터가 들어와도 일정하게 높은 정확도를 보여주는 모델이 좋은 모델이라 할 수 있으므로, validation 데이터셋과 test 데이터셋을 분리하여 검증하는 과정을 통해, 모델을 일반화시켜야 한다. #### References @@ -873,8 +761,8 @@ XGBoost의 장점은 다음과 같다. **GBM(Gradient Boosting Algorithm)** 이란 회귀분석 또는 분류 분석을 수행할 수 있는 **예측모형**이며 예측모형의 **앙상블 방법론** 중 **부스팅** 계열에 속하는 알고리즘이다. LightGBM, CatBoost, XGBoost는 모두 GBM을 기반으로 만들어졌다. (자세한 내용은 [Gradient Boosting Algorithm의 직관적인 이해 - DeepPlay](https://3months.tistory.com/368) 참고) -> **Q.** boosting 이라는 테크닉 자체가 sequential 한데 어떻게 병렬처리를 할까? -> **A.** 세가지 가능성이 제기된다. 나뉜 분기마다 각각 병렬처리하거나, 분기가 나뉘는 지점 계산을 병렬처리 하거나, 처음부터 feature별 정렬을 통해 병렬처리를 할 수 있다. (자세한 내용은 [XGBoost의 병렬처리가 어떻게 가능할까? - GoLab](http://machinelearningkorea.com/2019/07/25/xgboost-%EC%9D%98-%EB%B3%91%EB%A0%AC%EC%B2%98%EB%A6%AC%EA%B0%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EA%B0%80%EB%8A%A5%ED%95%A0%EA%B9%8C/) 참고) +> **💡 boosting 이라는 테크닉 자체가 sequential 한데 어떻게 병렬처리를 할까?** +> 세가지 가능성이 제기된다. 나뉜 분기마다 각각 병렬처리하거나, 분기가 나뉘는 지점 계산을 병렬처리 하거나, 처음부터 feature별 정렬을 통해 병렬처리를 할 수 있다. (자세한 내용은 [XGBoost의 병렬처리가 어떻게 가능할까? - GoLab](http://machinelearningkorea.com/2019/07/25/xgboost-%EC%9D%98-%EB%B3%91%EB%A0%AC%EC%B2%98%EB%A6%AC%EA%B0%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EA%B0%80%EB%8A%A5%ED%95%A0%EA%B9%8C/) 참고) #### References @@ -887,23 +775,18 @@ XGBoost의 장점은 다음과 같다. #### 앙상블 방법엔 어떤 것들이 있나요? -
- -
- -
+![앙상블 기법](./img/2-machine-learning/ensemble.png) **앙상블(Ensemble)** 은 여러개의 모델을 조합해서 그 결과를 뽑아 내는 방법이다. "정확도가 높은 강한 모델을 하나 사용하는 것보다, 정확도가 낮은 약한 모델을 여러개 조합 하는 방식의 정확도가 높다"는 개념에서 비롯한 방법이다. `Bagging`, `Boosting`, `Stacking` 등의 방법이 있다. -**배깅(Bagging, Bootstrap Aggregation)** 이란 샘플을 여러번 뽑아(Bootstrap = 복원 랜덤 샘플링) 각 모델을 학습시켜 결과물을 집계(Aggregation)하는 방법이다. 카테고리 데이터는 투표 방식(Votinig)으로 결과를 집계하며, 연속형 데이터는 평균으로 집계한다. Bagging을 사용한 대표적인 기법에는 `Random Forest` 방법이 있다. 학습 데이터가 충분하지 않더라도 충분한 학습효과를 주어 높은 bias의 underfitting 문제나, 높은 variance로 인한 overfitting 문제를 해결하는데 도움을 준다. +**배깅(Bagging, Bootstrap Aggregation)** 이란 샘플을 여러번 뽑아(Bootstrap = 복원 랜덤 샘플링) 각 모델을 학습시켜 결과물을 집계(Aggregation)하는 방법이다. 카테고리 데이터는 투표 방식(Voting)으로 결과를 집계하며, 연속형 데이터는 평균으로 집계한다. Bagging을 사용한 대표적인 기법에는 `Random Forest` 방법이 있다. 학습 데이터가 충분하지 않더라도 충분한 학습효과를 주어 높은 bias의 underfitting 문제나, 높은 variance로 인한 overfitting 문제를 해결하는데 도움을 준다. **부스팅(Boosting)** 이란 이전 모델의 오답에 가중치를 높게 부여하여 다음 모델을 학습하는 방법이다. 오답을 정답으로 맞추기 위해 오답에 더 집중하여 학습시키기 떄문에 일반적으로 배깅에 비해 정확도가 높다. 그러나 틀렸던 부분에 대해 반복적으로 학습하므로 오버피팅의 문제가 있으며, outlier에 취약하고, 속도가 느리다는 단점도 가지고 있다. `GBM(Gradient Boosting)` 방법이 대표적이고, `XGBoost, AdaBoost, GradientBoost` 등의 알고리즘이 존재한다. **스태킹(Stacking)** 이란 여러 개별 모델이 예측한 결과값을 다시 학습 데이터셋으로 사용해서 모델을 만드는 방법이다. 그러나 위의 그림과 같은 기본적인 스태킹 방법은 `같은 데이터셋을 통해 예측한 결과를 기반으로 다시 학습`하므로 `오버피팅` 문제점이 있다. 따라서 스태킹에 Cross Validation 방식을 도입하여 이 문제를 해결할 수 있다. 데이터를 쪼개고 이들 중 일부만을 가지고 학습한 모델을 여러개 만들어, 그 결과들을 `메타 학습 데이터셋(meta train dataset)` 으로 사용하여 다시 학습하는 것이다. 이 방법은 많은 개별 모델의 결과를 결합하여 예측 성능을 높일 수 있다는 장점이 있다. -> **배깅 vs 부스팅** -> **배깅**은 랜덤 복원추출(부트스트랩)을 여러번 반복하여 모델을 **병렬적**으로 여러개 학습을 시킨 다음, 평균을 내는 방식이다. -> 반면, **부스팅**은 모든 데이터를 학습에 사용하되, 오답에 더 큰 가중치를 두어 다음 회차를 학습시키는 **순차적**인 방법이다. +> **💡 배깅 vs 부스팅** +> **배깅**은 랜덤 복원추출(부트스트랩)을 여러번 반복하여 모델을 **병렬적**으로 여러개 학습을 시킨 다음, 평균을 내는 방식이다. 반면, **부스팅**은 모든 데이터를 학습에 사용하되, 오답에 더 큰 가중치를 두어 다음 회차를 학습시키는 **순차적**인 방법이다. #### References @@ -923,17 +806,15 @@ XGBoost의 장점은 다음과 같다. d-차원 데이터의 특징 벡터는 다음과 같이 표시된다. - - - +$$ -
- -> **컴퓨터비전(이미지)** 에서의 특징은 edge, corner 등을 의미한다. 픽셀 값이 급격히 변화하는 곳, 밝기의 변화, 색상의 변화, 그래디언트의 방향 등의 매칭 정보등을 특징으로 삼는다. SIFT, SURF 등의 방법이 존재한다. -> **자연어처리(텍스트)** 에서의 특징은 단어, 형태소, 서브워드, 토큰 등으로 표현될 수 있으며, BOW(Bag-of-Words)는 문서에서 단어의 발생을 설명하는 텍스트의 벡터 표현이다. 만약 8개의 단어로 이루어진 문장을 BoW로 만들면, 8차원(dimension)의 vector로서 하나의 단어를 표현할 수 있다. -> **정형데이터**에서의 특징은 각 attribute(열)를 의미한다. 키, 나이, 국적 등이 특징으로 사용될 수 있다. +> **💡 분야에 따른 피처벡터의 의미** +> +> - 컴퓨터비전(이미지)에서의 특징은 edge, corner 등을 의미한다. 픽셀 값이 급격히 변화하는 곳, 밝기의 변화, 색상의 변화, 그래디언트의 방향 등의 매칭 정보등을 특징으로 삼는다. SIFT, SURF 등의 방법이 존재한다. +> - **자연어처리(텍스트)** 에서의 특징은 단어, 형태소, 서브워드, 토큰 등으로 표현될 수 있으며, BOW(Bag-of-Words)는 문서에서 단어의 발생을 설명하는 텍스트의 벡터 표현이다. 만약 8개의 단어로 이루어진 문장을 BoW로 만들면, 8차원(dimension)의 vector로서 하나의 단어를 표현할 수 있다. +> - **정형데이터**에서의 특징은 각 attribute(열)를 의미한다. 키, 나이, 국적 등이 특징으로 사용될 수 있다. #### References @@ -950,7 +831,7 @@ $$ --> #### 좋은 모델의 정의는 무엇일까요? -> 한 줄로 요약하자면, 좋은 모델은 **데이터의 패턴을 잘 학습한 모델**로서, **한번도 본적 없는 데이터에 대해 옳은 판단을 내리는 모델**이 좋은 모델이라고 할 수 있다. +한 줄로 요약하자면, 좋은 모델은 **데이터의 패턴을 잘 학습한 모델**로서, **한번도 본적 없는 데이터에 대해 옳은 판단을 내리는 모델**이 좋은 모델이라고 할 수 있다. 머신러닝, 딥러닝 등을 사용하여 모델을 생성하는 이유는 `기계가 사람 대신 어떠한 결정을 내리기 위함`이다. 따라서 모델은 `결정을 대신하는 기계, 결정기`라고 볼 수 있다. 이 관점에서, 좋은 결정(옳은 결정)을 내리는 모델이 좋은 모델이다. 주어진 학습 데이터에 과적합된 모델의 경우, 주어진 데이터와 조금만 다른 데이터가 들어오면 제대로 분류하지 못하는 상황이 발생된다. @@ -972,17 +853,17 @@ $$ --> 50개의 작은 의사결정 나무는 앙상블에서 `Bagging` 기법을 사용한 모델로 볼 수 있다. 따라서 Bagging의 대표적인 방법인 `Random Forest` 방법이 왜 좋은지 설명하는 것으로, 왜 50개의 작은 의사결정 나무가 더 나은지 설명하고자 한다. -
- -
- -
+![](./img/2-machine-learning/random-forest-bagging.png) 큰 트리는 작은 편향(bias)와 큰 분산(variance)를 갖기 때문에, 매우 깊이 성장한 트리는 훈련데이터에 대해 과적합(overfitting)하게 된다. Random Forest 방식으로 학습하면, 트리들의 편향은 그대로 유지하면서, **여러 데이터셋/여러 경우에 대해 학습하기 떄문에 분산을 감소**시킬 수 있다. 또한 한 개의 결정트리의 경우, train 데이터에 있는 노이즈에 대해 매우 민감하지만, 여러 트리들을 만들면서 평균을 내면, **노이즈에 대해 강인**해질 수 있다. 따라서 하나의 깊은/큰 의사결정 나무보다 50개의 작은 의사결정 나무가 더 좋은 모델을 완성시킨다고 할 수 있다. -> **Bagging(Bootstrap Aggregating)** 은 Bootstrap(반복, 복원추출)하고, 이를 Aggregation(집계)하는 방법이다. 원래 데이터셋에 대해서 여러개의 작은 데이터셋 N개를 샘플링해서 만든다음, 각각의 데이터를 작은 모델 N개로 학습을 시킨다. 그 다음 학습된 N개의 모델을 모두 하나로 합쳐서 최종적인 모델로 사용하는 방법론을 의미한다. 결국, 병렬적으로 데이터를 나누어 여러 개의 모델을 동시에 학습시키는 방법이다. +> **Bagging(Bootstrap Aggregating)** -> **Random Forest**는 여러 의사 결정 나무를 생성한 후에 다수결(hard voting) 또는 평균(soft voting)에 따라 출력을 예측하는 알고리즘이다. 즉 의사 결정 나무와 bagging을 혼합한 형태라고 볼 수 있다. Random Forest의 특징은 bootstrap을 이용하여 학습 데이터셋에서 다양한 샘플을 추출하여 일부만 한번의 학습에 사용한다는 것이다. 데이터 샘플링 및 변수 선택을 통해 의사 결정 나무의 다양성을 확보할 수 있다. 이를 통해 예측의 변동성이 줄어들고, 과적합을 방지할 수 있어 결측치에 대해 강건하다는 장점을 가진다. 그러나 데이터의 수가 많아지면 의사결정나무에 비해 속도가 크게 떨어지고, 결과에 대한 해석이 어렵다는 단점이 있다. +Bagging은 Bootstrap(반복, 복원추출)하고, 이를 Aggregation(집계)하는 방법이다. 원래 데이터셋에 대해서 여러개의 작은 데이터셋 N개를 샘플링해서 만든다음, 각각의 데이터를 작은 모델 N개로 학습을 시킨다. 그 다음 학습된 N개의 모델을 모두 하나로 합쳐서 최종적인 모델로 사용하는 방법론을 의미한다. 결국, 병렬적으로 데이터를 나누어 여러 개의 모델을 동시에 학습시키는 방법이다. + +> **Random Forest** + +Random Forest는 여러 의사 결정 나무를 생성한 후에 다수결(hard voting) 또는 평균(soft voting)에 따라 출력을 예측하는 알고리즘이다. 즉 의사 결정 나무와 bagging을 혼합한 형태라고 볼 수 있다. Random Forest의 특징은 bootstrap을 이용하여 학습 데이터셋에서 다양한 샘플을 추출하여 일부만 한번의 학습에 사용한다는 것이다. 데이터 샘플링 및 변수 선택을 통해 의사 결정 나무의 다양성을 확보할 수 있다. 이를 통해 예측의 변동성이 줄어들고, 과적합을 방지할 수 있어 결측치에 대해 강건하다는 장점을 가진다. 그러나 데이터의 수가 많아지면 의사결정나무에 비해 속도가 크게 떨어지고, 결과에 대한 해석이 어렵다는 단점이 있다. #### References @@ -998,54 +879,40 @@ $$ --> 스팸 필터는 메일이 스팸 메일인지 아닌지에 대한 확률을 계산하여, 메일을 **분류(Classification)** 하는 문제이다. 로지스틱 회귀는 회귀를 바탕으로 데이터가 어떤 범주에 속할 확률을 0과 1 사이의 값으로 예측하고 그 확률에 따라 가능성이 더 높은 범주에 속하는 것으로 분류(Classification)해주는 지도 학습 알고리즘이다. 특히 **입력값이 아무리 크거나 작아도 0에서 1 사이의 값으로 맵핑**시킨다는 점에서 분류문제에 적합하다. 따라서 로지스틱 회귀가 스팸필터에 많이 사용된다. -> **추가내용** - -
- -
- -
+![](./img/2-machine-learning/linear-and-logistic-regression.png) > **분류문제에서 로지스틱 회귀가 적절한 이유** 로지스틱 회귀는 **시그모이드 함수(sigmoid function)** 를 통해 선형함수를 0과 1 사이의 함수로 바꾼 것이며, S자 형태를 보인다. 시그모이드 함수의 정의는 아래와 같다. - - - - -
+$$ 로지스틱 회귀의 가설함수는 다음과 같다. - - - - -
+$$ x값이 아무리 +, -로 작아지거나 커져도 항상 0과 1 사이의 값을 반환한다. 확률은 **0에서 1사이의 범위 내에 들어와야하므로** 이러한 형태가 적합하다. + 이렇게 H(x)의 값이 0과 1사이로 나오면, 위의 Hypothesis 함수로 regression을 한 결과값이 threshold(ex.0.5) 이상인 경우엔 1로 분류하고, threshold 보다 작으면 0으로 분류하면 되기 떄문이다. > **분류문제에서 선형회귀가 적합하지 않은 이유** `그림1`과 같이 주어진 데이터를 표현하는 그래프를 그려, 적절한 지점을 기준으로 두 그룹으로 분류할 수 있다. + 이때 `그림2`의 `new` 데이터가 새로 들어왔다고 해보자. 그래프는 새로운 데이터 `new`의 영향을 받아, 아래로 기울어진 형태로 업데이트되어, `그림3`의 붉은색 그래프 형태가 된다. 이렇게 되면, 원래는 1로 잘 분류되던 것들의 예측값이 기존 threshold 아래로 내려가게되어, 0으로 분류되어버리는 문제가 발생한다. -
- -
+![](./img/2-machine-learning/classification-and-linear-regression.png) + +선형회귀 함수는 어떤 입력값이 들어오느냐에 따라 **0과 1 사이의 범위를 벗어나기도** 한다. -
+또한, `H(x) = 100x`라는 가설함수(Hypothesis function)이 있다고 하자. x가 0.01 이상인 경우는 모두 1로 x가 0 이하인 경우는 모두 0으로 분류하게 된다. 이처럼 **x값에 너무 민감하게 반응**하는 모델이 만들어질 수 있다. 연산상으로는 매우 작은 값만 바뀌어도 아예 분류자체가 바뀌어버린다. -선형회귀 함수는 어떤 입력값이 들어오느냐에 따라 **0과 1 사이의 범위를 벗어나기도** 한다. -또한, `H(x) = 100x`라는 가설함수(Hypothesis function)이 있다고 하자. x가 0.01 이상인 경우는 모두 1로 x가 0 이하인 경우는 모두 0으로 분류하게 된다. 이처럼 **x값에 너무 민감하게 반응**하는 모델이 만들어질 수 있다. 연산상으로는 매우 작은 값만 바뀌어도 아예 분류자체가 바뀌어버린다. 더 나아가, 선형모델은 확률이 아닌, 점들의 보간(interpolate)만으로 이루어지므로 확률로 해석할 수 없다. 예측값이 확률이 아니기 때문에 한 클래스와 다른 **클래스를 구분할 수 있는 의미 있는 임계값이 없다.** 또한 다중 클래스를 가지는 분류문제로 확장할 수 없다는 문제점도 있다. 이러한 문제점들 때문에, 분류문제에서 선형 회귀 모델은 적합하지 못하다. #### References @@ -1062,25 +929,15 @@ x값이 아무리 +, -로 작아지거나 커져도 항상 0과 1 사이의 값 **최소자승법(OLS, Ordinary Least Squares)** 이란, 산점도를 통해 데이터의 분포 그래프를 그릴때, 이 데이터들의 경향을 알기 위한 최적의 추세선을 그리기 위한 방법 중 하나이다. OLS는 근사적으로 구하려는 해와 실제 해의 오차의 제곱의 합이 최소가 되는 해를 구하는 방법이다. -OLS Regression은 회귀를 통해서 방정식의 상수 값들을 추정하는 데에 사용된다. n개의 입력값과 그에 대응하는 출력값 이 있고, 이 계의 방정식이 변수 와 인 상수 으로 주어질 때, 의 값을 최소로 만드는 를 구하는 것이 문제의 목표이다. +OLS Regression은 회귀를 통해서 방정식의 상수 값들을 추정하는 데에 사용된다. n개의 입력값과 그에 대응하는 출력값 $(x_i, y_i)(1\leq i\leq n)$이 있고, 이 계의 방정식이 변수 $x$와 $\beta=(\beta_0, \beta_1, \cdots , \beta_k )$인 상수 $\beta$에 대한 식 $f(x, \beta)$으로 주어질 때, $\sum_i(y_i - f(x_i, \beta))^{2}$ 의 값을 최소로 만드는 $\beta$를 구하는 것이 문제의 목표이다. 추정하고자 하는 파라미터 β에 대한 표현식을 다음과 같이 구할 수 있다. - - - +$$ +{\hat {\beta}}=(\mathbf {X}^{\rm {T}}\mathbf {X})^{-1}\mathbf {X}^{\rm {T}}\mathbf {y} = {\big (} ~ {\textstyle \sum }\mathbf x_i \mathbf x_i^{\rm {T}},円{\big )}^{-1}{\big (} ~ {\textstyle \sum }\mathbf x_i y_i ~ {\big)} +$$ -
- -> **추가) OLS가 가지는 의미** - -
- -
- -
+![](./img/2-machine-learning/ols.png) 예를들어, 7개 데이터의 경향을 나타내는 추세선을 `그림2`와 같이 그렸다고 하자. 이때 실제 데이터의 y값(실제값)과 추세선의 y값(예측값)의 차를 **잔차(Residual)** 라고 한다. (아래 그래프에서 잔차는 점선으로 표시) @@ -1089,18 +946,15 @@ $$ --> 잔차 제곱의 합을 구하는 식은 아래와 같다. -
- -
- -
+![](./img/2-machine-learning/rss.png) 파란색 추세선보다 보라색 추세선의 잔차제곱의 합이 더 작다. 따라서 파란색 추세선보다 보라색 추세선이 위 7개의 데이터를 더 잘 표현해주는 추세선임을 알 수 있다. 이렇게 잔차 제곱의 합을 최소로 하는 방법이 최소자승법이며, 최소자승법을 활용하여 데이터를 가장 잘 표현하는 선형 회귀선을 그릴 수 있다. -> **추가) OLS vs. MSE** -> • OLS(Ordinary Least Square): 선형 회귀 모델을 만들기 위한 선횡 최소 제곱법, 모델을 만들때 사용한다. -> • MSE(Mean Square Error): 모델 성능 평가 지표, 모델을 평가할 때 사용한다. +> **💡 OLS vs. MSE** +> +> - OLS(Ordinary Least Square): 선형 회귀 모델을 만들기 위한 선횡 최소 제곱법, 모델을 만들때 사용한다. +> - MSE(Mean Square Error): 모델 성능 평가 지표, 모델을 평가할 때 사용한다. #### References diff --git a/answers/3-deep-learning.md b/answers/3-deep-learning.md index 3c8250f..10f9c40 100644 --- a/answers/3-deep-learning.md +++ b/answers/3-deep-learning.md @@ -1,10 +1,4 @@ -
-

🧠 Deep Learning 🧠

-
- -> 질문은 [zzsza님의 Datascience-Interview-Questions](https://github.com/zzsza/Datascience-Interview-Questions)를 참고하였습니다. - ---- +> **📌 질문은 [zzsza님의 Datascience-Interview-Questions](https://github.com/zzsza/Datascience-Interview-Questions)를 참고하였습니다.** ## Table of Contents @@ -61,22 +55,18 @@ #### 딥러닝은 무엇인가요? 딥러닝과 머신러닝의 차이는? -**딥러닝이란** 여러 층을 가진 인공신경망(Artificial Neural Network, ANN)을 사용하여 머신러닝 학습을 수행하는 것으로, 심층학습이라고도 부른다. +딥러닝이란 **여러 층을 가진 인공신경망(Artificial Neural Network, ANN)을 사용하여 머신러닝 학습을 수행하는 것**으로, 심층학습이라고도 부른다. -> 딥러닝은 엄밀히 말하자면 머신러닝에 포함되는 개념이다. 따라서 전통적인 머신러닝 기법과 딥러닝 기법의 차이를 설명하고자 한다. +딥러닝은 엄밀히 말하자면 머신러닝에 포함되는 개념이다. 따라서 전통적인 머신러닝 기법과 딥러닝 기법의 차이를 설명하고자 한다. -> 인공신경망, 퍼셉트론에 대한 내용은 [reference](http://tcpschool.com/deep2018/deep2018_deeplearning_intro)를 참고 +(인공신경망, 퍼셉트론에 대한 내용은 [reference](http://tcpschool.com/deep2018/deep2018_deeplearning_intro)를 참고) -**머신러닝과 딥러닝의 가장 큰 차이점**은 다음과 같다. 기존 머신러닝에서는 학습하려는 데이터의 여러 특징 중에서 `어떤 특징을 추출할지 사람이 직접 분석하고 판단`해야하는 반면, 딥러닝에서는 기계가 `자동으로 학습하려는 데이터에서 특징을 추출`하여 학습하게 된다. 따라서 특징 추출에 사람이 개입(feature engineering)하면 머신러닝, 개입하지 않으면 딥러닝이다. +머신러닝과 딥러닝의 가장 큰 차이점은 다음과 같다. 기존 머신러닝에서는 학습하려는 데이터의 여러 특징 중에서 **어떤 특징을 추출할지 사람이 직접 분석하고 판단**해야하는 반면, 딥러닝에서는 기계가 **자동으로 학습하려는 데이터에서 특징을 추출**하여 학습하게 된다. 따라서 특징 추출에 사람이 개입(feature engineering)하면 머신러닝, 개입하지 않으면 딥러닝이다. 또한, 딥러닝은 머신러닝보다 큰 데이터셋과 긴 학습시간이 필요하다. 정형데이터는 주로 머신러닝, 비정형데이터는 주로 딥러닝 방식을 사용한다. -> **추가내용) AI, ML, DL** +> **AI, ML, DL** -
- -
- -
+![](./img/3-deep-learning/ai.png) **인공지능이란** 인간이 가지고 있는 인식, 판단 등의 지적 능력을 모델링하여 컴퓨터에서 구현하는 것이다. 머신러닝, 딥러닝 외에도 다양한 분야가 인공지능 내에 포함된다. @@ -84,10 +74,9 @@ 머신러닝은 아래와 같이 분류된다. -- 지도학습 - - 분류, 회귀, 추천시스템, 시각/음성 인지(DL), 텍스트분석/NLP(DL) -- 비지도학습 - - 클러스터링, 차원축소, 강화학습 +| 지도 학습 | 비지도 학습 | +| :---------------------------------------------------------------: | :----------------------------: | +| 분류, 회귀, 추천시스템
시각/음성 인지(DL), 텍스트분석/NLP(DL) | 클러스터링, 차원축소, 강화학습 | #### References @@ -135,26 +124,22 @@ #### Tensorflow, PyTorch 특징과 차이가 뭘까요? -| 구분 | Tensorflow | PyTorch | -| ----------- | ------------------ | ------------------- | -| 패러다임 | Define and Run | Define by Run | +| 구분 | Tensorflow | PyTorch | +| :---------: | :----------------: | :-----------------: | +| 패러다임 | Define and Run | Define by Run | | 그래프 형태 | Static graph(정적) | Dynamic graph(동적) | Tensorflow와 Pytorch의 가장 큰 차이점은 딥러닝을 구현하는 패러다임이 다르다는 것이다. Tensorflow는 **Define-and-Run**인 반면에, Pytorch는 **Define-by-Run**이다. -> Define and Run (Tensorflow)
코드를 직접 돌리는 환경인 세션을 만들고, placeholder를 선언하고 이것으로 계산 그래프를 만들고(Define), 코드를 실행하는 시점에 데이터를 넣어 실행하는(Run) 방식으로 이는 계산 그래프를 명확히 보여주면서 실행시점에 데이터만 바꿔줘도 되는 유연함을 장점으로 갖지만, 그 자체로 비직관적이다. +Define and Run (Tensorflow)은 코드를 직접 돌리는 환경인 세션을 만들고, placeholder를 선언하고 이것으로 계산 그래프를 만들고(Define), 코드를 실행하는 시점에 데이터를 넣어 실행하는(Run) 방식이다. 이는 계산 그래프를 명확히 보여주면서 실행시점에 데이터만 바꿔줘도 되는 유연함을 장점으로 갖지만, 그 자체로 비직관적이다. -> Define by Run (PyTorch)
선언과 동시에 데이터를 집어넣고 세션도 필요없이 돌리면 되기때문에 코드가 간결하고 난이도가 낮은 편이다. +Define by Run (PyTorch)은 선언과 동시에 데이터를 집어넣고 세션도 필요없이 돌리면 되기때문에 코드가 간결하고 난이도가 낮은 편이다. 두 프레임워크 모두 계산 그래프를 정의하고 자동으로 그래디언트를 계산하는 기능이 있다. 하지만 Tensorflow의 계산 그래프는 정적이고 Pytorch는 동적이다. 즉 Tensorflow에서는 계산 그래프를 한 번 정의하고 나면 그래프에 들어가는 입력 데이터만 다르게 할 수 있을 뿐 같은 그래프만을 실행할 수 있다. 하지만 PyTorch는 각 순전파마다 새로운 계산 그래프를 정의하여 이용한다. -
- -
- -
+![](./img/3-deep-learning/static-dynamic-graph.png) #### References @@ -167,24 +152,21 @@ Tensorflow와 Pytorch의 가장 큰 차이점은 딥러닝을 구현하는 패 #### Data Normalization은 무엇이고 왜 필요한가요? -**Data Normalization(데이터 정규화)이란** feature들의 분포(scale)을 조절하여 균일하게 만드는 방법이다. 데이터 정규화가 필요한 이유는 데이터 feature 간 scale 차이가 심하게 날 때, 큰 범위를 가지는 feature(ex. 가격)가 작은 범위를 가지는 feature(ex. 나이)보다 더 강하게 모델에 반영될 수 있기 때문이다. +**Data Normalization(데이터 정규화)이란** feature들의 분포(scale)을 조절하여 균일하게 만드는 방법이다. 데이터 정규화가 필요한 이유는 데이터 feature 간 scale 차이가 심하게 날 때, 큰 범위를 가지는 feature(ex. 가격)가 작은 범위를 가지는 feature(ex. 나이)보다 더 강하게 모델에 반영될 수 있기 때문이다. + 즉, 데이터 정규화는 모든 데이터 포인트가 동일한 정도의 스케일(중요도)로 반영되도록 하는 역할을 수행하며, 아래와 같은 장점을 얻을 수 있다. - 학습속도가 개선된다. - 노이즈가 작아지므로 오버피팅을 억제시킨다. - 데이터를 덜 치우치게 만드므로, 좋은 성능을 보인다. -
- -
- -
+![](./img/3-deep-learning/data-normalization.png) -> **추가내용) Regularization, Normalization, Standardization** +> **Regularization, Normalization, Standardization** **Regularization(정규화, 규제)** 란 모델에 제약(penalty)를 주어 모델의 복잡성을 낮추고, 이를 통해 오버피팅을 방지하는 방법이다. 제약을 사용하면 학습 정확도(train accuracy)는 조금 낮아질 수 있지만, 테스트 정확도(test accuracy)를 높일 수 있다. 정규화에는 `Drop out, Early Stopping, Weight decay(Parameter Norm Penalty)`와 같은 방법이 존재한다. -- 자세한 Regularization 방법은 [reference](https://bsm8734.github.io/posts/bc-d012-3-dlbasic-optimization-regularization/) 참고 +(자세한 Regularization 방법은 [reference](https://bsm8734.github.io/posts/bc-d012-3-dlbasic-optimization-regularization/) 참고) **Normalization, Standardization**은 모두 데이터의 범위(scale)을 축소하는 방법이다.(re-scaling) 데이터의 범위 재조정이 필요한 이유는 `데이터의 범위가 너무 넓은 곳에 퍼져있을 때(scale이 크다면), 데이터셋이 outlier를 지나치게 반영`하여 오버피팅이 될 가능성이 높기 때문이다. 두 방법은 scale 조절 방식에 차이가 존재한다. @@ -192,12 +174,18 @@ Tensorflow와 Pytorch의 가장 큰 차이점은 딥러닝을 구현하는 패 - `Batch Normalization`: 적용시키려는 레이어의 통계량, 분포를 정규화시키는 방법이다. - `Min-Max Normalization`: 모든 데이터 중에서 가장 작은 값을 0, 가장 큰 값을 1로 두고, 나머지 값들은 비율을 맞춰서 모두 0과 1 사이의 값으로 스케일링하는 방법이다. 모든 feature들의 스케일이 동일하지만, 이상치(outlier)를 잘 처리하지 못한다. 식은 아래와 같다. - - + +$$ +x= {{x - x_{min}} \over {x_{max} - x_{min}}} +$$ **Standardization(표준화)** 란 표준화 확률변수를 구하는 방법이다. 이는 `z-score를 구하는 방법`을 의미한다. z-score normalization이라 불리기도 한다. - `Z-score`: 관측값이 평균 기준으로 얼마나 떨어져있는지 나타낼 때 사용한다. 각 데이터에서 데이터 전체의 평균을 빼고, 이를 표준편차로 나누는 방식이다. 이상치(outlier)를 잘 처리하지만, 정확히 동일한 척도로 정규화 된 데이터를 생성하지는 않는다. 식은 아래와 같다. - - + +$$ +z-score = {{x-{\mu}} \over {\sigma}} +$$ #### References @@ -213,63 +201,35 @@ Tensorflow와 Pytorch의 가장 큰 차이점은 딥러닝을 구현하는 패 #### 알고있는 Activation Function에 대해 알려주세요. (Sigmoid, ReLU, LeakyReLU, Tanh 등) -**Sigmoid** - -
- -
-
- -
- -
-
+> **Sigmoid** -sigmoid 함수는 입력을 0~1 사이의 값으로 바꿔준다. +![](./img/3-deep-learning/sigmoid.png) -입력 값이 크거나 작을 때 기울기가 0에 가까워지는 `saturation` 문제가 있다. -이는 `gradient vanishing` 문제를 야기하므로 요즘에는 활성화 함수로서 잘 사용되지 않는다. +sigmoid 함수는 $s(z) = \frac{1}{1 + e^{-z}}$로, 입력을 0~1 사이의 값으로 바꿔준다. -또한 값이 `zero-centered` 가 아니기 때문에 입력값의 부호에 그대로 영향을 받으므로 경사하강법 과정에서 정확한 방향으로 가지 못하고 지그재그로 움직이는 문제가 있다. [12-3 참고](#12-3) +입력 값이 크거나 작을 때 기울기가 0에 가까워지는 `saturation` 문제가 있다. 이는 `gradient vanishing` 문제를 야기하므로 요즘에는 활성화 함수로서 잘 사용되지 않는다. -**Tanh** +또한 값이 `zero-centered` 가 아니기 때문에 입력값의 부호에 그대로 영향을 받으므로 경사하강법 과정에서 정확한 방향으로 가지 못하고 지그재그로 움직이는 문제가 있다. ([12-3 참고](#12-3)) -
- -
-
+> **Tanh** -tanh 함수는 입력을 -1~1 사이의 값으로 바꿔준다. +![](./img/3-deep-learning/tanh.png) -sigmoid 함수와 마찬가지로 `saturation` 문제가 있다. +tanh 함수는 입력을 -1~1 사이의 값으로 바꿔준다. sigmoid 함수와 마찬가지로 `saturation` 문제가 있다. -**ReLU** +**> ReLU** -
- -
-
- -ReLU 함수는 입력이 양수면 그대로, 음수면 0을 출력한다. +![](./img/3-deep-learning/relu.png) -> f(x) = max(0, x) +ReLU 함수는 $f(x) = max(0, x)$으로, 입력이 양수면 그대로, 음수면 0을 출력한다. 계산 효율과 성능에서 뛰어난 성능을 보여 가장 많이 사용되는 활성화 함수이다. 양의 입력에 대해서는 `saturation` 문제가 발생하지 않는다. 음의 입력 값에 대해서는 어떤 업데이트도 되지 않는 `Dead ReLU` 문제가 발생한다. -계산 효율과 성능에서 뛰어난 성능을 보여 가장 많이 사용되는 활성화 함수이다. +> **Leaky ReLU** -양의 입력에 대해서는 `saturation` 문제가 발생하지 않는다. +![](./img/3-deep-learning/leaky-relu.png) -음의 입력 값에 대해서는 어떤 업데이트도 되지 않는 `Dead ReLU` 문제가 발생한다. +> -**LeakyReLU** - -
- -
-
- -> f(x) = max(0.01x, x) - -`ReLU` 와 마찬가지로 좋은 성능을 유지하면서 음수 입력이 0이 아니게 됨에 따라 `Dead ReLU` 문제를 해결하였다. +Leaky ReLU는 $f(x) = max(0.01x, x)$으로, ReLU 와 마찬가지로 좋은 성능을 유지하면서 음수 입력이 0이 아니게 됨에 따라 `Dead ReLU` 문제를 해결하였다. #### References @@ -282,76 +242,47 @@ ReLU 함수는 입력이 양수면 그대로, 음수면 0을 출력한다. #### 오버피팅일 경우 어떻게 대처해야 할까요? -**Regularization** +> **Early Stopping** -Generalization이 잘되도록 모델에 제약을 주며 학습을 하여 overfitting을 방지하는 방법 +training loss는 계속 낮아지더라도 validation loss는 올라가는 시점을 overfitting으로 간주하여 학습을 종료하는 방법이다. -- Early stopping +![](./img/3-deep-learning/early-stopping.png) - - training loss는 계속 낮아지더라도 validation loss는 올라가는 시점을 overfitting으로 간주하여 학습을 종료하는 방법 +> **Parameter Norm Penalty / Weight Decay** -
- -
+비용함수에 제곱을 더하거나($L_2 Regularization$) 절댓값을 더해서($L_1 Regularization$) weight의 크기에 페널티를 부과하는 방법을 말한다. -
+$$ +total cost = loss(D ; W) + \frac{\alpha}{2} \lVert W \rVert^2_2 +$$ -- Parameter norm penalty (weight decay) +> **Data augmentation** - - 비용함수에 제곱을 더하거나( ) 절댓값을 더해서( ) weight의 크기에 페널티를 부과하는 방법 +훈련 데이터의 개수가 적을 때, 데이터에 인위적으로 변화를 주어 훈련 데이터의 수를 늘리는 방법이다. -
- -
+![](./img/3-deep-learning/data-augmentation.png) -
+> **Noise robustness** -- Data augmentation +노이즈나 이상치같은 엉뚱한 데이터가 들어와도 흔들리지 않는(robust 한) 모델을 만들기 위해 input data나 weight에 일부러 노이즈를 주는 방법을 말한다. - - 훈련 데이터의 개수가 적을 때, 데이터에 인위적으로 변화를 주어 훈련 데이터의 수를 늘리는 방법 +![](./img/3-deep-learning/noise-robustness.png) -
- -
+> **Label smoothing** -
+모델이 Ground Truth를 정확하게 예측하지 않아도 되게 만들어 주어 정확하지 않은 학습 데이터셋에 치중되는 경향(overconfident)을 막아주는 방법이다. -- Noise robustness +> **Dropout** - - 노이즈나 이상치같은 엉뚱한 데이터가 들어와도 흔들리지 않는(robust 한) 모델을 만들기 위해 input data나 weight에 일부러 노이즈를 주는 방법 +각 계층 마다 일정 비율의 뉴런을 임의로 정해 drop 시키고 나머지 뉴런만 학습하도록 하는 방법을 말한다. 매 학습마다 drop 되는 뉴런이 달라지기 때문에 서로 다른 모델들을 앙상블 하는 것과 같은 효과가 있다. dropout은 **학습 시에만 적용**하고, 추론 시에는 적용하지 않는다. -
- -
- -
+![](./img/3-deep-learning/dropout.png) -- Label smoothing +> **Batch normalization** - - 모델이 Ground Truth를 정확하게 예측하지 않아도 되게 만들어 주어 정확하지 않은 학습 데이터셋에 치중되는 경향(overconfident)을 막아주는 방법 +활성화함수의 활성화값 또는 출력값을 정규화하는 방법이다. 각 hidden layer에서 정규화를 하면서 입력분포가 일정하게 되고, 이에 따라 Learning rate을 크게 설정해도 괜찮아진다. 결과적으로 학습속도가 빨라지는 효과가 있다. -- Dropout - - - 각 계층 마다 일정 비율의 뉴런을 임의로 정해 drop 시키고 나머지 뉴런만 학습하도록 하는 방법 - - 매 학습마다 drop 되는 뉴런이 달라지기 때문에 서로 다른 모델들을 앙상블 하는 것과 같은 효과가 있다. - - dropout은 **학습 시에만 적용**하고, 추론 시에는 적용하지 않는다. - -
- -
- -
- -- Batch normalization - - - 활성화함수의 활성화값 또는 출력값을 정규화하는 방법 - - 각 hidden layer에서 정규화를 하면서 입력분포가 일정하게 되고, 이에 따라 Learning rate을 크게 설정해도 괜찮아진다. 결과적으로 학습속도가 빨라지는 효과가 있다. - -
- -
- -
+![](./img/3-deep-learning/batch-normalization.png) #### References @@ -369,25 +300,20 @@ Generalization이 잘되도록 모델에 제약을 주며 학습을 하여 overf 하이퍼 파라미터(Hyper-parameter)는 모델링할 때, **사용자가 직접 세팅해주는 값**을 뜻한다. 하이퍼 파라미터는 정해진 최적의 값이 없으며, 사용자의 선험적 지식을 기반으로 설정(휴리스틱)한다. 예를들어 딥러닝의 하이퍼 파라미터에는 학습률, 배치 사이즈 등이 있고, 가중치는 학습 과정에서 바뀌는 값이며 이는 파라미터에 속한다. 하이퍼 파라미터 튜닝 기법에는 Manual Search, Grid Search, Random Search, Bayesian Optimization 등이 있다. 딥러닝에서의 하이퍼 파라미터는 아래의 그림을 참고한다. -
- -
- -
+![](./img/3-deep-learning/hyperparameter.png) -> **추가내용) 파라미터 vs. 하이퍼 파라미터** +> **파라미터 vs 하이퍼 파라미터** 파라미터와 하이퍼 파라미터를 구분하는 기준은 사용자가 직접 설정하느냐 아니냐이다. **사용자가 직접 설정하면 하이퍼 파라미터, 모델 혹은 데이터에 의해 결정되면 파라미터**이다. + 딥러닝에서 하이퍼 파라미터는 `학습률, 배치 크기, 은닉층의 개수` 등이 있고, 파라미터는 `가중치, 편향` 등이 있다. -
- -
+![](./img/3-deep-learning/parameter-vs-hyperparameter.png) -
+> **용어 정리** -> ✔︎ 선험적 지식: 경험하지 않아도 알 수 있는 것을 말한다. -> ✔︎ 휴리스틱: 체계적이면서 합리적인 판단이 굳이 필요하지 않은 상황에서 사람들이 빠르게 사용할 수 있도록, 보다 용이하게 구성된 간편추론의 방법이다. '대충 어림짐작하기', '눈대중으로 맞추기' 등의 방법을 일컫는다. +- 선험적 지식: 경험하지 않아도 알 수 있는 것을 말한다. +- 휴리스틱: 체계적이면서 합리적인 판단이 굳이 필요하지 않은 상황에서 사람들이 빠르게 사용할 수 있도록, 보다 용이하게 구성된 간편추론의 방법이다. '대충 어림짐작하기', '눈대중으로 맞추기' 등의 방법을 일컫는다. #### References @@ -402,59 +328,56 @@ Generalization이 잘되도록 모델에 제약을 주며 학습을 하여 overf 딥러닝에서 가중치를 잘 초기화하는 것은 기울기 소실이나 local minima 등의 문제를 야기할 수 있기 때문에 중요하다. -**LeCun Initialization** +> **LeCun Initialization** + 딥러닝의 대가 LeCun 교수님이 제시한 초기화 방법으로 들어오는 노드 수에 대해 정규 분포와 균등 분포를 따르는 방법이 있다. -정규 분포를 따르는 방법 +- **정규 분포를 따르는 방법** -
- -
-
+$$ +W \sim N(0, Var(W)), \quad Var(W) = \sqrt{\frac{1}{n_{in}}} +$$ -균등 분포를 따르는 방법 +- **균등 분포를 따르는 방법** -
- -
-
+$$ +W \sim U(- \sqrt{\frac{1}{n_{in}}}, + \sqrt{\frac{1}{n_{in}}}) +$$ + +> **Xavier Initialization** -**Xavier Initialization** LeCun 방법과 비슷하지만 들어오는 노드 수와 나가는 노드 수에 의존하고, 적절한 상수값도 발견하여 사용한 방법이다. -정규 분포를 따르는 방법 +- **정규 분포를 따르는 방법** -
- -
-
+$$ +W \sim N(0, Var(W)), \quad Var(W) = \sqrt{\frac{2}{n_{in} + n_{out}}} +$$ -균등 분포를 따르는 방법 +- **균등 분포를 따르는 방법** -
- -
-
+$$ +W \sim U(- \sqrt{\frac{6}{n_{in} + n_{out}}}, + \sqrt{\frac{6}{n_{in} + n_{out}}}) +$$ sigmoid 나 tanh 함수와는 좋은 결과를 보여주지만 ReLU 함수와 사용할 경우 0에 수렴하는 문제가 발생한다. 따라서 `sigmoid` 나 `tanh` 함수와 주로 많이 사용한다. -**He Initialization** +> **He Initialization** + `ReLU` 와 함께 많이 사용되는 방법으로, LeCun 방법과 같지만 상수를 다르게 하였다. 들어오는 노드만 고려한다. -정규 분포를 따르는 방법 +- **정규 분포를 따르는 방법** -
- -
-
+$$ +W \sim N(0, Var(W)), \quad Var(W) = \sqrt{\frac{2}{n_{in}}} +$$ -균등 분포를 따르는 방법 +- **균등 분포를 따르는 방법** -
- -
-
+$$ +W \sim U(- \sqrt{\frac{6}{n_{in}}}, + \sqrt{\frac{6}{n_{in}}}) +$$ #### References @@ -474,17 +397,16 @@ sigmoid 나 tanh 함수와는 좋은 결과를 보여주지만 ReLU 함수와 특히 DBN(Deep Belief Network)에서는 RBM들을 쌓아올려, 각 볼츠만 머신을 순차적으로 학습시킨다. +![](./img/3-deep-learning/boltzmann-machine.png) +
- +

색깔 별 cell의 역할은 아래와 같다. -
- -
-
+![](./img/3-deep-learning/boltzmann-machine-cell.png) #### References @@ -503,20 +425,17 @@ sigmoid 나 tanh 함수와는 좋은 결과를 보여주지만 ReLU 함수와 추가적으로 딥러닝 디버깅 툴은 아니지만, logging tool로서 tensorboard, wandb 등이 매우 유용하게 사용될 수 있다. -#### References - --- ## #11 #### 뉴럴넷의 가장 큰 단점은 무엇인가? 이를 위해 나온 One-Shot Learning은 무엇인가? -사람은 처음 보는 물건 (새 레이블) 에 대해 조금만 봐도 다른 것과 이 물건을 구분해낼 수 있다. -하지만 뉴럴넷은 이 물건을 구분해내기 위해서는 이 물건에 대한 많은 데이터를 학습해야한다. +사람은 처음 보는 물건 (새 레이블) 에 대해 조금만 봐도 다른 것과 이 물건을 구분해낼 수 있다. 하지만 뉴럴넷은 이 물건을 구분해내기 위해서는 이 물건에 대한 많은 데이터를 학습해야한다. -`One-shot Learning` 은 뉴럴넷도 새로운 레이블을 지닌 데이터가 적을 때 (one-shot 에서는 한 개) 에도 모델이 좋은 성능을 내도록 사용되는 방법이다. +**One-shot Learning** 은 뉴럴넷도 새로운 레이블을 지닌 데이터가 적을 때 (one-shot 에서는 한 개) 에도 모델이 좋은 성능을 내도록 사용되는 방법이다. -이를 위해서는 기존에 다른 레이블의 많은 데이터를 학습하여 데이터의 특성을 잘 이해하는 `pretrained` 모델이 필요하다. +이를 위해서는 기존에 다른 레이블의 많은 데이터를 학습하여 데이터의 특성을 잘 이해하는 **pretrained** 모델이 필요하다. 학습된 모델에 새로운 레이블의 데이터 하나 던져 주면 모델은 데이터의 특성에 대한 이해를 바탕으로 이 레이블에 대해서도 이해를 하게 된다. @@ -531,11 +450,7 @@ sigmoid 나 tanh 함수와는 좋은 결과를 보여주지만 ReLU 함수와 #### 요즘 sigmoid 보다 ReLU를 많이 쓰는데 그 이유는? -
- -
- -
+![](./img/3-deep-learning/activation-function.png) 우선 sigmoid와 ReLU 함수의 모양을 보자. sigmoid는 값이 큰 양수일수록 1에, 큰 음수일수록 0에 가까워진다. 반면 ReLU는 값이 양수이면 원래 값을 그대로 가져가고, 음수이면 0이다. @@ -555,14 +470,14 @@ sigmoid 나 tanh 함수와는 좋은 결과를 보여주지만 ReLU 함수와 #### Non-Linearity라는 말의 의미와 그 필요성은? -비선형(non-linearity)의 뜻을 알기 위해서는 우선 선형(linearity)가 무엇인지 알아야 한다. 어떤 모델이 선형적(linearity)라고 한다면 그 모델은 변수 과 가중치 으로 으로 표현할 수 있으며, 가산성(Additreivityly)과 동차성(Homogeneity)을 만족해야 한다. +비선형(non-linearity)의 뜻을 알기 위해서는 우선 선형(linearity)가 무엇인지 알아야 한다. 어떤 모델이 선형적(linearity)라고 한다면 그 모델은 변수 $x_1, x_2, ... , x_n$과 가중치 $w_1, w_2, ... , w_n$으로 $y = w_1 * x_1 + w_2 * x_2 + ... + w_n * x_n$으로 표현할 수 있으며, 가산성(Additreivityly)과 동차성(Homogeneity)을 만족해야 한다. -- **가산성**: 임의의 수 에 대해 가 성립 -- **동차성**: 임의의 수 $x, \alpha$에 대해 가 성립 +- **가산성**: 임의의 수 $x, y$에 대해 $f(x+y) = f(x) + f(y)$가 성립 +- **동차성**: 임의의 수 $x, \alpha$에 대해 $f(\alpha x) = \alpha f(x)$가 성립 이를 만족하지 못하는 모델을 비선형 관계에 있는 모델이라고 한다. -딥러닝에서 이런 비선형 관계는 활성화 함수(activation function)을 도입함으로써 표현할 수 있다. 그럼 비선형 관계 즉, 활성화 함수가 왜 필요할까? 바로 **활성화 함수를 사용해 여러 층을 쌓아서 더 복잡한 표현을 하기 위해서**이다. 활성화 함수가 인 선형 함수라고 생각해보자. 이 때 개의 층을 쌓았다고 할 때, 모델은 로 나타낼 수 있다. 라는 상수로 치환하면 결국 1층을 가진 신경망과 동일하다. 그렇기 때문에 비선형인 활성화 함수가 필요한 것이다. +딥러닝에서 이런 비선형 관계는 활성화 함수(activation function)을 도입함으로써 표현할 수 있다. 그럼 비선형 관계 즉, 활성화 함수가 왜 필요할까? 바로 **활성화 함수를 사용해 여러 층을 쌓아서 더 복잡한 표현을 하기 위해서**이다. 활성화 함수가 $h(x) = cx$인 선형 함수라고 생각해보자. 이 때 $n$개의 층을 쌓았다고 할 때, 모델은 $y = h^n(x) = c^nx$로 나타낼 수 있다. $c^n=k$라는 상수로 치환하면 결국 1층을 가진 신경망과 동일하다. 그렇기 때문에 비선형인 활성화 함수가 필요한 것이다. #### References @@ -577,11 +492,7 @@ sigmoid 나 tanh 함수와는 좋은 결과를 보여주지만 ReLU 함수와 ReLU는 양수일 때 인 선형 함수와 음수일 때 인 선형 함수 두 개를 결합된 형태이다. 그렇지만 ReLU는 선형 함수가 갖는 가산성을 만족하지 못하기 때문에 비선형 함수로 볼 수 있다. 하지만 ReLU가 어떻게 곡선 함수를 근사할 수 있을까? -
- -
- -
+![](./img/3-deep-learning/relu-approximate.png) ReLU를 여러 개 결합하면, 특정 지점에서 특정 각도만큼 선형 함수를 구부릴 수 있다. 이 성질을 이용하여 곡선 함수 뿐만 아니라 모든 함수에 근사를 할 수 있게 된다. @@ -602,11 +513,7 @@ ReLU의 가장 큰 문제점은 바로 죽은 뉴런(Dead Neurons)편향 이동(Bias Shift)이다. ReLU는 항상 0이상의 값을 출력하기 때문에 활성화값의 평균이 0보다 커 zero-centered하지 않다. 활성화값이 zero-centered되지 않으면 가중치 업데이트가 동일한 방향으로만 업데이트가 돼서 학습 속도가 느려질 수가 있다. 관련 내용은 [CS231n 6강 8:46](https://youtu.be/wEoyxE0GP2M?t=526)을 참고! -
- -
- -
+![](./img/3-deep-learning/selu-elu.png) 이를 해결하기 위해 배치 정규화(Batch Normalization)을 사용하거나 zero-centered된 ELU, SeLU와 같은 활성화 함수를 사용한다. @@ -625,13 +532,7 @@ ReLU의 가장 큰 문제점은 바로 죽은 뉴런(Dead Neurons) - -
-bias별 sigmoid 함수의 위치 - - -
+![bias별 sigmoid 함수의 위치](./img/3-deep-learning/bias-example.png) 편향(bias)는 활성화 함수가 왼쪽 혹은 오른쪽으로 이동한다. 가중치(weight)는 활성화 함수의 가파른 정도 즉, 기울기를 조절하는 반면, 편향(bias)는 **활성화 함수를 움직임으로써 데이터에 더 잘 맞도록 한다.** @@ -648,42 +549,27 @@ ReLU의 가장 큰 문제점은 바로 죽은 뉴런(Dead Neurons) - - -
+![](./img/3-deep-learning/how-to-gradient-descent.png) 딥러닝에서는 Loss function을 최소화시키기 위해 파라미터에 대해 Loss function을 미분하여 그 기울기값(gradient)을 구하고, 경사가 하강하는 방향으로 파라미터 값을 점진적으로 찾기위해 사용된다. Gradient Descent를 수식으로 표현하면 아래와 같다. -
- -
-
+$$ +W_{t+1} \leftarrow W_t - \eta g_t +$$ -**Gradient Descent의 문제점** +Gradient Descent의 문제점으로는 크게 두 가지가 있다. -- 적절한 step size(learning rate) +첫 번째로 적절한 step size(learning rate)가 필요하다. step size가 큰 경우 한 번 이동하는 거리가 커지므로 빠르게 수렴할 수 있다는 장점이 있다. 하지만, step size를 너무 크게 설정해버리면 최소값을 계산하도록 수렴하지 못하고 함수 값이 계속 커지는 방향으로 최적화가 진행될 수 있다. - - step size가 큰 경우 한 번 이동하는 거리가 커지므로 빠르게 수렴할 수 있다는 장점이 있다. 하지만, step size를 너무 크게 설정해버리면 최소값을 계산하도록 수렴하지 못하고 함수 값이 계속 커지는 방향으로 최적화가 진행될 수 있다. - - 한편 step size가 너무 작은 경우 발산하지는 않을 수 있지만 최적의 x를 구하는데 소요되는 시간이 오래 걸린다는 단점이 있다. +한편 step size가 너무 작은 경우 발산하지는 않을 수 있지만 최적의 x를 구하는데 소요되는 시간이 오래 걸린다는 단점이 있다. -
- -
-
- -- local minima 문제 +![](./img/3-deep-learning/step-size-problem.png) - - gradient descent 알고리즘을 시작하는 위치는 매번 랜덤하기 때문에 어떤 경우에는 local minima에 빠져 계속 헤어나오지 못하는 경우도 생긴다. - -
- -
-
+두 번째로 **local minima 문제**이다. gradient descent 알고리즘을 시작하는 위치는 매번 랜덤하기 때문에 어떤 경우에는 local minima에 빠져 계속 헤어나오지 못하는 경우도 생긴다. (자세한 내용은 [#14-1. GD가 Local Minima 문제를 피하는 방법은?](#14-1) 참고) -> 자세한 내용은 [#14-1. GD가 Local Minima 문제를 피하는 방법은?](#14-1) 참고 +![](./img/3-deep-learning/local-minima-problem.png) #### References @@ -696,10 +582,7 @@ Gradient Descent를 수식으로 표현하면 아래와 같다. #### 왜 꼭 Gradient를 써야 할까? 그 그래프에서 가로축과 세로축 각각은 무엇인가? 실제 상황에서는 그 그래프가 어떻게 그려질까? -
- -
-
+![](./img/3-deep-learning/cost-gradient.jpeg) Gradient가 양수이면 올라가는 방향이며 음수이면 내려가는 방향이다. 실제 상황에서는 Gradient 그래프가 0을 중심으로 진동하는 모양이 될 것이다. @@ -713,18 +596,13 @@ Gradient가 양수이면 올라가는 방향이며 음수이면 내려가는 방 #### GD 중에 때때로 Loss가 증가하는 이유는? -
- -
-
- -minima에 들어갔다가 나오는 경우일 것이다. +![](./img/3-deep-learning/cost-gradient-optima.jpeg) -실제로 사용되는 GD에서는 local minima 문제를 피하기 위해 Momentum 등의 개념을 도입한 RMSprop, Adam 등의 optimization 전략을 사용한다. +minima에 들어갔다가 나오는 경우일 것이다. 실제로 사용되는 GD에서는 local minima 문제를 피하기 위해 Momentum 등의 개념을 도입한 RMSprop, Adam 등의 optimization 전략을 사용한다. 각 optimization 전략에 따라 gradient가 양수인 방향으로도 parameter update step을 가져가는 경우가 생길 수 있으며, 이 경우에는 Loss가 일시적으로 증가할 수 있다. -> 자세한 내용은 [#17. SGD, RMSprop, Adam에 대해서 아는대로 설명한다면?](#17) 참고 +(자세한 내용은 [#17. SGD, RMSprop, Adam에 대해서 아는대로 설명한다면?](#17) 참고) #### References @@ -740,14 +618,11 @@ minima에 들어갔다가 나오는 경우일 것이다. 이렇게 거꾸로 전파시켜서 최종적으로 출력층에서의 output값에 대한 입력층에서의 input data의 기울기 값을 구할 수 있다. -이 과정에서 `chain rule`이 이용된다. +이 과정에서 **chain rule**이 이용된다. 출력층 바로 전 layer에서부터 기울기(미분값)을 계산하고 이를 점점 거꾸로 전파시키면서 전 layer들에서의 기울기와 서로 곱하는 형식으로 나아가면 최종적으로 출력층의 output에 대한 입력층에서의 input의 기울기(미분값)을 구할 수가 있다. 이를 그림으로 나타내면 아래와 같다. -
- -
-
+![](./img/3-deep-learning/backpropagation.png) 역전파 알고리즘이 해결한 문제가 바로 파라미터가 매우 많고 layer가 여러개 있을때 가중치w와 b를 학습시키기 어려웠다는 문제이다. @@ -770,26 +645,11 @@ local minima 문제가 사실은 고차원(High Dimensional)의 공간에서는 고차원의 공간에서 모든 축의 방향으로 오목한 형태가 형성될 확률은 거의 0에 가깝다. 따라서, 고차원의 공간에서 대부분의 critical point는 local minima가 아니라 saddle point다. 그리고, 고차원의 공간에서 설령 local minima가 발생한다 하더라도 이는 global minimum이거나 또는 global minimum과 거의 유사한 수준의 에러 값을 갖는다. 왜냐하면, critical point에 포함된 위로 볼록인 방향 축의 비율이 크면 클수록 높은 에러를 가지기 때문이다.(실험적 결과) local minima는 위로 볼록인 경우가 하나도 없는 경우이기 때문에 결과적으로 매우 낮은 에러를 갖게 될 것이다. -
- -
-
- -> **추가자료) Local minima** - -Local minima 문제는 에러를 최소화시키는 최적의 파라미터를 찾는 문제에 있어서 아래 그림처럼 파라미터 공간에 수많은 지역적인 홀(hole)들이 존재하여 이러한 local minima에 빠질 경우 전역적인 해(global minimum)를 찾기 힘들게 되는 문제를 일컫는다. - -
- -
-
+![](./img/3-deep-learning/saddle-point.png) -> **Critical point, Saddle point, Local minima** +> **Critical point, Saddle point, Local minimum** -
- -
-
+![](./img/3-deep-learning/critical-saddle-point-and-local-minima.png) - `critical point`: 일차 미분이 0인 지점이다. (local/global)minima, (local/global)maxima, saddle point를 가리킴 - `local minimum`: 모든 방향에서 극소값을 만족하는 점 @@ -814,41 +674,20 @@ Local minima 문제를 피하는 방법으로는 **Momentum, Nesterov Accelerate **Momentum**이란 관성을 의미하며, 이전 gradient의 방향성을 담고있는 `momentum` 인자를 통해 흐르던 방향을 어느 정도 유지시켜 local minima에 빠지지 않게 만든다. 즉, 관성을 이용하여, 학습 속도를 더 빠르게 하고, 변곡점을 잘 넘어갈 수 있도록 해주는 역할을 수행한다. -
- -
-
+![](./img/3-deep-learning/momentum.png) -**Nesterov Accelerated Gradient(NAG)** 는 모멘텀과 비슷한 역할을 수행하는 `Look-ahead gradient `인자를 포함하여, 라는 `accumulate gradient`가 gradient를 감소시키는 역할을 한다. 모멘텀과 다른 점은, 미리 한 스텝을 옮겨가본 후에 어느 방향으로 갈지 정한다는 것이다. +**Nesterov Accelerated Gradient(NAG)** 는 모멘텀과 비슷한 역할을 수행하는 `Look-ahead gradient `인자를 포함하여, $a$ 라는 `accumulate gradient`가 gradient를 감소시키는 역할을 한다. 모멘텀과 다른 점은, 미리 한 스텝을 옮겨가본 후에 어느 방향으로 갈지 정한다는 것이다. -
- -
-
+**Adagrad**란 뉴럴넷의 파라미터가 많이 바뀌었는지 적게 바뀌었는지 확인하고, 적게 변한건 더 크게 변하게 하고, 크게 변한건 더 작게 변화시키는 방법이다. Adagrad는 `sum of gradient squares`($G_t$)를 사용하는데, 이는 그래디언트가 얼만큼 변했는지를 제곱해서 더하는 것이므로 계속 커진다는 문제가 발생한다. $G_t$가 계속 커지면 분모가 점점 무한대에 가까워지게 되어, $W$ 업데이트가 되지 않게 되어, 뒤로 갈수록 학습이 점점 안되는 문제점이 발생한다. -- **Momentum vs. NAG** +![](./img/3-deep-learning/adagrad.png) -
- -
-
- -**Adagrad**란 뉴럴넷의 파라미터가 많이 바뀌었는지 적게 바뀌었는지 확인하고, 적게 변한건 더 크게 변하게 하고, 크게 변한건 더 작게 변화시키는 방법이다. Adagrad는 `sum of gradient squares`( )를 사용하는데, 이는 그래디언트가 얼만큼 변했는지를 제곱해서 더하는 것이므로 계속 커진다는 문제가 발생한다. 가 계속 커지면 분모가 점점 무한대에 가까워지게 되어, 업데이트가 되지 않게 되어, 뒤로 갈수록 학습이 점점 안되는 문제점이 발생한다. - -
- -
-
+**Adadelta**는 `Exponential Moving Average(EMA)`를 사용하여, Adagrad의 $G_t$가 계속 커지는 현상을 막을 수 있다. EMA는 현재 타임스텝으로부터 `윈도우 사이즈만큼의 파라미터 변화(그래디언트 제곱의 변화)를 반영`하는 역할을 하는데, 이전의 값을 모두 저장하는 것이 아닌, `이전 변화량에 특정 비율을 곱해 더한 인자`를 따로 두는 방식이다. Adadelta는 learning rate가 없다. -**Adadelta**는 `Exponential Moving Average(EMA)`를 사용하여, Adagrad의 가 계속 커지는 현상을 막을 수 있다. EMA는 현재 타임스텝으로부터 `윈도우 사이즈만큼의 파라미터 변화(그래디언트 제곱의 변화)를 반영`하는 역할을 하는데, 이전의 값을 모두 저장하는 것이 아닌, `이전 변화량에 특정 비율을 곱해 더한 인자`를 따로 두는 방식이다. Adadelta는 learning rate가 없다. +![](./img/3-deep-learning/adadelta.png) -
- -
-
- -> **Momentum**의 더 자세한 내용은 [모멘텀의 수식을 적어 본다면?](#17-3) 참고 -> **SGD, RMSprop, Adam**에 대한 설명은 [SGD, RMSprop, Adam에 대해서 아는대로 설명한다면?](#17) 참고 +(**Momentum**의 더 자세한 내용은 [모멘텀의 수식을 적어 본다면?](#17-3) 참고) +(**SGD, RMSprop, Adam**에 대한 설명은 [SGD, RMSprop, Adam에 대해서 아는대로 설명한다면?](#17) 참고) #### References @@ -861,7 +700,7 @@ Local minima 문제를 피하는 방법으로는 **Momentum, Nesterov Accelerate #### 찾은 해가 Global Minimum인지 아닌지 알 수 있는 방법은? -Gradient Descent 방식에서 lacal minima에 도달함은 증명되어있으나, global minima에 도달하는 것은 보장되지 않았다. 또한, 현재 지점이 global minima인지도 알 수 없다. 딥러닝에서 다루는 문제가 convexity를 만족하지 않기 때문이다. 대신, local minima를 찾는다면, 그 지점이 곧 global minima일 가능성이 크다. [Local Minima 문제에도 불구하고 딥러닝이 잘 되는 이유는?](#14)에서 언급했듯, saddle point가 아닌 완전한 local minimum이 발생하는 경우는 희귀하다. 따라서 모든 방향에서 아래로 볼록인 local minima를 발견한다면, 그 지점이 바로 global minima일 가능성이 높다. +Gradient Descent 방식에서 local minima에 도달함은 증명되어있으나, global minima에 도달하는 것은 보장되지 않았다. 또한, 현재 지점이 global minima인지도 알 수 없다. 딥러닝에서 다루는 문제가 convexity를 만족하지 않기 때문이다. 대신, local minima를 찾는다면, 그 지점이 곧 global minima일 가능성이 크다. [Local Minima 문제에도 불구하고 딥러닝이 잘 되는 이유는?](#14)에서 언급했듯, saddle point가 아닌 완전한 local minimum이 발생하는 경우는 희귀하다. 따라서 모든 방향에서 아래로 볼록인 local minima를 발견한다면, 그 지점이 바로 global minima일 가능성이 높다. #### References @@ -874,8 +713,7 @@ Gradient Descent 방식에서 lacal minima에 도달함은 증명되어있으나 #### Training 세트와 Test 세트를 분리하는 이유는? -모델은 데이터에 대해 예측값을 만들고 정답과 비교하며 업데이트되면서 학습이 된다. -그런데 학습 데이터에 대해서는 좋은 성능을 낸다 하더라도 본 적 없는 데이터에 대해서는 잘 대응하지 못하는 **오버피팅** 문제가 생긴다면 좋은 모델이 아니다. +모델은 데이터에 대해 예측값을 만들고 정답과 비교하며 업데이트되면서 학습이 된다. 그런데 학습 데이터에 대해서는 좋은 성능을 낸다 하더라도 본 적 없는 데이터에 대해서는 잘 대응하지 못하는 **오버피팅** 문제가 생긴다면 좋은 모델이 아니다. 이를 막기 위해 학습된 모델이 처음 보는 데이터에도 강건하게 성능을 내는지 판단하기 위한 수단으로 test 세트를 따로 만든다. @@ -921,9 +759,13 @@ test 데이터는 한 번도 학습에서 본 적 없는 데이터여야 한다. #### Regularization이란 무엇인가? -모델의 오버피팅을 막고 처음 보는 데이터에도 잘 예측하도록 만드는 방법을 Regularization(일반화)라고 한다. +모델의 오버피팅을 막고 처음 보는 데이터에도 잘 예측하도록 만드는 방법을 Regularization(일반화)라고 한다. + +대표적인 방법으로 [Dropout](https://github.com/boostcamp-ai-tech-4/ai-tech-interview/blob/main/answers/3-deep-learning.md#16-1), [L1, L2 Regularization](https://github.com/boostcamp-ai-tech-4/ai-tech-interview/blob/main/answers/2-machine-learning.md#21) 등이 존재한다. + +#### References -대표적인 방법으로 dropout, [L1-L2 Regularization](https://github.com/boostcamp-ai-tech-4/ai-tech-interview/blob/main/answers/machine-learning.md#21) 등이 있다. [6번 참고](#6) +- [L1 and L2 regularization for Deep Learning - Ujwal Tewari's Medium](https://medium.com/analytics-vidhya/regularization-understanding-l1-and-l2-regularization-for-deep-learning-a7b9e4a409bf) --- @@ -931,15 +773,9 @@ test 데이터는 한 번도 학습에서 본 적 없는 데이터여야 한다. #### Batch Normalization의 효과는? -
- -
-배치 정규화(Batch Normalization) 수식 -
- -
+![배치 정규화(Batch Normalization) 수식](./img/3-deep-learning/batch-normalization-formula.png) -배치 정규화(Batch Normalization)은 학습 시 **미니배치 단위로 입력의 분포가 평균이 0, 분산이 1이 되도록 정규화**한다. 더불어 로 스케일과 로 이동 변환을 수행한다. 이렇게 배치 정규화를 사용하면 다음과 같은 효과를 얻을 수 있다. +배치 정규화(Batch Normalization)은 학습 시 **미니배치 단위로 입력의 분포가 평균이 0, 분산이 1이 되도록 정규화**한다. 더불어 $\gamma$로 스케일과 $\beta$로 이동 변환을 수행한다. 이렇게 배치 정규화를 사용하면 다음과 같은 효과를 얻을 수 있다. - `장점 1` 기울기 소실/폭발 문제가 해결되어 큰 학습률을 설정할 수 있어 학습속도가 빨라진다. - `장점 2` 항상 입력을 정규화시키기 때문에 가중치 초깃값에 크게 의존하지 않아도 된다. @@ -958,15 +794,9 @@ test 데이터는 한 번도 학습에서 본 적 없는 데이터여야 한다. #### Dropout의 효과는? -
- -
-Deep Learning for Computer Vision -
- -
+![](./img/3-deep-learning/dropout-nn.png) -드롭아웃(Dropout)은 **설정된 확률 만큼 은닉층(hidden layer)에 있는 뉴런을 무작위로 제거하는 방법**으로, 오버피팅을 방지하기 위한 방법 중 하나이다. (정확히는 출력을 0으로 만들어 더이상의 전파가 되지 않도록 한다.) 드롭아웃(Dropout)은 학습 때마다 무작위로 뉴런을 제거하므로 매번 다른 모델을 학습시키는 것으로 해석할 수 있다. 그리고 추론 시 출력에 제거 확률 를 곱함으로써 앙상블 학습에서 여러 모델의 평균을 내는 효과를 얻을 수 있다. +드롭아웃(Dropout)은 설정된 확률 $p$만큼 은닉층(hidden layer)에 있는 뉴런을 무작위로 제거하는 방법으로, 오버피팅을 방지하기 위한 방법 중 하나이다. (정확히는 출력을 0으로 만들어 더이상의 전파가 되지 않도록 한다.) 드롭아웃(Dropout)은 학습 때마다 무작위로 뉴런을 제거하므로 매번 다른 모델을 학습시키는 것으로 해석할 수 있다. 그리고 추론 시 출력에 제거 확률 $p$를 곱함으로써 앙상블 학습에서 여러 모델의 평균을 내는 효과를 얻을 수 있다. #### References @@ -1003,15 +833,11 @@ test 데이터는 한 번도 학습에서 본 적 없는 데이터여야 한다. #### SGD, RMSprop, Adam에 대해서 아는대로 설명한다면? -> SGD - -Loss Function을 계산할 때 전체 train set을 사용하는 것을 Batch Gradient Descent 라고 한다. +> **SGD** -그러나 이렇게 계산을 할 경우 한번 step을 내딛을 때 전체 데이터에 대해 Loss Function을 계산해야 하므로 너무 많은 계산량이 필요하다. +Loss Function을 계산할 때 전체 train set을 사용하는 것을 Batch Gradient Descent 라고 한다. 그러나 이렇게 계산을 할 경우 한번 step을 내딛을 때 전체 데이터에 대해 Loss Function을 계산해야 하므로 너무 많은 계산량이 필요하다. -이를 방지하기 위해 보통은 Stochastic Gradient Descent(SGD)라는 방법을 사용한다. - -이 방법에서는 loss function을 계산할 때 전체 데이터(batch) 대신 데이터 한 개 또는 일부 조그마한 데이터의 모음(mini-batch)에 대해서만 loss function을 계산한다. +이를 방지하기 위해 보통은 Stochastic Gradient Descent(SGD)라는 방법을 사용한다. 이 방법에서는 loss function을 계산할 때 전체 데이터(batch) 대신 데이터 한 개 또는 일부 조그마한 데이터의 모음(mini-batch)에 대해서만 loss function을 계산한다. **데이터 한 개**를 사용하는 경우를 Stochastic Gradient Descent(SGD), 데이터의 일부(mini-batch)를 사용하는 경우를 mini-batch Stochastic Gradient Descent(mini-batch SGD)라고 하지만 **오늘날의 딥러닝에서 일반적으로 통용되는 SGD는 mini-batch SGD이다.** @@ -1019,45 +845,33 @@ Loss Function을 계산할 때 전체 train set을 사용하는 것을 Batch Gra 또한, SGD를 사용할 경우 Batch Gradient Descent에서 빠질 local minima에 빠지지 않고 더 좋은 방향으로 수렴할 가능성도 있다. -> RMSprop +> **RMSprop** RMSProp은 딥러닝의 대가 제프리 힌톤이 제안한 방법으로서, Adagrad의 단점을 해결하기 위한 방법이다. -Adagrad의 식에서 gradient의 제곱값을 더해나가면서 구한 부분을 합이 아니라 지수평균으로 바꾸어서 대체한 방법이다. +Adagrad의 식에서 gradient의 제곱값을 더해나가면서 구한 $G_t$부분을 합이 아니라 지수평균으로 바꾸어서 대체한 방법이다. -이렇게 대체를 할 경우 Adagrad처럼 가 무한정 커지지는 않으면서 최근 변화량의 변수간 상대적인 크기 차이는 유지할 수 있다. +이렇게 대체를 할 경우 Adagrad처럼 $G_t$가 무한정 커지지는 않으면서 최근 변화량의 변수간 상대적인 크기 차이는 유지할 수 있다. 식으로 나타내면 다음과 같다. -
- -
- -
+![](./img/3-deep-learning/rmsprop.png) -> Adam +> **Adam** Adam(Adaptive Moment Estimation)은 RMSProp과 Momentum 방식을 합친 것 같은 알고리즘이다. 이 방식에서는 Momentum 방식과 유사하게 지금까지 계산해온 기울기의 지수평균을 저장하며, RMSProp과 유사하게 기울기의 제곱값의 지수평균을 저장한다. -
- -
- -
- -다만, Adam에서는 m과 v가 처음에 0으로 초기화되어 있기 때문에 학습의 초반부에서는 가 0에 가깝게 bias 되어있을 것이라고 판단하여 이를 unbiased 하게 만들어주는 작업을 거친다. +![](./img/3-deep-learning/adam.png) - 의 식을 ∑ 형태로 펼친 후 양변에 expectation을 씌워서 정리해보면, 다음과 같은 보정을 통해 unbiased 된 expectation을 얻을 수 있다. +다만, Adam에서는 m과 v가 처음에 0으로 초기화되어 있기 때문에 학습의 초반부에서는 $m_t, v_t$가 0에 가깝게 bias 되어있을 것이라고 판단하여 이를 unbiased 하게 만들어주는 작업을 거친다. -이 보정된 expectation들을 가지고 gradient가 들어갈 자리에 가 들어갈 자리에 를 넣어 계산을 진행한다. +$m_t, v_t$의 식을 ∑ 형태로 펼친 후 양변에 expectation을 씌워서 정리해보면, 다음과 같은 보정을 통해 unbiased 된 expectation을 얻을 수 있다. -
- -
+이 보정된 expectation들을 가지고 gradient가 들어갈 자리에 $\widehat{m_t}, G_t$가 들어갈 자리에 $\widehat{v_t}$를 넣어 계산을 진행한다. -
+![](./img/3-deep-learning/adam-conclusion.png) #### References @@ -1084,15 +898,16 @@ SGD는 Loss Function을 계산할 때 전체 train dataset을 사용하는 Batch #### 미니배치를 작게 할때의 장단점은? -- 장점 +> **장점** + +- 한 iteration의 계산량이 적어지기 때문에 step 당 속도가 빨라진다. +- 적은 Graphic Ram으로도 학습이 가능하다. - - 한 iteration의 계산량이 적어지기 때문에 step 당 속도가 빨라진다. - - 적은 Graphic Ram으로도 학습이 가능하다. +> **단점** -- 단점 - - 데이터 전체의 경향을 반영하기 힘들다. 업데이트를 항상 좋은 방향으로 하지만은 않는다. +- 데이터 전체의 경향을 반영하기 힘들다. 업데이트를 항상 좋은 방향으로 하지만은 않는다. -> batch size에 관련된 논문은 [Batch Size in Deep Learning - hyeonseob](https://blog.lunit.io/2018/08/03/batch-size-in-deep-learning/) 참고 +(batch size에 관련된 논문은 [Batch Size in Deep Learning - hyeonseob](https://blog.lunit.io/2018/08/03/batch-size-in-deep-learning/) 참고) #### References @@ -1108,24 +923,15 @@ Momentum 방식은 말 그대로 Gradient Descent를 통해 이동하는 과정 현재 Gradient를 통해 이동하는 방향과는 별개로, 과거에 이동했던 방식을 기억하면서 그 방향으로 일정 정도를 추가적으로 이동하는 방식이다. - : time step t에서의 이동 벡터 -
- - +$$ - - - - - - -
+$$ -이 때, 는 얼마나 momentum을 줄 것인지에 대한 momentum term이다. +이 때, $v_t$는 time step t에서의 이동 벡터이며, $\gamma$는 얼마나 momentum을 줄 것인지에 대한 momentum term이다. #### References diff --git a/answers/4-python.md b/answers/4-python.md index ce98191..9c55e7e 100644 --- a/answers/4-python.md +++ b/answers/4-python.md @@ -1,8 +1,4 @@ -
-

🐍 Python Programming Language 🐍

-
- -> 질문은 [Top 100 Python Interview Questions You Must Prepare In 2021 - edureka!](https://www.edureka.co/blog/interview-questions/python-interview-questions/)을 참고하였으며, 질문에 대한 답변 중 일부는 위의 사이트의 답변을 참고하여 작성되었습니다. +> **질문은 [Top 100 Python Interview Questions You Must Prepare In 2021 - edureka!](https://www.edureka.co/blog/interview-questions/python-interview-questions/)을 참고하였습니다.** ## Table of Contents @@ -133,8 +129,8 @@ 파이썬은 정확하게는, 스크립트 언어이다. 모든 스크립트 언어는 프로그래밍 언어로 볼 수 있으나, 모든 프로그래밍 언어가 스크립트 언어로 분류되는 것은 아니다. 따라서 파이썬은 스크립트 언어이자, 프로그래밍 언어이다. 그러나 사람들은 일반적인 경우에 파이썬을 프로그래밍 언어의 목적으로 분류하고, 프로그래밍 목적으로 많이 사용한다. -- 스크립팅(scripting/Scripting Language) - - 스크립트 언어란 컴파일이 필요없이 실행될 수 있는 명령어의 집합이다. 스크립트 언어는 인터프리터를 사용하는데, 인터프리터는 컴파일 과정이 필요하지 않으며, 소스코드로 부터 바로 명령어를 해석할 수 있다. +> **💡 스크립팅(scripting/Scripting Language)** +> 스크립트 언어란 컴파일이 필요없이 실행될 수 있는 명령어의 집합이다. 스크립트 언어는 인터프리터를 사용하는데, 인터프리터는 컴파일 과정이 필요하지 않으며, 소스코드로 부터 바로 명령어를 해석할 수 있다. #### References @@ -148,8 +144,7 @@ 인터프리터는 고급 언어로 작성된 원시코드 명령어들을 한번에 한 줄씩 읽어들여서 실행하는 프로그램이다. 인터프리터 언어는 실행시간(runtime) 전에 기계 레벨 코드(machine-level code)를 만드는 컴파일 언어와 다르게 소스코드를 바로 실행하는 언어이며, 파이썬은 인터프리터 언어에 해당한다. -> 인터프리터 언어는 스크립트 언어와 동일한 의미이다. -> 스크립팅/스크립트 언어에 대한 질문과 답변은 [What type of language is python? Programming or scripting?](#3)을 참고한다. +인터프리터 언어는 스크립트 언어와 동일한 의미이다. 스크립팅/스크립트 언어에 대한 질문과 답변은 [What type of language is python? Programming or scripting?](#3)을 참고한다. #### References @@ -163,7 +158,7 @@ PEP(Python Enhancement Proposal)는 Python 코드를 포맷하는 방법을 지정하는 규칙 집합이다. 다른 사람과 원활하게 협업하려면 공통된 스타일 공유가 필요하며, 일관성 있는 스타일은 나중에 수정하기도 쉽다. PEP8은 파이썬 코드를 어떻게 구성할 지 알려주는 스타일 가이드로서의 역할을 한다. Python formatting tool에는 `black`, `flake8`, `autopep8`, `yamf` 등이 있다. -> PEP8 스타일 가이드 예시 +> **PEP8 스타일 가이드 예시** - whitespace - 한 줄의 문자 길이가 79자 이하여야 한다. @@ -185,7 +180,7 @@ PEP(Python Enhancement Proposal)는 Python 코드를 포맷하는 방법을 지 Python은 모든 것을 객체로 관리한다. 객체가 더이상 필요하지 않으면 파이썬 메모리 관리자가 자동으로 객체에서 메모리를 회수하는 방식을 사용하므로, 파이썬은 **동적 메모리 할당** 방식을 사용한다고 말할 수 있다. 힙(heap)은 동적할당을 구현하는데 사용된다. 힙을 사용하여 동적으로 메모리를 관리하면, 필요하지 않은 메모리를 비우고 재사용할 수 있다는 장점이 있다. 모든 파이썬 객체 또는 자료구조는 **python private heap** 공간에서 관리되며, 프로그래머는 이 공간에 접근할 수 없고, 대신 파이썬 인터프리터가 대신해서 관리한다. -> 더 자세히보기 +> **더 자세히보기** 파이썬 객체에 대한 힙 공간 할당을 담당하는 것을 **파이썬 메모리 관리자(Python Memory Manager)** 라고 부른다. Python 메모리 관리자에는 객체별 할당자가있기 때문에 int, string 등과 같은 특정 객체에 대해 메모리를 명확하게 할당 할 수 있다. 또한, 사용되지 않는 모든 메모리를 재활용하고 힙 공간에서 사용할 수 있도록 하는 **내장 Garbage Collector(GC)** 를 가지고 있다. @@ -204,23 +199,20 @@ namespace는 이름 지정 충돌(naming conflicts)을 피하기 위해 이름 네임스페이스가 필요한 이유는 다음과 같다. 프로그래밍을 수행하다보면 모든 변수 이름과 함수 이름을 정하는 것이 중요한데 이들 모두를 겹치지 않게 정하는 것은 사실상 불가능하다. 따라서 프로그래밍언어에서는 네임스페이스라는 개념을 도입하여, 특정한 하나의 이름이 통용될 수 있는 범위를 제한한다. 즉, **소속된 네임스페이스가 다르다면 같은 이름이 다른 개체를 가리키도록 하는 것이 가능**하다. -> 파이썬 네임스페이스의 특징 +> **파이썬 네임스페이스의 특징** - 네임스페이스는 딕셔너리 형태로 구현된다. - 모든 이름 자체는 문자열로 되어있고 각각은 해당 네임스페이스의 범위에서 실제 객체를 가리킨다. - 이름과 실제 객체 사이의 매핑은 가변적(Mutable)이므로 런타임동안 새로운 이름이 추가될 수 있다. - 빌트인 네임스페이스는 함부로 추가하거나 삭제할 수 없다. -> 파이썬 네임스페이스의 3가지 분류 +> **파이썬 네임스페이스의 3가지 분류** - `빌트인 네임스페이스(build-in namespace)`: 기본 내장 함수 및 기본 예외들의 이름들이 소속된다. 파이썬으로 작성된 모든 코드 범위가 포함된다. - `전역 네임스페이스(global namespace)`: 모듈별로 존재하며, 모듈 전체에서 통용될 수 있는 이름들이 소속된다. - `지역 네임스페이스(local namespace)`: 함수 및 메서드 별로 존재하며, 함수 내의 지역 변수들의 이름들이 소속된다. -
- -
-
+![](./img/4-python/namespace.png) #### References @@ -236,7 +228,7 @@ namespace는 이름 지정 충돌(naming conflicts)을 피하기 위해 이름 PYTHONPATH 환경 변수에 경로를 추가하면, 파이썬은 이 경로들을 `sys.path`에 추가한다. 이를 통해 파이썬 코드 내부에서 뿐만 아니라 파이썬 코드 밖에서도 `sys.path`를 조작할 수 있다. PYTHONPATH에는 `sys.path`에 추가할 여러 경로들이 들어간다. 리눅스에서는 `/foo:/bar`처럼 `:`로 두 경로를 구분하고, 윈도우에서는 `/foo;/bar`처럼 `;`로 두 경로를 구분한다. 이외에도 sys.path에는 파이썬에 포함된 여러 내장 모듈 등을 탐색하기 위한 기본 경로가 들어간다. -> 주의 `sys.path`의 순서 +> **`sys.path`의 순서** import는 `sys.path` 리스트에 들어있는 경로들을 탐색하며 불러올 파이썬 파일을 찾는다. 리스트에 들어있는 맨 처음 경로부터 탐색을 시작하여, 특정 경로에서 불러올 파일을 찾았다면 남은 경로를 더 찾아보지 않고 탐색을 중지한다. `sys.path`의 기본값은 아래의 순서대로 추가된다. @@ -245,7 +237,7 @@ import는 `sys.path` 리스트에 들어있는 경로들을 탐색하며 불러 - PYTHONPATH 환경 변수 - 기타 기본 경로 -> 아래의 코드를 통해서 `sys.path`를 직접 확인할 수 있다. +아래의 코드를 통해서 `sys.path`를 직접 확인할 수 있다. ```python import sys @@ -265,13 +257,14 @@ print(sys.path) 모듈이란 Python 코드를 포함하는 파일로써, 함수나 변수 또는 클래스를 모아 놓은 파일이다. 모듈은 다른 파이썬 프로그램에서 불러와 사용할 수 있게끔 만든 파이썬 파일이라고도 할 수 있다. 실행 가능한 코드를 포함하는, 파이썬 확장자 `.py`로 만든 파이썬 파일은 모두 모듈이다. 모듈을 사용하면, 다른 코드에 적용하기가 쉬워지므로 이식성이 좋아진다. -- 자주 사용되는 빌트인 모듈(built-in module)의 예시는 다음과 같다. - - `os` - - `sys` - - `math` - - `random` - - `datetime` - - `JSON` +자주 사용되는 빌트인 모듈(built-in module)의 예시는 다음과 같다. + +- `os` +- `sys` +- `math` +- `random` +- `datetime` +- `JSON` #### References @@ -283,10 +276,9 @@ print(sys.path) #### What are local variables and global variables in Python? -- **전역 변수(Global Variable)** : 함수 외부 또는 전역 공간에 선언된 변수를 전역 변수라고 한다. 프로그램의 모든 함수에서 전역변수에 접근할 수 있다. [Whenever Python exits, why isn’t all the memory de-allocated?](#35) 참고 -- **로컬 변수(Local Variable)** : 함수 내부에 선언된 변수를 로컬 변수라고 한다. 로컬 변수는 전역 공간이 아닌 로컬 공간에 있다. +**전역 변수(Global Variable)**는 함수 외부 또는 전역 공간에 선언된 변수이다. 프로그램의 모든 함수에서 전역변수에 접근할 수 있다. ([Whenever Python exits, why isn’t all the memory de-allocated?](#35) 참고) -> 예시 +**로컬 변수(Local Variable)**는 함수 내부에 선언된 변수를 말한다. 로컬 변수는 전역 공간이 아닌 로컬 공간에 있다. ```python a=2 @@ -302,7 +294,7 @@ add() # local var: b, c ``` -- `add()` 함수의 외부에서 `add()` 함수의 로컬 변수에 액세스하려고 하면 오류가 발생한다. +`add()` 함수의 외부에서 `add()` 함수의 로컬 변수에 액세스하려고 하면 오류가 발생한다. --- @@ -320,7 +312,7 @@ add() type conversion은 타입 캐스팅(type casting)과 동일한 의미를 가지며, 이는 어떤 데이터 타입을 다른 데이터 타입으로 변환하는 것을 말한다. -> 타입 캐스팅 함수의 종류 +> **타입 캐스팅 함수의 종류** - `int()`: 정수형으로 변환한다. - `float()`: 실수형으로 변환한다. @@ -374,12 +366,7 @@ Python에서는 array과 list가 동일한 방식으로 데이터를 저장한 array에서 사용할 수 있는 타입은 아래와 같다. -
- -
-
- -> 예시 +![](./img/4-python/array-type.png) ```python import array as arr @@ -404,8 +391,6 @@ print(My_list) 함수는 호출될 때만 실행되는 코드 블록이다. Python 함수를 정의하기 위해 def 키워드가 사용된다. 반복되는 부분을 함수로 만들어서 사용하면, 똑같은 코드를 여러번 반복하여 쓰지 않아도 되고, 프로그램의 흐름을 쉽게 파악할 수 있다는 장점이 있다. -> 예시 - ```python def new_func(): print("Hi, Welcome to Edureka") @@ -427,8 +412,6 @@ new_func(); # 함수 호출 `__init__`는 파이썬에서 특별하게 약속된 메서드 가운데 하나로, 초기화 메서드 혹은 생성자라고도 한다. 이 메서드는 클래스의 새 개체/인스턴스가 생성될 때 메모리를 할당하기 위해 자동으로 호출되며, 그 객체가 갖게 될 여러 가지 성질을 정해준다. 모든 클래스에는 `__init__` 메서드가 있다. -> 예시 - ```python class Employee: def __init__(self, name, age,salary): @@ -454,9 +437,8 @@ XYZ ''' ``` -> 추가내용) `__init__.py`은 무엇인가? - -python 3.3 이하 버전에서, package import하기 위해서 사용되는 규칙이다. 3.3 이후의 버전에서는 이 제약사항이 해제되었다. `__init__.py`는 python 프로그램이 디렉토리를 처음 가져올 때 자동으로 실행되는 **패키지 초기화 파일** 역할을 하고, **모듈의 네임스페이스 초기화** 역할을 한다. +> **💡 `__init__.py`은 무엇인가?** +> python 3.3 이하 버전에서, package import하기 위해서 사용되는 규칙이다. 3.3 이후의 버전에서는 이 제약사항이 해제되었다. `__init__.py`는 python 프로그램이 디렉토리를 처음 가져올 때 자동으로 실행되는 **패키지 초기화 파일** 역할을 하고, **모듈의 네임스페이스 초기화** 역할을 한다. #### References @@ -473,12 +455,7 @@ python 3.3 이하 버전에서, package import하기 위해서 사용되는 규 람다함수의 표현법을 그림으로 표현하면 아래와 같다. -
- -
-
- -> 예시 +![](./img/4-python/lambda-function.png) ```python a = lambda x, y : x + y @@ -663,7 +640,7 @@ print(random.sample(lst, 5)) # [70, 36, 32, 82, 5] #### What is the difference between range & xrange? -> 파이썬2에서는 `range`와 `xrange` 모두 존재하지만, 파이썬3부터는 `range`가 내부적으로 `xrange`로 동작하도록 바뀌어서 `range`만 존재한다. 그러므로 **파이썬2**를 기준으로 `range`와 `xrange`를 설명한다. +> _파이썬2에서는 `range`와 `xrange` 모두 존재하지만, 파이썬3부터는 `range`가 내부적으로 `xrange`로 동작하도록 바뀌어서 `range`만 존재한다. 그러므로 **파이썬2**를 기준으로 `range`와 `xrange`를 설명한다._ `range` 객체는 입력으로 받은 정수 범위의 값을 요소로 같는 리스트를 말한다. 그러므로 `range(3)`과 ` [0, 1, 2]`는 완전히 동일하다. @@ -699,14 +676,14 @@ for i in r: #### How do you write comments in python? -> 따옴표를 이용한 주석은 Docstring 형식으로 자세한 내용은 [#32](#32)를 참고! - `#`을 사용하여 주석을 달 수 있다. ```python # this is my comment ``` +따옴표를 이용한 주석은 Docstring 형식으로 자세한 내용은 [#32](#32)를 참고! + #### References - [Documenting Python Code: A Complete Guide - Real Python](https://realpython.com/documenting-python-code/) @@ -717,8 +694,6 @@ for i in r: #### What is pickling and unpickling? -Pickle module accepts any Python object and converts it into a string representation and dumps it into a file by using dump function, this process is called pickling. While the process of retrieving original Python objects from the stored string representation is called unpickling. - 우선 `직렬화(Serialization)`와 `역 직렬화(Deserialization)`의 개념을 알아야 한다. `직렬화`란 객체를 바이트 스트림(byte stream)으로 변환하여 디스크에 저장하거나 네트워크로 보낼 수 있도록 만들어주는 것을 말한다. 반대로 바이트 스트림을 파이썬 객체로 변환하는 것을 `역 직렬화`라고 한다. **pickle 모듈**은 파이썬 객체의 직렬화와 역 직렬화를 수행하는 모듈이다. 이 때 파이썬 객체를 직렬화할 때를 `pickling`이라고 하며, 바이트 스트림을 역 직렬화할 때를 `unpickling`이라고 한다. @@ -734,7 +709,7 @@ Pickle module accepts any Python object and converts it into a string representa #### What are the generators in python? -제너레이터(Generator)란 Iterator 객체를 간단히 만들 수 있는 함수를 말한다. 제너레이터는 다음과 같이 1 yield문과 함수, 2 표현식 형태로 만들 수 있다. +제너레이터(Generator)란 Iterator 객체를 간단히 만들 수 있는 함수를 말한다. 제너레이터는 다음과 같이 1) yield문과 함수, 2) 표현식 형태로 만들 수 있다. > **방법 1. yield문과 함수** @@ -815,8 +790,6 @@ print(string.lower()) # boostcamp ai tech #### How to comment multiple lines in python? -> 따옴표를 이용한 주석은 Docstring 형식으로 자세한 내용은 [#32](#32)를 참고! - `#`을 여러 줄 사용하여 여러 줄의 주석을 달 수 있다. ```python @@ -825,6 +798,8 @@ print(string.lower()) # boostcamp ai tech # - boostcamp ai tech team 4 ``` +따옴표를 이용한 주석은 Docstring 형식으로 자세한 내용은 [#32](#32)를 참고! + #### References - [Documenting Python Code: A Complete Guide - Real Python](https://realpython.com/documenting-python-code/) @@ -852,7 +827,7 @@ print(help(mult)) print(mult.__doc__) ``` -> **Comments(주석) vs Dosctrings** +> **💡 Comments(주석) vs Dosctrings** > comments와 docstrings은 각각 `#`, `"""`을 쓴다는 점에서 다르지만 가장 큰 차이는 **읽는 대상**이다. comments는 개발을 위해 동료 혹은 나중에 코드를 읽을 나에게 남겨놓는 것이고 docstrings는 이 코드를 사용할 사용자들이 이해하기 쉽도록 남겨놓는 것이다. #### References @@ -929,10 +904,10 @@ print(dir()) # 지역 스코프에 정의된 a와 func 다른 객체나 전역 네임스페이스에서 참조되는 객체를 순환 참조하는 파이썬 모듈은 항상 해제되지는 않는다. 또한 C 라이브러리가 예약한 메모리의 해당 부분을 해제하는 것은 불가능하다. 그러므로 파이썬 종료 시, 모든 메모리가 해제되지는 않는다. -> **순환 참조(Circular Reference)** +> **💡 순환 참조(Circular Reference)** > 두 객체가 서로 참조하는 경우를 말한다. -> **전역 네임스페이스(Global Namespace)** +> **💡 전역 네임스페이스(Global Namespace)** > 네임스페이스(namespace)란 프로그래밍 언어에서 특정 객체를 이름에 따라 구분할 수 있는 범위를 의미한다. 전역 네임스페이스는 import한 모듈들의 이름을 포함하며, 스크립트가 끝날 때까지 지속된다. #### References @@ -1013,38 +988,14 @@ print(ex) # {'name': 'Groot', 'lover': 'Penguin', 'feature': 'handsome'} #### How can the ternary operators be used in python? -ternary operators(삼항 연산자)는 조건문을 표시하는 데 사용되는 연산자이며 아래의 형태로 표현된다. - -```python -[true_value] if [condition] else [false_value] -``` - -> **Example_1** +ternary operators(삼항 연산자)는 조건문을 표시하는 데 사용되는 연산자이며 `[true_value] if [condition] else [false_value]`의 형태로 표현된다. ```python a = 123 -print("a is 123" if a==123 else "a is not 123") -``` - -> **Output** +print("a is 123" if a==123 else "a is not 123") # a is 123 -``` -a is 123 -``` - -
- -> **Example_2** - -```python a = 456 -print("a is 123" if a==123 else "a is not 123") -``` - -> **Output** - -``` -a is not 123 +print("a is 123" if a==123 else "a is not 123") # a is not 123 ``` #### References @@ -1061,45 +1012,27 @@ a is not 123 파이썬에서는 어디서부터 어디까지 `*args`에 담아야 할지 알 수 없기 때문에, 일반 변수를 앞에 두고 그 뒤에 `*args`를 지정해 주어야 한다. -> **Example_1** - ```python def name(*args): print(args) name("샐리", "펭귄", "히스", "원딜") +# output: ('샐리', '펭귄', '히스', '원딜') ``` -> **Output** - -``` -('샐리', '펭귄', '히스', '원딜') -``` - -
- `**kwargs`는 함수에 전달되는 keyword argument의 수를 모르거나, dictionary의 keyword argument들을 함수에 전달하고자 할 때 사용한다. `*args`와 `**kwargs`를 함께 사용하는 경우 `*args`를 `**kwargs`보다 앞에 두어야 한다. -> **Example_2** - ```python def name(**kwargs): print(kwargs) name(sally="샐리", penguin="펭귄", heath="히스", adc="원딜") +# output: {'sally': '샐리', 'penguin': '펭귄', 'heath': '히스', 'adc': '원딜'} ``` -> **Output** - -``` -{'sally': '샐리', 'penguin': '펭귄', 'heath': '히스', 'adc': '원딜'} -``` - -
- -- 일반 변수, `*args`, `**kwargs`를 모두 사용하는 경우 +일반 변수, `*args`, `**kwargs`를 모두 사용하는 경우 다음과 같은 순서를 따른다. ```python def function_name(일반변수, *args, **kwargs) @@ -1119,32 +1052,12 @@ def function_name(일반변수, *args, **kwargs) argument로는 sequence(string, bytes, tuple, list, range, ...), collection(dictionary, set, frozenset, ...)을 받는다. -> **Example_1** - ```python stg = "ai-tech-interview" -len(stg) -``` - -> **Output** - -``` -17 -``` - -
+len(stg) #17 -> **Example_2** - -```python ex_list = ["ai", "tech", "interview"] -len(ex_list) -``` - -> **Output** - -``` -3 +len(ex_list) # 3 ``` #### References @@ -1157,51 +1070,27 @@ len(ex_list) #### Explain split(), sub(), subn() methods of "re" module in Python. -파이썬에서 정규표현식을 사용하기 위해 "re" 모듈을 사용한다. +파이썬에서 정규표현식을 사용하기 위해 "re" 모듈을 사용한다. 문자열 수정을 위해 Python의 "re" 모듈은 3 가지 메서드를 제공한다. -문자열 수정을 위해 Python의 "re" 모듈은 3 가지 메서드를 제공한다. - -- `re.split(pattern, string, maxplit=0)`: pattern을 구분자로 string을 분리하여 list로 반환 -> **Example** +- `re.split(pattern, string, maxplit=0)`: pattern을 구분자로 string을 분리하여 list로 반환한다. ```python re.split('<[^]*>', ' Wow header
Hey

AltStyle によって変換されたページ (->オリジナル) /

') +# output: ['', ' Wow ', ' header ', ' ', ' Hey ', ' ', ''] ``` -> **Output** - -``` -['', ' Wow ', ' header ', ' ', ' Hey ', ' ', ''] -``` - -
- -- `re.sub(pattern, repl, string, count=0)`: string에서 pattern과 일치하는 부분에 대하여 repl로 교체하여 결과 문자열을 반환 -> **Example** +- `re.sub(pattern, repl, string, count=0)`: string에서 pattern과 일치하는 부분에 대하여 repl로 교체하여 결과 문자열을 반환한다. ```python re.sub('\d{4}', 'XXXX', '010-1234-5678') +# output: '010-XXXX-XXXX' ``` -> **Output** - -``` -'010-XXXX-XXXX' -``` - -
- -- `re.subn(pattern, repl, string, count=0)`: sub와 동일하나, 결과로 (결과문자열, 매칭횟수)를 튜플로 반환 -> **Example** +- `re.subn(pattern, repl, string, count=0)`: sub와 동일하나, 결과로 (결과문자열, 매칭횟수)를 튜플로 반환한다. ```python re.subn('\d{4}', 'XXXX', '010-1234-5678') -``` - -> **Output** - -``` -('010-XXXX-XXXX', 2) +# output: ('010-XXXX-XXXX', 2) ``` #### References @@ -1215,51 +1104,28 @@ re.subn('\d{4}', 'XXXX', '010-1234-5678') #### What are negative indexes and why are they used? -**인덱스** +> **인덱스** - 시퀀스 객체에 `[]`(대괄호)를 붙여 사용 - 시퀀스 객체의 인덱스는 항상 0부터 시작 - 시퀀스 객체(list, tuple, range, 문자열)에 사용가능 - 시퀀스객체[인덱스] -**음수 인덱스** +> **음수 인덱스** - 인덱스를 음수로 지정하면 뒤에서부터 요소에 접근하게 된다. - -1은 뒤에서 첫 번째, -5는 뒤에서 다섯 번째 요소를 뜻한다. - 시퀀스 객체(list, tuple, range, 문자열)에 사용가능 -> **Example_1** - ```python example = ['Boostcamp', 'AI', 'Tech', 'penguin', 'sally', 'adc', 'heath'] -print(example[5]) -print(example[-2]) -print(example[-4:]) -``` +print(example[5]) # adc +print(example[-2]) # adc +print(example[-4:]) # ['penguin', 'sally', 'adc', 'heath'] -> **Output** - -``` -adc -adc -['penguin', 'sally', 'adc', 'heath'] -``` - -
- -> **Example_2** - -```python example = "BoostDevs" -print(example[:5]) -print(example[-4:-1]) -``` - -> **Output** - -``` -Boost -Dev +print(example[:5]) # Boost +print(example[-4:-1]) # Dev ``` #### References @@ -1272,24 +1138,21 @@ Dev #### What are Python packages? -**모듈** +> **모듈** 모듈은 파이썬 코드를 논리적으로 묶어서 관리하고 사용할 수 있도록 하는 것으로, 보통 하나의 파이썬 `.py` 파일이 하나의 모듈이 된다. 모듈 안에는 함수, 클래스, 혹은 변수들이 정의될 수 있으며, 실행 코드를 포함할 수도 있다. -> 모듈에 관한 자세한 내용은 [#9. 모듈](#9) 참고 +모듈에 관한 자세한 내용은 [#9. 모듈](#9) 참고! -**패키지** +> **패키지** 패키지는 특정 기능과 관련된 여러 모듈을 묶은 것으로 패키지는 모듈에 namespace를 제공한다. 패키지는 하나의 디렉토리에 놓여진 모듈들의 집합을 가리키는데, 그 디렉토리에는 일반적으로 `__init__.py` 라는 패키지 초기화 파일이 존재한다. 패키지는 모듈들의 컨테이너로서 패키지 안에는 또다른 서브 패키지를 포함할 수도 있다. 파일시스템으로 비유하면 패키지는 일반적으로 디렉토리에 해당하고, 모듈은 디렉토리 안의 파일에 해당한다. -

-
- -
+![](./img/4-python/package.png) -> 패키지들의 모음인 라이브러리에 대한 내용은 [#52. 라이브러리](#52) 참고 +패키지들의 모음인 라이브러리에 대한 내용은 [#52. 라이브러리](#52) 참고! #### References @@ -1304,16 +1167,12 @@ Dev os 모듈을 import 한 후 `os.remove()` 함수를 사용하여 파일을 삭제할수있다. -> **Example** - ```python import os os.remove("ai-tech-interview.txt") ``` -
- -> 자세한 내용은 [os.remove - Python documentation](https://docs.python.org/3/library/os.html#os.remove) 참고 +자세한 내용은 [os.remove - Python documentation](https://docs.python.org/3/library/os.html#os.remove) 참고! --- @@ -1330,9 +1189,10 @@ Python의 Built-in type은 아래와 같다. - Boolean - Built-in function -> 자세한 내용은 [Built-in Types - Python documentation](https://docs.python.org/3/library/stdtypes.html) 참고 +자세한 내용은 [Built-in Types - Python documentation](https://docs.python.org/3/library/stdtypes.html) 참고! -> 빌트인built-in이란?
어떤 기능이나 함수 등이 내장 또는 빌트인되어 있다는 뜻은 그것이 프로그램에서 바로 사용가능하도록 준비되어 있다는 뜻
자세한 내용은 [basic-terminology-in-programming - shoark7](https://gist.github.com/shoark7/e8e103dd9a2ff11b94432c17c3826ab9#-%EB%82%B4%EC%9E%A5%EB%90%9Cbuilt-ins) 참고 +> 💡 빌트인built-in이란? +> 어떤 기능이나 함수 등이 내장 또는 빌트인되어 있다는 뜻은 그것이 프로그램에서 바로 사용가능하도록 준비되어 있다는 뜻이다. 자세한 내용은 [basic-terminology-in-programming - shoark7](https://gist.github.com/shoark7/e8e103dd9a2ff11b94432c17c3826ab9#-%EB%82%B4%EC%9E%A5%EB%90%9Cbuilt-ins) 참고할 것. --- @@ -1340,22 +1200,13 @@ Python의 Built-in type은 아래와 같다. #### What advantages do NumPy arrays offer over (nested) Python lists? -- numpy array는 하나의 데이터 타입만 정의가 가능하다. -- Python list와 가장 큰 차이점은 다이나믹 타이핑을 지원하지 않는다는 것이다. -- C의 Array를 사용하여 배열을 생성하기 때문에 속도가 빠르다 - -**np.array의 구조** - -
- -
-
+numpy array는 하나의 데이터 타입만 정의가 가능하다. Python list와 달리 다이나믹 타이핑을 지원하지 않으며, C의 Array를 사용하여 배열을 생성하기 때문에 속도가 빠르다. -Python list는 데이터 주소값을 저장하고 데이터를 가져올 때는 해당 주소에 가서 데이터를 가져온다. +![](./img/4-python/numpy-array.png) -반면 Numpy array는 C의 배열과 유사하여 연속된 주소를 가지고 있어 데이터를 가져올 때는 순서대로 가져오면 되기 때문에 메모리를 효율적으로 사용한다. +Python list는 데이터 주소값을 저장하고 데이터를 가져올 때는 해당 주소에 가서 데이터를 가져온다. 반면 Numpy array는 C의 배열과 유사하여 연속된 주소를 가지고 있어 데이터를 가져올 때는 순서대로 가져오면 되기 때문에 메모리를 효율적으로 사용한다. -> Numpy에 대한 내용은 [#66. Numpy](#66) 참고 +Numpy에 대한 내용은 [#66. Numpy](#66) 참고! #### References @@ -1369,105 +1220,57 @@ Python list는 데이터 주소값을 저장하고 데이터를 가져올 때는 `append()`, `extend()`, `insert()` 함수를 사용하여 list에 value를 추가할 수 있다. -**append()** +> **append()** -- 시간복잡도: `O(1)` - -`list.append(x)` 형태로 사용한다. 괄호 안에 값을 입력하면 새로운 요소를 list 맨 끝에 추가한다. 요소를 추가할 때는 객체로 추가하게 되는데, 입력한 값이 리스트와 같은 반복 가능한 iterable 자료형이더라도 객체로 저장한다. - -> **Example** +`list.append(x)` 형태로 사용하며, $O(1)$의 시간복잡도를 갖는다. 괄호 안에 값을 입력하면 새로운 요소를 list 맨 끝에 추가한다. 요소를 추가할 때는 객체로 추가하게 되는데, 입력한 값이 리스트와 같은 반복 가능한 iterable 자료형이더라도 객체로 저장한다. ```python nums = [1, 2, 3] nums.append(4) -print(nums) +print(nums) # [1, 2, 3, 4] nums.append([5, 6]) -print(nums) +print(nums) # [1, 2, 3, 4, [5, 6]] ``` -> **Output** - -``` -[1, 2, 3, 4] -[1, 2, 3, 4, [5, 6]] -``` - -
- -**extend()** - -- 시간복잡도: `O(N)` +> **extend()** -`list.extend(iterable)` 형태로 사용한다. 입력한 iterable 자료형의 항목 각각을 list의 끝에 하나씩 추가한다. iterable 자료형으로 추가되는 것이 아니라 iterable 자료형 안에 있는 항목이 하나씩 떼어져서 추가된다. append와 동일하게 요소를 list의 끝에 추가하지만 append와 다른 점은 괄호 안에는 iterable 자료형만 올 수 있다는 것이다. iterable 자료형이 아닌 경우 TypeError가 발생한다. - -> **Example** +`list.extend(iterable)` 형태로 사용하며, $O(N)$ 시간복잡도를 갖는다. 입력한 iterable 자료형의 항목 각각을 list의 끝에 하나씩 추가한다. iterable 자료형으로 추가되는 것이 아니라 iterable 자료형 안에 있는 항목이 하나씩 떼어져서 추가된다. append와 동일하게 요소를 list의 끝에 추가하지만 append와 다른 점은 괄호 안에는 iterable 자료형만 올 수 있다는 것이다. iterable 자료형이 아닌 경우 TypeError가 발생한다. ```python nums = [1, 2, 3] nums.extend([4]) -print(nums) +print(nums) # [1, 2, 3, 4] nums.extend([5, 6]) -print(nums) -``` - -> **Output** - -``` -[1, 2, 3, 4] -[1, 2, 3, 4, 5, 6] +print(nums) # [1, 2, 3, 4, 5, 6] ``` -
- -**insert()** +> **insert()** -- 시간복잡도: `O(N)` +- 시간복잡도: `` -`list.insert(i, x)` 형태로 사용한다. list의 원하는 위치 i 앞에 추가할 값 x를 삽입할 수 있다. i는 위치를 나타내는 인덱스를 숫자를 입력한다. 음수를 입력하면 배열의 끝을 기준으로 처리된다. 추가할 값 x는 객체로 추가되며 iterable 자료형이더라도 객체로 저장된다. - -> **Example** +`list.insert(i, x)` 형태로 사용하며, $O(N)$ 시간복잡도를 갖는다. list의 원하는 위치 i 앞에 추가할 값 x를 삽입할 수 있다. i는 위치를 나타내는 인덱스를 숫자를 입력한다. 음수를 입력하면 배열의 끝을 기준으로 처리된다. 추가할 값 x는 객체로 추가되며 iterable 자료형이더라도 객체로 저장된다. ```python nums = [1, 2, 3] nums.insert(0, 10) -print(nums) +print(nums) # [10, 1, 2, 3] nums.insert(-1, 99) -print(nums) +print(nums) # [10, 1, 2, 99, 3] nums.insert(len(nums), [20, 30]) -print(nums) -``` - -> **Output** - -``` -[10, 1, 2, 3] -[10, 1, 2, 99, 3] -[10, 1, 2, 99, 3, [20, 30]] +print(nums) # [10, 1, 2, 99, 3, [20, 30]] ``` -
- -**`+` 연산자** +> **`+` 연산자** -- 시간복잡도: `O(1)` - -`list_1 + list_2` 형태로 사용한다. - -> **Example** +`list_1 + list_2` 형태로 사용하며, $O(1)$ 시간복잡도를 갖는다. ```python nums = [1, 2, 4, 6, 1, 5] -print(nums + [10, 9, 8, 7]) -``` - -> **Output** - -``` -[1, 2, 4, 6, 1, 5, 10, 9, 8, 7] +print(nums + [10, 9, 8, 7]) # [1, 2, 4, 6, 1, 5, 10, 9, 8, 7] ``` #### References @@ -1483,102 +1286,42 @@ print(nums + [10, 9, 8, 7]) `remove()`, `pop()` 함수를 사용하여 list에 value를 삭제할 수 있다. -**remove()** +> **remove()** -- 시간복잡도: `O(N)` - -remove()는 지우고자 하는 인덱스가 아닌, 값을 입력하는 방식이다. 만약 지우고자 하는 값이 리스트 내에 2개 이상이 있다면 순서상 가장 앞에 있는 값을 지우게 된다. 값을 삭제할 때 삭제된 값을 반환하지 않는다. - -> **Example** +`remove()`는 지우고자 하는 인덱스가 아닌, 값을 입력하는 방식이다. 만약 지우고자 하는 값이 리스트 내에 2개 이상이 있다면 순서상 가장 앞에 있는 값을 지우게 된다. 값을 삭제할 때 삭제된 값을 반환하지 않는다. `remove()`는 시간복잡도 $O(N)$를 갖는다. ```python example = [1, 2, 3, 4, 5, 1] example.remove(1) -print(example) -``` - -> **Output** - +print(example) # [2, 3, 4, 5, 1] ``` -[2, 3, 4, 5, 1] -``` - -
- -**pop()** -- 시간복잡도: `O(N)` +> **pop()** -pop()은 리스트에서 지우고자 하는 값의 인덱스를 받아서 지우는 방식이다. 값을 삭제할 때 삭제된 값을 반환한다. 인덱스를 지정하지 않으면 리스트의 마지막 요소가 삭제되며 반환된다. - -> **Example_1** +`pop()`은 리스트에서 지우고자 하는 값의 인덱스를 받아서 지우는 방식이다. 값을 삭제할 때 삭제된 값을 반환한다. 인덱스를 지정하지 않으면 리스트의 마지막 요소가 삭제되며 반환된다. `pop()`은 시간복잡도 $O(N)$를 갖는다. ```python example = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -print(example.pop()) -print(example) -``` - -> **Output** +print(example.pop()) # 10 +print(example) # [1, 2, 3, 4, 5, 6, 7, 8, 9] -``` -10 -[1, 2, 3, 4, 5, 6, 7, 8, 9] -``` - -
- -> **Example_2** - -```python example = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -print(example.pop(3)) -print(example) +print(example.pop(3)) # 4 +print(example) # [1, 2, 3, 5, 6, 7, 8, 9, 10] ``` -> **Output** +> **del** -``` -4 -[1, 2, 3, 5, 6, 7, 8, 9, 10] -``` - -
- -**del** - -- 시간복잡도: `O(N)` - -`del list[i]` 형태로 사용한다. 값을 삭제할 때 삭제된 값을 반환하지 않는다. - -> **Example_1** +`del list[i]` 형태로 사용하며, 시간복잡도 $O(N)$을 갖는다. 값을 삭제할 때 삭제된 값을 반환하지 않는다. ```python example = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] del example[7] -print(example) -``` - -> **Output** - -``` -[1, 2, 3, 4, 5, 6, 7, 9, 10] -``` - -
- -> **Example_2** +print(example) # [1, 2, 3, 4, 5, 6, 7, 9, 10] -```python example = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] del example[7:] -print(example) -``` - -> **Output** - -``` -[1, 2, 3, 4, 5, 6, 7] +print(example) # [1, 2, 3, 4, 5, 6, 7] ``` #### References @@ -1593,7 +1336,7 @@ print(example) Python은 객체 지향 프로그래밍 언어이다. Python의 주요 OOP 개념에는 Class, Object, Method, Inheritance(상속), Polymorphism(다형성), Data Abstraction(데이터 추상화), Encapsulation(캡슐화)을 포함한다. -> 더 자세한 내용은 [#55. Inheritance](#55), [#59. Polymorphism](#59), [#60. Encapsulation](#60), [#61. Data Abstraction](#61) 참고 +더 자세한 내용은 [#55. Inheritance](#55), [#59. Polymorphism](#59), [#60. Encapsulation](#60), [#61. Data Abstraction](#61) 참고! #### References @@ -1605,71 +1348,34 @@ Python은 객체 지향 프로그래밍 언어이다. Python의 주요 OOP 개 #### What is the difference between deep and shallow copy? -**Shallow copy** - -- Shallow copy는 새로운 객체(변수)를 만든 후에 원본에 접근할 수 있는 참조(reference)를 입력한다. - - 이런 경우 서로 다른 변수명이지만 본질적으로 서로 같은 대상을 의미하므로 하나의 변수 역시 수정이 된다. -- 가변형(mutable) 자료형에 대해서 적용이 가능하다. - - 가변형(mutable) 자료형은 같은 주소에서 값(value)이 변경 가능하기 때문에 얕은 복사가 가능하다. - - 불변형(immutable) 자료형은 본질적으로 변경이 불가능하므로 재배정을 통해 변수를 바꾼다. 따라서 재배정이 이루어지므로 객체가 서로 달라진다. +Shallow copy는 **새로운 객체(변수)를 만든 후에 원본에 접근할 수 있는 참조(reference)를 입력**한다. 이런 경우 서로 다른 변수명이지만 본질적으로 서로 같은 대상을 의미하므로 하나의 변수 역시 수정이 된다. -> **Example** +가변형(mutable) 자료형에 대해서 적용이 가능하다. 가변형(mutable) 자료형은 같은 주소에서 값(value)이 변경 가능하기 때문에 얕은 복사가 가능하다. 반면 불변형(immutable) 자료형은 본질적으로 변경이 불가능하므로 재배정을 통해 변수를 바꾼다. 따라서 재배정이 이루어지므로 객체가 서로 달라진다. ```python a = [1, 2, 3, 4, 5] b = a # shallow copy a[1] = 10 -print(a, b) +print(a, b) # [1, 10, 3, 4, 5] [1, 10, 3, 4, 5] ``` -> **Output** - -``` -[1, 10, 3, 4, 5] [1, 10, 3, 4, 5] -``` - -
- -**Deep copy** - -- Deep copy는 새로운 객체(변수)를 만든 뒤에 원본의 복사본을 변수에 입력한다. - - 서로 값만 같을 뿐 본질적으로 서로 다르기 때문에 한 변수가 수정될 시 다른 변수가 수정되지 않는다. - -> **Example_1** +Deep copy는 **새로운 객체(변수)를 만든 뒤에 원본의 복사본을 변수에 입력**한다. 서로 값만 같을 뿐 본질적으로 서로 다르기 때문에 한 변수가 수정될 시 다른 변수가 수정되지 않는다. ```python a = [1, 2, 3, 4, 5] b = a[:] # deep copy a[1] = 10 -print(a, b) +print(a, b) # [1, 10, 3, 4, 5] [1, 2, 3, 4, 5] ``` -> **Output** - -``` -[1, 10, 3, 4, 5] [1, 2, 3, 4, 5] -``` - -
- -> **Example_2** - ```python import copy a = [1, 2, 3, 4, 5] b = copy.deepcopy(a) # deep copy a[1] = 10 -print(a, b) -``` - -> **Output** - -``` -[1, 10, 3, 4, 5] [1, 2, 3, 4, 5] +print(a, b) # [1, 10, 3, 4, 5] [1, 2, 3, 4, 5] ``` -
- #### References - [[Python]Shallow copy & Deep copy - 박현희](https://velog.io/@hyoniii_log/PythonShallow-copy-Deep-copy/) @@ -1686,9 +1392,8 @@ print(a, b) 하나의 자원에 여러 프로세스가 아무런 규칙없이 접근하면, 자원 동기화 문제가 발생할 수 있다. 이를 방지하기 위해서 자원에 lock을 두는데, Python은 모든 자원의 lock을 global하게 관리하고 있다. 한번에 하나의 스레드만 자원에 접근할 수 있다는 것이다. 이로인해, 자원을 공유하는 여러 스레드를 동시에 실행시킨다고 해도, 결국 GIL 때문에 한번에 하나의 스레드만 실행되는 것이다. -> 추가내용) 멀티스레딩이 유용한 경우? - -GIL은 cpu 동작에 대해서만 적용된다. 쓰레드가 cpu 동작을 마치고 I/O 작업을 실행하는 동안에는 다른 쓰레드가 cpu 동작을 동시에 실행할 수 있다. 따라서 cpu 동작이 많지 않고 I/O동작이 더 많은 프로그램에서는 멀티 쓰레드만으로 성능적으로 큰 효과를 얻을 수 있다. +> **💡 멀티스레딩이 유용한 경우** +> GIL은 cpu 동작에 대해서만 적용된다. 쓰레드가 cpu 동작을 마치고 I/O 작업을 실행하는 동안에는 다른 쓰레드가 cpu 동작을 동시에 실행할 수 있다. 따라서 cpu 동작이 많지 않고 I/O동작이 더 많은 프로그램에서는 멀티 쓰레드만으로 성능적으로 큰 효과를 얻을 수 있다. #### References @@ -1708,8 +1413,6 @@ GIL은 cpu 동작에 대해서만 적용된다. 쓰레드가 cpu 동작을 마 참고로 dis 모듈을 사용하여 소스 코드가 어떤 바이트 코드로 변환되는지 확인할 수 있다. -- 소스 코드 - ```python import dis @@ -1717,15 +1420,11 @@ def mult(a, b): return a*b dis.dis(mult) -``` - -- 출력 결과 - -```shell -4 0 LOAD_FAST 0 (a) - 2 LOAD_FAST 1 (b) - 4 BINARY_MULTIPLY - 6 RETURN_VALUE +# output: +# 4 0 LOAD_FAST 0 (a) +# 2 LOAD_FAST 1 (b) +# 4 BINARY_MULTIPLY +# 6 RETURN_VALUE ``` #### References @@ -1745,13 +1444,11 @@ dis.dis(mult) 파이썬 라이브러리는 패키지의 모음이다. -
- -
+![](./img/4-python/library.png) 주로 사용되는 파이썬 라이브러리로는 [`Numpy`](https://numpy.org/), [`Pandas`](https://pandas.pydata.org/), [`Matplotlib`](https://matplotlib.org/), [`Scikit-learn`](https://scikit-learn.org/stable/) 등이 있다. -> 패키지에 대한 더 자세한 내용은 [#42. 패키지](#42) 참고 +패키지에 대한 더 자세한 내용은 [#42. 패키지](#42) 참고! --- @@ -1771,26 +1468,15 @@ sep이 지정되면 구분자를 기준으로 문자열을 분리하고, sep이 maxsplit이 지정되면 그 수만큼의 분할이 수행되고, maxsplit이 지정되지 않았거나 -1인 경우에는 가능한 모든 분할이 수행된다. -> **Example** - ```python a = "ai tech interview" -print(a.split()) +print(a.split()) # ['ai', 'tech', 'interview'] a = "ai tech interview" -print(a.split()) +print(a.split()) # ['ai', 'tech', 'interview'] a = "ai-tech-interview" -print(a.split("-")) +print(a.split("-")) # ['ai', 'tech', 'interview'] a = "ai-tech-interview" -print(a.split("-", 1)) -``` - -> **Output** - -``` -['ai', 'tech', 'interview'] -['ai', 'tech', 'interview'] -['ai', 'tech', 'interview'] -['ai', 'tech-interview'] +print(a.split("-", 1)) # ['ai', 'tech-interview'] ``` #### References @@ -1803,17 +1489,13 @@ print(a.split("-", 1)) #### How to import modules in python? -`import` 키워드를 사용하여 모듈을 가져올 수 있다. 세 가지 방법으로 모듈을 가져올 수 있다. - ```python import [패키지/모듈] from [패키지] import [모듈/변수/함수/클래스] from [모듈] import [변수/함수/클래스] ``` -
- -> **Example** +`import` 키워드를 사용하여 모듈을 가져올 수 있다. 세 가지 방법으로 모듈을 가져올 수 있다. ```python import numpy # importing using the original module name @@ -1821,10 +1503,6 @@ import numpy as np # importing using an alias name from numpy import * # imports everything present in the numpy module ``` -
- -> 참고 - ```python from numpy import argmax as arm # 이런거도 된다 nums = [1, 2, 3, 4, 5] @@ -1968,11 +1646,10 @@ class 추상클래스명(metaclass=ABCMeta): 접두사 _ 가 한 개 있는 경우에는 protected, 접두사 _ 가 두 개 있는 경우에는 private, 접두사 _ 가 없거나 접미사 _ 가 두 개 이상 있는 경우에는 public 이다. -> [public, private, protect의 차이점 - Eureka Developer](https://eurekadeveloper.tistory.com/entry/public-private-protect%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90) - #### References - [[python] 접근 제어자 - 불곰](https://brownbears.tistory.com/112) +- [public, private, protect의 차이점 - Eureka Developer](https://eurekadeveloper.tistory.com/entry/public-private-protect%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90) --- @@ -1997,9 +1674,7 @@ print(e.a) # 10 #### What does an object() do? -파이썬은 모든 것이 객체이다. 따라서 기본적으로 object 클래스를 상속받고 있다. - -object() 함수를 사용하면 새로운 기본 object 객체를 반환받을 수 있다. +파이썬은 모든 것이 객체이다. 따라서 기본적으로 object 클래스를 상속받고 있다. `object()` 함수를 사용하면 새로운 기본 object 객체를 반환받을 수 있다. --- @@ -2104,7 +1779,7 @@ def big_number2(n): object interning 은 자주 사용될, 즉 재활용될 object 에 대해 매번 새로운 주소를 할당하는 것은 비효율적이므로, 하나의 주소에 값을 주고 그 주소를 재활용하는 작업을 말한다. -기본적으로 파이썬에서는 -5~256, [a-Az-Z0-9_] 에 대해 고정된 주소를 할당하여 interning 을 하고 있다. +기본적으로 파이썬에서는 `-5~256, [a-Az-Z0-9_]` 에 대해 고정된 주소를 할당하여 interning 을 하고 있다. #### References @@ -2116,11 +1791,11 @@ object interning 은 자주 사용될, 즉 재활용될 object 에 대해 매번 #### What is @classmethod, @staticmethod, @property? -**@classmethod** +> **@classmethod** 클래스 내부의 함수 중에 @classmethod 로 선언된 함수에 대해서는 클래스의 객체를 만들지 않고도 바로 접근이 가능하다. 하지만 함수의 첫 인자로 클래스를 받아서, 상속되었을 때 자식 클래스의 데이터를 따르는 특징이 있다. -**@staticmethod** +> **@staticmethod** @staticmethod 는 @classmethod 와 마찬가지로 클래스의 객체를 만들지 않고도 바로 접근할 수 있다. 하지만 클래스를 인자로 받지 않기 때문에, 상속되었을 때에도 자식 클래스의 데이터를 따르지 않고 처음에 클래스에서 선언한 데이터대로 함수가 사용된다. @@ -2156,7 +1831,8 @@ class KoreanLanguage(Language): 나의 언어는한국어 ``` -**@property** +> **@property** + 객체지향 언어에서는 캡슐화를 위해 변수를 직접 지정하지 않고 객체의 함수를 통해 지정하고 받아오는 setter, getter 함수를 사용한다. 파이썬에서는 이를 편하게 사용할 수 있도록 @property 를 제공한다. getter 가 될 함수에 @property 를, setter 가 될 함수에 @변수.setter 를 붙이면 된다. diff --git a/answers/5-network.md b/answers/5-network.md index 2432fba..c11ee94 100644 --- a/answers/5-network.md +++ b/answers/5-network.md @@ -1,10 +1,4 @@ -
-

🌐 Network 🌐

-
- -> 질문 중 일부는 [WeareSoft님의 tech-interview](https://github.com/WeareSoft/tech-interview)를 참고하였습니다. - ---- +> **📌 질문 중 일부는 [WeareSoft님의 tech-interview](https://github.com/WeareSoft/tech-interview)를 참고하였습니다.** ## Table of Contents @@ -47,29 +41,31 @@ #### TCP/IP의 각 계층을 설명해주세요. -> TCP/IP란? - TCP/IP는 인터넷에서 표준으로 사용되고 있는 네트워크 프로토콜(규칙)을 의미한다. TCP/IP는 IP(Internet Protocol)을 중심으로 한 여러 프로토콜의 집합체로, TCP/IP 5계층 혹은 TCP/IP 4계층(링크계층과 물리계층을 하나의 계층으로 보는 경우)으로 불린다. -> TCP/IP 5계층의 구조 - TCP/IP는 크게 5개의 계층으로 구성된다. -- **애플리케이션 계층**(Application Layer, L5) - - 네트워크 애플리케이션과 애플리케이션 계층 프로토콜이 있는 곳이다. HTTP, SMTP, FTP와 같은 많은 프로토콜을 포함한다. 도메인 주소를 32비트 네트워크 주소로 변환하는 기능을 위한 DNS(Domain Name Server)를 지원한다. 애플리케이션 계층 패킷을 **메시지**(message)라고 한다. -- **트랜스포트 계층**(Transport Layer, L4) - - 네트워크 계층에서 보내온 데이터 정렬, 오류 정정 등을 수행하고 신뢰할 수 있는 통신을 확보한다. TCP/UDP 같은 프로토콜이 이 계층에 위치한다. TCP, UDP에 대한 내용은 [[#4] TCP와 UDP의 차이를 설명해주세요.](#4) 을 참고한다. 트랜스포트 계층 패킷을 **세그먼트**(segment)라고 한다. -- **네트워크 계층**(Network Layer/IP Layer, L3) - - 다른 네트워크에 있는 목적지에 데이터를 전송하는 역할을 수행한다. 즉, 네트워크 간의 통신을 가능하게 해주는 역할을 수행한다. 이를 위해, 라우터(router) 장비와 IP 프로토콜(오직 하나만 존재), 라우팅 프로토콜이 사용된다. 라우터는 다른 네트워크와 통신하기 위해 경로를 설정하고 논리주소를 결정하는 역할을 수행한다.(경로설정) 네트워크 계층의 패킷을 **데이터그램**(datagram)이라 한다. -- **링크 계층**(Data Link Layer, L2) - - 네트워크 기기 간 데이터 전송 및 물리 주소를 결정하는 역할을 수행한다. 주로 건물이나 특정 지역을 범위로 하는 네트워크인 랜(LAN)에서 데이터를 정상적으로 주고받기 위해 필요한 계층이다. 데이터 링크 계층에서는 일반적으로 이더넷(Ethernet) 프로토콜이 사용되며, 스위치(switch) 같은 장치가 사용된다. 링크 계층 패킷을 **프레임**(frame)이라 한다. -- **물리 계층**(Physical Layer, L1) - - 물리적인 연결과 전기 신호 변환/제어를 담당하여, 이진 데이터를 전기 신호로 변환한다. 또한 컴퓨터와 네트워크 장비를 물리적으로 연결하여, 하나의 노드에서 다른 노드로 **비트를** 이동시키는 역할을 수행한다. 물리 계층의 프로토콜들은 링크(실제 전송매체 ex.광케이블)에 의존한다. - -
- -
-
+> **애플리케이션 계층**(Application Layer, L5) + +네트워크 애플리케이션과 애플리케이션 계층 프로토콜이 있는 곳이다. HTTP, SMTP, FTP와 같은 많은 프로토콜을 포함한다. 도메인 주소를 32비트 네트워크 주소로 변환하는 기능을 위한 DNS(Domain Name Server)를 지원한다. 애플리케이션 계층 패킷을 **메시지**(message)라고 한다. + +> **트랜스포트 계층**(Transport Layer, L4) + +네트워크 계층에서 보내온 데이터 정렬, 오류 정정 등을 수행하고 신뢰할 수 있는 통신을 확보한다. TCP/UDP 같은 프로토콜이 이 계층에 위치한다. TCP, UDP에 대한 내용은 [[#4] TCP와 UDP의 차이를 설명해주세요.](#4) 을 참고한다. 트랜스포트 계층 패킷을 **세그먼트**(segment)라고 한다. + +> **네트워크 계층**(Network Layer/IP Layer, L3) + +다른 네트워크에 있는 목적지에 데이터를 전송하는 역할을 수행한다. 즉, 네트워크 간의 통신을 가능하게 해주는 역할을 수행한다. 이를 위해, 라우터(router) 장비와 IP 프로토콜(오직 하나만 존재), 라우팅 프로토콜이 사용된다. 라우터는 다른 네트워크와 통신하기 위해 경로를 설정하고 논리주소를 결정하는 역할을 수행한다.(경로설정) 네트워크 계층의 패킷을 **데이터그램**(datagram)이라 한다. + +> **링크 계층**(Data Link Layer, L2) + +네트워크 기기 간 데이터 전송 및 물리 주소를 결정하는 역할을 수행한다. 주로 건물이나 특정 지역을 범위로 하는 네트워크인 랜(LAN)에서 데이터를 정상적으로 주고받기 위해 필요한 계층이다. 데이터 링크 계층에서는 일반적으로 이더넷(Ethernet) 프로토콜이 사용되며, 스위치(switch) 같은 장치가 사용된다. 링크 계층 패킷을 **프레임**(frame)이라 한다. + +> **물리 계층**(Physical Layer, L1) + +물리적인 연결과 전기 신호 변환/제어를 담당하여, 이진 데이터를 전기 신호로 변환한다. 또한 컴퓨터와 네트워크 장비를 물리적으로 연결하여, 하나의 노드에서 다른 노드로 **비트를** 이동시키는 역할을 수행한다. 물리 계층의 프로토콜들은 링크(실제 전송매체 ex.광케이블)에 의존한다. + +![](./img/5-network/tcp-ip-hierarchy.png) #### References @@ -82,21 +78,23 @@ TCP/IP는 크게 5개의 계층으로 구성된다. #### OSI 7계층와 TCP/IP 계층의 차이를 설명해주세요. -
- -
-
+![](./img/5-network/osi-7-layer.png) -❊ `네트워크 인터페이스 계층`: TCP/IP 5계층에서 물리계층과 링크계층을 하나로 묶은 것 +(`네트워크 인터페이스 계층`: TCP/IP 5계층에서 물리계층과 링크계층을 하나로 묶은 것) OSI 7계층은 TCP/IP 계층의 애플리케이션 계층을 더 세분화한 것이다. TCP/IP 계층과 다른, 응용계층, 표현계층과 세션계층에 대해서 설명하고 나머지는 [[#1] CP/IP의 각 계층을 설명해주세요.](#1)을 참고한다. -- **응용 계층**(Application Layer) - - 사용자 또는 애플리케이션이 네트워크에 접근할 수 있도록 해주는 계층이다. 사용자를 위한 인터페이스를 지원하며, 사용자에게 보이는 유일한 계층이다. 메일 전송, 인터넷 접속 등의 작업을 수행할 수 있다. -- **표현 계층**(Presentation Layer) - - 응용계층으로부터 전달받거나 전송하는 데이터의 인코딩 및 디코딩이 이루어지는 계층이다. 응용 계층에서 데이터를 이해할 수 있도록, 응용프로그램에 맞춰 변환하게 된다. 예를들어, JPEG, TIFF, GIF, MPEG 등의 다양한 포맷을 구분하게 된다. -- **세션 계층**(Session Layer) - - 응용프로세스가 통신을 관리하기 위한 방법을 정의한다. 네트워크상 양쪽의 연결을 관리/지속시키는 역할과 세션을 만들거나 없애는 역할을 담당하는 계층이다. 통신하는 사용자들을 동기화하고 오류복구를 진행한다. 통신연결은 포트를 기반으로 구성하여 연결되며, OS가 세션계층에 속한다. +> **응용 계층**(Application Layer) + +사용자 또는 애플리케이션이 네트워크에 접근할 수 있도록 해주는 계층이다. 사용자를 위한 인터페이스를 지원하며, 사용자에게 보이는 유일한 계층이다. 메일 전송, 인터넷 접속 등의 작업을 수행할 수 있다. + +> **표현 계층**(Presentation Layer) + +응용계층으로부터 전달받거나 전송하는 데이터의 인코딩 및 디코딩이 이루어지는 계층이다. 응용 계층에서 데이터를 이해할 수 있도록, 응용프로그램에 맞춰 변환하게 된다. 예를들어, JPEG, TIFF, GIF, MPEG 등의 다양한 포맷을 구분하게 된다. + +> **세션 계층**(Session Layer) + +응용프로세스가 통신을 관리하기 위한 방법을 정의한다. 네트워크상 양쪽의 연결을 관리/지속시키는 역할과 세션을 만들거나 없애는 역할을 담당하는 계층이다. 통신하는 사용자들을 동기화하고 오류복구를 진행한다. 통신연결은 포트를 기반으로 구성하여 연결되며, OS가 세션계층에 속한다. #### References @@ -107,32 +105,28 @@ OSI 7계층은 TCP/IP 계층의 애플리케이션 계층을 더 세분화한 ## #3 -#### Frame, Packet, Segment, Datagram을 비교해주세요. - -(❊ TCP/IP 5계층 기준으로 설명한다.) +#### Frame, Packet, Segment, Datagram을 비교해주세요. (TCP/IP 5계층 기준) - **Packet**: 컴퓨터 간에 데이터를 주고받을 때, 네트워크를 통해 전송되는 **데이터 조각**을 패킷이라고 부른다. 송신 측(애플리케이션)은 많은 양의 데이터를 한번에 보내는 것이 아니라, 일정 단위로 잘라서 보낸다. 각 계층에서 필요한 정보는 캡슐화/역캡슐화되어 전달되고, 수신 측은 받은 패킷을 다시 조립해서 사용한다. - **Segment**: Transport 계층(L4)에서 신뢰할 수 있는 통신을 구현하기 위한 헤더를 데이터(L5 계층 데이터)에 붙이는데, 이렇게 만들어진 패킷을 세그먼트라고 부른다. - **Datagram**: Network 계층(L3)에서 다른 네트워크와 통신하기 위한 헤더를 세그먼트(L4 계층 데이터)에 붙인것을 데이터그램, 데이터 세그먼트라고 부른다. - **Frame**: 데이터 링크 계층(L2)에서 물리적인 통신 채널을 열기 위해 패킷에 헤더와 트레일러를 붙인다. 트레일러는 데이터를 전달할 때 데이터 끝 부분에 붙이는 정보로, 주로 에러 검출에 사용된다. -
- -
-
+![](./img/5-network/capsulation.png) -> **추가내용) 왜 패킷을 잘라서 보낼까?** +> **왜 패킷을 잘라서 보낼까?** 많은 데이터를 한번에 보내게 되면, 데이터 손실의 가능성이 있으며, 대역폭(신호를 전송할 수 있는 주파수 범위)을 너무 많이 차지하게 되므로, 패킷의 흐름을 원활히 조절하기 위함이다. -> **추가내용) 소켓(Socket), 포트(Port), 패킷(Packet)?** +> **소켓(Socket), 포트(Port), 패킷(Packet)** + +**Port**는 프로세스를 식별하기 위해, 호스트 내부적으로 프로세스가 할당받는 고유한 값이다. 같은 호스트 내에서 서로 다른 프로세스가 같은 포트 넘버를 가질 수 있음, 대신 같은 소켓을 사용하지는 못한다. `accept()`를 통해 만들어지는 소켓에는 새로운 포트 번호가 할당되는 것이 아니라, 서버가 가지는 포트(웹서버 기준, 80)와 동일한 포트 번호를 가진다. 만약 지정된 포트 번호를 다른 소켓이 사용하고 있다면, `bind()` API는 에러를 리턴한다. 포트는 논리적인 접속장소이다. -- **Port**: 프로세스를 식별하기 위해, 호스트 내부적으로 프로세스가 할당받는 고유한 값이다. 같은 호스트 내에서 서로 다른 프로세스가 같은 포트 넘버를 가질 수 있음, 대신 같은 소켓을 사용하지는 못한다. `accept()`를 통해 만들어지는 소켓에는 새로운 포트 번호가 할당되는 것이 아니라, 서버가 가지는 포트(웹서버 기준, 80)와 동일한 포트 번호를 가진다. 만약 지정된 포트 번호를 다른 소켓이 사용하고 있다면, `bind()` API는 에러를 리턴한다. 포트는 논리적인 접속장소이다. -- **Socket**: 프로세스로부터 네트워크로 데이터를 전달하는 출입구(인터페이스) 역할을 한다. `프로세스에서 소켓을 연다`고 표현하며, 수신 측 호스트의 트랜스포트 계층은 실제로 데이터(세그먼트)를 직접 프로세스로 전달하지 않고, 중간 매개자인 소켓에게 전달한다. 호스트에서는 하나 이상의 소켓이 존재할 수 있으므로 소켓은 고유의 식별자를 가지고 있어야한다. 같은 프로세스가 같은 포트를 가지고도 여러 개의 소켓을 열 수 있기 때문에, 소켓과 포트는 다른 개념이다. +**Socket**은 프로세스로부터 네트워크로 데이터를 전달하는 출입구(인터페이스) 역할을 한다. `프로세스에서 소켓을 연다`고 표현하며, 수신 측 호스트의 트랜스포트 계층은 실제로 데이터(세그먼트)를 직접 프로세스로 전달하지 않고, 중간 매개자인 소켓에게 전달한다. 호스트에서는 하나 이상의 소켓이 존재할 수 있으므로 소켓은 고유의 식별자를 가지고 있어야한다. 같은 프로세스가 같은 포트를 가지고도 여러 개의 소켓을 열 수 있기 때문에, 소켓과 포트는 다른 개념이다. -→ 요약하자면, **소켓**은 프로세스가 네트워크를 통해서 데이터를 주고받으려면 반드시 열어야 하는 창구 같은 것이고, **포트**는 프로세스 식별을 위해 하나의 호스트에서 프로세스에 할당하는 고유값이고, **패킷**은 네트워크 상의 데이터 조각을 말하는 것이다. +요약하자면, **소켓**은 프로세스가 네트워크를 통해서 데이터를 주고받으려면 반드시 열어야 하는 창구 같은 것이고, **포트**는 프로세스 식별을 위해 하나의 호스트에서 프로세스에 할당하는 고유값이고, **패킷**은 네트워크 상의 데이터 조각을 말하는 것이다. -> 추가내용) 캡슐화/역캡슐화 +> **캡슐화/역캡슐화** - **캡슐화**(Encapsulation): (데이터 송신 시)하위 계층으로 패킷을 보낼때, 하위계층에서 필요로하는 추가정보(메타데이터)를 헤더/트레일러에 추가하여 보내게된다. - **역캡슐화**(Decapsulation): 데이터 수신 시, 상위 계층으로 패킷을 전달하고, 전달된 패킷의 헤더를 차례대로 제거하면서 데이터를 얻게 된다. @@ -150,16 +144,14 @@ OSI 7계층은 TCP/IP 계층의 애플리케이션 계층을 더 세분화한 TCP와 UDP는 모두 트랜스포트 계층(4계층)의 프로토콜이다. TCP와 UDP가 **공통적**으로 가지고 있는 기능은 아래와 같다. -1. **트랜스포트 다중화/역다중화 기능**(Transport Multiplexing/Demultiplexing) - - `호스트 대 호스트 전달`을 `프로세스 대 프로세스 전달`로 확장 -2. **무결성 검사(오류검출)** - - 헤더에 오류 검출 필드를 포함 +1. **트랜스포트 다중화/역다중화 기능**(Transport Multiplexing/Demultiplexing): `호스트 대 호스트 전달`을 `프로세스 대 프로세스 전달`로 확장 +2. **무결성 검사(오류검출)**: 헤더에 오류 검출 필드를 포함 이제 TCP와 UDP 각각에 대해 알아보자. **UDP**는 위의 가장 기본적인 두가지 기능만을 제공한다. UDP는 **비신뢰적인 서비스**로서, 프로세스에 의해서 전송된 데이터가 손상되지 않은채로 목적지에 도착하는 것을 보장하지 않는다. 또한 **비연결형 서비스**이며, 오류검출은 선택사항이다. -UDP는 비연결형 서비스이므로 연결설정이 불필요하고 연결상태가 없다. 따라서 연결을 설정하기위한 어떠한 지연이 없고, 유지해야하는 정보가 없기 때문에 더 많은 클라이언트를 수용할 수 있다. 또한 UDP의 패킷 오버헤드(8 byte per segment)가 TCP(20 byte pre segment)에 비해 더 작다는 장점이 있다. 그러나 혼잡제어를 사용하지 않아, 네트워크가 폭주상태에 빠지는 것을 막을 수 없다는 단점과 신뢰적이지 않으므로, 몇몇의 정보를 잃어버릴 수 있다는 단점이 존재한다. +UDP는 비연결형 서비스이므로 연결설정이 불필요하고 연결상태가 없다. 따라서 연결을 설정하기위한 어떠한 지연이 없고, 유지해야하는 정보가 없기 때문에 더 많은 클라이언트를 수용할 수 있다. 또한 UDP의 패킷 오버헤드(8 byte per segment)가 TCP(20 byte per segment)에 비해 더 작다는 장점이 있다. 그러나 혼잡제어를 사용하지 않아, 네트워크가 폭주상태에 빠지는 것을 막을 수 없다는 단점과 신뢰적이지 않으므로, 몇몇의 정보를 잃어버릴 수 있다는 단점이 존재한다. **TCP**는 가장 기본적인 두가지 기능도 제공하면서, 신뢰적인 데이터 전달(Reliable Data Transfer) 기능, 연결지향형 서비스, 혼잡제어(Congestion control) 등의 기능을 제공한다. @@ -179,10 +171,7 @@ UDP는 비연결형 서비스이므로 연결설정이 불필요하고 연결상 **UDP segment**의 간략한 구조는 아래와 같다. -
- -
-
+![](./img/5-network/udp-segment.png) 애플리케이션 데이터는 UDP 데이터그램의 데이터 필드에 위치한다. UDP 헤더는 2바이트(16비트)씩 구성된 4개의 필드를 가진다. UDP 헤더는 `출발지 포트번호`, `목적지 포트번호`, `체크섬`, `길이`로 이루어져있다. @@ -190,14 +179,11 @@ UDP는 비연결형 서비스이므로 연결설정이 불필요하고 연결상 - **체크섬**(checksum)은 세그먼트에 오류가 발생했는지를 검사하기 위해 사용되며, 체크섬은 UDP 세그먼트 이외에 IP 헤더의 일부 필드도 계산한다.(가상헤더) UDP 헤더와 데이터를 모두 포함하여 체크하게 된다. - **길이**는 헤더를 포함하는 UDP 세그먼트의 길이(바이트 단위)를 나타낸다. UDP헤더와 데이터를 합친 길이를 나타낸다. -
+--- **TCP segment**의 간략한 구조는 아래와 같다. -
- -
-
+![](./img/5-network/tcp-segment.png) TCP 소켓은 4개의 다른 요소들의 집합에 의해 식별된다.(`출발지 IP`, `출발지 포트번호`, `목적지 IP`, `목적지 포트번호`) 따라서 IP를 제외한 `출발지/도착지 포트번호`(각 16 bit)와 `sequence number`(32 bit), `ack number`(32 bit)를 합쳐, 기본적으로 20 byte의 헤더를 가지게 되며, 옵션을 포함하면 최대 60 byte의 헤더를 가질 수 있다. 다른 출발지 주소를 가지는 세그먼트는, 다른 소켓을 통해서 프로세스에 전달된다. UDP와 다르게, TCP 세그먼트는 출발지 주소가 다르면, 다른 소켓으로 전달된다. @@ -217,10 +203,7 @@ TCP 소켓은 4개의 다른 요소들의 집합에 의해 식별된다.(`출발 **핸드셰이크**(Handshake)란, 호스트 간 데이터를 전송하기 전에 먼저 정확한 전송을 보장하기 위해 상대방 컴퓨터와 사전에 세션을 수립하는 과정을 의미한다. -
- -
-
+![](./img/5-network/3-way-handshake.png) **3-way handshake**는 TCP의 연결을 초기화 할 때 사용한다. 양쪽 모두 데이터를 전송할 준비가 되었다는 것을 보장하고, 실제로 데이터 전달이 시작하기전에 한쪽이 다른 쪽이 준비되었다는 것을 알수 있도록 한다. 양쪽 모두 상대편에 대한 초기 순차일련변호를 얻을 수 있도록 한다. 절차는 다음과 같다. @@ -228,14 +211,9 @@ TCP 소켓은 4개의 다른 요소들의 집합에 의해 식별된다.(`출발 2. 접속 요청을 받은 프로세스가 요청을 수락한다는 확인 메시지를 보낸다. (ACK) 동시에 접속 요청을 받은 프로세스도 접속 요청을 한 프로세스에 연결 요청을 보낸다.(SYN) → (SYN + ACK) 3. 마지막으로 접속 요청 프로세스가 수락 확인을 보내 연결을 맺는다.(ACK) -> 단순히 응답을 주고받는데 2-way Handshake면 충분해보이지 않는가? 왜 3-way 일까? - -TCP/IP 통신은 양방향성 connection 이다. 위의 그림의 1번 과정에서 클라이언트가 연결 요청을 SYN으로 보내면, 서버는 클라이언트가 요청한 SYN에 대한 대답(ACK)과 함께, 자신도 연결하겠다는 요청의 의미로 SYN을 보내고, 클라이언트로부터 요청에 대한 대답(과정 3)을 받아야한다. 이 과정은 2-way handshaked에서는 성립될 수 없다. +단순히 응답을 주고받는데 2-way Handshake면 충분해보이지 않는가? 왜 3-way 일까? TCP/IP 통신은 양방향성 connection이다. 위의 그림의 1번 과정에서 클라이언트가 연결 요청을 SYN으로 보내면, 서버는 클라이언트가 요청한 SYN에 대한 대답(ACK)과 함께, 자신도 연결하겠다는 요청의 의미로 SYN을 보내고, 클라이언트로부터 요청에 대한 대답(과정 3)을 받아야한다. 이 과정은 2-way handshaked에서는 성립될 수 없다. -
- -
-
+![](./img/5-network/4-way-handshake.png) **4-way handshake**는 세션을 종료하기 위해 수행되는 절차이다. 구체적인 과정은 다음과 같다. @@ -244,15 +222,14 @@ TCP/IP 통신은 양방향성 connection 이다. 위의 그림의 1번 과정에 3. 서버가 통신이 끝났으면 연결이 종료되었다고 클라이언트에게 FIN 플래그를 전송한다. 4. 클라이언트는 확인했다는 메시지를 보낸다. -> `CLOSE_WAIT` 와 `TIME_WAIT` 상태란 무엇일까? - -`TIME_WAIT` 상태로 대기하는 이유는, 세션 종료후, 혹시나 네트워크에 아직 라이브 패킷이 존재할수도 있기때문이다. - -> 용어 +> **💡 `CLOSE_WAIT` 와 `TIME_WAIT` 상태란 무엇일까?** +> `TIME_WAIT` 상태로 대기하는 이유는, 세션 종료후, 혹시나 네트워크에 아직 라이브 패킷이 존재할수도 있기때문이다. -- **SYN**(Synchronization): 연결요청, 세션을 설정하는데 사용되며 초기에 시퀀스 번호를 보낸다. -- **ACK**(Acknowledgement): 보낸 시퀀스 번호에 TCP 계층에서의 길이 또는 양을 더한 것과 같은 값을 ACK에 포함하여 전송한다. -- **FIN**(Finish) : 세션을 종료시키는데 사용되며 더 이상 보낸 데이터가 없음을 표시한다. +> **💡 용어** +> +> - **SYN**(Synchronization): 연결요청, 세션을 설정하는데 사용되며 초기에 시퀀스 번호를 보낸다. +> - **ACK**(Acknowledgement): 보낸 시퀀스 번호에 TCP 계층에서의 길이 또는 양을 더한 것과 같은 값을 ACK에 포함하여 전송한다. +> - **FIN**(Finish) : 세션을 종료시키는데 사용되며 더 이상 보낸 데이터가 없음을 표시한다. #### References @@ -310,17 +287,11 @@ Connection을 맺을 때 사용하는 포트는 유한 범위 내에서 사용 #### HTTP와 HTTPS에 대해서 설명하고 차이점에 대해 설명해주세요. -- HTTP(Hyper Text Transfer Protocol) - HTTP란 **서버/클라이언트 모델을 따라 데이터를 주고받기 위한 프로토콜**이다. 즉, HTTP는 인터넷에서 하이퍼텍스트를 교환하기 위한 통신 규약으로, 80번 포트를 사용하고 있다. 따라서 HTTP 서버가 80번 포트에서 요청을 기다리고 있으며, 클라이언트는 80번 포트로 요청을 보내게 된다. HTTP는 1989년 팀 버너스 리(Tim Berners Lee)에 의해 처음 설계되었으며, WWW(World-Wide-Web) 기반에서 세계적인 정보를 공유하는데 큰 역할을 하였다. -

- -- HTTPS(Hyper Text Transfer Protocol Secure) -HTTPS는 **HTTP에 데이터 암호화가 추가된 프로토콜**이다. HTTPS는 HTTP와 다르게 433번 포트를 사용하며, 네트워크 상에서 중간에 제3자가 정보를 볼 수 없도록 공개키 암호화를 지원하고 있다. -

+HTTPS는 **HTTP에 데이터 암호화가 추가된 프로토콜**이다. HTTPS는 HTTP와 다르게 443번 포트를 사용하며, 네트워크 상에서 중간에 제3자가 정보를 볼 수 없도록 공개키 암호화를 지원하고 있다. HTTP는 암호화가 추가되지 않았기 때문에 보안에 취약한 반면, HTTPS는 안전하게 데이터를 주고받을 수 있다. 하지만 HTTPS를 이용하면 암호화/복호화의 과정이 필요하기 때문에 HTTP보다 속도가 느리다. 또한 HTTPS는 인증서를 발급하고 유지하기 위한 추가 비용이 발생하다. @@ -336,27 +307,7 @@ HTTP는 암호화가 추가되지 않았기 때문에 보안에 취약한 반면 #### HTTP 요청/응답 헤더의 구조를 설명해주세요. -- **HTTP Request Headers** - - - 해당 request에 대한 추가 정보(addtional information)를 담고 있는 부분 - - ex. request 메세지 body의 총 길이(Content-Length) 등 - - Key:Value 값으로 되어있다. - - ex. HOST:google.com → Key=HOST, Value=google.com - - Headers는 크게 3부분으로 나뉜다(general headers, request headers, entity headers) - - 자주 사용되는 header 정보에는 다음이 있다. - Host - 요청이 전송되는 target의 host url - ex. google.com - User-Agent - 요청을 보내는 클라이언트의 대한 정보 - ex. 웹브라우저에 대한 정보 - Accept - 해당 요청이 받을 수 있는 응답(response) 타입 - Connection - 해당 요청이 끝난후에 클라이언트와 서버가 계속해서 네트워크 컨넥션을 유지 할것인지 아니면 끊을것인지에 대해 지시하는 부분 - Content-Type - 해당 요청이 보내는 메세지 body의 타입 - ex. JSON을 보내면 application/json - Content-Length - 메세지 body의 길이 -

- -- **HTTP Response Headers** - - Response의 headers와 동일하다. - - 다만 response에서만 사용되는 header 값들이 있다. - ex. User-Agent 대신에 Server 헤더가 사용된다. -

- -
- -
-
- -
+(TODO: 답변 작성하기) #### References @@ -384,25 +335,17 @@ HTTP는 암호화가 추가되지 않았기 때문에 보안에 취약한 반면 #### CORS가 무엇인가요? -교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다. - -> CORS 체제는 브라우저와 서버 간의 안전한 교차 출처 요청 및 데이터 전송을 지원한다.
최신 브라우저는 XMLHttpRequest 또는 Fetch와 같은 API에서 CORS를 사용하여 교차 출처 HTTP 요청의 위험을 완화 한다. +교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 **추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제**이다. -- 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행한다. -- 브라우저는 보안 상의 이유로, 스크립트에서 시작한 교차 출처 HTTP 요청을 제한한다. - - ex) domain-a.com ↔ domain-b.com 간의 요청은 CORS 정책 위반으로, 브라우저에서 요청을 제한 -- 따라서 다른 출처의 리소스를 불러오기 위해서는, 그 출처에서 교차 출처 리소스 공유에 대한 헤더(CORS)를 응답시 반환 해주어야 한다. +CORS 체제는 브라우저와 서버 간의 안전한 교차 출처 요청 및 데이터 전송을 지원한다. 최신 브라우저는 XMLHttpRequest 또는 Fetch와 같은 API에서 CORS를 사용하여 교차 출처 HTTP 요청의 위험을 완화한다. -**CORS의 동작 원리** +> **CORS의 동작 원리** 1. 기본적으로 웹은 다른 출처의 리소스를 요청할 때는 HTTP 프로토콜을 사용하여 요청을 하는데, 이때 브라우저는 요청 헤더 (request header)에 `Origin` 필드에 요청을 보내는 출처를 담아 전송한다. 2. 서버는 요청에 대한 응답을 하는데, 응답 헤더(response header)에 `Access-Control-Allow-Origin`이라는 값에 '이 리소스를 접근하는 것이 허용된 출처'를 내려준다. - 이후 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 `Access-Control-Allow-Origin`을 비교해 본 후 이 응답이 유효한 응답인지 아닌지를 결정한다. -

+3. 이후 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 `Access-Control-Allow-Origin`을 비교해 본 후 이 응답이 유효한 응답인지 아닌지를 결정한다. -
- -
+![](./img/5-network/cors.png) #### References @@ -415,55 +358,26 @@ HTTP는 암호화가 추가되지 않았기 때문에 보안에 취약한 반면 #### HTTP GET과 POST 메서드를 비교/설명해주세요. -- **GET** - -GET은 클라이언트에서 서버로 어떠한 리소스로부터 정보를 요청하기 위해 사용되는 메서드이다. - -GET을 통한 요청은 URL 주소 끝에 파라미터로 포함되어 전송되며, 이 부분을 쿼리 스트링(query string)이라고 부른다. +> **GET** -방식은 URL 끝에 `?`를 붙이고 그다음 `변수명1=값1&변수명2=값2...` 형식으로 이어 붙이면 된다. +GET은 **클라이언트에서 서버로 어떠한 리소스로부터 정보를 요청하기 위해 사용되는 메서드**이다. GET을 통한 요청은 URL 주소 끝에 파라미터로 포함되어 전송되며, 이 부분을 쿼리 스트링(query string)이라고 부른다. -> ex. `www.example.com/show?name1=value1&name2=value2` +방식은 URL 끝에 `?`를 붙이고 그다음 `변수명1=값1&변수명2=값2...` 형식으로 이어 붙이면 된다. 예를 들면 `www.example.com/show?name1=value1&name2=value2`이다. 서버에서는 `name1`과 `name2`라는 파라미터 명으로 각각 `value1`과 `value2`의 파라미터 값을 전달받을 수 있다. -서버에서는 `name1`과 `name2`라는 파라미터 명으로 각각 `value1`과 `value2`의 파라미터 값을 전달받을 수 있다. +> **POST** -- GET의 특징 +POST는 **클라이언트에서 서버로 리소스를 생성하거나 업데이트하기 위해 데이터를 보낼 때 사용되는 메서드**이다. POST는 전송할 데이터를 HTTP 메시지 body 부분에 담아서 서버로 보낸다.(body의 타입은 Content-Type 헤더에 따라 결정된다.) - - GET 요청은 캐시가 가능하다. - - GET을 통해 서버에 리소스를 요청할 때 웹 캐시가 요청을 가로채 서버로부터 리소스를 다시 다운로드하는 대신 리소스의 복사본을 반환한다. HTTP 헤더에서 cache-control 헤더를 통해 캐시 옵션을 지정할 수 있다. - - GET 요청은 브라우저 히스토리에 남는다. - - GET 요청은 북마크 될 수 있다. - - GET 요청은 길이 제한이 있다. - - GET 요청은 중요한 정보를 다루면 안 된다. - - GET은 데이터를 요청할 때만 사용된다. -

+GET에서 URL의 파라미터로 보냈던 `name1=value1&name2=value2`가 body에 담겨 보내진다 생각하면 된다. POST로 데이터를 전송할 때 길이 제한이 따로 없어 용량이 큰 데이터를 보낼 때 사용하거나 GET처럼 데이터가 외부적으로 드러나는 건 아니라서 보안이 필요한 부분에 많이 사용된다. POST를 통한 데이터 전송은 보통 HTML form을 통해 서버로 전송된다. -- **POST** +> **GET과 POST의 차이점** -POST는 클라이언트에서 서버로 리소스를 생성하거나 업데이트하기 위해 데이터를 보낼 때 사용되는 메서드이다. +- 사용목적: GET은 서버의 리소스에서 데이터를 요청할 때, POST는 서버의 리소스를 새로 생성하거나 업데이트할 때 사용한다. +- 요청에 body 유무: GET은 URL 파라미터에 요청하는 데이터를 담아 보내기 때문에 HTTP 메시지에 body가 없다. POST는 body에 데이터를 담아 보내기 때문에 당연히 HTTP 메시지에 body가 존재한다. +- 멱등성(idempotent): GET 요청은 멱등이며, POST는 멱등이 아니다. -POST는 전송할 데이터를 HTTP 메시지 body 부분에 담아서 서버로 보낸다.(body의 타입은 Content-Type 헤더에 따라 결정된다.) - -GET에서 URL의 파라미터로 보냈던 `name1=value1&name2=value2`가 body에 담겨 보내진다 생각하면 된다. - -POST로 데이터를 전송할 때 길이 제한이 따로 없어 용량이 큰 데이터를 보낼 때 사용하거나 GET처럼 데이터가 외부적으로 드러나는 건 아니라서 보안이 필요한 부분에 많이 사용된다. - -POST를 통한 데이터 전송은 보통 HTML form을 통해 서버로 전송된다. - -- POST의 특징 - - - POST 요청은 캐시 되지 않는다. - - POST 요청은 브라우저 히스토리에 남지 않는다. - - POST 요청은 북마크 되지 않는다. - - POST 요청은 데이터 길이에 제한이 없다. -

- -- **차이점** - - 사용목적: GET은 서버의 리소스에서 데이터를 요청할 때, POST는 서버의 리소스를 새로 생성하거나 업데이트할 때 사용한다. - - 요청에 body 유무: GET은 URL 파라미터에 요청하는 데이터를 담아 보내기 때문에 HTTP 메시지에 body가 없다. POST는 body에 데이터를 담아 보내기 때문에 당연히 HTTP 메시지에 body가 존재한다. - - 멱등성(idempotent): GET 요청은 멱등이며, POST는 멱등이 아니다. - -> **멱등이란?**
멱등의 사전적 정의는 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다.
GET은 리소스를 조회한다는 점에서 여러 번 요청하더라도 응답이 똑같을 것이다. 반대로 POST는 리소스를 새로 생성하거나 업데이트할 때 사용되기 때문에 멱등이 아니라고 볼 수 있다.(POST 요청이 발생하면 서버가 변경될 수 있다.) +> **💡멱등이란?** +> 멱등의 사전적 정의는 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다. GET은 리소스를 조회한다는 점에서 여러 번 요청하더라도 응답이 똑같을 것이다. 반대로 POST는 리소스를 새로 생성하거나 업데이트할 때 사용되기 때문에 멱등이 아니라고 볼 수 있다.(POST 요청이 발생하면 서버가 변경될 수 있다.) #### References @@ -475,63 +389,46 @@ POST를 통한 데이터 전송은 보통 HTML form을 통해 서버로 전송 #### 쿠키(Cookie)와 세션(Session)을 설명해주세요. -- 쿠키(Cookie) - -쿠키는 클라이언트(브라우저) 로컬에 저장되는 키와 값이 들어있는 작은 데이터 파일이다. - -사용자 인증이 유효한 시간을 명시할 수 있으며, 유효 시간이 정해지면 브라우저가 종료되어도 인증이 유지된다는 특징이 있다. +> 쿠키(Cookie) -쿠키는 클라이언트의 상태 정보를 로컬에 저장했다가 참조한다. +쿠키는 **클라이언트(브라우저) 로컬에 저장되는 키와 값이 들어있는 작은 데이터 파일**이다. 사용자 인증이 유효한 시간을 명시할 수 있으며, 유효 시간이 정해지면 브라우저가 종료되어도 인증이 유지된다는 특징이 있다. -Response Header에 Set-Cookie 속성을 사용하면 클라이언트에 쿠키를 만들 수 있다. +쿠키는 클라이언트의 상태 정보를 로컬에 저장했다가 참조하며, Response Header에 Set-Cookie 속성을 사용하면 클라이언트에 쿠키를 만들 수 있다. 쿠키는 사용자가 따로 요청하지 않아도 브라우저가 Request 시에 Request Header를 넣어서 자동으로 서버에 전송한다. -- 쿠키의 동작 방식 +쿠키는 다음과 같이 동작한다. - 1. 클라이언트가 페이지를 요청 - 2. 서버에서 쿠키를 생성 - 3. HTTP 헤더에 쿠키를 포함 시켜 응답 - 4. 브라우저가 종료되어도 쿠키 만료 기간이 있다면 클라이언트에서 보관 - 5. 같은 요청을 할 경우 HTTP 헤더에 쿠키를 함께 보냄 - 6. 서버에서 쿠키를 읽어 이전 상태 정보를 변경할 필요가 있을 때 쿠키를 업데이트하여 변경된 쿠키를 HTTP 헤더에 포함시켜 응답 -

+1. 클라이언트가 페이지를 요청 +2. 서버에서 쿠키를 생성 +3. HTTP 헤더에 쿠키를 포함 시켜 응답 +4. 브라우저가 종료되어도 쿠키 만료 기간이 있다면 클라이언트에서 보관 +5. 같은 요청을 할 경우 HTTP 헤더에 쿠키를 함께 보냄 +6. 서버에서 쿠키를 읽어 이전 상태 정보를 변경할 필요가 있을 때 쿠키를 업데이트하여 변경된 쿠키를 HTTP 헤더에 포함시켜 응답 -- 세션(Session) +> 세션(Session) -세션은 쿠키를 기반하고 있지만, 사용자 정보 파일을 브라우저에 저장하는 쿠키와 달리 세션은 서버 측에서 관리한다. - -서버에서는 클라이언트를 구분하기 위해 세션 ID를 부여하며 웹 브라우저가 서버에 접속해서 브라우저를 종료할 때까지 인증 상태를 유지한다. +세션은 쿠키를 기반하고 있지만, 사용자 정보 파일을 브라우저에 저장하는 쿠키와 달리 세션은 **서버 측에서 관리**한다. 서버에서는 클라이언트를 구분하기 위해 세션 ID를 부여하며 웹 브라우저가 서버에 접속해서 브라우저를 종료할 때까지 인증 상태를 유지한다. 접속 시간에 제한을 두어 일정 시간 응답이 없다면 정보가 유지되지 않게 설정이 가능하다. +사용자에 대한 정보를 서버에 두기 때문에 쿠키보다 보안에 좋지만, 사용자가 많아질수록 서버 메모리를 많이 차지하게 된다. 즉 동접자 수가 많은 웹 사이트인 경우 서버에 과부하를 주게 되므로 성능 저하의 요인이 된다. + +클라이언트가 Request를 보내면, 해당 서버의 엔진이 클라이언트에게 유일한 ID를 부여하는 데 이것이 세션 ID다. -사용자에 대한 정보를 서버에 두기 때문에 쿠키보다 보안에 좋지만, 사용자가 많아질수록 서버 메모리를 많이 차지하게 된다. +세션의 동작 방식은 다음과 같다. -즉 동접자 수가 많은 웹 사이트인 경우 서버에 과부하를 주게 되므로 성능 저하의 요인이 된다. +1. 클라이언트가 서버에 접속 시 세션 ID를 발급 +2. 클라이언트는 세션 ID에 대해 쿠키를 사용해서 저장하고 가지고 있음 +3. 클라이언트는 서버에 요청할 때, 이 쿠키의 세션 ID를 서버에 전달해서 사용 +4. 서버는 세션 ID를 전달받아서 별다른 작업 없이 세션 ID로 세션에 있는 클라언트 정보를 가져옴 +5. 클라이언트 정보를 가지고 서버 요청을 처리하여 클라이언트에게 응답 -클라이언트가 Request를 보내면, 해당 서버의 엔진이 클라이언트에게 유일한 ID를 부여하는 데 이것이 세션 ID다. +> **쿠키와 세션의 차이점** -- 세션의 동작 방식 - - 1. 클라이언트가 서버에 접속 시 세션 ID를 발급 - 2. 클라이언트는 세션 ID에 대해 쿠키를 사용해서 저장하고 가지고 있음 - 3. 클라이언트는 서버에 요청할 때, 이 쿠키의 세션 ID를 서버에 전달해서 사용 - 4. 서버는 세션 ID를 전달받아서 별다른 작업 없이 세션 ID로 세션에 있는 클라언트 정보를 가져옴 - 5. 클라이언트 정보를 가지고 서버 요청을 처리하여 클라이언트에게 응답 -

- -- **차이점** - - 사용자의 정보가 저장되는 위치 - - 쿠키는 서버의 자원을 전혀 사용하지 않으며, 세션은 서버의 자원을 사용한다. - - 보안 - - 쿠키는 클라이언트 로컬에 저장되기 때문에 변질되거나 request에서 스니핑 당할 우려가 있어서 보안에 취약하다. - - 세션은 쿠키를 이용해서 세션 ID만 저장하고 그것으로 구분해서 서버에서 처리하기 때문에 비교적 보안성이 좋다. - - 라이프 사이클 - - 쿠키는 만료시간이 있지만 파일로 저장되기 때문에 브라우저를 종료해도 계속해서 정보가 남아 있을 수 있다. 또한 만료 기간을 넉넉하게 잡아두면 쿠키 삭제를 할 때까지 유지될 수도 있다. - - 반면에 세션도 만료시간을 정할 수 있지만 브라우저가 종료되면 만료시간에 상관없이 삭제된다. - - 속도 - - 쿠키에 정보가 있기 때문에 서버에 요청 시 속도가 빠르다. - - 세션은 정보가 서버에 있기 때문에 처리가 요구되어 비교적 느린 속도를 낸다. +- **사용자의 정보가 저장되는 위치**: 쿠키는 서버의 자원을 전혀 사용하지 않으며, 세션은 서버의 자원을 사용한다. +- **보안**: 쿠키는 클라이언트 로컬에 저장되기 때문에 변질되거나 request에서 스니핑 당할 우려가 있어서 보안에 취약하다. 반면 세션은 쿠키를 이용해서 세션 ID만 저장하고 그것으로 구분해서 서버에서 처리하기 때문에 비교적 보안성이 좋다. +- **라이프 사이클**: 쿠키는 만료시간이 있지만 파일로 저장되기 때문에 브라우저를 종료해도 계속해서 정보가 남아 있을 수 있다. 또한 만료 기간을 넉넉하게 잡아두면 쿠키 삭제를 할 때까지 유지될 수도 있다. 반면에 세션도 만료시간을 정할 수 있지만 브라우저가 종료되면 만료시간에 상관없이 삭제된다. +- **속도**: 쿠키에 정보가 있기 때문에 서버에 요청 시 속도가 빠르다. 반면 세션은 정보가 서버에 있기 때문에 처리가 요구되어 비교적 느린 속도를 낸다. 세션은 서버의 자원을 사용하기 때문에 무분별하게 만들다 보면 서버의 메모리가 감당할 수 없어질 수가 있고 속도가 느려질 수 있기 때문에 쿠키를 함께 사용한다. @@ -545,40 +442,21 @@ Response Header에 Set-Cookie 속성을 사용하면 클라이언트에 쿠키 #### DNS가 무엇인가요? -- **Domain** - -모든 네트워크 통신에는 고유의 주소, 즉 IP 주소가 필요하다. - -이때 통신을 주고받는 주체가 되는 네트워크에 연결되어 있는 모든 장치들을 host라고 한다. - -IP는 사람이 이해하고 기억하기 어렵기 때문에 이를 위해서 각 ip에 부여한 이름이 도메인이다. - -예를 들어 210.89.164.90의 도메인은 naver.com이다. -

+모든 네트워크 통신에는 고유의 주소, 즉 IP 주소가 필요하다. 이때 통신을 주고받는 주체가 되는 네트워크에 연결되어 있는 모든 장치들을 host라고 한다. IP는 사람이 이해하고 기억하기 어렵기 때문에 이를 위해서 각 ip에 부여한 이름이 도메인(Domain)이다. 예를 들어 210.89.164.90의 도메인은 naver.com이다. -- DNS(Domain Name Service) - -DNS(Domain Name Server 또는 Domain Name Service 모두를 의미)를 통해 네트워크 통신은 IP 주소를 사용하는데 어떻게 도메인을 가지고 통신을 할 수 있다. - -DNS는 숫자로 이루어진 IP 주소와 일정한 형식을 가진 도메인을 서로 매핑 시키고 정보를 가지고 있다. - -예를 들어 네이버에 접속하기 위해 주소창에 도메인(naver.com)을 입력하면, 컴퓨터는 해당 도메인이 연결된 네임서버(DNS)로 가서 서버 IP를 요청한다. +DNS(Domain Name Server 또는 Domain Name Service 모두를 의미)는 숫자로 이루어진 IP 주소와 일정한 형식을 가진 도메인을 서로 매핑 시키고 정보를 가지고 있다. 예를 들어 네이버에 접속하기 위해 주소창에 도메인(naver.com)을 입력하면, 컴퓨터는 해당 도메인이 연결된 DNS로 가서 서버 IP를 요청한다. 요청받은 네임 서버는 해당 도메인과 연결되어 있는 서버 IP(210.89.164.90)를 찾은 후, 컴퓨터에게 알려준다. -이처럼 도메인에 연결된 서버의 주소를 찾아주는 역할이 네임서버(DNS)이다. -

+이처럼 도메인에 연결된 서버의 주소를 찾아주는 역할이 **DNS**이다. -- **브라우저가 도메인에 해당하는 IP를 찾는 순서** +> **브라우저가 도메인에 해당하는 IP를 찾는 순서** 1. local cache 안에 검색한 해당 도메인의 IP가 있는지 확인한다. 이미 해당 도메인을 방문한 적이 있다면 컴퓨터가 해당 도메인의 IP를 기억하고 있으므로 그것을 사용한다. 2. 만약 캐시에 없다면 컴퓨터 내부에 파일 형태로 존재하는 hosts 파일을 검색해서 찾는다. 해당 hosts 파일에 특정 도메인과 IP를 매핑 시켜놓으면 해당 도메인은 지정한 IP로 이동한다. 3. 만약 위의 경우에서 도메인에 대한 IP를 찾지 못하면 최종적으로 DNS를 검색한다. -

-
- -
+![](./img/5-network/dns.png) #### References @@ -613,10 +491,7 @@ DNS는 숫자로 이루어진 IP 주소와 일정한 형식을 가진 도메인 URI는 Uniform Resource Identifier의 약자로, 자원을 식별자로 취급하여 나타내는 주소를 말한다. URI의 종류로 URL과 URN이 있다. URI는 일반적으로 다음과 같은 형식을 갖고 있다. -
- -
-
+![](./img/5-network/uri.png) #### References @@ -701,10 +576,7 @@ server_socket.bind(('', server_port)) # 소켓에 주소 바인딩 > **WebSocket** -
- -
-
+![](./img/5-network/web-socket.png) `WebSocket`은 서버와 브라우저 간 연결을 유지한 상태로 데이터를 교환할 수 있도록 하는 **프로토콜**을 말한다. @@ -734,10 +606,7 @@ server_socket.bind(('', server_port)) # 소켓에 주소 바인딩 IPv4와 IPv6는 **인터넷 프로토콜(IP)의 버전**을 말하며, IPv4는 IP의 4번째 버전, IPv6는 IP의 6번째 버전을 말한다. 이 때 인터넷 프로토콜은 호스트 간 패킷 교환 네트워크에서 패킷(Packet) 혹은 데이터그램(Datagram)으로 불리는 정보를 주고받는데 사용하는 프로토콜을 말한다. -
- -
-
+![](./img/5-network/ipv4-ipv6.png) `IPv4`는 헤더에 options이 존재하고, fragmentation/reassembly 기능을 제공해 MTU(Maximum Transport Unit)을 넘는 큰 데이터그램을 쪼개 전송을 하고 도착지에서 재조합을 한다. 또한 checksum 비트도 존재하여 매 라우터마다 checksum 비트를 갱신한다. @@ -755,7 +624,7 @@ IPv4와 IPv6는 **인터넷 프로토콜(IP)의 버전**을 말하며, IPv4는 I `MAC 주소(Media Access Control Address)`는 Data Link Layer에서 통신을 위해 **네트워크 인터페이스에 할당한 식별자**를 말한다. 즉, 모든 네트워크 장비는 자신의 MAC 주소가 있으며 주소는 장비 제조업체가 할당한다. MAC 주소는 물리적 주소(Physical Address)라고 불리기도 한다. -> **MAC 주소와 IP 주소의 차이** +> **💡 MAC 주소와 IP 주소의 차이** > MAC 주소와 IP 주소 모두 통신기기의 식별자라는 것은 동일하다. 다만 MAC 주소는 제조업체가 통신기기에 부여하는 식별자이며 같은 식별자를 같는 통신기기는 없다. IP 주소는 Network Layer에서 통신을 하기 위한 주소로 보통 통신사에서 부여하며 바뀔 수 있다. #### References @@ -771,22 +640,17 @@ IPv4와 IPv6는 **인터넷 프로토콜(IP)의 버전**을 말하며, IPv4는 I #### 라우터와 스위치, 허브의 차이를 설명해주세요. -> 여기서의 네트워크는 LAN(Local Area Network)를 말합니다. +(여기서의 네트워크는 LAN(Local Area Network)를 말합니다.) -
- router switch hub -
- 출처: Network Devices - GeeksforGeeks -
+![](./img/5-network/router-switch-hub.png) -
`라우터(Router)`는 Network Layer 3계층 장비로 **네트워크 사이를 연결하는 장치**이다. 최종 도착지의 네트워크에 도착할 수 있도록 적절한 경로를 설정하여 패킷을 전송한다. `스위치(Switch)`는 Data Link Layer 2계층 장비로 **네트워크 내에서 패킷을 전송하는 장치**를 말한다. 스위치로 요청이 들어오면 IP 주소에 대응되는 MAC 주소를 찾아 해당 MAC 주소로 패킷을 전송한다. 만약 IP 주소에 대응되는 MAC 주소가 없다면 허브처럼 브로드캐스트 방식으로 패킷을 전송하고 IP 주소와 MAC 주소를 대응시킨 테이블을 갱신시킨다. `허브(Hub)`는 Physical Layer 1계층 장비로 **여러 기기를 연결하여 네트워크를 만들어주는 장치**이다. 패킷을 받으면 연결된 모든 기기에 패킷을 전송한다. -> **브로드캐스트(Broadcast)란?** +> **💡 브로드캐스트(Broadcast)란?** > 브로드캐스트란 LAN에 있는 모든 네트워크 장비들에게 보내는 통신이다. #### References @@ -819,11 +683,7 @@ SMTP는 다음의 명령어를 사용하여 메일을 주고 받는다. #### 노트북으로 `www.google.com`에 접속을 했습니다. 요청을 보내고 받기까지의 과정을 자세히 설명해주세요. -
- web page request -
- 출처: Computer Networking A Top-Down Appoarch Chapter 6.7 -
+![](./img/5-network/browser-access-trip.png) > **1단계** @@ -857,85 +717,47 @@ TCP 소켓을 생성하고 3-way handshake로 연결을 생성한다. HTTP 요 #### 여러 네트워크 topology에 대해 간단히 소개해주세요. -##### 네트워크 토폴로지 - -컴퓨터끼리 정보를 교환하고 교류하는 형태를 의미하는 네트워크에서 토폴로지는 컴퓨터들의 특정한 망구성 방식을 의미한다. +컴퓨터끼리 정보를 교환하고 교류하는 형태를 의미하는 네트워크에서 토폴로지는 **컴퓨터들의 특정한 망구성 방식**을 의미한다. 하나의 네트워크 구성 방식을 보더라도, 노드와 링크와 같은 물리적 배치로 구분하는 **물리적 토폴로지**와 노드 간의 데이터 흐름으로 구분하는 **논리적 토폴로지**로 네트워크 구성을 각각 판단할 수 있다. -##### Star - -중앙에 위치한 메인 노드를 통해 다른 노드와 소통할 수 있는 구조 - -장점 - -- 장애 발견이 쉽고 관리가 용이함 - -단점 - -- 메인 노드에 장애가 발생하면 전체 네트워크 사용 불가능 - -
- -
-
- -##### Bus - -버스라는 공통 배선을 통해 노드들이 연결되어 있어서, 한 노드의 신호가 모든 노드에 전달됨 (타겟 노드만 신호에 반응을 하고 다른 노드는 무시함) - -장점 - -- 노드 추가 및 삭제가 용이 -- 한 노드에 장애가 발생해도 다른 노드에 영향을 주지 않음 - -단점 - -- 공통 배선의 크기(대역폭)가 제한되어 있으므로 배선에 과부하가 걸릴 경우 네트워크 성능 저하 +> **Star** -
- -
-
+중앙에 위치한 메인 노드를 통해 다른 노드와 소통할 수 있는 구조이다. -##### Ring +- `장점`: 장애 발견이 쉽고 관리가 용이함 +- `단점`: 메인 노드에 장애가 발생하면 전체 네트워크 사용 불가능 -각 노드가 양 옆으로 연결된 원형 구조, 단방향으로 신호가 전달됨 +![](./img/5-network/star-topology.png) -장점 +> **Bus** -- 단방향 구조로 단순하고, 중간에 있는 노드들이 증폭기의 역할을 해줌 (거리 제약 적어짐) +버스라는 공통 배선을 통해 노드들이 연결되어 있어서, 한 노드의 신호가 모든 노드에 전달된다. (타겟 노드만 신호에 반응을 하고 다른 노드는 무시한다.) -단점 +- `장점`: 노드 추가 및 삭제가 용이하며, 한 노드에 장애가 발생해도 다른 노드에 영향을 주지 않음 +- `단점`: 공통 배선의 크기(대역폭)가 제한되어 있으므로 배선에 과부하가 걸릴 경우 네트워크 성능 저하 -- 노드 추가 및 삭제가 어려움 +![](./img/5-network/bus-topology.png) -
- -
-
+> **Ring** -##### Mesh +각 노드가 양 옆으로 연결된 원형 구조, 단방향으로 신호가 전달된다. -다수의 노드가 서로 연결된 형태 (모두 연결되면 완전 연결형, 일부만 연결되면 부분 연결형) +- `장점`: 단방향 구조로 단순하고, 중간에 있는 노드들이 증폭기의 역할을 해준다. (거리 제약 적어진다.) +- `단점`: 노드 추가 및 삭제가 어렵다. -장점 +![](./img/5-network/ring-topology.png) -- 노드의 장애에 영향받지 않으며 유연한 대처가 가능함, 안정적임 +> **Mesh** -단점 +다수의 노드가 서로 연결된 형태이다. (모두 연결되면 완전 연결형, 일부만 연결되면 부분 연결형) -- 망 구축 비용이 크고, 노드 추가에도 비용이 많이 듬 +- `장점`: 노드의 장애에 영향받지 않으며 유연한 대처가 가능하고 안정적이다. +- `단점`: 구축 비용이 크고, 노드 추가에도 비용이 많이 든다. -
- -
-
+![완전 연결형](./img/5-network/mesh-full-topology.png) -
- -
-
+![부분 연결형](./img/5-network/mesh-part-topology.png) #### References @@ -948,22 +770,19 @@ TCP 소켓을 생성하고 3-way handshake로 연결을 생성한다. HTTP 요 #### subnet mask에 대해서 설명해주세요. -##### IP 주소와 서브네팅 (subnetting) +> **IP 주소와 서브네팅 (subnetting)** -IPv4 의 경우 의 숫자로 주소를 표현하고, 이를 국가, 회사 등 잘게 나눠 어느 영역을 쓰게할 것인지 결정한다. +IPv4 의 경우 2ドル^{32}$의 숫자로 주소를 표현하고, 이를 국가, 회사 등 잘게 나눠 어느 영역을 쓰게할 것인지 결정한다. 한정된 자원이기 때문에 효율적으로 노드에 주소를 할당하는게 중요하다. 이를 위해 IP 를 쪼개는, 네트워크 파트 + 호스트 파트로 구성하는 서브네팅을 활용한다. 기본적으로 IP 주소에 따라 5 개의 클래스로 구분된다. 각 클래스에 따라 네트워크 파트와 호스트 파트가 정해진다. -
- -
-
+![](./img/5-network/network-class.png) 위와 같은 클래스 구조와 더불어 더욱 효율적인 서브네팅을 위해서 사용하는 방법이 서브넷 마스크이다. -##### 서브넷 마스크 (subnet mask) +> **서브넷 마스크 (subnet mask)** 할당된 IP 주소는 기본적으로 네트워크 파트와 호스트 파트가 정해져있다. @@ -989,10 +808,7 @@ data encapsulation 은 데이터를 보내는 송신측에서 데이터를 생 반대로 데이터를 받는 수신측에서는 데이터를 받은 후에 계층을 거슬러 올라가면서 헤더를 떼내며 데이터를 파악한다. -
- -
-
+![](./img/5-network/data-encapsulation.png) #### References @@ -1010,27 +826,21 @@ DHCP (Dynamic Host Configuration Protocol) 는 동적으로 IP 주소나 기타 DHCP 는 UDP 를 사용하여 클라이언트/서버 구조로 통신한다. 그 과정은 아래와 같다. -1. DHCP discover - : 컴퓨터가 동일 서브넷으로 브로드캐스팅(255.255.255.255) 으로 DHCP 서버를 찾음 -2. DHCP offer - : DHCP 가 사용가능한 IP 주소의 리스트를 컴퓨터에게 전달함 -3. DHCP request - : 컴퓨터가 리스트 중 하나의 IP 주소를 선택하여 서버에 전달 -4. DHCP ack - : DHCP 가 컴퓨터에게 해당 IP 주소를 허락/거절하는 메세지를 전달 +1. `DHCP discover`: 컴퓨터가 동일 서브넷으로 브로드캐스팅(255.255.255.255)으로 DHCP 서버를 찾는다. +2. `DHCP offer`: DHCP 가 사용가능한 IP 주소의 리스트를 컴퓨터에게 전달한다. +3. `DHCP request`: 컴퓨터가 리스트 중 하나의 IP 주소를 선택하여 서버에 전달한다. +4. `DHCP ack`: DHCP 가 컴퓨터에게 해당 IP 주소를 허락/거절하는 메세지를 전달한다. -##### 장점 +> **장점** -- DHCP 서버에서 자동으로 IP 를 관리해주므로 편리함 - - IP 에 변동이 있을 때, DHCP 에만 정보를 입력하면 됨 - - 자동 할당 -- 사용중인 컴퓨터에 대해서만 할당하므로 효율적임 +- DHCP 서버에서 자동으로 IP 를 관리해주므로 편리하다. IP 에 변동이 있을 때, DHCP 에만 정보를 입력하면 된다. +- 사용중인 컴퓨터에 대해서만 할당하므로 효율적이다. -##### 단점 +> **단점** -- DHCP 서버에 의존하기 때문에 서버가 다운되는 경우 모든 컴퓨터에서 인터넷을 할 수 없음 -- 초기 DHCP 세팅 시간 및 트래픽이 큼 -- 단말 컴퓨터를 끌 경우, 완전히 주소가 release 될 때 까지 해당 IP 를 사용할 수 없음 +- DHCP 서버에 의존하기 때문에 서버가 다운되는 경우 모든 컴퓨터에서 인터넷을 할 수 없다. +- 초기 DHCP 세팅 시간 및 트래픽이 크다. +- 단말 컴퓨터를 끌 경우, 완전히 주소가 release 될 때 까지 해당 IP 를 사용할 수 없다. #### References @@ -1043,22 +853,19 @@ DHCP 는 UDP 를 사용하여 클라이언트/서버 구조로 통신한다. #### routing protocol을 몇 가지 설명해주세요. (ex. link state, distance vector) -
- -
-
+![](./img/5-network/routing.png) 패킷을 전달할 때 어느 경로로 갈지 정하는 것을 라우팅이라고 한다. -##### 라우팅 경로 고정 여부 +> **라우팅 경로 고정 여부** 어떤 경로로 라우팅할지를 미리 정해두냐 동적으로 정하냐에 따라 `정적 라우팅`, `동적 라우팅` 으로 구분한다. -##### 내/외부 라우팅 +> **내/외부 라우팅** 동적 라우팅에서 AS (Auotonomous System, 하나의 네트워크 관리자에 의해 관리되는 네트워크 집단) 를 기준으로 내부적으로 동작하냐, 외부적으로 동작하냐에 따라 `내부 라우팅` (RIP, IGRP, OSPF, EIGRP) 과 `외부 라우팅` (BGP, EGP) 으로 나눈다. -##### 라우팅 테이블 관리 +> **라우팅 테이블 관리** 동적 라우팅에서 어떤 방식으로 라우팅 테이블을 관리하느냐에 따라서도 방법이 다르다. 크게 link state, distance vector 방법이 있다. @@ -1086,18 +893,18 @@ link state 를 사용하는 프로토콜로는 OSPF, IS-IS 등이 있으며, lin 이더넷은 근거리 유선 통신을 위해 사용되는 네트워킹 방법으로 [CSMA/CD](https://security-nanglam.tistory.com/193)프로토콜을 사용한다. IEEE 802.3 에 표준으로 정의되었다. -장점 +> **장점** - 적은 용량의 데이터를 보낼 때 성능이 좋다. - 비용이 적고 관리가 쉽다. - 구조가 단순하다. -단점 +> **단점** - 캐리어 충돌이 발생할 수 있다. - 충돌이 발생하면 지연이 생긴다. -\*CSMA/CD 방법을 간략히 말하자면 버스 구조로 통신을 하는데 캐리어라는 네트워킹 상의 신호를 감지하여 캐리어가 없으면 정보를 보내는 방식이다. +CSMA/CD 방법을 간략히 말하자면 버스 구조로 통신을 하는데 캐리어라는 네트워킹 상의 신호를 감지하여 캐리어가 없으면 정보를 보내는 방식이다. #### References @@ -1124,33 +931,26 @@ link state 를 사용하는 프로토콜로는 OSPF, IS-IS 등이 있으며, lin 위 세가지 개념은 모두 네트워크의 성능과 관련되어 있다. -##### delay +> **delay** 하나의 데이터 패킷이 출발 지점에서 도착 지점에 도착한 시간을 의미한다. 딜레이는 -1. Processing Delay (처리 지연) - : 라우터가 들어온 패킷의 헤더를 확인하고 처리하는데 걸리는 시간 -2. Queueing Delay (큐 지연) - : 라우터가 다른 패킷을 처리하느라 패킷이 라우터의 큐에서 대기하는 시간 -3. Transmission Delay (전송 지연) - : 라우터의 성능 (전송 속도) 에 따라 패킷이 논리회로를 통과할 때까지 걸리는 시간 -4. Propagation Delay (전파 지연) - : 라우터간 거리에 의해 발생하는 지연 시간 +- `Processing Delay (처리 지연)`: 라우터가 들어온 패킷의 헤더를 확인하고 처리하는데 걸리는 시간 +- `Queueing Delay (큐 지연)`: 라우터가 다른 패킷을 처리하느라 패킷이 라우터의 큐에서 대기하는 시간 +- `Transmission Delay (전송 지연)`: 라우터의 성능 (전송 속도) 에 따라 패킷이 논리회로를 통과할 때까지 걸리는 시간 +- `Propagation Delay (전파 지연)`: 라우터간 거리에 의해 발생하는 지연 시간 의 합으로 계산된다. -
- -
-
+![](./img/5-network/network-delay.png) -##### timing(jitter) +> **timing(jitter)** delay 의 변동을 (변화량 수준) 의미한다. 같은 스위치가 아닌 경우 패킷마다 대기 시간이 달라지므로 지터가 생긴다. -##### throughput +> **throughput** 지정된 시간동안 실제로 전송된 정보량을 의미한다. diff --git a/answers/6-operating-system.md b/answers/6-operating-system.md index fe61f5b..c005982 100644 --- a/answers/6-operating-system.md +++ b/answers/6-operating-system.md @@ -1,10 +1,4 @@ -
-

🖥️ Operating System 🖥️

-
- -> 질문은 [WeareSoft님의 tech-interview](https://github.com/WeareSoft/tech-interview)를 참고하였습니다. - ---- +> **📌 질문은 [WeareSoft님의 tech-interview](https://github.com/WeareSoft/tech-interview)를 참고하였습니다.** ## Table of Contents @@ -47,10 +41,7 @@ - 각 프로세스는 별도의 주소 공간에서 실행되며, 한 프로세스는 다른 프로세스의 변수나 자료구조에 접근할 수 없다. - 한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간의 통신(IPC, Inter-Process Communication)을 사용해야 한다. -
- -
-
+![](./img/6-operating-system/process.png) 스레드(Thread)란 프로세스가 할당받은 자원을 이용하는 실행의 단위로 프로세스와는 다른 더 작은 실행 단위 개념이다. 스레드는 프로세스의 코드에 정의된 절차에 따라 실행되는 특정한 수행 경로이다. @@ -62,9 +53,7 @@ - 각각의 스레드는 별도의 레지스터와 스택을 갖고 있지만, 힙 메모리는 서로 읽고 쓸 수 있다. - 한 스레드가 프로세스 자원을 변경하면, 다른 이웃 스레드(sibling thread)도 그 변경 결과를 즉시 볼 수 있다. -
- -
+![](./img/6-operating-system/thread.png) #### References @@ -79,42 +68,34 @@ **멀티 프로세스**란 하나의 응용프로그램을 여러 개의 프로세스로 구성하여 각 프로세스가 하나의 작업을 처리하도록 하는 것이다. -- 장점 - - 여러 개의 자식 프로세스 중 하나에 문제가 발생하면 그 자식 프로세스만 죽는 것 이상으로 다른 영향이 확산되지 않는다. -- 단점 - - Context Switching에서의 오버헤드 - - Context Switching 과정에서 캐시 메모리 초기화 등 무거운 작업이 진행되고 많은 시간이 소모되는 등의 오버헤드가 발생하게 된다. - - 프로세스는 각각의 독립된 메모리 영역을 할당받았기 때문에 프로세스 사이에서 공유하는 메모리가 없어, Context Switching가 발생하면 캐시에 있는 모든 데이터를 모두 리셋하고 다시 캐시 정보를 불러와야 한다. - - 프로세스 사이의 어렵고 복잡한 통신 기법(IPC) - - 프로세스는 각각의 독립된 메모리 영역을 할당받았기 때문에 하나의 프로그램에 속하는 프로세스들 사이의 변수를 공유할 수 없다. +- `장점`: 여러 개의 자식 프로세스 중 하나에 문제가 발생하면 그 자식 프로세스만 죽는 것 이상으로 다른 영향이 확산되지 않는다. +- `단점` + - Context Switching 과정에서 캐시 메모리 초기화 등 무거운 작업이 진행되고 많은 시간이 소모되는 등의 오버헤드가 발생하게 된다. + - 프로세스는 각각의 독립된 메모리 영역을 할당받았기 때문에 하나의 프로그램에 속하는 프로세스들 사이의 변수를 공유할 수 없다. **멀티 스레드**란 하나의 응용프로그램을 여러 개의 스레드로 구성하고 각 스레드로 하여금 하나의 작업을 처리하도록 하는 것이다. 윈도우, 리눅스 등 많은 운영체제들이 멀티 프로세싱을 지원하고 있지만 멀티 스레드를 기본으로 하고 있다. 웹 서버는 대표적인 멀티 스레드 응용 프로그램이다. -- 장점 - - 시스템 자원 소모 감소(자원의 효율성 증대) - - 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리할 수 있다. - - 시스템 처리량 증가(처리 비용 감소) - - 스레드 간 데이터를 주고받는 것이 간단해지고 시스템 자원 소모가 줄어들게 된다. - - 스레드 사이의 작업량이 작아 Context Switching이 빠르다. - - 간단한 통신 방법으로 인한 프로그램 응답 시간 단축 - - 스레드는 프로세스 내의 Stack 영역을 제외한 모든 메모리를 공유하기 때문에 통신의 부담이 적다. -- 단점 - - 주의 깊은 설계가 필요하다. - - 디버깅이 까다롭다. +- `장점` + - 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리할 수 있다. + - 스레드 간 데이터를 주고받는 것이 간단해지고 시스템 자원 소모가 줄어들게 된다. + - 스레드 사이의 작업량이 작아 Context Switching이 빠르다. + - 스레드는 프로세스 내의 Stack 영역을 제외한 모든 메모리를 공유하기 때문에 통신의 부담이 적다. +- `단점` + - 주의 깊은 설계가 필요하며, 디버깅이 까다롭다. - 단일 프로세스 시스템의 경우 효과를 기대하기 어렵다. - - 다른 프로세스에서 스레드를 제어할 수 없다.(프로세스 밖에서 스레드 각각을 제어할 수 없다.) + - 프로세스 밖에서 스레드 각각을 제어할 수 없다. - 멀티 스레드의 경우 자원 공유의 문제가 발생한다.(동기화 문제) - 하나의 스레드에 문제가 발생하면 전체 프로세스가 영향을 받는다. > **멀티 프로세스 대신 멀티 스레드를 사용하는 이유** -1. 자원의 효율성 증대 +- **자원의 효율성 증대** 프로세스 간의 Context Switching 시 단순히 CPU 레지스터 교체뿐만 아니라 RAM과 CPU 사이의 캐시 메모리에 대한 데이터까지 초기화되므로 오버헤드가 발생한다. 멀티 프로세스로 실행되는 작업을 멀티 스레드로 실행할 경우, **프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어** 자원을 효율적으로 관리할 수 있다. 스레드는 프로세스 내의 메모리를 공유하기 때문에 독립적인 프로세스와 달리 스레드 간 데이터를 주고받는 것이 간단해지고 시스템 자원 소모가 줄어들게 된다. -2. 처리 비용 감소 및 응답 시간 단축 +- **처리 비용 감소 및 응답 시간 단축** 스레드는 Stack 영역을 제외한 모든 메모리를 공유하기 때문에 프로세스 간의 통신(IPC)보다 스레드 간의 통신의 비용이 적으므로 작업들 간의 통신의 부담이 줄어든다. @@ -130,7 +111,7 @@ CPU에서 여러 프로세스를 돌아가면서 작업을 처리하는 데 이 이처럼 여러 스레드가 함께 전역 변수를 사용할 경우 발생할 수 있는 충돌을 동기화 문제라고 한다. -> Context Switching에 대한 자세한 내용은 [#14. Context Switching이 무엇인지 설명하고 과정을 나열해주세요.](#14) 참고 +Context Switching에 대한 자세한 내용은 [#14. Context Switching이 무엇인지 설명하고 과정을 나열해주세요.](#14) 참고! #### References @@ -165,9 +146,7 @@ CPU에서 여러 프로세스를 돌아가면서 작업을 처리하는 데 이 캐시 메모리의 성능은 적중률에 의해 결정된다. -
- -
+![](./img/6-operating-system/hit-rate.png) #### References @@ -313,10 +292,7 @@ if __name__=="__main__": > **스케줄링의 단계** -
- -
-
+![](./img/6-operating-system/scheduling-level.png) #### References @@ -348,7 +324,7 @@ if __name__=="__main__": `SJF(Shortest Job First)`는 비선점 스케줄러로, **CPU burst time이 가장 작은 프로세스를 먼저 처리**한다. 가장 실행시간이 적은 프로세스를 먼저 처리하기 때문에 대기 시간을 줄일 수 있지만, 실행시간을 예측한다는 점에서 비현실적이며 계속해서 짧은 프로세스만 처리하므로 긴 프로세스는 뒤로 밀린다는 단점이 있다. -`SRTF(Shortest Remaining Time First)`는 선점 스케줄러로, **잔여 실행 시간이 더 적은 프로세스를 먼저 처리**한다. SJF의 장점을 극대화 했으나, 프로세스 생성 시 총 실행 시간 예측이 필요하고 잔여 시간을 계속 추적해야 해서 ovehead가 크고 구현 및 사용이 비현실적이다. +`SRTF(Shortest Remaining Time First)`는 선점 스케줄러로, **잔여 실행 시간이 더 적은 프로세스를 먼저 처리**한다. SJF의 장점을 극대화 했으나, 프로세스 생성 시 총 실행 시간 예측이 필요하고 잔여 시간을 계속 추적해야 해서 overhead가 크고 구현 및 사용이 비현실적이다. `Priority Scheduling`은 각 프로세스에 지정된 우선순위를 기준으로 **높은 우선순위를 가진 프로세스를 먼저 처리**한다. 이 방식의 단점은 계속해서 우선순위가 높은 프로세스가 들어오면 그 프로세스를 먼저 처리하므로 낮은 프로세스는 뒤로 밀리는 starvation 문제가 발생한다. 이는 일정 시간 이상 기다리면 프로세스의 우선순위를 높여주는 aging 방식으로 해결할 수 있다. @@ -368,18 +344,11 @@ if __name__=="__main__": **비동기**는 요청 결과에 관계 없이 바로 다음 요청을 수행하고, 결과는 `콜백` 함수를 통해 받는다. 비동기는 설계가 복잡하지만 효율적이다. -
- -
-
+![](./img/6-operating-system/sync-async.png) -> [추가자료] Blocking, Non-Blocking +> **Blocking, Non-Blocking** -**Blocking** 과 **Non-Blocking** 은 결과에 대한 관점보다는 `System Call(직접 제어할 수 없는 대상의 처리)` 의 관점으로 이해할 수 있다. - -**Blocking** 은 System Call 이 완료될 때까지 Waiting Queue 에서 대기한다. - -**Non-Blocking** 은 System Call 이 완료와 상관없이 자신의 작업을 진행한다. +Blocking 과 Non-Blocking은 결과에 대한 관점보다는 `System Call(직접 제어할 수 없는 대상의 처리)` 의 관점으로 이해할 수 있다. Blocking은 System Call 이 완료될 때까지 Waiting Queue에서 대기한다. Non-Blocking은 System Call이 완료와 상관없이 자신의 작업을 진행한다. #### References @@ -396,33 +365,29 @@ if __name__=="__main__": 제한된 메모리 크기를 효율적으로 사용하기 위해 메모리 관리 전략이 필요하다. -**스왑** +> **스왑** + 프로세스가 실행되기 위해서는 메모리에 올라가야한다. 실행되어야 하는 여러 프로세스 중, 기존에 메모리에 올라간 프로세스를 보조 기억장치 (HDD, SSD) 로 보내는 것을 swap-out, 보조 기억장치에 있던 프로세스를 메모리에 올리는 것을 swap-in 이라고 한다. 어떤 프로세스를 swap-out 시킬지에 대한 대표적인 방법으로는 round-robin 이 있다. -> 스왑에 관한 더 자세한 설명 +더 자세한 설명은 [15. Swapping에 대해 설명해주세요](#15)을 참고! -- [15. Swapping에 대해 설명해주세요](#15) +> **압축** -**압축** 메모리에 프로세스들을 올리다보면 아래 사진과 같이 빈 공간(free) 이 생긴다. 이 공간을 fragmentation(단편화) 이라고 한다. 현재 메모리에서 프로세스와 단편화를 파악하고 프로세스가 연속적으로 메모리 주소에 할당되게 단편화를 없애는 방법을 압축이라 한다. 압축은 효율적이지 못하기 때문에 좋은 메모리 관리 방법이 아니다. -
- -
-
+![](./img/6-operating-system/fragmentation.png) + +> **페이징** -**페이징** 메모리에 연속적으로 프로세스를 할당하지 않고, 메모리를 페이지라는 단위로 물리적으로 나눠서 페이지에 프로세스를 올리는 방법이다. 프로세스가 페이지 크기보다 크다면 여러 페이지를 사용한다. 페이지 크기보다 작은 프로세스가 할당되면 내부적으로 공간이 남는 내부 단편화가 발생할 수 있다. -**세그멘테이션** +> **세그멘테이션** + 페이징은 물리적 단위로 메모리를 나눴다면, 세그멘테이션은 논리적 단위로 메모리를 나눈다. 이를 위해 세그멘테이션 테이블을 사용하고, 테이블에는 시작주소인 base 와 최대 크기인 limit 가 포함되어 있다. 세그멘테이션은 세그멘트 간에 할당되지 않은 공간이 남는 외부 단편화가 발생할 수 있다. -
- -
-
+![](./img/6-operating-system/segmentation.png) #### References @@ -440,10 +405,7 @@ if __name__=="__main__": **Demand Paging** 는 프로세스에서 현재 필요한 페이지만 메모리에 올리는 방법이다. 이를 위한 페이지 테이블은 기존의 테이블에서 valid 와 modified 가 추가적으로 필요하다. -
- -
-
+![](./img/6-operating-system/demand-paging.png) valid 는 해당 페이지가 메모리에서 사용되고 있는지를 나타낸다. 페이지가 메모리에 없는 경우 (valid == 0) 를 **page fault** 라고 한다. 아래의 과정으로 페이지를 메모리에 할당한다. @@ -502,29 +464,20 @@ valid 는 해당 페이지가 메모리에서 사용되고 있는지를 나타 반면에 스케줄링과 동기화를 위해 커널을 호출하는데 무겁고 오래걸린다는 단점이 있다. 또한, 커널 수준 스레드는 스케줄링 과정에서, 저장한 내용을 다시 불러오는 과정이 필요하다. 이는, 사용자 모드에서 커널 모드로의 전환이 빈번하게 이뤄져 성능 저하를 유발한다. 또한 사용자가 프로그래밍할 때 구현하기 어렵고 자원을 더 많이 소비하는 경향이 있다는 단점이 있다. -> 멀티 스레드 모델 +> **멀티 스레드 모델** -
- -
-
+![](./img/6-operating-system/multi-thread-model.png) 사용자 수준 스레드와 커널 수준 스레드에 얘기하기 전에, 멀티 스레드 모델을 먼저 이해하는 것이 좋다. 멀티 스레드 모형이 위와 같이 존재하고, 어떤 멀티 스레드 모델을 사용하느냐에 따라서, 다르게 동작하기 때문에 사용자/커널 수준 스레드 차이가 발생하는 것이다. 추가적으로, 다대다 모델과 일대일 모델과 다대일 모델을 모두 채택하여 사용하는 경우가 있는데, 이를 `혼합형 모델`이라고 한다. -> 사용자/커널 수준 스레드 구조 차이 +> **사용자/커널 수준 스레드 구조 차이** -
- -
-
+![](./img/6-operating-system/user-kernel-thread.png) -> 스레드를 생성하는 방법 +> **스레드를 생성하는 방법** -1. kernel의 지원없이 완전히 user space에서만 library를 제공하는 방법 - - 라이브러리의 함수를 호출하는 것은 시스템 호출이 아니라 사용자 공간의 지역함수를 호출한다. -2. 운영체제에 의해 kernel space에서 구현하는 방법 - - 라이브러리 API를 호출하는 것은 kernel system call을 사용한다. +- **kernel의 지원없이 완전히 user space에서만 library를 제공하는 방법**: 라이브러리의 함수를 호출하는 것은 시스템 호출이 아니라 사용자 공간의 지역함수를 호출한다. +- **운영체제에 의해 kernel space에서 구현하는 방법**: 라이브러리 API를 호출하는 것은 kernel system call을 사용한다. #### References @@ -540,42 +493,36 @@ valid 는 해당 페이지가 메모리에서 사용되고 있는지를 나타 **메모리 단편화(Memory Fragmentation)** 는 RAM에서 메모리의 공간이 작은 조각으로 나뉘어져 사용가능한 메모리가 존재하지만, 할당이 불가능한 상태를 말한다. 자세히 설명하자면, 어떤 태스크가 메모리를 할당받기 위해서는, 연속된 메모리 공간이 필요하다. 그러나 메모리 단편화가 일어나면, 할당되지 않은 메모리의 총량이 충분해도, 이들이 작은 메모리 파편(Memory Fragment)으로 존재하고 있기 때문에 메모리 할당이 불가능한 상황이 발생한다. -
- -
-
+![](./img/6-operating-system/memory-fragmentation.png) **내부 단편화(Internal Fragmentation)** 란, 메모리를 할당할 때 프로세스가 필요한 양보다 더 큰 메모리가 할당되어서 프로세스에서 사용하는 메모리 공간이 낭비 되는 상황을 말한다. 예를 들어, 메모장을 켰는데 OS가 4kb를 할당해주었다고 해보자. 그런데 실제로는 1kb만큼만 사용했다고 한다면, 필요 이상으로 프로세스가 메모리를 할당받았으므로 내부 단편화가 3kb만큼 생겼다고 할 수 있다. **외부 단편화(External Fragmentation)** 란, 작은 메모리가 중간중간에 존재해서 메모리 공간은 충분하지만 실제로 할당할 수 없는 상황을 말한다. 메모리가 할당되고 해제되는 작업이 반복될 때 작은 메모리가 중간에 생기게 된다. 이를 hole이라고 부른다. 이렇게 중간에 끼인 hole들이 많아지면, 메모리 낭비로 인해, 총 가용공간이 충분하더라도 새로운 태스크가 메모리를 할당받지 못하는 상황이 올 수 있다. 예를 들어, 위의 그림처럼 메모리의 할당과 해제의 반복으로 인해 메모리 중간에 빈 hole들이 만들어졌다고 해보자. 현재 모든 hole의 총합은 16MB 이고, 9MB짜리 프로세스를 할당하고자 한다. 빈 메모리의 공간중에 제일 큰 빈 메모리(hole)의 크기가 9MB 보다 작을 때, 외부 단편화가 일어났다고 할 수 있다. -> 메모리 할당 방법 +> **메모리 할당 방법** 메모리 할당 방법은 크게 연속할당 방식과 불연속 할당 방식으로 나뉠 수 있다. **연속할당 방식**에는 `고정분할 방식`, `가변분할 방식`이 있고, **불연속 할당 방식**에는 `페이징 기법`과 `세그멘테이션 기법`, `페이지드 세그멘테이션`(Paged Segmentations) 기법 등이 있다. -#### 메모리 단편화의 해결방법 - -1. **압축(Compaction)기법** +- **압축(Compaction)기법** 주기적으로 삭제 공간을 회수하여, 메모리 공간을 정리하는 방식이다. 그러나 비용이 많이 든다는 단점이 있다. -2. **페이징(Paging)기법** - 가상메모리사용, 외부 단편화 해결, 내부 단편화 존재 +- **페이징(Paging)기법**: 가상메모리사용, 외부 단편화 해결, 내부 단편화 존재 + +![](./img/6-operating-system/paging.png) + +쉽게말해, 프로세스를 일정한 단위로 잘라서 사용하자는 방식이다. 프로세스의 주소 공간을 동일한 크기의 페이지 단위로 나누어 물리적 메모리의 서로 다른 위치에 페이지들을 저장하는 방식을 말한다. 이때, 논리(가상) 메모리의 단위는 페이지(page), 물리 메모리의 단위는 프레임(frame)이라고 부른다. -
- -
+페이징 기법을 사용하면 연속적이지 않은 공간도 활용할 수 있기 때문에 외부 단편화 문제를 해결할 수 있다. 대신 페이지 단위에 알맞게 꽉채워 쓰는게 아니므로 내부 단편화 문제는 여전히 존재한다. 페이지 단위를 작게하면 내부 단편화 문제도 해결할 수 있겠지만 대신 page mapping 과정이 많아지므로 오히려 효율이 떨어질 수 있다. -- 쉽게말해, 프로세스를 일정한 단위로 잘라서 사용하자는 방식이다. 프로세스의 주소 공간을 동일한 크기의 페이지 단위로 나누어 물리적 메모리의 서로 다른 위치에 페이지들을 저장하는 방식을 말한다. 이때, 논리(가상) 메모리의 단위는 페이지(page), 물리 메모리의 단위는 프레임(frame)이라고 부른다. -- 페이징 기법을 사용하면 연속적이지 않은 공간도 활용할 수 있기 때문에 외부 단편화 문제를 해결할 수 있다. 대신 페이지 단위에 알맞게 꽉채워 쓰는게 아니므로 내부 단편화 문제는 여전히 존재한다. 페이지 단위를 작게하면 내부 단편화 문제도 해결할 수 있겠지만 대신 page mapping 과정이 많아지므로 오히려 효율이 떨어질 수 있다. +- **세그멘테이션(Segmentation)기법**: 가상메모리사용, 내부 단편화 해결, 외부 단편화 존재 -3. **세그멘테이션(Segmentation)기법** - 가상메모리사용, 내부 단편화 해결, 외부 단편화 존재 +![](./img/6-operating-system/segmentation-method.png) -
- -
+하나의 프로세스를 구성하는 주소 공간은 일반적으로 코드, 데이터, 스택 등의 의미 있는 단위들로 구성되며, 이렇게 기능적인 구조를 하나의 세그먼트 단위로 삼아, 분할하여 저장된다. 즉, 페이징기법에서 가상메모리를 같은 크기의 단위로 분할했지만 세그멘테이션 기법에서는 가상메모리를 서로 크기가 다른 논리적 단위인 세그먼트로 분할해서 메모리를 할당하여 실제 메모리 주소로 변환을 하게 된다. 각 세그먼트는 연속적인 공간에 저장되어 있다. 세그먼트들의 크기가 다르기 때문에 미리 분할해 둘 수 없고 메모리에 적재될 때 빈 공간을 찾아 할당해야한다. 마찬가지로 mapping을 위해 세그먼트 테이블이 필요하다. -하나의 프로세스를 구성하는 주소 공간은 일반적으로 코드, 데이터, 스택 등의 의미 있는 단위들로 구성되며, 이렇게 기능적인 구조를 하나의 세그먼트 단위로 삼아, 분할하여 저장된다. 즉, 페이징기법에서 가상메모리를 같은 크기의 단위로 분할했지만 세그멘테이션 기법에서는 가상메모리를 서로 크기가 다른 논리적 단위인 세그먼트로 분할해서 메모리를 할당하여 실제 메모리 주소로 변환을 하게 된다. 각 세그먼트는 연속적인 공간에 저장되어 있다. 세그먼트들의 크기가 다르기 때문에 미리 분할해 둘 수 없고 메모리에 적재될 때 빈 공간을 찾아 할당해야한다. 마찬가지로 mapping을 위해 세그먼트 테이블이 필요하다. 프로세스가 필요한 메모리 만큼 할당해주기 때문에 내부단편화는 일어나지 않으나 여전히 중간에 프로세스가 메모리를 해제하면 생기는 hole, 즉 외부 단편화 문제는 여전히 존재한다. +프로세스가 필요한 메모리 만큼 할당해주기 때문에 내부단편화는 일어나지 않으나 여전히 중간에 프로세스가 메모리를 해제하면 생기는 hole, 즉 외부 단편화 문제는 여전히 존재한다. #### References @@ -593,9 +540,7 @@ Context Switching이란, 현재 실행중인 프로세스의 정보를 저장하 Context Switching 과정은 다음과 같다. -
- -
+![](./img/6-operating-system/context-switching.png) 1. Interrupt나 시스템 호출에 의해 context switching 요구 2. User Mode에서 Kernel Mode로 변경 @@ -603,7 +548,7 @@ Context Switching 과정은 다음과 같다. 4. 다음에 실행할 프로세스의 상태정보를 PCB에서 복구한 후 다음 프로세스를 실행 5. Kernel Mode에서 User Mode로 변경 -> Context Switching이 발생하는 상황 +> **Context Switching이 발생하는 상황** Context Switching은 인터럽트 발생 시에 발생하고, 인터럽트는 실행 중인 CPU 사용 할당 시간을 모두 소모하거나, 입출력을 위해 대기하는 경우에 발생하며, 프로세스의 CPU 제어권이 다른 프로세스에게 이양되는 상황으로 볼 수 있다. 따라서, 프로세스 상태와도 관련이 있으며, 3가지 상태 변화에 따라 인터럽트가 발생한다. Context Switch를 하는 주체는 OS 스케줄러이다. @@ -611,11 +556,11 @@ Context Switching은 인터럽트 발생 시에 발생하고, 인터럽트는 2. `ready` → `running` 3. `running` → `waiting` -> PCB(Process Control Block) +> **PCB(Process Control Block)** 프로세스를 관리하는데 있어 필요한 정보(메타 데이터)를 담고있는 운영체제 커널의 자료구조이다. 프로세스가 생성될 때마다 고유의 PCB가 생성되며, 프로세스가 완료되면 PCB는 제거된다. PCB에는 `Process ID`, `Process State`(ex. ready, running), `Program Counter`(다음 instruction), `Register 값`, `Pointer`, `CPU scheduling/Memory/Process information` 등의 정보가 포함된다. -> Thread 단위의 Context Switching +> **Thread 단위의 Context Switching** Process는 Thread보다 Context Switching 오버헤드가 크다. Thread는 Stack 영역을 제외한 모든 메모리를 공유하기 때문이다. @@ -633,22 +578,19 @@ Process는 Thread보다 Context Switching 오버헤드가 크다. Thread는 Stac #### Swapping에 대해 설명해주세요. -스와핑(Swapping)이란, 주기억장치(메인메모리)에 적재한 하나의 프로세스와 보조기억장치(하드디스크)에 적재한 다른 프로세스의 메모리를 교체하는 기법이다. +스와핑(Swapping)이란, **주기억장치(메인메모리)에 적재한 하나의 프로세스와 보조기억장치(하드디스크)에 적재한 다른 프로세스의 메모리를 교체하는 기법**이다. 프로세스가 실행되기 위해서는, 프로세스의 명령어와 명령어가 접근하는 데이터가 메모리에 적재되어있어야 한다. 메모리가 부족하면, 메모리 내에 존재하던 기존 프로세스를 backing store(하드디스크, 보조기억장치)라는 공간으로 내릴 수 있다.(=쫒아낸다) 그리고 다시 필요할 때 메모리에 불러와서 사용할 수도 있다. 필요없는 데이터를 backing store에 저장하는 것을 swap out, 필요한 데이터를 메모리에 올리는 것을 swap in이라고 한다. (메모리 기준으로 in, out) **프로세스 단위로 swap in, swap out하는 것**을 swapping이라고 한다. -> 표준 스와핑과 페이지 단위 스와핑 +> **표준 스와핑과 페이지 단위 스와핑** -
- -
-
+![](./img/6-operating-system/swapping.png) 스와핑을 사용하면, 실제 물리 메모리보다 더 많은 프로세스를 수용할 수 있다. 스와핑의 가장 중요한 역할은 프로세스의 수를 조절하여, 다중 프로그래밍의 정도(degree of muliprogramming)를 조절 할 수 있다는 것이다. 유휴 상태가 오래 지속되는 프로세스가 스와핑에 적합하며, swap out 될 대상 프로세스는 스와퍼(swapper)라고 불리는 **중기 스케쥴러**(medium-term scheduler)에 의해 선정된다. 주의할 점은, 스와핑이라는 개념이 프로세스가 종료되어 그 주소 공간을 디스크로 내쫓는 것이 아니라, 특정한 이유로 수행 중인 프로세스의 주소 공간을 일시적으로 메모리에서 디스크로 내려놓는 것을 의미한다는 것이다. 그러나 위와 같이 프로세스 단위로 스와핑하는 표준 스와핑 방법은 최근에 많이 사용되지 않는다. 메모리와 저장장치 사이에 프로세스 전체를 이동시키는 것이 힘들기 때문이다. 대신, 페이지 단위 스와핑을 이용한다. -> Backing Store +> **Backing Store** 스왑 영역(swap area)라고도 부르며, 디스크 내에 파일 시스템과는 별도로 존재하는 일정 영역을 말한다. 프로세스가 수행중인 동안에만 디스크에 일시적으로 저장하는 공간이므로 저장 기간이 상대적으로 짧은 저장공간이다. 다수의 사용자 프로세스를 담을 수 있을 만큼 충분히 큰 저장공간이어야 하고 어느 정도의 접근 속도가 보장되어야 한다는 특징이 있다. diff --git a/answers/7-data-structure.md b/answers/7-data-structure.md index ff28f05..2bad380 100644 --- a/answers/7-data-structure.md +++ b/answers/7-data-structure.md @@ -1,10 +1,4 @@ -
-

🗂 Data Structure 🗂

-
- -> 질문은 [WeareSoft님의 tech-interview](https://github.com/WeareSoft/tech-interview)를 참고하였으며, 질문에 대한 답변은 직접 작성하였습니다. - ---- +> **📌 질문은 [WeareSoft님의 tech-interview](https://github.com/WeareSoft/tech-interview)를 참고하였으며, 질문에 대한 답변은 직접 작성하였습니다.** ## Table of Contents @@ -34,38 +28,29 @@ #### linked list -array는 데이터가 연속적인 공간에 존재해야 한다는 특징이 있으나, linked list는 서로 떨어져 있는 데이터를 메모리 주소를 참조함으로써, 이어진 것처럼 사용할 수 있다. linked list는 구조체가 이어진 형태로 존재하며, 이 구조체를 `노드`라고 부른다. 노드는 값을 담고 있는 `데이터 필드`와 다음 구조체를 가리키는 `링크 필드(포인터)`로 구성된다. 정확히는, 포인터가 다음 구조체의 주소를 담고 있다. 보통, linked list의 맨 첫 원소를 가리키는 head 포인터와 맨 마지막 원소를 가리키는 tail 포인터를 통해, 리스트의 요소에 접근하거나 수정한다. linked list는 구현 방법에 따라, single linked list와 double linked list, circular linked list 등으로 구분할 수 있다. +linked list는 서로 떨어져 있는 데이터를 메모리 주소를 참조함으로써 이어진 것처럼 사용할 수 있다. linked list는 구조체가 이어진 형태로 존재하며, 이 구조체를 `노드`라고 부른다. 노드는 값을 담고 있는 `데이터 필드`와 다음 구조체를 가리키는 `링크 필드(포인터)`로 구성된다. 정확히는, 포인터가 다음 구조체의 주소를 담고 있다. 보통, linked list의 맨 첫 원소를 가리키는 head 포인터와 맨 마지막 원소를 가리키는 tail 포인터를 통해, 리스트의 요소에 접근하거나 수정한다. linked list는 구현 방법에 따라, single linked list와 double linked list, circular linked list 등으로 구분할 수 있다. -> Array vs. Linked list +> **Array vs. Linked list** array에서 중간에 값을 삽입하고 싶다면, 삽입할 위치 뒤의 모든 데이터가 한 칸씩 이동해야 한다는 단점이 있다. 또한, array가 할당받은 공간이 부족한데, 메모리상 뒤쪽의 메모리가 비어있지 않으면, 모든 데이터가 더 큰 홀로 이사를 가야 한다는 단점도 존재한다. linked list는 연속된 공간을 사용하지 않아도 되기 때문에 앞서 언급했던 array의 단점을 모두 해소할 수 있다. 그러나 N번째 데이터를 참조하고 싶을 때, 계속해서 다음 주소를 참조하는 형식으로 따라가야 하므로 메모리 참조에 시간이 오래 걸린다. 따라서 삽입과 삭제가 빈번한 경우에는 linked list를 사용하고, 참조가 빈번하게 일어날 때는 array를 쓰는 것이 바람직하다. -> Time Complexity 비교 +> **Time Complexity 비교** -- array - - insert: O(N) - - delete: O(N) - - find: O(1) -- list - - insert: O(1) - - delete: O(1) - - find: O(N) +| 구분 | Array | Linked List | +| :------: | :------: | :---------: | +| `insert` | $O(n)$ | $O(1)$ | +| `delete` | $O(n)$ | $O(1)$ | +| `find` | $O(1)$ | $O(n)$ | -> 삽입, 삭제, 접근 방법 +> **삽입, 삭제, 접근 방법** -- 접근 - - 원하는 원소가 나올때까지 링크 필드(포인터, 다음 노드)를 계속해서 탐색한다. -- 삽입 - 1. 삽입할 노드의 next에 현재 위치의 next를 연결한다. - 2. 현재 위치의 next에 삽입할 노드의 주소를 넣어준다. -- 삭제 - - 삭제할 노드의 next를 앞선 노드의 next에 연결해준다. +- 접근: 원하는 원소가 나올때까지 링크 필드(포인터, 다음 노드)를 계속해서 탐색한다. +- 삽입: 삽입할 노드의 next에 현재 위치의 next를 연결한 후, 현재 위치의 next에 삽입할 노드의 주소를 넣어준다. +- 삭제: 삭제할 노드의 next를 앞선 노드의 next에 연결해준다. -> 기본적인 linked list 구조 (=Single linked list 구조) +> **기본적인 linked list 구조 (=Single linked list 구조)** -
- -
+![](./img/7-data-structure/basic-linked-list.png) --- @@ -73,9 +58,7 @@ array에서 중간에 값을 삽입하고 싶다면, 삽입할 위치 뒤의 모 #### single linked list -
- -
+![](./img/7-data-structure/single-linked-list.png) [#1 Linked list](#1)에서 언급한 내용은 모두 Single linked list에 해당한다. Single linked list는 linked list 중에서도 가장 기본적인 구조로 되어 있으며, head에서 tail까지 단방향으로 포인터가 이어져 있으므로 N 번째 노드에서 N-1 번째 노드에 접근할 수 없다. 대신, 다시 head로부터 N-1 번의 탐색을 통해 접근해야 한다. @@ -89,9 +72,7 @@ array에서 중간에 값을 삽입하고 싶다면, 삽입할 위치 뒤의 모 #### double linked list -
- -
+![](./img/7-data-structure/double-linked-list.png) [#1-1 Single linked list](#1-1)은 단방향 연결이기 때문에 한번 다음 노드로 이동하면, 이전 노드로 돌아가기 힘들다는 단점이 있었다. 그러나 Double linked list는 뒤의 노드의 주소뿐만 아니라, 이전 노드의 주소도 담고 있다. 하나의 노드는 하나의 데이터와 두 개의 링크를 가지고 있으며, 각각의 링크를 prev와 next라고 부른다. 다음 노드를 참조하고 싶다면 next 링크가 담고 있는 주소를 확인하면 되고, 이전의 노드를 참조하고 싶다면 prev 링크가 가지는 주소를 확인하면 된다. @@ -105,9 +86,7 @@ array에서 중간에 값을 삽입하고 싶다면, 삽입할 위치 뒤의 모 #### circular linked list -
- -
+![](./img/7-data-structure/circular-linked-list.png) 앞서 언급했던 linked list 유형들과는 다르게, tail이 다시 head를 가리키는 구조를 가지고 있다. 따라서, tail 노드의 next에는 NULL이 들어가는 것 대신, head의 주소가 들어간다. @@ -123,23 +102,17 @@ array에서 중간에 값을 삽입하고 싶다면, 삽입할 위치 뒤의 모 해시 테이블은 (Key, Value)로 데이터를 저장하는 자료구조 중 하나로 빠르게 데이터를 검색할 수 있는 자료구조이다. 해시 테이블이 빠른 검색속도를 제공하는 이유는 내부적으로 배열(버킷)을 사용하여 데이터를 저장하기 때문이다. 해시 테이블은 각각의 Key값에 해시함수를 적용해 배열의 고유한 index를 생성하고, 이 index를 활용해 값을 저장하거나 검색하게 된다. 여기서 실제 값이 저장되는 장소를 버킷 또는 슬롯이라고 한다. -
- -
-
+![](./img/7-data-structure/hash-table.png) 예를 들어, `(Key, Value)쌍` 구조를 가지는 데이터 `("John Smith", "521-1234")`를 크기가 16인 해시 테이블에 저장한다고 하자. 그러면 먼저 `index = hash_function("John Smith") % 16` 연산을 통해 index 값을 계산한다. 그리고 `array[index] = "521-1234"` 로 value를 저장하게 된다. 이러한 구조로 데이터를 저장하면 Key값으로 데이터를 찾을 때 해시 함수를 1번만 수행하면 되므로 매우 빠르게 데이터를 저장/삭제/조회할 수 있다. 해시테이블의 평균 시간복잡도는 O(1)이다. -> 해시(Hash)값이 충돌하는 경우 +> **해시(Hash)값이 충돌하는 경우** 만약 "John Smith"를 해시 함수를 돌려 나온 값과 "Sandra Dee"를 해시 함수를 돌려 나온 값이 동일하다면, 아래와 같이 해결할 수 있다. **해결방법 1: Separate Chaining(분리 연결법)** -
- -
-
+![](./img/7-data-structure/separate-chaining.png) 동일한 버킷의 데이터에 대해 자료구조를 활용해 추가 메모리를 사용하여 다음 데이터의 주소를 저장하는 방법이다. 동일한 해시 값을 가지면, 동일한 버킷 안에 엔트리를 할당해줘야한다. 이 때, 버킷 내부의 엔트리 값들은 linked list 형태로 이어준다. 이러한 Chaining 방식은 해시 테이블의 확장이 필요없고 간단하게 구현이 가능하며, 손쉽게 삭제할 수 있다는 장점이 있다. 하지만 데이터의 수가 많아지면 동일한 버킷에 chaining되는 데이터가 많아지며 그에 따라 캐시의 효율성이 감소한다는 단점이 있다. @@ -153,11 +126,11 @@ Open Addressing이란 추가적인 메모리를 사용하는 Chaining 방식과 충돌을 방지하는 방법들은 데이터의 규칙성(클러스터링)을 방지하기 위한 방식이지만 공간을 많이 사용한다는 치명적인 단점이 있다. 만약 테이블이 꽉 차있는 경우라면 테이블을 확장해주어야 하는데, 이는 매우 심각한 성능의 저하를 불러오기 때문에 가급적이면 확정을 하지 않도록 테이블을 설계해주어야 한다. (통계적으로 해시 테이블의 공간 사용률이 70% ~ 80%정도가 되면 해시의 충돌이 빈번하게 발생하여 성능이 저하되기 시작한다고 한다.) 또한 해시 테이블에서 자주 사용하게 되는 데이터를 Cache에 적용하면 효율을 높일 수 있다. 자주 hit하게 되는 데이터를 캐시에서 바로 찾음으로써 해시 테이블의 성능을 향상시킬 수 있다. -> Time Complexity +> **시간 복잡도** + +삽입, 삭제, 탐색에 대해 해시 충돌이 일어나지 않는 경우에 $O(1),ドル 충돌이 일어난다면 최악의 경우에 $O(N)$의 시간 복잡도를 가진다. -- 삽입, 삭제, 탐색 - - 해시 충돌이 일어나지 않는 경우에 O(1), 충돌이 일어난다면 최악의 경우에 O(N)의 시간 복잡도를 가진다. - - O(N): 해시 충돌로 인해서 하나의 버킷에 여러 엔트리가 연결되어있는 경우에 모든 엔트리를 탐색해야할 수 있다. +왜냐하면 해시 충돌로 인해서 하나의 버킷에 여러 엔트리가 연결되어있는 경우에 모든 엔트리를 탐색해야할 수 있기 때문이다. #### References @@ -169,14 +142,9 @@ Open Addressing이란 추가적인 메모리를 사용하는 Chaining 방식과 #### stack -**LIFO (Last In First Out)** 구조의 자료형으로 한 쪽으로만 데이터를 넣고 뺄 수 있다. +![](./img/7-data-structure/stack.png) -`push` 명령으로 데이터를 넣고, `pop` 명령으로 가장 마지막에 들어간 데이터를 빼낸다. - -
- -
-
+**LIFO (Last In First Out)** 구조의 자료형으로 한 쪽으로만 데이터를 넣고 뺄 수 있다. `push` 명령으로 데이터를 넣고, `pop` 명령으로 가장 마지막에 들어간 데이터를 빼낸다. stack 은 브라우저의 뒤로가기 기능, ctrl + z (되돌리기), 지역 변수와 매개변수를 저장하는 stack 메모리 등에 사용된다. 이외에도 DFS 알고리즘 등 다양한 곳에 사용되는 자료형이다. @@ -193,15 +161,11 @@ stack 에 데이터가 꽉 차서 더 넣을 공간이 없는데 데이터를 pu #### queue -**FIFO (First In First Out)** 구조의 자료형으로 출구(front)와 입구(rear or back)가 따로 존재하여 먼저 입력된 데이터가 먼저 반환된다. +![](./img/7-data-structure/queue.png) -`push` 명령으로 rear 에 자료를 넣는다. rear += 1 되어 다음에 데이터를 받을 메모리를 가리켜야 한다. -`pop` 명령으로 front 에서 데이터를 빼낸다. front += 1 되어 다음에 데이터를 반환할 메모리를 가리켜야 한다. +**FIFO (First In First Out)** 구조의 자료형으로 출구(front)와 입구(rear or back)가 따로 존재하여 먼저 입력된 데이터가 먼저 반환된다. -
- -
-
+`push` 명령으로 rear 에 자료를 넣는다. rear += 1 되어 다음에 데이터를 받을 메모리를 가리켜야 한다. `pop` 명령으로 front 에서 데이터를 빼낸다. front += 1 되어 다음에 데이터를 반환할 메모리를 가리켜야 한다. queue 는 CPU 연산처리 작업대기, 프린터 인쇄, 프로세스 관리 등 들어온 순서를 보장해야하는 경우 사용된다. 이외에도 BFS 알고리즘 등에 사용된다. @@ -218,14 +182,11 @@ queue 의 rear 가 기리키는 공간에 데이터가 있는데 데이터를 pu #### circular queue -크기가 N 인 queue 에서 모든 원소를 다 채우면 rear 는 N-1 을 가리킨다. 이 때, pop 으로 제일 처음 원소를 제거하면 queue 에 남은 공간 1개가 생긴다. 하지만 rear 는 마지막을 가리키고 있기 때문에 더이상 원소를 추가할 수 없다. 이 문제를 해결하기 위해 원형 형태의 `circular queue` 를 사용한다. queue 와 같이 FIFO 구조의 자료형이다. +![](./img/7-data-structure/circular-queue.png) -
- -
-
+크기가 N 인 queue 에서 모든 원소를 다 채우면 rear 는 N-1 을 가리킨다. 이 때, pop 으로 제일 처음 원소를 제거하면 queue 에 남은 공간 1개가 생긴다. 하지만 rear 는 마지막을 가리키고 있기 때문에 더이상 원소를 추가할 수 없다. 이 문제를 해결하기 위해 원형 형태의 `circular queue` 를 사용한다. queue 와 같이 FIFO 구조의 자료형이다. -> 동작 방식 +동작 방식은 다음과 같다. - 처음에는 front 와 rear 가 같은 메모리를 가리킨다. - 데이터를 입력하기 위해 rear 는 메모리가 꽉찼는지 검사한다. 꽉찬 경우는 rear 다음 번의 메모리가 front 를 가리키는 경우 (rear + 1 == front) 인데, 꽉차지 않았다면 데이터를 입력하고 rear 는 다음 메모리로 이동한다. @@ -243,43 +204,27 @@ queue 의 rear 가 기리키는 공간에 데이터가 있는데 데이터를 pu 그래프는 정점과 간선으로 이루어진 자료구조이다. 정점 간의 연결관계는 간선으로 나타낸다. -##### 그래프의 종류 +> **그래프의 종류** -
- -
-
+![](./img/7-data-structure/graph.png) 간선이 담고있는 정보와 연결 상태에 따라 그래프의 종류가 나뉜다. 두 정점을 연결하는 간선에 방향이 없다면 `무방향 그래프`, 두 정점을 연결하는 간선에 방향이 존재하면 `방향 그래프`라고 부른다. 방향 그래프는 간선의 방향으로만 이동할 수 있다. 두 정점을 이동할 때 비용이 발생하면 `가중치 그래프`로 나타낼 수 있다. 모든 정점이 간선으로 연결된 경우, `완전 그래프`라고 부른다. -##### 그래프 구현 방식 +> **그래프 구현 방식** + +첫 번째로 **인접행렬 방식**이 있다. 노드를 인덱스로 삼는 2차원 배열을 만들어 각 노드가 간선으로 연결되어있으면 배열에 1을 넣어주고, 연결되지 않았다면 0을 넣어주면 된다. -
- -
-
+두 노드의 연결관계를 조회할 때, $O(1)$ 시간이 걸린다. 그러나 모든 정점에 대해, 간선 정보를 입력해야하므로 초기화에 $O(N^2)$ 시간이 소요된다. -- 인접행렬 방식 - - 노드를 인덱스로 삼는 2차원 배열을 만든다. - - 각 노드가 간선으로 연결되어있으면 배열에 1을 넣어주고, 연결되지 않았다면 0을 넣어준다. - - 두 노드의 연결관계를 조회할 때, O(1) 시간이 걸린다. - - 그러나 모든 정점에 대해, 간선 정보를 입력해야하므로 초기화에 시간이 소요된다. -- 노드의 수가 많고, 간선의 수가 적은 그래프의 경우에, 공간을 낭비하게 된다. +노드의 수가 많고, 간선의 수가 적은 그래프의 경우에, 공간을 낭비하게 된다. -
- -
-
+![](./img/7-data-structure/adjacent-matrix.png) -- 인접리스트 방식 - - 그래프의 노드들을 리스트로 표현한다. head 노드와 연결된 노드들을 링크에 달아준다. - - 한 정점에 연결된 노드들의 정보를 얻기 위해서 O(M) 시간이 걸린다.(M: 간선의 수) - - 간선 정보만 유지하므로, 공간 낭비가 적다. - - 두 정점이 연결되었는지 확인하기 위해서 O(M) 시간이 걸리며, 구현이 비교적 어렵다. +두 번째로 **인접리스트 방식**이 있다. 그래프의 노드들을 리스트로 표현한다. head 노드와 연결된 노드들을 링크에 달아주면 된다. -##### 그래프 용어 +한 정점에 연결된 노드들의 정보를 얻기 위해서 $O(M)$ 시간이 걸린다.(M은 간선의 수) 간선 정보만 유지하므로, 공간 낭비가 적으나 두 정점이 연결되었는지 확인하기 위해서 $O(M)$ 시간이 걸리며, 구현이 비교적 어렵다. -그래프에서 사용하는 용어는 다음과 같다. +> **그래프 용어** - `정점(vertice)` : 노드(node)라고도 하며 정점에는 데이터가 저장된다. - `간선(edge)`: 링크(arcs)라고도 하며 노드간의 관계를 나타낸다. @@ -299,9 +244,7 @@ queue 의 rear 가 기리키는 공간에 데이터가 있는데 데이터를 pu #### tree -tree는 그래프의 일종으로, 부모 노드 밑에 여러 자식 노드가 연결되고, 자식 노드 각각에 다시 자식 노드가 연결되는 재귀적 형태의 자료구조이다. 노드들은 서로 다른 자식 노드를 가지며 이때 각 노드는 재사용 되지 않는다. - -> 특징 +tree는 그래프의 일종으로, 부모 노드 밑에 여러 자식 노드가 연결되고, 자식 노드 각각에 다시 자식 노드가 연결되는 재귀적 형태의 자료구조이다. 노드들은 서로 다른 자식 노드를 가지며 이때 각 노드는 재사용 되지 않는다. 트리는 다음과 같은 특징을 갖는다. - 반드시 하나의 루트 노드만이 존재한다. - 모든 자식 노드는 한 개의 부모 노드만을 가진다. @@ -309,27 +252,25 @@ tree는 그래프의 일종으로, 부모 노드 밑에 여러 자식 노드가 - 사이클을 가지는 노드 집합이 존재하지 않는다. - 노드가 N개인 트리는 항상 N-1개의 간선을 가진다. -> 용어 - -
- -

- -- 노드(node): 트리를 구성하는 기본 원소 -- 루트 노드(root node/root): 트리에서 부모가 없는 최상위 노드, 트리의 시작점 -- 부모 노드(parent node): 루트 노드 방향으로 직접 연결된 노드 -- 자식 노드(child node): 루트 노드 반대 방향으로 직접 연결된 노드 -- 형제 노드(siblings node): 같은 부모 노드를 갖는 노드들 -- 잎 노드(leaf node)/단말 노드(terminal node): 자식이 없는 노드 -- 경로(path): 한 노드에서 다른 한 노드에 이르는 길 사이에 있는 노드들의 순서 -- 길이(length): 출발 노드에서 도착 노드까지 거치는 노드의 개수 -- 깊이(depth): 루트 경로의 길이 -- 레벨(level): 루트 노드(level=1)부터 노드까지 연결된 링크 수의 합 -- 높이(height): 가장 긴 루트 경로의 길이 -- 차수(degree): 각 노드의 자식의 개수 -- 트리의 차수(degree of tree): 트리의 최대 차수 = max[deg1, deg2, ..., degn] -- 크기(size): 노드의 개수 -- 너비(width): 가장 많은 노드를 갖고 있는 레벨의 크기 +> **트리 용어** + +![](./img/7-data-structure/tree-terms.png) + +- `노드(node)`: 트리를 구성하는 기본 원소 +- `루트 노드(root node/root)`: 트리에서 부모가 없는 최상위 노드, 트리의 시작점 +- `부모 노드(parent node)`: 루트 노드 방향으로 직접 연결된 노드 +- `자식 노드(child node)`: 루트 노드 반대 방향으로 직접 연결된 노드 +- `형제 노드(siblings node)`: 같은 부모 노드를 갖는 노드들 +- `잎 노드(leaf node)/단말 노드(terminal node)`: 자식이 없는 노드 +- `경로(path)`: 한 노드에서 다른 한 노드에 이르는 길 사이에 있는 노드들의 순서 +- `길이(length)`: 출발 노드에서 도착 노드까지 거치는 노드의 개수 +- `깊이(depth)`: 루트 경로의 길이 +- `레벨(level)`: 루트 노드(level=1)부터 노드까지 연결된 링크 수의 합 +- `높이(height)`: 가장 긴 루트 경로의 길이 +- `차수(degree)`: 각 노드의 자식의 개수 +- `트리의 차수(degree of tree)`: 트리의 최대 차수 = max[deg1, deg2, ..., degn] +- `크기(size)`: 노드의 개수 +- `너비(width)`: 가장 많은 노드를 갖고 있는 레벨의 크기 #### References @@ -344,13 +285,11 @@ tree는 그래프의 일종으로, 부모 노드 밑에 여러 자식 노드가 #### binary tree -
- -

+![](./img/7-data-structure/binary-tree.png) 이진 트리(binary tree)는 각각의 노드가 최대 두 개의 자식 노드를 가지는 트리를 말한다. 즉, 모든 노드의 차수(degree)가 2 이하인 트리를 말한다. 이진 트리의 모든 서브 트리들은 모두 이진 트리이다. -> 순회(Traversal) 방법 +> **순회(Traversal) 방법** - 전위 순회(preorder) 1. 노드를 방문한다. @@ -379,9 +318,7 @@ tree는 그래프의 일종으로, 부모 노드 밑에 여러 자식 노드가 #### full binary tree -
- -

+![](./img/7-data-structure/full-binary-tree.png) full binary tree는 단말 노드들을 제외한 모든 노드들이 2개의 자식 노드를 가지는 binary tree이다. @@ -395,9 +332,7 @@ full binary tree는 단말 노드들을 제외한 모든 노드들이 2개의 #### complete binary tree -
- -

+![](./img/7-data-structure/complete-binary-tree.png) 완전 이진 트리(complete binary tree)는 마지막 level을 제외한 나머지 level에 노드들이 가득 차있고, 마지막 level에서 노드는 가장 왼쪽부터 채워지는 형태의 binary tree이다. @@ -411,9 +346,7 @@ full binary tree는 단말 노드들을 제외한 모든 노드들이 2개의 #### bst(binary search tree) -
- -

+![](./img/7-data-structure/bst.png) 이진 탐색 트리(binary search tree)는 아래의 성질을 갖고 있는 이진 트리이다. @@ -422,32 +355,30 @@ full binary tree는 단말 노드들을 제외한 모든 노드들이 2개의 - 노드의 오른쪽 서브트리에는 그 노드의 값보다 큰 값들을 지닌 노드들로 이루어져 있다. - 좌우 서브트리는 각각이 다시 이진 탐색 트리여야 한다. -> 탐색(Search) +> **탐색(Search)** -- 검색하고자 하는 값을 루트 노드와 먼저 비교하고, 일치할 경우 루트 노드를 리턴한다. - - 불일치하고 검색하고자 하는 값이 루트 노드의 값보다 작을 경우 왼쪽 서브트리에서 재귀적으로 검색한다. - - 불일치하고 검색하고자 하는 값이 루트 노드의 값보다 큰 경우 오른쪽 서브트리에서 재귀적으로 검색한다. +검색하고자 하는 값을 루트 노드와 먼저 비교하고, 일치할 경우 루트 노드를 리턴한다. -> 삽입(Insert) +- 불일치하고 검색하고자 하는 값이 루트 노드의 값보다 작을 경우 왼쪽 서브트리에서 재귀적으로 검색한다. +- 불일치하고 검색하고자 하는 값이 루트 노드의 값보다 큰 경우 오른쪽 서브트리에서 재귀적으로 검색한다. -- 삽입을 하기 전, 탐색을 수행한다. -- 트리를 탐색한 후 키와 일치하는 노드가 없으면 마지막 노드에서 키와 노드의 크기를 비교해서 왼쪽이나 오른쪽에 새로운 노드를 삽입한다. +> **삽입(Insert)** -> 삭제(Delete) +삽입을 하기 전, 탐색을 수행한다. 트리를 탐색한 후 키와 일치하는 노드가 없으면 마지막 노드에서 키와 노드의 크기를 비교해서 왼쪽이나 오른쪽에 새로운 노드를 삽입한다. -삭제하려는 노드의 자식 수에 따라 +> **삭제(Delete)** -- 자식 노드가 없는 노드(리프 노드) 삭제: 해당 노드를 단순히 삭제한다. -- 자식 노드가 1개인 노드 삭제: 해당 노드를 삭제하고 그 위치에 해당 노드의 자식 노드를 대입한다. -- 자식 노드가 2개인 노드 삭제: 삭제하고자 하는 노드의 값을 해당 노드의 왼쪽 서브트리에서 가장 큰 값으로 변경하거나, 오른쪽 서브트리에서 가장 작은 값으로 변경한 뒤, 해당 노드(왼쪽 서브트리에서 가장 큰 값을 가지는 노드 또는 오른쪽 서브트리에서 가장 작은 값을 가지는 노드)를 삭제한다. +삭제하려는 노드의 자식 수에 따라 -> 복잡도 +- **자식 노드가 없는 노드(리프 노드) 삭제**: 해당 노드를 단순히 삭제한다. +- **자식 노드가 1개인 노드 삭제**: 해당 노드를 삭제하고 그 위치에 해당 노드의 자식 노드를 대입한다. +- **자식 노드가 2개인 노드 삭제**: 삭제하고자 하는 노드의 값을 해당 노드의 왼쪽 서브트리에서 가장 큰 값으로 변경하거나, 오른쪽 서브트리에서 가장 작은 값으로 변경한 뒤, 해당 노드(왼쪽 서브트리에서 가장 큰 값을 가지는 노드 또는 오른쪽 서브트리에서 가장 작은 값을 가지는 노드)를 삭제한다. -BST의 탐색, 삽입, 삭제의 복잡도는 모두 이다. (h: BST의 높이(height)) +> **시간 복잡도** -BST는 평균 시간 복잡도가 이지만 최악의 경우 이다. (skewed tree 이면 node의 수만큼 시간이 소요됨) +BST의 탐색, 삽입, 삭제의 복잡도는 모두 $O(h)$이다. (h는 BST의 높이) BST는 평균 시간 복잡도가 $O(\log_2 n)$이지만 최악의 경우 $O(n)$이다. (skewed tree 이면 node의 수만큼 시간이 소요됨) -- tree가 complete binary tree 거나 full binary tree 이면 , skewed tree 이면 +트리가 complete binary tree 거나 full binary tree 이면 $O(\log_2 n),ドル skewed tree 이면 $O(n)$의 시간복잡도를 갖는다. #### References @@ -461,11 +392,9 @@ BST는 평균 시간 복잡도가 힙(heap)
- 최대값 및 최소값을 찾아내는 연산을 빠르게 하기 위해 고안된 완전 이진 트리를 기본으로 한 자료구조로서 다음의 속성을 만족한다. -- A가 B의 부모 노드이면, A의 키값과 B의 키값 사이에는 대소관계가 성립한다. +> A가 B의 부모 노드이면, A의 키값과 B의 키값 사이에는 대소관계가 성립한다. heap의 종류에는 [min heap](#7-1), [max heap](#7-2)이 있다. @@ -473,20 +402,16 @@ heap의 종류에는 [min heap](#7-1), [max heap](#7-2)이 있다. 힙에서는 가장 높은(혹은 가장 낮은) 우선순위를 가지는 노드가 항상 루트 노드에 오게 되는 특징이 있으며, 이를 응용하여 우선순위 큐와 같은 추상적 자료형을 구현할 수 있다. -이진 힙(binary heap) +> 이진 힙(binary heap) -이진 힙은 다음과 같은 두 가지 특징을 갖는다. - -트리를 T, 임의 내부 노드를 v라고 하면 다음과 같다. +이진 힙은 다음과 같은 두 가지 특징을 갖는다. 트리를 T, 임의 내부 노드를 v라고 하면 다음과 같다. 1. 루트 노드를 제외한 각 내부 노드는 `key(T.parent(v)) < key(v)` 또는 `key(T.parent(v))> key(v)`이다. (즉, 키 값은 오름차순이거나 내림차순이다.) 2. 마지막 왼쪽 결합 노드들의 레벨을 제외한 다른 모든 레벨들은 완전 이진 트리를 형성한다. 힙 리스트(heap list)로 표현할 때 i번째 노드의 왼쪽 자식 노드의 위치는 2i가 되며, i번째 노드의 오른쪽 자식 노드의 위치는 2i+1이고, 또한 i번째 노드의 부모 노드의 위치는 i/2가 된다. -> 복잡도 - - +이진 힙의 시간복잡도는 $O(\log n)$이다. #### References @@ -498,13 +423,13 @@ heap의 종류에는 [min heap](#7-1), [max heap](#7-2)이 있다. #### min heap -
- -

+![](./img/7-data-structure/min-heap.png) 최소 힙(min heap)은 부모 노드의 키 값이 자식 노드의 키 값보다 작거나 같은 완전 이진 트리이다. -- key(부모 노드) key(자식 노드) +$$ +key(부모 노드) \leq key(자식 노드) +$$ #### References @@ -516,13 +441,13 @@ heap의 종류에는 [min heap](#7-1), [max heap](#7-2)이 있다. #### max heap -
- -

+![](./img/7-data-structure/max-heap.png) 최대 힙(max heap)은 부모 노드의 키 값이 자식 노드의 키 값보다 크거나 같은 완전 이진 트리이다. -- key(부모 노드) key(자식 노드) +$$ +key(부모 노드) \geq key(자식 노드) +$$ #### References @@ -536,13 +461,9 @@ heap의 종류에는 [min heap](#7-1), [max heap](#7-2)이 있다. > **레드-블랙트리의 정의** -
- 레드-블랙 트리 -
- 출처: Red-black tree - Wikipedia -
+![](./img/7-data-structure/red-black-tree.png) -레드-블랙 트리(Red-Black Tree)는 이진탐색트리(Binary Search Tree)의 한 종류로, 삽입(insert), 삭제(delete), 검색(retrieval) 연산을 에 수행하도록 보장하는 **균형 잡힌 트리**를 말한다. 즉, 트리의 높이가 이 되도록 한다. +레드-블랙 트리(Red-Black Tree)는 이진탐색트리(Binary Search Tree)의 한 종류로, 삽입(insert), 삭제(delete), 검색(retrieval) 연산을 $O(\log N)$에 수행하도록 보장하는 **균형 잡힌 트리**를 말한다. 즉, 트리의 높이가 $\log N$이 되도록 한다. 레드-블랙 트리는 **다음의 조건**을 만족한다. @@ -576,11 +497,7 @@ heap의 종류에는 [min heap](#7-1), [max heap](#7-2)이 있다. > **B-트리의 정의** -
- B트리 -
- 출처: B-tree Definition - Wikimedia -
+![](./img/7-data-structure/b-tree.png) B-트리는 이진 트리(Binary Tree)를 확장해 모든 리프 노드들이 같은 높이를 갖도록 하는 트리이다. 노드 내에 여러 개의 key가 있을 수 있으며, 최대 key의 개수에 따라 2개이면 2차 B-트리, N개면 N차 B-트리라고 부른다. diff --git a/answers/8-algorithm.md b/answers/8-algorithm.md index bbf9314..1b50751 100644 --- a/answers/8-algorithm.md +++ b/answers/8-algorithm.md @@ -1,10 +1,4 @@ -
-

🔻 Algorithm 🔻

-
- -> 질문은 [WeareSoft님의 tech-interview](https://github.com/WeareSoft/tech-interview)를 참고하였으며, 질문에 대한 답변은 직접 작성하였습니다. - ---- +> **📌 질문은 [WeareSoft님의 tech-interview](https://github.com/WeareSoft/tech-interview)를 참고하였습니다.** ## Table of Contents @@ -48,22 +42,13 @@ 알고리즘의 복잡도는 점근적 표기법으로 나타내는데, 점근적 표기법에는 대표적으로 O(빅오), Ω(오메가), Θ(세타)가 있다. -- O Noation (빅오 표기법) - - 점근적 상한선 - - 최악의 경우 -- Ω Notation (오메가 표기법) - - 점근적 하한선 - - 최상의 경우 -- θ Notation (세타 표기법) - - 점근적 상한선과 점근적 하한선의 교집합 - - 평균의 경우 +- O Notation (빅오 표기법): 점근적 상한선 / 최악의 경우 +- Ω Notation (오메가 표기법): 점근적 하한선 / 최상의 경우 +- θ Notation (세타 표기법): 점근적 상한선과 점근적 하한선의 교집합 / 평균의 경우 일반적으로 최악의 경우의 성능을 측정하는 빅오 표기법을 많이 사용한다. -
- -
-
+![](./img/8-algorithm/complexity.png) #### References @@ -79,18 +64,17 @@ 버블 정렬(Bubble Sort)은 배열의 0번부터 N-1번까지 탐색을 하면서 인접한 칸과 비교하여 swap을 하는 방식의 정렬 알고리즘이다. -
- -
-
+![](./img/8-algorithm/bubble-sort.png) 위의 과정이 버블 정렬을 1회 실시하고 나서의 결과이다. j번째 값과 j+1번째 값을 비교해서 만약 j번째 값이 더 크다면 swap을 해주는 식으로 동작한다. -> 시간 복잡도 +> **시간 복잡도** - +$$ +O(N^2) +$$ -> 파이썬 구현 +> **파이썬 구현** ```python def bubbleSort(alist): @@ -116,18 +100,17 @@ def bubbleSort(alist): 선택 정렬(Selection Sort)은 위치 변경 횟수를 줄여, 버블 정렬을 일부 개선한 기법이다. 주어진 배열 중에 최댓값을 찾아 정렬되지 않은 배열의 맨 뒤의 값과 자리를 바꾸어나가는 정렬 알고리즘이다. 배열의 맨 뒤부터 차례로 정렬이 된다. -
- -
-
+![](./img/8-algorithm/selection-sort.png) -버블 정렬은 왼쪽에 있는 값이 비교 대상인 오른쪽에 있는 값보다 크면 자리를 바꿔줬는데 반해, 선택 정렬은 일단 최댓값(혹은 최솟값)을 찾은 뒤에야 이 값을 정해진 위치로 보내주게 된다. 다시 말해 비교 횟수 측면에서는 버블 정렬과 선택 정렬이 같고 둘 모두 의 계산 복잡성을 갖지만 자리 이동(swap)측면에서는 선택 정렬이 효율적이다. +버블 정렬은 왼쪽에 있는 값이 비교 대상인 오른쪽에 있는 값보다 크면 자리를 바꿔줬는데 반해, 선택 정렬은 일단 최댓값(혹은 최솟값)을 찾은 뒤에야 이 값을 정해진 위치로 보내주게 된다. 다시 말해 비교 횟수 측면에서는 버블 정렬과 선택 정렬이 같고 둘 모두 $O(n^2)$의 계산 복잡성을 갖지만 자리 이동(swap)측면에서는 선택 정렬이 효율적이다. -> 시간 복잡도 +> **시간 복잡도** - +$$ +O(N^2) +$$ -> 파이썬 구현 +> **파이썬 구현** ```python def selectionSort(alist): @@ -156,18 +139,15 @@ def selectionSort(alist): 삽입 정렬(Insertion Sort)은 배열의 모든 요소를 배열의 시작부터 끝까지 현재 배열의 요소들과 비교해 가면서 적절한 위치에 삽입하는 정렬 알고리즘이다. -
- -
-
+![](./img/8-algorithm/insertion-sort.png) -> 시간 복잡도 +> **시간 복잡도** -- 최악의 경우(Worst): -- 평균적인 경우(Average): -- 최선의 경우(Best): +- 최악의 경우(Worst): $O(N^2)$ +- 평균적인 경우(Average): $O(N^2)$ +- 최선의 경우(Best): $O(N)$ -> 파이썬 구현 +> **파이썬 구현** ```python def insertion_sort(collection): @@ -198,16 +178,15 @@ def insertion_sort(collection): - Conquer: 각 부분 배열을 재귀적으로 병합 정렬을 사용하여 정렬한다. - Merge: 부분 배열을 하나의 배열로 결합한다. -
- -
-
+![](./img/8-algorithm/merge-sort.png) -> 시간 복잡도 +> **시간 복잡도** - +$$ +O(N \log N) +$$ -> 파이썬 구현 +> **파이썬 구현** ```python def merge_sort(list): @@ -235,22 +214,21 @@ def merge_sort(list): 힙 정렬(Heap Sort)은 완전 이진 트리로 구현되는 정렬 방식으로, 모든 노드가 힙 속성(각 노드의 값이 자신의 자식 노드 값보다 큰 이진 트리)을 만족하도록 재귀적으로 트리 구조를 만들어 정렬을 완성하는 정렬 알고리즘이다. -
- -
-
+![](./img/8-algorithm/heap-sort.png) -> 동작 원리 +> **동작 원리** 1. 주어진 원소들로 최대 힙을 구성한다. 2. 현재 힙의 루트 노드에는 최대값이 존재하게 된다. 루트의 값을 마지막 요소와 바꾼 후, 힙의 사이즈를 하나 줄인다. 3. 힙의 사이즈가 1보다 크면 위 과정을 반복한다. -> 시간 복잡도 +> **시간 복잡도** - +$$ +O(N \log N) +$$ -> 파이썬 구현 +> **파이썬 구현** ```python def heapify(unsorted, index, heap_size): @@ -287,22 +265,19 @@ def heap_sort(unsorted): #### Quick Sort -퀵 정렬(Quick Sort)는 pivot을 기준으로 pivot 앞에는 pivot보다 작은 값, 뒤에는 큰 값이 오도록 하여 배열을 분할하고, 분할된 두 개 배열 각각에 재귀적으로 이 과정을 반복해 정렬을 완성하는 정렬 알고리즘이다. 합병 정렬과 달리 주어진 배열을 임의로 나누지 않기 때문에 대개는 효율적이지만, pivot이 잘못 선택되면 복잡도가 이 될 수도 있다. +퀵 정렬(Quick Sort)는 pivot을 기준으로 pivot 앞에는 pivot보다 작은 값, 뒤에는 큰 값이 오도록 하여 배열을 분할하고, 분할된 두 개 배열 각각에 재귀적으로 이 과정을 반복해 정렬을 완성하는 정렬 알고리즘이다. 합병 정렬과 달리 주어진 배열을 임의로 나누지 않기 때문에 대개는 효율적이지만, pivot이 잘못 선택되면 복잡도가 $O(n^2)$이 될 수도 있다. -
- -
-
+![](./img/8-algorithm/quick-sort.png) 위의 과정이 퀵 정렬을 1회 실시하고 나서의 결과이다. 54(pivot)를 기준으로 두 개의 배열로 나뉜다. -> 시간 복잡도 +> **시간 복잡도** -- 최악의 경우(Worst): -- 평균적인 경우(Average): -- 최선의 경우(Best): +- 최악의 경우(Worst): $O(N^2)$ +- 평균적인 경우(Average): $O(N \log N)$ +- 최선의 경우(Best): $O(N \log N)$ -> 파이썬 구현 +> **파이썬 구현** ```python def quickSort(alist): @@ -360,22 +335,23 @@ def partition(alist, first, last): 계수 정렬(Counting Sort)은 입력값의 빈도를 세어서 이를 결과 리스트의 인덱스로 활용하고 입력 리스트의 요소값에 해당하는 결과 리스트 인덱스 위치에 채워 넣는 방식으로 정렬을 완성하는 정렬 알고리즘이다. 입력 리스트의 최댓값(k)이 커질수록 복잡도가 크게 높아진다. -
- -
-
+![](./img/8-algorithm/counting-sort.png) -> 동작 원리 +> **동작 원리** 1. 각 데이터의 개수를 모두 count 한다. 2. 최솟값부터 각 값까지의 count 누적합을 구한다. 3. 새로운 배열에 누적합의 개수를 줄여주며 저장한다. -> 시간 복잡도 +> **시간 복잡도** + +$$ +O(N+k) +$$ - , : 데이터의 최댓값 +($k$: 데이터의 최댓값) -> 파이썬 구현 +> **파이썬 구현** ```python def counting_sort(A, k): @@ -409,16 +385,17 @@ def counting_sort(A, k): 기수 정렬(Radix Sort)은 입력값의 자릿수(d) 각각에 대해 카운팅 정렬을 적용하여 입력 데이터의 최댓값인 k가 커질수록 효율이 떨어지는 카운팅 정렬의 단점을 보완한 정렬 알고리즘이다. 10진법으로 표현된 입력값에 기수 정렬을 적용하면 k 값이 9로 작아진다. -
- -
-
+![](./img/8-algorithm/radix-sort.png) -> 시간 복잡도 +> **시간 복잡도** - : 입력값의 자릿수 +$$ +d \times O(N) +$$ -> 파이썬 구현 +($d$: 입력값의 자릿수) + +> **파이썬 구현** ```python from math import log @@ -554,38 +531,36 @@ def fibb(n): #### Graph Traversal: BFS, DFS -##### BFS(Breadth-First Search, 너비우선탐색) +> **BFS(Breadth-First Search, 너비우선탐색)** BFS는 그래프 전체를 탐색하는 방법 중 하나로써, 현재 확인하는 노드의 인접한 노드들을 먼저 탐색하는 것이다. 시작 정점으로부터 가까운 정점을 먼저 방문하고 멀리 떨어져 있는 정점을 나중에 방문하는 순회하는 방식으로 노드를 탐색한다. 주로 구현은 Queue라는 자료구조에 이웃하는 정점을 다 담아놓고 차례대로 pop을 하는 방식으로 구현한다. 주로 두 노드 사이의 최단 경로 혹은 임의의 경로를 찾고 싶을 때 이 방법을 사용한다. -- BFS의 장점 - 1. 노드의 수가 적고 깊이가 얕은 경우 빠르게 동작할 수 있다. - 2. 단순 검색 속도가 깊이 우선 탐색(DFS)보다 빠르다. - 3. 너비를 우선 탐색하기에 답이 되는 경로가 여러개인 경우에도 최단경로임을 보장한다. - 4. 최단경로가 존재한다면 어느 한 경로가 무한히 깊어진다해도 최단경로를 반드시 찾을 수 있다. -- BFS의 단점 - 1. 재귀호출의 DFS와는 달리 큐에 다음에 탐색할 정점들을 저장해야 하므로 저장공간이 많이 필요하다. - 2. 노드의 수가 늘어나면 탐색해야하는 노드 또한 많아지기에 비현실적이다. +- `장점` + - 노드의 수가 적고 깊이가 얕은 경우 빠르게 동작할 수 있다. + - 단순 검색 속도가 깊이 우선 탐색(DFS)보다 빠르다. + - 너비를 우선 탐색하기에 답이 되는 경로가 여러개인 경우에도 최단경로임을 보장한다. + - 최단경로가 존재한다면 어느 한 경로가 무한히 깊어진다해도 최단경로를 반드시 찾을 수 있다. +- `단점` + - 재귀호출의 DFS와는 달리 큐에 다음에 탐색할 정점들을 저장해야 하므로 저장공간이 많이 필요하다. + - 노드의 수가 늘어나면 탐색해야하는 노드 또한 많아지기에 비현실적이다. -##### DFS(Depth-First Search, 깊이우선탐색) +> **DFS(Depth-First Search, 깊이우선탐색)** DFS는 그래프 전체를 탐색하는 방법중 하나로써, 시작점 부터 다음 분기(branch)로 넘어가기 전에 해당 분기를 완벽하게 탐색하고 넘어가는 방법이다. 먼저 보이는 노드부터 계속해서 깊이를 늘려가며 탐색하고, 더 이상 탐색할 노드가 없다면 이전 노드로 돌아가서 다른 브랜치를 다시 깊이 파보는 형식을 말한다. Stack이나 재귀함수를 통해서 구현할 수 있는데, 재귀함수가 구현이 간편하다. -- DFS의 장점 - 1. 현재 경로 상의 노드들만 기억하면 되므로, 저장 공간의 수요가 비교적 적다. - 2. 목표 노드가 깊은 단계에 있는 경우에도 해를 빨리 구할 수 있다. - 3. 구현이 너비 우선 탐색(BFS) 보다 간단하다. -- DFS의 단점 - 1. 단순 검색 속도는 너비 우선 탐색(BFS) 보다 느리다. - 2. 깊이 우선 탐색은 해를 구하면 탐색이 종료되므로, 구한 해가 최단 경로가 된다는 보장이 없다. 목표에 이르는 경로가 다수인 경우, DFS를 통해 구한 해가 최적이 아닐 수 있다. DFS를 사용하여 최단 경로를 구하기 위해서는, 모든 경로를 전부 확인해보아야 한다. +- `장점` + - 현재 경로 상의 노드들만 기억하면 되므로, 저장 공간의 수요가 비교적 적다. + - 목표 노드가 깊은 단계에 있는 경우에도 해를 빨리 구할 수 있다. + - 구현이 너비 우선 탐색(BFS) 보다 간단하다. +- `단점` + - 단순 검색 속도는 너비 우선 탐색(BFS) 보다 느리다. + - 깊이 우선 탐색은 해를 구하면 탐색이 종료되므로, 구한 해가 최단 경로가 된다는 보장이 없다. 목표에 이르는 경로가 다수인 경우, DFS를 통해 구한 해가 최적이 아닐 수 있다. DFS를 사용하여 최단 경로를 구하기 위해서는, 모든 경로를 전부 확인해보아야 한다. -> BFS와 DFS의 탐색 순서 +> **BFS와 DFS의 탐색 순서** -
- -
+![](./img/8-algorithm/bfs-dfs.png) -> 주의해야할 것 +> **주의해야할 것** 노드를 Queue 혹은 Stack에 넣을 때, 방문 여부를 반드시 표시해주어야 한다. 그렇지 않으면, 자료구조에 노드가 중복되게 들어갈 수 있기 때문이다. 방문 표시를 하지 않으면, 심한 경우에는 무한루프에 빠질 수도 있다. @@ -600,7 +575,7 @@ DFS는 그래프 전체를 탐색하는 방법중 하나로써, 시작점 부터 #### Shortest Path -한 노드에서 다른 노드로 가는 엣지에 cost 가 있는 그래프가 주어졌을 때, 한 지점 -> 목표 지점 또는 모든 지점 -> 모든 지점까지 cost 가 가장 적게 드는 최단 경로를 찾는 문제이다. +한 노드에서 다른 노드로 가는 엣지에 cost 가 있는 그래프가 주어졌을 때, 한 지점 → 목표 지점 또는 모든 지점 → 모든 지점까지 cost 가 가장 적게 드는 최단 경로를 찾는 문제이다. 대표적인 알고리즘으로 `Dijkstra`, `Floyd-Warshall`, `Bellman-Ford` 가 있다. @@ -612,14 +587,16 @@ DFS는 그래프 전체를 탐색하는 방법중 하나로써, 시작점 부터 기본 다익스트라 알고리즘은 출발 노드에서 다른 노드로 가는 최단 거리를 기록하는 최단 거리 테이블과 해당 노드 방문 여부를 살피는 visited 테이블을 사용한다. -> 동작 방식 0) 최단 거리 테이블에 출발 노드는 0, 나머지 노드는 INF 로 초기화 +> **동작 방식** + +최단 거리 테이블에 출발 노드는 0, 나머지 노드는 INF 로 초기화한다. 1. 먼저 출발 노드를 방문(visited[start] = True)하고 출발 노드에서 갈 수 있는 다른 노드들까지의 거리를 최단 거리 테이블에 기록한다. 2. 최단 거리 테이블을 보고 가장 거리가 짧은 노드를 방문한다(visited에 기록). 3. 해당 노드와 연결된 노드 중 방문하지 않은 노드에 대해 현재까지 거리 + 방문하지 않은 노드까지 거리가 최단 거리 테이블의 거리보다 짧다면 최단 거리 테이블을 갱신한다. 4. 모든 노드에 방문할 때까지 2 와 3 과정을 반복한다. -위 알고리즘의 시간 복잡도는 O(V^2) (V : 노드 개수) 이다. 모든 노드에 대해 방문하고 테이블을 모두 살펴보기 때문이다. 이를 개선하기 위해 최단 거리를 찾을 때 `우선순위 큐`를 사용하고 큐에서 꺼낸 거리보다 최단거리 테이블의 값이 더 작다면 방문한 것으로 간주한다. `우선순위 큐`를 사용한 시간 복잡도는 O(ElogV) (V : 노드 개수, E : 엣지 개수) 이다. +위 알고리즘의 시간 복잡도는 $O(V^2)$ ($V$ : 노드 개수) 이다. 모든 노드에 대해 방문하고 테이블을 모두 살펴보기 때문이다. 이를 개선하기 위해 최단 거리를 찾을 때 `우선순위 큐`를 사용하고 큐에서 꺼낸 거리보다 최단거리 테이블의 값이 더 작다면 방문한 것으로 간주한다. `우선순위 큐`를 사용한 시간 복잡도는 $O(ElogV)$ ($V$: 노드 개수, $E$: 엣지 개수) 이다. ```python import heapq @@ -685,16 +662,15 @@ DFS는 그래프 전체를 탐색하는 방법중 하나로써, 시작점 부터 모든 지점에서 모든 지점까지의 최단 경로를 구하는 알고리즘이다. -A -> B 를 거리를 구할 때, 특정 노드 X 를 중간에 거쳐 가는 값과 기존의 최단 경로 테이블 값 중 어느 것이 짧은지 비교하는 것이 핵심이다. 이 과정에서 X 를 모든 노드로 바꿔가며 진행하면 된다. +A → B 를 거리를 구할 때, 특정 노드 X 를 중간에 거쳐 가는 값과 기존의 최단 경로 테이블 값 중 어느 것이 짧은지 비교하는 것이 핵심이다. 이 과정에서 X 를 모든 노드로 바꿔가며 진행하면 된다. -모든 노드에 대해 해당 노드를 거쳐 가는 경우를 계산하므로 플로이드-워셜 알고리즘의 시간 복잡도는 O(V^3) (V : 노드 개수)이다. +모든 노드에 대해 해당 노드를 거쳐 가는 경우를 계산하므로 플로이드-워셜 알고리즘의 시간 복잡도는 $O(V^3)$($V$: 노드 개수)이다. 다익스트라가 그리디한 방식이었다면, 플로이드-워셜은 점화식을 통해 테이블을 갱신하기 때문에 DP 를 사용하는 방식이다. -
- -
-
+$$ +D_{ab} = min(D_{ab}, D_{ak} + D_{kb}) +$$ ```python INF = int(1e9) # 무한을 의미하는 값으로 10 억을 설정 @@ -745,17 +721,13 @@ for a in range(1, n+1): 다익스트라 알고리즘은 간선이 음수인 경우 음수 사이클에 빠질 수 있기 때문에 사용할 수 없다. 벨만 포드 알고리즘을 사용하면 음수 사이클을 찾을 수 있다. -기본적인 개념은 **모든 엣지**를 거치면서 최단거리를 찾는 것이다. 이 작업을 모든 노드에 대해 진행한다. 시간 복잡도는 O(VE) (V : 노드 개수, E : 엣지 개수) 이다. - -**과정** +기본적인 개념은 **모든 엣지**를 거치면서 최단거리를 찾는 것이다. 이 작업을 모든 노드에 대해 진행한다. 시간 복잡도는 $O(VE)$($V$: 노드 개수, $E$: 엣지 개수) 이다. 1. 출발 노드를 설정한다. 2. 최단 거리 테이블을 출발 노드는 0 나머지는 INF 로 초기화한다. -3. V-1 번 아래 과정을 수행한다. - -- 모든 E 를 확인하며 테이블 값보다 (현재 노드 최단거리 + 현재노드에서 해당 노드로 가는 거리)가 작다면 테이블을 갱신한다. +3. 모든 $E$를 확인하며 테이블 값보다 (현재 노드 최단거리 + 현재노드에서 해당 노드로 가는 거리)가 작다면 테이블을 갱신하는 것을 $V-1$번 반복한다. -이후 음수 사이클을 확인하기 위해서는 3 의 과정을 한 번만 더 수행한다. 이 때, 테이블이 갱신된다면 음수 사이클이 있는 것이다. +이후 음수 사이클을 확인하기 위해서는 3의 과정을 한 번만 더 수행한다. 이 때, 테이블이 갱신된다면 음수 사이클이 있는 것이다. 다익스트라 알고리즘은 최적의 해를 찾는데 비해, 벨만 포드 알고리즘은 모든 간선을 모든 노드 개수만큼 반복하는 점에서 비효율적이다. 하지만 음수 사이클을 처리할 수 있는 점이 특징이다. @@ -809,13 +781,13 @@ else: #### Minimum Spanning Tree -##### Spanning Tree +> **Spanning Tree** Spanning Tree(신장 트리)란 그래프에서 일부 간선을 선택해서 만든, 그래프 내의 모든 정점을 포함하는 트리를 말한다. Spanning Tree는 그래프의 `최소 연결 부분 그래프` 이다. `최소 연결`의 의미는 간선의 수가 가장 적다는 것이다. n개의 정점을 가지는 그래프가 모두 이어지기 위해서는 최소 (n-1)개의 간선이 필요하다. n개의 노드를 가지는 그래프에서 (n-1)개의 간선으로 연결되어 있으면 필연적으로 트리 형태가 되고, 이를 spanning tree라고 부른다. 또한, 트리 형식을 만족해야하므로 사이클을 포함해서는 안된다. DFS, BFS을 통해 탐색 도중에 사용된 간선만 모아서 이어주면, 그래프에서 신장 트리를 찾을 수 있다. 하나의 그래프에는 많은 신장 트리가 존재할 수 있다. -##### Minimum Spanning Tree +> **Minimum Spanning Tree** MST(Minimum Spanning Tree, 최소 신장 트리)란 Spanning Tree 중에서 사용된 간선들의 가중치 합이 최소인 트리를 말한다. @@ -841,13 +813,11 @@ Prim 알고리즘이란 시작 정점에서부터 출발하여 신장트리 집 - 즉, 가장 낮은 가중치를 먼저 선택한다. - 위의 과정을 트리가 (N-1)개의 간선을 가질 때까지 반복한다. -Prim 알고리즘의 시간 복잡도는, 주 반복문이 정점의 수 n만큼 반복하고, 내부 반복문이 n번 반복되므로, 이다. +Prim 알고리즘의 시간 복잡도는, 주 반복문이 정점의 수 n만큼 반복하고, 내부 반복문이 n번 반복되므로, $O(n^2)$이다. -> Prim 알고리즘의 수행 단계 +> **Prim 알고리즘의 수행 단계** -
- -
+![](./img/8-algorithm/prim.png) #### References @@ -873,13 +843,11 @@ Kruskal 알고리즘의 동작방법은 아래와 같다. - 사이클을 형성하는 간선을 제외한다. - 해당 간선을 현재의 MST(최소 비용 신장 트리)의 집합에 추가한다. -Kruskal 알고리즘의 시간 복잡도는 O(elog2e)이다. +Kruskal 알고리즘의 시간 복잡도는 $O(e \log_2 e)$이다. -> Kruskal 알고리즘 수행 단계 +> **Kruskal 알고리즘 수행 단계** -
- -
+![](./img/8-algorithm/kruskal.png) #### References @@ -932,7 +900,7 @@ Kruskal 알고리즘의 시간 복잡도는 O(elog2e)이다. 구현 방법은 [위상 정렬 - 이것이 취업을 위한 코딩테스트다](https://github.com/ndb796/python-for-coding-test/blob/master/10/6.py) 구현 코드를 참고! -> **진입 차수(degree)** +> **💡 진입 차수(degree)** > 노드의 관점에서 들어오는 간선의 개수를 진입 차수(degree)라고 한다. #### References diff --git a/answers/img/1-statistics-math/beta-distribution.png b/answers/img/1-statistics-math/beta-distribution.png new file mode 100644 index 0000000..da29dc0 Binary files /dev/null and b/answers/img/1-statistics-math/beta-distribution.png differ diff --git a/answers/img/1-statistics-math/eigen-vector.png b/answers/img/1-statistics-math/eigen-vector.png new file mode 100644 index 0000000..33e7e43 Binary files /dev/null and b/answers/img/1-statistics-math/eigen-vector.png differ diff --git a/answers/img/1-statistics-math/facebook-bayes-rule.png b/answers/img/1-statistics-math/facebook-bayes-rule.png new file mode 100644 index 0000000..7085039 Binary files /dev/null and b/answers/img/1-statistics-math/facebook-bayes-rule.png differ diff --git a/answers/img/1-statistics-math/facebook-probability.png b/answers/img/1-statistics-math/facebook-probability.png new file mode 100644 index 0000000..5709f44 Binary files /dev/null and b/answers/img/1-statistics-math/facebook-probability.png differ diff --git a/answers/img/1-statistics-math/gamma-distribution.png b/answers/img/1-statistics-math/gamma-distribution.png new file mode 100644 index 0000000..d7c0e25 Binary files /dev/null and b/answers/img/1-statistics-math/gamma-distribution.png differ diff --git a/answers/img/1-statistics-math/gaussian-normal-distribution.png b/answers/img/1-statistics-math/gaussian-normal-distribution.png new file mode 100644 index 0000000..6ebbde0 Binary files /dev/null and b/answers/img/1-statistics-math/gaussian-normal-distribution.png differ diff --git a/answers/img/3-deep-learning/batch-normalization.png b/answers/img/3-deep-learning/batch-normalization.png index 07c6665..19d8ad3 100644 Binary files a/answers/img/3-deep-learning/batch-normalization.png and b/answers/img/3-deep-learning/batch-normalization.png differ diff --git a/answers/statistics-math-distribution.md b/answers/statistics-math-distribution.md index 436f801..d6a7e7c 100644 --- a/answers/statistics-math-distribution.md +++ b/answers/statistics-math-distribution.md @@ -17,11 +17,11 @@ #### 베르누이 분포 -우선 베르누이 시행이란 결과가 두 가지 중 하나만 나오는 것을 말한다. 베르누이 확률변수는 시행결과가 0 또는 1이 나오므로 이산확률변수이다. +우선 베르누이 시행이란 결과가 두 가지 중 하나만 나오는 것을 말한다. 베르누이 확률변수는 시행결과가 0ドル$ 또는 1ドル$이 나오므로 이산확률변수이다. -- `pmf` : -- `expectation` : -- `variance` : +- `pmf` : $Bern(x;\theta) = \theta^x(1-\theta)^{1-x}$ +- `expectation` : $E[X] = \theta$ +- `variance` : $Var[X] = \theta ( 1-\theta)$ #### References @@ -34,11 +34,11 @@ #### 이항 분포 -베르누이 시행을 N번 시행한 것을 말한다. 예를 들어, 동전 던지기를 10번 던져서 앞면이 나온 횟수를 확률 변수로 둔다. 마찬가지로 시행 결과가 횟수로 나오므로 이산확률변수이다. +베르누이 시행을 $N$번 시행한 것을 말한다. 예를 들어, 동전 던지기를 10번 던져서 앞면이 나온 횟수를 확률 변수로 둔다. 마찬가지로 시행 결과가 횟수로 나오므로 이산확률변수이다. -- `pmf` : -- `expectation` : -- `variance` : +- `pmf` : $Bin(x;N, \theta) = \binom{N}{x} \theta^N (1-\theta)^{N-x}$ +- `expectation` : $E[X] = N\theta$ +- `variance` : $Var[X] = N\theta ( 1-\theta)$ #### References @@ -53,15 +53,22 @@ 카테고리 분포(Categorical distribution)는 베르누이 분포를 확장한 개념이다. 즉 카테고리 시행(여러개의 카테고리 중 하나를 선택하는 실험)의 결과는 카테고리 분포를 따르게 된다. 카테고리 분포를 누적하면 다항분포를 얻게 된다. -카테고리 확률변수는 one-hot vector로 표현할 수 있다. 예를 들어, 주사위의 경우 K=6인 카테고리 분포를 따른다고 표기할 수 있다. 눈이 2인 주사위면이 나왔다고 할때, 이때 카테고리 RV = [0,1,0,0,0,0]이 된다. RV안의 각 원소들은 베르누이 분포를 따르고, 각각 자신들만의 모수를 갖는다. +카테고리 확률변수는 one-hot vector로 표현할 수 있다. 예를 들어, 주사위의 경우 $K = 6$인 카테고리 분포를 따른다고 표기할 수 있다. 눈이 2인 주사위면이 나왔다고 할때, 이때 카테고리 $RV = [0 , 1, 0, 0, 0, 0]$이 된다. $RV$안의 각 원소들은 베르누이 분포를 따르고, 각각 자신들만의 모수를 갖는다. (RV = Random Variable = 확률변수) -카테고리가 K개일 때, 카테고리 분포의 확률질량함수는 아래와 같다. +카테고리가 $K$개일 때, 카테고리 분포의 확률질량함수는 아래와 같다. - +$$ +\text{Cat}(x; \mu) = +\begin{cases} +\mu_1 & \text{if } x = (1, 0, 0, \dots, 0) \\ +\mu_2 & \text{if } x = (0, 1, 0, \dots, 0) \\ +\mu_3 & \text{if } x = (0, 0, 1, \dots, 0) \\ +\vdots & \vdots \\ +\mu_K & \text{if } x = (0, 0, 0, \dots, 1) +\end{cases} +$$ - - -> RV = Random Variable = 확률변수 +$$\text{Cat}(x; \mu) = \mu_1^{x_1} \mu_2^{x_2} \cdots \mu_K^{x^K} = \prod_{k = 1}^{K} \mu_k^{x^k}$$ #### References @@ -74,17 +81,31 @@ #### 다항 분포 -성공확률이 θ인 베르누이 시행을 n번 반복했을 때의 성공횟수가 이항분포를 따르는 것처럼, 성공확률이 인 카테고리 시행을 n번 반복했을 때의 각 카테고리별 성공횟수는 다항분포(Multinomial distribution)을 따르게 된다. - - +성공확률이 $\theta$인 베르누이 시행을 n번 반복했을 때의 성공횟수가 이항분포를 따르는 것처럼, 성공확률이 $\theta=(\theta_1 ... \theta_k)$인 카테고리 시행을 $n$번 반복했을 때의 각 카테고리별 성공횟수는 다항분포(Multinomial distribution)을 따르게 된다. + +$$ +\left( \begin{matrix} +\text{베르누이 분포} \\ +\downarrow \\ +\text{이항 분포} +\end{matrix} \right) +\approx +\left( \begin{matrix} +\text{카테고리 분포} \\ +\downarrow \\ +\text{다항 분포} +\end{matrix} \right) +$$ 다항분포의 수식은 아래와 같다. - +$$ +\text{Mu}(x; N, \mu) = \binom{N}{x} \prod_{k=1}^{K} \mu_k^{x_k} = \binom{N}{x_1, \cdots, x_K} \prod_{k=1}^{K} \mu_k^{x_k} +$$ -> 예를들어, 주사위를 10번 던졌을 때, 1이 1번, 2가 2번, 3이 1번, 4가2번, 5가 3번, 6이 1번 나오는 확률을 계산하고자 한다. 이를 벡터로 나타내면 (1, 2, 1, 2, 3, 1)이 된다. 6번을 던졌을 때 x벡터처럼 나올 조합을 계산해야하며, 수식은 아래와 같다. +> 예를들어, 주사위를 10번 던졌을 때, 1이 1번, 2가 2번, 3이 1번, 4가2번, 5가 3번, 6이 1번 나오는 확률을 계산하고자 한다. 이를 벡터로 나타내면 $(1, 2, 1, 2, 3, 1)$이 된다. 6번을 던졌을 때 $x$ 벡터처럼 나올 조합을 계산해야하며, 수식은 아래와 같다. - +$$\binom{N}{x_{1}, \cdots , x_{K}} = \frac{N!}{x_{1}!, \cdots, x_{K}!} $$ #### References @@ -97,11 +118,15 @@ #### 가우시안 정규 분포 -평균을 중심으로 좌우가 대칭인 종 모양을 그리는 정규분포이다. 정규 분포의 확률 밀도 함수와 그 그래프는 아래와 같다. - - +평균을 중심으로 좌우가 대칭인 종 모양을 그리는 정규분포이다. 정규 분포의 확률 밀도 함수와 그 그래프는 아래와 같다. + +$$ +f(x) = \frac{1}{\sigma\sqrt{2\pi}} exp(- \frac{(x - \mu)^2}{2 \sigma^2}), -\infty < x < \infty, -\infty < \mu < \infty, \sigma> 0 +$$ -정규 분포 식에서 변수는 이다. σ와 μ는 그래프를 종모양으로 만드는데 사용된다. μ는 확률 변수 X의 평균이고 σ는확률 변수 X의 표준 편차이다. 종 모양의 그래프는 평균을 기준으로 좌우 대칭을 이룬다. 표준 편차가 높을 수록 그래프는 완만한 곡선 형태를 띄게 된다. +![](./img/1-statistics-math/gaussian-normal-distribution.png) + +정규 분포 식에서 변수는 $x$이다. $\sigma$와 $\mu$는 그래프를 종모양으로 만드는데 사용된다. $\mu$는 확률 변수 $X$의 평균이고 $\mu$는확률 변수 $X$의 표준 편차이다. 종 모양의 그래프는 평균을 기준으로 좌우 대칭을 이룬다. 표준 편차가 높을 수록 그래프는 완만한 곡선 형태를 띄게 된다. #### References @@ -119,15 +144,21 @@ t 분포는 정규분포와 같이 중심을 기준으로 좌우 대칭이고 df는 표본수와 관련이 있는 개념으로, 표본이 많아지면 표준정규분포와 거의 동일한 형태를 보인다. - 이면, -
- -
- +$Y \sim t(n)$이면, + +$$ +f(y) = \frac{\Gamma\left(\frac{n+1}{2}\right)}{\Gamma\left(\frac{n}{2}\right)\cdot\sqrt{\pi n}}\cdot\left(\frac{n}{y^2+n}\right)^{\frac{n+1}{2}},\quad-\infty < y < \infty +$$ + +$$ +E[Y] = 0 \quad Var[Y] = \frac{n}{n-2} +$$> 감마 함수 - +$$ +\Gamma(x) = \int_{0}^{\infty}u^{x-1}e^{-u}du +$$ #### References @@ -140,10 +171,11 @@ df는 표본수와 관련이 있는 개념으로, 표본이 많아지면 표준 #### 카이제곱 분포 -정규 분포의 제곱합은 분포를 따른다. -
+정규 분포의 제곱합은 $\chi^2$ 분포를 따른다. - +$$ +Z \sim N(0, 1) \quad \Rightarrow \quad Z^2 \sim \chi^2(df=1) \quad \Rightarrow \quad \sum_{i=1}^{n}Z^2_i \sim \chi^2(df=n) +$$ #### References @@ -156,10 +188,11 @@ df는 표본수와 관련이 있는 개념으로, 표본이 많아지면 표준 #### F 분포 -F 분포는 독립적인 변수의 비가 따르는 분포이다. -
+F 분포는 독립적인 $\chi^2$ 변수의 비가 따르는 분포이다. - +$$ +Q_1 \sim \chi^2(n_1), \quad Q_2 \sim \chi^2(n_2) \quad \Rightarrow \quad \frac{Q_1/n_1}{Q_2/n_2} \sim F(n_1, n_2) +$$ #### References @@ -174,27 +207,26 @@ F 분포는 독립적인 - - -
+$$ +f(x, k, \theta) = x^{k-1}\frac{e^{-x / \theta}}{\theta^k \Gamma (k)} \quad \text{for x> 0} +$$ -
- -
-
+![](./img/1-statistics-math/gamma-distribution.png) **감마 함수** **팩토리얼**을 함수로 일반화한 것 -
- -
-
+$$ +\Gamma (z) = \int_0^\infty t^{z-1} e^{-t} dt \ (\Re \ z> 0) +$$ + +$$ +\Gamma (n) = (n - 1)! +$$ #### References @@ -207,25 +239,19 @@ theta 와 k 는 감마 분포의 모수이다. #### 베타 분포 -베타 분포는 두 모수 a, b 에 대한 **베타 함수**를 나타내는 연속확률분포이다. +베타 분포는 두 모수 $a,ドル $b$ 에 대한 **베타 함수**를 나타내는 연속확률분포이다. -베타 함수는 이항 계수 (조합, combination 으로도 불림) 를 나타내는 함수인데, 이항 계수는 팩토리얼로 이루어져있기 때문에 베타 함수는 감마 함수로 나타낼 수 있다. +베타 함수는 이항 계수(조합, combination 으로도 불림) 를 나타내는 함수인데, 이항 계수는 팩토리얼로 이루어져있기 때문에 베타 함수는 감마 함수로 나타낼 수 있다. -베타 분포의 값은 0~1 사이이며 감마 분포와 마찬가지로 베이지안 추정을 위해 사용된다. +베타 분포의 값은 0ドル \sim 1$사이이며 감마 분포와 마찬가지로 베이지안 추정을 위해 사용된다. -
- -
-
+$$ +Beta(x; a, b) = \frac{\Gamma(\alpha + \beta )}{\Gamma ( \alpha ) \Gamma ( \beta )} x^{\alpha - 1} (1 - x)^{\beta - 1} +$$ -
- -
-
+![](./img/1-statistics-math/beta-distribution.png) #### References - [갈아먹는 통계 기초 [1] 확률 분포 정리 - 갈아먹는 머신러닝](https://yeomko.tistory.com/33) - [8.7 베타분포, 감마분포, 디리클레분포 - datascience school](https://datascienceschool.net/02%20mathematics/08.07%20%EB%B2%A0%ED%83%80%EB%B6%84%ED%8F%AC,%20%EA%B0%90%EB%A7%88%EB%B6%84%ED%8F%AC,%20%EB%94%94%EB%A6%AC%ED%81%B4%EB%A0%88%20%EB%B6%84%ED%8F%AC.html) - ---- diff --git a/logo.png b/logo.png index ad90b61..fbb527b 100644 Binary files a/logo.png and b/logo.png differ