# Deep Learning {{#include ../banners/hacktricks-training.md}} ## Deep Learning डीप लर्निंग मशीन लर्निंग का एक उपसमुच्चय है जो डेटा में जटिल पैटर्न को मॉडल करने के लिए कई परतों (डीप न्यूरल नेटवर्क) के साथ न्यूरल नेटवर्क का उपयोग करता है। इसने कंप्यूटर विज़न, प्राकृतिक भाषा प्रसंस्करण और भाषण पहचान सहित विभिन्न क्षेत्रों मेंRemarkable सफलता प्राप्त की है। ### Neural Networks न्यूरल नेटवर्क डीप लर्निंग के निर्माण खंड हैं। वे परतों में व्यवस्थित इंटरकनेक्टेड नोड्स (न्यूरॉन्स) से बने होते हैं। प्रत्येक न्यूरॉन इनपुट प्राप्त करता है, एक वेटेड सम लागू करता है, और एक आउटपुट उत्पन्न करने के लिए परिणाम को एक सक्रियण फ़ंक्शन के माध्यम से पास करता है। परतों को निम्नलिखित के रूप में वर्गीकृत किया जा सकता है: - **Input Layer**: पहली परत जो इनपुट डेटा प्राप्त करती है। - **Hidden Layers**: मध्यवर्ती परतें जो इनपुट डेटा पर परिवर्तन करती हैं। छिपी हुई परतों की संख्या और प्रत्येक परत में न्यूरॉन्स भिन्न हो सकते हैं, जिससे विभिन्न आर्किटेक्चर बनते हैं। - **Output Layer**: अंतिम परत जो नेटवर्क का आउटपुट उत्पन्न करती है, जैसे वर्गीकरण कार्यों में वर्ग संभावनाएँ। ### Activation Functions जब न्यूरॉन्स की एक परत इनपुट डेटा को संसाधित करती है, तो प्रत्येक न्यूरॉन इनपुट पर एक वेट और एक बायस लागू करता है (`z = w * x + b`), जहाँ `w` वेट है, `x` इनपुट है, और `b` बायस है। फिर न्यूरॉन का आउटपुट एक **सक्रियण फ़ंक्शन के माध्यम से पास किया जाता है ताकि मॉडल में गैर-रेखीयता पेश की जा सके**। यह सक्रियण फ़ंक्शन मूल रूप से यह संकेत करता है कि अगला न्यूरॉन "सक्रिय होना चाहिए और कितना"। यह नेटवर्क को डेटा में जटिल पैटर्न और संबंधों को सीखने की अनुमति देता है, जिससे यह किसी भी निरंतर फ़ंक्शन का अनुमान लगाने में सक्षम होता है। इसलिए, सक्रियण फ़ंक्शन न्यूरल नेटवर्क में गैर-रेखीयता पेश करते हैं, जिससे यह डेटा में जटिल संबंधों को सीखने की अनुमति मिलती है। सामान्य सक्रियण फ़ंक्शन में शामिल हैं: - **Sigmoid**: इनपुट मानों को 0 और 1 के बीच के रेंज में मैप करता है, अक्सर बाइनरी वर्गीकरण में उपयोग किया जाता है। - **ReLU (Rectified Linear Unit)**: यदि इनपुट सकारात्मक है तो इसे सीधे आउटपुट करता है; अन्यथा, यह शून्य आउटपुट करता है। इसे इसकी सरलता और गहरे नेटवर्क को प्रशिक्षित करने में प्रभावशीलता के कारण व्यापक रूप से उपयोग किया जाता है। - **Tanh**: इनपुट मानों को -1 और 1 के बीच के रेंज में मैप करता है, अक्सर छिपी हुई परतों में उपयोग किया जाता है। - **Softmax**: कच्चे स्कोर को संभावनाओं में परिवर्तित करता है, अक्सर बहु-वर्ग वर्गीकरण के लिए आउटपुट परत में उपयोग किया जाता है। ### Backpropagation बैकप्रोपगेशन वह एल्गोरिदम है जिसका उपयोग न्यूरल नेटवर्क को न्यूरॉन्स के बीच कनेक्शनों के वेट को समायोजित करके प्रशिक्षित करने के लिए किया जाता है। यह हानि फ़ंक्शन के ग्रेडिएंट की गणना करके काम करता है और वेट को ग्रेडिएंट के विपरीत दिशा में अपडेट करता है ताकि हानि को न्यूनतम किया जा सके। बैकप्रोपगेशन में शामिल चरण हैं: 1. **Forward Pass**: इनपुट को परतों के माध्यम से पास करके और सक्रियण फ़ंक्शन लागू करके नेटवर्क का आउटपुट गणना करें। 2. **Loss Calculation**: एक हानि फ़ंक्शन (जैसे, रिग्रेशन के लिए औसत वर्ग त्रुटि, वर्गीकरण के लिए क्रॉस-एंट्रॉपी) का उपयोग करके पूर्वानुमानित आउटपुट और सच्चे लक्ष्य के बीच हानि (त्रुटि) की गणना करें। 3. **Backward Pass**: कलन के श्रृंखला नियम का उपयोग करके प्रत्येक वेट के सापेक्ष हानि के ग्रेडिएंट की गणना करें। 4. **Weight Update**: हानि को न्यूनतम करने के लिए एक ऑप्टिमाइजेशन एल्गोरिदम (जैसे, स्टोकास्टिक ग्रेडिएंट डिसेंट, एडम) का उपयोग करके वेट को अपडेट करें। ## Convolutional Neural Networks (CNNs) कन्वोल्यूशनल न्यूरल नेटवर्क (CNNs) एक विशेष प्रकार का न्यूरल नेटवर्क है जिसे ग्रिड-जैसे डेटा, जैसे छवियों को संसाधित करने के लिए डिज़ाइन किया गया है। वे अपने स्पैटियल हायरार्की के फीचर्स को स्वचालित रूप से सीखने की क्षमता के कारण कंप्यूटर विज़न कार्यों में विशेष रूप से प्रभावी हैं। CNNs के मुख्य घटक शामिल हैं: - **Convolutional Layers**: स्थानीय विशेषताओं को निकालने के लिए इनपुट डेटा पर सीखने योग्य फ़िल्टर (कर्नेल) का उपयोग करके कन्वोल्यूशन ऑपरेशंस लागू करते हैं। प्रत्येक फ़िल्टर इनपुट पर स्लाइड करता है और एक डॉट प्रोडक्ट की गणना करता है, जिससे एक फीचर मैप उत्पन्न होता है। - **Pooling Layers**: महत्वपूर्ण विशेषताओं को बनाए रखते हुए उनके स्थानिक आयामों को कम करने के लिए फीचर मैप्स को डाउनसैंपल करते हैं। सामान्य पूलिंग ऑपरेशंस में मैक्स पूलिंग और एवरेज पूलिंग शामिल हैं। - **Fully Connected Layers**: एक परत में प्रत्येक न्यूरॉन को अगली परत में प्रत्येक न्यूरॉन से जोड़ते हैं, पारंपरिक न्यूरल नेटवर्क के समान। इन परतों का उपयोग आमतौर पर वर्गीकरण कार्यों के लिए नेटवर्क के अंत में किया जाता है। एक CNN के अंदर **`Convolutional Layers`**, हम निम्नलिखित के बीच भी अंतर कर सकते हैं: - **Initial Convolutional Layer**: पहली कन्वोल्यूशनल परत जो कच्चे इनपुट डेटा (जैसे, एक छवि) को संसाधित करती है और बुनियादी विशेषताओं जैसे किनारों और बनावटों की पहचान करने के लिए उपयोगी होती है। - **Intermediate Convolutional Layers**: अगली कन्वोल्यूशनल परतें जो प्रारंभिक परत द्वारा सीखी गई विशेषताओं पर निर्माण करती हैं, जिससे नेटवर्क को अधिक जटिल पैटर्न और प्रतिनिधित्व सीखने की अनुमति मिलती है। - **Final Convolutional Layer**: पूरी तरह से जुड़े परतों से पहले की अंतिम कन्वोल्यूशनल परतें, जो उच्च-स्तरीय विशेषताओं को कैप्चर करती हैं और वर्गीकरण के लिए डेटा को तैयार करती हैं। > [!TIP] > CNNs छवि वर्गीकरण, वस्तु पहचान, और छवि विभाजन कार्यों के लिए विशेष रूप से प्रभावी होते हैं क्योंकि वे ग्रिड-जैसे डेटा में विशेषताओं की स्थानिक हायरार्की को सीखने की क्षमता रखते हैं और वेट शेयरिंग के माध्यम से पैरामीटर की संख्या को कम करते हैं। > इसके अलावा, वे डेटा के साथ बेहतर काम करते हैं जो फीचर लोकैलिटी प्रिंसिपल का समर्थन करते हैं जहाँ पड़ोसी डेटा (पिक्सेल) अधिक संभावना है कि वे संबंधित हों बनिस्बत दूर के पिक्सेल के, जो अन्य प्रकार के डेटा जैसे पाठ के लिए नहीं हो सकता। > इसके अलावा, ध्यान दें कि CNNs जटिल विशेषताओं की पहचान करने में सक्षम होंगे लेकिन किसी भी स्थानिक संदर्भ को लागू नहीं कर पाएंगे, जिसका अर्थ है कि छवि के विभिन्न भागों में पाए जाने वाले समान विशेषता समान होगी। ### Example defining a CNN *यहाँ आपको PyTorch में एक कन्वोल्यूशनल न्यूरल नेटवर्क (CNN) को परिभाषित करने का विवरण मिलेगा जो 48x48 आकार के RGB छवियों के बैच के साथ शुरू होता है और विशेषताओं को निकालने के लिए कन्वोल्यूशनल परतों और मैक्सपूल का उपयोग करता है, इसके बाद वर्गीकरण के लिए पूरी तरह से जुड़े परतें होती हैं।* यहाँ आप PyTorch में 1 कन्वोल्यूशनल परत को परिभाषित कर सकते हैं: `self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1)`। - `in_channels`: इनपुट चैनलों की संख्या। RGB छवियों के मामले में, यह 3 है (प्रत्येक रंग चैनल के लिए एक)। यदि आप ग्रेस्केल छवियों के साथ काम कर रहे हैं, तो यह 1 होगा। - `out_channels`: आउटपुट चैनलों (फ़िल्टर) की संख्या जो कन्वोल्यूशनल परत सीखेगी। यह एक हाइपरपैरामीटर है जिसे आप अपने मॉडल आर्किटेक्चर के आधार पर समायोजित कर सकते हैं। - `kernel_size`: कन्वोल्यूशनल फ़िल्टर का आकार। एक सामान्य विकल्प 3x3 है, जिसका अर्थ है कि फ़िल्टर इनपुट छवि के 3x3 क्षेत्र को कवर करेगा। यह एक 3×3×3 रंग स्टाम्प की तरह है जिसका उपयोग in_channels से out_channels उत्पन्न करने के लिए किया जाता है: 1. उस 3×3×3 स्टाम्प को छवि क्यूब के शीर्ष-बाएँ कोने पर रखें। 2. प्रत्येक वेट को उसके नीचे के पिक्सेल से गुणा करें, सभी को जोड़ें, बायस जोड़ें → आपको एक संख्या मिलती है। 3. उस संख्या को एक खाली मैप में स्थिति (0, 0) पर लिखें। 4. स्टाम्प को एक पिक्सेल दाईं ओर स्लाइड करें (stride = 1) और तब तक दोहराएँ जब तक आप पूरे 48×48 ग्रिड को भर न दें। - `padding`: इनपुट के प्रत्येक पक्ष में जोड़े गए पिक्सेल की संख्या। पैडिंग इनपुट के स्थानिक आयामों को बनाए रखने में मदद करती है, जिससे आउटपुट आकार पर अधिक नियंत्रण मिलता है। उदाहरण के लिए, 3x3 कर्नेल के साथ 48x48 पिक्सेल इनपुट, 1 का पैडिंग कन्वोल्यूशन ऑपरेशन के बाद आउटपुट आकार को समान (48x48) बनाए रखेगा। इसका कारण यह है कि पैडिंग इनपुट छवि के चारों ओर 1 पिक्सेल की सीमा जोड़ती है, जिससे कर्नेल को किनारों पर स्लाइड करने की अनुमति मिलती है बिना स्थानिक आयामों को कम किए। फिर, इस परत में प्रशिक्षित करने योग्य पैरामीटर की संख्या है: - (3x3x3 (कर्नेल आकार) + 1 (बायस)) x 32 (out_channels) = 896 प्रशिक्षित करने योग्य पैरामीटर। ध्यान दें कि प्रत्येक कर्नेल के लिए एक बायस (+1) जोड़ा गया है क्योंकि प्रत्येक कन्वोल्यूशनल परत का कार्य इनपुट का एक रैखिक परिवर्तन सीखना है, जिसे समीकरण द्वारा दर्शाया गया है: ```plaintext Y = f(W * X + b) ``` जहाँ `W` वेट मैट्रिक्स है (सीखे गए फ़िल्टर, 3x3x3 = 27 पैरामीटर), `b` बायस वेक्टर है जो प्रत्येक आउटपुट चैनल के लिए +1 है। ध्यान दें कि `self.conv1 = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, padding=1)` का आउटपुट `(batch_size, 32, 48, 48)` आकार का टेन्सर होगा, क्योंकि 32 नए उत्पन्न चैनलों की संख्या है जो 48x48 पिक्सल के आकार के हैं। फिर, हम इस कन्वोल्यूशनल लेयर को दूसरे कन्वोल्यूशनल लेयर से जोड़ सकते हैं जैसे: `self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)`। जो जोड़ेगा: (32x3x3 (कर्नेल आकार) + 1 (बायस)) x 64 (out_channels) = 18,496 ट्रेन करने योग्य पैरामीटर और आउटपुट का आकार `(batch_size, 64, 48, 48)` होगा। जैसा कि आप देख सकते हैं, **पैरामीटर की संख्या प्रत्येक अतिरिक्त कन्वोल्यूशनल लेयर के साथ तेजी से बढ़ती है**, विशेष रूप से जब आउटपुट चैनलों की संख्या बढ़ती है। डेटा की मात्रा को नियंत्रित करने का एक विकल्प है कि प्रत्येक कन्वोल्यूशनल लेयर के बाद **मैक्स पूलिंग** का उपयोग किया जाए। मैक्स पूलिंग फीचर मैप्स के स्थानिक आयामों को कम करता है, जो पैरामीटर की संख्या और गणनात्मक जटिलता को कम करने में मदद करता है जबकि महत्वपूर्ण विशेषताओं को बनाए रखता है। इसे इस प्रकार घोषित किया जा सकता है: `self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)`। यह मूल रूप से 2x2 पिक्सल के ग्रिड का उपयोग करने और प्रत्येक ग्रिड से अधिकतम मान लेने का संकेत देता है ताकि फीचर मैप के आकार को आधा किया जा सके। इसके अलावा, `stride=2` का मतलब है कि पूलिंग ऑपरेशन एक बार में 2 पिक्सल आगे बढ़ेगा, इस मामले में, पूलिंग क्षेत्रों के बीच किसी भी ओवरलैप को रोकता है। इस पूलिंग लेयर के साथ, पहले कन्वोल्यूशनल लेयर के बाद आउटपुट आकार `(batch_size, 64, 24, 24)` होगा जब `self.pool1` को `self.conv2` के आउटपुट पर लागू किया जाएगा, जिससे आकार को पिछले लेयर के 1/4 तक कम किया जाएगा। > [!TIP] > यह महत्वपूर्ण है कि कन्वोल्यूशनल लेयर्स के बाद पूलिंग की जाए ताकि फीचर मैप्स के स्थानिक आयामों को कम किया जा सके, जो पैरामीटर की संख्या और गणनात्मक जटिलता को नियंत्रित करने में मदद करता है जबकि प्रारंभिक पैरामीटर महत्वपूर्ण विशेषताओं को सीखता है। > आप पूलिंग लेयर से पहले के कन्वोल्यूशन्स को इनपुट डेटा से विशेषताएँ निकालने के तरीके के रूप में देख सकते हैं (जैसे कि रेखाएँ, किनारे), यह जानकारी पूल किए गए आउटपुट में अभी भी मौजूद होगी, लेकिन अगली कन्वोल्यूशनल लेयर मूल इनपुट डेटा को नहीं देख पाएगी, केवल पूल किया गया आउटपुट, जो पिछले लेयर का एक कम किया गया संस्करण है जिसमें वह जानकारी है। > सामान्य क्रम में: `Conv → ReLU → Pool` प्रत्येक 2×2 पूलिंग विंडो अब फीचर सक्रियणों (“किनारा मौजूद / नहीं”) के साथ मुकाबला करती है, कच्चे पिक्सल तीव्रताओं के साथ नहीं। सबसे मजबूत सक्रियण को बनाए रखना वास्तव में सबसे महत्वपूर्ण सबूत को बनाए रखता है। फिर, आवश्यकतानुसार जितनी भी कन्वोल्यूशनल और पूलिंग लेयर्स जोड़ने के बाद, हम आउटपुट को फ्लैट कर सकते हैं ताकि इसे पूरी तरह से जुड़े लेयर्स में फीड किया जा सके। यह बैच में प्रत्येक नमूने के लिए टेन्सर को 1D वेक्टर में फिर से आकार देकर किया जाता है: ```python x = x.view(-1, 64*24*24) ``` और इस 1D वेक्टर के साथ जिसमें पिछले कन्वोल्यूशनल और पूलिंग लेयर्स द्वारा उत्पन्न सभी प्रशिक्षण पैरामीटर हैं, हम एक पूरी तरह से जुड़े लेयर को इस तरह परिभाषित कर सकते हैं: ```python self.fc1 = nn.Linear(64 * 24 * 24, 512) ``` जो पिछले लेयर के फ्लैट आउटपुट को लेगा और इसे 512 हिडन यूनिट्स पर मैप करेगा। ध्यान दें कि इस लेयर ने `(64 * 24 * 24 + 1 (bias)) * 512 = 3,221,504` ट्रेन करने योग्य पैरामीटर जोड़े हैं, जो संकुचन लेयर की तुलना में एक महत्वपूर्ण वृद्धि है। इसका कारण यह है कि पूरी तरह से जुड़े लेयर एक लेयर में हर न्यूरॉन को अगले लेयर के हर न्यूरॉन से जोड़ते हैं, जिससे पैरामीटर की संख्या बहुत अधिक हो जाती है। अंत में, हम अंतिम वर्ग लॉजिट्स उत्पन्न करने के लिए एक आउटपुट लेयर जोड़ सकते हैं: ```python self.fc2 = nn.Linear(512, num_classes) ``` यह `(512 + 1 (bias)) * num_classes` ट्रेन करने योग्य पैरामीटर जोड़ेगा, जहाँ `num_classes` वर्गीकरण कार्य में वर्गों की संख्या है (जैसे, GTSRB डेटासेट के लिए 43)। एक और सामान्य प्रथा यह है कि पूरी तरह से जुड़े परतों से पहले एक ड्रॉपआउट परत जोड़ी जाए ताकि ओवरफिटिंग को रोका जा सके। इसे इस तरह किया जा सकता है: ```python self.dropout = nn.Dropout(0.5) ``` इस परत में प्रशिक्षण के दौरान इनपुट यूनिट्स के एक अंश को यादृच्छिक रूप से शून्य पर सेट किया जाता है, जो विशिष्ट न्यूरॉन्स पर निर्भरता को कम करके ओवरफिटिंग को रोकने में मदद करता है। ### CNN कोड उदाहरण ```python import torch import torch.nn as nn import torch.nn.functional as F class MY_NET(nn.Module): def __init__(self, num_classes=32): super(MY_NET, self).__init__() # Initial conv layer: 3 input channels (RGB), 32 output channels, 3x3 kernel, padding 1 # This layer will learn basic features like edges and textures self.conv1 = nn.Conv2d( in_channels=3, out_channels=32, kernel_size=3, padding=1 ) # Output: (Batch Size, 32, 48, 48) # Conv Layer 2: 32 input channels, 64 output channels, 3x3 kernel, padding 1 # This layer will learn more complex features based on the output of conv1 self.conv2 = nn.Conv2d( in_channels=32, out_channels=64, kernel_size=3, padding=1 ) # Output: (Batch Size, 64, 48, 48) # Max Pooling 1: Kernel 2x2, Stride 2. Reduces spatial dimensions by half (1/4th of the previous layer). self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2) # Output: (Batch Size, 64, 24, 24) # Conv Layer 3: 64 input channels, 128 output channels, 3x3 kernel, padding 1 # This layer will learn even more complex features based on the output of conv2 # Note that the number of output channels can be adjusted based on the complexity of the task self.conv3 = nn.Conv2d( in_channels=64, out_channels=128, kernel_size=3, padding=1 ) # Output: (Batch Size, 128, 24, 24) # Max Pooling 2: Kernel 2x2, Stride 2. Reduces spatial dimensions by half again. # Reducing the dimensions further helps to control the number of parameters and computational complexity. self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2) # Output: (Batch Size, 128, 12, 12) # From the second pooling layer, we will flatten the output to feed it into fully connected layers. # The feature size is calculated as follows: # Feature size = Number of output channels * Height * Width self._feature_size = 128 * 12 * 12 # Fully Connected Layer 1 (Hidden): Maps flattened features to hidden units. # This layer will learn to combine the features extracted by the convolutional layers. self.fc1 = nn.Linear(self._feature_size, 512) # Fully Connected Layer 2 (Output): Maps hidden units to class logits. # Output size MUST match num_classes self.fc2 = nn.Linear(512, num_classes) # Dropout layer configuration with a dropout rate of 0.5. # This layer is used to prevent overfitting by randomly setting a fraction of the input units to zero during training. self.dropout = nn.Dropout(0.5) def forward(self, x): """ The forward method defines the forward pass of the network. It takes an input tensor `x` and applies the convolutional layers, pooling layers, and fully connected layers in sequence. The input tensor `x` is expected to have the shape (Batch Size, Channels, Height, Width), where: - Batch Size: Number of samples in the batch - Channels: Number of input channels (e.g., 3 for RGB images) - Height: Height of the input image (e.g., 48 for 48x48 images) - Width: Width of the input image (e.g., 48 for 48x48 images) The output of the forward method is the logits for each class, which can be used for classification tasks. Args: x (torch.Tensor): Input tensor of shape (Batch Size, Channels, Height, Width) Returns: torch.Tensor: Output tensor of shape (Batch Size, num_classes) containing the class logits. """ # Conv1 -> ReLU -> Conv2 -> ReLU -> Pool1 -> Conv3 -> ReLU -> Pool2 x = self.conv1(x) x = F.relu(x) x = self.conv2(x) x = F.relu(x) x = self.pool1(x) x = self.conv3(x) x = F.relu(x) x = self.pool2(x) # At this point, x has shape (Batch Size, 128, 12, 12) # Flatten the output to feed it into fully connected layers x = torch.flatten(x, 1) # Apply dropout to prevent overfitting x = self.dropout(x) # First FC layer with ReLU activation x = F.relu(self.fc1(x)) # Apply Dropout again x = self.dropout(x) # Final FC layer to get logits x = self.fc2(x) # Output shape will be (Batch Size, num_classes) # Note that the output is not passed through a softmax activation here, as it is typically done in the loss function (e.g., CrossEntropyLoss) return x ``` ### CNN कोड प्रशिक्षण उदाहरण निम्नलिखित कोड कुछ प्रशिक्षण डेटा बनाएगा और ऊपर परिभाषित `MY_NET` मॉडल को प्रशिक्षित करेगा। कुछ दिलचस्प मान नोट करने के लिए: - `EPOCHS` वह संख्या है जब मॉडल प्रशिक्षण के दौरान पूरे डेटासेट को देखेगा। यदि EPOCH बहुत छोटा है, तो मॉडल पर्याप्त नहीं सीख सकता है; यदि बहुत बड़ा है, तो यह ओवरफिट हो सकता है। - `LEARNING_RATE` ऑप्टिमाइज़र के लिए कदम का आकार है। एक छोटा लर्निंग रेट धीमी संकुचन की ओर ले जा सकता है, जबकि एक बड़ा इसे इष्टतम समाधान से अधिक कर सकता है और संकुचन को रोक सकता है। - `WEIGHT_DECAY` एक नियमितीकरण शब्द है जो बड़े वज़नों को दंडित करके ओवरफिटिंग को रोकने में मदद करता है। प्रशिक्षण लूप के संबंध में, यह कुछ दिलचस्प जानकारी है जो जानना आवश्यक है: - `criterion = nn.CrossEntropyLoss()` बहु-श्रेणी वर्गीकरण कार्यों के लिए उपयोग की जाने वाली हानि फ़ंक्शन है। यह एकल फ़ंक्शन में सॉफ्टमैक्स सक्रियण और क्रॉस-एंट्रॉपी हानि को संयोजित करता है, जिससे यह उन मॉडलों को प्रशिक्षित करने के लिए उपयुक्त बनाता है जो वर्ग लॉजिट्स आउटपुट करते हैं। - यदि मॉडल से अन्य प्रकार के आउटपुट की अपेक्षा की जाती, जैसे बाइनरी वर्गीकरण या रिग्रेशन, तो हम बाइनरी वर्गीकरण के लिए `nn.BCEWithLogitsLoss()` या रिग्रेशन के लिए `nn.MSELoss()` जैसी विभिन्न हानि फ़ंक्शंस का उपयोग करते। - `optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE, weight_decay=WEIGHT_DECAY)` एडे़म ऑप्टिमाइज़र को प्रारंभ करता है, जो गहरे शिक्षण मॉडलों को प्रशिक्षित करने के लिए एक लोकप्रिय विकल्प है। यह ग्रेडिएंट्स के पहले और दूसरे क्षणों के आधार पर प्रत्येक पैरामीटर के लिए लर्निंग रेट को अनुकूलित करता है। - अन्य ऑप्टिमाइज़र जैसे `optim.SGD` (स्टोकास्टिक ग्रेडिएंट डिसेंट) या `optim.RMSprop` का भी उपयोग किया जा सकता है, प्रशिक्षण कार्य की विशिष्ट आवश्यकताओं के आधार पर। - `model.train()` विधि मॉडल को प्रशिक्षण मोड में सेट करती है, जिससे ड्रॉपआउट और बैच सामान्यीकरण जैसी परतें प्रशिक्षण के दौरान मूल्यांकन की तुलना में अलग तरीके से व्यवहार करती हैं। - `optimizer.zero_grad()` बैकवर्ड पास से पहले सभी ऑप्टिमाइज़ किए गए टेन्सर्स के ग्रेडिएंट्स को साफ करता है, जो आवश्यक है क्योंकि PyTorch में डिफ़ॉल्ट रूप से ग्रेडिएंट्स जमा होते हैं। यदि साफ नहीं किया गया, तो पिछले पुनरावृत्तियों के ग्रेडिएंट्स वर्तमान ग्रेडिएंट्स में जोड़े जाएंगे, जिससे गलत अपडेट होंगे। - `loss.backward()` हानि के ग्रेडिएंट्स को मॉडल के पैरामीटर के संबंध में गणना करता है, जिन्हें फिर ऑप्टिमाइज़र द्वारा वज़नों को अपडेट करने के लिए उपयोग किया जाता है। - `optimizer.step()` गणना किए गए ग्रेडिएंट्स और लर्निंग रेट के आधार पर मॉडल के पैरामीटर को अपडेट करता है। ```python import torch, torch.nn.functional as F from torch import nn, optim from torch.utils.data import DataLoader from torchvision import datasets, transforms from tqdm import tqdm from sklearn.metrics import classification_report, confusion_matrix import numpy as np # --------------------------------------------------------------------------- # 1. Globals # --------------------------------------------------------------------------- IMG_SIZE = 48 # model expects 48×48 NUM_CLASSES = 10 # MNIST has 10 digits BATCH_SIZE = 64 # batch size for training and validation EPOCHS = 5 # number of training epochs LEARNING_RATE = 1e-3 # initial learning rate for Adam optimiser WEIGHT_DECAY = 1e-4 # L2 regularisation to prevent overfitting # Channel-wise mean / std for MNIST (grayscale ⇒ repeat for 3-channel input) MNIST_MEAN = (0.1307, 0.1307, 0.1307) MNIST_STD = (0.3081, 0.3081, 0.3081) # --------------------------------------------------------------------------- # 2. Transforms # --------------------------------------------------------------------------- # 1) Baseline transform: resize + tensor (no colour/aug/no normalise) transform_base = transforms.Compose([ transforms.Resize((IMG_SIZE, IMG_SIZE)), # 🔹 Resize – force all images to 48 × 48 so the CNN sees a fixed geometry transforms.Grayscale(num_output_channels=3), # 🔹 Grayscale→RGB – MNIST is 1-channel; duplicate into 3 channels for convnet transforms.ToTensor(), # 🔹 ToTensor – convert PIL image [0‒255] → float tensor [0.0‒1.0] ]) # 2) Training transform: augment + normalise transform_norm = transforms.Compose([ transforms.Resize((IMG_SIZE, IMG_SIZE)), # keep 48 × 48 input size transforms.Grayscale(num_output_channels=3), # still need 3 channels transforms.RandomRotation(10), # 🔹 RandomRotation(±10°) – small tilt ⇢ rotation-invariance, combats overfitting transforms.ColorJitter(brightness=0.2, contrast=0.2), # 🔹 ColorJitter – pseudo-RGB brightness/contrast noise; extra variety transforms.ToTensor(), # convert to tensor before numeric ops transforms.Normalize(mean=MNIST_MEAN, std=MNIST_STD), # 🔹 Normalize – zero-centre & scale so every channel ≈ N(0,1) ]) # 3) Test/validation transform: only resize + normalise (no aug) transform_test = transforms.Compose([ transforms.Resize((IMG_SIZE, IMG_SIZE)), # same spatial size as train transforms.Grayscale(num_output_channels=3), # match channel count transforms.ToTensor(), # tensor conversion transforms.Normalize(mean=MNIST_MEAN, std=MNIST_STD), # 🔹 keep test data on same scale as training data ]) # --------------------------------------------------------------------------- # 3. Datasets & loaders # --------------------------------------------------------------------------- train_set = datasets.MNIST("data", train=True, download=True, transform=transform_norm) test_set = datasets.MNIST("data", train=False, download=True, transform=transform_test) train_loader = DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True) test_loader = DataLoader(test_set, batch_size=256, shuffle=False) print(f"Training on {len(train_set)} samples, validating on {len(test_set)} samples.") # --------------------------------------------------------------------------- # 4. Model / loss / optimiser # --------------------------------------------------------------------------- device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = MY_NET(num_classes=NUM_CLASSES).to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE, weight_decay=WEIGHT_DECAY) # --------------------------------------------------------------------------- # 5. Training loop # --------------------------------------------------------------------------- for epoch in range(1, EPOCHS + 1): model.train() # Set model to training mode enabling dropout and batch norm running_loss = 0.0 # sums batch losses to compute epoch average correct = 0 # number of correct predictions total = 0 # number of samples seen # tqdm wraps the loader to show a live progress-bar per epoch for X_batch, y_batch in tqdm(train_loader, desc=f"Epoch {epoch}", leave=False): # 3-a) Move data to GPU (if available) ---------------------------------- X_batch, y_batch = X_batch.to(device), y_batch.to(device) # 3-b) Forward pass ----------------------------------------------------- logits = model(X_batch) # raw class scores (shape: [B, NUM_CLASSES]) loss = criterion(logits, y_batch) # 3-c) Backward pass & parameter update -------------------------------- optimizer.zero_grad() # clear old gradients loss.backward() # compute new gradients optimizer.step() # gradient → weight update # 3-d) Statistics ------------------------------------------------------- running_loss += loss.item() * X_batch.size(0) # sum of (batch loss × batch size) preds = logits.argmax(dim=1) # predicted class labels correct += (preds == y_batch).sum().item() # correct predictions in this batch total += y_batch.size(0) # samples processed so far # 3-e) Epoch-level metrics -------------------------------------------------- epoch_loss = running_loss / total epoch_acc = 100.0 * correct / total print(f"[Epoch {epoch}] loss = {epoch_loss:.4f} | accuracy = {epoch_acc:.2f}%") print("\n✅ Training finished.\n") # --------------------------------------------------------------------------- # 6. Evaluation on test set # --------------------------------------------------------------------------- model.eval() # Set model to evaluation mode (disables dropout and batch norm) with torch.no_grad(): logits_all, labels_all = [], [] for X, y in test_loader: logits_all.append(model(X.to(device)).cpu()) labels_all.append(y) logits_all = torch.cat(logits_all) labels_all = torch.cat(labels_all) preds_all = logits_all.argmax(1) test_loss = criterion(logits_all, labels_all).item() test_acc = (preds_all == labels_all).float().mean().item() * 100 print(f"Test loss: {test_loss:.4f}") print(f"Test accuracy: {test_acc:.2f}%\n") print("Classification report (precision / recall / F1):") print(classification_report(labels_all, preds_all, zero_division=0)) print("Confusion matrix (rows = true, cols = pred):") print(confusion_matrix(labels_all, preds_all)) ``` ## पुनरावर्ती न्यूरल नेटवर्क (RNNs) पुनरावर्ती न्यूरल नेटवर्क (RNNs) एक प्रकार के न्यूरल नेटवर्क हैं जो अनुक्रमिक डेटा, जैसे समय श्रृंखला या प्राकृतिक भाषा, को संसाधित करने के लिए डिज़ाइन किए गए हैं। पारंपरिक फीडफॉरवर्ड न्यूरल नेटवर्क के विपरीत, RNNs में ऐसे कनेक्शन होते हैं जो स्वयं पर वापस लूप करते हैं, जिससे उन्हें एक छिपी हुई स्थिति बनाए रखने की अनुमति मिलती है जो अनुक्रम में पिछले इनपुट के बारे में जानकारी कैप्चर करती है। RNNs के मुख्य घटक शामिल हैं: - **पुनरावर्ती परतें**: ये परतें इनपुट अनुक्रमों को एक समय चरण में संसाधित करती हैं, वर्तमान इनपुट और पिछले छिपे हुए स्थिति के आधार पर अपनी छिपी हुई स्थिति को अपडेट करती हैं। यह RNNs को डेटा में समय संबंधी निर्भरताओं को सीखने की अनुमति देता है। - **छिपी हुई स्थिति**: छिपी हुई स्थिति एक वेक्टर है जो पिछले समय चरणों से जानकारी का सारांश प्रस्तुत करता है। इसे प्रत्येक समय चरण में अपडेट किया जाता है और वर्तमान इनपुट के लिए भविष्यवाणियाँ करने के लिए उपयोग किया जाता है। - **आउटपुट परत**: आउटपुट परत छिपी हुई स्थिति के आधार पर अंतिम भविष्यवाणियाँ उत्पन्न करती है। कई मामलों में, RNNs का उपयोग भाषा मॉडलिंग जैसे कार्यों के लिए किया जाता है, जहाँ आउटपुट अनुक्रम में अगले शब्द के लिए एक संभाव्यता वितरण होता है। उदाहरण के लिए, एक भाषा मॉडल में, RNN एक शब्दों के अनुक्रम को संसाधित करता है, जैसे "बिल्ली ने पर" और पिछले शब्दों द्वारा प्रदान किए गए संदर्भ के आधार पर अगले शब्द की भविष्यवाणी करता है, इस मामले में, "चटाई"। ### लंबी शॉर्ट-टर्म मेमोरी (LSTM) और गेटेड पुनरावर्ती यूनिट (GRU) RNNs अनुक्रमिक डेटा, जैसे भाषा मॉडलिंग, मशीन अनुवाद, और भाषण पहचान जैसे कार्यों के लिए विशेष रूप से प्रभावी होते हैं। हालाँकि, वे **लंबी दूरी की निर्भरताओं के साथ संघर्ष कर सकते हैं, जैसे कि गायब ग्रेडिएंट्स** के मुद्दों के कारण। इसका समाधान करने के लिए, लंबी शॉर्ट-टर्म मेमोरी (LSTM) और गेटेड पुनरावर्ती यूनिट (GRU) जैसी विशेष आर्किटेक्चर विकसित की गईं। ये आर्किटेक्चर सूचना के प्रवाह को नियंत्रित करने के लिए गेटिंग तंत्र पेश करते हैं, जिससे उन्हें लंबी दूरी की निर्भरताओं को अधिक प्रभावी ढंग से कैप्चर करने की अनुमति मिलती है। - **LSTM**: LSTM नेटवर्क तीन गेट (इनपुट गेट, फॉरगेट गेट, और आउटपुट गेट) का उपयोग करते हैं ताकि सेल स्थिति में सूचना के प्रवाह को नियंत्रित किया जा सके, जिससे उन्हें लंबे अनुक्रमों में जानकारी को याद रखने या भूलने की अनुमति मिलती है। इनपुट गेट यह नियंत्रित करता है कि नए इनपुट और पिछले छिपे हुए स्थिति के आधार पर कितनी नई जानकारी जोड़ी जाए, फॉरगेट गेट यह नियंत्रित करता है कि कितनी जानकारी को त्यागना है। इनपुट गेट और फॉरगेट गेट को मिलाकर हमें नई स्थिति मिलती है। अंततः, नई सेल स्थिति को इनपुट और पिछले छिपे हुए स्थिति के साथ मिलाकर हमें नई छिपी हुई स्थिति भी मिलती है। - **GRU**: GRU नेटवर्क LSTM आर्किटेक्चर को सरल बनाते हैं, इनपुट और फॉरगेट गेट को एकल अपडेट गेट में मिलाकर, जिससे वे गणनात्मक रूप से अधिक कुशल हो जाते हैं जबकि फिर भी लंबी दूरी की निर्भरताओं को कैप्चर करते हैं। ## LLMs (बड़े भाषा मॉडल) बड़े भाषा मॉडल (LLMs) एक प्रकार के गहरे शिक्षण मॉडल हैं जो विशेष रूप से प्राकृतिक भाषा प्रसंस्करण कार्यों के लिए डिज़ाइन किए गए हैं। इन्हें विशाल मात्रा में पाठ डेटा पर प्रशिक्षित किया जाता है और ये मानव-समान पाठ उत्पन्न कर सकते हैं, प्रश्नों का उत्तर दे सकते हैं, भाषाओं का अनुवाद कर सकते हैं, और विभिन्न अन्य भाषा-संबंधित कार्य कर सकते हैं। LLMs आमतौर पर ट्रांसफार्मर आर्किटेक्चर पर आधारित होते हैं, जो अनुक्रम में शब्दों के बीच संबंधों को कैप्चर करने के लिए आत्म-ध्यान तंत्र का उपयोग करते हैं, जिससे उन्हें संदर्भ को समझने और सुसंगत पाठ उत्पन्न करने की अनुमति मिलती है। ### ट्रांसफार्मर आर्किटेक्चर ट्रांसफार्मर आर्किटेक्चर कई LLMs की नींव है। इसमें एक एन्कोडर-डिकोडर संरचना होती है, जहाँ एन्कोडर इनपुट अनुक्रम को संसाधित करता है और डिकोडर आउटपुट अनुक्रम उत्पन्न करता है। ट्रांसफार्मर आर्किटेक्चर के मुख्य घटक शामिल हैं: - **आत्म-ध्यान तंत्र**: यह तंत्र मॉडल को अनुक्रम में विभिन्न शब्दों के महत्व को तौलने की अनुमति देता है जब वह प्रतिनिधित्व उत्पन्न करता है। यह शब्दों के बीच संबंधों के आधार पर ध्यान स्कोर की गणना करता है, जिससे मॉडल प्रासंगिक संदर्भ पर ध्यान केंद्रित कर सकता है। - **मल्टी-हेड ध्यान**: यह घटक मॉडल को शब्दों के बीच कई संबंधों को कैप्चर करने की अनुमति देता है, जिसमें कई ध्यान सिर होते हैं, प्रत्येक इनपुट के विभिन्न पहलुओं पर ध्यान केंद्रित करता है। - **पोजिशनल एनकोडिंग**: चूंकि ट्रांसफार्मर में शब्द क्रम का कोई अंतर्निहित विचार नहीं होता है, पोजिशनल एनकोडिंग को इनपुट एम्बेडिंग में जोड़ा जाता है ताकि अनुक्रम में शब्दों की स्थिति के बारे में जानकारी प्रदान की जा सके। ## डिफ्यूजन मॉडल डिफ्यूजन मॉडल एक प्रकार के जनरेटिव मॉडल हैं जो डेटा उत्पन्न करना सीखते हैं एक डिफ्यूजन प्रक्रिया का अनुकरण करके। ये विशेष रूप से छवि उत्पन्न करने जैसे कार्यों के लिए प्रभावी होते हैं और हाल के वर्षों में लोकप्रियता प्राप्त की है। डिफ्यूजन मॉडल धीरे-धीरे एक सरल शोर वितरण को एक जटिल डेटा वितरण में बदलते हैं एक श्रृंखला के माध्यम से डिफ्यूजन चरणों। डिफ्यूजन मॉडल के मुख्य घटक शामिल हैं: - **फॉरवर्ड डिफ्यूजन प्रक्रिया**: यह प्रक्रिया धीरे-धीरे डेटा में शोर जोड़ती है, इसे एक सरल शोर वितरण में बदलती है। फॉरवर्ड डिफ्यूजन प्रक्रिया आमतौर पर शोर स्तरों की एक श्रृंखला द्वारा परिभाषित की जाती है, जहाँ प्रत्येक स्तर डेटा में जोड़े गए शोर की एक विशिष्ट मात्रा के लिए होता है। - **रिवर्स डिफ्यूजन प्रक्रिया**: यह प्रक्रिया फॉरवर्ड डिफ्यूजन प्रक्रिया को उलटने के लिए सीखती है, डेटा को धीरे-धीरे डिनॉइज़ करते हुए लक्ष्य वितरण से नमूने उत्पन्न करती है। रिवर्स डिफ्यूजन प्रक्रिया को एक हानि फ़ंक्शन का उपयोग करके प्रशिक्षित किया जाता है जो मॉडल को शोर नमूनों से मूल डेटा को पुनर्निर्माण करने के लिए प्रोत्साहित करता है। इसके अलावा, एक पाठ संकेत से छवि उत्पन्न करने के लिए, डिफ्यूजन मॉडल आमतौर पर इन चरणों का पालन करते हैं: 1. **पाठ एनकोडिंग**: पाठ संकेत को एक टेक्स्ट एनकोडर (जैसे, एक ट्रांसफार्मर-आधारित मॉडल) का उपयोग करके एक लेटेंट प्रतिनिधित्व में एनकोड किया जाता है। यह प्रतिनिधित्व पाठ के अर्थ को कैप्चर करता है। 2. **शोर नमूना लेना**: एक यादृच्छिक शोर वेक्टर को गॉसियन वितरण से नमूना लिया जाता है। 3. **डिफ्यूजन चरण**: मॉडल एक श्रृंखला के डिफ्यूजन चरणों को लागू करता है, धीरे-धीरे शोर वेक्टर को एक छवि में बदलता है जो पाठ संकेत के अनुरूप होती है। प्रत्येक चरण में छवि को डिनॉइज़ करने के लिए सीखे गए रूपांतरणों को लागू करना शामिल होता है। {{#include ../banners/hacktricks-training.md}}