Skip to content

[REFACTOR] 모델 변경 사항 반영#25

Merged
youyeon11 merged 4 commits intodevelopfrom
refactor/change-model-24
Oct 1, 2025
Merged

[REFACTOR] 모델 변경 사항 반영#25
youyeon11 merged 4 commits intodevelopfrom
refactor/change-model-24

Conversation

@youyeon11
Copy link
Contributor

📌 작업 목적

  • 모델 변경을 반영하여 반환타입 리팩토링 및 새로운 라이브러리 추가

🗂 작업 유형

  • 기능 추가 (Feature)
  • 버그 수정 (Bug Fix)
  • 리팩터링 (Refactor)
  • 성능 개선 (Performance)
  • 테스트 추가/수정 (Test)
  • 빌드/배포/환경 설정 (Chore)
  • 문서 수정 (Docs)

🔨 주요 작업 내용

  • timm 라이브러리가 추가되었습니다.
timm
  • model 변경 (LigthCNN -> EfficientNet)
    def _load_model(self, model_path: Path) -> EfficientNetBaseline:
        import __main__
        __main__.EfficientNetBaseline = EfficientNetBaseline

        object = torch.load(model_path, map_location=self.device, weights_only=False)

        if isinstance(object, nn.Module) :
            # 그 자체로 모델일 때
            model = object.to(self.device)
        elif isinstance(object, dict) :
            # 반환 타입이 state_dict
            state_dict = object
            for k in ['state_dict', 'model_state_dict', 'model']:
                if k in object and isinstance(object[k], dict):
                    state_dict[k] = object[k]
                    break

            model = EfficientNetBaseline(self.num_classes).to(self.device)

            missing, unexpected = model.load_state_dict(state_dict, strict=False)
            if missing or unexpected:
                print(f"[load_state_dict] missing keys: {missing}, unexpected keys: {unexpected}")
        else:
            # type 일치하지 않음
            raise TypeError(f"Unsupported checkpoint type: {type(object)}")

        model.eval()
        return model
  • 반환 타입이 모델 자체일 때랑 dict 형식일 때가 있어서 케이스 분리

🧪 테스트 결과

image

📎 관련 이슈


@youyeon11
Copy link
Contributor Author

🤖 Gemini 코드 리뷰 결과

1. 주요 변경 사항 요약 및 의도 파악

이 PR은 모델을 LightCNN에서 EfficientNet으로 변경하고 이에 따른 코드 수정 및 라이브러리 추가를 포함하는 리팩토링 작업입니다. 모델 변경으로 인해 torch.load 함수의 반환 타입이 모델 자체이거나 state_dict 형태일 수 있어 이를 처리하는 로직이 추가되었습니다. 또한, 새로운 모델 EfficientNet을 사용하기 위해 timm 라이브러리가 추가되었고, 모델 파일도 변경되었습니다. 이러한 변경을 통해 모델 성능 향상 및 코드 개선을 목표로 하는 것으로 이해됩니다. 관련 이슈 #24를 해결하는 PR입니다.

2. 코드 품질 및 가독성

  • 코드 스타일: 전반적으로 PEP 8 스타일 가이드를 잘 준수하고 있습니다. 다만, if isinstance(object, nn.Module):elif isinstance(object, dict): 사이에 빈 줄이 없는 부분 등 일부 간격 조정이 필요해 보입니다.
  • 변수/함수명: 변수명 object는 너무 일반적이라서 구체적인 의미를 나타내도록 loaded_model 또는 checkpoint 와 같이 변경하는 것이 좋겠습니다. state_dict 변수명은 명확하고 적절합니다.
  • 주석/문서화: _load_model 함수 내부의 주석은 각 조건문의 의도를 잘 설명하고 있어서 이해하기 쉽습니다. 하지만, 함수 자체에 대한 docstring이 없으므로 추가하는 것이 좋겠습니다. EfficientNetBaseline 클래스에도 docstring을 추가하여 pretrained, dropout 매개변수에 대한 설명을 포함하는 것이 좋습니다.
  • 중복 코드: 현재 눈에 띄는 중복 코드는 없습니다.

3. 잠재적 버그 및 엣지 케이스

  • 논리적 오류: state_dict 를 로드하는 부분에서 'state_dict', 'model_state_dict', 'model' 키 중 하나라도 존재하면 해당 값을 사용하도록 되어 있습니다. 만약 여러 키가 동시에 존재한다면 어떤 키가 우선순위를 갖는지 명확하지 않아 예상치 못한 결과가 발생할 수 있습니다. 우선순위를 명시적으로 정의하거나, 여러 키가 존재하는 경우 예외를 발생시키는 것이 좋겠습니다.
  • 경쟁 상태 (Race Condition): 현재 코드에서는 멀티쓰레드/비동기 환경에서 발생할 수 있는 경쟁 상태는 보이지 않습니다.
  • 에러 핸들링: _load_model 함수에서 TypeError를 발생시켜 지원하지 않는 checkpoint 타입을 처리하고 있는 것은 좋습니다. 하지만 load_state_dict에서 missing 또는 unexpected 키가 발생하는 경우, 현재는 단순히 출력만 하고 있습니다. 이러한 상황을 어떻게 처리할지 (예: 에러 로깅, 특정 기본값 사용)에 대한 명확한 정책이 필요합니다.

4. 성능 및 효율성

  • 시간 복잡도: 모델 로딩 부분에서 for k in ['state_dict', 'model_state_dict', 'model']: 루프는 최대 3번만 반복하므로 성능에 큰 영향을 미치지 않을 것으로 예상됩니다. 전반적인 성능은 EfficientNet 모델 자체의 성능에 더 의존적일 것입니다.
  • 자원 사용: 현재 코드에서 메모리 누수나 불필요한 I/O, 과도한 DB 쿼리 등이 발생할 가능성은 보이지 않습니다.
  • 최적화 제안: state_dict 로딩 로직에서 여러 키 중 하나를 선택하는 부분을 개선하여 우선순위를 명확히 하고 예외 처리를 추가하여 더욱 안전하게 구현할 수 있습니다.

5. 보안 및 아키텍처

  • 보안 취약점: 현재 코드에서 특별한 보안 취약점은 보이지 않습니다.
  • 아키텍처 적합성: 모델 변경은 애플리케이션의 아키텍처에 영향을 미칠 수 있는 중요한 변경입니다. 이 PR이 기존 시스템 아키텍처와 어떻게 부합하는지에 대한 설명이 PR 본문에 추가되면 좋겠습니다. 예를 들어, 모델 변경으로 인해 다른 부분의 코드 수정이 필요한지, API 스펙에 변경이 있는지 등을 명시하는 것이 좋습니다.
  • 확장성: 모델 변경은 향후 다른 모델로의 변경을 용이하게 하기 위해 추상화 계층을 도입하는 것을 고려해 볼 수 있습니다. 예를 들어, _load_model 함수가 특정 모델 클래스에 의존하지 않고 더 일반적인 인터페이스를 사용하도록 리팩토링하면 새로운 모델을 추가할 때 _load_model 함수를 수정하지 않고도 새로운 모델 클래스만 구현하면 되도록 변경할 수 있습니다.

@gemini-code-assist
Copy link

Summary of Changes

Hello @youyeon11, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 PredictorService에서 사용되는 모델을 LightCNN에서 EfficientNetBaseline으로 업데이트하는 것을 목표로 합니다. 이를 위해 timm 라이브러리를 통합하고, 다양한 형식으로 저장된 모델을 로드할 수 있도록 모델 로딩 로직을 개선했습니다. 전반적인 시스템의 모델 성능 및 유연성 향상에 기여할 것으로 예상됩니다.

Highlights

  • 모델 변경: 기존 LightCNN 모델이 EfficientNetBaseline 모델로 교체되었습니다. EfficientNetBaseline은 timm 라이브러리를 활용하여 구현되었습니다.
  • 라이브러리 추가: 새로운 모델 구현을 위해 timm 라이브러리가 requirements.txt에 추가되었습니다.
  • 모델 로딩 로직 개선: 모델 로딩 시, 저장된 객체가 nn.Module 인스턴스인지 state_dict 딕셔너리인지에 따라 유연하게 처리하도록 _load_model 메서드가 리팩토링되었습니다.
  • 모델 경로 업데이트: 서비스에서 사용하는 기본 모델 파일 경로가 best_model_0823.pt에서 best_model_0920.pt로 변경되었습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

모델 구조를 LightCNN에서 EfficientNet으로 변경하고, timm 라이브러리를 도입한 리팩토링 작업이네요. 모델 로딩 로직을 유연하게 변경하여 nn.Module 객체와 state_dict를 모두 처리할 수 있도록 한 점이 인상적입니다. 다만, state_dict를 로딩하는 로직에 치명적인 버그가 있어 수정이 필요하며, 로깅 및 의존성 관리 관점에서 몇 가지 개선 사항을 제안합니다. 자세한 내용은 각 파일의 주석을 참고해주세요.

state_dict = object
for k in ['state_dict', 'model_state_dict', 'model']:
if k in object and isinstance(object[k], dict):
state_dict[k] = object[k]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

이 부분의 로직에 오류가 있습니다. state_dict에서 실제 모델의 상태 사전을 추출해야 하는데, 현재 코드는 아무런 효과가 없습니다. state_dict = object[k]로 수정하여야 올바르게 state_dict를 갱신할 수 있습니다.

Suggested change
state_dict[k] = object[k]
state_dict = object[k]


missing, unexpected = model.load_state_dict(state_dict, strict=False)
if missing or unexpected:
print(f"[load_state_dict] missing keys: {missing}, unexpected keys: {unexpected}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

print 문을 사용하여 로그를 남기는 것보다 logging 모듈을 사용하는 것이 좋습니다. 서비스 환경에서는 logging을 통해 로그 레벨 관리, 포맷팅, 핸들러 설정 등 더 체계적인 로깅이 가능합니다. 파일 상단에 import logging을 추가하고, 이 부분은 logging.warning(...)을 사용하여 경고 메시지를 기록하는 것을 권장합니다.

Suggested change
print(f"[load_state_dict] missing keys: {missing}, unexpected keys: {unexpected}")
import logging
logging.warning(f"[load_state_dict] missing keys: {missing}, unexpected keys: {unexpected}")

dotenv
openai No newline at end of file
openai
timm No newline at end of file

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

재현 가능한 빌드를 위해 의존성 버전을 고정하는 것이 좋습니다. timm 라이브러리의 버전을 명시해주세요 (예: timm==0.9.16). 또한, 파일의 마지막에 개행 문자를 추가하는 것이 일반적인 관례입니다.

timm==0.9.16

@youyeon11 youyeon11 merged commit 893ce40 into develop Oct 1, 2025
@youyeon11 youyeon11 mentioned this pull request Oct 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant