97

9가지 사례로 익히는 고급 스파크 분석 - 맛보기

  • View
    277

  • Download
    3

Embed Size (px)

DESCRIPTION

샌디 라이자, 유리 레이저슨, 션 오언, 조시 윌스 지음 | 박상은, 권한철, 서양주 옮김 | 한빛미디어 | 2016년 07월 | 26,000원 ★ 스파크 실전편! 실무와 가장 가까운 경험을 제공한다. 이 책은 기능과 API를 단조롭게 나열하지 않는다. 현실과 동떨어진, 예제를 위한 예제를 따라 하지도 않는다. 대신 우리 주변에서 찾을 수 있고 우리 삶과 밀접한 실제 데이터를 가져와 함께 분석하고 다듬어본다. 그것도 하나가 아니라 9가지다. 음악 추천부터 이상 감지, 교통, 금융, 영상 데이터 등. 관심 가는 장을 먼저 봐도 좋고, 차례대로 천천히 따라 해봐도 좋다. 그럼 가장 진보한 분석 도구인 스파크로 다 함께 데이터의 바다를 항해해보자! ★ 현실 세계 데이터셋과 스파크의 만남 1. 오디오스크로블러(AudioScrobbler) 데이터셋으로 음악 추천하기 2. 의사 결정 나무로 산림 식생 분포 예측하기 3. K 평균 군집화로 네트워크 이상 감지하기 4. 숨은 의미 분석으로 위키백과 이해하기 5. 그래프엑스(GraphX)로 동시발생 네트워크 분석하기 6. 뉴욕 택시 운행 데이터로 위치 및 시간 데이터 분석하기 7. 몬테카를로 시뮬레이션으로 금융 리스크 추정하기 8. BDG 프로젝트와 유전체학 데이터 분석하기 9. 파이스파크(PySpark)와 썬더(Thunder)로 신경 영상 데이터 분석하기

Citation preview

9가지 사례로 익히는 고급 스파크 분석 : 현실 세계 빅데이터로 배우는 가장 실용적인 스파크 활용서

초판발행 2016년 7월 1일

지은이 샌디 라이자, 유리 레이저슨, 션 오언, 조시 윌스 / 옮긴이 박상은, 권한철, 서양주 / 펴낸이 김태헌

펴낸곳 한빛미디어 (주) / 주소 서울시 마포구 양화로 7길 83 한빛미디어(주) IT출판부 전화 02 – 325 – 5544 / 팩스 02 – 336 – 7124등록 1999년 6월 24일 제10 – 1779호 / ISBN 978 – 89 – 6848 – 289 – 2 93000

총괄 전태호 / 책임편집 김창수 / 기획·편집 이복연

디자인 표지·내지 여동일, 조판 백지선

영업 김형진, 김진불, 조유미 / 마케팅 박상용, 송경석, 변지영 / 제작 박성우, 김정우

이 책에 대한 의견이나 오탈자 및 잘못된 내용에 대한 수정 정보는 한빛미디어(주)의 홈페이지나 아래 이메일로

알려주십시오. 잘못된 책은 구입하신 서점에서 교환해 드립니다. 책값은 뒤표지에 표시되어 있습니다.

한빛미디어 홈페이지 www.hanbit.co.kr / 이메일 [email protected]

© 2016 HANBIT Media Inc.

Authorized Korean translation of the English edition of Advanced Analytics with Spark, ISBN 9781491912768 © 2015 Sandy Ryza, Uri Laserson, Sean Owen, and Josh WillsThis translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls

all rights to publish and sell the same.이 책의 저작권은 오라일리와 한빛미디어 (주)에 있습니다.

저작권법에 의해 한국 내에서 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다.

지금 하지 않으면 할 수 없는 일이 있습니다.

책으로 펴내고 싶은 아이디어나 원고를 메일 ( [email protected] ) 로 보내주세요. 한빛미디어(주)는 여러분의 소중한 경험과 지식을 기다리고 있습니다.

표지 동물은 송골매다. 이 매는 세상에서 가장 흔한 맹금류 중 하나로 남극을 제외한 모든 대륙에 서식한다.

또한, 도시, 열대 지역, 사막, 툰드라 등 다양한 환경에서 생존할 수 있다. 일부는 겨울과 여름 서식지 간

의 머나먼 여행을 한다.

송골매는 세상에서 가장 빨리 나는 새로, 시속 약 320km로 급강하할 수 있다. 참새나 오리와

같은 다른 새와 박쥐를 먹이로 하는데, 공중에서도 먹이를 낚아챌 수 있다.

다 자란 송골매의 날개는 푸른 잿빛을, 등은 어두운 갈색을 띠며, 담황색 배에는 갈색

점이, 하얀 얼굴에는 검은색 눈물점이 있다. 그리고 갈고리 모양의 부리와 강

한 발톱도 있다. 송골매의 영어 이름인 peregrine falcon은 라틴어의

peregrinus에서 온 말인데, 그 뜻은 방랑자다. 송골매는 매조련사들

의 사랑을 받아왔으며, 여러 세기에 걸쳐 사냥에 동원되었다.

오라일리 책의 표지에 등장하는 동물 중 상당수는 멸종 위기에 처해 있다. 이들 모두가 우리 세상에 소중한 존재다. 이 동

물들을 돕고 싶다면 animals.oreilly.com으로 가보자.

표지 그림은 라이데커의 『Royal Natural History』에서 가져왔다.

| 표지 설명 |

9가지 사례로 익히는 고급 스파크 분석

4

샌디 라이자 Sandy Ryza

클라우데라의 선임 데이터 과학자이자 아파치 스파크 프로젝트의 활동적인 컨트리뷰터다. 최근에

클라우데라에서 스파크 개발을 이끌었으며 지금은 고객들이 스파크를 사용해 다양한 형태의 분석을

구현하는 데 도움을 주고 있다. 또한 하둡 프로젝트의 관리 위원회 멤버이기도 하다.

유리 레이저슨 Uri Laserson

클라우데라의 선임 데이터 과학자이며, 하둡 생태계에서의 파이썬 활용에 주력하고 있다. 또한 고

객들이 다양한 문제에 하둡을 사용할 수 있도록 지원하고 있는데, 특히 생명 과학과 헬스 케어에 집

중하고 있다. 이전에는 MIT에서 생의공학biomedical engineering 박사 과정 중에 Good Start Genetics

라는 차세대 검진 회사를 공동 창업했다.

션 오언 Sean Owen

클라우데라의 유럽/중동/아프리카 대상 데이터 과학팀의 디렉터다. 아파치 머하웃Apache Mahout 기계

학습 프로젝트의 커미터이자 중요한 컨트리뷰터로, 머하웃의 Taste 추천 프레임워크를 개발했다.

션은 아파치 스파크의 커미터이기도 하다. 스파크, 스파크 스트리밍, 그리고 카프카로 개발한 하둡

에서 동작하는 실시간 대규모 학습을 위한 Oryx 프로젝트(예전에는 Myrrix라고 불렸던)를 만들

었다.

조시 윌스 Josh Wills

슬랙Slack 데이터 엔지니어링팀의 디렉터다. 전에는 클라우데라의 데이터 과학팀의 선임 디렉터로써

고객들과 함께 다양한 업계의 하둡 기반 솔루션을 개발했다. 자바로 최적화된 맵리듀스와 스파크 파

이프라인을 만드는 아파치 크런치Apache Crunch 프로젝트의 창설자이며 커미터를 맡고 있다. 클라우데

라에 합류하기 전에는 구글에서 광고 경매 시스템을 개발했고, Google+에서 사용하는 분석 인프

라의 개발을 이끌었다.

지은이 소개

5

박상은

컴퓨터에 붙은 그림을 보고 애플이라는 단어의 뜻을 알게 된 이 땅의 흔한 개발자 중 한 사람이다.

포항공과대학교에서 전산학을, 한국과학기술원에서 인공지능을 공부했으며, 그 덕분에 알파고와

스카이넷을 구분할 줄 아는 지혜를 갖추게 되었다. 메일, 브라우저, CMS, 도서 관리 시스템 등 일

관성을 찾기 어려운 다양한 프로젝트에 참여했으며 그 덕에 물에 물 탄 듯한 경력이 완성되는 듯했

으나, 최근 몇 년은 데이터 처리와 하둡과 관련한 연구 개발에 집중하고 있다. 현재 에스코어에서 하

둡 생태계를 이용한 데이터 플랫폼인 BigPodTM 개발에 참여하고 있으며, 특히 실시간으로 처리되

는 데이터의 수집과 시각화 사이의 시간 간격을 줄이는 데 관심이 있다.

권한철

에스코어의 빅데이터 플랫폼인 BigPodTM 개발자로 빅데이터 분석에 스파크를 활용하는 데 주력하

고 있다. 특히 실시간 스트리밍 데이터 분석과 통계 및 기계 학습 알고리즘을 활용한 데이터 분석에

관심이 많으며, 인간 생활을 이롭게 하는 기술과 제품을 만드는 것을 개발자로서의 삶의 목표로 하

고 있다.

서양주

한국과학기술원 학부에서 수학을, 서울대학교에서 석사과정으로 통계학을 전공하였으며, 티맥스소

프트를 시작으로 개발자로서 일하게 되었다. 그 후 에스코어에서 2013년 하둡과 스파크를 접한 이

후로 빅데이터 분석 업무를 주 업무로 수행하게 되었다. 현재는 카카오 RUBICS TF에서 실시간 콘

텐츠 추천 업무를 하고 있다.

옮긴이 소개

6

버클리에서 스파크 프로젝트를 시작한 이래로, 나는 단순히 빠른 병렬 시스템을 구축한다는 사

실보다는 점점 더 많은 사람이 대규모 컴퓨팅을 사용할 수 있게 돕는다는 점에 흥분해왔다. 데

이터 과학 전문가 네 명이 스파크 기반의 고급 분석에 대해서 쓴 이 책을 읽는 것이 즐거운 이

유가 바로 여기에 있다. 샌디, 유리, 션 그리고 조시는 오랫동안 스파크로 작업해왔으며, 그만

큼 충실한 설명과 예제를 이 책에 담아냈다.

이 책에서 가장 마음에 드는 부분은 실제 응용 사례와 현실 세계의 데이터셋을 가져와 예제 중

심으로 설명하는 점이다. 독자의 PC에서 직접 실행해볼 수 있는 아홉 개의 개별 빅데이터 예제

를 제공한 책은 흔치 않은데, 저자들은 이런 예제들을 모아서 스파크로 실습할 수 있도록 모든

것을 세팅해두었다. 게다가, 핵심 알고리즘만 다룬 것이 아니라, 정말로 좋은 결과를 얻는 데

필요한 데이터 준비와 모듈 튜닝의 복잡한 사항까지 다루고 있다. 독자는 이들 예제에서 터득

한 개념을 자신의 문제를 푸는 데 곧바로 적용할 수 있을 것이다.

오늘날 빅데이터 처리는 의심할 여지 없이 컴퓨터로 할 수 있는 가장 흥미로운 분야이며, 빠르

게 진화하고 새로운 아이디어들이 도입되는 분야이기도 하다. 나는 독자들이 이 흥미로운 새로

운 분야로 들어서는 데 이 책이 도움이 될 거라 기대한다.

마테이 자하리아 스파크 창시자, 『러닝 스파크』 저자

아파치 스파크는 빅데이터 영역에서 가장 핫한 기술로, 범용적이면서 빠른 대용량 분산 처리를

지원한다. 또한 기초 데이터 분석부터 기계 학습 등의 기능까지 지원하게 되면서 개발자만의

오픈 소스에서 분석가를 위한 오픈 소스로 주목받고 있다. 이 책은 스파크로 빅데이터를 분석

하기 위한 가장 실용적인 데이터와 분석 방법을 설명하고 있다. 빅데이터에 관심 있거나 종사

하는 개발자와 분석가 모두에게 추천한다.

이상훈한국 스파크 사용자 모임 운영자, 『실시간 분석의 모든 것』 역자

추천의 글

7

교통, 금융 분야 등의 실제 데이터로 데이터 획득, 전처리, 가중치 결정, 실행, 평가 그리고 시

각화까지 해볼 수 있는 스파크 활용서다. 스파크 입문을 넘어 실무에 적용하려 할 때 좋은 참고

서다. 자신의 관심 도메인에 맞는 부분만 찾아서 읽어도 좋을 것 같다.

최홍용현대오토에버

8

학교를 졸업하고 몇 군데의 회사를 거쳐 2008년에 지금의 회사에 입사했다. 처음에는 콘텐츠

관리 시스템 개발로 시작했지만, 몇 번의 굴곡을 거쳐 회사는 이름이 바뀌었고 내가 하는 개발

업무도 바뀌게 되었다. 2011년, 데이터를 집계, 분석하여 실시간으로 시각화하는 과제를 수행

하게 되었다. 지금은 다른 회사에서 잘나가고 계신 배병우 씨와 함께 이를 위한 시스템을 설계

하면서 아파치 스톰Apache Storm을 알게 되었다. 그 후 몇 년간, 우리 회사의 개발팀은 스톰의 끝

을 보고 왔다. 그리고 스톰의 몇 가지 한계를 실감하게 되었다. 스톰은 스트림을 처리하는 훌륭

한 도구지만, 딱 거기까지였다(물론 이번에 릴리스된 스톰 1.0에서는 많은 부분이 개선되긴 했

다). 상태를 저장할 방법이 없는 탓에 완전한 분산 컴퓨팅 환경이라 말할 수 없다든지, 오류가

났을 시에 원래 상태를 복원할 수 없는 등 스톰이 할 수 없는 일이 꽤 있었다.

그러던 어느 날, 공역자인 권한철 씨와 서양주 씨가 아파치 스파크를 만났다. 당시 약간 모자라

보이던 스파크는, 맵리듀스MapReduce 로직을 인메모리로 처리하여 성능을 확장할 수 있다는 점

외에도, 일반적인 프로그래밍 환경에 데이터 분산 처리의 거의 모든 것을 가져올 수 있다는 특

징을 가지고 있었다. 여기에 분산 환경마저도 추상화하여 설치 이외에는 별다른 고민 없이 분

산 데이터 처리가 가능하다는 매력도 지녔다. 그리고 스톰의 강점인 스트림 처리마저도 스파크

스트리밍Spark Streaming이 마이크로 배치 형태로 처리할 수 있었다. 데이터 처리의 팔방미인이라

고 해도 과언이 아니었고, 우리는 그때부터 스파크에 집중하게 되었다. 그리고 약 2년이 흘렀

다. 스파크를 활용한 몇 개의 과제를 성공적으로 수행했으며, 새로운 도구를 받아들이는데 다

소 보수적인 분야의 현장에서도 스파크를 활용하여 얻을 수 있는 이점을 받아들이고 있다. 우

리는 스파크의 시대가 열리는 것을 목격한 운 좋은 증인이 되었고, 이 책을 읽을 독자분들도 아

직 늦지 않았다는 이야기를 해주고 싶다.

이 책은 단순한 스파크 참고서가 아니다. 스파크 참고서로는 더 좋은 책들이 여럿 있다. 부끄럽

지만 우리는 이 책도 그러한 참고서 중 하나인 줄 알고 번역을 시작했고, 그 착각 탓에 더 어려

운 길을 가야 했지만, 동시에 더 재미있는 길을 가볼 수 있었다. 이 책의 매력은 다양한 현장의

분석을 책에 담아낸 점에 있다. 스파크로 무엇인가를 해야 할지가 막막하다면 이 책을 펴면 도

옮긴이의 말

9

움이 될 것이다. 굳이 스파크가 아닌 다른 도구를 사용하더라도 유용한 정보도 들어 있다. 이

책이 역자들에게 도움이 된 것처럼 독자들께도 도움이 될 것으로 생각한다.

이 책을 번역하느라 업무 부담을 조금씩 나눠주신 에스코어 엔터프라이즈 공통 플랫폼 그룹 김

세준 그룹장 이하 동료들에게 감사를 전한다. 동시에 몇 달 동안 아빠를 번역에 빼앗긴 건우에

게도 미안함을 전한다. 다른 역자들도 마찬가지의 미안함과 고마움을 가지고 있으리라 생각한

다. 번역이라는 것이 이렇게 어려운 작업인 줄은 상상도 못 했다. 책을 읽다가 책의 문장이 발

바닥에 꽂힌 가시 같다는 기분이 들면, 그 책임이 역자들에게도 있을 수 있음을 생각해주시기

바란다.

박상은

10

과거를 후회하는 걸 좋아하진 않지만, 잠시 태만했던 2011년 시절 믿기 어려운 일이 벌어졌다.

당시 나는 어려운 이산 최적화 문제를 클러스터에 효율적으로 분배하는 방법을 고민하고 있었

다. 내 지도교수는 스파크라는 것이 최신 유행이라며 설명해주었지만, 그 개념은 실현되기엔

너무 이상적이라 실패할 것으로 판단하고 바로 학부 졸업논문을 맵리듀스로 작성하였다. 그 후

스파크와 나 모두 성장하였지만, 스파크는 도저히 무시할 수 없는 거물이 되었다. 대략 2년 후,

스파크에 주목해야 함이 명백해졌다.

MPI부터 맵리듀스에 이르기까지, 스파크 이전의 프레임워크들은 분산 시스템의 어렵고 세세

한 핵심들을 추상화하여 대규모 자원을 활용한 프로그램을 작성할 수 있도록 해주었다. 이들

프레임워크는 늘어가는 데이터를 처리하기 위해 발전해온 만큼, 빅데이터가 진출할 수 있는 범

위는 이들 프레임워크의 능력 한계와 밀접하게 연관될 수밖에 없었다. 스파크는 분산 프로그램

도 일반 프로그램을 작성하듯 쉽게 짤 수 있게 하여 이 범위를 좀 더 넓혀주고 있다.

스파크를 사용하면 ETL 파이프라인의 성능이 엄청나게 향상될 것이며 매일 하둡의 신에게 절

망을 하소연하는 맵리듀스 프로그래머들의 고통을 덜어줄 것이다. 그러나 나에게 가장 흥미

로운 점은 항상 스파크가 개척해준 복잡한 분석 작업이었다. 스파크는 반복적 알고리즘iterative

algorithm과 대화형 탐색interactive exploration을 지원하는 패러다임을 갖춰, 마침내 데이터 과학자가 대

규모 데이터셋을 생산적으로 다룰 수 있는 오픈 소스 프레임워크가 되었다.

나는 데이터 과학을 가르치는 가장 좋은 방법은 예제를 활용한 것이라고 생각한다. 이를 위해

나와 동료 저자들은 책에 여러 가지 응용 예를 담았으며, 가장 일반적인 알고리즘들과 데이터

셋들, 그리고 대규모 분석에서의 디자인 패턴들 간의 상호작용을 다루려고 노력하였다. 이 책

은 독자가 처음부터 끝까지 정독하라는 의도로 쓰이지 않았다. 여러분이 성취해봤으면 하는 주

제나 흥미를 자아내는 장을 펼쳐보자.

샌디 라이자

지은이의 말

11

이 책의 1장에서는 데이터 과학과 빅데이터 분석이라는 넓은 맥락에서 스파크의 가치를 소개

한다. 그다음부터 각 장은 스파크를 사용한 독립적인 분석으로 구성된다. 2장은 데이터를 정제

하는 간단한 예로 스파크와 스칼라를 사용한 데이터 분석의 기초를 소개한다. 그리고 그다음

몇 장은 가장 일반적으로 사용되는 알고리즘 몇 개를 전형적인 분야에 적용하면서, 핵심적인

기계 학습 문제를 스파크를 활용하여 푸는 방법을 살펴볼 것이다. 나머지 장들은 좀 더 특수한

분야를 다룬다. 위키백과의 텍스트 안에 숨겨진 의미 관계를 알아보거나 유전체학 데이터도 분

석해볼 것이다.

예제 웹사이트

코드 예제와 데이터셋은 다음 주소에서 내려받을 수 있다.

https://github.com/sryza/aas

이 책의 구성

12

아파치 스파크와 MLlib이 없었다면 여러분이 이 책을 읽을 수 있었을 리 만무하다. 우리 모두

는 스파크와 MLlib을 개발하고 오픈 소스로 제공한 개발팀과 여기에 참여한 수백 명의 기여자

에게 감사를 전한다.

이 책을 검토하느라 시간을 내어준 모든 전문가에게도 감사를 전하고 싶다. 미카엘 베르니코,

이안 부스, 제레미 프리먼, 크리스 프레글리, 드바시시 고시, 줄리엣 호글랜드, 조나단 키블러,

프랭크 나샤프트, 닉 펜트리스, 코스타스 사켈리스, 마르셀로 반진, 그리고 줄리엣 호글랜드

(한 번 더) 모두 고마워! 신세를 졌어. 덕분에 책의 구성과 품질 모두 크게 개선되었다.

또한, 나(샌디)는 어려운 주제의 배경 이론과 관련하여 조언해준 조단 핀쿠스와 리처드 왕에

게 감사를 표한다.

이 책이 출판되고 독자의 손에 들어가기까지 물심양면으로 지원해주고 이런 경험을 하게 해준

마리 보구로와 오라일리에도 감사를 표한다.

샌디 라이자

감사의 말

13

CONTENTS

지은이 소개 .............................................................................................................................4

옮긴이 소개 .............................................................................................................................5

추천의 글 ................................................................................................................................6

옮긴이의 말 .............................................................................................................................8

지은이의 말 .......................................................................................................................... 10

이 책의 구성 .........................................................................................................................11

감사의 말 ............................................................................................................................. 12

CHAPTER 1 빅데이터 분석하기

1.1 데이터 과학의 어려움 .....................................................................................................23

1.2 아파치 스파크란 ............................................................................................................25

1.3 이 책에 관하여 ..............................................................................................................28

CHAPTER 2 스칼라와 스파크를 활용한 데이터 분석

2.1 데이터 과학자를 위한 스칼라 ..........................................................................................30

2.2 스파크 프로그래밍 모델..................................................................................................32

2.3 레코드 링크 ...................................................................................................................32

2.4 스파크 셸과 SparkContext 시작하기 ..............................................................................33

2.5 클러스터에서 클라이언트로 데이터 가져오기 ...................................................................41

2.6 클라이언트에서 클러스터로 코드 가져가기 ......................................................................45

2.7 튜플을 사용한 데이터 구조화와 케이스 클래스 .................................................................46

2.8 집계 .............................................................................................................................52

2.9 히스토그램 만들기 .........................................................................................................53

2.10 연속 변수에 대한 요약 통계량 ......................................................................................55

2.11 요약 통계량을 계산하는 재사용 가능한 코드 만들기 .......................................................56

14

2.12 간단한 변수 선택과 점수 매기기 ...................................................................................62

2.13 한 걸음 더 나아가기 ....................................................................................................64

CHAPTER 3 오디오스크로블러 데이터셋으로 음악 추천하기

3.1 데이터셋 .......................................................................................................................68

3.2 교차 최소 제곱 추천 알고리즘 .........................................................................................69

3.3 데이터 준비하기 ............................................................................................................73

3.4 첫 번째 모델 만들기 .......................................................................................................76

3.5 추천 결과의 추출 검사하기 .............................................................................................79

3.6 추천 품질 평가하기 ........................................................................................................81

3.7 AUC 계산하기 ..............................................................................................................83

3.8 하이퍼파라미터 선택하기................................................................................................85

3.9 추천 결과 만들기 ...........................................................................................................88

3.10 한 걸음 더 나아가기 ....................................................................................................90

CHAPTER 4 의사 결정 나무로 산림 식생 분포 예측하기

4.1 회귀로 돌아와서 ............................................................................................................94

4.2 벡터와 특징 ...................................................................................................................95

4.3 학습 예제 ......................................................................................................................96

4.4 의사 결정 나무와 랜덤 포레스트 .....................................................................................96

4.5 Covtype 데이터셋 ...................................................................................................... 100

4.6 데이터 준비하기 ......................................................................................................... 101

4.7 첫 번째 의사 결정 나무 ............................................................................................... 102

4.8 의사 결정 나무 하이퍼파라미터 .................................................................................... 107

4.9 의사 결정 나무 튜닝하기 ............................................................................................. 109

CONTENTS

15

4.10 범주형 특징 다시 살펴보기 ........................................................................................ 112

4.11 랜덤 포레스트 .......................................................................................................... 114

4.12 예측하기 .................................................................................................................. 117

4.13 한 걸음 더 나아가기 ................................................................................................. 117

CHAPTER 5 K-평균 군집화로 네트워크 이상 감지하기

5.1 이상 감지 ................................................................................................................... 122

5.2 K-평균 군집화 ........................................................................................................... 123

5.3 네트워크 침입 ............................................................................................................. 124

5.4 KDD 컵 1999 데이터셋 .............................................................................................. 125

5.5 첫 번째 군집화하기 ..................................................................................................... 126

5.6 k 선정하기 ................................................................................................................. 129

5.7 R에서 시각화 ............................................................................................................. 133

5.8 특징 정규화 ................................................................................................................ 135

5.9 범주형 변수 ................................................................................................................ 138

5.10 엔트로피와 함께 레이블 활용하기 .............................................................................. 139

5.11 군집화하기 ............................................................................................................... 140

5.12 한 걸음 더 나아가기 ................................................................................................. 142

CHAPTER 6 숨은 의미 분석으로 위키백과 이해하기

6.1 단어-문서 행렬 .......................................................................................................... 147

6.2 데이터 구하기 ............................................................................................................. 149

6.3 파싱하여 데이터 준비하기 ........................................................................................... 149

6.4 표제어 추출 ................................................................................................................ 151

6.5 단어빈도-역문서빈도(TF-IDF) 계산하기....................................................................... 153

16

6.6 특이값 분해 ................................................................................................................ 156

6.7 중요한 의미 찾기 ........................................................................................................ 158

6.8 낮은 차원 표현에 대한 의문과 고찰 .............................................................................. 163

6.9 단어와 단어 사이의 연관도 .......................................................................................... 164

6.10 문서와 문서 사이의 연관도 ........................................................................................ 166

6.11 단어와 문서 사이의 연관도 ........................................................................................ 168

6.12 여러 개의 단어로 질의하기 ........................................................................................ 169

6.13 한 걸음 더 나아가기 ................................................................................................. 171

CHAPTER 7 그래프엑스로 동시발생 네트워크 분석하기

7.1 네트워크 분석 사례: MEDLINE의 인용 색인 ................................................................. 174

7.2 데이터 구하기 ............................................................................................................. 176

7.3 스칼라 XML 라이브러리로 XML 문서 파싱하기 ............................................................. 178

7.4 MeSH 주요 주제와 주제들의 동시발생 분석하기 ........................................................... 181

7.5 그래프엑스로 동시발생 네트워크 구성하기 ................................................................... 184

7.6 네트워크의 구조 이해하기 ........................................................................................... 187

7.6.1 연결 성분 ............................................................................................................ 188

7.6.2 차수의 분포 ......................................................................................................... 191

7.7 관련성 낮은 관계 필터링하기 ....................................................................................... 193

7.7.1 EdgeTriplets 처리 ............................................................................................... 195

7.7.2 필터링된 그래프 분석하기 ...................................................................................... 197

7.8 작은 세상 네트워크 ..................................................................................................... 199

7.8.1 클릭과 군집계수 ................................................................................................... 199

7.8.2 프레겔을 사용하여 평균 경로 길이 계산하기 .............................................................. 201

7.9 한 걸음 더 나아가기 .................................................................................................... 207

CONTENTS

17

CHAPTER 8 뉴욕 택시 운행 데이터로 위치 및 시간 데이터 분석하기

