繁体   English   中英

为什么我一直将 Nan 作为输出?

[英]Why do I keep getting Nan as output?

我正在尝试用 C++ 编写一个简单的梯度下降算法(10,000 次迭代)。 这是我的程序:

#include<iostream>
#include<cmath>

using namespace std;

int main(){

  double learnrate=10; 
  double x=10.0; //initial start value

  for(int h=1; h<=10000; h++){
     x=x-learnrate*(2*x + 100*cos(100*x));
  }

  cout<<"The minimum is at y = "<<x*x + sin(100*x)<<" and at x = "<<x;

  return 0;
}

输出最终为:y=nan 和 x=nan。 我尝试通过将 x 和 y 的值放入一个文件来查看它们,经过一定量的迭代后,我得到了所有的 nan(对于 x 和 y)。 编辑:我将学习率(或步长)选为 10 作为实验,之后我将使用更小的值。

你的公式一定有问题。 x 的前 10 个值已经像地狱一样增加了:

-752.379
15290.7
-290852
5.52555e+06
-1.04984e+08
1.9947e+09
-3.78994e+10
7.20088e+11
-1.36817e+13
2.59952e+14

无论您选择什么起始值,下一个x的绝对值都会更大。

|next_x| = | x - 20 * x - 100 * cos(100*x) |

例如,考虑当您选择一个非常小的起始值 ( |x|->0 ) 时会发生什么,然后

|next_x| = | 0 - 20 * 0 - 100 * cos ( 0 ) | = 100

在调用余弦函数之前打印x ,您将看到在NaN (在h = 240 )之前打印的最后一个数字是:

-1.7761e+307

这意味着该值将趋于无穷大,无法表示(因此不是数字)。

它溢出了double类型。

如果您使用long double ,您将在 1000 次迭代中成功,但您仍然会在 10000 次迭代中溢出类型。

所以问题是参数learnrate太大了。 正如我上面建议的那样,您应该在使用范围更大的数据类型时执行 let 步骤。

因为在 h=240 时变量 "x" 超出了双精度类型的限制 (1.79769e+308)。 这是一个发散的等差数列。 您需要降低学习率。

还有几件事: 1- 不要使用“使用命名空间 std;” 这是不好的做法。 2- 您可以使用“std::isnan() 函数来识别这种情况。

下面是一个例子:

#include <iomanip>

#include <limits>
int main()
{


  double learnrate = 10.0;

  double x = 10.0; //initial start value

  std::cout<<"double type maximum=" << std::numeric_limits<double>::max()<<std::endl;
  bool failed = false;
  for (int h = 1; h <= 10000; h++)
  {

    x = x - learnrate*(2.0*x + 100.0 * std::cos(100.0 * x));
    if (std::isnan(x))
    {
      failed = true;
      std::cout << " Nan detected at h=" << h << std::endl;
      break;
    }
  }
  if(!failed)
  std::cout << "The minimum is at y = " << x*x + std::sin(100.0*x) << " and at x = " << x;

  return 0;
}

“学习率”太高了。 例如,将其更改为 1e-4,程序就可以运行,初始值至少为 10。 当学习率为 10 时,迭代跳得太远超过解决方案。

在最好的情况下,梯度下降不是一个好的算法。 对于严肃的应用程序,您希望使用更好的东西。 好多了。 搜索 Brent 优化器和 BFGS。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM