<?xml version="1.0" encoding="utf-8"?>
<search> 
  
  
    
    <entry>
      <title>Δ系统 (Δ-system) 引理</title>
      <link href="/math/set_theory/delta_system_lemma/"/>
      <url>/math/set_theory/delta_system_lemma/</url>
      
        <content type="html"><![CDATA[<h1 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h1><p>介绍了 $\Delta\text{-system}$ 这种特殊的集簇, 以及 $\Delta\text{-system lemma}$ 的证明.</p><h1 id="简单介绍"><a href="#简单介绍" class="headerlink" title="简单介绍"></a>简单介绍</h1><p>如果一个集簇 $\mathscr{A}$ 满足 $\forall x,y\in \mathscr{A}(x\cap y=r)$ , $r$ 是某个确定的集合, 那么这个集簇就叫做 $\Delta\text{-system}$ , $r$ 叫做这个 $\Delta\text{-system}$ 的根.</p><h1 id=""><a href="#" class="headerlink" title=""></a>$\Delta\text{-system lemma}$</h1><p>令 $\kappa$ 是某个不可数基数, 若正则基数 $\theta>\kappa$ 且满足 $\forall \alpha<\theta(|\alpha^{<\kappa}|<\theta)$ , 那么对某个集簇 $\mathscr{A}$ 若其满足 $|\mathscr{A}|\geqslant\theta$ 并且 $\forall x\in\mathscr{A}(|x|<\kappa)$ , 那么就存在子集 $\mathscr{B}\sub\mathscr{A}$ , $|\mathscr{B}|=\theta$ 且 $\mathscr{B}$ 是 $\Delta\text{-system}$ .</p><h2 id="证明"><a href="#证明" class="headerlink" title="证明"></a>证明</h2><p>事实上, 我们可以假设 $|\mathscr{A}|=\theta$ , 那么根据题设有 $\bigcup{\mathscr{A}}\leqslant\theta$ . 而由于 $\mathscr{A}$ 中的元素具体是什么与这个结论成立与否没有关系, 那么我们就可以假设 $\bigcup{\mathscr{A}}\subset\theta$ . 那么我们就得知 $\forall x\in \mathscr{A}(\exist\rho<\theta, \rho\cong x)$ , 即每个 $x$ 都有其对应的序. 又由于 $\theta$ 的正则性并且 $\theta>\kappa$ , 因此存在序数 $\rho<\theta$ 使得 $|\{x\in\mathscr{A}\mid x\cong \rho\}|=\theta$ , 否则有 $\forall \rho <\theta, \sup\{x\in\mathscr{A}\mid x\cong \rho\}<\theta$ , 然而又有 $\bigcup_\rho\{x\in\mathscr{A}\mid x\cong \rho\}=\mathscr{A}$ , 这意味着 $\{\sup\{x\in\mathscr{A}\mid x\cong \rho\}\}$ 与 $\theta$ 共尾, 违背了 $\theta$ 的正则性. 那么取这样的一个序数 $\rho$ , 令 $\mathscr{A_1}=\{x\in\mathscr{A}\mid x\cong \rho\}$ , 现在我们只对 $\mathscr{A}_1$ 做研究.</p><p>从 $\forall \alpha<\theta(|\alpha^{<\kappa}|<\theta)$ 中我们可以得知, $\mathscr{A}_1$ 中的元素是 $\alpha$ 的子集的数量少于 $\theta$ , 这是因为 $(\mathscr{P}(\alpha)\cap \mathscr{A})\subset\alpha ^{<\kappa}<\theta$. 这意味着 $\bigcup \mathscr{A}_1$ 和 $\theta$ 共尾. 取 $x\in\mathscr{A}_1$ , 令 $x(\xi)$ 为 $x$ 的第 $\xi$ 个元素, 显然存在一些 $\xi$ 使得 $\{x(\xi)\mid x\in \mathscr{A}\}$ 和 $\theta$ 共尾 (由 $\theta$ 的正则性可得) . 取 $\xi_0$ 为 最小的这样的 $\xi$​ . 令</p>$$\alpha_0=\sup\{x(\eta)+1\mid x\in \mathscr{A}\wedge\eta<\xi_0\}$$<p>这样就有 $\alpha_0<\theta$ 且对于任意的 $x\in\mathscr{A},\eta<\xi_0$ 有 $x(\eta)<\alpha_0$ . 对 $\mu<\theta$ 做递归, 令 $x_{\mu}\in\mathscr{A}$ 满足<br>$$x_{\mu}(\xi_0)>\max(\alpha_0,\sup\{x_\nu(\eta)\mid \nu<\mu,\eta<\xi_0\})$$<br>令 $\mathscr{A}_2=\{x_{\mu}\mid \mu<\theta\}$ , 容易验证 $\forall x,y\in\mathscr{A}, x\not=y((x\cap y)\subset\alpha_0)$ , 而 $|\alpha_0^{<\kappa}|<\theta$ , $|x\cap y|<\kappa$ , 这意味着 $\alpha_0$ 的所有小于 $\kappa$ 大小的子集的数量小于 $\theta$, 也就是说存在 $r\subset\alpha_0,\mathscr{B}\subset\mathscr{A}_0$ , 使得 $\mathscr{B}$ 是一个 $\Delta\text{-system}$ 且满足 $|\mathscr{B}|=\theta, \forall x,y\in\mathscr{B}(x\cap y=r)$​ .</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 集合论 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 集合论 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>基数乘法的不变性</title>
      <link href="/math/set_theory/cardinality_multiplication/"/>
      <url>/math/set_theory/cardinality_multiplication/</url>
      
        <content type="html"><![CDATA[<h1 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h1><p>本文主要证明了当基数 $\kappa\geqslant\omega$ , 那么有 $\kappa \oplus \kappa=\kappa, \kappa \otimes \kappa=\kappa$​ .</p><h1 id="简单介绍"><a href="#简单介绍" class="headerlink" title="简单介绍"></a>简单介绍</h1><p>这是一个重要的集合论定理, 无论是基数的幂 ($\alpha^\alpha$) 还是不可数集的不可数交, 都可以用这个定理导出.</p><h1 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h1><p>基数乘法和加法:</p>$\kappa\oplus\gamma=|\kappa\times\{0\}\cup\gamma\times\{1\}|$ ,$\kappa\otimes\gamma=|\kappa\times\gamma|$​# 证明我们可以先证明基数加法, 即 $\kappa\geqslant\omega$,  $\kappa\oplus\kappa=\kappa$ . 我们将使用超限归纳法. 命题等价于对于任意序数 $\alpha$ 都有 $|\alpha|\oplus|\alpha|=|\alpha|$ 对于某个序数 $\alpha\geqslant\omega$ , 若任意 $\beta<\alpha$ 都有 $|\beta|\oplus|\beta|=|\beta|$ , 那么分两种情况讨论. 假设 $\alpha$ 不是基数, 那么由于 $|\alpha|<\alpha$, 显然有 $|\alpha|\oplus|\alpha|=|\alpha|$ . 如果 $\alpha$ 是基数, 那么 $\alpha$ 一定是极限序数, 那么有 $\alpha=\sup\{\beta\mid \beta<\alpha\}$ , 根据基数加法的定义, 还有$$|\alpha|\oplus|\alpha|=\alpha\oplus\alpha=\left|\sup\{\beta\times\{0\}\cup\beta\times\{1\}\mid\beta<\alpha\}\right|$$<p>而我们又得知对任意 $\beta<\alpha$, 都有 $\beta\times\{0\}\cup\beta\times\{1\}<\alpha$ (根据基数加法的定义), 这意味着 $\sup\{\beta\times\{0\}\cup\beta\times\{1\}\mid\beta<\alpha\}\leqslant\alpha$ , 即 $\left|\sup\{\beta\times\{0\}\cup\beta\times\{1\}\mid\beta<\alpha\}\right|\leqslant\alpha$ 但是又有 $\alpha\oplus\alpha\geqslant\alpha$ , 根据势的三歧性, 则有 $\alpha\oplus\alpha=\alpha$ , 即 $|\alpha|\oplus|\alpha|=|\alpha|$ . 根据超限归纳法知命题成立.$\quad\blacksquare$​</p><p>而乘法的证明是类似的, 利用超限归纳法, 下面只证明当 $\alpha$ 是基数的情况. 根据定义, 有<br>$$|\alpha|\otimes|\alpha|=\alpha\otimes\alpha=\left|\sup\{\beta\times\beta\mid\beta<\alpha\}\right|$$<br>那么就有</p>$$|\alpha|\otimes|\alpha|=\left|\sup\{\beta\times\beta\mid\beta<\alpha\}\right|\leqslant\sup\{\beta\times\beta\mid\beta<\alpha\}\leqslant\alpha=|\alpha|$$<p>$\blacksquare$​</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 集合论 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 集合论 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>序数的唯一性</title>
      <link href="/math/set_theory/unique_ordinal/"/>
      <url>/math/set_theory/unique_ordinal/</url>
      
        <content type="html"><![CDATA[<h1 id="主要内容"><a href="#主要内容" class="headerlink" title="主要内容"></a>主要内容</h1><p>本文主要证明了序数的唯一性, 即若序数 $O_1 \cong O_2$ , 则有 $O_1=O_2$ ,  $\cong$ 是同构的意思.</p><h1 id="简单介绍"><a href="#简单介绍" class="headerlink" title="简单介绍"></a>简单介绍</h1><p>序数是指一类集合, 满足:</p><ul><li>可传递性, 即其元素也是其子集.</li><li>通过 $\in$ 关系构成良序集.</li></ul><h1 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h1><p>定义 $0=\{\}$ , 即 $0$ 是空集.</p><h1 id="证明"><a href="#证明" class="headerlink" title="证明"></a>证明</h1><p><strong>引理 1.</strong> 对于某个序数 $O\not=0$, 一定有 $0\in O$. </p><p><strong>证明:</strong> 任取 $x\in O$, 若 $x\not=0$ , 则取 $x'$ 为 $x\cap O$ 的最小元, 易得 $x'=0$ , 否则可取 $x''\in x'$ , 即可得出 $x''\in x\cap O$ , 与 $x'$ 为最小元矛盾.$\quad\blacksquare$</p><p><strong>引理 2.</strong> 记 $f\colon A\to B$ 为 $O_1$ 与 $O_2$ 之间保持结构的双射,  有 $f(0)=0$.</p><p><strong>证明:</strong> 设 $f(0)=x\in O_2$, 若 $x\not=0$, 则有 $0\in O_2$ , 这说明 $f^{-1}(0)\in0$ , 这是不可能的.$\quad\blacksquare$</p><p><strong>引理 3.</strong> 若 $x_1\in O_1$, 且有 $\forall x\in x_1, f(x)=x$ , 则有 $f(x_1)=x_1$.</p><p><strong>证明:</strong> 不妨设 $f(x_1)=x_2\in O_2$ , 则有 $x_2=\{f(x)\mid \forall x\in x_1\}=\{x\mid \forall x\in x_1\}=x_1$ (这很容易证明, 用反证法即可) , 即 $f(x_1)=x_1$.$\quad\blacksquare$</p><p>现在来证明整个命题: </p><p>取集合 $C=\{x\mid f(x)\not=x\}\in O_1$ , 若其不是空集, 则存在最小元 $x'$, 满足 $\forall x\in x', f(x)=x$ , 但由引理 3可得 $f(x')=x'$ , 这就产生了矛盾即 $x'\not\in C$ , 这也就说明 $C$ 为空集. $\quad\blacksquare$</p><p>由上讨论可知不仅序数是唯一的, 他们之间的同构映射也是唯一的.</p><h1 id="题外话"><a href="#题外话" class="headerlink" title="题外话"></a>题外话</h1><p>证明超穷归纳法也可以用类似的证明方法.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 集合论 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 集合论 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 3.1</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/3/3-1/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/3/3-1/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1>$$f'(0)=\lim_{x\to 0}\frac{f(x)-f(0)}{x-0}=\lim_{x\to0}\frac{f(x)}{x}$$<h2 id="2"><a href="#2" class="headerlink" title="2"></a>2</h2>$\frac{f(b_n)-f(a_n)}{b_n-a_n}$ 必然夹在 $\frac{f(b_n)-f(0)}{b_n-0}$ 与 $\frac{f(a_n)-f(0)}{a_n-0}$ 之间由夹逼定理可知,$$\lim_{n\to\infty}\frac{f(b_n)-f(a_n)}{b_n-a_n}=f'(0)$$<h2 id="7"><a href="#7" class="headerlink" title="7"></a>7</h2>$$\begin{aligned}&\lim_{n\to\infty}\left(\frac{f(a+1/n)}{f(a)}\right)\\=&1+\lim_{n\to\infty}\left(\frac{f(a+1/n)-f(a)}{f(a)}\right)\\=&1+\lim_{n\to\infty}\left(\frac{f(a+1/n)-f(a)}{1/n}\right)\lim_{n\to\infty}\left(\frac{1/n}{f(a)}\right)\\=&1+f'(a)\cdot0\\=&1\end{aligned}$$<h2 id="8"><a href="#8" class="headerlink" title="8"></a>8</h2><p>根据定义有<br>$$f'(a)=\lim_{x\to a}\frac{(x-a)\varphi(x)}{x-a}=\varphi(a)$$</p>$$g'(a)=\lim_{x\to a}\frac{|x-a|\varphi(x)}{x-a}=\varphi(a)=-\varphi(a)$$<p>这说明至少 $\varphi(a)=0$ .同时若 $\varphi(a)=0$ , 那么带入上面的式子有<br>$$g'(a)=0$$</p><h2 id="9"><a href="#9" class="headerlink" title="9"></a>9</h2><p>根据定义<br>$$f'(0)=\lim_{x\to0}\frac{x^\lambda\sin\frac{1}{x}}{x}=\lim_{x\to0}x^{\lambda-1}\sin\frac{1}{x}$$<br>我们已知当 $\lambda>0$ 时 $\lim_{x\to0}x^\lambda=0$ , $\lambda<0$ 时 $\lim_{x\to0}x^\lambda=\infty$ . 这就证明了命题.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.11</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-11/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-11/</url>
      
        <content type="html"><![CDATA[<h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>这说明存在 ${x^*}_n\to {x_0}^-,x_{*n}\to {x_0}^-$ , 使得 $f({x^*}_n)\to\mathop{\lim\sup}_{x\to {x_0}^-}f(x), f({x_*}_n)\to\mathop{\lim\inf}_{x\to {x_0}^-}f(x)$ . 根据介值定理在 $n<N$ 时取 $x_n=\alpha$ 即可. $N$ 是一个足够大的整数.</p><h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><h2 id="1"><a href="#1" class="headerlink" title="(1)"></a>(1)</h2><p>显然的.</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>根据 $\sup$ 的定义, 对于任意 $\epsilon>0$ 都有 $x\in A$ 使得 $\sup A\geqslant x>\sup A-\epsilon$ , 这说明我们可以在 $A=\{f(x)\colon 0<|x-x_0|<\frac{1}{n}\}$ 中找到 $\sup A\geqslant f(x_n)>\sup A-\frac{1}{n}$ , 显然 $f(x_n)\to\lim_{\delta\to 0^+}\varphi(\delta)$ . 因此 $\lim_{\delta\to 0^+}\varphi(\delta)=\mathop{\lim\inf}_{x\to x_0}f(x)$ . $\inf$ 同理. </p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.10</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-10/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-10/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><p>假设是无界的, 那么由本节前面内容可推出 $\lim_{x\to a}f(x)=\infty$ 或 $\lim_{x\to b}f(x)=\infty$ . 由一致连续的定义可推出矛盾.</p><h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>如果是有限区间, 有<br>$$f(a) + g(a)=\lim_{x\to a}f(x)+\lim_{x\to a}g(x)=\lim_{x\to a}f(x)+g(x)$$<br>说明 $f(a)+g(a)$ 是连续的. 如果是开区间只需补充两边定义即可成为闭区间, 而由该节内容可知闭区间中的连续函数必然一致连续.</p><p>如果是无穷区间, 就不一定成立, 比如 $f(x)=g(x)=x$ .</p><h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><p>补充定义, 然后和上一题有限区间情况类似.</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><p>由题目可得, 对于任意的 $\epsilon/4>0$ 存在 $b>0$ , 使得当 $x\geqslant b$ 时, 有 $|f(x)-f(+\infty)|<\epsilon/4$ . 由此可得当 $x_1, x_2>b$ 时, 有</p>$|f(x_1)-f(x_2)|<\epsilon/2$ . 选取区间 $[a, b]$ , 显然 $f$ 在 $[a,b]$ 上一致连续.因此对于任意 $\epsilon>0$ , 若 $x_1, x_2>b$ , 那么 $\delta$ 取多大都可以, 若 $x_1,x_2\in[a,b]$ , 由于本来就是一致连续, 对应的 $\delta$ 自然也存在. 对于 $x_1\in[a,b], x_2>b$ 的情况. 只需取 $\delta$ 满足 $\forall x, x'\in[a,b], |x-x'|<\delta, [f(x)-f(x')]<\epsilon/2$ 即可, 因为$$|f(x_1)-f(x_2)|\leqslant|f(x_1)-b|+|f(x_2)-b|<\epsilon$$<h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1><p>一致连续加减一致连续还是一致连续. </p><h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p><del>求根公式</del></p><p>显然该函数单调递增, 因此可以肯定 $(0, 1)$ 中必有一根.</p><h1 id="7"><a href="#7" class="headerlink" title="7"></a>7</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="(1)"></a>(1)</h2>$$\lim_{x\to+\infty}x^n+\varphi(x)=\lim_{x\to+\infty}x^n(1+\frac{\varphi(x)}{x^n})=+\infty$$<p>同理得<br>$$\lim_{x\to-\infty}x^n+\varphi(x)=-\infty$$</p><p>由零点定理可得必有一实根.</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>与 $(1)$ 类似, 我们有<br>$$\lim_{x\to\infty}x^n+\varphi(x)=+\infty$$<br>取 $f(x)=x^n+\varphi(x)$</p><p>因此对于存在 $A>0$ , 使得存在 $x_0$ 使得 $f(x_0)<A$ , 由介值定理可得存在 $x_1>0$ , 使得 $f(x_1)=A$ . 且存在 $x_2>0$ 使得当 $|x|\geqslant x_2$ 时, 有 $f(x)>A$ . 取闭区间 $[-x_2, x_2]$ , 该闭区间是有限区间, 且函数在该闭区间连续, 因此在此区间的函数的值域必然存在下界, 且该下界必然存在于值域中, 我们称为 $f(x_{*})$ . 显然 $x_1\in[-x_2, x_2]$ , 因此我们有 $f(x_*)\leqslant f(x_1)=A$ , 这表明 $y=x_*$ 是符合题意的.</p><h1 id="8"><a href="#8" class="headerlink" title="8"></a>8</h1><p>令函数 $g_n(x)=f(x)-f(x+\frac{1}{n})$ . 那么有 $g_n(0)=f(0)-f(\frac{1}{n})$ , $g_n(1-\frac{1}{n})=f(1-\frac{1}{n})-f(1)$ . </p><p>假设 $f(\frac{1}{n})>f(0), f(1-\frac{1}{n})>f(1)$ , 那么问题结束 (小于的情况类似, 不做讨论) . 如果不是这样, 假设 $f(\frac{1}{n})<f(0)$ , 那么 $f(\frac{1}{n})<f(1)<f(1-\frac{1}{n})$ 由于介值定理存在 $x\in(0+\frac{1}{n},1-\frac{1}{n})$ , 使得 $f(x)=f(1)$ . 取最大的那个 $x$ 称为 $x_1$ , 显然 $g_n(x_1)<0$ 成立. 否则有 $f(x_2)=f(1), x_{2}>x_1$ 的存在, 与 $x_1$ 的最大性矛盾.</p><h1 id="9"><a href="#9" class="headerlink" title="9"></a>9</h1><p>等价于 $f(x)=a$ 有至少两个解. $f(a)-a<0$ , 这说明在 $(-\infty,a)$ 与 $(a,+\infty)$ 之中各有至少一个解.</p><h1 id="10"><a href="#10" class="headerlink" title="10"></a>10</h1><p>记 $g(x)=x+f(x)$ , 显然这导致 $g(x)$ 的值域为无理数. 而若 $g(x)$ 是连续的,     那么根据介值定理以及有理数的稠密性, 必然存在 $x_0$ 使得 $g(x_0)$ 为有理数 ($g(x)$ 不可能为常值函数), 这说明 $g(x)$ 不是连续的, 同样, $f(x)$ 也不会是连续的.</p><h1 id="11"><a href="#11" class="headerlink" title="11"></a>11</h1><h2 id="1-2"><a href="#1-2" class="headerlink" title="(1)"></a>(1)</h2>$$kx-f(x)-(ky-f(y))=k(x-y)-(f(x)-f(y))\geqslant0$$<h2 id="2-2"><a href="#2-2" class="headerlink" title="(2)"></a>(2)</h2><p>令 $g(x) = (1-k)x+kx-f(x)$ . 显然 $g(x)$ 递增, 且有<br>$$\lim_{x\to-\infty}g(x)=-\infty,\lim_{x\to+\infty}g(x)=+\infty$$</p><h1 id="12"><a href="#12" class="headerlink" title="12"></a>12</h1><p>假设周期为 $T$ , 任取 $x_0\in\mathbb{R}$ , 显然函数在闭区间 $[x_0, x_0+T]$ 是一致连续的. 自然在其他的区间内也是一致连续的.</p><p>由于一致连续的函数加减并不影响一致连续的性质, 即只需证明 $\sin(x^2)$ 不是一致连续的即可, 这是容易证明的.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.9</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-9/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-9/</url>
      
        <content type="html"><![CDATA[<h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><p>由一致连续的定义知, 对于 $\epsilon>0$ , 存在 $\delta>0$ , 使得 $|f(x)-f(x\pm\delta)|<\epsilon$ . 任取 $x_0\in (a, b)$ , 有 $|f(x)-f(b-\epsilon_0)|<\epsilon([(b-x)/\delta]+1)$ , 其中 $[]$ 是取整函数. 这意味着 $f(b-\epsilon_0)$ 有限, 即 $b$ 的左邻域有限, 自然 $f(b-)$ 存在且有限.</p><p>$f(a+)$ 同理.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.8</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-8/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-8/</url>
      
        <content type="html"><![CDATA[<h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><h2 id="1"><a href="#1" class="headerlink" title="(1)"></a>(1)</h2><p>等价于<br>$$\begin{aligned}&\lim_{x\to1}\frac{x^n-1}{x^m-1}\\=&\lim_{t\to0}\frac{(t+1)^n-1}{(t+1)^m-1}\\=&\lim_{t\to0}\frac{t^n+nt+o(t)}{t^m+mt+o(t)}\\=&\lim_{t\to0}\frac{t^{n-1}+n+o(1)}{t^{m-1}+m+o(1)}\\=&\frac{n}{m}\end{aligned}$$</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>令 $1+\alpha x=t^m$ 可得<br>$$\lim_{t\to 1}\frac{\alpha(t-1)}{t^m-1}=\frac{\alpha}{m}$$</p><h2 id="3"><a href="#3" class="headerlink" title="(3)"></a>(3)</h2>$$\lim_{x\to0}\frac{\sqrt[m]{1+\alpha x}-\sqrt[n]{1+\beta x}}{x}=\lim_{x\to0}\frac{\sqrt[m]{1+\alpha x}-1}{x}-\lim_{x\to0}\frac{\sqrt[n]{1+\beta x}-1}{x}=\frac{\alpha}{m}-\frac{\beta}{n}$$<h2 id="4"><a href="#4" class="headerlink" title="(4)"></a>(4)</h2><p>原式等价于</p>$$\prod_{i=1}^{n}\lim_{x\to1}\frac{1-\sqrt[i]{x}}{1-x}=\prod_{i=1}^n\frac{1}{i}=\frac{1}{n!}$$<h1 id="3-1"><a href="#3-1" class="headerlink" title="3"></a>3</h1><h2 id="7"><a href="#7" class="headerlink" title="(7)"></a>(7)</h2><p>在我手上这个版本中是 $x\to+\infty$ , 实际上应该是 $n\to+\infty$​.</p>$$\lim_{n\to\infty}n\left(\cos\left(\frac{x}{\sqrt{n}}\right)-1\right)$$<p>等价于<br>$$\lim_{t\to0}x^2\frac{\cos(t)-1}{t^2}$$</p><p>由于 $\cos(t)-1\sim-\frac{1}{2}t^2$ , 结果为 $\frac{-x^2}{2}$ .</p><h1 id="4-1"><a href="#4-1" class="headerlink" title="4"></a>4</h1>$$\lim_{n\to\infty}n\frac{\sum_{i=1}^nx^i}{n}=\lim_{n\to\infty}\sum_{i=1}^nx^i=\lim_{n\to\infty}\frac{x-x^{n+1}}{1-x}=\frac{x}{1-x}$$]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.7</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-7/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-7/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="(1)"></a>(1)</h2><p>不能, 在 $0$ 处 $f$ 极限不存在.</p><h2 id="2"><a href="#2" class="headerlink" title="(2)"></a>(2)</h2>$x=0$ 处无定义, 但是在 $x=0$ 处有可去间断点, 因此如果补充定义, 那么该函数的定义域就是 $\mathbb{R}$ .## (3)是. 这等价于连续的定义.## (4)不能. $x_0$ 处不一定有定义, 且 $f(x_0)$ 的值无法从给定的公式计算 (也就是无关) .## (5)由题意知$$f(x_0)=\lim_{x\to x_0}f(x)=0$$<h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><h2 id="1-2"><a href="#1-2" class="headerlink" title="(1)"></a>(1)</h2><p>不连续.</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>不一定.</p><h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1><p> 这说明</p>$$f(x_0)=\lim_{x\to x_0}f(x)$$<p>即<br>$$|f(x)-f(x_0)|<\epsilon$$</p><p>易得.</p><h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p>不成立.</p><h1 id="7"><a href="#7" class="headerlink" title="7"></a>7</h1>$$\max(f(x), g(x))=\frac{f(x)+g(x)}{2}+\frac{|f(x)-g(x)|}{2}$$<p>显然是连续函数.</p> $\min$ 函数同理.# 9$$\lim_{x\to {x_0}^+}F(x)=\lim_{x\to{x_0}^+}f(x+)=\lim_{x\to{x_0}^+}f(x)=f(x+)=F(x)$$<h1 id="10"><a href="#10" class="headerlink" title="10"></a>10</h1><p>显然有 $f(nx)=nf(x)$ . 其中 $n$ 为整数. 对于 $x_0$ , 我们考虑如下数列:</p>$x_i=\frac{1}{10^i}$ , $|x-n_ix_i|<\frac{1}{10^i}$ . 很显然这样的 $n_i$ 是可以取到的.而又有 $f(n_ix_i)=n_if(x_i)=n_if(\frac{1}{10^i})=\frac{n_i}{10^i}f(1)=n_ix_if(1)$<p>那么只需令 $i\to\infty$ , 我们可以得到 $n_ix_i\to x_0$ , 由连续性得 $f(x_0)=x_0f(1)$ .</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.6</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-6/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-6/</url>
      
        <content type="html"><![CDATA[<h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><h2 id="1"><a href="#1" class="headerlink" title="(1)"></a>(1)</h2><p>由极限的加法可得.</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>由极限的乘法可得.</p><h2 id="3"><a href="#3" class="headerlink" title="(3)"></a>(3)</h2><p>由极限的乘法可得.</p><h2 id="4"><a href="#4" class="headerlink" title="(4)"></a>(4)</h2><p>只需证明</p>$$\frac{1}{1+\alpha}+\alpha-1=o(\alpha)$$<p>这等价于<br>$$\lim_{x\to x_0}\frac{\alpha}{1+\alpha}=0$$</p><p>这是显然的.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python 小技巧</title>
      <link href="/python/numpy/python_skill/"/>
      <url>/python/numpy/python_skill/</url>
      
        <content type="html"><![CDATA[<h1 id="将两个一维-array-所有的组合排列出"><a href="#将两个一维-array-所有的组合排列出" class="headerlink" title="将两个一维 array 所有的组合排列出"></a>将两个一维 array 所有的组合排列出</h1><p>你有两个一维数组: <code>array1</code>, <code>array2</code> . 现在需要将它们的所有元素的组合排列出 (组合成二维数组).</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">np.array(np.meshgrid(array1, array2).T.reshape(-<span class="number">1</span>, <span class="number">2</span>)</span><br></pre></td></tr></table></figure><h1 id="求出二维数组中最大值位置"><a href="#求出二维数组中最大值位置" class="headerlink" title="求出二维数组中最大值位置"></a>求出二维数组中最大值位置</h1><p>你有一个二维数组: <code>array</code> , 求其中最大值的二维坐标.</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">np.unravel_index(np.argmax(array), array.shape)</span><br></pre></td></tr></table></figure>]]></content>
      
      
      <categories>
          
          <category> Python </category>
          
          <category> Numpy </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> Numpy </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>《强化学习》(第 2 版) 习题 6</title>
      <link href="/ML/RL/reinforcement_learning/6/"/>
      <url>/ML/RL/reinforcement_learning/6/</url>
      
        <content type="html"><![CDATA[<h1 id="6-1"><a href="#6-1" class="headerlink" title="6.1"></a>6.1</h1><p>在 $V$ 被不断更新的情况下, 式子左边的 $V(S_t)$ 与右边的是不等价的. 因为右边的 $V(S_t)$ 是没有更新的, 而左边的 $V(S_t)$ 却是已经更新的. 因此右边得再加上 $\alpha\delta_t$ .</p><h1 id="6-2"><a href="#6-2" class="headerlink" title="6.2"></a>6.2</h1><p>我们将整个走高速以及到家的过程简化成一个状态 $s_2$ , 从新办公楼到新停车场到高速的过程简化成 $s_1$ , 显然 $V(s_2)$ 与之前的是一样的, 于是我们如果采取时序差分只需一步就可以获得较准确的更新, 这样显然比蒙特卡洛整个走一遍再更新的效率要高, 且准确度是差不多的 (关键就在于 $V(s_2)$ , 即某些状态的价值仍然相当正确的) .</p><h1 id="6-3"><a href="#6-3" class="headerlink" title="6.3"></a>6.3</h1><p>因为无折扣, 所以 $\gamma=1$ , 又因为在多数情况下回报 $R=0$ , 所以根据 $\text{TD}$ 方法的更新公式多数情况的价值都不会改变 (仍是 $0.5$). 而第一幕, 应该是到达了左边的终止状态, 值改变了 $-0.5\alpha$ .</p><h1 id="6-4"><a href="#6-4" class="headerlink" title="6.4"></a>6.4</h1><p>不知如何回答.</p><p>但是总的来说, $\alpha$ 越小, 收敛约慢, 相同的结果也越好. 且同一参数下 (至少不是太大的参数) $\text{TD}$ 总是优于蒙特卡洛. </p><h1 id="6-5"><a href="#6-5" class="headerlink" title="6.5"></a>6.5</h1><p>可能是因为 $\alpha$ 过大导致难以收敛. 应该与初始化有关.</p><h1 id="6-6"><a href="#6-6" class="headerlink" title="6.6"></a>6.6</h1><p>蒙特卡洛和 $\text{TD}$ . 猜不到.</p><h1 id="6-7"><a href="#6-7" class="headerlink" title="6.7"></a>6.7</h1><p>将第 5 章中 “离轨策略 $\text{MC}$ 控制算法, 用于估计 $\pi\approx\pi_*$“ 中更新公式中的 $[G-Q(S_t,A_t)]$ 改为 $[R_{t+1}+\max_aQ(S_{t+1}, a)-Q(S_t, A_t)]$ .<br>$$V(S_t)=R_{t+1}+\max_aV(S_{t+1})-V(S_t)$$</p><h1 id="6-8"><a href="#6-8" class="headerlink" title="6.8"></a>6.8</h1>$$\begin{aligned}G_t-Q(S_t,A_t)&=R_{t+1}+\gamma G_{t+1}-Q(S_t,A_t)+\gamma Q(S_{t+1}, A_{t+1})-\gamma Q(S_{t+1}, A_{t+1})\\&=\delta_t+\gamma(G_{t+1}-Q(S_{t+1}, A_{t+1}))\\&=\cdots\\&=\sum_{k=t}^{T-1}\gamma^{k-t}\delta_k\end{aligned}$$<h1 id="6-9"><a href="#6-9" class="headerlink" title="6.9"></a>6.9</h1><p><a href="/jupyter/强化学习-第2版/5/在有风的网格世界中向 8 个方向移动.html">在有风的网格世界中向 8 个方向移动</a></p><h1 id="6-10"><a href="#6-10" class="headerlink" title="6.10"></a>6.10</h1><p><a href="/jupyter/强化学习-第2版/5/随机强度的风.html">随机强度的风</a></p><h1 id="6-11"><a href="#6-11" class="headerlink" title="6.11"></a>6.11</h1><p>因为它的更新公式与 $\text{Sarsa}$ 的区别在于将 $Q(S', A')$ 换成了 $\max_aQ(S',a)$ . 这其实与将你当前的策略换成贪心策略是等价的. 因此事实上你其实是用了贪心策略来更新你现在的 (不一定是贪心) 的策略, 因此是 “离轨” 的.</p><h1 id="6-12"><a href="#6-12" class="headerlink" title="6.12"></a>6.12</h1><p> 并不.</p><p>$\text{Sarsa}$ 在 $Q$ 更新前就已经选取好了下一步动作 $A'$ . 而 $\text{Q}$ 学习在更新后才选取 $A'$ . 如果执行动作后的环境 $S'$ 仍然是先前的环境 $S$ . 那么 (下一步选取的动作) 就会产生不同.</p><h1 id="6-13"><a href="#6-13" class="headerlink" title="6.13"></a>6.13</h1><p>应当随机的用其中一个 $Q$ , 如何用 $\epsilon$-贪心 策略选取一个动作 $A_{t+1}$ , 然后在更新公式中用另一个 $Q$ 来计算 $Q(S_{t+1}, A_{t+1})$ . </p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 《强化学习》 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 习题 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.5</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-5/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-5/</url>
      
        <content type="html"><![CDATA[<h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><p>由和差化积可得<br>$$\begin{aligned}&\lim_{x\to+\infty}(\sin\sqrt{x+1}-\sin\sqrt{x-1})\\=&\lim_{x\to+\infty}2\cos \frac{\sqrt{x+1}+\sqrt{x-1}}{2}\sin\frac{\sqrt{x+1}-\sqrt{x-1}}{2}\end{aligned}$$<br>显然为 $0$ .</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><p>假设有<br>$$\sin\sqrt{x+k}=\sin\sqrt{x}+\epsilon_x^k$$<br>显然 $\lim_{x\to\infty}\epsilon_x^k=0$ , 由此可证得.</p><h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1>$$\left|\lim_{x\to+\infty}\sin(\pi\sqrt{n^2+1})\right|=\left|\lim_{x\to+\infty}\sin(\pi n+\epsilon_x)\right|=\left|\lim_{x\to\infty}\sin(\epsilon_x)\right|=0$$<p>因此有<br>$$\lim_{x\to+\infty}\sin(\pi\sqrt{n^2+1})=0$$</p><h1 id="7"><a href="#7" class="headerlink" title="7"></a>7</h1><p>原式等于<br>$$\lim_{n\to+\infty}n^{x-1}\left(1+\frac{1}{n}\right)^n$$<br>只有当 $x\in(-\infty,1]$ 时函数才有意义, 其中 $f((-\infty,1))=\{0\}$ , $f(1)=\mathrm{e}$ .</p><h1 id="8"><a href="#8" class="headerlink" title="8"></a>8</h1>$$\begin{aligned}\sum_{_{k=1}}^n\frac{|ka_k\sin{kx}|}{|kx|}&\leqslant\frac{|\sin x|}{|x|}\\\lim_{x\to 0}\sum_{_{k=1}}^n\frac{|ka_k\sin{kx}|}{|kx|}&\leqslant\lim_{x\to 0}\frac{|\sin x|}{|x|}\\\sum_{_{k=1}}^n|ka_k|&\leqslant1\end{aligned}$$]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.4</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-4/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-4/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><p>设函数 $f$ 在 $(x_0-r, x_0)$ ($r$ 是一个确定的正数) 上有定义. 设 $l$ 是一个给定的实数. 若对任意给定的 $\varepsilon>0$ , 存在一个 $\delta\in(0,r)$ , 使得当 $0<x_0-x<\delta$  时, 有<br>$$|f(x)-l|<\varepsilon,$$<br>则称 $l$ 为 $f$ 在 $x_0$ 处的<strong>右极限</strong>, 表示成<br>$$l=\lim_{x\to{x_0}^-}f(x).$$</p><h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>由定义显然.</p><h1 id="8"><a href="#8" class="headerlink" title="8"></a>8</h1><p>即对于任意的 $\epsilon>0$ 存在 $N\in\mathbb{Z}$ 使得当 $n>N$ 时有 $|f(x_n)-A|<\epsilon$ . 由递增性可得, 任意 $x\in(x_N,x_0)$ 都有 $|f(x)-A|<\epsilon$ . 由此可证.</p><h1 id="10"><a href="#10" class="headerlink" title="10"></a>10</h1><p>显然可以取得足够小的 $\delta>0$ , 使得有对于任意的某个 $N\in\mathbb{Z}$ 当 $n\leqslant N$ 时 $A_n$ 不包含于 $(x_0-\var,x_0+\var)$ , 因此对于 $x\in(x_0-\var,x_0+\var)$ 有 $|x-0|<\frac{1}{N}$ . 于是对于任意 $\epsilon>0$ , 只需找到 $N$ 使得 $\frac{1}{N}<\epsilon$ , 即可证明<br>$$\lim_{x\to x_0}f(x)=0$$<br>当然当 $x=0或1$ 时只有右极限与左极限 (都为 $1$) .</p><h1 id="14"><a href="#14" class="headerlink" title="14"></a>14</h1><p>由 1.6 节可知, 原式可以等价于</p>$$\lim_{n\to\infty}n\sin\left(2\pi n!\left({\mathrm e}_n\sum_{i=1}^n\frac{1}{i!}\right)\right)$$<p>其中 $\mathrm{e_n}=\mathrm{e}-\sum_{i=1}^n1/i!$ .</p><p>那么我们化简可得</p>$$\begin{aligned}&\lim_{n\to\infty}n\sin\left(2\pi n!\left(\epsilon_n\sum_{i=1}^n\frac{1}{i!}\right)\right)\\=&\lim_{n\to\infty}n\sin\left(2\pi\epsilon_n\right)\\=&\lim_{n\to\infty}2\pi n\epsilon_n\frac{\sin(2\pi\epsilon_n)}{2\pi\epsilon_n}\\=&2\pi\lim_{n\to\infty}n\epsilon_n\end{aligned}$$<p>在这节同样我们可以知道<br>$$\frac{n}{n!(n+1)}<n\epsilon_n<\frac{1}{n!}$$<br>令 $n\to\infty$ 即可得最终极限为 $0$ .</p><h1 id="15"><a href="#15" class="headerlink" title="15"></a>15</h1><p>在 $0$ 的邻域内始终存在 $x$ 使得 $g(x)=0$ .</p><h1 id="16"><a href="#16" class="headerlink" title="16"></a>16</h1><p>与书中是类似证法.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.3</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-3/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-3/</url>
      
        <content type="html"><![CDATA[<h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>用反证法. 若 $f$ 有两个不动点 $x_1, x_2$ , 显然这两个同样也是 $f\kern -0.2em \scriptsize\circ \normalsize \kern -0.4emf$ 的不动点.</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><h2 id="1"><a href="#1" class="headerlink" title="(1)"></a>(1)</h2><p>无穷多个.</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>不妨设 $f(x)=y$ . 显然有 $f(y)=x$ .又不妨设 $x\geqslant y$ , 那么显然有 $f(y)\geqslant f(x)$ , 由递增可知 $f(x)\geqslant f(y)$ . 那么就只有 $f(x)=f(y)$ , 也就是 $f(x)=x$ . 这是唯一解.</p><h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p>有<br>$$f(1+1)=f(2) = 2f(1)$$<br>用数学归纳法, 假设对于 $n$ , $f(n)=nf(1)$ 成立, 那么有<br>$$f(n+1)=f(n)+f(1)=(n+1)f(1)$$<br>证毕.</p><h1 id="7"><a href="#7" class="headerlink" title="7"></a>7</h1>$$(f(x+l)=f(x))\to(f(x-l)=f(x))$$<p>因此有 $f(l)=f(0), f(-l)=f(0)$ , 自然就是常函数.</p><h1 id="8"><a href="#8" class="headerlink" title="8"></a>8</h1><p>反证法.</p><p>若是, 则有<br>$$\begin{aligned}\sin (x+l)^2&=\sin x^2\\\sin (x^2+2xl+l^2)&=\sin x^2\end{aligned}$$<br>而<br>$$\sin(x^2+2k\pi)=\sin x^2$$<br>那么只能<br>$$2k\pi=2xl+l^2$$<br>显然不可能 ($x$ 是变量).</p><p>对于第二个函数, 则有</p>$$\begin{aligned}\sin (x+l)+\cos(\sqrt2(x+l))&=\sin x+\cos\sqrt2x\\\sin(x+l)-\sin x&=\cos\sqrt2x-\cos(\sqrt2(x+l))\\2\cos\left(\frac{2x+l}{2}\right)\sin\left(\frac{l}{2}\right)&=-2\sin\left(\frac{2\sqrt2x+\sqrt2l}{2}\right)\sin\left(\frac{-\sqrt2l}{2}\right)\end{aligned}$$<p>移项后显然不成立 (变量与定值).</p><h1 id="9"><a href="#9" class="headerlink" title="9"></a>9</h1><p>如果有一个函数 $f$ ,一个实数 $t$ , 不妨设 $f(t)=a, f(-t)=b$ .令 $g(t)+h(t)=a. g(t)-h(t)=b$ . 很明显, $g(t),h(t)$ 有唯一解. 再令 $g(-t)=g(t),h(-t)=-h(t)$ , 很显然有 $g(-t)+h(-t)=b$ . 对于任意的 $t$ 都可以如此构造, 我们可以得到一个偶函数 $g(t)$ , 一个奇函数 $h(t)$ , 使得 $g(t)+h(t)=f(t)$ .</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.2</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-2/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-2/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><p>利用定理 2.2.2 即可.</p><h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>将多项式方程按次数排序 (一次多项式, 两次多项式$\cdots$) , 显然, 每个次数多项式方程的解是可数的, 而多项式方程所有的次数是可数的. 根据定理 2.2.2 , 代数数是可数的.</p><h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><p>按区间中间与零点的距离排序, 右边优先.</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><p>将 $[0, 1]$ 间所有数换成二进制小数即可.</p><h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1><p>显然 $x$ 无法在这个排列中找到, 因此 $\mathrm{R}$ 不可数.</p><h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p>考虑一个直线集合 $L$ .首先我们选定一条直线 $l$ , 找到另一条直线 $l'$ 使得 $l'\parallel l$ , 同时 $l'\not\in L$ .这是容易找到的, 因为与 $l$ 垂直的直线上的点是不可数的, 而 $L$ 是可数集, 那么说明与 $l$ 垂直的直线上必然存在一个点使得过该点的平行于 $l$ 的直线 $l'$ 不属于 $L$ . 从而我们可以得知, $L$ 中的其他直线最多与 $l'$ 有一个交点. 那么将这些交点也划为一个集合 $P$ (交点集) , 这个集合显然是至多可数的, 而 $l'$ 上有不可数个点, 这说明必然有点不被 $L$ 中的直线覆盖, 证毕.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 2.1</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/2/2-1/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/2/2-1/</url>
      
        <content type="html"><![CDATA[<h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>用数学归纳法可以证明 $f^n(a)=a$ .</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><h2 id="1"><a href="#1" class="headerlink" title="(1)"></a>(1)</h2><p>既然是单射, 那么就有 $|f(A)|=|A|$ ($|A|$ 指的是这个集合中的元素个数) . 而又有 $f(A)\subseteq A$ .那么只能有 $f(A)=A$ .</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>上面的讨论同样说明映射 $f$ 是满射. 也就是说 $f$ 是双射, 自然 $f^{-1}$ 存在.</p><h2 id="3"><a href="#3" class="headerlink" title="(3)"></a>(3)</h2>$$\mathrm A^n_n=n!​$$<h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1><p>先对这个集合的元素制定一个符号, 数字 $i$ 就代表第 $i$ 个元素.</p><p>那么只需令 $f$ 为<br>$$f(i)=n-i+1$$<br>即可.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 1.11</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/1/1-11/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/1/1-11/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="(1)"></a>(1)</h2><p>等价于</p>$$\lim_{n\to \infty}\frac{1/n}{\ln(n/(n-1))}$$<p>由 1.6 节练习题 10 可得<br>$$\lim_{n\to \infty}\frac{1/n}{\ln(n)-\ln(n-1)}=\lim_{n\to\infty}\frac{1/n}{1/n+\varepsilon_n-\varepsilon_{n-1}}=1$$</p><h2 id="3"><a href="#3" class="headerlink" title="(3)"></a>(3)</h2><p>等价于</p>$$\lim_{n\to\infty}\frac{1/\sqrt{n}}{\sqrt{n}-\sqrt{n-1}}=\lim_{n\to\infty}1-\frac{\sqrt{n}}{\sqrt{n-1}} = 0$$<h2 id="4"><a href="#4" class="headerlink" title="(4)"></a>(4)</h2><p>等价于</p>$$0\leqslant\lim_{n\to\infty}\frac{\sqrt{n}}{n\sqrt{n}-(n-1)\sqrt{n-1}}=\lim_{n\to\infty}\frac{\sqrt n}{(n-1)\sqrt{n-1}+\sqrt n}\leqslant\lim_{n\to\infty}\frac{\sqrt{n}}{n\sqrt{n-1}}=0$$<p>因此极限为 $0$ .</p><h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>等价于</p>$$\lim_{n\to\infty}\mathrm{e}^{(\sum_{i=1}^n\ln(i)/n^2)}=\mathrm{e}^{\lim_{n\to\infty}\ln(n)/(2n-1)}=1$$<h1 id="3-1"><a href="#3-1" class="headerlink" title="3"></a>3</h1><p>等价于</p>$$\lim_{n\to\infty}\frac{(2n-1)^2}{n^3-(n-1)^3}=\lim_{n\to\infty}\frac{4n^2-4n+1}{3n^2-3n+1}=\frac{4}{3}$$<h1 id="4-1"><a href="#4-1" class="headerlink" title="4"></a>4</h1><p>等价于</p>$$\lim_{n\to\infty}\frac{na_n}{2n-1}=\frac{a}{2}$$<h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1><p>显然有</p>$$\lim_{n\to\infty}\frac{\sin n}{n}=0$$<p>但<br>$$\frac{\sin n-\sin(n-1)}{1}$$</p><p>却没有极限.</p><h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p>只证明有限数的情况.</p><p>同样有<br>$$A-\varepsilon<\frac{a_n-a_{n_0-1}}{b_n-b_{n_0-1}}<A+\varepsilon$$<br>因此就有</p>$$A-\epsilon\leqslant\mathop{\lim \inf}_{n\to\infty}\frac{a_n-a_{n_0-1}}{b_n-b_{n_0-1}}=\frac{a_{n_0-1}}{b_{n_0-1}}=\mathop{\lim \sup}_{n\to\infty}\frac{a_n-a_{n_0-1}}{b_n-b_{n_0-1}}\leqslant A+\varepsilon$$<p>令 $\varepsilon\to0$ 即可得.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>《强化学习》(第 2 版) 习题 5</title>
      <link href="/ML/RL/reinforcement_learning/5/"/>
      <url>/ML/RL/reinforcement_learning/5/</url>
      
        <content type="html"><![CDATA[<h1 id="5-1"><a href="#5-1" class="headerlink" title="5.1"></a>5.1</h1><p>因为 $20,21$ 这两个状态下玩家会停牌, 而此时赢庄家的概率会很高, 因此价值较大. 而小于 $20$ 时, 要牌可能会导致爆牌, 因此较低.</p><h1 id="5-2"><a href="#5-2" class="headerlink" title="5.2"></a>5.2</h1><p>我觉得不会. 应当都会收敛到真实值. </p><h1 id="5-3"><a href="#5-3" class="headerlink" title="5.3"></a>5.3</h1><p>不会画, 懒得画.</p><h1 id="5-4"><a href="#5-4" class="headerlink" title="5.4"></a>5.4</h1><p>只需修改 $\mathrm{average}$ 函数即可. 定义一个变量为 $pre\text -avg$ 储存之前的平均数, 然后定义 $\mathrm{average}$ 函数为</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">average</span>(<span class="params">G, pre-avg</span>):</span><br><span class="line">    n = <span class="built_in">len</span>(Returns)</span><br><span class="line">    <span class="keyword">return</span> avg + (G - avg) / n</span><br></pre></td></tr></table></figure><p>即可.</p><h1 id="5-5"><a href="#5-5" class="headerlink" title="5.5"></a>5.5</h1><p>首次访问是 $10$, 每次访问是 $5.5$.</p><h1 id="5-6"><a href="#5-6" class="headerlink" title="5.6"></a>5.6</h1><p>给定起始状态与起始动作 $S_t, A_t$ , 后续的状态-动作轨迹 $S_{t+1},A_{t+1},A_{t+1},\dots,S_T$ 在策略 $\pi$ 下的概率是</p>$$\Pr\{S_{t+1},A_{t+1},A_{t+1},\dots,S_T\mid S_t, A_t,A_{t+1\colon T-1}\sim\pi\}=p(S_{t+1}\mid S_t,A_t)\prod_{{k=t+1}}^{T-1}\pi(A_k\mid S_k)p(S_{k+1}\mid S_k,A_{k})$$<p>因此重要度采样比为</p>$$\rho_{t+1\colon T(t)-1}=\prod_{{k=t+1}}^{T-1}\frac{\pi(A_k\mid S_k)}{b(A_k\mid S_k)}$$<p>即将 $k$ 的起始向后移一位即可,</p>$$Q(s,a)\dot{=}\frac{\sum_{t\in\mathcal{T}(s)}\rho_{t+1\colon T(t)-1}G_t}{\sum_{t\in\mathcal{T}(s)}\rho_{t+1\colon T(t)-1}}$$<h1 id="5-7"><a href="#5-7" class="headerlink" title="5.7"></a>5.7</h1><p>由于一开始加权重要度采样就是有偏的, 因此误差会小幅度上升.</p><h1 id="5-8"><a href="#5-8" class="headerlink" title="5.8"></a>5.8</h1><p>由于这题的特殊性, 我们可以很简单的知道, 在每一幕中, 首次访问型 $s$ 状态的价值估计 (这里恰好等于回报) $G_0$ 的一半要小于每次访问型 $s$ 状态的价值估计 $G_0'$, 更准确些其实是有等式 $G_0+1=2G_0'$ . 因此就有</p>$$\infty=\mathbb{E}[X^2]/2<\mathbb{E}[{X'}^2]$$<p>这只能是 $\mathbb E[{X'}^2]=\infty$ .</p><h1 id="5-9"><a href="#5-9" class="headerlink" title="5.9"></a>5.9</h1><p>类似练习 5.4 .</p><h1 id="5-10"><a href="#5-10" class="headerlink" title="5.10"></a>5.10</h1><p>显然有</p>$$V_{n+1}=\frac{V_n\sum_{k=1}^{n-1}W_k+W_{n}G_n}{\sum_{k=1}^nW_k}=V_n+\frac{W_n}{C_n}(G_n-V_n)$$<h1 id="5-11"><a href="#5-11" class="headerlink" title="5.11"></a>5.11</h1><p>算法只是将 $\pi(A_t\mid S_t)$ 换成了 $1$ . 事实上本来就有 $\pi(A_t\mid S_t)=1$ , 这样的特性由上一步的 “如果”  保证.</p><h1 id="5-12"><a href="#5-12" class="headerlink" title="5.12"></a>5.12</h1><p>只做了第一个赛道.</p><p>同时没有判定边界, 因为一个一个手动输太麻烦了.</p><p><del>就是懒</del></p><p><a href="/jupyter/强化学习-第2版/5/赛道问题.html">赛道问题</a></p><h1 id="5-13"><a href="#5-13" class="headerlink" title="5.13"></a>5.13</h1> $R_{t+1}$ 只与 $A_t, S_t$ 有关, 因此可以推出.即$$\mathbb{E}[\rho_{t\colon T-1}R_{t+1}]=\mathbb{E}\left[R_{t+1}\prod_{k=t}^{T-1}\frac{\pi(A_k\mid S_k)}{b(A_k\mid S_k)}\right]=\mathbb{E}\left[\frac{\pi(A_t\mid S_t)}{b(A_t\mid S_t)}R_{t+1}\right]=\mathbb{E}[\rho_{t\colon t}R_{t+1}]$$<h1 id="5-14"><a href="#5-14" class="headerlink" title="5.14"></a>5.14</h1><p>判断是否 $0$ , 如果是, 伪代码第 13 行后面加的项中的 $G$ 乘上一个 $\gamma^{T}$ , 如果不是, 乘上 $(1-\gamma)\gamma^{T-t-1}$ .</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 《强化学习》 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 习题 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 1.10</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/1/1-10/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/1/1-10/</url>
      
        <content type="html"><![CDATA[<h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><h2 id="1"><a href="#1" class="headerlink" title="(1)"></a>(1)</h2><p>只需找到对应的子列 $\{a_{k_n}\}$ , 然后运用极限的四则运算即可.</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>由 1.8 节得 $\inf_{k\geqslant n}-a_k=-\sup_{k\geqslant n}a_k$ . 因此等式显然成立.</p><h2 id="3"><a href="#3" class="headerlink" title="(3)"></a>(3)</h2> $a_n>a^*-\sqrt\epsilon, b_n>b^*-\sqrt\epsilon$ , 于是就有 $a_nb_n>a_*b_*$ , 第一个左边不等式显然成立. 而又有$$\mathop{\lim\inf}_{n\to\infty}a_nb_n\leqslant\mathop{\lim\inf_{n\to\infty} a_nb^*}=b^*\mathop{\lim\inf a_n}_{n\to\infty}$$<p>显然第一个右边不等式也成立. 利用同样方法可以证明接下来的不等式.</p><h2 id="4"><a href="#4" class="headerlink" title="(4)"></a>(4)</h2><p>同 (1).</p><h1 id="3-1"><a href="#3-1" class="headerlink" title="3"></a>3</h1><p>依题意得存在 $N, n>N$ 时有 $a_n<(1+\epsilon)^n$ , 由此可得 $\lim_{n\to\infty}a_n/l^n=0$ . 这个关系是等价的.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 1.8</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/1/1-8/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/1/1-8/</url>
      
        <content type="html"><![CDATA[<h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><p>由于 $(n/(n-1))^{(n-1)}<\mathrm e<3\leqslant4-1\leqslant n-1,n\geqslant4$ 因此有 $\sqrt[n]{n}<\sqrt[n-1]{n-1}$ . 然后又有 $1<\sqrt{2}=\sqrt[4]{4}<\sqrt[3]{3}$ . 所以上确界是 $\sqrt[3]{3}$ , 下确界是 $1$ .</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><p>根据上下确界的定义, 可以找到两个子列极限分别为上下确界, 数列自然不收敛.</p><h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1><p>一个有界数列 $\{a_n\}$ , 我们找出它任意一个上界 $A$ 与下界 $B$ , 取用二分法将 $[A,B]$ 分为两个区间, 显然两个区间之中至少有一个有无穷多个数列的项在其中. 不停重复这个过程, 根据闭区间套定理可得一个极限 $a$ , 由我们选取的过程可得存在子列趋近于 $a$ .</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>《强化学习》(第 2 版) 习题 4</title>
      <link href="/ML/RL/reinforcement_learning/4/"/>
      <url>/ML/RL/reinforcement_learning/4/</url>
      
        <content type="html"><![CDATA[<h1 id="4-1"><a href="#4-1" class="headerlink" title="4.1"></a>4.1</h1>$$q_\pi(11,\text{down})=-1$$<h1 id="4-2"><a href="#4-2" class="headerlink" title="4.2"></a>4.2</h1><p>都是 $-20$ .</p><p>事实上只需要算出第一个 $-20$ 就可以了, 状态 13 与状态 15 具有相同的状态价值, 状态 13 的动态特性变化并不影响它的价值 ($\text{down}$ 都是 $-20$) .</p><h1 id="4-3"><a href="#4-3" class="headerlink" title="4.3"></a>4.3</h1>$$\begin{aligned}q_\pi(s,a)&{\dot{=}}\mathbb{E}_\pi[G_t\mid S_t=s,A_t=a]\\&{=}\mathbb{E_{\pi}}[R_{t+1}+\gamma G_{t+1}\mid S_t=s,A_t=a]\\&{=}\mathbb{E}_\pi[R_{t+1}+\gamma q_{\pi}(S_{t+1},A_{t+1})\mid S_t=s,A_t=a]\\&{=}\sum_{s',r}p(s',r\mid s,a)\left[r+\gamma \sum _{a'}\pi(a'\mid s') q_\pi(s',a')\right]\end{aligned}$$$$\begin{aligned}q_{k+1}(s,a)&{\dot{=}}\mathbb{E}_\pi[R_{t+1}+\gamma q_{k}(S_{t+1},A_{t+1})\mid S_t=s,A_t=a]\\&{=}\sum_{s',r}p(s',r\mid s,a)\left[r+\gamma \sum _{a'}\pi(a'\mid s') q_{k}(s',a')\right]\end{aligned}$$<h1 id="4-4"><a href="#4-4" class="headerlink" title="4.4"></a>4.4</h1><p>“如果 $old\text-action\not= \pi(s)$ “ 改为 “如果 $\sum_{s',r}p(s',r\mid s,\pi(s))[r+\gamma V(s')]\not=\sum_{s',r}p(s',r\mid s,old\text-action)[r+\gamma V(s')]$“ .</p><h1 id="4-5"><a href="#4-5" class="headerlink" title="4.5"></a>4.5</h1><ol><li>“任意设定 $V(s)\in R$ “ 改为 “任意设定 $Q(s, a)\in R$“ .</li><li>“对每一个 $s\in \mathcal S$ 循环” 改为 “对每一个 $s\in\mathcal S,a\in\mathcal A$ 循环” ,</li><li>‘策略评估’ 中循环的内容改为</li></ol>$$\begin{aligned}&q\leftarrow Q(s,a)\\&Q(s,a)\leftarrow\sum_{s',r}p(s',r\mid s,a)\left[r+\gamma \sum _{a'}\pi(a'\mid s') Q(s',a')\right]\\&\Delta\leftarrow\max(\Delta,|q-Q(s,a)|)\end{aligned}$$<ol><li>‘3. 策略改进’ 中 “$\pi(s)\leftarrow \mathop{\arg\max}_{a}\sum_{s',r}p(s',r\mid s,a)[r+\gamma V(s')]$“ 改为 “$\pi(s)\leftarrow \mathop{\arg\max}_{a}Q(s,a)$“ </li></ol><h1 id="4-6"><a href="#4-6" class="headerlink" title="4.6"></a>4.6</h1><p>3: $\pi(s)$ 不能只取定值 $a$ , 要根据题目要求设定.</p><p>2: 好像没啥要改的…</p><p>1: 初始化需要多弄一个参数 $\varepsilon$ .</p><h1 id="4-7"><a href="#4-7" class="headerlink" title="4.7"></a>4.7</h1><p>这训练方法效率也忒慢了… 于是我就<del>偷懒</del>无奈放弃了, 只写了策略评估的部分 (<del>真的不是我懒啊喂</del>).</p><p><a href="/jupyter/强化学习-第2版/4/杰克租车问题.html">杰克租车问题</a></p><h1 id="4-8"><a href="#4-8" class="headerlink" title="4.8"></a>4.8</h1><p>首先确定一点, 在赌资为 $50$ 美元时, $q_*(50,50)=v_*(50)>v_*(s), s<50$ . 如果赌资少于 $50$ , 当达到 $50$ 时就相当于成功了一小半. 如果赌资大于 $50$ (大一点), 在输的时候最好也是输到 $50$ 美元, 好有一个退路. 因此就有了如此奇怪 (不连续) 的策略. 当然 $25$ 美元, $75$ 美元也是特殊的两个情况, 一个 ($25$ 美元) 堵上全部赌资 (赢了的话) 刚刚好达到 “成功了一小半的境地”, 一个 ($75$ 美元) 堵上 $25$ 美元赢了的话刚刚好胜利, 输了还有 $50$ 美元, 赢得概率还是很大, $25$ 美元算是次优情况, 而 $75$ 美元是更优情况 (这里的优指的是比之前的情况的优势大了<strong>很多</strong>). 因此其他情况都在考虑输和赢对这 3 种情况的靠拢.</p><h1 id="4-9"><a href="#4-9" class="headerlink" title="4.9"></a>4.9</h1><p><a href="/jupyter/强化学习-第2版/4/赌徒问题.html">赌徒问题</a></p><p>是稳定的.</p><h1 id="4-10"><a href="#4-10" class="headerlink" title="4.10"></a>4.10</h1>$$\begin{aligned}q_{k+1}(s,a)&{\dot{=}}\max_{a'}\mathbb{E}_\pi[R_{t+1}+\gamma q_{k}(S_{t+1},A_{t+1})\mid S_t=s,A_t=a, A_{t+1}=a']\\&{=}\max_{a'}\sum_{s',r}p(s',r\mid s,a)\left[r+\gamma q_{k}(s',a')\right]\end{aligned}$$]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 《强化学习》 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 习题 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 1.7</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/1/1-7/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/1/1-7/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><p>是. 因为</p>$$|a_m-a_n|\leqslant|a_m-a_N|+|a_N-a_n|<2\epsilon$$<h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="(1)"></a>(1)</h2><p>不是, 简单举个反例, 调和级数.</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>那就是了, 对应于之前 1.5 的例二.</p><p>很显然有 $|a_{n+1}-a_n|<\frac{1}{(n+1)^2}$ , 那么 $|a_m-a_n|<\sum_{i=n+1}^m 1/i^2,(m>n)$ , 记<br>$$\lim_{n\to\infty}\sum_{i=1}^n\frac{1}{i^2}=L$$<br>那么对于任意 $\epsilon>0$ , 存在 $N\in\mathbb{Z}^*$ , 使得当 $n>N$ 时, 有<br>$$L-\sum_{i=1}^n\frac{1}{i^2}<\epsilon,\left(L>\sum_{i=1}^n\frac{1}{i^2}\right)$$<br>那么对于这样的 $\epsilon$ , 当 $m>n>N$ 时, 就有<br>$$|a_m-a_n|<\sum_{i=n+1}^m \frac{1}{i^2}<L-\sum_{i=1}^n\frac{1}{i^2}<\epsilon$$</p><p>那么该数列显然是基本列.</p><h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><h2 id="1-2"><a href="#1-2" class="headerlink" title="(1)"></a>(1)</h2><p>根据第 2 题 (2) 显然成立 (它是基本列) .</p><h2 id="2-2"><a href="#2-2" class="headerlink" title="(2)"></a>(2)</h2><p>记 $|a_n|<M$ .<br>$$|b_m-b_n|=\left|\sum_{i=n+1}^ma_iq^i\right|<M\sum_{i=n+1}^m|q^i|<M\frac{q^{n+1}-q^{m+1}}{1-q}=\frac{Mq^{n+1}(1-q^{m-n})}{1-q}<\frac{Mq^{n+1}}{1-q}$$<br>由于</p>$$\lim_{n\to\infty}\frac{Mq^{n+1}}{1-q}=0$$<p>那么对于任意 $\epsilon>0$ , 存在 $N\in\mathbb{Z}^*$ , 使得当 $n>N$ 时, 有<br>$$|b_m-b_n|<\frac{Mq^{n+1}}{1-q}<\epsilon$$</p><p>因此 $\{a_n\}$ 是基本列, 自然收敛.</p><h2 id="3-1"><a href="#3-1" class="headerlink" title="(3)"></a>(3)</h2><p>由 (2) 得成立.</p><h2 id="4"><a href="#4" class="headerlink" title="(4)"></a>(4)</h2><p>由 (3) 得成立.</p><h1 id="4-1"><a href="#4-1" class="headerlink" title="4"></a>4</h1><p>用反证法. 假设不收敛, 那么就有: 存在 $\epsilon>0$ , 使得任取 $N\in\mathbb{Z}^*$ , 都存在 $m>n>N$ 使得 $|a_m-a_n|>\epsilon$ . 取</p>$N_1<n_1<m_1<N_2<n_2<m_2\cdots$ , 设$$b_n=|a_2-a_1|+|a_3-a_2|+\dots+|a_n-a_{n-1}|$$<p>那么就有<br>$$b_k>\sum_{i=1}^k\sum_{j=n_i}^{m_i-1}|a_{j+1}-a_j|>\sum_{i=1}^k|a_{m_i}-a_{n_i}|>k\epsilon$$<br>左右同时取极限得<br>$$\lim_{k\to\infty}b_k=+\infty$$</p><p>与题设矛盾.</p><h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1><p>存在 $\epsilon>0$ , 使得对任意的 $N\in\mathbb{Z}^*$ , 都存在 $m>n>N$ 使得 $|a_m-a_n|>\epsilon$ .</p><h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p>即 $\{a_n\}$ 不是基本列, 那么就存在 $\epsilon>0$ , 使得对任意的 $N\in\mathbb{Z}^*$ , 都存在 $m>n>N$ 使得 $|a_m-a_n|>\epsilon$ . 像第 4 题一样, 取 $N_1<n_1<m_1<N_2<n_2<m_2\cdots$ , 然后取两个 $\{a_n\}$ 子列 $\{a_{n_k}\}$ 与 $\{a_{m_k}\}$ . 由本节定理 1.7.1 得我们可从子列 $\{a_{n_k}\}$ 与 $\{a_{m_k}\}$ 中分别取出两个收敛的子列 , 记为 $\{b_n\},\{c_n\}$ . (嗯…就是子列的子列…<del>无限套娃</del>) 这两个子列必然收敛于不同的值, 这是因为<br>$$\lim_{n\to\infty}b_n-\lim_{n\to\infty}c_n=\lim_{n\to\infty}(b_n-c_n)>\epsilon$$</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>《强化学习》(第 2 版) 习题 3</title>
      <link href="/ML/RL/reinforcement_learning/3/"/>
      <url>/ML/RL/reinforcement_learning/3/</url>
      
        <content type="html"><![CDATA[<h1 id="3-1"><a href="#3-1" class="headerlink" title="3.1"></a>3.1</h1><h2 id="1-确定游戏"><a href="#1-确定游戏" class="headerlink" title="1.确定游戏"></a>1.确定游戏</h2><p>闯关小游戏 (类似森林冰火人那种) , 游戏是确定的, 即你每次都可以用同样的方式获得同种分数</p><p>动作为上下左右, 可以考虑用相同时间间隔来进行离散处理, 通关给出正收益, 被攻击, 死亡给出负收益.</p><h2 id="2-对弈"><a href="#2-对弈" class="headerlink" title="2.对弈"></a>2.对弈</h2><p>棋类游戏, 给定对手, 那么对手的行为的概率就是可预测的, 那么环境 (棋盘) 就可预测.</p><h2 id="3-随机游戏"><a href="#3-随机游戏" class="headerlink" title="3.随机游戏"></a>3.随机游戏</h2><p> 比如 2048.</p><h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>不能. 环境信息决定于智能体的感知能力, 如果感知能力不够强 (不是上帝视角) , 那么同样的环境信息就可能是不同的情况, 那么这样的任务就不是 $\text{MDP}$ 框架.</p><h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><p>个人觉得是第一个层次 (即方向盘) . 首先要考虑 “动作” 操控 (实际操作) 的难度. 比如说轮胎、肌肉、思想这种层面, 即使训练好了, 如何方便之前的做出这种动作仍是一种困难. 而且要控制动作的数量. 肌肉要控制的地方太多了, 会导致训练的参数很多, 收敛慢. 而且还要便于人类理解. 人类就是操控方向盘来与环境交互的, 以方向盘层次作为训练的动作更容易理解.</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><p><img src="1.png" alt=""></p><p>这是我在<a href="https://github.com/LyWangPX/Reinforcement-Learning-2nd-Edition-by-Sutton-Exercise-Solutions/blob/master/Chapter%203/Solutions_to_Reinforcement_Learning_by_Sutton_Chapter_3_rx1.pdf">别的地方</a>找到的答案. 但我认为这样的答案是错误的 (或者是题目没有出得足够严谨) .</p><p>要知道 $r_{\text{search}},r_{\text{wait}}$ 在文中的定义是 “期望数量 (期望收益)” , 重点关注 “期望” , “期望” 并不能作为 $p(s',r\mid s,a)$ 中的 $r$ , 因为取得期望的概率在绝大多数的情况下不是 $1$ , 甚至是 $0$ . 这里的 $r$ 应该取 $0,1,2,3\cdots$ , 并且给出 $r$ 取 $0,1,2,3\cdots$ 的条件概率才能够做这道题. 但题目也不可能这么出, 因此我猜测出题人要的答案应该就是如此, 但是他出的这道题目并不对应这个答案 (出题不严谨) .</p><h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1>$$\sum_{s'\in \mathcal S}\sum_{r\in\mathcal R}p(s',r\mid s,a)=1, 对于所有s\in(\mathcal S\backslash 终结状态),a\in\mathcal A(s).$$<hr><h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p>每次的回报都是 $-\gamma^K$ , $K$ 是每一幕失败前的步数. 区别在于持续性任务将所有失败的事件都考虑了 (失败会大于等于一次) .</p><h1 id="7"><a href="#7" class="headerlink" title="7"></a>7</h1><p>可能没有采用折扣, 导致机器人认为只要走出迷宫即可, 不需要考虑时间的长短.</p><h1 id="8"><a href="#8" class="headerlink" title="8"></a>8</h1>$$G_5=0, G_4=2, G_3=4,G_2=8, G_1=6,G_0=4$$<hr><h1 id="9"><a href="#9" class="headerlink" title="9"></a>9</h1>$$G_1=7\sum_{i=1}^\infty 0.9^{i-1}=70, G_0=2+0.9\cdot70=65$$<hr><h1 id="10"><a href="#10" class="headerlink" title="10"></a>10</h1><p>中学等比数列+一丢丢极限(不严谨甚至可以直接忽略极限).</p><h1 id="11"><a href="#11" class="headerlink" title="11"></a>11</h1>$$\sum_{a}\pi(a|s=S_t)\sum_{s',r}p(s',r\mid s=S_t,a)r$$<hr><h1 id="12"><a href="#12" class="headerlink" title="12"></a>12</h1>$$v_{\pi}(s)=\sum_{a}\pi(a\mid s)q_{\pi}(s,a)$$<hr><h1 id="13"><a href="#13" class="headerlink" title="13"></a>13</h1>$$q_\pi(s,a)=\sum_{s',r}p(s',r\mid s,a)(r+\gamma v_{\pi}(s'))$$<hr><h1 id="14"><a href="#14" class="headerlink" title="14"></a>14</h1>$$(2.3+0.4-0.4+0.7)/4\approx0.7$$<hr><h1 id="15"><a href="#15" class="headerlink" title="15"></a>15</h1><p>应该是相对大小.</p>$$v_c=\frac{c}{1-\gamma}$$<hr><h1 id="16"><a href="#16" class="headerlink" title="16"></a>16</h1><p>会, 因为 $v_c$ 对每个状态来说都不一样了 (距离终结状态的距离不同) . 举例懒得举.</p><h1 id="17"><a href="#17" class="headerlink" title="17"></a>17</h1>$$q_{\pi}(s,a)=\sum_{s',r}p(s',r\mid s,a)\left[r+\gamma \sum_{a'}q_\pi(s',a')\pi(a'\mid s')\right]$$<hr><h1 id="18"><a href="#18" class="headerlink" title="18"></a>18</h1>$$v_\pi(s)=\mathbb{E}_{a\sim\pi(a\mid s)}[q_\pi(s,a)]=\sum_{a}\pi(a\mid s)q_{\pi}(s,a)$$<hr><h1 id="19"><a href="#19" class="headerlink" title="19"></a>19</h1>$$q_\pi(s,a)=\mathbb{E}_{s',r\sim p(s',r\mid s,a)}[r+v_\pi(s')]=\sum _{s', r}p(s',r\mid s,a)(r+\gamma v_{\pi}(s'))$$<hr><h1 id="20"><a href="#20" class="headerlink" title="20"></a>20</h1><p>绿色部分是 $-1$ , 洞口是 $0$ , 然后按照木杆的距离递减.</p><h1 id="21"><a href="#21" class="headerlink" title="21"></a>21</h1><p>绿色部分是 $-1$ , 然后按照推杆的距离画一个 $-2$ 等值线, 然后以木杆的距离递减.</p><h1 id="22"><a href="#22" class="headerlink" title="22"></a>22</h1>$$\gamma=0:\pi_{\text{left}},\gamma=0.9:\pi_{\text{right}},\gamma=0.5:\pi_{\text{both}}$$<hr><h1 id="23"><a href="#23" class="headerlink" title="23"></a>23</h1><p>懒得写, 式 (3.20) 套进去就好.</p><h1 id="24"><a href="#24" class="headerlink" title="24"></a>24</h1>$$G=\sum_{i=0}^\infty 10\gamma^{5i},24.419$$<hr><h1 id="25"><a href="#25" class="headerlink" title="25"></a>25</h1>$$v_*(s)=\max_aq_*(s,a)$$<hr><h1 id="26"><a href="#26" class="headerlink" title="26"></a>26</h1>$$q_*(s,a)=\sum_{s',r} p(s',r\mid s,a)[r+\gamma v_*(s')]$$<hr><h1 id="27"><a href="#27" class="headerlink" title="27"></a>27</h1>$$\pi_*(a\mid s)=\max_aq_*(s, a)$$<hr><h1 id="28"><a href="#28" class="headerlink" title="28"></a>28</h1>$$\pi_*(a\mid s)=\max_a\sum_{s',r} p(s',r\mid s,a)[r+\gamma v_*(s')]$$<hr><h1 id="29"><a href="#29" class="headerlink" title="29"></a>29</h1>$$\begin{aligned}v_\pi(s)&=\sum_{s',a}p(s'\mid s,a)[r(s,a)+\gamma v_\pi(s')]\\q_\pi(s,a)&=r(s,a)+\gamma\sum_{s'} p(s'\mid s,a)\sum_{a'}\pi(a'\mid s')q_\pi(s',a')\end{aligned}$$<p>最优价值函数同理.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 《强化学习》 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 习题 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 1.6</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/1/1-6/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/1/1-6/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="(1)"></a>(1)</h2>$$\lim_{n\to\infty}\left(1+\frac{1}{n-2}\right)^n=\lim_{n\to\infty}\left(1+\frac{1}{n-2}\right)^{n-2}\left(1+\frac{1}{n-2}\right)^2=\mathrm{e}$$<h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>显然当 $k=1$ 时成立. 假设对于 $k=i$ 成立, 那么有</p>$$\lim_{n\to\infty}\left(1+\frac{i+1}{n}\right)^n=\lim_{n\to\infty}\left(1+\frac{i}{n+1}\right)^n\left(1+\frac{1}{n}\right)^n=\mathrm{e}^{i+1}$$<p>因此对于 $i+1$ 同样成立, 得证.</p><h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><p>利用提示.</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><p>利用提示.</p><h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1><p>易证.</p><h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p>由上一题可得.</p><h1 id="7"><a href="#7" class="headerlink" title="7"></a>7</h1><p>右边不等式易证, 因此只证左边.</p>$$\left(\frac{n}{n+k}\right)^{n+k}=1\cdot \left(\frac{n}{n+k}\right)\dots \left(\frac{n}{n+k}\right)<\left(\frac{1+n(n+k)/(n+k)}{n+k+1}\right)^{n+k+1}=\left(\frac{n+1}{n+k+1}\right)^{n+k+1}$$<p>因此就有<br>$$\left(\frac{n+k}{n}\right)^{n+k}>\left(\frac{n+k+1}{n+1}\right)^{n+k+1}$$</p><p>因此显然.</p><h1 id="8"><a href="#8" class="headerlink" title="8"></a>8</h1><p><del>积分秒解</del></p>$$\begin{aligned}\ln(1+\frac{1}{n})&<\frac{1}{n}\\\ln(1+n)&<\frac{1}{n}+\ln(n)\end{aligned}$$<p>因此<br>$$\ln(1+n)<\frac{1}{n}+\frac{1}{n-1}+\dots+\frac{1}{2}+\frac{1}{1} +\ln1=1+\frac{1}{2}+\dots+\frac{1}{n}$$<br>又由于<br>$$\begin{aligned}\ln(1+\frac{1}{n})&>\frac{1}{n+1}\\\ln(1+n)&>\frac{1}{n+1}+\ln(n)\end{aligned}$$</p><p>同理</p><h1 id="9"><a href="#9" class="headerlink" title="9"></a>9</h1>$$\begin{aligned}1+\frac{1}{2}+\dots\frac{1}{n}-\frac{1}{2}-\frac{1}{3}-\frac{1}{n+1}&>x_n>0\\1-\frac{1}{n+1}&>x_n>0\end{aligned}$$<p>因此 $\{x_n\}$ 有界. 由于 $\ln(n+1)+\frac{1}{n+1}-\ln(n+2)>0$ ,  $\{x_n\}$ 是单调递增的, 因此极限存在.</p><h1 id="10"><a href="#10" class="headerlink" title="10"></a>10</h1><p>易证.</p><h1 id="11"><a href="#11" class="headerlink" title="11"></a>11</h1>$$\begin{aligned}\left(\frac{n+1}{\mathrm{e}}\right)^n<\left(\frac{n}{\mathrm{e}}\right)^{n-1}\cdot n\end{aligned}$$$$\mathrm{e}\left(\frac{n+1}{\mathrm{e}}\right)^{n+1}>\mathrm{e}\left(\frac{n}{\mathrm{e}}\right)^{n}\cdot n$$<p>因此只需数学归纳法就可证明.</p><h1 id="12"><a href="#12" class="headerlink" title="12"></a>12</h1><p>(怎么每次都被夹逼卡)</p><p>利用 11 题, 可得</p>$$\frac{n+1}{\mathrm{e}n}<\frac{(n!)^{1/n}}{n}<\frac{(n+1)(n+1)^{1/n}}{\mathrm{e}n}$$<p>用 1.2 节例 4 的类似方法可证明 $\lim_{n\to\infty}(n+1)^{1/n}=1$ . 那么由夹逼定则就可证明.</p><h1 id="13"><a href="#13" class="headerlink" title="13"></a>13</h1>$$s_{n+m}-s_n=\frac{1}{(n+1)!}\left[1+\frac{1}{n+2}+\dots+\frac{1}{(n+2)\cdots(n+m)}\right]>\frac{1}{(n+1)!}=\frac{n/(n+1)}{n!n}$$<h1 id="14"><a href="#14" class="headerlink" title="14"></a>14</h1>$$\begin{aligned}n!\mathrm{e}&=n!\left(1+\frac{1}{1!}+\frac{1}{3!}+\dots+\frac{1}{n!}+\frac{\theta_n}{n!n}\right)\\&=n!+\frac{n!}{1!}+\dots+\frac{\theta_n}{n}\end{aligned}$$<p>显然 $0<\theta_n/n<1$ , 因此 $n!\mathrm{e}-[n!\mathrm{e}]=\theta_n/n$ , 两边取极限得等于 $0$.</p><h1 id="15"><a href="#15" class="headerlink" title="15"></a>15</h1><p>由 10 得</p>$$\frac{1}{n+1}+\frac{1}{n+2}+\dots+\frac{1}{n+n}=\ln 2n+\gamma+\epsilon_{2n}-\ln n-\gamma-\epsilon_n=\ln2+\epsilon_{2n}-\epsilon_n$$<p>两边取极限得极限为 $\ln2$ ,</p><h1 id="16"><a href="#16" class="headerlink" title="16"></a>16</h1><p>显然 $\{x_n\}$ 单调 (递增) , 且 $0<x_n$ .</p><p>由算术几何平均不等式得</p>$$\left(1+\frac{1}{2}\right)\left(1+\frac{1}{2^2}\right)\cdots\left(1+\frac{1}{2^n}\right)<\left(1+\frac{1}{n}\right)^n<\mathrm{e}$$<p>自然极限存在.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 1.5</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/1/1-5/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/1/1-5/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="(1)"></a>(1)</h2><p>当 $n>10$ 时, 数列单调递减, 而 $x_n>0$ , 因此极限存在.</p><h2 id="2"><a href="#2" class="headerlink" title="(2)"></a>(2)</h2><p>数列单调递减, $x_n>0$ , 极限存在.</p><h1 id="2-1"><a href="#2-1" class="headerlink" title="2"></a>2</h1><p>显然该数列单调递增, 但有 $x_n<2$ (由数学归纳法得) , 因此极限存在.</p><h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><p>设数列 $\{a_n\}$ 是单调递增的, 若子列 $\{a_{k_n}\}$ 收敛, 说明 $a_{k_n}<A$ 即有界, 那么任取 $1\leqslant t<k_n$ , 都有 $a_1\leqslant a_t<a_{k_n}<A$ , 由于 $k_n$ 可以任取, 也就是说对于任意的 $t\in\mathbb{Z}^*$ 都有该结论, 即数列收敛.</p><p>对递减数列同理.</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><p>已经有提示了.</p><p>易得 $a_{n+1}>a_n$ , 即 $\{a_n\}$ 是单调数列, 由题意知有界, 因此有<br>$$(1-\lim_{n\to\infty}a_n)\lim_{n\to\infty}a_n\geqslant\frac{1}{4}, (1-\lim_{n\to\infty}a_n)\lim_{n\to\infty}a_n\leqslant\frac{1}{4}$$<br>那么只有<br>$$\lim_{n\to\infty}a_n=\frac{1}{2}$$</p><h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1>$$\begin{aligned}n^{n-1}&>(n-1)!\\(n!)^{n-1}&>(n-1)!^n\\(n!)^{1/n}&>(n-1)!^{1/(n-1)}\end{aligned}$$<h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p>易得 $x_n-x_1< \sum_{n=1}^\infty\frac{1}{n^2}$ , 而右边极限是存在的, 那么 $\{x_n\}$ 也就单调且有界, 即极限存在.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 1.4</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/1/1-4/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/1/1-4/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><p>当 $x$ 足够大, 时有<br>$$p(x)=x^3(1-\frac{4}{x}+\frac{5}{x^2}-\frac{6}{x^x})>\frac{x^3}{2}$$<br>显然 $\lim_{n\to\infty}p(n)=+\infty$ .</p><p>而当 $x$ 足够小时同理.</p><h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1>$$\frac{1}{n}(1+2+\dots+n)=\frac{1+n}{2}$$<p>显然.</p><h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><p>由求和公式显然.</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1>$$n(\sqrt n-\sqrt{n+1})=-\frac{n}{\sqrt n+\sqrt{n+1}}<-\frac{n}{2\sqrt{n+1}}=-\frac{\sqrt{n+1}}{2}+\frac{1}{2\sqrt{n+1}}$$<p>两边取极限可得.</p><h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1>$$\sum_{i=1}^n\frac{1}{\sqrt{n+i}}>\frac{n}{2\sqrt{2n}}=\frac{\sqrt{n}}{2\sqrt 2}$$<p>两边取极限可得.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>《强化学习》(第 2 版) 习题 2</title>
      <link href="/ML/RL/reinforcement_learning/2/"/>
      <url>/ML/RL/reinforcement_learning/2/</url>
      
        <content type="html"><![CDATA[<h1 id="2-1"><a href="#2-1" class="headerlink" title="2.1"></a>2.1</h1>$1/4$.# 2.24, 5必定发生了, 其余都可能发生.# 2.3首先应该要确定, 只要 $\epsilon$ 不取 $0$ , 经过足够长的时间应该都能够收敛到最优情况, 于是最优动作的概率为 $(1-\epsilon)\frac{\epsilon}{10}]$ , 而贪心取最优动作的概率取决于最开始的动作, 从期望值来看, 这个概率是 $1/10$ . 那么平均收益即可计算.$\epsilon-贪心$ :$$(1-\epsilon)\mathbb{E}[q_*(a_t)]+\epsilon\sum_{i=1}^{10}\mathbb{E}[q_*(a_i)]$$<p>其中 $a_t$ 是最优动作</p><p>贪心:<br>$$\frac{1}{10}\sum_{i=1}^{10}\mathbb{E}]q_*(a_i)]$$</p><h1 id="2-4"><a href="#2-4" class="headerlink" title="2.4"></a>2.4</h1>$$\alpha_i\prod_{j=i+1}^{n}(1-\alpha_j)$$<h1 id="2-5"><a href="#2-5" class="headerlink" title="2.5"></a>2.5</h1><p><a href="/jupyter/强化学习-第2版/2/多臂赌博机.html">多臂赌博机</a></p><p>可以明显看出常数步长对于非平稳问题的优势.</p><h1 id="2-6"><a href="#2-6" class="headerlink" title="2.6"></a>2.6</h1><p>因为其会探索得更多, 因此会更糟, 但同时由于其还拥有贪心的本质, 因此在不同臂收益差距明显时, 会出现峰值.</p><h1 id="2-7"><a href="#2-7" class="headerlink" title="2.7"></a>2.7</h1><p>只需证明最后表达式与 $Q_1$ 无关即可.  展开可得<br>$$Q_{n+1}=Q_1\prod_{i=1}^{n}(1-\beta_i)+\sum_{i=1}^nR_i\beta_i\prod_{j=i+1}^{n}(1-\beta_j)$$<br>显然有 $\beta_1=1$ . 因此<br>$$Q_{n+1} =\sum_{i=1}^nR_i\beta_i\prod_{j=i+1}^{n}(1-\beta_j)$$<br>与 $Q_1$ 无关.</p><h1 id="2-8"><a href="#2-8" class="headerlink" title="2.8"></a>2.8</h1><p>第 11 步恰好是 “10” 臂赌博机加一, 为什么这么恰好呢? 原因是 $\text{UBC}$ 的特点让其对于从未选择过的动作的优先度高于其他动作, 于是前 10 步恰好做过 10 钟动作, 因此对于每个动作来说 $\text{UBC}$ 特有的那一项标准差度量相等, 因此这一步完全是贪心的状态 (完全没有试探) , 因此产生一个小小的峰值. 而过了这一步, 试探的能力才会逐渐提升. 如果 $c=1$ , 也就是减少, 相当于提升了 $\text{UBC}$ 贪心的能力, 也就会更平滑, 尖峰就不会那么突出了. </p><h1 id="2-9"><a href="#2-9" class="headerlink" title="2.9"></a>2.9</h1><p>$\text{softmax}$ 就是广义的 $\text{sigmoid}$ .</p><h1 id="2-10"><a href="#2-10" class="headerlink" title="2.10"></a>2.10</h1><h2 id="1"><a href="#1" class="headerlink" title="(1)"></a>(1)</h2><p>只选动作 1 或动作 2 , 期望是 0.5 .</p><h2 id="2"><a href="#2" class="headerlink" title="(2)"></a>(2)</h2><p>最优期望是 0.55 . 当 A 时选择动作 2 , B 时选择动作 1 .</p><h1 id="2-11"><a href="#2-11" class="headerlink" title="2.11"></a>2.11</h1><p>这是要我把其他算法都实现一遍的意思??</p><p><a href="/jupyter/强化学习-第2版/2/多臂赌博机2.html">多臂赌博机2</a></p><p><img src="1.png" alt=""></p><p>好像有点丑.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 《强化学习》 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 习题 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>《强化学习》(第 2 版) 习题 1</title>
      <link href="/ML/RL/reinforcement_learning/1/"/>
      <url>/ML/RL/reinforcement_learning/1/</url>
      
        <content type="html"><![CDATA[<h1 id="1-1-左右互搏"><a href="#1-1-左右互搏" class="headerlink" title="1.1 左右互搏"></a>1.1 左右互搏</h1><h2 id="1"><a href="#1" class="headerlink" title="(1)"></a>(1)</h2><p>一开始应该收敛得很慢.</p><h2 id="2"><a href="#2" class="headerlink" title="(2)"></a>(2)</h2><p>应该不会, 我觉得它应该会收敛到必定不输的那个策略.</p><h1 id="1-2-对称性"><a href="#1-2-对称性" class="headerlink" title="1.2 对称性"></a>1.2 对称性</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="(1)"></a>(1)</h2><p>可以在更新价值表格时同时更新其对称位置.</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>应该会更快收敛.</p><h2 id="3"><a href="#3" class="headerlink" title="(3)"></a>(3)</h2><p>不应该. 因为如果对手有偏好, 那么我们对对称的位置应该有不同的考虑.</p><h2 id="4"><a href="#4" class="headerlink" title="(4)"></a>(4)</h2><p>不一定, 这与对手的策略有关.</p><h1 id="1-3-贪心策略"><a href="#1-3-贪心策略" class="headerlink" title="1.3 贪心策略"></a>1.3 贪心策略</h1><h2 id="1-2"><a href="#1-2" class="headerlink" title="(1)"></a>(1)</h2><p>如果是一开始就贪心, 当然是更差 (根本没有训练) . 如果已经收敛, 就会玩得更好.</p><h2 id="2-2"><a href="#2-2" class="headerlink" title="(2)"></a>(2)</h2><p>贪心难以收敛到最优策略.</p><h1 id="1-4-从试探中学习"><a href="#1-4-从试探中学习" class="headerlink" title="1.4 从试探中学习"></a>1.4 从试探中学习</h1><p>我认为从试探中学习的方式应该… 不太正确. 应该来说无论是学习还是胜率考虑都是不从试探中学习的更优.</p><h1 id="1-5-其他提升方法"><a href="#1-5-其他提升方法" class="headerlink" title="1.5 其他提升方法"></a>1.5 其他提升方法</h1><h2 id="1-3"><a href="#1-3" class="headerlink" title="(1)"></a>(1)</h2><p>不能.</p><h2 id="2-3"><a href="#2-3" class="headerlink" title="(2)"></a>(2)</h2><p>直接几个 <code>if</code> 判断就好了.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 《强化学习》 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 习题 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 1.2</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/1/1-2/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/1/1-2/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><p>只做部分, 且不完全做完<del>因为我懒</del>.</p><h2 id="3"><a href="#3" class="headerlink" title="(3)"></a>(3)</h2>$$\frac{n!}{n^n}<\frac{1}{n}$$<p>于是显然成立.</p><h2 id="5"><a href="#5" class="headerlink" title="(5)"></a>(5)</h2>$$\frac{2n+3}{5n-10} = \frac{2}{5}+\frac{7}{5n-10}$$<p>显然成立.</p><h2 id="9"><a href="#9" class="headerlink" title="(9)"></a>(9)</h2><p>取 $N=[\tan( \frac{\pi}{2}-\epsilon)]+1$, 那么当 $n>N$ 时, $\arctan n>\frac{\pi}{2}-\epsilon$ , 等价于 $|\arctan n-\frac{\pi}{2}|<\epsilon$ , 因此成立.</p><h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>狄利克雷函数.</p><h1 id="3-1"><a href="#3-1" class="headerlink" title="3"></a>3</h1><p>令 $\lim_{n\to\infty}a_n=a$ , $a$ 显然是个整数, 如若不然, $|a_n-a|\geqslant \max{(a-[a], [a]+1-a)}$ , 数列不收敛. 当 $a$ 为整数时, 若从某项起数列的项都等于一个常数 $b$ , 由收敛的定义得显然数列收敛且 $\lim_{n\to\infty}a_n=a=b$ . 若不存在某项使得在这项之后的项都等于一个常数, 那么 $|a_n-a|\geqslant 1$ , 原数列显然不收敛.</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="(1)"></a>(1)</h2><p>不可以. 只需令这无限多个正数都大于 1 即可.</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>不可以, 书里明确说了, 考虑的是 “小的方面” .</p><h2 id="3-2"><a href="#3-2" class="headerlink" title="(3)"></a>(3)</h2><p>可以, 理由同上.</p><h2 id="4-1"><a href="#4-1" class="headerlink" title="(4)"></a>(4)</h2><p>可以, 只需令 $k>[\frac{1}{\epsilon}]+1$ 即可.</p><h2 id="5-1"><a href="#5-1" class="headerlink" title="(5)"></a>(5)</h2><p>可以.对于任意的 $\epsilon'>0$ , 只需取 $\epsilon=\delta<\epsilon'$ , 并取 $N$ 使得这有限多项全在 $N$ 项之前即可.</p><h1 id="5-2"><a href="#5-2" class="headerlink" title="5"></a>5</h1>$a$ 是一个实数, 如果存在 $\epsilon>0$ , 使得对于任取的 $N\in\mathbb{N^*}$ , 都存在 $n>N$ 使得$$|a_n-a|>\epsilon$$<h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p>对于任意的 $\epsilon>0$ , 存在 $N'$ 使得当 $n>N$ 时,  $\frac{a_n}{n}<\epsilon$ , 那么只需找到 $N\geqslant N'$ 使得 $\max(a_1, a_2, \dots, a_N, a_{N+1})=a_{N+!}$ , 先假设可以找到这样的 $N$ , 那么当 $n>N$ 时, 假设 $a_k=\max(a_1, a_2, \dots,a_{n})$ 那么就有<br>$$\frac{\max(a_1, a_2, \dots,a_{n})}{n}\leqslant\frac{a_k}{k}<\epsilon$$<br>若无法找到这样的 $N$ , 那么说明数列在 $N$ 项之后是不单调递增的, 因此 $\max(a_1, a_2, \dots,a_{n})\leqslant\max(a_1, a_2, \dots,a_{N})=a_k, k\in\{1,2,3,\dots,N\}$ .因此只需取 $N=\left[\frac{a_k}{\epsilon}\right]+1$  即可.</p><h1 id="7"><a href="#7" class="headerlink" title="7"></a>7</h1>$$\begin{aligned}\because a_n-b_n=\frac{b_{n-1}-a_{n-1}}{2}\\\therefore \lim_{n\to\infty}a_n-b_n=0\\\forall\epsilon>0, \exist N\in\mathbb{Z}^*, |a_n-b_n|<\epsilon\end{aligned}$$<p>对 $a_n-c_n$ 做同样讨论, 最终得到<br>$$\exist N\in\mathbb{Z}^*,a_n-\epsilon<c_n<a_n+\epsilon, a_n-\epsilon<b_n<a_n+\epsilon$$ {, }<br>因此<br>$$3a_n-2\epsilon<a_n+b_n+c_n<3a_n+2\epsilon$$</p><p>由于 $a_n+b_n+c_n=a+b+c$ , 因此<br>$$3a_n-2\epsilon<a+b+c<3a_n+2\epsilon$$<br>等价于<br>$$\left|\frac{a+b+c}{3}-a_n\right|<\frac{2}{3}\epsilon<\epsilon$$<br>因此 $\lim_{n\to\infty}a_n=\frac{a+b+c}{3}$ . 同理得其他两个数列的极限.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 1.1</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/1/1-1/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/1/1-1/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><p>用反证法. 假设 $a+b$ 是有理数, 那么有 $a+b = \frac{p}{q}$ , 令 $a=\frac{p'}{q'}$ , 那么有<br>$$\begin{aligned}\frac{p'}{q'} + b &= \frac{p}{q}\\b&=\frac{pq'-p'q}{qq'}\end{aligned}$$<br>即 $b$ 为有理数, 与题目矛盾, 因此 $a+b$ 是无理数. $a-b$ 是同理可得.</p><p>若 $ab$ 是有理数, 那么有 $ab = \frac{p_0}{q_0}$ , 因此 $b=\frac{p_0}{aq_0}$ , 即 $b$ 为有理数, 矛盾, 因此 $ab$ 是无理数. $a/b$ 同理可得.</p><h1 id="2"><a href="#2" class="headerlink" title="2"></a>2</h1><p>这里只考虑大于零的情况 (小于等于零的情况类似, 因此为了方便不做讨论) .  假设有两个有理数 $a=\frac{p}{q}>b=\frac{p'}{q'}>0$ . 通分得 $\frac{pq'}{qq'}>\frac{p'q}{qq'}$ , 显然有 $\frac{pq'-1}{qq'}\geqslant\frac{p'q}{qq'}$ , 等价于 $\frac{kpq'-k}{qq'k}\geqslant\frac{p'qk}{qq'k}$ , 其中 $k\in\mathbb Z^*$因此 $a,b$ 两个有理数之间至少有 $\frac{kpq'}{qq'k}, \frac{kpq'-1}{qq'k},\dots,\frac{kpq'-k+1}{qq'k}$ , $k$ 个有理数, 有由于 $k$ 可以取任意大, 因此 $a,b$ 间有无限多个有理数. 而 $\frac{pq'}{qq'}>\frac{\sqrt{(pq')^2-1}}{qq'}>\frac{p'q}{qq'}$ , 由该节知  $\sqrt{(pq')^2-1}$ 是无理数, 由练习题 1 知 $\frac{\sqrt{(pq')^2-1}}{qq'}$ 是无理数, 因此两个有理数间至少有一个无理数. 由于两个有理数间有无限多个有理数, 因此两个有理数间也就有无限多个无理数.</p><h1 id="3"><a href="#3" class="headerlink" title="3"></a>3</h1><p>用类似书里的方法, 假设 $\sqrt[3]{2} = \frac{p}{q}$ , $p$ 与 $q$ 不存在公因子, 那么 $\sqrt[3]{2}q=p$ , 等价于 $2q^3=p^3$ , 显然 $p$ 是偶数, 令 $2p'=p$ , 那么 $q^3=8p^3$ , 因此 $q$ 也是偶数, 产生矛盾, 于是 $\sqrt[3]{2}$ 是无理数.</p><h1 id="4"><a href="#4" class="headerlink" title="4"></a>4</h1><p>平方得 $5+2\sqrt{6}$ , 显然是无理数, 假设 $\sqrt 2+\sqrt 3=\frac{p}{q}$ , 那么 $\frac{p^2}{q^2}$ 就是无理数了, 这显然不正确, 于是 $\sqrt 2+\sqrt 3$ 是无理数.</p><h1 id="5"><a href="#5" class="headerlink" title="5"></a>5</h1><p>一开始看这道题我就估计这与 $\sqrt{2}$ 是无理数有关, 果然猜对了.</p><p>显然 $(0,0)$ 是该圆上的一个有理点. 若 $\frac{p}{q},\frac{p'}{q'}\not=0, (\frac{p}{q},\frac{p'}{q'})$ 是该圆的一个有理点, 那么有 ${\left(\frac{p}{q}\right)}^2-{\left(\frac{p'}{q'}\right)}^2 -2\sqrt{2}\frac{p}{q}=0$ , 即 $2\sqrt 2=\frac{{\left(\frac{p}{q}\right)}^2-{\left(\frac{p'}{q'}\right)}^2}{\frac{p}{q}}$ 显然是有理数 (懒得化简) , 与 $\sqrt{2}$ 是无理数矛盾, 因此不存在 $(0,0)$ 之外的有理点, 即该圆只有唯一有理点.</p><h1 id="6"><a href="#6" class="headerlink" title="6"></a>6</h1><p>小学的竖式除法派上用场啦! 同样只考虑正数. 由于有尽小数可以看成是特殊无尽循环小数, 因此可以合并处理. 考虑 $\frac{p}{q}$ , 我们用竖式除法来做, 第 $n$ 次除得到的数 (第一个非零数开始算起) 称为 $a_n$ , 余下的数称为 $b_n$ (已经进位). 比如说 22/7 , 那么 $a_1=3, b_1=10, a_2=1, b_2=30$ .</p>$$\begin{aligned}22/7&=3\cdots\cdots1 \quad(进位变为10)\\10/7&=1\cdots\cdots3 \quad(进位变为30)\end{aligned}$$<p>显然对于固定的 $q$ ,那么 $a_n, b_n$ 完全由 $b_{n-1}$ 决定, 而我们又有 $b_n<10q$ .由鸽笼原理可知, 在 ${b_1, b_2,\dots, b_{10q}}$ 中必然存在两项相同, 假设这两项是 $b_i,b_j$ , $i<j$ , 那么循环节就是 $b_ib_{i+1}\cdots b_{j-1}$ , 也就是说我们找到了有理数 $\frac{p}{q}$ 的无尽小数表示.</p><p>后一个问题更简单些, 并且其实书中已经给出了求法, 这里不过多叙述.</p><h1 id="7"><a href="#7" class="headerlink" title="7"></a>7</h1><p>显然是无理数. 当然我们还是严谨的证明一下. 如果是有理数, 那么一定有循环节, 易知我们可以在这串数字中得到任意长度连续的 $0$ , 那么循环节只能由 $0$ 组成, 但是又不存在某位之后的所有数字都是 $0$ (必然会出现 $1$), 因此产生矛盾, 也就是说它是无理数.</p><h1 id="8"><a href="#8" class="headerlink" title="8"></a>8</h1>$$\begin{aligned}0.2499\cdots=0.25=\frac{1}{4}\\\begin{aligned}0.\dot 3\dot7\dot5\cdot1000&=375+0.\dot3\dot7\dot5\\0.\dot 3\dot7\dot5&=\frac{375}{999}\end{aligned}\\4.\dot5\dot1\dot8=4+0.\dot5\dot1\dot8\\\begin{aligned}0.\dot5\dot1\dot8\cdot1000&=518+0.\dot5\dot1\dot8\\0.\dot5\dot1\dot8&=\frac{518}{999}\end{aligned}\\4.\dot5\dot1\dot8=4+\frac{518}{999}=\frac{4514}{999}\end{aligned}$$<h1 id="9"><a href="#9" class="headerlink" title="9"></a>9</h1><p>与第七题是一样的证法. 易知我们可以从这串数字中得到任意长度连续的 $0$ , 于是循环节只能由 $0$ 组成, 同样也可以得到任意长度的 pl.$1$ , 于是循环节只能由 $1$ 组成, 矛盾, 于是该数为无理数.</p><h1 id="10"><a href="#10" class="headerlink" title="10"></a>10</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="(1)"></a>(1)</h2><p>若 $r,s\not=0$ , 那么令 $r=\frac{p}{q}, s=\frac{p'}{q'}$ , 易得 $\sqrt{2}=-\frac{pq'}{qp'}$ 矛盾.</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><h6 id="若-那么令-那么有-等价于-显然是有理数-矛盾"><a href="#若-那么令-那么有-等价于-显然是有理数-矛盾" class="headerlink" title="若  , 那么令  , 那么有  , 等价于  显然是有理数, 矛盾."></a>若 $r,s,t\not=0$ , 那么令  , 那么有 $r^2=2s^2+3t^2+2st\sqrt{6}$ , 等价于 $\sqrt{6} = \frac{r^2-2s^2-3t^2}{2st}$ 显然是有理数, 矛盾.</h6><h1 id="11"><a href="#11" class="headerlink" title="11"></a>11</h1><p>为了方便讨论, 我们将左边的展开式的项分类, 有几个 $a$ 相乘的项就称为几次项. 当它们都大于 $0$ 时, 展开左式得<br>$$1+a_1+a_2+\cdots+a_n+a_1a_2+\cdots>1+a_1+a_2+\cdots+a_n$$<br>当它们都小于 $0$ 时, 分两种情况讨论.</p><p>当 $\sum_{i=1}^n\leqslant-1$ 时. $(1+a_1)(1+a_2)\cdots(1+a_n)>0\geqslant1+a_1+a_2+\cdots+a_n$ .</p><p>当 $\sum_{i=1}^n>-1$ 时, 展开左式得 $1+a_1+a_2+\cdots+a_n+S$ , $S$ 是余下的项的和. 现证明 $S>0$ . 显然 $2k$ 次的项的和 (正数) 要大于 $2k+1$ 次项的和 (负数) 的绝对值. 比如<br>$$\sum_{i<j} a_ia_j=\sum_{i<j}a_ia_j\cdot1<-\sum_{i<j}a_ia_j\sum_{k\not=i,j}a_k$$<br>就是二次项和大于三次项和的绝对值. 也就是说 $S>0$ . 因此原式成立.</p><p>有点二项式展开的味道.</p><h1 id="12"><a href="#12" class="headerlink" title="12"></a>12</h1><p>本题 $(1),(2)$ 题可以合并, 即条件变成 $a_1,a_2,\dots a_n$ 符号相同, 且 $\left|\sum_{i=1}^na_i\right|<1$ . 由 11 题知后半部分成立, 因此我们只需证<br>$$\frac{1}{1-\sum_{k=1}^na_k}>\prod_{k=1}^n(1+a_k)$$<br>令 $a_{n+1} = 1-\sum_{k=1}^na_k$ , 那么由算数-几何平均不等式得<br>$$\begin{aligned}a_{n+1}\prod_{k=1}^n(1+a_k)&\leqslant1\\\prod_{k=1}^n(1+a_k)&\leqslant\frac{1}{a_{n+1}}\\\prod_{k=1}^n(1+a_k)&\leqslant\frac{1}{1-\sum_{k=1}^na_k}\end{aligned}$$<br>显然 $1+a_k>1>a_{n+1}$ , 等号无法取得. 因此<br>$$\prod_{k=1}^n(1+a_k)<\frac{1}{1-\sum_{k=1}^na_k}$$<br>得证.</p><h1 id="13"><a href="#13" class="headerlink" title="13"></a>13</h1><p>用书中方法即可证明.</p><h1 id="14"><a href="#14" class="headerlink" title="14"></a>14</h1><p>分别假设 $a\leqslant b, a>b$ 即可得. 几何意义即是, 在数轴上找到 $a,b$ 的中点, 然后向正半轴大的那个值靠拢.</p><h1 id="15"><a href="#15" class="headerlink" title="15"></a>15</h1><p>先证明两个的情况.</p><p>假设 $\frac{a_2}{b_2}\geqslant\frac{a_1}{b_1}$ , $b_1=kb_2$ , 那么就有$\frac{a_2}{b_2}\geqslant\frac{a_1}{kb_2}$ , 即 $ka_2\geqslant a_1$ , 因此有 $\frac{a_1+a_2}{b_1+b_2}\leqslant\frac{(1+k)a_2}{(1+k)b_2}=\frac{a_2}{b_2}$ , 同理得 $\frac{a_1+a_2}{b_1+b_2}\geqslant\frac{a_1}{b_1}$ .由于对于两项成立, 那么自然对于 $n$ 项成立.</p><h1 id="16"><a href="#16" class="headerlink" title="16"></a>16</h1><p>题目已经提示了.</p><p>当 $n=2$ 时显然成立. 假设当 $n=k$ 时成立, 那么有<br>$$(1+x)^k>1+kx$$<br>因此<br>$$(1+x)^{k+1}>(1+kx)(1+x)=1+(k+1)x+kx^2>1+(k+1)x$$<br>因此对于 $n=k+1$ 也成立, 证毕.</p><h1 id="17"><a href="#17" class="headerlink" title="17"></a>17</h1><p>即证<br>$$\begin{aligned}x^m(y^n-x^n)+y^m(x^n-y^n)&\leqslant0\\(x^m-y^m)(y^n-x^n)&\leqslant0\end{aligned}$$<br>显然成立 (异号) .</p><hr><h1 id="题外话"><a href="#题外话" class="headerlink" title="题外话"></a>题外话</h1><p>终于搞定累死我了…</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>(史济怀) 数学分析教程上册第 3 版-练习题 1.3</title>
      <link href="/math/mathematical_analysis/mathematical_analysis_practice/1/1-3/"/>
      <url>/math/mathematical_analysis/mathematical_analysis_practice/1/1-3/</url>
      
        <content type="html"><![CDATA[<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="(1)"></a>(1)</h2><p>不能.</p><h2 id="2"><a href="#2" class="headerlink" title="(2)"></a>(2)</h2><p>发散.</p><h2 id="3"><a href="#3" class="headerlink" title="(3)"></a>(3)</h2><p>发散.</p><h2 id="4"><a href="#4" class="headerlink" title="(4)"></a>(4)</h2><p>既可以收敛也可以发散.</p><h2 id="5"><a href="#5" class="headerlink" title="(5)"></a>(5)</h2>$\{a_n\},\{b_n\},\{c_n\}$ 都不一定收敛.# 2对于 $\epsilon'>0$, 存在 $N\in\mathbb{Z}^*$ , 使得当 $n>N$ 时, 有 $|a_n-a|<\epsilon'$ , 因此有 $|a_{n+1}-a_{n}|<|a_{n+1}-a|+|a-a_{n}|<2\epsilon'$, 因此只需 $\epsilon'$ 取得足够小, 就有$$\frac{a_{n+1}-a_n}{a_n}<\frac{2\epsilon'}{a+\epsilon'}<\epsilon$$<p>证毕.</p><h1 id="3-1"><a href="#3-1" class="headerlink" title="3"></a>3</h1><h2 id="1-2"><a href="#1-2" class="headerlink" title="(1)"></a>(1)</h2>$$\frac{3^n+(-2)^n}{3^{n+1}+(-2)^{n+1}}=\frac{1+\left(\frac{-2}{3}\right)^n}{3+\left(\frac{-2}{3}\right)^n\cdot(-2)}$$<p>利用极限的四则运算可得出极限为 $\frac{1}{3}$.</p><h2 id="3-2"><a href="#3-2" class="headerlink" title="(3)"></a>(3)</h2><p>将 $\sqrt{n+1}-\sqrt{n}$ 转换为 $\frac{1}{\sqrt{n+1}+\sqrt n}$ 即可.</p><h2 id="4-1"><a href="#4-1" class="headerlink" title="(4)"></a>(4)</h2>$$1<(\sqrt{n^2+n}-n)^{1/n}<\sqrt{n}^{1/n}<n^{1/n}$$<p>极限为 1.</p><h2 id="5-1"><a href="#5-1" class="headerlink" title="(5)"></a>(5)</h2>$$1-\frac{1}{n}<\left(1-\frac{1}{n}\right)^{1/n}<1$$<p>于是极限为 1.</p><h2 id="7"><a href="#7" class="headerlink" title="(7)"></a>(7)</h2>$$\arctan n<(\arctan n)^{1/n}<1$$<p>极限为 1.</p><h1 id="4-2"><a href="#4-2" class="headerlink" title="4"></a>4</h1><h2 id="3-3"><a href="#3-3" class="headerlink" title="(3)"></a>(3)</h2><p>利用 $a^2-b^2=(a+b)(a-b)$ .</p><h2 id="4-3"><a href="#4-3" class="headerlink" title="(4)"></a>(4)</h2><p>注意到</p>$$\frac{2+3}{1+2+3+4}=\frac{2}{4}, \frac{2+3+4}{1+2+3+4+5}=\frac{3}{5},\dots$$<p>因此<br>$$\begin{aligned}\frac{2}{1+2}\frac{2+3}{1+2+3}\frac{2+3+4}{1+2+3+4}\dots&=\frac{2}{18}\frac{2}{4}\frac{3}{5}\frac{4}{7}\dots \frac{(n+2)(n-1)}{2}\\&=\frac{1}{9}\frac{6}{n(n-1)}\frac{(n+2)(n-1)}{2}\\&=\frac{1}{3}\frac{n+2}{n-1}\end{aligned}$$</p><p>因此极限为 $\frac{1}{3}$ .</p><h2 id="6"><a href="#6" class="headerlink" title="(6)"></a>(6)</h2><p>,$(1-x)(1+x)=(1-x^2),(1-x^2)(1+x^2)=(1-x^4)\dots$ 直接滚雪球. </p><h1 id="5-2"><a href="#5-2" class="headerlink" title="5"></a>5</h1><h2 id="1-3"><a href="#1-3" class="headerlink" title="(1)"></a>(1)</h2><p>令 $b=ka,(k\geqslant 1)$ , 那么就有</p>$$((1+k^n)a^n)^{1/n}=\sqrt[n]{1+k^n}a$$<p>由于 $k<\sqrt[n]{1+k^n}<\sqrt[n]{2k^n}=\sqrt[n]2k$ , 因此极限为 $ka=b$ .</p><h2 id="2-1"><a href="#2-1" class="headerlink" title="(2)"></a>(2)</h2><p>类似 (1) , 极限为 $\max(a_1,a_2,\dots,a_m)$ .</p><h1 id="6-1"><a href="#6-1" class="headerlink" title="6"></a>6</h1>$$\frac{na_n-1}{n}\leqslant\frac{[na_n]}{n}\leqslant\frac{na_n}{n}$$<p>易证.</p><h1 id="7-1"><a href="#7-1" class="headerlink" title="7"></a>7</h1><p>存在 $N$ , 使得 $n>N$ 时, 有 $|a_n-a|<\epsilon$ . 因此就有</p>$$(a_1a_2\dots a_n)^{1/n}<(a_1a_2\dots a_{N}(a+\epsilon)^{n-N})^{1/n}=(a_1a_2\dots a_N)^{1/n}(a+\epsilon)^{1-\frac{N}{n}}$$<p>只需 $n$ 取足够大 , $\epsilon$ 取足够小即可小于任意给定正数.</p><h1 id="8"><a href="#8" class="headerlink" title="8"></a>8</h1><p>比较容易的就不写了.</p><h2 id="2-2"><a href="#2-2" class="headerlink" title="(2)"></a>(2)</h2><p>当 $a>1$ 时, 构造数列 $\{a_n\}=\{a,\frac{a+1}{a}, \frac{a+2}{a+1},\dots\}$ , 显然 $\lim_{n\to\infty}a_n=1$ . 于是</p>$$1<a^{1/n}<(a_1a_2\dots a_n)^{1/n}$$<p>又夹逼定则知极限为 1.</p><p>当 $a<1$ 时, 构造数列 $\{a_n\}=\{a,\frac{a-a/2}{a}, \frac{a-a/4}{a-a/2},\dots\}, (a_n=\frac{a-a/2^{n-1}}{a-a/2^{n-2}}, n>1)$ , 同样流程 (夹逼) .</p><h2 id="3-4"><a href="#3-4" class="headerlink" title="(3)"></a>(3)</h2><p>构造数列 $\{a_n\}=\{1,\frac{2}{1}, \frac{3}{2},\dots\}$ , 显然 $\lim_{n\to\infty}a_n=1$ . 于是</p>$$n^{1/n}=(a_1a_2\dots a_n)^{1/n}$$<p>易证.</p><h1 id="9"><a href="#9" class="headerlink" title="9"></a>9</h1><p>运用例 4 可证.</p><h1 id="10"><a href="#10" class="headerlink" title="10"></a>10</h1><p>极限的四则运算.</p><h1 id="11"><a href="#11" class="headerlink" title="11"></a>11</h1><p>整理并利用例 4 可证.</p><h1 id="12"><a href="#12" class="headerlink" title="12"></a>12</h1><p>这题想了很久利用例 4 来证, 结果是用夹逼… (说实话我觉得好多夹逼都有点奇技淫巧)</p>$$\frac{\frac{k}{n^2}}{2\sqrt{1+\frac{k}{n^2}}}<\sqrt{1+\frac{k}{n^2}}-1=\frac{\frac{k}{n^2}}{\sqrt{1+\frac{k}{n^2}}+1}<\frac{k}{2n^2}$$<p>易得 $\lim_{n\to\infty}\sum_{k=1}^n\frac{k}{2n^2}=\frac{1}{4}$ .</p><p>而<br>$$\frac{\frac{k}{n^2}}{2\sqrt{1+\frac{k}{n^2}}}>\frac{\frac{k}{n^2}}{2\sqrt{1+\frac{1}{n}}}$$<br>因此<br>$$\lim_{n\to\infty}\sum_{k=1}^n\frac{\frac{k}{n^2}}{2\sqrt{1+\frac{k}{n^2}}}<\lim_{n\to\infty}\sum_{k=1}^n\frac{\frac{k}{n^2}}{2\sqrt{1+\frac{1}{n}}}=\lim_{n\to\infty}\frac{\sqrt{1+\frac{1}{n}}}{4}=\frac{1}{4}$$</p><p>因此极限为 $1/4$ .</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 数学分析 </category>
          
          <category> 数学分析教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 数学分析 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>一个问题</title>
      <link href="/math/other/a_problem/"/>
      <url>/math/other/a_problem/</url>
      
        <content type="html"><![CDATA[<h1 id="说在前面"><a href="#说在前面" class="headerlink" title="说在前面"></a>说在前面</h1><p>这个问题我还没有解决.</p><h1 id="题目"><a href="#题目" class="headerlink" title="题目"></a>题目</h1><p>已知平面向量 $v_1,v_2,v_3,\cdots,v_n$ 满足 $\sum_{i=1}^n|\vec{v_i}|=1$ . 若必存在若干个向量, 它们的和的模不小于 $k$ , 求 $k$ 的最大值.</p><p>原题如下</p><p><img src="1.jpg" alt=""></p><p>给出的解法虽然很精彩, 但是并不是最大值 (最少是没证明 $1/4$ 是最大值) . 于是就产生了这个求最大值的想法.</p><h1 id="猜想"><a href="#猜想" class="headerlink" title="猜想"></a>猜想</h1><p>我猜测结果是 $1/\pi$ .</p><h1 id="一些结果"><a href="#一些结果" class="headerlink" title="一些结果"></a>一些结果</h1><p>令 $P\subseteq \{1,2,3,\cdots,n\}$ , 且满足 $\left|\sum_{i\in P}v_i\right|$ 为所有向量相加的组合中能取到的最大值, 我们来考虑如何选取得到这个向量的集合. 设一个向量 $\vec{w}\not=\vec 0$ , 如何取向量并相加才能使得这个相加后的向量在 $\vec{w}$ 上的投影的模最大? 很显然, 取一条过原点的直线, 然后分别将直线的两边的所有向量相加 (在直线上的向量相加与否并不影响这个模的取值), 得到的两个向量必有一个在 $\vec{w}$ 上的投影的模是最大的, 但是这样取到的最大的模必然小于等于 $\left|\sum_{i\in P}v_i\right|$ (当 $\vec w$ 与 $\sum_{i\in P}v_i$ 的方向相同或相反时取等号). 于是, 向量 $\left|\sum_{i\in P}v_i\right|$ 必然是某条过原点的直线的一边的所有向量的和的模.</p><p><img src="2.png" alt=""></p><p>因此, 我们就可以利用这个结果来设计一个较低复杂度 $O(n)$ 的程序, 来使我的猜想更加可信.</p><h1 id="代码验证"><a href="#代码验证" class="headerlink" title="代码验证"></a>代码验证</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line">rand = <span class="keyword">lambda</span> num, t: np.random.rand(num, t) - <span class="number">0.5</span></span><br><span class="line">sin = np.sin</span><br><span class="line">cos = np.cos</span><br><span class="line">arcsin = np.arcsin</span><br><span class="line">arccos = np.arccos</span><br><span class="line">sqrt = np.sqrt</span><br><span class="line">pi = np.pi</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">angle</span>(<span class="params">x0, y0</span>):</span><br><span class="line">    x = x0 / sqrt(x0**<span class="number">2</span> + y0**<span class="number">2</span>)</span><br><span class="line">    y = y0 / sqrt(x0**<span class="number">2</span> + y0**<span class="number">2</span>)</span><br><span class="line">    efactor = <span class="number">0.01</span></span><br><span class="line">    <span class="keyword">if</span> y &gt; <span class="number">0</span>:</span><br><span class="line">        theta = arcsin(y)</span><br><span class="line">        <span class="keyword">if</span> cos(theta) - x &lt; efactor:</span><br><span class="line">            <span class="keyword">return</span> theta</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span> pi - theta</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        theta = arcsin(y) + <span class="number">2</span>*pi</span><br><span class="line">        <span class="keyword">if</span> cos(theta) - x &lt; efactor:</span><br><span class="line">            <span class="keyword">return</span> theta</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span> <span class="number">3</span>*pi - theta</span><br><span class="line">        </span><br><span class="line"><span class="keyword">def</span> <span class="title function_">angle</span>(<span class="params">x0, y0</span>):</span><br><span class="line">    x = x0 / sqrt(x0**<span class="number">2</span> + y0**<span class="number">2</span>)</span><br><span class="line">    y = y0 / sqrt(x0**<span class="number">2</span> + y0**<span class="number">2</span>)</span><br><span class="line">    efactor = <span class="number">0.01</span></span><br><span class="line">    <span class="keyword">if</span> y &gt; <span class="number">0</span>:</span><br><span class="line">        theta = arcsin(y)</span><br><span class="line">        <span class="keyword">if</span> cos(theta) - x &lt; efactor:</span><br><span class="line">            <span class="keyword">return</span> theta</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span> pi - theta</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        theta = arcsin(y) + <span class="number">2</span>*pi</span><br><span class="line">        <span class="keyword">if</span> cos(theta) - x &lt; efactor:</span><br><span class="line">            <span class="keyword">return</span> theta</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">return</span> <span class="number">3</span>*pi - theta</span><br><span class="line"><span class="keyword">def</span> <span class="title function_">rand_vec</span>(<span class="params">num</span>):</span><br><span class="line">    res = []</span><br><span class="line">    <span class="keyword">for</span> x, y <span class="keyword">in</span> rand(num, <span class="number">2</span>):</span><br><span class="line">        res.append(Vector(x, y))</span><br><span class="line">    <span class="keyword">return</span> res</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">init_vec</span>(<span class="params">num</span>):</span><br><span class="line">    vec_arr = rand_vec(num)</span><br><span class="line">    res = []</span><br><span class="line">    length = <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> vec <span class="keyword">in</span> vec_arr:</span><br><span class="line">        length += vec.length()</span><br><span class="line">    <span class="keyword">for</span> vec <span class="keyword">in</span> vec_arr:</span><br><span class="line">        res.append(Vector(vec.x / length, vec.y / length))</span><br><span class="line">    <span class="keyword">return</span> res</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">init_sum_vec_list</span>(<span class="params">MAXNUM = <span class="number">100</span></span>):</span><br><span class="line">    vec_list = init_vec(MAXNUM)</span><br><span class="line">    vec_list.sort(key=(<span class="keyword">lambda</span> vec: vec.angle))</span><br><span class="line">    sum_vec = vec_list[-<span class="number">1</span>]</span><br><span class="line">    sum_vec_list = []</span><br><span class="line">    bedex = <span class="number">0</span></span><br><span class="line">    edex = <span class="number">0</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> bdex <span class="keyword">in</span> <span class="built_in">range</span>(MAXNUM):</span><br><span class="line">        sum_vec -= vec_list[bdex - <span class="number">1</span>]</span><br><span class="line">        bedex = edex</span><br><span class="line">        <span class="keyword">for</span> edex <span class="keyword">in</span> <span class="built_in">range</span>(bedex, bedex + MAXNUM):</span><br><span class="line">            sum_vec += vec_list[edex % MAXNUM]</span><br><span class="line">            <span class="keyword">if</span> edex + <span class="number">1</span> &lt; MAXNUM:</span><br><span class="line">                <span class="keyword">if</span> vec_list[(edex + <span class="number">1</span>) % MAXNUM].angle - vec_list[bdex % MAXNUM].angle &gt; pi:</span><br><span class="line">                    sum_vec_list.append(sum_vec)</span><br><span class="line">                    <span class="keyword">break</span></span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                <span class="keyword">if</span> vec_list[(edex + <span class="number">1</span>) % MAXNUM].angle - vec_list[bdex % MAXNUM].angle &gt; -pi:</span><br><span class="line">                    sum_vec_list.append(sum_vec)</span><br><span class="line">                    <span class="keyword">break</span></span><br><span class="line">    <span class="keyword">return</span> sum_vec_list</span><br><span class="line"></span><br><span class="line">res_len = []</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">100</span>):</span><br><span class="line">    res_len.append(<span class="built_in">max</span>(init_sum_vec_list()).length())</span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">min</span>(res_len))</span><br></pre></td></tr></table></figure><p>代码没有注释是因为<del>优秀的代码不需要注释</del>我太懒了. 最后结果算出来基本上都大于 0.5, 想来可能是简单的等概率随机分布并不适合生成随机向量, 以后有时间再优化一下吧.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 其他 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>一个不等式</title>
      <link href="/math/other/an_inequality/"/>
      <url>/math/other/an_inequality/</url>
      
        <content type="html"><![CDATA[<p> 发现一个不等式, 因此记录一下 (应该是正确的…吧)<br>$$\sum_{i=1}^nk_i\sin(\theta_i)\geqslant\frac{\sqrt{2}}{2}\sin\left(\frac{\sum_{i=1}^nk_i\theta_i}{\sum_{i=1}^nk_i}\right)\sum_{i=1}^n k_i,\qquad \theta_i\in[0,\frac{\pi}{2}]$$<br>对于 $\cos$ 函数也有类似的结果.</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 其他 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 不等式 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>复数乘法与旋转</title>
      <link href="/math/other/complex_multiplication_and_rotation/"/>
      <url>/math/other/complex_multiplication_and_rotation/</url>
      
        <content type="html"><![CDATA[<h1 id="旋转公式"><a href="#旋转公式" class="headerlink" title="旋转公式"></a>旋转公式</h1><p>对于一个点 $P_0(x_0,y_0)$ 来说 , $P_1(x_0\cos\theta-y_0\sin\theta,x_0\sin\theta+y_0\cos\theta)$ 是 $P_0$ 旋转 $\theta$ 角度 (顺时针) 后对应的点. 这个公式的推导是很简单的, 但是它这样的形式似乎并没有什么显而易见的规律. 但是, 复数乘法可以给我们一些启示.</p><h1 id="复数乘法的几何意义"><a href="#复数乘法的几何意义" class="headerlink" title="复数乘法的几何意义"></a>复数乘法的几何意义</h1><p>设 $z_1=a_1+b_1\mathrm{i}, z_2=a_2+b_2\mathrm{i}$ , 那么就有 $z_1z_2=a_1a_2-b_1b_2+(a_1b_2+a_2b_1)\mathrm{i}$ . 如果还看不出什么, 就进行三角换元, 令 $a_1=k_1\cos\alpha, b_1=k_1\sin\alpha, a_2=k_2\cos\beta,b_2=k_2\sin\beta$ , 那么就有 $k_1=|z_1|, k_2=|z_2|$ , 于是<br>$$\begin{aligned}z_1z_2&=a_1a_2-b_1b_2+(a_1b_2+a_2b_1)\mathrm{i}\\&=k_1k_2(\cos\alpha\cos\beta-\sin\alpha\cos\beta)+k_1k_2(\cos\alpha\sin\beta+\cos\beta\sin\alpha)\mathrm{i}\\&=k_1k_2\cos(\alpha+\beta)+k_1k_2\sin(\alpha+\beta)\mathrm{i}\end{aligned}$$<br>现在就很显然了, 复数乘法的几何意义在于, 若复数 $z_1$ 的长度为 $k_1$ , 角度为 $\alpha$ , $z_2$ 的长度为 $k_2$ , 角度为 $\beta$ , 那么它们乘积的结果的复数的长度即为 $k_1k_2$ , 角度为 $\alpha+\beta$ .</p><h1 id="旋转公式推导"><a href="#旋转公式推导" class="headerlink" title="旋转公式推导"></a>旋转公式推导</h1><p>这就启示我们使用一个特殊的复数即 $z'=\cos\theta+\sin\theta\mathrm{i}$ ,这个复数的特殊之处在于它的角度为 $\theta$ , 长度为 $1$ . 用这个复数去乘其他复数, 就可以起到旋转 $\theta$ 角的作用. 于是对于一个点 $P_0(x_0,y_0)$ , 我们将其表示在复平面即 $z_0=x_0+y_0\mathrm{i}$ , 然后就可以得到 $z_1=z_0z'=x_0\cos\theta-y_0\sin\theta+x_0\sin\theta+y_0\cos\theta\mathrm{i}$ , 再将 $z_1$ 重新用直角坐标系表达, 最终得到 $P_1(x_0\cos\theta-y_0\sin\theta,x_0\sin\theta+y_0\cos\theta)$ .</p><h1 id="Geogebra-演示"><a href="#Geogebra-演示" class="headerlink" title="Geogebra 演示"></a>Geogebra 演示</h1><p>我发现我越来越喜欢用 GGB 了…</p><iframe frameborder="no"title="复数乘法几何意义" src="https://www.geogebra.org/material/iframe/id/txdvzmv6/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/true/rc/false/ld/false/sdz/true/ctl/false/" width=100% height="480px"></iframe>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 其他 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 复数 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>在网页中嵌入 GGB 最简单的方法</title>
      <link href="/scribble/ggb_insert/"/>
      <url>/scribble/ggb_insert/</url>
      
        <content type="html"><![CDATA[<p>一开始我是想要用官网的 js 解析 <code>.ggb</code> 文件的, 结果发现速度太慢还一堆问题… 最后发现直接分享然后 iframe 引用才是最快最方便的.</p><p>打开 GeoGebra , 然后在制作好的图中点击分享 (如下图)</p><p><img src="1.png" alt=""></p><p>然后就会进入登录界面, 有账号直接登录, 没有就注册.</p><p>接着进入 <a href="https://www.geogebra.org">GGB 官网</a> , 登录并进入个人主页</p><p><img src="2.png" alt=""></p><p>接着看 <code>资源</code> 中是否有你分享的图, 如果没有, 重新回到 GGB 再次尝试分享.</p><p>然后点击进入你要嵌入到网页的资源, 查看该资源 ID .</p><p><img src="3.png" alt=""></p><p>记下 ID, 然后就可以在需要展示 GGB 的地方用 iframe 引用了</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;iframe </span><br><span class="line">frameborder=&quot;no&quot;</span><br><span class="line">title=&quot;随便写&quot; </span><br><span class="line">src=&quot;https://www.geogebra.org/material/iframe/id/刚刚记下的 ID/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/true/rc/false/ld/false/sdz/true/ctl/false/&quot; </span><br><span class="line">width=100% </span><br><span class="line">height=&quot;480px&quot;&gt;</span><br><span class="line">&lt;/iframe&gt;</span><br></pre></td></tr></table></figure><p>比如</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;iframe </span><br><span class="line">frameborder=&quot;no&quot;</span><br><span class="line">title=&quot;垂点抛物线&quot; src=&quot;https://www.geogebra.org/material/iframe/id/myysrpxf/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/true/rc/false/ld/false/sdz/true/ctl/false/&quot; </span><br><span class="line">width=100% </span><br><span class="line">height=&quot;480px&quot;&gt;</span><br><span class="line">&lt;/iframe&gt;</span><br></pre></td></tr></table></figure><p>就会有这样的效果:</p><iframe frameborder="no"title="垂点抛物线" src="https://www.geogebra.org/material/iframe/id/myysrpxf/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/true/rc/false/ld/false/sdz/true/ctl/false/" width=100% height="480px"></iframe>]]></content>
      
      
      <categories>
          
          <category> 杂文 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 教程 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>圆锥曲线二级结论</title>
      <link href="/math/other/conical_section_conclusion/"/>
      <url>/math/other/conical_section_conclusion/</url>
      
        <content type="html"><![CDATA[<p>最近推了一个圆锥曲线的结论, 因此记录一下.</p><p>先上结论:</p><p>若有圆锥曲线 $\Gamma\colon\frac{x^2}{A}+\frac{y^2}{B}=1$ ,$A$ 与 $B$ 不同时取负数 (这样就同时代表了双曲线和椭圆) , 那么对于一个在该圆锥曲线上的点 $P_1(x_1,y_1)$ 来说, 存在一个点 $P_2(\frac{A-B}{A+B}x_1,\frac{B-A}{A+B}y_1)$ . 若作直线 $l_1, l_2$ 过点 $P_0$ 且相互垂直, 那么这两条直线与该圆锥曲线异于 $P_0$ 的两个交点 $M,N$ 的连线恒过点 $P_1$ .</p><iframe frameborder="no"title="垂点椭圆双曲线" src="https://www.geogebra.org/material/iframe/id/zkwudkkg/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/true/rc/false/ld/false/sdz/true/ctl/false/" width=100% height="480px"></iframe><p>对于形如 $y^2=2px$ 的抛物线也有类似结论, 不过 $P_2$ 为 $(2p+x_1,-y_1)$.</p><iframe frameborder="no"title="垂点抛物线" src="https://www.geogebra.org/material/iframe/id/myysrpxf/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/true/rc/false/ld/false/sdz/true/ctl/false/" width=100% height="480px"></iframe><h1 id="如何得到"><a href="#如何得到" class="headerlink" title="如何得到"></a>如何得到</h1><p>我们以椭圆为例.</p><p>设椭圆 $\Gamma\colon\frac{x^2}{a^2}+\frac{y^2}{b^2}=1$ , 点 $P_2 (x_2, y_2)$ , 直线 $l_{MN}\colon y-y_2=k(x-x_2)$  联立可得<br>$$(a^2k^2+b^2)x^2+2a^2k(y_2-kx_2)x+a^2((kx_2-y_2)^2-b^2)=0$$<br>设直线 $l_{MN}$ 与曲线交点为 $M(x_m,y_m),N(x_n,y_n)$ 根据韦达定理可得<br>$$\begin{aligned}x_mx_n=\frac{a^2((kx_2-y_2)^2-b^2)}{a^2k^2+b^2},x_m+x_n=\frac{2a^2k(kx_2-y_2)}{a^2k^2+b^2}\\y_my_n=\frac{b^2((kx_2-y_2)^2-a^2k^2)}{a^2k^2+b^2},y_m+y_n=\frac{2b^2(y_2-kx_2)}{a^2k^2+b^2}\end{aligned}$$<br>同时设 $P_1(x_1,y_1)$ ,有<br>$$\begin{aligned}(x_m-x_1,y_m,y_1)\cdot(x_n-x_2,y_n-y_2)&=0\\x_nx_m-x_1(x_m+x_n)+{x_2}^2+y_ny_m-y_1(y_m+y_n)+{y_2}^2&=0\end{aligned}$$<br>代入得<br>$$\begin{aligned}a^2((kx_2-y_2)^2-b^2)-2x_1a^2k(kx_2-y_2)+b^2((kx_2-y_2)^2-a^2k^2)-2y_1b^2(y_2-kx_2)\\=-({x_1}^2+{y_1}^2)(a^2k^2+b^2)\end{aligned}$$<br>即上式对于任意 $k$ 成立. 凭借这个复杂的等式我们已可以 (理论上) 求出 $P_1$ 与 $P_2$ 的关系, 但是这样太困难了, 我们稍稍取下巧, 只需取两个 $k$ 值就行, 很容易想到 $k=0$ 与 $k\to\infty$ (即令 $1/ \to 0$),</p><p>令 $k=0$ 得<br>$$a^2({y_2}^2-b^2)+b^2{y_2}^2-2b^2y_1y_2=-b^2({x_1}^2+{y_1}^2)$$<br>令 $k\to\infty$ 得<br>$$b^2({x_2}^2-a^2)+a^2{x_2}^2-2a^2x_1x_2=-a^2({x_1}^2+{y_1}^2)$$<br>这就好多了. 但是我们发现, 已知 $x_2,y_2$ 去求 $x_1,y_1$ 有困难, 但是我们稍稍整理一下就会发现<br>$$(a^2+b^2)\cdot {y_2}^2 -2b^2y_1\cdot y_2 + b^2({x_1}^2+{y_1}^2)-a^2b^2=0\qquad(k=0)$$<br>而这恰好是一个以 $x_1,y_1$ 作为参数的关于 $y_2$ 的二元一次方程, 那么就让我们把 $x_1,y_1$ 看成已知, 而 $x_2,y_2$ 看成未知的吧.</p><p>用求根公式可得<br>$$y_2=\frac{2b^2y_1\pm\sqrt{4b^2{y_1}^2-4(a^2+b^2)(b^2({x_1}^2+{y_1}^2)-a^2b^2)}}{2(a^2+b^2)}$$<br>$x_2$ 的求法也是同理 (利用 $k\to \infty$ 的情况) , 这样我们就得出了结果.</p><p>等会… 这个公式和上面那个完全不一样啊! 而且还带 $\pm$ , 显然有一个解得舍去的啊! 事实上, 最上面那个公式只是这个公式的简化, 运用了到目前还没用过的最重要的等式, 即<br>$$\begin{aligned}\frac{{x_1}^2}{a^2}+\frac{{y_1}^2}{b^2}&=1\\a^2-{x_1}^2&=\frac{a^2}{b^2}{y_1}^2\end{aligned}$$因此有$$\begin{aligned}y_2&=\frac{2b^2y_1\pm\sqrt{4b^2{y_1}^2-4(a^2+b^2)(b^2({x_1}^2+{y_1}^2)-a^2b^2)}}{2(a^2+b^2)}\\&=\frac{b^2y_1\pm\sqrt{b^2(a^2-{x_1}^2)(a^2+b^2)-a^2b^2{y_1}^2}}{a^2+b^2}\\&=\frac{b^2y_1\pm\sqrt{a^2{y_1}^2(a^2+b^2)-a^2b^2{y_1}^2}}{a^2+b^2}\\&=\frac{b^2y_1\pm a^2y_1}{a^2+b^2}\end{aligned}$$<br>取 $+$ 的不符合实际情况 $y_1=y_2$ , 于是就有<br>$$y_1=\frac{b^2-a^2}{a^2+b^2}y_2$$<br>同理得<br>$$x_1=\frac{a^2-b^2}{a^2+b^2}x_2$$<br>双曲线和椭圆公式类似, 可以用同样方法求得, 并且归入最上面说到的一整个结论.</p><p>但是抛物线和它们可不太一样, 难道要重新求一遍? 并不, 注意到抛物线是椭圆的一种极限. 设抛物线 $E\colon y^2=2px$ , 有<br>$$E\colon\lim_{n\to\infty} \frac{(x-np)^2}{n^2p^2}+\frac{y^2}{np^2}=1$$<br>利用上面求出的公式, 有<br>$$\begin{aligned}x_2&=\lim_{n\to\infty}np+(x-np)\frac{n^2p^2-np^2}{n^2p^2+np^2}\\&=\lim_{n\to\infty}np+(x-np)\frac{n-1}{n+1}\\&=\lim_{n\to\infty}\frac{n-1}{n+1}x+\frac{2np}{n+1}\\&=2p+x_1\end{aligned}$$</p><p>$y_2=-y_1$ 也是类似求法.</p><p>由上得到了全部结果.</p><h1 id="感想"><a href="#感想" class="headerlink" title="感想"></a>感想</h1><p>解析几何就一句话: 干就完事了!</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 其他 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 圆锥曲线 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>解决 MathJax 与 Hexo 冲突问题</title>
      <link href="/hexo/hexo_conflict_mathjax/"/>
      <url>/hexo/hexo_conflict_mathjax/</url>
      
        <content type="html"><![CDATA[<p>将 Hexo 升级到 5.0 后, 发现 MathJax 与 Hexo 仍然有冲突. 然而网上大部分的方法对 5.0 版本的 Hexo 都没有用.</p><p>摸索许久后, 找到了一个比较不错的方法解决该问题. 即在公式前后加上 <code>` 与 `</code>, 即</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">{%raw%}$$</span><br><span class="line">xxxxxx (公式内容)</span><br><span class="line">$${%endraw%}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>就可以完美解决.</p><p><del>这绝对不是水文.</del></p>]]></content>
      
      
      <categories>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Hexo </tag>
            
            <tag> 水文 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>DQN 算法</title>
      <link href="/ML/RL/papers_read/Model-Free_RL/Deep_Q-Learning/1/"/>
      <url>/ML/RL/papers_read/Model-Free_RL/Deep_Q-Learning/1/</url>
      
        <content type="html"><![CDATA[<p>论文原文: <a href="https://www.cs.toronto.edu/~vmnih/docs/dqn.pdf">Playing Atari with Deep Reinforcement Learning</a> .</p><p>DQN (Deep Q-Networks) 算法, 简单来说就是 Deep Learning + Q Learning.</p><h1 id="Q-Learning"><a href="#Q-Learning" class="headerlink" title="Q Learning"></a>Q Learning</h1><p>Q Learning 实际上是维护一个 $Q$ 值表, 这个表可以认为是状态 $s$ 与动作 $a$ 的一个函数 $Q(s,a)$ , 其输出表示在状态 $s$ 下采用动作 $a$ 所获得的期望回报. 通过查询 $Q$ 值表, 就可以找出在某个状态 $s_t$ 下的最佳动作 $a_t$ .  Q Learning 算法的要点就在于得到一个足够真实的 $Q$ 值表. 而 $Q$ 值表的更新, 则基于 Bellman 方程 (详情可见<a href="https://yunist.cn/ML/RL/primer/basic_concepts/">RL 基本概念</a>).</p><h1 id="DQN"><a href="#DQN" class="headerlink" title="DQN"></a>DQN</h1><p>DQN 的核心思想与 Q Learning 一样, 但区别就在于 $Q$ 函数. 在 Q Learning 中, $Q$ 函数是 $Q$ 值表, 也即一个个状态-动作对与期望回报的一一对应, 也就是离散的, 而在一些环境中 (比如 Atari 2600 games) 状态几乎是无穷多的, 根本不可能用 $Q$ 值表来容纳, 于是我们就用回归的方法来解决. 用神经网络 $Q(s,a\mid\theta)$ 来作为 $Q$ 函数从而代替 $Q$ 值表, 而这样的 $Q$ 函数的更新, 也同样基于 Bellman 方程.</p><h2 id="数据获取与处理"><a href="#数据获取与处理" class="headerlink" title="数据获取与处理"></a>数据获取与处理</h2><p>获取游戏内容的最后 4 帧而不是 1 帧, 目的在于将游戏的动态过程表现出来. $\phi$ 函数保证输入给卷积神经网络的数据的维度固定. 而伪代码中的 $\text{Set}\;s_t+1=s_t,a_t,x_{t+1}$ 使得历史数据得以运用, 这就是为什么论文中说 “每一步的数据都可以在许多次参数更新中起到作用 (Each  step  of experience  is  potentially  used  in  many  weight  updates) .” </p><p><img src="1.png" alt=""></p><h2 id="输出的优化处理"><a href="#输出的优化处理" class="headerlink" title="输出的优化处理"></a>输出的优化处理</h2><p>一般来说, $Q$ 函数是根据状态 $s$ 和动作 $a$ 输出一个值 $r$ , 但是如果在实际中这样设计的话, 如果有 $n$ 个动作, 就要对每个动作都计算一次 $r$ 来得出最佳动作, 也就是计算 $n$ 次 ($n$ 次神经网络的前向传播) . 这样的话, 每次获取 $r$ 的计算时间与动作的个数乘正比, 如果动作数量足够多, 那么算力消耗会很大. 论文中给出了一个更优化的结构, 也就是 $Q$ 函数只依赖与状态 $s$ , 而其输出是传统 $Q$ 函数所有动作的输出结果的一个 array, 这样就可以只计算一次, 得到最佳动作.</p><h1 id="疑问"><a href="#疑问" class="headerlink" title="疑问"></a>疑问</h1><p>现在还有的疑问就是 $\phi$ 函数究竟要怎样实现呢? 希望大佬们不吝赐教.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 入门 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 论文精读 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>为你的博客添加一个播放器</title>
      <link href="/scribble/player_in_blog/"/>
      <url>/scribble/player_in_blog/</url>
      
        <content type="html"><![CDATA[<p>话不多说, 直接开整.</p><h1 id="播放器文件下载并引入"><a href="#播放器文件下载并引入" class="headerlink" title="播放器文件下载并引入"></a>播放器文件下载并引入</h1><p>地址在 <a href="https://github.com/cnyist/player">https://github.com/cnyist/player</a> .</p><p>下载下来后放入 <code>source</code> 目录中 (主题或 Hexo 自带的皆可) , 然后用 iframe 引入 <code>index.html</code> 文件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">iframe(name=&quot;player&quot;, id=&quot;player&quot;, src=&quot;/player/&quot;, frameborder=&quot;0&quot;, onload=&quot;this.width=player.jp_container_N.scrollWidth;{%raw%}$(&#x27;.songlist__item&#x27;).each(function()&#123;generate(${%endraw%}(this).attr(&#x27;id&#x27;))&#125;);&quot;, style=&quot;z-index:100; position:fixed; left:0px; bottom:0px&quot;)</span><br></pre></td></tr></table></figure><p>以上代码建议插入到 <code>head</code> 标签中 (这是 PUG 格式, 其他格式可以自行更改). 然后你就可以看见你的博客里多了一个播放器.</p><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> musicList = [&#123;</span><br><span class="line">    <span class="attr">title</span>: <span class="string">&quot;Life Is Beautiful&quot;</span>,</span><br><span class="line">    <span class="attr">artist</span>: <span class="string">&quot;The Afters&quot;</span>,</span><br><span class="line">    <span class="attr">mp3</span>: <span class="string">&quot;https://cdn.jsdelivr.net/gh/cnyist/music@master/The%20Afters%20-%20Life%20Is%20Beautiful/The%20Afters%20-%20Life%20Is%20Beautiful.mp3&quot;</span>,</span><br><span class="line">    <span class="attr">poster</span>: <span class="string">&quot;https://cdn.jsdelivr.net/gh/cnyist/music@master/The%20Afters%20-%20Life%20Is%20Beautiful/The%20Afters%20-%20Life%20Is%20Beautiful.jpg&quot;</span></span><br><span class="line">&#125;, &#123;</span><br><span class="line">    <span class="attr">title</span>: <span class="string">&quot;Fire&quot;</span>,</span><br><span class="line">    <span class="attr">artist</span>: <span class="string">&quot;Said The Sky&quot;</span>,</span><br><span class="line">    <span class="attr">mp3</span>: <span class="string">&quot;http://music.163.com/song/media/outer/url?id=435289279.mp3&quot;</span>,</span><br><span class="line">    <span class="attr">poster</span>: <span class="string">&quot;http://p1.music.126.net/tg2zke_mrqwuOPlEIEUjGg==/18294773975127592.jpg?param=130y130&quot;</span></span><br><span class="line">&#125;];</span><br></pre></td></tr></table></figure><p>都很直白, 如果要增加歌曲或者更改就按照格式就好了.</p><h1 id="配套播放框"><a href="#配套播放框" class="headerlink" title="配套播放框"></a>配套播放框</h1><p>在需要播放框的页面的底部引入 <code>js/generate.js</code> 文件, 同时写上这段 js,</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">generate_all</span>()</span><br></pre></td></tr></table></figure><p>并且引入 CSS <code>css/player_box.css</code> . 然后在需要插入音乐的地方写上</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">li</span> <span class="attr">class</span>=<span class="string">&quot;song_item&quot;</span> <span class="attr">id</span>=<span class="string">&quot;歌曲编号&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br></pre></td></tr></table></figure><p>其中歌曲编号是以歌曲顺序编的, 第一首为 ‘song1’ , 第二首为 ‘song2’ … 依此类推. 要插入音乐必须在播放器里配置这个音乐.</p>]]></content>
      
      
      <categories>
          
          <category> 杂文 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 教程 </tag>
            
            <tag> Blog </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>π 为什么会等于四</title>
      <link href="/math/other/why_pi_not_4/"/>
      <url>/math/other/why_pi_not_4/</url>
      
        <content type="html"><![CDATA[<p><img src="1.jpg" alt=""></p><p>我是在差不多三年前看到过这张图的. 曾经对极限完全不了解的我, 简单的认为由于边长一直不变, 所以不能这么算. 前几天有个同学的问题突然又激发了我对这个问题的思考, 突然意识到了之前的我对这个问题理解的浅显, 弄明白了这样论证的问题所在以及<strong>它为什么看起来如此正确</strong>.</p><h1 id="为什么是错误的"><a href="#为什么是错误的" class="headerlink" title="为什么是错误的?"></a>为什么是错误的?</h1><p>首先, 我们自然知道 $\pi=3.1415926\cdots$ , 而上面的论证中不断的重复折叠所得到的周长, 最终都不会收敛于圆的周长 (一直等于 $4$) . 但是这里就会有人疑惑了: 为什么最终得到的 $4$ 不是圆的周长呢? 明明折到最后就是个圆呀? 而这, 其实源于我们对图中表述 <code>不断的重复</code> 和 <code>一个图形怎样才是圆形</code> 的理解的混乱所致.</p><h2 id="什么是不断的重复"><a href="#什么是不断的重复" class="headerlink" title="什么是不断的重复?"></a>什么是不断的重复?</h2><p>在数学中, 有一个对应的概念, 即为极限. 重复次数设为 $n$ , 然后 $\lim n\to\infty$ 就可以认为是不断的重复了.</p><h2 id="一个图形怎样才是圆形"><a href="#一个图形怎样才是圆形" class="headerlink" title="一个图形怎样才是圆形?"></a>一个图形怎样才是圆形?</h2><p>为了方便表述, 我们只考虑一个单位半圆 (半径为 $1$) 的圆弧</p><p><img src="2.png" alt=""></p><p>通过适当的建系, 可以通过一个函数来描述它, 我们用 $f(x)$ 来表示这个半圆. 现在, 我们列出两个关于判定某个图形 (该图形可以用函数表达, 该函数设为 $g(x)$) 是不是该半圆的两个指标:</p><ol><li>$g(x) = f(x)$</li><li>函数曲线的长度为 $\pi$ (即等于该半圆长度)</li></ol><p>可以看到, 指标 1 其实是一个充要条件, 而指标 2 只是一个必要条件, 不过这足以用来解释矛盾的产生了. 我们将第 $n$ 次折叠后的正方形的函数设为 $g_n(x)$ , 结合起对 <code>不断的重复</code> 的理解 (求极限) , 我们来分析一下两种观点:</p><ul><li><p>不断的重复后正方形最终折叠成一个半圆</p><p>事实上这种想法用数学语言解释其实就是认为, 不断重复后的正方形的表达其实是 (此时正方形必须斜放, 不然不会有函数表达式, 但是这只是为了方便, 并不影响最终结果)</p>$$  \lim_{n\to\infty} g_n(x)  $$<p>并且有</p>$$  \lim_{n\to\infty} g_n(x)=f(x)  $$<p>按照指标 1 自然可以认为最终就是得到一个半圆.</p></li><li><p>不断的重复后最终并不是半圆</p><p>我们让 $l(g_n(x))$ 表示 $g_n(x)$ 函数曲线的长度 . 那么有</p>$$  \lim_{n\to\infty}l(g_n(x))=4\not-\pi  $$<p>根据指标 1 就可以认为最终其实不是圆.</p></li></ul><p>因此不同的答案的原因在于指标选取不同.</p><h2 id="那为什么不能证明-π-4"><a href="#那为什么不能证明-π-4" class="headerlink" title="那为什么不能证明 π = 4 ?"></a>那为什么不能证明 π = 4 ?</h2><p>通过上述解释, 可能有的人仍然疑惑: 明明按照指标 1 自然可以认为最终就是得到一个半圆, 那为什么最终 $\pi\not=4$ ? 这种想法产生的原因其实就是对极限运算的顺序的随意调换导致的. 可以用一个不等式来表示<br>$$\lim_{x\to\infty}l(g_n(x))\not=l(\lim_{x\to\infty}g_n(x))$$<br>以第一种观点来计算, 最终算得折叠后的图形的长度为 $\lim_{x\to\infty}l(g_n(x))=\pi$ , 而以第二种观点来计算, 最终得到的长度为 $l(\lim_{x\to\infty}g_n(x))=4$ . 用人话说就是: <strong>第一种观点下最终图形是半圆, 周长是 $\pi$ , 第二种观点下最终图形不是半圆, 周长自然就不是 $\pi$ 而是 $4$ .</strong> 而有人将这两个情况混在一起, 以第一种观点来讨论最终的图形是不是圆, 然后却以第二种观点来计算这个图形的长度, 自然就会产生谬误, 这也是这个论证极具有迷惑性的原因. 并且, 由于人们通常认为数学问题只会有一个答案, 因此会自然 (不自觉) 的把两种解释结合起来. 当然 (严谨的) 数学问题只会有一个答案, 但是用自然语言描述的数学问题, 由于其不够严谨, 因此才会产生不同的解答 (特别是谈到极限这类问题时).</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 极限 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>强化学习类论文常用表达</title>
      <link href="/ML/RL/papers_read/RL_papers_word/"/>
      <url>/ML/RL/papers_read/RL_papers_word/</url>
      
        <content type="html"><![CDATA[<p>由于自己英文实在是差, 所以把一些经常在论文里见到的却不太认得的表达记下来. 许多数学概念都有维基百科的相关链接, 要进去得 FQ , 如果你的浏览器可以装插件, 建议使用<a href="https://a.newday.me/">集装箱</a>.</p><div class="table-container"><table><thead><tr><th style="text-align:center">表达</th><th style="text-align:center">词性</th><th style="text-align:center">意义</th></tr></thead><tbody><tr><td style="text-align:center"><a href="https://zh.wikipedia.org/zh-hans/%E6%A6%82%E7%8E%87%E5%88%86%E5%B8%83">probability distribution</a></td><td style="text-align:center">n.</td><td style="text-align:center">概率分布</td></tr><tr><td style="text-align:center">discounted</td><td style="text-align:center">adj.</td><td style="text-align:center">有折扣的</td></tr><tr><td style="text-align:center">finite</td><td style="text-align:center">n.</td><td style="text-align:center">有限的</td></tr><tr><td style="text-align:center">infinite-horizon</td><td style="text-align:center">n.</td><td style="text-align:center">无限时间跨度</td></tr><tr><td style="text-align:center">factor</td><td style="text-align:center">n.</td><td style="text-align:center">因子</td></tr><tr><td style="text-align:center">denote</td><td style="text-align:center">v.</td><td style="text-align:center">表示</td></tr><tr><td style="text-align:center">stochastic</td><td style="text-align:center">adj.</td><td style="text-align:center">随机的</td></tr><tr><td style="text-align:center">standard definitions</td><td style="text-align:center">n.</td><td style="text-align:center">标准定义</td></tr><tr><td style="text-align:center">unnormalized</td><td style="text-align:center">adj.</td><td style="text-align:center">非规范的</td></tr><tr><td style="text-align:center">frequency</td><td style="text-align:center">n.</td><td style="text-align:center">频率</td></tr><tr><td style="text-align:center">notation</td><td style="text-align:center">n.</td><td style="text-align:center">符号</td></tr><tr><td style="text-align:center">imply</td><td style="text-align:center">v.</td><td style="text-align:center">暗示</td></tr><tr><td style="text-align:center">nonnegative</td><td style="text-align:center">adj.</td><td style="text-align:center">非负的</td></tr><tr><td style="text-align:center">guarantee</td><td style="text-align:center">v.</td><td style="text-align:center">保证</td></tr><tr><td style="text-align:center">constant</td><td style="text-align:center">adj.</td><td style="text-align:center">不变的</td></tr><tr><td style="text-align:center">deterministic</td><td style="text-align:center">adj.</td><td style="text-align:center">决定性</td></tr><tr><td style="text-align:center">nonzero</td><td style="text-align:center">adj.</td><td style="text-align:center">非零的</td></tr><tr><td style="text-align:center">algorithm</td><td style="text-align:center">n.</td><td style="text-align:center">算法</td></tr><tr><td style="text-align:center"><a href="https://zh.wikipedia.org/zh-cn/%E6%A5%B5%E9%99%90_%28%E6%95%B8%E5%88%97%29">converge</a></td><td style="text-align:center">v.</td><td style="text-align:center">收敛</td></tr><tr><td style="text-align:center">dependency</td><td style="text-align:center">n.</td><td style="text-align:center">依赖性</td></tr><tr><td style="text-align:center">sufficiently</td><td style="text-align:center">adv.</td><td style="text-align:center">充分地</td></tr><tr><td style="text-align:center">scheme</td><td style="text-align:center">n.</td><td style="text-align:center">方案</td></tr><tr><td style="text-align:center">mixture</td><td style="text-align:center">n.</td><td style="text-align:center">结合体</td></tr><tr><td style="text-align:center">derive</td><td style="text-align:center">n.</td><td style="text-align:center">推导</td></tr><tr><td style="text-align:center">modify</td><td style="text-align:center">v.</td><td style="text-align:center">改良</td></tr><tr><td style="text-align:center">restrictive</td><td style="text-align:center">adj.</td><td style="text-align:center">限制的</td></tr><tr><td style="text-align:center">stochastic</td><td style="text-align:center">adj.</td><td style="text-align:center">随机的</td></tr><tr><td style="text-align:center">typically</td><td style="text-align:center">adv.</td><td style="text-align:center">通常</td></tr><tr><td style="text-align:center"><a href="https://zh.wikipedia.org/zh-hans/%E5%8F%AF%E5%BE%AE%E5%87%BD%E6%95%B0">differentiable function</a></td><td style="text-align:center">n.</td><td style="text-align:center">可微函数</td></tr><tr><td style="text-align:center">monotonic</td><td style="text-align:center">adj.</td><td style="text-align:center">单调的</td></tr><tr><td style="text-align:center">conservative</td><td style="text-align:center">adj.</td><td style="text-align:center">保守的</td></tr><tr><td style="text-align:center">crucial</td><td style="text-align:center">adj.</td><td style="text-align:center">至关重要的</td></tr><tr><td style="text-align:center">variation</td><td style="text-align:center">n.</td><td style="text-align:center">变化</td></tr><tr><td style="text-align:center"><a href="https://zh.wikipedia.org/zh-hans/%E6%95%A3%E5%BA%A6">divergence</a></td><td style="text-align:center">n.</td><td style="text-align:center">散度</td></tr><tr><td style="text-align:center">discrete</td><td style="text-align:center">adj.</td><td style="text-align:center">离散的</td></tr><tr><td style="text-align:center">theorem</td><td style="text-align:center">n.</td><td style="text-align:center">定理</td></tr><tr><td style="text-align:center">bound</td><td style="text-align:center">n.</td><td style="text-align:center">边界, 范围</td></tr><tr><td style="text-align:center">appendix</td><td style="text-align:center">n.</td><td style="text-align:center">附录</td></tr><tr><td style="text-align:center"><a href="https://zh.wikipedia.org/wiki/%E8%80%A6%E5%90%88_%28%E6%A6%82%E7%8E%87%29">couple</a></td><td style="text-align:center">v.</td><td style="text-align:center">耦合</td></tr><tr><td style="text-align:center"><a href="https://zh.wikipedia.org/zh-hans/%E6%91%84%E5%8A%A8%E7%90%86%E8%AE%BA">perturbation theory</a></td><td style="text-align:center">n.</td><td style="text-align:center">摄动理论</td></tr><tr><td style="text-align:center">evaluation</td><td style="text-align:center">n.</td><td style="text-align:center">评估</td></tr><tr><td style="text-align:center">evaluate</td><td style="text-align:center">v.</td><td style="text-align:center">对…评价</td></tr><tr><td style="text-align:center">constrained</td><td style="text-align:center">adj.</td><td style="text-align:center">有约束的</td></tr><tr><td style="text-align:center">terminology</td><td style="text-align:center">n.</td><td style="text-align:center">术语</td></tr><tr><td style="text-align:center">surrogate</td><td style="text-align:center">adj.</td><td style="text-align:center">替代的</td></tr><tr><td style="text-align:center">descent</td><td style="text-align:center">n.</td><td style="text-align:center">下降</td></tr><tr><td style="text-align:center">approximation</td><td style="text-align:center">n.</td><td style="text-align:center">近似值</td></tr><tr><td style="text-align:center">parameterized</td><td style="text-align:center">adj.</td><td style="text-align:center">参数化的</td></tr><tr><td style="text-align:center">parameterization</td><td style="text-align:center">n.</td><td style="text-align:center">参数</td></tr><tr><td style="text-align:center">practical</td><td style="text-align:center">adj.</td><td style="text-align:center">可行的</td></tr><tr><td style="text-align:center">foundation</td><td style="text-align:center">n.</td><td style="text-align:center">基础</td></tr><tr><td style="text-align:center">arbitrary</td><td style="text-align:center">adj.</td><td style="text-align:center">任意的</td></tr><tr><td style="text-align:center">overload</td><td style="text-align:center">v.</td><td style="text-align:center">重载</td></tr><tr><td style="text-align:center">preceding</td><td style="text-align:center">adj.</td><td style="text-align:center">上述的</td></tr><tr><td style="text-align:center">equality</td><td style="text-align:center">n.</td><td style="text-align:center">等式</td></tr><tr><td style="text-align:center">penalty coefficient</td><td style="text-align:center">n.</td><td style="text-align:center">惩罚系数</td></tr><tr><td style="text-align:center">robust</td><td style="text-align:center">adj.</td><td style="text-align:center">强健的</td></tr><tr><td style="text-align:center">constraint</td><td style="text-align:center">n.</td><td style="text-align:center">约束</td></tr><tr><td style="text-align:center">impose</td><td style="text-align:center">v.</td><td style="text-align:center">施加</td></tr><tr><td style="text-align:center">motivate</td><td style="text-align:center">v.</td><td style="text-align:center">激励</td></tr><tr><td style="text-align:center">impractical</td><td style="text-align:center">adj.</td><td style="text-align:center">不明智的</td></tr><tr><td style="text-align:center">heuristic</td><td style="text-align:center">adj.</td><td style="text-align:center">启发式</td></tr><tr><td style="text-align:center">perspective</td><td style="text-align:center">n.</td><td style="text-align:center">观点</td></tr><tr><td style="text-align:center">demonstrate</td><td style="text-align:center">v.</td><td style="text-align:center">表明; 证明</td></tr><tr><td style="text-align:center"><a href="https://zh.wikipedia.org/zh-cn/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C">convolutional neural network</a></td><td style="text-align:center">n.</td><td style="text-align:center">卷积神经网络</td></tr></tbody></table></div>]]></content>
      
      
      <categories>
          
          <category> 杂文 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 英语 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 论文 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>理解皮亚诺公理第五条</title>
      <link href="/math/other/Peano_fifth_axiom/"/>
      <url>/math/other/Peano_fifth_axiom/</url>
      
        <content type="html"><![CDATA[<p>先上皮亚诺公理:</p><blockquote><ol><li>0 是<a href="https://zh.wikipedia.org/wiki/%E8%87%AA%E7%84%B6%E6%95%B0">自然数</a>；</li><li>每一个确定的自然数 <em>a</em>，都有一个确定的后继数 <em>a’</em>，<em>a’</em> 也是自然数；</li><li>对于每个自然数<em>b</em>、<em>c</em>，<em>b</em> = <em>c</em> 当且仅当 <em>b</em> 的后继数 = <em>c</em> 的后继数；</li><li>0 不是任何自然数的后继数；</li><li>任意关于自然数的命题，如果证明：它对自然数 0 是真的，且假定它对自然数 <em>a</em> 为真时，可以证明对 <em>a’</em>  也真。那么，命题对所有自然数都真。</li></ol></blockquote><p>第五条公理事实上保证了数学归纳法的正确性. 但是看到这里也许就会有些疑惑, 数学归纳法的成立是自然的呀? 为什么还需要一个第五公理?  对于自然数 $0$ 成立, 并且可以从 $a$ 正确推出 $a'$ 成立, 不就能从 $0$ 开始一直推然后遍历整个自然数集么?</p><p>但事实上并非如此, 我们之所以会认为 “能从 $0$ 开始一直推然后遍历整个自然数集” 是因为我们被现有的自然数集的概念束缚住了, 认为某个数 $a$ 一定能由 $0$ 一直取后继数得到. 但是我们仔细查看公理, <strong>并没有说明 (事实上也无法证明) 一个自然数一定可以由 $0$ 一直取后继数得到</strong>. 并且虽然公理 4 说明了 $0$ 不是任何自然数的后继数, 但是这<strong>并不代表自然数中只有 $0$ 不是任何自然数的后继数</strong>, 我们假设 $a$ 是自然数,  $a\not =0$ , 并且 $a$ 不是任何自然数的后继数, 事实上 <strong>$a$ 的存在并没有违反任意一条公理</strong>, 但是由于其不是任何自然数的后继数, 自然也就无法由 $0$ 一直取后继数来得到, 也就是说如果没有第五公理, 即使能够证明某个命题 “对自然数 0 是真的，且假定它对自然数 <em>a</em> 为真时，可以证明对 <em>a’</em>  也真。” 也不能推出该命题对于 $a$ 是真的. 因此第五公理的目的就是为了确保数学归纳法对于类似 $a$ 这样的数也可以成立. 当然, 就算整个自然数中只有 $0$ 不是自然数的后继数, 仍然可以存在自然数 $a\not=0$ 且 $a$ 不能由 $0$ 一直取后继数得到, 因为这并不违反公理.</p><p>例如 (下标只是一种记号) :<br>$$0\rightarrow1\rightarrow2\rightarrow3\rightarrow4\rightarrow\cdots$$<br>与<br>$$\cdots \rightarrow a_{-4}\rightarrow a_{-3}\rightarrow a_{-2}\rightarrow a_{-1}\rightarrow a_0\rightarrow a_1\rightarrow a_2\rightarrow a_3\rightarrow a_4\rightarrow\cdots$$<br>这两条链式结构之间没有相同元素 (显然是符合皮亚诺公理的) . 然而如果没有第五公理, 从 $0$ 开始的数学归纳法显然不会对下面那条链成立 (虽然对上面那条链成立).</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 其他 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 公理 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Gym 中的 gym.spaces</title>
      <link href="/ML/RL/spinningup/gym_spaces/"/>
      <url>/ML/RL/spinningup/gym_spaces/</url>
      
        <content type="html"><![CDATA[<p>每了解到一种就来这里做个记录.</p><h1 id="Box"><a href="#Box" class="headerlink" title="Box"></a>Box</h1><p>表示一个 n 维框, 即由 n 个数字描述这个空间.</p><h2 id="Box-high"><a href="#Box-high" class="headerlink" title="Box.high"></a>Box.high</h2><p>打印一个一维数组, 其中元素值为各个描述这个空间的数字的极大值.</p><h2 id="Box-low"><a href="#Box-low" class="headerlink" title="Box.low"></a>Box.low</h2><p>打印一个一维数组, 其中元素值为各个描述这个空间的数字的极小值.</p><h2 id="Box-sample"><a href="#Box-sample" class="headerlink" title="Box.sample()"></a>Box.sample()</h2><p>从可能的数值中随机采样.</p><h1 id="Discrete"><a href="#Discrete" class="headerlink" title="Discrete"></a>Discrete</h1><p>表示固定范围的非负数, 可以看做一些非负离散值的集合.</p><h2 id="Discrete-n"><a href="#Discrete-n" class="headerlink" title="Discrete.n"></a>Discrete.n</h2><p>可能的数值的总数.</p><h2 id="Discrete-sample"><a href="#Discrete-sample" class="headerlink" title="Discrete.sample()"></a>Discrete.sample()</h2><p>从可能的数值中随机采样.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> Spinning Up </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> Python </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> Gym </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Anaconda + PM2 部署 Jupyter 在服务器</title>
      <link href="/python/jupyter/jupyter_server/"/>
      <url>/python/jupyter/jupyter_server/</url>
      
        <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>最近学习发现电脑换来换去很麻烦, 然后就想到要把 Jupyter 部署在云服务器上, 正好服务器放在腾讯云也吃灰很久了, 就拿来玩一玩. 这里的所有操作都基于 Centos , 当然 Ubuntu 也适用, <strong>但是要将教程中所有 <code>root</code> 换成 <code>home/用户名</code> , 比如 <code>home/ubuntu</code> .</strong> </p><h1 id="部署-Jupyter"><a href="#部署-Jupyter" class="headerlink" title="部署 Jupyter"></a>部署 Jupyter</h1><h2 id="安装-Anaconda"><a href="#安装-Anaconda" class="headerlink" title="安装 Anaconda"></a>安装 Anaconda</h2><p>可以前往<a href="https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/">清华镜像源</a>选择对应版本, 找到你想要的 Anaconda3 版本, 通过下面的指令进行下载</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2020.07-Linux-x86_64.sh  # Anaconda3-2020.07-Linux-x86_64.sh 可以更换成你自己选择的版本</span><br></pre></td></tr></table></figure><p>然后安装</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bash Anaconda3-2020.07-Linux-x86_64.sh  # 同样更换你自己选择的版本</span><br></pre></td></tr></table></figure><p>然后一路 <code>enter</code> / <code>yes</code> 就完事. </p><h2 id="添加环境变量"><a href="#添加环境变量" class="headerlink" title="添加环境变量"></a>添加环境变量</h2><p>接着添加环境变量.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo vi /etc/profile</span><br></pre></td></tr></table></figure><p>输入密码后进入文件进行编辑. 在最底下加入两行</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Anaconda</span></span><br><span class="line">export PATH=&quot;/root/anaconda3/bin:{%raw%}$PATH&quot;</span><br></pre></td></tr></table></figure><p>如果搞不懂服务器中文件的编辑 (vim) 的话, 可以百度一下, 很多教程的. 编辑完后, 按 <code>ESC</code> 后输入 <code>:wq</code> 然后 <code>enter</code> 保存文件并退出 vi.</p><p>然后</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source ~/.bashrc</span><br></pre></td></tr></table></figure><p>接着重启服务器</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">reboot</span><br></pre></td></tr></table></figure><p>重启完成后验证是否安装成功</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">conda</span><br></pre></td></tr></table></figure><p>成功就不会报错.</p><h2 id="配置-Jupyter"><a href="#配置-Jupyter" class="headerlink" title="配置 Jupyter"></a>配置 Jupyter</h2><p>进入 Python</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python</span><br></pre></td></tr></table></figure><p>然后</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">from notebook.auth import passwd</span><br><span class="line">passwd()</span><br></pre></td></tr></table></figure><p>接着它就会让你输入密码, 输入你想要设置的密码并再确认一次, 然后它就会生成一串密匙</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#x27;sha1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&#x27;</span><br></pre></td></tr></table></figure><p>复制下来, 然后生成配置文件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jupyter lab --generate-config</span><br></pre></td></tr></table></figure><p>进入配置文件并修改</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vi /root/.jupyter/jupyter_notebook_config.py</span><br></pre></td></tr></table></figure><p>然后修改一下配置项, 如果要修改就将其前面的注释符号 <code>#</code> 删除</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">c.NotebookApp.ip = <span class="string">&#x27;*&#x27;</span></span><br><span class="line">c.NotebookApp.password = <span class="string">u&#x27;sha1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&#x27;</span>  <span class="comment"># 就是那串你复制的密匙</span></span><br><span class="line"><span class="comment"># 这个部分可改可不改, 不改就不要删除注释符号</span></span><br><span class="line">c.NotebookApp.notebook_dir = <span class="string">&#x27;/tree&#x27;</span> <span class="comment"># 输入要 jupyter 开启的目录, 如果不修改, 那么就会默认在输入命令的目录下打开</span></span><br><span class="line">c.NotebookApp.open_browser = <span class="literal">False</span> <span class="comment"># 禁止自动打开浏览器</span></span><br><span class="line">c.NotebookApp.allow_root = <span class="literal">True</span> <span class="comment"># 允许 root 启动</span></span><br></pre></td></tr></table></figure><p>然后就可以了</p><h2 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jupyter lab</span><br></pre></td></tr></table></figure><p>然后打开浏览器进入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">云服务器ip:8888</span><br></pre></td></tr></table></figure><p>然后输入你刚刚设置的密码就可以进入了.</p><h1 id="PM2-进程托管"><a href="#PM2-进程托管" class="headerlink" title="PM2 进程托管"></a>PM2 进程托管</h1><p>但是此时你必须一直开着服务器的终端不然 Jupyter 就会退出, 很不方便, 因此我们使用 PM2 来托管进程.</p><h2 id="安装-Node-js"><a href="#安装-Node-js" class="headerlink" title="安装 Node.js"></a>安装 Node.js</h2><p>使用下列命令安装</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">wget -qO- https://raw.github.com/creationix/nvm/master/install.sh | sh</span><br><span class="line">source ~/.bash_profile  # 如果是 Ubuntu 改成 source ~/.bashrc</span><br><span class="line">nvm install stable</span><br></pre></td></tr></table></figure><h2 id="安装并使用-PM2"><a href="#安装并使用-PM2" class="headerlink" title="安装并使用 PM2"></a>安装并使用 PM2</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install pm2 -g</span><br></pre></td></tr></table></figure><p>如果下载太慢先换成淘宝源</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm config set registry https://registry.npm.taobao.org</span><br></pre></td></tr></table></figure><p>然后再试一次</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install pm2 -g</span><br></pre></td></tr></table></figure><p>在任意的目录新建文件 <code>jupyter.js</code> , 然后写入如下内容</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//run</span></span><br><span class="line"><span class="keyword">const</span> &#123; exec &#125; = <span class="built_in">require</span>(<span class="string">&#x27;child_process&#x27;</span>)</span><br><span class="line"><span class="title function_">exec</span>(<span class="string">&#x27;jupyter lab&#x27;</span>,<span class="function">(<span class="params">error, stdout, stderr</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span>(error)&#123;</span><br><span class="line">                <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;exec error: ${%endraw%}&#123;error&#125;&#x27;</span>)</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;stdout: {%raw%}$&#123;stdout&#125;&#x27;</span>);</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;stderr: ${%endraw%}&#123;stderr&#125;&#x27;</span>);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>然后保存退出, 执行脚本</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pm2 start jupyter.js</span><br></pre></td></tr></table></figure><p>就可以愉快的在服务器上使用 Jupyter 啦!</p>]]></content>
      
      
      <categories>
          
          <category> Python </category>
          
          <category> Jupyter </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 教程 </tag>
            
            <tag> Jupyter </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>GAE 算法</title>
      <link href="/ML/RL/primer/GAE/"/>
      <url>/ML/RL/primer/GAE/</url>
      
        <content type="html"><![CDATA[<h1 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h1><p><del>众所周知,</del> 策略梯度有多种写法, 总的来说, 在保持策略梯度不变的情况下, 策略梯度可以写作<br>$$g=\mathbb{E}\left[\sum_{t=0}^{\infty}\Psi_t\nabla_\theta \log\pi_0(a_t\mid s_t)\right]\tag{1}$$<br>  其中 $\Psi$ 可以是<br>$$\begin{aligned}  1.\;&\sum\nolimits_{t=0}^\infty r_t&轨迹的总回报\\\\  2.\;&\sum\nolimits_{t'=t}^\infty r_{t'}&动作后轨迹的总回报\\\\  3.\;&\sum\nolimits_{t'=t}^\infty r_{t'}-b(s_t)&基线形式\\\\  4.\;&Q^{\pi}(s_t,a_t)&状态-动作价值函数\\\\  5.\;&A^{\pi}(s_t,a_t)&优势函数\\\\  6.\;&r_t+V^{\pi}(s_{t+1})-V^\pi(s_t)&\text{TD}\,残差  \end{aligned}$$<br>  其中<br>$$  \begin{align}  V^\pi(s_t):=\mathbb{E}_{\substack{s_{t+1:\infty},\\\\a_{t:\infty}}}\left[\sum_{l = 0}^\infty r_{t+l}\right]\qquad Q^\pi(s_t, a_t):=\mathbb{E}_{\substack{s_{t+1:\infty},\\\\a_{t+1:\infty}}}\left[\sum_{l = 0}^\infty r_{t+l}\right]\tag{2}\\\\  A^{\pi}(s_t,a_t)=Q^{\pi}(s_t,a_t)-V^{\pi}(s_t)\tag{3}  \end{align}$$<br>  这里逗号表示 $a:b$ 指的是 $(a,a+1,\dots,b)$ 这样的序列, $\mathbb{E}$ 的下标枚举了要被积分的变量. 前面 $5$ 项的推导或者推导资料在<a href="https://yunist.cn/ML/RL/primer/opt_param/">参数优化</a>中都有说明, 而 $\text{TD}$ 残差其实是优势函数的一种无偏估计.</p><p> 其中令 $\Psi_t=A^\pi(s_t, a_t)$ (优势函数) 的选择有几乎最小的方差. 这一点可以从策略梯度的角度直观的解释: 策略梯度中的每一步都会增加 “高于平均水平的动作” 的概率, 减少 “低于平均水平的动作” 的概率, 而优势函数 $A^{\pi}(s_t,a_t)=Q^{\pi}(s_t,a_t)-V^{\pi}(s_t)$ 恰好衡量了动作相对平均水平的好坏, 当动作高于平均水平时, 优势函数会取正数, 从而增加其概率; 当动作低于平均水平时, 优势函数会取负数. 从而降低其概率.</p><p> 我们利用一个参数 $\gamma$ 来降低回报对延迟效应的反应的权重 (即减少未来回报的影响) 来减少方差, 代价是引入偏差. 这个参数相当于有折损的 $\text{MDPs}$ 公式, 但是我们将其当做一个在无折损问题中的一个减少方差的参数. 这些有折损的公式可以表示为<br>$$  \begin{align}  V^{\pi, \gamma}(s_t):=\mathbb{E}_{\substack{s_{t+1:\infty},\\\\a_{t:\infty}}}\left[\sum_{l = 0}^\infty \gamma^l r_{t+l}\right]\qquad Q^{\pi, \gamma}(s_t, a_t):=\mathbb{E}_{\substack{s_{t+1:\infty},\\\\a_{t+1:\infty}}}\left[\sum_{l = 0}^\infty \gamma^l r_{t+l}\right]\tag{4}\\\\  A^{\pi, \gamma}(s_t,a_t)=Q^{\pi, \gamma}(s_t,a_t)-V^{\pi, \gamma}(s_t)\tag{5}  \end{align}$$<br>  梯度的有折损近似可以表示为<br>$$  g^\gamma:=\mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[\sum_{t=0}^{\infty}A^{\pi, \gamma}(s_t,a_t)\nabla_\theta \log\pi_0(a_t\mid s_t)\right]\tag{6}$$<br>  由于优势函数是未知的, 所以我们需要对它进行估计. 在实践中, 往往只能学习到 $A^{\pi,\gamma}$ 的一个有偏估计 (但没有那么偏) .</p><p> 我们引入一个关于 $A^{\pi,\gamma}$ 的一个估计, 并且这个估计是无偏的. 考虑一个与整个轨迹有关的优势函数的估计 $\hat{A}_t(s_{0:\infty},a_{0:\infty})$ . </p><p>  我们定义: <strong>一个估计 $\hat{A}_t$ 是 $\gamma\text{-just}$ 的当且仅当</strong><br>$$  \mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[\hat{A}_t(s_{0:\infty},a_{0:\infty})\nabla_\theta \log\pi_0(a_t\mid s_t)\right]=\mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[A^{\pi, \gamma}(s_t,a_t)\nabla_\theta \log\pi_0(a_t\mid s_t)\right]\tag{7}$$<br>  因此如果对于所有的 $t$ 来说 $\hat{A}_t$ 都是 $\gamma\text{-just}$ 的话, 就有<br>$$  \mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[\sum_{t=0}^{\infty}\hat{A}_t(s_{0:\infty},a_{0:\infty})\nabla_\theta \log\pi_0(a_t\mid s_t)\right]=g^\gamma\tag{8}$$<br>  一个令 $\hat{A}_t$ 为 $\gamma\text{-just}$ 的充分条件是 $\hat{A}_t$ 可以被分解为两个函数 $Q_t$ 和 $b_t$ 之间的差. 并且 $Q_t$ 可以依赖于轨迹中的任意变量, 但必须是 $\gamma$-折扣 的 $Q$ 函数 (状态-动作价值函数) 的无偏估计 (如果要求是状态-动作价值函数的估计, 那么由于马尔科夫性, 在时间 $t$ 之前的变量都对状态-动作价值函数的值没有影响, 因此 $Q_t$ 只被时间 $t$ 以及 $t$ 以后的变量决定), 而 $b_t$ 是先于 $a_t$ 被采样的动作和状态的任意函数. 即<strong>如果 $\hat{A}_t$ 可以被写成 $\hat{A}_t(s_{0:\infty},a_{0:\infty})=Q_t(s_{t:\infty},a_{t:\infty})-b_t(s_{0:t},a_{0:t-1})$ 的形式, 并且对于任意的 $(s_t,a_t)$ 有 $\mathbb{E}_{s_{t+1:\infty},a_{t+1:\infty}\mid s_t,a_t}[Q_t(s_{t:\infty},a_{t:\infty})]=Q^{\pi, \gamma}(s_t,a_t)$ , 那么 $\hat{A}$ 就是 $\gamma\text{-just}$ 的.</strong></p><p>  证明:<br>$$  \begin{align}  &\mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[\hat{A}_t(s_{0:\infty},a_{0:\infty})\nabla_\theta \log\pi_0(a_t\mid s_t)\right]\\\\  =&\mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[Q_t(s_{t:\infty},a_{t:\infty})\nabla_\theta \log\pi_0(a_t\mid s_t)\right]-\mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[b_t(s_{0:t},a_{0:t-1})\nabla_\theta \log\pi_0(a_t\mid s_t)\right]  \end{align}$$<br>  其中<br>$$  \begin{align}  &\mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[Q_t(s_{t:\infty},a_{t:\infty})\nabla_\theta \log\pi_0(a_t\mid s_t)\right]\\\\  =&\mathbb{E}_{\substack{s_{0:t},\\\\a_{0:t}}}\left[\mathbb{E}_{\substack{s_{t+1:\infty},\\\\a_{t+1:\infty}}}\left[Q^{\pi,\gamma}(s_t,a_t)\nabla_\theta \log\pi_0(a_t\mid s_t)\right]\right]\\\\  =&\mathbb{E}_{\substack{s_{0:t},\\\\a_{0:t}}}\left[\mathbb{E}_{\substack{s_{t+1:\infty},\\\\a_{t+1:\infty}}}\left[A^{\pi, \gamma}(s_t,a_t)\nabla_\theta \log\pi_0(a_t\mid s_t)\right]\right]\\\\  =&\mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[A^{\pi, \gamma}(s_t,a_t)\nabla_\theta \log\pi_0(a_t\mid s_t)\right]  \end{align}$$<br>  而<br>$$  \begin{align}  &\mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[b_t(s_{0:t},a_{0:t-1})\nabla_\theta \log\pi_0(a_t\mid s_t)\right]\\\\  =&\mathbb{E}_{\substack{s_{0:t},\\\\a_{0:t-1}}}\left[\mathbb{E}_{\substack{s_{t+1:\infty},\\\\a_{t:\infty}}}\left[b_t(s_{0:t},a_{0:t-1})\nabla_\theta \log\pi_0(a_t\mid s_t)\right]\right]\\\\  =&\mathbb{E}_{\substack{s_{0:t},\\\\a_{0:t-1}}}\left[\mathbb{E}_{\substack{s_{t+1:\infty},\\\\a_{t:\infty}}}\left[\nabla_\theta \log\pi_0(a_t\mid s_t)\right]b_t(s_{0:t},a_{0:t-1})\right]  \end{align}$$<br>  根据 $\text{EGLP}$ 定理 (见<a href="https://yunist.cn/ML/RL/primer/opt_param/">参数优化</a>) 有<br>$$  \mathbb{E}_{\substack{s_{t+1:\infty},\\\\a_{t:\infty}}}\left[\nabla_\theta \log\pi_0(a_t\mid s_t)\right]=0$$<br>  因此<br>$$  \mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[b_t(s_{0:t},a_{0:t-1})\nabla_\theta \log\pi_0(a_t\mid s_t)\right]=0$$<br>  所以有<br>$$  \mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[\hat{A}_t(s_{0:\infty},a_{0:\infty})\nabla_\theta \log\pi_0(a_t\mid s_t)\right]=\mathbb{E}_{\substack{s_{0:\infty},\\\\a_{0:\infty}}}\left[A^{\pi, \gamma}(s_t,a_t)\nabla_\theta \log\pi_0(a_t\mid s_t)\right]$$<br>  也就是说 $\hat{A}$ 是 $\gamma\text{-just}$ 的.</p><p>  容易验证, 下列估计表达式 $\hat{A}_t$ 也是 $\gamma\text{-just}$ 的:<br>$$  \begin{align}  &\bullet\sum\nolimits_{l=0}^\infty \gamma^l r_{t+l}&\qquad\qquad\qquad\qquad\bullet& A^{\pi,\gamma}(s_t,a_t)\\\\  &\bullet Q^{\pi,\gamma}(s_t,a_t)&\bullet& r_t+\gamma V^{\pi,\gamma}(s_{t+1})-V^{\pi,\gamma}(s_t)  \end{align}$$</p><h1 id="优势函数的估计"><a href="#优势函数的估计" class="headerlink" title="优势函数的估计"></a>优势函数的估计</h1><p> 令 $\delta_t^V=r_t+\gamma V(s_{t+1})-V(s_t)$ 为 $V$ 的 $\gamma$ 折扣 $\text{TD}$ 残差. 注意到 $\delta_t^V$ 可以被看做是动作 $a_t$ 的优势. 事实上, 如果我们有确切的价值函数 $V=V^{\pi,\gamma}$ , 那么 $\delta_t^{V^{\pi,\gamma}}$ 会是一个无偏的,  $\gamma\text{-just}$ 的优势估计.<br>$$  \begin{align}  \mathbb{E}_{s_{t+1}}\left[\delta_t^{V^{\pi,\gamma}}\right]&=\mathbb{E}_{s_{t+1}}\left[r_t+\gamma V^{\pi,\gamma}(s_{t+1})-V^{\pi,\gamma}(s_t)\right]\\\\  &=\mathbb{E}_{s_{t+1}}\left[Q^{\pi,\gamma}(s_t,a_t)-V^{\pi,\gamma}(s_t)\right]\\\\  &=A^{\pi,\gamma}(s_t,a_t)  \end{align}$$<br>  然而, 也只有当 $V=V^{\pi,\gamma}$ 时这个优势估计才是 $\gamma\text{-just}$ 的.</p><p> 接着, 让我们考虑 $k$ 项这样的 $\delta$ 相加的情况, 我们将其记为 $\hat{A}_t^{(k)}$<br>$$  \begin{align}  &\hat{A}_t^{(1)}:=\delta_t^V&=&-V(s_t)+r_t+\gamma V(s_{t+1})\tag{11}\\\\  &\hat{A}_t^{(2)}:=\delta_t^V+\gamma\delta_{t+1}^V&=&-V(s_t)+r_t+\gamma r_{t+1}+\gamma^2 V(s_{t+2})\tag{12}\\\\  &\hat{A}_t^{(2)}:=\delta_t^V+\gamma\delta_{t+1}^V+\gamma^2\delta_{t+2}^V&=&-V(s_t)+r_t+\gamma r_{t+1}+\gamma^2 r_{t+2}+\gamma^3 V(s_{t+3})\tag{13}  \end{align}$$</p>$$  \hat{A}_t^{(k)}:=\sum_{t=0}^{k-1}\gamma^l\delta_{t+l}^V=-V(s_t)+r_t+\gamma r_{t+1}+\dots+\gamma^{k-1}r_{t+k-1}+\gamma^kV(s_{t+k})\tag{14}$$<p>  容易得出当且仅当 $V=V^{\pi,\gamma}$ 时 $\hat{A}_t^{(k)}$ 是 $\gamma\text{-just}$ 的. 注意到当 $k\to \infty$ 时, 由于 $\gamma^kV(s_{t+k})$ 项急剧减小 (当 $V\not= V^{\pi,\gamma}$ 时, 该项会产生偏差), 因此其偏差也会减少,  而 $-V(s_t)$ 项是不会产生偏差的 (因为这是基线). 令 $k\to \infty$ , 我们得到<br>$$  \hat{A}_t^{(\infty)}=\sum_{l=0}^{\infty}\gamma^l\delta_{t+l}^V=-V(s_t)+\sum_{l=0}^\infty\gamma^lr_{t+l}\tag{15}$$<br>  仅仅是回报减去价值函数基线.</p><p> 广义优势估计 $(\text{generalized advantage estimator})$ $\mathrm{GAE}(\gamma,\lambda)$ 被定义为这些 $k$ 步估计量的指数加权平均:<br>$$  \begin{align}  \hat{A}_t^{\mathrm{GAE}(\gamma,\lambda)}&:=(1-\lambda)\left(\hat{A}_t^{(1)}+\lambda\hat{A}_t^{(2)}+\lambda^2\hat{A}_t^{(3)}+\cdots\right)\\\\  &=(1-\lambda)\left(\delta_t^V+\lambda(\delta_t^V+\gamma\delta_{t+1}^V)+\lambda^2(\delta_t^V+\gamma\delta_{t+1}^V+\gamma^2\delta_{t+2}^V)+\cdots\right)\\\\  &=(1-\lambda)\left(\delta_t^V(1+\lambda+\lambda^2+\cdots)+\gamma\delta_{t+1}^V(\lambda+\lambda^2+\lambda^3+\cdots)\\\\  +\gamma^2\delta_{t+2}^V(\lambda^2+\lambda^3+\lambda^4+\cdots)+\cdots\right)\\\\  &=(1-\lambda)\left(\delta_t^V\left(\frac{1}{1-\lambda}\right)+\gamma\delta_{t+1}^V\left(\frac{\lambda}{1-\lambda}\right)+\gamma^2\delta_{t+2}^V\left(\frac{\lambda^2}{1-\lambda}\right)+\cdots\right)\\\\  &=\sum_{l=0}^\infty(\gamma\lambda)^l\delta_{t+l}^V\tag{16}  \end{align}$$<br>  这个公式有两个特殊的情况即 $\lambda=0$ 和 $\lambda=1$ ,<br>$$\begin{align}  \mathrm{GAE}(\gamma, 0):&\hat{A}_t:=\delta_t=r_t+\gamma V(s_{t+1})-V(s_t)\tag{17}\\\\  \mathrm{GAE}(\gamma,1):&\hat{A}_t:=\sum_{l=0}^\infty \gamma^l\delta_{t+l}=\sum_{l=0}^\infty  \gamma^lr_{t+l}-V(s_t)\tag{18}  \end{align}$$<br>&nbsp;$\mathrm{GAE}(\gamma,1)$ 是 $\gamma\text{-just}$ 的, 不论 $V$ 的精度如何, 但由于其表达式中有多项和而导致其有高方差. 而 $\mathrm{GAE}(\gamma,0)$ 是 $\gamma\text{-just}$ 的当且仅当 $V=V^{\pi.\gamma}$ , 如果并非如此, 那么就会包含偏差, 但其往往具有更低的方差. 当 $0<\lambda<1$ 时我们得到更普遍的优势估计, 并且通过调整参数 $\lambda$ , 我们可以在偏差和方差之间取得一个平衡.</p><p> 我们引入了一个包含两个参数 $\gamma$ 和 $\lambda$ 的优势估计, 这两个参数都会影响偏差和方差之间的平衡. 但是, 它们的作用以及对平衡的影响有本质上的不同. $\gamma$ 决定了价值函数 $V^{\pi,\gamma}$ 的最大值, 而 $\lambda$ 对其并没有影响. 并且无论价值函数是否是正确的, 只要 $\gamma<1$ 那么对于梯度 $g$ 来说就一定会有偏差 (因为已经使用了有折损回报, 而我们要优化的是无折损回报, 而 $\gamma$ 可以看做是影响方差与偏差的一个参数) . 而当 $\lambda<1$ 时只有错误的价值函数才会带来偏差. 因此我们往往会发现 $\lambda$ 的最优值往往比 $\gamma$ 的最优值要低得多, 这有可能是因为当获取到一个足够准确的价值函数后 $\lambda$ 引入的误差要比 $\gamma$ 小得多.</p><p> 使用广义优势估计, 我们可以构建一个 $g^\gamma$ 的有偏估计<br>$$  g^\gamma\approx\mathbb{E}\left[\sum_{t=0}^{\infty}\nabla_\theta\log\pi_{\theta}(a_t\mid s_t)\hat{A}_t^{\mathrm{GAE(\gamma,\lambda)}}\right]=\mathbb{E}\left[\sum_{t=0}^{\infty}\nabla_\theta\log\pi_{\theta}(a_t\mid s_t)\sum_{l=0}^\infty (\gamma\lambda)^l\delta_{t+l}^V\right]\tag{19}$$<br>  当 $\lambda=1$ 时就是无偏的了.</p><h1 id="对回报变形后的解释"><a href="#对回报变形后的解释" class="headerlink" title="对回报变形后的解释"></a>对回报变形后的解释</h1><p>令 $\Phi \colon\mathcal{S}\to \mathbb{R}$ 为在状态空间上的任意函数考虑一个变形后的回报 $\tilde{r}$<br>$$  \tilde{r}(s,a,s')=r(s,a,s')+\gamma\Phi(s')-\Phi(s)\tag{20}$$<br>容易证明, 对于变形后的回报, 其有折损和为<br>$$  \sum_{l=0}^\infty \gamma^l \tilde{r}(s_{t+l},a_t,a_{t+l+1})=\sum_{l=0}^\infty \gamma^l r(s_{t+l},a_t,a_{t+l+1})-\Phi(s_t)\tag{21}$$<br>类似的, 我们定义<br>$$  \begin{align}  &\tilde{Q}^{\pi,\gamma}(s,a)=Q^{\pi,\gamma}(s,a)-\Phi(s)\tag{22}\\\\  &\tilde{V}^{\pi,\gamma}(s)=V^{\pi,\gamma}(s)-\Phi(s)\tag{23}\\\\  &\tilde{A}^{\pi,\gamma}(s,a)=(Q^{\pi,\gamma}(s,a)-\Phi(s)\tag{24})-(V^{\pi,\gamma}(s)-\Phi(s))=A^{\pi,\gamma}(s,a)  \end{align}$$<br>分别为变形后的回报, 价值, 优势函数.</p><p>注意到如果 $\Phi$ 如果恰好等于价值函数 $V^{\pi,\gamma}$ , 那么 $\tilde{V}^{\pi,\gamma}(s)$ 对于任何状态都等于零.</p><p>同样注意到使用变形后的回报对最大化有折损回报 $\sum_{t=0}^\infty \gamma^tr(s_t,a_t,s_{t+1})$ 的策略梯度是没有影响的. 但本文的目的其实是要最大化无折损回报, 而 $\gamma$ 是一个用来降低方差的参数.</p><p>引出回报变形后, 让我们考虑将其使用在梯度估计上. 注意到 $\tilde{r}$ 的形式与 $\delta^V$ 完全相同. 如果我们令 $\Phi=V$ , 那么就有<br>$$  \sum_{l=0}^\infty(\gamma\lambda)^l\tilde{r}(s_{t+l},a_t,s_{t+l+1})=\sum_{l=0}^\infty(\gamma\lambda)^l\delta_{t+l}^V=\hat{A}_t^{\mathrm{GAE}(\gamma,\lambda)}\tag{25}$$<br>  因此可以将 $\delta_{t}^V$ 理解为变形后的回报, 而 $\gamma\lambda$ 其实就是折损.</p><p> 还有另一种解释, 记响应函数 $\chi$ 为<br>$$\chi(l;s,a)=\mathbb{E}[r_{t+l}\mid s_t,a_t]-\mathbb{E}[r_{t+l}\mid s_t]\tag{26}$$<br>  注意到 $A^{\pi,\gamma}(s,a)=\sum_{l=0}^\infty \gamma^l\chi(l;s,a)$ . 然后重新回忆我们用折扣因子 $\gamma$ 和 $A^{\pi,\gamma}$ 来估计的策略梯度 (式 $(6)$) 中有如下形式<br>$$  \nabla_\theta \log\pi_0(a_t\mid s_t)A^{\pi, \gamma}(s_t,a_t)=\nabla_\theta \log\pi_0(a_t\mid s_t)\sum_{l=0}^\infty \gamma^l\chi(l;s,a)\tag{27}$$<br>  使用折扣 $\gamma<1$ 相当于急剧减少当 $l\gg 1/(1-\gamma)$ 的项 (因为 $\gamma^l$ 会变得很小) . 因此这些项带来的偏差会随着 $l$ 的增加而变少, 也就是说, 在大约 $1/(1-\gamma)$ 步后行动对回报的影响看起来像是被 “遗忘” 了.</p><p> 如果我们使用变形后的回报 $\tilde{r}$ 并且有 $\Phi=V^{\pi,\gamma}$ , 不难得到当 $l>0$ 时有 $\mathbb{E}[\tilde{r}_{t+l}\mid s_t,a_t]=\mathbb{E}[\tilde{r}_{t+l}\mid s_t]=0$ (由于 $t$ 之后时刻采取的动作的概率完全依赖于那时候的状态 $s$ , 而 $t$ 时刻的动作已经给定为 $a_t$) . 因此只有 $l=0$ 是项才是非零的. 因此变形回报将依赖长时间的梯度估计变成了瞬时的. 当然我们往往难以得到非常好的估计, 但这已经能够给出式 $(16)$ 的一个很好的解释: 变形后的回报可以通过拟合 $V^{\pi,\gamma}$ 来减少响应函数起作用的范围, 通过引入一个更陡的折损 $\gamma\lambda$ 来减少由回报延迟 (即梯度估计中有很多项回报的和) 引起的噪声 (这是产生方差的原因), 也就是当 $l\gg 1/(1-\gamma\lambda)$ 时忽略项 $\nabla_\theta \log\pi_0(a_t\mid s_t)\delta^{V}_{t+l}$​ .</p><h1 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h1><p> 这篇文章可能可以算是论文 <a href="https://arxiv.org/pdf/1506.02438.pdf">High-Dimensional Continuous Control Using Generalized Advantage Estimation</a> 的一个翻译, 但是其中增添了一些我自己的理解并且有些东西换了一些表述. 这篇文章只有论文前半部分的内容, 后面则是讲如何拟合价值函数以及一些探究, 有兴趣的可以看原论文. 其实原论文后面这段解释我看着怪怪的… 虽然说不出什么问题吧… 但是总感觉没什么必要… 因为前面的介绍以及推导已经解释了 $\text{GAE}$ 是如何起作用的… 还有我本人英语非常菜, 借助了翻译才一点点看下来… 如果哪个地方理解不对请指出, <del>还有大佬们请轻喷</del>.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 入门 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 优化算法 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 论文精读 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>零成本搭建网页代理</title>
      <link href="/scribble/proxy_web/"/>
      <url>/scribble/proxy_web/</url>
      
        <content type="html"><![CDATA[<p>网页代理是非常简单的一种代理方式, 我们借助 <a href="https://cloudflare.com">CloudFlare</a> 与 <a href="https://github.com/EtherDream/jsproxy">jsproxy</a> 项目可以免费搭建自己的网页代理.</p><h1 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h1><p>首先, 你需要有 <a href="https://github.com">Github</a> 和 <a href="https://cloudflare.com">CloudFlare</a> 账号 (怎么注册就不用我教了吧…) 并登陆.</p><h1 id="Github"><a href="#Github" class="headerlink" title="Github"></a>Github</h1><p>fork <a href="https://github.com/EtherDream/jsproxy">jsproxy</a> 项目,</p><p><img src="1.png" alt=""></p><p>然后进入到自己 fork 的 jsproxy 项目中, 进入 Settings 并下拉, 拉到 Github Pages 这一项</p><p><img src="2.png" alt=""></p><p>将 Select branch 设置成 gh-pages , 并 Save (这里我已经设置过了所以无法点击), 重新刷新并来到同样的位置, 它会显示大概如下内容</p><blockquote><p>Your site is published at <a href="https://xxxx.github.io/jsproxy/">https://xxxx.github.io/jsproxy/</a></p></blockquote><p>后面那串网址就是你的 Pages 地址, 记住它.</p><h1 id="CloudFlare"><a href="#CloudFlare" class="headerlink" title="CloudFlare"></a>CloudFlare</h1><p>进入<a href="https://dash.cloudflare.com/">主页</a>, 然后进入 Workers ,</p><p><img src="3.png" alt=""></p><p>并创建 Worker,</p><p><img src="4.png" alt=""></p><p>然后在左侧的 “脚本” 区写下如下代码, 其中第 6 行中 <code>https://xxxx.github.io/jsproxy</code> 需要替换成你的 Pages 地址 (就是我前面叫你记住的那个) ,</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * static files (404.html, sw.js, conf.js)</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">ASSET_URL</span> = <span class="string">&#x27;https://xxxx.github.io/jsproxy&#x27;</span><span class="comment">//这里填写你Github pages的网址！</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">JS_VER</span> = <span class="number">10</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">MAX_RETRY</span> = <span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/** <span class="doctag">@type</span> &#123;<span class="type">RequestInit</span>&#125; */</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">PREFLIGHT_INIT</span> = &#123;</span><br><span class="line">  <span class="attr">status</span>: <span class="number">204</span>,</span><br><span class="line">  <span class="attr">headers</span>: <span class="keyword">new</span> <span class="title class_">Headers</span>(&#123;</span><br><span class="line">    <span class="string">&#x27;access-control-allow-origin&#x27;</span>: <span class="string">&#x27;*&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;access-control-allow-methods&#x27;</span>: <span class="string">&#x27;GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;access-control-max-age&#x27;</span>: <span class="string">&#x27;1728000&#x27;</span>,</span><br><span class="line">  &#125;),</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">any</span>&#125; <span class="variable">body</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">number</span>&#125; <span class="variable">status</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">Object&lt;string, string&gt;</span>&#125; <span class="variable">headers</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">makeRes</span>(<span class="params">body, status = <span class="number">200</span>, headers = &#123;&#125;</span>) &#123;</span><br><span class="line">  headers[<span class="string">&#x27;--ver&#x27;</span>] = <span class="variable constant_">JS_VER</span></span><br><span class="line">  headers[<span class="string">&#x27;access-control-allow-origin&#x27;</span>] = <span class="string">&#x27;*&#x27;</span></span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(body, &#123;status, headers&#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">string</span>&#125; urlStr </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">newUrl</span>(<span class="params">urlStr</span>) &#123;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title function_">URL</span>(urlStr)</span><br><span class="line">  &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="title function_">addEventListener</span>(<span class="string">&#x27;fetch&#x27;</span>, <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> ret = <span class="title function_">fetchHandler</span>(e)</span><br><span class="line">    .<span class="title function_">catch</span>(<span class="function"><span class="params">err</span> =&gt;</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;cfworker error:\n&#x27;</span> + err.<span class="property">stack</span>, <span class="number">502</span>))</span><br><span class="line">  e.<span class="title function_">respondWith</span>(ret)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">FetchEvent</span>&#125; e </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">fetchHandler</span>(<span class="params">e</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> req = e.<span class="property">request</span></span><br><span class="line">  <span class="keyword">const</span> urlStr = req.<span class="property">url</span></span><br><span class="line">  <span class="keyword">const</span> urlObj = <span class="keyword">new</span> <span class="title function_">URL</span>(urlStr)</span><br><span class="line">  <span class="keyword">const</span> path = urlObj.<span class="property">href</span>.<span class="title function_">substr</span>(urlObj.<span class="property">origin</span>.<span class="property">length</span>)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (urlObj.<span class="property">protocol</span> === <span class="string">&#x27;http:&#x27;</span>) &#123;</span><br><span class="line">    urlObj.<span class="property">protocol</span> = <span class="string">&#x27;https:&#x27;</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;&#x27;</span>, <span class="number">301</span>, &#123;</span><br><span class="line">      <span class="string">&#x27;strict-transport-security&#x27;</span>: <span class="string">&#x27;max-age=99999999; includeSubDomains; preload&#x27;</span>,</span><br><span class="line">      <span class="string">&#x27;location&#x27;</span>: urlObj.<span class="property">href</span>,</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (path.<span class="title function_">startsWith</span>(<span class="string">&#x27;/http/&#x27;</span>)) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">httpHandler</span>(req, path.<span class="title function_">substr</span>(<span class="number">6</span>))</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">switch</span> (path) &#123;</span><br><span class="line">  <span class="keyword">case</span> <span class="string">&#x27;/http&#x27;</span>:</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;请更新 cfworker 到最新版本!&#x27;</span>)</span><br><span class="line">  <span class="keyword">case</span> <span class="string">&#x27;/ws&#x27;</span>:</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;not support&#x27;</span>, <span class="number">400</span>)</span><br><span class="line">  <span class="keyword">case</span> <span class="string">&#x27;/works&#x27;</span>:</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;it works&#x27;</span>)</span><br><span class="line">  <span class="attr">default</span>:</span><br><span class="line">    <span class="comment">// static files</span></span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">fetch</span>(<span class="variable constant_">ASSET_URL</span> + path)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">Request</span>&#125; <span class="variable">req</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">string</span>&#125; <span class="variable">pathname</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">httpHandler</span>(<span class="params">req, pathname</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> reqHdrRaw = req.<span class="property">headers</span></span><br><span class="line">  <span class="keyword">if</span> (reqHdrRaw.<span class="title function_">has</span>(<span class="string">&#x27;x-jsproxy&#x27;</span>)) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Response</span>.<span class="title function_">error</span>()</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// preflight</span></span><br><span class="line">  <span class="keyword">if</span> (req.<span class="property">method</span> === <span class="string">&#x27;OPTIONS&#x27;</span> &amp;&amp;</span><br><span class="line">      reqHdrRaw.<span class="title function_">has</span>(<span class="string">&#x27;access-control-request-headers&#x27;</span>)</span><br><span class="line">  ) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(<span class="literal">null</span>, <span class="variable constant_">PREFLIGHT_INIT</span>)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">let</span> acehOld = <span class="literal">false</span></span><br><span class="line">  <span class="keyword">let</span> rawSvr = <span class="string">&#x27;&#x27;</span></span><br><span class="line">  <span class="keyword">let</span> rawLen = <span class="string">&#x27;&#x27;</span></span><br><span class="line">  <span class="keyword">let</span> rawEtag = <span class="string">&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> reqHdrNew = <span class="keyword">new</span> <span class="title class_">Headers</span>(reqHdrRaw)</span><br><span class="line">  reqHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;x-jsproxy&#x27;</span>, <span class="string">&#x27;1&#x27;</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 此处逻辑和 http-dec-req-hdr.lua 大致相同</span></span><br><span class="line">  <span class="comment">// https://github.com/EtherDream/jsproxy/blob/master/lua/http-dec-req-hdr.lua</span></span><br><span class="line">  <span class="keyword">const</span> refer = reqHdrNew.<span class="title function_">get</span>(<span class="string">&#x27;referer&#x27;</span>)</span><br><span class="line">  <span class="keyword">const</span> query = refer.<span class="title function_">substr</span>(refer.<span class="title function_">indexOf</span>(<span class="string">&#x27;?&#x27;</span>) + <span class="number">1</span>)</span><br><span class="line">  <span class="keyword">if</span> (!query) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;missing params&#x27;</span>, <span class="number">403</span>)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">const</span> param = <span class="keyword">new</span> <span class="title class_">URLSearchParams</span>(query)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">const</span> [k, v] <span class="keyword">of</span> <span class="title class_">Object</span>.<span class="title function_">entries</span>(param)) &#123;</span><br><span class="line">    <span class="keyword">if</span> (k.<span class="title function_">substr</span>(<span class="number">0</span>, <span class="number">2</span>) === <span class="string">&#x27;--&#x27;</span>) &#123;</span><br><span class="line">      <span class="comment">// 系统信息</span></span><br><span class="line">      <span class="keyword">switch</span> (k.<span class="title function_">substr</span>(<span class="number">2</span>)) &#123;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">&#x27;aceh&#x27;</span>:</span><br><span class="line">        acehOld = <span class="literal">true</span></span><br><span class="line">        <span class="keyword">break</span></span><br><span class="line">      <span class="keyword">case</span> <span class="string">&#x27;raw-info&#x27;</span>:</span><br><span class="line">        [rawSvr, rawLen, rawEtag] = v.<span class="title function_">split</span>(<span class="string">&#x27;|&#x27;</span>)</span><br><span class="line">        <span class="keyword">break</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">// 还原 HTTP 请求头</span></span><br><span class="line">      <span class="keyword">if</span> (v) &#123;</span><br><span class="line">        reqHdrNew.<span class="title function_">set</span>(k, v)</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        reqHdrNew.<span class="title function_">delete</span>(k)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (!param.<span class="title function_">has</span>(<span class="string">&#x27;referer&#x27;</span>)) &#123;</span><br><span class="line">    reqHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;referer&#x27;</span>)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// cfworker 会把路径中的 `//` 合并成 `/`</span></span><br><span class="line">  <span class="keyword">const</span> urlStr = pathname.<span class="title function_">replace</span>(<span class="regexp">/^(https?):\/+/</span>, <span class="string">&#x27;{%raw%}$1://&#x27;</span>)</span><br><span class="line">  <span class="keyword">const</span> urlObj = <span class="title function_">newUrl</span>(urlStr)</span><br><span class="line">  <span class="keyword">if</span> (!urlObj) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">makeRes</span>(<span class="string">&#x27;invalid proxy url: &#x27;</span> + urlStr, <span class="number">403</span>)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/** <span class="doctag">@type</span> &#123;<span class="type">RequestInit</span>&#125; */</span></span><br><span class="line">  <span class="keyword">const</span> reqInit = &#123;</span><br><span class="line">    <span class="attr">method</span>: req.<span class="property">method</span>,</span><br><span class="line">    <span class="attr">headers</span>: reqHdrNew,</span><br><span class="line">    <span class="attr">redirect</span>: <span class="string">&#x27;manual&#x27;</span>,</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (req.<span class="property">method</span> === <span class="string">&#x27;POST&#x27;</span>) &#123;</span><br><span class="line">    reqInit.<span class="property">body</span> = req.<span class="property">body</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">proxy</span>(urlObj, reqInit, acehOld, rawLen, <span class="number">0</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">URL</span>&#125; urlObj </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">RequestInit</span>&#125; reqInit </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">number</span>&#125; retryTimes </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">proxy</span>(<span class="params">urlObj, reqInit, acehOld, rawLen, retryTimes</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> res = <span class="keyword">await</span> <span class="title function_">fetch</span>(urlObj.<span class="property">href</span>, reqInit)</span><br><span class="line">  <span class="keyword">const</span> resHdrOld = res.<span class="property">headers</span></span><br><span class="line">  <span class="keyword">const</span> resHdrNew = <span class="keyword">new</span> <span class="title class_">Headers</span>(resHdrOld)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">let</span> expose = <span class="string">&#x27;*&#x27;</span></span><br><span class="line">  </span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">const</span> [k, v] <span class="keyword">of</span> resHdrOld.<span class="title function_">entries</span>()) &#123;</span><br><span class="line">    <span class="keyword">if</span> (k === <span class="string">&#x27;access-control-allow-origin&#x27;</span> ||</span><br><span class="line">        k === <span class="string">&#x27;access-control-expose-headers&#x27;</span> ||</span><br><span class="line">        k === <span class="string">&#x27;location&#x27;</span> ||</span><br><span class="line">        k === <span class="string">&#x27;set-cookie&#x27;</span></span><br><span class="line">    ) &#123;</span><br><span class="line">      <span class="keyword">const</span> x = <span class="string">&#x27;--&#x27;</span> + k</span><br><span class="line">      resHdrNew.<span class="title function_">set</span>(x, v)</span><br><span class="line">      <span class="keyword">if</span> (acehOld) &#123;</span><br><span class="line">        expose = expose + <span class="string">&#x27;,&#x27;</span> + x</span><br><span class="line">      &#125;</span><br><span class="line">      resHdrNew.<span class="title function_">delete</span>(k)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (acehOld &amp;&amp;</span><br><span class="line">      k !== <span class="string">&#x27;cache-control&#x27;</span> &amp;&amp;</span><br><span class="line">      k !== <span class="string">&#x27;content-language&#x27;</span> &amp;&amp;</span><br><span class="line">      k !== <span class="string">&#x27;content-type&#x27;</span> &amp;&amp;</span><br><span class="line">      k !== <span class="string">&#x27;expires&#x27;</span> &amp;&amp;</span><br><span class="line">      k !== <span class="string">&#x27;last-modified&#x27;</span> &amp;&amp;</span><br><span class="line">      k !== <span class="string">&#x27;pragma&#x27;</span></span><br><span class="line">    ) &#123;</span><br><span class="line">      expose = expose + <span class="string">&#x27;,&#x27;</span> + k</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (acehOld) &#123;</span><br><span class="line">    expose = expose + <span class="string">&#x27;,--s&#x27;</span></span><br><span class="line">    resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;--t&#x27;</span>, <span class="string">&#x27;1&#x27;</span>)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// verify</span></span><br><span class="line">  <span class="keyword">if</span> (rawLen) &#123;</span><br><span class="line">    <span class="keyword">const</span> newLen = resHdrOld.<span class="title function_">get</span>(<span class="string">&#x27;content-length&#x27;</span>) || <span class="string">&#x27;&#x27;</span></span><br><span class="line">    <span class="keyword">const</span> badLen = (rawLen !== newLen)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (badLen) &#123;</span><br><span class="line">      <span class="keyword">if</span> (retryTimes &lt; <span class="variable constant_">MAX_RETRY</span>) &#123;</span><br><span class="line">        urlObj = <span class="keyword">await</span> <span class="title function_">parseYtVideoRedir</span>(urlObj, newLen, res)</span><br><span class="line">        <span class="keyword">if</span> (urlObj) &#123;</span><br><span class="line">          <span class="keyword">return</span> <span class="title function_">proxy</span>(urlObj, reqInit, acehOld, rawLen, retryTimes + <span class="number">1</span>)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">makeRes</span>(res.<span class="property">body</span>, <span class="number">400</span>, &#123;</span><br><span class="line">        <span class="string">&#x27;--error&#x27;</span>: <span class="string">`bad len: <span class="subst">${%endraw%}&#123;newLen&#125;</span>, except: <span class="subst">$&#123;rawLen&#125;</span>`</span>,</span><br><span class="line">        <span class="string">&#x27;access-control-expose-headers&#x27;</span>: <span class="string">&#x27;--error&#x27;</span>,</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (retryTimes &gt; <span class="number">1</span>) &#123;</span><br><span class="line">      resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;--retry&#x27;</span>, retryTimes)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">let</span> status = res.<span class="property">status</span></span><br><span class="line"></span><br><span class="line">  resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;access-control-expose-headers&#x27;</span>, expose)</span><br><span class="line">  resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;access-control-allow-origin&#x27;</span>, <span class="string">&#x27;*&#x27;</span>)</span><br><span class="line">  resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;--s&#x27;</span>, status)</span><br><span class="line">  resHdrNew.<span class="title function_">set</span>(<span class="string">&#x27;--ver&#x27;</span>, <span class="variable constant_">JS_VER</span>)</span><br><span class="line"></span><br><span class="line">  resHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;content-security-policy&#x27;</span>)</span><br><span class="line">  resHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;content-security-policy-report-only&#x27;</span>)</span><br><span class="line">  resHdrNew.<span class="title function_">delete</span>(<span class="string">&#x27;clear-site-data&#x27;</span>)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (status === <span class="number">301</span> ||</span><br><span class="line">      status === <span class="number">302</span> ||</span><br><span class="line">      status === <span class="number">303</span> ||</span><br><span class="line">      status === <span class="number">307</span> ||</span><br><span class="line">      status === <span class="number">308</span></span><br><span class="line">  ) &#123;</span><br><span class="line">    status = status + <span class="number">10</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(res.<span class="property">body</span>, &#123;</span><br><span class="line">    status,</span><br><span class="line">    <span class="attr">headers</span>: resHdrNew,</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">URL</span>&#125; urlObj </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">isYtUrl</span>(<span class="params">urlObj</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    urlObj.<span class="property">host</span>.<span class="title function_">endsWith</span>(<span class="string">&#x27;.googlevideo.com&#x27;</span>) &amp;&amp;</span><br><span class="line">    urlObj.<span class="property">pathname</span>.<span class="title function_">startsWith</span>(<span class="string">&#x27;/videoplayback&#x27;</span>)</span><br><span class="line">  )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">URL</span>&#125; urlObj </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">number</span>&#125; newLen </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">Response</span>&#125; res </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">parseYtVideoRedir</span>(<span class="params">urlObj, newLen, res</span>) &#123;</span><br><span class="line">  <span class="keyword">if</span> (newLen &gt; <span class="number">2000</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (!<span class="title function_">isYtUrl</span>(urlObj)) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">try</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> data = <span class="keyword">await</span> res.<span class="title function_">text</span>()</span><br><span class="line">    urlObj = <span class="keyword">new</span> <span class="title function_">URL</span>(data)</span><br><span class="line">  &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (!<span class="title function_">isYtUrl</span>(urlObj)) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> urlObj</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后点击 “保存并部署”, </p><p><img src="5.png" alt=""></p><p>然后在右侧的红框框内, 就可以看到你的网页代理的网址, 类似 <a href="https://xxxx.xxxx.workers.dev">https://xxxx.xxxx.workers.dev</a> 这样的.</p><p>这样, 你的网页代理就搭建好啦! 只要访问网页代理的网址, 就可以突破 GFW 轻松浏览被墙的网站了.</p><h1 id="绑定域名"><a href="#绑定域名" class="headerlink" title="绑定域名"></a>绑定域名</h1><p>首先需要拥有一个域名 (可以去 <a href="https://www.freenom.com">Freenom</a> 获取免费域名) 并且将域名托管到 CloudFlare (什么你问我怎么托管??? <del>有手就行</del>). 然后进入你的域名界面, 进入 Workers,</p><p><img src="6.png" alt=""></p><p>然后点击 “添加路由” , 在 “路由” 内填写你的域名以及二级前缀 (不知道什么是二级域名的自行百度…) 格式为 <code>二级前缀.你的域名/*</code> 并且在 “Worker” 中选你刚刚部署的 Worker,</p><p><img src="7.png" alt=""></p><p>当然这样还没完, 进入你域名的 DNS 解析到 CloudFlare 给你的 Worker 的域名</p><p><img src="8,png" alt=""></p><p>其中 “类型” 选择 “CNAME” , “名称” 填你的二级前缀, 内容填 CloudFlare 给你的 Worker 的域名 (类似 xxx.xxx.workers.dev) 然后保存.</p><p>这样域名就绑定成功, 可以访问你自己的域名愉快的 FQ 啦!</p>]]></content>
      
      
      <categories>
          
          <category> 杂文 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 教程 </tag>
            
            <tag> 白嫖 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>零成本制作随机图片 API</title>
      <link href="/scribble/make_api/"/>
      <url>/scribble/make_api/</url>
      
        <content type="html"><![CDATA[<p>最近有小伙伴问我 <a href="https://api.yunist.cn">api.yunist.cn</a> 这个 API 是怎么做的, 其实非常简单, 用 <a href="https://leancloud.cn/">LeanCloud</a> 的免费实例做的, 废话不多说, 开干!</p><h1 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h1><h2 id="创建账号及应用"><a href="#创建账号及应用" class="headerlink" title="创建账号及应用"></a>创建账号及应用</h2><p>先去 <a href="https://leancloud.cn/">LeanCloud</a> 注册个账号 (建议使用国际版, 这样绑定域名的时候不需要备案, 域名已经备案了的请无视) . 然后去控制台创建一个应用, 选择开发版, 名字就叫 image-api 吧.</p><p><img src="1.png" alt=""></p><h2 id="下载命令行工具"><a href="#下载命令行工具" class="headerlink" title="下载命令行工具"></a>下载命令行工具</h2><p>详情请看<a href="https://leancloud.cn/docs/leanengine_cli.html#hash1443149115">安装命令行工具</a>.</p><h2 id="登录并初始化项目"><a href="#登录并初始化项目" class="headerlink" title="登录并初始化项目"></a>登录并初始化项目</h2><p>命令行输入</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lean login</span><br></pre></td></tr></table></figure><p>登录, 然后按照提示选择区域并输入 LeanCloud 用户名和密码完成登录.</p><p>然后随意创建一个新文件夹, 进入里面执行</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lean init</span><br></pre></td></tr></table></figure><p>然后会输出大概类似下面的信息</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[?] Please select an app: </span><br><span class="line"> 1) Valine-Admin</span><br><span class="line"> 2) image-api</span><br><span class="line"> =&gt; </span><br></pre></td></tr></table></figure><p>输入 <code>2</code> , 回车, 然后又会出现</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">[?] Please select a language</span><br><span class="line"> 1) Node.js</span><br><span class="line"> 2) Python</span><br><span class="line"> 3) Java</span><br><span class="line"> 4) PHP</span><br><span class="line"> 5) Others</span><br><span class="line"> =&gt; </span><br></pre></td></tr></table></figure><p>输入 <code>4</code> 回车, 然后…</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[?] Please select an app template: </span><br><span class="line"> 1) Slim</span><br><span class="line"> =&gt;</span><br></pre></td></tr></table></figure><p>输入 <code>1</code> 回车, 项目就在本地初始化了.</p><h1 id="实现随机-API"><a href="#实现随机-API" class="headerlink" title="实现随机 API"></a>实现随机 API</h1><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><p>进入 <code>public/index.php</code> , 然后就可以在这里写实现随机 API 的代码了. 至于如何写随机 API … 其实很简单, <del>百度一下就有了.</del></p><p>可以写成如下形式</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line"><span class="variable">{%raw%}$num</span> = <span class="number">58</span>;</span><br><span class="line"><span class="variable">${%endraw%}url</span> = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line"><span class="variable">{%raw%}$img</span> = <span class="title function_ invoke__">file_get_contents</span>(<span class="variable">${%endraw%}url</span>, <span class="literal">true</span>);</span><br><span class="line"><span class="title function_ invoke__">header</span>(<span class="string">&#x27;Content-Type: image/jpeg&#x27;</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">{%raw%}$img</span>;</span><br><span class="line"><span class="keyword">exit</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure><p>其中 <code>$&#123;%endraw%&#125;url</code> 变量需要你自己填写逻辑. 如果还是不会, 还是百度吧…. (Google 也可以哟)</p><h2 id="上传并部署"><a href="#上传并部署" class="headerlink" title="上传并部署"></a>上传并部署</h2><p>写完代码之后就是上传和部署了, 非常简单, 只需要</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lean deploy --prod 1</span><br></pre></td></tr></table></figure><p>就好了.</p><h1 id="绑定域名"><a href="#绑定域名" class="headerlink" title="绑定域名"></a>绑定域名</h1><h2 id="绑定-LeanCloud-域名"><a href="#绑定-LeanCloud-域名" class="headerlink" title="绑定 LeanCloud 域名"></a>绑定 LeanCloud 域名</h2><p>如果你没有独立域名的话, 就只能绑定 LeanCloud 的二级域名. 进入应用 -&gt; 云引擎 -&gt; 设置 -&gt; 云引擎域名设置域名, 填写你想要的域名, 然后保存就可以了.</p><p><img src="2.png" alt=""></p><h2 id="绑定独立域名"><a href="#绑定独立域名" class="headerlink" title="绑定独立域名"></a>绑定独立域名</h2><p>绑定独立域名需要你拥有自己的域名. 点击 “绑定独立域名” , </p><p><img src="3.png" alt=""></p><p>然后在 “云引擎、ClientEngine 域名” 下点击 “绑定新域名”,</p><p><img src="4.png" alt=""></p><p>然后写上你想要绑定的域名, 点击确定. 根据它的提示去你域名 DNS 解析所在服务商进行 CNAME 解析. 绑定成功后, 会提示 “已绑定” .</p><h1 id="开始使用"><a href="#开始使用" class="headerlink" title="开始使用"></a>开始使用</h1><p>只要访问你绑定的域名就可以啦! 现在你就拥有了一个属于自己的 API , 是不是很简单呢. 不过 LeanCloud 免费实例是有休眠政策的.</p><blockquote><p>如果最近 24 小时内累计运行超过 18 小时，则强制休眠。此时新的请求会收到 503 的错误响应码</p></blockquote><p>所以… 如果想要无限制使用, 可以升级实例.</p>]]></content>
      
      
      <categories>
          
          <category> 杂文 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 教程 </tag>
            
            <tag> 白嫖 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Spinning Up 研究笔记 (一) - VPG </title>
      <link href="/ML/RL/spinningup/vpg/"/>
      <url>/ML/RL/spinningup/vpg/</url>
      
        <content type="html"><![CDATA[<h1 id="解决报错"><a href="#解决报错" class="headerlink" title="解决报错"></a>解决报错</h1><p>代码文件在 <code>spinup/alogs/pytorch/vpg/vpg.py</code> . 我们尝试运行代码, 然后就报错了… </p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line">usage: ipykernel_launcher.py [-h] [--env_name ENV_NAME] [--render] [--lr LR]</span><br><span class="line">ipykernel_launcher.py: error: unrecognized arguments: -f xxxx.json</span><br><span class="line"></span><br><span class="line">An exception has occurred, use %tb to see the full traceback.</span><br><span class="line"></span><br><span class="line">SystemExit: <span class="number">2</span></span><br><span class="line"></span><br><span class="line">xxxx/anaconda3/lib/python3<span class="number">.7</span>/site-packages/IPython/core/interactiveshell.py:xxxx: UserWarning: To exit: use <span class="string">&#x27;exit&#x27;</span>, <span class="string">&#x27;quit&#x27;</span>, <span class="keyword">or</span> Ctrl-D.</span><br><span class="line">  warn(<span class="string">&quot;To exit: use &#x27;exit&#x27;, &#x27;quit&#x27;, or Ctrl-D.&quot;</span>, stacklevel=<span class="number">1</span>)</span><br></pre></td></tr></table></figure><p>嗯, 先看篇<a href="https://yunist.cn/python/another/python_error/">这篇文章</a>解决. 然后再次运行, 又报错… 这次又是啥 ?!</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line">--&gt; <span class="number">342</span>     mpi_fork(args.cpu)  <span class="comment"># run parallel code with mpi</span></span><br><span class="line">...</span><br><span class="line">CalledProcessError: Command <span class="string">&#x27;[&#x27;</span>mpirun<span class="string">&#x27;, &#x27;</span>-np<span class="string">&#x27;, &#x27;</span><span class="number">4</span><span class="string">&#x27;, &#x27;</span>xxxx/anaconda3/<span class="built_in">bin</span>/python<span class="string">&#x27;, &#x27;</span>xxxx/anaconda3/lib/python3<span class="number">.7</span>/site-packages/ipykernel_launcher.py<span class="string">&#x27;, &#x27;</span>-<span class="string">f&#x27;, &#x27;</span>xxxx/.local/share/jupyter/runtime/kernel-342bc725-7d2c-4cba-95f4-32c9b625dd61.json<span class="string">&#x27;]&#x27;</span> returned non-zero exit status <span class="number">1.</span></span><br></pre></td></tr></table></figure><p>观察了一下, 于是直接粗暴的删掉这一行 (就是这么任性) . 再次运行, 还是报错 ???</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">...</span><br><span class="line">DependencyNotInstalled: No module named <span class="string">&#x27;mujoco_py&#x27;</span>. (HINT: you need to install mujoco_py, <span class="keyword">and</span> also perform the setup instructions here: https://github.com/openai/mujoco-py/.)</span><br></pre></td></tr></table></figure><p>这个问题我弄了好久, 最后发现好像是环境的问题, 我们将参数中 <code>env</code> 的值 <code>HalfCheetah-v2</code> 改为 <code>CartPole-v0</code> , 也就是</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">parser.add_argument(<span class="string">&#x27;--env&#x27;</span>, <span class="built_in">type</span>=<span class="built_in">str</span>, default=<span class="string">&#x27;HalfCheetah-v2&#x27;</span>)</span><br></pre></td></tr></table></figure><p>改成</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">parser.add_argument(<span class="string">&#x27;--env&#x27;</span>, <span class="built_in">type</span>=<span class="built_in">str</span>, default=<span class="string">&#x27;CartPole-v0&#x27;</span>)</span><br></pre></td></tr></table></figure><p>然后再次运行. 终于, 成功运行了, 这下能够愉快的开启我们的代码研究之旅了.</p><h1 id="Vanilla-Policy-Gradient"><a href="#Vanilla-Policy-Gradient" class="headerlink" title="Vanilla Policy Gradient"></a>Vanilla Policy Gradient</h1><p>伪代码</p><p><img src="1.svg" alt=""></p><p>使用 $\text{GAE-Lambda}$ (广义优势估计) 来进行优势估计. 因此需要拟合价值函数 $V^{\pi}(s_t)$ , 进而计算策略梯度进行优化. 有关广义优势估计的文章<a href="https://yunist.cn/ML/RL/primer/GAE/">在这</a>.</p><h1 id="代码详解"><a href="#代码详解" class="headerlink" title="代码详解"></a>代码详解</h1><h2 id="VPGBuffer"><a href="#VPGBuffer" class="headerlink" title="VPGBuffer"></a>VPGBuffer</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">A buffer for storing trajectories experienced by a VPG agent interacting</span></span><br><span class="line"><span class="string">with the environment, and using Generalized Advantage Estimation (GAE-Lambda)</span></span><br><span class="line"><span class="string">for calculating the advantages of state-action pairs.</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br></pre></td></tr></table></figure><p>从注释以及变量名中我们可以看出 <code>VPGBuffer</code> 是用来储存采样轨迹的各种信息的. </p><h2 id="store"><a href="#store" class="headerlink" title="store"></a>store</h2><p>储存轨迹中的变量, 一个很简单的函数.</p><h2 id="finish-path"><a href="#finish-path" class="headerlink" title="finish_path"></a>finish_path</h2><p>结束一个 epoch 时调用的函数, 用之前储存的变量来计算 <code>adv_buf</code> (广义优势) 与<code>ret_buf</code> (回报). </p><h3 id="self-adv-buf"><a href="#self-adv-buf" class="headerlink" title="self.adv_buf"></a>self.adv_buf</h3><p>计算广义优势估计.</p><p><code>last_val</code> 的作用是方便计算 <code>deltas</code> , 而 <code>deltas</code> 就是 $\{\delta_1^V,\delta_2^V,\delta_3^V,\dots\}$ . (见广义优势估计)</p><p>其中计算优势时调用了一个重要的函数 <code>core.discount_cumsum</code> 这个函数在 <code>core.poy</code> 中有定义. 注释如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">magic from rllab for computing discounted cumulative sums of vectors.</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">input: </span></span><br><span class="line"><span class="string">    vector x, </span></span><br><span class="line"><span class="string">    [x0, </span></span><br><span class="line"><span class="string">     x1, </span></span><br><span class="line"><span class="string">     x2]</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">output:</span></span><br><span class="line"><span class="string">    [x0 + discount * x1 + discount^2 * x2,  </span></span><br><span class="line"><span class="string">     x1 + discount * x2,</span></span><br><span class="line"><span class="string">     x2]</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br></pre></td></tr></table></figure><p> 确实很 <code>magic</code> . 而由于输入是 <code>deltas</code> 与 <code>self.gamma * self.lam</code> 而由注释看出计算的其实就是广义优势估计 $ \hat{A}_t^{\mathrm{GAE}(\gamma,\lambda)}$ .</p><h3 id="self-ret-buf"><a href="#self-ret-buf" class="headerlink" title="self.ret_buf"></a>self.ret_buf</h3><p>计算有折损状态函数 $V^{\pi,\gamma}(s_t)$.</p><h2 id="VPG"><a href="#VPG" class="headerlink" title="VPG"></a>VPG</h2><p>注释中已经详细介绍了参数的意义和作用. 中间有很多保存变量, 多线程的东西, 我们都略过, 只讲算法主体部分.</p><h3 id="ac"><a href="#ac" class="headerlink" title="ac"></a>ac</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ac = actor_critic(env.observation_space, env.action_space, **ac_kwargs)</span><br></pre></td></tr></table></figure><p>由 <code>actor_critic</code> 对象生成,  <code>actor_critic</code> 是对象 <code>core.MLPActorCritic</code> , 该对象在 <code>core.py</code> 中被定义, 由其从 <code>torch.nn.Module</code> 继承可知这是个神经网络.</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MLPActorCritic</span>(nn.Module):</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, observation_space, action_space, </span></span><br><span class="line"><span class="params">                 hidden_sizes=(<span class="params"><span class="number">64</span>,<span class="number">64</span></span>), activation=nn.Tanh</span>):</span><br><span class="line">        <span class="built_in">super</span>().__init__()</span><br><span class="line"></span><br><span class="line">        obs_dim = observation_space.shape[<span class="number">0</span>]</span><br><span class="line"></span><br><span class="line">        <span class="comment"># policy builder depends on action space</span></span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">isinstance</span>(action_space, Box):</span><br><span class="line">            self.pi = MLPGaussianActor(obs_dim, action_space.shape[<span class="number">0</span>], hidden_sizes, activation)</span><br><span class="line">        <span class="keyword">elif</span> <span class="built_in">isinstance</span>(action_space, Discrete):</span><br><span class="line">            self.pi = MLPCategoricalActor(obs_dim, action_space.n, hidden_sizes, activation)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># build value function</span></span><br><span class="line">        self.v  = MLPCritic(obs_dim, hidden_sizes, activation)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">step</span>(<span class="params">self, obs</span>):</span><br><span class="line">        <span class="keyword">with</span> torch.no_grad():</span><br><span class="line">            pi = self.pi._distribution(obs)</span><br><span class="line">            a = pi.sample()</span><br><span class="line">            logp_a = self.pi._log_prob_from_distribution(pi, a)</span><br><span class="line">            v = self.v(obs)</span><br><span class="line">        <span class="keyword">return</span> a.numpy(), v.numpy(), logp_a.numpy()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">act</span>(<span class="params">self, obs</span>):</span><br><span class="line">        <span class="keyword">return</span> self.step(obs)[<span class="number">0</span>]</span><br></pre></td></tr></table></figure><p><code>self.pi</code> 与 <code>self.v</code> 分别是动作函数与价值函数.</p><p>其中出现了判断 <code>action_space</code> 是 <code>Box</code> 还是 <code>Discrete</code> 类型的代码. <code>Box</code> 与 <code>Discrete</code> 都是 <code>Space</code> 对象, 描述当前动作或环境. 其中 <code>Box</code> 表示多维连续空间, <code>Discrete</code> 表示一维离散空间. <code>MLPGaussianActor</code> 与 <code>MLPCategoricalActor</code> 都分别刻画了一个神经网络. 其输入 <code>obs_dim</code> 个数据, 输出 <code>action_space.n</code> 或者 <code>action_space.shape[0]</code> 个数据, 并且隐层由 <code>hidden_sizes</code> 指定.</p><p>总之, <code>ac</code> 是两个神经网络的集合, 一个是动作函数, 一个是价值函数.</p><h3 id="var-counts"><a href="#var-counts" class="headerlink" title="var_counts"></a>var_counts</h3><p>查看定义, 其计算的是神经网络变量的个数 (激活函数也算) .</p><h3 id="compute-loss-pi"><a href="#compute-loss-pi" class="headerlink" title="compute_loss_pi"></a>compute_loss_pi</h3><p>计算动作的损失, 对参数求导正是参数的梯度.</p><p>对参数求导后相当于用了广义优势估计 <code>adv</code> 来估计梯度.</p><h3 id="compute-loss-v"><a href="#compute-loss-v" class="headerlink" title="compute_loss_v"></a>compute_loss_v</h3><p>计算价值的损失, 采用了均方误差.</p><p>从返回值为 <code>((ac.v(obs) - ret)**2).mean()</code> 可以看出其拟合的是 <code>ret</code> 变量 (对应广义优势估计中的 $V^{\pi,\gamma}(s_t)$), 也就是状态函数 (有折损的).</p><h3 id="update"><a href="#update" class="headerlink" title="update"></a>update</h3><p>一个函数, 是一次 epoch 后更新参数的过程, 其中先优化策略 (<code>pi_optimizer</code>) , 然后依据 <code>train_v_tiers</code> (每次 epoch 优化价值函数参数的次数) 多次优化价值函数 (<code>vf_optimizer</code>) .</p><h3 id="训练过程"><a href="#训练过程" class="headerlink" title="训练过程"></a>训练过程</h3><p>先在环境中 “走” 出一个 epoch (一个 epoch 的交互数 (interaction) 由 <code>steps_per_epoch</code> 指定), 然后调用 <code>update</code>  函数优化.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> Spinning Up </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> Python </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> Pytorch </tag>
            
            <tag> 代码实例 </tag>
            
            <tag> Spinning Up </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Spinning Up 研究笔记 (零) - 开端</title>
      <link href="/ML/RL/spinningup/begin/"/>
      <url>/ML/RL/spinningup/begin/</url>
      
        <content type="html"><![CDATA[<p>这个 “零” 主要是说明我写这个笔记的目的以及一些期望. Spinning Up 算是第一个我真正学习的 RL 项目, 我希望把 Spinning Up 项目中实现的算法都讲解一遍.</p><h1 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h1><p>首先 clone 下 <a href="https://github.com/openai/spinningup/">spinningup 项目</a> (不要告诉我你连 Git 都没下载),</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/openai/spinningup.git</span><br></pre></td></tr></table></figure><p>然后按照<a href="https://spinningup.openai.com/en/latest/user/installation.html">spinningup 安装教程</a>将该装的都装一遍, 接下来的代码都在其中执行. </p><h1 id="已经完成的"><a href="#已经完成的" class="headerlink" title="已经完成的"></a>已经完成的</h1><ul><li><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1></li></ul><ul><li><a href="https://spinningup.openai.com/en/latest/">OpenAI Spinning Up 文档</a></li><li><a href="https://github.com/openai/spinningup/">Spinning Up Github 项目</a></li></ul>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> Spinning Up </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> Spinning Up </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Intro to Policy Optimization 代码详解</title>
      <link href="/ML/RL/primer/Intro_to_Policy_Optimization_code/"/>
      <url>/ML/RL/primer/Intro_to_Policy_Optimization_code/</url>
      
        <content type="html"><![CDATA[<p>本篇文章是 OpenAI Spinnging Up 中 Part 3: Intro to Policy Optimization 中代码的学习笔记, 原文在 <a href="https://spinningup.openai.com/en/latest/spinningup/rl_intro3.html">https://spinningup.openai.com/en/latest/spinningup/rl_intro3.html</a> , 代码在 <a href="https://github.com/openai/spinningup/blob/master/spinup/examples/pytorch/pg_math/1_simple_pg.py">https://github.com/openai/spinningup/blob/master/spinup/examples/pytorch/pg_math/1_simple_pg.py</a> .</p><p>先给出代码</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> torch</span><br><span class="line"><span class="keyword">import</span> torch.nn <span class="keyword">as</span> nn</span><br><span class="line"><span class="keyword">from</span> torch.distributions.categorical <span class="keyword">import</span> Categorical</span><br><span class="line"><span class="keyword">from</span> torch.optim <span class="keyword">import</span> Adam</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> gym</span><br><span class="line"><span class="keyword">from</span> gym.spaces <span class="keyword">import</span> Discrete, Box</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">mlp</span>(<span class="params">sizes, activation=nn.Tanh, output_activation=nn.Identity</span>):</span><br><span class="line">    <span class="comment"># Build a feedforward neural network.</span></span><br><span class="line">    layers = []</span><br><span class="line">    <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(sizes)-<span class="number">1</span>):</span><br><span class="line">        act = activation <span class="keyword">if</span> j &lt; <span class="built_in">len</span>(sizes)-<span class="number">2</span> <span class="keyword">else</span> output_activation</span><br><span class="line">        layers += [nn.Linear(sizes[j], sizes[j+<span class="number">1</span>]), act()]</span><br><span class="line">    <span class="keyword">return</span> nn.Sequential(*layers)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">train</span>(<span class="params">env_name=<span class="string">&#x27;CartPole-v0&#x27;</span>, hidden_sizes=[<span class="number">32</span>], lr=<span class="number">1e-2</span>, </span></span><br><span class="line"><span class="params">          epochs=<span class="number">50</span>, batch_size=<span class="number">5000</span>, render=<span class="literal">False</span></span>):</span><br><span class="line"></span><br><span class="line">    <span class="comment"># make environment, check spaces, get obs / act dims</span></span><br><span class="line">    env = gym.make(env_name)</span><br><span class="line">    <span class="keyword">assert</span> <span class="built_in">isinstance</span>(env.observation_space, Box), \</span><br><span class="line">        <span class="string">&quot;This example only works for envs with continuous state spaces.&quot;</span></span><br><span class="line">    <span class="keyword">assert</span> <span class="built_in">isinstance</span>(env.action_space, Discrete), \</span><br><span class="line">        <span class="string">&quot;This example only works for envs with discrete action spaces.&quot;</span></span><br><span class="line"></span><br><span class="line">    obs_dim = env.observation_space.shape[<span class="number">0</span>]</span><br><span class="line">    n_acts = env.action_space.n</span><br><span class="line"></span><br><span class="line">    <span class="comment"># make core of policy network</span></span><br><span class="line">    logits_net = mlp(sizes=[obs_dim]+hidden_sizes+[n_acts])</span><br><span class="line"></span><br><span class="line">    <span class="comment"># make function to compute action distribution</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">get_policy</span>(<span class="params">obs</span>):</span><br><span class="line">        logits = logits_net(obs)</span><br><span class="line">        <span class="keyword">return</span> Categorical(logits=logits)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># make action selection function (outputs int actions, sampled from policy)</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">get_action</span>(<span class="params">obs</span>):</span><br><span class="line">        <span class="keyword">return</span> get_policy(obs).sample().item()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># make loss function whose gradient, for the right data, is policy gradient</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">compute_loss</span>(<span class="params">obs, act, weights</span>):</span><br><span class="line">        logp = get_policy(obs).log_prob(act)</span><br><span class="line">        <span class="keyword">return</span> -(logp * weights).mean()</span><br><span class="line"></span><br><span class="line">    <span class="comment"># make optimizer</span></span><br><span class="line">    optimizer = Adam(logits_net.parameters(), lr=lr)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># for training policy</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">train_one_epoch</span>():</span><br><span class="line">        <span class="comment"># make some empty lists for logging.</span></span><br><span class="line">        batch_obs = []          <span class="comment"># for observations</span></span><br><span class="line">        batch_acts = []         <span class="comment"># for actions</span></span><br><span class="line">        batch_weights = []      <span class="comment"># for R(tau) weighting in policy gradient</span></span><br><span class="line">        batch_rets = []         <span class="comment"># for measuring episode returns</span></span><br><span class="line">        batch_lens = []         <span class="comment"># for measuring episode lengths</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># reset episode-specific variables</span></span><br><span class="line">        obs = env.reset()       <span class="comment"># first obs comes from starting distribution</span></span><br><span class="line">        done = <span class="literal">False</span>            <span class="comment"># signal from environment that episode is over</span></span><br><span class="line">        ep_rews = []            <span class="comment"># list for rewards accrued throughout ep</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># render first episode of each epoch</span></span><br><span class="line">        finished_rendering_this_epoch = <span class="literal">False</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># collect experience by acting in the environment with current policy</span></span><br><span class="line">        <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line"></span><br><span class="line">            <span class="comment"># rendering</span></span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">not</span> finished_rendering_this_epoch) <span class="keyword">and</span> render:</span><br><span class="line">                env.render()</span><br><span class="line"></span><br><span class="line">            <span class="comment"># save obs</span></span><br><span class="line">            batch_obs.append(obs.copy())</span><br><span class="line"></span><br><span class="line">            <span class="comment"># act in the environment</span></span><br><span class="line">            act = get_action(torch.as_tensor(obs, dtype=torch.float32))</span><br><span class="line">            obs, rew, done, _ = env.step(act)</span><br><span class="line"></span><br><span class="line">            <span class="comment"># save action, reward</span></span><br><span class="line">            batch_acts.append(act)</span><br><span class="line">            ep_rews.append(rew)</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> done:</span><br><span class="line">                <span class="comment"># if episode is over, record info about episode</span></span><br><span class="line">                ep_ret, ep_len = <span class="built_in">sum</span>(ep_rews), <span class="built_in">len</span>(ep_rews)</span><br><span class="line">                batch_rets.append(ep_ret)</span><br><span class="line">                batch_lens.append(ep_len)</span><br><span class="line"></span><br><span class="line">                <span class="comment"># the weight for each logprob(a|s) is R(tau)</span></span><br><span class="line">                batch_weights += [ep_ret] * ep_len</span><br><span class="line"></span><br><span class="line">                <span class="comment"># reset episode-specific variables</span></span><br><span class="line">                obs, done, ep_rews = env.reset(), <span class="literal">False</span>, []</span><br><span class="line"></span><br><span class="line">                <span class="comment"># won&#x27;t render again this epoch</span></span><br><span class="line">                finished_rendering_this_epoch = <span class="literal">True</span></span><br><span class="line"></span><br><span class="line">                <span class="comment"># end experience loop if we have enough of it</span></span><br><span class="line">                <span class="keyword">if</span> <span class="built_in">len</span>(batch_obs) &gt; batch_size:</span><br><span class="line">                    <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># take a single policy gradient update step</span></span><br><span class="line">        optimizer.zero_grad()</span><br><span class="line">        batch_loss = compute_loss(obs=torch.as_tensor(batch_obs, dtype=torch.float32),</span><br><span class="line">                                  act=torch.as_tensor(batch_acts, dtype=torch.int32),</span><br><span class="line">                                  weights=torch.as_tensor(batch_weights, dtype=torch.float32)</span><br><span class="line">                                  )</span><br><span class="line">        batch_loss.backward()</span><br><span class="line">        optimizer.step()   </span><br><span class="line">        <span class="keyword">return</span> batch_loss, batch_rets, batch_lens</span><br><span class="line"></span><br><span class="line">    <span class="comment"># training loop</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(epochs):</span><br><span class="line">        batch_loss, batch_rets, batch_lens = train_one_epoch()</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&#x27;epoch: %3d \t loss: %.3f \t return: %.3f \t ep_len: %.3f&#x27;</span>%</span><br><span class="line">                (i, batch_loss, np.mean(batch_rets), np.mean(batch_lens)))</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="keyword">import</span> argparse</span><br><span class="line">    parser = argparse.ArgumentParser()</span><br><span class="line">    parser.add_argument(<span class="string">&#x27;--env_name&#x27;</span>, <span class="string">&#x27;--env&#x27;</span>, <span class="built_in">type</span>=<span class="built_in">str</span>, default=<span class="string">&#x27;CartPole-v0&#x27;</span>)</span><br><span class="line">    parser.add_argument(<span class="string">&#x27;--render&#x27;</span>, action=<span class="string">&#x27;store_true&#x27;</span>)</span><br><span class="line">    parser.add_argument(<span class="string">&#x27;--lr&#x27;</span>, <span class="built_in">type</span>=<span class="built_in">float</span>, default=<span class="number">1e-2</span>)</span><br><span class="line">    args, unknown = parser.parse_known_args()</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&#x27;\nUsing simplest formulation of policy gradient.\n&#x27;</span>)</span><br><span class="line">    train(env_name=args.env_name, render=args.render, lr=args.lr)</span><br></pre></td></tr></table></figure><p>这里我们会对大部分函数以及一些变量一一解析, 其中一些 Pytorch 的 API 可以参考我的<a href="https://yunist.cn/ML/framework/Pytroch/pytorch_api/">这篇文章</a>或者<a href="https://pytorch.org/docs/stable/index.html">官方文档</a> .</p><h1 id="mlp"><a href="#mlp" class="headerlink" title="mlp"></a>mlp</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">mlp</span>(<span class="params">sizes, activation=nn.Tanh, output_activation=nn.Identity</span>):</span><br><span class="line">    <span class="comment"># Build a feedforward neural network.</span></span><br><span class="line">    layers = []</span><br><span class="line">    <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(sizes)-<span class="number">1</span>):</span><br><span class="line">        act = activation <span class="keyword">if</span> j &lt; <span class="built_in">len</span>(sizes)-<span class="number">2</span> <span class="keyword">else</span> output_activation</span><br><span class="line">        layers += [nn.Linear(sizes[j], sizes[j+<span class="number">1</span>]), act()]</span><br><span class="line">    <span class="keyword">return</span> nn.Sequential(*layers)</span><br></pre></td></tr></table></figure><p>依据输入返回一个神经网络.</p><h2 id="参数"><a href="#参数" class="headerlink" title="参数"></a>参数</h2><ul><li><p><code>sizes</code></p><p>其中包含神经网络的层数以及节点数信息</p></li><li><p><code>activation</code></p><p>节点的激活函数, 这里默认是 <code>nn.Tanh</code> 也就是 $\tanh$ 函数</p></li><li><p><code>output_activation</code></p><p>输出的激活函数</p></li></ul><h2 id="解析"><a href="#解析" class="headerlink" title="解析"></a>解析</h2><p><code>layers</code> 中的每一个元素就是神经网络的一部分 (节点与激活函数), 而 <code>nn.Sequential(*layers)</code> 是将这些部分组合成一个神经网络. 其中</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(sizes)-<span class="number">1</span>):</span><br><span class="line">        act = activation <span class="keyword">if</span> j &lt; <span class="built_in">len</span>(sizes)-<span class="number">2</span> <span class="keyword">else</span> output_activation</span><br><span class="line">        layers += [nn.Linear(sizes[j], sizes[j+<span class="number">1</span>]), act()]</span><br></pre></td></tr></table></figure><p>这个循环, <code>act</code> 指的是激活函数, 当该层不是最后一层时使用 <code>activation</code> , 是时使用 <code>output_activation</code> 作为激活函数.</p><h1 id="get-policy"><a href="#get-policy" class="headerlink" title="get_policy"></a>get_policy</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">get_policy</span>(<span class="params">obs</span>):</span><br><span class="line">    logits = logits_net(obs)</span><br><span class="line">    <span class="keyword">return</span> Categorical(logits=logits)</span><br></pre></td></tr></table></figure><p>依据环境计算出动作的对数概率, 并依此返回一个 <code>Categorical</code> 对象.</p><h2 id="参数-1"><a href="#参数-1" class="headerlink" title="参数"></a>参数</h2><ul><li><p><code>obs</code></p><p>环境的参数, 描述了环境</p></li></ul><h2 id="解析-1"><a href="#解析-1" class="headerlink" title="解析"></a>解析</h2><p><code>logits_net</code> 是一个神经网络, 接受参数后输出最终结果 (动作的对数概率). 至于 <code>Categorical</code> 对象请自行了解.</p><h1 id="get-action"><a href="#get-action" class="headerlink" title="get_action"></a>get_action</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">get_action</span>(<span class="params">obs</span>):</span><br><span class="line">    <span class="keyword">return</span> get_policy(obs).sample().item()</span><br></pre></td></tr></table></figure><h2 id="参数-2"><a href="#参数-2" class="headerlink" title="参数"></a>参数</h2><ul><li><p><code>obs</code></p><p>环境的参数, 描述了环境.</p></li></ul><h2 id="解析-2"><a href="#解析-2" class="headerlink" title="解析"></a>解析</h2><p>利用 <code>Categorical</code> 对象采样动作.</p><h1 id="compute-loss"><a href="#compute-loss" class="headerlink" title="compute_loss"></a>compute_loss</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">compute_loss</span>(<span class="params">obs, act, weights</span>):</span><br><span class="line">    logp = get_policy(obs).log_prob(act)</span><br><span class="line">    <span class="keyword">return</span> -(logp * weights).mean()</span><br></pre></td></tr></table></figure><p>计算损失.</p><h2 id="参数-3"><a href="#参数-3" class="headerlink" title="参数"></a>参数</h2><ul><li><p><code>obs</code></p><p>环境的参数, 描述了环境</p></li><li><p><code>act</code></p><p>采样的动作</p></li><li><p><code>weights</code></p><p>某项的权重</p></li></ul><h2 id="解析-3"><a href="#解析-3" class="headerlink" title="解析"></a>解析</h2><p>损失函数对参数的梯度要和期望回报对参数的梯度相同, 而期望回报对参数的梯度的估计式为<br>$$\hat{g}=\frac{1}{|\mathcal{D}|}\sum_{\tau\in\mathcal{D}}\sum^T_{t=0}\nabla_\theta\log \pi_\theta(a_t\mid s_t)R(\tau)$$<br><code>logp</code> 其实就是 $\log \pi_\theta(a_t\mid s_t)$ , 而 <code>weight</code> 其实就是 $R(\tau)$ . 因此该函数返回的其实就是<br>$$\frac{1}{|\mathcal{D}|}\sum_{\tau\in\mathcal{D}}\sum^T_{t=0}\log \pi_\theta(a_t\mid s_t)R(\tau)$$<br>对 $\theta$ 求导后正是我们的梯度.</p><h1 id="train-one-epoch"><a href="#train-one-epoch" class="headerlink" title="train_one_epoch"></a>train_one_epoch</h1><p>这是训练一个 epoch 的函数 (神经网络参数更新一次) .</p><h2 id="解析-4"><a href="#解析-4" class="headerlink" title="解析"></a>解析</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> done:</span><br><span class="line">    <span class="comment"># if episode is over, record info about episode</span></span><br><span class="line">    ep_ret, ep_len = <span class="built_in">sum</span>(ep_rews), <span class="built_in">len</span>(ep_rews)</span><br><span class="line">    batch_rets.append(ep_ret)</span><br><span class="line">    batch_lens.append(ep_len)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># the weight for each logprob(a|s) is R(tau)</span></span><br><span class="line">    batch_weights += [ep_ret] * ep_len</span><br><span class="line"></span><br><span class="line">    <span class="comment"># reset episode-specific variables</span></span><br><span class="line">    obs, done, ep_rews = env.reset(), <span class="literal">False</span>, []</span><br><span class="line"></span><br><span class="line">    <span class="comment"># won&#x27;t render again this epoch</span></span><br><span class="line">    finished_rendering_this_epoch = <span class="literal">True</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># end experience loop if we have enough of it</span></span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(batch_obs) &gt; batch_size:</span><br><span class="line">        <span class="keyword">break</span></span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># take a single policy gradient update step</span></span><br><span class="line">optimizer.zero_grad()</span><br><span class="line">batch_loss = compute_loss(obs=torch.as_tensor(batch_obs, dtype=torch.float32),</span><br><span class="line">                          act=torch.as_tensor(batch_acts, dtype=torch.int32),</span><br><span class="line">                          weights=torch.as_tensor(batch_weights, dtype=torch.float32)</span><br><span class="line">                          )</span><br><span class="line">batch_loss.backward()</span><br><span class="line">optimizer.step()   </span><br></pre></td></tr></table></figure><p>依据 <code>batch_size</code> 确定走一个 epoch 走多少步. 然后当某个轨迹结束时 (也就是 <code>done</code> ) , 会计算总的回报, 然后通过 <code>compute_loss</code> 计算损失, 同时通过 Pytorch 的自动求导机制算出梯度, 然后用 <code>optimizer</code> (Adam 算法) 更新.</p><h1 id="train"><a href="#train" class="headerlink" title="train"></a>train</h1><p>整个过程其实就是重复多个 epoch , 然后最终训练 <code>epochs</code> 次. 如果需要利用 Gym 的可视化, 可以将 <code>render</code> 参数设为 <code>True</code></p><h2 id="参数-4"><a href="#参数-4" class="headerlink" title="参数"></a>参数</h2><ul><li><p><code>env_name</code></p><p>Gym 环境的名称</p></li><li><p><code>hidden_sizes</code></p><p>神经网络隐藏节点数, 可以自行调整</p></li><li><p><code>lr</code></p><p>学习率.</p></li><li><p><code>epochs</code></p><p>训练的 epoch 数</p></li><li><p><code>batch_size</code></p><p>一次 epoch 行动的次数</p></li><li><p><code>render</code></p><p>Gym 是否可视化 (<code>True</code> or <code>False</code>)</p></li></ul>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 入门 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> Python </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> Pytorch </tag>
            
            <tag> 代码实例 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python 各种报错解决</title>
      <link href="/python/another/python_error/"/>
      <url>/python/another/python_error/</url>
      
        <content type="html"><![CDATA[<p>这里只是列出我在学习过程中出现的各种错误以及解决方法, 并不代表我了解报错产生的原因以及解决的原理, 所以可能有时候并不起效. 在这里 <code>xxxx</code> 代表任意字符串 (避免出现每个人的报错因路径或其他原因而不同, 但是相同的字符串一般会给出) , <code>...</code> 代表大段字符串.</p><p>1.</p><p><strong>报错</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">usage: ipykernel_launcher.py [-h] [--env_name ENV_NAME] [--render] [--lr LR]</span><br><span class="line">ipykernel_launcher.py: error: unrecognized arguments: -f xxxx.json</span><br><span class="line"></span><br><span class="line">An exception has occurred, use %tb to see the full traceback.</span><br><span class="line"></span><br><span class="line">SystemExit: <span class="number">2</span></span><br><span class="line"></span><br><span class="line">xxxx/anaconda3/lib/python3<span class="number">.7</span>/site-packages/IPython/core/interactiveshell.py:xxxx: UserWarning: To exit: use <span class="string">&#x27;exit&#x27;</span>, <span class="string">&#x27;quit&#x27;</span>, <span class="keyword">or</span> Ctrl-D.</span><br><span class="line">  warn(<span class="string">&quot;To exit: use &#x27;exit&#x27;, &#x27;quit&#x27;, or Ctrl-D.&quot;</span>, stacklevel=<span class="number">1</span>)</span><br></pre></td></tr></table></figure><p><strong>解决</strong></p><p>将代码中的</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">args = parser.parse_args()</span><br></pre></td></tr></table></figure><p>替换为</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">args, _ = parser.parse_known_args()</span><br></pre></td></tr></table></figure><p>当然变量名可能不同, 将 args 替换为你使用的变量名就好了.</p><hr><p>2.</p><p><strong>报错</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[In] !pip install xxxx</span><br><span class="line">[Out] </span><br><span class="line">...</span><br><span class="line">MemoryError</span><br></pre></td></tr></table></figure><p><strong>解决</strong></p><p>使用 <code>–no-cache-dir</code> 参数</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">!pip –no-cache-<span class="built_in">dir</span> install xxxx</span><br></pre></td></tr></table></figure><p>如果还是不行, 请升级 pip 再试一次</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pip install --upgrade pip</span><br><span class="line">!pip –no-cache-<span class="built_in">dir</span> install xxxx</span><br></pre></td></tr></table></figure><hr>]]></content>
      
      
      <categories>
          
          <category> Python </category>
          
          <category> 其他 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 问题 </tag>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>一份 Pytorch API 指南</title>
      <link href="/ML/framework/Pytroch/pytorch_api/"/>
      <url>/ML/framework/Pytroch/pytorch_api/</url>
      
        <content type="html"><![CDATA[<p>这份指南会将我遇到的 pytorch api 的作用都记录下来, 因此内容会不断更新. 某些非常常用并且简单的就不会在这里列出, 比如说 <code>torch.tensor</code> .</p><h1 id="torch-distributions"><a href="#torch-distributions" class="headerlink" title="torch.distributions"></a>torch.distributions</h1><h2 id="torch-distributions-categorical"><a href="#torch-distributions-categorical" class="headerlink" title="torch.distributions.categorical"></a>torch.distributions.categorical</h2><h3 id="torch-distributions-categorical-Categorical"><a href="#torch-distributions-categorical-Categorical" class="headerlink" title="torch.distributions.categorical.Categorical"></a>torch.distributions.categorical.Categorical</h3><blockquote><p>CLASS</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">torch.distributions.categorical.Categorical(probs=<span class="literal">None</span>, logits=<span class="literal">None</span>, validate_args=<span class="literal">None</span>)</span><br></pre></td></tr></table></figure></blockquote><p>依据参数 <code>probs</code> 与 <code>logits</code> 来采样.</p><p>例子:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">m = Categorical(torch.tensor([<span class="number">0.25</span>, <span class="number">0.25</span>, <span class="number">0.25</span>, <span class="number">0.25</span>]))</span><br><span class="line">m.sample()  <span class="comment"># 在 0, 1, 2, 3 中等概率采样</span></span><br><span class="line"></span><br><span class="line">输出: </span><br><span class="line">    tensor(<span class="number">3</span>)</span><br><span class="line"></span><br><span class="line">m = Categorical(torch.tensor([[<span class="number">0.25</span>, <span class="number">0.25</span>, <span class="number">0.25</span>, <span class="number">0.25</span>], [<span class="number">0.25</span>, <span class="number">0.25</span>, <span class="number">0.25</span>, <span class="number">0.25</span>]]))</span><br><span class="line">m.sample()</span><br><span class="line"></span><br><span class="line">输出: </span><br><span class="line">    tensor([<span class="number">0</span>, <span class="number">2</span>])</span><br></pre></td></tr></table></figure><p>参数:</p><ul><li><p><code>prob</code> <em>(Tensor)</em></p><p><code>prob</code> 是 $N$ 维向量, 同时采样输出为 $N-1$ 维向量. <code>prob</code> 其中包含的每个 $1$ 维向量为该结果中该位置数据的概率向量.</p><blockquote><p><strong>注意:  <code>prob</code> 必须是非负的, 有限的, 并且和不为 0 . 它会被标准化为和为 1 的形式.</strong></p></blockquote></li><li><p><code>logits</code> <em>(Tensor)</em></p><p><code>prob</code> 的对数概率版本.</p><blockquote><p><strong>注意: <code>prob</code> 与 <code>logits</code> 不能同时使用.</strong></p></blockquote></li></ul><h1 id="torch-nn"><a href="#torch-nn" class="headerlink" title="torch.nn"></a>torch.nn</h1><h2 id="torch-nn-Identity"><a href="#torch-nn-Identity" class="headerlink" title="torch.nn.Identity"></a>torch.nn.Identity</h2><blockquote><p>CLASS</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">torch.nn.Identity(*args, **kwargs)</span><br></pre></td></tr></table></figure></blockquote><p>建立起一个输入模块, 什么都不做, 一般用于神经网络的输入层.</p><p>例子:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">m = nn.Identity(<span class="number">12</span>, <span class="number">2342</span>, abc=<span class="number">123</span>, asdfasudfio=<span class="number">23452345</span>)  <span class="comment"># 随意的参数</span></span><br><span class="line">m(torch.randn(<span class="number">128</span>, <span class="number">20</span>)).shape</span><br><span class="line"></span><br><span class="line">输出:</span><br><span class="line">    torch.Size([<span class="number">128</span>, <span class="number">20</span>])</span><br></pre></td></tr></table></figure><p>参数:</p><ul><li>参数是任意的, 并且没有任何影响.</li></ul><h2 id="torch-nn-Linear"><a href="#torch-nn-Linear" class="headerlink" title="torch.nn.Linear"></a>torch.nn.Linear</h2><blockquote><p>CLASS</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">torch.nn.Linear(in_features, out_features, bias=<span class="literal">True</span>)</span><br></pre></td></tr></table></figure></blockquote><p>用在线性方程 $y=xA^{\mathrm{T}}+b$ 中.</p><p>例子:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">m = nn.Linear(<span class="number">20</span>, <span class="number">30</span>)</span><br><span class="line"><span class="built_in">input</span> = torch.randn(<span class="number">128</span>, <span class="number">20</span>)</span><br><span class="line">output = m(<span class="built_in">input</span>)</span><br><span class="line">output.shape</span><br><span class="line"></span><br><span class="line">输出:</span><br><span class="line">    torch.Size([<span class="number">128</span>, <span class="number">30</span>])</span><br></pre></td></tr></table></figure><h2 id="torch-nn-Tanh"><a href="#torch-nn-Tanh" class="headerlink" title="torch.nn.Tanh"></a>torch.nn.Tanh</h2><blockquote><p>CLASS</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">torch.nn.Tanh</span><br></pre></td></tr></table></figure></blockquote><p>用于元素的函数:<br>$$\mathrm{Tanh}(x)=\tanh(x)=\frac{\exp(x)-\exp(-x)}{\exp(x)+\exp(-x)}$$<br><img src="/media/cloud/work/%E6%96%87%E7%AB%A0/%E4%B8%80%E4%BB%BD%20pytorch%20api%20%E6%8C%87%E5%8D%97/1.png" alt=""></p><p>例子:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">m = nn.Tanh()</span><br><span class="line">m(torch.Tensor([<span class="number">1</span>, <span class="number">3</span>, <span class="number">0.5</span>]))</span><br><span class="line"></span><br><span class="line">输出:</span><br><span class="line">    tensor([<span class="number">0.7616</span>, <span class="number">0.9951</span>, <span class="number">0.4621</span>])</span><br></pre></td></tr></table></figure><h2 id="torch-nn-Sequential"><a href="#torch-nn-Sequential" class="headerlink" title="torch.nn.Sequential"></a>torch.nn.Sequential</h2><blockquote><p>CLASS</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">torch.nn.Sequential(*args)</span><br></pre></td></tr></table></figure></blockquote><p>一个序列容器.</p><p>例子:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">nn.Sequential(</span><br><span class="line">    nn.Conv2d(<span class="number">1</span>,<span class="number">20</span>,<span class="number">5</span>),</span><br><span class="line">    nn.ReLU(),</span><br><span class="line">    nn.Conv2d(<span class="number">20</span>,<span class="number">64</span>,<span class="number">5</span>),</span><br><span class="line">    nn.ReLU()</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">输出:</span><br><span class="line">    Sequential(</span><br><span class="line">      (<span class="number">0</span>): Conv2d(<span class="number">1</span>, <span class="number">20</span>, kernel_size=(<span class="number">5</span>, <span class="number">5</span>), stride=(<span class="number">1</span>, <span class="number">1</span>))</span><br><span class="line">      (<span class="number">1</span>): ReLU()</span><br><span class="line">      (<span class="number">2</span>): Conv2d(<span class="number">20</span>, <span class="number">64</span>, kernel_size=(<span class="number">5</span>, <span class="number">5</span>), stride=(<span class="number">1</span>, <span class="number">1</span>))</span><br><span class="line">      (<span class="number">3</span>): ReLU()</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> OrderedDict</span><br><span class="line">nn.Sequential(OrderedDict([</span><br><span class="line">    (<span class="string">&#x27;conv1&#x27;</span>, nn.Conv2d(<span class="number">1</span>,<span class="number">20</span>,<span class="number">5</span>)),</span><br><span class="line">    (<span class="string">&#x27;relu1&#x27;</span>, nn.ReLU()),</span><br><span class="line">    (<span class="string">&#x27;conv2&#x27;</span>, nn.Conv2d(<span class="number">20</span>,<span class="number">64</span>,<span class="number">5</span>)),</span><br><span class="line">    (<span class="string">&#x27;relu2&#x27;</span>, nn.ReLU())</span><br><span class="line">]))</span><br><span class="line"></span><br><span class="line">输出:</span><br><span class="line">    Sequential(</span><br><span class="line">      (conv1): Conv2d(<span class="number">1</span>, <span class="number">20</span>, kernel_size=(<span class="number">5</span>, <span class="number">5</span>), stride=(<span class="number">1</span>, <span class="number">1</span>))</span><br><span class="line">      (relu1): ReLU()</span><br><span class="line">      (conv2): Conv2d(<span class="number">20</span>, <span class="number">64</span>, kernel_size=(<span class="number">5</span>, <span class="number">5</span>), stride=(<span class="number">1</span>, <span class="number">1</span>))</span><br><span class="line">      (relu2): ReLU()</span><br><span class="line">    )</span><br></pre></td></tr></table></figure><h1 id="torch-optim"><a href="#torch-optim" class="headerlink" title="torch.optim"></a>torch.optim</h1><p>方法:</p><ul><li><p><code>optimizer.step()</code></p><p>在使用 <code>backward()</code> 后可以调用该方法执行一次优化步骤.</p></li></ul><p>  例子:</p>  <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> <span class="built_in">input</span>, target <span class="keyword">in</span> dataset:</span><br><span class="line">    optimizer.zero_grad()</span><br><span class="line">    output = model(<span class="built_in">input</span>)</span><br><span class="line">    loss = loss_fn(output, target)</span><br><span class="line">    loss.backward()</span><br><span class="line">    optimizer.step()</span><br></pre></td></tr></table></figure><h2 id="torch-optim-Adam"><a href="#torch-optim-Adam" class="headerlink" title="torch.optim.Adam"></a>torch.optim.Adam</h2><blockquote><p>CLASS</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">torch.optim.Adam(params, lr=<span class="number">0.001</span>, betas=(<span class="number">0.9</span>, <span class="number">0.999</span>), eps=<span class="number">1e-08</span>, weight_decay=<span class="number">0</span>, amsgrad=<span class="literal">False</span>)</span><br></pre></td></tr></table></figure></blockquote><p>实现了 Adam 算法</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 框架 </category>
          
          <category> Pytorch </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 框架 </tag>
            
            <tag> Pytorch </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>参数优化</title>
      <link href="/ML/RL/primer/opt_param/"/>
      <url>/ML/RL/primer/opt_param/</url>
      
        <content type="html"><![CDATA[<h1 id="推导最简单的策略梯度"><a href="#推导最简单的策略梯度" class="headerlink" title="推导最简单的策略梯度"></a>推导最简单的策略梯度</h1><p>我们考虑一个随机的, 参数化的策略 $\pi_{\theta}$ . 我们的目标是最大化期望回报 (还可以称为性能函数, 与损失函数意义相反) $J(\pi_{\theta})=\mathop{\mathrm{E}}\limits_{\tau\sim \pi_{\theta}}[R(\tau)]$ . 这里使用<strong>有限无折损回报</strong> ($\textrm{finite-horizon undiscounted return}$) 来推导, 但是<strong>无限有折损回报</strong> ($\textrm{infinite-horizon discounted return}$) 的推导几乎是完全相同的.</p><p>我们会用<strong>梯度下降</strong> ($\textrm{gradient ascent}$) 来优化策略的参数, 比如<br>$$\theta_{k+1}=\theta_k+\alpha\nabla_{\theta}J(\pi_{\theta})|_{\theta_k}$$<br>其中 $\nabla_{\theta}J(\pi_{\theta})|_{\theta_k}$ 代表 $\theta$ 取值为 $\theta_k$ .</p><p>为了使用该算法, 我们需要一个能够用数值计算的策略梯度表达式. 这包括两个步骤:</p><ol><li>推导出策略性能的<strong>解析梯度</strong> ($\textrm{analytical gradient}$ , 什么是解析梯度? 详情看<a href="https://yunist.cn/ML/optimizer/numerical_analytical_gradient/">这篇文章</a>) , 以期望值的形式表现 (便于用平均值估计).</li><li>算出在样本上的估计的期望值, 可以使用有限步代理人-环境交互的数据.</li></ol><p>这里列出对推导解析梯度有帮助的一些事实.</p><ol><li>轨迹的概率. 采取策略 $\pi_{\theta}$ 所做出的轨迹 $\tau=\{s_0,a_0,\dots,s_{T+1}\}$ 的概率是</li></ol>$$P(\tau\mid \theta)=\rho_0(s_0)\prod_{t=0}^TP(s_{t+1}\mid s_t,a_t)\pi_{\theta}(a_t\mid s_t)$$<ol><li>对数的把戏. 我们知道 $\log x$ 对 $x$ 的导数是 $1/x$ , 于是根据链式法则有</li></ol>$$\nabla _{\theta}P(\tau\mid\theta)=P(\tau\mid \theta)\frac{1}{P(\tau\mid \theta)}\nabla_{\theta}P(\tau\mid \theta)=P(\tau\mid \theta)\nabla_{\theta}\log P(\tau\mid \theta)$$<ol><li>轨迹的对数概率</li></ol>$$\log P(\tau\mid \theta)=\log \rho_0(s_0)+\sum_{t=0}^T\bigg(\log P(s_{t+1}\mid s_t,a_t)+\log \pi_{\theta}(a_t\mid s_t)\bigg)$$<ol><li>环境函数的梯度. 由于 $\rho_0(s_0),P(s_{t+1}\mid s_t,a_t),R(\tau)$ 与 $\theta$ 都无关, 因此它们的梯度为 $0$ .</li><li>由第 4 条与第 3 条可知, 轨迹的对数概率的梯度是</li></ol>$$\begin{aligned}\nabla_{\theta}\log P(\tau \mid \theta)&={\nabla_{\theta}\log \rho_0(s_0)}+\sum_{t=0}^T\bigg({\nabla_{\theta }\log P(s_{t+1}\mid s_t,a_t)}+\nabla_{\theta}\log \pi_\theta(a_t\mid s_t)\bigg)\\\\&=\sum_{t=0}^Y\nabla_{\theta}\log \pi_\theta(a_t\mid s_t)\end{aligned}$$<p>由以上全部推导就有<br>$$\begin{aligned}\nabla_{\theta}J(\pi_\theta)&=\nabla_\theta\mathop{\mathrm{E}}_{\tau\sim\pi_0}[R(\tau)]\\\\&=\nabla_{\theta}\int_\tau P(\tau\mid \theta)R(\tau)\\\\&=\int_\tau \nabla_{\theta}P(\tau\mid \theta)R(\tau)\\\\&=\int_\tau P(\tau\mid \theta)\nabla_{\theta}\log P(\tau\mid \theta)R(\tau)\\\\&=\mathop{\mathrm{E}}_{\tau\sim\pi_\theta}[\nabla_{\theta}\log P(\tau\mid \theta)R(\tau)]\\\\&=\mathop{\mathrm{E}}_{\tau\sim\pi_\theta}\left[\sum_{t=0}^T\nabla_{\theta}\log \pi_\theta(a_t\mid s_t)R(\tau)\right]\end{aligned}$$<br>这样我们就可以用样本的平均值来估计策略梯度了. 假如我们有轨迹的集合 $\mathcal{D}=\{\tau_i\}_{i=1,\dots,N}$ , 并且这些轨迹都是代理人根据策略 $\pi_{\theta}$ 在环境中行动获得, 那么策略梯度可以估计为<br>$$\hat{g}=\frac{1}{|\mathcal{D}|}\sum_{\tau\in \mathcal{D}}\sum_{t=0}^T\nabla_\theta \log \pi_\theta(a_t\mid s_t)R(\tau)$$<br>其中 $|\mathcal{D}|$ 是集合 $\mathcal{D}$ 的元素个数.</p><h1 id="损失函数"><a href="#损失函数" class="headerlink" title="损失函数"></a>损失函数</h1><p>在强化学习中, 我们同样可以定义类似监督学习中的损失函数的概念, 但是在强化学习中的损失函数与监督学习中的损失函数有很大区别.  损失函数的梯度与策略梯度是相同的. 其接受的数据包含了 (状态, 动作, 权重) 三元组. </p><h2 id="与参数关系"><a href="#与参数关系" class="headerlink" title="与参数关系"></a>与参数关系</h2><p>在监督学习中, 损失只与数据有关而与参数无关, 但是在强化学习中, 由于数据是遵循最近的策略采样得来的, 因此损失也与参数有关.</p><h2 id="描述性能"><a href="#描述性能" class="headerlink" title="描述性能"></a>描述性能</h2><p>在强化学习中, 我们关心的是期望回报 $J(\pi_{\theta})$ , 而损失函数并不能很好的表达它. 最优化损失函数并不能保证能够提升期望回报. 你甚至可以将损失函数降低到 $-\infty$ 而同时策略性能 (期望回报) 并不怎样. 此时我们称其 “过拟合” . 但这与我们通常所称的过拟合有所不同, 这只是一种描述, 因为实际上并没有什么泛化的错误, 只是损失函数低得吓人. 因此如果想真正描述策略性能, 我们应该关心期望回报而不是损失函数.</p><h1 id="EGLP-定理"><a href="#EGLP-定理" class="headerlink" title="EGLP 定理"></a>EGLP 定理</h1><p>在这里我们会推导出一个在策略梯度中被广泛使用的一个中间结果, 我们称其为梯度对数概率期望 ($\text{Expect Grad-Log-Prob, EGLP}$) 定理.<br>$$\begin{aligned}\int_xP_{\theta}(x)&=1\\\\\nabla_\theta\int_xP_\theta(x)&=\nabla_\theta1\\\\\nabla_\theta\int_xP_\theta(x)&=0\\\\\int_x\nabla_\theta P_\theta(x)&=0\\\\\int_xP_\theta(x)\nabla_{\theta}\log P_\theta(x)&=0\\\\\mathop{\mathrm{E}}_{x\sim P_\theta}[\nabla_\theta\log P_\theta(x)]&=0\end{aligned}$$</p><h1 id="别让过去影响你"><a href="#别让过去影响你" class="headerlink" title="别让过去影响你"></a>别让过去影响你</h1><p>梯度更新表达式<br>$$\nabla_\theta J(\pi_\theta)=\mathop{\mathrm{E}}_{\tau\sim\pi_0}\left[\sum_{t=0}^{T}\nabla_\theta \log\pi_0(a_t\mid s_t)R(\tau)\right]$$<br>每次更新, 都可以让每个动作的对数概率随着 $R(\tau)$ (采取动作的总回报) 成比例增加. 但这意义不大. 代理人应该根据其采取行动后的后果 (好还是坏) 来决定如何更改 (加强) 策略, 而采取行动之前的奖励和这一步行动的好坏没有直接关系. 事实上, 这一直觉在数学上也有很好的表达. 可以证明, 梯度更新表达式也可以写成如下等价形式.<br>$$\nabla_\theta J(\pi_\theta)=\mathop{\mathrm{E}}_{\tau\sim\pi_\theta}\left[\sum_{t=0}^{T}\nabla_\theta \log\pi_\theta(a_t\mid s_t)\sum_{t'=t}^TR(s_{t'},a_{t'},s_{t'+1})\right]$$<br>这被称为<strong>奖励策略梯度</strong> ($\text{reward-to-go policy gradient}$).</p><p>证明过程比较繁琐, 不想看的可以略过.</p><h2 id="证明"><a href="#证明" class="headerlink" title="证明"></a>证明</h2><p>我们先提出一个函数<br>$$\mathop{\mathrm{E}}_{\tau\sim \pi_\theta}[f(t,t')]=\mathop{\mathrm{E}}_{\tau\sim\pi_\theta}[\nabla_\theta\log \pi_\theta(a_t\mid s_t)R(s_{t'},a_{t'},s_{t'+1})]$$<br>如果我们能证明当 $t'<t$ 时, 该式为 $0$ , 我们就能证明两种策略梯度的表达是等价的. 在 $t$ 与 $t'$ 时刻, 函数 $f(t,t')$ 只与 $s_t,a_t,s_{t'},a_{t'},s_{t'+1}$ 有关, 于是我们有<br>$$\begin{aligned}\mathop{\mathrm{E}}_{\tau\sim\pi_\theta}[f(t,t')]&= \int_\tau P(\tau\mid \pi_\theta)f(t,t')\\\\&=\int_{s_t,a_t,s_{t'},a_{t'},s_{t'+1}}P(s_t,a_t,s_{t'},a_{t'},s_{t'+1}\mid\pi_\theta)f(t,t')\\\\&=\mathop{\mathrm{E}}_{s_t,a_t,s_{t'},a_{t'},s_{t'+1}\sim\pi_\theta}[f(t,t')]\end{aligned}$$<br>根据贝叶斯法则, 我们有<br>$$\begin{aligned}\mathop{\mathrm{E}}_{A,B}[f(A,B)]&=\int_{A,B}P(A,B)f(A,B)\\\\&=\int_A\int_BP(B\mid A)P(A)f(A,B)\\\\&=\int_AP(A)\int_BP(B\mid A)f(A,B)\\\\&=\int_AP(A)\mathop{\mathrm{E}}_{B}\Big[f(A,B)\Big|A\Big]\\\\&=\mathop{\mathrm{E}}_A\bigg[\mathop{\mathrm{E}}_{B}\Big[f(A,B)\Big|A\Big]\bigg]\end{aligned}$$<br>若 $f(A,B)=h(A)g(B)$ , 那么还有<br>$$\begin{aligned}\mathop{\mathrm{E}}_{A,B}[f(A,B)]&=\mathop{\mathrm{E}}_A\bigg[\mathop{\mathrm{E}}_{B}\Big[f(A,B)\Big|A\Big]\bigg]\\\\&=\mathop{\mathrm{E}}_A\bigg[\mathop{\mathrm{E}}_{B}\Big[h(A)g(B)\Big|A\Big]\bigg]\\\\&=\mathop{\mathrm{E}}_A\bigg[h(A)\mathop{\mathrm{E}}_{B}\Big[g(B)\Big|A\Big]\bigg]\end{aligned}$$<br>因此就有<br>$$\begin{aligned}\mathop{\mathrm{E}}_{\tau\sim\pi_\theta}[f(t,t')]&=\mathop{\mathrm{E}}_{s_t,a_t,s_{t'},a_{t'},s_{t'+1}\sim\pi_\theta}[f(t,t')]\\\\&=\mathop{\mathrm{E}}_{s_{t'},a_{t'},s_{t'+1}\sim\pi_\theta}\bigg[\mathop{\mathrm{E}}_{s_t,a_t\sim\pi_\theta}\Big[f(t,t')\Big|s_{t'},a_{t'},s_{t'+1}\Big]\bigg]\\\\&=\mathop{\mathrm{E}}_{s_{t'},a_{t'},s_{t'+1}\sim\pi_\theta}\bigg[\mathop{\mathrm{E}}_{s_t,a_t\sim\pi_\theta}\Big[\nabla_\theta\log \pi_\theta(a_t\mid s_t)R(s_{t'},a_{t'},s_{t'+1})\Big|s_{t'},a_{t'},s_{t'+1}\Big]\bigg]\\\\&=\mathop{\mathrm{E}}_{s_{t'},a_{t'},s_{t'+1}\sim\pi_\theta}\bigg[R(s_{t'},a_{t'},s_{t'+1})\mathop{\mathrm{E}}_{s_t,a_t\sim\pi_\theta}\Big[\nabla_\theta\log \pi_\theta(a_t\mid s_t)\Big|s_{t'},a_{t'},s_{t'+1}\Big]\bigg]\end{aligned}$$<br>而<br>$$\begin{aligned}\mathop{\mathrm{E}}_{s_t,a_t\sim\pi_\theta}\Big[\nabla_\theta\log \pi_\theta(a_t\mid s_t)\Big|s_{t'},a_{t'},s_{t'+1}\Big]=\int_{s_t,a_t}P(s_t,a_t\mid\pi_\theta, s_{t'},a_{t'},s_{t'+1})\nabla_\theta\log \pi_\theta(a_t\mid s_t)\end{aligned}$$<br>当 $t'<t$ 时, 我们可以分解 $P(s_t,a_t\mid\pi_\theta, s_{t'},a_{t'},s_{t'+1})$<br>$$\begin{aligned}P(s_t,a_t\mid\pi_\theta, s_{t'},a_{t'},s_{t'+1})&=P(a_t\mid\pi_{\theta}, s_t,a_{t'},s_{t'+1})P(s_t\mid\pi_\theta, s_{t'},a_{t'},s_{t'+1})\\\\&=\pi_{\theta}(a_t\mid s_t,a_{t'},s_{t'+1})P(s_t\mid\pi_\theta, s_{t'},a_{t'},s_{t'+1})\\\\&=\pi_{\theta}(a_t\mid s_t)P(s_t\mid\pi_\theta, s_{t'},a_{t'},s_{t'+1})\end{aligned}$$<br>这是因为 $a_t$ 在当前环境 $s_t$ 已知晓时, 与之前做过的选择与之前经历的环境并无关系.</p><p>因此有<br>$$\begin{aligned}\mathop{\mathrm{E}}_{s_t,a_t\sim\pi_\theta}\Big[\nabla_\theta\log \pi_\theta(a_t\mid s_t)\Big|s_{t'},a_{t'},s_{t'+1}\Big]&=\int_{s_t,a_t}P(s_t,a_t\mid\pi_\theta, s_{t'},a_{t'},s_{t'+1})\nabla_\theta\log \pi_\theta(a_t\mid s_t)\\\\&=\int_{s_t,a_t}\pi_{\theta}(a_t\mid s_t)P(s_t\mid\pi_\theta, s_{t'},a_{t'},s_{t'+1})\nabla_\theta\log \pi_\theta(a_t\mid s_t)\\\\&=\int_{s_t}P(s_t\mid\pi_\theta, s_{t'},a_{t'},s_{t'+1})\int_{a_t}\pi_{\theta}(a_t\mid s_t)\nabla_\theta\log \pi_\theta(a_t\mid s_t)\\\\&=\mathop{\mathrm{E}}_{s_t\sim\pi_\theta}\bigg[\mathop{\mathrm{E}}_{a_t\sim\pi_\theta}\Big[\nabla_\theta \log\pi_\theta(a_t\mid s_t)\Big|s_t\Big]\bigg|s_{t'},a_{t'},s_{t'+1}\bigg]\end{aligned}$$<br>此时就要用到我们的 $\text{EGLP}$ 定理了.<br>$$\because \int_{a_t}\pi_\theta(a_t\mid s_t)\Big|s_t=1\\\\\therefore \mathop{\mathrm{E}}_{a_t\sim\pi_\theta}\Big[\nabla_\theta \log\pi_\theta(a_t\mid s_t)\Big|s_t\Big] =0$$<br>因此当 $t'<t$ 时 $\mathop{\mathrm{E}}_{\tau\sim\pi_\theta}[f(t,t')]=0$.</p><p>而当 $t'\geqslant t$ 时, 无法将 $P(s_t,a_t\mid\pi_\theta, s_{t'},a_{t'},s_{t'+1})$ 分解成该形式, 所以就不会有这个结果. 我们可以举个例子. 如果现在有 $80\%$ 的几率会下雨, 而你打算如果不下雨, 就有 $90\%$ 的可能会出去买水果. 此时, 无论之前发生了什么 (也许昨天下雨了 (环境) , 也许前天买了水果 (动作)) , 现在买水果的概率都是 $(1-80\%)\times90\%=16\%$ . 但是如果这个时候, 未来的你突然穿越回来, 告诉你你后来买了水果, 那么这时下雨的概率其实就改变了, 变得更倾向于不下雨 (事实上如果你后来买了水果, 不下雨的概率就会是 $1$ ). 如果没买, 则相反. 这就是未来影响现在而过去不影响现在.</p><blockquote><p>既然期望是相同的, 但根据这个式子来训练为什么会更好呢? 这是因为策略梯度需要用样本轨迹来估计, 而且最好是低方差的. 如果方差较大, 说明估计不太准确. 如果公式中包括过去的奖励, 虽然它们均值为 $0$ , 但方差并不是, 在公式中增加它们只会给策略梯度的样本估计增加噪音, 增加方差. 而这会导致需要较多的样本轨迹才能得到一个相对稳定的值 (收敛) . 删除它们后, 我们就可以用更少的样本轨迹得到低方差的估计, 也就是说更容易收敛. 举个例子, 如果你要估计一系列数字的期望 (也就是算平均值) , 它们服从的概率分布的期望其实都是 $50$, 但是一个方差很大, 一会 $100$ 一会 $20$ 一会 $3$, 你需要很多数字才能得到一个较为准确的值. 而另一个方差很小, 基本就是 $50.3$ , $49.8$ , $49.5$ 这样, 只需要几个数字就能估计得差不多.</p></blockquote><h1 id="策略梯度的基线"><a href="#策略梯度的基线" class="headerlink" title="策略梯度的基线"></a>策略梯度的基线</h1><p>由 $\text{EGLP}$ 可以得到一个非常直接的结论: 如果一个函数 $b(s_t)$ 只依赖于状态 $s_t$ , 那么有<br>$$\mathop{\mathrm{E}}_{a_t\sim\pi_\theta}[\nabla_\theta \log \pi_\theta(a_t\mid s_t)b(s_t)]=0$$<br>这使得我们可以在策略梯度的表达式中任意加上 (或删除) 这样的项而不改变最终结果, 比如说<br>$$\begin{aligned}\nabla_\theta J(\pi_\theta)&=\mathop{\mathrm{E}}_{\tau\sim\pi_\theta}\left[\sum_{t=0}^{T}\nabla_\theta \log\pi_\theta(a_t\mid s_t)\sum_{t'=t}^TR(s_{t'},a_{t'},s_{t'+1})\right]\\\\&=\mathop{\mathrm{E}}_{\tau\sim\pi_\theta}\left[\sum_{t=0}^{T}\nabla_\theta \log\pi_\theta(a_t\mid s_t)\left(\sum_{t'=t}^TR(s_{t'},a_{t'},s_{t'+1})-b(s_t)\right)\right]\end{aligned}$$<br>函数 $b$ 被称为<strong>基线</strong> ($\text{baseline}$).</p><p>基线函数一般是<strong>策略上的价值函数</strong> ($\text{on-policy value function}$) $V^\pi(s_t)$ . 稍微回想一下, 这个函数给出了代理人从状态 $s_t$ 开始, 使用策略 $\pi$ 以后的平均 (期望) 回报.<br>$$V^{\pi}(s) = \mathop{\mathrm E}_{\tau\sim\pi}[R(\tau)\mid s_0 = s]$$<br>经验上, 让基线 $b(s_t)=V^\pi(s)$ 对降低策略梯度的样本估计的方差有好处, 这会让策略学习更快, 更稳定. 从概念上来看, 这也很有意义: 它体现了一个直觉, 如果代理人得到了它所期望的 (即 $\sum_{t'=t}^TR(s_{t'},a_{t'},s_{t'+1})=V^\pi(s)$) , 他会对此 “感到” 中立 ( “中立” 在数学上看来即值为 $0$ ).</p><p>事实上, $V^\pi(s_t)$ 并不能被准确计算, 因此应该使用它的估计. 通常我们会使用一个与策略同步更新 (这样就能总是估计最近的策略的价值函数) 的神经网络 $V_\phi(s_t)$ 来估计它.</p><h1 id="策略梯度的其他形式"><a href="#策略梯度的其他形式" class="headerlink" title="策略梯度的其他形式"></a>策略梯度的其他形式</h1><p>我们已经见到了策略梯度的很多等价形式<br>$$\nabla_\theta J(\pi_\theta)=\mathop{\mathrm{E}}_{\tau\sim\pi_0}\left[\sum_{t=0}^{T}\nabla_\theta \log\pi_0(a_t\mid s_t)\Phi_t\right]$$<br>&nbsp;$\Phi_t$ 可以是<br>$$\Phi_t=R(\tau)$$<br>又或者<br>$$\Phi_t=\sum_{t'=t}^TR(s_{t'},a_{t'},s_{t'+1})$$<br>再或者<br>$$\Phi_t=\sum_{t'=t}^TR(s_{t'},a_{t'},s_{t'+1})-b(s_t)$$<br>但还有两种重要的形式.</p><ol><li>状态-动作价值函数</li></ol>$$\Phi_t=Q^{\pi_\theta}(s_t,a_t)$$<p>证明可以看<a href="https://spinningup.openai.com/en/latest/spinningup/extra_pg_proof2.html">这里</a>.</p><ol><li>优势方程</li></ol>$$\Phi_t=A^{\pi}(s_t,a_t)$$<p>而<br>$$A^{\pi}(s_t,a_t)=Q^{\pi}(s_t,a_t)-V^{\pi}(s_t)$$<br>由基线得知等价.</p><blockquote><p>为了更详细的了解这个主题, 你应该阅读 <a href="https://arxiv.org/abs/1506.02438">Generalized Advantage Estimation</a> (GAE). 也可以参考我的文章 <a href="https://yunist.cn/ML/RL/primer/GAE/">GAE 算法</a> .</p></blockquote>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 入门 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>线性代数命题证明 (一)</title>
      <link href="/math/linear_algebra/prove_1/"/>
      <url>/math/linear_algebra/prove_1/</url>
      
        <content type="html"><![CDATA[<h1 id="一"><a href="#一" class="headerlink" title="一"></a>一</h1><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>设 $M=\left[\begin{matrix}A&B\\\\C&D\end{matrix}\right]$ 为一个 $2n\times2n$ 矩阵, 其中每一块为一个 $n\times n$ 矩阵. 假设 $A$ 可逆且 $AC=CA$ . 那么有 $\det M=\det(AD-CB)$ .</p><h2 id="证明"><a href="#证明" class="headerlink" title="证明"></a>证明</h2><p>由于 $A$ 可逆且 $AC=CA$ , 所以两边左乘 $A^{-1}$ 有 $C=ACA^{-1}$ . 那么有<br>$$\begin{aligned}\det\left[\begin{matrix}A&B\\\\C&D\end{matrix}\right]&=\det\left[\begin{matrix}A&B\\\\C-A(CA^{-1})&D-B(CA^{-1})\end{matrix}\right]\\\\&=\det\left[\begin{matrix}A&B\\\\0&D-B(CA^{-1})\end{matrix}\right]\\\\&=\det(A)\det \Big(D-B(CA^{-1})\Big)\\\\&=\det\Big(D-B(CA^{-1})\Big)\det(A)\\\\&=\det\bigg(\Big(D-B(CA^{-1})\Big)A\bigg)\\\\&=\det(DA-BC)\end{aligned}$$<br>这已经很接近我们的答案了.</p><p>将矩阵沿主对角线旋转 (即转置) 与沿副对角线旋转并不改变行列式的值, 即<br>$$\det\left[\begin{matrix}A&B\\\\C&D\end{matrix}\right]=\det\left[\begin{matrix}D&C\\\\B&A\end{matrix}\right]$$<br>而根据上面的推导, 有<br>$$\det\left[\begin{matrix}D&C\\\\B&A\end{matrix}\right]=\det(AD-CB)$$<br>那么也就是说<br>$$\det\left[\begin{matrix}A&B\\\\C&D\end{matrix}\right]=\det\left[\begin{matrix}D&C\\\\B&A\end{matrix}\right]=\det(AD-CB)$$<br>$\blacksquare$</p><h1 id="二"><a href="#二" class="headerlink" title="二"></a>二</h1><h2 id="问题-1"><a href="#问题-1" class="headerlink" title="问题"></a>问题</h2><p>对于形如<br>$$D_n=\left|\begin{matrix}1&1&\cdots&1\\\\x_1&x_2&\cdots&x_n\\\\\vdots&\vdots&&\vdots\\\\{x_1}^{n-1}&{x_2}^{n-1}&\cdots&{x_n}^{n-1}\end{matrix}\right|$$<br>的 $n$ 阶行列式称为范德蒙德行列式, 并且有<br>$$D_n=\prod_{1\leqslant j<i\leqslant n}(x_i-x_j)$$</p><h2 id="证明-1"><a href="#证明-1" class="headerlink" title="证明"></a>证明</h2><p>我们用数学归纳法证明. 当 $n=2$ 时, 显然成立. 假设该结论对 $n-1$ 阶范德蒙德行列式成立, 那么对于 $n$ 阶范德蒙德行列式有<br>$$\left|\begin{matrix}1&1&\cdots&1\\\\x_1&x_2&\cdots&x_n\\\\\vdots&\vdots&\ddots&\vdots\\\\{x_1}^{n-1}&{x_2}^{n-1}&\cdots&{x_n}{n-1}\end{matrix}\right|=\left|\begin{matrix}1&1&\cdots&1\\\\0&x_2-x_1&\cdots&x_n-x_1\\\\\vdots&\vdots&\ddots&\vdots\\\\0&{x_2}^{n-1}-{x_2}^{n-2}x_1&\cdots&{x_n}^{n-1}-{x_n}^{n-2}x_1\end{matrix}\right|$$<br>即从下到上每行减去上一行的 $x_1$ 倍. 从而我们有<br>$$\begin{aligned}\left|\begin{matrix}1&1&\cdots&1\\\\0&x_2-x_1&\cdots&x_n-x_1\\\\\vdots&\vdots&\ddots&\vdots\\\\0&{x_2}^{n-1}-{x_2}^{n-2}x_1&\cdots&{x_n}^{n-1}-{x_n}^{n-2}x_1\end{matrix}\right|&=\left|\begin{matrix}x_2-x_1&\cdots&x_n-x_1\\\\\vdots&\ddots&\vdots\\\\{x_2}^{n-1}-{x_2}^{n-2}x_1&\cdots&{x_n}^{n-1}-{x_n}^{n-2}x_1\end{matrix}\right|\\\\&=\left|\begin{matrix}1(x_2-x_1)&\cdots&1(x_n-x_1)\\\\\vdots&\ddots&\vdots\\\\{x_2}^{n-2}(x_2-x_1)&\cdots&{x_n}^{n-2}(x_n-x_1)\end{matrix}\right|\\\\&=(x_2-x_1)(x_3-x_1)\cdots(x_n-x_1)\left|\begin{matrix}1&\cdots&1\\\\\vdots&\ddots&\vdots\\\\{x_2}^{n-2}&\cdots&{x_n}^{n-2}\end{matrix}\right|\\\\&=(x_2-x_1)(x_3-x_1)\cdots(x_n-x_1)\prod_{2\leqslant j<i\leqslant n}(x_i-x_j)\\\\&=\prod_{1\leqslant j<i\leqslant n}(x_i-x_j)\end{aligned}$$<br>$\blacksquare$</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 线性代数 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 线性代数 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>行列式几何意义的证明</title>
      <link href="/math/linear_algebra/geometric_det/"/>
      <url>/math/linear_algebra/geometric_det/</url>
      
        <content type="html"><![CDATA[<p> 行列式具有良好的性质, 通常它是线性代数中较为基本的内容. 而行列式有非常直观的几何性质, 其绝对值是以矩阵中的向量为棱的在标准正交基下的平行四边形 (六面体) 的体积, 当维数超过三维时, 有类似的结果, 我们可以称其为 “广义平行六面体” 的体积. 我们给出广义平行六面体体积的一个递归定义. 设 $A$ 为 $n\times n$ 矩阵, 其中第 $k$ 行向量 $L$ 即为广义平行六面体 $V$ 的一个棱,<br>$$\newcommand\xrule{\rule[.5ex]{2em}{.4pt}}\left[\begin{matrix}&\vdots&\\\\\xrule& L_k&\xrule\\\\&\vdots&\end{matrix}\right]$$<br>以 $L_2,L_3,\dots L_n$ 为平行六面体 $V$ 的底, 而以 $L_1$ 正交于 $L_2,L_3,\dots L_n$ 的分量 $H$ 作为 $V$ 的高, 将 $L_1$ 分为两个正交分量 $H$ 与 $G$, 而 $G$ 可以被 $L_2,L_3,\dots L_n$ 线性表示, 那么就有<br>$$L_1=H+G\\\\H\perp G\\\\H\perp L_2,L_3,\dots L_n\\\\G=a_2L_2+a_3L_3+\dots+a_nL_n$$<br>而该广义平行六面体的体积等于底面 (以 $L_2,L_3,\dots L_n$ 作为棱的低一维的广义平行六面体) 的体积与高 ($|M|$) 的乘积. 在广义平行六面体低于三维时, 其体积与长度, 面积相对应.</p><p>引理 1: 以 $L_2,L_3,\dots L_n$ 为棱的广义平行六面体的体积的平方等于 $\det(AA^{\mathrm{T}})$ .</p><p>证明: $A$ 是 $m\times n$ 矩阵, 因此 $AA^{\mathrm{T}}$ 是 $m\times m$ 方阵. 现在对 $m$ 进行归纳: 当 $m=1$ 时, $A$ 为行向量, 于是 $AA^{\mathrm T}$ 为长度的平方, 因此 $m=1$ 时成立.</p><p>假设 $m>1$ , 且对于 $m-1$ 的情况引理 1 成立. 那么我们可以将 $L_1$ 分为 $H+G$<br>$$\newcommand\xrule{\rule[.5ex]{2em}{.4pt}}\left[\begin{matrix}\xrule &L_1&\xrule\\\\\xrule &L_2&\xrule\\\\&\vdots& \\\\\xrule &L_m&\xrule\\\\\end{matrix}\right]=\left[\begin{matrix}\xrule &H+G&\xrule\\\\\xrule &L_2&\xrule\\\\&\vdots&\\\\\xrule &L_m&\xrule\\\\\end{matrix}\right]$$<br>而由于 $G$ 可以由 $L_2,L_3,\dots L_n$ 线性表示, 于是可以左乘初等矩阵将 $L_1$ 中的 $G$ 通过减去其余向量相应倍数消去, 并且由于 $\det(E)=1$ , 因此不会影响结果<br>$$\det\Big((EA)(EA)^{\mathrm T}\Big)=\det\Big((EA)(A^{\mathrm T}E^{\mathrm{\mathrm T}})\Big)=\det(AA^{\mathrm{T}})$$<br>我们用 $A^*$ 来代替 $EA$ , 并且将 $A^*$ 去除 $H$ 后的部分用 $D$ 表示<br>$$A^*=\left[\begin{matrix}\xrule & H&\xrule\\\\\xrule &L_2&\xrule\\\\&\vdots& \\\\\xrule &L_m&\xrule\\\\\end{matrix}\right]=\left[\begin{matrix}\xrule &H&\xrule\\\\\xrule &D&\xrule\\\\\end{matrix}\right]$$<br>因此有<br>$$\newcommand\lrule{\rule[.5ex]{.4pt}{2em}}A^*{A^*}^{\mathrm{T}}=\left[\begin{matrix}\xrule &H&\xrule\\\\\xrule &D&\xrule\\\\\end{matrix}\right]\left[\begin{matrix}\lrule &\lrule \\\\H^{\mathrm T}&D^\mathrm T\\\\\lrule &\lrule \\\\\end{matrix}\right]=\left[\begin{matrix}HH^{\mathrm T}&HD^{\mathrm T}\\\\DH^\mathrm T&DD^\mathrm T\end{matrix}\right]=\left[\begin{matrix}HH^{\mathrm T}&0\\\\0&DD^\mathrm T\end{matrix}\right]$$<br>因为 $H\perp D$ , 因此 $HD^{\mathrm T}=DH^{\mathrm T}=0$ .</p><p>而根据行列式的递归定义, 可得<br>$$\det\left(\left[\begin{matrix}HH^{\mathrm T}&0\\\\0&DD^\mathrm T\end{matrix}\right]\right)=HH^\mathrm T\cdot\det(DD^\mathrm T)$$<br>由归纳假设与广义平行四面体体积定义得, $\det(DD^\mathrm T)$ 是底面体积的平方, 而 $HH^\mathrm T$ 是高的长度的平方, 于是相乘就是体积的平方. 证毕</p><p>由引理 1, 我们可以轻松证明行列式的几何意义.<br>$$\begin{aligned}\det(AA^\mathrm T)=\det(A)\det(A^\mathrm T)=\det(A)^2&=体积^2\\\\|\det(A)|&= 体积\end{aligned}$$</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 线性代数 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 线性代数 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数值梯度与解析梯度</title>
      <link href="/ML/optimizer/numerical_analytical_gradient/"/>
      <url>/ML/optimizer/numerical_analytical_gradient/</url>
      
        <content type="html"><![CDATA[<h1 id="数值梯度-Numerical-Gradient"><a href="#数值梯度-Numerical-Gradient" class="headerlink" title="数值梯度 (Numerical Gradient)"></a>数值梯度 (Numerical Gradient)</h1>$$\frac{\mathrm{d}f(x)}{\mathrm{d}x}=\lim_{\Delta x\rightarrow 0}\frac{f(x+\Delta x)-f(x)}{\Delta x}\\\\\frac{\mathrm{d}f(x)}{\mathrm{d}x}\approx\frac{f(x+\epsilon)-f(x-\epsilon)}{2\epsilon}$$<p>根据上式, 当 $\epsilon$ 取得足够小时, 就可以近似的认为其是梯度. 这样的方法求梯度非常方便, 但是并不是完全精确 (总是存在误差) , 这就是<strong>数值梯度</strong>.</p><h1 id="解析梯度-Analytical-Gradient"><a href="#解析梯度-Analytical-Gradient" class="headerlink" title="解析梯度 (Analytical Gradient)"></a>解析梯度 (Analytical Gradient)</h1><p><strong>解析梯度</strong>即利用求导法则, 精确的求出其梯度, 推导一般比较麻烦, 但是如果推导出来, 那么求梯度的速度和精确度会好于数值梯度</p><h1 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h1><p>比如说我们要求 $f(x)=x^2$ 这个函数在 $x=2$ 时的梯度.</p><h2 id="数值梯度"><a href="#数值梯度" class="headerlink" title="数值梯度"></a>数值梯度</h2>$$\left.\frac{\mathrm{d}f(x)}{\mathrm{d}x}\right|_{x=2}\approx \left.\frac{f(x+\epsilon)-f(x-\epsilon)}{2\epsilon}\right|_{x=2,\epsilon=0.0001}=4.000000000004$$<h2 id="解析梯度"><a href="#解析梯度" class="headerlink" title="解析梯度"></a>解析梯度</h2>$$\left.\frac{\mathrm{d}f(x)}{\mathrm{d}x}\right|_{x=2}=2x|_{x=2}=4$$]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 优化算法 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 优化算法 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>超几何分布抽取概率证明</title>
      <link href="/math/probability_theory/hypergeometric_distribution/"/>
      <url>/math/probability_theory/hypergeometric_distribution/</url>
      
        <content type="html"><![CDATA[<h1 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h1><p>相信大家都在高中接触过超几何分布. 超几何分布是<strong>不放回</strong>的, 该分布给出了抽取 $n$ 次后抽到次品次数的概率. 如果一个随机变量 $X$ 服从于超几何分布, 那么有<br>$$P(X=k)=\frac{C_{N}^kC_{M-N}^{n-k}}{C_{M}^{n}}$$<br>其中 $k$ 为抽取到的次品数, $M$ 为总数, $N$ 为总次品数.</p><h1 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h1><p>生活中很多变量都服从于超几何分布, 我们举个例子</p><blockquote><p>假设你们班要选出 $10$ 个人参加某个活动, 但是想要参加活动的人却有 $40$ 个人, 那么就要采取抽纸条的方式来选出参加活动的人. 准备 $40$ 张纸条, 其中有 $10$ 张是被标记了的. $40$ 个候选人每人抽取一张纸条, 抽到被标记纸条的人就可以参加活动.</p></blockquote><p>当已经有 $n$ 个人抽取了之后, $n$ 个人里面有 $X$ 个人可以参加活动, 这个 $X$ 就服从于超几何分布. 现在我们想要讨论的问题是: <strong>这样的抽取公平吗? 先抽和后抽对你抽到标记纸条的概率有没有影响?</strong> 再抽象一点, 即<strong>如果第 $n$ 次抽取时, 前面 $n-1$ 次抽取的结果都未知, 那么这次抽取抽到次品的概率是多少?</strong></p><p>直觉告诉我们, 应该是公平的, 也就是说在这样一个无返回抽样中, 无论先后, 抽取到次品的概率都是一样的, 并且这个值应该就是 $N/M$ .</p><h1 id="证明"><a href="#证明" class="headerlink" title="证明"></a>证明</h1><p>我们先说明几个数学符号, 以便后续推导</p><ul><li>$N$, $M$ 分别为次品数和总数</li><li>$X_1,X_2,\dots,X_n$ 分别为第 $n$ 次抽取抽取到的次品个数 ( $X_n$ 服从两点分布, 即其值要么 $0$ 要么 $1$)</li></ul><p>首先, 我们可以立即得出, $P(X_1=1) = \frac{N}{M}$ . 然后我们尝试计算 $P(X_2=1)$<br>$$\begin{aligned}P(X_2=1)&=P(X_2=1,X_1=1)+P(X_2=1,X_1=0)\\\\&=P(X_2=1\mid X_1=1)P(X_1=1)+P(X_2=1\mid X_1=0)P(X_1=0)\\\\&=\frac{N}{M}\frac{N-1}{M-1}+\frac{M-N}{M}\frac{N}{M-1}\\\\&=\frac{N(M-N+N-1)}{M(M-1)}\\\\&=\frac{N}{M}\end{aligned}$$<br>果然, $P(X_2=1)$ 也等于 $\frac{N}{M}$ .</p><p>不过… 好像还是没有什么思路, 那我们继续计算 $P(X_3=1)$<br>$$\begin{aligned}P(X_3=1)&=\sum_{X_1}\sum_{X_2}P(X_3,X_2,X_1)\\\\&=\sum_{X_1}\sum_{X_2}P(X_3\mid X_2,X_1)P(X_2\mid X_1)P(X_1)\\\\&=\left(\frac{N}{M}\frac{N-1}{M-1}\frac{N-2}{M-2}+\frac{N}{M}\frac{M-N}{M-1}\frac{N-1}{M-2}\right)\\\\&+\left(\frac{M-N}{M}\frac{N}{M-1}\frac{N-1}{M-2}+\frac{M-N}{M}\frac{M-N-1}{M-1}\frac{N}{M-2}\right)\end{aligned}$$<br>并且有<br>$$\frac{N}{M}\frac{N-1}{M-1}\frac{N-2}{M-2}+\frac{N}{M}\frac{M-N}{M-1}\frac{N-1}{M-2}=\frac{N}{M}\frac{N-1}{M-1}\\\\\frac{M-N}{M}\frac{N}{M-1}\frac{N-1}{M-2}+\frac{M-N}{M}\frac{M-N-1}{M-1}\frac{N}{M-2}=\frac{M-N}{M}\frac{N}{M-1}$$<br>于是同样的 $P(X_3=1)=\frac{N}{M}$ .</p><p>现在我们思考 $P(X_3=1)$ 与 $P(X_2=1)$ , $P(X_2=1)$ 与 $P(X_1=1)$ 之间有什么关系. 我们想象有很多轨迹, 每条轨迹最终都可以到达 $X_2=1$ 这种情况, 而将所有的能达到 $X_2=1$ 的轨迹产生的概率相加, 就是 $P(X_2=1)$ . $\frac{N}{M}\frac{N-1}{M-1}$ (第一次抽中, 第二次抽中) 和 $\frac{M-N}{M}\frac{N}{M-1}$ (第一次没抽中, 第二次抽中) 最终都可以达到<strong>第二次抽中</strong>这个结果 (也就是 $X_2=1$), 而也就只有这两条轨迹, 因此它们的概率相加便是 $P(X_2)=1$ .</p><p>类似的, 我们考虑 $X_3=1$ 的各个轨迹. $X_3=1$ 的轨迹和 $X_2=1$ 的轨迹有没有什么关联? 当然有, $X_3=1$ 的轨迹可以由 $X_2=1$ 的轨迹 “派生” 出来. 每一条 $X_2=1$ 轨迹都可以派生为两条 $X_3=1$ 轨迹, 比如说 $\frac{N}{M}\frac{N-1}{M-1}$ (第一次抽中, 第二次抽中), 这一条 $X_2=1$ 轨迹, 可以派生出 $\frac{N}{M}\frac{N-1}{M-1}\frac{N-2}{M-2}$ (第一次抽中, 第二次抽中, 第三次抽中) 与 $\frac{N}{M}\frac{(M-1)-(N-1)}{M-1}\frac{N-1}{M-2}$ (第一次抽中, 第二次没抽中, 第三次抽中) 两条轨迹, 即第二次抽中与没抽中的区别. 而 $X_4=1$ 的轨迹与 $X_3=1$ 的轨迹, $X_5=1$ 的轨迹与 $X_4=1$ 的轨迹, 乃至 $X_n=1$ 的轨迹与 $X_{n-1}=1$ 的轨迹之间, 都有这种派生关系. 如果能够证明, 一条轨迹出现的概率等于其派生出的两条轨迹出现的概率之和 (前面的计算已经看出在 $n=1,2$ 时满足这种关系), 那么就能够用数学归纳法证明每次抽取抽到次品的概率是相同的. 于是就要证明<br>$$\cdots \frac{N-a}{M-b} = \cdots\frac{N-a}{M-b}\frac{N-a-1}{M-b-1}+\cdots\frac{(M-b)-(N-a)}{M-b}\frac{N-a}{M-b-1}$$<br>由于 $X_n=1$ 的某条轨迹派生出 $X_{n+1}=1$ 的轨迹的过程中, 轨迹前面 $n-1$ 个动作 (即是否抽取到) 是不变的, 因此用 $\cdots$ 代替. 上面的式子显然成立, 于是我们就证明了 $P(X_n=1)=P(X_{n-1}=1)=\dots= P(X_1=1)=\frac{N}{M}$ . 也就是说, 游戏是公平的.</p><h1 id="应用"><a href="#应用" class="headerlink" title="应用"></a>应用</h1><p>据此, 我们可以轻松得出, 超几何分布的期望和二项分布是类似的. 即如果 $X$ 服从于超几何分布, 那么如果抽取 $n$ 次, $E(X)=n\frac{N}{M}=np$ (将 $\frac{N}{M}$ 看成一个概率 $p$ ).</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 概率论 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 分布 </tag>
            
            <tag> 概率论 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>RL 算法分类</title>
      <link href="/ML/RL/primer/algorithm_classify/"/>
      <url>/ML/RL/primer/algorithm_classify/</url>
      
        <content type="html"><![CDATA[<p><img src="1.svg" alt=""></p><h1 id="有模型与无模型"><a href="#有模型与无模型" class="headerlink" title="有模型与无模型"></a>有模型与无模型</h1><p>强化学习的一个最重要的分支即为<strong>有模型</strong> ($\textrm{Model-Base}$) 与<strong>无模型</strong> ($\textrm{Model-Free}$) 学习. 它们的区别在于, 代理人 ($\textrm{Agent}$, 即执行算法的主体) 是否获得环境的模型 ($\textrm{Model}$). 有了模型, 就可以预知状态转移以及回报.</p><h2 id="有模型"><a href="#有模型" class="headerlink" title="有模型"></a>有模型</h2><p>有模型能够让代理人在做出决策前先思考, 看看在做出某个可能的动作后会发生什么, 并在可能的动作中选择出确切的决策. 与无模型相比, 能够大大提高样本效率 ($\textrm{sample efficiency}$, 你从每条样本中得到的越多, 样本效率就越高, 详情可见 <a href="https://ai.stackexchange.com/questions/5246/what-is-sample-efficiency-and-how-can-importance-sampling-be-used-to-achieve-it">What is sample efficiency?</a>). </p><p>但是有模型学习同样也有缺点, <strong>得到一个很好描述现实的模型通常是不可能的.</strong> 并且代理人有可能在模型上学到一些 “偏见” (可以类比监督学习中的过拟合), 这使得代理人在模型中表现德很好, 但是在真实环境中表现并不是很好 (甚至很差) .</p><h2 id="无模型"><a href="#无模型" class="headerlink" title="无模型"></a>无模型</h2><p>无模型就比较好介绍了, 就是没有这个模型.</p><h1 id="如何学习"><a href="#如何学习" class="headerlink" title="如何学习"></a>如何学习</h1><h2 id="无模型-1"><a href="#无模型-1" class="headerlink" title="无模型"></a>无模型</h2><h3 id="参数优化"><a href="#参数优化" class="headerlink" title="参数优化"></a>参数优化</h3><p>参数优化方法将策略表示为一个与 $\theta$ 有关的函数 $\pi_{\theta}(a\mid s)$ . 优化参数 $\theta$ 可以直接用<strong>性能指标</strong> ($\textrm{performance objective}$ , 可以类比损失函数) $J(\pi_{\theta})$ 来进行<strong>梯度提升</strong> ($\textrm{gradient ascent}$) , 也可以使用性能指标的近似 (当性能指标本身难以获得时) 来间接的优化.</p><p>参数优化一般是<strong>同策略</strong> ($\textrm{on-policy}$) 的, 即<strong>策略改进和策略评估的对象是同一个策略</strong>, 与之相对的还有<strong>异策略</strong> ($\textrm{off-policy}$),  详情可见 <a href="https://stats.stackexchange.com/questions/184657/what-is-the-difference-between-off-policy-and-on-policy-learning">What is the difference between off-policy and on-policy learning ?</a></p><h3 id="Q-Learning"><a href="#Q-Learning" class="headerlink" title="Q-Learning"></a>Q-Learning</h3><p> &nbsp;$\textrm{Q-Learning}$ 方法会学习一个近似器 ($\textrm{approximator}$) $Q_{\theta}(s,a)$ 来近似动作-价值函数, 优化的过程常常使用异策略的方法, 即可以不理会代理人真正选择的动作所产生的数据, 而使用其他数据 (比如说最优动作产生的数据). 而得到 $Q_{\theta}(s,a)$ 后, 每个状态的动作如下给出<br>$$a(s)=\mathop{\arg\max}_aQ_\theta(s,a)$$</p><h3 id="优缺点"><a href="#优缺点" class="headerlink" title="优缺点"></a>优缺点</h3><p>参数优化 与 $\textrm{Q-Learning}$ 各自有其优缺点. 由于参数优化法直接优化你想要的 (策略 $\pi$) , 这使得它更加稳固与可靠. 而 $\textrm{Q-Learning}$ 通过优化近似动作-价值函数 $Q_{\theta}(s,a)$ 来间接优化策略 $\pi$ , 使得它并没有那么稳固 ($\textrm{Q-Learning}$ 有许多失败的模式), 但是当它生效时, 样本效率会非常高, 它可以高效的利用信息. </p><h2 id="有模型-1"><a href="#有模型-1" class="headerlink" title="有模型"></a>有模型</h2><p>在有模型中, 模型要么被给出, 要么要学习.</p><h3 id="纯规划-Pure-Planning"><a href="#纯规划-Pure-Planning" class="headerlink" title="纯规划 (Pure Planning)"></a>纯规划 (Pure Planning)</h3><p>纯规划是一个最基础的算法, 它不显式的表示策略, 而是用纯规划技术比如<strong>模型预测控制</strong> ($\textrm{model-predictive control, MPC}$) 来选择动作. 每次代理人观察环境时, 它会计算出一个计划 (行动的序列) , 并且这个计划相对于这个模型来说是最优的, 然后执行该计划的第一个动作 (即当前最优动作) , 然后舍弃该计划其余动作. 这种计算在每次代理人与环境交互的时候都会执行一次, 并产生一个新计划.</p><h3 id="专家迭代-Expert-Iteration"><a href="#专家迭代-Expert-Iteration" class="headerlink" title="专家迭代 (Expert Iteration)"></a>专家迭代 (Expert Iteration)</h3><p>比纯计划更进一步, 专家迭代学习并使用了一个显式的策略 $\pi_{\theta}(a\mid s)$ . 代理人在模型中使用一种规划算法 (比如蒙特卡罗搜索树) 来采样, 然后为计划生成候选动作, 这要比单纯的基于策略做出动作效果要好. 因此称之为 “专家” .</p><h3 id="无模型的数据增强-Data-Augmentation"><a href="#无模型的数据增强-Data-Augmentation" class="headerlink" title="无模型的数据增强 (Data Augmentation)"></a>无模型的数据增强 (Data Augmentation)</h3><p>利用在模型上采样的数据, 来训练无模型策略, 可以理解为扩充 (增强) 了数据. 可以使用虚拟数据 (采样生成的数据) 和真实数据的混合, 或者直接全部使用虚拟数据.</p><h3 id="规划嵌入策略"><a href="#规划嵌入策略" class="headerlink" title="规划嵌入策略"></a>规划嵌入策略</h3><p>将规划本身也嵌入策略中, 作为其子部分. 这样策略不仅要考虑当前动作, 还要考虑当前是否要进行规划以及如何规划 (规划本身也会影响动作的选择) . 这样当模型和现实有较大差距时, 策略会学着去不做规划.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 入门 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Hexo modify theme butterfly</title>
      <link href="/hexo/hexo_modify_theme_butterfly/"/>
      <url>/hexo/hexo_modify_theme_butterfly/</url>
      
        <content type="html"><![CDATA[<p><strong>本魔改主题适用 Hexo 4 . 所有魔改均可取消! 配置默认不开启, 因此可以平滑换到魔改 butterfly 主题.</strong></p><p>首先推介 <a href="https://docs.jerryc.me/">butterfly 文档</a>, 这里只介绍魔改部分的配置. <strong>这里的示例仅为合法示例, 即你填了该示例不一定能正确显示, 仅供参考.</strong> </p><p><a href="https://github.com/cnyist/hexo-modify-theme-butterfly">魔改主题 Github 地址</a></p><h1 id="使用主题-amp-平滑更换"><a href="#使用主题-amp-平滑更换" class="headerlink" title="使用主题 &amp; 平滑更换"></a>使用主题 &amp; 平滑更换</h1><h2 id="下载并配置"><a href="#下载并配置" class="headerlink" title="下载并配置"></a>下载并配置</h2><p>进入主题目录, 下载主题</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/cnyist/hexo-modify-theme-butterfly.git</span><br></pre></td></tr></table></figure><p>将下载下来的主题文件夹名字改为 <code>Butterfly</code> , 同时修改hexo配置文件<code>_config.yml</code>，把主題改为<code>Butterfly</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">theme: Butterfly</span><br></pre></td></tr></table></figure><p>如果你没有 pug 以及stylus的渲染器, 请下载安装: </p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-renderer-pug hexo-renderer-stylus --save</span><br></pre></td></tr></table></figure><p>or</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add hexo-renderer-pug hexo-renderer-stylus</span><br></pre></td></tr></table></figure><p><strong>如果你之前不是使用 butterfly 主题, 那么到这里你已经配置完毕, 接下来更改主题下 <code>_config.yml</code> 文件以个性化.</strong></p><h2 id="更换"><a href="#更换" class="headerlink" title="更换"></a>更换</h2><p>对比魔改主题的 <code>_config.yml</code> 与原主题 <code>_config.yml</code> 的区别, 将魔改配置加上 <strong>(默认关闭, 所以加上并不会有什么变化)</strong>, 并且将原主题多出的配置删除 (可能没有). 然后将更改过的 <code>_config.yml</code> 替换魔改主题的 <code>_config.yml</code> 就可以成功启用 (如果使用 <code>butterfly.yml</code> 同理).</p><h1 id="配置项"><a href="#配置项" class="headerlink" title="配置项"></a>配置项</h1><h2 id="cdn-post"><a href="#cdn-post" class="headerlink" title="cdn_post"></a>cdn_post</h2><p>自动将图片替换为 cdn 加速过的, 仅对图片有部署在 Github 上的博客有效.</p><ul><li>img<ul><li>值为 true 或 false, 值为 true 即在文章页开启图片加速 (不包括 cover).</li><li>示例: <code>false</code></li></ul></li><li>cover: true # 文章 cover 加速(启用后只能用相对路径, 具体请看魔改 butterfly 文档)<ul><li>值为 true 或 false, 值为 true 即开启文章 cover 加速.</li><li>示例: <code>false</code></li></ul></li><li>cdn_url<ul><li>将 “<a href="https://cdn.jsdelivr.net/gh/cnyist/blog/">https://cdn.jsdelivr.net/gh/cnyist/blog/</a>“ 中的 <code>cnyist</code> 换成你 Github 的用户名, <code>blog</code> 换成博客的 Github 仓库名.</li><li>示例: <code>&quot;https://cdn.jsdelivr.net/gh/cnyist/blog/&quot;</code></li></ul></li></ul><h2 id="content-opacity"><a href="#content-opacity" class="headerlink" title="content_opacity"></a>content_opacity</h2><p>设置透明度.</p><ul><li>post<ul><li>文章页设置, 填 0-1, 0为完全透明, 1为完全不透明.</li><li>示例: <code>1</code></li></ul></li><li>page<ul><li>页面设置, 填 0-1, 0为完全透明, 1为完全不透明</li><li>示例: <code>1</code></li></ul></li></ul><h2 id="banner-transparent"><a href="#banner-transparent" class="headerlink" title="banner_transparent"></a>banner_transparent</h2><p>隐藏 banner .</p><ul><li>值为 true 或 false , 值为 true 即隐藏 banner, false 即保持原样. <strong>此配置是用来和随机背景配合使用的.</strong></li><li>示例: <code>true</code></li></ul><h2 id="footer-transparent"><a href="#footer-transparent" class="headerlink" title="footer_transparent"></a>footer_transparent</h2><p>页脚透明度.</p><ul><li>填 0-1, 0为完全透明, 1为完全不透明.</li><li>示例: <code>1</code></li></ul><h2 id="random-background"><a href="#random-background" class="headerlink" title="random_background"></a>random_background</h2><p>首先你要准备一系列的图片作为随机背景的图片. 你应该把图片放在 Github 的仓库. 图片的命名要求有一定的格式. 比如说, 如果有 5 张图片, 那么应该命名为 0.jpg, 1.jpg, 2.jpg, 3.jpg, 4.jpg . 或者是 0.png, 1.png, 2.png, 3.png, 4.png  . 即编号从 0 开始递增且后缀必须相同. 将这些图片存在 Github 仓库中的某个文件夹中, 就可以开始下一步配置.</p><ul><li><p>post</p><ul><li>值为 true 或 false , 值为 true 即在文章页开启随机背景, false 即在文章页不开启随机背景.</li><li>示例: <code>false</code></li></ul></li><li><p>page</p><ul><li>值为 true 或 false , 值为 true 即在 page 页开启随机背景, false 即在 page 页不开启随机背景.</li><li>示例: <code>true</code></li></ul></li></ul><ul><li>username<ul><li>填你的 Gthub 用户名.</li><li>示例: <code>cnyist</code></li></ul></li></ul><ul><li><p>repo</p><ul><li>填存放图片的 Github 仓库名</li><li>示例: <code>banner</code></li></ul></li><li><p>path</p><ul><li>填存放图片的路径, 记得在最后和前面加上一个 <code>/</code> . 比如说, 我将图片存放在仓库中的 <code>source/img</code> 文件夹中, 那么你应该填 <code>/source/img/</code> . 如果你直接就放在根目录, 那么直接填一个 <code>/</code> 即可.</li><li>示例: <code>/img/</code></li></ul></li><li><p>img_num</p><ul><li>即你的图片的数量</li><li>示例: <code>55</code></li></ul></li><li><p>suffix</p><ul><li>图片的后缀, 比如 <code>.png</code> , <code>.jpg</code> , <code>.webp</code> 等等.</li><li>示例: <code>.jpg</code></li></ul></li></ul><h2 id="Twikoo"><a href="#Twikoo" class="headerlink" title="Twikoo"></a>Twikoo</h2><p>基于腾讯云的无后端评论系统, 具体介绍, 配置看<a href="https://twikoo.js.org">官方文档</a>.</p><ul><li>envId<ul><li>填写你的腾讯云云开发环境 ID</li><li>示例: <code>wkendi-382diw</code></li></ul></li></ul>]]></content>
      
      
      <categories>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Hexo </tag>
            
            <tag> 搭建站点 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>RL 基本概念</title>
      <link href="/ML/RL/primer/basic_concepts/"/>
      <url>/ML/RL/primer/basic_concepts/</url>
      
        <content type="html"><![CDATA[<h1 id="两种回报函数"><a href="#两种回报函数" class="headerlink" title="两种回报函数"></a>两种回报函数</h1><p>在强化学习中, 有两种常用的回报函数, 即<strong>有限无折损回报 ($\textrm{finite-horizon undiscount return}$)</strong> , 它将有限时间内每个时刻的奖赏加起来作为总回报:<br>$$R(\tau)=\sum_{t = 0}^Tr_t$$<br>与<strong>无限有折损回报 ($\textrm{infinite-horizon discount return}$)</strong> , 将往后至无穷的时间内每个时刻的奖赏加权后求和作为总回报.<br>$$R(\tau) = \sum_{t = 0}^\infty\gamma^tr_t$$<br>其中 $\gamma\in(0,1)$ , 是一个参数.</p><p>有限无折损回报很容易理解, 那么为什么会有无限有折损回报这种形式呢? 这有着直觉和数学上的双重意义.</p><ul><li>直觉上, 我们会将眼前利益看得更重要, 而未来的利益则显得没那么重要 ($\textrm{Cash now is better than cash later}$) .</li><li>数学上, 无限无折损回报会无法收敛到一个有限的值, 而乘上 $\gamma^t$ 这个折扣因子 ($\textrm{discount factor}$) 可以很好的解决这个问题.</li></ul><p>虽然这两种函数在数学上差别很大, 但在 $\textrm{deep RL}$ 中, 这两者往往会混用: 用无折扣来最优化参数, 同时在估算价值函数的时候使用有折扣.</p><h1 id="价值函数"><a href="#价值函数" class="headerlink" title="价值函数"></a>价值函数</h1><p>价值函数有两种, 一种是价值函数, 一种是动作-价值函数. 它们俩的区别就在于当前动作是否给出</p><p>价值函数<br>$$V^{\pi}(s) = \mathop{\mathrm E}_{\tau\sim\pi}[R(\tau)\mid s_0 = s]$$<br>动作-价值函数<br>$$Q^\pi(s,a)=\mathop{\mathrm{E}}_{\tau\sim\pi}[R(\tau)\mid s_0=s,a_0=a]$$<br>可以显而易见的看到差别就在于 $a$ 是否被指定.</p><p>强化学习的目的就在于求出最优策略, 我们将最优策略下的价值函数和动作价值函数用 $V^*(s)$ 与 $Q^*(s,a)$ 来表示, 则有<br>$$V^*(s)=\max_\pi\mathop{\mathrm{E}}_{\tau\sim\pi}[R(\tau)\mid s_0=s]\\\\Q^*(s,a)=\max_\pi\mathop{\mathrm{E}}_{\tau\sim\pi}[R(\tau)\mid s_0=s,a_0=a]$$<br>同时容易得出以下两个等式<br>$$V^\pi(s)=\mathop{\mathrm{E}}_{a\sim\pi}[Q^\pi(s,a)]\\\\V^*(s)=\max_{a}Q^*(s,a)$$<br>这里要注意, 在默认的情况下, 回报函数 $R(\tau)$ 一般是指无限有折损回报 ($\textrm{infinite-horizon discount return}$) , 如果使用的是有限无折损回报, 那么还要接受一个额外的参数: 时间.</p><h1 id="Bellman-方程"><a href="#Bellman-方程" class="headerlink" title="Bellman 方程"></a>Bellman 方程</h1><p>Bellman 方程给出了求解最优策略的过程. 对于某个策略 $\pi$ , 我们有<br>$$V^\pi(s) = \mathop{\mathrm{E}}_{a\sim\pi,s'\sim P}[r(s,a)+\gamma V^\pi(s')]\\\\Q^{\pi}(s,a)=\mathop{\mathrm{E}}_{s'\sim P}\left[r(s,a)+\gamma\mathop{\mathrm{E}}_{a'\sim\pi}[Q^\pi(s',a')]\right]$$<br>　用时对于最优策略, 我们有<br>$$V^*(s) = \max_{a}\mathop{\mathrm{E}}_{s'\sim P}[r(s,a)+\gamma V^\pi(s')]\\\\Q^*(s,a)=\mathop{\mathrm{E}}_{s'\sim P}\left[r(s,a)+ \gamma \max_{a'}Q^\pi(s',a')\right]$$<br>其中 $s'\sim P$ 是 $s'\sim P(\cdot\mid s,a)$ 的缩写, $a\sim \pi$ 与 $a'\sim \pi$ 分别是 $a\sim \pi(\cdot\mid s)$ 与 $a'\sim \pi(\cdot\mid s')$ 的缩写.</p><h1 id="优势方程"><a href="#优势方程" class="headerlink" title="优势方程"></a>优势方程</h1><p>优势方程 $A^{\pi}(s,a)$考虑了某个动作 $a$ 在当前状态 $s$ 以及采取策略 $\pi$ 下到底有多好.<br>$$A^{\pi}(s,a)=Q^{\pi}(s,a)-V^{\pi}(s)$$</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 入门 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>仅引入 JS 实现博客 CDN 加速</title>
      <link href="/hexo/jsdelivr_js/"/>
      <url>/hexo/jsdelivr_js/</url>
      
        <content type="html"><![CDATA[<h1 id="前提"><a href="#前提" class="headerlink" title="前提"></a>前提</h1><p>博客 cdn 加速网上有很多的教程, 其中免备案, 最好用的就是 Jsdelivr 了, 我也写过一篇<a href="https://yunist.cn/hexo/Hexo_blog_build/">用 Jsdelivr 加速的文章</a>, 但是似乎很多人一开始都看不懂如何用 Jsdelivr 加速… 这篇文章的原理也是基于 Jsdelivr 加速博文图片, 但是<strong>保留了原来的相对路径</strong>. 并且能够<strong>仅引入一个 JS 实现 Jsdelivr 加速</strong> . </p><ul><li><p><strong>本文的方法只能实现博文内图片加速, 其余页面的图片无法加速 (为了避免与友链图片等冲突, 并且像文章封面这种图片难以只用 JS 实现替换为 Jsdelivr 链接) .</strong></p></li><li><p><strong>本文能够成功的前提是图片在原文中用相对路径引用, 同时博客部署在 Github 上.</strong></p></li><li><strong>本文的方法可能和懒加载有冲突, 因此建议关闭懒加载 (实际上使用了 Jsdelivr 后加载是飞速的, 根本不需要懒加载) .</strong></li><li><strong>除 Butterfly 主题外, 其他主题的 JS 代码并没有经过严格的测试, 因此可能出现 Bug , 请及时留言.</strong></li><li><strong>由于主题版本的原因, JS 代码可能会出错或者失效, 请及时留言.</strong></li></ul><h1 id="JS-代码"><a href="#JS-代码" class="headerlink" title="JS 代码"></a>JS 代码</h1><p>为了方便小白, 这里把部分主题 JS 代码写法都写出来了 (什么? 没有你的主题? 那就留言, 我看到有时间就会加上的) .</p><h2 id="Butterfly"><a href="#Butterfly" class="headerlink" title="Butterfly"></a>Butterfly</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&quot;cnyist&quot;</span>;</span><br><span class="line"><span class="keyword">var</span> repository = <span class="string">&quot;blog&quot;</span>;</span><br><span class="line"><span class="keyword">if</span>(<span class="variable language_">document</span>.<span class="property">domain</span> != <span class="string">&#x27;localhost&#x27;</span>)&#123;</span><br><span class="line"><span class="keyword">if</span>(<span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;post&quot;</span>))&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;article-container&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>))&#123;</span><br><span class="line">  <span class="keyword">if</span> (<span class="built_in">isNaN</span>(key))&#123;</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">  &#125;</span><br><span class="line">    <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;article-container&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span> = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;article-container&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span>.<span class="title function_">replace</span>(<span class="variable language_">document</span>.<span class="property">domain</span>,<span class="string">&quot;cdn.jsdelivr.net/gh/&quot;</span> + name + <span class="string">&quot;/&quot;</span> + repository)</span><br><span class="line">&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Matery"><a href="#Matery" class="headerlink" title="Matery"></a>Matery</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&quot;cnyist&quot;</span>;</span><br><span class="line"><span class="keyword">var</span> repository = <span class="string">&quot;blog&quot;</span>;</span><br><span class="line"><span class="keyword">if</span>(<span class="variable language_">document</span>.<span class="property">domain</span> != <span class="string">&#x27;localhost&#x27;</span>)&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;articleContent&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>))&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">isNaN</span>(key))&#123;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;articleContent&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span> = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;articleContent&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span>.<span class="title function_">replace</span>(<span class="variable language_">document</span>.<span class="property">domain</span>,<span class="string">&quot;cdn.jsdelivr.net/gh/&quot;</span> + name + <span class="string">&quot;/&quot;</span> + repository)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Icarus"><a href="#Icarus" class="headerlink" title="Icarus"></a>Icarus</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&quot;cnyist&quot;</span>;</span><br><span class="line"><span class="keyword">var</span> repository = <span class="string">&quot;blog&quot;</span>;</span><br><span class="line"><span class="keyword">if</span>(<span class="variable language_">document</span>.<span class="property">domain</span> != <span class="string">&#x27;localhost&#x27;</span>)&#123;</span><br><span class="line">    <span class="keyword">if</span>(<span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;post-copyright&quot;</span>)[<span class="number">0</span>] || <span class="variable language_">document</span>.<span class="property">URL</span> == <span class="string">&quot;https://&quot;</span> + <span class="variable language_">document</span>.<span class="property">domain</span> + <span class="string">&#x27;/&#x27;</span>)&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> <span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;card-content article&quot;</span>)[<span class="number">0</span>].<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>))&#123;</span><br><span class="line">            <span class="keyword">if</span> (<span class="built_in">isNaN</span>(key))&#123;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        <span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;card-content article&quot;</span>)[<span class="number">0</span>].<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span> = <span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;card-content article&quot;</span>)[<span class="number">0</span>].<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span>.<span class="title function_">replace</span>(<span class="variable language_">document</span>.<span class="property">domain</span>,<span class="string">&quot;cdn.jsdelivr.net/gh/&quot;</span> + name + <span class="string">&quot;/&quot;</span> + repository)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Next"><a href="#Next" class="headerlink" title="Next"></a>Next</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&quot;cnyist&quot;</span>;</span><br><span class="line"><span class="keyword">var</span> repository = <span class="string">&quot;blog&quot;</span>;</span><br><span class="line"><span class="keyword">if</span>(<span class="variable language_">document</span>.<span class="property">domain</span> != <span class="string">&#x27;localhost&#x27;</span>)&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;posts&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>))&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">isNaN</span>(key))&#123;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;posts&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span> = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;posts&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span>.<span class="title function_">replace</span>(<span class="variable language_">document</span>.<span class="property">domain</span>,<span class="string">&quot;cdn.jsdelivr.net/gh/&quot;</span> + name + <span class="string">&quot;/&quot;</span> + repository)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Volantis"><a href="#Volantis" class="headerlink" title="Volantis"></a>Volantis</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&quot;cnyist&quot;</span>;</span><br><span class="line"><span class="keyword">var</span> repository = <span class="string">&quot;blog&quot;</span>;</span><br><span class="line"><span class="keyword">if</span>(<span class="variable language_">document</span>.<span class="property">domain</span> != <span class="string">&#x27;localhost&#x27;</span>)&#123;</span><br><span class="line">    <span class="keyword">if</span>(<span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;post&quot;</span>))&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;post&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>))&#123;</span><br><span class="line">            <span class="keyword">if</span> (<span class="built_in">isNaN</span>(key))&#123;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;post&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span> = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;post&quot;</span>).<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span>.<span class="title function_">replace</span>(<span class="variable language_">document</span>.<span class="property">domain</span>,<span class="string">&quot;cdn.jsdelivr.net/gh/&quot;</span> + name + <span class="string">&quot;/&quot;</span> + repository)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(<span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;post-list&quot;</span>)[<span class="number">0</span>])&#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> <span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;post-list&quot;</span>)[<span class="number">0</span>].<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>))&#123;</span><br><span class="line">            <span class="keyword">if</span> (<span class="built_in">isNaN</span>(key))&#123;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;post-list&quot;</span>)[<span class="number">0</span>].<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span> = <span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&quot;post-list&quot;</span>)[<span class="number">0</span>].<span class="title function_">getElementsByTagName</span>(<span class="string">&#x27;img&#x27;</span>)[key].<span class="property">src</span>.<span class="title function_">replace</span>(<span class="variable language_">document</span>.<span class="property">domain</span>,<span class="string">&quot;cdn.jsdelivr.net/gh/&quot;</span> + name + <span class="string">&quot;/&quot;</span> + repository)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="使用方式"><a href="#使用方式" class="headerlink" title="使用方式"></a>使用方式</h1><p>将 JS 代码中 <code>name</code> 变量换成你自己的 Github 用户名, <code>repository</code> 变量换成你自己的存放博客的 Github 仓库. 如果<strong>以上主题是你使用的主题</strong>, 那么改完之后就<strong>可以引入这个 JS 开始使用了 (最好放在 Html 的 body 处引用, 因为 Html 的加载是从上至下的)</strong>, 什么?! 你连引用 JS 都不会?! 好吧, 那接下来说得再详细一点.</p><p>首先根据你的主题, 将对应的 JS 代码保存为 <code>jsdelivr.js</code> 文件保存在<strong>主题的</strong> <code>source/js</code> 文件夹. 如果你的主题支持 <code>_config.yml</code> 中添加 JS 代码 (进入你的主题搜索 JS 关键字可能就可以搜到, 比如 Butterfly 就支持)</p><p><img src="1.png" alt="Butterfly _conifg.yml"></p><p>那就直接加 <code>/jsdelivr.js</code> 上去就好了 (为什么我这里写的是 <code>/js/jsdelivr.js</code> ? 因为我把这个 JS 放在 <code>source</code> 文件夹下的 <code>js</code> 文件夹里了, 鉴于某些主题可能没有该文件夹, 因此放在 <code>source</code> 文件夹并且写 <code>/jsdeliv.js</code> 是最保险的) .</p><p>当然部分主题的添加 JS 代码的方式可能不同, 有些是添加链接就好 (比如上面的例子), 有些是要写标签 (比如新版 Butterfly), 如果是写标签的话. 就将 <code>&lt;script src=&quot;/jsdelivr.js&quot;&gt;&lt;/script&gt;</code> 写进去就好了 (注意 yml 文件语法) .</p><p>如果都没有, 那就需要更改源文件了.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script src=&quot;/jsdelivr.js&quot;&gt;&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>将以上代码放入 ejs 源文件的 body 标签里 (就是被 <code>&lt;body&gt;</code> 和 <code>&lt;/body&gt;</code> 包围的区域, 你可以查找关键字 <code>&lt;body&gt;</code> 然后将以上代码放到这个标签的下面).</p><p><strong>如果以上 js 代码没有你的主题, 你又不好意思留言 (或者不想等太久) , 那么就需要你自己更改以上 js 代码.</strong>以 Butterfly 主题的 js 代码为例, 将 <code>article-container</code> 改成你自己主题的文章内容的 Html 标签 id , 而 <code>post</code> 改成你自己主题 Post 文章特有的 id (就是说这个 id page 是没有的, 用于判断该页是 Post 还是 Page) .</p>]]></content>
      
      
      <categories>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Hexo </tag>
            
            <tag> 搭建站点 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>强化学习入门 Demo</title>
      <link href="/ML/RL/primer/RL_demo/"/>
      <url>/ML/RL/primer/RL_demo/</url>
      
        <content type="html"><![CDATA[<h1 id="Q-Learning"><a href="#Q-Learning" class="headerlink" title="Q Learning"></a>Q Learning</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> IPython</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">length = <span class="number">4</span>  <span class="comment"># 道路长度</span></span><br><span class="line">epsilon = <span class="number">0.9</span>  <span class="comment"># 贪心值</span></span><br><span class="line">a = [<span class="number">0</span>, <span class="number">1</span>]  <span class="comment"># 动作</span></span><br><span class="line">Q_a = np.zeros([length + <span class="number">1</span>, <span class="built_in">len</span>(a)])  <span class="comment"># Q-a表</span></span><br><span class="line">alpha = <span class="number">0.1</span></span><br><span class="line">gamma = <span class="number">0.9</span></span><br><span class="line">game_over = <span class="literal">False</span>  <span class="comment"># 一轮游戏是否结束</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">print_environment</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;打印环境&quot;&quot;&quot;</span></span><br><span class="line">    <span class="built_in">str</span> = <span class="string">&#x27;-&#x27;</span> * state</span><br><span class="line">    <span class="built_in">str</span> += <span class="string">&#x27;o&#x27;</span></span><br><span class="line">    <span class="built_in">str</span> += <span class="string">&#x27;-&#x27;</span> * (length - state - <span class="number">1</span>)</span><br><span class="line">    <span class="keyword">if</span> state != length:</span><br><span class="line">        <span class="built_in">str</span> += <span class="string">&#x27;{%raw%}$&#x27;</span></span><br><span class="line">    <span class="built_in">print</span>(<span class="built_in">str</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">best_Q</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;最佳动作获得的Q&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">return</span> Q_a[state].<span class="built_in">max</span>()</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">best_action</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;最佳动作, 有多个最大从中随机选择一个&quot;&quot;&quot;</span></span><br><span class="line">    max_arr = np.argsort(Q_a[state])[::-<span class="number">1</span>]  <span class="comment"># 排序</span></span><br><span class="line">    max_index = np.random.randint(<span class="number">0</span>, np.<span class="built_in">sum</span>(Q_a[state] == Q_a[state][max_arr[<span class="number">0</span>]]))  <span class="comment"># 随机选择</span></span><br><span class="line">    <span class="keyword">return</span> max_arr[max_index]</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">update_Q</span>(<span class="params">state, next_state, action, reward</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;更新Q表&quot;&quot;&quot;</span></span><br><span class="line">    Q_a[state][action] += alpha * (reward + gamma * best_Q(next_state) - Q_a[state][action])</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">greedy</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;贪婪策略&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">if</span> np.random.rand() &lt; epsilon:</span><br><span class="line">        <span class="keyword">return</span> best_action(state)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> np.random.randint(<span class="number">0</span>, Q_a[state].shape[<span class="number">0</span>])  <span class="comment"># 随机动作</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">update_state</span>(<span class="params">now_state, action</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;更新环境及获取奖赏&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">if</span> action == <span class="number">0</span>:</span><br><span class="line">        <span class="keyword">if</span> now_state != <span class="number">0</span>:</span><br><span class="line">            next_state = now_state - <span class="number">1</span></span><br><span class="line">            reward = <span class="number">0</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            next_state = now_state</span><br><span class="line">            reward = <span class="number">0</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">if</span> now_state == length - <span class="number">1</span>:</span><br><span class="line">            next_state = now_state + <span class="number">1</span></span><br><span class="line">            reward = <span class="number">1</span>  <span class="comment"># 到达终点奖励</span></span><br><span class="line">            <span class="keyword">global</span> game_over</span><br><span class="line">            game_over = <span class="literal">True</span>  <span class="comment"># 游戏结束</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            next_state = now_state + <span class="number">1</span></span><br><span class="line">            reward = <span class="number">0</span></span><br><span class="line">    print_environment(next_state)</span><br><span class="line">    <span class="keyword">return</span> next_state, reward</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">Q_learning</span>(<span class="params">start, rounds, max_times</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;start是起点, rounds是轮数, max_times是每轮迭代最大次数&quot;&quot;&quot;</span></span><br><span class="line">    state = start</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(rounds):</span><br><span class="line">        state = start</span><br><span class="line">        print_environment(state)</span><br><span class="line">        time.sleep(<span class="number">1</span>)</span><br><span class="line">        IPython.display.clear_output()  <span class="comment"># 清空输出</span></span><br><span class="line">        <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(max_times):</span><br><span class="line">            <span class="keyword">global</span> game_over</span><br><span class="line">            <span class="keyword">if</span> game_over:</span><br><span class="line">                game_over = <span class="literal">False</span></span><br><span class="line">                <span class="built_in">print</span>(<span class="string">&#x27;Game Over&#x27;</span>)</span><br><span class="line">                time.sleep(<span class="number">1</span>)</span><br><span class="line">                IPython.display.clear_output()  <span class="comment"># 清空输出</span></span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            action = greedy(state)</span><br><span class="line">            next_state, reward = update_state(state, action)</span><br><span class="line">            update_Q(state, next_state, action, reward)</span><br><span class="line">            state = next_state</span><br><span class="line">            time.sleep(<span class="number">1</span>)</span><br><span class="line">            IPython.display.clear_output()  <span class="comment"># 清空输出</span></span><br><span class="line"></span><br><span class="line">            </span><br><span class="line">Q_learning(<span class="number">0</span>, <span class="number">5</span>, <span class="number">100</span>)</span><br></pre></td></tr></table></figure><h1 id="Sarsa"><a href="#Sarsa" class="headerlink" title="Sarsa"></a>Sarsa</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> IPython</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">length = <span class="number">5</span>  <span class="comment"># 道路长度(由于saras算法过于保守, 所以如果设太长的话...你可能得等半天)</span></span><br><span class="line">epsilon = <span class="number">0.9</span>  <span class="comment"># 贪心值</span></span><br><span class="line">a = [<span class="number">0</span>, <span class="number">1</span>]  <span class="comment"># 动作</span></span><br><span class="line">Q_a = np.zeros([length + <span class="number">1</span>, <span class="built_in">len</span>(a)])  <span class="comment"># Q-a表</span></span><br><span class="line">alpha = <span class="number">0.1</span></span><br><span class="line">gamma = <span class="number">0.9</span></span><br><span class="line">game_over = <span class="literal">False</span>  <span class="comment"># 一轮游戏是否结束</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">print_environment</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;打印环境&quot;&quot;&quot;</span></span><br><span class="line">    <span class="built_in">str</span> = <span class="string">&#x27;-&#x27;</span> * state</span><br><span class="line">    <span class="built_in">str</span> += <span class="string">&#x27;o&#x27;</span></span><br><span class="line">    <span class="built_in">str</span> += <span class="string">&#x27;-&#x27;</span> * (length - state - <span class="number">1</span>)</span><br><span class="line">    <span class="keyword">if</span> state != length:</span><br><span class="line">        <span class="built_in">str</span> += <span class="string">&#x27;${%endraw%}&#x27;</span></span><br><span class="line">    <span class="built_in">print</span>(<span class="built_in">str</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">best_Q</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;最佳动作获得的Q&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">return</span> Q_a[state].<span class="built_in">max</span>()</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">best_action</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;最佳动作, 有多个最大从中随机选择一个&quot;&quot;&quot;</span></span><br><span class="line">    max_arr = np.argsort(Q_a[state])[::-<span class="number">1</span>]  <span class="comment"># 排序</span></span><br><span class="line">    max_index = np.random.randint(<span class="number">0</span>, np.<span class="built_in">sum</span>(Q_a[state] == Q_a[state][max_arr[<span class="number">0</span>]]))  <span class="comment"># 随机选择</span></span><br><span class="line">    <span class="keyword">return</span> max_arr[max_index]</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">update_Q</span>(<span class="params">state, next_state, action, next_action, reward</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;更新Q表, 相比Q Learning的差别就在于并非选取最佳动作获得的Q而是实际动作获得的Q&quot;&quot;&quot;</span></span><br><span class="line">    Q_a[state][action] += alpha * (reward + gamma * Q_a[next_state][next_action] - Q_a[state][action])</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">greedy</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;贪婪策略&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">if</span> np.random.rand() &lt; epsilon:</span><br><span class="line">        <span class="keyword">return</span> best_action(state)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> np.random.randint(<span class="number">0</span>, Q_a[state].shape[<span class="number">0</span>])  <span class="comment"># 随机动作</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">update_state</span>(<span class="params">now_state, action</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;更新环境及获取奖赏&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">if</span> action == <span class="number">0</span>:</span><br><span class="line">        <span class="keyword">if</span> now_state != <span class="number">0</span>:</span><br><span class="line">            next_state = now_state - <span class="number">1</span></span><br><span class="line">            reward = <span class="number">0</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            next_state = now_state</span><br><span class="line">            reward = <span class="number">0</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">if</span> now_state == length - <span class="number">1</span>:</span><br><span class="line">            next_state = now_state + <span class="number">1</span></span><br><span class="line">            reward = <span class="number">1</span>  <span class="comment"># 到达终点奖励</span></span><br><span class="line">            <span class="keyword">global</span> game_over</span><br><span class="line">            game_over = <span class="literal">True</span>  <span class="comment"># 游戏结束</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            next_state = now_state + <span class="number">1</span></span><br><span class="line">            reward = <span class="number">0</span></span><br><span class="line">    print_environment(next_state)</span><br><span class="line">    <span class="keyword">return</span> next_state, reward</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">Sarsa</span>(<span class="params">start, rounds, max_times</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;start是起点, rounds是轮数, max_times是每轮迭代最大次数&quot;&quot;&quot;</span></span><br><span class="line">    state = start</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(rounds):</span><br><span class="line">        state = start</span><br><span class="line">        print_environment(state)</span><br><span class="line">        time.sleep(<span class="number">1</span>)</span><br><span class="line">        IPython.display.clear_output()  <span class="comment"># 清空输出</span></span><br><span class="line">        action = greedy(state)</span><br><span class="line">        <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(max_times):</span><br><span class="line">            <span class="keyword">global</span> game_over</span><br><span class="line">            <span class="keyword">if</span> game_over:</span><br><span class="line">                game_over = <span class="literal">False</span></span><br><span class="line">                <span class="built_in">print</span>(<span class="string">&#x27;Game Over&#x27;</span>)</span><br><span class="line">                time.sleep(<span class="number">1</span>)</span><br><span class="line">                IPython.display.clear_output()  <span class="comment"># 清空输出</span></span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            next_action = greedy(state)</span><br><span class="line">            next_state, reward = update_state(state, action)</span><br><span class="line">            update_Q(state, next_state, action, next_action, reward)</span><br><span class="line">            state = next_state</span><br><span class="line">            action = next_action</span><br><span class="line">            time.sleep(<span class="number">1</span>)</span><br><span class="line">            IPython.display.clear_output()  <span class="comment"># 清空输出</span></span><br><span class="line"></span><br><span class="line">            </span><br><span class="line">Sarsa(<span class="number">0</span>, <span class="number">10</span>, <span class="number">100</span>)</span><br></pre></td></tr></table></figure><h1 id="Sarsa-Lambda"><a href="#Sarsa-Lambda" class="headerlink" title="Sarsa Lambda"></a>Sarsa Lambda</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> IPython</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">length = <span class="number">5</span>  <span class="comment"># 道路长度</span></span><br><span class="line">epsilon = <span class="number">0.9</span>  <span class="comment"># 贪心值</span></span><br><span class="line">a = [<span class="number">0</span>, <span class="number">1</span>]  <span class="comment"># 动作</span></span><br><span class="line">Q_a = np.zeros([length + <span class="number">1</span>, <span class="built_in">len</span>(a)])  <span class="comment"># Q-a表</span></span><br><span class="line">E = Q_a.copy()  <span class="comment"># 状态表, 可以理解为遗忘程度 (0 即为完全遗忘, 1 即为完全记得, 按照遗忘程度来给出贡献)</span></span><br><span class="line">alpha = <span class="number">0.1</span></span><br><span class="line">gamma = <span class="number">0.9</span></span><br><span class="line">trace_decay = <span class="number">0.9</span>  <span class="comment"># lambda值</span></span><br><span class="line">game_over = <span class="literal">False</span>  <span class="comment"># 一轮游戏是否结束</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">print_environment</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;打印环境&quot;&quot;&quot;</span></span><br><span class="line">    <span class="built_in">str</span> = <span class="string">&#x27;-&#x27;</span> * state</span><br><span class="line">    <span class="built_in">str</span> += <span class="string">&#x27;o&#x27;</span></span><br><span class="line">    <span class="built_in">str</span> += <span class="string">&#x27;-&#x27;</span> * (length - state - <span class="number">1</span>)</span><br><span class="line">    <span class="keyword">if</span> state != length:</span><br><span class="line">        <span class="built_in">str</span> += <span class="string">&#x27;$&#x27;</span></span><br><span class="line">    <span class="built_in">print</span>(<span class="built_in">str</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">best_Q</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;最佳动作获得的Q&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">return</span> Q_a[state].<span class="built_in">max</span>()</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">best_action</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;最佳动作, 有多个最大从中随机选择一个&quot;&quot;&quot;</span></span><br><span class="line">    max_arr = np.argsort(Q_a[state])[::-<span class="number">1</span>]  <span class="comment"># 排序</span></span><br><span class="line">    max_index = np.random.randint(<span class="number">0</span>, np.<span class="built_in">sum</span>(Q_a[state] == Q_a[state][max_arr[<span class="number">0</span>]]))  <span class="comment"># 随机选择</span></span><br><span class="line">    <span class="keyword">return</span> max_arr[max_index]</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">update_Q</span>(<span class="params">state, next_state, action, next_action, reward</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;更新Q表, 相比Sarsa的差别就在于E表起到了对之前的Q表更新的作用&quot;&quot;&quot;</span></span><br><span class="line">    <span class="comment"># 这里有两种更新方式, 可以都尝试一下</span></span><br><span class="line">    <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">    E[state][action] += 1</span></span><br><span class="line"><span class="string">    &quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">global</span> E</span><br><span class="line">    <span class="keyword">global</span> Q_a</span><br><span class="line">    E[state,:] = <span class="number">0</span></span><br><span class="line">    E[state][action] = <span class="number">1</span></span><br><span class="line">    Q_a += alpha * E * (reward + gamma * Q_a[next_state][next_action] - Q_a[state][action])</span><br><span class="line">    E *= trace_decay * gamma</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">greedy</span>(<span class="params">state</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;贪婪策略&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">if</span> np.random.rand() &lt; epsilon:</span><br><span class="line">        <span class="keyword">return</span> best_action(state)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> np.random.randint(<span class="number">0</span>, Q_a[state].shape[<span class="number">0</span>])  <span class="comment"># 随机动作</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">update_state</span>(<span class="params">now_state, action</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;更新环境及获取奖赏&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">if</span> action == <span class="number">0</span>:</span><br><span class="line">        <span class="keyword">if</span> now_state != <span class="number">0</span>:</span><br><span class="line">            next_state = now_state - <span class="number">1</span></span><br><span class="line">            reward = <span class="number">0</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            next_state = now_state</span><br><span class="line">            reward = <span class="number">0</span></span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">if</span> now_state == length - <span class="number">1</span>:</span><br><span class="line">            next_state = now_state + <span class="number">1</span></span><br><span class="line">            reward = <span class="number">1</span>  <span class="comment"># 到达终点奖励</span></span><br><span class="line">            <span class="keyword">global</span> game_over</span><br><span class="line">            game_over = <span class="literal">True</span>  <span class="comment"># 游戏结束</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            next_state = now_state + <span class="number">1</span></span><br><span class="line">            reward = <span class="number">0</span></span><br><span class="line">    print_environment(next_state)</span><br><span class="line">    <span class="keyword">return</span> next_state, reward</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">Sarsa_Lambda</span>(<span class="params">start, rounds, max_times</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;start是起点, rounds是轮数, max_times是每轮迭代最大次数&quot;&quot;&quot;</span></span><br><span class="line">    state = start</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(rounds):</span><br><span class="line">        state = start</span><br><span class="line">        print_environment(state)</span><br><span class="line">        time.sleep(<span class="number">1</span>)</span><br><span class="line">        IPython.display.clear_output()  <span class="comment"># 清空输出</span></span><br><span class="line">        action = greedy(state)</span><br><span class="line">        <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(max_times):</span><br><span class="line">            <span class="keyword">global</span> game_over</span><br><span class="line">            <span class="keyword">if</span> game_over:</span><br><span class="line">                game_over = <span class="literal">False</span></span><br><span class="line">                <span class="built_in">print</span>(<span class="string">&#x27;Game Over&#x27;</span>)</span><br><span class="line">                time.sleep(<span class="number">1</span>)</span><br><span class="line">                IPython.display.clear_output()  <span class="comment"># 清空输出</span></span><br><span class="line">                E[:] = <span class="number">0</span>  <span class="comment"># E表归0</span></span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            next_action = greedy(state)</span><br><span class="line">            next_state, reward = update_state(state, action)</span><br><span class="line">            update_Q(state, next_state, action, next_action, reward)</span><br><span class="line">            state = next_state</span><br><span class="line">            action = next_action</span><br><span class="line">            time.sleep(<span class="number">1</span>)</span><br><span class="line">            IPython.display.clear_output()  <span class="comment"># 清空输出</span></span><br><span class="line"></span><br><span class="line">            </span><br><span class="line">Sarsa_Lambda(<span class="number">0</span>, <span class="number">10</span>, <span class="number">100</span>)</span><br></pre></td></tr></table></figure>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 入门 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> Python </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 代码实例 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>读懂西瓜书 16 : 强化学习</title>
      <link href="/ML/watermelon_book/read/16/"/>
      <url>/ML/watermelon_book/read/16/</url>
      
        <content type="html"><![CDATA[<h1 id="K-摇臂赌博机"><a href="#K-摇臂赌博机" class="headerlink" title="K-摇臂赌博机"></a>K-摇臂赌博机</h1><h2 id="探索与利用"><a href="#探索与利用" class="headerlink" title="探索与利用"></a>探索与利用</h2><p>探索与利用总是矛盾的, 要使奖赏最大, 就要在探索与利用之间做好权衡.</p><h2 id="ϵ-贪心"><a href="#ϵ-贪心" class="headerlink" title="ϵ-贪心"></a>ϵ-贪心</h2><p>以 $\epsilon$ 的概率进行探索, 以 $1-\epsilon$ 的概率进行利用.</p><h3 id="增量式计算"><a href="#增量式计算" class="headerlink" title="增量式计算"></a>增量式计算</h3><p>令 $Q(k)$ 记录摇臂 $k$ 的平均奖赏. 若摇臂 $k$ 被尝试了 $n$ 次, 得到的奖赏是 $v_1,v_2,\dots,v_n$ , 则平均奖赏为<br>$$Q(k)=\frac{1}{n}\sum_{i=1}^nv_i$$<br>由于如果这样计算的话, 需要记录 $n$ 个奖赏值, 算法效率也不高 ( $\mathcal O(n)$ ) , 所以采用增量式计算.<br>$$\begin{aligned}Q_n(k)&=\frac{1}{n}\big((n-1)\times Q_{n-1}(k)+v_n\big)\\\\&=Q_{n-1}(k)+\frac{1}{n}\big(v_n-Q_{n-1}(k)\big)\end{aligned}$$<br>这样就只需要记录两个值: 已尝试次数 $n-1$ 以及最近平均奖赏 $Q_{n-1}(k)$ . 算法复杂度也下降到 $\mathcal O(1)$ .</p><h2 id="Softmax"><a href="#Softmax" class="headerlink" title="Softmax"></a>Softmax</h2><p> &nbsp;$\mathrm{Softmax}$ 可以看做是高维的 $\mathrm{Sigmoid}$ 函数. 使用 $\mathrm{Softmax}$ 可以让那些奖赏更高的摇臂有更高的被选取概率.<br>$$p(k) = \frac{\mathrm{e}^{\frac{Q(k)}{\tau}}}{\sum_{i=1}^K\mathrm{e}^{\frac{Q(i)}{\tau}}}$$<br>其中 $\tau>0$ 称为 “温度” . 温度趋近于 $0$ , 将倾向于 “仅利用” , 温度趋近于无穷大, 将倾向与 “仅探索” . 我们假设 $k'$ 是奖赏最高的那个摇臂, 那么有<br>$$\begin{aligned}p(k')=\lim_{\tau\to0 }\frac{\mathrm{e}^{\frac{Q(k')}{\tau}}}{\sum_{i=1}^K\mathrm{e}^{\frac{Q(i)}{\tau}}}&=\lim_{\tau\to0 }\frac{1}{1+\sum_{i=1,i\not=k'}^K\frac{\mathrm{e}^{(Q(i)/\tau)}}{\mathrm{e^{(Q(k')/\tau)}}}}\\\\\end{aligned}$$<br>注意到求和的每一项都趋近于 $0$ , 于是有<br>$$\begin{aligned}p(k')=\lim_{\tau\to0 }\frac{\mathrm{e}^{\frac{Q(k)}{\tau}}}{\sum_{i=1}^K\mathrm{e}^{\frac{Q(i)}{\tau}}}&=\lim_{\tau\to0 }\frac{1}{1+\sum_{i=1,i\not=k'}^K\frac{\mathrm{e}^{(Q(i)/\tau)}}{\mathrm{e^{(Q(k')/\tau)}}}}\\\\&=\frac{1}{1+0}\\\\&=1\end{aligned}$$<br>趋近于无穷大是相反的一个过程.</p><h1 id="有模型学习"><a href="#有模型学习" class="headerlink" title="有模型学习"></a>有模型学习</h1><h2 id="策略评估"><a href="#策略评估" class="headerlink" title="策略评估"></a>策略评估</h2><h3 id="式-16-7-与-16-8"><a href="#式-16-7-与-16-8" class="headerlink" title="式 (16.7) 与 (16.8)"></a>式 (16.7) 与 (16.8)</h3><p>对于这两个式子, 注意到<br>$$\sum_{a\in A}\pi(x,a)\sum_{x'\in X}P_{x\to x'}^a$$<br>计算了下一步到状态 $x'$ 的概率. 而<br>$$\sum_{a\in A}\pi(x,a)\sum_{x'\in X}\left(P_{x\to x'}^a\frac{1}{T}R_{x\to x'}^a\right)$$<br>则计算了假如下一步转移到状态 $x'$ , 这一步的期望奖赏. (这里用的是 $T$ 步积累奖赏, $\gamma$ 折扣累积奖赏也是类似的) .</p><h2 id="策略改进"><a href="#策略改进" class="headerlink" title="策略改进"></a>策略改进</h2><p>原来的策略评估只是将所有可能的动作产生的期望以概率求和, 那么为什么不直接选择最好的那个动作呢? 这就叫做策略改进. 由于每一步改进都会变得更好, 于是到最后不能变得再好的时候 (也就是收敛) 时, 就达到了最优策略.</p><h2 id="策略迭代与值迭代"><a href="#策略迭代与值迭代" class="headerlink" title="策略迭代与值迭代"></a>策略迭代与值迭代</h2><p>第一个算法是将两个部分分开, 效率较低, 而第二个算法同时进行两个部分, 效率较高.</p><h1 id="免模型学习"><a href="#免模型学习" class="headerlink" title="免模型学习"></a>免模型学习</h1><p>​           没有模型, 我们就不能方便的计算出每一步的期望了, 因此就要近似的计算.</p><h2 id="蒙特卡罗强化学习"><a href="#蒙特卡罗强化学习" class="headerlink" title="蒙特卡罗强化学习"></a>蒙特卡罗强化学习</h2><p>通过蒙特卡罗随机游走, 采样出 $n$ 条轨迹, 为了保证每条轨迹都不同, 因此采用了 $\epsilon$-贪心策略, 即以 $1-\epsilon$ 的概率选取确定性的策略 $\pi$ (在这里也可以等价为最优动作) 来作为当前动作, 以 $\epsilon$ 的概率选取随机动作 (同样包括策略 $\pi$ ) . 因此策略 $\pi$ 被选取到的概率是 $1-\epsilon+\frac{\epsilon}{|A|}$ , $A$ 为动作集合.</p><h3 id="同策略"><a href="#同策略" class="headerlink" title="同策略"></a>同策略</h3><p>同策略即评估和改进的是同一个策略, 即 $\epsilon$-贪心策略. 但是 $\epsilon$-贪心策略本来是帮助策略评估 (走出不同轨迹) 的, 而不是为了最终使用, 于是就有了异策略.</p><h3 id="异策略"><a href="#异策略" class="headerlink" title="异策略"></a>异策略</h3><p>异策略采用了两种策略, 一种用来评估, 一种用来改进. 其实现原理与拒绝-接受采样差不多.</p><h2 id="时序差分学习"><a href="#时序差分学习" class="headerlink" title="时序差分学习"></a>时序差分学习</h2><p>由于蒙特卡罗强化学习需要对策略评估后才能做出改进, 而前面的策略迭代与值迭代算法的更新是实时的, 于是蒙特卡罗强化学习方法就显得效率太低, 这是由于没有充分利用强化学习的 $\mathrm{MDP}$ 结构. $\mathrm{MDP}$ 结构的一大特点就是无后效性, 但是蒙特卡罗强化学习的 “全部评估-全部学习” 方法没有很好的利用这一点.</p><p>时序差分学习与蒙特卡罗强化学习的差别就在于, 蒙特卡罗强化学习在求平均 (近似期望) 的时候是 “批处理式” 的, 而时序差分学习是 “增量式” 的.<br>$$Q_{t+1}^\pi(x,a)=Q_{t}^\pi(x,a)+\frac{1}{t+1}\big(r_t+1-Q_{t}^\pi(x,a)\big)$$<br>通常将 $\frac{1}{t+1}$ 替换为系数 $\alpha_{t+1}$ , 在实践中通常令 $\alpha_{t+1}$ 为一个较小的正数值 $\alpha$ . 当然, 这样就不是求平均了, 但是将 $Q_{t}^\pi(x,a)$ 展开, 你会发现系数之和还是 $1$ , 只不过越往后系数越大, 也就是越靠后积累的奖赏越重要, 随着 $\alpha$ 不断增大, 这一特点也在不断扩大. <strong>总而言之, 时序差分学习与蒙特卡罗强化学习的区别就类似于策略迭代与值迭代的两个算法之间的区别.</strong></p><p>时序差分学习同样分为同策略与异策略, 与蒙特卡罗强化学习类似.</p><h1 id="值函数近似"><a href="#值函数近似" class="headerlink" title="值函数近似"></a>值函数近似</h1><p>值函数近似的过程其实就是回归. 用 $\boldsymbol{\theta}^{\mathrm{T}}\boldsymbol{x}$ 和 $\boldsymbol{\theta}^{\mathrm{T}}(\boldsymbol{x},a)$ 来近似 $V^\pi(\boldsymbol{x})$ 和 $Q^\pi(\boldsymbol{x},a)$ , 这样就能解决连续空间有无穷多状态的问题. 至于回归用的算法, 可以自己决定.</p><h1 id="模仿学习"><a href="#模仿学习" class="headerlink" title="模仿学习"></a>模仿学习</h1><h2 id="直接模仿学习"><a href="#直接模仿学习" class="headerlink" title="直接模仿学习"></a>直接模仿学习</h2><p>可以说就是 “预测” 人类专家的动作. 对于离散的动作, 使用的是分类, 对于连续的动作, 使用的是回归. 利用这样的方式学得人类专家的决策, 然后再通过强化学习进一步改进. 也就是 “监督学习” + “强化学习” = “直接模仿学习” .</p><h2 id="逆强化学习"><a href="#逆强化学习" class="headerlink" title="逆强化学习"></a>逆强化学习</h2><p>直接模仿学习是 “直接” 学习现有的范例, 然后根据已有的奖赏函数继续学习. 而逆强化学习的 “逆” 就体现在, 它根据现有的范例, <strong>反推出</strong>奖赏函数, 然后利用反推出的奖赏函数学习. 而反推出的奖赏函数要符合什么性质呢, 就是要保证在此奖赏函数下, 范例就是最优策略. 由于所有策略几乎不可能都尝试一遍, 因此往往采用迭代的方式, 先随机生成一个策略然后求取奖赏函数, 然后根据奖赏函数再求取策略, 如此反复直到策略和奖赏函数都符合范例.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 强化学习 </category>
          
          <category> 西瓜书 </category>
          
          <category> 入门 </category>
          
          <category> 读懂西瓜书 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 强化学习 </tag>
            
            <tag> 西瓜书 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>强迫症的 LaTeX</title>
      <link href="/scribble/obsessive_LaTeX/"/>
      <url>/scribble/obsessive_LaTeX/</url>
      
        <content type="html"><![CDATA[<p>这篇博文写了一些关于数学公式的规范. 为啥写这个呢, 因为规范了自己数学公式的写法, 才能更有效率的写数学公式. 当然这篇博文不会把所有标准都列出来, 只是强调一些比较小的点. <strong>当然这里所说全部都是 $\mathrm{Markdwon}$ 中的 $\LaTeX$ 公式, 也可以说成是 $\mathrm{MathJax}$ , 所以请大佬们轻喷.</strong></p><h1 id="积分"><a href="#积分" class="headerlink" title="积分"></a>积分</h1><p>正确的积分写法应该是</p><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">\int</span> f(x)<span class="keyword">\,</span><span class="keyword">\mathrm</span>&#123;d&#125;x</span><br></pre></td></tr></table></figure>$$\int f(x)\,\mathrm{d}x$$<p>即 $\mathrm{d}x$ 与被积函数之间要有一个小小的间隔 <code>\,</code> , 并且 $\mathrm{d}$ 要用正体.</p><h1 id="cdots-还是-ldots"><a href="#cdots-还是-ldots" class="headerlink" title="cdots 还是 ldots ?"></a>cdots 还是 ldots ?</h1><p>正确的用法是</p><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1+2+3+<span class="keyword">\cdots</span>+n</span><br></pre></td></tr></table></figure>$$1+2+3+\cdots+n$$<figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1,2,3,<span class="keyword">\ldots</span>,n</span><br></pre></td></tr></table></figure>$$1,2,3,\ldots,n$$<p>即省略号要和它们两边的符号等高. 不过还有一个方便的命令, 即 <code>\dots</code> , 它可以判断应该用哪个省略号.</p><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">1+2+3+<span class="keyword">\dots</span>+n<span class="keyword">\\</span><span class="keyword">\\</span></span><br><span class="line">1,2,3,<span class="keyword">\dots</span>,n</span><br></pre></td></tr></table></figure>$$1+2+3+\dots+n\\\\1,2,3,\dots,n$$<h1 id="正体"><a href="#正体" class="headerlink" title="正体"></a>正体</h1><p>常数 <code>\mathrm&#123;e&#125;</code> $\mathrm{e}$ , 虚数 <code>\mathrm&#123;i&#125;</code> $\mathrm{i}$ 都要用正体 (以前好像没注意) .</p><h1 id="大-O-符号"><a href="#大-O-符号" class="headerlink" title="大 O 符号"></a>大 O 符号</h1><p>这个似乎没有统一… 反正我用 <code>\mathcal&#123;O&#125;</code> $\mathcal{O}$ .</p><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">\mathcal</span>&#123;O&#125;(1),<span class="keyword">\mathcal</span>&#123;O&#125;(n),<span class="keyword">\mathcal</span>&#123;O&#125;(<span class="keyword">\log</span> n)</span><br></pre></td></tr></table></figure>$$\mathcal{O}(1),\mathcal{O}(n),\mathcal{O}(\log n)$$<h1 id="竖线"><a href="#竖线" class="headerlink" title="竖线"></a>竖线</h1><p>条件概率中的竖线要用 <code>\mid</code> 而不是 <code>|</code></p><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">p(x<span class="keyword">\mid</span><span class="keyword">\alpha</span>)</span><br></pre></td></tr></table></figure>$$p(x\mid\alpha)$$<figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">p(x|<span class="keyword">\alpha</span>)</span><br></pre></td></tr></table></figure>$$p(x|\alpha)$$<h1 id="文本"><a href="#文本" class="headerlink" title="文本"></a>文本</h1><p>文本要用 <code>\textrm</code> 来写, 加粗就用 <code>\textbf</code> (以前我傻乎乎的用 <code>\mathrm</code> 来写…)</p><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">\textrm</span>&#123;I am Cloud Player.&#125;<span class="keyword">\textbf</span>&#123;I am Cloud Player.&#125;</span><br></pre></td></tr></table></figure>$$\textrm{I am Cloud Player.}\textbf{I am Cloud Player.}$$<h1 id="冒号"><a href="#冒号" class="headerlink" title="冒号"></a>冒号</h1><p>当冒号做二元运算符时, 直接输入 <code>:</code> 就好了, 比如两个数的比值</p><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a:b=1:2</span><br></pre></td></tr></table></figure>$$a:b=1:2$$<p>而当其单纯做冒号时, 需要使用用 <code>\colon</code> , 比如直线</p><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">l<span class="keyword">\colon</span> x+y+1=0</span><br></pre></td></tr></table></figure>$$l\colon x+y+1=0$$<p>或者函数映射</p><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">f<span class="keyword">\colon</span> A<span class="keyword">\to</span> B</span><br></pre></td></tr></table></figure>$$f\colon A\to B$$<p>参考资料:</p><ul><li><a href="http://kuing.orzweb.net/archiver/?tid-3190.html">http://kuing.orzweb.net/archiver/?tid-3190.html</a></li></ul><h1 id="箭头"><a href="#箭头" class="headerlink" title="箭头"></a>箭头</h1><p>极限和映射里不要再傻傻的用 <code>\rightarrow</code> 了! 要用 <code>\to</code> .</p><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">\lim</span><span class="built_in">_</span>&#123;x<span class="keyword">\to</span> <span class="keyword">\infty</span>&#125;<span class="keyword">\sum</span><span class="built_in">_</span>&#123;i=0&#125;<span class="built_in">^</span>x <span class="keyword">\frac</span>&#123;1&#125;&#123;2<span class="built_in">^</span>i&#125; = 2<span class="keyword">\\</span><span class="keyword">\\</span></span><br><span class="line">f<span class="keyword">\colon</span> A<span class="keyword">\to</span> B</span><br></pre></td></tr></table></figure>$$\lim_{x\to \infty}\sum_{i=0}^x \frac{1}{2^i} = 2\\\\f\colon A\to B$$]]></content>
      
      
      <categories>
          
          <category> 杂文 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> LaTeX </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>LDA 详解</title>
      <link href="/ML/model/LDA/"/>
      <url>/ML/model/LDA/</url>
      
        <content type="html"><![CDATA[<h1 id="先验知识"><a href="#先验知识" class="headerlink" title="先验知识"></a>先验知识</h1><h2 id="Gamma-函数"><a href="#Gamma-函数" class="headerlink" title="Gamma 函数"></a>Gamma 函数</h2><ul><li><a href="https://yunist.cn/math/probability_theory/gamma/">Gamma 函数详解</a></li></ul><h2 id="Beta-Dirichlet-分布与共轭"><a href="#Beta-Dirichlet-分布与共轭" class="headerlink" title="Beta/Dirichlet 分布与共轭"></a>Beta/Dirichlet 分布与共轭</h2><ul><li><a href="https://yunist.cn/math/probability_theory/beta/">Beta 函数, Beta 分布详解</a></li></ul><h2 id="MCMC-吉布斯采样"><a href="#MCMC-吉布斯采样" class="headerlink" title="MCMC, 吉布斯采样"></a>MCMC, 吉布斯采样</h2><p>这块资料暂时自己去找, 等我有空写了 $\textrm{MCMC}$ 的教程再补上.</p><h1 id="LDA-介绍"><a href="#LDA-介绍" class="headerlink" title="LDA 介绍"></a>LDA 介绍</h1><h2 id="构成"><a href="#构成" class="headerlink" title="构成"></a>构成</h2><p>&nbsp;$\textrm{LDA (Latent Dirichlet Allocation)}$ 是一种词袋模型. 由<strong>语料</strong>, <strong>文档</strong>, <strong>话题</strong>. <strong>词</strong>, 这三个概念组成.</p><ul><li><p>语料</p><p>语料是文档的集合.</p></li><li><p>文档</p><p>文档是词的集合, 可以看做是一篇作文, 或是像这篇一样的博文, 反正就是一篇完整的文本.</p></li><li><p>话题</p><p>话题给出了某个词出现的概率. 到底是啥呢? $\textrm{LDA}$ 认为, 文档中每个词都应该有它的话题, 词是由话题来生成的. 比如说某个词的话题是 “概率论” , 那么这个词就很有可能是 “$\textrm{Gamma}$ 函数” , 而不太可能是 “吃饭” . “可能” 与 “不太可能” 在数学上用概率描述, 而话题就给出了这个概率的值. </p></li><li><p>词</p></li><li>这应该无需多解释, “词” 本身就是一个词. 文档是由一个个词组成的</li></ul><h2 id="生成文档过程"><a href="#生成文档过程" class="headerlink" title="生成文档过程"></a>生成文档过程</h2><p>生成文本的过程, 就像是上帝抛骰子. 关于这个骰子如何抛, 频率派与贝叶斯派有不同的解释, 而 $\textrm{LDA}$ 就是基于贝叶斯派的解释. </p><h3 id="频率派"><a href="#频率派" class="headerlink" title="频率派"></a>频率派</h3><p>频率派认为, 上帝有两种骰子, 一种是 $\textrm{doc-topic}$ 骰子, 它有 $K$ 个面, 每个面都是一个 $\textrm{topic}$ 的编号. 还有一种是 $\textrm{topic-word}$ 骰子, 一共有 $K$ 个, 正好对应 $\textrm{doc-topic}$ 的 $K$ 个面. 每个 $\textrm{topic-word}$ 骰子有 $V$ 个面, 每一个面都对应一个词. 生成文档包括两个过程:抛投  骰子, 得到一个  编号.</p><ol><li>抛投 $\textrm{doc-topic}$ 骰子, 得到一个 $\textrm{topic}$ 编号.</li><li>按照这个 $\textrm{topic}$ 编号, 找到对应的 $\textrm{topic-word}$ 骰子, 再次抛投, 生成一个词.</li></ol><p>假如说一个文档有 $N$ 个词, 那么以上过程就重复 $N$ 次, 这样就生成了这篇文档所有的词, 这篇文档也就生成完毕.</p><h3 id="贝叶斯派"><a href="#贝叶斯派" class="headerlink" title="贝叶斯派"></a>贝叶斯派</h3><p>对于这样的抛骰子过程, 贝叶斯派可就不满意了. 无论是 $\textrm{doc-topic}$ 骰子, 还是 $\textrm{topic-word}$ 骰子, 都是模型里的参数, 参数都是随机变量, 怎么能没有先验呢?</p><p>于是, 就有了两大缸骰子, 一缸装了 $\textrm{doc-topic}$ 骰子, 一缸装了 $\textrm{topic-word}$ 骰子, 相比频率派, 贝叶斯派多了 $1,2$ 两个过程.</p><ol><li>从 $\textrm{topic-word}$ 缸中取出 $K$ 个 $\textrm{topic-word}$ 骰子, 每个 $\textrm{topic-word}$ 骰子有 $V$ 个面, 每一个面都对应一个词.</li><li>从 $\textrm{doc-topic}$ 缸中取出一个 $\textrm{doc-topic}$ 骰子, 所有的 $\textrm{doc-topic}$ 骰子都只有 $K$ 个面.</li><li>抛投 $\textrm{doc-topic}$ 骰子, 得到一个 $\textrm{topic}$ 编号.</li><li>按照这个 $\textrm{topic}$ 编号, 找到对应的 $\textrm{topic-word}$ 骰子, 再次抛投, 生成一个词. 如果一篇文档所有的词没有生成完毕, 那么就跳到第 $3$ 点继续重复生成词.</li></ol><p>执行完这 $4\,$$ 个过程一篇文档就生成完成, 然后重新回到 $2\,$$ , 生成下一篇文档 (也就是说 $K\,$$ 个 $\textrm{topic-word}\,$$ 骰子不用重新抽取), 直到整个语料 (包含 $M\,$$ 篇文档) 生成完毕, 也就是重复 $M\,$$ 次. **每篇文档都是独立的, 每个词也是, 所以生成的过程可以互相交换.**## 目标&nbsp;$\textrm{LDA}$ 的目标就是给定文档 然后估计文档中每个词的 $\textrm{topic}$ , 以及估计出你取到的 $\textrm{doc-topic}$ 骰子与 $\textrm{topic-word}$ 骰子到底是长啥样 (每个面的概率) . 我们这里将某篇文档的 $\textrm{doc-topic}$ 骰子记为 $\vec{\theta}<em>m$ , 整个语料中的 $\textrm{doc-topic}$ 骰子记为 $\vec{\theta}_1,\dots,\vec{\theta}_M$ . $\vec\theta_m$ 向量的每个分量的值就是取到某个 $\textrm{topic}$ 编号的概率. 而 $K$ 个 $\textrm{topic-word}$ 骰子记为 $\vec\varphi_1, \vec\varphi_2,\dots,\vec\varphi_K$ . 我们的目的就是求出 $\varphi_1, \varphi_2,\dots,\varphi_K$ 与 $\vec{\theta}_1,\dots,\vec{\theta}_M$. 我们再将每篇文档中的词记为 $\vec{w}$ , 整个语料 $\mathcal{W}$ 包含 $M$ 篇文档记为 $\vec{\boldsymbol{\mathrm{w}}}=(\vec{w}_1,\dots\vec{w}_M)$ , 所有的 $\textrm{word}$ 对应的 $\textrm{topic}$ 记为 $\boldsymbol{\vec{\mathrm{z}}}=(\vec{z}_1,\dots\vec{z}_M)$ .## 先验分布由于 $\textrm{topic}$ 与 $\textrm{word}$ 的数量服从 $\textrm{Multinomial}$ 分布, 很自然就把骰子的分布设为与其共轭的 $\textrm{Dirichlet}$ 分布. 于是有$$p(\vec\theta_m\mid\vec{\alpha})=Dir(\vec\theta_m\mid \vec{\alpha})\\\\p(\vec\varphi_k\mid\vec{\beta})=Dir(\vec\varphi_k\mid\vec{\beta})\\\\p(\vec n_m\mid\vec\theta_m)= Mult(\vec n_m\mid\vec\theta_m)\\\\p(\vec n_k\mid\vec z_m,\varphi)=Mult(\vec n_k\mid \vec z_m,\varphi)$$其中 $\vec\alpha, \vec\beta$ 是 $\textrm{Dirichlet}$ 分布的参数, 求取前就已经确定, $\varphi=(\vec\varphi_1, \vec\varphi_2,\dots,\vec\varphi_K)$ , $N_m$ 是第 $m$ 篇文档中词的数量.  $\vec{n}_m=(\vec{n}_m^{(1)},\dots,\vec{n}_m^{(K)})$ , 它的分量 $\vec{n}_m^{(k)}$ 代表第 $m$ 篇文档中第 $k$ 个 $\textrm{topic}$ 产生的词的数量. $\vec{n}_k=(\vec{n}_k^{(1)},\dots,\vec{n}_k^{(V)})$ , $\vec n_k^{(v)}$ 表示第 $k$ 个 $\textrm{topic}$ 产生的词中 $\mathrm{word}\;v$ 的个数. 当然这里表述有点不严谨, 因为都用的是字母 $n$ , 只是根据下标区别.## 联合分布这里注意到, 整个 $\textrm{LDA}$ 过程就是 $(M+K)$ 个 $\textrm{Dirichlet-Multinomial}$ 共轭. $$p(\vec{\boldsymbol{\mathrm{w}}}, \boldsymbol{\vec{\mathrm{z}}}\mid\vec{\alpha},\vec{\beta})=p(\vec{\boldsymbol{\mathrm{w}}}\mid \boldsymbol{\vec{\mathrm{z}}},\vec{\beta})p(\boldsymbol{\vec{\mathrm{z}}}\mid \vec{\alpha})$$现在我们要分别求出 $p(\vec{\boldsymbol{\mathrm{w}}}\mid \boldsymbol{\vec{\mathrm{z}}},\vec{\beta})$ , 与 $p(\boldsymbol{\vec{\mathrm{z}}}\mid \vec{\alpha})$ .这里设. 那么有$$\begin{aligned}p(\boldsymbol{\vec{\mathrm{z}}}\mid \vec{\alpha})&=\prod_{m=1}^Mp(\vec{z}_m\mid\vec{\alpha})\\\\&=\prod_{m=1}^M\int p(\vec{z}_m\mid\vec{\theta}_m)p(\vec{\theta}_m\mid\vec{\alpha})\,\rm{d}\vec{\theta}_m\\\\&=\prod_{m=1}^M\int p(\vec{z}_m\mid\vec{\theta}_m) Dir(\vec\theta_m\mid \vec{\alpha})\,\rm{d}\vec{\theta}_m\\\\&=\prod_{m=1}^M\int \prod_{k=1}^K{\left(\vec{\theta}_m^{(k)}\right)}^{\vec{n}_m^{(k)}}\frac{1}{\Delta(\vec{\alpha})} \prod_{k=1}^K{\left(\vec{\theta}_m^{(k)}\right)}^{\alpha_v-1}\,\mathrm{d}\vec{\theta}_m\\\\&=\prod_{m=1}^M\frac{1}{\Delta(\vec{\alpha})}\int \prod_{k=1}^K{\left(\vec{\theta}_m^{(k)}\right)}^{\vec{n}_m^{(k)}+\alpha_v-1} \,\mathrm{d}\vec{\theta}_m\\\\&=\prod_{m=1}^M\frac{\Delta(\vec{n}_m+\vec{\alpha})}{\Delta(\vec{\alpha})}\end{aligned}$$上式已经给出了 $M$ 个 $\textrm{Dirichlet-Multinomial}$ 共轭. 其中 $\Delta(\vec\alpha)$ 是归一化因子, 也可以看做是高维的 $\textrm{Beta}$ 函数. (本来还想根据规律称其为狄利克雷函数, 但是这个名字已经被占用了) .$$\Delta(\vec\alpha)=\int\prod_{k=1}^K{\left(\vec{\theta}_m^{(k)}\right)}^{\alpha_k-1}\,\mathrm{d}\vec{\theta}_m$$还记得我上面提到的吗, 由于**每篇文档都是独立的, 每个词也是, 所以生成的过程可以互相交换.** 那么在每个词的 $\textrm{topic}$ (也就是 $\vec{\varphi}$ 与 $\vec{z}_m$) 已经生成的条件下, 可以将语料中的词进行交换, 将相同 $\textrm{topic}$ 的词放在一起生成$$\vec{\boldsymbol{\mathrm{w}}}'=(\vec{w}_{(1)},\dots\vec{w}_{(K)})\\\\\boldsymbol{\vec{\mathrm{z}}}'=(\vec{z}_{(1)},\dots\vec{z}_{(K)})$$因此有$$\begin{aligned}p(\vec{\boldsymbol{\mathrm{w}}}\mid \boldsymbol{\vec{\mathrm{z}}},\vec{\beta})&=p(\vec{\boldsymbol{\mathrm{w}}}'\mid \boldsymbol{\vec{\mathrm{z}}}',\vec{\beta})\\\\&=\prod_{k=1}^Kp(\vec{w}_{(k)}\mid\vec{z}_{(k)}, \vec\beta)\\\\&=\prod_{k=1}^K\int p(\vec w_{(k)}\mid\vec z_{(k)},\vec\varphi_k)p(\vec\varphi_k\mid\vec{\beta})\,\mathrm{d}\vec\varphi_k\\\\&=\prod_{k=1}^K\int \prod_{v=1}^V\left({\vec\varphi_k^{(v)}}\right)^{\vec n_k^{(v)}}\frac{1}{\Delta(\vec{\beta})}\prod_{v=1}^V\left({\vec\varphi_k^{(v)}}\right)^{\vec\beta_v-1}\,\mathrm{d}\vec\varphi_k\\\\&=\prod_{k=1}^K\frac{1}{\Delta(\vec{\beta})}\int \prod_{v=1}^V\left({\vec\varphi_k^{(v)}}\right)^{\vec n_k^{(v)}+\vec\beta_v-1}\,\mathrm{d}\vec\varphi_k\\\\&=\prod_{k=1}^K\frac{\Delta(\vec{n}_k+\vec{\beta})}{\Delta(\vec{\beta})}\end{aligned}$$&nbsp;$\Delta(\beta)\,$$ 同样是归一化因子$$<br>\Delta(\beta)=\int \prod</em>{v=1}^V\left({\vec\varphi<em>k^{(v)}}\right)^{\vec\beta_v-1}\,\mathrm{d}\vec\varphi_k<br>$$最终有$$<br>\begin{aligned}<br>p(\vec{\boldsymbol{\mathrm{w}}}, \boldsymbol{\vec{\mathrm{z}}}\mid\vec{\alpha},\vec{\beta})&amp;=p(\vec{\boldsymbol{\mathrm{w}}}\mid \boldsymbol{\vec{\mathrm{z}}},\vec{\beta})p(\boldsymbol{\vec{\mathrm{z}}}\mid \vec{\alpha})\\<br>&amp;=\prod</em>{k=1}^K\frac{\Delta(\vec{n}<em>k+\vec{\beta})}{\Delta(\vec{\beta})}\prod</em>{m=1}^M\frac{\Delta(\vec{n}<em>m+\vec{\alpha})}{\Delta(\vec{\alpha})}<br>\end{aligned}<br>$$多么简洁漂亮!## 吉布斯采样我们要估计的是 $p(\boldsymbol{\vec{\mathrm{z}}}\mid\vec{\boldsymbol{\mathrm{w}}})$ , 根据吉布斯采样的要求, 我们要求出 $p(z_i\mid\boldsymbol{\vec{\mathrm{z}}}</em>{-i},\vec{\boldsymbol{\mathrm{w}}})$ . $$p(z_i=k\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}})p(w_i=v\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})=p(z_i=k,w_i=v\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})$$注意到 $p(w<em>i=t\mid\boldsymbol{\vec{\mathrm{z}}}</em>{-i},\vec{\boldsymbol{\mathrm{w}}}<em>{-i})$ 与 $p(z_i=k\mid\boldsymbol{\vec{\mathrm{z}}}</em>{-i},\vec{\boldsymbol{\mathrm{w}}})$ 无关, 因此有$$p(z_i=k\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}})\propto p(z_i=k,w_i=v\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})$$那么就有$$\begin{aligned}p(z_i=k\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}})&\propto p(z_i=k,w_i=v\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})\\\\&=\left(\int p(z_i=k,\vec\theta_m\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})\,\mathrm{d}\vec\theta_m\right)\left(\int p(w_i=v,\vec{\varphi}_k\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})\,\mathrm{d\vec\varphi_k}\right)\\\\&=\left(\int p(z_i=k\mid\vec{\theta}_m)p(\vec\theta_m\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})\,\mathrm{d}\vec\theta_m\right)\left(\int p(w_i=v\mid \vec\varphi_k)p(\vec{\varphi}_k\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})\,\mathrm{d\vec\varphi_k}\right)\end{aligned}$$注意到 $p(\vec\theta<em>m\mid\boldsymbol{\vec{\mathrm{z}}}</em>{-i},\vec{\boldsymbol{\mathrm{w}}}<em>{-i})$ 是一个 $\textrm{Dirichlet-Multinomial}$ 共轭结构即$$Dir(\vec\theta_m\mid\vec\alpha)+Mult(\vec n_m\mid \vec\theta_m)=Dir(\vec\theta_m\mid\vec n_m+\vec\alpha)$$所以$$p(\vec\theta_m\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})=Dir(\vec\theta_m\mid\vec n_{m,-i}+\vec\alpha)$$&nbsp;$p(\vec{\varphi}_k\mid\boldsymbol{\vec{\mathrm{z}}}</em>{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})$ 也有类似的结论. 因此有$$\begin{aligned}p(z_i=k\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}})&\propto \left(\int p(z_i=k\mid\vec{\theta}_m)p(\vec\theta_m\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})\,\mathrm{d}\vec\theta_m\right)\left(\int p(w_i=v\mid \vec\varphi_k)p(\vec{\varphi}_k\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}}_{-i})\,\mathrm{d\vec\varphi_k}\right)\\\\&=\left(\int \theta_{mk} Dir(\vec\theta_m\mid\vec n_{m,-i}+\vec\alpha)\,\mathrm{d}\vec\theta_m\right)\left(\int \varphi_{kv}Dir(\vec\varphi_k\mid\vec n_{k,-i}+\vec\beta)\,\mathrm{d\vec\varphi_k}\right)\\\\&=E(\theta_{mk})E(\varphi_{kv})\\\\&=\hat{\theta}_{mk}\hat{\varphi}_{kv}\end{aligned}$$根据 $\textrm{Dirichlet}$ 分布的期望, 我们得到$$\hat{\theta}_{mk}=\frac{\vec{n}_{m,-i}^{(k)}+\alpha_k}{\sum_{k=1}^K(\vec{n}_{m,-i}^{(k)}+\alpha_k)}\\\\\hat{\varphi}_{kv}=\frac{\vec{n}_{k,-i}^{(v)}+\alpha_k}{\sum_{v=1}^V(\vec{n}_{k,-i}^{(v)}+\alpha_k)}$$因此$$p(z_i=k\mid\boldsymbol{\vec{\mathrm{z}}}_{-i},\vec{\boldsymbol{\mathrm{w}}})\propto\frac{\vec{n}_{m,-i}^{(k)}+\alpha_k}{\sum_{k=1}^K(\vec{n}_{m,-i}^{(k)}+\alpha_k)}\cdot\frac{\vec{n}_{k,-i}^{(v)}+\alpha_k}{\sum_{v=1}^V(\vec{n}_{k,-i}^{(v)}+\alpha_k)}$$通过吉布斯采样, 我们就可以估计出 $\varphi_1, \varphi_2,\dots,\varphi_K$ 与 $\vec{\theta}_1,\dots,\vec{\theta}_M$ 了.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 模型 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 机器学习 </tag>
            
            <tag> 概率图模型 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Valine 评论回复增强</title>
      <link href="/hexo/valine_admin/"/>
      <url>/hexo/valine_admin/</url>
      
        <content type="html"><![CDATA[<p>由于 Valine 本身的评论回复并不是很好用, 而且现在的版本甚至已经取消了评论回复的功能, 因此我们需要 Valine-Admin 来增强.</p><h1 id="部署"><a href="#部署" class="headerlink" title="部署"></a>部署</h1><p>首先我推荐使用国际版的 LeanCloud 而不是华东华北节点 (不用身份证绑定域名也不用备案啥的) , 将数据迁移到国际版可以用 LeanCloud 的数据导入导出功能实现, 不过要注意导出功能只能在中午 12 点前使用.</p><p>进入你原本的 Valine 评论的 LeanCloud 应用, 选择 <code>云引擎 -&gt; 部署 -&gt; 部署项目 -&gt; Git 源码部署 -&gt; 配置 Git</code> 中填入 <code>https://github.com/DesertsP/Valine-Admin.git</code> , 然后保存.</p><p><img src="1.png" alt=""></p><p><code>分支或提交</code> 填入 <code>master</code>  , 然后点击部署</p><p><img src="2.png" alt=""></p><p>第一次部署需要一点点时间.</p><h1 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h1><p>接下来就是配置了. 进入 <code>云引擎 -&gt; 设置</code> 界面配置环境变量.</p><p><img src="3.png" alt=""></p><div class="table-container"><table><thead><tr><th>变量</th><th>值</th><th>说明</th></tr></thead><tbody><tr><td>SITE_NAME</td><td></td><td>网站名称</td></tr><tr><td>SITE_URL</td><td></td><td>网站地址</td></tr><tr><td>SMTP_USER</td><td></td><td>SMTP 用户名 (一般为你的邮箱)</td></tr><tr><td>SMTP_PASS</td><td></td><td>授权码 (详情请看<a href="https://service.mail.qq.com/cgi-bin/help?subtype=1&amp;id=28&amp;no=1001256">获取授权码</a>)</td></tr><tr><td>SMTP_SERVICE</td><td>QQ</td><td>邮件服务提供商</td></tr><tr><td>SENDER_EMAIL</td><td></td><td>发件人邮箱</td></tr><tr><td>ADMIN_URL</td><td></td><td>Web 主机域名</td></tr><tr><td>SMTP_HOST</td><td>smtp.qq.com</td><td>SMTP 服务器地址</td></tr><tr><td>SMTP_SECURE</td><td>true</td><td>SMTP 安全验证</td></tr><tr><td>SMTP_PORT</td><td>465</td><td>SMTP 端口</td></tr><tr><td>MAIL_SUBJECT</td><td>\${PARENT\_NICK}，您在\${SITE_NAME}上的评论收到了回复</td><td>@通知邮件主题模板</td></tr><tr><td>MAIL_TEMPLATE</td><td></td><td>@通知邮件内容模板</td></tr><tr><td>MAIL_SUBJECT_ADMIN</td><td>\${SITE_NAME}上有新评论了</td><td>博主邮件通知主题模板</td></tr><tr><td>MAIL_TEMPLATE_ADMIN</td><td></td><td>博主邮件通知内容模板</td></tr><tr><td>BLOGGER_EMAIL</td><td></td><td>收件邮箱 (一般和发件邮箱一样)</td></tr></tbody></table></div><p><strong>其中</strong></p><ul><li><strong>MAIL_TEMPLATE:</strong></li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;div style=&quot;border-radius: 10px 10px 10px 10px;font-size:13px;    color: #555555;width: 666px;font-family:&#x27;Century Gothic&#x27;,&#x27;Trebuchet MS&#x27;,&#x27;Hiragino Sans GB&#x27;,微软雅黑,&#x27;Microsoft Yahei&#x27;,Tahoma,Helvetica,Arial,&#x27;SimSun&#x27;,sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);&quot;&gt;&lt;div style=&quot;width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;&quot;&gt;&lt;p style=&quot;font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;&quot;&gt;您在&lt;a style=&quot;text-decoration:none;color: #ffffff;&quot; href=&quot;${%endraw%}&#123;SITE_URL&#125;&quot;&gt; {%raw%}$&#123;SITE_NAME&#125;&lt;/a&gt;上的留言有新回复啦！&lt;/p&gt;&lt;/div&gt;&lt;div style=&quot;margin:40px auto;width:90%&quot;&gt;&lt;p&gt;${%endraw%}&#123;PARENT_NICK&#125; 同学，您曾在文章上发表评论：&lt;/p&gt;&lt;div style=&quot;background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;&quot;&gt;{%raw%}$&#123;PARENT_COMMENT&#125;&lt;/div&gt;&lt;p&gt;${%endraw%}&#123;NICK&#125; 给您的回复如下：&lt;/p&gt;&lt;div style=&quot;background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;&quot;&gt;{%raw%}$&#123;COMMENT&#125;&lt;/div&gt;&lt;p&gt;您可以点击&lt;a style=&quot;text-decoration:none; color:#12addb&quot; href=&quot;${%endraw%}&#123;POST_URL&#125;#comments&quot;&gt;查看回复的完整內容&lt;/a&gt;，欢迎再次光临&lt;a style=&quot;text-decoration:none; color:#12addb&quot;                href=&quot;{%raw%}$&#123;SITE_URL&#125;&quot;&gt; ${%endraw%}&#123;SITE_NAME&#125;&lt;/a&gt;。&lt;/p&gt;&lt;style type=&quot;text/css&quot;&gt;a:link&#123;text-decoration:none&#125;a:visited&#123;text-decoration:none&#125;a:hover&#123;text-decoration:none&#125;a:active&#123;text-decoration:none&#125;&lt;/style&gt;&lt;/div&gt;&lt;/div&gt;</span><br></pre></td></tr></table></figure><ul><li><strong>MAIL_TEMPLATE_ADMIN</strong></li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;div style=&quot;border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;&quot;&gt;&lt;h2 style=&quot;border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;&quot;&gt;您在&lt;a style=&quot;text-decoration:none;color: #12ADDB;&quot; href=&quot;{%raw%}$&#123;SITE_URL&#125;&quot; target=&quot;_blank&quot;&gt;${%endraw%}&#123;SITE_NAME&#125;&lt;/a&gt;上的文章有了新的评论&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;{%raw%}$&#123;NICK&#125;&lt;/strong&gt;回复说：&lt;/p&gt;&lt;div style=&quot;background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;&quot;&gt; ${%endraw%}&#123;COMMENT&#125;&lt;/div&gt;&lt;p&gt;您可以点击&lt;a style=&quot;text-decoration:none; color:#12addb&quot; href=&quot;$&#123;POST_URL&#125;&quot; target=&quot;_blank&quot;&gt;查看回复的完整內容&lt;/a&gt;&lt;br&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure><ul><li><strong>ADMIN_URL</strong></li></ul><p><img src="4.png" alt=""></p><p><code>ADMIN_URL</code> 填写 <code>设置</code> 下面的 <code>Web 主机域名</code> . 国际版可以自定义二级域名, 但是华东华北节点只能使用 LeanCloud 给你分配的二级域名, 当然都是可以绑定自己的域名的, 只是华东华北需要已备案的域名.  绑定域名选择云引擎域名.</p><h1 id="定时任务"><a href="#定时任务" class="headerlink" title="定时任务"></a>定时任务</h1><p>由于 LeanCloud 免费版会自休眠, 这会影响到邮件的发送, 于是要设置定时任务.</p><p><img src="5.png" alt=""></p><p>点击创建定时任务, 我们需要创建两个定时任务, 名字当然是自己填.</p><p>每天早上 8 点将没发出去的邮件补发:</p><ul><li><p>函数: resend_mails</p></li><li><p>Cron 表达式: 0 0 8 <em> </em> ?</p></li></ul><p>7-23 点, 每半小时自唤醒:</p><ul><li>函数: self_wake</li><li>Cron 表达式: 0 0/30 7-23 <em> </em> ?</li></ul><p><strong>如果你使用的是国际版, 由于时区的原因, 需要更改函数为.</strong></p><p>每天早上 8 点将没发出去的邮件补发:</p><ul><li>函数: resend_mails</li><li>Cron 表达式: <code>0 0 0 * * ?</code></li></ul><p>7-23 点, 每半小时自唤醒:</p><ul><li>函数: self_wake</li><li>Cron 表达式: <code>0 0/30 0-16 * * ?</code></li></ul><h1 id="评论后台"><a href="#评论后台" class="headerlink" title="评论后台"></a>评论后台</h1><p>进入你配置的 <code>ADMIN_URL/sign-up</code> 这个网址, 什么意思呢? 比如说你的 <code>ADMIN_URL</code> 是 <code>example.leanapp.cn</code> , 那么就访问 <code>example.leanapp.cn/sign-up</code> . 进入后注册管理员名字与密码, 然后会自动跳转到登陆, 然后输入刚刚注册的管理员邮箱 (管理员邮箱一般就是 <code>SMTP 用户名</code> ) 与密码就可以进入后台了.</p><p>如果没有注册界面直接就跳到登陆界面, 请手动删除 <code>存储 -&gt; 结构化数据 -&gt; _user</code> 中用户然后再试. 如果出现 <code>undefined is not a valid value</code> 报错那么应该是你的 <code>ADMIN_URL</code> 没有配置, 如果配置了还有这个问题, 尝试重启实例.</p><h1 id="报错解决"><a href="#报错解决" class="headerlink" title="报错解决"></a>报错解决</h1><h2 id="SMTP-邮箱配置异常"><a href="#SMTP-邮箱配置异常" class="headerlink" title="SMTP 邮箱配置异常"></a>SMTP 邮箱配置异常</h2><p>应该是授权码没有配置正确, 重新检查, 然后重启实例.</p><h2 id="undefined-is-not-a-valid-value"><a href="#undefined-is-not-a-valid-value" class="headerlink" title="undefined is not a valid value"></a>undefined is not a valid value</h2><p>应该是你的 <code>ADMIN_URL</code> 没有配置, 如果配置了还有这个问题, 尝试重启实例.</p>]]></content>
      
      
      <categories>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Hexo </tag>
            
            <tag> 教程 </tag>
            
            <tag> 搭建站点 </tag>
            
            <tag> 问题 </tag>
            
            <tag> Valine </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>解决 Hexo 本地搜索 search.xml 文件加载过慢</title>
      <link href="/hexo/local_search_speed_up/"/>
      <url>/hexo/local_search_speed_up/</url>
      
        <content type="html"><![CDATA[<h1 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h1><p>由于不想使用第三方, 我使用了本地搜索. 但是本地搜索带来的一个问题是, search.xml 太大了, 加载速度缓慢. 如果我们将 search.xml 文件使用外链引用 (例如用 Jsdelivr 加速过的链接) , 就可以解决这个问题.</p><h1 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h1><p>打开主题下的 <code>local-search.js</code> 文件 (不同主题的位置会不同, 但是一般都在 <code>source/js</code> 这种文件夹里) , 找到如下字段</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">url</span>: <span class="variable constant_">GLOBAL_CONFIG</span>.<span class="property">root</span> + path</span><br></pre></td></tr></table></figure><p>改成</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">url</span>: 外链</span><br></pre></td></tr></table></figure><p>外链推荐使用 Jsdelivr 的 cdn (引用 Github 的资源, 不需要手动更新, 速度也挺快) . 如果你的博客部署在 Github Pages, 那么就可以改成如下形式</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure><p>如果你还不知道什么是 Jsdelivr , 可以看我的<a href="https://yunist.cn/hexo/Hexo_blog_build/#Jsdelivr-%E5%8A%A0%E9%80%9F">这篇文章</a>. </p><p>换了外链后, 速度明显增加, 几乎是秒加载.</p>]]></content>
      
      
      <categories>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Hexo </tag>
            
            <tag> 搭建站点 </tag>
            
            <tag> 问题 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Butterfly 主题魔改记录</title>
      <link href="/hexo/butterfly_modify/"/>
      <url>/hexo/butterfly_modify/</url>
      
        <content type="html"><![CDATA[<p>记录下我对 Butterfly 主题的魔改, 一方面可供参考, 另一方面可以记录下自己的修改方便查找.</p><p><strong>本博客已开源! 请看 <a href="https://yunist.cn/hexo/hexo_modify_theme_butterfly/">Hexo modify theme butterfly</a>. 以下魔改部分集合到魔改主题, 部分已放弃 (不兼容或者其他原因). 如果更改失效, 可能是版本问题, 如果想要尽快使用这些魔改, 最便捷的方式是直接使用我的魔改主题. 魔改主题保留了所有原配置, 所有魔改配置均可关闭.</strong></p><h1 id="Mathjax-公式渲染去除滚动条"><a href="#Mathjax-公式渲染去除滚动条" class="headerlink" title="Mathjax 公式渲染去除滚动条"></a>Mathjax 公式渲染去除滚动条</h1><p>进入 <code>source/css/_layout/third-party.styl</code> , 找到如下内容</p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.has-jax</span></span><br><span class="line">  <span class="attribute">overflow</span>: auto</span><br></pre></td></tr></table></figure><p>改成</p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.has-jax</span></span><br><span class="line">  <span class="attribute">overflow</span>: visible</span><br></pre></td></tr></table></figure><h1 id="设置半透明"><a href="#设置半透明" class="headerlink" title="设置半透明"></a>设置半透明</h1><p>效果看我博客. </p><p>进入<code>source/css/_layout/page.styl</code> 文件, 找到以下内容</p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.layout_page</span></span><br><span class="line">  <span class="attribute">display</span>: flex</span><br><span class="line">  <span class="attribute">align-items</span>: flex-start</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span> auto</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">2rem</span> <span class="number">15px</span></span><br><span class="line">  <span class="attribute">max-width</span>: <span class="number">1200px</span></span><br></pre></td></tr></table></figure><p> 后面加上 <code>opacity:0.7</code> 改为</p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.layout_page</span></span><br><span class="line">  <span class="attribute">display</span>: flex</span><br><span class="line">  <span class="attribute">align-items</span>: flex-start</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span> auto</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">2rem</span> <span class="number">15px</span></span><br><span class="line">  <span class="attribute">max-width</span>: <span class="number">1200px</span></span><br><span class="line">  <span class="attribute">opacity</span>:<span class="number">0.7</span></span><br></pre></td></tr></table></figure><p>这里的 0.7 是透明度, 取值 0~1 , 越大越不透明, 越小越透明, 可以自己取值.</p><h1 id="post-文章侧边栏去掉滚动条"><a href="#post-文章侧边栏去掉滚动条" class="headerlink" title="post 文章侧边栏去掉滚动条"></a>post 文章侧边栏去掉滚动条</h1><p>文章有标题时, 左边就会出现侧边栏, 而侧边栏的滚动条实在是不太美观, 于是隐藏掉.</p><p>进入 <code>layout/includes/sidebar.pug</code> 看到以下内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">if (page.encrypt == true)</span><br><span class="line">  div.sidebar-toc__content.toc-div-class(style=&quot;display:none&quot;)!=toc(page.origin, &#123;list_number: tocNumber&#125;)</span><br><span class="line">else </span><br><span class="line">  div.sidebar-toc__content!=toc(page.content, &#123;list_number: tocNumber&#125;)</span><br></pre></td></tr></table></figure><p>只要为侧边栏加一个 <code>style=&quot;overflow: hidden;&quot;</code> 就能隐藏滚动条, 因此改为</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">if (page.encrypt == true)</span><br><span class="line">  div.sidebar-toc__content.toc-div-class(style=&quot;display:none&quot;)!=toc(page.origin, &#123;list_number: tocNumber&#125;)</span><br><span class="line">else </span><br><span class="line">  div.sidebar-toc__content(style=&quot;overflow: hidden;&quot;)!=toc(page.content, &#123;list_number: tocNumber&#125;)</span><br></pre></td></tr></table></figure><p>就好了.</p><h1 id="非-post-随机-banner-网页背景-页脚图片"><a href="#非-post-随机-banner-网页背景-页脚图片" class="headerlink" title="非 post 随机 banner , 网页背景, 页脚图片"></a>非 post 随机 banner , 网页背景, 页脚图片</h1><h2 id="页脚-banner-头图设置为透明"><a href="#页脚-banner-头图设置为透明" class="headerlink" title="页脚, banner 头图设置为透明"></a>页脚, banner 头图设置为透明</h2><h3 id="页脚"><a href="#页脚" class="headerlink" title="页脚"></a>页脚</h3><p>在 <code>butterfly/layout/includes/layout.pug</code> 下找到如下代码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">- var footer_bg = theme.footer_bg == false ? &#x27;&#x27; : bg_img</span><br></pre></td></tr></table></figure><p>在其下面追加变成</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">- var footer_bg = theme.footer_bg == false ? &#x27;&#x27; : bg_img</span><br><span class="line">if !is_post()</span><br><span class="line">  - var footer_bg = &#x27;background-color: transparent;&#x27;</span><br></pre></td></tr></table></figure><h3 id="banner-头图"><a href="#banner-头图" class="headerlink" title="banner 头图"></a>banner 头图</h3><p>在 <code>butterfly/layout/includes/header/index.pug</code> 下找到如下代码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">#nav(class=isHomeClass style=bg_img)</span><br></pre></td></tr></table></figure><p>在其上追加变成</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">if !is_post()</span><br><span class="line">  - var bg_img = &#x27;background-color:transparent;&#x27;</span><br><span class="line">#nav(class=isHomeClass style=bg_img)</span><br></pre></td></tr></table></figure><h2 id="随机背景设置"><a href="#随机背景设置" class="headerlink" title="随机背景设置"></a>随机背景设置</h2><p>在 <code>butterfly/layout/includes/layout.pug</code> 下找到如下代码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">if theme.background</span><br><span class="line">  - var is_photo = theme.background.substring(3,0) === &#x27;url&#x27; ? &#x27;photo&#x27;:&#x27;color&#x27;</span><br></pre></td></tr></table></figure><p>改为</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">- var is_photo = &#x27;photo&#x27;</span><br></pre></td></tr></table></figure><p>(对, 就是直接替换, 注意位置要一样, 当然你也可以把原来的代码注释掉)</p><p>然后在 <code>butterfly/layout/includes/layout.pug</code> 下找到如下代码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">footer#footer(style=footer_bg data-type=is_bg)</span><br><span class="line">  !=partial(&#x27;includes/footer&#x27;, &#123;&#125;, &#123;cache:theme.fragment_cache&#125;)</span><br></pre></td></tr></table></figure><p>在其下追加变成</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">footer#footer(style=footer_bg data-type=is_bg)</span><br><span class="line">  !=partial(&#x27;includes/footer&#x27;, &#123;&#125;, &#123;cache:theme.fragment_cache&#125;)</span><br><span class="line">if !is_post()</span><br><span class="line">  script() var bg_index = Math.floor(Math.random() * #&#123;theme.bg_num&#125;);var res = &#x27;background-image: url(&quot;https://cdn.jsdelivr.net/gh/cnyist/banner/&#x27; + bg_index + &#x27;-min.jpg&quot;); background-attachment: fixed;&#x27;;document.getElementById(&#x27;web_bg&#x27;).style = res</span><br></pre></td></tr></table></figure><p>同时在 <code>butterfly/_config.yml</code> 里添加以下内容</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># banner图数量</span></span><br><span class="line"><span class="attr">bg_num:</span> <span class="number">48</span></span><br></pre></td></tr></table></figure><p>当然这只是使用我的 banner 图片, 如果要用你自己的, 还需要相应的更改, 这需要图片的 url 符合一定的格式, 即</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">前缀 + [从 0 开始递增序号] + 后缀</span><br></pre></td></tr></table></figure><p>然后将内容改成</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">footer#footer(style=footer_bg data-type=is_bg)</span><br><span class="line">  !=partial(&#x27;includes/footer&#x27;, &#123;&#125;, &#123;cache:theme.fragment_cache&#125;)</span><br><span class="line">if !is_post()</span><br><span class="line">  script() var bg_index = Math.floor(Math.random() * #&#123;theme.bg_num&#125;);var res = &#x27;background-image: url(&quot;前缀&#x27; + bg_index + &#x27;后缀&quot;); background-attachment: fixed;&#x27;;document.getElementById(&#x27;web_bg&#x27;).style = res</span><br></pre></td></tr></table></figure><p>同时将 <code>_config.yml</code> 刚刚添加的配置设置为你的 banner 图数量.</p><p>举个例子, 我的 banner 图 url 就是</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">前缀 + [从 0 开始递增序号] + -min.jpg</span><br></pre></td></tr></table></figure><p>其中某个 banner 图就是</p><p><a href="https://cdn.jsdelivr.net/gh/cnyist/banner/3-min.jpg">https://cdn.jsdelivr.net/gh/cnyist/banner/3-min.jpg</a></p><p>其中 <code>https://cdn.jsdelivr.net/gh/cnyist/banner/</code> 就是我图片的 url 的前缀, <code>3</code> 即是 [从 0 开始递增序号] (也就是说还有 0, 1, 2…) , <code>-min.jpg</code> 是图片 url 的后缀.</p><p>只要你的图片的 url 由这三个部分组成, 那么就可以将前缀和后缀填入代码中, 这样就可以实现使用自己的 banner 了.</p><h1 id="footer-动态颜色"><a href="#footer-动态颜色" class="headerlink" title="footer 动态颜色"></a>footer 动态颜色</h1><p>这里只设置 post 文章中的 (避免与 page 的魔改冲突).</p><p>打开 <code>layout/includes/head.pug</code> , 添加以下内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">if is_post()</span><br><span class="line">  link(rel=&#x27;stylesheet&#x27;, href=&quot;footer.min.css&quot;)</span><br></pre></td></tr></table></figure><p>就好了.</p><h1 id="黑暗模式下-nav-处黑色浮块消除"><a href="#黑暗模式下-nav-处黑色浮块消除" class="headerlink" title="黑暗模式下 nav 处黑色浮块消除"></a>黑暗模式下 nav 处黑色浮块消除</h1><p>打开 <code>source/css/_mode/darkmode.styl</code> 找到如下字段</p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-id">#nav</span></span><br><span class="line">  <span class="selector-pseudo">&amp;:before</span></span><br><span class="line">    <span class="attribute">position</span>: absolute</span><br><span class="line">    <span class="attribute">top</span>: <span class="number">0</span></span><br><span class="line">    <span class="attribute">right</span>: <span class="number">0</span></span><br><span class="line">    <span class="attribute">bottom</span>: <span class="number">0</span></span><br><span class="line">    <span class="attribute">left</span>: <span class="number">0</span></span><br><span class="line">    <span class="attribute">background-color</span>: alpha(<span class="variable">$dark</span>-black, .<span class="number">7</span>)</span><br><span class="line">    <span class="attribute">content</span>: <span class="string">&#x27;&#x27;</span></span><br></pre></td></tr></table></figure><p>去掉 <code>background-color</code> 改为</p><figure class="highlight styl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-id">#nav</span></span><br><span class="line">  <span class="selector-pseudo">&amp;:before</span></span><br><span class="line">    <span class="attribute">position</span>: absolute</span><br><span class="line">    <span class="attribute">top</span>: <span class="number">0</span></span><br><span class="line">    <span class="attribute">right</span>: <span class="number">0</span></span><br><span class="line">    <span class="attribute">bottom</span>: <span class="number">0</span></span><br><span class="line">    <span class="attribute">left</span>: <span class="number">0</span></span><br><span class="line">    <span class="attribute">content</span>: <span class="string">&#x27;&#x27;</span></span><br></pre></td></tr></table></figure><h2 id="随机-banner"><a href="#随机-banner" class="headerlink" title="随机 banner"></a>随机 banner</h2><p>Butterfly 主题的 banner 大图一个页面是只有一张的, 并且主题配置里也没有多张的设置, 因此如果你想要实现 banner 能够随机显示, 那么就需要魔改主题.</p><h2 id="2-1-0"><a href="#2-1-0" class="headerlink" title="2.1.0"></a>2.1.0</h2><p>在 <code>Butterfly/layout/includes/nav.pug</code> 文件中添加以下内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">script document.getElementById(&quot;nav&quot;).style = &#x27;background-image: url(&quot;&#x27; + Math.floor(Math.random()*9) + &#x27;.jpg&quot;); background-attachment: fixed;&#x27;</span><br></pre></td></tr></table></figure><p>在以上的代码中需要将 <code>cnyist</code> 换成你自己的 github 用户名 (如果你是部署在 github 上的话). 其原理就是利用 js 生成 0-8 的随机数, 然后修改 banner 图.</p><p>当然仅仅加这段代码是没有用的, 还要在 <code>Butterfly/source/img/banner/</code> 下 (没有文件夹就自己创建) 放你自己想用的 banner 大图, 名字限定在 [0-8].jpg. 如果要增加 banner 图片的话名字就继续递增, 同时上面的代码中的 <code>9</code> 改成你的 banner 图数量. 当然如果数量不足 9 张, 那么同样也要改成你的 banner 图数量.</p><p>这段代码还会把文章的 banner 也变为随机 banner 而不是 cover, 于是如果想要文章的 banner 还是原来的图的话, 那就再加一个条件判断.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">if !is_post()</span><br><span class="line">  script document.getElementById(&quot;nav&quot;).style = &#x27;background-image: url(&quot;&#x27; + Math.floor(Math.random()*9) + &#x27;.jpg&quot;); background-attachment: fixed;&#x27;</span><br></pre></td></tr></table></figure><h2 id="2-2-5"><a href="#2-2-5" class="headerlink" title="2.2.5"></a>2.2.5</h2><p>升级到 2.2.5 版本后, 发现原来的随机 banner 效果居然失效了! 然后查看源码才发现 <code>nav.png</code> 这个文件似乎被作者抛弃了, 将 banner 图的功能放在了 <code>Butterfly/layout/includes/header/index.pug</code> 里. 因此只要把以上代码放进这个文件里就行了, 代码的说明和上面是一样的, 至于 <code>nav.pug</code> 里的内容改不改都一样的.</p>]]></content>
      
      
      <categories>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Hexo </tag>
            
            <tag> 搭建站点 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Beta 函数, Beta 分布详解</title>
      <link href="/math/probability_theory/beta/"/>
      <url>/math/probability_theory/beta/</url>
      
        <content type="html"><![CDATA[<h1 id="推导"><a href="#推导" class="headerlink" title="推导"></a>推导</h1><h2 id="第一种"><a href="#第一种" class="headerlink" title="第一种"></a>第一种</h2><p>&nbsp;$\mathrm{Beta}$ 分布一般被用于建模<strong>伯努利试验事件成功的概率</strong>的概率分布. 什么叫做<strong>伯努利试验事件成功的概率</strong>? 我们来举个例子.</p><blockquote><p>如果有一枚硬币, 分为正反两面 (不一定均匀) , 那么假设你抛了 $10$ 次, 正面有 $7$ 次, 那么抛这枚硬币是正面的概率是多少呢? 当然我们一般会说是 $7/10$ , 但这只是最好的估计. 可能是 $1/10$ 吗? 当然可能, 但是可能性不高. 这里的 $7/10$ , $1/10$ 就是所谓<strong>伯努利试验事件成功的概率</strong>. 而其服从的分布就是<strong>伯努利试验事件成功的概率</strong>的概率分布.</p></blockquote><p>二项分布相信大家高中就都已经接触过了<br>$$P(x) = \binom{n}{x}q^x(1-q)^{n-x}$$<br>这是已知参数 $n, q$ 来估计 $x$ , 我们同样可以将其等价地写为 $P(x\mid  q)$ . 那如果我们知道了 $n,x$ , 要如何估计 $q$ 呢? 也就是如何求出 $P(q\mid x)$ (省略了 $n$ 是为了方便写公式, 毕竟两个条件概率都是已知 $n$ 的) .</p><p>根据贝叶斯公式, 我们有<br>$$P(q\mid x) = \frac{P(x\mid q)P(q)}{P(x)}$$<br>其中 $P(x)$ 是常量 (因为我们已知 $x$ ) . 而 $P(q)$ 是多少呢? $P(q)$ 被称为先验分布, 在我们对某一随机变量一无所知的时候, 一般可以认为它服从均匀分布. 那么, 就有<br>$$p(q\mid x)\propto P(q\mid x)\propto P(x\mid q)\propto q^x(1-q)^{n-x}$$<br>其中 $p(q\mid x)$ 为随机变量 $Q$ 的概率密度函数, 概率密度函数需要满足在定义域内积分为 $1$ . 我们乘上常数 $k$​ , 使其满足这个性质.</p>$$p(q\mid x) = kq^x(1-q)^{n-x}$$$$\begin{aligned}\int_0^1kq^x(1-q)^{n-x}\,\mathrm{d}q = k\int_0^1q^x(1-q)^{n-x}\,\mathrm{d}q &= 1\\\\k&=\frac{1}{\int_0^1q^x(1-q)^{n-x}\,\mathrm{d}q}\end{aligned}$$<p>记 $x = a, n-x=b, B(a+1,b+1)=k^{-1}$ , 也就是说<br>$$B(a,b) = \int_0^1q^{a-1}(1-q)^{b-1}\,\mathrm{d}q$$<br>这个 $B(a,b)$ 即为 $\mathrm{Beta}$ 函数, 这即是 $\mathrm{Beta}$ 函数的由来. 而 $\mathrm{Beta}$ 分布的概率密度函数则为<br>$$f(q)=\frac{1}{B(a,b)}q^{a-1}(1-q)^{b-1}$$</p><h2 id="第二种"><a href="#第二种" class="headerlink" title="第二种"></a>第二种</h2><p>假设你和我玩一个游戏, 我说</p><blockquote><p>我有一个魔盒, 上面有一个按钮. 我每按下一次按钮, 就会均匀的产生一个 $[0,1]$ 之间的随机数. 现在我连按 $10$ 次, 那么你猜猜, 第 $7$ 大的数字是多少? 误差不超过 $0.01$ 就算赢.</p></blockquote><p>用数学语言来描述就是</p><ul><li>$X_1,X_2\cdots, X_n\mathop{\sim}\limits^{\mathrm{iid}}Uniform(0,1),$</li><li>把这 $n$ 个随机变量排序后得到顺序统计量 $X_{(1)},X_{(2)},\cdots,X_{(n)},$</li><li>问 $X_{(k)}$ 的分布是什么</li></ul><p>对上面的游戏而言, $n=10,k=7$ . 如果我们求出了 $X_{(7)}$ 的分布, 那么用概率密度的极值点去猜测是最好的策略. </p><p>我们尝试计算 $X_{(k)}$ 落在区间 $[x,x+\Delta x]$ 的概率 $P(x<X_{(k)}<x+\Delta x)$.</p><p> 把 $[0,1]$ 区间分为 $3$ 段, 即 $[0,x),[x,x+\Delta x],(x+\Delta x,1]$ . 假设 $X_{(k)}$ 在区间 $[x,x+\Delta x]$ 中, 我们先考虑一个简单情形:</p><ul><li>$[x, x+\Delta x]$ 中只有一个点</li></ul><p>不失一般性, 我们先考虑一个符合上述要求的事件 $E$ .<br>$$\begin{aligned}E=\{&X_1\in[x,x+\Delta x],\\\\&X_i\in[0,x)\;\;\;\;(j=2,\cdots,k),\\\\&X_j\in(x+\Delta x,1]\;\;\;\;(i=k+1,\cdots,n)\}\end{aligned}$$</p><p><img src="2.jpg" alt=""></p><p>则有<br>$$\begin{aligned}P(E)&=\prod_{i=0}^nP(X_i)\\\\&=x^{k-1}(1-x-\Delta x)^{n-k}\Delta x\\\\&=x^{k-1}(1-x)^{n-k}\Delta x+o(\Delta x)\end{aligned}$$<br>其中 $o(\Delta x)$ 表示 $\Delta x$ 的高阶无穷小. 我们来计算一下与 $E$ 事件等价的事件有多少个. 首先, 在 $[x,x+\Delta x]$ 中的数一共有 $n$ 种取法, 然后在 $[0, x)$ 中的数有 $\binom{n-1}{k-1}$ 种取法, 而一旦给定前面的数所在的区间, $(x+\Delta x,1]$ 区间中的数也就给定. 于是一共有 $n\binom{n-1}{k-1}$ 种情况.</p><ul><li>$[x, x+\Delta x]$ 中有两个点</li></ul>$$\begin{aligned}E'=\{&X_1,X_2\in[x,x+\Delta x],\\\\&X_i\in[0,x)\;\;\;\;(j=3,\cdots,k),\\\\&X_j\in(x+\Delta x,1]\;\;\;\;(i=k+1,\cdots,n)\}\end{aligned}$$<p><img src="3.jpg" alt=""></p><p>那么就有<br>$$\begin{aligned}P(E')&=\prod_{i=0}^nP(X_i)\\\\&=x^{k-2}(1-x-\Delta x)^{n-k}(\Delta x)^2\\\\&=o(\Delta x)\end{aligned}$$</p><p>也就是说, 在 $[x, x+\Delta x]$ 中的数字超过 $1$ 个, 那么概率就是 $o(\Delta x)$ . </p><p>因此 $X_{(k)}$ 的概率密度函数为<br>$$\begin{aligned}f(x) &= \lim_{\Delta x\rightarrow0}\frac{P(x<X_{(k)}<x+\Delta x)}{\Delta x}\\\\&=n\binom{n-1}{k-1}x^{k-1}(1-x)^{n-k}\\\\&=\frac{n!}{(k-1)!(n-k)!}x^{k-1}(1-x)^{n-k}\\\\&=\frac{\Gamma(n+1)}{\Gamma(k)\Gamma(n-k+1)}x^{k-1}(1-x)^{n-k}\end{aligned}$$<br>令 $k=a,n-k+1=b$ , 上式可写为<br>$$f(x) = \frac{\Gamma(a+b)}{\Gamma(a)\Gamma(b)}x^{a-1}(1-x)^{b-1}$$<br>下面我们会证明 $B(a,b)=\frac{\Gamma(a)\Gamma(b)}{\Gamma(a+b)}$ , 也就是说<br>$$f(x)=\frac{1}{B(a,b)}x^{a-1}(1-x)^{b-1}$$<br>&nbsp;$\frac{1}{B(a,b)}x^{a-1}(1-x)^{b-1}$ 即为 $Beta$ 分布的概率密度函数.</p><p>看起来完全不同的两种问题, 居然能推导出完全相同的式子!</p><h1 id="Beta-函数与-Gamma-函数的关系"><a href="#Beta-函数与-Gamma-函数的关系" class="headerlink" title="Beta 函数与 Gamma 函数的关系"></a>Beta 函数与 Gamma 函数的关系</h1><p><img src="1.png" alt=""></p><p>假设向长度为 $1$ 的桌面丢一颗红球, 设红球与桌面最左边的距离为 $x$ , 那么随意再丢一颗白球, 在红球左边的概率为 $x$ . 那么丢 $n$ 次白球, 其中再红球左边的次数为 $k$ 次, 那么随机变量 $K$ 显然服从参数为 $n, x$ 的二项分布. 即 $K\sim Binomial(n,x)$ . 那么有<br>$$P(K=k\mid x)=\binom{n}{k}x^k(1-x)^{n-k}$$<br>根据贝叶斯公式, 有<br>$$P(K=k,x) = P(K=k\mid x)P(x)$$<br>由于 $P(x)$ 是均匀分布. 那么求边缘概率有<br>$$\begin{aligned}P(K=k) &= \sum_{x}P(K=k\mid x)P(x)\\\\&=\int_0^1\binom{n}{k}x^k(1-x)^{n-k}\,\mathrm{d}x\\\\&=\binom{n}{k}\int_0^1x^k(1-x)^{n-k}\,\mathrm{d}x\end{aligned}$$<br>现在我们换一种方式丢球, 等价的求出 $P(K=k)$ . 先把 $n+1$ 个球全部丢出, 然后任选一个球为红球, 那么此时任意一个球被选到的概率都是 $1/(n+1)$ 因此其左边球的数量为 $n$ 的概率也都为 $1/(n+1)$ (每颗球的左边球数量都不同, 而且数量范围在 $0\sim n$ ) . 因此我们有<br>$$\begin{aligned}\binom{n}{k}\int_0^1x^k(1-x)^{n-k}\,\mathrm{d}x&=\frac{1}{n+1}\\\\\int_0^1x^k(1-x)^{n-k}\,\mathrm{d}x&=\frac{k!(n-k)!}{(n+1)!}\end{aligned}$$<br>令 $k=a-1,n-k=b-1$, 根据 $\mathrm{Gamma}$ 函数的定义, 有<br>$$\begin{aligned}\int_0^1x^{a-1}(1-x)^{b-1}\,\mathrm{d}x&=\frac{(a-1)!(b-1)!}{(a+b-1)!}\\\\B(a,b)&=\frac{\Gamma(a)\Gamma(b)}{\Gamma(a+b)}\end{aligned}$$</p><hr><h1 id="Beta-Binomial-共轭"><a href="#Beta-Binomial-共轭" class="headerlink" title="Beta-Binomial 共轭"></a>Beta-Binomial 共轭</h1><p>还记得上面的游戏吗? 为了降低难度, 我又说:</p><blockquote><p>我再次按下 $5$ 次按钮, 然后得到 $5$ 个 $[0,1]$ 之间的随机数, 然后我会告诉你这 $5$ 个数与之前第 $7$ 大的数字相比, 谁大谁小, 然后你继续猜第 $7$ 大的数字是多少.</p></blockquote><p>假设这 $5$ 个数有 $3$ 个大于第 $7$ 大的数字, $2$ 个小于.</p><p>实际上, 这个 “降低难度” 的游戏其实是同一个游戏, 把它重新表达一下, 其实和下面这个游戏是等价的:</p><blockquote><p>我有一个魔盒, 上面有一个按钮. 我每按下一次按钮, 就会均匀的产生一个 $[0,1]$ 之间的随机数. 现在我连按 $10+5$ 次, 那么你猜猜, 第 $7+2$ 大的数字是多少? 误差不超过 $0.01$ 就算赢.</p></blockquote><p>也就是说, 本来 $X_{(7)}$ 的分布是 $Beta(7,10-7+1)$ . 给定另外的数据 $M_1\sim B(5,X_{(7)}),M_2=5-M_1$  (二项分布, $M_1$ 是小于第 $7$ 大数字的个数, $M_2$ 是大于), 那么 $X_{(7)}$ 的分布就会变成 $Beta(7+M_1,10-7+1+M_2)$ .</p><p>推广至一般情况, 即</p><ul><li>$X_1,X_2,\cdots,X_n\mathop\sim\limits^{\mathrm{iid}}Uniform(0,1)$ , 排序后对应的顺序统计量为 $X_{(1)}, X_{(2)},\cdots,X_{(n)}$ ,</li><li>$Y_1,Y_2,\cdots,Y_m\mathop\sim\limits^{\mathrm{iid}}Uniform(0,1)$ , 且有 $m_1$ 个比 $X_{(k)}$ 大, $m_2$ 个比 $X_{(k)}$ 小,</li><li>$p = X_{(k)}$ , 求 $P(p\mid Y_1,Y_2,\cdots,Y_m)$ 的分布</li></ul><p>贝叶斯参数估计的基本过程是<br>$$先验分布+数据的知识=后验分布$$<br>上面第一点其实就是先验分布即 $Beta(p\mid k,n-k+1)$ , 第二点就是数据的知识 $m_1,m_2$ ,第三点就是后验分布即 $Beta(p\mid k+m_1,n-k+1+m_2)$ .</p><p>合起来就是<br>$$Beta(p\mid k,n-k+1)+BinomCount(m_1,m_2)=Beta(p\mid k+m_1,n-k+1+m_2)$$<br>同样我们可以写为<br>$$Beta(p\mid a,b)+BinomCount(m_1,m_2)=Beta(p\mid a+m_1,b+m_2)$$<br>这就是所谓 $\textbf{Beta-Binomial}$ <strong>共轭</strong> .</p><h1 id="Dirichlet-分布"><a href="#Dirichlet-分布" class="headerlink" title="Dirichlet 分布"></a>Dirichlet 分布</h1><p>&nbsp;$\mathrm{Dirichlet}$ 分布其实就是多维的 $\mathrm{Beta}$ 分布. 继续上面的游戏, 我可以说:</p><blockquote><p>我再按 $20$ 次按钮, 那么你猜猜, 第 $7$ 大的数字和第 $14$ 大的数字分别是多少? </p></blockquote><p>按照上面的方式, 转换为数学语言即</p><ul><li>$X_1,X_2\cdots, X_n\mathop{\sim}\limits^{\mathrm{iid}}Uniform(0,1),$</li><li>把这 $n$ 个随机变量排序后得到顺序统计量 $X_{(1)},X_{(2)},\cdots,X_{(n)},$</li><li>问 $X_{(k_1)}$ 与 $X_{(k_1+k_2)}$ 的联合分布是什么</li></ul><p><img src="4.jpg" alt=""></p><p>同样推导过程, 有<br>$$\begin{aligned}&\,\;\;\;\;P\Big(X_{(k1)}\in (x_1,x_1+\Delta x),X_{(k_1+k_2)}\in(x_2, x_2+\Delta x)\Big)\\\\&=n(n-1)\binom{n-2}{k_1-1,k_2-1}{x_1}^{k_1-1}{x_2}^{k_2-1}{x_3}^{n-k_2-k_1}(\Delta x)^2\\\\&=\frac{n!}{(k_1-1)!(k_2-1)!(n-k_1-k_2)!}{x_1}^{k_1-1}{x_2}^{k_2-1}{x_3}^{n-k_2-k_1}(\Delta x)^2\\\\&=\frac{\Gamma (n+1)}{\Gamma (k_1)\Gamma (k_2)\Gamma (n-k_1-k_2+1)}{x_1}^{k_1-1}{x_2}^{k_2-1}{x_3}^{n-k_2-k_1}(\Delta x)^2\end{aligned}$$<br>因此 $X_{(k_1)}$ 与 $X_{(k_1+k_2)}$ 的联合分布为<br>$$f(x_1,x_2,x_3)=\frac{\Gamma (n+1)}{\Gamma (k_1)\Gamma (k_2)\Gamma (n-k_1-k_2+1)}{x_1}^{k_1-1}{x_2}^{k_2-1}{x_3}^{n-k_2-k_1}$$</p><p><strong>这里其实只有两个变量即 $x_1, x_2$ , 而 $x_3 = 1-x_1-x_2$ , 写成三个变量的形式只是为了对称.</strong></p><p>令 $k_1=\alpha_1,k_2=\alpha_2,n-k_1-k_2+1=\alpha_3$ 有<br>$$f(x_1,x_2,x_3)=\frac{\Gamma (\alpha_1+\alpha_2+\alpha_3)}{\Gamma (\alpha_1)\Gamma (\alpha_2)\Gamma (\alpha_3)}{x_1}^{\alpha_1-1}{x_2}^{\alpha_2-1}{x_3}^{\alpha_3-1}$$</p><h1 id="Dirichlet-Multinomial-共轭"><a href="#Dirichlet-Multinomial-共轭" class="headerlink" title="Dirichlet-Multinomial 共轭"></a>Dirichlet-Multinomial 共轭</h1><p>同样的推导, 这里就不细说了, 结果就是<br>$$Dir(\vec p\mid \vec k) + MultCount(\vec m)=Dir(\vec p\mid \vec k+\vec m)$$<br>其中 $\vec p=(p_1,p_2,p_3),p_3=1-p_1-p_2$ (同样为了更对称) .</p><p>当然, 我们还可以继续提高维度, 得到更高维的 $\mathrm{Dirichlet}$ 分布以及 $\mathrm{Dirichlet-Multinomial}$ 共轭.  一般形式的 $\mathrm{Dirichlet}$ 分布定义如下<br>$$Dir(\vec p\mid\vec \alpha)=\frac{\Gamma(\sum_{k=1}^K \alpha_k)}{\sum_{k=1}^K\Gamma(\alpha_k)}\prod_{k=1}^K{p_k}^{\alpha_k-1}$$<br>多项分布定义为<br>$$Mult(\vec n\mid \vec p,N)=\binom{N}{\vec n}\prod_{k=1}^K{p_k}^{n_k}$$<br>这两个分布是共轭关系.</p><h1 id="Deta-Dirichlet-分布的期望"><a href="#Deta-Dirichlet-分布的期望" class="headerlink" title="Deta, Dirichlet 分布的期望"></a>Deta, Dirichlet 分布的期望</h1><p>如果 $p\sim Beta(t\mid \alpha, \beta)$ , 则<br>$$\begin{aligned}E(p)&=\int_0^1t\cdot \frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)}t^{\alpha-1}(1-t)^{\beta-1}\,\mathrm{d}t\\\\&=\frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)}\int_0^1t^{\alpha}(1-t)^{\beta-1}\,\mathrm{d}t\\\\\end{aligned}$$<br>而<br>$$\int_0^1Beta(t\mid \alpha+1,\beta)=\int_0^1\frac{\Gamma(\alpha+\beta+1)}{\Gamma(\alpha+1)\Gamma(\beta)}t^{\alpha}(1-t)^{\beta-1}\,\mathrm{d}t=\frac{\Gamma(\alpha+\beta+1)}{\Gamma(\alpha+1)\Gamma(\beta)}\int_0^1t^{\alpha}(1-t)^{\beta-1}\,\mathrm{d}t=1$$<br>于是<br>$$\begin{aligned}E(p)&=\frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)}\int_0^1t^{\alpha}(1-t)^{\beta-1}\,\mathrm{d}t\\\\&=\frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)}\frac{\Gamma(\alpha+1)\Gamma(\beta)}{\Gamma(\alpha+\beta+1)}\\\\&=\frac{\alpha}{\alpha+\beta}\end{aligned}$$<br>对于 $\mathrm{Beta}$ 分布的多维形式 $\mathrm{Dirichlet}$ 分布也有类似的结论, 即如果 $\vec p\sim Dir(\vec t\mid\vec\alpha)$ , 那么有<br>$$E(\vec p)=\left(\frac{\alpha_1}{\sum_{k=1}^K\alpha_k},\frac{\alpha_2}{\sum_{k=1}^K\alpha_k},\cdots,\frac{\alpha_K}{\sum_{k=1}^K\alpha_k}\right)$$</p><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><h2 id="网络资料"><a href="#网络资料" class="headerlink" title="网络资料"></a>网络资料</h2><ul><li><p><a href="https://blog.csdn.net/lucien_zong/article/details/50041341">认识Beta函数</a></p></li><li><p><a href="https://www.zhihu.com/question/30269898">如何通俗理解 beta 分布？</a></p></li></ul>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 概率论 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 函数 </tag>
            
            <tag> 分布 </tag>
            
            <tag> 概率论 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>如何快速搭建一个属于自己的网址导航</title>
      <link href="/scribble/build_nav/"/>
      <url>/scribble/build_nav/</url>
      
        <content type="html"><![CDATA[<p>收藏夹内容太多, 有时候不方便找, 那么这时你就需要一个网址导航来放你的收藏夹的内容啦! <del>我知道理由很牵强, 反正就是要搭网址导航, 理由什么的自己去想.</del> 这篇博文默认你已经注册了 <a href="https://github.com">Github</a> .</p><h1 id="Fork-网址导航项目"><a href="#Fork-网址导航项目" class="headerlink" title="Fork 网址导航项目"></a>Fork 网址导航项目</h1><p><a href="https://github.com/WebStackPage/WebStackPage.github.io">项目地址</a></p><h1 id="开启-Pages-服务"><a href="#开启-Pages-服务" class="headerlink" title="开启 Pages 服务"></a>开启 Pages 服务</h1><p><img src="1.png" alt=""></p><p>进入到你 Fork 后的仓库, 进入 Settings, 拉到下面开启 GitHub Pages.</p><p>此时, 你的网址导航已经成功建立, 可以根据上面的 “Your site is published at <a href="https://xxxx.xxx">https://xxxx.xxx</a>“</p><p> 来进入你的网址导航. 如果要自定义域名, 可以在下面那个 “Custom domain” 框框里写上你自己的域名, 然后设置 CNAME 域名解析记录到 <code>用户名.github.io</code> . 就可以用你自己的域名访问网址导航了.</p><h1 id="修改内容"><a href="#修改内容" class="headerlink" title="修改内容"></a>修改内容</h1><p>这个网址导航现在还不能算是你 “自己的” , 因此可以修改 index.html 来修改其成为你自己个性的网址导航. 修改的过程我就不细说了, 无非就是修改 favicon, title 这些的. 但是修改其中网址导航的网站可不是一件简单的工作, 一不留神就改错了, 因此我专门写了一个方便修改的 Python 脚本.</p><h2 id="NavCreate"><a href="#NavCreate" class="headerlink" title="NavCreate"></a>NavCreate</h2><p><a href="https://github.com/cnyist/NavCreate">项目地址</a></p><p>使用方法在仓库里有说, 我在这里再说一遍.</p><p>该 Python 脚本开头有 title, favicon 等变量, 你修改为自己的, 然后在 text.txt 文本文件中写入固定格式内容, 最后执行 Python 脚本, 就可以在 out.txt 中生成相应的内容, 复制进 index.html , 就可以实现自定义网址导航.</p><p>格式借鉴了 markdown 语法, 用 #, ##, ###, 生成相应的多级目录.</p><p>固定格式是指: (注意这里的逗号是英文的)</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">网站url,网站logo,网站名,网站描述</span><br></pre></td></tr></table></figure><p>如果网站名或网站描述中有 <code>,</code> (英文逗号) , 需要用 <code>&amp;#44</code> 代替</p><p>我举个例子, 如果写成下面这样</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 资料文档</span></span><br><span class="line"><span class="section">## 文档</span></span><br><span class="line">https://www.pypandas.cn/docs/,pandas.png,Pandas 文档,Pandas: 强大的 Python 数据分析支持库</span><br><span class="line">https://www.numpy.org.cn/reference/,numpy.png,NumPy 文档,NumPy 参考手册</span><br><span class="line">https://sklearn.apachecn.org/,sklearn.png,sklearn 文档,scikit-learn (sklearn) 官方文档中文版</span><br><span class="line"><span class="section">## 速查表</span></span><br><span class="line"><span class="section">### 机器学习</span></span><br><span class="line">https://developers.google.com/machine-learning/glossary?hl=zh-cn,机器学习术语表.png,机器学习术语表,本术语表中列出了一般的机器学习术语和 TensorFlow 专用术语的定义.</span><br><span class="line">https://blog.csdn.net/liuxiao214/article/details/78130910,机器学习专业名词中英文对照.png,机器学习专业名词中英文对照,机器学习专业名词中英文对照</span><br><span class="line"><span class="section"># 工具网站</span></span><br><span class="line"><span class="section">## 壁纸图片</span></span><br><span class="line">https://wall.alphacoders.com/?lang=Chinese,wallpaper<span class="emphasis">_abyss.png,Wallpaper Abyss,高清壁纸&amp;#44 桌面背景</span></span><br></pre></td></tr></table></figure><p>那么会生成如下页面</p><p><img src="build_nav.png" alt=""></p><hr><p><strong>最后… <del>重点来啦!</del> 我的网址导航: <a href="https://nav.clouder.im/">https://nav.clouder.im/</a></strong></p>]]></content>
      
      
      <categories>
          
          <category> 杂文 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 教程 </tag>
            
            <tag> 搭建站点 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>手把手教你将博客备份到 Github</title>
      <link href="/hexo/back_blog_up/"/>
      <url>/hexo/back_blog_up/</url>
      
        <content type="html"><![CDATA[<p>如果由于某些原因, 你把博客源文件弄丢了. 要是有备份, 那么就可以迅速恢复过来, 要是没有… 那你辛辛苦苦写的好几十篇博文就可能毁于一旦. 所以备份是很重要的. 那么要备份到哪呢? 这里我推荐 Github , 方便快捷, 而且不怕跑路.</p><span id="more"></span><h1 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h1><p>首先, 进入博客根目录执行</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git init</span><br></pre></td></tr></table></figure><p>然后就会在目录下生成一个 <code>.git</code> 文件. </p><h1 id="创建-Github-仓库"><a href="#创建-Github-仓库" class="headerlink" title="创建 Github 仓库"></a>创建 Github 仓库</h1><p>进入你的 <a href="https://github.com">Github</a> , 新建一个仓库, 复制该仓库的 SSH url .</p><h1 id="添加远程仓库"><a href="#添加远程仓库" class="headerlink" title="添加远程仓库"></a>添加远程仓库</h1><p>回到博客根目录, 执行</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote add origin git@github.com:xxx/xxx  // 即你的 SSH url</span><br></pre></td></tr></table></figure><p>然后</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git add *  // 这一步可能会报错, 如果报错换成 `git add * -f` 再试试</span><br><span class="line">git commit -m &quot;想写啥就写啥, 反正不能不写&quot;</span><br><span class="line">git push origin master  // 如果报错, 可以直接强制 push 即 `git push -f origin master`</span><br></pre></td></tr></table></figure><p>然后你就发现 Github 仓库多了你的源文件.</p><h1 id="设置私密仓库"><a href="#设置私密仓库" class="headerlink" title="设置私密仓库"></a>设置私密仓库</h1><p>如果你不想要你的博客源文件被别人看到, 你可以设置私密仓库, 现在 Github 私密仓库已经是免费的了 (Github 真良心) .</p>]]></content>
      
      
      <categories>
          
          <category> Git </category>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Git </tag>
            
            <tag> Hexo </tag>
            
            <tag> 教程 </tag>
            
            <tag> 搭建站点 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Valine 评论回复发送重置密码邮件</title>
      <link href="/hexo/Valine_reply/"/>
      <url>/hexo/Valine_reply/</url>
      
        <content type="html"><![CDATA[<p><strong>更新: Valine 新版已经停用了邮件提醒功能.</strong></p><h1 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h1><p>在 Valine 评论系统中留下邮箱后, 回复会发送一份邮件到留下的邮箱. 这本来是评论通知功能, 但是却发送了重置 LeanCloud 密码的邮件?</p><h1 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h1><p>其实原因就在于, Valine 的评论通知功能是基于 LeanCloud 发送重置密码的邮件功能的, 所以才会发送重置密码的邮件.</p><h1 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h1><p>进入 LeanCloud 控制台, 修改邮件模板.</p><p><img src="1.png" alt=""></p><p>改为</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">你在 &#123;&#123;appname&#125;&#125; 的评论收到了新的回复</span><br><span class="line"></span><br><span class="line">&lt;p&gt;Hi, &#123;&#123;username&#125;&#125;&lt;/p&gt;</span><br><span class="line">&lt;p&gt;</span><br><span class="line">你在 &#123;&#123;appname&#125;&#125; 的评论收到了新的回复，请点击查看：</span><br><span class="line">&lt;/p&gt;</span><br><span class="line">&lt;p&gt;&lt;a href=&quot;你的站点&quot; style=&quot;display: inline-block; padding: 10px 20px; border-radius: 4px; background-color: #3090e4; color: #fff; text-decoration: none;&quot;&gt;马上查看&lt;/a&gt;&lt;/p&gt;</span><br></pre></td></tr></table></figure><p>注意自定义重置密码界面要改为你的站点.</p><p>问题成功解决!</p><p><img src="2.png" alt=""></p><p><strong>虽然没有更改邮件模板会发送重置密码的邮件, 但是经过测试, 这个邮件并没有什么卵用, 所以并不用担心.</strong></p>]]></content>
      
      
      <categories>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Hexo </tag>
            
            <tag> 搭建站点 </tag>
            
            <tag> 问题 </tag>
            
            <tag> Valine </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Gamma 函数详解</title>
      <link href="/math/probability_theory/gamma/"/>
      <url>/math/probability_theory/gamma/</url>
      
        <content type="html"><![CDATA[<h1 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h1><p>&nbsp;$\mathrm{Gamma}$ 函数如下定义<br>$$\Gamma(x) = \int_0^{\infty}t^{x - 1}e^{-t}\,\mathrm{d}t$$<br>那么它是如何来的呢?</p><p>考虑如下的一个数列<br>$$a_n = \{1, 4, 9, 16, \cdots\}$$<br>这个数列可以用通项公式 $n^2$ 来表达, 即使 $n$ 为实数也是良好定义的. 现在我们来考虑阶乘 $n!$ . 在 $n$ 为整数时, 它是良好定义的, 但是当 $n$ 为实数时呢? $0.5!$ 等于多少? 欧拉于 1729 年完美的解决了这个问题, 由此导致了 $\mathrm{Gamma}$ 函数的产生. $\mathrm{Gamma}$ 函数可以看作是定义在实数域的 $(n - 1)!$ 为什么不是 $n!$ 呢? 后面会说明.</p><p>欧拉考虑了如下形式的积分 (至于为什么是<strong>如下形式</strong>的<strong>积分</strong>, 请自行了解).<br>$$J(e,n) = \int_0^1 x^e(1 - x)^n\,\mathrm{d}x$$<br><strong>这里的 $e$ 并不是自然对数的底数, 而是任意实数.</strong> 由分布积分可得<br>$$\begin{aligned}\int_0^1x^e(1 - x)^n\mathrm dx &= \int_0^1\left(\frac{1}{e + 1}x^{e+1}\right)'(1 - x)^n\,\mathrm{d}x\\\\&=\left.\left(\left(\frac{1}{e+1}x^{e+1}\right)(1 - x)^n\right)\right|^1_0 - \int_0^1\left(\frac{1}{e+1}x^{e+1}\right)\cdot-n(1-x)^{n - 1}\,\mathrm{d}x\\\\&=\frac{n}{e+1}\int_0^1 x^{e + 1}(1 - x)^{n - 1}\end{aligned}$$<br>因此<br>$$J(e, n) = \frac{n}{e+1}J(e+1, n-1)$$<br>不断进行这个过程, 最终会得到<br>$$\begin{aligned}J(e, n) &= \frac{n(n - 1)(n - 2)\cdots1}{(e+1)(e+2)(e + 3)\cdots(e+n)}J(e+n, 0)\\\\&= \frac{n(n - 1)(n - 2)\cdots1}{(e+1)(e+2)(e + 3)\cdots(e+n)}\left.\left(\frac{1}{e+n+1}x^{e+n+1}\right)\right|^1_0\\\\&=\frac{n!}{(e+1)(e+2)(e + 3)\cdots(e+n)(e+n+1)}\end{aligned}$$<br>因此有<br>$$n! = (e+1)(e+2)\cdots(e+n+1)J(e,n)\tag{1}$$<br>此时就已经可以表达实数域的 $n!$ 了.</p><p>为了式子更加简化, 欧拉运用了<del>亿点点</del>计算技巧, 取 $e = f/g$ 并令 $f\rightarrow1, g\rightarrow0$ .</p><p>首先令 $x = t^{\frac{g}{f+g}}$ , 而有<br>$$\begin{aligned}\frac{\,\mathrm{d}x}{\,\mathrm{d}t} &= \frac{g}{f+g}t^{\frac{g}{f+g} - 1}\\\\\mathrm dx &= \frac{g}{f+g}t^{-\frac{f}{f+g}}\mathrm dt\end{aligned}$$</p><p>当 $x\in[0,1]$ 时, $t\in[0, 1]$ .</p><p>带入式 $(1)$ 可得<br>$$\begin{aligned}n! &= (e+1)(e+2)\cdots(e+n+1)\int_0^1 x^e(1 - x)^n\,\mathrm{d}x\\\\&= (\frac{f}{g}+1)(\frac{f}{g}+2)\cdots(\frac{f}{g}+n+1)\int_0^1t^{\frac{f}{f+g}}(1 - t^{\frac{g}{f+g}})^n \frac{g}{f+g}t^{-\frac{f}{f+g}}\,\mathrm{d}t\\\\&=(\frac{f}{g}+1)(\frac{f}{g}+2)\cdots(\frac{f}{g}+n+1)\int_0^1(1 - t^{\frac{g}{f+g}})^n\frac{g}{f+g}\,\mathrm{d}t\\\\&=\frac{(f+g)(f+2g)\cdots(f+(n+1)g)}{g^{n+1}}\int_0^1\left(\frac{1-t^{\frac{g}{f+g}}}{\frac{g}{f+g}}\right)^n\left(\frac{g}{f+g}\right)^{n + 1}\,\mathrm{d}t\\\\&=\frac{(f+g)(f+2g)\cdots(f+(n+1)g)}{(f+g)^{n+1}}\int^1_0\left(\frac{1-t^{\frac{g}{f+g}}}{\frac{g}{f+g}}\right)^n\,\mathrm{d}t\end{aligned}$$<br>积分左边显然等于 $1$ , 那么右边等于什么呢?</p><p>上式等价于<br>$$\int^1_0\left(\lim_{x\rightarrow0}\frac{1-t^{x}}{x}\right)^n\,\mathrm{d}t$$<br>使用洛必达法则<br>$$\begin{aligned}\int^1_0\left(\lim_{x\rightarrow0}\frac{1-t^{x}}{x}\right)^n\,\mathrm{d}x &= \int^1_0\left(\lim_{x\rightarrow0}-t^x\ln t\right)^n\,\mathrm{d}t\\\\&= \int_0^1(-\ln t)^n\,\mathrm{d}t\end{aligned}$$<br>于是 $n!$ 就简化成了<br>$$n! =\int_0^1(-\ln t)^n\,\mathrm{d}t$$<br>令 $t = \mathrm{e}^{-u}$ , <strong>(注意这里的 $e$ 为自然对数的底数)</strong> , 当 $t\in[0, 1]$ 时 $u\in [0, +\infty]$ .</p><p>有<br>$$\begin{aligned}\frac{\,\mathrm{d}t}{\,\mathrm{d}u} &= (\mathrm{e}^{-u})'\\\\\frac{\,\mathrm{d}t}{\,\mathrm{d}u}&= -\mathrm{e}^{-u}\\\\\,\mathrm{d}t&=-\mathrm{e}^{-u}\,\mathrm{d}u\end{aligned}$$<br>这里要注意到 $\mathrm{d}u < 0$ .</p><p>因此<br>$$\begin{aligned}n! &= \int_0^{+\infty} u^n\mathrm{e}^{-u}\,\mathrm{d}u\end{aligned}$$<br>由于积分中的 $\mathrm{d}u>0$ , 因此负号被抵消了. </p><p>这就是 $n!$ 的积分表达, 而<br>$$\Gamma(x) = \int_0^{\infty}t^{x - 1}\mathrm{e}^{-t}\,\mathrm{d}t = (n-1)!$$<br>所以, 为什么不是 $n!$ 呢? 欧拉最早的 $\mathrm{Gamma}$ 函数定义还真是 $\Gamma(n) = n!$ 但是欧拉后来不知道出于什么原因, 修改了 $\mathrm{Gamma}$ 函数的定义, 使得 $\Gamma(n) = (n-1)!$ 有数学家猜测可能是欧拉研究了如下形式的积分<br>$$\begin{aligned}B(m,n)&=\int_0^1x^{m-1}(1-x)^{n-1}\,\mathrm{d}x\\\\&=\frac{\Gamma(m)\Gamma(n)}{\Gamma(m+n)}\end{aligned}$$<br>这个函数现在称为 $\mathrm{Beta}$ 函数. 看, 多么有美感的一个式子, 如果 $\Gamma(n) = n!$ , 那么就会变为<br>$$B(m, n) = \frac{\Gamma(m)\Gamma(n)}{\Gamma(m+n+1)}$$<br>公式的美感就降低了.</p><p>其证明可以看我的<a href="https://yunist.cn/math/probability_theory/beta/">这篇文章</a>.</p><p>不过, 这只是一个定义, 并不需要太纠结.</p><hr><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><h2 id="网络资料"><a href="#网络资料" class="headerlink" title="网络资料"></a>网络资料</h2><ul><li><p><a href="https://www.jianshu.com/p/387ab7b9998b">Gamma 函数推导</a></p></li><li><p><a href="http://bloglxm.oss-cn-beijing.aliyuncs.com/lda-LDA%E6%95%B0%E5%AD%A6%E5%85%AB%E5%8D%A6.pdf">LDA 数学八卦</a></p></li></ul>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 概率论 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 函数 </tag>
            
            <tag> 概率论 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>git clone 速度太慢? 一招教你加速 git (效果显著)</title>
      <link href="/git/quickly_git_clone/"/>
      <url>/git/quickly_git_clone/</url>
      
        <content type="html"><![CDATA[<p>在天朝, 由于众所周知的原因, git clone github 仓库的速度非常的慢, 所以这里就介绍一个加速 git 的方法.<br><span id="more"></span></p><h1 id="fork-仓库"><a href="#fork-仓库" class="headerlink" title="fork 仓库"></a>fork 仓库</h1><p>如果是自己的仓库可以跳过, 如果要 git clone 别人的仓库, 那就先 fork 到自己的 github 仓库中.</p><h1 id="注册码云"><a href="#注册码云" class="headerlink" title="注册码云"></a>注册码云</h1><p>首先注册一个码云账号 (可以用 github 账号登陆) , <a href="https://gitee.com/">点此进入</a>. </p><p><img src="1.png" alt=""></p><p>点击 <code>从 GitHub/GitLab 导入仓库</code> </p><p><img src="2.png" alt=""></p><p>找到你要 git clone 的仓库, 然后导入.</p><h1 id="git-clone-码云仓库"><a href="#git-clone-码云仓库" class="headerlink" title="git clone 码云仓库"></a>git clone 码云仓库</h1><p>成功导入后, 进入你已经导入成功的码云仓库, 然后使用 https 方式 clone.</p><p><img src="3.png" alt=""></p><p>然后你就会发现…简直是飞速!!!</p><p>如果想要 git push 到 github 而不是码云, 那么只要更改远程仓库地址为 github 就好了.</p>]]></content>
      
      
      <categories>
          
          <category> Git </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Git </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>hexo d 命令后 github 无法更新问题</title>
      <link href="/hexo/hexo_d_github_problem/"/>
      <url>/hexo/hexo_d_github_problem/</url>
      
        <content type="html"><![CDATA[<span id="more"></span><h1 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h1><p><code>hexo d</code> 后查看仓库, 发现根本没有更新, 仔细观察 shell 的输出, 还会看到如下报错</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Branch master set up to track remote branch master from git@github.com:xxxx/xxxx.github.io.git.</span><br></pre></td></tr></table></figure><p>其中 xxxx 是你的 github 用户名.</p><h1 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h1><p>删除 <code>hexo/.deploy_git</code> 文件, 然后重新尝试 <code>hexo d</code> , 就可以成功更新了.</p><p><del>这应该不算水文吧.</del></p>]]></content>
      
      
      <categories>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Hexo </tag>
            
            <tag> 搭建站点 </tag>
            
            <tag> 问题 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>读懂西瓜书 14 : 概率图模型</title>
      <link href="/ML/watermelon_book/read/14/"/>
      <url>/ML/watermelon_book/read/14/</url>
      
        <content type="html"><![CDATA[<h1 id="马尔可夫性"><a href="#马尔可夫性" class="headerlink" title="马尔可夫性"></a>马尔可夫性</h1><p>本章最重要的概念就是马尔可夫性. 马尔可夫性是指变量的状态只与其前一个时刻的状态有关, 而与其他的状态无关, 称为 “无后效性” . 这里可以作一个拓展, 即指变量的状态只与其周围的变量状态有关, 这里的 ‘周围’ 既可以是时间也可以是空间.</p><h1 id="隐马尔可夫模型"><a href="#隐马尔可夫模型" class="headerlink" title="隐马尔可夫模型"></a>隐马尔可夫模型</h1><p>隐马尔可夫模型包括两条链, 一条是由可观测的状态组成的, 一条是由不可观测的状态 (隐变量) 组成的. 那么究竟是什么呢, 我们举个例子.</p><p>假设每天的天气只与前一天的天气有关. 比如今天如果是晴天, 那么明天有 $70\%$ 的可能还是晴天, 有 $30\%$ 的可能是阴天. 如果今天是阴天, 那么明天有 $50\%$ 的可能是晴天, 有 $50\%$ 的可能还是阴天. 一天只能有一种天气, 所以我们每天都能观测到一种天气, 这是可观测的. 比如经过一个星期, 我们得到了天气关于时间的一个序列</p><div class="table-container"><table><thead><tr><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center">3</th><th style="text-align:center">4</th><th style="text-align:center">5</th><th style="text-align:center">6</th><th style="text-align:center">7</th></tr></thead><tbody><tr><td style="text-align:center">晴</td><td style="text-align:center">晴</td><td style="text-align:center">晴</td><td style="text-align:center">阴</td><td style="text-align:center">阴</td><td style="text-align:center">晴</td><td style="text-align:center">晴</td></tr></tbody></table></div><p>现在假设你有个朋友在国外, 你想要知道他们那边的天气, 但是你只了解你的朋友是在家里还是外出, 并不知道具体天气如何, 而且你还知道假如是晴天, 那么他有 $70\%$ 的可能出去, 有 $30\%$ 的可能呆在家, 如果是阴天, 那么有 $10\%$ 的可能出去, 有 $90\%$ 的可能呆在家. 假如又过了一个星期, 虽然这个星期里的天气是确实存在的, 可是你并不知道, 这就是那条由隐变量组成的 “隐链” . 你的朋友的状态和天气有关, 你也了解你的朋友的状态, 那么朋友这一个星期里的状态也构成一天链, 这就是由可观测的状态组成的 “明链” .</p><div class="table-container"><table><thead><tr><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center">3</th><th style="text-align:center">4</th><th style="text-align:center">5</th><th style="text-align:center">6</th><th style="text-align:center">7</th></tr></thead><tbody><tr><td style="text-align:center">出去</td><td style="text-align:center">在家</td><td style="text-align:center">晴</td><td style="text-align:center">在家</td><td style="text-align:center">在家</td><td style="text-align:center">在家</td><td style="text-align:center">出去</td></tr></tbody></table></div><p>明链和暗链结合在一起, 就有了隐马尔可夫模型.</p><p><img src="1.png" alt=""></p><p>以上面的例子来说明. $y_i$ 就是第 $i$ 天的天气, $x_i$ 是你朋友第 $i$ 天的活动. 而状态转移概率 $\boldsymbol A$ 为<br>$$\left[\begin{matrix}0.7&0.3\\\\0.5&0.5\end{matrix}\right]$$<br>输出观测概率 $\boldsymbol{B}$ 为<br>$$\left[\begin{matrix}0.7&0.3\\\\0.1&0.9\end{matrix}\right]$$<br>初始状态概率 $\boldsymbol{\pi}$ 为<br>$$\left[\begin{matrix}1\\\\0\end{matrix}\right]$$<br>产生观测序列 $\{x_1, x_2, \dots\}$ 的过程书上已经有了, 这里不再详细叙述.</p><p>当然, 一个确定的模型并不一定能产生确定的结果, 上面的例子只是一种可能结果, 还有其他很多种结果, 出现的概率各不相同.</p><p>而隐马尔可夫模型的三个基本问题我们也用例子来说一下:</p><ul><li>即我们得到了朋友这一个星期的状态, 那么给定模型 $\lambda = [\boldsymbol{A},\boldsymbol{B} , \boldsymbol{\pi}]$ , 计算出出现这个状态的概率.</li><li>给定模型 $\lambda = [\boldsymbol{A},\boldsymbol{B} , \boldsymbol{\pi}]$ 以及朋友这个星期的状态, 那么推测出这个星期朋友那里的天气是怎样的.</li><li>给出朋友这个星期的状态, 如何调整参数 $\lambda$ 才能使朋友出现这样的状态的可能性最大.</li></ul><h1 id="马尔可夫随机场"><a href="#马尔可夫随机场" class="headerlink" title="马尔可夫随机场"></a>马尔可夫随机场</h1><h2 id="Hammersley-Clifford-定理"><a href="#Hammersley-Clifford-定理" class="headerlink" title="Hammersley-Clifford 定理"></a>Hammersley-Clifford 定理</h2><p>&nbsp;$\textrm{Hammersley-Clifford}$ 定理指出概率无向图模型的联合概率可以分解为定义在极大团上的势函数的乘积. 即<br>$$P(\boldsymbol{\mathrm{x}}) = \frac{1}{Z}\prod_{Q\in \mathcal{C}}\psi_Q(\boldsymbol{\mathrm{x}}_Q)\\\\$$<br>定理充分性的证明在西瓜书中其实已经给出. (即西瓜书中所说的简单的验证)</p><h3 id="极大团"><a href="#极大团" class="headerlink" title="极大团"></a>极大团</h3><blockquote><p>若在一个团中加入另外任何一个节点都不再写成团, 则称该团为 “极大团” (maximal); 换言之, 极大团就是不能被其他团所包含的团.</p></blockquote><p>换句话讲就是, 找不到这个团之外的一个结点和这个团中所有结点之间都有边, 那么这个团就是极大团. 可以利用反证法证明: 如果极大团被其他团所包含, 那么根据团的定义, 这个极大团之外还会有一个结点 (该结点在这个极大团之外却在那个包含这个极大团的团之内) 与团中所有节点都有边, 违背了极大团的定义, 因此不成立.</p><h3 id="势函数"><a href="#势函数" class="headerlink" title="势函数"></a>势函数</h3><p>势函数从何而来, 为什么是这样定义? 相信你一开始也和我一脸懵逼. 现在我试着将我所理解的势函数尽我所能表达出来.</p><p>势函数本身用来刻画某种 ‘偏好’ . 即你依靠经验认为结点之间应该有某种关系. 比如说你如果认为结点之间的值应该要差不多, 那么当它们的值确实差不多时, 你应该给出更高的分数, 如果他们的值相差较大, 你就应该给出更低的分数. 依靠这样的准则, 就可以构造出一个势函数, 来实现你的给分策略. 势函数的形式不是唯一的, 只不过常用指数函数来定义势函数. 使用指数函数的目的是为了满足非负性 (概率总不可能是负的吧) . </p><p>至于势函数和后面提到的特征函数到底有什么根本上的区别… <del>好吧我也不清楚.</del></p><h3 id="规范化因子"><a href="#规范化因子" class="headerlink" title="规范化因子"></a>规范化因子</h3>$$P(\boldsymbol{\mathrm{x}}) = \frac{1}{Z}\prod_{Q\in \mathcal{C}}\psi_Q(\boldsymbol{\mathrm{x}}_Q)\\\\$$<p>其中 $Z = \sum_\boldsymbol{\mathrm{x}}\prod_{Q\in\mathcal{C}}\psi_Q(\boldsymbol{\mathrm{x}}_Q)$ 是规范化因子, 那么它究竟起到什么作用呢? 其实它起到的作用就是保证 $\sum_\boldsymbol{\mathrm{x}}P(\boldsymbol{\mathrm x}) = 1$ , 即保证我们算出的是一个 “概率” . 而概率具有的性质就是所有可能结果的概率和为 $1$ .</p><h2 id="马尔可夫性-1"><a href="#马尔可夫性-1" class="headerlink" title="**马尔可夫性"></a>**马尔可夫性</h2><p>事实上, 这些 ‘**马尔可夫性’ 成立的前提都在于某个变量只与其相邻变量有关.</p><h3 id="全局马尔可夫性"><a href="#全局马尔可夫性" class="headerlink" title="全局马尔可夫性"></a>全局马尔可夫性</h3><p>简单的来说, 就是两 ‘团’ 变量被中间的 ‘变量墙’ 隔开, 因此具有独立性.</p><h3 id="局部马尔可夫性"><a href="#局部马尔可夫性" class="headerlink" title="局部马尔可夫性"></a>局部马尔可夫性</h3><p>可以形象的认为 $n^*(v)$ 像一圈围墙将 $v$ 包围了起来, 这堵墙存在时 (变量给定时) , 会将 $v$ 与外界分离 (即独立于外界) .</p><p>这里说明一个可能不太清楚的点.</p><blockquote><p>令 $V$ 为图的结点集, $n(v)$ 为结点 $v$ 在图上的邻接结点, $n^*(v) = n(v) \cup \{v\}$ , 有 $\boldsymbol{\mathrm{x}}_v \perp \boldsymbol{\mathrm{x}}_{V\backslash n^*(v)}$ .</p></blockquote><p> 这里的 $\boldsymbol{\mathrm{x}}_{V\backslash n^*(v)}$ 中的 $V\backslash n^*(v)$ 应该是集合 $V$ 去除 $n^*(v)$ 集合. 所有的 $A\backslash B$ 运算都是集合 $A$ 去掉其中的集合 $B$ 部分.</p><h3 id="成对马尔可夫性"><a href="#成对马尔可夫性" class="headerlink" title="成对马尔可夫性"></a>成对马尔可夫性</h3><p>只要两个变量不在同一条边上, 那么就可以将这两个变量完全用其他结点隔离开, 最极端的情况就是把除了这两个变量的节点都当成 ‘墙’ , 这两个变量的周围都是 ‘墙’ , 被这堵墙隔开后, 它们就具有独立性. 这就是成对马尔可夫性. 如果这两个变量在同一条边上, 那么无论是多厚的墙, 两个变量间还是有一条绳子 (边) 连着, 他们仍然不会分离, 不具有成对马尔可夫性.</p><h1 id="条件随机场"><a href="#条件随机场" class="headerlink" title="条件随机场"></a>条件随机场</h1><p>条件随机场与隐马尔可夫模型、马尔可夫随机场的最主要区别在于条件随机场是判别式模型, 而隐马尔可夫模型和马尔科夫随机场是生成式模型. 顾名思义, 条件随机场就是有 ‘条件’ 的 马尔可夫 ‘随机场’ . 同样基于最大团定义了势函数, 只不过还多引入了一个特征函数.</p><p>条件随机场的结构是任意的. 但是一般我们会考虑 “链式条件随机场” ($\mathrm{chain-structured\;CRF}$).</p><p><img src="2.png" alt=""></p><h2 id="特征函数"><a href="#特征函数" class="headerlink" title="特征函数"></a>特征函数</h2><p>特征函数刻画了相邻变量之间的相关关系以及观测序列对它们的影响. </p><h1 id="学习与推断"><a href="#学习与推断" class="headerlink" title="学习与推断"></a>学习与推断</h1><h2 id="变量消去"><a href="#变量消去" class="headerlink" title="变量消去"></a>变量消去</h2><p>变量消去一般用来求边缘概率 (可以理解为求和的过程可以一个个的 ‘消去’ 变量, 故为变量消去). 如果进行暴力求和来求边缘概率, 那么时间复杂度会达到可怕的 $O(N^T)$ , 其中 $N$ 是变量可能的取值数, $T$ 是要消去变量的总数. 这个复杂度可以说是基本上不可能进行求解的, 但好在我们有更快的算法, 那就是动态规划.</p><h3 id="动态规划"><a href="#动态规划" class="headerlink" title="动态规划"></a>动态规划</h3>$$\begin{aligned}P(x_5) &= \sum_{x_4}\sum_{x_3}\sum_{x_2}\sum_{x_1}P(x_1, x_2, x_3, x_4)\\\\&=\sum_{x_4}\sum_{x_3}\sum_{x_2}\sum_{x_1}P(x_1)P(x_2\mid x_1)P(x_3 \mid x_2)P(x_4 \mid x_3)P(x_5\mid x_3)\end{aligned}$$<p>上式可以等价的表达为<br>$$P(x_5) = \sum_{x_3}P(x_5\mid x_3)\sum_{x_4}P(x_4 \mid x_3)\sum_{x_2}P(x_3 \mid x_2)\sum_{x_1}P(x_1)P(x_2\mid x_1)$$<br>注意一个问题, 这里面加不加括号都是一样的, 什么意思呢? 其实就是<br>$$(\sum_ix_i)(\sum_jx_j) = \sum_i(x_i\sum_jx_j)$$<br>首先我们从最后一个 $\sum$ 开始算<br>$$\sum_{x_1}P(x_1)P(x_2\mid x_1)$$<br>可以看到这只与 $x_2$ 有关, 即这是一个关于 $x_2$ 的函数, 我们简写为 $m_{12}(x_2)$ 那么我们再寻找 $x_2$ 从何而来<br>$$\sum_{x_2}P(x_4\mid x_3)$$<br>这里就有了 $x_2$ (前面的 $\sum$ 是对 $x_2$ 求和), 因此就可以结合起来<br>$$\sum_{x_2}P(x_3\mid x_2)m_{12}(x_2)$$<br>这是一个只与 $x_3$ 有关的函数, 同样简写为 $m_{23}(x_3)$ .</p><p>我们按照这样的方法一个个去向前推进, 即每次寻找未提供的变量 (就是没有说这个变量具体的值, 又或者说目前的函数可以表达为只与这个变量有关的函数) 在哪 (即 $\sum$ 下的变量), 然后互相结合递推, 注意到, 可能有两个未提供的变量同时与一个 $\sum$ 有关, 比如 $\sum_{x_2}P(x_3\mid x_2)$ 和 $\sum_{x_4}P(x_4\mid x_3)$ 同时与 $x_3$ 有关, 于是分别求出, 再与 $\sum_{x_3}$ 结合.</p><p>这样算法的复杂度就降为了 $O(NT)$ .</p><p>但是就是有一个缺点, 再次计算另一个边缘分布时有些变量又要求一遍, 造成冗余计算.</p><h2 id="信念传播"><a href="#信念传播" class="headerlink" title="信念传播"></a>信念传播</h2><p>信念传播其实就是基于变量消去做了一些改进, 可以理解为存储了中间变量 (比如 $m_{12}(x_2)$ ), 这样计算的时候直接使用就行了.</p><h2 id="近似推断"><a href="#近似推断" class="headerlink" title="近似推断"></a>近似推断</h2><p>我们的目标是要计算函数 $f(x)$ 在概率密度函数 $p(x)$ 下的期望<br>$$\mathbb{E}_p[f] = \int f(x)p(x)\mathrm{d}x$$<br>由于积分比较困难, 所以可以根据 $p(x)$ 采样作无偏估计<br>$$\hat{f} = \frac{1}{N}\sum^{N}_{i = 1}f(x_i)$$<br>但是如果 $p(x)$ 较为复杂, 直接采样可能比较复杂, 因此就有了其他间接采样的方法. $\mathrm{MCMC}$ 就是概率图模型中最常用的方法.</p><h3 id="MCMC-采样"><a href="#MCMC-采样" class="headerlink" title="MCMC 采样"></a>MCMC 采样</h3><p>&nbsp;$\mathrm{MCMC\,(Markov\;Chain\;Monte\;Carlo)}$ 方法是构造一条马尔可夫链, 此马尔科夫链的平稳分布正是 $p(x)$ . 也就是说, 运行马尔科夫链一段时间后 (即收敛到平稳分布), 此时产出的样本 $\mathrm{x}$ 近似服从分布 $p$ .</p><p> 具体来说,  $\mathrm{MCMC}$ 有一个代表算法 $\mathrm{Metropolis-Hastings\,(MH)}$ .</p><h4 id="Metropolis-Hastings"><a href="#Metropolis-Hastings" class="headerlink" title="Metropolis-Hastings"></a>Metropolis-Hastings</h4><p>令转移核为 $p(x, x')$<br>$$p(x, x') = q(x,x')\alpha(x.x')$$<br>其中 $q(x, x')$ 与 $\alpha(x,x')$ 分别称为建议分布 $(\mathrm{proposal\;distribution})$ 和接受分布 $(\mathrm{acceptance\;distribution})$ . 建议分布是一个你自由选择的分布, 一般来说要比较容易抽样 (比如均匀分布) . 接受分布 $\alpha(x,x')$ 是<br>$$\alpha(x,x') = min\left\{1, \frac{p(x')q(x', x)}{p(x)q(x, x')}\right\}$$<br>因此 $p(x, x')$ 可以写为<br>$$p(x, x') = \left\{\begin{array}qq(x, x'),&p(x')q(x', x)\geqslant p(x)q(x, x')\\\\q(x', x)\displaystyle\frac{p(x')}{p(x)}, &p(x')q(x', x) < p(x)q(x, x')\end{array}\right.$$<br>假设在时刻 $(t - 1)$ 处于状态 $x$ , 即 $x_{t - 1} = x$, 那么有</p><blockquote>$1$. 按照建议分布 $q(x, x')$ 抽取一个候选状态 $x'$<p>$2$. 按照接受分布 $\alpha(x, x')$ 决定是否接受 $x'$. 接受则产生下一个样本 $x_t = x'$ , 拒绝就让 $x_t = x_{t - 1}$. 同时 $t = t + 1$ , 然后回退到 $1$ 步骤.</p></blockquote><p>这个抽取样本过程等价于直接按照 $p(x, x')$ 抽取. </p><p>每次抽样时刻都会增加 $1\,$$ . 那么当经过一段时间后, 马尔可夫链可以达到平稳分布, 而 $p(x)\,$$ 正是其平稳分布. 这是因为对于分布 $p(x)\,$$ 来说, 这个马尔可夫链是可逆的, 而可逆马尔科夫链是平稳分布的充分条件. 达到平稳分布后, 其后产生的样本即满足分布 $p(x)\,$$ , 此时我们就能轻松抽样了.#### 单变量 Metropolis-Hastings 算法单变量 $\mathrm{MH}$ 算法与传统 $\mathrm{MH}$ 算法的区别就在于单变量 $\mathrm{MH}$ 算法是每一次样本产生是对多元变量的每一分量依次抽样, 从而实现对整个多元变量的一次抽样, 这大概就是 '单变量' $\mathrm{MH}$ 算法名字的由来.#### 吉布斯采样吉布斯采样是 $\mathrm{MH}$ 算法的特例, 更准确的说应该是单变量 $\mathrm{MH}$ 算法的特例. 它将建议分布 $q(x’, x)$ 设置成 $p(x<em>j\mid x’</em>{-j})$ , 即$$q(x, x') = p(x'_j\mid x_{-j})$$&nbsp;$x<em>{-j}$ 即为除了 $x</em>{j}$ 外的其他分量的集合.这样就可以让接受概率 $\alpha = 1$ , 从而大大提高采样效率.### 变分推断#### EM 算法&nbsp;$\mathrm{EM}$ 算法在 $7.6$ 节就已经作了一个介绍, 其分为 $\boldsymbol{\mathrm{E}}$ 步和 $\boldsymbol{\mathrm{M}}$ 步. 对于某时刻的 $\Theta<em>t$ 来说, 可以根据 $\Theta_t$ 与已观测变量 $\boldsymbol{\mathrm X}$ 计算隐变量 $\boldsymbol{\mathrm Z}$ 的分布 $P(\boldsymbol{\mathrm{Z}}\mid\boldsymbol{\mathrm{X}},\Theta_t)$ , 并且还要计算出一个与 $\Theta$ 有关的函数 $P(\boldsymbol{\mathrm{X}}, \boldsymbol{\mathrm{Z}}\mid\Theta)$ (以便后续 $\boldsymbol{\mathrm{M}}$ 步计算期望) . 然后 $\boldsymbol{\mathrm{M}}$ 步即令新的参数 $\Theta</em>{t + 1}$ 能够最大化对数似然$$\Theta_{t + 1} = \underset{\Theta}{\arg\max}\sum_{\boldsymbol{\mathrm{Z}}}P(\boldsymbol{\mathrm{Z}}\mid\boldsymbol{\mathrm{X}},\Theta_t)\ln P(\boldsymbol{\mathrm{X}}, \boldsymbol{\mathrm{Z}}\mid\Theta)$$这个式子其实是对数似然函数在分布 $P(\boldsymbol{\mathrm{Z}}\mid\boldsymbol{\mathrm{X}},\Theta<em>t)$ 下的期望.#### 式 14.36 推导$$\mathcal{L}(q) = \int q(\boldsymbol{\mathrm{z}})\ln \left\{\frac{p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}})}{q(\boldsymbol{\mathrm{z}})}\right\}\mathrm{d}\boldsymbol{\mathrm{z}}$$根据$$q(\boldsymbol{\mathrm{z}}) = \prod^{M}_{i = 1}q_i(\boldsymbol{\mathrm{z}}_i)$$为了简化, 我们将 $q_i(\boldsymbol{\mathrm{z}}</em>{i\not=j})$ 简写为 $q<em>i$代入可得$$\begin{aligned}\mathcal{L}(q) &= \int \prod_{i}q_i\ln \left\{\frac{p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}})}{q(\boldsymbol{\mathrm{z}})}\right\}\mathrm{d}\boldsymbol{\mathrm{z}}\\\\&= \int \prod_{i}q_i\left\{\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}) - \sum_i \ln q_i\right\}\mathrm{d}\boldsymbol{\mathrm{z}}\\\\&= \int \prod_{i}q_i\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}) - \int\prod_{i}q_i\sum_i \ln q_i\mathrm{d}\boldsymbol{\mathrm{z}}\\\\&= \int q_j\prod_{i \not= j}q_i\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}})\mathrm{d}\boldsymbol{\mathrm{z}} - \int \prod_{i}q_i\sum_i \ln q_i\mathrm{d}\boldsymbol{\mathrm{z}}\end{aligned}$$注意到$$\int f(x) \mathrm{d}x = \int \left\{\int f(\boldsymbol{x})\mathrm{d}\boldsymbol{x}_{-i}\right\}\mathrm{d}\boldsymbol{x}_i$$其中 $\boldsymbol{x}$ 是一个向量, $\boldsymbol{x}</em>{i}$ 是 $\boldsymbol{x}$ 的一个分量,  $\boldsymbol{x}<em>{-i}$ 是除了 $\boldsymbol{x}</em>{i}$ 以外的分量集合.更一般的, 可以将 $\boldsymbol{x}$ 拆分成互斥的分量集合, 然后像这样嵌套积分.因此$$\begin{aligned}\mathcal{L}(q) &= \int q_j\prod_{i \not= j}q_i\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}})\mathrm{d}\boldsymbol{\mathrm{z}} - \int \prod_{i}q_i\sum_i \ln q_i\mathrm{d}\boldsymbol{\mathrm{z}}\\\\&= \int\left\{\int q_j\prod_{i \not= j}q_i\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}})\mathrm{d}\boldsymbol{\mathrm{z}}_{i\not=j}\right\}\mathrm{d}\boldsymbol{\mathrm{z}}_j - \int \prod_{i}q_i\sum_i \ln q_i\mathrm{d}\boldsymbol{\mathrm{z}}\end{aligned}$$**为了表达更清晰, 这里的符号和西瓜书稍稍不同, 这里 $\mathrm{d}\boldsymbol{\mathrm{z}}<em>{i\not  =j}$ 代表了对除了 $\boldsymbol{\mathrm{z}}</em>{i}$ 以外的分量积分, 西瓜书应该也是表达这个意思, 但是符号不太清晰.**同时由于 $q<em>j$ 与 $\boldsymbol{\mathrm{z}}</em>{i\not=j}$ 没有关系, 所以提出积分$$\begin{aligned}\mathcal{L}(q) &= \int\left\{\int q_j\prod_{i \not= j}q_i\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}})\mathrm{d}\boldsymbol{\mathrm{z}}_{i\not=j}\right\}\mathrm{d}\boldsymbol{\mathrm{z}}_j - \int \prod_{i}q_i\sum_i \ln q_i\mathrm{d}\boldsymbol{\mathrm{z}}\\\\&= \int q_j\left\{\int \prod_{i \not= j}q_i\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}})\mathrm{d}\boldsymbol{\mathrm{z}}_{i\not=j}\right\}\mathrm{d}\boldsymbol{\mathrm{z}}_j - \int \prod_{i}q_i\sum_i \ln q_i\mathrm{d}\boldsymbol{\mathrm{z}}\end{aligned}$$我们单独取后一项进行进一步分析$$\int \prod_{i}q_i\sum_i \ln q_i\mathrm{d}\boldsymbol{\mathrm{z}} = \int \left(\sum_i\left\{\prod_{i}q_i\right\}\ln q_i\right)\mathrm{d}\boldsymbol{\mathrm{z}}$$对于每一个 $\int \left(\left{\prod<em>{i}q_i\right}\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}}$ 来说, 有$$\begin{aligned}\int \left(\left\{\prod_{i}q_i\right\}\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}} &= \int\left\{\int \left(q_j\left\{\prod_{i\not=j}q_i\right\}\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}}_{i\not = j}\right\}\mathrm{d}\boldsymbol{\mathrm{z}}_j\end{aligned}$$由于 $q_j$ 与 $\boldsymbol{\mathrm{z}}_i$ 没有关系, 于是可以提出积分$$\begin{aligned}\int \left(\left\{\prod_{i}q_i\right\}\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}} &= \int q_j\left\{\int \left(\left\{\prod_{i\not=j}q_i\right\}\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}}_{i\not = j}\right\}\mathrm{d}\boldsymbol{\mathrm{z}}_j\end{aligned}$$注意到 $\left{\int \left(\left{\prod</em>{i\not=j}q_i\right}\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}}_i\right}$ 与 $\boldsymbol{\mathrm{z}}_j$ 也没有关系, 而且 $\int q_j \mathrm{d}\boldsymbol{\mathrm{z}}_j = 1$ , 于是$$\begin{aligned}\int \left(\left\{\prod_{i}q_i\right\}\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}} &= \int q_j\left\{\int \left(\left\{\prod_{i\not=j}q_i\right\}\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}}_{i\not = j}\right\}\mathrm{d}\boldsymbol{\mathrm{z}}_j\\\\&= \int \left(\left\{\prod_{i\not=j}q_i\right\}\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}}_{i\not = j}\end{aligned}$$事实上, 可以一直反复这种提取, 消去的过程, 最终得到$$\begin{aligned}\int \left(\left\{\prod_{i}q_i\right\}\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}} &= \int \left(q_k\ln q_k\right)\mathrm{d}\boldsymbol{\mathrm{z}}_k\end{aligned}$$于是$$\begin{aligned}\int \prod_{i}q_i\sum_i \ln q_i\mathrm{d}\boldsymbol{\mathrm{z}} &= \int \left(\sum_i\left\{\prod_{i}q_i\right\}\ln q_i\right)\mathrm{d}\boldsymbol{\mathrm{z}}\\\\&= \int \sum_i q_i\ln q_i\mathrm{d}\boldsymbol{\mathrm{z}}_i\\\\&= \int q_j\ln q_j\mathrm{d}\boldsymbol{\mathrm{z}}_j + \int \sum_{i\not=j} q_i\ln q_i\mathrm{d}\boldsymbol{\mathrm{z}}_{i\not = j}\\\\&= \int q_j\ln q_j\mathrm{d}\boldsymbol{\mathrm{z}}_j + \mathrm{const}\end{aligned}$$我们只关心与 $\boldsymbol{\mathrm{z}}_j$ 有关的变量, 因此后面的项可以当作常量 $\mathrm{const}$ .因此$$\begin{aligned}\mathcal{L}(q) &= \int q_j\left\{\int \prod_{i \not= j}q_i\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}})\mathrm{d}\boldsymbol{\mathrm{z}}_{i\not=j}\right\}\mathrm{d}\boldsymbol{\mathrm{z}}_j - \int \prod_{i}q_i\sum_i \ln q_i\mathrm{d}\boldsymbol{\mathrm{z}}\\\\&=\int q_j\left\{\int \ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}})\prod_{i \not= j}q_i\mathrm{d}\boldsymbol{\mathrm{z}}_{i\not=j}\right\}\mathrm{d}\boldsymbol{\mathrm{z}}_j - \int q_j\ln q_j\mathrm{d}\boldsymbol{\mathrm{z}}_j + \mathrm{const}\\\\&= \int q_j\ln\tilde{p}(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)\mathrm{d}\boldsymbol{\mathrm{z}}_j - \int q_j\ln q_j\mathrm{d}\boldsymbol{\mathrm{z}}_j + \mathrm{const}\end{aligned}$$(理解倒是不难, 可是这公式也太多了吧...写了我好长一段时间..公式是真的难写...) #### 式 14.40 推导$$\begin{aligned}\ln \tilde{p}(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j) &= \mathbb{E}_{i\not=j}[\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)] + \mathrm{const}\\\\\tilde{p}(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)&= \exp(\mathbb{E}_{i\not=j}[\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)]) \cdot  \exp(\mathrm{const})\end{aligned}$$而又因为$$\begin{aligned}\int \tilde{p}(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)\mathrm{d}\boldsymbol{\mathrm{z}}_j &= 1\\\\\int \exp(\mathbb{E}_{i\not=j}[\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)]) \cdot  \exp(\mathrm{const})\mathrm{d}\boldsymbol{\mathrm{z}}_j&= 1\\\\ \exp(\mathrm{const})&=\frac{1}{\int \exp(\mathbb{E}_{i\not=j}[\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)])\mathrm{d}\boldsymbol{\mathrm{z}}_j}\end{aligned}$$于是$$\begin{aligned}\tilde{p}(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)&= \exp(\mathbb{E}_{i\not=j}[\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)]) \cdot  \exp(\mathrm{const})\\\\&= \frac{\exp(\mathbb{E}_{i\not=j}[\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)])}{\int \exp(\mathbb{E}_{i\not=j}[\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)])\mathrm{d}\boldsymbol{\mathrm{z}}_j}\end{aligned}$$由于 $q_j^*(\boldsymbol{\mathrm z}_j) = \tilde{p}(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)$ , 因此$$q_j^*(\boldsymbol{\mathrm z}_j) = \frac{\exp(\mathbb{E}_{i\not=j}[\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)])}{\int \exp(\mathbb{E}_{i\not=j}[\ln p(\boldsymbol{\mathrm{x}}, \boldsymbol{\mathrm{z}}_j)])\mathrm{d}\boldsymbol{\mathrm{z}}_j}$$</p><h2 id="话题模型"><a href="#话题模型" class="headerlink" title="话题模型"></a>话题模型</h2><p>其实就是一个具体的模型, 理解了前面的内容这里应该也没什么问题. 当然这只是看懂, 如果要理解背后的原理, 就需要<del>亿点点</del>数学基础了.</p><p>最近看了 <a href="https://bloglxm.oss-cn-beijing.aliyuncs.com/lda-LDA%E6%95%B0%E5%AD%A6%E5%85%AB%E5%8D%A6.pdf">LDA 数学八卦</a>, 感觉写的还是很不错的, 公式一遍遍细细的看, 是能够看懂的, 想要了解 LDA 的推荐看一看.</p><hr><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><h2 id="网络资料"><a href="#网络资料" class="headerlink" title="网络资料"></a>网络资料</h2><ul><li><a href="https://www.bilibili.com/video/av70839977">白板推导</a></li><li><a href="https://datawhalechina.github.io/pumpkin-book">南瓜书</a></li><li><a href="https://bloglxm.oss-cn-beijing.aliyuncs.com/lda-LDA%E6%95%B0%E5%AD%A6%E5%85%AB%E5%8D%A6.pdf">LDA 数学八卦</a></li></ul><h2 id="书籍"><a href="#书籍" class="headerlink" title="书籍"></a>书籍</h2><ul><li>《统计学习方法》李航</li></ul>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 模型 </category>
          
          <category> 西瓜书 </category>
          
          <category> 读懂西瓜书 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 概率图模型 </tag>
            
            <tag> 西瓜书 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>优化算法汇总</title>
      <link href="/ML/optimizer/optimizer_all/"/>
      <url>/ML/optimizer/optimizer_all/</url>
      
        <content type="html"><![CDATA[<p>许多机器学习算法都是为了找到损失函数的最小值, 而损失函数是一个关于参数 $$w$$ 的函数. 但是很多算法并没有闭式解, 因此需要优化算法来帮助找到最小值. 这篇博文并不详细讲解优化算法, 只作简单介绍.<br><span id="more"></span></p><blockquote class="pullquote mindmap mindmap-md"><ul><li>优化算法<ul><li>数值优化法<ul><li>梯度下降法<ul><li>批量梯度下降 (BGD)</li><li>随机梯度下降 (SGD)</li><li>小批量梯度下降 (MBGD)</li></ul></li><li>基于梯度下降法的衍生算法<ul><li>动量法 (Momentum)</li><li>Nesterov Accelerated Gradient</li><li>AdaGrad</li><li>RMSProp</li><li>AdaDelta</li></ul></li><li>牛顿法</li></ul></li><li>其他方法<ul><li>EM 算法</li><li>拉格朗日乘子法</li></ul></li></ul></li></ul></blockquote><h1 id="数值优化法"><a href="#数值优化法" class="headerlink" title="数值优化法"></a>数值优化法</h1><h2 id="梯度下降法"><a href="#梯度下降法" class="headerlink" title="梯度下降法"></a>梯度下降法</h2><p><img src="1.jpg" alt=""></p><h3 id="批量梯度下降-BGD"><a href="#批量梯度下降-BGD" class="headerlink" title="批量梯度下降 (BGD)"></a>批量梯度下降 (BGD)</h3><p>批量梯度下降大概是最经典的优化算法之一吧, 也是很多人入门机器学习学的第一个优化算法. 梯度下降的原理就在于 “梯度” , “梯度” 就是函数变化率最大的方向, 一直向着梯度的反方向 “行走” , 值就会变得越来越小, 直到梯度为 0 才停止, 此时则达到了最小值 (可能是局部最小值与全局最小值, 或是鞍点) .</p><h3 id="随机梯度下降-SGD"><a href="#随机梯度下降-SGD" class="headerlink" title="随机梯度下降 (SGD)"></a>随机梯度下降 (SGD)</h3><p>如果数据集过大, 那么每次计算梯度都需要遍历整个数据集, 这样消耗的时间太久, 导致训练过慢, 由此引进了随机梯度下降. 随机梯度下降每次训练只使用一个数据, 大大加快了计算梯度的效率, 同时, 还可以跳出局部最小值. 但是也导致了一个问题, 就是每次下降的方向都不一定是最优的, 甚至可能往反方向进行, 因此较难收敛, 为了解决这个问题, 产生了 $\mathrm{mini-batch\,(MBGD)}$ .</p><h3 id="小批量梯度下降-MBGD"><a href="#小批量梯度下降-MBGD" class="headerlink" title="小批量梯度下降 (MBGD)"></a>小批量梯度下降 (MBGD)</h3><p>&nbsp;$\mathrm{MBGD}$ 结合了 $\mathrm{BGD}$ 和 $\mathrm{SGD}$ 的优点, 一次只训练一小部分训练集, 即保证了梯度的方向大致是正确的, 又保证了更新的速度. 算是一种折中的做法, 效果也是很不错.</p><h2 id="基于梯度下降法的衍生算法"><a href="#基于梯度下降法的衍生算法" class="headerlink" title="基于梯度下降法的衍生算法"></a>基于梯度下降法的衍生算法</h2><h3 id="动量法-Momentum"><a href="#动量法-Momentum" class="headerlink" title="动量法 (Momentum)"></a>动量法 (Momentum)</h3><p>有时候, 某些方向的梯度过大时, 那么就有可能造成震荡, 导致收敛过慢, 甚至无法收敛. 由此引进了动量法.</p><p>动量法通过对历史梯度进行指数加权来平滑优化轨迹, 如果历史梯度与当前相反 (也就是说会 “震荡”) , 那么就会相应减少步长, 以达到 “平滑” 的目的.</p><h3 id="Nesterov-Accelerated-Gradient"><a href="#Nesterov-Accelerated-Gradient" class="headerlink" title="Nesterov Accelerated Gradient"></a>Nesterov Accelerated Gradient</h3><p>动量法的改进算法, 可以看作是更 “高瞻远瞩” 的动量法, 性能比动量法好很多.</p><h3 id="AdaGrad"><a href="#AdaGrad" class="headerlink" title="AdaGrad"></a>AdaGrad</h3><p>动量法是通过改变步长来防止发散, 而 $\mathrm{AdaGrad}$ 是通过给不同的变量赋予不同的、动态变化的学习率来防止发散. 其原理是根据历史梯度的绝对值来降低学习率 (降低的大小不同), 直观上来看, 如果历史梯度绝对值一直比较大, 就会降低学习率. 但是由于降低的过程是一直累加, 所以到训练后期学习率会过小, 难以产生有用的解, 因此又产生了它的改进算法: $\mathrm{RMSProp}$ 与 $\mathrm{AdaDelta}$ .</p><h3 id="RMSProp"><a href="#RMSProp" class="headerlink" title="RMSProp"></a>RMSProp</h3><p> &nbsp;$\mathrm{RMSProp}$ 和 $\mathrm{AdaGrad}$ 的区别在于, $\mathrm{AdaGrad}$ 对历史梯度是一直累加, 而 $\mathrm{RMSProp}$ 是通过指数加权历史梯度来防止步长过小.</p><h3 id="AdaDelta"><a href="#AdaDelta" class="headerlink" title="AdaDelta"></a>AdaDelta</h3><p>&nbsp;$\mathrm{AdaDelta}$ 又对 $\mathrm{RMSProp}$ 作了进一步的改进, 将参数 $\mu$ 也用指数加权替代了.</p><h2 id="牛顿法-Newton-Method"><a href="#牛顿法-Newton-Method" class="headerlink" title="牛顿法 (Newton Method)"></a>牛顿法 (Newton Method)</h2><p>牛顿法是对泰勒展开的应用. 一般比梯度下降收敛的速度要快很多. 但是对于多维变量, 由于要求矩阵的二阶导 (也就是 $\mathrm{Hessen}$ 矩阵) , 所以会比较麻烦.</p><h1 id="其他方法"><a href="#其他方法" class="headerlink" title="其他方法"></a>其他方法</h1><h2 id="EM-算法"><a href="#EM-算法" class="headerlink" title="EM 算法"></a>EM 算法</h2><p>&nbsp;$\mathrm{EM}$ 算法一般用来估计隐变量, 总结一句话: 我 迭 代 我 自 己.</p><h2 id="拉格朗日乘子法"><a href="#拉格朗日乘子法" class="headerlink" title="拉格朗日乘子法"></a>拉格朗日乘子法</h2><p>拉格朗日乘子法通过引入拉格朗日乘子, 可将有 $d$ 个变量与 $k$ 个约束条件的最优化问题转化为具有 $d + k$ 个变量的无约束优化问题求解.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 优化算法 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 优化算法 </tag>
            
        </tags>
      
    </entry>
    
    
    
    
    
    <entry>
      <title>棋类游戏有必胜策略吗</title>
      <link href="/math/other/chess_strategy/"/>
      <url>/math/other/chess_strategy/</url>
      
        <content type="html"><![CDATA[<p>现在在棋类游戏这方面, AI 已经完胜人类. 即使是最复杂的围棋, 人类也败下阵来. 那么, 是否存在一种策略, 使得黑方或白方必胜呢. 如果这种策略存在, 那么棋类游戏还有其存在意义吗?</p><h1 id="策梅洛-Zermelo-定理"><a href="#策梅洛-Zermelo-定理" class="headerlink" title="策梅洛 (Zermelo) 定理"></a>策梅洛 (Zermelo) 定理</h1><p>在 1913 年, 策梅洛 (Zermelo) 证明了策梅洛定理, 定理表示在二人的有限游戏中，如果双方皆拥有完全的资讯, 并且运气因素并不牵涉在游戏中, 那先行或后行者当中必有一方有必胜/必不败的策略. 若运用至国际象棋, 则策梅洛定理表示 “要么黑方有必胜之策略、要么白方有必胜之策略、要么双方也有必不败之策略” .<br>策梅洛的论文于1913年以德文发表, 并被 Ulrich Schwalbe 和 Paul Walker 于1997年译为英文.<br>很明显棋类游戏符合上述 “有限游戏”, “拥有完全资讯”, “不包括运气因素” 的要求, 因此是存在必胜或不败的策略的.</p><h1 id="证明"><a href="#证明" class="headerlink" title="证明"></a>证明</h1><p>最让我惊奇的是这条定理的证明如此简单, 只需利用数学归纳法.<br>首先我们定义这个有限游戏的结局, 即黑方胜, 白方胜, 以及平局, 规定在游戏开始后第 m 步如果没有分出胜负则是平局.<br>我们先考虑差一步就可以得到结局的局面, 假设此时是黑方做出决策 (在这里黑方和白方是相对的, 不存在哪一方先手) 此时显然有三种互斥的结局.</p><ul><li>如果这一步可以获胜, 那么黑方有必胜策略, 白方必败.</li><li>这一步怎么走都会败, 那么黑方必败, 白方有必胜策略.</li><li>如果不胜也不败, 那么会平局, 则双方有不败策略.</li></ul><p>假设第 n+1 步的局面要么有某方必胜策略, 要么有不败策略, 这里证明对于 n 步的局面也同样如此.<br>如果第 n 步是黑方做出决策, 那么有互斥的三种情况</p><ul><li>存在一种策略可以导向黑方必胜 (也就是第 n+1 步黑方必胜局面) 局面, 那么黑方有必胜策略.</li><li>所有策略都会导向白方必胜 (也就是第 n+1 步白方必胜局面), 那么黑方必输, 白方有必胜策略.</li><li>所有策略黑方都不败不胜 (也就是第 n+1 步双方不败局面), 那么双方必平局.</li></ul><p>因此递推成立, 数学归纳法证明完成.</p><h1 id="思考"><a href="#思考" class="headerlink" title="思考"></a>思考</h1><p>虽然必然存在必胜或不败策略, 但是并不知道怎样的策略和哪方先手可以必胜、不败, 而且要找出这样的策略也应该是十分困难的, 所以棋类游戏仍然还有其意义. 而且就算找到了这样的 “完美策略” , 那么也不是人类能够掌握的 (时间, 空间复杂度太高).</p>]]></content>
      
      
      <categories>
          
          <category> 数学 </category>
          
          <category> 其他 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数学 </tag>
            
            <tag> 博弈论 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>史上最全的 Hexo 博客搭建配置完全指南</title>
      <link href="/hexo/Hexo_blog_build/"/>
      <url>/hexo/Hexo_blog_build/</url>
      
        <content type="html"><![CDATA[<p>本篇博客基于 <code>Centos 7.x</code> root 用户.<br>最近利用 Hexo + Github Pages 搭建了一个博客, 总体来说比较满意, 中间也踩了不少坑. 于是将我的配置过程全部记录下来, 就有了这篇博文.<br>关于 Hexo 搭建配置的博文网上还是挺多的, 但是零零散散, 这篇博文就当成是一个大合集吧. 废话不多说, 下面开始我们的正篇.</p><h1 id="搭建"><a href="#搭建" class="headerlink" title="搭建"></a>搭建</h1><h2 id="准备环境"><a href="#准备环境" class="headerlink" title="准备环境"></a>准备环境</h2><h3 id="安装-Git"><a href="#安装-Git" class="headerlink" title="安装 Git"></a>安装 Git</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo yum install git-core</span><br></pre></td></tr></table></figure><h3 id="安装-Node-js"><a href="#安装-Node-js" class="headerlink" title="安装 Node.js"></a>安装 Node.js</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">wget -qO- https://raw.github.com/creationix/nvm/master/install.sh | sh</span><br><span class="line">source ~/.bash_profile</span><br><span class="line">nvm install stable</span><br></pre></td></tr></table></figure><h3 id="安装-Hexo"><a href="#安装-Hexo" class="headerlink" title="安装 Hexo"></a>安装 Hexo</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mkdir hexo</span><br><span class="line">npm install -g hexo-cli</span><br><span class="line">cd hexo/</span><br><span class="line">hexo init</span><br></pre></td></tr></table></figure><p>测试服务</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo server</span><br></pre></td></tr></table></figure><p>这时你可以打开浏览器访问 <a href="http://localhost:4000">http://localhost:4000</a> 就可以看到你刚刚搭建成功的博客页面了. 当然如果你使用的是云服务器, 那么同样可以打开 <a href="">(云服务器的 ip):4000</a> 来访问博客.</p><h2 id="将博客部署到-Github"><a href="#将博客部署到-Github" class="headerlink" title="将博客部署到 Github"></a>将博客部署到 Github</h2><p>把博客部署到 Github 是大多数站长的选择. </p><h3 id="注册-Github-账号"><a href="#注册-Github-账号" class="headerlink" title="注册 Github 账号"></a>注册 Github 账号</h3><p>首先你要有一个 Github 账号 (已有账号可以跳过), <a href="https://github.com/">点此</a>前往注册. 输入你的邮箱和你起的用户名, 密码就可以注册了. 这里我们假设你的用户名为 <code>cnyist</code> 邮箱为 <code>371622558@qq.com</code> (下面所有出现用户名和邮箱的内容换成你自己的就好了).</p><h3 id="设置-user-name-和-user-email"><a href="#设置-user-name-和-user-email" class="headerlink" title="设置 user.name 和 user.email"></a>设置 user.name 和 user.email</h3><p>这里要给 git 设置变量.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git config --global user.name &quot;cnyist&quot;</span><br><span class="line">git config --global user.email &quot;371622558@qq.com&quot;</span><br></pre></td></tr></table></figure><h3 id="配置-SSH-密匙"><a href="#配置-SSH-密匙" class="headerlink" title="配置 SSH 密匙"></a>配置 SSH 密匙</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa -C user.email</span><br><span class="line">/root/.ssh/id_rsa</span><br></pre></td></tr></table></figure><p>然后直接输入回车回车.<br>这时进入到 <code>/root/.ssh/</code> 目录下查看 <code>id_rsa.pub</code> 文件, 你可以使用如下命令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vi /root/.ssh/id_rsa.pub</span><br></pre></td></tr></table></figure><p>这时就用 vim 打开了该文件, 复制文件里的所有内容 (所有内容, 一个字符都不要漏) . 然后<a href="https://github.com/settings/keys">到 Github 添加 ssh 密匙</a>.<br>点击 <code>New SSH key</code> 按钮进行添加<br><img src="1.png" alt=""><br><img src="2.png" alt=""><br>点击 <code>Add SSH key</code>确认添加.</p><h3 id="创建仓库"><a href="#创建仓库" class="headerlink" title="创建仓库"></a>创建仓库</h3><p>在登陆状态下打开 <a href="https://github.com/">Github 主页</a>, 点击 <code>New</code> 创建新仓库.<br><img src="3.png" alt=""><br>这里要注意, 这个仓库的命名是有一定格式的, 格式是: 用户名.github.io,<br>比如我的就是 blog (还记得我之前说的吗, 出现用户名和邮箱通通换成你自己的就好了).<br><img src="4.png" alt=""><br>点击 <code>Create repository</code> 创建该仓库. 由于我已经创建了这个仓库, 所以有报错.</p><h3 id="配置-config-yml"><a href="#配置-config-yml" class="headerlink" title="配置 _config.yml"></a>配置 _config.yml</h3><p>进入到博客根目录 (也就是一个名字叫 hexo 的目录, 一般在你的主目录下),<br>打开一个名字叫 _config.yml 的文件, 找到 <code>deploy</code> 这个部分, 修改成如下内容:</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span></span><br><span class="line">    <span class="attr">type:</span> <span class="string">git</span></span><br><span class="line">    <span class="attr">repo:</span> <span class="string">git@github.com:cnyist/blog.git</span></span><br><span class="line">    <span class="attr">branch:</span> <span class="string">master</span></span><br></pre></td></tr></table></figure><p>保存一下. (将所有用户名和邮箱都改成自己的, 这已经是第三次提醒了哦~)</p><h3 id="部署"><a href="#部署" class="headerlink" title="部署"></a>部署</h3><p>清空静态页面</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo cl</span><br></pre></td></tr></table></figure><p>生成静态页面</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo g</span><br></pre></td></tr></table></figure><p>先运行下面这条命令否则直接部署会报错</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-deployer-git --save</span><br></pre></td></tr></table></figure><p>然后将 public 文件内容部署到 Github 仓库</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo d</span><br></pre></td></tr></table></figure><p><code>hexo cl&amp;&amp;hexo g&amp;&amp;hexo d</code> 称为部署三件套.<br>此时你的个人博客就部署成功啦! 你可以通过访问 <a href="https://blog">https://blog</a> 来浏览你的博客页面 (还记得前面提示了三次啥吗~) .<br>这已经算是一个完整的 Hexo 博客了, 之后会有进一步的美化配置教程.</p><h2 id="Hexo-发布文章简单介绍"><a href="#Hexo-发布文章简单介绍" class="headerlink" title="Hexo 发布文章简单介绍"></a>Hexo 发布文章简单介绍</h2><p>在 Hexo 博客目录内 (包括其子目录) 执行</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new &quot;文章名&quot;</span><br></pre></td></tr></table></figure><p>就会在 <code>hexo/source/_posts</code> 下创建一个 <code>文章名.md</code> 文件, 里面可以写下你的 markdown 文章, 然后通过执行部署三件套, 就能部署到你的个人博客里.</p><h3 id="Front-matter"><a href="#Front-matter" class="headerlink" title="Front-matter"></a>Front-matter</h3><p>在文章正文前, 一般都有由两行 <code>---</code> 包起来的内容, 称为 Front-matter .在 Hexo 官方文档里, 是这么说的</p><blockquote><p>Front-matter 是文件最上方以 <code>---</code> 分隔的区域，用于指定个别文件的变量.</p></blockquote><p>比如</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: Hello World</span><br><span class="line"><span class="section">date: 2013/7/13 20:46:25</span></span><br><span class="line"><span class="section">---</span></span><br></pre></td></tr></table></figure><p>干什么的应该从名字就能看出来. 这里不过多介绍如何写文章, <a href="https://hexo.io/zh-cn/docs/">官方文档</a>已经写得很详细了.</p><h3 id="文章资源文件夹"><a href="#文章资源文件夹" class="headerlink" title="文章资源文件夹"></a>文章资源文件夹</h3><p>文章资源文件夹一般是用于存放文章的图片, 方便管理. 进入站点 <code>_config.yml</code> 将 <code>post_asset_folder</code> 选项设置为 <code>true</code></p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">post_asset_folder:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>打开该选项后, 如果你使用 <code>hexo new &quot;文章名&quot;</code> 来创建文章, 会在同一目录生成同名文件夹. 如果在里面放了图片 <code>abc.png</code> , 那么你就可以使用 <code>![](abc.png)</code> 这样的 markdown 语法来引用该图片 (<strong>在 markdown 编辑器中可能无法正确显示, 但是部署上去是完全正常的</strong>) . 这样就能实现使用相对路径引用图片.</p><h2 id="config-yml-配置介绍"><a href="#config-yml-配置介绍" class="headerlink" title="_config.yml 配置介绍"></a>_config.yml 配置介绍</h2><p>_config.yml 这个文件我们前面已经更改过它一次了, 就是在配置部署的时候, 还记得吗? 这是整个 Hexo 博客的配置文件, 现在我们列出主要需要更改的地方, 按照关键字去查找更改就好了.</p><ul><li><strong>所有配置的配置名和配置值都要隔一个空格, 比如说 title 这个配置, 必须要写成 <code>title: 云玩家</code> 而不可以写成 <code>title:云玩家</code>. 前后是一个空格的区别!!! 这是 yaml (即以 <code>.yml</code> 为后缀的文件) 的语法, 要严格遵守.</strong></li></ul><h3 id="site"><a href="#site" class="headerlink" title="site"></a>site</h3><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Site</span></span><br><span class="line"><span class="attr">title:</span> <span class="comment"># 网站标题</span></span><br><span class="line"><span class="attr">subtitle:</span> <span class="comment"># 网站副标题</span></span><br><span class="line"><span class="attr">description:</span> <span class="comment"># 网站描述</span></span><br><span class="line"><span class="attr">keywords:</span> <span class="comment"># 网站关键词</span></span><br><span class="line"><span class="attr">author:</span> <span class="comment"># 网站作者</span></span><br><span class="line"><span class="attr">language:</span> <span class="comment"># 语言, 一般填 &#x27;zh-CN&#x27;</span></span><br><span class="line"><span class="attr">timezone:</span> <span class="comment"># 时区, 可以不填</span></span><br></pre></td></tr></table></figure><p>暂时就这一项需要配置.</p><h1 id="美化"><a href="#美化" class="headerlink" title="美化"></a>美化</h1><h2 id="更换域名"><a href="#更换域名" class="headerlink" title="更换域名"></a>更换域名</h2><p>我们常常看到别人的博客域名并不是 xxxx.github.io 形式的, 而是其他的域名. 这是因为别人绑定了自己的域名. 下面就来教你如何绑定自己的域名.</p><h3 id="购买域名"><a href="#购买域名" class="headerlink" title="购买域名"></a>购买域名</h3><p>首先, 你要拥有一个域名, 域名可以在很多地方买到, 比如阿里云, 腾讯云等等. 不同的域名价格也不同, 但是基本上都不是很贵. 购买域名过程中的实名等等步骤这里就不再详细讲解.</p><h3 id="域名解析"><a href="#域名解析" class="headerlink" title="域名解析"></a>域名解析</h3><p>购买了域名后, 可以添加解析到你的 Github Pages. 下面我们以腾讯云为例. 首先在你的域名管理处找到你要解析的域名, 点击 <code>解析</code> 按钮, 进入解析界面. 然后点添加记录, 就可以添加解析记录了.<br>这条解析记录我们需要填的有 6 个值, 分别是 <code>主机记录</code>, <code>记录类型</code>, <code>线路类型</code>, <code>记录值</code>, <code>TTL</code>. 下面我们来一一说明.</p><p>主机记录: 主机记录其实就是域名前缀, 比如说 www.xxxx.com, 域名其实就是 xxxx.com, 而主机记录是 www. 一般博客的主机记录可以设置为 blog, 比如我的博客就是 <a href="https://yunist.cn">yunist.cn</a>. blog 是我的域名主机记录, 我的域名是 <code>yunist.cn</code>. 当然有些前缀比较特殊, 比如说 <code>*</code>, <code>*</code> 是指泛解析, 就是说可以解析所有前缀. 还有就是 <code>@</code>, 这个前缀是说解析主域名, 也就是不带任何前缀.</p><p>记录类型: 这里不详细说明所有的记录类型, 只说明我们要用到的 <code>CHAME</code> 解析, 即指向另一个域名 (所以你这里应该知道要填啥了吧. 对了! 就是 CHAME).</p><p>线路类型: 我们这里填默认就好 (其他选项到后面双部署的时候会用到).</p><p>TTL: 这个值是你的解析记录在 DNS 中的缓存时间, 你可以简单理解为, TTL 值越大, 解析会越快, 但是一旦更改, 更改生效的时间就会更久. 我是设置为默认的 600秒, 即 10 分钟.</p><p>所有值填完之后就可以点击 <code>保存</code> 添加解析记录了.</p><h3 id="Github-Pages-添加解析"><a href="#Github-Pages-添加解析" class="headerlink" title="Github Pages 添加解析"></a>Github Pages 添加解析</h3><p>创建 CHAME 文件</p><p>进入 hexo 主目录并输入以下命令</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">touch source/CNAME</span><br></pre></td></tr></table></figure><p>进入该文件并添加你刚刚解析的域名, 记得要加上你的前缀, 比如你解析的是 blog 主机记录, 你就要写上 blog.xxxx.com (这里域名为 xxxx.com). 比如我的就写 <a href="https://yunist.cn">yunist.cn</a>.<br>最后执行部署三件套 <code>hexo cl&amp;&amp;hexo g&amp;&amp;hexo d</code> 后就可以用你自己的域名访问你的博客啦!</p><h2 id="修改博客默认主题"><a href="#修改博客默认主题" class="headerlink" title="修改博客默认主题"></a>修改博客默认主题</h2><p>大家可以看到<a href="https://yunist.cn">我的博客</a>界面很好看, 而且还有很多不同的博客界面, 这就涉及到主题的配置了. 这里配置主题以 <a href="https://github.com/jerryc127/hexo-theme-Butterfly">Butterfly</a> 这个主题为例. <strong>现在我的博客已开源, 你也可以直接使用我的源码达到我博客的效果, 详情请看 <a href="https://yunist.cn/hexo/hexo_modify_theme_butterfly/">Hexo modify theme butterfly</a>.</strong></p><h3 id="下载主题并使用"><a href="#下载主题并使用" class="headerlink" title="下载主题并使用"></a>下载主题并使用</h3><p>在 Hexo 根目录下执行命令</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone -b master https://github.com/jerryc127/hexo-theme-Butterfly.git themes/Butterfly</span><br></pre></td></tr></table></figure><p>如果没有 cheerio 则需要安装</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install cheerio --save</span><br></pre></td></tr></table></figure><p>下载 Butterfly 主题. 然后就会看到根目录下 theme 这个文件夹里多了一个 Butterfly 文件夹. 进入博客根目录的 _config.yml 文件 (不是 theme 里的哦), 找到 theme 这一项, 把值改为 Butterfly.<br><img src="5.png" alt=""><br>然后部署三件套, 之后再打开你的博客, 大概率会发现无法正常打开, 那么这时候需要安装 pug 以及 stylus 的渲染器</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-renderer-pug hexo-renderer-stylus --save</span><br></pre></td></tr></table></figure><p>重新部署就会发现你的博客大变样了.</p><h3 id="配置主题"><a href="#配置主题" class="headerlink" title="配置主题"></a>配置主题</h3><p>此时就要配置我们的主题了, 配置项大多都在 <code>hexo/themes/Butterfly/_config.yml</code> 这个文件里. 我们打开它. 同样的这里列出建议改动的地方.<br>再次提醒</p><ul><li><strong>所有配置的配置名和配置值都要隔一个空格, 比如说 title 这个配置, 必须要写成 <code>title: 云玩家</code> 而不可以写成 <code>title:云玩家</code>. 前后是一个空格的区别!!! 这是 yaml (即以 <code>.yml</code> 为后缀的文件) 的语法, 要严格遵守.</strong></li></ul><p>banner: 查找 banner 关键字, 可以修改默认 banner 为你自己的图片. 什么是banner 呢, 其实就是博客里页面中的各种图片 (不是文章里的图片).<br>比如这三项</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># the banner image of archive page</span></span><br><span class="line"><span class="attr">archive_img:</span> <span class="string">new_3.jpg</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># the banner image of tag page</span></span><br><span class="line"><span class="attr">tag_img:</span> <span class="number">7.</span><span class="string">jpg</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># the banner image of category page</span></span><br><span class="line"><span class="attr">category_img:</span> <span class="string">new_5.jpg</span></span><br></pre></td></tr></table></figure><p>分别代表归档, 标签, 分类页的 banner (该页面上面的大图). 当然还有 index 的banner (主页). 这里要注意, 所谓标签, 分类页的 banner 代表的是具体标签, 分类里的图, 而不是标签, 分类. 分类的图 <del>(好吧你们肯定听不懂我在说啥)</del>. 下面看例子<br>这是标签<br><img src="6.png" alt="标签"><br>这是具体标签<br><img src="7.png" alt="具体标签"><br>明白区别了吗, 标签包含了具体标签, 具体标签被标签包含!!<br>所以上面更改的是具体标签的图, 当然两个都可以改成同一个, 我就是这么做的. 标签页如何更改要具体看下面 <code>文章 cover</code> 的内容.</p><p>favicon: 即网站图标</p><p>social: 可以更改为你的社交账号如 Github, QQ邮箱等</p><p>avatar: 即头像</p><p>canvas_ribbon: 即各种彩带特效, 可以自己一个个开启试试效果</p><h2 id="menu-介绍"><a href="#menu-介绍" class="headerlink" title="menu 介绍"></a>menu 介绍</h2><p>通过修改 menu , 可以实现增加, 减少页面. 比如有些博客有 <code>关于我(about)</code> 页面, 有些博客有 <code>影视</code>, <code>音乐</code> 等界面. 这些都是通过生成页面并修改 menu 实现的.</p><h3 id="修改-menu"><a href="#修改-menu" class="headerlink" title="修改 menu"></a>修改 menu</h3><p>进入博客主题的 _config.yml 配置文件, 搜索 <code>menu</code> 关键字, 就可以快速找到 menu 的配置项. 可能长这个样子</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">menu:</span></span><br><span class="line">  <span class="attr">Home:</span> <span class="string">/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-home</span></span><br><span class="line">  <span class="attr">Archives:</span> <span class="string">/archives/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-archive</span></span><br><span class="line">  <span class="attr">Tags:</span> <span class="string">/tags/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-tags</span></span><br><span class="line">  <span class="attr">Categories:</span> <span class="string">/categories/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-folder-open</span></span><br><span class="line">  <span class="attr">Link:</span> <span class="string">/link/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-link</span></span><br><span class="line">  <span class="attr">About:</span> <span class="string">/about/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-heart</span></span><br><span class="line">  <span class="string">List||fa</span> <span class="attr">fa-list:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">Music</span> <span class="string">||</span> <span class="string">/music/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-music</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">Movie</span> <span class="string">||</span> <span class="string">/movies/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-film</span></span><br></pre></td></tr></table></figure><p>下面我们来详细介绍.<br>添加一个页面的格式是</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">页面名:</span> <span class="string">/路径/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-图标名</span></span><br></pre></td></tr></table></figure><p>页面名就是页面名 <del>(废话)</del> , 路径是相对于你的博客路径, 比如说你的博客主页是 <a href="https://yunist.cn">yunist.cn</a> , 那么相对路径 <code>/tags/</code> 就是 <a href="https://yunist.cn/tags/">yunist.cn/tags/</a>而图标名可能要说明一下,  hexo博客菜单所使用的图标都是用的 Font Awesome , 它并不是一张图片，你可以理解他就是一种字体. 它为您提供可缩放矢量图标, 它可以被定制大小、颜色、阴影以及任何可以用CSS的样式. 想要了解更多可以看<a href="http://www.fontawesome.com.cn/">中文官网</a>, 想要什么图标也可以上去查它的名字.<br>这里还有一个比较特殊的一项</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">List||fa</span> <span class="attr">fa-list:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">Music</span> <span class="string">||</span> <span class="string">/music/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-music</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">Movie</span> <span class="string">||</span> <span class="string">/movies/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-film</span></span><br></pre></td></tr></table></figure><p>这项其实是生成了一个子菜单, 格式就是</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">子菜单名||fa</span> <span class="string">图标名:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">页面1</span> <span class="string">||</span> <span class="string">/路径1/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-图标名1</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">页面2</span> <span class="string">||</span> <span class="string">/路径2/</span> <span class="string">||</span> <span class="string">fa</span> <span class="string">fa-图标名2</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">....(依此类推)</span></span><br></pre></td></tr></table></figure><h3 id="分类-标签页等的生成"><a href="#分类-标签页等的生成" class="headerlink" title="分类, 标签页等的生成"></a>分类, 标签页等的生成</h3><p>修改了 menu 后, 页面其实并没有生成, 博客一开始是没有这些页面的, 点击会 404. 如何生成这些页面呢?<br><img src="8.png" alt=""><br>执行以下代码</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">hexo new page tags</span><br><span class="line">hexo new page categories</span><br></pre></td></tr></table></figure><p>就可以生成相应页面, 更进一步的, 你可以根据你配置的 menu 生成任意的自定义页面, 即使用</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new page xxxx</span><br></pre></td></tr></table></figure><p>来生成 <code>xxxx</code> 这个页面. 如 <code>about</code> 关于我页面, 只需要执行</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new page about</span><br></pre></td></tr></table></figure><p>就好了.</p><h1 id="增加功能"><a href="#增加功能" class="headerlink" title="增加功能"></a>增加功能</h1><h2 id="添加-mathjax-引擎使博客支持-LaTeX"><a href="#添加-mathjax-引擎使博客支持-LaTeX" class="headerlink" title="添加 mathjax 引擎使博客支持 LaTeX"></a>添加 mathjax 引擎使博客支持 LaTeX</h2><p>LaTeX 数学公式对于我这种写文章经常用数学公式的非常重要, 当然如果你不需要完全可以跳过这段.<br>有很多主题其实已经配置好了 mathjax, 这里来说明如何配置.<br>进入主题的 _config.yml 文件, 找到 mathjax 这一项配置, 改成如下</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mathjax:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="comment"># true 表示每一頁都加載mathjax.js</span></span><br><span class="line">  <span class="comment"># false 需要時加載，須在使用的Markdown Front-matter 加上 mathjax: true</span></span><br><span class="line">  <span class="attr">per_page:</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure><p><code>per_page</code> 这一项最好为 <code>false</code> 这样在不需要数学公式的时候可以节省加载时间. 如果你想在某篇文章使用 mathjax 引擎的话, 就在这个文章的 Front-matter (还记得这是什么吗) 里加入 <code>mathjax: true</code> 就好了.<br>当然有些主题本身没有集成 mathjax, 怎么办呢. 这里给出解决方案.</p><h3 id="使用-Kramed-代替-Marked"><a href="#使用-Kramed-代替-Marked" class="headerlink" title="使用 Kramed 代替 Marked"></a>使用 Kramed 代替 Marked</h3><p>Hexo 默认的渲染引擎是 marked，但是 marked 不支持 mathjax. kramed 是在 marked 的基础上进行修改而来的.<br>执行以下命令</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm uninstall hexo-renderer-marked --save</span><br><span class="line">npm install hexo-renderer-kramed --save</span><br></pre></td></tr></table></figure><h3 id="安装-hexo-renderer-mathjax-包"><a href="#安装-hexo-renderer-mathjax-包" class="headerlink" title="安装 hexo-renderer-mathjax 包"></a>安装 hexo-renderer-mathjax 包</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-renderer-mathjax --save</span><br></pre></td></tr></table></figure><p>重新部署, 成功显示数学公式. 样例<a href="https://yunist.cn/ML/watermelon_book/answer/7/">看这</a>.</p><ul><li><strong>mathjax 默认不渲染由两个美元符号包括在内的公式 (即所谓行内公式), 只渲染由两对美元包括在内的公式 (即所谓行间公式), 而各大博客网站 (如简书, 博客园, CSDN) 所用数学引擎都是 katex (是渲染的), 因此迁移会有一点问题. 而且还有一个问题就是 LaTeX 中的下划线 <code>_</code> 在 markdown 中的含义是斜体, 会发生歧义, 所以我采用了一种笨拙的方法来解决这个问题, 我写了一个 Python 脚本当作 “转换器”, 主要原理就是把所有单个的美元都变成一对美元, 这样啥问题都解决了. </strong></li></ul><h3 id="开启使用"><a href="#开启使用" class="headerlink" title="开启使用"></a>开启使用</h3><p>一般来说在主题的配置文件中都会有 mathjax 的选项, 设置值为 <code>true</code> . 由于渲染 mathjax 会比较慢, 所以默认应该是并非每个页面都渲染, 如果要使用需要在要渲染的文章的 Front-matter 里加入</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mathjax: true</span><br></pre></td></tr></table></figure><p>这样就能开启使用了.</p><h2 id="Valine-评论功能"><a href="#Valine-评论功能" class="headerlink" title="Valine 评论功能"></a>Valine 评论功能</h2><p>为什么是 Valine 呢? 因为我喜欢. (不用登陆啥的太方便了)<br>同样的, 很多 Hexo 主题集成了 Valine 评论系统, 我们先在主题的 _config.yml 文件中找到 <code>Valine</code> 这个配置</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># valine comment system. https://valine.js.org</span></span><br><span class="line"><span class="attr">valine:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">false</span> <span class="comment"># if you want use valine,please set this value is true</span></span><br><span class="line">  <span class="attr">appId:</span> <span class="comment"># leancloud application app id</span></span><br><span class="line">  <span class="attr">appKey:</span> <span class="comment"># leancloud application app key</span></span><br><span class="line">  <span class="attr">notify:</span> <span class="literal">false</span> <span class="comment"># valine mail notify (true/false) https://github.com/xCss/Valine/wiki</span></span><br><span class="line">  <span class="attr">verify:</span> <span class="literal">false</span> <span class="comment"># valine verify code (true/false)</span></span><br><span class="line">  <span class="attr">pageSize:</span> <span class="number">10</span> <span class="comment"># comment list page size</span></span><br><span class="line">  <span class="attr">avatar:</span> <span class="string">monsterid</span> <span class="comment"># gravatar style https://valine.js.org/#/avatar</span></span><br><span class="line">  <span class="attr">lang:</span> <span class="string">en</span> <span class="comment"># i18n: zh-cn/en</span></span><br><span class="line">  <span class="attr">placeholder:</span> <span class="string">Please</span> <span class="string">leave</span> <span class="string">your</span> <span class="string">footprints</span> <span class="comment"># valine comment input placeholder(like: Please leave your footprints )</span></span><br><span class="line">  <span class="attr">guest_info:</span> <span class="string">nick,mail,link</span> <span class="comment">#valine comment header info</span></span><br><span class="line">  <span class="attr">bg:</span> <span class="string">/img/comment_bg.png</span> <span class="comment"># valine background</span></span><br><span class="line">  <span class="attr">count:</span> <span class="literal">false</span> <span class="comment"># top_img顯示評論數</span></span><br></pre></td></tr></table></figure><p><code>enable</code> 改成 <code>true</code> appId 与 appKey 这两项的值需要通过 <a href="https://www.leancloud.cn/">LeanCloud</a> 获得.<br>首先当然是先注册一个 LeanCloud 账号, 然后进入到<a href="https://leancloud.cn/dashboard/applist.html#/apps">控制台</a>, 创建一个应用, 自己随便填应用名称, 选择开发版, 然后进入这个应用, 进入 <code>设置-&gt;应用 keys</code> 就可以看到你的 appId 和 appKey了.<br><img src="9.png" alt=""><br>将这两个值填入, 就可以使用 Valine 了, 但是如果使用评论的时候报错, 那么可以看<a href="https://yunist.cn/hexo/problem_in_Valine/">我的这篇文章</a>, 解决了 Valine 报错的问题.</p><h2 id="cnzz统计"><a href="#cnzz统计" class="headerlink" title="cnzz统计"></a>cnzz统计</h2><p>进入<a href="https://web.umeng.com">友盟官网</a>注册一个账号, 然后进入<a href="https://workbench.umeng.com/home">工作台</a>, 点击 <code>添加Web</code>, 按照要求填写, 然后会要求在你的网站添加统计代码. 我们一般将这段统计代码添加到网页的页脚.<br>博客页脚布局一般在主题下的 <code>layout/includes/footer.ejs</code> 下, 在最后添加你选择的代码. 当然, 页脚布局有可能是 <code>layout/includes/footer.pug</code> (比如说 Butterfly 主题就是这样) , 那么又稍有不同.<br>比如其中一个代码是</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span> <span class="attr">src</span>=<span class="string">&quot;https://s4.cnzz.com/z_stat.php?id=1278667709&amp;web_id=1278667709&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>那么要改成</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">script(</span><br><span class="line">    type=&quot;text/javascript&quot;</span><br><span class="line">    src=&quot;https://s4.cnzz.com/z_stat.php?id=1278667709&amp;web_id=1278667709&quot;</span><br><span class="line">    )</span><br></pre></td></tr></table></figure><p>再比如</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span><span class="language-javascript"><span class="variable language_">document</span>.<span class="title function_">write</span>(<span class="built_in">unescape</span>(<span class="string">&quot;%3Cspan id=&#x27;cnzz_stat_icon_1278667709&#x27;%3E%3C/span%3E%3Cscript src=&#x27;https://s4.cnzz.com/z_stat.php%3Fid%3D1278667709&#x27; type=&#x27;text/javascript&#x27;%3E%3C/script%3E&quot;</span>));</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>要改成</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">script(type=&quot;text/javascript&quot;) document.write(unescape(&quot;%3Cspan id=&#x27;cnzz_stat_icon_1278667709&#x27;%3E%3C/span%3E%3Cscript src=&#x27;https://s4.cnzz.com/z_stat.php%3Fid%3D1278667709&#x27; type=&#x27;text/javascript&#x27;%3E%3C/script%3E&quot;));</span><br></pre></td></tr></table></figure><p>(注意 <code>document.write</code> 前面有一个空格)<br>那么到底要怎么改呢, 聪明的同学可能已经找出了规律, 即 <code>script()</code> 括号里的内容其实是每一个代码开头的 <code>&lt;script&gt;</code> 标签里的内容, 然后 <code>script()</code> 后的内容 (注意要隔一个空格) 就是被两对尖括号包起来的内容, 比如</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">document.write(unescape(&quot;%3Cspan id=&#x27;cnzz_stat_icon_1278667709&#x27;%3E%3C/span%3E%3Cscript src=&#x27;https://s4.cnzz.com/z_stat.php%3Fid%3D1278667709&#x27; type=&#x27;text/javascript&#x27;%3E%3C/script%3E&quot;));</span><br></pre></td></tr></table></figure><p>当然如果里面没有内容就空着.<br>根据这个规律, 我们可以得出其他代码的写法<br>再再比如</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">&quot;text/javascript&quot;</span>&gt;</span><span class="language-javascript"><span class="variable language_">document</span>.<span class="title function_">write</span>(<span class="built_in">unescape</span>(<span class="string">&quot;%3Cspan id=&#x27;cnzz_stat_icon_1278667709&#x27;%3E%3C/span%3E%3Cscript src=&#x27;https://s4.cnzz.com/z_stat.php%3Fid%3D1278667709%26show%3Dpic&#x27; type=&#x27;text/javascript&#x27;%3E%3C/script%3E&quot;</span>));</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><p>应该改成</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">script(type=&quot;text/javascript&quot;) document.write(unescape(&quot;%3Cspan id=&#x27;cnzz_stat_icon_1278667709&#x27;%3E%3C/span%3E%3Cscript src=&#x27;https://s4.cnzz.com/z_stat.php%3Fid%3D1278667709%26show%3Dpic&#x27; type=&#x27;text/javascript&#x27;%3E%3C/script%3E&quot;));</span><br></pre></td></tr></table></figure><p>以上其实是 <a href="https://pugjs.org/">pug</a> 语言的语法, pug 是一个 HTML 模板工具, 想更多的了解 pug, 建议查看<a href="https://pugjs.org/zh-cn/api/getting-started.html">官方文档</a>.</p><h2 id="让博客支持脑图-思维导图"><a href="#让博客支持脑图-思维导图" class="headerlink" title="让博客支持脑图 (思维导图)"></a>让博客支持脑图 (思维导图)</h2> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-simple-mindmap</span><br></pre></td></tr></table></figure><p>然后只要在 markdown 文件中按照下面的语法就能写出脑图啦~</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#123;% pullquote mindmap mindmap-md %&#125;</span><br><span class="line"><span class="bullet">-</span> demo</span><br><span class="line"><span class="bullet">  -</span> 这是一个分支</span><br><span class="line"><span class="bullet">  -</span> 这是另一个分支</span><br><span class="line"><span class="bullet">    -</span> 分支的分支哦</span><br><span class="line"><span class="bullet">    -</span> 分支的另一个分支哦</span><br><span class="line"><span class="bullet">  -</span> 没有分支的分支</span><br><span class="line"><span class="bullet">  -</span> 没有分支的另一个分支</span><br><span class="line">&#123;% endpullquote %&#125;</span><br></pre></td></tr></table></figure><blockquote class="pullquote mindmap mindmap-md"><ul><li>demo<ul><li>这是一个分支</li><li>这是另一个分支<ul><li>分支的分支哦</li><li>分支的另一个分支哦</li></ul></li><li>没有分支的分支</li><li>没有分支的另一个分支</li></ul></li></ul></blockquote><h1 id="加速博客"><a href="#加速博客" class="headerlink" title="加速博客"></a>加速博客</h1><p>Github Pages 的服务器在国外, 所以速度其实并不咋地, 所以这里给出优化方案.</p><h2 id="CloudFlare-加速"><a href="#CloudFlare-加速" class="headerlink" title="CloudFlare 加速"></a><a href="https://www.cloudflare.com">CloudFlare</a> 加速</h2><p>CloudFlare 是一家国外的 CDN 加速服务商. 事实上, 我并不推荐 CloudFlare 对你的博客进行 CDN 加速, 因为 CloudFlare 在国内并没有多少节点, 还很不稳定, 而且挂了 CF 后速度似乎还更慢了些, 所以这里不详细讲解, 想用的自己去了解吧.</p><h2 id="Jsdelivr-加速"><a href="#Jsdelivr-加速" class="headerlink" title="Jsdelivr 加速"></a><a href="https://www.jsdelivr.com/">Jsdelivr</a> 加速</h2><p>绝对要推荐这个, 加速利器, <strong>你不需要注册, 甚至连登陆它的网站都不用, 就可以免费使用 Jsdelivr 加速, 简直业界良心啊有木有.</strong> Jsdelivr 可以加速 Github 上的静态文件, 很多主题都有配置, 我们这里介绍如何通过 Jsdelivr 引用 Github 资源.</p><p>首先, 如果你看不懂以下教程, 没关系, 我还准备了另外一个简单的方式使用 Jsdelivr , 详情请看<a href="https://yunist.cn/hexo/jsdelivr_js/#Icarus">这篇文章</a>.</p><p>你可以认为 Jsdelivr 里放了你传上 Github 的文件 <strong>(这个 ‘放’ 的过程是自动的, 只要 Github 上有资源, 就会被 ‘放’ 到 Jsdelivr 上)</strong>, 由于 GFW 的关系, 国内访问 Github 上的资源是很慢的, 那么我们可以通过访问 Jsdelivr 来间接访问 Github 上的资源.</p><p>Github 上的某个资源是有其位置的, 如何访问一个 Github 资源? 你只需要知道:</p><ul><li>用户名</li><li>仓库名</li><li>资源在仓库中的位置</li></ul><p>同样, Jsdelivr 中的某个资源也是有其位置, 如何访问一个经 Jsdelivr 加速的 Github 资源? 你同样只需要知道:</p><ul><li>用户名</li><li>仓库名</li><li>资源在仓库中的位置</li></ul><p><strong>访问互联网上的资源需要通过 <code>url(统一资源定位器)</code> .</strong></p><p>那么:</p><p>某个 Github 资源通过 Github 引用的 url 格式是:</p><p><strong><a href="https://raw.githubusercontent.com/用户名/仓库名/master/资源在仓库中的位置">https://raw.githubusercontent.com/用户名/仓库名/master/资源在仓库中的位置</a></strong></p><p>而通过 Jsdelivr 引用的 url 格式就是:</p><p><strong>资源在仓库中的位置</strong></p><p>Jsdelivr 加速的原理就是, 把静态资源的 url 全部替换为 Jsdelivr 的 url (比如图片等资源).</p><p><strong>这里再提醒一遍, 任何 Github 资源都可以在 Jsdelivr 上引用, 不受仓库限制, 很多教程提到新建一个所谓 “cdn” 仓库, 但是根本没必要, Github 仓库上限 100G , 建博客绰绰有余.</strong></p><h2 id="图床"><a href="#图床" class="headerlink" title="图床"></a>图床</h2><p>相信很多人都有使用图床的经历, 在文章中直接引用外链也能显著的加速, 但是上面已经介绍了 Jsdelivr 加速了, 所有图片都可以通过 Jsdelivr 加速, 已经没有使用图床的必要了. 但是还是有人想用图床, 那么这里介绍一种发生, 搭建自己的图床. 利用的原理还是 Jsdelivr 加速, 即将 Github 当成图床, 然后通过 Jsdelivr 引用. 这里利用了一个方便的工具 <a href="">Picgo</a>, 它可以方便的上传图片到 Github (但是经常出错, <del>非常玄学, 时灵时不灵</del>, 经过本人测试, 只有 2.0.4 这个版本勉强能用, 但还是经常出错, <del>反正就是玄学</del>).</p><h2 id="网页预加载脚本-instant-page"><a href="#网页预加载脚本-instant-page" class="headerlink" title="网页预加载脚本 instant.page"></a>网页预加载脚本 instant.page</h2><p>这个脚本可以实现页面的预加载, 将用户想要访问的页面缓存下来, 需要时直接从缓存读取. </p><ul><li><strong>Butterfly 自带该脚本, 因此如果使用 Butterfly 主题可以不用配置.</strong></li></ul><h3 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h3><ul><li>在用户点击网站链接之前, 他们将鼠标悬停在该链接上. 当用户徘徊 65 毫秒时, 他们将点击该链接有两个机会, 因此 instant.page 此时开始预加载, 平均超过 300 毫秒, 以便页面预加载.</li><li>instant.page 是渐进式增强 - 对不支持它的浏览器没有影响.</li><li>instant.page 对站内访问速度的提升的确很给力。然而它只会预加载自己的站内链接，而不会预加载其他外链。</li></ul><h3 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h3><p>将这段代码放到主题目录下的 <code>layout/includes/layout.ejs</code> 文件中的 <code>&lt;/body&gt;</code> 标签前就可以了.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script src=&quot;https://cdn.jsdelivr.net/npm/instant.page@latest/instantpage.min.js&quot;&gt;&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>当然, 同样也有 <code>layout/includes/layout.pug</code> 的情况 (同样比如 Butterfly), 那么可以将以下代码放到 <code>head</code> 前</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">script(src=&quot;https://cdn.jsdelivr.net/npm/instant.page@latest/instantpage.min.js&quot;)</span><br></pre></td></tr></table></figure><p><img src="10.png" alt=""></p><h1 id="Butterfly-主题升级"><a href="#Butterfly-主题升级" class="headerlink" title="Butterfly 主题升级"></a>Butterfly 主题升级</h1><p><strong>注意! 所有重大改动必须备份! 别怪我没提醒你!</strong></p><p><strong>注意! 所有重大改动必须备份! 别怪我没提醒你!</strong></p><p><strong>注意! 所有重大改动必须备份! 别怪我没提醒你!</strong></p><p>先要将本地的所有修改先暂时存储起来:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git stash</span><br></pre></td></tr></table></figure><p>然后再</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git pull</span><br></pre></td></tr></table></figure><p>最后还原暂时存储的内容</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git stash pop</span><br></pre></td></tr></table></figure><p>这时, 就需要你去修改一些冲突的地方了, 冲突的地方挺好找的, 观察一下就发现规律了. 可以执行 <code>hexo g</code> 然后查看报错的地方, 一般来说报错的地方就是和更新内容有冲突的地方, 需要自己一个个去改. <strong>如果你在 <code>_data</code> 文件下有 <code>butterfly.yml</code> 文件, 一定要将新增配置复制过去, 否则可能会出现一些问题 (比如说顶栏消失) .</strong></p><h1 id="Butterfly-主题魔改"><a href="#Butterfly-主题魔改" class="headerlink" title="Butterfly 主题魔改"></a>Butterfly 主题魔改</h1><p><strong>本博客已开源, 请看 <a href="https://yunist.cn/hexo/hexo_modify_theme_butterfly/">Hexo modify theme butterfly</a>.</strong></p><p>主题魔改具体看<a href="https://yunist.cn/hexo/butterfly_modify/">这里</a>.</p><hr><p>暂时就这么多, 以后可能还会补充.</p>]]></content>
      
      
      <categories>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Hexo </tag>
            
            <tag> 教程 </tag>
            
            <tag> 搭建站点 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>解决 Hexo 配置 Valine 各种问题</title>
      <link href="/hexo/problem_in_Valine/"/>
      <url>/hexo/problem_in_Valine/</url>
      
        <content type="html"><![CDATA[<h1 id="报错"><a href="#报错" class="headerlink" title="报错"></a>报错</h1><p>解决报错:</p><ul><li>Code: undefined [410 GET <a href="https://avoscloud.com/1.1/classes/Comment">https://avoscloud.com/1.1/classes/Comment</a>]</li><li>Code 403: 访问被api域名白名单拒绝，请检查你的安全域名设置</li><li>Code -1: Request has been terminated</li></ul><h2 id="Code-undefined-410-GET-https-avoscloud-com-1-1-classes-Comment"><a href="#Code-undefined-410-GET-https-avoscloud-com-1-1-classes-Comment" class="headerlink" title="Code: undefined [410 GET https://avoscloud.com/1.1/classes/Comment]"></a>Code: undefined [410 GET <a href="https://avoscloud.com/1.1/classes/Comment">https://avoscloud.com/1.1/classes/Comment</a>]</h2><p>很多 Hexo 主题都会集成很多评论系统, 我了解了一下最满意的还是 Valine. Valine 不用登陆就可以评论, 我本人就很讨厌登陆来登陆去的.<br>在主题的 “_config.yml” 文件中应该有关于 Valine 的配置, 可能长这个样子</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">valine:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span> <span class="comment"># if you want use valine,please set this value is true</span></span><br><span class="line">  <span class="attr">appId:</span>  <span class="comment"># leancloud application app id</span></span><br><span class="line">  <span class="attr">appKey:</span>  <span class="comment"># leancloud application app key</span></span><br><span class="line">  <span class="attr">notify:</span> <span class="literal">true</span> <span class="comment"># valine mail notify (true/false) https://github.com/xCss/Valine/wiki</span></span><br><span class="line">  <span class="attr">verify:</span> <span class="literal">true</span> <span class="comment"># valine verify code (true/false)</span></span><br><span class="line">  <span class="attr">pageSize:</span> <span class="number">10</span> <span class="comment"># comment list page size</span></span><br><span class="line">  <span class="attr">avatar:</span> <span class="string">monsterid</span> <span class="comment"># gravatar style https://valine.js.org/#/avatar</span></span><br><span class="line">  <span class="attr">lang:</span> <span class="string">zh-cn</span> <span class="comment"># i18n: zh-cn/en</span></span><br><span class="line">  <span class="attr">placeholder:</span> <span class="string">快快献上你的评论~</span> <span class="comment"># valine comment input placeholder(like: Please leave your footprints )</span></span><br><span class="line">  <span class="attr">guest_info:</span> <span class="string">nick,mail,link</span> <span class="comment">#valine comment header info</span></span><br><span class="line">  <span class="attr">bg:</span> <span class="string">/img/comment_bg.png</span> <span class="comment"># valine background</span></span><br><span class="line">  <span class="attr">count:</span> <span class="literal">true</span> <span class="comment"># top_img显示评论数</span></span><br></pre></td></tr></table></figure><p>appId 与 appKey 自己注册 <a href="https://www.leancloud.cn/">leancloud</a> 然后创建应用获取, 但是配置完出现报错: <code>Code: undefined [410 GET https://avoscloud.com/1.1/classes/Comment]</code>, 出现问题的原因在于何处? 上谷歌查了查, 有人说是华东节点有 bug, 可是我选的是华北节点啊, 然后看到<a href="https://rightofriver.github.io/2019/10/30/ValineBug1/#fn:3">这篇文章</a>, 成功解决了我的问题. 首先是 “_config.yml” 里的配置和注释 ‘#’ 号不能连在一起, 也就是 “xxxx# xxx” 要改成 “xxxx # xxx”.</p><h2 id="Code-403-访问被api域名白名单拒绝，请检查你的安全域名设置"><a href="#Code-403-访问被api域名白名单拒绝，请检查你的安全域名设置" class="headerlink" title="Code 403: 访问被api域名白名单拒绝，请检查你的安全域名设置"></a>Code 403: 访问被api域名白名单拒绝，请检查你的安全域名设置</h2><p>然后可能又出现一个报错: <code>Code 403: 访问被api域名白名单拒绝，请检查你的安全域名设置</code>, 这个报错就很简洁明了了, 把你博客的域名添加到 “安全中心” 的 “Web 安全域名” 里, 注意端口等等要完全正确.<br><img src="1.png" alt=""></p><h2 id="Code-1-Request-has-been-terminated"><a href="#Code-1-Request-has-been-terminated" class="headerlink" title="Code -1: Request has been terminated"></a>Code -1: Request has been terminated</h2><p>这个报错出现的原因大多都是因为 Comment Class 不存在, 因此经过测试有两种方法可以解决该问题</p><ul><li>随便发一条评论, Comment 这个 Class 就会自己生成. (最简便的方法)</li><li>进入到 LeanCloud , 然后进入 Valine 的应用, 然后进入 <code>存储 -&gt; 结构化数据 -&gt; 创建 Class</code> , 然后创建一个名叫 <code>Comment</code> 的 Class. 其他的选项都是默认的就好了. 创建过后, 报错解决.</li></ul><h1 id="其他问题"><a href="#其他问题" class="headerlink" title="其他问题"></a>其他问题</h1><h2 id="评论无法拉取"><a href="#评论无法拉取" class="headerlink" title="评论无法拉取"></a>评论无法拉取</h2><p>可能是因为使用国际版 LeanCloud 导致的 (api 地址更换), 只需要将 Valine 配置项 <code>serverURLs</code> 改成</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">serverURLs:</span> <span class="string">https://xxxxxxxx.api.lncldglobal.com</span></span><br></pre></td></tr></table></figure><p>其中 <code>xxxxxxxx</code> 是你的 LeanCloud App ID 前八位. 修改后重新部署即解决.</p>]]></content>
      
      
      <categories>
          
          <category> Hexo </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Hexo </tag>
            
            <tag> 搭建站点 </tag>
            
            <tag> 问题 </tag>
            
            <tag> Valine </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>《机器学习》 西瓜书习题 第 7 章: 贝叶斯分类器</title>
      <link href="/ML/watermelon_book/answer/7/"/>
      <url>/ML/watermelon_book/answer/7/</url>
      
        <content type="html"><![CDATA[<h1 id="习题"><a href="#习题" class="headerlink" title="习题"></a>习题</h1><h2 id="7-1"><a href="#7-1" class="headerlink" title="7.1"></a>7.1</h2><p><strong>试使用极大似然法估算西瓜数据集 $3.0$ 中前 $3$ 个属性的类条件概率.</strong></p><p>极大似然法即计算如何才能使结果出现的可能性最大, 因此类条件概率为其在数据集里出现的概率, 即<br>$$P(X = x\mid C = c) = \frac{|D_{X, x}|}{|D_{X, c}|}$$<br>其中 $D_{X, x}$ 表示属性 $X$ 中取值为 $x$ 的集合, $D_{X,x}$ 表示属性 $X$ 中类别为 $c$ 的集合.<br>所以前 $3$ 个属性的类条件概率为<br>$$\begin{align}P(X = 青绿\mid C = 是) = \frac{3}{8}, P(X = 乌黑\mid C = 是) = \frac{4}{8}, P(X = 浅白\mid C = 是) = \frac{1}{8}\\\\P(X = 青绿\mid C = 否) = \frac{3}{9}, P(X = 乌黑\mid C = 否) = \frac{2}{9}, P(X = 浅白\mid C = 否) = \frac{4}{9}\\\\P(X = 青绿\mid C = 否) = \frac{3}{9}, P(X = 乌黑\mid C = 否) = \frac{2}{9}, P(X = 浅白\mid C = 否) = \frac{4}{9}\\\\P(X = 蜷缩\mid C = 是) = \frac{5}{8}, P(X = 稍蜷\mid C = 是) = \frac{3}{8}, P(X = 硬挺\mid C = 是) = \frac{0}{8}\\\\P(X = 蜷缩\mid C = 否) = \frac{3}{9}, P(X = 稍蜷\mid C = 否) = \frac{4}{9}, P(X = 硬挺\mid C = 否) = \frac{2}{9}\\\\P(X = 浊响\mid C = 是) = \frac{6}{8}, P(X = 沉闷\mid C = 是) = \frac{2}{8}, P(X = 清脆\mid C = 是) = \frac{0}{8}\\\\P(X = 浊响\mid C = 否) = \frac{4}{9}, P(X = 沉闷\mid C = 否) = \frac{3}{9}, P(X = 清脆\mid C = 否) = \frac{2}{9}\end{align}$$</p><h2 id="7-2"><a href="#7-2" class="headerlink" title="7.2"></a>7.2</h2><p><strong>试证明: 条件独立性假设不成立时, 朴素贝叶斯分类器仍有可能产生最优贝叶斯分类器.</strong></p><p>原书 $\mathrm p.164$</p><blockquote><p>若属性间依赖对所有类别影响相同, 或依赖关系的影响能互相抵消, 则属性条件独立性假设在降低计算开销的同时不会对性能产生负面影响 $[\mathrm{Zhang}, 2004].$</p></blockquote><h2 id="7-3"><a href="#7-3" class="headerlink" title="7.3"></a>7.3</h2><p><strong>试编程实现拉普拉斯修正的朴素贝叶斯分类器, 并以西瓜数据集 $3.0$ 为训练集, 对 $\mathrm p.151$ “测 $1$“ 样本进行判别.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/261652">https://aistudio.baidu.com/aistudio/projectdetail/261652</a></p><h2 id="7-4"><a href="#7-4" class="headerlink" title="7.4"></a>7.4</h2><p><strong>实践中使用式 $(7.15)$ 决定分类类别时, 若数据的维数非常高, 则概率连乘 $\prod_{i = 1}^{d}P(x_i\mid c)$ 的结果通常会非常接近于 $0$ 从而导致下溢. 试述防止下溢的可能方案.</strong></p><p>遇到问题, 要多查书. 书里其实已经给了解决方案, 那就是取对数.</p><h2 id="7-5"><a href="#7-5" class="headerlink" title="7.5"></a>7.5</h2><p><strong>试证明: 二分类任务中两类数据满足高斯分布且方差相同时, 线性判别分析产生贝叶斯最优分类器.</strong></p><p>我们先分析 $\mathrm{LDA}$ , 两类数据都满足高斯分布并且方差相同, 于是两类数据的形状是一样的, 只是所处位置不同. $\mathrm{LDA}$ 需要将样本中心的间隔最大化, 并且无论数据投影在哪一条直线上样本内方差都是一样的 (因为是个圆) , 所以应该会投射在一个与两个样本中心的连线平行的直线上 (此时样本中心相距最远). 在样本中心的连线的中点是两个类的分割点.</p><p>而贝叶斯会将在某个位置出现的点分成最可能的类, 这个最可能我们用样本来估计它的概率. 根据高斯分布, 距样本中心越远点的分布越少, 相应的概率也变小, 那么分界线在哪呢? (就是刚刚好分成 $1$ 类的概率是 $50\%$, $0$ 类的概率也是 $50\%$) 其实也是样本中心连线的中点, 更准确的说是过该点与样本中心连线的直线垂直的平面, 因为该平面上每一点与两个样本中心的距离都是相同的. </p><p>因此线性判别分析与贝叶斯产生了相同效果的分类界限, 于是它们是等价的.</p><h2 id="7-6"><a href="#7-6" class="headerlink" title="7.6"></a>7.6</h2><p><strong>试编程实现 $\mathrm {AODE}$ 分类器, 并以西瓜数据集 $3.0$ 为训练集, 对 $\mathrm p.151$ 的 “测 $1$“ 样本进行判别.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/261652">https://aistudio.baidu.com/aistudio/projectdetail/261652</a></p><h2 id="7-7"><a href="#7-7" class="headerlink" title="7.7"></a>7.7</h2><p><strong>给定 $d$ 个二值属性的二分类任务, 假设对于任何先验概率项的估算至少需 $30$ 个样例, 则在朴素贝叶斯分类器式 $(7.15)$ 中估算先验概率项 $P(c)$ 需 $30\times 2 = 60$ 个样例. 试估计在 $\mathrm{AODE}$ 式 $(7.23)$ 中估算先验概率项 $P(c, x_i)$ 所需的样例数 (分别考虑最好和最坏情形).</strong></p>$$P(c\mid \boldsymbol{x}) \propto \sum_{\begin{array}{c}\scriptstyle i = 1\\\\\scriptstyle|D_{x_i}|\geqslant m' \end{array}}^{d}P(c, x_i)\prod_{j = 1}^d P(x_j\mid c, x_i)\tag{7.23}$$<p>最好情形就是 $60$ 个了, 即 $x_i$ 只有两种取值并且和 $c$ 一起出现, 也就是<br>$$P(c) = P(c, x_i)$$<br>最坏情形则为 $30\times 2 \times i$ 个, 即每种情况各有 $30$ 个样例, 由于有两类, $i$ 个取值, 所以一共有 $2 \times i$ 种情况, 因此就为 $30\times 2 \times i$ 个.</p><h2 id="7-8"><a href="#7-8" class="headerlink" title="7.8"></a>7.8</h2><p><strong>考虑图 $7.3$ , 试证明: 在同父结构中, 若 $x_1$ 的取值未知, 则 $x_3\perp \!\!\! \perp x_4$ 不成立; 在顺序结构中, $y \perp z \mid x$, 但 $y \perp \!\!\! \perp z$ 不成立.</strong></p><p>在这里我就不得不得吐个槽, $\perp \!\!\! \perp$这个符号实在是太难找, 只能用两个 $\perp$ 重叠来替代 <del>(所以如果见到两个接着的 $\perp$ 不要奇怪)</del>.<br><img src="1.png" alt="贝叶斯网中三个变量之间的典型依赖关系"><br>这里要用到的重要式子是<br>$$P_B(x_1, x_2, \dots, x_d) = \prod_d^{i = 1}P_B(x_i\mid \pi_i) = \prod_{i = 1}^d \theta_{x{_i}\mid\pi_i}\tag{7.26}$$<br>对同父结构来说, 由于 $x_1$ 已知, 我们设 $x_1 = x$ 因此 $P(x_1 = x) = 1$, 因此有<br>$$\begin{aligned}P(x_1 = x, x_3, x_4) &= P(x_3\mid x_1 = x)P(x_4\mid x_1 = x)P(x_1 = x)\\\\P(x_3, x_4) &= P(x_3)P(x_4)\end{aligned}$$<br>即 $x_3 \perp x_4 \mid x_1$ .</p><p>而如果 $x_1$ 未知, 那么同样的有<br>$$P(x_1, x_3, x_4) = P(x_3\mid x_1)P(x_4\mid x_1)P(x_1)$$</p>$$\begin{aligned}P(x_3, x_4) &= \sum_{i = 1}^mP(x_1 = x_1^i, x_3, x_4)\\\\&=\sum_{i = 1}^mP(x_3\mid x_1 = x_1^i)P(x_4\mid x_1 = x_1^i)P(x_1 = x_1^i)\end{aligned}$$<p>其中 $m$ 是 $x_1$ 可能的取值数, $x_1^i$ 是 $x_1$ 第 $i$ 个取值.<br>$$P(x_3) = \sum_{i = 1}^mP(x_3\mid x_1 = x_1^i)\\\\P(x_4) = \sum_{i = 1}^mP(x_4\mid x_1 = x_1^i)\\\\$$<br>$$\because \left[\sum_{i = 1}^mP(x_3\mid x_1 = x_1^i)\right]\left[\sum_{i = 1}^mP(x_4\mid x_1 = x_1^i)\right] \geqslant \sum_{i = 1}^mP(x_3\mid x_1 = x_1^i)P(x_4\mid x_1 = x_1^i)$$</p><p>且<br>$$P(x_1 = x_1^i) \leqslant 1$$</p>$$\begin{aligned}\therefore \left[\sum_{i = 1}^mP(x_3\mid x_1 = x_1^i)\right]\left[\sum_{i = 1}^mP(x_4\mid x_1 = x_1^i)\right] &\geqslant \sum_{i = 1}^mP(x_3\mid x_1 = x_1^i)P(x_4\mid x_1 = x_1^i)P(x_1 = x_1^i)P(x_1 = x_1^i)\\\\P(x_3)P(x_4) &\geqslant p(x_3, x_4)\end{aligned}$$<p>当且仅当 $x_1$ 已知时取等, 即 $x_1$ 未知时, $x_3\perp \!\!\! \perp x_4$ 不成立.</p><p>对于顺序结构来说, 我们用同样的方法去证明.</p><p>若 $x$ 取值已知且值为 $a$, 则有<br>$$P(x = a) = 1$$<br>$$\begin{aligned}\thereforeP(x, y, z) &= P(y\mid x)P(x\mid z)P(z)\\\\P(y, z)&= P(y) \times 1 \times P(z) = P(y)P(z)\end{aligned}$$</p><p>即 $y \perp z \mid x$</p><p>当 $x$ 取值未知时<br>$$\begin{aligned}P(y, z) &= \sum_{i = 1}^mP(x = x_i, y, z)\\\\&=\sum_{i = 1}^mP(y\mid x = x_i)P(x = x_i\mid z)P(z)\\\\&=P(z)\sum_{i = 1}^mP(y\mid x = x_i)P(x = x_i\mid z)\end{aligned}\\\\P(y) = \sum_{i = 1}^mP(y\mid x = x_i)\\\\\because P(x = x_i\mid z) \leqslant 1$$<br>其中 $m$ 为 $x$ 取值数量, $x_i$ 为 $x$ 的第 $i$ 个取值.<br>$$\therefore \begin{aligned}\sum_{i = 1}^mP(y\mid x = x_i) &\geqslant \sum_{i = 1}^mP(y\mid x = x_i)P(x = x_i\mid z)\\\\\sum_{i = 1}^mP(y\mid x = x_i)P(z) &\geqslant P(z)\sum_{i = 1}^mP(y\mid x = x_i)P(x = x_i\mid z)\\\\P(y)P(z)&\geqslant P(y, z)\end{aligned}$$<br>当且仅当 $x$ 已知时取等, 即 $x$ 未知时, $y\perp \!\!\! \perp z$ 不成立.</p><h2 id="7-9"><a href="#7-9" class="headerlink" title="7.9"></a>7.9</h2><p><strong>以西瓜数据集 $2.0$ 为训练集, 试基于 $\mathrm{BIC}$ 准则构建一个贝叶斯网.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/261652">https://aistudio.baidu.com/aistudio/projectdetail/261652</a></p><h2 id="7-10"><a href="#7-10" class="headerlink" title="7.10"></a>7.10</h2><p><strong>以西瓜数据集 $2.0$ 中属性 “脐部” 为隐变量, 试基于 $\mathrm{EM}$ 算法构建一个贝叶斯网.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/261652">https://aistudio.baidu.com/aistudio/projectdetail/261652</a></p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 西瓜书 </category>
          
          <category> 习题 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 西瓜书 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Jupyter 公式渲染问题</title>
      <link href="/python/jupyter/jupyter_formula_render/"/>
      <url>/python/jupyter/jupyter_formula_render/</url>
      
        <content type="html"><![CDATA[<p>Jupyter lab 中的公式有时候很丑, 想要变得好看一点, 于是找到了 Jupyter 中的一个插件解决该问题. 在左上角进入 Settings -&gt; Advanced Settings Editor, </p><p><img src="2.png" alt=""></p><p>然后会打开一个 Settings 文件, 点击 Extension Manager 并在右边填入 <code>&#123;&quot;enable&quot;: true&#125;</code> 然后保存</p><p><img src="3.png" alt=""></p><p>就可以开启插件了. 开启插件在左边侧边栏会有多出一个插件选项, 进入后搜索 katex-extension 装上, 然后等一会它会告诉你是否 <code>rebuild</code> 啥的, 一路点 <code>是</code> , 等一会就好了.</p><p>成果:<br><img src="1.png" alt=""><br>好看多了.</p>]]></content>
      
      
      <categories>
          
          <category> Python </category>
          
          <category> Jupyter </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 问题 </tag>
            
            <tag> LaTeX </tag>
            
            <tag> Jupyter </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>jupyter lab 中编辑 .md文件</title>
      <link href="/python/jupyter/md_file_in_jupyterlab/"/>
      <url>/python/jupyter/md_file_in_jupyterlab/</url>
      
        <content type="html"><![CDATA[<span id="more"></span><p>本来以为 jupyter lab 里没办法预览 .md 文件, 还找了好久插件, 结果其实不用插件也可以, 只要打开 .md 文件, 然后右键就有 Show Markdown Preview 选项, 点了之后就可以在右半边实时预览.<br><del>好吧这是一篇水文.</del></p>]]></content>
      
      
      <categories>
          
          <category> Python </category>
          
          <category> Jupyter </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 水文 </tag>
            
            <tag> Jupyter </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>百度 AI Studio 的 notebook 字体问题</title>
      <link href="/scribble/AI_Studio_notebook_font/"/>
      <url>/scribble/AI_Studio_notebook_font/</url>
      
        <content type="html"><![CDATA[<span id="more"></span><p>在用百度 AI Studio 中的 notebook 时, 发现光标会偏移, 有时字体也很难看, 浏览器怎么设置都没有用, 例如下图就是光标偏移.<br><img src="1.png" alt=""><br>然后发现了一个很好用的插件可以解决问题: Stylus (怎么下载安装自己百度)</p><p>就这玩意<br><img src="2.png" alt=""><br>编写样式给 aistudio.baidu.com , 填写以下内容:<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">pre, <span class="selector-tag">code</span>, <span class="selector-tag">kbd</span>, <span class="selector-tag">samp</span> &#123;</span><br><span class="line">    <span class="attribute">font-family</span>: monospace <span class="meta">!important</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.cc</span> <span class="selector-class">.ace_editor</span> &#123;</span><br><span class="line">    <span class="attribute">font-family</span>: monospace <span class="meta">!important</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.cc</span> pre &#123;</span><br><span class="line">    <span class="attribute">font-family</span>: Arial <span class="meta">!important</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>解决!<br>摸索一下就可以随便改网页字体了.<br>注: 我的是 ubuntu 系统.</p>]]></content>
      
      
      <categories>
          
          <category> 杂文 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 问题 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>numpy 中判断某字符串 array 是否含有子字符串</title>
      <link href="/python/numpy/judge_child_in_array/"/>
      <url>/python/numpy/judge_child_in_array/</url>
      
        <content type="html"><![CDATA[<p>本想着有什么函数可以直接调用的, 结果网上找了一大圈没找到, 还有好多错的…<br><span id="more"></span><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">numpy.char.count(a, sub, start=<span class="number">0</span>, end=<span class="literal">None</span>)</span><br></pre></td></tr></table></figure><br>该函数是用来计数 sub 在 a 中出现多少次, 我们稍加修改就能达到我们要的效果.<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">numpy.char.count(a, sub, start=<span class="number">0</span>, end=<span class="literal">None</span>) != <span class="number">0</span></span><br></pre></td></tr></table></figure><br>函数的具体介绍看<a href="https://numpy.org/devdocs/reference/generated/numpy.char.count.html#numpy.char.count">官方文档</a>.</p><p>举例:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line">a = np.array([<span class="string">&#x27;abc&#x27;</span>, <span class="string">&#x27;akjs&#x27;</span>, <span class="string">&#x27;23ha&#x27;</span>, <span class="string">&#x27;sdfg&#x27;</span>, <span class="string">&#x27;arge&#x27;</span>, <span class="string">&#x27;8908d&#x27;</span>, <span class="string">&#x27;aaaab&#x27;</span>, <span class="string">&#x27;hhdaa&#x27;</span>, <span class="string">&#x27;wer&#x27;</span>], dtype=<span class="string">&#x27;str&#x27;</span>)</span><br><span class="line">np.char.count(a, <span class="string">&#x27;a&#x27;</span>)</span><br><span class="line"><span class="comment"># array([1, 1, 1, 0, 1, 0, 4, 2, 0])</span></span><br><span class="line">np.char.count(a, <span class="string">&#x27;a&#x27;</span>) != <span class="number">0</span></span><br><span class="line"><span class="comment"># array([ True,  True,  True, False,  True, False,  True,  True, False])</span></span><br></pre></td></tr></table></figure></p>]]></content>
      
      
      <categories>
          
          <category> Python </category>
          
          <category> Numpy </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Python </tag>
            
            <tag> Numpy </tag>
            
        </tags>
      
    </entry>
    
    
    
    
    
    <entry>
      <title>《机器学习》 西瓜书习题 第 6 章: 支持向量机</title>
      <link href="/ML/watermelon_book/answer/6/"/>
      <url>/ML/watermelon_book/answer/6/</url>
      
        <content type="html"><![CDATA[<h1 id="习题"><a href="#习题" class="headerlink" title="习题"></a>习题</h1><h2 id="6-1"><a href="#6-1" class="headerlink" title="6.1"></a>6.1</h2><p><strong>试证明样本空间中任意点 $\boldsymbol{x}$ 到超平面 $(\boldsymbol{w}, b)$ 的距离为式 $(6.2)$ .</strong></p><p><img src="1.png" alt=""></p><p>设超平面为 $\ell(\boldsymbol{w}, b)$ , $\boldsymbol{x}$ 在 $\ell$ 上的投影为 $\boldsymbol{x_0}$ , 离超平面的距离为 $r$ . 容易得<br>$$\boldsymbol{w}\perp \ell\\\\\boldsymbol{x} = \boldsymbol{x_0} + r\frac{\boldsymbol{w}}{||\boldsymbol{w}||}\\\\\boldsymbol{w}^\mathrm{T}\boldsymbol{x_0} + b = 0$$<br>则有<br>$$\boldsymbol{x_0} = \boldsymbol{x} - r\frac{\boldsymbol{w}}{||\boldsymbol{w}||}$$</p>$$\begin{aligned}\boldsymbol{w}^\mathrm{T}(\boldsymbol{x} - r\frac{\boldsymbol{w}}{||\boldsymbol{w}||}) + b &= 0\\\\\boldsymbol{w}^\mathrm{T}\boldsymbol{x} - r\frac{\boldsymbol{w}^\mathrm{T}\boldsymbol{w}}{||\boldsymbol{w}||} + b &= 0\\\\\boldsymbol{w}^\mathrm{T}\boldsymbol{x} - r\frac{||\boldsymbol{w}||^2}{||\boldsymbol{w}||} + b &= 0\\\\\boldsymbol{w}^\mathrm{T}\boldsymbol{x} + b &= r\frac{||\boldsymbol{w}||^2}{||\boldsymbol{w}||}\\\\\end{aligned}$$<p>即得<br>$$r = \frac{\boldsymbol{w}^\mathrm{T}\boldsymbol{x} + b}{||\boldsymbol{w}||}$$<br>由于距离是大于等于 $0$ 的, 所以结果再加上绝对值<br>$$r = \frac{\left|\boldsymbol{w}^\mathrm{T}\boldsymbol{x} + b\right|}{||\boldsymbol{w}||}\tag{6.2}$$</p><h2 id="6-2"><a href="#6-2" class="headerlink" title="6.2"></a>6.2</h2><p><strong>试使用 $\mathrm{LIBSVM}$ , 在西瓜数据集 $3.0\alpha$ 上分别用线性核和高斯核训练一个 $\mathrm{SVM}$ , 并比较其支持向量的差别.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/259787">《机器学习》西瓜书 第 6 章 编程实例</a></p><h2 id="6-3"><a href="#6-3" class="headerlink" title="6.3"></a>6.3</h2><p><strong>选择两个 $\mathrm{UCI}$ 数据集, 分别用线性核和高斯核训练一个 $\mathrm{SVM}$ , 并与 $\mathrm{BP}$ 神经网络和 $\mathrm{C4.5}$ 决策树进行实验比较.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/259787">《机器学习》西瓜书 第 6 章 编程实例</a></p><h2 id="6-4"><a href="#6-4" class="headerlink" title="6.4"></a>6.4</h2><p><strong>试讨论线性判别分析与线性核支持向量机在何种条件下等价.</strong></p><p>线性判别分析能够解决 $n$ 分类问题, 而 $\mathrm{SVM}$ 只能解决二分类问题, 如果要解决 $n$ 分类问题要通过 $\mathrm{OvR(One\ vs\ Rest)}$ 来迂回解决.</p><p>线性判别分析能将数据以同类样例间低方差和不同样例中心之间大间隔来投射到一条直线上, 但是如果样本线性不可分, 那么线性判别分析就不能有效进行, 支持向量机也是.<br>综上, 等价的条件是:</p><ul><li>数据有且仅有 2 种, 也就是说问题是二分类问题.</li><li>数据是线性可分的.</li></ul><h2 id="6-5"><a href="#6-5" class="headerlink" title="6.5"></a>6.5</h2><p><strong>试述高斯核 $\mathrm{SVM}$ 与 $\mathrm{RBF}$ 神经网络之间的联系.</strong></p><p>实际上都利用了核技巧, 将原来的数据映射到一个更高维的空间使其变得线性可分.</p><h2 id="6-6"><a href="#6-6" class="headerlink" title="6.6"></a>6.6</h2><p><strong>试析 $\mathrm{SVM}$ 对噪声敏感的原因.</strong></p><p>&nbsp;$\mathrm{SVM}$ 的特性就是 “支持向量” . 即线性超平面只由少数 “支持向量” 所决定. 若噪声成为了某个 “支持向量” —— 这是非常有可能的. 那么对整个分类的影响是巨大的. 反观对率回归, 其线性超平面由所有数据共同决定, 因此一点噪声并无法对决策平面造成太大影响.</p><h2 id="6-7"><a href="#6-7" class="headerlink" title="6.7"></a>6.7</h2><p><strong>试给出试 $(6,52)$ 的完整 $\mathrm{KKT}$ 条件.</strong></p><p>&nbsp;$\mathrm{KKT}$ 条件:<br>$$\begin{cases}\xi_i \geqslant 0\\\\\hat{\xi}_i \geqslant 0\\\\f(\boldsymbol{x}_i) - y_i - \epsilon - \xi_i \leqslant 0\\\\y_i - f(\boldsymbol{x}_i) - y_i - \epsilon - \hat{\xi}_i \leqslant 0\\\\\mu_i \geqslant 0\\\\\hat{\mu}_i \geqslant 0\\\\\alpha_i \geqslant 0\\\\\hat{\alpha}_i \geqslant 0\\\\\mu_i\xi_i = 0\\\\\hat{\mu}_i\hat{\xi}_i = 0\\\\\alpha_i(f(\boldsymbol{x}_i) - y_i - \epsilon - \xi_i) = 0\\\\\hat{\alpha}_i(y_i - f(\boldsymbol{x}_i) - y_i - \epsilon - \hat{\xi}_i) = 0\end{cases}$$</p><h2 id="6-8"><a href="#6-8" class="headerlink" title="6.8"></a>6.8</h2><p><strong>以西瓜数据集 $3.0\alpha$ 的 “密度” 为输入, “含糖率” 为输出, 试使用 $\mathrm{LIBSVM}$ 训练一个 $\mathrm{SVR}$.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/259787">《机器学习》西瓜书 第 6 章 编程实例</a></p><h2 id="6-9"><a href="#6-9" class="headerlink" title="6.9"></a>6.9</h2><p><strong>试使用核技巧推广对率回归, 产生 “核对率回归” .</strong></p><blockquote><p>可以发现, 如果使用対率损失函数 $\ell_{log}$ 来代替式 $(6.29)$ 中的 $0/1$ 损失函数, 则几乎就得到了対率回归模型 $(3.27)$ .</p></blockquote><p>我们根据原文, 将损失函数换成 $\ell_{log}$, 再使用核技巧, 就能实现 “核対率回归” .</p><h2 id="6-10"><a href="#6-10" class="headerlink" title="6.10*"></a>6.10*</h2><p><strong>试设计一个能显著减少 $\mathrm{SVM}$ 中支持向量的数目而不显著降低泛化性能的方法.</strong></p><p>可以将一些冗余的支持向量去除到只剩必要的支持向量. 比如在二维平面, 只需要 $3$ 个支持向量就可以表达一个支持向量机, 所以我们将支持向量去除到只剩 $3$ 个.</p><p>更广泛的情况是, 若是 $n$ 维平面, 那么只需要 $n + 1$ 个支持向量就能表达一个支持向量机.</p><h1 id="资料推荐"><a href="#资料推荐" class="headerlink" title="资料推荐"></a>资料推荐</h1><ul><li><a href="https://blog.csdn.net/v_july_v/article/details/7624837">支持向量机通俗导论（理解SVM的三层境界）</a></li></ul>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 西瓜书 </category>
          
          <category> 习题 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 西瓜书 </tag>
            
        </tags>
      
    </entry>
    
    
    
    
    
    <entry>
      <title>《机器学习》 西瓜书习题 第 5 章: 神经网络</title>
      <link href="/ML/watermelon_book/answer/5/"/>
      <url>/ML/watermelon_book/answer/5/</url>
      
        <content type="html"><![CDATA[<h1 id="习题"><a href="#习题" class="headerlink" title="习题"></a>习题</h1><h2 id="5-1"><a href="#5-1" class="headerlink" title="5.1"></a>5.1</h2><p><strong>试述将线性函数 $$f(\boldsymbol{x}) = \boldsymbol{w}^{\mathrm{T}}\boldsymbol{x}$$ 用作神经元激活函数的缺陷.</strong></p><p>理想中的激活函数是阶跃函数, 但是它不连续, 不光滑, 所以要一个连续、光滑的函数替代它. 线性函数虽然连续、光滑, 但是它跟阶跃函数并不是那么相似. 线性函数对 $$0$$ 周围的数值和对趋近 $$\infty$$ 的数值是一视同仁的, 而这样的性质我们并不需要, 我们更在乎那些处于 $$0$$ 周围的, 在被分为正 (大于 $$0$$ ) 还是负 (小于 $$0$$ ) 的界限边的 ‘模糊’ 的数值, 因此有了 $$\mathrm{Sigmoid}$$ 函数, 它的特点就是在 $$0$$ 周围输出急剧变化.</p><h2 id="5-2"><a href="#5-2" class="headerlink" title="5.2"></a>5.2</h2><p><strong>试述使用图 $$5.2(\mathrm{b})$$ 激活函数的神经元与对率回归的联系.</strong></p><p>这已经非常明显了, 対率回归的激活函数也是 $$Sigmoid$$ .</p><h2 id="5-3"><a href="#5-3" class="headerlink" title="5.3"></a>5.3</h2><p><strong>对于图 $$5.7$$ 中的 $$v_{ih}$$ 试推导出 $$\mathrm{BP}$$ 算法中的更新公式 $$(5.13)$$ .</strong></p><p>全部展开, 得<br>$$\begin{aligned}\Delta v_{ih} &= -\eta\frac{\partial E_k}{\partial b_h}\frac{\partial b_h}{\partial \alpha_h}x_i\\\\&=-\eta\frac{\partial E_k}{\partial b_h}\frac{\partial b_h}{\partial \alpha_h}\frac{\partial \alpha_h}{\partial v_{ih}}\\\\&=-\eta\frac{\partial E_k}{\partial v_{ih}}\end{aligned}$$<br>显然成立.</p><h2 id="5-4"><a href="#5-4" class="headerlink" title="5.4"></a>5.4</h2><p><strong>试述式 $$(5.6)$$ 中学习率的取值对神经网络训练的影响.</strong></p><p>学习率太低, 训练速度太慢. 学习率太高, 不容易收敛 (在极值点附近反复迭代) .</p><h2 id="5-5"><a href="#5-5" class="headerlink" title="5.5"></a>5.5</h2><p><strong>试编实现标准 $$\mathrm{BP}$$ 算法和积累 $$\mathrm{BP}$$ 算法, 在西瓜数据集 $$3.0$$ 上分别用这两个算法训练一个单隐层网络, 并进行比较.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/163796">《机器学习》西瓜书 第 3 章 编程实例</a></p><h2 id="5-6"><a href="#5-6" class="headerlink" title="5.6"></a>5.6</h2><p><strong>试设计一个 $$\mathrm{BP}$$ 改进算法, 能通过动态调整学习率显著提升收敛速度. 编程实现该算法, 并选择两个 $$\mathrm{UCI}$$ 数据集与标准 $$\mathrm{BP}$$ 算法进行实验比较.</strong></p><p>简单描述一下, 就是一开始学习率比较高 (来更快逼近) , 然后学习率慢慢变小 (提高精度) ,</p><h2 id="5-7"><a href="#5-7" class="headerlink" title="5.7"></a>5.7</h2><p><strong>根据式 $$(5.18)$$ 和 $$(5.19)$$ , 试构造一个能解决异或问题的单层 $$\mathrm{RBF}$$ 神经网络.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/163796">《机器学习》西瓜书 第 3 章 编程实例</a></p><h2 id="5-8"><a href="#5-8" class="headerlink" title="5.8"></a>5.8</h2><p><strong>从网上下载或自己编程实现 $$\mathrm{SOM}$$ 网络, 并观察其在西瓜数据集 $$3.0\alpha$$ 上产生的结果.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/163796">《机器学习》西瓜书 第 3 章 编程实例</a></p><h2 id="5-9"><a href="#5-9" class="headerlink" title="5.9*"></a>5.9*</h2><p><strong>试推导用于 $$\mathrm{Elman}$$ 网络的 $$\mathrm{BP}$$ 算法.</strong></p><p>说实话这个问题太变态了, 不过上网搜索一番总算是差不多弄懂了, 我自己估计说不清楚, 所以推荐<a href="https://zybuluo.com/hanbingtao/note/541458">零基础入门深度学习(5) - 循环神经网络</a>.</p><h2 id="5-10"><a href="#5-10" class="headerlink" title="5.10"></a>5.10</h2><p><strong>从网上下载或自己编程实现一个卷积神经网络, 并在手写字符识别数据 $$\mathrm{MNIST}$$ 上进行实验测试.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/163796">《机器学习》西瓜书 第 3 章 编程实例</a></p><h1 id="资料推荐"><a href="#资料推荐" class="headerlink" title="资料推荐"></a>资料推荐</h1><ul><li><a href="https://www.zybuluo.com/hanbingtao/note/433855">零基础入门深度学习系列</a></li><li><a href="https://www.jianshu.com/p/74bb815f612e">读懂反向传播算法（bp算法）</a></li></ul>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 西瓜书 </category>
          
          <category> 习题 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 西瓜书 </tag>
            
        </tags>
      
    </entry>
    
    
    
    
    
    <entry>
      <title>《机器学习》 西瓜书习题 第 4 章: 决策树</title>
      <link href="/ML/watermelon_book/answer/4/"/>
      <url>/ML/watermelon_book/answer/4/</url>
      
        <content type="html"><![CDATA[<h1 id="习题"><a href="#习题" class="headerlink" title="习题"></a>习题</h1><h2 id="4-1"><a href="#4-1" class="headerlink" title="4.1"></a>4.1</h2><p><strong>试证明对于不含冲突数据 (即特征向量完全相同但标记不同) 的训练集, 必存在与训练集一致 (即训练误差为 0)的决策树.</strong></p><p>既然每个标记不同的数据特征向量都不同, 只要树的每一条 (从根解点到一个叶节点算一条) 枝干代表一种向量, 这个决策树就与训练集一致.</p><h2 id="4-2"><a href="#4-2" class="headerlink" title="4.2"></a>4.2</h2><p><strong>试析使用 “最小训练误差” 作为决策树划分选择准则的缺陷.</strong></p><p>&nbsp;$4.1$ 说明了如果数据不冲突, 可以完全拟合数据集, 这正是使用 “最小训练误差” 作为决策树划分选择准则的结果. 而这是绝对的过拟合.</p><h2 id="4-3"><a href="#4-3" class="headerlink" title="4.3"></a>4.3</h2><p><strong>试编程实现基于信息熵进行划分选择的决策树算法, 并为表 $4.3$ 中数据生成一棵决策树.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/250517">《机器学习》西瓜书 第 3 章 编程实例</a></p><h2 id="4-4"><a href="#4-4" class="headerlink" title="4.4"></a>4.4</h2><p><strong>试编程实现基于基尼指数进行划分选择的决策树算法, 为表 $4.2$ 中数据生成预剪枝、后剪枝决策树, 并与未剪枝决策树进行比较.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/250517">《机器学习》西瓜书 第 3 章 编程实例</a></p><h2 id="4-5"><a href="#4-5" class="headerlink" title="4.5"></a>4.5</h2><p><strong>试编程实现基于対率回归进行划分选择的决策树算法, 并为表 $4.3$ 中数据生成一棵决策树.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/250517">《机器学习》西瓜书 第 3 章 编程实例</a></p><h2 id="4-6"><a href="#4-6" class="headerlink" title="4.6"></a>4.6</h2><p><strong>试选择 $4$ 个 $\mathrm{UCI}$ 数据集, 对上述 $3$ 种算法所产生的未剪枝、预剪枝、后剪枝决策树进行实验比较, 并进行适当的统计显著性检验.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/250517">《机器学习》西瓜书 第 3 章 编程实例</a></p><h2 id="4-7"><a href="#4-7" class="headerlink" title="4.7"></a>4.7</h2><p><strong>图 $4.2$ 是一种递归算法, 若面临巨量数据, 则决策树的层数会很深, 使用递归方法易导致 “栈” 溢出. 试使用 “队列” 数据结构, 以参数 $MaxDepth$ 控制树的最大深度, 写出与图 $4.2$ 等价、但不使用递归的决策树生成算法.</strong></p><p>伪代码:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 输入: 训练集 D</span></span><br><span class="line"><span class="comment">#      属性集 A</span></span><br><span class="line">array[<span class="number">0</span>] = [D, A]</span><br><span class="line"><span class="keyword">for</span> D, A <span class="keyword">in</span> array:</span><br><span class="line">    生成节点node;</span><br><span class="line">    <span class="keyword">if</span> D中样本全属于同一类别C:</span><br><span class="line">        将node标记为C类叶节点</span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line">    <span class="keyword">elif</span> A = 空 <span class="keyword">or</span> D中样本在A上取值相同:</span><br><span class="line">        将node标记为叶节点, 其类别标记为D中样本数最多的类</span><br><span class="line">        <span class="keyword">continue</span></span><br><span class="line">    从A中选择最优划分属性a</span><br><span class="line">    <span class="keyword">for</span> a_v <span class="keyword">in</span> a每个取值:</span><br><span class="line">        为node生成一个分支, 令D_v表示D在a上取值为a_v的样本子集</span><br><span class="line">        <span class="keyword">if</span> D_v == null:</span><br><span class="line">            将分支节点标记为叶节点, 其类别标记为D中样本最多的类</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        <span class="keyword">elif</span></span><br><span class="line">            array.append([D_v, A \ &#123;a&#125;])</span><br><span class="line"><span class="comment"># 输出: 以node为根节点的一棵决策树</span></span><br></pre></td></tr></table></figure></p><h2 id="4-8"><a href="#4-8" class="headerlink" title="4.8*"></a>4.8*</h2><p><strong>试将决策树生成的深度优先搜索过程修改为广度优先搜索, 以参数 $MaxNode$ 控制树的最大结点数, 将题 $4.7$ 中基于队列的决策树算法进行改写. 对比题 $4.7$ 中的算法, 试析哪种方式更易于控制决策树所需存储不超出内存.</strong></p><p>&nbsp;$4.7$ 其实已经是广度优先搜索了…</p><p>防止内存溢出就是要让深度优先搜索不要递归过深, 广度优先搜索不要太多结点在同一个深度, 因此如果树比较长, 建议用广度优先搜索, 如果树比较宽, 建议用深度优先搜索.</p><h2 id="4-9"><a href="#4-9" class="headerlink" title="4.9"></a>4.9</h2><p><strong>试将 $4.4.2$ 节对缺失值的处理机制推广到基尼指数的计算中去.</strong></p>$$\rho = \frac{\sum_{\boldsymbol{x}\in\tilde{D}}w_{\boldsymbol{x}}}{\sum_{\boldsymbol{x}\in D}w_{\boldsymbol{x}}}$$$$\tilde{p}_k = \frac{\sum_{x\in \tilde{D}_k}w_{\boldsymbol{x}}}{\sum_{x\in \tilde{D}}w_{\boldsymbol{x}}}\quad{(1 \leqslant k \leqslant |\mathcal{Y}|)}$$$$\tilde{r}_v = \frac{\sum_{\boldsymbol{x}\in \tilde{D}^v}w_{\boldsymbol{x}}}{\sum_{\boldsymbol{x}\in \tilde{D}}w_{\boldsymbol{x}}}\quad{(1 \leqslant v \leqslant V)}$$<p>&nbsp;$w_{\boldsymbol{x}}$ 是权值, 初始化为 $1$ .</p><p>那么推广后的基尼指数为:<br>$$\mathrm{Gini}(D) = 1 - \sum_{k = 1}^{|\mathcal{Y}|}\tilde{p}_k^2$$</p>$$\mathrm{Gini\_index}(D, a) = \rho\sum_{v = 1}^{V}\tilde{r}_v\mathrm{Gini}(\tilde{D}^v)$$<p>同时如果按某属性 $a$ 划分, 那么某个缺失该属性的样本按照总体属性比例改变权值进入下一结点 (见书 $\mathrm{P}88$).</p><h2 id="4-10"><a href="#4-10" class="headerlink" title="4.10"></a>4.10</h2><p><strong>从网上下载或自己编程实现任意一种多变量决策树算法, 并观察其在西瓜数据集 $3.0$ 上产生的结果.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/250517">《机器学习》西瓜书 第 3 章 编程实例</a></p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 西瓜书 </category>
          
          <category> 习题 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 西瓜书 </tag>
            
        </tags>
      
    </entry>
    
    
    
    
    
    <entry>
      <title>《机器学习》 西瓜书习题 第 3 章: 线性模型</title>
      <link href="/ML/watermelon_book/answer/3/"/>
      <url>/ML/watermelon_book/answer/3/</url>
      
        <content type="html"><![CDATA[<h1 id="习题"><a href="#习题" class="headerlink" title="习题"></a>习题</h1><h2 id="3-1"><a href="#3-1" class="headerlink" title="3.1"></a>3.1</h2><p><strong>试析在什么情况下式 $(3.2)$ 中不必考虑偏置项 $b$ .</strong></p><p>书中有提到, 可以把 $x$ 和 $b$ 吸收入向量形式 $\hat{w} = (w;b)$ .此时就不用单独考虑 $b$ 了.</p><p>其实还有很多情况不用, 比如说使用了 $\mathrm{one-hot}$ 编码, 就可以不用考虑偏置项.</p><p>更广泛的情况是, 如果偏置项 $b$ 可以被 “包含” 在另外的一些离散特征里, 那么就不用考虑. 就是偏置项可以以一定系数加到离散特征中. (可能看了还是不太懂, 我以后有时间会重写一个的.)</p><h2 id="3-2"><a href="#3-2" class="headerlink" title="3.2"></a>3.2</h2><p><strong>试证明, 对于参数 $w$, 对率回归的目标函数 $(3.18)$ 是非凸的, 但其对数似然函数 $(3.27)$ 是凸的.</strong></p>$$y = \frac{1}{1 + e^{-(\boldsymbol w^\mathrm T\boldsymbol x + b)}}\tag{3.18}$$$$\ell(\boldsymbol\beta) = \sum^m_{i = 1}(-y_i\boldsymbol \beta^\mathrm T\boldsymbol{\hat{x}}_i)\tag{3.18}$$<p>计算其海森矩阵, 判断是否正定. 海森矩阵可以类比成一元函数的二阶导, 正定可以类比为二阶导恒大于 $0$ .</p><h2 id="3-3"><a href="#3-3" class="headerlink" title="3.3"></a>3.3</h2><p><strong>编程实现対率回归, 并给出西瓜数据集 $3.0\alpha$ 上的结果.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/238277">《机器学习》西瓜书 第 3 章 编程实例</a></p><h2 id="3-4"><a href="#3-4" class="headerlink" title="3.4"></a>3.4</h2><p><strong>选择两个 $\mathrm{UCI}$ 数据集, 比较 $10$ 折交叉验证法和留一法所估计出的错误率.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/238277">《机器学习》西瓜书 第 3 章 编程实例</a></p><h2 id="3-4-1"><a href="#3-4-1" class="headerlink" title="3.4"></a>3.4</h2><p><strong>编程实现线性判别分析, 并给出西瓜数据集 $3.0\alpha$ 上的结果.</strong></p><p><a href="https://aistudio.baidu.com/aistudio/projectdetail/238277">《机器学习》西瓜书 第 3 章 编程实例</a></p><h2 id="3-6"><a href="#3-6" class="headerlink" title="3.6"></a>3.6</h2><p><strong>线性判别分析仅在线性可分数据上能获得理想结果, 试设计一个改进方法, 使其能较好地用于飞线性可分数据.</strong></p><p>像 $6.3$ 节介绍的那样, 使用核函数, 就可以运用于非线性可分数据.</p><h2 id="3-7"><a href="#3-7" class="headerlink" title="3.7"></a>3.7</h2><p><strong>令码长为 $9$, 类别数为 $4$ , 试给出海明距离意义下理论最优的 $\mathrm{ECOC}$ 二元码并证明之.</strong></p><p>首先要给出理论最优, 我们先要确定 ‘最优’ 的指导标准.</p><blockquote><p> 对同等长度的编码, 理论上来说, 任意两个类别之间的编码距离越远, 则纠错能力越强.</p></blockquote><p>我们要将 ‘任意两个类别的编码距离’ 用数学表达, 这样才能进行求解. 那么怎么用数学表达这个 ‘距离’ 呢? 这里考虑到 ‘总体距离最大’ , 同时我们还要保证每两个类别之间的反码的距离也 ‘最大’ , 所以我们浅显的使用每两个类别之间的海明距离乘和其反码的海明距离的积来作为衡量标准(有点绕),  我们定义一个变量 $L$ 用来表达这个积, 也就是有<br>$$L = \prod_{1\leqslant i< j\leqslant 4}dis(r_i, r_j)dis(r_i, -r_j)$$<br>&nbsp;$dis(r_i, r_j)$ 表示第 $i$ 个编码和第 $j$ 个编码之间的海明距离, $dis(r_i, r_j)$ 表示第 $i$ 个编码和第 $j$ 个编码的反码之间的海明距离. $L$ 越大代表这种编码方式越好.</p><p>于是我写了段程序来搜索 $L$ 的最大值 <del>(直接爆搜)</del> .</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;cmath&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXCOL = <span class="number">9</span>;  <span class="comment">// 码长为 9 </span></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXROW = <span class="number">4</span>;  <span class="comment">// 类别数为 4 </span></span><br><span class="line"></span><br><span class="line"><span class="type">bool</span> code[MAXROW][MAXCOL];  <span class="comment">// 记录最大值时编码排列</span></span><br><span class="line"><span class="type">bool</span> temp_code[MAXROW][MAXCOL];  <span class="comment">// 表示当前编码排列</span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> mmax = <span class="number">0</span>;  <span class="comment">// 记录最大值</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">dif_val</span><span class="params">(<span class="type">bool</span> a[MAXCOL], <span class="type">bool</span> b[MAXCOL])</span></span>&#123;  <span class="comment">// 求两个编码之间的海明距离</span></span><br><span class="line">    <span class="type">int</span> cnt1 = <span class="number">0</span>;</span><br><span class="line">    <span class="type">int</span> cnt2 = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span> ; i &lt; MAXCOL ; ++i)&#123;</span><br><span class="line">        <span class="keyword">if</span>(a[i] != b[i])    ++cnt1;</span><br><span class="line">        <span class="keyword">if</span>(a[i] == b[i])++cnt2;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> cnt1 * cnt2;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">cost</span><span class="params">(<span class="type">bool</span> code[MAXROW][MAXCOL])</span></span>&#123;  <span class="comment">// 求当前编码排列的 L</span></span><br><span class="line">    <span class="type">int</span> res = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span> ; i &lt; MAXROW ; ++i)&#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> j = i + <span class="number">1</span> ; j &lt; MAXROW ; ++j)&#123;</span><br><span class="line">            res *= <span class="built_in">dif_val</span>(code[i], code[j]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> row = <span class="number">2</span>, <span class="type">int</span> col = <span class="number">0</span>)</span></span>&#123;  <span class="comment">// 深度优先搜索, 枚举每个位置的编码 (0 和 1)</span></span><br><span class="line">    <span class="keyword">if</span>(row == MAXROW)    <span class="keyword">return</span>;  <span class="comment">// 边界条件</span></span><br><span class="line">    temp_code[row][col] = <span class="number">1</span>;  <span class="comment">// 先枚举 1</span></span><br><span class="line">    <span class="type">int</span> temp = <span class="built_in">cost</span>(temp_code);</span><br><span class="line">    <span class="keyword">if</span>(mmax &lt; temp)&#123;  <span class="comment">// 发现更好的编码排列, 进行更新</span></span><br><span class="line">        mmax = temp;</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span> ; i &lt; MAXROW ; ++i)</span><br><span class="line">            <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">0</span> ; j &lt; MAXCOL ; ++j)</span><br><span class="line">                code[i][j] = temp_code[i][j];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(col == MAXCOL - <span class="number">1</span>)    <span class="built_in">dfs</span>(row + <span class="number">1</span>, <span class="number">0</span>);  <span class="comment">// 下一层</span></span><br><span class="line">    <span class="keyword">else</span>    <span class="built_in">dfs</span>(row, col + <span class="number">1</span>);</span><br><span class="line">    temp_code[row][col] = <span class="number">0</span>;  <span class="comment">// 返回再枚举 0</span></span><br><span class="line">    temp = <span class="built_in">cost</span>(temp_code);</span><br><span class="line">    <span class="keyword">if</span>(mmax &lt; temp)&#123;  <span class="comment">// 同上</span></span><br><span class="line">        mmax = temp;</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span> ; i &lt; MAXROW ; ++i)</span><br><span class="line">            <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">0</span> ; j &lt; MAXCOL ; ++j)</span><br><span class="line">                code[i][j] = temp_code[i][j];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(col == MAXCOL - <span class="number">1</span>)    <span class="built_in">dfs</span>(row + <span class="number">1</span>, <span class="number">0</span>);  <span class="comment">// 同上</span></span><br><span class="line">    <span class="keyword">else</span>    <span class="built_in">dfs</span>(row, col + <span class="number">1</span>);</span><br><span class="line">    <span class="keyword">return</span> ;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span> ; i &lt; MAXCOL ; ++i)&#123;</span><br><span class="line">        temp_code[<span class="number">0</span>][i] = <span class="number">1</span>;  <span class="comment">// 不失一般性, 令第一个类别的编码全部为 1 </span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span> ; i &lt;= MAXCOL ; ++i)&#123;  <span class="comment">// 不失一般性, 枚举第二个类别 1 的数量 (1 ~ 9)</span></span><br><span class="line">        temp_code[<span class="number">1</span>][i - <span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line">        <span class="built_in">dfs</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span> ; i &lt; MAXROW ; ++i)&#123;  <span class="comment">// 打印最终结果</span></span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">0</span> ; j &lt; MAXCOL ; ++j)&#123;</span><br><span class="line">            cout &lt;&lt; code[i][j] &lt;&lt; <span class="string">&#x27; &#x27;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        cout &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    cout &lt;&lt; mmax;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;  <span class="comment">// 我的码风是不是很好看</span></span><br></pre></td></tr></table></figure><p>结果:</p><div class="table-container"><table><thead><tr><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center">3</th><th style="text-align:center">4</th><th style="text-align:center">5</th><th style="text-align:center">6</th><th style="text-align:center">7</th><th style="text-align:center">8</th><th style="text-align:center">9</th></tr></thead><tbody><tr><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">1</td></tr><tr><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">0</td><td style="text-align:center">0</td><td style="text-align:center">0</td><td style="text-align:center">0</td><td style="text-align:center">0</td></tr><tr><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">0</td><td style="text-align:center">0</td><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">0</td><td style="text-align:center">0</td></tr><tr><td style="text-align:center">1</td><td style="text-align:center">1</td><td style="text-align:center">0</td><td style="text-align:center">0</td><td style="text-align:center">1</td><td style="text-align:center">0</td><td style="text-align:center">0</td><td style="text-align:center">1</td><td style="text-align:center">1</td></tr></tbody></table></div><p>64000000</p><p>当然我们要把 $0$ 换成 $-1$.</p><p>所以, 我们求出了海明距离下理论最优的, 码长为 $9$, 类别数为 $4$ 的 $\mathrm{EOOC}$ 二元码. 至于证明, 在我们定义的衡量标准下, 其正确性是显然的.</p><h2 id="3-8"><a href="#3-8" class="headerlink" title="3.8*"></a>3.8*</h2><p><strong>$\mathrm{EOOC}$ 编码能起到理想纠错作用的重要条件是: 在每一位编码上出错的概率相当且独立. 试析多分类任务经 $\mathrm{EOOC}$ 编码后产生的二类分类器满足该条件的可能性及由此产生的影响.</strong></p><p>&nbsp;$\mathrm{EOOC}$ 编码不仅要和其他编码距离尽量大, 还要和其他编码的反码距离也要大. 这是因为每个二类分类器的错误可能相似. 考虑一个极端情况, 要是错误完全相同, 那么分类器出错的后果就是输出码为原来的反码.</p><h2 id="3-9"><a href="#3-9" class="headerlink" title="3.9"></a>3.9</h2><p><strong>使用 $\mathrm{OvR}$ 和 $\mathrm{MvM}$ 将多分类任务分解为二分类任务求解时, 试述为何无需专门针对类别不平衡性进行处理.</strong></p><p>原文就已经提到</p><blockquote><p>对 $\mathrm{OvR}$ 、$\mathrm{MvM}$ 来说, 由于对每个类进行了相同的处理, 其拆解出的二分类任务中类别不平衡的影响会相互抵消, 因此通常不需要专门处理.</p></blockquote><h2 id="3-10"><a href="#3-10" class="headerlink" title="3.10*"></a>3.10*</h2><p><strong>试推导出多分类代价敏感学习 (仅考虑基于类别的误分类代价) 使用 “再缩放” 能获得理论最优解的条件.</strong></p><p>原文中提到</p><blockquote><p>再缩放的思想虽简单, 但实际操作却并不平凡, 主要因为 “训练集是真实样本总体的无偏采样” 这个假设往往并不成立.</p></blockquote><p>因此假设成立应该也算是获得理论最优解的一个条件(<del>好水啊</del>).</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 西瓜书 </category>
          
          <category> 习题 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 西瓜书 </tag>
            
        </tags>
      
    </entry>
    
    
    
    
    
    <entry>
      <title>《机器学习》 西瓜书习题 第 2 章: 模型评估与选择</title>
      <link href="/ML/watermelon_book/answer/2/"/>
      <url>/ML/watermelon_book/answer/2/</url>
      
        <content type="html"><![CDATA[<h1 id="习题"><a href="#习题" class="headerlink" title="习题"></a>习题</h1><h2 id="2-1"><a href="#2-1" class="headerlink" title="2.1"></a>2.1</h2><p><strong>数据集包含 $1000$ 个样本, 其中 $500$ 个正例、$500$ 个反例, 将其划分为包含 $70\%$ 样本的训练集和 $30\%$ 样本的测试集用于留出法评估, 试估算共有多少种划分方式.</strong></p><p>如果划分要保证正例和反例一样多的话, 那么划分方式数量 $n$ 有<br>$$\begin{aligned}n &= C^{500\times35\%}{500}\times C{500}^{500\times 35\%}\\\\&=(C^{175}_{500})^{2}\end{aligned}$$<br>如果不考虑的话则有<br>$$n = C^{500\times 70\%}_{500}=C^{350}_{500}$$</p><h2 id="2-3"><a href="#2-3" class="headerlink" title="2.3"></a>2.3</h2><p><strong>数据集包含 $100$ 个样本, 其中正、反例各一半, 假定学习算法所产生的模型是将新样本预测为训练样本数较多的类别 (训练样本数相同时进行随机猜测) , 试给出用 $10$ 折交叉验证法和留一法分别对错误率进行评估所得的结果.</strong></p><p>&nbsp;$10$ 折交叉验证, 我们认为划分是随意的, 那么根据对称性可知, 对于每个子集来说正例更多的概率为 $\frac{1}{2}$ , 反例也是一样, 所以预测测试集相当于随机预测, 即错误率为 $50\%$ .</p><p>而留一法要么选择一个正例作为测试集, 要么选择一个反例, 无论是哪一种, 总会预测与测试集相反的结果, 即正确率为 $0\%$ .</p><p>这告诉我们留一法并不一定比交叉验证法更 ‘好’ . 而要看具体情况选择要划分为几个子集 (即几折交叉验证, 而留一法只是交叉验证法的特例, 即子集数等于样本数, 每个子集包含一个样本) .</p><h2 id="2-3-1"><a href="#2-3-1" class="headerlink" title="2.3"></a>2.3</h2><p>**若学习器 $\mathrm{A}$ 的 $\mathrm{F1}$ 值比学习器 $\mathrm{B}$ 高, 试析 $\mathrm{A}$ 的 $\mathrm{BEP}$ 值是否也比 $\mathrm{B}$ 高.</p><p>&nbsp;$\mathrm{F1}$ 值和  并没有必然联系, 很容易就可以找出一个反例.</p><p>&nbsp;$\mathrm{F1}\,$$ 值和 $\mathrm{BEP}\,$$ 并没有必然联系, 很容易就可以找出一个反例.## 2.4**试述真正例率 $(\mathrm{TPR})$、假正例率 $(\mathrm{FPR})$ 与查准率 $(\mathrm{P})$ 、查全率 $(\mathrm{R})$ 之间的联系.**根据表 &nbsp;$2.1$ 分类结果混淆矩阵|预测结果<br>真实情况|正例|反例||:-:|:-:|:-:||正例|$\mathrm{TP}$ (真正例)|$\mathrm{FN}$ (假反例)||反例|$\mathrm{FP}$ (假正例)|$\mathrm{TN}$ (假反例)|则有$$\begin{aligned}\mathrm{TPR} = \frac{\mathrm{TP}}{\mathrm{TP}+\mathrm{FN}}\\\\\mathrm{FPR} = \frac{\mathrm{FP}}{\mathrm{FP} + \mathrm{TN}}\\\\\mathrm{P} = \frac{\mathrm{TP}}{\mathrm{TP} + \mathrm{FP}}\\\\\mathrm{R} = \frac{\mathrm{TP}}{\mathrm{TP} + \mathrm{FN}}\end{aligned}$$## 2.5**试证明式 $(2.22)$.**$$\begin{aligned}\ell_{rank} = \frac{1}{m^+m^-}\sum_{\boldsymbol{x}^+\in D^+}\sum_{\boldsymbol{x}^-\in D^-}\Big(\mathbb{I}\big(f(\boldsymbol{x^+}) < f(\boldsymbol{x^-})\big)+\frac{1}{2}\mathbb{I}\big(f(\boldsymbol{x^+})=f(\boldsymbol{x^-})\big)\Big)\end{aligned}\tag{2.21}$$$$AUC = 1 - \ell_{rank}\tag{2.22}$$其实只要去分解 $(2.21)$ 就能发现它求的是 $\mathrm{ROC}$ 曲线每一小段的右边的面积之和. $\frac{1}{m^+m^-}$ 求的是单位矩形的面积, $\sum\limits<em>{\boldsymbol{x}^-\in D^-}\mathbb{I}\big(f(\boldsymbol{x^-}) &lt; f(\boldsymbol{x^-})\big)$ 求的是左边有多少个单位矩形, $\sum\limits</em>{\boldsymbol{x}^+\in D^+}$ 是对每一段都进行上述求和, 而 $\frac{1}{2}\mathbb{I}\big(f(\boldsymbol{x^+})=f(\boldsymbol{x^-})\big)$ 则是考虑到了斜线的结果 (某个正例和反例的分类概率相同) .## 2.6**试述错误率与 $\mathrm{ROC}$ 曲线的联系.**错误率越低, $\mathrm{ROC}$ 曲线越凸. 是长得凸, 跟凸函数不一样.## 2.7**试证明任意一条 $\mathrm{ROC}$ 曲线都有一条代价曲线与之对应, 反之亦然.**想象我们现在有一条 $\mathrm{ROC}$ 曲线, 根据书上的方法我们可以画出有且仅有一条代价曲线. 因此第一个问题得证. 至于第二个问题, 反之应该不亦然, 观察书中图 `2.5 代价曲线与期望总体代价` 可以发现有些线段是无法 '影响' 代价曲线的 (整体在曲线上方且不作为某点切线), 因此我们可以认为在画出代价曲线的同时我们损失了信息, 因此我们无法仅通过代价曲线 '还原' $\mathrm{ROC}$ 曲线, 所以反之不亦然. 但是如果有无穷多数据以致 $\mathrm{ROC}$ 曲线与代价曲线变得光滑 (处处可导), 那么是可以成立的(但是这样的前提 `数据无穷多` 根本无法成立).## 2.8**$\mathrm{Min-max}$ 规范化和 $\mathrm{z-score}$ 规范化是两种常用的规范化方法. 令 $x$ 和 $x’$ 分别表示变量在规范化前后的取值, 相应的, 令 $x<em>{min}$ 和 $x</em>{max}$ 表示规范化前的最小值和最大值, $x’<em>{min}$ 和 $x’</em>{max}$ 表示规范化后的最小值和最大值, $\bar{x}$ 和 $\sigma_x$ 分别表示规范化前的均值和标准差, 则 $\mathrm{min-max}$ 规范化、$\mathrm{z-score}$ 规范化分别如式 $(2, 43)$ 和 $(2, 44)$ 所示. 试析二者的优缺点.**$$x' = x'_{min} + \frac{x - x_{min}}{x_{max} - x_{min}}\times (x'_{min} - x'{max}), \tag{2.43}$$$$x' = \frac{x - \bar{x}}{\sigma_x}. \tag{2.44}$$&nbsp;$\mathrm{z-score}$ 是最常用的规范化, 可令样本均值为 $0$ , 标志差和方差为 $1$ , 这样的好处是可以使用相应的标准 (比如标准正态分布). $\mathrm{Min-max}$ 规范化让数据分布在 $[min’, max’]$. $\mathrm{Min-max}$ 优点在于新加入数据不大于最大值以及不小于最小值时不需要重新计算, 但缺点在于如果有极端值 (极大或极小) 会导致其他点几乎缩成一个点.  $\mathrm{z-score}$ 的优点已说过, 缺点就是加入新数据时必须重新计算. 归一化还可以加快训练速度.## 2.9**试述 $\chi^2$ 检验过程.**&nbsp;$\chi^2$ 中文称卡方检验.>卡方检验就是统计样本的实际观测值与理论推断值之间的偏离程度，实际观测值与理论推断值之间的偏离程度就决定卡方值的大小，如果卡方值越大，二者偏差程度越大；反之，二者偏差越小；若两个值完全相等时，卡方值就为0，表明理论值完全符合。注意：卡方检验针对分类变量。$$\chi^2 = \sum_{i= 1}^{k}\frac{(f_i - np_i)^2}{np_i}\tag{1}$$假设有两个随机变量 $X$ 和 $Y$ , 值域为 ${x_1, x_2}$ 和 ${y_1, y_2}$, 其样本频数列联表为||$y_1$|$y_2$|总计||:--------------:|:-------------:|:-------------:|:---------:||$x_1$|$a$|$b$|$a+b$||$x_2$|$c$|$d$|$c+d$||总计|$a+c$|$b+d$|$a+b+c+d$|&nbsp;$H_1$: $X$ 与 $Y$ 有关系.&nbsp;$H_0$: $X$ 与 $Y$ 没有关系.那么根据 $(1)$ 有$$\chi^2 = \frac{n(ad-bc)^2}{(a+b)(c+d)(a+c)(b+d)}$$自由度$$v=(行数-1)(列数-1) = 1$$ , 然后查表, 得到 $H_1$ 成立的概率, 按需要决定是否接受原假设.## 2.10***试述在 $\mathrm{Friedman}$ 检验中使用式 $(2.34)$ 与 $(2.35)$ 的区别.**式 $(2.34)\,$$ 没有考虑多个数据集之间的影响, 因此说太保守.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 西瓜书 </category>
          
          <category> 习题 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 西瓜书 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>《机器学习》 西瓜书习题 第 1 章: 绪论</title>
      <link href="/ML/watermelon_book/answer/1/"/>
      <url>/ML/watermelon_book/answer/1/</url>
      
        <content type="html"><![CDATA[<h1 id="习题"><a href="#习题" class="headerlink" title="习题"></a>习题</h1><h2 id="1-1"><a href="#1-1" class="headerlink" title="1.1"></a>1.1</h2><p><strong>表 $1.1$ 中若只包含编号为 $1$ 和 $4$ 的两个样例, 试给出相应的版本空间.</strong></p><p>这应该不难理解吧，直接上表格.</p><div class="table-container"><table><thead><tr><th style="text-align:center">编号</th><th style="text-align:center">色泽</th><th style="text-align:center">根蒂</th><th style="text-align:center">敲声</th><th style="text-align:center">好瓜</th></tr></thead><tbody><tr><td style="text-align:center">$1$</td><td style="text-align:center">青绿</td><td style="text-align:center">蜷缩</td><td style="text-align:center">浊响</td><td style="text-align:center">是</td></tr><tr><td style="text-align:center">$4$</td><td style="text-align:center">乌黑</td><td style="text-align:center">稍蜷</td><td style="text-align:center">沉闷</td><td style="text-align:center">否</td></tr></tbody></table></div><h2 id="1-2"><a href="#1-2" class="headerlink" title="1.2"></a>1.2</h2><p><strong>与使用单个合取式来进行假设表示相比, 使用 “析合范式” 将使得假设空间具有更强的表示能力. 例如</strong><br>$$好瓜 \leftrightarrow \big((色泽=*)\wedge(根蒂=蜷缩)\wedge(敲声=*)\big)\vee\big((色泽=乌黑)\wedge(根蒂=*)\wedge(敲声=沉闷)\big)$$<br><em>*会把 “$(色泽=*)\wedge(根蒂=蜷缩)\wedge(敲声=*)\,$$" 以及 "$(色泽=乌黑)\wedge(根蒂=</em>)\wedge(敲声=沉闷)\,$$" 都分类为 "好瓜" . 若使用最多包含 $k\,$$ 个合取式的析合范式来表达 $1.1\,$$ 西瓜分类问题的假设空间, 试估算共有多少种可能的假设.**一共有 $3$ 个特征, 第一个特征有 $3$  种取值(算上 $<em>$ ), 第二, 三个都是 $4$ 种取值.每个合取式我们分为三项:色泽, 根蒂, 敲声.这里要注意某个项其实是可以同时选择两种取值的, 比如色泽这一项可以是 $\big((色泽=青绿)\wedge(色泽=乌黑)\big)$ 而不是只能有一个取值.那么第一项只可能选择一个或两个取值, 取值是一个时有 $3$ 种可能, 取值为两种时只有 $1$ 种可能(即除了 $</em>$ 外的另两种一起取到),  其他项以此类推, 那么就有 $4\times7\times7=196$ 种合取式, 因此 $k<em>{ma\boldsymbol{x}}=196$. 所以可能的假设总数为 $\sum^{k</em>{ma\boldsymbol{x}}}<em>{i=1}C</em>{k<em>{ma\boldsymbol{x}}}^i$ , 即任意取 $1\sim k</em>{ma\boldsymbol{x}}$个合取式然后组合成的析合范式的数量.当然我们这里不考虑冗余 ~~(因为我懒)~~ .## 1.3**若数据包含噪声, 则假设空间中有可能不存在与所有训练样本都一致的假设. 在此情形下, 试设计一种归纳偏好用于假设选择.**当然是奥卡姆剃刀啦, "如无必要, 勿增实体", 大概体现了一种哲学思想吧.## 1.4***本章 $1.4$ 节在论述 "没有免费的午餐" 定理时, 默认使用了 "分类错误率" 作为性能度量来对分类器进行评估. 若换用其他性能度量 $\ell$ ,则将式$(1.1)$改为**$$E_{ote}(\mathfrak{L}_a\mid X,f)=\sum_h\sum_{\boldsymbol{\boldsymbol{x}}\in \mathcal{X}-X}P(\boldsymbol{\boldsymbol{x}})\ell(h(\boldsymbol{\boldsymbol{x}}),f(\boldsymbol{\boldsymbol{x}}))P(h\mid X,\mathfrak{L}_a)$$**试证明 "没有免费的午餐定理" 仍成立.**其实和原来的推导差不多. 对所有可能的 $f$ 按均匀发布对误差求和, 有$$\begin{aligned}\sum_fE{ote}(\mathfrak{L}a\mid X,f)&=\sum_f\sum_h\sum{\boldsymbol{x}\in \mathcal{X}-X}P(\boldsymbol{x})\ell(h(\boldsymbol{x}),f(\boldsymbol{x}))P(h\mid X,\mathfrak{L}a)\\\\&=\sum_{\boldsymbol{x}\in\mathcal{X}-X}P(\boldsymbol{x})\sum_hp(h\mid X,\mathfrak{L})\sum_f\ell(h(\boldsymbol{x}),f(\boldsymbol{x}))\\\\&=\sum_{\boldsymbol{x}\in\mathcal{X}-X}P(\boldsymbol{x})\sum_hp(h\mid X,\mathfrak{L})E(\ell)\\\\&=E(\ell)\sum_{\boldsymbol{x}\in\mathcal{X}-X}P(\boldsymbol{x})\sum_hp(h\mid X,\mathfrak{L})\\\\&=E(\ell)\sum_{\boldsymbol{x}\in\mathcal{X}-X}P(\boldsymbol{x})\cdot1\\\\&=E(\ell)\sum_{\boldsymbol{x}\in\mathcal{X}-X}P(\boldsymbol{x})\end{aligned}$$&nbsp;$E(\ell)$ 为 $\ell$ 的数学期望(就是 $\ell$ 这个函数所有可能输出的均值去乘 $2^{|\mathcal{X}|}$, 因为 $f$ 是任意的. ~~反正是个常数.~~).最终表达式与学习算法 $\mathfrak{L}$ 无关, 于是$$\sum_fE_{ate}(\mathfrak{L}\mid X,f)=\sum_fE_{ate}(\mathfrak{L}\mid X,f)$$<br>所以 “没有免费的午餐定理” 仍成立.</p><h2 id="1-5"><a href="#1-5" class="headerlink" title="1.5"></a>1.5</h2><p><strong>试述机器学习能在互联网搜索的哪些环节起什么作用.</strong></p><p>这个就多了, 比如搜索引擎, 图片搜索, 智能化推荐, 还有很多很多. 当然你还可以用机器学习来破解反爬虫, 比如识别简单的验证码.</p>]]></content>
      
      
      <categories>
          
          <category> 机器学习 </category>
          
          <category> 西瓜书 </category>
          
          <category> 习题 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 机器学习 </tag>
            
            <tag> 习题 </tag>
            
            <tag> 西瓜书 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Hello World</title>
      <link href="/HelloWorld/"/>
      <url>/HelloWorld/</url>
      
        <content type="html"><![CDATA[<h1 id="测试用文章"><a href="#测试用文章" class="headerlink" title="测试用文章"></a>测试用文章</h1><p><img src="HelloWorld.png" alt=""></p><p> 行列式具有良好的性质, 通常它是线性代数中较为基本的内容. 而行列式有非常直观的几何性质, 它是矩阵中以向量为棱的平行四边形 (六面体) 的有向体积, 当维数超过三维时, 有类似的结果, 我们可以称其为 “广义平行六面体” 的有向体积. 我们给出广义平行六面体体积的一个递归定义. 设 $A$ 为 $n\times n$ 矩阵, 其中第 $k$ 行向量 $L$ 即为广义平行六面体 $V$ 的一个棱,<br>$$\newcommand\xrule{\rule[.5ex]{2em}{.4pt}}\left[\begin{matrix}\xrule& L_1&\xrule\\\\\xrule &L_2&\xrule\\\\\vdots \\\\\xrule &L_m&\xrule\\\\\end{matrix}\right]=\left[\begin{matrix}\xrule &H+G&\xrule\\\\\xrule &L_2&\xrule\\\\\vdots\\\\\xrule &L_m&\xrule\\\\\end{matrix}\right]$$<br>以 $L_2,L_3,\dots L_n$ 作为棱的平行六面体为 $V$ 的底,<br>$$\newcommand\lrule{\rule[.5ex]{.4pt}{2em}}A^*{A^*}^{\mathrm{T}}=\left[\begin{matrix}\xrule&H&\xrule\\\\\xrule &D&\xrule\\\\\end{matrix}\right]\left[\begin{matrix}\lrule&\lrule\\\\H^{\mathrm T}&D^\mathrm T\\\\\lrule &\lrule\\\\\end{matrix}\right]$$</p>]]></content>
      
      
      
    </entry>
    
    
  
  
</search>