8.1 데이터 얻기 ................................................................................................................ 210

8.2 스파크에서 시간과 지리 데이터 다루기 ......................................................................... 211

8.3 JodaTime과 NScalaTime을 이용한 시간 데이터 .......................................................... 212

8.4 Esri Geometry API와 Spray를 사용한 지리 데이터 ...................................................... 214

8.4.1 Esri Geometry API 살펴보기 ................................................................................ 215

8.4.2 GeoJSON 소개 .................................................................................................. 216

8.5 뉴욕 택시 운행 데이터 준비하기 .................................................................................. 219

8.5.1 잘못된 레코드 대규모로 다루기 ............................................................................... 221

8.5.2 지리 정보 분석하기 ............................................................................................... 225

8.6 스파크에서 세션화하기 ................................................................................................ 229

8.6.1 세션 구성하기: 스파크에서 보조 정렬하기 ................................................................. 230

8.7 한 걸음 더 나아가기 ................................................................................................... 234

CHAPTER 9 몬테카를로 시뮬레이션으로 금융 리스크 추정하기

9.1 금융 분야 전문 용어 .................................................................................................... 236

9.2 VaR 계산 방법 ............................................................................................................ 237

9.2.1 분산-공분산 ....................................................................................................... 237

9.2.2 역사적 시뮬레이션 ................................................................................................ 238

9.2.3 몬테카를로 시뮬레이션 .......................................................................................... 238

9.3 우리의 모델 ................................................................................................................ 239

9.4 데이터 구하기 ............................................................................................................. 240

9.5 전처리하기 ................................................................................................................. 241

9.6 요인 가중치 결정하기 .................................................................................................. 245

9.7 표본추출하기 .............................................................................................................. 248

9.8 다변량 정규분포 ......................................................................................................... 250

18

9.9 실험 실행하기 ............................................................................................................. 252

9.10 수익 분포 시각화하기 ............................................................................................... 256

9.11 결과 평가하기 .......................................................................................................... 257

9.12 한 걸음 더 나아가기 ................................................................................................. 260

CHAPTER 10 BDG 프로젝트와 유전체학 데이터 분석하기

10.1 모델링과 저장소를 분리하기 ...................................................................................... 264

10.2 ADAM CLI를 이용한 유전체학 데이터 처리................................................................ 267

10.2.1 파케이 형식과 열 기반 저장소 .............................................................................. 274

10.3 ENCODE 데이터로부터 전사인자 결합 부위 예측하기 ................................................ 277

10.4 1000 게놈 프로젝트에서 유전자형 질의하기 .............................................................. 285

10.5 한 걸음 더 나아가기 ................................................................................................. 287

CHAPTER 11 파이스파크와 썬더로 신경 영상 데이터 분석하기

11.1 파이스파크 소개 ....................................................................................................... 290

11.1.1 파이스파크 내부 구조 ......................................................................................... 292

11.2 썬더 라이브러리 개요와 설치 .................................................................................... 294

11.3 썬더로 데이터 읽어 들이기 ........................................................................................ 296

11.3.1 썬더 핵심 자료형 ............................................................................................... 303

11.4 썬더를 이용해서 신경 세포 유형 분류하기 .................................................................. 304

11.5 한 걸음 더 나아가기 ................................................................................................. 310

CONTENTS

19

APPENDIX A 스파크 더 깊숙히

A.1 직렬화 ....................................................................................................................... 313

A.2 어큐뮬레이터 ............................................................................................................. 314

A.3 스파크와 데이터 과학자의 작업흐름 ........................................................................... 315

A.4 파일 형식 ................................................................................................................... 318

A.5 스파크의 하위 프로젝트들 ........................................................................................... 319

A.5.1 MLlib ............................................................................................................... 319

A.5.2 스파크 스트리밍 ................................................................................................. 320

A.5.3 스파크 SQL ...................................................................................................... 321

A.5.4 그래프엑스 ........................................................................................................ 321

APPENDIX B MLlib 파이프라인 API

B.1 단순한 모델링을 넘어서 .............................................................................................. 324

B.2 파이프라인 API .......................................................................................................... 325

B.3 문서 분류 예제 검토 ................................................................................................... 326

찾아보기 ................................................................................................................................................... 329

21Chapter 1 - 빅데이터 분석하기

“데이터 애플리케이션은 소시지와 비슷하다. 어떻게 만드는지 모르는 편이 나으니까.”1

-오토 폰 비스마르크

● 셀 수 없이 많은 트랜잭션과 수천 가지 특징을 가지고 신용카드 부정 사용을 감지하기 위한 모델 구축

● 수백만 사용자에게 수백만 가지의 제품 중 적절한 것을 지능적으로 추천

● 수백만 가지 요소를 고려한 포트폴리오 시뮬레이션을 통한 투자 위험도 추정

● 질환의 유전적 연관성을 파악하기 위한 대규모 인간 유전자 분석

몇 년 전만 하더라도 이와 같은 일들은 꽤 어려운 일이었다. 오늘날을 빅데이터의 시대라고 말할

수 있는 이유는 기존에는 경험하지 못한 규모로 정보를 수집, 저장, 처리할 수 있는 도구가 준비

되었기 때문이다. 이 배경에는 오픈 소스 생태계가 있는데, 그 덕분에 엄청난 양의 데이터를 다

룰 수 있는 컴퓨터 클러스터 환경을 저렴하게 사용할 수 있게 되었다. 아파치 하둡Apache Hadoop

과 같은 분산 시스템이 대세가 되었으며, 거의 모든 분야의 수많은 현장에서 활용하고 있다.

하지만 돌덩어리와 끌이 있다고 해서 조각상이 다 만들어진 것이 아니듯, 이들 도구와 각종 데

이터를 갖추었다는 것과 이를 활용하여 무언가 쓸모 있는 일을 한다는 것 사이에는 차이가 있

다. 그래서 데이터 과학이 필요해졌다. 조각이 도구를 사용하여 원석을 (조각가가 아닌) 누군가

에게 의미 있는 무언가로 바꾸는 작업이라면, 데이터 과학은 원본 데이터를 (데이터 과학자가

1 옮긴이_ 비스마르크는 원래 ‘데이터 애플리케이션’이 아니라 ‘법률’이 그러하다고 말했다.

빅데이터 분석하기

CHAPTER 1

샌디 라이자

22 9가지 사례로 익히는 고급 스파크 분석

아닌) 누군가의 관심을 끌 만한 의미 있는 것으로 바꾸는 작업이다.

흔히 ‘쓸모 있는 일 하기’는 스키마schema를 설계하고 SQL을 사용하여 “등록 과정의 세 번째 페

이지에 도달한 엄청난 수의 사용자 중 25세 이상은 몇 명인가?”와 같은 질문에 답하는 것을 의

미한다. 이런 질문에 쉽게 답할 수 있도록 데이터 웨어하우스data warehouse를 구성하고 정보를 체

계화하는 방법을 다루는 분야도 거대하지만, 이 책에서는 이런 복잡한 일은 되도록 다루지 않

으려 한다.

때때로 ‘쓸모 있는 일 하기’에는 노력이 더 필요할 수 있다. SQL은 여전히 주요한 수단이다. 하

지만 다루는 데이터가 매우 독특하거나 복잡한 분석이 필요하다면 SQL보다 유연하고 근본적

이며 기계 학습과 통계학 분야의 기능이 풍부한 새로운 프로그래밍 패러다임이 필요해진다. 이

런 유형의 분석이 이 책에서 이야기하려는 대상이다.

오랜 기간에 걸쳐 R, PyData 스택(파이썬 데이터 분석 도구 모음), 옥타브Octave와 같은 오픈

소스 프레임워크 덕에 작은 데이터셋dataset을 빠르게 분석하고 모델을 수립할 수 있었다. 데이터

셋의 일부를 사용해서 기계 학습 모델을 학습시키고 나머지 데이터의 레이블을 예측하는 데 10

줄 이내의 코드로도 가능하다. 여기서 조금만 더 나아가면 결측치missing data를 보정하고, 몇몇 모

델을 실험해 최적의 모델을 찾고, 한 모델의 결과를 다른 모델을 적합fit시키기 위한 입력으로

사용할 수 있다. 대규모 데이터셋에서 동일한 결과를 얻기 위해 컴퓨터 클러스터 환경을 활용

한다면 이상의 과정이 어떻게 달라질까?

단순히 프레임워크를 여러 노드에서 동작하게끔 확장하고 프로그래밍 모델은 그대로 유지한

채 분산 환경에서 잘 동작하게끔 내부를 수정하는 것이 옳을 수도 있다. 하지만 단일 노드에서

는 문제가 되지 않았지만 분산 컴퓨팅에서는 새롭게 고민해야 하는 것들이 있다. 예를 들어 네

트워크는 메모리보다 월등히 느리므로 데이터가 클러스터의 여러 노드에 나뉘어 있다면 많은

데이터를 참조하는 알고리즘은 성능이 매우 나빠진다. 분산 환경에서 동작하는 노드의 수가 늘

어날수록 오류가 발생할 가능성도 커진다. 이러한 사실들을 종합해볼 때 고도의 병렬 실행 코

드를 쉽게 작성할 수 있는, 분산 환경의 특징에 충실한 프로그래밍 패러다임이 필요하다.

하나의 노드에서 동작하는 PyData나 R과 같은 도구가 소프트웨어 커뮤니티에서 최근 주목받

고 있지만, 이들만이 데이터 분석을 위한 도구는 아니다. 대량의 데이터를 다루는 유전체학과

같은 과학 분야에서도 수십 년간 병렬 컴퓨팅 프레임워크를 발전시켜왔다. 이 분야에서 데이터

를 다루는 사람 대부분은 HPChigh-performance computing (고성능 컴퓨팅)라는 클러스터 컴퓨팅 환경

23Chapter 1 - 빅데이터 분석하기

에 익숙하다. PyData나 R은 확장성이 부족해 문제라면, HPC에서는 추상화 수준이 지나치게

낮아서 발생하는 나쁜 사용성이 문제다. 예컨대 DNA 염기서열로 가득 찬 커다란 파일을 병렬

처리하려면 수작업으로 일일이 작은 파일로 나눈 후, 각각에 대한 처리 작업을 클러스터의 스

케줄러에 하나씩 등록해야 한다. 일부에서 오류가 발생하면 작업자는 그 오류를 직접 찾아내서

수동으로 재입력해야 한다. 분석하다 보면 전체 데이터셋의 정렬과 같은 데이터 전체를 사용해

야 하는 작업을 수행해야 할 때가 있다. 이 경우에는 커다란 데이터 모두를 하나의 노드에 밀어

넣거나 MPI와 같은 저수준 분산 프레임워크에 의존해야 하는데, 그러려면 C 언어와 분산 네

트워크 환경을 잘 이해하고 있어야 한다. 또, HPC 환경에 맞게 제작된 도구들은 저수준 저장

소 모델로부터 인메모리in-memory 데이터 모델을 분리하기가 어려운 경우가 많다. 예를 들어 많

은 도구가 POSIX 파일시스템의 단일 데이터 스트림으로만 데이터를 읽을 수 있도록 만들어졌

다. 이러한 도구는 병렬화하거나 데이터베이스 같은 다른 종류의 백엔드 저장소를 사용하도록

변경하기가 쉽지 않다. 하둡 생태계의 최근 시스템들은 사용자가 클러스터 환경을 단일한 컴퓨

터 환경처럼 다룰 수 있도록 추상화해준다. 파일을 쪼개 여러 노드에 걸쳐 있는 저장소에 분산

하고, 일을 작은 단위로 나누어 처리하고, 오류를 복구하는 모든 작업을 자동으로 수행한다. 하

둡 생태계는 큰 데이터 파일을 다루는 과정도 자동화할 수 있으며, HPC보다 훨씬 저렴하다.

1.1 데이터 과학의 어려움

데이터 과학을 실제로 적용하다 보면 종종 어려운 문제에 부딪히게 된다. 클라우데라Cloudera의

데이터 과학팀은 이러한 어려움을 널리 알리는 데 큰 역할을 해왔다. 대량의 데이터로부터 복

잡한 분석을 성공적으로 처리하는 시스템을 구축하려면 (설사 실제로 벌어지지 않더라도) 이

런 어려움에 관해서 알고 있어야 한다.

첫째, 성공적인 분석을 위한 작업의 대부분은 데이터의 전처리 과정에서 이루어진다. 데이터는

너저분하다. 그래서 데이터를 활용하기 전에 정제, 개조, 합치기, 섞기 같은 여러 가지 전처리

과정이 필요하다. 특히, 육안으로 검사하기 어려울 정도로 데이터가 많다면 어떠한 전처리 과

정이 필요한지를 파악하는 일조차 별도의 처리 과정이 필요하다. 심지어 모델의 성능을 최적화

해야 할 때는 알고리즘을 선택해서 구현하는 일보다 특징을 추출하고 선택하는 데 일반적으로

더 많은 노력이 들어간다.

24 9가지 사례로 익히는 고급 스파크 분석

예컨대 온라인 구매 데이터에서 사기 행위를 찾는 모델을 만들고자 한다면 데이터 과학자들은

사용자가 작성하는 주문서 상의 여러 정보, 즉 사용자 IP의 위치 정보, 로그인 시간, 웹 사이트

내비게이션 로그와 같은 활용 가능한 수많은 특징 중에서 무엇을 사용할지 선택해야 한다. 선

택한 각 특징을 기계 학습 알고리즘에 적합한 벡터로 변환해야 하며, 이를 위해서 더블형double

숫자로 이루어진 2차원 배열을 수학적 모델로 변환하는 일 정도는 해줄 수 있는 시스템이 있어

야 한다.

둘째, 데이터 과학에서 반복iteration은 기본적인 과정이다. 보통은 모델을 만들고 분석하는 과정

에서 같은 데이터를 여러 번 반복해서 읽게 된다. 이는 기계 학습이나 통계적 절차의 특징에 기

인하는데, 값이 수렴할 때까지 입력 데이터를 반복해서 사용하는 확률적 구배법Stochastic Gradient

Descent이나 기댓값 최대화법Expectation Maximization과 같은 널리 사용되는 최적화 기법들을 보면 알

수 있다. 반복은 데이터 과학자 자신의 작업 흐름 안에서도 문제가 된다. 데이터 과학자가 처

음 접하는 데이터셋을 파악하고자 할 때, 특정 질의의 결과를 가지고 다음에 수행해야 할 질의

를 결정하는 것이 일반적이다. 모델을 만들 때도 데이터 과학자는 단 한 번의 시도로 모델이 완

성되리라 기대하지 않는다. 실험을 통해서 알맞은 특징을 선택하고, 적절한 알고리즘을 선택하

고, 유의성 검정을 하고, 맞춤 하이퍼파라미터들을 찾아낸다. 어떤 프레임워크가 같은 데이터

를 매번 디스크에서 가져온다면 전체 프로세스의 속도가 디스크 입출력만큼 느려지고, 결과적

으로 할 수 있는 일의 양이 줄어들게 된다.

셋째, 잘 돌아가는 모델이 완성되었다고 해서 일이 끝나는 것은 아니다. 데이터 과학의 핵심이

데이터를 직접 분석하지 않는 사람들에게 유용한 정보를 뽑아내는 것이라면, 데이터 과학자 컴

퓨터의 텍스트 파일에 회귀 가중치의 목록 형태로 저장된 모델은 진정한 목적이 될 수 없다. 데

이터 애플리케이션이라면 데이터 추천 시스템이나 실시간 사기 탐지 시스템처럼 의미 있게 활

용할 수 있어야 한다. 이런 시스템에서는 모델이 제품 서비스의 일부이므로 주기적으로 혹은

실시간으로 다시 생성해야 할 수도 있다.

이런 상황에서는 연구를 위한 분석과 현장을 위한 분석을 구분해야 한다. 연구를 위한 분석은 데

이터에 대한 탐색적 분석exploratory analytics을 의미한다. 이 분석에서는 데이터의 특성을 이해하려 시

도한다. 그 결과를 시각화하고, 아직 적용하지 않은 이론들을 시험한다. 여러 종류의 특징과 현

재의 데이터를 보강할 수 있는 후보 데이터도 시험하게 된다. 한두 가지는 성공하기를 바라면

서 다양한 알고리즘을 시험하는 것이다. 반면 데이터 애플리케이션을 구축하는 현장에서는 운

영을 위한 분석operational analytics을 수행한다. 분석 모델을 실제 의사 결정에 영향을 주는 서비스에

25Chapter 1 - 빅데이터 분석하기

적용하며, 시간 흐름에 따른 모델의 성과를 추적하고, 정확도를 조금이라도 올리기 위한 미세

조정 방안을 궁리한다. 그리고 서비스 수준 협약서Service Level Agreement (SLA )와 가동시간uptime도

고민하게 된다. 일반적으로 R과 같은 언어로 탐색적 분석은 수행한 이후에, 양산 단계에서는

데이터 처리 과정을 자바나 C++로 완전히 새롭게 구현하곤 한다.

물론 처음에 만든 모델의 코드를 실무 애플리케이션에서도 사용할 수 있다면 좋겠지만, R과 같

은 언어는 성능도 좋지 않은 데다가 제품의 다른 구성요소들과 통합하기에는 적합하지 않다.

반대로 자바나 C++와 같은 언어 쪽은 탐색적 분석에 쓸만한 도구를 찾아보기 어렵다. 자바나

C++에서는 데이터와 상호작용할 수 있는 REPLRead-Evaluate-Print-Loop 환경이 부족하며, 간단한

변환식을 구현하는 데도 많은 양의 코드가 필요하다. 그리하여 모델링 과정에서도 쉽게 쓸 수

있고 제품에도 적용할 수 있는 프레임워크가 필요한 상황이 되었다.

1.2 아파치 스파크란

아파치 스파크로 들어가보자. 스파크는 세련된 방법으로 클러스터의 여러 노드로 프로그램을

분배하고, 그 위에서 동작하는 프로그램을 개발할 수 있도록 개발된 오픈 소스 프레임워크다.

UC 버클리의 AMPLab에서 시작해, 지금은 아파치 소프트웨어 재단에서 관리하는 스파크는,

데이터 과학자가 분산 프로그래밍을 할 수 있게 해주는 아마도 최초의 오픈 소스 소프트웨어일

것이다.

스파크를 쉽게 이해하기 위하여 스파크의 선배라 할 수 있는 맵리듀스MapReduce와 비교해보자.

맵리듀스는 수십만 개의 노드를 활용하는 병렬 처리를 간단히 구현할 수 있는 모델로, 대량의

데이터 연산 분야에 일대 혁신을 가져왔다. 맵리듀스는 거의 선형에 가까운 확장성을 보여준

다. 데이터가 많아지면 컴퓨팅 노드도 그만큼 추가하여 같은 시간에 일을 마무리 지을 수 있음

을 의미한다. 그리고 ‘하나의 노드에서는 잘 발생하지 않는 오류라도 규모가 큰 클러스터 환경

에서는 일상적’이라는 상식으로부터도 자유롭다. 맵리듀스는 일을 작은 단위의 작업으로 쪼개

고, 단위 작업에서 오류가 나더라도 전체에 영향을 주지 않도록 우아한 방식으로 오류를 처리

한다.

스파크는 맵리듀스의 선형 확장성과 결함 허용성fault tolerance, 내결함성을 유지하면서, 세 가지 중요

한 개선을 이루어냈다. 먼저, ‘맵 단계 후 리듀스 단계’를 지키지 않아도 되며, 훨씬 일반적인 방

26 9가지 사례로 익히는 고급 스파크 분석

향성 비순환 그래프directed acyclic graph (DAG ) 형태로 정의한 연산들을 실행할 수 있다. 맵리듀스

라면 임시 결과를 분산 파일시스템에 반드시 저장해야 하는 상황에서, 스파크는 파이프라인의

다음 단계로 임시 결과를 바로 넘길 수 있다는 뜻이다. 이는 맵리듀스의 후손이자 마이크로소

