본문 바로가기
AI Framework/PyTorch

[PyTorch] 15주차: 모델의 성능 모니터링 및 유지보수

by cogito21_python 2024. 5. 31.
반응형

강의 목표

  • 모델 성능 모니터링의 중요성 이해
  • 실시간 예측 시스템 모니터링 방법 학습
  • 모델의 성능 유지보수 및 업데이트 전략 학습

강의 내용

1. 모델 성능 모니터링의 중요성

  • 성능 모니터링의 필요성
    • 모델의 성능 저하 감지 및 원인 분석
    • 실시간 예측 시스템의 신뢰성 유지
  • 모니터링의 주요 지표
    • 예측 정확도
    • 응답 시간
    • 자원 사용량 (CPU, GPU, 메모리)

2. 실시간 예측 시스템 모니터링 방법

  • 로그 수집 및 분석
    • 예측 요청 및 응답 로그 수집
    • 로그 분석을 통한 성능 이슈 파악
     
import logging

# 로그 설정
logging.basicConfig(filename='app.log', level=logging.INFO)

# Flask 예측 함수에 로그 추가
def get_prediction(image_bytes):
    tensor = transform_image(image_bytes)
    outputs = model(tensor)
    _, predicted = torch.max(outputs.data, 1)
    logging.info(f'Predicted: {predicted.item()}')  # 로그 추가
    return predicted.item()

 

  • 모니터링 도구 사용
    • Prometheus, Grafana 등의 모니터링 도구를 사용하여 성능 지표 시각화
    • Flask 애플리케이션에 Prometheus 클라이언트 통합
     
from prometheus_client import start_http_server, Summary

# 요청 처리 시간 측정을 위한 메트릭 정의
REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing request')

@REQUEST_TIME.time()
def get_prediction(image_bytes):
    tensor = transform_image(image_bytes)
    outputs = model(tensor)
    _, predicted = torch.max(outputs.data, 1)
    return predicted.item()

if __name__ == '__main__':
    # Prometheus HTTP 서버 시작
    start_http_server(8000)
    app.run()

 

3. 모델 성능 유지보수 및 업데이트 전략

  • 성능 저하 원인 분석
    • 데이터 분포 변화
    • 모델 노후화
  • 주기적 재학습 및 업데이트
    • 새로운 데이터를 반영하여 주기적으로 모델 재학습
    • 지속적인 성능 평가 및 모델 업데이트
     
def retrain_model(new_data, new_labels):
    # 새로운 데이터로 모델 재학습
    model.train()
    optimizer = optim.Adam(model.parameters(), lr=0.001)
    for epoch in range(5):
        running_loss = 0.0
        for inputs, labels in DataLoader(TensorDataset(new_data, new_labels), batch_size=32, shuffle=True):
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item()
        print(f'Retraining Epoch {epoch+1}, Loss: {running_loss/len(new_data)}')
    torch.save(model, 'model.pth')

 

  • 모델 버전 관리
    • 모델 버전 번호 부여 및 관리
    • 모델 업데이트 시 버전 정보와 함께 기록
     
import datetime

def save_model_with_version(model, version):
    date_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
    model_path = f'model_v{version}_{date_str}.pth'
    torch.save(model, model_path)
    print(f'Model saved as {model_path}')

# 모델 저장 예시
save_model_with_version(model, 1)

 

4. 프로젝트 설명 및 진행

  • 프로젝트 개요
    • 모델 성능 모니터링 및 유지보수를 위한 실전 프로젝트 수행
    • 실시간 예측 시스템에서 모델 성능 모니터링 및 업데이트
  • 데이터셋 선택
    • Kaggle 또는 기타 오픈 데이터셋에서 프로젝트 데이터셋 선택
  • 프로젝트 단계
    • 데이터 전처리 및 준비
    • 모델 설계 및 학습
    • 실시간 예측 시스템 모니터링 설정
    • 성능 저하 원인 분석 및 모델 업데이트

5. 프로젝트 예시

  • 예시 프로젝트: 실시간 예측 시스템 모니터링 및 유지보수
    • 데이터셋 로드 및 전처리
    • 모델 학습 및 배포
    • Prometheus 및 Grafana를 이용한 성능 모니터링 설정
    • 성능 저하 시 모델 재학습 및 업데이트
     
import torch
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import torchvision.models as models
import torch.optim as optim
import torch.nn as nn
from torch.utils.data import DataLoader
from flask import Flask, request, jsonify
from prometheus_client import start_http_server, Summary
from PIL import Image
import io

# 데이터 전처리 변환
transform = transforms.Compose([
    transforms.Resize((28, 28)),
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,))
])

# MNIST 데이터셋 로드
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
val_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)

train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)

# 간단한 CNN 모델 정의
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
        self.fc1 = nn.Linear(64 * 7 * 7, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 64 * 7 * 7)  # Flatten the tensor
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 모델 학습
model = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

num_epochs = 5
for epoch in range(num_epochs):
    model.train()
    running_loss = 0.0
    for inputs, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    print(f'Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}')

# 모델 저장
torch.save(model, 'model.pth')

# Flask 앱 정의
app = Flask(__name__)

# Prometheus 설정
REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing request')

# 모델 로드
model = torch.load('model.pth')
model.eval()

# 이미지 전처리 함수
def transform_image(image_bytes):
    transform = transforms.Compose([
        transforms.Resize((28, 28)),
        transforms.ToTensor(),
        transforms.Normalize((0.5,), (0.5,))
    ])
    image = Image.open(io.BytesIO(image_bytes))
    return transform(image).unsqueeze(0)

# 예측 함수
@REQUEST_TIME.time()
def get_prediction(image_bytes):
    tensor = transform_image(image_bytes)
    outputs = model(tensor)
    _, predicted = torch.max(outputs.data, 1)
    return predicted.item()

@app.route('/predict', methods=['POST'])
def predict():
    if request.method == 'POST':
        file = request.files['file']
        img_bytes = file.read()
        prediction = get_prediction(img_bytes)
        return jsonify({'prediction': prediction})

if __name__ == '__main__':
    start_http_server(8000)  # Prometheus HTTP 서버 시작
    app.run()

 

6. 프로젝트 발표 및 코드 리뷰

  • 프로젝트 발표
    • 각 그룹 또는 개인은 프로젝트 결과 발표
    • 모델 설계, 훈련 과정, 성능 모니터링 및 유지보수 결과 공유
  • 코드 리뷰 및 피드백
    • 각 그룹의 코드를 리뷰하고 피드백 제공
    • 개선할 점 및 좋은 점 공유

7. 실습 및 과제

  • 실습 과제
    • 모델 성능 모니터링 설정 및 유지보수 계획 수립
    • Prometheus 및 Grafana를 이용한 실시간 모니터링 설정
    • 성능 저하 시 모델 재학습 및 업데이트 수행
     
# 실습 과제 예시
from flask import Flask, request, jsonify
import torch
from torchvision import transforms
from PIL import Image
import io
from prometheus_client import start_http_server, Summary

# Prometheus 설정
REQUEST_TIME = Summary('request_processing_seconds', 'Time spent processing request')

# 모델 로드 및 Flask 설정
app = Flask(__name__)
model = torch.load('model.pth')
model.eval()

def transform_image(image_bytes):
    transform = transforms.Compose([
        transforms.Resize((28, 28)),
        transforms.ToTensor(),
        transforms.Normalize((0.5,), (0.5,))
    ])
    image = Image.open(io.BytesIO(image_bytes))
    return transform(image).unsqueeze(0)

@REQUEST_TIME.time()
def get_prediction(image_bytes):
    tensor = transform_image(image_bytes)
    outputs = model(tensor)
    _, predicted = torch.max(outputs.data, 1)
    return predicted.item()

@app.route('/predict', methods=['POST'])
def predict():
    if request.method == 'POST':
        file = request.files['file']
        img_bytes = file.read()
        prediction = get_prediction(img_bytes)
        return jsonify({'prediction': prediction})

if __name__ == '__main__':
    start_http_server(8000)  # Prometheus HTTP 서버 시작
    app.run()

 

  • 과제 제출
    • Jupyter Notebook 파일 및 Flask 코드 제출
    • 제출 기한: 다음 강의 시작 전까지

 

반응형