<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko"><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://leeyongjoo.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://leeyongjoo.github.io/" rel="alternate" type="text/html" hreflang="ko" /><updated>2021-02-08T17:56:07+09:00</updated><id>https://leeyongjoo.github.io/feed.xml</id><title type="html">leeyongjoo의 블로그</title><subtitle>안녕하세요🙋‍♂️하나씩 정리하는 개발공부로그입니다.
</subtitle><author><name>이용주</name><email>nyk700@naver.com</email></author><entry><title type="html">빅데이터 - Spark MLlib 모델 튜닝, PMML</title><link href="https://leeyongjoo.github.io/2021/02/05/big-data-spark-mllib-tuning-pmml" rel="alternate" type="text/html" title="빅데이터 - Spark MLlib 모델 튜닝, PMML" /><published>2021-02-05T00:00:00+09:00</published><updated>2021-02-05T00:00:00+09:00</updated><id>https://leeyongjoo.github.io/2021/02/05/big%20data%20spark%20mllib%20tuning%20pmml</id><content type="html" xml:base="https://leeyongjoo.github.io/2021/02/05/big-data-spark-mllib-tuning-pmml">&lt;h1 id=&quot;spark-mllib&quot;&gt;Spark MLlib&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;Spark MLlib 모델 튜닝&lt;/li&gt;
  &lt;li&gt;ML Pipeline 기반 머신러닝 모델 만들기&lt;/li&gt;
  &lt;li&gt;머신러닝 모델을 API를 이용하여 서빙하기&lt;/li&gt;
  &lt;li&gt;Spark 내용 총 정리&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;spark-mllib-모델-튜닝&quot;&gt;Spark MLlib 모델 튜닝&lt;/h2&gt;

&lt;p&gt;(ML Tuning)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;최적의 하이퍼 파라미터 선택
    &lt;ul&gt;
      &lt;li&gt;최적의 모델 혹은 모델의 파라미터를 찾는 것이 아주 중요&lt;/li&gt;
      &lt;li&gt;하나씩 테스트 하는 것 vs 다수를 동시에 테스트 하는 것&lt;/li&gt;
      &lt;li&gt;모델 선택의 중요한 부분은 테스트 방법
        &lt;ul&gt;
          &lt;li&gt;홀드 아웃, 교차 검증&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 보통 ML Pipeline 과 같이 사용&lt;/p&gt;

&lt;p&gt;📌 Spark MLlib 모델 테스트&lt;/p&gt;

&lt;p&gt;모델 테스트 방법은 크게 2가지가 존재&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;홀드 아웃(Train-Validation Split) - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TranValidationSplit&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;훈련용과 테스트용 데이터 기반 테스트&lt;/li&gt;
      &lt;li&gt;잘못 나눌경우 제대로 된 결과를 얻을 수 없다. → 교차 검증을 이용하여 해결&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;교차 검증(Cross Validation) - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CrossValidator&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;홀드 아웃(Train-Validation Split)을 반복하여 여러번 훈련 후 성능 지표를 계산하고 그것들의 평균을 내는 방법&lt;/li&gt;
      &lt;li&gt;K-Fold 테스트라고도 함&lt;/li&gt;
      &lt;li&gt;트레이닝 셋을 K 개의 서브셋으로 나누어 총 K 번을 훈련
        &lt;ul&gt;
          &lt;li&gt;i 번째 훈련 할 때는 다음을 반복
            &lt;ol&gt;
              &lt;li&gt;i 번째 서브셋을 빼고 훈련을 진행하여 모델 빌딩&lt;/li&gt;
              &lt;li&gt;i 번째 서브셋을 이용하여 테스트 수행&lt;/li&gt;
            &lt;/ol&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;👉 홀드아웃 테스트보다 더 안정적이다 (오버피팅 문제가 감소)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Spark MLlib 모델 튜닝(Tuning)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TranValidationSplit&lt;/code&gt; : 홀드아웃 기반 테스트 수행&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CrossValidator&lt;/code&gt; : 교차검증(K-Fold) 기반 테스트 수행&lt;/li&gt;
  &lt;li&gt;⭐ 3 개의 입력이 존재
    &lt;ul&gt;
      &lt;li&gt;Estimator : 머신러닝 모델 (혹은 ML Pipeline)&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Evaluator&lt;/strong&gt; : 머신러닝 모델의 성능을 나타내는 지표&lt;/li&gt;
      &lt;li&gt;Parameter : 훈련 반복 횟수 등의 하이퍼 파라미터
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ParamGridBuilder&lt;/code&gt;를 이용하여 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ParamGrid&lt;/code&gt; 타입의 변수 생성&lt;/li&gt;
          &lt;li&gt;예) 훈련 횟수, 트리의 최대 깊이 등&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 최종적으로 가장 결과가 좋은 모델을 리턴!&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;&lt;strong&gt;Evaluator&lt;/strong&gt;&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;머신러닝 모델 성능 측정에 사용되는 지표(metrics)&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evaluate&lt;/code&gt; 함수가 제공됨
    &lt;ul&gt;
      &lt;li&gt;테스트셋의 결과가 들어있는 &lt;strong&gt;데이터프레임&lt;/strong&gt;(prediction 컬럼이 존재)과 &lt;strong&gt;파라미터&lt;/strong&gt;(성능 지표 관련)를 입력
        &lt;ul&gt;
          &lt;li&gt;보통 이 데이터프레임은 머신러닝 모델의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transform&lt;/code&gt; 함수가 리턴해준 값&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;머신러닝 알고리즘에 따라 다양한 Evaluator가 제공됨
    &lt;ul&gt;
      &lt;li&gt;RegressionEvaluator, BinaryClassificationEvaluator (AUC가 성능 지표가 됨), MulticlassClassificationEvaluator, MultilableClassificationEvaluator, RankingEvaluaotr&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌  Spark MLlib 머신러닝 모델 빌딩 전체 프로세스&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;데이터프레임 기반 트레이닝 셋&lt;/li&gt;
  &lt;li&gt;ML Pipeline (Estimator)&lt;/li&gt;
  &lt;li&gt;머신러닝 모델&lt;/li&gt;
  &lt;li&gt;ML Tuning (TrainValidationSplit or CrossValidator)
    &lt;ul&gt;
      &lt;li&gt;Estimator(ML Pipeline), Evaluator, Parameter(ParamGrid)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;최종 모델&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;실습️-ml-pipeline-기반-머신러닝-모델-만들기&quot;&gt;실습🖥️: ML Pipeline 기반 머신러닝 모델 만들기&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;ML pipeline 사용하여 모델 빌딩&lt;/li&gt;
  &lt;li&gt;다양한 Transformer 사용
    &lt;ul&gt;
      &lt;li&gt;Imputer, StringIndexer, VectorAssembler&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;MinMaxScaler&lt;/strong&gt;를 사용하여 피쳐값을 0과 1 사이로 스케일링
        &lt;ul&gt;
          &lt;li&gt;기본적으로 VectorAssembler로 벡터로 변환된 피쳐컬럼에 적용&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;머신러닝 알고리즘으로 GBTClassifier와 LogisticRegression을 사용 (2개 생성)
    &lt;ul&gt;
      &lt;li&gt;📌 GBTClassifier(Gradient Boosted Tree Classfier)
        &lt;ul&gt;
          &lt;li&gt;의사결정 트리(Decision Tree)의 머신러닝 알고리즘&lt;/li&gt;
          &lt;li&gt;Regression과 Classification에 모두 사용 가능&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;모델 튜닝으로 CrossValidation을 사용하여 모델 파라미터 선택
    &lt;ul&gt;
      &lt;li&gt;Estimator - ML Pipeline을 인자로 지정&lt;/li&gt;
      &lt;li&gt;Evaluator - BinaryClassificationEvaluator 사용&lt;/li&gt;
      &lt;li&gt;ParamGrid - ParamGridBuilder를 사용하여 생성&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ML Pipeline 사용 절차&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;트레이닝 셋에 수행해야하는 feature transformer들을 생성&lt;/li&gt;
  &lt;li&gt;머신러닝 모델 알고리즘(Estimator)을 생성&lt;/li&gt;
  &lt;li&gt;순서대로 파이썬 리스트에 추가
    &lt;ul&gt;
      &lt;li&gt;머신러닝 알고리즘이 마지막으로 추가되어야 함&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;파이썬 리스트를 인자로 Pipeline 개체 생성&lt;/li&gt;
  &lt;li&gt;Pipeline 개체를 이용하여 모델 빌딩 → 2가지 방법 존재
    &lt;ul&gt;
      &lt;li&gt;Pipeline의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fit&lt;/code&gt; 함수를 호출하여 트레이닝 셋 데이터프레임 지정&lt;/li&gt;
      &lt;li&gt;ML Tuning의 입력으로 지정하여 여러 하이퍼 파라미터를 테스트해보고 결과가 가장 좋은 모델을 선택
        &lt;ul&gt;
          &lt;li&gt;이때 교차검증을 사용&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(예제) ML Pipleline 사용 - 타이타닉 생존 예측 모델&lt;/p&gt;

&lt;h3 id=&quot;logisticregression-이용&quot;&gt;LogisticRegression 이용&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;필요한 Transformer와 Estimator 들을 만들고 순서대로 리스트에 추가&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.ml.feature&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Imputer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StringIndexer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VectorAssembler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MinMaxScaler&lt;/span&gt;

 &lt;span class=&quot;c1&quot;&gt;# Gender
&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stringIndexer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StringIndexer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inputCol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Gender&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputCol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'GenderIndexed'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

 &lt;span class=&quot;c1&quot;&gt;# Age
&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imputer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Imputer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strategy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'mean'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputCols&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Age'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputCols&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'AgeImputed'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

 &lt;span class=&quot;c1&quot;&gt;# Vectorize
&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputCols&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Pclass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'SibSp'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Parch'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Fare'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'AgeImputed'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'GenderIndexed'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;assembler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VectorAssembler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inputCols&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inputCols&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputCol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;features&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

 &lt;span class=&quot;c1&quot;&gt;# MinMaxScaler
&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minmax_scaler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MinMaxScaler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inputCol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;features&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputCol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;features_scaled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

 &lt;span class=&quot;n&quot;&gt;stages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stringIndexer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;imputer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assembler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minmax_scaler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ul&gt;
      &lt;li&gt;stringIndexer : 문자를 숫자로 변환&lt;/li&gt;
      &lt;li&gt;imputer : 비어있는 값을 처리 (strategy에 따라 처리)&lt;/li&gt;
      &lt;li&gt;assembler : inputCols 컬럼들을 벡터로 만들어 하나의 컬럼에 적재&lt;/li&gt;
      &lt;li&gt;minmax_scaler : 값 범위를 0~1 사이로 변환&lt;/li&gt;
    &lt;/ul&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.ml.classification&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LogisticRegression&lt;/span&gt;

 &lt;span class=&quot;n&quot;&gt;algo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LogisticRegression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;featuresCol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;features_scaled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labelCol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Survived&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;lr_stages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;algo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

 &lt;span class=&quot;n&quot;&gt;lr_stages&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;# [StringIndexer_1976e7f16274,
&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#  Imputer_56fe707b5a4d,
&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#  VectorAssembler_98d57e0b3a89,
&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#  MinMaxScaler_b3dd5bb113e7,
&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#  LogisticRegression_7e7d6a154cc5]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ul&gt;
      &lt;li&gt;마지막에 알고리즘 추가&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;앞서 만든 리스트를 Pipeline의 인자로 지정&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.ml&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Pipeline&lt;/span&gt;

 &lt;span class=&quot;n&quot;&gt;pipeline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Pipeline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lr_stages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c1&quot;&gt;# evaluator 생성
&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.ml.evaluation&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BinaryClassificationEvaluator&lt;/span&gt;

 &lt;span class=&quot;n&quot;&gt;evaluator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BinaryClassificationEvaluator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;labelCol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Survived'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metricName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'areaUnderROC'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;💡 다음과 같이 pipeline을 이용하여 바로 모델 빌드 하는것도 가능!&lt;/p&gt;

        &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Survived'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Pclass'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Gender'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Age'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'SibSp'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Parch'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'Fare'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randomSplit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;lr_model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pipeline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;lr_cv_predictions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lr_model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.ml.evaluation&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BinaryClassificationEvaluator&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;evaluator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BinaryClassificationEvaluator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;labelCol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Survived'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metricName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'areaUnderROC'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;evaluator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;evaluate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lr_cv_predictions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# 0.8671428571428581
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;ML Tuning - ParamGrid와 CrossValidator 생성&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.ml.tuning&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParamGridBuilder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrossValidator&lt;/span&gt;

 &lt;span class=&quot;n&quot;&gt;paramGrid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParamGridBuilder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addGrid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;algo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxIter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

 &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrossValidator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;estimator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pipeline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;estimatorParamMaps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paramGrid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;evaluator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;evaluator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;numFolds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

 &lt;span class=&quot;c1&quot;&gt;# Run cross validations.
&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cvModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;lr_cv_predictions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cvModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;evaluator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;evaluate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lr_cv_predictions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;# 0.8676819407008096
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cv.fit()&lt;/code&gt; 는 교차 검증을 수행하고 가장 좋은 모델을 리턴&lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;어느 하이퍼 파라미터 조합이 최선의 결과를 냈는지 알고 싶다면&lt;/p&gt;

        &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;params&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cvModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getEstimatorParamMaps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cvModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getEvaluator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getMetricName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metric&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metric&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cvModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;avgMetrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# 	  areaUnderROC  maxIter
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 0	  0.826748	    1
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 1	  0.838885	    5
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 2	  0.845797	    10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;gbt-classifier-이용&quot;&gt;GBT Classifier 이용&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;위의 과정에서 알고리즘 추가 이전 과정은 동일&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.ml.classification&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GBTClassifier&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;gbt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GBTClassifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;featuresCol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;features_scaled&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labelCol&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Survived&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;gbt_stages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gbt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;gbt_stages&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# [StringIndexer_1976e7f16274,
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;#  Imputer_56fe707b5a4d,
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;#  VectorAssembler_98d57e0b3a89,
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;#  MinMaxScaler_b3dd5bb113e7,
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;#  GBTClassifier_2fe98abcabe9]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.ml&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Pipeline&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pipeline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Pipeline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stages&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gbt_stages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.ml.tuning&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ParamGridBuilder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrossValidator&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;paramGrid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParamGridBuilder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
               &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addGrid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gbt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxDepth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
               &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addGrid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gbt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxBins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
               &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addGrid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gbt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxIter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
               &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CrossValidator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;estimator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pipeline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;estimatorParamMaps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paramGrid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;evaluator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;evaluator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;numFolds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Run cross validations.
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;cvModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;lr_cv_predictions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cvModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;evaluator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;evaluate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lr_cv_predictions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# 0.8682479784366579
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;pmml&quot;&gt;PMML&lt;/h1&gt;

