Nadaraya-Waston估计是非参数模型中的经典核回归(Kernel Regression)模型,如无特别说明,一般情况下核回归就是指Nadaraya-Waston估计。它无需对数据的分布进行假设,运用核函数对数据进行估计。
在回归分析中,假设因变量 Y Y Y可以由自变量 X X X来解释,即
Y = m ( x ) Y = m(x) Y=m(x)
但我们不知道 m m m的具体形式,也是我们要求的模型。
给定观测数据 { X i , Y i } , i = 1 , … , n \{X_i, Y_i\}, i=1,\dots,n {Xi,Yi},i=1,…,n, Y Y Y的条件期望为:
E ( Y ∣ X = x ) = ∫ y f ( y ∣ x ) d y = ∫ y f ( x , y ) f X ( x ) d y = m ( x ) E(Y|X=x) = \int yf(y|x)dy = \int y \frac{f(x,y)}{f_X(x)} dy = m(x) E(Y∣X=x)=∫yf(y∣x)dy=∫yfX(x)f(x,y)dy=m(x)
运用核密度估计,可以得知 f ( x ) f(x) f(x)的概率密度函数(PDF, Probability Density Function)的估计为: f ^ X ( x ) = 1 n ∑ i = 1 n K h ( x − X i ) \hat{f}_X (x) =\frac{1}{n} \sum_{i=1}^n K_h(x-X_i) f^X(x)=n1i=1∑nKh(x−Xi)
联合概率密度函数 f ( x , y ) f(x, y) f(x,y)的核密度估计为: f ^ h , g ( x , y ) = 1 n ∑ i = 1 n K h ( x − X i h ) K g ( y − Y i g ) \hat{f}_{h,g}(x, y) =\frac{1}{n} \sum_{i=1}^n K_h(\frac{x-X_i}{h}) K_g (\frac{y-Y_i}{g}) f^h,g(x,y)=n1i=1∑nKh(hx−Xi)Kg(gy−Yi)
其中 h , g h,g h,g分别为核函数 K h ( ⋅ ) K_h(·) Kh(⋅)和 K g ( ⋅ ) K_g(·) Kg(⋅)的窗宽参数。
因此,前文条件期望中的分子我们可以化简为:
∫ y f ^ h , g ( x , y ) d y = 1 n ∑ i = 1 n 1 h K ( x − X i h ) y g K ( y − Y i g ) d y = 1 n ∑ i = 1 n K h ( x − X i ) ∫ ( s g + Y i ) K ( s ) d s = 1 n ∑ i = 1 n K h ( x − X i ) Y i \begin{array}{l} \int y\hat{f}_{h,g} (x,y)dy = \frac{1}{n} \sum_{i=1}^n \frac{1}{h}K(\frac{x-X_i}{h}) \frac{y}{g} K (\frac{y-Y_i}{g})dy \\ = \frac{1}{n} \sum_{i=1}^n K_h(x-X_i) \int (sg+Y_i)K(s)ds \\ = \frac{1}{n} \sum_{i=1}^n K_h(x-X_i)Y_i \end{array} ∫yf^h,g(x,y)dy=n1∑i=1nh1K(hx−Xi)gyK(gy−Yi)dy=n1∑i=1nKh(x−Xi)∫(sg+Yi)K(s)ds=n1∑i=1nKh(x−Xi)Yi
于是,我们可以得到NW估计
m ^ h ( x ) = n − 1 ∑ i = 1 n K h ( x − X i ) Y i n − 1 ∑ i = 1 n K h ( x − X i ) = 1 n ∑ i = 1 n ( ∑ i = 1 n K h ( x − X i ) n − 1 ∑ i = 1 n K h ( x − X i ) ) Y i = 1 n ∑ i = 1 n W h i ( x ) Y i \begin{array}{l} \hat{m}_h (x) = \cfrac{n^{-1} \sum_{i=1}^n K_h(x-X_i)Y_i}{n^{-1} \sum_{i=1}^n K_h(x-X_i)} \\ =\frac{1}{n} \sum_{i=1}^n (\cfrac{ \sum_{i=1}^n K_h(x-X_i)}{n^{-1} \sum_{i=1}^n K_h(x-X_i)})Y_i \\ =\frac{1}{n} \sum_{i=1}^n W_{hi}(x)Y_i \end{array} m^h(x)=n−1∑i=1nKh(x−Xi)n−1∑i=1nKh(x−Xi)Yi=n1∑i=1n(n−1∑i=1nKh(x−Xi)∑i=1nKh(x−Xi))Yi=n1∑i=1nWhi(x)Yi
从最后一行式子我们可以看到,NW估计可以看成是因变量 Y i Y_i Yi的局部带权平均,权重大小由核函数确定,越靠近估计点 x x x的 Y Y Y所获得的权重就越大。
首先定义一下核函数,这里我们采用常见的高斯核函数:
K ( t ) = 1 2 π e x p ( 1 2 t 2 ) K(t) = \cfrac{1}{\sqrt{2\pi}} exp(\cfrac{1}{2}t^2) K(t)=2π1exp(21t2),
K h ( t ) = 1 h K ( t h ) K_h (t) = \cfrac{1}{h} K(\cfrac{t}{h}) Kh(t)=h1K(ht).
代码实现:
import numpy as np
import matplotlib.pyplot as plt
def Gauss_kernel(t, h):
'''高斯核函数 $K_h (t)$。
input:
h: 窗宽,即光滑参数,float.
t: 位置参数,float.
'''
x = t / h
out = (1 / h) * 1 / np.sqrt(2*np.pi) * np.exp(-0.5*x*x)
return out
def NW1(X, Y, h):
'''
Nadaraya-Waston 估计拟合回归函数。矩阵解法。
input:
X: 自变量, np.array, [number, 1]
Y: 因变量,np.array, [number, 1]
h: 窗宽,即光滑参数,float.
output:
y_pred: Y的拟合值。
'''
number = X.shape[0]
one = np.ones(shape = (number, 1))
y_pred = np.zeros(shape=Y.shape)
for j in range(number):
diag_list = []
for i in range(number):
diag_list.append(Gauss_kernel(X[i] - X[j], h))
d_list = [i[0] for i in diag_list] # 若报错可将 i[0] 改为 i
W = np.diag(d_list)
y_pred[j] = np.linalg.inv(one.T @ W @one) @ one.T @ W @ Y
return y_pred
def NW2(X, Y, h):
'''
Nadaraya-Waston 估计拟合回归函数。for循环解法。
input:
X: 自变量, np.array, [number, 1]
Y: 因变量,np.array, [number, 1]
h: 窗宽,即光滑参数,float.
output:
y_pred: Y的拟合值。
'''
number = X.shape[0]
y_pred = np.zeros(shape=Y.shape)
for i in range(number):
up, low = 0, 0
for j in range(number):
k = Gauss_kernel(X[j] - X[i], h)
up += k * Y[j]
low += k
y_pred[i] = up / low
return y_pred
测试一下:
# 生成仿真数据
number = 201
X = np.linspace(0, 2, number)
X = X[:, np.newaxis]
print('X.shape = ', X.shape)
np.random.seed(0)
e = np.random.normal(0, 0.2, number)
e = e[:, np.newaxis]
print('e.shape = ', e.shape)
Y = 2*X + np.sin(5*np.pi*X) + e
Y_true = 2*X + np.sin(5*np.pi*X)
print('Y.shape = ', Y.shape)
# 测试不同窗宽
h_list = [0.1, 0.05, 0.025, 0.01]
y_pre = []
for h in h_list:
y_pre.append(NW1(X, Y, h))
y_pre = np.array(y_pre)
# 画图
plt.figure(figsize=(20, 12), dpi=80)
plt.rc('font', family='Times New Roman', weight = 'medium', size=15) #设置英文字体
font1={'family' : 'Times New Roman', 'size': 15}
# plt.ylabel(r"$x_{a,b}^{m,n}$",fontdict=font1)
for i in range(len(h_list)):
ax = plt.subplot(2, 2, i+1)
ax.scatter(X, Y, c='k', s = 3, label='$Simulation$')
ax.plot(X, Y_true, lw=1.5, label='$Truth$')
ax.plot(X, y_pre[i], lw=3, label='$\hat{m}_h (x)$')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend()
ax.set_title('h = %.2f'%h_list[i])
# plt.savefig('compare_h.png')
plt.show()
结果如下图:
可以看到窗宽h越大,NW估计曲线越平滑,此时方差小,偏差大;相反地,窗宽h越小,NW估计曲线越不平整,此时方差大,偏差小。这个时候就要在方差和偏差之间寻找一个平衡,即最优窗宽,使得方差和偏差不至于“偏科”太严重。上图中 h = 0.03 h = 0.03 h=0.03就是一个较优的窗宽。寻找最优窗宽的方法有很多,这里不再赘述,感兴趣的同学可以查阅相关资料。
其实说白了,NW估计就是个局部带权均值估计,如果样本量足够,在低维数据上表现还不错,但在高维数据上的就可能比不过其他方法了。当然,这只是我的看法,文章若有错误之处,欢迎各位大佬在评论区畅所欲言~
[1] Härdle W, Müller M, Sperlich S, et al. Nonparametric and semiparametric models[M]. Berlin: Springer, 2004.