NLP 기초: 토큰화, 임베딩 및 최신 파이프라인
음성 비서에게 무언가를 요청할 때마다 Google 번역으로 텍스트를 번역하세요. 이메일 받은편지함에서 스팸을 필터링하거나 동영상의 자동 자막을 읽으세요. 당신은 그것을 사용하고 있습니까? 자연어 처리(NLP). 이 규율은, 언어학, 컴퓨터 과학, 인공지능의 교차점에서 인간의 언어를 이해하고, 해석하고, 생성하도록 기계를 교육합니다.
최근 몇 년 동안 NLP 분야는 급격한 변화를 겪었습니다. 우리는 지나갔다 뉘앙스를 이해할 수 있는 신경 모델에 대한 손으로 쓴 규칙과 정적 사전, 맥락과 심지어 아이러니함. 버트, GPT, 야마 차세대 모델은 우리가 탐구할 기본 사항 없이는 불가능합니다. 이 기사에서는: 토큰화, gli 임베딩 그리고 최신 NLP 파이프라인.
이것은 시리즈의 첫 번째 기사입니다. 최신 NLP: BERT에서 LLM까지. 우리는 절대적인 기본부터 시작하여 필요한 직관을 단계별로 구축합니다. 고급 언어 모델을 이해합니다. 우리는 특별한 관심을 기울일 것입니다 영어권 자료에서는 종종 간과되는 이탈리아어의 특수성에 대해 설명합니다.
무엇을 배울 것인가
- NLP란 무엇이며 왜 거의 모든 최신 AI 애플리케이션의 기초가 됩니까?
- 텍스트 전처리 방법: 소문자, 불용어, 형태소 분석 및 표제어 추출
- 토큰화에 대한 다양한 접근 방식: 단어 수준, 문자 수준 및 하위 단어(BPE, WordPiece, SentencePiece)
- 고전적인 텍스트 표현: Bag of Words 및 TF-IDF
- 단어 임베딩: Word2Vec, GloVe 및 의미의 기하학적 직관
- 상황별 임베딩: 정적 표현에서 BERT까지
- 문장 임베딩과 실제 적용
- 최신 NLP 파이프라인: 원시 텍스트에서 예측까지
- 이탈리아어에 대한 전처리의 특수성
- Python 코드를 사용한 완전한 엔드투엔드 예제
시리즈 개요
| # | Articolo | 집중하다 |
|---|---|---|
| 1 | 현재 위치 - NLP 기초 | 토큰화, 임베딩, 파이프라인 |
| 2 | BERT와 트랜스포머 | Attention 아키텍처, 사전 학습 |
| 3 | 감성 분석 | BERT를 사용한 텍스트 분류 |
| 4 | 명명된 엔터티 인식 | 텍스트에서 엔터티 추출 |
| 5 | 허깅페이스 트랜스포머 | 사전 학습된 라이브러리 및 모델 |
| 6 | 모델 미세 조정 | 귀하의 도메인에 BERT를 적용하십시오 |
| 7 | 이탈리아어를 위한 NLP | 이탈리아어용 템플릿 및 리소스 |
| 8 | BERT에서 LLM까지 | GPT, LLaMA 및 텍스트 생성 |
1. 텍스트 전처리: 데이터 준비
NLP 모델이 텍스트와 함께 작동하려면 먼저 다음이 필요합니다. 깨끗하고 표준화된. 거칠고 시끄러운 텍스트: 구두점, 대문자, 약어, 이모티콘, HTML, URL. 전처리는 이러한 혼란을 구조화되고 일관된 형식.
1.1 소문자화 및 정규화
첫 번째 단계는 모든 텍스트를 소문자로 변환하는 것입니다. 컴퓨터의 경우 "Home", "home" 및 "HOME"은 완전히 다른 세 개의 문자열입니다. 소문자로 통일합니다.
import re
import unicodedata
def normalize_text(text: str) -> str:
"""Normalizzazione base del testo."""
# Lowercasing
text = text.lower()
# Rimozione accenti (opzionale, NON consigliato per italiano)
# text = unicodedata.normalize('NFKD', text)
# Rimozione punteggiatura
text = re.sub(r'[^\w\s]', '', text)
# Rimozione spazi multipli
text = re.sub(r'\s+', ' ', text).strip()
return text
testo = "L'NLP e FANTASTICO! Analizza testi in 50+ lingue."
print(normalize_text(testo))
# Output: "lnlp e fantastico analizza testi in 50 lingue"
이탈리아어 악센트에 주의하세요
영어를 사용하는 많은 NLP 파이프라인에서는 악센트 제거가 표준 단계입니다. 이탈리아어에서는 그러나 악센트는 단어의 의미를 변경합니다. "하지만" (접속사) 대 "하지만" (나무), "그리고" (접속사) 대 "그리고" (동사). 악센트를 제거하지 마십시오 이탈리아어 텍스트로 작업할 때.
1.2 불용어: 정보 내용이 없는 단어
Le 불용어 의미론적 의미가 거의 없는 매우 자주 사용되는 단어입니다. 관사, 전치사, 접속사. 이를 제거하면 데이터의 차원이 감소합니다. 모델이 의미 있는 단어에 집중하는 데 도움이 됩니다.
이탈리아어 대 영어 불용어
| Lingua | 불용어의 예 | 일반적인 개수 |
|---|---|---|
| 영어 | the, is, at, which, on, a, an, and, 또는 | ~180단어 |
| 이탈리아 사람 | the, the, the, of, to, from, in, with, on, for, that, and, not, a | ~300단어 |
이탈리아어는 기사의 풍부함으로 인해 영어보다 불용어가 더 많습니다. (il, lo, la, i, gli, le), 연결된 전치사 (del, dello, della, nei, nei, nelle) 그리고 보조 동사 형태.
# Approccio 1: NLTK
from nltk.corpus import stopwords
import nltk
nltk.download('stopwords')
stop_it = set(stopwords.words('italian'))
print(f"Stopwords italiane NLTK: {len(stop_it)}")
# Output: Stopwords italiane NLTK: 279
testo = "il gatto mangia il pesce sul tavolo della cucina"
tokens = testo.split()
filtrato = [t for t in tokens if t not in stop_it]
print(filtrato)
# Output: ['gatto', 'mangia', 'pesce', 'tavolo', 'cucina']
# Approccio 2: spaCy (più completo)
import spacy
nlp = spacy.load("it_core_news_lg")
doc = nlp("il gatto mangia il pesce sul tavolo della cucina")
filtrato_spacy = [token.text for token in doc if not token.is_stop]
print(filtrato_spacy)
# Output: ['gatto', 'mangia', 'pesce', 'tavolo', 'cucina']
1.3 형태소 분석과 원형 분석
두 기술 모두 단어를 기본 형태로 축소하지만 그 방식은 매우 다릅니다.
형태소 분석과 Lemmatization - 비교
| 나는 기다린다 | 형태소 분석 | 표절화 |
|---|---|---|
| 방법 | 경험적 규칙으로 접미사 잘라내기 | 사전 및 형태소 분석 사용 |
| 결과 | 어간(항상 실제 단어는 아님) | Lemma(사전의 실제 단어) |
| IT 사례 | "먹어요" -> "먹어요" | "먹다" -> "먹다" |
| 속도 | 매우 빠르다 | 느림(사전 필요) |
| 정도 | 낮음(일반적인 과잉 형태소) | 높음(올바른 형태) |
| 이탈리아어의 경우 | 눈덩이 스테머(이탈리아 포터) | spaCy it_core_news_lg |
from nltk.stem.snowball import SnowballStemmer
import spacy
# Stemming con Snowball
stemmer = SnowballStemmer("italian")
parole = ["mangiando", "mangiare", "mangiato", "correre", "correndo", "bellissimo"]
stems = [stemmer.stem(p) for p in parole]
print(dict(zip(parole, stems)))
# {'mangiando': 'mang', 'mangiare': 'mang', 'mangiato': 'mang',
# 'correre': 'corr', 'correndo': 'corr', 'bellissimo': 'bellissim'}
# Lemmatization con spaCy
nlp = spacy.load("it_core_news_lg")
doc = nlp("Le ragazze stavano mangiando le mele più belle")
lemmi = [(token.text, token.lemma_, token.pos_) for token in doc]
for testo, lemma, pos in lemmi:
print(f" {testo:15s} -> {lemma:15s} ({pos})")
# le -> il (DET)
# ragazze -> ragazza (NOUN)
# stavano -> stare (AUX)
# mangiando -> mangiare (VERB)
# le -> il (DET)
# mele -> mela (NOUN)
# più -> più (ADV)
# belle -> bello (ADJ)
이탈리아어의 경우, spaCy를 사용한 표제어 추출 그리고 거의 항상 바람직하다
형태소에. 모델 it_core_news_lg 500,000개의 단어 벡터를 포함합니다.
토큰화, POS 태깅, 종속성 구문 분석, NER 및 표제어 분석을 지원합니다.
2. 토큰화: 기계가 텍스트를 읽는 방법
La 토큰화 텍스트를 개별 단위로 나누는 과정 전화 토큰. NLP 파이프라인의 첫 번째이자 가장 중요한 단계는 다음과 같습니다. 토큰화의 품질은 각 후속 모델의 성능에 직접적인 영향을 미칩니다.
세 가지 기본 접근 방식이 있으며 각각 서로 다른 이점과 장단점이 있습니다.
2.1 단어 수준 토큰화
가장 직관적인 접근 방식: 각 단어가 토큰이 됩니다.
# Approccio naive: split per spazio
testo = "L'intelligenza artificiale cambia il mondo"
tokens_naive = testo.split()
print(tokens_naive)
# ["L'intelligenza", 'artificiale', 'cambia', 'il', 'mondo']
# Problema: "L'intelligenza" e un singolo token!
# Approccio migliore: spaCy
import spacy
nlp = spacy.load("it_core_news_lg")
doc = nlp(testo)
tokens_spacy = [token.text for token in doc]
print(tokens_spacy)
# ["L'", 'intelligenza', 'artificiale', 'cambia', 'il', 'mondo']
# spaCy gestisce correttamente le elisioni italiane
단어 수준 토큰화의 한계
- 엄청난 어휘력: 각각의 고유한 단어에는 어휘 항목이 필요합니다. 이탈리아어에는 수십만 가지의 변화형이 있습니다
- 어휘에서 벗어난 단어(OOV): 학습 중에 한 번도 본 적이 없는 단어는 <UNK>(알 수 없음)가 됩니다.
- 형태학적 공유 없음: "먹는다", "먹는다", "먹는다"는 세 가지 완전히 별개의 관련 없는 토큰입니다.
2.2 캐릭터 수준 토큰화
다른 극단에서는 각 문자가 토큰이 됩니다. 어휘력이 약해요 (26글자+숫자+구두점) 그런데 그 순서가 엄청 길어집니다.
Testo: "ciao mondo"
Word-level: ["ciao", "mondo"] -> 2 token
Char-level: ["c","i","a","o"," ","m","o","n","d","o"] -> 10 token
Testo di 1000 parole:
Word-level: ~1.000 token
Char-level: ~5.000 token (5x più lungo!)
문자 토큰화는 알 수 없는 단어(모든 단어) 문제를 해결합니다. 표현할 수 있지만 시퀀스가 너무 길어서 모델을 만들기가 어렵습니다. 텍스트에서 장거리 관계를 포착합니다.
2.3 하위 단어 토큰화: 최적의 절충안
La 하위 단어 토큰화 모든 현대 모델에서 사용되는 방법 (BERT, GPT, LLaMA, T5). 아이디어는 훌륭합니다. 일반적인 단어는 전체로 유지되지만 단어는 rare는 모델이 이미 본 하위 단위(하위 단어)로 나뉩니다.
하위 단어 토큰화 알고리즘
| 연산 | 사용처 | 전략 | 방향 |
|---|---|---|---|
| BPE (바이트 쌍 인코딩) | GPT-2, GPT-3, GPT-4, LLaMA, RoBERTa | 가장 빈번한 쌍의 반복 병합 | 상향식 |
| 워드피스 | BERT, DistilBERT, ELECTRA | 가능성을 최대화하는 병합 | 상향식 |
| 문장조각 | T5, 알버트, XLNet, mBART | 텍스트를 원시 문자 스트림으로 처리 | 언어 독립적 |
| 유니그램 | SentencePiece(선택 사항), ALBERT | 큰 어휘부터 시작하여 덜 유용한 토큰을 제거합니다. | 하향식 |
BPE(바이트 쌍 인코딩) 작동 방식
BPE는 단일 문자에서 시작하여 가장 자주 사용되는 쌍을 반복적으로 병합합니다. 원하는 어휘 크기에 도달할 때까지.
Corpus: "basso basso bassa basso"
Passo 0 - Vocabolario iniziale (caratteri):
b, a, s, o
Passo 1 - Coppia più frequente: (s, s) -> "ss"
b a ss o b a ss o b a ss a b a ss o
Passo 2 - Coppia più frequente: (a, ss) -> "ass"
b ass o b ass o b ass a b ass o
Passo 3 - Coppia più frequente: (b, ass) -> "bass"
bass o bass o bass a bass o
Passo 4 - Coppia più frequente: (bass, o) -> "basso"
basso basso bass a basso
Vocabolario finale: [b, a, s, o, ss, ass, bass, basso]
워드피스 대 BPE
WordPiece는 BPE와 유사한 접근 방식을 사용하지만 더하기 쌍을 선택하는 대신
잦은, 최대화하는 것을 선택하십시오 있을 수 있는 일 말뭉치의
훈련의. 실제로 WordPiece는 더 유용한 토큰을 생성하는 병합을 선호합니다.
단순히 가장 일반적인 언어 모델이 아닌 언어 모델의 경우. 시작되지 않는 토큰
단어 앞에는 ##.
SentencePiece: 언어 독립
SentencePiece의 주요 차이점은 사전 토큰화가 필요하지 않습니다.. BPE와 WordPiece는 텍스트가 이미 단어(일반적으로 공백으로)로 구분되어 있다고 가정합니다. 영어와 이탈리아어에서는 잘 작동하지만 중국어, 일본어, 태국어와 같은 언어에서는 작동하지 않습니다. 단어 사이에 공백을 사용하지 않습니다. SentencePiece는 텍스트를 원시 바이트 스트림으로 처리합니다. 진정한 언어 독립적으로 만드는 것입니다.
3. 실제 예: HuggingFace를 사용한 토큰화
BERT와 GPT-2가 동일한 이탈리아어 텍스트를 어떻게 토큰화하는지 구체적으로 살펴보겠습니다.
우리는 도서관을 이용할 거예요 transformers 허깅페이스(HuggingFace) 제작.
from transformers import AutoTokenizer
# Testo di esempio in italiano
testo = "L'intelligenza artificiale sta rivoluzionando il mondo"
# --- BERT (WordPiece) ---
bert_tok = AutoTokenizer.from_pretrained("dbmdz/bert-base-italian-cased")
bert_tokens = bert_tok.tokenize(testo)
bert_ids = bert_tok.encode(testo)
print("BERT tokens:", bert_tokens)
print("BERT IDs: ", bert_ids)
# BERT tokens: ['L', "'", 'intelligenza', 'artificiale', 'sta',
# 'rivoluzionando', 'il', 'mondo']
# BERT IDs: [102, 55, 7, 5765, 6892, 379, 28648, 42, 1601, 103]
# --- GPT-2 (BPE) ---
gpt2_tok = AutoTokenizer.from_pretrained("gpt2")
gpt2_tokens = gpt2_tok.tokenize(testo)
gpt2_ids = gpt2_tok.encode(testo)
print("\nGPT-2 tokens:", gpt2_tokens)
print("GPT-2 IDs: ", gpt2_ids)
# GPT-2 tokens: ['L', "'", 'int', 'ell', 'ig', 'enza', ' art',
# 'ific', 'iale', ' sta', ' riv', 'oluz', 'ion',
# 'ando', ' il', ' mondo']
# --- Confronto ---
print(f"\nBERT: {len(bert_tokens)} token")
print(f"GPT-2: {len(gpt2_tokens)} token")
주요 관찰
- BERT 이탈리아어 (
dbmdz/bert-base-italian-cased)는 어휘가 이탈리아어 텍스트에 대해 훈련되었기 때문에 "intelligence" 및 "rivoluzionando"를 정수 토큰으로 인식합니다. - GPT-2 어휘가 주로 영어 텍스트를 기준으로 훈련되었기 때문에 이탈리아어 단어를 더 많은 하위 단어로 나눕니다.
- 대상 언어로 훈련된 토크나이저는 더 적은 수의 토큰을 생성합니다. 주의 창에서 더 많은 맥락 e 토큰당 비용 절감
- BERT는 특수 토큰을 추가합니다.
[CLS]처음에 그리고[SEP]결국. GPT-2는 그렇지 않습니다
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("dbmdz/bert-base-italian-cased")
# Dimensione vocabolario
print(f"Vocabolario BERT italiano: {tok.vocab_size} token")
# Output: Vocabolario BERT italiano: 31102 token
# Token speciali
print(f"[CLS] = {tok.cls_token} (ID: {tok.cls_token_id})")
print(f"[SEP] = {tok.sep_token} (ID: {tok.sep_token_id})")
print(f"[PAD] = {tok.pad_token} (ID: {tok.pad_token_id})")
print(f"[UNK] = {tok.unk_token} (ID: {tok.unk_token_id})")
print(f"[MASK] = {tok.mask_token} (ID: {tok.mask_token_id})")
# Decodifica: da token IDs -> testo
ids = tok.encode("NLP e fantastico")
print(f"\nEncode: {ids}")
print(f"Decode: {tok.decode(ids)}")
# Decode: [CLS] NLP e fantastico [SEP]
4. Bag of Words와 TF-IDF: 고전적 표현
단어 임베딩 이전에는 텍스트가 다음과 같이 표현되었습니다. 희소 벡터 단어 빈도를 기준으로 합니다. 이러한 방법은 여전히 많은 상황에서 사용됩니다. 그리고 그 한계를 이해하면 임베딩이 혁명이 된 이유를 이해하는 데 도움이 됩니다.
4.1 단어백(BoW)
모델 단어 가방 문서를 벡터로 표현합니다. 여기서 각 위치는 어휘 단어와 해당 단어의 값과 수에 해당합니다. 문서에서 해당 단어가 나타납니다.
from sklearn.feature_extraction.text import CountVectorizer
documenti = [
"il gatto mangia il pesce",
"il cane mangia la carne",
"il gatto insegue il cane"
]
vectorizer = CountVectorizer()
bow_matrix = vectorizer.fit_transform(documenti)
print("Vocabolario:", vectorizer.get_feature_names_out())
# ['cane', 'carne', 'gatto', 'il', 'insegue', 'la', 'mangia', 'pesce']
print("\nMatrice BoW:")
print(bow_matrix.toarray())
# [[0, 0, 1, 2, 0, 0, 1, 1], # doc 1
# [1, 1, 0, 1, 0, 1, 1, 0], # doc 2
# [1, 0, 1, 2, 1, 0, 0, 0]] # doc 3
4.2 TF-IDF(용어빈도 - 역문서빈도)
TF-IDF는 자체 단어에 가중치를 부여하여 BoW를 개선합니다. 상대적 중요성. 문서에서는 자주 등장하지만 전체 자료에서는 드물게 나타나는 단어에 더 큰 가중치가 부여됩니다. 어디서나 일반적인 단어("the", "the" 등)는 가중치가 낮습니다.
TF-IDF(t, d) = TF(t, d) x IDF(t)
dove:
TF(t, d) = frequenza del termine t nel documento d
IDF(t) = log(N / df(t))
N = numero totale di documenti
df(t) = numero di documenti che contengono il termine t
Esempio:
Parola "gatto" in documento 1:
TF = 1/5 = 0.2 (1 occorrenza su 5 parole)
IDF = log(3/2) = 0.405 (appare in 2 documenti su 3)
TF-IDF = 0.2 x 0.405 = 0.081
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
documenti = [
"il gatto mangia il pesce",
"il cane mangia la carne",
"il gatto insegue il cane"
]
tfidf = TfidfVectorizer()
tfidf_matrix = tfidf.fit_transform(documenti)
print("Feature:", tfidf.get_feature_names_out())
print("\nMatrice TF-IDF (arrotondata):")
print(np.round(tfidf_matrix.toarray(), 3))
# "pesce" e "carne" hanno pesi più alti perchè appaiono
# in un solo documento (più discriminanti)
BoW 및 TF-IDF의 한계
- 의미 없음: "개"와 "개"는 완전히 다릅니다. "은행"(강)과 "은행"(기관)은 동일합니다.
- 주문 없음: "고양이가 쥐를 먹는다"와 "쥐가 고양이를 먹는다"는 표현이 같다
- 높은 차원성: 100,000개의 단어로 구성된 어휘는 거의 모두 0인 100,000차원 벡터를 생성합니다(희소 벡터).
- 일반화 없음: 단어 사이의 관계를 포착하지 못합니다("왕"과 "여왕"은 친밀감이 없습니다).
5. 단어 임베딩: 기하학으로서의 의미
I 단어 임베딩 그들은 단어를 변형하여 NLP에 혁명을 일으켰습니다. 캡처하는 조밀한 저차원 벡터(일반적으로 100-300차원) 단어 사이의 의미적 관계. 비슷한 의미를 가진 두 단어는 벡터 이웃 벡터 공간에서.
5.1 Word2Vec: 모든 것을 변화시킨 발명품
Tomas Mikolov와 동료가 소개(Google, 2013), Word2Old 단어가 나타나는 문맥에서 시작하여 단어의 벡터를 학습합니다. 직관 기본 및 분포 가설: "단어의 특징은 다음과 같습니다. 그는 회사를 유지합니다."(J.R. Firth, 1957)
두 가지 Word2Vec 아키텍처
| 건축학 | 입력 | 출력 | 직관 |
|---|---|---|---|
| CBOW (연속적인 단어 가방) | 문맥(주변 단어) | 타겟 단어 | "___이(가) 먹는다"라는 맥락을 고려하여 "고양이"를 예측하세요. |
| 스킵그램 | 타겟 단어 | 문맥(주변 단어) | "cat"이라는 단어가 주어지면 "the", "eat" 등을 예측하세요. |
실제로, 스킵그램 소규모 데이터세트 및 캡처에 가장 적합 희귀한 단어가 더 좋습니다. CBOW 더 빠르고 자주 사용되는 단어와 잘 작동합니다.
Frase: "il gatto nero mangia il pesce fresco"
^
parola target
Con window_size = 2, Skip-gram impara:
gatto -> il (contesto a sinistra, distanza 1)
gatto -> nero (contesto a destra, distanza 1)
gatto -> mangia (contesto a destra, distanza 2)
Dopo milioni di frasi, parole che appaiono in contesti
simili avranno vettori simili:
gatto ~ felino ~ micio (contesti simili: "il ___ mangia")
cane ~ canino ~ cucciolo (contesti simili: "il ___ corre")
5.2 단어의 산술
단어 임베딩의 가장 놀라운 특성은 다음과 같습니다. 의미론적 관계 대수 연산이 됩니다 캐리어에. 유명한 비유는 다음과 같습니다.
왕 - 남자 + 여자 = 여왕
이것은 우연이 아닙니다. "남자"에서 "여자"로 이어지는 벡터는 다음과 같은 벡터입니다. "왕"에서 "여왕"으로. 이는 국가-자본, 동사-과거 시제, 최상급 형용사.
import gensim.downloader as api
# Carica word embeddings pre-addestrati
model = api.load("word2vec-google-news-300")
# Analogia: re - uomo + donna = ?
result = model.most_similar(
positive=["king", "woman"],
negative=["man"],
topn=3
)
print("king - man + woman =")
for word, score in result:
print(f" {word}: {score:.4f}")
# king - man + woman =
# queen: 0.7118
# monarch: 0.6189
# princess: 0.5902
# Similarità tra parole
print(f"\ncat ~ dog: {model.similarity('cat', 'dog'):.4f}")
print(f"cat ~ car: {model.similarity('cat', 'car'):.4f}")
# cat ~ dog: 0.7609
# cat ~ car: 0.2004
5.3 GloVe: 단어 표현을 위한 전역 벡터
장갑 (Stanford, 2014)는 예측하는 대신 다른 접근 방식을 취합니다. Word2Vec과 같은 단어별 컨텍스트, GloVe는 첫 번째 컨텍스트를 구축합니다. 전역 동시 발생 매트릭스 전체 코퍼스를 인수분해한 다음 이 행렬을 사용하여 벡터를 얻습니다. 기반으로 한 방법의 장점을 결합합니다. Word2Vec 로컬 학습의 글로벌 통계입니다.
Word2Vec 대 GloVe
| 나는 기다린다 | Word2Old | 장갑 |
|---|---|---|
| 방법 | 예측(신경망) | 개수 기반(행렬 분해) |
| 문맥 | 로컬 창 | 글로벌 코퍼스 통계 |
| 훈련 | 온라인(텍스트 스크롤) | 배치(전체 배열) |
| 일반적인 크기 | 100, 200, 300 | 50, 100, 200, 300 |
| 성능 | 비유에 탁월함 | 유사성 우수 |
6. 상황별 임베딩: 같은 단어, 다른 의미
Word2Vec과 GloVe에는 근본적인 한계가 있습니다. 단일 벡터 모든 단어와 함께, 맥락에 관계없이. 그러나 언어는 가득 차 있습니다. 모호함: "은행"이라는 단어는 완전히 다른 의미를 갖습니다. "학교 책상"과 "나폴리 책상".
그만큼 상황별 임베딩 이 문제를 해결하세요: 벡터 단어의 내용은 그것이 나타나는 전체 문장에 따라 달라집니다. 이는 에서 사용하는 접근 방식입니다. BERT, GPT 및 모든 Transformer 기반 모델.
정적 임베딩과 상황별 임베딩
| 나는 기다린다 | 정적(Word2Vec, GloVe) | 상황별(BERT, GPT) |
|---|---|---|
| 단어에 대한 벡터 | 고정된 것, 항상 같은 것 | 상황에 따라 다름 |
| 다의성 | 관리되지 않음("은행"에는 이동통신사가 하나만 있음) | 관리됨("거래"는 각 의미에 대해 서로 다른 벡터를 가짐) |
| 모델 | 조회 테이블 | 심층 신경망(변압기) |
| 모델 크기 | 몇 MB | 수백 MB 또는 GB |
| 속도 | 즉각적인 | 포워드 패스가 필요합니다 |
from transformers import AutoTokenizer, AutoModel
import torch
import torch.nn.functional as F
# Carica BERT italiano
tokenizer = AutoTokenizer.from_pretrained("dbmdz/bert-base-italian-cased")
model = AutoModel.from_pretrained("dbmdz/bert-base-italian-cased")
def get_word_embedding(sentence: str, word: str):
"""Ottieni l'embedding contestuale di una parola nella frase."""
inputs = tokenizer(sentence, return_tensors="pt")
tokens = tokenizer.tokenize(sentence)
with torch.no_grad():
outputs = model(**inputs)
# outputs.last_hidden_state: [batch, seq_len, hidden_dim]
embeddings = outputs.last_hidden_state[0] # [seq_len, 768]
# Trova l'indice del token target
word_idx = tokens.index(word) + 1 # +1 per [CLS]
return embeddings[word_idx]
# "banco" in contesti diversi
emb_scuola = get_word_embedding("Il banco di scuola e rotto", "banco")
emb_banca = get_word_embedding("Il banco di Napoli e storico", "banco")
emb_pesce = get_word_embedding("Il banco del pesce e fresco", "banco")
# Calcola similarità coseno
sim_12 = F.cosine_similarity(emb_scuola.unsqueeze(0), emb_banca.unsqueeze(0))
sim_13 = F.cosine_similarity(emb_scuola.unsqueeze(0), emb_pesce.unsqueeze(0))
sim_23 = F.cosine_similarity(emb_banca.unsqueeze(0), emb_pesce.unsqueeze(0))
print(f"banco(scuola) ~ banco(banca): {sim_12.item():.4f}")
print(f"banco(scuola) ~ banco(pesce): {sim_13.item():.4f}")
print(f"banco(banca) ~ banco(pesce): {sim_23.item():.4f}")
# I vettori saranno DIVERSI perchè BERT capisce il contesto!
이것이 근본적인 개념적 도약입니다. BERT를 사용하면 "은행"이라는 단어가 더 이상 존재하지 않습니다. 고정된 의미. 벡터는 다음과 같이 주변 환경에 따라 변경됩니다. 인간의 언어 이해에서 발생합니다.
7. 문장 임베딩: 전체 문장에 대한 하나의 벡터
종종 우리는 단일 단어를 삽입할 필요가 없지만전체 문장 또는 단락. 그만큼 문장 임베딩 그들은 의미를 압축합니다 단일 고정 크기 벡터에 모든 길이의 텍스트를 포함합니다.
참조 모델 e 문장-BERT(SBERT), 이는 변경됩니다.
비교 최적화된 문장 임베딩을 생성하는 BERT 아키텍처
유사성. 이탈리아어의 경우 모델 paraphrase-multilingual-MiniLM-L12-v2
384차원 벡터로 50개 이상의 언어를 지원합니다.
문장 임베딩의 응용
| 애플리케이션 | 설명 | 작동 방식 |
|---|---|---|
| 의미 검색 | 키워드가 아닌 의미로 검색하세요 | 쿼리 삽입, 가장 가까운 문서 검색 |
| 클러스터링 | 유사한 텍스트를 자동으로 그룹화 | 임베딩에 대한 K-평균 또는 HDBSCAN |
| 중복 감지 | 중복되거나 거의 중복된 항목 찾기 | 코사인 유사성 임계값 > 0.9 |
| 제로샷 분류 | 학습 데이터 없이 순위 지정 | 텍스트 임베딩과 라벨 임베딩 비교 |
from sentence_transformers import SentenceTransformer, util
# Modello multilingue (supporta italiano)
model = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2")
# Frasi in italiano
frasi = [
"Il gatto dorme sul divano",
"Il felino riposa sul sofa",
"La borsa e salita oggi",
"I mercati finanziari sono in crescita",
"Ho comprato un nuovo computer portatile"
]
# Genera embeddings (1 vettore per frase, 384 dimensioni)
embeddings = model.encode(frasi, convert_to_tensor=True)
print(f"Shape: {embeddings.shape}") # [5, 384]
# Calcola matrice di similarità
cosine_scores = util.cos_sim(embeddings, embeddings)
print("\nMatrice di Similarità:")
for i in range(len(frasi)):
for j in range(i + 1, len(frasi)):
print(f" {frasi[i][:40]:40s} <-> {frasi[j][:40]:40s}")
print(f" Similarità: {cosine_scores[i][j]:.4f}")
# Risultati attesi:
# "gatto dorme" <-> "felino riposa" : ~0.85 (molto simili)
# "borsa salita" <-> "mercati crescita": ~0.70 (correlati)
# "gatto dorme" <-> "borsa salita" : ~0.10 (non correlati)
8. 최신 NLP 파이프라인
우리는 개별 구성요소를 살펴보았습니다. 이제 작동 방식을 이해하기 위해 이들을 하나로 묶어 보겠습니다. 하나 최신 엔드투엔드 NLP 파이프라인, BERT, GPT 및 Transformer를 기반으로 한 모든 모델.
Testo Grezzo
|
v
[1. TOKENIZZAZIONE]
Input: "L'intelligenza artificiale e fantastica"
Output: ["L'", "intelligenza", "artificiale", "e", "fantastica"]
|
v
[2. ENCODING (Token -> ID)]
Input: ["L'", "intelligenza", "artificiale", "e", "fantastica"]
Output: [102, 55, 5765, 6892, 15, 23456, 103]
^[CLS] ^[SEP]
|
v
[3. EMBEDDING LAYER]
Input: [102, 55, 5765, 6892, 15, 23456, 103]
Output: Matrice [7 x 768] - un vettore 768-dim per ogni token
|
v
[4. TRANSFORMER ENCODER/DECODER]
Self-Attention: ogni token "guarda" tutti gli altri
Input: Matrice [7 x 768]
Output: Matrice [7 x 768] (vettori contestualizzati)
|
v
[5. TASK HEAD]
Classificazione: [CLS] embedding -> softmax -> classe
NER: ogni token -> etichetta entità
Generazione: ultimo token -> prossimo token
QA: posizione inizio/fine risposta
토큰의 역할 [CLS]
BERT에서는 특수 토큰 [CLS] 각 입력의 시작 부분에 삽입됩니다.
Transformer의 모든 레이어를 통과한 후 임베딩은 다음을 나타냅니다.
전체 시퀀스. 분류 작업의 입력으로 사용됩니다.
(감정 분석, 스팸 감지 등).
9. 이탈리아어를 위한 NLP: 특수성과 도구
이탈리아어는 영어와 구별되는 NLP에 대한 독특한 과제를 제시합니다. 그리고 다른 언어에서. 이러한 특성을 아는 것은 시스템 구축에 필수적입니다. 이탈리아어에 효과적인 NLP.
9.1 이탈리아어의 언어적 과제
NLP를 위한 이탈리아어의 특징
| 도전 | 설명 | Esempio |
|---|---|---|
| 풍부한 형태 | 각 동사에는 수십 개의 활용형이 있습니다. | "먹다"에는 50개 이상의 형태가 있습니다(나는 먹습니다, 나는 먹습니다, 나는 먹습니다, 우리는 먹습니다...) |
| 생략 및 아포스트로피 | 관사와 전치사 병합 | "그 남자", "예술의", "친구", "올해" |
| 연결된 전치사 | 전치사 + 기사를 한 단어로 | "del"(di+il), "nello"(in+lo), "sulla"(su+la) |
| 중요한 악센트 | 그들은 의미를 바꾼다 | "e"(및) 대 "e"(is), "da"(from) 대 "da"(주다) |
| 음핵 대명사 | 그들은 동사에 충실 | "give it to me" (give+me+it), "그에게 가져다 줘" |
| 무료 주문 | SVO는 필수가 아닙니다 | "마르코는 케이크를 먹는다" = "마르코는 케이크를 먹는다" |
9.2 이탈리아어를 위한 사전 훈련된 모델
주요 이탈리아 모델
| 모델 | 기초적인 | 작업 | 저장소 |
|---|---|---|---|
| dbmdz/bert-base-italian-cased | 버트 | 범용 이탈리아어 NLP | 포옹얼굴 |
| 알베르토 | 버트 | 이탈리아 소셜 미디어 (트위터) | 포옹얼굴 |
| 이탈리아 감성을 느껴보세요 | 움베르토 | 이탈리아 감성 분석 | 밀라NLProc |
| 이탈리아 감성을 느껴보세요 | 움베르토 | 감정 감지(기쁨, 분노, 두려움, 슬픔) | 밀라NLProc |
| 이탈리아어-법률-BERT | 버트 | 이탈리아어 법률 문서 | 딜리카리 |
| DeepMount00/Italian_NER_XXL | 버트 | 이탈리아어로 명명된 개체 인식 | 포옹얼굴 |
| it_core_news_lg | 스파시 CNN | 토큰화, POS, NER, 보조정리, 구문 분석 | 스파시 |
9.3 이탈리아어 전용 전처리
import spacy
import re
class ItalianPreprocessor:
"""Pipeline di preprocessing specifica per l'italiano."""
def __init__(self):
self.nlp = spacy.load("it_core_news_lg")
# Stopwords aggiuntive regionali/informali
self.custom_stops = {
"cioe", "quindi", "comunque", "praticamente",
"allora", "insomma", "magari", "ecco", "tipo",
"boh", "mah", "vabbe", "ok", "okay"
}
def preprocess(self, text: str, remove_stops: bool = True,
lemmatize: bool = True) -> list[str]:
"""Preprocessing completo per testo italiano."""
# 1. Normalizzazione base
text = text.lower()
text = re.sub(r'http\S+|www\.\S+', '', text) # rimuovi URL
text = re.sub(r'[^\w\s\']', '', text) # mantieni apostrofi
text = re.sub(r'\d+', '', text) # rimuovi numeri
text = re.sub(r'\s+', ' ', text).strip()
# 2. Analisi con spaCy
doc = self.nlp(text)
# 3. Filtraggio e lemmatizzazione
tokens = []
for token in doc:
# Salta punteggiatura e spazi
if token.is_punct or token.is_space:
continue
# Salta stopwords se richiesto
if remove_stops and (token.is_stop or
token.text in self.custom_stops):
continue
# Lemmatizza o usa la forma originale
word = token.lemma_ if lemmatize else token.text
if len(word) > 1: # salta caratteri singoli
tokens.append(word)
return tokens
# Esempio d'uso
prep = ItalianPreprocessor()
testo = """L'intelligenza artificiale sta rivoluzionando
il modo in cui le aziende italiane gestiscono i loro
processi, cioe praticamente tutto sta cambiando."""
risultato = prep.preprocess(testo)
print("Token processati:", risultato)
# ['intelligenza', 'artificiale', 'rivoluzionare', 'modo',
# 'azienda', 'italiano', 'gestire', 'processo', 'cambiare']
10. 엔드투엔드 예: 이탈리아어로 의미 검색
우리가 배운 모든 것을 하나의 완전한 예에 넣어 보겠습니다. 의미 검색 이탈리아어 텍스트 모음에 관한 것입니다. 세트가 주어지면 문서 및 사용자 쿼리를 사용하여 가장 관련성이 높은 문서를 찾습니다. 문장 임베딩.
from sentence_transformers import SentenceTransformer, util
import torch
class SemanticSearchIT:
"""Motore di ricerca semantica per testi italiani."""
def __init__(self, model_name: str =
"paraphrase-multilingual-MiniLM-L12-v2"):
self.model = SentenceTransformer(model_name)
self.documents: list[str] = []
self.embeddings = None
def index_documents(self, documents: list[str]) -> None:
"""Indicizza i documenti calcolando gli embeddings."""
self.documents = documents
self.embeddings = self.model.encode(
documents,
convert_to_tensor=True,
show_progress_bar=True
)
print(f"Indicizzati {len(documents)} documenti")
print(f"Shape embeddings: {self.embeddings.shape}")
def search(self, query: str, top_k: int = 3) -> list[dict]:
"""Cerca i documenti più rilevanti per la query."""
query_embedding = self.model.encode(
query, convert_to_tensor=True
)
scores = util.cos_sim(query_embedding, self.embeddings)[0]
top_results = torch.topk(scores, k=min(top_k, len(self.documents)))
results = []
for score, idx in zip(top_results.values, top_results.indices):
results.append({
"documento": self.documents[idx],
"score": round(score.item(), 4),
"indice": idx.item()
})
return results
# --- Esempio d'uso ---
corpus = [
"Python e un linguaggio di programmazione versatile e facile da imparare",
"Il machine learning permette ai computer di imparare dai dati",
"Angular e un framework per costruire applicazioni web moderne",
"La pasta alla carbonara e un piatto tipico della cucina romana",
"I database relazionali usano SQL per interrogare i dati",
"Il deep learning utilizza reti neurali con molti strati nascosti",
"Roma e la capitale d'Italia e ha una storia millenaria",
"Le API REST permettono la comunicazione tra servizi web",
"Il Natural Language Processing analizza e comprende il testo",
"La pizza napoletana e patrimonio UNESCO dal 2017"
]
# Crea il motore di ricerca e indicizza
search_engine = SemanticSearchIT()
search_engine.index_documents(corpus)
# Esegui alcune ricerche
queries = [
"come analizzare il linguaggio naturale",
"framework per sviluppo frontend",
"cucina tradizionale italiana"
]
for query in queries:
print(f"\nQuery: '{query}'")
print("-" * 60)
results = search_engine.search(query, top_k=3)
for i, r in enumerate(results, 1):
print(f" {i}. [{r['score']:.4f}] {r['documento']}")
예상 결과
의미론적 검색에는 다음이 포함됩니다. 의미, 단어뿐만이 아닙니다. 예를 들어:
- "자연어를 분석하는 방법" 해당 단어가 정확히 포함되어 있지 않더라도 NLP 문서를 찾습니다.
- "프론트엔드 개발을 위한 프레임워크" 문서에 "프론트엔드"가 나타나지 않더라도 Angular를 찾습니다(그러나 "최신 웹 애플리케이션"은 의미상 관련이 있습니다).
- "전통 이탈리아 요리" 모델이 의미론적 관계를 이해하므로 카르보나라와 피자를 모두 찾습니다.
로드맵: 여기에서 LLM까지
이 기사에서 우리는 현대 NLP의 기초를 구축했습니다. 상황별 임베딩 및 전체 파이프라인까지 텍스트 전처리. 우리가 택한 경로를 요약해 보겠습니다.
개념 요약
| 개념 | 그가 하는 일 | 진화 |
|---|---|---|
| 전처리 | 원시 텍스트를 정리하고 표준화합니다. | 수동 규칙 -> spaCy 파이프라인 |
| 토큰화 | 텍스트를 개별 단위로 나눕니다. | 단어 -> 문자 -> 하위 단어(BPE/WordPiece) |
| 활/TF-IDF | 텍스트를 희소 벡터로 나타냅니다. | 단순하지만 의미가 없음 |
| 단어 임베딩 | 의미를 포착하는 조밀한 벡터 | Word2Vec -> GloVe -> FastText |
| 상황별 임베딩 | 상황에 따른 벡터 | ELMo -> BERT -> GPT |
| 문장 임베딩 | 전체 문장에 대한 벡터 | 미디어 풀링 -> Sentence-BERT |
에서 다음 기사 있는 건축으로 도약하겠습니다. 모든 것에 혁명을 일으켰습니다: 트랜스포머. 메커니즘을 자세히 살펴보겠습니다. 의 자기 관심, 우리는 왜 BERT가 게임 체인저였는지 이해하고 배울 것입니다. 텍스트 분류, 질문 답변 등 실제 작업에 사용합니다.
자세히 알아볼 수 있는 리소스
- spaCy 이탈리아 모델: spaCy 이탈리아 모델 공식 문서(spacy.io/models/it)
- HuggingFace 모델: 사전 훈련된 이탈리아어 모델 저장소(huggingface.co/models?언어=it)
- 문장-BERT: 문장 변환기 문서(sbert.net)
- 느낌: 이탈리아어에 대한 감정 분석 및 감정 분류(MilaNLProc)
- 종이 Word2Vec: "벡터 공간에서 단어 표현의 효율적인 추정"(Mikolov et al., 2013)
- 종이장갑: “단어 표현을 위한 전역 벡터”(Pennington et al., 2014)
- 종이 BERT: "BERT: 심층 양방향 변환기의 사전 훈련"(Devlin et al., 2019)







