Wykrywanie oszustw za pomocą BigQuery Graph

1. Wprowadzenie

Marketing Header - Fraud in Fintech

Nieuczciwe działanie często obejmuje ukryte sieci powiązanych encji, np. wiele kont, które mają ten sam adres e-mail, numer telefonu lub adres pocztowy. Tradycyjne relacyjne bazy danych mogą mieć problemy z wydajnym wykonywaniem zapytań dotyczących tych złożonych relacji wieloetapowych.

BigQuery Graph umożliwia analizowanie tych sieci na dużą skalę za pomocą baz danych grafów. Możesz zdefiniować wykres właściwości na podstawie istniejących tabel BigQuery i używać języka zapytań do wykresów (GQL) do znajdowania wzorców w danych.

Częstym zastosowaniem sieci grafów w wykrywaniu oszustw jest blokowanie zamówień z adresem dostawy powiązanym z siecią oszustw lub blokowanie płatności należących do .

W tym ćwiczeniu utworzysz rozwiązanie do wykrywania oszustw za pomocą BigQuery Graph. Wczytasz dane z Cloud Storage, utworzysz graf właściwości i użyjesz zapytań do grafu, aby zidentyfikować podejrzane połączenia.

Czego się nauczysz

  • Jak utworzyć zbiór danych BigQuery i wczytać dane.
  • Jak zdefiniować graf właściwości za pomocą DDL.
  • Jak wysyłać zapytania do grafu za pomocą języka GQL.
  • Jak wykrywać oszustwa za pomocą analizy grafów.

Czego potrzebujesz

  • Projekt Google Cloud z włączonymi płatnościami.
  • Środowisko notatnika BigQuery (BigQuery Studio lub Colab Enterprise).

Koszt

W tym module używane są płatne zasoby Google Cloud. Szacowany koszt to mniej niż 5 USD, przy założeniu, że po zakończeniu usuniesz zasoby.

2. Zanim zaczniesz

Wybieranie lub tworzenie projektu w chmurze Google Cloud

  1. W konsoli Google Cloud na stronie selektora projektów wybierz lub utwórz projekt w chmurze Google Cloud.
  2. Sprawdź, czy w projekcie Google Cloud włączone są płatności. Dowiedz się, jak sprawdzić, czy płatności są włączone.

Wybierz środowisko

Aby ukończyć ten moduł, potrzebujesz środowiska notatnika. Możesz użyć BigQuery Studio lub Colab Enterprise.

  1. Otwórz stronę BigQuery w konsoli Google Cloud.
  2. Do uruchamiania zapytań o grafy będziesz używać notatnika w Pythonie.

Uruchamianie Cloud Shell

  1. Kliknij Aktywuj Cloud Shell u góry konsoli Google Cloud.
  2. Potwierdź uwierzytelnianie:
gcloud auth list
  1. Potwierdź projekt:
gcloud config get project
  1. W razie potrzeby ustaw:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID

Włącz interfejsy API

Aby włączyć wymagany interfejs BigQuery API, uruchom to polecenie:

gcloud services enable bigquery.googleapis.com

3. Wczytaj dane

W tym kroku utworzysz zbiór danych BigQuery i wczytasz przykładowe dane z Cloud Storage.

Przykładowe dane składają się z kilku plików CSV przedstawiających symulowane środowisko sprzedaży detalicznej:

  • customers.csv: informacje o koncie klienta,
  • emails.csv: Adresy e-mail.
  • phones.csv: numery telefonów.
  • addresses.csv: adresy pocztowe,
  • customer_emails.csv, customer_phones.csv, customer_addresses.csv: łączenie tabel.
  • orders.csv: historia zamówień, w tym oznaczenia oszustw;

Tworzenie zbioru danych

Utwórz zbiór danych o nazwie fraud_demo, w którym będą przechowywane tabele.

  1. W tym ćwiczeniu będziemy wykonywać polecenia SQL. Te polecenia możesz uruchomić w BigQuery Studio > Edytor SQL lub użyć polecenia bq query w Cloud Shell. Nowe zapytanie SQLZakładamy, że używasz edytora SQL BigQuery, aby zapewnić sobie lepsze wrażenia podczas tworzenia instrukcji wielowierszowych.
CREATE SCHEMA IF NOT EXISTS `fraud_demo` OPTIONS(location="US");

Wczytywanie tabel

Aby wczytać dane z Cloud Storage do zbioru danych, uruchom te instrukcje SQL.

LOAD DATA OVERWRITE `fraud_demo.customers`
FROM FILES (
  format = 'CSV',
  uris = ['gs://sample-data-and-media/fraud-demo-data/customers.csv'],
  skip_leading_rows = 1
);

LOAD DATA OVERWRITE `fraud_demo.emails`
FROM FILES (
  format = 'CSV',
  uris = ['gs://sample-data-and-media/fraud-demo-data/emails.csv'],
  skip_leading_rows = 1
);

LOAD DATA OVERWRITE `fraud_demo.phones`
FROM FILES (
  format = 'CSV',
  uris = ['gs://sample-data-and-media/fraud-demo-data/phones.csv'],
  skip_leading_rows = 1
);

LOAD DATA OVERWRITE `fraud_demo.addresses`
FROM FILES (
  format = 'CSV',
  uris = ['gs://sample-data-and-media/fraud-demo-data/addresses.csv'],
  skip_leading_rows = 1
);

LOAD DATA OVERWRITE `fraud_demo.customer_emails`
FROM FILES (
  format = 'CSV',
  uris = ['gs://sample-data-and-media/fraud-demo-data/customer_emails.csv'],
  skip_leading_rows = 1
);

LOAD DATA OVERWRITE `fraud_demo.customer_phones`
FROM FILES (
  format = 'CSV',
  uris = ['gs://sample-data-and-media/fraud-demo-data/customer_phones.csv'],
  skip_leading_rows = 1
);

LOAD DATA OVERWRITE `fraud_demo.customer_addresses`
FROM FILES (
  format = 'CSV',
  uris = ['gs://sample-data-and-media/fraud-demo-data/customer_addresses.csv'],
  skip_leading_rows = 1
);

LOAD DATA OVERWRITE `fraud_demo.orders`
FROM FILES (
  format = 'CSV',
  uris = ['gs://sample-data-and-media/fraud-demo-data/orders.csv'],
  skip_leading_rows = 1
);

4. Tworzenie wykresu właściwości

Po wczytaniu danych możesz zdefiniować wykres właściwości. Graf właściwości składa się z węzłów (encji) i krawędzi (relacji).

W tym laboratorium węzły to:

  • Klient: reprezentuje właściciela konta.
  • Telefon: reprezentuje numer telefonu.
  • Email: reprezentuje adres e-mail.
  • Address: reprezentuje adres pocztowy.

Krawędzie to:

  • OwnsPhone: łączy klienta z telefonem.
  • OwnsEmail: łączy klienta z adresem e-mail.
  • LinkedToAddress: łączy klienta z adresem.

Tworzenie wykresu

Aby utworzyć graf o nazwie FraudDemo w zbiorze danych fraud_demo, uruchom tę instrukcję DDL:

CREATE OR REPLACE PROPERTY GRAPH fraud_demo.FraudDemo
  NODE TABLES(
    fraud_demo.customers
      KEY(account_id)
      LABEL Customer PROPERTIES(
        account_id,
        name),

    fraud_demo.emails
      KEY(email)
      LABEL Email PROPERTIES(
        email,
        email_type),

    fraud_demo.phones
      KEY(phone_number)
      LABEL Phone PROPERTIES(
        phone_number,
        phone_type),

    fraud_demo.addresses
      KEY(address)
      LABEL Address PROPERTIES(
        address,
        address_type)
  )
  EDGE TABLES(
    fraud_demo.customer_emails
      KEY(account_id, email)
      SOURCE KEY(account_id) REFERENCES customers(account_id)
      DESTINATION KEY(email) REFERENCES emails(email)
      LABEL OwnsEmail PROPERTIES(
        account_id,
        email,
        last_updated_ts),

    fraud_demo.customer_phones
      KEY(account_id, phone_number)
      SOURCE KEY(account_id) REFERENCES customers(account_id)
      DESTINATION KEY(phone_number) REFERENCES phones(phone_number)
      LABEL OwnsPhone PROPERTIES(
        account_id,
        phone_number,
        last_updated_ts),

    fraud_demo.customer_addresses
      KEY(account_id, address)
      SOURCE KEY(account_id) REFERENCES customers(account_id)
      DESTINATION KEY(address) REFERENCES addresses(address)
      LABEL LinkedToAddress PROPERTIES(
        account_id,
        address,
        last_updated_ts)
  );

5. Analizowanie sieci (2 połączenia)

Otwórz Nowy notatnik w BigQuery Studio.

Utwórz nowy notatnik

W części tego ćwiczenia dotyczącej wizualizacji i rekomendacji użyjemy notatnika Google Colab w BigQuery Studio. Dzięki temu możemy łatwo wizualizować wyniki wykresu.

Notatnik grafów BigQuery jest zaimplementowany jako IPython Magics. Dodając polecenie magiczne %%bigquery z funkcją TO_JSON, możesz wizualizować wyniki w sposób pokazany w kolejnych sekcjach. W tym kroku uruchomisz zapytanie do grafu, aby znaleźć proste połączenia między kontami. Jest to zapytanie „2-hop”, ponieważ przemieszcza się 2 kroki od węzła początkowego, aby znaleźć powiązane węzły (np. Klient –> E-mail –> Klient).

Zaczniemy od zbadania konta należącego do Nicole Wade. Chcemy znaleźć wszystkie konta powiązane z nią w 2 krokach.

Uruchamianie zapytania 2-Hop Query

Uruchom w notatniku to zapytanie.

%%bigquery --graph
GRAPH fraud_demo.FraudDemo
MATCH 
 p=(a:Customer) 
  ( -[e:OwnsEmail|OwnsPhone|LinkedToAddress WHERE e.last_updated_ts < '2025-07-30']- (n) ){2}
WHERE a.account_id IN ("d2f1f992-d116-41b3-955b-6c76a3352657")
  -- Verify the final node in the hop array is a Customer
  AND 'Customer' IN UNNEST(LABELS(n[OFFSET(1)]))

RETURN TO_JSON(p) AS paths

Interpretowanie wyników

To zapytanie:

  1. Zaczyna się od węzła Customer z wartością account_id „d2f1f992-d116-41b3-955b-6c76a3352657” (Nicole Wade).
  2. Podąża za dowolną krawędzią OwnsEmail, OwnsPhone lub LinkedToAddress do węzła łączącego (Phone, Email lub Address).
  3. Podąża krawędziami z powrotem od tego węzła łączącego do innych węzłów Customer.
  4. Filtruje krawędzie na podstawie sygnatury czasowej (last_updated_ts), aby zobaczyć stan sieci w określonym czasie.

Powinno być widać, że Zachary CordovaBrenda Brown są połączeni z Nicole za pomocą tego samego adresu.

6. Analizowanie sieci (4 przeskoki)

W tym kroku rozszerzysz zapytanie, aby znaleźć bardziej złożone relacje. Będziemy szukać połączeń 4-hop. Dzięki temu możemy znajdować konta połączone za pomocą kilku podmiotów pośrednich (np. Klient A –> e-mail –> Klient B –> telefon –> Klient C).

Będziemy też obserwować, jak ta sieć zmienia się z czasem.

Stan „Przed”

Najpierw przyjrzyjmy się sieci w dniu 30 lipca 2025 r.

Uruchom poniższe zapytanie:

%%bigquery --graph
%%bigquery --graph

MATCH p= ANY SHORTEST (a:Customer) 
  ( -[e:OwnsEmail|OwnsPhone|LinkedToAddress WHERE e.last_updated_ts < '2025-07-30']- (n) ){3, 5}(reachable_a:Customer)
WHERE a.account_id IN ("d2f1f992-d116-41b3-955b-6c76a3352657")
  -- Ensure the final node in the dynamic chain is actually a Customer
  AND 'Customer' IN UNNEST(LABELS(n[OFFSET(ARRAY_LENGTH(n) - 1)]))
GRAPH fraud_demo.FraudDemo
RETURN 
  TO_JSON(p) AS paths,                   -- Array of all traversed edges
  ARRAY_LENGTH(e) AS hop_count

Stan „Po”

Zobaczmy teraz, jak wygląda sieć 2 tygodnie później. Uruchomimy to samo zapytanie, ale bez ograniczeń dotyczących daty.

Uruchom poniższe zapytanie:

