NLP Basics Sinhala | Text Preprocessing, Tokenization, Stemming, Lemmatization, POS Tagging Explained

NLP Basics Sinhala | Text Preprocessing, Tokenization, Stemming, Lemmatization, POS Tagging Explained

Unlocking the Power of Language: Natural Language Processing Basics Sinhala Guide

ආයුබෝවන්, ටෙක් ලෝකය එක්ක එකතු වෙලා ඉන්න හැමෝටම!

ඉතින් කොහොමද යාලුවනේ? මේ දවස්වල හැමතැනම කතා වෙන Artificial Intelligence (AI), විශේෂයෙන්ම Large Language Models (LLMs) ගැන ඔයාලා අහල ඇතිනේ. ChatGPT, Bard වගේ ඒවා කොහොමද අපි කතා කරන භාෂාව තේරුම් අරගෙන, හරියට මනුස්සයෙක් වගේ උත්තර දෙන්නේ කියන එක හරිම පුදුම සහගතයි නේද? මේ හැමදේකම පිටිපස්සේ තියෙන මූලිකම තාක්ෂණික ශිල්පක්‍රමය තමයි Natural Language Processing (NLP) කියන්නේ.

ඔව්, ඔව්, NLP කියන්නේ AI වල ගොඩක් වැදගත් අංගයක්. සරලවම කිව්වොත්, NLP කියන්නේ පරිගණක වලට අපි කතා කරන, ලියන මනුස්ස භාෂාව (human language) තේරුම් ගන්න, විශ්ලේෂණය කරන්න, හා ප්‍රතිචාර දක්වන්න පුළුවන් විදියට පුහුණු කරන එක. ඔයාට Chatbot එකක් හදන්න ඕන වුණත්, Sentiment Analysis කරන්න වුණත්, නැත්නම් Machine Translation සිස්ටම් එකක් හදන්න වුණත්, මේ NLP මූලික කරුණු දැනගෙන ඉන්න එක අත්‍යවශ්‍යයි.

අද අපි මේ NLP ලෝකයේ මූලිකම පියවර කිහිපයක් ගැන කතා කරමු. මේවා තමයි ඕනෑම NLP project එකක මුලික පදනම. අපි මේ guide එකෙන් Text Preprocessing, Tokenization, Stemming, Lemmatization, සහ Part-of-Speech (POS) Tagging ගැන ඉතාම සරලව, උදාහරණ එක්ක බලමු. Python භාෂාවෙන් සරල කෝඩ් (code) උදාහරණත් දෙන්නම්, ඒ නිසා ඔයාලට මේ concepts තව දුරටත් තේරුම් ගන්න ලේසි වෙයි.

අපි පටන් ගමු එහෙනම්!

1. Text Preprocessing – භාෂාව සකස් කරගනිමු!

අපි හිතමු ඔයාට customer reviews ගොඩක් තියෙනවා කියලා. මේවා පරිගණකයකට තේරුම් ගන්න දෙනකොට ඒවා raw විදියටම දෙන්න බෑ. මොකද, capital letters, punctuation marks, numbers, special characters වගේ දේවල් නිසා පරිගණකයට noise එකක් ඇතිවෙන්න පුළුවන්. Text Preprocessing කියන්නේ මේ raw text එක clean කරලා, NLP ඇල්ගොරිතම වලට වැඩ කරන්න පුළුවන් තත්වෙට ගේන එක.

මේක හරියට කෑමක් උයන්න කලින් එළවලු හෝදලා, කපලා ලෑස්ති කරනවා වගේ වැඩක්. අපි බලමු මේ preprocessing වලදි කරන ප්‍රධාන දේවල් මොනවද කියලා:

අ. Lowercasing

සාමාන්‍යයෙන් "Apple" සහ "apple" කියන්නේ එකම වචනය වුණත්, පරිගණකයකට මේවා වෙනස් වචන දෙකක් විදියට පෙනෙන්න පුළුවන්. ඒ නිසා, text එකේ තියෙන හැම අකුරක්ම lowercase වලට හරවන එක තමයි මුලින්ම කරන්නේ. මේකෙන් consistency එකක් ඇති වෙනවා.

ආ. Removing Punctuation and Numbers

කොමාව (,), තිත (.), ප්‍රශ්නාර්ථ ලකුණ (?), ඉලක්කම් (1, 2, 3) වගේ දේවල් ගොඩක් වෙලාවට අපේ analysis එකට වැදගත් වෙන්නේ නෑ. ඒවා ඉවත් කිරීමෙන් text එක තවත් clean වෙනවා.

ඇ. Removing Special Characters

@, #, $, % වගේ special characters (විශේෂ අකුරු)ත් ගොඩක් වෙලාවට noise එකක් විදියට ක්‍රියා කරනවා. ඒවත් ඉවත් කරන එක හොඳයි.

ඈ. Removing Stop Words

"the", "a", "is", "are", "and" වගේ වචන (stop words) භාෂාවේ බහුලව පාවිච්චි වෙනවා වුණත්, ඒවා තනි තනිව ගත්තාම එච්චර ලොකු අර්ථයක් දෙන්නේ නෑ. Sentiment analysis වගේ tasks වලදි මේවා ඉවත් කරන එකෙන් computational cost එක අඩු කරගන්න පුළුවන් වගේම, වඩාත් වැදගත් වචන වලට අවධානය යොමු කරන්නත් පුළුවන්.

අපි මේක Python කෝඩ් එකකින් බලමු:


import re
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize

# NLTK data download (run this once)
# import nltk
# nltk.download('punkt')
# nltk.download('stopwords')

text = "Hello World! This is a great example of NLP preprocessing. I bought 2 apples and an orange."

print(f"Original text: {text}")

# 1. Lowercasing
text = text.lower()
print(f"After lowercasing: {text}")

# 2. Removing Punctuation and Numbers
# Remove numbers
text = re.sub(r'\d+', '', text)
print(f"After removing numbers: {text}")

# Remove punctuation
text = re.sub(r'[^\w\s]', '', text)
print(f"After removing punctuation: {text}")

# 3. Removing Stop Words
# First, tokenize the text to get individual words
tokens = word_tokenize(text)

# Get English stop words
stop_words = set(stopwords.words('english'))

# Filter out stop words
filtered_tokens = [word for word in tokens if word not in stop_words]

# Join tokens back to form a clean string
cleaned_text = " ".join(filtered_tokens)
print(f"After removing stop words: {cleaned_text}")

මේ code එක රන් කරන්න කලින්, ඔයාලට nltk library එක install කරලා, ඒකට අවශ්‍ය punkt සහ stopwords data download කරගන්න සිද්ධ වෙනවා. ඒක එක පාරක් කළාම ඇති (උඩ කෝඩ් එකේ comment කරලා තියෙන nltk.download() lines දෙක uncomment කරලා run කරන්න).

2. Tokenization – වචන වලට කඩමු!

Text Preprocessing කරලා අපේ text එක clean කරගත්තට පස්සේ ඊළඟට කරන්න ඕන වැදගත් දේ තමයි Tokenization. Tokenization කියන්නේ text එක කුඩාම අර්ථවත් කොටස් වලට (tokens) වෙන් කරන එක. මේ tokens කියන්නේ වචන (words), punctuation marks (ඒවා ඉවත් නොකරනවා නම්), ඉලක්කම් වගේ දේවල් වෙන්න පුළුවන්. Tokenization නැතුව අපිට NLP algorithms වලින් වැඩ කරන්න බෑ.

සරලවම කියනවා නම්, "I love NLP" කියන වාක්‍යය "I", "love", "NLP" කියලා වචන තුනකට කඩන එක තමයි word tokenization කියන්නේ. ඒ වගේම, sentence tokenization කියලා එකකුත් තියෙනවා, ඒකෙන් කරන්නේ paragraph එකක් sentences වලට වෙන් කරන එක.

මේකෙන් වෙන්නේ, අපි text එකේ තියෙන වචන හෝ වාක්‍ය තනි තනිව analysis කරන්න පුළුවන් විදියට සකස් කරගන්න එක. NLP tasks ගොඩක් වෙලාවට ආරම්භ වෙන්නේ tokenization වලින්.

අපි මේකත් Python NLTK (Natural Language Toolkit) library එක පාවිච්චි කරලා කොහොමද කරන්නේ කියලා බලමු:


from nltk.tokenize import word_tokenize, sent_tokenize

text_for_tokenization = "Natural Language Processing is fascinating! It helps computers understand human language. This is a great field."

# 1. Word Tokenization
words = word_tokenize(text_for_tokenization)
print(f"Word Tokens: {words}")

# 2. Sentence Tokenization
sentences = sent_tokenize(text_for_tokenization)
print(f"Sentence Tokens: {sentences}")

උඩ කෝඩ් එකෙන් අපිට පැහැදිලිව පේනවා, word_tokenize එකෙන් වචන වලට වෙන් කරන හැටි, sent_tokenize එකෙන් වාක්‍ය වලට වෙන් කරන හැටි. NLTK කියන්නේ NLP වලට තියෙන මාර powerful library එකක්!

3. Stemming vs. Lemmatization – වචන මුලට යමු!

Text Preprocessing සහ Tokenization කරාට පස්සේ, ඊළඟට අපි කරන තවත් වැදගත් step එකක් තමයි word normalization. මේකෙන් කරන්නේ එකම වචනයේ විවිධ forms (උදා: "run", "running", "ran") එකම base form එකකට ගේන එක. මේකට ප්‍රධාන ක්‍රම දෙකක් තියෙනවා: Stemming සහ Lemmatization.

මේක වැදගත් වෙන්නේ, "කෑම", "කනවා", "කෑවා" වගේ වචන වලින් ලැබෙන්නේ එකම මූලික අදහසක් නිසා, පරිගණකයකට මේ හැම එකක්ම වෙන වෙනම වචන විදියට නොදැක, එකම "කෑම" කියන concept එකට අයිති වෙන විදියට හඳුන්වා දෙන එක.

3.1. Stemming – වචන වල කඳ සොයමු

Stemming කියන්නේ වචනයක අවසානයේ තියෙන suffixes (ප්‍රත්‍යය) කපා දාලා, වචනයේ "කඳ" (stem) එක හොයාගන්න එක. මේක සාමාන්‍යයෙන් rule-based විදියට තමයි කරන්නේ. උදාහරණයක් විදියට, "running", "runner" කියන වචන දෙකෙන්ම "run" කියන stem එක ගන්න පුළුවන්.

Stemming වල වාසිය තමයි ඒක ගොඩක් වේගවත්. ඒත් අවාසිය තමයි, සමහර වෙලාවට මේ stem එක කියන්නේ නියම dictionary word එකක් නෙමෙයි වෙන්න පුළුවන්. ඒ කියන්නේ "beautiful" කියන එක "beauti" වගේ stem එකකට අඩු වෙන්න පුළුවන්. ඒක grammatically වැරදියි.

NLTK වල PorterStemmer එක ගොඩක් ජනප්‍රියයි:


from nltk.stem import PorterStemmer

ps = PorterStemmer()

words_for_stemming = ["program", "programs", "programmer", "programming", "programmed"]

print("Stemming Examples:")
for w in words_for_stemming:
    print(f"{w} : {ps.stem(w)}")

මේ output එක බැලුවොත්, "programmer" කියන එක "programm" වුණත්, "programming" කියන එක "program" වෙනවා. මේක perfect නෑ, ඒත් ගොඩක් වෙලාවට හොඳට වැඩ කරනවා.

3.2. Lemmatization – වචන වල නියම මූලික රූපය

Lemmatization කියන්නේ stemming වලට වඩා ටිකක් advanced process එකක්. මේකෙන් කරන්නේ වචනයක් ඒකේ base හෝ dictionary form එකට (lemma) ගේන එක. Lemmatization වලදි vocabulary එකක් සහ morphological analysis (වචන වල ව්‍යුහය විශ්ලේෂණය) භාවිතා කරනවා. ඒ නිසා හැම වෙලාවෙම අපිට ලැබෙන්නේ නියම dictionary word එකක්.

උදාහරණයක් විදියට, "better" කියන වචනයේ lemma එක "good". "ran" කියන එකේ lemma එක "run". Stemming වලදි වගේ අහඹු විදියට අකුරු කපා දාන්නේ නෑ.

මේක stemming වලට වඩා accurate වුණත්, computationally ටිකක් බරයි, ඒ කියන්නේ ටිකක් වෙලා යනවා. ඒත් වඩා හොඳ results ඕන නම් lemmatization තමයි තෝරාගන්න ඕන.

NLTK වල WordNetLemmatizer එක භාවිතා කරන හැටි බලමු:


from nltk.stem import WordNetLemmatizer
from nltk.corpus import wordnet

# NLTK data download (run this once)
# import nltk
# nltk.download('wordnet')
# nltk.download('omw-1.4') # Open Multilingual Wordnet

lemmatizer = WordNetLemmatizer()

words_for_lemmatization = ["cats", "cacti", "geese", "rocks", "better", "ran", "running"]

print("\nLemmatization Examples:")
for w in words_for_lemmatization:
    # We can specify the part-of-speech (e.g., noun, verb) for better accuracy
    # If not specified, it defaults to noun.
    print(f"{w} : {lemmatizer.lemmatize(w, pos=wordnet.VERB)}") # trying with verb first
    print(f"{w} : {lemmatizer.lemmatize(w)}") # default (noun)

මේ code එක රන් කරන්න කලින් wordnet සහ omw-1.4 data download කරගන්න අමතක කරන්න එපා. WordNetLemmatizer එකට Part-of-Speech (POS) එක දෙන්න පුළුවන් නම් accuracy එක තවත් වැඩි වෙනවා. උදාහරණයක් විදියට "running" කියන එක verb එකක් විදියට lemmatize කරොත් "run" කියලා එනවා. noun විදියට කරොත් "running" කියලාම එන්න පුළුවන්.

Stemming vs. Lemmatization: කවදා මොකක්ද පාවිච්චි කරන්නේ?

  • Stemming: වේගය (speed) වැදගත් වන, විශාල datasets සඳහා සහ precision එක එතරම්ම වැදගත් නොවන tasks (උදා: Information Retrieval) සඳහා සුදුසුයි.
  • Lemmatization: accuracy එක සහ වචන වල නියම අර්ථය තේරුම් ගැනීම වැදගත් වන tasks (උදා: Question Answering, Chatbots) සඳහා සුදුසුයි.

