Deep Learning – 08 – Shallow Neural Networks

Shallow Neural Networks

Shallow என்றால் ஆழமற்ற என்று பொருள். deep என்றால் ஆழமான என்று பொருள். எனவே Deep நியூரல் நெட்வொர்கைப் பற்றிக் கற்பதற்கு முன்னர் இந்த shallow நியூரல் நெட்வொர்கைப் பற்றித் தெரிந்து கொள்வோம். இதற்கு முன்னர் நாம் பயன்படுத்திய மார்பகப் புற்றுநோய்க்கான உதாரணத்தையே இங்கும் பயன்படுத்திக் கொள்வோம். ஆனால் இதன் உள்ளீடு மற்றும் வெளியீட்டு layer-க்கிடையில் hidden layer ஒன்று காணப்படும். அதில் நாம் வரையறுக்கும் எண்ணிக்கையில் அமைந்த nodes-ஐப் பெற்றிருக்கும். இதன் வழியே செயல்படும்போது அதிக அளவிலான features குறைந்த எண்ணிக்கையில் மாற்றப்பட்டு கணிப்புகள் நிகழும்.

கீழ்க்கண்ட நிரலில் மாதிரித் தரவுகள் train_test_split மூலம் பிரிக்கப்பட்டு normalize செய்யப்படுவதற்கு முன்னர் , வரைபடம் ஒன்று வரைந்து பார்க்கப்படுகிறது. அதில் முதல் 2 features-ஐ எடுத்துக் கொண்டு (X_cancer[:,0], X_cancer[:,1]) அவற்றில் உள்ள தரவுகள் 0 அல்லது 1 எனும் வகைப்பாட்டில் (c=y_cancer) எவ்வகையின் கீழ் அமைகின்றன என்பது முறையே கரும்புள்ளிகளாகவும், மஞ்சள் புள்ளிகளாகவும் வரைந்து காட்டப்படுகிறது. இவை வரைபடத்தில் நேர்கோடு முறையில் பிரிக்க இயலாத தரவுகளாகக் கலந்திருப்பதைக் காணலாம். எனவே எளிய logistic regression-ஐப் பயன்படுத்துவது இதற்கு உதவாது. shallow neural network கொண்டு இதனை நாம் பிரிக்கப் போகிறோம். மேலும் இவற்றை tensor flow பயன்படுத்திச் செய்யப் போகிறோம். சென்ற எடுத்துக்காட்டில் நாம் அனைத்தையும் கோட்பாடுகளாக நிரல் எழுதி செய்தோம். இப்போது அவற்றுக்கான tensor flow செயல்பாட்டுத் திட்டங்களைப் பயன்படுத்தப் போகிறோம்.


from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
import tensorflow as tf
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
def normalize(data):
col_max = np.max(data, axis = 0)
col_min = np.min(data, axis = 0)
return np.divide(data – col_min, col_max – col_min)
(X_cancer, y_cancer) = load_breast_cancer(return_X_y = True)
cmap = matplotlib.colors.ListedColormap(['black','yellow'])
plt.figure()
plt.title('Non-linearly separable classes')
plt.scatter(X_cancer[:,0], X_cancer[:,1], c=y_cancer, marker= 'o', s=50, cmap=cmap, alpha = 0.5 )
plt.show()
plt.savefig('fig1.png', bbox_inches='tight')
X_train, X_test, Y_train, Y_test = train_test_split(X_cancer, y_cancer, random_state = 25)
X_train = normalize(X_train).T
Y_train = Y_train.reshape(1, len(Y_train))
X_test = normalize(X_test).T
Y_test = Y_test.reshape(1, len(Y_test))
X = tf.placeholder(dtype = tf.float64, shape = ([X_train.shape[0],None]))
Y = tf.placeholder(dtype = tf.float64, shape = ([1,None]))
W1 = tf.Variable(initial_value=tf.random_normal([8,X_train.shape[0]], dtype = tf.float64) * 0.01)
b1 = tf.Variable(initial_value=tf.zeros([8,1], dtype=tf.float64))
W2 = tf.Variable(initial_value=tf.random_normal([1,8], dtype=tf.float64) * 0.01)
b2 = tf.Variable(initial_value=tf.zeros([1,1], dtype=tf.float64))
print (W1,b1,W2,b2)
Z1 = tf.matmul(W1,X) + b1
A1 = tf.nn.relu(Z1)
Z2 = tf.matmul(W2,A1) + b2
cost = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=Z2,labels=Y))
GD = tf.train.GradientDescentOptimizer(0.2).minimize(cost)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(5000):
c = sess.run([GD, cost], feed_dict={X: X_train, Y: Y_train})[1]
if i % 1000 == 0:
print ("cost after %d epoch:"%i)
print(c)
correct_prediction = tf.equal(tf.round(tf.sigmoid(Z2)), Y)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print("Accuracy for training data:", accuracy.eval({X: X_train, Y: Y_train}))
print("Accuracy for test data:", accuracy.eval({X: X_test, Y: Y_test}))

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

cost after 0 epoch:
0.6931285163990998
cost after 1000 epoch:
0.051629796747703585
……………………….
cost after 4000 epoch:
0.0307175769807556
Accuracy for training data: 0.9906103
Accuracy for test data: 0.91608393

Input Layer-ல் placeholders-ஐ உருவாக்குதல்:

பயிற்சிக்கு அளித்துள்ள தரவுகள் training, testing என்று பிரிக்கப்பட்டு, normalize மற்றும் reshape செய்யப்படுகின்றன. பின்னர் , உள்ளீட்டு மற்றும் வெளியீட்டுத் தரவுகளை நியூரல் நெட்வொர்க்குச் செலுத்தி பயிற்சி அளிப்பதற்கான X, Y எனும் 2 placeholders உருவாக்கப்படுகின்றன. இவற்றின் வழியாகத்தான் தரவுகள் அனைத்தும் நியூரல் நெட்வொர்க்குச் செல்கின்றன. இவற்றில் அமையும் columns-ன் எண்ணிக்கை மாதிரித் தரவுகளில் உள்ள features-ன் எண்ணிக்கையில் இருக்க வேண்டும் என்பதற்காக X_train.shape[0] என்பதும், rows-ன் எண்ணிக்கையில் நாம் குறிப்பாக எவ்வளவு தரவு மாதிரிகளை செலுத்தப் போகிறோம் என்பது தெரியாத பட்சத்தில் None என்பதும் X-ன் வடிவமைப்பில் கொடுக்கப்பட்டுள்ளன. அவ்வாறே Y-ன் வடிவமைப்பில், ஒரே ஒரு target column-ல் அமையும் பல்வேறு records என்பதைக் குறிக்கும் வகையில் [1,None] என்பது கொடுக்கப்பட்டுள்ளது.
X = tf.placeholder(dtype = tf.float64, shape = ([num_features,None]))
Y = tf.placeholder(dtype = tf.float64, shape = ([1,None]))
இப்போது நியூரல் நெட்வொர்க்கின் முதல் அடுக்கில் X_train-ல் உள்ள 30 features-க்கான placeholder nodes அமைந்திருக்கும்.

Hidden Layer-க்கான அளவுருக்களை அமைத்தல்:

placeholders வழியேதான் ஒவ்வொரு feature-ல் உள்ள தரவுகளும் அடுத்த layer-க்குச் செலுத்தப்படும். அடுத்த layer தான் hidden layer. இது shallow neural network என்பதால் ஒரே ஒரு hidden layer-தான் இருக்கும். இவற்றில் அமையும் nodes-ன் எண்ணிக்கையை நாம் 8 என வரையறுத்துள்ளோம். எனவே இந்த 8 nodes-க்கான அளவுருக்கள் (weights & bias) W1, b1 எனும் பெயரில் அமைந்துள்ளன.
W1 எனும் variable-க்கு tf.random_normal() மூலம் 30 features-க்கான அளவுருக்கள் ஒவ்வொரு node-க்கும் தனித்தனியாக random முறையில் தேர்ந்தெடுக்கப்பட்டு துவக்க மதிப்பாக அமைகிறது. அதாவது hidden layer-ல் உள்ள ஒவ்வொரு node-ம் random-ஆக தேர்ந்தெடுக்கப்பட்ட 30 weights parameters-ஐத் தங்கியிருக்கும். எனவே 30 columns-க்கான 8 rows-ஐக் கொண்ட ஒரு டென்சார் இதில் உருவாக்கப்படும்.
b1 எனும் variable-க்கு துவக்க மதிப்பாக பூஜ்ஜியம் என்பது அமையும். hidden layer-ல் உள்ள ஒவ்வொரு node-க்கும் இதனை அமைக்க tf.zeros() மூலம் ஒரே column-ல் 8 பூஜ்ஜியங்களைக் கொண்ட ஒரு டென்சார் உருவாக்கப்படுகிறது.
W1 = tf.Variable(initial_value=tf.random_normal([8,num_features], dtype = tf.float64) * 0.01)
b1 = tf.Variable(initial_value=tf.zeros([8,1], dtype=tf.float64))

