Data Augmentation (데이터 증강)

5단 분석법

순서
분석
단어
내용
1
일반 명사
데이터
자료, 문자, 숫자, 소리, 그림, 영상, 단어 등의 형태로 된 의미 단위
증강
수나 양을 늘려 더 강하게 함
이미지 증강
자료의 수나 양을 늘려서 더 강하게 함
2
고유 명사
이미지 증강
기계 학습을 위해 새로운 데이터를 첨가하거나, 수를 늘리는 기법
3
사용 이유
이미지 증강
모델 학습에 필요한 데이터의 다양성과 양을 증가시켜 과적합을 방지하고, 일반화 성능을 향상시키기 위해서
4
사용 방법
이미지 증강
1. 이미지 회전 2. 이미지 뒤집기 3. 이미지 이동 4. 이미지 확대/축소 5. 색상 변형 6. 노이즈 추가
5
다른 기술과의 비교
이미지 증강
-

정의

일반 명사

데이터
자료, 문자, 숫자, 소리, 그림, 영상, 단어 등의 형태로 된 의미 단위
증강
수나 양을 늘려 더 강하게 함
데이터 증강
자료의 수나 양을 늘려서 더 강하게 함
데이터는 문자, 숫자, 소리, 그림, 영상, 단어 등의 형태로 된 의미 단위 즉, 자료를 뜻합니다.
증강은 수나 양을 늘려 더 강하게 하는 것을 말합니다.
데이터 증강은 자료의 수나 양을 늘려서 더 강하게 한다는 의미로 해석할 수 있습니다.
고유명사를 살펴볼까요?

고유 명사

이미지 증강
기계 학습을 위해 새로운 데이터를 첨가하거나, 수를 늘리는 기법
데이터 증강은 기계 학습을 위해 새로운 데이터를 첨가하거나, 수를 늘리는 기법입니다.
데이터 증강에는 다양한 기법들이 존재합니다. GAN을 통해 데이터 증강을 설명하도록 하겠습니다.

GAN (Generative Adversarial Networks)

항목
설명
모델
GAN (Generative Adversarial Network)
구성 요소
위조자 (Generator), 판별자 (Discriminator)
위조자 역할
가짜 이미지를 생성 (가짜 지폐를 만드는 사람)
판별자 역할
입력된 이미지가 진짜인지 가짜인지 구별 (지폐 감별기)
목표
위조자: 판별자를 속일 만큼 진짜 같은 가짜 이미지 생성 판별자: 진짜와 가짜 이미지를 정확하게 구별
과정
- 위조자: 처음에 무작위로 이미지 생성 - 판별자: 진짜와 가짜 이미지를 구별 - 반복 학습: 위조자는 더 정교한 가짜 이미지를 생성, 판별자는 이를 구별하는 능력 향상 - 결과: 매우 현실적인 가짜 이미지 생성
데이터 중요성
딥 러닝에서 양질의 데이터 수집 중요, 데이터 증강은 유용하지만 실제 데이터와 동일하지 않음
데이터 증강
데이터셋이 적을 때 유용하나, 실제 데이터와 동일하지 않아 많이 사용되지는 않음
기호
의미
설명
z
노이즈 (Noise)
위조자가 가짜 이미지를 생성할 때 사용하는 임의의 입력 값
G
위조자 (Generator)
노이즈 z를 받아 가짜 이미지를 생성하는 모델
G(z)
가짜 이미지 (Fake Money)
위조자가 생성한 가짜 이미지. 위조자가 노이즈 z를 입력받아 생성한 결과물
x
진짜 이미지 (Real Money)
실제 데이터, 즉 진짜 이미지. 판별자가 이를 입력받아 가짜 이미지와 비교하게 됨
D
판별자 (Discriminator)
입력된 이미지가 진짜인지 가짜인지 구별하는 모델
D(G(z)) : 0
판별자가 가짜 이미지(G(z))를 가짜로 인식
판별자가 위조자가 생성한 가짜 이미지를 입력받았을 때, 이를 가짜(0)로 판별함
D(x) : 1
판별자가 진짜 이미지(x)를 진짜로 인식
판별자가 실제 이미지를 입력받았을 때, 이를 진짜(1)로 판별함
이 그림은 GAN의 개념과 작동 원리를 간략하게 정리한 것입니다.
두 개의 신경망이 서로 경쟁하면서 실제 같은 데이터를 생성하는 모델입니다.
GAN을 쉽게 이해하려면 위조자와 판별자가 있고 계속 체크하는 방식이라고 생각하시면 됩니다.
위조자는 가짜 이미지를 생성하는 역할을 합니다.
예를 들어, 위조자는 가짜 지폐를 만드는 사람이라고 생각할 수 있습니다.
위조자의 목표는 판별자가 가짜 지폐를 진짜 지폐로 착각하게 만드는 것입니다.
판별자는 입력된 이미지가 진짜인지 가짜인지 구별하는 역할을 합니다.
예를 들어, 판별자는 은행의 지폐 감별기라고 할 수 있습니다.
판별자의 목표는 진짜 지폐와 가짜 지폐를 정확하게 구별해내는 것입니다.
위조자는 처음에 무작위로 지폐를 생성합니다.
이 지폐는 대부분 판별기에 의해 쉽게 가짜로 판별됩니다.
하지만 위조자는 판별기가 속도록 지폐를 점점 더 정교하게 만들기 위해 학습합니다.
판별자는 진짜 지폐와 위조자가 만든 가짜 지폐를 모두 받습니다.
판별자는 이 지폐가 진짜인지 가짜인지 구별하도록 학습합니다.
위조자가 만든 가짜 지폐와 진짜 지폐가 섞여 판별기로 들어갑니다.
판별자는 이를 구별하려 하고, 위조자는 판별자를 속이기 위해 더 진짜 같은 가짜 지폐를 만듭니다.
이 과정이 반복되면서 위조자는 점점 더 정교한 가짜 지폐를 만들고, 판별자는 이를 구별하는 능력을 향상시킵니다.
이러한 경쟁을 통해 위조자는 판별자를 속일 수 있을 만큼 진짜 같은 가짜 이미지를 생성하게 됩니다.
판별자 역시 진짜와 가짜를 구별하는 능력이 점점 더 좋아집니다.
이 과정에서 위조자가 만들어낸 이미지는 매우 현실적인 수준에 이르게 됩니다.
이처럼 GAN은 위조자와 판별자가 서로 경쟁하면서 실제 같은 데이터를 생성하는 모델입니다.
딥 러닝에서 제일 중요한 것은 양질의 데이터를 최대한 많이 수집해서, 좋은 모델을 만들어내는 것입니다.
데이터 증강을 하게되면 데이터셋의 양을 늘리는 데 도움이 되는 것은 분명하지만, 실제 데이터와 100% 동일한 형식을 가진 데이터가 생기는 것은 아니기 때문에 실제로는 많이 사용하지 않는 기법입니다.
하지만, 데이터셋의 수가 너무 적은 상황에서는 충분히 시도해볼만한 가치가 있는 기법인 것은 분명합니다.

사용 이유

데이터 증강
모델 학습에 필요한 데이터의 다양성과 양을 증가시켜 과적합을 방지하고, 일반화 성능을 향상시키기 위해서
이유
내용
데이터 다양성 증가
모델이 다양한 상황에 대해 잘 일반화할 수 있도록 다양한 형태의 데이터를 제공합니다.
과적합 방지
모델이 훈련 데이터에 과적합* 되지 않도록 도와줍니다. 이는 모델이 새로운 데이터에 대해서도 좋은 성능을 보이도록 합니다.
일반화 성능 향상
다양한 변형된 데이터를 학습함으로써 모델이 새로운 데이터에 대해 잘 대응할 수 있도록 합니다.
데이터 부족 문제 해결
실제 데이터가 부족한 상황에서 증강 기법을 통해 더 많은 데이터를 확보할 수 있습니다.
모델의 견고성 향상
증강된 데이터로 학습한 모델은 노이즈나 변형된 데이터에도 잘 대응할 수 있게 됩니다.

사용 방법

데이터 증강
1. 이미지 회전 2. 이미지 뒤집기 3. 이미지 이동 4. 이미지 확대/축소 5. 색상 변형 6. 노이즈 추가

1. 랜덤 이미지 생성 및 표시

from PIL import Image # 이미지를 생성하고 조작하기 위한 라이브러리 import numpy as np # 배열 및 행렬 연산을 위한 라이브러리 def create_random_image(size=(100, 100)): return Image.fromarray(np.random.randint(0, 256, size + (3,), dtype=np.uint8)) def show_image(image, title="Image"): import matplotlib.pyplot as plt # 함수 내부에서 import하여 필요할 때만 로드 plt.imshow(image) plt.title(title) plt.axis('off') plt.show() image = create_random_image() # create_random_image((200, 200)) show_image(image, "Random Image")
Python
복사
create_random_image 함수:
(100, 100) 크기의 랜덤 RGB 이미지를 생성합니다.
np.random.randint를 사용하여 0부터 255 사이의 랜덤 값을 생성하고, 이를 RGB 배열로 만듭니다.
Image.fromarray를 사용하여 NumPy 배열을 PIL 이미지로 변환합니다.
show_image 함수:
matplotlib를 사용하여 이미지를 화면에 표시합니다.
이미지의 제목과 축을 비활성화하여 이미지를 깔끔하게 표시합니다.
image 변수에 랜덤 이미지를 생성하고, 이를 화면에 표시합니다.
numpy 배열(N-dimensional array)이 무엇인가요? 파이썬에도 리스트가 있는데 왜 사용해야할까요?
NumPy 라이브러리에서 제공하는 다차원 배열 객체입니다. numpy 배열을 사용하는 이유는 아래와 같습니다. 1. 속도: NumPy 배열은 리스트보다 훨씬 빠릅니다. 2.메모리 효율성: NumPy 배열은 메모리를 더 효율적으로 사용합니다. 동일한 데이터 타입의 요소들이 연속적인 메모리 블록에 저장되기 때문에, 메모리 접근 속도가 빨라지고, 메모리 사용량이 줄어듭니다. 3. 벡터화 연산: NumPy 배열은 벡터화 연산을 지원하여, 루프를 사용하지 않고도 배열 전체에 대한 연산을 한 번에 수행할 수 있습니다. 이는 코드의 가독성과 실행 속도를 모두 향상시킵니다. 4. 풍부한 기능 : NumPy는 수학 함수, 선형 대수, 난수 생성, 푸리에 변환 등 많은 기능을 제공합니다. 5. 브로드캐스팅: NumPy는 배열 간의 크기가 다른 경우에도 자동으로 크기를 맞춰서 연산을 수행하는 브로드캐스팅을 지원합니다. 6. 다른 라이브러리와의 통합: 많은 데이터 과학 및 기계 학습 라이브러리(예: Pandas, Scikit-learn, TensorFlow 등)가 NumPy 배열을 기본 데이터 구조로 사용하여, 이들 라이브러리와의 통합이 용이합니다. 추가 설명 : 링크

2. 이미지 회전

def rotate_image(image, angle): return image.rotate(angle) rotated_image = rotate_image(image, 45) show_image(rotated_image, "Rotated Image")
Python
복사
rotate_image 함수:
주어진 이미지를 특정 각도로 회전시킵니다.
rotate 메서드는 이미지를 주어진 각도만큼 시계 방향으로 회전시킵니다.
rotated_image 변수에 원본 이미지를 45도 회전시킨 이미지를 저장하고, 이를 화면에 표시합니다.

3. 이미지 뒤집기

from PIL import ImageOps def flip_image(image, direction): if direction == 'horizontal': return ImageOps.mirror(image) elif direction == 'vertical': return ImageOps.flip(image) flipped_image = flip_image(image, 'horizontal') show_image(flipped_image, "Flipped Image")
Python
복사
flip_image 함수:
이미지를 가로 또는 세로로 뒤집습니다.
ImageOps.mirror는 이미지를 좌우 대칭으로 뒤집습니다.
ImageOps.flip는 이미지를 상하 대칭으로 뒤집습니다.
flipped_image 변수에 원본 이미지를 가로로 뒤집은 이미지를 저장하고, 이를 화면에 표시합니다.
코랩으로 보기 : link iconGoogle Colab

4. 이미지 이동

def translate_image(image, x, y): array = np.array(image) # np.array() 입력 데이터를 NumPy 배열로 변환 translated_array = np.roll(array, shift=(y, x), axis=(0, 1)) # shift=(y, x): 이미지를 x축 방향으로 30픽셀, y축 방향으로 50픽셀 이동, # axis=(0, 1) : 기준 축을 0,1로 이동 return Image.fromarray(translated_array) translated_image = translate_image(image, 50, 30) show_image(translated_image, "Translated Image")
Python
복사
translate_image 함수:
이미지를 주어진 x, y 값만큼 평행 이동시킵니다.
np.array() 입력 데이터를 NumPy 배열로 변환
이미지는 보통 행렬(픽셀 값) 형태로 표현되며, NumPy 배열로 변환하면 각 픽셀 값을 행렬 형태로 다룰 수 있게 됩니다. 이 예제에서 image는 PIL 이미지 객체이고, np.array(image)는 이미지를 NumPy 배열로 변환한 것입니다.
np.roll 함수는 배열을 지정된 축을 따라 이동시킵니다.
array: 이동할 원본 배열입니다.
shift: 각 축에 대해 이동할 요소의 수입니다. 단일 값이나 튜플로 지정할 수 있습니다.
단일 값일 경우, 모든 축에 대해 동일한 크기로 이동합니다.
튜플로 지정할 경우, 각 축마다 다른 크기로 이동할 수 있습니다.
axis: 이동할 축을 지정합니다. 단일 축이나 튜플로 지정할 수 있습니다.
단일 축일 경우, 해당 축만 이동합니다.
튜플로 지정할 경우, 각 축마다 지정된 크기로 이동할 수 있습니다.
translated_image 변수에 원본 이미지를 (x=50, y=30) 만큼 이동시킨 이미지를 저장하고, 이를 화면에 표시합니다.
코랩으로 보기 : link iconGoogle Colab
shift = (x, y)가 아닌 shift = (y, x)로 되어있는 이유가 있나요?
shift(y, x)로 되어있는 이유는 np.roll 함수가 배열의 첫 번째 축을 행(y)으로, 두 번째 축을 열(x)로 처리하기 때문입니다.

5. 이미지 크기 조정

def resize_image(image, scale): width, height = image.size return image.resize((int(width * scale), int(height * scale))) print(f"Original Image Size: {original_image.size}") resized_image = resize_image(original_image, 1.5) print(f"Resized Image Size: {resized_image.size}") show_image(resized_image, "Resized Image")
Python
복사
resize_image 함수:
이미지를 주어진 비율로 크기를 조정합니다.
image.size는 이미지의 현재 크기를 반환합니다.
resize 메서드는 새로운 크기로 이미지를 변경합니다.
resized_image 변수에 원본 이미지를 1.5배 확대시킨 이미지를 저장하고, 이를 화면에 표시합니다.
코랩으로 보기 : link iconGoogle Colab

6. 이미지 밝기 조절

from PIL import ImageEnhance # PIL(Python Imaging Library)은 파이썬에서 이미지를 처리하기 위한 라이브러리 def change_brightness(image, factor): enhancer = ImageEnhance.Brightness(image) return enhancer.enhance(factor) brightened_image = change_brightness(image, 1.5) show_image(brightened_image, "Brightened Image")
Python
복사
change_brightness 함수:
이미지의 밝기를 조절합니다.
ImageEnhance.Brightness는 밝기 조절 객체를 생성합니다.
enhance 메서드는 주어진 배율로 밝기를 조절합니다.
brightened_image 변수에 원본 이미지의 밝기를 1.5배로 조절한 이미지를 저장하고, 이를 화면에 표시합니다.
코랩으로 보기 : link iconGoogle Colab

7. 이미지에 노이즈 추가

def add_noise(image): array = np.array(image) noise = np.random.normal(0, 25, array.shape).astype(np.uint8) # 0 : 노이즈의 평균값, 25: 노이즈의 평균편차 noisy_image = np.clip(array + noise, 0, 255).astype(np.uint8) return Image.fromarray(noisy_image) # 노이즈가 추가된 배열을 다시 이미지 객체로 변환하여 반환합니다. noisy_image = add_noise(image) # 노이즈가 추가된 이미지를 화면에 표시합니다. show_image(noisy_image, "Noisy Image")
Python
복사
add_noise 함수:
이미지에 랜덤한 노이즈를 추가합니다.
np.random.normal은 주어진 평균과 표준 편차를 사용하여 정규 분포의 노이즈를 생성합니다.
np.clip은 값이 0에서 255 사이로 제한되도록 합니다.
이는 이미지의 픽셀 값이 유효한 범위(0-255)를 벗어나지 않도록 하기 위함입니다.
noisy_image 변수에 원본 이미지에 노이즈를 추가한 이미지를 저장하고, 이를 화면에 표시합니다.
코랩으로 보기 : link iconGoogle Colab
uint8이 무엇인가요?
0에서 255까지의 양의 정수를 나타내는 8비트 부호 없는 정수입니다. uint8은 unsigned 8-bit integer의 약자입니다.
np.random.normal() 이 무엇인가요?
np.random.normal()은 정규 분포를 따르는 랜덤 값을 생성하는 함수입니다. 이 함수는 평균과 표준편차를 기반으로 랜덤 값을 생성합니다. 이미지에 노이즈를 추가할 때, 이 랜덤 값을 픽셀 값(RGB값)에 더하여 노이즈를 만드는 데 사용됩니다.
정규분포 예시
참고 : 이미지는 보통 RGB (빨강, 초록, 파랑) 값으로 구성된 픽셀들의 모음으로 이루어져 있습니다. 각 픽셀은 특정한 RGB 값을 가지며, 이 값은 0에서 255 사이의 정수로 표현됩니다.
참고 : 정규 분포 생성 코드

Google Colab

알면 좋은 정보

데이터증강을 데이터셋이 풍부할 때 많이 하나요?
데이터 증강(data augmentation)은 주로 데이터의 양이 부족할 때 사용하는 기법입니다. 데이터 증강을 통해 모델이 다양한 상황을 학습할 수 있도록 도와줍니다. 하지만 데이터의 양이 이미 충분하다면, 데이터 증강이 오히려 데이터셋의 질을 낮출 수 있습니다. 이는 다음과 같은 이유 때문입니다:
1.
노이즈 증가: 데이터 증강 과정에서 불필요한 노이즈가 추가될 수 있습니다. 이는 모델이 학습해야 하는 중요한 특징을 혼란스럽게 할 수 있습니다.
2.
중복 데이터: 데이터 증강이 잘못 사용되면, 원본 데이터의 변형된 형태가 중복되어 데이터셋에 추가될 수 있습니다. 이는 모델이 같은 데이터를 여러 번 학습하게 만들어 일반화 성능을 떨어뜨릴 수 있습니다.
3.
불필요한 변형: 모든 데이터 증강 기법이 항상 긍정적인 효과를 주는 것은 아닙니다. 특정 증강 기법이 데이터의 본질적인 특징을 왜곡시킬 수 있습니다.
따라서, 데이터의 양이 풍부하고 질이 좋은 경우에는 데이터 증강이 필요하지 않을 수 있습니다. 대신 데이터의 질을 높이는 데 집중하는 것이 더 바람직할 수 있습니다. 예를 들어, 데이터 클리닝, 이상치 제거, 고품질 데이터 수집 등이 포함됩니다.
결론적으로, 데이터 증강의 필요성은 데이터셋의 양과 질에 따라 다르며, 항상 그 효과를 신중하게 평가해야 합니다.

미니퀘스트

1번 미니퀘스트 - 이미지 데이터 증강 실습

주피터 랩에서 Python과 Pillow를 사용하여 이미지 회전, 뒤집기, 이동, 확대/축소, 색상 변형, 노이즈 추가를 해보세요.

문제 설명

1.
필요한 라이브러리 설치 및 불러오기
2.
이미지 불러오기
3.
이미지 증강 기법 적용

코드

