Scipy数学函数的Scala实现

23 sec read

最近在推进项目的时候,遇到需要将线下的Python代码转化成线上的集群代码,由于机器代码环境是Scala,所以需要将代码翻译一遍,遇到的最大问题就是数学函数。由于Python环境下有很多强大的数学统计和分析的包,所以基本上很多数学函数可在Python包中找到,而Scala相对就弱一些。本次遇到的困难主要是以下三个数学函数:

gamma 函数的对数

该函数返回的是gamma 函数的对数,即gammaln(A) = log(gamma(A)) 。输入 A 必须是非负数和实数。gammaln 命令可避免直接使用 log(gamma(A)) 计算时可能会出现的下溢和上溢。

在scipy中其适用的是Cpython实现,基于此代码,可以有的解决方案为:

  • 抽离相关的C语言代码,将其编程成.so文件,在Scala中直接调用.so文件中的函数
  • 阅读相关的C语言代码,理解其逻辑,将其转化成Scala代码。

除了上述解决方式外,还可以寻找是否有现成的Scala代码

高斯超几何函数2F1(a,b,c,d)

hyp2f1是Scipy中高斯超几何函数的实现。找到了C语言出处,同样也找到了Scala实现

上述代码编译时会出错,主要原因是~^运算符不正确,正常情况下~为按位取反,^为按位异或。在这里很难解释清楚。查询了该项目,发现~^是被重新定义的为了求幂运算符。类似python中的**。类似实现:

指数函数的和的对数logsumexp

在讲解logsumexp函数之前我们先要了解下这个函数是用来做什么的。假设我们有N个实数\{x_n\}_{n=1}^N,我们想要求如下公式:

    \[z = \log \sum_{n=1}^{N}\exp\{x_n\}\]

如果x_n很大或很小,直接计算可能会上溢出或下溢出,从而导致严重问题。举个例子,对于[0 1 0],直接计算是可行的,我们可以得到1.55。但对于[1000 1001 1000],却并不可行,我们会得到inf;对于[-1000,-999,-1000],还是不行,我们会得到-inf。导致此问题的原因是因为浮点数只有64位,在计算指数函数的环节exp{1000}会发生上溢出,计算exp(-1000)时会发生下溢出。即便在数学世界上式的值显然不是无穷大,但在计算机的浮点数世界里就是求不出来。解决方案很简单:

    \[\log \sum_{n=1}^{N}\exp\{x_n\} = a + \log \sum_{n=1}^{N}\exp\{x_n - a\}\]

对任意a都成立,这意味着我们可以自由地调节指数函数的指数部分,一个典型的做法是取\{x_n\}_{n=1}^N中的最大值。Python实现:

由于逻辑比较简单,直接翻译为Scala即可,这里不做详细解释了。

打赏作者
微信支付标点符 wechat qrcode
支付宝标点符 alipay qrcode

C语言学习:size_t

在学习C语言的时候,遇到了一个新的数据类型size_t,截止目前也没有完全理清这个类似的具体场景及出现的原因。
44 sec read

C语言学习:main()函数的正确写法

C语言虽然是一门古老的语言,但是其标准一直在完善,所以很多以前支持的语法在到当前已经不能在使用了。 C语言的版
41 sec read

学习C语言是否已经过时?

C 语言诞生与1972年,作为一中古老的编程语言一直存在着,有些人想问,现在还值得去学习C语言吗?学习更加现代
13 sec read

发表评论

电子邮件地址不会被公开。 必填项已用*标注