이번 주는 PySpark 기초부터 머신러닝 적용까지의 흐름을 학습하는 것을 목표로 하였습니다.
RDD, DataFrame의 구조와 동작 방식, Spark SQL을 이용한 데이터 분석, 그리고 PySpark MLlib을 활용한 회귀·분류 모델 구현 과정을 실습하였습니다.
추가로 파이프라인을 활용해 데이터 전처리·모델 학습 과정을 자동화하고, 실제 게임 데이터 분석 프로젝트를 수행하였습니다.
[PySpark를 활용해 데이터 처리부터 머신러닝 모델 구현까지 전체 흐름을 익히고, 파이프라인과 실제 데이터 분석 프로젝트를 통해 실전 적용 역량을 강화하는 것] 을 목표로 삼았습니다
expr 문법을 활용해 조건 검색, 그룹 집계, 조인, 윈도우 함수 등을 실습함이번 주에 실습하면서 겪었던 어려움이나 궁금증의 해결 과정을 기록하였습니다
다음은 마인크래프트 데이터를 분석하고 예측 하는 모델을 만드는 실습을 수행하면서 겪었던 문제점 입니다
캐글에서 머신러닝 실습용 데이터를 찾다가 마인크래프트를 주제로 한 흥미로워 보이는 데이터가 있어서 고르게 되었다
데이터 자체는 타겟 컬럼도 없고 게시글에서 요구하는 목표도 없었기에 주제를 스스로 정해야 했었는데 문제는 내가 마인크래프트를 한번도 플레이 해본 적도 없으며 유튜버들이 플레이 하는 것을 시청한 적도 없어 도메인 지식이 전무했다는 점이다
심지어 csv 파일도 15개나 되어서 처음에는 어떤 데이터 파일을 이용하고 주제를 정할지가 되게 막막 했었던 것 같다
그래서 마인크래프트(줄여서 마크)를 실제로 플레이 하는 다른 동기와 함께 데이터를 어떻게 다룰지 고민을 하며 실습을 진행하였다
덕분에 주제를 같이 정할 수 있게 되었는데 “어떠한 몬스터를 처치해야 허기짐을 잘 채울 수 있을까?” 라는 타겟을 정하게 되었다
마크에서는 몬스터를 잡으면 음식이 드롭이 되는데 음식마다 허기짐을 채우는 정도가 다르다
또한 몬스터마다 체력과 공격력이 달라 잡는 난이도가 상이하다 따라서 몬스터를 쓰러트리는데 들이는 수고 대비 채울 수 있는 허기짐 → 즉 배고픔을 채우는 효율이 가장 좋은 몬스터는 무엇인지 예측을 하는 것을 목표로 삼았다
mobs = mobs.withColumn("healthPoints", col("healthPoints").cast("double"))
mobs = mobs.withColumn("maxDamage", when(col("maxDamage").isNull(), 0).otherwise(col("maxDamage")).cast("double"))
mobs = mobs.withColumn("difficultyScore", col("healthPoints") + col("maxDamage") * 2)
food = food.withColumn("hunger", col("hunger").cast("double")) # 드롭 가치 = hunger
먼저 효율을 계산하기 위해 몬스터를 잡는 난이도를 새로 정의했는데 몬스터 테이블에 있는 체력(생명력)과 공격력을 조합해서 난이도를 산정하였다
아무래도 단순히 생명력이 많은 것보단 내가 맞았을때 높은 데미지가 들어오는게 더 부담이 크다고 판단을 하여 공격력에 가중치 * 2를 둬서 난이도를 계산하게 되었다
# 가성비 계산: 드롭 가치 / (사냥 난이도 + 1)
mob_efficiency = mob_efficiency.withColumn(
"efficiencyScore",
col("totalDropValue") / (col("difficultyScore") + 1)
하지만 예측률이 꽤나 떨어졌었고 난이도 컬럼의 수식에 문제가 있다고 판단되어 따라서 난이도(difficultyScore) 컬럼을 대신해서 체력과 공격력 컬럼을 선택하여 학습을 시키기로 하였다
# 5. 피처 엔지니어링: 필요 컬럼 선택
features = ["totalDropValue", "healthPoints", "maxDamage"]
그 결과 결정계수가 0.7대에서 0.84까지 오르게 되었다.
from pyspark.ml.feature import StandardScaler, VectorAssembler
num_assembler = VectorAssembler(inputCols=["totalDropValue", "healthPoints", "maxDamage"], outputCol= 'feature_vector')
stages += [num_assembler]
from pyspark.ml import Pipeline
pipeline = Pipeline(stages=stages)
fitted_transform = pipeline.fit(train_df)
vtrain_df = fitted_transform.transform(train_df)
vtrain_df.printSchema()
lr = LinearRegression(maxIter=50, solver='normal',
labelCol='efficiencyScore', featuresCol='feature_vector')
model = lr.fit(vtrain_df)
#테스트데이터도 변환
vtest_df = fitted_transform.transform(test_df)
#테스트데이터로 예측
pred = model.transform(vtest_df)
model.summary.r2, model.summary.rootMeanSquaredError
# output: 0.848, 0.041
다음은 마인크래프트 실습을 수행하면서 느낀점 입니다
게임의 데이터를 가지고 무언가를 예측해볼 수 있다는게 매력적으로 보여서 해당 게임의 도메인 지식이 없었지만 머신러닝 실습용 주제로 선택을 하게 되었습니다.
주제를 재미있어 보인다는 이유로 선택했지만 해당 게임에 대한 도메인 지식 부족으로 인해 분석 방향을 잡는 데 어려움이 있었습니다.
어떤 테이블을 결합하고, 어떤 컬럼을 제거할지 판단하는 과정에서 시간이 많이 소요되었고, 데이터 양 역시 충분하지 않아 모델 학습과 평가에 제약이 있었습니다.
이번 경험을 통해 다양한 CSV 파일을 결합해 새로운 주제를 시도하는 아이디어를 얻게 되었으며,
앞으로는 주제 선정 시 도메인 지식을 미리 확보해 전처리와 모델링 과정을 더 효율적으로 진행해야겠다고 느꼈습니다.
이번 주말에는 운전면허 시험 합격 예측 모델을 다시 다루면서 pyspark에서의 머신러닝 환경을 복습할 예정이며 추가로 ADSP 공부계획을 준비할 것입니다.