RNN, LSTM, GRU Sinhala Guide | Sequence Modeling Basics | AI for Developers

RNN, LSTM, GRU Sinhala Guide | Sequence Modeling Basics | AI for Developers

අද කාලේ AI (Artificial Intelligence) ගැන කතා නොකරන කෙනෙක් නැහැ නේද? ChatGPT, Midjourney, Google Bard වගේ දේවල් නිසා AI දැන් අපේ එදිනෙදා ජීවිතේ කොටසක් වෙලා. මේවායින් වෙන දේවල් දැක්කම, සමහර වෙලාවට අපිට හිතෙනවා මේවා පිටිපස්සේ තියෙන තාක්ෂණය හරි සංකීර්ණයි කියලා. ඒ වගේම, speech recognition (හඬ හඳුනාගැනීම), machine translation (භාෂා පරිවර්තනය), text generation (පෙළ නිර්මාණය) වගේ දේවල් කොහොමද හරියටම කරන්නේ කියලා ප්‍රශ්නත් ඇතිවෙන්න පුළුවන්.

මේ හැමදේටම පදනම වෙන්නේ "Sequence Modeling" කියන සංකල්පය. Sequence Modeling කියන්නේ අනුපිළිවෙලක් විදිහට එන දත්ත (data) analyse කරන එක. උදාහරණයක් විදිහට, භාෂාවක් කියන්නේ වචන ගොඩක අනුපිළිවෙලක්. කාලගුණ දත්තත් එක දිගට එන අනුපිළිවෙලක්. සාමාන්‍ය Neural Networks වලට මේ වගේ අනුපිළිවෙලවල් වල තියෙන සම්බන්ධතා තේරුම් ගන්න අමාරුයි.

ඔන්න ඔය ප්‍රශ්නයට විසඳුම තමයි Recurrent Neural Networks (RNNs). මේ ලිපියෙන් අපි RNNs කියන්නේ මොකක්ද, ඒවා කොහොමද වැඩ කරන්නේ, ඒවායේ තියෙන ගැටළු සහ ඒ ගැටළු විසඳන්න ආපු Long Short-Term Memory (LSTMs) සහ Gated Recurrent Units (GRUs) කියන දේවල් ගැන විස්තරාත්මකව කතා කරනවා. ඒ වගේම, practical උදාහරණයක් එක්ක මේවා කොහොමද යොදාගන්නේ කියලත් අපි බලමු. ඔයා data scientist කෙනෙක් වෙන්න හරි, Machine Learning engineer කෙනෙක් වෙන්න හරි බලාපොරොත්තු වෙනවා නම්, මේ දැනුම ඔයාට ගොඩක් වැදගත් වේවි.

Recurrent Neural Networks (RNNs) - අතීතය මතක තියාගන්න AI

සාමාන්‍ය Neural Networks (අපි මේවාට Feedforward Neural Networks කියමු) තනි input එකකට output එකක් දෙනවා. උදාහරණයක් විදිහට, පින්තූරයක් දීලා ඒකේ තියෙන්නේ බල්ලෙක්ද බළලෙක්ද කියලා කියන්න පුළුවන්. ඒත් "මම බත් කනවා" කියන වාක්‍යය analyse කරනකොට, "මම" කියන එකෙන් පස්සේ "බත්" එන්නේ ඇයි, ඊට පස්සේ "කනවා" එන්නේ ඇයි කියලා තේරුම් ගන්න සාමාන්‍ය Neural Network එකකට අමාරුයි. මොකද, ඒකට කලින් ආපු වචන මතක තියාගන්න "memory" එකක් නැති නිසා.

RNNs වල විශේෂත්වය තමයි ඒවට "memory" එකක් තියෙන එක. මේ memory එක තමයි "hidden state" එක කියලා හඳුන්වන්නේ. මේ hidden state එක කලින් වෙච්ච දේවල් මතක තියාගෙන, ඊළඟ input එක process කරන්න උදව් කරනවා. හරියට අපි කතාවක් අහනකොට, කලින් කිව්ව දේවල් මතක තියාගෙන තමයි ඊළඟට කියන දේ තේරුම් ගන්නේ. RNNs වැඩ කරන්නෙත් ඒ වගේ. මේක අපිට මෙහෙම හිතන්න පුළුවන්:

  • Input එකක් එනවා.
  • RNN එක ඒක process කරනවා.
  • Output එකක් දෙනවා, ඒ වගේම ඊළඟට එන input එකට උදව් වෙන්න "hidden state" එකක් හදාගෙන ඒක මතක තියාගන්නවා.
  • ඊළඟ input එක එනකොට, කලින් හදාගත්තු "hidden state" එකත් එක්ක තමයි ඒක process කරන්නේ.

