diff --git a/Lecture01.md b/Lecture01.md new file mode 100644 index 0000000..b3fbe17 --- /dev/null +++ b/Lecture01.md @@ -0,0 +1,167 @@ +# CS231n 1강 컴퓨터 비전의 역사💻👓 + +## 0. Intro + +- 무수한 센서(ex. 카메라)로부터 비롯된 엄청나게 많은 시각 데이터 + + → 이에 따라 visual data를 잘 활용할 수 있는 알고리즘의 중요성 증대 + + → 하지만 실제로 이들을 이해하고 해석하는 일은 상당히 어려운 일임 + +- 매분 약 500시간 이상의 동영상이 업로드 됨 (2020년 유튜브 통계자료) + +## 1. Computer Vision + +- 컴퓨터 비전은 학제적(interdisciplinary)인 분야로, 굉장히 다양한 분야와 맞닿아 있다. + - 물리학 - 광학, 이미지 구성, 이미지의 물리적 형성 + - 생물학, 심리학 - 동물의 뇌가 어떤 방식으로 시각 정보를 보고 처리하는지를 이해 + - 컴퓨터 과학, 수학, 공학 - 컴퓨터 비전 알고리즘을 구현할 컴퓨터 시스템을 구축할 때 필요 + +## 2. Vision의 역사 + +### 1) Biological Vision (**Evolution’s Big Bang)** + +- 5억 4천만 년 전에 천만 년이라는 짧은 시간동안 생물의 종이 폭발적으로 증가한 시기가 있었음 + + → 가장 설득력 있는 가설은 Biological vision의 탄생 (by. Andrew Parker) + +- 5억 4천만 년 전 최초의 눈이 생겨나고 가장 중요한 감각기관으로 자리매김함 + +### 2) Mechanical Vision (camera) + +- 1600년대 초창기의 카메라, Obscura + - 핀홀 카메라 이론을 기반으로 함 - 빛을 모아주는 구멍 하나, 카메라 뒤편의 평평한 면에서 정보를 모으고 이미지를 투영시킴 + - 생물학적으로 발전한 초기의 눈과 유사 + +### 3) Hubel & Wiesel의 연구 (1959) + +- “포유류의 시각적 처리 메커니즘은 무엇일까?”하는 질문으로부터 연구 시작 +- 시각 처리 관점에서 인간의 뇌와 비슷한 고양이 뇌를 연구 + - 고양이 뇌 뒷면(primary visual cortex area가 있는)에 전극을 꽂아 어떤 자극을 줘야 뉴런들이 반응하는지를 관찰 +- 연구로부터 시각 처리가 처음에는 단순한 구조로 시작하고, 그 정보가 통로를 거치면서 점점 복잡해진다는 것을 발견 + +## 3. Computer Vision의 역사 + +### 1) Block World (1963) + +- 컴퓨터 비전에서 최초의 박사 학위 논문으로, 눈에 보이는 사물들을 기하학적인 모양으로 단순화시킴 +- 연구의 목표는 눈에 보이는 세상을 인식하고, 그 모양을 재구성하는 것이었음 + +### 2) “The summer vision project” (1966) + +- 컴퓨터 비전의 시작이 된 MIT의 프로젝트 +- ‘The summer vision project is an attempt to use our summer workers effectively in the construction of a significant part of a virtual system.’ + +### 3) Vision(David Marr) (1970s) + +- David Marr이 생각하는 비전이 무엇인지, 컴퓨터 비전이 어떤 방향으로 나아가야 하는지, 컴퓨터가 visual world를 인식하기 위해 어떤 알고리즘을 개발해야하는지를 담고 있는 책 +- 우리가 눈으로 받아들인 이미지를 최종적인 full 3D 표현으로 만들려면 몇 단계의 과정을 거쳐야 한다고 주장 + + ![Untitled](https://user-images.githubusercontent.com/79077316/156922509-807740ee-68e0-4ba3-ba6b-8c644626ba8b.png) + + 1. **Input Image** + 2. **Primal Sketch** - 경계(edges), 막대(bars), 끝(ends), virtual lines, curves, boundaries가 표현 + + 이전에 Hubel과 Wiesel은 시각 처리의 초기 단계는 경계(edges)와 같은 단순한 구조와 밀접한 관련이 있다고 주장했음 + + 3. **2.5D Sketch** - 표면(surfaces), 깊이(depth), 층(layer), 불연속 점과 같은 것들을 종합하여 표현 + 4. **3D Model** - 앞의 단계들을 모두 모아 surface and volumetric primitives 형태의 계층적으로 조직화된 최종적인 3D 모델 + + → 이런 사고 방식은 오랫동안 비전에 대한 아주 이상적인, 지배적인 사고방식으로 여겨져 옴 + + +### 4) Generalized Cylinder, Pictorial Structure (1970s) + +![Untitled](https://user-images.githubusercontent.com/79077316/156922506-80a84c97-d977-4b11-af1e-0a5698747d9c.png) + +- Generalized Cylinder - 사람을 원통 모양으로 조합해서 만듦 +- Pictorial Structure - 사람을 주요 부위와 관절로 표현함 +- 두 방법 모두 단순한 모양과 기하학적인 구성을 이용해서 복잡한 객체를 단순화시킴 + +### 5) by David Lowe (1987) + +- David Lowe는 어떻게 해야 실제 세계를 단순한 구조로 재구성/인식할 수 있을지를 고민함 +- 선(lines), 경계(edges), 직선(straight lines) 그리고 이들의 조합을 이용해서 사물을 재구성함 +- 60/70/80 년대는 컴퓨터 비전으로 어떤 일을 할 수 있을지를 고민한 시기이지만, 단순한 toy example에 불과했음 + +### 6) Object Segmentation - Normalized Cut (1997) + +- 객체 인식(object recognition)이 어렵다면 객체 분할(object segmentation)을 먼저 하자! + - 여기서 질문! 근데 객체 분할이 객체 인식보다 더 어려운 task 아닌가? 여기서 말하는 객체 분할은 라벨링을 하지 않고 픽셀을 grouping 하는 방법을 얘기하는 건가? +- 객체 분할(Image segmentation)은 이미지의 각 픽셀을 의미 있는 방향으로 grouping 하는 방법 +- 20세기부터 인터넷과 디지털 카메라의 발전으로 사진의 질이 훨씬 좋아졌고, 더 좋은 실험 데이터가 많이 생겨남 + +### 7) Object recognition - SIFT (1990s~) + +![Untitled](https://user-images.githubusercontent.com/79077316/156922514-4f894ac0-59bd-44ca-9948-3925c45e8fff.png) + +- 1990년대 후반 ~ 2010년대까지 특징(Feature)기반 객체 인식 알고리즘 +- David Lowe의 **SIFT feature**를 사용하는 방법은 객체의 여러 특징 중 다양한 변화에 잘 변하지 않는 객체에서 중요한(diagnostic) 특징들을 찾아내고, 다른 객체에 그 특징들을 매칭시키는 방법 + +### 8) Face Detection - by Viola & Jones (2001) + +- AdaBoost 알고리즘을 이용한 real-time face detection +- 컴퓨터 비전에서 유난히 발전 속도가 빨랐던 분야가 얼굴 인식 +- 이 연구를 계기로 statistical machine learning 방법이 탄력을 받기 시작함 + - ex) support vector machine, boosting, graphical models, neural networks +- 2006년 Fuji Flim은 실시간 얼굴 인식이 가능한 최초의 디지털 카메라를 선보임 + +### 9) Support Vector Machine - Spatial Pyramid Matching (2006) + +- 기본 아이디어는 이미지에서 특징을 잘 뽑아내면, 특징들이 이미지에 대한 단서를 제공해줄 것이라는 생각 +- 이미지의 여러 부분과 여러 해상도에서 추출한 특징을 하나의 feature descriptor로 표현하고 Support vector machine 알고리즘을 적용함 + +### 10) Human Recognition - HoG, Deformable Part Model (2005, 2009) + +![Untitled](https://user-images.githubusercontent.com/79077316/156922513-b56dceb9-710d-415c-a721-b151e8cf5f18.png) + +### 11) PASCAL Visual Object Challenge (2006~2012) + +- Benchmark Dataset 중 하나로, 20개의 object 클래스와 클래스당 수만 개의 이미지셋 +- 위 데이터셋을 이용해 객체 인식(object recognition) 기술을 test한 결과 성능이 꾸준히 증가함 + +### 12) ILSVRC (2010~) + +- 대부분의 머신러닝 알고리즘에서 overfitting의 문제 발생 + + → 문제의 원인 중 하나는 시각 데이터가 너무 복잡하다는 것 + + → 모델의 input은 복잡한 고차원의 데이터이고, 이로 인해 모델을 데이터셋에 fit하게 하려면 더 많은 parameters가 필요 + + → 또 학습 데이터가 부족하면 overfitting이 훨씬 더 빠르게 발생했고, 일반화 능력이 떨어졌음 + +- ‘머신러닝의 overfitting 문제를 극복하면서, 세상의 모든 객체들을 인식할 수 있는가?’와 같은 물음으로 부터 ImageNet의 프로젝트가 시작됨 +- ImageNet의 데이터는 약 15만 장의 이미지와 22만 가지의 클래스 +- 2009년부터 ImageNet 팀이 ILSVRC 대회 주최 +- 이 대회의 목적은 이미지 분류 문제를 푸는 알고리즘을 테스트하기 위함 +- 2012년 챌린지에서 우승한 알고리즘이 바로 **Convolutional Neural Network(Deep Learning)** + - CNN이 바로 컴퓨터 비전의 비약적인 발전을 이끌어낸 주역 + - 앞으로 이 강의에서는 CNN에 대해 중점적으로 다룰 것임 + +## 3. CNN + +- 2012년에 CNN의 시대가 시작되었고, 이후 CNN 모델을 개선하고 튜닝하려는 많은 시도가 있었음 +- CNN이 2012년에 처음 나온 것은 아니고, 오래전부터 존재했음 + +### 1) 2012년 이전의 CNN + +**LeNet (1998)** + +- 숫자 인식을 위한 CNN 모델 개발 +- 이미지를 input으로 받아서 숫자와 문자를 인식할 수 있도록 함 +- raw pixel을 입력으로 받아 여러 convolutional layer를 거치고 sub sampling, fully-connected layer를 거치게 됨 +- 2012년의 많은 CNN 아키텍처들이 90년대의 LeNet 아키텍처를 기반으로 하기 때문에 아키텍처가 서로 비슷함 + +### 2) 2012년 이후의 CNN + +- 2012년이 되어서야 CNN이 빛을 보게 된 이유는 바로 (1)**연산량의 증가**와 (2)**데이터의 증가** 때문임 + +(1) 연산량의 증가 + +- 연산량의 증가는 딥러닝 역사에서 아주 중요한 요소임 +- 컴퓨터의 계산속도가 매년 빨라져서 계산 능력이 좋아짐 (무어의 법칙) +- GPU의 발전으로 강력한 병렬처리가 가능해짐, 이는 계산 집약적인 CNN 모델을 고속으로 처리하는데 적합함 + +(2) 데이터의 증가 + +- 90년대와 비교했을 때 사용 가능한 데이터셋이 매우 많아짐 \ No newline at end of file diff --git a/Lecture02.md b/Lecture02.md new file mode 100644 index 0000000..cad014a --- /dev/null +++ b/Lecture02.md @@ -0,0 +1,178 @@ +# CS231n 2강 Image classification (knn과 linear classification) + +## 1. Image Classification + +- 인풋 이미지가 주어진 클래스 중 어떤 클래스에 속하는지 분류하는 태스크 + +### Semantic gap + +- 기계 입장에서 image classification이 어려운 이유는 사람이 보는 이미지와 기계가 보는 이미지가 다르기 때문 +- 사람 ↔ 기계가 이미지를 받아들이는 방식에 의미론적인 차이가 존재 (semantic gap) +- 컴퓨터는 이미지를 **숫자 집합**으로 인식 + - 이미지의 각 픽셀이 r, g, b 3개의 숫자로 표현됨 + +### Challenges + +- 이미지 분류를 어렵게 하는 여러 challenge가 존재함 + - viewpoint variation(바라보는 시점), illumination(조명), deformation(이미지 속 객체의 변형), occlusion(가려지는 현상), background clutter(배경과 비슷해 보이는 현상), intraclass variation(클래스 내의 다양성) +- 예를 들어, 고양이 사진의 viewpoint가 달라지면 이미지의 픽셀 값도 모두 달라지고 기계가 보는 이미지는 완전히 다른 이미지가 되는 것임. 그럼에도 이미지를 여전히 ‘고양이’로 분류할 줄 알아야 함 +- 사람의 시각체계와 달리 위의 모든 challenge들을 극복하고 컴퓨터가 이미지를 잘 분류해내는 건 기적에 가까움 +- 일부 제한된 상황을 가정하면 이미지 분류가 가능해짐 + + 👉🏻 어떻게 가능해질까? + + +### Edge를 이용해 이미지를 분류하는 방법 + +- Hubel과 Wiesel의 연구에서 Edge가 이미지를 인식할 때 중요한 역할을 한다는 것을 알게 됨 +- 이미지에서 edges를 계산하고, 다양한 corner와 edge를 분류해서 이미지를 분류함 + - 예를 들어 고양이 이미지에서 edge를 추출해내고, ‘Y’ 모양이면 고양이의 코로 분류함 +- 하지만 이런 방식은 문제가 있는데, + 1. 알고리즘이 robust하지 않음 (즉 이미지에 변화가 있을 때 다른 클래스로 잘못 분류함) + 2. 확장성이 없음 (고양이를 분류하는 규칙을 직접 만들어 분류하는 것이기 때문에 고양이가 아닌 다른 객체는 인식하지 못함) +- 위와 같은 문제로 data-driven approach(데이터 중심 접근 방법)으로 옮겨 감 + +### Data-driven approach 데이터 중심 접근 방법 + +- 위에서 직접 규칙을 만들어 나가는 대신에 + 1. 엄청 많은 데이터셋을 수집하고, + 2. 데이터셋을 이용해서 machine learning classifier를 학습시켜 이미지 분류 모델을 만들어 냄 + + 👉🏻 따라서 함수 두 개가 필요함 train, test + +- 이미지를 분류할 때 사용되는 굉장히 general한 방법임 + 1. Collect a data set of images and labels + 2. Use Machine Learning to train a classifier + 3. Evaluate the classifier on new images + +```python +def train(images, labels): + #machine learning! + return model + +def predict(model, test_images): + #use model to predict labels + return test_labels +``` + +- 데이터 중심 접근 방법은 머신 러닝의 key insight! + +## 2. Nearest Neighbor + +- 굉장히 간단한 알고리즘이지만 data-driven approach로서 아주 좋은 방법임 + 1. 모든 학습 데이터를 기억하고 + 2. 새로운 이미지(test image)와 기존의 학습 데이터를 비교해서 **가장 유사한** 이미지로 레이블을 예측함 + + 👉🏻 이때 가장 유사한 것의 기준을 무엇이며, 두 이미지를 어떻게 비교할까? 다른 말로 **“이미지 간의 차이를 어떻게 측정할 것인가?”** + + ### L1 Distance + + ![Untitled](https://user-images.githubusercontent.com/79077316/158099511-e3415d96-1a29-4ace-a107-a674de5e7141.PNG) + + - L1 distance는 같은 point의 input 이미지(test set)의 픽셀에서 training image의 픽셀 값을 빼고 절댓값을 취함 + - 이렇게 픽셀 간의 차이를 계산하고 모든 결과를 더한 것이 L1 distance의 결과값이 됨 +- `numpy`의 벡터 연산을 이용하면 NN Classifier를 구현하는 코드는 간결해짐 + +![Untitled](https://user-images.githubusercontent.com/79077316/158099513-2e4ef171-12e7-415c-9aa8-a1a588f0a56d.PNG) + +- training set의 이미지가 N개일 때, train 함수의 시간 복잡도는 O(1)이고, test 함수의 시간 복잡도는 O(N) +- test time에서 N개의 학습 데이터를 test image와 모두 비교하면서 test time >> train time +- 실제로 우리는 train time 보다는 test time에서 빠르게 동작하기를 원함 +- 하지만 NN 알고리즘은 정반대로 test time에서 시간이 많이 걸림 +- CNN과 같은 parametric model은 NN과 반대로 train time에서는 시간이 오래 걸릴지 모르지만, test time은 엄청 빠름 (뒤에서 소개할 linear classification도 parametric 방법) + +### NN의 decision regions + +![Untitled](https://user-images.githubusercontent.com/79077316/158099517-4fb5e2c7-36f8-4610-8be7-f3270b2a8591.PNG) + +- 🙄 nn의 decision regions가 어떻게 그려지는 건지 아직 제대로 이해를 못했다. 좀 더 공부하고 추가할 예정! +- 위 그림의 결과를 보면 성능이 그닥 좋지 않음 + 1. 가운데에 노란 점. nn은 ‘가장 가까운 이웃’만을 보기 때문에 생기는 문제(🙄 이게 왜..?) + 2. noise나 spurious +- 위의 문제들 때문에 nn의 조금 더 일반화된 방법인 knn 알고리즘이 탄생 + +## 3. K-Nearest Neighbor + +![Untitled](https://user-images.githubusercontent.com/79077316/158099521-e6b018a9-9374-4100-9f00-c271ed5ceb34.PNG) + +- 단순하게 가장 가까운 이웃만을 찾기보다는, distance metric을 이용해서 가까운 이웃을 k개 찾고, 이웃끼리 다수결 투표를 함. 이웃 들 중 가장 많은 득표수를 획득한 클래스의 레이블로 예측하는 방법 +- 이때 k는 1보다 커야 함 +- 위 그림은 모두 동일한 데이터셋을 사용한 knn 분류기 +- nn(k=1)보다 경계가 부드러워지고, nn에서 문제가 되는 점들도 보이지 않음. 그림에서의 흰색 영역은 knn이 ‘majority’를 결정할 수 없는 영역 + +### Distance metric + +- knn에서 서로 다른 점(이미지)들을 어떻게 비교할 것인가? + + 👉🏻 “Distance metric” 거리 척도를 사용해서 거리로 두 점을 비교한다! + + +![Untitled](https://user-images.githubusercontent.com/79077316/158099529-12822681-3a18-44a6-bde8-abb25b53dfdd.PNG) + +- 🙄 L1 Distance와 L2 Distance 관련 내용이 잘 이해가 가지 않아서 이것 역시 더 공부하고 추가할 예정이다. 아래 내용들이 잘 이해되지 않음... +- 기존의 좌표계를 회전시키면 L1 distance는 변하는 반면 L2 distance는 좌표계와 아무런 연관이 없음 +- 동일한 데이터에 대해 어떤 거리 척도를 사용하느냐에 따라 결정 경계(decision boundaries)의 모양이 달라짐 +- L1 distance ⇒ 결정 경계가 coordinate axis(좌표 축)에 영향을 받음 +- L2 distance ⇒ 좌표 축에 영향을 받지 않고 결정 경계를 만들기 때문에 더 자연스러움 + +### Hyperparameter + +- knn을 사용할 때 결정해야 하는 것들이 있음 + 1. k를 몇으로 설정할 것인지 + 2. 어떤 거리 척도를 사용할 것인지 + + **👉🏻** 이런 것들을 **“hyperparameter”** 라고 함 + +- 하이퍼파라미터는 train time에 학습하는 것이 아니므로 train time 전에 반드시 설정해야 함 +- 하이퍼파라미터는 데이터로 직접 학습시킬 수 있는 것이 아님 + + **👉🏻 그래서 하이퍼파라미터를 어떻게 정하냐?** + +- 하이퍼파라미터를 정하는 것은 문제의존적(problem dependent)이다. 즉 문제마다 다르다 +- 가장 간단한 방법으로는 데이터에 맞게 여러 값들을 시도해보고 가장 좋은 값을 찾는 것임 + + **👉🏻 이건 구체적으로 어떻게 시도할 수 있을까?** + + +1️⃣ **하이퍼 파라미터를 구하는 첫 번째 방법** + +- 데이터를 training set, validation set, test set 세 개로 나눈다. +- 다양한 hyperparmeter로 training set을 학습시키고, validation set으로 검증한다. validation set에서 가장 성능이 좋았던 hyperparameter를 선택한다. +- 위에서 만든 classifier를 가지고 test set에서 마지막에 딱 한 번만 성능을 test한다. +- 여기서 결국 중요한 것은 classifier가 한 번도 보지 못한 데이터(test set)를 얼마나 잘 예측하는지가 분류기의 성능을 결정한다는 것임 + +2️⃣ **두 번째 방법, cross validation (교차 검증)** + +![Untitled](https://user-images.githubusercontent.com/79077316/158099532-f0e532ef-4836-49c6-8518-02b8d99fb0a0.PNG) + +- 첫 번째 방법과 마찬가지로 training set과 test set을 나누어 test set은 마지막에 성능을 테스트할 때만 딱 한 번 사용한다. +- training set을 여러 개로 나눈다. 예를 들어 위 예제에서는 5-fold cross validation 예제라 5개로 나눈다. +- 처음 4개의 fold에서 hyperparameter를 학습시키고 나머지 한 fold에서 알고리즘을 평가한다. +- 위 과정을 모든 fold에 대해서 반복하여 최적의 hyperparameter를 찾는다. +- 이 방법은 데이터셋이 작을 때만 사용하여 딥러닝에서는 많이 사용하지 않음 + +### 이미지 분류기로써의 knn + +- 실제로 입력이 이미지인 경우에는 knn을 잘 사용하지 않음 +- 이유는 + 1. test time에서 매우 느림 + 2. L1/L2 distance가 이미지를 비교하는 척도로서 적절하지 않음 + 3. 차원이 증가함에 따라 필요한 학습데이터의 양이 기하급수적으로 증가함 + +## 4. Linear classification + +- Linear classification은 간단한 알고리즘이지만 neural network와 cnn의 기반이 되는 알고리즘으로 매우 중요함 +- 강의에서는 neural network를 레고 블럭, Linear classifier를 낱개 블럭, cnn을 블럭으로 만든 거대한 타워에 비유함 + +### Parametric approach + +- Linear classification은 parametric의 가장 단순한 형태임 (앞서 knn은 parameter가 없었다) + +![Untitled](https://user-images.githubusercontent.com/79077316/158099544-1ae233c2-c239-49c5-93c4-7918670ffba0.PNG) + +- parametric approach는 training set의 정보를 파라미터 w(가중치)에 요약함 +- 따라서 test time 시 training data에 대한 정보가 필요 없게 됨. 파라미터 w만 있으면 됨 + - 앞서 knn에서는 test time에서 모든 학습 데이터에 대한 정보가 필요했고, 때문에 test time에서 시간이 많이 걸림 +- 어떤 식으로 가중치 w와 데이터를 조합할지는 여러 가지 방법이 존재하고, 이게 모두 다양한 neural network 아키텍처를 설계하는 과정이다 +- bias는 데이터와 무관하게 특정 클래스에 우선권을 부여하는 역할을 함 +- Linear classifier는 곧 선형 1차 함수로, 분류하기 어려운 케이스도 많이 있음 \ No newline at end of file diff --git a/Lecture03.md b/Lecture03.md new file mode 100644 index 0000000..9668586 --- /dev/null +++ b/Lecture03.md @@ -0,0 +1,124 @@ +# CS231n 2강 Loss functions and optimization + +## 1. Loss function(손실함수) +- Loss function은 classifier가 얼마나 잘 수행해내는지 알려줌 +- weight 값을 판단하는 기준이 됨 +- loss will be high, if we’re doing a poor job of classifying the training data + +### 1) Multiclass Support Vector Machine loss (Hinge loss) +- (x_i, y_i)에서 x_i는 image, y_i는 (integer) label을 의미. 이때 scores vector: s=f(x_i, W) +- SVM loss는 다음과 같이 구한다 + +![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0tezW%2Fbtq8cQIUB8A%2Fr9zOokxuPgfQrLF7R3oc71%2Fimg.png) + +- s_j는 잘못된 label의 score, s_yi는 제대로 된 label의 score 의미. 1은 safety margin +- s_j – s_yi + 1 = s_j – (s_yi – 1). (correct label score – 1)보다 큰 incorrect label score가 있다면 loss는 0보다 크게 됨 +- 가능한 loss의 min 값은 0, max 값은 무한대 +- 만약 j=y_i인 경우도 포함한다면 loss값이 모두 1씩 증가하여 loss의 평균 값도 1 증가 +- 전체 dataset에 대한 loss 값은 평균 낸 값 + +![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcy1rHI%2Fbtq8cFVxIgW%2F9QJKFYnBKOqjUQM5dGWbb1%2Fimg.png) + +- 일반적으로 weight 값은 작은 값으로 초기화 -> score 값이 0에 가까운 값으로 나타남 + -> 이때의 SVM loss는 max(0, 0-0+1) = 1이므로 초기의 전체 SVM loss 값은 (class – 1) + -> sanity check에 이용됨 +- squared hinge loss는 다음과 같다 + +![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfZkxo%2Fbtq8cPDe4pM%2F9pKCX6kTaOdkzJh4KoSonk%2Fimg.png) + +- 제곱을 해서 non linear하게 되고, 차이가 생김 +- 제곱을 하지 않은 hinge loss가 일반적이지만 경우에 따라 squared hinge loss를 사용하기도 함 +- Multiclass SVM loss example code + +![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuHXnT%2Fbtq8bqjDhVY%2FOlSAUSkznR8DuHzQ9VL1P0%2Fimg.png) + +#### Regularization + +- unique한 weight 값을 지정해주기 위해 regularization 개념 등장 + +![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6Z8ii%2Fbtq8cNTmhK2%2FtKe1NmJSvukwWLsxWrGsL0%2Fimg.png) + +- Data loss : training dataset에 최적화하려고 함 +- Regularization : test data에 최대한 일반화하려고 함 + -> data에 fit하고 가장 최적화된 weight값을 추출 +- weight regularization을 더해주면 training data에 대한 정확도는 안 좋아지겠지만 test data에 대한 정확도는 좋아짐 + +#### L2 regularization + +- weight 값을 0에 가깝도록 유도 +- weight를 최대한 spread out 해서 모든 데이터 값의 input feature들을 고려함 +- “diffuse over everything” 동일한 score라면 weight가 최대한 spread out된 것을 선호함 + +#### λ 값 + +- 높으면 모델이 단순해짐 + - underfitting 위험 존재 +- 낮으면 모델이 복잡해짐 + - overfitting 위험 존재 + +### 2) Softmax classifier +- scores = unnormalized log probabilities of the classes +- s = f(x_i;W) +- Softmax loss(Cross entropy loss)는 다음과 같이 구한다 + + ![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIMp8b%2Fbtq8ceDSe46%2FRzCbkYHf8UjElkMgjlJyYK%2Fimg.png) + +- L_i의 가능한 min값은 0, max는 무한 +- weight값이 초기에 0에 가까운 값으로 초기화될 때 loss는 -log(1/class) -> sanity check에 이용 + +### 3) Softmax vs. SVM + +![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FICUjx%2Fbtq8dR8z7t7%2Fx4Bv6U66U7HeP5YWVWCYkk%2Fimg.png) + +- datapoint의 score 값을 약간 변경했을 때, +- softmax는 데이터에 민감해서 모든 data 값을 다 고려하기 때문에 loss 값이 변함 +- svm은 데이터에 둔감해서 data 값들이 변하게 되더라도 loss 값은 변하지 않음 + +## 2. Optimization +- loss를 minimize하는 최적의 weight를 찾아가는 과정 + +### Strategy 1: Random search +- 절대로 사용해서는 안되는 전략 very bad idea + +### Strategy 2: Follow the slopenumerical gradient +#### numerical gradient +- evaluate the gradient numerically +- 1차원인 경우 +![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwqRye%2Fbtq8btVRWh5%2F0ttQB6GKkKcXV7SPqtapLK%2Fimg.png) + +- 다차원인 경우 + - gradient는 vector로 나타남 +- approximate, slow, easy to write + +#### analytic gradient +- use calculus to compute gradient +- exact, fast, error-prone3. Gradient Descent + +![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbz9UAh%2Fbtq8a6s0DG1%2FP0Vw7tsSCnnNvVmsYkcMYK%2Fimg.png) + +- step size는 learning rate이라고도 불림. +- Learning rate와 regularization strength는 모두 hyperparameter이라 최적의 값을 찾는 게 매우 중요함 + +![](https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fci6SdX%2Fbtq8c0roh4p%2F1OCv1Nn7Ez4rZK7HPXU6f0%2Fimg.png) + +- 임의의 위치에서 가운데 빨간색 지점으로 가는 것, 즉 기울기가 0에 가까운 지점으로 가는 것이 목표 +- full batch gradient descent: training set 전체를 이용 +- mini batch gradient descent: small portion of the training set 이용 + +#### Stochastic Gradient Descent (SGD) +- mini batch gradient descent의 대표적인 예 +- approximate sum using a minibatch of examples 32/64/128 common + +## 4. Image features - CNN 등장 이전의 방식들 +- CNN이 나오기 전 image classification 이 이루어진 방식 +- image feature를 추출한 다음에 concatenation 시켜서 하나의 giant column vector를 만들어 linear classifier 적용 + - example: color histogram +- 모든 pixel들의 color를 추출 + - example: histogram of oriented gradients (HoG) +- edge들의 orientation feature를 추출 +- 방향값을 히스토그램으로 표현 + - example: bag or words +- 이미지의 random patch 잘라 냄 + -> 이미지에서 각도, 색깔 등의 image feature 추출 + -> 새로운 이미지가 들어오면 이미지를 잘라내어 cluster과 비교 +- 이처럼 특징을 추출해서 linear classifier에 적용하는 방식이 아니라, model이 스스로 이미지 특징을 뽑아내도록 하는 것이 CNN \ No newline at end of file diff --git a/Lecture05.md b/Lecture05.md new file mode 100644 index 0000000..4a63e22 --- /dev/null +++ b/Lecture05.md @@ -0,0 +1,162 @@ +# CS231n Lecture 5 | Convolutional Neural Networks + +## 1. Neural Networks의 역사 + +### 1) Hubel & Wiesel의 연구 + +- 자세한 연구 내용은 1강을 참고 + +![Untitled (5)](https://user-images.githubusercontent.com/79077316/161549788-a63a19bd-c1b1-4899-bc2d-310300a72c5c.png) + +**실험에서 알게 된 것** + +1. 실험에서 뉴런이 oriented edges와 shapes와 같은 것에 반응한다는 것을 알게 됨 +2. 실험 결과 대뇌 피질 내부에 지형적인 매핑(topographical mapping)이 존재하는 것을 알게 됨 +3. 피질 내 서로 인접해 있는 세포들은 visual field 내에 지역성을 띄고 있음 +4. 뉴런들이 계층적인 구조를 지님 + - simple cell, complex cell, hypercomplex cell 모두 계층적으로 연결되어 있음 + - simple cell + - 다양한 edges의 방향과 빛의 방향에 반응 + - complex cell + - 빛의 방향 뿐만 아니라 움직임에서 반응 + - hypercomplex cell + - 끝 점(end point) 과 같은것에 반응 + + 👉🏻 물체의 corner 또는 blob에 대한 아이디어를 얻게 됨 + + +### 2) Neocognitron (Fukushima, 1980) + +![Untitled (6)](https://user-images.githubusercontent.com/79077316/161549800-b32e5ceb-4d82-4d59-9d3c-55bc69b15340.png) + +- hubel과 wiesel의 연구에서 발견한 simple cell과 complex cell의 아이디어를 사용한 최초의 NN +- simple cell과 complex cell을 교차시킴 (SCSC...) +- Simple cells은 학습가능한 parameters를 가지고 있고, Complex cells은 pooling과 같은 것으로 구현하여 작은 변화에 Simple cells보다 더 강인함 + +### 3) LeNet, 1998 + +![Untitled (7)](https://user-images.githubusercontent.com/79077316/161549814-41d61b7a-4ed1-4a16-bce9-a4b3c97c3f14.png) + +- 최초로 NN을 학습시키기 위해 Backprop과 gradient-based learning을 적용함 +- 문서 인식에서 꽤 좋은 성능을 보임 (우편번호의 숫자 인식) + +### 4) AlexNet, 2012 + +![Untitled (8)](https://user-images.githubusercontent.com/79077316/161549880-5342c913-18eb-4575-aa80-ad1cb5a6e0d9.png) + +- convnet으로 이전의 NN보다 더 크고 깊어짐 +- GPU의 발전으로 ImageNet dataset과 같은 대규모의 데이터도 활용할 수 있게 됨 + +## 2. Convolutional Neural Networks + +### 1) Conv layer의 연산 과정 + +![Untitled (9)](https://user-images.githubusercontent.com/79077316/161549867-bb737fd0-e3df-46bf-9290-3af19f251d5c.png) + +- FC layer와 Conv layer의 차이점은 기존의 구조를 보존시킨다는 것임 + - FC layer는 입력 이미지를 벡터 한 줄로 길게 폈다면 conv layer는 기존의 이미지를 그대로 유지함 +- 가중치 값이 들어있는 filter를 이용해서 이미지를 슬라이딩하면서 내적 연산을 수행함 +- filter는 입력의 깊이(depth)만큼 확장됨 +- 5x5x3의 필터는 벡터를 길게 펴서 1x75 길이의 벡터가 됨 +- 필터의 각 w와 이에 해당하는 이미지의 픽셀 값을 곱함 + - W^Tx + b + - W를 transpose한 값과 입력 이미지의 픽셀 값을 내적 연산하고 bias 값을 더함 + +### 2) Convolution 연산 + +![Untitled (10)](https://user-images.githubusercontent.com/79077316/161549892-a45bc997-3595-45b1-a94a-a29ff00af0a2.png) + +- convolution 연산은 입력 이미지의 좌상단부터 시작하여 필터의 모든 요소를 가지고 내적을 수행하여 하나의 값을 얻게 됨 +- 하나의 필터를 가지고 이미지 전체에 대해 convolution 연산을 수행해서 출력 결과 activation map을 얻음 + +![Untitled (11)](https://user-images.githubusercontent.com/79077316/161549914-0b98d25a-a52a-4ee8-b26e-dbb3105099cd.png) + +- 보통 위 그림과 같이 convolution layer에서는 필터마다 다른 특징을 추출해내기 위해 여러 개의 필터를 사용함 + +![Untitled (12)](https://user-images.githubusercontent.com/79077316/161549825-887ddbb6-5821-4c51-b021-56c34f79e22a.png) + +- conv layer들을 연산하고 각각을 쌓아 올리게 되면 위와 같이 간단한 linear layer들이 여러 겹 쌓인 neural network가 됨 + +![Untitled (13)](https://user-images.githubusercontent.com/79077316/161549924-be90d83c-7aab-421a-9f5b-5557f297df6d.png) + +- conv layer 사이사이에 activation function이나 pooling layer을 추가함 +- 각 layer의 출력은 그 다음 layer의 입력이 됨 +- 각 layer는 여러 개의 필터를 가지고 있고, 각 필터마다 각각의 activation map을 만듦 + +![Untitled (14)](https://user-images.githubusercontent.com/79077316/161549933-13b9f67d-578c-4fc0-9333-994eec8f555e.png) + +- hubel & wiesel의 연구 결과처럼 여러 개의 layer들은 각 필터를 거치면서 계층적으로 학습함 +- 앞쪽에 있는 필터에서는 edge와 같은 low-level feature를 학습함 +- mid-level에서는 corner나 blobs와 같은 좀 더 복잡한 특징을 학습함 +- high-level에서는 좀 더 객체와 닮은 것들이 출력 결과로 나옴 +- layer의 계층에 따라 단순/복잡한 특징이 존재함 + +![Untitled (15)](https://user-images.githubusercontent.com/79077316/161549944-09ff394d-8003-43dd-abc3-1e16569e6704.png) + +- 각 activation은 이미지가 필터를 통과한 결과이고, 이미지 중 어느 위치에서 해당 필터가 크게 반응하는지 알려줌 + +### 3) Activation map의 연산 과정 + +![Untitled (16)](https://user-images.githubusercontent.com/79077316/161549955-4c02d48b-5ad8-4d3e-9beb-fcdcf20bdeb8.png) + +- 간단한 예시로 7 x 7 입력에 3 x 3 필터가 있다고 해보자 +- 3x3 필터를 이미지의 왼쪽 상단부터 씌워서 해당 값들의 내적을 수행함 +- 위 이미지의 연산 결과는 activation map의 가장 왼쪽, 윗부분의 출력값이 됨 +- 연산이 끝나면, 필터를 오른쪽으로 한칸씩 움직여서 반복 연산을 수행함 +- 이렇게 반복하면 결국 5x5의 출력을 얻게 됨 + +![Untitled (17)](https://user-images.githubusercontent.com/79077316/161549971-477cf5cc-c88c-4e02-bbed-a7366c8a9650.png) + +- 필터를 이동하는 칸 수를 stride라고 함 +- stride=2인 경우 출력은 3x3이 됨 +- stride=3인 경우 이미지의 사이즈에 맞아 떨어지지 않아 제대로 연산이 동작하지 않음 + +![Untitled (18)](https://user-images.githubusercontent.com/79077316/161549980-a9b3c778-6325-48d4-aeea-6c25b2d5cffd.png) + +- 스트라이드의 크기에 따라 출력 사이즈가 어떻게 될 것인지 알려주는 수식 +- 위 수식을 이용해서 어떤 크기의 필터를 사용해야 하는지, stride를 몇으로 했을 때 이미지에 꼭 맞는지, 출력의 사이즈는 어떻게 되는지 알 수 있음 +- stride가 클수록 출력은 점점 작아짐 + +**zero-padding** + +- 출력의 사이즈를 조절하는 방법 → 입력 사이즈와 출력 사이즈를 같도록 하기 위함 +- 바깥쪽 부분의 이미지 픽셀값이 상대적으로 덜 강조되는 문제를 해결하기 위한 방법 +- 이미지의 가장 자리에 0을 채워 넣는 방법 + +![Untitled (19)](https://user-images.githubusercontent.com/79077316/161549991-3ff7db5d-b494-442a-82b5-4472e4ed2246.png) + +- zero-padding을 적용하면0 N=9를 넣어 수식을 사용하면 됨 +- 위 예제의 경우 출력의 사이즈는 7x7x(필터의 개수) + +### 4) Brain Neuron 관점에서의 Conv layer + +![Untitled (20)](https://user-images.githubusercontent.com/79077316/161549998-c2f8c581-a54e-4eed-9662-eb8d73fa4dfa.png) + +- 전체 이미지의 특정 위치에 필터를 놓고 내적을 수행 +- 뇌의 뉴런과 다른 점은 우리 뇌의 뉴런은 local connectivity를 가지고 있음 + - conv layer처럼 슬라이딩을 해서 모든 부분과 연산을 하는 게 아니라, 우리 뇌의 뉴런은 특정 부분에만 연결되어 있음 + - 하나의 뉴런은 한 부분만 처리하고, 뉴런들이 여러 개가 모여서 전체 이미지를 처리하는 것임 +- 위 이미지에서 한 뉴런의 receptive field는 5x5임 + - receptive field란 한 뉴런이 한 번에 수용할 수 있는 영역을 의미 + +![Untitled (21)](https://user-images.githubusercontent.com/79077316/161550009-9e8b6094-47dd-4553-839c-c7be4aec2775.png) + +- 출력의 사이즈는 28x28x(필터의 개수) +- 파란색 volume 안에 5개의 점은 정확하게 같은 지역에서 추출된 서로 다른 특징임 + +### 5) Pooling layer + +![Untitled (22)](https://user-images.githubusercontent.com/79077316/161550021-223ac637-845e-4cb5-a0a8-bc6cc4e059ef.png) + +- CNN에는 conv layer 말고도 pooling layer가 있음 +- pooling layer는 representation을 더 작게 만듦 + - representation을 작게 하면 파라미터의 수가 줄게 됨 + - 공간적인 불변성도 얻을 수 있음 +- 결국 pooling layer가 하는 일은 downsampling +- 단, depth는 변하지 않음 + +![Untitled (23)](https://user-images.githubusercontent.com/79077316/161550027-b42a6ea8-571c-4f9e-83f9-d96b4af5ced0.png) + +- 일반적으로 max pooling이 많이 쓰임 +- 2x2 필터이고, stride=2일 때 필터 안에 가장 큰 값을 고르면 됨 +- conv layer 연산과 달리 pooling 할 때는 겹치지 않도록 하는 것이 일반적임 \ No newline at end of file diff --git a/Lecture06.md b/Lecture06.md new file mode 100644 index 0000000..00dec28 --- /dev/null +++ b/Lecture06.md @@ -0,0 +1,83 @@ +# CS231n Lecture 6 | Training Neural Networks part 1 +## 1. 활성화 함수 +### 1) 활성화 함수란? +- 뉴럴 네트워크에서는 노드에 들어오는 값들에 대해 곧바로 다음 레이어로 전달하지 않고 활성화 함수(Activation Function) 를 통과시킨 후에 전달 +- 언더피팅의 문제를 개선 +- 활성화 함수는 특정 featur에 대해 이 정보를 얼마나 활성화할 것인지를 할 결정하는 역할 +- 활성화 함수로 비선형 함수를 사용 -> non-linearity 제공 + +### 2) 활성화 함수의 종류 +![](https://user-images.githubusercontent.com/79077316/162682579-a239f6e9-fb92-4221-9c6d-013e4df7785f.png) +![](https://user-images.githubusercontent.com/79077316/162682584-625f5b09-b5e4-4252-b347-ffff766152ab.png) +![](https://user-images.githubusercontent.com/79077316/162682588-da122b00-2d38-496f-a10e-0e1c71330b9d.png) +![](https://user-images.githubusercontent.com/79077316/162682593-84ab638f-48c9-4dad-9bed-dcffb5222e33.png) +![](https://user-images.githubusercontent.com/79077316/162682605-9d65a575-cac8-4900-8ea2-80f0d4eaf0c1.png) + +**실전에서는...** +1. 디폴트로 ReLU를 사용하세요 +2. Leaky ReLU/Maxout/ELU 시도해 보세요 +3. tanh는 사용하더라도 기대는 하지 마세요 +4. 시그모이드는 더 이상 사용하지 마세요 + +## 2. 데이터 전처리 +### 1) 평균차감(Mean subtraction) +- 데이터의 모든 feature값에 대하여 평균값을 차감하는 방법 +![](https://user-images.githubusercontent.com/79077316/162682614-a26dda96-798a-4191-991e-c13458e23e2b.png) + +### 2) 정규화(normalization) +- 각 차원의 데이터가 동일한 범위 내의 값을 갖도록 하는 방법 + +**Feature Scaling '스케일을 조정한다'** +1. Standardization(z-score normalization) +2. Min-Max normalization +다만 이미지 데이터에서는 정규화가 필요하지 않다. Zero-centering only! (라고 강의에는 나오긴 한데, 해당 강의의 과제에서는 이미지 데이터에 대해서도 정규화를 한다...) +![](https://user-images.githubusercontent.com/79077316/162682621-ef9b657f-d7c8-46f5-83d3-918c93730c7f.png) + + +### 3) PCA와 Whitening +![](https://user-images.githubusercontent.com/79077316/162682626-ab3c258e-d2e1-4bb1-91a3-014f3a43e88a.png) + +- 머신러닝에서는 pca나 whitening 과 같은 더 복잡한 전처리 과정도 있긴 하지만 이 수업에서 다룰 이미지 데이터에서는 단순히 zero-centering 정도만 사용하고 normalization 이나 그 밖의 복잡한 방법들은 잘 사용하지 않음 + +## 3. 가중치 초기화 +- Q) 가중치의 초기화를 모두 0으로 설정한다면? + - 모든 뉴런들이 동일한 연산을 수행함 + - symmetry breaking이 일어나지 않음 + +- 가중치 초기화의 기본적인 아이디어 + - 0에 가까운 random number로 초기화 + - 정규분포 사용 + - Weight decay: 가중치 매개변수의 값이 작아지도록 학습하는 방법 + - 오버피팅을 억제하는 테크닉 + - 표준편차가 1인 정규분포로 가중치를 초기화할 경우, 신경망이 깊어지면 문제가 발생 -> vanishing gradient 발생 -> xavier 초기화 방법 등장 + +### xavier 초기화 방법 +![](https://user-images.githubusercontent.com/79077316/162682635-5544cb30-5126-43f2-ba26-1a867ce42061.png) + +- Xavier 초깃값은 이전 노드와 다음 노드의 개수에 의존하는 방법 +- 이렇게 이전 노드의 개수가 많아지면 그 수로 나눠주기 때문에 결국 weight 값이 작아지고, 반대로 들어오는 이전 뉴런의 개수가 적으면 weight 값은 커짐 +- 입력의 수가 적은 수더라도 큰 가중치와 곱해지기 때문에 히스토그램을 보면 saturation이 발생하지도 않고, 각 층의 활성화 값이 적당히 고루게 분포되어 있는 걸 확인할 수 있음 +- 하지만 xavier 초기값은 활성화 함수가 선형인 것을 전제로 한 결과이기 때문에 active regime 부분에서는 비교적 선형함수라고 볼 수 있는 시그모이드나 하이퍼볼릭 탄젠트 함수에서는 잘 사용이 되지만, 렐루함수를 이용할 때는 문제가 생김 -> He 초기값 등장 + +### He 초깃값 +![](https://user-images.githubusercontent.com/79077316/162682647-6a6bc32b-3f76-4c1d-9dca-c53468fb40dc.png) + +- He 초깃값은 xaiver function에서 표준편차를 루트 2배 해준 것 +- 히스토그램을 보면 xavier 초기값으로 가중치를 초기화한 경우는 층이 깊어지면서 치우침이 조금식 커지는데, he 초깃값을 이용한 경우는 훨씬 균일하게 분포되었고, 층이 깊어져도 분포가 균일한 것이 유지되는 것을 확인할 수 있음 +- 이러한 실험 결과를 바탕으로 활성화 함수로 렐루를 사용할 때는 He 초깃값을, 시그모이드나 하이퍼볼릭 탄젠트와 같은 s자 모양 곡선일 때는 xavier 초깃값을 사용 + +## 4. 배치 정규화 +- 활성화 값 분포가 적당히 퍼져 있는 것은 학습이 원활하게 수행됨 +- 배치 정규화를 통해 활성화 값 분포를 적당히 퍼트리도록 할 수 있음 +- Mini batch 단위로 정규화를 수행, 정규화 결과 평균은 0, 분산은 1이 됨 +- 활성화 함수의 앞/뒤에 BN Layer을 삽입 +![](https://user-images.githubusercontent.com/79077316/162682659-9298f93d-e8cc-4bfe-be54-9b1cbe73258a.png) +![](https://user-images.githubusercontent.com/79077316/162682671-e9eef54f-1952-4729-83a2-d3bd5de8b1a7.png) + +## 5. 하이퍼파라미터 최적화 +- cross-validation 전략 - coarse하기 시작해서 나중에 fine tuning하기 +- 처음에는 epoch로 작은 숫자를 줘서 반복을 여러 번 하지 않고, 두번째에 좀 더 running time을 길게 해서 세부적인 hyperparameter search를 시작 +![](https://user-images.githubusercontent.com/79077316/162682675-305b37bc-aed5-4697-9501-e7e07e452dc1.png) +![](https://user-images.githubusercontent.com/79077316/162682691-b698b7e7-f07a-4eac-a2e6-11fed31154db.png) + +- Hyperparmeter를 구하는 경우에 언제나 radom search의 방법으로! \ No newline at end of file diff --git a/Lecture07.md b/Lecture07.md new file mode 100644 index 0000000..5b472d9 --- /dev/null +++ b/Lecture07.md @@ -0,0 +1,91 @@ +# CS231n Lecture 7 | Training Neural Networks part 2 + +## 1. Fancier Optimization +### 1) Problems with SGD +- SGD는 미니 배치에서 데이터 loss를 계산하고, gradient의 반대 방향으로 파라미터를 업데이트 하는 방법 +- 지그재그 방향으로 loss가 최소인 점을 찾아가므로 convergence가 매우 느림 +- loss 함수에 local minima나 saddle point가 있는 경우 gradient descent가 멈춰버림 + - 고차원에서는 saddle point가 더 일반적으로 일어남 + +### 2) SGD + Momentum +- SGD에서는 X를 직접 연산식에 포함하는 반면 momentum에서는 속도 변수 vx 도입 +- gradinet를 계산할 때 gradient 방향과 velocity를 모두 고려 +- rho는 friction과 같아 velocity가 너무 커지지 않도록 마찰을 주는 것임(보통 0.9나 0.99로 설정) +- 모멘텀을 추가함으로써 노이즈가 평균화되어 더 매끄러워짐 + +### 3) Nesterov Momentum +- Nesterov Momentum은 gradient step을 계산하기 전에 momentum step을 미리 고려하는 방법 +- 시작점을 momentum step의 종료점으로 변경한 다음 gradient step을 evaluate하는 방법 +- NAG Nesterov Accelerated Gradient라고도 함 +- Nesterov Momentum은 그냥 momentum보다 항상 convergence rate이 좋음(convex에서만) +- 미리 velocity 방향을 예측해서 gradient를 구함 +- non-convex 그래프가 더 많은 neural network에서는 성능이 별로 좋지 않아 잘 쓰이지 않음 + +### 4) AdaGrad +- per-parameter adaptive learning rate method로서 각 매개변수에 맞춤으로 update하는 방법 +- grad squared를 구해서 이를 나눠줌 +- step을 진행할수록 분모가 커져서 X가 작아짐 + - 처음은 빠른 속도로 접근했다가 점차 속도가 느려지고 학습이 종료되는 문제가 있음 + - 이 문제를 해결하기 위해 나온 것이 RMSProp + +### 5) RMSProp +- AdaGrad에서 decay rate 개념을 도입 +- 누적된 gradient 제곱항에 decay rate을 곱해주고, 현재 gradient의 제곱항에는 (1-decay rate)을 곱해줌 + - 이를 통해 AdaGrad와 비슷하게 속도 조절이 가능함 + - 보통 decay_rate은 0.9 혹은 0.99를 이용 + +### 6) Adam +- momentum과 RMSProp 사이에 first moment와 second moment가 너무 작아지지 않게 하기 위해 bias correction 항을 추가 +- Adam with beta1=0.9, beta2=0.999, learning_rate=1e-3 or 5e-4면 아주 좋음! + +### 7) learning rate decay +- SGD, SGD+Momentum, Adagrad, RMSProp, Adam 모두 하이퍼파라미터 learning rate을 필요로 함 + - 모두 1차 미분을 활용한 first order optimization method +- learning rate decay개념을 도입한다!!! +- 처음에는 빠르게 convergence가 일어나므로 큰 learning rate을 적용하고 서서히 learning rate decay를 적용함으로써 그 값을 작게 만들어서 적용해줌 + - step decay + - exponential decay => 이 방법이 제일 많이 쓰임 + - 1/t decay + +**second-order optimization** +- Hessian을 도입함으로써 convergence가 매우 빨라지고, learning rate과 같은 hyperparameter가 필요 없게 됨 +- 하지만 딥러닝에서는 잘 사용하지 안 함!! Hessian은 nxn 행렬인데 딥러닝 파라미터 수가 몇 백개만 넘어가도 연산이 매우 힘들어짐 + +**실전에서는...** +- Adam이 좋은 default choic +- full batch이고 stochastic, parameter이 적다면 L-BFGS도 좋은 선택 + +### 8) Model Ensemble +- loss를 줄이면서 동시에 train과 val accuracy의 갭을 줄여야 함 => 갭을 줄이기 위해 사용하는 가장 간단하고 빠른 방법이 바로 앙상블(Ensemble) + 1. train multiple independent models + 2. at test time average their results + 여러 개의 모델을 만들고 이들의 평균을 이용하는 방법이다 + +**more tips and tricks** +- 모델을 독립적으로 학습시키는 방법이 아닌 학습 도중 중간 모델들을 저장(snapshot)하고 앙상블로 사용하는 방법 => test할 때는 여러 snapshoots의 예측값들의 평균을 사용 + +## 2. Regularization +### 1) Dropout +- 특정 노트를 랜덤하게 꺼버리는 방법 => forward pass에서 특정 뉴런의 활성화 값을 0으로 만들어 버림 +- feature 간의 상호작용을 방지함으로써 다양한 featrue 값들이 골고루 사용될 수 있도록 함 => overfitting 방지 +- 단일 모델로 앙상블 효과를 가질 수 있음 +- 함수에 z(random mask)가 추가됨 +- 이미 학습된 네트워크의 test time에 임의성을 부여하는 건 적절하지 않으므로 randomness를 average out시킴 +- 적분하기가 어려워 샘플링을 통해 적분을 근사시키는 방법을 이용함 +- test time의 기댓값이 train time의 절반밖에 되지 않으므로 네트워크의 출력값에 dropout probability(0.5)를 곱해줘야 함 +- dropout을 사용하면 학습 시간이 길어지지만, test data에 잘 일반화할 수 있는 모델을 만들 수 있음 + +### 2) Batch normalization + +### 3) Data Augmentation +- horizontal flips +- random crops and scales +- color jitter + - randomize contrast and brightness 학습시킬 때 이미지를 계속 바꿔주면서 학습을 시키면 regularization의 효과를 얻을 수 있음 + +## 3. Transfer Learning +- 전이학습은 CNN에서 모델을 학습시킬 때 데이터가 많이 필요할 것이라는 편견을 깬 아이디어 +- CNN layer에서 ImageNet과 같은 큰 데이터셋으로 학습시킴 +- 훈련된 모델을 우리가 가진 작은 데이터셋에 적용 +- 이미 정의한 가중치 행렬을 초기화시키고 나머지 layer들의 가중치는 freeze시킴(초기화한 layer만 재사용하는 것) +- learning rate을 조금 낮춰서 finetuning 해주면 좋음 \ No newline at end of file diff --git a/Lecture09.md b/Lecture09.md new file mode 100644 index 0000000..ee7f977 --- /dev/null +++ b/Lecture09.md @@ -0,0 +1,167 @@ +# CS231N Lecture9 | CNN Architectures + +> ImageNet 챌린지에서 우승한 모델들로, 대표적인 CNN 모델들(AlexNet, VGGNet, GoogleNet, ResNet)을 살펴볼 것이다. 이외에도 잘 사용하진 않지만 역사적으로 중요한 모델이나, 흥미로운 모델, 최신(2017 기준) 모델들도 다룰 것이다. + +> 앞으로 말하는 ‘네트워크가 깊다’는 것은 “학습 가능한 가중치를 가진 레이어”의 개수가 많은 것을 의미한다. 가령 conv layer나 FC layer를 말하고, 이때 pooling layer는 포함되지 않는다. + +## 0. LeNet + +- 실제로 성공적으로 사용된 최초의 conv net +- 숫자 인식에서 엄청난 성공을 거둠 + +## 1. AlexNet (2012) +![Untitled](https://user-images.githubusercontent.com/79077316/167327738-7f942639-e68c-423f-8494-8140511142cb.png) + +- 최초의 large scale CNN으로 LeNet-5와 기본 구조가 크게 다르지 않음 + - 2개의 GPU로 병렬연산을 수행하기 위해 병렬적인 구조로 설계된 것이 가장 큰 변화 +- ImageNet의 classification task에서 우승한 모델 +- CNN의 부흥을 일으킨 모델 +- 다양한 task의 transfer learning에 많이 사용되어 옴 +- 5개의 conv layer와 3개의 FC layer로 구성됨 + - conv1 - max pool1 - norm1 - conv2 - max pool2 - norm2 - conv3 - conv4 - conv5 - max pool3 - fc6 - fc7 - fc8 + - input 이미지의 크기는 227x227x3 + - 첫번째 layer의 출력 사이즈: 55x55x96(width x height x 필터의 개수) + - parameter의 수: (11x11x3)x96 = 35K개 + - 두번째 layer의 출력 사이즈: 27x27x96(depth의 크기는 변하지 않음) +- conv1 (첫 번째 layer) +- pooling layer + - 파라미터가 없음 + - 가중치가 없고 특정 지역에서 가장 큰 값을 추출하는 역할만 함 +- FC layer + - 4096개의 노드를 가진 레이어 + - FC8은 softmax 함수 사용 + +### Details/restropectives + +- 활성화함수로 ReLU를 사용 +- Data augmentation을 엄청 함 (flipping, jittering, color norm 등등) +- Drop out 0.5 - 학습 시 batch size는 128 +- SGD momentum 0.9 +- 초기 learning rate은 1e-2이고, val accuracy가 올라가지 않는 지점에서는 learning rate을 1e-10까지 줄임 +- L2 weight decay +- 모델 앙상블로 성능을 향상시킴 +- AlexNet 논문의 아키텍처와 관련된 이슈 - 위 그림에서는 첫 레이어가 224x224라고 되어 있지만 실제 입력은 227x227 + +다른 Conv Net과의 차이점 -> 모델이 두 개로 나눠져서 서로 교차함 + +- 모델의 기본 구조가 병렬 구조로 이루어져 있으며 두 개로 나눠져서 서로 교차함 → 네트워크를 GPU에 분산시켜서 넣음 + - 첫 번째 레이어의 출력이 55x55x96이고, 각각의 GPU에서의 depth가 48 + - 두 개의 GPU에서 feature map을 절반씩 나눠가짐 + - conv1, 2, 4,5에서는 같은 GPU 내에 있는 feature map(48개)만 사용 + - 반면에 conv3, FC6, 7, 8은 전체 feature map(98개)과 연결되어 있음 + +## 2. VGGNet (2014) +![2](https://user-images.githubusercontent.com/79077316/167327740-cf7e068a-1e85-4aab-8f32-d1534e41b379.png) +- 2014년도 ImageNet challenge의 classification task에서 2등한 oxford의 모델 +- localization challenge 등 다른 task에서는 1등한 모델 +- 이전 모델들과 비교했을 때 네트워크가 훨씬 기어지고 더 작은 필터를 사용함 +- AlexNet에서는 8개의 레이어였지만 VGGNet에서는 16-19개의 레이어를 가짐 +- 3x3 사이즈의 아주 작은 크기의 필터만 사용 + - 필터의 크기가 작으면 파라미터의 수가 더 적어지고, 큰 필터를 사용했을 때보다 레이어를 더 많이 쌓아서 네트워크를 더 깊게 만들 수 있음(depth⬆) +- 3x3 필터를 3개 쌓은 것은 결국 7x7 필터를 사용하는 것과 동일한 receptive field를 가짐 + - receptive field는 filter가 한 번에 볼 수 있는 입력의 sparical area + - 7x7 필터와 동일한 receptive field를 가지면서도 더 깊은 레이어를 쌓게 됨 + - 네트워크를 더 깊게 함으로써 non-linearity를 더 추가할 수 있고, 파라미터의 수도 더 적어짐 (depth c인 네트워크에 대해 3x3 필터를 3개 사용할 경우 파라미터의 수는 3x3xCxCx3, 7x7 필터인 경우 7x7xCxC) +- 네트워크가 깊다는 것은 학습 가능한 가중치를 가진 레이어의 개수가 많다는 것을 의미 + +### **Details** + +- Local Response Normalization 사용 안 함 +- 성능 향상을 위해 앙상블 기법 사용 +- VGG19가 메모리를 조금 더 쓰지만 성능이 좀 더 좋음 +- 보통 VGG16을 더 많이 사용함 + +## 3. GoogleNet (2014) +![](https://user-images.githubusercontent.com/79077316/167327742-8d48da73-b2c7-477c-83c5-fb7e4ab40eeb.png) + +- 2014년도 ImageNet challenge 우승 모델 +- 22개의 layers +- **Inception module**을 여러 개 쌓아서 만듦 +- 파라미터의 수를 줄이기 위해 FC-layer를 없앰 +- 네트워크가 훨씬 깊은데도 전체 파라미터 수는 5M 정도로 AlexNet(60M)보다 적음 + +![](https://user-images.githubusercontent.com/79077316/167327745-5753410f-2302-4b77-979c-4eb66588f0fe.png) + +- “network within a network”라는 개념으로 local topology를 구현 +- 각각의 local network가 Inception module +- 위 그림은 기본적인 Inception module(naive version) +- 내부에는 동일한 입력을 받는 서로 다른 다양한 크기의 필터들이 **병렬적**으로 존재함 + - 이는 다양한 feature를 뽑기 위해 여러 종류의 convolution filter를 병렬적으로 사용한 것임 +- 다양한 연산을 수행하고 이를 하나로 합치는 단순한(naive) 방식에는 여러 문제가 있음 + - 계산 비용의 문제. 연산량이 매우 많아짐 + - pooling layer에서 depth가 그대로 유지돼서 레이어를 거칠 때마다 다른 레이어의 출력이 계속해서 더해져서 depth가 점점 커짐 + 👉🏻 **bottleneck layer**를 사용해서 해결! + + +**bottleneck layer** + +- conv 연산을 수행하기 전에 입력을 더 낮은 차원으로 보냄 +- 입력의 depth를 더 낮은 차원으로 projection 함 +- Feature depth를 줄이기 위해 1x1 conv layer 사용 +- input feature map들 간의 선형결합(linear combination)이라고 할 수 있음 + +![](https://user-images.githubusercontent.com/79077316/167327751-fbc93d44-361e-4a0e-88a2-67025d38ee2a.png) + +- GoogleNet의 앞단(stem)은 일반적인 네트워크 구조 +- 가중치를 가진 학습 가능한 레이어의 개수는 22개 +- 각 Inception module은 1x1/3x3/5x5 conv layer를 병렬적으로 가지고 있음 +- 앞단 이후에 Inception module을 쌓아올리고 마지막에 classifier 결과를 출력 +- 보조분류기(auxiliary classifier)가 추가됨 + - average pooling과 1x1 conv가 있고 FC-layer도 있음 + - softmax로 ImageNet 클래스 분류 + - ImageNet trainset loss 계산 + - 네트워크가 깊어서 네트워크의 끝 뿐만 아니라 보조분류기에서도 loss를 계산함 + - 보조분류기를 추가함으로써 그레디언트를 얻게 되고, 중간 레이어의 학습을 도움 + +## 4. ResNet (2015) + +![](https://user-images.githubusercontent.com/79077316/167327757-24af8186-bdfd-4b7b-86bf-dde6b63632a5.png) + +- 2015 ILSVRC 우승한 모델 +- 152개의 layer로 네트워크의 깊이가 매우 깊은 모델 +- DNN에서 layer를 깊게 쌓을수록 성능이 더 좋아질 것이라고 예상했지만, 실제로는 20개 이상부터는 성능이 낮아지는 degradation 문제 발생 +- ResNet은 Residual learning이라는 방법을 통해 모델의 층이 깊어져도 학습이 잘 되도록 구현한 모델 + +### Residual Learning +- 56 Layer의 CNN과 20 Layer의 CNN을 비교하여 테스트했을 때, test error가 56 Layer의 CNN이 더 높았음 +- training error 역시 56 Layer CNN이 더 안 좋은 것으로 보아 성능이 낮은 이유가 overfitting 때문이 아님을 알 수 있음 +- ResNet 저자들이 내린 가설은 더 깊은 모델 학습 시 optimization에 문제가 생긴다는 것. 즉 모델이 깊어질수록 최적화가 어렵다. +- “네트워크의 깊이가 더 깊다면 적어도 더 얕은 모델만큼의 성능은 나와야 한다” 이 추론을 이용해서 더 얕은 모델의 가중치를 더 깊은 모델의 일부 레이어에 복사. 나머지 레이어는 identity mapping(input을 그대로 output으로). 이렇게 하면 적어도 shallower model만큼의 성능은 보장됨 +- 레이어를 단순하게 쌓지 않음으로써 위 motivation을 모델 아키텍처에 적용 + +![](https://user-images.githubusercontent.com/79077316/167327759-3a86d173-b7e1-46dc-9c48-a357a636a174.png) +👉🏻 Direct mapping 대신 Residual mapping을 하도록 블럭을 쌓는다! + +- H(x)를 바로 학습하기보다 H(x)-x를 학습하도록! -> 이를 위해 skip connection 도입! +- 오른쪽 그림의 skip connection은 가중치가 없고, 입력은 identity mapping으로 그대로 output으로 내보냄 +- 최종 출력값인 H(x)=F(x)+x에서 x는 input이 되고, F(x)는 변화량(delta, residual). 즉 최종 출력 값은 **input X + 변화량(Residual)** +- 결국 네트워크는 변화량(residual)만 학습하면 됨. H(x)를 직접 학습하는 대신 Residual를 학습하는 것이 훨씬 쉬울 것이라고 생각. +- Identity Mapping에 가까운 값을 얻기 쉬움 ( F(x)=0 ) +- ResNet은 이처럼 residual block들을 쌓아 올린 구조 + +### Details + +![](https://user-images.githubusercontent.com/79077316/167327764-48896a15-6165-4670-abec-f620cfc74772.png) +- 각각의 Residual block은 두 개의 3x3 conv layers로 이루어져 있음 +- 주기적으로 필터를 두 배씩 늘리고 stride 2를 이용해서 downsampling을 수행 +- 네트워크 초반에는 Conv-layer가 추가적으로 있고 네트워크 끝에는 FC-layer가 없음 +- Global Average Pooling을 사용 + - 하나의 Map 전체는 Average pooling +- 마지막에는 1000개의 클래스 분류를 위한 노드가 붙음 +- ResNet의 경우 모델의 depth가 50 이상일 때 GoogleNet과 유사하게 Bottleneck Layer를 도입함 + - 1x1 Conv layer를 도입하여 초기 필터의 depth를 줄여줌 +- ResNet은 Conv layer 뒤에 모두 Batch Norm을 사용 +- 가중치 초기화는 Xavier/2를 사용 +- SGD + Momentum (0.9) +- Minibatch size 256 +- weight decay 적용 +- Drop out은 하지 않음 + +## 5. 모델별 Complexity + +![](https://user-images.githubusercontent.com/79077316/167327773-da920b24-fbb6-47eb-90af-c6d3e623bd7c.png) + +- 오른쪽 그래프에서 원의 크기는 메모리 사용량을 나타냄 +- VGG - 가장 효율성이 떨어짐. 메모리 사용량도 크고 연산량이 많음 +- AlexNet - 계산량이 작지만, 메모리 사용량이 크고 비효율적. 정확도도 낮은 편 +- ResNet - 메모리 사용량과 계산량은 중간 정도이지만 accuracy는 최상위 \ No newline at end of file diff --git a/Lecture10.md b/Lecture10.md new file mode 100644 index 0000000..96a3b7d --- /dev/null +++ b/Lecture10.md @@ -0,0 +1,160 @@ +# CS231N Lecture10 | RNN + +## 1. RNN이란? +- Vanilla Neural Network - one to one + +![다운로드](https://user-images.githubusercontent.com/79077316/168616004-9f71308d-5f8d-41c0-9bc0-07ff5f5b4828.png) + +- 지금까지 배운 아키텍처의 모양 +- 이미지 또는 벡터를 input으로 받고, hidden layer를 거쳐서 하나의 출력을 내보냄 + +### RNN(Recurrent Neural Networks) + +![다운로드 (2)](https://user-images.githubusercontent.com/79077316/168616001-8d2671bc-5024-48ff-b993-e78f38ab2e33.png) + +- RNN은 가변 길이의 입/출력(데이터)을 다루기 위해 필요한 방법 +- RNN은 작은 "Recurrent Core Cell"를 가지고 있음 +- RNN은 내부에 hidden state를 가지고 있음 +- hidden state는 새로운 입력이 들어올 때마다 매번 업데이트 됨 + 1. RNN이 입력을 받는다. + 2. 모든 스텝마다 'Hidden state'를 업데이트한다. + 3. 출력값을 내보낸다. + +- one to many: Image Captioning +- many to one: Sentiment Classification +- many to many: Machine Translation/Video classification on frame level + +### RNN의 구조 + +![다운로드 (3)](https://user-images.githubusercontent.com/79077316/168615999-cc7d8144-00e0-49f3-b61e-cf6c1de4ab35.png) + +- 매 스텝마다 x_t가 들어오고 기존의 h_t-1를 입력으로 받아 h_t를 업데이트 +- h_t는 f의 출력으로 다음 상태의 hidden state +- f의 인풋은 이전 상태의 hidden state인 h_t-1과 현재 상태의 입력상태인 x_t +- 다음 단계에서는 h_t와 x_t+1이 f의 인풋이 됨 +- RNN에서 출력 값을 가지려면 h_t를 입력으로 하는 FC-layer를 추가해야 함 +- 이때 f와 w는 매 스텝마다 동일함 + +![다운로드 (4)](https://user-images.githubusercontent.com/79077316/168615995-e965c3e9-ad68-4070-a0ae-22a613cfaa6e.png) + +- 이때 tanh는 비선형성을 구현하기 위해 사용됨 +- RNN이 hidden state를 가지며 이를 재귀적으로 feedback함 + +### RNN의 computational graph + +![다운로드 (5)](https://user-images.githubusercontent.com/79077316/168615992-a3c99c1c-edef-4b42-a72b-2856ebcb5b7f.png) + +- 첫 스텝에서 initial hidden state인 h_0은 보통 0으로 초기화 +- 출력인 h_1이 다시 입력으로 들어가서 이 과정이 재귀적으로 반복됨 + +![다운로드 (6)](https://user-images.githubusercontent.com/79077316/168615990-230e5a0f-e425-4ee8-be80-a4f95d396340.png) + +- 똑같은 set의 파라미터를 가지고 업데이트함 +- 동일한 가중치 행렬이 매번 사용됨 + +![다운로드 (7)](https://user-images.githubusercontent.com/79077316/168615985-2251b24e-d516-4456-9f30-ce370f54abe0.png) + +- 각 스텝마다 개별적으로 y_t에 대한 loss를 계산할 수 있음 +- RNN의 최종 loss는 각 개별 loss들의 합임 + +![다운로드 (8)](https://user-images.githubusercontent.com/79077316/168615984-6a113fed-e990-4773-8c00-26d87aeb227f.png) + +- 최종 hidden state에서만 출력 값을 가짐 + +![다운로드 (9)](https://user-images.githubusercontent.com/79077316/168615981-6a98c982-f9da-4de2-acee-2ac8ded4fd7e.png) + +- 고정입력을 받지만 가변출력인 경우 +- 고정입력인 x는 모델의 initial hidden state를 초기화시키는 용도로 사용 +- 모든 스텝에서 출력 값을 가짐 + +![다운로드 (10)](https://user-images.githubusercontent.com/79077316/168615979-9ce6ca03-7c50-451f-8c37-a3fc663d689c.png) + +- machine translation에 사용할 수 있는 모델 +- 가변입력과 가변출력을 가짐 +- many to one과 one to many의 결합으로 볼 수 있음 +- many to one: encoder로서 가변입력을 받음. 가변 입력을 하나의 벡터로 요약함 +- one to many: decoder로서 앞에서 요약한 하나의 벡터에 대해 가변출력을 내보냄 + +### Character-level Language Model +- 문자열 시퀀스를 입력으로 받아서 다음 문자를 예측하는 모델 +- RNN은 대개 language modeling에서 자주 사용됨 + +![다운로드 (11)](https://user-images.githubusercontent.com/79077316/168615976-d37bfb2c-8935-4ef7-9b4a-43f8da00daa9.png) + +- h, e, l, o라는 문자들이 있고, 문자열 "hello"를 만들고 싶다고 하자 +- input 문자들을 벡터로 만든 다음 함수식을 이용해서 hidden layer의 값을 구함 + +![다운로드 (12)](https://user-images.githubusercontent.com/79077316/168615973-0b188941-7fb2-4dff-a7d5-b7404decfc07.png) + +- 스코어를 확률 분포로 표현하기 위해 softmax함수를 사용함 +- 인풋에 문자 "h"가 주어지면 output layer에서 모든 문자(h, e, l, o)에 대한 스코어를 얻을 수 있음 +- test-time에 이 스코어를 sampling하여 다음 문자 선택에 이용 + +### Backpropagation through time +- 위의 모델을 train시키려면 하나의 출력값을 알기 위해서 모든 loss 값들을 알아야 함 +- 연산량이 엄청 많아짐 + +![다운로드 (13)](https://user-images.githubusercontent.com/79077316/168615969-45ae0646-bd0b-4e9b-be8f-c0f179758b88.png) + +### Truncated Backpropagation through time +- 실제로는 Truncated Backpropagation through time을 통해서 backprob을 근사시키는 방법을 이용함 +- train할 때 한 스텝을 일정한 단위로 나눈 후 서브시퀀스의 loss들만 계산함 + +![다운로드 (14)](https://user-images.githubusercontent.com/79077316/168615964-2f878c01-bb20-4387-86f1-56b6e084dd6a.png) + +## 2. Image Captioning +- CNN과 RNN을 혼합한 대표적인 방법 +- Image captioning 모델의 입력은 이미지이고, 출력은 자연어로 된 caption + +![다운로드 (15)](https://user-images.githubusercontent.com/79077316/168615960-bd1b1c4d-2541-4380-adfb-af6cc37ac9b2.png) + +- CNN에서 입력 이미지를 받아 요약된 이미지 정보가 있는 vector를 출력 +- CNN의 벡터는 RNN의 초기 step의 입력으로 들어감 +- RNN에서는 caption에 사용할 문자들을 만들어냄 + +![다운로드 (16)](https://user-images.githubusercontent.com/79077316/168615959-161c446e-1a4c-4309-a9e5-cc1560551ac4.png) + +- 마지막에 END라는 토큰으로 문장의 끝을 알려줌 +- END가 샘플링되면 모델은 더이상 단어를 생성하지 않고 이미지에 대한 caption이 완성됨 +- 이 모델은 supervised learning으로 학습시킴 + +### Image captioning with Attention +- caption을 생성할 때 이미지의 다양한 부분에 더 집중 + +![다운로드 (17)](https://user-images.githubusercontent.com/79077316/168615956-baf560e2-5a2e-44e4-9d01-ea2f4be63c99.png) + +- 모델이 이미지에서 보고싶은 위치에 대한 분포를 만들어냄 -> 이는 train time에 모델이 어느 위치를 봐야하는지에 대한 attention +- 첫번째 hidden state인 h_0은 이미지의 위치에 대한 분포를 계산(a1) +- a1을 다시 벡터 집합과 연산하여 이미지 attention(z1)을 만들어냄 + +![다운로드 (18)](https://user-images.githubusercontent.com/79077316/168615944-dd6a2c69-979c-4574-b999-b5565bd0b744.png) + +- z1은 다시 다음 스텝의 입력으로 들어감 +- 다음 스텝부터는 단어들의 분포인 d_t까지 두 개의 출력이 생성됨 +- 결과를 보면, 모델이 caption을 생성할 때 더 의미있는 부분에 attention을 집중하는 것을 알 수 있음 +- RNN + Attention 조합은 image captioning 뿐만 아니라 Visual Question Answering(VQA)에서도 사용됨 + +## 3. LSTM +- 하지만 일반적인 RNN은 잘 사용하지 않음 +- backward pass에서 gradient를 계산할 때의 문제점이 있는데... + +![다운로드 (19)](https://user-images.githubusercontent.com/79077316/168616009-d2d04099-e1a2-44f4-b2dc-e7977b87ab8c.png) + +- 매번 RNN cell을 통과할 때마다 가중치 행렬을 곱하게 됨 +- h_0의 gradient를 구하려면 모든 RNN cell을 거쳐야됨 + +![다운로드 (20)](https://user-images.githubusercontent.com/79077316/168616007-05692d94-1955-4b75-bf62-465a5fc500c2.png) + +- exploding gradient는 Gradient clipping 기법을 사용하여 해결함 +- gradient의 L2 norm이 임계값보다 큰 경우 gradient가 최대 임계값을 넘지 못하도록 조정해줌 +- vanishing gradient의 문제는 조금 더 복잡한 RNN 아키텍처를 도입해서 해결해야 함 -> LSTM + +### LSTM +- Long Short Term Memory로 RNN의 vanishing gradient와 exploding gradients의 문제를 해결하기 위해 디자인됨 + +![다운로드 (21)](https://user-images.githubusercontent.com/79077316/168616005-2deb243f-aa6e-49ec-8e84-9edce1109d6a.png) + +- 한 셀당 2개의 hidden state가 있음 +- 각 gate마다 사용하는 non linearity가 다름 +- 2개의 값을 입력으로 받고 쌓은 다음 4개의 gates를 계산하기 위해 가중치 행렬을 곱해줌 +- 각 gate의 출력은 hidden state의 크기와 동일 \ No newline at end of file diff --git a/Lecture12.md b/Lecture12.md new file mode 100644 index 0000000..5ca7817 --- /dev/null +++ b/Lecture12.md @@ -0,0 +1,157 @@ +# CS231N Lecture12 | Visualizing and Understanding + +CNN의 내부는 어떻게 생겼을까? 네트워크의 중간과정을 확인할 방법은 없을까? +가장 만만하게 접근해 볼 수 있는 게 **first layer**를 시각화하는 방법! + +## 1\. Visualize First layer + +![다운로드](https://user-images.githubusercontent.com/79077316/173313985-21fcae1b-70e8-4185-9a37-79b0f472b7b1.png) + +conv layer의 학습된 가중치들을 시각화해서 필터들이 무엇을 찾는지 알 수 있다. 엣지 성분과 다양한 각도와 위치에서의 보색이 나타난다. conv filter와 이미지의 일부영역과 내적한 결과가 첫번째 layer의 출력이다. +중간 레이어들도 시각화할 수 있긴 하지만, 필터들이 이미지와 직접 연결되어 있지 않기 때문에 가중치들을 시각화한다 해도 이를 해석하는 것은 쉽지 않다. + +## 2\. Visualize Last layer + +### 1) Nearest Neighbors + +마지막 hidden layer를 시각화하는 방법은 nearest neighbors를 이용한 방법이다. CNN(AlexNet)에서 나온 4096 차원의 feature vector에서 nearest neighbors를 계산한 결과는 다음 그림과 같다. + +![다운로드 (2)](https://user-images.githubusercontent.com/79077316/173313993-335a4866-3d39-45df-85f7-13104b0742b5.png) + +### 2) 차원 축소 Dimensionality Reduction (PCA) + +최종 레이어에서 어떤 일어나는지를 시각화하는 것을 '차원 축소'의 관점으로 볼 수도 있다. + +![다운로드 (3)](https://user-images.githubusercontent.com/79077316/173314004-2a684648-d226-41fb-ab1e-3b9d4c8d9ec9.png) + +차원 축소를 위한 간단한 알고리즘으로 **PCA(Principle Component Analysis)** 가 있다. 4096차원과 같은 고차원의 특징 벡터들을 2차원으로 압축시키는 기법이다. PCA 기법을 통해 특징 공간을 더 직접적으로 시각화시킬 수 있다. +PCA보다 더 강력한 알고리즘으로 **t-SNE 알고리즘** 이 있다. 위 그림에서 t-distributed Stochastic Neighbor Embeddings 알고리즘으로 28x28차원의 이미지를 입력으로 받아서 2차원으로 압축하여 다음과 같이 회색조로 시각화할 수 있다. + +## 3\. Visualizing Activations + +AlexNet의 conv5 layer는 3차원의 값(width x height x depth)을 반환한다. 이 3차원의 덩어리가 바로 네트워크의 레이어가 출력하는 값이고, 이를 **'activation volume'** 이라고 한다. 이 덩어리를 하나씩 잘라낸 것을 **activation map** 이라고 한다. + +### 1) Maximally Activating Patches + +어떤 이미지가 들어와야 각 뉴런들의 활성이 최대화되는지 시각화하는 방법이다. + +![다운로드 (4)](https://user-images.githubusercontent.com/79077316/173314045-2c7cd1bd-8a3d-4314-951b-0b5c8940c952.png) + +AlexNet의 conv5 layer를 선택했고, 128개의 채널 중에 17번째 채널을 선택했다. 어떤 이미지가 17번째 activation map을 최대로 활성화 시키는지를 시각화한 결과이다. 각각의 그림은 해당 레이어의 활성을 최대화시키는 패치들을 나타낸 것이다. + +### 2) Occlusion Experiments + +![다운로드 (5)](https://user-images.githubusercontent.com/79077316/173314037-cd93dfc1-914d-4cc5-b230-7aba4c25c4ba.png) + +입력의 어떤 부분이 분류를 결정짓은 근거가 되는지에 대한 실험이다. +먼저 입력 이미지의 일부를 가림패치(occlusion patch)로 가린다. 가린 부분은 데이터의 평균값으로 채운다. 이 이미지를 네트워크에 통과시키고, 네트워크가 이미지를 예측한 확률을 기록한다. 가림패치를 전체 이미지에 대해 돌아가면서(slide) 같은 과정을 반복한다. + +✔️이 실험의 아이디어는 만약 이미지의 일부를 가렸는데, 네트워크 score의 변화가 크게 발생한다면 가려진 부분이 분류를 결정짓는 중요한 부분이었을 것! ~> 이런 시각화는 네트워크의 성능을 높이는 것이 아닌 개발자의 이해가 목적! + +### 3) Saliency Maps + +![다운로드 (6)](https://user-images.githubusercontent.com/79077316/173314054-8dd913f2-01d0-459d-9b1f-5e1c75400434.png) + +입력 이미지의 각 픽셀들에 대해서 예측한 클래스 스코어의 그래디언트를 계산하는 방법이다. '1차 근사적 방법'으로 어떤 픽셀이 영향력 있는지를 알려준다. + +### 4) Intermediate Features via Guided backprop + +![다운로드 (7)](https://user-images.githubusercontent.com/79077316/173314104-664d54a2-348f-4b83-9c86-3d1cb5b8e2a6.png) + +backprop시 전체 네트워크가 '양의 부호인 gradient'만을 고려하는 방법이다. +네트워크의 중간 뉴런을 하나 고르고, 입력 이미지의 각 픽셀에 대한 네트워크 중간 뉴런의 그래디언트를 계산한다. guided backprop시 ReLU를 통과할 때 ReLU의 gradient의 부호가 양수이면 그대로 통과시키고, 부호가 음수이면 backprop하지 않는다. 훨씬 더 선명하고 좋은 이미지를 얻을 수 있다. + +## 4\. Visualizing CNN features: Gradient Ascent + +![다운로드 (8)](https://user-images.githubusercontent.com/79077316/173314101-02dc1ca1-cc92-400a-b967-46e0c164bc0d.png) + +입력 이미지에 의존하지 않고 cnn feature를 시각화하는 방법이다. 네트워크의 weight는 고정시키고, 특정 뉴런을 활성화시키는 '일반적인' 입력 이미지를 찾아내는 방법이다. +함수 식에 regularization term도 추가되었는데, 생성되는 이미지가 특정 네트워크의 특성에 오버피팅되는 것을 방지하기 위함이다. regularization term을 추가함으로써 + +- 1) 생성된 이미지가 특정 뉴런의 값을 최대화시키는 방향으로 생성되도록 하고, +- 2) 생성된 이미지가 자연 상태에서 잘 볼 수 있도록 + +되길 원한다. 결국, 생성된 이미지가 비교적 자연스럽도록 강제하는 역할을 한다. 여기서 I\* 가 이미지의 픽셀 값을 나타낸다. + +![다운로드 (9)](https://user-images.githubusercontent.com/79077316/173314097-99606a41-352e-4444-bfcc-52fd0f51a8e0.png) + + +일반적인 이미지를 만들어내는 방법은 다음과 같다. + +1. gradient ascent를 위한 초기 이미지들을 zeros, uniform, noise등으로 초기화시켜준다. +2. 초기화를 하고 나면 이미지를 네트워크에 통과시켜서 스코어 값을 계산한다. +3. 이미지의 각 픽셀에 대한 해당 뉴런의 스코어의 gradient를 계산하여 backprop을 수행한다. +4. gradient ascent를 이용해서 이미지 픽셀 자체를 업데이트 한다. (해당 스코어를 최대화시키려 함) + 그리고 생성된 이미지에 대해 L2 norm을 계산해서 더해준다. + +![다운로드 (10)](https://user-images.githubusercontent.com/79077316/173314112-a9760fe4-2809-43e8-aa30-f6624fa5a96e.png) + +## 5\. Deep Dream + +DeepDream의 목적은 '재미있는 이미지를 만드는 것'이다. + +![다운로드 (11)](https://user-images.githubusercontent.com/79077316/173314187-1a1949a1-e744-496e-ab6f-f6b2f8dfedad.png) + +1. 입력 이미지를 cnn의 중간 레이어를 통과시키고, +2. backprop을 할 때 해당 레이어의 그래디언트를 activation 값으로 설정한다. +3. backprop을 해서 이미지를 업데이트하는 과정을 계속 반복한다. + +이를 네트워크가 해당 이미지에서 뽑아낸 특징들을 증폭시키려는 것으로 해석할 수 있다. 그리고 이는 해당 레이어에서 나온 특징들의 L2 norm을 최대화시키는 것으로도 볼 수 있다. 위의 구름 이미지에 대해 다음과 같은 결과를 얻을 수 있다. + +![다운로드 (12)](https://user-images.githubusercontent.com/79077316/173314178-07916928-54cf-46f3-ba2f-b5c116475bd6.png) + +## 6\. Feature Inversion + +이 방법은 네트워크의 다양한 Layer에서 어떤 요소들을 포착하고 있는지 짐작할 수 있는 방법이다. + +![다운로드 (13)](https://user-images.githubusercontent.com/79077316/173314171-91977700-1f0e-40df-a750-3d3f0e61b7c3.png) + +방법은 다음과 같다. 어떤 이미지를 네트워크에 통과시키고, 네트워크를 통과시켜 얻은 activation map을 저장해둔다. 그리고 이 activation map만 가지고 이미지를 재구성한다. +이 방법에서 regularizer를 추가한 gradient ascent를 이용한다. 스코어를 최대화하는 방법 대신 특징 벡터의 거리가 최소화하는 방향으로 update를 시킨다. 여기서 **total variation regularizer** 은 상하좌우 인접 픽셀 간의 차이에 대한 패널티를 부여하여 생성된 이미지가 자연스러운 이미지가 되도록 해준다. + +![다운로드 (14)](https://user-images.githubusercontent.com/79077316/173314190-f872236e-efd4-4a37-a4ad-0d8147c036ba.png) + +## \+ Texture Synthesis + +텍스처 합성은 구조적 컨텐츠를 활용하여 작은 디지털 샘플 이미지에서 큰 디지털 이미지를 알고리즘적으로 구성하는 과정이다. + +1) nearest neighbor를 통한 텍스처 합성 방법(고전적인 방법) + +신경망 대신에 scan line을 따라서 한 픽셀씩 이미지를 생성해 나가는 방식이다. + +2) neural texture synthesis + +Neural texture synthesis 를 구현하기 위해서 Gram matrix라는 개념을 이용한다. +**Gram Matrix** 란 서로 다른 공간 정보에 있는 Channel들을 가지고 외적을 계산하여 새로운 Matrix를 만드는 것을 말한다. 이 Matrix는 특징 벡터간 다양한 상관 관계를 한 번에 나타낼 수 있도록 만들어졌다. + +![다운로드 (15)](https://user-images.githubusercontent.com/79077316/173314248-02fe3b40-5119-4f55-b35f-e934670ec562.png) + +과정은 Gradient Ascent 과정과 비슷하다. 좀 더 깊은 레이어에서 생성한 gram matrix를 이용해야 텍스처 합성에 잘 활용할 수 있다! + +![다운로드 (16)](https://user-images.githubusercontent.com/79077316/173314245-8ed472b2-2fd8-477e-80d1-1e1736dc017c.png) + +## 7\. Neural Style Transfer + +텍스처 합성을 예술에 적용한 개념이 바로 Neural style transfer이다. Gram Matrix를 재구성하는 것과 Feature를 재구성 하는 것을 합하여 만들어진 이미지 결과가 Neural Style Transfer이다. + +![다운로드 (17)](https://user-images.githubusercontent.com/79077316/173314241-87287d6c-5a62-456c-9410-3a635fb662f0.png) + +Neural Style Transfer에서는 입력이 두 가지이다. + +- 첫 번째 Content Image는 우리의 최종 이미지가 어떻게 생겼으면 좋겠는지 알려주는 이미지이고, +- 두 번째 Style Image는 최종 이미지의 Texture가 어떻게 생겼으면 좋겠는지 알려주는 이미지이다. + 최종 이미지는 Content Image의 Feature Reconstruction Loss도 최소화하고, Style Image의 Gram Matrix Reconstruction Loss도 최소화하도록 만들어진 이미지이다. + +하지만 Neural Style Transfer는 수많은 forward, backward 과정을 반복해야 하므로 굉장히 느리다는 단점이 있다. 따라서 Style Transfer를 위해 네트워크를 학습시키는 또 다른 방법이 있다. + +![다운로드 (18)](https://user-images.githubusercontent.com/79077316/173314252-33efc8b8-ce20-4801-8d8d-0af6a682f3b2.png) + +### Fast Style Transfer + +합성하고자 하는 이미지의 최적화를 전부 수행하는 것이 아니라 Content Image만을 입력으로 받아서 단일 네트워크를 학습시키는 방법이다. + +이 네트워크 학습시에는 content loss와 style loss를 동시에 학습시키고 네트워크의 가중치를 업데이트를 시킨다. 학습은 좀 오래걸리지만 한 번 학습을 시키고 나면 이미지를 네트워크에 통과시키면 결과를 바로 볼 수 있다. + +앞서 본 Style Transfer의 단점은 네트워크 하나당 하나의 Style Transfer만을 만들 수 밖에 없다는 점이다. 이에 구글에서 Content Image와 Style Image를 동시에 넣는 방식으로 다양한 스타일을 만들어 내는 논문을 제안했다. + +![다운로드 (19)](https://user-images.githubusercontent.com/79077316/173314251-5a2f0fa0-1c40-4449-98f8-bc04d738f3a0.png) \ No newline at end of file diff --git a/Pytorch_ImageClassification.md b/Pytorch_ImageClassification.md new file mode 100644 index 0000000..a2beb25 --- /dev/null +++ b/Pytorch_ImageClassification.md @@ -0,0 +1,181 @@ +# Pytorch로 이미지 분류 실습하기 + +다음과 같은 단계로 이미지 분류를 실습할 수 있다. + +1. CIFAR10 데이터셋을 로드하고 정규화 한다. `torchvision` +2. Convolutional Neural Network을 define한다. +3. Loss funcion을 define한다. +4. 학습 데이터를 이용해서 네트워크를 훈련시킨다. +5. 테스트 데이터를 이용해서 네트워크를 테스트한다. + +## 1. **Load and normalize CIFAR10** + +`torchvision` 을 이용해서 CIFAR10 데이터셋을 로드한다. + +```python +import torch +import torchvision +import torchvision.transforms as transforms +``` + +Torchvision 데이터 세트의 출력은 [0, 1] 범위의 PILImage 이미지이다. 정규화된 범위 [-1, 1]의 텐서로 변환한다. + +> PILImage란 이미지 분석 및 처리를 쉽게 할 수 있는 라이브러리(python imaging library, PIL)이다. pillow 모듈이라고 하고, 다양한 이미지 파일 형식을 지원하는 이미지 프로세싱 라이브러리의 한 종류이다. + + +```python +transform = transforms.Compose( + [transforms.ToTensor(), + transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) + +batch_size = 4 + +trainset = torchvision.datasets.CIFAR10(root='./data', train=True, + download=True, transform=transform) +trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, + shuffle=True, num_workers=2) + +testset = torchvision.datasets.CIFAR10(root='./data', train=False, + download=True, transform=transform) +testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, + shuffle=False, num_workers=2) + +classes = ('plane', 'car', 'bird', 'cat', + 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') +``` + +## **2. Define a Convolutional Neural Network** + +```python +import torch.nn as nn +import torch.nn.functional as F + +class Net(nn.Module): + def __init__(self): + super().__init__() + self.conv1 = nn.Conv2d(3, 6, 5) + self.pool = nn.MaxPool2d(2, 2) + self.conv2 = nn.Conv2d(6, 16, 5) + self.fc1 = nn.Linear(16 * 5 * 5, 120) + self.fc2 = nn.Linear(120, 84) + self.fc3 = nn.Linear(84, 10) + + def forward(self, x): + x = self.pool(F.relu(self.conv1(x))) + x = self.pool(F.relu(self.conv2(x))) + x = torch.flatten(x, 1) # flatten all dimensions except batch + x = F.relu(self.fc1(x)) + x = F.relu(self.fc2(x)) + x = self.fc3(x) + return x + +net = Net() +``` + +## **3. Define a Loss function and optimizer** + +Cross-Entropy 손실함수와 SGD+momentum으로 optimizer를 사용한다. + +```python +import torch.optim as optim + +criterion = nn.CrossEntropyLoss() +optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) +``` + +## **4. Train the network** + +data iterator를 반복시켜서 네트워크를 훈련시켜 보겠다. + +```python +for epoch in range(2): # loop over the dataset multiple times + + running_loss = 0.0 + for i, data in enumerate(trainloader, 0): + # get the inputs; data is a list of [inputs, labels] + inputs, labels = data + + # zero the parameter gradients + optimizer.zero_grad() + + # forward + backward + optimize + outputs = net(inputs) + loss = criterion(outputs, labels) + loss.backward() + optimizer.step() + + # print statistics + running_loss += loss.item() + if i % 2000 == 1999: # print every 2000 mini-batches + print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 2000:.3f}') + running_loss = 0.0 + +print('Finished Training') +``` + +![Untitled](https://user-images.githubusercontent.com/79077316/166426837-1e9b7f30-5927-46da-8d4b-3bcc3ff53e83.png) + +그리고 다음 코드를 이용해서 훈련된 모델을 저장한다. + +```python +PATH = './cifar_net.pth' +torch.save(net.state_dict(), PATH) +``` + +## **5. Test the network on the test data** + +신경망이 예측하는 class label을 ground-truth와 비교해서 신경망을 테스트할 것이다. + +전체 신경망을 테스트 하기 전에 테스트 셋을 한번 확인해보겠다. + +```python +dataiter = iter(testloader) +images, labels = dataiter.next() + +# print images +imshow(torchvision.utils.make_grid(images)) +print('GroundTruth: ', ' '.join(f'{classes[labels[j]]:5s}' for j in range(4))) +``` + +![Untitled](https://user-images.githubusercontent.com/79077316/166426845-68a48bab-7b7f-4195-9ed6-b45eb9180052.png) + +아까 저장했던 모델을 다시 로드한다. + +```python +net = Net() +net.load_state_dict(torch.load(PATH)) +``` + +훈련된 신경망이 어떻게 예측하는지 확인해보겠다. + +```python +outputs = net(images) + +_, predicted = torch.max(outputs, 1) + +print('Predicted: ', ' '.join(f'{classes[predicted[j]]:5s}' + for j in range(4))) +``` + +![Untitled](https://user-images.githubusercontent.com/79077316/166426850-c45f57c2-3c5a-4c5d-a45f-c07f74dddba4.png) + +이제 네트워크가 전체 데이터셋에서 어떤 결과를 보이는지 알아보겠다. + +```python +correct = 0 +total = 0 +# since we're not training, we don't need to calculate the gradients for our outputs +with torch.no_grad(): + for data in testloader: + images, labels = data + # calculate outputs by running images through the network + outputs = net(images) + # the class with the highest energy is what we choose as prediction + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + +print(f'Accuracy of the network on the 10000 test images: {100 * correct // total} %') +``` + +![Untitled](https://user-images.githubusercontent.com/79077316/166426855-65d37f07-7108-4e4d-9dd5-bc4f4220d7f6.png) \ No newline at end of file diff --git a/Pytorch_Transferlearning.md b/Pytorch_Transferlearning.md new file mode 100644 index 0000000..f3d668f --- /dev/null +++ b/Pytorch_Transferlearning.md @@ -0,0 +1,283 @@ +# 컴퓨터 비전을 위한 전이학습(transfer learning) PyTorch 실습 + +전이학습을 이용하여 이미지 분류를 위한 CNN을 어떻게 학습시키는지 알아보겠다. 전이학습에서 중요한 2가지는 다음과 같다. + +- **Finetuning the convnet**: 무작위 초기화 대신, 신경망을 ImageNet 1000 데이터셋 등으로 미리 학습한 신경망으로 초기화한다. 학습의 나머지 과정들은 평상시와 같다. +- **ConvNet as fixed feature extractor**: 여기서는 마지막에 fully connected layer를 제외한 모든 신경망의 가중치를 고정시킨다. 이 마지막 fully connected layer는 새로운 무작위의 가중치를 갖는 계층으로 대체되고, 이 레이어만 학습된다. + +## 0. Import modules + +필요한 모듈들을 다음과 같이 임포트해준다. + +```python +# License: BSD +# Author: Sasank Chilamkurthy + +from __future__ import print_function, division + +import torch +import torch.nn as nn +import torch.optim as optim +from torch.optim import lr_scheduler +import torch.backends.cudnn as cudnn +import numpy as np +import torchvision +from torchvision import datasets, models, transforms +import matplotlib.pyplot as plt +import time +import os +import copy + +cudnn.benchmark = True +plt.ion() # interactive mode +``` + +## 1. **Load Data** + +데이터를 로드하기 위해 `torchvision` 과 `torch.utils.data` 패키지를 사용한다. 이번 실습에서는 개미와 벌을 분류하는 이미지 분류 모델을 훈련시키는 것이다. training set은 약 120장 정도 있고, test set은 75장 있다. 일반적으로 이 정도의 데이터셋이면 모델을 학습시키기에 매우 작은 데이터셋이지만, 우리는 여기서 **전이학습**을 할 것이므로 비교적 잘 모델을 일반화시킬 수 있다. + +```python +# Data augmentation and normalization for training +# Just normalization for validation +data_transforms = { + 'train': transforms.Compose([ + transforms.RandomResizedCrop(224), + transforms.RandomHorizontalFlip(), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) + ]), + 'val': transforms.Compose([ + transforms.Resize(256), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) + ]), +} + +data_dir = 'drive/MyDrive/Colab Notebooks/data/hymenoptera_data' +image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), + data_transforms[x]) + for x in ['train', 'val']} +dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4, + shuffle=True, num_workers=4) + for x in ['train', 'val']} +dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']} +class_names = image_datasets['train'].classes + +device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") +``` + +Data augmentation을 이해하기 위해 training 이미지 몇 개를 시각화해보겠다. + +```python +def imshow(inp, title=None): + """Imshow for Tensor.""" + inp = inp.numpy().transpose((1, 2, 0)) + mean = np.array([0.485, 0.456, 0.406]) + std = np.array([0.229, 0.224, 0.225]) + inp = std * inp + mean + inp = np.clip(inp, 0, 1) + plt.imshow(inp) + if title is not None: + plt.title(title) + plt.pause(0.001) # 갱신이 될 때까지 잠시 기다립니다. + +# 학습 데이터의 배치를 얻습니다. +inputs, classes = next(iter(dataloaders['train'])) + +# 배치로부터 격자 형태의 이미지를 만듭니다. +out = torchvision.utils.make_grid(inputs) + +imshow(out, title=[class_names[x] for x in classes]) +``` + +![Untitled](https://user-images.githubusercontent.com/79077316/166427284-9ae7bb66-94de-495a-9c91-94d3a8e2f06c.png) + +## 2. **Training the model** + +이제 모델을 학습시키기 위한 함수들을 작성해보겠다. + +- **Scheduling the learning rate** +- **Saving the best model** + +아래에서 매개변수 `scheduler` 는 LR scheduler object이다. + +```python +def train_model(model, criterion, optimizer, scheduler, num_epochs=25): + since = time.time() + + best_model_wts = copy.deepcopy(model.state_dict()) + best_acc = 0.0 + + for epoch in range(num_epochs): + print(f'Epoch {epoch}/{num_epochs - 1}') + print('-' * 10) + + # Each epoch has a training and validation phase + for phase in ['train', 'val']: + if phase == 'train': + model.train() # Set model to training mode + else: + model.eval() # Set model to evaluate mode + + running_loss = 0.0 + running_corrects = 0 + + # Iterate over data. + for inputs, labels in dataloaders[phase]: + inputs = inputs.to(device) + labels = labels.to(device) + + # zero the parameter gradients + optimizer.zero_grad() + + # forward + # track history if only in train + with torch.set_grad_enabled(phase == 'train'): + outputs = model(inputs) + _, preds = torch.max(outputs, 1) + loss = criterion(outputs, labels) + + # backward + optimize only if in training phase + if phase == 'train': + loss.backward() + optimizer.step() + + # statistics + running_loss += loss.item() * inputs.size(0) + running_corrects += torch.sum(preds == labels.data) + if phase == 'train': + scheduler.step() + + epoch_loss = running_loss / dataset_sizes[phase] + epoch_acc = running_corrects.double() / dataset_sizes[phase] + + print(f'{phase} Loss: {epoch_loss:.4f} Acc: {epoch_acc:.4f}') + + # deep copy the model + if phase == 'val' and epoch_acc > best_acc: + best_acc = epoch_acc + best_model_wts = copy.deepcopy(model.state_dict()) + + print() + + time_elapsed = time.time() - since + print(f'Training complete in {time_elapsed // 60:.0f}m {time_elapsed % 60:.0f}s') + print(f'Best val Acc: {best_acc:4f}') + + # load best model weights + model.load_state_dict(best_model_wts) + return model +``` + +## 3. **Visualizing the model predictions** + +```python +def visualize_model(model, num_images=6): + was_training = model.training + model.eval() + images_so_far = 0 + fig = plt.figure() + + with torch.no_grad(): + for i, (inputs, labels) in enumerate(dataloaders['val']): + inputs = inputs.to(device) + labels = labels.to(device) + + outputs = model(inputs) + _, preds = torch.max(outputs, 1) + + for j in range(inputs.size()[0]): + images_so_far += 1 + ax = plt.subplot(num_images//2, 2, images_so_far) + ax.axis('off') + ax.set_title(f'predicted: {class_names[preds[j]]}') + imshow(inputs.cpu().data[j]) + + if images_so_far == num_images: + model.train(mode=was_training) + return + model.train(mode=was_training) +``` + +## 4. **Finetuning the convnet** + +미리 학습시킨 모델을 불러온 후 마지막에 fully connected layer를 초기화시킨다. + +```python +model_ft = models.resnet18(pretrained=True) +num_ftrs = model_ft.fc.in_features +# Here the size of each output sample is set to 2. +# Alternatively, it can be generalized to nn.Linear(num_ftrs, len(class_names)). +model_ft.fc = nn.Linear(num_ftrs, 2) + +model_ft = model_ft.to(device) + +criterion = nn.CrossEntropyLoss() + +# Observe that all parameters are being optimized +optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9) + +# Decay LR by a factor of 0.1 every 7 epochs +exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1) +``` + +## 5. **Train and evaluate** + +```python +model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler, + num_epochs=25) +``` + +![Untitled](https://user-images.githubusercontent.com/79077316/166427289-5d7bc940-a33a-4b70-a06e-41b4e8baf6b5.png) + +```python +visualize_model(model_ft) +``` + +![Untitled](https://user-images.githubusercontent.com/79077316/166427296-b868fd9f-c503-477b-9711-2d1bd7fda73c.png) + +## 6. **ConvNet as fixed feature extractor** + +마지막 FC layer를 제외하고는 신경망을 고정시킨다. **requires_grad = False**를 설정해서 매개변수를 고정하여 `backward()` 중 gradient가 계산되지 않도록 한다. + +```python +model_conv = torchvision.models.resnet18(pretrained=True) +for param in model_conv.parameters(): + param.requires_grad = False + +# Parameters of newly constructed modules have requires_grad=True by default +num_ftrs = model_conv.fc.in_features +model_conv.fc = nn.Linear(num_ftrs, 2) + +model_conv = model_conv.to(device) + +criterion = nn.CrossEntropyLoss() + +# Observe that only parameters of final layer are being optimized as +# opposed to before. +optimizer_conv = optim.SGD(model_conv.fc.parameters(), lr=0.001, momentum=0.9) + +# Decay LR by a factor of 0.1 every 7 epochs +exp_lr_scheduler = lr_scheduler.StepLR(optimizer_conv, step_size=7, gamma=0.1) +``` + +## 7. **Train and evaluate** + +CPU에서 학습 및 평가를 하는 경우 이전과 비교했을 때 약 절반 가량의 시간만이 소요된다. 대부분의 신경망에서 gradinet를 계산할 필요가 없기 때문이다. 하지만 forward는 당연히 계산이 필요하다. + +```python +model_conv = train_model(model_conv, criterion, optimizer_conv, + exp_lr_scheduler, num_epochs=25) +``` + +![Untitled](https://user-images.githubusercontent.com/79077316/166427298-9ba29e84-bf3e-46a1-8f0d-1c9f12e79a99.png) + +```python +visualize_model(model_conv) + +plt.ioff() +plt.show() +``` + +![Untitled](https://user-images.githubusercontent.com/79077316/166427304-5f282997-a847-4f0a-9717-52ed0a21a1b1.png) \ No newline at end of file diff --git a/paper_Learning Deep Features for Discriminative Localization.md b/paper_Learning Deep Features for Discriminative Localization.md new file mode 100644 index 0000000..da3b813 --- /dev/null +++ b/paper_Learning Deep Features for Discriminative Localization.md @@ -0,0 +1,35 @@ +# Learning Deep Features for Discriminative Localization + +## Overview + +- 위치에 대한 정보가 없는 GT(Classification에 대한 정보만 있는 Ground-Truth)이더라도 **GAP**(Global Average Pooling)을 활용하여 localization 능력을 줄 수 있음 + - conv layer에서 object를 localize 하는 능력이 뛰어남에도, 이 능력은 classification을 위한 FC layer에서 손실됨 + - 이때 마지막 layer까지 localization ability를 유지하기 위한 mechanism으로 GAP 제안 +- **CAM**(Class Activation Mapping) 소개 +- Bounding Box 정보에 대한 학습 없이 ILSVRC 2014에서 객체 위치 파악에 대해 37.1%(Top-5기준) 달성 +- 해당 네트워크는 분류(Classification)에 대한 목표를 가지고 학습하더라도 이미지 영역을 localization 할 수 있음 + +## Related work + +- CAM 등장 전에는 end-to-end 구조가 존재하지 않았음 +- CAM을 사용할 경우 추가적인 모델 수정 없이 weight와 feature map을 활용하여 localization을 할 수 있음 → end-to-end +- CAM 대신 GMP(global max pooling)나 GAP 방법을 활용하여 localization을 시도 + + → 이 방법은 한계가 있음. 물체의 전체를 보는 게 아니라 경계부분만 봄 + + +## Class Activation Mapping (CAM) +- 모델의 전체적인 구조: conv layer → GAP → softmax +- "a weighted sum of the presence of visual patterns at difference spatial location” +- CAM은 마지막 convolutional feature map의 내적(dot product)과 FC-layer의 Class별 Weight의 합 + +## Global Average Pooling(GAP) vs. Global Max Pooling(GMP) + +- GMP와 GAP 모두 classification에서 정확도는 비슷함 +- 하지만 localization에서는 GAP >> GMP + - GMP는 feature map에서 하나의 뚜렷한 특징을 찾아내고, GAP는 이미지 전체적으로 뚜렷한 특징이 있는지를 찾아냄 + +## Results + +- 비슷한 카테고리의 이미지들에서는 비슷한 객체가 주로 추출됨 +- 추상적인 설명이 label로 제공된 이미지에 대해서도 해당 정보가 포함된 위치를 잘 포착해냄 \ No newline at end of file diff --git a/paper_Mask R-CNN.md b/paper_Mask R-CNN.md new file mode 100644 index 0000000..64a2be7 --- /dev/null +++ b/paper_Mask R-CNN.md @@ -0,0 +1,32 @@ +# Mask R-CNN + +- 논문: https://arxiv.org/pdf/1703.06870.pdf + +## Overview + +- 이미지 내에서 각 instance(object)에 대한 segmentation mask 생성 (classification + localization) +- Mask R-CNN은 Faster R-CNN에 mask branch를 추가한 구조 +- 연구 목표는 instance segmentation task에서 사용 가능한 딥러닝 프레임워크를 개발하는 것 + +## Related Work + +- R-CNN +- Instance segmentation + +## Mask R-CNN +- Faster R-CNN의 RPN에서 얻은 ROI(Region of Interest)에 대해 pixel 단위의 segmentation mask를 예측하는 branch를 추가한 구조 +- 객체의 class를 예측하는 classification branch, bbox regression을 수행하는 bbox regression branch와 독립적으로 segmentation mask를 예측하는 mask branch를 추가 +- Mask R-CNN과 Faster R-CNN과 차이는 RoIAlign + - Faster R-CNN은 pixel 단위의 segmentation을 위해 설계되지 않음 + - 이를 위해 RoIAlign이라는 간단하면서 정확한 공간 정보를 보존하는 레이어 제안 + - 이는 Faster R-CNN보다 mask의 정확도를 10~50% 높임 + +**Mask representation** + +- mask는 input object의 spatial layout의 encode 결과 +- class와 box의 위치 정보들이 FC layer를 거치면서 고정된 vector로 변환되기 때문에 공간적 정보 손실 발생 +- mask는 convolution 연산에 의해 공간적 정보를 최소화시킬 수 있음 +- fully convolution networks를 사용하여 각 RoI에 대해 m x m 사이즈의 mask를 예측 +- mask는 FCN에 의해 1차원 벡터로 축소되지 않고, m x m 형태로 공간 정보 유지 가능 +- FC layer보다 더 적을 파라미터 수가 사용되고, 연산 속도가 빠르고 정확함 +- mask 정보를 m x m 형태로 보존하기 위해선, RoI feature가 요구됨 → 이를 위해 RoIAlign layer를 만듦 \ No newline at end of file diff --git a/paper_Mediapipe Hands_On-device Real-time Hand Tracking.md b/paper_Mediapipe Hands_On-device Real-time Hand Tracking.md new file mode 100644 index 0000000..61d8e64 --- /dev/null +++ b/paper_Mediapipe Hands_On-device Real-time Hand Tracking.md @@ -0,0 +1,24 @@ +# Mediapipe Hands: On-device Real-time Hand Tracking + +- 논문: https://arxiv.org/pdf/2006.10214.pdf + +## Overview + +- 장치 내에 사람의 손 골격을 실시간으로 추적하는 솔루션 +- 머신 러닝을 사용하여 단일 프레임에서 손의 21개 3D 랜드마크를 추론 +- 파이프라인은 두 가지 모델로 구성됨 + + 1) palm detector + + 2) hand landmark model + + +## Palm detection model + +- 모바일 실시간 사용을 위한 single shot detector model +- 손바닥과 주먹과 같은 단단한 물체의 경계 상자를 추정하는 것이 손가락의 관절로 손을 감지하는 것보다 훨씬 간단함 → 손바닥 감지기를 학습시킴 +- encoder-decoder feature extractor는 작은 개체에 대해서도 더 큰 장면의 context 인식을 위해 사용됨 + +## Hand landmark model + +- 전체 이미지에 대한 손바닥 감지 후 hand landmark model은 회귀, 즉 좌표 예측을 통해 감지된 손 영역 내부의 21개 3D 손 관절 좌표의 정확한 키포인트 위치를 예측 \ No newline at end of file