7.7. 정규화¶
ml.Model.predict() 는 일부 신경망이 둘 이상의 입력 텐서를 가지기 때문에 입력의 리스트 를 받지만, 이 리스트에는 입력별 인수를 인라인으로 담을 방법이 없습니다 – “이 입력은 (x, y, w, h) 로 크롭하되 다른 입력은 그대로 두라”는 키워드 인수 슬롯이 없습니다. ml.preprocessing.Normalization 은 그 공백을 메우는 래퍼입니다. Normalization 인스턴스는 하나의 입력에 대한 매개변수를 담으며, 스크립트는 기본값 외의 무언가가 필요할 때마다 래핑된 입력을 predict 리스트에 전달합니다.
이를 사용하는 가장 흔한 이유는 전체 이미지가 아니라 캡처된 프레임의 특정 영역을 크롭하여 신경망에 넣기 위해서입니다.
7.7.1. 매개변수¶
Normalization(scale=(0.0, 1.0),
mean=(0.0, 0.0, 0.0),
stdev=(1.0, 1.0, 1.0),
roi=None)
roi– 리사이즈하기 전에 크롭할 소스 프레임 내의(x, y, w, h)사각형입니다. 기본값은 전체 프레임입니다.Normalization의 대부분의 용도는 이 매개변수만 설정합니다.scale– 부동소수점 입력 텐서가 정규화 후에 기대하는(min, max)범위입니다. 픽셀 범위0..255가 이 범위로 선형 매핑됩니다. 흔한 값은 ReLU로 학습된 신경망의 경우(0.0, 1.0), 대칭적으로 정규화된 신경망의 경우(-1.0, 1.0)입니다.mean– 스케일링 후 이미지에서 빼는 채널별(R, G, B)평균입니다. 신경망이 학습된 채널 통계와 일치합니다 – ImageNet에서 유래한 신경망의(0.485, 0.456, 0.406)이 정석적인 예입니다. 그레이스케일 신경망은 표준0.299*R + 0.587*G + 0.114*B를 사용해 평균을 루마 값으로 축소합니다.stdev– 평균을 뺀 후 이미지를 나누는 채널별(R, G, B)표준편차로, 역시 신경망의 학습 통계와 일치합니다. 그레이스케일 신경망의 경우 같은 방식으로 루마로 축소됩니다.
7.7.2. 매개변수가 중요한 경우¶
신경망의 input_dtype 이 int8 또는 uint8 일 때 scale, mean, stdev 는 무시됩니다. 정수 입력 신경망의 경우 크롭된 이미지 바이트가 텐서에 직접 기록되며, 신경망 자체의 input_scale 과 input_zero_point 가 정수-실수 변환을 처리합니다. 이 세 매개변수는 신경망이 부동소수점 입력을 기대할 때만 중요합니다.
roi 는 모든 경우에 읽힙니다 – 입력 dtype에 관계없이 소스 프레임의 어느 부분이 신경망에 도달하는지를 제어합니다.
7.7.3. ROI와 리사이즈¶
ROI는 소스 차원에서 신경망의 입력 차원으로 쌍선형 보간으로 스케일됩니다. 이미지는 대상의 중앙에 배치되고 스케일링이 대상을 채웁니다 – 종횡비는 보존하지 않습니다. 정사각형이 아닌 ROI를 정사각형 신경망 입력에 넣으면 가로 또는 세로로 늘어나서 나옵니다.
이 늘어남이 중요한지는 신경망에 따라 다릅니다. MediaPipe 계열(BlazeFace, FaceLandmarks, HandLandmarks, MoveNet) 같은 얼굴 검출 및 랜드마크 모델은 정사각형 크롭으로 학습되어 입력 종횡비가 어긋나면 빠르게 성능이 저하됩니다. 이런 모델의 경우 애플리케이션은 정사각형 ROI를 제공해야 합니다 – window() 를 통해 정사각형 프레임 크기로 캡처하거나 roi= 매개변수로 크롭하는 방식입니다. YOLO 계열 객체 검출기는 일반적으로 무작위 늘어남을 포함하는 증강으로 학습되어 정사각형이 아닌 ROI도 큰 정확도 손실 없이 받아들이므로, 캡처한 전체 프레임을 그대로 넣어도 보통 괜찮습니다.
신경망의 입력 차원이 ROI와 정확히 일치할 때 스케일은 복사로 축약되며, 이것이 가장 비용이 적은 경우입니다.
7.7.4. 기본값 재정의하기¶
predict() 는 각 image.Image 입력을 자동으로 Normalization() 으로 래핑합니다 – 위의 기본 매개변수를 사용합니다. 카메라와 함께 출하되는 대부분의 모델은 기본값이 이미 다루는 픽셀 범위로 학습되었으므로, 흔한 경우는 이미지를 직접 전달하는 것입니다:
result = model.predict([img])
커스텀 ROI를 사용하려면 – 가장 흔한 재정의 – ROI를 설정한 Normalization 을 만들고 이미지를 그것에 바인딩합니다:
from ml.preprocessing import Normalization
norm = Normalization(roi=(80, 60, 160, 120))
result = model.predict([norm(img)])
신경망의 학습 시점 채널 통계와 일치시키려면 부동소수점 매개변수를 설정합니다:
norm = Normalization(scale=(0.0, 1.0),
mean=(0.485, 0.456, 0.406),
stdev=(0.229, 0.224, 0.225))
result = model.predict([norm(img)])
Normalization 인스턴스를 이미지에 대해 호출하면 엔진이 텐서를 채우는 데 사용하는 새로운 바인딩된 인스턴스가 반환됩니다. 이 바인딩된 인스턴스가 원시 이미지 대신 predict가 받아들이는 것이며, 입력별 객체이기 때문에 다중 입력 신경망은 같은 predict 리스트 안에서 서로 다른 ROI를 가진 이미지들을 섞을 수 있습니다.
애플리케이션이 이미 텐서 형태로 만들어 둔 입력을 기대하는 신경망의 경우 – 주변장치에서 온 버퍼, 다른 파이프라인이 계산한 ndarray, 이미지가 아닌 수치 데이터 – Normalization 을 통째로 건너뛰고 ndarray 또는 그것을 생성하는 호출 가능 객체를 전달합니다. predict() 는 그것들을 래핑 없이 엔진으로 통과시킵니다.