මේ ක්‍රියාවලිය ටිකක් ගණිතමය වශයෙන් බලමු. සරල RNN Cell එකක් මෙහෙම විස්තර කරන්න පුළුවන්:

h_t = tanh(W_hh * h_{t-1} + W_xh * x_t + b_h)
y_t = W_hy * h_t + b_y

මෙහිදී:

  • x_t කියන්නේ වර්තමාන input එක (current input).
  • h_t කියන්නේ වර්තමාන hidden state එක (current hidden state).
  • h_{t-1} කියන්නේ කලින් hidden state එක (previous hidden state).
  • W_hh, W_xh, W_hy කියන්නේ weights (මේවා training කරනකොට adjust වෙනවා).
  • b_h, b_y කියන්නේ biases.
  • tanh කියන්නේ activation function එකක්.
  • y_t කියන්නේ වර්තමාන output එක (current output).

මේ formula එකෙන් පෙන්නුම් කරන්නේ, වර්තමාන hidden state එක හදන්න, කලින් hidden state එකත්, වර්තමාන input එකත් දෙකම පාවිච්චි කරන බවයි. මේක තමයි RNNs වල "recurrent" (පුනරාවර්තන) ස්වභාවය.

RNNs වල වාසි:

  • Sequence data (කාලයත් එක්ක වෙනස් වෙන දත්ත) effectively handle කරන්න පුළුවන්.
  • Text, speech වගේ දේවල් වල තියෙන context එක තේරුම් ගන්න පුළුවන්.

RNNs වල අවාසි:

  • Vanishing/Exploding Gradient Problem: මේක තමයි ලොකුම ගැටලුව. RNNs වලට ඈත අතීතයේ තියෙන දත්ත (long-term dependencies) මතක තියාගන්න අමාරුයි. අපි මේ ගැන ඊළඟට කතා කරමු.
  • සමහර වෙලාවට train කරන්න අමාරුයි.

RNNs වල සීමාවන් සහ LSTMs, GRUs වල මැජික් එක

Vanishing/Exploding Gradient Problem - මතක නැතිවීම සහ අධි උත්තේජනය

RNNs වලදී, network එක train කරනකොට Backpropagation Through Time (BPTT) කියන algorithm එකක් පාවිච්චි කරනවා. මේකෙන් වෙන්නේ network එකේ weights update කරන එක. හැබැයි, sequence එක දිග වැඩිවෙනකොට, gradient (weights කොච්චර වෙනස් කරන්න ඕනෙද කියලා කියන අගය) එක හරිම පොඩි වෙලා හෝ හරිම ලොකු වෙලා weights හරියට update වෙන්නේ නැති වෙන්න පුළුවන්.

  • Vanishing Gradient: gradient එක හරිම පොඩි වුණාම, network එකේ layers වලට කලින් වෙච්ච දේවල් වල බලපෑම සම්පූර්ණයෙන්ම වගේ නැතිවෙලා යනවා. ඒ කියන්නේ, "long-term dependencies" (ඈත අතීතයේ දත්ත) මතක තියාගන්න අමාරු වෙනවා.
  • Exploding Gradient: gradient එක හරිම ලොකු වුණාම, weights එකපාරටම හුඟක් වෙනස් වෙලා, network එක destabilize වෙන්න පුළුවන්. මේකෙන් training process එක අසාර්ථක වෙනවා.

මේ ප්‍රශ්න නිසා, සාමාන්‍ය RNNs වලට සෑහෙන්න දිග sequence එකක් analyse කරන්න අමාරුයි.

Long Short-Term Memory (LSTM) Networks - මතකයට ගේට්ටු

