首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >优化算法的选择是否影响多类logistic回归的准确性?

优化算法的选择是否影响多类logistic回归的准确性?
EN

Data Science用户
提问于 2017-07-04 15:50:47
回答 2查看 756关注 0票数 7

我最近完成了安德鲁·吴的机器学习练习3--用Python实现课程学习

在最初完成练习的1.4至1.4.1部分时,我遇到了一些困难,以确保我的训练模型的准确性达到预期的94.9%。即使在调试并确保我的成本和梯度函数没有bug,并且我的预测器代码工作正常之后,我仍然只能得到90.3%的准确性。我在scipy.optimize.minimize中使用共轭梯度(CG)算法。

出于好奇,我决定尝试另一种算法,并使用Goldfarb (BFGS)。令我惊讶的是,准确度大大提高到96.5%,超出了我的预期。由于优化算法的不同,CG和BFGS的两种不同结果的比较可以在我的记事本中看到。

这是由于不同的优化算法选择不同的精度差异的原因吗?如果是,那么谁能解释一下原因吗?

此外,我非常希望对我的代码进行任何检查,以确保在我的任何函数中没有导致这种情况的错误。

谢谢。

编辑:下面我添加了这个问题所涉及的代码,在这个页面中我这样做的评论中的请求,而不是让读者参考到我的木星笔记本的链接。

模型成本函数:

代码语言:javascript
复制
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

实现一个-vs-所有分类培训的函数:

代码语言:javascript
复制
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

调用函数用不同的优化方法训练模型:

代码语言:javascript
复制
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

我们看到,根据所使用的算法,预测结果不同:

代码语言:javascript
复制
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中找到链接在这篇文章中。

EN

回答 2

Data Science用户

回答已采纳

发布于 2017-07-08 10:04:17

对数值精度和稳定性的限制导致优化例程陷入困境。

通过将正则化术语更改为0.0,您可以很容易地看到这一点--这在原则上没有理由不起作用,而且您没有使用任何特别需要它的特性工程。当正则化设置为0.0时,您将看到精度达到极限,并在计算成本函数时尝试获取0的日志。两种不同的优化程序会受到不同的影响,因为在路线上取不同的样本点到最小。

我认为,随着调整期设定得很高,你可以消除数值上的不稳定性,但代价是看不到计算的真实情况--实际上,正则化条件在困难的训练例子中占主导地位。

您可以通过修改成本函数来弥补某些准确性问题:

代码语言:javascript
复制
def compute_cost_regularized(theta, X, y, lda):
    reg =lda/(2*len(y)) * np.sum(theta[1:]**2) 
    return reg - 1/len(y) * np.sum(
      y @ np.log( np.maximum(sigmoid(X@theta), 1e-10) ) 
      + (1-y) @ np.log( np.maximum(1-sigmoid(X@theta), 1e-10) ) )

此外,为了在培训过程中获得一些反馈,您可以添加

代码语言:javascript
复制
                       options = {
                           'disp': True
                       }

minimize的电话。

通过这种改变,您可以尝试将正则化项设置为零。当我这么做的时候,我得到:

代码语言:javascript
复制
predict_one_vs_all(X_bias, theta_all_optimized_cg)
Out[156]:
94.760000000000005
In [157]:

predict_one_vs_all(X_bias, theta_all_optimized_bfgs)
/usr/local/lib/python3.6/site-packages/ipykernel/__main__.py:2: RuntimeWarning: overflow encountered in exp
  from ipykernel import kernelapp as app
Out[157]:
98.839999999999989

CG值94.76似乎与预期的结果很好地匹配-所以我想知道这是否是在没有调整的情况下完成的。BFGS值仍然“更好”,尽管我不确定在培训和评估期间给出警告消息时我有多信任它。要判断这个明显更好的训练结果是否真的转化为更好的数字检测,您需要在一个持久测试集上测量结果。

票数 3
EN

Data Science用户

发布于 2017-07-11 12:07:47

CG不收敛到最小值,也不收敛于BFGS

请允许我在这里给我自己的问题加上一个答案,给一个自愿看我代码的好朋友的学分。他不在Data上,也不觉得有必要创建一个账户来发布答案,所以他错过了这个机会,把这个机会发给了我。

我也要参考@Neil,因为他对数值稳定性问题的分析有可能解释这一点。

因此,我的解决方案背后的主要前提是:

我们知道成本函数是凸的,这意味着它没有局部变量,而且只有一个全局最小值。由于用BFGS训练的参数比用CG训练的预测要好,这意味着BFGS比CG更接近于最小值。无论BFGS是否收敛到全球最小值,我们都不能肯定,但我们可以肯定地说,它比CG更接近。

因此,如果我们使用CG训练的参数,并通过使用BFGS的优化例程,我们应该看到这些参数得到进一步的优化,因为BFGS使一切接近最小。这将提高预测精度,使其更接近于普通BFGS训练得到的预测精度。

下面是验证这一点的代码,变量名称与问题中的相同:

代码语言:javascript
复制
# Copy the old array over, else only a reference is copied, and the 
# original vector gets modified
theta_all_optimized_bfgs_from_cg = np.copy(theta_all_optimized_cg)

for k in range(y.min(),y.max()+1):
    grdtruth = np.where(y==k, 1,0)
    results = minimize(compute_cost_regularized,theta_all_optimized_bfgs_from_cg[k-1,:], 
                       args = (X_bias,grdtruth,0.1),
                       method = "BFGS", 
                       jac = compute_gradient_regularized, options={"disp":True})
    # 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_optimized_bfgs_from_cg[k-1,:] = theta_optimized

在执行循环期间,只有一个迭代产生了显示非零次数优化例程迭代的消息,这意味着执行了进一步的优化:

代码语言:javascript
复制
Optimization terminated successfully.
         Current function value: 0.078457
         Iterations: 453
         Function evaluations: 455
         Gradient evaluations: 455

其结果得到了改进:

代码语言:javascript
复制
In[19]:  predict_one_vs_all(X_bias, theta_all_optimized_bfgs_from_cg)
Out[19]:  96.439999999999998

通过进一步的训练从CG获得的参数,通过额外的BFGS运行,我们进一步优化了它们,给出了96.44%的预测精度,它非常接近于直接使用BFGS获得的96.48%

我用这个解释更新了我的笔记本。

当然,这会引发更多的问题,比如为什么CG在这个成本函数上的效果不如BFGS,但我想这些问题都是针对另一篇文章的。

票数 2
EN
页面原文内容由Data Science提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://datascience.stackexchange.com/questions/20170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档