Natural Language Processing and Text Mining (NLPTM)
Bagian dari Combined Module: Unstructured Data Analysis (UDA)
Prasyarat:
- NLPTM-01
Code Lesson NLPTM-02
Code dari lesson ini dapat di akses di Link berikut (wajib login ke Google/Gmail): Code NLPTM-02
Di link tersebut anda langsung bisa merubah code dan menjalankannya. Keterangan lebih lanjut di Video NLPTM-02
Sangat disarankan untuk membuka code dan video berdampingan/"side-by-side" untuk mendapatkan pengalaman belajar yang baik. Silahkan modifikasi (coba-coba) hal lain, selain yang ditunjukkan di video untuk mendapatkan pengalaman belajar yang lebih mendalam. Tentu saja juga silahkan akses berbagai referensi lain untuk memperkaya pengetahuan lalu diskusikan di forum yang telah disediakan.
Video Lesson NLPTM-02
Natural Language Processing and Text Mining (NLPTM)
Unstructured Data Analysis (UDA)*
Unstructured Data Analysis (UDA)*
02 - Dasar-Dasar Natural Language Processing (NLP)- Bagian ke-01 ¶
(C) Taufik Sutanto - 2020
tau-data Indonesia ~ https://tau-data.id
tau-data Indonesia ~ https://tau-data.id
Outline Module NLPTM-02/UDA-02:¶
- Tokenisasi
- Stemming dan Lemma
import warnings; warnings.simplefilter('ignore')
import nltk
try:
import google.colab
IN_COLAB = True
!wget https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/taudataDDGsna.py
!mkdir data
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/contoh.pdf
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/slang.txt
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/stopwords_id.txt
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/stopwords_en.txt
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/kata_dasar.txt
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/wn-ind-def.tab
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/wn-msa-all.tab
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/ind_SA.csv
!wget -P data/ https://raw.githubusercontent.com/taudata-indonesia/eLearning/master/data/all_indo_man_tag_corpus_model.crf.tagger
!pip install --upgrade spacy python-crfsuite unidecode textblob sastrawi sklearn-pycrfsuite
!pip install --upgrade unidecode twython tweepy beautifulsoup4 tika
!python -m spacy download en
!python -m spacy download xx
!python -m spacy download en_core_web_sm
nltk.download('popular')
except:
IN_COLAB = False
print("Running the code locally, please make sure all the python module versions agree with colab environment and all data/assets downloaded")
Tokenisasi¶
Tokenisasi adalah pemisahan kata, simbol, frase, dan entitas penting lainnya (yang disebut sebagai token) dari sebuah teks untuk kemudian di analisa lebih lanjut. Token dalam NLP sering dimaknai dengan "sebuah kata", walau tokenisasi juga bisa dilakukan ke kalimat, paragraf, atau entitas penting lainnya (misal suatu pola string DNA di Bioinformatika).
Mengapa perlu tokenisasi?
- Langkah penting dalam preprocessing, menghindari kompleksitas mengolah langsung pada string asal.
- Menghindari masalah (semantic) saat pemrosesan model-model natural language.
- Suatu tahapan sistematis dalam merubah unstructured (text) data ke bentuk terstruktur yang lebih mudah di olah.
[Image Source]: https://www.softwareadvice.com/resources/what-is-text-analytics/
Tokenisasi dengan modul NLTK
Kelebihan:
- Well established dengan dukungan bahasa yang beragam
- Salah satu modul NLP dengan fungsi terlengkap, termasuk WordNet
- Free dan mendapat banyak dukungan akademis.
Kekurangan:
- "Tidak support" bahasa Indonesia
- Murni Python: relatif lebih lambat
import nltk
T = "Hello, Mr. Man. He smiled!! This, i.e. that, is it."
Word_Tokens = nltk.word_tokenize(T)
print(Word_Tokens) # tokenisasi kata
['Hello', ',', 'Mr.', 'Man', '.', 'He', 'smiled', '!', '!', 'This', ',', 'i.e', '.', 'that', ',', 'is', 'it', '.']
# Bandingkan jika menggunakan fungsi split di Python, apakah bedanya?
print(T.split())
# Apakah kesimpulan yang bisa kita tarik?
# Split() ==> Bukan Tokenisasi!.
['Hello,', 'Mr.', 'Man.', 'He', 'smiled!!', 'This,', 'i.e.', 'that,', 'is', 'it.']
Sentence_Tokens = nltk.sent_tokenize(T)
print(Sentence_Tokens) # Tokenisasi kalimat
# Perhatikan hasilnya, ada berapa kalimat yang di deteksi? setuju?
['Hello, Mr. Man.', 'He smiled!!', 'This, i.e.', 'that, is it.']
Trigger Diskusi Forum:</h3>¶
- Apakah tanda baca seperti "?" atau "!" akan memisahkan kalimat?
- Apakah tanda "carriage return"/enter/ganti baris memisahkan kalimat?
- Apakah ";" memisahkan kalimat?
- Apakah tanda dash "-" memisahkan kata? Dalam bahasa Indonesia/Inggris?
Tips: Perhatikan bentuk struktur data "output" dari tokenisasi NLTK.
Catatan: pindah baris di Python string bisa dilakukan dengan menggunakan symbol "\n"
Contoh:
Tokenisasi dengan modul Spacy¶
Kelebihan:</p>
- Di claim lebih cepat (C-based)
- License termasuk untuk komersil
- Dukungan bahasa yang lebih banyak dari NLTK (termasuk bahasa Indonesia*)
Kekurangan:
- Fungsi yang lebih terbatas (dibandingkan NLTK).
- Karena berbasis compiler, sehingga instalasi cukup menantang.
# Contoh tokenisasi menggunakan Spacy
from spacy.lang.en import English
nlp_en = English()
T = "Hello, Mr. Man. He smiled!! This, i.e. that, is it."
nlp = nlp_en(T)
for token in nlp:
print(token.text, end =', ')
Hello, ,, Mr., Man, ., He, smiled, !, !, This, ,, i.e., that, ,, is, it, .,
nlp_en.add_pipe(nlp_en.create_pipe('sentencizer')) # New in latest Spacy
nlp = nlp_en(T)
for kalimat in nlp.sents:
print(kalimat)
Hello, Mr. Man. He smiled!! This, i.e. that, is it.
# Hati-hati! ... token bukan string di Spacy, karena C-based, ia bekerja di byte bukan unicode.
token = nlp[0]
print(token)
type(token)
#token=='Hello'
Hello
spacy.tokens.token.Token
Trigger Diskusi Forum:</h3>¶
- Apakah hasil tokenisasi Spacy = NLTK? Mengapa?
- Lakukan latihan seperti yang dilakukan sebelumnya dengan modul NLTK, apakah hasilnya sama dengan Spacy?
Catatan: Contoh sederhana ini menekankan perbedaan ilmu linguistik dan computational linguistic.</p>
Tokenisasi dengan TextBlob¶
Kelebihan:</p>
- Sederhana & mudah untuk digunakan/pelajari.
- Textblob objects punya behaviour/properties yang sama dengan string di Python.
- TextBlob dibangun dari kombinasi modul NLTK dan (Clips) Pattern
Kekurangan:
- Tidak secepat Spacy dan NLTK
- Language Model terbatas: English, German, French
*Blob : Binary large Object
# Tokenizing di TextBlob
from textblob import TextBlob
T = "Hello, Mr. Man. He smiled!! This, i.e. that, is it."
print(TextBlob(T).words)
['Hello', 'Mr', 'Man', 'He', 'smiled', 'This', 'i.e', 'that', 'is', 'it']
kalimatS = TextBlob(T).sentences
print([str(kalimat) for kalimat in kalimatS])
['Hello, Mr. Man.', 'He smiled!!', 'This, i.e.', 'that, is it.']
Trigger Diskusi Forum:</h3>¶
- Ada yang berbeda dari hasilnya? Apakah lebih baik seperti ini?
Tips: TextBlob biasa digunakan untuk prototyping pada data yang tidak terlalu besar.
Catatan: Hati-hati tipe data Blob tidak biasa (objek).
# Saat melakukan coding di Python, selalu perhatikan "tipe data" yang dihasilkan oleh modul.
A = TextBlob(T).sentences
B = TextBlob(T).words
print(A[0], type(A[0]))
print(B[0], type(B[0]))
# Apakah bedanya dengan tipe data str biasa di python?
Hello, Mr. Man. <class 'textblob.blob.Sentence'> Hello <class 'textblob.blob.Word'>
# Di Spacy ini tidak berlaku
B[0]=='Hello'
True
# "properties" Blob word
print(dir(C))
['LancasterStemmer', 'PorterStemmer', 'SnowballStemmer', '__add__', '__class__', '__contains__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__module__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'capitalize', 'casefold', 'center', 'correct', 'count', 'define', 'definitions', 'detect_language', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'get_synsets', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'lemma', 'lemmatize', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'pluralize', 'pos_tag', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'singularize', 'spellcheck', 'split', 'splitlines', 'startswith', 'stem', 'string', 'strip', 'swapcase', 'synsets', 'title', 'translate', 'translator', 'upper', 'zfill']
# "properties" string di Python
print(dir(D))
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
Tokenisasi tidak hanya language dependent, tapi juga environment dependent¶
Tokenization sebenarnya tidak sesederhana memisahkan berdasarkan spasi dan removing symbol. Sebagai contoh dalam bahasa Jepang/Cina/Arab suatu kata bisa terdiri dari beberapa karakter.
# Contoh Tokenizer untuk twitter
from nltk.tokenize import TweetTokenizer
Tokenizer = TweetTokenizer(strip_handles=True, reduce_len=True)
tweet = "@Kirana_Sutanto I am so happpppppppy"
print(Tokenizer.tokenize(tweet))
# Masih salah (i.e. "happpy"), nanti kita akan perbaiki ini dengan "spell check"
# catatan: pada permasalahan "Sentiment analysis" kata yang ditulis panjang seperti diatas
# bisa mengindikasikan sentiment yang kuat
['I', 'am', 'so', 'happpy']
Tokenisasi (NLP) Bahasa Indonesia:¶
NLTK belum support Bahasa Indonesia, bahkan module NLP Python yang support bahasa Indonesia secara umum masih sangat langka. Beberapa resources yang dapat digunakan:
- KirraLabs: Mix of NLP-TextMining resources
- Sastrawi 1.0.1: untuk "stemming" & stopwords bahasa Indonesia.
- Daftar Kata Dasar Indonesia: Bisa di load sebagai dictionary di Python
- Wiktionary: ProyekWiki bahasa Indonesia [termasuk Lexicon]
- WordNet Bahasa Indonesia: Bisa di load sebagai dictionary (atau NLTK*) di Python.
- Daftar Kata Baku-Tidak Baku: Bisa di load sebagai dictionary di Python.
- Spacy: Cepat/efisien, MIT License, tapi language model Indonesia masih terbatas.
- UdPipe: Online request & restricted license (support berbagai bahasa - pemrograman).
# Contoh Tokenisasi dalam bahasa Indonesia dengan Spacy
from spacy.lang.id import Indonesian
nlp_id = Indonesian() # Language Model
teks = 'Sore itu, Hamzah melihat kupu-kupu di taman. Ibu membeli oleh-oleh di pasar'
tokenS_id = nlp_id(teks)
#T = []
#for token in tokenS_id:
# T.append(token)
print([t for t in tokenS_id])
[Sore, itu, ,, Hamzah, melihat, kupu-kupu, di, taman, ., Ibu, membeli, oleh-oleh, di, pasar]
# Jika menggunakan Language model English:
tokenS_en = nlp_en(teks)
print([token.text for token in tokenS_en])
['Sore', 'itu', ',', 'Hamzah', 'melihat', 'kupu', '-', 'kupu', 'di', 'taman', '.', 'Ibu', 'membeli', 'oleh', '-', 'oleh', 'di', 'pasar']
Word Case (Huruf BESAR/kecil):
- Untuk menganalisa makna (semantic) dari suatu (frase) kata dan mencari informasi dalam proses textmining, seringnya (*) kita tidak membutuhkan informasi huruf besar/kecil dari kata tersebut.
- Text case normaliation dapat dilakukan pada string secara efisien tanpa melalui tokenisasi (mengapa?).
- Namun, bergantung pada analisa teks yang akan digunakan pengguna harus berhati-hati dengan urutan proses (pipelining) dalam preprocessing. Mengapa dan apa contohnya?
(*) Coba temukan minimal 2 pengecualian dimana huruf kapital/kecil (case) mempengaruhi makna/pemrosesan teks.
# Ignore case (huruf besar/kecil)
T = "Hi there!, I am a student. Nice to meet you :)"
print(T.lower())
print(T.upper())
# Perintah ini sangat efisien karena hanya merubah satu bit di setiap (awal) bytes dari setiap karakter
# Sehingga tetap efisien jika ingin dilakukan sebelum tokenisasi
hi there!, i am a student. nice to meet you :) HI THERE!, I AM A STUDENT. NICE TO MEET YOU :)
Morphological-Linguistic Normalization: Stemming & Lemmatization¶
(Canonical Representation)
Stemming dan Lemma¶
-
Stemmer akan menghasilkan sebuah bentuk kata yang disepakati oleh suatu sistem tanpa mengindahkan konteks kalimat. Syaratnya beberapa kata dengan makna serupa hanya perlu dipetakan secara konsisten ke sebuah kata baku. Banyak digunakan di IR & komputasinya relatif sedikit. Biasanya dilakukan dengan menghilangkan imbuhan (suffix/prefix).
-
lemmatisation akan menghasilkan kata baku (dictionary word) dan bergantung konteks.
-
Lemma & stemming bisa jadi sama-sama menghasilkan suatu akar kata (root word). Misal : Melompat ==> lompat
Mengapa melakukan Stemming & Lemmatisasi?
- Sering digunakan di IR (Information Retrieval) agar ketika seseorang mencari kata tertentu, maka seluruh kata yang terkait juga diikutsertakan.
Misal: organize, organizes, and organizing dan democracy, democratic, and democratization. - Di Text Mining Stemming dan Lemmatisasi akan mengurangi dimensi (mengurangi variasi morphologi), yang terkadang akan meningkatkan akurasi.
- Tapi di IR efeknya malah berkebalikan: meningkatkan recall, tapi menurunkan akurasi [Link]. Contoh: kata operate, operating, operates, operation, operative, operatives, dan operational jika di stem menjadi operate, maka ketika seseorang mencari "operating system", maka entry seperti operational and research dan operative and dentistry akan muncul sebagai entry dengan relevansi yang cukup tinggi.
Stemming tidak perlu "benar", hanya perlu konsisten. Sehingga memiliki berbagai variansi, (sebagian) contoh di NLTK:
# Contoh Stemming di NLTK
from nltk.stem.lancaster import LancasterStemmer
from nltk.stem.porter import PorterStemmer
from nltk.stem.snowball import SnowballStemmer
T = 'presumably I would like to MultiPly my provision, saying tHat without crYing'
print('Sentence: ',T)
StemmerS = [LancasterStemmer, PorterStemmer, SnowballStemmer]
Names = ['Lancaster', 'Porter', 'SnowBall']
for stemmer_name,stem in zip(Names,StemmerS):
if stemmer_name == 'SnowBall':
st = stem('english')
else:
st = stem()
print(stemmer_name,': ',' '.join(st.stem(t) for t in T.split()))
# perhatikan, kita tidak melakukan case normalization (lowercase)
# Hasil stemming bisa tidak bermakna
Sentence: presumably I would like to MultiPly my provision, saying tHat without crYing Lancaster : presum i would lik to multiply my provision, say that without cry Porter : presum I would like to multipli my provision, say that without cri SnowBall : presum i would like to multipli my provision, say that without cri
# Contoh Lemmatizer di NLTK
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
T = "apples and Oranges are similar. boots and hippos aren't, don't you think?"
print('Sentence: ', T)
print('Lemmatize: ',' '.join(lemmatizer.lemmatize(t) for t in T.split()))
# Lemma case sensitive. Dengan kata lain string harus diubah ke dalam bentuk huruf kecil (lower case)
Sentence: apples and Oranges are similar. boots and hippos aren't, don't you think? Lemmatize: apple and Oranges are similar. boot and hippo aren't, don't you think?
# Lemmatizer menggunakan informasi pos. "pos" (part-of-speech) akan dibahas di segmen berikutnya
print(lemmatizer.lemmatize("better", pos="a")) # adjective
print(lemmatizer.lemmatize("better", pos="v")) # verb
good better
# TextBlob Stemming & Lemmatizer
from textblob import Word
# Stemming
print(Word('running').stem()) # menggunakan NLTK Porter stemmer
# Lemmatizer
print(Word('went').lemmatize('v'))
# default Noun, plural akan menjadi singular dari akar katanya
# Juga case sensitive
run go
# Spacy Lemmatizer English
import spacy
nlp = spacy.load("en_core_web_sm")
E = "I am sure apples and oranges are similar"
doc = nlp(E)
for token in doc:
print(token.text, token.lemma_)
# Perhatikan huruf besar/kecil
I -PRON- am be sure sure apples apple and and oranges orange are be similar similar
# Lemmatizer dengan Sastrawi
from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
stemmer = StemmerFactory().create_stemmer()
I = "perayaan itu Berbarengan dengan saat kita bepergian ke Makassar"
print(stemmer.stem(I))
print(stemmer.stem("Perayaan Bepergian Menyuarakan"))
# Ada beberapa hal yang berbeda antara Sastrawi dan modul-modul diatas.
# Apa sajakah?
raya itu bareng dengan saat kita pergi ke makassar raya pergi suara
Tips:¶
- Secara umum 'biasanya' di Text Mining yang kita butuhkan hanyalah Lemma.
- "Kecuali" di aplikasi IR, spelling correction, variasi kata, clustering, atau terkadang klasifikasi. Pada aplikasi-aplikasi tersebut stemming terkadang lebih diinginkan.
- Stemming jauh lebih cepat, tapi tidak selalu tersedia di modul NLP.
- Beberapa algoritma tertentu membutuhkan tanda "." dan "," : contohnya untuk document summarization di textRank.
- "_" juga biasa digunakan untuk menyatakan frase kata di representasi n-grams (misal "buah_tangan").
- Stemming juga digunakan pada Word Sense Disambiguation (WSD)
Trigger Diskusi Forum:¶
- Untuk menghemat storage database, apakah sebaiknya kita menyimpan saja hasil preprocessed texts/documents?
End of Module NLPTM-02
Referensi lain untuk belajar Text Mining di Python
- Farzindar, A., & Inkpen, D. (2017). Natural language processing for social media. Synthesis Lectures on Human Language Technologies, 10(2), 1-195.
- Kao, A., & Poteet, S. R. (Eds.). (2007). Natural language processing and text mining. Springer Science & Business Media.
- Perkins, J. (2014). Python 3 Text Processing with NLTK 3 Cookbook. Packt Publishing Ltd.
- http://www.nltk.org/book/
Tidak ada komentar:
Posting Komentar
Relevant & Respectful Comments Only.