%%bigquery --graph
GRAPH fraud_demo.FraudDemo
MATCH p= ANY SHORTEST (a:Customer) 
  ( -[e:OwnsEmail|OwnsPhone|LinkedToAddress]- (n) ){3, 5}(reachable_a:Customer)
WHERE a.account_id IN ("d2f1f992-d116-41b3-955b-6c76a3352657")
  -- Ensure the final node in the dynamic chain is actually a Customer
  AND 'Customer' IN UNNEST(LABELS(n[OFFSET(ARRAY_LENGTH(n) - 1)]))

RETURN 
  TO_JSON(p) AS paths,                   -- Array of all traversed edges
  ARRAY_LENGTH(e) AS hop_count

Interpretowanie wyników

Usuwając filtry daty, wysyłasz zapytanie dotyczące pełnego zbioru danych. Zauważysz, że sieć znacznie się rozrosła. Nicole Wade należy teraz do znacznie większej, dobrze powiązanej grupy. Szybkie rozszerzanie sieci połączonych urządzeń jest silnym wskaźnikiem potencjalnie nieuczciwych działań, takich jak udostępnianie zasobów przez grupę oszustów.

7. Generowanie raportu o oszustwie

W tym kroku połączysz analizę grafów z tradycyjnymi firmowymi bazami danych (zamówieniami), aby wygenerować kompleksowy raport o oszustwach. Będziesz rozpoznawać zagrożone konta i potencjalnie fałszywe zamówienia.

To zapytanie jest bardziej złożone. Używa funkcji GRAPH_TABLE do uruchamiania zapytania o graf w standardowej wersji SQL i oblicza zmianę rozmiaru sieci (diff) między stanami „przed” i „po”, które zaobserwowaliśmy w poprzednim kroku.

Uruchamianie zapytania raportu o oszustwach

Uruchom w notatniku to zapytanie.

%%bigquery --graph
WITH num_orders AS (
  SELECT account_id, COUNT(1) AS num_order
  FROM fraud_demo.orders
  WHERE order_time > '2025-07-30'
  GROUP BY account_id
),

orders AS (
  SELECT account_id, order_id, fraud, order_total
  FROM fraud_demo.orders
  WHERE order_time > '2025-07-30'
),

-- Use Quantified Path Patterns to find connections up to 4 hops away
latest_connect AS (
  SELECT 
    account_id, 
    ARRAY_LENGTH(ARRAY_AGG(DISTINCT connected_id)) AS size
  FROM GRAPH_TABLE(
    fraud_demo.FraudDemo
    MATCH (a:Customer)-[:OwnsEmail|OwnsPhone|LinkedToAddress]-{4}(connected:Customer)
    RETURN a.account_id AS account_id, connected.account_id AS connected_id
  )
  GROUP BY account_id
),

prev_connect AS (
  SELECT 
    account_id, 
    ARRAY_LENGTH(ARRAY_AGG(DISTINCT connected_id)) AS size
  FROM GRAPH_TABLE(
    fraud_demo.FraudDemo
    -- Apply the timestamp filter to EVERY edge in the 4-hop chain
    MATCH (a:Customer)
          (-[e:OwnsEmail|OwnsPhone|LinkedToAddress WHERE e.last_updated_ts < '2025-07-30']-(n)){4}
    WHERE 'Customer' IN UNNEST(LABELS(n[OFFSET(3)]))
    RETURN a.account_id AS account_id, n[OFFSET(3)].account_id AS connected_id
  )
  GROUP BY account_id
),

edge_changes AS (
  SELECT account_id, MAX(last_updated_ts) AS max_last_updated_ts
  FROM fraud_demo.customer_addresses
  GROUP BY account_id
)

SELECT
    la.account_id,
    o.order_id,
    la.size AS latest_size,
    COALESCE(pa.size, 0) AS previous_size,
    la.size - COALESCE(pa.size, 0) AS diff,
    nos.num_order,
    o.fraud AS reported_as_fraud,
    o.order_total,

    CASE
      WHEN (la.size - COALESCE(pa.size, 0)) > 10 AND nos.num_order IS NULL THEN "CUSTOMER AT RISK"
      WHEN (la.size - COALESCE(pa.size, 0)) > 10 AND nos.num_order IS NOT NULL AND o.fraud THEN "CONFIRMED FRAUD ORDER"
      WHEN (la.size - COALESCE(pa.size, 0)) > 10 AND nos.num_order IS NOT NULL AND NOT o.fraud THEN "POTENTIAL FRAUD ORDER"
      ELSE ""
    END AS notes
