线性代数基础(一):向量与空间

前言 这是"线性代数基础"专栏的第一篇。这个专栏的目的很明确:补齐看懂本站进阶数学文章所需的基础。读完本文(以及后续两篇),你应该能顺畅读懂《矩阵微积分如何服务反向传播》和《Softmax 与缩放点积的数学》。 我们从一个最朴素的问题开始:什么是向量? 它为什么值得花一整篇来讨论? 向量:从几何到坐标 向量有两种看待方式,二者等价,互为补充: 几何视角:向量是空间中带方向和长度的箭头。它表示"从一点移动到另一点"。 代数视角:向量是 $\mathbb{R}^n$ 中的一个有序数组,如 $v = (v_1, v_2, \dots, v_n)$。其中 $n$ 是维度。 在深度学习中,我们几乎总是用数组(张量)表示向量:一个词嵌入是几百维的向量,一张图片展开后是几万维的向量。几何直觉在低维(2D/3D)依然成立,只是"看不见",但公式可以推广到任意维度。 向量的基本运算 对向量 $u, v$ 和标量 $c$: 加法:$(u + v)_i = u_i + v_i$。几何上就是"首尾相接"(平行四边形法则)。 数乘:$(cv)_i = c v_i$。几何上是把箭头拉伸($|c| > 1$)或压缩($|c| < 1$),$c < 0$ 时反向。 这两个运算非常重要,因为"对加法和数乘封闭"正是下一篇文章里"向量空间"定义的核心。 点积与范数 点积(内积) 两个 $n$ 维向量 $a$、$b$ 的点积定义为对应分量乘积之和: $$ a \cdot b = \sum_{i=1}^{n} a_i b_i $$它的几何形式揭示了本质: $$ a \cdot b = \|a\| \|b\| \cos\theta $$其中 $\theta$ 是两个向量之间的夹角,$\|a\|$ 是 $a$ 的模长(范数)。也就是说,点积同时度量了两个向量的长度和方向一致性:夹角越小,点积越大。 ...

📅 August 4, 2026 · ⏱️ 11 min · 📝 约 1718 字 · 👁️ — 次阅读

深度学习从拆箱开始——序言

为什么要写这个专栏 笔者在上学期学习了 COMP3314,一门传统机器学习课程。然而,传统机器学习在特征提取和模型设计上都需要大量的人工干预,难以适应复杂的现实世界数据。相比之下,深度学习通过多层神经网络自动学习数据的特征表示,在图像识别、自然语言处理等领域取得了许多重要突破。这个专栏旨在记录笔者从零开始学习深度学习的过程,分享理论推导和实战经验,希望能帮助同样对深度学习感兴趣的读者快速入门并逐步深入理解这一领域。 写作说明 这个专栏不会被写成一份固定课程表。深度学习本身发展很快,我自己的学习兴趣也会随着论文、项目和课程不断变化;如果一开始就把文章顺序钉死,反而容易限制后面真正想写的问题。 因此,这里更像是一组持续更新的学习笔记:有些文章会解释基础概念,例如什么是机器学习和深度学习;有些文章会拆解训练机制,例如正向传播与反向传播;也会有一些文章直接进入具体模型,例如为什么 ResNet 能训练 152 层。 如果某篇文章里的数学推导开始依赖更复杂的矩阵知识,我会把这部分拆到独立的 Math 专栏(线性代数 与 AI Math)里。比如 ResNet 中关于 Jacobian、向量-Jacobian 乘积和恒等矩阵的部分,就可以配合矩阵微积分如何服务反向传播一起看。这样,Deep Learning 专栏可以保持主线清晰,而数学细节也有足够空间展开。

📅 June 15, 2026 · 🔄 更新于 2026-08-04 · ⏱️ 3 min · 📝 约 485 字 · 👁️ — 次阅读

为什么 ResNet 能训练 152 层——残差连接的直觉与数学

前言 直接从 Deep Learning 概览跳到 ResNet 会有一点跳跃,因为 ResNet 不只是一个 CNN 结构,它还依赖正向传播、反向传播和梯度流这些训练机制。如果你还不熟悉“网络是函数复合”“损失如何反传到参数”这些概念,可以先看正向传播与反向传播:神经网络到底如何学习。 ResNet(Residual Network,残差网络)是经典视觉网络中绕不开的模型,因为它解决的不是“怎么设计一个更复杂的卷积层”,而是一个更基础的问题:网络变深以后,为什么反而更难训练? 直觉上,深层网络至少不应该比浅层网络差。假设一个 20 层网络已经能学到不错的函数,那么 56 层网络完全可以让后面 36 层近似恒等映射,理论上应该复现 20 层网络的效果。但在 ResNet 论文之前,实验中经常观察到相反现象:网络加深后,训练误差也会上升。这不是单纯的过拟合,因为过拟合通常表现为训练误差低、测试误差高;这里的问题是训练集本身都拟合不好。 这个现象通常被称为退化问题(Degradation Problem)。ResNet 的核心贡献,就是用一种非常简单的结构改写了深层网络的优化目标。 先看普通网络在学什么 设某一组卷积层想学习的目标函数是: $$ H(x) $$这里的 $x$ 是输入特征图,$H(x)$ 是这几层网络最终应该输出的特征。普通卷积网络会直接让堆叠的层去拟合 $H(x)$。 ResNet 的想法是:不要直接学 $H(x)$,而是学习它和输入 $x$ 之间的差值: $$ F(x) = H(x) - x $$于是目标输出可以改写成: $$ H(x) = F(x) + x $$这个 $F(x)$ 就叫残差映射(Residual Mapping),而旁边那条把 $x$ 直接加回输出的路径,就是跳跃连接(Skip Connection) 或 Shortcut Connection。 flowchart LR x["输入 x"] --> block["普通卷积层堆叠"] block --> h["直接学习 H(x)"] 普通网络的压力在于:每一组层都必须直接学出目标映射 $H(x)$。而 ResNet 把这个任务拆成两部分:主分支只学习“相对输入还需要改什么”,shortcut 分支直接把输入送到输出端。 ...

📅 July 31, 2026 · 🔄 更新于 2026-08-04 · ⏱️ 16 min · 📝 约 2546 字 · 👁️ — 次阅读

线性代数进阶:矩阵微积分如何服务反向传播

前言 这一篇不是基础线性代数笔记。矩阵乘法、转置、逆矩阵、特征值这些基础概念默认你已经见过。我们只关心一个更具体的问题:为什么深度学习里的反向传播经常要用矩阵微积分来描述? 在标量函数里,导数告诉我们“输入变化一点,输出会怎么变”。但神经网络里大量对象都不是标量:输入是向量,权重是矩阵,中间特征是高维张量,损失函数最后才压成一个标量。因此,普通的一元导数不够用,我们需要用 Jacobian、梯度向量和链式法则来描述这些对象之间的局部关系。 从标量导数到 Jacobian 设一个函数把向量 $x \in \mathbb{R}^n$ 映射到向量 $y \in \mathbb{R}^m$: $$ y = f(x) $$它的 Jacobian 矩阵定义为: $$ \begin{aligned} J_f(x) &= \frac{\partial y}{\partial x} \\\\ &= \begin{bmatrix} \frac{\partial y_1}{\partial x_1} & \cdots & \frac{\partial y_1}{\partial x_n} \\\\ \vdots & \ddots & \vdots \\\\ \frac{\partial y_m}{\partial x_1} & \cdots & \frac{\partial y_m}{\partial x_n} \end{bmatrix} \end{aligned} $$Jacobian 的含义不是“又多了一个复杂矩阵”,而是:它描述了函数 $f$ 在某一点附近的局部线性近似。 $$ f(x + \Delta x) \approx f(x) + J_f(x)\Delta x $$这就是 AI 中 Jacobian 最重要的直觉:非线性网络在局部可以近似看成线性变换。 ...

📅 August 1, 2026 · 🔄 更新于 2026-08-04 · ⏱️ 9 min · 📝 约 1361 字 · 👁️ — 次阅读

正向传播与反向传播:神经网络到底如何学习

前言 如果只看 PyTorch 代码,训练神经网络似乎很简单:写一个 forward,算出 loss,调用 loss.backward(),再让优化器更新参数。但这几行代码背后,其实压缩了深度学习最核心的一条数学主线: 正向传播负责把输入变成预测,反向传播负责把误差变成每个参数应该调整的方向。 理解这条主线之后,再看 CNN、ResNet、Transformer 或 LoRA,很多公式就不再像突然冒出来的符号。它们本质上都在回答同一个问题:信息如何向前流动,梯度又如何向后流动。 从一个神经元开始 一个最简单的神经元可以写成: $$ z = w^\top x + b $$其中 $x$ 是输入向量,$w$ 是权重向量,$b$ 是偏置。线性部分 $z$ 再经过一个非线性激活函数: $$ a = \sigma(z) $$如果没有激活函数,很多层线性变换叠在一起仍然只是一个线性变换,网络无法表示复杂的非线性关系。激活函数的作用,就是让每一层都能在“线性组合”之外引入弯曲和分段变化。 一层网络在做什么 把一个神经元扩展成一层全连接网络,可以写成矩阵形式: $$ \begin{aligned} z^{(l)} &= W^{(l)} a^{(l-1)} + b^{(l)} \\\\ a^{(l)} &= \sigma\left(z^{(l)}\right) \end{aligned} $$这里的上标 $(l)$ 表示第 $l$ 层。$a^{(l-1)}$ 是上一层输出,$W^{(l)}$ 和 $b^{(l)}$ 是这一层参数,$a^{(l)}$ 是这一层输出。 从这个角度看,神经网络并不是一个神秘黑盒,而是一串函数复合: $$ x \xrightarrow{f_1} a^{(1)} \xrightarrow{f_2} a^{(2)} \xrightarrow{f_3} \cdots \xrightarrow{f_L} \hat{y} $$正向传播就是沿着这条链从左到右计算。 ...

📅 August 1, 2026 · 🔄 更新于 2026-08-04 · ⏱️ 11 min · 📝 约 1687 字 · 👁️ — 次阅读

什么是机器学习和深度学习——从规则到数据的范式转移

前言 欢迎来到 Deep Learning 专栏。我们假设你修过一门传统机器学习课程(比如 HKU 的 COMP3314),或者对 ML 有基本了解;你也可能已经装过 PyTorch、跑通过几个示例项目,但对背后的数学原理还没有清晰的理解。这个专栏的目标是:从零开始,系统地拆解深度学习的核心概念和算法,让你不仅"能用",还能"懂"。 传统机器学习 想象一下我们小时候,父母是怎么教我们认识世界的。当你看到一只动物,父母可能会说:“这是一只猫——它有四条腿、毛茸茸的身体、喜欢吃鱼。” 我们会发现,想要区分一个东西是什么,我们会捕捉它的特征(四条腿、毛茸茸、喜欢吃鱼),并把这些特征和一个标签(猫)联系起来。这就是传统机器学习的核心思想:特征工程 + 模型训练。 在传统 ML 中,人类专家负责设计特征(例如图像的边缘直方图、纹理描述子),然后让算法(如 SVM、决策树)学习这些特征与标签之间的映射。这类方法在简单任务上效果不错,但当数据变得复杂——高分辨率图像、自然语言、原始音频——手工设计特征就成了瓶颈:你很难用几百个手工特征去描述一只猫的全部视觉变化。模型的性能天花板,本质上取决于特征的质量。 深度学习:为什么要"深" 为什么出现了深度学习? 在传统机器学习中,面对极其复杂且高维的数据时,依赖人工提取特征(比如手动设计边缘检测算子)遇到了难以逾越的瓶颈。深度学习的出现,正是为了解决“特征工程”的局限性。它通过引入多层次的组合原理,让模型自己从数据中学习表示。简单来说,较低的隐藏层学习简单的概念(如边缘、颜色),较高的隐藏层将这些简单概念组合成复杂的概念(如汽车、狗)。虽然早期的神经网络深受生物大脑机制启发,但现代深度学习已经不再将神经科学作为刚性指导,而是更多地依赖于应用数学(如线性代数、概率论、数值优化)来进行构建。 深度学习的历史 深度学习看似是近几年才爆发的全新领域,但实际上它已经经历了漫长的发展、多次改名与起伏。它的历史大致可以划分为三次浪潮: 第一次浪潮:控制论(Cybernetics,1940s–1960s) — 以生物学习理论为基础,出现了最早的线性模型(感知机 Perceptron、ADALINE)。当时人们希望通过逆向大脑的计算原理来建立智能。然而早期的线性模型存在严重局限——连简单的异或(XOR)函数都无法学习——直接导致了神经网络研究的第一次大衰退。 第二次浪潮:联结主义(Connectionism,1980s–1990s) — 核心思想是”大量简单的计算单元连接在一起时可以实现智能行为”。这一时期提出了对今天至关重要的分布式表示(Distributed Representation) 和 反向传播(Backpropagation) 算法,并引入了处理序列数据的 LSTM。但后来因投资者对 AI 的期望过高而不切实际,加之 SVM 等核方法的崛起,神经网络再次陷入低谷。 第三次浪潮:深度学习复兴(2006 年至今) — 以逐层贪婪预训练(Greedy Layer-wise Pretraining)为突破口,学术界终于找到了有效训练深层网络的方法。深度网络在测试样例上的泛化能力大幅提升,在图像识别、语音识别等复杂任务上全面超越了传统基于手工特征的 AI 系统。 为什么深度学习这几年才爆发 深度学习的核心算法(如反向传播)其实在 80 年代就已经存在,它的真正爆发和走向成熟主要归功于以下三个核心驱动力: 数据量爆炸:ImageNet(2009)、维基百科、YouTube 等大规模标注数据集的涌现。一个粗略的经验法则是:5000 个标注样本能达到可接受的性能,而 1000 万个样本能达到或超越人类水平。你在 COMP3314 课上学 SVM 或逻辑回归时,用的往往是数百行的小型结构化数据集;而 DL 时代面对的是百万级的复杂图像和文本,数据量本身催生了方法论的彻底变革。 算力与模型规模的指数级增长:GPU 从渲染管线变成并行计算引擎,CUDA 生态成熟。这使得神经网络的规模大约每 2.4 年就能翻一倍,如今庞大的参数量使网络能够处理前所未有的复杂任务。 算法演进与基建完善:ReLU 等现代激活函数的广泛使用解决了梯度消失问题、Batch Normalization 加速了训练、ResNet 让训练 100+ 层极深网络成为可能。同时,TensorFlow、PyTorch 等软件库极大降低了工程实现的门槛。 传统 ML vs 深度学习:一张对比表 维度 传统 ML(SVM、XGBoost) 深度学习 特征提取 人工设计,依赖领域知识 网络自动学习层次化表示 数据需求 几百到几千可训练 通常需要大量标注数据 计算资源 CPU 足够 GPU/TPU,训练成本高 可解释性 较高(特征权重可读) 较低,常被称为"黑盒" 代表任务 表格数据、小样本分类 图像、语音、NLP、生成 什么时候用传统 ML,什么时候用 DL 一个快速决策框架: ...

📅 June 15, 2026 · 🔄 更新于 2026-08-01 · ⏱️ 12 min · 📝 约 1815 字 · 👁️ — 次阅读

Large Language Models: 改变世界的语言革命

前言 2018 年 6 月,OpenAI 发布了首个基于 Transformer 架构的语言模型 GPT(Generative Pre-trained Transformer),标志着大语言模型(Large Language Models, LLM)时代的到来。 笔者接触 LLM 的时间很晚。笔者第一次了解到人工智能技术大约是在 2020 年,了解的是 Siri——一款 Apple 公司推出的智能语音助手。那时,笔者对人工智能的认知还停留在语音识别和图像识别这类传统的、基于规则或特定任务的 AI 技术上。 直到 2023 年,ChatGPT 的出现彻底打破了这种刻板印象。它不再是那种只会回答"对不起,我没听懂"的死板程序,而是展现出了令人惊叹的上下文理解与生成能力。直至 2024 年,LLM 已经跃升为人工智能领域的核心基础设施,并在自然语言处理、代码生成、知识问答等多个领域展现出强大的降维打击能力。 彼时,笔者第一次尝试使用 ChatGPT 进行代码生成,切身体验了 LLM 在编程辅助方面的巨大潜力。通过与 ChatGPT 的自然语言交互,笔者能够快速生成复杂的代码片段、精准调试报错程序。即使是面对晦涩的算法问题,它也能像一位不知疲倦的资深工程师一样,提供详细的逻辑拆解和替代方案。这种革命性的交互式编程体验,让笔者深刻认识到:我们正在经历一场软件工程范式的重构。 9.11 > 9.9 ?? 在大家惊叹于 LLM 无所不能的同时,也发生了一些令人啼笑皆非的"降智"事件。当时引发群众广泛讨论的一个有趣话题是:为什么询问 ChatGPT"9.11 和 9.9 哪个更大"时,它的回答往往是 9.11 更大? 人们尝试用不同的语气提问,甚至切换不同的语言,但早期的 LLM 几乎都会掉进这个陷阱。这一现象虽然看似荒诞,但却完美暴露了 LLM 底层运行逻辑的一个核心特征:它是一个"文字接龙"的高手,而不是一个内置了计算器的数学天才。 造成这个现象的原因主要有两个: 分词机制(Tokenization):LLM 看待世界的方式不是单个字母,而是"词元(Token)"。在切分 9.11 时,它可能会将其视为 9、.、11。在语言模型的潜意识里,整数 11 显然大于 9。 语料库的语义偏差:在人类互联网的海量文本中,带小数点的数字经常被用作"软件版本号"。从版本迭代的逻辑来看,v9.11 确实是 v9.9 之后发布的新版本。 这个经典的错觉引发了学术界和工业界对 LLM 逻辑推理边界的深刻反思,也成为了推动模型向"深度思考"和"强化学习"演进的催化剂。这让我们不禁要问:这些看起来像人的机器,到底是由什么构成的? ...

📅 June 22, 2026 · ⏱️ 20 min · 📝 约 3118 字 · 👁️ — 次阅读

解析代码的正确姿势:Tree-sitter 的原理和实践

前言 如果你用过 GitHub Copilot、ChatGPT 或者其他 AI 编程助手,你可能会注意到它们在理解代码结构和语法方面表现得非常出色。这背后有一个关键技术—— Tree-sitter 。本文将深入探讨 Tree-sitter 的原理、它在 AI Agent 时代的不可替代性,以及如何在 Python 和 C++ 项目中构建一套代码解析流水线。 什么是 Tree-sitter? 简单来说,Tree-sitter 是一个用于解析代码的增量解析器生成器,它可以将源代码解析成抽象语法树(AST),并提供高效的增量更新能力。它支持多种编程语言,并且可以生成高性能的解析器,使得开发者能够快速构建代码分析工具、编辑器插件和其他与代码相关的应用。 AST(抽象语法树) 抽象语法树(AST,Abstract Syntax Tree),简称 AST,是源代码的抽象语法结构的树状表示。它位于源代码和机器代码之间,提供了一种更高层次的代码表示方式。AST 的节点表示语言的语法结构,如变量声明、函数调用、条件语句等,而边则表示这些结构之间的关系。 AST 的核心作用 代码分析:AST 提供了对代码结构的深入理解,使得静态分析工具能够检测潜在的错误、代码风格问题和安全漏洞。 代码转换:通过操作 AST,开发者可以实现代码的自动重构、优化和转换,例如将一种编程语言的代码转换为另一种语言。 代码生成:编译器可以通过 AST 生成目标代码,从而实现源代码到机器代码的转换。 例如,在 JavaScript 中,以下代码: javascript Copy function add(a, b) { return a + b; } 可以被解析为如下的 AST: ...

