12篇改变一切的AI论文:详细解释与代码示例

本文有一个短视频:TikTok

1. 概述

你每天使用的大多数AI系统——ChatGPT、Midjourney、Google搜索与AI概览——都建立在约十几篇研究论文的基础之上。本文介绍了这12篇论文,用简明易懂的语言解释了核心思想,并用简短的Java代码片段演示了每个思想。读完后,你会理解为什么Transformer“吃掉”了整个NLP世界,为什么RAG能解决幻觉问题,以及为什么一个“逐步思考”的提示词竟然这么强大。

2. AlexNet (2012)——深度学习开始“看见”

在AlexNet之前,计算机视觉依赖于手工特征工程。AlexNet使用卷积神经网络(CNN)和ReLU激活及dropout,在GPU上训练,并在ImageNet 2012上击败所有对手,错误率低了近10个百分点。这是深度学习时代的开场爆炸。

public class ConvOutputSizeCalculator {

    public static int outputSize(int inputSize, int kernelSize, int stride, int padding) {
        return (inputSize - kernelSize + 2 * padding) / stride + 1;
    }

    public static void main(String[] args) {
        // AlexNet输入图像:227x227,核11x11,步长4
        int size = outputSize(227, 11, 4, 0);
        System.out.println(size);
    }
}
55

outputSize计算conv层之后的特征图大小。对于227×227输入和11×11核步长4的情况,输出是55×55×96——正是AlexNet第一层的大小。ReLU帮助梯度不像sigmoid那样“消失”,所以更深的网络仍然可以训练。

3. GAN (2014)——两个网络对抗生成真实图像

生成对抗网络(GAN)将两个网络置于对抗关系中:生成器试图创建虚假图像欺骗判别器,判别器试图区分真假图像。两者在每一轮训练中都相互改进。

public record GanLosses(double discriminatorLoss, double generatorLoss) {}

public class GanLossCalculator {

    public static GanLosses compute(double probReal, double probFake) {
        double dLoss = -(Math.log(probReal) + Math.log(1 - probFake));
        double gLoss = -Math.log(probFake);
        return new GanLosses(dLoss, gLoss);
    }
}

probReal是判别器正确识别真实图像的概率,probFake是它被生成器欺骗的概率。判别器希望probReal → 1且probFake → 0;生成器则相反。这是典型的零和博弈。

注意: GAN以难以训练而著称——容易出现模式崩溃(生成器只产生几种重复的图像)。后来的扩散模型稳定得多,所以大多数现代图像生成系统(DALL·E、Stable Diffusion)不再使用GAN。

4. Transformer (2017)——“Attention Is All You Need”

Transformer完全放弃了RNN/LSTM,取而代之以自注意力机制:每个token直接查看句子中的所有其他token来计算相关性,无需顺序处理。这是GPT、Claude、Llama、BERT等模型的基础架构。

public class ScaledDotProductAttention {

    public static double[] attendFirstToken(double[][] query, double[][] key) {
        int seqLen = key.length;
        int dim = query[0].length;
        double scale = Math.sqrt(dim);
        double[] scores = new double[seqLen];
        for (int j = 0; j < seqLen; j++) {
            double dot = 0;
            for (int k = 0; k < dim; k++) dot += query[0][k] * key[j][k];
            scores[j] = dot / scale;
        }
        return softmax(scores);
    }

    private static double[] softmax(double[] row) {
        double max = Arrays.stream(row).max().orElse(0);
        double sum = 0;
        double[] exps = new double[row.length];
        for (int i = 0; i < row.length; i++) {
            exps[i] = Math.exp(row[i] - max);
            sum += exps[i];
        }
        for (int i = 0; i < exps.length; i++) exps[i] /= sum;
        return exps;
    }
}

dot / scale这一行将点积除以sqrt(dim)以避免值过大导致softmax饱和。softmax的结果是注意力权重——与正在考虑的token关系密切的token将获得较高的权重,用于混合value向量。

5. Scaling Laws (2020)——损失按幂律递减

OpenAI发现:每当按指数增加参数、数据或计算量时,损失会按照相当平滑且可预测的幂律递减——没有“魔法”,只需正确扩展。

public class ScalingLawEstimator {

    // L(N) = (Nc / N)^alpha — N: 参数数量(十亿),Nc、alpha:来自经验数据的常数
    public static double estimateLoss(double paramsBillion, double nc, double alpha) {
        return Math.pow(nc / paramsBillion, alpha);
    }
}

