## Pra pemrosesan text Pemrosesan Bahasa Alami (NLP) telah maju secara signifikan dan sekarang memainkan peran penting dalam berbagai aplikasi dunia nyata seperti chatbot, mesin pencari, dan analisis sentimen. Langkah awal dalam alur kerja NLP apa pun adalah pra-pemrosesan teks, yang menyiapkan data teks mentah untuk analisis dan pemodelan lebih lanjut. Pemrosesan teks melibatkan pembersihan dan penyiapan data teks mentah untuk analisis atau pelatihan model lebih lanjut. Pra-pemrosesan teks yang tepat dapat secara signifikan berdampak pada kinerja dan akurasi model NLP. **Pentingnya Pra-pemrosesan Teks** Data teks mentah biasanya mengandung noise dan tidak terstruktur, mengandung berbagai ketidakkonsistenan seperti kesalahan ketik, bahasa gaul, singkatan, dan informasi yang tidak relevan. Pra-pemrosesan membantu dalam: * **Meningkatkan Kualitas Data:** Menghapus noise dan informasi yang tidak relevan memastikan bahwa data yang dimasukkan ke dalam model bersih dan konsisten. * **Meningkatkan Kinerja Model:** Teks yang telah diproses dengan baik dapat menghasilkan ekstraksi fitur yang lebih baik, meningkatkan kinerja model NLP. * **Mengurangi Kompleksitas:** Menyederhanakan data teks dapat mengurangi kompleksitas komputasi dan membuat model lebih efisien. ### **Teknik Pra-pemrosesan Teks dalam NLP** * **Ekspresi Reguler:** Ekspresi reguler (regex) adalah alat penting dalam pra-pemrosesan teks untuk Pemrosesan Bahasa Alami (NLP). Alat ini memungkinkan pencocokan pola dan manipulasi teks yang efisien dan fleksibel. * **Tokenisasi:** Tokenisasi adalah proses memecah teks menjadi unit-unit yang lebih kecil seperti kata atau kalimat. Ini adalah langkah penting dalam NLP karena mengubah teks mentah menjadi format terstruktur yang dapat dianalisis lebih lanjut. * **Lematisasi dan Stemming:** Lematisasi dan stemming adalah teknik yang digunakan dalam NLP untuk mengurangi kata-kata ke bentuk dasar atau akar mereka. Proses ini penting untuk tugas-tugas seperti normalisasi teks, temu balik informasi, dan penambangan teks. * **Parts of Speech (POS):** Penandaan Parts of Speech (POS) melibatkan pelabelan setiap kata dalam sebuah kalimat dengan part of speech-nya yang sesuai, seperti kata benda, kata kerja, kata sifat, dll. Informasi ini sangat penting untuk banyak aplikasi NLP, termasuk parsing, temu balik informasi, dan analisis teks. **Contoh - Pra-pemrosesan Teks dalam NLP** Sekarang, kita akan melakukan tugas-tugas pada korpus sampel: ```python corpus = [ "I can't wait for the new season of my favorite show!", "The COVID-19 pandemic has affected millions of people worldwide.", "U.S. stocks fell on Friday after news of rising inflation.", "<html><body>Welcome to the website!</body></html>", "Python is a great programming language!!! ??" ] ``` 1. **Pembersihan Teks** Kita akan mengonversi teks menjadi huruf kecil, menghapus tanda baca, angka, karakter khusus, dan tag HTML. * Mendefinisikan fungsi `clean_text()` untuk membersihkan dan menormalkan data teks mentah untuk tugas NLP. * Menerapkan `clean_text()` ke setiap dokumen dalam daftar korpus menggunakan list comprehension. * Menyimpan versi yang telah dibersihkan dari semua dokumen dalam daftar baru bernama `cleaned_corpus`. * Mencetak `cleaned_corpus` yang siap untuk tokenisasi. ```python import re import string from bs4 import BeautifulSoup def clean_text(text): text = text.lower() # Huruf kecil text = re.sub(r'\d+', '', text) # Hapus angka text = text.translate(str.maketrans('', '', string.punctuation)) # Hapus tanda baca text = re.sub(r'\W', ' ', text) # Hapus karakter khusus text = BeautifulSoup(text, "html.parser").get_text() # Hapus tag HTML return text cleaned_corpus = [clean_text(doc) for doc in corpus] print(cleaned_corpus) ``` **Output:** `['i cant wait for the new season of my favorite show', 'the covid pandemic has affected millions of people worldwide', 'us stocks fell on friday after news of rising inflation', 'htmlbodywelcome to the websitebodyhtml', 'python is a great programming language ']` 2. **Tokenisasi** * Membagi teks yang telah dibersihkan menjadi token (kata). * Mengimpor `word_tokenize` untuk membagi teks menjadi kata-kata . * Mengunduh model tokenizer NLTK yang diperlukan ('punkt_tab'). * Melakukan tokenisasi pada setiap dokumen yang telah dibersihkan dalam `cleaned_corpus`. * Menyimpan daftar token untuk setiap dokumen dalam `tokenized_corpus`. * Mencetak output tokenisasi akhir (daftar dari daftar kata). ```python from nltk.tokenize import word_tokenize import nltk nltk.download('punkt_tab') tokenized_corpus = [word_tokenize(doc) for doc in cleaned_corpus] print(tokenized_corpus) ``` **Output:** `[['i', 'cant', 'wait', 'for', 'the', 'new', 'season', 'of', 'my', 'favorite', 'show'], ['the', 'covid', 'pandemic', 'has', 'affected', 'millions', 'of', 'people', 'worldwide'], ['us', 'stocks', 'fell', 'on', 'friday', 'after', 'news', 'of', 'rising', 'inflation'], ['htmlbodywelcome', 'to', 'the', 'websitebodyhtml'], ['python', 'is', 'a', 'great', 'programming', 'language']]` 3. **Penghapusan Kata Umum (Stop Words)** Menghapus kata-kata umum dari token. * Mengimpor daftar stop words bahasa Inggris dari `nltk.corpus.stopwords`. * Mengunduh korpus stop words menggunakan `nltk.download('stopwords')`. * Menyimpan semua stop words bahasa Inggris (seperti "the", "is", "and", dll.) dalam sebuah set bernama `stop_words` untuk pencarian cepat. * Mengiterasi setiap dokumen dalam `tokenized_corpus` dan menghapus semua stop words. * Menyimpan token yang telah dibersihkan (bukan stop word) ke dalam `filtered_corpus`. * Mencetak daftar dokumen. ```python from nltk.corpus import stopwords nltk.download('stopwords') stop_words = set(stopwords.words('english')) filtered_corpus = [[word for word in doc if word not in stop_words] for doc in tokenized_corpus] print(filtered_corpus) ``` **Output:** `[['cant', 'wait', 'new', 'season', 'favorite', 'show'], ['covid', 'pandemic', 'affected', 'millions', 'people', 'worldwide'], ['us', 'stocks', 'fell', 'friday', 'news', 'rising', 'inflation'], ['htmlbodywelcome', 'websitebodyhtml'], ['python', 'great', 'programming', 'language']]` 4. **Stemming dan Lematisasi** Mengurangi kata-kata ke bentuk dasarnya menggunakan stemming dan lemmatisasi. * Mengimpor `PorterStemmer` dan `WordNetLemmatizer` dari NLTK. * Mengunduh sumber daya wordnet yang diperlukan untuk lemmatisasi. * Menginisialisasi stemmer dan lemmatizer. * Menerapkan stemming ke setiap kata dalam `filtered_corpus` dan menyimpan hasilnya dalam `stemmed_corpus`. * Menerapkan lemmatisasi ke setiap kata dalam `filtered_corpus` dan menyimpan hasilnya dalam `lemmatized_corpus`. * Mencetak versi korpus yang telah distem dan dilemmatisasi. ```python from nltk.stem import PorterStemmer, WordNetLemmatizer nltk.download('wordnet') stemmer = PorterStemmer() lemmatizer = WordNetLemmatizer() stemmed_corpus = [[stemmer.stem(word) for word in doc] for doc in filtered_corpus] lemmatized_corpus = [[lemmatizer.lemmatize(word) for word in doc] for doc in filtered_corpus] print("\n4. Korpus Setelah Stemming:") print(stemmed_corpus) print("\nKorpus Setelah Lematisasi:") print(lemmatized_corpus) ``` **Output:** `4. Korpus Setelah Stemming: [['cant', 'wait', 'new', 'season', 'favorit', 'show'], ['covid', 'pandem', 'affect', 'million', 'peopl', 'worldwid'], ['us', 'stock', 'fell', 'friday', 'news', 'rise', 'inflat'], ['htmlbodywelcom', 'websitebodyhtml'], ['python', 'great', 'program', 'languag']] Korpus Setelah Lematisasi: [['cant', 'wait', 'new', 'season', 'favorite', 'show'], ['covid', 'pandemic', 'affected', 'million', 'people', 'worldwide'], ['u', 'stock', 'fell', 'friday', 'news', 'rising', 'inflation'], ['htmlbodywelcome', 'websitebodyhtml'], ['python', 'great', 'programming', 'language']]` 5. **Menangani Kontraksi** Mengembalikan kata-kata yang merupakan bentuk singkat (kontraksi) menjadi bentuk lengkapnya * Mengimpor pustaka `contractions`, yang memperluas kata-kata yang disingkat. * Menerapkan `contractions.fix()` ke setiap dokumen dalam `cleaned_corpus`. * Memperluas semua kontraksi dalam teks untuk kejelasan dan konsistensi yang lebih baik. * Menyimpan output dalam `expanded_corpus`. * Mencetak daftar dokumen dengan semua kontraksi yang telah diperluas. ```python import contractions expanded_corpus = [contractions.fix(doc) for doc in cleaned_corpus] print("\n5. Korpus Setelah Penanganan Kontraksi:") print(expanded_corpus) ``` **Output:** `5. Korpus Setelah Penanganan Kontraksi: ['i cannot wait for the new season of my favorite show', 'the covid pandemic has affected millions of people worldwide', 'us stocks fell on friday after news of rising inflation', 'htmlbodywelcome to the websitebodyhtml', 'python is a great programming language ']` ### Kontraksi bahasa indonesia ```pyhton= import re def expand_indonesian_contractions(text): """ Fungsi untuk memperluas bentuk slang atau kontraksi informal bahasa Indonesia menjadi bentuk baku. Args: text (str): Teks input dalam bahasa Indonesia. Returns: str: Teks dengan kontraksi/slang yang telah diperluas. """ # Kamus kontraksi/slang bahasa Indonesia contractions_dict = { "gak": "tidak", "ga": "tidak", "nggak": "tidak", "enggak": "tidak", "ngga": "tidak", "gk": "tidak", # Sangat informal "gue": "saya", "gw": "saya", "gua": "saya", "lu": "kamu", "loe": "kamu", "dah": "sudah", "udah": "sudah", "aja": "saja", "ajah": "saja", "yg": "yang", "utk": "untuk", "dlm": "dalam", "dr": "dari", "dg": "dengan", "jd": "jadi", "krn": "karena", "tp": "tapi", "tapi": "tetapi", # Bisa dianggap normalisasi "banget": "sekali", # Dalam konteks "enak banget" -> "enak sekali" "bgt": "sekali", "lagi": "sedang", # Opsional, tergantung konteks "lg": "sedang", } # Membuat pola regex untuk mencocokkan kata-kata utuh pattern = r'\b(' + '|'.join(re.escape(key) for key in contractions_dict.keys()) + r')\b' # Fungsi pengganti (DIPERBAIKI) def replace_match(match): original_word = match.group(0) # Ambil kata asli (misal: 'Gue') lower_word = original_word.lower() # Konversi ke huruf kecil (misal: 'gue') return contractions_dict[lower_word] # Cari di kamus # Lakukan penggantian expanded_text = re.sub(pattern, replace_match, text, flags=re.IGNORECASE) return expanded_text # --- Contoh Penggunaan --- corpus = [ "Gue gak mau makan itu, rasanya aneh banget!", "Lu udah selesai belajar belum? Aku lagi ngerjain tugas nih.", "Buat presentasi yg bagus utk besok, ya!", "Dia emang jago, tp jangan sombong dong.", "Kerjaannya gampang bgt, cuma ngetik doang." ] print("Teks Asli:") for doc in corpus: print(f" -> {doc}") print("\nTeks Setelah Penanganan Kontraksi:") expanded_corpus = [expand_indonesian_contractions(doc) for doc in corpus] for doc in expanded_corpus: print(f" -> {doc}") ``` **Output:** `Teks Asli: -> Gue gak mau makan itu, rasanya aneh banget! -> Lu udah selesai belajar belum? Aku lagi ngerjain tugas nih. -> Buat presentasi yg bagus utk besok, ya! -> Dia emang jago, tp jangan sombong dong. -> Kerjaannya gampang bgt, cuma ngetik doang. Teks Setelah Penanganan Kontraksi: -> saya tidak mau makan itu, rasanya aneh sekali! -> kamu sudah selesai belajar belum? Aku sedang ngerjain tugas nih. -> Buat presentasi yang bagus untuk besok, ya! -> Dia emang jago, tapi jangan sombong dong. -> Kerjaannya gampang sekali, cuma ngetik doang.` **6. Menangani Emoji dan Emotikon** Mengonversi emoji ke representasi teksnya. * Mengimpor pustaka `emoji` untuk menangani emoji dalam teks. * Menerapkan `emoji.demojize()` ke setiap dokumen dalam `cleaned_corpus`. * Mengonversi semua emoji menjadi teks deskriptif. * Menyimpan output ke dalam `emoji_corpus`. * Mencetak daftar dokumen di mana emoji diganti dengan nama yang mudah dibaca. ```python import emoji emoji_corpus = [emoji.demojize(doc) for doc in cleaned_corpus] print(emoji_corpus) ``` **Output:** `['i cant wait for the new season of my favorite show', 'the covid pandemic has affected millions of people worldwide', 'us stocks fell on friday after news of rising inflation', 'htmlbodywelcome to the websitebodyhtml', 'python is a great programming language ']` --- **7. Pemeriksaan Ejaan** Memperbaiki kesalahan ejaan dalam teks. * Mengimpor kelas `SpellChecker` dari pustaka `pyspellchecker`. * Menginisialisasi pemeriksa ejaan dengan `spell = SpellChecker()`. * Mengiterasi setiap kata dalam setiap dokumen yang telah ditokenisasi dari `tokenized_corpus`. * Menerapkan `spell.correction(word)` untuk memperbaiki kata-kata yang salah eja. * Menyimpan kata-kata yang telah diperbaiki ke dalam `corrected_corpus`. * Mencetak daftar dokumen yang telah ditokenisasi dengan perbaikan ejaan yang telah diterapkan. ```python from spellchecker import SpellChecker spell = SpellChecker() corrected_corpus = [[spell.correction(word) for word in doc] for doc in tokenized_corpus] print(corrected_corpus) ``` **Output:** `[['i', 'cant', 'wait', 'for', 'the', 'new', 'season', 'of', 'my', 'favorite', 'show'], ['the', 'bovid', 'pandemic', 'has', 'affected', 'millions', 'of', 'people', 'worldwide'], ['us', 'stocks', 'fell', 'on', 'friday', 'after', 'news', 'of', 'rising', 'inflation'], [None, 'to', 'the', None], ['python', 'is', 'a', 'great', 'programming', 'language']]` Setelah menyelesaikan semua langkah pra-pemrosesan, korpus akhir telah siap untuk tugas NLP hilir seperti ekstraksi fitur, klasifikasi teks, atau analisis sentimen. Pipeline terstruktur ini memastikan teks bersih, distandardisasi, dan dioptimalkan untuk pemodelan, pada akhirnya meningkatkan efektivitas dan keandalan aplikasi NLP. ## Spelling bahasa indonesia ### Menggunakan Peter Norvig Spell Checker Metode paling sederhana untuk Spelling Corrector adalah dengan metode yang diterapkan oleh [Peter Norvig](https://norvig.com/spell-correct.html) dengan pendekatan Bayes Theorem. --- Untuk mendapatkan kata yang tepat dapat dituliskan dengan persamaan berikut: $$correction (w) = argmax_{c ∈ candidates} P(c|w)$$ artinya dicari probabilitas suatu kata $w$ yang paling tinggi dari kumpulan $candidates$. Misalkan diketahui seperti berikut. ``` w = 'kcing' candidates = ['kacing', 'kecing', 'kucing'] P('kacing'|'kcing') = 0.6 P('kecing'|'kcing') = 0.3 P('kucing'|'kcing') = 0.8 ``` Hasilnya tentu saja untuk `correction('kcing')` adalah `kucing` dengan probabilitas terbesar yaitu `0.8`. Persamaan di atas dapat dituliskan menjadi $$correction (w) = argmax_{c ∈ candidates} \frac{P(c)P(w|c)}{P(w)}$$ Karena $P(w)$ adalah sama untuk setiap kemungkinan `candidate c`, maka bisa kita hilangkan dan ditulis menjadi $$correction (w) = argmax_{c ∈ candidates} P(c)P(w|c)$$ Berdasarkan persamaan di atas, terdapat empat bagian: 1. **Selection Mechanism**: $argmax$, digunakan untuk memilih kandidat yang memiliki probabilitas tertinggi. 2. **Candidate Model**: $c ∈ candidates$, menunjukkan kandidat kata `c` dari kumpulan kandidat `candidates`. 3. **Language Model**: $P(c)$, probabilitas kandidat `c` muncul pada sebuah corpus dokumen. Pada kasus kita, misalkan probabilitas kemunculan `P(kucing)` pada corpus `wiki.txt` adalah `0.3`. 4. **Error Model**: $P(w|c)$, menunjukkan probabilitas bahwa kata `w` adalah teks yang dimaksud pada kandidat `c`. Contohnya `P('kcing'|'kacing') = 0.1` lebih rendah dari `P('kcing'|'kucing') = 0.4`. ## Candidate Model: Sbuah konsep baru: penyuntingan sederhana pada sebuah kata dapat berupa * penghapusan (menghilangkan satu huruf) * transposisi (menukar dua huruf yang bersebelahan), * substitusi (mengubah satu huruf menjadi huruf lain), atau * penyisipan (menambahkan satu huruf). Fungsi Fungsi `edits1(word)` adalah jantung dari algoritma koreksi ejaan Peter Norvig. Fungsinya adalah untuk menghasilkan **semua kemungkinan string** yang dapat dibuat dari kata input `word` dengan melakukan **tepat satu operasi edit**. Operasi edit yang dimaksud adalah empat jenis kesalahan pengetikan paling umum: 1. **Penghapusan (Deletion):** Menghapus satu huruf. * **Contoh `'cat'`:** * Dari `('', 'cat')` -> `'' + 'at'` = `'at'` * Dari `('c', 'at')` -> `'c' + 't'` = `'ct'` * Dari `('ca', 't')` -> `'ca' + ''` = `'ca'` * Dari `('cat', '')` -> dilewati karena `R` kosong. * **Hasil:** `['at', 'ct', 'ca']` 2. **Transposisi (Transposition):** Menukar posisi dua huruf yang bersebelahan. **Contoh `'cat'`:** * `('', 'cat')`: `R='cat'`, panjang>1 -> `'' + 'a' + 'c' + 't'` = `'act'` * `('c', 'at')`: `R='at'`, panjang>1 -> `'c' + 't' + 'a' + ''` = `'cta'` * `('ca', 't')`: dilewati karena `len(R)=1`. * `('cat', '')`: dilewati. * **Hasil:** `['act', 'cta']` 3. **Penggantian (Replacement):** Mengganti satu huruf dengan huruf lain. * **Contoh `'cat'` (hanya menunjukkan beberapa hasil):** * Dari `('', 'cat')`: Ganti `'c'` dengan setiap huruf: `'aat'`, `'bat'`, `'cat'`, `'dat'`, ..., `'zat'`. * Dari `('c', 'at')`: Ganti `'a'` dengan setiap huruf: `'cbt'`, `'cct'`, `'cdt'`, ..., `'czt'`. * Dari `('ca', 't')`: Ganti `'t'` dengan setiap huruf: `'caa'`, `'cab'`, `'cac'`, ..., `'caz'`. * **Hasil:** Daftar yang sangat panjang (26 * jumlah huruf dalam kata). 4. **Penyisipan (Insertion):** Menambahkan satu huruf di suatu posisi. * **Contoh `'cat'`:** * Dari `('', 'cat')`: Sisipkan setiap huruf di awal: `'acat'`, `'bcat'`, `'ccat'`, ..., `'zcat'`. * Dari `('c', 'at')`: Sisipkan setiap huruf setelah `'c'`: `'caat'`, `'cbat'`, `'ccat'`, ..., `'czat'`. * Dari `('ca', 't')`: Sisipkan setiap huruf setelah `'ca'`: `'caat'`, `'cabt'`, `'cact'`, ..., `'cazt'`. * Dari `('cat', '')`: Sisipkan setiap huruf di akhir: `'cata'`, `'catb'`, `'catc'`, ..., `'catz'`. * **Hasil:** Daftar yang sangat panjang (26 * (panjang kata + 1)). ## Contoh: Misal kita memiliki sebuah korpus teks pelatihan yang sangat kecil, hanya terdiri dari satu kalimat: > **"the cat and the dog"** --- ### **Langkah 1: Membangun Kamus Frekuensi (WORDS)** Kita akan menghitung berapa kali setiap kata muncul dalam korpus ini. 1. **Tokenisasi dan Normalisasi:** * Ubah semua huruf menjadi kecil: `"the cat and the dog"` * Pisahkan menjadi kata-kata individual: `['the', 'cat', 'and', 'the', 'dog']` 2. **Hitung Frekuensi:** * `'the'` muncul **2** kali. * `'cat'` muncul **1** kali. * `'and'` muncul **1** kali. * `'dog'` muncul **1** kali. Jadi, kamus frekuensinya adalah: ```python WORDS = { 'the': 2, 'cat': 1, 'and': 1, 'dog': 1 } ``` 3. **Hitung Total Kata (N):** * Total jumlah kata dalam korpus adalah: `2 + 1 + 1 + 1 = 5`. * Jadi, `N = 5`. --- ### **Langkah 2: Menghitung Probabilitas P(c) untuk Setiap Kata** Sekarang, kita bisa menghitung probabilitas setiap kata `c` dengan rumus: **`P(c) = Frekuensi(c) / N`** * **`P('the')`** = `2 / 5` = **0.4** * Artinya, ada 40% kemungkinan kata acak yang diambil dari korpus ini adalah "the". * **`P('cat')`** = `1 / 5` = **0.2** * **`P('and')`** = `1 / 5` = **0.2** * **`P('dog')`** = `1 / 5` = **0.2** --- ### **Langkah 3: Aplikasi dalam Koreksi Ejaan (Contoh Manual)** Misalnya, pengguna mengetik kata yang salah: **`'dgo'`**. Sistem koreksi ejaan akan menghasilkan beberapa kandidat kata yang mungkin, misalnya: * `'dog'` (dengan mengganti posisi 'g' dan 'o') * `'do'` (dengan menghapus 'g') * `'ago'` (dengan mengganti 'd' menjadi 'a') Namun, dalam kamus frekuensi kita (`WORDS`), hanya kata `'dog'` yang ada. Kata `'do'` dan `'ago'` **tidak ada** dalam kamus, sehingga frekuensinya dianggap 0, dan `P('do') = 0`, `P('ago') = 0`. Sistem kemudian akan memilih kandidat dengan probabilitas tertinggi: * `P('dog') = 0.2` * `P('do') = 0.0` * `P('ago') = 0.0` **Kesimpulan:** Kata `'dgo'` akan dikoreksi menjadi **`'dog'`** karena `'dog'` adalah satu-satunya kandidat yang valid dan memiliki probabilitas tertinggi (0.2) berdasarkan model bahasa kita. ---