&lt;p&gt;다양한 머신러닝 개발 플랫폼들이 존재&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Scikit-Learn, PyTorch, Tensorflow 등 (Spark MLlib 포함)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;다양한 머신러닝 개발 플랫폼이 공통적으로 지원해주는 파일 포맷이 있다면 머신러닝 모델 서빙환경의 통일이 가능!&lt;/p&gt;

&lt;p&gt;👉 PMML, MLeap이 대표적인 범용 머신러닝 모델 파일포맷&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;이러한 공통 파일 포맷이 지원해주는 기능이 미약하여 복잡된 모델의 경우 지원 불가&lt;/p&gt;
&lt;/blockquote&gt;

&lt;dl&gt;
  &lt;dt&gt;PMML&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;Machine Learning 모델을 마크업 언어로 표현해주는 XML 언어 (Predictive Model Markup Language)&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;간단한 입력 데이터 전처리와 후처리 지원 (하지만 제약사항이 많음)&lt;/li&gt;
  &lt;li&gt;PySpark에서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyspark2pmml&lt;/code&gt; 을 사용
    &lt;ul&gt;
      &lt;li&gt;내부적으로 자바 jar 파일(jpmml-sparkml) 사용&lt;/li&gt;
      &lt;li&gt;너무 복잡함&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;전체적인-절차&quot;&gt;전체적인 절차&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;ML Pipeline을 PMML 파일로 저장
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyspark2pmml&lt;/code&gt; 파이썬 모듈 설치 (jar 파일 설치 필요)&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyspark2pmml.PMMLBuilder&lt;/code&gt; 를 이용하여 ML Pipeline을 PMML 파일로 저장&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;PMML 파일을 기반으로 모델 예측 API로 론치
    &lt;ul&gt;
      &lt;li&gt;Openscoring 프레임워크 (Java)&lt;/li&gt;
      &lt;li&gt;AWS SageMaker&lt;/li&gt;
      &lt;li&gt;Flask + PyPMML&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;이 API로 승객정보를 보내고 예측 결과를 받는 클라이언트 코드 작성&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;예제&quot;&gt;예제&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;머신러닝 모델을 PMML 파일로 저장하는 예제&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark2pmml&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PMMLBuilder&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;pmmlBuilder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PMMLBuilder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sparkContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;train_fr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cvModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pmmlBuilder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buildFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;titinic.pmml&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cvModel&lt;/code&gt; : 머신러닝 모델 혹은 ML Pipeline&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;train_fr&lt;/code&gt; : 트레이닝셋 데이터프레임&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;PMML 파일을 PyPPML로 로딩하고 호출하는 예제&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pypmml&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# loading
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'single_iris_dectree.pmml'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# predict
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;predict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'sepal_lenght'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'sepal_width'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'petal_length'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'petal_width'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>이용주</name><email>nyk700@naver.com</email></author><category term="Programmers 인공지능 데브코스" /><category term="Big Data" /><category term="Spark MLlib" /><category term="PMML" /><summary type="html">Spark MLlib Spark MLlib 모델 튜닝 ML Pipeline 기반 머신러닝 모델 만들기 머신러닝 모델을 API를 이용하여 서빙하기 Spark 내용 총 정리 Spark MLlib 모델 튜닝 (ML Tuning) 최적의 하이퍼 파라미터 선택 최적의 모델 혹은 모델의 파라미터를 찾는 것이 아주 중요 하나씩 테스트 하는 것 vs 다수를 동시에 테스트 하는 것 모델 선택의 중요한 부분은 테스트 방법 홀드 아웃, 교차 검증 👉 보통 ML Pipeline 과 같이 사용 📌 Spark MLlib 모델 테스트 모델 테스트 방법은 크게 2가지가 존재 홀드 아웃(Train-Validation Split) - TranValidationSplit 훈련용과 테스트용 데이터 기반 테스트 잘못 나눌경우 제대로 된 결과를 얻을 수 없다. → 교차 검증을 이용하여 해결 교차 검증(Cross Validation) - CrossValidator 홀드 아웃(Train-Validation Split)을 반복하여 여러번 훈련 후 성능 지표를 계산하고 그것들의 평균을 내는 방법 K-Fold 테스트라고도 함 트레이닝 셋을 K 개의 서브셋으로 나누어 총 K 번을 훈련 i 번째 훈련 할 때는 다음을 반복 i 번째 서브셋을 빼고 훈련을 진행하여 모델 빌딩 i 번째 서브셋을 이용하여 테스트 수행 👉 홀드아웃 테스트보다 더 안정적이다 (오버피팅 문제가 감소) Spark MLlib 모델 튜닝(Tuning) TranValidationSplit : 홀드아웃 기반 테스트 수행 CrossValidator : 교차검증(K-Fold) 기반 테스트 수행 ⭐ 3 개의 입력이 존재 Estimator : 머신러닝 모델 (혹은 ML Pipeline) Evaluator : 머신러닝 모델의 성능을 나타내는 지표 Parameter : 훈련 반복 횟수 등의 하이퍼 파라미터 ParamGridBuilder를 이용하여 ParamGrid 타입의 변수 생성 예) 훈련 횟수, 트리의 최대 깊이 등 👉 최종적으로 가장 결과가 좋은 모델을 리턴! Evaluator 머신러닝 모델 성능 측정에 사용되는 지표(metrics) evaluate 함수가 제공됨 테스트셋의 결과가 들어있는 데이터프레임(prediction 컬럼이 존재)과 파라미터(성능 지표 관련)를 입력 보통 이 데이터프레임은 머신러닝 모델의 transform 함수가 리턴해준 값 머신러닝 알고리즘에 따라 다양한 Evaluator가 제공됨 RegressionEvaluator, BinaryClassificationEvaluator (AUC가 성능 지표가 됨), MulticlassClassificationEvaluator, MultilableClassificationEvaluator, RankingEvaluaotr 📌 Spark MLlib 머신러닝 모델 빌딩 전체 프로세스 데이터프레임 기반 트레이닝 셋 ML Pipeline (Estimator) 머신러닝 모델 ML Tuning (TrainValidationSplit or CrossValidator) Estimator(ML Pipeline), Evaluator, Parameter(ParamGrid) 최종 모델 실습🖥️: ML Pipeline 기반 머신러닝 모델 만들기 ML pipeline 사용하여 모델 빌딩 다양한 Transformer 사용 Imputer, StringIndexer, VectorAssembler MinMaxScaler를 사용하여 피쳐값을 0과 1 사이로 스케일링 기본적으로 VectorAssembler로 벡터로 변환된 피쳐컬럼에 적용 머신러닝 알고리즘으로 GBTClassifier와 LogisticRegression을 사용 (2개 생성) 📌 GBTClassifier(Gradient Boosted Tree Classfier) 의사결정 트리(Decision Tree)의 머신러닝 알고리즘 Regression과 Classification에 모두 사용 가능 모델 튜닝으로 CrossValidation을 사용하여 모델 파라미터 선택 Estimator - ML Pipeline을 인자로 지정 Evaluator - BinaryClassificationEvaluator 사용 ParamGrid - ParamGridBuilder를 사용하여 생성 ML Pipeline 사용 절차 트레이닝 셋에 수행해야하는 feature transformer들을 생성 머신러닝 모델 알고리즘(Estimator)을 생성 순서대로 파이썬 리스트에 추가 머신러닝 알고리즘이 마지막으로 추가되어야 함 파이썬 리스트를 인자로 Pipeline 개체 생성 Pipeline 개체를 이용하여 모델 빌딩 → 2가지 방법 존재 Pipeline의 fit 함수를 호출하여 트레이닝 셋 데이터프레임 지정 ML Tuning의 입력으로 지정하여 여러 하이퍼 파라미터를 테스트해보고 결과가 가장 좋은 모델을 선택 이때 교차검증을 사용 (예제) ML Pipleline 사용 - 타이타닉 생존 예측 모델 LogisticRegression 이용 필요한 Transformer와 Estimator 들을 만들고 순서대로 리스트에 추가 from pyspark.ml.feature import Imputer, StringIndexer, VectorAssembler, MinMaxScaler # Gender stringIndexer = StringIndexer(inputCol = &quot;Gender&quot;, outputCol = 'GenderIndexed') # Age imputer = Imputer(strategy='mean', inputCols=['Age'], outputCols=['AgeImputed']) # Vectorize inputCols = ['Pclass', 'SibSp', 'Parch', 'Fare', 'AgeImputed', 'GenderIndexed'] assembler = VectorAssembler(inputCols=inputCols, outputCol=&quot;features&quot;) # MinMaxScaler minmax_scaler = MinMaxScaler(inputCol=&quot;features&quot;, outputCol=&quot;features_scaled&quot;) stages = [stringIndexer, imputer, assembler, minmax_scaler] stringIndexer : 문자를 숫자로 변환 imputer : 비어있는 값을 처리 (strategy에 따라 처리) assembler : inputCols 컬럼들을 벡터로 만들어 하나의 컬럼에 적재 minmax_scaler : 값 범위를 0~1 사이로 변환 from pyspark.ml.classification import LogisticRegression algo = LogisticRegression(featuresCol=&quot;features_scaled&quot;, labelCol=&quot;Survived&quot;) lr_stages = stages + [algo] lr_stages # [StringIndexer_1976e7f16274, # Imputer_56fe707b5a4d, # VectorAssembler_98d57e0b3a89, # MinMaxScaler_b3dd5bb113e7, # LogisticRegression_7e7d6a154cc5] 마지막에 알고리즘 추가 앞서 만든 리스트를 Pipeline의 인자로 지정 from pyspark.ml import Pipeline pipeline = Pipeline(stages = lr_stages) # evaluator 생성 from pyspark.ml.evaluation import BinaryClassificationEvaluator evaluator = BinaryClassificationEvaluator(labelCol='Survived', metricName='areaUnderROC') 💡 다음과 같이 pipeline을 이용하여 바로 모델 빌드 하는것도 가능! df = data.select(['Survived', 'Pclass', 'Gender', 'Age', 'SibSp', 'Parch', 'Fare']) train, test = df.randomSplit([0.7, 0.3]) lr_model = pipeline.fit(train) lr_cv_predictions = lr_model.transform(test) from pyspark.ml.evaluation import BinaryClassificationEvaluator evaluator = BinaryClassificationEvaluator(labelCol='Survived', metricName='areaUnderROC') evaluator.evaluate(lr_cv_predictions) # 0.8671428571428581 ML Tuning - ParamGrid와 CrossValidator 생성 from pyspark.ml.tuning import ParamGridBuilder, CrossValidator paramGrid = (ParamGridBuilder() .addGrid(algo.maxIter, [1, 5, 10]) .build()) cv = CrossValidator( estimator=pipeline, estimatorParamMaps=paramGrid, evaluator=evaluator, numFolds=5 ) # Run cross validations. cvModel = cv.fit(train) lr_cv_predictions = cvModel.transform(test) evaluator.evaluate(lr_cv_predictions) # 0.8676819407008096 cv.fit() 는 교차 검증을 수행하고 가장 좋은 모델을 리턴 어느 하이퍼 파라미터 조합이 최선의 결과를 냈는지 알고 싶다면 import pandas as pd params = [{p.name: v for p, v in m.items()} for m in cvModel.getEstimatorParamMaps()] pd.DataFrame.from_dict([ {cvModel.getEvaluator().getMetricName(): metric, **ps} for ps, metric in zip(params, cvModel.avgMetrics) ]) # areaUnderROC maxIter # 0 0.826748 1 # 1 0.838885 5 # 2 0.845797 10 GBT Classifier 이용 위의 과정에서 알고리즘 추가 이전 과정은 동일 from pyspark.ml.classification import GBTClassifier gbt = GBTClassifier(featuresCol=&quot;features_scaled&quot;, labelCol=&quot;Survived&quot;) gbt_stages = stages + [gbt] gbt_stages # [StringIndexer_1976e7f16274, # Imputer_56fe707b5a4d, # VectorAssembler_98d57e0b3a89, # MinMaxScaler_b3dd5bb113e7, # GBTClassifier_2fe98abcabe9] from pyspark.ml import Pipeline pipeline = Pipeline(stages = gbt_stages) from pyspark.ml.tuning import ParamGridBuilder, CrossValidator paramGrid = (ParamGridBuilder() .addGrid(gbt.maxDepth, [2, 4, 6]) .addGrid(gbt.maxBins, [20, 60]) .addGrid(gbt.maxIter, [10, 20]) .build()) cv = CrossValidator( estimator=pipeline, estimatorParamMaps=paramGrid, evaluator=evaluator, numFolds=5 ) # Run cross validations. cvModel = cv.fit(train) lr_cv_predictions = cvModel.transform(test) evaluator.evaluate(lr_cv_predictions) # 0.8682479784366579 PMML 다양한 머신러닝 개발 플랫폼들이 존재 Scikit-Learn, PyTorch, Tensorflow 등 (Spark MLlib 포함) 다양한 머신러닝 개발 플랫폼이 공통적으로 지원해주는 파일 포맷이 있다면 머신러닝 모델 서빙환경의 통일이 가능! 👉 PMML, MLeap이 대표적인 범용 머신러닝 모델 파일포맷 이러한 공통 파일 포맷이 지원해주는 기능이 미약하여 복잡된 모델의 경우 지원 불가 PMML Machine Learning 모델을 마크업 언어로 표현해주는 XML 언어 (Predictive Model Markup Language) 간단한 입력 데이터 전처리와 후처리 지원 (하지만 제약사항이 많음) PySpark에서는 pyspark2pmml 을 사용 내부적으로 자바 jar 파일(jpmml-sparkml) 사용 너무 복잡함 전체적인 절차 ML Pipeline을 PMML 파일로 저장 pyspark2pmml 파이썬 모듈 설치 (jar 파일 설치 필요) pyspark2pmml.PMMLBuilder 를 이용하여 ML Pipeline을 PMML 파일로 저장 PMML 파일을 기반으로 모델 예측 API로 론치 Openscoring 프레임워크 (Java) AWS SageMaker Flask + PyPMML 이 API로 승객정보를 보내고 예측 결과를 받는 클라이언트 코드 작성 예제 머신러닝 모델을 PMML 파일로 저장하는 예제 from pyspark2pmml import PMMLBuilder pmmlBuilder = PMMLBuilder(spark.sparkContext, train_fr, cvModel) pmmlBuilder.buildFile(&quot;titinic.pmml&quot;) cvModel : 머신러닝 모델 혹은 ML Pipeline train_fr : 트레이닝셋 데이터프레임 PMML 파일을 PyPPML로 로딩하고 호출하는 예제 from pypmml import Model # loading model = Model.load('single_iris_dectree.pmml') # predict model.predict({'sepal_lenght': 5.1, 'sepal_width': 3.5, 'petal_length': 1.4, 'petal_width': 0.2})</summary></entry><entry><title type="html">빅데이터 - Spark MLlib</title><link href="https://leeyongjoo.github.io/2021/02/04/big-data-spark-mllib" rel="alternate" type="text/html" title="빅데이터 - Spark MLlib" /><published>2021-02-04T00:00:00+09:00</published><updated>2021-02-04T00:00:00+09:00</updated><id>https://leeyongjoo.github.io/2021/02/04/big%20data%20spark%20mllib</id><content type="html" xml:base="https://leeyongjoo.github.io/2021/02/04/big-data-spark-mllib"></content><author><name>이용주</name><email>nyk700@naver.com</email></author><category term="Programmers 인공지능 데브코스" /><category term="Big Data" /><category term="Spark MLlib" /><summary type="html"></summary></entry><entry><title type="html">빅데이터 - Spark SQL</title><link href="https://leeyongjoo.github.io/2021/02/03/big-data-spark-sql" rel="alternate" type="text/html" title="빅데이터 - Spark SQL" /><published>2021-02-03T00:00:00+09:00</published><updated>2021-02-03T00:00:00+09:00</updated><id>https://leeyongjoo.github.io/2021/02/03/big%20data%20spark%20sql</id><content type="html" xml:base="https://leeyongjoo.github.io/2021/02/03/big-data-spark-sql">&lt;h1 id=&quot;spark-sql&quot;&gt;Spark SQL&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;SQL 이란?&lt;/li&gt;
  &lt;li&gt;SQL 실습&lt;/li&gt;
  &lt;li&gt;Spark SQL 이란?&lt;/li&gt;
  &lt;li&gt;Spark SQL 실습&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;sql&quot;&gt;SQL&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;구조화된 데이터를 다루는데 사용
    &lt;ul&gt;
      &lt;li&gt;모든 대용량 데이터 웨어하우스는 SQL 기반
        &lt;ul&gt;
          &lt;li&gt;Redshift, Snowflake, BigQuery, Hive&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Spark도 SparkSQL을 지원&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데이터 분야에서 반드시 익혀야할 기본 기술&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;관계형-데이터베이스&quot;&gt;관계형 데이터베이스&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;대표적인 관계형 데이터베이스
    &lt;ul&gt;
      &lt;li&gt;서버 한대 - MySQL, Postgres, Oracle, …
        &lt;ul&gt;
          &lt;li&gt;빠른 응답 속도, 용량 한계&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;데이터 웨어하우스 - Redshift, Snowflake, BigQuery, Hive, …
        &lt;ul&gt;
          &lt;li&gt;큰 용량을 지원&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;관게형 데이터베이스는 &lt;strong&gt;테이블&lt;/strong&gt;이 존재
    &lt;ul&gt;
      &lt;li&gt;테이블 구조
        &lt;ul&gt;
          &lt;li&gt;테이블은 레코드로 구성&lt;/li&gt;
          &lt;li&gt;레코드는 하나 이상의 필드로 구성&lt;/li&gt;
          &lt;li&gt;필드(컬럼)는 이름과 타입으로 구성&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(예제) 웹서비스 사용자/세션 정보&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;사용자 ID&lt;/code&gt; : 보통 웹서비스에서는 등록된 사용자마다 유일한 ID를 부여&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;세션 ID&lt;/code&gt; : 사용자가 외부 링크 또는 직접 방문해서 올 경우 세션을 생성
    &lt;ul&gt;
      &lt;li&gt;세션을 만들어낸 소스를 채널이란 이름으로 기록해둠 (시간도 포함)&lt;/li&gt;
      &lt;li&gt;하나의 사용자 ID 는 여러 개의 세션 ID를 가질 수 있음&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 위 정보를 기반으로 다양한 데이터 분석과 지표 설정 가능 (마케팅, 사용자 트래픽 등)&lt;/p&gt;

