# -*- coding: utf-8 -*-
# Convolutional Neural Networks(CNN)을 이용한 MNIST 분류기(Classifier) - Keras API를 이용한 구현

import tensorflow as tf

# MNIST 데이터를 다운로드 
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# 이미지들을 float32 데이터 타입으로 변경
x_train, x_test = x_train.astype('float32'), x_test.astype('float32')
# 28*28 형태의 이미지를 784차원으로 flattening 
x_train, x_test = x_train.reshape([-1, 784]), x_test.reshape([-1, 784])
# [0, 255] 사이의 값을 [0, 1]사이의 값으로 Normalize
x_train, x_test = x_train / 255., x_test / 255.
# 레이블 데이터에 one-hot encoding을 적용
y_train, y_test = tf.one_hot(y_train, depth=10), tf.one_hot(y_test, depth=10)

# tf.data API를 이용해서 데이터를 섞고 batch 형태로 가져옴
train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_data = train_data.repeat().shuffle(60000).batch(50)
train_data_iter = iter(train_data)

여기까지는 앞서 실습했던 코드와 같다.

 

2021.10.15 - [Study/Deep Learning] - TensorFlow 2.0과 Softmax Regression을 이용한 MNIST 숫자분류기 구현

 

TensorFlow 2.0과 Softmax Regression을 이용한 MNIST 숫자분류기 구현

<가설 정의> 1. MNIST 데이터를 불러와 학습하기 적합한 형태로 변형 # -*- coding: utf-8 -*- import tensorflow as tf # MNIST 데이터를 다운로드 (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mn..

these-dayss.tistory.com

 

 

# tf.keras.Model을 이용해서 CNN 모델을 정의
class CNN(tf.keras.Model):
  def __init__(self):
    super(CNN, self).__init__()
    # 첫번째 Convolution Layer
    # 5x5 Kernel Size를 가진 32개의 Filter를 적용
    self.conv_layer_1 = tf.keras.layers.Conv2D(filters=32, kernel_size=5, strides=1, padding='same', activation='relu')
    self.pool_layer_1 = tf.keras.layers.MaxPool2D(pool_size=(2, 2), strides=2)

    # 두번째 Convolutional Layer
    # 5x5 Kernel Size를 가진 64개의 Filter를 적용
    self.conv_layer_2 = tf.keras.layers.Conv2D(filters=64, kernel_size=5, strides=1, padding='same', activation='relu')
    self.pool_layer_2 = tf.keras.layers.MaxPool2D(pool_size=(2, 2), strides=2)

    # Fully Connected Layer
    # 7x7 크기를 가진 64개의 activation map을 1024개의 특징들로 변환
    self.flatten_layer = tf.keras.layers.Flatten() #Flattening 수행하는 함수
    self.fc_layer_1 = tf.keras.layers.Dense(1024, activation='relu')

    # Output Layer
    # 1024개의 특징들(feature)을 10개의 클래스-one-hot encoding으로 표현된 숫자 0~9-로 변환
    self.output_layer = tf.keras.layers.Dense(10, activation=None)

  def call(self, x):
    # CNN 같은 경우 인풋 데이터를 Flattening 된 1차원 데이터로 받을 필요가 없음! 따라서 이미지 Dimesion 자체를 인풋으로 받음
    # MNIST 데이터를 3차원 형태로 reshape. MNIST 데이터는 grayscale 이미지기 때문에 3번째차원(컬러채널)의 값은 1.
    x_image = tf.reshape(x, [-1, 28, 28, 1])
    # 28x28x1 -> 28x28x32
    h_conv1 = self.conv_layer_1(x_image)
    # 28x28x32 -> 14x14x32
    h_pool1 = self.pool_layer_1(h_conv1)
    # 14x14x32 -> 14x14x64
    h_conv2 = self.conv_layer_2(h_pool1)
    # 14x14x64 -> 7x7x64
    h_pool2 = self.pool_layer_2(h_conv2)
    # 7x7x64(3136) -> 1024
    h_pool2_flat = self.flatten_layer(h_pool2)
    h_fc1 = self.fc_layer_1(h_pool2_flat)
    # 1024 -> 10
    logits = self.output_layer(h_fc1)
    y_pred = tf.nn.softmax(logits)

    return y_pred, logits

대략 이런 구조

 

# cross-entropy 손실 함수를 정의
@tf.function
def cross_entropy_loss(logits, y):
  return tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y))

# 최적화를 위한 Adam 옵티마이저를 정의
optimizer = tf.optimizers.Adam(1e-4)  #0.0001