Output Layer-க்கான அளவுருக்களை அமைத்தல்:

கடைசியாக உள்ளது வெளியீட்டு layer. இதற்கான அளவுருக்கள் W2, b2 எனும் பெயரில் அமைக்கப்படுகின்றன. வெளியீட்டு layer என்பது ஒரே ஒரு node-ஐக் கொண்டது. இதற்கு முந்தைய hidden layer-ல் உள்ள 8 nodes கணக்கிட்ட மதிப்புகளே இதற்கான features. ஆகவே இந்த 8 features-க்கான ஒரு node-வுடைய அளவுருக்கள் tf.random_normal([1,8]) மூலம் வரையறுக்கப்படுகின்றன. அவ்வாறே அந்த ஒரு node-வுடைய bias மதிப்பும் பூஜ்ஜியம் tf.zeros([1,1] என வரையறுக்கப்படுகிறது. W2 = tf.Variable(initial_value=tf.random_normal([1,8], dtype=tf.float64) * 0.01)
b2 = tf.Variable(initial_value=tf.zeros([1,1], dtype=tf.float64))

முன்னோக்கிப் பரவுதல் (Forward Propagation):

hidden layer-ல் உள்ள 8 நியூரான்கள் placeholders-வழியே வருகின்ற தரவுகளுடன் weights மற்றும் bias-ஐச் சேர்த்து தனது கணக்கீடுகளைத் தொடங்கும். இவ்வாறு கணக்கிட்டுக் கிடைத்த மதிப்பே Z1 என்று அழைக்கப்படுகிறது. இவற்றை 0 அல்லது 1 எனும் வகையின் கீழ் கணிக்க sigmoid-க்கு பதிலாக relu அல்லது tanh போன்ற ஏதாவதொன்றைப் பயன்படுத்தலாம். hidden layer-ல் உள்ள 8 நியூரான்களும் இதுபோன்ற 8 வகையான கணிப்புகளை வெளியிடுகின்றன. இதுவே A1 ஆகும். இம்மதிப்புடன் output layer-ல் உள்ள 1 நியூரானானது அதனுடைய weights மற்றும் bias-ஐச் சேர்த்து Z2-ஐக் கணக்கிடுகிறது. இம்மதிப்பை மீண்டும் 0/1 -ன் கீழ் வகைப்படுத்தத் தேவையில்லை. Tensor flow-ஐப் பொருத்தவரை கடைசி layer-லிருந்து வெளிவரும் activate செய்யப்படாத மதிப்பையே இழப்பைக் கணக்கிடுவதற்கான cost function-க்குள் செலுத்த வேண்டும். பின்னர் அந்த cost function தனக்குள்ளாகவே sigmoid மூலம் 0/1 என activate செய்துவிடும்.
Z1 = tf.matmul(W1,X) + b1
A1 = tf.nn.relu(Z1)
Z2 = tf.matmul(W2,A1) + b2

இழப்பைக் கணக்கிடுதல் (Finding cost):

sigmoid_cross_entropy() என்பது Tensor flow-ல் இழப்பைக் கண்டுபிடிக்கப் பயன்படுகிறது. இதற்குள் கடைசி layer-லிருந்து வெளிவருகின்ற activate செய்யப்படாத Z2 கணிப்புகளும், உண்மையான Y மதிப்புகளும் செலுத்தப்படுகின்றன. இவற்றை வைத்துக் கண்டுபிடித்த இழப்பின் சராசரியைக் கணக்கிட tf.reduce_mean() பயன்படுகிறது.
cost = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=Z2,labels=Y))

