PatchPreprocessor는 훈련 과정에서 이미지의 M × N 영역을 무작위로 샘플링합니다. 입력 이미지의 공간 차원이 CNN이 예상하는 것보다 클 때 패치 전처리를 적용합니다. 이는 과적 합을 줄이는 데 도움이되는 일반적인 기술이므로 정규화의 한 형태입니다. 훈련 중에 전체 이미지를 사용하는 대신, 대신 무작위로 잘라내어 네트워크로 전달합니다 (크롭 전처리의 예는 아래 그림 참조).

이 자르기를 적용한다는 것은 데이터 증가와 유사하게 네트워크가 똑같은 이미지를 볼 수 없음을 의미합니다 (무작위로 발생하지 않는 한). 이전 장에서 알 수 있듯이 각 이미지가 256×256 픽셀 인 Kaggle Dogs vs. Cats 이미지의 HDF5 데이터 세트를 구성했습니다. 그러나 이 장의 뒷부분에서 구현할 AlexNet 아키텍처는 227×227 픽셀 크기의 이미지 만 허용 할 수 있습니다. 어떻게 해야 할까요?
SimplePreprocessor를 적용하여 256×256 픽셀 각각의 크기를 227×227로 축소 하시겠습니까? 아닙니다. 이것은 훈련 중에 256×256 이미지에서 227×227 영역을 무작위로 잘라 데이터 증가를 수행 할 수있는 좋은 기회입니다. 실제로 이 프로세스는 Krizhevsky et al. ImageNet 데이터 세트에서 AlexNet을 훈련시킵니다. 다른 모든 이미지 전처리 기와 마찬가지로 PatchPreprocessor는 pyimagesearch의 전처리 하위 모듈에서 정렬됩니다.


5 행은 PatchPreprocessor에 대한 구성을 정의합니다. 잘라낸 이미지의 대상 너비와 높이를 제공하기 만하면됩니다. 그런 다음 전처리 기능을 정의 할 수 있습니다.

scikit-learn 라이브러리의 extract_patches_2d 함수를 사용하면 self.width x self.height 크기의 임의 패치를 쉽게 추출 할 수 있습니다. 입력 이미지가 주어지면이 함수는 이미지에서 패치를 무작위로 추출합니다. 여기서 max_patches = 1을 제공하여 입력 이미지에서 하나의 임의 패치 만 필요함을 나타냅니다.
PatchPreprocessor 클래스는 실제 쓰이는 법은 별로 보이지 않지만 실제로는 또 다른 데이터 증가 계층을 적용하여 과적합을 방지하는 매우 효과적인 방법입니다. AlexNet을 교육 할 때 PatchPreprocessor를 사용합니다. 다음 전처리 기인 CropPreprocessor는 훈련 된 네트워크를 평가할 때 사용됩니다.
다음으로 오버 샘플링을 위해 10 개의 크롭을 계산하는 CropPreprocessor를 정의해야합니다. CNN의 평가 단계에서 입력 이미지의 네 모서리 + 중앙 영역을 잘라낸 다음 해당 수평 반전을 수행하여 입력 이미지 당 총 10 개의 샘플을 얻습니다 (아래 그림).

왼쪽 : 원본 256 × 256 입력 이미지.
오른쪽 : 10 자르기 전처리기를 적용하여 중앙, 네 모서리 및 해당 수평 거울을 포함하여 이미지의 227 × 227 자르기 10 개를 추출합니다.
이 10 개의 샘플은 CNN을 통과 한 다음 확률이 평균화됩니다. 이 오버 샘플링 방법을 적용하면 분류 정확도가 1-2 % 증가하는 경향이 있습니다 (경우에 따라 더 높음). CropPreprocessor 클래스는 전처리 하위 모듈에 있습니다.

croppreprocessor.py 파일을 열고 정의 해 보겠습니다
# import the necessary packages
import numpy as np
import cv2
class CropPreprocessor:
def __init__(self, width, height, horiz=True, inter=cv2.INTER_AREA):
# store the target image width, height, whether or not
# horizontal flips should be included, along with the
# interpolation method used when resizing
self.width = width
self.height = height
self.horiz = horiz
self.inter = inter
6 행은 생성자를 CropPreprocessor에 정의합니다. 유일한 필수 인수는 잘린 각 영역의 대상 너비와 높이입니다. 또한 OpenCV가 크기 조정에 사용할 보간 알고리즘과 함께 수평 뒤집기를 적용할지 (기본값은 True) 여부를 선택적으로 지정할 수도 있습니다. 이러한 인수는 모두 preprocess 메서드 내에서 사용하기 위해 클래스 내부에 저장됩니다. 이제 preprocess 메서드을 정의 해 보겠습니다.
ㅁ

전처리 방법은 오버 샘플링을 적용 할 이미지 인 단일 인수만 필요합니다. 21 행에서 입력 이미지의 너비와 높이를 가져와서 네 모서리 (각각 왼쪽 위, 오른쪽 위, 오른쪽 아래, 왼쪽 아래)의 (x, y) 좌표를 계산할 수 있습니다) 22-26 행.
그런 다음 이미지의 중앙 자르기는 29 행과 30 행에서 계산 된 다음 31 행의 좌표 목록에 추가됩니다.
이제 각 크롭을 추출 할 준비가 되었습니다.

35 행에서 직사각형 크롭의 시작 및 끝 (x, y) 좌표를 반복합니다. 36 행은 NumPy 배열 슬라이싱을 통해 크롭을 추출한 다음 37 행에서 크기를 조정하여 목표 너비와 높이 치수가 충족되도록합니다. 크롭은 크롭 리스트에 추가됩니다.
수평 뒤집기를 계산해야하는 경우 5 가지 원본 크롭을 각각 뒤집어 전체적으로 10 가지 크롭을 남길 수 있습니다. #

그런 다음 자르기 배열이 48 행의 호출 함수로 반환됩니다. 정규화를 위해 MeanPreprocessor를 사용하고 오버 샘플링을 위해 CropPreprocessor를 사용하면 가능한 것보다 더 높은 분류 정확도를 얻을 수 있습니다.