Deep Learning – 16 – BM, RBM, DBN Networks

Boltzmann Machinesஎன்பதிலிருந்து உருவானதே Restricted boltzmann machines ஆகும். முதலில் Boltzmann Network என்றால் என்ன என்று பார்ப்போம். மாதிரித் தரவுகளில் உள்ள அதிகப்படியான features-ல் இருந்து நமக்கு வேண்டிய முக்கிய அம்சங்களை மட்டும் உருவாக்கும் வேலையை Boltzmann Machinesசெய்கிறது. இது வெறும் input மற்றும் hidden லேயரை மட்டும் பெற்று விளங்கும் நெட்வொர்க் ஆகும். மற்ற deep learning மாடலில் உள்ளது போன்று output லேயர் என்ற ஒன்று தனியாகக் கிடையாது. இந்த இரண்டு லேயரில் உள்ள nodes அனைத்தும் undirected முறையில் இணைக்கப்பட்டிருக்கும். அதாவது மற்ற நெட்வொர்க் போன்று தரவுகளை முன்னோக்கி மட்டுமே செலுத்தாமல், இவற்றில் உருவாக்கப்படும் தரவுகள் அனைத்து திசையிலும் செலுத்தப்பட்டு மற்ற nodes-ஐ உருவாக்கும். எனவேதான் இது ‘Generative Deep Learning Model’ என்று அழைக்கப்படுகிறது. இதன் அமைப்பு பின்வருமாறு.

இதில் உள்ள ஒவ்வொரு nodes-ம் சிறப்பு அம்சங்களைக் கண்டறிய உதவும் ஒரு feature detector-ஆக செயல்படும். இதில் இணைப்பு முறை எவ்வாறு இருக்குமென்றால், இரண்டு லேயரில் உள்ள nodes-ம் ஒன்றோடொன்று இணைப்பை ஏற்படுத்திக் கொள்வதுடன், ஒரே லேயரில் உள்ள nodes-ம் தங்களுக்குள் இணைப்பை ஏற்படுத்திக் கொள்ளும். இதனால் உருவாகக் கூடிய அதிக அளவு feature detectors-ஆல், நெட்வொர்கின் வேகம் குறைந்து காணப்படும். இதனைத் தவிர்ப்பதற்காக வந்ததே Restricted Boltzmann Machines ஆகும். இதன் அமைப்பு பின்வருமாறு.

RBM என்பது ஒரே லேயரில் உள்ள nodes தங்களுக்குள் இணைப்பை ஏற்படுத்திக் கொள்வதை மட்டும் restrict செய்யும். மற்றபடி இதுவும் BN-ஐப் போன்றே இரண்டு லேயரைக் கொண்ட நியூரல் நெட்வொர்க் ஆகும். முதலாவது லேயர் input எனவும், இரண்டாவது லேயர் hidden எனவும் அழைக்கப்படும். இது ஒரே லேயரில் உள்ள nodes-க்குள் ஏற்படும் இணைப்பை மட்டும் restrict செய்வதால், ‘Restricted Boltzmann Network’ என்ற பெயரில் அழைக்கப்படுகிறது. இதுவும் undirected என்பதால், பின்னோக்கிப் பரவுதல் மூலம் gradient descent முறையில் அளவுருக்களை சரி செய்வது என்பது இதில் கிடையாது. அதற்கு பதிலாக ‘Contrastive divergence’ எனும் முறை பயன்படுத்தப்படுகிறது. இது ஆற்றலைக் குறைப்பதைக் குறிக்கோளாகக் கொண்டு செயல்படும் ஒரு இயற்பியல் சமன்பாட்டினை வைத்து செயல்படுகிறது. எனவே இது ‘Energy based model’ வகையைச் சார்ந்தது எனலாம். dimensionality reduction, collaborative filtering, feature learning and topic modeling போன்ற இடங்களில் இது செயலாற்றி வருகிறது. RBM என்பது visible nodes வழியே வரும் உள்ளீட்டுத் தரவுகளுடன் random -ஆகத் தேர்ந்தெடுக்கப்பட்ட அளவுருக்களை(weights) இணைத்து hidden nodes-ஐ உருவாக்கும். பின்னர் உருவாக்கப்பட்ட hidden nodes அதே அளவுருக்களைப் பயன்படுத்தி அதே எண்ணிக்கையில் அமைந்த visible nodes-ஐ மறு உருவாக்கம் செய்கிறது.