对于从经验数据中固定的nc和alpha,增加paramsBillion使得estimateLoss逐渐减小但速度变慢(收益递减)。这就是为什么AI实验室投入数亿美元用于计算:损失递减是可预测的,而非赌博。

注意: 扩展规律不是无限的。超过某个阈值后,要再降低一点损失需要以巨大的指数倍增加计算——这就是为什么该领域正转向改进数据和架构,而不仅仅“做大”。

6. GPT-3 (2020)——规模创造新能力

拥有1750亿参数的GPT-3表明:足够大的模型可以进行少样本学习——只需在提示中提供几个示例,无需重新微调权重。

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>
@Service
public class FewShotClassifier {

    private final ChatClient chatClient;

    public FewShotClassifier(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    public String classifySentiment(String review) {
        String prompt = """
                评论:"产品很好,送货快" -> 正面
                评论:"货物有缺陷,无法使用" -> 负面
                评论:"%s" ->
                """.formatted(review);
        return chatClient.prompt(prompt).call().content();
    }
}

提示中的两个示例充当“教”模型如何格式化答案的角色,都在上下文中进行——无需重新训练。这正是较小的模型难以做好的突现能力。

7. InstructGPT & RLHF (2022)——将粗糙的LLM变为有用的助手

原始的GPT-3善于预测下一个token,但不“听话”——它可能会给出题外话的答案或有害的内容。InstructGPT使用人类反馈强化学习(RLHF):人类对答案进行排名,据此训练奖励模型,然后使用奖励模型通过PPO优化策略。

public record Completion(String text, double rewardScore) {}

public class RewardBasedSelector {

    public Completion pickBest(List<Completion> candidates) {
        return candidates.stream()
                .max(Comparator.comparingDouble(Completion::rewardScore))
                .orElseThrow();
    }
}

上面的代码只演示了最后一步:根据奖励模型的评估选择奖励最高的完成度。在实际操作中,PPO逐步更新策略模型的权重,使其从一开始就能自动生成高分答案,无需事后选择。

注意: RLHF需要大量人类标注的排名数据,成本高昂且容易受评分者偏见的影响。后来出现了DPO(直接偏好优化)等技术来降低这种成本。

8. ViT (2020)——图像也可以是一个“句子”

Vision Transformer将图像分割成小补丁(例如16×16像素),将每个补丁展平成向量,然后将它们视为token输入Transformer编码器——架构与文本处理完全相同。

public class PatchEmbeddingCalculator {

    public static int numPatches(int imageSize, int patchSize) {
        int gridSize = imageSize / patchSize;
        return gridSize * gridSize;
    }
}

对于224×224的图像和16×16的补丁,numPatches返回196——相当于196个token的“句子”输入Transformer。通过这种方式,ViT重复使用了在NLP中已证明有效的注意力技术来解决视觉问题,并在训练数据足够大时超越CNN。

9. DDPM (2020)——加噪然后学会去噪

去噪扩散概率模型(DDPM)为所有现代扩散模型奠定了基础:前向过程在许多步骤中逐渐向图像添加高斯噪声,反向过程学会预测并去除噪声以重建原始图像。

public class ForwardDiffusion {

    public static double[] addNoise(double[] x0, double alphaBarT, Random random) {
        double[] xt = new double[x0.length];
        for (int i = 0; i < x0.length; i++) {
            double noise = random.nextGaussian();
            xt[i] = Math.sqrt(alphaBarT) * x0[i] + Math.sqrt(1 - alphaBarT) * noise;
        }
        return xt;
    }
}

alphaBarT控制在步骤t保留原始图像相对于噪声的比例:接近1意味着接近原始图像,接近0意味着接近纯噪声。生成模型学习反向这个过程——从纯噪声开始,逐步“去噪”生成有意义的图像。

10. Latent Diffusion (2021)——在压缩空间中去噪

直接在像素上运行扩散过程计算量很大。潜在扩散通过自编码器将图像压缩到更小的潜在空间,在那里运行整个去噪过程,然后解码回图像——这是Stable Diffusion的设计基础。

public class LatentCompressionCalculator {

    public static long pixelCount(int width, int height, int channels) {
        return (long) width * height * channels;
    }
}
pixelCount(512, 512, 3) = 786_432   // 像素空间
pixelCount(64, 64, 4)   = 16_384    // 潜在空间

大约48倍的压缩率使扩散过程运行得快得多,同时仍保持图像质量,因为像素空间中的大部分“冗余”信息(均匀色域、微小细节)在压缩时已被自编码器丢弃。

11. CLIP (2021)——在一个空间中连接图像和文字

CLIP在数百万个(图像,标题)对上训练对比学习:匹配的对的嵌入接近,不匹配的对远离。结果是一个共享空间,允许使用余弦相似度比较文本和图像。

@Service
public class ImageTextMatcher {

