Deep Learning – 04 – PyTorch

Deep Neural Network-ன் செயல்பாடுகளை ஆராய்வதற்கு உதவும் மற்றொரு வலிமையான கட்டமைப்பே PyTorch ஆகும். இது முகநூலின் செயற்கை அறிவுத்திறன் ஆய்வுக் குழு மூலம் உருவாக்கப்பட்ட பைதானை அடிப்படையாகக் கொண்ட ஒரு library ஆகும். Torch எனப்படும் இயந்திர வழிக்கற்றலுக்கான தொகுப்பின் அடிப்படையில் உருவானதே pytorch ஆகும்.

Tensors

நியூரல் நெட்வொர்கைப் பொருத்தவரை தரவுகள் அனைத்தும் டென்சார் எனப்படும் கொள்கலனின் வழியேதான் செயல்படுகின்றன. இந்த பைடார்‌ச்சிலும் torch.Tensor() எனும் class மூலமாக தரவுகளை டென்சாராக உருவாக்கலாம். கீழ்க்கண்ட உதாரணத்தில் x1 எனும் பெயர் கொண்ட காலி டென்சார் உருவாக்கப்பட்டுள்ளது. பின்னர் [1,2,3] எனும் 1d array-வைக் கொண்ட x2 டென்சார் உருவாக்கப்பட்டுள்ளது. இது 3 உறுப்புகளைக் கொண்டுள்ளது என்பதனால், இதன் size மதிப்பு 3 என வெளிப்படுவதைக் காணலாம். மேலும் ஒவ்வொரு உறுப்பின் பக்கத்திலும், புள்ளியை இட்டு அனைத்தையும் Float32 வகையில் உருவாக்கும். அவ்வாறு இல்லாமல் int64 வகையில் உருவாக்க விரும்பினால், பெரிய T-க்கு பதிலாக சிறிய t -ஐ இட்டு torch.tensor() அல்லது torch.as_tensor() என்ற இரண்டில் ஏதாவது ஒன்றைப் பயன்படுத்தி உருவாக்கலாம். இவ்விரண்டையும் வைத்து உருவாக்கப்பட்ட x3, x4 டென்சார்கள் ஒரே மாதிரி ஒரே வகையில் உருவாக்கப்பட்டுள்ளதைக் காணவும். எனவேதான் இவ்விரண்டு டென்சாரையும் கூட்டி அதன் மதிப்பு ([2, 4, 6]) வெளிப்படுத்தப்பட்டுள்ளது. அதுவே x2-ஐயும் x3-ஐயும் கூட்ட இயலாது.
ஒவ்வொரு டென்சாரும் dtype, device, layout எனும் 3 பண்புகளைப் பெற்றிருக்கும். dtype என்பது டென்சாரின் தரவு வகையை வெளிப்படுத்த உதவும். device என்பது ஒரு டென்சார் CPU-ல் இயங்கிக் கொண்டிருக்கிறதா அல்லது GPU-ல் இயங்கிக் கொண்டிருக்கிறதா என்பதை வெளிப்படுத்தும்.layout எனும் பண்பு ஒரு டென்சாருடைய நினைவக அமைப்பை (memory layout) வெளிப்படுத்தும். தற்போதைக்கு torch.strided எனும் மதிப்பையே இது வெளிப்படுத்தும். சோதனை முயற்சியாக torch.sparse_coo என்பது பயன்படுத்தப்பட்டு வருகிறது.
அடுத்ததாக eye(), zeros(), ones() போன்றவை முறையே முற்றொருமை அணி, பூஜ்ஜிய அணி, 1-ஐ மட்டும் கொண்ட அணி ஆகியவற்றை கொடுக்கப்பட்டுள்ள வடிவத்தில் உருவாக்குகின்றன. பின்னர் rand() மூலம் 1d, 2d, 3d போன்ற வடிவங்களில் random-ஆக அமைந்த எண்களைக் கொண்ட அணிகள் உருவாக்கப்பட்டுள்ளன.


import torch
x1 = torch.Tensor()
print (x1)
x2 = torch.Tensor([1,2,3])
print (x2)
print (x2.size())
print (x2.dtype)
x3 = torch.tensor([1,2,3])
x4 = torch.as_tensor([1,2,3])
print (x3)
print (x4)
print (x3+x4)
#print (x2+x3)
print (x4.dtype)
print (x4.device)
print (x4.layout)
print (torch.eye(2))
print (torch.zeros(2,2))
print (torch.ones(2,2))
print (torch.rand(2))
print (torch.rand(2,3))
print (torch.rand(2,3,4))

view raw

PyTorch.py

hosted with ❤ by GitHub

நிரலுக்கான வெளியீடு:
tensor([])

tensor([1., 2., 3.])
torch.Size([3])
torch.float32

