performance - F# Pick 基于输入的函数?

标签 performance f# sigmoid

我有以下功能

let private sigmoid (z:float) =
    1.0 / (1.0 + exp(-z))
let private sigmoidM (z : Matrix<float>) : Matrix<float> =
    z.Map (fun x -> sigmoid(x))
let private sigmoidV (z:Vector<float>) =
    z.Map(fun x -> sigmoid(x))

我只想使用 sigmoid,它根据输入对标量、向量或矩阵执行。

也就是说,此函数需要非常高效,因为它位于循环的最关键部分。关于如何做到这一点的任何见解?如果它会很慢,请随意发布如何谨慎它会很慢。

最佳答案

您可以使用标准的 .NET 重载:

open MathNet.Numerics.LinearAlgebra

type Sigmoid() = class end with
    static member sigmoid (z:float) = 1.0 / (1.0 + exp(-z))
    static member sigmoid (z:Matrix<float>) = z.Map (fun x -> Sigmoid.sigmoid(x))
    static member sigmoid (z:Vector<float>) = z.Map (fun x -> Sigmoid.sigmoid(x))

// Usage
let x = Sigmoid.sigmoid 4.3
let y = Sigmoid.sigmoid (matrix [[1.0; 2.0]; [3.0; 4.0]])
let z = Sigmoid.sigmoid (vector  [1.0; 2.0])

// Results
val x : float = 0.9866130822
val y : Matrix<float> = 
          DenseMatrix 2x2-Double
            0.731059  0.880797
            0.952574  0.982014
val z : Vector<float> = seq [0.7310585786; 0.880797078]

这不会影响性能,因为重载解析是在编译时完成的。

对标准 .NET 重载不满意?不想将函数编码为成员?您想让它更通用(也接受 float32)并可扩展到其他类型吗?

使用静态类型约束:

type Sigmoid() = class end with
    static member Sigmoid (_:Sigmoid, z:float  ) = 1.0  / (1.0  + exp(-z))
    static member Sigmoid (_:Sigmoid, z:float32) = 1.0f / (1.0f + exp(-z))

let inline _sigmoid (s:'Sigmoid) (x:'T) :'T =
    ((^T or ^Sigmoid) : (static member Sigmoid : 'Sigmoid * 'T -> 'T) (s, x))

let inline sigmoid x = _sigmoid (Sigmoid()) x 

type Sigmoid  with
    static member inline Sigmoid (_:Sigmoid, z:Matrix<'T>) = z.Map (fun x -> sigmoid x)
    static member inline Sigmoid (_:Sigmoid, z:Vector<'T>) = z.Map (fun x -> sigmoid x)

// Usage
let x = sigmoid 4.3
let y = sigmoid (matrix [[ 1.0; 2.0 ];[ 3.0; 4.0 ]])
let z = sigmoid (vector [ 1.0; 2.0 ])

let x' = sigmoid 4.3f
let y' = sigmoid (matrix [[1.0f; 2.0f];[ 3.0f; 4.0f]])
let z' = sigmoid (vector [ 1.0f; 2.0f])

更新

请注意,@TheInnerLight 在评论中指出,对于您的特定 sigmoid 函数,您还可以编写:

let inline sigmoid z = 
    LanguagePrimitives.GenericOne / (LanguagePrimitives.GenericOne + exp(-z))

这适用于 floatfloat32

这最终也适用于向量和矩阵,具体取决于它们的实现。

如果所有操作取反、除法和 exp 已经是这些类型的泛型,并且它们都支持 GenericOne,那么对于您的特定情况,这将是一个更好的解决方案。

不幸的是,截至目前,MathNet 并未以这种方式为 Matrix 和 Vector 实现 GenericOneexp

关于performance - F# Pick 基于输入的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37752451/

相关文章:

mysql - 单表层次结构的性能问题

f# - 计算表达式中的递归函数

F#:有没有办法通过 ObjectExpression 将属性添加到类型输出

java - 什么时候在神经网络中实现 Sigmoid 函数?

python - Keras 二元分类 - Sigmoid 激活函数

python - 提高 pandas python 的性能

c# - 如何为二维 LINQ 操作创建高效的数据结构?

c# - Azure移动服务: Serialization of Tables

python - 计算 sigmoid 最快的方法是什么?

SQL Server SELECT 最后 N 行