    private final EmbeddingModel embeddingModel;

    public ImageTextMatcher(EmbeddingModel embeddingModel) {
        this.embeddingModel = embeddingModel;
    }

    public double similarity(String caption, float[] imageEmbedding) {
        float[] textEmbedding = embeddingModel.embed(caption);
        return cosine(textEmbedding, imageEmbedding);
    }

    private double cosine(float[] a, float[] b) {
        double dot = 0, normA = 0, normB = 0;
        for (int i = 0; i < a.length; i++) {
            dot += a[i] * b[i];
            normA += a[i] * a[i];
            normB += b[i] * b[i];
        }
        return dot / (Math.sqrt(normA) * Math.sqrt(normB));
    }
}

如果标题与图像内容相符,similarity返回接近1的值;如果无关,则返回接近0或负值。这是许多电子商务产品正在使用的自然语言描述图像搜索(文本到图像搜索)背后的机制。

12. Chain-of-Thought (2022)——一句提示词解锁推理

仅仅在提示中加入“逐步思考”这个短语,大型LLM就会自动将复杂问题分解为较小的步骤,相比直接回答能大大减少计算错误和逻辑错误。

public String solveWithReasoning(ChatClient chatClient, String question) {
    String prompt = """
            请在回答之前逐步思考。
            问题:%s
            推理:
            """.formatted(question);
    return chatClient.prompt(prompt).call().content();
}

要求模型在给出最终答案前“推理”迫使它生成中间token作为支撑——就像人类在回答难题前先打草稿一样。

注意: 思维链增加了生成的token数量,导致成本和延迟更高。对于简单问题(直接事实查询),强制使用CoT只会降低速度而不会提高准确性。

13. RAG (2020)——检索后生成,不再编造

检索增强生成(RAG)将LLM与文档检索步骤相连,在生成答案前检索真实文档,有助于减少幻觉并允许基于原始训练范围之外的最新数据进行回答。

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>
@Service
public class DocumentAnsweringService {

    private final VectorStore vectorStore;
    private final ChatClient chatClient;

    public DocumentAnsweringService(VectorStore vectorStore, ChatClient.Builder builder) {
        this.vectorStore = vectorStore;
        this.chatClient = builder.build();
    }

    public String answer(String question) {
        List<Document> relevant = vectorStore.similaritySearch(
                SearchRequest.query(question).withTopK(3));

        String context = relevant.stream()
                .map(Document::getContent)
                .collect(Collectors.joining("\n---\n"));

        String prompt = """
                根据以下文档回答问题。如果没有信息,请说"不清楚"。
                文档:
                %s

                问题:%s
                """.formatted(context, question);

        return chatClient.prompt(prompt).call().content();
    }
}

similaritySearch检索与问题语义最接近的3个文档片段,将它们连接到提示作为上下文,然后强制模型基于该上下文回答,而不是“回忆”模糊的训练记忆。

class DocumentAnsweringServiceTest {

    @Test
    void shouldReturnUnknownWhenNoRelevantDocument() {
        VectorStore emptyStore = mock(VectorStore.class);
        when(emptyStore.similaritySearch(any())).thenReturn(List.of());

        ChatClient stubClient = mock(ChatClient.class, RETURNS_DEEP_STUBS);
        when(stubClient.prompt(anyString()).call().content()).thenReturn("不清楚");

        ChatClient.Builder builder = mock(ChatClient.Builder.class);
        when(builder.build()).thenReturn(stubClient);

        DocumentAnsweringService service = new DocumentAnsweringService(emptyStore, builder);

        String result = service.answer("公司何时成立?");

        assertThat(result).contains("不清楚");
    }
}

测试确认当找不到相关文档时,答案必须说“不清楚”而不是编造答案——这正是RAG的grounding目标。

注意: 如果你的整个文档库只有几十页,直接填充到上下文窗口比构建完整的RAG管道加向量存储更简单便宜。RAG仅在数据量大或经常变化时才值得使用。

14. 结论

这12篇论文不是独立的——它们相互构建:Transformer是GPT-3和ViT的基础;扩展规律解释了为什么GPT-3有效;RLHF将GPT-3转变为ChatGPT;DDPM是Latent Diffusion的源头;CLIP是扩散模型理解文本提示的桥梁。清楚地理解每一块拼图能帮助你更快地阅读新论文,因为现在大多数“新”思想都是这些基础的变体或组合。

llmdeep-learningtransformerragai