Julia: Base内积的状态

创建于 2018-01-15  ·  146评论  ·  资料来源: JuliaLang/julia

如果用户需要为一般 Hilbert 空间定义自定义内积,那么 Base 中这种泛化的当前状态是什么? https://github.com/JuliaLang/julia/issues/16573是一个相关但不太普遍的问题。 我关心的是不是数组的新类型。

我想建议将dot重命名为inner ,或者可能指导用户将inner(x,y)定义为对象xy之间的一般内积

inner(x::AbstractVector, y::AbstractVector) = dot(x, y)

如果更改是合理的,它可以成为 Julia v1.0 的一部分吗?

linear algebra

最有用的评论

自从#27401 现在合并后,是否应该关闭它?

所有146条评论

您能否详细解释一下您的用例,以及为什么将它放在 Base 中而不是仅在包中定义它是有益的? 一个具体的例子是最好的。 您是否期望同时加载的包中有多个inner定义?

我认为为这些数学空间提供正式的接口将帮助用户更好地利用类型系统。 例如,我希望聚类方法适用于任何度量空间。 如果我可以使用内部产品定义我的类型,我将从开箱即用的Clustering.jl中受益(在相应地修复包之后)。 也可以推广许多其他基于距离或基于投影的算法。

作为一个具体的例子,我今天在尝试为成分数据定义几何时遇到了这个限制: https ://github.com/juliohm/CoDa.jl 我宁愿专注于一个著名的inner函数在 Base 中定义而不是定义我自己的接口,其他人都不会知道。

为什么不为您的 Hilbert 空间类型扩展dot ? 我很确定它的设计考虑了通用的内部产品。

点积的概念比内积的概念更严格。 后者是为一般空间定义的,而点积仅在存在由有限基定义的坐标系概念时才定义。 dot(x,y)的语义是x'*y ,其中xy表示笛卡尔世界中对象的坐标。 数学教科书很少会提到点积这个词,因为作者通常有兴趣在更一般的(不一定是有限或欧几里得)空间中处理材料。

为了进一步区分,在具有内积<x,y> (或inner(x,y) )的希尔伯特空间中,对象可以是无限的,并且语义x'*y不适用。 例如,在泛函数据分析中,对象是函数fg ,内积通常通过数值积分获得: inner(f,g) = quadrature(f*g) 。 将此操作称为点积具有误导性。

我在CoDa.jl包中指出的另一个例子是成分数据。 组合对象位于单纯形世界中, x'*y操作对它没有任何意义。 但是,存在一种等距变换(对数比变换),人们可以使用该变换将组合映射到另一个几何图形中,然后可以将点积与坐标一起应用。 使用坐标不是必需的,但这是该领域的常见做法。 结果可以返回到对象存在的原始空间。

我看不出在语言中维护术语dot有什么好处,但是如果有人要求向后兼容,那么概括inner(x::AbstractVector, y::AbstractVector) = dot(x,y)就可以完美地工作。

你能详细说明反对这一改变的理由吗?

你能详细说明反对这一改变的理由吗?

我们通常需要相当多的理由来向 Base 添加新的公共功能,这就是反对意见。 这可以由InnerProducts包提供。 为什么需要将它内置到语言本身中? 这是@andreasnoack上面提出的第一个问题——它得到了一个有点模糊的答案:“我认为这些数学空间的正式接口将帮助用户更好地利用类型系统”。 包中定义的接口没有任何理由比 Base 中的接口更正式。 Base.inner提供了InnerProducts.inner没有的什么? 这是一个真正的问题,可以有一个令人信服的答案,但我不知道那个答案可能是什么,这就是为什么要问这个问题。

我没有看到一个好的论据来定义一个基本的数学概念,比如在 Base 中没有的其他地方的内积。 主要受众是科学计算人员的语言将受益于正确的术语。 为什么norm的概念是在Base.LinAlg中定义的,而在同一个队列上的inner应该在一个包中定义? 除了这种不一致之外,该语言已经有了dot ,这让我想知道为什么它应该有如此具体的东西而不是更笼统的概念?

所以你想要基础语言中所有可能的数学概念? 在 Base 中没有定义的东西不会强迫人们使用错误的术语。 norm函数是从LinAlg导出的,因为它是在LinAlg中定义和使用的。 dot类似。 您是否建议将dot重命名为inner

所以你想要基础语言中所有可能的数学概念?

我从没有说过。

在 Base 中没有定义的东西不会强迫人们使用错误的术语。

我确信它不会。 推广错误的术语是问题所在。 来自较少数学背景的人会采用点的用法,因为他们在 Base 中看到它。 使用术语“点”积来表示内积的概念是不正确的。 这对数学界也是有害的,数学界时不时地努力修复错误术语留下的这些伤疤。 我这一代的学生总是不得不参考旧书来正确理解术语,这不应该是这样。

您是否建议将点重命名为内部

在我看来,这已经是一个重大改进。 请参阅我上面给出的关于功能和成分数据的所有示例。 这些社区的人们永远不会在他们的工作中使用dot这个词。 “点”更像是一个计算机科学术语,而不是其他任何东西。

除了dot之外,将dot重命名为inner与将inner添加到 Base 是完全不同的提议。 这更像是一个“正确的术语”问题,您和其他 linalg 人员将不得不对此进行讨论,尽管我似乎记得我们曾经对此进行过讨论并得出结论dot是此函数实现的正确名称。

将 dot 重命名为 inner 与在 dot 之外添加 inner 到 Base 是完全不同的提议。

这是我在此线程的第一条消息中提出的:

我想建议将 dot 重命名为 inner,或者指导用户将 inner(x,y) 定义为对象 x 和 y 之间的一般内积

我再说一遍,点积是我在这里讨论的操作的不正确术语。 内积、外积、标量积……这些都是数学对象。 “点积”是一个计算对象:它获取两个数字序列并执行x1*y1 + x2*y2 + ... xn*yn ,这在其他数学空间中是无用的操作。

我专注于您提出的第二个选项,这似乎是添加Base.inner并作为后备调用Base.dot 。 任何一个选项都是可能的,但都需要一些理由:要添加一个新操作,需要一个理由,为什么它不能只是在一个包中(这个讨论的最初部分是关于什么的); 要重命名,需要确定dot是错误的名称,而inner是正确的名称(对话似乎已经转向)。

@juliohm值得(重新)说明目前正在积极努力缩小Base并鼓励使用软件包。 在这种情况下, dot似乎对于标准 Julia 中提供的参与线性代数的所有类型都是正确的(即NumberArray - 所以是的,有一个明确的、已知的,在所有情况下都是有限的基础——因此我认为我们在术语上没有犯错,尽管可能有更好的选择)。 我不反对这个提议——但想指出这一点来澄清为什么你可能会遇到一些“潜在的”变革阻力。

同样值得记住的是,相当多的 Julia 新人可能熟悉点积,但不熟悉内积(例如,他们在大学里学过一点物理,但不是数学专业的),所以也有一些理由保留dot (更不用说我们有一个与之对应的中缀运算符 - 我想我们可以将它映射到inner ,但这有点不太明显)。 我们也没有outer函数或各种其他可能的操作。

因此,有一个负担来说明如何将其放入Base (或LinAlg )中比将其放入用户包中更好。 主要原因似乎是提供一个可以被其他人共享和扩展的接口——这是一个合理的总结吗? 关于让Clustering.jl中的通用代码与您的内部产品一起工作的论点似乎非常引人注目。 此外,在我们似乎将LinAlg拆分为 stdlib 包的上下文中 - 我在想,如果我要编写一个名为LinearAlgebra的包,我可能会很乐意包含一个inner功能供其他人扩展。

感谢@andyferris分享您的想法。 我非常清楚地看到了阻力,这是我不太兴奋的事情。 不过,我很好奇这个具体的提议是如何导致代码增加的? 对我来说,这似乎是代码中的一个微不足道的变化,抽象方面的重大改进。 Clustering.jl 的示例只是众多示例之一,请考虑任何基于内核的方法,该方法可以用于存在内积概念的任意 Julia 类型。 MultivariateStats.jl 有很多。

关于关于LinAlg拆分为单独包的评论,我同意这似乎是封装数学产品的好地方。 我假设未来的这个LinearAlgebra包将默认导入到 Julia 会话中,因此所有用户都可以访问innerouter等概念马上。

是的,标准库都是与 Julia 系统映像一起构建的,并且默认可用。 至少对于 v1.x 系列,没有人需要输入using LinAlg (我认为它不会被重命名为LinearAlgbebra ,顺便说一句,我只是把它作为一个假设的竞争对手) .

澄清一下,它将加载标准 Julia,因此您不必安装任何东西,但您仍然需要编写using LinAlg来获取它导出的名称。

这就是奇怪的地方,对吧,因为我们将在没有using LinAlg的情况下获得*方法等等? (换句话说, LinAlg是一种盗版)。

是的,这基本上就是我们必须划清界限的地方:Base 必须定义尽可能多的线性代数功能,以使 LinAlg 不是海盗,所以 matmul 在 Base 中定义,因为Array*两者都是。 不过,时髦的矩阵类型和非基本操作仍然存在。

让我给你一个具体的例子,并问你如何使用当前界面解决它,也许这可以为我澄清一些事情。

目标是使用成分数据进行因子分析。 我有一种称为Composition的类型和组合空间中的内积。 我收集了许多样品(例如岩石样品)并将它们全部放入一个大的Vector{Composition}中(例如成分 = %water、%grain、%air)。 现在我想在这个数据向量上调用另一个包(例如MultivariateStats.jl)中实现的因子分析算法。 如果没有默认导入inner产品,您将如何实现该功能?

我从最后的评论中了解到,MultivariateStats.jl 和 CoDa.jl 都必须依赖于 LinAlg.jl。 MultivariateStats.jl 中的依赖项只是将名称inner带入范围。 CoDa.jl 中的依赖项是为inner定义一个可由 MultivariateStats.jl 调用的方法。 这就是你的建议吗?

似乎Composition{D}+*下的D维向量空间。

我很想定义对偶向量空间。

因此,您可以定义adjoint(::Composition) -> DualComposition*(::DualComposition, ::Composition) -> scalar (当前inner )。 DualComposition除了在里面放一个Composition之外不需要做太多事情。

https://en.wikipedia.org/wiki/Dot_product的第一句话似乎暗示dot可以是对任何两个迭代的操作。 我们可以使其递归并为Number定义它,并将inner定义为抽象线性代数函数,它恰好与NumberAbstractArray重叠。

谢谢@andyferris ,感谢您对双重空间的想法。 不过,我宁愿不依赖新类型来完成这项任务。 最终的解决方案是不必要的复杂。

我有兴趣理解的是为什么会这样:

inner(x,y) = sum(x.*y)
norm(x) = sqrt(inner(x,x))

export inner, norm

基地不受欢迎? 我假设这是为该语言的用户专门定义函数名称所需要的全部内容。 请记住,我提出这些问题的真正目的是了解核心开发人员的观点。 我想在谈话再次走向错误的方向之前这么说。

从一般对数学感兴趣的人的角度来看,默认情况下不导出这些概念是不自然的,而是将它们定义在LinAlg中。 我认为LinAlg是数组类型的这些高级概念的实现。 也许我的整个工作不需要数组上的线性代数,但我仍然可以从跨包内积的概念中受益(例如 MultivariateStats.jl、Clustering.jl)。 另外,我可能不想在我的包中包含LinAlg作为依赖项,因为它不是。

如果我可以进一步强调,还有内积的概念,它独立于数组。 这个概念由 Base 中的语句export inner表示。 有表示坐标inner(x,y) = sum(x.*y)的类数组对象的内积的实现。 如有必要,可以像上面一样将此操作定义为 Base 中的后备方法。

另一个用例示例是 Krylov 方法。 如果您有例如具有内积的函数空间,那么您可以使用 Krylov 方法在该无限维函数空间的一个小的有限维子空间中逼近一个线性问题或特征问题。

我也有自己的对象,它们形成向量/希尔伯特空间,但不属于<: AbstractArray 。 从类比来看,秩N>1的数组也形成向量空间并且可以在 Krylov 方法中用作“向量”,我开始依赖使用vecdotvecnorm是内积和范数的广义概念。 所以我一直在开发一个包含 Krylov 方法的包,它使用函数作为线性运算符,并且 'vector's 可以是任何类型,只要该类型的对象支持vecdotvecnorm和一些其他东西( scale!zero ,...)。 但也许这滥用了 Base 中这些概念的含义,所以在这里理顺正确的界面会很好。

对 - vecdot可以重命名为inner

(现在我模糊地想知道norm是否真的应该被称为matrixnorm对于矩阵norm总是匹配inner 。似乎可能有两个不同的norm正在发生的事情,这给概括它带来了一些困难)

事实上,对于一般的类向量对象,查询向量空间的维度也很有用(例如,在我的示例用例中验证 Krylov 维度不应大于整个空间的维度)。 嵌套数组的示例表明length在这里不是正确的概念,即对于这些情况需要一些递归的长度概念。

现在对于使用嵌套数组作为一般向量的示例, vecdotvecnorm在某些情况下甚至不是内积和范数的正确概念,如 #25093 中所述,即它们是不递归调用vecdotvecnorm 。 我将这些函数解释为通用内积和规范函数是触发 #25093 的原因,但似乎这可能不是这些函数的意图(不确定它们的意图是什么)。

所以我同意我们需要一个一致的接口来跨包使用,因此它属于一个中心位置(可能不在 Base 但肯定在标准库中,例如,必须这样做using VectorSpaces )。 至于命名,我看到两个选项:

选项1(到目前为止我的解释):
前缀vec表示该对象在将其解释为通用向量时的属性,因此

  • 嵌套数组的vecdotvecnorm是固定的 (PR #25093)
  • 添加了新的veclength定义

选项 2(可能更好):使用数学上更正确的名称

  • inner
  • dimension
  • 但是如何处理norm

最后,只需 ping @stevengj ,因为他肯定会有一些有用的评论; 如果给您带来不便,我深表歉意。

这个名字是所有这一切中最不有趣的部分。 使用函数dot来引用任意希尔伯特空间的一般内积,我有零问题。 不仅没有其他合理的含义,例如“两个函数的点积”,在非正式用法中看到“函数的点积”也很常见,尤其是在试图强调与有限维向量的类比的教学环境中空格。

@juliohminner(x,y) = sum(x.*y)通常甚至不是内部产品,因此这将是一个非常糟糕的后备方案。

但是dot已经没有为 Base 中充当向量的各种对象计算正确的内积(实际上是失败的),例如排名N>1的数组或嵌套数组(嵌套向量是唯一的情况)它在哪里正常工作)。 此外,通用名称norm对于矩阵来说变得模棱两可,因为我同意当前选择让它返回诱导范数,但有时也需要“向量范数”(Frobenius 范数)。

因此,我影响最小的建议是放弃语义vecnorm(x) = norm(vec(x))而是将vecnorm(x)解释为“因为x是某种泛型类型的对象,其行为类似于向量空间,计算x " 的对应向量范数(与vecdot类似)。 虽然这是解释(以及文档)的转变,但 Base 中对象的实际实现/操作不会有很大不同(PR #25093),并且在大多数情况下会产生相同的结果(排名N数组标量或向量)。 返回相应向量空间维度x的函数veclength(x) #$ 将完成接口。

然后,自定义包在定义表现为向量的新类型时应该学会实现这些功能。

在非正式使用中看到“函数的点积”是很常见的,尤其是在试图强调与有限维向量空间的类比的教学环境中

请不要说名字不重要,因为它是。 我将重复第 n 次:内积和点积不是一回事。 任何带有抽象希尔伯特空间的严肃材料暴露作品都不会使用“点”。 如果您更愿意相信维基百科而不是我的话,以下是复制和粘贴的定义:

内积

在线性代数中,内积空间是具有称为内积的附加结构的向量空间。 这种附加结构将空间中的每对向量与称为向量内积的标量相关联

点积

在数学中,点积或标量积是一种代数运算,它采用两个等长的数字序列(通常是坐标向量)并返回一个数字。


这种对改进语言中的术语和数学一致性的抵制是令人沮丧的。 无论我向您展示多少事实,无论有多少示例和用例,除了“我对 dot 没问题”之外,没有任何反驳论据。

@juliohm ,术语是惯例问题,而不是正确性问题。 我同意在希尔伯特空间的正式用法中,尤其是无限维空间,“内积”一词几乎完全被使用。 但是,正如我所说,如果您搜索“点积函数”,您也会发现该术语的大量非正式用法。 如果你说“取这个希尔伯特空间的两个元素的点积”,每个数学家都会知道你指的是一个内积,即使对于无限维空间也是如此,所以没有真正的混淆危险,因为没有其他术语“点积”的标准概括。 这就是为什么我不认为“dot”与“inner”的拼写辩论是一个中心问题。

重要的要在这里确定一个人想要的语义,以及类型在定义新的希尔伯特空间或巴纳赫空间时应该实现的函数集。 目前,如果你想定义一个代表新希尔伯特空间的类型,你应该定义dotnorm (因为我们目前缺乏后者的后备),我猜adjoint如果你想映射到双空间对象。

正如@Jutho所说,这一切都因数组数组的情况而变得复杂,因为人们可能想要在那里做多种可能的事情。 由于所有可能的语义都没有标准化的名称,因此很难找到满足所有人的名称/语义。 有关vecdot语义的讨论,请参见 #25093。 我自己在这里没有很好的答案。

这里有一些可能性

  1. x[i]' * y[i]的总和。 目前,这是dot(x,y) 。 不是矩阵向量的内积(它给出一个矩阵),并且目前还没有为多维数组定义所有内容。
  2. dot(x[i], y[i])的总和,包括多维数组和conj(x)*yNumber 。 目前,这是vecdot(x,y)
  3. 某些函数,例如inner(x,y)定义为始终是真正的内积,对于数组,使其总和inner(x[i],y[i]) — 本质上是@Jutho想要的“递归 vecdot”。 但是,对于矩阵A ,这个内积与我们当前norm定义的诱导范数norm(A)不一致。 要修复它,我们必须将矩阵的norm(A)更改为默认为 Frobenius 范数,这可能是一个影响深远的突破性变化。

一个问题(在 #25093 中部分讨论)是我们是否在 Base 中需要所有这三个,或者我们是否可以摆脱两个(以及哪两个,以及我们如何称呼它们)。 @Jutho的建议,据我了解,本质上是消除 Base 中的选项 2,然后将vecdotvecnorm用于选项 3。然后我们有一个真正的内积,但是术语对于 Julia 来说是相当独特的,对于例如无限维希尔伯特空间来说有点奇怪。 当然,那不会是世界末日。

另一种可能性(有点独立于我们对vecdot所做的事情)是(返回)要求dot成为真正的内积。 即消除行为1,并使dot(x::AbstractVector, y::AbstractVector)等于sum dot(x[i],y[i]) 。 仍然不要为多维数组定义它(与norm保持一致)。

我目前的个人倾向是将dot定义为真正的内积(应与norm一致),将其更改为向量的总和dot(x[i],y[i]) (即更改矩阵向量的情况),并继续不为多维数组定义它。 然后按照@Jutho的建议定义vecdot以递归调用vecdot ,并带有后备vecdot(x,y) = dot(x,y) 。 最后,说新的“希尔伯特空间”类型应该定义dotnorm 。 对我来说,这似乎是破坏性最小、最容易理解的变化。

norm(x) = sqrt(real(dot(x,x)))后备也是一种可能性,尽管它有点危险,因为它容易受到虚假溢出的影响。请注意,由于技术原因,我们不能使用sqrt(dot(x,x))作为后备:我们想要一个Real结果,而不是Complex结果。)

感谢@stevengj提供的信息丰富的反应。 只是一个小评论:

带有后备vecdot(x,y) = dot(x,y) 。 最后,说新的“希尔伯特空间”类型应该定义dotnorm

这样做有两个问题。 vecdot(x,y) = dot(x,y)后备不能存在,因为vecdot已经接受Any参数来处理通用迭代器。 第二个问题是,如果dotnorm被暴露为真正的内积和规范,任何像用户类型这样的向量都应该定义,那么即使使用例如 Krylov 方法编写包应该使用完全通用的向量类类型,它仍然不适用于用户想要使用嵌套或多维数组作为向量类对象的情况。 因此,我认为vecdotvecnorm是类向量对象的一般内积和范数。 这也很好地符合这样一个事实,即对于矩阵,大多数人确实会期望norm是诱导矩阵/算子范数。

至于实际用例(以表明这不是特殊情况)。 随机矩阵有一个最大的 (Perron-Frobenius) 特征值,其对应的特征向量代表一个定点概率分布。 在其量子泛化中,概率分布泛化为一个正定矩阵(密度矩阵),这个矩阵就是一个完全正映射的不动点(最大特征值对应的特征向量),即映射rho -> sum(A[i] rho A[i]^\dagger for i = 1:N)因此rho是密度矩阵, A[i]是每个i的矩阵(称为表示完全正映射的克劳斯算子)。 对于大矩阵维数,Arnoldi 方法非常适合寻找定点密度矩阵。

我目前的个人倾向是将 dot 定义为真正的内积(应该与规范一致),将其更改为向量的 sum of dot(x[i],y[i])。 最后,说新的“希尔伯特空间”类型应该定义点和范数。

这已经是一个巨大的进步。 在 Base 中记录dot以具有inner语义至少将允许用户定义自己的空间而无需导入不必要的库。 我对命名不满意,但至少该功能可供需要它的人使用。

是的,我认为有一个文档化的接口来实现“希尔伯特空间”类型会很好。

当然,考虑到向量空间的这个通用接口,如果它包含上面建议的norm ,那么这应该是矩阵的 Frobenius 范数(并推广到高维数组,因为所有数组都是向量的元素空间)。 在这种情况下,我们需要一个单独的矩阵“运算符规范”函数( matnormopnorm或其他东西,或者norm上的关键字参数......)。

@andyferris ,请注意我的最后评论。 normdot不能成为一般的 Hilbert 空间接口,因为它们甚至不适用于 Julia 中类似向量的对象,例如高维数组和嵌套数组。 因此vecdotvecnorm是一个“更好”(在最少破坏的意义上)的候选者。

重提这个话题,我认为这与我希望在不久的将来用这门语言做的数学类型非常相关。 对于如何改进内积的通用性和语义,是否达成了共识?

这是我个人关于产品的数学本体的一部分。
如果它可以帮助记忆/带来共识

奖励:没有维基百科参考

在这一点上, @Jutho在#25093 中的提议似乎是破坏性最小的更改,尽管在这种情况下vec*术语对我来说有点奇怪。

我同意vec*术语很奇怪。 这就是为什么将函数重命名为具有标准名称对所有用户都有益的原因。

我也同意vec*术语很奇怪。

我同意,作为vecdot的替代方法,我们可以引入一种新方法inner ,但我不知道“替换” vecnorm的好名字。 事实上,我认为vecnorm并没有那么糟糕,向量范数对于我们想要的操作来说是一个成熟且明确的术语。

这里的基本问题是矩阵和多维数组,通常的norm(A)不对应于内积,以及上面讨论的数组数组。 在这些情况下,需要进行一些消歧(例如vec*fro* )来指示预期的内积。

你可以有一个默认为vecdotinner函数,但是为同一个函数有两个名称有点傻,而且仍然存在调用规范的问题。

我还发现vecdot这个名字很奇怪,事实上,我什至不知道它的存在,并且为它创建了我自己的函数......称为inner

我的理解是,我们可以弃用奇怪的vecdot以支持inner ,并为用户提供内部产品语义以实现自己的空间。

关于norm ,我不知道。 我打开这个问题是为了讨论内积,也许另一个问题适合讨论 Base 中的规范状态。

我想我们可以有inner(x,y)innernorm(x) = sqrt(inner(x,x)) (优化特殊情况以避免溢出)而不是vecdotvecnorminnernorm有点不寻常,但在上下文中相当清晰。

为这一变化点赞。 innerinnernorm的名称清晰且与概念一致。 我希望他们能进入 Julia v1.0。

innerinnernorm对我来说似乎没问题。

我仍然要说,在我看来,我们的norm函数并不能很好地适应 Julia 的通用函数和调度系统以及我所谓的“清晰接口”,其中不应该进行调度语义选择,只是实现选择。 我个人宁愿我们可以说“ norm返回向量空间元素的范数”,其中矩阵和线性运算符仍然是向量空间的元素(您可以将它们相加并乘以标量) . 我们也可以有例如“ opnorm返回线性运算符的运算符范数”(或matnorm或其他)。

目前我们有“ norm返回向量空间元素的范数,除非该元素也是线性运算符,在这种情况下,我们将为您提供运算符范数”。 我个人觉得派遣永远不应该令人惊讶。

即我更喜欢一个总是做向量范数的函数和另一个总是做运算符范数的函数,并且没有一个函数试图同时做这两者。

更喜欢它@andyferris :+1: 不是由空间中的内积引起的规范的特定规范可以有一个更具体的名称。 名称norm将准确表示norm(x) = sqrt(inner(x,x)) ,并且可以根据用户类型的需要重新定义。

我个人宁愿我们可以说“ norm返回向量空间元素的范数”

当前的norm函数满足该定义。 对于矩阵,它计算诱导(算子)范数,这是向量空间的完全有效范数。 (向量空间根本不必内积或范数。)

如果您认为运算符范数不是“向量空间的范数”,您可能会对“范数”的定义感到有些困惑。

这也是norminnernorm之间有用的区别。 如果你定义norm ,我会说它只意味着你有一个巴拿赫空间(或者至少是一个范数向量空间)。 如果你定义innernorm ,它意味着你有一个希尔伯特空间(或至少一个内积空间),并且这个范数与inner是一致的。

例如,自适应数值积分(ala quadgk)只需要一个范数向量空间,而不是一个内积空间。

当然,对不起,我的语言可能有点太不准确了。 向量空间显然有许多有效范数,包括各种算子范数。

我想我的意思是,也许我更喜欢选择哪个规范比隐式更明确? 而且,如果您使用相同的函数(例如,没有额外的关键字参数),您将获得“相同”的规范,在这种情况下,欧几里得似乎是AbstractArray的一个有点站得住脚的选择。

这也是norminnernorm之间有用的区别。 如果你定义范数,我会说它只意味着你有一个巴拿赫空间(或者至少是一个范数向量空间)。 如果您定义innernorm ,则意味着您有一个希尔伯特空间(或至少一个内积空间),并且该范数与inner一致。

这似乎是合理的,但我仍然想知道为什么如果一个对象有一个innernorm它需要一个不同norm ? 我也可以建议 Banach 空间的接口需要norm而内积空间的接口需要同时提供norminner 。 然后,这些函数可以在需要 Banach 对象或适当内积空间的通用代码中使用(编辑:认为在 Banach 空间中工作的代码也会自动在内积空间上工作)。

我认为你建议norm(x)总是指某种元素方面的欧几里德范数(即矩阵的 Frobenius 范数),即基本上vecnorm现在是递归情况的模。 在这种情况下,我们不妨将dot(x,y)重新定义为相应的内积( inner也可以,但dot具有中缀变体x ⋅ y的优势)。

原则上我没问题,但这将是一个重大变化,在 0.7 之前可能有点晚了……

L2 在高维中也是一个很好的默认值吗?
本文谈论距离,但也可能涉及规范
https://stats.stackexchange.com/questions/99171/why-is-euclidean-distance-not-a-good-metric-in-high-dimensions

在这种情况下,我们不妨将 dot(x,y) 重新定义为相应的内积(inner 也可以,但 dot 具有中缀变体 x ⋅ y 的优势)

我们可以完全摆脱dot吗? 中缀符号应该与名为dot的函数的存在无关。 只需使用 Julia 数组的inner方法定义中缀即可。 那可能吗?

这就是它的本质,点积:一个方便的符号 x ⋅ y,用于表示 R^n 中 x 和 y 向量与欧几里得几何的内积。

@stevengj我认为这是一个很好的总结,是的。

@o314 L2 在高维中是一个很好的默认值吗? 可能不是,但如果norm(v::AbstractVector)选择的规范取决于length(v) :) 我同样不喜欢它来猜测我的矩阵还是高维数组是“对于 L2 来说太大了” - 我建议也许这应该由用户明确标记?

@juliohm这绝对是可能的,尽管如前所述,这些是我们建议的重大更改。 (再次,对递归情况下的操作取模,以及之前关于innerdot之间可能差异的讨论)。

@stevengj ,我对@andyferris所暗示的解释是,由于鸭子类型,很难确定用户是否要将对象解释为向量(并使用相应的向量p -norm)或作为运算符(并计算诱导的p -norm)。 所以我认为别无选择,只能明确指定想要的行为。 当前的方法有点奇怪,因为norm试图隐式猜测是根据输入选择向量范数还是诱导范数,而vecnorm是一种明确指定您想要的方式向量范数(这也是为什么我没有发现vecnorm这样一个坏名字的原因)。 一个更彻底的改变是使norm始终默认为向量范数,并明确指定何时需要诱导范数,使用(关键字)参数或完全不同的函数。

另一方面,我也不介意innernorm这个名字,因为这是一个基于内积的规范(即在欧几里得情况下总是p=2 )。 我发现很难判断自定义对象(vec)norm是否应该支持可选参数p作为接口的一部分,因为在我的一些用例中,只有p=2很容易计算。

这就是它的本质,点积:一个方便的符号 x ⋅ y,用于表示 R^n 中 x 和 y 向量与欧几里得几何的内积。

我同意这一点,因为我不记得在一般(例如复杂)向量空间的上下文中见过符号x ⋅ y 。 我认为在这种情况下只使用数学符号(x,y)或狄拉克符号< x | y > 。 在电磁学中,人们经常使用E ⋅ B表示 3 维欧几里得空间中的向量,即使使用复数符号(即相量),这并不意味着复共轭。 如果需要,在这种情况下会明确表示复杂的共轭。 所以我不介意dot只是变成sum(x_i * y_i)而没有复数或 Hermitian 共轭,并且inner成为一般内积空间的正确内积。 不幸的是,这可能无法在单个发布周期中完成。

L2 在高维中是一个很好的默认值吗? 可能不是,但是如果例如 norm(v::AbstractVector) 选择的范数取决于长度(v) :) 我同样不喜欢它来猜测我的矩阵或高维数组是“对于 L2 来说太大了” - 我建议也许这应该由用户明确标记?

我在BIM世界工作,我们处理 2d 和 3d,但 4d、5d、6d 也可能是 7d。 我们永远不会走得更远。 在任何时候,我们都知道我们在哪些维度工作,以及涉及哪些算法。 这在很大程度上就足够了。

我无法表达从事 ML、信息检索等工作的人的观点。在那里,可能 norminf 更好。 在我的 pov 中重要的是可猜测性和稳定性。 如果 ML 中的人们需要不同的默认设置,我一点也不会感到震惊。 如果没有混乱。 例如。 它是在编译时明确和静态地决定的。 如果在算法应用过程中保持稳定和一致,它甚至是奢侈的。

Inspired from array:similar没有完全实现并测试它。

norm2 = x -> x |> inner |> sqrt
norminf = ...
NMAX = 10
for N in 1:NMAX
    <strong i="13">@eval</strong> begin norm(a::Array{T,N}) where {T} = norm2 end
end
norm(a::Array{T,n}) where {T} = norminf

我们可以完全摆脱 dot 吗? 中缀符号应该与名为 dot 的函数的存在无关。 只需使用 Julia 数组的内部方法定义中缀。 那可能吗?

norm(x::AbstractVector, p::Real=2) = vecnorm(x, p) # https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/generic.jl#L498
vecdot(x::Number, y::Number) = conj(x) * y # https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/generic.jl#L657
dot(x::Number, y::Number) = vecdot(x, y) # https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/generic.jl#L659
function dot(x::AbstractVector, y::AbstractVector) # https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/generic.jl#L677

# Call optimized BLAS methods for vectors of numbers
dot(x::AbstractVector{<:Number}, y::AbstractVector{<:Number}) = vecdot(x, y) # https://github.com/JuliaLang/julia/blob/master/stdlib/LinearAlgebra/src/generic.jl#L698

Dot / vecdot 意味着使用共轭并决定何时去 BLAS。 这必须在某个地方处理。 但这应该可以在单个命名空间中进行管理。

L2 在高维中是一个很好的默认值吗? 可能不是

L2 也是无限维空间(例如函数)最常见的范数。 我认为期望任何向量空间都是合理的默认值。

显然,您也希望有其他可用的规范。 如果我们尽可能将norm(x)重新定义为元素 L2,那么norm(x, p)将是元素 Lₚ,并且我们需要一些其他函数(例如opnorm )来对应相应的诱导/运营商规范。

我同意这一点,因为我不记得在一般(例如复杂)向量空间的上下文中见过符号x ⋅ y

我在另一个线程 IIRC 中给出了几个引用(例如 BLAS 使用dot表示复杂的点积,即使使用函数内积这个术语,您也可以找到教学资源)。 术语“内积”通常被引入“点积的概括”。 我认为任何人都不会对欧几里得内积的dot表示法感到惊讶,而且有一个中缀运算符很方便。

当然,我们可以保持dot原样并引入inner ,但我认为这会造成令人困惑的二分法——在最常见的情况下,函数是等价的,但在奇怪的情况下(例如矩阵数组)它们会有所不同。

但同样,要进行重大更改可能有点晚了,所以我们可能不得不求助于innernorminner 。 无论如何,有人需要尽快创建公关。

如果形成共识的合理衡量标准,我可能能够投入一些带宽来探索相关(短)时间尺度上的实施,包括潜在的重大变化。 我很欣赏阐明这些操作的语义并给它们明确名称的动力。 最好的!

我看到两个主要选项:

  • 非破坏性,添加了一个功能: inner(x,y)innernorm(x) 。 替换vecdotvecnorm ,并对数组数组进行递归。

  • 突破:将norm(x,p=2)更改为始终元素和递归,替换vecnorm ,并为运算符/诱导范数引入一个新函数opnorm 。 使dot(x,y)成为相应的元素点积,替换vecdot 。 (替代方案:重命名为inner ,但有一个中缀运算符很好,同时有dotinner很烦人。)

如果我是从头开始设计东西,我更喜欢 2,但是默默地改变norm的含义可能太破坏性了。

一种中间选项是定义innerinnernorm (弃用vecdotvecnorm ),并将norm(matrix)弃用为opnorm 。 然后,在 1.0 中,重新引入norm(matrix) = innernorm(matrix) 。 这样,人们最终可以只使用innernorm ,而我们将dot作为数组向量的当前奇兽(与inner一致)

关于innernorm的一个奇怪之处是您想要一种指定 L1 或 Linf“元素”规范的方法,但这些规范都不对应于内积,因此innernorm(x,p)有点用词不当。

我喜欢你的中间选项。

如上所述,我喜欢innernorm(x)这个名字,因为它暗示p=2并且不应该有第二个参数。 我有一些我只知道如何计算内积范数的对象。 但是对于当前的(vec)norm ,我不清楚p参数是否是假定的 Base 接口的一部分,所以我不知道是省略第二个参数还是支持它然后显式检查p != 2并产生错误。

但我认为在你的提案的中间阶段没有任何不推荐的方式来做vecnorm(matrix, p!=2)的问题。

我也喜欢中间选项——我们肯定希望对规范进行适当的弃用循环,而不是立即做出重大改变。 (作为用户,重大更改让我感到害怕,但我认为在我的 v1.0 代码中修复弃用就像是对未来干净、清晰代码的投资)。

我们真的需要innernorm还是我们现在可以只使用vecnorm (然后弃用vecnorm以支持norm )?

实际上,我认为简单地将dot替换为inner并没有引起任何骚动……我也认为内积意味着点积的泛化已经很清楚了。

可以在两个单独的 PR 中实施更改:

  1. dot替换为inner并赋予其广义含义。 或者,使中缀\cdot表示法指向 Julia 数组之间的内部。
  2. 围绕规范变体和术语的更多讨论和弃用循环。

我的理解是 PR 1 可以在 Julia v1.0 之前合并。 它没有破裂。

inner替换dot仍然会破坏,因为dot目前不是数组数组的真正内积——所以你会改变含义,而不仅仅是重命名。 我支持将含义更改为真正的内积,但是如果您更改含义(将其定义为真正的内积),我认为继续将其拼写为dot没有问题。

