<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://www.raylene.online</id>
    <title>Raylene's Blog</title>
    <updated>2026-06-05T13:29:24.976Z</updated>
    <generator>Feed for Node.js</generator>
    <author>
        <name>Raylene</name>
        <email>raylene_y@163.com</email>
        <uri>https://www.raylene.online</uri>
    </author>
    <link rel="alternate" href="https://www.raylene.online"/>
    <link rel="self" href="https://www.raylene.online/atom.xml"/>
    <subtitle>从未停止对未知的探索，尝试分享一些有用的东西</subtitle>
    <logo>https://www.raylene.online/favicon.png</logo>
    <icon>https://www.raylene.online/favicon.ico</icon>
    <rights>All rights reserved 2026, Raylene</rights>
    <entry>
        <title type="html"><![CDATA[从零到完美：Mermaid 时序图绘制工作流]]></title>
        <id>https://www.raylene.online/blog/mermaid-workflow</id>
        <link href="https://www.raylene.online/blog/mermaid-workflow"/>
        <updated>2026-06-05T02:00:00.000Z</updated>
        <summary type="html"><![CDATA[给技术文档画几十张时序图，发现 AI 画的图插进 Word 就崩。花了一天把 beautiful-mermaid 改成了能直接输出 Word 兼容 SVG 的工具包。]]></summary>
        <content type="html"><![CDATA[<h2>写在前面</h2>
<p>最近在写一份技术文档，需要画架构图、时序图、流程图，加起来十几张。我比较抗拒用鼠标拖框——改个文字要重新对齐，换个节点要重画连线。</p>
<p>Mermaid 用代码生成图就好多了，改文字就改图。但问题来了：AI 生成的 Mermaid 代码渲染出来的 SVG，浏览器看着挺好，一插进 Word 就炸了。</p>
<p>矩形变黑块。线条消失。箭头方向乱跑。</p>
<p>花了一整天踩坑，最后把 beautiful-mermaid 这个开源库从里到外改了一遍，打包成了一个换台设备也能一键跑的工具包。这篇文章就是踩坑记录。</p>
<blockquote>
<p><strong>TIP</strong>: 如果你只是想在 Word 里插一张 Mermaid 图，直接跳到最后一节看工具包用法。</p>
</blockquote>
<h2>先看效果</h2>
<p>这是同样的 Mermaid 源码，经过工具包渲染后的输出，直接拖进 Word 完美显示：</p>
<p><img src="/media/seq-compare-toolkit.svg" alt="工具包渲染"></p>
<blockquote>
<p><strong>IMPORTANT</strong>: 问题不在 Mermaid，也不在 beautiful-mermaid。问题在 Word 的 SVG 渲染能力——它不支持 CSS 变量 <code>var(--bg)</code>，不支持 <code>color-mix()</code>，也不认 <code>orient=&quot;auto-start-reverse&quot;</code>。</p>
</blockquote>
<h2>第一关：文字全溢出了</h2>
<p>刚开始渲染的第一批图，所有中文标签都溢出边框。</p>
<p>追了一下源码，beautiful-mermaid 估算文字宽度用的公式是 <code>text.length × fontSize × 0.52</code>。这个 0.52 是拉丁字符的平均宽高比。中文字符的宽高比接近 0.92——差了一倍。一个 5 字中文标签，估算宽度 34px，实际需要 60px。</p>
<p>修起来简单：数一下中文字符数，分别乘不同的系数。</p>
<pre><code class="language-js">// 原来：所有字符按拉丁算
return text.length * fontSize * widthRatio;

// 改后：中文单独算
const cjk = (text.match(/[一-鿿]/g) || []).length;
const latin = text.length - cjk;
return latin * fontSize * widthRatio + cjk * fontSize * 0.92;
</code></pre>
<p>修完这个，文字不溢出了。但图还是不对。</p>
<h2>第二关：菱形又大又丑</h2>
<p>流程图里的判断节点（菱形）用的是 <code>side = max(width, height) + diamondExtra</code>。原库的 <code>diamondExtra: 24</code>——额外加 24px。一个&quot;资源负载评估&quot;标签，文字宽 60px，加上 32px 内边距，再加上 24px 额外空间，菱形撑到 116×116。</p>
<p>旁边的矩形节点&quot;接收任务&quot;才 80×38。菱形比矩形大三倍，视觉上很突兀。</p>
<p>两刀修：<code>diamondExtra</code> 砍到 8，长标签加 <code>&lt;br/&gt;</code> 换行。&quot;任务复杂度<br/>评估&quot;拆成两行后，菱形从 118px 缩到 100px。</p>
<p>但 <code>&lt;br/&gt;</code> 在 beautiful-mermaid 里默认不生效——<code>escapeXml</code> 会把 <code>&lt;</code> 转成 <code>&amp;lt;</code>。得让 <code>escapeXml</code> 保留 <code>&lt;br/&gt;</code>，然后把单行 <code>&lt;text&gt;</code> 改成多行 <code>&lt;tspan&gt;</code>。</p>
<h2>第三关：时序图缺胳膊少腿</h2>
<p>Mermaid 的标准时序图有几个要素：参与者矩形、虚线生命线、激活框（覆盖在生命线上的细条）、箭头、文字。</p>
<p>beautiful-mermaid 只渲染了前两个+后两个。激活框没了。</p>
<p>原因是激活框只在 Mermaid 源码里显式标了 <code>+</code>/<code>-</code> 时才画。标准 Mermaid 不需要——自动从第一条消息到最后一条画激活框。</p>
<p>补了一段自动计算逻辑：每个参与者扫描自己的第一条和最后一条消息，中间全画激活框。白底、黑边框、居中在虚线上。</p>
<p>然后是箭头起止点。原版箭头从参与者中心出发，直接越过激活框到目标中心——箭头扎进框里了。改成从激活框右边缘出发，到目标激活框左边缘止。</p>
<p>自调用消息（自己发给自己的箭头）的箭头是折线，向右绕一圈回来。这个折线把激活框也带歪了——alt 框的宽度只算了参与者的宽度，没算自调用消息向右延伸的部分。修复方式是在框宽度计算里扫描框内每一条消息的标签位置。</p>
<h2>第四关：Word 不认你的 CSS</h2>
<p>前三关调完之后，浏览器里看着已经很好了。插进 Word——全崩。</p>
<p>F12 看了一下 SVG 源码，beautiful-mermaid 用 CSS 变量实现主题：</p>
<pre><code class="language-html">&lt;rect fill=&quot;var(--_node-fill)&quot; stroke=&quot;var(--_node-stroke)&quot; ... /&gt;
</code></pre>
<p><code>--_node-fill</code> 的定义在 <code>&lt;style&gt;</code> 里：<code>var(--surface, color-mix(in srgb, var(--fg) 3%, var(--bg)))</code>。</p>
<p>浏览器能解这个链条，Word 不能。Word 看到 <code>var(--_node-fill)</code> 不认识，默认给黑色——所以矩形全黑了。<code>color-mix()</code> 不认识，直接跳过——所以线条消失了。</p>
<p>解决方案：写了一个 <code>flatten-svg.js</code>，把 SVG 里所有 CSS 变量替换为具体色值。github-white 主题的配色很简单：</p>
<table>
<thead>
<tr>
<th>变量</th>
<th>值</th>
</tr>
</thead>
<tbody><tr>
<td><code>--bg</code> / <code>--surface</code></td>
<td><code>#FFFFFF</code></td>
</tr>
<tr>
<td><code>--line</code> / <code>--border</code> / <code>--accent</code></td>
<td><code>#000000</code></td>
</tr>
<tr>
<td><code>--fg</code></td>
<td><code>#1f2328</code></td>
</tr>
<tr>
<td><code>--muted</code></td>
<td><code>#555555</code></td>
</tr>
</tbody></table>
<p><code>color-mix(in srgb, var(--fg) 20%, var(--bg))</code> 这种相对值也直接算成 <code>#d2d3d4</code>。</p>
<p>还把 <code>&lt;style&gt;</code> 块整个删了——Word 不需要那些 CSS 定义，只要元素上的颜色属性是具体的。</p>
<p>另外发现 Word 不支持 SVG 的 <code>dy</code> 属性（相对于基线的偏移量）。文本位置原本是 <code>&lt;text y=&quot;100&quot; dy=&quot;0.35em&quot;&gt;</code>，Word 忽略 <code>dy</code>，文字就偏上了。改成 <code>&lt;text y=&quot;105&quot;&gt;</code>——把偏移直接算进 y 坐标，问题解决。</p>
<h2>第五关：箭头的方向——坑最深的</h2>
<p>颜色问题修完之后，插进 Word 一看——返回箭头全朝右了。</p>
<p>时序图里，实线箭头（请求）朝右，虚线箭头（返回）朝左。但 Word 里所有箭头都朝右。</p>
<p>问题出在 SVG 的 <code>&lt;marker&gt;</code> 标签。beautiful-mermaid 给 marker 设了 <code>orient=&quot;auto-start-reverse&quot;</code>——浏览器会根据线条方向自动把 marker 翻转 180 度。Word 不认这个属性，所有箭头按原始多边形方向渲染，全朝右。</p>
<p>试了三版。</p>
<p><strong>第一版</strong>：把 <code>auto-start-reverse</code> 换成 <code>auto</code>。Word 还是不认。</p>
<p><strong>第二版</strong>：创建两个 marker——<code>-l</code>（左指）和 <code>-r</code>（右指），根据线条 <code>x1 &gt; x2</code> 判断往哪走。方向对了，但位置漂了——箭头尖没对齐线端点。排查发现我只翻转了多边形的顶点坐标，没改 <code>refX</code>（连接点）。左指箭头的尖在 x=0 但 refX 还指着 x=10。</p>
<p><strong>第三版</strong>：翻转多边形的时候同步翻转 refX。左指箭头：多边形镜像 + refX 归零。右指箭头：原样保留。</p>
<pre><code class="language-js">// 左指 marker: 多边形水平翻转 + refX 归零
const flipped = polygon.replace(...); // x -&gt; w-x
const lMarker = marker.replace(&#39;refX=&quot;10&quot;&#39;, &#39;refX=&quot;0&quot;&#39;).replace(polygon, flipped);
// 右指 marker: 原样
const rMarker = marker;
</code></pre>
<blockquote>
<p><strong>WARNING</strong>: <code>auto-start-reverse</code> 只影响 sequence 图的 <code>seq-arrow</code> 和 <code>seq-arrow-open</code> marker。流程图的 <code>arrowhead</code> 用的是 <code>orient=&quot;auto&quot;</code> 不需要处理。还有个大坑：正则匹配 marker 时如果用 <code>[\s\S]*?</code> 会跨过前面的 <code>&lt;marker&gt;</code> 标签，把相邻的 <code>arrowhead</code> 也吞进去复制一份——结果变成两个 <code>id=&quot;arrowhead&quot;</code>，SVG 非法，Word 直接不渲染箭头。改成 <code>&lt;marker\b[^&gt;]*\bid=&quot;...&quot;</code> 匹配单个标签才修好。</p>
</blockquote>
<h2>工具包</h2>
<p>所有修改已经打包。换台设备：</p>
<pre><code class="language-bash">git clone https://github.com/Raylene-Y/mermaid-toolkit.git &amp;&amp; cd mermaid-toolkit
bash install.sh
</code></pre>
<p>然后一行命令：</p>
<pre><code class="language-bash">node render-custom.mjs -i diagram.mmd -o diagram.svg -t github-white
node flatten-svg.js diagram.svg
</code></pre>
<p><code>diagram-flat.svg</code> 直接拖进 Word——白底黑线，箭头方向正确，菱形大小合理，激活框正常。</p>
<p>项目地址：<a href="https://github.com/Raylene-Y/mermaid-toolkit">github.com/Raylene-Y/mermaid-toolkit</a></p>
<h2>总结</h2>
<p>一天时间改了 18 处。核心教训就三条：</p>
<ol>
<li><strong>英文开源库对中文的支持几乎为零</strong>。文字宽度、换行、标记方向，每个环节都要手动适配。</li>
<li><strong>Word 的 SVG 支持远比你想象的弱</strong>。CSS 变量、<code>color-mix()</code>、<code>auto-start-reverse</code> 全不支持。但它的 SVG 规范支持其实还行——只要把颜色写死、marker 拆好，就能完美渲染。</li>
<li><strong><code>flatten-svg.js</code> 打通了最后一公里</strong>。原来是 beautiful-mermaid → 浏览器能看但 Word 不能看，现在加一层压平，输出直接进 Word。</li>
</ol>
<p>如果有和我一样需要在 Word 文档里大量插 Mermaid 图的，这个工具包应该能省你一天时间。</p>
]]></content>
        <author>
            <name>Raylene</name>
            <email>raylene_y@163.com</email>
            <uri>https://www.raylene.online</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[深度学习理论]]></title>
        <id>https://www.raylene.online/blog/DeepLearning-Theory</id>
        <link href="https://www.raylene.online/blog/DeepLearning-Theory"/>
        <updated>2024-06-05T04:10:00.000Z</updated>
        <summary type="html"><![CDATA[这篇文章讲述深度学习理论知识图谱，包括分类、聚类、回归和降维]]></summary>
        <content type="html"><![CDATA[<p>这篇文章讲述深度学习理论知识图谱，包括分类、聚类、回归和降维</p>
<h2>深度学习方法概述：分类、聚类、回归和降维</h2>
<p><img src="/media/bf8e8e080a4ba51d6ec9f4aa7dc37eb0.png" alt="descript"></p>
<h2>使用Pytorch构建DeepLearning算法的基本流程：</h2>
<p>以线性模型为例：</p>
<h3>1. DataSet - 数据集准备</h3>
<h3>2. Model - 模型选择</h3>
<p>$$
y = w \times x + b
$$</p>
<h3>3. Training - 训练模型</h3>
<ul>
<li><strong>随机初始化</strong> $w$（通常也包含 $b$）</li>
<li><strong>定义优化器</strong>（如梯度下降）</li>
<li><strong>定义损失函数</strong>（Loss Function）：<br>$$
\text{Loss}^{(i)} = (y_{\text{hat}}^{(i)} - y^{(i)})^2
$$</li>
<li><strong>优化权重</strong>：<br>通过改变 $w$ 最小化<strong>代价函数</strong>（Cost Function）：
$$
\text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_{\text{hat}}^{(i)} - y^{(i)})^2
$$
（示例方法：穷举所有权重值对应的 MSE）</li>
</ul>
<h3>4. Inferring - 预测应用</h3>
<p>确定最优权重 $w$ 后，将模型用于推理/预测：
$$
y_{\text{pred}} = w_{\text{final}} \times x_{\text{new}} + b
$$</p>
<h2>损失函数、目标函数、价值函数概念</h2>
<ul>
<li><p><strong>损失函数 (Loss Function)</strong>：单个样本的损失<br>$$\text{Loss}^{(i)} = f(y_{\text{pred}}^{(i)}, y_{\text{true}}^{(i)})$$</p>
</li>
<li><p><strong>价值函数 (Value Function)</strong>：所有样本损失和的平均值<br>$$J(\theta) = \frac{1}{m} \sum_{i=1}^{m} \text{Loss}^{(i)}$$</p>
</li>
<li><p><strong>目标函数 (Objective Function)</strong>：需要最小化或最大化的整体函数<br>$$\min_{\theta} J(\theta) \quad \text{或} \quad \max_{\theta} J(\theta)$$</p>
</li>
</ul>
<h2>权重W初始化策略</h2>
<h3>Q：初始化权重值过小会怎样？</h3>
<p><strong>答</strong>：梯度值下降会非常缓慢</p>
<h3>Q：初始化权重值过大会怎样？</h3>
<p><strong>答</strong>：会导致梯度下降过快，错过最优解</p>
<h3>Q：初始化所有权重值W=0会怎样？</h3>
<p><strong>答</strong>：会导致所有神经元都相同</p>
<h3>Q：正确的权重初始化策略有哪些？</h3>
<ol>
<li><p><strong>初始化w=小的随机数，适用于小型网络</strong>  </p>
<ul>
<li>假设：使用 $W = 1 \times \text{np.random.randn}(D,H)$，tanh激活函数会出现什么情况？<br><strong>答</strong>：网络饱和。权重 $W$ 较大 → 输出较大 → tanh 输出接近 $\pm 1$</li>
</ul>
</li>
<li><p><strong>w从标准高斯分布中取样，依据输入数据数量进行缩放</strong><br>$$W \sim \mathcal{N}(0, \sigma^2), \quad \sigma = \frac{1}{\sqrt{n_{\text{input}}}}$$</p>
</li>
</ol>
<h2>优化算法</h2>
<h3>梯度下降 (GD)</h3>
<ul>
<li><strong>特点</strong>：性能低，时间复杂度低</li>
<li><strong>计算</strong>：价值函数的梯度</li>
<li><strong>下降方向</strong>：负梯度方向</li>
<li><strong>步长大小</strong>：学习率</li>
<li><strong>更新规则</strong>：<br>$$\theta_{t+1} = \theta_t - \eta \nabla J(\theta_t)$$</li>
<li><strong>优点</strong>：可并行计算，凸函数全局最优</li>
<li><strong>缺点</strong>：无法解决鞍点问题</li>
</ul>
<h3>随机梯度下降 (SGD)</h3>
<ul>
<li><strong>特点</strong>：性能高，时间复杂度高</li>
<li><strong>计算</strong>：随机样本的损失函数梯度</li>
<li><strong>下降方向</strong>：随机选某个样本的损失函数**的负梯度为下降方向更新权重</li>
<li><strong>更新规则</strong>：<br>$$\theta_{t+1} = \theta_t - \eta \nabla \text{Loss}^{(i)}(\theta_t)$$</li>
<li><strong>问题</strong>：山谷震荡、鞍点问题，无法并行</li>
</ul>
<h3>Mini-batch 梯度下降</h3>
<ul>
<li><strong>方法</strong>：将样本分组，计算组内样本损失和的梯度<br>$$\theta_{t+1} = \theta_t - \eta \nabla \left( \frac{1}{b} \sum_{i=1}^{b} \text{Loss}^{(i)}(\theta_t) \right)$$</li>
</ul>
<h3>动量方法 (Momentum)</h3>
<ul>
<li><strong>原理</strong>：随机梯度下降 + 惯性</li>
<li><strong>下降方向</strong>：带衰减的前一次的下降方向 + 学习率 * 当前算出的梯度</li>
<li><strong>更新规则</strong>：($\gamma$: 动量衰减系数)
$$
\begin{aligned}
v_t &amp;= \gamma v_{t-1} + \eta \nabla \theta_t \
\theta_{t+1} &amp;= \theta_t - v_t
\end{aligned}
$$</li>
</ul>
<h3>Adagrad</h3>
<ul>
<li><strong>原理</strong>：随机梯度下降 + 自适应学习率</li>
<li><strong>下降方向</strong>：（学习率/sqrt(历史梯度的平方和)）* 当前计算出的梯度</li>
<li><strong>更新规则</strong>：<br>$$
\begin{aligned}
g_t &amp;= \nabla \theta_t \
G_t &amp;= G_{t-1} + g_t^2 \
\theta_{t+1} &amp;= \theta_t - \frac{\eta}{\sqrt{G_t + \epsilon}} \odot g_t
\end{aligned}
$$</li>
<li><strong>缺陷</strong>：梯度平方项$G_t$ 单调增 → 学习率 $\downarrow$</li>
</ul>
<h3>Adam</h3>
<ul>
<li><strong>原理</strong>：随机梯度 + 惯性 + 自适应学习率</li>
<li><strong>下降方向</strong>：学习率/sqrt(过往梯度平方和当前梯度平方的平均值) * 过往梯度与当前梯度的平均值</li>
<li><strong>更新规则</strong>：<br>$$
\begin{aligned}
m_t &amp;= \beta_1 m_{t-1} + (1-\beta_1)g_t \quad &amp;\text{(一阶矩估计)} \
v_t &amp;= \beta_2 v_{t-1} + (1-\beta_2)g_t^2 \quad &amp;\text{(二阶矩估计)} \
\hat{m}_t &amp;= \frac{m_t}{1-\beta_1^t}, \quad \hat{v}<em>t = \frac{v_t}{1-\beta_2^t} \
\theta</em>{t+1} &amp;= \theta_t - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_t
\end{aligned}
$$</li>
</ul>
<h2>手推前馈运算和反向传播</h2>
<h3>基本步骤</h3>
<ol>
<li><strong>绘制计算图</strong>：构建网络计算流程图</li>
<li><strong>前馈计算</strong>：计算得到损失函数值<br>$$
\text{Loss} = f(\text{forward}(x, W))
$$</li>
<li><strong>计算局部偏导数</strong>：基于计算图计算各节点偏导</li>
<li><strong>链式法则</strong>：组合局部偏导得到最终梯度<br>$$
\frac{\partial \text{Loss}}{\partial W} = \prod \frac{\partial \text{node}<em>i}{\partial \text{node}</em>{i-1}}
$$</li>
</ol>
<h3>节点梯度传播规则</h3>
<h4>加法节点</h4>
<ul>
<li><strong>前向传播</strong>：$z = x + y$</li>
<li><strong>反向传播</strong>：梯度直接赋值给所有输入分支<br>$$
\frac{\partial L}{\partial x} = \frac{\partial L}{\partial z}, \quad
\frac{\partial L}{\partial y} = \frac{\partial L}{\partial z}
$$</li>
</ul>
<h4>Max节点</h4>
<ul>
<li><strong>前向传播</strong>：$z = \max(x, y)$</li>
<li><strong>反向传播</strong>：梯度仅回传给最大值分支<br>$$
\frac{\partial L}{\partial x} = 
\begin{cases} 
\frac{\partial L}{\partial z} &amp; \text{if } x &gt; y \
0 &amp; \text{otherwise}
\end{cases}, \quad
\frac{\partial L}{\partial y} = 
\begin{cases} 
\frac{\partial L}{\partial z} &amp; \text{if } y &gt; x \
0 &amp; \text{otherwise}
\end{cases}
$$</li>
<li><strong>解释</strong>：前向传播中只有最大值向后传递</li>
</ul>
<h4>倍乘节点</h4>
<ul>
<li><strong>前向传播</strong>：$z = k \times x$（$k$为常数）</li>
<li><strong>反向传播</strong>：梯度值按比例缩放<br>$$
\frac{\partial L}{\partial x} = k \times \frac{\partial L}{\partial z}
$$</li>
</ul>
<h4>分支节点（一个节点连接多个下游）</h4>
<ul>
<li><strong>前向传播</strong>：$y_1 = f(x), y_2 = g(x)$</li>
<li><strong>反向传播</strong>：下游梯度相加回传<br>$$
\frac{\partial L}{\partial x} = \frac{\partial L}{\partial y_1} \frac{\partial y_1}{\partial x} + \frac{\partial L}{\partial y_2} \frac{\partial y_2}{\partial x}
$$</li>
</ul>
<h2>回归问题与分类问题的联系（以逻辑回归到二分类为例）</h2>
<p>在模型外<strong>套用激活函数将回归的预测值映射为 (0,1) 之间的概率值</strong>，设置分类阈值（通常为 0.5）：</p>
<ul>
<li>预测概率 &gt; 阈值 → 判定为类别 1</li>
<li>预测概率 &lt; 阈值 → 判定为类别 0</li>
</ul>
<p>$$
p(y=1|x) = \sigma(w^Tx + b) = \frac{1}{1 + e^{-(w^Tx + b)}}
$$</p>
<h2>机器学习的本质</h2>
<p><strong>学习数据分布</strong>：</p>
<ul>
<li>预测值服从一个概率分布 $P_{\text{pred}}(y|x)$</li>
<li>真实标签服从一个概率分布 $P_{\text{true}}(y|x)$</li>
<li>利用分布之间的差异（如 KL 散度）作为损失函数：
$$
\mathcal{L} = D_{\text{KL}}(P_{\text{true}} | P_{\text{pred}})
$$</li>
<li>计算梯度并更新权重以最小化分布差异</li>
</ul>
<h2>常见激活函数</h2>
<h3>Sigmoid</h3>
<p><strong>公式</strong>：
$$
\sigma(z) = \frac{1}{1 + e^{-z}}
$$</p>
<p><strong>优缺点</strong>：</p>
<ul>
<li>✅ 输出范围 (0,1)，适合概率输出</li>
<li>❌ 当 $|z|$ 很大时梯度趋于 0（<strong>梯度消失</strong>）</li>
<li>❌ 输出不以 0 为中心（导致梯度恒正/恒负）</li>
<li>❌ 指数计算代价高</li>
</ul>
<h3>Tanh</h3>
<p><strong>公式</strong>：
$$
\tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}}
$$</p>
<p><strong>优缺点</strong>：</p>
<ul>
<li>✅ 输出范围 (-1,1)，以 0 为中心</li>
<li>❌ 当 $|z|$ 很大时梯度趋于 0（梯度消失）</li>
<li>❌ 指数计算代价高</li>
</ul>
<h3>ReLU (Rectified Linear Unit)</h3>
<p><strong>公式</strong>：
$$
\text{ReLU}(z) = \max(0, z)
$$</p>
<p><strong>优缺点</strong>：</p>
<ul>
<li>✅ 计算复杂度低（无指数运算）</li>
<li>✅ 解决正区间的梯度消失问题</li>
<li>✅ 提供稀疏表达能力（单侧抑制）</li>
<li>❌ $z &lt; 0$ 时梯度为 0（<strong>神经元死亡</strong>问题）</li>
</ul>
<h3>ReLU 改进方案</h3>
<h4>Leaky ReLU (LReLU)</h4>
<p><strong>公式</strong>：
$$
\text{LReLU}(z) = 
\begin{cases} 
z &amp; \text{if } z &gt; 0 \
\alpha z &amp; \text{if } z \leq 0 
\end{cases}
\quad (\alpha \approx 0.01)
$$</p>
<ul>
<li>使用斜率为 $\alpha$ 的线性函数替代 0</li>
<li>缓解神经元死亡问题</li>
</ul>
<h4>ELU (Exponential Linear Unit)</h4>
<p><strong>公式</strong>：
$$
\text{ELU}(z) = 
\begin{cases} 
z &amp; \text{if } z &gt; 0 \
\alpha(e^z - 1) &amp; \text{if } z \leq 0 
\end{cases}
$$</p>
<ul>
<li>建立负饱和机制</li>
<li>对噪声有更好的鲁棒性</li>
</ul>
<h4>Maxout</h4>
<p><strong>公式</strong>：
$$
\text{Maxout}(z) = \max(w_1^Tx + b_1, w_2^Tx + b_2)
$$</p>
<ul>
<li>将参数数量翻倍</li>
<li>训练两个权重组合，取最大值作为输出</li>
<li>能拟合任意凸函数</li>
</ul>
<center><img src="/media/43215cc067a8421268de4887a5c3c2b6.png" alt="常用git命令" /></center>
]]></content>
        <author>
            <name>Raylene</name>
            <email>raylene_y@163.com</email>
            <uri>https://www.raylene.online</uri>
        </author>
    </entry>
    <entry>
        <title type="html"><![CDATA[git常用命令与常见面试题汇总]]></title>
        <id>https://www.raylene.online/blog/interview-git-cmd</id>
        <link href="https://www.raylene.online/blog/interview-git-cmd"/>
        <updated>2024-04-05T12:10:00.000Z</updated>
        <summary type="html"><![CDATA[这篇文章讲述git框架，总结常用git命令及开发中的常见问题]]></summary>
        <content type="html"><![CDATA[<p>这篇文章讲述git框架，总结常用git命令及开发中的常见问题</p>
<h2>git框架介绍</h2>
<p>Git 框架结构及各区域关系：Git 的核心结构分为四个关键区域，它们协同工作实现版本控制：</p>
<p><img src="/media/git.png#pic_center" alt="git框架结构及各区域关系图"></p>
<h3>1. Workspace（工作区）</h3>
<ul>
<li><strong>定义</strong>：开发者直接操作的本地目录（可见文件系统）  </li>
<li><strong>内容</strong>：当前可见的文件/目录（包含已跟踪和未跟踪文件）  </li>
<li><strong>特点</strong>：所有修改首先发生在这里</li>
</ul>
<h3>2. Index / Stage（暂存区/缓存区）</h3>
<ul>
<li><strong>定义</strong>：临时存储待提交修改的缓冲区  </li>
<li><strong>内容</strong>：通过 <code>git add</code> 添加的文件快照  </li>
<li><strong>特点</strong>：充当工作区和仓库区的过渡层</li>
</ul>
<h3>3. Repository（仓库区/本地仓库）</h3>
<ul>
<li><strong>定义</strong>：存储项目完整历史的数据库  </li>
<li><strong>内容</strong>：  <ul>
<li>提交历史（commit objects）  </li>
<li>分支/标签指针（.git/refs）  </li>
<li>元数据（.git 目录）</li>
</ul>
</li>
<li><strong>核心文件</strong>：  <ul>
<li><code>HEAD</code>：指向当前分支  </li>
<li><code>objects</code>：存储所有 Git 对象（blob/tree/commit）</li>
</ul>
</li>
</ul>
<h3>4. Remote（远程仓库）</h3>
<ul>
<li><strong>定义</strong>：云端共享仓库（如 GitHub/GitLab）  </li>
<li><strong>内容</strong>：其他成员可访问的中央代码库  </li>
<li><strong>特点</strong>：通过 URL 标识（<code>origin</code> 为默认别名）</li>
</ul>
<h2>常用git命令</h2>
<center><img src="/media/git-cmd.png" alt="常用git命令" width="500" /></center>


<h2>常见问题</h2>
<h3>1. 隔离设计价值：</h3>
<ul>
<li>暂存区允许选择性提交</li>
<li>本地仓库保证离线工作能力</li>
<li>远程仓库实现团队协作</li>
</ul>
<h3>2. 提交时发生冲突，如何解决？</h3>
<p><strong>为什么会产生冲突?</strong> </p>
<p>在合并分支的时候，master分支和dev分支恰好有人都修改了同一个文件，GIT不知道应该以哪一个人的文件为准，所以就产生了冲突了。 <strong>两个分支相同文件相同位置的的不同操作！</strong></p>
<p><strong>如何解决?</strong> </p>
<p>发生冲突，在IDE里面对比本地文件和远程分支的文件，然后把远程分支上文件的内容手工修改到本地文件，然后再提交冲突的文件使其保证与远程分支的文件一致，消除冲突，然后再提交自己修改的部分。</p>
<ul>
<li>通过git stash命令，把工作区的修改提交到栈区，目的是保存工作区的修改；</li>
<li>通过git pull命令，拉取远程分支上的代码并合并到本地分支，目的是消除冲突；</li>
<li>通过git stash pop命令，把保存在栈区的修改部分合并到最新的工作空间中；</li>
</ul>
<h3>3. 新建git功能分支的步骤？</h3>
<ul>
<li>Git branch name     创建名字为name的branch</li>
<li>Git checkout xxx_dev    切换到名字为xxx_dev的分支</li>
<li>Git pull    从远程分支拉取代码到本地分支</li>
<li>Git checkout -b main_furture_xxx    创建并切换到 main_furture_xxx 分支</li>
<li>Git push origin main_furture_xxx    执行推送的操作，完成本地分支向远程分支的同步</li>
</ul>
<p>在执行git pull的时候，提示当前branch没有跟踪信息：</p>
<ul>
<li>git pull origin  远程分支名称</li>
<li>git branch --set-upstream-to=origin/远程分支名称 本地分支名       （先建立远程分支与本地分支的连接，再pull）</li>
<li>git pull    再次pull</li>
</ul>
<h3>4. fork、 branch、clone 之间的区别？</h3>
<ul>
<li><strong>fork</strong>：是对存储仓库（repository）进行的远程的，服务器端的拷贝。复刻不是git范畴。</li>
<li><strong>clone</strong>：不是复刻，克隆是对某个远程仓库的本地拷贝。克隆时，实际上是拷贝整个存储仓库，包括所有的历史记录和分支。</li>
<li><strong>branch</strong>：是一种机制，用于处理单一存储仓库中的变更，并最终目的是用于与其他部分代码合并。</li>
</ul>
<h3>5. 说明GIT合并的两种方法以及区别</h3>
<p>Git代码合并有两种：Git Merge 和 Git ReBase</p>
<ul>
<li><p><strong>Git Merge</strong>：这种合并方式是将两个分支的历史合并到一起，现在的分支不会被更改，它会比对双方不同的文件缓存下来，生成一个commit，去push。</p>
</li>
<li><p><strong>Git ReBase</strong>：这种合并方法通常被称为“衍合”。他是提交修改历史，比对双方的commit，然后找出不同的去缓存，然后去push，修改commit历史。</p>
</li>
</ul>
]]></content>
        <author>
            <name>Raylene</name>
            <email>raylene_y@163.com</email>
            <uri>https://www.raylene.online</uri>
        </author>
    </entry>
</feed>