读到这篇小文的朋友:新年好!今天我们将在本文中简单探索一个结合Wolfram语言的神经网络与B样条功能的有趣问题。
相信不少朋友在绘制等值面(contour surface)时,为了让结果看起来更加平滑流畅,都试过调高 PlotPoints ——即使这样会导致文件尺寸膨胀、笔记本3D交互性能下降。在笔记本界面里,解决这个问题的方法之一是用B样条曲线/曲面来近似我们的目标——作为一个性质良好的函数逼近工具,少量控制点定义的B样条就能给出(至少在视觉上)相当不错的逼近效果。本文尝试就此提供一个简单的思路,并探索如何利用可微分编程(在当前版本Wolfram语言中这通过神经网络框架来实现)来避免繁复的拟合公式、节省可观的内存消耗。
一些帮助函数
ClearAll[FindDivisionsExact]
FindDivisionsExact[range : {_, _}, n_Integer?(# >= 2 &)] :=
Rescale[Range[n] // N // Rescale, {0, 1}, range]
FindDivisionsExact[n_Integer?(# >= 2 &)] :=
FindDivisionsExact[{0, 1}, n]
ClearAll[pipe, branch, branchSeq]
pipe = RightComposition;
branch = Through@*{##} &;
branchSeq = pipe[branch@##, Apply@Sequence] &;
作为拟合目标的等值面
作为示例,我们选择大家喜闻乐见的来自 ContourPlot3D 文档的隐式周期曲面,并将其限制在一个球体区域 R 内:
之后,我们将在上述曲面片的边界 bR 上随机选择成对的点,并尝试寻找以这些点为两端、且属于曲面 S 的样条曲线段:
B样条曲线的模型
正如我们过去的Community文章中曾经提到过的,均匀B样条曲线通常都简单定义为其控制点按B样条基函数(BSplineBasis)加权线性组合的结果:
本文的拟合不涉及基函数的变化,因此我们可以简单地将上述公式离散化,从而得到曲线的离散近似:
这里 N 代表基函数离散化后得到的矩阵,P 是各曲线控制点组成的矩阵。矩阵尺寸的含义如下表:
神经网络表示的B样条曲线模型
如上所述,样条曲线在这里可以近似为 C=N·P。但我们在代码实现时并不是简单地一个 LinearLayer 就了事,因为这里曲线的端点(即第一个和最后一个控制点)是预定义或由外部设定的,只有"中间"的控制点才应该留给优化系统调节。因此这里我们有必要做简单的隔离:
将上述模板模型中的"basis"和"midCpts"两层替换为具体的 NetArrayLayer 就能获得实例化的曲线模型:(但"basis"层的实例化请继续阅读后文。)
B 样条基函数
如同以前介绍过的,在选定控制曲线光滑度的次数( bsDegree )和控制曲线形态最高可能复杂度的控制点个数( CPtsNum )后,我们可以调用 BSplineBasis 完全确定一组B样条基函数。进一步指定采样数量(
曲线的实例化
如同之前的实例化做法,但这里将"basis"层以 basisNet 取而代之,我们就得到了一组真正的B样条曲线:
神经网络表示的等值面模型
与曲线相比等值面模型相对简单。我们只需根据等值面公式构造一个网络,其输入是一组 d (d=$embeddedDim=3) 维空间的点的坐标,输出是一个衡量这些点与目标等值面符合程度的标量值:
注意这里的输入数据维度设定 TensorWithMinRankT[2] 具有足够的兼容性,因此我们的 surfaceMatchNet 在输入一组点(s*d)或多组点(c*s*d)时都能正常运作:
输入十万个点的例子:
输入8组、每组一万个点的例子:
用神经网络求解拟合问题
现在我们有能输出 c 条曲线上的各 s 个点的曲线模型 curvePrototype,有能评价任意组输入点对目标曲面符合程度的 surfaceMatchNet,将两者拼接起来,我们立即得到能评价曲线对目标曲面符合程度的网络:
我们从边界区域 bR 上选择 c 对随机点对,将其作为 c 条曲线的端点,并要求最终符合度尽可能高(对应于 "fit goodness" -> 0 ):
这里,总的来说更高的样条次数及合理多的控制点个数可能给出更好的拟合效果:
平均到每个点上的符合度:
从图上可以看出上面结果确实很好地拟合了目标等值面:
两条边界曲线 == 一条"缎带"
上文我们描述了一个将样条曲线拟合到等值面的简便方法,立刻可以想到,两条形态、距离足够相近的样条曲线可以通过张量积样条曲面生成一个用 BSplineSurface 描述的"缎带"的几何模型。(关于样条张量积的另一个例子可以参考我们过去的帖子。)
组合这两组端点,我们就得到了可以代入前文神经网络的端点集合:
类似前文的训练过程——但采用稍小的学习率(~(10^-5))——给出类似如下的结果:
拟合结果可视化
如前所述,我们将"缎带"表示为 BSplineSurface :
尝试各种不同的设定(如 shadings 及 Lighting 等),我们可以得到各种有趣的可视化效果:
也可以尝试在更细的缎带上采用 StippleShading 或 HalftoneShading :
一些剩余的问题
用神经网络而不是更传统的 FindFit 进行拟合在这里有什么好处?
事实上,传统的公式+拟合的方式理论上是可行的且实际上通常更快,但神经网络提供了一个描述问题和计算过程的不同方式,在该方式里内存的消耗大大降低了:
我们能用类似的方法近似获得曲面上的测地线吗?
对等值面来说,求测地线将对应着约束优化问题,在神经网络表述下并没有那么直接又高效的方法。另一方面,对参数化曲面,我们总可以用类似方法高效拟合其测地线。