파이콘 2023에서 들은 내용과 후기입니다.

logo


1. 짠내나는 데이터 다루기 (부제 : 제한된 메모리로 다룰 수 있는 현실적인 데이터)

  • 로컬에서 큰 사이즈 데이터 다루기
  • 데이터가 30G 정도 되면 클라우드에서 분산처리 함. 로컬에서 잘 하지 않음
  • 그러나 그런 환경이 되지 않는다면? 제한된 장비로 어디까지 다룰 수 있는지
  • 오늘 내용은 32기가 환경에서 작성
  • 개인 장비는 4~64기가 정도
  • 8G 환경에서 32G보다 큰 파일을, 혹은 수백~수천개 파일을 메모리에 모두 로드해야 한다면? 아예 불러오는게 안 될 수도 있음. 심지어 메모리를 데이터 처리만 하는 데 쓰는 것도 아님 (여러 앱 켜 놓음)
  • 주어진 장비로 해야 한다면, 메모리 사용량을 줄이는 작업 환경으로 해야 함
    • 기본적으로는 다른 프로그램 제거/비활성화. 가상 메모리 설정 변경 등
    • 주피터라면 쓰지 않는 노트북 Shutdown or 주피터 재시작
  • 메모리 낭비요소 제거했다면, 이제는?
  • sklearn의 중장기 로드맵: pandas와의 호환성
  • pandas 제한 사항
    • 데이터를 메모리에 로드. 메모리보다 더 큰 데이터는 어려움
    • subset, 파생 변수 등 복사본 만들면, 메모리 더 늘어남
  • 메모리 사용량 줄이기
    • 샘플링. 필요한 행/열만
    • 청크
    • parquet 형식 사용하여 데이터 압축
    • 병렬처리
    • 분산처리 프레임워크 dask, vaex, Pyspark

메모리 사용 줄이는 방법

  • 한번에 불러오지 못한다면, 조금씩 나누기
    • 작은 크기로 축소 (행/열 제거)
    • 필요한 데이터만 subset으로 가공
  • Chunked Processing
    • 데이터를 작은 청크로 나누어 처리
    • 메모리에 한 번에 로드하지 않고, chunk size 지정하여 청크 단위로 반복적인 처리
    • Iterator 활용. 각 청크는 메모리에 로드되지 않음?
  • 파일 용량 줄이기 (다운캐스트)
    • parquet 포맷 활용
    • 열 지향 데이터 파일 형식. 열 기반 압축. 한 열은 같은 형식이기 때문에 압축에 유리
    • 메타 정보를 포함하기 때문에, 아주 작은 데이터는 오히려 사이즈가 늘어날 수 있음
    • Parquet Metadata: 파일의 구조, 스키마 정보, 저장된 행 수, 컬럼 정보, 압축/인코딩 방식 등 제공
  • 데이터 타입 변경
    • 판다스는 기본적으로 int64/float64. 가능하면 int8까지. object 형식인 str도 변경?
    • 다운캐스트 후 타입 변경하면 1/8까지 줄어들기도 함
    • 애초에 불러올 때 타입 지정할 수도 있지만, 그러면 int8 이상의 데이터가 있을 수 있음
    • 청크로 앞부분만 불러와서 타입 확정하고, 전체 데이터에 적용할 수도 있음
    • 다운사이징 연습: 캐글 데이터
      • Hotel Booking Demand: 29MB -> 5.6MB
  • multiprocessing: 특정 데이터를 여러 환경에서 불러올 때
  • 분산 컴퓨팅 프레임워크: Dask, Vaex 등
    • 근데 여기까지 안 가도, pandas 차원에서 사이즈 줄이고, 처리하면서 지우면 메모리 많이 아낄 수 있음
    • pandas와 유사한 API
  • DB 저장
    • 근데 로그 데이터는 보통 db보다 파일 단위로 저장
  • ML 기법 사용
    • 행렬분해를 통한 차원축소
    • 원본 정보 잃어버릴 수 있음

