Hand On Machine Learning with Scikit Learn, Keras & TensorFlow PART II 정리 - yarak001/machine_learning_common GitHub Wiki
- 인공 신경망은 뇌에 있는 생물학적 neuron network에서 영감을 받은 machine learning model
- 인공 신경망은 deep learning의 핵심
- Keras는 신경망의 구축, 훈련, 평가, 실행을 목적으로 설계된 멋지고 간결한 고수준 API
- 인공신경망의 부흥
- 신경망을 훈련하기 위한 data가 엄청나게 많아졌음
- H/W가 크게 발정함
- 훈련 algorithm 향상
- 일부 인공 신경망의 이론상 제한이 실전에서 문제가 되지 않음이 밝혀짐
- 인공 신경망이 투자와 진보의 선순환에 들어간 것으로 보임
- 매컬러와 피츠가 생물학적 neuron에서 착안한 매우 단순한 model 제안했으며 이는 향후 artificial neuron이 됨
- 이 model은 하나 이상의 이진(on/off) 입력과 이진 출력 하나를 가짐
- 가장 간단한 인공 신경망 구조 중 하나로 1975년 프랑크 로젠블라트(Frank Rosenblatt)가 제안
- Perceptron은 TLU(threshold logit unit), LTU(linear threadhold unit)으로 불리는 조금 다른 형태의 인공 neuron을 기반으로 함
- 입력과 출력이 (이진 on/off 값이 아닌) 어떤 숫자이고, 각각의 입력 연결은 가중치와 연관됨
- TLU는 입력 가중치 합을 계산(z=w1x1+w2x2+...+wnxn=XTW) 뒤 계산된 합에 계단함수(step function)를 적용하여 결과 출력, 즉 hw(X)=step(z) 여기서 z=XTW
- Perceptron에서 가장 널리 사용되는 계단 함수는 Heaviside step function, 이따금 부호 함수(sign function)을 대신 사용하기 함
- Perceptron은 층이 하나뿐인 TLU로 구성
- 한층에 있는 모든 neuron이 이전층의 모든 neuron과 연결되어 있을 때 이를 완전 연결 층(fully connected layer) 또는 밀집 층(dense layer) 이라 부름
- Perceptron의 입력은 입력 neuron 이라 불리는 특별한 통과 neuron에 주입되며 이 neuron은 어떤 입력이 주입되든 그냥 출력으로 통과시킴
- 입력층(input layer) 은 모두 입력 neuron으로 구성
- 헤브의 규칙(Hebb's rule) 또는 헤브 학습(Hebbian learning): Donald Heb는 "The Organization of Behavior"(Wiley, 1949)에서 생물학적 neuron이 다른 neuron을 활성화시킬 때 이 두 neuron의 연결이 더 강해진다 제안함, "서로 활성화되는 세포가 서로 연결된다". 즉, 두 neuron이 동시에 활성화 될 때마다 이들 사이의 연결 가중치가 증가하는 경향이 있음
- Perceptron 학습 규칙은 오차가 감소되도록 연결을 강화시키는 것. Perceptron에 한 번에 한 개의 sample이 주입되면 각 sample에 대해 예측이 만들어짐. 잘못된 예측을 하는 모든 출력 neuron에 대해 올바른 예측을 만들 수 있도록 입력에 연결된 가중치를 강화시킴
- Perceptron 수렴 이론(Perceptron convergence theorem): 훈련 sample이 선형적으로 구분될 수 있다면 이 algorithm이 정답에 수렴할 수 있음
- Perceptron은 class 확률을 제공하지 않으며 고정된 임계값을 기준으로 예측을 만듦, 이런 이유로 Perceptron보다는 logistic regression이 선호됨
- Perceptron은 XOR 문제를 풀 수 없음 => Perceptron을 여러 개 쌓아올린 다층 Perceptron(MLP) 으로 해결
- 다층 Perceptron은 (통과) 입력층(input layer) 하나와 은닉층(hidden layer) 라 불리는 하나 이상의 TLU층과 마지막 출력층(output layer) 로 구성됨
- 입력에 가까운 층을 보통 하위층(lower layer), 출력에 가까운 층을 상위층(upper layer) 라 부름
- 출력층을 제외하고 모든 층은 편향 neuron을 포함하며 다음 층과 완전히 연결됨
- **심층 신경망(DNN, deep neural network): 은닉층을 여러 개 쌓아 올린 인공 신경망
-
역전파(backpropagation) 훈련 algorithm
- 다층 Perceptron을 훈련하는 방법으로, Gradient를 자동으로 계산하는 경사하강법
- Network를 두 번(정방향, 역방향) 통화하는 것만드로 이 역전파 algorithm은 모든 model parameter에 대한 network 오차의 gradient를 계산 할 수 있음.
- Gradient를 구하고 나면 평범한 경사 하강법을 수행하며, 전체 과정은 network가 어떤 해결책으로 수렴될 때가진 반복.
- 순서요약
- 각 훈련 sample에 대해 역전파 algorithm이 먼저 예측을 만들고(정방향 계산) 오차를 측정
- 역방향으로 각 층을 거치면서 각 연결이 오차에 기여한 정도를 측정(역방향 계산)
- 오차가 감소하도록 가중치를 조정(경사 하강법)
- algorithm이 잘 동작하도록 활성화 함수에 변화를 줌, 즉 계단 함수를 logistic(sigmoid) 함수로 바꿈. 계단 함수는 수평선 밖에 없어 gradient를 계산할 수 없지만, logistic함수는 어디서든지 0이 아닌 gradient가 잘 정의되어 있음
- 역전파 Algorithm은 logistic 함수뿐 아니라, Tanh(Hyperbolic Tangent) 함수, ReLU(Rectified Linear Unit)도 활성화 함수로 많이 쓰임
- 활성화 함수가 필요한 이유는? 선형 변환을 여러개 연결해도 선형 변환이기 때문, 층 사이에 비선형을 추가하지 않으면 아무리 층을 많이 쌓아도 하나의 층과 동일해짐, 비선형 활성화 함수가 있는 충분히 큰 심층 신경망은 이론적으로 어떤 연속 함수도 근사할 수 있음
- 일반적으로 회귀용 다층 Perceptron을 만들 때 출력 neuron에 활성화 함수를 사용하지 않고 어떤 범위의 값도 출력되도록 함. 하지만 출력이 항상 양수여야 한다면 출력층에 ReLU 활성화 함수 또는 softplut함수 사용
- 어떤 범위 안의 값을 예측하고 싶다면 sigmoid 함수는 tanh함수를 사용하고 label의 scale를 적절한 범위로 조정
- 훈련시에 사용하는 손실 함수는 전형적으로 평균 제곱 오차지만 훈련 set에 이상치가 많다면 대신 평균 절대값 오차 또는 이 둘을 조합한 Huber 손실을 사용
hyperparameter | 일반적인 값 |
---|---|
입력 neuron수 | 특성마다 하나(예를 들어, MNIST의 경우 28X28=784) |
은닉층 수 | 문제에 따라 다름, 일반적인 1에서 5사이 |
은닉층의 neuron 수 | 문제이 따라 다름, 일반적으로 10에서 100사이 |
출력 neuron 수 | 예측 차원마다 하나 |
은닉층의 활성화 함수 | ReLU(또는 SELU. 11장 참조) |
출력층의 활성화 함수 | 없음, 또는 (출력이 양수일 때) ReLU/softplus나 (출력을 특정 범위로 제한할 때) logistic/tanh 사용 |
손실 함수 | MSE나 (이상치가 있다면) MAE/Huber |
- 다층 Perceptron은 분류작업에도 사용할 수 있음
- 이진 분류 문제에서는 logistic 활성화 함수를 가진 하나의 출력 neuron만 필요
- 다층 Perceptron은 다중 label 이진 분류(Multilabel binary classification) 문제를 쉽게 처리할 수 있음, 예를 들어, email이 spam인지 아닌지를 예측하고, 동시에 긴급한 mail인지 아닌지를 예측하는 문제
- 3개 이상의 class중 한 class에만 속할 수 있다면(예를 들어 숫자 image 분류에서 class를 0~9까지) class마다 하나의 출력 neuron이 필요, 출력층에는 softmax함수를 사용해야함. softmax함수는 모든 예측 확률을 0과 1사이로 만들고 모두 더했을때 1이 되도록 만듦.(Class가 서로 배타적일 경우 필요) 이를 다중 분류(multiclass classification) 이라 함
- 확률 분포를 예측해야 하므로 손실 함수는 일반적으로 cross-entropy 손실(또는 log 손실이라고도 함)을 선택하는 것이 좋음
hyperparameter | 이진 분류(binary classification) | 다중 label 분류(multi label classification) | 다중 분류(multi class classification) |
---|---|---|---|
입력층과 은닉층 | 회귀와 동일 | 회귀와 동일 | 회귀와 동일 |
출력 뉴련수 | 1개 | label마다 1개 | class마다 1개 |
출력층의 활성화 함수 | logstic 함수 | logistic 함수 | softmax 함수 |
손실 함수 | crossentorpy | crossentorpy | crossentorpy |
- Keras는 모든 종류의 신경망을손쉽게 만돌고 훈련, 평가, 실행할 수 있는 고수준 deep learning API
- Keras의 참조 구현(이를 Keras라고 부르기도 함)은 프랑스아 숄레가 연구 project의 일환으로 개발했으며, 2015년 3월에 open source로 공개
- 이 참조 구현은 계산 backend에 의존하여 신경망에 필요한 많은 연산을 수행
- 인기있는 세 가지 deep learning library인 Tensorflow, Microsoft Cognitive Toolkit(CNTK), Theano에서 backend 선택 가능. 이러한 참조 구현을 multibackend Keras
- 2016년 후반부터 Apache MXNet, Apple Core ML, Web browser상 실행을 위한 java script나 type script, NVIDIA등의 모든 종류의 GPU에서 실행은 위한 PlaidML에서 Keras 실행 가능
- TensorFlow 자체적인 Keras 구현인 tf.keras 를 bundle로 포함시킴. 이 구현은 backend로 tensorflow만 지원. 하지만 효율적인 data 적재와 전처리를 간편하게 수행할 수 있는 tensorFlow API등 유용한 기능등ㄹ이 더 제공됨.
- TensorFlow와 Keras 다음으로 인기 있는 deep learning library는 Facebook PyTorch임. PyTorch는 간결함과 훌륭한 문서 덕에 2018년에 급격히 인기가 높아짐
- Keras를 사용하여 datasest 적재하기
- Sequential API를 사용하여 Model 만들기
- kernel_inititalizer(Kernel 은 연결 가중치 행렬의 또 다른 이름)와 bias_initializer를 통해 가중치를 초기화 할 수 있음
- 가중치 행렬의 크기는 입력의 크기에 달려 있음, 이 때문에 Sequential model의 첫 번째 층을 추가할 때 input_shape 매개변수를 지정하는 것임. 그렇지만 입력 크기를 지정하지 않아도 Keras는 model을 build하기 전까지 입력 크기를 기달리 것임, model build는 실제 data를 주입할 때(예를 들어, 훈련 과정 중에) build() method를 호출할 때 일어남. model이 실제 build 되기 전에 층이 가중치를 가지지 않으면(summary() method 호출이나 model 저장 등의) 특정 작업을 수행할 수 없음. 따라서 model을 만들때 입력 크기를 알고 있다는 지정하는 것이 좋음
- Model compile
- compile() method를 호출하여 손실 함수와 optimizer를 지정, 부가적으로 훈련과 평가시 계산할 지료를 추가로 지정
- label이 정수 하나로 이뤄져있고(즉, sample마다 target class index 하나가 있음. 여기서는 0~9사이의 정수), class가 배타적이면 sparse_categorical_crossentropy 손실 사용
- Sample마다 class별 target 확률을 가지다면(예를 들어 class 3dml rdudn [0., 0., 0., 1., 0., 0., 0., 0., 0.,0.]인 one-hot vector라면) categorical_crossentropy 손실 사용
- 하나 또는 그 이상의 이진 label을 가진 이진 분류라면 출력층에 softmax대신 sigmoid를 사용하고, binary_crossentropy 손실 사용
- Model 훈련과 평가
- model을 훈련하려면 간단하게 fit() method 호출
- Keras는 epoch이 끝날 때마다 검증 set를 사용해 손실과 추가적인 측정 지표를 계산
- 훈련 set의 data가 특정 class에 편중되어 있다면 fit() method를 호출할때 class_weight 매개변수를 지정하는 것이 좋음. 빈도수가 적은 class는 높은 가중치를, 빈도수가 높은 class는 낮은 class를 부여
- Sample별로 가중치를 부여하고 싶다면 sample_weight 매개변수 지정
- class_weight와 sample_weight가 모두 지정되면 Keras는 두 값을 곱하여 사용
- validation_data tuple의 세 번째 원소로 검증 set에 대한 sample별 가중치를 지정할 수 도 있음 (class 가중치는 지정 못함)
- fit() method가 반환하는 History 객체는 훈련 parameter(history.params), 수행된 epoch list(history.epoch)가 포함됨. 이 객체의 가장 중요한 속성은 epoch이 끝날 때마다 훈련 set와 검증 set에 대한 손실과 측정한 지표를 담은 dictonary(history.history)임.
- 검증 손실은 epoch가 끝난 후 계산되고 훈련 손실은 epoch가 진행되는 동안에 계산되므로, 훈련 곡선은 epoch의 절반만큼 왼쪽으로 이동시켜 검증 곡선과 비교하는 것이 좋음.
- model의 성능이 만족스럽지 않다면 처음으로 돌아가 hyperparameter를 tuning. 맨 처음 확인할 것은 학습률, optimizer, 층의 개수, 층에 있는 neuron 개수, 은닉층이 사용하는 활성화 함수와 같은 model의 hyperparameter를 tuning. batch_size같은 다른 hyperparamter도 tuning
- model의 검증 정확도가 만족스럽다면 model을 상용 환경으로 배포하기 전에 evaluate() method를 사용하여 test set로 model을 평가하여 일반화 오차를 추정, 검증 set보다 test set에서 성능이 조금 낮은 것이 일반적. 왜냐하면 hyperparemeter를 tuning한 곳은 검증 set이기 때문에.. 그렇다고 test set에서 tuning하면 안됨. 일반화 오차를 매우 낙관적으로 추정하게 되므로..
- Model을 사용해 예측을 만들기
- predict() method를 사용해 새로운 sample에 대한 예측 수행, predict_clsses() method를 사용해서 가장 높은 확률을 가진 class index를 추출할 수 있음
- 분류와 주된 차이점은 출력층이 활성화 함수가 없는 하나의 neuron(하나의 값을 예측하기 때문에)을 가진다는 것과 손실 함수로 평균 제곱 오차를 사용한다는 것
- 입력과 출력이 여러 개거나 더 복잡한 network topology를 만들기 위해 사용
- 층을 만들면서 입력과 함꼐 함수처럼 호출되어 함수형 API라고 부르는 이유임. Python에는 객체를 함수처럼 호출하면 실행되는 특수한 call() method가 있음. 이 method에서 build() method를 호출하여 층의 가중치를 생성
- 순차적이지 않은 신경망
- 여러 입력이 필요한 경우
- 여러 개의 출력이 필요한 경우
- 여러 출력이 필요한 작업. 예들 들어, 그림에 있는 주요 물체를 분류하고 위치를 인식등에 사용. 회귀 작업(물체 중심의 좌표와 너비, 높이를 찾음)과 분류 작업을 함께하는 경우
- 동일한 data에서 독립적인 여러 작업을 수행할 경우. 예를 들어 얼굴 사진으로 다중 분류 작업(multitask classification)을 수행할 수 있음. 예를 들어, 한 출력은 사람의 표정을 분류하고, 다른 출력은 안경을 썼는지 구분하는 작업
- 규제 기법으로 사용하는 경우. 예를 들어 신경망 구조안에 보조 출력을 추가하여 하위 network가 나머지 network에 의존하지 않고 그 자체로 유용한 것을 학습하는지 확인할 수 있음
- 각 출력마다 손실 함수 필요. 기본적으로 Keras 나열된 손실을 모두 더한 최종 손실 값을 훈련에 사용. 보조 출력보다 주 출력에 더 관심이 많다면 주 출력의 손실에 더 많은 가중치를 부여할 수 있으며 이럴 경우 model compile시 loss_weight를 사용해서 손실 가중치를 지정
- Sequential API와 함수형 API는 모두 선언적(declarative). 사용할 층과 연결 방식 먼저 정의 후 data 주입하여 훈련이나 추론 시작함.
- 장점: model을 저장하거나 복사, 공유가 쉽고, model의 구조를 출력하거나 분석하기 좋음. Framework가 크기를 짐작하고 type을 확인하여 error를 일찍 발견할 수 있음. 전체 model이 층으로 구성된 정적 graph이므로 debugging 쉬움
- 단점: 정적이라는 단점, model이 반복문을 포함하고 다양한 크기를 다뤄야하고, 조건문을 가지는 등의 동적인 구조를 만들 수 없음
- Subclassing API
- 조금 더 명령형(imperative) style의 programming 가능
- 순서
- Model class를 상속
- 생성자 안에서 필요한 층 생성
- call() method안에 수행하려는 연산 기술
- 장정: 높은 유연성
- 단점: model 구조가 call() method안에 숨겨져 있기 때문에 Keras가 쉽게 분석 할 수 없음. 즉, model을 저장하거나 복사할 수 없음. summary() method를 호출하면 층의 목록만 나열하고 층간의 연결 정보를 얻을 수 없음. Keras가 type과 크기를 미리 확인할 수 없어 실수가 발생하기 쉬움
- 높은 유연성이 필요하지 않다면 Sequential API나 함수형 API를 사용하는 것이 좋음
- Sequential API와 함수형 API는 save() method를 사용해 간단히 저장 가능
- Keras HDF5 format을 사용하여 model의 구조(hyperparameter 포함)와 층의 모든 parameter(연결 가중치와 편향) 저장, hyperparamter현재 상태와 optimizer도 저장
- load_model() method를 사용하여 model load
- Subclassing에서는 위 방식을 사용할 수 없음. save_weight(), load_weight() method를 사용하여 model parameter를 저장하고 복원할 수 있으나 그 외에는 모두 수동으로 저장하고 복원해야 함.
- fit() method에 callbacks 매개변수를 사용하여 Keras가 훈련의 시작이나 끝에 호출할 객체 list를 지정할 수 있음
- ModelCheckpoint callback는 훈련하는 동안 일정한 간격으로 model의 checkpoint를 저장, ModelCheckpoint를 만들 때 save_best_only=True로 하면 최상의 검증 set 점수에서만 model을 저장
- EarlyStopping callback은 일정 epoch(patience 매개변수로 지정) 동안 검증 set에 대한 점수가 향상되지 않으면 훈련을 중단.
- Computer가 문제를 일으키는 것을 대비해서 ModelCheckponit callback, 시간과 computing 자원 절약을 위해서 EarlyStopping callback을 함께 사용
- 사용자 정의 callback 생성 가능
- fit() method에서 호출: on_train_begin(), on_train_end(), on_epoch_begin(), on_epoch_end(), on_batch_begin(), on_batch_end()
- evaluate() method에서 호출: on_test_begin(), on_test_end(), on_test_epoch_begin(), on_test_epoch_end(), on_test_batch_begin(), on_test_batch_end()
- predict() method에서 호출: on_predict_begin(), on_predict_end(), on_predict_epoch_begin(), on_predict_epoch_end(), on_predict_batch_begin(), on_predict_batch_end()
- 매우 좋은 interactive한 시각화 도구
- 학습 곡선 표시 및 비교, 계산 graph 시각화, 훈련 통계 분석, model 생성 image 확인 및 3D에 투영된 복잡한 다차원 data 시각화 및 자동 clustering등의 기능 제공
- Tensorboard를 사용하려면 program을 수정하여 event file이라는 특별한 이진 log file에 시각화 하려는 data를 출력
- TensorBoard callback 사용
- TensorFlow는 tf_summary package로 저수준 API 제공.
- 신경망의 유연성은 단점이기도 함. 조정할 hyperparameter들이 많기 때문임.
- 어떤 hyperparameter가 주어진 조합에 최적인지 알수 있을까? 한가지 방법은 많은 hyperparameter 조합을 시도해보고 어떤 것이 검증 set에서(또는 K-fold 교차 검증) 가장 좋은 점수를 내는지 확인
- GridSearchCV나 RandomSearchCV를 사용해 hyperparameter 공간을 탐색할 수 있음. 이렇게 하기 위해서는 Keras model을 scikit-learn 추정기처럼 보이도록 바꿔야함
- 일련의 hyperparameter로 Keras model을 만들고 compile할 수 있는 함수 생성
- 위 과정에서 함수를 사용해서 KerasRegressor or KerasClasssifer 객체 생성
- scikit-learn 회귀 추정기처럼 fit() method로 model훈련, score() method로 평가, predict() method로 예측
- model 하나를 훈련하고 평가하려는 것이 아니라 수백 개의 model을 훈련하고 검증 set에서 최상의 model을 선택해야 함. hyperparameter가 많으므로 Grid search보다는 Random search를 사용하는 것이 좋음. 은닉층 개수, neuron 개수, 학습률을 사용해 hyperparameter 탐색
- 실행
- 실행이 끝나면 Random search가 찾은 최상의 hyperparameter와 훈련된 model을 얻을 수 있음
- 이 model을 저장하고 test set에서 평가하여 성능이 만족스럽다면 상용 환경에 배포
- 장정: 사용법이 어렵지 않고, 간단한 문제에 잘 동작
- 단점: 훈려에 시간이 많이 걸리고, 대규모 dataset으로 복잡한 model을 훈련할 때 탐색할 수 있는 hyperparameter 공간에 제약이 생김
- 방안:
- 탐색 과정을 수동으로 보조하여 문제 완화. 즉, hyperparameter 값의 범위를 크게하여 빠르게 첫번째 random search수행하고, 여기서 찾아진 hyperparameter 값을 중심으로 더 좁은 범위를 탐색. 역시 시간이 오래 걸림
- hyperparameter 공간을 탐색하는 여러 기법 사용
- 탐색 지역이 좋다고 판명될 때 더 탐색을 수행. 수동 작업 방식을 대신 관리하여 훨씬 적은 시간에 더 나은 solution을 만듦
- Hyperparameter 최적화 python library
- Hyperopt
- Hyperas, kopt, Talos
- Keras Tuner
- Scikit-Optimize(skopt)
- Spearmit
- Hyperband
- Sklearn_Deap
- Hyperparameter 최적화 python service
- Google Cloud Hyperparameter Tuning Service
- [Arimo] (https://arimo.com)
- [SigOpt] (https://sigopt.com)
- [Oscar] (https://oscar.calldesk.ai)
- GridSearchCV나 RandomSearchCV를 사용해 hyperparameter 공간을 탐색할 수 있음. 이렇게 하기 위해서는 Keras model을 scikit-learn 추정기처럼 보이도록 바꿔야함
- Hyperparameter tuning은 연구가 활발한 분야. 진화 Algorithm 등장. Google도 hyperparameter 탐색뿐 아니라 문제에 최적인 신경망 구조를 찾기 위해 진화 전략 사용(Google의 [AutoML service] (https://cloud.google.com/automl)
Number of Hidden Layers
- 복잡한 문제에서는 심층 신경망이 얕은 신경망보다 parameter 효율성(parameter efficiency) 가 좋음.
- 심층 신경망은 복잡한 함수를 modeling하는 데 얕은 신경망보다 훨씬 적은 수의 neuron을 사용하므로 동일한 양의 data를 훈련하는데 높은 성능 낼 수 있음
- 아래쪽 은닉층은 저순준 구조, 중간층은 중간 수준 구조, 위촉 은닉층과 출력층은 고수준 구조를 modeling함
- 심층 신경망은 새로운 data 일반화에도 좋음
- 전이학습(transfer learning): 비슷한 작업에서 가장 뛰어난 성능을 낸 미리 훈련된 network 일부를 재사용하는 것, 훈련속도는 휠씬 빠르고, data는 훨씬 적게 필요
Number of Neurons per Hidden Layer
- 입력층과 출력층의 neuron 개수는 해당 작업에 필요한 입력과 출력의 형태에 따라 결정
- 대부분의 경우 모든 은닉층의 같은 개수의 neuron 사용, 또한 tuning할 hyperparameter가 층마다 한 개씩 아니 전체를 통틀어 한개를 사용. dataset마다 다르지만 다은 은닉층보다 첫번째 은닉층의 neuron수를 크게하는 것도 도움이 됨
- 실전에서는 과적합까지 층의 개수와 neuron수를 늘리기 보다는 더 많은 층과 neuron을 가진 model을 선택하고, 과대적합되지 않도록 조기종료나 규제기법을 사용하는 것이 간단하고 효과적(stretch pants 방식)
- 일반적으로 층의 neuron 수보다는 층 수를 늘리는 것이 이득
- 학습률
- 가장 중요한 hyperparameter
- 일반적으로 최적의 학습률은 최대 학습률의 절반정도.
- 좋은 학습률을 찾는 한 가지 방법은 매우 낮은 학습률에서 시작하여 점진적으로 매우 큰 학습률까지 수백 번 반복하여 model을 훈련하는 것
- Optimizer
- 고전적인 평범한 mini batch 경사 하강법보다 좋은 optimizer 선택과 optimizer의 hyperparameter tuning이 중요
- batch 크기
- Model의 성능과 훈련시간에 영향
- 큰 batch 사용의 장점은 GPU와 같은 H/W 가속기를 효율적으로 활용할 수 있음. 초당 처리량이 증가됨
- GPU RAM에 맞는 가장 큰 batch 크기 사용을 권장. 실전에서 작은 batch에서 보다 성능이 떨어지는 경우도 있으니 주의. 한 가지 전략은 학습률 예열을 사용해 큰 batch 크기를 시도해보고 훈련이 불안정하거나 최종성능이 만족스럽지 않은 경우 작은 batch 크기 사용
- 활성화 함수
- 일반적으로 ReLU 활성화 함수가 모든 은닉층에 좋은 기본 값
- 출력층의 활성화 함수는 수행 작업에 따라 달라짐
- 반복 횟수
- Tuning이 필요없으며, 대시 EarlyStopping사용
- 최적의 학습률은 다른 hyperparameter에 의존적. 특히 batch 크기에 영향을 받음. 따라서 다른 hyperparameter를 수정하면 반드시 학습률도 tuning해야 함
- 심층 신경망 훈련시 접할수 있는 문제
- gradient 소실, gradient 폭주: 심층 신경망의 아래쪽으로 갈수록 gradient가 점점 더 작아지거나 커지는 현상. 하위층 훈련을 어렵게 만드는 요인
- 대규모 신경망을 위한 훈련 data가 충분하지 않거나 label 작업비용이 많이들 수 있음
- 훈련이 극단적으로 느려질 수 있음
- 수백만개의 parameter를 가진 model은 훈련 set에 대한 과대적합 위험이 매우 큼. 특히 훈련 sample이 충분하지 않거나 잡음이 많은 경우
- 역전파 algorithm: 신경망의 모든 parameter에 대한 오차 함수의 gradient를 계산사며 경사 하강법 단계에서 이 gradient를 사용하여 각 parameter를 수정
- Gradient 손실(vanishing gradient) : 경사 하강법이 하위층으로 진행될수록 gradient가 점점 작아지는 경우. 하위층의 연결 가중치를 변경되지 않은 채로 두어 수렴이 힘들어짐
- Gradient 폭주(exploding gradient) : Gradient가 점점 커져서 여러 층이 비정상적으로 큰 가중치로 갱신되면 alogrithm은 발산(diverse)함
- 원인 (2010년 Xavier Glorot과 Yoshua Bengio 논문 발표)
- logistic sigmoid 활성화 함수와 가중치 초기화 방법(평균이 0이고 표준편차가 1인 정규분포)의 조화. 이는 각 층에서 출력의 분산이 입력의 분산보다 더 커지게 됨. 신경망의 위쪽으로 갈수록 활성화 함수가 0이나 1에 수렴하게 되는데, 이는 logistic 함수의 평균이 0이 아니라 0.5라서 더욱 나뻐지게 됨(tanh함수는 평균이 0이므로 깊은 신경망에서 logistic함수 보다 조금 나음)
- Glorot과 Bengio는 불안정한 gradient를 완화하기 위해서 다음과 같은 주장을 함
-
적절한 신호가 흐르기 위해서는 각 층의 출력에 대한 분산이 입력에 대한 분산과 같아야 한다
-
역방향에서 층을 통과하기 전과 후의 gradient 분산이 동일해야 한다.
-
실전에서 잘 동작하는 입증된 초기화 방법을 제안하고 이후 여러가지 초기화 방안들이 발표됨
- 층의 fan-in과 fan-out : 층의 입력과 출력 연결 개수
초기화 전략 활성화 함수 정규분포 Glorot 활성화 함수 없음, tanh, logistic, softmax 1/fanavg He ReLU 함수와 그 변종들 2/fanin LuCun SELU 1/fanin
-
- Keras는 기본적으로 균등분포인 Glorot 초기화 사용
- 활성화 함수를 잘못 선택하면 자치 gradient 손실이나 폭주로 이어질 수 있다 (2010년 Xavier Glorot과 Yoshua Bengio 논문 발표)
- 생물학적 neuron방식과 비슷한 sigmoid 활성화 함수가 최선이라고 믿어지만 다른 활성화 함수가 심층 신경망에서 더 잘 작돋함을 밝힘
- ReLU 함수는 특정 양수값에 수렴하지 않는다는 점과 계산속도가 빠르다는 장점 있음
- dying ReLU: 훈련하는 동안 일부 neuron이 0 이외의 값을 출력하지 않음. neuron의 가중치가 바뀌어 훈련 set에 있는 모든 sample에 대해 입력의 가중치 합이 음수가 되면 neuron이 죽음. 가중치 함이 음수이면 ReLU 함수의 gradient는 0이 되므로 경사하강법이 더 이상 동작하지 않음
- LeakyReLU : dying ReLU 문제 해결하기 위한 ReLU의 변종. hyperparameter α가 이 함수가 새는(leaky) 정도를 결정. 새는 정도란 z<0일 때 이 함수의 기울기이며, 일반적을 0.01로 설정. 이 작은 기울기가 LeakyReLU를 절대 죽지 않게 만듦. 최근 논문에서 LeakyReLU가 항상 ReLU보다 성능이 높다고 함
- RReLU(Randomized leaky ReLU) : 훈련하는 동안 주어진 범위에서 α를 무작위로 선택하고 test시에는 평균을 사용. 훈련 set의 과대적합 위험을 줄이는 규제 역할을 하는 것처럼 보임
- PReLU(Parametric leaky ReLU) : α가 훈련하는 동안 학습(α가 hyperparameter가 아니라 다른 model parameter와 마찬가지로 역전파에 의해 변경됨). 대규모 image dataset에서 ReLU보다 성능이 크게 앞서지만, 소규모 dataset에서는 과대적합의 위험이 있음
-
ELU(exponetial linear unit) : 다른 모든 ReLU 변종의 성능을 앞지렀음. 훈련 시간이 줄고 신경망의 test set성능도 더 높았음(2015년 Djork-Ame Clevert 논문)
- 단점: 지수 함수를 사용하므로 ReLU나 그 변종들보다 계산이 느림. 훈련동안 수렴 속도가 빨라서 느린 계산이 상쇄되지만 test시에는 ELU를 사용한 network가 ReLU를 사용한 network보다 느릴 것임
-
SELU(Scaled ELU) : 완전 연결 층만 쌓아서 신경망을 만들고 모든 은닉층이 SELU 활성화 함수를 사용한다면 network가 자기 정규화(self-normalize)된다고 함, 훈련하는 동안 각 층의 출력이 평균 0과 표준펴낯 1을 유지하는 경향이 있음(2017년 Gunter Klambauer 논문)
- 자기 정규화를 위한 조건
- 입력 특성이 반드시 표준화(평균 0, 표준편차 1)되어야 함
- 모든 은닉층의 가중치는 LeCun 정규분포로 초기화 되어야 함. Keras에서는 kernel_initializer="lecun_normal"
- Network는 일렬로 쌓은 층으로 구성되어야 함. 순환 신경망이나 skip 연결 과 같은 순차적이지 않은 구조에 SELU를 사용하면 자기 정규화되는 것이 보장되지 않음.
- 자기 정규화를 위한 조건
- 심층신경망에서는 일반적으로 SELU>ELU>LeakyReLU류>ReLU>tanh>logistic(sigmoid)
- 자기 정규화 되지 못하는 구조라면 SELU보다는 ELU
- 실행 속도가 중요하다면 LeakyReLU
- 신경망이 과대적합 되었다면 RReLU, 훈련 set가 아주 크다면 PReLU 포함
- ReLU는 지금까지 가장 널리 사용되는 활성화 함수이므로 속도가 중요하다면 선택
- Batch 정규화(Batch normalization(BN)) : 각 층에서 활성화 함수를 통과하기 전이나 후에 연산을 하나 추가. 이 연산은 단순하게 입력을 원점에 맞추고 정규환 한 다음. 각 층에서 두 개의 새로운 parameter로 결과값의 scale을 조정하고 이동시킴. 많은 경우 신경망의 첫 번째 층으로 batch 정규롸를 추가하면 훈련 set를 표준화할 필요가 없음
- 입력 data를 원점에 맞추고 정규화하려면 algorithm은 평균과 표준편차를 추정해야 함. 이를 위해 mini batch에서 입력의 평균과 표준편차를 평가(그래서 이름이 batch 정규화)
- 훈련하는 동안 배치 정규화는 입력을 정규화한 다음 scale을 조정하고 이동시킴. 그렇다면 test시에는? 아마 sample batch가 아니라 sample 하나에 대한 예측을 만들어야 함. 한가지 방법은 훈련이 끝난 후 전체 훈련 dataset를 신경망에 통과시켜 batch 정규화층의 각 입력에 대한 평균과 표준편차를 계산. 예측할 때 batch 입력 평균과 표준편차로 이 '최종'입력 평균과 표준편차를 대신해서 사용할 수 있음
- 그러나 대부분 batch 정규화 구현은 층의 입력 평균과 표준편차의 이동 평균을 사용해 훈련하는 동안 최종 통계를 추정. Keras의 BatchNormalization층은 이를 자동으로 수행.
- 정리
- Batch 정규화 층마다 네 개의 parameter vector가 학습됨. γ(출력 scale vector), β(출력 이동 vector)는 일반적인 역전파를 통해 학습됨. μ(최종 입력 평균 vector), σ(최종 입력 표준편차 vector)는 지수 이동 평균을 통해 추정됨. μ와 σ는 훈련하는 동안 추정되지만 훈련이 끝난 후 사용 됨
- Image net 분류 작업에서 큰 성과를 냄. Gradient 소실 문제가 크게 감소하여 tanh, logistic 활성화 함수 같은 수렴성을 가진 활성화 함수를 사용할 수 있음. 가중치 초기화에 network가 훨씬 덜 민감.
- Batch 정규화는 규제와 같은 역할을 하여 dropout과 같은 다른 규제 기법의 필요성을 줄여줌
- Batch 정규화는 model의 복잡도를 키우고, 실행 시간 면에서도 손해지만 다행히 훈련이 끝난 후 이전 층과 batch 정규화 층을 합쳐 실행 속도 저하를 피할 수 있음.
- Batch 정규화를 사용할 때 epoch마다 더 많은 시간이 걸려 훈련이 오래 걸릴 수 있지만 수렴이 훨씬 빨라지므로 보통 상쇄됨. 따라서 더 작은 epoch으로 동일한 성능에 도달할 수 있음
- Keras로 Batch 정규화 구현하기
- 은닉층의 활성화 함수 전이나 후에 BatchNormalization 층 추가
- Batch 정규화 층은 입력마다 네 개의 parameter γ, β, μ, σ를 추가. 마지막 두개 parameter μ, σ는 이동 평균으로 역전파로 학습되지 않음
- 활성화 삼수 전에 batch 정규화 층을 추가하려면 은닉층에서 활성화 함수를 지정하지 말고 batch 정규화 층 뒤에 별도의 층으로 추가해야 함.
- 중요 parameter는 momentum과 axis가 있음
- Batch 정규화 층은 훈련 도중과 훈련이 끝난 후에 수행되는 계산이 다름. 훈련 동안에는 batch 통계를 사용하고 훈련이 끝난 후에는 '최종' 통계를 사용
- BatchNormalization은 심층 신경망에서 매우 널리 사용하는 층이 되었고, 보통 모든 층 뒤에 batch 정규화가 있다고 가정하므로 종종 신경망 그림에서 빠져 있음
- Gradient Clipping : 역전파 될때 일정 임계값을 넘어서지 못하게 gradient를 잘라 폭주를 완화하는 방법. 순환 신경망에는 Batch 정규화를 적용하기 어려워 이 방법을 많이 사용
- Keras에서 gradient clipping을 구현하려면 optimizer를 만들때 clipvalue와 clipnorm 매개 변수 지정
- 임계값은 hyperparameter로 tuning할 수 있음
- gradient vector의 방향을 바꿀 수 있음
- gradient clipping이 gradient vector의 방향을 바꾸지 못하게 하려면 clipvalue대신 clipnorm 지정
- 훈련하는 동안 gradient가 폭주한다면 다른 임계값으로 값과 norm을 모두 사용할수 있다.(tensorboard를 사용해서 gradient 크기 추적). 그리고 검증 set에서 어떤 방식이 가장 좋은 성과를 내는지 확인
- 전이 학습(transfer learning) : 처음부터 DNN을 훈련하지 않고 해결하려는 것과 비슷한 유형의 문제를 처리한 신경망이 이미 있는지 찾아본 다음. 그 신경망의 하위층 재사용. 훈련 속도를 크게 높일 뿐 아니라 훈련 data도 크게 줄임
- 일반적으로 전이 학습은 저수준 특성이 비슷한 입력에서 잘 동작함
- 작업이 비슷할수록 (낮은 층부터 시작해서) 더 많은 층을 재사용. 아주 비슷한 작업이라면 모든 은닉층을 유지하고 출력층만 교체
- 사용 방법
- 재사용하는 층을 모두 동결
- model을 훈련하고 성능 평가
- 맨 위에 있는 한 두개 은닉층을 동결 해제하고 역전파를 통해 가중치 조정하여 성능이 향상되는지 확인
- 훈련 data가 많을수록 많은 층의 동결 해제 가능. 재사용 층의 동결 해제할 때는 학습률을 줄이는 것이 좋음
- 만약 좋은 성능이 안나고 훈련 data가 적다면 상위 은닉층을 제거하고 남은 은닉층 동결. 이런 식으로 재사용할 은닉층의 적절한 개수를 찾을 때까지 반복
- 훈련 data가 아주 많다면 은닉층을 제거하는 대신 다른 것을 바꾸거나 더 많은 은닉층 추가 가능
- 순서 예시
- model A로부터 model B 생성 후 필요한 층 추가
- model B 훈련시 model A가 영향을 받으므로 이를 피하려면 clone_model() method로 구조 복제 후 set_weight() method로 가중치 설정
- 처음 몇번의 epoch동안 재사용 층을 동결하고 새로운 층에게 적절한 가중치 학습시간 부여
- 층의 trainable 속성 False로 설정
- 재사용된 층의 동결을 해제하고 정밀 tuning을 위해 model B 훈련 계속
- 재사용된 층의 동결은 해제한 후에는 학습률을 낮추는 것이 좋음
- 층을 동결하거나 동결을 해제한 후 반드시 model을 compile해야 함. 왜냐하면 compile() method가 model에서 훈련될 가중치를 모으기 때문
- 전이 학습은 조금 더 일반적인 특성을 (특히 아래쪽 층에서)감지하는 경향이 있는 심층 합성공 신경망에서 잘 동작함
- blahblahblah~~정리 필요
- blahblahblah~~정리 필요
- 훈련 속도를 높이는 네 가지 방법
- 연결 가중치 초기화
- 좋은 활성화 함수
- Batch 정규화
- 전이 학습
- 더 빠른 Optimizer
- Keras에서 SGD optimizer에 momentum 매개변수 할당
- NAG는 일반적으로 기본 momentum 최적화보다 훈련 속도가 빠름
- Kreas에서 SGD optimizer 생성시 use_nesterov=True 지정
- 가장 가파는 차원을 따라 gradient vector의 scale를 감소 시킴
- **적응적 학습률(adaptive learning rate)**학습률을 감소시키지만 경사가 완만한 차원보다 가파른 차원에 대해서 더 빠르게 감소. 전역 최적점 방향으로 더 곧장 가도록 갱신하는데 도움
- 간단한 2차 방적식 문제는 잘 동작하지만 훈련시 너무 일찍 멈추는 경우가 종종 발생
- Keras에 Adagrad optimizer가 있지만 심층 신경망에는 사용하지 말아야 함. (선형 회귀 같은 간단한 작업에는 효과적일 수 있음
- 훈련 시작부터의 모든 gradient가 아닌 가장 최근 반복에서 비롯된 gradient만 누적하여 AdaGrad의 문제점 해결
- Keras에서 RMSprop optimizer
- Adam (적응적 momentum 추정(adaptive momentum estimation)) : momentum optimizer와 RMSProp optimizer를 합친 것
- Keras에서 Adam 사용
- AdaMax: Adam의 변종 optimizer: Adam + NAG
- Nadam: Adam의 변종 optimizer
Class | 수렴 속도 | 수렴 품질 |
---|---|---|
SGD | * | *** |
SGD(momentum=...) | ** | *** |
SGD(momentum=..., nesterov=True) | ** | *** |
Adagrad | *** | *(너무 일찍 멈춤) |
RMSProp | *** | **또는 *** |
Adam | *** | **또는 *** |
Nadam | *** | **또는 *** |
AdaMax | *** | **또는 *** |
- 거듭제곱 기반 scheduling(power scheduling)
- 지수 기반 scheduling(exponetial scheduling)
- 구가별 고정 scheduling(piecewise scheduling)
- 성능 기반 scheduling(performance scheduling)
- 1 cycle scheduling(1 cycle scheduling)
- 심층 신경망은 수만 개에서 수백만 개의 parameter를 가지고 있어 매우 자유도가 높아 복잡한 dataset을 학습할 수 있지만 훈련 set에 과대적합 되기 쉬우며 이를 방지하기 위해서 규제가 필요
- 조기 종료는 최상의 규제 방법 중 하나. Batch 정규화는 gradient 문제를 위해 고안 되었지만 괜찮은 규제 방법도 됨
- L1 규제: 신경망의 연결 가중치 제한하기 위해 사용(많은 가중치가 0)
- L2 규제: 희소 model을 만들기 위해 사용
- keras_regularization.l1(), keras.regularization.l2(), keras.regularization.l1_l2()
- 일반적으로 network의 모든 은닉층에 동일한 활성화 함수, 동일한 초기화 전략, 동일한 규제를 적용하기 때문에 매개변수 값이 반복되는 경우가 많음 이는 code를 읽기 어렵게 만들고 bug를 만들기 쉬움. 이를 피하기 위해 반복문을 사용하도록 code를 refactoring 또는 Python의 functools.partial()함수를 사용하여 기본 매개변수 값을 사용하여 함수 호출을 감쌈
-
신경망의 인기있는 규제 방법 중 하나.
-
Dropout으로 훈련된 neuron은 이웃한 neuron에 맞춰 적응할 수 없으며 자기 자신이 유용해져야함. 이런 neuron들은 입력 neuron에 지나치게 의존하지 않고 모든 입력 neuron에 주의을 기울이게 되어 입력값의 작은 변화에 덜 민감해짐. 결국 더 안정적인 network가 되어 일반화 성능이 향상됨
-
Dropout은 각 훈련 step에서 고유의 model이 생성된다고 생가해되 됨. 결과적으로 만들어진 신경망은 이 모든 신경망을 평균한 ensemble로 볼수 있음
-
일반적으로 (출력층을 제외한) 맨 위의 층부터 세 번째 층까지 있는 neuron에만 dropout을 적용
-
Dropout은 훈련하는 동안에만 활성화 되므로 훈련 손실과 검증 손실을 비교하면 오해를 일으킬 수 있음. 특히 비슷한 훈련 손실과 검증 손실을 얻더라도 model이 훈련 set에 과대적합될 수 있으므로 훈련이 끝난 뒤 dropout을 배고 훈련 손실을 평가해야 함
-
dropout 비율 model이 과적합되면 증가, 과소적합되면 감소. 층이 클 때는 비율을 증가, 작은 때는 감소
-
최신 신경망 구조는 마지막 은닉층 뒤에 dropout 사용
-
dropout은 훈련을 느리게 만드는 경향이 있지만 성능을 향상시키므로 가치가 있음
-
Keras에서는 keras.layers.Dropout 사용
- blahblahblah~~정리 필요
- 각각의 neuron에 대해 입력 가중치 w가 ||w||2<=r이 되도록 제한(r은 max-norm규제 hyperparameter, ||.||는 l2 norm)
- max-norm규제는 (Batch 정규화를 사용하지 않았을 떄)불안정한 gradient 문제를 완화
- keras에서 keras.constraints.max_norm() 함수를 사용하여 Dense()의 kernel_constraint 매개 변수 지정(사용자 정의 규제 함수를 지정할 수 있음). bias_constraint 매개변수를 이용해서 편향을 규제할 수 도 있음
hyperparameter | 기본값 |
---|---|
kernel 초기화 | He |
활성화 함수 | ELU |
정규화 | 얕은 신경망: 없음, 깊은 신경망: batch 정규화 |
규제 | 조기 종료(필요하면 L2규제 추가) |
Optimizer | momentum(or RMSProp, Nadam) |
학습률 schedule | 1 Cycle |
[ 기본 DNN 설정 ] |
hyperparameter | 기본값 |
---|---|
kernel 초기화 | Lecun |
활성화 함수 | SELU |
정규화 | 없음 |
규제 | 필요하다면 α dropout |
Optimizer | momentum(or RMSProp, Nadam) |
학습률 schedule | 1 Cycle |
[ 자기 정규활르 위한 DNN 설정 ] |
- 입력 특성을 정규화 하라
- 비슷한 문제를 해결한 model을 찾을 수 있다면 사전 훈련된 신경망 재사용을 해봐라
- label 없은 data가 많다면 비지도 사전훈련을 사용해 봐라
- 비슷한 작업을 위한 label된 data가 많다면 보조 작업에서 사전 훈련을 수행할 수 있다.
- 희소 model이 필요하다면 L1규제를 사용하라(훈련된 가중치를 0으로 만듬). 매우 희소한 model이 필요하면 Tensorflow model 최적화 toolkit(TF-MOT)를 사용할 수 있음
- 빠른 응답을 하는 model이 필요하면 층 개수를 줄이고, batch 정규화 적용, LeakyReLU나 ReLU와 같은 빠른 활성화 함수 사용. 부동 소수정 정밀도를 낮추거나(32 -> 16 -> 8) TF-MOT를 사용할 수 있음
- 위험에 민감하고 속도가 매우 중요하지 않은 application에서는 성능 향상과 불확실성 추정/신뢰할 수 있는 확률 추정을 위해 MC-Dropout을 사용할 수 있음
- A Quick Tour of TensorFlow
- TensorFlow 요약
- 핵심 구조는 numpy와 비슷하지만 GPU지원
- 분산 computing 지원
- 일종의 JIT(just-in-time) compiler 포함. 속도 향상이 memory 최적화를 위해서 계싼 최적화함. Python 함수에서 계산 graph(computation graph) 추출후 최적화하고 효율적으로 실행
- 계산 graph는 platform 중립적 format으로 어떤 환경에서든 사용 가능
- 자동미분과 고성능 Optimizer를 제공하므로 모든 종류의 손실 함수를 쉽게 최소화 할 수 있음
- Tensorflow CPU, GPU, TPU 사용가능
- 하나의 library 그 이상으로 광범위한 생태계를 가짐
- 시각화: tensorboard
- 제품화 library 모음: TFX(TensorFlow Extended). data 시가고하, 전처리, model 분석, serving등이 포함됨
- 사전 훈련된 신경망: **[TensorFlow Hub]++
- TensorFlow model 저장소
- TensorFlow Resource page: 1, 2
- TensorFlow 요약
- TensorFlow API는 tensor를 순환시킴
- tensor는 한 연산에서 다른 연산을 흐름. 그래서 TensorFlow
- tensor는 ndarray와 매우 유사. 일반적으로 다차원 배열(scalar값도 가질 수 있음)
- tf.constant()로 생성
- tf.Tensor는 shape와 type을 가짐
- index 참조 numpy와 배우 비슷
- 모든 종류의 tensor 연산 가능
- Tensor와 Numpy는 함께 사용하기 편함
- Numpy는 기본적으로 64bit 정밀도를 사용하지만, TensorFlow는 32bit 정밀도를 사용. 일반적으로 신경망은 32bit 정밀도로 충분하고 더 빠르고 memory도 적게 사용. Numpy 배열을 tessor로 만들때 dtype=tf.float32로 지정해야 함
- Type 변환은 성능을 크게 감소 시킬 수 있고, type이 자동으로 변화면 사용자가 눈치채지 못 할 수 있음. TensorFlow는 어떤 type 변환도 자동으로 수행되지 않음. 호환되지 않는 type의 tensor로 연산실행시 예외 발생
- tf.cast()
- tf.Tensor는 변경 불가능한 객체
- tf.Variable 값 변경 가능
- tf.Variable은 tf.Tensor와 비슷, assign() method로 값 할당, 원소 slice후 assing() method나 scatter_updata(), scatter_nd_update() method로 개별 원소 수정 가능
- tf.SparceTensor ** 희소 tensor, 대부분 0으로 채워진 tensor를 효율적으로 나타냄.
- tf.TensorArray ** Tensor의 list, 기본적으로 고정된 길이를 가지지만 동적으로 바꿀 수 있음. list에 포함된 모든 tensor는 크기와 type이 동일
- tf.RaggedTensor ** list의 list, Tensor에 포함된 값은 동일한 data type을 가져야 하지만, list의 길이는 다를 수 있음
- String Tensor
- set ** 집합은 일반적인 tensor(또는 희소 tensor)를 나타냄
- queue ** 단계별로 tensor를 저장
- Huber 손실: 회귀 model을 훈련하는데 훈련 set에 잡음 data가 조금 있는 경우 손실함수로 사용 (MSE는 큰 오차에 너무 과한 벌칙을 가하기 때문에 정확하지 않은 model 생성, MAE는 이상치에 관대하여 훈련이 수렴되지까지 시간이 걸리고, 정밀하게 훈련되지 않음 mapping해야 함
- Keras가 함수 이름을 저장하므로 사용자 정의 손실 함순를 저장한 model은 아무 이상 없이 저장됨
- Model을 load할 때는 함수 이름과 실제 함수를 mapping한 dictionary 전달해야 함. 좀더 일반적으로 사용자 정의 객체를 포함한 model을 load할 때는 그 이름과 객체를
- model을 저장할 때는 손실 함수의 매개변수 값이 저장되지 않으므로, model을 load할때 값을 지정해야함
- 또는 keras.losses.Loss class를 상속하고 get_config() method를 구현해야 함 ** model을 저장할 때 Keras는 손실 객체의 get_config() method를 호출하여 반환된 설정을 HDF5 file에 JSON형태로 저장. model을 load하면 HuberLoss class의 from_config() class method 호출. 이 method는 기본 손실 class(Loss)에 구현되어 있고 생성자에게 **config 매개변수를 전달하여 class instance를 생성
- 손실, 규제, 제한, 초기화, 지표, 활성화 함수, 층, model과 같은 대부분의 Keras 기능은 customizing 가능
- 대부분 적절한 입력과 출력을 가진 간단한 함수를 작성하면 됨, 매개변수는 정의하려는 함수의 종류에 따라 달라짐
- 함수가 model과 함께 저장해야 할 hyperparameter를 가지고 있다면 keras.regularizers.Regularizer, keras.constraints.Contraint, keras.initializers.Initializer, keras.layers.Layer와 같이 적절한 class를 상속
- 손실, 층, model의 경우 call() method를 구현해야 함
- 규제, 초기화 ,제한의 경우 call() method를 구현해야 함
- 손실은 model을 훈련하기 위해 경사 하강법에서 사용하므로 미분 가능해야 하고 gradient가 모든 곳에서 0이 아니여야 함.
- 지표는 model을 평가해야 함. 지표는 훨씬 이해하기 쉬어야 함. 미분이 가능하지 않거나 모든 곳에서 gradient가 0이어도 괜찮음
- streamingㅈ metric or stateful metric : 배치마다 점진적으로 update되는 지표
- kears.metrics.Metric class를 상속하여 streaming 지표 생성
- 가중치가 필요 없는 사용자 정의 층을 만들기 위한 가장 간단한 방법은 python 함수를 만든 후 keras.layers.Lambda층으로 감쌈. 이 층은 sequential API, subclassing API에서 보통의 층과 동일하게 사용. 또는 활성화 함수로도 사용 가능
- 가중치가 있는 층을 만들려면 keras.layers.Layer를 상속 ** 생성자: 모든 hyperparameter를 매개변수로 받음(**kargs로 매개변수를 추가하는 것도 중요). 부모 생성자를 호출하면서 kwargs를 전달. 이를 통해 input_shape, trainable, name과 같은 기본 매개변수를 처리. hyperparameter를 속성으로 저장하고 activation 매개변수를 적절한 활성화 함수로 설정 ** build(): 가중치마다 add_weight()를 호출하여 층의 변수를 생성. 층이 처음 사용될 때 호출됨. 이 시점에는 keara가 layer의 입력 크기를 알고 있으므로 build() method로 크기를 전달 build() method (반드시) 끝에서 부모의 build() method를 호출해야 함. 이를 통해 층이 만들어졌다는 것을 Keras가 인식(self.built=True로 설정됨) ** call(): 해당 layer에서 필요한 연산 수행 ** computer_output_shape(): 출력 크기를 반환 ** get_config(): 설정을 저장
- 동적인 layer을 제외하고 tf.keras가 자동으로 출력 크기를 추측할 수 있다면 compute_output_shape() method 생략 가능
- 훈련과 test에서 다르게 동작하는 층(e.g.: Dropout, BatchNormalization) 이 필요하다면 call() method에 training 매개변수를 추가하여 훈련인지 test인지를 결정
- keras.Model class를 상속하여 생성자에서 층과 변수를 만들고 model이 해야 하 작업을 call() method에 구현
- save() method를 사용해 model을 저장하고, keras.models.load_model() method를 사용해 저장된 model을 load하고 싶다면 get_config() method구현. 또한 save_weights(), load_weights() method를 사용해 가중치 저장 및 load
- Model class는 Layer class의 sub class. compile(), fit(), evaluate(), predict() 추가적인 기능이 있음. get_layers(), save() tehod가 있음
- Layer층을 Model처름 정의 가능하나. 일반적으로 model 안의 내부 구성 요소(즉, model의 층이나 재사용 가능한 층의 block)를 model(훈련 대상 객체)와 구분하는 것은 당연
- blahblahblah~~정리 필요
- blahblahblah~~정리 필요
- blahblahblah~~정리 필요
- TensorFlow1에서 Graph는 TensorFlow 핵심이지만 복잡도가 높았음. TensorFlow2에도 있지만 이전만큼 핵심적이지 않고 사용하기 쉬움
- tf.function() or @tf.function ** Python 함수를 TensorFlow 함수로 변경. 반환 값은 tensor임. 원본 Python함수는 python_function 속성을 참조 ** 함수에서 수행되는 계산을 분석하고 동일한 작업을 수행하는 계산 graph를 생성 ** TensorFlow는 사용하지 않은 계싼을 제거하고 표현을 단순화 ** 최적화된 graph가 준비되면 TensorFlow함수는 적절한 순서에 맞춰(가능하면 병렬로) graph내의 연산을 효율적으로 실행 -> 일반적으로 원본 Python함수보다 빠름 (특히 복잡한 연산에서 더 빠름). Python 함수를 더 빠르게 실행하려면 TensorFlow함수로 변환하라!!
- 사용자 정의 손실, 지표, 층 또는 어떤 사용자 정의 함수를 작성하고 이를 Keras model에 사용할 때 keras는 이 함수를 자동으로 TensorFlow 함수로 변환(tf.function() 필요 없음. 자동 변환을 막으려면 사용자 정의 층이나 model을 마들대 dynamic=True로 지정 또는 model compile() method 호출시 run_eagerly=True지정)
- TensorFlow 함수는 호출에 사용되는 입력 크기와 data type에 맞춰 매번 새로운 graph생성(매개변수 값이 tensor인 경우만 해당. Python값은 매번 생성) -> 다형성(polymorphism) 처리
- Python 값으로 TensorFlow 함수를 여러 번 호출하면 program이 느려지고 memory 사용량이 증가함. 층의 neuron개수와 같은 hyperparameter처럼 몇 개의 고유한 값이 있은 경우에만 매개변수 값에 Python값을 사용. 이렇게 해야 TensorFlow model을 최적화 할 수 있음.
- Graph 생성 순서
- ** AutoGraph ** : Python 함수 source code 분석 후 순환문 및 제어문을 찾은 후 TensorFlow 연산으로 변경하여 upgrade 함수 생성
- TensorFlow가 1번 단계에서 생성된 upgrade 된 함수 호출. 매개변수 값을 전달하는 대신 값이 값이 없고 이름, data type, 크기만 가지는 Symbolic Tensor전달
- 2번의 호출은 Graph mode 로 실행. 즉 TensorFlow 연산이 해당 연산을 나타내고 tensor를 출력하기 위해 graph에 node 추가(Eager execution or Eager mode 와 반대 개념) => 어떤 연산도 하지 않음
- Tracing 과정을 통해 최종 graph 생성
- 대부분의 경우 TensorFlow 연산을 수행하는 Python 함수를 TensorFlow 함수로 바꾸는 것은 간단. @tf.function decorator를 사용하면 TensorFlow가 알아서 처리
- 규칙
- Numpy등 표준 library를 포함하여 다른 library를 호출하면 tracing 과정에서 실행됨. 즉 graph에 포함되지 않음
- 다른 Python 함수나 TensorFlow 함수를 호출할 수 있음. 이 함수들의 연산을 감지하므로 동일한 규칙을 따름. 이런 함수들은 @tf.fuction decorator를 적용할 필요 없음
- 함수에서 TensorFlow 변수를 만든다면 처음 호출될 때만 수행되어야 함. 그렇지 않으면 예외 발생. TensorFlow 함수 밖에서 생성하는 것이 좋음. 변수 값 할당은 = 대신 assign() method 사용
- Python 함수의 source code는 TensorFlow에서 사용가 가능해야 함
- TensorFlow는 tensor나 dataset을 순회하는 for문만 감지. for i in range(x) 대신 for i in tr.range(x) 사용. 그렇지 않으면 graph에 표현 안됨
- 성능면에서 반복문보다는 가능한한 vector 구현 사용 추천
- The Data API
- Chaining Transformations
- Shuffling the Data
- Preprocessing the Data
- Putting Everything Together
- Prefetching
- Using the Dataset with tf.keras
- The TFRecord Format
- Compressed TFRecord Files
- A Brief Introduction to Protocol Buffers
- TensorFlow Protobufs
- Loading and Parsing Examples
- Handling Lists of Lists Using the SequenceExample Protobuf
- Preprocessing the Input Features
- Encoding Categorical Features Using One-Hot Vectors
- Encoding Categorical Features Using Embeddings
- Keras Preprocessing Layers
- TF Transform
- The TensorFlow Datasets (TFDS) Project
- Exercises
- 합성공 신경망(CNN: Convoluational Neural Network)는 대뇌의 시각 피질 연구에서 시작되었고, 최근 컴퓨터 성능향상, 많은 양의 훈련 data, 개선된 신경망 훈련 기술로 image 처리시 인간을 능가하는 성능 달성
- CNN은 시각 분야게 국한 되지 않고 음성인식(voice recognition) , 자연어 처리(NLP: natural language process) 와 같은 다른 작업에서 많이 사용
- 시각 피질 않의 많은 neuron이 작은 국부 수용장(local receptive unit) 을 가진다.
- 시각 피질에 대한 연구 -> 합성곱 신경망 으로 진화
- Image 인식 문제에서 완전 연결 심층 신경망을 사용하지 않은 이유는 큰 image에 대해 많은 parameter가 만들어지기 때문. CNN은 층을 부분적으로 연결하고 가중치를 공유하여 문제 해결
- 참고: 합성곱 신경망
- 합성곱 연산: Kernel 또는 Filter라는 m x n 크기 행렬로 높이(height) x 너비(width) 크기의 image를 처음부터 끝가지 겹치며 훑으면서 m x n크기의 겹쳐지는 부분의 각 image와 kernel이 원소의 값을 곱해서 모두 더한 값을 출력
- 특성 map(feature map) : Kernel을 사용하여 합성곱 연산을 통하여 나온 결과
- stride : kernel의 이동 범위
- padding : 합성곱의 연산의 결과로 얻은 특성 map은 입력보다 크리가 작아진다는 특징이 있음. 합성곱 연산 후에도 특성 map의 크기가 입력과 동일하게 유지하도록 할 때 사용
- 합성곱 신경망에서 가중치는 kernel 행렬의 원소들임.
- 합성곱 편향은 kernel을 적용한 뒤에 더해짐. 편향은 하나만 존재하며 kernel이 적용된 결과의 모든 원소에 더해짐
- 합성곱 층(convolutional layer): 합성곱 연산을 통해서 특성 map을 얻고, 활성화 함수를 지나는 연산을 하는 합성곱 신경망의 은닉층
- 특성 map의 크기 계산 방법
- 다수 channel을 가질 경우의 합성곱 연산(3차원 tensor의 합성곱 연산)
- Kernel의 channel수도 입력 channel의 수만큼 존재해야 함.
- channel수가 값으므로 합성곱 연산을 channel마다 수행 후, 그 결과를 모두 더하여 최종 특성 map 생성
- 합성곱 연산의 결과로 얻은 특성 map의 channel 차원은 RGB channel등과 같은 color의 의미를 담고 있지 않음
-
Pooling
- 특성 map을 down sampling하여 특성 map의 크기를 줄이는 연산. 일반적으로 최대 pooling과 평균 pooling이 사용됨
- Kernel과 stride 개념을 가짐. 그렇지만 학습해야 할 가중치가 없으며 연산 후 channel 수가 변하지 않음
- 상위 참조
- 상위 참조
- 상위 참조
- 상위 참조
- 상위 참조
- 상위 참조
- 물체의 위치를 추정하는 것은 회귀 작업. 물체 주위의 bounding box를 예측하는 일반적인 방법은 물체 중심의 수평, 수직 좌표와 높이, 너비를 예측하는 것
- image bounding box 작업(label은 만드는 것은 machine learning project에서 가장 어렵고 비용이 많이 드는 작업중 하나)
- Open source: VGG Image Annotator, LabelImg, OpenLabeler, ImageLab
- 유료 제품: LabelBox, Supervisely
- Crowd sourcing platform: Amazon machanical turk -> image가 매우 많은 경우. 여러 절차가 필요하므로 꼭 필요한지 확인해야 함
- IoU(intersection over union) : bounding box에 대한 성능지표. 예측한 bounding box와 target bounding box사이의 중첩되는 영역을 전체 영역으로 나눈 것. tf.keras.metrics.MeanIoU
- 객체 탐지(Object detection): 하나의 image에서 여러 물체를 분류라고 위치를 추정하는 작업
- Pixel이 속한 객체의 class로 분류
- 참고: 순환신경망(Recurrent Neural Network)
- 미래를 예측할 수 있는 Network
- 일반적으로 이 신경망은 지금까지 봤던 모든 network처럼 고정 길이 입력이 아닌 임의 길이를 가진 sequence를 다룰 수 있음
- 문장, 문서, Audio sample을 입력으로 받을 수 있고, 자동 번역, speech to speech 같은 자연어 처리(NLP: Natural Language Process)에 매우 유용
- RNN이 sequence data를 다루 수 있는 유용한 신경망은 아님. 작은 sequence의 경우 밀집 network가, audio sample이나 text처럼 긴 sequence는 합성곱 신경망도 잘 동작
- RNN은 FFNN와 매우 유사하지만 뒤쪽으로 순환하는 연결이 있따는 점이 다름
- 각 Time step(또는 Frame) t마다 **순환 neuron은 물론 x(t)와 이전 time step의 출력인 y(t-1)를 입력으로 받음
- 순환 neuron으로 된 층 생성도 쉬움. 각 time step t마다 모든 neuron은 입력 vector xt와 이전 time step의 출력 vector y(t-1)를 받음
- 각 순환 neuron은 두 벌의 가중치를 가짐. 하나는 x(t)를 위한 것이고, 다른 하나는 이전 time step의 출력 y(t-1)를 위한 것임. 각각 w(x), wy. 순환층 전채를 생각하면 Wx, Wy
- 출력값 계산 수학식 blahblahblah~~~
- Time step t에서의 순환 neuron의 출력은 이전 time step의 모든 입력에 대한 함수이므로 이를 일종의 Memory 형태라 말할 수 있음
- Memory Cell(또는 간단히 Cell) : time step에 걸쳐서 어떤 상태를 보존하는 신경망의 구성요소
- 기본 RNN 기본 cell의 경우 출력은 cell의 상태와 동일하지만, 더 복잡한 cell에서는 항상 그렇지 않음(cell의 hidden 상태를 다음 time step에 입력)
- Sequence to Sequence: 주가 예측
- Sequence to Vector: 영화 review 감성 점수
- Vector to Sequence: image caption
- Encode - Decoder: 문장 번역
- Sequence to Sequence를 이용한 번역보다 성능이 좋음. 문장의 마지막 단어가 번역의 첫 번째 단어에 영향을 줄 수 있기 때문임. 그래서 전체 문장이 주입될 때까지 대기 필요
- BPTT(BackPropagation Trough Time) : Time step으로 network를 펼치고 보통의 역전파를 사용하여 훈련함
-
시계열: time step마다 하나 이상의 값을 가진 sequence.
- 단변량 시계열 : time step마다 값이 하나
- 다변량 시계열 : time step마다 값이 여러 개
- 예측(forecasting) : 미래의 값 예측
- 값 대체(imputation) : 비어있는 값을 채우는 것
- 시계열을 (그리고 문장과 같은 다른 종류의 sequence)를 다룰 때 입력 특성은 일반적으로 [batch_size, time step 수, 차원 수] 크기의 3차원 배열로 나타냄
- RNN을 시작하기 전에 기준 성능을 몇 개 준비하는 것이 좋음 (아래는 기준 성능의 예시)
- 순진한 예측(naive forecating) : 각 시계열의 마지막 값을 그대로 예측
- 완전 연결 network 사용
- keras.layer.SimpleRNN
- 순환 신경망은 어떤 길이의 time step도 처리할 수 있기 때문에 (이전 model과 달리) 입력 sequence의 길이를 지정할 필요 없음
- 기본적으로 SimpleRNN층은 tanh 활성화 함수 사용
- 기본 RNN에서는 출력이 새로운 상태가 됨. 이 새로운 상태가 다음 입력값 x(t)와 함께 동일한 순환 neuron으로 전달됨. 이 과정이 마지막 time step까지 반복됨. 그 다음 층의 마지막 값 출력. 모든 시계열에 대해 이 과정이 동시에 일어남
- 기본적으로 Keras의 순환 층은 최종 출력만 반환. time step마다 출력을 반환하려면 return_sequence=True 지정
- 선형 model은 각 neuron에 대해 입력(time step)마다 하나의 parameter를 가지고 편향 존재. 기본 RNN의 순환 neuron은 입력과 은닉 상태 차원(기본 RNN에서는 층의 순환 neuron 개수와 같음)마다 하나의 parameter와 편향 가짐. 기본 RNN에서는 총 3개의 parameter있음
- RNN cell을 여러 층으로 쌓은 것
- 모든 순환 층에서 return_sequence=True로 설정해야 함(마지막 출력만 관심 댛상이면 마지막 층은 설정하지 않음)
- 마지막 SimpleRNN층은 기본적으로 tanh 활성화 삼수를 사용하기 때문에 다른 활성화 함수를 사용해야 하는 경우 출력층을 Dense층으로 바꾸는 경우가 많음
- keras.layers.TimeDistributed: 이 층은 다른 층(예를 들어, Dense층)을 감싸서 입력 sequence의 모든 time step의 출력을 적용. 각 time step을 별개의 sample처럼 다루도록 입력의 크기를 바꾸어 이를 효과적으로 수행. ([batch_size, time step 수, 입역 차원] -> [batch_size * time step 수, 입력 차원]) 그 다음 감싸고 있는 층에 값을 적용하고 출력 크기를 sequence로 되돌림([batch_size * time step 수, 입력 차원] ->[batch_size, time step 수, 입역 차원]). 실제로 Dense층은 sequence(그리고 더 고차원) 입력을 받을 수 있지만 Dense층을 time step마다 독립적으로 적용하고 model이 하나의 vector가 아니라 sequence를 출력한다는 것을 잘 드러내도록 TimeDeistributed를 사용
- 시계열을 예측할 때 오차 막대(Error bar)를 사용하는 것이 유용
- 긴 sequence의 data를 다룰 때 많은 time step에 걸쳐 실행해야 하므로 RNN이 매우 깊은 network가 됨.
- 심층 신경망처럼 gradient 소실과 폭주 문제를 가질 수 있음
- 훈련시 오랜시간이 걸리거나 불안정할 수 있음
- RNN이 긴 sequence를 처리할 때 입력의 첫 부분을 조금씩 잊어버릴 수 있음
- 활성화 함수
- 불안정한 gradient 문제는 좋은 가중치 초기화, 빠른 optimizer, dropout등으로 완화할 수 있지만, 수렴하지 않은 활성화 함수(e.g. ReLU)는 큰 도움이 되지 않고 RNN을 더 불안정하게 만들 수 있음.
- 이유는 경사하강법이 첫번째 time step에서 출력을 조금 증가시키는 방향으로 가중치를 update한다 가정하면, 동일한 가중치가 모든 time step마다 동일하게 사용되지 때문에 출력이 폭주할 수 함. 수렴하지 않은 활성화 함수는 이를 막지 못함. 작은 학습율을 사용하여 이런 위험을 감소시킬 수 있지만 간단히 tanh같은 수렴하는 활성화 ㅎ마수를 사용할 수 있음(tanh가 기본값인 이유임)
- 같은 방식으로 gradient 자체가 폭주할 수 있음. 훈련이 불안정하다고 느껴지면 gradient 크기를 monitoring하고 gradient clipping을 사용하는 것이 좋음
- Batch 정규화
- Batch 정규화는 FFNN처럼 RNN에 효율적으로 사용할 수 없음. 사실 time step사이에 사용할 수 없고 순환층 사이만 가능
- Memory Cell에 batch 정규화층을 추가하여 time step마다 적용 가능. 하지만 입력이나 은닉상태의 실제 scale과 이동에 상관없이 동일한 parameter를 가진 batch 정규화가 time step마다 사용될 것임
- Batch 정규화는 RNN 성능 개선에 큰 도움은 안됨
-
층 정규화(Layer normalizatio)
- Batch 정규화와 매우 비슷하지만 batch 차원에 대해 정규화하는 대신 특성 차원에 대해 정규화
- Sample에 독립적으로 time step마다 동적으로 필요한 통계 계산
- 사용자 정의 RNN cell생성 후 층 생성 가능
- Dropout
- keras.layers.RNN을 제외한 모든 순환 층과 Keras에서 제공하는 모든 cell은 dropout, recurrent_dropout 매개변수 지원
- dropout: time step마다 입력에 적용되는 dropout 비율
- recurrent_dropout: time step마다 은닉 상태에 대한 dropout 비율
- RNN에서 time step마다 dropout을 적용하기 위해 사용자 정의 cell을 만들 필요 없음
- RNN을 거치면서 data가 변화디므로 일부 정보는 매 훈련 step마다 사라짐
- 장기 memory를 가진 여러 종류의 cell이 연구되어 최근에는 기본 cell(SimpleRNN)이 많이 사용되지 않음
-
장단기 memory(LSTM: Long Short Term Memory)
- keras.layers.LSTM: GPU 실행에 최적화 되어 있으므로 선호되는 방법임
- keras.layers.RNN층에 LSTMCell을 매개 변수로 지정: 사용자 정의 cell을 만들때 많이 사용
- 입력 gate, 삭제 gate, 출력 gate를 가짐
- LSTM cell은 중요한 입력을 인식하고(입력 gate), 장기 상태에 저장하고, 필요한 기간 동안 이를 보존하고(삭제 gate), 필용할 때만다 이를 추출하기 위해 학습
-
핍홀 연결(peephole connnection)
- LSTM gate 제어기에 장기 상태도 조금 노출시켜 좀 더 많음 문맥을 감지하는 LSTM 변종
- 성능을 향상하는 경우가 많지만 늘 그렇지 않음.
- tf.keras.experimental.PeepholeLSTMCell 층
-
Geta 순환 Unit(GRU: Gate Recurrent Unit)
- LSTM cell의 간소화 version
- keras.layers.GRUCell을 기반으로 하는 keras.layers.GRU층 제공
- LSTM과 GRU cell은 RNN성공의 주역이지만 매우 제한적인 단기 기억을 가짐. 100 time step이상의 sequence에서 장기 pattern 학습에 어려움 있음. 이에 대한 한 가지 방법은 1D 합성곱 층을 사용해 입력 sequence를 짧게 줄이는 것
- 1D 합성곱 층을 사용해 시퀀스 처리하기
- 1D 합성곱 층이 몇개의 kernel을 sequenced 위를 sliding하여 kernel 마다 1D 특성 map 추출
- 각 kernel은 매우 짧은 하나의 순차 pattern을 감지하도록 학습됨
- WAVENET
- keras.utils.get_file() 함수를 사용해 data download
- 모든 글자를 정수로 encoding: keras.preprocessing.text.Tokenizer() 함수 사용. encoding된 ID값은 1에서부터 시작(0은 masking에 사용)
- 암묵적으로 RNN이 과거(훈련 set)에서 학습하는 pattern이 미래에도 등장한다고 가정. 이 시계열 data(넓은 의미에서)가 **변하지 않는다(stationary)**고 가정
- 많은 경우 시계열에서 이 가정은 타당(e.g. 화학법칙) 하나 그렇지 않은 경우도 있음(e.g. 금융시장)
- 시계열이 진짜 중분히 안정적인지 확인하려면 시간에 따라 검증 set에 대한 model의 오차를 그려볼 수 있음. model이 검증 set 마지막보다 첫 부분에서 성능이 더 좋다면 이 시계열이 충분히 안정되지 않았다 추측할 수 있음
- 시계열을 훈련/검증/test set로 나누는 것은 간단한 작업이 아니며, 문제에 따라 달라짐
- 백 만개 이상의 글자로 이뤄진 sequence를 통째로 훈련할 수 시는 없음. 이 RNN은 백만 개의 층이 있는 심층 신경망과 비슷하고 매우 긴 sample 하나로 훈련하는 것과 같음
- Dataset의 window() method를 사용해 긴 sequence를 작은 많은 text window 변환. 전체 text에서 매울 짧은 부분 문자열
- TBPTT(Truncated Backpropagation Trough Time): RNN이 위의 부분 문자열 길이만큼만 역전파을 위해 펼쳐짐
- dataset.window()
- shift=1로 지정하면 가장 큰 훈련 set 생성
- drop_remainder=True로 지정하여 모든 window가 동일한 size를 가지게 함
- 결과물은 중첩 dataset(nested dataset)
- dataset.flat_map()
- model은 dataset이 아니라 tensor를 기대하므로 중첩 dataset을 바로 사용할 수 없음. 그러므로 중첩 dataset를 flat dataset 으로 만들기 위해 사용
- 중첩 dataset을 평평하게 만들기 전에 각 dataset에 적용할 변환 함수를 매개변수로 받을 수 있음
- datatset.shuffle(), dataset().batch()
- window마다 batch(window_length) 호출
- 경사 하강법은 훈련 set sample이 동일 독립 분포일 때 가장 잘 작동하므로 shuffle()
- dataset.map()
- 입력과 target으로 분리
- 범주형 입력 특성은 one-hot vector나 embedding으로 encoding 되어야 하므로 변환시 사용
- dataset.prefetch()
- tf.random.categorical()
- 상태가 없는 RNN(stateless RNN) : 훈련 반복마다 model의 은닉 ㅅ아태를 0으로 초기화. time step마다 상태를 update하고 마지막 time step후에는 필요 없기 때문에 버림
- 상태가 있는 RNN(stateful RNN) : 한 훈련 batch 처리후에 마지막 상태를 다음 훈련 batch의 초기 상태로 사용. 역전파는 짧은 sequence에서 일어나지만 model이 장기간 pattern 학습 가능.
- 순차적이고 겹치지 않은 입력 sequence 생성(stateless RNN에서 훈련하기 위해 사용한 섞은 뒤 겹쳐진 sequence와 다름)
- dataset 생성시 window()에 shift=1이 아닌 shift=n_steps사용. shuffle() method 제거
- 각 batch의 첫 번째 window를 생각하면 연속적이지 않을 수 있으므로, 하나의 window를 가지는 batch 생성
- 한 batch에서 n번째 입력 sequence의 시작은 정확히 이전 batch의 n번째 입력 sequence의 끝 지점
- 각 순환 층을 만들때 stateful=True로 지정
- 상태가 있는 RNN은 batch 크기를 알아야 함(batch에 있는 입력 sequence 상태를 보존해야 하기 때문)
- IMDB
- MNIST가 computer vision계의 'hello world'라면, 자연어 처리계에서는 IMDB review
- 영화 review 50,000개(훈련 25,000, test 25,000)
- Notebook에서 감당할 시간 안에 처리할 수 있을 만큼 간단하지만 충분히 재미있고 도전 가치 있음
- data 전처리
- 실전 projec에서는 직접 text 전처리
- Tokenizer class 사용. char_level=False 단어 단위 처리. 대부분 구두점, 줄바꿈. tab을 포함한 많은 글자가 제거됨
- 공백 기준 단어 분리 시. 국가에 따라 문제가 있을 수 있음
- 더 좋은 방법은
- 부분 단어 수준으로 text를 token화 하거나 비지도 학습 방법
- Google의 SentencePiece
- 부분 단어를 encoding하는 방법
- Byte pair encoding
- TF.text library
- Byte pair encoding의 변종인 WordPiece를 포함한 많은
- 부분 단어 수준으로 text를 token화 하거나 비지도 학습 방법
- 원래 data 그대로 model이 padding token을 무시하도록 학습 되어야 함. padding token을 무시핟록 model에게 알려주어 실제 의미가 있는 data에 집중할 수 있게 만드는 것은 당연
- Embedding층의 mask_zero=True: 이렇게 하면 이어지는 모든 층에서 (ID가 0인) padding token을 무시
- Mask tensor는 model에 의해 이어지는 모든 층에 time step 차원이 유지되는 한 자동을 전파됨. 층마다 mask tensor를 다르게 다룰 수 있지만 일반적으로 masking된 time step을 무시함.
- 만약 mask가 출력에도 전파된다면(sequence를 출력하는 model) 손실에도 적용될 수 있음. 따라서 masking된 time step은 손실에 영향을 미치지 못할 것임(이 time step의 손실은 0)
- Mask를 받는 모든 층은 making을 지원해야 함(그렇지 않으면 예외 발생). 모든 순환층은 물론 TimeDistributed층과 몇 개의 다른 층도 포함
- Masking을 지원하는 모든 층은 supports_masking 속성값이 True.
- Masking을 지원하는 사용자 정의 층을 만들려면 call() method에 mask 매개변수 추가. 생성자에 self.supports_making=True 지정. 사용자 정의 층이 Embedding층으로 시작하지 않은다면 대신 keras.layers.Masking층 사용할 수 있음.
- Masking층과 mask 자동 전파는 Sequentail model에 가장 적합. Conv1D층과 순환 층을 섞는 것과 같이 복잡한 model에서는 항상 동작하지 않음. 이런 경우 함수형 API나 subclassing API를 사용해 직접 mask를 계산하여 다음 층에 전달해야 함
- 대량의 text corpus에서 훈련된 단어 embedding을 재사용할 수 있음. 그러므로 많은 parameter를 사용해서 단어 embedding을 학습하기보다 사전 훈련된 embedding 재사용을 검토해 보는 것이 좋음
- TensorFlow Hub Project: 사전 훈련된 model component(모듈(module))를 model에 추가하기 쉽게 만들어줌.
- Module과 사전 훈련된 가중치를 자동으로 download 받아 model에 포함 시킴
- 기본적으로 TF hub는 download한 file을 local system의 임시 directory에 caching. TFHUB_CACHE_DIR 환경 변수를 지정하여 원하는 directory에 지정할 수 있음
- 일반적인 tensor는 크기가 고정되어 있기 때문에 동일한 길이의 문장만 담을 수 있음. 문장의 길이가 다른 경우에는 masking을 사용하여 처리. 문장길이 차이가 많이 나는 경우에는 비슷한 길이의 bucket을 group화. bucket에 담긴 문장이 모두 동일한 길이를 가지도록 padding 추가(tf.data.experimental.bucket_by_sequenct_length())
- EOS token 이후의 출력은 무시
- Sampling Softmax: 출력 어휘 사전이 방대한 경우 모든 단어의 확률을 출력하면 속도가 매우 느려짐. 이를 피하기 위해 target 단어에 대한 logit과 target이 아닌 단어에 대한 logit만을 고려함. TensorFlow에서는 훈련 시 tf.nn.sample.softmax_loss() 함수를 사용하고 추론 시에는 일반 softmax 함수를 사용(Sampling softmax는 target을 알고 있어야 하므로 추론시 사용할 수 없음)
- TensorFlow Addon project에는 여러가지 Sequence-to-Sequence 도구를 가지고 있어 제품 수준의 encoder-decoder를 쉽게 만들 수 있음
- 양방향 순환층(bidirectional recurrent layer) : 하나는 왼쪽에서 오른쪽으로 단어를 읽고 다른 하나는 오른쪽에서 왼쪽으로 읽음. 그 다음 일반적으로 이 두출력을 연결
- keras.layers.Bidirectional
- Beam 검색(Beam search): model이 앞선 실수를 고칠 수 있게 하는 방법 중 하나. k개의 가능성이 있는(예를 들면 상위 3개) 문장의 list를 유지하고 decoder 단계마다 이 문장의 단어를 하나씩 생성하영 가능성 있는 k개이 문장 생성. 여기서 k는 Beam 너비(Bean width)
- TensorFlow Addon BeamSearchDecoder
- 참고: Attention Mechanism
- 각 time step에서 (encoder에 의해 encoding하여) 적절한 단어에 decoder가 초점을 맞추도록 하는 기술
- Attention은 신경망 기계 번역(그리고 일반적인 NLP 작업)에 큰 변환를 만들었음. 특히 (30개 단어 이상의) 긴 문장에 대해서 최고 수준의 성능을 크게 향상 시킴
- Encoder의 마지막 은닉 상태만 decoder로 보내는 것이 아니라 encoder의 모든 출력을 decoder로 전송. 각 time step마다 decoder의 memory cell은 이런 모든 encoder 출력의 가중치 합을 계산하고 주의를 집중해야 할 단어를 결정
- Bahdanau attention(concatenative attention, additive attention)
- Luong attention(multiplicative attention)
- TensorFlow Addon에 여러가지 attention 제공
- 설명가능성(explainability) : Attention의 추가적인 장점은 model이 어떤 출력을 만들도록 이끄는 것이 무엇인지 이해하기 쉬움. model의 예측이 올바르지 않을 때 유용. 일부 application에서 설명 가능한 model을 debugging하는 용도 뿐만 아니라 법적 요구 사항일 수 있음
- NLP외에 Attention이 활용되는 분야 중 하나
- 예를 들어 image caption이 visual attention을 활용한 application임
- 참고: Transformer
- 순환층이나 합성곱층을 전혀 사용하지 않고 attention만 (그리고 embedding층, dense층, 정규화층, 몇 가지 다른 구성 요소를 더해) 사용해 NMT 문제에서 최고 수준 성능을 크게 향상
- 추가적인 장점은 이 주고즐 훨씬 빠르게 훈련할 수 있고 병렬화하기 쉬움. 따라 서 이전 model에서 최고 성능을 내기 위해 피룡한 시간과 비용 일부만으로 훈련할 수 있음
- 2018년은 'NLP를 위한 imagenet 시대'라고 부를 정도로 놀라운 속도로 발전됨. 갈수록 큰 LSTM과 transformer기반의 modeldl 엄청난 dataset에서 훈련됨
- ELMO(Embedding from Language Model)
- GPT
- 비지도 사전훈련 방식. Transformer와 유사한 구조
- 대규모 dataset에서 (masked multi-head attention층만 사용한) transformer module 23개를 쌓아 규모가 크지만 간단한 model을 사전 훈련함
- BERT(Bidirectional Encoder Representation from Transformer)
- GPT와 비슷한 구조지만 (transformer의 encoder처럼) mask가 없는 multi-head attention 층 사용
- 자연스럽게 양방향성을 가짐
- 두 가지 사전 훈련 작업
-
MLM(Masked Langugage Model)
- 문장에 있는 각 단어는 15% 확률로 masking후 model은 masking한 단어를 예측하도록 훈련
- 선택된 각 단어는 80% 확률로 masking되고 10% 확률로 다른 단어로 바꿈(model을 세부 tuning하는 동안 token이 없기 때문에 사전 훈련과 세부 tuning 사이의 차이점을 줄이기 위해서임). 그리고 10% 확률로 그래도 남겨짐(정확한 답으로 model을 편향시키기 위함)
-
NSP(Next Sentence Prediction)
- 두 문장이 연속적인지 아닌지를 예측하도록 model을 훈련
- 질문 대답이나 수반 관계와 같은 작업에서 세부 tuning을 할때 model 성능을 크게 향상시킴
-
MLM(Masked Langugage Model)
- Efficient Data Representations
- Performing PCA with an Undercomplete Linear Autoencoder
- Stacked Autoencoders
- Implementing a Stacked Autoencoder Using Keras
- Visualizing the Reconstructions
- Visualizing the Fashion MNIST Dataset
- Unsupervised Pretraining Using Stacked Autoencoders
- Tying Weights
- Training One Autoencoder at a Time
- Convolutional Autoencoders
- Recurrent Autoencoders
- Denoising Autoencoders
- Sparse Autoencoders
- Variational Autoencoders
- Generating Fashion MNIST Images
- Generative Adversarial Networks
- The Difficulties of Training GANs
- Deep Convolutional GANs
- Progressive Growing of GANs
- StyleGANs
- Exercises
- Learning to Optimize Rewards
- Policy Search
- Introduction to OpenAI Gym
- Neural Network Policies
- Evaluating Actions: The Credit Assignment Problem
- Policy Gradients
- Markov Decision Processes
- Temporal Difference Learning
- Q-Learning
- Exploration Policies
- Approximate Q-Learning and Deep Q-Learning
- Implementing Deep Q-Learning
- Deep Q-Learning Variants
- Fixed Q-Value Targets
- Double DQN
- Prioritized Experience Replay
- Dueling DQN
- The TF-Agents Library
- Installing TF-Agents
- TF-Agents Environments
- Environment Specifications
- Environment Wrappers and Atari Preprocessing
- Training Architecture
- Creating the Deep Q-Network
- Creating the DQN Agent
- Creating the Replay Buffer and the Corresponding Observer
- Creating Training Metrics
- Creating the Collect Driver
- Creating the Dataset
- Creating the Training Loop
- Overview of Some Popular RL Algorithms
- Exercises
- Serving a TensorFlow Model
- Using TensorFlow Serving
- Creating a Prediction Service on GCP AI Platform
- Using the Prediction Service
- Deploying a Model to a Mobile or Embedded Device
- Using GPUs to Speed Up Computations
- Getting Your Own GPU
- Using a GPU-Equipped Virtual Machine
- Colaboratory
- Managing the GPU RAM
- Placing Operations and Variables on Devices
- Parallel Execution Across Multiple Devices
- Training Models Across Multiple Devices
- Model Parallelism
- Data Parallelism
- Training at Scale Using the Distribution Strategies API
- Training a Model on a TensorFlow Cluster
- Running Large Training Jobs on Google Cloud AI Platform
- Black Box Hyperparameter Tuning on AI Platform
- Exercises