Deep Belief Network என்பதை இன்னும் சற்று மேம்படுத்தப்பட்ட RBM எனலாம். இது Stack of RBM என்று அழைக்கப்படுகிறது. RBM-ன் ஒவ்வொரு லேயரிலும் உள்ள தனித்தனி nodes-ன் இணைப்புகளைத் தவிர்த்து, மாறாக லேயருக்கிடையேயான இணைப்பை ஊக்குவிக்கிறது. இது ஒன்றுக்கும் மேற்பட்ட hidden லேயர்களைக் கொண்டிருப்பின், ஒவ்வொரு லேயரும் தனக்கு முந்தைய லேயருடனும், தனக்கு அடுத்த லேயருடனும் இணைப்பை ஏற்படுத்திக் கொண்டு செயல்படுகிறது. தனக்கு முந்தைய லேயருக்கு hidden லேயராகவும், தனக்கு அடுத்த லேயருக்கு visible லேயராகவும் செயல்படுகிறது. ஒரே லேயருக்குள்ளோ அல்லது அருகாமையில் அமையாத லேயருடனோ இணைப்பை ஏற்படுத்தாது. இதன் அமைப்பு பின்வருமாறு.

மேற்கண்ட அனைத்தும் UPN(Unsupervised Pretrained Network) வகையைச் சார்ந்தது. அதாவது ஏற்கெனவே unsupervised முறையில் பயிற்சி அளித்து உருவாக்கப்பட்ட algorithms ஆகும். RBM என்பது features-ஐப் பிரித்தெடுத்து தரவுகளை மீண்டும் மறுஉருவாக்கம் செய்யப் பயன்படும். ஆனால் இதனால் கடினமான features-ஐக் கையாள முடியாது. படங்கள், ஒளி, ஒலி போன்றவற்றின் மீது செயல்பட்டு cluster images, video capture sound, text போன்ற வேலைகளைச் செய்வதற்கு DBN பெரிதும் பயன்படுகிறது.

கீழ்க்கண்ட எடுத்துக்காட்டில் 943 பயனர்கள், 1682 படங்களுக்கு வழங்கிய தரவரிசை மதிப்புகள் பயிற்சிக்கு, பரிசோதனைக்கு என இரண்டு கோப்புகளாக உள்ளன. ‘u1.base’ , ‘u1.test’ எனும் இரண்டு பெயரில் இருக்கும் இவற்றை கீழ்க்கண்ட முகவரியில் சென்று பதிவிறக்கம் செய்துகொள்ளலாம்.
www.kaggle.com/prajitdatta/movielens-100k-dataset
இத்தரவுகளில் உள்ள 1682 படங்களையும் தனித்தனி features-ஆக எடுத்துக்கொண்டு , நாம் RBM மூலம் 200 features-ஐ தேர்ந்தெடுக்கப்போகிறோம். எனவே RBM-ன் உள்ளீட்டு லேயரில் 1682 nodes-ம், hidden லேயரில் 200 nodes-ம் அமையும். இந்த உள்ளீட்டு லேயரில் உள்ள ஒவ்வொரு node-ம் ஒவ்வொரு படத்தைக் குறிக்கும். இதன் வழியேதான் மொத்தம் உள்ள 943 பயனர்களும் அக்குறிப்பிட்ட படத்திற்கு அளித்த தரவரிசை மதிப்புகள் செலுத்தப்படும். பின்னர் sampling மூலம் 200 features தேர்ந்தெடுக்கப்படும். இதற்கான நிரல் பின்வருமாறு.