# 최적화를 위한 function을 정의
@tf.function
def train_step(model, x, y):  #실제 Gradient Descent 한번 수행
  with tf.GradientTape() as tape:
    y_pred, logits = model(x)
    loss = cross_entropy_loss(logits, y)
  gradients = tape.gradient(loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

# 모델의 정확도를 출력하는 함수를 정의
@tf.function
def compute_accuracy(y_pred, y):
  correct_prediction = tf.equal(tf.argmax(y_pred,1), tf.argmax(y,1))
  accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

  return accuracy
  
# Convolutional Neural Networks(CNN) 모델을 선언
CNN_model = CNN()

# 10000 Step만큼 최적화를 수행
for i in range(10000):
  # 50개씩 MNIST 데이터를 불러옴
  batch_x, batch_y = next(train_data_iter)
  # 100 Step마다 training 데이터셋에 대한 정확도를 출력
  if i % 100 == 0:
    train_accuracy = compute_accuracy(CNN_model(batch_x)[0], batch_y)
    print("반복(Epoch): %d, 트레이닝 데이터 정확도: %f" % (i, train_accuracy))
  # 옵티마이저를 실행해 파라미터를 한스텝 업데이트
  train_step(CNN_model, batch_x, batch_y)

# 학습이 끝나면 학습된 모델의 정확도를 출력
print("정확도(Accuracy): %f" % compute_accuracy(CNN_model(x_test)[0], y_test))

 

결과

10000번의 epoch 결과, 정확도는 99% 정도가 나왔다. 앞서 실습했던 모델들과 비교하면 CNN 구조의 정확도가 월등히 높은 것을 확인할 수 있다.

'Study > Deep Learning' 카테고리의 다른 글

tf.train.CheckpointManager API  (0) 2021.10.18
드롭아웃(Dropout)  (0) 2021.10.17
CNN(Convolutional Neural Networks)  (0) 2021.10.17
CNN 의 등장  (0) 2021.10.16
오토인코더 Autoencoder  (0) 2021.10.15

컨볼루션 신경망, CNN

:: 이미지 분야를 다루는데 최적화 된 인공신경망 구조

: 크게 컨볼루션층(Convolution Layer), 풀링층(Pooling, 서브샘플링 Subsampling Layer) 으로 구성되어 있다.

CNN 구조/ 출처 http://taewan.kim/post/cnn/

 


1. 컨볼루션 Convolution 층

: 컨볼루션 연산(합성곱 연산)을 통해서 이미지의 특징을 추출해내는 역할

 

- 컨볼루션

: 커널(Kernel) 또는 필터(Filter)라고 불리는 윈도우 크기만큼의 X×X 크기의 행렬을 Y×Y 크기의 이미지 행렬의 X×X 크기

부분과 곱해서 모두 더하는 수학 연산자

 

출처 https://halfundecided.medium.com/%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-cnn-convolutional-neural-networks-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-836869f88375

 

이렇게 원본 이미지에 커널을 이용해서 컨볼루션을 수행하면 커널의 종류에 따라 원본 이미지의 특징들(Features)이 활성화 맵(Activation Map) 으로 추출되게 된다.

 

이때, 어떤 커널을 사용하느냐에 따라 원본 이미지에서 다양한 특징을 추출할 수 있다.

커널 종류에 따른 다양한 추출 이미지 / 출처 https://en.wikipedia.org/wiki/Kernel_(image_processing)

 

이렇게 추출한 활성화 맵은 원본 이미지에서 명확히 드러나지 않던 특징들을 보여준다.

자동차와 사람을 분류하고자 할 때, 원본 이미지 자체를 사용하는 것보다 모서리만 추출된 특징 이미지를 사용하는 것이 더 효율적일 것이다.

 


2. 풀링 Pooling 층

: 차원을 축소하는 연산 수행

 

종류?

- 최대값 풀링 Max Pooling , 평균값 풀링 Average Pooling, 최소값 풀링 Min Pooling 등

 

Max Pooling / 출처 https://developers.google.com/machine-learning/practica/image-classification/convolutional-neural-networks

최대값 풀링은 이미지의 X×X 크기 부분에서 가장 큰 값 하나를 추출해서 원본 이미지의  X×X개의 값을 1개의 값으로 축소한다.

 

동일한 원리로 평균값 풀링, 최소값 풀링은 평균값, 최소값으로 축소한다.

풀링층 역시 이미지의 좌측 상단에서 우측하단으로 순차적으로 전체 이미지에 대해 풀링을 수행한다.

 

 

이러한 이미지 차원 축소를 통해 필요한 연산량을 감소시킬 수 있고, 이미지의 가장 강한 특징만을 추출하는 특징 선별 효과가 있다. 

 

 


→ 컨볼루션층을 거치면 인풋 이미지의 가로, 세로 차원이 축소된다. 

출력 이미지 가로 길이 계산법

(W in = 인풋 이미지의 가로 길이, W out = 출력 이미지의 가로 길이, F = 필터의 크기, S = 스트라이드)

 

+) 스트라이드? 컨볼루션 연산시 건너뛰는 정도

