복붙노트

[SCALA] 스파크에서 층화 추출법

SCALA

스파크에서 층화 추출법

나는 사용자와 구매 데이터를 포함하는 데이터 세트가 있습니다. 여기서 첫 번째 요소는 userId를하는 예이며, 두 번째 제품 ID이고, 세 번째는 부울을 나타낸다.

(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)
... 

나는 20 %의 휴식을 취하며 다른 RDD를 구축하는 동안은 각 사용자 데이터의 80 %를 가지고와 RDD를 구축 있는지 확인하려면. 전화 기차와 테스트를 할 수 있습니다. 나는 데이터 세트가 크기 때문에이 메모리 문제를 만들 수 있기 때문에 시작하는 GROUPBY를 사용하여 멀리하고 싶습니다. 가장 좋은 방법은이 뭐죠 할까?

나는 다음을 수행 할 수 있지만, 이것은 각 사용자의 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()

해결법

  1. ==============================

    1.한 가지 가능한 솔루션은 홀든의 대답이며, 여기에 몇 가지 다른 솔루션입니다 :

    한 가지 가능한 솔루션은 홀든의 대답이며, 여기에 몇 가지 다른 솔루션입니다 :

    RDDs 사용 :

    당신은 PairRDDFunctions 클래스에서의 sampleByKeyExact 변환을 사용할 수 있습니다.

    그리고 이것은 내가 얼마나입니다 :

    다음 목록을 고려 :

    val seq = Seq(
                    (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(seq).map(x => (x._1,(x._2,x._3)))
    

    sampleByKeyExact 각 키에 대한 부분의지도를 소요하기 때문에 그럼, 다음 각 키에 분수를 설정합니다 :

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

    내가 여기 짓을하는 것은 별개의 키를 찾은 다음 분수에 각각 0.8와 동일 연결할 키에 대한 매핑입니다. 나는지도로 전체를 수집합니다.

    지금 샘플 :

    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
    

    DataFrames 사용 :

    의 이전 섹션에서 동일한 데이터 (서열)를 생각해 보자.

    val df = seq.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가 필요합니다 :

    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
    

    스파크는 1.5.0 이후 당신은 DataFrameStatFunctions.sampleBy 방법을 사용할 수 있습니다 :

    df.stat.sampleBy("keyColumn", fractions, seed)
    
  2. ==============================

    2.이런 식으로 뭔가 잘 "블링크 DB"같은에 적합 할 수있다, 그러나 질문을 볼 수 있습니다. 하나가 질문 한 내용을 해석하는 방법에는 두 가지가 있습니다 :

    이런 식으로 뭔가 잘 "블링크 DB"같은에 적합 할 수있다, 그러나 질문을 볼 수 있습니다. 하나가 질문 한 내용을 해석하는 방법에는 두 가지가 있습니다 :

    1) 당신은 사용자의 80 %를 원하고, 당신은 그들에 대한 모든 데이터를합니다. 2) 각 사용자 데이터의 80 %를 원하는

    # 1의 경우, 사용자 ID를 얻을 수있는지도를 할 별개의 호출하고 (당신이 MLUtils 또는 BernoulliCellSampler에 kFold보고 할 수 있습니다) 그 중 80 %를 샘플링 할 수 있습니다. 그런 다음 원하는 ID의 단지 세트에 입력 데이터를 필터링 할 수 있습니다.

    # 2의 당신은 BernoulliCellSampler을보고 간단하게 직접 적용 할 수 있습니다.

  3. from https://stackoverflow.com/questions/32238727/stratified-sampling-in-spark by cc-by-sa and MIT license