Skip to content
Guides3 min read

브라우저 탭에서 돌아가는 분할을 내놓기까지

클릭 분할과 개방 어휘 텍스트 프롬프트가 모두 GPU 없이 클라이언트에서 돕니다. 그러기까지 필요했던 것은 검증된 인코더 계약, 측정으로 고른 양자화, 그리고 손으로 쓴 토크나이저였습니다.

Potato Team

pip install potato-annotation 하나로 GPU도, 새 파이썬 의존성도, 주석 시점의 외부 통신도 없이 분할이 동작해야 합니다.

마지막 제약은 사치가 아닙니다. 몇몇 연구 그룹은 Potato를 에어갭 환경에 배포하는데, 거기서 클릭 시점에 내려받는 모델은 느린 기능이 아니라 없는 기능입니다. 그래서 Potato의 이미지 보조 모델 두 개는 모두 ONNX Runtime Web을 통해 주석자의 브라우저에서 돕니다. 클릭 분할에는 MobileSAM, 텍스트 프롬프트에는 Grounding DINO입니다.

거기에 들어간 세 가지는 적어 둘 만합니다. 이 프로젝트 바깥에도 통하기 때문입니다.

인코더 계약에는 그럴듯한 해석이 여럿 있다

SAM의 이미지 인코더는 전처리된 텐서를 받는데, 그 명세에는 해석의 여지가 있습니다. 정규화, 리사이즈 관례, 패딩, 채널 순서입니다.

우리는 한 가지 해석을 구현해 마스크를 얻었습니다. 보기에 멀쩡했습니다. 정답 대비 중심점 오차는 70에서 148픽셀, 파이프라인이 망가진 것이 아니라 조금 엉성한 주석자로 읽히는 종류의 오차였습니다. 서로 다른 그럴듯한 해석 셋이 모두 자신만만하고 그럴듯한, 틀린 마스크를 내놓았습니다.

올바른 해석은 0.1px에 안착합니다.

교훈은 "명세를 더 꼼꼼히 읽어라"가 아닙니다. 여기서의 잘못된 해석은 정답 없이는 보이지 않는다는 것입니다. 마스크는 모양이 맞고, 대체로 맞는 자리에 있으며, 아래쪽 검사는 전부 통과합니다. 네 후보를 갈라놓는 것은 알려진 정답과의 수치 비교뿐이고, 그중 맞는 것은 하나입니다.

그래서 이 계약은 주석에 적어 두는 대신 실제 가중치에 대한 테스트로 고정되어 있습니다. 주석도 똑같이 참이었겠지만 회귀는 잡지 못했을 것입니다.

양자화는 진짜 선택이었다

686MB 모델을 브라우저에서 돌리려면 양자화는 선택 사항이 아닙니다. 다만 어떤 양자화를 쓸지는 대개 내보내기 도구의 기본값이 정해 버립니다.

완전 정밀도 Grounding DINO 내보내기와 견주어 측정한 결과입니다.

내보내기완전 정밀도 대비 박스 IoU크기
q4f160.972151 MB
int80.874201 MB

q4f16은 원래의 기하 구조를 눈에 띄게 더 많이 보존하면서 동시에 50MB 더 작습니다. int8이 관행적인 선택이고, 그랬다면 더 큰 파일에 더 나쁜 모델을 담아 내놓았을 것입니다.

이것을 재는 데 반나절이 걸렸고, 재지 않았다면 그 선택은 영구히 남았을 것입니다. 화면에 박스가 뜨기 시작한 뒤에 양자화 선택을 다시 들여다보는 사람은 없기 때문입니다.

이후 COCO의 고양이 두 마리 사진으로 실제 확인했습니다. 두 고양이가 각각 0.724와 0.688로 검출되었고, 박스는 파이썬 참조 구현과 소수점 넷째 자리까지 일치했습니다.

토크나이저를 손으로 쓰기

Grounding DINO는 캡션이 BERT와 같은 방식으로 토큰화되어야 합니다. 손쉬운 수는 transformers.js를 끌어오는 것입니다.

그것은 함수 하나를 위해 약 2MB의 자바스크립트를, 이미 151MB짜리 모델을 불러오는 페이지에 얹는 일이라, WordPiece를 직접 구현했습니다. 대략 200줄이고, HuggingFace의 tokenizers와 토큰 단위로 대조해 두었습니다.

절약한 바이트가 요점은 아닙니다. 요점은 모델의 학습 토크나이저와 어긋나는 토크나이저가 임계값 문제처럼 보이는 미묘하게 틀린 검출을 만든다는 것입니다. 토크나이저를 의심하기까지 box_threshold를 만지느라 하루를 쓰게 됩니다. 토큰 수준의 동등성 테스트가 있으면 그 실패 유형은 가능성이 낮아지는 정도가 아니라 불가능해집니다.

브라우저가 더 이상 답이 아닌 지점

영상 마스크 전파는 서버 쪽에서 돌며, 이는 일관성의 훼손이 아니라 의도한 예외입니다.

경제성이 다릅니다. 클릭 분할은 클릭마다 값싼 디코더 한 번을 쓰고, 그 상대인 인코딩은 이미지마다 한 번 계산해 캐시해 둡니다. 전파는 프레임마다 모델 전체를 한 번씩 통과해야 하고, 모델은 그래프 다섯 개에 걸쳐 181MB이며, 영상은 이미 서버에 있습니다. 브라우저 탭에서 백 프레임은 페이지가 몇 분간 얼어붙는다는 뜻입니다.

우리는 프레임에서 프레임으로 다시 프롬프트하는 더 가벼운 브라우저 내 캐리포워드 경로를 유지하고 있으며, 이 둘을 같은 기능으로 서술하지 않으려 조심합니다. "SAM 2 전파가 당신의 브라우저에서 돕니다"는 더 좋은 문장이자 거짓인 문장입니다.

이것을 만들 사람에게 해 줄 말

  1. 출력보다 정답을 먼저 확보하십시오. 실패 유형은 그럴듯한 오답이고, 그것은 검토를 통과합니다.
  2. 양자화를 측정하십시오. 기본값은 다른 제약을 안고 있던 누군가가 내린 선택입니다.
  3. 전처리를 참조 구현과 수치로 검증하십시오. 눈으로는 0.1px과 148px의 오차를 한눈에 구별할 수 없습니다.
  4. 인코더와 디코더를 분리하고 비싼 쪽을 캐시하십시오. 클릭이 즉각적으로 느껴지는 이유는 통째로 그 분리 덕분입니다.

더 읽을거리