11/05/2025

머신 러닝을 시작하는 프로그래머가 저지르는 실수


머신러닝을 시작할 때 정해진 방법은 없습니다. 각기 다른 방식으로 배우고, 목적 그리고 목표도 다릅니다.

프로그래머가 머신러닝의 세계로 뛰어드는 것은 새로운 프로그래밍 언어를 배우는 것과는 다른 경험입니다. 논리와 명확한 규칙, 100% 예측 가능한 결과에 익숙한 경험을 규칙이 아닌 데이터에서 패턴을 학습하고, 확률과 통계에 기반한 경험으로 바꿔야 합니다.

이런 근본적인 차이 때문에, 뛰어난 프로그래머도 머신러닝을 시작할 때 함정에 빠지곤 합니다. 이 글은 프로그래머가 겪을 수 있는 실수와 머신러닝 실무자로 거듭나기 위한 사고방식의 전환에 대해 이야기합니다.


실수 1: 바퀴를 재발명하려고 한다. (알고리즘 구현에 집착)

가장 흔한 실수입니다. 프로그래머는 종종 "이 기술이 어떻게 작동하는지" 알아야 직성이 풀립니다. 그래서 선형 회귀, 서포트 벡터 머신 같은 알고리즘을 밑바닥부터 직접 구현하려고 시도할 수 있습니다.

이는 마치 웹 애플리케이션을 만들기 위해 HTTP 프로토콜과 TCP/IP 소켓을 직접 구현하는 것과 같습니다. 물론 훌륭한 경험이 되겠지만, 당장 무언가를 해결하기 위해서는 비효율적입니다.

"알고리즘과 작동 원리"와 "이 알고리즘을 문제에 적용하는 법" 두 가지를 동시에 해결해야 합니다. 이미 어느정도 최적화된 라이브러리가 있는데, 굳이 처음부터 코드를 짜는 것은 낭비일 수 있습니다.

일단 라이브러리 사용자가 되었으면 합니다. 잘 만들어진 라이브러리를 가져와 문제에 적용하는 것부터 해보는것을 추천합니다. 알고리즘의 세부 구현은 나중에 그 기술을 깊게 파고들거나, 운영 환경에 맞는 커스터마이징이 필요할 때 파고들어도 늦지 않습니다.


실수 2: 100% 정확도를 추구한다.

프로그래밍 세계에서는 버그는 "0" 또는 "1"입니다. 코드는 작동하거나, 작동하지 않거나 둘 중 하나입니다. 하지만 머신러닝의 세계는 다릅니다.

소프트웨어 버그는 "실패"이지만, 머신러닝 모델의 95% 정확도는 "엄청난 성공"일 수 있습니다.

머신러닝은 본질적으로 통계적 추론입니다. 현실 세계의 데이터는 노이즈가 많고 불완전합니다. 100% 정확한 모델은 사실상 불가능하며, 만약 100%가 나왔다면 "Overfitting"울 의심해야 합니다.

"이 정도면 괜찮은데?"를 받아들이는 것이 중요합니다. 90% 정확도의 모델이라도 비즈니스 문제를 해결하고 가치를 창출할 수 있다면 성공입니다.

"완벽한 정답"이 아닌 "최선의 추정치"를 찾는 것을 목표로 해야 합니다. 모델의 성능을 높이는 것도 중요하지만, 그 모델이 실제 문제를 해결하는데 얼마나 유용한지를 기준으로 판단해야 합니다.


실수 3: 코드만 보고 프로세스를 놓친다.

프로그래머는 종종 "어떤 알고리즘을 사용할까?"라는 "모델링(코딩)" 단계에 집중합니다. 머신러닝에서는 모델링 코드가 차지하는 비중은 20%도 되지 않을 수 있습니다.

