230405 수업 - CNN

Yunit·2023년 4월 5일
0

복습

Linear Regression

종속 변수가 연속적인 숫자값.
학습데이터의 상태(종속변수)가 변한다.

Logistic Regression

  • binary classification
    0~1 사이의 확률값 1개

=> 학습데이터의 상태(종속변수)가 다시 변한다.

Multinomial Classification

BMI지수 학습

class별 확률값
ex. (0.6, 0.3, 0.1)

지금까지의 공통점

정형데이터를 대상으로 했다.
이제는 비정형데이터를 대상으로 하려 한다. 인지와 관련된 데이터. 소리, 그림, ...


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

Artificial 은 생략하는 경우가 많음.
keras Model을 기본으로 생각하면 쉽다.
Layer를 추가한다. input 레이어와 output 레이어 사이에 hidden layer를 추가하는 것.

DNN(Deep Neural Network)

계층을 많이 주어 깊은 신경망을 만든다고 해서 지은 이름.
이게 곧 Deep Learning이다. 이름만 바꿨다기보단, 이때부터 러닝 기술이 확실히 좋아졌다고 생각하면 된다.
ex. 알파고

Image 데이터는? Image를 DNN을 이용해서 학습하면 좋겠네?

컴퓨터에게는 공간지각능력이 없기 때문에, 이에 대한 데이터를 다 넣어줘야 한다.

  • 이미지 데이터

이미지는 가로, 세로 pixel의 집합. 2차원이다. 그리고 이미지의 입력은 기본적으로 3차원이다. DNN은 입력이 2차원이라서 차원 수를 맞춰줘야 해.
그래서 이미지 데이터를 2차원에서 1차원으로 바꿔. 가로 세로 데이터를 그냥 한 줄로 쭉 나열하는 거야. 이렇게 하면 1차원 데이터가 되긴 하는데, 공간 데이터가 사라지지? 그래서 이미지 학습에 한계가 있었어.

CNN

DNN은 입력이 2차원이라서 이미지 학습에 한계가 있었다. 이를 해결하고자 개발된 게 CNN 알고리즘이다.
여기부터는 Local에서 하지 않고, 구글 colab에서 학습한다.

  • 구글 드라이브
  • 전에 만들었던 폴더 들어가기 (파이썬 실습)
  • 우클릭 - 더보기 - Google Colaboratory (설치 안 되어 있으면 설치부터 하자)
  • 왼쪽 메뉴에서 폴더 모양 클릭
  • 오른쪽에서는 역삼각형 눌러서 리소스 보기 클릭
  • 우측 하단에 '런타임 유형 변경'
    기본값으로 'Noun' 이 되어 있다. 이거 느림. GPU로 바꾸자.
  • 리소스를 다시 계산해준다.
  • 구글 드라이브 마운트
    왼쪽 폴더리스트 위에서 구글 드라이브 마운트하는 버튼이 있다. 클릭하자.

세팅 끝!

Image 파일

데카르트 좌표계

일반적인 좌표계. 위쪽 방향이 y축, 오른쪽 방향이 x축이다.
(x, y) 로 표현한다.

Image 좌표계

이미지는 전용 좌표계가 따로 있다. 오른쪽이 x축인 건 동일한데, 아래가 y축인 게 차이점이다.
(y, x) 으로 표현한다. y축부터 먼저 표시하는 것.

모든 이미지는 3차원이라고 생각하자.

각 픽셀 당 R, G, B 세 개의 데이터가 있다. 각 데이터마다 0~255 즉 2^8 값을 가진다. 24bit로 표현되는데, 이걸 True Color 라고 한다.
그럼 픽셀 당 가로 좌표, 세로 좌표, color데이터 세 개를 모아서 3차원이 되는 것.

Gray-scale(흑백) image는?

R, G, B 값의 평균을 내서 동일한 값을 넣는다.
ex. [10, 150, 20] -> [60, 60, 60]

이미지를 2차원화

이 흑백 3차원 데이터를 2차원으로 표현하려면?
가로, 세로 좌표계 안에 color 데이터를 값 하나로 표현하는 것


실습

  • 이미지를 구글 드라이브에 하나 복사
  • colab에 코드 작성

이미지 띄우기

  • 코드
# from google.colab import drive
# drive.mount('/content/drive')

import numpy as np
from PIL import Image # 이미지처리하기 편한 라이브러리
import matplotlib.pyplot as plt

color_img = Image.open('/content/drive/MyDrive/한국SW산업협회 교육-Java 과정/파이썬 실습/fruits.jpg')

plt.imshow(color_img)
plt.show()
  • 출력

pixel 데이터로 변환 후 이미지 띄우기

  • 코드
# 우리가 필요한 건 ndarray다.
# numpy를 이용해서 데이터를 뽑아내자.

color_pixel = np.array(color_img)

# pixel 데이터를 이용해도 그림을 그리는 게 가능하다.
plt.imshow(color_pixel)
plt.show()
print('shape : {}'.format(color_pixel.shape))
  # 출력
  #   shape : (426, 640, 3)
  #   (세로 픽셀 수, 가로 픽셀 수, 차원 수)
  • 출력

이미지 흑백처리하기(3차원 흑백 이미지)

  • 코드
# 위의 그림을 흑백으로 바꿔보자.
# 각 pixel의 RGB값을 평균내서 RGB칸에 설정하면 흑백처리된다.

gray_pixel = color_pixel.copy()

for y in range(gray_pixel.shape[0]):
  for x in range(gray_pixel.shape[1]):
    gray_pixel[y, x] = np.mean(gray_pixel[y,x])
      # gray_pixel[y,x] 데이터가 r, g, b 세 개의 데이터이므로 평균을 얻을 수 있다.

plt.imshow(gray_pixel)
plt.show()
print(gray_pixel.shape)
  • 출력

이미지 흑백처리하기(2차원 흑백 이미지)

  • 코드
# 흑백 3차원 이미지를 2차원으로 변경
# 3차원이 아니라 2차원 흑백 이미지로 만들어보자.
# 사이즈를 더 줄일 수 있음.

# 이미지 데이터 2차원으로 변경
gray_2d_pixel = gray_pixel[:,:,0]
print(gray_2d_pixel.shape)

# 이미지 출력
plt.imshow(gray_2d_pixel, cmap='gray')
plt.show()
  • 출력


CNN(Convolutional Neural Network)

비정형 데이터의 가장 대표적인 데이터 image. 이를 학습하려면 어떻게 하면 좋다?
-> CNN(Convolutional Neural Network)
합성곱 이라고도 부르고, Convnet(컨브넷) 이라고도 부른다.

DNN 수행 로직

CNN 수행 로직

Convolution 연산

convolution 연산. conv 연산. 합성곱 연산

  • 정의

    f, g 2개의 함수가 있다.
    f를 반전, 전이시켜서 g와 곱한 다음, 그 결과를 적분한다.

이거..? 몰라도 돼.

Image Pixel Data와 Filter의 동작 방식

합성곱 연산을 왜 사용할까?

Filter를 한 번 거치면, 보통은 원본 이미지 데이터의 크기가 줄어든다. 대신 filter를 여러 개 사용하여, 합성곱의 결과 데이터들을 여러 개 얻을 수 있다. 이렇게 만들어진 여러 데이터들을 활용하면, 학습의 결과가 좋아지게 되는 것.


CNN 실습 - colab

모듈 불러오기

  • 코드
# module 불러오기

import numpy as np # numpy 기능
import tensorflow as tf # tensorflow 기능
import matplotlib.pyplot as plt # 그림그리기
import matplotlib.image as img # image 불러오기 위함
  • 출력

없음

도화지 준비

  • 코드
# 그림 그리기

# 도화지 준비
fig = plt.figure(figsize=(10,10)) # 가로세로 크기는 inch단위

# 도화지를 위 아래 두 부분으로 나누기
ax1 = fig.add_subplot(1,2,1) # 행 1, 열 2, 순서 1번째
ax2 = fig.add_subplot(1,2,2) # 행 1, 열 2, 순서 2번째

# 이미지 불러오기
ori_image = img.imread('/content/drive/MyDrive/한국SW산업협회 교육-Java 과정/파이썬 실습/girl-teddy.jpg')
ax1.imshow(ori_image)
  • 출력

이미지 준비

  • 코드
# 이미지 준비

print(ori_image.shape)
  # 출력
  # (429, 640, 3)
  # 가로pixel, 세로pixel, 채널수

