Word2vec, FastText, Glove
இம்மூன்றும் embedding வேலையை செய்வதற்கான pre-trained மாடல்கள் ஆகும். இதில் Word2vec எனும் pre-trained மாடலை பயன்படுத்தி Embedding செய்வதற்கான எடுத்துக்காட்டு பின்வருமாறு.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import tensorflow as tf | |
from tensorflow.keras.preprocessing.text import Tokenizer | |
from tensorflow.keras.models import Sequential | |
from tensorflow.keras.layers import Embedding, LSTM, Dense, Bidirectional, SimpleRNN | |
from tensorflow.keras.preprocessing.sequence import pad_sequences | |
x = "தமிழ்நாடு இந்தியாவின் தெற்கே அமைந்த ஒரு அழகிய மாநிலமாகும். இது பல்வேறு கலாச்சார பாரம்பரியங்களையும், செழிப்பான சாகுபடிமுறையையும் கொண்டுள்ளது. தமிழ்நாட்டின் தலைநகரமான சென்னை, தொழில்நுட்பம் மற்றும் கல்வியில் முன்னணி வகிக்கிறது. மாமல்லபுரம், தஞ்சாவூர் பெரிய கோயில் போன்ற வரலாற்று முக்கியத்துவம் வாய்ந்த இடங்கள் சுற்றுலாப் பயணிகளை ஈர்க்கின்றன. தமிழ்நாட்டின் கலை, இலக்கியம் மற்றும் இசை உலகளாவிய புகழ் பெற்றவை" | |
tokens = Tokenizer() | |
tokens.fit_on_texts([x]) | |
dictionary = tokens.word_index | |
x_n_grams = [] | |
for line in x.split('.'): | |
line_tokens = tokens.texts_to_sequences([line])[0] | |
for i in range(1, len(line_tokens)): | |
n_grams = line_tokens[:i+1] | |
x_n_grams.append(n_grams) | |
max_line_len = max([len(i) for i in x_n_grams]) | |
training_data = np.array(pad_sequences(x_n_grams, maxlen=max_line_len, padding='pre')) | |
train_X = training_data[:, :-1] | |
train_y = training_data[:, -1] | |
total_words = len(dictionary) + 1 | |
y = np.array(tf.keras.utils.to_categorical(train_y, num_classes=total_words)) | |
model = Sequential() | |
from gensim.models import Word2Vec | |
vec = Word2Vec(sentences=[i.split() for i in x.split('.')], vector_size=100, window=5, min_count=1, workers=1) | |
embeds = np.zeros((total_words, 100)) | |
for word, i in dictionary.items(): | |
if word in vec.wv: | |
embeds[i] = vec.wv[word] | |
model.add(Embedding(total_words, 100, input_length=max_line_len – 1, weights=[embeds], trainable=False)) | |
model.add(LSTM(150)) | |
model.add(Dense(total_words, activation='softmax')) | |
model.build(input_shape=(None, max_line_len-1)) | |
print(model.summary()) | |
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) | |
model.fit(train_X, y, epochs=100, verbose=1) | |
input_text = "தமிழ்நாடு" | |
predict_next_words= 3 | |
for _ in range(predict_next_words): | |
input_token = tokens.texts_to_sequences([input_text])[0] | |
input_x = pad_sequences([input_token], maxlen=max_line_len-1, padding='pre') | |
predicted = np.argmax(model.predict(input_x), axis=-1) # Greedy. tensorflow.random.categorical(input_token,num_samples=1) for sampling for beam search | |
output_word = "" | |
for word, index in tokens.word_index.items(): | |
if index == predicted: | |
output_word = word | |
break | |
input_text += " " + output_word | |
print(input_text) | |
""" | |
Run above code after running below line | |
!pip install –force-reinstall scipy pandas gensim | |
""" |
இந்த மாடலுக்கான சம்மரியில் non-trainable params என்பது ஒரு குறிப்பிட்ட எண்ணிக்கையிலான பெராமீட்டர்களை வெளிப்படுத்துவதைக் காணலாம். இது Word2vec மாடலில் உள்ள frozen லேயருக்கான பெராமீட்டர்கள் ஆகும்.
Word embeddings
முதலில் எம்பெடிங் செய்யப்படுவதன் பின்னணியில் இருக்கும் தத்துவத்தைப் பற்றி புரிந்து கொள்வோம். “யாரு மனசுல யாரு? அவருக்கு என்ன பேரு?” என்று ஒரு நிகழ்ச்சி உள்ளது. அதில் கலந்து கொள்ளும் இருவரில் ஒருவர், ஏதாவதொரு பிரபலமான நபரைப் பற்றி நினைத்துக் கொள்வார். மற்றவர் அதைக் கண்டுபிடிக்க வேண்டும். ஆனால் நினைத்துக் கொண்டுள்ளவருக்கு ஆம்/இல்லை போன்ற பதில்களை மட்டுமே கூற அனுமதி உண்டு. இதை வைத்தே மற்றவர் அதைக் கண்டுபிடிக்க வேண்டும். எனவே கேள்வி கேட்கும் நபர் சாதுர்யமாக “அவர் விளையாட்டுத் துறையைச் சேர்ந்தவரா?” என்பார். “ஆம்!” என பதில் வந்தால் உடனே “கால் பந்து வீரரா?” என்பார். இதற்கும் “ஆம்!” என பதில் வந்தால் “இந்திய நாட்டுக்காரரா?” என்பார். “இல்லை” என பதில் வந்தால் வேறு நாட்டின் பெயரைச் சொல்லிக் கேட்பார். இதேபோல பல்வேறு கேள்விகளை எழுப்பி எழுப்பி இறுதியில் அவர் யார் என்பதைக் கண்டுபிடித்து விடுவார். இவர் கேட்கும் கேள்விகள் அனைத்தும், அவர் மனதில் உள்ளதைக் கண்டுபிடிப்பதற்கான features ஆகும். இதே தத்துவம் தான் Embedding லேயரிலும் பயன்படுகிறது.
நமது vocabulary-யில் உள்ள ஒவ்வொரு வார்த்தையையும் 100 எனும் fixed size கொண்ட வெக்டருக்குள் அர்த்தம் பொதிந்த நிலையில் சேமிப்பதே Embedding என்று பார்த்தோம். ஒரு வார்த்தையின் அர்த்தத்தைப் புரிந்து கொள்ள, மறைமுகமாக கேட்கப்படும் பல்வேறு கேள்விகளே இந்த 100 வகையான features ஆகும். உதாரணத்துக்கு ‘தெற்கே’ எனும் வார்த்தையை சேமிக்க, அது நாடா? உயர்திணையா? திசையா? உணவுப் பொருளா? கால நேரமா? போன்ற நூறு வகையான கேள்விகள் மூலம் அந்த வார்த்தை சேமிக்கப்படுகின்றது. எனவே ஒரே மாதிரியான வார்த்தைகளுக்கு கிட்டத்தட்ட ஒரே மாதிரியான பதில்கள் கிடைப்பதால், அவை ஒரே மாதிரியான வெக்டர்களை உருவாக்குகின்றன.
Euclidean distance என்பது இரண்டு வெக்டர்களுக்கிடையே ஆன தூரத்தைக் கணக்கிட உதவும். எனவே ஒரே மாதிரியான வெக்டர்களுக்கான இடைவெளி குறைவாகவும், எதிர்மறையான வெக்டர்களுக்கான இடைவெளி அதிகமாகவும் இருக்கும். இதை வைத்தே ஒரே மாதிரியான வார்த்தைகள், எதிரெதிரான வார்த்தைகள் போன்றவற்றைக் கணக்கிட்டுக் கூற இயலும். Word2vec, FastText, Glove போன்றவற்றில் இதை செய்து பார்க்கலாம்.
Architectural Difference
Word2vec என்பது கீழ்க்கண்ட இரு கட்டமைப்புகளைக் கொண்டு எம்பெடிங் செய்கிறது.
- CBOW – continuous bag of words
- Skip-grams
“உன் நண்பர்கள் யார் எனச் சொல்; நான் உன்னை பற்றிச் சொல்கிறேன்” என்று ஒரு வாசகம் வருமே! அதேபோல, ஒரு வார்த்தைக்கு முன்னும் பின்னும் உள்ள வார்த்தைகளின் அடிப்படையில், நடுவில் உள்ள வார்த்தையைக் கண்டுபிடிக்க முயல்வது CBOW ஆகும். அதுவே, “உன்ன மாதிரிதான டா, உன் கூட்டாளியும் இருப்பான்” என்போமே! அதைப்போல, நடுவில் உள்ள வார்த்தையை வைத்து அதற்கு முன்னும் பின்னும் உள்ள வார்த்தைகளைக் கண்டுபிடிக்க முயல்வது skip-gram ஆகும். இரண்டுமே கிட்டத்தட்ட ஒன்றுதான்! ஆனால், எதை வைத்து எதை முடிவு செய்கிறார்கள் என்பதைப் பொறுத்து context window எது? target word எது? என்பதில் வேறுபடுகிறது. விண்டோ சைஸ் என்பது ஒரு வார்த்தைக்கு முன்னும் பின்னும் எத்தனை வார்த்தைகள் வரை கணக்கில் கொள்ளலாம் என்பதைக் குறிக்கிறது.
Word2vec மாடலில் ஒரு சில மேன்மைகளைச் செய்து ஃபேஸ்புக் நிறுவனம் வெளியிட்டதே FastText எனும் மாடல் ஆகும். இது out of syllabus-ல் உள்ள வார்த்தைகளையும் கண்டுபிடிக்க வல்லது. ஏனெனில் இது பயிற்சி எடுத்துக் கொள்ளும் போதே வார்த்தைகளை பிரித்து மேய்ந்து விடுகிறது. ஒரு பாடத்திட்டத்தை படித்து முடிக்கும் ஒருவனை விட, பிரித்து மேயும் ஒருவனால் தான் out of syllabus-ல் கேள்வி கேட்டாலும் பதில் அளிக்க முடியும். அதைப்போல, வார்த்தை வார்த்தையாக அல்லாமல் எழுத்தெழுத்தாகப் பிரித்து மேய்ந்து இது கற்றுக் கொள்கிறது. விண்டோ சைஸ் என்பது இங்கு எழுத்துக்களின் எண்ணிக்கையைக் குறிக்கிறது. எனவே தான் பகுதி எழுத்துக்களைக் கோர்த்து vocabulary-யில் இல்லாத புதிய வார்த்தையையும் இதனால் உருவாக்க முடிகிறது. எடுத்துக்காட்டாக, [தமிழ், மிழ்நா, ழ்நாடு, நாடுஇ, டுஇந், இந்தி, ந்தியா, தியாவி, யாவின்…] என்பதுபோல மும்மூன்று எழுத்துக்களாகப் பிரித்து பயிற்சி எடுத்துக் கொள்ளும். இதனுடன் வேறு வார்த்தையிலிருந்து பிரிந்த மும்மூன்று எழுத்துக்களான ஈழம், த்துவா ஆகியவை சேரும் பொழுது. தமிழீழம், இந்துத்துவா போன்ற புதிய வார்த்தைகள் உருவாக வாய்ப்புள்ளது. இதுதான் FastText மாடலின் சிறப்பு!
Glove என்பது குளோபல் வெக்டர் ஆகும். Word2vec -ல் நான் குறிப்பிட்டது போல உன்னைப் பொறுத்து உன் நண்பர்களை முடிவு செய்வதும், உன் நண்பர்களைப் பொறுத்து உன்னை முடிவு செய்வதும் லோக்கல் context. அதுவே “இதெல்லாம் இப்படித்தான் முடியும்னு எனக்கு ஏற்கனவே தெரியும்” என்று ஒரு சிலர் கூறுவார்களே! அதுவே குளோபல் கான்டெக்ஸ்ட். உதாரணத்துக்கு ‘மசூதி இடிப்பு’ பற்றி செய்தித்தாளில் படித்துக் கொண்டிருக்கும் ஒருவர், “இவனுங்க மாஞ்சி மாஞ்சி இராமாயணமும் மகாபாரதமும் டி.வி.யில ஒளிபரப்பும்போதே நெனச்சேன்; இதெல்லாம் இப்படித்தான் முடியும்னு” என்று இரண்டையும் சம்பந்தப்படுத்தி பேசுவார். ஆனால் செய்தித்தாளில் இராமாயணமோ மகாபாரதமோ “மசூதி இடிப்பு” எனும் வார்த்தைக்கு முன்னோ பின்னோ காணப்படாது. இருந்தாலும், அவருடைய மொத்த வாழ்க்கையும் ட்ரெய்னிங் டேட்டாவாக எடுத்துக்கொண்டு, பக்தி இயக்கங்களின் வளர்ச்சிக்கும் – கலவரங்களின் வெடிப்புக்குமான frequency-யை கணக்கிட்டுக் கொண்டே வந்து, இறுதியில் அவருடைய குளோபல் கான்டெக்ஸ்ட் மூலம் “இரண்டும் தொடர்புடைய நிகழ்வுகள் தான்!” என்பதை கண்டுபிடித்து விடுவார். இதே முறையைத்தான் Glove பின்பற்றுகிறது. ஒரு வார்த்தையை கண்டுபிடிக்க அதற்கு அருகாமையில் உள்ளவற்றைக் கணக்கில் கொள்ளாமல், மொத்த டேட்டாவிலும் அருகருகே அமைகின்ற வார்த்தைகளின் frequency-யை பொறுத்துக் கண்டுபிடிக்கிறது. king – man + woman என்று கொடுத்தால் queen என்று வெளிப்படுத்துவதெல்லாம் glove செய்யும் வேலைதான்!
Sample programs
word2vec – இல் உள்ள ஒரு சில முக்கியமான ஃபங்க்ஷன் பற்றி இங்கு காணலாம்
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!pip install gensim | |
pip install numpy==1.23.5 | |
from gensim.models import word2vec | |
import nltk | |
nltk.download('stopwords') | |
nltk.download('punkt_tab') | |
paragraph = "Periyar was a social reformer in Tamil Nadu. He founded the Self-Respect Movement. This movement aimed to promote equality and end caste discrimination. Today, he is celebrated as a key figure in the fight for social justice and equality in Tamil Nadu" | |
lines = [i for i in paragraph.split('.')] | |
x= [[word for word in nltk.word_tokenize(each_line) if word.lower() not in nltk.corpus.stopwords.words('english')] for each_line in lines] | |
model = word2vec.Word2Vec(x, window=10, vector_size=5, min_count=1, sg=1, sample=1e-3) | |
print (model.wv.index_to_key) | |
print (model.wv['Periyar']) | |
print (model.wv.similarity('Self-Respect', 'equality')) | |
print (model.wv.most_similar(positive=['Periyar'],topn=2)) | |
#print (model.wv.most_similar(positive=['Peri'],topn=2)) |
- wv[] என்பது ஒரு வார்த்தைக்கான வெக்டரை வெளியிடுகிறது.
- wv.index_to_key என்பது வெக்டராக மாற்றப்படும் வார்த்தைகளின் பட்டியலை வெளியிடுகிறது. வார்த்தைகள் அதன் ஃப்ரீக்குவன்சியை பொறுத்து பட்டியலில் முதலிடம் பெறுகின்றன. அதிக முறை இடம் பெற்றுள்ள வார்த்தைகள் முதலாவதாகவும், மற்றவை அதனைத் தொடர்ந்தும் அமைகின்றன. இதில் is, was, between போன்ற ஆங்கிலத் துணைச் சொற்கள் இல்லாததை கவனிக்கவும். ஏனெனில் அதனை வெக்டராக்கி ஒரு பிரயோஜனமும் இல்லை.
- wv.similarity() என்பது இரு வார்த்தைகள் எந்த அளவுக்கு தொடர்புடையவை எனும் மதிப்பினை வெளியிடுகின்றன. இது 1 என வெளிப்படுத்தினால் அதிக தொடர்புடையவை என்றும், 0 என்றால் தொடர்பில்லாதவை என்றும், -1 என்றால் எதிர்மறையாகத் தொடர்புடையது என்றும் அர்த்தம்.
- இம்மதிப்புகளைத் தழுவியே wv.most_similar() எனும் ஃபங்ஷனும் செயல்படுகிறது. இதற்குள் பாசிட்டிவ் எனக் கொடுத்தால் அதிக தொடர்புடைய வார்த்தைகளையும், நெகட்டிவ் எனக் கொடுத்தால் எதிர்மறையாகத் தொடர்புடைய வார்த்தைகளையும், கொடுக்கப்பட்டுள்ள எண்ணிக்கைக்கு ஏற்ப வெளிப்படுத்தும்.
- இரு வார்த்தைகள் எந்த அளவுக்கு தொடர்புடையவை என்பதைக் குறிக்க வெளிப்படும் மதிப்பு, அதனுடைய வெக்டர்களால் உருவாகும் கோணத்தின் cos similarity மதிப்பினை பொறுத்து அமையும். இதைப்பற்றி முக்கோணவியல் பகுதியில் இன்னும் விரிவாகக் காணலாம்.
model.wv.index_to_key
[‘social’, ‘Tamil’, ‘Nadu’, ‘equality’, ‘justice’, ‘aimed’, ‘reformer’, ‘founded’, ‘Self-Respect’, ‘Movement’, ‘movement’, ‘promote’, ‘fight’, ‘end’, ‘caste’, ‘discrimination’, ‘Today’, ‘,’, ‘celebrated’, ‘key’, ‘figure’, ‘Periyar’]
model.wv[‘Periyar’]
[-0.1233535 0.02211227 0.12094565 -0.05680101 -0.12347045]
model.wv.similarity(‘Self-Respect’, ‘equality’)
0.31390482
model.wv.most_similar(positive=[‘Periyar’],topn=2)
[(‘Tamil’, 0.8870946764945984), (‘reformer’, 0.8688445687294006)]
negative:
[(‘key’, 0.8121072053909302), (‘,’, 0.5541471838951111)]
positive=[‘Peri’]
KeyError: “Key ‘Peri’ not present in vocabulary”
word2vec என்பது வார்த்தை வார்த்தையாகப் பிரித்து வெக்டர்களை உருவாக்கும் என்பதை அறிவோம். ஆகவே, ஒரு வார்த்தையின் முதல் சில எழுத்துக்களை மட்டும் கொடுத்து, அதற்குத் தொடர்பான வார்த்தையை வெளிப்படுத்தக் கூறினால், பிழைச்செய்தி வெளிப்படும். அதுவே FastText என்பது எழுத்தெழுத்தாகப் பிரித்துச் சேமிப்பதால், அது தொடர்புடைய வார்த்தையை வெளிப்படுத்தும். இந்த ஒரு வித்தியாசத்தைத் தவிர மற்ற அனைத்தும் இரண்டிலும் ஒன்றுதான்!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from gensim.models.fasttext import FastText | |
paragraph = "Periyar was a social reformer in Tamil Nadu. He founded the Self-Respect Movement. This movement aimed to promote equality and end caste discrimination. Today, he is celebrated as a key figure in the fight for social justice and equality in Tamil Nadu" | |
lines = [i for i in paragraph.split('.')] | |
x= [[word for word in nltk.word_tokenize(each_line) if word.lower() not in nltk.corpus.stopwords.words('english')] for each_line in lines] | |
model = FastText(x, window=20, min_count=1, sg=1, sample=1e-3) | |
print (model.wv.index_to_key) | |
print (model.wv['Periyar']) | |
print (model.wv.similarity('Self-Respect', 'equality')) | |
print (model.wv.most_similar(positive=['Periyar'],topn=2)) | |
print (model.wv.most_similar(positive=['Peri'],topn=2)) |
model.wv.most_similar(positive=[‘Peri’],topn=2)
[(‘Periyar’, 0.4749273955821991), (‘social’, 0.2427682876586914)]
Glove என்பது குளோபல் கான்டெக்ஸ்ட் ஆகும். கேரளாவில் “பெரியார் நதி” என்று ஒன்று உள்ளது. ஆகவே பெரியார் என்பதைக் கொடுத்து அதற்குத் தொடர்புடைய வார்த்தைகளை வெளிப்படுத்த கூறினால், அதனை நதியின் பெயராகக் கருதி வேறு இரு நதிகளின் பெயரை வெளிப்படுத்துவதைக் காணலாம்.
Periyar River is a major river in Kerala, India. That’s why it’s returning other rivers like ‘teesta’ (India), ‘neris’ (Europe).