GraphFDS-01
GraphFDS 시리즈 , 첫 번째 게시물. 그래프 자료구조부터 그래프가 FDS에서 왜 유용한지 그리고 그 유용함을 활용하기 위해 원시 데이터에서 그래프 데이터로 변환화는 과정 까지를 다룹니다.
Dec 24, 2023
tl;dr
- 그래프 데이터 개괄에 대해 이야기합니다.
- FDS 에서 그래프가 무엇을 할 수 있을지에 대해 이야기합니다.
- 그래프 데이터를 활용하기위해 원시 데이터부터 그래프 데이터까지 변환하는 과정에 대해 이야기합니다.
1.그래프 데이터란 무엇일까요?
- 네트워크 (노드 링크) , 그래프 (벌텍스 , 엣지)로 표현합니다. 복잡계 물리학측면에서 주로 네트워크라는 용어를 활용하고 수학 측면에서 주로 그래프라는 용어를 활용합니다. 그 근본은 다르나 목적은 유사하기에 논문과 같은 학계에 활용할 언어가 아니라면, 혼용해서 사용해도 별 문제는 없습니다. ex) 그래프 데이터 - 노드 엣지로 구성되어 있음.
- 참고로 수학 이론 측면에서 그래프를 좀 더 구체적으로 이야기해보자면, 다음과 같습니다. 객체의 일부 쌍들이 '연관되어'있는 객체 집합 구조.
- 그래프를 표현하기 위해서 주로 '인접 행렬' 과 '인접 리스트' 형태를 활용합니다. 이 때 각 표현 형태마다 장단점이 존재하는데요. 이 둘을 비교 대상으로 각각 삼아 시간 복잡도 측면, 공간 복잡도 측면에서 무엇이 유리하고 무엇이 불리한지 이야기해보겠습니다.
- 먼저, 인접 행렬의 장점부터 말해보자면 모든 연결관계가 2차원 행렬 형태로 저장되어 있기 때문에, 관계 탐색시 행렬의 유무만 확인하면 되기에 관계 있는 노드만을 탐색할 때 신속하여 시간 복잡도 측면에서 유리합니다. 반면에, 그래프의 모든 노드 그리고 관계를 2차원 행렬로 표현해야하기에 관계의 유무를 모두 저장해야 합니다. 따라서, 이를 저장 관리하기 위한 공간이 많이 필요하기에 공간복잡도 측면에서는 불리합니다.
- 다음, 인접 리스트는 연결되어 있는 노드와 관계를 연결 리스트 형태로 표현하여, 존재하는 엣지들만 저장 관리하기에 필요한 공간이 상대적으로 적습니다. 따라서, 공간복잡도 측면에서 유리합니다. 반면에, 노드간 관계 유무를 확인하기 위해 형성되어 있는 인접 리스트를 모두 탐색하며 공통 리스트인지를 확인해야하기에 시간 복잡도 측면에서 불리합니다.
- 그렇기에 데이터를 활용하기 전에 어떤 형태로 그래프를 표현할지에 대한 고민이 선행되어야만 효과적으로 그래프를 적용할 수 있습니다.
- 어떤 형태로 표현할지에 대한 기준은 다음과 같습니다. '엣지'의 희소성 다시 말해 그래프 밀도에 따라 그 선택 기준이 달라지겠는데요. 만약 그래프 밀도 분포가 높다면, 한 노드당 연결된 노드들이 많다는것을 간접적으로 암시하기에 인접행렬이 유리합니다. 반면에, 밀도 분포가 낮다면 , 한 노드당 연결된 노드들이 적다는것을 간접적으로 암시하기에 인접 리스트가 유리합니다.
- scipy.sparse , dgl.sparse , torch.sparse , pyg.sparse 모두 앞서 말한 이야기와 비슷한 맥락을 띄기에 지금 현 데이터의 분포를 확인해보고 이를 기반으로, sparse형태를 적용하는게 유리한지 edgelist 형태를 적용하는게 유리한지 비교하는 과정이 필요합니다.
- 그래프 데이터의 장점은 데이터 탐색 속도 최적화 라고 할 수 있습니다. 각 객체간 연결을 탐색하며, 이 결과를 토대로 데이터가 어떤 값을 가지고 있는지를 나타냅니다. '연결'을 탐색하기 위한 전략은 크게 DFS(Depth-First-Search) 와 BFS(Breath-First-Search) 로 나누어지는데요. 연결을 깊이 중심으로 탐색할 것이냐, 너비 중심으로 탐색할 것이냐 라는 차이로 나뉘어집니다. 예로 들어 설명들어 보겠습니다.
- 본 포스팅의 취지는 FDS 와 그래프이기에 디테일한 설명은 생략하되, 어떤식으로 BFS , DFS 가 진행되는지 간단한 프로세스 그림 , 파이썬 코드만 이야기하고 넘어가겠습니다.
- 파이썬 코드
# dfs implementation code def iterative_dfs(start_v): discovered = [] stack = [stack_v] while stack: v = stack.pop() if v not in discovered: discovered.append(v) for w in graph[v]: stack.append(w) return discovered # bfs implementation code def iterative_bfs(start_v): discovered = [start_v] queue = [start_v] while queue: v = queue.pop(0) for w in graph[v]: if w not in discovered: discovered.append(w) queue.append(w) return discovered
- 참고로 트리구조도 그래프 구조에 속해있지만, '순환'이 있고 없고에 따라 그래프 그리고 트리 로 나뉘어집니다.
요약
그래프의 활용에 따라 그래프를 어떻게 표현할지 선택하는게 중요합니다. 그래프 인접 행렬과 그래프 인접 리스트에 따라 그 장단이 뚜렷하기에 때문인데요. 이 선택의 지표로는 주로 그래프 밀도 분포를 계산하여 확인합니다. 밀도 분포가 power-law 를 띄거나 normal 를 띄거나 하는 등에 따라 엣지가 희소한지 밀집한지를 간접적으로 확인할 수 있기에, 이 과정을 차트 형태로 시각화하는 작업이 필요하다고 할 수 있습니다.
2. 그래프 데이터가 왜 FDS 에서?
- 그렇다면 왜 그래프 데이터를 금융 FDS에서 사용하는 걸까? 기존 방식 부터 살펴보고 무슨 한계점이 존재하고 그 한계점을 어떻게 그래프가 보완할 수 있는지에 대해 이야기해보겠다.
- 한 줄로 간단하게 말해보자면 그래프 적용 전 후에 따라 상관성 적용 편의성이 적어지고 커진다고 할 수 있다. 기존 방식인 그래프 적용 전에는 이상 거래에 대해 판단할 때 해당 유저의 과거 거래 데이터를 활용한다. 잠시 , 과거 거래 데이터에 더욱 명확히 이야기해보자면, 필자도 작성하며 과거 데이터 하위 개념으로 내역데이터과 이력데이터 두 가지 데이터 관리 형태로 표현됨을 처음 알았다. 내역데이터는 변경이 되는 데이터고 이력데이터는 변경이 되지않은 형태로 쌓이는 데이터라고 보면 된다. 금융 관점에서 이야기하면 나의 계좌 잔액은 지속적으로 변하기에 내역 데이터이고, 내가 송금한 거래 데이터는 불변하기에 이력데이터라고 할 수 있다.
- 다시 돌아와서, 결국 내 계좌 잔액인 이력 데이터 측면 과거데이터와 과거 타 매체와 거래한 내역인 내역 데이터 측면 과거데이터 두 부분을 모두 고려하며 이상 유무를 판단해야한다라고 볼 수 있다.데이터 설계 측면에서 이를 과연 한 테이블에 두었을까 ?라는 근본적인 물음을 해본다면, 나는 아닐것이다 라고 생각한다. 결국 여기에 이 과거 데이터들의 유무를 확인하기 위해 관계 조회(조인)이 발생하게 되는것이다.
- 엄밀히 말해보면, 개인의 데이터라 하더라도 결국 과거 데이터 속에서 관계를 확인하는 작업이 필요함을 간접적으로 암시한다.방금 언급한 '과거 데이터'를 내역 그리고 이력으로 나누었는데 이를 금융권에선 '원장 데이터'와 '거래 데이터'라고 지칭한다. 원장이라 함은 원본장부의 줄임말이며, 데이터간 중복이 발생할 때 원장 데이터를 기준으로 데이터 무결성을 판단한다. 그러기에, 데이터 무결성을 판단할 기준을 한 마스터 테이블에 저장하고 관리하기에 그 관리해야할 요소 양이 방대할 수 밖에 없으며, 특정 데이터를 조회할 때 그 방대함 속에서 원하는 데이터를 추출해야하기에 부득이하게 많은 조인 연산이 들 수 밖에 없다. 반면 '거래 데이터' 는 거래 확정 시점에 적혀있는 매체간의 거래 기록을 담아 놓은 데이터이다.
- 지금까지 잠시 동안 금융권 데이터 형태에 대해 이야기해보았는데, 기존에는 '개인'의 거래 여부를 확인하기 위해 굉장히 많은 요소들이 개입되고 있음을 알아보았습니다. 여기에 '개인'의 거래가 현존하는 FDS 룰을 위배하는지, 준수하는지를 필터링을 통해 판단해야하기에 소요되는 작업들이 굉장히 많다고 할 수 있습니다.
- 개인의 특성을 파악하는데도 이렇게 챌린징이 많은데 추가로 저희는 거래 데이터 내에서 입금 출금 송금 세 가지 거래에서 대상이 어떤 형태로 이루어져 있는지도 면밀히 확인해야합니다. 예를 들어, 아래 그림으로 표현해보자면
- 제가 거래를 했는데 '평소'와 다른 '금액'을 유지민이라는 '대상' 에게 '압구정' 은행 이라는 채널을 통해 전달한 정황이 포착되었습니다. 이 때, 과거 데이터로부터 '평소' 라는 것에 대한 기준을 가져와, 현재 거래 데이터를 비교해야합니다. 추가로 '평소'와 별다른 바가 없다 하더라도 각 은행권에서 설계해놓은 FDS 패턴과 유사한지에 대해 추가 비교를 하게됩니다. 짐작하시겠지만, 이 과정에서 소요되는 조인연산이 굉장히 많이 필요합니다. 이 때, 활용 측면에서 그래프가 유리한데요. 이를 데이터 베이스 관점에서 언급하면 '정규화'를 얼마나 진행했는지 다시 말해, 얼마나 데이터 테이블들이 분산되어 있는지가 그래프 효율성과 밀접한 상관성이 있다고 할 수 있습니다.
- 예를 들어, 데이터 관리를 위해 여러개의 테이블로 나누어진 데이터가 있다고하면 이 데이터와 연관되어 있는 정보를 추추하기 위해 각 테이블들을 모두 탐색하며 그 관계를 도출하여야 하기에 여기에서 발생하는 연산이 비효율적이라고 할 수 있습니다. 반대로 생각해보면, 비정규화된 테이블들이 많을수록 테이블마다 정보를 확인하는 과정이 상대적으로 적기에 오히려 그래프 데이터 형태가 장점을 어필할 수 있는 부분이 적어진다 라고 할 수 있습니다.
- 어떤점에서 유리한지 말씀드려보자면, 다음 두 가지로 볼 수 있습니다.
1)스키마리스
- RDB 와 GDB , SQL 과 NoSQL 두 개념의 차이를 언급할 때 주로 활용되는 표현입니다. 구조에 연연하지 않고 데이터를 다룰 수 있다는게 스키마리스를 의미합니다. 한가지를 예로 들어 설명해보겠습니다. 요즘 마이데이터 덕분에 저희는 자기가 보유하고 있는 모든 금융 통신 등의 내역을 플랫폼에서 확인할 수 있게 되었는데요. 때문에 각기 다른 형태의 데이터들을 가져올 때 데이터 정합성을 우선 점검하게 됩니다.
- 제가 A플랫폼에서 A카드를 가지고 결제한 내역이 B 플랫폼에서 확인했을시 A카드+@ 라고 나타날 시, 이 데이터는 동일 데이터가 아니기 때문이죠. 이러한 상황이 발생하게된다면, 거래내역에 대한 불신이 생기고 그에 따라 플랫폼에 대한 불신이 생기기에 유저 이탈이 발생할 여지가 큽니다. 그래서 이를 중개하여 각 데이터를 표준화하는 업무가 따로 배치될 만큼 그 정합성에 대해 많은 노력을 기울이고 있습니다. 잠시 이야기가 샜는데요. 여기에서 만약 평소 A 카드로 거래했던 제가 새로운 카드를 B를 개통하여 첫 거래만 진행한 후 이후 다시 A카드를 사용한다고 해보겠습니다. 거래내역을 기록해야하기에 이때, 테이블형태로 보면 B카드를 위한 새로운 컬럼이 발생하게 됩니다. 단 하나의 거래내역과 카드 정보를 반영하기 위해서말이죠.
- 정합성 측면에서 굉장히 합리적인 선택이라 하지만, 한 내역을 증빙하기 위해 낭비되는 공간이 발생하기에 비효율적인 선택이라고 볼 수 있습니다. 동일한 상황에서 NoSQL 그래프를 사용한다면, 단순히 노드 그리고 엣지 각각 한개만을 추가하면되기에, 공간의 낭비가 줄어들게 됩니다. 이처럼 기존 테이블 형태에 구속받지 않고 새로운 정보에 대해 Update Delete 등의 연산이 유연하다는 게 그래프의 장점이라고 할 수 있습니다.
- 위 그림은 B카드를 기반으로 거래가 발생할 시 RDB 그리고 GDB 에서는 어떻게 관리할지에 대해 표현한 그림입니다. RDB는 거래 내역과 이력을 추가로 적용하기 위해 행과 열이 증가합니다. 이 때, B카드의 추가 특성인 여신거래가능 기능을 포함하여 적용해야하기에 평이한 카드특성ABC에 추가로 열을 만들어주어야합니다. 만일 여러개의 카드 여러개의 특성들이 있다고 생각해보면, 이 하나의 특성을 표현하기 위해 낭비되는 공간이 어마어마한거죠. 반면에, 그래프로 표현한다면 간단합니다. 거래내역을 엣지에 그리고 카드 특성을 노드 각각의 프로퍼티에 담아줍니다.
- 이는, 현대 사회에서 핵심 가치인 편의성을 고려한 핀테크(금융)에서 발생할 여지가 큰 부분입니다. 새롭고 신속함에 중독되어있는 요즘세대에서 다양한 데이터들이 발생하기 마련인데 이 데이터들이 발생할때마다 그 특성을 모두 관리하여야하기에 위와 같은 경우가 빈번하게 발생합니다. 이 측면에서 스키마리스라는 특성이 스키마 없이 데이터를 관리 및 저장할 수 있기에 유연하다라는 측면에서 각광받고 있습니다.
2) 상관성
- 그림4 을 보시면 '송금하다'라는 특성을 기반으로 연결된 3개의 각기 다른 Account 노드를 확인할 수 있습니다. 말장난일수도 있지만 나의 Account 에서 송금한 Account 가 송금한 Account 은 과연 무슨 관련이 있을까요? 이를 확인하기 위해서는 그래프는 간단하게 '송금하다'라는 관계로 연관되어 있는 경로들을 조회하여 이 경로에 포함되어 있는 노드들을 조회하여 분석을 하면 됩니다.
- 이처럼 거래에 대한 상관성을 굉장히 쉽고 신속하게 그리고 직관적으로 분석할 수 있다는 점에서 그래프가 각광받고 있습니다.
- 그림을 통해 기존 방식과 그래프 방식을 비교해볼게요.
- 기존에는 단순히 '자신'의 거래를 기반으로 이상하다 라는 기준을 판단한다는 것 대비 그래프 방식은 나와 거래한 대상이 주로 어떤 패턴으로 거래했는지에 대해서도 고려하기에 이상하다 라는 기준을 확대해서 해석을 할 수 있다는 점이 장점이자 차이점이라고 할 수 있습니다. 예를 들면, 제가 거래한 계좌가 저 뿐만아니라, 다른 계좌로부터 받은 재화들 대다수가 이상한 송금 거래였다면 이는 사기 거래일 확률이 높다 라고 판단할 수 있어 제재를 가하기 위한 근거로써 유의미하다는거죠.
- 결국 제재에 대한 판단 근거를 확대해서 판정할 수 있기에 사기 판단에 대한 문맥을 추가로 고려할 수 있다는게 그래프 방식, FDS의 장점이라고 정리할 수 있겠네요.
요약
이상탐지 분야에서 그래프의 장점은 크게 1.스키마리스 2. 상관성 이라고 할 수 있습니다. 기존 관점에서 확대하여 거래에 대한 맥락을 추가로 반영하기에 사기 패턴탐지 정밀도를 높일 수 있고 미처 탐지하지 못한 패턴을 발견하여 잠재적인 위험을 파악할 수 있고 대처할 수 있다는게 FDS 에서 그래프의 장점이라고 할 수 있습니다.
3. 기존 데이터에서 그래프 데이터형태로 변형하기 위해 거쳐야 하는 다섯 가지 과정들.
- 지금까지 그래프와 FDS에 대해 알아보았습니다. 그래프를 활용하기 위해서 먼저 '그래프' 형태의 데이터가 필요하겠죠? 생각해보면, 현실에서 그래프 데이터가 떡하니 실무 환경에서 여러분들을 기다리는 경우는 굉장히 드뭅니다. 만일, 그래프 데이터가 존재한다 하더라도, 그래프 데이터 형태로 변환한 실무자인 데이터 설계자의 의도를 이해하는 작업이 선행되어야 효율적으로 그래프 데이터를 활용할 수 있습니다.
- 본 섹션에서는 원시 데이터인 테이블 데이터를 그래프 데이터로 변환하는 작업을 여러분들에게 전달하는 것이 목적이기에 이 과정에 대해 이야기 해보겠습니다. 그래프 데이터는 1. 문제 정의 2. 기존 데이터 이해 3. 관계 생성 4. 그래프 시각화 5. 시나리오 점검 이렇게 다섯 가지 절차를 거치며 탄생하게 됩니다. FDS에 그래프를 적용한다는 전제하에 어떻게 과정이 진행되는지 나열해보겠습니다.
1) 문제 정의
- FDS의 최종 목적은 결국 사기 패턴 탐지입니다. 과연 패턴을 탐지하기 위해선 무엇이 필요할까요? 이 근본적인 질문에 답할 수 있게 고민을 해봐야 합니다. 그래프 방식은 기존 방식과 다르게 상관성을 활용해 미처 발견하지 못한 사기 패턴에 연관된 매체들을 탐지하고, 더 나아가 패턴에 연관된 그래프와 연관이 없는 그래프를 기계학습에 적용하여 패턴 간 차이점을 정량화합니다. '데이터 간 연관성 극대화', '패턴 정량화'를 목표로 합니다.
2) 기존 데이터 이해
- 금융 시스템에서는 이력 데이터와 내역 데이터 두 가지 형태로 다뤄진다고 가정합니다. 기존 데이터를 잘 이해하기 위해서는 그래프를 활용하기 위한 FDS에서 필요한 전처리 작업이 필요합니다. 이력 데이터와 내역 데이터 중 어떤 정보가 이상 패턴을 탐지하는 데 도움이 될지를 선별하는 시간이라고 할 수 있습니다. 기존 방식은 이 데이터를 모두 고려하여 진행하겠지만, 그래프 측면에서는 스키마리스라는 특성을 최대한 활용하는 것이 핵심입니다. 유연성 있는 모델링을 위해서는 기존의 관점과는 다르게 문제를 해결할 수 있는 그래프의 관점을 적극적으로 채택하여 데이터를 이해해야 합니다.
3) 관계 생성 및 그래프 프로퍼티 할당
- 문제 정의 단계에서는 사기 패턴에 '연관'되어 있는 매체들을 탐지하기 위한 최종 목표를 설정했습니다. 이 목표를 달성하기 위해 기존 데이터를 이해한 배경지식을 기반으로 데이터 간의 관계를 생성합니다. 관계가 설정되었으면, 나열되어 있는 그래프 내 노드와 관계에 어떤 특성들이 반영되면 좋을지에 대해 고민해야합니다. 이때, 노드의 특성인 프로퍼티를 다른 노드로 간주하여 새로운 노드로 표현할 수 있고 반대로 특정 노드를 프로퍼티로 간주하는 경우도 발생합니다.
- 그래프 모델링 2를 선택하게 된다면 상점과 연결되어 있는 카드를 기반으로 유저들 패턴을 볼 수 있겠고, 그래프 모델링 3을 선택하게 된다면 상점과 연결되어 있는 거래들을 기반으로 유저들 패턴을 볼 수 있습니다. 이처럼 ‘무엇’에 중점을 두느냐에 따라 그래프가 다르기 때문에 이 부분에서 늘 문제정의 그리고 그래프의 목적에 대해 상기하며 그래프를 모델링하는것이 중요합니다.
4) 그래프 시각화
- 앞서 3)단계 에서 생성한 그래프를 그래프 데이터베이스에 적재합니다. 이 후, ‘사기’와 연관되어 있는 노드들을 데이터베이스 질의문인 Cypher로 조회합니다. 조회 결과를 정상/이상 거래 패턴 및 거래 간 연관성을 명확하게 파악합니다.
5) 시나리오 점검 (문제 해결을 위한 커뮤니케이션)
- 4) 까지 진행한 상황을 각 팀 관계자분들과 협의하는 과정입니다. 그래프 모델링은 주관이 많이 반영되는 분야이기에, 객관성을 반영하기 위한 작업이라고 할 수 있습니다. 처음 문제정의부터 왜 그래프를 이렇게 디자인했는지 까지 논의하며 이를 통해 얻게 되는 프로토타이핑 , 기대결과 그리고 비즈니스 임팩트까지 이 과정을 통해 조율하게 됩니다.
그래프 모델링
온라인상에서 마주하는 잘 정돈되어있는 그래프 형태 데이터와 달리 현실 대다수 데이터들은 정돈되어 있지않은 원시 데이터 형태로 저희를 기다리고 있습니다. 이 원시 데이터로부터 관계를 추출하여 저희가 사전에 그래프 기획 단계에서 정의한 문제들을 해결하는게 핵심인 단계입니다. 구체적으로는, 데이터 웨어하우스 & 데이터 레이크에 보관되어 있는 여러 테이블 형태의 데이터들을 그래프 형태로 바꿔야 하는거죠. 이를 그래프 ETL & ELT , 그래프 디자인 , 그래프 모델링 등 상황에 따라 다르게 부르곤하는데, 저는 주로 그래프 모델링 이라고 부릅니다.
- 마지막으로는 이 섹션에서 언급한 그래프 데이터 모델링을 할 때 유용한 툴을 소개시켜 드리려고해요. 'arrows.app'이라는 앱입니다. neo4j 에서 개발한 앱입니다. 그래프 스키마를 설계하는데 노드 / 관계마다 각각 레이블 , 프로퍼티를 어떻게 설정할것이며 이에 따라 두께 크기 색깔을 어떻게 정할지 커스터마이징까지 할 수있는 앱입니다.
- share 나 download/export 탭을 활용하여, 디자인 보드 내에 디자인 된 그래프 스키마 공유도 가능합니다. 추가로, export 에서 Cypher GraphQL 탭을 클릭하신다면, 디자인한 그래프 스키마를 바로 neo4j 에 적재하여 어떤식으로 시각화되는지도 확인도 가능하기에 그래프 모델링 진행시에 굉장히 편리합니다.
- https://neo4j.com/labs/arrows/ 에서 상세 내역을 볼 수 있습니다
요약
그래프 모델링은 뚜렷한 공식, 정답이 없는 분야라고 할 수 있습니다. 다시 말해서, 그래프 디자인하는 실무자의 주관이 많이 개입되는 분야라고 할 수 있습니다. 그래프 설계자가 문제 정의를 어떻게 하느냐에 따라 그래프 구조가 달라지고, 그 구조에 따라 패턴을 질의하는 방식 그리고 더 나아가 딥러닝의 추론 결과까지 달라지기에 그래프 모델링 과정이 가장 중요하다 라고 할 수 있습니다.
Reference
- DB정규화, 왜 하는가? / https://greypencil.tistory.com/125
- 거래데이터와 원장데이터, 두 개는 다르다. / https://greypencil.tistory.com/87
- 이력 데이터와 내역 데이터 2 / https://dataprofessional.tistory.com/43
- bfs,dfs 알고리즘 그림 / https://open4tech.com/bfs-vs-dfs/
Share article