본문 바로가기
C.W.K.
Stream
Lesson 04 of 05 · published

Tensor 는 거짓말을 안 해

~13 min · tensor-classification, safetensors, reliability, registry

Level 0툴 빌려 쓰는 사람
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"파일명은 그 파일에 대한 사람의 주장이야. 안에 든 tensor 는 파일 자신의 고백이고. 고백 쪽을 믿어."

사람은 이름을 틀려

진짜 모델 디렉토리를 한 바퀴 돌아 보면 거짓말이 나와. lora_something.safetensors 라는 이름인데 사실은 backbone 이 통째로 구워진 merged checkpoint 인 파일. sdxl/ 이라는 폴더인데 누가 잘못 떨어뜨린 SD1.5 모델이 들어 있는 경우. vendor 이름을 달고 있는데 실은 커뮤니티가 fine-tune 한 checkpoint. 사람은 끊임없이 이름 바꾸고 폴더 옮기고 잘못 붙여. 그리고 파일명을 믿는 분류기는 그 실수를 하나도 빠짐없이 물려받아.

tensor 가 기준이야

safetensors 파일 안에는 tensor 를 전부 나열한 헤더가 있어. key 이름이랑 shape 이 적혀 있지. 그 key 랑 shape 은 모델의 실제 아키텍처가 정하는 거라 파일 이름 바꾼다고 흉내 낼 수가 없어. 진짜 SDXL 모델은 SDXL 의 tensor key 를 갖고, 진짜 FLUX transformer 는 FLUX 의 것을 가져. 이 파일이 진짜로 뭔지 알고 싶으면 이름을 읽지 말고 헤더를 읽어. 안에 실제로 뭐가 들었는지 보는 거야.

겉에 붙은 딱지 말고 안에 든 내용으로 가려내. 딱지(파일명, 폴더, 확장자)는 그 파일을 마지막으로 만진 사람의 주장이야. 내용(tensor key 랑 shape)은 그 파일이 실제로 무엇인가고. 둘이 어긋나면 — 그리고 언젠가 반드시 어긋나 — 이기는 쪽은 늘 내용이야.

구체적인 함정: merged checkpoint

이게 왜 중요한지 실제 예를 보자. 누가 LoRA tensor 를 backbone 이랑 같이 구워 놓은 checkpoint 를 공유해. 파일명이나 lora_ key 가 있다는 것만 보면 순진한 분류기는 이걸 LoRA, 그러니까 작은 덧붙임 파일이라고 불러. 그런데 backbone 이 통째로 들어 있으니까 실제로는 기가바이트짜리 full checkpoint 야. 이걸 틀리면 엔진이 몇 GB 짜리 'LoRA' 를 작은 패치인 줄 알고 올리려 하고, 그 아래로 전부 깨져. 해법은 LoRA key 를 보기 전에 backbone 이 통째로 들어 있는지부터 확인하는 거야. 검사 순서가 곧 증거의 우선순위인 거지.

증거가 겹칠 수 있으면 확실한 것부터 검사해. 한 파일이 여러 분류의 신호를 동시에 갖고 있을 수 있어. 그래서 분류기는 제일 결정적인 흔적부터 봐야 해. LoRA 이름보다 backbone 통째가 먼저인 것처럼, 제일 센 증거가 이기게. 검사 순서는 아무렇게나 정하는 게 아니라 어느 단서가 어느 단서를 덮는지의 순위표야.

어디를 훑느냐와 무엇이냐는 다른 축이야

여기 미묘한 두 번째 교훈이 있어. 어느 디렉토리를 훑을지 정하는 것과 이 파일이 무슨 종류인지 정하는 건 별개의 질문이야. 엔진은 models 디렉토리는 훑고 embeddings 디렉토리는 뺀다고 치자. 그건 훑을 범위에 대한 결정이고, 폴더로 정해도 돼. 그런데 그 범위 안에서 파일의 종류는 절대 폴더로 안 정해. 오직 tensor 로만 정해. 이 두 축을 뭉뚱그리는 게 폴더를 믿으면 안 되는 자리에서까지 폴더를 믿게 되는 길이야.

정당한 폴더 판단이 부당한 폴더 판단까지 정당화하게 두지 마. 뭘 훑을지 정하는 데 폴더를 쓰는 건 괜찮아. 폴더는 합리적인 범위 경계니까. 이 모델이 무엇인지 정하는 데 폴더를 쓰는 게 실수고. 같은 폴더인데 질문이 둘이야. 갈라 놓지 않으면 믿을 만한 범위 판단이 못 믿을 종류 판단한테 신뢰를 빌려주게 돼.

피파의 고백

난 파일명을 믿고 싶었어. 바로 거기 있고, 읽기도 빠르고, 대개 맞으니까. 아빠는 나를 틀린 경우들 앞에 앉혀 놨어. registry 를 조용히 오염시키는 게 바로 그것들이거든. 이름만 보고 넘어간 잘못 붙은 파일 하나면 엔진이 영영 자신 있게 틀린 짓을 해. tensor 를 읽는 건 느리고 덜 편한데, 실제로 참인 건 그쪽뿐이야. 그때부터 난 편한 신호를 편하다는 그 이유로 의심하는 법을 배웠어.

Code

순서가 곧 어느 증거가 어느 증거를 덮는지·python
# safetensors 헤더 — tensor key 랑 shape — 를 읽어서 가려내.
# 파일명은 절대 안 봐. 제일 결정적인 흔적부터 검사해.
from safetensors import safe_open

def classify(path) -> str:
    with safe_open(path, framework="pt") as f:
        keys = set(f.keys())

    # 1. backbone 이 통째로 있으면 그게 다 이겨. merged checkpoint 는
    #    lora_ key 가 같이 구워져 있어도 backbone 을 통째로 싣고 있어.
    if any(k.startswith("model.diffusion_model.") for k in keys):
        return "checkpoint"          # 기가바이트짜리 전체 모델

    # 2. backbone 통째가 아니라는 걸 확인한 다음에야 lora_ 흔적이 믿을 만해져.
    if any(k.startswith("lora_") for k in keys):
        return "lora"                # 작은 덧붙임

    return "unknown"

# 파일 이름이 'lora_x.safetensors' 여도 checkpoint 일 수 있어.
# 정하는 건 tensor 야. 이름은 사람의 짐작이었을 뿐이고.

External links

Exercise

네 코드에서 이름이나 확장자, 아니면 사용자가 고른 딱지로 분류하거나 길을 정하는 자리를 골라 봐. 대신 읽을 수 있는 내용이 뭐가 있는지 찾아. 그다음 심술궂은 경우를 하나 만들어 봐. 딱지가 내용에 대해 거짓말하는 파일이나 입력 말이야. 지금 코드가 거기서 틀린 짓을 해? 그 버그가 딱지를 믿은 값이야.
Hint
심술궂은 경우가 핵심이야. 딱지가 정직할 때만 맞는 분류기는 분류기가 아니라 딱지를 그대로 옮겨 적은 것뿐이거든. 일부러 잘못 붙인 입력으로 시험해 봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.