2025, Oct 31 20:31

Keras Dense बनाम NumPy matmul: CPU/GPU पर छोटे अंतर का असली कारण

TensorFlow/Keras की Dense लेयर और NumPy matmul के आउटपुट में 1e-5 स्तर का अंतर क्यों आता है? CPU बनाम GPU निष्पादन, पुनरुत्पादन और allclose तुलना के तरीके जानें.

TensorFlow/Keras की एक साधारण Dense परत को शुद्ध NumPy फॉरवर्ड पास से मिलाना सतही तौर पर आसान लगता है। इनपुट मैट्रिक्स को वेट मैट्रिक्स से गुणा करें, बायस छोड़ दें, और परिणाम एक जैसे आने चाहिए। व्यवहार में, लगभग 1e-5 के आसपास सूक्ष्म अंतर दिख सकते हैं, जो हैरान करते हैं जब एकमात्र दिखाई देने वाला ऑपरेशन मैट्रिक्स गुणन ही हो।

विरोध दिखाने वाला न्यूनतम उदाहरण

import numpy as np
import keras
from keras import layers
print("Keras version:", keras.__version__)
print("Backend", keras.backend.backend())
# एक छोटा मॉडल बनाएँ
src = layers.Input((2,), name='inp')
dense_out = layers.Dense(5, kernel_initializer='random_normal', use_bias=False, name='dense')(src)
toy_net = keras.Model(inputs=src, outputs=dense_out)
# रैंडम इनपुट
feed = np.random.random(size=(5, 2)).astype(np.float32)
# Keras का फॉरवर्ड पास
y_keras = toy_net.predict(feed)
# Dense की kernel (वेट मैट्रिक्स) निकालें
[weight_mat] = toy_net.layers[1].get_weights()
# NumPy का फॉरवर्ड पास
y_np = np.matmul(feed, weight_mat)
# तुलना करें
print("Keras result:\n", y_keras)
print("NumPy result:\n", y_np)
print("Same result:", np.allclose(y_keras, y_np))

असल अंतर का कारण क्या है

जो अंतर दिख रहा है, वह Dense लेयर में किसी कस्टम गणना से या किसी छुपे अतिरिक्त ऑपरेशन से नहीं आता। फर्क इस बात से आता है कि गणना कहाँ चल रही है। NumPy CPU पर चलता है। TensorFlow/Keras वही matmul GPU पर चला सकता है। अलग‑अलग हार्डवेयर पथ एक ही गणितीय ऑपरेशन की भिन्न अमल‑कार्यप्रणालियाँ उपयोग करते हैं, जिससे फ्लोटिंग‑पॉइंट परिणामों में मामूली फर्क पड़ता है। यही पर्याप्त है कि अन्यथा समान गणनाओं में छोटे विचलन आ जाएँ।

यहाँ तक कि (5, 2) आकार के छोटे इनपुट को (2, 5) आकार के kernel से गुणा करने पर भी, अलग‑अलग निष्पादन इकाइयों पर फ्लोटिंग‑पॉइंट ऑपरेशनों का संचय प्रति तत्व लगभग 1e-5 के अंतर तक ले जा सकता है।

Keras और NumPy का आउटपुट कैसे मिलाएँ

यदि आप Keras मॉडल को CPU पर चलाते हैं, तो इस मामले में आपको NumPy जैसा ही परिणाम मिलेगा। CUDA को निष्क्रिय करने से TensorFlow/Keras CPU पथ का उपयोग करने के लिए बाध्य होता है और यह अंतर मिट जाता है।

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
import numpy as np
import keras
from keras import layers
print("Keras version:", keras.__version__)
print("Backend", keras.backend.backend())
src = layers.Input((2,), name='inp')
dense_out = layers.Dense(5, kernel_initializer='random_normal', use_bias=False, name='dense')(src)
toy_net = keras.Model(inputs=src, outputs=dense_out)
feed = np.random.random(size=(5, 2)).astype(np.float32)
y_keras = toy_net.predict(feed)
[weight_mat] = toy_net.layers[1].get_weights()
y_np = np.matmul(feed, weight_mat)
print("Same result:", np.allclose(y_keras, y_np))

व्यवहार में यह क्यों मायने रखता है

छोटे संख्यात्मक बदलाव परतों में फैल सकते हैं और टेस्ट, पुनरुत्पादन जाँच या रिग्रेशन थ्रेशहोल्ड को प्रभावित कर सकते हैं। यदि आप फॉरवर्ड पास को किसी संदर्भ NumPy इम्प्लीमेंटेशन के खिलाफ सत्यापित करते हैं, तो आपके डीप‑लर्निंग फ्रेमवर्क के पीछे कौन‑सा compute डिवाइस है, यह बिटवाइज़ और tolerance‑आधारित तुलना को सीधे प्रभावित करता है।

निष्कर्ष

यदि आपको रैखिक लेयरों के लिए TensorFlow/Keras और NumPy के बीच समानता चाहिए, तो दोनों को या तो CPU पर चलाएँ या दोनों को GPU पर। जब यह संभव न हो, तो सहनशीलता के साथ तुलना करें और छोटे‑छोटे फर्क की अपेक्षा रखें—यहाँ तक कि सरल मैट्रिक्स गुणन में भी। यह समझना कि अंतर CPU बनाम GPU निष्पादन से आता है, आपको डिबगिंग, वैलिडेशन और पुनरुत्पाद्य टेस्ट लिखने के लिए सही वातावरण चुनने में मदद करता है।

यह लेख StackOverflow पर एक प्रश्न (लेखक: el_grezeq) और el_grezeq द्वारा दिए गए उत्तर पर आधारित है।