머신러닝의 성공은 알고리즘이 아니라 데이터와 프로세스에 있습니다. 따라서 전체 워크플로우에 익숙해져야 합니다.

  1. 문제 정의: 무엇을 하려고 하는가?
  2. 데이터 수집 및 정제
  3. 모델이 잘 학습할 수 있도록 데이터를 가공
  4. 모델 선택 및 훈련: 다양한 모델을 빠르게 테스트
  5. 평가 및 튜닝: 모델의 성능을 검증하고 개선
  6. 배포 및 모니터링: 실제 서비스 적용

GUI기반 도구로 이 전체 흐름을 먼저 경험해보는 것도 좋은 방법입니다. 코딩 없이 데이터가 어떻게 흘러가는지 한눈에 볼 수 있습니다.

나중에 Weka에 대해서 다뤄보도록 할께요.


실수 4: 수학에 압도당하거나 무시하거나

"머신러닝을 하려면 수학 학위가 필요한가요?" 많은 이들이 겁부터 먹습니다. 혹은 반대로 "라이브러리가 다 해주는데 수학이 필요한가요?" 라며 수학을 무시합니다. 둘 다 문제입니다.

자동차 운전을 위해 엔진의 연소 원리를 알 필욘 없지만, 차가 꿀렁거리거나 이상한 소리가 나면 최소한의 지식(엔진오일, 냉각수)이 있어야 문제를 진단할 수 있습니다.

모델이 왜 이런 예측을 했는지, 왜 성능이 안나오는지 이유를 모른 채 그저 파라미터만 바꿔가며 "감"에 의존하는 수학 무시형은 디버깅이 불가능해집니다.

이론에만 매몰되어 실제 코드를 한 줄도 짜보지 못하는 수학에 압도형은 지쳐서 포기하게 됩니다.

그래서 필요할 때 학습하는 전략을 취하시면 됩니다.

  1. 일단 라이브러리로 모델을 돌려봅니다.
  2. 모델 성능이 기대에 미치지 못하면, 해당 알고리즘의 작동 원리와 관련된 수학을 찾아보며 이해도를 높입니다.
  3. 수학은 머신러닝을 시작하기 위한 필수 조건이 아니라, 더 잘하기 위한 핵심 도구입니다.


실수 5: 자동화

마지막으로, 프로그래머분들이 가진 강력한 무기를 잊지 않았으면 합니다. 바로 자동화와 시스템 구축 능력입니다. 많은 데이터 사이언티스트가 Colab or Jupyter에서 훌륭한 모델을 만들지만, 이를 실제 운영 환경에 배포하고 유지보수하는데 어려움을 겪습니다.

프로그래머는 이미 익숙한 CI/CD, 테스트 자동화, 빌드 및 배포에 대한 파이프라인 개념은 머신러닝 세계에서는 MLOps라고 불립니다. 이 영역은 프로그래머가 가장 빛을 발휘할 수 있는 기회입니다. 모델을 "만드는 것"을 넘어, 모델을 "안정적으로 서비스하는 것"에서 가치를 증명하시면 됩니다.

머신러닝은 코딩 스킬에 "실험"과 "통계"라는 새로운 스킬을 더하는 과정입니다. 알고리즘 구현이라는 숲에 갇히지 말고, 라이브러리를 활용해 문제를 해결하는 더 큰 그림을 보세요.

프로그래머들의 강력한 엔지니어링 능력은 머신러닝 프로젝트를 "연구"에서 "제품"으로 만드는 핵심 열쇠가 될 것입니다.

11/03/2025

누군가 내게 말해줬더라면 좋았을 것들

본 글은 샘 알트먼의 블로그의 "What I Wish Someone Had Told Me"의 글을 번역했습니다.


1. 낙관주의, 집착, 자기 믿음, 순수한 추진력 그리고 인맥은 일이 시작되는 방식이다.

2. 응집력 있는 팀, 침착함과 긴급함의 적절한 조화, 비이성적인 헌신은 일이 마무리되는 방식이다. 장기적인 안목은 부족하기 쉽다. 단기적으로 사람들이 어떻게 생각하는지에 대해 걱정하지 않으려 노력해야 한다. 이는 시간이 지남에 따라 더 쉬워질 것이다.

3. 팀이 별로 중요하지 않은 쉬운 일을 하는 것보다 정말로 중요한 어려운 일을 하는 것이 더 쉽다. 대담한 아이디어는 사람들에게 동기를 부여한다.

4. 인센티브는 초능력이다. 신중하게 설정해야 한다.

5. 당신의 자원을 확신이 강한 소수에게 베팅하도록 집중해야 한다. 말하기는 쉽지만 이행하기는 어렵다. 당신이 생각하는 것보다 더 많은 것을 삭제할 수 있다.

6. 명확하고 간결하게 소통해라.

7. 불필요한 겉치레와 관료주의를 볼 때무다 맞서 싸우고 다른 사람들도 그렇게 하도록 해라. 조직도가 사람들이 생산적으로 함께 일하는 데 방해가 되지 않도록 해라.

8. 중요한 것은 결과이다. 좋은 과정이 나쁜 결과를 변명하게 두지 말아라.

9. 채용에 더 많은 시간을 써야 한다. 빠른 개선 속도를 보이는 잠재력이 높은 사람들에게 위험을 감수해라. 지능 외에도 일을 완수해낸 증거를 찾아라.

10. 슈퍼스타들은 보기보다 훨씬 가치가 있지만, 당신은 사람들이 조직의 성과에 미치는 순수한 영향을 기준으로 평가해야 한다.

11. 빠른 반복은 많은 것을 만회할 수 있다. 빨리 반복한다면 틀리는 것은 괜찮다. 계획은 수십 년 단위로, 실행은 주 단위로 측정되어야 한다.

12. 비즈니스 세계의 물리 법칙과 맞서 싸우지 말아라.

13. 영감은 사라지기 쉽고 삶은 빠르게 지나간다. 아무것도 하지 않는 것은 교활한 위험이다.

14. 규모는 종종 놀라운 창발적 특성을 가진다. 규모가 커지면 예상치 못한 새로운 특성들이 나타난다.

15. 복리 지수는 마법과 같다. 특히, 당신은 규모와 함께 복리 이점을 얻는 비즈니스를 만들고 싶을 것이다.

16. 다시 일어서서 계속 나아가라.

17. 훌륭한 사람들과 함게 일하는 것은 인생에서 가장 멋진 것 중 하나다.

10/23/2025

제로샷 학습 (Zero-Shot Learning)

본 글은 제로샷 학습(Zero-Shot Learning)의 개념을 이해하고, 실제 예제 코드를 통해 이를 구현하는 방법을 설명합니다. 제로샷 학습이 무엇이고, 왜 중요한지를 Hugging Face를 이용해 얼마나 쉽게 활용할 수 있는지 다루도록 하겠습니다.


제로샷 학습이란 무엇인가?

전통적인 머신러닝 모델을 훈련시키는 방식으로 "암기 과목" 공부와 비슷합니다. 예를 들어 모델에게 "고양이"와 "개" 사진 1000장을 보여주며 "이건 고양이야, 이건 강아지야"라고 정답(Label)을 알려줍니다. 학습이 끝난 모델은 "고양이"와 "강아지"는 잘 구분하지만, 한 번도 본 적 없는 "코끼리" 사진을 주면 혼란에 빠집니다.


제로샷 학습은 이와는 정반대입니다. 이름 그대로, 0(Zero)개의 예시(Shot)만 보고도 문제를 푸는 방식입니다. 예를 들어 모델에게 "고양이"나 "강아지"라는 정답(Label) 자체를 가르친 적이 없습니다. 대신, 모델은 "언어"와 "이미지" 사이의 "관계"와 "개념"을 미리 학습합니다.


마치 우리가 "얼룩말"을 한 번도 본적이 없어도, "말이랑 비슷한데 몸에 검은 줄무늬가 있어"라는 설명만 듣고도 얼룩말을 알아볼 수 있는 것과 같습니다.


