我试图在CalTech lecture here描述的Python和Numpy中实现径向基函数。数学对我来说似乎很清楚所以我觉得奇怪的是它不起作用(或者似乎不起作用)。这个想法很简单,人们为每个高斯形式选择一个子采样数量的中心,形成一个核心矩阵,并试图找到最佳系数。即求解Kc = y
其中K是具有最小二乘的guassian核(gramm)矩阵。为此我做了:
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个中心,它们使用训练集中的每个数据点生成基本相同的图形。我假设使用数据集中的每个数据点应该或多或少完美地复制曲线,但它没有(过度拟合)。它产生:
这似乎不正确。我将提供完整的代码(运行没有错误):
import numpy as np
from sklearn.metrics.pairwise import euclidean_distances
from scipy.interpolate import Rbf
import matplotlib.pyplot as plt
## Data sets
def get_labels_improved(X,f):
N_train = X.shape[0]
Y = np.zeros( (N_train,1) )
for i in range(N_train):
Y[i] = f(X[i])
return Y
def get_kernel_matrix(x,W,S):
beta = get_beta_np(S)
#beta = 0.5*tf.pow(tf.div( tf.constant(1.0,dtype=tf.float64),S), 2)
Z = -beta*euclidean_distances(X=x,Y=W,squared=True)
K = np.exp(Z)
return K
N = 5000
low_x =-2*np.pi
high_x=2*np.pi
X = low_x + (high_x - low_x) * np.random.rand(N,1)
# f(x) = 2*(2(cos(x)^2 - 1)^2 -1
f = lambda x: 2*np.power( 2*np.power( np.cos(x) ,2) - 1, 2) - 1
Y = get_labels_improved(X , f)
K = 2 # number of centers for RBF
indices=np.random.choice(a=N,size=K) # choose numbers from 0 to D^(1)
subsampled_data_points=X[indices,:] # M_sub x D
stddev = 100
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 )
Y_pred = np.dot( Kern , C )
plt.plot(X, Y, 'o', label='Original data', markersize=1)
plt.plot(X, Y_pred, 'r', label='Fitted line', markersize=1)
plt.legend()
plt.show()
由于情节看起来很奇怪,我决定阅读有关绘图功能的文档,但我找不到任何明显的错误。
答案 0 :(得分:4)
主要问题是不幸选择用于插值的函数的标准偏差:
stddev = 100
您的功能(驼峰)的功能大小约为1.因此,请使用
stddev = 1
因为来自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个中心可以很好地适应。
import numpy as np
from sklearn.metrics.pairwise import euclidean_distances
import matplotlib.pyplot as plt
N = 5000
low_x =-2*np.pi
high_x=2*np.pi
X = np.sort(low_x + (high_x - low_x) * np.random.rand(N,1), axis=0)
f = lambda x: 2*np.power( 2*np.power( np.cos(x) ,2) - 1, 2) - 1
Y = f(X)
K = 30 # number of centers for RBF
indices=np.random.choice(a=N,size=K) # choose numbers from 0 to D^(1)
subsampled_data_points=X[indices,:] # M_sub x D
stddev = 1
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(Kern, Y)[0]
Y_pred = np.dot(Kern, C)
plt.plot(X, Y, 'o', label='Original data', markersize=1)
plt.plot(X, Y_pred, 'r', label='Fitted line', markersize=1)
plt.legend()
plt.show()