머신러닝 엔지니어 실무-Section2-1
인프런 Chris Song님 강의 정리
Section2: 코드 품질, 데이터 검증, 모델 분석
리서치 코드 품질 관리
코드 품질 문제 유형
- 각자 개인 컴퓨터에 저장되어 있음
- 복사 붙여넣기로 개발된 코드로 인한 중복이 많다
- 연구 결과 재연이 불가능
- 너무 많은 전역 변수 (side-effect)
 --> 최대한 파라미터를 전달하고 받아오는 방식으로 고쳐야함..
- 너무 긴 코드 (디버깅 불편, 함수와 클래스 구분이 명확하지 않음)
 --> python의 경우 500 line 미만으로 개발!
- 상대 참조 (나중에 폴더 구조가 바뀌면, 디버깅이 어려워짐)
 --> PYTHONPATH 환경변수를 활용해서 시작 지점을 명확하게 하고, absolute import를 사용해야함
- 명확하지 않은 변수명
깨진 유리창의 법칙
- 만일 한 건물의 유리창이 깨어진 채로 방치되어 있다면, 곧 다른 유리창들도 깨어질 것
- 코드 품질 문제도 좋지 않으면, 다른 사람들의 코드 품질도 안 좋아 질 것이다.
린트와 유닛테스트
린트란? (강좌에 없는 내용)
개념
- 문법 오류, 코드 컨벤션 등을 잡아주는 검사기
- 의심스럽거나, 에러를 발생하기 쉬운 코드에 표시(flag)를 달아 놓음
- 매번 코드 리뷰를 통해 코드 컨벤션을 체크할 수 있지만,
 모든 코드를 매번 체크하면서 컨벤션을 유지하는 것은 어려움
- 각 언어 별로 이를 위한 도구가 존재하는데, 이를 Lint한다고 하는 것 같음
flake8
- Python의 Lint 도구
- PEP8을 기반으로 코드 컨벤션을 검사함
- Flake8 Rules
  
 
- 예시
# main.py
import os
def    helloworld(s):
    return f"Hello World! {s}"
if __name__ == '__main__':
    print(helloworld('Caleb'))
flake8 main.py

1) F401 --> os 라이브러리를 impor 해놓고 사용하지 않았다.
2) E302 --> 라이브러리를 import 했으면 두 줄은 띄워라
3) E271 --> helloworld 함수 명칭에 공백 여러개가 있다
4) E305 --> 함수나 클래스를 정의한 이후에 비어있는 2줄을 넣어라
5) W292 --> 파일의 마지막에는 공백 line을 삽입해라
- 예시 수정
def helloworld(s):
    return f"Hello World! {s}"
if __name__ == '__main__':
    print(helloworld('Caleb'))
    
black
- 코드의 가독성을 높여줌
- 자동으로 re-format을 해줌
# Before
def       helloworld(a):
    print("Hello world! {a}!")#asdasd
if __name__ == "__main__":
    helloworld("Yang")
--> 최대한 파라미터를 전달하고 받아오는 방식으로 고쳐야함..
--> python의 경우 500 line 미만으로 개발!
--> PYTHONPATH 환경변수를 활용해서 시작 지점을 명확하게 하고, absolute import를 사용해야함
모든 코드를 매번 체크하면서 컨벤션을 유지하는 것은 어려움

# main.py
import os
def    helloworld(s):
    return f"Hello World! {s}"
if __name__ == '__main__':
    print(helloworld('Caleb'))flake8 main.py

1) F401 --> os 라이브러리를 impor 해놓고 사용하지 않았다.
2) E302 --> 라이브러리를 import 했으면 두 줄은 띄워라
3) E271 --> helloworld 함수 명칭에 공백 여러개가 있다
4) E305 --> 함수나 클래스를 정의한 이후에 비어있는 2줄을 넣어라
5) W292 --> 파일의 마지막에는 공백 line을 삽입해라
def helloworld(s):
    return f"Hello World! {s}"
if __name__ == '__main__':
    print(helloworld('Caleb'))
    # Before
def       helloworld(a):
    print("Hello world! {a}!")#asdasd
if __name__ == "__main__":
    helloworld("Yang")
# After
# black main.py
def helloworld(a):
    print("Hello world! {a}!")  # asdasd
if __name__ == "__main__":
    helloworld("Yang")타입 어노테이션/타입 체크란? (강좌에 없는 내용)
- 파이썬의 동적(dynamic) 타입 처리는 일회성 script or 소규모 application을 개발할 때는 큰 장점으로 작용함
- 하지만 application 규모가 커지게 되면, 다이나믹함이 치명적인 버그로 이어질 확률이 높음
 --> 이는 안정성에 위험 요소로 작용함
- 타입 어노테이션(type annotation)은 파이썬 코드에 타입을 명시하기 위한 표준을 정립하기 위한 것- python 3.5부터 추가됨
 
- 변수나 함수에 타입이 명시된 파이썬 코드는 정적 타입 검사기를 통해 코드를 실행하지 않고도 타입 에러를 찾아낼 수 있음
타입 검사
- gi라는 변수의 타입을 int로 명시하기 위해 타입 어노테이션을 추가했다.
- 아래 코드를 python으로 실행하면 문제 없이 돌아간다.- 타입 어노테이션은 언어 레벨에서는 코드 실행에 아무 영향이나 제약을 주지 않기 때문
 
- 아래와 같이 타입 어노테이션을 사용하는 것을 타입 힌팅(type hinting)이라고 한다.- 주로 코드를 읽기 쉽게 하거나, 코드 편집기(IDE), 린터(linter)에서 활용됨
 
# test.py
# python test.py
gi: int="4"
print(gi)
- 하지만 위 코드를 mypy로 실행해보면 에러가 발생한다.- 변수의 타입과 저장된 값의 타입이 다른 type error 발생
 
# test.py
# mypy test.py
gi: int="4"
print(gi)

- mypy를 사용하면 python interpreter가 잡지 못하는 타입 버그를 찾아낼 수 있음
오류 검사
- mypy를 사용하면 타입 자체의 버그 뿐만 아니라 실제 런타임에 발생할 수 있는 오류를 미리 알아낼 수도 있음
- 아래 코드를 실행하면 gi 함수 두 번째 인자에 str타입이 넘어가기에 오류가 발생함
# test.py
# python test.py
def gi(msg: str, times: int=1) -> list:
    return [msg] * times
gi("Hi", "4")

- 위 코드를 mypy로 돌려보면 미리 오류가 발생할 것임을 알려준다.
# test.py
# mypy test.py
def gi(msg: str, times: int=1) -> list:
    return [msg] * times
gi("Hi", "4")

지속적 통합 (CI)
- Continuous integration
- 소프트웨어의 질적 향상을 채크하고 배포 시간을 줄일 수 있음
- Ex. Github Actions, Jenkins
CI란? (강좌에 없는 내용)
- 팀의 구성원들이 작업한 내용을 정기적으로 통합하는 것- 각각의 팀멤버들로부터 Submit된 소스코드를 정기적으로 통합하는 것
 
- CI tool: 위 내용을 시행해주는 프로그램
CI 시스템 구축
- CI 시스템이 구축되지 않은 경우: - 개발자들이 각자 개발한 소스코드를 형상관리 서버에 커밋하면 별도의 품질관리를 거치지 않고, 대부분 개발이 끝난 막바지에 통합을 하여 테스트를 진행함
- 이 경우, 잘못된 소스코드를 형상관리 시스템에 반영하였을 경우에 발생되는 문제가 개발 후반에 장애로 발견됨
 
- CI 시스템이 구축된 경우: - CI서버는 형상관리 서버에 Commit된 소스코드를 주기적으로 폴링하여 컴파일, 단위테스트, 코드 인스펙션 등의 과정을 수행- 폴링: - 일정한 주기를 가지고 서버와 응답을 주고 받는 방식
- 충돌 회피 또는 동기화 처리의 목적으로 다른 장치의 상태를 주기적으로 검사하여 일정한 조건을 만족할 떄 송수신 등의 자료처리를 함
 
- 컴파일: 사람의 언어를 컴퓨터가 이해할 수 있는 언어로 바꿔주는 과정
- 코드 인스펙션: 정의된 룰을 기반으로 소스 코드를 검사하여 오류 및 위험요인을 식별하여 알려주는 기능
 
- 폴링: 
- 신규 or 수정된 소스코드가 결함이 있는지 여부를 지속적으로 검증함
- 검증 결과는 이메일, RSS등의 피드백 매커니즘을 통해 개발자에게 전달- RSS: 블로그, 뉴스, 칼럼 등 업데이트가 잦은 콘텐츠들을 사용자가 편하게 볼 수 있도록 만들어진 규약
 
- 조기 결함을 발견하여 해결 가능
 
- CI서버는 형상관리 서버에 Commit된 소스코드를 주기적으로 폴링하여 컴파일, 단위테스트, 코드 인스펙션 등의 과정을 수행
Github Actions (강좌에 없는 내용)
개요
- Github에서 제공하는 워크플로우(workflow)를 자동화하도록 도와주는 도구
- 테스트, 빌드, 배포 등의 다양한 작업들을 자동화하여 처리
- public 저장소의 경우 무료로 사용 가능하며 private 저장소는 월마다 제공되는 무료 사용량 초과 시에 요금이 부과- 무료 계정 기준 500MB의 스토리지와 월마다 2,000분 제공
 
- Github 저장소에서 등록하거나 .github/workflows폴더 내에.yml파일을 추가하여 등록할 수 있음- Github 저장소 등록 
- yml파일 --> 강의 내용
 
- Github 저장소 등록
Github Actions의 구성
- 워크 플로우(workflows)- 저장소에 추가하는 자동화된 프로세스
- 하나 이상의 job으로 이루어져 있으며, 이벤트에 의해 실행됨
 
- 이벤트(Events)- 워크플로우를 실행하는 특정 활동이나 규칙
- 커밋의 push, pull request가 생성되었을 때, 저장소 dispath event를 통해 Github 외부에서 발생하는 활동으로도 이벤트를 발생시킬 수 있음
- schedule에 POSIX cron 문법으로 스케줄 이벤트를 발생시킬 수 있음
 
- 러너(runners)- Github 액션 러너 애플리케이션이 설치된 서버
- Github에서 호스팅하는 러너를 사용할 수도 있고 직접 호스팅 할 수도 있음
 
- 작업(jobs)- 워크플로우의 기본 단위
- 스텝으로 이루어져 있음
- 워크플로우는 여러 작업을 병렬적으로 실행하며 순차적으로 실행하도록 설정 할 수 있음- 빌드와 테스트 코드 수행 작업을 순차적으로 실행 (빌드 실패 시, 테스트는 진행 실행되지 않음)
 
 
- 스텝(steps)- 작업에서 커맨드를 실행하는 독립적인 단위
- 한 작업의 각 스텝들은 동일한 러너에서 실행되므로 해당 작업의 액션들은 서로 데이터를 공유함
 
- 액션(actions)- 워크플로우의 가장 작은 요소
- 직접 만들어 사용할 수도 있고, 마켓에 등록된 만들어진 것을 가져와 사용할 수도 있음
 
워크 플로우 관리
- 민감한 정보 저장- 비밀번호, 인증서 같은 정보는 Github에 secret으로 저장하여 환경변수로 사용이 가능함
 
- 의존적인 작업 구성- 작업은 병렬적으로 수행됨
- 다른 작업이 완전히 끝난 후에 작업을 실행시키고 싶다면 needs 키워드를 통해 작업이 의존성을 갖도록 지정하면 됨 
 
- 빌드 매트릭스 활용- 워크플로우가 다양한 OS, 플랫폼, 언어의 여러 조합에서 테스트를 실행하려는 경우 빌드 매트릭스를 활용하면 됨
- 빌드 옵션을 배열로 받는 strategy 키워드를 사용하면 됨 
 
- 종속성 캐싱- GIthub의 러너는 각 작업에서 새로운 환경으로 실행됨
- 작업들이 종속성을 재사용하는 경우 파일들을 캐싱하여 성능을 높이면 됨
- 캐시를 생성하면 해당 저장소의 모든 워크플로우에서 사용 가능 
 
Github Actions 적용사례

- Github에서 Pull Request를 생성했을 때, 자동으로 Github이 다음과 같이 3가지 작업을 자동으로 수행시킴- 테스트 자동화: 유닛테스트를 돌린 후 결과를 Code Climate에 전송
- 코드 Lint 체크: black & flake8 
 
코딩 컨벤션 체크 자동화 Workflow
- 코딩 컨벤션을 따라야하는 이유- 코드 가독성을 높여서 함께하는 팀원들에 대한 배려
- 코드의 품질 및 코딩 속도 향상
- 모든 팀원들이 동일한 스타일의 코드를 유지
 
- Github repository에서 .github/workflows/lint.yml파일을 생성- 아래와 같이 workflow를 설정해두면, 앞으로 코딩 컨벤션을 맞추지 못하면 Github가 PR merge를 차단함
- main 브랜치에 본인의 코드를 머지하려면 코딩 컨벤션을 맞춰야만 함
 
name: Lint Code Base
on: push
jobs:
  # Set the job key. The key is displayed as the job name
  # when a job name is not provided
  super-lint:
    # Name the Job
    name: Lint Code Base
    # Set the type of machine to run on
    runs-on: ubuntu-latest
    env:
      OS: ${{ matrix.os }}
      PYTHON: '3.7'
    steps:
      # Checks out a copy of your repository on the ubuntu-latest machine
      - name: Checkout code
        uses: actions/checkout@v2
      # Runs the Super-Linter action
      - name: Lint Code Base
        uses: github/super-linter@v3
        env:
          DEFAULT_BRANCH: master
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          VALIDATE_PYTHON_BLACK: true
          VALIDATE_PYTHON_FLAKE8: true
테스트 자동화 Workflow
- 
테스트 자동화 시스템 구축 이유 - 설계 수정 시간의 단축- 설계 수정은 시간이 지날 수록 그 비용이 급격하게 증가함
- 테스트를 먼저 설계하고 개발을 진행하게 되면, 각 함수의 구조와 기능 정의를 명확하게 하므로, 설계의 구조적 문제를 빠르게 찾아낼 수 있게됨
 
- 객체지향적인 코드 개발- 본격적인 개발에 앞서 테스트 코드를 먼저 작성한다면 좀 더 명확한 기능과 구조를 설계할 수 있음
 
- 디버깅 시간 단축- 모델의 인퍼런스 결과가 이상한 경우엔 그 원인이 어디로부터 왔는지 명확하게 이해하기 어려움
- 데이터 전/후 처리에 테스트 코드를 작성하면, 모델의 인퍼런스 결과를 좀 더 신뢰할 수 있음
 
- 유지보수 용이성- 테스트 코드들을 작성하게 되면, 한 모듈의 기능 변화가 다른 모듈에 어떤 영향을 미치는 지 테스트 코드를 돌려봄으로써 바로 추적할 수 있게됨
- 기능을 추가하더라도 사이드 이펙트에 대한 염려로부터 자유로워짐
 
 
- 설계 수정 시간의 단축
- 
Code Climate: 코드 품질 관리를 모니터링하도록 해주는 유료 솔루션 (오픈소스의 경우에는 무료)  - 코드 품질 모니터링 대시보드 생성 가능
- 코드의 결함이나 안좋은 패턴들을 감지하고 자동으로 코드 리뷰가 달림 --> 코드 리뷰 자동화 (생산성 향상) 
 
참고
- Flake8로 Python Code를 Lint 해보자
- 파이썬 타입 체크 - Mypy
- CI란?
- 폴링이란
- 폴링개념
- 인터럽트(interupt)와 폴링(polling)의 차이와 개념
- 컴파일이란
- 정적 테스트와 코드 리뷰 - 코드 인스펙션
- RSS 란 무엇인가
- Github Actions이란?
- 리서치 코드의 지속적 통합(CI) 튜토리얼(상편)
- 리서치 코드의 지속적 통합(CI) 튜토리얼(하편)
Author And Source
                            
                            이 문제에 관하여(머신러닝 엔지니어 실무-Section2-1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
                                
                                https://velog.io/@gjtang/머신러닝-엔지니어-실무-Section2-1
                            
                            
                            
                                저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
                            
                            
                                
                                
                                 우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                            
                            
                        
                    
                
                
                
            
Author And Source
이 문제에 관하여(머신러닝 엔지니어 실무-Section2-1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@gjtang/머신러닝-엔지니어-실무-Section2-1저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)