前言
欢迎来到“AI 自学路线”的第二阶段!
在经历了数学基础的“洗礼”后,你现在的状态可能是一个“懂原理但手无寸铁”的战略家。从今天开始,我们要打造你的武器。
很多同学会说:“Python 我早就会了,不就是写脚本吗?” 且慢。 做 Web 开发的 Python 和做 AI 的 Python,简直是两种语言。
- • Web 开发关注:逻辑判断、数据库交互、并发请求。
- • AI 开发关注:数据的形状(Shape)、维度的变换、并行的计算。
今天这第一篇,我们不谈复杂的库,先来把最基础的 “容器”(数据结构)和 “流水线”(编程范式)搞清楚。这是你未来看懂复杂模型源码的基石。
一、 数据结构:一场关于“效率”的战争
在 AI 的世界里,数据量通常是巨大的。百万级的图片、亿级的文本。如果我们选错了存储数据的容器,训练速度可能会慢上 100 倍。
1. 列表 (List):灵活的“散装货车”
Python 原生的 List 是我们最熟悉的工具。
# 一个典型的 Listmy_data = [1, "apple", 3.14, [1, 2]]
- • 当我们刚从硬盘读取图片或文本时,因为大小不一,通常先丢进 List 里。
- • 致命弱点:它像一辆装满不同货物的大巴车,CPU 无法对它进行批量加速。如果你用
for 循环遍历 List 做乘法,在 AI 领域这就叫“龟速”。
2. 字典 (Dict):模型的“配置单”
# 一个典型的 Dictmodel_config = { "learning_rate": 0.001, "batch_size": 32, "layers": [64, 128, 10]}
- • 特点:键值对映射,查找速度快(Hash Map)。
- • 你会在加载模型权重(
state_dict)、读取 JSON 格式的训练数据、配置超参数时疯狂使用字典。它是 AI 程序的“控制面板”。
3. 张量 (Tensor) 的前身:从 List 到 Array
这是 AI 最核心的概念。虽然我们还没讲 NumPy 和 PyTorch,但你必须先在脑海里建立 “张量思维”。
如果说 List 是散装货车,那么 张量(Tensor) 就是标准化的 集装箱。
- • 规则:里面的元素类型必须完全一致(通常是浮点数 float32)。
- • 形状 (Shape):必须是矩形阵列(维数固定)。
在 Python 原生语法中,我们可以用“嵌套列表”来模拟张量:
# 0维 (标量 Scalar): 一个数# 代表:Loss 值x = 5.0# 1维 (向量 Vector): 一行数# 代表:一段音频、一句话的特征x = [1.0, 2.0, 3.0]# 2维 (矩阵 Matrix): 表格# 代表:一张灰度图 (高x宽)、一个Excel表x = [[1.0, 2.0], [3.0, 4.0]]# 3维 (张量 Tensor): 立方体# 代表:一张彩色图 (高x宽x通道数RGB)# ...以此类推
AI 工程师的直觉养成: 普通程序员看到 [[...]] 想到的是“列表套列表”; AI 工程师看到 [[...]] 第一反应必须是:“这是个 2 维矩阵,Shape 是 (行数, 列数)。”
二、 函数式编程:打造无副作用的“流水线”
在处理海量数据时,写一堆 for i in range(len(data)) 既丑陋又慢。AI 代码追求的是简洁和并行。
1. 列表推导式 (List Comprehension)
这是 Python 对 AI 工程师最友好的语法糖。它能把数学公式直接翻译成代码。
场景:把所有数据归一化(平方处理)。
- • 普通写法 (累赘):
data = [1, 2, 3, 4]squared = []for x in data: squared.append(x ** 2)
- • AI 写法 (优雅):
data = [1, 2, 3, 4]squared = [x ** 2 for x in data] # 一行搞定
2. Lambda 与 Map
虽然 List 推导式很强,但在构建复杂的数据处理 Pipeline 时,map 和 lambda 依然由其地位。
场景:同时处理两组数据(比如图片路径和对应的标签)。
paths = ["img1.jpg", "img2.jpg"]labels = [0, 1]# 打包数据 (Zip 是个神器)dataset = list(zip(paths, labels))# 结果: [('img1.jpg', 0), ('img2.jpg', 1)]# 按条件过滤 (Filter)# 只要标签为 1 的数据positive_samples = list(filter(lambda x: x[1] == 1, dataset))
核心思想: 不要去修改原始变量(Side Effect),而是通过函数变换,生成新的数据流。这保证了在多线程数据读取(DataLoader)时不会出现线程安全问题。
三、 实战:手搓一个“数据预处理器”
为了检验这一篇的学习成果,我们不用任何第三方库,仅用 Python 原生语法,模拟一次 “词向量化” (Embedding) 的预处理过程。这是 NLP(自然语言处理)的第一步。
任务:将一句英文,转换成机器能看懂的“数字矩阵”。
# 1. 原始语料 (Raw Data)corpus = [ "I love AI", "Python is great"]# 2. 构建词表 (Dict的作用: 建立 单词 -> ID 的映射)# 这一步通常叫 Tokenizationvocab = { "I": 0, "love": 1, "AI": 2, "Python": 3, "is": 4, "great": 5}# 3. 文本转序列 (List推导式 + Dict查询)# 把单词变成数字 IDsequences = [ [vocab[word] for word in sentence.split()] for sentence in corpus]# 结果 sequences: [[0, 1, 2], [3, 4, 5]]# 4. 模拟 One-Hot 编码 (张量思维的雏形)# 假设我们要把每个数字变成一个向量# 0 -> [1, 0, 0, 0, 0, 0]# 1 -> [0, 1, 0, 0, 0, 0]def to_one_hot(seq, vocab_size): # 初始化一个全0矩阵 (模拟 Tensor) # Shape: (句子长度, 词表大小) matrix = [[0] * vocab_size for _ in range(len(seq))] # 填值 for i, word_id in enumerate(seq): matrix[i][word_id] = 1 return matrix# 处理第一句话one_hot_tensor = to_one_hot(sequences[0], len(vocab))print("原始句子:", corpus[0])print("数字序列:", sequences[0])print("One-Hot矩阵 (模拟张量):")for row in one_hot_tensor: print(row)# 原始句子: I love AI# 数字序列: [0, 1, 2]# One-Hot矩阵 (模拟张量):# [1, 0, 0, 0, 0, 0]# [0, 1, 0, 0, 0, 0]# [0, 0, 1, 0, 0, 0]
代码解读
- 3. 嵌套 List 用来模拟最终输入给模型的矩阵结构。
- 4. List 推导式 让我们在两行代码内完成了分词和 ID 转换。
四、 结语:容器已备,只欠“算力”
今天通过原生 Python,你已经窥探到了 AI 代码的冰山一角:
- • 我们的目标是构造出整齐划一的 Matrix (嵌套列表)。
但是,细心的你肯定发现了:“上面那个 One-Hot 编码用了双层循环,如果我有 100 万句话,岂不是要跑一整天?”
你说到了点子上。Python 原生列表虽好,但它太慢了。 下一篇,我们将引入 AI 界的“工业革命”工具 —— NumPy 和 Pandas。我们将把刚才那堆慢吞吞的循环,变成瞬间完成的矩阵魔法。
下一篇预告:《Python工具链(二):NumPy与Pandas —— 拒绝循环,像数学家一样操作矩阵》
📚 建议练习
- 1. 熟悉 Python 的列表推导式,尝试把所有包含
for 循环的代码都重写一遍。 - 2. 理解
zip、enumerate 这两个函数,它们在 AI 数据读取中无处不在。