&lt;p&gt;위의 예제를 데이터베이스와 테이블로 표현&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;raw_data 데이터베이스
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user_session_channel&lt;/code&gt; 테이블
        &lt;ul&gt;
          &lt;li&gt;컬럼명: userId, 타입: int&lt;/li&gt;
          &lt;li&gt;&lt;strong&gt;컬럼명: sessionId, 타입: varchar(32)&lt;/strong&gt;&lt;/li&gt;
          &lt;li&gt;컬럼명: channel, 타입: varchar(32)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;session_timestamp&lt;/code&gt; 테이블
        &lt;ul&gt;
          &lt;li&gt;&lt;strong&gt;컬럼명: sessionId, 타입: varchar(32)&lt;/strong&gt;&lt;/li&gt;
          &lt;li&gt;컬럼명: ts, 타입: timestamp&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;sql-소개&quot;&gt;SQL 소개&lt;/h3&gt;

&lt;dl&gt;
  &lt;dt&gt;SQL(Structured Query Language)&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;관계형 데이터베이스에 있는 데이터(테이블)를 질의하는 언어&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;두 종류의 언어로 구성(DDL, DML)&lt;/li&gt;
&lt;/ul&gt;

&lt;dl&gt;
  &lt;dt&gt;DDL(Data Definition Language)&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;테이블 구조 정의 언어&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;CREATE TABLE&lt;/li&gt;
  &lt;li&gt;DROP TABLE&lt;/li&gt;
  &lt;li&gt;ALTER TABLE&lt;/li&gt;
&lt;/ul&gt;

&lt;dl&gt;
  &lt;dt&gt;DML(Data Manipulation Language)&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;테이블 데이터 조작 언어&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;SELECT FROM&lt;/p&gt;

    &lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;필드&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;필드&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블명&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;선택조건&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;필드지정&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ASC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;DESC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;LIMIT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;INSERT INTO&lt;/li&gt;
  &lt;li&gt;UPDATE FROM&lt;/li&gt;
  &lt;li&gt;DELETE FROM&lt;/li&gt;
&lt;/ul&gt;

&lt;dl&gt;
  &lt;dt&gt;📌 테이블 조인(JOIN)&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;두개 이상의 테이블이나 데이터베이스를 연결하여 데이터를 검색하는 방법&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;INNER JOIN (교집합)&lt;/li&gt;
  &lt;li&gt;LEFT OUTER JOIN&lt;/li&gt;
  &lt;li&gt;RIGHT OUTER JOIN&lt;/li&gt;
  &lt;li&gt;FULL OUTER JOIN (합집합)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;️-sql-실습&quot;&gt;🖥️ SQL 실습&lt;/h2&gt;

&lt;p&gt;colab에서 Redshift 기반 SQL 실습&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;데이터베이스 테이블 (위의 예제의 테이블)
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw_data.session_timestamp&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raw_data.user_session_channel&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;분석할 것들
    &lt;ul&gt;
      &lt;li&gt;월별 세션 수&lt;/li&gt;
      &lt;li&gt;월별 사용자 수 (MAU; Monthly Active User)&lt;/li&gt;
      &lt;li&gt;월별 채널별 사용자 수&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;주비터 SQL 엔진 설정&lt;/p&gt;

    &lt;p&gt;SQL 엔진 로드&lt;/p&gt;

    &lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load_ext&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sql&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;관계형 데이터베이스 연결 (AWS의 Redshift)&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%sql postgresql://사용자ID:패스워드@호스트:포트번호/접속DB&lt;/code&gt;&lt;/p&gt;

    &lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;와&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PW&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;를&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;자신의&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;환경에&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;맞게&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;수정&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sql&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postgresql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;guest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Guest1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!*@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;learnde&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cduaw970ssvt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;northeast&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;redshift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amazonaws&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5439&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prod&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SELECT 실행&lt;/p&gt;

    &lt;p&gt;일별 세션ID 개수를 세션ID 개수에 대하여 내림차순으로 10개 출력&lt;/p&gt;

    &lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sql&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;DATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COUNT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sessionID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_timestamp&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;DESC&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;LIMIT&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;JOIN 추가&lt;/p&gt;

        &lt;p&gt;일별 방문 사용자 수&lt;/p&gt;

        &lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;o&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_session_channel&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;과&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_timestamp&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;테이블의&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;조인이&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;필요&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sql&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;DATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;COUNT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;userID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_timestamp&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_session_channel&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usc&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sessionID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;usc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sessionID&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;ORDER&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;BY&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;LIMIT&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;‘o’ 를 포함하는 채널의 개수&lt;/p&gt;

        &lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;sql&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;distinct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_session_channel&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channel&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ilike&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'%o%'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;distinct&lt;/code&gt;는 중복 제외, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ilike&lt;/code&gt;는 소문자 대문자 구분 하지 않음)&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;pandas와-연동&quot;&gt;pandas와 연동&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user_session_channel&lt;/code&gt; 테이블 정보 가져오기&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sql&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user_session_channel&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# sql.run.ResultSet
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# userid	sessionid	channel
# 0	779	7cdace91c487558e27ce54df7cdb299c	Instagram
# 1	230	94f192dee566b018e0acf31e1f99a2d9	Naver
# 2	369	7ed2d3454c5eea71148b11d0c25104ff	Youtube
# 3	248	f1daf122cde863010844459363cd31db	Naver
# 4	676	fd0efcca272f704a760c3b61dcc70fd0	Instagram
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;groupby&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;channel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# channel
# Facebook     16791
# Google       16982
# Instagram    16831
# Naver        16921
# Organic      16904
# Youtube      17091
# dtype: int64
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;groupby&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;channel&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sessionid&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# channel
# Facebook     16791
# Google       16982
# Instagram    16831
# Naver        16921
# Organic      16904
# Youtube      17091
# Name: sessionid, dtype: int64
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;session_timestamp&lt;/code&gt; 테이블 정보 가져오기&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sql&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;raw_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session_timestamp&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;df_st&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;새로운 컬럼 만들기 (date)&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;df_st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'date'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;df_st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'ts'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;%d-%02d-%02d&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;date 컬럼별로 세션 수를 카운트하고 date를 기준으로 내림차순 정렬&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;df_st&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;groupby&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;date&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sessionid&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reset_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'count'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;date&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ascending&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;spark-sql-1&quot;&gt;Spark SQL&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;SparkSQL과 Spark Core의 차이점&lt;/li&gt;
  &lt;li&gt;SparkSQL의 일반적인 사용법&lt;/li&gt;
&lt;/ul&gt;

&lt;dl&gt;
  &lt;dt&gt;SparkSQL&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;구조화된 데이터 처리를 위한 Spark 모듈&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;대화형 Spark 셸 제공&lt;/li&gt;
  &lt;li&gt;Dataframe을 SQL로 처리 가능
    &lt;ul&gt;
      &lt;li&gt;RDD 데이터나 외부 데이터(스토리지나 관계형 데이터베이스)를 Dataframe으로 변환한 후 처리&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;👉 데이터프레임은 테이블이 되고 sql 함수를 사용 가능&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;SparkSQL 사용하여 외부 데이터베이스 연결
    &lt;ul&gt;
      &lt;li&gt;외부 데이터베이스 기반으로 데이터프레임 생성
        &lt;ul&gt;
          &lt;li&gt;SparkSession의 read 함수를 사용하여 테이블 혹은 SQL 결과를 데이터프레임으로 읽어옴&lt;/li&gt;
          &lt;li&gt;📌 Redshift 연결 에제
            &lt;ol&gt;
              &lt;li&gt;SparkSession을 만들때 외부 데이터베이스에 맞는 JDBC jar 을 지정 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config&lt;/code&gt; 에 지정)&lt;/li&gt;
              &lt;li&gt;SparkSession의 read 함수를 호출
                &lt;ul&gt;
                  &lt;li&gt;로그인 정보와 읽어올 테이블 혹은 SQL 지정&lt;/li&gt;
                  &lt;li&gt;결과가 데이터프레임으로 리턴&lt;/li&gt;
                &lt;/ul&gt;
              &lt;/li&gt;
              &lt;li&gt;리턴된 데이터프레임에 테이블 이름 지정&lt;/li&gt;
              &lt;li&gt;SparkSession의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sql()&lt;/code&gt; 함수 사용&lt;/li&gt;
            &lt;/ol&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;️-spark-sql-실습&quot;&gt;🖥️ Spark SQL 실습&lt;/h2&gt;

&lt;p&gt;PySpark, Py4J 패키지 설치&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pyspark&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;3.0.1 &lt;span class=&quot;nv&quot;&gt;py4j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;0.10.9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Redshift 관련 JAR 파일을 설치&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /usr/local/lib/python3.6/dist-packages/pyspark/jars &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; wget https://s3.amazonaws.com/redshift-downloads/drivers/jdbc/1.2.20.1043/RedshiftJDBC42-no-awssdk-1.2.20.1043.jar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;📌 구글 colab 에서의 pyspark의 jars 디렉토리 경로:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/lib/python3.6/dist-packages/pyspark/jars&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spark Session&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;spark.jars를 통해 앞서 다운로드 받은 &lt;strong&gt;Redshift 연결을 위한 JDBC 드라이버&lt;/strong&gt;를 사용함 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.config(&quot;spark.jars&quot;, ...)&lt;/code&gt;)&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;from pyspark.sql import SparkSession

