1.1 人工智能、机器学习与深度学习的关系
我刚开始学深度学习时,总把人工智能、机器学习、深度学习这三个词混着用。后来画了三个同心圆才理清楚。人工智能是最大的圈,它想让机器像人一样思考、决策、行动。机器学习是人工智能里面的一个子集,它不靠人写死规则,而是让机器从数据里自己找规律。深度学习又是机器学习里的一个分支,它用多层神经网络去学那些复杂的模式。我常跟朋友说,你先把这张关系图刻在脑子里,后面选方向、看论文都会轻松很多。
朋友问我该从哪学起,我说先弄明白层级关系。拿自动驾驶举例,人工智能是总目标,机器学习负责识别路况、预测行人轨迹,深度学习处理摄像头图像和雷达点云。我做过一个猫狗分类的小项目,那就是深度学习在机器学习框架下的具体应用。从历史看,深度学习爆发靠三样东西:数据、算力、算法。2012年AlexNet在图像识别比赛上拿了冠军,从那以后大家才真正重视深度神经网络。
现在这三者经常被媒体混用,但你自己心里要清楚。理解层级关系能帮你判断一个任务该用传统机器学习还是深度学习。我见过有人拿深度学习做小表格数据预测,效果还不如线性回归。搞清楚概念边界,是入门的第一块垫脚石。
1.2 深度学习的典型应用与能力边界
深度学习能做的事确实很多。我亲手试过图像分类、语音转文字、文本情感分析。工业场景里,人脸识别、推荐系统、医学影像辅助诊断都有它的影子。我朋友在医疗公司做AI,他说模型看CT片可以帮医生标记可疑区域。另一个做自动驾驶的同学讲,他们的模型能识别车道线、车辆、行人。这些应用让我觉得深度学习像一把万能钥匙。
能力边界也很明显。它需要大量标注数据,算力要求高,模型像个黑箱。我训练过一个图像分类模型,在测试集上准确率95%,换到真实场景就翻车。光线一变、角度一歪,它就认不出来了。我朋友说医疗AI的误诊责任和可解释性是大问题,医生不敢完全信任一个说不清理由的模型。雨雪天气下,自动驾驶模型的性能也会下降。
从我个人经验看,小数据任务传统机器学习可能更合适。深度学习擅长感知类、高维数据,比如图像、语音、文本。我建议新手先了解它能做什么、不能做什么。你知道了边界,就不会拿着锤子找钉子。我常提醒自己,工具没有好坏,只有合不合适。
1.3 新手学习路线与前置知识:Python、数学基础与工具链
我的学习路线是Python先行。我花了两个月学基础语法、列表、字典、函数、类。接着用NumPy做矩阵运算,Pandas处理数据,Matplotlib画图。数学方面,线性代数重点看矩阵乘法、特征值,微积分看导数、链式法则,概率看条件概率、贝叶斯。这些不用学到数学系水平,够用就行。我一开始被数学公式吓住,后来发现边写代码边补数学,理解快得多。
工具链我推荐Jupyter Notebook、VS Code、PyTorch。我一开始用Anaconda管理环境,后来转用venv。朋友数学好但编程弱,他先补Python再补数学。另一个朋友编程强数学弱,他边做项目边补数学。两种路径都行,关键别停下。我见过有人线性代数只懂矩阵乘法,照样跑通了CNN。边学边补效率更高。
我常跟新手说,前置知识不是门槛,是台阶。你不需要先成为数学家再碰深度学习。Python基础两周就能上手,数学可以在项目里慢慢补。工具链不用一次学全,用到什么查什么。我现在的习惯是,遇到不会的数学概念,先看直观解释,再动手实现一遍。
1.4 常见学习误区与优质资源筛选
我踩过的误区:收藏了上百个视频,一个没看完。追求大而全的课程,结果卡在数学推导。跳过动手,只看理论。盲目追新,学了一半发现框架更新了。这些坑让我浪费了半年。我朋友更惨,他报了个高价班,老师念PPT,他听了三个月还在讲感知机。后来他退课自己啃文档,反而进步更快。
优质资源要筛选。吴恩达的机器学习课适合入门,李沐的《动手学深度学习》代码和理论结合,fast.ai重实践,PyTorch官方教程最权威。我建议选一个主线,别贪多。判断资源好坏,看它有没有项目、有没有社区、更新频率如何。我常去GitHub看star数,去知乎看评价。资源不在多,在精。一个课程反复看三遍,比十个课程看一遍强。
我现在的筛选标准很简单:能跑通代码、有讨论区、作者还在维护。我常提醒自己,收藏不等于学会。别做松鼠党,囤一堆资源不吃。你选一个,跟到底,做完项目再换下一个。
1.5 从理论到实践的阶段目标设定
我设定阶段目标的方法:先跑通MNIST手写数字识别,理解数据加载、模型定义、训练循环。再复现一个CIFAR-10分类,尝试调参。做一个小项目,比如猫狗分类或者情感分析。每个阶段两周左右。跑通MNIST那天我特别兴奋,虽然准确率只有92%,但我知道流程走通了。
从理论到实践,我建议先模仿再创新。我一开始照着教程敲代码,敲完改参数看效果。后来自己写数据管道,自己设计网络。朋友从理论入手,先推公式再写代码,他也成功了。路径不同,目标一致。我每周定一个小目标,比如这周搞懂反向传播,下周实现一个全连接网络。目标要具体、可衡量。
我常提醒自己,完成比完美重要。跑通一个烂模型,比空想一个好模型强。你可以在GitHub上开一个仓库,记录每天的学习进度。阶段目标别定太大,小步快跑,持续反馈。我见过有人三个月从零到能复现论文,靠的就是每天推进一小步。
2.1 神经网络基本结构:神经元、层与激活函数
我画过一张神经元示意图,输入信号乘上权重,加上偏置,再经过激活函数,得到一个输出。这个输出会传给下一层神经元。单看一个神经元,它像在做加权求和加非线性变换。我常跟朋友说,神经网络就是很多这样的神经元堆叠起来。层与层之间全连接,前一层的每个输出都连到后一层的每个输入。我第一次用代码实现全连接层时,发现就是矩阵乘法加偏置,再套激活函数。那时候我才明白,数学公式和代码一一对应,理解起来快很多。
激活函数是神经网络里我最喜欢聊的部分。没有它,多层网络等价于一层线性变换,学不到复杂模式。Sigmoid把输出压到0到1,Tanh压到-1到1,ReLU把负数变零、正数保留。我刚开始学的时候,朋友把激活函数比作开关,决定神经元要不要兴奋。我试过在隐藏层用Sigmoid,训练很慢,后来换ReLU,速度提升明显。ReLU计算简单,梯度不容易消失,成了我大多数项目的默认选择。
层数多了,网络容量变大,能拟合更复杂的函数。我做过一个实验,两层全连接网络在MNIST上准确率92%,加到五层后到了97%。层数不是越多越好,我见过有人堆到几十层,结果梯度消失,训练不动。我现在的习惯是,先从两三层开始,看效果再加深。神经元数量也类似,太少欠拟合,太多容易过拟合。我常提醒自己,结构是骨架,激活函数是灵魂,两者要搭配着调。
2.2 前向传播、损失函数与反向传播机制
前向传播是我理解神经网络的第一步。数据从输入层进入,经过每一层的加权求和与激活,最终到达输出层。我跑通MNIST那次,看着一张28x28的图片变成10个概率值,心里特别有成就感。前向传播就是推理过程,模型给出预测。我朋友做文本分类,前向传播把词向量序列变成情感标签。这个过程不需要更新参数,只是计算。我写代码时,前向传播通常几行就搞定,model(x) 一调用就出来了。
损失函数告诉我模型错得有多离谱。分类任务常用交叉熵,回归任务用均方误差。我训练猫狗分类时,交叉熵从2.3降到0.1,我知道模型在进步。损失函数是模型优化的方向标。我朋友说,选错损失函数,模型会往奇怪的方向学。我试过用均方误差做分类,收敛很慢,换成交叉熵后效果好很多。损失函数把预测和真实标签的差距变成一个标量,反向传播才有东西可算。
反向传播是深度学习的核心机制。它利用链式法则,从输出层往回算每个参数的梯度。我手动推导过一个两层网络的梯度,算到后面头都大了。后来用PyTorch的自动求导,一行 loss.backward() 就搞定。反向传播的本质是分配责任,每个权重为最终误差贡献了多少,就调整多少。我常跟学弟说,前向传播是考试,损失函数是分数,反向传播是复盘错题。我朋友做语音识别,反向传播让模型从错误中学习,慢慢逼近正确输出。
2.3 梯度下降与优化器:SGD、Momentum、Adam
梯度下降是我最早接触的优化方法。它沿着梯度的反方向更新参数,步长由学习率控制。我一开始用SGD,学习率设0.01,训练损失震荡得厉害。学习率太大,模型跳过最优解。学习率太小,收敛慢得让人着急。我试过0.001,训练稳定但需要更多轮次。SGD每次用一小批数据算梯度,随机性带来噪声,也带来跳出局部最优的可能。我朋友用SGD训练图像模型,调了三天学习率才找到合适值。
Momentum给梯度下降加了惯性。它累积历史梯度,让更新方向更稳定。我加动量后,训练震荡明显减小,收敛速度变快。动量像下山时推你一把,让你不会在半路卡住。我试过动量系数0.9,效果不错。Nesterov动量更聪明,先看一步再更新。我现在的项目里,SGD加动量是常见组合。朋友做序列预测,动量帮他跨过了平坦区域。
Adam结合了动量和自适应学习率。它为每个参数维护不同的学习率,适合稀疏数据和大多数任务。我第一次用Adam,默认学习率0.001,模型很快收敛,调参负担小。Adam像给每个参数配了私人教练,根据梯度大小自动调整步伐。我跑CIFAR-10时,Adam比SGD快很多。朋友做自然语言处理,Adam几乎是默认选择。我提醒自己,Adam方便,某些任务SGD加精细调参能取得更好泛化。优化器没有绝对好坏,看任务和数据。
2.4 过拟合、正则化、Dropout与批归一化
过拟合是我踩过最多的坑。训练集准确率99%,测试集只有70%,模型把训练数据背下来了。我画过损失曲线,训练损失一直降,验证损失先降后升。那个转折点就是过拟合的开始。我朋友做医学图像,过拟合导致模型在真实数据上误判。过拟合像学生只背答案不理解原理,换道题就不会做。我后来学会看验证集表现,早停法帮我在验证损失回升时停止训练。
正则化是抑制过拟合的手段。L2正则化给损失函数加上权重平方和,让权重不要太大。L1正则化让权重稀疏,可以做特征选择。我试过L2正则化,测试集准确率提升了三个点。Dropout在训练时随机丢弃一部分神经元,让网络不依赖特定路径。我加Dropout后,模型泛化能力变强。朋友说Dropout像团队轮流休息,避免某个人过度承担。我通常在全连接层用Dropout,比例0.5左右,卷积层用得少。
批归一化让每层输入分布稳定。它在小批量数据上计算均值和方差,做归一化,再缩放平移。我训练深层网络时,批归一化加速收敛,允许更大学习率。没有批归一化,深层网络很难训练。我朋友做生成模型,批归一化帮助很大。我试过在卷积层后加批归一化,训练稳定很多。批归一化也有正则化效果,有时可以替代Dropout。我现在的习惯是,深层网络先加批归一化,再看要不要Dropout。
2.5 张量、计算图与自动求导原理
张量是深度学习的数据容器。标量是0维张量,向量是1维,矩阵是2维,彩色图像是3维。我刚开始学的时候,把张量当成NumPy数组,只是多了GPU支持和自动求导。PyTorch的Tensor可以在GPU上运算,速度比CPU快几十倍。我处理图像数据时,张量形状通常是[batch, channel, height, width]。朋友做文本,张量形状是[batch, sequence, embedding]。理解张量维度,是调试模型的基本功。
计算图记录运算过程。每个节点是一个操作,边是数据流动。前向传播时,计算图动态构建。反向传播时,沿着计算图反向遍历,算梯度。我画过一个小型计算图,理解加法、乘法、激活函数如何连接。PyTorch是动态图,每次前向传播都重新构建。TensorFlow 1.x是静态图,先定义再运行。我朋友喜欢动态图,调试方便。动态图让代码像普通Python,我写起来顺手。
自动求导解放了双手。PyTorch的autograd记录所有操作,调用backward()自动算梯度。我不用手动推导链式法则,只需要定义前向传播。自动求导的核心是计算图和链式法则的结合。我试过关闭自动求导做推理,速度更快。朋友做研究,自动求导让他快速实验新结构。我提醒自己,自动求导方便,理解背后的链式法则仍然重要。遇到梯度爆炸或消失,知道原理才能调试。
2.6 卷积神经网络与循环神经网络初步认知
卷积神经网络是我进入计算机视觉的起点。它用卷积核在图像上滑动,提取局部特征。卷积核共享权重,参数比全连接网络少很多。我跑CIFAR-10时,卷积层加池化层,准确率比全连接网络高一大截。卷积神经网络擅长捕捉空间结构,边缘、纹理、形状逐层抽象。我朋友做人脸识别,卷积神经网络是骨干。我理解卷积时,把它想象成手电筒在图片上扫,每次看一小块。
循环神经网络处理序列数据。它有记忆,当前输出依赖当前输入和上一时刻的隐藏状态。我做过文本分类,把词向量序列喂给RNN,最后用隐藏状态分类。RNN的挑战是长序列梯度消失,难以捕捉长距离依赖。LSTM和GRU通过门控机制缓解这个问题。朋友做语音识别,用LSTM效果不错。我试过用RNN预测正弦波,简单序列可以,长序列就吃力。
卷积神经网络和循环神经网络是深度学习的两个重要方向。卷积网络处理网格结构数据,图像、视频、医学影像。循环网络处理序列数据,文本、语音、时间序列。我现在的学习路线是,先掌握全连接网络,再深入卷积网络,最后补循环网络。朋友从循环网络入门,做自然语言处理。路径不同,核心原理相通。我常跟新手说,理解这两种网络,后面学Transformer、注意力机制会轻松很多。
3.1 开发环境搭建:Python、CUDA、Jupyter与虚拟环境
我装第一套深度学习环境花了整整一个下午。Python版本选错,CUDA和显卡驱动对不上,pip装包各种冲突。后来我学乖了,每一步都查官方文档。Python我选3.9或3.10,太新太旧都容易出问题。Miniconda是我现在最推荐的工具,它帮我管理Python版本和虚拟环境。我朋友用Anaconda,GUI界面方便,但下载体积大,启动慢。我更喜欢Miniconda加命令行,轻量可控。创建虚拟环境时,我会明确指定Python版本,conda create -n dl python=3.10,这样以后不会污染系统环境。
CUDA是NVIDIA显卡的并行计算平台。我装CUDA之前会先跑nvidia-smi看驱动支持的CUDA版本。驱动版本决定我能装哪个CUDA。我踩过坑,CUDA装了12.1,PyTorch只支持11.8,结果用不了GPU。现在我直接去PyTorch官网找安装命令,它会告诉我对应的CUDA版本。我朋友用AMD显卡,走ROCm路线,配置更麻烦。没有GPU也能学深度学习,CPU跑小模型可以,跑大模型会等到怀疑人生。我建议新手先用Colab或Kaggle的免费GPU,省去环境折腾。
Jupyter Notebook是我做实验的首选。它把代码、输出、文字说明放在一个文件里,方便回看和分享。我习惯用Jupyter Lab,界面更现代,能同时开终端和文件浏览器。VSCode也能跑Notebook,调试功能强。我朋友喜欢PyCharm,工程管理方便,适合写大型项目。我现在的流程是,探索阶段用Jupyter,整理成脚本用VSCode。虚拟环境加Jupyter内核,python -m ipykernel install --user --name=dl,这样Jupyter里能选对环境。
3.2 数据准备:加载、清洗、增强与训练集验证集测试集划分
数据准备花的时间比我预想的多得多。我一开始以为深度学习就是搭模型调参,后来发现百分之七十的时间在搞数据。加载数据时,我用torchvision.datasets或tf.keras.datasets,内置数据集省事。自己的数据用ImageFolder或自定义Dataset类。我朋友做医疗影像,DICOM格式要额外库来读。加载后我会先看几张样本,确认标签和图像对得上。数据路径里中文和空格有时会报错,我尽量用英文下划线命名。
清洗数据是个细致活。我处理过带缺失值的表格数据,简单填充均值或中位数,复杂情况用模型预测。图像数据里,我遇到过损坏文件、重复图片、标签错误。我写脚本遍历数据集,检查每张图能否正常打开,尺寸是否一致。我朋友做文本分类,清洗包括去HTML标签、统一大小写、处理表情符号。数据不平衡时,我会做重采样或加权损失。我现在的习惯是,清洗完先统计类别分布,画个柱状图看看。
数据增强让模型看到更多变化。图像任务里,我常用随机裁剪、水平翻转、旋转、颜色抖动。torchvision.transforms和tf.keras.layers提供现成方法。我试过在CIFAR-10上加增强,测试准确率涨了五个点。增强只在训练时做,验证和测试用原始数据。我朋友做语音,加噪、变速、变调是常见增强。数据划分我按70/15/15或80/10/10,训练集训练,验证集调参,测试集最后评估。划分前我会打乱数据,确保每类分布均匀。时间序列数据不能随机划分,要按时间顺序切。
3.3 模型构建、训练、验证与测试完整流程
模型构建我从简单开始。全连接网络、小卷积网络,先跑通再复杂化。PyTorch里我继承nn.Module,在__init__定义层,在forward定义计算。TensorFlow用Keras的Sequential或Functional API,几行就能搭好。我朋友喜欢用预训练模型改最后一层,省时省力。我搭模型时会打印结构,print(model),确认参数量和层连接。输入输出维度要对上,我在这上面犯过很多错。图像分类输出维度等于类别数,文本分类也是。
训练循环是核心。我写训练循环的步骤:前向传播、算损失、清梯度、反向传播、更新参数。PyTorch里五步走,TensorFlow用model.fit更简洁。我习惯每个epoch后在验证集上评估,记录训练损失和验证损失。我朋友训练时用学习率调度器,在验证损失不降时降低学习率。我跑MNIST时,训练损失从2.3降到0.05,验证准确率到98%。训练轮数太多会过拟合,我一般设个早停,验证损失连续几轮不降就停。
测试是最后一步。我用测试集评估最终模型,只跑一次,不根据测试结果调参。测试准确率才是真实性能。我朋友做竞赛,测试集是提交后才知道结果。我跑CIFAR-10,测试准确率比验证低一两个点,正常。我现在的流程是,训练完保存模型权重,torch.save(model.state_dict(), 'model.pth'),测试时加载回来。我会记下每个实验的配置和结果,方便对比。模型评估不只看准确率,混淆矩阵、F1分数、AUC我根据任务选。
3.4 超参数调优与模型评估指标选择
超参数调优是个体力活。学习率、批大小、网络层数、每层神经元数、正则化系数,组合起来空间很大。我一开始手动调,改一个跑一次,效率低。后来我用网格搜索和随机搜索,写脚本自动跑。我朋友用贝叶斯优化,Optuna或Ray Tune,更聪明。学习率是最重要的超参数,我一般先调它。批大小影响训练稳定性和速度,显存够就用大一点。我跑CIFAR-10时,学习率0.001、批大小64是常用起点。
评估指标要选对。分类任务,准确率适合类别均衡,F1适合不平衡。我做过疾病检测,正样本很少,准确率虚高,F1和召回率更有意义。我朋友做目标检测,mAP是标准指标。回归任务用MSE、MAE、R²。我训练时监控多个指标,损失看收敛,准确率看效果。验证集指标用来调参,测试集指标用来报告。我提醒自己,指标是工具,理解业务需求才能选对。
调参有策略。我通常先粗调,学习率按数量级试,0.1、0.01、0.001。找到大致范围再细调。网络结构我从小往大加,先保证能训练,再提升容量。我朋友用早停和模型检查点,保存验证集最好的模型。我试过用学习率预热,前几个epoch慢慢升学习率,训练更稳。超参数之间有关联,学习率和批大小要一起调。我现在的习惯是,记录每次实验的超参数和结果,用表格对比。
3.5 入门项目实战:MNIST、CIFAR-10与文本分类
MNIST是我第一个实战项目。手写数字识别,6万张训练图,1万张测试图,28x28灰度。我搭了个三层全连接网络,训练几轮就到97%。后来加卷积层,到99%。MNIST简单,适合熟悉流程。我朋友用它学PyTorch和TensorFlow,对比两个框架的写法。我跑MNIST时,第一次看到损失下降、准确率上升,特别兴奋。这个数据集小,CPU也能跑,新手友好。
CIFAR-10比MNIST难。10类彩色图,32x32,飞机、汽车、鸟、猫等。我搭卷积网络,加批归一化和Dropout,训练到85%左右。我朋友用ResNet,到93%。CIFAR-10适合学卷积网络、数据增强、正则化。我跑的时候,发现过拟合很明显,训练准确率99%,测试才70%。加数据增强和Dropout后,差距缩小。这个数据集让我理解了卷积网络的优势,全连接网络在图像上效果差很多。
文本分类是另一个入门方向。我用IMDB影评数据集,正面负面二分类。流程是把文本转成词向量序列,喂给嵌入层加LSTM或一维卷积,最后全连接分类。我朋友用预训练词向量,效果更好。我跑文本分类时,学到序列长度、词汇表大小、填充截断的处理。Transformer现在很火,入门还是从RNN和CNN开始。我建议新手三个项目都跑一遍,图像和文本各体验一下,找到自己的兴趣方向。
3.6 调试技巧、常见报错与训练过程可视化
调试深度学习代码,我总结了几招。形状不匹配是最常见的错,我养成打印张量形状的习惯。print(x.shape) 放在关键位置。梯度为NaN,通常是学习率太大或损失函数数值不稳定。我把学习率调小,加梯度裁剪。显存不够,减小批大小或模型规模。我朋友用torch.cuda.empty_cache()清缓存。损失不降,检查数据标签对不对,学习率是否合适,模型有没有梯度。我试过忘写optimizer.zero_grad(),梯度累积,训练乱套。
常见报错我列几个。CUDA out of memory,显存超了,减小批大小。RuntimeError: size mismatch,形状不对,检查输入输出维度。Expected all tensors to be on the same device,数据和模型在不同设备,.to(device)统一。Loss is nan,学习率太大或数据有异常值。我朋友遇到CUDA error: device-side assert triggered,通常是标签越界。我现在的习惯是,报错先看最后一行,再往上找源头。搜索引擎和官方文档是好朋友。
可视化训练过程帮我看清模型状态。我画损失曲线和准确率曲线,横轴epoch,纵轴指标。训练损失和验证损失一起画,看是否过拟合。我朋友用TensorBoard,实时看曲线、权重分布、计算图。我试过用matplotlib手动画,简单直接。混淆矩阵让我看哪些类别容易混淆。我跑CIFAR-10时,猫和狗混淆最多。可视化不仅为了好看,是调试和决策的依据。我现在的每个项目都会加日志和曲线图。
3.7 实验记录、复现与版本管理基础
实验记录我以前不重视,后来吃了亏。跑了几十个实验,忘了哪个配置最好,只能重跑。现在我每次实验都记:日期、数据集、模型结构、超参数、训练轮数、结果。我用Markdown表格或Excel记录。我朋友用Weights & Biases或MLflow,自动记录超参数和指标。我试过用TensorBoard的日志,但不如表格直观。我现在的习惯是,实验记录里写清楚改动点,比如“加了Dropout 0.5,验证准确率涨了2%”。
复现是深度学习的痛点。随机种子、库版本、硬件差异都会影响结果。我固定随机种子,torch.manual_seed(42),np.random.seed(42)。库版本我写进requirements.txt,pip freeze > requirements.txt。我朋友用Docker,环境完全隔离,复现最可靠。我试过在不同机器上跑同一份代码,结果有微小差异,GPU型号和CUDA版本不同。我现在的习惯是,重要实验记录随机种子和库版本,代码提交到Git。
版本管理我推荐Git。代码、配置、笔记都放进去。我每个实验开一个分支,或者用commit记录改动。我朋友用DVC管理数据和模型权重,大文件不进Git。我试过把模型权重上传到网盘,链接记在笔记里。GitHub和GitLab都能托管代码,私有仓库免费额度够用。我现在的流程是,本地Git管理,定期push到远程。实验记录和代码一起版本化,回头看很清楚。复现别人的实验时,先看他们的代码和配置,再跑一遍对比结果。
4.1 框架生态与设计哲学:动态图、静态图与动态图融合
我最早接触的是TensorFlow 1.x,写代码像在画施工图。先定义计算图,所有节点和边搭好,再开Session喂数据。图没建完什么都跑不了,想打印个中间结果得用tf.Print,调试全靠猜。我朋友当时做图像分类,光调通一个卷积层就花了两天,报错信息只给个节点名字,不告诉你哪里出错。那会儿大家管这叫“TensorFlow式劝退”。
PyTorch出现后我的感受完全变了。代码一行行往下走,张量是什么值随时能看,断点打在哪儿都行。我写训练循环的时候,前向传播、算损失、反向传播、更新参数,跟写普通Python没区别。我朋友从TensorFlow 1.x转过来,第一周就说“回不去了”。动态图的灵活在调试和实验阶段太重要了,研究场景下没人想跟计算图搏斗。
TensorFlow 2.x改成了默认动态图,Keras做高层封装,手感和PyTorch接近了很多。我去年重新用TensorFlow 2.x写项目,tf.function可以把Python函数转成静态图加速,既保留了调试的方便,又能在部署时拿回性能。PyTorch这边有TorchScript,也是动态转静态的路子。两个框架都在往中间靠,动态图和静态图不再是非此即彼。
我现在的判断是,设计哲学的分野还在,只是没那么绝对了。PyTorch偏向“所见即所得”,TensorFlow偏向“先封装再优化”。我朋友在工业界做推荐系统,他更在意部署时的图优化和跨平台一致性。我做实验的时候更在意改一行代码立刻能看到结果。场景不同,偏好就不同。
4.2 安装方式、API风格与最小代码示例对比
装PyTorch我闭着眼睛都能操作。官网选好系统、CUDA版本,复制那条pip命令到终端,等几分钟就完事。我用conda建虚拟环境,conda create -n pt python=3.10,再pip装torch和torchvision。Windows上偶尔缺个VC运行库,装一次就永久解决。我朋友用Mac的MPS后端,PyTorch也支持,不用额外折腾。
TensorFlow的安装单看命令更简单,pip install tensorflow就完事,GPU支持从2.11开始进了同一个包。麻烦在版本对应关系。我装TensorFlow的时候得先查官网表格:2.10对CUDA 11.2,2.11对CUDA 11.2,2.12对CUDA 11.8。我有次装完跑不了GPU,查了半天发现是cuDNN版本差了个小版本号。我朋友现在只用Docker装TensorFlow,镜像拉下来环境就是对的。
写最小模型能看出API性格。PyTorch里我定义一个类继承nn.Module,在__init__里声明层,在forward里写计算,然后自己写训练循环。TensorFlow用Keras的Sequential,三行搭模型,model.compile指定优化器和损失,model.fit一行开始训练。我朋友教深度学习入门用Keras,学生半小时就能跑出结果。我自己做研究还是用PyTorch手写循环,想改哪里改哪里。
两种风格我都用。快速验证想法用Keras,省去模板代码的麻烦。需要自定义训练逻辑,比如梯度惩罚、多任务损失加权,我用PyTorch手写循环。我现在的习惯是,教学演示用Keras让学生先建立信心,深入研究用PyTorch掌握细节。框架的API风格没有优劣,只有场景匹配。
4.3 模型定义、训练循环、数据加载与GPU加速对比
模型定义上,PyTorch让我感觉像在写Python类,层是属性,计算逻辑是方法,还能在前向传播里加print或者条件分支。TensorFlow的Functional API适合搭复杂拓扑,多输入多输出、共享层、残差连接,用函数式的方式连起来很直观。我朋友做多模态模型,图像和文本两个输入分支,Keras的Functional API写起来比PyTorch清爽。PyTorch也能做,只是需要多定义几个forward参数。
训练循环的差异我体会最深。PyTorch里五步走:optimizer.zero_grad()、前向传播、算损失、loss.backward()、optimizer.step()。写得多了闭着眼都能打出来。好处是我想在循环里插什么就插什么,梯度裁剪、学习率预热、自定义指标,全在明面上。TensorFlow的model.fit把循环封装了,回调函数能插入行为,但想改底层逻辑得重写train_step。我跑标准任务用model.fit,跑研究性实验用PyTorch。
数据加载两个框架都有成熟工具。PyTorch的Dataset加DataLoader,多进程加载、打乱、批处理,用起来顺手。TensorFlow的tf.data管道式写法,map、batch、prefetch,性能优化做得很细。我处理大规模图像数据的时候,tf.data的prefetch和并行映射能明显提升吞吐。PyTorch的num_workers也有类似效果,Windows上多进程要加if __name__ == '__main__'保护。
GPU加速两个框架都成熟了。PyTorch用.to(device)搬模型和数据,torch.cuda提供显存查看和缓存清理。TensorFlow用tf.config配置显存增长,tf.device指定设备。我跑同样的ResNet,两个框架的GPU利用率差不多,速度差异常常来自数据管道。我朋友做过基准测试,有些算子在PyTorch上快,有些在TensorFlow上快,取决于版本和显卡型号。我现在的习惯是,GPU加速不是选框架的关键,生态和部署需求才是。
4.4 部署能力、生产化工具与移动端支持对比
部署这块TensorFlow积累深。TensorFlow Serving我在好几个工业项目里见过,模型版本管理、A/B测试、自动扩缩容,配套齐全。我朋友在电商公司做推荐,TensorFlow Serving扛过大促流量。TFX是端到端生产化平台,数据验证、模型训练、评估、部署全覆盖,概念多学起来陡,搭好之后省心。TFLite在移动端基本是标准方案,安卓和iOS都有成熟示例。
PyTorch部署追得很快。TorchServe是官方工具,模型打包、版本控制、监控指标都支持。我跑过TorchServe的demo,配置比TensorFlow Serving简单。ONNX是跨框架的模型交换格式,PyTorch和TensorFlow都能导出,ONNX Runtime做推理。我朋友做跨平台部署,ONNX是他的首选,一次导出多端运行。TorchScript能序列化模型脱离Python跑,C++调用也支持。
移动端TensorFlow有TFLite,我把图像分类模型转成TFLite放到安卓手机上跑过,速度可以接受。PyTorch的PyTorch Mobile支持的算子少一些,社区活跃度不如TFLite。我朋友做手机端人脸识别选了TFLite,文档和示例多。我现在的看法是,移动端优先TensorFlow Lite,PyTorch Mobile适合已经深度绑定PyTorch的团队。
浏览器端TensorFlow.js是独一份。我在浏览器里跑过姿态估计的demo,不需要后端。PyTorch模型可以转ONNX再转TensorFlow.js,转换链路长容易丢算子。我朋友做教育产品用TensorFlow.js在网页上演示推理,用户体验好。我选部署方案时会看目标平台,服务器端两个框架都行,移动端TensorFlow有优势,浏览器端TensorFlow.js基本是唯一选择。
4.5 社区活跃度、文档质量与学习曲线对比
学术界PyTorch的声量这几年明显更高。我读论文,大部分开源代码是PyTorch写的。NeurIPS、ICML这些顶会的论文实现,PyTorch占了大半。我朋友在高校做研究,组里清一色PyTorch。GitHub上PyTorch的star数超过了TensorFlow,issue响应也快。我提过几个PyTorch的issue,维护者回复挺及时。
工业界TensorFlow的社区依然庞大。我身边做生产的工程师用TensorFlow的比例不低。Stack Overflow上TensorFlow的问题数量多,历史积累深,搜报错信息往往能找到答案。TensorFlow官方文档结构清晰,教程从入门到进阶都有。我朋友初学的时候看TensorFlow官网教程,一步步跟着做,上手不难。PyTorch的文档也不错,有些高级功能说明不够细,需要看源码或社区讨论。
学习曲线我自己的体验是PyTorch对新手更友好。Python风格的代码,动态图调试,报错信息直观。我教别人入门深度学习一般推荐PyTorch起步。TensorFlow 2.x比1.x简单太多,但Keras封装了细节,出问题调试要绕一圈。我朋友从TensorFlow 1.x转2.x花了不少时间适应。我现在的建议是,先学PyTorch理解原理,再学TensorFlow了解工程化。
教程和课程两个框架都不缺。PyTorch官方有60分钟入门教程,Fast.ai的课程用PyTorch,Andrej Karpathy的神经网络课程也是PyTorch。TensorFlow官方有Coursera专项课程,DeepLearning.AI的TensorFlow开发者证书。我朋友看TensorFlow官方视频学,我更喜欢PyTorch的社区教程。学习资源不是选框架的障碍,两个都有足够多的优质材料。
4.6 选型建议:研究、教学、工业部署与个人项目
做研究我推荐PyTorch。学术界主流,论文复现代码多,动态图灵活,调试方便。我跑实验的时候,PyTorch让我快速试错,改模型结构、加自定义损失函数都很自然。我朋友做强化学习,PyTorch的动态图几乎是刚需,计算图随环境变化。研究场景下PyTorch的生态和社区支持更好。
教学我倾向PyTorch。代码直观,学生能看清每一步。我教入门课用PyTorch写训练循环,学生能理解前向传播、反向传播、梯度更新的全过程。TensorFlow的model.fit把训练循环藏起来,学生容易知其然不知其所以然。我朋友在培训机构教TensorFlow,先讲Keras高层API再拆底层。我现在的观点是,教学先用PyTorch打基础,再学TensorFlow的高层封装。
工业部署TensorFlow有优势。TensorFlow Serving、TFX、TFLite经过大规模生产验证,稳定性和性能有保障。我朋友在金融公司做风控模型,TensorFlow Serving上线三年没出过大问题。PyTorch的TorchServe也在进步,生产案例的积累不如TensorFlow。我选工业部署框架时会看团队技术栈,已经用TensorFlow的继续用,从零开始的可以两个都评估。
个人项目我选PyTorch。上手快,社区活跃,遇到问题容易找到答案。我自己的小项目、Kaggle比赛都用PyTorch。我朋友做个人项目用TensorFlow,因为工作中用熟了。个人项目没有标准答案,选自己顺手的。我建议新手两个都装,各跑一个MNIST感受一下再决定主用哪个。框架是工具,用熟了都能解决问题。
4.7 从PyTorch到TensorFlow的迁移学习要点
从PyTorch转TensorFlow,第一道坎是思维方式的切换。PyTorch里我习惯手动控制一切,训练循环、梯度清零、参数更新。TensorFlow 2.x的Keras把很多步骤封装了,我需要学会信任model.fit和回调函数。我朋友转的时候总想手动写训练循环,后来发现Keras的train_step可以自定义才找到平衡。迁移的时候先接受高层API,再逐步深入底层。
张量操作和API命名的差异需要适应。PyTorch的torch.nn对应TensorFlow的tf.keras.layers,torch.optim对应tf.keras.optimizers,torch.utils.data对应tf.data。我列过一张对照表贴在显示器旁边,写代码随时查。我朋友把PyTorch的模型定义一行行翻译成Keras,翻译完再对照检查。我现在的习惯是写一个小demo,同样的模型在两个框架里各实现一遍,对比差异。
数据管道是迁移的重点。PyTorch的Dataset和DataLoader直观,TensorFlow的tf.data管道式写法需要时间适应。我处理图像数据时用tf.data.Dataset.from_tensor_slices然后map做增强,batch和prefetch优化性能。我朋友做文本数据,tf.data的TextLineDataset和padded_batch帮他省了很多事。迁移的时候我把数据加载逻辑单独写,确保输入格式一致。
调试和错误处理的习惯要调整。PyTorch报错直接指向出错的行,TensorFlow的图执行模式有时报错信息不那么直观。我朋友用tf.debugging工具排查,我习惯在tf.function外面先跑eager模式确认逻辑。迁移过程中我会先用小数据跑通整个流程再上大数据。两个框架的模型权重可以互相转换,通过ONNX做桥梁,我试过把PyTorch模型转ONNX再导入TensorFlow,算子兼容性还行,复杂模型需要调整。迁移不是重写,是理解两个框架的差异找到对应写法。
5.1 计算机视觉、自然语言处理与语音方向概览
我刚学完基础之后最迷茫的就是选方向。那会儿我把深度学习当成一个整体,觉得学会卷积和循环网络就能包打天下。真到了做项目才发现,计算机视觉、自然语言处理、语音三个领域之间的差距,比我想象的大得多。我花了两三个月把三个方向各跑了一遍。
计算机视觉是我最先接触的,因为效果最直观。图像分类、目标检测、语义分割,改改网络结构就能看到结果。我搭第一个目标检测模型的时候,把一张街景图里的车和人框出来,那种成就感推着我往下走。视觉的入门门槛相对低,数据增强、预训练模型、开源代码都很成熟。我朋友做医学影像分割,用U-Net改一改就能出不错的结果。视觉方向对工程能力的要求偏重,数据处理、标注、增强、部署,流水线很长。
自然语言处理我入门时踩了不少坑。早期我用循环网络做文本分类,训练慢,长文本效果差。Transformer出来之后整个领域变了,我重新学注意力机制、位置编码、预训练微调。NLP的数据处理跟视觉完全两套思路,分词、词表、序列填充、注意力掩码,每一步都有细节。我朋友做对话系统,光数据清洗和构造就花了大半个月。NLP的评估也比视觉麻烦,BLEU、ROUGE这些指标看数字不如看一张图直观。
语音方向我接触得最晚。语音识别、语音合成、声纹识别,每个子方向的信号处理基础都不一样。我跑过一个语音识别的demo,从音频加载、梅尔频谱提取到声学模型训练,链条比我想的长。语音数据的时间对齐、采样率、噪声处理,全是坑。我朋友做语音合成,调音色和韵律调了几个月。三个方向里语音的入门资料最少,社区规模也小一些,但工业需求稳定。我现在的建议是,先都摸一遍,看哪个方向让你愿意花时间钻进去。
5.2 预训练模型、迁移学习与大模型基础
我早期训练模型从随机初始化开始,几百张图跑几十轮,准确率卡在七十几上不去。后来学会用预训练模型,在ImageNet上训好的权重拿过来微调,同样数据准确率上到九十几。那次之后我基本不再从零训模型。预训练加微调成了我的默认操作。我朋友做小样本分类,冻结主干网络只训分类头,几张图就能有可用结果。
迁移学习的核心是特征复用。卷积网络浅层学边缘和纹理,深层学语义,这些特征在不同任务间通用。我把图像分类的预训练模型迁移到目标检测,主干网络直接拿来用,只重设计检测头。NLP这边更明显,BERT预训练完,接个分类层微调就能做情感分析、意图识别。我现在的习惯是,拿到新任务先找有没有相近的预训练模型,有就微调,没有才考虑从头设计。
大模型这两年彻底改变了玩法。我第一次用GPT系列做文本生成,发现不微调也能完成不少任务。提示工程取代了一部分传统微调的工作。我朋友做代码补全,用大模型API加上少量示例就上线了。大模型的能力边界还在扩,我关注的几个方向是参数高效微调、提示优化、检索增强生成。传统深度学习工程师的技能树在变,从训模型慢慢转向用模型和调模型。
参数量从百万级跳到百亿级,我最大的感受是资源门槛。以前一张消费级显卡能跑实验,现在大模型推理都得算显存。我朋友用LoRA做参数高效微调,在单卡上微调七B模型,显存占用降了很多。我试过量化推理,把模型压到int8,速度上去了精度掉一点。大模型不是每个任务都需要,我现在的判断是,任务简单、数据少、延迟要求高,传统模型更合适。任务开放、数据多、能接受延迟,大模型值得试。
5.3 模型部署、MLOps与推理性能优化
模型在notebook里跑通和上线服务是两码事。我第一次部署模型,本地预测正常,放到服务器上QPS低得可怜。排查发现每次请求都重新加载模型,改成服务启动时加载一次,性能立刻上去。部署要考虑的东西比训练多。我朋友做在线推理,批量请求、异步处理、超时重试,每一项都要调。
推理性能优化我踩过的坑不少。模型剪枝去掉冗余权重,量化把浮点转成定点,蒸馏用小模型学大模型,这些方法我都试过。我做过一次图像分类的部署优化,原模型推理要两百毫秒,量化加TensorRT加速之后降到三十毫秒。我朋友做移动端部署,用NCNN和MNN这些推理框架,算子融合和内存复用做得细。优化之前先profile,找到瓶颈再动手,盲目优化常常白费功夫。
MLOps是把模型从实验推向生产的工程体系。数据版本管理、实验追踪、模型注册、持续训练、监控告警,一环扣一环。我早期用文件夹管理实验,模型文件命名混乱,过两周自己都分不清哪个是哪个。后来用MLflow记录参数和指标,用DVC管理数据版本,复现实验轻松很多。我朋友团队用Kubeflow搭流水线,从数据到部署自动化,人力省了一大截。
监控是上线之后的事,也是容易被忽视的部分。模型上线不是终点,数据分布会漂移,模型效果会衰减。我做过一个推荐模型,上线三个月后点击率下滑,查出来是用户行为变了,训练数据过时。我现在的做法是监控输入分布和预测分布,偏差超过阈值就触发重新训练。我朋友团队用Prometheus加Grafana做监控面板,模型指标和系统指标一起看。部署和运维是长期工作,不是一次性任务。
5.4 论文阅读、开源项目与竞赛实践方法
我读论文经历过三个阶段。刚开始逐字读,一篇读一周,读完啥也没记住。后来学会读摘要、引言、图表、结论,十分钟判断这篇值不值得细读。现在我先看有没有开源代码,有代码直接跑,跑通了再回头看论文细节。我朋友做研究,组会汇报论文,要求讲清楚问题、方法、实验、局限。读论文的目的是获取思路,不是背诵公式。
顶会论文我关注NeurIPS、ICML、ICLR、CVPR、ACL这几个。我每周花两三个小时刷arXiv,看标题和摘要筛选。有意思的存下来,周末细读一两篇。我朋友用Zotero管理文献,按主题打标签,写论文时找引用很方便。我现在的习惯是读完一篇写一段总结,用自己的话复述核心贡献和局限。不写总结的论文,过一个月基本忘光。
开源项目是最好的学习材料。我读PyTorch源码理解自动求导的实现,读Transformers库理解预训练模型的接口设计。我朋友通过给开源项目提PR,代码能力进步飞快。我建议从跑通项目开始,改配置文件、换数据集、加功能,逐步深入。遇到不懂的就提issue或看讨论区,维护者的回复往往比文档更清楚。参与开源不一定要贡献代码,提bug、改文档、翻译都是贡献。
竞赛是检验能力的实战场。我打过Kaggle的图像分类比赛,前期特征工程和数据处理花的时间比调模型多。比赛里最有效的方案常常是融合多个模型,单模型再强也有限。我朋友打比赛组队,一个人做数据,一个人做模型,一个人做融合。竞赛的经验和工业项目不完全一样,比赛可以堆算力和做集成,工业场景要考虑延迟和成本。我现在的看法是,竞赛适合练手和学技巧,别把比赛排名当成能力的全部。
5.5 学习计划制定、项目作品集与职业发展路径
我给自己定学习计划吃过亏。一开始定得太满,每天学四小时,坚持两周就崩了。后来改成每周定三个小目标,完成就打勾,节奏稳了很多。我朋友用番茄钟,学二十五分钟休息五分钟,一天下来有效学习时间不比我少。学习计划要留缓冲,生活里总有意外。我现在的做法是,每周复盘一次,没完成的顺延,不苛责自己。
项目作品集比证书管用。我面试的时候,面试官更关心我做过什么项目,遇到什么问题,怎么解决的。我把自己做的几个项目整理到GitHub,写清楚背景、方法、结果、代码结构。我朋友做数据科学,作品集里放了两个端到端的项目,从数据采集到模型部署,面试时聊得很深。作品集不在多,在完整,能讲清楚一个项目的来龙去脉比堆十个半成品强。
职业路径我观察下来有几条。算法工程师做模型研发和优化,工程能力要求高。数据科学家偏分析和实验设计,业务理解要强。机器学习工程师介于两者之间,工程和算法都要懂。我朋友从算法转产品,对技术理解帮他在产品设计上有优势。我现在的判断是,前几年先做深一个方向,有了深度再扩展广度。浅尝辄止的简历在市场上竞争力有限。
持续学习是这个行业的常态。我工作之后发现,学校学的知识两年就过时一半。我保持每周读论文、每月跑新模型、每季度学一个新工具的习惯。我朋友每年定一个学习主题,去年是MLOps,今年是大模型微调。学习不一定要有大块时间,通勤听播客、午休看技术博客都是积累。我现在的状态是,把学习当成工作的一部分,不是额外负担。
5.6 深度学习伦理、安全与可持续学习建议
模型偏见是我做项目时真实遇到的问题。我训过一个招聘筛选模型,发现对某些群体的推荐率明显偏低,查出来是训练数据本身就有历史偏见。修复偏见比想象中难,重采样、对抗训练、后处理都只能缓解。我朋友做医疗影像,不同肤色人群的模型表现有差异。我现在的做法是,训练前检查数据分布,训练后分群体评估。公平性不是一个指标能衡量的,需要持续关注。
安全性在部署之后变得具体。对抗样本能让图像分类模型把熊猫认成长臂猿,我试过生成对抗样本,人眼看着没变化的图,模型完全判错。我朋友做自动驾驶感知,对抗攻击是真实威胁。模型提取、数据投毒、后门攻击,这些安全问题是深度学习的阴暗面。我关注的方向是鲁棒训练和输入检测。安全不是加个模块就能解决的,要贯穿数据、训练、部署全流程。
隐私和合规我近两年才开始重视。模型可能记住训练数据里的敏感信息,生成模型可能复现训练样本。我处理用户数据的时候会做脱敏,训练用差分隐私加噪声。我朋友做金融风控,数据合规要求严格,联邦学习成了选项。法规在收紧,欧盟的AI法案、国内的算法推荐管理规定,做产品要了解。技术能力再强,不合规的产品也上不了线。
可持续学习我最大的体会是别把自己烧干。深度学习这个领域节奏快,新模型新论文天天有。我经历过一段焦虑期,觉得不学就跟不上,熬夜看论文反而效率更低。我朋友选择深耕一个方向,其他方向只了解大概。我现在的策略是,核心方向深入,相关方向扩展,无关方向忽略。学习是长跑,保持节奏比冲刺重要。身体和心态是持续学习的本钱,我每周留一天完全不碰技术,陪家人或者出门走走。技术会变,学习能力和健康是长期资产。
评论
发表评论