2015-08-27 6 views
16

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

(2147481832,23355149,1) 
(2147481832,973010692,1) 
(2147481832,2134870842,1) 
(2147481832,541023347,1) 
(2147481832,1682206630,1) 
(2147481832,1138211459,1) 
(2147481832,852202566,1) 
(2147481832,201375938,1) 
(2147481832,486538879,1) 
(2147481832,919187908,1) 
... 

मुझे यकीन है कि मैं केवल एक उपयोगकर्ता डेटा के 80% लेने के लिए और एक RDD निर्माण जबकि 20% के बाकी लेने के लिए और एक दूसरे RDD निर्माण करना चाहते हैं। कॉल ट्रेन और परीक्षण चलो। मैं समूह का उपयोग करने से दूर रहना चाहता हूं क्योंकि शुरुआत से यह स्मृति समस्या पैदा कर सकता है क्योंकि डेटा सेट बड़ा है। ऐसा करने का सबसे अच्छा तरीका क्या है?

मैं निम्नलिखित कर सकता था लेकिन यह प्रत्येक उपयोगकर्ता का 80% नहीं देगा।

val percentData = data.map(x => ((math.random * 100).toInt, x._1. x._2, x._3) 
val train = percentData.filter(x => x._1 < 80).values.repartition(10).cache() 

उत्तर

18

एक संभावना यह होल्डन के जवाब में है, और यह एक और एक है:

आप PairRDDFunctions वर्ग से, sampleByKeyExact परिवर्तन का उपयोग कर सकते हैं।

sampleByKeyExact (बूलियन withReplacement, scala.collection.Map भिन्न, लंबे बीज) इस RDD कुंजी द्वारा नमूना के एक सबसेट (स्तरीकृत नमूने के माध्यम से) लौटें बिल्कुल math.ceil युक्त (numItems * samplingRate) प्रत्येक के लिए स्ट्रैटम (एक ही कुंजी के साथ जोड़े का समूह)।

और यह मैं कैसे करना होता है:

निम्न सूची को ध्यान में रखते:

val list = List((2147481832,23355149,1),(2147481832,973010692,1),(2147481832,2134870842,1),(2147481832,541023347,1),(2147481832,1682206630,1),(2147481832,1138211459,1),(2147481832,852202566,1),(2147481832,201375938,1),(2147481832,486538879,1),(2147481832,919187908,1),(214748183,919187908,1),(214748183,91187908,1)) 

मैं एक RDD जोड़ी बनाना होगा, कुंजी के रूप में सभी उपयोगकर्ताओं मानचित्रण:

val data = sc.parallelize(list.toSeq).map(x => (x._1,(x._2,x._3))) 

फिर मैं निम्नलिखित के रूप में प्रत्येक कुंजी के लिए fractions सेट अप करूंगा, क्योंकि आपने देखा है कि sa

val fractions = data.map(_._1).distinct.map(x => (x,0.8)).collectAsMap 

मैं यहाँ क्या किया है, वास्तव में, कुंजी पर मानचित्रण अलग लगता है और फिर एक अंश के लिए प्रत्येक कुंजी सहयोगी 0.8 के बराबर है तो मैं पूरी इकट्ठा करने के लिए: mpleByKeyExact प्रत्येक कुंजी के लिए अंश का एक नक्शा ले जाता है एक मानचित्र के रूप में

अब नमूना करने के लिए, सब मुझे क्या करना है:

import org.apache.spark.rdd.PairRDDFunctions 
val sampleData = data.sampleByKeyExact(false, fractions, 2L) 

या

val sampleData = data.sampleByKeyExact(withReplacement = false, fractions = fractions,seed = 2L) 

आप अपनी चाबी या डेटा या डेटा नमूने पर गिनती की जाँच कर सकते हैं:

scala > data.count 
// [...] 
// res10: Long = 12 

scala > sampleData.count 
// [...] 
// res11: Long = 10 

संपादित करें: मैंने स्तरीकृत नमूनाकरण करने के लिए एक हिस्सा जोड़ने का निर्णय लिया है o एन DataFrame एस।

तो हम ऊपर दिए गए उदाहरण से उसी डेटा (list) पर विचार करेंगे।

val df = list.toDF("keyColumn","value1","value2") 
df.show 
// +----------+----------+------+ 
// | keyColumn| value1|value2| 
// +----------+----------+------+ 
// |2147481832| 23355149|  1| 
// |2147481832| 973010692|  1| 
// |2147481832|2134870842|  1| 
// |2147481832| 541023347|  1| 
// |2147481832|1682206630|  1| 
// |2147481832|1138211459|  1| 
// |2147481832| 852202566|  1| 
// |2147481832| 201375938|  1| 
// |2147481832| 486538879|  1| 
// |2147481832| 919187908|  1| 
// | 214748183| 919187908|  1| 
// | 214748183| 91187908|  1| 
// +----------+----------+------+ 

हम अंतर्निहित RDD की आवश्यकता होगी कि जिस पर हम अपने प्रमुख को परिभाषित करने के लिए पहले स्तंभ होने के लिए द्वारा इस RDD में तत्वों की tuples बनाता करने के लिए:

val data: RDD[(Int, Row)] = df.rdd.keyBy(_.getInt(0)) 
val fractions: Map[Int, Double] = data.map(_._1) 
             .distinct 
             .map(x => (x, 0.8)) 
             .collectAsMap 

val sampleData: RDD[Row] = data.sampleByKeyExact(withReplacement = false, fractions, 2L) 
           .values 

val sampleDataDF: DataFrame = spark.createDataFrame(sampleData, df.schema) // you can use sqlContext.createDataFrame(...) instead for spark 1.6) 

अब आप गिनती जाँच कर सकते हैं अपनी चाबी या df या डेटा नमूने पर:

scala > df.count 
// [...] 
// res9: Long = 12 

scala > sampleDataDF.count 
// [...] 
// res10: Long = 10 

संपादित करें 2: के बाद से स्पार्क 1.5.0 आप DataFrameStatFunc उपयोग कर सकते हैं tions.sampleBy विधि:

df.stat.sampleBy("keyColumn", fractions, seed) 
+0

यह बहुत अच्छा है, क्या मैं 20% प्राप्त करने के लिए घटा सकता हूं? या आप एक बेहतर समाधान की सिफारिश करते हैं? –

+1

अच्छी तरह से आपके पास नया rdd है, तो आप इसके साथ कुछ भी कर सकते हैं। – eliasah

+0

मुझे rdd पर उपलब्ध नमूना विधि दिखाई देती है लेकिन नमूना नहीं है BeyKeyExact –

2

ऐसा कुछ ऐसा है जो "ब्लिंक डीबी" जैसे कुछ के लिए उपयुक्त हो सकता है, लेकिन सवाल को देखते हैं। आपने जो पूछा है उसे समझने के दो तरीके हैं:

1) आप अपने 80% उपयोगकर्ताओं को चाहते हैं, और आप उनके लिए सभी डेटा चाहते हैं। 2) आप प्रत्येक उपयोगकर्ता डेटा

का 80% # 1 के लिए आप एक नक्शा कर सकता है उपयोगकर्ता आईडी प्राप्त करने के लिए, अलग, और फिर नमूना उनमें से 80% (आप MLUtils या में kFold को देखने के लिए चाहते हो सकता है फोन चाहते हैं BernoulliCellSampler)। फिर आप अपने इनपुट डेटा को केवल इच्छित आईडी के सेट पर फ़िल्टर कर सकते हैं।

# 2 के लिए आप BernoulliCellSampler देख सकते हैं और इसे सीधे लागू कर सकते हैं।