프트 연구소에서 시작된 Dryad (http://research.microsoft.com/en-us/projects/dryad/ )와

유사한 방식이다.

두 번째, 사용자가 연산을 더욱 자연스럽게 표현할 수 있도록 풍부한 변환 방식을 제공하여 처

리 능력을 확장하고 있다. 개발자 중심의 기능을 제공하여 몇 줄의 코드만으로 복잡한 파이프

라인을 구현할 수 있는 간소화된 API를 제공한다.

마지막 개선은 인메모리 처리 방식이다. 스파크의 탄력적 분산 데이터셋Resilient Distributed Dataset

(RDD )이라는 추상 개념은 개발자가 처리 파이프라인의 어느 지점에서라도 데이터를 클러스

터의 메모리로 저장할 수 있도록 해준다. 이후 단계에서 같은 데이터를 사용해야 한다면 데이

터를 다시 연산하거나 디스크로부터 다시 읽을 필요가 없다는 뜻이다. 이 능력 덕분에 과거의

분산 처리 엔진들이 하지 못했던 용도로도 사용할 수 있게 되었다. 예를 들어 데이터셋을 여러

번 훑어야 하는 알고리즘이나 사용자 요청에 빠르게 응답하기 위해 커다란 인메모리 데이터셋

을 스캔해야 하는 반응형 애플리케이션reactive application에 아주 적합하다.

데이터 분석에서 가장 큰 병목이 CPU, 디스크, 네트워크 같은 컴퓨팅 환경이 아니라 분석가의

생산성에 달려 있음을 이해한다면 아마도 가장 중요한 점은 앞 절에서 이야기한 ‘데이터 과학

의 어려움’을 해결하는 데 스파크가 좋은 해답이라는 사실일 것이다. 전처리부터 모델 평가까

지의 전체 과정을 단일 프로그래밍 환경에서 수행하는 것이 개발 속도 면에서 얼마나 큰 이점

인지는 아무리 과장해도 지나치지 않을 것이다. REPL 환경의 분석 라이브러리들을 가지고 많

은 것을 표현할 수 있는 프로그래밍 모델로 묶어내면 맵리듀스와 같은 특정 프레임워크를 사용

하느라 여러 IDE를 오갈 필요도 없고, R과 같은 프레임워크를 사용하느라 HDFS로부터 데이

터를 표본추출하거나 이리저리 이동시킬 필요도 없다. 분석가가 데이터를 조사하는 시간이 절

약될수록 뭔가 쓸만한 일을 할 가능성은 더 커진다.

데이터 조작 또는 ETL에 적용할 수 있다는 면을 보면 스파크는 빅데이터를 다루는 매트랩Matlab

이라기보다는 빅데이터를 다루는 파이썬에 가까워 보인다. 범용 연산 엔진으로서 스파크의 핵

심 API는 통계, 기계 학습, 행렬 연산의 어떤 기능과도 독립적인, 데이터 변환을 위한 강력한

토대를 제공한다. 스파크의 스칼라 API와 파이썬 API 덕분에 범용 언어에서 쉽게 불러 쓸 수

27Chapter 1 - 빅데이터 분석하기

있고, 다른 라이브러리와 함께 사용할 수도 있다.

스파크의 인메모리 캐시 기능은 반복적으로 이루어지는 크고 작은 모든 데이터 처리에 이상적

이다. 이 기능을 활용하면 학습 데이터를 반복해서 읽어야 하는 기계 학습 알고리즘에서는 학

습 데이터를 메모리에 캐시해둘 수 있다. 데이터 과학자가 데이터를 파악하려 할 때도 데이터

를 디스크에서 매번 읽어 들이는 대신, 메모리에 올려둔 채 다양한 질의를 테스트해보고, 또 그

결과를 메모리에 쉽게 저장할 수도 있다.

마지막으로, 스파크는 탐색용 분석 시스템과 운영용 분석 시스템 사이의 간격을 좁힐 수 있

다. 세간에서 데이터 과학자는 통계학자보다는 엔지니어링을 잘하고 엔지니어보다는 통계 활

용에 능하다고 이야기하지만, 적어도 스파크는 대부분의 탐색 시스템보다는 운영 시스템에

서 쓰기에 좋고, 운영 시스템에서 일반적으로 사용하는 기술들에 비해 데이터 탐색에도 적합

하다. 스파크는 근본적으로 성능과 신뢰성 모두를 위해서 만들어졌다. 자바 가상 기계Java Virtual

Machine (JVM )에서 돌아가기 때문에 자바 스택에서 돌아가는 수많은 운영 및 디버깅 도구도 활

용할 수 있다.

스파크는 하둡 생태계의 다양한 도구와 통합하기에도 좋다. 스파크는 맵리듀스가 지원하는 모

든 데이터 포맷을 읽고 쓸 수 있어서, 에이브로Avro, 파케이Parquet와 같은 하둡의 일반적인 데이

터 저장 파일 포맷도 사용할 수 있다. 물론 하둡 이전부터 사용된 쉼표로 분리된 텍스트 형식

CSV도 지원한다. 그리고 HBase와 카산드라Cassandra 같은 NoSQL 데이터베이스로부터 데이터를

읽고 쓸 수도 있다. 스파크 스트리밍Spark Streaming이라는 스트림 처리 라이브러리로는 플룸Flume이

나 카프카Kafka로부터 스트림 데이터를 입력받을 수도 있다. SQL 라이브러리인 스파크 SQL로

는 하이브 메타스토어Hive Metastore와 상호작용이 가능한데, 맵리듀스를 대체하기 위하여 하이브

와 연동하는 데이터 처리 엔진으로 스파크를 활용하려는 프로젝트가 이 책을 쓰는 동안에도 진

행 중이다. 하둡의 스케줄링과 자원 관리를 담당하는 YARNYet Another Resource negotiator, 얀 내부에서

도 동작이 가능하다. 이를 통해서 클러스터 사이에서 자원을 동적으로 공유할 수 있으며, 맵리

듀스나 임팔라Impala와 같은 다른 처리 엔진에서도 동일한 정책으로 관리할 수 있게 되었다.

물론, 스파크가 모든 면에서 좋기만 한 것은 아니다. 이 책을 쓰고 있는 지금도 스파크의 코어

엔진은 완성도를 높여가고 있지만, 아직 맵리듀스에 비해서 역사도 짧고 맵리듀스를 능가하는

일괄 처리batch processing용 도구가 되지도 못했다. 스트림 처리, SQL, 기계 학습, 그리고 그래프

처리와 같은 특화된 하위 모듈들은 아직 성숙해가는 과정에 있으며 대규모 API 개선이 진행 중

28 9가지 사례로 익히는 고급 스파크 분석

이다. 예를 들어 기계 학습 라이브러리인 MLlib의 데이터 파이프라인과 변환 API 모델은 이

책을 쓰는 동안에도 계속 개발 중이다. 통계와 모델링 기능은 아직 R과 같은 단일 노드 언어의

근처에도 가지 못했다. 풍부한 SQL 기능을 제공한다지만 아직 하이브에도 뒤처져 있다.

1.3 이 책에 관하여

이 책의 나머지 부분에서는 스파크의 장점이나 단점은 다루지 않는다. 기본적인 스파크 프로그

래밍 모델과 스칼라 언어의 기초는 소개하지만, 스파크의 레퍼런스에 해당하는 내용이나 모든

것에 대한 포괄적인 지침 같은 것은 제공하지 않으려 한다. 기계 학습, 통계학, 선형대수의 튜

토리얼로 만들 생각도 없다. 물론, 필요하다면 기본적인 배경 정도는 설명할 것이다.

그 대신, 우리는 대량의 데이터셋을 다루는 복잡한 분석을 스파크로 실제 해보며, 그 생생한 느

낌을 독자에게 전달하고자 한다. 단순히 모델을 구축하고 평가하는 데 그치지 않고, 전체 파이

프라인을 돌아보며 데이터 정제, 전처리, 데이터 조사, 실제 제품으로 만들기까지를 보여주고

자 한다. 아마도 실제 예제를 통해서 보여주는 방법이 최선일 것이다. 그래서 우선 스파크와 그

생태계를 간단한 설명한 후, 그다음 장부터는 각 분야의 데이터를 스파크로 분석하는 독립적인

설명들로 채울 것이다.

가능하다면 단순히 ‘정답’을 제공하기보다는 데이터 과학의 절차 전체, 즉 모든 반복, 막다른

길, 재시도 등을 설명할 것이다. 이 책은 스칼라, 스파크, 기계 학습, 데이터 분석에 더 친숙해

지는 계기가 될 것이다. 그리고 이 모두는 더 큰 목적을 향한 과정이다. 우리는 이번 장의 처음

에 언급한 여러 업무에 어떻게 접근하는지를 가르치려는 것이다. 약 30쪽 내외로 구성된 각 장

을 통해 데이터 애플리케이션의 일부를 만들어내는 방법을 가능한 한 실제처럼 설명할 것이다.

29Chapter 2 - 스칼라와 스파크를 활용한 데이터 분석

“흥미를 잃지 않는다면 못할 일은 아무 것도 없다.”

-데이비드 포스터 월리스

데이터 정제는 모든 데이터 과학 프로젝트의 시작이자, 매우 중요한 일이다. 분석에 사용하는 데

이터의 품질이나 다른 내재적 원인에 의하여 분석 결과가 왜곡되거나 실제와 다른 결론이 도출

된다면 아무리 뛰어난 분석 방법이라 할지라도 도움이 되지 않을 것이다.

이러한 중요성에도 불구하고 데이터 과학 서적이나 강의에서는 데이터 정제 과정에 관해서 다

루지 않거나 그냥 언급만 하고 지나치곤 한다. 사실 데이터 정제는 꽤 지루한 과정이다. 우리가

새 문제에 써보고 싶은 멋진 기계 학습 알고리즘을 적용하기 전에 거쳐야 하는 아주 따분한 일

이다. 많은 풋내기 데이터 과학자들은 최소한의 데이터 품질 수준으로 분석을 시작하고, 복잡

한 알고리즘을 적용한 후 말도 안 되는 답을 얻고 나서야 비로소 데이터 품질에 심각한 문제가

있음을 깨닫는 경우가 많다.

“쓰레기를 넣으면 쓰레기가 나온다garbage in, garbage out”라는 말도 있지만, 현실은 이보다 훨씬 심

각하다. 어떤 데이터에 쉽게 파악되지 않는 심각한 품질 문제가 있어서 문제가 없는 데이터로

오인된다면 도출된 결과도 마치 문제가 없는 것처럼 보일 수 있다는 것이다. 이런 종류의 실수

로 인해 심각한 오답을 제시하는 것은 데이터 과학자에게는 치명적이다.

데이터 과학자로서 갖추어야 할 중요한 소질 하나는 데이터 분석의 모든 단계에서 흥미롭고 가

스칼라와 스파크를 활용한 데이터 분석

CHAPTER 2

조시 윌스

30 9가지 사례로 익히는 고급 스파크 분석

치 있는 문제를 찾아내는 능력이다. 분석의 초기 단계에 기술과 통찰을 더하면 최종 결과물의

신뢰도는 더 커지게 된다.

데이터 과학자에게 데이터 품질 관리에 신경을 쓰라고 하다니, 물론 말은 쉽다. 아이들에게 채

소를 먹으라고 이야기하는 것처럼 말이다. 멋진 기계 학습 알고리즘을 만들어보거나, 스트리밍

데이터를 처리하는 엔진을 개발한다든지, 복잡하게 연결된 그래프를 분석한다든지 하는 일에

사용할 수 있는 스파크와 같은 새로운 도구를 써보는 일이 훨씬 재미있기 때문이다. 그래서 스

파크와 스칼라를 활용하여 데이터를 정제하는 예제로부터 시작하려고 한다.

2.1 데이터 과학자를 위한 스칼라

데이터 과학자 대부분은 데이터를 조작하고 분석할 때 R이나 파이썬과 같은, 자신에게 가장 능

숙한 특정 도구를 선호한다. 어쩔 수 없이 다른 환경에서 일하게 되더라도 선호하는 도구에 집

착하며 그 도구를 사용할 수 있는 환경으로 데이터를 가지고 나갈 방법을 모색하곤 한다. 새로

운 문법과 새로운 패턴을 습득해야 하는 새로운 도구를 도입하는 것은 최선의 상황에서도 꽤

힘든 도전적인 일이다.

스파크에는 R이나 파이썬으로 코드를 작성할 수 있는 라이브러리와 래퍼wrapper가 있다. 그중

파이스파크PySpark라는 훌륭한 파이썬 래퍼는 이 책의 뒷부분에서도 일부 다루고 있다. 하지만

대부분의 예제는 스칼라로 제공할 것이다. 스파크 자체가 스칼라 언어로 구현되어 있어서, 스

칼라를 직접 사용하면 다음과 같은 효과를 기대할 수 있다.

성능 면에서 유리하다.

스칼라처럼 JVM에서 동작하는 언어 위에서 R이나 파이썬으로 만들어진 알고리즘을 실행하

려면 코드와 데이터를 변환하거나 다른 환경으로 옮기는 작업이 추가로 필요하며, 때에 따

라서는 이 추가 과정에서 오류가 생길 수도 있다. 반면, 스파크가 제공하는 스칼라 API를 사

용한다면 의도한 대로 동작할 가능성이 매우 커진다.

31Chapter 2 - 스칼라와 스파크를 활용한 데이터 분석

최신 기능을 활용할 수 있다.

스파크의 기계 학습, 스트림 처리, 그래프 분석 등의 라이브러리는 모두 스칼라로 작성했기

때문에 새로운 기능이 파이썬이나 R 환경까지 지원하는 데 시일이 걸리는 편이다. 그러므로

스파크가 제공하는 모든 최신 기능을 곧바로 사용하려 한다면 최소한 스칼라에 대해서 조금

은 알아야 하며, 그 기능들을 확장하여 새로운 문제에 적용하려면 스칼라를 어느 정도 능숙

하게 다룰 수 있어야 한다.

스파크의 철학을 이해하기 쉽다.

파이썬이나 R로 스파크를 사용한다 할지라도, 스파크의 API에는 이를 구현한 언어인 스칼

라로부터 시작된 철학이 녹아 있다. 여러분이 다른 언어를 사용하더라도 스칼라로 스파크를

다루는 방법을 알고 있다면 스파크 체계를 이해하고 문제를 ‘스파크답게’ 해결하는 데 도움

이 된다.

다른 데이터 분석 도구들과는 많이 다르기 때문에 설명하기 힘든, 스칼라의 또 다른 장점이 있

다. 만약 R이나 파이썬을 가지고 데이터베이스로부터 데이터를 가져와서 분석해왔다면 데이터

를 SQL로 가져온 후, 작업 환경을 R이나 파이썬으로 바꿔서 그 데이터를 다루고 시각화하는

절차에 익숙할 것이다. 누군가는 클러스터에 저장된 데이터에 접근하여 작업하는 일과 PC에

저장된 데이터를 다루고 시각화하는 일에 각각 다른 언어를 사용해왔을 수도 있다. 오랫동안

사용해 익숙해졌다면 이런 방식의 불편함을 자각하지 못할 수도 있다.

스칼라와 스파크를 사용한다면 이야기가 달라진다. 어떤 경우에도 같은 언어를 사용할 수 있기

때문이다. 스칼라 코드를 작성하여 스파크를 통해 클러스터에서 데이터를 가져오고, 스칼라 코

드를 작성하여 그 데이터를 로컬 환경에서 다룰 수 있다. 무엇보다 좋은 점은 로컬에서 작성한

스칼라 코드를 데이터가 저장되어 있는 클러스터에 보내서 바로 실행시키는 방식으로, 데이터

를 로컬 환경으로 가져오지 않고도 일을 처리할 수 있다는 것이다. 데이터가 저장되어 있고 처

리되는 위치와 상관없이, 데이터를 조작하고 분석하는 모든 일을 하나의 환경에서 할 수 있다

는 것이 얼마나 혁신적인지 설명하기는 쉽지 않지만, 일단 경험해보면 알 것이다. 필자들은 스

파크를 처음 접했을 때 느꼈던 신비한 힘을 예제에 담아내려고 노력했다.

32 9가지 사례로 익히는 고급 스파크 분석

2.2 스파크 프로그래밍 모델

스파크 프로그래밍을 위해서 데이터와 이를 담은 저장소가 필요하다. 데이터는 보통 하둡 분산

파일시스템Hadoop Distributed File System (HDFS )과 같은 분산 저장소에 저장한다. 일반적으로 스파크

프로그램은 다음과 같은 몇 개의 연이은 단계로 구성된다.

● 입력 데이터에 적용할 변환을 정의한다.

● 변환된 데이터를 저장소로 보내거나 구동자driver의 로컬 메모리로 반환하는 액션을 수행한다.

● 분산 처리 방식으로 계산된 결과를 바탕으로 로컬 계산을 수행한다. 이 작업은 다음에 수행할 변환과 액션을

결정하는 기준이 될 수도 있다.

스파크를 이해한다는 것은 스파크 프레임워크가 제공하는 두 가지 기능 분류인 저장 storage과 실

행execution의 관계를 이해한다는 것이다. 스파크는 데이터 처리 파이프라인의 어떤 지점에서도

데이터를 메모리에 캐시하여 나중에 재사용할 수 있도록 함으로써, 저장과 실행을 훌륭하게 연

결해두었다.

2.3 레코드 링크

우리가 이 장에서 논의할 문제는 문헌과 실무 현장에서 엔티티 해소entity reolution, 레코드 중복 제

거record deduplication, 병합 및 제거merge-and-purge, 목록 정리list washing 등 다양한 이름으로 불리고 있

다. 모순적이게도 이 문제가 다양한 이름으로 불리기 때문에 문제 해결을 위한 기술들을 훑어

보고자 해도 관련 논문조차 다 찾아내기 어렵다. 오히려 이 데이터 정제 문제에 대한 참고 문헌

들에서 중복 제거를 수행할 데이터 과학자가 필요한 처지다! 이 장의 목적을 원만히 이루기 위

해 이제부터 ‘같은 실체를 가리키는 레코드들을 연결짓는’ 이 문제를 레코드 링크record linkage라 부

르겠다.

이 문제의 일반적인 형태는 다음과 같다. 하나 또는 그 이상의 데이터 출처로부터 데이터를 수

집하여 취합하면 그 속의 레코드 일부가 실제로는 같은 고객, 같은 환자, 같은 위치, 같은 행사

등 동일한 실체를 가리킬 수 있다. 각 실체는 이름, 주소, 생일과 같은 여러 속성을 가지고 있어

서 동일한 실체를 가리키는 레코드들을 찾아내려면 이 속성값을 이용해야 한다. 안타깝게도 이

33Chapter 2 - 스칼라와 스파크를 활용한 데이터 분석

속성값들은 불완전하다. 형식이 다르거나 오타가 있거나 값이 누락되었을 수 있다. 그러므로

단순하게 속성이 같은지만을 검사한다면 상당수의 중복 레코드를 놓치게 될 것이다. [표 2-1]

을 살펴보자.

표 2-1 레코드 링크의 어려움

이름 주소 도시 주 전화번호

조시의 커피숍 선셋 대로 1234 서 할리우드 CA (213)-555-1212

조시 코피 선셋 대로 1234, 서 할리우드 CA 555-1212

커피숍 체인 #1234 선셋 가 1400, 2 할리우드 CA 206-555-1212

커피숍 체인 지역 사무소 선셋 가 1400, 2호실 할리우드 캘리포니아 206-555-1212

이 표에서 위의 두 줄은 각각 ‘서 할리우드’와 ‘할리우드’라는 도시에 있는 서로 다른 커피숍처럼

보인다. 하지만 이는 입력상의 실수로, 사실은 같은 커피숍을 가리킨다. 그다음의 두 줄은 주

소가 같지만 2개의 서로 다른 사업장을 가리키고 있는데, 하나는 실제 커피숍이며 다른 하나는

지역의 체인점 사무소다. 둘 다 시애틀에 있는 본사의 대표 전화번호가 기록되어 있다.

이 예제는 레코드 링크가 얼마나 어려운지를 보여준다. 각각의 묶음이 서로 유사하게 보이더라

도 중복이 있는지를 결정하기 위해 사용하는 기준은 묶음마다 다르다. 사람은 직관으로 쉽게

구분할 수 있겠지만 컴퓨터가 그 구분법을 학습하기에는 어려운 형태다.

2.4 스파크 셸과 SparkContext 시작하기

여기에서는 UC 어바인의 기계 학습 데이터 저장소UC Irvine Machine Learning Repository에서 구할 수 있

는 표본 데이터를 사용한다. 이 저장소에서 연구와 교육을 위한 흥미로운 (더구나 무료인) 데

이터셋들을 구할 수 있다. 우리가 분석할 데이터셋은 2010년에 독일의 한 병원에서 실시한 레

코드 링크 연구에서 나온 것으로, 환자의 성과 이름, 주소, 생일 등 몇 가지 기준에 따라 묶은

수백만 건의 환자 기록 묶음이 들어 있다. 각 묶음에는 문자열 유사도에 따라 0.0부터 1.0까지

점수를 매겼고, 그 후 같은 사람을 표현한 묶음과 그렇지 않은 묶음을 분류해 일일이 표시하였

다. 데이터셋을 만드는 데 사용한 필드 자체의 원래 값은 환자의 개인 정보를 보호하기 위해 제

34 9가지 사례로 익히는 고급 스파크 분석

거되었으며 식별번호, 필드별 유사도 점수, 묶음별 실제 분류값(같은 사람인지 여부)이 레코

드 링크 연구 용도로 발행되었다.

아래와 같이 셸shell 명령어로 저장소로부터 데이터를 가져오자.

$ mkdir linkage

$ cd linkage/

$ curl -L -o donation.zip http://bit.ly/1Aoywaq

$ unzip donation.zip

$ unzip 'block_*.zip'

사용할 수 있는 하둡 클러스터가 있으면, HDFS에 블록 데이터용으로 디렉터리를 생성하고 데

이터 파일을 그 디렉터리에 복사한다.

$ hadoop fs -mkdir linkage

$ hadoop fs -put block_*.csv linkage

이 책의 예제 코드는 1.2.1 버전의 스파크를 사용한다. 필요한 릴리스는 스파크 프로젝트 사이

트에서 내려받을 수 있다(http://spark.apache.org/downloads.html ). 클러스터 환경을 사용

하든 로컬 PC 환경을 사용하든, 스파크 참조 문서를 보고 환경을 설정하면 된다(http://spark.

apache.org/docs/latest/ ).

이제 spark-shell을 실행할 준비가 되었다. spark-shell은 스파크 확장 API를 제공하는 스

칼라 REPLread-eval-print loop이다. REPL이라는 용어가 생소하다면 R 환경과 유사한 것으로 생각

하면 된다. spark-shell은 스칼라 프로그래밍 언어를 사용하여 함수를 정의하고 데이터를 다

룰 수 있는 공간이다.

YARN을 지원하는 하둡 클러스터가 있다면 스파크 마스터를 yarn-client로 지정해서 스파

크 작업을 클러스터에서 실행할 수 있다.

$ spark-shell --master yarn-client

PC에서 실행하려면 local[N] 인수를 지정하여 실행하면 된다. 여기에서 N은 실행할 스레드

의 개수다. 이 값을 *로 지정하면 가용한 CPU 코어 개수로 자동으로 설정된다. 예를 들어 사용

할 PC가 8코어 장비라면 8개의 스레드로 실행된다.

67Chapter 3 - 오디오스크로블러 데이터셋으로 음악 추천하기

“De gustibus non est disputandum.”

(취향에 이유를 따지지 마라.)

누군가 나에게 직업을 물을 때 ‘데이터 과학’ 또는 ‘기계 학습’이라고 직설적으로 대답하면, 들리

기야 멋있게 들리지만 반응은 싸한 편이다. 실제 데이터 과학자들조차도 이 용어의 뜻을 명확

하게 정의하지 못하고 있으니(큰 데이터를 저장하고, 계산하고, 무언가 예측하는 일?) 당연히

그럴 만하다. 예를 들어 이야기해보자.

“아마존에서 고객이 과거에 구매한 책들과 유사한 책을 추천해주는 걸 알고 계신가요? 정말요?

네. 바로 그게 제가 하는 일입니다.”

추천 엔진은 적어도 내 주변 사람은 모두 알고 있으며, 또 많은 사람이 아마존을 통해 경험한

대규모 기계 학습의 사례일 것이다. 소셜 네트워크에서 동영상 사이트, 그리고 온라인 소매업

까지 모든 영역에 적용되는 공통분모에 해당하는 것이며, 또한 실제로 동작하는 모습을 직접

관찰할 수도 있다. Gmail이 우리가 신경 쓰지 않아도 스팸을 골라내는 그 방법으로, 스포티파

이Spotify 역시 재생할 음악을 컴퓨터가 골라주고 있다는 사실을 알고 있다.

다른 기계 학습 알고리즘에 비해 추천 알고리즘의 결과는 훨씬 직관적이다. 게다가 흥미롭기까

지 하다. 개인의 음악 취향이 너무 사적이어서 설명하기 어렵다고 누구나 생각하지만, 추천 엔

오디오스크로블러 데이터셋으로 음악 추천하기

CHAPTER 3

션 오언

68 9가지 사례로 익히는 고급 스파크 분석

진은 우리가 좋아할 것으로 생각하지도 못한 음악을 찾아내는 놀라운 일을 해낸다.

추천 엔진이 널리 사용되는 음악과 영화 분야에서는 추천된 목록이 누군가 과거에 듣거나 본

콘텐츠와 왜 잘 들어맞는지를 추리해내기가 상대적으로 쉽다. 하지만 모든 군집화clustering1나 분

류classification 알고리즘이 설명하기 쉬운 건 아니다. 예컨대 서포트 벡터 머신support vector machine 분

류기는 계수들의 집합으로 구성되는데, 예측은 하더라도 그 계수들의 의미를 설명하기란 전문

가조차도 쉽지 않다.

그래서 앞으로 3개의 장에 걸쳐서 스파크의 핵심 기계 학습 알고리즘을 다루기 전에, 이번 장

에서 음악에 특화된 추천 엔진을 먼저 들여다보는 것이 좋다고 판단했다. 스파크와 MLlib을 실

제 세상의 문제에 적용하는 방식을 소개하고, 또 앞으로 이어질 장에서 더 깊게 들어갈 기본적

인 기계 학습 알고리즘을 소개하는 적절한 방법이라 생각한다.

3.1 데이터셋

이 장의 예제에서는 오디오스크로블러Audioscrobbler에서 공개한 데이터셋을 사용하려 한다. 오디

오스크로블러는 2002년에 초기 인터넷 스트리밍 라디오 서비스를 제공한 last.fm을 위해서 만

들어진 첫 번째 음악 추천 시스템이다. 오디오스크로블러는 스크로블링2용 오픈 API를 제공했

고, 청취자의 음악 재생 내역을 기록했다. 서드파티 앱과 사이트들이 추천 엔진에 음악 감상 관

련 데이터를 돌려준 덕에, 이 시스템의 사용자는 수백만 명에 이르렀다.

당시의 추천 엔진 관련 연구는 대부분 평점 데이터를 학습하는 데 그쳤다. 즉, “개똥이가 프린

스에게 별점 3개 반을 주었군”과 같은 입력을 가지고 동작하는 도구처럼 보이곤 했다.

오디오스크로블러의 데이터셋이 재미 있는 점은 “개똥이가 프린스를 들었어”와 같은 단순 재생

정보만 기록한다는 것이다. 단순 재생 여부는 평가보다 정보가 적다. 개똥이가 듣는다는 사실

만으로 개똥이가 실제로 좋아하는지 혹은 싫어하는지를 판단할 수 없기 때문이다. 종종 별 관

심 없는 아티스트의 음악을 틀어놓을 때도 있고, 또 음악을 틀어놓고 외출해버릴 수도 있다.

1 옮긴이_ 영어 그대로 클러스터링이라고도 많이 부르나, 이 책에서는 분산 처리 분야의 용어인 클러스터링과 명확히 구분하기 위해 우리말 용어인 군집화를 사용하기로 한다.

2 옮긴이_ 음악을 들을 때 아티스트, 제목, 앨범 등의 정보를 last.fm 서버에 보내는 작업이다.

69Chapter 3 - 오디오스크로블러 데이터셋으로 음악 추천하기

하지만 감상한 음악을 평가하는 횟수는 음악을 듣는 일에 비해서 훨씬 드물다. 그래서 음악 감

상 데이터 하나의 정보량은 음악 평가 데이터 하나의 정보량보다 적지만, 음악 감상 데이터셋

은 크기도 훨씬 크고, 더 많은 사용자와 아티스트를 포함하며, 정보의 총량도 훨씬 많다. 사용

자와 아티스트 사이의 관계가 어떤 명시적 평가나 ‘좋아요’ 버튼으로 직접 주어지는 대신, 다른

행위로부터 유추할 수 있는 형식이므로 이런 종류의 데이터를 암묵적 피드백implicit feedback이라고

부르기도 한다.

2005년에 last.fm에서 배포한 데이터셋의 스냅샷을 인터넷에서 압축된 파일 형태로 구할 수

있다(http://bit.ly/1KiJdOR ). 압축 파일을 내려받은 후, 그 안의 파일을 몇 개 찾아보자. 중심

이 되는 데이터셋은 user_artist_data.txt 파일에 들어 있다. 이 안에는 141,000명의 사용자와

160만 명의 아티스트 정보가 담겨 있으며 약 2,420만 건의 음악 재생 정보가 재생 횟수와 함

께 기록되어 있다.

또한, 이 데이터셋의 artist_data.txt 파일에는 각각의 아티스트에 ID를 부여하고 있다. 음악

이 재생되면 클라이언트 프로그램이 재생되는 아티스트의 이름을 전송하는데, 그 이름은 잘못

기록되었거나 공식 명칭이 아닐 수 있으며, 이러한 오류가 뒤늦게 발견될 수도 있다. 예를 들

어 ‘The Smiths’, ‘Smiths, The’, ‘the smiths’는 데이터셋 안에서는 별도의 아티스트 ID를 가

질지도 모르지만, 이 명칭들은 모두 단 한 사람에게 붙여진 것일 수 있다. 그래서 데이터셋의

artist_alias.txt 파일은 아티스트 명칭의 흔한 오기 패턴과 다양한 변형 표기법으로 기록된 아

티스트 ID를 해당 아티스트의 대표 ID와 연결 짓고 있다.

3.2 교차 최소 제곱 추천 알고리즘

우리는 암묵적 피드백 데이터에 적합한 추천 알고리즘을 선택해야 한다. 우리의 데이터셋은 전

적으로 사용자와 아티스트의 음악 사이의 상호작용으로만 구성된다. 사용자에 대한 어떤 정보

도, 그리고 이름 외에는 아티스트에 대한 어떤 정보도 포함하고 있지 않다. 우리는 사용자와 아

티스트의 속성에 대해 아는 바가 없어도 학습이 가능한 알고리즘이 필요하다. 이런 알고리즘을

일반적으로 협업 필터링collaborative filtering (http://en.wikipedia.org/wiki/Collaborative_filtering )

이라고 한다. 예를 들어 사용자 두 명이 단지 동년배라서 취향이 비슷하다고 이야기하는 것은

협업 필터링이 아니다. 두 사람이 들은 노래 중 같은 것이 많기 때문에 같은 노래를 좋아할 것

70 9가지 사례로 익히는 고급 스파크 분석

이라고 결정하는 것이 협업 필터링의 예라고 할 수 있다.

수천만 건의 재생 기록을 담은 이 데이터는 일견 방대해 보이지만, 다른 관점에서 보면 밀도가

낮기 때문에 꼭 그렇지도 않다. 평균적으로 한 사용자가 160만 명의 아티스트 중 171명의 노

래만 재생했다. 어떤 사용자는 딱 한 아티스트의 노래만 듣기도 했다. 어찌 되었든 음악을 듣는

누구라도 처음에는 딱 한 곡의 청취 기록만 있었을 것이다!

최종적으로, 대규모 모델을 만들 수 있고 동시에 빠른 추천이 가능한, 확장 가능한 알고리즘이

필요하다. 일반적으로 추천 결과가 내일 나온다면 너무 늦다. 1초 이내의 준 실시간으로 나와

야 한다.

이 예제에서는 잠재 요인latent-factor (http://en.wikipedia.org/wiki/Factor_analysis ) 모델로

분류할 수 있는 많은 알고리즘 중 하나를 사용하고자 한다. 잠재 요인 모델은 다수의 사용자

와 상품 사이에서 관측된 상호작용observed interaction을 상대적으로 적은 수의 관측되지 않은, 숨은 원인

unobserved, underlying reason으로 설명하려 할 때 사용한다. 이는 수백만의 사람이 수천 개의 음반 중

특정 음반을 구입한 이유를 (직접 관측할 수 없고 데이터도 주어지지 않은) 수십 개 음악 장르

에 대한 개인 취향으로 설명하는 것과 유사하다.

더 구체적으로는 행렬 분해matrix factorization (http://en.wikipedia.org/wiki/Non-negative_matrix_

factorization ) 모델을 사용할 것이다. 수학적으로 이들 알고리즘에서는 사용자와 제품 데이터

를 큰 행렬 A로 간주해 다루는데, A는 사용자 i가 아티스트 j의 음악을 들었다면 A의 i행 j열

에 값이 존재하는 행렬이다. A는 희소 행렬sparse matrix이다. 사용자-아티스트의 가능한 모든 조합

중 오직 극소수만이 실제 데이터로 등장하기 때문에 이 행렬의 원소 대부분은 0이 된다. 이들

행렬 분해 알고리즘은 A를 더 작은 행렬 X와 Y의 행렬곱으로 분해하는데, 이 X와 Y는 매우

길쭉하다. A가 다수의 행과 열을 가지기 때문에 X와 Y는 매우 많은 행을 가지게 되는 데 반해,

열은 몇 개(k ) 되지 않는다. k개의 열은 상호작용하는 데이터를 설명하는 데 사용하는 잠재 요

인에 해당한다.

[그림 3.1]에서 볼 수 있듯, k가 작기 때문에 이 분해는 근사치일 수밖에 없다.

71Chapter 3 - 오디오스크로블러 데이터셋으로 음악 추천하기

A Xk

k

YT

그림 3.1 행렬 분해

원래의 행렬 A는 매우 희소한 데 비해 행렬곱 XY T는 밀도가 매우 높아서 이 알고리즘을 행렬

채우기matrix completion 알고리즘이라고 부를 때도 있다. 설사 값이 0인 원소가 있다 할지라도 매우

드물게 나타나므로, 이 모델은 A의 근삿값일 뿐이다. 원래의 행렬 A에서 결측된(즉, 값이 0

인) 많은 원소에 대한 값조차도 생성한다는(채워준다는) 관점에서 행렬 분해는 하나의 모델이

라 할 수 있다.

다행히도 이는 선형대수학이 직관과 아주 잘 들어맞는 경우다. 이 두 행렬은 각 사용자와 각 아

티스트를 하나씩의 행으로 담고 있다. 이 행들은 매우 작은 수(k개)의 값만을 가진다. 그리고

각 값은 모델에서 숨어 있는 특징에 대응한다. 그래서 행들은 사용자와 아티스트가, 아마도 취

향이나 장르에 대응하리라 추측되는, 이들 잠재 요인과 얼마나 밀접하게 관련되는지를 표시하

게 된다. 그리고 사용자-잠재 요인 행렬과 잠재 요인-아티스트 행렬의 행렬곱은 사용자-아티

스트 상호작용 밀집 행렬의 완벽한 근사치에 해당한다.

안타까운 점은 A를 완벽하게 표현하기에는 X와 Y가 충분히 크지 않아(선형대수학에서는 계

수rank가 너무 작다고 기술한다. http://bit.ly/1ALoQKF ) A = XY T의 일반적인 해를 구할 수

없다는 것이다. 알고 보면 사실은 좋은 일이다. A는 발생할 수 있는 모든 상호작용 중 아주 작

은 표본일 뿐이다. 어떤 면에서 A는 정보가 매우 드문드문 존재하는 행렬이므로 (크지 않은 k

개의 잠재 요인으로 잘 설명해야 한다는 감춰진 진실의 관점에서 보면) 설명하기 어려운 것이

라 믿게 된다. 고양이 그림의 직소 퍼즐을 생각해보자. 완성된 퍼즐을 보고 고양이라고 설명하

기는 아주 쉬워도, 조각 몇 개만 쥐고 있다면 이것이 어떤 그림이라고 설명하기란 매우 어렵다.

72 9가지 사례로 익히는 고급 스파크 분석

XY T은 여전히 A에 가능한 한 가까워야 한다. 어쨌든 이것이 우리가 해야 할 일이다. 정확하

게 구하지는 못할 것이고 또 구할 수도 없다. 설상가상으로, X와 Y의 정답 모두를 동시에 직접

적으로 구할 수조차 없다. 그나마 나은 소식은 Y를 알고 있을 때는 X의 정답을 구할 수 있음이

자명하고, 그 반대도 마찬가지라는 것이다. 뭐, 아직은 둘 다 모르는 상태지만!

다행히 이런 딜레마를 극복하고 제대로 된 해를 찾아주는 알고리즘이 있다. 더 구체적으로

설명하면, 이 장의 예제에서는 X와 Y를 계산하기 위해 교차 최소 제곱Alternating Least Squares (ALS,

http://bit.ly/16ilZZV ) 알고리즘을 사용할 것이다. 이런 종류의 접근법은 넷클릭스 프라이즈

Netflix Prize (http://en.wikipedia.org/wiki/Netflix_Prize )가 열리던 시절에 발표된 <암묵적 피

드백 데이터셋에 대한 협업 필터링Collaborative Filtering for Implicit Feedback Datasets>(http://yifanhu.net/

PUB/cf.pdf )과 <넷플릭스 프라이즈를 위한 대규모의 병렬 협업 필터링Large-scale Parallel Collaborative

Filtering for the Netflix Prize>(http://goo.gl/y34MK2 )과 같은 논문 덕에 유명해졌다. 사실 스파크의

MLlib이 제공하는 ALS 알고리즘도 이 논문들에서 아이디어를 가져와 구현한 것이다.

Y의 값을 모르지만, 무작위로 값이 선택된 행 벡터로 초기화할 수는 있다. 그런 다음 간단한

선형대수를 통해 주어진 A와 Y에 대한 최적 X를 구할 수 있다. 사실, X의 각 행 i는 Y와 A의

한 행의 함수로 독립적으로 쉽게 계산할 수 있다. 독립적으로 수행할 수 있으니 병렬 처리가 가

능하며, 이는 대규모로 계산할 때 매우 훌륭한 장점이다.

A iY (Y TY )-1 = X i

이 수식의 양 변을 똑같이 만들기란 불가능하므로, 우리의 목표는 양 변의 차이인

|A iY (Y TY )-1 - X i|, 즉 두 행렬에서 대응되는 원소 간 차의 제곱의 합을 최소화하는 것이다.

여기서 최소 제곱least squares이라는 이름이 유래되었다. 실전에서는 역행렬을 구하는 방법으로 계

산하지 않고 QR 분해QR decomposition (http://en.wikipedia.org/wiki/QR_decomposition )와 같은

방법으로 더 빠르게 바로 계산할 수 있다. 앞의 식은 단순히 행 벡터가 어떻게 계산되는지의 이

론을 설명하기 위한 것이다.

같은 방법으로 X로부터 각 Y j를 계산할 수 있다. 그리고 다시 같은 방법으로 Y j로부터 X를 계

산할 수 있다. 그래서 이 과정을 교차 alternating라고 한다. 이제 한 가지 작은 문제만 남았다. Y는

무작위로 만들어진 값이므로, 비록 X가 최적값으로 계산되었지만 가짜 해에 불과하다는 것이다.

다행히도 이 과정을 반복해가다 보면 종국에는 X와 Y 모두 제대로 된 해로 수렴하게 된다.

93Chapter 4 - 의사 결정 나무로 산림 식생 분포 예측하기

예측은 매우 어려우며, 미래에 대해서는 특히 그렇다.

-닐스 보어

19세기 후반 영국의 우생학자 프랜시스 골턴 경Sir Francis Galton은 완두콩과 사람 등을 대상으로 그

키를 측정하는 데 집중했다. 그는 키가 큰 완두콩과 사람의 다음 세대 역시 평균보다 크다는 사

실을 발견했다. 놀라운 발견이라고는 할 수 없다. 하지만 그다음 세대는 평균적으로 부모보다

조금 작았다. 사람의 경우 키가 2미터에 달하는 야구 선수의 자식은 물론 평균보다야 크겠지

만, 그렇다고 2미터까지 크지는 않는다는 뜻이다.

이 연구의 뜻하지 않은 결과 덕분에 골턴은 부모 세대의 키와 비교하여 자식 세대의 키를 정리

해보았고 둘 사이에 대략적인 선형 관계가 있음을 알아냈다. 큰 부모 완두콩은 큰 자식 완두콩

으로 이어졌지만, 큰 부모보다는 조금 작았다. 작은 부모 완두콩도 작은 자식 완두콩으로 이어

지지만, 역시 부모보다는 조금 컸다. 이 선형 관계에서 직선의 기울기는 1보다 작은 양수였고,

골턴은 이 현상을 평균으로의 회귀regression to the mean라고 표현했다. 오늘날 우리도 이 표현을 사용

한다.

당시에는 인지하지 못했을지언정, 나에게 이 선형 관계는 예측 모델의 오래된 예로 보인다. 두

값을 연결한 선이 있다는 것은 하나의 값이 다른 값에 대해 많은 것을 시사할 수 있음을 의미한

다. 어떤 완두콩의 자식의 크기는 그 완두콩과 비슷할 것이라고 가정하는 것보다 이 관계를 이

용하여 자식 세대의 크기를 계산하는 쪽이 훨씬 정확할 것이다.

의사 결정 나무로 산림 식생 분포 예측하기

CHAPTER 4

션 오언

94 9가지 사례로 익히는 고급 스파크 분석

4.1 회귀로 돌아와서

통계학이 체계를 갖춘 지 한 세기 이상이 지나고 기계 학습과 데이터 과학이 등장한 오늘날

에도, 주어진 값들로부터 새로운 값을 예측하는 방법으로 ‘회귀(http://en.wikipedia.org/

wiki/Regression_analysis )’를 꼽는다. 심지어 값이 평균에 가까워지거나 실제로 가까워지

려는 움직임조차 없을지라도 말이다. 또한, 회귀 기법은 분류 기법과 연관되어 있다(http://

en.wikipedia.org/wiki/Statistical_classification ). 일반적으로 회귀는 크기, 수입, 온도와

같은 숫자를 예측하는 반면, 분류는 ‘스팸 메일’, ‘고양이 사진’과 같은 레이블이나 범주를 예측하

는 데 사용한다.

회귀와 분류의 연결 지점은, 두 방법 모두 하나 이상의 값이 주어졌을 때 하나 이상의 값

을 예측하는 일이라는 것이다. 이를 위해서 학습을 위한 입출력 체계가 구성되어 있어야 하

며, 질문과 이에 대한 답변도 제공되어야 한다. 이러한 탓에 회귀와 분류는 지도 학습supervised

learning (http://ko.wikipedia.org/wiki/지도_학습) 유형에 들어간다.

분류와 회귀는 가장 오래되고 가장 잘 연구된 유형의 예측 분석이다. 서포트 벡터 머신support

vector machine, 로지스틱 회귀logistic regression, 나이브 베이즈 분류naïve Bayes, 신경망neural networks, 그리

고 딥 러닝deep learning과 같은 분석 패키지나 라이브러리에서 자주 접하는 대부분의 알고리즘은

분류와 회귀 기법이다. 3장의 주제인 추천 엔진도 더 직관적이라는 이유로 앞 장의 주제로 사

용했지만, 역시 비교적 최근에 따로 떨어져나온 기계 학습의 하위 주제일 뿐이다.

이번 장에서는 분류와 회귀 모두에 적용할 수 있는 대중적이고 유연한 알고리즘인 의사 결정 나

무(http://en.wikipedia.org/wiki/Decision_tree ), 그리고 그것의 확장판인 랜덤 포레스트

(http://en.wikipedia.org/wiki/Random_forest )를 다루고자 한다. 이 알고리즘과 관련한

흥미로는 사실은 닐스 보어가 미래 예측에 대해서 말한 것과 달리 미래를 예측에 사용할 수 있

으며, 적어도 아직은 우리가 명확히 알지 못하는 것을 예측할 수 있다는 것이다. 예를 들어 온

라인에서의 행동 양식으로부터 차를 살 가능성을 예측한다든지, 전자우편 내의 어떤 단어로부

터 이 전자우편이 스팸인지 여부를 찾아낸다든지, 위치와 토양의 화학성분비가 주어졌을 때 몇

제곱미터의 땅에서 작물을 재배할 수 있는지 등과 같은 것이다.

95Chapter 4 - 의사 결정 나무로 산림 식생 분포 예측하기

4.2 벡터와 특징

특정 데이터셋과 알고리즘을 선택하는 방법, 그리고 회귀와 분류가 동작하는 방법을 설명하기

위해서는 우선 입력과 출력을 나타내는 용어들을 간단하게 정의할 필요가 있다.

오늘의 일기를 전제로 내일의 최고 기온을 예측하는 문제를 생각해보자. 별문제 없어 보이지

만, 그저 ‘오늘의 일기’라고 하면 너무 광범위한 개념이라 학습 데이터로 사용하려면 구조화해

야 한다.

오늘 일기의 다음과 같은 특징으로부터 내일 기온을 예측할 수 있다.

● 오늘의 최고 기온

● 오늘의 최저 기온

● 오늘의 습도

● 흐림(cloudy ), 비(rainy ), 맑음(clear )과 같은 날씨 유형

● 내일 일시적 한파를 예상한 기상 예보관의 수

이 특징들은 종종 차원dimension, 예측 변수predictor 또는 단순히 변수variable로 불린다. 각각의 특징은

정량화될 수 있다. 예를 들어 최고 기온과 최저 기온은 섭씨온도로 측정하고, 습도는 0과 1 사

이의 소수로 계량하고, 날씨 유형은 ‘cloudy’, ‘rainy’, ‘clear’로 표시할 수 있다. 물론 예보관의

수는 정수다. 이에 따라 오늘의 일기는 ‘13.1, 19.0, 0.73, cloudy, 1’과 같은 하나의 리스트로

축약할 수 있다.

이 다섯 가지 특징을 순서대로 묶어 특징 벡터feature vector라고 부르고 어떤 날의 일기를 표현할 수

있다. 이 벡터에 숫자형이 아닌 값이 포함될 수 있고, 또 어떤 값은 생략될 수도 있다는 점만 제

외하면 선형대수에서의 벡터 사용법과 유사하다.

이들 특징은 모두 같은 형식이 아니다. 앞의 두 개는 섭씨온도로 측정한 값이지만, 세 번째는

단위가 없는 비율이다. 네 번째는 아예 수가 아니고, 다섯 번째는 음이 아닌 정수다.

논하는 바의 목적에 맞춰 이 책에서는 범주형 특징categorical feature과 수치형 특징numeric feature 두 종류

의 특징만 다룰 것이다. 여기서 수치형 특징은 수를 사용해 정량화할 수 있고 순서가 의미가 있

다. 예를 들어 오늘의 최고 기온인 23도가 어제 최고 기온인 22도보다 높다고 이야기하는 것은

유효하다. 날씨 유형을 제외한 모든 특징은 수다. ‘clear’와 같은 용어는 수도 아니고 순서도 없

96 9가지 사례로 익히는 고급 스파크 분석

다. 그래서 ‘cloudy’가 ‘clear’보다 크다고 말하는 것은 의미가 없다. 이것이 범주형 특징에 해

당하며, 여러 불연속discrete 값 중 하나를 취하게 된다.

4.3 학습 예제

예측을 위해서는 학습 알고리즘을 데이터로 학습시켜야 한다. 이를 위해 과거의 데이터로부터

얻은 많은 수의 입력 데이터와 각각에 대응하는 정확한 출력 데이터가 필요하다. 이 문제에서

예를 들자면, 어느 날 기온은 최저 12도, 최고 16도이며, 습도는 10%, 날씨는 맑고, 아무도 한

파 예보를 하지 않았다는 그 날의 일기 정보와 함께, 다음 날의 최고 기온인 17.2도가 동시에

학습 알고리즘에 제공되는 형태다. 이러한 예제 데이터가 충분히 많이 있어야 다음 날의 최고

기온을 예측하는 학습 알고리즘을 제대로 학습시킬 수 있다.

특징 벡터는 학습 알고리즘에 입력을 표현하기 위한 체계적인 방법을 제공한다. 여기에서는

{12.5, 15.5, 0.10, clear, 0}가 된다. 예측의 출력이나 목표 또한 특징으로 간주할 수 있는

데, 예를 들어 내일 최고 기온 17.2는 수치형 특징이다.

특징 벡터에 목표도 하나의 특징으로 포함시키는 일이 드물지 않다. 학습을 위한 완전한 예제

는 목표인 다음 날의 최고 기온까지 포함한 {12.5, 15.5, 0.10, clear, 0, 17.2}까지로 봐야

하며, 이 예제들의 집합을 학습 데이터셋training set이라고 부른다.

회귀에서는 수를, 분류에서는 범주를 대상으로 삼는다는 점을 기억하자. 모든 회귀나 분류 알

고리즘이 범주형 특징을 다루거나 범주를 목적으로 할 수 있는 것은 아니다. 일부는 수치형 특

징으로만 제한된다.

4.4 의사 결정 나무와 랜덤 포레스트

의사 결정 나무decision tree에 속하는 알고리즘은 범주형 특징과 수치형 특징 모두를 자연스럽게 다

룰 수 있다. 병렬로 쉽게 구축할 수도 있다. 의사 결정 나무는 데이터 내의 독특한 값outlier, 이상치

들에 잘 휘둘리지 않는 특성을 가지는데, 몇몇 극단적인 오류를 내포한 값들이 예측치에 영향

을 줄 수 없음을 의미한다. 그리고 전처리나 정규화 과정을 거치지 않고도 다른 유형과 다른 척

97Chapter 4 - 의사 결정 나무로 산림 식생 분포 예측하기

도의 데이터를 다룰 수 있다(이 내용은 5장에서 다시 소개할 것이다).

의사 결정 나무를 더 강력하게 일반화한 알고리즘이 랜덤 포레스트random decision forest다. 이 장에서

는 스파크 MLlib이 제공하는 DecisionTree와 RandomForest를 데이터셋에 적용해서 이들

알고리즘의 유연성을 살펴볼 것이다.

의사 결정 나무 기반의 알고리즘은 직관적으로 이해할 수 있고 추론할 수 있다는 또 하나의 장

점이 있다. 실제로 누구나 의사 결정 나무에 내재된 방식과 같은 추론을 일상에서 사용하리라

생각한다. 예를 들어 나는 모닝커피에 우유를 섞어 마시는데, 우유를 붓기 전에 우유가 상했는

지를 생각해본다. 확신이 없다면 그 우유의 유통 기한이 지났는지를 확인한다. 유통 기한이 지

나지 않았다면 상하지 않았을 것으로 예측한다. 유통 기한이 지났더라도 사흘이 넘지 않았다면

상하지 않은 것으로 예측하고, 사흘이 넘었다면 냄새를 맡아봐서 그 냄새가 이상하면 상한 것,

그렇지 않다면 상하지 않은 것으로 예측한다.

예측으로 이어지는 일련의 예/아니오 선택이 의사 결정 나무에 내재된 추론 방식이다. 각각의

결정으로 두 결과 중 하나로 넘어가는데, [그림 4-1]에서 볼 수 있듯, 최종 결과일 수도 있고

또 다른 결정의 순간일 수도 있다. 이런 의미에서 이 프로세스는 각각의 결정을 내부 노드로,

최종 해답을 말단 노드로 가지는 트리 구조로 간주하는 것이 자연스럽다.

그림 4-1 의사 결정 나무 : 우유가 상했나?

98 9가지 사례로 익히는 고급 스파크 분석

이런 규칙은 어린 시절 수년간 직관적으로 습득해 적용해온 것으로, 상한 우유와 상하지 않은

우유를 구분하는 간단하면서도 쓸만한 규칙이자, 의사 결정 나무의 성격을 보여주는 좋은 예다.

이것은 단순화한 의사 결정 나무로, 정밀하게 만들어지지 않았다. 더 자세한 설명을 위해서 다

른 예제를 생각해보자. 로봇이 이색 애완동물 가게에서 일하고 있다. 로봇은 상점 문을 열기 전

에 가게의 어떤 동물이 아이에게 적절할지를 알고 싶어 한다. 가게 주인은 가게를 떠나기 전에

애완동물 아홉 마리의 목록을 만들어 아이에게 적절한지 여부를 기록했다. 애완동물을 조사하

면서 이 목록을 결합하여 [표 4-1]과 같은 자료를 만든다.

표 4-1 이색 애완동물 상점 ‘특징 벡터’

이름 무게(Kg ) 다리의 수 색 아이에게 적절한가?

초꼬 20 .5 4 갈색 적절

콩이 3 .1 0 녹색 부적절

호야 0 .2 0 구릿빛 적절

치즈 1390 .8 4 회색 부적절

나비 12 .1 4 회색 적절

다롱이 150 .9 2 구릿빛 부적절

은띵이 0 .1 100 갈색 부적절

꾸꾸 1 .0 2 회색 부적절

루비 10 .0 4 갈색 적절

이름은 특징으로 포함되지 않는다. 이름만으로 무엇인가를 예측할 수 있을 것으로 생각할만한

이유가 없다. ‘루비’라는 이름은 고양이한테도, 독거미한테도 붙일 수 있기 때문이다. 이름을 제

외하고 두 개의 수치형 특징(무게와 다리의 수)과 하나의 범주형 특징(색)이 있다. 그리고 이

특징들로 예측할 범주인 아이에게 적절한지 여부가 있다.

처음에는 [그림 4-2]처럼 무게를 유일한 판단 기준으로 삼는 간단한 의사 결정 나무를 이 데이

터셋에 적합fit시켜보자.

121Chapter 5 - K-평균 군집화로 네트워크 이상 감지하기

알고 있음이 알려진 것들이 있다. 즉, 우리가 알고 있음을 우리가 아는 것들이 있다. 또, 우리는 모

르고 있음이 알려진 것들이 있다는 것도 알고 있다. 다시 말해서, 우리가 모르는 어떤 것들이 있음

을 우리는 알고 있다. 그러나 역시 모르고 있음이 알려지지 않은 것들, 즉 우리가 모르고 있는지도

모르는 것들도 있다.

-도널드 럼스펠드

분류와 회귀는 강력하고 깊이 연구된 기계 학습 기술이다. 4장에서는 모르는 값들을 예측하는

데 쓰이는 분류기를 다루었다. 한 가지 문제가 있었는데, 새로운 데이터에 대한 모르는 값들을

예측하려면 사전에 관측한 많은 사례의 목표값을 알고 있어야 했다. 분류기는 우리 데이터 과

학자가 찾고 있는 것이 무엇인지 이미 알고 있고, 입력과 그에 따른 결과가 알려진 사례가 확보

되었을 때만 도움이 될 수 있다. 학습 과정에서 사례별 정확한 결과값을 입력으로 받아들이기

때문에 이런 종류의 방법을 지도 학습이라 한다.

하지만 일부 또는 전체 사례의 정확한 결과를 모르는 상황에서는 지도 학습 방법에 문제가 있

다. 전자상거래 사이트 고객들을 쇼핑 습관이나 취향으로 나누는 문제를 생각해보자. 입력으로

사용되는 특징에는 구매 이력, 클릭 정보, 인구통계학적 정보 등이 있다. 결과는 고객들을 나눈

집단들일 것이다. 아마도 어떤 집단은 유행에 민감한 구매자들을 나타낼 것이고, 또 다른 집단

은 가격에 민감하며 싸고 질 좋은 물건을 사려는 고객으로 밝혀질 것이고, 기타 등등의 집단이

있을 것이다.

K-평균 군집화로 네트워크 이상 감지하기

CHAPTER 5

션 오언

122 9가지 사례로 익히는 고급 스파크 분석

새로운 고객이 가입할 때마다 그 고객이 어떤 목표 레이블target label에 해당하는지 결정해야 한다

면 분류기와 같은 지도 학습 기술은 곧 문제에 봉착하게 될 것이다. 누가 유행에 민감하다고 여

겨야 할지에 대한 선험적 지식1이 없기 때문이다. 사실 맨 처음에는 ‘유행에 민감함’이란 기준이

사이트 고객을 의미 있게 군집화하는지조차 확신할 수 없을 것이다.

다행히도 비지도 학습unsupervised learning, 자율 학습(https://goo.gl/U7mBF4 ) 방법이 도움이 될 수 있

다. 이 방법은 이용할 수 있는 목표값이 하나도 없기 때문에 어떤 목표값을 예측하기 위한 학습

을 하지 않는다. 그러나 이 방법은 데이터의 구조를 학습할 수 있고, 비슷한 입력들의 집단을

찾을 수 있고, 발생할 가능성이 높은 입력과 그렇지 않은 입력의 종류를 학습할 수 있다. 이번

장에서는 MLlib의 군집화 구현을 사용하여 비지도 학습을 소개할 것이다.

5.1 이상 감지

이상 감지anomaly detection, 이상 탐지는 그 이름이 암시하듯 특이한 것들을 찾아내는 문제다. 특정 데이

터셋에서 ‘이상한’이 뜻하는 바를 이미 알고 있다면 지도 학습 방법으로도 이상한 부분을 쉽게

찾아낼 수 있을 것이다. 지도 학습 알고리즘은 ‘정상normal’이나 ‘이상anomaly’ 레이블이 붙은 입력

을 받아서 그 둘을 구분하도록 학습될 것이다. 하지만 이상한 것들의 본질은 ‘모르고 있음이 알

려지지 않은 것’이라는 데 있다. 다시 말해, 관측하고 이해할 수 있게 된 ‘이상’은 더 이상 ‘이상’

이 아닌 것이다.

이상 감지는 사기fraud를 찾거나 네트워크 공격을 탐지하거나 서버의 문제점 또는 센서를 갖춘

설비의 문제점을 발견하는 데 주로 사용한다. 이런 경우에는 새로운 형태의 사기, 새로운 침입,

새로운 서버 장애 유형 등 지금까지 겪어보지 못한 새로운 종류의 이상을 찾아내는 능력이 중

요하다.

비지도 학습 기법은 이럴 때 유용하다. 왜냐하면, 비지도 학습 기법은 입력 데이터의 정상적인

형태를 학습해가며 새로운 데이터가 과거 데이터와 비슷하지 않을 때 이를 감지할 수 있기 때

문이다. 과거와 다른 새로움이 반드시 공격이나 사기인 것은 아니다. 단지 특이한 것이므로 더

1 옮긴이_ 선험적 지식이란 경험을 한 뒤에 얻은 후험적(경험적) 지식과 반대되는 개념으로 경험과 독립해서 어떤 개념이나 사실에 대해 지식을 갖는다면 그것을 경험에 앞선 지식 즉, 선험적 지식이라 한다.

123Chapter 5 - K-평균 군집화로 네트워크 이상 감지하기

조사해볼 가치가 있다.

5.2 K-평균 군집화군집화는 가장 잘 알려진 비지도 학습 방법이다. 군집화 알고리즘은 데이터를 자연스럽게 군집

(집단)으로 묶는 것을 목적으로 한다. 서로 비슷하지만 그 외의 것들과는 다른 데이터 포인트

들이 의미 있는 군집을 나타낼 가능성이 높으므로, 군집화 알고리즘은 이런 데이터를 같은 군

집으로 묶기 위해 노력한다.

K-평균 군집화K-means Clustering (http://ko.wikipedia.org/wiki/K-평균_알고리즘)는 아마도 가장

널리 사용되는 군집화 알고리즘일 것이다. 이 알고리즘은 데이터셋에서 k개의 군집을 찾으려

시도하며, 여기서 k는 데이터 과학자가 정한다. k는 해당 모델의 하이퍼파라미터이고, 적절한

값은 데이터셋에 따라 다를 것이다. 사실 좋은 k 값을 선정하는 것이 이번 장의 핵심이다.

고객의 행위와 같은 정보를 포함한 데이터셋에서 ‘비슷하다’는 말은 무슨 의미일까? 또 트랜잭

션과 같은 데이터셋에서는? K-평균 알고리즘에서는 데이터 포인트 간 거리라는 개념이 필요하

다. K-평균 알고리즘에서는 데이터 포인트 간 거리를 측정할 때 간단한 유클리디안 거리Euclidean

distance, 유클리드 거리를 가장 널리 사용하는데, 이 책을 쓰는 시점에 스파크 MLlib이 유일하게 지원

하는 거리 함수이기도 하다. 유클리디안 거리는 특징들이 모두 숫자인 데이터에서 사용할 수

있다. 데이터 포인트들이 ‘비슷하다’는 것은 둘 사이의 유클리디안 거리가 가깝다는 뜻이다.

K-평균 알고리즘에서 군집은 그 군집을 이루는 모든 요소 점들의 중심을 나타내는 하나의 점

에 지나지 않는다. 사실 요소 점들은 모두 숫자로 이루어진 특징 벡터일 뿐이며, 간단히 벡터라

고 부를 수 있다. 여기서는 점으로 생각하는 게 더 직관적일 수 있다. 이들은 유클리디안 공간

Euclidean space, 유클리드 공간에서는 점으로 취급하기 때문이다.

군집의 한가운데를 군집 중심centroid이라 하며, 군집 내의 점들의 산술 평균에 해당한다. 그래서

K-평균이라고 부르는 것이다. 이 알고리즘은 우선 일부 데이터 포인트들을 초기 군집 중심으

로 선택한다. 그런 후에 각각의 데이터 포인트는 가장 가까운 중심으로 할당된다. 그런 다음에

군집별로 군집에 할당된 모든 데이터 포인트의 산술 평균을 구해서 새로운 군집 중심을 구한

다. 이 과정이 반복된다.

124 9가지 사례로 익히는 고급 스파크 분석

이 알고리즘에 대해서는 당장은 이 정도면 충분하다. 더 흥미롭고 자세한 내용은 다음 활용 사

례에서 보게 될 것이다.

5.3 네트워크 침입

뉴스를 보면 소위 사이버 공격이 점점 늘어나고 있다. 어떤 공격은 정상적인 네트워크 접근을

방해할 목적으로 대량의 네트워크 트래픽을 쏟아 붙는다. 또 다른 공격은 네트워크 소프트웨어

의 취약점을 공격하여 승인되지 않은 권한을 확보하려 시도한다. 트래픽을 이용한 공격은 매우

명확한 상황인 데 비해, 익스플로잇exploit이라고도 하는 취약점 공격을 감지하기란 네트워크 요청들

의 거대한 건초 더미에서 바늘 찾기와 같을 수 있다.

몇몇 취약점 공격의 행동 패턴은 알려져 있다. 예를 들어 빠르고 지속해서 모든 포트에 접근해

보는 일은 정상적인 소프트웨어가 할 만한 행동은 아니지만, 침입자라면 컴퓨터에서 악용할 만

한 서비스를 찾기 위해서 맨 처음 하는 일반적인 행위다.

만약 짧은 시간에 원격 호스트가 서로 다른 포트에 접근한 횟수를 집계할 수 있었다면 포트 스

캐닝 공격을 꽤 잘 예측할 수 있는 특징을 가진 것이다. 몇 건 정도는 아마도 정상이겠지만, 수

백 건이 되면 공격일 것이다. 전송하고 수신한 바이트의 수, TCP 오류 등 네트워크 연결과 관

련한 다른 특징도 동일한 방식을 활용해서 다른 종류의 침입을 탐지할 수도 있다.

하지만 알려지지 않은 미지의 상황이라면 어떨까? 지금까지 한 번도 알려진 적이 없어서 분류

된 적도 없는 그런 공격이 가장 큰 위협일 수 있다. 잠재적 네트워크 침입을 찾아내는 일은 이

상 감지에 해당한다. 이런 경우는 침입 행위로 알려져 있지 않지만, 과거에 관측된 연결들과는

양상이 다르다.

이상한 네트워크 연결을 찾아내는 데 K-평균과 같은 비지도 학습 기법을 사용할 수 있다. K-

평균 방법은 연결 각각에 대한 통계에 기반하여 연결들을 군집화할 수 있다. 결과로 나온 군집

들 자체에는 의미가 없다. 하지만 군집들은 전체적으로 과거의 연결들과 유사한 연결 유형들을

정의하고 있다. 어떤 군집과도 유사하지 않은 연결은 이상한 연결일 수 있다. 군집들이 정상 연

결들의 영역을 정의할 때 그 군집들은 의미를 가진다. 그 범위 밖의 모든 연결은 특이하며 잠재

적으로 이상한 연결인 것이다.

125Chapter 5 - K-평균 군집화로 네트워크 이상 감지하기

5.4 KDD 컵 1999 데이터셋

KDD 컵KDD Cup (http://www.sigkdd.org/kddcup/index.php )은 ACM의 특화 분야 분과

에서 매년 주최하던 데이터 마이닝 대회다. 해마다 하나의 기계 학습 문제가 데이터셋과 함

께 출제되며, 연구자들은 그 문제를 푸는 최선의 답을 상세히 기술한 논문을 제출한다. 캐

글Kaggle (http://www.kaggle.com/ )이 열리기 전에, KDD 컵은 캐글과 비슷한 것이었다.

네트워크 침임을 주제로 한 1999년 대회의 데이터셋은 지금도 사용할 수 있다(http://bit.

ly/1ALCuZN ). 이번 장에서는 이 데이터를 학습하여 스파크를 사용한 이상 네트워크 트래픽

감지 시스템을 구축하는 것을 보여주려 한다.

NOTE_ 이 데이터셋을 실제 네트워크 침입 감지 시스템을 구축하는 데 이용하지는 마라! 이 데이터가 꼭 그

당시의 실제 네트워크 트래픽을 반영하는 것도 아니며, 어쨌든 이 데이터는 15년도 더 전의 트래픽 패턴을 반

영할 뿐이다.

다행히도 주최 측은 네트워크 패킷 원본을 개별 네트워크 연결에 관한 요약 정보 형태로 처리

해두었다. 데이터셋의 크기는 약 708MB이며 490만 개의 연결을 담고 있다. 방대하다고까지

하기는 그렇지만 제법 큰 데이터인데, 이 장에서 필요한 만큼은 된다. 데이터셋은 각 연결의 전

송된 바이트 수, 로그인 시도 횟수, TCP 에러 개수 등과 같은 정보를 담고 있다. 데이터의 한

줄이 연결 하나에 대응하며 다음과 같이 38개의 수치형 특징을 포함한 CSV 형식으로 만들어

졌다.2

0,tcp,http,SF,215,45076,

0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,

0.00,0.00,0.00,0.00,1.00,0.00,0.00,0,0,0.00,

0.00,0.00,0.00,0.00,0.00,0.00,0.00,normal.

이 연결은 HTTP 서비스에 대한 TCP 연결로, 215바이트를 송신하고 45,706바이트를 수신했

다. 사용자는 로그인되어 있으며, 기타 다른 내용도 포함하고 있다. 많은 특징이 17번째 특징

인 num_file_creations와 같은 횟수 정보다.3

2 옮긴이_ 총 42개의 값 중 범주형 특징 3개와 레이블 1개를 빼서 38개다.

3 옮긴이_ 각 특징의 이름과 형태는 공개된 데이터셋의 kddcup.names 파일(http://goo.gl/CBEZv5)에 기록돼 있다.

126 9가지 사례로 익히는 고급 스파크 분석

또 많은 특징이 15번째 특징인 su_attempted처럼 어떤 행위가 있음 혹은 없음을 나타내는 0

또는 1을 취한다. 4장에서 소개한 원-핫 인코딩을 사용해 범주형 특징을 수치형으로 다시 표

현한 것과 비슷해 보이지만, 사실 동일한 방법으로 묶거나 관련지은 것은 아니다. 이들은 예/

아니오 특징 같은 것이고, 따라서 범주형 특징임에는 거의 틀림없다. 범주형 특징을 숫자로 바

꾸어 마치 순서가 있는 것처럼 취급하는 것이 항상 적절한 것은 아니지만, 이진binary 범주형 특

징과 같이 특별한 경우에는 0과 1을 취하는 수치형 특징에 대응하더라도 대부분의 기계 학습

알고리즘에서 놀랍게도 잘 동작할 것이다.

끝에서 두 번째인 dst_host_srv_rerror_rate와 같이 나머지는 모두 비율을 나타내고

0.0~1.0의 값을 가진다.

흥미롭게도 레이블은 마지막 필드로 제공된다. 대부분의 연결은 정상(normal. )이지만, 일부

는 다양한 유형의 네트워크 공격 사례로 기록되어 있다. 이를 이용하여 알려진 공격을 정상 연

결과 구분하도록 학습할 수 있지만, 여기서 하려는 것은 이상을 감지하여 궁극적으로 알려지지

않은 새로운 공격을 찾아내는 것이다. 레이블은 이런 목적과 맞지 않기 때문에 대부분의 예제

에서 제외했다.

5.5 첫 번째 군집화하기

kddcup.data.gz 파일의 압축을 풀고 HDFS로 복사하자. 다른 장과 마찬가지로 이 예제에서도

파일이 /user/ds/ 디렉터리에 있다고 가정한다. spark-shell을 띄우고 다음과 같이 CSV 데이

터를 String의 RDD로 불러들인다.

val rawData = sc.textFile("hdfs:///user/ds/kddcup.data")

먼저 데이터셋를 들여다보자. 데이터에 어떤 레이블이 있고, 그 레이블은 각각 몇 개씩 있을

까? 다음 코드는 레이블별 개수를 세어 레이블-개수 튜플을 생성하고, 이를 내림차순 정렬한

결과를 출력한다.

rawData.map(_.split(',').last).countByValue().toSeq.

sortBy(_._2).reverse.foreach(println)

145Chapter 6 - 숨은 의미 분석으로 위키백과 이해하기

스노든의 무리는 작년에 어디 있었나?1

-요사리안 대위

데이터 엔지니어링 과정의 대부분은 수집한 데이터를 질의가 가능한 형태로 가공하는 일이다.

테이블 형태로 구조화되어 있으면 SQL을 사용할 수 있듯, 데이터가 구조화되어 있으면 형식

언어로 질의할 수 있다. 높은 수준으로 구조화하는 일이 결코 쉬운 일은 아니지만, 데이터를 테

이블 형태 만드는 일 자체는 간단할 수도 있다. 다양한 데이터 출처로부터 데이터를 가져다가

테이블 하나에 쑤셔넣은 다음, 정해진 방법에 따라 데이터를 정제하고 잘 합쳐내면 되는 일이

다. 구조화되지 않은 텍스트 데이터를 다루는 것은 완전히 다른 일이다. 사람이 가져다 쓸 수

있는 형태로 데이터를 준비하는 작업은 ‘조립assembly’이라기 보다는 잘 될 때는 ‘색인indexing’, 잘

안 될 때는 ‘억지coercion’다. 일반적으로 색인을 사용하면 주어진 단어들을 포함한 문서 집합을

빠르게 찾을 수 있다. 하지만 종종 정확한 문자열이 주어지지 않았더라도 특정 단어와 관련된

문서를 찾고자 할 때도 있는데, 표준적인 검색 색인에서는 주어진 텍스트의 ‘주제’와 관련한 숨

어 있는 구조를 찾아내지 못할 때가 많다.

숨은 의미 분석Latent Semantic Analysis (LSA )은 문서 뭉치를 더 잘 이해하고, 뭉치에 속한 문서 속 단어

들 사이의 관계를 찾는 자연어 처리Natural Language Processing (NLP ) 및 정보 검색 기술이다. LSA는 뭉

치들로부터 적절한 의미들의 집합을 뽑아낸다. 각각의 의미는 다양하게 변형되어 문서에 나

1 옮긴이_ 조지프 헬러의 소설 <캐치-22>의 주인공인 요사리안 대위가 소설 중에서 던진 돌아온 답이 없는 질문이다.

숨은 의미 분석으로 위키백과 이해하기

CHAPTER 6

샌디 라이자

146 9가지 사례로 익히는 고급 스파크 분석

타나는데, 그중에 해당 문서 뭉치가 다루는 주제에 부합되는 것이 있다. 수학적으로 접근하기

는 아직 이르지만, 모든 의미는 세 가지 속성을 갖는다. 첫째는 뭉치에 속한 각 문서가 가지는

관련성의 정도, 둘째는 뭉치 내의 각 단어가 가지는 관련성의 정도, 셋째는 어떤 의미가 데이

터셋 내의 변형을 설명하는 데 얼마나 유용한가를 나타내는 중요도 점수다. 예를 들어 ‘아시모

프Asvimov’와 ‘로봇’이라는 단어 사이의 강한 연관성, 그리고 파운데이션 연작2 문서들과 과학 소

설 문서들 사이의 강한 연관성에 LSA를 적용하면 (연관성이 지니는) 의미를 찾아낼 수 있다.

LSA를 시행하면서 매우 중요한 의미들만 선택하면 관련성이 낮은 노이즈를 제거하고 겹치는

부분을 합칠 수 있으며, 이를 통해서 데이터를 더 간단하게 표현할 수 있다.

이런 간단한 표현을 다양한 작업에 적용할 수 있다. LSA로부터 단어와 단어 사이, 문서와 문서

사이, 그리고 단어와 문서 사이의 유사성 점수를 얻을 수 있다. 뭉치 안의 다양한 패턴을 잘 묶어

내면, 단순히 특정 단어가 몇 번 나왔는지나 어떤 단어 조합이 함께 나온 게 몇 번인지를 세는

것보다 유사성 점수가 그 문서를 이해하는 데 더 도움이 될 것이다. 이러한 유사성 척도는 특정

단어와 연관된 문서 찾기, 주제가 같은 문서끼리 묶기, 그리고 관련 단어 찾기 등과 같은 작업

에 알맞은 방법이다.

LSA는 특이값 분해(SVD )라는 선형대수 기법을 활용하여 이러한 더 낮은 차원의 표현 방법을

찾아낸다. 특이값 분해는 3장에서 본 ALS 분해의 더 강력한 버전으로 생각하면 된다. 먼저, 각

문서에 특정 단어가 나온 횟수를 세어 단어-문서 행렬term-document matrix을 만든다. 이 행렬의 행은

단어에, 열은 문서에 해당하고, 각 원소는 특정 문서에 있어서 특정 단어의 중요도를 나타낸다.

그런 다음 특이값 분해를 적용하여 이 행렬을 세 개의 행렬로 분해한다. 하나는 문서들과 관련

된 의미들을 표현한 행렬, 다른 하나는 단어들과 관련된 의미들을 표현한 행렬, 마지막 하나는

각 의미의 중요도를 담고 있는 행렬이다. 이런 구조의 행렬에서 덜 중요한 의미들에 대응하는

행과 열을 제거하여 원 행렬의 낮은 계수 근사low-rank approximation를 만들 수 있다. 각각의 행렬에서

중요도가 떨어지는 의미에 대응하는 행과 열을 제거한 후 다시 곱하면 원래의 행렬에 가까운 행

렬을 만들 수 있다. 이때 의미가 하나씩 제거될 때마다 이 근사의 정확성은 점점 떨어지게 된다.

이 장에서는 숨은 의미의 관계에 근거하여 인간 지식의 전 범위를 아우르는 질의를 가능하게

하는 소소한 작업에 착수하려 한다. 구체적으로 말하자면, 원문 텍스트 기준으로 약 46GB에

달하는 위키백과에 포함된 모든 문서로 구성된 문서 뭉치에 LSA를 적용할 것이다. 이 데이터

2 옮긴이_ 아이작 아시모프는 ‘로봇 3원칙’으로 유명한 작고한 SF 소설 작가이며 ‘파운데이션’은 그의 연작 SF 소설의 제목이다.

147Chapter 6 - 숨은 의미 분석으로 위키백과 이해하기

를 읽고, 정제하고, 수치 형태로 개조하는 데이터 전처리 과정에 스파크를 활용하는 방법을 다

루려고 한다. 또, 특이값 분해를 계산하는 방법과 이것을 어떻게 해석하고 활용해야 하는지를

보여줄 것이다.

LSA 외에도 특이값 분해는 폭넓게 활용되고 있다. 기후 변화 추세 파악(마이클 만의 유명한

하키 스틱 그래프, http://en.wikipedia.org/wiki/Hockey_stick_controversy ), 얼굴 인식, 이

미지 압축과 같은 다양한 곳에 사용된다. 스파크는 엄청나게 커다란 데이터셋도 행렬 분해할

수 있어서 또 다른 새로운 분야에도 기술의 이기를 전파할 수 있을 것이다.

6.1 단어-문서 행렬

분석에 들어가기 전에, 문서 뭉치 내의 원문에서 LSA에 사용할 단어-문서 행렬을 만들어야 한

다. 이 행렬의 각 행은 문서 뭉치에서 등장하는 단어들을 나타내고, 각 열은 문서를 나타낸다.

대략, 행과 열이 만나는 지점의 값은 어떤 (열에 해당하는) 문서에 있어서 (행에 해당하는) 단

어의 중요도에 대응되어야 한다. 중요도를 계산하는 방법이 몇 가지 있지만, 가장 널리 쓰이는

것은 단어 빈도term frequency (TF )와 역문서 빈도inverse document frequency (IDF )를 곱하는 방법이고, 줄

여서 TF-IDF라고 한다.

def termDocWeight(termFrequencyInDoc: Int, totalTermsInDoc: Int,

termFreqInCorpus: Int, totalDocs: Int): Double = {

val tf = termFrequencyInDoc.toDouble / totalTermsInDoc

val docFreq = totalDocs.toDouble / termFreqInCorpus

val idf = math.log(docFreq)

tf * idf

}

TF-IDF는 문서를 적절하게 설명할 수 있는 단어에 대한 두 가지 직관을 담아내고 있다. 첫 번

째 직관은 특정 문서에 어떤 단어가 많이 나올수록 그 문서에서 그 단어는 더욱 중요하다는 것

이다. 두 번째 직관은 전역적으로 볼 때 모든 단어의 가치가 동일하지는 않다는 것이다. 약방의

감초같이 항상 등장하는 단어보다 문서 뭉치의 다른 문서에는 잘 쓰이지 않는 단어가 등장하는

쪽이 더 의미가 있다. 그래서 뭉치의 전체 문서에서 단어가 출현하는 빈도의 역inverse을 사용하

148 9가지 사례로 익히는 고급 스파크 분석

자는 것이다.

문서 뭉치에서 단어들의 출현 빈도는 기하급수적인 모습을 띈다. 상용 단어들은 준 상용 단어

들보다 수십 배 더 자주 등장하지만, 이러한 준 상용 단어들조차 드문드문 사용되는 단어들에

비하면 수십, 수천 배 더 자주 등장한다. 이 때문에 단순히 역문서 빈도를 그대로 사용하면 드

문드문 사용되는 단어들에 어마어마하게 큰 가중치를 부여해서 다른 모든 단어의 영향력이 무

시되는 문제가 생긴다. 그래서 실전에서는 역문서 빈도의 로그 값을 사용한다. 로그 값을 사용

하면 곱의 차를 합의 차로 바꾸어서, 빈도로부터 오는 격차를 완화한다.

모델을 만들려면 몇 가지 가정이 필요하다. 문서를 ‘단어들의 가방’으로 생각하자. 이는 어순이

나 문장 구조, 또는 부정을 나타내는 꾸밈말 같은 것은 무시하겠다는 것이다. 또 각각의 단어는

한 가지 의미만을 가지며, 다의어多義語는 다루지 않는다. 예를 들어 “라디오헤드는 역대 최고의

밴드다”에서의 밴드와 “고무 밴드가 끊어졌어”에서의 밴드의 차이를 모델이 구분하지 못한다

는 뜻이다. 만약 두 문장이 한 문서 뭉치에서 자주 등장하면 고무와 라디오헤드가 연결된다.

우리가 사용할 문서 뭉치에는 천만 개의 문서가 포함되어 있다. 잘 알려지지 않은 기술 용어까

지 포함하면 영어 단어는 약 백만 개에 달하는데, 이 중 일부인 수만 개 정도면 문서 뭉치를 이

해하는 데 유용하지 않을까 한다. 단어의 수에 비해서 문서의 수가 훨씬 많으니, 단어-문서 행

렬을 각각이 하나의 문서에 대응하는 희소 벡터sparse vector들의 집합인 행 행렬row matrix 형태로 만드

는 것이 타당하다.

위키백과를 덤프한 원문은 하나의 커다른 XML 파일로, 그 안에 각 문서가 <page> 태그로 구

분되어 있다. 이를 단어-문서 행렬 형태로 바꾸기 위한 전처리 과정은 다음과 같다. 먼저 이

XML 파일을 문서 단위로 쪼개고, 각 문서에서 위키 특화 태그를 제거해 플레인 텍스트 파일로

바꿔야 한다. 그다음, 이 플레인 텍스트 파일을 토큰으로 나눈다. 이때 여러 가지 형태3로 표기

된 단어를 기본형으로 바꾸어 전체 토큰의 가짓수를 줄이는 과정을 거친다. 이 과정을 표제어 추

출lemmatization라고 한다. 그러고 나면 이 토큰을 대상으로 단어 빈도와 문서 빈도를 계산하여, 최

종적으로 실제 벡터 객체를 만들게 된다.

앞 단계에서는 각각의 문서를 완전히 병렬로 처리할 수 있지만(스파크에서는 처리 과정이 맵

함수들로 구성된다는 의미다), 역문서 빈도를 계산할 때는 모든 문서를 대상으로 집계하는 과

3 옮긴이_ 복수형이나 과거 분사 등

149Chapter 6 - 숨은 의미 분석으로 위키백과 이해하기

정이 필요하다. 몇몇 유용한 범용 자연어 처리 도구와 위키백과에 특화된 추출 도구들을 사용

하면 도움이 된다.

6.2 데이터 구하기

위키백과는 문서를 덤프하는 기능을 제공한다. 다음과 같이 http://dumps.wikimedia.org/

enwiki에 들어 있는 문서들을 하나의 커다란 XML 파일 형태로 덤프하여 HDFS에 저장한다.

$ curl -s -L http://dumps.wikimedia.org/enwiki/20150304/\

$ enwiki-20150304-pages-articles-multistream.xml.bz2 \

$ | bzip2 -cd \

$ | hadoop fs -put - /user/ds/wikidump.xml

이 작업은 시간이 좀 걸릴 것이다.

6.3 파싱하여 데이터 준비하기

덤프 파일의 앞 부분은 다음과 같은 모양이다.

<page>

<title>Anarchism</title>

<ns>0</ns>

<id>12</id>

<revision>

<id>584215651</id>

<parentid>584213644</parentid>

<timestamp>2013-12-02T15:14:01Z</timestamp>

<contributor>

<username>AnomieBOT</username>

<id>7611264</id>

</contributor>

<comment>Rescuing orphaned refs (&quot;autogenerated1&quot; from rev

584155010; &quot;bbc&quot; from rev 584155010)</comment>

<text xml:space="preserve">{{Redirect|Anarchist|the fictional character|

150 9가지 사례로 익히는 고급 스파크 분석

Anarchist (comics)}}

{{Redirect|Anarchists}}

{{pp-move-indef}}

{{Anarchism sidebar}}

'''Anarchism''' is a [[political philosophy]] that advocates [[stateless society|

stateless societies]] often defined as [[self-governance|self-governed]] voluntary

institutions,&lt;ref&gt;&quot;ANARCHISM, a social philosophy that rejects

authoritarian government and maintains that voluntary institutions are best suited

to express man's natural social tendencies.&quot; George Woodcock.

&quot;Anarchism&quot; at The Encyclopedia of Philosophy&lt;/ref&gt;&lt;ref&gt;

&quot;In a society developed on these lines, the voluntary associations which

already now begin to cover all the fields of human activity would take a still

greater extension so as to substitute

...

스파크 셸을 시작해보자. 이 장에서는 작업을 좀 더 쉽게 만들어주는 몇몇 라이브러리를 활용

할 것이다. 의존성 있는 라이브러리를 모두 포함한 JAR 파일을 빌드해주는 메이븐 프로젝트를

깃허브 저장소에 올려두었다.

$ cd lsa/

$ mvn package

$ spark-shell --jars target/ch06-lsa-1.0.0.jar

아파치 머하웃Mahout 프로젝트로부터 XmlInputFormat 클래스의 손을 빌려 위키백과의 커다란

덤프 파일을 여러 문서로 쪼갤 수 있다. 다음과 같이 RDD를 만들어보자.

import com.cloudera.datascience.common.XmlInputFormat

import org.apache.hadoop.conf.Configuration

import org.apache.hadoop.io._

val path = "hdfs:///user/ds/wikidump.xml"

@transient val conf = new Configuration()

conf.set(XmlInputFormat.START_TAG_KEY, "<page>")

conf.set(XmlInputFormat.END_TAG_KEY, "</page>")

val kvs = sc.newAPIHadoopFile(path, classOf[XmlInputFormat],

classOf[LongWritable], classOf[Text], conf)

val rawXmls = kvs.map(p => p._2.toString)

173Chapter 7 - 그래프엑스로 동시발생 네트워크 분석하기

세상은 참 좁다. 계속해서 교차하고 있다.

-데이비드 미첼

데이터 과학자들은 다양한 분야, 다양한 깊이의 학문적 배경을 지니고 있다. 비록 많은 사람이

컴퓨터 과학, 수학, 물리학을 공부했겠지만, 신경과학, 사회학, 정치학 등을 전공한 사람도 있

다. 후자의 분야는 뇌, 사람, 정치기구 등 컴퓨터와 관련 없는 분야를 연구하고 학과생에게 프

로그래밍을 가르치진 않지만, 데이터 과학자로 성장하는 데 발판이 되는 중요한 특징 두 가지

를 지니고 있다.

첫째, 이들 분야는 대상들(신경세포든 개인이든 국가든 상관없이) 사이의 ‘관계’를 이해하고

그 관계가 대상의 행동에 어떻게 영향을 주는지를 이해하는 데 초점을 맞추고 있다. 둘째, 과거

10년간의 폭발적인 데이터 증가로 대상들의 관계와 관련한 거대한 규모의 정보에 접근할 수

있게 되었고, 이 데이터셋을 구하고 관리하기 위한 새로운 기술을 개발해야 했다.

각 영역의 과학자들이 서로, 그리고 데이터 과학자들과 협업하기 시작하면서 그들이 관계를 분

석하면서 사용하던 많은 기술을 다른 분야에도 적용할 수 있음을 깨달았다. 그리하여 네트워크

과학network science 분야가 탄생했다. 네트워크 과학에는 대상(꼭짓점vertex, node ) 사이의 관계(변

edge, link, line )를 연구하는 수학 분야인 그래프 이론graph theory에서 탄생한 도구들이 사용된다. 또한,

그래프 이론은 자료구조부터 컴퓨터 구조, 그리고 인터넷과 같은 네트워크 설계까지 컴퓨터 과

학에서 연구하는 모든 것에 널리 사용된다.

그래프엑스로 동시발생 네트워크 분석하기

CHAPTER 7

조시 윌스

174 9가지 사례로 익히는 고급 스파크 분석

그래프 이론과 네트워크 과학은 비즈니스 분야에도 큰 영향을 주었다. 대부분의 인터넷 회사

가 영향력 있는 관계 네트워크를 구축하고 분석하는 데 경쟁자들보다 우위를 점하는 식으로 회

사의 가치를 높여 왔다. 아마존과 넷플릭스의 추천 알고리즘은 각 회사가 만들고 통제해온 사

용자-제품구매(아마존), 사용자-감상평(넷플릭스) 네트워크에 의존한다. 페이스북과 링크

드인은 콘텐츠의 피드를 구성하고, 광고를 삽입하고, 새로운 관계를 맺어주기 위해서 사용자를

분석하여 사람 사이의 관계 그래프를 만든다. 이 중에서도 가장 유명한 사례로는 구글의 웹 검

색 알고리즘인 페이지랭크PageRank를 꼽을 수 있을 것이다.

이들 네트워크 중심 회사에 필요했던 엄청난 양의 계산과 분석 수요는 맵리듀스와 같은 분산

처리 프레임워크가 만들어지는 계기가 되었을 뿐 아니라, 계속해서 늘어만 가는 데이터를 분

석하여 가치를 만들어내는 도구를 사용할 줄 아는 데이터 과학자들을 고용하는 계기가 되었다.

맵리듀스의 초기 활용사례 중 하나가 페이지랭크의 핵심 공식을 풀어내는 확장 가능하고 신뢰

성 있는 방법을 구축하는 것이었다. 시간이 지나면서 그래프가 점점 커지자 데이터 과학자들

은 분석 속도를 더 높여야 한다는 압박에 시달렸다. 그 결과 구글의 프레겔Pregel, 야후의 지라프

Giraph, 카네기멜론 대학교의 그래프랩GraphLab과 같이 그래프를 병렬로 처리하는 새로운 프레임

워크가 개발되었다. 이 프레임워크들은 결함 허용, 인메모리, 반복 가능, 그래프 중심의 분석을

지원했고, 특정 유형의 그래프 연산에서는 데이터 중심의 병렬 처리 프레임워크인 맵리듀스에

비해서 자릿수가 다를 정도로 더 빠른 모습을 보여주었다.

이 장에서는 그래프엑스GraphX라는 스파크 라이브러리를 소개하려 한다. 이 라이브러리는 프레

겔, 지라프, 그래프랩에서 처리하던 그래프 중심 병렬 작업의 많은 부분을 스파크가 처리할 수

있도록 확장한다. 비록 모든 연산을 전용 그래프 프레임워크만큼 빠르게 수행할 수는 없겠지

만, 그래프엑스가 스파크 라이브러리라는 사실은 일반적인 데이터 분석 워크플로우에서 언제

든지 그래프(혹은 네트워크) 중심 데이터셋도 분석할 수 있음을 뜻한다. 즉, 지금까지 사용해

온 익숙한 스파크 추상화에 병렬 그래프 처리 프로그래밍을 더할 수 있다.

7.1 네트워크 분석 사례: MEDLINE의 인용 색인

온라인 의학 문헌 분석 및 검색 시스템인 MEDLINEMedical Literature Analysis and Retrieval System Online은

생명과학과 의학 저널들에서 발행한 학술 논문의 데이터베이스로, 미국 국립 보건원의 한 부

175Chapter 7 - 그래프엑스로 동시발생 네트워크 분석하기

서인 미국 국립 의학도서관에서 관리하고 제공한다. 수천 개의 저널에 실린 기사들을 기록하는

인용 색인은 1879년부터 시작했고, 1971년부터 의과 대학에 온라인으로 제공했으며, 1996년

부터는 웹을 통해서 일반에 제공하고 있다. 주 데이터베이스는 1950년대 이후의 2천만 건이

넘는 기사를 담고 있으며, 공휴일을 제외한 매일 갱신한다.

엄청난 인용 데이터의 크기와 빈번한 갱신 주기 때문에 연구 커뮤니티에서는 MeSHMedical subject

Headings (의학 주제 제목)이라는 포괄적인 의미 태그를 개발하여 색인에 포함된 모든 인용에 적

용했다. 이들 태그는 문헌 검토를 위해서 문서 사이의 관계를 조사할 때 사용할 수 있는 중요한

프레임워크를 제공하며, 데이터 기반 제품을 만드는 기초 자료로 사용할 수도 있다. 2001년에

PubGene사는 생의학 텍스트 마이닝을 활용한 첫 번째 상용 제품을 선보였다. 이 제품은 사

용자가 관련 문서들을 연결하는 MeSH 키워드의 그래프를 탐색하게 해주는 검색 엔진이었다.

이 장에서는 스칼라, 스파크, 그래프엑스를 사용하여 MEDLINE 데이터 중 최근에 발행된 인

용 데이터 일부에 대한 MeSH 네트워크를 만들고 변환하고 분석해볼 것이다. 여기서 수행할

네트워크 분석은 2014년 카스트린Kastrin 등이 쓴 <함께 사용된 MeSH 키워드 네트워크의 거대

한 구조: 거시적 특징들의 정적 분석Large-Scale Structure of a Network of Co-Occurring MeSH Terms: Statistical Analysis

of Macroscopic Properties>에서 아이디어를 가져온 것이다. 다만, 이 논문에서 사용한 인용 데이터와는

다른 부분집합을 사용할 것이며, 이 논문에서는 R과 C++를 사용했지만 여기서는 그래프엑스

로 분석할 것이다.

우리의 목적은 인용 그래프의 모양과 특성에 대한 감을 잡는 것이다. 우리는 데이터셋의 완전

한 조망을 얻기 위해서 여러 각도에서 공략할 것이다. 먼저 핵심 주제들, 그리고 이 주제들이

동시에 발생하는 정도를 살펴보는, 즉 그래프엑스를 사용할 필요가 없는 간단한 분석으로 시

작할 것이다. 그다음으로는 연결 성분connected component를 찾을 것이다. 이를 통해서 “특정 주제에

서 다른 주제로 색인 경로를 따라갈 수 있을 것인가?”와 같은 질문에 대답할 수 있다. 그 후에,

그래프의 차수 분포degree distribution를 살펴 특정 주제의 관련성이 얼마나 넓게 걸쳐 있는지에 대한

감을 잡고, 다른 주제들과 가장 많이 연결된 주제를 찾아볼 것이다. 마지막으로 군집계수clustering

coefficient와 평균 경로 길이average path length를 구하는, 두 가지의 조금 전문적인 그래프 통계량을 계산

할 것이다. 이들 통계량은 여러모로 사용되겠지만, 여기서는 인용 그래프가 웹이나 페이스북의

사회 관계망 같은 우리 주변의 현실 세상 그래프와 얼마나 비슷한가를 이해하게끔 해줄 것이다.

176 9가지 사례로 익히는 고급 스파크 분석

7.2 데이터 구하기

미국 국립 보건원의 FTP 서버에서 인용 색인 데이터의 표본을 얻을 수 있다.

$ mkdir medline_data

$ cd medline_data

$ wget ftp://ftp.nlm.nih.gov/nlmdata/sample/medline/*.gz

옮긴이_ 번역하는 시점에 앞의 방법으로 얻게 되는 데이터는 2016년의 표본이며, 독자가 읽는 시점에는 더

최근의 표본으로 바껴 있을지도 모른다. 이 때문에 이 책의 예제가 보여주는 결과와 여러분이 실습하면서 접

하게 될 결과는 다소 상이할 수 있다. 번역하는 입장에서는 조금 난감한 상황이지만, 저자의 논지를 따라가기

위하여 책에서 소개하는 예제와 그 결과를 그대로 소개하기로 했다. 역자 또한 2014년 데이터로 테스트 할

수 없었다는 점과, 결과가 다르다고 해서 대세에 큰 영향을 주지 않는다는 것을 밝혀 둔다.

HDFS에 올리기 전에 인용 데이터의 압축을 풀고 검사를 하자.

$ gunzip *.gz

$ ls -ltr

...

total 843232

-rw-r--r-- 1 spark spark 162130087 Dec 17 2013 medsamp2014h.xml

-rw-r--r-- 1 spark spark 146357238 Dec 17 2013 medsamp2014g.xml

-rw-r--r-- 1 spark spark 132427298 Dec 17 2013 medsamp2014f.xml

-rw-r--r-- 1 spark spark 102401546 Dec 17 2013 medsamp2014e.xml

-rw-r--r-- 1 spark spark 102715615 Dec 17 2013 medsamp2014d.xml

-rw-r--r-- 1 spark spark 89355057 Dec 17 2013 medsamp2014c.xml

-rw-r--r-- 1 spark spark 69209079 Dec 17 2013 medsamp2014b.xml

-rw-r--r-- 1 spark spark 58856903 Dec 17 2013 medsamp2014a.xml

압축을 풀면 총 600MB의 XML 파일들이 나온다. 표본 파일의 각 엔트리는 MedlineCitation

레코드로, 저널 이름, 권호issue, 출간일, 저자명, 초록abstract, 해당 기사와 관련된 MeSH 키워

드들 등, 생의학 저널에 기고된 기사와 관련된 정보가 들어 있다. 각 MeSH 키워드에는 그

키워드가 나타내는 개념이 그 기사의 핵심 주제인지를 알려주는 속성도 포함된다. 그러면

medsamp2014a.xml에 포함된 첫 번째 인용 레코드를 살펴보자.

177Chapter 7 - 그래프엑스로 동시발생 네트워크 분석하기

<MedlineCitation Owner="PIP" Status="MEDLINE">

<PMID Version="1">12255379</PMID>

<DateCreated>

<Year>1980</Year>

<Month>01</Month>

<Day>03</Day>

</DateCreated>

...

<MeshHeadingList>

...

<MeshHeading>

<DescriptorName MajorTopicYN="N">Intelligence</DescriptorName>

</MeshHeading>

<MeshHeading>

<DescriptorName MajorTopicYN="Y">Maternal-Fetal Exchange</DescriptorName>

</MeshHeading>

...

</MeshHeadingList>

...

</MedlineCitation>

6장에서 다루었던 위키백과 문서 관련 숨은 의미 분석(LSA )에서는 주로 XML의 각 레코드에

담긴 구조화되지 않은 기사 텍스트에 관심을 두었다. 하지만 이번 장의 동시발생 분석에서는

XML의 구조를 직접 파싱하여 <DesciptorName> 태그에 담긴 값을 꺼내려 한다. 마침, 스칼라

에는 XML 문서를 파싱하고 질의하기 위한 scala-xml이라는 훌륭한 라이브러리가 있어서 이

작업을 쉽게 처리할 수 있다.

인용 데이터를 HDFS에 올리는 것부터 시작해보자.

$ hadoop fs -mkdir medline

$ hadoop fs -put *.xml medline

이제 스파크 셸을 시작할 준비가 되었다. 6장에서 언급한 XML 데이터 파싱 코드

(XmlInputFormat 클래스)를 이 장에서도 사용한다. 이 코드를 컴파일하고 JAR 파일로 만들

어 사용할 것이다. 다음과 같이 깃 저장소에서 common/ 디렉터리로 이동한 다음, 메이븐을 사

용해 빌드하자.

178 9가지 사례로 익히는 고급 스파크 분석

$ cd common/

$ mvn package

$ spark-shell --jars target/common-1.0.0.jar

XML 형식의 MEDLINE 데이터를 셸에 읽어 들이는 함수를 만들어보자.

import com.cloudera.datascience.common.XmlInputFormat

import org.apache.spark.SparkContext

import org.apache.hadoop.io.{Text, LongWritable}

import org.apache.hadoop.conf.Configuration

def loadMedline(sc: SparkContext, path: String) = {

@transient val conf = new Configuration()

conf.set(XmlInputFormat.START_TAG_KEY, "<MedlineCitation ")

conf.set(XmlInputFormat.END_TAG_KEY, "</MedlineCitation>")

val in = sc.newAPIHadoopFile(path, classOf[XmlInputFormat],

classOf[LongWritable], classOf[Text], conf)

in.map(line => line._2.toString)

}

val medline_raw = loadMedline(sc, "medline")

START_TAG_KEY 설정 파라미터의 값을 MedilineCitation 시작 태그의 앞 부분(“</

MedilineCitation”)으로 설정했다. 왜냐하면 이 태그의 구체적인 속성 값은 레코드마다 다

를 수 있기 때문이다. 따라서 XmlInputFormat은 이러한 서로 다른 속성들을 포함한 레코드를

반환할 것이다.

7.3 스칼라 XML 라이브러리로 XML 문서 파싱하기

스칼라는 XML과 관련한 흥미로운 이력을 가지고 있다. 버전 1.2 이후로 스칼라는 XML을 기

본 자료형으로 다룬다. 그런 이유로 다음 코드도 문법적으로 올바르다.

import scala.xml._

val cit = <MedlineCitation>data</MedlineCitation>

209Chapter 8 - 뉴욕 택시 운행 데이터로 위치 및 시간 데이터 분석하기

시간과 공간만큼 내게 혼란을 주는 것은 없다.

그러나 시간과 공간만큼 나를 괴롭히지 않는 대상도 없다.

왜냐하면 나는 그 주제를 한 번도 생각해 본 적이 없기 때문이다.

-찰스 램

뉴욕은 노란 택시로 유명해서, 노점상에서 핫도그를 사 먹거나 엘리베이터를 타고 엠파이어 스

테이트 빌딩 꼭대기까지 올라가보는 일과 마찬가지로 노란 택시 타보기가 뉴욕 관광의 일부가

되었다.

뉴욕 주민은 러시아워나 우천 시와 같은 특별한 상황에서 택시를 잡을 때, 언제 혹은 어디가 좋

은지와 같은 수많은 (입증되지 않은 경험에 근거한) 정보를 가지고 있다. 하지만 모든 사람이

오후 4~5시와 교대시간만큼은 그냥 지하철을 타라고 이구동성으로 이야기한다. 이 시간에 노

란 택시들은 주로 퀸스에 위치한 교대 장소로 돌아가 운전기사를 교대하는데, 늦게 돌아오는

운전기사에게는 벌금이 부과된다.

2014년 3월, 뉴욕 택시 리무진 위원회는 영업 중인 택시의 수와 손님을 태운 택시의 비율을

시간대별로 정리한 인포그래픽을 트위터 계정 @nyctaxi (https://twitter.com/nyctaxi )로 공

유했다. 당연하게도 오후 4시에서 6시 사이에 영업 중인 택시의 수는 눈에 띌 만큼 적었고, 또

2/3에 해당하는 택시가 손님을 태우고 있었다.

뉴욕 택시 운행 데이터로 위치 및 시간 데이터 분석하기

CHAPTER 8

조시 윌스

210 9가지 사례로 익히는 고급 스파크 분석

이 트위터를 자칭 도시 계획 전문가이자 지도 제작자이자 데이터 광인 크리스 홍Chris Whong이 주

목했다. 그는 인포그래픽 제작에 사용한 데이터를 공개할 수 있는지 알려달라고 @nyctaxi 계

정으로 트윗을 보냈고, 택시 위원회는 정보공개법에 따른 공식 요청서와 데이터를 담아 갈 하

드디스크만 제출하면 된다고 대답했다. 요청서를 작성하고 500GB의 하드디스크 2개를 구입

한 이틀 후, 크리스는 2013년 1월 1일부터 12월 31일까지의 모든 택시 영업 정보를 손에 쥐

었다. 여기서 그치지 않고, 그는 모든 택시 승객 데이터를 인터넷에 올렸고, 이 정보는 뉴욕의

승객 수송과 관련한 멋진 시각화 자료들을 만드는 데 사용되었다.

택시의 경제학을 이해하는 데 중요한 통계량 하나는 영업시간과 손님을 태운 시간의 비율인 이

용률이다. 승객의 목적지는 이용률에 영향을 주는 요소다. 예를 들어 한낮에 유니언 광장 근처

에서 손님을 내린 택시는 1~2분 안에 바로 다음 승객을 태운 반면, 새벽 2시에 스태튼 섬에서

손님을 내린 택시는 다음 승객을 찾기 위해서 맨해튼까지 돌아와야 했다. 이러한 영향을 수치

화하여 택시에 다음 승객이 탈 때까지의 평균 시간을 승객이 내린 지역의 함수로 만들어내고자

한다. 승객이 내린 지역은 맨해튼, 브루클린, 퀸스, 브롱크스, 스태튼 섬, 기타(예를 들어 뉴어

크Newark 국제공항과 같은 뉴욕 바깥 지역)가 될 것이다.

이를 분석하려면 두 종류의 데이터를 다뤄야 한다. 하나는 날짜와 시간 같은 시간 데이터이고,

다른 하나는 경도와 위도 및 지역 경계와 같은 위치 데이터다. 이 장에서는 이런 데이터를 다루

는 데 스칼라와 스파크를 어떻게 사용해야 하는지를 설명할 것이다.

8.1 데이터 얻기

이번 분석은 2013년 1월의 요금 데이터만 다룰 것인데, 압축을 풀면 2.5GB 정도 된다.

2013년의 월별 데이터는 http://www.andresmh.com/nyctaxitrips/에서 내려받을 수 있다. 여

러분이 사용할 수 있는 스파크 클러스터가 충분히 크다면 뒤에서 수행할 분석을 2013년 전체

데이터를 가지고도 해볼 수 있을 것이다. 당장은 클라이언트 노드에 작업 디렉터리를 만들고

요금 데이터의 구조를 살펴보도록 하자.

$ mkdir taxidata

$ cd taxidata

211Chapter 8 - 뉴욕 택시 운행 데이터로 위치 및 시간 데이터 분석하기

$ wget https://nyctaxitrips.blob.core.windows.net/data/trip_data_1.csv.zip

$ unzip trip_data_1.csv.zip

$ head -n 10 trip_data_1.csv

이 파일은 헤더를 제외하면 한 줄에 택시 운행 한 건씩 CSV 형식으로 기록되어 있다. 각 운행

정보는 택시 정보(해시된 메달리온 번호1 )와 운전자 정보(해시된 핵 라이선스hack license, 택시면허),

운행 시작 시각과 종료 시각과 같은 시간 정보, 그리고 승객의 탑승 지점과 하차 지점의 경도·

위도 정보 등의 속성을 가진다.

8.2 스파크에서 시간과 지리 데이터 다루기

자바 플랫폼의 최고 장점 하나는 수년간 개발되어온 방대한 양의 코드다. 어떤 자료형이나 알

고리즘이든 누군가가 이미 자바 라이브러리로 개발해두었을 가능성이 크며, 그 라이브러리의

오픈 소스 버전이 존재하여 내려받을 수 있고 무료로 사용할 수 있을 가능성이 크다.

물론, 무료 라이브러리가 있다는 이유만으로 어떤 문제를 푸는 데 그 라이브러리에 의존할 필

요는 없다. 오픈 소스 프로젝트는 품질, 버그 수정, 새로운 기능과 관련한 개발 상황, API의 사

용 편의성, 그리고 잘 작성된 문서와 학습 자료의 유무와 같은 관점에서 편차가 심하다.

우리의 라이브러리 선정 과정은 개발자가 애플리케이션 개발에 필요한 라이브러리를 선정하는

과정과 약간 다르다. 우리는 대화형 데이터 분석에 사용하기 좋고 분산 애플리케이션에서 쉽게

사용할 수 있는 라이브러리를 원한다. 특히 RDD에서 다룰 주요 자료형이 Serializable 인터

페이스를 구현해야 하고 Kryo 같은 라이브러리를 사용해서 쉽게 직렬화할 수 있기를 원한다.

거기다가 대화형 분석에 사용하는 라이브러리는 가능한 한 다른 외부 라이브러리에는 의존하

지 않기를 바랄 것이다. 메이븐이나 SBT와 같은 도구는 개발자가 애플리케이션을 빌드할 때

복잡한 의존성 문제를 처리해주지만, 대화형 데이터 분석의 경우에 필요한 모든 코드를 JAR 파

일에 그냥 다 담아버리고 스파크 셸에서 로드하여 그대로 분석을 시작하는 것이 훨씬 좋다. 게

다가 라이브러리가 의존성을 다수 갖게 되면 스파크 자체가 사용하는 다른 라이브러리들과 버

전 충돌이 발생할 수도 있다. 이 상황이 심해지면 소위 ‘JAR 지옥’이라 부를만한 진단하기 어려

1 옮긴이_ 메달리온은 뉴욕 노란 택시의 전면에 장착하는 휘장을 말하고, 메달리온에는 번호가 부여되어 있다.

212 9가지 사례로 익히는 고급 스파크 분석

운 오류 상황에 빠지게 된다.

마지막으로 추상 팩토리 패턴이나 방문자 패턴과 같은 디자인 패턴을 많이 사용하지 않는, 비

교적 간단하고 풍부한 API를 선호한다. 디자인 패턴이 애플리케이션 개발자에게는 유용하겠지

만, 분석과 관련 없는 부분에서 코드를 훨씬 더 복잡하게 만드는 경향이 있다. 그나마 나은 것

은 많은 자바 라이브러리에 스칼라 래퍼가 있어, 라이브러리를 사용하는 데 필요한 장식 코드

를 줄이고 스칼라의 장점을 살리고 있다.

8.3 JodaTime과 NScalaTime을 이용한 시간 데이터

시간 데이터라면 자바의 Date 클래스와 Calendar 클래스를 사용할 수 있다. 하지만 사용해본

사람이라면 누구나 이 클래스들은 사용하기 어려우며 간단한 연산에도 많은 양의 장식 코드가

필요하다는 점을 알고 있다. 그래서 최근 몇 년 사이 시간 데이터를 다루는 자바 라이브러리로

JodaTime이 선택되어 왔다.

스칼라에서 JodaTime을 사용할 수 있게 해주는 NScalaTime 래퍼 라이브러리가 준비되어

있다. NScalaTime은 몇 가지 추가적인 문법적 편의성을 제공하며, 다음과 같이 한 줄만 임포

트하면 이 모든 기능을 사용할 수 있다.

import com.github.nscala_time.time.Imports._

JodaTime과 NScalaTime은 DateTime 클래스를 중심으로 돌아간다. DateTime 객체는 자

바 String 객체처럼 값을 바꿀 수 없는 불변 객체이고(일반 자바 API에서 Calendar나 Date

의 객체와는 다르다) 시간 데이터 계산에 쓰이는 함수를 몇 개 제공한다. 아래 예제에서 dt1은

2014년 9월 4일 오전 9시를, dt2는 2014년 10월 31일 오후 3시를 나타낸다.

val dt1 = new DateTime(2014, 9, 4, 9, 0)

dt1: org.joda.time.DateTime = 2014-09-04T09:00:00.000-07:00

dt1.dayOfYear.get

res60: Int = 247

val dt2 = new DateTime(2014, 10, 31, 15, 0)

213Chapter 8 - 뉴욕 택시 운행 데이터로 위치 및 시간 데이터 분석하기

dt2: org.joda.time.DateTime = 2014-10-31T15:00:00.000-07:00

dt1 < dt2

res61: Boolean = true

val dt3 = dt1 + 60.days

dt3: org.joda.time.DateTime = 2014-11-03T09:00:00.000-08:00

dt3 > dt2

res62: Boolean = true

데이터 분석에서는 문자열로 표현된 시간을 우리가 계산할 수 있는 DateTime 객체로 변환

해야 할 경우가 흔하다. 간단하게는 다양한 형식의 시간 표현을 파싱하는 데 유용한 자바의

SimpleDateFormat을 사용하는 방법이 있다. 아래 코드는 택시 데이터셋에서 사용한 형식의

시간 데이터를 파싱한다.

import java.text.SimpleDateFormat

val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

val date = format.parse("2014-10-12 10:30:44")

val datetime = new DateTime(date)

DateTime 객체를 파싱하고 나면, 그다음에는 보통 두 시각이 몇 시, 몇 분, 몇 초만큼 차이 나

는지를 알아보는 시간 간격 연산을 해보길 원한다. JodaTime에서는 Duration 클래스로 일정

기간을 나타낸다. 이 클래스는 다음과 같이 두 개의 DateTime 인스턴스로부터 만들 수 있다.

val d = new Duration(dt1, dt2)

d.getMillis

d.getStandardHours

d.getStandardDays

JodaTime은 시간대time zone, 일광 절약 시간제Daylight Saving Time, 서머 타임와 같은 귀찮고 세밀한 부

분까지 모두 처리해주므로 걱정 거리가 한결 줄어든다.

214 9가지 사례로 익히는 고급 스파크 분석

8.4 Esri Geometry API와 Spray를 사용한 지리 데이터

JVM에서 시간 데이터를 다루는 일은 쉽다. 그냥 JodaTime을 쓰면 되며, 만약 NScalaTime

과 같은 래퍼를 사용하는 쪽이 이해하기 쉽다면 그렇게 할 수도 있다. 지리 데이터쪽의 답은 그

렇게 간단하지 않다. 다양한 라이브러리와 도구가 기능, 개발 상태, 성숙도에서 차이를 보여서

모든 상황에 압도적으로 널리 사용되는 자바 라이브러리는 없다.

가장 중요한 질문은 “어떤 유형의 지리 데이터인가?”다. 주요한 두 유형으로 벡터vector와 래스

터raster가 있으며, 각각은 지원하는 도구도 다르다. 우리 예제인 택시 운행 기록에는 경도와 위

도라는 위치 값이 있고, 뉴욕의 여러 지역 경계를 표현하는 벡터 데이터도 있다. 이 데이터는

GeoJSON 형태로 저장되어 있으므로 우리는 GeoJSON 데이터를 파싱하여 경도와 위도를 알

아내고, 그 값이 나타나는 위치가 특정 지역의 경계를 의미하는 다각형 내부에 있는지를 알아

내는 것 같은 위치 관계를 다룰 수 있는 라이브러리가 필요하다.

안타깝지만, 우리의 바람에 정확히 들어맞는 오픈 소스 라이브러리는 없다. GeoJSON 데이

터를 자바 객체로 변환하는 GeoJSON 파서 라이브러리가 있으나, 결과로 생성된 객체의 공간

관계를 분석해줄 관련 지리 라이브러리가 없다. GeoTools 프로젝트라는 것도 있지만, 다수의

컴포넌트와 의존성을 가진다. 이런 라이브러리가 바로 스파크 셸에서 사용할 라이브러리를 선

택할 때 피하려고 하는 것이다. 마지막으로 자바용 Esri Geometry API가 있는데, 의존성이

거의 없고 공간 관계도 분석할 수 있다. 하지만 GeoJSON 표준 중 일부 형태만 파싱할 수 있

기 때문에 몇 가지 데이터 전처리 없이는 우리가 내려받은 GeoJSON 데이터를 파싱할 수 없다.

적합한 분석 도구가 없다는 것은 데이터 분석가에게는 큰 난관이다. 그러나 우리는 데이터 과

학자다. 만약 도구의 한계로 문제를 해결하지 못한다면 새로운 도구를 만들면 된다. 여기서

는 JSON 데이터 파싱 기능을 지원하는 수많은 스칼라 프로젝트 중 하나를 이용하여 ‘Esri

Geometry API에서 처리할 수 없는 사례까지 포함한’ 모든 GeoJSON 데이터를 파싱할 수

있도록 기능을 추가할 것이다. 다음의 몇 개의 절에서 다룰 코드는 이 책의 깃허브 저장소

는 물론, 독립 라이브러리로 형태로도 깃허브에도 따로 공개하여(http://github.com/jwills/

geojson ) 다른 스칼라 지리 분석 프로젝트에도 사용할 수 있다.

235Chapter 9 - 몬테카를로 시뮬레이션으로 금융 리스크 추정하기

지질학을 이해하고 싶다면 지진을 공부하라.

경제학을 이해하고 싶다면 경기 침체를 공부하라.

-벤 버냉키

합리적인 상황에서 여러분은 얼만큼의 손실을 예상할 수 있는가? 이것이 최대손실예상액Value at

Risk (VaR )이라는 금융 통계량이 측정하고자 하는 양이다. VaR은 1987년 주식 시장 붕괴 직후

개발되어 금융 서비스 조직에서 광범위하게 사용하고 있다. 이 통계량은 금융 기관들이 추구하

는 신용 등급을 만족하기 위해 보유해야 하는 현금의 양을 정하는 데 도움을 준다. 즉, 자산 관

리에서 필수적인 역할을 한다. 일부 기관은 대규모 포트폴리오들의 리스크 특성을 더 광범위하

게 이해하기 위해 사용하고, 또 다른 일부는 즉각적인 결정들을 알리는 데 도움을 얻기 위해 거

래 실행 전에 이 값을 계산한다.

VaR 통계량을 추정하는 여러 정교한 방법들 대부분은 계산량이 매우 많은 방법인 임의 상황

에서의 시장 시뮬레이션에 의존한다. 그리고 이런 방법 뒤에는 몬테카를로 시뮬레이션Monte Carlo

simulation이라는 기술이 있다. 이 기술은 수천에서 수백만의 임의 시장 시나리오를 제기하고, 그

상황이 포트폴리오에 어떤 영향을 주는지 관찰한다. 몬테카를로 시뮬레이션은 자연스럽게 대

규모로 병렬화되기 때문에 스파크는 이를 위한 최적의 도구다. 스파크는 수천의 코어를 활용하

여 임의 실험을 수행하고 그 결과를 집계할 수 있다. 범용 데이터 변환 엔진인 스파크는 시뮬레

이션 관련 전처리와 후처리에도 능숙하다. 스파크는 원시 금융 데이터를 시뮬레이션 수행에 필

샌디 라이자

몬테카를로 시뮬레이션으로 금융 리스크 추정하기

CHAPTER 9

236 9가지 사례로 익히는 고급 스파크 분석

요한 모델 파라미터들로 변환하는 일뿐만 아니라 결과의 애드혹ad-hoc 분석도 지원한다. 스파크

의 간단한 프로그래밍 모델은 HPC 환경을 이용하는 전통적인 방법보다 개발 기간을 현저히

줄일 수 있다.

‘예상할 수 있는 손실의 양’을 좀 더 엄격하게 정의해보자. VaR은 단순한 투자 리스크 측정치이

고, 투자 포트폴리오가 특정 기간에 입을 수 있는 최대 손실의 합리적인 추정을 예측한다. VaR

통계량은 포트폴리오, 보유 기간, 유의 확률p-value, p값이라는 세 파라미터에 따라 값이 달라진다.

5%의 유의 확률로 보유 기간은 2주일 때의 VaR 통계량이 1백만 달러라면, 2주 동안 1백만 달

러 이상의 손실을 볼 확률이 5%라는 의미다.

조건부 최대손실예상액Conditional Value at Risk (CVaR )이라는 통계량 계산 방법도 논의할 것이다(기대

손실Expected Shortfall이라고도 한다). CVaR은 바젤 은행 감독 위원회가 VaR보다 더 나은 리스크

척도로 최근 제안했다. CVaR 통계량은 VaR 통계량처럼 3개의 파라미터를 가지나, 기대 손실

대신 컷오프 값을 고려한다. 5%의 q값q-value에 보유 기간은 2주일 때 CVaR 통계량이 5백만 달

러라면, 전체 시나리오 중 최악의 결과를 내는 5%의 시나리오들에서의 평균 손실이 5백만 달

러라는 의미다.

이번 장에서는 VaR 모델링을 다루며 여러 가지 개념, 방법, 패키지를 소개할 것이다. 구체적으

로는 커널 밀도 추정과 breeze-viz 패키지를 이용한 시각화, 다변량 정규분포에서의 표본추

출, 아파치 커먼즈 수학Apache Commons Math 패키지의 통계 함수들을 다룰 것이다.

9.1 금융 분야 전문 용어

이 장에서는 금융 분야에 특화된 용어들을 사용한다. 먼저 이들 용어를 간단히 정의해보자.

금융상품Instrument

거래 가능한 자산으로 채권, 대출, 옵션, 주식이 있다. 어떤 시점이든 금융상품은 판매할 수

있는 가격을 가진다고 간주한다.

포트폴리오Portfolio

금융 기관이 소유한 금융상품들의 모음

237Chapter 9 - 몬테카를로 시뮬레이션으로 금융 리스크 추정하기

수익Return

금융상품 또는 포트폴리오의 일정 기간의 가격 변화

손실Loss

마이너스 수익

지수Index

가상의 금융상품 포트폴리오. 예를 들어 나스닥 지수는 약 3,000개의 미국 혹은 국제 기업

들의 주식과 유사 금융상품을 포함한다.

시장 요인Market Factor

특정 시간에 재정 상황의 거시적 측면을 나타내는 지표로 사용될 수 있는 값. 예를 들어 미

국의 국내 총생산(GDP ) 또는 달러-유로 환율과 같은 지수 값이 있다. 이 책에서는 종종

시장 요인을 그냥 요인이라고 언급할 것이다.

9.2 VaR 계산 방법

지금까지 우리의 VaR 정의는 완벽하지 않았다. 이 통계량을 추정하려면 포트폴리오가 기능하

는 모델을 제안하고 이 포트폴리오의 수익에 대한 확률 분포를 선택해야 한다. 기관들은 VaR

을 계산하기 위해 다양한 방법을 쓰고 있지만, 이 모든 방법은 이어서 살펴볼 몇 가지 일반적인

방법의 범주에 속하는 경향이 있다.

9.2.1 분산-공분산 분산-공분산Variance-Covariance은 단연코 가장 간단하고 가장 계산량이 적은 방법이다. 분산-공분산

모델은 각 금융상품의 수익이 정규분포를 따른다고 가정하여 VaR 통계량을 해석적으로 추정

할 수 있게 한다.

238 9가지 사례로 익히는 고급 스파크 분석

9.2.2 역사적 시뮬레이션역사적 시뮬레이션Historical Simulation은 요약 통계에 의존하는 대신 역사적 데이터의 분포를 직접 이

용하여 리스크를 추정한다. 예를 들어 포트폴리오의 신뢰수준 95% VaR을 알아내기 위해 그

포트폴리오의 지난 100일 간의 성과를 보고 그중 5번째로 나쁜 날의 값으로 VaR 통계량 값을

추정할 수도 있다. 이 방법의 문제는 역사적 데이터가 그만큼 많이 쌓여 있지 않을 수 있고, 과

거 데이터는 새로 가정하는 시나리오들을 포함하지 못할 수 있다는 것이다. 포트폴리오를 구성

하는 금융상품들의 과거 이력에는 시장붕괴가 없을 수 있지만, 여컨대 우리는 시장붕괴 상황에

서 그 포트폴리오에 무슨 일이 일어날지 모델링하고 싶을 수 있다. 역사적 시뮬레이션을 이러

한 상황에 덜 민감하게 만들어주는 기술로 데이터 속에 쇼크shock를 넣는 등의 기법이 있지만 여

기서는 다루지 않기로 한다.

9.2.3 몬테카를로 시뮬레이션이 장의 나머지에서 중점적으로 다룰 몬테카를로 시뮬레이션은 포트폴리오를 임의 상황에서 시

뮬레이션함으로써 이전 방법들에서의 가정들을 약화시키려고 노력한다. 확률 분포의 닫힌 형태

closed-form를 해석적으로 유도할 수 없다면 보통 이 분포에 영향을 주는 더 간단한 무작위 변수를

반복해서 표본추출하여, 이렇게 추출한 변수들이 전체에 어떤 영향을 주는지 관찰하여 확률 밀

도 함수probability density function (PDF )를 추정할 수 있다. 가장 일반적인 형태에서 이 방법은 다음과

같다.

● 시장 상황들과 각 금융상품의 수익 사이의 관계를 정의한다. 이 관계는 역사적 데이터에 적합된fitted 모델의 형

태를 가진다.

● 간단하게 표본추출하기 위해 시장 상황들에 대한 분포들을 정의한다. 이들 분포들은 역사적 데이터에 적합된

다.

● 임의 시장 상황들로 구성된 실험trial들을 제기한다.

● 각 실험에서 전체 포트폴리오 손실을 계산하고 이들 손실에 대한 경험적 분포empirical distribution를 정의한다. 이는

만약 우리가 실험을 100번 실행하고 유의수준 5% VaR을 추정하길 원한다면 손실이 5번째로 큰 실험으로

부터 얻어진 손실값을 추정치로 선택할 것임을 뜻한다. 5% CVaR을 계산하려면 최악의 결과를 내는 실험 5개의 평균 손실을 구할 것이다.

239Chapter 9 - 몬테카를로 시뮬레이션으로 금융 리스크 추정하기

물론, 몬테카를로 방법 역시 완벽한 건 아니다. 실험 조건을 생성하고 그 조건으로부터 금융상

품 성과를 추정하는 모델들은 반드시 단순화한 가정을 해야 하며, 결과로 얻은 분포는 모델들

과 역사적 데이터가 들어간 분포보다 더 정확할 수는 없을 것이다.

9.3 우리의 모델

몬테카를로 리스크 모델은 일반적으로 각 금융상품의 수익을 일련의 시장 요인 항term으로 표현

한다. 공통적인 시장 요인은 S&P 500, 미국 GDP, 환율 같은 지수값일 것이다. 그 후에 이런

시장 상황에서 각 금융상품의 수익을 예측하는 모델이 필요하다. 우리 시뮬레이션에서는 간단

한 선형 모델을 사용할 것이다. 이전에 내린 수익의 정의에 따라 요인 수익은 특정 기간 동안 시

장 요인 값의 변화다. 예를 들어 특정 기간에 S&P 500 지수가 2,000에서 2,100으로 움직였다

면 요인 수익은 100일 것이다. 우리는 요인 수익들의 간단한 변형으로부터 일련의 특징을 얻을

것이다. 즉, 어떤 함수 φ를 적용해서 실험 t용의 시장 요인 벡터 m t를 변형하여 길이가 다를

수 있는 특징 벡터 f t를 만들려는 것이다.

f mt t= ( )ϕ

금융상품별로 각 특징에 가중치를 부여하는 모델을 학습할 것이다. 실험 t에서 금융상품 i의

수익인 r i t를 계산하기 위해 우리는 금융상품에 대한 절편intercept term인 c i, 특징 j의 금융상품 i

에 대한 회귀 가중치regression weight인 w ij, 그리고 실험 t에서 무작위로 생성된 특징 j의 값인 f t j

를 사용할 것이다.

r c w fit ij

wi

ij tj= + ×=∑1

즉, 각 금융상품의 수익은 시장 요인 특징들의 수익에 해당 금융상품에 대한 특징들의 가중치

를 곱한 값의 합이다. 우리는 역사적 데이터를 활용하여 금융상품별 선형 모형을 적합시킬 수

있다(선형 회귀분석을 한다고도 한다). 만약 VaR 계산에서 보유 기간이 2주라면 회귀분석은

과거 이력에서의 모든 ‘겹쳐지는’ 2주 간격 각각을 레이블링된 포인트로 취급한다. 여기서 ‘겹쳐

240 9가지 사례로 익히는 고급 스파크 분석

지는’의 의미는, 예컨대 1~14일과 2~15일이 각각 하나의 2주 간격이 된다는 말이다.

또한, 우리가 더 복잡한 모델을 선택할 수도 있다는 점을 언급해두고자 한다. 예를 들어 모델이

꼭 선형일 필요는 없다. 모델은 회귀 트리여도 되고 명시적으로 특정 도메인 지식을 포함할 수

있다.

시장 요인들로부터 금융상품 손실을 계산할 수 있는 모델이 생겼으니, 이제 시장 요인들의 움

직임을 시뮬레이션하는 절차가 필요하다. 간단히 각 시장 요인 수익은 정규분포를 따른다고 가

정할 수 있다. 시장 요인들은 흔히 서로 연관되어 있다는 사실(나스닥 지수가 내려가면 다우

지수도 악화될 가능성이 높다)을 반영하기 위해 우리는 비대각 공분산 행렬non-diagonal covariance matrix

을 가지는 다변량 정규분포를 사용할 수 있다.

mt ( , )µ Σ

여기서 μ는 요인들의 수익에 대한 경험적 평균empirical mean 벡터이고, Σ는 요인들의 수익에 대한

경험적 공분산 행렬empirical covariance matrix이다.

이전과 마찬가지로 더 복잡한 시장 시뮬레이션 방법을 선택하거나 시장 요인별로 다른 유형의

분포(꼬리 쪽이 두꺼운 분포라든지)를 가정해도 된다.

9.4 데이터 구하기

대규모로 잘 형식화된 역사적 가격 데이터를 찾기는 어려울 수 있으나, 야후!Yahoo!에서 다양한

주식 데이터를 CSV 형식으로 내려받을 수는 있다. 예제 깃허브 저장소의 risk/data 디렉터리

에 있는 다음의 스크립트는 일련의 REST 요청을 날여 나스닥에 등록된 모든 주식의 과거 데이

터를 내려받아 stocks/ 디렉터리에 저장한다.

$ ./download-all-symbols.sh

리스크 요인들에 대한 역사적 데이터도 필요하다. 우리는 시장 요인으로 S&P 500과 나스닥 지

수의 값들뿐만 아니라 미국 재무부가 발행한 30년 만기 국채와 원유 가격들을 사용할 것이다.

263Chapter 10 - BDG 프로젝트와 유전체학 데이터 분석하기

그래서 우리는 유전자의 구성 물질을 우주로 쏴 보내야 한다.1

-조지 처치

차세대 염기서열 분석next-generation DNA sequencing (NGS ) 기술의 출현으로 생명과학도 데이터가 주도

하는 분야로 급변하고 있다. 하지만 DRMAADistributed Resource Management Application API2나 MPIMessage

Passing Interface3와 같은 사용하기 어려운 저수준의 개발 환경과 정형화되지 않은 텍스트 기반 파일

포맷이 난립하는 상황에서 개발된 전통적인 컴퓨팅 생태계 탓에, 이 데이터를 효율적으로 이용

하기까지 많은 난관에 부딪히고 있다.

이 장의 주요 목적은 세 가지다. 먼저, 일반적인 스파크 사용자에게 하둡과 함께 사용하기 좋은

새로운 직렬화 방법과 파일 형식(에이브로Avro와 파케이Parquet )을 소개한다. 이 형식들은 데이터

를 관리할 때 마주치는 수많은 문제를 매우 단순하게 만들어준다. 압축된 바이너리 형태, 서비

스 지향 아키텍처(SOA ), 언어 간 상호 호환성을 위해서 보통은 이런 직렬화 방법을 사용하도

록 권장한다. 다음으로는, 숙련된 생물정보학자가 일반적인 유전체학 작업을 어떻게 수행하는

지를 스파크의 맥락에서 보여준다. 구체적으로 말하면, 처리 대상인 유전체 데이터와 필터 데

1 옮긴이_ 조지 처치는 그의 저서 『Regenesis: How Synthetic Biology Will Reinvent Nature and Ourselves』에서 인류의 역사를 보존하기 위한 방법으로 인간의 유전체 정보를 담은 전파를 우주로 보내자고 제안한다.

2 옮긴이_ 그리드, 클라우드 컴퓨팅 등에서 사용할 수 있도록 정의된 분산 컴퓨팅 API. 자세한 내용은 DRMAA 워킹 그룹 홈페이지(https://www.drmaa.org/)를 참조하기 바란다.

3 옮긴이_ 분산 및 병렬 처리에서 정보 교환과 관련된 추상화 수준의 상위 표준이다.

BDG 프로젝트와 유전체학 데이터 분석하기

CHAPTER 10

유리 레이저슨

264 9가지 사례로 익히는 고급 스파크 분석

이터를 대량으로 다루고, 전사인자transcription factor 결합 부위 예측 모델을 세우고, 1000 게놈 프

로젝트의 변이체에 대해서 ENCODEEncyclopedia of DNA Elements 게놈 주석 데이터를 결합하는 일에

스파크를 사용할 것이다.4 마지막으로, 아담 프로젝트ADAM project의 튜토리얼을 제공한다. 이 프

로젝트는 대규모 유전체 분석을 위한 유전체 특화 에이브로 스키마와, 스파크 기반의 API, 명

령줄 도구의 모음이다. 아담은 하둡과 스파크를 이용한 게놈 분석 툴킷GATK 모범 사례를 분산

형태로 구현하여 제공한다.

이 장에서 유전체학 관련 부분은 일반적인 문제들에 익숙한 숙련된 생물정보학자를 대상으로

하지만, 데이터 직렬화 부분은 대량의 데이터를 다루는 모든 이에게 유용할 것이다.

10.1 모델링과 저장소를 분리하기

생물정보학자는 파일 포맷에 대하여 고민하며 많은 시간을 보낸다. 파일 포맷의 예로는 .fasta,

.fastq, .sam, .bam, .vcg, .gvcf, .bcf, .bed, .gff, .gtf, .narrowPeak, .wig, .bigWig,

.bigBed, .ped, .tped 등이 있을 것이다. 이중 많은 포맷의 명세가 불완전하고 모호하며(이

러한 이유로 일관되게 구현되리라 확신하기 어렵다) 데이터를 ASCII로 인코딩하기 때문이다.

ASCII 데이터는 생물정보학에서 매우 흔하지만 비효율적이며 상대적으로 압축률이 낮다(그

래서 https://github.com/samtools/hts-specs처럼 명세 개선에 힘쓰는 커뮤니티도 생겨났다).

거기에다 데이터를 항상 파싱해야 하기에 추가적인 계산 사이클이 필요하다. 이들 파일 포맷

모두 서열 정렬 판독aligned sequence read, 유전자형 명칭called genotype, 염기서열 특징sequence feature, 표

현형phenotype과 같은 몇 가지 공통 객체 타입만을 필수로 저장하기 때문에 문제가 두드러진다.

(‘염기서열 특징’이라는 용어는 유전체학에서 조금씩 다른 의미로 사용되고 있는데, 이 장에서

는 UCSC 유전체 브라우저의 기록 요소라는 의미로 사용한다.) 유명한 라이브러리로는 바이

오파이썬biopython (http://biopython.org/ )이 있는데, 이 라이브러리는 모든 파일 포맷을 소수의

공통된 인메모리 모델(예를 들어 Bio.Seq, Bio.SeqRecord, Bio.SeqFeature )로 읽어 들이

는 파서들(예를 들어 Bio.SeqlO )로 가득 차 있다.

4 옮긴이_ 전사(transcription)는 DNA의 유전 정보를 RNA에 복사하는 과정이다. 이를 통해서 DNA 복제 과정에 필요한 단백질을 RNA가 형성하는 등의 대사가 이루어진다. 전사인자는 이 전사 과정에 개입하는 단백질을 의미한다. 유전자의 발현은 이들 전사인자의 결

합 부위의 결합에 의해 조절되므로 이를 예측하는 것은 유전체학의 중요한 이슈 중 하나다. ENCODE와 1000 게놈 프로젝트는 각각 https://www.encodeproject.org/와 http://www.1000genomes.org/를 참조하기 바란다.

265Chapter 10 - BDG 프로젝트와 유전체학 데이터 분석하기

이러한 모든 문제를 아파치 에이브로와 같은 직렬화 프레임워크를 사용하여 단번에 해결할 수 있

다. 내부의 저장소 파일 포맷으로부터 데이터 모델(즉, 명시적인 스키마)을 분리할 수 있으며,

인메모리 표현이 가능하다는 에이브로의 특징이 해결의 열쇠다. 에이브로는 특정 유형의 데이

터를 프로세스 사이에 전달하는 방법이나 데이터를 특정한 파일 포맷으로 기록하는 프로세스

를 지정한다. 이때 프로세스들이 인터넷을 사이에 두고 멀리 떨어져 있더라도 상관없다. 예를

들어 에이브로를 사용하는 자바 프로그램은 에이브로의 데이터 모델과 완전히 호환되는 여러

기본 파일 포맷으로 데이터를 기록할 수 있다. 각각의 프로세스가 여러 파일 포맷들과 모두 호

환되는지는 걱정할 필요가 없다. 프로세스는 에이브로 데이터를 해석할 수 있고, 파일시스템에

서 에이브로로 데이터를 읽어올 수만 있으면 된다.

예제로 염기서열 특징을 들여다보자. 우선 에이브로의 인터페이스 정의 언어interface definition

language (IDL )를 사용하여 객체에 적합한 스키마를 지정한다.

enum Strand {

Forward,

Reverse,

Independent

}

record SequenceFeature {

string featureId;

string featureType; ❶

string chromosome;

long startCoord;

long endCoord;

Strand strand;

double value;

map<string> attributes;

}

❶ ‘보존conservation’, ‘지네centipede’, ‘유전자gene’ 등의 유형이 올 수 있다.

이 자료형은, 예를 들자면 보존 수준, 프로모터promoter의 존재 또는 리보솜 결합 부위, 전사인자

결합 부위 등을 인코딩하는 데 사용할 수 있다.5 인코딩할 때 고려할 수 있는 방법으로, 제약은

5 옮긴이_ 프로모터는 유전체 내의 전사 시작점과 전사 방향을 지시하는 특수한 유전체 염기서열을 의미하며, 리보솜은 아미노산을 연결하여 단백질을 합성하는 세포소기관이다.

266 9가지 사례로 익히는 고급 스파크 분석

많지만 성능은 훨씬 좋은 이진 버전의 JSON이 있다. 특정한 데이터 스키마가 주어지면 에이브

로는 객체에 맞는 정확한 이진 인코딩을 정하여 네트워크를 통하거나 디스크에 저장된 상태로

프로세스끼리 쉽게 데이터를 주고받을 수 있다. 에이브로 프로젝트는 자바, C/C++, 파이썬,

펄Perl을 포함한 많은 언어에서 에이브로로 인코딩된 데이터를 처리할 수 있는 모듈을 제공한

다. 그렇게 통신이 이루어지고 나면, 메모리상의 객체를 프로그래밍 언어에 가장 알맞다고 생

각되는 방법으로 자유롭게 저장하면 된다. 저장 포맷과 데이터 모델을 분리하여 한 차원 높은

유연성과 추상화를 제공하는 것이다. 에이브로 데이터는 열 기반 파일 포맷(파케이 파일) 속

의 에이브로-직렬화 이진 객체Avro-serialized binary object (에이브로 컨테이너 파일)의 형태나 텍스트

JSON 형태로 저장할 수 있다. 전자는 빠른 질의를 위한 것이고, 후자는 유연성을 극대화하기

위한 것이다(효율은 가장 낮다). 마지막으로 에이브로는 필요에 따라 사용자가 새로운 필드를

추가할 수 있는 스키마 진화 기능을 지원한다. 그 덕분에 스키마를 추가해도 모든 소프트웨어

가 구 버전과 새 버전의 스키마를 문제없이 처리할 수 있다.

요약하자면, 에이브로는 진화할 수 있는 데이터 스키마를 쉽게 명시하고, 많은 프로그래밍 언

어가 같은 데이터를 처리하고 여러 가지 포맷을 사용하여 데이터를 저장할 수 있게 해주는 효

율적인 이진 인코딩 수단이다. 에이브로 스키마를 사용해서 데이터를 저장하기로 하면, 계산

성능을 높이는 동시에 점점 더 많은 특수 데이터 포맷을 다뤄야 하는 고통에서 벗어날 수 있다.

직렬화/RPC 프레임워크들

개발 현장에는 수많은 직렬화 프레임워크가 존재한다. 빅데이터 커뮤니티에서 가장 널리 사용하

는 프레임워크는 아파치 에이브로, 아파치 쓰리프트Apache Thrift, 구글의 프로토콜 버퍼Protocol Buffers

다. 셋 모두 객체나 메시지의 스키마를 명시할 때 사용하는 인터페이스 정의 언어를 제공하며 다

양한 프로그래밍 언어로 컴파일할 수 있다는 점이 핵심이다. 프로토콜 버퍼에서도 지원하는 IDL

에 덧붙여, 쓰리프트는 RPC를 명시하는 방법도 제공한다. (구글은 스터비Stubby라는 RPC 메커

니즘을 가지고 있지만, 오픈 소스로 제공하지는 않는다.) 그리고 에이브로는 IDL과 RPC 외에도

데이터를 디스크에 저장하기 위한 파일 포맷을 지정하는 기능도 제공한다. 이들 모두는 다른 언

어를 지원하고 언어별로 성능이 다르므로 어떤 상황에 어떤 프레임워크가 적당하다고 일반화해

말하기는 어렵다.

앞의 예제에서 사용한 특정한 SequenceFeature 모델은 실 데이터에 사용하기에는 조금 단순

했다. 하지만 빅데이터 유전체학 프로젝트BDG project (http://bdgenomics.org/ )를 보면 다음의 예를

267Chapter 10 - BDG 프로젝트와 유전체학 데이터 분석하기

포함하여 객체를 표현하기 위한 수많은 에이브로 스키마를 이미 정의해두었다.

● 리드read6를 위한 AlignmentRecord

● 특정 위치에서의 기본 관측을 위한 Pileup

● 알려진 유전체 변이와 메타데이터를 위한 Variant

● 특정한 유전자좌위locus에서 지정된 유전자형을 위한 Genotype

● 염기서열 특징을 위한 Feature (유전체 세그먼트에 대한 주석)

실제 스키마는 깃허브에서 bdg-formats (https://github.com/bigdatagenomics/bdg-

formats )를 보면 찾을 수 있다. 세계 유전체학 보건연대Global Alliance for Genomics and Health에서도 자

체 에이브로 스키마들을 개발하기 시작했다(https://github.com/ga4gh/schemas ). 이것이

http://xkcd.com/927/와 같은 에이브로 스키마 경쟁의 확산으로 변하지 않기를 바란다. 그렇

기는 해도 에이브로는 현재의 사용자 정의 ASCII보다 성능과 데이터 모델링 면에서 많은 이점

을 제공한다. 이 장의 나머지에서는 BDG 스키마 일부를 사용하여 몇몇 일반적인 유전체학 작

업을 수행할 것이다.

10.2 ADAM CLI를 이용한 유전체학 데이터 처리

NOTE_ 이 장에서는 스파크 기반의 유전체학을 위한 아담 프로젝트를 비중 있게 다룬다. 이 프로젝트는 문

서화를 포함하여 한참 개발이 진행 중이다. 만약 문제가 발생하면 깃허브 상의 최신 README 파일과 깃허

브 이슈 추적 시스템, 또는 아담 개발자 메일링 리스트를 꼭 확인하자.

아담ADAM은 BDG의 유전체학 코어 도구 집합의 이름이다. 매핑된 리드들의 집합을 가지고 여

러 다른 작업에서 중복 표시, 기본 품질 점수 조정, 염기서열 상의 삽입 또는 삭제 재정렬indel

realignment과 변이 추출을 수행해주는 도구들이 포함되어 있다. 사용 편의를 위해서 코어 기능을

래핑한 명령줄 인터페이스도 있다. HPC 환경과는 달리, 이들 명령줄 도구는 하둡과 HDFS에

연동되어 수동으로 파일을 쪼개거나 잡을 스케줄링하지 않아도 대부분의 작업을 클러스터 상

6 옮긴이_ 유전자를 판독할 때 전체 유전자를 한 번에 쭉 읽어내지 못하므로, 여러 조각을 내서 읽은 후 이를 병합하여 판독하는 방식을 사용한다. 이때 조각의 판독된 정보를 흔히 리드(read)라 한다.

268 9가지 사례로 익히는 고급 스파크 분석

에서 자동으로 병렬 처리할 수 있게 되어 있다.

먼저 README에서 알려주는 대로 아담을 빌드해보자.

git clone -b adam-parent-0.16.0 \

https://github.com/bigdatagenomics/adam.git

cd adam

export "MAVEN_OPTS=-Xmx512m –XX:MaxPermSize=128m"

mvn clean package –DskipTests

아담에는 스파크의 spark-submit 스크립트를 인터페이스로 사용하는 전송 스크립트가 들어

있다. 이 스크립트를 사용하는 가장 손쉬운 방법은 별칭alias을 지정해두는 것이다.

export $ADAM_HOME=path/to/adam

alias adam-submit="$ADAM_HOME/bin/adam-submit"

README의 지시대로 $JAVA_OPTS 설정을 이용해 추가적인 JVM 옵션을 지정할 수 있다. 더

많은 정보가 필요하면 appassember 문서를 확인하자.7 여기까지 성공했다면 명령줄에서 아담

을 실행하고 다음과 같은 안내 메시지가 나오는지 보자.

$ adam-submit

...

e 888~-_ e e e

d8b 888 \ d8b d8b d8b

/Y88b 888 | /Y88b d888bdY88b

/ Y88b 888 | / Y88b / Y88Y Y888b

/_____Y88b 888 / /______Y88b / YY Y888b

/ Y88b 888_-~ / Y88b / Y888b

Choose one of the following commands:

ADAM ACTIONS

compare : Compare two ADAM files based on read name

findreads : Find reads that match particular individual

or comparative criteria

depth : Calculate the depth from a given ADAM file,

at each variant in a VCF

7 옮긴이_ http://www.mojohaus.org/appassembler/appassembler-maven-plugin/

289Chapter 11 - 파이스파크와 썬더로 신경 영상 데이터 분석하기

우리는 뇌가 차가운 오트밀과 농도가 같다는 사실에는 관심이 없다.

-앨런 튜링

영상 장비와 자동화 분야의 발전으로 뇌 기능과 관련된 데이터가 넘쳐나게 되었다. 과거의 실

험은 몇 개의 전극으로부터 시계열time series 데이터를 만들거나 뇌 단면의 정지 영상 몇 장을

얻는 데 그친 반면, 오늘날의 기술은 유기체가 활발히 활동하는 동안 넓은 영역의 수많은 신

경 세포neuron에서 뇌 활동을 샘플링할 수 있다. 실제로, 오바마 정부는 브레인 이니셔티브BRAIN

initiative1 프로젝트를 승인하였다. 이 프로젝트는, 예를 들어 장기간에 걸쳐 쥐의 뇌에서 모든 신

경 세포의 전기적 활동을 동시에 기록하는 것과 같은 매우 높은 수준의 기술 개발을 목표로 하

고 있다. 측정 기술의 혁신도 분명히 필요하겠지만, 생성된 데이터의 양은 생물학 분야에 완전

히 새로운 패러다임을 열 것이다.

이번 장에서는 파이썬으로 스파크를 구동하는 파이스파크PySpark API (http://spark.apache.

org/docs/latest/api/python )를 소개한다. 더불어 일반적인 대량의 시계열 데이터, 특히 신

경 영상neuroimaging 데이터를 처리하기 위해서 파이스파크 상에서 개발된 썬더Thunder 프로젝

트(http://thunder-project.org/ )도 소개할 것이다. 파이스파크는 시각화를 위한 맷플롯립

matplotlib이나 ‘실행 가능한 문서’를 만들기 위한 아이파이썬 노트북IPython Notebook (주피터Jupyter 프

1 옮긴이_ 버락 오바마 미국 대통령은 2013년 4월 ‘브레인 이니셔티브(BRAIN initiative)’를 발표하였다. 이 프로젝트의 목표는 인간 두뇌 활동의 모든 경로와 지도를 완성하여 뇌 속의 신경 세포가 어떻게 상호작용하는지를 규명하는 것이다.

파이스파크와 썬더로 신경 영상 데이터 분석하기

CHAPTER 11

유리 레이저슨

290 9가지 사례로 익히는 고급 스파크 분석

로젝트)까지도 포함한 파이데이터PyData 생태계와 잘 통합되어 있기 때문에 탐색적 빅데이터 분

석에 특히 잘 맞는 도구다.

제브라피쉬zebrafish2의 뇌 구조 일부를 이해하는 작업에 이들 도구를 사용할 것이다. 시간의 흐

름에 따른 제브라피쉬의 활동 패턴을 파악하기 위해서 썬더를 사용해서(신경 세포의 그룹으로

표현되는) 뇌의 서로 다른 영역을 군집화할 것이다.

11.1 파이스파크 소개

파이썬은 고수준 문법과 광범위한 라이브러리 패키지 덕분에 다양한 도구 중에서도 수많은 데

이터 과학자가 선호하는 도구다(http://bit.ly/186ShId ). 스파크 생태계는 데이터 분석 환경에

파이썬이 중요함을 인식해왔으며, 과거에 시도한 파이썬과 JVM의 통합 노력이 큰 성과를 거두

지 못했음에도 불구하고 스파크용 파이썬 API에 투자하기 시작했다.3

전문가용 계산과 데이터 과학을 위한 파이썬

파이썬은 전문가용 계산과 데이터 과학에서 선호하는 도구다. 예전에는 매트랩MATLAB, R, 매스매

티카Mathematica를 사용했을 애플리케이션에서 지금은 파이썬을 사용하고 있다. 그 이유는 다음과

같다.

● 파이썬은 사용하고 배우기 쉬운 고급 언어다.

● 수치 계산부터 웹 스크랩 유틸리티와 시각화 도구에 이르기까지 폭넓은 라이브러리가 있다.

● C/C++ 코드와 쉽게 결합할 수 있어, BLAS/LAPACK/ATLAS를 포함한 고성능 라이브러리를 활

용하기에도 좋다.4

2 옮긴이_ 성체의 크기가 3~4cm 정도인 열대 민물고기로 인간의 유전자 구성과 상당 부분 비슷하여 다양한 질병 연구에 활용되고 있다.

3 옮긴이_ Jython, JPype 등 여러 프로젝트에서 자바와 파이썬을 통합하려 노력해왔고 지금도 진행 중이다. 하지만 성능 측면에서도, 보급 측면에서도 성공적이라 평가하긴 어렵다. .NET(C#)과 파이썬을 통합하려는 IronPython과 같은 프로젝트도 있는데, 마찬가지다.

4 옮긴이_ BLAS(Basic Linear Algebra Subprograms)는 벡터 곱, 행렬 곱과 같은 저수준 행렬과 벡터의 수치 연산을 위한 포트란 라이브러리이며, LAPACK(Linear Algebra PACKage)는 이 책의 앞에서 등장한 특이값 분해(SVD)와 같은 고수준의 연산을 지원하는 포트란 라이브러리다. ATLAS(Automatically Tuned Linear Algebra Software)는 BLAS와 LAPACK의 일부를 포트란 77과 C 언어용 라이브러리로 이식한 것이다.

291Chapter 11 - 파이스파크와 썬더로 신경 영상 데이터 분석하기

기억해 두면 좋을 라이브러리를 몇 개 소개하자면 다음과 같다.

numpy/scipy/matplolib

고속 배열 연산, 전문가용 함수, 그리고 널리 사용되는 매트랩에서 영감을 받은 플로팅 라이

브러리를 포함한 일반적인 매트랩의 기능을 재현한다.

pandas

R의 data.frame과 비슷한 기능을 제공한다. 보통은 성능도 더 뛰어나다.

scikit-learn/statsmodels

분류, 회귀, 군집화, 행렬 분해와 같은 기계 학습과 통계 모델을 고품질로 구현하여 제공한다.

nltk

자연어 처리에 널리 사용되는 라이브러리다.

https://github.com/vinta/awesome-python에서 다른 많은 라이브러리의 목록을 찾을 수

있다.

스파크처럼 파이스파크를 시작해보자.

export IPYTHON=1 # 파이스파크는 IPython 셸을 사용할 수 있다.

pyspark --master ... --num-executors ... ❶

❶ pyspark는 spark-shell과 동일한 인수를 받는다.

환경 변수를 IPYTHON=1로 설정하면 파이스파크에서 아이파이썬 셸을 사용하는데, 이는 우

리가 보편적으로 추천하는 방식이다. 파이썬 셸을 시작하면 클러스터와 상호작용하는 파이썬

SparkContext 객체를 생성한다. SparkContext를 사용할 수 있게 되면 파이스파크 API는 스

파크 API와 매우 유사하게 동작한다. 예를 들어 다음은 CSV 데이터를 읽어 들이는 모습이다.

raw_data = sc.textFile('path/to/csv/data') # RDD[string]

# 필터링하고, 쉼표를 기준으로 나누고, 실수(float)를 파싱하여 RDD[list[float]]를 얻는다.

data = (raw_data

.filter(lambda x: x.startswith("#"))

.map(lambda x: map(float, x.split(','))))

data.take(5)

292 9가지 사례로 익히는 고급 스파크 분석

스칼라 API에서 하는 그대로, 텍스트 파일을 읽어 들여 #으로 시작하는 행을 필터링하여 제외

하고, CSV 데이터를 float 값의 목록으로 파싱한다. 인수로 전달된 (예를 들어 filter나 map

에 전달된) 파이썬 함수들은 매우 유연하다. 파이썬 객체를 인수로 받아 파이썬 객체를 반환

해야 한다(filter의 반환 값은 불리언 값으로 해석된다). 제약이 없는 것은 아니다. 먼저, 파

이썬 함수 객체는 cloudpickle로 직렬화할 수 있어야 한다. 익명(람다) 함수도 마찬가지다.

그리고 클로저에서 참조하는 모듈은 모두 실행자 프로세스가 돌아가는 환경의 PYTHONPATH

환경 변수에 지정된 위치에 있어야 한다. 참조 모듈을 사용하려면 그 모듈을 클러스터 전체

에 설치하고 그 위치를 실행자 프로세스 구동 환경의 PYTHONPATH에 명시하거나, 적절한 모

듈 ZIP/EGG 파일들을 스파크로 명시적으로 분산시키고 PYTHONPATH에 추가해야 한다.

sc.addPyFile()을 호출하면 후자의 방식으로 동작하게 할 수 있다.

파이스파크 RDD는 단지 파이썬 객체들의 RDD일 뿐이다. 파이썬 리스트처럼 이 RDD에는

혼합된 자료형의 객체도 저장할 수 있다(모든 객체가 PyObject의 인스턴스인 덕분이다).

아무래도 파이스파크 API는 스파크의 최신 API를 반영하기까지 시일이 걸릴 수 있으므로, 일

부 기능은 스칼라에서 더 빨리 사용할 수 있다. 하지만 핵심 API 이외에도 MLlib에 사용할 파

이썬 API가 이미 존재한다. 실제로 썬더 프로젝트에서 이 API를 사용하고 있다.

11.1.1 파이스파크 내부 구조디버깅을 간소화하고 잠재적인 성능 저하의 원인을 알고 대처하려면 파이스파크의 구현 원리

를 어느 정도 이해해두는 것이 좋다. [그림 11-1]을 보자.

그림 11-1 파이스파크 내부 구조

293Chapter 11 - 파이스파크와 썬더로 신경 영상 데이터 분석하기

파이스파크의 파이썬 인터프리터가 시작될 때 인터프리터와 소켓을 통해 통신하는 JVM도 함

께 실행된다. 파이스파크는 이 통신에 Py4J 프로젝트를 사용한다. JVM은 실제 스파크 구동자

로서의 역할을 하며, 클러스터 노드의 스파크 실행자들과 통신하는 JavaSparkContext를 로

드한다. 그후에는 SparkContext 객체가 호출한 파이썬 API는 JavaSparkContext에서 호출

하는 자바 API로 변환된다. 예를 들어 파이스파크의 sc.textFile()는 JavaSparkContext

의 textFile 메서드를 호출하며, 마지막에는 HDFS에서 데이터를 읽어 들이기 위해서 스파크

실행자의 JVM들과 통신한다.5

클러스터의 스파크 실행자들은 파이썬 인터프리터를 코어마다 실행하는데, 사용자 코드를

실행해야 할 때는 데이터 통신을 위해 파이프pipe를 이용한다. 로컬 파이스파크 클라이언트

의 파이썬 RDD는 로컬 JVM의 PythonRDD 객체에 대응한다. RDD와 관련한 데이터는 실

제로는 스파크를 구동하는 JVM의 자바 객체로 되어 있다. 예를 들어 파이썬 인터프리터에

서 sc.textFile()을 실행하면 JavaSparkContext의 textFile 메서드를 호출하고 이 메

서드가 데이터를 클러스터 상의 자바 String 객체로 읽어 들일 것이다. 비슷한 방식으로

newAPIHadoopFile을 사용하여 파케이/에이브로 파일을 읽으면 자바 에이브로 객체로 읽어

들일 것이다.

파이썬 RDD에서 API가 호출되면 파이썬 람다 함수 같은 모든 연관 코드는 클라우드피클

cloudpickle 모듈을 통해서 직렬화되어 실행자들로 분산된다. 그런 다음, 데이터는 자바 객체에서

파이썬에서 사용할 수 있는 형태(예를 들어 피클pickle 객체)로 변환되고 파이프를 통해 실행자

와 관련된 파이썬 인터프리터로 흘러 들어간다. 필요한 모든 파이썬 처리는 인터프리터에서 실

행되며, 결과(기본 설정으로는 피클 객체)는 다시 JVM에 있는 RDD로 저장된다.

파이썬의 실행 코드 직렬화 기능은 스칼라의 직렬화만큼 강력하지는 않다. 파이스파크 개발자

들이 지금은 없어진 파이클라우드PiCloud에서 만든 클라우드피클이라는 별도 모듈을 사용해야

했던 이유다.

5 옮긴이_ Py4J는 파이썬 인터프리터에서 파이썬 프로그램이 JVM의 자바 객체에 동적으로 접근할 수 있도록 처리해준다.

294 9가지 사례로 익히는 고급 스파크 분석

아이파이썬 노트북(주피터)에 파이스파크 설정하기

아이파이썬 노트북은 탐색적 분석과 계산이 가능한 ‘연구 노트’로 환상적인 도구다. 아이파이썬

노트북을 사용하여 텍스트, 그림, 실행 코드(원래는 파이썬만 지원했으나 지금은 다른 언어도 지

원한다)를 통합할 수 있다. 또, 플랫폼 호스팅을 포함한 다른 여러 기능도 제공한다. 아이파이썬

노트북은 스파크에도 잘 맞지만, 파이스파크가 특별한 방식으로 초기화되어야 하기 때문에 정확

하게 설정하기 위해서는 몇 가지를 주의해야 한다. 자세한 내용은 http://bit.ly/186UfIE 블로그

게시물을 참조하자.

11.2 썬더 라이브러리 개요와 설치

썬더 라이브러리의 예제와 문서

썬더 패키지는 훌륭한 문서와 튜토리얼을 제공한다. 이어지는 예제는 썬더에서 제공하는 데이터

와 튜토리얼에서 가져왔다.

썬더는 스파크에서 대용량의 공간과 시계열 데이터셋(즉, 커다란 다차원 행렬)을 처리하기 위

한 파이썬 도구 모음이다. 행렬 계산에는 넘파이NumPy 모듈을, 몇몇 통계 기법를 분산 처리하는

데에는 MLlib 라이브러리를 적극적으로 사용한다. 파이썬으로 만들어져서 매우 유연하고, 또

수많은 개발자가 이용할 수 있다. 다음 절에서는 썬더 API를 소개하고 썬더와 파이스파크로

감싸진 MLlib의 K-평균 군집화 구현을 사용하여 몇몇 신경활동을 추적해 패턴들을 분류해볼

것이다.

썬더를 사용하려면 스파크뿐 아니라 파이썬 라이브러리인 넘파이, 사이파이SciPy, 맷플롯립

matplotlib, 사이킷런scikit-learn이 필요하다. pip install thunder-python으로 아주 쉽게 설치할

수 있지만, 스파크 1.1과 하둡 1.x 이외의 버전을 사용하려면 깃 저장소에서 체크아웃해야 한

다(상자글 참조). 또한, 썬더는 아마존 EC2로 쉽게 배포해주는 스크립트를 포함하고 있으며

전통적인 HPC 환경에서도 잘 동작한다.

329찾아보기

INDEX

숫 자

1000 게놈 프로젝트 264

3D화소(voxel) 289

거리 123

마할라노비스 거리 142

유클리디안 거리 123

코사인 유사도 163

고계함수(higher-order function) 43

곡선 아래 면적(AUC) 82

교차 최소 제곱 알고리즘 69, 72

최소 제곱 72

QR 분해 72

과적합 86, 100, 107, 111

교차 검증 데이터셋 83

구동자(driver) 32

구아카몰 288

군집 중심(centroid) 123

군집화 68, 123

그래프 이론 173

군집계수 175, 200

꼭짓점(vertex, node) 173

변(edge, link, line) 173

연결 성분 175, 188

연결성 188

완전 그래프 199

차수 191

차수 분포 175, 191

클릭(clique) 199

트라이앵글 수 200

평균 경로 길이 175

그래프엑스(GraphX) 174, 321

EdgeRDD 185

VertexRDD 185

금융상품(instrument) 236

난수 253

메르센 트위스터 254

네트워크 과학 173

다변량 정규분포 250

MultivariateNormalDistribution 클래스 250

단어-문서 행렬 146, 147

단어 빈도(term frequency, TF) 147

대량 동기 병렬(bulk-synchronous parallel, BSP)

202

데이터 과학 21

데이터 정제 29

데카르트 변형 252

동반 객체 58

동시발생 그래프 184

동시발생 네트워크 184

랜덤 포레스트 94, 97, 114

RandomForest 클래스 97

레코드 링크 32

맷플롯립(matplotlib) 298

메이븐 40

몬테카를로 시뮬레이션 235, 238

경험적 분포 238

실험 238

문서 빈도 153

범주 변수 55

범주형 특징(categorical feature) 95

보조 정렬 230

330 찾아보기

INDEX

보통최소제곱 회귀 246

OLSMultipleLinearRegression 클래스 246

부분 적용 함수 85

부트스트래핑 257

분류 68

분류 94

분산-공분산 237

불순도 측정 108

불용어(stop word) 151

브라운 운동 260

브레인 이니셔티브 프로젝트 289

브로드캐스트 변수 77

브리쉬-고드프리 검정법 247

비지도 학습(자율 학습) 122

빅데이터 유전체학(BDG) 프로젝트 266

산림 식생 데이터 100

서포트 벡터 머신 68

세션, 세션화 229

섹션(또는 스플릿) 38

셔플 311

손실(loss) 237

수신자 조작 특성(ROC) 82

수익(return) 237

수치형 특징(numeric feature) 95

숨은 의미 분석(Latent Semantic Analysis, LSA) 145

스칼라 30

스칼라 컬렉션 54

스크로블링 68

스테이지 311

스파크 셸(spark-shell) 34

스파크 스트리밍 320

스파크 콘텍스트(SparkContext) 36

파이썬 SparkContext 291

스파크 SQL 321

SchemaRDD 321

스프레이(Spray) 217

시장 요인(market factor) 237

실패율 검정 258

썬더 289, 294

Images 객체 296

Series 객체 300

아담(ADAM) 프로젝트 264

아이파이썬 노트북(IPython Notebook) 289, 294

아파치 머하웃(Mahout) 150

암묵적 피드백 69

암묵적 형변환 48

액션 41

어간 추출(stemming) 151

어큐뮬레이터 314

에이브로(Avro) 263, 265

엔트로피 108, 139

역문서 빈도(inverse document frequency, IDF) 147

역사적 시뮬레이션 238

연속 변수 55

오디오스크로블러 68

온전성 검사 137

이상 감지(이상 탐지) 122

익명 함수 44

의사 결정 나무 94, 96

DecisionTree 클래스 97

원-핫 인코딩 101

자료형 추정(type inference) 37, 39

자유도 194

작은 세상 네트워크 199

잠재 디리클레 할당 171

잠재 요인 모델 70

정규화 135

표준점수(standard score) 135

331찾아보기

재현율 105

정밀도 103, 105

정확도 105

조건부 최대손실예상액(CVaR, 기대손실) 236

주성분 분석 133, 171

지니 불순도 108

지도 학습 94, 121

지수(index) 237

직렬화 313

직렬화 프레임워크 266

차세대 염기서열 분석 263

차원 감소 133

추천 엔진 67

최대손실예상액(VaR) 235

카이제곱 검정 194

카이제곱 분포 194

카이제곱 통계량 194

캐글 경진대회 100

캐시 51

커널 밀도 추정 248

케이스 클래스(case class) 49

콜모고로프-스미르노프 검정법 260

클러스터 41, 45

탄력적 분산 데이터셋(RDD) 37

테스트 데이터셋 83

통용식별자(WKID) 215

튜플 자료형 47

특이값 분해(Singular Value Decomposition, SVD)

133, 146, 156

낮은 계수 근사 146

정규직교 기저 156

특징(feature) 95

특징 벡터(feature vector) 95

파이스파크(PySpark) API 289, 290

클라우드피클 293

PythonRDD 293

파이프라인 API 323, 325

파케이(Parquet) 263, 274

조건절 푸시다운(predicate pushdown) 276

조건절(predicate) 276

페어 RDD 55

평균으로의 회귀 93

포트폴리오(portfolio) 236

표제어 추출(lemmatization) 148, 151

프레겔 174, 202

피어슨 상관관계 250

하둡 분산 파일시스템(HDFS) 32

하이퍼파라미터(hyperparameter) 79, 85

학습 데이터셋 83

함수형 프로그래밍 43

행렬 분해 모델 70

엔트로피 108, 139

행렬 채우기 알고리즘 71

MatrixFactorizationModel 78

협업 필터링 69

혼합 정규분포 260

화소(pixel) 289

회귀 94

희소 행렬(sparse matrix) 70

A ~ Z

AUC(곡선 아래 면적) 82

BSP(대량 동기 병렬) 202

Cloud9 151

332 찾아보기

INDEX

Core NLP 프로젝트 151

Covtype 데이터셋 100

CVaR(조건부 최대손실예상액) 236

Either[L, R] 222

ENCODE 264

Esri Geometry API 214

Geometry 객체 215

GeoJSON 214, 216

JodaTime 라이브러리 212

k-겹 교차 검증 84

K-평균 군집화 123, 304

군집 중심(centroid) 123

실루엣 계수 143

k 값 129

K-평균++ 131

K-평균|| 131

KMeansModel 127

StreamingKMeans 142

KDD 컵 125

Kryo 211, 313

LSA(숨은 의미 분석) 145

MEDLINE 174

MeSH 태그 175

MLlib 68, 319

NScalaTime 래퍼 라이브러리 212

DateTime 클래스 212

Duration 클래스 213

Q-Q 플롯 260

R에서 시각화 133

RDD(탄력적 분산 데이터셋) 37

Rating 객체 80

REPL 40

scala.xml 패키지 179

SVD(특이값 분해) 133, 146, 156

TF-IDF 147

단어 빈도(TF) 147

문서 빈도 153

역문서 빈도(IDF) 147

VaR(최대손실예상액) 235

XML 리터럴 179

z-스택 289

www.hanbi t .co.kr

이것이 프로그래밍이다!

이것이 안드로이드다

진정한 안드로이드 개발자로 이끌어줍니다.

SDK 5.0 롤리팝 호환!

책만 보고,

동영상 강좌로도 만족하지 못했다면 Daum 카페 '슈퍼드로이드'에서 만나요

cafe.daum.net/superdroid

박성근 저 | 1,164쪽 | 45,000원

이것이 C언어다

세상에 없던 새로운C언어 입문서 탄생!

삼성, LG에서 펼쳐졌던 전설의 명강의를 풀타임 동영상 강좌로!

이보다 더 확실한 방법은 없다, 칠판강의

전체 동영상 강좌 유투브 전격 공개!

http://goo.gl/tJK3Tu

서현우 저 | 708쪽 | 25,000원

이것이 자바다

가장 중요한 프로그래밍 언어를 하나배워야 한다면, 결론은 자바다!

중급 개발자로 나아가기 위한 람다식,

JavaFX, NIO 수록

자바의 모든 것을 알려주는 인터넷 강의궁금한 것은 카페에서!

cafe.naver.com/thisisjava

신용권 저 | 1,224쪽 | 30,000원

저자 직강 동영상 제공!

모던 웹을 위한

JavaScript + jQuery 입문

www.hanbi t .co.kr

지금은모던 웹 시대!

HTML5 분야 부동의 1위 도서HTML5 표준안 확정에 맞춘 완전 개정판의 귀환!

HTML5 권고안과 최신 웹 브라우저 환경 대응

윤인성 저 | 624쪽 | 30,000원

모던 웹 디자인을 위한

HTML5 + CSS3 입문

자바스크립트에서 제이쿼리, 제이쿼리 모바일까지 한 권으로 끝낸다!

시대의 흐름에 맞춰 다시 쓴 자바스크립트 교과서

윤인성 저 | 980쪽 | 32,000원

페이스북, 월마트, 링크드인은 왜 Node.js를 선택했는가?

이 물음에 대한 답은 Node.js가 보여주는 빠른 처리 능력 때문이다.

윤인성 저 | 484쪽 | 25,000원

모던 웹을 위한

Node.js프로그래밍

필요한 것만 배워 바로 현장에서 쓰는 HTML5순서대로 읽으며 실습할 수 있는 HTML5 자습서

김상형 저 | 700쪽 | 32,000원

HTML5 + CSS3 정복

www.hanbi t .co.kr

Hanbit eBook Realtime

DRM free!어떤 디바이스에서도 자유롭게

eBook Oriented!전자책에 꼭 맞는 최적의 내용과 디자인

Hanbit eBook

Realtime 70

김세훈 지음

MFC프로그래밍주식분석 프로그램 만들기

이연복 지음

Hanbit eBook

Realtime 49Hanbit eBook

Realtime 89

자바 개발자를 위한

Vert.x애플리케이션 개발

Hanbit eBook

Realtime 49Hanbit eBook

Realtime 92

모바일/웹 메시징STOMP와 MQTT로 개발하는 IoT

모바일/웹 애플리케이션

제프 메스닐 지음 / 조건희 옮김

Mobile and Web Messaging

Hanbit eBook

Realtime 90

JavaScriptPromise azu 지음 / 주우영 옮김

www.hanbi t .co.kr /ebook

www.hanbi t .co.kr

전자부품 백과사전 vol.1찰스 플랫 지음 / 배지은 옮김 / 30,000원

취미공학에 필요한 핵심 전자부품을 사전식으로 정리한 안내서.

Zero to Maker: 누구나 메이커가 될 수 있다데이비드 랭 지음 / 장재웅 옮김 / 14,000원

일반인에서 메이커로. 날백수에서 무인 잠수정 회사 CEO가 된 사나이, 데이비드 랭의 메이커 도전기.

처음 시작하는 센서키모 카르비넨,테로 카르비넨 지음임지순 옮김 / 13,000원

세상을 수치로 읽어내는 부품인 센서를 알려주는 책. 이 책을 통해 자신만의 프로젝트에 다양한 센서를 사용해보자.

프로젝트로 배우는 라즈베리 파이 도날드 노리스 지음 / 임지순 옮김

다양한 실전 프로젝트를 통해 라즈베리 파이를 쉽고 재미있게 배워본다.

Maker Pro 존 베이첼 지음 / 가격미정

메이커라면 반드시 읽어야 할 필수 계발서. 프로 메이커들과의 인터뷰 및 에세이 수록.

Make: 센서 키모 카르비넨, 테로 카르비넨, 빌 발토카리 지음 / 가격미정

필수 전자부품인 센서를 마이크로 컨트롤러 보드에 응용하는 방법을 담았다.

전자부품 백과사전 vol.2 찰스 플랫 지음 / 가격미정

<전자부품 백과사전> 시리즈의 두 번째 도서다.

즐거운 상상이 가득! 2015년 화제의 신간

전자부품 백과사전 vol.1찰스 플랫 지음 / 배지은 옮김 / 30,000원

취미공학에 필요한 핵심 전자부품을 사전식으로 정리한 안내서.

Zero to Maker: 누구나 메이커가 될 수 있다데이비드 랭 지음 / 장재웅 옮김 / 14,000원

일반인에서 메이커로. 날백수에서 무인 잠수정 회사 CEO가 된 사나이, 데이비드 랭의 메이커 도전기.

처음 시작하는 센서키모 카르비넨,테로 카르비넨 지음임지순 옮김 / 13,000원

세상을 수치로 읽어내는 부품인 센서를 알려주는 책. 이 책을 통해 자신만의 프로젝트에 다양한 센서를 사용해보자.

프로젝트로 배우는 라즈베리 파이 도날드 노리스 지음 / 임지순 옮김

다양한 실전 프로젝트를 통해 라즈베리 파이를 쉽고 재미있게 배워본다.

Maker Pro 존 베이첼 지음 / 가격미정

메이커라면 반드시 읽어야 할 필수 계발서. 프로 메이커들과의 인터뷰 및 에세이 수록.

Make: 센서 키모 카르비넨, 테로 카르비넨, 빌 발토카리 지음 / 가격미정

필수 전자부품인 센서를 마이크로 컨트롤러 보드에 응용하는 방법을 담았다.

전자부품 백과사전 vol.2 찰스 플랫 지음 / 가격미정

<전자부품 백과사전> 시리즈의 두 번째 도서다.

즐거운 상상이 가득! 2015년 화제의 신간