2014-04-30 5 views
8

के साथ बैलेंस numpy सरणी कृपया मुझे मौजूदा से बाहर एक नया सरणी बनाने के लिए एक साफ तरीका खोजने में मदद करें। यह किसी भी वर्ग के उदाहरण की संख्या कक्षा में उदाहरणों की अधिकतम संख्या से छोटी है, तो इसे अधिक नमूना होना चाहिए। नमूने मूल सरणी से लिया जाना चाहिए (कोई फर्क नहीं पड़ता, बेतरतीब ढंग से या क्रमिक रूप से है कि क्या)ओवर-सैम्पलिंग

मान लें, प्रारंभिक सरणी यह ​​है:

classes = [ 0, 1, 9] 

:

[ 2, 29, 30, 1] 
[ 5, 50, 46, 0] 
[ 1, 7, 89, 1] 
[ 0, 10, 92, 9] 
[ 4, 11, 8, 1] 
[ 3, 92, 1, 0] 

अंतिम स्तंभ वर्गों में शामिल है कक्षाओं का वितरण निम्नलिखित है:

distrib = [2, 3, 1] 

मुझे जो चाहिए मूल सरणी से यादृच्छिक रूप से लिया गया, सभी वर्गों के बराबर संख्या के नमूने के साथ एक नई सरणी बनाने के लिए, उदा।

[ 5, 50, 46, 0] 
[ 3, 92, 1, 0] 
[ 5, 50, 46, 0] # one example added 
[ 2, 29, 30, 1] 
[ 1, 7, 89, 1] 
[ 4, 11, 8, 1] 
[ 0, 10, 92, 9] 
[ 0, 10, 92, 9] # two examples 
[ 0, 10, 92, 9] # added 

उत्तर

9

निम्नलिखित कोड क्या करता है आप के बाद कर रहे हैं:

:

a = np.array([[ 2, 29, 30, 1], 
       [ 5, 50, 46, 0], 
       [ 1, 7, 89, 1], 
       [ 0, 10, 92, 9], 
       [ 4, 11, 8, 1], 
       [ 3, 92, 1, 0]]) 

unq, unq_idx = np.unique(a[:, -1], return_inverse=True) 
unq_cnt = np.bincount(unq_idx) 
cnt = np.max(unq_cnt) 
out = np.empty((cnt*len(unq),) + a.shape[1:], a.dtype) 
for j in xrange(len(unq)): 
    indices = np.random.choice(np.where(unq_idx==j)[0], cnt) 
    out[j*cnt:(j+1)*cnt] = a[indices] 

>>> out 
array([[ 5, 50, 46, 0], 
     [ 5, 50, 46, 0], 
     [ 5, 50, 46, 0], 
     [ 1, 7, 89, 1], 
     [ 4, 11, 8, 1], 
     [ 2, 29, 30, 1], 
     [ 0, 10, 92, 9], 
     [ 0, 10, 92, 9], 
     [ 0, 10, 92, 9]]) 

जब numpy 1.9 जारी किया गया है, या यदि आप विकास शाखा से संकलन है, तो पहले दो लाइनों में संघनित किया जा सकता है

unq, unq_idx, unq_cnt = np.unique(a[:, -1], return_inverse=True, 
            return_counts=True) 

ध्यान दें कि, np.random.choice काम करता है, इस बात की कोई गारंटी नहीं है कि मूल सरणी की सभी पंक्तियां आउटपुट में मौजूद होंगी, जैसा उपरोक्त उदाहरण दिखाता है। यह प्रत्येक वर्ग के लिए बराबर संभावना के साथ एक यादृच्छिक वितरण देता

unq, unq_idx = np.unique(a[:, -1], return_inverse=True) 
unq_cnt = np.bincount(unq_idx) 
cnt = np.max(unq_cnt) 
out = np.empty((cnt*len(unq) - len(a),) + a.shape[1:], a.dtype) 
slices = np.concatenate(([0], np.cumsum(cnt - unq_cnt))) 
for j in xrange(len(unq)): 
    indices = np.random.choice(np.where(unq_idx==j)[0], cnt - unq_cnt[j]) 
    out[slices[j]:slices[j+1]] = a[indices] 
out = np.vstack((a, out)) 

>>> out 
array([[ 2, 29, 30, 1], 
     [ 5, 50, 46, 0], 
     [ 1, 7, 89, 1], 
     [ 0, 10, 92, 9], 
     [ 4, 11, 8, 1], 
     [ 3, 92, 1, 0], 
     [ 5, 50, 46, 0], 
     [ 0, 10, 92, 9], 
     [ 0, 10, 92, 9]]) 
+0

दूसरा समाधान मेरी समस्या हल करता है, बहुत बहुत धन्यवाद! – funkifunki

5

: अगर वह की जरूरत है, आप की तरह कुछ कर सकता है

distrib = np.bincount(a[:,-1]) 
prob = 1/distrib[a[:, -1]].astype(float) 
prob /= prob.sum() 

In [38]: a[np.random.choice(np.arange(len(a)), size=np.count_nonzero(distrib)*distrib.max(), p=prob)] 
Out[38]: 
array([[ 5, 50, 46, 0], 
     [ 4, 11, 8, 1], 
     [ 0, 10, 92, 9], 
     [ 0, 10, 92, 9], 
     [ 2, 29, 30, 1], 
     [ 0, 10, 92, 9], 
     [ 3, 92, 1, 0], 
     [ 1, 7, 89, 1], 
     [ 1, 7, 89, 1]]) 

प्रत्येक वर्ग समान प्रायिकता, गारंटी नहीं बराबर घटना है।

+1

कोड का वास्तव में अच्छा टुकड़ा होने पर यह वास्तव में समस्या को हल नहीं करता है, क्योंकि सभी वर्गों की समान उपस्थिति की गारंटी नहीं है: आप [0 0 0 1 1 1 9 9 9] प्राप्त कर सकते हैं, लेकिन यह भी पकड़ना संभव है [9 0 9 9 9 0 1 9]। बहुत धन्यवाद, हालांकि, अच्छा उदाहरण! – funkifunki

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^