Databricks ML Associate

Databricks ML Associate 시험 노트개념 정리13 MIN

Spark DataFrame 요약 통계와 시각화

describe와 summary가 무엇을 다르게 내놓는지, dbutils.data.summarize가 그 위에 무엇을 더하는지, 그리고 피처 조합마다 어떤 그림과 어떤 수치로 관계를 보는지 정리합니다.

시험의 두 번째 영역인 「ML Workflows / Data Processing」은 배점 19%이고, 그 시작이 데이터를 처음 열어 보는 자리입니다. 문항은 「이 DataFrame에서 중앙값을 보려면 무엇을 부르는가」·「연속형 둘의 관계를 보려면 어느 그림인가」처럼 나옵니다. 메서드 이름과 출력 모양을 그대로 묻기 때문에, 읽어서 아는 것과 쳐 본 것의 차이가 크게 갈리는 자리입니다.

describe와 summary가 갈리는 한 칸

둘 다 수치 컬럼의 요약을 한 DataFrame으로 돌려주지만 줄 수가 다릅니다.

메서드 나오는 통계
df.describe() count mean stddev min max — 다섯 줄
df.summary() 위 다섯에 25% 50% 75%를 더한 여덟 줄

한 칸 차이가 사분위수입니다. 중앙값이나 사분위수가 필요하면 describe()로는 나오지 않습니다. 이 한 줄이 그대로 문항이 되므로 짝을 외워 둘 값이 있습니다.

summary()는 여기에 더해 원하는 통계만 골라 받는 인자를 받습니다.

df.describe().show()
df.summary().show()
df.summary("count", "min", "50%", "99%", "max").show()

주의할 점이 둘입니다. summary()의 백분위수는 근사값입니다(정확한 정렬 대신 근사 알고리즘을 씁니다). 그리고 stddev는 표본 표준편차로, 분모가 n−1n-1 입니다 — 손으로 검산할 때 모집단 공식으로 계산하면 값이 미세하게 어긋납니다.

문자열 컬럼도 함께 나옵니다. 이때 mean과 stddev는 비어 있고 min·max는 사전순으로 채워집니다.

dbutils.data.summarize가 더하는 것

dbutils.data.summarize(df)는 노트북 안에 요약 통계 화면을 그려 주는 Databricks 전용 도구입니다. 표를 돌려주는 것이 아니라 컬럼마다 카드를 그리고, 거기에 위 두 메서드에 없는 것이 들어 있습니다.

  • 결측값 개수와 비율 — describe()의 count를 전체 행 수와 비교해 사람이 빼야 했던 값입니다.
  • 분포 그림 — 수치형은 히스토그램, 범주형은 상위 값의 빈도.
  • 고유값 개수(distinct count).

기본은 근사 계산이라 큰 테이블에서도 빠르고, 정확한 값이 필요하면 precise=True를 줍니다. 대신 그만큼 느려집니다.

dbutils.data.summarize(df)
dbutils.data.summarize(df, precise=True)

「결측이 얼마나 되는지 한 번에 보려면」이라는 물음의 답이 describe()가 아니라 이쪽인 이유가 첫 줄에 있습니다.

피처 한 종류를 볼 때

그림은 대개 display()로 그립니다. Databricks 노트북에서 display(df)를 부르면 표가 나오고, 그 표 아래의 시각화 추가 단추로 히스토그램·산점도·상자그림 같은 그림을 붙일 수 있습니다. df.show()는 글자로만 찍기 때문에 이 단추가 붙지 않습니다 — 「그림을 그리려면 무엇을 부르는가」를 묻는 문항에서 이 둘이 나란히 보기로 섭니다.

그림을 고르는 기준은 피처가 범주형인가 연속형인가 하나입니다.

범주형 피처는 값이 정해진 몇 갈래로 나뉘는 피처입니다(지역·요금제·기기 종류). 이때 보는 것은 각 값이 몇 번 나오는가이므로 막대그래프입니다.

df.groupBy("plan").count().orderBy("count", ascending=False).display()