因此,我们可以在 0.7 中执行以下操作:

  1. 弃用norm(matrix)opnorm(matrix)norm(vector of vectors)vecnorm
  2. 弃用dot([vector of arrays], [vector of arrays])来调用sum
  3. 假设vecdot(x,y)vecnorm(x, p=2)是欧几里得内积/规范(对于p=2 ),并使它们递归(这有点破坏,但实际上可能没什么大不了的) .

然后,在 1.0 中:

  1. 弃用vecnormnormvecdotdot 。 (不确定 1.0 版本规则是否允许这样做,@StefanKarpinski?)

(请注意,令人惊讶的是, numpy.inner函数并不总是内积。但 NumPy 关于innerdot的术语已经有一段时间很奇怪了。)

我更喜欢继续拼写为dot的原因:

  • 有一个中缀拼写很好。
  • 对于在普通有限维向量空间上操作的非数学家来说, dot是欧几里得内积的更熟悉的名称。 (数学家很容易适应使用名称dot来表示任意希尔伯特空间上的内积函数——“点积”对于此类空间没有其他可能的含义。)
  • 同时拥有innerdot会令人困惑,因为它们在某些情况下会重合,但在其他情况下可能不会(如果我们保持当前dot的含义)。
  • 在线性代数之外, inner在计算机科学中还有很多其他潜在的含义,因此从 Base 中导出这个名字有点烦人。

你能详细说明你反对inner这个名字吗? 我还是不明白
这就是为什么您更喜欢反对该线程上每个人的术语的原因
赞同?

2018 年 5 月 15 日星期二上午 5:13 Steven G. Johnson [email protected]
写道:

(请注意,numpy.inner
https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.inner.html
令人惊讶的是,函数并不总是内积。)


你收到这个是因为你被提到了。
直接回复此邮件,在 GitHub 上查看
https://github.com/JuliaLang/julia/issues/25565#issuecomment-389144575
或使线程静音
https://github.com/notifications/unsubscribe-auth/ADMLbdcpeWo7M4prYz76NoqUPIkfVPP3ks5tysZlgaJpZM4ReGXu
.

没有一个理由对我有说服力:

>

  • 有一个中缀变体很好。

是的,中缀符号仍然可以存在,无论重命名为
如上所述的内部。

>

  • 对于在普通有限维上操作的非数学家
    向量空间,点是欧几里得内的一个更熟悉的名字
    产品。 (数学家很容易适应使用名称点来表示
    任意希尔伯特空间上的内积函数——“点积”没有
    此类空间的其他可能含义。)

这种说法不好:让我们把错误的教给普通人
术语,因为他们很懒惰,无法学习新的合适的词,
并强迫数学家违背自己的意愿使用错误的术语。

>

  • 同时拥有 inner 和 dot 会令人困惑,因为它们会
    在某些情况下重合,但在其他情况下可能不重合(如果我们保留当前点
    意义)。

我们不需要两者,去掉不太通用的名称,我们同意是
此时点。

>

  • 在线性代数之外,inner 还有很多其他的潜力
    在计算机科学中的含义,因此它有点烦人
    从 Base 导出此名称。

在线性代数之外,我可以找到点的许多用途。 更适合
点中缀表示法意味着完全不同的东西。

>

我正在以固定格式重新发布@juliohm的最后一篇文章。


没有一个理由对我有说服力:

有一个中缀变体很好。

是的,如上所述,无论重命名为 inner ,中缀符号仍然可以存在。

对于在普通有限维向量空间上操作的非数学家来说,点是欧几里得内积的更熟悉的名称。 (数学家很容易适应使用名称 dot 来表示任意希尔伯特空间上的内积函数——“点积”对于此类空间没有其他可能的含义。)

这种说法是不好的:让我们教给普通人错误的术语,因为他们懒惰,学不会一个新的合适的词,并强迫数学家违背他们的意愿使用错误的术语。

同时拥有 inner 和 dot 会令人困惑,因为它们在某些情况下会重合,但在其他情况下可能不会(如果我们保留当前的 ​​dot 含义)。

我们不需要两者,摆脱不太通用的名称,我们同意在这一点上是点。

在线性代数之外,inner 在计算机科学中还有很多其他潜在的含义,因此从 Base 中导出这个名字有点烦人。

在线性代数之外,我可以找到点的许多用途。 对于点中缀表示法来说,更多的是意味着完全不同的东西。

是的,如上所述,无论重命名为 inner ,中缀符号仍然可以存在。

您当然可以定义const ⋅ = inner ,但是您的术语不一致。 我以为您不喜欢将“点积”用作一般的内积?

强迫数学家违背自己的意愿使用错误的术语

数学家知道术语既不是对也不是错,它只是传统的或非常规的(可能是一致的或不一致的)。 (而且大多数人不会进入数学领域,因为他们对规范拼写充满热情。)根据我的经验,如果你告诉数学家,在量子力学中,向量被称为“状态”,伴随的被称为“匕首”,并且双重向量被称为“胸罩”,它们完全不关心。 同样,如果您告诉任何有经验的数学家在 Julia 中的内积拼写为dot(x,y)x ⋅ y ,我认为任何有经验的数学家都不会眨眼不止一次,特别是因为这些术语已经被理解为在许多情况下的同义词。 (如果你说“在这个函数空间中取两个函数的点积”,我怀疑你会发现任何不知道你指的是内积的数学家。)

另一方面,对于没有受过训练的数学家并且没有接触过抽象内积空间的人(即大多数用户),我的经验是,不熟悉的术语更像一个障碍。 “如何在 Julia 中取两个向量的点积?” 将成为常见问题解答。

除了选择语义之外,这里真的没有数学难题需要解决。 拼写问题纯粹是为了方便和使用。

在线性代数之外,我可以找到点的许多用途。 对于点中缀表示法来说,更多的是意味着完全不同的东西。

除了 Julia 和许多其他编程语言多年来一直使用dot并且这不是问题。 inner将是新的破损。

最终,与语义和弃用路径相比,这个(或任何其他)函数的拼写是小问题,但我认为平衡提示有利于dot

你当然可以定义 const ⋅ = inner,但是你的术语是不一致的。 我以为您不喜欢将“点积”用作一般的内积?

我想你还是没明白。 将 dot 称为内积并没有矛盾。 它一种内在产品,对我们许多人来说是一种非常具体且无用的产品。 只不过是sum(x.*y)

如果dot这个词最终在 Julia 中具有inner的语义,我可以向你们保证,这将是一场历史性的灾难,许多人会感到恼火。 我可以预见教室里的教授会解释这样的事情:“你知道,我们现在要为我们的空间定义内积,但在 Julia 中,有人 (@stevengj) 决定将其命名为 dot。”

如果最终发生这种情况,我将确保我会截取此线程以供将来参考。

你是唯一一个坚持使用dot术语的@stevengj ,没有其他人对此表示反对。 如果你能在做出决定之前重新考虑这个事实,那就太好了。

它是一种内在产品,对我们许多人来说是一种非常具体且无用的产品。 无非是 sum(x.*y)。

如果您认为“点积”只能指 ℝⁿ 中的欧几里得内积,那么您不应该定义const ⋅ = inner ,您应该只定义⋅(x::AbstractVector{<:Real}, y::AbstractVector{<:Real}) = inner(x,y)

你不能同时拥有它:要么inner可以使用作为中缀同义词(在这种情况下,中缀运算符在你的用语中都是“错误的”并且命名不一致)或它没有中缀同义词(一种特殊情况除外)。

我可以预见教室里的教授会解释这样的事情:“你知道,我们现在要为我们的空间定义内积,但在 Julia 中,有人 (@stevengj) 决定将其命名为 dot。”

哈哈,我愿意从这个想象中的愤怒教授那里得到热量。 说真的,如果你认为“点积”这个词只在 ℝⁿ 中使用过,或者如果在其他 Hilbert 空间中使用这个词,数学家会感到愤怒,那么你需要多看看。

这将是一场历史性的灾难

严重地?

这种讨论似乎正在侵蚀人们可能认为的欢迎、文明和建设性的环境。 意见和背景不同,但请不要进行人身攻击或责备任何人,并假设所有各方都在真诚地辩论他们的观点。

我可以预见教室里的教授会解释这样的事情:“你知道,我们现在要为我们的空间定义内积,但在 Julia 中,有人 (@stevengj) 决定将其命名为 dot。”

在这里也值得一提的是,史蒂文_是_一位教授。 :眨眼:

我也反对删除dot以支持innerdot术语被广泛使用,并且在 Julia 中没有该函数,当它在 Python 和 MATLAB 中时会令人惊讶。 但是,我也喜欢inner这个术语,因为它更适合非ℝⁿ 向量空间,尤其是矩阵。

顺便说一句,当我测试 Julia 中的方法时,我注意到dot仅适用于真实向量/矩阵。 这是故意的吗?

同时拥有 inner 和 dot 会令人困惑,因为它们在某些情况下会重合,但在其他情况下可能不会(如果我们保留当前的 ​​dot 含义)。

@stevengjinner替换vecdot并保留dot会完全荒谬吗? 现在,您所描述的确切问题已经存在,只是使用vecdot而不是inner

