Spark MLlib을 활용한 기초 통계 및 데이터 분석

1. 요약 통계 (Summary Statistics)

Spark MLlib은 RDD[Vector] 형태의 데이터에 대해 열 단위의 요약 통계 기능을 제공합니다. 이를 위해 Statistics 클래스의 colStats 메서드를 사용하며, 이 메서드는 각 컬럼의 최대값, 최소값, 평균, 분산 등을 포함하는 MultivariateStatisticalSummary 객체를 반환합니다.

import org.apache.spark.mllib.linalg.Vector
import org.apache.spark.mllib.stat.{MultivariateStatisticalSummary, Statistics}
import org.apache.spark.rdd.RDD

// 벡터 형태의 RDD 생성
val inputData: RDD[Vector] = ... 

// 컬럼별 요약 통계 계산
val statResult: MultivariateStatisticalSummary = Statistics.colStats(inputData)

// 결과 출력 예시
println(s"컬럼별 평균: ${statResult.mean}")         // 각 컬럼의 평균값을 담은 DenseVector
println(s"컬럼별 분산: ${statResult.variance}")     // 각 컬럼의 분산
println(s"0이 아닌 요소 개수: ${statResult.numNonzeros}") // 각 컬럼 내 비정상(non-zero) 데이터 수

2. 상관관계 분석 (Correlations)

두 데이터셋 간의 연관성을 파악하는 것은 통계 분석의 핵심입니다. MLlib은 기본적으로 피어슨(Pearson)스피어만(Spearman) 두 가지 상관계수 계산 방식을 지원합니다.

상관계수 모델의 특징

  • Pearson 상관계수: 데이터가 정규 분포를 따르며 등간 척도인 경우에 주로 사용하며, 선형적 관계의 강도를 측정합니다.
  • Spearman 상관계수: 데이터의 순위를 기준으로 계산하며, 정규 분포를 따르지 않는 비모수적 데이터셋에도 적용 가능합니다.
import org.apache.spark.SparkContext
import org.apache.spark.mllib.linalg._
import org.apache.spark.mllib.stat.Statistics
import org.apache.spark.rdd.RDD

val sc: SparkContext = ...

// 두 개의 Double 타입 RDD 간의 상관관계 계산
val sequenceA: RDD[Double] = ...
val sequenceB: RDD[Double] = ...
val pearsonCorr: Double = Statistics.corr(sequenceA, sequenceB, "pearson")

// 벡터 RDD를 이용한 상관관계 행렬 생성
val matrixData: RDD[Vector] = ... 
val correlationMatrix: Matrix = Statistics.corr(matrixData, "spearman")

3. 층화 추출 (Stratified Sampling)

층화 추출법은 모집단을 서로 겹치지 않는 여러 개의 하위 집단(층)으로 나누고, 각 층에서 정해진 비율에 따라 샘플을 무작위로 추출하는 방식입니다. Spark에서는 Key-Value 형태의 RDD에서 Key를 기준으로 샘플링을 수행합니다.

주요 메서드

  • sampleByKey: 각 데이터를 순회하며 설정된 확률에 따라 샘플링 여부를 결정합니다. 근사적인 샘플 크기를 얻을 때 사용됩니다.
  • sampleByKeyExact: 설정된 비율에 맞춰 정확하게 샘플링을 수행합니다. 연산 비용은 더 높지만 99.9% 이상의 정확도를 보장합니다.
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD

val sc: SparkContext = ...
val rawData: RDD[(String, Int)] = ... // (Key, Value) 형태의 데이터

// 각 키별로 추출할 비율 설정
val samplingWeights = Map("GroupA" -> 0.1, "GroupB" -> 0.5, "GroupC" -> 0.3)

// 근사치 기반 층화 추출
val approxSample = rawData.sampleByKey(withReplacement = false, fractions = samplingWeights)

// 정확한 비율 기반 층화 추출
val exactSample = rawData.sampleByKeyExact(withReplacement = false, fractions = samplingWeights)

추출 방식에 있어 중복을 허용하는 경우(withReplacement = true)에는 포아송(Poisson) 분포가 활용되며, 중복을 허용하지 않는 경우에는 베르누이(Bernoulli) 분포가 활용됩니다.

태그: Apache Spark MLlib Statistics data analysis Scala

7월 11일 22:37에 게시됨