스트라이드가 크면 컨볼루션 수행 시 차원이 많이 축소되고 스트라이드가 작으면 차원이 조금 축소된다.

 

또한 모든 차원이 정수로 나누어 떨어지지 않을 수 있으므로 인풋 이미지의 상하좌우 모서리에 P만큼 0을 채워주는 제로패딩(Zero-Padding)을 P만큼 적용해준다.

제로 패딩 / 출처 https://excelsior-cjh.tistory.com/180 

 

 

출력 이미지 세로 길이 계산법

출력 이미지 세로 길이 계산법은 가로 길이 계산법과 같다.

 

 

 

마지막으로, 컨볼루션층의 출력결과와 3번째 차원은 컨볼루션 필터 개수 K가 된다.

따라서 컨볼루션층의 결과로 출력되는 차원은 [W out, H out, K] 이다.

 

예를 들어, [28x28x1] MNIST 이미지에 4x4 크기의 필터(F=4)에 스트라이드가 2(S=2)이고, 제로 패딩을 1만큼 적용한(P=1) 64개의 필터개수(K=64)를 가진 컨볼루션층을 적용하면 출력 결과로 [14,14,64]

즉, 14x14 크기의 64개의 활성화맵이 추출된다.

 

 

이런 과정을 거친 활성화 맵들은 마지막에 Flattening으로 펼친 다음 완전연결층(ANN)의 인풋으로 들어가서 Softmax 분류를 수행하게 된다.

사람은 고양이를 판단할 때,

엎드려 있던지, 귀가 가려져 있던지, 꼬리만 보이던지, 줄무늬가 있던지/없던지, 배경과 비슷한 색이던지 

대부분 고양이라고 판단할 수 있다.

 

하지만 컴퓨터는 모든 픽셀을 0-255 단위의 숫자로 보고 판단하기 때문에 판단하는데 어려움을 겪을 수 있다.

 

따라서 사람이 사물의 특징을 기술한 Handcrafted Feature 로 기계를 학습시키면 해결이 될 것이라 판단했지만 이는 한계가 있었다. 

 

이 후 End-To-End Learning(종단간 기계학습) 방법이 등장하게 되는데, 이는 입력 및 출력을 직접 고려하여 네트워크 가중치를 최적화 하는 학습을 말한다. 

즉, 데이터만 사람이 넣어주고 중간 부분을 딥러닝 모델에 위임한다는 것이다. 따라서 사람이 많은 개수의 데이터(input, output) 만 모아준다면 자동으로 학습하도록 한다. 

 

 

여기서 CNN의 개념이 등장한다.

CNN은 Convolutional Nerual Networks의 약자로 전처리 작업이 들어가는 딥러닝 모델이다. 

이는 Raw Image들로부터 특징들(Features)을 자동으로 학습하도록 하는 것이 목표이다.

 

CNN의 중요 포인트는 이미지 전체보다는 부분을 보는 것, 이미지의 한 픽셀과 주변 픽셀들의 연관성을 살리는 것이다.

 

오토인코더?

:: 대표적인 비지도 학습(Unsupervised Learning, 데이터의 숨겨진 특징을 찾는 것이 목표)을 위한 인공신경망 구조 중 하나

출처 https://excelsior-cjh.tistory.com/187

출력층 Output Layer의 노드 개수와 입력층 Input Layer의 노드 개수가 동일한 구조의 인공신경망이라고 생각하면 된다.

 

따라서, 오토인코더의 출력은 원본 데이터 Raw Data를 재구축 Reconstruction한 결과가 된다.

 

똑같은 결과가 나오는데 이를 왜 사용할까?

오토인코더의 핵심은 은닉층의 출력값이다.

 

오토인코더의 구조를 보면 입력층과 출력층의 노드 개수보다 은닉층의 노드 개수가 적다는 것을 알 수 있다.

더 작은 표현력으로 원본 데이터의 모든 특징들을 학습해야 하기 때문에 이 출력값은 원본 데이터에서 불필요한 특징들을 제거한 압축된 특징들을 학습하게 된다.

따라서 은닉층의 출력값을 원본 데이터 대신에 분류기 Classifier의 입력으로 사용한다면 더욱 좋은 분류 성능을 기대할 수 있다.

 

 

 

 

 

2021.10.15 - [Study/Deep Learning] - TensorFlow 2.0과 Softmax Regression을 이용한 MNIST 숫자분류기 구현

 

TensorFlow 2.0과 Softmax Regression을 이용한 MNIST 숫자분류기 구현

<가설 정의> 1. MNIST 데이터를 불러와 학습하기 적합한 형태로 변형 # -*- coding: utf-8 -*- import tensorflow as tf # MNIST 데이터를 다운로드 (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mn..

these-dayss.tistory.com

이전 글을 참고하면 이해가 잘 갈 것이다.

 

 

# -*- coding: utf-8 -*-
# 텐서플로우를 이용한 ANN(Artificial Neural Networks) 구현 - Keras API를 이용한 구현

import tensorflow as tf

# MNIST 데이터를 다운로드 
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# 이미지들을 float32 데이터 타입으로 변경
x_train, x_test = x_train.astype('float32'), x_test.astype('float32')
# 28*28 형태의 이미지를 784차원으로 flattening 함
x_train, x_test = x_train.reshape([-1, 784]), x_test.reshape([-1, 784])
# [0, 255] 사이의 값을 [0, 1]사이의 값으로 Normalize 함
x_train, x_test = x_train / 255., x_test / 255.
# 레이블 데이터에 one-hot encoding을 적용
y_train, y_test = tf.one_hot(y_train, depth=10), tf.one_hot(y_test, depth=10)

# 학습을 위한 설정값들을 정의
learning_rate = 0.001
num_epochs = 30     # 학습횟수
batch_size = 256    # 배치개수
display_step = 1    # 손실함수 출력 주기
input_size = 784    # 28 * 28
hidden1_size = 256
hidden2_size = 256
output_size = 10

# tf.data API를 이용해서 데이터를 섞고 batch 형태로 가져옴
train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_data = train_data.shuffle(60000).batch(batch_size) # 한번 epoch가 끝날 때마다 셔플(섞어줌)

# 초기 W값과 b 값을 초기화
def random_normal_intializer_with_stddev_1():
  return tf.keras.initializers.RandomNormal(mean=0.0, stddev=1.0, seed=None)

대충 그리자면 이런 구조다

# tf.keras.Model을 이용해서 ANN 모델을 정의
class ANN(tf.keras.Model):
  def __init__(self):
    super(ANN, self).__init__()
    self.hidden_layer_1 = tf.keras.layers.Dense(hidden1_size,
                                                activation='relu',
                                                kernel_initializer=random_normal_intializer_with_stddev_1(),
                                                bias_initializer=random_normal_intializer_with_stddev_1())
    self.hidden_layer_2 = tf.keras.layers.Dense(hidden2_size,
                                                activation='relu',
                                                kernel_initializer=random_normal_intializer_with_stddev_1(),
                                                bias_initializer=random_normal_intializer_with_stddev_1())
    self.output_layer = tf.keras.layers.Dense(output_size,
                                              activation=None,
                                              kernel_initializer=random_normal_intializer_with_stddev_1(),
                                              bias_initializer=random_normal_intializer_with_stddev_1())

  def call(self, x):
    H1_output = self.hidden_layer_1(x)
    H2_output = self.hidden_layer_2(H1_output)
    logits = self.output_layer(H2_output)

    return logits

 

 

# cross-entropy 손실 함수를 정의
@tf.function
def cross_entropy_loss(logits, y):
  return tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y))

# 최적화를 위한 Adam 옵티마이저를 정의, 기본 옵티마이저를 업그레이드 한 것. 미분값이 0인 곳도 넘어감
optimizer = tf.optimizers.Adam(learning_rate)

# 최적화를 위한 function을 정의
@tf.function
def train_step(model, x, y):  #한 번의 Gradient Descent 수행
  with tf.GradientTape() as tape:
    y_pred = model(x)
    loss = cross_entropy_loss(y_pred, y)
  gradients = tape.gradient(loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

# 모델의 정확도를 출력하는 함수를 정의
@tf.function
def compute_accuracy(y_pred, y):
  correct_prediction = tf.equal(tf.argmax(y_pred,1), tf.argmax(y,1))
  accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

  return accuracy

 

 

# ANN 모델을 선언
ANN_model = ANN()

# 지정된 횟수만큼 최적화를 수행
for epoch in range(num_epochs):
  average_loss = 0.
  total_batch = int(x_train.shape[0] / batch_size)
  # 모든 배치들에 대해서 최적화를 수행
  for batch_x, batch_y in train_data:
    # 옵티마이저를 실행해서 파라마터들을 업데이트
    _, current_loss = train_step(ANN_model, batch_x, batch_y), cross_entropy_loss(ANN_model(batch_x), batch_y)
    # 평균 손실을 측정
    average_loss += current_loss / total_batch
  # 지정된 epoch마다 학습결과를 출력
  if epoch % display_step == 0:
    print("반복(Epoch): %d, 손실 함수(Loss): %f" % ((epoch+1), average_loss))

# 테스트 데이터를 이용해서 학습된 모델이 얼마나 정확한지 정확도를 출력
print("정확도(Accuracy): %f" % compute_accuracy(ANN_model(x_test), y_test)) # 정확도: 약 94%

 

 

결과

epoch 횟수 별로 손실함수 값이 어떻게 변화하는지 알 수 있다.

(한 번의 epoch는 인공 신경망에서 전체 데이터 셋에 대해 forward pass/backward pass 과정을 거친 것을 말함. 즉, 전체 데이터 셋에 대해 한 번 학습을 완료한 상태)

 

epoch가 반복되면서 손실함수 값이 점진적으로 감소하는 것을 알 수 있고

30번 모두 끝난 후의 모델의 학습 정확도를 계산해보면 약 94%임을 알 수 있다.

인공신경망(ANN, Artificial Neural Network)

 

인간의 뇌 : 엄청난 양의 병렬 처리 연산기(by 뉴런의 생물학적 구조)

컴퓨터 : 순차 처리 연산기 -> 단순한 기초 연산은 인간보다 훨씬 뛰어남

 

"컴퓨터도 인간의 뇌처럼 대량의 병렬 처리 연산을 수행하도록 한다면 컴퓨터도 인간이 쉽게 할 수 있는 인지행동을 할 수 있지 않을까?"

 

 

<퍼셉트론 Perceptron>

생물학적 뉴런을 공학적인 구조로 변형한 그림, 가중치에 기반한 의사결정모델

 

- 가중치 : Input의 중요도를 나타냄

출처 https://liveyourit.tistory.com/63

- 입력층과 출력층을 가지고 있다.

 

퍼셉트론 동작과정

- 입력층에서 인풋 데이터 x 를 받고, 이를 가중치 W와 곱한 후, 편향 b를 더한다.

이 값을 활성함수의 입력값으로 대입하여 출력층은 최종적으로 0 또는 1의 값을 출력한다.

 

계단 함수

 

퍼셉트론은 활성 함수로 계단 함수(Step Function)을 사용해서 값이 0보다 크면 1, 0보다 작으면 0을 출력한다.

 

이진분류

즉, 퍼셉트론은 입력값을 받으면 2개의 출력값 중 하나를 출력해내는 선형 이진분류기(Linear Binary Classifier)이다.

 

선형분류로 처리할 수 없는 XOR 문제(3번째)                                        출처 https://steemit.com/kr-steemit/@beseeyong/xor

--> 단순한 선형분류기에 불과하며, 간단한 XOR 문제도 해결할 수 없다는 사실이 증명되며 인기가 사그라들었음

 


<다층 퍼셉트론 MLP (Multi-Layer Perceptron) = 인공신경망 ANN>

선형 분리가 불가능한 문제도 해결할 수 있다는 사실이 밝혀지며 다시 인공신경망 연구를 계속하게 된다.

 

- 다층 퍼셉트론은 입력층과 은닉층, 출력층으로 구성

은닉층은 입출력 과정에서 직접적으로 보이진 않지만 숨겨진 특징을 학습하는 역할

출처 https://m.blog.naver.com/samsjang/221030487369

 

이는 활성함수로 비선형 함수(시그모이드 Sigmoid와 쌍곡 탄젠트 Tangent Hyperbolic, ReLU)를 사용한다.

 

앞 두 함수(시그모이드, 쌍곡탄젠트)는 Input data가 특정 값을 넘어가면 미분값이 0이 되는 현상 "Vanishing Gradient Problem(기울기값이 사라지는 문제)" 이 발생한다. 

ReLU에선 양수 데이터에 대해선 미분값이 살아있어 이 문제가 줄어들기 때문에 최근엔 이 함수를 많이 사용한다.

 

 

이렇게 입력층과 출력층 사이에 여러개의 은닉층이 있는 인공신경망ANN을 심층 신경망(Deep Neural Network)라고 부르며, 심층 신경망을 학습하기 위해 고안된 알고리즘을 딥러닝(Deep Learning)이라고 부르는 것이다.

<가설 정의>

1. MNIST 데이터를 불러와 학습하기 적합한 형태로 변형

# -*- coding: utf-8 -*-

import tensorflow as tf

# MNIST 데이터를 다운로드 
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

load_data() 호출 시 MNIST 데이터를 numpy (int)array 형태로 반환해줌

x_train, y_train에는 약 60000개의 트레이닝 데이터, x_test, y_test에는 약 10000개의 테스트 데이터가 있음

 

 

# 이미지들을 float32 데이터 타입으로 변경
x_train, x_test = x_train.astype('float32'), x_test.astype('float32')
# 28*28 형태의 이미지를 784차원으로 flattening 함
x_train, x_test = x_train.reshape([-1, 784]), x_test.reshape([-1, 784])
# [0, 255] 사이의 값을 [0, 1]사이의 값으로 Normalize 함
x_train, x_test = x_train / 255., x_test / 255.

astype : 데이터 형변환

reshape(-1,~) : 여기서 -1은 매직넘버. 앞 차원에 알아서 맞춰줌. 기본 옵션이라고 생각

flattening : 2차원 데이터를 한 픽셀씩 펼쳐서 1차원 데이터로 변경하는 것. 28*28 -> 784

 

MNIST 데이터는 픽셀 하나당 0-255까지의 숫자값을 가지므로 ,이를 255로 나누면 0-1 사이로 normalize 됨

 

# 레이블 데이터에 one-hot encoding을 적용
y_train, y_test = tf.one_hot(y_train, depth=10), tf.one_hot(y_test, depth=10)

정답 데이터가 int 형이므로 one-hot encoding 을 적용해준다.

( 1 → 1000000000, 2 → 0100000000, 3 → 0010000000 이런 형식) 

 


2. 전체 데이터를 원하는 mini-batch 개수만큼 묶어줌

# tf.data API를 이용해서 데이터를 섞고 batch 형태로 가져옴
train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_data = train_data.repeat().shuffle(60000).batch(100)
train_data_iter = iter(train_data)

tf.data.Dataset : api. 미니배치 단위로 묶는 과정을 손쉽게 할 수 있도록 함

iter : iterator. 100개씩의 미니배치를 순차적으로 가리키게 됨

 


3. 소프트맥스 회귀 모델 정의

# tf.keras.Model을 이용해서 Softmax Regression 모델을 정의
class SoftmaxRegression(tf.keras.Model):
  def __init__(self):
    super(SoftmaxRegression, self).__init__()
    self.softmax_layer = tf.keras.layers.Dense(10,
                                               activation=None,
                                               kernel_initializer='zeros',
                                               bias_initializer='zeros')

  def call(self, x):
    logits = self.softmax_layer(x)

    return tf.nn.softmax(logits)

tf.keras.Model : 상속받는 클래스

tf.keras.layers.Dense : Wx+b를 추상화 해놓은 api (input을 넣었을 때 output으로 바꿔주는 중간 다리)

→ 10 = units. 출력 값의 크기, activation = 활성화 함수, kernel_initializer = 가중치(W) 초기화 함수, bias_initializer = 편향(b) 초기화 함수

 

call : 클래스 호출 시 동작하는 함수

logits : softmax(Wx+b)가 적용된 10 dimension의 값이 담겨있음

 


<손실함수 정의>

# cross-entropy 손실 함수를 정의
@tf.function
def cross_entropy_loss(y_pred, y):
  return tf.reduce_mean(-tf.reduce_sum(y * tf.math.log(y_pred), axis=[1]))
  #return tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logtis, labels=y)) # tf.nn.softmax_cross_entropy_with_logits API를 이용한 구현

<최적화>

# 최적화를 위한 그라디언트 디센트 옵티마이저를 정의
optimizer = tf.optimizers.SGD(0.5)

# 최적화를 위한 function을 정의
@tf.function
def train_step(model, x, y):
  with tf.GradientTape() as tape:
    y_pred = model(x)
    loss = cross_entropy_loss(y_pred, y)
  gradients = tape.gradient(loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

SGD : 옵티마이저 종류 중 하나

0.5 : learning rate

 

 

# 모델의 정확도를 출력하는 함수를 정의
@tf.function
def compute_accuracy(y_pred, y):  #모델이 예측한 값, 정답값
  correct_prediction = tf.equal(tf.argmax(y_pred,1), tf.argmax(y,1))  #일치 개수 반환
  accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  #0~1 사이의 정확도 반환

  return accuracy

argmax :  최대값을 갖는 성분의 인덱스를 반환

y_pred는 softmax 함수 결과 값이 들어있다. [0.01, 0.4, 0.7, 0.04, 0.2, 0.082, 0.03, 0.002, 0.3, 0.06] 

하지만 정답값 y에는 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] 과 같은 형식으로 들어있다.

따라서 y_pred에 argmax 함수를 취하여 최대값을 갖는 성분의 인덱스를 반환하여 비교시키는 작업이 필요하다

 

 

# SoftmaxRegression 모델을 선언
SoftmaxRegression_model = SoftmaxRegression()

# 1000번 반복을 수행하면서 파라미터 최적화를 수행
for i in range(1000):
  batch_xs, batch_ys = next(train_data_iter)  #100개씩의 mini-batch 데이터가 반환
  train_step(SoftmaxRegression_model, batch_xs, batch_ys)

# 학습이 끝나면 학습된 모델의 정확도를 출력
print("정확도(Accuracy): %f" % compute_accuracy(SoftmaxRegression_model(x_test), y_test)) # 정확도 : 약 91%

batch_xs : (100, 784) MNIST 데이터

batch_ys : 100 dimension의 원-핫 인코딩된 데이터

 

 

 

결과

 

 

# -*- coding: utf-8 -*-

import tensorflow as tf

# 선형회귀 모델(Wx + b)을 위한 tf.Variable을 선언
W = tf.Variable(tf.random.normal(shape=[1]))
b = tf.Variable(tf.random.normal(shape=[1]))

@tf.function
def linear_model(x):
  return W*x + b

# 손실 함수를 정의
# MSE 손실함수 \mean{(y' - y)^2}
@tf.function
def mse_loss(y_pred, y):
  return tf.reduce_mean(tf.square(y_pred - y))

# 최적화를 위한 그라디언트 디센트 옵티마이저를 정의
optimizer = tf.optimizers.SGD(0.01)

# 최적화를 위한 function을 정의
@tf.function
def train_step(x, y):
  with tf.GradientTape() as tape:
    y_pred = linear_model(x)
    loss = mse_loss(y_pred, y)
  gradients = tape.gradient(loss, [W, b])
  optimizer.apply_gradients(zip(gradients, [W, b]))

# 트레이닝을 위한 입력값과 출력값을 준비
x_train = [1, 2, 3, 4]
y_train = [2, 4, 6, 8]

# 경사하강법을 1000번 수행
for i in range(1000):
  train_step(x_train, y_train)

# 테스트를 위한 입력값을 준비
x_test = [3.5, 5, 5.5, 6]
# 테스트 데이터를 이용해 학습된 선형회귀 모델이 데이터의 경향성(y=2x)을 잘 학습했는지 측정
# 예상되는 참값 : [7, 10, 11, 12]
print(linear_model(x_test).numpy())

 

1-8 = 가설 정의

파라미터 W,b 정의

tf.Variable = api

random.normal = 가우시안 distribution에서 random 값을 뽑음

shape 인자 값 = 지정하고자 하는 모델의 파라미터 shape. 선형 회귀에선 하나의 데이터(x)를 받아 하나를 도출해내는 것이기 때문에 1차원으로 지정함

 

9-11 =Linear Regression 함수 작성

-----------------------------------------------------------------------------------------------

13 - 17 = 손실함수 정의

loss(예측값, 정답값)

square = 제곱함수

reduce_mean = 평균함수

 

-----------------------------------------------------------------------------------------------

19 - 29 = optimization 정의, gradient descent 정의

SGD : mini-batch gradient descent 실행해 주는 기본적인 옵티마이저

0.01 = learning rate

 

train_step : gradient descent를 한 단계 실행해주는 함수

y_pred : linear regression에 기반한 예측값

mse : mean_sqaured_error

gradients : loss에 대한 해당 파라미터(W,b)에 대한 gradient 값

zip : 계산한 gradient와 갱신 대상 파라미터(W,b)를 묶어줌 (   zip([1,2,3],[4,5,6]) ==> (1,4), (2,5), (3,6)   )

 

 

딥러닝 알고리즘의 "학습" = apply_gradient 함수를 반복 호출해 랜덤 파라미터를 학습 방향성에 맞게 변형 시켜주는 것!

 

실행 결과

 

 

'Study > Deep Learning' 카테고리의 다른 글

다층 퍼셉트론 MLP  (0) 2021.10.15
TensorFlow 2.0과 Softmax Regression을 이용한 MNIST 숫자분류기 구현  (0) 2021.10.15
TensorFlow  (0) 2021.10.15
다양한 Computer Vision 문제 영역  (0) 2021.10.14
머신러닝 Data 종류  (0) 2021.10.14

:: 구글에서 개발하여 공개한 딥러닝/머신러닝을 위한 오픈소스 라이브러리

:: 오픈소스

:: C++, JAVA, GO, python 등의 언어 지원

 

 

장점

1. 손쉬운 딥러닝 모델 구현 by Python API

2. Mobile Device부터 멀티 GPU 클러스터까지 지원하는 폭넓은 Portability

3. 강력한 시각화를 지원하는 TensorBoard 제공

4. 전세계적으로 폭넓은 사용자 Community

5. Google의 강력한 지원과 발빠른 신기능 업데이트

 

 

 

+) Tensor = "n차원 행렬"

0-d tensor : scalar

1-d tensor : vector

2-d tensor : matrix

 

 

 

1. Image Classification

인풋 이미지가 어떤 라벨(label)에 대응되는지 인풋 이미지에 대한 분류를 수행하는 문제 영역

ex) 이 이미지는 강아지고 이 이미지는 고양이다

출처 https://becominghuman.ai/cifar-10-image-classification-fd2ace47c5e8

 

2. Face Detection

얼굴이 있는 영역의 위치정보를 Bounding Box로 찾는 문제 영역 (x,y 좌표로 찾아줌)

위치 정보만 딱 알려줌

출처 https://www.technologyreview.com/2015/02/16/169357/the-face-detection-algorithm-set-to-revolutionize-image-search/

 

3. Face Alignment

얼굴의 특징 영역(눈,코,입) 을 포인트(Landmark)로 찾는 문제 영역

face detection보다 디테일함. 눈썹, 광대, 표정 등 디테일한 정보를 식별할 수 있음

출처 https://rapidapi.com/blog/top-facial-recognition-apis/

 

4. Steering Angle Prediction

자동차의 적합한 Steering Angle 조작값을 예측하는 문제 영역 (핸들링에 대한 조작값을 예측)

출처 https://paperswithcode.com/task/self-driving-cars/codeless?page=4

 

5. Super Resolution

저해상도 이미지를 인풋으로 받으면 이를 고해상도 이미지로 변경해주는 문제영역

출처 https://smilegate.ai/2020/10/19/ygs-super-resolution/

 

6. Object Detection

물체가 있는 영역의 위치정보를 Bounding Box로 찾고 Bounding Box 내에 존재하는 사물의 라벨(Label)을 분류하는 문제영역 

ex) 이 Box 안에 있는 물체는 사람/자동차/고양이 이다. 까지 분류 가능

출처 https://hoya012.github.io/blog/Tutorials-of-Object-Detection-Using-Deep-Learning-what-is-object-detection/

 

7. Image Captioning

전체 이미지에 대한 설명문을 자동 생성하는 문제 영역

ex) 이 이미지는 강아지가 자고 있는 모습이다. 이 이미지는 사람이 달려가는 모습이다. 등

출처 https://www.analyticsvidhya.com/blog/2018/04/solving-an-image-captioning-task-using-deep-learning/

 

8. Neural Style Transfer

콘텐츠 이미지(사진)에 스타일 이미지(명작,회화 등)를 덧씌운 합성 이미지를 만드는 문제영역

ex) 건물의 사진에 고흐의 <별이 빛나는 밤에>를 합성한 이미지

출처 https://towardsdatascience.com/light-on-math-machine-learning-intuitive-guide-to-neural-style-transfer-ef88e46697ee

 

9. Generative Model

트레이닝 데이터의 분포를 학습하고 이를 이용해서 새로운 가짜 Fake 데이터를 생성하는 문제영역

 출처 https://www.kdnuggets.com/2020/03/generate-realistic-human-face-using-gan.html

 

10. Semantic Image Segmentation

이미지의 전체 픽셀에 대한 분류를 수행하는 문제영역

ex) 나무, 사람, 도로, 차도, 새 등 이미지의 픽셀마다 분류를 함

출처 https://theaisummer.com/Semantic_Segmentation/

 

11. Brain Tumor Segmentation

Brain 이미지 내에 종양(Tumor)이 있는 부분을 자동 분류하는 문제영역

출처 https://developer.nvidia.com/blog/automatically-segmenting-brain-tumors-with-ai/

 

12. Face Recognition

Face Detection이 진행된 상태에서 해당 Bounding box 위치에 존재하는 얼굴이 누구인지 신원(identity)를 식별하는 문제영역

출처 https://www.pyimagesearch.com/2018/06/25/raspberry-pi-face-recognition/

 

13. Face Verification

두 개의 얼굴 이미지를 인풋으로 받아서 해당 얼굴 이미지가 동일인물인지 아닌지를 판단하는 문제영역

출처 https://pralab.diee.unica.it/en/FaceVerification

 

14. Face Hallucination

얼굴 이미지에 대한 Super Resolution을 수행하는 문제영역

출처 https://paperswithcode.com/task/face-hallucination/codeless?page=4

 

 

15. Text Detection

이미지 내에 텍스트가 존재하는 영역의 위치정보를 Bounding Box로 찾는 문제영역

출처 https://cloud.google.com/vision/docs/ocr

 

16. Optical Character Recognition(OCR)

Text Detection이 수행된 Bounding Box 내에 존재하는 글자가 어떤 글자인지를 인식하는 문제영역

출처 https://m.blog.naver.com/rdproject/222113275331

 

17. License Plate Detection

Text Detection과 OCR을 이용해서 차량 번호판을 인식하는 문제영역

출처 https://medium.com/@quangnhatnguyenle/detect-and-recognize-vehicles-license-plate-with-machine-learning-and-python-part-1-detection-795fda47e922

 

18. Defect Detection

공정 과정상에 불량(Defect)을 검출하는 문제영역

출처 https://www.cognex.com/blogs/deep-learning/deep-learning-for-automotive-industry

 

19. Human Pose Estimation

인간의 중요 신체 부위를 Keypoint라는 점으로 추정해서 현재 포즈를 예측하는 문제영역

출처 https://towardsdatascience.com/realtime-multiple-person-2d-pose-estimation-using-tensorflow2-x-93e4c156d45f

'Study > Deep Learning' 카테고리의 다른 글

TensorFlow 2.0을 이용한 선형 회귀(Linear Regression) 알고리즘 구현  (0) 2021.10.15
TensorFlow  (0) 2021.10.15
머신러닝 Data 종류  (0) 2021.10.14
머신러닝 기본 프로세스  (0) 2021.10.14
딥러닝의 응용분야  (0) 2021.10.13

+ Recent posts