FROM latest_connect la
LEFT JOIN prev_connect pa ON la.account_id = pa.account_id
LEFT JOIN num_orders nos ON la.account_id = nos.account_id
LEFT JOIN orders o ON la.account_id = o.account_id
INNER JOIN edge_changes ec ON la.account_id = ec.account_id
WHERE nos.num_order > 1 OR (la.size - COALESCE(pa.size, 0)) > 10
ORDER BY diff DESC

Interpretowanie wyników

Ten raport zawiera:

  • account_id: identyfikator analizowanego konta.
  • order_id: Identyfikator ostatniego zamówienia.
  • latest_size: rozmiar połączonej sieci.
  • previous_size: rozmiar sieci 2 tygodnie temu;
  • diff: wzrost rozmiaru sieci;
  • num_order: liczba ostatnich zamówień.
  • reported_as_fraud: czy zamówienie zostało oznaczone jako oszukańcze.
  • order_total: łączna kwota zamówienia.
  • notes: obliczony stan ryzyka na podstawie wzrostu sieci i historii zamówień.

Zobaczysz konta z dużymi wartościami diff i wysokimi łącznymi kwotami zamówień, które są najlepszymi kandydatami do dalszego zbadania. Notatki „KLIENT ZAGROŻONY” i „POTENCJALNE OSZUSTWO” pomagają określić priorytety tych kont.

8. Wykrywanie na dużą skalę

W tym ostatnim kroku analizy wizualizujesz sieć w większej skali. Zamiast zaczynać od jednego konta, będziesz wyszukiwać połączenia między zestawem podejrzanych kont.

Dzięki temu możesz sprawdzić, czy kilka niezależnych analiz zagrożeń nie jest w rzeczywistości częścią tej samej większej grupy oszustów.

Uruchamianie zapytania skalowanego

Uruchom w notatniku to zapytanie.

%%bigquery --graph
GRAPH fraud_demo.FraudDemo
MATCH
p= ANY SHORTEST (a:Customer) 
  ( -[e:OwnsEmail|OwnsPhone|LinkedToAddress]- (n) ){3, 5}
(reachable_a:Customer)
-- these IDs are from the previous results
WHERE a.account_id in (   "845f2b14-cd10-4750-9f28-fe542c4a731b"
  , "3ff59684-fbf9-40d7-8c41-285ade5002e6"
  , "8887c17b-e6fb-4b3b-8c62-cb721aafd028"
  , "03e777e5-6fb4-445d-b48c-cf42b7620874"
  , "81629832-eb1d-4a0e-86da-81a198604898"
  , "845f2b14-cd10-4750-9f28-fe542c4a731b",
   "89e9a8fe-ffc4-44eb-8693-a711a3534849"
 )
 LIMIT 400
RETURN TO_JSON(p) as paths

Interpretowanie wyników

To zapytanie zwraca złożony wykres pokazujący, jak określone podejrzane konta nakładają się na siebie i współdzielą zasoby. Teraz możesz wykrywać oszustwa na dużą skalę, identyfikując klastry aktywności, które mogą wymagać skoordynowanej reakcji.

9. Czyszczenie

Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby zużyte w tym ćwiczeniu, usuń zbiór danych i wykres właściwości.

Aby zwolnić miejsce w środowisku, uruchom te instrukcje SQL.

DROP PROPERTY GRAPH IF EXISTS fraud_demo.FraudDemo;
DROP SCHEMA IF EXISTS fraud_demo CASCADE;

10. Gratulacje

Gratulacje! Udało Ci się utworzyć rozwiązanie do wykrywania oszustw za pomocą BigQuery Graph.

Wiesz już, jak:

  • wczytać dane z Cloud Storage do BigQuery;
  • Zdefiniuj graf właściwości za pomocą DDL.
  • Wysyłaj zapytania do wykresu za pomocą języka GQL, aby znajdować proste i złożone relacje.
  • Łączenie analizy grafów z firmowymi bazami danych w celu identyfikowania ryzyka.
  • Wizualizacja sieci na dużą skalę.

Więcej zasobów