Ver3.5 ๐ Transformers๋ก ๋ฒ์ญ AI ์ค์ต

๐ Transformers๋ก ๋ฒ์ญ AI ์ค์ต
ํ๊น ํ์ด์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋๋ง์ ๋ฒ์ญ AI ๋๋ฑ ๋ง๋ค๊ธฐ ๐ ๏ธโจ
์ผ, ์์งํ ๋งํด๋ด. ๋ฒ์ญ AI ๋ง๋ ๋ค๊ณ ํ๋ฉด ์ ์ง ์์ฒญ ์ด๋ ค์ธ ๊ฒ ๊ฐ์ง ์์? ๐
๋ฅ๋ฌ๋ ๋
ผ๋ฌธ ์์ญ ํธ ์ฝ์ด์ผ ํ๊ณ , ์๋ฐฑ๋ง ๊ฐ์ ๋ฐ์ดํฐ ์ง์ ๋ชจ์์ผ ํ๊ณ , GPU ์๋ฒ ๋ช ๋ ๋๋ ค์ผ ํ ๊ฒ ๊ฐ์ ๋๋?
๊ทผ๋ฐ ์ฌ์ค ํ๊น
ํ์ด์ค(Hugging Face)์ Transformers ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐ๋ฉด, ํ์ด์ฌ ์ฝ๋ ๋ช ์ค๋ง์ผ๋ก ์ง์ง ๋ฒ์ญ AI๋ฅผ ๋๋ฑ ๋ง๋ค ์ ์์ด! ๐
์ค๋์ ๊ทธ ์ ์ธ๊ณ๋ฅผ ๊ฐ์ด ํํํด๋ณด์. ์ด๋ก ๋ ํํํ๊ฒ, ์ค์ต๋ ๊ผผ๊ผผํ๊ฒ โ ์์ ์น์ ํ๊ฒ ์ค๋ช
ํด์ค๊ฒ. ์ค๋น๋์ง? ๐ฅ
๐ค Transformers ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ญ๋ฐ?
๋จผ์ ๊ธฐ๋ณธ๋ถํฐ ์ง๊ณ ๊ฐ์. Transformers๋ ํ๊น
ํ์ด์ค(Hugging Face)๋ผ๋ AI ์คํํธ์
์ด ๋ง๋ ์คํ์์ค ํ์ด์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ.
2018๋
์ ์ฒ์ ๋์๊ณ , ์ง๊ธ์ AI ๊ฐ๋ฐ์๋ค ์ฌ์ด์์ ์ฌ์ค์ ํ์ค ๋๊ตฌ๋ก ์๋ฆฌ์ก์ ์ํ์ผ.
๐ค ํ๊น ํ์ด์ค ์ ๊ณต PyTorch / TensorFlow ์ง์ ์์ฒ ๊ฐ์ ์ฌ์ ํ์ต ๋ชจ๋ธ NLP / ๋น์ / ์ค๋์ค ๋ชจ๋ ์ปค๋ฒ
์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ๋๋ก ๋ฒ์ญ, ์์ฝ, ๊ฐ์ฑ๋ถ์, ์ง์์๋ต, ํ ์คํธ ์์ฑ ๋ฑ ๊ฑฐ์ ๋ชจ๋ NLP ํ์คํฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ด.
๊ทธ๋ฆฌ๊ณ ํต์ฌ์ โ ์ด๋ฏธ ํ์ต๋ ๋ชจ๋ธ(Pre-trained Model)์ ๊ทธ๋ฅ ๊ฐ์ ธ๋ค ์ธ ์ ์๋ค๋ ๊ฒ! ๐
์ฌ๊ธฐ์ ์ ๊น, "Transformer"๋ผ๋ ๋จ์ด ์์ฒด์ ๋ํด์๋ ์์๋์.
Transformer๋ 2017๋
๊ตฌ๊ธ์ด ๋ฐํํ ๋
ผ๋ฌธ "Attention is All You Need"์์ ์ฒ์ ๋ฑ์ฅํ ๋ฅ๋ฌ๋ ์ํคํ
์ฒ์ผ.
์ด ๊ตฌ์กฐ๊ฐ ๋ฑ์ฅํ๋ฉด์ NLP ๋ถ์ผ๊ฐ ์์ ํ ๋ค์ง์ด์ก๊ณ , BERT, GPT, T5 ๊ฐ์ ์ด๊ฑฐ๋ ์ธ์ด๋ชจ๋ธ๋ค์ด ๋ชจ๋ ์ด Transformer ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด์ก์ด.
๋ฌธ์ฅ ๋ด ๋จ์ด๋ค์ด ์๋ก ์ผ๋ง๋ ๊ด๋ จ ์๋์ง๋ฅผ ๊ณ์ฐํด์, ๋ฌธ๋งฅ์ ํจ์ฌ ์ ์ดํดํ ์ ์๊ฒ ํด์ค.
์๋ฅผ ๋ค์ด "๋๋ ์ฌ๊ณผ๋ฅผ ๋จน์๋ค. ๊ทธ๊ฒ์ ๋ง์์๋ค."์์ '๊ทธ๊ฒ'์ด '์ฌ๊ณผ'๋ฅผ ๊ฐ๋ฆฌํจ๋ค๋ ๊ฑธ ๋ชจ๋ธ์ด ์ค์ค๋ก ํ์ ํ๋ ๊ฑฐ์ผ!
๐ ๏ธ ํ๊ฒฝ ์ค์ ๋ถํฐ ์์ํ์!
์, ์ด์ ์ง์ง ์ค์ต ๋ค์ด๊ฐ๋ณผ๊ฒ. ๋จผ์ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ค์นํด์ผ ํด.
ํ์ด์ฌ 3.8 ์ด์ ํ๊ฒฝ์ด๋ฉด ์ถฉ๋ถํ๊ณ , Google Colab์ ์ฐ๋ฉด GPU๋ ๋ฌด๋ฃ๋ก ์ธ ์ ์์ด์ ๊ฐ์ถ์ผ! ๐
ํฐ๋ฏธ๋(๋๋ Colab ์ )์์ ์๋ ๋ช ๋ น์ด๋ฅผ ์คํํด์ค.
pip install transformers
pip install torch
pip install sentencepiece
pip install sacremoses
ํนํ MarianMT ๊ณ์ด ๋ฒ์ญ ๋ชจ๋ธ์ ์ธ ๋ ํ์๋ก ์ค์นํด์ผ ํด!
ํ์ด์ฌ์์ ์๋ ์ฝ๋๋ก ๋ฒ์ ํ์ธํด๋ด.
import transformers
print(transformers.__version__)
# ์: 4.40.0 ์ด์์ด๋ฉด OK!
Python 3.8+ transformers 4.30+ torch 2.0+ RAM 4GB ์ด์
GPU๊ฐ ์์ด๋ CPU๋ก ์ถฉ๋ถํ ์ค์ต ๊ฐ๋ฅํด! ๋ค๋ง ์๋๊ฐ ์ข ๋๋ฆด ์ ์์ด. ๐
Google Colab์์ ๋ฐํ์ ์ ํ์ GPU๋ก ์ค์ ํ๋ฉด ํจ์ฌ ๋น ๋ฅด๊ฒ ๋์๊ฐ.
๐ ๊ฐ์ฅ ๋น ๋ฅธ ๋ฐฉ๋ฒ: pipeline() ํจ์ ์ฌ์ฉํ๊ธฐ
ํ๊น
ํ์ด์ค Transformers์ ๊ฝ์ ๋ฐ๋ก pipeline() ํจ์์ผ!
๋ชจ๋ธ ๋ก๋ฉ, ํ ํฌ๋์ด์ง, ์ถ๋ก , ๋์ฝ๋ฉ๊น์ง โ ์ด ๋ชจ๋ ๊ณผ์ ์ ๋จ ๋ช ์ค๋ก ์ฒ๋ฆฌํด์ค. ์ง์ง ๋ง๋ฒ ๊ฐ๋ค๊ณ ๐ช
from transformers import pipeline
# ํ๊ตญ์ด โ ์์ด ๋ฒ์ญ ํ์ดํ๋ผ์ธ ์์ฑ
translator = pipeline(
task="translation",
model="Helsinki-NLP/opus-mt-ko-en"
)
# ๋ฒ์ญ ์คํ!
result = translator("์๋
ํ์ธ์! ์ค๋ ๋ ์จ๊ฐ ์ ๋ง ์ข๋ค์.")
print(result)
# ์ถ๋ ฅ: [{'translation_text': 'Hello! The weather is really nice today.'}]
์ด๋? ์ง์ง ์ด๊ฒ ๋์ด์ผ! ๐ฒ
pipeline() ํจ์์ ํ์คํฌ ์ด๋ฆ๊ณผ ๋ชจ๋ธ ์ด๋ฆ๋ง ๋ฃ์ด์ฃผ๋ฉด, ํ๊น
ํ์ด์ค ํ๋ธ์์ ๋ชจ๋ธ์ ์๋์ผ๋ก ๋ค์ด๋ฐ์์ ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ด.
task: ์ํํ ํ์คํฌ ์ข ๋ฅ (์: "translation", "text-generation", "sentiment-analysis")
model: ์ฌ์ฉํ ๋ชจ๋ธ ์ด๋ฆ (ํ๊น ํ์ด์ค ํ๋ธ์ ๋ชจ๋ธ ID)
device: ์คํ ์ฅ์น (0 = GPU ์ฒซ ๋ฒ์งธ, -1 = CPU)
max_length: ์ถ๋ ฅ ์ต๋ ๊ธธ์ด ์ค์ ๊ฐ๋ฅ
๐ ๋ค์ํ ์ธ์ด ์ ๋ฒ์ญ ๋ชจ๋ธ
ํ๊น
ํ์ด์ค ํ๋ธ์๋ Helsinki-NLP ๊ทธ๋ฃน์ด ๋ง๋ ์๋ฐฑ ๊ฐ์ ๋ฒ์ญ ๋ชจ๋ธ์ด ์์ด.
๋ชจ๋ธ ์ด๋ฆ ๊ท์น์ Helsinki-NLP/opus-mt-{์์ค์ธ์ด}-{ํ๊ฒ์ธ์ด} ํ์์ด์ผ.
ํโ์
Helsinki-NLP/opus-mt-ko-en์โํ
Helsinki-NLP/opus-mt-en-ko์โ์ผ
Helsinki-NLP/opus-mt-en-jap์โ์ค
Helsinki-NLP/opus-mt-en-zh์โํ
Helsinki-NLP/opus-mt-en-fr์โ๋
Helsinki-NLP/opus-mt-en-de์โ์คํ์ธ
Helsinki-NLP/opus-mt-en-es
# ์์ด โ ํ๊ตญ์ด ๋ฒ์ญ
translator_en_ko = pipeline(
task="translation",
model="Helsinki-NLP/opus-mt-en-ko"
)
text = "Artificial intelligence is changing the world rapidly."
result = translator_en_ko(text)
print(result[0]['translation_text'])
# ์ถ๋ ฅ: ์ธ๊ณต์ง๋ฅ์ด ์ธ์์ ๋น ๋ฅด๊ฒ ๋ณํ์ํค๊ณ ์์ต๋๋ค.
๐ฌ ๋ ๊น์ด ํ๊ณ ๋ค๊ธฐ: ๋ชจ๋ธ๊ณผ ํ ํฌ๋์ด์ ์ง์ ๋ค๋ฃจ๊ธฐ
pipeline()์ด ํธํ๊ธด ํ๋ฐ, ์ค์ ํ๋ก์ ํธ์์๋ ๋ ์ธ๋ฐํ ์ ์ด๊ฐ ํ์ํ ๋๊ฐ ๋ง์.
๊ทธ๋ด ๋๋ ๋ชจ๋ธ(Model)๊ณผ ํ ํฌ๋์ด์ (Tokenizer)๋ฅผ ์ง์ ๋ถ๋ฌ์์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์จ์ผ ํด.
ํ ์คํธ๋ฅผ ๋ชจ๋ธ์ด ์ดํดํ ์ ์๋ ์ซ์(ํ ํฐ ID)๋ก ๋ณํํด์ฃผ๋ ๋๊ตฌ์ผ.
์๋ฅผ ๋ค์ด "์๋ ํ์ธ์"๋ผ๋ ๋จ์ด๊ฐ [1234, 5678, 9012] ๊ฐ์ ์ซ์ ๋ฐฐ์ด๋ก ๋ฐ๋๋ ๊ฑฐ์ง.
๋ฒ์ญ ๋ชจ๋ธ๋ง๋ค ์๊ธฐ๋ง์ ํ ํฌ๋์ด์ ๋ฅผ ๊ฐ์ง๊ณ ์์ด์, ๋ฐ๋์ ๊ฐ์ ๋ชจ๋ธ์ ํ ํฌ๋์ด์ ๋ฅผ ์จ์ผ ํด!
from transformers import MarianMTModel, MarianTokenizer
# ๋ชจ๋ธ ์ด๋ฆ ์ค์
model_name = "Helsinki-NLP/opus-mt-ko-en"
# ํ ํฌ๋์ด์ ์ ๋ชจ๋ธ ๋ก๋
tokenizer = MarianTokenizer.from_pretrained(model_name)
model = MarianMTModel.from_pretrained(model_name)
# ๋ฒ์ญํ ํ
์คํธ
texts = [
"์ค๋์ ์ ๋ง ์ข์ ๋ ์ด์์.",
"ํ์ด์ฌ์ผ๋ก AI๋ฅผ ๋ง๋๋ ๊ฑด ์๊ฐ๋ณด๋ค ์ฌ์์!"
]
# ํ ํฌ๋์ด์ง (ํ
์คํธ โ ํ ํฐ ID)
inputs = tokenizer(
texts,
return_tensors="pt", # PyTorch ํ
์ ํ์
padding=True, # ๋ฐฐ์น ์ฒ๋ฆฌ๋ฅผ ์ํ ํจ๋ฉ
truncation=True, # ์ต๋ ๊ธธ์ด ์ด๊ณผ ์ ์๋ฅด๊ธฐ
max_length=512
)
print("ํ ํฐ ID ์์:", inputs['input_ids'][0][:10])
# ์ถ๋ ฅ: tensor([ 234, 1234, 5678, ...])
# ๋ชจ๋ธ๋ก ๋ฒ์ญ ์์ฑ
import torch
with torch.no_grad(): # ์ถ๋ก ์ ๊ทธ๋๋์ธํธ ๊ณ์ฐ ๋ถํ์
translated_tokens = model.generate(
**inputs,
max_length=512,
num_beams=4, # ๋น ์์น: 4๊ฐ ํ๋ณด ํ์
early_stopping=True
)
# ํ ํฐ ID โ ํ
์คํธ๋ก ๋์ฝ๋ฉ
translated_texts = tokenizer.batch_decode(
translated_tokens,
skip_special_tokens=True # [PAD], [EOS] ๊ฐ์ ํน์ ํ ํฐ ์ ๊ฑฐ
)
for original, translated in zip(texts, translated_texts):
print(f"์๋ฌธ: {original}")
print(f"๋ฒ์ญ: {translated}")
print("---")
num_beams=1: Greedy Search โ ๋งค ์คํ ๋ง๋ค ๊ฐ์ฅ ํ๋ฅ ๋์ ๋จ์ด ํ๋๋ง ์ ํ. ๋น ๋ฅด์ง๋ง ํ์ง ๋ฎ์.
num_beams=4: Beam Search โ 4๊ฐ์ ํ๋ณด ๊ฒฝ๋ก๋ฅผ ๋์์ ํ์. ๋ ์์ฐ์ค๋ฌ์ด ๋ฒ์ญ ๊ฒฐ๊ณผ.
num_beams=8: ๋ ๋ง์ ํ๋ณด ํ์. ํ์ง์ ์ฌ๋ผ๊ฐ์ง๋ง ์๋๊ฐ ๋๋ ค์ ธ.
์ผ๋ฐ์ ์ผ๋ก 4~6 ์ ๋๊ฐ ํ์ง๊ณผ ์๋์ ๊ท ํ์ด ์ข์! ๐ฏ
๐ฏ ์ค์ ํ๋ก์ ํธ: ๋ค๊ตญ์ด ๋ฒ์ญ๊ธฐ ๋ง๋ค๊ธฐ
์ด์ ๋ฐฐ์ด ๊ฑธ ํ์ฉํด์ ์ค์ ๋ก ์ธ ์ ์๋ ๋ค๊ตญ์ด ๋ฒ์ญ๊ธฐ๋ฅผ ๋ง๋ค์ด๋ณด์!
์ฌ์ฉ์๊ฐ ํ
์คํธ์ ๋ชฉํ ์ธ์ด๋ฅผ ์
๋ ฅํ๋ฉด ์๋์ผ๋ก ๋ฒ์ญํด์ฃผ๋ ํ๋ก๊ทธ๋จ์ด์ผ. ๐ช
from transformers import pipeline
from typing import Optional
class MultilingualTranslator:
"""๋ค๊ตญ์ด ๋ฒ์ญ๊ธฐ ํด๋์ค"""
# ์ง์ ์ธ์ด ์ ์ ์
SUPPORTED_MODELS = {
('ko', 'en'): 'Helsinki-NLP/opus-mt-ko-en',
('en', 'ko'): 'Helsinki-NLP/opus-mt-en-ko',
('en', 'fr'): 'Helsinki-NLP/opus-mt-en-fr',
('en', 'de'): 'Helsinki-NLP/opus-mt-en-de',
('en', 'es'): 'Helsinki-NLP/opus-mt-en-es',
('en', 'ja'): 'Helsinki-NLP/opus-mt-en-jap',
('en', 'zh'): 'Helsinki-NLP/opus-mt-en-zh',
('fr', 'en'): 'Helsinki-NLP/opus-mt-fr-en',
('de', 'en'): 'Helsinki-NLP/opus-mt-de-en',
}
def __init__(self):
self.loaded_models = {} # ์บ์: ํ ๋ฒ ๋ก๋ํ ๋ชจ๋ธ ์ฌ์ฌ์ฉ
def translate(
self,
text: str,
source_lang: str,
target_lang: str,
max_length: int = 512
) -> Optional[str]:
"""
ํ
์คํธ๋ฅผ ๋ฒ์ญํ๋ ๋ฉ์ธ ํจ์
Args:
text: ๋ฒ์ญํ ํ
์คํธ
source_lang: ์์ค ์ธ์ด ์ฝ๋ (์: 'ko', 'en')
target_lang: ํ๊ฒ ์ธ์ด ์ฝ๋ (์: 'en', 'fr')
max_length: ์ต๋ ์ถ๋ ฅ ๊ธธ์ด
Returns:
๋ฒ์ญ๋ ํ
์คํธ ๋๋ None (์ง์ํ์ง ์๋ ์ธ์ด ์)
"""
lang_pair = (source_lang, target_lang)
# ์ง์ ์ฌ๋ถ ํ์ธ
if lang_pair not in self.SUPPORTED_MODELS:
print(f"โ '{source_lang}' โ '{target_lang}' ๋ฒ์ญ์ ์ง์ํ์ง ์์์.")
return None
model_name = self.SUPPORTED_MODELS[lang_pair]
# ๋ชจ๋ธ ์บ์ ํ์ธ (์ด๋ฏธ ๋ก๋๋ ๋ชจ๋ธ์ ์ฌ์ฌ์ฉ)
if model_name not in self.loaded_models:
print(f"โณ ๋ชจ๋ธ ๋ก๋ฉ ์ค: {model_name}")
self.loaded_models[model_name] = pipeline(
task="translation",
model=model_name,
max_length=max_length
)
print(f"โ
๋ชจ๋ธ ๋ก๋ ์๋ฃ!")
translator = self.loaded_models[model_name]
result = translator(text, max_length=max_length)
return result[0]['translation_text']
def get_supported_pairs(self):
"""์ง์ํ๋ ์ธ์ด ์ ๋ชฉ๋ก ์ถ๋ ฅ"""
print("๐ ์ง์ํ๋ ๋ฒ์ญ ์ธ์ด ์:")
for (src, tgt) in self.SUPPORTED_MODELS.keys():
print(f" {src} โ {tgt}")
# ์ฌ์ฉ ์์
translator = MultilingualTranslator()
# ํ๊ตญ์ด โ ์์ด
result1 = translator.translate(
"์ฌ๋ฅ๋ท์์ AI ๋ฒ์ญ ์๋น์ค๋ฅผ ์ ๊ณตํ๊ณ ์ถ์ด์!",
source_lang='ko',
target_lang='en'
)
print(f"๋ฒ์ญ ๊ฒฐ๊ณผ: {result1}")
# ์์ด โ ํ๋์ค์ด
result2 = translator.translate(
"Machine learning is fascinating!",
source_lang='en',
target_lang='fr'
)
print(f"๋ฒ์ญ ๊ฒฐ๊ณผ: {result2}")
๋ชจ๋ธ ์บ์ฑ: ํ ๋ฒ ๋ก๋ํ ๋ชจ๋ธ์ ๋์ ๋๋ฆฌ์ ์ ์ฅํด์ ์ฌ์ฌ์ฉํด. ๋งค๋ฒ ๋ค์ด๋ก๋ํ๋ฉด ์๊ฐ์ด ๋๋ฌด ์ค๋ ๊ฑธ๋ฆฌ๊ฑฐ๋ !
ํ์ ํํ :
Optional[str] ๊ฐ์ ํ์
ํํธ๋ฅผ ์จ์ ์ฝ๋ ๊ฐ๋
์ฑ์ ๋์์ด.ํด๋์ค ์ค๊ณ: ๋ฒ์ญ๊ธฐ๋ฅผ ํด๋์ค๋ก ๋ง๋ค๋ฉด ์ฌ๋ฌ ์ธ์ด ์์ ๊ด๋ฆฌํ๊ธฐ ํจ์ฌ ํธํด.
๐ ๋ฒ์ญ ํ์ง ํ๊ฐ: BLEU ์ค์ฝ์ด ์ดํดํ๊ธฐ
๋ฒ์ญ AI๋ฅผ ๋ง๋ค์์ผ๋ฉด "์ด ๋ฒ์ญ์ด ์ผ๋ง๋ ์ข์๊ฐ?"๋ฅผ ์ธก์ ํด์ผ๊ฒ ์ง? ๐ค
๋ฒ์ญ ํ์ง ํ๊ฐ์์ ๊ฐ์ฅ ๋ง์ด ์ฐ์ด๋ ์งํ๊ฐ ๋ฐ๋ก BLEU(Bilingual Evaluation Understudy) ์ค์ฝ์ด์ผ.
๊ธฐ๊ณ ๋ฒ์ญ ๊ฒฐ๊ณผ์ ์ฌ๋์ด ์์ฑํ ์ฐธ์กฐ ๋ฒ์ญ(Reference Translation)์ ๋น๊ตํด์ ์ ์ฌ๋๋ฅผ 0~1 ์ฌ์ด ์ ์๋ก ๋ํ๋ด๋ ์งํ์ผ.
๊ณ์ฐ ์๋ฆฌ: n-gram(์ฐ์๋ n๊ฐ์ ๋จ์ด) ๋จ์๋ก ์ผ๋ง๋ ๊ฒน์น๋์ง ์ธก์ ํด.
์๋ฅผ ๋ค์ด ๊ธฐ๊ณ ๋ฒ์ญ: "The cat sat on the mat"
์ฐธ์กฐ ๋ฒ์ญ: "The cat is sitting on the mat"
โ ๊ฒน์น๋ ๋จ์ด๋ค์ ๋น์จ์ ๊ณ์ฐํด์ ์ ์๋ฅผ ๋งค๊ฒจ!
์ ์ ํด์:
0.0 ~ 0.1 โ ๊ฑฐ์ ์ธ๋ชจ์๋ ๋ฒ์ญ ๐ข
0.1 ~ 0.3 โ ์ด๋ ์ ๋ ์ดํด ๊ฐ๋ฅ
0.3 ~ 0.5 โ ๊ฝค ์ข์ ๋ฒ์ญ ๐
0.5 ์ด์ โ ์ ๋ฌธ๊ฐ ์์ค ๋ฒ์ญ ๐
# BLEU ์ค์ฝ์ด ๊ณ์ฐ ์ค์ต
# ๋จผ์ sacrebleu ์ค์น: pip install sacrebleu
import sacrebleu
# ๊ธฐ๊ณ ๋ฒ์ญ ๊ฒฐ๊ณผ (hypothesis)
hypothesis = ["The weather today is really nice."]
# ์ฌ๋์ด ์์ฑํ ์ฐธ์กฐ ๋ฒ์ญ (reference)
reference = ["The weather is very nice today."]
# BLEU ์ค์ฝ์ด ๊ณ์ฐ
bleu = sacrebleu.corpus_bleu(hypothesis, [reference])
print(f"BLEU ์ค์ฝ์ด: {bleu.score:.2f}")
# ์ถ๋ ฅ: BLEU ์ค์ฝ์ด: 42.35 (0~100 ์ค์ผ์ผ๋ก๋ ํํ ๊ฐ๋ฅ)
BLEU๋ ๋จ์ด ๊ฒน์นจ๋ง ๋ณด๊ธฐ ๋๋ฌธ์, ์๋ฏธ๋ ๊ฐ์ง๋ง ํํ์ด ๋ค๋ฅธ ๋ฒ์ญ์ ๋ฎ์ ์ ์๋ฅผ ๋ฐ์ ์ ์์ด.
์๋ฅผ ๋ค์ด "I'm happy" = "I feel joyful"์ ์๋ฏธ๊ฐ ๊ฐ์ง๋ง BLEU ์ ์๋ ๋ฎ๊ฒ ๋์.
๊ทธ๋์ ์ต๊ทผ์๋ COMET, BERTScore ๊ฐ์ ๋ ๋ฐ์ ๋ ํ๊ฐ ์งํ๋ ํจ๊ป ์ฌ์ฉํด!
โก ์ฑ๋ฅ ์ต์ ํ ๊ฟํ ๋ชจ์
๋ฒ์ญ AI๋ฅผ ์ค์ ์๋น์ค์ ์ฐ๋ ค๋ฉด ์๋์ ๋ฉ๋ชจ๋ฆฌ ํจ์จ๋ ์ค์ํด.
๋ช ๊ฐ์ง ์ค์ฉ์ ์ธ ์ต์ ํ ๋ฐฉ๋ฒ์ ์๋ ค์ค๊ฒ! ๐
1๏ธโฃ ๋ฐฐ์น ์ฒ๋ฆฌ(Batch Processing)
์ฌ๋ฌ ๋ฌธ์ฅ์ ํ ๋ฒ์ ์ฒ๋ฆฌํ๋ฉด ํจ์ฌ ๋น ๋ฅด๊ฒ ๋ฒ์ญํ ์ ์์ด.
from transformers import pipeline
translator = pipeline(
"translation",
model="Helsinki-NLP/opus-mt-ko-en",
device=0 # GPU ์ฌ์ฉ (์์ผ๋ฉด -1)
)
# โ ๋นํจ์จ์ ์ธ ๋ฐฉ๋ฒ: ํ๋์ฉ ๋ฒ์ญ
texts = ["์๋
ํ์ธ์", "์ค๋ ๋ ์จ๊ฐ ์ข์์", "ํ์ด์ฌ์ ์ฌ๋ฏธ์์ด์"]
results_slow = [translator(text) for text in texts]
# โ
ํจ์จ์ ์ธ ๋ฐฉ๋ฒ: ๋ฐฐ์น๋ก ํ ๋ฒ์ ๋ฒ์ญ
results_fast = translator(
texts,
batch_size=8 # ํ ๋ฒ์ 8๊ฐ์ฉ ์ฒ๋ฆฌ
)
print("๋ฐฐ์น ๋ฒ์ญ ๊ฒฐ๊ณผ:")
for text, result in zip(texts, results_fast):
print(f" {text} โ {result[0]['translation_text']}")
2๏ธโฃ ๋ชจ๋ธ ์์ํ(Quantization)
๋ชจ๋ธ ํฌ๊ธฐ๋ฅผ ์ค์ฌ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ๋ฎ์ถ๊ณ ์๋๋ฅผ ๋์ด๋ ๊ธฐ๋ฒ์ด์ผ.
import torch
from transformers import MarianMTModel, MarianTokenizer
model_name = "Helsinki-NLP/opus-mt-ko-en"
tokenizer = MarianTokenizer.from_pretrained(model_name)
model = MarianMTModel.from_pretrained(model_name)
# ๋์ ์์ํ ์ ์ฉ (CPU์์ ํจ๊ณผ์ )
quantized_model = torch.quantization.quantize_dynamic(
model,
{torch.nn.Linear}, # Linear ๋ ์ด์ด๋ง ์์ํ
dtype=torch.qint8 # 8๋นํธ ์ ์๋ก ๋ณํ
)
# ๋ชจ๋ธ ํฌ๊ธฐ ๋น๊ต
import os
torch.save(model.state_dict(), 'original_model.pt')
torch.save(quantized_model.state_dict(), 'quantized_model.pt')
original_size = os.path.getsize('original_model.pt') / 1024 / 1024
quantized_size = os.path.getsize('quantized_model.pt') / 1024 / 1024
print(f"์๋ณธ ๋ชจ๋ธ ํฌ๊ธฐ: {original_size:.1f} MB")
print(f"์์ํ ๋ชจ๋ธ ํฌ๊ธฐ: {quantized_size:.1f} MB")
print(f"ํฌ๊ธฐ ๊ฐ์: {(1 - quantized_size/original_size)*100:.1f}%")
์ผ๋ฐ์ ์ผ๋ก FP32(32๋นํธ ๋ถ๋์์์ ) โ INT8(8๋นํธ ์ ์)๋ก ์์ํํ๋ฉด:
๐ฆ ๋ชจ๋ธ ํฌ๊ธฐ: ์ฝ 75% ๊ฐ์
โก ์ถ๋ก ์๋: CPU์์ 2~4๋ฐฐ ํฅ์
๐ฏ ๋ฒ์ญ ํ์ง: ์ฝ๊ฐ ์ ํ๋์ง๋ง ๋๋ถ๋ถ ํ์ฉ ๊ฐ๋ฅํ ์์ค
3๏ธโฃ ๊ธด ํ ์คํธ ์ฒ๋ฆฌ: ์ฒญํฌ ๋ถํ
๋ฒ์ญ ๋ชจ๋ธ์ ๋ณดํต ์ต๋ 512 ํ ํฐ๊น์ง๋ง ์ฒ๋ฆฌํ ์ ์์ด.
๊ธด ๋ฌธ์๋ฅผ ๋ฒ์ญํ ๋๋ ์ ์ ํ ๋ถํ ํด์ ์ฒ๋ฆฌํด์ผ ํด.
def translate_long_text(text, translator, max_chunk_length=400):
"""
๊ธด ํ
์คํธ๋ฅผ ๋ฌธ์ฅ ๋จ์๋ก ๋ถํ ํด์ ๋ฒ์ญํ๋ ํจ์
"""
# ๋ฌธ์ฅ ๋จ์๋ก ๋ถํ (๋ง์นจํ, ๋๋ํ, ๋ฌผ์ํ ๊ธฐ์ค)
import re
sentences = re.split(r'(?<=[.!?])\s+', text)
chunks = []
current_chunk = []
current_length = 0
for sentence in sentences:
sentence_length = len(sentence)
if current_length + sentence_length > max_chunk_length:
if current_chunk:
chunks.append(' '.join(current_chunk))
current_chunk = [sentence]
current_length = sentence_length
else:
current_chunk.append(sentence)
current_length += sentence_length
if current_chunk:
chunks.append(' '.join(current_chunk))
# ๊ฐ ์ฒญํฌ ๋ฒ์ญ ํ ํฉ์น๊ธฐ
translated_chunks = []
for i, chunk in enumerate(chunks):
print(f"์ฒญํฌ {i+1}/{len(chunks)} ๋ฒ์ญ ์ค...")
result = translator(chunk)
translated_chunks.append(result[0]['translation_text'])
return ' '.join(translated_chunks)
# ์ฌ์ฉ ์์
long_text = """
์ธ๊ณต์ง๋ฅ์ ํ๋ ์ฌํ์์ ๋งค์ฐ ์ค์ํ ์ญํ ์ ํ๊ณ ์์ต๋๋ค.
ํนํ ์์ฐ์ด ์ฒ๋ฆฌ ๋ถ์ผ์์ ํฐ ๋ฐ์ ์ด ์ด๋ฃจ์ด์ก์ต๋๋ค.
๋ฒ์ญ, ์์ฝ, ์ง์์๋ต ๋ฑ ๋ค์ํ ํ์คํฌ์์ ์ธ๊ฐ ์์ค์ ์ฑ๋ฅ์ ๋ณด์ด๊ณ ์์ต๋๋ค.
์์ผ๋ก๋ AI ๊ธฐ์ ์ ๊ณ์ ๋ฐ์ ํ ๊ฒ์ผ๋ก ์์๋ฉ๋๋ค.
"""
from transformers import pipeline
translator = pipeline("translation", model="Helsinki-NLP/opus-mt-ko-en")
result = translate_long_text(long_text.strip(), translator)
print("๋ฒ์ญ ๊ฒฐ๊ณผ:")
print(result)
๐ ํ์ธํ๋: ๋๋ง์ ๋ฒ์ญ ๋ชจ๋ธ ๋ง๋ค๊ธฐ
๊ธฐ์กด ๋ชจ๋ธ์ ๊ทธ๋๋ก ์ฐ๋ ๊ฒ๋ ์ข์ง๋ง, ํน์ ๋๋ฉ์ธ(์ํ, ๋ฒ๋ฅ , IT ๋ฑ)์ ํนํ๋ ๋ฒ์ญ์ด ํ์ํ๋ค๋ฉด
ํ์ธํ๋(Fine-tuning)์ ํด์ผ ํด!
์ฌ์ ํ์ต๋ ๋ชจ๋ธ์ ๋ด ๋ฐ์ดํฐ๋ก ์ถ๊ฐ ํ์ต์ํค๋ ๊ฑฐ์ผ. ๐
๋ณ๋ ฌ ์ฝํผ์ค (์๋ฌธ-๋ฒ์ญ๋ฌธ ์) GPU (์ต์ 8GB VRAM ๊ถ์ฅ) datasets ๋ผ์ด๋ธ๋ฌ๋ฆฌ Seq2SeqTrainer
๋ณ๋ ฌ ์ฝํผ์ค๋ ์๋ฌธ๊ณผ ๋ฒ์ญ๋ฌธ์ด ์์ผ๋ก ์ด๋ฃจ์ด์ง ๋ฐ์ดํฐ์ ์ด์ผ.
์: "์๋ ํ์ธ์" โ "Hello" ์ด๋ฐ ์์ผ๋ก ์๋ง~์๋ฐฑ๋ง ์์ด ํ์ํด.
from transformers import (
MarianMTModel,
MarianTokenizer,
Seq2SeqTrainer,
Seq2SeqTrainingArguments,
DataCollatorForSeq2Seq
)
from datasets import Dataset
import pandas as pd
# 1. ํ์ต ๋ฐ์ดํฐ ์ค๋น (์์: IT ๋๋ฉ์ธ ๋ฒ์ญ ๋ฐ์ดํฐ)
train_data = {
'ko': [
"ํ์ด์ฌ์ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์
๋๋ค.",
"๋ฅ๋ฌ๋ ๋ชจ๋ธ์ ํ์ต์ํค๋ ค๋ฉด GPU๊ฐ ํ์ํฉ๋๋ค.",
"API๋ ์ ํ๋ฆฌ์ผ์ด์
ํ๋ก๊ทธ๋๋ฐ ์ธํฐํ์ด์ค์ ์ฝ์์
๋๋ค.",
# ... ์ค์ ๋ก๋ ์์ฒ~์๋ง ๊ฐ์ ๋ฐ์ดํฐ๊ฐ ํ์ํด!
],
'en': [
"Python is an object-oriented programming language.",
"A GPU is needed to train deep learning models.",
"API stands for Application Programming Interface.",
]
}
df = pd.DataFrame(train_data)
dataset = Dataset.from_pandas(df)
# 2. ๋ชจ๋ธ๊ณผ ํ ํฌ๋์ด์ ๋ก๋
model_name = "Helsinki-NLP/opus-mt-ko-en"
tokenizer = MarianTokenizer.from_pretrained(model_name)
model = MarianMTModel.from_pretrained(model_name)
# 3. ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ ํจ์
def preprocess_function(examples):
inputs = tokenizer(
examples['ko'],
max_length=128,
truncation=True,
padding=False
)
with tokenizer.as_target_tokenizer():
targets = tokenizer(
examples['en'],
max_length=128,
truncation=True,
padding=False
)
inputs['labels'] = targets['input_ids']
return inputs
# ๋ฐ์ดํฐ์
์ ์ฒ๋ฆฌ
tokenized_dataset = dataset.map(
preprocess_function,
batched=True,
remove_columns=['ko', 'en']
)
# 4. ํ์ต ์ค์
training_args = Seq2SeqTrainingArguments(
output_dir="./my-ko-en-translator",
num_train_epochs=3,
per_device_train_batch_size=8,
warmup_steps=100,
weight_decay=0.01,
logging_dir="./logs",
logging_steps=10,
save_strategy="epoch",
predict_with_generate=True,
fp16=True, # ํผํฉ ์ ๋ฐ๋ ํ์ต (GPU ํ์)
learning_rate=5e-5,
)
# 5. ๋ฐ์ดํฐ ์ฝ๋ ์ดํฐ ์ค์
data_collator = DataCollatorForSeq2Seq(
tokenizer,
model=model,
padding=True
)
# 6. ํธ๋ ์ด๋ ์์ฑ ๋ฐ ํ์ต ์์
trainer = Seq2SeqTrainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset,
data_collator=data_collator,
tokenizer=tokenizer,
)
print("๐ ํ์ธํ๋ ์์!")
trainer.train()
print("โ
ํ์ธํ๋ ์๋ฃ!")
# 7. ํ์ธํ๋๋ ๋ชจ๋ธ ์ ์ฅ
trainer.save_model("./my-ko-en-translator-final")
tokenizer.save_pretrained("./my-ko-en-translator-final")
๋ฐ์ดํฐ๊ฐ ์ ์ ๋๋ ํ์ต๋ฅ (learning_rate)์ ๋ฎ๊ฒ ์ค์ ํด์ผ ํด. (1e-5 ~ 5e-5 ๊ถ์ฅ)
๋๋ฌด ๋์ผ๋ฉด ๊ธฐ์กด์ ํ์ต๋ ์ง์์ ์์ด๋ฒ๋ฆฌ๋ Catastrophic Forgetting์ด ๋ฐ์ํ ์ ์์ด!
๊ทธ๋ฆฌ๊ณ Early Stopping์ ํ์ฉํด์ ๊ณผ์ ํฉ์ ๋ฐฉ์งํ๋ ๊ฒ๋ ์ค์ํด.
๐ ์น API๋ก ๋ฐฐํฌํ๊ธฐ: FastAPI ์ฐ๋
๋ฒ์ญ ๋ชจ๋ธ์ ๋ง๋ค์์ผ๋ฉด ์ค์ ๋ก ์๋น์ค๋ก ๋ฐฐํฌํด์ผ๊ฒ ์ง? ๐
FastAPI๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฒ์ญ AI๋ฅผ REST API๋ก ๋น ๋ฅด๊ฒ ๋ฐฐํฌํ ์ ์์ด.
์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์ AI ๋ฒ์ญ ์๋น์ค๋ฅผ ์ ๊ณตํ๊ณ ์ถ๋ค๋ฉด ์ด๋ฐ ๋ฐฉ์์ผ๋ก ๊ตฌํํ ์ ์์ด!
pip install fastapi uvicorn
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from transformers import pipeline
from typing import Optional
import time
app = FastAPI(
title="๋ฒ์ญ AI API",
description="Transformers ๊ธฐ๋ฐ ๋ค๊ตญ์ด ๋ฒ์ญ ์๋น์ค",
version="1.0.0"
)
# ์์ฒญ ๋ฐ์ดํฐ ๋ชจ๋ธ ์ ์
class TranslationRequest(BaseModel):
text: str
source_lang: str = "ko"
target_lang: str = "en"
max_length: Optional[int] = 512
# ์๋ต ๋ฐ์ดํฐ ๋ชจ๋ธ ์ ์
class TranslationResponse(BaseModel):
original_text: str
translated_text: str
source_lang: str
target_lang: str
processing_time: float
# ์ง์ ๋ชจ๋ธ ๋งคํ
MODELS = {
"ko-en": "Helsinki-NLP/opus-mt-ko-en",
"en-ko": "Helsinki-NLP/opus-mt-en-ko",
"en-fr": "Helsinki-NLP/opus-mt-en-fr",
"en-de": "Helsinki-NLP/opus-mt-en-de",
}
# ๋ชจ๋ธ ์บ์
model_cache = {}
def get_translator(source_lang: str, target_lang: str):
"""๋ชจ๋ธ ๋ก๋ ๋ฐ ์บ์ฑ"""
key = f"{source_lang}-{target_lang}"
if key not in MODELS:
raise HTTPException(
status_code=400,
detail=f"์ง์ํ์ง ์๋ ์ธ์ด ์: {source_lang} โ {target_lang}"
)
if key not in model_cache:
model_cache[key] = pipeline(
"translation",
model=MODELS[key]
)
return model_cache[key]
@app.get("/")
async def root():
return {"message": "๋ฒ์ญ AI API์ ์ค์ ๊ฑธ ํ์ํด์! ๐"}
@app.get("/supported-languages")
async def get_supported_languages():
"""์ง์ํ๋ ์ธ์ด ์ ๋ชฉ๋ก ๋ฐํ"""
return {
"supported_pairs": list(MODELS.keys()),
"total": len(MODELS)
}
@app.post("/translate", response_model=TranslationResponse)
async def translate(request: TranslationRequest):
"""ํ
์คํธ ๋ฒ์ญ ์๋ํฌ์ธํธ"""
if not request.text.strip():
raise HTTPException(
status_code=400,
detail="๋ฒ์ญํ ํ
์คํธ๋ฅผ ์
๋ ฅํด์ฃผ์ธ์."
)
if len(request.text) > 5000:
raise HTTPException(
status_code=400,
detail="ํ
์คํธ๊ฐ ๋๋ฌด ๊ธธ์ด์. 5000์ ์ดํ๋ก ์
๋ ฅํด์ฃผ์ธ์."
)
start_time = time.time()
translator = get_translator(request.source_lang, request.target_lang)
result = translator(
request.text,
max_length=request.max_length
)
processing_time = time.time() - start_time
return TranslationResponse(
original_text=request.text,
translated_text=result[0]['translation_text'],
source_lang=request.source_lang,
target_lang=request.target_lang,
processing_time=round(processing_time, 3)
)
# ์๋ฒ ์คํ: uvicorn main:app --reload --port 8000
์๋ฒ ์คํ ํ
http://localhost:8000/docs์ ์ ์ํ๋ฉดFastAPI๊ฐ ์๋์ผ๋ก ์์ฑํด์ฃผ๋ Swagger UI์์ ๋ฐ๋ก API๋ฅผ ํ ์คํธํ ์ ์์ด!
๋๋ curl ๋ช ๋ น์ด๋ก๋ ํ ์คํธ ๊ฐ๋ฅํด:
curl -X POST "http://localhost:8000/translate" -H "Content-Type: application/json" -d '{"text":"์๋
ํ์ธ์","source_lang":"ko","target_lang":"en"}'
๐ ์์ฃผ ๋ฐ์ํ๋ ์ค๋ฅ์ ํด๊ฒฐ๋ฒ
์ค์ตํ๋ค ๋ณด๋ฉด ๋ถ๋ช ํ ์ค๋ฅ๋ฅผ ๋ง๋๊ฒ ๋ ๊ฑฐ์ผ. ๋ฏธ๋ฆฌ ์์๋๋ฉด ๋นํฉํ์ง ์์ ์ ์์ด! ๐
์์ธ: sentencepiece ๋๋ sacremoses๊ฐ ์ค์น๋์ง ์์
ํด๊ฒฐ:
pip install sentencepiece sacremoses ์คํ
์์ธ: GPU ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ
ํด๊ฒฐ:
- ๋ฐฐ์น ํฌ๊ธฐ(batch_size) ์ค์ด๊ธฐ
-
torch.cuda.empty_cache() ์คํ- ๋ชจ๋ธ์ CPU๋ก ์ด๋:
model.to('cpu')- ํผํฉ ์ ๋ฐ๋(fp16) ์ฌ์ฉ
์์ธ: ์ ๋ ฅ ํ ์คํธ๊ฐ ๋๋ฌด ์งง๊ฑฐ๋, ์ธ์ด ๊ฐ์ง ์คํจ
ํด๊ฒฐ:
- ์ต์ 5๋จ์ด ์ด์์ ๋ฌธ์ฅ ์ ๋ ฅ
-
max_length ํ๋ผ๋ฏธํฐ ๋๋ฆฌ๊ธฐ-
num_beams ๊ฐ ์กฐ์ (4~6 ๊ถ์ฅ)
์์ธ: ๋คํธ์ํฌ ์๋ ๋๋ ํ๊น ํ์ด์ค ์๋ฒ ์ํ
ํด๊ฒฐ:
- ํ๊ฒฝ๋ณ์ ์ค์ :
TRANSFORMERS_CACHE๋ก ์บ์ ๊ฒฝ๋ก ์ง์ - ๋ชจ๋ธ์ ๋ก์ปฌ์ ๋ฏธ๋ฆฌ ์ ์ฅ:
model.save_pretrained('./local-model')- ๋ก์ปฌ ๋ชจ๋ธ ๋ก๋:
pipeline("translation", model="./local-model")
MarianMT ๋ชจ๋ธ ํ๋๊ฐ ๋ณดํต 300MB ~ 1GB ์ ๋ ๋ผ.
์ธํฐ๋ท ์ฐ๊ฒฐ์ด ํ์ํ๊ณ , ๋์คํฌ ๊ณต๊ฐ๋ ์ถฉ๋ถํ ํ๋ณดํด๋ฌ์ผ ํด!
๐ ๋ ๋์๊ฐ๊ธฐ: ์ต์ ๋ฒ์ญ ๋ชจ๋ธ๋ค
MarianMT ์ธ์๋ ํ๊น
ํ์ด์ค์๋ ๋ค์ํ ๋ฒ์ญ ๋ชจ๋ธ๋ค์ด ์์ด.
๊ฐ๊ฐ์ ํน์ง์ ์์๋๋ฉด ์ํฉ์ ๋ง๋ ๋ชจ๋ธ์ ์ ํํ ์ ์์ด! ๐ฏ
1. Helsinki-NLP/MarianMT
- ํน์ง: ๊ฐ๋ณ๊ณ ๋น ๋ฆ, ๋ค์ํ ์ธ์ด ์ ์ง์
- ์ ํฉ: ๋น ๋ฅธ ํ๋กํ ํ์ดํ, ๋ฆฌ์์ค ์ ํ ํ๊ฒฝ
- ํฌ๊ธฐ: ~300MB
2. facebook/mbart-large-50-many-to-many-mmt
- ํน์ง: 50๊ฐ ์ธ์ด ์ง์, ๋์ ๋ฒ์ญ ํ์ง
- ์ ํฉ: ๋ค๊ตญ์ด ์๋น์ค, ๊ณ ํ์ง ๋ฒ์ญ
- ํฌ๊ธฐ: ~2.4GB
3. Helsinki-NLP/opus-mt-tc-big-ko-en
- ํน์ง: ํโ์ ํนํ, ๋ ํฐ ๋ชจ๋ธ๋ก ๋์ ํ์ง
- ์ ํฉ: ํ๊ตญ์ด ๋ฒ์ญ ํ์ง์ด ์ค์ํ ๊ฒฝ์ฐ
- ํฌ๊ธฐ: ~1.2GB
4. google/mt5-base
- ํน์ง: ๊ตฌ๊ธ์ ๋ค๊ตญ์ด T5 ๋ชจ๋ธ, ํ์ธํ๋์ ์ ํฉ
- ์ ํฉ: ์ปค์คํ ๋ฒ์ญ ๋ชจ๋ธ ๊ฐ๋ฐ
- ํฌ๊ธฐ: ~580MB
# mBART ๋ชจ๋ธ๋ก ๋ค๊ตญ์ด ๋ฒ์ญ ์์
from transformers import MBartForConditionalGeneration, MBart50TokenizerFast
model = MBartForConditionalGeneration.from_pretrained(
"facebook/mbart-large-50-many-to-many-mmt"
)
tokenizer = MBart50TokenizerFast.from_pretrained(
"facebook/mbart-large-50-many-to-many-mmt"
)
# ์์ค ์ธ์ด ์ค์ (ํ๊ตญ์ด)
tokenizer.src_lang = "ko_KR"
article_ko = "์ธ๊ณต์ง๋ฅ ๊ธฐ์ ์ด ๋น ๋ฅด๊ฒ ๋ฐ์ ํ๊ณ ์์ต๋๋ค."
encoded_ko = tokenizer(article_ko, return_tensors="pt")
# ํ๊ฒ ์ธ์ด: ์์ด
generated_tokens = model.generate(
**encoded_ko,
forced_bos_token_id=tokenizer.lang_code_to_id["en_XX"]
)
translation = tokenizer.batch_decode(
generated_tokens,
skip_special_tokens=True
)
print(translation[0])
# ์ถ๋ ฅ: Artificial intelligence technology is developing rapidly.
- ๋น ๋ฅธ ์๋ + ๊ฐ๋ฒผ์ด ํ๊ฒฝ โ MarianMT
- ๋์ ํ์ง + ๋ค๊ตญ์ด โ mBART-50
- ํ๊ตญ์ด ํนํ โ opus-mt-tc-big-ko-en
- ์ปค์คํ ํ์ธํ๋ โ mT5 ๋๋ mBART
์ฌ๋ฅ๋ท์์ AI ๋ฒ์ญ ์๋น์ค๋ฅผ ์ ๊ณตํ๋ค๋ฉด, ์๋น์ค ๊ท๋ชจ์ ์๊ตฌ์ฌํญ์ ๋ง๊ฒ ๋ชจ๋ธ์ ์ ํํ๋ ๊ฒ ์ค์ํด!
๐ ์ค๋ ๋ฐฐ์ด ๊ฒ ์ด์ ๋ฆฌ!
์, ์ ๋ง ๋ง์ ๊ฑธ ๋ฐฐ์ ์ง? ๐ ๋ง์ง๋ง์ผ๋ก ์ค๋ ํต์ฌ ๋ด์ฉ์ ์ ๋ฆฌํด๋ณผ๊ฒ!
ํ๊น ํ์ด์ค์ Transformers๋ ์์ฒ ๊ฐ์ ์ฌ์ ํ์ต ๋ชจ๋ธ์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ.
pipeline("translation", model="...") ํ ์ค๋ก ๋ฒ์ญ AI๋ฅผ ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ด.
MarianMTModel๊ณผ MarianTokenizer๋ฅผ ์ง์ ๋ค๋ฃจ๋ฉด ๋ ์ธ๋ฐํ ์ ์ด๊ฐ ๊ฐ๋ฅํด.
๋ฐฐ์น ์ฒ๋ฆฌ, ์์ํ, ์ฒญํฌ ๋ถํ ๋ฑ์ผ๋ก ์ค์ ์๋น์ค์ ์ ํฉํ ์ฑ๋ฅ์ ๋ผ ์ ์์ด.
Seq2SeqTrainer๋ฅผ ์ฌ์ฉํด์ ํน์ ๋๋ฉ์ธ์ ํนํ๋ ๋ฒ์ญ ๋ชจ๋ธ์ ๋ง๋ค ์ ์์ด.
๋ฒ์ญ ๋ชจ๋ธ์ REST API๋ก ๋ฐฐํฌํด์ ์ค์ ์๋น์ค๋ก ๋ง๋ค ์ ์์ด.
โ ํ๊น ํ์ด์ค ํ๋ธ(huggingface.co)์์ ๋ค์ํ ๋ฒ์ญ ๋ชจ๋ธ ํ์ํด๋ณด๊ธฐ
โก ์์ ๋ง์ ๋๋ฉ์ธ ๋ฐ์ดํฐ๋ก ํ์ธํ๋ ์คํํด๋ณด๊ธฐ
โข BLEU, COMET ๋ฑ ๋ค์ํ ํ๊ฐ ์งํ๋ก ๋ชจ๋ธ ์ฑ๋ฅ ์ธก์ ํด๋ณด๊ธฐ
โฃ Docker + FastAPI๋ก ๋ฒ์ญ ์๋น์ค ์ปจํ ์ด๋ํํด๋ณด๊ธฐ
โค ํ๊น ํ์ด์ค Spaces์ ๋ฌด๋ฃ๋ก ๋ฐ๋ชจ ์ฑ ๋ฐฐํฌํด๋ณด๊ธฐ ๐
๊ด๋ จ ํค์๋
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.

๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.