본문 바로가기
Development/for Machine Learning

ML Python 프로젝트의 test code만들기(feat. Pytest)

by IMCOMKING 2020. 3. 16.

Test Code의 필요성

ML뿐만 아니라, 거대한 규모의 프로그램을 개발할 때에는 반드시 테스트 코드가 필요하다. 물론 협업을 하고, 대규모 프로젝트를 오랜 기간 서비스하기 위해서도 테스트 코드는 반드시 필요하다. 머신러닝 코드는 특히나 numerical한 연산을 다루기 때문에 버그를 잡기가 쉽지 않고, 엄청나게 많은 configuration이 존재하고, 학습의 재현성이 필요하기 때문에 코드의 검증이 오래 걸린다. 또한 협업을 하다보면 누군가가 추가하면서 바꾼 기능 때문에 내가 예전에 쓰던 코드가 동작하지 않는 일이 너무나 빈번하다. 이러한 일을 막고 버그를 줄이는 방법은 테스트 코드를 작성하는 것이다.


Test for ML project

머신러닝 프로젝트에 대해서도 공동 개발을 할 경우에는 pytest를 이용한 Test Coverage 측정이 필요하다. 그래서 test coverage를 대충 80%이상 통과해야 PR이 가능한 방식으로 협업을 해야한다.

그런데 일반 서비스 프로젝트와 달리 ML은 GPU로 학습이 잘 되어서 성능이 원래대로 나오는지 까지 확인해야 아마 버그 없음을 증명할 수 있을텐데, 이렇게까지 하기에는 너무 엔지니어링과 계산량이 방대하고, 연구의 영역과 겹치게 된다. 그렇다고 일반 서비스 프로젝트 처럼 함수 단위로 input과 output을 체크하는 test는 ML코드에 있어서 역시나 너무 과한 오버 엔지니어링이다.


따라서 적절한 수준은 아마도 아주 작은 1 batch-size 정도의 데이터만 가지고, cpu에서 돌렸을 때 에러가 나지 않는 정도로 정하면 딱 적절한 수준이라고 볼 수 있다. 그래서 모델에 구현된 여러가지 다양한 config에서 모두 에러 없이 실행되는 지 확인하면 된다.

https://www.facebook.com/sanghyuk.chun/posts/3780004285404427



1 단계: Dry run 성공

모델의 학습을 제외한 모든 실행이 제대로 동작하는 지 테스트한다.
코드 단에서는 매우 간단히 극소량의 데이터에 대해 1 epoch만 돌려보는 방식으로 구현한다.

2 단계: Toy dataset에 대해 training acc 100% 오버피팅 성공

아주 작은 소량의 데이터에 대해 100% overfitting이 되는지 확인한다.

3 단계: 실제 dataset에 대해 정상적인 learning curve를 확인

train/valid/test 에 대한 성능이 정상적으로 출력되는지 확인한다.



Python에서 Test code를 작성하기

우선 가장 먼저 해야 할 일은 PyTest와 Unittest 중에서 무엇을 사용할 지 선택하는 것이다. Python 개발자 커뮤니티의 여론은 PyTest가 다방면에서 우위에 있다고 한다. 따라서 나 또한 PyTest를 ML프로젝트 적용하는 것을 시도해보고자 한다.

https://www.slant.co/versus/9148/9149/~unittest_vs_pytest


PyTest


* 설치 방법

pip install pytest


* 실행 방법

python 프로젝트에 들어간 다음, pytest 을 입력하면 해당 프로젝트내에 존재하는

test_*.py or *_test.py 로 된 파일을 모두 찾아서 자동으로 실행한다.


* 테스트 코드 파일 작성 방법

위의 이름을 가진 .py 파일을 만들고, 검사할 함수를 정의한다.

원할 경우 assert를 이용해서 조건을 검사할 수도 있고, 단순 실행성공만 원하면 assert를 생략할 수도 있다.

def test_duet_sf():
class Conf:
data_usage = 1.0
batch_size = 2

assert get_dataset(Conf) is not None


* 실행 옵션

- 특정 파일/폴더 제외하고 실행하기

pytest --ignore=tests/foobar/test_foobar_03.py


* pytest의 config 파일 만들기

pytest.ini 파일을 만든다.

아래의 링크에서 필요한 옵션을 찾아 정의한다.

https://docs.pytest.org/en/latest/reference.html?highlight=pytest.ini#configuration-options


예시)

[pytest] norecursedirs = src tmp*

norecursedirs를 사용하면, --ignore로 무시할 경로를 지정하는 것과 동일한 효과를 낸다.




Jenkins와 github Webhook을 이용해 pytest 자동 실행하기



* 혹은 Travis CI를 사용할 수도 있다. https://americanopeople.tistory.com/289



댓글