<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Daisy's Blog]]></title><description><![CDATA[Daisy's Blog]]></description><link>https://blog.petals.top</link><image><url>https://cdn.hashnode.com/uploads/logos/69fff364e3eebc2e2021e3fe/e7f9fb17-2cb0-463b-9d6a-24099e9b48f2.png</url><title>Daisy&apos;s Blog</title><link>https://blog.petals.top</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 10 May 2026 05:48:03 GMT</lastBuildDate><atom:link href="https://blog.petals.top/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[共轭梯度：一种高中解析几何的视角]]></title><description><![CDATA[本文没有任何数学推导。我们从直观上理解这个算法，然后直接介绍算法的流程。希望了解数学推导的读者可以查看 CMU 的教案 及其 翻译 。
1. 问题
对于实对称矩阵 \( A \in \mathbb{R}^{n \times n} \) 和向量 \( b \in \mathbb{R}^n \) ，求解
$$Ax = b$$
或者，等价的，
$$\text{argmin}_x f(x)$$
其中
$$]]></description><link>https://blog.petals.top/cg-geometry-perspective</link><guid isPermaLink="true">https://blog.petals.top/cg-geometry-perspective</guid><dc:creator><![CDATA[Da1sy petals]]></dc:creator><pubDate>Sun, 10 May 2026 03:29:29 GMT</pubDate><content:encoded><![CDATA[<p>本文没有任何数学推导。我们从直观上理解这个算法，然后直接介绍算法的流程。希望了解数学推导的读者可以查看 <a href="https://www.cs.cmu.edu/~quake-papers/painless-conjugate-gradient.pdf">CMU 的教案</a> 及其 <a href="https://flat2010.github.io/2018/10/26/%E5%85%B1%E8%BD%AD%E6%A2%AF%E5%BA%A6%E6%B3%95%E9%80%9A%E4%BF%97%E8%AE%B2%E4%B9%89/#8-%E5%85%B1%E8%BD%AD%E6%A2%AF%E5%BA%A6%E6%B3%95">翻译</a> 。</p>
<h2>1. 问题</h2>
<p>对于实对称矩阵 \( A \in \mathbb{R}^{n \times n} \) 和向量 \( b \in \mathbb{R}^n \) ，求解</p>
<p>$$Ax = b$$</p>
<p>或者，等价的，</p>
<p>$$\text{argmin}_x f(x)$$</p>
<p>其中</p>
<p>$$f(x) = \frac{1}{2}x^T A x - b^T x$$</p>
<h2>2. 预备知识</h2>
<h3>2.1. 从高中学的二级结论说起</h3>
<p>高中的时候我们学过椭圆：</p>
<p>$$a^{-2}x^2 + b^{-2}y^2 = 1$$</p>
<p>如果你记性好的话，你应该记得这个二级结论：</p>
<img src="https://cdn.hashnode.com/uploads/covers/69fff364e3eebc2e2021e3fe/bb6a4f0c-07ed-43b6-90cc-57fc347cbf72.png" alt="" style="display:block;margin:0 auto" />

