spaCy: NLP Kelas Industri di Python
spaCy adalah pustaka open-source untuk pemrosesan bahasa alami (NLP) yang dirancang untuk penggunaan produksi. Jika large language model unggul dalam menghasilkan teks bebas, spaCy berfokus pada analisis teks yang cepat, deterministik, dan terstruktur: tokenisasi, penandaan kelas kata, dependency parsing, dan pengenalan entitas bernama. Tutorial ini membahas spaCy mulai dari instalasi hingga melatih model kustom, dengan satu contoh teks bisnis yang konsisten sepanjang pembahasan.
Apa Itu spaCy dan Posisinya
spaCy adalah pustaka Python yang mengubah teks mentah menjadi data linguistik terstruktur. Pustaka ini menyertakan model statistik terlatih untuk banyak bahasa dan menyediakan model objek yang rapi (Doc, Token, Span) untuk mengolah hasilnya. Pustaka ini ditulis dengan mempertimbangkan kinerja, sehingga mampu memproses teks dalam jumlah besar secara cepat di CPU.
spaCy vs. Large Language Model
LLM dan spaCy menyelesaikan masalah yang berbeda, dan dalam praktiknya keduanya sering digabungkan.
- Deterministik: spaCy menghasilkan keluaran yang sama untuk masukan yang sama setiap kali. Hal ini penting untuk pipeline yang memberi makan sistem hilir atau yang harus dapat diaudit.
- Kecepatan dan biaya: spaCy berjalan di CPU biasa dan memproses ribuan dokumen per detik untuk banyak tugas. Tidak ada biaya API per token.
- Struktur: spaCy mengembalikan anotasi bertipe pada level span (entitas, token, dependensi), bukan teks bebas yang harus diurai kembali.
- Privasi: teks tidak perlu keluar dari infrastruktur Anda.
Pola yang umum adalah menggunakan spaCy untuk ekstraksi dan perutean bervolume tinggi, lalu menyisakan LLM untuk sebagian kecil kasus yang benar-benar memerlukan penalaran terbuka. spaCy juga dapat mengintegrasikan prompt LLM sebagai komponen pipeline melalui paket spacy-llm bila Anda ingin keduanya dalam satu alur kerja.
Instalasi dan Mengunduh Model
Pasang spaCy dengan pip. Disarankan menggunakan virtual environment agar versi model tetap terkunci pada proyek Anda.
python -m venv .venv
source .venv/bin/activate # di Windows: .venv\Scripts\activate
pip install spacy
Model didistribusikan terpisah dari pustaka. Unduh model bahasa Inggris berukuran kecil untuk memulai:
python -m spacy download encorewebsm
Model bahasa Inggris mengikuti konvensi penamaan: en (bahasa), core (pipeline serbaguna), web (dilatih pada teks web), dan sufiks ukuran:
encorewebsm— kecil, cepat, tanpa word vector.encorewebmd— sedang, menyertakan word vector.encoreweblg— besar, lebih banyak vector.encorewebtrf— berbasis transformer, akurasi tertinggi, butuh komputasi lebih besar.
Anda dapat memeriksa apa yang terpasang dan memvalidasi kompatibilitasnya:
python -m spacy info
python -m spacy validate
Pipeline nlp dan Objek Inti
Memuat model memberi Anda objek nlp. Memanggilnya pada sebuah string akan menjalankan seluruh pipeline dan mengembalikan sebuah Doc.
import spacy
nlp = spacy.load("encorewebsm")
text = "Acme Corp acquired Globex Ltd for $4.5 billion in March 2023."
doc = nlp(text)
print(type(doc)) #
print(len(doc)) # jumlah token
print([token.text for token in doc])
Sebuah Doc adalah urutan objek Token. Potongan token yang berurutan adalah sebuah Span. Tiga objek inilah yang menjadi fondasi untuk segala hal lainnya.
# Token: satu kata, tanda baca, atau simbol
first = doc[0]
print(first.text, first.idx) # "Acme" 0
Span: potongan dari Doc
span = doc[0:2]
print(span.text) # "Acme Corp"
Kalimat juga merupakan Span
for sent in doc.sents:
print(sent.text)
Memeriksa Pipeline
Objek nlp memuat daftar komponen yang terurut. Anda dapat memeriksanya dan memodifikasinya.
print(nlp.pipenames)
['tok2vec', 'tagger', 'parser', 'attribute
ruler', 'lemmatizer', 'ner']
Setiap komponen menambahkan anotasi pada Doc saat dokumen melewatinya.
Tokenisasi, POS Tagging, dan Lematisasi
Tokenisasi memecah teks menjadi token menggunakan aturan spesifik bahasa. spaCy menangani kontraksi, tanda baca, dan kasus khusus tanpa kehilangan offset karakter asli.
doc = nlp("Acme didn't expand into Europe until 2024.")
for token in doc:
print(f"{token.text:>10} | {token.lemma:>8} | {token.pos:>6} | {token.tag}")
Atribut token yang berguna:
token.text— teks aslinya.token.lemma— bentuk dasar (misalnya "acquired" menjadi "acquire").token.pos— kelas kata kasar (NOUN, VERB, PROPN).token.tag— tag halus (VBD, NNP).token.isstop— apakah ia kata henti (stop word).token.isalpha,token.likenum,token.ispunct— flag boolean yang berguna.
contentwords = [t.lemma for t in doc if not t.isstop and not t.ispunct]
print(contentwords)
Dependency Parsing
Dependency parser menetapkan relasi sintaksis antar token, membentuk sebuah pohon. Inilah cara Anda menemukan nomina mana yang menjadi subjek sebuah verba, atau token mana yang menjadi tempat menempelnya sebuah pewatas.
doc = nlp("Acme Corp acquired Globex Ltd for $4.5 billion.")
for token in doc:
print(f"{token.text:>10} --{token.dep}--> {token.head.text}")
Setiap token memiliki head (induk sintaksisnya) dan label dep yang menjelaskan relasinya (nsubj, dobj, prep). Anda juga dapat menelusuri anak (children):
verb = [t for t in doc if t.lemma == "acquire"][0]
subjects = [child for child in verb.children if child.dep == "nsubj"]
objects = [child for child in verb.children if child.dep == "dobj"]
print("subjek:", subjects)
print("objek:", objects)
Ini memberi fondasi sederhana untuk ekstraksi relasi, yang akan kita bahas lagi nanti.
Pengenalan Entitas Bernama (NER)
NER mengidentifikasi objek dunia nyata seperti organisasi, orang, uang, dan tanggal. Entitas yang dikenali muncul di doc.ents sebagai objek Span dengan atribut label.
doc = nlp("Acme Corp acquired Globex Ltd for $4.5 billion in March 2023.")
for ent in doc.ents:
print(f"{ent.text:>15} | {ent.label:>10} | {ent.startchar}-{ent.endchar}")
Label keluaran yang umum mencakup ORG, MONEY, dan DATE. Untuk memahami sebuah label, tanyakan pada spaCy:
print(spacy.explain("ORG")) # "Companies, agencies, institutions, etc."
Visualisasi dengan displaCy
spaCy menyertakan visualizer bawaan. Dalam sebuah skrip, ia menyajikan halaman web kecil; dalam notebook, ia menampilkan secara inline.
from spacy import displacy
doc = nlp("Acme Corp acquired Globex Ltd for $4.5 billion in March 2023.")
Penyorotan entitas
displacy.serve(doc, style="ent")
Pohon dependensi
displacy.serve(doc, style="dep")
Dalam notebook Jupyter, gunakan displacy.render(doc, style="ent") alih-alih serve. Anda juga dapat mengekspor SVG hasil render ke berkas untuk laporan.
Pencocokan Berbasis Aturan: Matcher dan PhraseMatcher
Model statistik memang andal, tetapi sebagian pola lebih baik diungkapkan sebagai aturan: kode produk, satuan, atau frasa tetap. spaCy menyediakan dua matcher untuk ini.
Matcher
Token Matcher mencocokkan urutan yang dijelaskan oleh atribut token. Setiap pola adalah daftar kamus, satu kamus per token.
from spacy.matcher import Matcher
matcher = Matcher(nlp.vocab)
Cocokkan " acquired "
pattern = [
{"POS": "PROPN", "OP": "+"},
{"LEMMA": "acquire"},
{"POS": "PROPN", "OP": "+"},
]
matcher.add("ACQUISITION", [pattern])
doc = nlp("Acme Corp acquired Globex Ltd last year.")
for matchid, start, end in matcher(doc):
span = doc[start:end]
print(nlp.vocab.strings[matchid], "->", span.text)
Kunci OP mengontrol kuantifier: ! (negasi), ? (opsional), + (satu atau lebih), * (nol atau lebih).
PhraseMatcher
Bila Anda sudah memiliki daftar istilah persis, seperti katalog produk atau daftar pantau nama perusahaan, PhraseMatcher lebih cepat dan lebih sederhana.
from spacy.matcher import PhraseMatcher
phrasematcher = PhraseMatcher(nlp.vocab, attr="LOWER")
terms = ["Acme Corp", "Globex Ltd", "Initech"]
patterns = [nlp.makedoc(t) for t in terms]
phrasematcher.add("COMPANIES", patterns)
doc = nlp("Both acme corp and Initech reported strong quarters.")
for matchid, start, end in phrasematcher(doc):
print(doc[start:end].text)
Entitas Kustom dengan EntityRuler
EntityRuler memungkinkan Anda menambahkan entitas melalui aturan dan menggabungkannya dengan NER statistik. Ini adalah alat yang tepat ketika Anda memiliki istilah domain yang tidak dikenal model.
ruler = nlp.addpipe("entityruler", before="ner")
patterns = [
{"label": "PRODUCT", "pattern": "Widget Pro"},
{"label": "PRODUCT", "pattern": [{"LOWER": "widget"}, {"LOWER": "lite"}]},
{"label": "ORG", "pattern": "Initech"},
]
ruler.add
patterns(patterns)
doc = nlp("Initech launched Widget Pro and widget lite this quarter.")
for ent in doc.ents:
print(ent.text, ent.label)
Menempatkan ruler before="ner" membuat aturan Anda diprioritaskan; menempatkannya setelah membuat model statistik yang menang saat terjadi konflik. Pilih berdasarkan seberapa besar Anda memercayai masing-masing sumber.
Word Vector dan Kemiripan
Model sedang dan besar menyertakan word vector, yang memungkinkan Anda mengukur kemiripan semantik. Model kecil tidak menyertakannya, jadi pasang encorewebmd untuk bagian ini.
python -m spacy download encorewebmd
nlpmd = spacy.load("encorewebmd")
doc = nlp
md("revenue profit lettuce")
tokens = [t for t in doc]
for t in tokens:
print(t.text, t.hasvector, round(t.vectornorm, 2))
print(tokens[0].similarity(tokens[1])) # revenue vs profit (lebih tinggi)
print(tokens[0].similarity(tokens[2])) # revenue vs lettuce (lebih rendah)
Objek Doc dan Span juga menyediakan .similarity, yang dihitung dari rata-rata vector tokennya. Vector ini bersifat statis (bebas konteks), jadi untuk kemiripan yang peka konteks Anda akan menggunakan model transformer atau model embedding khusus.
Pemrosesan Efisien dengan nlp.pipe
Memanggil nlp(text) di dalam loop cukup baik untuk segelintir dokumen, tetapi untuk satu korpus hal itu lambat. nlp.pipe memproses teks sebagai aliran, mengelompokkannya menjadi batch, dan dapat menggunakan banyak proses.
texts = [
"Acme Corp acquired Globex Ltd for $4.5 billion.",
"Initech hired 200 engineers in Berlin.",
"Umbrella Inc reported a loss in Q3 2024.",
]
for doc in nlp.pipe(texts, batchsize=50):
orgs = [ent.text for ent in doc.ents if ent.label == "ORG"]
print(orgs)
Dua opsi penting:
batchsize— berapa banyak teks yang disangga per batch. Sesuaikan dengan ukuran dokumen Anda.nprocess— jumlah proses pekerja. Gunakan-1untuk semua core, tetapi ukur dahulu; overhead-nya bisa melebihi manfaatnya untuk teks pendek.
Jika Anda hanya membutuhkan sebagian pipeline, nonaktifkan komponen yang tidak Anda pakai untuk menghemat waktu:
with nlp.selectpipes(enable=["tok2vec", "ner"]):
for doc in nlp.pipe(texts):
print(doc.ents)
Anda juga dapat melampirkan metadata Anda sendiri pada setiap teks dan menerimanya kembali bersama Doc:
data = [("doc-1", "Acme Corp grew."), ("doc-2", "Initech shrank.")]
for doc, ctx in nlp.pipe(data, astuples=True):
print(ctx, "->", [t.text for t in doc])
Komponen Pipeline Kustom
Anda dapat menyisipkan logika Anda sendiri ke dalam pipeline dengan dekorator @Language.component. Sebuah komponen menerima Doc, memodifikasinya, lalu mengembalikannya. Contoh di bawah mengekstrak relasi pengakuisisi/target sederhana menggunakan hasil dependency parse dan menyimpannya sebagai atribut kustom.
from spacy.language import Language
from spacy.tokens import Doc
Daftarkan atribut ekstensi kustom pada Doc
if not Doc.hasextension("acquisitions"):
Doc.setextension("acquisitions", default=[])
@Language.component("acquisitionextractor")
def acquisitionextractor(doc):
results = []
for token in doc:
if token.lemma == "acquire" and token.pos == "VERB":
subj = [c for c in token.children if c.dep == "nsubj"]
obj = [c for c in token.children if c.dep == "dobj"]
if subj and obj:
results.append({
"acquirer": subj[0].text,
"target": obj[0].text,
})
doc..acquisitions = results
return doc
nlp.addpipe("acquisitionextractor", last=True)
doc = nlp("Acme acquired Globex. Initech acquired Hooli.")
print(doc..acquisitions)
Atribut ekstensi kustom diakses melalui namespace ., yang menjaganya tetap terpisah dari atribut bawaan spaCy. Komponen dapat diurutkan dengan first, last, before, atau after.
Melatih Model NER Kustom
Ketika entitas bawaan tidak mencukupi, Anda dapat melatih model sendiri. spaCy modern menggunakan alur kerja berbasis konfigurasi yang berpusat pada berkas config.cfg dan perintah spacy train, alih-alih loop pelatihan yang ditulis manual.
Langkah 1: Siapkan Data Pelatihan sebagai DocBin
Data pelatihan disimpan dalam format biner .spacy menggunakan DocBin. Setiap contoh adalah sebuah Doc dengan span entitas standar emas (gold).
import spacy
from spacy.tokens import DocBin
nlp = spacy.blank("en")
TRAINDATA = [
("Acme Corp launched Widget Pro.", {"entities": [(0, 9, "ORG"), (19, 29, "PRODUCT")]}),
("Initech ships Widget Lite today.", {"entities": [(0, 7, "ORG"), (14, 25, "PRODUCT")]}),
]
def makedocbin(data):
db = DocBin()
for text, ann in data:
doc = nlp.makedoc(text)
ents = []
for start, end, label in ann["entities"]:
span = doc.charspan(start, end, label=label, alignmentmode="contract")
if span is not None:
ents.append(span)
doc.ents = ents
db.add(doc)
return db
makedocbin(TRAINDATA).todisk("./train.spacy")
makedocbin(TRAINDATA).todisk("./dev.spacy") # dalam praktik gunakan set uji terpisah
Selalu periksa bahwa charspan mengembalikan sebuah span; offset yang tidak selaras secara diam-diam menghasilkan None dan akan membuang anotasi Anda.
Langkah 2: Buat Berkas Config
spaCy dapat menghasilkan config awal yang masuk akal untuk Anda, lalu mengisi nilai default.
python -m spacy init config config.cfg --lang en --pipeline ner
python -m spacy init fill-config config.cfg config.cfg
config.cfg yang dihasilkan mendeklarasikan pipeline, arsitektur model, dan hiperparameter pelatihan. Bagian utama yang perlu dikenali adalah [paths] (lokasi data Anda), [nlp] (definisi pipeline), dan [training] (optimizer, batching, evaluasi).
Langkah 3: Latih dan Evaluasi
Arahkan trainer ke data Anda dan ke direktori keluaran.
python -m spacy train config.cfg \
--output ./output \
--paths.train ./train.spacy \
--paths.dev ./dev.spacy
spaCy menulis model terbaik dan model terakhir ke ./output. Anda dapat mengevaluasi pada set uji terpisah lalu memuat pipeline terlatih seperti model lainnya.
python -m spacy evaluate ./output/model-best ./dev.spacy
trained = spacy.load("./output/model-best")
doc = trained("Globex Inc released Widget Pro.")
print([(e.text, e.label) for e in doc.ents])
Untuk proyek nyata, gunakan lebih banyak contoh (ratusan hingga ribuan per label), pertahankan set dev terpisah yang sesungguhnya, dan pertimbangkan spacy debug data untuk menangkap masalah anotasi sebelum pelatihan.
Model Berbasis Transformer
Untuk akurasi tertinggi, spaCy menyediakan pipeline transformer seperti encorewebtrf, yang menggunakan model seperti RoBERTa di belakang layar melalui paket spacy-transformers.
pip install spacy-transformers
python -m spacy download encorewebtrf
nlptrf = spacy.load("encorewebtrf")
doc = nlptrf("Acme Corp acquired Globex Ltd for $4.5 billion.")
print([(e.text, e.label) for e in doc.ents])
Pipeline transformer memberi representasi yang peka konteks dan biasanya akurasi lebih baik pada kasus sulit, dengan mengorbankan kecepatan dan memori. Pipeline ini sangat terbantu oleh GPU. Pendekatan praktisnya adalah membuat prototipe dengan model kecil, mengukur akurasi pada data Anda, lalu naik ke md/lg/trf hanya jika angka-angkanya membenarkan langkah itu.
Praktik Terbaik
- Muat model sekali saja.
spacy.loadmahal; muat saat startup dan gunakan kembali objeknlp. - Gunakan
nlp.pipeuntuk batch. Inilah percepatan tunggal terbesar untuk pemrosesan korpus. - Nonaktifkan komponen yang tidak dipakai. Jika hanya butuh NER, jangan membayar parser.
- Kunci versi model. Model terikat pada versi spaCy; catat dalam requirements agar hasil tetap dapat direproduksi.
- Gabungkan aturan dan statistik. Gunakan
EntityRulerdan matcher untuk pola yang sudah diketahui dan berpresisi tinggi, serta model statistik untuk kasus ekor panjang (long tail). - Validasi offset saat membangun data pelatihan. Selalu pastikan
char_spanbukanNone. - Ukur sebelum meningkatkan skala. Mulai dengan
sm, dan adopsi transformer hanya bila peningkatan akurasinya nyata dan membenarkan biayanya. - Pertahankan set evaluasi terpisah. Tanpa itu Anda tidak bisa tahu apakah perubahan benar-benar membantu.
Kesimpulan dan Poin Utama
spaCy adalah pilihan praktis ketika Anda membutuhkan pemrosesan teks yang cepat, terstruktur, dan dapat diulang di lingkungan produksi. spaCy melengkapi large language model alih-alih bersaing dengannya: spaCy menangani ekstraksi dan struktur bervolume tinggi, sementara LLM dapat mengambil sebagian kecil kasus yang membutuhkan penalaran terbuka.
Poin-poin utama:
- Pipeline
nlpmengubah teks menjadiDocberisi objekTokendanSpanyang membawa anotasi tokenisasi, POS, lemma, dependensi, dan entitas. - Alat berbasis aturan (
Matcher,PhraseMatcher,EntityRuler) menambahkan perilaku berpresisi tinggi dan spesifik domain di samping model statistik. - Word vector pada model
md/lgmemungkinkan perbandingan kemiripan; transformer padatrfmendorong akurasi lebih jauh. nlp.pipedan pemilihan komponen adalah tuas utama untuk memproses korpus besar secara efisien.- Alur kerja pelatihan berbasis config (data
DocBin,config.cfg,spacy train) memungkinkan Anda membangun model NER kustom secara dapat direproduksi.
Dengan blok-blok pembangun ini, Anda dapat menyusun pipeline NLP yang tangguh, cepat dijalankan, mudah diaudit, dan praktis untuk dikembangkan.