
在数字支付与电商高速发展的今天,交易欺诈已成为金融与商业领域的顽疾。传统的反欺诈方案多依赖规则引擎或机器学习分类模型,存在规则僵化、对新型欺诈模式响应滞后、高误报率等痛点。
随着技术的迭代演进,针对交易行为的分析决策也有了新的思路,将交易行为转化为向量并存入向量数据库,通过检索偏离正常行为的向量实现毫秒级欺诈检测,将响应时间从分钟级压缩至毫秒级,大幅提升了风控效率与准确性。今天我们将由浅入深拆解这一技术方案,从核心概念、技术原理、实现流程到代码示例,全面解析如何利用向量数据库构建实时交易反欺诈系统。

在深入技术交流前,我们需要厘清三个关键概念:交易行为向量、向量数据库、异常向量检索。
交易行为本身是一组多维度的离散或连续特征,将这些特征映射到高维向量空间中,就形成了交易行为向量。一个典型的交易行为特征集合包括:
例如,一笔交易的原始特征可能是:
{
"user_reg_days": 180,
"history_trade_count": 56,
"trade_amount": 299.9,
"trade_hour": 20,
"is_common_device": 1,
"ip_city": "北京"
}通过特征标准化、编码(如 IP 地址经纬度编码、商品类型独热编码)后,即可转化为一个固定长度的高维向量,例如 [0.52, 0.31, 0.85, 0.78, 1.0, 0.63]。这个向量就代表了该笔交易的行为特征指纹。
我们对这些特征进行详细说明,并分析这些特性在特定场景下表现得特征:
1.2.1 基础风控维度:账号健康度(user_reg_days + history_trade_count)
1.2.2 核心交易特征:金额与时间(trade_amount + trade_hour)
1.2.3 环境风控维度:设备与地域(is_common_device + ip_city)
这些字段最终会被转化为高维向量,核心价值在于:
针对该特征集合,可进一步补充维度提升反欺诈准确性:
该特征集合覆盖了账号、交易、环境三大核心风控维度,是交易行为向量化的基础:
向量数据库是专门用于存储、索引和检索高维向量的数据库系统,其核心能力是相似性检索。与传统关系型数据库不同,向量数据库不依赖主键匹配,而是通过计算向量间的距离(如欧氏距离、余弦相似度)判断向量的相似程度。
主流向量数据库包括 ChromaDB、Milvus、Pinecone 等,它们具备以下核心特性:
异常向量检索的核心逻辑是:正常交易行为的向量会在向量空间中形成密集的聚类,而欺诈交易的向量会偏离这些聚类,处于向量空间的稀疏区域。
具体来说,系统会先基于用户历史正常交易向量构建用户级正常行为向量库,当新交易产生时,将其向量与用户正常向量库中的向量进行相似度检索:
向量检索的核心优化点正在于此:通过向量数据库的高效检索能力,将传统模型“批量计算 - 离线更新”的模式升级为“实时检索 - 即时判断”,实现毫秒级响应。
基于向量数据库的实时交易反欺诈系统,整体流程可分为四个核心步骤,我们用流程图清晰展示:

