Skip to content

三角函数在风控中的应用——循环特征编码与三角回归 ​

2026年6月22日

先验直觉: 1月到12月的数值距离是11,但实际时间距离只有一个月。如果用1-12给月份编码,模型会以为12月"离"1月很远——这在统计学上是错的,而且在风控中可以导致模型学不到真实的季节模式。

关键词: 三角函数,循环编码,特征工程,三角回归,LendingClub,周期性


01 一个被忽略的编码问题 ​

做特征工程时,我们经常会遇到循环变量(Cyclic Variable):

  • 月份:12 → 1 不是距离13,是距离1
  • 星期:周日 → 周一不是距离7,是距离1
  • 小时:23 → 0不是距离24,是距离1

最常见的错误是用 1-12 的整数表示月份。这会让模型学到"12月和1月差异很大"——而实际上它们之间只有31天。

三角函数提供了一个优雅的解决方案:把循环变量映射到单位圆上的角度,用 sin 和 cos 编码。


02 为什么数值编码是错的? ​

做一个 Toy Demo。生成一个简单的 sin 波加噪声,分别用两种方式建模:

  • 线性回归直接将连续值 t 作为特征(类似月份=1-12)
  • 三角回归用 sin(t) 和 cos(t) 作为特征

结果一目了然:

模型R²参数数
线性回归0.162(截距+斜率)
三角回归0.943(截距+sin+cos)

线性模型认为"t 越大,y 越大或越小"——它对周期模式无能为力。三角回归只用了一个额外的参数,就正确捕捉了数据的周期性。

数学直觉很简单:任何一个正弦波 A⋅sin⁡(ωt+ϕ) 都可以展开为:

A⋅sin⁡(ωt+ϕ)=α⋅sin⁡(ωt)+β⋅cos⁡(ωt)

所以用 sin(t) 和 cos(t) 做特征,线性回归就能拟合任意相位和大小的正弦模式。


03 三种编码方式对比 ​

对于月份这个循环变量,有三种常见的编码方式:

方式一:数值编码 ​

把月份映射为 1-12 的整数。问题:12和1的欧氏距离是 11,但真实距离是 1。

d欧几里得(12,1)=12−1=11(错误!)

方式二:One-hot 编码 ​

把月份展开为 12 个二元哑变量,模型自由学习每个月的效应。

d汉明(Jan,Feb)=1(相邻)d汉明(Jan,Dec)=1(也相邻——对吗?)

One-hot 的问题是:参数多(11 个额外参数),且无法利用"月份之间顺序关系"的信息。

方式三:Sin/Cos 编码 ​

把月份映射到单位圆上:

xmonth=sin⁡(2π⋅month12),ymonth=cos⁡(2π⋅month12)

12月(角度 330∘)和1月(角度 30∘)的欧氏距离:

d欧几里得(Dec,Jan)=(sin⁡330∘−sin⁡30∘)2+(cos⁡330∘−cos⁡30∘)2≈0.52

这个距离远小于 12 和 1 的数值距离 11,而且和 1 月到 2 月的距离(0.52)完全一致——正确体现了"相邻月份应该等距"这个直觉。

Sin/cos 编码还有一个隐藏优势:只需要 2 维,比 one-hot 的 12 维节省 83% 的参数。


04 单位圆的几何直觉 ​

为什么 sin 和 cos 能正确编码循环关系?因为月份在本质上是一个角度变量。

把 12 个月均匀分布在单位圆上,每个月的坐标就是 (cos⁡θ,sin⁡θ),其中 θ=2π⋅month/12。

从图中可以直观看到:

  • 相邻月份的 sin/cos 坐标是"相邻"的(距离 ≈ 0.52)
  • 相隔半年的月份(如1月和7月)在圆上对望(距离 ≈ 2.0)
  • 没有一个方向优先——所有月份在二维空间中的分布是均匀的

这正是我们想要的循环距离度量。


05 LendingClub 实战:月度违约率 ​

用 LendingClub 220 万笔贷款数据,按放款月份聚合违约率。

在13年中,各月的违约率有一定差异:

月份样本量违约率
1月114,98318.86%
2月106,12818.68%
3月128,78419.80%
4月111,93520.48%
5月106,89520.41%
6月102,94620.27%
7月132,16620.12%
8月114,99619.75%
9月92,91419.79%
10月138,91818.80%
11月116,28019.02%
12月106,97019.47%

违约率从 2 月的 18.68% 上升到 4-5 月的 20.4%+,再回落。这是一个明显的季节性信号——但信号很弱(极差仅 1.8pp)。

三角回归拟合的完整计算结果如下:

违约率=19.62+0.10⋅sin⁡(2πm/12)+(−0.75)⋅cos⁡(2πm/12)=19.62+0.75⋅sin⁡(2πm/12−1.44)
月份sin(θ)cos(θ)实际违约率三角拟合残差
Jan+0.500+0.86618.86%19.02%-0.17
Feb+0.866+0.50018.68%19.33%-0.65
Mar+1.000+0.00019.80%19.72%+0.08
Apr+0.866-0.50020.48%20.08%+0.40
May+0.500-0.86620.41%20.32%+0.09
Jun+0.000-1.00020.27%20.37%-0.09
Jul-0.500-0.86620.12%20.22%-0.09
Aug-0.866-0.50019.75%19.91%-0.16
Sep-1.000+0.00019.79%19.52%+0.27
Oct-0.866+0.50018.80%19.16%-0.36
Nov-0.500+0.86619.02%18.93%+0.09
Dec-0.000+1.00019.47%18.87%+0.59

回归系数的几何意义:振幅 A=0.102+0.752=0.75pp 代表季节性波动的幅度;相位 ϕ=−82.5° 表示波谷在 2 月(违约最低点)、波峰在 7 月附近。