위에서 언급한 개념을 더 쉽게 이해하기 위해 "도서관 사서"로 비유해보겠습니다.


전통적인 사서 (훈련 필요)

  • 이 사서는 "역사", "과학" 코너만 압니다.

  • 새롭게 "경제" 책이 들어오면, 이 사서는 이 책을 어디에 둬야 할지 모릅니다. "경제" 코너를 새로 만들고, 어떤 책이 경제 책인지 수백 권의 예시를 보여주며 "다시 훈련(Fine-tuning)" 해야 합니다.


제로샷 사서 (훈련 불필요)

  • 이 사서는 "역사", "과학" 코너를 암기한 것이 아니라, "책의 내용"과 "코너 이름(Label)"의  의미를 모두 이해하고 있습니다.

  • 새로운 "경제" 책이 들어오면, 사서는 이 책을 읽어봅니다.

  • 그리고 우리가 제시한 새로운 코너 이름(Lable)인 "경제"의 의미도 생각해봅니다.

  • 사서는 이 책의 내용은 "경제"라는 단어의 의미와 매우 가깝다고 추론하고 책을 분류합니다.


이제 제로샷 학습에 대해서 이해가 되셨나요?


왜 이 학습법이 혁신적일까?

전통적인 AI 모델 구축의 가장 큰 병목은 "데이터 라벨링" 입니다. 수만, 수십만 개의 데이터에 일일이 정답을 매핑하는 작업은 시간과 비용이 엄청나게 듭니다.


제로샷은 이 문제를 해결합니다.

  • 비용 절감: 데이터 라벨링 비용이 절감됩니다.

  • 유연성: "정치", "사회"로 분류하던 모델을 "IT", "예술"로 분류하고 싶을 때, 모델을 재훈련할 필요 없이 Label 이름만 바꿔주면 됩니다.

  • 신속성: 아이디어가 떠오른 즉시 프로토타입을 만들 수 있습니다.


제로샷 구현 예시

텍스트 분류

가장 기본적인 제로샷 텍스트 분류 예제를 살펴보겠습니다.

먼저 Hugging Face의 transformers 라이브러리를 설치합니다.


!pip install transformers


다음은 텍스트(sequence)와 후보 라벨(candidate_labels)만으로 분류를 수행하는 코드입니다.


from transformers import pipeline


classifier = pipeline("zero-shot-classification", model="MoritzLaurer/mDeBERTa-v3-base-mnli-xnli")

sequence_to_classify = "내일 중요한 축구 경기가 열린다고 한다."

candidate_labels = ["정치", "경제", "스포츠", "IT/기술"]

output = classifier(sequence_to_classify, candidate_labels, multi_label=False)

print(output)


위 코드를 실행하면 아래와 같은 결과가 나오게됩니다.


{'sequence': '내일 중요한 축구 경기가 열린다고 한다.', 

'labels': ['스포츠', 'IT/기술', '정치', '경제'], 

'scores': [0.9846686720848083, 0.008273092098534107,0.0036497144028544426, 0.003408558899536729]}


  • sequence: 원본 텍스트

  • labels: 점수가 높은 순서대로 정렬된 라벨 리스트

  • scores: 각 라벨 대한 신뢰도 점수(0~1)


"축구 경기"라는 텍스트가 "스포츠" 라벨과 가장 관련성(0.98)이 높다고 나옵니다. 위 모델은 정확하게 추론해냈습니다.


만약, 하나의 텍스트가 여러 개의 라벨에 속할 수 있다면, multi_label=True 옵션을 사용합니다.


from transformers import pipeline


classifier = pipeline("zero-shot-classification", model="MoritzLaurer/mDeBERTa-v3-base-mnli-xnli")

sequence_to_classify = "이 레스토랑은 음악은 훌륭하지만, 음식 맛은 평범했다."

candidate_labels = ["음식", "서비스", "음악", "가격"]

output = classifier(sequence_to_classify, candidate_labels, multi_label=True)

print(output)


위 코드를 실행하면 아래의 결과가 나오게됩니다.


{'sequence': '이 레스토랑은 음악은 훌륭하지만, 음식 맛은 평범했다.', 'labels': ['음악', '음식', '서비스', '가격'], 'scores': [0.9990034103393555, 0.9980430006980896, 0.9746165871620178, 0.48950350284576416]}


multi_label=True로 설정하면, 점수(scores)의 총합이 1이 되지 않습니다. 따라서 각 라벨이 독립적으로 "참일 확률"을 계산할 수 있습니다. 위 결과는 "음악"과 "음식" 모두에 관한 내용임을 추론한 것입니다.


이미지 분류

제로샷 개념은 텍스트에만 국한되지 않습니다. "개념"을 이해하는 모델이라면 이미지 분류나 객체 탐지에도 적용할 수 있습니다.

텍스트 분류가 NLI 모델을 기반으로 한다면, 이미지 분류는 CLIP(Contrastive Language Image Pre-training) 모델을 기반으로 합니다.


CLIP 모델은

  • 인터넷에서 수집한(이미지, 이미지 설명 텍스트) 쌍 정보를 엄청나게 많이 학습한 모델입니다.

  • CLIP은 "고양이 사진"과 "고양이라는 텍스트"가 서로 "가까운" 개념임을 압니다.


from transformers import pipeline

from PIL import Image

import requests # URL에서 이미지를 불러오기 위해


# 1. 제로샷 '이미지' 분류 파이프라인 로드

#    CLIP 모델을 명시적으로 지정해줍니다.

image_classifier = pipeline(

    "zero-shot-image-classification", 

    model="openai/clip-vit-large-patch14"

)


# 2. 분류할 이미지 준비 (인터넷에서 고양이 사진 불러오기)

url = "https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba"

image = Image.open(requests.get(url, stream=True).raw)


# 3. 후보 레이블 (텍스트로)

#    모델은 이 텍스트와 이미지의 '유사도'를 계산합니다.

labels = ["a photo of a cat", "a photo of a dog", "a photo of a car"]


# 4. 분류 실행

result = image_classifier(image, candidate_labels=labels)

pprint.pprint(result)


위 코드를 실행하면 아래의 결과가 나옵니다.

[{'score': 0.9979252815246582, 'label': 'a photo of a cat'}, {'score': 0.0012550547253340483, 'label': 'a photo of a dog'}, {'score': 0.0008196595590561628, 'label': 'a photo of a car'}]


모델은 이미지를 보고, 우리가 제시한 라벨 중 "a photo of a cat"이라는 설명과 이미지의 개념이 99.7% 일치한다고 판단했습니다.


객체 분류

이미지 전체를 분류하는 것을 넘어, 이미지 안의 특정 객체들을 텍스트로 찾아내는 것도 가능합니다.

from transformers import pipeline

from PIL import Image

import requests # URL에서 이미지를 불러오기 위해


# 1. 제로샷 '객체 탐지' 파이프라인 로드

object_detector = pipeline(

"zero-shot-object-detection",

model="google/owlvit-large-patch14"

)


# 2. (위와 동일한 고양이 이미지 사용)

url = "https://images.unsplash.com/photo-1514888286974-6c03e2ca1dba"

image = Image.open(requests.get(url, stream=True).raw)


# 3. 찾아내고 싶은 객체들의 이름 (텍스트)

labels_to_find = ["cat nose", "cat eyes", "remote control"]


# 4. 탐지 실행

result = object_detector(image, candidate_labels=labels_to_find)

print(result)


위 코드를 실행하면 아래의 결과나 나옵니다.