好的...期待,有什么直播建议? 他们是否:

  • dot视为更广泛类型的通用内积。 它已经在向量的向量上正确递归,但我们会让它在矩阵等上工作( @jebej我不觉得同时拥有dotinner是有用的,并且作为史蒂文说,我们至少在口语中经常使用dot来表示内积,这并没有——这只是术语)。
  • 考虑使norm与上述dot以及所有AbstractArray更加一致,最终引入例如opnorm用于运算符规范(在AbstractMatrix ) 并在适当的弃用后具有(以新旧表示法) norm(matrix) == vecnorm(matrix) 。 在这一点上,也许我们不再需要vecdotvecnorm了?

那正确吗? 我认为这些至少会让我们得到一个具有“干净”接口的相对一致的线性代数故事,其中通用代码可以使用dotnorm作为处理内积空间的可靠对与类型无关。

@andyferris ,是的,我认为如果我们进行此更改,那么我们只需要dotnorm (尽管它们现在是对数组或任何维度的数组数组的递归欧几里德操作对于 norm 我们还定义norm(x,p)为 p-norm) 和opnorm ,不再有vecdotvecnorm

请注意,对dot的更改是一项重大更改,因为dot目前不是矩阵向量的真正内积 (#22392),这在 #22220 (#22220 (在这一点上消除vecdot不被认为是 IIRC)。 但是,这是在 0.7 中引入的,因此它不会破坏任何实际发布的代码。 事实上,0.6 中的dot已经是任意维数组上的欧几里得点积,这有点意外(#22374)。 此处建议的更改将恢复和扩展 0.6 的行为,并更改norm以与其保持一致。

一个问题是norm(x,p)是否会递归调用norm(x[i])norm(x[i],p) 。 两者都是潜在有用的行为。 我倾向于前者,因为它更通用—— x[i]可能是一些任意的范数向量空间,它只定义了norm而不是 p 范数。 递归调用norm也是vecnorm现在所做的,因此它与将vecnorm弃用为norm是一致的。

@jebej , master 和 0.6 上的dot对我来说都适用于复杂的数组:例如, dot([3im],[4im])正确返回12+0im

norm(matrix)更改为 Frobenius 规范的另一个好处是便宜得多。 通常只使用norm(A-B)来了解两个矩阵之间的差异有多大,而不必太在意范数的具体选择,但是很多用户不会意识到当前的默认值norm(matrix)要求我们计算 SVD。

很高兴看到围绕几个要点形成共识! :) (除非有人击败我(如果你有带宽,请这样做!)或之前点击 alpha 标签,我将在发布 #26997 后尝试实施当前的共识点。)最好!

供将来参考的另一个链接: https ://math.stackexchange.com/a/476742

为了说明这里有意识地采用的糟糕命名,以及由单一思想强加的糟糕决定。 点积和内积具有不同的数学性质。 你正在迫使整个社区反对数学文献中众所周知的东西。

对于未来的读者来说,如果我们有一个集体决定,应该做些什么:

# make dot what it is, a NOTATION
⋅(x::AbstractVector, y::AbstractVector) = sum(x[i]*y[i] for i in indices(x))

# replace the name dot by the more general inner
inner(x, y) = # anything

我想我们成为宇宙第一个使用积”一词来表示除ℝⁿ之外的任何东西的内积的人。 我能够将自己的意愿强加在这个线程上(主要是通过勒索其他开发人员)来将这种创新推向世界,这是一件好事! 点积将不再仅仅是“符号”:相反,它将是一个表示内积的符号(众所周知,为符号分配含义与“符号”相反)。

非常好的决策 :clap: 这绝对是一个共识。 阅读上面的评论,你会看到每个人是如何同意的。 :+1:

或者也许我应该引用一些评论,以便很清楚这是如何达成共识的:

>

对 - vecdot 可以重命名为 inner

通过@andyferris

选项 2(可能更好):使用数学上更正确的名称


方面
但是规范怎么办?

通过@Jutho

我同意,作为 vecdot 的替代方案,我们可以引入一种新方法 inner

通过@Jutho

我也觉得 vecdot 的名字很奇怪,事实上,我什至不知道它的存在,并为它创建了我自己的函数......称为内部。

通过@jebej

还有很多...

人们可以互相大声辩论,提出许多分歧点,但仍然通过被说服和平衡利弊达成共识(尽管并不总是一致)。 (我同意这里的每个选项都有优点和缺点。)我很抱歉,看起来(暂时!)在这里凝胶化的结果不是你喜欢的结果,但我不确定你是怎么想的我“强加”了我的意志。

(当然,并没有做出任何最终决定——甚至还没有 PR,更不用说合并了。)

我只希望我们能够根据语言的受众做出决定。 如果有人选择 Julia 作为工具,我相信这个人至少听说过inner产品这个词。 这是一个非常流行的概念,远非异国情调。 异国情调的东西包括“持久同源性”、“量子理论”,这些都不太广泛传播,我反对包含这种类型的术语。

毕竟我只想拥有一种语言,它是科学计算、数学等方面的最佳语言。

@juliohm ,所有的论点都是基于我们认为的听众的需求,我们所有人都在努力让 Julia 成为一种尽可能好的语言。 理性的人可以对术语得出不同的结论,因为数学不能决定拼写。

首先,如上所述,我当然可以同意@stevengj目前的提议,并坚持将dot作为内积的通用名称。 另外,我不喜欢这个讨论的方式,当然希望被正确引用。 @juliohm ,你给我的第二句话不是我的。

话虽如此,在考虑利弊时,我想提以下几点作为深思熟虑。 以下主要是缺点,但我同意@stevengj 提到的优点。 很容易有单独的用例让dot只是意味着sum(x[i]*y[i] for i ...) 。 在中缀点符号在数学中最常用的情况下,这确实是典型的含义。 作为内积,中缀点符号通常(尽管当然不是唯一的)保留给实向量空间。 其他用例包括启用诸如σ ⋅ n之类的东西,其中σ是泡利矩阵的向量,而n是标量的向量。 正如在其他线程中向我指出的那样,这是当前实现dot方式背后的动机之一。 BLAS 决定仅将dot用于真实向量并区分dotudotc用于复杂向量的事实是另一个需要考虑的问题。 具有 BLAS 背景的人可能会感到困惑,当他们想要真正的内积(即dotc )时,他们是否想要计算dot(conj(u),v)dot(u,v)具有复杂的向量。 此外,他们可能会寻找一种方法来做dotu而不首先制作手头向量的共轭副本。

@Jutho引用是您的,您的完整评论复制如下:

我同意,作为 vecdot 的替代方案,我们可以在内部引入一种新方法,但我不知道“替换”vecnorm 的好名字。 事实上,我认为 vecnorm 并没有那么糟糕,向量范数对于我们想要的操作来说是一个成熟且明确的术语。

无论如何,引用的目的是表明当我们考虑这个主题时,这里许多人的愿望是什么(至少作为第一个自然想法)。 如果你随着时间的推移改变了你的愿望,那就是另一回事了。 在使用希尔伯特空间进行任何建模时,我自己永远不会从脑海中弹出“点”这个词。 这感觉不自然,与我所学的不一致。

@Jutho :此外,他们可能会寻找一种方法来做dotu而不首先制作手头向量的共轭副本。

导出dotu函数的可能性不时出现(参见例如#8300)。 我同意这有时是一个有用的函数:一个非共轭欧几里得“内积”(不再是真正的内积),它是一个对称双线性(不是倍半线性)形式dotu(x,y) == dotu(y,x) (非共轭),即使对于复杂的向量空间. 但是该操作的实用性并不限于ℂⁿ——例如,由于易性,这种乘积经常出现在麦克斯韦方程的无限维向量空间(函数)中(本质上:典型有损材料中的麦克斯韦算子是类似于“复对称矩阵”——在非共轭“内积”下对称)。 因此,如果我们将dot(x,y)定义为一般欧几里德内积(第一个参数共轭),那么在任何向量空间上为非共轭欧几里得积定义dotu(x,y)函数是很自然的有意义的地方。 但是,我不认为将dotu函数作为反对dot的参数的可能性。 在大多数情况下,当您使用复杂的向量空间时,您需要共轭积,因此这是正确的默认行为。

但我同意一种可能性是定义dot(x,y) = sum(x[i]'*y[i] for i = 1:length(x)) ,这是当前在 master 中定义的方式(不是 0.6),并将inner(x,y)定义为真正的点积。 这具有提供两种功能的优点,这两种功能在某些情况下都可能有用。 然而,我们有两个函数几乎总是一致的,除了矩阵数组,我怀疑决定何时使用其中一个会有点混乱。 当他们的意思是inner时,许多人会写dot $ ,并且在大多数情况下它对他们来说可以正常工作,但是如果传递一个矩阵数组,他们的代码会做一些意想不到的事情。 我的怀疑是,在 99% 的情况下,人们想要真正的内部产品,并且“产品总和”版本可以留给一个包,如果确实需要它(而不是仅仅调用sum )。

@juliohm ,我误读了您的帖子,因为我认为名称在各自的引号上方(而不是下方),因此我认为您将@jebej的引号归功于我。 对此我深表歉意。

@stevengj ,我当然没有考虑将dot(x,y) = sum(x[i]'*y[i] for i = 1:length(x))作为合理的默认值。 在像σ ⋅ n这样的情况下,第一个或第二个参数的复数/厄米共轭是不必要的。 所以我的意思是,在科学公式中使用中缀点符号的许多(但实际上不是全部)情况下,它的含义与dotu一致,即sum(x[i]*y[i] for i = 1:length(x))没有共轭,要么作为实向量空间的内积或更一般的构造。

因此,如果我要提出一个替代建议(尽管我不一定提倡),那就是具有两个功能:

  • dot(x,y) = sum(x[i]*y[i] for i...) ,它仍然是真实向量的正确内积(这可能是不太熟悉或不熟悉内积一词的人的用例),但也允许更一般的构造,如σ ⋅ n ,因此是对应于中缀符号的函数

  • inner(x,y)是始终有效的内积,具有共轭和递归,将被人们在更一般的技术环境中使用。

我并不认为这是在 Julia 语言中采用的好选择,但我确实认为这就是它在许多文献中的使用方式。 当使用中缀点时,它或者作为实向量上下文中的内积,或者在一些更一般的结构中,它只是意味着收缩。 当打算在任意向量空间上进行一般内积时,大多数科学文献(但您肯定已经展示了反例)切换到<u,v><u|v> (在第一个符号中仍然讨论两个参数中的一个是共轭的)。

我可以接受这个提议,但我同样可以接受只有dot作为一般内积。 最后,这是一个拥有良好文档的问题,我也不敢相信有人会因为这个“设计”选择而绊倒。

@Jutho ,我同意将dot定义为仅表示收缩的情况并不少见。 当然,人们可以通过两种方式找到示例。 例如,在编程语言和流行库中:

  • 非共轭:Numpy dot (奇怪的是, inner ),Mathematica 的Dot ,Maxima . ,BLAS dotu

  • 共轭:Matlab 的dot ,Fortran 的DOT_PRODUCT ,Maple 的DotProduct ,Petsc 的VecDot ,Numpy vdot ,BLAS dotc (注意缺少Fortran 77 中的重载使得即使他们想调用这个dot也是不可能的),Eigen 的

一方面,共轭内积通常在教科书中作为“点积”概念对复向量“自然”扩展来介绍——非共轭版本在某种意义上是一种“非自然”扩展,因为它通常不是你想要什么。 (考虑一个事实,在其标准库中提供共轭dot函数的语言中——Matlab、Fortran、Julia、Maple——只有 Maple 提供了非共轭变体,这暗示着需求不足。)另一方面,非共轭dotu函数在某些特殊情况下(其中一些我在上面提到)很方便(作为补充)。

如果我们同时拥有dotinner ,我怀疑很多人最终会在他们真正想要inner的代码时意外使用dot通用的。 (我敢打赌,Numpy 的inner只是因为这样的事故而没有共轭 - 他们在实现它时考虑到了真正的数组,并且没有考虑复杂的情况,直到改变为时已晚,所以他们添加了笨拙地命名为vdot 。)如果我们有dot和(可能) dotu ,那么dot是默认选择和dotu会更清楚

(我同意⟨u,v⟩⟨u|v⟩(u,v)是任意希尔伯特空间上的内积更常见的符号——它们是我自己通常使用的符号——但这些符号是Julia 的非入门者。有一些关于将 Unicode 括号解析为函数/宏调用的讨论,例如 #8934 和 #8892,但它从未走到任何地方,而且这似乎不太可能很快改变。)

我完全同意你的评估@stevengj

我也是。

我怀疑是时候让我们中的一个人在 PR 中使用任一实现,看看结果如何。

@Jutho我总是将Pauli矩阵的点积视为高阶张量收缩的简写......向量空间之一是真实的,3D。

我同意 ⟨u,v⟩、⟨u|v⟩ 或 (u,v) 是任意 Hilbert 空间上的内积的更常见符号——它们是我自己通常使用的符号——但这些符号对 Julia 来说是行不通的。

实际上可以使⟨u,v⟩工作。

@StefanKarpinski :实际上可以让 ⟨u,v⟩ 工作。

绝对可以,并且在#8934 中建议支持这种精确的符号,但它从未走到过任何地方。 (另请注意,尖括号还有其他常见用途,例如 ⟨u⟩ 通常表示某种平均值。)它是非破坏性的,仍然可以在某些时候添加,但期望在不久的将来似乎不合理学期。 键入\langle<tab> x, y \rangle<tab>也很慢,因此从编程的角度来看,对于基本操作来说不是很方便。

我们不能为它重载 <> ,对吧?

不能说我已经阅读了关于这个巨大线程的每条评论,但我只想强调几点,其中一些之前已经提出:

  • 区分点和内部似乎过于迂腐。 事实上,在我看来,这似乎很荒谬,因为在法语中只有一个术语——“标量积”——而且对我来说很难区分具有相同名称的事物;-)
  • 当您来自 numpy 并使用复杂的数组时,默认情况下共轭dot是有史以来最好的事情。 这里没有决定点,我只是想说我很高兴我不再需要做这些conj(dot()) s!
  • 拥有两个在大多数情况下具有相同行为但有时不同的函数是糟糕的设计,并且已经并将导致混淆,代码应该调用一个实际上调用另一个,只是因为用户不知道更好。 这对于norm尤其烦人:如果您正在编写优化算法并希望在norm(delta x) < eps时停止,您将编写norm 。 但是然后你想优化图像或其他东西,你运行你的代码,它突然启动到一个大数组的无法杀死的(因为 BLAS)SVD。 这不是学术性的,它在 Optim.jl 中造成了麻烦,毫无疑问在其他包中也是如此。 除非他们有特定的理由寻找它,否则没有人会知道vecnorm的存在。
  • 基于前一点,任何合并dotvecdot以及normvecnorm的解决方案都是好的,即使它消除了一些灵活性数组数组案例。 对于规范,在处理定义了多个规范的事物(例如矩阵)时,我经常补充一点,用户想要的是调用norm获得规范,而不是特别关心哪个规范。 由于其计算上的难处理性,诱导规范通常具有理论而非实际意义。 它们还特定于 2D-array-as-operator 解释,而不是 2D-array-as-storage 解释(图像是 2D 数组,但它不是任何有用意义上的运算符)。 有可能计算它们很好,但它们不应该成为默认的norm 。 具有可发现替代方案的合理、简单和有据可查的默认设置比尝试的聪明要好(如果用户想做一件聪明的事情,让他们明确地去做)。

因此,在@stevengj上 +1

是的,我认为如果我们进行此更改,那么我们只需要点和范数(它们现在是对任何维度的数组或数组数组的递归欧几里德运算,尽管对于范数,我们也将 norm(x,p) 定义为p-norm) 和 opnorm,不再有 vecdot 或 vecnorm。

norm/opnorm 的一个更“julian”的替代方案可能是有一个 Operator 类型,它可以包装一个 2D 数组, norm在该数组上执行 opnorm。 这可以在包级别完成(其中几个已经存在)

我宁愿输入opnorm(matrix)而不是norm(Operator(matrix)) ...

我要从这里的花生画廊插话说我喜欢这里的发展方向—— vecnormvecdot一直困扰着我。 需要明确地要求运算符范数——这对我来说似乎一直是相当专业的——似乎比必须要求一个更快、更容易计算的范数(例如 Frobenius 范数)要理智得多。 编写opnorm似乎是要求相对专业的运算符规范的一个很好的界面。

我也觉得dotinner之间的细微区别可能会导致混淆和猖獗的误用。 当两个功能都做他们想做的事情并且其中一个更容易时,向用户说明他们应该使用哪个功能往往效果不佳。 我的印象是,当真正的内部积⟨u,v⟩实际存在时,在通用代码中sum(x*y for (x,y) in zip(u,v))实际上是您想要的相对较少。 如果这确实是我们想要的,那么只需编写类似的东西来计算它就相当容易、清晰和高效(因为 Julia 就是这样)。

是否调用u⋅v函数dotinner似乎是所有这一切中最不重要的部分。 我相当肯定,这两种选择都不会被历史学家视为一场灾难——尽管历史学家会关心的想法肯定是讨人喜欢的。 一方面,如果我们同意保留u⋅v的“真正内积”含义,那么是的, inner是更正确的数学术语。 另一方面,当存在具有相应函数名称的语法时,当名称与语法匹配时,它往往会减少用户的混淆。 由于此处的语法使用点,因此该经验法则支持将此操作拼写为dot 。 也许这可能是定义const dot = inner并导出两者的合理案例? 然后人们可以使用或扩展他们喜欢的任何名称,因为它们是同一个东西。 如果有人想将其中一个名称用于其他名称,则另一个名称将以其默认含义保持可用。 当然,这会为同一个函数生成三个导出名称—— dotinner ——这似乎有点过分了。

是否可以选择删除符号或将其替换为<u,v>

注释:

  • 它使意图明确。 比较这两个例子:
<u,v> * M * x

对比

u ⋅ v * M * x
  • <u,v>语法意味着关联:首先我们对uv进行操作,然后是表达式的其余部分。

  • 如果用户努力输入<u,v> ,那么他很可能不会想到简单的sum(x[i]*y[i])这个符号很容易用眼睛跳过,还有很多其他的含义。 特别是,在线性代数中,对于域 F 上的向量空间 V,标量α ∈ F向量v ∈ V的乘积在各种教科书中表示为α ⋅ v

  • 删除或替换也将消除导出多个名称的问题。 对于一般的内积,只需要导出inner<,> ,数组的默认实现与可迭代求和语义相匹配。

  • 如果需要为域 F 上的向量空间 V 定义如上所述的逐向量乘积,他/她将能够为其定义符号。 然后向量空间将用漂亮的短语法完全定义,并且可以通过进一步定义<u,v>扩展到希尔伯特空间。

我们绝对不能使用语法<u,v> ; 我们可以使用的语法是⟨u,v⟩ ——注意 Unicode 括号,而不是小于和大于符号, <> 。 我们还有u'v作为点积或内积的语法? (我不确定是哪个...)

是的,对不起,它的 unicode 版本。 读起来会很清楚。 它还可以使用多个名称解决此问题,并免费用于其他目的。

我不认为我们想将用于任何其他目的——这似乎会令人困惑。

想象一下能够编写如下代码是多么美妙:

⟨α ⋅ u, v⟩ + ⟨β ⋅ w, z⟩

对于抽象向量(或类型) u,v,w,z ∈ V和标量α, β ∈ F

u'v是仅用于一维数组的内积(和点积,如果您遵循共轭约定),而不是例如矩阵。 (这是将中缀点限制为 1d 数组毫无意义的另一个原因,因为我们已经为这种情况提供了一个简洁的符号。)

Stefan,“正确的数学术语”是一个类别错误——数学正确性不是一个适用于术语/符号的概念。 (用“常规”代替“正确”。但随后担忧变得不那么紧迫,)

更多用例: https ://stackoverflow.com/questions/50408177/julia-calculate-an-inner-product-using-boolean-algebra

以及使用⟨,⟩符号的布尔内积的正式推导: https ://arxiv.org/abs/0902.1290

编辑:固定链接到论文

您如何看待尖括号语法提案? 它会解决这里提出的问题吗?

那么你的建议到底是什么? 大致是这样的吗:

  1. dot弃用为inner
  2. u⋅v弃用为⟨u,v⟩

那么就没有dot函数和运算符了吗?

这种变化会合理吗?

抱歉延迟回复,我正在参加互联网访问受限的会议。

只是为了清晰和完整,这里的反建议是什么? 没做什么?

为了进一步澄清该提议,涉及到语义变化:广义内积。

注意:我们现在已经对此进行了辩论,以至于存在无法进入 0.7-alpha 的真正风险。 这并不意味着它在 alpha 之后就不能改变,但是在那之后会有更多的不愿意改变的事情。

是的,我希望我有能力在很久以前提交 PR。 实现它超出了我的能力范围,尽管我发现它是非常重要的功能。

即使不考虑运算符语法问题,对于每组语义概念(当前的dotvecdot和当前的normvecnorm )。

对于dot方面,似乎整个选项空间(再次折扣运算符)是:

I. 通过将 0.7 中的行为更改为没有标准 depwarn 的内积(尽管您可以警告行为正在更改),从而在数组向量上静默破坏dot 。 在 0.7 中也将 $ vecdot弃用为dot
二、 在 0.7 中,弃用vecdotinner的所有输入。
三、 在 0.7 中,将数组向量上的dot弃用到其定义中,将dot弃用在其他输入上,将vecdot弃用在inner的所有输入上。
四。 在 0.7 中,将数组向量上的dotvecdot弃用为未导出的函数或其定义,并弃用vecdot的所有其他输入到dot 。 在 1.0 中,在具有内积语义的数组向量上添加dot

对于规范方面,围绕单一路径达成了一些共识(在 0.7 中,将矩阵上的 $ norm弃用为opnorm并可能将vecnorm弃用为innernorm ;在 1.0 ,在具有当前vecnorm语义的矩阵上添加norm ),但这也会导致 1.0 中的额外名称( vecnorminnernorm ); 再次避免这种情况的方法可能是将 0.7 中的vecnorm弃用为其定义或未导出的函数(如Base.vecnorm ),而不是导出的名称。

...我想。 希望我没有让事情变得比现在更糟。

任何熟悉代码库的人都可以为更改提交 PR 吗?

我们能否将每个人似乎都同意的规范内容分开并至少完成它? dotinner位更具争议性,但我们不要让这阻碍了不是的部分。

@StefanKarpinski ,请注意它们有些耦合:对于同时具有点(内部)产品和规范的类型,它们应该是一致的。

好吧,我真的不在乎这是怎么回事。 谁来做这项工作,谁来决定。

我有一个 PR (#25093),通过使它们递归来使vecdot表现为真正的内积(并且vecnorm作为相应的规范)。 这可能有助于作为未来dotnorm外观的起点。 不幸的是,我缺乏 git 技能让我搞砸了那个 PR,所以我关闭了它,计划在新的迭代语法完成后返回它。

然而,几天前刚刚第二次成为父亲意味着我的日历中目前没有“空闲时间”时段。

几天前刚刚第二次当爸爸

恭喜朱托! 🎉

是的,恭喜!

似乎围绕同时拥有dotinner的想法可能会形成一些共识,其中:

  1. inner是真正的递归内积
  2. dot = dot(x,y) = sum(x[i]'*y[i] for i = 1:length(x))是否共轭,因此对于Vector{<:Number}Vector{<:Real}将与dot重叠

关于:

当他们的意思是内部时,许多人会写点,并且在大多数情况下它对他们来说会很好,但是如果传递一个矩阵数组,他们的代码会做一些意想不到的事情。

我不相信这会是一个问题。 由于这是一个相当少见的操作,我希望人们至少尝试一下,看看它做了什么和/或查看文档。

我认为以上将是一个很大的变化,并且不会造成很大的破坏,因为在大多数情况下dot的语义不会改变。

似乎围绕同时拥有dotinner的想法可能会形成一些共识

相反,来自https://github.com/JuliaLang/julia/issues/25565#issuecomment -390069503 的讨论似乎倾向于使用其中之一,而不是两者,如https://github 中所述。 com/JuliaLang/julia/issues/25565#issuecomment -390388230 并得到很好的反应支持。

也许inner (还有dot )应该是递归的内部/点/标量产品,旧的行为可以在诸如dotc(x,y) = sum(x[i]' * y[i] for i in eachindex(x))dotu(x,y) = sum(transpose(x[i]) * y[i] for i in eachindex(x))之类的函数中实现? 名称dotudotc将匹配相应的 BLAS 名称。

(我同意 ⟨u,v⟩、⟨u|v⟩ 或 (u,v) 是任意希尔伯特空间上的内积的更常见符号——它们是我自己通常使用的符号——但这些符号对 Julia 来说是行不通的. 有一些关于将 Unicode 括号解析为函数/宏调用的讨论,例如 #8934 和 #8892,但它从未走到任何地方,而且这似乎不太可能很快改变。)

@stevengj ,当您自己将这一段添加到之前的评论中时,您的意思是语法⟨u,v⟩很难在语言中实现?

这个功能有没有机会进入 Julia v1.0? 我有很多想法和包装取决于一般内积的概念。 请让我知道我是否应该降低我的期望。 抱歉一直提醒。

你没看过#27401吗?

谢谢@jebej ,谢谢@ranocha带头:心:

当您自己将这一段添加到之前的评论中时,您的意思是语法⟨u,v⟩很难在语言中实现?

添加到解析器在技术上并不难,但事实证明很难就如何(以及是否)在语言中表示自定义括号达成共识。 请参阅#8934 的讨论,该讨论在 4 年前无处可去,此后一直没有恢复。 (加上在不同领域人们对许多不同事物使用相同的括号这一事实,例如 ⟨u⟩ 用于统计物理学中的整体平均值。)#8892 中提出的另一个问题是许多不同 Unicode 的视觉相似性括号。

谢谢@stevengj ,感谢您的澄清。 我已经很兴奋我们将有跨包标准化的通用内部产品。 :100: 也许尖括号符号将来会在另一个发布周期中大放异彩。 能够编写与我们出版物中的数学完全一样的代码并不那么重要,但非常方便。

如果⟨args...⟩是调用anglebrackets运算符或其他东西的有效语法(调用该语法调用的函数实际上有点棘手,因为我们没有任何先例),那么人们可以选择他们想要的语法含义。

@StefanKarpinski ,#8934 中的论点是它应该是一个宏。 我认为我们从未达成共识。

(如果我们在 Base 中决定anglebrackets(a,b)意味着inner(a,b) ,那将阻止人们“选择他们想要的任何含义”,因为已经做出了决定。
当然,这不是一个糟糕的选择,但可能没有必要在 Base 中为其分配一个含义,只要它们被解析即可。)

我不记得那次讨论的细节,但制作宏对我来说显然是个坏主意。

对于#27401,我认为我们可以考虑认真对待内积。

传统上,只有在合并相关 PR 时才会关闭问题......

当然,我猜我们可以让它保持打开状态。 只是想把它从分类标签上拿下来。

自从#27401 现在合并后,是否应该关闭它?

此页面是否有帮助?
0 / 5 - 0 等级