如果用三种模型分别拟合这个模式:

模型R²参数数
数值月份(线性)0.0032
三角回归(sin/cos)0.7343
One-hot 12个月1.00012

但这里有一个隐藏的问题:上述分析用的是 12 个月聚合数据——把 11 年间的每个 1 月平均成一个点。聚合放大了季节信号,但也丢失了信息。

如果用 139 个月 × 年 的原始数据点直接拟合呢?

模型参数R²MAE
仅季节 sin/cos(月份)30.0023.74pp
线性年份趋势20.0013.71pp
年份 sin/cos(经济周期)30.2192.68pp
年份 sin/cos + 季节 sin/cos50.2212.68pp

在 139 个点中,仅月份 sin/cos 几乎为零(R²=0.002)。而仅年份 sin/cos 就解释了 22% 的变异。

为什么?因为年份效应远大于季节效应。把年份也视为一个循环变量(经济周期 ≈ 10 年),用 sin/cos 拟合:

y=17.44+3.28⋅sin⁡(2πt/139+ϕ)⏟年份周期, 6.56pp+0.32⋅sin⁡(2πm/12+ψ)⏟月份周期, 0.64pp

年份效应(6.56pp)是季节效应(0.64pp)的 10 倍。2008 年金融危机后违约率飙升、2014 年低谷、2016 年网贷泡沫——这些经济周期波动的幅度远大于"2 月违约低、7 月违约高"的季节模式。

加上月份 sin/cos 后,R² 仅从 0.219 增加到 0.221——ΔR²=0.002。换言之,在这个数据中,季节信号在年份周期面前几乎可以忽略。

但这不意味着季节编码不重要——恰恰相反,正确的编码是捕捉微弱信号的前提。如果直接用数值月份(1-12),连 0.002 都捕捉不到。而且,在其他行业中——电商的 11 月促销、旅游的暑期旺季、零售的圣诞季——季节信号可能强到即使不聚合也清晰可见。

数据量不大时(12个月),dummy 模型可以完美拟合。但三角回归用仅3个参数(截距+sin+cos)就解释了 73% 的变异——参数效率是 dummy 的 4 倍。

数值月份模型几乎是一条水平直线(R²=0)——它完全无法捕捉先升后降的季节模式。而三角回归的 sin/cos 特征正确拟合了"春秋低、夏冬高"的起伏。


06 Python 代码 ​


07 数学文化:从三角函数到傅里叶级数 ​

三角回归的背后,是数学史上最强大的工具之一——傅里叶级数。

1807年,约瑟夫·傅里叶向巴黎科学院提交了一篇论文,声称任何周期函数都可以分解为正弦和余弦函数的无穷级数:

f(t)=a0+∑k=1∞[aksin⁡(kωt)+bkcos⁡(kωt)]

当时拉格朗日、拉普拉斯都反对——这么"不连续"的函数怎么可能用光滑的正弦波拼出来?但傅里叶是对的。今天,从信号处理、气象预测到金融时间序列,傅里叶变换无处不在。

在风控场景中,我们通常只需要第一个谐波(k=1)就能捕捉主要季节模式——就像本文用 sin(2πt/12) 和 cos(2πt/12) 做的。当季节模式更复杂时(如双峰、非对称),加入 k=2、k=3 的谐波即可:

f(t)=β0+β1sin⁡(2πt/12)+β2cos⁡(2πt/12)+β3sin⁡(4πt/12)+β4cos⁡(4πt/12)+…

每个谐波对加 2 个参数,比 one-hot 的逐月编码更省参数,且保留了变量的循环结构。


08 关键要点 ​

  1. 循环变量不要用数值编码——12月到1月的数值距离是 11,实际距离是 1,模型会学到错误的关系

  2. Sin/Cos 编码用 2 维表示循环关系——等价于把变量投影到单位圆上,距离度量正确

  3. 三角回归是 sin/cos 编码的自然延伸——把 sin(θ) 和 cos(θ) 作为回归特征,用 3 个参数(含截距)就可拟合任意相位和大小的正弦模式

  4. LendingClub 实战:数值月份 R²≈0,三角回归 R²=0.73——参数效率是 one-hot 的 4 倍

  5. 适用场景:月份、星期、小时等循环时间特征;空间角度;风向;任何有周期性的变量

  6. 局限:sin/cos 编码假设循环关系是对称的。对于不对称的季节模式(如电商11月、12月高峰),需要引入高阶谐波或额外特征

  7. 和傅里叶级数的关系:三角回归的本质是傅里叶一级近似——只用基频谐波拟合周期信号。需要更复杂模式时可叠加高阶谐波

  8. 在风控中的价值:虽然 LendingClub 月份信号弱(极差 1.8pp),但在消费信贷中,节假日效应、年终效应、季度性流动资金变化都是真实存在的季节信号——正确编码是模型捕捉这些信号的前提


参考文献 ​

  1. Fisher, N. I. (1993). Statistical Analysis of Circular Data. Cambridge University Press — 循环数据统计分析的经典教材,系统论述sin/cos编码的理论基础
  2. Mardia, K. V., & Jupp, P. E. (2000). Directional Statistics. Wiley — 方向统计学的权威参考,包含循环变量的回归模型
  3. Bloomfield, P. (2000). Fourier Analysis of Time Series: An Introduction (2nd ed.). Wiley — 傅里叶级数在时间序列分析中的应用,三角回归的进阶阅读
  4. Harvey, A. C. (1990). Forecasting, Structural Time Series Models and the Kalman Filter. Cambridge University Press — 包含三角回归在季节调整中的经典应用

关注公众号:QIAN数据