# 重要性采样/Importance Sampling


```python
import random
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
```

## 继续前面的例子

- 我们使用被积函数作为 PDF
    - 但是需要它进行归一化，也就是说在样本空间，也就是$[a,b]$区间内积分要等于 1
    - 这样我们就需要对这个函数乘上一个系数 $C$
    - 通过下面这个简单的推导，就可以得出 $C$ 的值
$$
\begin{align}
& p(x) = C 3 x^2 \\
\Rightarrow & \quad \int_{a}^{b} C 3 x^2 dx = 1 \\
\Rightarrow & \quad C x^3 \big|_{a}^{b} = 1 \\
\Rightarrow & \quad C (b^3 - a^3) = 1 \\
\Rightarrow & \quad C = \frac{1}{b^3 - a^3}
\end{align}
$$

- 求 CDF

$$
P(x) = \int_a^x 3C t^2 \mathrm{d} t \\
P(x) = C t^3 \big|_{a}^{x} \\
P(x) = C (x^3 - a^3)
$$

- 求 CDF 的反函数

$$
P^{-1}(x) = \sqrt[3]{\frac{x}{C} + a^3}
$$

- 所以，我们的采样函数为
    - 其中 $\xi$ 即为 Uniform Sampling 的样本

$$
X = \sqrt[3]{\frac{\xi}{C} + a^3}
$$


```python
# 定义被积函数
def my_f(x):
    return 3*(x**2)

# 定义原函数
def my_F(x):
    return x**3

# 定义积分区间
a = 4
b = 8

# 使用原函数求解析解
def analytic_solution(F, a, b):
    return F(b)-F(a)
```


```python
def my_monte_carlo(func, a, b, n):
    result = 0
    C = (b**3)-(a**3)
    
    for i in range(n):
        xi = random.uniform(a,b)
        x = (xi/C+a**3)**(1.0/3)
        pdf = 3*(x**2)/C
        y = func(x)
        result += y/pdf
        
    return result/n
```


```python
analytic = analytic_solution(my_F, a, b)
print("analytic solution = ", analytic)

my_result = my_monte_carlo(my_f, a, b, 10000)
print("my_monte_carlo.result = {result}, error = {error}".format(result=my_result,error=analytic-my_result))
```

    analytic solution =  448
    my_monte_carlo.result = 448.0, error = 0.0


## 完美 PDF 并不存在

通过上述试验，我们发现，同样的样本数量，蒙特卡洛方法的误差已经惊人的降低到了$0$！

另外，你还可以尝试一下，把样本数量设置为1，同样可以得到误差为 0 的结果！这是因为我们使用了完美的 PDF 函数，并且成功求出了它的 CDF，以及 CDF 的反函数。这只是一个简单的试验的例子，这种理想的情况在实际工作中是不存在的。因为如果你可以像我前面那面求出完美的 PDF 的话，你也就可以得到解析解，也就用不到蒙特卡洛方法了。:)

在后面对于 BRDF 那种复杂函数采样的话，一般会选用一个尽量和它的分布接近的简单函数作为 PDF，然后推导出重要性采样的方法。

## 参考资料

- [Physically Based Rendering: Sampling Random Variables](https://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/Sampling_Random_Variables)
- [UCSD CSE 168 - Computer Graphics II: Rendering](https://cseweb.ucsd.edu/~viscomp/classes/cse168/sp20/info.html)


```python

```

862fa0cd35446e32bec3b33b0bdbd55682f4ad9e
ipynb
Jupyter Notebook
docs/part-1/07-Sampling.ipynb
neil3d/LearnPBR
5e54a1389f05d161c8977cffb95bfa4b724548f8
MIT
2021-06-23T04:32:24.000Z
2021-12-31T02:48:33.000Z
docs/part-1/07-Sampling.ipynb
neil3d/learnpbr
5e54a1389f05d161c8977cffb95bfa4b724548f8
MIT
docs/part-1/07-Sampling.ipynb
neil3d/learnpbr
5e54a1389f05d161c8977cffb95bfa4b724548f8
MIT
Qwen/Qwen-72B
1. YES
2. YES