드디어 마지막 stage인 Product serving에 도달하게 되었다.
이전부터 자주 글로 소통하시던 마스터님이셔서 그런지 강의도 엄청나게 많고 내용도 많아보였다.
최종 프로젝트와 같이 병행해야 해서 모든 지식을 습득할 수 있을 지 걱정되지만, 두 마리 토끼 다 잡도록 노력하자.
강의 듣는 거 보단 최종 프로젝트부터 진행하는게 좋다고 판단함.
무엇을 했나요?
지난주까지 대회에 집중하느라 최종 프로젝트에서 내가 맡은 파트인 Pytorch 모델을 on-device에서 구동 가능하도록 Porting하는 방법에 대해 조사하지 못했다. 그래서 일단 강의는 미뤄두고 ONNX에 대해 조사하며, 학습한 모델을 ONNX로 변환하는 방법과 어떤 원리로 변환이 되고, 변환을 하기 위해 조정해야 하는 게 무엇인지 찾아보았다.
별다른 블로그 글이나 동영상을 찾지 못해 공식문서의 tutorial과 github에 의존해서 ONNX를 배우고 있다.
현재까지 알게 된 바로는 변환할 모델의 Input size를 고정시켜 줘야 한다는 점, ONNX가 갖고 있는 Operator로 mudule들을 ONNX에 맞게 변환시키기 때문에 모델은 반드시 이에 맞는 구조를 갖춰야 한다는 점이다. 두 번째 내용이 중요한데, 자세히 조사해보진 않았지만 만약 porting을 원하는 모델에 맞는 operator가 없을 경우, 내가 직접 operator를 만들어야 하는 것 같다. 다만 이 과정이 상당히 어려워 보였다. (이 점 때문에 멘토님께서 API로 저장된 모델을 사용하는 걸 추천하셨다.)
일단은 쉽게 변환이 되는 모델을 불러 ONNX로 변환하는 코드를 만들었고, ONNX가 만들어지는 것까지 확인하였다. 내일은 이 파일이 정상적인 구조를 갖고 있는지 확인하고, 이를 다시 TFLite로 변환하는 코드를 구현할 예정이다.
model_path = os.path.join(model_dir, 'deeplabv3_mobilenet_v3_large_sample.pth')
model_pt = torch.load(model_path)
model = torch.hub.load('pytorch/vision:v0.10.0', 'deeplabv3_mobilenet_v3_large', pretrained=True).to(device)
model.load_state_dict(model_pt)
model.eval()
batch_size = 8
dummy_input = torch.zeros(batch_size, 3, 960, 720).to(device)
input_names = [ "actual_input_1" ] + [ "learned_%d" % i for i in range(16) ]
output_names = [ "output1" ]
# 'f' 파라미터로 파일 이름 맞추는 거 잊지말기
torch.onnx.export(model, dummy_input, f='sample_onnx_model.onnx', verbose=True, input_names=input_names, output_names=output_names,
operator_export_type=torch.onnx.OperatorExportTypes.ONNX_ATEN_FALLBACK)
모델은 멘토님 추천대로 DeepLabV3를 사용해보고 있고, 전체 파이프라인을 확인한 후 성능을 보고 점차 더 작은 모델을 쓸 생각이다.
아직 input_names와 output_names는 어떤 식으로 입력되는 지는 잘 모르겠다.