구름 이미지를 업로드하면 AI가 구름의 종류를 자동으로 분류해주는 웹 서비스입니다.
- 이미지 업로드: 클릭 또는 드래그 앤 드롭으로 구름 사진 업로드
- AI 분류: ConvNeXt 딥러닝 모델로 구름 종류 실시간 분류
- 확률 시각화: 각 클래스별 예측 확률을 막대 그래프로 표시
- 예시 이미지 제공: 분류 결과에 맞는 세부 구름 종류별 예시 이미지 표시
- 신뢰도 경고: 신뢰도 70% 미만 시 재업로드 안내
| 클래스 | 한국어 | 세부 종류 |
|---|---|---|
high |
상층운 | 권적운(Cc), 권운(Ci), 권층운(Cs), 비행운(Ct) |
middle |
중층운 | 고층운(As), 고적운(Ac) |
low |
하층운 | 층운(St), 층적운(Sc), 난층운(Ns) |
vertical |
수직운 | 적란운(Cb), 적운(Cu) |
| 분류 | 기술 |
|---|---|
| 백엔드 | FastAPI, Uvicorn |
| AI 모델 | PyTorch, ConvNeXt (HuggingFace Transformers) |
| 이미지 처리 | Pillow, Torchvision |
| 프론트엔드 | HTML, CSS, Vanilla JS (Jinja2 템플릿) |
- Python 3.9+
- 학습된 모델 파일:
cloud_classification.pt
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtuvicorn main:app --reload브라우저에서 http://localhost:8000 접속
구름 이미지를 분류합니다.
요청
Content-Type: multipart/form-data
file: <이미지 파일>
응답
{
"prediction": "high",
"confidence": 92.35,
"all_probabilities": [
{ "label": "high", "probability": 92.35 },
{ "label": "middle", "probability": 4.12 },
{ "label": "low", "probability": 2.31 },
{ "label": "vertical", "probability": 1.22 }
]
}해당 카테고리의 세부 구름 종류별 예시 이미지 URL을 반환합니다.
예시: GET /sample/high
{
"samples": [
{ "subcategory": "Ci", "image_url": "/static/image/high/Ci/Ci-N001.jpg" },
{ "subcategory": "Cs", "image_url": "/static/image/high/Cs/Cs-N003.jpg" }
]
}goorm/
├── main.py # FastAPI 앱, 라우터
├── model.py # 모델 로드 및 추론
├── cloud_classification.pt # 학습된 ConvNeXt 모델 가중치
├── requirements.txt
├── templates/
│ └── index.html # 프론트엔드 UI
└── static/
└── image/
├── high/ # 상층운 예시 이미지 (Cc, Ci, Cs, Ct)
├── middle/ # 중층운 예시 이미지 (Ac, As)
├── low/ # 하층운 예시 이미지 (Ns, Sc, St)
└── vertical/ # 수직운 예시 이미지 (Cb, Cu)
- 아키텍처: ConvNeXt (HuggingFace
ConvNextForImageClassification) - 입력 크기: 224 × 224 (RGB)
- 정규화: ImageNet 평균/표준편차 (
[0.485, 0.456, 0.406]/[0.229, 0.224, 0.225]) - 출력: 4개 클래스 소프트맥스 확률
학습 과정은 구름 이미지 분류 파인튜닝.ipynb 노트북에 정리되어 있습니다.
HuggingFace의 facebook/convnext-tiny-224 (ImageNet 사전학습 가중치)를 4-class 분류로 파인튜닝했습니다.
model = ConvNextForImageClassification.from_pretrained(
"facebook/convnext-tiny-224",
num_labels=4,
ignore_mismatched_sizes=True
)- Google Drive에서
ImageFolder형식으로 train / val 세트 로드 - HuggingFace
AutoImageProcessor로 전처리 후DataLoader에 공급
| 구분 | 배치 크기 | 셔플 |
|---|---|---|
| Train | 16 | O |
| Validation | 16 | X |
| 항목 | 값 |
|---|---|
| Optimizer | AdamW |
| Learning Rate | 5e-5 |
| Epochs | 10 |
| 체크포인트 기준 | Validation Accuracy 최대값 |
- 매 에폭마다 train loss 계산 후 역전파
- Validation Accuracy 측정
- 이전 최고 정확도 초과 시
best_model.pt로 체크포인트 저장 (epoch, model/optimizer state dict, acc 포함)
Epoch 0 | loss: x.xxxx | val acc: x.xxxx
🔥 Best model saved! acc = x.xxxx
...
학습 완료 후 Confusion Matrix와 Classification Report로 성능을 분석했습니다.
| 지표 | 의미 |
|---|---|
| Precision (정밀도) | 모델이 특정 클래스로 예측한 것 중 실제로 맞은 비율. 오탐(False Positive)이 적을수록 높음 |
| Recall (재현율) | 실제 특정 클래스인 것 중 모델이 올바르게 찾아낸 비율. 미탐(False Negative)이 적을수록 높음 |
| F1-score | Precision과 Recall의 조화평균. 둘 다 높아야 F1도 높으며, 어느 한쪽이 낮으면 점수가 낮아짐 |
| Support | 해당 클래스의 실제 데이터 샘플 수 |
| Accuracy | 전체 샘플 중 올바르게 예측한 비율 |
| Macro avg | 각 클래스의 Precision/Recall/F1을 단순 평균. 클래스 불균형을 무시하고 모든 클래스를 동등하게 취급 |
| Weighted avg | 각 클래스의 support(샘플 수)에 비례하여 가중 평균. 샘플이 많은 클래스가 전체 점수에 더 큰 영향을 미침 |
precision recall f1-score support
high 0.84 0.88 0.86 94
low 0.71 0.74 0.72 72
middle 0.43 0.37 0.39 41
vertical 0.86 0.82 0.84 38
accuracy 0.74 245
macro avg 0.71 0.70 0.70 245
weighted avg 0.73 0.74 0.74 245
상층운 (high) — F1: 0.86
support가 94개로 가장 많은 데이터셋을 보유하고 있으며, 권운(Ci)의 새털 모양, 권층운(Cs)의 넓게 퍼진 베일 형태 등 상층운 특유의 얇고 섬세한 구조가 다른 클래스와 시각적으로 명확히 구분됩니다. 충분한 데이터량과 뚜렷한 시각적 특징이 맞물려 가장 높은 F1 점수를 기록했습니다.
하층운 (low) — F1: 0.72
support가 72개로 두 번째로 많은 데이터셋을 가지고 있으며, 층운(St)의 낮게 깔리는 균일한 회색 층, 층적운(Sc)의 덩어리진 패턴 등 비교적 명확한 특징을 가집니다. 다만 날씨에 따라 흐릿하거나 경계가 불분명한 이미지가 포함될 수 있어 상층운보다는 다소 낮은 점수가 나왔습니다.
중층운 (middle) — F1: 0.39
support가 41개로 가장 적은 데이터셋을 가지고 있으며, 고층운(As)·고적운(Ac)은 상층운·하층운과 시각적으로 경계가 모호하기 때문에 모델이 인접 클래스와 혼동하는 경우가 많아 낮은 F1 점수가 나왔습니다.
수직운 (vertical) — F1: 0.84
support가 38개로 전체 클래스 중 가장 적은 데이터셋임에도 불구하고, 적운(Cu)·적란운(Cb)은 수직으로 크게 발달하는 뚜렷한 탑 모양을 가지고 있어 다른 클래스와 형태적으로 명확히 구분됩니다. 덕분에 모델이 적은 데이터로도 특징을 잘 학습하여 높은 F1 점수를 기록했습니다.