3D数学系列之——再谈蒙特卡洛积分和重要性采样

目录

  • 一、前篇文章回顾
  • 二、积分的黎曼和形式
  • 三、积分的概率形式(蒙特卡洛积分)
  • 四、误差
  • 五、蒙特卡洛积分计算与收敛速度
  • 六、重要性采样
  • 七、重要性采样方法和过程
  • 八、重要性采样的优缺点

一、前篇文章回顾

  在前一篇文章3D数学系列之——从“蒙的挺准”到“蒙的真准”解密蒙特卡洛积分!中,介绍了下面的这些朴素的公式:
灰色部分中点数 总的点数 ≈ 灰色部分面积 矩形面积 ⇒ 灰色部分面积 ≈ 矩形面积 × 灰色部分中点数 总的点数 \begin{align} & \cfrac{ 灰色部分中点数 } {总的点数} \approx \cfrac{灰色部分面积} {矩形面积} \\[2ex] & \Rightarrow 灰色部分面积 \approx 矩形面积 \times \cfrac{ 灰色部分中点数 } {总的点数} \end{align} 总的点数灰色部分中点数矩形面积灰色部分面积灰色部分面积矩形面积×总的点数灰色部分中点数

灰色部分面积 ≈ 矩形面积 × P ( P 为点落在灰色部分的概率) 灰色部分面积 \approx 矩形面积 \times P \quad (P为点落在灰色部分的概率) 灰色部分面积矩形面积×PP为点落在灰色部分的概率)

  虽然最终通过一个简单的概率乘法就可以计算出积分值,但是如何得到这个精确的概率值从而得到比较精确的积分值却不是那么简单的。并且这个方法直接用于计算或者说模拟计算来说,不确定的东西太多。下面我们就继续从积分的基本公式开始,讨论一下看看有没有进一步更形式化和更精确一点的方法。

二、积分的黎曼和形式

  对于数值积分计算来说,积分的黎曼和形式是最基本的形式:
∫ a b f ( x ) d x ≈ ∑ n = 1 N f ( x n ) b − a N (1) \int \limits_a^b {f}(x) \mathrm{d} x \approx \sum \limits_{n=1}^N {f}(x_n) \cfrac{b-a}{N} \tag{1} abf(x)dxn=1Nf(xn)Nba(1)
  这是一个常见和基本的可以用于积分计算程序的基本公式。

三、积分的概率形式(蒙特卡洛积分)

  接着我们对黎曼和使用著名的”陶哲轩瞪眼法“进行观察。

  首先对于求和来说,第一项是 f ( x n ) {f}(x_n) f(xn) ,这里我们一般会比较容易知道 f ( x ) {f}(x) f(x) 的解析形式或者可以知道它的一些离散值。

  在实际计算中需要生成的是 x n x_n xn 的序列,这个序列是跟后面的 ( b − a ) N \cfrac{(b-a)}{N} N(ba) 紧密关联的,因为需要保证 x i − x i − 1 = b − a N x_{i}-x_{i-1} = \cfrac{b-a}{N} xixi1=Nba x n x_n xn 序列是个等差数列,间隔是就是 ( b − a ) N \cfrac{(b-a)}{N} N(ba)

  这时,我们先打开思路,既然前一讲中已经可以通过随机变量的形式来计算积分,那么这时我们可不可以用一组随机数的序列来代替 x n x_n xn 的序列呢?

  既然讲到随机,那么回忆一下概率论中关于“均匀分布随机变量”的概率密度函数(The Probability Distribution Function,缩写为 PDF):
p ( x ) = { 1 b − a , a < x < b 0 , 其他 (2) \mathrm{p}(x) = \begin{cases} \cfrac{1}{b-a}, \quad a \lt x \lt b \\[2ex] 0, \quad 其他 \end{cases} \tag{2} p(x)= ba1,a<x<b0,其他(2)
  接着我们用"陶哲轩瞪眼法"观察黎曼和公式与上面这个公式,此时我们应灵光乍现想到下面这样的形式:
∫ a b f ( x ) d x ≈ ∑ n = 1 N f ( x n ) b − a N = 1 N ∑ n = 1 N f ( x n ) × ( b − a ) 根据乘以一个数等于除以一个数的倒数这个法则,有: = 1 N ∑ n = 1 N f ( x n ) p ( x n ) (3) \int \limits_a^b {f}(x) \mathrm{d} x \approx \sum \limits_{n=1}^N {f}(x_n) \cfrac{b-a}{N} \\[2ex] = \cfrac{1}{N} \sum \limits_{n=1}^{N} {f}(x_n) \times (b-a) \\[2ex] 根据乘以一个数等于除以一个数的倒数这个法则,有: \\[2ex] = \cfrac{1}{N} \sum \limits_{n=1}^{N} \cfrac{{f}(x_n)}{\mathrm{p}(x_n)} \tag{3} abf(x)dxn=1Nf(xn)Nba=N1n=1Nf(xn)×(ba)根据乘以一个数等于除以一个数的倒数这个法则,有:=N1n=1Np(xn)f(xn)(3)
  啊哈!太好了,这一切看似是公式间的一种巧合或者说技巧性的,接着我们思考下它的意义。因为刚才我们已经说过原来的 x n x_n xn 序列是个等差序列,本身就是均匀分布的,所以其概率密度函数(PDF)就是均匀分布变量的 PDF。如果我们取一个随机的 x n x_n xn 序列,并假设知道它的 PDF p ( x n ) \mathrm{p}(x_n) p(xn) 那么就可以根据上面这个式子的结果来计算积分值了。并且当 x n x_n xn 不断增多时,和 1 N ∑ n = 1 N f ( x n ) p ( x n ) \cfrac{1}{N} \sum \limits_{n=1}^{N} \cfrac{{f}(x_n)}{\mathrm{p}(x_n)} N1n=1Np(xn)f(xn) 也就越接近原始的积分值!这也就是传说中的蒙特卡洛积分的基本形式。它是合理且有意义的,起码我们不用只靠前一讲中的“蒙的真准”的方法了。需要注意的就是其中 f ( x n ) p ( x n ) \cfrac{{f}(x_n)}{p(x_n)} p(xn)f(xn) 项看上去虽然很奇怪,但他其实是有实际含义的,一般被称作概率平均。

  当然使用随机序列 x n x_n xn 是有条件的,即要求:
∫ − ∞ + ∞ p ( x ) = 1 (4) \int \limits_{-\infty}^{+\infty} \mathrm{p}(x) = 1 \tag{4} +p(x)=1(4)
  接着我们继续观察(还是使用 “陶哲轩瞪眼法”)那个带有 PDF 的蒙特卡洛积分公式,发现其中还有个 1 N \cfrac{1}{N} N1 , 这时我们应该突然明白其实这个式子还是个平均值的公式,而讲到平均值,学过概率论的同学就应该立刻想到“数学期望”。一般的数学期望的定义:
E [ f ( X ) ] = ∑ n = 1 ∞ f ( x n ) p ( x n ) E[{f}(X)] = \mathop{\sum}\limits_{n = 1}^{\infty} {f}(x_n) \mathrm{p}(x_n) E[f(X)]=n=1f(xn)p(xn)
  也就是说如果我们知道了随机变量 x n x_n xn 的随机 PDF: p ( x n ) \mathrm{p}(x_n) p(xn),那么随机变量函数的数学期望就可以用上式计算。当然如果 x n x_n xn 是连续的随机变量,那么就可以用积分形式来表示上面的表达式:
E [ f ( X ) ] = ∫ − ∞ + ∞ f ( x ) p ( x ) d x E[{f}(X)] = \mathop{\int}\limits_{-\infty}^{+\infty} {f}(x) \mathrm{p}(x) dx E[f(X)]=+f(x)p(x)dx
  这时,为了验证蒙特卡洛积分公式的正确性,我们来看看它的数学期望:
E ( F ( X ) ) = E [ 1 N ∑ n = 1 N f ( x n ) p ( x n ) ] = 1 N ∑ n = 1 N ∫ a b f ( x ) p ( x ) × p ( x ) d x = 1 N ∑ n = 1 N ∫ a b f ( x ) d x = ∫ a b f ( x ) d x E(F(X)) = E \left[ \cfrac{1}{N} \sum \limits_{n=1}^{N} \cfrac{{f}(x_n)}{\mathrm{p}(x_n)} \right] \\[2ex] = \cfrac{1}{N} \sum \limits_{n=1}^{N} \int \limits_{a}^{b} \cfrac{{f}(x)}{\mathrm{p}(x)} \times \mathrm{p}(x) \mathrm{d}x \\[2ex] = \cfrac{1}{N} \sum \limits_{n=1}^{N} \int \limits_{a}^{b} {f}(x) \mathrm{d} x \\[2ex] = \int \limits_{a}^{b} {f}(x) \mathrm{d}x E(F(X))=E[N1n=1Np(xn)f(xn)]=N1n=1Nabp(x)f(x)×p(x)dx=N1n=1Nabf(x)dx=abf(x)dx
  这个结果简直太棒了!它说明蒙特卡洛积分公式的数学期望就是我们要求的积分值。这也间接的证明我们前面靠瞪眼法得到的公式本质上是正确的。或者说,蒙特卡洛积分的结果对于积分真值是无偏差的,也就是说是原积分的无偏估计。这个可以由“大数定理”来保证。只是不同的随机变量序列 x n x_n xn 会以不同的“速度”靠近积分原值。

四、误差

  按照数学家们的“尿性”,一定会严格的分析一下整个“蒙的挺准”的过程中的误差。既然刚才已经分析了蒙特卡洛积分的数学期望,那么继续根据概率论的知识,我们来分析下它的误差。一般对于随机序列来说,我们取其方差来评估其靠近真实值的程度。那么就让我们来计算下蒙特卡洛积分的方差:
σ 2 [ F n ( X ) ] = σ 2 [ 1 N ∑ n = 1 N f ( x n ) p ( x n ) ] = 1 N 2 ∑ n = 1 N ∫ a b ( f ( x ) p ( x ) − E ( F n ( X ) ) ) 2 × p ( x ) d x = 1 N [ ∫ a b ( f ( x ) p ( x ) ) 2 × p ( x ) d x − E ( F x ( X ) ) 2 ] = 1 N [ ∫ a b f ( x ) 2 p ( x ) d x − E ( F n ( X ) ) 2 ] (5) \sigma^2[F_n(X)] \\[2ex] = \sigma^2 \left[ \cfrac{1}{N} \sum \limits_{n=1}^{N} \cfrac{f(x_n)}{\mathrm{p}(x_n)} \right] \\[2ex] = \cfrac{1}{N^2} \sum \limits_{n=1}^{N} \int \limits_a^b \left( \cfrac{f(x)}{\mathrm{p}(x)} - E(F_n(X)) \right)^2 \times \mathrm{p}(x) \mathrm{d}x \\[2ex] =\cfrac{1}{N}\left[ \int \limits_a^b \left( \cfrac{{f}(x)}{\mathrm{p}(x)} \right)^2 \times \mathrm{p}(x) \mathrm{d}x - E(F_x(X))^2 \right] \\[2ex] = \cfrac{1}{N} \left[ \int \limits_a^b \cfrac{{f}(x)^2}{\mathrm{p}(x)} \mathrm{d}x - E(F_n(X))^2 \right] \tag{5} σ2[Fn(X)]=σ2[N1n=1Np(xn)f(xn)]=N21n=1Nab(p(x)f(x)E(Fn(X)))2×p(x)dx=N1 ab(p(x)f(x))2×p(x)dxE(Fx(X))2 =N1 abp(x)f(x)2dxE(Fn(X))2 (5)
  上面最终包含了 1 N \cfrac{1}{N} N1 项的最终的一堆公式,就是蒙特卡洛积分的方差,根据概率论的定义,其标准差就是方差的算术平方根。

  按照最终的证明结果,蒙特卡洛积分值与积分真实值之间的标准差(误差)有如下的形式:

误差 ∝ 1 N (6) 误差 \varpropto \cfrac{1}{\sqrt{N}} \tag{6} 误差N 1(6)
  即最终误差正比于N的平方根的倒数。

五、蒙特卡洛积分计算与收敛速度

  有了前面这些数学知识的加持,那么我们就可以来看看用蒙特卡洛积分来计算积分时到底“速度”如何?

  其实看到这里,大家应该有个疑惑,我们费劲巴拉的推导了半天,到底在图个啥?

  那么如果你看了前一篇文章(3D数学系列之——从“蒙的挺准”到“蒙的真准”解密蒙特卡洛积分!),首先应该想到有了蒙特卡洛积分公式,我们是不是可以开始靠“蒙”来计算积分了?答案是肯定的,要计算蒙特卡洛积分,我们就需要产生一个随机变量的序列 x n x_n xn 并且需要知道其概率密度函数(PDF) p ( x n ) \mathrm{p}(x_n) p(xn) (有时候不需要知道 PDF 的表达式,只需要知道每个随机变量对应的概率值即可) 然后代入公式的右侧进行计算:
∫ a b f ( x ) d x ≈ 1 N ∑ n = 1 N f ( x n ) p ( x n ) (3) \int \limits_a^b {f}(x) \mathrm{d} x \approx \cfrac{1}{N} \sum \limits_{n=1}^{N} \cfrac{{f}(x_n)}{\mathrm{p}(x_n)} \tag{3} abf(x)dxN1n=1Np(xn)f(xn)(3)
这样计算的好处是,我们可以用大一些(计算能力充足时)或者小一些(计算能力不足时)的随机变量序列来进行计算。

  当然这样计算的限制是,根据对蒙特卡洛方法标准差的计算,最终可以知道如果我们想提高计算精度一倍,那么差不多就需要将N提高4倍( 1 4 = 1 2 \cfrac{1}{\sqrt{4}}=\cfrac{1}{2} 4 1=21 ,即误差减小一半)。所以这就是平常所说的蒙特卡洛积分法收敛慢的根本原因。

  例如在我们关注的图形的光照积分估算过程中,这是个麻烦的问题,比如原先需要每个点采样1000条光线近似计算最终光照效果,要提高一倍精确度从而改进画质效果的话,那么每个点就需要采集4000条光线进行积分。因此,基本上现实中很少直接用蒙特卡洛积分的基本形式来求积分值的。

  所以最终这个结论是有点令人灰心丧气的,不过请继续往后看,这么好的方法一定已经有很多人帮我们想了很多办法来解决问题的。

六、重要性采样

  OK,看到这里你还没有晕过去的话,请为自己点个赞先!

  鉴于前面说的直接运用蒙特卡洛方法进行积分计算时,因为固有偏差的问题,而导致算法过程收敛过慢(N的平方根倒数的量级)所以在计算效率上是不尽人意的。那么既然是因为偏差导致的问题,我们就继续从偏差来分析看看:
σ 2 [ F n ( X ) ] = 1 N [ ∫ a b f ( x ) 2 p ( x ) d x − E ( F n ( X ) ) 2 ] = 1 N [ ∫ a b f ( x ) 2 p ( x ) d x − ( ∫ a b f ( x ) d x ) 2 ] \sigma^2[F_n(X)] \\[2ex] = \cfrac{1}{N} \left[ \int \limits_a^b \cfrac{{f}(x)^2}{\mathrm{p}(x)} \mathrm{d}x - E(F_n(X))^2 \right] \\[2ex] =\cfrac{1}{N} \left[ \int \limits_a^b \cfrac{{f}(x)^2}{\mathrm{p}(x)} \mathrm{d}x - \left( \int \limits_a^b {f}(x) \mathrm{d}x \right)^2 \right] σ2[Fn(X)]=N1 abp(x)f(x)2dxE(Fn(X))2 =N1 abp(x)f(x)2dx abf(x)dx 2
  这时如果我们想要标准差(方差的开方)最小,那么就需要让上式结果等于0,此时我们继续使用瞪眼法可以发现,这需要下面的等式成立:
p ( x ) = ∣ f ( x ) ∣ ∫ a b f ( x ) d x (7) \mathrm{p}(x) = \cfrac{|{f}(x)|}{\int \limits_a^b {f}(x) \mathrm{d}x} \tag{7} p(x)=abf(x)dxf(x)(7)
  在很多其他的资料中,推得这个式子之后,忽略了讲解它的意义。乍看上去,貌似我们要知道我们需要使用的随机变量的概率密度,就需要先知道最终积分的结果,使得这个式子变成了无用的“鸡肋”。

  其实不然,这个式子恰恰给我们指明了一个非常明确的方向。

  它说明,如果我们要使得方差、标准差最小,那么就要找到一个随机变量序列使得它的概率密度函数与被积函数 f ( x ) {f}(x) f(x) 在“形状”上要高度一致!这是个很重要的信息。为什么这样说呢?其实仔细观察这个式子可以发现其中的定积分其实是个常数 ∫ a b f ( x ) d x \int \limits_a^b {f}(x) \mathrm{d}x abf(x)dx ,所以整个式子表达的意思是说 :
p ( x ) = ∣ f ( x ) ∣ S = A ∣ f ( x ) ∣ (8) \mathrm{p}(x) = \cfrac{|{f}(x)|}{S} = A|{f}(x)| \tag{8} p(x)=Sf(x)=Af(x)(8)
  即最终当概率密度函数其实就是被积函数的一个常数倍的时候,整个方差最小,也即标准差会非常小。

  这是整个重要性采样的出发点,也就是说我们可以依据被积函数的特征,构造一个与之匹配的概率分布函数的形状,然后生成特意构造的随机序列,再返回到蒙特卡洛积分 ∫ a b f ( x ) d x ≈ 1 N ∑ n = 1 N f ( x n ) p ( x n ) \int \limits_a^b {f}(x) \mathrm{d} x \approx \cfrac{1}{N} \sum \limits_{n=1}^{N} \cfrac{{f}(x_n)}{\mathrm{p}(x_n)} abf(x)dxN1n=1Np(xn)f(xn) 进行计算,那么只需要非常少的 x n x_n xn 就可以得到非常精确的积分结果,因为这样的序列计算后使得蒙特卡洛积分最终的方差、标准差都变得非常小,甚至为0。

  也就是说这样的随机序列,使得蒙特卡洛积分能够快速收敛!也就是说,咱们之前说的普通的蒙特卡洛积分过程误差与 1 N \cfrac{1}{\sqrt{N}} N 1 成正比导致我们必须付出平方倍的计算量,才能使的误差变小的规律可以被打破了,因为这个因子的后面那堆复杂的表达式在我们特意的设计下几乎 = 0,所以我们完全不用浪费过多的计算量来获取较精确的积分结果。 这个过程就被称为重要性采样!

七、重要性采样方法和过程

  那么最终如何进行上面所说的重要性采样呢?其实核心就是构造使的蒙特卡洛积分方差和标准差最小的随机数序列 x n x_n xn

  1、根据定义 ∫ a b p ( x ) d x \int \limits_a^b \mathrm{p}(x) \mathrm{d}x abp(x)dx 就是概率密度函数 p ( x ) p(x) p(x) 对应的累积分布函数(Cumulative Distribution Function),简称做 CDF,通常其正式定义如下:
C D F ( x ) = ∫ − ∞ x p ( x ~ ) d x ~ (9) \mathrm{CDF}(x) = \int \limits_{-\infty}^{x} p( \tilde{x} ) \mathrm{d} \tilde{x} \tag{9} CDF(x)=xp(x~)dx~(9)
  然后选择一个跟被积分的函数“相类似”的概率密度函数 PDF 来计算其 CDF;

  2、接着推导出 CDF 的反函数 C D F − 1 ( x ) \mathrm{CDF}^{-1}(x) CDF1(x)

  3、然后生成一个均匀分布的随机变量序列 u n ∈ [ 0 , 1 ] u_n \in [0,1] un[0,1] ;

  4、使用 u n u_n un 代入 CDF 的反函数 C D F − 1 ( x ) \mathrm{CDF}^{-1} (x) CDF1(x) 计算出随机序列 x n x_n xn ;

  5、最后将 x n x_n xn 代入蒙特卡洛积分中计算函数的积分值;

  通常在很小规模的 x n x_n xn 序列下,就可以计算出很高精度的积分值。

  举例来说,假设我们需要求一个形似 ∫ 0 π A sin ⁡ ( x ) d x \int \limits_0^{\pi} A \sin(x) \mathrm{d}x 0πAsin(x)dx 的积分,此时根据被积函数为正弦函数的特征,构造 p ( x ) = c sin ⁡ ( x ) x ∈ [ 0 , π ] p(x) = c \sin(x) \quad x \in [0,\pi] p(x)=csin(x)x[0,π] ,然后我们计算它的 CDF:
∫ 0 π c sin ⁡ ( x ) d x = c [ − cos ⁡ ( x ) ] 0 π = 2 c = 1 ∵ ∫ 0 π p ( x ) d x = 1 ⇒ c = 1 2 用 x 替换积分上限,得到 C D F 的表达式,有: C D F ( x ) = ∫ 0 x 1 2 sin ⁡ ( t ) d t = 1 2 [ − cos ⁡ ( t ) ] 0 x = 1 2 ( 1 − cos ⁡ ( x ) ) \int \limits_{0}^{\pi} c \sin(x) \mathrm{d}x = c \Biggl[-\cos(x)\Biggr]_0^{\pi} = 2 c = 1 \\[2ex] \because \quad \int_0^{\pi} p(x) \mathrm{d}x = 1 \\[2ex] \Rightarrow c = \cfrac{1}{2} \\[2ex] 用 x 替换积分上限,得到CDF 的表达式,有: \\[2ex] CDF(x) = \int\limits_0^x \cfrac{1}{2} \sin(t)\mathrm{d}t = \cfrac{1}{2} \Biggl[ -\cos(t) \Biggr]_0^{x} = \cfrac{1}{2}(1-\cos(x)) 0πcsin(x)dx=c[cos(x)]0π=2c=10πp(x)dx=1c=21x替换积分上限,得到CDF的表达式,有:CDF(x)=0x21sin(t)dt=21[cos(t)]0x=21(1cos(x))
  有了 CDF 那么我们来计算其反函数:
y = 1 2 ( 1 − cos ⁡ ( x ) ) ⇒ x = arccos ⁡ ( 1 − 2 y ) y = \cfrac{1}{2}(1-\cos(x)) \\[2ex] \Rightarrow \quad x = \arccos(1-2y) y=21(1cos(x))x=arccos(12y)
  接着我们生成一个均匀分布的随机数序列 u n u n ∼ [ 0 , 1 ] u_n \quad u_n \sim [0,1] unun[0,1] 代入上式中计算得到指定分布的随机序列 x n = arccos ⁡ ( 1 − 2 u n ) x_n = \arccos(1-2u_n) xn=arccos(12un),最终用这个序列按照蒙特卡洛积分公式计算即可快速得到 ∫ 0 π A sin ⁡ ( x ) d x \int \limits_0^{\pi} A \sin(x) \mathrm{d}x 0πAsin(x)dx 的积分值。

  那么详细的计算过程和程序就先略过了,在后续的 IBL 教程中将有更详细的应用讲解和实际工程中的代码。有兴趣的同学可以自己编写程序比较一下,即先用黎曼和及库函数sin计算得到积分结果,然后与库函数cos的直接计算结果进行比较,最好能求出方差,然后再用刚才推导出的 C D F − 1 CDF^{-1} CDF1 函数计算的序列代入蒙特卡洛积分公式中计算积分结果,同样与cos函数直接计算的结果求差,或者求方差,看看有什么区别?

八、重要性采样的优缺点

  根据前面的叙述,重要性采样的全部目的就是为了缩小 x n x_n xn 的规模,同时还能保证一定的精度,其实就是之前标题所说的从 “蒙的挺准” 到 “蒙的更准”,而且计算量还大大变小了,这对于很多需要数值积分的计算来说是非常非常好的优化方法。另外对于高维的积分来说,重要性采样的方法依然有效!这样带来的好处就是,原本复杂度可能是 O ( n α ) α ∈ Z + , α ⩾ 1 O(n^{\alpha}) \quad \alpha \in Z^+,\alpha \geqslant 1 O(nα)αZ+,α1 的问题,有可能直接变成了 O ( n ) O(n) O(n) 的问题,这对于我们关注的图形光照计算领域来说简直就是福音!因为我们需要处理的图形往往都是 n 3 n^3 n3 维度的,并且在复杂光照渲染算法中需要大量的 3D 积分,所以有了蒙特卡洛积分和重要性采样方法,就使得该过程的计算量几何级数的被减少,这最终使得实时 PBR 渲染成为可能。

  当然重要性采样也有缺点,根据刚才描述的过程,大家应该能想到,第一,如果被积函数 f ( x ) {f}(x) f(x) 过于复杂时,我们基本无法简单的模拟出一个形似的 p ( x ) p(x) p(x) 函数,从而整个过程有可能就前功尽弃;第二个方面就是说,通过 C D F − 1 CDF^{-1} CDF1 函数计算出的序列 x n x_n xn 有可能使得 f ( x ) {f}(x) f(x) 的值过于集中于一些较大函数值得地方,从而导致最终积分的结果与真值之间产生正偏差。

  当然幸运的是这两条缺点在我们的 PBR 渲染中几乎碰不到,也就没什么太大的影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/796.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

集成方法!

目录 关注降低variance,选择bias较小的基学习器 Bagging Stacking Random Forest 关注降低bias,选择variance较小的基学习器 Adaboost Boosting 关注降低variance,选择bias较小的基学习器 Bagging 给定m个样本的数据集&#xff0c;利用有放回的随机采样法&#xff0c;得…

【Linux】操作系统(Operator System)

操作系统&#xff08;Operator System &#xff09;一、操作系统的概念二、操作系统的作用三、系统调用和库函数一、操作系统的概念 操作系统是一组控制和管理计算机软硬件资源&#xff0c;为用户提供便捷使用的计算机程序的集合&#xff0c;是配置在计算机硬件系统上的第一层…

模拟实现字符串有关函数(详细讲解)

在编写程序时&#xff0c;我们都喜欢写出简便并且效率高的代码&#xff0c;那么此时库函数中的有些函数就是我们的不二之选&#xff0c;那么&#xff0c;大家汇米你实现吗&#xff1f;下面就先从我们最简单的字符串函数说起&#xff1a; 1.strlen 这个是函数的格式&#xff0c…

做了个springboot接口参数解密的工具,我给它命名为万能钥匙(已上传maven中央仓库,附详细使用说明)

前言&#xff1a;之前工作中做过两个功能&#xff0c;就是之前写的这两篇博客&#xff0c;最近几天有个想法&#xff0c;给它做成一个springboot的start启动器&#xff0c;直接引入依赖&#xff0c;写好配置就能用了 springboot使用自定义注解实现接口参数解密&#xff0c;普通…

SpringSecurity学习(七)授权

授权 什么是权限管理 权限管理核心概念 SpringSecurity权限管理策略 基于URL地址的权限管理 基于方法的权限管理 一、权限管理 二、授权核心概念 在认证的过程成功之后会将当前用户登录信息保存到Authentication对象中&#xff0c;Authentication对象中有一个getAuthorities…

ChatGPT-4震撼发布

3月15日消息&#xff0c;美国当地时间周二&#xff0c;人工智能研究公司OpenAI发布了其下一代大型语言模型GPT-4&#xff0c;这是其支持ChatGPT和新必应等应用程序的最新AI大型语言模型。该公司表示&#xff0c;该模型在许多专业测试中的表现超出了“人类水平”。GPT-4, 相较于…

基于Java+Springboot+vue高校资源共享交流平台设计和实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

SpringBoot介绍。

目录 一、SpringBoot简介 1、SpringBoot开发步骤 2、官网构建工程 3、SpringBoot概述 二、配置文件 1、配置文件格式 2、yaml格式 3、yaml配置文件数据读取 三、多环境配置 1、yam文件 2、properties文件 3、命令行启动参数设置 四、SpringBoot整合 1、SpringBo…

界面开发(4)--- PyQt5实现打开图像及视频播放功能

PyQt5创建打开图像及播放视频页面 上篇文章主要介绍了如何实现登录界面的账号密码注册及登录功能&#xff0c;还简单介绍了有关数据库的连接方法。这篇文章我们介绍一下如何在设计的页面中打开本地的图像&#xff0c;以及实现视频播放功能。 实现打开图像功能 为了便于记录实…

OCPC系列 - OCPC介绍扫盲贴来啦

本文对oCPC做个介绍&#xff0c;它是一种智能投放模式&#xff0c;系统通过对广告主转化数据的对接和深度理解&#xff0c;实时预估每一次点击的转化率并基于竞争环境智能出价&#xff0c;通过强化高转化率曝光机会的获取&#xff0c;弱化低转化率曝光机会的展现&#xff0c;以…

力扣-进店却未进行过交易的顾客

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目&#xff1a;1581. 进店却未进行过交易的顾客二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行…

文心一言正式对标GPT-4,是青铜还是王者?

昨天&#xff0c;OpenAI正式发布GPT-4模型 号称史上最先进的AI系统 今天&#xff0c;百度文心一言在万众瞩目中闪亮登场 这款产品被视为中国版ChatGPT 在这一个多月内备受关注 文心一言某种程度上具有了对人类意图的理解能力 回答的准确性、逻辑性、流畅性都逐渐接近人类…

Go 微服务开发框架 DMicro 的设计思路

Go 微服务开发框架 DMicro 的设计思路 DMicro 源码地址: Gitee:dmicro: dmicro是一个高效、可扩展且简单易用的微服务框架。包含drpc,dserver等 背景 DMicro 诞生的背景&#xff0c;是因为我写了 10 来年的 PHP&#xff0c;想在公司内部推广 Go, 公司内部的组件及 rpc 协议都…

多模态特征融合:图像、语音、文本如何转为特征向量并进行分类

多模态特征融合前言输入层&#xff0c;数据集转为特征向量图像语音什么是时域信号&#xff0c;什么是频域信号语音信号转换 - 1.傅立叶变换语音信号转换 - 2.梅尔频率倒谱系数文本词袋模型词嵌入模型输出层&#xff0c;多模态模型合并前言 学习多模态的话题可以从深度学习的分…

【YOLOv8/YOLOv7/YOLOv5/YOLOv4/Faster-rcnn系列算法改进NO.57】引入可形变卷积

文章目录前言一、解决问题二、基本原理三、​添加方法四、总结前言 作为当前先进的深度学习目标检测算法YOLOv8&#xff0c;已经集合了大量的trick&#xff0c;但是还是有提高和改进的空间&#xff0c;针对具体应用场景下的检测难点&#xff0c;可以不同的改进方法。此后的系列…

[JS与链表]普通链表

为什么要用链表要储存一系列数据&#xff0c;最常用的数据结构是数组。数组有个缺点就是在中间插入或删除元素需要移动元素&#xff0c;成本很高。什么是链表链表也是有序元素的集合结构。链表中的元素在内存中并不是连续放置的。每个元素都可以理解为一个对象。包含了本身元素…

简单了解JSP

JSP概念与原理概念: Java Server Pages&#xff0c;Java服务端页面一种动态的网页技术&#xff0c;其中既可以定义 HTML、JS、CSS等静态内容&#xff0c;还可以定义Java代码的动态内容JSP HTML Java, 用于简化开发JSP的本质上就是一个ServletJSP 在被访问时&#xff0c;由JSP容…

博途PLC开放式以太网通信TRCV_C指令应用编程(运动传感器UDP通信)

博途PLC开放式以太网通信TSENG_C指令应用,请参看下面的文章链接: 博途PLC 1200/1500PLC开放式以太网通信TSEND_C通信(UDP)_plc的udp通信_RXXW_Dor的博客-CSDN博客开放式TSEND_C通信支持TCP 、UDP等,关于TSEND_C的TCP通信可以参看下面这篇文章:博途PLC 1200/1500PLC开放式…

opencv识别车道线(霍夫线变换)

目录1、前言2、霍夫线变换2.1、霍夫线变换是什么&#xff1f;2.2、在opencv中的基本用法2.2.1、HoughLinesP函数定义2.2.2、用法3、识别车道3.1、优化3.1.1、降噪3.1.2、过滤方向3.1.3、截选区域3.2、测试其它图片3.2.1、代码3.2.2、图片13.2.3、图片23.2.4、图片31、前言 最近…

C++模拟实现红黑树

目录 介绍----什么是红黑树 甲鱼的臀部----规定 分析思考 绘图解析代码实现 节点部分 插入部分分步解析 ●父亲在祖父的左&#xff0c;叔叔在祖父的右&#xff1a; ●父亲在祖父的右&#xff0c;叔叔在祖父的左&#xff1a; 测试部分 整体代码 介绍----什么是红黑树 红…