मैं एक डेटासेट को एक विशिष्ट कॉलम द्वारा समूहबद्ध करने के लिए एक हॉट एन्कोड लेने की कोशिश कर रहा हूं, इसलिए मैं उस कॉलम में प्रत्येक आइटम के लिए एक पंक्ति प्राप्त कर सकता हूं जिसमें उस विशिष्ट पंक्ति के लिए एक हॉट कॉलम सत्य है। ऐसा लगता है कि यह छोटे डेटा पर काम कर रहा है और डैस्क का उपयोग बड़े डेटासेट के लिए काम करता प्रतीत होता है लेकिन जब मैं फ़ाइल को सहेजने का प्रयास कर रहा हूं तो मुझे समस्याएं आ रही हैं। मैंने सीएसवी और लकड़ी की छत फ़ाइल की कोशिश की है। मैं परिणामों को सहेजना चाहता हूं और फिर मैं इसे बाद में विखंडू में खोल सकता हूं।

यहाँ समस्या दिखाने के लिए कोड है (नीचे दी गई स्क्रिप्ट 2M पंक्तियाँ और 30k तक अद्वितीय मान एकहॉट एन्कोड के लिए उत्पन्न करती है)।

import pandas as pd
import numpy as np
import dask.dataframe as dd
from dask.distributed import Client, LocalCluster, wait

sizeOfRows = 2000000
columnsForDF = 30000 
partitionsforDask = 500 
print("partition is ", partitionsforDask)


cluster = LocalCluster()
client = Client(cluster)
print(client)



df = pd.DataFrame(np.random.randint(0,columnsForDF,size=(sizeOfRows, 2)), columns=list('AB'))
ddf = dd.from_pandas(df, npartitions=partitionsforDask)
# ddf = ddf.persist()
wait(ddf)

# %%time
# need to globally know the categories before one hot encoding
ddf = ddf.categorize(columns=["B"])
one_hot = dd.get_dummies(ddf, columns=['B'])
print("starting groupby")
# result = one_hot.groupby('A').max().persist() # or to_parquet/to_csv/compute/etc.
# result = one_hot.groupby('A', sort=False).max().to_csv('./daskDF.csv', single_file = True)
result = one_hot.groupby('A', sort=False).max().to_parquet('./parquetFile')
wait(result)

ऐसा लगता है कि यह तब तक काम करता है जब तक यह समूह को सीएसवी या लकड़ी की छत तक नहीं करता। उस समय, मुझे श्रमिकों के बारे में कई त्रुटियां मिलती हैं जो 95% मेमोरी से अधिक हो जाती हैं और फिर प्रोग्राम "मारे गए कार्यकर्ता" अपवाद से बाहर निकलता है:

distributed.nanny - WARNING - Worker exceeded 95% memory budget. Restarting
KilledWorker: ("('dataframe-groupby-max-combine-3ddcd8fc854613101b4bdc7fccde32cd', 1, 0, 0)", <Worker 'tcp://127.0.0.1:33815', name: 6, memory: 0, processing: 22>)

अपनी मशीन की निगरानी करते हुए, मैं कभी भी अधिक मेमोरी के करीब नहीं जाता और मेरा ड्राइव स्थान 300 जीबी से अधिक है जिसका कभी उपयोग नहीं किया जाता है (इस प्रक्रिया के दौरान कोई फ़ाइल नहीं बनाई जाती है, हालांकि यह ग्रुपबाय सेक्शन में है)।

मैं क्या कर सकता हूं?

अपडेट - मैंने सोचा कि मैं एक पुरस्कार जोड़ूंगा। मुझे .to_csv के साथ भी यही समस्या हो रही है, क्योंकि किसी और को भी इसी तरह की समस्या थी, मुझे आशा है कि व्यापक दर्शकों के लिए इसका मूल्य है।

3
Lostsoul 30 पद 2020, 04:07
1
मैं इसे ज्यूपिटर नोटबुक में jupyter.org/try पर पुन: पेश कर सकता हूं।
 – 
jakub
30 पद 2020, 04:59
अरे क्या आपने इस मुद्दे को हल कर लिया है?
 – 
HanaKaze
27 जिंदा 2021, 20:56
1
नहीं, इसे हल नहीं कर सका और एक अलग समाधान मिला। एक हॉट एन्कोडिंग के बजाय प्रयुक्त एम्बेडिंग।
 – 
Lostsoul
28 जिंदा 2021, 19:45

1 उत्तर

सबसे बढ़िया उत्तर

आइए पहले अंतिम परिणाम के बारे में सोचें: यह 30'000 कॉलम और 30'000 पंक्तियों के साथ एक डेटाफ्रेम होगा। यह ऑब्जेक्ट लगभग 6.7 जीबी मेमोरी लेगा। (मेमोरी फ़ुटप्रिंट को कम करने के लिए dtypes के साथ खेलने की गुंजाइश है और डेटा में सभी संयोजन दिखाई नहीं दे सकते हैं, लेकिन सादगी के लिए इन बिंदुओं को अनदेखा करें)

अब, कल्पना कीजिए कि हमारे पास केवल दो विभाजन थे और प्रत्येक विभाजन में सभी संभावित डमी चर संयोजन शामिल थे। इसका मतलब यह होगा कि प्रत्येक कार्यकर्ता को .groupby().max() ऑब्जेक्ट को स्टोर करने के लिए कम से कम 6.7 जीबी की आवश्यकता होगी, लेकिन अंतिम चरण के लिए 13.4 जीबी की आवश्यकता होगी क्योंकि अंतिम कार्यकर्ता को उन दो वस्तुओं के .max को खोजने की आवश्यकता होगी। स्वाभाविक रूप से, यदि आपके पास अधिक विभाजन हैं, तो अंतिम कार्यकर्ता पर स्मृति आवश्यकताएँ बढ़ेंगी। प्रासंगिक फ़ंक्शन में split_every निर्दिष्ट करके इसे dask में नियंत्रित करने का एक तरीका है। उदाहरण के लिए, यदि आप .max(split_every=2) निर्दिष्ट करते हैं, तो किसी भी कार्यकर्ता को अधिकतम 2 ऑब्जेक्ट प्राप्त होंगे (split_every का डिफ़ॉल्ट मान 8 है)।

500 विभाजनों के प्रसंस्करण की शुरुआत में, यह संभावना है कि प्रत्येक विभाजन में संभावित डमी मानों का केवल एक सबसेट होगा, इसलिए स्मृति आवश्यकताएँ कम हैं। हालाँकि, जैसे-जैसे dask अंतिम परिणाम की गणना में आगे बढ़ता है, यह विभिन्न डमी मूल्य संयोजनों के साथ वस्तुओं को मिलाएगा, इसलिए पाइपलाइन के अंत में मेमोरी की आवश्यकताएं बढ़ेंगी।

सिद्धांत रूप में, आप संसाधनों का उपयोग यह सीमित करने के लिए भी कर सकते हैं कि एक कार्यकर्ता कितने कार्य करेगा एक समय में कार्य करें, लेकिन यदि कार्यकर्ता के पास कार्यों को संभालने के लिए पर्याप्त स्मृति नहीं है तो यह मदद नहीं करेगा।

इससे बाहर निकलने के संभावित तरीके क्या हैं? कम से कम कुछ विकल्प:

  • बड़े संसाधनों वाले श्रमिकों का उपयोग करें;

  • कार्य को सरल बनाएं (उदाहरण के लिए संभावित श्रेणियों के सबसेट के आधार पर कार्य को कई उप-कार्यों में विभाजित करें);

  • delayed/futures के साथ एक कस्टम वर्कफ़्लो विकसित करें जो डेटा को सॉर्ट करेगा और कस्टम प्राथमिकताओं को लागू करेगा, यह सुनिश्चित करते हुए कि कार्यकर्ता अंतिम एकत्रीकरण के लिए आगे बढ़ने से पहले काम का एक सबसेट पूरा करें।

यदि कार्यकर्ता स्मृति एक बाधा है, तो उपसमुच्चय को बहुत बारीक होना होगा। उदाहरण के लिए, सीमा पर, केवल एक संभावित डमी वेरिएबल संयोजन को सब्मिट करने के लिए बहुत कम मेमोरी आवश्यकताएं होंगी (प्रारंभिक डेटा लोड और फ़िल्टर को अभी भी एक विभाजन को फिट करने के लिए पर्याप्त मेमोरी की आवश्यकता होगी), लेकिन निश्चित रूप से यह एक चरम उदाहरण है जो दसियों उत्पन्न करेगा हजारों कार्यों में से, इसलिए बड़े श्रेणी के समूहों की सिफारिश की जाती है (कार्यों की संख्या और स्मृति आवश्यकताओं को संतुलित करना)। एक उदाहरण देखने के लिए, आप इस संबंधित answer की जांच कर सकते हैं।

3
SultanOrazbayev 8 अप्रैल 2021, 10:29