在JavaScript中执行指数回归

如何解决在JavaScript中执行指数回归

重要更新:

经过大量研究和实验,我学到了一些东西,使我重新提出了这个问题。我不是在尝试找到“指数回归”,而是在尝试使用有界输入和潜在无界输出来优化非线性误差函数。

只要函数是线性的,就存在一种直接计算最佳参数以最小化平方误差项的方法(通过获取函数的导数,找到导数等于零的点,然后使用该局部最小值作为您的解决方案)。人们常常说“指数回归”是指a * e^(b*x)形式的方程。其原因如下所述,原因是通过获取双方的自然对数,可以将其完美地映射到线性方程上,因此可以使用相同的方法在一个步骤中直接进行计算。

但是在我的情况下,方程a * b^x不会映射到线性方程,因此没有直接解决方案。相反,必须迭代确定解决方案。

有一些非线性曲线拟合算法。尤其是Levenberg-Marquardt。我发现了该算法的一些实现:

不幸的是,我尝试了所有这三种实现,曲线拟合只是 残酷 。我有一些具有11,000点的样本数据,我知道其最佳参数为a = 0.08b = 1.19,但是这些算法通常返回诸如a = 117,b = 0.000001a = 0,b = 3243224

这样的奇怪结果。 >

接下来,我尝试使用Excel验证我对问题的理解。可以写一个定义为sum((y - y')^2)的误差函数,其中y'是给定参数和输入x的估计值。然后问题就落在最小化此错误功能上。我打开了数据(CSV),为“计算”值添加了一个列,为平方误差项添加了另一列,然后最终使用Solver优化了误差项的总和。这做得很漂亮!我回来了a = 0.0796,b = 1.1897。在同一张图上绘制两条线(原始数据和估计数据)显示出非常好的拟合度。

起初我尝试使用OpenOffice进行相同的操作,但是OpenOffice内置的求解器与我进行的Levenberg-Marquardt实验一样糟糕,并且反复给出了毫无价值的解决方案。即使我设置了初始值,它也会“优化”问题并提出比开始时更糟糕的事情。

在Excel中证明了我的概念之后,我尝试使用optimization-js。我尝试了他们的遗传优化和鲍威尔优化(因为我没有梯度函数),在两种情况下都产生了可怕的结果。

我确实找到了a question regarding how Excel's Solver works,它链接到an ugly PDF。我还没有花时间阅读PDF,但是它可能为手动解决问题提供了提示。我还发现a Python example据报道实现了通用梯度下降(与Excel相同的算法),因此,如果我能理解它并重写它以接受通用函数作为输入,那么我也许可以使用它。 / p>

新问题(给出了所有答案):

如何最好在JavaScript中使用(尽管其他语言也可以在AWS Lambda上运行,但是可以接受),如何才能将参数优化为以下函数以最小化其输出?

data = /* ... read from CSV ... */;
let errorFunc = function([a,b]) {
    let sumSqErr = 0;
    data.forEach(pt => {
        const est = a * Math.pow(b,pt.x);
        const err = est - pt.y;
        sumSqErr += err * err;
    });
    return sumSqErr * 1e-7;
}

旧问题:

给定几千个数据点,我想执行最小二乘回归分析以计算以下形式的方程的ab

y = a * b^x

在我上大学的时候,我知道如何使用矩阵数学来做到这一点,但恐怕那是10年前的事了,我已经退出了实践。我从使用https://www.youtube.com/watch?v=fb1CNQT-3Pg之类的YouTube系列矩阵开始,学习了最小二乘参数的计算-但是,在摸索了一下如何从 linear 回归到 指数 之一,我决定看看是否有人已经为我解决了这个问题,然后去Google搜索“ JavaScript指数回归”

这打开了两个库:

但是,这两个库都可以求解以下形式的方程:

y = a * e^(b*x)

我想知道是否有人可以帮助我将上述形式转换为我想要的形式(我可以在执行回归之前修改输入的yx值,例如计算或每个人的自然对数),或者是否有人可以指导我完成不使用第三方库的这种回归的基础知识(可能会使用math.js之类的东西来简化矩阵运算)

更新

考虑一下,我意识到为什么每个库都可以解决y = a * e^(b*x)了-取双方的自然对数可简化为基本的线性回归:

ln(y) = ln(a * e^(b*x))
ln(y) = ln(a) + ln(e^(b*x))
ln(y) = ln(a) + b*x

ln(a)替换为a',并在执行回归分析之前将所有输入y的值取自然对数(我们可以将新值称为y')显示我们现在只是在做线性回归:

y' = a' + bx (solve for a' and b)

然后您可以计算e^(a')来恢复a

不幸的是,由于指数的基数不是恒定的,所以我要解决的问题更加复杂。要“求解” b,必须有可能独自在方程的一侧获得b。我们能做的最好的是:

y = ab^x
(y/a) = b^x
(y/a)^(1/x) = b

这使我们取x的“第y根”我不完全确定这在实践中将如何(或是否)起作用?与之前的示例中,我对y个输入进行自然日志记录(对每个输入执行一个通用操作)不同,我需要对它执行 different 操作每个输入(一个y我取平方根,另一个我取立方根,另一个我取第四根,依此类推)

这种回归是否有可能只能迭代解决(例如,通过牛顿方法)?如果是这样,我将如何解决呢?我需要先计算一个复杂的导数吗?

解决方法

首要:

  • 我的方程是可微的,只是不确定如何将其微分。误差函数是一个和,因此偏导数只是使用链规则计算的和内部的导数。这意味着我可以使用任何需要梯度的非线性优化器算法
  • 当输入中的很小变化导致输出中的 大量 变化时,许多非线性优化器就会遇到麻烦,例如指数函数就是这种情况。调整阻尼参数或收敛参数可以对此有所帮助

经过一些工作,我能够得到一个梯度下降版本来计算与Excel相同的答案,但是运行却花了15秒钟(vs Excel在2秒钟之内就运行了Solver)–显然我的实现很差>

更重要的是

请参阅:https://math.stackexchange.com/a/3850781/209313

e^(bx)b^x之间没有有意义的区别。因为b^x == e^(log(b)*x)。因此,我们可以使用线性回归模型,然后通过将b发挥模型所产生的功效来计算e

使用regression-js

const reg = require("regression");
const data = /* ... get data from CSV ... */;
const results = reg.exponential(data);
console.log("a: " + results.equation[0] + ",b: " + Math.exp(results.equation[1]));

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res