import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.nn.parallel
import torch.optim as optim
import torch.utils.data
from torch.autograd import Variable
def convert(data):
new_data = []
for i in range(1, 944):
id_movies = data[:,1][data[:,0] == i]
id_ratings = data[:,2][data[:,0] == i]
ratings = np.zeros(1682)
ratings[id_movies – 1] = id_ratings
new_data.append(list(ratings))
return new_data
W = torch.randn(200, 1682)
a = torch.randn(1, 200)
b = torch.randn(1, 1682)
def hidden(x):
wx = torch.mm(x,W.t())
activation = wx + a.expand_as(wx)
ph = torch.sigmoid(activation)
return ph, torch.bernoulli(ph)
def visible(y):
wy = torch.mm(y,W)
activation = wy + b.expand_as(wy)
pv = torch.sigmoid(activation)
return pv, torch.bernoulli(pv)
def train(v0, vk, ph0, phk):
global W,a,b
W += (torch.mm(v0.t(), ph0) – torch.mm(vk.t(), phk)).t()
b += torch.sum((v0 – vk), 0)
a += torch.sum((ph0 – phk), 0)
training_set = pd.read_csv('./u1.base', delimiter = '\t')
test_set = pd.read_csv('./u1.test', delimiter = '\t')
training_set = np.array(training_set, dtype = 'int')
test_set = np.array(test_set, dtype = 'int')
print (max(max(training_set[:,0]), max(test_set[:,0])))
print (max(max(training_set[:,1]), max(test_set[:,1])))
training_set = convert(training_set)
test_set = convert(test_set)
training_set = torch.FloatTensor(training_set)
test_set = torch.FloatTensor(test_set)
training_set[training_set == 0] = -1
training_set[training_set == 1] = 0
training_set[training_set == 2] = 0
training_set[training_set >= 3] = 1
test_set[test_set == 0] = -1
test_set[test_set == 1] = 0
test_set[test_set == 2] = 0
test_set[test_set >= 3] = 1
for epoch in range(1, 11):
train_loss = 0
s = 0.
for i in range(0, 943, 100):
vk = training_set[i:i+100]
v0 = training_set[i:i+100]
ph0,_ = hidden(v0)
for k in range(10):
_,hk = hidden(vk)
_,vk = visible(hk)
vk[v0<0] = v0[v0<0]
phk,_ = hidden(vk)
train(v0, vk, ph0, phk)
train_loss += torch.mean(torch.abs(v0[v0>=0] – vk[v0>=0]))
s += 1.
print('epoch: '+str(epoch)+' loss: '+str(train_loss/s))
test_loss = 0
s = 0.
for i in range(943):
v = training_set[i:i+1]
vt = test_set[i:i+1]
if len(vt[vt>=0]) > 0:
_,h = hidden(v)
_,v = visible(h)
test_loss += torch.mean(torch.abs(vt[vt>=0] – v[vt>=0]))
s += 1.
print('test loss: '+str(test_loss/s))

view raw

16_RBM.py

hosted with ❤ by GitHub

நிரலுக்கான விளக்கம்:
1. முதலில் மாதிரித் தரவுகள் training_set, test_set எனும் பெயரில் 2 dataframes-ஆக சேமிக்கப்பட்டு பின்னர் numpy array வடிவில் மாற்றப்படுகின்றன.
training_set = pd.read_csv(‘./u1.base’, delimiter = ‘\t’)
test_set = pd.read_csv(‘./u1.test’, delimiter = ‘\t’)
training_set = np.array(training_set, dtype = ‘int’)
test_set = np.array(test_set, dtype = ‘int’)
இதில் உள்ள மதிப்புகள் பின்வருமாறு அமையும்.
print (training_set[:3])
[[ 1 2 3 876893171]
[ 1 3 4 878542960]
[ 1 4 3 876893119]
[ 1 5 3 889751712]]
• முதல் column-ல் உள்ளது 1 முதல் 943 வரை அமைந்த பயனருக்கான எண்ணைக் குறிக்கிறது.
• 2 வது column-ல் உள்ளது 1 முதல் 1682 வரை அமைந்த படங்களுக்கான எண் ஆகும். அதாவது முதல் பயனர் எந்தெந்த படங்களுக்கு தரவரிசை மதிப்புகளை அளித்துள்ளார் என வெளிப்படுத்தியபின், 2-வது 3-வது என ஒவ்வொரு பயனரும் rating அளித்துள்ள படங்களை வெளிப்படுத்தும்.
• 3 வது column-ல் ஒரு பயனர் அக்குறிப்பிட்ட படத்துக்குக் கொடுத்துள்ள தரவரிசை எண் மதிப்பு அமைந்திருக்கும். 1 முதல் 5 வரை அமைந்த எண்களால் ஒரு படத்தின் தரம் குறிக்கப்படுகிறது.
• 4 வது column எந்த நேரத்தில் அப்பயனர் தர மதிப்பைக் கொடுத்துள்ளார் என்பதை வெளிப்படுத்துகிறது.
மொத்தம் எத்தனை பயனர்களும், படங்களும் உள்ளன எனும் விவரம் பின்வருமாறு கண்டுபிடிக்கப்பட்டுள்ளது. ஏனெனில் இத்தரவுகள் training, testingஎன இரண்டாகப் பிரிந்திருப்பதால், இரண்டிலும் உள்ள பெரிய மதிப்பு கண்டுபிடிக்கப்பட்டு, அதில் பெரியது கண்டுபிடிக்கப்படுகிறது.
print (max(max(training_set[:,0]), max(test_set[:,0]))) – 943 Users
print (max(max(training_set[:,1]), max(test_set[:,1]))) – 1682 Movies

2. இப்போது RBM தனது வேலையைத் தொடங்குவதற்கு ஏற்றவாறு 943 rows மற்றும் 1682 columns-ல் அமைந்த தர வரிசை மதிப்புகளைக் கொண்ட ஒரு அணி உருவாக்கப்பட வேண்டும். இத்தகைய அமைப்பினை உருவாக்கும் வேலையைத்தான் convert() function செய்கிறது.
def convert(data):
new_data = []
for i in range(1, 944):
id_movies = data[:,1][data[:,0] == i]
id_ratings = data[:,2][data[:,0] == i]
ratings = np.zeros(1682)
ratings[id_movies – 1] = id_ratings
new_data.append(list(ratings))
return new_data
இந்த function-க்குள் முதலில் ஒரு காலிப் பட்டியல் உருவாக்கப்படுகிறது. பின்னர் for loop மூலம் ஒவ்வொரு பயனரும் எந்தெந்த படங்களுக்கு rating அளித்துள்ளார், என்னென்ன rating அளித்துள்ளார் எனும் விவரம் id_movies , id_ratings எனும் இரண்டு பட்டியல்களாக சேமிக்கப்படுகின்றன. இது பின்வருமாறு.
print (id_movies)
[ 2 3 4 5 7 8 9 11 13 15 16 18 19 21 22 25 26 28
29 30 32 34 35 37 38 40 41 42 43 45 46 48 50 52 55 57
58 59 63 66 68 71 75 77 79 83 87 88 89 93 94 95 99 101
105 106 109 110 111 115 116 119 122 123 124 126 127 131 133 135 136 137
138 139 141 142 144 146 147 149 152 153 156 158 162 165 166 167 168 169
172 173 176 178 179 181 182 187 191 192 194 195 197 198 199 203 204 205
207 211 216 217 220 223 231 234 237 238 239 240 244 245 246 247 249 251
256 257 261 263 268 269 270 271] = 134

print (id_ratings)
[3 4 3 3 4 1 5 2 5 5 5 4 5 1 4 4 3 4 1 3 5 2 1 2 3 3 2 5 4 5 4 5 5 4 5 5 4
5 2 4 4 3 4 4 4 3 5 4 5 5 2 4 3 2 2 4 5 1 5 5 3 5 3 4 5 2 5 1 4 4 3 5 1 3
3 2 4 4 3 2 5 3 4 3 4 5 5 2 5 5 5 5 5 5 3 5 4 4 5 4 4 5 5 5 4 4 5 3 5 3 5
3 3 5 1 4 2 4 4 3 2 2 5 1 4 4 4 4 1 1 5 5 5 2] = 134

முதல் பயனர் 134 படங்களுக்கு rating கொடுத்துள்ளார். எனவே முதல் பயனருக்கான இவ்விரண்டு பட்டியல்களும் மேற்கண்டவாறு காணப்படும். மொத்தமாக உள்ள 1682 படங்களில் 134 படங்களுக்கே rating கொடுத்துள்ளார். எனவே rating அளிக்காத படங்களுக்கு 0 எனும் மதிப்பினை நாம் வழங்க வேண்டும். எனவே அடுத்ததாக 0 -ஐ மட்டும் பெற்று விளங்கும் ratings எனும் பெயர் கொண்ட 1d array உருவாக்கப்படுகிறது. இது பின்வருமாறு.
ratings = np.zeros(1682)
print (ratings)
[0. 0. 0. … 0. 0. 0.]
இது 1682 columns-ல் அமைந்த 0’s ஐப் பெற்றிருக்கும். பின்னர் எந்த படங்களுக்கு மட்டும் rating வழங்கப்பட்டுள்ளதோ, அந்த இடத்தில் மட்டும் 0-ஐ நீக்கி வழங்கப்பட்ட rating-ஆல் மாற்றம் செய்யும். இதற்காக ratings[id_movies – 1] = id_ratings எனக் கொடுக்கப்பட்டுள்ளது. இந்த இடத்தில் id_movies எனக் கொடுக்காமல் id_movies – 1 என கொடுக்கப்பட்டிருப்பதைக் கவனிக்கவும். ஏனெனில் 2 வது படத்துக்கு 3 எனும் மதிப்பீடு அளிக்கப்பட்டிருந்தால், இந்த array-ல் இரண்டாவதாக அமைந்திருக்கும் 0-ஐ மாற்றுவதற்கு பதிலாக, மூன்றாவதாக அமைந்திருக்கும் 0-ஐ மாற்றிவிடும். ஏனெனில் படங்களின் index 1-லிருந்து ஆரம்பிக்கிறது. ஆனால் array-ன் index 0-லிருந்து ஆரம்பிக்கிறது. இதனைத் தவிர்ப்பதற்காகவே id_movies – 1 என கொடுக்கப்பட்டுள்ளது.

இதே முறையில் மொத்தம் 943 பயனர்களுக்கு 943 1d array உருவாக்கப்படுகிறது. இவை new_data எனும் பெரிய பட்டியலுக்குள் ஒவ்வொன்றாகச் சேர்க்கப்படுகின்றன. இப்போது print(new_data[0]) எனக் கொடுத்துப் பார்த்தால், முதல் பயனர் rating அளித்துள்ள 2,3,4,5,7 ஆகிய இடங்களில் மட்டும் அவைகளுக்கான rating வெளிப்படுவதைக் காணலாம். 1,6 மற்றும் பல rating அளிக்காத இடங்களில் 0 வெளிப்படுவதைக் காணலாம். இது பின்வருமாறு.
[0.0, 3.0, 4.0, 3.0, 3.0, 0.0, 4.0, 1.0, 5.0, 0.0, 2.0, 0.0, 5.0, …. 0.0, 0.0]

3. மேற்கண்ட முறையில் அனைத்து பயிற்சித் தரவுகளையும் மாற்றி அமைத்து பின்னர் PyTorch ஏற்றுக் கொள்ளக் கூடிய array வடிவில் மாற்றுவதற்கான நிரல் பின்வருமாறு.
training_set = convert(training_set)
test_set = convert(test_set)
training_set = torch.FloatTensor(training_set)
test_set = torch.FloatTensor(test_set)

4. இது binary classification-க்கான problem என்பதால் தரவுகள் அனைத்தையும் 0’s & 1’s வடிவில் மாற்றப்போகிறோம். 1,2 எனும் குறைந்த மதிப்பீடுகள் 0-ஆலும், 3,4,5 எனும் அதிக அளவில் அமைந்த மதிப்பீடுகள் 1- ஆலும் இடமாற்றம் செய்யப்படுகின்றன. ஏற்கெனவே தரவரிசை அளிக்கப்படாததைக் குறிக்கும் 0 மதிப்பு -1 ஆல் இடமாற்றம் செய்யப்படுகிறது. இதற்கான நிரல் பின்வருமாறு.
training_set[training_set == 0] = -1
training_set[training_set == 1] = 0
training_set[training_set == 2] = 0
training_set[training_set >= 3] = 1
test_set[test_set == 0] = -1
test_set[test_set == 1] = 0
test_set[test_set == 2] = 0
test_set[test_set >= 3] = 1