📅 June 21, 2026 · ⏱️ 12 min · 📝 约 1901 字 · 👁️ — 次阅读

状态机——Agent 的行为骨架

前言 做 Agent 开发时,最让工程师头疼的问题往往不是底层大模型(LLM)不够聪明,而是 Agent 的行为难以可控。在真实的业务场景中,用户的一句话可能隐含多种意图,或者意图非常模糊。这就要求 Agent 必须学会在不同的"对话阶段"之间灵活切换——从最初的寒暄问候,到多轮的信息收集,再到决定调用外部工具,最后与用户确认并结束对话。 如果仅仅依靠 Prompt 让大模型自主决定下一步该做什么(例如纯粹的 ReAct 模式),系统会变得极其脆弱。模型可能会陷入死循环、产生幻觉,或者跳过关键的业务校验步骤。为了解决这种复杂性,我们需要引入软件工程中久经考验的标准工具:状态机(State Machine)。它能为概率性的 LLM 提供一个确定性的行为骨架。 什么是状态机 理解状态机最直观的方法是想象一扇普通的门。这扇门有两个状态:开 与 关。你可以对它施加两个事件(动作):推 与 拉。 如果你对一扇处于关状态的门执行推事件,门就会进入开状态。但如果门已经是开的状态,再执行推就没有任何意义(甚至是一个非法操作)。这就是状态机的核心逻辑:当前状态 + 触发事件 $\to$ 新状态。 在计算机科学中,它的形式化定义通常是一个五元组: 状态集合($S$):系统所有可能状态的有限集合。 初始状态($s_0$):系统启动时的默认状态($s_0 \in S$)。 事件集合($E$):触发状态改变的输入或条件。 转移函数($\delta: S \times E \to S$):定义了在特定状态下接收到特定事件时,应该转移到哪个新状态。 终止状态集合($F$):表示流程结束的状态集合($F \subseteq S$)。 在构建 Agent 时,我们通常会遇到两种常见的状态机类型: 有限状态机(Finite State Machine, FSM):状态和事件的数量是有限的,所有的状态流转(转移函数)都是在代码中严格预先定义好的。它非常适合逻辑固定、边界清晰的任务。 图状态机(Graph-based State Machine):这是目前复杂 Agent 框架的主流(如 LangGraph)。它的状态流转可以是动态计算的,原生支持条件分支、循环回路以及并行处理,更适合处理多轮对话和复杂的逻辑编排。 为什么 Agent 需要状态机 一个可靠的 Agent 绝不能是一个"黑盒"。它的运行生命周期应该经历明确的阶段,并且每个阶段(状态)都有单一、清晰的职责。我们来看一个典型的 Agent 运转流程: flowchart TD A[空闲 IDLE] -->|用户提问| B[分析意图 ANALYZING] B -->|需要工具| C[调用工具 TOOL_CALL] B -->|无需工具| D[生成回复 RESPOND] C -->|工具完成| D D -->|发送回复| A 在这个流程中,核心关键点在于意图分析后的条件分支。有些用户请求(如"你是谁?")可以直接生成回复;而有些请求(如"今天香港的天气如何?")则必须先去调用天气 API。 ...

📅 June 19, 2026 · ⏱️ 19 min · 📝 约 2903 字 · 👁️ — 次阅读

初见

