जिन चीजों में मैंने अभी तक कोशिश की है, उनमें से एक पीईटीबल्स समाधान वर्तमान में सबसे अच्छा है, इसके बाद एक समाधान के बाद numpy
का उपयोग memmapped arrays के लिए करता है। हालांकि PyTables समाधान सरल नहीं है।यदि आप एक PyTables सरणी को सीधे अनुक्रमणित करने के लिए पूर्णांक की एक शफल सरणी का उपयोग करते हैं, तो यह बहुत धीमा है। निम्नलिखित दो-चरणीय प्रक्रिया बहुत तेज है:
- बूलियन इंडेक्स सरणी का उपयोग करके सरणी का एक यादृच्छिक सबसेट चुनें। यह एक chunkwise फैशन में किया जाना चाहिए। यदि आप सीधे इंडेक्स सरणी को PyTables सरणी में पास करते हैं, तो यह धीमा है।
- Preallocate एक numpy सरणी और स्लाइस कि टुकड़ों में PyTables सरणी विभाजित की एक सूची बना।
- प्रत्येक हिस्सा पूरी तरह स्मृति में पढ़ें, और फिर उस हिस्सा के लिए सही मूल्यों का चयन करने के सूचकांक सरणी की इसी हिस्सा का उपयोग करें।
- चयनित मानों को प्रीलोकेटेड सरणी में संग्रहीत करें।
- फिर प्रीलोकेटेड सरणी को घुमाएं।
यह प्रक्रिया एक सामान्य शफल प्रक्रिया के रूप में यादृच्छिक रूप से क्रमपरिवर्तन उत्पन्न करती है। यदि यह स्पष्ट प्रतीत नहीं होता है, तो इस पर विचार करें: (n choose x) * x! = x! * n!/(x! * (n - x)!) = n!/(n - x)!
। यह विधि प्रत्येक प्रशिक्षण चक्र के लिए एक शफल-ऑन-लोड करने के लिए पर्याप्त तेज़ है। यह डेटा को ~ 650 एम तक संपीड़ित करने में भी सक्षम है - लगभग 90% अपस्फीति।
मेरा वर्तमान कार्यान्वयन यहां है; इसे कॉर्पस में प्रत्येक प्रशिक्षण खंड के लिए एक बार कहा जाता है। (लौटे सरणियों कहीं shuffled हैं।)
def _h5_fast_bool_ix(self, h5_array, ix, read_chunksize=100000):
'''Iterate over an h5 array chunkwise to select a random subset
of the array. `h5_array` should be the array itself; `ix` should
be a boolean index array with as many values as `h5_array` has
rows; and you can optionally set the number of rows to read per
chunk with `read_chunksize` (default is 100000). For some reason
this is much faster than using `ix` to index the array directly.'''
n_chunks = h5_array.shape[0]/read_chunksize
slices = [slice(i * read_chunksize, (i + 1) * read_chunksize)
for i in range(n_chunks)]
a = numpy.empty((ix.sum(), h5_array.shape[1]), dtype=float)
a_start = 0
for sl in slices:
chunk = h5_array[sl][ix[sl]]
a_end = a_start + chunk.shape[0]
a[a_start:a_end] = chunk
a_start = a_end
return a
यह मेरे लिए कुछ हद तक पागल है कि एक O (n^2) दृष्टिकोण (हर हिस्सा के लिए पूरे PyTables सरणी पर पुनरावृत्ति) एक हे की तुलना में तेजी इस मामले में है (एन) दृष्टिकोण (यादृच्छिक रूप से प्रत्येक पंक्ति को एक पास में चुनना)। लेकिन हे, यह काम करता है। थोड़ी अधिक संकेत के साथ, इसे मनमाने ढंग से गैर-यादृच्छिक क्रमपरिवर्तन लोड करने के लिए अनुकूलित किया जा सकता है, लेकिन इससे यहां की तुलना में अधिक जटिलता बढ़ जाती है।
mmap
समाधान उन लोगों को जो किसी भी कारण से एक शुद्ध numpy समाधान की जरूरत के लिए यहाँ संदर्भ के लिए है। यह लगभग 25 मिनट में सभी डेटा को घुमाता है, जबकि उपर्युक्त समाधान उस समय आधा से भी कम समय में प्रबंधित करता है। यह रैखिक रूप से भी स्केल करना चाहिए, क्योंकि mmap
(अपेक्षाकृत) कुशल यादृच्छिक पहुंच की अनुमति देता है।
import numpy
import os
import random
X = []
Y = []
for filename in os.listdir('input'):
X.append(numpy.load(os.path.join('input', filename), mmap_mode='r'))
for filename in os.listdir('output'):
Y.append(numpy.load(os.path.join('output', filename), mmap_mode='r'))
indices = [(chunk, row) for chunk, rows in enumerate(X)
for row in range(rows.shape[0])]
random.shuffle(indices)
newchunks = 50
newchunksize = len(indices)/newchunks
for i in range(0, len(indices), newchunksize):
print i
rows = [X[chunk][row] for chunk, row in indices[i:i + newchunksize]]
numpy.save('X_shuffled_' + str(i), numpy.array(rows))
rows = [Y[chunk][row] for chunk, row in indices[i:i + newchunksize]]
numpy.save('Y_shuffled_' + str(i), numpy.array(rows))
क्या आप मछुआरों को पंक्तियों को जोड़ सकते हैं और फिर मछुआरे कॉलम को येट कर सकते हैं? चूंकि आप केवल व्यक्तिगत पंक्तियों/कोल्स को स्वैप कर रहे हैं, इसलिए इसे आपकी याददाश्त का दुरुपयोग नहीं करना चाहिए। यदि गति समस्या है तो आप इसे सी एक्सटेंशन के रूप में कर सकते हैं (आपको वास्तव में यादृच्छिक बनाने के लिए स्वैप का एक टन चाहिए)। –
क्षमा करें, मैं स्पष्ट नहीं था - मुझे केवल पंक्तियों को कॉलम को घुमाने की आवश्यकता नहीं है। यह सिर्फ इतना है कि इसे सभी को स्मृति में लोड करने का कोई अच्छा तरीका नहीं है, न ही कुछ स्पष्ट डिस्क-आधारित विधियां व्यावहारिक हैं। – senderle