5. இப்போது பயிற்சிக்குச் செலுத்தப்படும் தரவுகள் பின்வரும் வடிவில் அமைந்திருக்கும். இதில் 943 rows மற்றும் 1682 columns காணப்படும்.
print (training_set)
print (training_set.size())
tensor([[-1., 1., 1., …, -1., -1., -1.],
[ 1., -1., -1., …, -1., -1., -1.],
[-1., -1., -1., …, -1., -1., -1.],
…,
[ 1., -1., -1., …, -1., -1., -1.],
[-1., -1., -1., …, -1., -1., -1.],
[-1., 1., -1., …, -1., -1., -1.]])
torch.Size([943, 1682])
பின்னர் for loop மூலம் 10 சுழற்சிகள் உருவாக்கப்பட்டு, ஒவ்வொரு சுழற்சியிலும் பயிற்சிக்குப் பயன்படுத்திய அளவுருக்களை சரி செய்யும் நிகழ்வு நடைபெறுகிறது. மேலும் மீண்டும் ஒரு for loop மூலம் நூறு நூறாக அமைந்த 10 தொகுதிகளில் தரவுகளைப் பிரித்து பயிற்சி அளிக்கிறது. weights, bias ஆகியவை பயிற்சிக்குப் பயன்படுத்தப்பட்ட அளவுருக்கள் ஆகும். இவை random-ஆன மதிப்புகளைப் பெற்று இப்பயிற்சியைத் தொடங்குகிறது. மேலும் ஒவ்வொரு சுழற்சியிலும் இத்தகைய அளவுருக்களை மேம்படுத்துவதற்கு train() எனும் function-ஐப் பயன்படுத்துகிறது. Input மற்றும் hidden லேயர்கள் இரண்டும் ஒரே weights மதிப்பினைப் பயன்படுத்துகின்றன. ஆனால் இதற்கான bias மதிப்புகள் மட்டும் வேறுபடுகின்றன. a என்பது hidden லேயருக்கானது . b என்பது inputலேயருக்கானது. weights என்பது random-ஆகத் தேர்ந்தெடுக்கப்பட்ட (200,1682) வடிவில் அமைந்த மதிப்புகளைப் பெற்றுத் துவங்கும்.
hidden() மற்றும் visible() functions இரண்டும் ஒவ்வொரு முறையும் hidden node-க்கான மாதிரிகளையும், visible node-க்கான மாதிரிகளையும் தேர்ந்தெடுக்கின்றன. இவைகள் இரண்டும் 2 மதிப்புகளைத் திருப்பி அளிக்கின்றன. முதலாவது மதிப்பு ஒவ்வொரு மாதிரியும் sample-ஆக அமைவதற்கான நிகழ்தகவைக் குறிக்கும். இரண்டாவது மதிப்பு Bernoulli முறையில் தேர்ந்தெடுக்கப்பட்ட sample-ஐப் பெற்றிருக்கும். மேலும் hidden () வெளிப்படுத்துகின்றன தரவுகளின் வடிவம் torch.Size([100, 200]) என இருப்பதையும், visible () வெளிப்படுத்துகின்றன தரவுகளின் வடிவம் torch.Size([100, 1682]) என இருப்பதையும் காணலாம்.

print (ph0)
tensor([[9.9967e-01, 2.0279e-21, 1.0000e+00, …, 3.9762e-26, 1.0000e+00, 1.0000e+00],
[1.1460e-09, 2.4450e-22, 1.0000e+00, …, 3.7041e-22, 1.0000e+00, 2.0576e-08],
[1.9920e-03, 1.8334e-11, 1.0000e+00, …, 3.2599e-21, 1.0000e+00, 1.1196e-17],
…,
[3.3063e-03, 4.9096e-21, 1.0000e+00, …, 1.1215e-25, 1.0000e+00, 2.0377e-05],
[9.8176e-01, 5.9265e-14, 1.0000e+00, …, 6.0945e-25, 1.0000e+00, 2.3354e-03],
[2.9210e-09, 1.6359e-11, 1.0000e+00, …, 2.2869e-15, 1.0000e+00, 2.2399e-13]])

இம்முறையிலேயே RBM, features-ஐத் தேர்வு செய்கிறது. பயிற்சி அளித்து முடித்தபின், அதே தரவுகளைப் பயன்படுத்தி hidden நியூரான்களைத் தூண்டுவதன் மூலம் இதனை நாம் சோதித்துக் கொள்ளலாம்.

%d bloggers like this: