ResNet 기반 망막증 분류 #1 Conv2D 기반 이미지 분류

ResNet 기반 망막증 분류 #1 Conv2D 기반 이미지 분류 #

#2026-02-27


#1

당뇨병 환자의 몸에서는 혈당이 오랜 기간 높은 상태로 유지된다. 이 높은 혈당이 온몸의 작은 혈관들을 서서히 망가뜨리는데, 눈의 망막에 있는 미세 혈관도 예외가 아니다. 혈관이 손상되면 피가 새고, 비정상적인 새 혈관이 자라나고, 결국 망막이 제 기능을 못 하게 되면서 시력을 잃을 수 있다. 이것이 당뇨병성 망막증이다. 안과 의사는 이 병을 진단하기 위해 안저 사진을 찍는다. 안저란 눈 뒤쪽의 망막 바닥 면을 말하는데, 특수 카메라로 동공을 통해 들여다보면 망막의 혈관 구조가 고스란히 보인다. 의사는 이 사진에서 출혈 반점, 비정상 혈관, 부종 같은 징후를 찾아서 병의 심각도를 판정한다. 문제는 이 판독에 전문성과 시간이 많이 든다. 이에 분석 목적은 안저 사진을 보고 자동으로 심각도를 판정하는 것이다.

#

#2 데이터셋과 문제 설정

Kaggle Diabetic Retinopathy Detection 데이터셋은 수만 장의 안저 사진이 들어 있고 각 사진에는 안과 의사가 매긴 등급이 붙어 있다. 0은 정상, 1은 경증, 2는 중등도, 3은 중증, 4는 증식성으로 가장 심각한 단계다. 등급 0의 사진을 보면 깨끗한 혈관 구조가 보인다. 등급이 올라갈수록 작은 출혈 반점이 나타나기 시작하고, 혈관이 불규칙해지고, 심한 경우에는 망막 전체에 출혈과 비정상 혈관이 가득 차 있다.

등급 0: 정상 (No DR)
등급 1: 경증 (Mild)
등급 2: 중등도 (Moderate)
등급 3: 중증 (Severe)
등급 4: 증식성 (Proliferative DR) ← 가장 심각

이는 단순 분류가 아닌 순서가 있는 분류이다. 일반적인 고양이, 개, 새를 구분하는 문제에서 고양이를 개로 잘못 분류하나 새로 잘못 분류하나, 둘 다 “한 번 틀린 것"이다. 오분류의 심각도가 동일하다. 하지만 당뇨병성 망막증은 다르다. 등급 0(정상)인 환자를 등급 1(경증)로 잘못 예측하는 건 한 단계 차이니까 그나마 덜 심각하다. 그런데 등급 0을 등급 4(증식성)로 예측하면 어떻게 되나? 정상인 환자에게 가장 심각한 진단을 내리는 셈이다. 반대로 등급 4를 등급 0으로 예측하면? 당장 치료가 필요한 환자를 정상이라고 돌려보내는 것이다. 이건 실명으로 이어질 수 있는 치명적인 실수다. 이렇게 등급 사이에 순서와 거리가 있는 분류 문제를 순서형 분류(Ordinal Classification)라고 부른다. 0, 1, 2, 3, 4라는 숫자가 단순한 이름표가 아니라 심각도의 정도를 나타내는 척도다. 한 단계 차이로 틀리는 것과 네 단계 차이로 틀리는 것의 무게가 완전히 다르다.

그래서 단순 정확도(accuracy)만으로는 모델을 제대로 평가할 수 없다. 정확도는 “맞았느냐 틀렸느냐"만 따지지, “얼마나 크게 틀렸느냐"는 신경 쓰지 않기 때문이다. 등급 0을 등급 1로 예측하든 등급 4로 예측하든 정확도 관점에서는 똑같이 “하나 틀린 것"이다. 하지만 의학적으로, 그리고 환자의 삶에서 이 두 실수의 무게는 하늘과 땅 차이다. 이 문제의 특수성을 반영하는 적절한 평가 방법이 필요한 이유다.

#

#3

이 분석에서는 3가지 파일로 나뉜 하나의 실험을 한다:

파일역할
data.py이미지 전처리 + 데이터셋 로드
model.pyResNet 기반 분류 모델 + 데이터 증강 + 평가 지표
run.py전체 파이프라인 실행

data.py로 이미지 전처리와 데이터셋 로딩, model.py로 ResNet 기반의 분류 모델 정의와 데이터 증강 및 평가, run.py로 실제로 학습과 평가를 실행한다.

이전에 DNA 서열을 Conv1D로 분석한 것처럼, 여기서는 망막 사진을 Conv2D 기반의 ResNet으로 분석하는 것이다. 입력이 1차원 서열에서 2차원 이미지로 바뀌었고, 문제가 이진 분류나 회귀에서 순서형 다중 분류로 바뀌었지만, “입력을 숫자로 바꾸고 합성곱으로 패턴을 찾아서 판단을 내린다"는 근본 구조는 동일하다.