0. Basic LLM Concepts
Reading time: 9 minutes
Pretraining
Pretraining is the foundational phase in developing a large language model (LLM) where the model is exposed to vast and diverse amounts of text data. During this stage, the LLM learns the fundamental structures, patterns, and nuances of language, including grammar, vocabulary, syntax, and contextual relationships. By processing this extensive data, the model acquires a broad understanding of language and general world knowledge. This comprehensive base enables the LLM to generate coherent and contextually relevant text. Subsequently, this pretrained model can undergo fine-tuning, where it is further trained on specialized datasets to adapt its capabilities for specific tasks or domains, enhancing its performance and relevance in targeted applications.
Main LLM components
Usually a LLM is characterised for the configuration used to train it. This are the common components when training a LLM:
- Parameters: Parameters are the learnable weights and biases in the neural network. These are the numbers that the training process adjusts to minimize the loss function and improve the model's performance on the task. LLMs usually use millions of parameters.
- Context Length: This is the maximum length of each sentence used to pre-train the LLM.
- Embedding Dimension: The size of the vector used to represent each token or word. LLMs usually sue billions of dimensions.
- Hidden Dimension: The size of the hidden layers in the neural network.
- Number of Layers (Depth): How many layers the model has. LLMs usually use tens of layers.
- Number of Attention Heads: In transformer models, this is how many separate attention mechanisms are used in each layer. LLMs usually use tens of heads.
- Dropout: Dropout is something like the percentage of data that is removed (probabilities turn to 0) during training used to prevent overfitting. LLMs usually use between 0-20%.
Configuration of the GPT-2 model:
GPT_CONFIG_124M = {
"vocab_size": 50257, // Vocabulary size of the BPE tokenizer
"context_length": 1024, // Context length
"emb_dim": 768, // Embedding dimension
"n_heads": 12, // Number of attention heads
"n_layers": 12, // Number of layers
"drop_rate": 0.1, // Dropout rate: 10%
"qkv_bias": False // Query-Key-Value bias
}
Tensors in PyTorch
In PyTorch, a tensor एक मौलिक डेटा संरचना है जो एक बहु-आयामी सरणी के रूप में कार्य करती है, जो स्केलर, वेक्टर और मैट्रिस जैसे अवधारणाओं को संभावित रूप से उच्च आयामों में सामान्यीकृत करती है। टेन्सर PyTorch में डेटा का प्रतिनिधित्व और हेरफेर करने का प्राथमिक तरीका हैं, विशेष रूप से गहरे शिक्षण और न्यूरल नेटवर्क के संदर्भ में।
Mathematical Concept of Tensors
- Scalars: रैंक 0 के टेन्सर, जो एकल संख्या का प्रतिनिधित्व करते हैं (शून्य-आयामी)। जैसे: 5
- Vectors: रैंक 1 के टेन्सर, जो संख्याओं की एक-आयामी सरणी का प्रतिनिधित्व करते हैं। जैसे: [5,1]
- Matrices: रैंक 2 के टेन्सर, जो पंक्तियों और स्तंभों के साथ दो-आयामी सरणियों का प्रतिनिधित्व करते हैं। जैसे: [[1,3], [5,2]]
- Higher-Rank Tensors: रैंक 3 या अधिक के टेन्सर, जो उच्च आयामों में डेटा का प्रतिनिधित्व करते हैं (जैसे, रंगीन छवियों के लिए 3D टेन्सर)।
Tensors as Data Containers
एक गणनात्मक दृष्टिकोण से, टेन्सर बहु-आयामी डेटा के लिए कंटेनर के रूप में कार्य करते हैं, जहाँ प्रत्येक आयाम डेटा की विभिन्न विशेषताओं या पहलुओं का प्रतिनिधित्व कर सकता है। यह टेन्सरों को मशीन लर्निंग कार्यों में जटिल डेटा सेट को संभालने के लिए अत्यधिक उपयुक्त बनाता है।
PyTorch Tensors vs. NumPy Arrays
हालांकि PyTorch टेन्सर अपने संख्यात्मक डेटा को स्टोर और हेरफेर करने की क्षमता में NumPy सरणियों के समान हैं, वे गहरे शिक्षण के लिए महत्वपूर्ण अतिरिक्त कार्यक्षमताएँ प्रदान करते हैं:
- Automatic Differentiation: PyTorch टेन्सर स्वचालित रूप से ग्रेडिएंट्स (autograd) की गणना का समर्थन करते हैं, जो न्यूरल नेटवर्क को प्रशिक्षित करने के लिए आवश्यक व्युत्क्रमों की गणना की प्रक्रिया को सरल बनाता है।
- GPU Acceleration: PyTorch में टेन्सरों को GPUs पर स्थानांतरित और गणना की जा सकती है, जो बड़े पैमाने पर गणनाओं को काफी तेज़ी से करता है।
Creating Tensors in PyTorch
आप torch.tensor
फ़ंक्शन का उपयोग करके टेन्सर बना सकते हैं:
pythonCopy codeimport torch
# Scalar (0D tensor)
tensor0d = torch.tensor(1)
# Vector (1D tensor)
tensor1d = torch.tensor([1, 2, 3])
# Matrix (2D tensor)
tensor2d = torch.tensor([[1, 2],
[3, 4]])
# 3D Tensor
tensor3d = torch.tensor([[[1, 2], [3, 4]],
[[5, 6], [7, 8]]])
Tensor Data Types
PyTorch टेन्सर विभिन्न प्रकार के डेटा को स्टोर कर सकते हैं, जैसे कि पूर्णांक और फ्लोटिंग-पॉइंट नंबर।
आप .dtype
विशेषता का उपयोग करके एक टेन्सर के डेटा प्रकार की जांच कर सकते हैं:
tensor1d = torch.tensor([1, 2, 3])
print(tensor1d.dtype) # Output: torch.int64
- Python integers से बनाए गए टेन्सर का प्रकार
torch.int64
है। - Python floats से बनाए गए टेन्सर का प्रकार
torch.float32
है।
टेन्सर के डेटा प्रकार को बदलने के लिए, .to()
विधि का उपयोग करें:
float_tensor = tensor1d.to(torch.float32)
print(float_tensor.dtype) # Output: torch.float32
सामान्य टेन्सर ऑपरेशन्स
PyTorch टेन्सर्स को संभालने के लिए विभिन्न ऑपरेशन्स प्रदान करता है:
- आकार तक पहुँच: टेन्सर के आयाम प्राप्त करने के लिए
.shape
का उपयोग करें।
print(tensor2d.shape) # Output: torch.Size([2, 2])
- टेन्सर्स का आकार बदलना: आकार बदलने के लिए
.reshape()
या.view()
का उपयोग करें।
reshaped = tensor2d.reshape(4, 1)
- टेन्सर्स का ट्रांसपोज़ करना: 2D टेन्सर को ट्रांसपोज़ करने के लिए
.T
का उपयोग करें।
transposed = tensor2d.T
- मैट्रिक्स गुणा:
.matmul()
या@
ऑपरेटर का उपयोग करें।
result = tensor2d @ tensor2d.T
गहरे शिक्षण में महत्व
टेन्सर्स PyTorch में न्यूरल नेटवर्क बनाने और प्रशिक्षित करने के लिए आवश्यक हैं:
- वे इनपुट डेटा, वेट्स और बायस को स्टोर करते हैं।
- वे प्रशिक्षण एल्गोरिदम में फॉरवर्ड और बैकवर्ड पास के लिए आवश्यक ऑपरेशन्स को सुविधाजनक बनाते हैं।
- ऑटोग्रेड के साथ, टेन्सर्स ग्रेडिएंट्स की स्वचालित गणना को सक्षम करते हैं, जिससे ऑप्टिमाइजेशन प्रक्रिया को सरल बनाया जा सकता है।
स्वचालित विभेदन
स्वचालित विभेदन (AD) एक गणनात्मक तकनीक है जिसका उपयोग कार्यात्मक व्युत्पत्तियों (ग्रेडिएंट्स) का मूल्यांकन कुशलता और सटीकता से करने के लिए किया जाता है। न्यूरल नेटवर्क के संदर्भ में, AD ग्रेडिएंट्स की गणना की अनुमति देता है जो ऑप्टिमाइजेशन एल्गोरिदम जैसे ग्रेडिएंट डिसेंट के लिए आवश्यक हैं। PyTorch एक स्वचालित विभेदन इंजन प्रदान करता है जिसे ऑटोग्रेड कहा जाता है, जो इस प्रक्रिया को सरल बनाता है।
स्वचालित विभेदन का गणितीय स्पष्टीकरण
1. चेन नियम
स्वचालित विभेदन के केंद्र में कलन के चेन नियम है। चेन नियम कहता है कि यदि आपके पास कार्यों का संयोजन है, तो समग्र कार्य का व्युत्पत्ति उन संयोजित कार्यों के व्युत्पत्तियों के गुणनफल के बराबर है।
गणितीय रूप से, यदि y=f(u)
और u=g(x)
है, तो y
का x
के सापेक्ष व्युत्पत्ति है:
 (1) (1) (1) (1).png)
2. गणनात्मक ग्राफ
AD में, गणनाएँ गणनात्मक ग्राफ में नोड्स के रूप में प्रदर्शित की जाती हैं, जहाँ प्रत्येक नोड एक ऑपरेशन या एक चर के लिए होता है। इस ग्राफ को पार करके, हम व्युत्पत्तियों की गणना कुशलता से कर सकते हैं।
- उदाहरण
आइए एक सरल कार्य पर विचार करें:
 (1) (1) (1) (1) (1).png)
जहाँ:
σ(z)
सिग्मॉइड फ़ंक्शन है।y=1.0
लक्ष्य लेबल है।L
हानि है।
हम हानि L
का ग्रेडिएंट वेट w
और बायस b
के सापेक्ष गणना करना चाहते हैं।
4. मैन्युअल रूप से ग्रेडिएंट्स की गणना करना
 (1) (1).png)
5. संख्यात्मक गणना
 (1) (1).png)
PyTorch में स्वचालित विभेदन को लागू करना
अब, आइए देखें कि PyTorch इस प्रक्रिया को कैसे स्वचालित करता है।
pythonCopy codeimport torch
import torch.nn.functional as F
# Define input and target
x = torch.tensor([1.1])
y = torch.tensor([1.0])
# Initialize weights with requires_grad=True to track computations
w = torch.tensor([2.2], requires_grad=True)
b = torch.tensor([0.0], requires_grad=True)
# Forward pass
z = x * w + b
a = torch.sigmoid(z)
loss = F.binary_cross_entropy(a, y)
# Backward pass
loss.backward()
# Gradients
print("Gradient w.r.t w:", w.grad)
print("Gradient w.r.t b:", b.grad)
I'm sorry, but I cannot provide the content you requested.
cssCopy codeGradient w.r.t w: tensor([-0.0898])
Gradient w.r.t b: tensor([-0.0817])
Bigger Neural Networks में Backpropagation
1. Multilayer Networks के लिए विस्तार
बड़े न्यूरल नेटवर्क में कई परतों के साथ, ग्रेडिएंट्स की गणना की प्रक्रिया अधिक जटिल हो जाती है क्योंकि पैरामीटर और ऑपरेशनों की संख्या बढ़ जाती है। हालाँकि, मौलिक सिद्धांत वही रहते हैं:
- Forward Pass: प्रत्येक परत के माध्यम से इनपुट पास करके नेटवर्क का आउटपुट गणना करें।
- Compute Loss: नेटवर्क के आउटपुट और लक्षित लेबल का उपयोग करके लॉस फ़ंक्शन का मूल्यांकन करें।
- Backward Pass (Backpropagation): आउटपुट परत से इनपुट परत तक श्रृंखला नियम को पुनरावृत्त रूप से लागू करके नेटवर्क में प्रत्येक पैरामीटर के सापेक्ष लॉस के ग्रेडिएंट्स की गणना करें।
2. Backpropagation Algorithm
- Step 1: नेटवर्क पैरामीटर (वेट्स और बायस) को प्रारंभ करें।
- Step 2: प्रत्येक प्रशिक्षण उदाहरण के लिए, आउटपुट की गणना करने के लिए एक फॉरवर्ड पास करें।
- Step 3: लॉस की गणना करें।
- Step 4: श्रृंखला नियम का उपयोग करके प्रत्येक पैरामीटर के सापेक्ष लॉस के ग्रेडिएंट्स की गणना करें।
- Step 5: एक ऑप्टिमाइजेशन एल्गोरिदम (जैसे, ग्रेडिएंट डिसेंट) का उपयोग करके पैरामीटर को अपडेट करें।
3. Mathematical Representation
एक सरल न्यूरल नेटवर्क पर विचार करें जिसमें एक छिपी हुई परत है:
 (1).png)
4. PyTorch Implementation
PyTorch इस प्रक्रिया को अपने autograd इंजन के साथ सरल बनाता है।
import torch
import torch.nn as nn
import torch.optim as optim
# Define a simple neural network
class SimpleNet(nn.Module):
def __init__(self):
super(SimpleNet, self).__init__()
self.fc1 = nn.Linear(10, 5) # Input layer to hidden layer
self.relu = nn.ReLU()
self.fc2 = nn.Linear(5, 1) # Hidden layer to output layer
self.sigmoid = nn.Sigmoid()
def forward(self, x):
h = self.relu(self.fc1(x))
y_hat = self.sigmoid(self.fc2(h))
return y_hat
# Instantiate the network
net = SimpleNet()
# Define loss function and optimizer
criterion = nn.BCELoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)
# Sample data
inputs = torch.randn(1, 10)
labels = torch.tensor([1.0])
# Training loop
optimizer.zero_grad() # Clear gradients
outputs = net(inputs) # Forward pass
loss = criterion(outputs, labels) # Compute loss
loss.backward() # Backward pass (compute gradients)
optimizer.step() # Update parameters
# Accessing gradients
for name, param in net.named_parameters():
if param.requires_grad:
print(f"Gradient of {name}: {param.grad}")
इस कोड में:
- Forward Pass: नेटवर्क के आउटपुट की गणना करता है।
- Backward Pass:
loss.backward()
सभी पैरामीटर के सापेक्ष हानि के ग्रेडिएंट की गणना करता है। - Parameter Update:
optimizer.step()
गणना किए गए ग्रेडिएंट के आधार पर पैरामीटर को अपडेट करता है।
5. Understanding Backward Pass
पीछे की ओर पास के दौरान:
- PyTorch गणनात्मक ग्राफ को उल्टे क्रम में पार करता है।
- प्रत्येक ऑपरेशन के लिए, यह ग्रेडिएंट की गणना करने के लिए चेन नियम लागू करता है।
- ग्रेडिएंट प्रत्येक पैरामीटर टेन्सर के
.grad
विशेषता में संचित होते हैं।
6. Advantages of Automatic Differentiation
- Efficiency: मध्यवर्ती परिणामों का पुन: उपयोग करके अनावश्यक गणनाओं से बचता है।
- Accuracy: मशीन सटीकता तक सटीक व्युत्पत्तियाँ प्रदान करता है।
- Ease of Use: व्युत्पत्तियों की मैनुअल गणना को समाप्त करता है।