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