Agent前两周系统学习笔记

4 阅读28分钟

前两周系统学习笔记

说明

本笔记覆盖 Python 核心语法 + 大模型工作原理,按「基础→进阶」分周编排,包含核心知识点、代码示例、注意事项、实操任务、进阶提示,适配新手系统学习与即时自测。


第一周:基础认知与核心入门

本周学习目标

  1. 掌握 Python 基础语法,能编写简单的条件判断、循环程序
  2. 理解大模型的核心基础概念(Token、上下文窗口、分词)
  3. 能独立处理简单的 Python 语法错误(如除数为0、类型错误、缩进错误)
  4. 熟练使用交互式环境(IDLE 或 Jupyter Notebook)进行代码调试

模块1:Python 核心语法 - 基础篇

1.1 变量与数据类型

变量规则
维度核心内容注意事项
变量命名1. 命名:字母/数字/下划线,不能以数字开头
2. 无需声明类型,赋值即定义
3. 支持多变量赋值:a, b = 10, 20
4. 支持链式赋值:x = y = z = 0
1. 变量名区分大小写(Ageage
2. 避免使用关键字(如 if/for/class)作为变量名
3. 变量名应具有描述性,遵循PEP 8命名规范(小写字母+下划线)

代码示例:

# 合法命名
name = "Alice"
age_18 = True

# 多变量赋值
x, y, z = 1, 2.5, "hello"

# 链式赋值
a = b = c = 100

# 查看类型
print(type(age_18))  # <class 'bool'>
核心数据类型
维度核心内容注意事项
不可变类型- int(整数):5 100 0b1010(二进制)
- float(浮点数):3.14 2.0 1e-3
- str(字符串):"python" 'AI' """多行"""
- bool(布尔):True False
- tuple(元组):(1, 2, 3)
- NoneType:None
1. 元组即使只有一个元素,也需加逗号:(5,)
2. 浮点数存在精度问题(如 0.1+0.2 不等于 0.3),可使用 decimal.Decimal 处理精确计算
可变类型- list(列表):[1, 2, 3]
- dict(字典):{"name": "Bob", "age": 20}
- set(集合):{1, 2, 3}
- bytearray(字节数组)
字典的键必须是不可变类型(如字符串/数字/元组)

代码示例:

# 不可变类型:修改会报错
tup = (1, 2)
# tup[0] = 10  # 报错:TypeError

# 可变类型:可修改
lst = [1, 2]
lst[0] = 10  # 合法,lst变为 [10, 2]

# 字符串不可变
s = "hello"
# s[0] = 'H'  # 报错
s = "Hello"   # 重新赋值,新字符串对象
类型转换
维度核心内容注意事项
常用转换常用函数:int()/float()/str()/bool()/list()/tuple()/set()/dict()
转换规则:仅合法格式可转(如 "10" 可转 int,"abc" 不可)
进制转换:int("1010", 2) 二进制转十进制
1. 空字符串/0/None/空容器转 bool 为 False,非空/非0 为 True
2. 浮点转 int 会直接截断小数部分(不是四舍五入)
3. 字典转 list 得到键列表

代码示例:

# 合法转换
num1 = int("100")      # 100
num2 = float(5)        # 5.0
num3 = int("1a", 16)   # 26 (十六进制转十进制)

# 异常处理(避免转换报错)
try:
    num4 = int("abc")
except ValueError:
    print("输入不是合法数字")

# bool转换规则
print(bool(""))    # False
print(bool("abc")) # True
print(bool(0))     # False
print(bool(1))     # True
实操任务
  1. 定义三个变量:name(姓名)、age(年龄)、height(身高),使用合适的数据类型并打印它们的类型。
  2. 尝试将一个包含数字的字符串(如 "123")分别转换为整数、浮点数、布尔值,观察结果。
  3. 创建一个元组 t = (1, 2, 3),尝试修改元组中的元素,观察错误信息并理解不可变类型。
  4. 计算 0.1 + 0.2 并比较是否等于 0.3,若不等,思考如何解决。
进阶提示
  • Python 中所有数据都是对象,变量名是对象的引用。可以使用 id() 函数查看对象的内存地址,理解赋值操作的本质。
  • 了解 Python 的“小整数缓存”机制(-5 到 256 的整数被重用)。

1.2 运算符与流程控制

常用运算符
类别核心内容注意事项
算术运算符+ - * /(除法)//(整除)%(取余)**(幂)整除 // 是向下取整(对于负数需注意)
比较运算符== != > < >= <=比较返回布尔值
逻辑运算符and(与)or(或)not(非)支持短路运算
赋值运算符= += -= *= /= //= %= **=复合赋值
位运算符& ` ^ ~ << >>`用于整数二进制位操作
成员运算符in not in判断元素是否在容器中
身份运算符is is not判断两个对象是否为同一对象(内存地址)

代码示例:

# 算术运算
print(10 // 3)  # 3(整除,向下取整)
print(10 % 3)   # 1(取余)
print(2 ** 3)   # 8(幂运算)

# 逻辑运算
print(3>2 and 5<4)  # False
print(not True)     # False

# 赋值运算
a = 5
a += 3  # a = a + 3
print(a)  # 8

# 位运算
print(5 & 3)   # 1 (0101 & 0011 = 0001)
print(5 << 1)  # 10 (左移一位相当于乘以2)

# 成员运算
lst = [1,2,3]
print(2 in lst)  # True

# 身份运算
x = [1,2]
y = [1,2]
print(x is y)    # False (不同对象)
print(x == y)    # True (值相等)
条件判断
维度核心内容注意事项
if-elif-else语法:if-elif-else缩进(4个空格)是语法核心
支持多条件嵌套
Python 3.10+ 支持 match-case 模式匹配
match-case类似其他语言的switch,但功能更强需Python 3.10+

代码示例:

score = 85
if score >= 90:
    print("优秀")
elif 80 <= score < 90:
    print("良好")
else:
    print("继续努力")

# 嵌套条件
age = 18
if age >= 18:
    if age <= 25:
        print("青年")
    else:
        print("成年")

# match-case (Python 3.10+)
command = "start"
match command:
    case "start":
        print("开始")
    case "stop":
        print("停止")
    case _:
        print("未知命令")
循环结构
维度核心内容注意事项
for循环遍历可迭代对象(列表/字符串/range/字典等)
range(start, end, step):生成整数序列(左闭右开)
遍历字典时默认遍历键,需用.items()获取键值对
while循环条件为True时执行,需避免死循环注意更新循环变量
break/continuebreak(终止循环)、continue(跳过当前轮)可配合else子句
for-else循环正常结束(未被break中断)时执行else常用于搜索场景

代码示例:

# for循环:遍历1-5
for i in range(1, 6):
    print(i)

# while循环:累加1-100
sum_num = 0
i = 1
while i <= 100:
    sum_num += i
    i += 1
print(sum_num)  # 5050

# break/continue
for i in range(5):
    if i == 2:
        continue  # 跳过i=2
    if i == 4:
        break     # 终止循环
    print(i)      # 输出:0 1 3

# for-else
for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(n, '等于', x, '*', n//x)
            break
    else:
        # 循环中没有找到因数
        print(n, '是质数')
异常处理
维度核心内容注意事项
try-except语法:try-except[异常类型]-else-finally
作用:捕获报错,避免程序崩溃
可以捕获多个异常类型
可以使用 as e 获取异常对象
1. 可捕获多类异常(如 ValueError/TypeError
2. 避免滥用 except:(不指定异常类型)
3. 可以使用 except Exception as e 捕获大多数异常
raise手动抛出异常可自定义异常类

代码示例:

# 捕获除数为0异常
try:
    a = 10 / 0
except ZeroDivisionError as e:
    print(f"错误:{e}")  # 错误:division by zero
else:
    print("计算成功")  # 无异常时执行
finally:
    print("无论是否报错都执行")

# 捕获多个异常
try:
    num = int("abc")
except (ValueError, TypeError) as e:
    print("输入类型错误:", e)

# 手动抛出异常
def divide(a, b):
    if b == 0:
        raise ValueError("除数不能为0")
    return a / b
实操小任务
  1. 计算:(10 + 5) * 2 - 8 // 2,验证结果是否为26。
  2. 编写程序:输入一个数,判断是否为正数且是偶数。
  3. 输入一个年份,判断是否为闰年(能被4整除但不能被100整除,或者能被400整除)。
  4. 编写程序:用循环计算10的阶乘(10! = 1×2×…×10)。
  5. 打印九九乘法表。
  6. 使用 while 循环实现猜数字游戏(随机生成1-100,用户输入猜测,提示“猜大了/猜小了”,直到猜中)。
  7. 编写一个程序,接收用户输入的两个数字,进行除法运算,处理可能出现的除零错误和值错误(输入非数字)。
  8. 使用 while 循环实现:不断要求用户输入密码,直到输入正确密码(假设正确密码为 "python123")为止,并限制最多尝试3次。
进阶提示
  • 了解 Python 的短路运算:andor 会返回最后一个计算的值,而不仅仅是布尔值。例如 3 and 5 返回 5
  • 学习使用 enumerate 同时获取索引和值:for i, val in enumerate(lst):
  • 了解 pass 语句作为占位符。

1.3 大模型工作原理 - 基础篇

核心概念通俗解释关键注意点
Token(令牌)大模型处理文本的最小单位,不是单纯的“字/词”,而是「子词/字符」的组合。所有文本需先转为 Token 才能被模型处理。分词算法常见的有 BPE、WordPiece、SentencePiece 等。1. 不同语言和模型的分词规则不同,导致 Token 数量与文字数量无直接对应。
2. 模型的“最大 Token 限制”指的是输入+输出的总 Token 数,不是字数。
3. 中文一个汉字通常是一个 Token,但英文一个单词可能拆成多个 Token。
上下文窗口模型能“记住并参考”的「输入+输出」Token 总数上限(如 GPT-3.5 是 4096 Token,GPT-4 支持 128k)。上下文窗口决定了一次性能处理多长的内容。1. 窗口过小的问题:无法处理长文档、多轮对话记忆丢失。
2. 实际使用中需注意 Token 计数,可通过分词器估算 Token 数量。
大模型核心定位基于深度学习的“语言模型”,核心能力是「理解自然语言」+「生成自然语言」,而非“真正思考”。它通过预训练学习到统计规律,能根据上下文预测下一个 Token。1. 大模型的“知识”来自预训练数据,截止到训练截止时间(无实时学习能力)。
2. 模型可能产生“幻觉”(hallucination),生成看似合理但不符合事实的内容。
分词器(Tokenizer)将原始文本转换为 Token ID 序列的工具,同时也能将 ID 序列转回文本。分词器包含词表和合并规则。不同的模型使用不同的分词器,不能混用。例如 GPT 使用的 BPE 和 BERT 使用的 WordPiece 不同。

代码示例(使用 tiktoken 估算 Token 数):

import tiktoken

# 加载 GPT-4 的分词器
enc = tiktoken.encoding_for_model("gpt-4")

text = "Hello, world! 你好,世界!"
tokens = enc.encode(text)
print(f"Token 数量: {len(tokens)}")
print(f"Token IDs: {tokens}")
print(f"解码回文本: {enc.decode(tokens)}")
实操任务
  1. 使用在线 Token 计数器(如 OpenAI 的 Tokenizer 工具)或 Python 的 tiktoken 库,计算一段中文和英文文本的 Token 数量,对比字数与 Token 数的差异。
  2. 假设一个模型的上下文窗口为 4096 Token,你有一段 6000 Token 的文档需要总结,请设计一个处理方案(如分段、摘要、RAG)。
  3. 思考为什么大模型需要分词器?如果直接按字符处理会有什么问题?
进阶提示
  • 深入了解 BPE 算法的工作原理:如何从字符开始逐步合并高频对,构建子词词表。
  • 学习不同模型的分词器差异:如 LLaMA 使用 SentencePiece,GPT 使用 BPE,BERT 使用 WordPiece。
  • 了解“Token 经济”:API 按 Token 计费,如何优化提示词减少 Token 消耗。

第一周自测题(简易版)

1. Python 部分

  1. 写出代码:输入两个数,计算除法,若除数为0则提示“除数不能为0”。
  2. 用循环打印 10 以内的所有奇数(使用 for 和 while 两种方式)。
  3. 定义一个变量 s = "Python",尝试修改第一个字符为 'p',观察错误并解释原因。
  4. 编写程序,接收用户输入的一个整数,判断它是否是质数。

2. 大模型部分

  1. 简述 Token 对大模型的作用,为什么不能直接按字符处理?
  2. 上下文窗口大小为 2000 Token 的模型,处理 3000 字的中文文本会有什么问题?可以如何解决?
  3. 什么是“幻觉”?举例说明大模型可能产生的幻觉现象。

第二周:进阶应用与原理深挖

本周学习目标

  1. 掌握 Python 列表推导式、函数高级特性、面向对象编程基础
  2. 理解 Transformer 架构、自注意力机制的核心作用,以及位置编码的意义
  3. 能解释大模型“预训练+微调”流程和文本生成逻辑,了解常见生成策略
  4. 能够分析大模型的过拟合、欠拟合、幻觉等问题及其解决方法

模块1:Python 核心语法 - 进阶篇

2.1 列表推导式(高效处理列表)

基础用法
维度核心内容注意事项
列表推导式[表达式 for 变量 in 可迭代对象 if 条件]
替代“循环+判断”,代码更简洁
1. 避免过度嵌套(超过两层)影响可读性
2. 复杂逻辑建议用普通循环
3. 列表推导式生成新列表,内存占用较大;大数据集考虑生成器表达式
其他推导式字典推导式{key_expr: value_expr for item in iterable if condition}
集合推导式{expression for item in iterable if condition}
生成器表达式(expression for item in iterable if condition)
生成器表达式惰性计算,适合大数据流

代码示例:

# 过滤偶数并乘以2
lst = [1,2,3,4,5]
new_lst = [x*2 for x in lst if x%2==0]
print(new_lst)  # [4, 8]

# 生成1-10的平方列表
square_lst = [x**2 for x in range(1,11)]
print(square_lst)  # [1,4,...,100]

# 嵌套列表推导式:二维列表扁平化
matrix = [[1,2], [3,4]]
flat_lst = [x for row in matrix for x in row]
print(flat_lst)  # [1,2,3,4]

# 生成九九乘法表(二维)
multi = [f"{i}×{j}={i*j}" for i in range(1,10) for j in range(1,10) if i<=j]

# 带条件的复杂表达式:对奇数平方,偶数保留原值
mixed = [x**2 if x%2 else x for x in range(1,6)]
print(mixed)  # [1, 2, 9, 4, 25]

# 字典推导式
names = ['Alice', 'Bob', 'Charlie']
name_len = {name: len(name) for name in names}
print(name_len)  # {'Alice': 5, 'Bob': 3, 'Charlie': 7}

# 集合推导式
words = ['apple', 'banana', 'avocado']
first_letters = {word[0] for word in words}
print(first_letters)  # {'a', 'b'}

# 生成器表达式
gen = (x**2 for x in range(1000000))
print(next(gen))  # 0
print(next(gen))  # 1
实操任务
  1. 使用列表推导式生成 1 到 50 之间所有能被 3 整除的数的平方。
  2. 给定一个字符串列表 words = ['hello', 'world', 'python', 'ai'],使用列表推导式生成每个单词的大写形式,并过滤掉长度小于 5 的单词。
  3. 使用字典推导式,将列表 [1,2,3,4] 转换为字典,键为数字,值为数字的立方。
  4. 使用生成器表达式计算前 100 个自然数的平方和,并与列表推导式比较内存占用(可以使用 sys.getsizeof() 粗略比较)。
进阶提示
  • 了解“海象运算符” := 在列表推导式中的用法(Python 3.8+),可以在条件中重复使用计算结果。
  • 列表推导式的执行顺序:从外到内,先循环后条件。

2.2 函数(代码复用核心)

函数定义与调用
维度核心内容注意事项
定义def 函数名(参数): 函数体,return 返回值函数内定义的变量是“局部变量”,外部无法访问
文档字符串"""函数说明"""可通过 函数名.__doc__ 查看

代码示例:

# 定义求和函数
def add(a, b):
    """计算两数之和(函数文档字符串)"""
    return a + b

# 调用函数
result = add(5, 3)
print(result)  # 8

# 查看函数说明
print(add.__doc__)  # 计算两数之和(函数文档字符串)
参数规则
维度核心内容注意事项
默认参数def func(a, b=10): 默认参数需放在非默认参数后默认参数尽量不用可变类型(如列表)
关键字参数调用时指定参数名,顺序不限提高可读性
可变参数*args(可变位置参数,接收元组)
**kwargs(可变关键字参数,接收字典)
参数名可自定义,但习惯用 argskwargs
仅限关键字参数* 后面的参数必须用关键字传递Python 3 引入

代码示例:

# 默认参数
def say_hello(name, msg="你好"):
    print(f"{msg}{name}")

say_hello("张三")           # 你好,张三
say_hello("李四", msg="下午好")  # 下午好,李四

# 可变参数
def calc_sum(*args):
    return sum(args)

print(calc_sum(1,2,3))  # 6

# 可变关键字参数
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=25)  # name: Alice  age: 25

# 仅限关键字参数
def greet(name, *, greeting="Hello"):
    print(f"{greeting}, {name}")

greet("Bob", greeting="Hi")  # Hi, Bob
# greet("Bob", "Hi")  # 报错,greeting必须用关键字
作用域
维度核心内容注意事项
LEGB规则Local → Enclosing → Global → Built-in查找变量顺序
global声明全局变量尽量避免在函数内部修改全局变量
nonlocal声明外层变量(用于嵌套函数)修改外层非全局变量

代码示例:

x = 10  # 全局变量
def outer():
    y = 20  # outer 的局部变量
    def inner():
        nonlocal y  # 引用 outer 的 y
        y += 5
        global x    # 引用全局 x
        x += 1
        print(x, y)
    inner()
outer()  # 11 25
print(x)  # 11
匿名函数(lambda)
维度核心内容注意事项
lambdalambda 参数: 表达式只能包含一个表达式,不能包含语句或复杂逻辑

代码示例:

# 定义lambda
square = lambda x: x**2
print(square(5))  # 25

# 结合sorted按值排序字典
students = [{'name': 'Alice', 'score': 85}, {'name': 'Bob', 'score': 72}]
sorted_students = sorted(students, key=lambda s: s['score'])
print(sorted_students)  # [{'name': 'Bob', 'score': 72}, {'name': 'Alice', 'score': 85}]

# 结合map
nums = [1,2,3,4]
squared = list(map(lambda x: x**2, nums))
print(squared)  # [1,4,9,16]
递归函数
维度核心内容注意事项
递归函数调用自身,必须包含终止条件(基线条件)Python 默认递归深度限制约1000,可调整但不建议

代码示例:

# 阶乘递归
def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n-1)

print(factorial(5))  # 120

# 斐波那契数列
def fib(n):
    if n <= 1:
        return n
    else:
        return fib(n-1) + fib(n-2)
实操任务
  1. 编写一个函数 is_palindrome(s),判断字符串是否为回文(忽略大小写和空格)。
  2. 编写一个函数 calculate,接受任意数量的数值,返回它们的和、平均值、最大值、最小值(使用可变参数)。
  3. 实现一个装饰器(进阶),但可以先不用。尝试编写一个函数,使用默认参数时注意可变对象的陷阱(例如默认参数为列表),并演示问题。
  4. 使用 lambda 和 filter 过滤出列表中所有偶数,并与列表推导式比较。
进阶提示
  • 学习“装饰器”(decorator):用于在不修改函数代码的情况下增强函数功能(如计时、日志)。
  • 了解“偏函数”(functools.partial)固定部分参数。
  • 学习“生成器函数”(yield)实现惰性计算。

2.3 面向对象(类与对象)

类的定义与实例化
维度核心内容注意事项
类定义class 类名: 定义类类属性所有实例共享,实例属性每个实例独有
__init__构造方法,初始化实例属性不是构造函数,对象创建后自动调用
self代表实例本身,必须作为第一个参数通过 self 访问实例属性和方法

代码示例:

class Student:
    # 类属性(所有实例共享)
    school = "第一中学"
    
    # 构造方法:初始化实例属性
    def __init__(self, name, age, score):
        self.name = name  # 实例属性
        self.age = age
        self.score = score
    
    # 实例方法:计算平均分
    def get_avg_score(self):
        if not self.score:
            return 0.0
        return sum(self.score)/len(self.score)
    
    # 实例方法:获取信息
    def get_info(self):
        avg = self.get_avg_score()
        return f"姓名:{self.name},学校:{self.school},平均分:{avg}"

# 实例化对象
stu1 = Student("李四", 20, [75,88,92])
# 访问属性/调用方法
print(stu1.school)  # 第一中学
print(stu1.get_info())  # 姓名:李四,学校:第一中学,平均分:85.0
类的继承
维度核心内容注意事项
继承子类继承父类的属性和方法,可重写父类方法使用 super() 调用父类方法
多继承支持多继承,但应谨慎使用方法解析顺序(MRO)使用 类名.__mro__ 查看

代码示例:

# 子类:继承Student类
class CollegeStudent(Student):
    # 重写构造方法
    def __init__(self, name, age, score, major):
        # 调用父类构造方法
        super().__init__(name, age, score)
        self.major = major  # 新增属性
    
    # 重写方法
    def get_info(self):
        avg = self.get_avg_score()
        return f"姓名:{self.name},专业:{self.major},平均分:{avg}"
    
    # 新增方法
    def study(self):
        print(f"{self.name} 正在学习 {self.major}")

# 实例化子类
stu2 = CollegeStudent("王五", 22, [80,85], "计算机")
print(stu2.get_info())  # 姓名:王五,专业:计算机,平均分:82.5
stu2.study()  # 王五 正在学习 计算机
访问控制
维度核心内容注意事项
命名约定单下划线 _name:表示“受保护”
双下划线 __name:名称修饰(name mangling)
Python 没有严格的私有成员,靠自觉遵守

代码示例:

class Person:
    def __init__(self, name, age):
        self._name = name   # 受保护(约定)
        self.__age = age    # 私有(名称修饰)
    
    def get_age(self):
        return self.__age

p = Person("Tom", 25)
print(p._name)      # Tom (仍可访问,但不推荐)
# print(p.__age)    # 报错 AttributeError
print(p._Person__age)  # 25 (通过名称修饰后的名字可访问)
print(p.get_age())  # 25 (通过方法访问)
特殊方法(魔术方法)
维度核心内容注意事项
__str__面向用户的字符串表示,由 print()str() 调用若未定义,回退到 __repr__
__repr__面向开发者的表示,通常可用来重建对象交互式解释器默认调用
其他__len____add__ 等实现容器行为和运算符重载

代码示例:

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
    
    def __str__(self):
        # 面向用户的字符串表示
        return f"《{self.title}》 by {self.author}"
    
    def __repr__(self):
        # 面向开发者的表示,通常可用来重建对象
        return f"Book('{self.title}', '{self.author}')"
    
    def __len__(self):
        return len(self.title)

book = Book("Python编程", "张三")
print(str(book))   # 《Python编程》 by 张三
print(repr(book))  # Book('Python编程', '张三')
print(len(book))   # 9
类方法与静态方法
维度核心内容注意事项
@classmethod类方法,第一个参数为 cls,可访问类属性常用于工厂模式
@staticmethod静态方法,无特殊参数,相当于独立函数放在类命名空间内

代码示例:

class MathUtil:
    pi = 3.14159
    
    @classmethod
    def circle_area(cls, radius):
        return cls.pi * radius ** 2
    
    @staticmethod
    def add(x, y):
        return x + y

print(MathUtil.circle_area(5))  # 78.53975
print(MathUtil.add(3, 5))       # 8
实操任务
  1. 定义一个类 Book,包含属性:title(书名)、author(作者)、pages(页数),方法:get_book_info()(返回“书名:XXX,作者:XXX,页数:XXX”)。并实现 __str__ 方法,使得 print(book) 输出格式化的信息。
  2. 定义一个类 BankAccount,包含属性:owner(账户名)、balance(余额,默认为0),方法:deposit(amount) 存款,withdraw(amount) 取款(余额不足时提示),display_balance() 显示余额。
  3. 创建一个子类 SavingsAccount 继承 BankAccount,新增属性 interest_rate,方法 apply_interest() 将利息加入余额。
  4. 尝试使用 @classmethod 定义一个工厂方法,从字符串创建对象,例如 Book.from_string("Python编程,张三,200")
进阶提示
  • 学习“属性装饰器” @property,将方法变为属性访问,并可实现计算属性。
  • 了解“抽象基类”(abc模块)定义接口。
  • 研究“多态”和“鸭子类型”的概念。

模块2:大模型工作原理 - 进阶篇

2.1 核心架构:Transformer

flowchart LR
    A[输入文本] --> B[Tokenization(分词)]
    B --> C[Embedding(嵌入:Token转向量)]
    C --> D[位置编码 Positional Encoding]
    D --> E[编码器Encoder:自注意力+前馈网络]
    E --> F[解码器Decoder:自注意力+掩码+交叉注意力+前馈网络]
    F --> G[输出层:线性变换+Softmax]
    G --> H[预测下一个Token]
核心组件通俗解释核心作用
自注意力机制模型计算文本中“每个Token与其他Token的关联权重”,理解上下文逻辑。通过查询(Q)、键(K)、值(V)的矩阵运算,得到每个Token的加权表示。让模型关注到相关词语,例如“他”关联“小明”
多头注意力将自注意力机制并行多次(多个头),每个头关注不同的语义空间,最后拼接结果。提升模型表达能力,从多角度理解文本
位置编码由于Transformer没有循环结构,需要显式注入位置信息。常用正弦余弦函数或可学习的位置嵌入。让模型知道单词的顺序,例如“我爱你”和“你爱我”语义不同
前馈网络每个注意力层后接一个全连接前馈网络,对每个位置的表示进行非线性变换。进一步提取和转换特征
编码器处理输入文本,提取语义信息(理解“输入是什么”)。由多个相同的层堆叠。负责“读懂”用户的提示词
解码器基于编码器的语义信息,逐Token生成输出文本。包含掩码自注意力(防止看到未来Token)和交叉注意力(关注编码器输出)。负责“生成”符合上下文的回答
优势相比传统RNN/LSTM,Transformer支持“并行计算”,处理长文本更快,且能捕捉长距离依赖。是大模型的核心架构基础

代码示例(使用 Hugging Face 加载BERT模型查看架构):

from transformers import BertModel
model = BertModel.from_pretrained("bert-base-uncased")
print(model)
实操任务
  1. 阅读图解Transformer(如 Jay Alammar 的博客),尝试用手工计算一个简单的自注意力例子(2个Token,2维向量)。
  2. 使用 Hugging Face 的 transformers 库加载一个小型 Transformer 模型(如 BERT-tiny),观察其架构(打印模型结构)。
  3. 解释为什么 Transformer 需要位置编码?如果去掉会怎样?
进阶提示
  • 了解“残差连接”和“层归一化”在Transformer中的作用,防止梯度消失和加速训练。
  • 学习“因果掩码”(causal mask)在解码器中的使用,确保生成时不能看到未来Token。

2.2 大模型训练与生成流程

阶段核心内容通俗类比
预训练数据:海量通用文本(书籍、网页、文章)
目标:学习通用语言知识(语法、常识、逻辑)
任务:语言建模(预测下一个Token)或掩码语言建模
相当于“小学到高中的通识教育”
微调数据:小批量特定任务数据(如客服对话、翻译数据)
目标:适配具体任务(客服、代码生成、翻译等)
方式:全量微调或参数高效微调(LoRA等)
相当于“大学的专业课程”
文本生成流程1. 输入提示词 → Tokenization
2. Token → Embedding + 位置编码
3. 自注意力计算
4. 解码器预测“下一个Token”的概率分布
5. 根据生成策略选择下一个Token
6. 重复直到生成结束符
模型不是“写全文”,而是“猜下一个字”
生成策略贪婪搜索、随机采样、Top-k采样、Top-p采样、束搜索贪婪:最保险;采样:有创意;Top-p:动态平衡
温度参数在Softmax前将logits除以温度T:T小则分布尖锐(趋近贪婪),T大则分布平滑(增加随机性)低温使模型保守,高温使模型有创造性

代码示例(使用GPT-2进行文本生成):

from transformers import GPT2LMHeadModel, GPT2Tokenizer

model = GPT2LMHeadModel.from_pretrained("gpt2")
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")

input_text = "Once upon a time"
inputs = tokenizer(input_text, return_tensors="pt")

# 贪婪搜索
greedy_output = model.generate(**inputs, max_length=50)
print(tokenizer.decode(greedy_output[0]))

# 采样(温度=0.7)
sample_output = model.generate(**inputs, max_length=50, do_sample=True, temperature=0.7)
print(tokenizer.decode(sample_output[0]))

# Top-p采样
top_p_output = model.generate(**inputs, max_length=50, do_sample=True, top_p=0.9)
print(tokenizer.decode(top_p_output[0]))
实操任务
  1. 使用 Hugging Face 的 transformers 库加载一个GPT-2模型,尝试用不同的生成策略(贪婪、采样、top-k、top-p)生成文本,观察差异。
  2. 找一个微调的例子:例如使用 transformers 的 Trainer 对预训练模型进行情感分类微调(可使用IMDb数据集)。
  3. 解释为什么需要微调?如果直接使用预训练模型进行特定任务,效果可能不佳的原因是什么?
进阶提示
  • 了解“指令微调”(Instruction Tuning)和“RLHF”(基于人类反馈的强化学习)如何提升模型对话能力。
  • 研究“上下文学习”(In-Context Learning)与微调的区别。
  • 学习参数高效微调方法(LoRA、Prefix Tuning)的原理。

2.3 大模型常见问题与优化

问题定义解决思路
过拟合模型在训练数据上表现极好,但在未见过的测试数据上表现差(“死记硬背”)增加数据量、正则化(Dropout、权重衰减)、早停、降低模型复杂度
欠拟合模型在训练数据和测试数据上表现都差(“没学够”)增加训练轮数、提升模型复杂度、减少正则化、优化数据质量
幻觉模型生成“看似合理但不符合事实”的内容高质量数据、检索增强生成(RAG)、提示工程、RLHF惩罚幻觉
偏见与伦理模型学习到训练数据中的社会偏见,生成有害内容数据去偏、对抗训练、内容审核、AI伦理准则
长文本处理模型受限于上下文窗口,无法处理超长文档长窗口模型、RAG、摘要式处理、滑动窗口
推理速度慢大模型参数量大,生成速度慢模型量化、批处理、KV缓存、高效架构(MQA、GQA)、硬件加速
实操任务
  1. 假设你正在开发一个医疗问答系统,大模型有时会产生幻觉给出错误的医疗建议。请设计一个方案来减少幻觉(例如结合知识库、提示工程等)。
  2. 查找一个关于大模型偏见的案例,分析其产生原因,并提出缓解措施。
  3. 如果模型在特定任务上表现不佳(欠拟合),你会尝试哪些优化?
进阶提示
  • 了解“检索增强生成”(RAG)的架构和工作原理,以及如何用LangChain等框架实现。
  • 学习“指令微调”如何缓解幻觉(如让模型学会说“我不知道”)。
  • 探索“思维链”(Chain-of-Thought)提示如何提升复杂推理能力。

第二周自测题(简易版)

1. Python 部分

  1. 定义一个类 Book,包含属性:title(书名)、author(作者)、pages(页数),方法:get_book_info()(返回“书名:XXX,作者:XXX,页数:XXX”),并实现 __str__ 方法。
  2. 编写函数:接收一个列表,返回列表中所有元素的乘积(处理空列表返回1,遇到非数字元素抛出异常)。
  3. 使用列表推导式生成一个包含 1 到 20 之间所有奇数的平方的列表。
  4. 解释 *args**kwargs 的作用,并给出一个示例函数。

2. 大模型部分

  1. 简述 Transformer 中自注意力机制的作用,并解释为什么需要多头注意力。
  2. 大模型“预训练”和“微调”的核心区别是什么?微调为什么能提升特定任务效果?
  3. 为什么大模型生成文本是“逐Token”的,而非一次性生成?如果一次性生成会有什么问题?
  4. 列举至少两种减少大模型幻觉的方法,并简要说明原理。

总结

核心知识点回顾

Python 部分

  1. 基础层:掌握变量/数据类型、运算符、条件判断、循环、异常处理,是编写程序的基础;
  2. 进阶层:列表推导式提升列表处理效率,函数实现代码复用,面向对象是大型项目的核心编程范式;
  3. 关键原则:代码需兼顾“正确性”与“可读性”,异常处理避免程序崩溃;理解可变与不可变对象对编程的影响;掌握作用域规则,避免变量污染。

大模型部分

  1. 基础层:Token 是模型处理文本的最小单位,上下文窗口决定模型的“记忆容量”;分词器是连接文本和模型的桥梁。
  2. 核心架构:Transformer 是大模型的基础,自注意力机制解决了上下文关联问题,位置编码赋予模型顺序感知,多头注意力提升表达能力。
  3. 核心流程:大模型通过“预训练学通用知识+微调适配具体任务”,文本生成是“逐Token预测”的过程,生成策略(温度、Top-p等)影响输出多样性。
  4. 常见问题:过拟合、欠拟合、幻觉、偏见等需要针对性地优化,如数据清洗、正则化、检索增强等。

学习建议

  1. Python 学习:每学一个知识点,立即编写代码验证(如学完函数,写1-2个实用函数);多用调试工具(print、pdb)理解代码执行过程;阅读优秀代码,学习规范。
  2. 大模型学习:结合实际场景理解(如用 ChatGPT 时,观察它的回答是否受上下文长度影响,尝试不同生成参数);动手实践:使用 Hugging Face 库加载模型、进行推理和微调;关注前沿论文和博客,理解技术演进。
  3. 自测闭环:每周完成自测题,错题对应回顾知识点,确保“学一个会一个”。可创建错题本,记录易错点和解决方案。
  4. 项目驱动:尝试用所学知识完成一个小项目(如命令行工具、简单的对话机器人),加深理解和综合运用能力。