<p>这是一个从圆里面推广而来的结论：如果 \( a = b \) ，椭圆退化为圆， \( k_{OM}k_l = -1 \) ，即 \( OM, l \) 两条直线垂直。</p>
<h3>2.2. 最速下降法</h3>
<p>首先，你应该知道梯度下降法：</p>
<p>$$x_{i+1} = x_i - \alpha\nabla f(x_i)$$</p>
<p>最速下降法就是在梯度下降法的基础上，选择 \( \alpha \) 使得 \( x_{i+1} \) 达到最小（在搜索方向上的最小值）：</p>
<p>$$\alpha^* = \text{argmin}_\alpha f(x_i - \alpha\nabla f(x_i))$$</p>
<h2>3. 共轭梯度法</h2>
<h3>3.1. 记号</h3>
<ul>
<li><p>\( x_i \) ：第 \( i \) 次循环之后的 \( x \) 向量</p>
</li>
<li><p>\( r_i \) ： \( b - Ax_i \) ，目标函数在 \( x_i \) 点的负梯度，或者线性方程组在 \( x_i \) 点的残差。* 请记住：负梯度和残差是一个东西！</p>
</li>
<li><p>\( d_i \) ：在 \( x_i \) 点的搜索方向。最速下降算法里 \( d_i = r_i \) ，共轭梯度里面需要一点修正。</p>
</li>
</ul>
<h3>3.2. 最速下降</h3>
<ol>
<li><p>最速下降的新方向： \( r_{i+1} \)</p>
<ul>
<li><p>新方向与前一步下降方向 \( r_i \) 垂直（画个等高线图直观理解，或者回想一下“等势面和电场线垂直”）</p>
<img src="https://cdn.hashnode.com/uploads/covers/69fff364e3eebc2e2021e3fe/9966a0bd-6e5f-474c-85dd-30dada11d805.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
</li>
<li><p>最速下降的 \( \alpha \)</p>
</li>
</ol>
<p>$$\alpha_i = \frac{r_i^T r_i}{d_i^T A d_i}$$</p>
<h3>3.3. 共轭梯度</h3>
<p>我们直接逐项类比最速下降。</p>
<ul>
<li><p>新方向与前一步下降方向 \( r_i \) 垂直 → 斜率之积为 \( -a^{-2}b^2 \) (Section 2.1)</p>
<ul>
<li><p>这个方向由最速下降的方向进行一些小改动得到，我们可以在后面的算法部分看到。把这个方向从和前一个搜索方向垂直改动到斜率之积为 \( -a^{-2}b^2 \) 就是 CG 和最速下降唯一不同的地方。</p>
<img src="https://cdn.hashnode.com/uploads/covers/69fff364e3eebc2e2021e3fe/017c0f24-544d-492b-beb1-c7fb74936585.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
</li>
<li><p>步长 \( \alpha \) ：由于是在一条直线上做优化，因此和最速下降的 \( \alpha \) 相同。</p>
</li>
</ul>
<p>由于一次迭代只涉及到两个点、两个向量，只能构成一个平面，我们甚至不需要将二维向多维推广。</p>
<ul>
<li>若需推导，我们需要做的只是把点的 \( n \) 维坐标映射到二维，然后对截面椭圆对应的二阶二次型进行 SVD 获得其长轴 \( a \) 和短轴 \( b \) ，进而根据其离及上述斜率积的二级结论计算两个方向的关系。这里不展开。</li>
</ul>
<h3>3.4. 算法</h3>
<h4>3.4.1. 初始化</h4>
<p>算法输入： \( A, b, x_0 \)</p>
<p>$$\vec{d}{(0)} = \vec{r}{(0)} = \vec{b} - \mathbf{A}\vec{x}_{(0)}$$</p>
<h4>3.4.2. 算法过程</h4>
<p>$$\begin{align*} \alpha_{(i)} &amp;= \frac{\vec{r}{(i)}^T \vec{r}{(i)}}{\vec{d}{(i)}^T \mathbf{A}\vec{d}{(i)}} \ \vec{x}{(i+1)} &amp;= \vec{x}{(i)} + \alpha_{(i)}\vec{d}{(i)} \ \vec{r}{(i+1)} &amp;= \vec{r}{(i)} - \alpha{(i)}\mathbf{A}\vec{d}{(i)} \ \beta{(i+1)} &amp;= \frac{\vec{r}{(i+1)}^T \vec{r}{(i+1)}}{\vec{r}{(i)}^T \vec{r}{(i)}} \ \vec{d}{(i+1)} &amp;= \vec{r}{(i+1)} + \beta_{(i+1)}\vec{d}_{(i)} \end{align*}$$</p>
<p>其中的最后一步就是通过 \( \beta \) 将 \( r_{i+1} \) 修正成 \( d_{i+1} \) 的。</p>
<h4>3.4.3. 起讫</h4>
<ol>
<li><p><strong>起</strong>：如果你对解 \( x \) 有粗略的估计，就使用那个值作为起始点 \( x_0 \) ；否则，直接使用 \( x_0 = 0 \) 。</p>
</li>
<li><p><strong>讫</strong>：通常的做法是在残差向量的 2-norm 小于某个给定阈值的时候就停下来。通常这个阈值为初始残差的一小部分</p>
</li>
</ol>
<p>$$|r_i| &lt; \varepsilon |r_0|$$</p>
<p>其中 \( \varepsilon \) 是一个输入的参数。</p>
<h3>3.5. 杂项</h3>
<ol>
<li>由于 \( Ad_i \) 在每个循环中都要被计算，且</li>
</ol>
<p>$$r_{i+1} = r_i - \alpha_i A d_i$$</p>
<p>故可以用上式计算 \( r_{i+1} \) ，而不必用 \( b - Ax_{i+1} \) 。</p>
<ol>
<li>上述方法有浮点误差累计的危险，因此我们应该每过几个循环就重新用 \( r_i = b - Ax_i \) 重新计算残差。</li>
</ol>
]]></content:encoded></item></channel></rss>