본문으로 건너뛰기
Tech

최근 아티클

최근 아티클을 표시합니다.
    Research8 MIN

    점포·건물·격자를 매출 예측용 그래프로 연결하는 방법

    소속·거리·격자 식별자를 구분해 점포와 건물, 배후지를 이종그래프로 연결하기

    A점포는 B건물에 입점해 있습니다. 카드 자료에는 A점포가 참조하는 격자가 G격자로 기록돼 있습니다. B건물에서는 면적을, G격자에서는 주변 인구를 가져옵니다. 모두 A점포의 주변 정보지만 연결하는 근거는 다릅니다.

    A점포와 B건물은 건물 소속을 확인하고, A점포와 G격자는 격자 식별자를 대조합니다. 가까운 격자를 대신 붙이면 카드 자료에 기록된 곳과 다른 지역의 정보를 읽을 수 있습니다. 이 글의 점포·건물·격자는 이 차이를 설명하기 위한 가상 사례입니다.

    1편이 자료의 범위와 시점을 다뤘다면, 이번에는 소속·거리·식별자로 관계를 구성하고 학습 데이터로 옮기는 과정을 살펴봅니다.

    다양한 공간정보를 서로 다른 노드로 유지하고 공간 관계로 연결한 그림

    점포와 건물을 따로 남겨 연결합니다

    A점포의 매출표에 B건물의 면적을 붙이면 건물 크기를 알 수 있습니다. 하지만 그 숫자만으로는 다른 점포도 B건물에 입점해 있는지 알기 어렵습니다. 표에 이런 관계를 넣으려면 이웃을 어떤 값으로 요약할지 먼저 정해야 합니다.

    여기서는 A점포와 B건물을 따로 남기고 둘 사이에 연결을 둡니다. 점포·건물 같은 대상이 노드, 그 사이의 연결이 간선입니다. 점포·건물·격자처럼 종류가 다른 대상을 함께 담아 이종그래프라고 부릅니다. 점포는 POI로 표기합니다.

    노드담는 정보원천과 연결하는 식별자
    POI과거 매출, 업종원천 POI 식별자
    건축물면적, 형상, 주변 밀도건축물 관리번호
    배후지인구·가구·소득·종사자, 교통·토지이용100m 격자 식별자

    A점포의 매출을 예측할 때 B건물과 G격자는 주변 환경을 설명합니다. 기본 구성에서는 지역 통계를 담는 배후지로 100m 격자를 씁니다. 상권 권역을 쓰는 경우는 뒤에서 따로 구분합니다.

    같은 건물의 C점포와 이웃 D건물은 B건물을 거쳐 A점포로 이어집니다. 이웃 H격자는 G격자를 통해 A점포와 연결됩니다.

    A점포·C점포, B건물·D건물, G격자·H격자의 기본 관계 네트워크. C점포와 D건물은 B건물을 거쳐 A점포로, H격자는 G격자를 거쳐 A점포로 연결된다

    샘플링 전 가능한 경로입니다. A점포를 향하는 방향을 강조했으며, 역방향과 건물–격자 관계 등 일부 간선은 생략했습니다.

    동네의 건물과 점포를 관계로 읽으면

    동네 위에서 보면 A점포와 C점포는 B건물 안에 있고, D건물은 길 건너편에 있습니다. G격자와 H격자의 경계는 도로·건물 경계와 별개입니다.

    가상 동네의 도로와 건물 위에 A점포·C점포, B건물·D건물, G격자·H격자와 정보 전달 경로를 겹쳐 놓은 평면도

    실측 지도가 아닌 설명용 동네입니다. 화살표는 보행 경로가 아닌 가능한 정보 전달 방향이며, 역방향과 건물–격자 관계 등 일부 간선은 생략했습니다. A점포와 G격자의 연결 근거는 지도상의 포함 여부가 아니라 원천의 격자 식별자 일치입니다.

    연결 기준은 다음 네 관계군으로 나눕니다.

    소속 건물을 연결합니다

    A점포가 B건물에 입점했음을 확인하면 두 방향으로 연결합니다. A점포에서 소속 건물로 보내는 관계는 belongs_to, B건물에서 입점 점포로 보내는 관계는 contains라고 부릅니다. 영문은 코드에서 사용하는 관계 이름입니다.

    같은 소속 관계라도 A점포 → B건물은 점포 정보를, B건물 → A점포는 건물 정보를 전달하므로 방향을 구분합니다.

    같은 타입의 이웃을 찾습니다

    중심점 사이 거리가 100m 안인 건물들을 서로 연결합니다. 이 가까운 건물 연결의 코드 이름이 adjacent입니다. 검색에는 가까운 좌표를 빠르게 찾는 cKDTree를 사용합니다.

    그림의 B건물과 D건물은 이 조건을 만족한다고 가정했습니다. 보행 가능성을 기준으로 연결한 것은 아닙니다.

    100m 격자는 중심점에서 150m 안의 이웃 격자와 서로 연결합니다. 이 이웃 격자 연결을 neighbors라고 부릅니다. 같은 거리 기반이어도 건물 이웃과는 다른 관계입니다.

    건물 주변 격자를 연결합니다

    건물 주변의 지역 정보를 읽기 위해 중심에서 500m 반경 안의 격자를 연결합니다. 이 관계는 위 그림에서 생략했습니다.

    건물에서 주변 격자로 보내는 관계는 situated_in, 주변 격자에서 건물로 보내는 관계는 covers입니다. 이름과 달리 지도상의 포함 여부가 아니라 반경으로 연결합니다. 거리가 멀수록 낮아지는 감쇠값을 간선 속성으로 기록하되, 모델이 학습한 정보의 비중인 attention까지 거리에 따라 반드시 감소하는 것은 아닙니다.

    통행 저해 요소와 권역 구분 열은 원천에 값이 없어 상수로 채웁니다. 실제 관측값이 아니며, 현재 이 관계에서 간선마다 달라지는 신호는 거리 감쇠값입니다.

    격자 식별자를 대조합니다

    A점포는 카드 자료와 불러온 100m 격자의 식별자가 정확히 일치할 때만 G격자와 연결합니다. 점포에서 일치하는 격자로 보내는 관계는 directly_in, 격자에서 해당 점포로 보내는 관계는 reaches입니다. 거리나 지도상의 포함 여부로 새로 판정하지 않습니다.

    POI의 격자 식별자 = 로드한 격자의 식별자
      → 점포와 해당 격자를 양방향으로 연결
    
    식별자 없음 또는 해당 격자가 로드되지 않음
      → 가까운 격자로 대체하지 않고 미연결 사유 기록

    연결 방향에 따라 이름을 나눕니다

    A점포 → B건물과 B건물 → A점포는 같은 대상을 잇지만 서로 다른 정보를 보냅니다. 그래서 방향별로 이름을 붙입니다. 건물–격자와 점포–격자 연결도 둘씩 나누고, 건물 이웃과 격자 이웃을 더하면 여덟 관계 타입이 됩니다.

    가까운 건물 연결과 이웃 격자 연결은 양방향이어도 같은 이름을 씁니다. 연결선의 개수와 관계 타입 수는 다릅니다. 그림에서는 쉬운 표현을 쓰고, 코드 이름은 아래 표에서 대응시켰습니다.

    출발 노드코드 이름도착 노드쉬운 표현
    건축물adjacent건축물가까운 건물 연결
    POIbelongs_to건축물소속 건물로
    건축물containsPOI입점 점포로
    건축물situated_in배후지주변 격자로
    배후지covers건축물주변 격자에서 건물로
    배후지neighbors배후지이웃 격자 연결
    POIdirectly_in배후지식별자가 일치하는 격자로
    배후지reachesPOI해당 점포로

    기본 그래프를 만들 때는 이 여덟 타입이 있는지 확인합니다. 모든 연결을 매번 계산에 쓰는 것은 아니며, 예측에 도움이 되는지도 따로 검증해야 합니다.

    점포의 정보와 연결을 나눠 담습니다

    A점포의 과거 매출은 점포 정보에, B건물의 면적은 건물 정보에 담습니다. G격자의 인구도 격자 정보로 따로 둡니다. B건물 → A점포와 G격자 → A점포의 연결에는 누가 누구에게 정보를 보내는지와 관계 이름을 기록합니다.

    B건물·A점포·G격자의 입력 정보를 종류별로 담고, 건물에서 입점 점포로 보내는 연결과 격자에서 해당 점포로 보내는 연결을 별도로 보존하는 학습 데이터 변환 개념도

    번호와 입력 항목은 설명용이며 실제 수치·차원은 생략했습니다. A점포의 다음 달 매출 정답은 입력과 분리합니다. 나머지 저장 항목은 아래 표와 같습니다.

    모델이 읽을 때는 A점포·B건물·G격자 대신 번호를 씁니다. 각 종류 안에서 원본 식별자를 정렬해 번호를 붙이고, 원래 대상을 찾을 대응표를 남깁니다. 세 대상이 모두 0번이어도 점포·건물·격자 배열에 따로 있으므로 섞이지 않습니다.

    이렇게 정보를 숫자 배열인 텐서(tensor)에 담습니다. 구현에서는 NetworkX의 MultiDiGraph를 PyTorch Geometric의 HeteroData로 바꾸며, 저장 위치는 다음과 같습니다.

    그래프에 있던 정보학습 데이터의 위치
    POI·건축물·배후지 노드각각 lower·upper·hinter
    타입별 노드 피처각 노드 타입의 x
    POI의 다음 달 매출 정답lower.y
    관계별 출발·도착 노드의 인덱스edge_index
    거리 감쇠 등 관계별 속성edge_attr
    학습·검증·시험에 사용할 POI 구분예측 대상 POI의 마스크

    A점포의 다음 달 매출 정답은 lower.y에 따로 담습니다. 이 학습용 경로는 정답이 없으면 중단하므로, 미래 예측에는 그대로 쓸 수 없습니다. 정답 없는 입력을 처리하는 경로는 7편에서 확인 과제로 다룹니다.

    변환이 끝나면 다음 세 가지를 확인합니다.

    • 번호에서 A점포의 원래 카드 행을 다시 찾을 수 있는지 확인합니다.
    • A점포–B건물과 A점포–G격자의 관계·방향이 남아 있는지 봅니다. 세 노드 타입과 여덟 관계 타입, 간선 수와 직접 격자 결합률도 확인합니다.
    • 입력·정답·간선 속성의 위치와 크기가 맞는지, 학습·검증·시험 점포가 겹치지 않는지 검사합니다.

    격자 대신 상권 권역을 쓰면 연결도 달라집니다

    A점포 주변의 다른 점포를 업종과 거리로 직접 연결하는 구성도 있습니다. 경쟁·보완 후보를 잇는 co-location 실험입니다. 기본 그래프에 선 두 종류만 더하는 것이 아니라, 주변 정보를 담는 공간 단위부터 100m 격자에서 상권 권역으로 바꿉니다.

    구분기본 구성co-location 실험
    배후지 노드100m 격자상권 권역
    건축물 ↔ 배후지500m 반경 안의 여러 격자권역 1:1 연결
    배후지 ↔ 배후지격자 인접권역 간 근접
    POI ↔ 배후지격자 식별자 일치없음
    POI ↔ POI없음complements · competes
    전체 관계 타입 수88

    300m 이내의 점포 중 같은 대분류이면서 중분류가 다르면 보완 후보(complements), 같은 중분류이면 경쟁 후보(competes)로 양방향 연결합니다. 업종과 거리로 정한 후보 관계이지, 실제 경쟁·보완 효과를 확인한 것은 아닙니다.

    점포끼리 직접 연결할 때는 매출 이력이 전달되지 않도록 입력 항목을 제한합니다. 다만 건물을 거쳐 정보가 오가는 간접 경로까지 막는 것은 아닙니다.

    격자 노드가 없으므로 directly_in과 reaches는 쓰지 않으며, 두 구성을 함께 켜면 구축 단계에서 중단합니다. 관계 타입 수가 같아도 같은 그래프는 아닙니다.

    실험에서 사용한 관계와 성능에 따른 채택 여부는 6편에서 살펴봅니다.

    연결된 이웃을 어디까지 읽을지 정합니다

    A점포에서 B건물과 G격자를 찾고, 다시 그 이웃을 따라가면 읽을 대상이 늘어납니다. 연결을 만들었다면 그중 어디까지 한 번에 계산할지도 정해야 합니다.

    3편(공개 예정)에서는 같은 점포·건물·격자에서 이웃을 골라 학습 배치를 만들고, 정보를 제공하는 점포와 정답을 비교할 점포를 구분합니다.

    에

    에이전트파트

    다양한 데이터와 AI Agent 기술을 연결해 사용자의 의사결정을 돕습니다.

    다른 글