我偷偷生成一波数据$x$,生成1000个吧,这些数据是从一个分布取样的,既然是偷偷生成的,那肯定不能告诉这个分布是什么~~~
聪明的你肯定先画个散点图看看大概是什么分布:
<span class="line"><span style="color: #286983">import</span><span style="color: #575279"> matplotlib</span><span style="color: #797593">.</span><span style="color: #575279">pyplot </span><span style="color: #286983">as</span><span style="color: #575279"> plt</span></span>
<span class="line"><span style="color: #575279">plt</span><span style="color: #797593">.</span><span style="color: #575279">hist</span><span style="color: #797593">(</span><span style="color: #575279">x</span><span style="color: #797593">,</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">bins</span><span style="color: #286983">=</span><span style="color: #D7827E">20</span><span style="color: #797593">)</span></span>
打眼一看这不就是正态分布吗,正态分布的话需要知道两个参数$\mu, \sigma$,也就是均值和标准差,于是聪明的你会定义两个变量,这两个变量就是你要learning的参数。
<span class="line"><span style="color: #575279">mu </span><span style="color: #286983">=</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">tensor</span><span style="color: #797593">(</span><span style="color: #D7827E">1.0</span><span style="color: #797593">,</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">requires_grad</span><span style="color: #575279"> </span><span style="color: #286983">=</span><span style="color: #575279"> </span><span style="color: #D7827E">True</span><span style="color: #797593">)</span></span>
<span class="line"><span style="color: #575279">sigma </span><span style="color: #286983">=</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">tensor</span><span style="color: #797593">(</span><span style="color: #D7827E">1.0</span><span style="color: #797593">,</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">requires_grad</span><span style="color: #575279"> </span><span style="color: #286983">=</span><span style="color: #575279"> </span><span style="color: #D7827E">True</span><span style="color: #797593">)</span></span>为了方便,你可能不想自己实现SGD来优化这俩参数了,你会选择使用torch内置的优化器来优化这俩参数:
<span class="line"><span style="color: #575279">optimizer </span><span style="color: #286983">=</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">optim</span><span style="color: #797593">.</span><span style="color: #575279">SGD</span><span style="color: #797593">([</span><span style="color: #575279">mu</span><span style="color: #797593">,</span><span style="color: #575279"> sigma</span><span style="color: #797593">],</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">lr</span><span style="color: #286983">=</span><span style="color: #D7827E">2e-2</span><span style="color: #797593">)</span></span>lr是学习率,设定的小一点会好点。pytoch内置的大多数常用的分布函数,任君挑选:
<span class="line"><span style="color: #575279">q </span><span style="color: #286983">=</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">distributions</span><span style="color: #797593">.</span><span style="color: #575279">Normal</span><span style="color: #797593">(</span><span style="color: #907AA9; font-style: italic">loc</span><span style="color: #286983">=</span><span style="color: #575279">mu</span><span style="color: #797593">,</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">scale</span><span style="color: #286983">=</span><span style="color: #575279">sigma</span><span style="color: #797593">)</span></span>这样就相当于定义了一个均值为1,标准差为1的正态分布$q(x)$,你的目标是通过使用最大似然估计来得到$\mu, \sigma$先写个似然函数:
<span class="line"><span style="color: #575279">negative_log_likelihood </span><span style="color: #286983">=</span><span style="color: #575279"> </span><span style="color: #286983">-</span><span style="color: #D7827E">1</span><span style="color: #575279"> </span><span style="color: #286983">*</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">sum</span><span style="color: #797593">(</span><span style="color: #575279">q</span><span style="color: #797593">.</span><span style="color: #575279">log_prob</span><span style="color: #797593">(</span><span style="color: #575279">x_batch</span><span style="color: #797593">))</span></span>pytorch并没有提供prob方法返回概率,反正你也不会用概率相乘,都是概率的对数相加,于是对log_prob求和就可以了。接下来计算$\mu, \sigma$的梯度
<span class="line"><span style="color: #575279">negative_log_likelihood</span><span style="color: #797593">.</span><span style="color: #575279">backward</span><span style="color: #797593">()</span></span>
<span class="line"><span style="color: #575279">optimizer</span><span style="color: #797593">.</span><span style="color: #575279">step</span><span style="color: #797593">()</span></span>顺便调用一下optimizer.step()方法来更新一下$\mu, \sigma$,执行多次之后,就能得到目标了。
至于,偷偷生成数据的过程,其实是用均值为-4,方差为2的正态分布生成了1000个样本。
于是经过上述的学习过程,$\mu, \sigma$会在-4,2前后徘徊,因为毕竟是取样的数据,与真实分布还是有差距的~
完整代码:
<span class="line"><span style="color: #286983">import</span><span style="color: #575279"> numpy </span><span style="color: #286983">as</span><span style="color: #575279"> np</span></span>
<span class="line"><span style="color: #286983">from</span><span style="color: #575279"> scipy</span><span style="color: #797593">.</span><span style="color: #575279">stats </span><span style="color: #286983">import</span><span style="color: #575279"> norm</span></span>
<span class="line"><span style="color: #286983">import</span><span style="color: #575279"> torch</span></span>
<span class="line"><span style="color: #286983">import</span><span style="color: #575279"> matplotlib</span><span style="color: #797593">.</span><span style="color: #575279">pyplot </span><span style="color: #286983">as</span><span style="color: #575279"> plt</span></span>
<span class="line"><span style="color: #797593; font-style: italic">#</span><span style="color: #9893A5; font-style: italic"> 生成数据</span></span>
<span class="line"><span style="color: #575279">x </span><span style="color: #286983">=</span><span style="color: #575279"> np</span><span style="color: #797593">.</span><span style="color: #575279">random</span><span style="color: #797593">.</span><span style="color: #575279">normal</span><span style="color: #797593">(</span><span style="color: #907AA9; font-style: italic">loc</span><span style="color: #575279"> </span><span style="color: #286983">=</span><span style="color: #575279"> </span><span style="color: #286983">-</span><span style="color: #D7827E">4</span><span style="color: #797593">,</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">scale</span><span style="color: #575279"> </span><span style="color: #286983">=</span><span style="color: #575279"> </span><span style="color: #D7827E">2</span><span style="color: #797593">,</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">size</span><span style="color: #575279"> </span><span style="color: #286983">=</span><span style="color: #575279"> </span><span style="color: #D7827E">1000</span><span style="color: #797593">)</span></span>
<span class="line"><span style="color: #575279">plt</span><span style="color: #797593">.</span><span style="color: #575279">hist</span><span style="color: #797593">(</span><span style="color: #575279">x</span><span style="color: #797593">,</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">bins</span><span style="color: #286983">=</span><span style="color: #D7827E">20</span><span style="color: #797593">)</span></span>
<span class="line"><span style="color: #575279">x </span><span style="color: #286983">=</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">tensor</span><span style="color: #797593">(</span><span style="color: #575279">x</span><span style="color: #797593">)</span></span>
<span class="line"><span style="color: #797593; font-style: italic">#</span><span style="color: #9893A5; font-style: italic"> MLE</span></span>
<span class="line"><span style="color: #575279">mu </span><span style="color: #286983">=</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">tensor</span><span style="color: #797593">(</span><span style="color: #D7827E">1.0</span><span style="color: #797593">,</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">requires_grad</span><span style="color: #575279"> </span><span style="color: #286983">=</span><span style="color: #575279"> </span><span style="color: #D7827E">True</span><span style="color: #797593">)</span></span>
<span class="line"><span style="color: #575279">sigma </span><span style="color: #286983">=</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">tensor</span><span style="color: #797593">(</span><span style="color: #D7827E">1.0</span><span style="color: #797593">,</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">requires_grad</span><span style="color: #575279"> </span><span style="color: #286983">=</span><span style="color: #575279"> </span><span style="color: #D7827E">True</span><span style="color: #797593">)</span></span>
<span class="line"><span style="color: #575279">optimizer </span><span style="color: #286983">=</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">optim</span><span style="color: #797593">.</span><span style="color: #575279">SGD</span><span style="color: #797593">([</span><span style="color: #575279">mu</span><span style="color: #797593">,</span><span style="color: #575279"> sigma</span><span style="color: #797593">],</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">lr</span><span style="color: #286983">=</span><span style="color: #D7827E">2e-2</span><span style="color: #797593">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #797593; font-style: italic">#</span><span style="color: #9893A5; font-style: italic"> SGD</span></span>
<span class="line"><span style="color: #575279">idx </span><span style="color: #286983">=</span><span style="color: #575279"> </span><span style="color: #56949F">list</span><span style="color: #797593">(</span><span style="color: #B4637A; font-style: italic">range</span><span style="color: #797593">(</span><span style="color: #B4637A; font-style: italic">len</span><span style="color: #797593">(</span><span style="color: #575279">x</span><span style="color: #797593">)))</span></span>
<span class="line"><span style="color: #286983">for</span><span style="color: #575279"> epoch </span><span style="color: #286983">in</span><span style="color: #575279"> </span><span style="color: #B4637A; font-style: italic">range</span><span style="color: #797593">(</span><span style="color: #D7827E">2</span><span style="color: #797593">):</span></span>
<span class="line"><span style="color: #575279"> np</span><span style="color: #797593">.</span><span style="color: #575279">random</span><span style="color: #797593">.</span><span style="color: #575279">shuffle</span><span style="color: #797593">(</span><span style="color: #575279">idx</span><span style="color: #797593">)</span></span>
<span class="line"><span style="color: #575279"> </span><span style="color: #286983">for</span><span style="color: #575279"> i </span><span style="color: #286983">in</span><span style="color: #575279"> </span><span style="color: #B4637A; font-style: italic">range</span><span style="color: #797593">(</span><span style="color: #D7827E">0</span><span style="color: #797593">,</span><span style="color: #B4637A; font-style: italic">len</span><span style="color: #797593">(</span><span style="color: #575279">idx</span><span style="color: #797593">),</span><span style="color: #D7827E">10</span><span style="color: #797593">):</span></span>
<span class="line"><span style="color: #575279"> x_batch </span><span style="color: #286983">=</span><span style="color: #575279"> x</span><span style="color: #797593">[</span><span style="color: #575279">idx</span><span style="color: #797593">[</span><span style="color: #575279">i</span><span style="color: #797593">:</span><span style="color: #575279">i</span><span style="color: #286983">+</span><span style="color: #D7827E">10</span><span style="color: #797593">]]</span></span>
<span class="line"><span style="color: #575279"> optimizer</span><span style="color: #797593">.</span><span style="color: #575279">zero_grad</span><span style="color: #797593">()</span></span>
<span class="line"><span style="color: #575279"> q </span><span style="color: #286983">=</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">distributions</span><span style="color: #797593">.</span><span style="color: #575279">Normal</span><span style="color: #797593">(</span><span style="color: #907AA9; font-style: italic">loc</span><span style="color: #286983">=</span><span style="color: #575279">mu</span><span style="color: #797593">,</span><span style="color: #575279"> </span><span style="color: #907AA9; font-style: italic">scale</span><span style="color: #286983">=</span><span style="color: #575279">sigma</span><span style="color: #797593">)</span></span>
<span class="line"><span style="color: #575279"> negative_log_likelihood </span><span style="color: #286983">=</span><span style="color: #575279"> </span><span style="color: #286983">-</span><span style="color: #D7827E">1</span><span style="color: #575279"> </span><span style="color: #286983">*</span><span style="color: #575279"> torch</span><span style="color: #797593">.</span><span style="color: #575279">sum</span><span style="color: #797593">(</span><span style="color: #575279">q</span><span style="color: #797593">.</span><span style="color: #575279">log_prob</span><span style="color: #797593">(</span><span style="color: #575279">x_batch</span><span style="color: #797593">))</span></span>
<span class="line"><span style="color: #575279"> negative_log_likelihood</span><span style="color: #797593">.</span><span style="color: #575279">backward</span><span style="color: #797593">()</span></span>
<span class="line"><span style="color: #575279"> optimizer</span><span style="color: #797593">.</span><span style="color: #575279">step</span><span style="color: #797593">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #B4637A; font-style: italic">print</span><span style="color: #797593">(</span><span style="color: #EA9D34">"</span><span style="color: #286983">{}</span><span style="color: #EA9D34">,</span><span style="color: #286983">{}</span><span style="color: #EA9D34">"</span><span style="color: #797593">.</span><span style="color: #575279">format</span><span style="color: #797593">(</span><span style="color: #575279">mu</span><span style="color: #797593">.</span><span style="color: #575279">detach</span><span style="color: #797593">(),</span><span style="color: #575279"> sigma</span><span style="color: #797593">.</span><span style="color: #575279">detach</span><span style="color: #797593">()))</span></span>