spark &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; SparkSession &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .builder &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .appName&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Python Spark SQL basic example&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .config&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;spark.jars&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;/usr/local/lib/python3.6/dist-packages/pyspark/jars/RedshiftJDBC42-no-awssdk-1.2.20.1043.jar&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .getOrCreate&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;sparksql-맛보기&quot;&gt;SparkSQL 맛보기&lt;/h3&gt;

&lt;p&gt;Pandas로 csv 파일 로드&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import pandas as pd

namegender_pd &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; pd.read_csv&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://s3-geospatial.s3-us-west-2.amazonaws.com/name_gender.csv&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

namegender_pd.head&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# name	gender&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 0	Adaleigh	F&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 1	Amryn	Unisex&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 2	Apurva	Unisex&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 3	Aryion	M&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 4	Alixia	F&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pandas 데이터프레임 ➡️ Spark 데이터프레임으로 변환&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;namegender_df &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; spark.createDataFrame&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;namegender_pd&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

namegender_df.printSchema&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# root&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#  |-- name: string (nullable = true)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#  |-- gender: string (nullable = true)&lt;/span&gt;

namegender_df.show&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# +----------+------+&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |      name|gender|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# +----------+------+&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |  Adaleigh|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |     Amryn|Unisex|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |    Apurva|Unisex|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |    Aryion|     M|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |    Alixia|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |Alyssarose|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |    Arvell|     M|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |     Aibel|     M|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |   Atiyyah|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |     Adlie|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |    Anyely|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |    Aamoni|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |     Ahman|     M|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |    Arlane|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |   Armoney|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |   Atzhiry|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# | Antonette|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |   Akeelah|     F|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# | Abdikadir|     M|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |    Arinze|     M|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# +----------+------+&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# only showing top 20 rows&lt;/span&gt;