数据采集是系统的基础,需要实时捕获每一笔交易的全维度特征。在实际工程中,通常通过埋点系统、交易中台接口、用户画像系统整合数据,输出包含用户、交易、环境维度的结构化数据。
特征向量化是核心环节,直接决定后续检索的准确性。该步骤分为两个子流程:
2.1 特征预处理
2.2 向量生成
预处理后的特征集合通过拼接或加权组合,生成固定长度的高维向量。例如,将 10 个预处理后的特征拼接为长度为 10 的向量,或通过深度学习模型(如 DNN)生成更具代表性的嵌入向量。
将生成的交易行为向量存入向量数据库,并构建高效索引。需要注意两个关键点:
当新交易产生时,执行以下检索流程:
我们以 ChromaDB 为例,实现一个简化版的交易行为向量存储与异常检索系统。
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
import chromadb
from chromadb.config import Settings
import os
import logging
# ===================== 1. 配置详细日志(控制台+文件) =====================
# 日志配置:输出级别、格式、存储路径
log_dir = "./logs"
if not os.path.exists(log_dir):
os.makedirs(log_dir)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
logging.StreamHandler(), # 控制台输出
logging.FileHandler(f"{log_dir}/fraud_detection.log", encoding="utf-8") # 文件存储
]
)
logger = logging.getLogger("交易反欺诈系统")
# ===================== 2. 初始化ChromaDB(适配新版) =====================
persist_directory = "./chroma_persist"
if not os.path.exists(persist_directory):
os.makedirs(persist_directory)
logger.info(f"创建ChromaDB持久化目录:{persist_directory}")
# 初始化持久化客户端
client = chromadb.PersistentClient(
path=persist_directory,
settings=Settings(
allow_reset=True,
anonymized_telemetry=False
)
)
client.reset()
logger.info("重置ChromaDB数据库(测试环境)")
# ===================== 3. 定义核心配置(便于维护) =====================
# 风控阈值配置
FRAUD_THRESHOLD = 0.7 # 相似度阈值:低于此值判定为异常
TOP_K = 3 # 检索相似向量数量
USER_ID = "U001" # 目标用户ID
NORMAL_TRADE_NUM = 4 # 正常交易样本数
# 输出核心配置日志
logger.info("="*50)
logger.info("【核心风控配置】")
logger.info(f"异常交易判定阈值:余弦相似度 < {FRAUD_THRESHOLD}")
logger.info(f"检索相似向量数量:Top-{TOP_K}")
logger.info(f"目标分析用户:{USER_ID}")
logger.info(f"正常交易样本数量:{NORMAL_TRADE_NUM}")
logger.info("="*50)
# ===================== 4. 数据预处理与向量化 =====================
# 模拟交易数据
data = pd.DataFrame({
"user_id": ["U001", "U001", "U001", "U001", "U001", "U001"],
"user_reg_days": [180, 180, 180, 180, 180, 180],
"history_trade_count": [56, 57, 58, 59, 60, 61],
"trade_amount": [299.9, 199.0, 399.5, 499.0, 10.0, 9999.0],
"trade_hour": [20, 19, 21, 20, 3, 23],
"is_common_device": [1, 1, 1, 1, 0, 0]
})
logger.info(f"加载交易数据:共{len(data)}条,其中前{NORMAL_TRADE_NUM}条为正常交易,后{len(data)-NORMAL_TRADE_NUM}条为待检测交易")
# 特征预处理
scaler = MinMaxScaler(feature_range=(0, 1))
feature_cols = ["user_reg_days", "history_trade_count", "trade_amount", "trade_hour", "is_common_device"]
data_scaled = scaler.fit_transform(data[feature_cols])
vectors = data_scaled.tolist()
metadatas = [{"user_id": row["user_id"], "trade_id": f"T{idx}"} for idx, row in data.iterrows()]
ids = [f"T{idx}" for idx in range(len(vectors))]
# 输出向量维度日志
logger.info(f"特征列:{feature_cols}")
logger.info(f"向量维度:{len(vectors[0])}维")
logger.info(f"示例向量(T0):{vectors[0]}")# ===================== 5. 正常交易向量入库 =====================
collection_name = f"user_{USER_ID}_normal_trades"
# 删除旧集合
try:
client.delete_collection(name=collection_name)
logger.info(f"删除已存在的集合:{collection_name}")
except Exception as e:
logger.warning(f"集合{collection_name}不存在,无需删除:{e}")
# 创建新集合
collection = client.create_collection(
name=collection_name,
metadata={"hnsw:space": "cosine"} # 余弦相似度空间
)
logger.info(f"创建用户{USER_ID}的正常交易向量集合:{collection_name}")
# 入库正常交易向量
normal_vectors = vectors[:NORMAL_TRADE_NUM]
normal_metadatas = metadatas[:NORMAL_TRADE_NUM]
normal_ids = ids[:NORMAL_TRADE_NUM]
try:
collection.add(
embeddings=normal_vectors,
metadatas=normal_metadatas,
ids=normal_ids
)
logger.info(f"正常交易向量入库完成:{len(normal_vectors)}条")
logger.info(f"入库向量ID:{normal_ids}")
logger.info(f"集合当前向量总数:{collection.count()}")
except Exception as e:
logger.error(f"正常向量入库失败:{str(e)}", exc_info=True)
# ===================== 6. 异常交易检测(带详细日志) =====================
logger.info("\n" + "="*50)
logger.info("开始检测异常交易")
logger.info("="*50)# 待检测向量(异常样本)
test_vectors = vectors[NORMAL_TRADE_NUM:]
test_metadatas = metadatas[NORMAL_TRADE_NUM:]
test_ids = ids[NORMAL_TRADE_NUM:]
for idx, (vector, meta, trade_id) in enumerate(zip(test_vectors, test_metadatas, test_ids)):
logger.info(f"\n--- 检测交易 {trade_id} ---")
# 输出待检测交易原始特征
raw_data = data.iloc[NORMAL_TRADE_NUM + idx]
logger.info(f"原始特征:{raw_data.to_dict()}")
logger.info(f"待检测向量:{vector}")
# 检索相似向量
try:
results = collection.query(
query_embeddings=[vector],
n_results=TOP_K,
where={"user_id": USER_ID}
)
# 解析检索结果
retrieved_ids = results["ids"][0]
retrieved_distances = results["distances"][0]
retrieved_metadatas = results["metadatas"][0]
# 输出检索结果日志
logger.info(f"检索到Top-{TOP_K}相似正常交易:{retrieved_ids}")
logger.info(f"余弦距离(越小越相似):{[round(d, 4) for d in retrieved_distances]}")
# 计算平均相似度(余弦相似度=1-余弦距离)
avg_distance = np.mean(retrieved_distances) if retrieved_distances else 1.0
avg_similarity = 1 - avg_distance
logger.info(f"计算过程:平均余弦距离={round(avg_distance, 4)} → 平均余弦相似度={round(avg_similarity, 4)}")
# 风控决策
if avg_similarity < FRAUD_THRESHOLD:
logger.warning(f"【异常交易判定】交易{trade_id}:平均相似度{round(avg_similarity, 4)} < 阈值{FRAUD_THRESHOLD}")
logger.warning(f"判定原因:该交易行为向量与用户{USER_ID}的正常交易向量相似度过低,偏离正常行为模式")
print(f"\n交易 {trade_id}:平均相似度 {avg_similarity:.2f} → 🚨 异常交易,触发风控")
else:
logger.info(f"【正常交易判定】交易{trade_id}:平均相似度{round(avg_similarity, 4)} ≥ 阈值{FRAUD_THRESHOLD}")
logger.info(f"判定原因:该交易行为向量与用户{USER_ID}的正常交易向量高度相似,符合正常行为模式")
print(f"\n交易 {trade_id}:平均相似度 {avg_similarity:.2f} → ✅ 正常交易")
except Exception as e:
logger.error(f"检测交易{trade_id}失败:{str(e)}", exc_info=True)
print(f"\n交易 {trade_id}:检测失败 → ❌ 触发风控审核")
logger.info("\n" + "="*50)
logger.info("异常交易检测流程结束")
logger.info("="*50)2025-12-23 18:10:41,915 - INFO - 重置ChromaDB数据库 2025-12-23 18:10:41,915 - INFO - ========================================== 2025-12-23 18:10:41,916 - INFO - 【核心风控配置】 2025-12-23 18:10:41,916 - INFO - 异常交易判定阈值:余弦相似度 < 0.7 2025-12-23 18:10:41,916 - INFO - 检索相似向量数量:Top-3 2025-12-23 18:10:41,916 - INFO - 目标分析用户:U001 2025-12-23 18:10:41,916 - INFO - 正常交易样本数量:4 2025-12-23 18:10:41,916 - INFO - ========================================== 2025-12-23 18:10:41,918 - INFO - 加载交易数据:共6条,其中前4条为正常交易,后2条为待检测交易 2025-12-23 18:10:41,924 - INFO - 特征列:['user_reg_days', 'history_trade_count', 'trade_amount', 'trade_hour', 'is_common_device'] 2025-12-23 18:10:41,924 - INFO - 向量维度:5维 2025-12-23 18:10:41,924 - INFO - 示例向量(T0):[0.0, 0.0, 0.029021924116528177, 0.85, 1.0] 2025-12-23 18:10:41,926 - WARNING - 集合user_U001_normal_trades不存在,无需删除:Collection user_U001_normal_trades does not exist. 2025-12-23 18:10:41,977 - INFO - 创建用户U001的正常交易向量集合:user_U001_normal_trades 2025-12-23 18:10:42,012 - INFO - 正常交易向量入库完成:4条 2025-12-23 18:10:42,012 - INFO - 入库向量ID:['T0', 'T1', 'T2', 'T3'] 2025-12-23 18:10:42,014 - INFO - 集合当前向量总数:4 2025-12-23 18:10:42,014 - INFO - =========================================== 2025-12-23 18:10:42,015 - INFO - 开始检测异常交易 2025-12-23 18:10:42,015 - INFO - =========================================== 2025-12-23 18:10:42,015 - INFO ---- 检测交易 T4 --- 2025-12-23 18:10:42,016 - INFO - 原始特征:{'user_id': 'U001', 'user_reg_days': 180, 'history_trade_count': 60, 'trade_amount': 10.0, 'trade_hour': 3, 'is_common_device': 0} 2025-12-23 18:10:42,016 - INFO - 待检测向量:[0.0, 0.7999999999999989, 0.0, 0.0, 0.0]2025-12-23 18:10:42,022 - INFO - 检索到Top-3相似正常交易:['T3', 'T2', 'T1'] 2025-12-23 18:10:42,022 - INFO - 余弦距离(越小越相似):[0.5845, 0.7151, 0.8457] 2025-12-23 18:10:42,023 - INFO - 计算过程:平均余弦距离=0.7151 → 平均余弦相似度=0.2849 2025-12-23 18:10:42,023 - WARNING - 【异常交易判定】交易T4:平均相似度0.2849 < 阈值0.7 2025-12-23 18:10:42,024 - WARNING - 判定原因:该交易行为向量与用户U001的正常交易向量相似度过低,偏离正常行为模式 交易 T4:平均相似度 0.28 → 🚨 异常交易,触发风控 2025-12-23 18:10:42,025 - INFO ---- 检测交易 T5 --- 2025-12-23 18:10:42,026 - INFO - 原始特征:{'user_id': 'U001', 'user_reg_days': 180, 'history_trade_count': 61, 'trade_amount': 9999.0, 'trade_hour': 23, 'is_common_device': 0} 2025-12-23 18:10:42,026 - INFO - 待检测向量:[0.0, 1.0, 1.0, 1.0, 0.0] 2025-12-23 18:10:42,034 - INFO - 检索到Top-3相似正常交易:['T3', 'T2', 'T1'] 2025-12-23 18:10:42,035 - INFO - 余弦距离(越小越相似):[0.4006, 0.4494, 0.5462] 2025-12-23 18:10:42,036 - INFO - 计算过程:平均余弦距离=0.4654 → 平均余弦相似度=0.5346 2025-12-23 18:10:42,037 - WARNING - 【异常交易判定】交易T5:平均相似度0.5346 < 阈值0.7 2025-12-23 18:10:42,037 - WARNING - 判定原因:该交易行为向量与用户U001的正常交易向量相似度过低,偏离正常行为模式 交易 T5:平均相似度 0.53 → 🚨 异常交易,触发风控 2025-12-23 18:10:42,038 - INFO - =========================================== 2025-12-23 18:10:42,038 - INFO - 异常交易检测流程结束 2025-12-23 18:10:42,038 - INFO - ===========================================
可以看到,两条异常交易向量与正常向量的相似度均低于阈值,被成功识别。
在示例1的基础上优化,通过 matplotlib 生成交易特征对比图、相似度分布直方图、正常/异常向量空间分布图,直观展示异常交易的判定依据,并补充了细化的特征异常度分析:
import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler
import chromadb
from chromadb.config import Settings
import os
import logging
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
import seaborn as sns
img_dir = "./analysis_imgs"
for dir_path in [img_dir]:
if not os.path.exists(dir_path):
os.makedirs(dir_path)
# 设置中文字体(避免乱码)
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False # 解决负号显示问题
# ===================== 2. 初始化ChromaDB =====================
persist_directory = "./chroma_persist"
if not os.path.exists(persist_directory):
os.makedirs(persist_directory)
print(f"创建ChromaDB持久化目录:{persist_directory}")
client = chromadb.PersistentClient(
path=persist_directory,
settings=Settings(allow_reset=True, anonymized_telemetry=False)
)
client.reset()
print("重置ChromaDB数据库(测试环境)")
# ===================== 3. 核心配置 =====================
FRAUD_THRESHOLD = 0.7 # 相似度阈值
TOP_K = 3 # 检索相似向量数量
USER_ID = "U001"
NORMAL_TRADE_NUM = 4
print("="*50)
print("【核心风控配置】")
print(f"异常交易判定阈值:余弦相似度 < {FRAUD_THRESHOLD}")
print(f"检索相似向量数量:Top-{TOP_K}")
print(f"目标分析用户:{USER_ID}")
print(f"正常交易样本数量:{NORMAL_TRADE_NUM}")
print("="*50)
# ===================== 4. 数据预处理与向量化 =====================
# 模拟交易数据
data = pd.DataFrame({
"user_id": ["U001", "U001", "U001", "U001", "U001", "U001"],
"user_reg_days": [180, 180, 180, 180, 180, 180],
"history_trade_count": [56, 57, 58, 59, 60, 61],
"trade_amount": [299.9, 199.0, 399.5, 499.0, 10.0, 9999.0],
"trade_hour": [20, 19, 21, 20, 3, 23],
"is_common_device": [1, 1, 1, 1, 0, 0]
})
# 标记交易类型(正常/待检测)
data["trade_type"] = ["正常"]*NORMAL_TRADE_NUM + ["待检测"]*(len(data)-NORMAL_TRADE_NUM)
print(f"加载交易数据:共{len(data)}条,其中前{NORMAL_TRADE_NUM}条为正常交易,后{len(data)-NORMAL_TRADE_NUM}条为待检测交易")
# 特征预处理
scaler = MinMaxScaler(feature_range=(0, 1))
feature_cols = ["user_reg_days", "history_trade_count", "trade_amount", "trade_hour", "is_common_device"]
data_scaled = scaler.fit_transform(data[feature_cols])
vectors = data_scaled.tolist()
metadatas = [{"user_id": row["user_id"], "trade_id": f"T{idx}", "trade_type": row["trade_type"]}
for idx, row in data.iterrows()]
ids = [f"T{idx}" for idx in range(len(vectors))]
# 输出向量维度日志
print(f"特征列:{feature_cols}")
print(f"向量维度:{len(vectors[0])}维")
print(f"示例向量(T0):{vectors[0]}")
# ===================== 5. 正常交易向量入库 =====================
collection_name = f"user_{USER_ID}_normal_trades"
try:
client.delete_collection(name=collection_name)
print(f"删除已存在的集合:{collection_name}")
except Exception as e:
print(f"集合{collection_name}不存在,无需删除:{e}")
collection = client.create_collection(
name=collection_name,
metadata={"hnsw:space": "cosine"}
)
print(f"创建用户{USER_ID}的正常交易向量集合:{collection_name}")
# 入库正常交易向量
normal_vectors = vectors[:NORMAL_TRADE_NUM]
normal_metadatas = metadatas[:NORMAL_TRADE_NUM]
normal_ids = ids[:NORMAL_TRADE_NUM]
try:
collection.add(embeddings=normal_vectors, metadatas=normal_metadatas, ids=normal_ids)
print(f"正常交易向量入库完成:{len(normal_vectors)}条")
print(f"入库向量ID:{normal_ids}")
print(f"集合当前向量总数:{collection.count()}")
except Exception as e:
print(f"正常向量入库失败:{str(e)}", exc_info=True)
# ===================== 6. 可视化分析函数 =====================
def plot_trade_feature_comparison(data, feature_cols, save_path):
"""
绘制正常/待检测交易特征对比图
"""
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
fig.suptitle(f"用户{USER_ID}交易特征对比(正常VS待检测)", fontsize=14, fontweight="bold")
# 选择核心特征绘制
plot_features = ["trade_amount", "trade_hour", "history_trade_count", "is_common_device"]
for idx, feat in enumerate(plot_features):
ax = axes[idx//2, idx%2]
# 分组统计
normal_feat = data[data["trade_type"]=="正常"][feat]
test_feat = data[data["trade_type"]=="待检测"][feat]
# 绘制对比
x = ["正常交易均值", "待检测交易均值"]
y = [normal_feat.mean(), test_feat.mean()]
ax.bar(x, y, color=["#2E8B57", "#DC143C"], alpha=0.7)
ax.set_title(f"{feat.replace('_', ' ')} 对比", fontsize=12)
ax.set_ylabel("特征值")
# 添加数值标注
for i, v in enumerate(y):
ax.text(i, v+0.02, f"{v:.2f}", ha="center", va="bottom", fontsize=10)
plt.tight_layout()
plt.savefig(save_path, dpi=300, bbox_inches="tight")
print(f"特征对比图已保存:{save_path}")
plt.show()
def plot_similarity_distribution(similarity_data, save_path):
"""
绘制相似度分布直方图(含阈值线)
"""
fig, ax = plt.subplots(figsize=(10, 6))
# 绘制相似度分布
ax.hist(similarity_data, bins=10, color="#4682B4", alpha=0.7)
# 添加阈值线
ax.axvline(FRAUD_THRESHOLD, color="#DC143C", linestyle="--", linewidth=2, label=f"异常阈值:{FRAUD_THRESHOLD}")
# 标注异常交易
for idx, sim in enumerate(similarity_data):
if sim < FRAUD_THRESHOLD:
ax.scatter(sim, 0.5, color="red", s=50, label=f"异常交易T{NORMAL_TRADE_NUM+idx}" if idx==0 else "")
ax.set_title(f"用户{USER_ID}交易相似度分布", fontsize=14, fontweight="bold")
ax.set_xlabel("余弦相似度")
ax.set_ylabel("频次")
ax.legend()
ax.grid(axis="y", alpha=0.3)
plt.savefig(save_path, dpi=300, bbox_inches="tight")
print(f"相似度分布图已保存:{save_path}")
plt.show()
def plot_vector_space(vectors, labels, save_path):
"""
向量空间可视化(PCA降维到2D)
"""
from sklearn.decomposition import PCA
# PCA降维到2维
pca = PCA(n_components=2)
vectors_2d = pca.fit_transform(vectors)
fig, ax = plt.subplots(figsize=(10, 8))
# 绘制正常交易向量
normal_2d = vectors_2d[:NORMAL_TRADE_NUM]
ax.scatter(normal_2d[:,0], normal_2d[:,1], color="#2E8B57", s=100, label="正常交易", alpha=0.8)
# 绘制待检测交易向量
test_2d = vectors_2d[NORMAL_TRADE_NUM:]
ax.scatter(test_2d[:,0], test_2d[:,1], color="#DC143C", s=100, marker="x", label="待检测交易", alpha=0.8)
# 添加标注
for idx, (x, y) in enumerate(vectors_2d):
ax.text(x+0.01, y+0.01, f"T{idx}", fontsize=9)
ax.set_title(f"用户{USER_ID}交易向量空间分布(PCA降维)", fontsize=14, fontweight="bold")
ax.set_xlabel("PCA维度1")
ax.set_ylabel("PCA维度2")
ax.legend()
ax.grid(alpha=0.3)
plt.savefig(save_path, dpi=300, bbox_inches="tight")
print(f"向量空间分布图已保存:{save_path}")
plt.show()
# ===================== 7. 异常交易检测(带细化分析+可视化) =====================
print("\n" + "="*50)
print("开始检测异常交易")
print("="*50)
# 待检测向量
test_vectors = vectors[NORMAL_TRADE_NUM:]
test_metadatas = metadatas[NORMAL_TRADE_NUM:]
test_ids = ids[NORMAL_TRADE_NUM:]
# 存储相似度结果(用于可视化)
similarity_results = []
for idx, (vector, meta, trade_id) in enumerate(zip(test_vectors, test_metadatas, test_ids)):
print(f"\n--- 检测交易 {trade_id} ---")
# 1. 输出原始特征
raw_data = data.iloc[NORMAL_TRADE_NUM + idx]
print(f"原始特征:{raw_data.to_dict()}")
print(f"待检测向量:{vector}")
# 2. 特征异常度分析
print("【特征异常度分析】")
normal_data = data[data["trade_type"]=="正常"]
for feat in ["trade_amount", "trade_hour", "is_common_device"]:
normal_mean = normal_data[feat].mean()
test_val = raw_data[feat]
# 计算偏离度(相对差值)
deviation = abs(test_val - normal_mean) / normal_mean if normal_mean !=0 else 1.0
deviation_pct = deviation * 100
if deviation_pct > 50: # 偏离超过50%判定为异常特征
print(f" {feat}:正常均值={normal_mean:.2f},当前值={test_val},偏离度={deviation_pct:.1f}% → 异常")
else:
print(f" {feat}:正常均值={normal_mean:.2f},当前值={test_val},偏离度={deviation_pct:.1f}% → 正常")
# 3. 检索相似向量
try:
results = collection.query(
query_embeddings=[vector],
n_results=TOP_K,
where={"user_id": USER_ID}
)
retrieved_ids = results["ids"][0]
retrieved_distances = results["distances"][0]
retrieved_metadatas = results["metadatas"][0]
# 4. 输出检索结果
print(f"检索到Top-{TOP_K}相似正常交易:{retrieved_ids}")
print(f"余弦距离(越小越相似):{[round(d, 4) for d in retrieved_distances]}")
# 5. 计算相似度
avg_distance = np.mean(retrieved_distances) if retrieved_distances else 1.0
avg_similarity = 1 - avg_distance
similarity_results.append(avg_similarity)
print(f"计算过程:平均余弦距离={round(avg_distance, 4)} → 平均余弦相似度={round(avg_similarity, 4)}")
# 6. 风控决策
if avg_similarity < FRAUD_THRESHOLD:
print(f"【异常交易判定】交易{trade_id}:平均相似度{round(avg_similarity, 4)} < 阈值{FRAUD_THRESHOLD}")
print(f"判定原因:1. 特征偏离度超过50%;2. 与正常交易向量相似度过低,行为模式异常")
print(f"\n交易 {trade_id}:平均相似度 {avg_similarity:.2f} → 🚨 异常交易,触发风控")
else:
print(f"【正常交易判定】交易{trade_id}:平均相似度{round(avg_similarity, 4)} ≥ 阈值{FRAUD_THRESHOLD}")
print(f"判定原因:特征偏离度在正常范围,与正常交易向量高度相似")
print(f"\n交易 {trade_id}:平均相似度 {avg_similarity:.2f} → ✅ 正常交易")
except Exception as e:
print(f"检测交易{trade_id}失败:{str(e)}", exc_info=True)
similarity_results.append(0.0)
print(f"\n交易 {trade_id}:检测失败 → ❌ 触发风控审核")
# ===================== 8. 生成可视化分析图 =====================
print("\n" + "="*50)
print("生成可视化分析图表")
print("="*50)
# 8.1 交易特征对比图
plot_trade_feature_comparison(
data=data,
feature_cols=feature_cols,
save_path=f"{img_dir}/trade_feature_comparison.png"
)
# 8.2 相似度分布直方图
plot_similarity_distribution(
similarity_data=similarity_results,
save_path=f"{img_dir}/similarity_distribution.png"
)
# 8.3 向量空间分布图
plot_vector_space(
vectors=vectors,
labels=["正常"]*NORMAL_TRADE_NUM + ["待检测"]*(len(vectors)-NORMAL_TRADE_NUM),
save_path=f"{img_dir}/vector_space_distribution.png"
)
print("\n" + "="*50)
print("异常交易检测流程结束")
print(f"可视化图表已保存至:{img_dir}")
print("="*50)重置ChromaDB数据库 ================================================== 【核心风控配置】 异常交易判定阈值:余弦相似度 < 0.7 检索相似向量数量:Top-3 目标分析用户:U001 正常交易样本数量:4 ================================================== 加载交易数据:共6条,其中前4条为正常交易,后2条为待检测交易 特征列:['user_reg_days', 'history_trade_count', 'trade_amount', 'trade_hour', 'is_common_device'] 向量维度:5维 示例向量(T0):[0.0, 0.0, 0.029021924116528177, 0.85, 1.0] 集合user_U001_normal_trades不存在,无需删除:Collection user_U001_normal_trades does not exist. 创建用户U001的正常交易向量集合:user_U001_normal_trades 正常交易向量入库完成:4条 入库向量ID:['T0', 'T1', 'T2', 'T3'] 集合当前向量总数:4

================================================== 开始检测异常交易 ================================================== --- 检测交易 T4 --- 原始特征:{'user_id': 'U001', 'user_reg_days': 180, 'history_trade_count': 60, 'trade_amount': 10.0, 'trade_hour': 3, 'is_common_device': 0, 'trade_type': '待检测'} 待检测向量:[0.0, 0.7999999999999989, 0.0, 0.0, 0.0] 【特征异常度分析】 trade_amount:正常均值=349.35,当前值=10.0,偏离度=97.1% → 异常 trade_hour:正常均值=20.00,当前值=3,偏离度=85.0% → 异常 is_common_device:正常均值=1.00,当前值=0,偏离度=100.0% → 异常 检索到Top-3相似正常交易:['T3', 'T2', 'T1'] 余弦距离(越小越相似):[0.5845, 0.7151, 0.8457] 计算过程:平均余弦距离=0.7151 → 平均余弦相似度=0.2849 【异常交易判定】交易T4:平均相似度0.2849 < 阈值0.7 判定原因:1. 特征偏离度超过50%;2. 与正常交易向量相似度过低,行为模式异常 交易 T4:平均相似度 0.28 → 🚨 异常交易,触发风控 --- 检测交易 T5 --- 原始特征:{'user_id': 'U001', 'user_reg_days': 180, 'history_trade_count': 61, 'trade_amount': 9999.0, 'trade_hour': 23, 'is_common_device': 0, 'trade_type': '待检测'} 待检测向量:[0.0, 1.0, 1.0, 1.0, 0.0] 【特征异常度分析】 trade_amount:正常均值=349.35,当前值=9999.0,偏离度=2762.2% → 异常 trade_hour:正常均值=20.00,当前值=23,偏离度=15.0% → 正常 is_common_device:正常均值=1.00,当前值=0,偏离度=100.0% → 异常 检索到Top-3相似正常交易:['T3', 'T2', 'T1'] 余弦距离(越小越相似):[0.4006, 0.4494, 0.5462] 计算过程:平均余弦距离=0.4654 → 平均余弦相似度=0.5346 【异常交易判定】交易T5:平均相似度0.5346 < 阈值0.7 判定原因:1. 特征偏离度超过50%;2. 与正常交易向量相似度过低,行为模式异常 交易 T5:平均相似度 0.53 → 🚨 异常交易,触发风控

================================================== 生成可视化分析图表 ================================================== 特征对比图已保存:./analysis_imgs/trade_feature_comparison.png 相似度分布图已保存:./analysis_imgs/similarity_distribution.png 向量空间分布图已保存:./analysis_imgs/vector_space_distribution.png ================================================== 异常交易检测流程结束 可视化图表已保存至:./analysis_imgs ==================================================

如果将上述方案落地到生产环境,我们可以朝以下三方面进行调优处理:向量质量优化、检索性能优化、阈值动态调整。
向量的质量直接决定检索准确性,可通过以下方式优化:
面对高并发的实时交易场景,需从索引和部署层面优化性能:
固定阈值难以适配复杂场景,需实现动态阈值机制:
将交易行为转化为向量并利用向量数据库实现实时异常检索,是反欺诈技术从被动规则向主动感知的跨越。其核心优势体现在实时性,毫秒级检索响应,适配高并发交易场景;灵活性,无需重新训练模型即可适配新型欺诈模式;精准性,基于用户级行为聚类,降低跨用户误判概率,未来,随着大模型与向量数据库的深度融合,通过大模型生成交易行为的语义向量,结合向量数据库的检索能力,实现对隐蔽欺诈行为的精准识别。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。