# 1. 필요한 라이브러리 설치 및 불러오기 from PIL import Image, ImageEnhance, ImageOps import numpy as np import matplotlib.pyplot as plt # 2. 이미지 불러오기 image_path = 'Lenna.jpg' # 이미지 경로를 입력하세요 image = Image.open(image_path) # 3. 이미지 증강 기법 적용 # 이미지 회전 def rotate_image(image, angle): return image.rotate(angle) # 이미지 뒤집기 def flip_image(image, direction): if direction == 'horizontal': return ImageOps.mirror(image) elif direction == 'vertical': return ImageOps.flip(image) # 이미지 이동 (이미지 크기 변경 없이 이동 효과를 위해 배경 추가) def translate_image(image, x, y): array = np.array(image) translated = np.roll(array, shift=(y, x), axis=(0, 1)) return Image.fromarray(translated) # 이미지 확대/축소 def resize_image(image, scale): width, height = image.size return image.resize((int(width * scale), int(height * scale))) # 색상 변형 def change_brightness(image, factor): enhancer = ImageEnhance.Brightness(image) return enhancer.enhance(factor) # 노이즈 추가 def add_noise(image): array = np.array(image) noise = np.random.normal(0, 25, array.shape) noisy_image = np.clip(array + noise, 0, 255).astype(np.uint8) return Image.fromarray(noisy_image) # 증강된 이미지들 보여주기 fig, ax = plt.subplots(2, 3, figsize=(15, 10)) ax[0, 0].imshow(rotate_image(image, 45)) ax[0, 0].set_title("Rotated Image") ax[0, 1].imshow(flip_image(image, 'horizontal')) ax[0, 1].set_title("Flipped Image") ax[0, 2].imshow(translate_image(image, 50, 30)) ax[0, 2].set_title("Translated Image") ax[1, 0].imshow(resize_image(image, 1.5)) ax[1, 0].set_title("Resized Image") ax[1, 1].imshow(change_brightness(image, 1.5)) ax[1, 1].set_title("Brightness Changed") ax[1, 2].imshow(add_noise(image)) ax[1, 2].set_title("Noisy Image") plt.tight_layout() plt.show()
Python
복사

결과 설명

Rotated Image
이미지를 45도 회전한 결과입니다. 원본 이미지에서 새로운 각도로 변형된 데이터를 얻을 수 있습니다.
Flipped Image
이미지를 수평으로 뒤집은 결과입니다. 원본 이미지의 좌우가 반전된 데이터를 생성합니다.
Translated Image
이미지를 x축으로 50픽셀, y축으로 30픽셀 이동한 결과입니다. 이미지의 위치를 변경하여 새로운 데이터를 만듭니다.
Resized Image
이미지를 1.5배 확대한 결과입니다. 원본 이미지의 크기를 변경하여 다양한 크기의 데이터를 얻습니다.
Brightness Changed
이미지의 밝기를 1.5배 증가시킨 결과입니다. 이미지의 밝기를 변형하여 다양한 조명 조건을 모방합니다.
Noisy Image
이미지에 노이즈를 추가한 결과입니다. 노이즈가 추가된 데이터를 통해 모델이 노이즈에 강인한 성능을 갖추도록 합니다.

코드 설명

2번 미니퀘스트 - 이미지 증강을 활용한 모델 성능 향상

주피터 랩에서 Python과 TensorFlow를 사용해 데이터셋을 증강하여 더 많은 학습 데이터를 생성하고, 이를 활용해 모델을 학습시켜 보세요.

문제 설명

1.
필요한 라이브러리 설치 및 불러오기
2.
데이터셋 불러오기 및 증강
3.
모델 생성 및 학습
4.
모델 평가

코드

# 1. 필요한 라이브러리 설치 및 불러오기 import tensorflow as tf from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras import layers, models # 2. 데이터셋 불러오기 및 증강 (train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.cifar10.load_data() # 데이터 증강을 위한 ImageDataGenerator 설정 datagen = ImageDataGenerator( rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, horizontal_flip=True, brightness_range=[0.8, 1.2], zoom_range=0.2 ) # 데이터셋 준비 train_images = train_images.astype('float32') / 255.0 test_images = test_images.astype('float32') / 255.0 # 3. 모델 생성 및 학습 model = models.Sequential([ layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)), layers.MaxPooling2D((2, 2)), layers.Conv2D(64, (3, 3), activation='relu'), layers.MaxPooling2D((2, 2)), layers.Conv2D(64, (3, 3), activation='relu'), layers.Flatten(), layers.Dense(64, activation='relu'), layers.Dense(10, activation='softmax') ]) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 증강된 데이터를 사용하여 모델 학습 train_generator = datagen.flow(train_images, train_labels, batch_size=64) model.fit(train_generator, epochs=10, validation_data=(test_images, test_labels)) # 4. 모델 평가 test_loss, test_acc = model.evaluate(test_images, test_labels) print(f'Test accuracy: {test_acc}')
Python
복사

결과 설명

데이터 증강
1.
데이터 증강 기법
회전
이미지를 최대 40도 회전시켜 다양한 각도의 데이터를 생성했습니다.
이동
이미지를 좌우로 최대 20%, 상하로 최대 20% 이동시켜 다양한 위치의 데이터를 생성했습니다.
수평 반전
이미지를 수평으로 반전시켜 좌우 대칭된 데이터를 생성했습니다.
밝기 변화
이미지의 밝기를 80%에서 120%까지 조정하여 다양한 조명 조건을 모방했습니다.
확대/축소
이미지를 20%까지 확대하거나 축소하여 다양한 크기의 데이터를 생성했습니다.
전단
이미지를 최대 20% 잘라 끊어 형태가 변형된 데이터를 생성했습니다.
모델 학습 및 평가
1.
모델 구조
간단한 CNN 모델을 사용하여 이미지 데이터를 처리했습니다.
Conv2D 레이어와 MaxPooling2D 레이어를 통해 이미지의 특징을 추출하고, Dropout 레이어를 통해 과적합을 방지했습니다.
BatchNormalization 레이어를 사용하여 학습을 안정화하고 성능을 향상시켰습니다.
2.
학습률 스케줄링
ReduceLROnPlateau 콜백을 사용하여 검증 손실이 향상되지 않을 때 학습률을 조정했습니다.
모델 성능
학습 결과
모델은 학습 과정에서 일정한 정확도를 유지했지만, 검증 데이터에 대한 성능이 크게 향상되지 않았습니다.
테스트 정확도
최종 테스트 정확도는 약 10%로, 이는 랜덤 추측과 비슷한 수준입니다.

코드 설명

미니퀘스트 답안지

알아 두면 좋은 정보

ImageDataGenerator (Tensorflow, Keras)

정의

ImageDataGenerator는 딥러닝 프레임워크인 Keras에서 제공하는 유틸리티 클래스입니다.
주로 이미지 데이터를 실시간으로 증강하고 전처리하는 데 사용됩니다.
ImageDataGenerator의 주요 기능으로는 데이터 증강, 데이터 전처리, 배치 생성이 있습니다.
기능
설명
데이터 증강
이미지 데이터를 회전, 이동, 확대/축소, 뒤집기, 밝기 조정, 전단 변환 등 다양한 방식으로 변형
데이터 전처리
이미지 데이터를 정규화, 표준화, 특정 채널 변환, ZCA Whitening 등으로 전처리
배치 생성
NumPy 배열 또는 디렉토리 구조에서 증강된 이미지 배치를 실시간으로 생성
배치란 무엇인가요?
배치(batch)는 머신 러닝과 딥 러닝에서 자주 사용되는 용어로, 대규모 데이터셋을 한 번에 모두 처리하지 않고, 나눠서 여러 번에 걸쳐 처리하는 작은 데이터 묶음을 의미합니다. 이는 메모리 효율성을 높이고, 모델 학습 속도를 개선하기 위해 사용됩니다.

사용 이유

ImageDataGenerator를 사용하는 이유는 실시간 데이터 증강으로 학습 데이터양을 늘려 모델 성능을 향상시키고, 과적합을 방지하며, 모델의 일반화 성능을 높일 수 있기 때문입니다.
이유
설명
모델 성능 향상
이미지 데이터를 실시간으로 증강함으로써 모델의 학습 데이터양을 효과적으로 증가시킬 수 있습니다. 이는 모델이 더 다양한 데이터를 학습하게 하여, 성능을 향상시킬 수 있습니다.
과적합 방지
데이터 증강은 모델이 학습 데이터에 과적합(overfitting)되는 것을 방지하는 데 도움이 됩니다. 다양한 변형 데이터를 학습함으로써 모델이 특정 데이터 패턴에 과도하게 맞춰지는 것을 막을 수 있습니다.
일반화 성능 향상
증강된 데이터를 통해 모델은 보다 일반화된 특성을 학습할 수 있습니다. 이는 모델이 새로운 데이터에서도 좋은 성능을 보이도록 도와줍니다.
데이터 효율성
제한된 양의 데이터를 가지고 있는 경우, 데이터 증강을 통해 데이터의 양을 효과적으로 늘릴 수 있습니다. 이는 특히 데이터 수집이 어려운 경우 유용합니다.
자동화된 전처리
ImageDataGenerator를 사용하면 데이터 전처리 과정이 자동화되어, 매번 수동으로 데이터를 변형할 필요가 없습니다. 이는 데이터 준비 시간을 줄여주고, 효율적인 워크플로우를 제공합니다.

사용 방법

9개의 증강된 이미지가 3x3 그리드로 표시하는 예제로 ImageDataGenerator 사용방법에 대해 이해해보도록 하겠습니다.
1.
초기화
ImageDataGenerator 객체를 생성할 때, 다양한 데이터 증강 옵션을 설정합니다.
예를 들어, 회전, 이동, 확대/축소, 수평/수직 뒤집기, 밝기 조정 등을 설정할 수 있습니다.
from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Input # 데이터 증강 설정 datagen = ImageDataGenerator( rotation_range=20, # 이미지를 무작위로 회전시키는 범위, -20도 ~ 20도 width_shift_range=0.2, # 수평 방향으로 무작위 이동시키는 범위, 20% height_shift_range=0.2, # 수직 방향으로 무작위 이동시키는 범위, 20% shear_range=0.2, # 전단 변환(shearing transformation)을 적용하는 범위, 20% zoom_range=0.2, # 이미지를 무작위로 확대 또는 축소하는 범위를 설정, 80% ~ 120% horizontal_flip=True, # 이미지를 수평 방향으로 뒤집기 fill_mode='nearest' # 이미지 변형 중 빈 픽셀을 채우는 방식, 'nearest'는 가장 가까운 픽셀의 값을 사용하여 빈 공간을 채웁니다. )
Python
복사
전단 변환(shearing transformation)이란 무엇인가요?
전단 변환(Shearing Transformation)은 이미지를 한 축을 기준으로 특정 각도로 기울이는 변환 방식입니다. 이 변환은 이미지의 모양을 바꿔서 마치 이미지가 비스듬히 기울어져 있는 것처럼 보이게 합니다. 전단 변환은 이미지의 형태와 구조를 변화시켜 다양한 시각적 변형을 추가하는 데 유용합니다.

전단 변환의 이해