여기서 읽는 것이 둘입니다 — 한쪽으로 심하게 쏠려 있는가(클래스 불균형), 그리고 몇 갈래인가(카디널리티). 갈래가 수천이면 뒤에 나올 원-핫 인코딩이 곤란해집니다.

연속형 피처는 값이 이어진 수인 피처입니다(금액·나이·체류 시간). 이때는 히스토그램으로 분포의 모양을, 상자그림(box plot)으로 사분위수와 이상치의 위치를 봅니다. 히스토그램은 봉우리가 몇 개인지와 꼬리가 어느 쪽으로 긴지를 보여 주고, 상자그림은 그 꼬리에 있는 개별 점을 집어 줍니다. 둘은 경쟁하는 그림이 아니라 서로 다른 질문에 답합니다.

피처 둘을 견줄 때

조합이 셋이고 도구가 각각 다릅니다.

조합 그림 수치
연속형 × 연속형 산점도 상관계수
범주형 × 범주형 누적·묶음 막대 교차표와 카이제곱
범주형 × 연속형 범주별 상자그림 범주별 평균·중앙값

연속형끼리 — 산점도와 상관계수

상관계수(피어슨)는 두 연속형 피처가 함께 커지고 함께 작아지는 정도를 −1-1 부터 11 사이 수로 나타낸 값입니다.

r=∑(xi−xˉ)(yi−yˉ)∑(xi−xˉ)2∑(yi−yˉ)2r = \frac{\sum (x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum (x_i - \bar{x})^2}\sqrt{\sum (y_i - \bar{y})^2}}
df.stat.corr("tenure_months", "monthly_spend")

수 하나만 보면 안 되는 이유가 여기 있습니다. 피어슨 상관계수는 직선 관계만 잽니다. 완벽한 U자 관계도 rr 이 0에 가깝게 나옵니다. 그래서 산점도를 함께 그립니다 — 곡선인지, 두 덩어리로 나뉘어 있는지, 한 점이 혼자 멀리 있어 값을 끌고 있는지는 그림에만 보입니다.

범주형끼리 — 교차표와 카이제곱

교차표(crosstab)는 두 범주형의 값 조합마다 개수를 센 표입니다.

df.stat.crosstab("device", "churn").show()
해지 유지 합
모바일 30 70 100
데스크톱 20 80 100
합 50 150 200

이 표만 보면 모바일 해지율이 30%, 데스크톱이 20%라 차이가 있어 보입니다. 카이제곱 검정은 그 차이가 우연으로 볼 만한 크기인지를 재는 검정입니다. 두 변수가 무관하다고 가정했을 때의 기대 빈도를 구하고, 실제 빈도가 거기서 얼마나 떨어져 있는지를 더합니다.

Eij=(행 합)×(열 합)전체,χ2=∑(Oij−Eij)2EijE_{ij} = \frac{(\text{행 합}) \times (\text{열 합})}{\text{전체}}, \qquad \chi^2 = \sum \frac{(O_{ij} - E_{ij})^2}{E_{ij}}

기대 빈도는 네 칸 모두 100×50/200=25100 \times 50 / 200 = 25 와 100×150/200=75100 \times 150 / 200 = 75 입니다. 그러면

χ2=5225+5275+5225+5275=1+13+1+13≈2.67\chi^2 = \frac{5^2}{25} + \frac{5^2}{75} + \frac{5^2}{25} + \frac{5^2}{75} = 1 + \tfrac{1}{3} + 1 + \tfrac{1}{3} \approx 2.67

자유도는 (2−1)(2−1)=1(2-1)(2-1) = 1 이고 유의수준 0.05의 기준값이 3.84이므로, 이 차이는 우연으로 볼 만한 범위입니다. 표만 보고 「기기가 해지에 영향을 준다」고 결론지으면 안 되는 자리입니다. Spark에서는 pyspark.ml.stat의 ChiSquareTest가 이 값을 내주며, 입력 피처를 벡터로 모아 넘겨야 합니다.

연습 문제

  1. 컬럼의 중앙값이 필요합니다. 알맞은 것은?
    ① df.describe()
    ② df.summary()
    ③ df.count()
    ④ df.printSchema()
    ②. describe()는 count·mean·stddev·min·max 다섯 줄뿐이고 사분위수가 없습니다.
  2. df.summary()에 대한 설명으로 옳은 것을 둘 고르시오.
    ① 기본 출력에 25%·50%·75%가 들어간다
    ② 원하는 통계만 인자로 골라 받을 수 있다
    ③ 백분위수를 항상 정확히 계산한다
    ④ 문자열 컬럼은 아예 제외한다
    ⑤ 결측값 비율을 함께 보여 준다
    ①과 ②. 백분위수는 근사값이고(③), 문자열 컬럼도 count·min·max가 나오며(④), 결측 비율은 dbutils.data.summarize의 몫입니다(⑤).
  3. 전체 200행 중 모바일 100행(해지 30·유지 70), 데스크톱 100행(해지 20·유지 80)인 교차표가 있습니다. 「모바일 × 해지」 칸의 기대 빈도는?
    ① 20
    ② 25
    ③ 30
    ④ 50
    ②. 행 합 100, 열 합 50, 전체 200이므로 100×50/200=25100 \times 50 / 200 = 25 입니다. 실제 관측값 30과 5만큼 어긋납니다.
  4. x=(1,2,3,4,5)x = (1, 2, 3, 4, 5), y=(2,4,5,4,5)y = (2, 4, 5, 4, 5) 의 피어슨 상관계수에 가장 가까운 값은?
    ① 0.32
    ② 0.55
    ③ 0.77
    ④ 0.98
    ③. 평균은 각각 3과 4입니다. 편차곱의 합이 4+0+0+0+2=64+0+0+0+2=6, 제곱합이 각각 10과 6이므로 r=6/60≈0.775r = 6/\sqrt{60} \approx 0.775 입니다.
  5. 두 연속형 피처의 상관계수가 0.02로 나왔습니다. 「관계가 없다」고 결론짓기 전에 해야 할 일은?
    ① 표본 수를 늘린다
    ② 산점도를 그려 곡선 관계나 덩어리 구조를 확인한다
    ③ 교차표를 만든다
    ④ 카이제곱 검정을 돌린다
    ②. 피어슨 상관계수는 직선 관계만 재므로 U자 같은 곡선 관계는 0에 가깝게 나옵니다. ③·④는 범주형끼리를 볼 때 쓰는 도구입니다.
  6. 결측값이 얼마나 되는지 컬럼별로 한 번에 훑고 싶습니다. 가장 알맞은 것은?
    ① df.describe()
    ② df.summary()
    ③ dbutils.data.summarize(df)
    ④ df.stat.crosstab()
    ③. 결측 개수·비율과 분포 그림, 고유값 수를 컬럼마다 카드로 그려 줍니다.
  7. 「요금제(범주형)에 따라 월 사용액(연속형)이 다른가」를 보려 합니다. 가장 알맞은 조합은?
    ① 산점도와 상관계수
    ② 요금제별 상자그림과 범주별 평균·중앙값
    ③ 교차표와 카이제곱
    ④ 히스토그램 하나
    ②. 범주형 × 연속형은 범주마다 분포를 갈라 보는 자리입니다. ①은 연속형끼리, ③은 범주형끼리입니다.
  8. dbutils.data.summarize(df, precise=True)로 바꾸면 달라지는 것은?
    ① 결측값이 자동으로 채워진다
    ② 백분위수와 고유값 개수를 근사가 아니라 정확히 계산하고, 그만큼 느려진다
    ③ 문자열 컬럼이 제외된다
    ④ 결과가 DataFrame으로 반환된다
    ②. 기본값은 속도를 위한 근사 계산입니다.

이 절의 판단은 결국 하나로 모입니다. 무엇을 보고 싶은지가 도구를 정하고, 수치 하나로 끝내지 않는다. 상관계수 0.02와 카이제곱 2.67은 둘 다 「관계 없음」쪽으로 읽히지만, 앞은 그림을 더 봐야 확인되고 뒤는 기준값과 견줘야 말이 됩니다.

Databricks ML Associate 시험 노트 전체 보기