namegender_df.groupBy&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;gender&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;.count&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;.collect&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [Row(gender='F', count=65),&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#  Row(gender='M', count=28),&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#  Row(gender='Unisex', count=7)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;📌 참고링크: &lt;a href=&quot;https://towardsdatascience.com/pyspark-and-sparksql-basics-6cb4bf967e53&quot;&gt;🔗&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;데이터프레임을 테이블 뷰로 만들어서 SparkSQL로 처리&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;createOrReplaceTempView : SparkSession이 살아있는 동안 존재&lt;/li&gt;
  &lt;li&gt;createGlobalTempView : Spark 드라이버가 살아있는 동안 존재&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;namegender_df.createOrReplaceTempView&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;namegender&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

namegender_group_df &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; spark.sql&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;SELECT gender, count(1) FROM namegender GROUP BY 1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

namegender_group_df.collect&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [Row(gender='F', count(1)=65),&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#  Row(gender='M', count(1)=28),&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#  Row(gender='Unisex', count(1)=7)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Redshift와 연결해서 테이블들을 데이터프레임으로 로딩&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user_session_channel_df &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; spark.read &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .format&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;jdbc&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .option&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;driver&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;com.amazon.redshift.jdbc42.Driver&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .option&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;url&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;jdbc:redshift://learnde.cduaw970ssvt.ap-northeast-2.redshift.amazonaws.com:5439/prod?user=guest&amp;amp;password=Guest1!*&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .option&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dbtable&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;raw_data.user_session_channel&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .load&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;

session_timestamp_df &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; spark.read &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .format&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;jdbc&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .option&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;driver&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;com.amazon.redshift.jdbc42.Driver&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .option&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;url&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;jdbc:redshift://learnde.cduaw970ssvt.ap-northeast-2.redshift.amazonaws.com:5439/prod?user=guest&amp;amp;password=Guest1!*&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .option&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dbtable&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;raw_data.session_timestamp&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    .load&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;session_timestamp_df&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# pyspark.sql.dataframe.DataFrame&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;테이블 뷰 생성 후 해당 뷰를 이용하여 sql 함수 실행&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;user_session_channel_df.createOrReplaceTempView&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user_session_channel&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
session_timestamp_df.createOrReplaceTempView&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;session_timestamp&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;channel_count_df &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; spark.sql&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&quot;
    SELECT channel, count(distinct userId) uniqueUsers
    FROM session_timestamp st
    JOIN user_session_channel usc ON st.sessionID = usc.sessionID
    GROUP BY 1
    ORDER BY 1
&quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;위의 sql문은 당장 실행되지 않고 아래 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.show()&lt;/code&gt; 메서드를 호출되면 그때 실행된다 → ⭐Lazy Execution 방식&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;channel_count_df
&lt;span class=&quot;c&quot;&gt;# DataFrame[channel: string, uniqueUsers: bigint]&lt;/span&gt;

channel_count_df.show&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# +---------+-----------+&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |  channel|uniqueUsers|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# +---------+-----------+&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# | Facebook|        889|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |   Google|        893|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |Instagram|        895|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |    Naver|        882|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |  Organic|        895|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# |  Youtube|        889|&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# +---------+-----------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;dl&gt;
  &lt;dt&gt;특정 조건에 맞는 데이터 조회 SQL문 실행 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;like&lt;/code&gt; 이용)&lt;/dt&gt;
  &lt;dd&gt;채널명에 ‘o’를 포함하고 있는 채널의 개수를 출력&lt;/dd&gt;
&lt;/dl&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;channel_with_o_count_df &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; spark.sql&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&quot;
    SELECT COUNT(1)
    FROM user_session_channel
    WHERE channel like '%o%'
&quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

channel_with_o_count_df.collect&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# [Row(count(1)=50864)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>이용주</name><email>nyk700@naver.com</email></author><category term="Programmers 인공지능 데브코스" /><category term="Big Data" /><category term="SQL" /><category term="Spark SQL" /><summary type="html">Spark SQL SQL 이란? SQL 실습 Spark SQL 이란? Spark SQL 실습 SQL 구조화된 데이터를 다루는데 사용 모든 대용량 데이터 웨어하우스는 SQL 기반 Redshift, Snowflake, BigQuery, Hive Spark도 SparkSQL을 지원 데이터 분야에서 반드시 익혀야할 기본 기술 관계형 데이터베이스 대표적인 관계형 데이터베이스 서버 한대 - MySQL, Postgres, Oracle, … 빠른 응답 속도, 용량 한계 데이터 웨어하우스 - Redshift, Snowflake, BigQuery, Hive, … 큰 용량을 지원 관게형 데이터베이스는 테이블이 존재 테이블 구조 테이블은 레코드로 구성 레코드는 하나 이상의 필드로 구성 필드(컬럼)는 이름과 타입으로 구성 (예제) 웹서비스 사용자/세션 정보 사용자 ID : 보통 웹서비스에서는 등록된 사용자마다 유일한 ID를 부여 세션 ID : 사용자가 외부 링크 또는 직접 방문해서 올 경우 세션을 생성 세션을 만들어낸 소스를 채널이란 이름으로 기록해둠 (시간도 포함) 하나의 사용자 ID 는 여러 개의 세션 ID를 가질 수 있음 👉 위 정보를 기반으로 다양한 데이터 분석과 지표 설정 가능 (마케팅, 사용자 트래픽 등) 위의 예제를 데이터베이스와 테이블로 표현 raw_data 데이터베이스 user_session_channel 테이블 컬럼명: userId, 타입: int 컬럼명: sessionId, 타입: varchar(32) 컬럼명: channel, 타입: varchar(32) session_timestamp 테이블 컬럼명: sessionId, 타입: varchar(32) 컬럼명: ts, 타입: timestamp SQL 소개 SQL(Structured Query Language) 관계형 데이터베이스에 있는 데이터(테이블)를 질의하는 언어 두 종류의 언어로 구성(DDL, DML) DDL(Data Definition Language) 테이블 구조 정의 언어 CREATE TABLE DROP TABLE ALTER TABLE DML(Data Manipulation Language) 테이블 데이터 조작 언어 SELECT FROM SELECT 필드1, 필드2, ... FROM 테이블명 WHERE 선택조건 ORDER BY 필드지정 [ASC|DESC] LIMIT N; INSERT INTO UPDATE FROM DELETE FROM 📌 테이블 조인(JOIN) 두개 이상의 테이블이나 데이터베이스를 연결하여 데이터를 검색하는 방법 INNER JOIN (교집합) LEFT OUTER JOIN RIGHT OUTER JOIN FULL OUTER JOIN (합집합) 🖥️ SQL 실습 colab에서 Redshift 기반 SQL 실습 데이터베이스 테이블 (위의 예제의 테이블) raw_data.session_timestamp raw_data.user_session_channel 분석할 것들 월별 세션 수 월별 사용자 수 (MAU; Monthly Active User) 월별 채널별 사용자 수 주비터 SQL 엔진 설정 SQL 엔진 로드 %load_ext sql 관계형 데이터베이스 연결 (AWS의 Redshift) %sql postgresql://사용자ID:패스워드@호스트:포트번호/접속DB # ID와 PW를 자신의 환경에 맞게 수정 %sql postgresql://guest:Guest1!*@learnde.cduaw970ssvt.ap-northeast-2.redshift.amazonaws.com:5439/prod SELECT 실행 일별 세션ID 개수를 세션ID 개수에 대하여 내림차순으로 10개 출력 %%sql SELECT DATE(ts) date, COUNT(sessionID) FROM raw_data.session_timestamp GROUP BY 1 ORDER BY 2 DESC LIMIT 10; JOIN 추가 일별 방문 사용자 수 # raw_data.user_session_channel과 raw_data.session_timestamp 테이블의 조인이 필요 %%sql SELECT DATE(st.ts) date, COUNT(usc.userID) FROM raw_data.session_timestamp st JOIN raw_data.user_session_channel usc ON st.sessionID = usc.sessionID GROUP BY 1 ORDER BY 1 LIMIT 10; ‘o’ 를 포함하는 채널의 개수 %%sql SELECT distinct channel FROM raw_data.user_session_channel WHERE channel ilike '%o%' (distinct는 중복 제외, ilike는 소문자 대문자 구분 하지 않음) pandas와 연동 user_session_channel 테이블 정보 가져오기 result = %sql SELECT * FROM raw_data.user_session_channel type(result) # sql.run.ResultSet df = result.DataFrame() df.head() # userid sessionid channel # 0 779 7cdace91c487558e27ce54df7cdb299c Instagram # 1 230 94f192dee566b018e0acf31e1f99a2d9 Naver # 2 369 7ed2d3454c5eea71148b11d0c25104ff Youtube # 3 248 f1daf122cde863010844459363cd31db Naver # 4 676 fd0efcca272f704a760c3b61dcc70fd0 Instagram df.groupby([&quot;channel&quot;]).size() # channel # Facebook 16791 # Google 16982 # Instagram 16831 # Naver 16921 # Organic 16904 # Youtube 17091 # dtype: int64 df.groupby([&quot;channel&quot;])[&quot;sessionid&quot;].count() # channel # Facebook 16791 # Google 16982 # Instagram 16831 # Naver 16921 # Organic 16904 # Youtube 17091 # Name: sessionid, dtype: int64 session_timestamp 테이블 정보 가져오기 result = %sql SELECT * FROM raw_data.session_timestamp df_st = result.DataFrame() 새로운 컬럼 만들기 (date) df_st['date'] = df_st['ts'].apply(lambda x: &quot;%d-%02d-%02d&quot; % (x.year, x.month, x.day)) date 컬럼별로 세션 수를 카운트하고 date를 기준으로 내림차순 정렬 df_st.groupby([&quot;date&quot;])[&quot;sessionid&quot;].count().reset_index(name='count').sort_values(&quot;date&quot;, ascending=False) Spark SQL SparkSQL과 Spark Core의 차이점 SparkSQL의 일반적인 사용법 SparkSQL 구조화된 데이터 처리를 위한 Spark 모듈 대화형 Spark 셸 제공 Dataframe을 SQL로 처리 가능 RDD 데이터나 외부 데이터(스토리지나 관계형 데이터베이스)를 Dataframe으로 변환한 후 처리 👉 데이터프레임은 테이블이 되고 sql 함수를 사용 가능 SparkSQL 사용하여 외부 데이터베이스 연결 외부 데이터베이스 기반으로 데이터프레임 생성 SparkSession의 read 함수를 사용하여 테이블 혹은 SQL 결과를 데이터프레임으로 읽어옴 📌 Redshift 연결 에제 SparkSession을 만들때 외부 데이터베이스에 맞는 JDBC jar 을 지정 (.config 에 지정) SparkSession의 read 함수를 호출 로그인 정보와 읽어올 테이블 혹은 SQL 지정 결과가 데이터프레임으로 리턴 리턴된 데이터프레임에 테이블 이름 지정 SparkSession의 sql() 함수 사용 🖥️ Spark SQL 실습 PySpark, Py4J 패키지 설치 !pip install pyspark==3.0.1 py4j==0.10.9 Redshift 관련 JAR 파일을 설치 !cd /usr/local/lib/python3.6/dist-packages/pyspark/jars &amp;amp;&amp;amp; wget https://s3.amazonaws.com/redshift-downloads/drivers/jdbc/1.2.20.1043/RedshiftJDBC42-no-awssdk-1.2.20.1043.jar 📌 구글 colab 에서의 pyspark의 jars 디렉토리 경로: /usr/local/lib/python3.6/dist-packages/pyspark/jars Spark Session spark.jars를 통해 앞서 다운로드 받은 Redshift 연결을 위한 JDBC 드라이버를 사용함 (.config(&quot;spark.jars&quot;, ...)) from pyspark.sql import SparkSession spark = SparkSession \ .builder \ .appName(&quot;Python Spark SQL basic example&quot;) \ .config(&quot;spark.jars&quot;, &quot;/usr/local/lib/python3.6/dist-packages/pyspark/jars/RedshiftJDBC42-no-awssdk-1.2.20.1043.jar&quot;) \ .getOrCreate() SparkSQL 맛보기 Pandas로 csv 파일 로드 import pandas as pd namegender_pd = pd.read_csv(&quot;https://s3-geospatial.s3-us-west-2.amazonaws.com/name_gender.csv&quot;) namegender_pd.head() # name gender # 0 Adaleigh F # 1 Amryn Unisex # 2 Apurva Unisex # 3 Aryion M # 4 Alixia F Pandas 데이터프레임 ➡️ Spark 데이터프레임으로 변환 namegender_df = spark.createDataFrame(namegender_pd) namegender_df.printSchema() # root # |-- name: string (nullable = true) # |-- gender: string (nullable = true) namegender_df.show() # +----------+------+ # | name|gender| # +----------+------+ # | Adaleigh| F| # | Amryn|Unisex| # | Apurva|Unisex| # | Aryion| M| # | Alixia| F| # |Alyssarose| F| # | Arvell| M| # | Aibel| M| # | Atiyyah| F| # | Adlie| F| # | Anyely| F| # | Aamoni| F| # | Ahman| M| # | Arlane| F| # | Armoney| F| # | Atzhiry| F| # | Antonette| F| # | Akeelah| F| # | Abdikadir| M| # | Arinze| M| # +----------+------+ # only showing top 20 rows namegender_df.groupBy([&quot;gender&quot;]).count().collect() # [Row(gender='F', count=65), # Row(gender='M', count=28), # Row(gender='Unisex', count=7)] 📌 참고링크: 🔗 데이터프레임을 테이블 뷰로 만들어서 SparkSQL로 처리 createOrReplaceTempView : SparkSession이 살아있는 동안 존재 createGlobalTempView : Spark 드라이버가 살아있는 동안 존재 namegender_df.createOrReplaceTempView(&quot;namegender&quot;) namegender_group_df = spark.sql(&quot;SELECT gender, count(1) FROM namegender GROUP BY 1&quot;) namegender_group_df.collect() # [Row(gender='F', count(1)=65), # Row(gender='M', count(1)=28), # Row(gender='Unisex', count(1)=7)] Redshift와 연결해서 테이블들을 데이터프레임으로 로딩 user_session_channel_df = spark.read \ .format(&quot;jdbc&quot;) \ .option(&quot;driver&quot;, &quot;com.amazon.redshift.jdbc42.Driver&quot;) \ .option(&quot;url&quot;, &quot;jdbc:redshift://learnde.cduaw970ssvt.ap-northeast-2.redshift.amazonaws.com:5439/prod?user=guest&amp;amp;password=Guest1!*&quot;) \ .option(&quot;dbtable&quot;, &quot;raw_data.user_session_channel&quot;) \ .load() session_timestamp_df = spark.read \ .format(&quot;jdbc&quot;) \ .option(&quot;driver&quot;, &quot;com.amazon.redshift.jdbc42.Driver&quot;) \ .option(&quot;url&quot;, &quot;jdbc:redshift://learnde.cduaw970ssvt.ap-northeast-2.redshift.amazonaws.com:5439/prod?user=guest&amp;amp;password=Guest1!*&quot;) \ .option(&quot;dbtable&quot;, &quot;raw_data.session_timestamp&quot;) \ .load() type(session_timestamp_df) # pyspark.sql.dataframe.DataFrame 테이블 뷰 생성 후 해당 뷰를 이용하여 sql 함수 실행 user_session_channel_df.createOrReplaceTempView(&quot;user_session_channel&quot;) session_timestamp_df.createOrReplaceTempView(&quot;session_timestamp&quot;) channel_count_df = spark.sql(&quot;&quot;&quot; SELECT channel, count(distinct userId) uniqueUsers FROM session_timestamp st JOIN user_session_channel usc ON st.sessionID = usc.sessionID GROUP BY 1 ORDER BY 1 &quot;&quot;&quot;) 위의 sql문은 당장 실행되지 않고 아래 .show() 메서드를 호출되면 그때 실행된다 → ⭐Lazy Execution 방식 channel_count_df # DataFrame[channel: string, uniqueUsers: bigint] channel_count_df.show() # +---------+-----------+ # | channel|uniqueUsers| # +---------+-----------+ # | Facebook| 889| # | Google| 893| # |Instagram| 895| # | Naver| 882| # | Organic| 895| # | Youtube| 889| # +---------+-----------+ 특정 조건에 맞는 데이터 조회 SQL문 실행 (like 이용) 채널명에 ‘o’를 포함하고 있는 채널의 개수를 출력 channel_with_o_count_df = spark.sql(&quot;&quot;&quot; SELECT COUNT(1) FROM user_session_channel WHERE channel like '%o%' &quot;&quot;&quot;) channel_with_o_count_df.collect() # [Row(count(1)=50864)]</summary></entry><entry><title type="html">빅데이터 - Spark</title><link href="https://leeyongjoo.github.io/2021/02/02/big-data-spark" rel="alternate" type="text/html" title="빅데이터 - Spark" /><published>2021-02-02T00:00:00+09:00</published><updated>2021-02-02T00:00:00+09:00</updated><id>https://leeyongjoo.github.io/2021/02/02/big%20data%20spark</id><content type="html" xml:base="https://leeyongjoo.github.io/2021/02/02/big-data-spark">&lt;h1 id=&quot;빅데이터&quot;&gt;빅데이터&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;빅데이터 정의와 예&lt;/li&gt;
  &lt;li&gt;Hadoop&lt;/li&gt;
  &lt;li&gt;Spark
    &lt;ul&gt;
      &lt;li&gt;소개&lt;/li&gt;
      &lt;li&gt;Spark 프로그래밍 개념(RDD, Dataframe, Dataset)&lt;/li&gt;
      &lt;li&gt;Spark vs Pandas&lt;/li&gt;
      &lt;li&gt;데이터 구조&lt;/li&gt;
      &lt;li&gt;개발환경&lt;/li&gt;
      &lt;li&gt;맛보기&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;빅데이터-정의와-예&quot;&gt;빅데이터 정의와 예&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;빅데이터 정의
    &lt;ul&gt;
      &lt;li&gt;“서버 한대로 처리할 수 없는 규모의 데이터”&lt;/li&gt;
      &lt;li&gt;“기존의 소프트웨어로는 처리할 수 없는 규모의 데이터”
        &lt;ul&gt;
          &lt;li&gt;오라클이나 MySQL과 같은 관계형 데이터베이스
            &lt;ul&gt;
              &lt;li&gt;분산환경을 염두에 두지 않음&lt;/li&gt;
              &lt;li&gt;Scale-up 접근방식 (메모리, CPU, 디스크 추가)&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;4V 관점
        &lt;ul&gt;
          &lt;li&gt;&lt;strong&gt;Volume&lt;/strong&gt;: 데이터의 크기가 &lt;strong&gt;대용량&lt;/strong&gt;인지&lt;/li&gt;
          &lt;li&gt;Velocity: 데이터의 처리 속도가 중요한지&lt;/li&gt;
          &lt;li&gt;Variety: 구조화/비구조화 데이터인지&lt;/li&gt;
          &lt;li&gt;Veracity: 데이터의 품질이 좋은지&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;빅데이터 예
    &lt;ul&gt;
      &lt;li&gt;모바일 디바이스&lt;/li&gt;
      &lt;li&gt;스마트 TV&lt;/li&gt;
      &lt;li&gt;각종 센서 데이터 (IoT 센서)&lt;/li&gt;
      &lt;li&gt;네트워킹 디바이스&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;hadoop&quot;&gt;Hadoop&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;대용량 처리 기술이란?
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;분산 환경&lt;/strong&gt; 기반 (1대 혹은 그 이상의 서버로 구성)
        &lt;ul&gt;
          &lt;li&gt;분산 컴퓨팅과 분산 파일 시스템이 필요&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Fault Tolerance&lt;/strong&gt; : 소수의 서버가 고장나도 동작해야 함&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;확장이 용이&lt;/strong&gt;해야 함 (Scale Out)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;dl&gt;
  &lt;dt&gt;하둡(Hadoop)&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;Doug Cutting이 구글랩 발표 논문들에 기반해 만든 오픈소스 프로젝트&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ol&gt;
  &lt;li&gt;2003년 The Google &lt;strong&gt;File System&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;2004년 &lt;strong&gt;MapReduce&lt;/strong&gt;: Simplified Data processing on Large Cluster&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;처음 시작은 Nutch라는 오픈 소스 검색엔진의 하부 프로젝트&lt;/li&gt;
  &lt;li&gt;두 개의 서브 시스템으로 구현됨 (Hadoop 1.0)
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HDFS&lt;/code&gt; ← 분산 파일 시스템&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MapReduce&lt;/code&gt; ← 분산 컴퓨팅 시스템
        &lt;ul&gt;
          &lt;li&gt;새로운 프로그래밍 방식으로 대용량 데이터 처리의 효율을 극대화하는데 맞춤&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;hdfs&quot;&gt;HDFS&lt;/h3&gt;

&lt;dl&gt;
  &lt;dt&gt;HDFS(Hadoop Distributed File System)&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;분산 파일 시스템&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;데이터를 블록단위로 저장&lt;/li&gt;
  &lt;li&gt;블록 복제 방식 (Replication)
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Fault tolerance&lt;/strong&gt;를 보장할 수 있는 방식으로 블록들이 저장됨&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;mapreduce&quot;&gt;MapReduce&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;MapReduce 프로그래밍의 문제점
    &lt;ul&gt;
      &lt;li&gt;작업에 따라서 복잡해짐
        &lt;ul&gt;
          &lt;li&gt;&lt;strong&gt;Hive&lt;/strong&gt; 처럼 MapReduce로 구현된 SQL 언어들이 다시 각광을 받게 됨&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;기본적으로 배치 작업에 최적화 (실시간 처리 ❌)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;MapReduce 프로그래밍 예제
    &lt;ul&gt;
      &lt;li&gt;Word Count : 문장이 주어지면 단어가 몇번 나오는지 카운트&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔥 하둡(Hadoop)을 이용한 데이터 시스템 구성&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;하둡은 Data Warehouse에 해당&lt;/li&gt;
  &lt;li&gt;워크플로우 관리에는 Airflow가 대세&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 Hadoop 1.0 → Hadoop 2.0&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/46367323/106577922-4bfda500-6582-11eb-9d29-d3d2f099292e.png&quot; alt=&quot;https://user-images.githubusercontent.com/46367323/106577922-4bfda500-6582-11eb-9d29-d3d2f099292e.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;사진출처: &lt;a href=&quot;http://annovate.blogspot.com/2014/07/big-data-hadoop-1x-vs-hadoop-2x.html&quot;&gt;http://annovate.blogspot.com/2014/07/big-data-hadoop-1x-vs-hadoop-2x.html&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;하둡 1.0
    &lt;ul&gt;
      &lt;li&gt;HDFS 위에 MapReduce 라는 분산 컴퓨팅 시스템이 도는 구조&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;하둡 2.0 (YARN 이라고 부르기도 함)
    &lt;ul&gt;
      &lt;li&gt;아키텍처가 크게 변경됨&lt;/li&gt;
      &lt;li&gt;Spark는 하둡 2.0 위에서 애플리케이션 레이어로 실행됨&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;spark&quot;&gt;Spark&lt;/h2&gt;

&lt;p&gt;Hadoop은 1세대 빅데이터 처리기술이고&lt;/p&gt;

&lt;p&gt;Spark은 2세대 빅데이터 기술이라고 할 수 있다.&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Spark&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;버클리 대학의 AMPLab에서 아파치 오픈소스 프로젝트로 2013년 시작&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;하둡의 뒤를 잇는 2세대 빅데이터 기술
    &lt;ul&gt;
      &lt;li&gt;하둡 2.0을 분산환경으로 사용 가능 (자체 분산환경을 지원하기도 함)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;MapReduce의 단점을 대폭적으로 개선
    &lt;ul&gt;
      &lt;li&gt;Pandas와 비슷함 (Pandas는 서버 한대, Spark는 다수 서버 분산환경)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Spark vs MapReduce
    &lt;ul&gt;
      &lt;li&gt;MapReduce
        &lt;ol&gt;
          &lt;li&gt;디스크 기반&lt;/li&gt;
          &lt;li&gt;하둡 위에서만 동작&lt;/li&gt;
          &lt;li&gt;키와 밸류 기반 프로그래밍&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
      &lt;li&gt;Spark
        &lt;ol&gt;
          &lt;li&gt;메모리 기반
            &lt;ul&gt;
              &lt;li&gt;메모리가 부족해지면 디스크 사용&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;하둡(YARN)이외에도 다른 분산 컴퓨팅 환경 지원&lt;/li&gt;
          &lt;li&gt;다양한 방식의 컴퓨팅을 지원
            &lt;ul&gt;
              &lt;li&gt;배치 프로그래밍, 스트리밍 프로그래밍, SQL, 머신 러닝, 그래프 분석 등&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Spark 구조
    &lt;ul&gt;
      &lt;li&gt;Driver Program : 여러개의 병렬적인 작업으로 나뉘어져&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;spark-프로그래밍-개념&quot;&gt;Spark 프로그래밍 개념&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;RDD(Resilient Distributed Dataset)
    &lt;ul&gt;
      &lt;li&gt;로우레벨 프로그래밍 API로 세밀한 제어가 가능&lt;/li&gt;
      &lt;li&gt;하지만 코딩의 복잡도 증가&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;DataFrame, Dataset (Pandas의 데이터프레임과 유사)
    &lt;ul&gt;
      &lt;li&gt;하이레벨 프로그래밍 API로 점점 많이 사용되는 추세&lt;/li&gt;
      &lt;li&gt;SparkSQL 사용 시에 사용하게 됨&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;보통 Scala, Java, Python을 사용&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;spark-vs-pandas&quot;&gt;Spark vs Pandas&lt;/h3&gt;

&lt;p&gt;📌 Pandas&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;파이썬으로 데이터 분석을 하는데 가장 기본이 되는 모듈 중의 하나
    &lt;ul&gt;
      &lt;li&gt;소규모의 구조화된 데이터(테이블 형태의 데이터)를 다루는데 최적
        &lt;ul&gt;
          &lt;li&gt;작은 크기의 데이터로 제약 (큰 데이터의 경우 Spark 사용)&lt;/li&gt;
          &lt;li&gt;병렬 처리를 지원하지 않음&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Pandas로 할 수 있는 일 예시
    &lt;ul&gt;
      &lt;li&gt;구조화된 데이터 읽어오고 저장
        &lt;ul&gt;
          &lt;li&gt;csv, json 등 다양한 포맷 지원&lt;/li&gt;
          &lt;li&gt;관계형 데이터베이스에서 읽어오는 것도 가능&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;다양한 통계 뽑기
        &lt;ul&gt;
          &lt;li&gt;컬럼 별 평균, 표준편차, 상관관계 계산 등&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;데이터 청소 (데이터 전처리)
        &lt;ul&gt;
          &lt;li&gt;NA 값 처리&lt;/li&gt;
          &lt;li&gt;정규화(normalization)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;시각화(visualization)
        &lt;ul&gt;
          &lt;li&gt;matplotlib를 이용하여 다양한 형태로 시각화&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;데이터-구조&quot;&gt;데이터 구조&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Spark 세션
    &lt;ul&gt;
      &lt;li&gt;Spark 프로그램의 시작은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SparkSession&lt;/code&gt;을 만드는 것&lt;/li&gt;
      &lt;li&gt;Spark 세션을 통해 Spark이 제공하는 다양한 기능 사용
        &lt;ul&gt;
          &lt;li&gt;Spark 컨텍스트, Hive 컨텍스트, SQL 컨텍스트&lt;/li&gt;
          &lt;li&gt;(Spark 2.0 이전에는 기능에 따라 다른 컨텍스트를 생성해야 했음)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Spark 데이터 구조 (3가지)
    &lt;ul&gt;
      &lt;li&gt;RDD (Resilient Distributed Dataset)
        &lt;ul&gt;
          &lt;li&gt;로우레벨 데이터로 클러스터내의 서버에 분산된 데이터를 지칭&lt;/li&gt;
          &lt;li&gt;레코드별로 존재하며 구조화된 데이터나 비구조화된 데이터 모두 지원&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Dataframe, Dataset
        &lt;ul&gt;
          &lt;li&gt;RDD 위에 만들어지는 하이레벨 데이터로 RDD와는 달리 필드 정보를 가지고 있음 (테이블)&lt;/li&gt;
          &lt;li&gt;Dataset은 Dataframe과 달리 타입 정보가 존재하며 컴파일 언어에서 사용가능
            &lt;ul&gt;
              &lt;li&gt;컴파일 언어: Scala/Java에서 사용가능&lt;/li&gt;
              &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PySpark&lt;/code&gt; 에서는 Dataframe을 사용 (&lt;strong&gt;SparkSQL을 사용하는 것이 일반적💡&lt;/strong&gt;)&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;RDD
    &lt;ul&gt;
      &lt;li&gt;변경이 불가능한 분산 저장된 데이터
        &lt;ul&gt;
          &lt;li&gt;RDD는 다수의 파티션으로 구성되고 Spark 클러스터 내 서버들에 나눠 저장됨&lt;/li&gt;
          &lt;li&gt;로우레벨의 함수형 변환 지원 (map, filter, flatMap 등)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;RDD가 아닌 일반 파이썬 데이터는 parallelize 함수로 RDD로 변환&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Dataframe 데이터프레임
    &lt;ul&gt;
      &lt;li&gt;RDD처럼 변경이 불가능한 분산 저장된 데이터&lt;/li&gt;
      &lt;li&gt;RDD와 다르게 관계형 데이터베이스 테이블처럼 &lt;strong&gt;컬럼&lt;/strong&gt;으로 나눠 저장
        &lt;ul&gt;
          &lt;li&gt;pandas의 dataframe과 거의 유사&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;다양한 데이터 소스 지원: 파일, Hive, 외부 데이터베이스, RDD 등&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Dataset 데이터셋 (Spark 1.6부터)
    &lt;ul&gt;
      &lt;li&gt;RDD와 SparkSQL의 최적화 엔진 두 가지 장점을 취함&lt;/li&gt;
      &lt;li&gt;타입이 있는 컴파일 언어에서만 사용 가능
        &lt;ul&gt;
          &lt;li&gt;Scala와 Java 에서만 지원 (Python ❌)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;개발-환경&quot;&gt;개발 환경&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;개인 컴퓨터에 설치하고 사용하는 방법
    &lt;ul&gt;
      &lt;li&gt;설치가 복잡함&lt;/li&gt;
      &lt;li&gt;spark-submit을 이용해 실행가능&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;각종 무료 노트북을 사용하는 방법⭐
    &lt;ul&gt;
      &lt;li&gt;구글 &lt;strong&gt;Colab&lt;/strong&gt; 이용⭐&lt;/li&gt;
      &lt;li&gt;제플린의 무료 노트북 사용&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;AWS의 EMR 클러스터 사용하는 방법
    &lt;ul&gt;
      &lt;li&gt;거의 프로덕션 호나경에 가까움&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;-spark-실습&quot;&gt;💻 Spark 실습&lt;/h2&gt;

&lt;p&gt;PySpark, Py4J 패키지 설치&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pip&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyspark&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;py4j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tl&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;drwxr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4096&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Feb&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample_data&lt;/span&gt;

&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sample_data&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;55504&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rw&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;18289443&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Feb&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mnist_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rw&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;36523880&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Feb&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mnist_train_small&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rw&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;   &lt;span class=&quot;mi&quot;&gt;301141&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Feb&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;california_housing_test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rw&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1706430&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Feb&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;california_housing_train&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rwxr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;     &lt;span class=&quot;mi&quot;&gt;1697&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Jan&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anscombe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rwxr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;      &lt;span class=&quot;mi&quot;&gt;930&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Jan&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;README&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;md&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;spark-session&quot;&gt;&lt;strong&gt;Spark Session&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Spark 2.0 부터 entry point로 사용 (이전에는 SparkContext 사용)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SparkSession&lt;/code&gt; 을 이용하여 RDD, 데이터프레임 등을 생성&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SparkSeesion.builder&lt;/code&gt; 를 호출하여 생성하며, 다양한 함수들을 통해 세부 설정 가능
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.master&lt;/code&gt; : 클러스터 호스트를 지정
        &lt;ul&gt;
          &lt;li&gt;local → 서버에 놀고 있는 spark&lt;/li&gt;
          &lt;li&gt;[&lt;em&gt;] → 숫자를 입력 (&lt;/em&gt;는 모두)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.getOrCreate()&lt;/code&gt; : appName에 해당하는 객체가 존재하면 그것을 가져오고 없으면 새로 생성&lt;/li&gt;
    &lt;/ul&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.sql&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SparkSession&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;spark&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SparkSession&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;\
          &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;master&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;local[*]&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;\
          &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;appName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'PySpark_Tutorial'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;\
          &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getOrCreate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;spark&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# SparkSession - in-memory
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# SparkContext
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Spark UI
&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Version
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# v3.0.1
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Master
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# local[*]
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# AppName
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# PySpark_Tutorial
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;python-객체를-rdd로-변환&quot;&gt;Python 객체를 RDD로 변환&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;python 리스트 생성&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;n&quot;&gt;name_list_json&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'{&quot;name&quot;: &quot;keeyong&quot;}'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'{&quot;name&quot;: &quot;benjamin&quot;}'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'{&quot;name&quot;: &quot;claire&quot;}'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

 &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&lt;/span&gt;

 &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name_list_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;jn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;# keeyong
&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# benjamin
&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# claire
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;python 리스트를 RDD로 변환&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;RDD로 변환되는 순간  Spark 클러스터의 서버들에 데이터가 나눠 저장됨 (파티션) → Lazy Execution 방식&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.parallelize()&lt;/code&gt; : RDD로 변환&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.collect()&lt;/code&gt; : 파이썬 객체로 출력&lt;/li&gt;
    &lt;/ul&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;n&quot;&gt;rdd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sparkContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parallelize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_list_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;rdd&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;# ParallelCollectionRDD[4] at readRDDFromFile at PythonRDD.scala:262
&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;# 3
&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;parsed_rdd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;parsed_rdd&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;# PythonRDD[3] at RDD at PythonRDD.scala:53
&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;parsed_rdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;# [{'name': 'keeyong'}, {'name': 'benjamin'}, {'name': 'claire'}]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;python 리스트를 데이터프레임으로 변환&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.sql.types&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StringType&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;spark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;createDataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_list_json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StringType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# 3
&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printSchema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# root
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;#  |-- value: string (nullable = true)
&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;df&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'*'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# [Row(value='{&quot;name&quot;: &quot;keeyong&quot;}'),
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;#  Row(value='{&quot;name&quot;: &quot;benjamin&quot;}'),
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;#  Row(value='{&quot;name&quot;: &quot;claire&quot;}')]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;컬럼 이름을 설정&lt;/p&gt;

        &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;parsed_name_rdd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;parsed_name_rdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ['keeyong', 'benjamin', 'claire']
&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyspark.sql&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Row&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Or some other column name
&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;df_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parsed_name_rdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toDF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;df_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;printSchema&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# root
&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# |-- name: string (nullable = true)
&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;df_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'name'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# [Row(name='keeyong'), Row(name='benjamin'), Row(name='claire')]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>이용주</name><email>nyk700@naver.com</email></author><category term="Programmers 인공지능 데브코스" /><category term="Big Data" /><category term="Spark" /><summary type="html">빅데이터 빅데이터 정의와 예 Hadoop Spark 소개 Spark 프로그래밍 개념(RDD, Dataframe, Dataset) Spark vs Pandas 데이터 구조 개발환경 맛보기 빅데이터 정의와 예 빅데이터 정의 “서버 한대로 처리할 수 없는 규모의 데이터” “기존의 소프트웨어로는 처리할 수 없는 규모의 데이터” 오라클이나 MySQL과 같은 관계형 데이터베이스 분산환경을 염두에 두지 않음 Scale-up 접근방식 (메모리, CPU, 디스크 추가) 4V 관점 Volume: 데이터의 크기가 대용량인지 Velocity: 데이터의 처리 속도가 중요한지 Variety: 구조화/비구조화 데이터인지 Veracity: 데이터의 품질이 좋은지 빅데이터 예 모바일 디바이스 스마트 TV 각종 센서 데이터 (IoT 센서) 네트워킹 디바이스 Hadoop 대용량 처리 기술이란? 분산 환경 기반 (1대 혹은 그 이상의 서버로 구성) 분산 컴퓨팅과 분산 파일 시스템이 필요 Fault Tolerance : 소수의 서버가 고장나도 동작해야 함 확장이 용이해야 함 (Scale Out) 하둡(Hadoop) Doug Cutting이 구글랩 발표 논문들에 기반해 만든 오픈소스 프로젝트 2003년 The Google File System 2004년 MapReduce: Simplified Data processing on Large Cluster 처음 시작은 Nutch라는 오픈 소스 검색엔진의 하부 프로젝트 두 개의 서브 시스템으로 구현됨 (Hadoop 1.0) HDFS ← 분산 파일 시스템 MapReduce ← 분산 컴퓨팅 시스템 새로운 프로그래밍 방식으로 대용량 데이터 처리의 효율을 극대화하는데 맞춤 HDFS HDFS(Hadoop Distributed File System) 분산 파일 시스템 데이터를 블록단위로 저장 블록 복제 방식 (Replication) Fault tolerance를 보장할 수 있는 방식으로 블록들이 저장됨 MapReduce MapReduce 프로그래밍의 문제점 작업에 따라서 복잡해짐 Hive 처럼 MapReduce로 구현된 SQL 언어들이 다시 각광을 받게 됨 기본적으로 배치 작업에 최적화 (실시간 처리 ❌) MapReduce 프로그래밍 예제 Word Count : 문장이 주어지면 단어가 몇번 나오는지 카운트 🔥 하둡(Hadoop)을 이용한 데이터 시스템 구성 하둡은 Data Warehouse에 해당 워크플로우 관리에는 Airflow가 대세 📌 Hadoop 1.0 → Hadoop 2.0 사진출처: http://annovate.blogspot.com/2014/07/big-data-hadoop-1x-vs-hadoop-2x.html 하둡 1.0 HDFS 위에 MapReduce 라는 분산 컴퓨팅 시스템이 도는 구조 하둡 2.0 (YARN 이라고 부르기도 함) 아키텍처가 크게 변경됨 Spark는 하둡 2.0 위에서 애플리케이션 레이어로 실행됨 Spark Hadoop은 1세대 빅데이터 처리기술이고 Spark은 2세대 빅데이터 기술이라고 할 수 있다. Spark 버클리 대학의 AMPLab에서 아파치 오픈소스 프로젝트로 2013년 시작 하둡의 뒤를 잇는 2세대 빅데이터 기술 하둡 2.0을 분산환경으로 사용 가능 (자체 분산환경을 지원하기도 함) MapReduce의 단점을 대폭적으로 개선 Pandas와 비슷함 (Pandas는 서버 한대, Spark는 다수 서버 분산환경) Spark vs MapReduce MapReduce 디스크 기반 하둡 위에서만 동작 키와 밸류 기반 프로그래밍 Spark 메모리 기반 메모리가 부족해지면 디스크 사용 하둡(YARN)이외에도 다른 분산 컴퓨팅 환경 지원 다양한 방식의 컴퓨팅을 지원 배치 프로그래밍, 스트리밍 프로그래밍, SQL, 머신 러닝, 그래프 분석 등 Spark 구조 Driver Program : 여러개의 병렬적인 작업으로 나뉘어져 Spark 프로그래밍 개념 RDD(Resilient Distributed Dataset) 로우레벨 프로그래밍 API로 세밀한 제어가 가능 하지만 코딩의 복잡도 증가 DataFrame, Dataset (Pandas의 데이터프레임과 유사) 하이레벨 프로그래밍 API로 점점 많이 사용되는 추세 SparkSQL 사용 시에 사용하게 됨 보통 Scala, Java, Python을 사용 Spark vs Pandas 📌 Pandas 파이썬으로 데이터 분석을 하는데 가장 기본이 되는 모듈 중의 하나 소규모의 구조화된 데이터(테이블 형태의 데이터)를 다루는데 최적 작은 크기의 데이터로 제약 (큰 데이터의 경우 Spark 사용) 병렬 처리를 지원하지 않음 Pandas로 할 수 있는 일 예시 구조화된 데이터 읽어오고 저장 csv, json 등 다양한 포맷 지원 관계형 데이터베이스에서 읽어오는 것도 가능 다양한 통계 뽑기 컬럼 별 평균, 표준편차, 상관관계 계산 등 데이터 청소 (데이터 전처리) NA 값 처리 정규화(normalization) 시각화(visualization) matplotlib를 이용하여 다양한 형태로 시각화 데이터 구조 Spark 세션 Spark 프로그램의 시작은 SparkSession을 만드는 것 Spark 세션을 통해 Spark이 제공하는 다양한 기능 사용 Spark 컨텍스트, Hive 컨텍스트, SQL 컨텍스트 (Spark 2.0 이전에는 기능에 따라 다른 컨텍스트를 생성해야 했음) Spark 데이터 구조 (3가지) RDD (Resilient Distributed Dataset) 로우레벨 데이터로 클러스터내의 서버에 분산된 데이터를 지칭 레코드별로 존재하며 구조화된 데이터나 비구조화된 데이터 모두 지원 Dataframe, Dataset RDD 위에 만들어지는 하이레벨 데이터로 RDD와는 달리 필드 정보를 가지고 있음 (테이블) Dataset은 Dataframe과 달리 타입 정보가 존재하며 컴파일 언어에서 사용가능 컴파일 언어: Scala/Java에서 사용가능 PySpark 에서는 Dataframe을 사용 (SparkSQL을 사용하는 것이 일반적💡) RDD 변경이 불가능한 분산 저장된 데이터 RDD는 다수의 파티션으로 구성되고 Spark 클러스터 내 서버들에 나눠 저장됨 로우레벨의 함수형 변환 지원 (map, filter, flatMap 등) RDD가 아닌 일반 파이썬 데이터는 parallelize 함수로 RDD로 변환 Dataframe 데이터프레임 RDD처럼 변경이 불가능한 분산 저장된 데이터 RDD와 다르게 관계형 데이터베이스 테이블처럼 컬럼으로 나눠 저장 pandas의 dataframe과 거의 유사 다양한 데이터 소스 지원: 파일, Hive, 외부 데이터베이스, RDD 등 Dataset 데이터셋 (Spark 1.6부터) RDD와 SparkSQL의 최적화 엔진 두 가지 장점을 취함 타입이 있는 컴파일 언어에서만 사용 가능 Scala와 Java 에서만 지원 (Python ❌) 개발 환경 개인 컴퓨터에 설치하고 사용하는 방법 설치가 복잡함 spark-submit을 이용해 실행가능 각종 무료 노트북을 사용하는 방법⭐ 구글 Colab 이용⭐ 제플린의 무료 노트북 사용 AWS의 EMR 클러스터 사용하는 방법 거의 프로덕션 호나경에 가까움 💻 Spark 실습 PySpark, Py4J 패키지 설치 !pip install pyspark==3.0.1 py4j==0.10.9 !ls -tl total 4 drwxr-xr-x 1 root root 4096 Feb 1 17:27 sample_data !ls -tl sample_data total 55504 -rw-r--r-- 1 root root 18289443 Feb 1 17:27 mnist_test.csv -rw-r--r-- 1 root root 36523880 Feb 1 17:27 mnist_train_small.csv -rw-r--r-- 1 root root 301141 Feb 1 17:27 california_housing_test.csv -rw-r--r-- 1 root root 1706430 Feb 1 17:27 california_housing_train.csv -rwxr-xr-x 1 root root 1697 Jan 1 2000 anscombe.json -rwxr-xr-x 1 root root 930 Jan 1 2000 README.md Spark Session Spark 2.0 부터 entry point로 사용 (이전에는 SparkContext 사용) SparkSession 을 이용하여 RDD, 데이터프레임 등을 생성 SparkSeesion.builder 를 호출하여 생성하며, 다양한 함수들을 통해 세부 설정 가능 .master : 클러스터 호스트를 지정 local → 서버에 놀고 있는 spark [] → 숫자를 입력 (는 모두) .getOrCreate() : appName에 해당하는 객체가 존재하면 그것을 가져오고 없으면 새로 생성 from pyspark.sql import SparkSession spark = SparkSession.builder\ .master(&quot;local[*]&quot;)\ .appName('PySpark_Tutorial')\ .getOrCreate() spark # SparkSession - in-memory # SparkContext # Spark UI # Version # v3.0.1 # Master # local[*] # AppName # PySpark_Tutorial Python 객체를 RDD로 변환 python 리스트 생성 name_list_json = [ '{&quot;name&quot;: &quot;keeyong&quot;}', '{&quot;name&quot;: &quot;benjamin&quot;}', '{&quot;name&quot;: &quot;claire&quot;}' ] import json for n in name_list_json: jn = json.loads(n) print(jn[&quot;name&quot;]) # keeyong # benjamin # claire python 리스트를 RDD로 변환 RDD로 변환되는 순간 Spark 클러스터의 서버들에 데이터가 나눠 저장됨 (파티션) → Lazy Execution 방식 .parallelize() : RDD로 변환 .collect() : 파이썬 객체로 출력 rdd = spark.sparkContext.parallelize(name_list_json) rdd # ParallelCollectionRDD[4] at readRDDFromFile at PythonRDD.scala:262 rdd.count() # 3 parsed_rdd = rdd.map(lambda el:json.loads(el)) parsed_rdd # PythonRDD[3] at RDD at PythonRDD.scala:53 parsed_rdd.collect() # [{'name': 'keeyong'}, {'name': 'benjamin'}, {'name': 'claire'}] python 리스트를 데이터프레임으로 변환 from pyspark.sql.types import StringType df = spark.createDataFrame(name_list_json, StringType()) df.count() # 3 df.printSchema() # root # |-- value: string (nullable = true) df.select('*').collect() # [Row(value='{&quot;name&quot;: &quot;keeyong&quot;}'), # Row(value='{&quot;name&quot;: &quot;benjamin&quot;}'), # Row(value='{&quot;name&quot;: &quot;claire&quot;}')] 컬럼 이름을 설정 parsed_name_rdd = rdd.map(lambda el:json.loads(el)[&quot;name&quot;]) parsed_name_rdd.collect() # ['keeyong', 'benjamin', 'claire'] from pyspark.sql import Row row = Row(&quot;name&quot;) # Or some other column name df_name = parsed_name_rdd.map(row).toDF() df_name.printSchema() # root # |-- name: string (nullable = true) df_name.select('name').collect() # [Row(name='keeyong'), Row(name='benjamin'), Row(name='claire')]</summary></entry><entry><title type="html">빅데이터 - 데이터 팀</title><link href="https://leeyongjoo.github.io/2021/02/01/big-data-data-team" rel="alternate" type="text/html" title="빅데이터 - 데이터 팀" /><published>2021-02-01T00:00:00+09:00</published><updated>2021-02-01T00:00:00+09:00</updated><id>https://leeyongjoo.github.io/2021/02/01/big%20data%20data%20team</id><content type="html" xml:base="https://leeyongjoo.github.io/2021/02/01/big-data-data-team">&lt;h1 id=&quot;빅데이터&quot;&gt;빅데이터&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;데이터 팀
    &lt;ul&gt;
      &lt;li&gt;역할&lt;/li&gt;
      &lt;li&gt;구성원&lt;/li&gt;
      &lt;li&gt;조직구조&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;모델 개발 시 고려할 점&lt;/li&gt;
  &lt;li&gt;데이터 관련 교훈&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;데이터-팀의-역할&quot;&gt;데이터 팀의 역할&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;데이터 팀의 미션
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;신뢰할 수 있는 데이터&lt;/strong&gt;를 바탕으로 부가가치 생성&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데이터 팀의 목표
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;정책 결정에 사용&lt;/strong&gt;
        &lt;ul&gt;
          &lt;li&gt;결정과학(Decision Science)라고 부르기도 함
            &lt;ul&gt;
              &lt;li&gt;&lt;strong&gt;데이터 참고 결정&lt;/strong&gt;(data informed decisions)을 가능하게 함&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;사용자의 서비스 경험 개선
        &lt;ul&gt;
          &lt;li&gt;머신 러닝과 같은 데이터 기반 알고리즘을 통해 개선
            &lt;ul&gt;
              &lt;li&gt;개인화를 바탕으로 추천과 검색 기능 제공&lt;/li&gt;
              &lt;li&gt;사람의 개입/도움이 필요&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;1-데이터-인프라-구축&quot;&gt;1. 데이터 인프라 구축&lt;/h3&gt;

&lt;p&gt;데이터 인프라 : 데이터 웨어하우스와 ETL&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;데이터 웨어하우스란?&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;회사에 필요한 모든 데이터를 모아놓은 중앙 데이터베이스 (SQL)&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;데이터의 크기에 맞게 어떤 데이터베이스를 사용할 지 선택&lt;/li&gt;
&lt;/ul&gt;

&lt;dl&gt;
  &lt;dt&gt;ETL(Extract, Transform, Load) 이란?&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;소스에 존재하는 데이터들을 데이터 웨어하우스로 복사해오는 코드를 지칭&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;Extract : 외부 데이터 소스에서 데이터를 추출&lt;/li&gt;
  &lt;li&gt;Transform : 데이터의 포맷을 원하는 형태로 변환&lt;/li&gt;
  &lt;li&gt;Load : 변환된 데이터를 최종적으로 데이터 웨어하우스로 적재&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-데이터-분석-수행&quot;&gt;2. 데이터 분석 수행&lt;/h3&gt;

&lt;dl&gt;
  &lt;dt&gt;데이터 분석이란?&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;회사와 팀별 중요 지표(metrics)를 정의하고 대시보스 형태로 &lt;strong&gt;시각화&lt;/strong&gt;(visualization) (중요지표 예: 매출액, 월간 사용자 수 등)&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dd&gt;
    &lt;p&gt;이외에도 데이터와 관련한 다양한 분석/리포팅 업무 수행&lt;/p&gt;
  &lt;/dd&gt;
  &lt;dt&gt;시각화 대시보드&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;보통 중요한 지표를 시간의 흐름과 보여줌&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;지표의 경우 3A(Accessible, Actionable, Auditable)가 중요&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-머신러닝인공지능-적용&quot;&gt;3. 머신러닝/인공지능 적용&lt;/h3&gt;

&lt;p&gt;데이터 인프라에 저장된 데이터를 기반으로 지도학습을 통해 머신러닝 모델들을 개발하여 추천, 검색 등을 개인화하는 것이 일반적인 패턴&lt;/p&gt;

&lt;h2 id=&quot;데이터-팀의-구성원&quot;&gt;데이터 팀의 구성원&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;데이터 엔지니어 (Data Engineer)
    &lt;ul&gt;
      &lt;li&gt;데이터 인프라 구축 (데이터 웨어하우스, ETL)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데이터 분석가 (Data Analyst)
    &lt;ul&gt;
      &lt;li&gt;데이터 웨어하우스의 데이터를 기반으로 지표를 만들고 시각화 (대시보드)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데이터 과학자 (Data Scientist)
    &lt;ul&gt;
      &lt;li&gt;과거 데이터를 기반으로 미래를 예측하는 머신러닝 모델을 만들어 고객들의 서비스 경험을 개선 (개인화, 자동화, 최적화 등)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;작은 회사에서는 한 사람이 몇개의 역할을 동시에 수행하기도 한다…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;데이터-엔지니어&quot;&gt;데이터 엔지니어&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;기본적으로 소프트웨어 엔지니어
    &lt;ul&gt;
      &lt;li&gt;보통은 파이썬 사용. 자바 혹은 스칼라와 같은 언어도 아는 것이 좋음&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데이터 인프라 구축
    &lt;ul&gt;
      &lt;li&gt;데이터 웨어하우스를 만들고 이를 관리 (보통 클라우드 사용)
        &lt;ul&gt;
          &lt;li&gt;예) AWS의 Redshift, 구글 클라우드의 BigQuery, 스노우플레이크(Snowflake)나 오픈 소스 기반의 Hadoop/Spark&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;ETL 코드를 작성하고 주기적으로 실행
        &lt;ul&gt;
          &lt;li&gt;예) 스케줄러로 Airflow 사용&lt;/li&gt;
          &lt;li&gt;(Airflow는 오픈소스 프로젝트로 파이썬 3 기반이며 에어비앤비, 우버, 리프트, 쿠팡 등에서 사용)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데이터 분석가와 과학자 지원&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;데이터-분석가&quot;&gt;데이터 분석가&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;비즈니스 인텔리전스를 책임
    &lt;ul&gt;
      &lt;li&gt;중요 지표를 정의하고 이를 대시보드 형태로 시각화
        &lt;ul&gt;
          &lt;li&gt;예) 대시보드 - 태블로(Tableau), 룩커(Looker) / 오픈소스 - 수퍼셋(Superset) 을 많이 사용&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;회사 내 다른 팀들의 데이터 관련 질문 대답&lt;/li&gt;
  &lt;li&gt;필요한 스킬셋
    &lt;ul&gt;
      &lt;li&gt;SQL, 통계적 지식&lt;/li&gt;
      &lt;li&gt;비즈니스 도메인에 관한 깊은 지식 💡&lt;/li&gt;
      &lt;li&gt;보통 코딩은 하지 않음&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;데이터-과학자&quot;&gt;데이터 과학자&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;머신러닝 형태로 사용자들의 경험을 개선
    &lt;ul&gt;
      &lt;li&gt;문제에 맞춰 가설을 세우고 데이터를 수집한 후에 예측 모델을 만들고 이를 테스트&lt;/li&gt;
      &lt;li&gt;테스트는 가능하면 &lt;strong&gt;A/B 테스트&lt;/strong&gt;를 수행하는 것이 좋음&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;필요한 스킬셋
    &lt;ul&gt;
      &lt;li&gt;머신러닝/인공지능에 대한 깊은 지식과 경험&lt;/li&gt;
      &lt;li&gt;코딩 능력 (파이썬과 SQL)&lt;/li&gt;
      &lt;li&gt;통계 지식, 수학 지식 (통계 &amp;gt; 수학)&lt;/li&gt;
      &lt;li&gt;⭐끈기와 열정 (박사 학위가 도움이 되는 이유 중의 하나)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;A/B 테스트란?&lt;/dt&gt;
  &lt;dd&gt;
    &lt;p&gt;온라인 서비스에서 새 기능의 임팩트를 객관적으로 측정하는 방법&lt;/p&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;ul&gt;
  &lt;li&gt;새로운 기능을 론치함으로 생기는 위험부담을 줄이는 방법
    &lt;ul&gt;
      &lt;li&gt;100%를 론치하는 것이 아니라 작게 시작하고 관찰 후 결정&lt;/li&gt;
      &lt;li&gt;예) 먼저 5%의 사용자에게만 론치하고 나머지 95%의 사용자와 중요 지표를 비교 → 별 문제 없으면 10%, 20% 점진적으로 키워감&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;2개의 그룹으로 나누고 시간을 두고 관련 지표를 비교
    &lt;ul&gt;
      &lt;li&gt;두 그룹의 특성은 비슷해야한다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;가설에 영향을 주는 지표를 미리 정하고 시작&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;데이터-팀의-조직구조&quot;&gt;데이터 팀의 조직구조&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;중앙집중 구조: 모든 데이터 팀원들이 하나의 팀으로 존재
    &lt;ul&gt;
      &lt;li&gt;일의 우선 순위는 중앙 데이터팀이 최종 결정&lt;/li&gt;
      &lt;li&gt;데이터 팀원들간의 지식과 경험의 공유가 쉬워지고 커리어 경로가 더 잘 보임&lt;/li&gt;
      &lt;li&gt;현업 부서의 만족도가 떨어짐&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;분산 구조: 데이터 팀이 현업 부서별로 존재
    &lt;ul&gt;
      &lt;li&gt;일의 우선순위는 각 팀별로 결정&lt;/li&gt;
      &lt;li&gt;지식과 경험의 공유가 힘들고 데이터 인프라나 데이터 공유가 힘들어짐&lt;/li&gt;
      &lt;li&gt;현업 부서의 만족도는 처음에는 좋지만 갈수록 힘들어짐&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;중앙집중과 분산의 하이드리드 모델
    &lt;ul&gt;
      &lt;li&gt;가장 이상적인 조직 구조&lt;/li&gt;
      &lt;li&gt;데이터 팀원들은 일부는 중앙에서 인프라적인 일을 수행하고, 일부는 현업팀으로 파견식으로 일하되 주기적으로 일을 변경&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;모델-개발-시-고려할-점&quot;&gt;모델 개발 시 고려할 점&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;누군가 모델 개발부터 최종 론치까지 책임질 사람이 필요&lt;/li&gt;
  &lt;li&gt;모델 개발 초기부터 개발/론치 과정을 구체화하고 소통
    &lt;ul&gt;
      &lt;li&gt;모델을 어떻게 검증할 것인지?&lt;/li&gt;
      &lt;li&gt;모델을 어떤 형태로 엔지니어들에게 넘길 것인지?&lt;/li&gt;
      &lt;li&gt;모델을 프로덕션에서 A/B 테스트할 것인지?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;개발된 모델이 바로 프로덕션에서 론치가능한 프로세스/프레임워크가 필요
    &lt;ul&gt;
      &lt;li&gt;예) R로 개발된 모델은 바로 프로덕션 론치 불가능&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;첫 모델 론치는 시작일 뿐 → 운영을 통해 점진적인 개선을 하는 것이 중요
    &lt;ul&gt;
      &lt;li&gt;피드팩 루프 필요
        &lt;ul&gt;
          &lt;li&gt;운영에서 생기는 데이터를 가지고 개선점 찾기
            &lt;ul&gt;
              &lt;li&gt;검색이라면 CTR(Click Through Rate)을 모니터링하고 모든 데이터를 기록&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;주기적으로 모델 재빌딩
            &lt;ul&gt;
              &lt;li&gt;온라인 러닝 : 모델이 프로덕션에서 사용되면서 계속적으로 업데이트 되는 방식의 머신러닝&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;수익 증대 필요
    &lt;ul&gt;
      &lt;li&gt;데이터를 통해 회사 수익에 긍정적인 영향을 주어야 함&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데이터 인프라
    &lt;ul&gt;
      &lt;li&gt;데이터 인프라 없이는 데이터 분석이나 모델링 불가능&lt;/li&gt;
      &lt;li&gt;고려할 점
        &lt;ul&gt;
          &lt;li&gt;클라우드 vs 직접 구성&lt;/li&gt;
          &lt;li&gt;배치 vs 실시간&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;데이터 품질
    &lt;ul&gt;
      &lt;li&gt;데이터 청소 작업 중요 (데이터 품질 유지에 노력 필요)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;중요 지표
    &lt;ul&gt;
      &lt;li&gt;지표를 세우는 것이 중요&lt;/li&gt;
      &lt;li&gt;지표의 계산에 있어서 객관성이 중요&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔥 간단한 솔루션으로 시작하는 것이 좋다. (한 큐에 모델을 완성하는 것 보다는 반복 기반의 점전적인 개발방식이 더 좋다)&lt;/p&gt;

