我尝试按照加州理工学院的讲义中描述的那样,在Python和Numpy中实现径向基函数。数学原理对我来说很清晰,所以我觉得奇怪的是它似乎不起作用(或者看起来不起作用)。这个想法很简单,选择一个子采样的中心数量,为每个高斯形式构建一个核矩阵,并尝试找到最佳系数。也就是说,解Kc = y
,其中K是高斯核(格拉姆)矩阵,通过最小二乘法。针对这个,我做了如下操作:
beta = 0.5*np.power(1.0/stddev,2)Kern = np.exp(-beta*euclidean_distances(X=X,Y=subsampled_data_points,squared=True))#(C,_,_,_) = np.linalg.lstsq(K,Y_train)C = np.dot( np.linalg.pinv(Kern), Y )
但是当我尝试用原始数据绘制插值时,它们看起来完全不一样:
使用了100个随机中心(来自数据集)。我也尝试了10个中心,这基本上产生了与使用训练集中每个数据点相同的结果。我假设使用数据集中每个数据点应该或多或少地完美复制曲线,但实际上并没有(过拟合)。它产生了:
这看起来似乎不正确。我将提供完整的代码(可以无错误运行):
由于图表看起来很奇怪,我决定阅读绘图函数的文档,但我找不到明显的错误之处。
回答:
插值函数的缩放
主要问题是不幸选择了用于插值的函数的标准差:
stddev = 100
你的函数的特征(它的隆起)大小大约是1。所以,使用
stddev = 1
X值的顺序
红色线条的混乱是因为matplotlib的plt
连接了按给定顺序的连续数据点。由于你的X值是随机顺序的,这导致了混乱的左右移动。使用排序后的X值:
X = np.sort(low_x + (high_x - low_x) * np.random.rand(N,1), axis=0)
效率问题
你的get_labels_improved
方法效率低下,因为它循环遍历X的元素。使用Y = f(X)
,将循环留给低级NumPy内部处理。
此外,计算超定系统的最小二乘解应该使用lstsq,而不是计算伪逆(计算成本高)并乘以它。
这是清理后的代码;使用30个中心可以得到一个很好的拟合。