4. Part-of-Speech (POS) Tagging – වචන වල භූමිකාව හඳුනාගනිමු!

අපේ text එක clean කරලා, tokens වලට කඩලා, base forms වලටත් ගෙනාවට පස්සේ ඊළඟට කරන්න පුළුවන් තවත් වැදගත් දෙයක් තමයි Part-of-Speech (POS) Tagging. මේකෙන් කරන්නේ tokenized text එකේ තියෙන හැම වචනයකටම ඒකේ ව්‍යාකරණමය භූමිකාව (grammatical category) අදාළ tag එකක් විදියට එකතු කරන එක.

සරලවම කිව්වොත්, noun, verb, adjective, adverb වගේ parts of speech වලට වචන වර්ග කරන එක. POS tagging එකෙන් අපිට sentence එකක ව්‍යුහය සහ වචන වල සම්බන්ධතා තේරුම් ගන්න පුළුවන්. මේක Named Entity Recognition (NER), Sentiment Analysis, Machine Translation වගේ advanced NLP tasks වලට ගොඩක් වැදගත්.

නිකන් හිතන්නකෝ, "Can" කියන වචනය verb එකක්ද (ability) නැත්නම් noun එකක්ද (metal container) කියලා POS tagger එකට හොයාගන්න පුළුවන් නම්, context එක තේරුම් ගැනීම කොච්චර ලේසිද?

NLTK වල pos_tag function එක පාවිච්චි කරලා මේක කොහොමද කරන්නේ කියලා බලමු:


from nltk.tag import pos_tag
from nltk.tokenize import word_tokenize

# NLTK data download (run this once)
# import nltk
# nltk.download('averaged_perceptron_tagger')

text_for_pos = "The quick brown fox jumps over the lazy dog."
tokens_for_pos = word_tokenize(text_for_pos)

# Perform POS tagging
pos_tags = pos_tag(tokens_for_pos)

print(f"POS Tags: {pos_tags}")

# Let's try another example to see context
text_for_pos_2 = "I can swim and I have a can of soda."
tokens_for_pos_2 = word_tokenize(text_for_pos_2)
pos_tags_2 = pos_tag(tokens_for_pos_2)

print(f"\nPOS Tags for context example: {pos_tags_2}")

මේ කෝඩ් එක රන් කරන්න කලින් averaged_perceptron_tagger කියන NLTK data එක download කරගන්න අමතක කරන්න එපා. Output එක බැලුවොත්, ('The', 'DT'), ('quick', 'JJ'), ('brown', 'JJ') වගේ tuples එනවා. DT කියන්නේ determiner, JJ කියන්නේ adjective. NLTK වල tagset එක බලලා මේ tags වල තේරුම තේරුම් ගන්න පුළුවන්. දෙවැනි උදාහරණයෙන් "can" කියන වචනය context එක අනුව MD (modal verb) සහ NN (noun) විදියට වෙන් කරන හැටි හොඳට පේනවා.

නිගමනය (Conclusion)

ඉතින් යාලුවනේ, අද අපි Natural Language Processing (NLP) වලට අත්‍යවශ්‍ය මූලික පියවර කිහිපයක් ගැන කතා කළා. Text Preprocessing වලින් අපේ raw text එක clean කරගන්න හැටිත්, Tokenization වලින් වචන වලට කඩාගන්න හැටිත්, Stemming සහ Lemmatization වලින් වචන ඒවායේ මූලික ස්වරූපයට ගේන හැටිත්, අන්තිමට POS Tagging වලින් වචන වල ව්‍යාකරණමය භූමිකාව හඳුනාගන්න හැටිත් අපි ඉගෙන ගත්තා.

මේ හැම step එකක්ම ඕනෑම NLP project එකක සාර්ථකත්වයට ගොඩක් වැදගත්. මේවා හොඳට තේරුම් ගැනීමෙන්, ඔයාලට AI සහ LLM වගේ advanced areas වලට යන්න හොඳ පදනමක් ලැබෙනවා.

මේ concepts තවත් ගැඹුරින් අධ්‍යයනය කරන්න. NLTK library එකේ තියෙන අනෙකුත් features ගැනත් හොයලා බලන්න. මේක ඔයාලගේ ඊළඟ NLP project එකට implement කරලා බලන්න!

මේ ගැන ඔයාලගේ අදහස්, ප්‍රශ්න, හෝ අත්දැකීම් පහළින් comment කරන්න අමතක කරන්න එපා! අපි ඊළඟ tutorial එකෙන් නැවත හමු වෙමු! ඔබට සුභ දවසක්!