tensor([1, 2, 3])
tensor([1, 2, 3])
tensor([2, 4, 6])

torch.int64
cpu
torch.strided

tensor([[1., 0.], [0., 1.]])
tensor([[0., 0.], [0., 0.]])
tensor([[1., 1.], [1., 1.]])
tensor([0.7487, 0.0652])
tensor([[0.6830, 0.9479, 0.7002],[0.3283, 0.8602, 0.6711]])
tensor([[[0.8002, 0.9752, 0.4617, 0.5603],[0.1520, 0.6906, 0.9570, 0.7589],[0.0122, 0.8932, 0.9644, 0.3375]],
[[0.5123, 0.3771, 0.5494, 0.1664],[0.0154, 0.4539, 0.8266, 0.8343],[0.8994, 0.5009, 0.0348, 0.0757]]])

Some useful commands

topk() என்ற கட்டளைக்குள் k=1 என்றால் முதலாவது பெரிய மதிப்பையும், k=2 என்றால் முதல் இரண்டு பெரிய மதிப்புகளையும் வெளிப்படுத்தும். கீழ்க்கண்ட உதாரணத்தில் X எனும் 2d டென்சார் உருவாக்கப்பட்டுள்ளது. அதற்குள் dim=1 எனும்போது கொடுக்கப்பட்ட 3 columns-ஐ 0,1,2 என பரிமாணப்படுத்தி, முதல் row-ல் உள்ள 3 columns-ல் பெரிய மதிப்பான 120-ஐயும், 2வது row-ல் உள்ள 3 columns-ல் பெரிய மதிப்பான 160-ஐயும் மற்றும் அவற்றின் பரிமாணங்களையும் வெளிப்படுத்துகிறது. அதுவே dim=0 எனும்போது கொடுக்கப்பட்ட 2 rows-ஐ 0,1 என பரிமாணப்படுத்தி, முதல் column-ல் உள்ள 2 rows-ல் பெரிய மதிப்பான 160-ஐயும், 2வது column-ல் உள்ள 2 rows-ல் பெரிய மதிப்பான 120-ஐயும், மூன்றாவது column-ல் உள்ள 2 rows-ல் பெரிய மதிப்பான 90-ஐயும் மற்றும் அவற்றின் பரிமாணங்களையும் வெளிப்படுத்துகிறது.
டென்சாரில் இருந்து ஒரு எண்ணை மட்டும் பிரித்து எடுக்க torch.Tensor().item() என்பது பயன்படுகிறது. x.mul(2) என்பது கொடுக்கப்பட்ட எண்ணை டென்சாரில் உள்ள அனைத்து மதிப்புகளுடனும் பெருக்கி வெளிப்படுத்தும். அதுவே எந்த ஒரு operation-ன் பக்கத்திலும் underscore-ஐ சேர்க்கும்போது (mul_()), அது வெளிப்படுத்தும் புதிய மதிப்புகளால் ஏற்கெனவே உள்ள மதிப்புகளை இடமாற்றம் செய்யும்.. இங்கு நாம் underscore-ஐப் பயன்படுத்தியுள்ளத்தால் இனிமேல் x-ன் மதிப்பு 2-ஆல் பெருக்கிக் கிடைத்த புதிய மதிப்புகளையே பெற்றிருக்கும். reshape செய்யும்போதும் இம்மதிப்புகளே மறுவடிவம் செய்யப்படுவதைக் காணலாம்.
ஒரு டென்சாரை array-ஆக மாற்ற அந்த டென்சாரின் பெயர் பக்கத்தில் புள்ளி வைத்து numpy() என்பது பயன்படுகிறது. அதுவே ஒரு array-வை டென்சாராக மாற்றுவதற்கு torch.from_numpy() என்பதற்குள் மாற்ற வேண்டிய array()-வைக் கொடுக்க வேண்டும்.
ஒரு டென்சாரை மறுவடிவம்(reshape) செய்வதற்கு view() கட்டளை பயன்படுகிறது. அதாவது கொடுக்கப்பட்ட 2d டென்சாரை 1d-ஆக மாற்றுவதற்கு, அந்த டென்சாரின் பக்கத்தில் புள்ளி வைத்து view(1,6) எனக் கொடுக்கலாம். அதாவது இரண்டு rows-ல் உள்ள மூன்று மூன்று columns அனைத்தும் ஒரே row-ல் வந்துவிடும். இல்லையெனில் view(1,-1) எனக் கொடுக்கலாம். -1 எனும்போது, நாம் குறிப்பிட்டு இத்தனை உறுப்புகள் என்று கூறத் தேவையில்லை. அத்தனையும் மறுவடிவம் செய்யப்பட்டுவிடும்.


import torch
x = torch.Tensor([[110,120,90],[160,20,60]])
print (x.topk(k = 1, dim = 1))
print (x.topk(k = 2, dim = 1))
print (x.topk(k = 1, dim = 0))
print (x.topk(k = 2, dim = 0))
print (torch.Tensor([110]).item())
print (x.mul_(2))
y = x.numpy()
z = torch.from_numpy(y)
print (type(y))
print (type(z))
a = x.view(1,-1)
print(a)
print(a.size())

நிரலுக்கான வெளியீடு:

torch.return_types.topk(values=tensor([[120.],[160.]]),indices=tensor([[1],[0]]))
torch.return_types.topk(values=tensor([[120., 110.],[160., 60.]]),indices=tensor([[1, 0],[0, 2]]))
torch.return_types.topk(values=tensor([[160., 120., 90.]]),indices=tensor([[1, 0, 0]]))
torch.return_types.topk(values=tensor([[160., 120., 90.],[110., 20., 60.]]),indices=tensor([[1, 0, 0],[0, 1, 1]]))

110.0
tensor([[220., 240., 120.],[ 40., 320., 180.]])

<class ‘numpy.ndarray’>
<class ‘torch.Tensor’>
tensor([[220., 240., 120., 40., 320., 180.]])
torch.Size([1, 6])

GPU

CPU என்பது ஒரு கணினியின் மூளை என்றால், அந்த மூளையின் செயல்திறனை பலமடங்கு அதிகரிக்கும் வகையில் தற்போது உருவாக்கம் அடைந்திருப்பதே GPU ஆகும். இது Graphics Processing Unitஎனப்படும். Graphics, 3d games போன்றவற்றில் திரை ஒழுங்கமைவு செயல்களை அதிகளவு செய்வதற்கும், செயற்கை அறிவுத்திறன் துறைகளில் பல்வேறு கடின கணித செயல்பாடுகளை துரிதமாக செய்து முடிக்கவும் இந்த GPU பெரிதும் உதவுகிறது. இதன் துரித ஆற்றல்தான் இதனுடைய சிறப்பே!
கீழ்க்கண்ட உதாரணத்தில் random-ஆக தேர்ந்தெடுக்கப்பட்ட ஆயிரம் rows & columns-ஐக் கொண்ட a மற்றும் b எனும் இரண்டு 2d அணிகள் உருவாக்கப்பட்டுள்ளன. பின்னர் இவை இரண்டும் matmul() மூலம் ஒன்றோடொன்று பெருக்கப்படுகின்றன. இந்த செயல் நடைபெறுவதற்கு முன்னர் உள்ள நேரமும் பின்னர் உள்ள நேரமும் முறையே startமற்றும் end எனும் இரு variables -ல் சேமிக்கப்படுகின்றன. பின்னர் இவை இரண்டுக்குமான வித்தியாசத்தைக் கண்டுபிடிப்பதன் மூலம் இந்த செயல் CPU-ல் நடைபெறுவதற்கான நேரம் கணக்கிடப்படுகிறது.
பின்னர் நமது கணினியில் GPU இருக்கிறதா என்பதை சோதிக்க cuda.is_available() எனும் கட்டளை பயன்படுகிறது. இது True என வெளிப்படுத்தினால், நமது a, b எனும் டென்சார் களை GPU-ல் செயல்படுவதற்கு ஏற்ற வகையில் மாற்ற .cuda() எனும் function உதவுகிறது. இதன் மூலம் அவை GPU-ல் ஏற்றப்பட்ட பின் மீண்டும் இவ்விரண்டு அணிகளின் பெருக்கலுக்கான நேரம் கணக்கிடப்படுகிறது. CPU -ல் இதற்கான நேரம் 22 விநாடிகள் என்றால், GPU -ல் இன்னும் துரிதமாக 0.0002 விநாடியில் இச்செயல் நடைபெற்று முடிந்திருப்பதைக் காணலாம்.


import time
import torch
a = torch.rand(10000,10000)
b = torch.rand(10000,10000)
start = time.time()
a.matmul(b)
end = time.time()
print("{} seconds".format(end – start))
print (torch.cuda.is_available())
a = a.cuda()
b = b.cuda()
start = time.time()
a.matmul(b)
end = time.time()
print("{} seconds".format(end – start))

view raw

PyTorch_GPU

hosted with ❤ by GitHub

உங்களது கணினியில் GPU இல்லையெனில், google colab எனும் பின்வரும் இணைப்பைப் பயன்படுத்தி கீழ்க்கண்ட சோதனையைச் செய்து பார்க்கலாம்.
colab.research.google.com/notebooks/welcome.ipynb

நிரலுக்கான வெளியீடு:

22.068870782852173 seconds
True
0.00020956993103027344 seconds
<class ‘numpy.ndarray’>
<class ‘torch.Tensor’>
tensor([[220., 240., 120., 40., 320., 180.]])
torch.Size([1, 6])

%d bloggers like this: