【问题标题】:expand 1 dim vector by using taylor series of log(1+e^x) in python在 python 中使用 log(1+e^x) 的泰勒级数展开 1 个暗淡向量
【发布时间】:2020-10-27 05:59:02
【问题描述】:

我需要使用特定非线性函数的泰勒级数扩展 (e^x or log(x) or log(1+e^x)) 对来自 1 个暗像素向量的每个像素值进行非线性扩展,但至少基于泰勒级数,我目前的实现不适合我概念。背后的基本直觉是将像素阵列作为 CNN 模型的输入神经元,其中每个像素都应该通过非线性函数的泰勒级数展开进行非线性展开。

新更新 1

根据我对泰勒级数的理解,泰勒级数是根据函数F 的值为变量x 的函数F 编写的,它是变量x0 的另一个值的导数。在我的问题中,F 是特征(又名像素)的非线性变换的函数,x 是每个像素值,x0 是麦克劳林级数逼近为 0。

新更新 2

如果我们使用log(1+e^x) 的泰勒级数,近似阶数为 2,则每个像素值将通过取泰勒级数的第一个和第二个展开项产生两个新像素。

图解

这是上述公式的图解说明:

其中X是像素数组,p是泰勒级数的近似阶,α是泰勒展开系数。

我想用非线性函数的泰勒级数展开来非线性地展开像素向量,如上图所示。

我目前的尝试

这是我当前的尝试,它不适用于像素阵列。我在考虑如何使同样的想法适用于像素数组。

def taylor_func(x, approx_order=2):
    x_ = x[..., None] 
    x_ = tf.tile(x_, multiples=[1, 1, approx_order+ 1])  
    pows = tf.range(0, approx_order + 1, dtype=tf.float32) 
    x_p = tf.pow(x_, pows) 
    x_p_ = x_p[..., None]
    return x_p_

x = Input(shape=(4,4,3))
x_new = Lambda(lambda x: taylor_func(x, max_pow))(x)

我的新尝试

x_input= Input(shape=(32, 32,3))

def maclurin_exp(x, powers=2):
    out= 0
    for k in range(powers):
        out+= ((-1)**k) * (x ** (2*k)) / (math.factorial(2 * k))
    return res

x_input_new = Lambda(lambda x: maclurin_exp(x, max_pow))(x_input)

这种尝试不会产生上述数学公式所描述的内容。我敢打赌我在扩展时错过了一些东西。谁能指出我如何纠正这个问题?有更好的主意吗?

目标

我想采用像素向量并通过某些非线性函数的泰勒级数展开来进行非线性分布或展开。有没有办法做到这一点?有什么想法吗?谢谢

【问题讨论】:

  • 嗨,Jared,你能澄清一下你的想法吗?我不明白你写的方程式。您是否尝试将大小为N 的输入图像替换为M 与像素值x[i] 的大小为pN 的连接数组M 与形式为x[i]**k 的元素块,与k=1...pp 作为泰勒级数的截断幂?
  • 我想这是我不完全理解的部分。泰勒级数是为变量x 的函数F 编写的,根据函数F 的值,它是变量x0 的另一个值的导数。所以当你说expand pixel vector with Taylor series expansion 时,我不清楚函数是什么,变量是什么。函数是否代表像素的值,而变量是其在二维数组中的坐标(离散值)?
  • 看不懂function is Taylor expansion of non-linear function的概念。考虑一个简单的幂 2 截断 Taylor series,就像它在您的原始帖子 F(x) = F(x0) + F'(x0)*(x-x0) + 0.5*F''(x0)*(x-x0)**2 中一样。什么Fxx0 在这里?如果x是原图,那么x0是什么?
  • 我有一些想法。第一个是 log(0) 和 ln(0) 渐近到负无穷大。另外,我正在做一个泰勒级数扩展,因为它更灵活。但今晚或明天我应该有东西给你。私聊也没问题。
  • 您知道,我正在努力为您提供最灵活和最完整的答案,我可以给出我理解的问题。我首先关注代码,因为这是您提出的问题。至于样条,我有点需要看看它会融入你正在做的事情中。

标签: python tensorflow conv-neural-network nonlinear-functions taylor-series


【解决方案1】:

这是一个非常有趣的问题,但我还不能说我对此很清楚。所以,虽然我有一些想法,但我可能会错过你想要做的事情的主旨。

您似乎想开发自己的激活函数,而不是使用 RELU 或 softmax。那里当然没有坏处。你给了三个候选人:e^x, log(x), and log(1+e^x)

注意 log(x) 渐近地接近负无穷 x --> 0。所以,log(x) 是正确的。如果这是为了检查你得到的答案,或者是在你入睡时记下的东西,不用担心。但如果不是,您应该花一些时间并确保您了解您所做的事情的基础,因为后果可能非常严重。

您表示您正在寻找一个规范的答案,而您在这里得到了一个二合一的答案。你会得到一个规范的答案和高性能的代码。

考虑到您不太可能编写出比 SciPy、Numpy 或 Pandas 更快、更精简的代码。或者,PyPy。或者 Cython。他们的东西是标准的。因此,不要试图通过编写自己的、性能较低(并且可能存在错误)的版本来与它们竞争,然后随着时间的推移您将不得不对其进行维护。相反,通过使用它们来最大化您的开发和运行时间。

让我们看一下 SciPy 中的 e^x 实现,并为您提供一些可以使用的代码。我知道您在这个阶段不需要图表,但它们很漂亮,可以帮助您了解 Taylor(或 Maclaurin,又名 Euler-Maclaurin)将如何随着近似顺序的变化而工作。恰好 SciPy 内置了泰勒近似。

import scipy
import numpy as np
import matplotlib.pyplot as plt

from scipy.interpolate import approximate_taylor_polynomial

x = np.linspace(-10.0, 10.0, num=100)

plt.plot(x, np.exp(x), label="e^x", color = 'black')

for degree in np.arange(1, 4, step=1):

    e_to_the_x_taylor = approximate_taylor_polynomial(np.exp, 0, degree, 1, order=degree + 2)

    plt.plot(x, e_to_the_x_taylor(x), label=f"degree={degree}")

plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.0, shadow=True)

plt.tight_layout()
plt.axis([-10, 10, -10, 10])
plt.show()

产生这个:

但是假设你擅长“数学”,可以这么说,并且如果它更“数学”,那么你愿意使用稍微慢一些的东西,因为它可以很好地处理符号表示法。为此,我建议使用 SymPy。

考虑到这一点,这里有一些带有图表的 SymPy 代码,因为它看起来不错,而且我们需要返回并再次点击另一个点。

from sympy import series, Symbol, log, E
from sympy.functions import exp
from sympy.plotting import plot
import matplotlib.pyplot as plt
%matplotlib inline

plt.rcParams['figure.figsize'] = 13,10
plt.rcParams['lines.linewidth'] = 2

x = Symbol('x')

def taylor(function, x0, n):
    """ Defines Taylor approximation of a given function
    function -- is our function which we want to approximate
    x0 -- point where to approximate
    n -- order of approximation
    """    
    return function.series(x,x0,n).removeO()

# I get eyestain; feel free to get rid of this
plt.rcParams['figure.figsize'] = 10, 8
plt.rcParams['lines.linewidth'] = 1

c = log(1 + pow(E, x))

plt = plot(c, taylor(c,0,1), taylor(c,0,2), taylor(c,0,3), taylor(c,0,4), (x,-5,5),legend=True, show=False)

plt[0].line_color = 'black'
plt[1].line_color = 'red'
plt[2].line_color = 'orange'
plt[3].line_color = 'green'
plt[4].line_color = 'blue'
plt.title = 'Taylor Series Expansion for log(1 +e^x)'
plt.show()

我认为任何一个选项都能让你到达你需要去的地方。

好的,现在谈谈另一点。经过一番修改后,您明确表示 log(1 +e^x) 是您的首选。但其他人没有通过嗅探测试。 e^x 随着多项式次数的变化而剧烈波动。由于算法的不透明性以及很少有人能从概念上理解这些东西,数据科学家可以把事情搞砸到人们甚至无法想象的程度。因此,请确保您对此的理论非常扎实。

最后一件事,考虑将 Erlang Distribution 的 CDF 视为一个激活函数(假设我是对的,并且您希望将自己的激活函数作为一个研究领域)。我认为没有人看过它,但它看起来很有希望。我认为您可以将 RGB 的每个通道分解为两个参数之一,另一个是物理坐标。

【讨论】:

    【解决方案2】:

    您可以使用tf.tiletf.math.pow 来生成级数展开的元素。然后您可以使用tf.math.cumsum 计算部分和s_i。最终,您可以乘以权重 w_i 并计算最终总和。

    这是一个代码示例:

    import math
    import tensorflow as tf
    
    x = tf.keras.Input(shape=(32, 32, 3))  # 3-channel RGB.
    
    # The following is determined by your series expansion and its order.
    # For example: log(1 + exp(x)) to 3rd order.
    # https://www.wolframalpha.com/input/?i=taylor+series+log%281+%2B+e%5Ex%29
    order = 3
    alpha = tf.constant([1/2, 1/8, -1/192])  # Series coefficients.
    power = tf.constant([1.0, 2.0, 4.0])
    offset = math.log(2)
    
    # These are the weights of the network; using a constant for simplicity here.
    # The shape must coincide with the above order of series expansion.
    w_i = tf.constant([1.0, 1.0, 1.0])
    
    elements = offset + alpha * tf.math.pow(
        tf.tile(x[..., None], [1, 1, 1, 1, order]),
        power
    )
    s_i = tf.math.cumsum(elements, axis=-1)
    y = tf.math.reduce_sum(w_i * s_i, axis=-1)
    

    【讨论】:

    • @Jared 是 elements 张量,它代表级数展开的元素。它的形状为(?, 32, 32, 3, order),其中order 是级数展开的顺序。所以第一个词是elements[..., 0],第二个词是elements[..., 1]等等。
    • @Jared delta1 和 delta2 是什么?它是在哪里定义的?
    • 它在我的帖子中显示在图表上方。 delta1 是第一个泰勒展开项,delta2 是第一个和第二个展开项之和。我想将 delta1 和 delta2 作为两个新扩展的神经元,它们将独立地传递给卷积滤波器。如果可能的话,是否有可能扩展您的想法?非常感谢!
    • @Jared 当然,在上面的代码中就是s_i。它是所有系列元素沿轴的累积和,因此s_i[..., 0] 只是第一项,s_i[..., 1] 是第一项和第二项之和,依此类推。
    • @Jared 对于特定订单没有硬编码,它适用于任何订单。最后一个维度的大小决定了顺序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    • 2016-01-24
    • 2022-06-18
    • 2021-12-26
    • 2014-03-27
    • 2020-02-18
    • 2020-04-10
    相关资源
    最近更新 更多