[Greenplum] 오픈소스 Greenplum DB와 Apache MADlib을 활용한 그래프 분석, 네트워크 분석 (Graph analytics with Greenplum and Apache MADlib)
Greenplum and PostgreSQL Database 2019. 8. 25. 10:08제가 2019년 1월 30일에 Pivotal 의 Data Science Webinar 에서 발표했었던 "오픈소스 그림플럼 DB와 아파치 MADlib을 활용한 그래프 분석, 네트워크 분석 (Graph analytics with Greenplum and Apache MADlib)" 자료를 공유합니다.
[ Agenda ]
1. Why Graph Analytics?
2. What is Graph Analytics?
3. Graph Analytics with Apache MADlib on Greenplum in parallel
presented by Hongdon Lee, Pivotal Senior Data Scientist
[ 파일 첨부: Graph Analytics with Greenplum and Apache MADlib ]
Pivotal_Graph_Analytics_w_MADlib_GPDB_20190130.pdf
개별 단위별 객체, 대상만을 놓고 나누어 분석하는 환원주의(Reductionism: Divide and conquer) 대비 전체를 하나로 놓고 관계와 연결에 주목해서 분석하면 새로운 인사이트를 얻을 수 있다는 전체론 관점(Holism: Everything has to be understood in relation to the whole)의 분석 기법으로 그래프 이론(graph theory)과 네트워크 분석(network analysis)을 소개하는 자료입니다.
그래프 분석 시 도전 사항으로 복잡도가 매우 높아 연산 부하가 크고 분석이 불가능하거나 시간이 오래 걸린다는 점입니다. 이를 해결할 수 있는 대안으로 MPP(Massively Parallel Processing) 아키텍처 기반의 오픈소스 Greenplum DB와 Apache MADlib을 이용한 그래프, 네트워크 분석의 In-Database 병렬 처리 분석을 소개하였습니다.
Webinar 발표할 때 재미를 더하기 위해서 슬라이드 중간 중간에 제 사진도 좀 넣어보았는데요, 이렇게 파일 공유하려니 좀 쑥스럽기도 하네요. ^^; Webinar 발표할 때는 우리나라말로 했었는데요, 글로벌 데이터 팀 구성원들한테도 공유할 생각으로 슬라이드는 영어로 만들었습니다. 중간에 수식도 많은데 영어라서 눈에 잘 안들어온다는 피드백이 있었는데요, 양해 바랍니다. ^^;;;
알고리즘 세부 소개하는 부분은 위키피디아를 많이 참고하였습니다.
저는 실제 프로젝트 하면서 그래프 / 네트워크 분석이 제공할 수 있는 인사이트의 유용함을 경험하기도 했구요, Greenplum DB 에서 MADlib으로 분석하면서 In-DB parallel processing의 강력함을 경험했던 지라 기회되면 꼭 한번 소개를 하고 싶었던 주제였습니다. R이나 Python으로 노트북에서 network 분석 공부할 땐 아무 문제 없다가도, 실제 기업이나 공공기관의 수 terabyte, petabyte 급 데이터를 마주하게 되면 당황하기 마련인데요, 이럴 때 사용할 수 있는 방법, 툴입니다.
주요 장표 몇 장만 아래에 화면 캡쳐한거 소개하자면요,
- Everything is connected!
- Network: Everywhere with Everything, All the time
- What is Graph Theory?
- Graph algorithms and measures
- Tools for Graph Analytics
- Apache MADlib: Scaleable, In-Database Machine Learning in SQL
- Apache MADlib: Graph Analytics Functions
그래프/ 네트워크 분석 주제 중에서 Page Rank 에 대한 간단한 예제 SQL 코드와 Graphviz, PyGraphviz를 활용한 네트워크 시각화 코드도 공유합니다.
[ 그래프 분석 MADlib SQL codes ]
---------------------------------------------- -- Graph Analytics with Greenplum and MADlib ---------------------------------------------- -- CREATE VERTEX TABLE DROP TABLE IF EXISTS vertex; CREATE TABLE vertex( id INTEGER ) DISTRIBUTED RANDOMLY; INSERT INTO vertex VALUES (0), (1), (2), (3), (4), (5), (6); select * from vertex -- CREATE EDGE TABLE DROP TABLE IF EXISTS edge; CREATE TABLE edge( src INTEGER, dest INTEGER, user_id INTEGER ) DISTRIBUTED BY (user_id); INSERT INTO edge VALUES (0, 1, 1), (0, 2, 1), -- user id 1 (0, 4, 1), (1, 2, 1), (1, 3, 1), (2, 3, 1), (2, 5, 1), (2, 6, 1), (3, 0, 1), (4, 0, 1), (5, 6, 1), (6, 3, 1), (0, 1, 2), (0, 2, 2), -- user id 2 (0, 4, 2), (1, 2, 2), (1, 3, 2), (2, 3, 2), (3, 0, 2), (4, 0, 2), (5, 6, 2), (6, 3, 2); select * from edge; -- (1) Compute the PageRank with All IDs DROP TABLE IF EXISTS pagerank_out, pagerank_out_summary; SELECT madlib.pagerank( 'vertex' -- Vertex table , 'id' -- Vertex id column , 'edge' -- Edge table , 'src=src, dest=dest' -- Comma delimited string of edge arguments , 'pagerank_out' -- Output table of RageRank , NULL -- Default damping factor (0.85) ); SELECT * FROM pagerank_out ORDER BY pagerank DESC; -- (2) Compute the PageRank of vertices associated with each user using the grouping feature DROP TABLE IF EXISTS pagerank_gr_out, pagerank_gr_out_summary; SELECT madlib.pagerank( 'vertex' -- Vertex table , 'id' -- Vertex id column , 'edge' -- Edge table , 'src=src, dest=dest' -- Comma delimited string of edge arguments , 'pagerank_gr_out' -- Output table of PageRank , NULL -- Default damping factor (0.85) , NULL -- Default max iterations (100) , 0.00000001 -- Threshold , 'user_id'); -- Grouping column name SELECT * FROM pagerank_gr_out ORDER BY user_id, pagerank DESC; -- (3) Personalized PageRank of vertices {2, 4} DROP TABLE IF EXISTS pagerank_pers_out, pagerank_pers_out_summary; SELECT madlib.pagerank( 'vertex' -- Vertex table , 'id' -- Vertex id column , 'edge' -- Edge table , 'src=src, dest=dest' -- Comma delimited string of edge arguments , 'pagerank_pers_out' -- Output table of PageRank , NULL -- Default damping factor (0.85) , NULL -- Default max iterations (100) , NULL -- Default Threshold (1/number of vertices*1000) , NULL -- No Grouping , '{2, 4}' -- Personalization vertices ); SELECT * FROM pagerank_pers_out ORDER BY pagerank DESC; SELECT * FROM pagerank_pers_out_summary;
|
[ Graphviz를 활용한 네트워크 시각화 Python codes ]
#!/usr/bin/env python2 # -*- coding: utf-8 -*- """ Created on Tuesday Jau 29 2019 @author: Hongdon Lee """ #%% network visualization using Graphviz import numpy as np import pandas as pd import pygraphviz as pgv def run_query(query): import pandas as pd import psycopg2 as pg # DB Connection conn = pg.connect(host='localhost', port='5432', dbname='gpadmin', user='gpadmin', password='pivotal') # Get a DataFrame query_result = pd.read_sql(query, conn) conn.close() return query_result #%% Network Edge Table query = """ select a.*, b.pagerank from edge a left outer join pagerank_out b on a.src = b.id ; """ edge_pagerank = run_query(query) #%% PageRank Values query = """ select * from pagerank_out; """ pagerank_out = run_query(query) #%% NW Visualization using Graphviz with different size proportional to PageRank import pygraphviz as pgv # Generating the output flow_graph with PyGraphviz flow_graph = pgv.AGraph(strict=False, directed=True) # directed graph # Flow Direction(Left to Right, or Top to Bottom) flow_graph.graph_attr['rankdir'] = 'LR' # from Left to Right # Node Shape flow_graph.node_attr['shape'] = 'circle' # Making node with different size proportional to PageRank for i in range(len(pagerank_out)): label_text = str(pagerank_out.id[i]) + '\n(' + str(pagerank_out.pagerank[i].round(decimals=2)) + ')' node_width = pagerank_out.pagerank[i]*10 node_height = pagerank_out.pagerank[i]*10
flow_graph.add_node(str(pagerank_out.id[i]), label=label_text, **{'width': str(node_width), 'height': str(node_height)}) # Adding edge with different color by user_id colors = ['blue', 'red']
for i in range(len(edge_pagerank)): if edge_pagerank.user_id[i] == 1: color_text = colors[0] else: color_text = colors[1]
flow_graph.add_edge(str(edge_pagerank.src[i]) , str(edge_pagerank.dest[i]) , color = color_text) #----- Finally, Draw the Network Diagram using dot program :-) flow_graph.draw("/Users/ihongdon/Documents/nw_diagram.png", prog='dot') |
[ Docker image를 이용해서 Greenplum, MADlib, PL/R, PL/Python 분석 환경 구성하는 방법 (싱글 노드의 로컬 기능 테스트, 공부 용도로)]
https://rfriend.tistory.com/379
https://hub.docker.com/r/hdlee2u/gpdb-analytics
많은 도움이 되었기를 바랍니다.
ps. 앤 해서웨이(ANNE HATHAWAY)와 연결해주실 분 계신가요? 6 degrees of separation 의 기적이 저에게도 일어날 수 있으려나요? ^^"