scipy中fmin_cg的梯度函数

时间:2016-05-16 20:03:38

标签: python algorithm numpy machine-learning scipy

我试图使用scipy的共轭梯度算法(fmin_cg)来找到在线性模型中最佳拟合的参数theta。

数据文件HouseData.csv(例如房屋面积,房价):

120, 250
200, 467
250, 500
1200, 2598
1500, 3000

代码是:

from scipy import optimize
import numpy as np

data=np.genfromtxt('HouseData.csv',delimiter=',')
X=np.c_[np.ones(len(data)),data[:,:-1]]
Y=data[:,[-1]]

def cost_Function(theta):
    theta1=theta[np.newaxis].T
    #print('theta: ',theta1)
    cost = Y-np.dot(X, theta1)
    return (cost*cost).sum()

# Gradient Function
def gradf(theta):
    theta1 = theta[np.newaxis].T
    cost = Y - np.dot(X, theta1)
    #print('cost*X.sum(0) is', np.sum(cost*X,axis=0))
    return np.sum(cost*X,axis=0)


x0 = np.asarray((0,1)) #initial guess
result = optimize.fmin_cg(cost_Function,x0,fprime=gradf)
print(result)    

如果没有fprime = gradf,代码会返回正确的结果,但是梯度函数有什么问题?当如上所述包含它时,算法将准确返回theta的输入。你还有什么不同的方法可以提高性能吗? 这只是一个简单的例子,但算法也应该运行X,其中包含许多列和行。

(python 3.5.1,scipy和numpy最新版本)

2 个答案:

答案 0 :(得分:3)

你的渐变显然是错误的。

由于您的成本函数是二次方,我们可以使用gradf(x) = (f(x + eps) - f(x - eps)) / (2 eps)合理地近似梯度。让我们尝试一下:

e0 = np.array([1, 0])
e1 = np.array([0, 1])
eps = 1e-5

x0 = np.array([1, 1])

df_yours = gradf(x0)
# array([  3.54000000e+03,   4.05583000e+06])

df_approx = np.array([
    cost_Function(x0 + eps*e0) - cost_Function(x0 - eps*e0),
    cost_Function(x0 + eps*e1) - cost_Function(x0 - eps*e1)
]) / (2 * eps)
# array([ -7.07999999e+03,  -8.11166000e+06])

没有进行数学分析(顺便说一下,你绝对应该做而不是猜测),你的渐变函数会偏离-0.5因子。这种负面影响非常重要。

答案 1 :(得分:1)

Eric关于渐变函数符号的评论至关重要。这是当前正在运行的代码,其中np.dot(X,theta1) - Y现在是正确的,并且因子0.5被添加到cost_Function

from scipy import optimize
import numpy as np

data=np.genfromtxt('HouseData.csv',delimiter=',')
X=np.c_[np.ones(len(data)),data[:,:-1]]
Y=data[:,[-1]]

def cost_Function(theta):
    theta1=theta[np.newaxis].T
    cost = Y-np.dot(X, theta1)
    return 0.5*(cost*cost).sum()

# Gradient Function
def gradf(theta):
    theta1 = theta[np.newaxis].T
    cost = np.dot(X, theta1) - Y
    return np.sum(cost*X,axis=0)

x0 = np.asarray((0.1,2)) #initial guess

result = optimize.fmin_cg(cost_Function,x0,fprime=gradf)
print(result)