前言 大家好,这里是 HJJJ。 想必作为一个 CS 学生,搭建一个个人博客是必经之路。然而由于本人先前的懒惰,一直没有探索这个领域。直到最近,突然发现自己已经学了不少东西了,而有些学到的东西由于缺少实际应用,已经快要忘记了——于是我决定搭建一个个人博客,用来记录学习过程和心得体会。 什么是网站? 网站是由一系列通过超链接相互关联的网页组成的集合,通过域名访问,并托管在一个或多个服务器上。服务器负责存储网站的内容,域名则提供了用户访问的地址。网站可以包含文本、图片、视频、音频等多种类型的内容,用户通过浏览器来访问这些内容。 静态网站和动态网站 网站大致分为静态网站和动态网站两类。 静态网站是指那些内容固定不变的网站,用户访问时看到的内容是预先生成的。这些网站通常使用 HTML、CSS 和 JavaScript 来构建,内容由开发者手动编写和更新。静态网站的优点是加载速度快且安全性较高,因为它们不依赖服务器端的处理。 动态网站则是指那些内容可以根据用户的请求动态生成的网站。这些网站通常使用服务器端语言(如 PHP、Python、Ruby 等)和数据库来存储和管理内容。动态网站的优点是可以提供个性化的用户体验和更丰富的功能,但它们可能会面临性能和安全方面的挑战。 对于个人博客来说,大多数时候我们只是在展示静态内容——文章、图片、代码片段。动态网站的功能虽然强大,但维护成本和性能开销都更高。因此,静态网站生成器成了我的首选。 选择 Hugo 静态网站生成器有很多选择:Jekyll、Hexo、Hugo、Zola……每个都有自己的特点。我最终选择 Hugo,主要看中三点: 速度极快:Hugo 基于 Go 语言构建,生成整个站点通常只需要几毫秒到几秒,远快于大多数同类工具。 单文件部署:Hugo 是一个独立的可执行文件,不需要安装任何依赖环境,下载就能用。 主题丰富:Hugo 社区提供了大量现成的主题,直接拿来用就能得到一个美观的博客。 Hugo 允许用户使用 Markdown 文件来编写内容,并通过模板系统来定义网站的结构和样式,对我这种想专注于写作的人来说非常友好。 如何使用 Hugo 搭建博客 首先,你需要寻找一个地方来放你的源码。这里以 Windows 系统为例,打开命令行工具,进入你想要存放博客源码的目录。例如,我想把源码放在 D 盘的 blog 文件夹下: PowerShell Copy cd D:\blog 接下来,使用 Hugo 命令创建一个新的站点文件夹(我们这里先给它起名叫 myblog,你也可以换成别的名字): PowerShell Copy hugo new site myblog 这条命令会在当前目录下创建一个名为 myblog 的文件夹,里面包含了 Hugo 站点的基本结构。 进入新创建的站点文件夹并初始化 Git: PowerShell Copy cd myblog git init 初始化 Git 仓库是为了后续将代码推送到 GitHub。先在本地修改源码,完成内容编写后推送到 GitHub,再部署到托管服务器,这样其他人就可以通过互联网访问我们的网站了。 接下来,我们需要选择一个主题来美化我们的网站。Hugo 有很多现成的主题可供选择,你可以在 Hugo Themes 上浏览和选择适合你的主题。选择好主题后,按照主题的安装说明将其添加到你的 Hugo 站点中。以 PaperMod 为例,安装命令如下: PowerShell Copy git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod 这条命令会将 PaperMod 主题添加到你的站点的 themes 文件夹中。 在你的站点的 hugo.toml 配置文件中,你可以设置 theme 参数为你选择的主题名称。例如: toml Copy theme = "PaperMod" 现在,你可以使用 Hugo 的命令来创建新的内容了。例如,创建一个新的博客文章: PowerShell Copy hugo new posts/my-first-post.md 这条命令会在 content/posts 文件夹下创建一个名为 my-first-post.md 的 Markdown 文件,你可以在其中编写你的博客内容。 当你完成了内容的编写后,我们可以打开一个本地服务器来预览我们的网站: PowerShell Copy hugo server -D 这条命令会启动一个本地服务器,并在浏览器中打开你的站点预览页面。你可以在这里查看你的博客文章,并进行调整和修改(-D 参数表示包括草稿文章在内的所有内容都会被预览)。 ...

📅 June 11, 2026 · 🔄 更新于 2026-06-17 · ⏱️ 9 min · 📝 约 1401 字 · 👁️ — 次阅读
Comments