실제 데이터 적용

  • 국민건강보험공단_의약품처방정보
    • 공공데이터포털에서 가장 큰 데이터
    • 2009~2020 모두 다운받으면 31GB
  • 청크로 나누어 로드(이걸 일단 파일로 저장하여 메모리 아끼기) -> 다운캐스트 -> parquet로 저장 -> 청크 합치기
    • 31GB -> 5GB 정도가 됨
  • pandas.to_numeric
    • downcast 옵션 있음. 맞는 사이즈로 줄여줌
  • 큰 데이터 하나보다, 작은 데이터 여러 개가 처리가 빠른 듯
  • 1G 정도의 28개 파일 -> 10MB 정도의 409개 파일
  • 그래도 여전히 메모리 사용 크다면?
    • db처럼 정규화. 컬럼 분리
  • 분석(分析)의 사전적 의미는 ‘쪼개는 것’
    • 선거처럼 출구조사(표본조사)
    • 서브셋을 나눠 합치면 메모리 아낄 수 있음



2. Async state machine

파이썬으로 구현된 분산 시스템에서 시간이 오래 걸리는 작업의 추적 및 상태 관리에 대한 어려움과 이를 해결하기 위한 추상적 아이디어들을 제시합니다. 코드 예시가 있기는 하지만 상세한 파이썬 코드 구현은 없고 고수준으로 추상화된 예시만 나오는 가벼운 발표이니 이 점 염두에 두시기 바랍니다.

  • 분산 시스템
    • Task 하위에 여러 Subtask
    • 어떤 task는 굉장히 오래 걸릴 수 있음
    • 병렬 데이터 처리 작업 등에 사용. tast1은 1~50, task2는 51~100 등
  • Task Lifecycle
    • api serer에서 task의 상태를 여러 status로 정의하여 관리
      • Preparing, Running, Terminating, Error, Terminated 등
    • 근데 subtask도 비슷하게 상태 관리 로직 필요. substask와 task의 상태 관리 예외 처리 하려면 복잡해짐
  • asyncio 예외처리
    • subtask에 따라서 에러 발생시 상위 task의 상태를 지정하기도 함
  • state machine
    • 한 번에 하나의 상태만 가지는 머신
    • task를 하나의 state machine으로 간주
    • state: task의 상태와 해당 상태에서 실행해야 할 함수
    • event: 함수의 리턴값
  • 분산시스템: CAP Theorem
    • 이 중 Partition tolerance는 타협 안하는 요소? 네트워크 문제가 발생해도 시스템 동작. Retry 정책
  • Reconciliation loop
    • 각 컴포넌트들이 따로 동작하는 게 아니라, 중앙 저장소와 입출력
    • k8s도 이런 아키텍처?
    • RPC Call에 의한 예외처리가 아님. 그 자리에 DB가 들어옴



3. 로컬 환경에서 사이즈가 큰 데이터를 처리/분석하기 위한 전략: Pandas 2.0, HF Datasets

  • 판다스는 메모리를 많이 쓰는 구조
  • numpy는 pandas를 위한 구조가 아니어서, pandas로 변환하기 비효율적인 부분 있음
  • 싱글 머신을 위해 디자인됨. 분산 환경에 적합하지 않음

pandas 2.0

  • 2023.04 발표
  • 설치하면 자동으로 적용되며, 기존 버전과의 호환성 좋음
  • 메모리 효율성
  • 시계열 데이터 성능 향상
  • Nullable 데이터 타입. int가 null 있으면 float로 변경되던게 Nullable Int로 됨
  • CoW Improvement
    • copy on write. 변경과 동시에 쓰기?
    • 기존에는 데이터프레임 변경시, 카피본까지 메모리 참조
    • cow 개념: 메모리 안정성
    • chained assignment

Apache Arrow

  • 인메모리 데이터 위한 프레임워크. pandas와 integration 됨
  • 판다스에서 dtype="float32[pyarrow]" 와 같이 쓸 수 있음
  • string type: pd.Stringtype()
  • numpy 타입에 비해 속도 향상

버전 3개 실험

  • 0.24.2 / 2.0.3 / 2.0.3 with pyarrow
  • pd.read_csv(파일명, engine='pyarrow')
    • pyarrow 없이 하는거는 0.24.2와 큰 차이 없음
    • pyarrow 하면 훨씬 빨라짐. 근데 dtype이 변하는 건 아님
  • 파일 읽기,쓰기 속도
    • csv «« parquet < pickle, feather
    • 근데 pickle에서도 pyarrow가 더 빠름
    • 다만 pickle은 저장 사이즈가 큼. parquet 추천. Pyspark와도 호환 잘됨(압축률 좋음)
  • 실험 1: 행별 연산
    • Iteration(.iterrows, pd.DataFrame.apply) vs Vectorization (pd.Series, np.array)
    • 전자보다는 후자가 훨씬 빠름. 전자는 메모리 사용도 많음
    • 후자는 어떻게 쓰는거지?
  • 실험 2: 같은 연산 비교
    • sort_values.head vs nlargest
    • 모든 버전에서 후자가 훨씬 빠름. 메모리 사용도 줄임
  • 실험 3: 특정 조건 만족하는 행 select
    • 2.0에서 DataFrame.apply 속도가 빨라짐
    • df.merge > df.isin »» df.apply > List comprehension
  • Method Chaining
    • 이전 버전에서는 디버깅 어려운 문제 있었음
    • 3.10부터는 행 단위 오류 제공. 가독성이 좋아서 이제는 추천
    • cow 개선으로 인해, 가비지 콜렉터도 제공
    • 이제는 하나씩 할당하는 것에 비해 속도도 빨라짐. 메모리 사용도 줄임
  • 그래도 데이터가 로컬 hdd보다 크다면?
    • hugging face 데이터셋
    • 이거도 Apache Arrow 포맷. 메모리 제약 없이 불러올 수 있음



4. 반복적인 일이 싫은 선생님의 Python을 활용한 학교에서의 업무자동화 사례

  • 현직 수학교사
  • 업무자동화 사례 1: 학교생활기록부
    • 기록 & 점검하는 업무가 중요
    • 독서활동상황 입력 지침: “전체 학년 동안 동일한 책 중복하여 입력지 않음”
    • 인쇄된 생기부를 수기로 형광펜으로 중복된 책을 확인하고는 함
    • 생기부 담당자는 1,000명의 생기부 검토
    • 규칙이 아주 명확하여, 인쇄 대신 csv 파일 전처리하여 리포트 출력
    • 책 제목 오타가 있을 수 있음
      • 같은 문자열로 인식하는 방법 -> 형태소 분석 라이브러리 사용 (kiwi. 한국어 자연어처리 라이브러리)
      • 수학의 역사(지즈강) vs 수학의 역샤(지즈강): 형태소 분석하여 유사도 계산 가능
      • list 요소 개수(중복 허용) / set 요소 개수(중복 없음) 비율 계산하여, 중복이 많을수록 유사한 것으로 간주
      • n권의 책을 2권씩 비교. cutoff 이상인 경우에만 출력
  • 업무자동화 사례 2: 원터치 대시보드
    • 코로나 시기 온라인 과제 확인. 5개 반 150명의 과제 제출을 확인하고, 미제출시 독려해야 함
    • 과제별, 개인별로 클릭 처리해야 함
    • 원클릭으로 모든 반 학생들 중 미제출자 확인할 수 없을까?
    • selenium, requests 이용하여 로그인 후 시스템 접속
    • 그래서 미제출자 데이터 모음
  • 업무자동화 사례 2: 모둠을 랜덤 편성
    • 랜덤 아니더라도, 비슷한 학생들끼리 or 다양한 학생들끼리 편성하려먼 어떻게?
    • 적당히 랜덤성 주면서, 학생들 특성 고려한 조편성
    • 예시: E 6명, I 6명을 4개 조(3명씩)로 나눔. 한 조당 E/I 1~2명씩 편성
    • 가상 데이터: faker 라이브러리
    • 그룹에서 범주별 인원수의 표준편차가 작아지도록 편성
  • 이제 동료 선생님에게 코드 전달하거나, 매뉴얼, 프로토타입 제공 등의 요구 생김
    • 코드가 있는 건 서로 이해하기 어려움

Streamlit

  • 완성하신 웹앱
  • 퓨어 파이썬만으로 웹앱 구현 가능 (프론트 경험 전혀 필요x)
  • print 대신 st.write() 쓰면 되고, 마크다운 같이 작성
  • 파일 업로드하여 처리 가능. seaborn 이용하여 시각화도 가능
  • 안정적이진 않음. Django가 더 안정적



5. pandas와 PySpark로 데이터 워크로드 확장하기

  • databricks 개발자
  • pandas 워크로드를 어떻게 PySpark로 분산처리 하는가?
  • pandas는 분산처리가 안됨. 큰 컴퓨터를 쓰거나, 데이터 다운샘플링 하거나, 분산처리 프레임워크로 옮겨야 함(오늘 내용)
  • spark 구조
    • Driver가 Worker에게 task 명령
    • Worker는 하나씩의 Executor 있음. client로부터 받은 task 실행하여 Driver로 리턴
  • PySpark는 pandas와 구조가 다름. operation 할 때마다 데이터를 업데이트하는 구조가 아님. 불변성 DataFrame(rdd)
  • PySpark: Lazy Execution. pandas: Eager Execution
  • 다른점 표 참고(사진)

pandas api on spark

  • pyspark.pandas = pandas로 로컬에서 분산처리
  • import pyspark.pandas as pd 하면, 기존 워크로드에서 그대로 분산처리
    • pyspark.pandas DataFrame -> InternalFrame 거침(인덱스 지정) -> Spark DataFrame
  • 단일 노드에서 pandas보다 빠른 성능 (pandas는 싱글 코어)
  • 인덱스 종류
    • sequence
      • pandas의 lazy index와 같이, 순차적으로 1씩 증가함
      • 전체 파티션이 단일 노드에서만 처리될 수 있음 -> 큰 데이터는 지양
    • distributed-sequence
      • 1씩 증가
      • group by 방식. 분산처리에 적합
    • distributed
      • 1씩 증가하지 않으나, 순차적으로 증가x. 임의로 증가
      • 파티션별로 인덱스 할당하고, globally 1씩 증가
      • 가장 높은 성능
  • PySpark vs PySpark.pandas
    • pandas를 더 큰 데이터로 분산 처리 하고 싶다면, 후자
    • PySpark 배우고 싶고, 100% 기능 원한다면 PySpark

pandas udf and function API

  • pandas udf: scala udf, python udf와 동일. PySpark column 반환. Series 인풋 Series 아웃풋
  • pandas function API: PySpark DataFrame 반환. DataFrame 인풋, DataFrame 아웃풋
  • udf: 원하는 결과 형태에 따라 타입 힌트를 줌
    • 타입은 pd.Series, int(집계 값) 등
  • function API: Vectorization 방식
  • oom(out-of-memory) 문제: Salt
  • 로컬에서 돌려 보고, Spark에서 돌리는 식으로 사용
  • for 루프는 항상 Vectorization(e.g.numpy)을 우선으로 해 보고 생각해야 함. 효율성이 좋지 않음

Spark Connect

  • 많은 IDE들이 Spark를 잘 연결하지 못하고 있음. pycharm, jupyter 등
  • 언어 지원도 제한적
  • Spark Connect API: 응용 프로그램, IDE, 여러 언어를 통합하는 API Layer
    • DataFrame API, ML API 등 있음?
    • IDE에서 사용 가능한지 보기
  • 엣지 디바이스에서 jvm 같은거 설치하지 않아도, 클라이언트에서 python만 설치하면 가볍게 Spark 사용 가능. line별로 디버깅도 가능
    • 근데 spark는 Lazy Execution으로, 출력 전에 logical plan이 변경될 수 있음. line별 디버깅에 한계가 있어 보임