&lt;p&gt;📌 요약&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;데이터 팀의 목표는 신뢰할 수 있는 데이터를 바탕으로 부가가치를 생성하는 것이다.&lt;/li&gt;
  &lt;li&gt;데이터 직군에는 엔지니어, 분석가, 과학가 이렇게 세 종류가 존재한다.&lt;/li&gt;
  &lt;li&gt;데이터 팀 조직 구조에는 중앙집중, 분산, 하이브리드의 세 종류가 존재한다.&lt;/li&gt;
  &lt;li&gt;모델 개발은 &lt;strong&gt;론치와 운영&lt;/strong&gt;에 초점을 맞춰야 한다.&lt;/li&gt;
  &lt;li&gt;데이터 팀의 존재 여부는 수익 증대이다.&lt;/li&gt;
  &lt;li&gt;단순한 솔루션이 제일 좋은 솔루션이다. (모든 문제에 딥러닝 사용 ❌)&lt;/li&gt;
&lt;/ul&gt;</content><author><name>이용주</name><email>nyk700@naver.com</email></author><category term="Programmers 인공지능 데브코스" /><category term="Big Data" /><summary type="html">빅데이터 데이터 팀 역할 구성원 조직구조 모델 개발 시 고려할 점 데이터 관련 교훈 데이터 팀의 역할 데이터 팀의 미션 신뢰할 수 있는 데이터를 바탕으로 부가가치 생성 데이터 팀의 목표 정책 결정에 사용 결정과학(Decision Science)라고 부르기도 함 데이터 참고 결정(data informed decisions)을 가능하게 함 사용자의 서비스 경험 개선 머신 러닝과 같은 데이터 기반 알고리즘을 통해 개선 개인화를 바탕으로 추천과 검색 기능 제공 사람의 개입/도움이 필요 1. 데이터 인프라 구축 데이터 인프라 : 데이터 웨어하우스와 ETL 데이터 웨어하우스란? 회사에 필요한 모든 데이터를 모아놓은 중앙 데이터베이스 (SQL) 데이터의 크기에 맞게 어떤 데이터베이스를 사용할 지 선택 ETL(Extract, Transform, Load) 이란? 소스에 존재하는 데이터들을 데이터 웨어하우스로 복사해오는 코드를 지칭 Extract : 외부 데이터 소스에서 데이터를 추출 Transform : 데이터의 포맷을 원하는 형태로 변환 Load : 변환된 데이터를 최종적으로 데이터 웨어하우스로 적재 2. 데이터 분석 수행 데이터 분석이란? 회사와 팀별 중요 지표(metrics)를 정의하고 대시보스 형태로 시각화(visualization) (중요지표 예: 매출액, 월간 사용자 수 등) 이외에도 데이터와 관련한 다양한 분석/리포팅 업무 수행 시각화 대시보드 보통 중요한 지표를 시간의 흐름과 보여줌 지표의 경우 3A(Accessible, Actionable, Auditable)가 중요 3. 머신러닝/인공지능 적용 데이터 인프라에 저장된 데이터를 기반으로 지도학습을 통해 머신러닝 모델들을 개발하여 추천, 검색 등을 개인화하는 것이 일반적인 패턴 데이터 팀의 구성원 데이터 엔지니어 (Data Engineer) 데이터 인프라 구축 (데이터 웨어하우스, ETL) 데이터 분석가 (Data Analyst) 데이터 웨어하우스의 데이터를 기반으로 지표를 만들고 시각화 (대시보드) 데이터 과학자 (Data Scientist) 과거 데이터를 기반으로 미래를 예측하는 머신러닝 모델을 만들어 고객들의 서비스 경험을 개선 (개인화, 자동화, 최적화 등) 작은 회사에서는 한 사람이 몇개의 역할을 동시에 수행하기도 한다… 데이터 엔지니어 기본적으로 소프트웨어 엔지니어 보통은 파이썬 사용. 자바 혹은 스칼라와 같은 언어도 아는 것이 좋음 데이터 인프라 구축 데이터 웨어하우스를 만들고 이를 관리 (보통 클라우드 사용) 예) AWS의 Redshift, 구글 클라우드의 BigQuery, 스노우플레이크(Snowflake)나 오픈 소스 기반의 Hadoop/Spark ETL 코드를 작성하고 주기적으로 실행 예) 스케줄러로 Airflow 사용 (Airflow는 오픈소스 프로젝트로 파이썬 3 기반이며 에어비앤비, 우버, 리프트, 쿠팡 등에서 사용) 데이터 분석가와 과학자 지원 데이터 분석가 비즈니스 인텔리전스를 책임 중요 지표를 정의하고 이를 대시보드 형태로 시각화 예) 대시보드 - 태블로(Tableau), 룩커(Looker) / 오픈소스 - 수퍼셋(Superset) 을 많이 사용 회사 내 다른 팀들의 데이터 관련 질문 대답 필요한 스킬셋 SQL, 통계적 지식 비즈니스 도메인에 관한 깊은 지식 💡 보통 코딩은 하지 않음 데이터 과학자 머신러닝 형태로 사용자들의 경험을 개선 문제에 맞춰 가설을 세우고 데이터를 수집한 후에 예측 모델을 만들고 이를 테스트 테스트는 가능하면 A/B 테스트를 수행하는 것이 좋음 필요한 스킬셋 머신러닝/인공지능에 대한 깊은 지식과 경험 코딩 능력 (파이썬과 SQL) 통계 지식, 수학 지식 (통계 &amp;gt; 수학) ⭐끈기와 열정 (박사 학위가 도움이 되는 이유 중의 하나) 📌 A/B 테스트란? 온라인 서비스에서 새 기능의 임팩트를 객관적으로 측정하는 방법 새로운 기능을 론치함으로 생기는 위험부담을 줄이는 방법 100%를 론치하는 것이 아니라 작게 시작하고 관찰 후 결정 예) 먼저 5%의 사용자에게만 론치하고 나머지 95%의 사용자와 중요 지표를 비교 → 별 문제 없으면 10%, 20% 점진적으로 키워감 2개의 그룹으로 나누고 시간을 두고 관련 지표를 비교 두 그룹의 특성은 비슷해야한다. 가설에 영향을 주는 지표를 미리 정하고 시작 데이터 팀의 조직구조 중앙집중 구조: 모든 데이터 팀원들이 하나의 팀으로 존재 일의 우선 순위는 중앙 데이터팀이 최종 결정 데이터 팀원들간의 지식과 경험의 공유가 쉬워지고 커리어 경로가 더 잘 보임 현업 부서의 만족도가 떨어짐 분산 구조: 데이터 팀이 현업 부서별로 존재 일의 우선순위는 각 팀별로 결정 지식과 경험의 공유가 힘들고 데이터 인프라나 데이터 공유가 힘들어짐 현업 부서의 만족도는 처음에는 좋지만 갈수록 힘들어짐 중앙집중과 분산의 하이드리드 모델 가장 이상적인 조직 구조 데이터 팀원들은 일부는 중앙에서 인프라적인 일을 수행하고, 일부는 현업팀으로 파견식으로 일하되 주기적으로 일을 변경 모델 개발 시 고려할 점 누군가 모델 개발부터 최종 론치까지 책임질 사람이 필요 모델 개발 초기부터 개발/론치 과정을 구체화하고 소통 모델을 어떻게 검증할 것인지? 모델을 어떤 형태로 엔지니어들에게 넘길 것인지? 모델을 프로덕션에서 A/B 테스트할 것인지? 개발된 모델이 바로 프로덕션에서 론치가능한 프로세스/프레임워크가 필요 예) R로 개발된 모델은 바로 프로덕션 론치 불가능 첫 모델 론치는 시작일 뿐 → 운영을 통해 점진적인 개선을 하는 것이 중요 피드팩 루프 필요 운영에서 생기는 데이터를 가지고 개선점 찾기 검색이라면 CTR(Click Through Rate)을 모니터링하고 모든 데이터를 기록 주기적으로 모델 재빌딩 온라인 러닝 : 모델이 프로덕션에서 사용되면서 계속적으로 업데이트 되는 방식의 머신러닝 수익 증대 필요 데이터를 통해 회사 수익에 긍정적인 영향을 주어야 함 데이터 인프라 데이터 인프라 없이는 데이터 분석이나 모델링 불가능 고려할 점 클라우드 vs 직접 구성 배치 vs 실시간 데이터 품질 데이터 청소 작업 중요 (데이터 품질 유지에 노력 필요) 중요 지표 지표를 세우는 것이 중요 지표의 계산에 있어서 객관성이 중요 🔥 간단한 솔루션으로 시작하는 것이 좋다. (한 큐에 모델을 완성하는 것 보다는 반복 기반의 점전적인 개발방식이 더 좋다) 📌 요약 데이터 팀의 목표는 신뢰할 수 있는 데이터를 바탕으로 부가가치를 생성하는 것이다. 데이터 직군에는 엔지니어, 분석가, 과학가 이렇게 세 종류가 존재한다. 데이터 팀 조직 구조에는 중앙집중, 분산, 하이브리드의 세 종류가 존재한다. 모델 개발은 론치와 운영에 초점을 맞춰야 한다. 데이터 팀의 존재 여부는 수익 증대이다. 단순한 솔루션이 제일 좋은 솔루션이다. (모든 문제에 딥러닝 사용 ❌)</summary></entry></feed>