第一层:客户基础特征
客户基础特征是反洗钱特征分层体系中的第一层,也是最底层、最稳定的特征层。该层数据主要来源于客户开户、信息变更及定期复核环节,具有静态为主、低频更新的特点。在SQL建模中,第一层特征通常作为维度表或左连接基表参与后续特征计算。
4.1 客户身份信息(KYC)
KYC(Know Your Customer)是反洗钱合规的起点,也是特征工程中最基础的属性来源。核心字段包括:
| 字段类别 | 典型字段 | SQL数据类型 | 特征用途 |
|---|---|---|---|
| 身份标识 | 客户编号、证件类型、证件号码 | VARCHAR / CHAR | 客户唯一标识、黑名单匹配 |
| 基本信息 | 姓名、性别、出生日期、国籍 | VARCHAR / DATE | 年龄分段、跨境风险识别 |
| 联系方式 | 手机号、邮箱、居住地址 | VARCHAR | 异常联系模式、地址一致性 |
| 职业信息 | 职业、单位名称、单位地址 | VARCHAR | 职业风险分类、关联交易识别 |
| 证件有效期 | 证件签发日、到期日 | DATE | 证件过期预警、异常续期检测 |
建模提示:KYC字段在SQL中通常存储在
customer_info 或 kyc_detail 表中。建议对证件号码、手机号做脱敏处理后,再用于特征拼接,避免敏感数据泄露。
4.2 客户风险等级
客户风险等级是金融机构根据监管要求及内部模型对客户进行的风险分层。常见等级包括:
- 低风险(Low):普通工薪阶层、长期稳定交易、无负面记录
- 中风险(Medium):自由职业、跨境交易频繁、资金来源复杂
- 高风险(High):政治敏感人物(PEP)、制裁国家关联、历史可疑交易
- 禁止类(Prohibited):黑名单客户、制裁名单命中、监管禁止开户
在SQL建模中,风险等级通常以枚举值或数值分数存储,并作为后续交易监控、预警阈值调整的核心权重因子。
SQL示例:风险等级数值化映射
-- 将风险等级转为数值权重,用于后续特征加权
SELECT
customer_id,
risk_level,
CASE risk_level
WHEN '低风险' THEN 1
WHEN '中风险' THEN 2
WHEN '高风险' THEN 3
WHEN '禁止类' THEN 9
ELSE 0
END AS risk_score
FROM customer_risk;
4.3 客户地域
地域特征包括客户的常住地址、开户机构所在地、交易对手所在地等。在反洗钱特征中,地域维度主要用于:
- 跨境风险识别:客户是否涉及FATF高风险国家/地区
- 地域集中度:同一地址关联多个客户(团伙风险)
- 异常迁徙:客户短期内频繁变更地址或开户地
| 地域层级 | 粒度 | 特征示例 |
|---|---|---|
| 国家/地区 | ISO 3166-1 代码 | CN、US、IR(伊朗) |
| 省级/州 | 行政区划代码 | 310000(上海)、CA(加州) |
| 城市/区县 | 城市名称或代码 | 北京朝阳区、纽约曼哈顿 |
| 街道/邮编 | 详细地址或邮编 | 200120、100022 |
4.4 客户行业分类
行业分类是判断客户资金流动合理性的重要依据。不同行业的交易金额、频率、对手特征差异显著。常见高风险行业包括:
- 现金密集型:餐饮、零售、超市、加油站
- 跨境贸易:进出口、跨境电商、物流货代
- 虚拟资产:数字货币交易、区块链项目
- 博彩娱乐:线上博彩、赛马、彩票
- 珠宝艺术品:贵金属、古董、奢侈品
行业分类避坑:不要直接使用客户填写的行业名称做特征,应映射到统一的行业分类标准(如GB/T 4754-2017或NAICS)。同一行业名称在不同机构可能含义不同,标准化映射是SQL建模的第一步。
4.5 第一层特征分层结构图
下图展示了客户基础特征的四类核心维度及其在反洗钱特征体系中的位置:
4.6 第一层特征SQL建模要点
在SQL中构建第一层特征时,需遵循以下原则:
- 维度表优先:将客户基础特征存储在独立的维度表中,避免在事实表中重复存储
- 标准化映射:对行业、地域、职业等字段做统一编码映射
- 时间戳管理:记录每个特征的生效时间、失效时间,支持历史回溯
- 空值处理:对缺失的KYC字段使用默认值或标记,避免NULL导致特征失效
SQL示例:第一层特征宽表构建
-- 构建客户基础特征宽表,用于后续特征拼接
CREATE TABLE dwd_customer_base_features AS
SELECT
a.customer_id,
a.name,
a.gender,
a.birth_date,
TIMESTAMPDIFF(YEAR, a.birth_date, CURDATE()) AS age,
a.nationality,
a.occupation,
b.risk_level,
b.risk_score,
c.country_code,
c.province_code,
c.city_code,
d.industry_code,
d.industry_name,
d.risk_flag AS industry_risk_flag
FROM customer_info a
LEFT JOIN customer_risk b ON a.customer_id = b.customer_id
LEFT JOIN customer_address c ON a.customer_id = c.customer_id AND c.is_primary = 1
LEFT JOIN industry_dict d ON a.industry_code = d.industry_code;