小菜鸟

java菜鸟号正在起航

大模型第一课:手写推导线性回归的“灵魂”

在深度学习和人工智能的宏大叙事中,Transformer、大语言模型动辄拥有千亿参数,令人望而生畏。但如果我们剥去这些复杂的外衣,会发现一切神经网络的基石,其实都源于一个最简单的模型——线性回归

今天这篇博客,我们不谈复杂的框架代码,而是回归数学本质。我们将通过一份手写的学习笔记,彻底搞懂机器是如何通过“试错”来学会预测的。

核心观点:理解线性回归,就是掌握了深度学习的“第一性原理”。


一、模型的诞生:给数据画一条直线

想象一下,你是一名房产中介,手头有一堆历史成交数据(房子的面积和对应的价格)。你的目标是找到一条规律,能最好地“穿过”这些数据点,从而根据新房子的面积来预测它的价格。

这就是线性回归要解决的问题:拟合

为了实现这个目标,我们需要定义两个核心要素:

  • 输入值 (x):喂给模型的特征数据(例如:房子面积)。
  • 输出值 (z):模型给出的预测结果(例如:预测房价)。

为了让 x 变成 z,我们需要两个可调节的参数——这也是模型真正要去“学习”的东西:

  1. 权重 ($w$, Weight):决定输入 x 对结果的影响程度。在几何上,它是直线的斜率
  2. 偏置 ($b$, Bias):决定当 x=0 时的基础值。在几何上,它是直线的截距

于是,我们得到了机器学习界最经典的公式:

💡 笔记划重点:这个简单的线性公式,就是所有神经网络神经元计算的雏形。


二、怎么才算“学得好”?引入 Loss 函数

模型给出了预测值 z,但怎么知道它准不准呢?我们需要一个“裁判”来打分。这个裁判就是损失函数(Loss Function)

同时,我们需要一个参照标准——目标值 (Y, Ground Truth),也就是真实答案(例如:房子的实际成交价)。

笔记中使用了最直观的均方误差(MSE)思想。为了简化推导,我们只看单个样本的误差平方:

阅读全文 »

从静态词向量到动态理解:NLP 预训练模型的完整进化图谱

在自然语言处理(NLP)的学习过程中,理清模型的演进路线至关重要。这不仅仅是算法的更迭,更是我们对“如何让机器理解语言”这一认知不断深化的过程。回顾过去几年,我们经历了一场从简单的词嵌入到大规模预训练模型的技术革命。

今天,我们就来梳理一下这条从 Word2Vec 到 ELMo,再到 BERT 的进阶之路,看看它们是如何一步步改变我们对“语言表示”的理解的。


一、起点:Word2Vec 与静态词向量

一切的起点是从 Word2Vec 开始的。

维度 说明
核心思想 将离散的词语映射为连续的向量空间(Embedding)
核心贡献 解决了计算机无法直接处理文本的问题,并且捕捉到了词语之间的语义关系。比如:King - Man + Woman ≈ Queen
致命局限 它是静态的。无论上下文如何变化,“苹果”这个词的向量永远是一样的,无法区分是水果还是科技公司。

这种“一词多义”的困境,严重限制了模型对上下文的理解能力。


二、序列建模:RNN 及其变体

为了让机器理解句子的顺序和语境,我们引入了循环神经网络(RNN)。

原理:RNN 具有“记忆”功能,当前的输出不仅取决于当前的输入,还取决于上一时刻的状态。这使得它能够处理变长的序列数据。

痛点:标准的 RNN 存在严重的梯度消失/梯度爆炸问题,导致它很难记住长句子开头的信息(即长距离依赖问题)。

改进:为了解决这个问题,LSTM(长短期记忆网络)和 GRU(门控循环单元)应运而生。它们通过引入“门控机制”,有效地控制了信息的遗忘和保留,成为了当时处理序列任务的主流选择。

模型 核心创新 解决的问题
RNN 循环结构,具有“记忆” 处理变长序列
LSTM 遗忘门、输入门、输出门 长距离依赖(梯度消失)
GRU 更新门、重置门(LSTM 的简化版) 长距离依赖,参数更少

三、架构升级:Seq2Seq 模型