[{'score': 0.5476904511451721, 'label': 'cat nose', 'box': {'xmin': 2350, 'ymin': 1570, 'xmax': 2640, 'ymax': 1818}}, 

{'score': 0.3316132128238678, 'label': 'cat eyes', 'box': {'xmin': 2021, 'ymin': 1199, 'xmax': 2931, 'ymax': 1442}}, {'score': 0.31051504611968994, 'label': 'cat eyes', 'box': {'xmin': 2027, 'ymin': 1200, 'xmax': 2940, 'ymax': 1449}}, 

{'score': 0.29117435216903687, 'label': 'cat eyes', 'box': {'xmin': 2680, 'ymin': 1215, 'xmax': 2952, 'ymax': 1438}}, {'score': 0.24599002301692963, 'label': 'cat eyes', 'box': {'xmin': 2046, 'ymin': 1199, 'xmax': 2328, 'ymax': 1417}}, 

{'score': 0.17471081018447876, 'label': 'cat nose', 'box': {'xmin': 2336, 'ymin': 1601, 'xmax': 2644, 'ymax': 1821}}, {'score': 0.14712969958782196, 'label': 'cat eyes', 'box': {'xmin': 2679, 'ymin': 1215, 'xmax': 2953, 'ymax': 1450}}, 

{'score': 0.14246635138988495, 'label': 'cat eyes', 'box': {'xmin': 2018, 'ymin': 1200, 'xmax': 2332, 'ymax': 1435}}, {'score': 0.14067652821540833, 'label': 'cat eyes', 'box': {'xmin': 1985, 'ymin': 1186, 'xmax': 2983, 'ymax': 1478}}, 

{'score': 0.13866569101810455, 'label': 'cat eyes', 'box': {'xmin': 1765, 'ymin': 1098, 'xmax': 3168, 'ymax': 1572}}]

 

결론

이제까지 제로샷에 대해서 알아보았고, 장점과 한계에 대해서 다시 한번 살펴보겠습니다.


제로샷의 장점

  • 데이터가 필요 없음

  • 유연성: 비즈니스 요구사항이 변경되어 분류 카테고리를 늘려야 할 때, 재훈련없이 candidate_labels만 수정하면 됩니다.

  • 프로토타이핑: "이런 분류가 어떨까?" 라는 아이디어를 검증하기 위해 간단히 테스트할 수 있습니다.


제로샷의 한계

  • 정확도: 모든 것을 적당히 알지만, 한 분야의 "전문가" 보다는 못합니다. 만약 "고객 리뷰"에 대해 "긍정/부정"으로 분류하는 단 하나의 작업만 수행해야 한다면, 해당 작업에 특화된 데이터로 "파인 튜닝"한 모델이 제로샷 모델보다 좋습니다.

  • 모호성: NLI 기반 모델은 라벨의 "단어 의미"에 크게 의존합니다. "IT, 기술" 처럼 의미가 비슷한 라벨이 함께 있으면 모델이 혼동합니다. 따라서 복잡한 분류는 어려울 수 있습니다.

  • 속도 및 크기: 제로샷을 수행하는 NLI 모델이나 CLIP 모델은 크기가 매우 큽니다. 특화 모델보다 추론 속도가 느릴 수 있습니다.


제로샷 학습은 "모든 것을 대체하는" 만병 통치약은 아닙니다. 하지만 AI 개발의 패러다임을 바꾸는 강력한 도구이기에 아래의 상황에서 사용 하시기를 추천 드립니다.

  • 초기 탐색 및 프로토타이핑: 어떤 종류의 데이터가 유입되는지, 어떤 분류가 의미 있을지 빠르게 탐색할 때 활용

  • 데이터가 절대적으로 부족할 때: 라벨링된 데이터가 아예 없을 때 유일한 선택지

  • 동적인 분류가 필요할 때: 분류 카테고리가 매일같이 바뀌는 환경일 때 (e.g. 실시간 뉴스 토픽 분류)


여기서 사용된 코드는
https://github.com/monocleface/huggingface-tutorials/blob/main/natural-language-processing/sample_zeroshot_classification.ipynb 에서 보시면 됩니다.