<repo_name>unlocker-sy/deep_learning_basic<file_sep>/study/tensorflow/dl_for_everyone_season2/README.md
# 모두를 위한 딥러닝 시즌 2
모두를 위한 딥러닝 시즌2 의 내용을 개인적으로 필요한 부분만 요약, 이해한대로 정리한 자료
https://deeplearningzerotoall.github.io/season2/lec_tensorflow.html

# Youtube
 - 시즌1
 https://hunkim.github.io/ml/
 - 시즌2
https://www.youtube.com/playlist?list=PLQ28Nx3M4Jrguyuwg4xe9d9t2XE639e5C



# Slide
 - 시즌1
 https://hunkim.github.io/ml/
 - 시즌2
 https://drive.google.com/drive/folders/1twBsdLkI2P15J0DgYs77_E_EVKt7Ghav

# Code
https://github.com/deeplearningzerotoall/TensorFlow<file_sep>/study/tensorflow/dl_for_everyone_season2/01_basic_concept_deeplearning.md
# ML lec01 기본적인 Machine Learning 의 용어와 개념 설명

머신러닝, 딥러닝의 목표는 룰을 찾아서 예측을 할수 있는 시스템을 만드는 것이 목표다.  
이 목표를 찾기 위해서는 학습을 시켜서 룰을 찾는데 데이터는 라벨링된 데이터를 사용한다.  
라벨링된 데이터를 사용하기 때문에 Supervised Learning이라고 한다.  
라벨링되지 않은 데이터를 사용하는 것을 Unsupervised learning이라고 한다.  

여기서는 주로 Supervised learning에 대해 살펴보게 될 것이다.  
예를 들어서 Supervised learning을 구현할 수 있는 종류가 뭐가 있는지 보자. 
얼만큼 시간을 공부했느냐에 따라 Pass, 점수(score)를 예측하고자 한다 (regression)  
얼만큼 시간을 공부했느냐에 따라 Pass, Non-Pass를 예측하고자 한다 (Binary classification)  
얼만큼 시간을 공부했느냐에 따라 등급 (A, B, C, ~ ,F)를 예측하고자 한다 (multi-label classification)  

linear regression을 어떻게 모델을 만들고 어떻게 학습을 시키는지..<file_sep>/docker/run_container.sh
#!/bin/sh
docker run -p 8888:8888 -it --volume="$PWD/../study:/workdir/study" deeplearning_keras:imx-1
<file_sep>/study/tensorflow/dl_for_everyone_season2/10_nn_relu_xavier_overfitting_dropout.md
# Relu

이진 분류 문제를 해결하기 위해 Sigmoid를 activation function로 사용했고

다중 분류 문제를 위해 Softmax를 사용했다.

그런데 이전의 모델과는 다르게 neural network를 사용할 경우, back proagation을 반복하면서 gradient값이 점점 작아지는 문제가 있다. 

relu에 대해 살펴보기 전에 먼저 Sigmoid의 문제점에 대해 먼저 살펴보자.



## Sigmoid의 문제점

Sigmoid의 경우 back propogation을 반복하면서 gradient 값이 점점 작아져 사라지는 문제가 있다. (vanishing gradient)

이를 해결하기 위한 activation function으로 relu라는 것이 있다.

아래 그림을 보면 시그모이드 그래프 중 빨간 부분에서 gradient값이 0에 가까워지고 있다

<img src="./img/sigmoid_vanishing_gradient.png" width="80%">



## Relu

x가 음수일 경우에는 f(x)는 0이 되고 0보다 클 경우에는 이전에 보았던 wx+b 와 같은 형태이고 문제가 되었던 sigmoid의 gradient가 작아지는 부분이 없는 것을 볼 수 있다.



<img src="./img/relu.png" width="80%">



## Weight

아래의 우측 그래프를 보면 local minima, global minima가 있다.

Neural network를 학습시키면서 back propagation을 반복하면서 local minima에 빠지지 않고 global minima를 찾을 수 있어야 하는데, 이를 위해 적절한 weight의 초기값을 설정하는 것이 중요하다.  
(아래의 w,c 그래프에서 적절한 시작점에서 경사하강법을 수행하면 올바른 global minimum을 찾을 수 있으므로)  
이렇게 weight를 초기화시키기 위한 방법 중의 xavier initialization라는 것이 있고 이를 통해 weight를 적절한 값으로 초기화시킬 수 있다.  
tensorflow에서는 weight를 initialize하기 위한 방법으로 RandomNormal(), glory_uniform(), he_uniform()함수를 제공해준다. 이후의 예제코드를 통해 확인해보자  
<img src="./img/xavier_initialization.png" width="100%">

## Overfitting, Drop out

보통 모델을 학습 및 평가할 때 data set을 train set, validation set, test set으로 나누어서 학습 및 평가를 한다.  
예측을 위해 모델을 학습시킬 때, train set에 과도하게 학습이 될 경우, train set에만 최적화된 예측모델이 되어서 새로운 데이터(test set)에서는 정확도가 낮아지게 된다.  
그래서 train set에서는 학습만 시키고 validation set을 통해 모델을 평가해보고 이를 토대로 다시 모델을 튜닝하고 완성된 모델을 test set에서 평가를 하게 된다..  
즉, train set에서 학습을 시키고 validation set을 통해 평가한 뒤, 모델을 다시 튜닝을 하는데 이때 dropout이라는 것을 사용한다.
그 후 test set에서 평가를 하는 방식으로 대부분 구현을 한다고 한다.  
아래 그림을 보면 첫번째 그림은 학습이 너무 적게 되어서 모델(직선? 그래프)이 데이터에 적게 fitting된 것을 볼 수 있다. 이를 under fitting이라고 한다.  
두번째 그림을 보면, 모델(직선)이 적절하게 학습되었지만 몇몇 개의 데이터들이 그래프의 경계를 벗어나 있는 것을 볼 수 있다. drop out이란 이런 몇몇 개의 데이터를 dropout시키기 위한 방법으로 보인다. tensorflow에서는 랜덤하게 dropout하는 방식을 사용한다.  
세번째 그림을 보면 모델이 데이터에 과도하게 학습된 것을 볼 수 있다. 이 경우, train data에서는 좋은 예측을 하지만, 새로운 데이터에서는 좋은 성능을 내지 못하는 문제가 있다.  
<img src="./img/overfitting_dropout.png" width="100%">

아래 그림을 보면 고양이 사진을 인식, 분류하기 위한 모델이 있고 overfitting 문제를 해결하기 위해 회색 부분으로 표시된 부분을 제거하게 된다.  
이렇게 dropout되고 난 후 regularization이 되었다고 한다.  
  
<img src="./img/cat_dropout1.png" width="100%">  
<img src="./img/cat_dropout2.png" width="100%">  



## Imlementation
 - dropout을 사용하기 전  
~~~ python
class create_model(tf.keras.Model):
  def __init__(self, label_dim):
    super(create_model, self).__init()
    
    weight_init = tf.keras.initializers.glorot_uniform()
    self.model = tf.keras.Sequential()
    
    self.model.add(flatten())# [N, 28, 28, 1] -> [N, 784]
    
    for i in range(2):
      # [N, 784] -> [N, 256] -> [N, 256]
      self.model.add(dense(256, weight_init))
      self.model.add(relu())
      
    self.model.add(dense(label_dim, weight_init))
    
	def call(self, x, training=None, mask=None):
    x = self.model(x)
    
    return x
~~~

 - dropout을 사용할 경우  
~~~python
class create_model(tf.keras.Model):
  def __init__(self, label_dim):
    super(create_model, self).__init__()
    
    weight_init = tf.keras.initializers.glorot_uniform()
    self.model = tf.keras.Sequential()
    
    self.model.add(flatten())# [N, 28, 28, 1] -> [N, 784]
    
    for i in range(2):
      # [N, 784] -> [N, 256] -> [N, 256]
      self.model.add(dense(256, weight_init))
      self.model.add(relu())
      self.model.add(dropout(rate=0.5))
      
    self.model.add(dense(label_dim, weight_init)) #[N, 256] -> [N, 10]
    
    def call(self, x, training=None, mask=None):
      x = self.model(x)
      
      return x
~~~

<file_sep>/study/tensorflow/dl_for_everyone/2_2_cost_function_and_gradiant_descent.md

~~~
이 포스트는 홍콩과기대 김성훈 교수님 강의내용을 개인적으로 이해한대로 정리한 내용입니다.  
개인적인 호기심으로? 스터디한 내용을 정리한 포스팅입니다.  
틀린 부분이 있을 수 있으니 감안하시길 .. 아래 사이트에 강의 내용이 있습니다.
~~~
[모두를 위한 딥러닝 강의](http://hunkim.github.io/ml/)  
[모두를 위한 딥러닝 깃허브](https://github.com/hunkim/DeepLearningZeroToAll)  


# 개요
앞에서 살펴본 비용함수라는 것은 가설이 실제 데이터와 얼마나 차이나는지 확인하는 방법이다.  
가설을 변화시켜가면서 비용함수의 값을 최소화 시키게 되면, 실제 데이터를 통해서 다음 데이터는 어떤 값을 갖게 될지 예측을 할 수 있다.  
최적의 비용함수를 찾기 위한 방법 중 하나가 기울기와 절편을 변화시켜 가면서 찾는 방법인데, 이를 경사하강법(gradiant descent)이라고 한다.  
그런데 텐서플로에서는 미분 등의 식을 통해 경사하강법을 직접 구현하지 않아도 텐서플로 패키지 내의 함수를 통해서 구현할 수 있다.  
텐서플로의 함수를 사용하지 않고 직접 구현하는 방법은 다음에 확인해보기로 하고 우선 텐서플로에서 제공해주는 경사하강법의 사용 예를 살펴보자..  


# 텐서플로 구현  

대부분의 구현 방법은 아래 그림과 같다. 1: graph(연산, node, 들을 선언및 초기화)를 build하고, 2. 실제 축적되어있는 data(통계치등)를 넣어서 실행을 시킨다. 3.실행의 결과의 값들을 update한다..  
<left><img src="image/tensorflow_mechanics.png" width="400" height="300"></left>


# W, b 값 부여(weight, bias) 및 가설  

Variable이라는 것은 프로그래밍 언어에서 사용하는 변수와는 조금 다른 텐서플로에서 사용하는 변수 비슷한 개념인데,  
tensorflow가 학습하면서 변경을 시킬 수 있는, 훈련시킬수 있는 Variable이라고 한다.  
그리고 random_normal함수는 random함수를 의미하고 아래 코드에서는 1차원의 random함수를 통해 w, b값을 선언했다  
hypothesis라는 node를 선언하고 wx+b로 node를 초기화했다  

~~~python
W = tf.Variable(tf.random_normal([1]), name='weight')  
b = tf.Variable(tf.random_normal([1]), name='bias')  

#Our hypothesis XW+b
hypothesis = x_train * W + b
~~~


# 비용함수

앞에서 봤던 것과 같이 비용함수는 (H(x)-y)^2 가된다. reduce_mean은 평균을 구하는 함수라고 한다.(i를 1~m까지 증가시킨 값을 1/m)  

~~~python
#cost/loss function
cost = tf.reduce_mean(tf.square(hypothesis - y_train))
~~~


# 최적의 비용함수 찾기

최적의 비용함수를 찾기 위한 방법 중의 하나가 경사하강법(gradiant descent)라는 것인데, tensorflow에서는 아래와 같이 경사하강법을 쉽게 사용할 수 있는 벙법을 제공해주고 있다.  

코드를 보면 경사하강법을 사용하는 optimizer를 선언하고 optimizer의 minimize함수를 호출하면서 cost(비용함수)를 최소화시키고 이를 train이라는 노드로 초기화 한다.  

~~~python
#Minimize
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)
~~~

노드라는 것은 앞에서 봤던 트리 형태의 동그란 부분, 즉 연산을 의미한다고 보면 될 것 같다.  
여기까지가 그래프를 building하는 과정이다.  
그리고 그래프를 동작시켜서 값을 찾는 과정은 다음과 같다.  

~~~python
sess.run(train)
~~~

전체 예제 코드는 다음과 같다..  
~~~python
#Lab 2 Linear Regression
import tensorflow as tf
tf.set_random_seed(777)  # for reproducibility  

#X and Y data  
x_train = [1, 2, 3]  
y_train = [1, 2, 3]
 
#Try to find values for W and b to compute y_data = x_data * W + b
#We know that W should be 1 and b should be 0
#But let TensorFlow figure it out
W = tf.Variable(tf.random_normal([1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name='bias')
 
#Our hypothesis XW+b
hypothesis = x_train * W + b
 
#cost/loss function
cost = tf.reduce_mean(tf.square(hypothesis - y_train))
 
#Minimize
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)
 
#Launch the graph in a session.
sess = tf.Session()
#Initializes global variables in the graph.
sess.run(tf.global_variables_initializer())
 
#Fit the line
for step in range(2001):
    sess.run(train)
    if step % 20 == 0:
        print(step, sess.run(cost), sess.run(W), sess.run(b))
 
#Learns best fit W:[ 1.],  b:[ 0.]
 
'''
0 2.82329 [ 2.12867713] [-0.85235667]
20 0.190351 [ 1.53392804] [-1.05059612]
40 0.151357 [ 1.45725465] [-1.02391243]
...
1920 1.77484e-05 [ 1.00489295] [-0.01112291]
1940 1.61197e-05 [ 1.00466311] [-0.01060018]
1960 1.46397e-05 [ 1.004444] [-0.01010205]
1980 1.32962e-05 [ 1.00423515] [-0.00962736]
2000 1.20761e-05 [ 1.00403607] [-0.00917497]
'''
~~~
<file_sep>/study/keras/5_deep_learning_for_computer_vision/5_deep_learning_for_computer_vision.md

# 5.1. Introduction to convnet
convnet(convolutional neural networks)의 전체 구조는 다음 그림과 같은 구조로 이루어져 있다  
고양이가 한 물체를 보았을 때 뇌의 한부분만 반응하는 것에 착안한 모델이라고 한다.
아직은 잘 모르지만, 그림을 보면 conv, relu는 한 쌍으로 구성되어 있는 것을 볼 수 있다.  
아래 그림은 "자동차"그림을 "자동차"로 인식하기 위한 CNN인데, Convolution으로는 각각 다른 자동차이미지들로 구성되어있는 것을 볼수 있다.
<left><img src="img/CNN.png" width="400" height="300"></left> 


### CONV, RELU, POOL에 관한 간단한 용어 및 개념 정리  
<left><img src="img/ConvReluFilter.png" width="400" height="300"></left>

CONV 는 한 이미지에서의 필터를 적용해서 얻은 데이터를 의미한다.
예를 들어 32x32x3(width, height, depth)의 이미지에서 stride를 옮겨가면서 filter를 적용한 값을 의미한다.
RELU라는 것은 함수와 비슷한 개념인데, Wx+b와 같은 식을 적용하는 함수와 같은 것으로 보인다.
실제 코드에서는 **activation='relu'** 와 같은 형태로  인자를 넘기고 있다.  
(참고할만한 내용)  
neural network의 layer는 보통 입력값을 가지고 있는데 이것을 vecotr라고 부르고 weight matrix를 곱한다..  
https://stackoverflow.com/questions/43504248/what-does-relu-stand-for-in-tf-nn-relu


POOL 은 sampling, resizing을 의미하고, 여러가지 방법이 있지만 max pooling이라는 방법을 주로 쓴다


#### 다시 책으로 돌아와서
convnet은 입력 텐서의 형태 (image_height, image_width, image_channels)(배치 차원을 포함하지 않음)를 취한다.
~~~python
from keras import layers
from keras import models

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
~~~  

~~~
>>> model.summary()
________________________________________________________________
Layer (type)                     Output Shape          Param #
================================================================
conv2d_1 (Conv2D)                (None, 26, 26, 32)    320
________________________________________________________________
maxpooling2d_1 (MaxPooling2D)    (None, 13, 13, 32)    0
________________________________________________________________
conv2d_2 (Conv2D)                (None, 11, 11, 64)    18496
________________________________________________________________
maxpooling2d_2 (MaxPooling2D)    (None, 5, 5, 64)      0
________________________________________________________________
conv2d_3 (Conv2D)                (None, 3, 3, 64)      36928
================================================================
Total params: 55,744
Trainable params: 55,744
Non-trainable params: 0
~~~

앞에서 본것과 같이 Conv와 pooling layer가 반복되고 있는 것을 볼 수 있다.
tensorflow에서는 필터의 크기를 사용자가 직접 계산하고 필터의 갯수도 직접 지정하는 것으로 보이는데
keras의 경우는 필터의 크기를 알아서 계산해 주는 것으로 보인다.  
이 코드에 대해 이해하기 위해서는 Conv2D와 MaxPooling2D레이어가 하는 일에 대해 알아 보는 것이 필요하다.(다음 절에서)  

이 단계가 끝나고 conv2d, maxpooling를 통해 최종적으로 나온 값은 연결 분류기 네트워크 ( Dense레이어 스택)에 공급한다.
텐서플로에서의 Fully Connected Layer와 같은 역할을 하는 것으로 보인다.

~~~python
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
~~~

이 단계를 거치고 나서는 모델을 훈련시키는 단계가 있다
이에 대한 코드는 5.4.절을 참고

##### 요약하면 세 단계를 통해서 이미지를 인식할 수 있다.
1. Convolution, max pooling 연산을 통해서 출력값의 생성
2. 1번의 출력값을 이용해서 네트워크에 공급(5.3.절 참고)
3. 이렇게 구성한 convnet을 훈련시키는 단계

### 5.1.1. 컨벌루션 연산
조밀하게 연결된 레이어와 컨볼 루션 레이어의 근본적인 차이점은 다음과 같습니다. Dense레이어는 입력 특징 공간에서 전체 패턴을 학습합니다 (예 : MNIST 숫자, 모든 픽셀을 포함하는 패턴).  
반면에 컨볼 루션 레이어는 **로컬 패턴**을 학습합니다 ( 그림 5.1 참조 ) : 이미지의 경우 입력의 작은 2D 창에서 발견되는 패턴. 이전 예에서이 창은 모두 **3 × 3**이었습니다.

###### 그림 5.1.
<left><img src="img/LocalPattern.jpg" width="100" height="100"></left> 

그들은 패턴의 공간 계급을 배울 수있다 ( 그림 5.2 참조 ). 첫 번째 컨볼 루션 계층은 가장자리와 같은 작은 로컬 패턴을 학습하고, 두 번째 컨볼루션 계층은 첫 번째 계층의 기능으로 만들어진 더 큰 패턴을 학습하는 등의 작업을 수행합니다. 이것은 convnets이 점점 더 복잡하고 추상적인 시각적 개념을 효율적으로 학습하도록 합니다 (시각적 세계는 근본적으로 공간적으로 계층적이기 때문에)

###### 그림 5.2.
<left><img src="img/ConvolutionLayer_CatExample.jpg" width="300" height="300"></left> 

**[이미지의 depth]**  
컨볼 루션 은 두 개의 공간 축 ( 높이 와 너비 )과 깊이 축 ( 채널 축 이라고도 함)이있는 피쳐 맵 이라는 3D 텐서를 통해 작동합니다 . RGB 이미지의 경우 깊이 축의 크기는 3입니다. 이미지에 빨강, 녹색 및 파랑의 세 가지 색상 채널이 있기 때문입니다. 흑백 사진의 경우 MNIST 숫자와 마찬가지로 깊이는 1 (회색 레벨)입니다.  

**[Conv2D() 함수]**  
~~~python
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
~~~  

~~지금까지 본 내용들은 위 코드 한줄을 위한 개념 설명이었다..ㅜㅜ~~ 이 코드의 의미는 다음과 같다.    
MNIST 예제에서 첫 번째 컨볼 루션 계층은 크기의 기능 맵을 가져 와서 크기 (28, 28, 1)의 기능 맵을 출력한다. 입력에 대해 32 개의 필터를 계산합니다.((26, 26, 32)가 된다) 즉, input_shape의 인자 값이 맵의 크기가 되고, 첫 인자인 32가 필터의 크기가 되는 것으로 보인다
 
입력에서 추출한 패치의 크기 - 일반적으로 3 × 3 또는 5 × 5이고, 이 예에서는 3 × 3이며 일반적인 선택이라고 한다.  
출력 피처의 깊이 맵 - 컨볼 루션에 의해 계산 된 필터의 수(크기)이며 이 예제는 깊이가 32에서 시작하여 깊이가 64로 끝난다.
이 깊이를 어떤 기준으로 설정하는지에 대해서는 5.3. 5.4.절에서 설명이 될것 같다. Keras Conv2D레이어에서 이러한 매개 변수는 레이어에 전달 된 첫 번째 인수 Conv2D(output_depth, (window_height, window_width))이다.  

***Convolution Layer의 동작과정을 그림으로 보면 다음과 같다.***
<left><img src="img/convnet_flow_diagram.jpg" width="300" height="300"></left>


컨볼 루션은 3 x 3 또는 5 x 5 크기의 창(필터, ~~여기서는 필터와 창을 혼용해서 사용하는 것 같다~~)을 3D 입력 맵 위로 슬라이딩하며 (모양 (window_height, window_width, input_depth)) 의 3D 패치를 추출하게 된다.  
필터는 stride(간격)값에 따라 이동하는 간격이 달라지며, 필터의 갯수도 이값에 의해 다음 입력의 width, height의 값이 증가 또는 감소를 하게 될 것이다.
(필터의 동작방법은 다음 그림을 참고)
***즉, 요약하면*** output depth는 전달인자로 결정할 수 있고 layer를 한번 거칠때마다 필터의 크기(width, height, depth)는 계속 감소하게 될 것이다.
이렇게 생성된 output모델은 width x height x output depth의 크기를 가지게 된다.


##### 필터(창)의 슬라이딩  
<left><img src="img/filter_window_sliding.jpg" width="300" height="300"></left>

##### stride
예제에서의 conv2D후의 2번째 layer의 크기를 계산해보면..  
stride(간격)은 1이고, 간격 1씩을 이동하면 (28-3)/1 + 1 = 26 크기의 창이 2번째 layer의 입력이 된다.
계산 방법은 (입력 width - 필터 width)/stride + 1 이다.


# 5.2. Training a convnet from scratch on a small datasheet

# 3. Using a pre-trained convnet

# 4. Visualizing what convnet learn
<file_sep>/docker/Dockerfile
FROM ubuntu:16.04

RUN sed -i s/archive.ubuntu.com/ftp.daumkakao.com/g /etc/apt/sources.list
RUN apt-get clean
RUN apt-get update 
RUN apt-get install -y make 
RUN apt-get install -y git unzip 
RUN apt-get install -y wget
RUN apt-get install -y build-essential

# install python3.6, BeutifulSoup4 package
# for use "add-apt-repository command"
RUN apt-get install -y software-properties-common
RUN add-apt-repository ppa:jonathonf/python-3.6
# RUN add-apt-repository ppa:deadsnakes/ppa
RUN apt-get update
# RUN apt-get install -y python3.6
RUN apt-get install -y python3.6-dev
RUN apt-get install -y python3-pip
RUN pip3 install --upgrade pip
RUN pip3 install requests
RUN apt-get install -y python3-bs4

# Install BLAS Library to boost Tensor-Operation
RUN apt-get install -y build-essential \
cmake git unzip pkg-config libopenblas-dev liblapack-dev

# Install HDF5(대용량 수치 데이터파일을 효율적인 이진포맷으로 저장해준다.)
RUN apt-get install -y libhdf5-serial-dev python-h5py

# for jupyter, tensorflow, keras package
# RUN pip3 install tensorflow scikit-learn jupyter matplotlib pandas keras seaborn plotly
RUN pip3 install tensorflow scikit-learn jupyter matplotlib pandas keras seaborn

# # Install numpy, scipy, matplotlib
RUN pip3 install numpy scipy pyyaml

RUN pip3 uninstall -y tornado
RUN pip3 install tornado==5.1.1
# RUN pip3 install tornado

RUN pip3 uninstall -y pillow
RUN pip3 install pillow

# Set environment variables
# UBUNTU korean locale
RUN apt-get install -y locales
ENV LANGUAGE=ko_KR.UTF-8 
ENV LANG=ko_KR.UTF-8
RUN locale-gen ko_KR.UTF-8
ENV LC_ALL ko_KR.UTF-8

# make shared directory with HOST and set working directory
WORKDIR /workdir

# Set up our notebook config.
COPY jupyter_notebook_config.py /root/.jupyter/
COPY run_jupyter.sh /workdir
EXPOSE 8888
CMD ["/bin/bash"]
<file_sep>/study/tensorflow/dl_for_everyone/3_1_multi_variable_linear_regression.md

~~~
이 포스트는 홍콩과기대 김성훈 교수님 강의내용을 개인적으로 이해한대로 정리한 내용입니다.  
개인적인 호기심으로? 스터디한 내용을 정리한 포스팅입니다.  
틀린 부분이 있을 수 있으니 감안하시길 .. 아래 사이트에 강의 내용이 있습니다.
~~~
[모두를 위한 딥러닝 강의](http://hunkim.github.io/ml/)  
[모두를 위한 딥러닝 깃허브](https://github.com/hunkim/DeepLearningZeroToAll)  

# remind.. 

H(x)란(가설).. 
어떻게 예측할 것인지를 의미.. 
(경사하강법을 통해서 cost function(비용함수)를 최소화하는 최적의 H(x)를 찾고, 이 H(x)를 통해서 다음에는 어떤 값을 가질 것인지를 예측할 수 있다.)  

cost function(비용함수)이란..  
실제 통계 등의 데이터와 H(x)값이 얼마나 차이나는지를 의미
  
gradiant descent algorithm(경사하강법)이란..  
x축이 w이고 y축이 cost function인 그래프를 생각해보자.  
결국 w값을 조정해가면서 cost function의 최소값을 찾는 방법이다.  
이렇게 찾는 방법이 기울기(w)를 하강시켜가면서 0이 되는 지점을 찾는 것이기 때문에 경사하강법이라 부르는 듯..  
경사하강법을 사용하기 위한 전제?가 있는데.. cost function이 convection function(아래로 볼록한 함수)의 형태이어야한다는 것..  
<left><img src="image/3/3_linear_regression_remind.png" width="400" height="300"></left>


# 입력이 여러개일 경우는..
아래 그림 처럼 입력데이터 셋이 여러개(quiz1, quiz2, midterm) 일 경우에는 어떻게 Cost function을 계산할 것이며, cost function을 최소가 H(x)는 어떻게 찾을 것인가..
<left><img src="image/3/3_multi_variable_linear_regression_example.png" width="400" height="300"></left>
  
  
우선 H(x)는 아래와 같은 형태일 것이다.
<left><img src="image/3/3_multi_variable_Hypothesis.png" width="400" height="300"></left>

cost function은 아래와 같은 형태일 것이다.
<left><img src="image/3/3_multi_variable_cost_function.png" width="400" height="300"></left>
  
그런데, 행렬을 사용하면 H(x)를 입력값의 추가 및 수정이 편한 형태로 바꿀 수 있다.  
<left><img src="image/3/3_hypothesis_using_matrix.png" width="400" height="300"></left>

이제 w값을 변경해가며 cost function이 최소가 되는 값을 찾으면 된다.
이는 경사하강법을 사용해서 찾으면 된다..

<file_sep>/README.md
# Docker build  
 - cd docker  
 - docker build -t deeplearning_keras:imx-1 .
  
# Run Docker container 
  - docker run -p 8888:8888 -it --volume="$PWD/..:/workdir/deeplearning_keras_study" -v ${PWD}/build:/workdir/build deeplearning_keras:imx-1
  - or ./run_container.sh

# Docker 컨테이너, 이미지 삭제
 - Docker 컨테이너 모두 삭제
 docker rm $(docker ps -a -q)
 - Docker 이미지 모두 삭제
 docker rmi $(docker images -q)
 - 특정 이미지만 삭제
 (image 리스트 확인)
 docker images
 docker rmi 이미지id

# execute jupyter notebook in Docker Container
  - /workdir/run_jupyter.sh --allow-root &

# 특이점
  - ubuntu에서 docker build시에 plotly 패키지를 설치하면서 error가 발생해서 repository를 통해서 설치하도록 수정했다.<file_sep>/study/tensorflow/dl_for_everyone_season2/12_recurrent_neural_network.md
# Recurrent Neural Network
RNN(Recurrent Neural Network)는 연속적인 데이터를 예측하기 위한 모델이다.  
또, RNN에는 몇가지 단점이 있어서 이를 보완하기 위한 모델로 LSTM과 GRU와 같은 모델이 있다.  
LSTM과 GRU에 대해서는 다음 장에서 살펴보기로 하고 RNN을 집중적으로 살펴보자.
여기서는 단어를 예로 들어서 RNN의 동작 원리에 대해 심플하게 설명하고 있다.  
  
# dataset
deeplearning은 이미 가지고 있는 데이터를 학습해서 실제 데이터에서 다음 값을 예측하거나 분류를 하는 것이 목표이다.  
학습을 위해서 사용하는 데이터는 데이터에 대한 라벨(정답)이 있는 데이터셋을 사용한다.  
여기서는 주로 단어예측과 관련된 내용을 설명하는데, 단어에 대한 라벨링(이진 값으로 변환)을 '원 핫 인코딩'을 하여 만든다.  
원핫인코딩을 하는 방법도 두가지로 나눌 수 있다. 단어 단위로 하거나 문자 단위로 하는 것이다.  
또, 원핫인코딩 대신 단어임베딩이라는 것도 많이 사용되는데, 단어임베딩은 메모리를 더 적게 쓰면서 더 빨리 값을 가져올 수 있다는 장점이 있다.  
각 단어에 대한 값이 이진으로 코딩되어 있는 대신, 해시알고리즘을 사용해서 값을 더 빨리 찾을 수 있기 때문이다.  
이런 방법에 대해서는 다음 챕터에서 더 자세히 살펴보고 여기서는 원핫인코딩을 사용해서 문자 중심의 예측을 위한 rnn을 더 집중적으로 살펴보자.  

# RNN이란..
아래 그림에서 볼 수 있듯이 현재의 입력에 대한 출력이 다음 입력으로 사용되는 것을 볼 수 있다.  
오른쪽의 그림을 보자.  
X입력을 받고 이 데이터에 대한 상태인 h가 다음 모델의 입력으로 입력되는 구조를 보여주고 있다.  
<img src="./img/rnn1.png" width="80%">  

## h에 대해 살펴보면..    
입력을 받을 때마다 상태에 해당하는 h가 갱신되는데, 이를 수식으로 살펴보면 아래 그림과 같다.  
h는 새롭게 갱신될 new state를 의미한다.  
fw라는 함수에 이전 h(state)와 현재 입력값이 입력되어서 현재의 h가 갱신되고 있다.  
fw란 weight값을 가진 어떤 함수를 의미하는데, 이 함수는 다음 그림에서 더 자세히 살펴보자.  
<img src="./img/rnn2.png" width="80%">  

## fw함수가 뭔지 더 자세히 보면..  
아래 수식을 보면 fw함수는 이전의 h(state)에 weight를 곱한 값과 x에 weight를 곱한 값을 activation함수(tanh함수)에 넣는 것을 볼 수 있다.  
tanh함수는 activation함수로 -1에서 1사이의 값을 가지고 기존의 sigmoid에 비해 vanishing gradient문제가 해결된 함수다.  
결국, 이 fw함수로 현재의 h함수를 업데이트되는 것이다.  
<img src="./img/rnn_fw.png" width="80%">  

## hidden layer
h는 상태를 의미하지만 rnn모델에서 hidden layer를 의미하기도 하는데,  
아래 그림들을 보면 매 step마다 입력에 대해 h(hidden layer)가 업데이트되는 것을 볼 수 있다.  
<img src="./img/rnn_hidden_layer0.png" width="50%">  
<img src="./img/rnn_hidden_layer1.png" width="50%">
<img src="./img/rnn_hidden_layer2.png" width="50%">
<img src="./img/rnn_hidden_layer3.png" width="50%">
<img src="./img/rnn_hidden_layer4.png" width="50%">  
  
## output layer
output layer에서는 hidden layer를 통해 나온 현재의 h값(state)에 weight값을 곱해서 outlayer의 값이 출력되게 된다.  
이 슬라이드 상에는 나오지 않았지만, 각 단어의 확률값을 출력하기 위해서 softmax를 activation function으로 사용한 것으로 보인다.  
<img src="./img/rnn_hidden_output_layer.png" width="80%">  

## rnn 모델의 종류
<img src="./img/rnn_models1.png" width="50%">  
<img src="./img/rnn_models2.png" width="50%">  
<img src="./img/rnn_models3.png" width="50%">  
<img src="./img/rnn_models4.png" width="50%">  
<img src="./img/rnn_models5.png" width="50%">  
  
## advanced rnn models
<img src="./img/rnn_advanced_models.png" width="50%">  
<file_sep>/study/tensorflow/dl_for_everyone_season2/11_convolution_neural_network.md
# Convolutional Neural Network

[참고]  
https://hunkim.github.io/ml/lec11.pdf  
https://drive.google.com/drive/folders/1twBsdLkI2P15J0DgYs77_E_EVKt7Ghav  

image 분류에 가장 많이 사용되는 분류 방법인데, 뇌가 이미지를 인식하는 방법에서 힌트를 얻었다고 한다.  
아래 그림을 보면, 그림의 한 부분에 대해 인식하는 뇌의 부분이 모두 다른 것을 보여주고 있는데, Convolution neural network도 이와 비슷한 원리로 구현된다.  
<img src="./img/cnn_concept_from_brain.jpg" width="50%">

CNN은 기본적으로 Convolution, Pooling, Fully Connected layer로 구성되어 있다.
<img src="./img/cnn_overview.jpg" width="50%">  


  
아래 그림의 Convolution, Pooling layer는 특정한 특징을 추출하는 layer이고.(feature extraction)  

Fully connected layer는 분류를 하는 layer이다. (사진이 강아지인지 고양이인지, classification)  
<img src="./img/convolution_neural_network.jpg"/>  


## Convolution layer
--------

- convolution연산과 filter의 갯수
  filter로 한번의 convolution 연산을 하면 통과하면 하나의 숫자가 나온다.  
  filter를 stride간격으로 input map전체를 순회하고 나면 out map이 나오게 된다.  
  filter의 갯수에 따라 out map의 갯수가 결정되게 되고, 이는 다음 layer의 input map의 갯수가 된다.  
  그림으로 살펴보자.  
  
<img src="./img/filter.jpg" width="50%">  

stride가 1이라고 가정했을 때, filter의 갯수에 따라 출력맵의 갯수가 결정되는 것을 볼 수 있다.(필터의 갯수와 출력맵의 갯수는 동일)  
<img src="./img/convolution_layer_one_filter.jpg" width=200>
<img src="./img/convolution_layer_two_filter.jpg" width=270>
<img src="./img/convolution_layer_six_filter.jpg" width=350>

<img src="./img/convolution_layer_filters.jpg" width=500>  

- convolution연산 (filter computing)
convolution 연산의 계산은 아래와 같이 이미지의 픽셀 값과 필터의 각 원소들의 합으로 계산된다.
<img src="./img/filter_computing.jpg" float:left/>

- convolution연산과 stride, padding
stride란 filter가 움직이는 간격의 크기를 의미한다.  
stride 값과 filter, input map의 크기에 따라 생성되는 출력 맵의 크기가 달라지게 되는데,  
출력되는 맵의 크기는 (width - filter width)/stride + 1이다.  
filter를 거치면서 out map의 크기가 점점 작아지게 되는데, 이로 인해 data의 손실이 일어날 수 있다.  
이를 방지하기 위해 padding을 사용하는데, 아래 그림처럼 filter의 크기에 따라 padding을 달리하면 outmap의 크기가  
input map의 크기와 같아지는 것을 볼 수 있다.  
<img src="./img/padding_stride.png" width=500/>  

## Activation
각 Conv layer를 거친뒤 다음 입력으로 입력되기 전에 Activation function을 거치는데 이 때, Relu를 사용한다.  
아래 그림처럼 Relu activation function으로 인해 음수 값들은 0이되고 양수 값들은 그대로 유지된다.  
<img src="./img/layer_activation.jpg" width=500/>  


## Pooling Layer
-----
Convolution layuer에서는 filter를 stride간격으로 convolution연산을 해서 output맵을 만들어낸다.  
아래의 그림을 보면 convolution연산을 거치면서 점점 이미지가 옅어지는 것을 볼 수 있다.  
Convolution 연산을 거치고 나온 맵에서 특징을 추출을 해야 하는데, 이때 사용하는 것이 pooling이라는 것이다.  
<img src="./img/cnn_overview.jpg" width="50%">  
pooling연산은 '값들을 모은다', 'sampling한다', 'resize한다' 와 유사한 의미로 볼 수 있다.  
pooling연산을 하는 방법으로 두가지가 있는데, 맵의 평균값을 구해서 이 맵의 전체적인 특징을 뽑아내는 것과(average pooling)  
맵의 가장 큰 특징을 뽑아내기 위한 방법(max pooling)이 있다.  
<img src="./img/max_pooling1.jpg" width=200>
<img src="./img/max_pooling2.jpg" width=270>  
  
max pooling의 실제 연산은 아래 그림처럼 filter가 stride간격으로 이동하면서 최대값을 구해서 out map을 구성한다.  
아래 그림에서는 2x2 filter를 2칸 간격으로 이동하면서 filter와 겹치는 영역에서의 최대값을 뽑아서 out map을 구성하고 있다.  
<img src="./img/max_pooling_operation.jpg" width=350>  


## Fully Connected Layer
-----
Fully Connected layer에서는 Conv와 Max layer들을 통해서 나온 out map을 1차원으로 쭉 펼친다.  
그리고 Softmax activation function을 통해 분류(classification)를 하게 된다.  
아래 그림을 보면 FC Layer를 통해서 cat/dog로 분류되는 것을 볼 수 있다.  
<img src="./img/fully_connected_layer.jpg" width="50%">

## 그 외의 참고사항
 - 아래 링크에서 이미지의 특징들이 어떻게 출력되는지 과정을 살펴볼 수 있다.  
    http://cs.stanford.edu/people/karpathy/convnetjs/demo/cifar10.html<file_sep>/study/tensorflow/dl_for_everyone/2_1_Linear Regression Concept.md

# Linear Regression의 개념

아래와 같은 data가 있다고 해보자.  
<left><img src="image/regression_data.png" width="400" height="300"></left>

그럼 이 data에 대한 가설(H(x))은 다음과 같을 것이다.  
<left><img src="image/hypothesis.png" width="400" height="300"></left>

이 데이터에 대한 그래프와 식은 다음과 같을 것이다.  
그리고 다른 데이터들에 대한 식은 노란색과 빨간색 선들이라고 해보자.  
<left><img src="image/regression_data_equation.png" width="400" height="300"></left>

이 때 어떤 식이 더 좋은지에 대해 판단할 수 있어야 한다..  
이때 사용하는 것이 비용함수라는 것이다.  
<left><img src="image/regression_data_which hypothesis is better.png" width="400" height="300"></left>

비용함수라는 것은 가설과 실제 데이터의 차가 얼마나 되는지를 의미하는 것이다.  
<left><img src="image/cost_function.png" width="400" height="300"></left>

이 그래프의 전체 비용함수를 구하면 다음과 같을 것이다.  
<left><img src="image/cost_function_sum.png" width="400" height="300"></left>

결국, 주어지는 data(앞에서의 표)들에 대한 좋은 가설을 얻기 위해서는 기울기와 절편을 움직이면서 비용함수에 대한 값이 적게 나오는 가설을 선택하면 될 것이다..  
<left><img src="image/regressin_goal.png" width="400" height="300"></left>
<file_sep>/study/tensorflow/dl_for_everyone_season2/04_multi_variable_linear_regression.md
# multi variable linear regression
전의 예에서는 변수가 하나뿐이었다 (공부한 시간)  
이번에는 변수가 여러개라고 생각 해보자 (quiz1, quiz2, midterm)  
행렬을 사용하면 표현식이 간단해진다. 프로그램 상에서 xw로 표현이 가능하다.  
x의 컬럼과 w의 열의 수가 같아야 하기 때문에 XW로 표현을 한다.(텐서플로에서도 xw로 표현함)  
입력은 (데이터의 갯수,데이터 안의 변수 갯수)  
  
## 간단한 형태의 w1, w2, w3을 계산하는 코드  
~~~python
# data and label
x1 = [ 73.,  93.,  89.,  96.,  73.]
x2 = [ 80.,  88.,  91.,  98.,  66.]
x3 = [ 75.,  93.,  90., 100.,  70.]
Y  = [152., 185., 180., 196., 142.]

# random weights
w1 = tf.Variable(tf.random_normal([1]))
w2 = tf.Variable(tf.random_normal([1]))
w3 = tf.Variable(tf.random_normal([1]))
b  = tf.Variable(tf.random_normal([1]))

learning_rate = 0.000001

for i in range(1000+1):
    # tf.GradientTape() to record the gradient of the cost function
    with tf.GradientTape() as tape:
        hypothesis = w1 * x1 +  w2 * x2 + w3 * x3 + b
        cost = tf.reduce_mean(tf.square(hypothesis - Y))
    # calculates the gradients of the cost
    w1_grad, w2_grad, w3_grad, b_grad = tape.gradient(cost, [w1, w2, w3, b])
    
    # update w1,w2,w3 and b
    w1.assign_sub(learning_rate * w1_grad)
    w2.assign_sub(learning_rate * w2_grad)
    w3.assign_sub(learning_rate * w3_grad)
    b.assign_sub(learning_rate * b_grad)

    if i % 50 == 0:
      print("{:5} | {:12.4f}".format(i, cost.numpy()))
~~~  
  
## 위에서 본 각각의 w1, w2, w3을 계산하는 코드의 문제점
각각의 w1, w2, w3을 계산하는 코드는 x1,x2,x3,y의 값을 직접 입력해야 하는 번거로움이 있다.  
또, 코드의 크기가 커지고, 데이터의 크기도 커지면서 유지보수의 어려움이 생기는 문제가 있다.  
~~~python
for i in range(1000+1):
	with tf.GradientTape() as tape:
		hypothesis = w1 * x1 + w2 * x2 + w3 * x3 + b
		#COST함수를 구한다.
		cost = tf.reduce_mean(tf.square(hypothesis - Y))
	
	# tape에 기록된 하나의 값을 꺼내서 cost함수에 대한 W1,W2,W3,B의 각각 개별의 미분값을 가져온다.
	w1_grad, w2_grad, w3_grad, b_grad = tape.gradient(cost, [w1, w2, w3, b])
	
	# W1값을 업데이트한다.
	w1.assign_sub(learning_rate * w1_grad)
	w2.assign_sub(learning_rate * w2_grad)
	w3.assign_sub(learning_rate * w3_grad)
	
	if i % 50 == 0:
		print("{:5} | {:12.4f}".format(i, cost.numpy()))
~~~  
  
## 행렬(numpy)를 이용해서 x1,x2,x3,y 값을 정의
numpy slicing  
~~~python
data = np.array([
	#X1, X2, X3, y
	[73., 80., 75., 152.],
	[93., 88., 93., 185.],
	[89., 91., 90., 180.],
	[96., 98., 100., 196.],
	[73., 66., 70., 142.]
], dtype=np.float32)


# slice data
X = data[:, : -1]
y = data[:, [-1]]
~~~

## numpy를 사용하면 아래처럼 더 깔끔하게 코드를 구현이 가능하다  
~~~python
data = np.array([
    # X1,   X2,    X3,   y
    [ 73.,  80.,  75., 152. ],
    [ 93.,  88.,  93., 185. ],
    [ 89.,  91.,  90., 180. ],
    [ 96.,  98., 100., 196. ],
    [ 73.,  66.,  70., 142. ]
], dtype=np.float32)

# slice data
X = data[:, :-1]
y = data[:, [-1]]

W = tf.Variable(tf.random_normal([3, 1]))
b = tf.Variable(tf.random_normal([1]))

learning_rate = 0.000001

# hypothesis, prediction function
def predict(X):
    return tf.matmul(X, W) + b

print("epoch | cost")

n_epochs = 2000
for i in range(n_epochs+1):
    # tf.GradientTape() to record the gradient of the cost function
    with tf.GradientTape() as tape:
        cost = tf.reduce_mean((tf.square(predict(X) - y)))

    # calculates the gradients of the loss
    W_grad, b_grad = tape.gradient(cost, [W, b])

    # updates parameters (W and b)
    W.assign_sub(learning_rate * W_grad)
    b.assign_sub(learning_rate * b_grad)
    
    if i % 100 == 0:
        print("{:5} | {:10.4f}".format(i, cost.numpy()))
~~~
<file_sep>/study/tensorflow/dl_for_everyone/README.md
# 홍콩 과기대 김성훈 교수님이 강의하신 내용을 개인적으로 공부하면서 정리한 내용입니다.
# 아래 링크를 참조
https://hunkim.github.io/ml
<file_sep>/study/tensorflow/dl_for_everyone/1_machine_learning_basic.md

# 1. 머신러닝의 개념과 용어

AI(Artificial Intelligence), 프로그램..
프로그램이란 input에 대한 out을 출력하는 것이 프로그램이다..
AI는 정해진 input에 대한 out을 예측할 수 있어야 한다.
input에 대한 out을 예측할 수 있도록, 수 많은 데이터를 학습해서 예측할 수 있도록 해주는 것이 머신러닝이다.
프로그램인데, 이것을 개발자가 어떻게 할지를 정하는 것이 아니라, 프로그램이 데이터를 통해 학습해서
스스로 배우는 영역을 머신러닝이라고 한다.
그리고 이런 머신러닝의 여러 방법 중 하나가 신경망 이론을 이용한 딥러닝이라는 것이다.
<left><img src="image/machine_learning_deep_learning.png" width="400" height="300"></left>

# 텐서플로 기본 용어
https://www.tensorflow.org/guide/graphs
https://docs.google.com/presentation/d/137IlT2N3AYcclqxNuc8j9RDrIeHiYkSZ5JPg_vg9Jqk/edit#slide=id.g1d115b0ec5_0_32

노드는 수학적인 연산을 의미하며 아래 그림의 동그란 것들이 노드에 해당한다.
엣지는 간선을 의미하는데 데이터 어레이를 의미한다.. 쉽게 말해 데이터 셋을 의미하는 듯하다.

<left><img src="image/tensors_flowing.gif"></left>



# node, session이란..
node는 앞에서의 설명과 같이 operation을 의미한다... 특정한 상수가 될수 도 있는 것으로 보인다.
특정한 상수 대신 실행 중에 입력을 받고 싶으면 placeholder라는 것을 사용한다고 한다.  
session 이란 위에서 노드들을 감싸고 있는 네모 박스들과 같은 역할을 의미하는 것으로 보인다.
실행 중에도 데이터를 입력받아서 어떤 값일지 예측할 수 있도록 해주는 노드와 간선들로 이루어진 모델인 듯 하다.
<left><img src="image/tensorflow_mechanics.png" width="400" height="300"></left>


~~~python
# node(operation)
hello = tf.constant("hello tensorflow")
# start session
sess = tf.Session()
# run op and get result
print(sess.run(hello))
~~~


아래 예제에서는 node1, node2, node3모두 node이다.
node1, node2는 상수 노드이고, node3은 더하는 연산의 노드가 된다.

~~~python
node1 = tf.constant(3.0, tf.float32)
node2 = tf.constant(4.0, tf.float32)
node3 = tf.add(node1, node2)
~~~

# place holder
adder_node에 session을 run시킬 때 feed_dict로 a와 b의 값을 넣어주고 있다..
여기에 들어가는 값들은 엑셀파일에 정의되어있는 수치일 수도 있고 특정 기간 동안 센서 등을 통해 수집된 데이터일 수도 있을 것이다.
어쨌든 중요한 것은 실행 중에 입력값을 넣어 줄 수 있다는 것인듯..
(feed_dict, 이름 잘지은 듯 하다. 먹이로 주는 데이터?)
~~~python
a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
adder_node = a+b

print(sess.run(adder_node, feed_dict = {a:3, b: 4.5}))
print(sess.run(adder_node, feed_dict = {a: [1,3], b: [2,4]}))
#7.5
#[3. 7.]
~~~

<left><img src="image/tensorflow_mechanics2.png" width="400" height="300"></left>

<file_sep>/study/tensorflow/dl_for_everyone_season2/06_softmax_classifier_cross_entropy.md
# Softmax function
Softmax function은 다중 분류를 하기 위한 함수로 H(x)를 확률 값으로 표현해준다.  
아래 그림에서 볼 수 있듯이 각각의 입력을 확률로 바꿔주고 있다.  
<img src="./img/softmax_function.png" width="80%">  
  
## Cost function  
Softmax의 Costfunction으로는 cross entropy를 사용한다.  

<img src="./img/softmax_cost_function.png" width="80%">



## Implementation

### cost function: cross entropy

<img src="./img/softmax_cross_entropy_with_logits.png" width="80%">

### H(x), cost function

<img src="./img/softmax_hypothesis_cost_function.png" width="80%">



### gradient function, accuracy

<img src="./img/gradient_function_accuracy.png" width="80%">

## Training !!!!

<img src="./img/softmax_training.png" width="80%">





<file_sep>/study/tensorflow/dl_for_everyone_season2/05_logistic_regression.md
# Logistic regression

## Logistic Regression이란?(logistic vs linear)

logistic regression은 선형적인 값에 대한 예측을 하기위한 모델인 Linear Regression과 달리  
분류(classification)을 하기 위한 것이다.

- Linear regression  
  아래 그림의 우측을 보면 linear regression의 경우 곡선, 직선을 따라서 데이터들이 표현되어 있다.  
  이 곡선,직선의 방정식?그래프를 모델이 학습하게 된다. 학습을 하는 원리에 대해서는 이전 챕터 1,2 참조하면 됨.(cost, w, b, learning rate)  
- Logistic regression  
  이름처럼 선형적인 것이 아니라 논리적인 것이다. 아래 좌측의 그림처럼 네모와 세모를 분류하기 위한 모델이다.  
  네모와 세모 중간에는 곡선이 하나 있는데 이 곡선을 기준으로 네모인지 세모인지 판단할 수 있게 된다.  
  마찬가지로 이 곡선도 학습할 수 있는데, 어떻게 학습하는지에 대해 살펴보자.  
- 분류의 문제의 경우 여기서는 이진분류(binary classification)만을 다루지만 다음챕터에서 multinomial classification을 통해 T/F만이 아닌 다양한 라벨로 분류하는 방법을 살펴보게 될 것이다.  
  
<img src="./img/logistic_vs_linear.png" width="80%">  
  
## Hypothesis  
### 두 가지 경우로 나눌 수 있다.  
  점들을 그룹들로 나누는 모델, 그래프에서 값이 일정 수치 이상일 경우 True/False(Pass/Fail)을 예측할 수 있는 모델로 나눌 수 있다.  
----
- 점들을 그룹으로 나누는 모델  
  위의 그림처럼 네모와 세모를 경계짓는 곡선들의 경우 Binary Regression을 통해 True/False 를 판단할 수 있다.  
  이 경우, 두 그룹 간의 직선(또는 곡선)이 Hypothesis가 되는데,  
  이는 이전 챕터에서 배웠던 것과 같이 가설(Hypothesis)과 실제 데이터(y) 간의 거리를 구하는 cost 함수를 사용해서 cost를 최소화되는 곡선을 찾고, 이 결과로 분류가 가능하다.  
  <img src="./img/hypothesis_representation1.png" width="80%">
  <img src="./img/logistic_regression_cost_function.png" width="80%">

- 일정 수치 이상일 경우 True/False를 판단하는 모델  
  예를 들어 y = x+b의 직선이 있고 이 직선은 공부시간(x)에 대한 시험성적(y)에 대한 직선이라고 해보자.  
  시험 성적이 50이하일 경우, Fail, 50이상일 경우 Pass라고 하면, pass, fail을 표현하는 그래프는 아래와 같이 계단 모양이 될 것이다.  아래 그래프는 가설을 Sigmoid함수의 입력으로 주면 아래와 같은 그래프 형태가 된다.  

  <img src="./img/hypothesis_representation2.png" width="80%">
  <img src="./img/logistic_regression_cost_function2.png" width="80%">
  
시험성적 뿐 아니라, 혈당 수치에 대한 당뇨 확률? 이건 너무 당연한 비유겠지만.. 또는 한달 평균 운동 시간에 대한 비만 확률? 같은 경우에도 사용할 수 있지 않을까..  

## sigmoid function  
슬라이드로 살펴보자..  
<img src="./img/sigmoid_function.png" width="80%">  

## Softmax classification  
Activation function으로 Sigmoid 대신 Softmax를 사용하면 0또는 1로 분류하는 이진분류가 아닌 다수의 라벨로 분류할 수 있다.  
softmax는 입력을 확률값으로 표현해주는 함수로 이에 대한 자세한 내용은 다음장(6_softmax_classifier.md)에서 보자
<img src="./img/logistic_regression_softmax.png" width="80%">
<file_sep>/study/tensorflow/dl_for_everyone_season2/02_linear_regression.md
# [Tensorflow] Lec-02 ~ 03 Linear Regression
 - Regression
 - Linear Regression
 - Hypothesis
 - Which hypothesis is better?
 - Cost, Cost function
 - Goal: Minimize cost

## Regression
회귀, 모든 데이터들은 평균으로 회귀하려는 속성을 갖는다. 통계학쪽에서 유명한 말인듯하다..뭔소리야..

## 선형회귀
데이터를 가장 잘 대변하는 직선의 방정식을 찾는 것

## Hypothesis
데이터를 표현하는 직선 방정식
H(x) = Wx+b

## Whichi Hypothes is better
실제 데이터와 가설과의 차이, cost를 최소화된 가설..
코스트의 합이 최소인 직선을 찾는다.

## cost, cost function
가설에서 실제데이터를 뺀 값을 에러라고 하고
cost function은 에러의 제곱을 평균값을 cost function이라고 한다.  
<img src="./img/Hypothesis_Cost_function.png" width="50%">  

## Goal: Minimize cost



# Simple Linear Regression 개념

## Build hypothesis and cost
 - H(x) = Wx + b  
 - 예제 코드 상에서 간단한 형태의 코드를 보기 위해 W, b의 값은 초기 값으로 임의의 값을 지정한다.  
 - 실제로는 보통 random값을 부여한다.  
 - reduce_mean(): 평균값 구하는 함수, 차원이 하나 줄어들면서 mean을 구한다는 의미로 reduce가 앞에 붙어있다.  
~~~python
v = [1., 2., 3., 4.]
tf.reduce_mean(v) #2.5
~~~  
  
 - 비용함수  
~~~python
cost = tf.reduce_mean(tf.square(hypothesis - y_data))
~~~  
-----
## Gradient descent
 - 경사를 내려가면서 cost가 최소가 되는 W, b를 찾는 알고리즘.  
-----
### W, b 값 구하기
 - tf.GradientTape  
    (아래 코드 참고)
    with 구문안의 블록안의 변수들의 정보를 tape에 기록하고  
    tape에 기록된 변수들의 정보(w,b)를 이후에 tape.gradient()함수를 통해 경사도를 구한다.  
    tape.gradient()함수는 cost함수에 대해 변수들(w,b)에 대한 개별 미분값(기울기)을 구해서 tuple을 반환한다.  
    learning rate값은 W_grad, b_grad 값을 얼만큼 반영할 것인지를 결정한다.  
    아래의 코드가 한 걸음이라고 보면 됨, W와 b가 한번 업데이트 된 것이다.  
~~~python
with tf.GradientTape() as tape:
    hypothesis = W * x_data + b
    cost = tf.reduce_mean(tf.square(hypothesis - y_data))

W_grad, b_grad = tape.gradient(cost, [W, b])

# W, b 값 업데이트: W -= learning_rate * W_grad
W.assign_sub(learning_rate * W_grad)
b.assign_sub(learning_rate * b_grad)
~~~

# [Tensorflow] Lab-02 Simple Linear Regression
 구현 예를 보자.  
 위에서 살펴본 개념들에 대한 내용이 중복되지만 중요한 개념이니 한번 더 반복해서 보자.
-----
## Build hypothesis and cost
 - H(x) = Wx + b  
 - 예제 코드 상에서는 간단한 형태의 코드를 보기 위해 W, b의 값은 초기 값으로 임의의 값을 지정한다.  
 - 실제로는 보통 random값을 부여한다.  
 - reduce_mean(): 평균값 구하는 함수, 차원이 하나 줄어들면서 mean을 구한다는 의미로 reduce가 앞에 붙어있다.  
~~~python
v = [1., 2., 3., 4.]
tf.reduce_mean(v) #2.5
~~~
  
 - 비용함수  
~~~python
cost = tf.reduce_mean(tf.square(hypothesis - y_data))
~~~  
-----
## Gradient descent  
 - 경사를 내려가면서 cost가 최소가 되는 W, b를 찾는 알고리즘.

-----
### W, b 값 구하기
 - tf.GradientTape
    (아래 코드 참고)
    with 구문안의 블록안의 변수들의 정보를 tape에 기록하고  
    tape에 기록된 변수들의 정보(w,b)를 이후에 tape.gradient()함수를 통해 경사도를 구한다.  
    tape.gradient()함수는 cost함수에 대해 변수들(w,b)에 대한 개별 미분값(기울기)을 구해서 tuple을 반환한다.  
    learning rate값은 W_grad, b_grad 값을 얼만큼 반영할 것인지를 결정한다.  
    아래의 코드가 한 걸음이라고 보면 됨, W와 b가 한번 업데이트 된 것이다.  
~~~python
with tf.GradientTape() as tape:
    hypothesis = W * x_data + b
    cost = tf.reduce_mean(tf.square(hypothesis - y_data))

W_grad, b_grad = tape.gradient(cost, [W, b])

# W, b 값 업데이트: W -= learning_rate * W_grad
W.assign_sub(learning_rate * W_grad)
b.assign_sub(learning_rate * b_grad)
~~~
-----


### cost는 어떻게 줄일까?
How to minimize cost(Gradient Descent)  
<img src="./img/Hypothesis_Cost_function.png" width="50%">  

 - Error : H(x) - y  
 - cost : (H(x)i - yi)의 제곱의 평균값  
 - Gradient Descent: cost 함수의 최소값을 찾는 알고리즘으로 Gradient Descent알고리즘을 사용한다.  
    최적화?.. 이득을 최대화하거나 손실을 최소화한다 -> gradient descent알고리즘은 손실을 최소화한다.  
     W1, W2, W3.. 등 변수가 여러개 있을 경우에도 손실을 최소화시킬 수 있는 알고리즘이다.  

 - Gradient Descent 알고리즘은 어떻게 동작하는가?  
    - 최초의 추정을 통해 W, b 값을 초기화한다.(0,0 또는 random값 등 최초의 초기화된 값)  
      cost가 최소가 될 수 있도록 지속적으로(매 스텝마다) W,b값을 조금씩 바꾼다.  
    - W, b 값을 지속적으로 업데이트할 때, Gradient값을 구해서 cost값이 최소화되는 방향으로 업데이트한다.  
    - 위의 두 과정을 반복한다.  
    - 최소값에 도달했다고 판단될때까지..  
    - 아래 그림을 참고..  

    <img src="./img/cost_function_grad_w_b_learning_rate.png" width="50%">  

- 위 그림의 수식에서처럼 W값에 기울기*x값 *learningrate값을 빼서 이동하는 과정이 Gradient descent가 된다.  

- local minimum, convex function  

  <img src="./img/convex_local_minima.png" width="50%">

  위 그림 처럼 주변 값들에 비해 cost값이 작은 값을 local minimum이라고 한다.  

  Local minimum값이 여러개 존재하기 때문에 gradient descent 알고리즘을 사용할 수 없다.  
  cost function이 아래 그래프와 같이 local minimum과 global minimum이 일치할 때, gradient descent 알고리즘을 사용할 수 있다.  
  그래서 local minima에 빠지지 않기 위해서는 적절한 W가 적절한 시작점에서부터 경사하강법을 수행할 수 있도록 하는 것이 필요한데,  
  추후, 이를 위해 weight initialize를 하는데 이 내용은 10장의 nn을 보면서 보도록 하자.(xavier)
  <img src="./img/convection_function.jpeg" width="50%">  

  

- 