일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 백준
- CPU스케줄링
- 해시
- SpringBatch
- 외래키제약조건위반
- 폰켓몬
- 트리맵
- 2178
- BFS
- Spring JPA
- JPA
- 프로그래머스
- DB replication
- 운영체제
- 그래프탐색
- 구현
- 트리셋
- 산업은행청년인턴
- fatch
- 프로젝트
- springboot
- CS
- 임베디드타입
- flyway
- 파이널프로젝트
- 컴퓨터구조
- 스케일아웃
- 코테
- findById
- 산업은행it
- Today
- Total
나 JAVA 봐라
[학부 연구] 자기지도학습을 통한 신장분할 본문
'자기지도학습을 통한 신장분할' 을 주제로 학부 연구 했던 내용을 정리해본다.
멀티미디어학회에 제출한 논문 링크입니다! -> 복부 CT 영상에서 직소 퍼즐 기반 자기지도학습을 통한 신장 분할
내가 한 일들
(데이터 전처리, 논문 리뷰,... 등의 여러 활동을 했지만 실험 효율을 위해 했던 노력에 대해서만 작성해본다 !)
기존 실험 방식은 아래와 같다.
1. 4개의 dataset 중 하나를 정한다. (각각 25%, 50%, 75%, 100% 데이터셋이 있음)
2. 해당 dataset에 대해 여러 파라미터로 train을 진행한다. (lr은 0.005, 0.01 / batch_size는 8, 16, 32 -> 조합하면 총 6번의 실험)
3. 각 train/test의 결과를 지정된 디렉토리에 저장한다.
처음 연구를 시작했을 때, 코드 내에서 파라미터를 직접 수정하여 하드코딩 했어야 했다.
이렇게 하드 코딩하며, "코드를 수정하며 잘못된 파라미터 값을 넣는" 등의 실수가 생겼다.
매번 코드 수정하는 것도 시간이 들어가기에, 우선은 인라인으로 파라미터를 전달할 수 있도록 "argparse"를 사용했다. 이를 통해 코드 수정 없이도 파라미터 값을 바꾸어 유연성이 향상되었다.
# <기존의 하드코딩 해야하는 코드>
lr = 0.005
batch_size = 8
num_epoch = 200
data_dir = "data_dir 경로(train data가 저장된 경로)"
data_dir_test = "data_dir_test 경로 (test data가 저장된 경로)"
best_ckpt_dir = "best_ckpt_dir 경로 (특정 체크포인트의 모델을 저장하는 경로.)"
patience = 20
result_dir = "result_dir 경로 (test 데이터에 대한 segmentaion 결과)"
mode = "test" # 모드가 train 이면 train/ test면 test 수행
# <argparse를 활용하여 수정한 코드>
parser = argparse.ArgumentParser(description="Pytorch-UNet-JigsawEncoder",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--lr", default=0.005, type=float, dest="lr")
parser.add_argument("--batch_size", default=8, type=int, dest="batch_size")
parser.add_argument("--num_epoch", default=200, type=int, dest="num_epoch")
parser.add_argument("--data_dir", default="train data default 경로", type=str, dest="data_dir")
parser.add_argument("--data_dir_test", default="test data default 경로", type=str, dest="data_dir_test")
parser.add_argument("--best_ckpt_dir", default="best_ckpt_dir default 경로", type=str, dest="best_ckpt_dir")
parser.add_argument("--patience", default=20, type=int, dest="patience")
parser.add_argument("--result_dir", default="segmentation default 경로", type=str, dest="result_dir")
parser.add_argument("--mode", default="test", type=str, dest="mode") #모드가 train 이면 train/ test면 test 수행
args = parser.parse_args()
위와 같이 수정했기에 명령줄에서 파라미터를 전달하여 실행할 수 있었다.
# <인라인으로 파라미터 전달>
python train.py --lr 0.005 --batch_size 16 --data_dir "/home/data_meniscus/train-kid-labeled-small-foreground-25" --best_ckpt_dir "기본경로/SL25_0.005_16/bestcheckpoint" --result_dir "기본경로/SL25_0.005_16/result" --save_csv_dir "기본경로/SL25_0.005_16/csv" --mode "train"
실제 실험을 진행할 때에는 실험마다 사용하는 데이터셋, 저장되는 디렉토리, lr, batch_size 등 파라미터가 다 달랐기에 매 실험마다 다른 값을 입력해야했다. 하여 전보다는 편해졌지만 여전히 수동으로 파라미터를 입력해야했고, 휴먼 에러가 잦았다. (문제점 1)
또한, 이렇게 하더라도 한 줄씩밖에 실험하지 못하기에, 해당 실험이 끝날 때까지 기다렸다가 끝나면 다른 파라미터 입력해서 또 실험 돌리고... 하는 과정들이 너무 비효율적이었다. (문제점 2)
그리고 학교 서버를 사용하면서 사용할 수 있는 GPU를 분명 받았는데, 장기간 자리를 비워서 실험을 하지 않으면 바로 알아채고 내 GPU 털림ㅠ... 여튼 실험을 계속 할 수가 없었다. (매일매일 벌어지는 GPU 쟁탈전) 그래서 GPU를 쉬는 텀 없이 사용해야 했다,,
그래서 쉘 스크립트 작성을 통해
1. 여러 파라미터 조합으로 알아서 실험이 진행되고(자동화),
2. 경로도 직접 입력할 필요 없이 컨벤션에 맞춰서 알아서 디렉토리에 저장될 수 있도록 했다.
# <작성한 쉘 스크립트>
#!/bin/bash
# 파라미터 값들을 배열로 정의
lrs=(0.005 0.005 0.005 0.01 0.01 0.01)
batch_sizes=(8 16 32 8 16 32)
data_dir="/home/data_meniscus/train-kid-labeled-small-foreground-25"
# 반복문을 통해 각 파라미터에 대해 실행
for ((i=0; i<${#lrs[@]}; i++)); do
# 파이썬 스크립트 실행
python train2.py --lr ${lrs[$i]} --batch_size ${batch_sizes[$i]} --data_dir "$data_dir" --mode "train"
done
쉘 스크립트에서 lrs, batch_sizes, data_dir만 바꾸어주면 수동 작업 필요없이 원하는 파라미터로 실험이 자동화되었다.
# 경로 설정 간소화
parser = argparse.ArgumentParser(description="Pytorch-UNet-JigsawEncoder",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--lr", default=0.005, type=float, dest="lr")
parser.add_argument("--batch_size", default=8, type=int, dest="batch_size")
parser.add_argument("--num_epoch", default=200, type=int, dest="num_epoch")
parser.add_argument("--data_dir", default="/home/data_meniscus/train-kid-labeled-small-foreground-25", type=str, dest="data_dir")
parser.add_argument("--data_dir_test", default="/home/data_meniscus/KiTS19/test-kid-small", type=str, dest="data_dir_test")
parser.add_argument("--best_ckpt_dir", default=None, type=str, dest="best_ckpt_dir")
parser.add_argument("--patience", default=20, type=int, dest="patience")
parser.add_argument("--result_dir", default=None, type=str, dest="result_dir")
parser.add_argument("--mode", default="test", type=str, dest="mode") #모드가 train 이면 train/ test면 test 수행
args = parser.parse_args()
# best_ckpt_dir 및 result_dir 경로 설정
if args.best_ckpt_dir is None:
args.best_ckpt_dir = f"~/{args.data_dir[-2:]}_{args.lr}_{args.batch_size}/bestcheckpoint"
if args.result_dir is None:
args.result_dir = f"~/{args.data_dir[-2:]}_{args.lr}_{args.batch_size}/result"
또한, 저장되는 디렉토리도 "데이터셋 종류(25,50,75,100 중 하나) + lr + batch_size" 로 통일하여서 직접 입력하지 않도록 했다.
위와 같이 인라인 입력과 쉘 스크립트를 활용한 자동화 작업으로 얻은 성과(내가 느꼈을 때)와 느낀 점은 아래와 같다.
1. 반복 작업 자동화
- 매번 명령어를 입력할 필요 없이 스크립트를 실행하여 자동화하여, 시간을 절약하고 실수를 줄였다. (기존에는 일주일에 6번 정도 모델 학습이 진행되었다면, 이제는 비어있는 시간 없이 계속 실험이 진행되다보니 30번 정도 모델 학습이 되었다.)
2. 파라미터 관리 용이
기존에는 매번 명령어를 입력하여 파라미터를 변경하기에 다음에 어떤 파라미터를 입력해야하는지 혼란이 있었다. 하지만 스크립트 내에서 파라미터를 설정하여, 기존의 불편함을 해결했다. 또한, 여러 파라미터 다양한 조합으로 간편하게 실험할 수 있었다.
느낀 점
단순한 작업이라 할지라도, 이를 자동화함으로써 효율성을 크게 향상시킬 수 있다는 것을 알았다.
새로운 기술을 도입하거나 복잡한 알고리즘을 구현하지 않고, 현재의 도구를 최대한 활용하는 것만으로도 많은 시간과 노력을 절약할 수 있기에, 문제를 해결하는데 있어 적절한 방법을 선택하는 것이 중요함을 배웠다.
또한, 효율적인 실험 환경의 중요성을 깨달았다. 실제로 자동화를 통해 실험 속도가 향상되어, 주어진 시간 내에 더 많은 조합으로 실험을 수행했다. 그리고 이는 실제 연구 성과에도 큰 도움이 되어 국제 학회에 논문 제출 예정이다. 이를 통해 효율성을 고민하는 태도를 갖추어 향후 프로젝트에서도 효율적인 개발을 위해 노력하게 되었다.
'프로젝트' 카테고리의 다른 글
[Spring Boot] SSE로 알림 기능 구현하기 (0) | 2024.03.11 |
---|---|
Boot-Up : 개발 전 시동 걸기 (1) | 2023.12.20 |