写机器学习笔记的时候总会遇到公式。静态博客里有两个主流选择:KaTeX 和 MathJax。我最后选了前者。

行内公式

用 $...$ 包起来就行。比如梯度下降的更新规则可以写成 $x_{t+1} = x_t - \eta \nabla f(x_t)$,其中 $\eta$ 是学习率。

注意一个问题:$ 出现在正文里(比如讲价格)时会被误判成公式开头。KaTeX 的 auto-render 对这种情况比较宽容,实在不行就用 \$ 转义。

独立公式

两个 $ 包住一整行:

$$ \mathcal{L}(\theta) = -\frac{1}{N}\sum_{i=1}^{N} \log p_\theta(y_i \mid x_i) $$

交叉熵损失,几乎每篇笔记都会出现。

再比如高斯分布的概率密度:

$$ p(x) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) $$

接入方式

KaTeX 可以直接从 npm 装进来,构建时打包进站点,不依赖任何 CDN:

npm install katex

然后在需要的页面里渲染:

import renderMathInElement from 'katex/contrib/auto-render';
import 'katex/dist/katex.min.css';

renderMathInElement(document.body, {
  delimiters: [
    { left: '$$', right: '$$', display: true },
    { left: '$', right: '$', display: false },
  ],
  ignoredTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
  throwOnError: false,
});

ignoredTags 一定要包含 pre 和 code,否则代码块里的 $ 也会被当成公式解析,排版直接爆炸。

为什么不用 MathJax

MathJax 语法支持更全,\begin{aligned}、\operatorname 这类写法几乎不会翻车。但它体积大得多,而且默认走 CDN,在国内访问经常转圈。

我的原则是:能自托管的东西就不要依赖 CDN。字体和公式库都是。

KaTeX 渲染速度也快,一次 renderMathInElement 下来几乎无感。对一个总共几十个公式的博客来说,完全够用。