Haskell hmatrix Vector 和 Matrix 的数据类型

Haskell data type for hmatrix Vector and Matrix

我刚刚开始学习 Haskell,我已经阅读了 LYAH 的定义数据类型部分,并且正在尝试为置信度传播实施 Sum-Product 算法。其中一项基本任务是定义概率图形模型。

如下所示,我试图通过打结来表示图,其中每个节点代表高斯分布并且具有与其邻居的恒定权重链接(目前)。但是,在尝试定义 Mean 和 Covariance 类型时,我在指定 Matrix 和 Vector 类型的类型时遇到了一些困难,即 Float 或 Double。

module Graph(Graph) where

import Numeric.LinearAlgebra

data Mean = Mean Vector
data Covariance = Covariance Matrix
data Gaussian = Gaussian Mean Covariance

data Node = Node [Node] Gaussian
data Graph = Graph [Node]

在这个简单的示例中,将均值定义为双精度类型的向量并将协方差定义为双精度类型的矩阵的语法是什么。此外,如何概括以使 MeanCovariance 可以是 Float 或 Double 类型?

我目前从 GHCi 获得以下信息

Graph.hs:5:18: error:
    • Expecting one more argument to ‘Vector’
      Expected a type, but ‘Vector’ has kind ‘* -> *’
    • In the type ‘Vector’
      In the definition of data constructor ‘Mean’
      In the data declaration for ‘Mean’
Failed, modules loaded: none.

我正在按照描述使用 hmatrix 包 here

VectorMatrix 在标量类型上进行了参数化(因此您不仅可以拥有浮点“实数”矩阵,还可以拥有整数矩阵、复数矩阵等) .这就是 GHC 通过 ‘Vector’ has kind ‘* -> *’ 告诉你的:就其本身而言,Vector 不是一个类型(类型有种类 *,又名 Type)。相反,它是一个 类型函数 将类型 * 映射到类型 * 的类型。像 Double 这样的标量已经是普通类型,所以你可以只对它们应用 Vector

GHCi> :kind Vector
Vector :: * -> *
GHCi> :k Double
Double :: *
GHCi> :k Vector Double
Vector Double :: *

因此你需要

newtype Mean = Mean (Vector Double)
newtype Covariance = Covariance (Matrix Double)

(newtype 与此处的 data 做同样的事情,但效率更高一点,因为不需要额外的 box/pointer)。

或者,您可以使用更有意义类型的向量 spaces,例如

import Math.LinearMap.Category

newtype Mean v = Mean v
newtype Covariance v = Covariance (v +> DualVector v)

这样做的好处是在编译时检查维度,这可以防止严重的运行时错误(原则上也可以提高性能,但坦率地说 linearmap-category 库还没有优化)。

然后您还可以通过向量参数化其他类型 space:

data Gaußian v = Gaußian (Mean v) (Covariance v)
data Node v = Node [Node v] (Gaussian v)
data Graph v = Graph [Node v]

与您的问题有些无关:这种打结确实感觉很优雅,但它并不是表示图形的合适方式,因为无法对节点进行身份检查。对于所有可区分的方法,图中的任何循环都会导致无限结构。在实践中,你不会绕过给你的节点,例如Int 标签并为边缘保留单独的结构。