有了强大的 RNN/LSTM 作为基础组件,Seq2Seq(Sequence-to-Sequence)架构诞生了。

结构:它由两个 RNN 组成——编码器(Encoder)解码器(Decoder)

工作流

阅读全文 »

Python 多进程:8 核 CPU 只有 1 个在跑?那是 GIL 在”捣乱”

写了一个计算密集型的程序,跑起来 CPU 占用 100%,但仔细一看——8 个核心只有 1 个在满负荷运转,剩下 7 个几乎闲置。

这不是程序写得不对,是 Python 的 GIL(全局解释器锁) 在”从中作梗”。GIL 规定:同一时刻,只有一个线程能执行 Python 代码。所以多线程在计算任务上,形同虚设。

多进程是绕过 GIL 的方案——每个进程有自己独立的 Python 解释器,各自跑各自的,操作系统把它们调度到不同的 CPU 核心上,真正实现了并行。

什么场景用多进程? CPU 密集型——大量计算、加密解密、图像处理、数据压缩。这种任务”算”的时间多,”等”的时间少,多线程没用,多进程才是答案。

先看证据:多线程 vs 多进程,差距一目了然

import multiprocessing
import threading
import time
from concurrent.futures import ThreadPoolExecutor

def cpu_work(n):
    """纯计算,不干别的"""
    count = 0
    for i in range(2, n):
        is_prime = all(i % j != 0 for j in range(2, int(i**0.5) + 1))
        if is_prime:
            count += 1
    return count

# 单线程
start = time.time()
cpu_work(100000)
print(f"单线程: {time.time() - start:.2f}s")

# 多线程(4个)
start = time.time()
with ThreadPoolExecutor(4) as ex:
    [cpu_work(100000) for _ in range(4)]
print(f"多线程: {time.time() - start:.2f}s")   # 比单线程还慢!

# 多进程(4个)
start = time.time()
with multiprocessing.Pool(4) as pool:
    pool.map(cpu_work, [100000] * 4)
print(f"多进程: {time.time() - start:.2f}s")   # 约单线程的 1/4

典型结果:

单线程: 2.35s
多线程: 2.78s   ← 不仅没快,还慢了
多进程: 0.68s   ← 接近 4 倍提速

多线程在计算任务上不仅无效,线程切换还带来额外开销。多进程才是真正的并行。

多进程池:别反复创建进程,用池复用

每次创建进程都要分配内存、启动解释器,开销不小。实际开发用进程池——预先创建一批进程,任务来了分配,干完了回收。

import multiprocessing

def worker(n):
    return n ** 2

if __name__ == "__main__":
    # 默认进程数 = CPU 核心数
    with multiprocessing.Pool() as pool:
        # map:批量提交,保持顺序
        results = pool.map(worker, range(100))
        
        # apply_async:异步提交单个任务
        async_result = pool.apply_async(worker, (10,))
        result = async_result.get()  # 获取结果(会阻塞)

进程数设多少?

任务类型 建议进程数
CPU 密集型 CPU 核心数
I/O 密集型(但不想用异步) CPU 核心数 × 2
内存密集型 CPU 核心数 ÷ 2

设多了没用,操作系统频繁切换进程反而拖慢速度。

阅读全文 »

深度学习三大支柱:CNN、RNN 与预训练语言模型

核心认知:深度学习并非单一技术,而是由不同架构组成的“武器库”——CNN 擅长捕捉空间特征(图像),RNN 擅长处理时序依赖(文本、语音),而预训练语言模型(PLM)则通过“预训练+微调”范式,彻底改变了自然语言处理的方式。

本文将从原理到应用,系统讲解三种核心深度学习架构,帮助你建立完整的知识体系。


目录

  1. 卷积神经网络(CNN)
  2. 循环神经网络(RNN)与双向RNN
  3. 预训练语言模型与微调
  4. 三者对比与选型

卷积神经网络(CNN)

为什么需要 CNN?

传统的全连接神经网络在处理图像时会遇到两个致命问题:

问题 说明 后果
参数爆炸 一张 224×224 的彩色图片有 150,528 个像素,全连接层的参数数量 = 输入维度 × 输出维度 需要海量数据和计算资源
丢失空间结构 全连接层将像素展平为一维向量,忽略像素间的空间关系 无法识别边缘、形状等局部模式

CNN 的解决方案:通过局部连接权重共享,大幅减少参数数量,同时保留空间结构信息。

CNN 的核心组件

┌─────────────────────────────────────────────────────────────────────┐
│                        CNN 整体架构                                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   输入图像        卷积层       池化层       卷积层       池化层      全连接层      输出   │
│                                                                     │
│   ┌─────┐      ┌─────┐      ┌─────┐      ┌─────┐      ┌─────┐      ┌─────┐      ┌─┐   │
│   │     │ ──→ │     │ ──→ │     │ ──→ │     │ ──→ │     │ ──→ │     │ ──→ │ │   │
│   │ 224 │      │ 222 │      │ 111 │      │ 110 │      │ 55  │      │ 4096│      │10│   │
│   │ ×224│      │ ×222│      │ ×111│      │ ×110│      │ ×55 │      │     │      │ │   │
│   │ ×3  │      │ ×32 │      │ ×32 │      │ ×64 │      │ ×64 │      │     │      └─┘   │
│   └─────┘      └─────┘      └─────┘      └─────┘      └─────┘      └─────┘            │
│     3             32           32           64           64          4096            10  │
│   (RGB通道)    (特征图)     (降维后)      (特征图)      (降维后)      (特征向量)      (类别) │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

1. 卷积层(Convolutional Layer)

卷积核(Filter/Kernel):一个小的权重矩阵(如 3×3 或 5×5),在输入图像上滑动,计算局部区域的点积,生成特征图。

卷积操作可视化(步长=1,无填充)

输入图像 (5×5)              卷积核 (3×3)              输出特征图 (3×3)
┌─────────────────┐        ┌─────────┐              ┌─────────────────┐
│ 1  1  1  0  0 │        │ 1  0  1 │              │ 4  3  4 │
│ 0  1  1  1  0 │   ⊙    │ 0  1  0 │     =      │ 2  4  3 │
│ 0  0  1  1  1 │        │ 1  0  1 │              │ 2  3  4 │
│ 0  0  1  1  0 │        └─────────┘              └─────────────────┘
│ 0  1  1  0  0 │
└─────────────────┘

每个输出位置 = 卷积核与输入对应区域的逐元素乘积之和

关键参数

阅读全文 »

让 AI 学会“自我反思”:用 LangGraph 构建能不断改进的智能写作 Agent

一、问题的起源:一次生成真的够吗?

传统的 AI Agent 通常采用“一次性生成”的模式:用户输入指令 → 模型输出结果 → 结束。这种方式存在一个明显的缺陷:

AI 无法审视自己的输出,也不知道自己写得对不对。

想象一下,如果让一个人类写文章:

  1. 先写初稿 ✍️
  2. 再读一遍,找问题 🤔
  3. 不满意就修改 🔧
  4. 再读,再改,直到满意 ✅

这种写作-反思-修改-再反思的循环,是人类提升作品质量的本能方法。那么,能不能让 AI 也学会这套流程?

答案是肯定的。LangGraph 提供了构建这种循环工作流的能力。

二、什么是 LangGraph?

LangGraph 是 LangChain 生态中用于构建有状态、多步骤、循环式 Agent 的框架。它的核心概念非常简单:

概念 英文 说明 类比
状态 State 所有节点共享的“记事本” 白板
节点 Node 一个具体的操作/函数 工位上的一个员工
Edge 节点之间的连线 员工之间的传话路径
条件边 Conditional Edge 根据状态决定下一步走向 有决策权的经理

与传统 Agent 最大的区别:LangGraph 天然支持循环(Loop),这是实现“自我反思”的基础。

三、本次实现的工作流

我们将构建一个具有自我反思能力的写作 Agent,它的工作流程如下:

START → 写作节点 → 反思节点 → 质量评分 ≥8? 
                              ↓
                         是 → END
                              ↓
                         否 → 修改节点 → (回到反思节点)

这是一个典型的反馈循环架构,广泛用于需要持续优化的场景。

阅读全文 »
0%