我最近在 Coursera 上使用 Python 完成了 Andrew Ng 的机器学习练习 3。
在最初完成练习的第 1.4 到 1.4.1 部分时,我遇到了困难,以确保我训练的模型具有与预期 94.9% 匹配的准确度。即使在调试并确保我的成本和梯度函数没有错误并且我的预测器代码正常工作之后,我仍然只能获得 90.3% 的准确率。我在scipy.optimize.minimize
.
出于好奇,我决定尝试另一种算法,并使用 Broyden-Fletcher-Goldfarb-Shannon (BFGS)。令我惊讶的是,准确率大幅提升至 96.5%,超出预期。CG 和 BFGS 这两种不同结果的比较可以在我的笔记本中查看标题Difference in accuracy due to different optimization algorithm。
造成这种准确性差异的原因是由于优化算法的选择不同吗?如果是,那么有人可以解释为什么吗?
此外,我将非常感谢对我的代码进行任何审查,以确保我的任何函数中都没有导致此问题的错误。
谢谢你。
编辑:在下面我添加了问题中涉及的代码,根据我在此页面中的评论中的请求,而不是让读者参考我的 Jupyter 笔记本的链接。
模型成本函数:
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def compute_cost_regularized(theta, X, y, lda):
reg =lda/(2*len(y)) * np.sum(theta[1:]**2)
return 1/len(y) * np.sum(-y @ np.log(sigmoid(X@theta))
- (1-y) @ np.log(1-sigmoid(X@theta))) + reg
def compute_gradient_regularized(theta, X, y, lda):
gradient = np.zeros(len(theta))
XT = X.T
beta = sigmoid(X@theta) - y
regterm = lda/len(y) * theta
# theta_0 does not get regularized, so a 0 is substituted in its place
regterm[0] = 0
gradient = (1/len(y) * XT@beta).T + regterm
return gradient
实现一对多分类训练的功能:
from scipy.optimize import minimize
def train_one_vs_all(X, y, opt_method):
theta_all = np.zeros((y.max()-y.min()+1, X.shape[1]))
for k in range(y.min(),y.max()+1):
grdtruth = np.where(y==k, 1,0)
results = minimize(compute_cost_regularized, theta_all[k-1,:],
args = (X,grdtruth,0.1),
method = opt_method,
jac = compute_gradient_regularized)
# optimized parameters are accessible through the x attribute
theta_optimized = results.x
# Assign thetheta_optimized vector to the appropriate row in the
# theta_all matrix
theta_all[k-1,:] = theta_optimized
return theta_all
调用该函数以使用不同的优化方法训练模型:
theta_all_optimized_cg = train_one_vs_all(X_bias, y, 'CG') # Optimization performed using Conjugate Gradient
theta_all_optimized_bfgs = train_one_vs_all(X_bias, y, 'BFGS') # optimization performed using Broyden–Fletcher–Goldfarb–Shanno
我们看到预测结果因所使用的算法而异:
def predict_one_vs_all(X, theta):
return np.mean(np.argmax(sigmoid(X@theta.T), axis=1)+1 == y)*100
In[16]: predict_one_vs_all(X_bias, theta_all_optimized_cg)
Out[16]: 90.319999999999993
In[17]: predict_one_vs_all(X_bias, theta_all_optimized_bfgs)
Out[17]: 96.480000000000004
对于任何想要获取任何数据来尝试代码的人,他们可以在我的 Github 中找到它,正如本文中链接的那样。