Machine Learning – 16 – Vectors

classification problem என்பது ‘ஆம்’ அல்லது ‘இல்லை’ எனும் மதிப்பின் கீழ் கணிப்பினை நிகழ்த்தும் என ஏற்கனவே கண்டோம். இவை முறையே 1 அல்லது 0-ஆல் குறிக்கப்படும். நாம் சிலசமயம் வாக்கியங்களையோ, நிழற்படங்களையோ, ஓவியங்களையோ உள்ளீடாகக் கொடுத்து பயிற்சி அளிக்க வேண்டியிருக்கும். இதுபோன்ற இடங்களில் இவற்றையெல்லாம் 1’s & 0’s -ஆக மாற்றுவதற்கு உதவுவதே vector ஆகும். இங்கு sklearn வழங்குகின்ற பல்வேறு வகையான வெக்டர்கள் பற்றியும் அவற்றின் பயன்பாடுகள் பற்றியும் காணலாம்.

பல்வேறு வாக்கியங்களைப் பெற்றிருக்கும் ஒரு தொகுப்பு corpus எனப்படுகிறது. இந்த corpus-ல் உள்ள அனைத்தையும் 0’s & 1’s ஆக மாற்றுவதற்கு dictvectorizer() , countvectorizer() ஆகியவை பயன்படுகின்றன.

கீழ்க்கண்ட உதாரணத்தில் corpus1 மற்றும் corpus2 எனும் இரண்டு corpus கொடுக்கப்பட்டுள்ளன. முதலில் உள்ளது dictvectorizer() -க்கு உதாரணமாகவும், இரண்டாவதாக உள்ளது countvectorizer() -க்கு உதாரணமாகவும் அமைந்துள்ளது. அடுத்ததாக vector எனும் variable-ல், corpus2-ல் உள்ள வாக்கியங்களுக்கான encode செய்யப்பட்ட வெக்டர்கள் அமைந்துள்ளன. இவற்றை வைத்து நாம் இரண்டு வெக்டர்களுக்கிடையேயான euclidean distance-ஐ எவ்வாறு கண்டுபிடிப்பது என்று பார்க்கலாம்.


from sklearn.feature_extraction import DictVectorizer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_extraction.text import HashingVectorizer
from sklearn.metrics.pairwise import euclidean_distances
corpus1 = [{'Gender': 'Male'},{'Gender': 'Female'},{'Gender': 'Transgender'},{'Gender': 'Male'},{'Gender': 'Female'}]
corpus2 = ['Bird is a Peacock Bird','Peacock dances very well','It eats variety of seeds','Cumin seed was eaten by it once']
vectors = [[2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0],[0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0]]
# one-hot encoding
v1 = DictVectorizer()
print (v1.fit_transform(corpus1).toarray())
print (v1.vocabulary_)
# bag-of-words (term frequencies, binary frequencies)
v2 = CountVectorizer()
print (v2.fit_transform(corpus2).todense())
print (v2.vocabulary_)
print (TfidfVectorizer().fit_transform(corpus2).todense())
print (HashingVectorizer(n_features=6).transform(corpus2).todense())
print (euclidean_distances([vectors[0]],[vectors[1]]))
print (euclidean_distances([vectors[0]],[vectors[2]]))
print (euclidean_distances([vectors[0]],[vectors[3]]))

view raw

vectors.py

hosted with ❤ by GitHub

1. dictvectorizer() என்பது ஒரு categorical variable-ஐ 1’s & 0’s -ஆக மாற்ற உதவும். இங்கு ‘Gender’ எனும் categorical variable-ன் மதிப்பாக ‘Male’, ‘Female’, ‘Transgender’ ஆகியவை அமைந்துள்ளன. முதலில் இத்தகைய unique மதிப்புகளை வைத்து ஒரு dictionary-ஐ உருவாக்கும். பின்னர் இந்த 3 தனித்தனி வார்த்தைகளும், அவற்றைப் பெற்று விளங்கும் 5 வரிகளும் 5*3 dimension கொண்ட ஒரு matrix-ஆக உருவாக்கப்படும். அதாவது ஒவ்வொரு வரியும் அந்த matrix-ன் ஒரு row ஆகவும், அந்த வரியில் dictionary-ல் உள்ள வார்த்தை இடம்பெற்றிருப்பின் 1 எனவும், இல்லையெனில் 0 எனவும் போட்டு வைத்துக்கொள்ளும். இவ்வாறே ஒரு வெக்டர் உருவாக்கப்படுகிறது. இதுவே one-hot encoding எனப்படுகிறது.

print (v1.fit_transform(corpus1).toarray())
[[0. 1. 0.]
 [1. 0. 0.]
 [0. 0. 1.]
 [0. 1. 0.]
 [1. 0. 0.]]

fit_transform() என்பது நமது corpus-ஐ உள்ளீடாக எடுத்துக்கொண்டு வெக்டருக்குக் கற்றுக்கொடுக்கும். to_dense() என்பது வார்த்தைகளின் அடர்த்திக்கான வெக்டரை உருவாக்கும். _vocabulary என்பது நமது வெக்டர் உருவாக்கத்திற்கு உதவிய dictionary-ஐக் கொண்டிருக்கும்.

print (v1.vocabulary_)
{'Gender=Male': 1, 'Gender=Female': 0, 'Gender=Transgender': 2}

2. countvectorizer() என்பது கொடுக்கப்பட்ட வாக்கியங்கள் அனைத்தையும் 1’s & 0’s -ஆக மாற்றும். நமது உதாரணத்தில் 4 வரிகளும், 17 தனித்துவ வார்த்தைகளும் உள்ளன. எனவே 4*17 dimension கொண்ட matrix உருவாக்கப்பட்டுள்ளது. ன் ஒவ்வொரு வரியிலும் எந்தெந்த வார்த்தை இடம்பெற்றுள்ளதோ அது 1 எனவும், இடம்பெறாத வார்த்தை 0 எனவும் அமைந்திருப்பதைக் காணலாம். இதுவே bag of words எனப்படுகிறது.

வார்த்தைகள் அமைந்திருக்கும் அதே வரிசையில்தான் encode செய்யப்பட்டவை இடம் பெற்றிருக்கும் எனக் கூற முடியாது. வார்த்தைகளில் உள்ள எல்லா எழுத்துக்களையும், சிறிய எழுத்துக்களாக மாற்றிவிட்டு அதனை tokens-ஆக மாற்றும். Tokenization என்பது இரண்டுக்கும் மேற்பட்ட எழுத்துக்களைப் பெற்றிருக்கும் வார்த்தைகளை இடைவெளி வைத்துப் பிரித்து tokens-ஆக மாற்றுவதே ஆகும். Tokens என்பது கோப்பினுள் இடம் பெற்றுள்ள வார்த்தைகள் ஆகும்.

Bird is a Peacock Bird’,’Peacock dances very well’,’It eats variety of seeds’,’Cumin seed was eaten by it once’

print (v2.fit_transform(corpus2).todense())
[[2 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 1]
 [0 0 0 0 0 1 0 1 1 0 0 0 1 1 0 0 0]
 [0 1 1 0 1 0 0 1 0 1 0 1 0 0 0 1 0]]

இதனை binary frequency மற்றும் term frequency என்னும் இரண்டு விதங்களில் குறிப்பிடலாம். binary என்பது வெறும் 1’s & 0’s -ஐ மட்டும் வெளிப்படுத்தும். term என்பது ஒவ்வொரு வார்த்தையும் எத்தனை முறை இடம்பெற்றுள்ளது என்பதை வெளிப்படுத்தும். இங்கு Bird என்பது முதல் வாக்கியத்தில் இரண்டு முறை உள்ளதால் அந்த இடத்தில் 2 என வெளிப்படுத்தப்பட்டுள்ளதைக் காணவும்.

இதற்கான vocabulary-ல் அந்த வரியிலிருந்தும் எடுக்கப்பட்ட 17 தனித்துவ வார்த்தைகள் அமைந்திருப்பதைக் காணவும் (0 முதல் 16 வரை). இங்கு Bird, Peacock, it ஆகிய வார்த்தைகள் இரண்டு முறை இடம்பெற்றுள்ளது. ஆனால் ஒரே ஒரு முறை மட்டும் தான் இங்கு சேமிக்கப்பட்டுள்ளது. அவ்வாறே case-sensitive இல்லாமல் it, It ஆகிய இரண்டும் ஒன்றாக எடுத்துக்கொள்ளப்பட்டுள்ளது. மேலும் a என்பது ஒரு தனி வார்த்தையாக எடுத்துக்கொள்ளப்படவில்லை.

print (v2.vocabulary_)
{'bird': 0, 'is': 6, 'peacock': 10, 'dances': 3, 'very': 14, 'well': 16, 'it': 7
, 'eats': 5, 'variety': 13, 'of': 8, 'seeds': 12, 'cumin': 2, 'seed': 11, 'was':
 15, 'eaten': 4, 'by': 1, 'once': 9}

3. TfidfVectorizer() என்பது இத்தகைய term frequency மூலம் உருவாக்கப்படும் வெக்டரை normalize செய்து அந்த frequency -க்கான weight-ஐ வெளிப்படுத்தும். வெறும் raw count-ஆக 2 என வெளிப்படுத்தாமல், அதனை normalize செய்து வெளிப்படுத்துவதே L2 Normalization (level2) எனப்படும்.

 
print (TfidfVectorizer().fit_transform(corpus2).todense())
[[0.84352956 0.         0.         0.         0.         0.
  0.42176478 0.         0.         0.         0.3325242  0.
  0.         0.         0.         0.         0.        ]
 [0.         0.         0.         0.52547275 0.         0.
  0.         0.         0.         0.         0.41428875 0.
  0.         0.         0.52547275 0.         0.52547275]
 [0.         0.         0.         0.         0.         0.46516193
  0.         0.36673901 0.46516193 0.         0.         0.
  0.46516193 0.46516193 0.         0.         0.        ]
 [0.         0.38861429 0.38861429 0.         0.38861429 0.
  0.         0.30638797 0.         0.38861429 0.         0.38861429
  0.         0.         0.         0.38861429 0.        ]]  

4. HashingVectorizer() என்பது அகராதியின் துணை இல்லாமலேயே நேரடியாக வெக்டரை உருவாக்கும். மேற்கண்ட dict & count ஆகிய இரண்டும் 2 படிகளில் வேலை செய்யும். முதலில் வெக்டர் உருவாக்கத்திற்குத் தேவையான dictionary-யை உருவாக்கும். அடுத்தபடியாகத்தான் வெக்டரை உருவாக்கும். இதில் முதல் படியைத் தவிர்த்து நேரடியாக வெக்டரை உருவாக்குவதைத்தான் Hashing Trick என்போம். ஏனெனில் dictionary-ன் அளவு பெருகப் பெருக அந்தளவுக்குப் பெரிய அகராதியை சேமிக்கத் தேவையான memory-ன் அளவும் அதிகரிக்கும். இதைத் தவிர்ப்பதற்காக வந்ததே இவ்வகையான வெக்டர் ஆகும்.

print (HashingVectorizer(n_features=6).transform(corpus2).todense())
[[ 0.         -0.70710678 -0.70710678  0.          0.          0.        ]
 [ 0.          0.         -0.81649658 -0.40824829  0.40824829  0.        ]
 [ 0.75592895  0.         -0.37796447  0.         -0.37796447 -0.37796447]
 [ 0.25819889  0.77459667  0.         -0.51639778  0.          0.25819889]]

5. euclidean_distances என்பது encode செய்யப்பட்ட இரண்டு வாக்கியங்களுக்கிடையேயான வேறுபாடு எந்த அளவுக்கு உள்ளது
என்பதைக் கணக்கிட உதவும். மேற்கண்ட உதாரணத்தில் முதல் இரண்டு வாக்கியங்களுக்கு இடையேயான வேறுபாடு சற்று குறைவாகவும், முதலுக்கும் 3-வது வாக்கியத்துக்குமான வேறுபாடு சற்று அதிகமாகவும், முதலுக்கும் 4-வது வாக்கியத்துக்குமான வேறுபாடு இன்னும்
சற்று அதிகமாகவும் இருப்பதைக் காணலாம்.

print (euclidean_distances([vectors[0]],[vectors[1]]))
[[2.82842712]]

print (euclidean_distances([vectors[0]],[vectors[2]]))
[[3.31662479]]

print (euclidean_distances([vectors[0]],[vectors[3]]))
[[3.60555128]]
%d bloggers like this: