ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

TensorFlow入门第一周:从环境搭建到线性拟合的完整实践记录

TensorFlow入门第一周:从环境搭建到线性拟合的完整实践记录 看到“Tensflow学习第T1周打卡”这个标题我忍不住笑了一下——这不就是我一个月前在搜索引擎输入框里敲下的那个词吗当时信誓旦旦要开始学这个深度学习框架结果第一步就把框架名字拼错了。这个拼写错误后来成了一个标签提醒我自己入门这件事最重要的不是比谁跑得早而是比谁稳得住。这篇文章就是我的T1周打卡记录第一周我究竟做了什么、为什么这样做、踩了哪些坑、哪些东西如果你也要学可以提前避开。它不打算把深度学习讲得多深但足够让一个和我一样从零开始的人在搭完环境、跑通demo之后真正对TensorFlow建立起一个可继续往上盖的基座。如果你也处在“Tensflow”这个拼写错误的阶段这篇应该用得上。1. 第一周的路线取舍先啃概念还是先跑代码1.1 复制现成代码跑通之后我发现自己什么都没学会很多新手走的路子是这样的找一段MNIST手写数字识别的代码复制进Jupyter Notebook点击运行看着loss从2.3慢慢降到0.1准确率冲上99%然后截图发个动态配上一句“Aha我在学人工智能了”。我第一周也干过这件事。结果呢第二天我尝试改动其中一个小参数——把epochs从5改成10——程序崩了报错信息里有几十个英文单词我一个都不认识。那一刻我意识到跑通别人的代码不等于学会了。那种“代码能跑但报错看不懂”的状态比完全不会还难受。因为你连下一步往哪里走都不知道搜索引擎能帮你解决“具体报错”但解决不了“你根本不知道哪儿可能出错”的盲区。后来我换了个思路重新规划第一周的目标。我给自己定的标准不是“运行成功”而是“能向一个完全不懂的人讲清楚这个程序到底在干什么”。按这个标准MNIST上手就不合适了——它涉及卷积、池化、Dropout、交叉熵太多东西第一周根本没能力消化。我决定换一个更小的起点先让TensorFlow执行最简单的张量运算然后做一个线性拟合。1.2 最终敲定的学习顺序环境、概念、demo、复盘我的第一周最终被切成了四个小块环境准备装好Python、TensorFlow写一个import验证程序。概念学习搞懂张量、变量、形状、数据类型、自动求导这几件事。小demo用TensorFlow拟合一条直线目标是把训练循环里每行代码的作用讲出来。复盘与输出把踩坑记录整理成笔记同时规划第2周的方向。这个顺序看起来没什么稀奇但有一个容易被忽略的关键点我把“搞懂概念”放在了“跑demo”前面但又不是先啃大部头理论而是带着问题去看概念。比如我先问自己“训练到底在训练什么”再去查变量和梯度而不是从“深度学习简史”开始读。带着问题查资料效率比按目录读书高得多。这就像你想做一道番茄炒蛋与其先把《中华烹饪全书》读完不如直接问“这道菜先放油还是先放蛋”然后动手做。第一周的知识体量就那么大按需学习比系统学习更合适。1.3 给自己设了一个“理解检验”的硬指标这周我发现一个特别好用的自测方法每学完一个概念关掉所有教程用自己的话把它写出来或者讲一遍。如果卡壳了说明还没真懂。比如学完张量我写下的检验稿是“张量就是一个可以装任意维度数据的容器它有形状shape和类型dtype。标量是0维张量向量是1维矩阵是2维图像这种三通道数据可以看成3维张量。”写出来之后我对张量的理解就从“见过这个词”变成了“能解释这个词”。这种检验方法会有点费时间但它的价值在于把“听过”变成“会用”而后者才是后续学习真正吃力的地方。2. 环境搭建是这周最磨人的环节版本背后的逻辑2.1 先想清楚CPU版还是GPU版我装TensorFlow之前脑子里想的还是大学时代装软件那套逻辑去官网下载最新版点下一步下一步。结果一查发现事情没那么简单。TensorFlow在2.x版本之后已经把CPU版和GPU版合并成一个包了直接用pip install tensorflow装的就是CPU版本。如果你的机器有NVIDIA显卡且驱动、CUDA、cuDNN都装好了同一个包也能自动用GPU加速。那到底选CPU还是GPU我的建议是第一周如果只是为了跑通流程、理解概念CPU版本完全够用。线性拟合、MNIST这种小模型CPU上跑也就几十秒几分钟的事。我自己第一周就是纯CPU跑的没有任何问题。如果你后续要跑大模型、图像识别再考虑GPU和CUDA也不迟。很多人一上来就想把CUDA配好结果卡了两天还没见到TensorFlow长什么样。这其实是在用“装备焦虑”代替“学习动作”——显卡装好了代码没写一行这种进度等于零。2.2 Python与TensorFlow版本匹配的实践证明这一周我在版本匹配上花的时间最多。给你看一组我实测后觉得可以照抄的搭配截止我写这篇文章时的稳定组合用途推荐配置补充说明纯CPU入门Python 3.10 tensorflow 2.13兼容性相对稳妥资料也最多Windows下想用GPUPython 3.9 tensorflow 2.102.11之后Windows GPU不再原生支持需要转WSL2想完全跳过本地配置Docker镜像tensorflow/tensorflow:2.13.0-gpu官方镜像省去大量环境折腾这里面的坑在于TensorFlow的版本和Python版本并不是随意搭配的。我装的时候先装了Python 3.12然后直接pip install tensorflow结果报错“找不到匹配的wheel”。后来才明白TensorFlow的发布节奏跟不上Python新版本的推出速度。新版Python发布后往往要等几个月甚至更久TensorFlow才会跟上。最稳妥的方法是去PyPI上查tensorflow这个包支持的Python版本范围再决定装哪个Python而不是先装好最新版Python再回头找TensorFlow。我在踩过这个坑之后养成了一个习惯任何框架的安装第一步永远是先看它的官方文档或者PyPI页面而不是凭感觉选版本。2.3 安装后的“一分钟自检”装完之后不要急着写模型先跑下面这段代码确定基础环境没问题import tensorflow as tf print(tf.__version__) print(tf.config.list_physical_devices(GPU))如果你用的是CPU版第二行会输出一个空列表这很正常。到这一步没报错说明TensorFlow本体已经装好了。接着再跑一个最简单的张量运算a tf.constant([[1.0, 2.0], [3.0, 4.0]]) b tf.constant([[5.0, 6.0], [7.0, 8.0]]) print(a b)看到两行数字输出环境这关就算过了。我把这段自检代码存成了一个名为tf_env_check.py的文件后面每次换机器、换环境都会先跑一遍。确认环境没问题再继续而不是把时间浪费在“环境有问题但误以为是代码有问题”的排查上。这个习惯帮我省下了大量时间。因为TensorFlow的报错信息里环境类错误和代码类错误的特征很不一样先确认环境后面分析报错时能少走一半弯路。3. 三个绕不开的基础概念张量、动态计算图、自动求导3.1 张量把数据装进一个带形状和类型的容器里TensorFlow里的Tensor就是张量。听起来很玄其实你就把它理解成一个多维数组容器每个容器都有两个属性形状shape和数据类型dtype。比如tf.constant([[1, 2], [3, 4]])就是一个形状为(2, 2)、类型为int32的张量。第一周我在张量上花了不少时间做练习包括创建不同形状的张量、改变形状reshape、类型转换cast、张量之间的加减乘除。其中让我印象最深的一课是TensorFlow张量的形状规则非常严格很多新手报错都出在shape不匹配上。比如你在矩阵乘法里把两个(2, 3)的矩阵相乘会直接报错因为矩阵乘法的规则要求左矩阵的列数等于右矩阵的行数。这不是TensorFlow在为难你而是数学规则本身就是这样。学到这里我才恍然大悟以前线代课上学的那些东西不是没用是没用对地方。我建议新手在第一周至少亲手尝试这些张量操作创建tf.constant、tf.zeros、tf.ones、tf.random.normal变换tf.reshape、tf.transpose运算tf.matmul、tf.add、tf.reduce_mean类型tf.cast、tf.float32、tf.int64这些操作看起来像在“炒冷饭”但它们是后面所有模型代码的原料。原料熟了炒菜才不糊。3.2 动态计算图TF 2.x默认的即时执行模式如果你去翻早期的TensorFlow教程会看到“会话Session”和“占位符placeholder”这些东西那是TF 1.x时代的写法。TF 2.x做了很大改动默认使用动态图模式Eager Execution代码写出来是什么顺序执行就是什么顺序。再也不用先构建一个静态计算图再扔进session.run()里去跑。我用一个生活化的类比来理解动态图你在厨房做饭。静态图版本是先把整份菜谱写成一张流程图然后交给一个只会按图执行的机器人去做中途想改配方得先改流程图再重来。动态图版本是你自己站在锅前面先放油看到油热了再放葱下一步想怎么走完全由你决定甚至可以尝一口再决定加不加盐。对新手来说动态图的容错率高太多了。写一行跑一行出错了立刻能定位到是哪一行的问题。这也是为什么我一再强调看教程前先确认版本别把TF 1.x的旧教程往2.x上套。很多初学者在社区里贴出的报错十有八九是旧代码配新框架。3.3 自动求导GradientTape是理解训练循环的钥匙如果说张量是数据的容器模型是数据的加工流程那自动求导就是让模型“学习”的根本动力。在TF 2.x中最常用的求导工具是tf.GradientTape。它的逻辑很简单在with tf.GradientTape() as tape:这段代码块里做的运算tape都会记录下来最后用tape.gradient()就能算出目标对指定变量的梯度。第一周我反复琢磨了梯度gradient这个概念它告诉你的是“当前参数往哪个方向调整损失函数能下降得最快”。我把它想象成下山你站在山坡上想知道往哪个方向走一步能最快到达山脚梯度就是那个方向指示器。有了GradientTapeTensorFlow帮我们把“算导数”这件数学苦差事包办了我们要做的是决定“往这个方向走多少步”——也就是学习率learning rate。我第一次跑通训练循环后回过头再看GradientTape突然明白了训练的本质反复调整参数让损失函数的值不断下降。这个循环跟GradientTape的具体实现无关它是所有梯度下降类算法的共同骨架。第一周就把这个骨架刻进脑子里后面学CNN、RNN、Transformer你会发现训练循环长得一模一样。4. 第一个真正“懂”的demo用不到200行代码拟合一条直线4.1 造训练数据先准备好有标准答案的练习册第一周我给自己定的练习是拟合一条直线。这个任务足够小小到我可以用眼睛验证最终结果对不对。造数据的方式很简单——在一个已知的线性关系上叠加一点随机噪声import numpy as np import tensorflow as tf # 生成200个在[-2, 2]区间均匀分布的点 X tf.constant(np.linspace(-2, 2, 200), dtypetf.float32) # 真实关系是 y 2x 1叠加标准差为0.1的高斯噪声 y 2.0 * X 1.0 np.random.normal(0, 0.1, 200)这里用tf.constant构造X用NumPy生成随机噪声。数据本身很简单但“造数据”这一步对理解机器学习有很大的帮助你提前知道了标准答案后面看模型有没有学对心里就有底了。很多深度学习教程喜欢直接丢给你一个现成的数据集让你下载、导入、训练。但那对新手来说像是一个黑盒子——你不知道数据长什么样也不知道合理的结果应该是什么。自己造数据相当于把黑盒子打开了你不仅看到了里面的零件还亲手把它们装了一遍。4.2 定义可训练变量与损失函数接下来定义两个可训练变量w和b分别代表权重和偏置初始值都设为0.5w tf.Variable(0.5) b tf.Variable(0.5)这里有个很关键的区别为什么用tf.Variable而不用tf.constant因为Variable是“可变”的训练过程就是要不断修改它的值让模型逼近真实答案而constant一旦定义就不可变了。这个区别后面在做各种模型时都反复出现——凡是需要在训练中被更新的参数都要放进Variable里。然后定义损失函数也就是衡量模型预测值和真实值差距的尺子。第一周我用的是均方误差MSEdef compute_loss(X, y, w, b): y_pred w * X b loss tf.reduce_mean(tf.square(y_pred - y)) return loss对新手来说看这段代码比看任何公式都直观预测值和真实值之差先平方消除正负号的影响、放大较大误差再求平均得到一个代表“整体差距有多大”的数字。损失值越小说明当前模型越接近真实关系。4.3 训练循环里每一步发生了什么训练过程用代码写出来非常朴素重复“算损失、求梯度、更新参数”三步。其中“求梯度”用的就是前面提到的GradientTape“更新参数”用的是assign_sub等价于w w - learning_rate * gradientlearning_rate 0.1 for step in range(200): with tf.GradientTape() as tape: loss compute_loss(X, y, w, b) grads tape.gradient(loss, [w, b]) w.assign_sub(learning_rate * grads[0]) b.assign_sub(learning_rate * grads[1]) if step % 20 0: print(fstep {step}: loss{float(loss.numpy()):.4f}, w{float(w.numpy()):.3f}, b{float(b.numpy()):.3f})跑完200轮之后我得到的w逼近2.0b逼近1.1左右。和真实关系y2x1对比误差非常小。那一刻我确定了我是真的“看懂”了一个训练过程——数据进来预测比较差距算梯度更新参数重复。这个循环就是深度学习中“训练”这件事的本质。跑完这个demo之后我又做了一个小实验把学习率改成0.5看会发生什么。结果loss开始震荡w和b在正确值附近来回跳动就是不收敛。把学习率改成0.001收敛又变得特别慢200步之后还没接近真实值。这个实验让我对“学习率是训练中最重要的超参数之一”有了直观的体会比看书上写一百句“学习率过大容易震荡”都管用。4.4 一个很少被提到的细节numpy()方法的用途上面代码里我用了loss.numpy()这个细节worth单独说一句。在TF 2.x里张量对象可以调用.numpy()方法把Tensor转换成一个NumPy数组。这对于打印、观察中间结果非常方便。我用这个方法查看了训练过程中w和b的实时变化还画了一张简单的散点图看拟合直线怎么一点点逼近真实直线。这里我不放图了但建议你也做一遍这个操作每20步把当前拟合直线画出来你会看到一条直线在数据点之间缓慢旋转、平移、稳定下来。那个过程很解压也很涨信心。5. 踩坑记录这些错误一周内我至少各犯两次5.1 拼写与命名从“Tensflow”到模块导入错误先说那个最经典的Tensflow。我一开始搜资料、打标签全是“Tensflow”导致我一度以为网上说的“tensorflow”和我学的“Tensflow”是两个不同的框架。后来才发现就是少了一个“o”正确拼写是TensorFlow。这个错误看起来幼稚但它在真实世界里相当常见——搜索引擎、论坛提问、GitHub代码很多新手都在用错别名。我的建议是从现在开始所有代码、文件名、标签统一写TensorFlow养成肌肉记忆。类似的坑还有很多。比如有些旧教程写tf.placeholder、tf.Session在TF 2.x里直接报AttributeError。遇到这种报错不用怀疑自己的环境多半是教程版本太老。看教程第一件事不是看内容而是看作者给出的版本号这是我第一周养成的习惯。还有一个很低级但很容易犯的错误文件命名。我一开始把一个Python文件命名为tensorflow.py然后运行结果死活import不到tensorflow。原因很简单——Python在导入时找到了同目录下的tensorflow.py把它当成了你要导入的模块自然找不到真正的tensorflow。这个问题排查了我整整半小时解决办法不要把你的脚本命名为tensorflow.py或者tf.py。5.2 报错排查看懂第一行提示比搜全网更重要这一周我遇到的报错十有八九是shape mismatch形状不匹配。一开始我的处理方式是复制报错去搜索找到的答案五花八门浪费时间。后来我总结出一套自己的排查流程先读最后一行找到报错类型和位置比如InvalidArgumentError: Incompatible shapes。再看报错前面几行定位是哪一行的哪两个张量在运算时形状对不上。把涉及的两个shape打印出来手动检查运算的维度规则。如果还是不明白再去搜但搜索关键词只复制报错类型那一小段别把整段报错都不加处理地贴进去。这套流程听起来很基础但非常管用。因为搜索引擎能给你的答案前提是你问对了问题。如果你连报错类型都看不出来搜出来的结果大概率也是隔靴搔痒。还有一个心得TensorFlow的报错信息虽然又长又吓人但它的设计其实很友好。前半段是内部的调用栈后半段通常会有一两句人话告诉你问题在哪。别被前半段的代码栈劝退直接看最后两行很多时候答案已经写在那里了。5.3 学习节奏打卡不是发朋友圈是给自己交代“第T1周打卡”这种说法本身带着一股坚持的仪式感。第一周实行下来我最大的体会是打卡的格式不重要重要的是你每次打卡都留下了可追溯的产出。我的打卡模板很简单本周目标、完成情况、踩坑记录、下周计划。目标不设太多3到4项以内。人一天只有24小时如果给自己列十项任务失败概率很高失败两次之后打卡这件事就容易中断。与其追求“每天都有进展”不如追求“每周都有产出”。哪怕这一周只搞懂了一个概念也比列了十个任务一个都没做完强。还有一个非常实用的习惯每次踩坑解决后马上记一条“报错类型解决方式”到笔记里。第一周我记了大约10条内容包括安装版本组合、pip安装时的镜像源配置、shape报错案例等等。这些笔记在接下来的几个星期里反复救我于水火。别高估记忆力也别高估搜索引擎。自己的踩坑日志永远是最精准的参考资料——因为它是你用自己的话记录的问题和你自己的理解水平完全对齐。官方案例写得再好你也可能看不懂某个词但你自己写下的笔记每一个字都是当时的你能消化的。5.4 关于pip安装太慢的解决思路第一周装TensorFlow时我在国内默认PyPI源下速度慢到令人绝望。后来换了清华的镜像源速度提升明显。这个操作其实一行命令就能解决但我还是踩了一个小坑只改了一次就忘了保存到配置文件里换了个环境又慢回去了。正确做法是直接把镜像源写进全局配置让pip默认走镜像。具体命令在不同系统上略有不同一般格式是在用户目录写一个pip.ini或~/.pip/pip.conf文件把index-url指向镜像地址。这个属于环境配置的基础操作第一周花十分钟搞定后续所有pip安装都能受益。在运行环境方面还有一个小建议尽量别用系统自带的Python推荐单独安装一个干净的Python环境或者直接用conda创建虚拟环境。虚拟环境能避免不同项目之间的包版本互相干扰。我第一周就在系统Python里装了一堆包后来有个项目的依赖和我自己的代码冲突费了很大劲才理清。虚拟环境这件事越早养成习惯越好。最后再说一点这周最大的体会。我不否认未来还会遇到更难的问题但第一周让我最踏实的收获不是跑通了某个demo而是建立了一个“报错-定位-解决-记录”的闭环。TensorFlow也好深度学习也好本质上是一门需要大量动手的学问。光看不练假把式光练不记白练。一个非常实际的建议给自己准备一个专门的笔记本文件就叫“TF踩坑日志”。从现在开始每次遇到问题先自己尝试定位原因然后把解决过程记录下来。三周之后你再回头看这本日志它会是你最宝贵的复习资料。如果你也处在“Tensflow”这个拼写错误的阶段不用急按自己的节奏走。环境没装好就慢慢装概念不懂就多查几下demo跑不通就回到最小案例。第一周不贪多把这个闭环转起来你后面学到的东西才有一个地方能挂住。
返回列表