수평 전단: 수평 방향으로 전단 변환을 하면 이미지가 왼쪽이나 오른쪽으로 기울어집니다.
수직 전단: 수직 방향으로 전단 변환을 하면 이미지가 위쪽이나 아래쪽으로 기울어집니다.

시각적 예시

예를 들어, 원래 이미지는 아래와 같습니다:
+----+ | | | | | | +----+
Lua
복사
수평 전단 변환을 적용하면 이미지가 다음과 같이 기울어집니다:
+----+ / / / / +----+
Lua
복사
수직 전단 변환을 적용하면 이미지가 다음과 같이 기울어집니다:
+----+ | | | | | / | / +--+
Lua
복사
fill_mode란 무엇인가요?
fill_mode는 이미지 변형 중 빈 픽셀을 채우는 방식입니다.
'nearest'는 가장 가까운 픽셀의 값을 사용하여 빈 공간을 채웁니다.
'constant'는 특정 값으로 빈 공간을 채웁니다.
'reflect'는 경계를 따라 반사된 값으로 빈 공간을 채웁니다.
원래 이미지: | 1 2 3 | | 4 5 6 | | 7 8 9 | 반사된 이미지: | 3 2 1 2 3 2 1 | | 6 5 4 5 6 5 4 | | 9 8 7 8 9 8 7 | | 6 5 4 5 6 5 4 | | 3 2 1 2 3 2 1 |
Lua
복사
이미지의 경계를 넘어가면 반대쪽 경계로 연결되는 방식으로 빈 공간을 채웁니다.
원래 이미지: | 1 2 3 | | 4 5 6 | | 7 8 9 | 랩된 이미지: | 9 7 8 9 7 8 9 | | 3 1 2 3 1 2 3 | | 6 4 5 6 4 5 6 | | 9 7 8 9 7 8 9 | | 3 1 2 3 1 2 3 |
Lua
복사
2.
데이터 피팅
증강을 적용할 이미지 데이터를 fit 메서드를 통해 ImageDataGenerator 객체에 맞춥니다.
# 예시 데이터 (x_train, y_train) 생성 import numpy as np x_train = np.random.rand(100, 150, 150, 3) # 100개의 150x150 RGB(3) 이미지 y_train = np.random.randint(2, size=100) # 100개의 라벨 (0 또는 1) # 데이터 피팅 datagen.fit(x_train)
Python
복사
라벨이란 무엇인가요?
라벨은 각 이미지가 속한 클래스를 나타냅니다. 즉. 각 데이터 포인트(예: 이미지)가 속하는 정답 또는 분류를 나타냅니다.
클래스는 무엇인가요?
라벨이 가리키는 범주로, 데이터가 속할 수 있는 그룹입니다. 예를 들어, 이미지가 고양이인지 개인지 구분할 때, '고양이'와 '개'가 각각 클래스가 됩니다.
3.
데이터 생성
flow 또는 flow_from_directory 메서드를 사용하여 증강된 이미지 배치를 생성합니다.
flow는 NumPy 배열에서 직접 데이터를 생성합니다.
# 데이터 생성기 초기화 it = datagen.flow(x_train, y_train, batch_size=32)
Python
복사
flow_from_directory는 디렉터리 구조에서 데이터를 생성합니다.
# 디렉터리 구조에서 데이터 생성 # it = datagen.flow_from_directory('data/train', target_size=(150, 150), batch_size=32, class_mode='binary')
Python
복사
4.
모델 훈련
생성된 데이터 배치를 사용하여 모델을 훈련시킵니다.
from tensorflow.keras import Input # 간단한 모델 정의 model = Sequential([ Input(shape=(150, 150, 3)), Conv2D(32, (3, 3), activation='relu'), MaxPooling2D((2, 2)), Conv2D(64, (3, 3), activation='relu'), MaxPooling2D((2, 2)), Flatten(), Dense(64, activation='relu'), Dense(1, activation='sigmoid') ]) # 모델 컴파일 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # 모델 훈련 model.fit(it, steps_per_epoch=3, epochs=5)
Python
복사
코랩으로 보기 : link iconGoogle Colab

실습 프로젝트 - 1

CIFAR-10 데이터셋을 사용하여 이미지 데이터를 로드하고, ImageDataGenerator를 이용해 다양한 증강 기법을 적용한 후, 이를 시각화해 보세요.
CIFAR-10 데이터셋 설명
문제 설명
1.
CIFAR-10 데이터셋 로드
# CIFAR-10 데이터셋 로드 (x_train, y_train), (x_test, y_test) = cifar10.load_data()
Python
복사
2.
ImageDataGenerator 설정
3.
증강된 이미지 생성
4.
증강된 이미지 시각화
코드
# 필요한 라이브러리 임포트 import numpy as np import matplotlib.pyplot as plt from tensorflow.keras.datasets import cifar10 from tensorflow.keras.preprocessing.image import ImageDataGenerator # CIFAR-10 데이터셋 로드 (x_train, y_train), (x_test, y_test) = cifar10.load_data() # ImageDataGenerator 설정 datagen = ImageDataGenerator( rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.2, zoom_range=0.2, horizontal_flip=True, fill_mode='nearest' ) # 데이터 피팅 datagen.fit(x_train) # 증강된 이미지 생성 augmented_images = datagen.flow(x_train[:1], batch_size=1) # 증강된 이미지 시각화 plt.figure(figsize=(10, 10)) for i in range(9): plt.subplot(3, 3, i+1) batch = next(augmented_images) image = batch[0].astype('uint8') plt.imshow(image) plt.axis('off') plt.show()
Python
복사
결과(예시) 설명
9개의 증강된 이미지가 3x3 그리드로 표시됩니다.
원본 이미지를 다양한 방식으로 변형하여 증강된 이미지들을 확인할 수 있습니다.
이러한 데이터 증강 기법은 모델의 일반화 성능을 높이고, 데이터 부족 문제를 해결하는 데 도움을 줍니다.
코드 설명
답안지

실습 프로젝트 - 2

ImageDataGenerator를 사용하여 데이터 증강을 적용한 모델과 그렇지 않은 모델의 성능을 비교합니다.
두 모델 모두 CIFAR-10 데이터셋을 사용하여 훈련하며, 증강의 효과를 확인하기 위해 모델의 정확도를 비교합니다.
문제 설명
1.
CIFAR-10 데이터셋 로드
# CIFAR-10 데이터셋 로드 및 전처리 (x_train, y_train), (x_test, y_test) = cifar10.load_data() x_train, x_test = x_train / 255.0, x_test / 255.0 y_train, y_test = to_categorical(y_train), to_categorical(y_test)
Python
복사
2.
기본 모델 정의 및 훈련
3.
데이터 증강을 적용한 모델 정의 및 훈련
4.
두 모델의 성능 비교
코드
결과 (예시)
기본 모델
데이터 증강을 적용하지 않은 모델입니다.
증강 모델
ImageDataGenerator를 사용하여 데이터 증강을 적용한 모델입니다.
각 모델은 10 에포크 동안 훈련되었으며, 각 에포크에서의 검증 정확도가 그래프로 나타납니다.
결과 설명
1.
기본 모델
초기에는 빠르게 검증 정확도가 상승하지만, 일정 수준에 도달한 후에는 성능 향상이 둔화됩니다.
2.
증강 모델
검증 정확도가 더 안정적으로 상승하며, 일반적으로 더 높은 검증 정확도에 도달합니다.
코드 설명
답안지

NumPy 배열(numpy.ndarray)

윗 글에 추가설명을 위해 남긴 글입니다.(링크)

1. 성능

속도: NumPy 배열은 리스트보다 훨씬 빠릅니다. 이는 NumPy가 C로 작성된 내부 루프를 사용하여 배열 연산을 수행하기 때문입니다.
메모리 효율성: NumPy 배열은 메모리를 더 효율적으로 사용합니다. 동일한 데이터 타입의 요소들이 연속적인 메모리 블록에 저장되기 때문에, 메모리 접근 속도가 빨라지고, 메모리 사용량이 줄어듭니다.

2. 기능

벡터화 연산: NumPy 배열은 벡터화 연산을 지원하여, 반복문을 사용하지 않고도 배열 전체에 대한 연산을 한 번에 수행할 수 있습니다. 이는 코드의 가독성과 실행 속도를 모두 향상시킵니다.
# 파이썬 리스트를 사용한 요소별 연산 a = [1, 2, 3, 4] b = [5, 6, 7, 8] c = [] for i in range(len(a)): c.append(a[i] + b[i]) print(c) # 출력: [6, 8, 10, 12]
Python
복사
import numpy as np a = np.array([1, 2, 3, 4]) b = np.array([5, 6, 7, 8]) c = a + b # 벡터화 연산 print(c) # 출력: [ 6 8 10 12]
Python
복사

3. 다차원 배열

다차원 배열: NumPy는 다차원 배열을 자연스럽게 지원합니다. 파이썬 리스트로는 다차원 배열을 표현하기 어렵고 비효율적입니다.
import numpy as np a = np.array([[1, 2, 3], [4, 5, 6]]) print(a.shape) # 출력: (2, 3)
Python
복사

4. 다양한 수학 함수와 라이브러리

풍부한 기능: NumPy는 수학 함수, 선형 대수, 난수 생성, 푸리에 변환 등 많은 기능을 제공합니다.
import numpy as np a = np.array([1, 2, 3, 4]) print(np.mean(a)) # 평균 계산: 2.5 print(np.std(a)) # 표준편차 계산: 1.118033988749895
Python
복사

5. 브로드캐스팅

브로드캐스팅: NumPy는 배열 간의 크기가 다른 경우에도 자동으로 크기를 맞춰서 연산을 수행하는 브로드캐스팅을 지원합니다.
import numpy as np a = np.array([1, 2, 3]) b = 2 c = a * b # 브로드캐스팅 print(c) # 출력: [2 4 6]
Python
복사

6. 통합 및 호환성

다른 라이브러리와의 통합: 많은 데이터 과학 및 기계 학습 라이브러리(예: Pandas, Scikit-learn, TensorFlow 등)가 NumPy 배열을 기본 데이터 구조로 사용하여, 이들 라이브러리와의 통합이 용이합니다.

요약

NumPy 배열은 빠르고 효율적이며, 다차원 배열과 풍부한 수학 함수를 지원합니다. 이러한 이유로, 과학 계산, 데이터 분석 및 기계 학습에서 파이썬의 기본 리스트 대신 NumPy 배열을 사용하는 것이 일반적입니다.
ⓒ 2024 startupcode. 모든 권리 보유. 무단 복제 금지.