RNNs වල තිබුණු Vanishing Gradient Problem එකට විසඳුමක් විදිහට තමයි Long Short-Term Memory (LSTM) Networks බිහිවෙන්නේ. 1997 දී Sepp Hochreiter සහ Jürgen Schmidhuber විසින් මේවා හඳුන්වා දුන්නා. LSTMs වල තියෙන විශේෂත්වය තමයි ඒවට "cell state" කියන දිගු කාලීන මතකයක් (long-term memory) සහ ඒ මතකය පාලනය කරන්න "gates" කියන යාන්ත්‍රණයක් තියෙන එක.

අපි මේ "gates" තුන ගැන බලමු:

  1. Forget Gate (අමතක කිරීමේ ගේට්ටුව): මේ ගේට්ටුව තීරණය කරන්නේ කලින් cell state එකෙන් මොනවද අමතක කරන්න ඕනේ කියලා. මේක sigmoid function එකක් පාවිච්චි කරලා 0ත් 1ත් අතර අගයක් දෙනවා. 0 නම් සම්පූර්ණයෙන්ම අමතක කරනවා, 1 නම් සම්පූර්ණයෙන්ම මතක තියාගන්නවා.
  2. Input Gate (ඇතුළු කිරීමේ ගේට්ටුව): මේ ගේට්ටුව තීරණය කරන්නේ අලුතෙන් cell state එකට මොනවද එකතු කරන්න ඕනේ කියලා. මේකට කොටස් දෙකක් තියෙනවා:මේ දෙක එකතු වෙලා තමයි අලුත් තොරතුරු cell state එකට එකතු වෙන්නේ.
    • sigmoid layer එකකින් මොනවද update කරන්න ඕනේ කියලා තීරණය කරනවා.
    • tanh layer එකකින් අලුත් candidate values (අගයන්) ටිකක් හදනවා.
  3. Output Gate (ප්‍රතිදාන ගේට්ටුව): මේ ගේට්ටුව තීරණය කරන්නේ වර්තමාන hidden state එක (output) විදිහට මොනවද දෙන්න ඕනේ කියලා. මේකත් sigmoid layer එකකින් cell state එකේ මොන කොටසද output කරන්න ඕනේ කියලා තීරණය කරලා, tanh function එකකින් cell state එක transform කරලා final output එක දෙනවා.

මේ ගේට්ටු තුනෙන් වෙන්නේ, LSTM Network එකකට අවශ්‍ය තොරතුරු දිගු කාලීනව මතක තියාගන්නත්, අනවශ්‍ය තොරතුරු අමතක කරන්නත්, වර්තමාන task එකට අදාළ තොරතුරු පමණක් output කරන්නත් හැකියාව ලැබෙන එක. මේ නිසා LSTMs වලට "long-term dependencies" effectively handle කරන්න පුළුවන්.

Gated Recurrent Units (GRUs) - සරල කළ මතකය

Gated Recurrent Units (GRUs) කියන්නේ LSTMs වලට වඩා ටිකක් සරල, ඒ වගේම 2014 දී Kyunghyun Cho et al. විසින් හඳුන්වා දුන්, තවත් Recurrent Neural Network architecture එකක්. GRUs වල LSTMs වල වගේ "cell state" එකක් නැහැ. ඒ වෙනුවට "hidden state" එකම දිගු කාලීන මතකය විදිහට ක්‍රියා කරනවා. ඒ වගේම, මේවාට තියෙන්නේ gates දෙකක් විතරයි:

  1. Update Gate: මේ ගේට්ටුව "forget gate" එකයි "input gate" එකයි දෙකේම වැඩ කරනවා. ඒ කියන්නේ, කලින් hidden state එකෙන් මොනවද අමතක කරන්න ඕනේ, ඒ වගේම අලුත් තොරතුරු වලින් මොනවද එකතු කරන්න ඕනේ කියලා මේ ගේට්ටුව තීරණය කරනවා.
  2. Reset Gate: මේ ගේට්ටුව තීරණය කරන්නේ කලින් hidden state එකේ මොන කොටස්ද වර්තමාන input එකත් එක්ක ඒකාබද්ධ කරන්න ඕනේ කියලා. මේක කලින් hidden state එකේ වැදගත්කම "reset" කරන්න වගේ වැඩ කරනවා.

GRUs LSTMs වලට වඩා සරල නිසා, ඒවට අඩු parameters ප්‍රමාණයක් තියෙනවා. මේ නිසා GRUs train කරන්න LSTMs වලට වඩා ඉක්මන් වෙන්න පුළුවන්, විශේෂයෙන්ම dataset එක පොඩි නම්. සමහර වෙලාවට LSTMs වලට සමාන performance එකක් GRUs වලින් ලබාගන්නත් පුළුවන්.

Sequence Modeling වල Practical ප්‍රයෝජන සහ Python Code Example එකක්

RNNs, LSTMs, GRUs කියන දේවල් තේරුම් ගත්තාට, ඒවා මොනවටද පාවිච්චි කරන්නේ කියලා දැනගන්න එකත් වැදගත් නේද? මේවාගේ practical ප්‍රයෝජන සෑහෙන්න වැඩියි.

ජීවිතේට සමීප උදාහරණ

  • Natural Language Processing (NLP):
    • Machine Translation: Google Translate වගේ සේවාවන් වලදී එක භාෂාවකින් තව භාෂාවකට පරිවර්තනය කරන්න මේවා පාවිච්චි කරනවා. වාක්‍යයක වචන අනුපිළිවෙලක් විදිහට analyse කරලා තමයි මේක කරන්නේ.
    • Text Generation: ChatGPT, chatbots වගේ දේවල් වලට අලුත් පෙළ (text) හදන්න පුළුවන් වෙන්නේ මේ techniques නිසා.
    • Speech Recognition: Siri, Alexa වගේ virtual assistants වලට අපේ කටහඬ හඳුනාගන්න පුළුවන් වෙන්නේ මේ RNN-based models නිසා.
    • Sentiment Analysis: සමාජ මාධ්‍ය වල comment එකකින් කෙනෙක්ගේ සිතුවිලි (positive, negative, neutral) හඳුනාගන්න පුළුවන්.
  • Time Series Prediction:
    • Stock market prediction (කොටස් වෙළඳපොල අනාගතය කීම).
    • Weather forecasting (කාලගුණ අනාවැකි).
  • Video Analysis:
    • Video එකක් ඇතුළේ වෙන ක්‍රියා (action recognition) හඳුනාගැනීම.

Code Example: සරල LSTM එකක් පාවිච්චි කරලා Text Generation (Python/Keras)

දැන් අපි බලමු මේ concepts එකක් code එකකින් කොහොමද ක්‍රියාත්මක කරන්නේ කියලා. අපි මෙතනදී සරල character-level text generation උදාහරණයක් පාවිච්චි කරනවා. ඒ කියන්නේ, දීලා තියෙන අකුරු ටිකක් පාවිච්චි කරලා ඊළඟට එන්න පුළුවන් අකුර මොකක්ද කියලා LSTM එකකින් predict කරන එක.

අපි Python වල TensorFlow/Keras Library එක පාවිච්චි කරනවා. මේක ඉතාමත් user-friendly framework එකක්.

import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
from tensorflow.keras.utils import to_categorical

# 1. Sample Text Data - අපි 'ලංකා' කියන සිංහල වචනය පාවිච්චි කරමු
text = "ලංකා"
chars = sorted(list(set(text))) # Unique අකුරු
char_to_int = dict((c, i) for i, c in enumerate(chars)) # අකුරක් අංකයකට map කිරීම
int_to_char = dict((i, c) for i, c in enumerate(chars)) # අංකයක් අකුරකට map කිරීම

n_chars = len(text)
n_vocab = len(chars) # Unique අකුරු ගාන

print(f"Total Characters: {n_chars}")
print(f"Total Unique Characters (Vocabulary Size): {n_vocab}")
print(f"Character to Integer Mapping: {char_to_int}")

# 2. Prepare dataset of input to output pairs encoded as integers
# අපි මෙතනදී sequence_length එක 1ක් විදිහට ගමු, ඒ කියන්නේ එක අකුරකින් ඊළඟ අකුර predict කරනවා.
seq_length = 1
dataX = [] # Input sequences
dataY = [] # Output characters (what comes next)

for i in range(0, n_chars - seq_length, 1):
    seq_in = text[i:i + seq_length] # Input: e.g., 'ල'
    seq_out = text[i + seq_length]  # Output: e.g., 'ං'
    dataX.append([char_to_int[char] for char in seq_in])
    dataY.append(char_to_int[seq_out])

print(f"\nExample Input Sequences (Integer Encoded): {dataX}")
print(f"Example Output Characters (Integer Encoded): {dataY}")

# 3. Reshape input to be [samples, time steps, features]
# LSTM වලට 3D input එකක් ඕනේ. [Number of Samples, Time Steps (sequence_length), Number of Features (1)]
X = np.reshape(dataX, (len(dataX), seq_length, 1))
# Normalize input - 0ත් 1ත් අතර අගයන්ට convert කරනවා.
X = X / float(n_vocab)
# One hot encode the output variable - output එක categorical format එකට.
y = to_categorical(dataY)

print(f"\nInput Shape (X): {X.shape}")
print(f"Output Shape (y): {y.shape}")

# 4. Define the LSTM Model
model = Sequential()
model.add(LSTM(128, input_shape=(X.shape[1], X.shape[2]))) # LSTM layer එකක්. 128 units කියන්නේ මතක තියාගන්න පුළුවන් දේවල් ප්‍රමාණය.
model.add(Dense(y.shape[1], activation='softmax')) # Output layer එක. Softmax වලින් probabilities දෙනවා.
model.compile(loss='categorical_crossentropy', optimizer='adam') # Model එක compile කරනවා. Loss function, optimizer.

print("\nModel Summary:")
model.summary()

# 5. Train the Model (for demonstration, limited epochs)
# අපි පොඩි dataset එකක් නිසා, පොඩි epochs ගානකින් උදාහරණය පෙන්වමු.
# Real world applications වලට වැඩි epochs ප්‍රමාණයක් ඕනේ.
model.fit(X, y, epochs=200, batch_size=1, verbose=0)
print("\nModel Trained Successfully!")

# 6. Generate Characters
# මුලින්ම predict කරන්න පටන් ගන්න initial pattern එකක් ගන්නවා.
start_index = 0
pattern = dataX[start_index] # e.g., [char_to_int['ල']]
generated_text = "".join([int_to_char[value[0]] for value in pattern]) # 'ල'

print(f"\n--- Seed: '{generated_text}' ---")

# ඊළඟට අකුරු generate කරමු.
for i in range(n_chars - seq_length): # අපි text එකේ දිගටම generate කරන්න බලමු.
    x = np.reshape(pattern, (1, seq_length, 1)) # Input එක LSTM එකට දෙන විදිහට reshape කරනවා.
    x = x / float(n_vocab) # Normalize කරනවා.
    prediction = model.predict(x, verbose=0) # ඊළඟ අකුරේ probability predict කරනවා.
    index = np.argmax(prediction) # වැඩිම probability තියෙන අකුර තෝරනවා.
    result = int_to_char[index] # අංකය අකුරකට convert කරනවා.
    generated_text += result # Generate කරපු අකුර text එකට එකතු කරනවා.
    pattern.append(index) # Pattern එක update කරනවා.
    pattern = pattern[1:len(pattern)] # පරණම අකුර අයින් කරලා අලුත් අකුර දානවා (sliding window).

print(f"--- Generated: '{generated_text}' ---")

මේ code එකෙන් වෙන්නේ, "ලංකා" කියන වචනයට LSTM එකක් train කරලා, ඒක පාවිච්චි කරලා ආයෙත් "ලංකා" කියන වචනය generate කරන්න උත්සාහ කරන එක. dataset එක ගොඩක් පොඩි නිසා, සමහර විට හරියටම "ලංකා" කියලා එන්නේ නැති වෙන්න පුළුවන්, හැබැයි RNN එකේ sequence learning capacity එක තේරුම් ගන්න මේක හොඳ උදාහරණයක්.

Code එකෙන් ඉගෙන ගත හැකි දේ:

  • RNNs වලට data prepare කරන හැටි (integer encoding, one-hot encoding, reshaping).
  • Keras framework එකෙන් LSTM model එකක් define කරන හැටි.
  • Model එක train කරලා predict කරන හැටි.

LSTM ද GRU ද? තෝරාගන්නේ කොහොමද?

හරි, දැන් අපි RNNs, LSTMs, GRUs ගැන ඉගෙන ගත්තා. හැබැයි මොන model එකද තෝරාගන්නේ කියලා ප්‍රශ්නයක් එන්න පුළුවන්. මෙන්න ඒ ගැන සරල මගපෙන්වීමක්:

  • LSTM Networks:
    • GRUs වලට වඩා සංකීර්ණයි, parameters ගාන වැඩියි.
    • ඉතා දිගු sequence (long sequences) වල, විශේෂයෙන්ම මතකය (memory) ගොඩක් වැදගත් වන අවස්ථාවලදී හොඳින් ක්‍රියා කරන්න පුළුවන්.
    • Training කරන්න ටිකක් වැඩි කාලයක් යන්න පුළුවන්.
  • GRU Networks:
    • LSTMs වලට වඩා සරලයි, parameters ගාන අඩුයි.
    • Training කරන්න ඉක්මන්.
    • බොහෝ අවස්ථාවලදී LSTMs වලට සමාන හෝ ඊට ආසන්න performance එකක් ලබා දෙනවා, විශේෂයෙන්ම dataset එක එතරම් විශාල නැති අවස්ථාවලදී.
    • සැලකිය යුතු තරම් computational resources නොමැති විට හෝ training speed වැදගත් වන විට හොඳ තේරීමක්.

සාරාංශයක් විදිහට:

මුලින්ම GRU එකක් පාවිච්චි කරලා බලන්න. ඒක සරලයි, ඉක්මන්. performance එක මදි වුණොත්, එහෙම නැත්නම් ඔයාගේ problem එකට ඉතා දිගු මතකයක් (long-term memory) අවශ්‍ය නම් LSTM එකකට මාරු වෙන්න පුළුවන්. අන්තිමට, හැමවිටම experimentation තමයි හොඳම විසඳුම! ඔයාගේ දත්ත (data) සහ problem එකට වඩාත්ම ගැලපෙන්නේ මොකක්ද කියලා හොයාගන්න විවිධ model test කරලා බලන්න වෙනවා.

ඔබේ AI ගමනට අලුත් පියවරක්!

ඉතින් යාලුවනේ, අද අපි Recurrent Neural Networks (RNNs), ඒවායේ ගැටළු, සහ ඒ ගැටළු විසඳන්න ආපු Long Short-Term Memory (LSTMs) සහ Gated Recurrent Units (GRUs) කියන බලවත් tools ගැන ගොඩක් දේවල් ඉගෙන ගත්තා. Sequence Modeling කියන AI Field එකේ ගොඩක් වැදගත් සංකල්පයක්. අපි දැක්කා මේවා Natural Language Processing, Time Series Prediction වගේ දේවල් වලට කොච්චර ප්‍රයෝජනවත්ද කියලා.

අපි මතක තියාගන්න ඕනෙ ප්‍රධාන දේවල්:

  • RNNs වලට "memory" එකක් තියෙනවා (hidden state), ඒක කලින් දත්ත මතක තියාගන්න උදව් වෙනවා.
  • ඒත් RNNs වලට "long-term dependencies" මතක තියාගන්න අමාරුයි (Vanishing Gradient Problem).
  • LSTMs සහ GRUs කියන්නේ මේ ගැටලුවට විසඳුම්. ඒවාට "gates" තියෙනවා මතකය පාලනය කරන්න.
  • LSTMs වලට "cell state" එකක් තියෙනවා, GRUs වලට gates අඩුයි, ඒක නිසා ටිකක් සරලයි.

මේ දැනුම ඔයාට AI Field එකේ තව දුරටත් ගොඩක් දේවල් ඉගෙන ගන්න උදව් වෙයි කියලා අපි හිතනවා. නිකම්ම කියවලා නවතින්න එපා! මේ concepts තව දුරටත් research කරන්න, අපි දීපු code example එක modify කරලා බලන්න. ඔයාගේම data set එකක් අරගෙන model එකක් train කරන්න උත්සාහ කරන්න.

ඔයාගේ අත්දැකීම්, ප්‍රශ්න, අදහස් මොනවද කියලා comment section එකේ ලියන්න අමතක කරන්න එපා. අපි හැමෝම එකතු වෙලා මේ AI Field එකේ ඉදිරියට යමු! තවත් මේ වගේ tutorials එක්ක ඉක්මනින්ම හම්බවෙමු! ඔබට ජය!