# 입력이미지의 형태
# Conv 연산 함수는 4차원 데이터를 요구한다.
# 따라서 3차원이었던 데이터를 4차원으로 변경해야 한다.
# (1, 429, 640, 3) => (이미지 개수, height, width, color)
input_image = ori_image.reshape((1,) + ori_image.shape)
input_image = input_image.astype(np.float32)
print('Convolution input image.shape : {}'.format(input_image.shape))

# 입력이미지 channel 변경
# (1, 429, 640, 1) => (이미지 개수, height, width, color)
# slicing을 이용하여 첫번째 R(Red) 값만 이용
channel_1_input_image = input_image[:,:,:,0:1] # numpy의 slicing 활용
print('Channel 변경 input_image.shape : {}'.format(channel_1_input_image.shape))
  • 출력

Filter data 준비

  • 코드
# filter 준비

# filter
# (3,3,1,1) => (filter height, filter width, filter channel, filter 개수)
# filter의 채널은 원본 이미지의 채널과 항상 동일해야 한다.
#   따라서 세 번째 값이 1이 되도록 만든다.
weight = np.array([[[[-1]],[[0]],[[1]]],
                   [[[-1]],[[0]],[[1]]],
                   [[[-1]],[[0]],[[1]]]])
# -1 값은 크게 의미 없음.
print('적용할 filter shape : {}'.format(weight.shape))
  • 출력

Convolution(합성곱) 결과

  • 코드
# Convolution(합성곱) 결과

conv2d = tf.nn.conv2d(channel_1_input_image,
                      weight,
                      strides=[1,1,1,1],
                      padding='VALID').numpy()
print('Convolution 결과 shape : {}'.format(conv2d.shape))
  # 출력
  #   Convolution 결과 shape : (1, 427, 638, 1)
  #   원본에 비해 2픽셀씩 줄어들었다.
  • 출력

결과출력하기

  • 코드
# 출력하기

# 도화지 준비
fig = plt.figure(figsize=(10,10)) # 가로세로 크기는 inch단위

# 도화지를 위 아래 두 부분으로 나누기
ax1 = fig.add_subplot(1,2,1) # 행 1, 열 2, 순서 1번째
ax2 = fig.add_subplot(1,2,2) # 행 1, 열 2, 순서 2번째

# 이미지 불러오기
ori_image = img.imread('/content/drive/MyDrive/한국SW산업협회 교육-Java 과정/파이썬 실습/girl-teddy.jpg')

t_img = conv2d[0,:,:,:]

ax1.imshow(ori_image)
ax2.imshow(t_img)
fig.tight_layout()
plt.show()
  • 출력


합성곱연산(Convolution)

이미지의 특징을 뽑아내서 학습에 좋은 이미지를 만드는 것!
이 때, Filter(kernel 이라고도 함) 에 따라 달라지고, 여러 개의 Filter를 사용하게 되면, 이미지 원본 1개에서 특징만 추출한 이미지 여러 개를 만들 수 있다.

다만, 잘못하면 너무 많은 양의 데이터가 생성된다. (이미지 사이즈가 약간 줄어들긴 하지만...)
-> 이 문제를 해결하기 위해 Image Size를 줄인다.
그리고 이 역할을 담당하는 게 바로 Pooling Layer다.
CNN에서 가장 많이 사용하는 것은 MAX pooling 이다.

Filter의 중요성

filter가 좋아서, 특징을 잘 뽑아내는 filter를 사용할 경우 더 좋은 결과값을 얻을 것이다. 따라서 가장 좋은 결과값을 얻기 위해 filter를 끊임없이 변경시킨다.
loss계산을 마치고 다시 반복하려 할 때, filter값을 변경시킨다.

우리가 학습을 통해서 갱신시키고, 우리가 얻으려고 하는 값이 바로 filter의 weight 값이다

weight = np.array([[[[-1]],[[0]],[[1]]],
                   [[[-1]],[[0]],[[1]]],
                   [[[-1]],[[0]],[[1]]]])

MAX pooling

Feature map

feature map : image에서 filter를 거쳐서, 특징을 뽑아낸 이미지

MAX pooling 실습

  • 코드
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import matplotlib.image as img

fig = plt.figure(figsize=(10,10))  # 가로세로 크기 inch단위

ax1 = fig.add_subplot(1,3,1)
ax2 = fig.add_subplot(1,3,2)
ax3 = fig.add_subplot(1,3,3)

ori_image = img.imread('/content/drive/MyDrive/한국SW산업협회 교육-Java 과정/파이썬 실습/girl-teddy.jpg')

# 첫 번째 그림판에는 이미지 원본 출력
ax1.imshow(ori_image)

# 입력이미지의 형태
# (1, 429, 640, 3) => (이미지 개수, height, width, color)
input_image = ori_image.reshape((1,) + ori_image.shape)
input_image = input_image.astype(np.float32)
print('Convolution input image.shape : {}'.format(input_image.shape))

# 입력이미지 channel 변경
# (1, 429, 640, 1) => (이미지 개수, height, width, color)
# slicing을 이용하여 첫번째 R(Red) 값만 이용
channel_1_input_image = input_image[:,:,:,0:1]
print('Channel 변경 input_image.shape : {}'.format(channel_1_input_image.shape))


# filter
# (3,3,1,1) => (filter height, filter width, filter channel, filter 개수)
# weight = np.random.rand(3,3,1,1)
weight = np.array([[[[-1]],[[0]],[[1]]],
                   [[[-1]],[[0]],[[1]]],
                   [[[-1]],[[0]],[[1]]]])
print('적용할 filter shape : {}'.format(weight.shape))

# stride : 1 (가로1, 세로1)
# padding = 'VALID'

conv2d = tf.nn.conv2d(channel_1_input_image,
                      weight,
                      strides=[1,1,1,1],
                      padding='VALID').numpy()
t_img = conv2d[0,:,:,:]
# 2번째 그림판에 convolution한 이미지(특징을 뽑아낸) 출력
ax2.imshow(t_img)


## pooling 처리 ##

# ksize = pooling filter의 크기
pool = tf.nn.max_pool(conv2d, 
                      ksize=[1,3,3,1],
                      strides=[1,3,3,1], 
                      padding='VALID').numpy()
t_img = pool[0,:,:,:]
# 3번째 그림판에 pooling한 이미지(크기를 줄인) 출력
ax3.imshow(t_img)


fig.tight_layout()
plt.show()

# 여기서 나온 conv2d, pool 설정 코드들은 실제로는 사용되지 않는다.
# 설명을 위해서 명시해본 것.
  • 출력


러닝 정확도 비교

공통 코드

  • 코드
### 공통 코드 - 데이터 만들기

# module 불러오기
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split # train 데이터와 test 데이터를 분리하기 위함
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping # 작업 도중 조기 종료시키기

# Raw Data Loading
df = pd.read_csv('/content/drive/MyDrive/한국SW산업협회 교육-Java 과정/파이썬 실습/mnist-train.csv')
display(df.head(), df.shape)
  # 출력
  #   data frame 5 rows × 785 columns
  #   (42000, 785)
# 우리 데이터는 샘플로 제공된 거라서 결측치, 이상치가 없다.
# 실제로 할 때는 결측치, 이상치 처리를 반드시 해야 한다.

# 데이터 나누기
x_data_train, x_data_test, t_data_train, t_data_test = \
train_test_split(df.drop('label', axis=1, inplace=False),
                 df['label'],
                 test_size=0.3)

# 정규화 진행
scaler = MinMaxScaler()
scaler.fit(x_data_train)
x_data_train_norm = scaler.transform(x_data_train)
x_data_test_norm = scaler.transform(x_data_test)
  • 출력


첫 번째(Multinomial Classification) - 학습

  • 코드
### 첫 번째 Model : Multinomial Classification(머신러닝)

model_1 = Sequential()

model_1.add(Flatten(input_shape=(784,)))
model_1.add(Dense(10, activation='softmax'))

model_1.compile(optimizer=Adam(learning_rate=1e-4),
                loss='sparse_categorical_crossentropy',
                metrics=['accuracy']) # 정확도를 근간으로 우리 모델을 평가

early_stopping = EarlyStopping(monitor='val_loss',
                               patience=3, # loss값이 떨어지지 않는 경우 몇 번이나 참을지 설정
                               verbose=1, # 중간 결과값 화면에 출력
                               mode='auto', # 정해져있는 값이니 그냥 auto
                               restore_best_weights=True) # 최적의 값을 얻었을 때 그 값 저장해두기

model_1.fit(x_data_train_norm,
            t_data_train,
            epochs=2000,
            validation_split=0.2,
            verbose=1,
            batch_size=100,
            callbacks=[early_stopping]) # early_stopping값 적용시키기

# 출력
  # Epoch 153/2000
  # 217/236 [==========================>...] - ETA: 0s - loss: 0.2379 - accuracy: 0.9323Restoring model weights from the end of the best epoch: 150.
  # 236/236 [==============================] - 1s 3ms/step - loss: 0.2351 - accuracy: 0.9334 - val_loss: 0.2908 - val_accuracy: 0.9189
  # Epoch 153: early stopping
  # <keras.callbacks.History at 0x7f51fa9201f0>
  • 출력

첫 번째(Multinomial Classification) - 평가

  • 코드
### 첫 번째 Model => Multinomial Classification(머신러닝)
# 평가

print(model_1.evaluate(x_data_test_norm, t_data_test))
# 출력
  # 394/394 [==============================] - 1s 2ms/step - loss: 0.2813 - accuracy: 0.9222
  # [0.28126806020736694, 0.9222221970558167]
  • 출력


두 번째(DNN) - 학습

  • 코드
### 두 번째 Model : DNN(딥러닝)

model_2 = Sequential()

# input layer
model_2.add(Flatten(input_shape=(784,)))

# hidden layer 추가
# node의 개수는 아무거나 적음. 물론, 더 효과적인 개수에 대해 정리된 것도 있음.
model_2.add(Dense(64, activation='relu'))
model_2.add(Dense(128, activation='relu'))
model_2.add(Dense(32, activation='relu'))

# output layer
model_2.add(Dense(10, activation='softmax'))

model_2.compile(optimizer=Adam(learning_rate=1e-4),
                loss='sparse_categorical_crossentropy',
                metrics=['accuracy']) # 정확도를 근간으로 우리 모델을 평가

early_stopping = EarlyStopping(monitor='val_loss',
                               patience=3, # loss값이 떨어지지 않는 경우 몇 번이나 참을지 설정
                               verbose=1, # 중간 결과값 화면에 출력
                               mode='auto', # 정해져있는 값이니 그냥 auto
                               restore_best_weights=True) # 최적의 값을 얻었을 때 그 값 저장해두기

model_2.fit(x_data_train_norm,
            t_data_train,
            epochs=2000,
            validation_split=0.2,
            verbose=1,
            batch_size=100,
            callbacks=[early_stopping]) # early_stopping값 적용시키기

# 출력
  # Epoch 49/2000
  # 231/236 [============================>.] - ETA: 0s - loss: 0.0462 - accuracy: 0.9884Restoring model weights from the end of the best epoch: 46.
  # 236/236 [==============================] - 1s 4ms/step - loss: 0.0464 - accuracy: 0.9884 - val_loss: 0.1412 - val_accuracy: 0.9597
  # Epoch 49: early stopping
  # <keras.callbacks.History at 0x7f5244a2c4f0>
  • 출력

두 번째(DNN) - 평가

  • 코드
### 두 번째 Model : DNN(딥러닝)
# 평가

print(model_2.evaluate(x_data_test_norm, t_data_test))
# 출력
  # 394/394 [==============================] - 1s 2ms/step - loss: 0.1410 - accuracy: 0.9592
  # [0.14098674058914185, 0.9592063426971436]

# 결과 비교
# 첫 번째 : 0.922
# 두 번째 : 0.959
  • 출력


세 번째(CNN) - 학습

  • 코드
### 세 번째 Model : CNN(딥러닝)

from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dropout
  # Conv2D : conv 계산 후 relu 돌리는 레이어
  # MaxPooling2D : Max Pooling
  # Dropout : 과적합을 피할 수 있게 해주는 것

model_3 = Sequential()

## Feature Extraction(Convolution 처리)
# convolution
model_3.add(Conv2D(filters=32,
                   kernel_size=(3, 3),
                   activation='relu',
                   input_shape=(28, 28, 1)))
  # filters=32 : filter의 개수
  #   이를 통해, 원본 데이터 1개 당 32개의 변형 데이터를 얻을 수 있다.
  # kernel_size=(3,3) : filter(kernel)의 행렬 크기
  # input_shape=(28, 28, 1)
  #   첫 번째 input은 ㅁ 와 ㅁㅁㅁㅁ 가 합쳐진다.
  #   이미지 한 개의 shape을 적으면 된다.
  #   28 x 28 사이즈, 채널은 1개짜리

# pooling
model_3.add(MaxPooling2D(pool_size=(2, 2)))
  # pool_size=(2, 2) : pooling하는 필터 크기

# 위 내용(conv, pooling)을 원하는 대로 반복
# convolution
model_3.add(Conv2D(filters=64,
                   kernel_size=(3, 3),
                   activation='relu'))

# pooling
model_3.add(MaxPooling2D(pool_size=(2, 2)))

# convolution
model_3.add(Conv2D(filters=64,
                   kernel_size=(3, 3),
                   activation='relu'))

# input layer
# 이번에는 input_shape을 고정적으로 잡지 않는다.
#   앞단계 설정에 따라 몇 개의 input이 들어올 지 알 수 없기 때문
model_3.add(Flatten())

# hidden layer 추가
# node의 개수는 아무거나 적음. 물론, 더 효과적인 개수에 대해 정리된 것도 있음.
model_3.add(Dense(128, activation='relu'))

# output layer
model_3.add(Dense(10, activation='softmax'))

model_3.compile(optimizer=Adam(learning_rate=1e-4),
                loss='sparse_categorical_crossentropy',
                metrics=['accuracy']) # 정확도를 근간으로 우리 모델을 평가

early_stopping = EarlyStopping(monitor='val_loss',
                               patience=3, # loss값이 떨어지지 않는 경우 몇 번이나 참을지 설정
                               verbose=1, # 중간 결과값 화면에 출력
                               mode='auto', # 정해져있는 값이니 그냥 auto
                               restore_best_weights=True) # 최적의 값을 얻었을 때 그 값 저장해두기



# CNN에는 여러 장의 이미지가 들어가기 때문에, 반드시 4차원 데이터를 넣어줘야 한다.
# 따라서 기존에 2차원이었던 데이터 x_data_train_norm 를 4차원으로 바꿔서 사용해야 한다.
model_3.fit(x_data_train_norm.reshape(-1, 28, 28, 1),
            t_data_train,
            epochs=2000,
            validation_split=0.2,
            verbose=1,
            batch_size=100,
            callbacks=[early_stopping]) # early_stopping값 적용시키기

# 출력
  # Epoch 27/2000
  # 236/236 [==============================] - ETA: 0s - loss: 0.0291 - accuracy: 0.9905Restoring model weights from the end of the best epoch: 24.
  # 236/236 [==============================] - 1s 6ms/step - loss: 0.0291 - accuracy: 0.9905 - val_loss: 0.0551 - val_accuracy: 0.9827
  # Epoch 27: early stopping
  # <keras.callbacks.History at 0x7f5244b457c0>
  • 출력

세 번째(CNN) - 평가

  • 코드
### 세 번째 Model : CNN(딥러닝)
# 평가

print(model_3.evaluate(x_data_test_norm.reshape(-1, 28, 28, 1),
                       t_data_test))
# 출력
  # 394/394 [==============================] - 1s 3ms/step - loss: 0.0534 - accuracy: 0.9836
  # [0.05337640270590782, 0.9835714101791382]

# 결과 비교
# 첫 번째 : 0.922
# 두 번째 : 0.959
# 세 번째 : 0.984
  • 출력


CNN 정리

CNN을 이용해서 Model을 학습하면, Image 학습, 예측에 좋은 결과를 얻을 수 있다.
우리가 배운 내용

  • 데이터는 어떠한 형태로 입력해야 할까?

  • Model은 어떻게 만들까?
    -> keras 이용하기

  • Model 학습, 평가하기
    -> keras 이용하기

  • 그러면, 실사 데이터를 이용해서 학습 & 예측하려면 어떻게 해야할까?
    많은 양의 실사 이미지 모으기 / 라벨링 / 사이즈 균일하게 리사이징

이러한 번거로움을 줄이기 위한 방법이 전이학습 이다.

profile
배우는 중

0개의 댓글