Gradient descent மூலம் இழப்பைக் குறைத்தல்:

Tensor flow-ல் derivative-ஐக் கணக்கிட்டு, அதனடிப்படையில் அளவுருக்களை மாற்றி, இழப்பினைக் குறைப்பதை ஒரே வரியில் செய்து விடலாம். GradientDescentOptimizer() எனும் function இதற்கான வேலையைச் செய்கிறது. 0.2 என்பது இதற்கு அளிக்கப்பட்டுள்ள learning rate ஆகும். சென்ற படியில் கண்டுபிடித்த cost மதிப்பு இதன் மீது செயல்படும் minimize() எனும் function-க்குள் செலுத்தப்படுகிறது.
train_net = tf.train.GradientDescentOptimizer(0.2).minimize(cost)

Session-ஐ உருவாக்கி அனைத்தையும் இயக்குதல்:

tf.global_variables_initializer() என்பது நம்முடைய நிரலில் நாம் variable என வரையறுத்துள்ள அனைத்தையும், அதனதன் துவக்க மதிப்புகளை பெற்றுக் கொள்ளச் செய்யும். ஒரு session-ஐ உருவாக்கி, அதன் மூலம் இந்த function-ஐ நாம் இயக்க வேண்டும். பின்னர் for loop மூலம் 5000 சுற்றுகளை உருவாக்கி, ஒவ்வொரு சுற்றிலும் cost கண்டுபிடிப்பதற்கான நிரலையும், gradient descent மூலம் அதைக் குறைப்பதற்கான நிரலையும் இயக்க வேண்டும்.அவ்வாறே X, Y -க்கான placeholders-ஐ வரையறுத்துள்ள இடத்தில், X_train மற்றும் Y_train -ல் உள்ள தரவுகளை feed_dict = {} மூலமாக நாம் செலுத்தியுள்ளோம். இத்தரவுகளுக்கான cost, 5000 முறை கண்டுபிடிக்கப்பட்டு ஒவ்வொரு முறையும் gradient descent மூலம் குறைக்கப்படுகிறது. குறைக்கப்பட்ட இழப்பு c எனும் variable-ல் [GD, cost] என கொடுக்கப்பட்டுள்ளதற்கு ஏற்ப [None,0.6931285163990998] எனும் முறையில் சேமிக்கப்படுகிறது. இதில் வலப்பக்கம் உள்ள cost-ஐ மட்டும் சேமிக்க sess.run()[1] என கொடுக்கப்பட்டுள்ளது. அடுத்ததாக 1000 சுற்றுகளுக்கு ஒருமுறை cost-ஐ பிரிண்ட் செய்யுமாறு if condition மூலம் கூறியுள்ளோம்.

உருவாக்கியுள்ள நியூரல் நெட்வொர்கை மதிப்பீடு செய்தல்:

எவ்வளவு கணிப்புகள் சரியாக நிகழ்ந்துள்ளன என்பதற்கான டென்சார் correct_prediction எனும் பெயரில் உருவாக்கப்பட்டுள்ளது. அவைகளின் சராசரிக்கான டென்சார் accuracy எனும் பெயரில் உருவாக்கப்பட்டுள்ளது. அதன் மீது செயல்படும் eval() function, பயிற்சித் தரவுகளையும், சோதனைத் தரவுகளையும் palceholders-க்கான இடத்தில் செலுத்தி, இரண்டின் accuracy-ஐயும் கண்டுபிடிக்கிறது.

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

cost after 0 epoch:
0.6931285163990998
cost after 1000 epoch:
0.051629796747703585
……………………….
cost after 4000 epoch:
0.0307175769807556
Accuracy for training data: 0.9906103
Accuracy for test data: 0.91608393

%d bloggers like this: