ShowMeAI-人工智能工具笔记-一-
ShowMeAI 人工智能工具笔记(一)
[双语字幕+资料下载] Jupyter Notebook 超棒教程!50分钟,把安装、常用功能、隐藏功能和Terminal讲解得清清楚楚。学完新手也能玩转! - P6:6)内核和变量 - ShowMeAI - BV1yv411379J
好的。那么让我们创建另一个部分。我们来谈谈重启内核和变量。所以这将涉及到我之前提到的。关于分配变量。然后可以访问它们,直到你明确删除。删除变量或重启笔记本。让我们看看我们现在的D。
我们的变量目录以及我们可以访问的所有内容。所以x和y仍然被定义。如果我执行打印y。这仍然存在。因为我们没有使用DEL方法删除它。删除y,所以我们还没有使用那个删除它,也没有重启笔记本。所以我将很快向你展示这两种方法。首先,让我们去掉y。
所以这并不返回任何东西。它只是删除变量。让我们回到这里,再次运行D。你会看到y不再存在于我们的变量中。所以如果我们执行打印y。哦,y未定义。它曾被定义。然后我们删除了它。这就是发生的事情。所以让我们再定义y。Y等于再见,世界。
打印Y。看起来不错。我已经使用X键删除了另一个单元。我将继续使用X在这里删除。如果我们执行D,你会注意到y现在又回来了,Y也回来了。所以我可以退出这个笔记本。哦,是的。实际上,我们确实需要保存我们的更改。谢谢。小弹窗。
所以我要保存我们的更改,命令S,或者你可以在这里文件,保存和检查点。让我们关闭我们的笔记本。你会注意到我们在Jupyter教程文件夹中列出的笔记本旁边有一个小绿色书本。
现在,这意味着它正在运行。这里说正在运行,非常有帮助。如果我们点击运行标签,你会看到这个笔记本正在运行。刚刚连续说了很多次正在运行。好吧,如果我们回到文件。这意味着我们的Python仍然在后台运行。
它仍在跟踪我们所有的变量,一切仍然存储在内存中。所以如果我再次点击这个笔记本并重新打开它。然后我下来这里。到Dr。注意这个数字14,这是在我们保存之前执行的第14个单元。让我们再运行一次。现在是第15个单元。我们仍然可以访问X和Y。
所以我不会再次运行这个赋值单元。我不会运行我们赋值Y的单元。我将打印y。它仍然打印。Y仍然在这里。仅仅关闭标签并不会关闭笔记本。笔记本不会关闭。直到你明确关闭它,你可以点击旁边,然后在我们的主标签中点击关闭。
你也可以做文件,关闭和停止。或者你可以回到终端,直接关闭整个Jupyter笔记本。在这里运行的服务。你可以关闭整个东西,这样就会关闭你所有的笔记本。
所以笔记本会继续运行。直到你告诉它停止。另一种重置这个笔记本的方法是去内核。让我们去内核选项卡。你会看到可以对 Python 内核做不同的操作。所以我将点击。重启,我现在要重启内核。
这和关闭笔记本再重新打开是一样的效果。所以我们所有的变量都会消失。为什么不再在内存中。如果我们想让 Y 等于“你好,世界”。我们需要再次运行这个单元。而且,X 也将不再在内存中。所以这就像重启你的电脑。这是重启笔记本,你会失去一些内容。
你会失去这里内存中的变量。那么我们开始吧。让我们保存它。
让我们去内核,重启。
让我们重启这个内核。好的,这里闪烁成蓝色。内核准备好了。现在让我们运行 D,看看这个数字会发生什么。砰,回到一。这告诉我们。这是一个新版本的 Python。在这里,你会注意到 X 和 Y 现在都消失了,因为这就像关闭 Python 一样。
然后再重新打开它。所以如果我下去打印 Y。我们会得到“名称 Y 未定义”,因为我们正在处理一个新的 Python 内核,而我们还没有定义它。因此,对于 Jupyter 笔记本来说,这一点非常重要。这就是为什么,如果可以的话。尽量运行你的单元。我将要重启。
这里再重启一次。尽量从头到尾写并运行你的单元,这样在运行时一切都能理解。一次一个单元,从单元到单元再到单元。因为。如果你在这里分配了变量 Y。然后在分配之前在这里打印它。这在技术上是可行的。如果你已经运行了这个单元,然后再回到这里运行这个单元。
这就是为什么如果不小心,Jupiter Notes 可能会变得相当混乱的原因。如果你不小心的话。那么如果你重启这个。这本笔记本现在无法按这种时间顺序逻辑运行。因为一旦到达这个单元,我们就试图在分配之前打印它。
通常情况下,你希望你的笔记本在一个良好的逻辑顺序中流畅地进行,从头到尾。如果你保持这种顺序,那将使你成为一个 Jupyter 笔记本的高手,因为我认为很多人。很多人都忘记了这一点。所以你可能已经学到了比很多使用 Jupyter 笔记本的人更多的知识。因为你现在已经了解了内核以及它与存储变量的关系。
[双语字幕+资料下载]“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P15:L15- 自定义模型与拟合 - ShowMeAI - BV1em4y1U7ib
好了,伙计们发生了什么。 欢迎回来看另一个视频在这个视频中。 我们将探索如何构建更灵活的训练循环。 到目前为止,我们一直在使用模型适合,如果您可以使用模型适合那是很棒的。 但有时候你需要更多的灵活性。 所以在这个视频中我们将看看如何自定义模型适合。
然后在下一个视频中,我们将看看如何从头开始构建自定义训练循环。
好的,首先,这里只是一些基本的导入,你们以前都见过这些。 然后我们只需加载Ms数据集。 所以我们不会做任何复杂的事情。 我只是想向你展示一般结构,然后可以应用于许多不同的问题。 好吧,我们要xtrain y train,x 测试,y 测试,我们只是要M加载数据。
然后我们要做 xtrain 是 xtrain 点重塑然后我们只会有。 我猜所有的例子减去1,然后28281,我们在这里做重塑只是为了添加这个频道。 然后作为类型转换为流32,然后通过除以255来规范化。 所以让我们复制这个,让我们换一行。 干 X 测试。 测试,并且。 让我们创建我们的模型。
首先,所以模型等于ks顺序。 然后我们要做的层输入。 然后输入的形状是28,281。 层来到64,3内核大小,我填充相同,所以我只是快速地通过这个。 这实际上不是视频的最重要部分。 😔,所以现在我们有了一个模型。
我们要创建一个类,我们要称它为自定义适合。 然后我们要从Kaosta模型继承。 然后我们要做的第一件事是我们要创建一个init函数,我们要发送到这里的所有东西都是模型。 所以我们要首先调用超级来继承Kaosta模型。 所以我们要做的是自己然后在这里。 然后我们要做的是将模型设置为模型。
然后我们要做的是定义一个训练步骤,这将在模型点拟合中使用。 所以我们的目标基本上是。 我们想做像训练一样的自定义,等待自定义。 那模型的什么自定义适合。 我们要送进那个模型。 然后我们将做训练点适合,我们将送入 x 训练,Y 训练。
然后批量大小和vpos数量通常是这样的。尽管这个适配将以自定义方式进行,我们将定义我们想要如何执行。因此,我的意思是,有很多用例需要自定义训练循环,尽可能使用模型Efi,当不能时尝试自定义你的模型,这就是我们在这个视频中所做的。为了获得最大的灵活性,你从头开始训练循环,但实际上需要这样做的一个例子是生成对抗网络。我并不假设你熟悉这个,只是说有很多这样的例子。
这很有用。好的,那么我们进行一次训练步骤。我们将发送数据,然后我们将得到一个x和y的元组。所以我们只需让x和y等于数据。接着我们将使用TF梯度记录作为记录。
我们这样做的原因是因为现在我们将进行前向传播和损失函数。当我们在那个上下文中进行操作时,它将记录所有执行的操作,这将有助于计算反向传播的梯度。
基本上,我们要做的y预测是一个自我点模型。我们将发送x。我们会指定训练为真,然后对于这个损失函数,我们将做损失等于自我编译的损失。然后我们将发送y和y预测。
这将在编译中完成。所以在这里,我们将进行训练编译,我们将发送。在这里我们将发送优化器为Kara的Oprs,Adamom。然后我们将发送损失为Kara的损失,稀疏的分类交叉熵。逻辑等于真。然后我们还将做指标为准确性。
所以这是我们第一次进行编译的情况。我还将向你展示如何进行自定义编译。但让我们逐步进行。因此我们现在将继续在这个编译下进行训练步骤。自我编译的损失使用这个稀疏分类交叉熵来自训练编译。
在那之后,我们基本上想要获得梯度,对吧,我们现在完成了前向传播。这部分是前向传播,我们在这个记录下进行所有操作。然后我们将训练变量设置为自我可训练变量,这些变量都存储在这个父类中。这辆车的模型,因此我们不必担心这个,然后我们想要获得梯度。
我们将执行带有梯度的记录。然后我们将做损失和训练变量,对吧。所以我们正在获得相对于训练变量的损失梯度,这正是我们想要改变的。接着我们将进行一步,优化器步骤,一个梯度下降步骤,我们将执行自我优化器的应用。梯度。
然后在这里我们将执行zip梯度和训练变量。接下来我们将自我编译的度量更新状态Y和Y预测。这将用于准确率。最后,我们将返回M.name。你会看到它的含义,M.name M.result对于自我度量。
所以我们获取MD.name,这将是损失,比如说。然后我们获取结果,即当前损失,然后我们为所有度量执行这一步,这将是损失和准确率。在这种情况下。我想这就是第一步的全部内容。我们现在应该能够运行这个。如你所见,它似乎有效。
是的,所以基本上。接下来的步骤是我们想要进行自己的编译。所以我们要在这里定义编译。我们将传入优化器和损失。然后我们将执行自定义的编译。所以,是的。
然后我们将自我优化器等于优化器,自我损失等于损失。然后我们只需做基本上相同的事情,训练.tcomp。除了我们不在这里传入度量,所以我们只使用优化器和损失。
现在基本上就是这样,我们只需将这个地方改为编译后的损失。我们将使用存储在这里的自我损失。所以自我损失,然后让我们看看,是的,我们仍然可以使用自我优化器,然后让我们重新运行它。现在,如你所见,我们没有得到准确率。
所以我们需要自己跟踪这个度量。我们可以,比如说,在这里创建。我们可以做。准确率度量是。Ca us那个矩阵spae类别准确率。我们就叫它名字。's看名字等于。准确率。然后,在这里,在编译的度量内。
我们要做的是准确率度量的更新状态。我们将传入Y和Y预测,然后我们可以去掉这个编译的度量。嗯。所以希望这就是全部。让我们看看能否运行这个。好的。既然我们自己在跟踪准确率。
我们在这里将明确写出。所以我们将做损失在这种情况下,就是损失。然后我们将做准确率。是。准确率度量.result。希望现在我们可以得到损失和准确率。是的。这看起来和我们之前做的很相似。
只是现在我们完全由自己来进行 compile。好的,所以现在我们得到了 compile,得到了训练步骤,我们通常会在训练结束后执行训练的评估,然后是 x test 和 y test,接着我们指定批量大小。我们说 32。这里有一件事是,这个 dot fit 在训练步骤上有效,而 evaluate 则在测试步骤上有效。
为了使这个工作,我们实际上需要定义另一个函数,并且我们需要执行测试步骤,尽管这个步骤会稍微简单一点,因为首先我们将解包数据,然后计算预测,因此我们的预测将是 self。
我们在指定训练为 false 的同时使用 t model X。我们所做的是,如果我们使用批量归一化或 dropout,那么在测试和训练期间它们的行为是不同的,我们只是告诉模型现在是在测试模式。因此,请确保这些在不同情况下有不同行为的模块设置为测试模式或评估模式。
然后我们将计算损失,即 y 预测的子损失。接着我们将进行准确性对称更新状态 y y 预测。最后,我们将返回一个包含损失的字典,损失就是 loss,准确性则是 accuracy。我们正在执行对称的结果,一切都很好,因此这与训练步骤非常相似。
虽然它被大大简化了,因为我们没有进行梯度下降更新,所以我们不需要跟踪这个 tape 来确保我们拥有所有的梯度等等。因此,让我们运行这个,大约两个 epochs,然后进行评估。好的。
所以在这之后,我们看到在 test set 上得到了 93,第一次是 0poC,97,然后几乎达到 98。不过,我想我们想在这里建立的是,这似乎确实在训练并且运行良好。所以这就是如何创建你自己的,指定训练步骤和测试步骤,从而覆盖训练的 fit,然后进行评估。这样,你可以在训练步骤中构建更复杂的模型,但仍然拥有执行训练 dot fit 的灵活性,这意味着你仍然可以使用训练 dot compile,尽管在最后一次我们进行了覆盖。
compile,但你明白我的意思,你仍然可以使用他们的 compile 和所有那些指标。如果你有任何问题,请在下面的评论区留言,非常感谢你观看这个视频,希望下次再见到你。
[双语字幕+资料下载]Jupyter Notebook 超棒教程!50分钟,把安装、常用功能、隐藏功能和Terminal讲解得清清楚楚。学完新手也能玩转! - P10:10)使用 pandas 加载和显示数据 - ShowMeAI - BV1yv411379J
好的,你在 Jupyter 笔记本中可能会做的主要事情之一是查看、转换和清理数据。所以让我们使用 pandas 加载一些数据,看看效果如何。所以加载。使用 pandas 加载数据。所以我要做的第一件事是将 pandas 导入为 PD D。如果你看过其他一些项目数据科学的视频,这个 Jupyter 笔记本现在。
因为我们目前的设计是个乱七八糟,这真是一场灾难。我绝对推荐观看其他一些视频,看看如何以良好的流程使用 Jupyter 笔记本进行项目。通常我会把所有的导入放在 Jupyter 笔记本的最顶部。我将它们全部保留在那里。但现在,这只是关于使用 Jupyter 笔记本。
所以我们就在这里做导入。所以我需要一些数据。让我去找一些数据。让我们去,如果你在谷歌上搜索,让我们看看 Caggle 心脏病。所以我相信这个心脏病 UCI 数据集,这是我们在另一个项目数据科学视频中使用的一个。我认为 map plot Lib 教程可能让我们下载这个数据。
我们将在这里点击。解压它。让我把下载界面拖过来,好的,heart.tc CSV。所以我很快回到我的终端。我只是要使用终端来移动这个文件。所以我将从我的主目录移动。从下载到。Home project,数据科学,Jupiter 教程。哦,实际上。
我不想移动整个下载文件夹。我想移动 heart do CSV。好了。这样。好的。所以我运行这个,你会看到 Heart.dot CSsV 从我的下载文件夹中消失。我们来关闭它。回到 Jupiter 笔记本。现在。我要做的第一件事是运行 LS。现在,LS 实际上是一个。
这是一个终端命令。这就像一个 bash 命令,用于列出你当前目录中的内容。但它也可以在 Jupyter 笔记本的代码单元中使用,这真的很好。所以你可以输入 LS。😊并打印出你当前目录的内容。所以你会看到我们的 heart.csv 数据。我将做 DF 等于 P D 点 read,CSV。
我将直接读取我们的数据。所以我们读取这个,你会看到它执行得很好。现在,如果我只做 D F。这里是 Jupiter 笔记本如何显示这些数据。所以这真的不错。实际上。你可以看到,如果你将鼠标悬停在数据行上,它会高亮显示。你会看到这些行看起来很不错。你有这种交替的灰白色。
这样你就可以很容易地看到数据。我将使用DF dot head
来查看前五行数据。列名都很清晰并且是粗体的,所以你可以看到列名是什么,以及哪些列对应于这些数据。这是使用Jupyter笔记本和pandas读取数据的一个优点。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P1:L1- 安装和设置深度学习环境(Anaconda 和 PyCharm) - ShowMeAI - BV1em4y1U7ib
🎼女士们,先生们,欢迎来到世界上最好的 TensorFlow 教程!
我已经计划和构建这些视频有一段时间了,目标是为我们在 TensorFlow 中建立一个坚实的基础。观看并完成这些视频后,你将准备好开始做自己酷炫的项目。因此,我希望你对 Python 的基础知识有所了解,最好还有一些线性代数的数学知识,了解深度学习背后的理论也很重要,这样你会更容易理解我们实际在做的事情。
但如果你没有安装,我会写下理论前提,并推荐你一些很好的资源,让你可以学习每个特定视频的主题。通过这种方式,我可以完全专注于 TensorFlow 和编码部分,使这些视频更加简洁。
好的,既然如此,大家我们就开始吧。在开始之前,我们需要安装它,没开玩笑,这可能是最困难的部分。最简单的开始方法就是使用 Google Coab,视频描述中会有链接,所以使用 Coab 你不需要安装任何东西。如果由于某种原因它不起作用,你可以暂时使用这个,它的界面看起来大概是这样的,你会有一些单元格,可以直接导入 TensorFlow STF,然后我们可以执行类似于打印 TensorFlow 版本的操作。
你将拥有最新版本的 TensorFlow。现在,最好是将它安装在你自己的电脑上,我想我找到了一些相对简单的方法来安装适用于 GPU 和 CPU 的 TensorFlow,我会展示我知道的最简单的设置方法。首先我们要访问的链接,以及所有的链接都会在视频描述中。我们向下滚动,点击下载 Anaconda,然后根据我的情况选择 64 位 Windows 的特定 Anaconda 安装,接下来我们要去的第二个页面是 PyCharm 的安装,这是我推荐的编辑器,我们将下载社区版本,也就是免费的版本。
现在你已经下载了这两样东西,我们将开始安装 Anaconda。让我们以管理员身份运行它,基本上我们只需要保持默认选项,所以我们点击下一步,我同意,下一步,下一步,然后安装。安装完成后,我们会点击下一步,下一步,然后完成。
好吧,我们要打开 Anaconda,首先要做的是创建一个环境。Anaconda 允许你拥有多个环境,每个环境可以有不同的软件包。例如,假设你想要一个 Python 的版本,然后另一个版本,你可以为这两者创建不同的环境。现在我们要创建的环境取决于你是否启用了 GPU,或者是要在 CPU 上运行。因此,你可以访问这个页面,查看你的显卡是否具备所需的计算能力。
如果你确实启用了 GPU,那么你需要先下载显卡的驱动程序。所以如果你是玩家,可能已经有这些驱动程序,因此不用担心。不过,例如,如果你有 G4 体验并且有最新的驱动程序,可能已经安装了 NviIo 驱动程序,所以你不需要再做了,但其他情况可以在这个页面上找到。我们从你有 GPU 的选项开始,所以我们将执行 conda create --name
,称之为 Tf,代表 Tensorflow,然后再写 Tensorflow-GPU
,按下回车。
很棒的是,安装内容时,如果你查看将要下载的库,它会下载 Nvidia 的工具包,并且还会下载相关的代码和库。所以你不必费心去寻找特定版本以匹配等,只需输入确认,然后它会下载你所需的一切。
所以,当这完成后,我们现在有一个可以在 GPU 上运行 Tensorflow 的环境,而我们所需做的只是一条命令来安装它。因此,这种方式的唯一缺点是 Tensorflow 并没有原生支持 Conda,这意味着我们将会稍微滞后一些版本,而在这种情况下,最新版本是 2。
现在我们要使用 Tensorflow 2.1,但这样做可以节省很多麻烦。如果 Tensorflow 团队的任何人正在观看这个视频,请考虑使用 Conda 发布 Tensorflow,因为 Pythtorch 这样做非常简单,安装也很方便,这对我们使用 TensorFlow 的用户来说轻松很多。对于在 CPU 上安装 Tensorflow 的第二个选项,我们将创建一个名为 Tf 的环境,称之为 CPU。
然后我们需要激活该环境。因此,我们将执行 Con activate Tensorflow CPU
。我们要做的第一件事是安装 Pip。现在我们有了 Pip,可以执行 Pip install TensorF
。
下一步是安装 Pycharm,我们只需点击下一步,下一步。我想要一个快捷方式,然后我想把 Python 文件关联到 Pycharm 打开,接着点击下一步。安装。然后运行 Pyr。导入设置可以不勾选,没问题。然后这样也可以。😔 接着我会安装 Vim,但如果你不知道 Vim 是什么,或者不使用它。
然后不要安装这个。接着开始使用 Pycharm。我们要做的是,嗯,让我们看看。我们可以创建一个新项目。然后我们可以做,P,叫它。我们的第一个项目。接下来我们会去现有的解释器,这里我们会去,嗯,这里有个点点点。
我们将去 Conda 环境,现在你应该能看到你的两个环境。所以如果你刚创建了一个,你应该能看到那个环境。我要选择那个启用了 GPU 的 Tf,然后我会点击“使其对所有项目可用”,然后按确定。
现在我们有了那个解释器,我只需点击创建。
是的。现在你应该能够做,嗯,你应该能够执行 import tensorflow as tf
。然后我们可以执行 print(tf.version)
。这样我们就得到了 TensorFlow 版本 2.1.0。如果你使用的是 CPU,你可能应该有最新版本。假设由于某种原因这不起作用,我见过一些人有找到 Conda 环境的问题。
你还应该能够进入设置,然后能够进入项目的 Python 解释器,在这里你应该能够点击添加,然后选择 Conda 环境,接着选择现有环境,然后在这里你应该能看到解释器。
在这种情况下是 TensorFlow CPU,然后你可以选择使其对所有项目可用。
所以,如果你找不到 Python 解释器,这就是本视频关于设置 TensorFlow 的全部内容。如果你有任何问题,请留言,我会尽力帮助你。话不多说,在下一个视频中我们将开始编码,希望能在那儿见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P10:L10- 保存和加载模型 - ShowMeAI - BV1em4y1U7ib
在本视频中,我们将探讨保存和加载模型权重的方法,以及如何保存整个模型,并执行被称为序列化模型的操作。
好的,这里有一些代码,希望你能从之前的教程中感到熟悉。我们首先进行一些基本的导入,然后加载 Ms 数据集。接下来我在这里创建了三个不同的模型。它们都是相同的模型架构,只是使用了不同的 API。第一个模型使用的是顺序 API,包含两个具有 64 个节点的全连接层和一个具有 10 个输出节点的层;类似地,model2 将使用功能 API 创建相同的模型。
最后,我们使用子类化的方法。首先,我们来为这个视频创建一个大纲。首先,我将向你展示如何保存和加载模型权重。其次,我将向你展示如何保存和加载整个模型,这被称为序列化模型。
因此,当我们保存和加载整个模型时,它将被保存为数据结构,这意味着它可以在不同的 TensorFlow 框架上加载,例如 TensorFlow.js、TensorFlow Lite。举例来说,你可以在你的 PC 上训练一个模型,然后如果你想将其投入生产并创建一个应用程序,你可以直接加载你之前训练的模型,而无需进行任何转换。此外,这样做将保存权重,也会保存模型架构,因此你不必实际拥有模型的代码,同时也会保存训练配置,这就是你传递给模型的原因。
编译。最后,它还会保存优化器和状态。例如,如果你使用的是 Adam 优化器,它将跟踪指数加权平均值,这在优化器内部。所以如果你只是保存权重,那么每次从模型加载权重时,优化器的状态都会被重置。
好的,让我们先从如何保存和加载模型权重开始。你要做的是在训练后进行保存,所以我们在模型训练后进行评估,然后使用 model.save_weights
,并指定文件夹。我们来做一个保存模型的操作,如果现在运行它,打开我们运行脚本的文件夹,里面将会有一个名为 save_model 的文件夹,所有保存权重的文件都将存放在这个文件夹里。
现在加载模型时,你可以使用model.load_weights
并指定该文件夹,保存模型后运行。同时,在之前的第一次训练后,准确率大约是90%,而现在经过一个周期后,准确率是97%。
这意味着它实际上是从之前加载权重。因此,需要记住的一点是,你不能在不同的实现之间交换和加载权重。例如,如果我们使用来自功能API的模型运行,那么会出现错误,说明它们不兼容。因此,这里的一条一般规则是,你需要以保存时的确切方式加载模型。如果你已经使用顺序或功能API进行过操作,并且知道如何做到这一点,请留言。
这对某些人可能会有所帮助。但总的来说,你需要以完全相同的方式加载模型。因此,如果你使用顺序创建并保存了模型,那么在加载模型时也需要保持原来的形式。现在,当保存模型时,你可以使用不同的格式。例如,我认为你可以指定保存格式,比如H5格式。因此,TensorFlow保存的有两种不同的格式:TensorFlow默认格式和HDF5格式,HDF5格式是之前在TensorFlow 1中使用的,而自TensorFlow 2以来,他们使用了TensorFlow默认的保存格式。所以,你可以查看官方文档,了解如何使用特定文件格式进行保存和加载。我将展示如何操作。
默认情况下,当我们想要保存和加载整个模型并序列化模型时,我们将执行model.save
,然后进行完整保存模型或类似的操作。
它会将模型保存到该文件夹中。是的,我们会收到这个错误警告,来自TensorFlow的。对此你无能为力,如果你收到了,就忽略它。从我的理解来看,我们没有做错任何事情,希望在未来的版本中能修复。但无论如何,你现在是在保存模型,而你可以完全移除这一部分,因此可以删除模型编译部分,只需指定model = ksmod.load_model
,然后指定该目录,完整保存模型,这样就会加载整个架构。
所以你在这里还可以做的是,可以删除你现在正在加载的模型的代码,这也将在加载模型内部完成,并且它也会加载训练配置,所以模型编译就是我们可以删除那部分的原因,现在。
我们重新运行这个。我们可以看到它在那个点继续训练,然后我们再次遇到这个错误,因为它正在保存模型,无论是使用顺序、功能还是子类化,这都有效。因此,之前你保存的默认格式是 HDF55 格式。
你必须做一些我想是令人烦恼的事情,你需要在这里创建一个明确的获取配置函数,同时你也需要从配置文件创建一个新格式的函数。你不必这样做。因此,如果你使用旧格式,我将参考官方文档说明如何操作,但这就是如何使用 Tensorflow 保存和加载模型,包括权重和序列化模型版本。希望这个视频对你有帮助,如果你有任何问题,请在下面的评论中留下。
非常感谢你的观看,期待在下一个视频中见到你!
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P11:L11- 迁移学习、微调和 TensorFlow Hub - ShowMeAI - BV1em4y1U7ib
在这个视频中,我将向你展示如何使用预训练模型,包括如何冻结层和进行微调。所以在这段精彩的介绍之后,我们开始吧!
好的,现在我们面前的代码应该会让你感到很熟悉。我们几乎在所有视频中都使用过这些代码,除了这一行命令:Tensorflow Hub。稍后我会详细解释这个命令,但首先,如果你没有安装,可以谷歌搜索 Conda Tensorflow Hub,你会找到这个页面,链接也会在描述中,你可以使用这个命令下载它。如果你使用 Conda,就运行这个命令;如果你使用 Pip,则只需运行 Pip install Tensorflow Hub
,就这样。
在这个视频中,我主要想做三件事。首先,如果你有之前训练的预训练模型,我会向你展示如何使用它。如果你不熟悉保存和加载模型的内容,可以查看我之前的视频。接着,我将向你展示如何使用 Keras 模型,Keras 有许多可以轻松导入的预训练模型。
最后,我将向你展示如何从 Tensorflow Hub 加载预训练模型。Tensorflow Hub 有很多预训练模型。正如我所说的,我稍后会详细介绍这一点。首先,对于我们的预训练模型,我将复制数据集加载的相关内容。
这里是 Ms 数据集。我们已经制作了多个视频。接下来,我将加载一个预训练模型。因此模型会加载。这个模型可能是你训练的,或者是你在 GitHub 上找到的某个模型。
你只需加载该模型,然后可以使用 print(model.summary)
。接下来,你需要查看你想要的部分。如果你想要整个模型,那么就加载该模型,继续训练。但是通常在进行迁移学习时,我们会选择几个层进行训练。
假设我们想要。假设我们想要除了最后一个以外的所有内容,对吧?假设我们有,假设这个类别数是 1000,对于 imagenet 或类似的东西。但对于 Ms,我们将有 10 个类别,所以我们必须用自己的最后一层替换这一层,但我们可以使用那个特定模型的前面层。所以我们如何做到这一点是,我们会这样做,sort of 基础输入,我们会做 model 的层,我们将取我们想要开始的层,那是第一层,所以我们要做 model layers 0 然后点输入。然后我们要做基础输出,我称之为基础是因为我们将使用这个预链模型作为我们的基础模型,然后我们将 sort of 在那之上构建一个层。所以我们在这里做的是,sort of 检查哪个,通过检查 sort zero1 到。
3,4,5,6,7。所以你想要从第七个输出。或者你可以从后往前数,所以你可以这样做,这是 minus1,然后 minus2。所以我们要做的是 model 的层,然后 minus2。然后点输出。所以我们想要从这个展平层输出。在其他词中,我们。
我们正在移除这个层。最后的密集层。所以也有其他方法可以做到这一点。你也可以使用 get layer,然后 sort of 取名字。但我们只会坚持使用索引。这样就可以了。然后我们要做。输出,我们将构建自己的。所以这可以是一个模型。
一个顺序模型或类似的东西。我们只会添加一个单独的层。所以我们要做的就是层,然后10个输出节点,然后是基础输出,对吧,所以我们首先通过这里运行,然后基础输出的输出将被发送到这个最终输出。
然后,我想我们可以称之为最终输出。然后我们将做 model 等于 ks 那个。不,等等,我们要做,是的,Ks 那个模型基础输入。输入等于基础输入。输出等于最终输出。输出,我想,因为有多个。所以接下来。我们可以打印模型的总结。也许这也应该叫别的什么,而不是模型,所以我们可以。
你知道,我们可以称这个新模型,因为我们已经改变了另一个有趣的是。我们实际上没有改变任何东西。我们只是替换了,因为我们之前预训练的模型有这一层。但你大致明白这个点,你可以用不同的类别数等替换它。所以这只是一个简单的例子,说明你实际上是如何做到的。
所以如果我们现在打印新模型的摘要,是的,正如我所说的,我们会得到完全相同的模型,但这里的模型现在是不同的,所以如果我们例如将其更改为15,那么最后的层将会有15个输出节点,但在这种情况下我们想要10个。然后你会像平常一样进行操作,我将复制编译和拟合的部分。
我认为这并不是非常相关。我们在之前的视频中已经看过了。所以在这种情况下,你只需创建一个新模型并编译,然后拟合新模型,我们现在可以运行这个。好吧,在仅仅一个周期后,我们可以看到它的准确率超过了97%,这暗示了预训练确实有一些效果。同时,我们可以看到,经过三个周期后,它的准确率几乎达到了99%。
你还可以做的是,假设这个预训练模型你不想实际训练整个模型,这就是你想进行微调的情况。因此,我们需要冻结这个预训练模型的层,而你可以很简单地做到这一点,就是执行model.trainable = False
。这样会冻结所有的层。
你还可以做的另一件事是迭代模型的层。因此,for layer in model.layers:
。然后你可以,在这种情况下,我们已经将每一层都设置为不可训练,因此我们可以做一些像assert layer.trainable == False
的操作。但如果我们没有在这里执行这一行代码,例如。
如果你只想更改特定的层,你也可以迭代特定的层,比如从1到5,然后你可以将层设置为不可训练。是的,这里有两种不同的方法来做同样的事情。是的。
所以我注意到一个错误,在编辑视频时,我写的是可训练层为false。嗯,我不太确定这到底是什么意思,但我们想要的应该是将某层的可训练性设置为false,所以这只是一个打字错误,出于某种原因它仍然运行了,我不确定这有什么区别,但这就是我们想要做的,而这已经在这一行代码中完成,所以其实没关系。
但如果你想要迭代你的层,这就是你应该怎么做。这样做的好处是,如果我们现在运行它,重新运行,我不知道你是否看到过,但运行一个周期大约花费了15秒或16秒,因此如果我们现在运行它而不这样做,我们会发现实际时间几乎减半。所以,进行微调和冻结层的好处在于,它的运行速度会快得多,我想这就是预训练模型的常见使用案例,你会拿这个巨型模型,将某些层冻结到特定点,然后只在最后添加几个线性层以适应你的具体用例。
是的,实际上我们可以看到,在这种情况下,它的性能确实更好。基本上是相同的。这是因为这些导入的层之前已经在Ms上训练过。所以我想这是一个场景,当你有自己的模型或加载了自己的模型时,我现在要去掉代码,我们将继续下一个部分。所以如果你想使用预训练的ks模型的话。
因此,ks库有很多可以很容易导入的模型,我将向你展示一个用例。它将与我们之前所做的非常相似,但使用这些模型的CA API。所以让我们创建一些随机数据,仅用于演示以运行模型。所以我们将做Tf随机正态,然后形状我们将做,比如说三个示例,五个示例299。
和9乘以3。这只是为了适应我们将要导入的模型。我马上会给你展示,但这些是X标签或特征。它们是299的图像,然后是RGB的三个通道。然后我们有TF常量,可以说是0,1,2,3,4。
所以有五个类别,它们都是不同的独特类别。然后模型是Kas应用程序。在这里,你可以使用许多不同的模型。所以我将选择inception V3。然后有许多参数可以在这里传入,你可以阅读更多官方文档。
但最重要的一点是,你可以将include top设置为true或false。基本上,在最后的全连接层中,你可以去掉这些,只获取特征向量,然后将其输入到你自己的顺序模型中或类似的东西。所以这可能是最重要的参数之一。我们可以先这样做。
然后让我们做模型摘要,看看它是什么样的。是的,所以我们可以看到,在这种情况下,实际上对于inception V3,最后只有一个全连接层。所以我假设你熟悉inception模块。
但本质上,它在这一层有不同卷积网络的连接,然后进行全局平均池化,最后进行全连接。所以如果你设置include top为false,它将去掉最后的全连接层。但假设我们只是想从这个开始。那么我们现在要做的与之前非常相似。
你可以将基本输入设置为模型的layers 0 .input。然后基本输出是这些输出是模型的层。然后我们假设再次,我们只想去掉最后一个全连接层,但当然,如果最后有多个全连接层的话。
你可以执行-3-4,删除你想要的确切数量。在这种情况下,我们只想删除最后一个。然后是 dot output。接下来我们要做的是最终输出。再次强调,我们只进行一层,因此让我们设置五个节点,因为我们有五个类别。
然后是基础输出。这与我们之前所做的非常相似。接着新模型是 Kas,模型输入等于基础输入,输出等于最终输出。然后你就可以编译。因此,我将复制这段以节省一些时间。编译,我们就用 atom。
分类处理,没什么。没有新内容。接下来我们要做的是 new model dot fit。所以让我们执行 new model dot fit。X 和 Y,然后 epox 设为 15,verbose 设为 2。这应该非常快,对吧,我们只有五个示例,5 个随机数据点。所以让我们看看它能否使用这个巨大的 Inception V3 网络过拟合 5 个数据点。
基础输入未定义,好吧。😔,基础输入就在那儿。好吧,所以在这 15 个回合的训练进行得相当快。正如我们所见,准确率达到了 100%,损失非常低。不过,当然,这只是一个演示,展示了如何使用这个 ks 应用程序模型导入内容。所以我现在想向你展示如何使用 Tensorflow hub。Tensorflow hub 实际上就是 Tf hubub dev,它基本上是一个你可以获取许多不同预训练模型的地方,适用于不同场景。假设我们只想要一些图像,你可以在这里找到很多模型,可以浏览并查看。
假设我们想要再次使用 Inception V3,所以我们可以直接去这个模型。它是为特征向量而设计的,这与 kis 模型类似,其中你可以设置 top 等于 false,这样就会给你一个特征向量,这正是这个模型的作用。
他们将 Inception V3 分离为一个包含全连接层的模型和一个仅返回特征向量的模型。
然后你做的就是复制 URL。当你有了 URL。
然后你可以返回代码。所以,再次让我们生成一些随机数据。我们生成的 TF 随机正态分布形状为 5,2,99,2,99,3。这几乎正是我们之前为加载 ks 所做的。再一次,我们正在加载完全相同的模型。所以这不会有什么新东西,只是向你展示如何使用 Tensorflow hub。
然后你要做的是 URL 设为,然后你将 URL 粘贴到这里。接着,你要做的是基本模型,然后 Uub 等于 ks.Layer.U。然后,输入形状为 299,2,99,3。接下来,你要做的是 model 等于 kas sequential。然后再做基本模型,对吧,这不包括全连接层。
然后你可以添加你想要的任何层。因此层的节点数为一百二十八。激活函数等于。不再。我们的层数为64,激活等于relu。然后是的。让我们做一个最终的层,10个上升,5个输出节点。我们只有五个类别。然后再次,你将进行模型编译和模型拟合。所以我只是要把这些复制过来。
然后我想我漏掉了KRS模型的一件事,当然。你可以做我们做的第一个示例,所以你可以设置基础模型的可训练性为false,这样你就可以进行微调。我可能也应该为另一个模型展示这一点,因为这是所有模型都可以做的事情。是的,作为示例,让我们尝试运行这个并看看它的样子。好的。
所以在这种情况下,它实际上并没有过拟合太多。因此我们可能需要运行更长时间,但正如我们所看到的,至少它达到了100%的准确率。差不多就是这样。这些是我想向你展示的不同预训练和微调、冻结层的方式。希望这个视频对你有用,如果你有任何问题,请在评论中留下,我希望在下一个视频中见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P12:L12- TensorFlow 数据集 - ShowMeAI - BV1em4y1U7ib
在这个视频中,我们将查看 TensorFlow 数据集,以及如何加载不同的数据集,进行预处理并高效加载数据。
好的,下面是通过 Ka datasets 提供的数据集,这也是我们到目前为止主要使用的。正如你所看到的,数据集相对较少,我们一直在使用 Cycipher 10 和 MNist。如果我们现在只看 TensorFlow 数据的比较,如此可见,我们有许多其他数据集,包括音频、图像、图像分类和目标检测。
问答、结构、文本摘要、视频翻译。我的意思是,这个数据集上有很多种类。因此我们学习它是有意义的,同时也使我们能够极高效地加载数据。现在我觉得有必要提到的是,我们将要处理的内容与 Tf 数据并不相同。
TensorFlow 数据使加载数据变得简单,它使用 Tf 数据。但是,如果你有自定义数据需要加载,那么你需要使用 Tf 数据。因此,TensorFlow 数据是一个高层封装器,旨在使加载常用数据变得非常简单。在接下来的视频中,我们将看看如何使用 Tf 数据来构建数据集的输入管道,或许是你自己收集的,或是从互联网上抓取的等等。
在这个数据集中,会有一些相似性,因为 Tf 数据是 Tf 数据的封装器。因此我们在这个视频中学到的内容在加载自定义数据时仍然会有用。
好了,够了,不再多说了。现在我们要做的是看看代码。你现在看到的就是我们一直在使用的标准导入。这个是新的,来自 TensorFlow 数据的导入 TFDS,这个是新的。如果你没有这些,可以搜索一下如何下载。所以对于这个,只需执行 Pip install TensorFlow 数据。
说明中也会提供 Anaconda 的链接,以及 Pip 的命令。好的,当你下载完毕后,我们要做的是先加载 Ms 数据集。我们在 Ms 上工作了很多,我想我们都感到厌倦了。
但这实际上只是一个简单的用例,展示它是如何工作的。所以我们将进行 DS train 和 DS test。我们将从 TensorFlow 数据集中获取一个训练数据集和一个测试数据集。然后,我们还会获取一些关于数据集的 DSS 信息。我们这样做的方式是通过 TfDS 加载。
然后我们将进行 Mnist。所以我们进行分割,这里的字符串就是你在 Tensor 数据目录中找到的内容。然后你只需将数据集名称写成字符串。接着我们将进行分割,并且将进行训练和测试。
所以这就是我们将 DS Strain 作为这个元组中第一个输出的原因。因此我们先进行训练分割,然后进行测试。一些数据集也有验证集,因此你还需要在这里添加一个验证字符串。Emmins 没有这个,但你需要检查特定的数据集。
所以你需要了解该数据集的分割情况。然后我们将设置 shuffle files 为 true。Tensorflow 数据集通常将内容存储在称为 TF records 的东西中,通常分成多个文件,比如说每个文件有 1000 个示例,这样做的原因是可以流式传输。因此,如果你在服务器上工作,可以通过互联网进行流式传输,然后在训练时同时加载,这在使用 Google TpUs 等进行训练时非常有用。因此我们希望打乱这些文件,以便不再看到完全相同的文件序列,尽管那些 1000 个示例内的批次将被打乱和随机化,我们仍希望打乱文件,以便顺序不同。
好的,然后我们将设置为 supervise equals true。这意味着它将返回一个元组,即图像和标签的元组。否则,它将返回一个字典。然后我们将设置 info 为 true。所以这就是我们获得 Ds info 的原因。如果我们移除这个。
我们将其设置为 false,我们只会获取 Ds train 和 Ds test。首先,通常我们会打印 DS 的信息,以便实际查看数据集的样子。在这种情况下,我想我们已经知道了,但图像形状是 28x28,数据类型是 Tf U in 8,标签没有形状,它只是一个整数,类型是 Tf in 64,并且我们有 10 个类别。
总例数为 70,000、10,000 和 60,000 用于我们的训练,然后你可以看到引用等。如果你将其用于论文或类似的事情。好的。如果你还有更新版本的 Tensorflow,我认为是 2.3 及以上。然后你也可以做类似的事情,figure equals Tftds 显示示例 DSs train DSs info,所以我们将设置测试集及其信息,而不是训练集,然后设置行和列,你会看到这将如何运行。
所以让我们重新运行它,将 supervised 设置为 false,然后你会看到它会看起来像这样,你可以看到你的数据集的一些示例。在这里,我们有四行四列,如我们指定的那样,然后我们可以看到下面的名称和标签。接下来,我们需要做的就是创建一个函数,因此我们将定义 normal image,并传入一张图像。
以及一个标签。我们要做的就是对图像进行归一化。因此,本质上我们要确保图像为 TF flow 32,然后将其除以 255,使其在 0 到 1 的范围内。因此我们将返回 TF.dot ca image,然后 TF.dot flow 32,再除以 255。
然后我们将返回标签。那么,现在我们可以执行 Ds train 等于 DSstrain.map,然后归一化图像。好的,这本质上会对每一个示例进行映射,并首先运行这个函数。
然后我们还可以指定 nu parallel calls,因为在发送到这个归一化图像时,没有固有的序列需要执行,因此可以并行处理,然后我们指定要进行多少个并行调用,你可以自己指定,比如 5 或 10,基本上这将是模型的一个超参数。一个很酷的事情是 TensorFlow 允许你进行自动调优,因此它会找出 TensorFlow 认为最好的方法,想要进行自动调优,你可以执行 Tf do data that experimental.dot auto tune。
然后我们将执行 Dstrain 等于 Dstrain.dot cache,这个缓存本质上是在第一次加载数据后,它会在内存中跟踪其中的一些数据,以便下次加载更快。接着,DSstrain 等于 DSstrain.dot shuffle,我们可以设置缓冲区的大小,比如设置为 1000,这意味着它不会看到数据集的整个范围。
但这个数字在某种程度上也依赖于文件的大小,在这种情况下,Tf 数据集将它们存储起来,但你也可以在这里执行 DSs info.dot splits,然后获取训练数据,接着你可以执行 nu examples,这样我们就可以确保随机打乱它们。
然后我们将执行 Dstrain 等于 Dstrain.dot batch,然后可以设置一些批处理大小。让我们在这里设置批处理大小,假设批处理大小为 64。好的,回到这里。另外,我们还将执行 D Strain.dot prefetch,然后我们也会在这上面设置自动调优。
此外,在预取阶段,当它在GPU上运行时,会预取64个示例,以便在GPU调用完成后可以立即运行。我们在测试集上也要做同样的事情。所以我们要做的基本上是相同的操作。
所以我们将执行D S test = D S test.map(normalize_image)
,并且nonpar
设置为auto tune
。然后我们将执行Bch
,因此我们不会在测试集上打乱数据。最后,我们将执行prefetch
,并设置为auto2
。好的,这部分是实际数据处理,这与我们使用TF数据加载数据时会非常相似。
所以这已经是由这个工具方便加载的Tensorflow数据了。但在那之后,当我们有自定义数据集时,这正是我们要做的。接下来我们需要做的是创建一个简单的模型。让我们用keras.Sequential
来创建,并设置输入为28,28,1
。
然后我们只需添加一个卷积层,32个输出通道,3的卷积核大小,然后是relu
激活。接着我们将展平。然后再添加一层。就是这样。现在我们要做的就是编译模型。你之前都见过这些。所以模型编译时优化器设置为keras.optimizers.Adam
,我们可以设置学习率。
然后损失设置为keras.losses.sparse_categorical_crossentropy
,指标将是准确率。接着,我们将在训练集上调用model.fit
,通常你需要传入x
和y
。所以如果你有x
和y
,你将传入x
然后是y
。现在因为我们在训练集中有了所有数据。
我们可以直接传入,这将包含x
和y
标签,然后我们可以将epochs
设置为5或者其他值,然后在测试集上评估模型。如果没有错误,让我们看看。希望这能正常工作。是的,我们需要做的事情有一件。
我们在想要展示示例时设置了supervise equals false
。但为了让它工作,我们必须将supervise
设置为true
。所以让我们重新运行一下,看看问题出在哪里。我们需要做的是将logicit
设置为true
。否则,这将无法训练。我想这就是我们缺少的部分。好的。
因此,我们在测试集上得到了98%的准确率。这是一个与图像相关的示例。我在想我们也可以看看一些不同的文本分类内容。这将稍微复杂一些,因为这也涉及文本的处理等。
我们将非常简单地进行操作,专注于数据。但我们将查看 IMDB 数据评论。因此,基本上这些是关于电影的评论,我们想要对这些评论进行情感分析,并判断评论是积极的还是消极的。举个例子,有些评论可能是“这部电影太糟糕了”,那么我们会给它一个零,因为这是负面的。
然后如果有人说“这部电影真的很好”,那么我们可能会将其设置为一。所以这就是我们正在处理的数据,和之前类似。D S train,D S test。我们将进行 TFDS dot load,然后指定 IMDB 评论。我们将拆分为 train 和 test。
然后我们将设置 shuffle 文件为 true,supervised 也为 true。然后设置 info 为 true。好的,就和我们刚刚做的一样。现在我们还需要做的是,如果我们只是...那么我们可以做的第一件事是,实际上,我们可以打印 D S info,然后我们可以做。我不知道,类似于...对于 S train 中的文本和标签,我们可以打印文本。
然后我们就结束吧。只用一个例子。所以开始理解一下它的样子。然后我们要进行拆分。好的。我们获得了一些信息。我们有测试和训练。所以我们有 25k 个训练示例,25k 个测试示例。然后这个无监督的,我想是我们没有标签的评论。
然后,没错,我们会很有趣。我和八个朋友一起参加了这部电影的提前观看。是的,你可以看到。这是一个相当长的评论,不过无论如何。然后,这就是我们首先需要做的,实际上是进行分词,以便我们不能将整个句子发送到我们的模型中。我们需要先进行分词,假设我们有一个字符串“你好,我爱这个”。
我爱这部电影。然后我们要进行分词。基本上,输出将是一个独立单词的列表。所以我爱,然后等等,你明白我的意思。接下来我们需要做的是将其数字化,因为我们不能在这里发送字符串。我们需要使用某个词汇将这些单词转换为索引。好的。
所以我们需要做的是进行分词,并且我们可以使用 Tensorflow 数据来完成这个任务。我们可以对特征文本进行分词。而这里有一点就是,Tensorflow 有很多不同的方式来处理文本,老实说,有点让人困惑。你可以用 Tensorflow 数据进行预处理,CAs 也有一个分词功能。你可以对其进行预处理,然后还有一个名为 Tensorflow text 的库,但实际上关于它的信息并不多。
所以是的,我目前不太确定这三种中哪一种最好,这个 Tensorflow 数据似乎运作得很好。不过无论如何,在我们获取这个分词器之后,我们将定义构建词汇表。然后我们将创建一个词汇表,它将是一个集合。接着我们将处理文本,而在 DS S 训练中我们不需要标签。我们将更新词汇表。
分词器对该文本进行分词。然后我们需要将其转换为 numpy。然后我们将其转换为小写,这样字母大小写就不太重要了。有一件事,如果你很观察的话,我们现在在我们的词汇表中添加每一个单词,这并不是理想的。对吧,通常会设置一些频率。假设它在我们的数据中出现五次,然后我们将其添加到词汇表,因为那样它就是一个重要的词。
所以这并不是为了效率,也不是为了准确性。我只是想给你展示一个如何做的非常简单的例子。我想你可以尝试让它更好。是的,可以做一些检查,看看那个特定单词出现了多少次,然后如果它出现,就添加进去。
如果某个词出现了一定次数,类似于这个情况。然后我们将返回这个词汇表。所以我们将词汇表等于构建词汇表。然后我们现在要做的一件事是我们将进行编码器。如我所说,我们需要对所有已分词的单词进行数字化处理。
这将通过 TFTS 进行特征处理,即文本进行分词编码。然后我们将首先发送我们的词汇表,接着我们将指定超出词汇的标记。如果我们得到一个不在词汇表中的单词,在这种情况下。
我们不会得到任何正确的结果,因为我们在添加每一个单词,但无论如何。然后我们将设置小写为真。分词器,我们将指定我们的分词器。好的,现在我们可以定义我的编码。我们将获取一些文本张量,然后获取一些标签,我们将做的是返回编码器来编码该文本张量。我们将先将其转换为 Ny,然后返回标签。所以这个编码器的本质是对其进行分词,然后根据这个词汇表将其转换为索引。所以它将完成我们所需的一切。
然后我们要做另一个函数。所以我们将进行编码映射。我们将发送一些文本和标签。这里的事情是数据加载也是 Tensorflow 图的一部分。所以这是一个 Python 函数,我们需要做一个函数以指定此函数的输入和输出,使其成为图的一部分。因此我们将做编码文本,然后标签是 Tf py 函数,所以我们实际上将指定我们将通过某个 Python 函数发送它,并且我们将指定该函数,因此我的编码,我们还需要指定输入,这是因为它是图的一部分,我们将做文本和标签,然后我们将 T out 设置为 Tf in 64 Tf in 64,因为在进行数字化时,它将变成代表我们词汇表中单词的整数。
并且这两个都将是整数。然后我们还需要进行编码和文本点设置形状。因此我们需要指定形状,并且我们将指定为 none。我们之所以指定 none 是因为我们实际上有一个序列,而该序列可以是任意长度。尽管标签只会是单个整数 0 和 1。好吧,然后在最后。
返回编码文本,逗号,标签。因此这可能会感觉有点,我不知道,笨拙。像是不必要的,但。可能还有更好的方法来做到这一点。这只是。我设法让它工作,似乎这是一个标准的做法。好吧,然后我们将进行自动调整 Tf,那是实验点自动调整。
我们要做 DS 训练是 DSstrain 点映射。我们将通过编码映射发送它。我们在代码映射中称其为。然后,nu 并行。调用是自动调整。然后我们要做这个。让我们做缓存。所以点缓存。然后我们将 D S 训练设置为 DS 训练点洗牌。我们写 10000。
现在我们要做的是 D S 训练。那个填充批处理。我们必须进行填充批处理,因为我们批中的所有序列长度都不同。所以我们需要填充到最长的示例。然后我们在这里做填充批处理 32,并且需要指定填充形状。嗯。
所以我们需要做 none。然后只是一个元组。在 Tensorflow 的新版本中,这部分不是必需的,但我们在这里所做的基本上是指定将要填充的形状。因此,当我们在这里指定 none 时,那些是用于图像或文本序列的。这就是我们想要填充的。因此我们在那个上写 none。
然后 Tensorflowlow 将会知道我们想要填充那个,然后我们要进行 DS 的训练。那是预取。然后再一次。自动调整。同样对于我们的测试集,我们只需进行 DS 的测试。点映射和代码映射。编码映射。就是这样。然后我们也会在那个上进行填充批处理。所以 D S 拥有那个填充批处理。32。
然后再次,填充形状。A将为无,并且只是一个元组。好的。这就是文本和数据的预处理。我们现在要做的是创建我们的模型。所以我们只是要创建一个非常简单的模型。然后我们首先要做的是层开始掩蔽。
掩蔽值等于0。因此,基本上。在这里,我们告诉TensorF,填充的值将用索引0填充。这些值将在计算中被忽略。假设我们有一个长度为1000的序列,还有一个长度为20。那么长度为20的序列将被980个零填充,执行所有这些的计算是完全不必要的。
所以当我们做这个层掩蔽时,我们只是让Tensorflow知道忽略那些值为0的,不进行任何计算。是的,所以。然后我们要做层嵌入。输入维度将是词汇表的长度,再加上2加2。因为我们在进行这个填充批次时将索引0添加到了我们的词汇表中。
我们还有一个超出,超出词汇的索引。因此,我们只是将其加2。然后让我们指定一些输出维度,我们将指定32,这对于嵌入大小来说非常小。通常,你会有300或者类似的。但再次强调,这只是为了说明。
然后你还会做一些LCSTM或某种序列模型。在这种情况下,我们要做的是全局,全球平均。1D池化。假设我们的序列中有1000个单词。然后我们将每个索引,每个单词映射到输出维度32。因此,基本上我们有。
你知道,批量大小。在这种情况下乘以1000。然后在嵌入之后,我们将得到批量大小乘以100乘以32。所以每个单词都映射到输出维度32。然后在这个平均池化之后,我们将得到批量大小乘以32。
本质上是对所有示例的所有序列取平均。是的。所以然后我们要做层开始密集。64的激活等于re。然后在最后。我们只需添加一个密集层。假设它将输出一个单一的浮点值。如果它小于0,那么就是负数。所以小于零。
负数,大于0。正数或者可能大于或等于。所以我们要做的是使用二元交叉熵,这将使用sigmoid激活函数。所以,是的,我想这一部分稍微有点高级。如果你没完全跟上,也没关系。但现在我们要做的是模型编译。
我想你还可以做的一件事是,可以像我们之前做的那样输出两个节点。然后你可以使用sparse categorical cross entropy
,就像我们通常所做的那样。只是当我们有两个类别时,我们可以使用另一种损失函数,而这个损失函数就是binary cross entropy
。
交叉熵,然后从logicit
等于真。然后我们可以指定优化器,优化器使用atom
,学习率为3e-4
。然后我们可以指定剪切值,以避免梯度爆炸的问题。然后在指标方面,我们将使用Accuracy
。好的,最后,我们只需执行model.fit(D, S_train)
。我们就这样做1nypos。
然后我们将对测试集进行评估。因此,再次强调,这不是为了准确性或其他什么,仅仅是为了演示我们如何从TensorFlow数据集中获取数据,构建词汇表,预处理文本,进行高效加载,然后创建一个简单的模型来展示它的工作原理。所以让我们运行它,看看结果。好的,首先。
我们能不能先聊聊它第一次运行时没有任何错误的事情。我是说,我写了所有这些代码,它第一次运行就成功了。这可能是第一次真正发生这种情况。所以在测试集上,我们最终得到了89%。让我们看看能否向上滚动。这就是我设置verbose
为2的原因。
顺便说一下,然后在训练集上我们得到了大约96%。所以,好吧,我们可以,有一些正则化的空间,也有一些空间。我们可以尝试再训练一段时间。当然,我们可以让模型变得更大等等。但在这种情况下,这样就可以了。所以好吧。
所以希望这个视频对你有帮助。我知道最后这一部分可能有点复杂,但我也想展示一下如何处理文本,并且我还想提到有很多不同的方法可以做到这一点。这是其中一种。如果你有觉得更好的替代方法来处理这些文本,请在评论中告诉我。不管怎样,非常感谢你观看这个视频。我希望在下一个视频中见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P13:L13- 数据增强 - ShowMeAI - BV1em4y1U7ib
好的,大家,欢迎回来观看另一个视频。在这个视频中,我们将看看数据增强。因此我们这里有一些基本的 Tensorflow 和 Keras 导入,以及我们在之前的视频中查看的 Tensorflow 数据集作为 TFDS。
所以我们基本上做的和那个视频一样。我们正在加载 CIFAR-10 数据集。
这部分基本上是从之前的视频中复制过来的,我们对图像进行一些归一化处理,因此我们用 255 来除,映射每个图像通过这个归一化的图像。我们进行缓存、洗牌、批处理,然后预取,测试集几乎相同,只是没有缓存和洗牌。
然后我们有一个相当简单的模型。我们输入 32x32 和三个通道,第一层就是一个。
是的,所以这是一个非常小的模型,因为这只是专注于数据增强部分。但基本上我们有两个组合层、最大池化、卷积、扁平化,然后最后有两个密集层。
然后模型编译和模型拟合 5 个周期,然后模型评估。
好的,我想向你展示两种数据增强的方法。
首先,这里假设你正在使用一个 Tensorflow 数据集,这在大多数情况下都是如此。要么是通过 Tensorflow 数据加载,要么是为你的自定义数据进行自定义加载,这部分我们还未讨论,但未来的视频中会涉及。因此我们在这里要定义另一个函数。
哦,我们将在这里找到另一个函数,定义 augment,然后我们将传入图像和标签。
有许多不同的 Tensorflow 函数可以用于数据增强,我会链接到你可以查看的文档。我将向你展示它的结构以及一些基本的内容。当然。
如果你愿意,可以添加更多,或者删除其中一些。但首先,我们想要对图像进行调整大小。这是一个常见的事情。在这种情况下,你知道。这些图像已经调整为32乘32,但也许有时图像不完全,可能不是所有的图像都正好是这个大小。因此我们可能需要进行一些调整。我们要做的是新的高度等于新的宽度。
我们将其指定为32。所以我们不需要进行任何调整,因为已经完成了。但这只是你应该如何做的。
所以图像等于T F dot image dot resize。我们将发送该图像。然后我们将指定新的高度和新的宽度。
好吧,然后假设我们想要,我不知道。将图像转换为灰度,所以现在通道是三个通道。对吧。假设我们想将其转换为灰度,以便我们的模型能够对灰度图像和彩色图像进行预测。但也许我们不想对所有图像进行灰度处理,对吧。
我们希望仍然保留一些颜色。因此,在某种概率下,我们想要进行转换。然后你可以做一些像F TF dot random dot uniform的事情。你可以指定最小值,例如零,最大值1。假设如果小于0.1,这将在10%的情况下发生。然后我们要做的是进行Tf doim。RGB转灰度。
关于那张图像。现在一个问题是,由于我们正在转换为灰度,因此输出通道将只有一个,但当然。在这种情况下,我们的模型将期望输入通道为三个。因此,解决这个问题的一种方法是。
你可以将那一个通道复制到三个通道中,因此你可以复制那个通道,使其变成三个通道,尽管这三个通道都是相同的。但这样做是为了确保模型能够正常工作,因此你可以做一些类似于TF tile的事情。
然后你可以做1,1,3。所以在这里,我们将不复制这个维度。这里不复制这个维度,我们将复制三次。这是通道的维度,这是通道数的维度。
这可能有点棘手。所以如果你没有完全理解,也没关系。确保你了解这个瓦片的T是做什么的,然后就是。真的。关键是你可以使用if语句和其他类似的东西,而不需要对你的示例进行确定性的增强,因此你可以在数据增强中引入随机性。我想这里非常重要的一点是,我经常看到人们谈论数据增强,就好像你在扩展你的数据集一样,因此如果你有100张带有这种数据增强的图像。
你会得到大约 300 个这样的样本。这并不是数据增强的正常做法。通常的做法是实时进行增强,也就是说这在 CPU 上并行完成,而 GPU 正在训练模型。因此,在训练当前批次时,它会获取下一个批次,并且在这些图像上实时进行增强。所以,实际上你是在有效地扩大你的数据集。
但这并不完全如此,例如,如果你看看这张,对于每个图像我们以 10% 的概率将其转换为灰度,那么引入这种数据增强后的有效数据集大小是什么?这有点棘手,特别是如果你引入更多随机性。假设我们做图像等于 TF 图像随机。
图像的亮度,然后指定最大变化量,这在其变化范围内。因此,当我们引入这样的随机亮度后,有效的数据集大小是什么?
我想,在 Infinite'ca 中,它可能会稍微改变模型的亮度,只有在特定像素上,变化非常微小。而且这可以在每个图像上进行。所以我认为这很重要。谈论数据集的大小在文档之后有点棘手,所以请记住这一点。另外一件事是,这些操作都将在每张图像上顺序完成。
首先,我们在调整大小,然后进行随机 RG,我想,没错,随机 RGB 转灰度。接着我们会做随机亮度。然后我们可以添加更多内容。再一次,我真的鼓励你查看文档,因为还有很多其他内容,你也可以创建自己的数据增强。在这种情况下。
我们只是使用他们的函数,这在大多数情况下已经足够了。我们将进行 TF 图像随机对比度。我们将输入图像,指定一些下限值和上限值,至于这些函数具体在做什么,我想你可以打印出来看看它们的作用,但具体的效果是什么。
我建议你阅读这些特定函数的文档。因此,我想在这个视频中我们学习如何使用数据增强,而不是从头开始实现它。
还有一件事是,你可以进行非常常见的增强,可以垂直或水平翻转图像。尽管我会小心一点。根据你拥有的数据集,例如使用MNIST,你不想水平翻转图像,因为例如,如果你垂直和水平翻转一个9,那会本质上改变图像的数字,所以你要确保你所做的数据增强并不会破坏图像的正确标签。
所以在数据增强上要小心,更多的数据增强并不总是更好,你需要确保你所做的一切仍然能保持每张图像的正确标签。嗯。不过,我的意思是,假设你有狗的图片或其他。
如果你水平翻转一只狗,它仍然是一只狗。如果你垂直翻转,它仍然是一只狗。因此在很多情况下,这是有意义的。只需小心一点。那么我们要做的是图像是TF,图像随机翻转左右。在50%的情况下,它将随机翻转左右。我想做一些。
你可以选择翻转的概率。我还没有找到可以做到这一点的函数。我想自己实现并不太难,但它可以通过Pytorch获得。我认为TensorFlow也能做到,希望他们未来能实现。而且你还可以进行图像处理,TF图像,随机翻转,上下翻转,图像。
我不打算再次使用50%的概率,这次视频中不会使用。最后,我们只是返回图像和标签。好的,现在我们有了我们的函数,我们要做的是映射它。所以,例如,我们将在这里洗牌后进行。
等于thetrain dot map,然后进行增强。所以它首先会对图像进行归一化,我想我们也可以指定非并行调用,因为每个图像本身并没有什么可以并行处理的,这就是为什么我们要进行非并行调用。
是的,我想这就是了。这就是我们需要添加的所有内容。所以我们先运行一下,以确保它实际上能工作,等等。
好吧,所以它似乎可以运行。再说一次,我们并不关注性能。虽然我强烈建议你在之前的视频中,我们在Cypher1on上进行了训练。我想我们在测试集上得到了78%左右,或者类似的结果,并引入数据限制。我认为你可以做得更好,并进行一些模型修改。
我认为你至少可以做到90%,所以这是我强烈建议你做的。玩一下代码,加上数据限制,看看是否能提高准确性,并告诉我你的进展。
但这是进行数据增强的一种方法。我将向你展示另一种方法。我认为这是推荐的方式。这种方式效率很高,并且在模型训练时完成。但另一种常见的方法是你可以这样做。
这是针对TensorFlow版本大于或等于2.3.0的,当前最新版本。所以我们可以进行数据增强,并可以构建一个顺序模型。因此在这里。
我们将把数据增强作为模型的一部分,我认为这有利有弊。我觉得这更简单,因为它只是模型的一部分,但我不太确定这是否是在模型训练时进行的,例如。
在这里进行的数据增强,是在模型仍然训练当前批次时并行进行的,同时在CPU上进行。
我认为这样做会损失一些性能,但我觉得这更简单。无论如何,我们将进行实验层的预处理。所以,正如你所看到的,这仍然是新的。这就是为什么它仅在最新模型中可用。
所以我们将进行预处理,调整大小。我们将指定高度和宽度。再一次,我将链接到这个实验性预处理的文档,这里有很多不同的函数。但你可以使用层.实验.预处理,进行随机翻转。你可以指定模式,可以设置为水平、垂直,或者仅垂直或仅水平。
为了保持之前的数据增强,我将进行水平翻转。然后我们还可以做一些像层.实验.预处理.随机对比度的操作,然后指定因子,比如0.1。没错,就是这样。当然,你可以添加更多,可以添加很多。
但我认为现在这样就很好。接下来我们要做的是把它加在这里的顶部。我们将在这里进行数据增强。因此,它将通过数据增强处理,然后发送到各层。所以让我们运行这个,确保一切正常。嗯,这真是个失误。我不小心停止了录制,我想我讲了大约10分钟,所以我会尽量回忆我说过的内容。你可以看到,我们在只经过一个epoch后达到了41%,而且我们并不在意准确率。
但如果你将其与我们之前的结果进行比较,我认为我们在1到2个epoch后只有26%或28%,而且我想我们使用的是同一个模型,对吧,唯一不同的就是数据增强,所以之前我们使用了一些更多的数据增强,比如随机亮度和随机灰度等。
当我们添加更多的数据增强时,我们使模型更难过拟合训练数据,因为它看到了如此多样的图像。在之前的视频中,我们谈到了关于L2和dropout的正则化。
一种非常有效的方法是数据增强。因此,过拟合本质上是对训练数据过度适应,对过拟合的一种解释就是它基本上只是记忆训练数据,而记忆并不会导致一种通用的理解,所以你可以从自己的角度思考一下。
拥有更多的记忆内容使其更难,对吧?如果你要记忆的东西非常少,记忆起来就非常容易,网络也是同样的道理,因此如果我们添加更多内容、更多图像,就会使其更难以记忆,这样可以减少过拟合。此外,L2和dropout非常推荐你尝试数据增强,不仅是为了扩展数据集,以提高模型性能。
这样做也会因为有更多的图像进行训练而改善模型性能,但这也会减少过拟合。所以,是的,我想就这些。如果你有任何问题,请在评论区留言。非常感谢你观看这个视频,希望下次再见。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P14:L14- 使用 Keras 进行回调并编写自定义回调 - ShowMeAI - BV1em4y1U7ib
大家好,欢迎回到 TensorFlow 数据教程。在这段视频中,我们将看看如何使用回调以及如何创建自定义回调。对于那些不熟悉回调的人,我最好解释一下这是什么,基本上,回调是自定义模型在训练或评估期间行为的一种方式,我认为在看到一些示例后,你会更清楚它的能力。但在深入之前,我们先快速浏览一下代码,这里的大部分内容或者说全部内容在之前的视频中都很熟悉,我们只是进行了导入,正在用 TensorFlow 数据加载 MS 数据集。
这只是为了避免 GPU 错误,所以我们正在加载 MS 数据集。我们通过在数据集上使用映射来规范化图像,缓存、打乱批次、预取。所有这些都来自 TensorFlow 数据教程,然后我们创建一个非常非常小的模型。只有一个卷积层和一个最终的全连接层。
我想我们应该在这里就有这样密集的层。然后没问题。然后你不应该看到这一部分,所以我现在就把它去掉。好吧。所以我们有模型编译,然后我们有模型拟合。这就是启动代码的样子。没问题。
我们想要做的第一件事是进行保存回调。我已经向你展示了如何保存和加载模型,但这通常是在训练完成后进行的。所以如果你训练 10 个回合,我已经向你展示了如何在模型拟合后保存它。
但假设你希望在训练过程中保存它。也许每个回合,或者你只想保存到目前为止的最佳模型,我会向你展示一个方法。这是回调的完美示例。所以,基本上。让我们在创建模型后、编译之前来做这个。
所以我们将使用保存回调,这是卡拉斯回调模型检查点,这是我们将要使用的。卡拉斯有很多不同的回调,我建议你查看所有相关的文档。这个也有很多参数可以传入,我只会用其中的一部分。首先,我们将指定一个文件路径,所以我们就叫它检查点。
然后我们将做仅保存权重,我们将设置为真。然后我们将监控准确率。然后我们还可以有一个参数,我们只保存最佳的,例如我们可以设置保存最佳仅为真或假,让我们设置为假,这样它实际上在每个epoch时都会保存,我也将向你展示自定义的,所以我们如何创建我们的自定义回调,并且你可以指定你想要保存的时间。
那么,当我们有这个保存回调时,我们将去我们的模型,拟合它,我们将做回调,然后我们将进行回调参数等于,然后是列表,我们将发送那个回调,在这种情况下是保存回调。
所以让我们从这里开始,运行一下,确保它能正常工作。
好吧,在那个文件中有一个包含模型权重的文件夹,所以它似乎可以工作,然后我将向你展示我们如何添加另一个回调,假设我们想要一个学习率调度器,所以我们可以将初始学习率设为0。
01,然后我们希望随着epoC
的进展来改变学习率。那么我们可以这样做:假设我们做。
首先,我们将定义我们的调度器函数,所以我们将定义调度器,我们将传入epoC
和学习率,然后我们可以做这样的事情:如果epoC
小于2,那么我们将返回学习率,否则我们可以返回学习率乘以0。
99,所以本质上我们在每个epoC
中降低1%,这取决于你决定这是一个好的调度器,我只是给你展示一个例子,你可以根据自己的需要实现它。然后我们将做学习调度器的回调来进行学习率调度。
我们将发送该函数,然后我们还会发送verboos equals1
以便在学习率变化时获得打印语句。所以让我们重新运行一下,确保它可以正常工作。哦,是的,这是我一个很大的错误,我们还得发送它。所以在这里的回调中,我们只需添加一个逗号,然后添加那个。
学习率调度器,希望现在它可以正常工作。好吧,如你所见,它正在随着每个epoC
降低学习率,这个幅度有点难以判断,但大约是1%。当然,你可以做更高级的调度器。好吧,TensorFlow关于编写自定义回调的官方教程非常不错,我会在下面的描述中链接它。这是我阅读过很多次以获取现在提供给你的信息的教程。
本质上,当你创建自己的自定义回调时,你可以自定义模型的行为,有很多不同的函数。例如,在训练开始时,你可以做一些事情,这取决于你选择做什么。但有很多不同的函数可以自定义行为,比如on train、on epoch begin、on epoch和on test begin等。
在测试结束时,在预测开始时,等等。所以让我们尝试构建自己的自定义回调。它会是一个相当简单的,但希望能说明它能做什么。我们将使用这些函数之一。我们将使用这个定义在epoch结束时。
尽管你可以使用不同的,并对此进行实验。我也将在描述中链接这个教程。好的。那么让我们回到代码。我要做的是创建。
类,然后我们称之为自定义回调。接着我们将从Kas回调继承。如我所说,我们将使用定义。在Epoch结束时,我们将传入epoch,然后设置logs。默认为none,但我们将接收日志,我会给你展示,以便我们可以打印。首先。
我们可以打印logs.dot keys。所以让我们打印一下,它将在每个epoch结束时打印。我做了和之前一样的错误,我们显然需要初始化并传入它。所以我们可以在这结束时做自定义回调,然后调用或初始化它,希望我们能看到想要的行为。好的,如你所见,这里有一个字典,你有损失、准确度和学习率。
我还想提到的是,当你有验证集和训练集时,这个损失和准确度将变成训练准确度、训练损失、验证准确度、验证损失等等。例如,我们来看一下。所以例如,在这里。当我们监控准确度时,如果你使用训练和验证集。
你需要指定监控哪个,因此在这种情况下,你可能监控验证准确度或类似的东西。只需提到它,以便如果你有训练和验证集,你需要确切指定你想在这里使用的内容。你可以使用print logs.dot keys获取这些,我们看到有损失、准确度和学习率。但我们将做的是,如果logs.dot get。
那么让我们先获得准确率,然后假设如果准确率是,我不知道,高于0.90%。 好吧,这样就很糟糕,但你明白我的意思。所以如果在这种情况下训练准确率超过90%,但当然,如我所说,如果你还有验证集,你可以做验证准确率。这样就可以了。
如果是这样的话,我们将打印出准确率超过90%并停止训练。然后我们可以让self.model.stop_training等于true。这只是自定义回调可以做的一个例子。再次提醒,教程中还有更多的例子和更详细的内容。
在官方教程中,你可以在自定义回调中使用所有这些不同的函数。但无论如何,让我们看看这是否有效。让我们运行这个。好吧,所以在只经过一个周期后得到了超过90%的准确率,因此在这里停止训练,当然。所以例如,除了在周期结束时检查,也许你想在批次之后检查。
所以当那一批次达到我们想要的准确率时,我们想要停止训练,你可以在批次上进行,但无论如何,这就是回调和如何编写一些非常简单的自定义回调的内容,非常感谢你观看这个视频,如果你有任何问题。
将它们留在下面,我希望在下一个视频中见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P16:L16- 自定义训练循环 - ShowMeAI - BV1em4y1U7ib
大家好,希望你们过得非常棒。在这个视频中,我将向你展示如何从零开始实现训练循环。
这意味着我们不再使用model.fi
,而是完全从头开始自己做。如果你对编码和Pythtorch熟悉,那么这将更符合你训练网络的习惯。不过,让我们开始吧,在这个视频中,我们不会在训练内容和数据等方面做任何复杂的事情。
重点是向你展示它的整体结构。这里的启动代码只是一些你在之前视频中见过的基本导入。我们将使用Tensorflowlow data sets
,所以如果你还没看过那个视频,可以在右上角找到。我们在这里加载Ms data set
,所以我们有训练集和测试集,然后我们还有一个用于标准化图像的函数,这些都是从那个视频复制粘贴过来的,然后我们这里有一个非常非常简单的模型。
只需一个卷积层和一个全连接层,然后我们在这里添加全连接层,就像这样,然后我们就可以开始了。首先,我们需要一些指标,所以让我们设置准确率指标,这是ks do metrics dot our
。
分类准确率。接下来,我们先进行训练循环。首先,我们将训练若干个周期。在这种情况下,我们将训练epochs
为5。我们只需写for epoch in range epochs
,或者我们可以称它为😔,Num epoch
。
所以就在这里进行nu epoch
。😔 然后我们可以打印。只需打印。换行,然后开始训练周期。接着,我们可以这样做:epoch
。现在我们使用F字符串。接下来,我们将遍历训练中的所有批次。我们将使用for batch index
然后X batch comm a Y batch in enumerate AD train
。
好的,我们将进行若干个周期的训练。在这里,我们首先写with Tf gradient tape
作为tape
。这用于记录我们在前向传播中要进行的所有操作,以便后续进行模型权重的反向传播。我们将进行Y prediction is model.X batch
,然后指定training is true
。
然后我们将计算损失,使用我们在这里指定的损失函数。我们将输入y batch
,真实标签,以及y predictions
,就是我们刚刚通过前向传播计算得到的。好的,这样我们就有了那些在tape
下的内容,然后我们可以计算梯度our equal tape dot gradient
。
然后我们指定损失,然后是模型我们的可训练权重。所以我们基本上想要损失对可训练参数的梯度。然后或者说是可训练权重。然后我们将进行优化器。应用梯度。我们可以 zip 梯度,模型可训练权重。
然后我们将进行准确度指标 dot 更新状态。Y batch 和 Y 预测。这样我们就能了解那个 epoch 的准确度。到这里结束。我们将做训练准确度等于准确度指标的结果。然后我们可以打印,这样我们就可以处理 epoch 的准确度,然后。我们可以直接做。
训练准确度就是这样。然后我们可以重置准确度指标,以便它在下一个 epoch 时为零。所以 accuracysymmetric dot 重置状态。这就是训练循环的内容。这看起来非常类似于我们在上一个视频中讲解如何自定义模型的过程,只不过现在我们只是去掉了模型的拟合,而是为我们想训练的 epoch 数添加了一个循环。
然后我们想做的就是,我想。测试循环。这是用于训练的,然后我们将需要一个测试循环来评估我们的模型。我们不需要运行几个 epoch。我们可以只运行一次数据集。所以我们将做批次索引和 X batch。
Y batchge 列举 DSs 测试,我想现在我们并没有使用批次索引。但我的意思是,你可以。所以我想你也可以遍历 DSs 测试,没有必要做 enumerate。不过有时你会想要批次索引。无论如何。我们不需要使用梯度记录。我们不会收集梯度。因此,我们将在这个模型中做 y 预测,当 X batch 训练等于真时,然后 accuracysymmetric dot 更新。
状态 Y badge,然后 Y 预测。最后我们可以做训练准确度等于 accuracysymmetric dot 结果。对,就像我们在这里做的一样。然后我们可以,我想我们可以打印测试集的准确度。然后我们可以像这里一样写训练。最后,我们可以再次重置。虽然我们不必这样做,因为那是我们要做的最后一件事。不过无论如何。
如果你想要一个训练循环和测试循环,它看起来就是这样,当然你也可以。我是说,你可以把这个放在一个像 define train 的函数里。然后你可以,比如说,按范围的 epoch 只需调用那个函数。
训练1个周期,也许。然后运行它。所以你知道你可以思考一下你想如何构建这个结构。但是这就是训练循环的基本原理。这非常简单,我们以最简单的方式实现了它,当然,如果你在做一些更复杂的事情,比如生成对抗网络或GAN,那么它看起来会比这个复杂得多。
但基本方法仍然是相同的,我认为如果你理解了这个基本框架,那么在处理更复杂的事情时,这将帮助你理解它的整体结构。好的,首先我们应该运行这个并确保它能工作。但它没有。
所以它没有属性梯度。这是因为我们想要一个tap dot梯度。好的。正如我们所看到的,这很有道理,它正在训练并且有效。所以是的。无论如何,这就是本视频的内容,希望你觉得有用,如果你有任何问题,请在下面的评论区留言。我想我之前说过感谢观看,但谢谢你观看,希望在下一个视频中见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P17:L17- 完整的 TensorBoard 指南 - ShowMeAI - BV1em4y1U7ib
本视频的目标是让你充分理解如何使用 TensorBoard 来更轻松地理解错误并修改我们的模型。这个视频较长,因为涉及的内容太多,关于 TensorBoard 的内容。因此,让我首先给你展示一下我们将在本教程中学习的内容概览。我们将从学习或许是最基础但也是最有用的事情开始,即获取这些准确度和损失图。
在这个示例中,你会看到训练我们模型时使用不同学习率的准确度图。接下来,我们将学习如何可视化图像。在这个示例中,我们对图像进行了少量的数据增强,将极少数图像转换为灰度,因此可视化这些变化将非常有用,以确保我们期望发生的事情确实正在发生。
比如,在这里我们有一匹马,它已经被转换为灰度图像。我们还将看到如何创建混淆矩阵并将其发送到 TensorBoard,在这里我们将预测标签放在 Y 轴上,真实标签放在 X 轴上,这样我们可以看到模型在何处错误分类图像。
比如,在这里我们看到它正确预测飞机的概率为 65%,但在 7% 的时间里,它错误地将鸟类分类为飞机。我们还可以看到它正确预测猫的概率为 40%,而最大的错误发生在它将猫误分类为狗的情况,大约占 21%。其他有用的功能是你可以可视化我们模型的图形,在这里我们有一个非常。
一个非常简单的模型,它接受两个输入 X 和 Y,执行矩阵乘法,然后将其通过一个激活函数,这将是模型的输出。因此,如果你正在构建更复杂的模型,比如 Resnets,这种模型可以确保所有跳跃连接位于正确的位置,这将是非常有用的。
或者,如果你只是想更好地理解并更直观地查看模型的外观,TensorBoard 还能做其他酷事,你可以可视化并查看模型各种参数的分布,这对调试非常有用。如果你收到错误信息并想确切知道错误发生在模型的哪个地方,那么这些分布图将有助于你了解错误发生在哪一层。我们还有更多的内容要查看,比如我们将使用 TensorBoard 的 Hpars API 进行超参数搜索,这样你就可以看到哪些参数适合你的模型。
通过观察在这种情况下丢弃率、学习率和单元数之间的不同相关性,以及这些因素如何最终影响单次训练后准确率。为了更容易理解这一点,我们可以将注意力限制在仅关注与最佳准确率对应的部分。我们在这里看到的是,模型更倾向于使用相对较低的丢弃率,然后希望有一个非常高的学习率和较高的单元数。在这种情况下,我们正在检查训练集上的准确率,因此这可能是模型希望使用非常低的丢弃率的原因。我们还将学习如何使用TensorBoard的投影器选项卡,这在视觉上非常棒,你可以使用不同的算法,如t-SNE和PCA,以了解模型如何学习表示这些图像。
从一个非常高维空间投影到3D空间,在这里我们可以轻松可视化它们。例如,这里我们在MNIST数据集上运行它,我们可以,例如,使用TS&算法,如果我们现在搜索零,那么我们可以看到这里有零的聚类。同样,如果我们搜索数字二,我们会看到这里有一个数字二的聚类,这对理解模型的工作原理以及模型如何创建其表示是非常有用的。TensorFlow分析器也是一个非常有用的工具,它允许你查看哪些部分占用了最多的时间,以及在训练中你应该关注哪些方面进行改进。例如,在这里我们给出了不同部分的总结,以及它们在训练中占用的时间。因此在这里的图表中,我们可以看到输入占用了很大一部分时间。
占用了很大一部分时间,因此他们还给出了一些建议,表示该程序高度依赖输入,因为约84%的总步骤时间都在等待输入。因此,在这个特定的程序中,我们应该努力改善输入管道的效率,分析器的其他部分也可以看到许多不同的部分。
不过稍后再讲,现在你对我们将要覆盖的TensorBoard的不同部分和领域有了一个概念,所以让我们开始吧。
好的,为了让这个视频至少相对结构清晰,我将其分成不同的文件,每个文件专注于TensorBoard的一个特定部分。对于每个部分,我有一个起始代码,我的想法是快速讲解这个基于我之前许多教程的代码。所以我会相对快速地讲解,然后你可以查看之前的视频,我会引用那些视频以便对每个部分进行更深入的探讨。
所以我们将一切基于这个起始代码,然后我们将修改它或添加一些部分以写入 TensorBoard。首先,这是我们需要的基本导入,然后这是我们之前看到的内容。
我们将添加这两行,以避免任何 GPp 错误。我们正在从 TensorFlow 数据集中加载 CIFAR 10 数据集。我们通过除以 255 来规范化这些图像。然后我们对这些图像进行了数据增强,然后进行映射、缓存、批处理和预取训练和测试集。
虽然我们没有对测试集进行随机打乱。然后我们在这里有类名,这些将在投影仪标签中用于查看每个相应图像的正确标签。接下来我们有一个模型,这里是一个非常简单的模型,使用了组合层,两个组合层,一个最大池化层,一个展平层,然后是两个稠密层,中间有 dropout。
然后在这里我们有一些自定义训练循环的设置,所以我们首先获取模型。接着我们有损失函数,我们有优化器,在这种情况下,我们有一个准确性对称体来跟踪当前的准确性。
然后我们有这两个训练记录器,这将用于写入 TensorBoard,这些将是训练和测试,因此我们将为每个记录训练步骤和测试步骤。好的,然后我们有自定义循环。我们将遍历每个周期,范围是 nu Epos,然后在 DS train 中进行分批,这个过程非常基础。
我们在进行前向传播,反向传播。然后我们在这里进行梯度更新或优化步骤。然后我们对训练集做同样的事情,尽管我们没有进行反向传播。我们只是在检查准确性。好的,对于这个第一个文件。
实际上我将要做一些看起来可能有点奇怪的事情,但我们会去掉很多代码。
所以我想我们就到这里。
这里的想法是,这段起始代码是我们几乎所有文件的基础,你可以在这里看到。但我们希望在这个特定的文件中使用回调,这是一个更简单的方法,我们不使用自定义训练循环,所以我想首先展示这一点。因此,在获取模型后,我们将直接执行 model.dot compile,我们将指定我们的优化器,在这种情况下我们只会使用 Adam。
然后我们将指定损失。在这种情况下,我们将使用稀疏分类交叉熵,并且 log 设为 true。我们还将指定指标,在这种情况下将是准确率。好的,然后我们将做 Tensor board 回调。所以这可能是使用 Tensor board 的最简单方法,我将给你展示它的具体作用。
但这非常方便,所以你所要做的就是需要做 cars。回调 Tensor board,你必须指定一个日志目录,它会跟踪所有日志,所以我们就这样做,称之为 TBb 回调目录。然后我们指定一些直方图频率,这个我们将设置为一。这个用于我之前展示的梯度分布图等所有东西。
好的,最后我们将进行模型拟合,所以我们将传入 DS train。我们将传入 epoch 数,假设我不知道 a5。然后我们将做验证数据,实际上我们将传入测试集,通常你会这样做,所以为了目的,我们就假装测试集是验证数据。我知道这样做非常不正确,但这对于这个目的来说并不重要。
然后我们将指定回调,我们将做 Tensor board 回调。然后我们将指定 verbose 设为 2。好的,就这样。让我们运行这个,我将向你展示在 Tensor board 中的样子。但实际上,在我们这样做之前,我需要向你展示如何实际运行它。
所以你如何运行这个,你需要进入你有的文件夹。具体来说,就是你运行这个特定脚本的地方。然后你还需要激活你安装了 Tensorflow 的环境。然后你会做的是,tensor board,你会做 log De。
然后你需要指定你在这里称为的那个,TB 回调目录。如果你运行这个,我们将返回一个 URL,这在本例中是本地主机 6006。所以如果我们去查看这个。
更新后,我们将得到这样的结果,其中包含每个 epoch 的训练和验证准确度,同时我们也有损失函数的结果。因此你可以看到,验证准确度实际上更高,这可能有点奇怪,但请记住,我们正在使用 dropout,同时也在使用数据增强,这可能使模型在训练数据上更难过拟合。例如,我们将一些图像转换为灰度,当然,这可能更具挑战性,所以这大概就是为什么通常你会看到这种情况反转,训练准确度高于验证准确度。
好的,但正如我们在这个标签上看到的,我们有四个不同的内容。这只是用于 SCRS 的,关于损失和准确度的。你还有图形,告诉我们它看起来如何,我们有输入、两个组合层、最大池化、扁平化和稠密的 dropout,然后是另一个稠密层。
这样你可以在这里检查它,然后我们有之前展示给你的分布,你可以看到所有参数的梯度。或者更确切地说,是参数的分布。好的。这是使用回调设置 Tensor board 的最基本方式,我将要展示的是如何从自定义训练循环中实现它,因此从现在开始我们将专注于此。但请知道我将向你展示的大多数内容也可以使用回调和模型拟合来完成,但使用自定义训练循环使我们拥有更多灵活性,实际上使很多事情变得更简单。
所以让我们全屏查看这个。再一次,这只是你之前看到的起始代码,我们要做的就是移动到自定义训练循环的部分。这里我们想要添加打印到 Tensor board 的功能。因此,一个想法是。
要么你为每个批次写入 Tensor board,所以你可以在这里执行。或者你可以在这里执行,这样也可以。但也许每个 epoch 执行会使图形更清晰,因此我们可以在这里使用训练者作为默认值。然后我们想要发送损失值,同时也想发送准确度,这里有一件事是我们要发送损失值。
就像这样,这实际上只是该批次的最后损失,所以要注意,你可能希望发送该批次的平均损失。因此你会有一个损失列表,然后取其均值发送,但这可以展示如何写入 Tensor board,因此我们会在那里发送损失,然后发送步骤,我们可以用 epoch 作为我们的步骤。
然后我们将做同样的事情,使用 dot scalar。我们将使用准确度,所以让我滚动到下方,我们将发送准确度,准确度将存储在这个 accuracy metric 的结果中。请记住,在每个 epoch 之间它会重置,并且在训练和测试之间也会重置。
这应该是通过测试集进行迭代的。好的,然后我们要添加 chsmetryduct 结果。我们将再次指定步数为 epoch。现在我们完成了训练,我们也想为测试做同样的事情。因此,我们可以在这里复制并粘贴,并确保更改所有这些内容,测试写入器的步数仍然是 epoch,步数仍然是 epoch,所以希望现在没有错误。
所以这里需要记住的一点是,我们现在使用了另一个日志目录。在这里,我们使用日志,并在日志中存储两个子文件夹,分别用于训练和测试。首先让我们运行这个,接着我们要再次打开这个 Anaconda 提示符。
我们将使用这个,但我们会指定日志文件夹只是 logs,然后它将自动找到训练和测试。如果我们运行它,然后去打开 Firefox 或其他浏览器,访问 Tboard 的那个网址。
本地地址 6006。
我想我们在这里只需等一下,因为它会写入每个 epoch,所以好的。在这里,我们现在可以看到准确度图,例如最后的图,这些将是非常清晰的离散步骤,因为我们只是每个 epoch 记录一次。
当然,正如我所说,你可以每个批次进行记录,这样会得到更平滑的图形。但这里有一点奇怪的是,测试集的准确率高于训练集,我想这可能与我选择的增强方法有关。例如,我将训练中的一些 RGB 转换为灰度,这当然会让模型在这些数据上训练得更困难,所以这可能就是原因。这就是我想向你展示的内容,你还可以做更复杂的事情,比如进行超参数搜索,可以指定学习率之类的。
让我们缩进一下。
在一个步骤中。所以你可以做的是。你可以为每个相应的学习率训练一个特定数量的vpoOs模型,这里我只对这五个不同的学习率进行网格搜索,所以我们来做这个,我们可以设置训练步骤等于测试步骤,每次都将其设置为零。
然后我们将执行训练日志,使用TF.dot.summary.dot.create_file_writer。然后我们将进行日志训练。但是我们还将添加。让我们看看。我还会添加学习率的字符串,以便我们可以区分不同的运行。所以让我们再做一次,并进行测试写入。这里我们将执行测试。
然后我们需要获取模型,因为我们想要刷新,每次都重置权重。因此,我们将执行获取模型,然后优化器是ks.optimizeims.Adam。所以我们也需要使用这个特定的学习率重新初始化优化器。你可以这样做,并且可以像这样从一些纪元中写入测试写入器。
但就像我说的,让我们对每个批次执行一次。这可能会使图表更平滑,因此我们在这里要做的是指定训练步骤,而不是纪元,然后在这里我们将训练步骤迭代增加一,这将是图表中的一个离散步骤,然后我们也会对测试写入器执行同样的操作。
所以我们得把这个改成测试,让我们看看。测试步骤。我们必须对所有这些进行处理,以确保我们不会在这里犯任何错误。我们还将将其迭代增加一。好的,让我们想想还有什么需要更改的。
我们可以减少纪元的数量,以加快速度。让我运行一下,然后我会向你展示它在Tensor板上的样子。
好的,看着这个张量板,我刚刚将训练部分分离出来,所以你可以在这里写“train”,你可以获取所有不同的模型,这些对应于不同的学习率,你也可以在这里进行一些平滑处理,这样你就可以知道损失在每个批次之间变化很大,因此你可以使用一些平滑处理来制作更好看的图表,然后,比如说。
就在这种情况下,如果我们进行比较,初始学习率应该在0.001和0.0001之间,这两个学习率之间是橙色和红色的。所以关于损失图和准确率图就是这样,你可以随意玩玩,这非常有用。那么让我们继续获取图像。所以我们这里要做的第一件事是可视化图像,可能我们要做的第一件事是添加一些数据增强,我们将使用matplotlib来绘制它。
他们想要在0和1之间的值。所以我们可以使用matpl1。
值,所以我们可以使用T F clip
。通过值,图像然后裁剪值最小为0,裁剪值最大为1。顺便说一句,如果你在想为什么会低于或高于这个0和1的范围,因为我们除以255,这应该是自然范围,但由于数据增强,某些像素值可能会低于或高于1,所以我们只是想确保最后它们实际上在0和1之间,这在后面会用到,但我马上会向你展示。
所以我们可以在这里实际移除训练部分,这样我们就可以这样处理批次,我们可以通过enumerate DS train
来迭代每个批次的XY。首先我们将创建一个图形,并创建一个图像网格。
所以我们将传入x和Y,以及类名。这里是一个我们将在这个u函数中创建的函数。我们将创建一个图像网格,然后将宽度设置为默认值。我们将做Tfsmary image
。然后我们将发送可视化图像。我们将做绘图到图像,并发送图形和步骤。
这等于步骤。因此在这种情况下,我们只会使用一个单独的写入器,就这样做。而不是使用训练步骤,我们只称之为步骤。就这样。然后这就是我们将要做的所有事情。我们将逐步迭代。
当然我们需要创建这个图像网格,并且我们需要创建这个图像绘图。我想先说有更简单的方法可以做到这一点,而我在这里所做的确实使这个图像网格的创建变得复杂,但这有助于或者说更好。
如果你想以整洁的方式呈现,使其以网格形式显示,并在上方有标签。那么这就是你想要的做法,虽然还有更简单的方法来绘制图像,但效果可能不够美观,当然我们希望它看起来不错。那么让我们开始,我首先要复制一些将在此文件中使用的导入内容。
我们首先要做的事情是,我们有,嗯,让我看看,我们定义了绘图到图像。然后我们将发送一些图形。因此,让我们先处理那个。然后我们还有另一个图像,实际上是另一个函数,我们有图像网格,发送一些数据,发送一些标签,并发送一些类名。
我将从 TensorFlow 官方教程中复制这个绘图到图像。这是从 TensorFlow 官方指南中偷来的,你可以在这里看到 URL,但基本上,它将指定的 mapplot lib 绘图转换为 PNG 图像并返回它,这个应用的图形在此调用后被关闭且不可访问,所以基本上它是在内存中将 mapplot lib 绘图转换为 PNG,然后解码为张量,接着可以发送到 TensorBoard,因此在这里我们使用 IO 将绘图保存在内存中。
然后我们关闭图形,防止它直接在笔记本中显示。然后,我们通过 image.decode PNG 将 PNG 缓冲区转换为 TF 图像。最后,我们添加批量维度。我不想过多关注这一点,我认为这并不相关,这只是一些样板代码,以确保它处于正确格式。
这是一个张量,然后这个图像网格是我们将首先创建的,因此我们将创建图像网格,这将创建这个 Matplotlib 图形,然后我们将其发送到这个绘图到图像,接着会发送到 TensorBoard。
首先,数据应该采用这种格式,因此我们需要有批量大小。HW 然后是通道。所以我们可以首先断言数据的维度为 4,我们要做的是创建一个图形,所以图形是 PLT.dot.figure 的 fig size,这只是 Matplotlib 的导入。就在这里,importpl pipeline as PLT。所以我们以 10 和 10 的 fig size 创建它,这我认为是以英寸为单位,因此可能会有点混淆。
我尝试过不同的值,这就是看起来不错的效果,所以无论如何,图像数量将是数据的形状 0,我想这对于特定的批量大小来说是特定的,我们在这里使用的 fig size,我尝试过的是批量 32,你也可以使用更大的批量大小,它看起来仍然相对不错。我在这里做的是将图像数量设为数据形状的 0,这是一种通用格式,并不特定于 32。
整数 N 为 MP 的平方根的上取整图像,因为我们想要一个好看的网格,一个正方形网格,因此网格的大小将是图像数量的平方根,上取整到下一个整数值。接着我们将迭代范围为数据的形状 0 的 I,因此对于数据中的每个图像,我们将为该图像创建一个子图。
子图的大小将是大小。大小和大小,正好是图像总数,而当前特定图像将由这个索引指定,即 i+1。该图的标题将是类别名称。
标签是该索引的值。然后我们在这里使用该索引的类名称来获取它的名称,接下来我们将做xt
,并发送一个空列表,然后我们将做yt
,并做类似的事情,最后我们将设置plot grid
为false
。
然后我们将检查数据形状的第三个维度是否为1。我们将进行绘图,并将CMap设置为PLT.dot.Cm.dot.binary
以获取灰度图。如果是灰度图,我们将这样处理;如果是RGB,我们将直接使用plot I show of data of I
。最后,看看这里的内容。
我们将返回图形。在这里我们不需要指定任何CMap,因为默认情况下是RGB。所以这里有很多Matplotlib的内容,我不想深入细节,但你能理解整体概念吧。即使你对Matplotlib不太熟悉,我认为我们正在创建一个图形,然后创建一个子图,这将是这些特定的训练图像,大小为size
,行数由我们传入的图像数量决定。
所以假设我们传入16张图像,那么网格将是4乘4,每个单元格将是我们训练集中的一张图像。现在我们有了图像网格,然后我们有plot to image
,所以如果我们回到这里,这应该可以正常工作。我们先做图像网格,然后做plot to image
,这里我们正在写入我们批次中的每一张图像。这并不是特别必要,也许你想在每个epoch时执行一次。
但这可能很有用,可以查看所有图像,所以让我们运行它。看看它的样子。好吧,在这里我们需要导入它。所以我们需要在这里做from us import plot to image
和image grid
。然后重新运行它,希望能成功。好吧,writer未定义,所以我想这应该是。
😔,Wrier dot为默认设置。
好吧,如果我们现在打开TensorBoard,我们会得到一个漂亮的格式。标签会打印在上方,正如你所看到的,这是一种正方形网格,例如这里是6乘6,然后这些最后的图像没有被任何图像覆盖,因为我们进行了密封并向上取整。但我觉得这看起来很好,这是一种可视化图像的好方法,你可以看到这里每个批次的步骤。一件事是,如果你向后滚动一次,你会看到实际上是六个步骤。
如果你在Anaconda中调用TensorBoard,你可以发送另一个参数,即samples per plugin
,这将指定你希望在此步骤滑块中显示多少张图像。例如,如果你将其指定为94。
这意味着这里的一个滑动步骤是针对一个批次,而不是像这种情况下大约 25 个批次。所以如果你对此感到困惑,这只是需要记住的一点。但无论如何,这就是我们如何可视化图像的方式。
接下来我们要创建这个混淆矩阵,这也有点复杂。但是正如你之前看到的,它会表现得相当不错,所以让我们一步一步来,再次这是启动代码。通常你会通过同时发送所有图像以及输出和 y 标签来创建混淆矩阵,但在这种情况下,我们想要在每个批次处理时更新它,假设我们有一个庞大的数据集,无法一次性发送。
我们将创建一个最初为空的混淆矩阵。所以我们将使用 MP.zeros,长度为类名。然后类名的长度,这将是行数和列数。我们将在遍历我们的批次时更新它。
所以我们将要在这里进行混淆矩阵的计算,使用的是 confusion is plus equals 函数。我们将发送输入 y 和 Y 预测,以及类名。然后这将累加到混淆矩阵中,可能会产生一些数值的四舍五入误差等。
但至少这个近似值非常好,足以获取模型学习的良好表示。然后在这个批次之后,我们将使用默认的宽度训练进行操作。我们将使用 Tf.summary.im,并指定名称为混淆矩阵。然后我们会做 App plot confusion matrix,这又将是另一个函数。
我们将发送混淆矩阵,并按批次索引进行除法,因为我们将在每次更新时获得一个具有自己概率的混淆矩阵,范围在零到一之间。但由于这是一个线性操作,我们可以按批次索引进行除法。
然后我们将得到整个 epoch 的概率平均值。当然,你知道这样做可能会导致溢出,因为你实际上是在每个批次中加一,但为了导致溢出,你需要有一个非常大的数据集。即使你有 100,000 个样本,100,000 也远离溢出。
所以这没问题,只需记住这一点,然后我们有类名。接下来我们将把这一步指定为epoch。因此,我们每个epoch绘制混淆矩阵,因为这也可能相当昂贵。好的,然后我们不必为测试集做这个,但当然如果你愿意,也可以为测试集做。
但我实际上将去掉这个。像这样,因为我们不需要那样,这样可以节省一些计算资源。所以我们现在想要去到u函数,并创建那两个函数。好的,我们首先要获取混淆矩阵。我们将传入y标签,传入Los,传入类名。
所以这里是正确的标签。这就是模型的输出。这些是类名。让我们快速处理一下,然后我们还想定义绘制混淆矩阵的方法,并将其作为输入。某些混淆矩阵,我将其称为CM,我们还将传入一些类名,所以也许首先我们想要实际创建混淆矩阵,并且为了不从头开始,我们将使用SK learn来生成混淆矩阵。
创建混淆矩阵可能会是一个单独的视频。我想。但我们将进行预测,即逻辑回归的nuy arg max,然后x是1。因此我们在这里也将其转换为Numpy。所以从nuy到Tensorflow的转换相当顺利。因此我们只需直接做nu argm,然后那将是预测结果。
然后我们要使用SK learn的matrix.confusion_matrix
来生成混淆矩阵。我们将传入y标签,传入预测结果。然后我们将传入标签,作为NP的类名长度范围。这基本上是为了确保我们得到的混淆矩阵在行和列上都与类名的长度相等,因为假设我们的批量大小为32,我们可能不会从每个类中得到一个样本,这会破坏我们的混淆矩阵。
所以我们这样做只是为了确保它的确是我们想要的大小。然后我们将返回混淆矩阵。好的。然后我们想要绘制混淆矩阵,这里我们将根据类名的数量设置大小。我们将创建一个图形,即PLT.figure,然后fig size是size, size。
我们将执行绘图,并展示混淆矩阵。我们将进行插值,插值方法是最近邻。你可以查看文档了解这到底是在做什么。我不太确定不同的插值算法是什么。
但这似乎是一个默认值,然后我们将使用CM是PLt.cm.bls。这只是让颜色变成蓝色。我们稍后会看到它的具体样子,但接下来我们将使用PLT.back.title。我们将指定混淆矩阵,然后索引将是NPR范围内的类名长度。
好的。然后我们将进行plot.do.x_ticks。我们将发送索引。这就是有多少种x值。我们将有多少个,然后可以指定它们的名称,我们将使用类名,确保它们看起来不错,并且文本不会重叠。
我们将指定旋转为45度。然后我们将进行ytics,并进行索引和类名的设置。好的。然后我们希望确保进行归一化,因此我们要归一化混淆矩阵。我们通过CM是NP.dot.around来实现。我们将使用CMm类型Float。
然后我们会通过看到总和x等于1来进行除法。我们将要做domp donuax,并指定小数位数U。这只是为了确保所有内容加起来为1。对于特定的预测,所有不同标签的和只能等于1。
所以这就是我们要做的,我们想要打印,或者说是的。我们希望得到特定概率的文本。因此,我们首先会设定阈值为CM.dot.max,并将其除以二,然后我们将用这个做一些相当酷的事情。
但你将在一秒钟内看到。我们将遍历大小范围内的I,然后进行4 J的遍历,没错。我们需要遍历每一行,然后遍历每一列,首先如果CMI J大于阈值,颜色为白色,否则为黑色。所以如果它超过某个阈值,我们将把它设为白色,因为那个单元格的背景色会相对较暗。
然后我们将把颜色设为白色,否则如果值较低,则意味着它是相对较浅的单元格或浅色单元格。某种更白的单元格,因此我们将把文本颜色设为黑色。然后我们将使用plot.do.text,指定位置为IJ,然后发送实际值,即CMIj。
我们将进行水平对齐,选择中心以居中文本。然后我们将设定颜色为color,这就是我们在这里指定的内容。好的,接下来我们将使用plot.tight.layout,这只是为了获得一些良好的格式。然后我们将使用plot.x_label,将真实标签作为x值。
然后 y 轴的标签是预测的。预测标签。同样,正如我们之前所做的。这现在是一个 matplot 图形,为了使其在 TensorBoard 中显示良好,它需要转换为张量。因此,我们可以重用该图形以生成图像,然后返回 CMm 图像。好的,现在我们可以回去,希望这现在能工作。
所以如果我们现在运行,这实际上是无法工作的,对吧,我们还需要从 Us 导入这些内容,导入 confusion matrix 的名称,然后是 plot confusion matrix,希望这现在可以运行。那么我们看看。
好吧,如你所见,它似乎在工作。当然,我们现在只运行了一次 epoch,因此我们的模型相当糟糕,这在对角线的值中得到了体现。这是它准确分类每个特定类别的概率,所以在这种情况下,飞机大约是 50% 等等。因此,我的意思是让我们增加 epoch 的数量,假设到 5,并重新运行它,然后你会看到随着 epoch 的增加,这一情况有所改善。
好的,如你所见,情况变得更好了,但模型仍然很糟糕。我们使用的是一个非常小的模型。因此,你仍然可以看到它并不完美,但无论如何,可视化似乎有效。
现在让我们转到创建图形。这将是一个猜测,稍微简单一点。那么让我们看看。我实际上不需要这些东西。因此,我们将移除这里的所有数据集内容。我们将全部删除。我们实际上要做的是使用 writer。我们将使用 TF summary。
创建。文件写入器。我们将指定日志,然后指定图形。就叫它这个吧。接下来,我们将定义一些函数。我的函数将接收 x 和 y 的输入,然后返回 Tf.nn.ReLU,然后是 Tf.matmul,然后是 x 和 y。因此,它只是在进行矩阵乘法,然后获取结果。
我们将做 x 是 Tf.random.uniform 形状为 3x3,y 也是类似的 Tf.random.uniform 三维矩阵。然后我们需要创建,添加 Tf.function。因此,自从 TensorFlow 2.0 起,默认情况下以 eager 模式执行。但在 eager 模式下实际上无法创建这些图形,因此我们需要确保它在静态图中运行。
因此,这个 Tia 函数确保函数被转换并在静态图中运行。当这完成后。现在我们将执行 Tf.summary.trace,并设置 graph 为 true,profiler 也为 true。然后我们将执行我的函数,输入我们刚刚发送的 x 和 y。然后我们将使用 writer 作为默认值。我们将执行 TF summary.dot trace export。
我们要做的名字,我们就叫它函数跟踪。😔。我们将步骤设为0,因为我们只做一次,然后是分析器。我们的目录将是。日志,然后我们不能这样做,所以我们需要这样做。只是一个奇怪的事情。我们需要这样做,然后进行图形可视化,让我们看看。
如果我没记错的话,我们还需要这样做。如果你想可视化模型,这样应该可以工作,所以我的意思是,如果你有一个模型,只需在这里返回X的模型,所以只需在这里使用Keras的顺序模型创建你的模型,然后返回X的模型,这样仍然可以工作。我想在这里做的只是给你展示一个非常简单的例子,但当然这可以广泛使用,所以如果我们运行这个,然后去TensorBoard,或者让我们先看看没有错误,是的,我们在这里收到一些警告,我不太确定该怎么处理。我是说。
有时在TensorFlow中,你会遇到错误,但如果一切正常。我不知道。我不知道该怎么处理这个。不过,我们只是看看图形,它会显示没有数据集名称训练。好吧!
然后我们有这个X和Y矩阵相乘Re,然后就是输出。有时这些图形看起来有点奇怪。我不确定为什么我们在这里有两个身份。嗯。不过,是的。所以无论如何。你可以看到我们正在做的最相关部分,然后Re,个人来说,我没有使用太多,但。
我想这在调试一些非常复杂的模型时可能很有用。但是无论如何。让我们回到代码,所以我们现在要处理超参数,这非常有用。我会说如果你想进行超参数搜索,并且可以很漂亮地可视化。
嗯,是的,我们将再次从起始代码开始,并进行修改。现在我们要修改的内容是。我们要创建一种。一个函数。我们称之为训练模型,让我们进行一个周期。然后我们将传入一些叫做H PR的内容,实际上我们需要导入这个。
首先,我们需要导入的是来自Tensorboard插件的内容。插件中的H PR导入API作为H。这只是为了H参数API。我们将其导入为H。那么让我们回到那个函数。我们将在这里做的。假设在我们的模型中,我们会复制那个模型,假设我们想在模型上玩一下。
假设我们想在这里进行一些尝试,我们就称之为密集层中的单位数量,当然你可以想象对不同值进行这样的操作等等,但我在这个例子中只使用这个。我将向你展示如何从中获取Hpm,并且假设我们也想尝试一下dropout。
所以等一下,先移除这个,然后使用某个drop rate。然后我们还想尝试一下学习率。从这个h参数中,我们将获得单位,做H参数,然后称之为H nu units。我们将获得一个drop rate,当然。
我们还没有定义这些,但我们稍后会进行。因此我们将获得H dropout,然后我们也将获得学习率。这是Kaos optimizeimrs.adom。学习率将设置为学习率。我们也需要获取学习率。这来自H的H学习率。好的。
现在我们有了这些,我们想要的是,哦等一下,那是学习率优化器。那是优化器,我们使用的是从H primes得到的学习率。然后我们使用这个单位和这个drop rate来创建模型。然后我们实际上要创建一个训练epoch,我们将用这个来进行。
所以我们要复制这个并放到这里。说这个功能,不,不是这个。这是训练模型1个epoch。这将训练1个epoch,所以我们可以粘贴它。这就应该是这样。然后我们要写入Tensor board,所以写入TBb。我们将通过指定它们的运行目录来实现。
由于我们进行许多不同的运行,使用不同的学习率和drop rate等。我们将首先指定日志,然后是训练,然后我们将进行。加上单位的字符串。然后我们将进行单位,所以这只是一个整数。然后我们将进行单位,并且我们将使用下划线来使其可读。
然后我们将进行drop rate的字符串处理。然后我们将进行drop out。然后我们将进行学习率的字符串处理。😔 然后我们将进行学习率。那么这看起来可能有点奇怪,这只是为了不让一行太长,所以这样看起来还不错。我们可以轻松阅读它。当我们有运行目录时。
这个将根据单位drop rate和学习率而有所不同。我们将进行w.T F点summary,点create file。Rer of that run directory。我们将其设为默认。所以请注意,我们没有使用train writer。我们创建文件写入器时会写入,因此这对每个人来说都是不同的。
然后我们将进行h参数的h参数。我们将准确性定义为准确性指标结果。所以这将记录此运行中使用的值。然后我们有准确性。然后我们有Tf摘要做标量。准确性。
然后我们将传入那个准确性,我们只会进行第一步。之后,我们需要重置对称状态。好了,现在我们可以。我想我们可以删除这个获取模型,因为我们为每个人创建了模型。然后我们就不需要那个。😔,我们不需要Vpo的数量,或者是的,我们可以。
我们可以有纪元数量,但我实际上会将其仅运行一个纪元。因此我要删除那个。然后我们想要有损失。我们想要有优化器,我们想要有对称的。然后我们不需要那些,因为我们每次都已经用新方法写了它。
然后我们将指定H nu单位。我们将进行H。t H每个Ram。我们将做nu单位。我们将称之为这个。然后我们将进行Hp dot离散。我们将传入32,64,128。这意味着我们选择该特定密集层中的单元数量为32、64或128。
所以我们在这里有点像使用网格搜索,如果你熟悉超参数搜索,你可能知道使用随机搜索更好。我不打算解释原因,但本质上使用随机搜索更好。当然。
你在这里需要做的是,首先可能使用随机搜索对值进行随机抽样,然后将这些值放入离散值中,但无论如何,这里只是为了说明,我用一种非常简单的方式来处理。以离散步骤进行。
以网格搜索的方式进行,然后我们将进行H dropout,做H dot H PRm。我们将传入dropout。我们将做HB。t离散,并指定0.1、0.2、0.3和0.5,所以假设我们有这四个值,然后我们有HP学习率。我们来做HB进行H参数。它被称为学习率。再一次。
我们将HP出离散。嗯。然后1 e minus3,1 e minus5和1 e minus5,4和5。所以无论如何,你在这里还可以做的是,有一个叫做H dot int间隔的东西,我认为它是实际间隔。然后你可以从中抽样。但是。我真的看不出这些的意义。我只是自己抽样,然后找到值,然后将其作为离散值放入。
所以我认为这在一般情况下也会很好,但可能有一些我并不熟悉的用例。因此,当我们有这些时。我们可以在这里更改,我们不会使用之前用过的正常训练循环。我们要做的是使用HP学习率的完整学习率。
域值。我们将以 H nu 单位进行四个单元的计算,这些域值。还有在 HP dropout 中的速率。域值。通过这种方式,我们只是在这些离散值中迭代贷款利率单元。然后。我们将仅运行一次训练周期。但否则,你会在这个地方为 epoC 的范围内进行多次训练。
但是我们只会进行一次。所以我们将 h 参数等于一个字典。然后我们将指定 H 学习率等于一个学习率。那么这里有什么问题呢?
😔,是的,需要使其不等于这样,然后 Hum 单元。我们将其指定为单元。HP dropout 仅仅是速率。好的。然后我们将调用那个函数,也就是训练模型 1 个 H 周期。所以实际上。这一点是你不能。在这里进行多次训练,因为那样会。
稍微重置一下。是的,你需要做的是修改这个。所以你需要在这里添加一个循环。我想象中是这样的,但是。无论如何。这只是为了说明如何在不同的超参数下进行单次训练周期。这可能需要一段时间才能运行,所以我会运行它,希望我们不会遇到任何错误。
好的,所以我们在这里获得 H 参数,我会稍微放大一点,你会看到它随着数据点的增加而更新。好的,现在我们得到了所有这些超参数,这可能看起来有点混乱。
所以你可以做的就是,看看我能否做到,你可以指定某种。前几个。最高的准确性。在这种情况下,我们可以看到前几个对应于高单位数,基本上较大的模型在学习率为 0 的情况下总是更好。
001,所以我们选择的这些中最高的那个,然后最好是选择最低的 dropout 级别,这样做是因为我们是在训练集上进行的,实际上你应该在验证集上进行,以确保这是正确的。但再次强调,我们只是想演示这在 Tensor board 中是如何工作的。
所以使用 H 参数就到此为止。现在我们想要继续做投影器,而投影器非常酷且可以非常有用,所以让我们转到那个文件,其实我们不需要这些东西。所以我要删除模型,并且我将删除这里几乎所有的内容。
我们其实不需要。任何东西,真的,我们只需要一个批次,一个 X 批次,一个 y 批次。我们可以通过使用 S strain 的下一次迭代来实现。然后我们将把它发送到某个函数。我们将创建一个绘图到投影器的函数。我们将发送 X 批次,并且我们将再次发送 X 批次。我稍后会解释这一点,然后我们将发送 Y 批次。
我们将发送类名。我们还会发送一些日志目录。我们就叫它Proge,像投影仪那样。因此,我们在这里发送exppat两次的原因是,这个我们要创建的函数显然会接收一些数据点,对吧。
这些图像。它将接收一些标签,但也会接收一些特征向量。通常,你会将你的图像、数据发送到模型,然后从模型中获取一些特征向量,特征向量可能是任意维度的数字。
然后这个投影仪将接收这个特征向量,并试图将其投影到图像上,看看哪些特征,以及使用像TS&E或PCA这样的算法进行投影,看看我们的模型认为在特征向量所描述的相似组中有什么。
而我们在这种情况下要做的是不将其发送到某个模型。这意味着我们将使用图像本身。我们将重塑图像。将其变为一个长的特征向量,包含该图像的像素值。这将是我们的特征向量。同样,正如本教程中大多数内容一样,它是为了说明如何使用Tensorboard,因此这就是为了简化我们的操作。
但通常这将是一个特征向量,为了让你清楚,你会得到特征向量。你会用Xpat做模型,你会得到一个特征向量,然后在这里你会调用那个特征向量。现在我们不会这样做,正如我所说,我们需要做的就是创建这个plot to projector。在我忘记之前,让我们从U中导入plot to projector。
然后我们将再次使用这些u函数。我们需要两个东西。首先,我们需要一个称为创建精灵图像的东西,精灵图像本质上是我们将提取的图像,输入或X patch,输入的X patch。我们将创建一个精灵图像,它将包含我们发送的那个批次中的所有图像。让我看看我能否举一个例子。
所以emnist的精灵图像是这样的,或者说这是时尚emnist。所以就在这里。这是一个精灵图像。正如你所看到的,这是一组许多、许多不同图像的集合,集中在一个单一的图像中。这将对发送到Tensor board非常有用,这样我们只需发送一张图像,而不是多张。因此,这就是我们首先需要做的。我不会这样做。
我打算直接偷用它,我会复制粘贴。所以这段内容是从这个人那里偷来的。安德鲁·B·马丁。是的,你可以阅读一下,我们就要使用它。我不会专注于它的功能。基本上,它创建了这个精灵图像,并进行一些重塑和处理,添加填充以获得这个图像。
我们将创建这个定义投影到投影仪的函数,我们要传入的是 X。就是我所说的特征向量,Y,类名。我们将指定一些日志目录。默认情况下。我们就称之为默认日志轨迹,然后我们还将获得 Me 文件。
我们将指定元数据。TSV。好吧,这样会让我们用它们的目的更清晰。因此首先,我们需要确保 X 维度的数量为四。因为我们将假设它的形式是这样的,我们有批量大小。
我们有高度、宽度和通道。非常令人沮丧的一点是,如果你已经有一个包含此日志目录的目录,你是无法运行这个的。因此,我们将进行检查,如果 OS.path 是目录。也就是说,如果日志方向中存在目录,则意味着那里有一些旧的投影仪文件。
接下来,我们将进行 shuttle。移除 3 和移除树的日志目录。然后,我们将创建日志目录。基本上,我们从头开始清理。所以我们将创建一个新的、干净的、全新的文件夹。好吧,然后我们将继续。
我将指定 Sprites 文件,它将是日志目录的操作系统路径连接,然后我们将称之为 sprite_sub.png。接着我们将生成 sprite 是输入数据的创建精灵。然后我们将做 CM M V2,写入精灵文件。精灵文件和精灵。
好吧,然后我们想要生成标签名称。我们将通过将标签设置为 Y 的类名来实现。因此每个训练示例的相应整数目标值,I 是训练示例。然后我们将在 Y 的形状范围内进行循环。
然后我们将写入元数据 TSV 文件,这将用于在投影仪中绘制标签。所以我们将打开操作系统路径连接,日志目录和元数据文件。这就是我们所称的,然后我们将写入这个文件。我们将以 F 的方式打开它。因此,对于标签中的每一个,我们将进行 Ft 写入。
我们将进行换行,并使用点格式标签,全都吗?
所以我们只会传入标签,然后我们将换行,这只是我们想要的结构张量。现在我将做的是处理特征向量。如果特征向量的维度不等于 2,那就意味着这不是一个特征向量,比如说。
就像我们现在所做的,我们两次发送 exppat。所以如果是这样的话,我们要做 print。然后我们要看注释。特征向量不是一个形式批次逗号特征。然后我们可以进行重塑,尝试把它变成这个形式。然后我们要做的是特征向量。等于 Tf do reshape。然后特征向量。
然后。特征向量 dot shape0,然后是 -1。好的,然后我们要做。特征向量是 T F 变量。所以我们只需将其转换为 T F 变量。然后我们要做 checkpoint 是 Tf train dot checkpoint 的嵌入等于特征向量。接着 checkpoint dot save,然后 OS path 显示日志目录。
然后我们将指定 embeddings. ckKP。嗯。基本上我们将特征向量保存到日志目录,然后嵌入那个 CKPT,这就是 TensorBoard 想要的名称。然后我们将设置一个配置,这个配置将写入 projector。
所以我们要配置的是 projector dot projector config。嵌入是 config do embeddings add。然后我们要做 embedding dot tensor name,我们要指定嵌入。然后我们需要在这里做,做 dot attribute。然后是变量名变量值。接着我们需要做嵌入的 met data path。
我们需要做 meta file。是的,如果你觉得这有点笨拙,我的意思是。代码有点。要做这个有很多代码。我不会太关注具体的 Pythtor 代码,例如这在一行中完成。字面上是一行,但在 TensorFlow 中这有点困难,嵌入投影器通常用于投影嵌入,这没错吧。
当我们为图像这样做时,我们需要以这种。非常复杂的方式来做。但无论如何,这就是我们的做法,如果你发现更好的方法,请留言。但这是我目前找到的最好方法。然后我们将做嵌入。sprite。图像路径,然后我们将做 sprite。p 和 ng。所以我们只是在指定图像路径。
然后我们正在做嵌入 thatt sp 单图像维度扩展。然后我们需要指定 x 形状为 1,接着 x 形状为 2。所以我们指定了高度和宽度。最后,我们必须做 projector,visualize embedding。我们要发送日志目录,然后是配置,这样就好了。
所以现在希望如果没有错误的话。这应该可以运行。
而这并不正确。😔。
所以错误是当我们对图像进行归一化时,当我们创建这些精灵图像时。我们需要确保不除以 255。如果我们重新运行它。我们现在应该能够获得正确的像素值。
正如你所看到的,我们有这些图像,我们可以看到那是一只狗,然后那是一艘船。我认为那是一匹马,让我们看看还有什么。是的,反正你可以玩玩这个。我们这里的图像很少,所以你可能想做的是将批量大小更改为500。
如果我们重新运行,这个速度实际上很快。
好吧,所以我认为你在这里需要做的,如果你重新运行,你需要做。
有点像一个新的。所以如果我们现在重新运行它。
然后我们在Tensorboard中再次打开它。
有时这有效,有时无效。但现在它有效。好吧。现在我们得到500张图像,然后你可以使用T-SNE和PCA,这也是我尝试制作的。
通用,按我们可以将其替换为Mist的方式,我们可以直接运行它,然后如果我们现在检查它。
好吧。是的。那么当然我们无法进行数据增强,所以让我们完全移除数据增强,但我们无法将已经是灰度的东西转换为灰度。不过除此之外,我认为这应该是通用的,我们可以将其更改为Mist。然后你将能够进行投影。
你喜欢的任何类型。
好吧,等等,还有一件事,实际上。是的,这是最后一个文件。但我也想在TensorFlow Pro中展示另一个东西。TensorFlow Pro自TensorFlow 2.2以来可用,如果你跟着这些教程,你会知道我使用的是TensorFlow 2。
我在GPU上运行,因此我无法使用它,实际上你需要一个GPU来运行。
所以我所做的是。
Google Colab,这与他们的官方教程非常接近。但实际上,我将逐步进行,也许你在未来观看这个视频时,你可以轻松安装TensorFlow 2.2及以上版本与Anaconda。所以你可能可以做到这一点,并创建一个新的文件。
所以你不需要在Google Collab上执行这个,但这样做只是为了说明。首先,我们在这里有一些导入,然后我们需要执行这个Pip安装Tensorboard插件profile。我们正在导入Tensorflow,在这里我们确保我们在GPU上运行,正如我所说的。这是一个要求。然后TensorFlow,我认为它在CPU上也可以工作,但某些功能需要。
有一个要求是你必须在GPU上执行。所以我们在做tensor数据集。我们正在导入MNIST,非常类似于你在这个教程中看到的。然后我们对图像进行归一化,进行一些映射,然后批处理。接着我们创建一个非常简单的模型并进行模型编译。
然后我们创建一些日志,并生成这些日志。这是来自Tensorflow官方教程,使用当前时间的日志,这种方法非常聪明,因为每次运行时会生成一个新的日志文件,因为时间发生了变化。所以这是一种很好的避免错误的方法,而不是以项目的方式删除文件夹,如果存在的话。这样做可能更简单,我认为。好吧,然后我们有tensor board回调,我们只是在创建它,他们所做的就是执行这个profile批次,他们执行500到520。所以这是使用Tensor board回调,但如果你有自定义循环,也有多种方式可以做到这一点。
如果你想了解更多如何实现,我将引用这个官方教程链接在视频描述中。然后我们只是在做模型拟合,并再次使用这个tensor board进行回调。
然后如果我们扩展Tensorboard的负载。我们打开Tensorboard并使用日志de equal logs运行它。然后我们可以得到这些不同的东西,所以我们得到了一个概览页面。也许我需要重新运行这个。我想是的,所以我们将进行工厂重置运行时。
然后我们将运行所有内容。所以然后我们可以打开分析器,我们将得到一些不同的工具,我们有一个概览页面,老实说,我还没有详细查看这些。但我会给你展示它们的概述,这可能是最容易查看和理解的地方,他们给出了所有不同部分的摘要,所以你可以看到训练的所有不同组件的时间。
你还可以看到不同的东西,放置让TF操作在主机和设备上执行的数量。我不太确定这里主机和设备之间的区别是什么。所以再次强调,我不是性能分析的专家,但也许有人可以评论这个区别。不过,你可以在这里看到的其他内容包括设备计算精度,如果你使用的是16位。
计算中有多少百分比是在16位上完成的?然后,你可以看到一些推荐,这个图表也相当有用。比如说,你可以看到输入高度输入绑定,85%在等待输入。
比如说,现在我们知道可以做点缓存,我们还能做什么呢?可以进行非并行调用的自动调优。我们可以对两者都这样做。所以没有。😔,并行调用是自动调优,然后我们可以做。缓存。然后我们还可以做点预取,可以进行自动调优的点预取。
我们可以再次发送自动调优,是的,我想我会重新运行这个。所以。运行时间,运行全部,我们将看看输出是否有任何差异。在TensorFlow分析器中,顺便说一下,这个分析批次是在两个批次之间,这里说明你想要分析的内容,所以在这里我们想要分析从500的索引批次到520的索引批次,所以我们只是对20个批次进行分析,如果你做得太多批次,可能会出现内存不足的错误,因此他们建议只做20个或10个批次,并且最好不要放在初始批次中,而是在训练中间进行,因为初始化某些东西可能需要时间。
好吧,让我们再看看分析器,看看是否有什么不同,现在我们可以看到你的程序是适度地输入绑定,因为160%在等待输入。但这比我们刚刚的85%有了很大的改善。那我们再看看你还有什么。
实际上,你知道吗,你可以自己尝试一下,你会看到。我还将参考一个TensorFlow的官方教程,值得深入研究这个TensorFlow分析器。但是,是的,举个例子,你可以看到矩阵乘法占用了25%。这是操作时间中最大的一块,然后还有不同的东西,比如追踪查看器,你可以获得一个非常。
低级别的视图,查看CPU和GPU上执行的所有操作,确切地看到哪些占用了时间。所以这是一个非常非常酷的工具,这更多是一个入门介绍,展示如何让它运行,是的。所以就是这样。这将是一个非常长的视频。我可以看到这一点。希望这个视频至少在理解TensorBoard方面是有用的。是的。
非常感谢你观看这个视频,希望在下一个视频中见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P18:L18- 图像的自定义数据集 - ShowMeAI - BV1em4y1U7ib
在这个视频中,我们将学习多种高效加载自定义图像数据集的方法。也许你已经在线抓取了这些数据,或者自己创建了它。因此,我将向你展示三种不同的方法,这些方法都是高效且良好的,但其中一种可能更方便,具体取决于你的数据集结构。
第一个方法是我们将图像放在不同的子文件夹中。通常我们会有一个好的老MNT,在这种情况下,我们有01到9的文件夹。如果你查看其中一个子文件夹,我们只有五张图像,但当然你可以想象有很多张。在这里,我们有所有与该类对应的图像,对于第九个文件夹,我们有数字9,当然在这种情况下,标签与类名完全相同,但你也可以想象其他情况,比如说猫和狗的数据集,那么你只需将0替换为猫,然后再为狗创建一个文件夹。在这种情况下,标签正好就是类名。因此,进入代码,这些是我们将使用的所有导入。
我将向你展示两种加载此数据的方法,因此我们先指定图像高度,图像高度将是28,图像宽度也将是28。然后我们设定批处理大小为2,因为我们只有这么少的示例。同时,我们还将创建一个非常简单的k序列模型,只是为了演示这能工作,并且我们可以对这个小数据集进行过拟合。现在让我们进入第一种方法。
我们将使用来自目录的数据集。因此,我们要做的是将Ds train作为Tf ks,处理这个图像。来自目录的数据集。首先,我们要指定图像所在的文件夹,或者说子文件夹的位置。在这个例子中,它位于data中,然后在Mist子文件夹下。
然后我们将进行标签推断。这意味着标签是根据子文件夹的结构按字母顺序推断的。接着我们将指定标签模式为整数。这里有不同的选项,但整数是最常见的选项,你也可以使用类别或二进制,这意味着这将是一个类别向量。所以基本上这会用于一热编码等等。
然后你还可以发送一些叫做类名的东西。所以在这种情况下我们的类名将是 0,1 到 3 等等,这样理解是对的。但假设我们在这里替换 1 和 0。这意味着索引 0 实际上代表数字 1。但是,当然,这会有点混淆。
所以让我们把那些改回去。然后我们可以指定颜色模式。在这种情况下。我们要指定灰度。你也可以在这里指定 RGB。然后你指定批量大小。假设是两个。我们有参数。是的,我们这里有批量大小等于。所以我们来做批量大小。将是两个。
然后我们可以做图像大小,将是图像高度和图像宽度。它会重新调整大小,如果不是这个尺寸。然后我们将设置 shuffle 等于 true,以便我们获得随机顺序。然后我们可以指定种子,如果你想要的话,这很重要。
假设你将其分为验证集和训练集,并且每次运行时希望得到完全相同的训练和验证集,那么设置种子是很重要的。然后我们也可以做类似验证拆分的事情。让我们将其设置为 0.1。
所以 10% 的图像将会在验证数据中。然后为了确保这是训练,我们可以指定子集等于训练。
训练。😔 然后我们对验证所做的只是简单复制粘贴所有内容。
然后我们首先将名称更改为,比如说,D validation。然后在这里我们会将其拆分为验证,这样它将随机拆分为原始数据的 10% 的验证数据,存放在子文件夹中。
现在当我们使用来自目录的这个图像数据集时,它将会是一个 TensorFlow 数据集格式,现在我们知道该怎么做来自之前的视频。假设我们想做一些数据增强,那将是相当简单的。
我们将像在数据增强教程中那样做,给我一个简单的例子。我们会使用图像是 Tf 图像随机的 亮度,然后让我们传入 X。指定一些最大增量。然后我们会返回图像和 Y。所以这只是一个非常简单的数据增强。我们会做 DS S train 等于 D Strain.dot map 然后 augment。😔
然后假设你想要训练这个。你会在范围内进行四个时期,我不知道,10 或你选择的时期数。所以让我们明确一下。这是为自定义循环而做的。然后你会对 S train 中的 x 和 Y 进行操作。然后你会进行训练。但现在我们先不深入这个,但我们在之前的教程中已经讨论过了。
当然,如果你想要使用model.dot compile,那也是可以的。所以你只需要,让我复制一下,这样我们就不必在这上面花费不必要的时间。所以再一次,这些在之前的教程中都有介绍,但在这里我们用Adam优化器和稀疏分类交叉熵来编译模型,然后我们用model.fit进行10个周期的训练。假设我们只需运行这个,我们可以在这里看到它找到50个文件,然后使用其中45个进行训练,而验证使用其中5个。为了明确,这45个中没有任何一张图片会与这5个用于验证的图片相同,因此它们是独特的,我们没有在验证数据上进行训练。
好的,然后我们可以看到每110个框,我们有100%的训练准确率。这意味着我们对这45个训练样本过拟合。好的,这就是方法一。这个方法很好。然后对于方法二,我们将使用图像数据生成器,然后从目录中流式传输。我们首先要定义这个图像数据生成器。所以我们要做的是data_generator=ImageDataGenerator,我们在顶部导入了这个。
所以我们在这一行导入了这个。所以我们要做的是图像数据生成器,首先,我们将指定重缩放,并将其设置为1/255。我们这样做是为了确保它是浮点数。我们将通过255进行除法来标准化图像,然后我们可以在这个图像数据生成器中指定很多数据增强。
所以我们来举个例子,我们可以做旋转范围,并且你可以传入很多不同的参数。我会把文档部分放在屏幕上,让你可以看到,但实际上有很多,所以比我现在展示的要多。
然后你可以做像缩放范围这样的操作,假设是0.99到0.99。这将意味着缩小1%,然后在这个范围内再缩小1%。但是这将是随机进行的。所以,我的意思是,这非常,非常少,让我们至少设定5%。然后我们可以进行水平翻转,并将其设置为false。
我们不想翻转数字,这会毁掉其中的一些。因此我们也可以进行垂直翻转。默认情况下,它们也是false。我只是展示一下你会怎么做。你可以指定更多内容,比如数据格式,我们可以设置通道为最后。这是TensorFlow希望的标准方式。
但是如果你愿意,你也可以先有通道。然后你也可以像我们之前那样指定验证拆分。不过我们现在就将这个设置为0。然后D类型将是TF float 32。
当我们有数据的图像数据生成器时,我们将构建这个训练生成器,因为到目前为止我们尚未为任何图像指定目录。所以现在我们只是指定了数据处理方式。因此我们所做的就是使用 datagen。通过目录流动。
所以我们通过目录从这个数据生成器流动,在这个图像数据生成器对象上。然后在这里我们指定数据,然后再指定子文件夹,然后是目标大小。我们将指定图像。图像高度,图像宽度。然后我们指定批大小。假设批大小为二,颜色模式为灰度。
但你也可以将其设置为RGB,类别模式将是稀疏的,这样做是因为我们希望它是一个表示那一个的整数。我们不想要独热编码。然后我们可以再次进行随机化,我们希望数据被随机化,然后我们可以做子集训练,在这种情况下,由于我们将验证分割设置为零。
这将是整个过程,但你可以像之前那样复制这个,然后指定验证生成器,然后在这里指定验证。所以如果你在这里使用验证数据,你将只需复制粘贴所有内容,然后指定子集为验证。假设你将它们放在不同的文件夹中,你将有一个训练文件夹和一个验证文件夹,你只需在这里更改文件夹,也许你不想进行数据增强,因此你还需要指定一个新的数据生成器。
但对,所以我们将指定 see,这在我们希望不同运行得到相同结果时很重要。然后,好的。这就是实际生成器的内容。让我给你展示一个示例。我们来做一个训练循环。让我们只是执行传递。
但在这里你可以指定一个训练步骤。然后我将首先向你展示自定义循环。这与我们之前看到的稍有不同。所以假设在我不知道的范围内,再做10次或者你选择的训练周期。我们需要在这里计算批次数。因此假设我们从0开始。
我们将执行4 x 和 y 在 D S 训练中。我们将通过增加批次数来迭代一次。现在我们已经处理了一个额外的批次。我们将步进一次。然后我们将进行训练。因此,我们将在这里调用训练,并且这在自定义循环教程中,如果你对此不熟悉的话。
然后我们要检查如果批数大于等于25。因此基本上如果等于25。我选择25的原因是因为那是我们的数据集长度,或者更具体地说,是我们的训练数据集长度除以批大小。所以如果是这种情况。那么我们现在已经遍历了整个数据集,我们需要中断。
我们需要中断的原因是因为我们有一个生成器对象,如果不中断它将永远运行。所以这是你如何指定自定义训练循环设置的方式。让我复制一下代码。节省一些时间。让我过一下,如果你要进行模型编译。是的,我们重新进行模型编译只是为了重置优化器状态。
然后我们将使用稀疏分类列度量准确率,这里没有什么奇怪的,然后当我们进行模型拟合时,我们将发送我们在这里构建的训练生成器,然后进行每个时期的步骤,与这里的步骤完全相同,如果批量数量为25。那么每个时期的步骤是25,verbose设置为2,这很正常。
如果我们有一个验证生成器,我们会将验证数据设置为等于该验证生成器。然后验证步骤将与每个时期的步骤类似,即验证集的长度除以批量大小。好的。这希望能为你提供两种不同方法的清晰视角,假设数据是以子文件夹的方式结构化的。
第二种你的数据集可能结构化的方式是,你将所有图像放在一个文件夹中,然后有一个对应的CSV文件,CSV文件告诉你文件名和标签。例如,在这种情况下,它说明0_1 JPEG是目标标签,所以数字是0。
标签是0,然后对文件夹中的所有图像都这样处理,并给出所有对应的标签。所以如果这是数据结构化的一种常见方式,那么我将告诉你该如何进行。接下来是代码,这些是我们将要使用的导入,我想这没有什么奇怪的。我们要做的第一件事是指定目录,哦我的天,目录是数据,然后是Mmunist images CSV,这就是我决定的名称。我们要做的第一件事是使用pandas读取CSV以创建数据框。
然后我们将使用pandas读取CSV文件。我们将指定目录,然后进行。然后我们将添加train.csv。现在我们有了CSV文件,我们可以处理文件路径。我们可以创建数据框,然后从该列中获取,记住我们称之为文件名的那一列。
然后我们可以处理这些值。这将给我们所有的正确结果,让我实际打印一下。这样会更清晰。我想。所以,像这样。哦,文件路径。好的,正如你所看到的,我们基本上得到了所有文件名的列表,在这种情况下,它们格式很好。你知道。
你在这里有标签,然后你有那个的索引。所以这是 digit0、digit0、digit1,依此类推。不过,不管怎样,我们有文件路径,我们可以获取标签。我们可以通过做几乎相同的事情来做到这一点,但我们做标签,然后我们做 dot values。现在我们有了文件路径和标签,而在这种情况下,标签将是整数。
然后我们做的是 Dtrain 是 Tf dot data do data set dot from tensor slices。好吧,所以我们做的是发送文件路径。然后是标签。好的,我们这样做是因为在这个列表中,第一个值将等于这个标签列表中第一个元素的标签。因此我们使用 from from tensor slices 将它们映射在一起,类似于你在 Python 中使用 zip。然后我们做一个读取图像的函数。
所以我们发送图像文件,也发送标签。我们首先做的是 TF do o do 读取文件。所以我们将从图像文件中读取那个文件。此外,我们需要先指定目录,然后添加图像文件。对吧。
我们正在读取那个文件,然后我们将做 TF dot image dot decode image。接下来我们将发送图像,通道设置为 1,因为我们有灰度图像。然后我们将 D type 设置为 Tf floatat 32,然后我们只返回图像和标签。为了说明,让我也给你展示一下,或者说不展示你将会。
你可以定义增强。如果你想要数据增强,你需要图像和标签。然后,我想这里是数据增强,但在这种情况下,我们只返回图像和标签,然后你会像之前一样做映射。所以 DSre dot map,我们会发送给读取图像,然后你知道的 dot map augment,然后我们可以进行两个的 dot batch。好的。因此,现在我们有了 Ds train。这就是加载数据的全部内容。
我只想给你展示如何为训练设置,它非常基本。我们将做 for poC 在 10 的范围内。然后我们将做 4 x 和 Y 在 DS S train。因此我们将在这里训练。在这种情况下,我们只会 pass。让我们做打印。现在,让我们只做 pass。好的。那么让我复制一下,给你展示它是如何工作的。
这里我们有与之前看到的相同的模型,简单模型。然后我们有 model compile。接下来是 model fit。所有这些在之前的视频中应该非常熟悉。然后如果我们运行它,我们可以看到我们很快就过拟合了,因为图像太少了。但这正是我们所期待的。这就是方法。
希望这能给你一个很好的方法,展示如何做到这一点。
好的,第三种方式是如果你将所有图像放在一个单独的文件夹中。因此在这种情况下,我们没有CSV文件,只是将所有文件放在一个文件夹中,但我们假设这里有某种良好的格式,以便我们可以通过文件名解释该图像的标签。因此在这种情况下,正如我们之前所说,首位数字代表图像的类别,第二个值只是索引,因此我们实际上可以仅通过文件名进行处理。
我们可以解释该图像的标签应该是什么。
所以进入代码,这些是我们将要使用的输入,我们还将使用Pathlib
。它在标准库中,我将在稍后给你展示我们将用它做什么。因此,让我们开始指定,我想,我们将批大小设置为2,然后图像高度为28,图像宽度为28。接下来我们将指定目录。
也就是数据,并且仅限于EMNIST图像。因此首先,要创建TensorFlow数据集,我们将执行Ds_train = TF.data.Dataset.list_files
。然后我们将执行一个字符串,在这里我们将指定使用pathlib
。所以不深入探讨,我们使用pathlib
是因为这是list_files
希望的默认目录格式。
所以我们将使用pathlib.Path
,然后获取目录。接着加上.jpeg
,好的。所以它基本上会找到该目录中以.jpeg
结尾的所有文件。好的,那么你接下来要做的是定义一个处理函数。
给定文件路径,我们需要处理图像,就像我们在之前的文件中看到的那样。因此,我们将定义处理路径。我们会发送文件包。然后我们将使用TFIO.read_file
读取文件路径中的图像。接着我们会进行TF.image.decode_jpeg
,然后通道设置为1。然后,标签将取决于图像的文件格式。
所以这对于每种场景都是不同的,我只是给你展示一种方法。因此这里的标签是TF.strings
,我们将执行TF.strings.split
,我们将使用文件路径,然后指定分割。所以在这种情况下,我们是按路径分隔符分割的,我认为它被称为,然后在我们的情况下。
也许我可以这样做。因此对于x
和y
在S_train
中,我可以执行Y.print
。Y.TF.strings.split
。而且或者说,我们只是有一个文件路径,所以文件路径。我们将通过这个来分割文件路径。你将看到它的样子。通过这种方式,我认为你可以更容易地跟随我所采用的逻辑。所以这里我们有数据。
仅限于emmin图像。然后我们有这个。当然,这里是关于文件的重要信息。那么我们要做的是取这个列表的第二个索引。我们将取这部分。在我们的情况下,这取决于您的数据集,但在我们的情况下,我们可以直接取这个并将其转换为数字。
那么我们如何做到这一点呢?让我们看看,我们可以做label是Tfstrs.substr
,从label位置零开始,长度为一。如果您的类名称长度不一,您可以再次分割,例如,如果您有像猫这样的东西。
狗,马之类的,如果这两者的长度不同,您需要以某种方式进行分割。但这只是处理字符串的方式。然后label,我们可以使用TF strings do2 number
,传入label,并且我们也可以指定输出类型为TF in 64。所以在这种情况下,我们有处理过的图像和标签。那么我们要做的是DSstrain
是DSstrainin
。
映射。然后我们只需做一个处理路径。接着我们会进行批处理并传入批量大小。好的,我将再次复制模型,确保它能正常工作。因此,我们有,您知道的,之前的简单模型。我们模型编译与之前相似,模型拟合,并传入D S train
。
所以让我们运行一下,确保它能正常工作。哦,对了。这里我们还需要取index2
。所以让我们重新运行一下。好的,我们看到在tiny buck之后,我们将获得100%的训练准确率。非常感谢您观看这个视频,这里介绍了三种加载自定义图像数据集的方法,希望您觉得这个视频有用,期待在下个视频中见到您。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P19:L19- 使用 TextLineDataset 自定义文本数据集 - ShowMeAI - BV1em4y1U7ib
大家好,欢迎回来观看另一个视频。在这个视频中,我们将看看如何使用 Tensorflow 的文本行数据来加载我们自己定制的文本数据集,这个数据集可能是我们项目中正在使用的。让我给你展示一下我们主要在这个视频中使用的数据集。这个数据集,顺便说一下,如果你熟悉的话,是一个情感分析数据,我们会得到一条电影评论,并且我们应该判断该评论是正面还是负面。
好的,例如在这个案例中,我们再次看到,科斯纳先生将一部电影拖得比必要的时间更长,然后继续。此外,我们还有一列用于标签,标识是负面还是正面评论,然后我们有它是属于测试集还是训练集。
需要记住的一件事是,这个数据集实际上也包含无监督的评论。所以在清理和过滤这个数据集时,我们要考虑这一点。
我想说的是,每个数据的结构都将有所不同。但我认为,向你展示如何处理这种特定数据,使用文本行数据将使你理解处理文本数据的方法,这种方法可以扩展到许多不同种类的数据。在视频的最后,我还会向你展示一些在处理与这个数据集结构不相似的数据集时的想法。让我们开始吧。
好吧,让我们开始创建一个文本行数据集。所以我们将进行 Ds train 是 TF.dot.data.do.text line data set。我们将传入我们刚刚查看的 emdb.csv 文件。如你所见,这个文件将包含来自训练集和测试集的示例。
所以我们可以创建另一个 T 测试,作为 Tf 数据文本行数据集的 imMDb。cv。哦,IMDb 的 CSV,然后结束引号。所以我们在这里要做的是,例如,对于 Ds train,我们将尝试过滤出所有属于测试集的示例,反之亦然,对于测试集,我们将尝试过滤出所有属于训练集的示例。在做任何事情之前,了解这一点是好的。所以我们将对 Ds train 中的每一行进行处理,并打印出这一行。好吧,如果我们这样做,它会按顺序打印每一行,因此我们可能不想这样做。
我们可以先执行dot skip1
,这将跳过描述所有列的第一行,然后我们可以执行dot take
,我们只需执行dot take 5
,这意味着我们将仅获取五个示例。那么让我们看看,运行一下看看结果如何。如您所见,我们得到第一个示例或索引01,然后得到评论。
我们获取测试集,然后得到负面评论。我们想要的是这个,我们可以通过printf.string.split
将其分割,然后用逗号分隔,这实际上会将评论也分割。那么我们可以做到这一点。
为了避免这种情况,如果我们在这里传入一个参数max split = 4
。那么它将分割这个,这个,这个,这个,然后只会将剩下的评论分割一次。因此,它不会继续分割评论。我们可以重新运行并看看效果如何。
如我们所见,现在它在单行上执行这个操作。好的,所以我们想要的首先是测试集,对吧,这将是这里的第一个索引。因此,我们要做的事情是创建一个函数,称为filter train
,并传入一行。我们要做的第一件事是分割行,并执行TF string.start split
。
开始分割行,用逗号分割。然后我们可以发送max split = 4
。所以首先我们可以看看那个特定示例的归属,我们可以称之为data belonging
。所以这可能是训练集或测试集。我们将通过split line index1
来实现。
但是我们也可以得到情感类别,这是索引2的分割行。因此,这可能是正面或负面,或者是无监督的,我们不希望无监督的样本出现在我们的数据集中,所以我们会根据这两个来过滤,数据可以是训练集或测试集,正如我们之前所看到的。
所以我们要做的就是返回true
。让我们看看能否这样做。返回true
,如果数据集归属等于训练集。如果情感类别不是无监督的。那么这是我们希望在Ds train
中拥有的示例。如果不是的话。
我们将返回false。那么我们可以在这里使用dot filter,通过这个名为filter train的过滤函数。如果我们现在再次调用DSstrain,就会发现我们只获得属于训练集的部分,这正是我们想要的。接下来,我们希望为测试集创建一个相同的功能,称为filter test,其他部分应该完全相同,只需将这里改为test,然后对测试集进行相同的filter操作。需要注意的是,你可能想要提前将它们分割成两个不同的CSsv文件。
训练的CSsv和测试的csv,通过这种方式,你可以节省计算资源,因为不必在实际训练模型时过滤示例,但你可能需要在其他地方使用这个过滤函数,因此了解它的存在和用法是好的。
现在我们已经完成了这一步,接下来我们想看看能否做一些待办事项列表。首先,我们要创建某种词汇表。如果我们要将其输入到模型中,我们必须首先创建一个词汇表。我在之前的TensorFlow视频中已经展示了如何做到这一点。
我将再次展示这个过程,因为我认为它非常有价值,能帮助到你。当我们创建了词汇表后,我们希望能够将文本字符串转换为数字索引。我们将使用token text encoder,我相信它就是这个,稍等我确认一下。是的,它叫token text encoder,这会为我们完成这个任务。
最后,我们要填充批次,以便可以发送。比如说S、R和N。对,这就是我们现在想做的。为了创建词汇表,我们首先需要一个分词器。这里有几种不同的分词器。我将使用的是TensorFlow dataset中的tokenizer。
TFTS功能是text.dot.tokenizer。我们要创建一个函数,称为build vocabulary。这个分词器会将句子拆分。比如说我有一个句子:我爱香蕉。它会将其拆分为一个列表:我爱,香蕉,好的,然后就可以进行标记化。
或者更确切地说,抱歉,这将能够进行数字化,这是我们的步骤2,类似于索引。这个特定单词在我们词汇表中的索引,所以假设我们只有这三个单词,也许它们的索引是0、1和2,然后这些可以在稍后发送到我们的R和N中。因此,在构建词汇表时,我们将发送一些数据,也许是DSs train,我们将发送DSs train,并且将发送一些阈值,因为我们希望如果这个词出现了这么多次,那么我们想要将其包含在我们的数据中。
在这种情况下,我们将选择,我不知道,假设是200。这将取决于数据,但我们就选择200,因为这是一个相对较大的数据集。此外,还有不同的方法来构建词汇表。你可以想象以多种方式进行此操作,我可能会向你展示一种更简单的方法。
所以首先,我们需要的是频率,这将只是一个字典。然后我们将处理词汇表,并进行一个集合。首先,我们将执行vocabulary.dot update。我们将发送一些开始标记,好吧,句子开始标记,这在这个示例中就是我们所称的。然后我们将执行vocabulary.dot update,添加句子结束标记,所以EOS表示句子结束,接着是标记。我们希望将这些添加到我们的词汇表中,然后我们将执行for line in DS train.dot skip of one,因此我们将跳过第一行,然后执行split line Tf string.dot split line。
焦点然后最大拆分等于4。然后我们将获得文本或评论。我们将通过拆分索引4的行来实现。然后我们将获得标记化的文本。为了获得它,我们将使用tokenizer.dot tokenize文本。我们还需要将其转换为numpy。接着,我们还要进行dot lower,因为如果字母或单词是大写的。
那么这实际上并没有什么意义。我们只会将所有内容转换为小写,以减少词汇表中的单词数量。然后我们将处理四个单词。在标记化文本中。如果这个词不在频率字典中,我们将添加它。因此,我们将执行frequencies of word,并将其设置为1。
但如果它在我们的词汇表中,那么我们将执行frequencies of word。我们将其加一。然后我们将检查是否达到了阈值,对吧。那是我们在这里发送的阈值。所以,如果frequencies.of word等于某个阈值。那么我们将执行vocabulary.dot update,然后是tokenize文本。好吧。
然后在最后,我们将返回词汇。这是一个相当简单的函数。我们将通过发送我们的DSs train
来完成这件事。那么我们可以这样做,词汇等于构建词汇。因此调用那个函数,我们将传入DSs train
。现在,我们可能不想每次都这样做,因为这可能会花费很多时间。
计算这个可能需要一些时间。所以我们可以打开vocabulary.OBG
,然后我们可以这样做。我们将使用pickle
,这就是我们为什么要导入它。我们将使用pickle.dump
词汇,然后是词汇文件。好的,这样就可以了。
构建词汇并将其保存到vocabulary.OBG
。好的,如果我们创建了它,也许我们想要一些加载它的东西。我们可以通过打开词汇文件来做到这一点。词汇对象和我们的RB
用于读取,然后词汇是通过pickle.load
加载该词汇文件。好的,在这种情况下。
首先,让我们先取消注释。因此我们将建立一个词汇,如果我们想在其他时间运行它,也可以保存它。好的,然后我们将创建一些编码器,可以进行数字化。这是将分词字符串转换为索引。所以我们通过encoder = Tfds.features.text.token_text_encoder
来做到这一点。首先,我们将传入词汇的列表。
然后我们将指定一些词汇结束标记,并将其指定为“未知”。这些将是所有未包含在我们数据集中,且频率至少为200的单词。然后我们将设置lowercase = true
,并且还将设置分词器。
在这个例子中,仅仅是一个分词器。好的,那么我们要定义我的编码器。我们得到的是一些文本张量,以及一些标签。我们要做的第一件事是编码文本,就是,我们将使用我们的编码器,对吧。这种令牌文本编码器可以将我们发送的文本张量数字化。
所以我们通过编码器的encode
方法来做到这一点,并传入texttensor
。然后我们将返回编码的文本和标签。好的,现在在TensorFlow中,我们需要做一件事,这可能有点不必要的复杂,但我们需要确保这个Python函数是我们计算图的一部分。
所以我们需要定义另一个函数。我们称之为encode.Map
函数。我们将传入一行文本,就是之前我们看到并打印的标签、评论等等的长行。我们要做的第一件事是拆分行。我们将使用TF strings.split
方法,以逗号为分隔符,最大分割数为4。
然后我们将得到标签字符串,它将是索引2的分割行。所以我不会再打印这一行。只需相信我这是索引2。如果我们进行了分割,这将是索引2。因此这将是负面或积极的。并且就是这样,因为我们也删除了所有未标记的部分。
然后评论将是,我们将在开始时添加一个起始标记。我们将与索引4的分割行一起添加它。所以那是最后一个,将是一个较长的文本字符串。最后,我们还将添加句子结束标记。好的,这就是我们的评论。
然后这将被发送到这个标记文本编码器。它将进行标记化。它将转为小写。然后将其映射到一些数字值。我们可以稍后将其发送到我们的模型。因此,标签将是1。标签字符串等于积极。
否则对于负编码文本,将是零,逗号标签。将等于Tf那pi函数。我们将使用我上面定义的编码器。输入将是评论以及标签。然后我们需要指定输出,在这种情况下,输出将是T F in 64和T f in 32。
所以这部分是为了。这个句子,审查,以及这个将用于标签,它只会是0或1,然后是编码文本的点集形状。这是我们需要为计算图做的,我们将把它设置为一个列表中的none,我们将设置为none,因为评论长度是可以变化的,评论可能仅仅是500个字符,或者可能是100个字符,然后我们将进行标签的点集形状,并且我们只会发送一个列表,因为它只会有一个值,然后我们将返回编码文本,并且我们也将返回标签。
好的,现在我们已经定义了处理数据所需的一切。我们只需对DS train和DS test数据集执行这些映射。所以首先,我们将进行自动调优,希望你对这里所有步骤都很熟悉,来自Tensorflow数据集教程。因此我们将执行Tf data do experimental.dot autotune。
我们将做DSstrain等于DSstrain.dot map。我们将通过map函数来映射它。我们将指定并行调用的数量。这只是为了,如果我们。这样做是为了让它们并行运行,从而加快数据加载速度。然后。
我们还可以调用dot cache,这将缓存一些内容到内存中,以便下一个更快。因此,我们还需要进行洗牌,如你所见,所有的示例都是负面的,然后是积极的,我们希望随机化。因此,数据集的长度为25000用于训练。因此我们将进行洗牌25000。
现在,也许25000有点多。你可以选择5000,但我们就这样吧。做一下打乱,大约5000,确保它完全随机。然后我们需要进行批处理,记住所有评论的长度可能不同。所以我们需要进行填充,使用填充批处理来实现。
指定批处理大小为32。然后我们指定填充形状,在更新的TensorFlow版本中,你不需要这样做。但在旧版本中,我想在2.2之前可能需要这样做。我们需要在这里指定为None,因为我们不知道评论的长度,然后我们只指定一个空元组。这将用于标签,因为它只会是一个整数。
好的,现在我们有了这个,我们可以对测试集做同样的事情。但我们不需要进行映射和打乱,所以我们可以直接这样做。通过编码映射函数,然后进行填充批处理32。再次设置形状,虽然不应该需要这样做,但如果你使用的是旧版本。
你可能需要。所以我在这里包含它。我会快速完成这个。我将创建一个模型。我们在之前的视频中实际上就做过这个。好的,所以相当快,我们只是创建了一个非常简单的模型,实际上只是做嵌入,然后对这些嵌入做全局平均池化。
这些嵌入的输出。然后我们通过一个稠密层映射,最后输出一个节点。接着我们指定了二元交叉熵,因为我们只有两个类,使用的是自适应动量优化器。好的,希望没有错误,这个应该可以运行。好的,但它没有。让我们看看。文本。好的,我们实际上在这个构建词汇表的函数中得到了相当早的结果。
那么,让我们看看我们得到了什么。是的,这里写的是文本做N。我们应该有评论。我们想把它转换为小写,然后想对实际的评论进行标记化。所以希望让我们看看这是否可以运行。好的,令人惊讶的是,这实际上成功了,所以我们可以看到我们得到了。
看看在训练中经过15个回合后达到了97%,而在测试集上得到了88%。但我觉得我们表现如何并不重要,重要的是它实际上可以运行。因此在构建词汇表时,或许你可以修改它,让它仅仅使用。
前1000个单词,然后你就不需要设置这个阈值,我认为这应该很容易实现。正如我一开始所说,这个过程对于每个数据集来说都不同,因为结构会有所不同,所以我想给出一个不同结构的例子。比如说,我有一个测试示例,包含三个CSV文件,实际上它们是完全相同的。
并且带上它,这也是IMDB数据,只是我们在一个文件中有几个示例,在另一个文件中也有几个示例,然后在第三个文件中还有几个示例。所以在这种情况下,如果你将其拆分为多个CSV文件,你可以这样做。
这在处理大型数据集时可能是非常常见的。
然后让我们做一下,我导入系统,然后看一下退出。所以它不会运行下面的代码。然后你可以指定文件名。在这种情况下,分别是test example1那CSV、test example2那CSV,然后test example3那CSV。所以我们可以简单地做data set是TF数据文本行数据集,文件名的数据集。
而且一切都会正常工作。所以就像你把它们都放在一个CSV文件中一样,这真是太神奇了。这就是你可以做的一件事。我们可以只是为了确保它正常工作。我们可以打印行。😊,正如你所看到的,它打印了所有的,包括这里的第一个。实际上,它为所有的都打印了。
所以,也许你想要做的是,为那些CSV文件移除这个。但是这对于多个文件来说是一种相当方便的方法。现在,有一点是你可能想对所有这些CSV文件进行不同的预处理。它们的结构可能不像这里那样完全相同,然后你可以指定data1为TF数据文本行数据集,然后我们可以处理test example1那CSV,然后我们可以跳过第一行,但也许你会做一些,比如通常你会做dot map,然后预处理一下,如果你有不同的处理方式,所以我们就复制一下。
对于所有的。所以我们将做2,3,2,3。然后在你处理它们之后,结合它们,具体取决于这些单独的CSV文件的结构,你可以做一些,比如data是dataset1 dot concatenate,然后dataset2,然后concatenate dataset 3。通过这种方式,我们再次获得整个数据集。
所以如果我们在数据中做四行然后打印那行,我们就得到了整个数据集,包括所有这三个CSV文件。好的,这就是如果你有多个文件的情况。再说一次,让我们导入这个。这开始退出。
所以假设我们有一种翻译数据集。实际上,我将创建这个,我们只是做英语,然后我们做瑞典语,好的,所以我们有它们,我们有英语CSV,然后我们有瑞典语CSV。好的,所以让我们做language1,然后我们就说我爱金枪鱼,我爱土豆。
我爱培根。然后我们可以做语言,瑞典语。所以你不会希望人们都能理解,可能是的,我们写的是什么,金枪鱼。Toun fik。yog 和 scar Potis,yog 和 scar。培根,所以现在我们有这三样,对吧,我们有。
这里只是三个示例,但我们将如何加载它们。首先,我们可以指定一些分词器,正如我们之前所做的。使用 TFDS 做特征处理和文本分词器。然后我们处理英语是 TF 的数据文档文本行数据集。我们会有那个英语做 CSv。对于瑞典语,我们将使用 TF 数据。
文本行数据集,瑞典点 TSV。然后你可以做 D,D S。我们的数据集是那个数据的 T,那个数据集的 zip。然后你可以处理英语和瑞典语。所以现在我们可以在数据集中做四个英语和瑞典语。然后我们可以再次跳过第一行。接着我们可以做类似打印的操作。
tokenizer 做分词。英语点 Nai。然后我们可以做 tokenizer 做分词 瑞典点 numpy。然后我们还需要做 UTF 8 解码,因为我们使用特殊字符。所以特殊字符会是类似这样的。这就是我们为什么要做 UTF 8 解码。现在让我们运行一下,看看结果如何。
然后我们可以看到它正在分割我们之前的示例,这是一个配对,对吧。这是第一个的翻译。接下来你需要做的是,你需要首先准备一个词汇表。然后你需要为每种语言进行分词和奇迹化单词。
所以这就是我希望向你展示的内容,你应该相对自信能够使用这两个。然后我们需要做填充批次来获取批次。等等。然后我们还需要创建一个模型,创建模型。这个模型在这种情况下可能类似于序列到序列模型,这可能对你来说有点过于复杂。或者它甚至可能是一个变换器网络。我没有涉及这些,因为我认为它们有点过于高级。
这超出了本视频的范围。我们在这个视频中想要重点关注的内容,希望能尽量清晰,就是如何加载自定义文本数据集。使用这个文本行数据集,希望我也向你展示了一些不同的方法,具体取决于你的数据集结构。所以我之前说过,没有哪个数据集是完全相同的。
所有数据的结构都将有所不同。所以加载它的方法将取决于你的数据集。但愿你学到了一些加载数据的一般原则,这些原则可以应用到你自己的项目中。视频到此为止,希望你觉得这个视频有用,非常感谢你的观看,希望下个视频见。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P2:L2- 张量基础 - ShowMeAI - BV1em4y1U7ib
大家好,希望你们都很好,欢迎来到第二个教程,我们将在这里学习基本的张量操作,这是深度学习库的基本构件。
好的,让我们先来看看张量是什么。从编程的角度来看,张量本质上是一个多维数组,能够在 GPU 上运行。从更数学的角度来看,张量是标量、向量和矩阵的推广。例如,向量是一个一维张量,矩阵是一个二维张量。
所以,既然这样,我们就深入了解一些基本操作以及如何在 TensorFlow 中实现它们。我们将从导入 Tensorflow 作为 TF 开始。如果我们直接运行这个,会收到来自 Tensorflow 的消息,基本上是在说它成功打开了 Kuta 库等等,如果你在 GPU 上运行,我觉得这有点烦人,所以我实际上要去...
导入 OS,然后你可以做 OS.do.environment 或者 envion 或者随便你怎么发音 TF 和 CPP min log level。你可以将其设为字符串等于 2,所以本质上这会给我们带来错误信息,但这些信息将被忽略。所以如果我们现在重新运行,我们将不会得到任何东西,反正。
让我们开始我们要讨论的内容,我会有不同的部分。本质上,我将从张量的初始化开始,展示不同的初始化方法,然后是我们可以执行的更数学的操作,接着是张量的索引,最后是张量的重塑。所以。
我们先从如何在 Tensorflow 中创建张量开始。我们可以做的是将 x 设为 Tf.dot.constant。好的。我们可以在这里设置一些值,比如说,我们设定一个标量,就是一个单一的数字,所以我们将其设为四,然后打印出来。
这就是一个标量值的张量,它没有形状,不过我们也可以看到 D 类型,在这种情况下是 32。如果我们设定为 4.0,我认为这将是 flow 32。所以我们还可以指定形状,比如说我们希望它是 1,1,然后如果我们重新运行,将会得到类似于 4 和形状 1 1 的结果。
您还可以指定 D 类型,所以假设我们想使用 float 32,您可以执行 Tf.dot.float32
,如果我们运行它,它将是一个 float 32,现在它是一个 1x1 的矩阵,仅仅是一个标量而已,但有时在对张量进行不同操作时,指定形状是很重要的。
假设我们想创建一个更大的矩阵,即二维张量,我们可以使用 TF.constant
,然后做一个列表,里面再嵌套一个列表,可以写成 1,2,3,然后再调用另一个列表 4,5,6。这样会创建两行,每行有三列,因此这将创建一个 2x3 的矩阵,如果我们打印它,我们会得到 2x3,您同样可以指定形状等。
现在,您还可以手动初始化张量,您也可以使用其他初始化方法,比如您可以做 x = Tf.ones
,并且可以指定形状,可以做一个元组作为第一个参数,形状是 3,3,这样如果我们打印,它将得到一个 3x3 的维度。
而是一个 3x3 的矩阵,仅包含 1 的值。还有其他操作,比如您可以做 x = Tf.dot.zeros
,然后 I
是 2x3,这将是一个全零的 2x3 矩阵。还有一些其他的方法,比如 Tf.dot.I
,您也可以使用或类似的方式。
在线性代数中,您有 I 作为单位矩阵。如果您发音 I,那听起来像是 I,这就是您指定相同矩阵的方式,因此对角线上的元素是 1,其他位置是 0。如果我们打印它,我们会得到类似这样的结果,对角线上是 1,您还可以指定 D 类型等。如果您想要一些来自分布的东西,Tenflow 也有不同的方法来实现,我只是想展示一些更常见的方式。
如果我们想从均匀分布中生成,可以写 x = Tf.random.normal
,并且可以指定形状作为第一个输入的元组,假设我们只想要一个 3x3 的矩阵,当然,您也可以做更多维度,我只是为了方便做一个矩阵。
然后我们可以设置均值为 0,标准差为 1。这将来自一个正态分布。如果我们打印它,可能会得到大多数值在 0 和 1 之间。是的,我的意思是,值在 -1 和 1 之间。然后,如果我们想从均匀分布中生成,可以使用 Tf.random.uniform
。
我们可以指定 1,3,一个向量,然后可以指定最小值和最大值。假设最小值等于 0,然后最大值等于 1。这些将会在 0 和 1 之间有值。它将看起来像这样。这些确实是一些基本的初始化方法,TensorFlow 还有更多,其实我想展示的另一种是可以做类似 Python range 函数的操作,所以只需 TF dot range,例如,如果你做 TF range 的 9,我们打印出来将得到一个从 0 到 1 的向量,然后到 8,9 不包括,完全和 Python 一样。如果你想指定更多,可以设定起始值为 1,然后限制为。
我不知道,假设为 10。然后我们还可以指定增量,因此在这种情况下增量是步长,我不太确定为什么叫增量,但它是值之间的步长。所以假设增量等于 2,那么我们将从 1 开始,接下来的值将是步长为 2,因此我们将得到 1 和 3。我们打印出来,所以得到 1、3、5。
7 和 9 好吧,正如我们所看到的,我们现在创建了这个,这是一个 d 类型的向量,类型为 32,你可以在这个函数中指定 d 类型,但假设你想将其转换为特定类型,那么你可以做 TF dot cast,并传入输入向量,然后你可以指定 D 类型。例如,假设我们想要流 F 64。
在深度学习中,这种情况相当少见。好吧,我们也需要打印它。因此通常你会有 F 32 或甚至 F 16。流 F 64 是相当不寻常的,但使用转换。这确实是不同类型之间转换的一种方法。例如,假设我们想要浮点数,我们会像之前一样做 TF dot float。
然后我们只需指定我们想要的位数,比如 16、32、64。你还可以使用 TF dot int,支持 8、16、34、64。同时你也可以使用 TF dot Bo 将布尔值转换为 0 和 1,这些都是将其转换为不同 D 类型的一些方法。好吧,接下来让我们进行数学运算。首先,我们创建两个向量。
我们设定 x 等于 TF constant,然后是 1、2、3,然后设定 y 等于 TF constant 的 9、8 和 7。如果我们将这里的列相加,我们会得到 10、10 和 10。假设我们想要相加。我们可以设定 Z 等于 TF dot add x 和 Y。如果我们打印 add,则会逐元素相加每个元素。所以这将会把 1 加上 9,2 加上 8,3 加上 7。如果我们运行并打印 add,我们将得到 10。
10 和 10。现在你也可以做 Z 等于 X,然后加上 y,这是一种等效的做法,也许这是最方便的方式,这两者实际上是等价的,所以你选择哪一个都没关系,所以我可能会选择第二种,因为那样更简单。如果我们想要做一些类似的减法,我们可以做 TF dot subtract。
X 和 y 类似地,你也可以做 z 等于 x 减 y,这两者也是等价的。假设你想知道,这将进行逐元素减法,所以将 1 减去 9,2 减去 8,3 减去 7。如果我们想进行逐元素除法,所以我们想要进行除法。
假设,1 的值为 9,2 的值为 8,3 的值为 7,我们可以做 Z 等于 Tf.divide 和 x,y。类似地,我们也可以做 x 然后进行除法。这也会进行逐元素除法。对于逐元素乘法,我们可以做 Tf.multiply x 和 y,但我们也可以做 x 然后直接。
所以 x 星 y 然后。假设我们想进行点积。所以在这种情况下,点积就是做 1 乘以 9 加 2 乘以 8 加 3 乘以 7。所以它会加起来。它会逐元素操作,所以会进行逐元素乘法,然后求和可以使用 Tf.dot 和 tensor.dot,这是一种更高级的函数,可以用于更多的场景,但在这种情况下,我们将对 x 和 y 进行操作,并指定 x 的值,这里是 1。如果我们现在打印,这基本上会对元素进行逐元素乘法,然后求和。
例如,如果我们想手动执行这个,我想我们会做 x 乘以 y,然后做 TF.reduce_sum,然后我们将指定我们应该在哪里加起来的维度,所以 x 等于 0。然后我们可以打印 Z。通过这种方式,我们得到相同的结果。
我也不太确定为什么叫 reduce sum 而不只是 Tf.sum,但好吧。现在假设你想进行逐元素指数运算。你可以做 z 等于 x,然后就像在 Python 中一样。你会这样做,这将逐元素地将每个元素或逐元素地对每个元素进行 5 次方运算。
然后我们想要打印 Z。然后我们得到 132 除以 243,这似乎是准确的。然后我想给你展示如何进行矩阵乘法,所以如果我们指定,假设 TF.random.normal 然后做一个 2x3 矩阵,y 是 Tf.random.normal 然后是 3x4。我们可以做 z 等于 Tf.matrix.multiply 和 mat Mole。然后仅指定 x 和 y。
我们也可以这样做得更方便。我们可以做 Z 等于 x。我真的不确定我该如何发音。所以 x 在 @ 符号下,我认为是 x @ y,然后我们将。让我们在这两个上打印,所以在我们运行之前。我只是想在这里顶部添加两行。我们将处理物理设备。
我们将获取我们的 GPU,然后我们将做 Tf.config.experimental.set_memory_growth,我只有一个 GPU。所以物理设备为 0,然后将其设置为 true,本质上这将使得 TensorFlow 不会在 GPU 上分配所有内存。有时你可能会遇到这些奇怪的错误,如果发生这种情况,就添加这两行。
但是如果你没有问题,就不应该需要添加这些。不过无论如何,让我们回到打印这个。所以如果我们现在看到这些是等效的,对吧?所以你可以用MaMo
或者只是使用加号。好的,我们继续讨论张量的索引。假设我们做类似X TF constant
的操作,然后。
我不知道,只是一个包含一些值的向量,0,1,1,2,3,1,2,3。类似于这样。然后我们可以用print X
,然后用一个冒号,这将打印出所有元素,所以这与打印X
是一样的。
然后我们就能得到所有的元素。但假设我们只是想,我不知道,比如第一个元素。所以我们希望获取这个向量的部分。我们可以用print X
和1 colon
,这样就会打印出除了第一个零值以外的所有内容。然后假设我们也只想要这两个,11,我们可以看看。
我们可以用print x1,3
,这将是不包括第三个索引,所以0,1,2,3,这不会包括这里的值2,因此我们只会得到这个包含两个元素的向量。假设我们想要所有值,但希望跳过每个其他元素,比如我们想要这个值。
我们想跳过下一个,并希望得到这个值,跳过下一个,接下来我们可以使用colonco 2
,这将跳过每个其他元素,我们将得到01.32,然后我不知道,假设我们想以相反的顺序打印,可以用x
和colonco minus1
,这将以相反的顺序打印。
我只是想注释掉,以免它总是打印。我想假设我们只想指定索引,比如我们想要,我不知道,这个和这个,所以我们想要0和2。我们可以做类似indices equals TF constant
的操作。然后我们可以为这些值指定索引。然后我们可以使用,做。
假设我们将其称为x in
,然后用Tf.dot.gather
。从x
,从张量x
中,我们想收集特定的索引0和3,所以如果我们打印x in
,我们现在会得到0和2。我们想提取的值。好的,这仅适用于向量。我们再来一个例子,假设我们取一个矩阵,所以我们做x = T of constant
。
然后我们来做1和2,3和4,5和6。所以这将是一个三乘二的矩阵,然后假设我们想获得第一行的所有元素。我们可以这样做,x
和0
。我们也可以通过x comma
和所有的元素来实现。因此,当我们添加张量的多个维度时,我们用逗号分隔这些维度。
同样地,就像我们在向量中所做的那样,我们可以指定我们想要的行。因此,假设我们只想挑选前两行,我们可以做x[0:2]
,不包括2
,所以在这种情况下我们只取0
和1
。然后我们可以用逗号来表示所有,所以如果我们打印出来,现在应该得到一个包含1
、2
、3
和4
的二乘二矩阵,这就是基本的张量索引。
让我们删除那些打印语句,现在进行一些基本的重塑,假设我们有x
是Tf范围为九,因此我们将有九个元素,我们想将其重塑为一个三乘三的矩阵。
然后我们可以执行x = Tf.dot.reshape(x)
,并指定维度,因此我们做三乘三,然后现在打印x
,我们将得到01012
作为第一行,然后3,4,5,6,7,8
作为最后一行。假设你想转置一下,这样我们将把它作为第一列而不是第一行,方法是x = Tf.dot.transpose(x)
,我们还可以为排列指定perm
,这也适用于多个维度,而不仅仅是这里的两个维度,你可以在这种情况下指定0
或1,0
,这样就可以交换轴了。如果我们现在打印x
,那么第一行将成为我们的第一列,第二行现在是我们的第二列。
我们的第二行现在就是这里的第二列。所以这就是张量操作的基础知识,非常感谢观看视频,在下一个视频中我们将开始构建一些基本的神经网络。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P20:L20- 皮肤癌分类项目 - ShowMeAI - BV1em4y1U7ib
🎼欢迎来到本系列教程的最后一部视频。在这个视频中,我想通过一个项目示例,这也是这些教程开始时的目标,即我们构建一个扎实的 Tensorflow 基础,以便自信地开始自己的项目。在这个项目中,我们希望建立一个网络,可以分类皮肤病变的图像是良性还是恶性。
这意味着它们是无害的,或者如果它们是恶性的,那实际上就是癌症。因此,像任何项目一样,我们在过程中可能会遇到一些问题,我们将看到如何解决这些问题。
所有项目中的第一件事是获取一些数据,经过一些谷歌搜索,我发现了一个名为 IIic 数据集的数据集。让我给你展示一下如何下载它。我们将搜索 IIac 训练数据。我们只需打开这个链接,它也会在视频描述中。
我们要做的就是输入我们的电子邮件地址,完成后,我们将获得带有输入的训练数据,格式为 JPEG 图像,并且还有一个 CSV 文件,记录了皮肤病变所在的年龄、性别和位置。
还有如果实际病变是恶性或良性的标注。然后我们有测试数据,所以我们有 25000 张这样的图像,还有一个包含 8200 张图像的测试数据集,但正如你所看到的,它们没有真实标签,这是因为这个 IsIic 实际上是一个挑战。IsIac 挑战是,他们在这 8200 张图像上能获得什么样的准确率?因此在这个视频中。
我们会稍微改变一下方法。我们将选择这 25000 张图像,将其分成测试集、训练集和验证集。然后我们将看看能获得什么准确率。因此,在实际挑战中,由于我们会有更多的数据,我们可能会获得更好的性能,但我认为这就是。
这已经足够好了,你知道,我们有很多图像。因此,要下载它们,我们只需按下这三个按钮。在这种情况下,你知道,由于我们有很多图像,实际上是 10GB,下载会花一些时间。所以在下载后,我们会得到这三个文件,并且我们会得到一个包含所有图像的文件夹,然后还有两个 CSV 文件。
所以我们有真实值。看起来是这样的。我们有图像,图像的文件名,然后第一列是它是否是恶性的。所以0代表良性,1代表恶性。然后他们还对实际情况有不同的类别。是什么类型的皮肤病变,但我们会简化一下,实际上我们只关心这两个。
所以我们关心的只是皮肤病变是否实际上是癌症,而不是它是什么类型的皮肤病变。然后在这里我们有训练元数据。所以如果我们打开它,我们得到文件名,然后我们得到那个人的年龄以及它的位置,性别我们在这个视频中也将进一步简化,我们将完全忽略这个文件,所以我们只会获取图像,而不包含关于年龄的额外信息。
但是如果你想提高准确性,我只能想象拥有这些信息会使模型更好。因此,我只是编辑了文件名,然后将文件夹更改为图像,然后我们有标签,再加上我们可以移除的额外信息,因为我们不会使用这些。因此,首先我们现在需要做的是创建一个训练集。
一个测试集和一个验证集,因此我们需要编写一些处理脚本,可以将这些图像放在一个文件夹中,然后你可以用不同的方式来做,但我的想法是把它们放在一个例如训练文件夹中,然后在这个训练文件夹中,我们创建两个额外的文件夹,一个用于良性,另一个用于恶性。
然后我们将所有良性文件放入这个文件夹中用于训练集,而所有恶性文件放入那个文件夹中,然后我们可以使用图像数据生成器,正如我们在之前的教程中所见,以加载这个自定义图像数据集,所以让我删除这个文件夹,我们将创建一个为我们完成所有这些的脚本。
好的,这些是我们将要使用的所有导入。我们将调用这个过程为数据处理。因此首先,我们要做的一件事是设置一个种子。我们将其设置为1,以便在多次运行脚本时获得完全相同的拆分。
然后我们将对这个种子进行随机种子处理。接着我们将指定图像的目录。因此我们要做的目录是。我称之为存放图像文件夹和所有那些东西的文件夹。因此在Isaac中,在那个文件夹中会有一个图像文件夹。我们还将指定训练集,这将会是。
我们将把它放入数据的一个文件夹中,并且它将位于训练的子文件夹中。然后我们将获取测试数据,并将进行数据测试。然后我们还会有一个验证集。所以我们将把它放入数据验证中。如果这些文件夹不存在,我们需要创建它们。
所以我们将使用 OS 创建目录。我们将创建训练文件夹,然后添加良性,并且我们将再做一个。用于训练的恶性文件夹。然后我们复制粘贴这个,并且我们将为训练和验证做这个。我更倾向于测试集,然后是验证。所以测试。测试。😔,然后验证。验证,好的。
现在我们应该在数据文件夹中放置所有需要的文件夹,并且在这些文件夹内,我们有三个子文件夹:训练、测试和验证,并且在这些文件夹内,我们还有两个额外的文件夹:良性和恶性。我们现在要做的一件事是统计我们要放入每个文件夹的示例数量,因此我们将测试示例。
等于训练示例,等于验证示例,所有的初始化为零。然后我们要在打开的环境中执行四行操作,我们将读取那个 CSV 文件的标签。CSV 文件包含它是否实际上是恶性的或良性的。接下来我们要读取这些行。我们将从第一行之后一直读取到最后一行,因为我们不想要第一行。
第一行只是关于列的信息。然后我们将分割这一行。我们正在进行行的分割,并且会按逗号分割,因为这是 CSV 文件。它是以逗号分隔的。我们将获取图像文件,它将是分割行的第一个索引。如果它是良性还是恶性。
这将是分割行的索引 1。好的,所以现在当我们实际进行分割时,我们需要决定测试集应该有多少示例,验证集应该有多少示例。在这种情况下,我将把 80% 放在训练上,把 10% 放在验证上,然后将剩余的 10% 放在测试集上。
所以我们将获取一些随机数,并将进行随机选择,这将是 0 到 1 之间的均匀随机数。然后我们将检查这个随机数是否小于 0.8,如果是,那么我们将设置位置为训练。并且我们将训练示例加 1。或者如果随机数小于 0.9。
好的,它将转到磁盘。首先,如果它小于 0.8,那么我们将检查它是否小于 0.9,这实际上意味着如果它在 0.8 和 0.9 之间。然后我们将其设置为验证。并且我们将迭代验证示例加 1。否则。
它将介于0.9和1之间。然后我们只是将位置设置为测试集。是的,然后我们将以每次1的方式迭代测试示例。好的。现在我们将做的是如果良性或恶性的浮动整数,我们得这样做,因为这里是0.0,所以我们得先转换为浮动,然后是整数。我尝试仅使用整数,但没有成功。
然后,如果这是零,我们将使用chatill.copy。所以我并不打算实际移动文件,如果有任何错误。我只是将它们复制,然后如果这个可行,你可以删除文件。所以我们将处理Isaac图像,然后加上图像文件再加上.JPEG。
这是图像的文件格式。然后我们将其移动到位置。加上bin9,加上图像文件,然后是.JPEG。好的,所以我们是从这个位置移动到这个位置,而这个位置依赖于这个随机数。
所以它要么在训练测试中,要么在验证中。好的。那么另一个场景是,如果你可以在这里使用Els。我要使用Elsif整数的良性恶性等于一。然后我们将进行左侧复制。我们可以直接复制粘贴这个。
这里将基本上和它一样,只是它不会是良性,而是恶性。最后,我们可以打印。可以用F字符串显示训练示例的数量,因为我们已经计算过了,对吧?
我们可以这样处理训练示例。然后我们可以复制,粘贴,并为验证和测试集做同样的事情。所以我们可以设置测试示例的数量,验证示例的数量也会相应。好的。希望这个脚本现在可以工作,我将运行它,看看我们得到什么,好的。
现在,如果我打开那个文件夹,我们会看到这里有一个名为数据的文件夹。然后在里面我们有所有的拆分。因此对于测试集,我们有良性或恶性,然后我们有属于那个文件夹的所有文件。
好的,现在我们实际上处理了数据。现在我们可以继续这个训练脚本。
首先,我已经复制了所有导入,以免浪费时间。我们在之前的视频中都用过它们,但如果你没有,可以当然安装它们。好的,首先,让我们看看我们有所有的示例。所以我将首先写出这些。训练示例是20225。
我们有测试示例是2551,然后是验证示例。我们使用2555。接着,我们将指定图像高度,这将是图像宽度,我们将其设置为224。因此,我认为其中一些实际上可能超过1000像素,甚至更大。
因此,我们将把所有图像调整为224乘224,这是相当标准的像素高度和宽度。然后我们将指定批处理大小,我们将指定为32。接着我们需要一个实际的模型。你在这里有很多选择。你可以使用Resnet,使用Inceptionnet,或者许多不同的Efficient nets。
我会使用一个有点奇怪的模型。我会使用一个叫做Nonet nacenet的模型。我不太确定如何发音。不过,我之前没听说过这个模型。有时候尝试新东西是很有趣的,我不认为这是最好的选择。我认为你可以使用Efficient net,它会更好。好吧。
加载模型的方式是model equals kos dot sequential。我们现在将创建整个模型。所以我们将使用Tensorflow hub,正如我们之前看到的,我们将使用hub dot k layer。我将复制粘贴这个链接,如果我们从这个URL获取它,我会在视频描述中粘贴这个链接。
这样可以获得特征向量,然后我们将使用逗号并设置trainable equals true,所以我们也会训练这个。接着我们将执行layers flatten,其实这并不是必须的。我认为它已经是扁平化的,是的,我们可以删除这一行,然后我们将执行layers dense one,并且我们将激活函数设置为sigmoid。这是因为我们只有两个类。好吧。
通常你可能会使用这个预训练的模型,然后可以添加一些层。在这种情况下,我们将用这个预训练模型训练整个模型,并且我们只会有一个单一的全连接层。所以,你知道,我并不是在构建最大的模型,这个Nasnet其实也不大。但它会很好地用于演示,你知道,我们仍然会获得不错的性能。
然后我们将进行训练数据生成器,我们将指定图像数据生成器。正如我们在之前的视频中看到的,我们将首先将比例调整为1除以255。我们将设置旋转范围来指定数据增强,假设为15度。你也可以在这里做得更多,以获得更多的数据增强。
但15似乎是一个不错的值,然后缩放范围我们将设置为0.95到0.95,这意味着它将随机缩小5度,然后放大5度,我们将指定水平翻转为真,垂直翻转也为真,因为无论你如何旋转或翻转图像,如果它是癌细胞,翻转后仍然是癌细胞,这与图像数字6或9的情况并不相同。
但在这种情况下是可行的。所以我们将数据格式设为通道最后。我们将进行验证拆分,但实际上并不进行验证拆分。因此我们将数据类型设为TF flow 32。然后我们将进行验证数据生成器,并且我们将使用图像数据生成器。顺便说一下,为什么这里不使用验证拆分是因为如果我们这样做的话。
然后所有这些数据增强也将应用于验证集,这并不是我们想要的,我们希望验证集与测试集相似,而测试集将没有任何数据增强。所以这里我们只将重缩放为1/55。然后我们将进行TF flow 32。然后我们将对测试数据生成器做同样的操作。
图像数据生成器的重缩放为1除以255,然后数据类型为TF flow 32。好的,现在我们有数据生成器来指定如何加载图像,并且实际上并没有指定我们在获得带数据增强的图像时应该做什么。
然后我们将进行train generator是train.data generator do flow from directory。这里我们指定数据训练,也就是文件夹对吧。然后目标大小将等于图像高度,图像宽度。如果不是指数则将进行重缩放。然后我们将批量大小设为批量大小。
颜色模式将为RGB,我认为默认也是RGB。然后我们将类模式设为二进制。然后shuffle设为true。然后我们也将设置一个Cd。好的,所以让我们复制这个,我们也将用于验证和测试集。
所以复制粘贴。然后我们将进行验证生成器,它将是验证数据生成器。然后我们只需将其更改为验证,但其余部分应完全相同。然后是测试生成器,测试数据生成器。然后我们将这里更改为测试。好的,现在我们拥有所有这些。
然后我们将进行model.dot compile。我们将指定编译。我们将指定优化器,并使用Kaas optimizers.dot at。我们将学习率设置为3e-4。我们将损失设为binary cross entropy。然后从Loit等于false。
然后指标在这种情况下只是准确性。好的,我还想说几句关于我们如何加载数据的事。在这种情况下,我们使用的是图像数据生成器。但如果你看过我关于图像的自定义数据集,我展示了两种方法,如果按这种方式结构化,我认为将其转换为TensorFlow数据集并进行数据增强会更有效。
如果你想提高性能,以及这个程序运行和加载数据的速度,我认为这样做会更快。但我觉得这样稍微方便一些,所以我在这里使用它,但请知道你绝对可以提高它的性能。你能改善它的原因是你可以并行加载数据,并且可以进行预取等操作。
好的,现在我们有了模型,我们将进行模型拟合,我们将发送训练生成器,我们将周期设置为,我不知道,先设置为1。然后我们将进行每个周期的步骤,我们将进行训练示例。
按批次大小进行整除。然后我们要进行验证数据。验证生成器。验证步骤是验证示例。按批次大小进行划分。好的,那我们就先从这里开始,并确保它能够运行。我们会很快改进这个。好的,所以我实际上要在这里停止训练。
它只运行了15个批次,但我们得到了准确率,已经是77%。好的,如果你没有考虑过这一点,那么什么是好的准确率呢?通常如果是两个类,那就是50%,超过50%就比单纯猜测要好。因此,这意味着在仅仅15个批次后,这是一个非常好的模型。
如果你使用的是像Mist这样的工具,类是平衡的,那样是可以的,但在这种情况下,我们的数据非常不平衡。你知道,可能不到1%或1%的案例实际上是恶性的,而绝大多数,即99%是良性案例。所以在这种情况下,准确性将是一个非常有缺陷的指标。这是你在做项目时可能遇到的问题的一个例子。
最初只考虑使用准确性。嗯。我们很快意识到这是一个缺陷。
好的,接下来我们要引入一些新指标,我将链接到Andrew Ug的两场讲座,他在讲解为什么在我们有偏斜类的情况下不能使用这些指标,以及我们可以做些什么,比如使用精确度和召回率。它们将在描述中,我建议你观看,这将让我们接下来的内容更加清晰。
所以我们将引入这些新度量。我们将执行metrics等于Keras.metrics。我们仍然可以使用二进制准确率。我们将设置name等于准确率。我们仍会使用它,但这并不是特别重要。我们可以删除这个,因为它并没有告诉我们太多信息。
然后我们可以使用精度,并将其命名为精度。然后我们可以使用Keras度量召回率。召回率是另一个度量,我不确定他在那两个视频中是否有提到Keras度量AU。我建议你谷歌一下这些是什么。
我不会深入探讨,这会是另一个视频。所以我只专注于如何在这个视频中使用它们。然后我们在这里设置这个度量标准。我们将要设置度量标准。所有。现在我们有了这些改进的度量标准。嗯。最后。
我们可以在验证生成器上评估你的模型。假设verbose等于2,那么我们也做这个。然后可能我们还想在测试生成器上进行评估。实际上我有一个我训练过的模型,我想我训练了大约50个周期。
所以我将加载那个模型以节省一些时间,我们将执行model等于Kras models加载模型Isaac model,它在那个目录里。所以你知道这里就是我使用的确切模型,我只是训练了更长时间,我们将把它用作我们的预训练的一部分或其他什么。
所以我们可以将这个epoch保持为一。否则,我们将不得不训练大约50个周期。然后我们将在验证生成器和测试生成器上进行评估。我还将向你展示如何绘制ROC曲线,因为将会有一个。
ROC曲线将预测真阳性率与假阳性率之间的关系。因此这两者之间会存在权衡。我们将绘制一条曲线来确切地看到这种权衡是如何进行的。所以我要定义绘制ROC。我们将发送标签和一些数据。
然后我们将执行predictions等于model.predict在那个数据上。接着我们将计算假阳性率和真阳性率。我们将从SK学习的ROC曲线中获取,所需的仅是发送这些标签和那些标签的预测。然后我们将执行PLT.plot,假阳性率乘以100来获得百分比,真阳性率作为Y轴。
在这种情况下,x轴标签将是假阳性。y轴标签将是真阳性。同样,以百分比表示。然后我们只需执行PLT.show。我们需要在这里发送实际标签,但我们只有一个生成器。因此,我们将执行测试标签这个空的Numpy数组。
我们将批次数量设为0,然后我们将迭代测试生成器。因此在测试生成器中,测试标签将是NP数据和测试标签2,然后我们将Y附加到测试标签上。因此,我们必须迭代,批次数量加1。如果批次数量。
数学上,这是测试样本的总数除以批量大小。因此这只是将测试集中的所有示例整合成一个数组。然后我们将中断。好的。因此现在我们有测试标签,然后有数据。那么我们可以做什么呢?
我们可以绘制测试标签的R O C曲线,然后我们正在处理测试生成器。这将在图上给我们那个R O C曲线。因此,不仅在这里获得所有指标,我们还将在最后得到一个漂亮的图。我想我评论了那个模型。是的。
所以我们在这里加载这个模型。但当然,如果你想的话,可以稍微训练一下。然后你只需保存那个模型。因此我们将使用这个来保存,以确保不丢失到目前为止的模型,我们要去这个指标,并且我们要做的不等于。等等,确实是在fit中。是的,我们要去这里。回调等于ks.Dot callbacks。
模型检查点。我们将指定给以撒模型。这将每个周期保存当前模型。现在运行这个,希望一切正常。好的,因此我们从该训练周期获得所有值,正如你所见,我们已经训练了很多,且在训练数据上过拟合了。
这意味着我们可能需要引入更多的正则化。但我们也得到了验证准确率、验证精确度等等。然后我们还得到了这个图,长得像这样。这里有一点,正如你所看到的,我们的验证A U大约是86%。这意味着这是该曲线下的面积。
这是一种常见的指标,通常人们会使用。因此在测试集上运行并评估,我们可以看到我们得到了约6073%的精确度。因此,实际上这意味着如果你去看医生,而他有70%的精确度。这意味着如果他说你有癌症,他在73%的情况下是正确的。然后是召回率。
这意味着如果你去他的办公室,而你有癌症。他在54%的情况下会告诉你你实际上有癌症。然后在这种情况下的A U C,这是一种汇总指标,大约是87%在测试集上。
好的,值得注意的是,这也是一个奖金为$30,000的挑战。这正是我们刚才看到的数据集,只不过他们使用的是训练数据,然后在提交模型时。
它是在这个未知的测试数据上进行测试的。因此我们可以在这里看到排行榜。他们在这里的分数,而这里的分数实际上是我们为AUC计算的分数,这个分数是接收操作特征曲线下的面积,这正是TensorFlow计算的。那么我们得到了什么呢?
我们得到了0分,约87分,而他们得到了95分。因此,正如你所看到的,他们的模型要好得多。我还想说,这些结果不一定可比,因为我们没有使用相同的测试集,并且我们并没有在完全相同的数据上进行训练。实际上,我们只是在他们训练的子集上进行训练,因为他们可能使用了整个训练数据。不过,看到这种情况并进行比较,至少作为我们模型好坏的一个近似是非常有趣的,但我们离获胜还有很大距离。
0000,但也许你可以训练一个更大的模型,可能你可以做一些数据增强,或许你可以将准确率提高到90%以上,或者类似的水平。所以这就是本视频的内容,希望你能够跟上这个项目示例。我也希望你从这些TensorFlow教程中学到了很多,并且你觉得自己现在准备好开始做自己的项目,并在TensorFlow中创建东西。
非常感谢你观看这个视频和这些教程视频。我希望在未来的另一个TensorFlow教程中再见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P3:L3- 具有顺序和功能 API 的神经网络 - ShowMeAI - BV1em4y1U7ib
大家好吗,希望你们一切都好,欢迎回到教程 Nuummerro Tres。
现在我们要创建一个基本的神经网络,构建和训练神经网络有很多理论。你可以跟随这个视频构建神经网络,但当然我也希望你真正理解我们在做什么。因此,为了保持这些视频简洁明了,我将向你推荐不同的优秀资源,以便你能更深入地了解理论,我真的建议你首先这样做。我推荐的第一个资源是 31 个关于神经网络的系列视频,这些视频非常适合建立直觉和理解。如果你想要更深入的解释,我推荐安德鲁·吴的深度学习专业课程的第一和第二个课程的这些视频讲座,这三个播放列表都将在视频描述中列出。
让我们开始导入代码,我们将导入 Tensorflow,作为 TF,实际上在这之前我们要导入 OS。
然后我们要做的是 OS 并且做 Veron,我们将设置 TFF CPP min log level 等于 2,这样将忽略 Tensorflow 的信息消息,但我们仍然会收到错误消息等等,然后我们就可以继续。
从 TensorFlow 导入 KaRS,让我解释一下什么是 CARS。自 TensorFlow 2.0 以来,KaRS 已与 TensorFlow 集成,是官方的高级 API,本质上是构建神经网络和模型时的首选。因此,构建神经网络时,你将使用 CAS,具体而言,根据你在创建模型时所需的灵活性,你将使用 CAS 的不同 API,更具体地说,在这个视频中我们将查看 CAS 的顺序 API 和功能 API。
然后我们将从Tensorflow cares导入layers以导入我们今天将使用的数据集,我们将从Tensorflow ks data sets导入Mist。我们今天使用的数据集是Mist数据集,我会保持简短,因为我知道你们中很多人厌倦了听关于Mminist的事情,所以基本上它是数字的图像,范围从0到9,我们有60,000张训练图像和10,000张测试图像,图像是灰度的,所以它们只有一个通道,像素为28乘28,因此相对较小。如果你在GPU上运行时遇到任何问题,那么你应该尝试复制粘贴这两行代码,但如果没有问题,那么你就不需要复制它们了。另外,我注意到这里应该只有1f,所以Tf。
好吧,那么无论如何,让我们继续,现在让我们实际上开始加载我们的数据集,我们将加载训练数据集。所以我们将加载X train,然后是Y train作为标签,还有X test和Y test。我们只需执行emminist load data,然后打印X.dot.shape。还有。打印Y train的shape。我们有60,000张图像,它们都是28乘28的。现在。
这里有一件事,我们将把它们发送到神经网络。所以我们需要将它们展平,以便我们只有一列长的特征值。我们可以通过执行x train等于Xtrain.dot.reshape-1然后784来做到这一点。所以这里的-1意味着保持该维度上的任何值。在这种情况下是60。
000,然后放置,这将是28乘28。所以我们要将这两个维度展平。还有。现在当我们加载数据时,它们将是nuy数组,并且它们也将是float 64,所以我们可以做s type,然后是float 32,只是为了减少一些计算,然后我们还希望规范化这些值,使它们不再在0到255之间。
我们希望将它们归一化到0到1之间,以便更快的训练,所以我们将除以255,然后对xt x test执行相同的操作。所以x test。reshape-128乘28。然后,S type。Flolow 32,然后除以255。所以这些将是nuy数组,你可以做类似于xtrain等于Tf convert to tensor,然后你可以对Xtrain和ytrain等做类似操作。但实际上这将由Tensorflow内部完成。
所以如果它在nuy数组中,我们不需要太过担心。转换将自动发生,可以这么说。所以我们现在要做的第一件事实际上是创建一个模型。我们将创建一个基本的神经网络,并使用KRS的顺序API,你可以将顺序API视为非常方便,但灵活性不是很高,对吧。
非常方便,但灵活性不高。所以我所指的是,例如,它只允许一个输入映射到一个输出,这是一大限制。但是如果你有一个输入到一个输出,那么顺序模型正是你想要使用的。因此,我们创建这个的方式是使用model = ks.sequential。
然后我们将发送一个列表,这个列表将是层,因此我们要做的第一件事是做密集层。这是一个完全连接的层,假设我们想在网络的第一层中有512个节点,然后我们将设置激活,所以我们只需将激活设置为,然后我们将使用reL激活函数,然后你就可以将它们写成层,这样它将自动通过这些层发送,因此例如我们想要另一个层。
另一个完全连接的层,使用密集层,假设我们想要256个节点,然后激活设置为re,对于输出层,最后一层我们想要密集层,并且我们想要映射到10个节点,每个数字一个节点,并且在这一层我们不想要激活。
函数,因为这是我们的输出层。我们将在输出层使用softmax,但这将在损失函数内部完成。然后我们将执行model.compile,在这里我们基本上告诉Keras如何配置我们网络的训练部分,例如,我们将指定要使用的损失函数,我们将使用Keras损失的稀疏分类交叉熵。然后我们将有一个参数,设置from_logits = true,这是因为我们没有softmax激活,所以当我们设置from_logits = true时。
它将首先发送到softmax,然后将其映射到稀疏分类交叉熵,所以你可能对交叉熵损失比较熟悉,当它是稀疏分类时,意味着标签,所以ytrain标签只是对应正确标签的整数,例如,如果它是数字3。
然后该特定示例的y train将只是3,如果你去掉稀疏,所以你会使用分类交叉熵。那样你需要有独热编码。但在我们的情况下并不是这样。然后我们可以指定优化器,因此我们将使用Ks.optimizeims.adam,作为参数我们可以设置学习率,所以我们设置为0.001。
然后我们也可以指定指标。在我们的案例中,我们希望指标为准确率,以便CA在训练期间跟踪当前的运行准确率。然后在使用model.compile后,我们可以进行model.fit。所以你可以理解model.compile指定了网络配置。
关于损失函数、优化器等,然后在model.fit
中我们实际上指定了网络的具体训练。我们想要传入x_train
和y_train
,然后指定要训练的批大小。
假设我们设定为32,然后设定我们想要训练5个周期。然后我们可以使用verbose=True
,这样每个周期后就会打印结果。否则你会看到一个进度条,不过无论如何,在训练之后我们想要评估模型,所以我们将调用model.evaluate
,并发送x_test
、y_test
和batch_size=32
,然后verbose
,因此这里不需要指定周期数。
我们只训练一个周期。所以如果我们现在运行它。仅运行5b
批次,我们在训练集上得到约99%的准确率,在测试集上为98%,这还算不错。现在我想谈谈的就是如果我们首先指定输入,我们会使用Keras.Input
并指定输入的形状。
在我们的情况下为28x28。然后我们可以调用model.
,所以我们可以打印model.summary
。好的,让我们在这里退出代码,我将执行exit
,然后我们可以看到网络的一些信息。例如,我们的第一层有512个节点,参数有400,000个,接着我们可以看到256、130和130k,最后输出层有10个节点。
5k参数,如果我们移除这个输入,即input_shape
,我们就无法打印model.summary
,或者说我们可以打印model.summary
,但必须在model.fit
之后进行,也就是说在我们实际传入数据之后。使用这个input_shape
可以让你获取关于模型本身的更多信息。
我们现在创建了模型,使用Sequential
并指定了所有层,你也可以这样做:model = Ks.Sequential
。然后可以逐层添加,例如,model.add(Ks.Input)
,然后形状为784。接着我们可以model.add
添加层。
所以我们做同样的网络,然后激活函数为relu
。然后model.add
添加层,节点数为256。激活为relu
。最后一层,节点数为10。令人惊讶的是,你可以逐层添加,然后可以打印model.summary
。进行这些模型摘要是一个更常见的调试工具。也许对这些非常简单的神经网络不适用,但当你构建更复杂的模型并想查看每一层时。
输入对于这些特定层的变化有多大。你可以做model.summary,然后添加一层,你可以再次做model.summary,依此类推。所以这里有两种使用顺序API的方法,正如我所说的,它非常方便,但不够灵活,因为我们只能将一个输入映射到一个输出。这并不意味着顺序API在任何方面都是糟糕的,如果你能使用顺序API,你应该这样做。所以这就是。
如果你无法使用它,你该怎么办,那时我们转向功能API。功能API更灵活。例如,我可以处理多个输入和多个输出。所以让我向你展示它是如何工作的。我们将首先指定输入,因此我们将执行该输入并设置形状为784。然后我们将做x等于。
层的密度为512,所以我们将构建完全相同的网络,然后可以进行激活等于relu,然后在你初始化这个层之后,你将用输入调用它。好的,在这种情况下是我们之前定义的那个,然后对于下一个层,我们将做x等于layers do1s到256激活等于relu,然后在这里我们将传入前一个层,所以在我们这里是x,然后对于输出,我们将做outputs等于layers do dens,然后我们将做10个节点,顺便说一句,为了换换口味,让我们进行激活等于softmax。
然后在那上面做X。现在,仅仅因为我们在这里使用了激活等于softmax。这从Loist来看是不正确的,因此我们必须将其更改为false。这也是默认的默认参数,所以我们也可以完全移除它。现在让我们重新运行这个,看看它是否有效。抱歉,我忘记了一行,这一点非常重要。
所以我们在这里看到的一个问题是准确性没有提高。如果你仔细想想,我们没有在这个模型上使用softmax,而这是我们最新定义的模型,因此你可以看到使用softmax是多么重要,但无论如何。
我们需要做的是model等于ks.model。然后我们需要指定input等于input。然后output等于output。好的,这就是我们需要做的所有事情。它将接受我们在这里定义的这些输入和输出并构建模型。现在如果我们运行这个,希望它能正常工作。
所以正如我们现在看到的,我们得到了与第一次运行模型非常相似的结果,大约98%,在测试集上也是大约98%。所以像往常一样,你也可以在这里打印模型的摘要,获取关于模型的信息。你还可以命名特定的层,比如我们可以做成类似“name equals first layer, name equals second layer”,然后如果你运行model.dot summary,我们将在这里看到第一个层,第一层密集层,因为这是我们命名的,它将被命名为“first layer”,然后是“second layer”。
现在我还想展示一些如何提取特定层输出的细节,这在调试时可能会很有用。所以这将适用于无论是使用顺序模型还是功能模型。我们就以顺序模型为例。所以我将设置退出条件,以便我们专注于这个模型。我们将重写这个模型,执行model equals kos.dot model,然后我们将输入设置为model.do input,然后输出。
我们将指定model.dot layers,然后如果我们执行-1,那将是输出,也就是最后一个层。所以如果我们举个例子执行-2,我们将得到那个层,然后需要指定dot output,因此我们可以执行类似于“feature equal model.dot predict”的操作,这里“model.dot predict”是用于我们发送的特定例子,因此在这种情况下,我们发送多个例子,实际上是所有60个。
不过无论如何,我们可以打印feature.dot shape,然后我们将获得60,000和256的形状,这就是你可以做到的一种方式。你还可以指定一个名字,比如“my layer”,然后可以执行model.dot get layer,指定“my layer”,然后点输出。如果我们运行这个,我们将得到完全相同的结果,只是根据那个特定层的名字来获取层。
你可以获取所有层的输出,可以通过“layer do output for layer in model.dot layers”来实现,这样我们就会得到所有的特征。例如,我们可以对特征进行循环,并打印feature.dot shape,所以如果我们运行这个,我们将获得所有层的输出,第一层、第二层和第三层的输出。因此,在调试时这可能会很有用。所以让我们实际去掉那些,以确保代码按我们最初编写的方式正常工作。
这里有几个建议,可以尝试代码并获得更多经验。首先,你可以尝试通过增加模型大小、延长训练时间等,看看能获得什么准确率。你应该能够在测试集上至少超过98.1%。
我的第二个建议是尝试使用不同的优化器,比如说尝试带动量的梯度下降、Adam和RMSProp。看看哪个能给你带来最佳结果。第三个问题是,如果你去掉数据的归一化,是否会有任何区别。这些是使用Keras创建神经网络的一些基础,利用顺序模型和函数式API。在未来的视频中,我将展示更复杂的函数式API示例。但在此之前,我们将学习如何构建卷积神经网络。所以谢谢你的观看,希望在下一个视频中再见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P4:L4- 具有顺序和功能 API 的卷积神经网络 - ShowMeAI - BV1em4y1U7ib
欢迎回来,大家希望你们一切都好。在这个视频中,我们将继续并构建一个卷积神经网络,和往常一样,视频描述中有资源链接,可以进一步了解本视频的概念。所以话不多说。
让我们开始吧。我们首先导入 OS,然后我们将使用 OS dot environment 设置 Tf CPP Min log level,这只是为了忽略 Tensorflow 的一些信息消息,这些消息可能会让人有点烦。接着,我们将导入 Tensorflow,使用 Tf。从 Tensorflow 导入 ks。
从 Tensorflow dot ks 导入 layers,然后从 Tensorflow dot Cars 导入数据集。我们将导入 Cypher 10。所以在这个视频中,我们将看看 Cypher 10 数据集,它基本上是来自 10 个不同类别(如飞机)的更多自然图像。
汽车、手机、鸟、卡车等等。图像如下。
我们有 50,000 张训练图像,10,000 张测试图像,总共 60,000 张,每张图像是 32 x 32 像素,所以它们相对较小,而且是 RGB 彩色的,因此它们有三个通道。我发现了 Andrea Kpathy 的一篇很有趣的博客文章,他实际上自己在 Cypher 10 上进行了训练,并得出结论,看看 Cypher 10 的人类水平准确率约为 94%,如果你查看最近在 Cypher 10 上训练的模型,它们的性能超越了这一点,因此更近期的模型在这个数据集上远远超过人类的表现。
现在我将复制两行代码,你可能并不需要它们,但如果你在 GPU 上运行并遇到任何问题,那么这两行可能会帮助你。好的,回到我们在这个视频中实际想做的事情。
我们首先想要加载 Cypher 10 数据集,这与我们在上一个视频中加载 MNIS 的方法非常相似。所以我们将执行 x train、Y train、X test、Y test,然后调用 Cypher 10 dot load data。我们再次希望将其转换为 F 32,因为在 F 64 中计算效率不高,属于不必要的计算。
我们可以做的是将 xtrain 赋值为 xtrain 的类型,然后为 float 32,然后为了归一化,我们还可以将其除以 255,使像素值在 0 和 1 之间。同样对于 X test,我们可以将 x test 赋值为 x test 的类型 float 32。
然后我们只需除以255。好的。所以对于我们的实际模型,让我们从一个顺序模型开始,然后我们将构建并使其更高级一点。我们将执行model = K.as.Sequential,并指定输入形状。由于我们正在使用卷积神经网络,我们不会在开始时进行重塑。
这意味着我们将保持高度为32,宽度为32,并且有三个RGB通道,所以这就是每个图像的输入形状。接下来我们将执行layers.co2d,我不太确定,32个输出通道是第一个。这里的第一个参数是我们希望这个卷积层输出多少个通道,所以一开始我们有三个通道,我们希望输出为32。接着我们将指定卷积核大小,我们将其设置为3,如果在这里设置一个整数,它将扩展为高度和宽度相同的卷积核大小,所以本质上是更简洁地写出这个。
然后我们可以指定填充方式,在这里你可以选择有效或相同,因此有效是默认的。那么发生的情况是,这些像素值。如果我们使用相同的卷积,那么它们将被保持,因此在这一层之后,它们仍将是32像素的高度和32像素的宽度。
但是如果我们使用有效的填充,那么这将根据我们的卷积核大小而变化。在这种情况下,它们实际上将变成30乘30像素。所以这本质上只是一个超参数,你可以随意调整。我会将其设置为有效,虽然这样做没有意义,因为这是默认参数。
然后我们可以设置激活函数,类似于我们为神经网络所做的设置为RE。接着进行最大池化到D。在这里我们可以指定池大小,假设为2乘2,这样输入就会减半。例如,如果我们在这里使用有效卷积,那么结果将是30乘30,当然你可以打印模型摘要来实际查看这些变化。
也许我们真的可以这样做,所以让我们打印模型摘要。让我们看看。正如我们现在所看到的,第一次过后,将是30乘30,然后我们有32个通道,最大池化后,输入大小像素将是15乘15。接着我们可以再添加几层,所以层数是D。
假设有64个输出通道,内核大小为3。然后我们再次使用有效的填充和激活函数。嗯。再进行一次最大池化。然后,我们将有128个通道,我们只需将其翻倍,再加上3,激活函数为相对。然后对于我们的实际输出,我们将进行层展平,假设有一个中间层,因此我们将在这个全连接层中有64个节点,激活函数为相对,最后我们只需进行密集层,有10个输出节点。
这就是我们的实际模型。然后我们将编译我们的模型。因此,编译模型时指定损失函数为CAs,该损失函数是稀疏的分类交叉熵,与我们在上个视频中使用的相同,因为我们的输出没有softmax激活。然后假设优化器使用Adam,因此我们还需要设置学习率。
设置为3e-4,然后指标保持跟踪准确率。好的。这就是我们模型的编译,现在实际上训练模型。让我们进行模型拟合x_train,y_train,批大小假设为264。然后运行10个周期,设置verbose等于2,这样每个周期后会打印输出,以便你不会看到进度条。
但是它将在每个训练周期打印有关训练的信息。训练后,让我们在测试集上评估模型。然后同样,设置批大小相同,没有周期,因为我们只会运行一次,verbose等于2。好的,让我们运行这个,希望一切正常。
那么,让我们在这里打印模型摘要。然后我们可以检查一下。😔 好吧,所以我们开始训练了。在这里我们可以看到模型的大部分参数。总参数数量为1225,000。
这实际上是一个非常非常小的网络,因此我们并不期待得到非常非常高的准确率,而只是为了说明如何构建卷积层,然后使用最大池化等等。我相信 AlexNet,这是第一个真正革命性地改变计算机视觉的卷积神经网络,大约有6000万个参数,所以让我们来看看225,000究竟有多小。
好的,让我们看看训练是否完成,然后再打印模型摘要。好的,所以我们去掉那个。😔 然后看看我们得到了什么,最后训练准确率为72%,测试准确率为68%。现在你可以看到我们有很大的提升空间。如果你训练更久,可能会得到更好的准确率,但我们并不太关注这个。接下来我们将看看如何使用函数式API构建功能,并构建一个非常相似的卷积神经网络,但我们会添加一些更高级的内容。
让我们做一个函数。首先定义我的模型。然后在里面,让我们设定输入为Kas input
,形状为32,32,3。接下来,让我们设定x
等于layers.com2d
,使用32个通道,卷积核大小为3。然后我们将输入传入该层。
我们将使用批归一化,视频描述中会有相关信息。如果你不熟悉批归一化,我们将初始化它,然后将x
传入。你可能注意到这里没有使用激活函数,这是因为如果我们使用批归一化,我们希望先通过卷积层,然后再通过批归一化,最后通过激活函数。我们可以这样实现。
激活函数是x
的re
。对了,让我们添加一些最大池化。实际上我们不需要指定池化大小,所以让我们看看,是的,我在这里做到了。但我们实际上不需要在这时指定池化大小为2乘2,这是默认参数。
当然,你可以更改为你想要的任何东西,只是2乘2是你最常用的。所以我们先做最大池化,然后通过这个进行处理,再创建另一个层。让我们做layers.column2d
64,我不知道。
让我们设定卷积核大小为5,填充为相同,然后做一个Another batch norm
,也就是批归一化,作用于x
。然后是激活函数activations.relu
,作用于x
。在这之后,让我们再来一次,设置layers.com2d
128,3,然后是x
。然后是另一个批归一化,作用于x
的激活。
然后我们将通过一个全连接层。所以我们将使用layers.dense
,64个节点,激活函数为re
。输出将是layers.dense
的10个节点,作用于x
。然后为了创建我们的模型,我们将设定model = Cas model
,接着需要指定输入和输出。
这将根据这些内容创建模型。因此,我们将输出和输入分别等于输入和输出。然后我们将返回我们的模型,对吧?所以现在这是我们的模型,看起来与之前的模型非常相似,只是我们添加了批量归一化。我们可以做的是用 my_model
来表示模型,然后可以使用与顺序模型相同的编译、拟合和评估方法,所以现在让我们来运行它。
好的,我们出现了一个错误。让我们看看问题出在哪里。好的,我想我知道问题所在,我们需要在中间添加一个扁平化层,因为当我们通过全连接层时,形状将不匹配。因此,我们将使用 layers.Flatten()
,然后对X进行处理,希望这次可以正常工作。好的,我们可以看到的一件事是,在使用这些批量归一化后,经过10个训练周期,训练速度明显加快。我记得之前的训练准确率为72%,现在几乎达到了93%。
尽管测试集的准确率并没有显著提高,我认为实际上有所下降。这显然是模型对训练数据过拟合的迹象。因此,当模型过拟合时,我们需要以不同的方式使用正则化。实际上,我们将在下一个视频中查看如何改善这个问题,以使这两个结果的差距缩小一些,而不是如此之大。
这里有几个建议,可以尝试对代码进行修改,以获取更多的经验。首先是检查你在测试集上可以获得怎样的准确率,通过延长训练时间或增加模型大小,可能还可以通过改变内核大小、调整填充等方式来尝试。第二点是在上一段视频中,我们在Eminist上训练了一个全连接神经网络,使用COvnet处理该数据集会得到怎样的结果。不过不管怎样,在这个视频中你看到的是如何使用顺序和功能API来训练一个基本的神经网络。如果你有任何问题,请在下面的评论中留言。非常感谢你观看这个视频,希望在下一个视频中见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P5:L5- 使用 L2 和 Dropout 添加正则化 - ShowMeAI - BV1em4y1U7ib
大家好,欢迎回来观看另一个Tensorflow教程,在上一个视频中,我们构建了一个简单的卷积神经网络,当我们训练它时,我们发现训练准确率和测试准确率之间存在相当大的差距,当出现这种情况时,我们定义模型对训练数据过拟合。现在我们称减少过拟合的方法为正则化,有多种正则化方法,简单提一下,你可以减少模型容量以避免过拟合,或者添加L2正则化、dropout、早停或数据增强。如果你不熟悉这些术语,请确保观看我之前提到的理论先修视频,我们将在这一系列教程的最后探索所有这些正则化方法,但在这个视频中我只想向你展示如何将L2正则化和dropout添加到我们的模型中。
所以在这个视频中,我们将保持简单,其他方法在我看来最好放在单独的视频中,以保持视频更加简洁。我们要做的第一件事是从Tensorflow导入层,但我们还将添加正则化器。
然后当我们向下滚动到我们的模型时,我们首先添加L正则化,你需要为每一层单独添加它,因此为了简单起见,我们也将做padding等于same,然后我们需要执行kernel regularizer。
正则化器.dot L2。然后我们将设置该特定层的去正则化权重。因此我们将其设置为0.01。然后我们必须对所有层执行此操作。因此在这一层。我们也将做padding等于same,仅为简单起见。我们将执行kernel regularizer等于regularizer L2 0.01。然后我们只需要一个更多的步骤。
所以我们将要进行操作。同样在这里。添加等于相同。列常规正则化器等于正则化器做L20。01。然后我们也将其添加到这里的全连接层。我们将添加dropout,但我们也会添加正则化。因此我们将使用两者。设置相同的权重。
然后在这些层之间,我们将设置一个dropout层。所以让我们做layers.dot.dropout。然后设置一个值为0.5,这样它将丢弃这层和那层之间的0.5连接。然后让我们通过它运行x。因此现在我们已经添加了L2和dropout。我还想提到的是,我们添加了批量归一化,批量归一化的目的是更好地规范化数据,以实现更快的训练等等。
但是它也有一个正则化的效果,因此批量规范也可以看作是一种正则化形式,所以现在我们使用的确实是三种方法:L2、dropout和批量规范。使用像dropout这样的正则化时,训练时间会更长,因为我们在每个批次之间丢弃了许多连接。所以我们在这里做的是,不是训练100次,而是实际上要运行150次。
然后让我们看看得到的测试精度如何,以及这是否比上一次训练有所改进。好的,所以在150个周期后,我们得到的训练精度为82%,测试集约为74.5%。所以看起来我们确实需要训练超过150个周期,但至少在这里我们可以看到,在上一个视频中,我们有大约93%的训练精度和72%的测试集,在这种情况下,它们之间的差距要小得多,范围明显减少。我认为如果我们再训练更久,会有更好的效果。
差距会变大,但不同之处在于我们已经看到对测试集的泛化能力更好,即使训练精度低了很多。最后一个视频的名字,不过无论如何,这个视频相对简单快捷,仅展示了如何添加L2和dropout正则化,我们将在未来的视频中探索更多添加正则化的方法。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P6:L6- RNN、GRU、LSTM 和双向性 - ShowMeAI - BV1em4y1U7ib
大家好,希望你们过得不错,放上引言,然后我们来聊聊 RNN 等等。
好的,我有我们通常需要的导入。这是为了忽略可能相当烦人的 Tensorflow 消息。尽管我们仍然会收到错误消息,然后使用 Tensorflow 的层构建我们的层,还有 emminis 数据集。这只是为了如果你在 GPU 上运行时遇到任何问题,这两行通常会帮助你。好的,我们来开始我们实际想做的事情。
我们将开始加载数据,因此我们将做 Xtrain,Y train,然后 X test,Y test。等于 Ms.dot.load data,然后我们将 Xtrain 设置为 float 32 类型。当前是 float 64,为了节省计算,我们将其转换。然后我们将通过除以 255 来归一化,使其位于 0 到 1 之间。
对于测试集也做同样的处理。所以流 32,除以 255。那么我们这里做的是什么呢?我们有一张 28x28 像素的图像,当我们把它送入 RNN、GRU 或 LSTM 时,会是怎样的呢?我们会用这三种模型,但实际上我们会针对每个时间步展开图像的一行。比如对于特定的时间步,假设第一个时间步,它将取图像的第一行并发送,然后对于第二个时间步,它将取第二行并发送。为了澄清,你不会使用序列模型来处理图像。
这不是最好的模型,您可以使用我们在两段视频前讨论的 CNN,但使用 RNN 也能奏效。正如我们将看到的,尽管数据集并不理想,但我们将获得合理的性能。这更多是为了说明如何在 Tensorflow 中实际实现 RNN、GRU 和 LSTM,而数据集并不是最佳选择。
不过我们只是选择一个简单的例子来说明。好的,话不多说,实际上我们要做我们的模型,我们将使用 keras 的 sequential。我们会添加模型,然后指定输入。在这种情况下,我们将指定 none 和 28。这里指定 none 是因为我们不需要一个特定的时间步数,所以我们每个时间步有 28 个像素,而在这种情况下,我们实际上有 28 个时间步,但不需要指定该维度。
然后我们将创建一个模型。添加简单的 Rn 层。所以这只是一个基础的 Rn。然后假设有 512 个节点。作为附加参数,我们可以设置 return sequences 为 true,这样它将返回每个时间步骤的输出,这样我们可以在多个 RnN 层之间叠加,所以这个 RnN 的输出将是 512 个节点,然后返回序列在这种情况下会输出每个时间步骤的 512,因为我们将有 28 个时间步骤,然后我们也可以进行激活,将其设置为 Relu。
然后我们可以再添加一个,可以要求添加简单的 Rn 层,我们再做一次 512。我们将设置激活为 Relu。对于输出层,我们将添加模型层。dense,我们将有 10 个输出节点,因此你会注意到在这个第二个简单的 RnN 中,我们没有设置 return sequences。因此对于输出我们没有 return sequences 等于 true。意味着它将传递每个时间步骤,然后在这个简单的 RnN 的最后输出。
我们将在上面添加一个 dense 层,并将有 10 个输出节点。首先做打印模型摘要,所以我们可以看到这里的模型摘要,对于第一个 RnN,我们将有 none none,然后是 512,所以我们将有 512 个输出节点,每个时间步骤都有。我们之所以有 none 和 none,是因为我们有一个是针对批次的,另一个是针对隐藏状态的。我认为这个是针对批次的,另一个是针对隐藏状态的。然后在第二个层中,我们没有设置 return sequences 为 true,因此我们只有 none 对于批次,然后从最后的隐藏状态得到 512 个节点,当它处理所有输入时。最后我们只需要在此基础上添加一层。因此,现在我们要做的就是模型编译,并指定损失函数,使用 ks 的损失 sparse category。
croros entropy,然后我们将设置 from logics 为 true,因为我们在最后的 dense 层没有 softmax。然后优化器,我们将使用 ks 的优化器,设置为 atom。我们将学习率设置为 0.001。然后指标,我们只需跟踪准确性。现在我们要做的就是在训练集上使用模型进行拟合。然后指定批量大小,假设为 64。然后让我们运行 10 次。
而 verbo 等于 2 只是为了每个周期打印。然后在最后,我们想对我们的测试集进行评估。所以我们将发送 X 测试和标签 Y 测试。我们还将指定批量大小为 64,然后再次设置 verboos 等于 2。好吧。那么我们来运行一下,看看是否能成功。好吧,在 10 个周期后,我们在训练集上得到了 98%,在测试集上也接近 98%。
我想在这里提到,我们使用了ReLU激活函数。训练递归网络的默认设置是使用tanh。我不知道在这种情况下是否会更好,但无论如何,我只是想提一下。如果你不指定激活函数。
在构建这些递归网络时,默认是使用tanh。因此,还有一点是,运行这个过程比我想象的要长一些,所以我们在下一个模型中使用256个单元。我们现在想做的基本上是一样的,但我们想构建一个GRU。我们要做的就是将这个简单的RNN更改为GRU,这几乎就是你需要做的全部。因此,如果我们现在重新运行,我们可以看看结果。我想这不是一个公平的比较,但GRU的性能应该优于简单的RNN,尽管我们现在使用了一半的单元,并且使用tanh而不是ReLU,但重点并不是比较,而是展示它的有效性,以及如何使用简单的RNN和GRU。
LSTM相对简单,我们只需将其更改为LSTM,但无论如何。我还想展示如何实现双向层。好的,在10个epoch后,我们在训练集上达到了99.5%,在测试集上接近99%。这实际上相当不错,两个层的GRU,256个单元,能达到这个水平确实不错,所以现在我们将其更改为LSTM,看看是否有所改善。
LSTM和GRU在性能上是等效的。我认为LSTM稍微优于GRU,但让我们看看在这个数据集上是否如此。好的,似乎我们的性能几乎是相同的。LSTM稍微好一些,也许在测试集上,但大体上是一样的。
所以我们现在想做的是,不仅使用单向LSTM,而是使用双向LSTM,添加它非常简单。我们只需添加双向层,就像这样。然后像这样。因此,我们将添加双向层,然后发送LSTM层。
让我们为第二个节点这样做。或者说,让我们开始吧。那么我们先打印一个模型总结,看看它的样子。好的,我不打算让它训练。所以从这里可以看出,由于我们添加了这个双向层,我们将得到512个节点,而不是256个。因此,我们在LSTM中为每个隐藏状态的计算指定的节点数量是256。
但是,由于我们添加了双向结构,我们将有一个向前和一个向后的节点。所以这里的节点数量会加倍。如你所见,我们可以对第二个节点也进行双向层的操作。
我们可以添加这个。😔,就在这里,这也将有512个节点。那么我们来运行一下,看看双向是否比单向的LSTM好。经过10个epoch,我们看到性能与单向使用基本相同,所以双向并没有真正起到帮助作用。我也不太确定为什么,可能只是需要更多的训练,或者它并没有那么大的帮助。
对于这个特定的数据集,但通常情况下,使用双向作为默认设置是一个不错的选择。不过无论如何,这就是如何进行简单的RN、GRU和LSTM的基础知识,以及如何添加双向性。在这个场景中,我们使用了MNIS数据集,所以使用Ms数据时我们给自己提供了很大的便利。在训练更复杂的数据时,你需要考虑更多的事情,比如为每个批次填充和屏蔽数据,我们将在未来的视频中讨论,当我们加载更复杂和自定义的数据时。
感谢观看,希望在下一个视频见到你!
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P7:L7- 函数式 API 的更深入示例 - ShowMeAI - BV1em4y1U7ib
大家好,希望你们过得不错,欢迎回来参加另一个TensorFlow教程。我有点愧疚,因为到目前为止,我们一直在使用顺序和函数式API,但实际上我提供的示例并不需要使用函数式API,所以我想给你一个更真实的例子,在这个例子中你确实不能只使用顺序API。我们再来看一下MNIST,但稍微有些不同,我们现在每个示例有两个数字,例如这里有数字零和一。
我会在描述中提供一个链接,以便你可以下载这些内容,以便你也能跟着视频一起学习。不过,我们现在不会专注于自定义数据。因此,实际数据的加载将在未来的单独视频中进行。现在我只是想给你一个更实际的例子,说明函数式API如何变得有用。所以让我们开始代码,这里是我们一直在使用的基本导入,还有一个是pandas,这将用于加载数据集,你可以使用Conda安装pandas,我相信这样你就会得到这个。因此,正如我所说,我们不会专注于实际的数据加载部分,意味着我将在这里复制粘贴一些东西,我不喜欢复制粘贴,但我们不会在这个视频中关注那部分,所以在描述中也会有一个链接,你可以复制粘贴这段代码。
我将粘贴代码,基本上这是用于加载实际数据的代码。所以我们使用pandas从CSV文件读取数据,然后使用Tf数据,再次强调,我将在另一个视频中详细讲解如何加载数据。所以我想重点关注的是,现在每个示例有两个目标值,这意味着我们不能使用顺序模型,因为顺序模型只能将一个输入映射到一个输出,但现在我们实际上有两个输出,所以我们要构建一个模型,记住我们必须现在使用函数式API,所以我们将从Keras开始。
输入形状我们将指定为64乘64像素,并且它们只有一个通道,因为它们是灰度图像,然后我们将使用一个2D卷积层,假设过滤器数量为32,我们将指定当前值。
假设大小为3,为了简单起见。然后是的。我想我们可以设置相同的填充,然后我们还要进行正则化。所以让我们回到顶部,我还想指定一些超参数。让我们来设置超参数。并且指定批处理大小。
我们做64,然后指定权重衰减为0.001。关于我们两部视频前所做的L2归一化,我相信。然后我们指定学习率为0.001。好了,现在我们回到模型。我们将做卷积正则化器。我将T cart。实际上,我们可以。
我们还可以导入这一点。所以我们来做层。输入正则项。然后,返回。😔。然后正则化器点L2,再加上权重衰减。好的。然后我们得到一组输入。现在我们来做一个批量层。所以层批量归一化X。到目前为止,没什么新鲜事,对吧,我们之前都做过这些。
而且没什么不同,但我只是想给你一个更深入的示例,实际上你会使用这个。所以区别在于我们得到输出时。但无论如何。然后让我们做Keras的激活函数为relu,然后再做一个卷积到。嗯,我不知道,假设64,3,然后卷积正则化器等于正则化L2的权重衰减。
然后我们也将输入X传入。再一次。我们将做一个批量归一化,传入x,然后Keras激活为relu。对x做一个最大池化。嗯。我不知道。我们再做一个卷积层。卷积到。让我们指定64和3。然后做relu。所以这里没有池化,然后是卷积正则化器。
Keras只是正则化L2的权重。好的。然后。是的,我们可以再做一层,所以到D 128的过滤器,现在我们将其加倍,激活为Relu,然后传入x。然后我们可以做一次最大池化,然后。让我们扁平化。现在我们来得到输出。我们要做的是做一个全连接层。
所以层是128个节点。让我们设置激活函数为值,然后发送下一个。并且。我们还要添加一些正则化,所以我们来做层丢弃0.5,然后传入X。然后。是的,我们实际上可以再做一层,所以我们来做层64,激活等于X的值。现在我们得到实际的输出。我们现在要做的是什么。
我们来做输出1,并做一个全连接层。你将做10个节点,然后。我们给它一个名字。让它成为我们的第一个数字。然后我们将传入x,再做输出2。我们将做层10,名字为第二个数字。然后我们将传入x。所以如你所见,我们使用输入X映射到两个不同的输出,对吧,这实际上会给出两个不同的分支,这就是功能API变得有用的时候,对吧,就这两行,因为我们使用顺序模型是不错的。
这非常简单,非常紧凑,但它不能像这样做事情。这就是当我们实际上必须使用功能时,它是如此狭窄,你也可以将它们结合起来。例如,你可以在顺序模型中这样做,然后你可以在功能模型上做这两个。所以你也可以结合这两者。但无论如何。
我只是想说这只是为了两个输出,然后我要做模型。
模型关心的是模型输入等于输入输出现在是一个列表,我们将进行输出1。输出2。当我们执行模型时。😔,编译。我们将设置优化器。让我们使用Adam优化器。然后在这里设置学习率。接着我们将指定损失。而损失实际上将是两个损失。
所以我们将进行损失,稀疏。我们将使用稀疏分类交叉熵。并且从large,它等于true。或者实际上,这次我们去掉它。这样做。我们可以在这里指定激活等于softmax。就这样。这样我们就不需要从Loit做了。所以激活是softmax。
然后我们将进行一个损失函数。我想有一种方法可以让这个更紧凑。我实际上还没有尝试过,但我认为如果你只是指定这个,那将对两者都适用。但你可以试试看。所以安全的方式就是将它们全部写上。因此我们将使用稀疏的分类交叉熵。
对于两者。然后我们想跟踪指标等于。准确性。现在和往常一样,我们将在这种情况下执行模型训练。我们只需传入训练数据和批量大小,所有内容都在数据加载部分内部处理,而我还没有再次覆盖。但我们不太关心这个,然后让我们做5个epoch,两个都等于2,然后模型进行评估。
在测试数据集上进行评估。然后verbose等于2。是的。所以让我们运行这个,看看当我们在这个多位数的Mist上训练时,如果不出错我们会得到什么样的准确性。所以我们。Cars没有属性。😔,激活,所以我相信我们得做激活。让我们找出那个错误,看看。激活。回去。😔,来了激活。
所以激活就在这里。希望没有其他地方。会有更多。好的,所以我可能忘记在这里发送它。😔,还有其他错误吗,让我们看看。我找不到更多错误,所以我们再运行一次。好的,输出一次是输出一次。是的,我们可以做输出。所以我称之为输出。就这样。现在,请工作。得到了。
没有为第一个提供数据。数字。好的,所以经过很长时间,我想我找到了错误。错误是没有为第一个数字提供数据。每个键在第一个数字和第二个数字中都有数据。好的,令人惊讶的是。我不知道为什么,但如果我只是去掉。这样说第一和第二。
然后如果我重新运行它,它实际上开始训练而没有错误。实际上我不知道这是为什么。如果你知道,请评论,因为我对此非常惊讶。这可能是我遇到的最奇怪的错误之一。在五个完整的训练周期后,我们在训练集上对这两个数字几乎都达到了96.3%。有趣的是,当它开始识别其中一个数字时,它也开始识别另一个数字,因此它们几乎是同等水平地提高。如果你继续训练,我猜它们会有相当大的提升,但在测试集上又如何呢。
我们得到了大约90%,但是在第二个值上只得到了83,所以我猜在测试集上可能更难识别第二个数字。不过,我还想检查的一个事情是,如果我们去掉,然后只用一个损失函数,那如果能扩展到两个函数就好了,所以我们来试试看,这似乎是有效的。好了,这就是本视频的内容,感谢你的观看。
看看Fun API的一个更实际的例子,非常感谢你观看这个视频,希望在下一个视频中再见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P8:L8- 使用 Keras 进行模型子类化 - ShowMeAI - BV1em4y1U7ib
大家好!希望你们一切都好,欢迎回来观看这个视频。我们将迈出构建模型的下一步,学习模型子类化。这是一种极其灵活的构建模型的方法。到目前为止,我们接触到了顺序 API,它的灵活性很小,但使用起来非常方便;我们也看到了功能性 API 的例子,它在构建模型时提供了更多的灵活性。在这个视频中,我们将使用子类化,这是最灵活的方法。所以我会复制所有的导入和其他内容,我们之前都见过这些,确保不浪费太多时间。导入 OS 和忽略 TensorFlow 的信息消息,使用 Keras 的层来构建我们的模型。这两行代码将帮助你解决在 GPU 上运行时遇到的问题,然后这三行代码将加载数据集。
我们正在加载 MNIST 数据集,然后在这里进行形状调整。我们只是在这里调整形状,以添加通道数量的维度,然后将其转换为 F32,并通过 255 进行归一化。好吧,这些都是你之前见过的内容。现在我们想要做的是,首先激励一下我们要做的事情:我们已经看到了一个卷积网络的例子,并将其映射到批量归一化,然后再运行。这个结构我们已经使用了多次,假设你需要写这段代码 10 次,那将会写出很多代码。所以我们实际上可以为这种块创建一个类。让我们来做这个,定义类 CNN 块。
我们将从层继承,这将跟踪所有进行反向传播等操作的内容。然后,我们创建一个初始化函数,指定输出通道的数量,以及内核大小。如果你熟悉 PyTorch,子类化的使用与创建 PyTorch 模型是完全一样的。
首先我们创建我们的初始化函数,了解如何构建这个模块,并使用 super 来运行父类层。然后我们将做 CNNM 块的初始化,并创建我们的组合层。因此,Seph.co 是 layers.Com2D,我们将指定输出通道和内核大小。
然后我们让填充保持不变。然后对于批归一化,我们将只做 layers.batch.normalization。然后我们将只做调用方法。所以我们将做调用输入张量,然后我们将指定训练。我们将其默认设置为训练,默认值为 false。
所以我们在这里指定训练,因为我们使用了批归一化。批归一化的工作方式在训练模式和评估模式下是不同的,但无论如何。我们有一个调用方法在这里。调用方法,如果你熟悉 Pytorch,本质上就是前向方法。但无论如何。
所以我们正在初始化要使用的模块,这里是 comm 2 D 和批归一化。然后在调用方法中,我们接受一些输入张量,并将其通过这些层运行。因此,我们将做 x 等于 self.com 的输入张量,然后我们将做 self.baor 的 x。
然后我们将指定训练等于训练,然后我们将做 x 等于 Tf.nn.Relu.Of x。所以我们正在进行批归一化的 ReLU,然后我们将返回 X。这就是我们在这里看到的结构。虽然现在我们可以多次从这个类中重用它。例如,我们可以做一些类似的事情。我们的模型是 Kra.dot.sequential。
然后我们要做 CNN 块,假设我们有 32 个输出通道。CNN 块 64 个输出通道。CNN 块 128,然后层展平。然后层1s 10 个节点。好的,如果你在这里写这段代码,仅仅为了这个块,它将是多行。三行,对吧,它将是批归一化、ReLU 和其他的,这会非常麻烦,会占用不必要的空间,并且不那么简洁。所以这是我们可以做到的一种方式,我们也可以现在指定,所以我们可以做 model.compile。
我们可以做优化器等于 ks.do.optimize.do.atom,我们可以做损失等于 ks.losses.spars.Pateorical.cross.entropy,然后从逻辑上讲等于 true。指标,我们将使用准确率作为指标。然后我们可以做 model.fit。在我们的 x train,y train。批大小,64 轮次。我不知道,3。然后详细程度等于 2,然后让我们也做 model.evaluate x test,y test。
批大小为64,两个都等于2。然后我们运行它。所以经过3个块后,我们在训练集上获得99%的准确率,在测试集上为98.75%。创造这些块并调用这些方法的惊人之处在于,它感觉非常像Pytors,如果你习惯了,但如果你习惯于Nmpy,它又像是在使用Nmpy。我听说这有点像面向对象的Nmpy,我同意,因为这感觉非常直观,我们可以做诸如打印X.dot shape的事情,每次调用时,它将打印出此时x的形状,而这个CNN块根据通道运行多次,第一次是32,然后是64,再到128,然后再次运行,因此是32,6428,这使得调试变得非常简单。
这样做可以让你在任何你想打印的地方打印形状。不过,让我们现在做一些更复杂的东西,或者说一个更大的模型。我们要创建一个名为Resblock的类,所以我们将构建一些类似于Resnet的东西,并希望在这个视频结束时,你能够从这样的角度看待:如果我们使用功能性或顺序API重建一些类似的内容,或许你会觉得这非常好。
非常困难或占用很多空间,并不像我们在这个视频中那样紧凑。因此,如果你不熟悉Resnet,可以观看描述中的视频,以便更熟悉。我们不会重建Resnet,而是做一些类似于Resnet的事情。所以我们再次进行层叠层。
然后我们将进行初始化。接下来,让我们设置通道。好的,所以我们来做一个res block。首先,我们需要调用super init。然后假设这个res block将包含三个我们创建的CNN块。因此,我们可以在这里传递通道,假设它的默认值。
我不知道,32,6428,类似这样的。然后我们将做一些。其实,让我们不初始化它们。假设我们有通道。它将是一个包含三个值的列表。我们将创建三个CNN块。所以让我们做self CNNN 1是CNN块,然后我们将使用通道,通道0和卷积核大小3。
而且我们实际上不需要指定这一点。所以记住,我们在这里使用关键字参数,并将其设置为3,因此可以保持这样,然后是self.dot CNN N 2。我们将做另一个块,使用通道1。然后self CNN3,我们将进行CNN块,通道2。接下来我们可以做一些类似池化的操作。
Layers.dot max oing 2 d。😔,然后所以。我们将运行三个这样的块,每个块都是一个CNN,一个batchor,然后是Relu,接着我们将运行一个最大池化,以保持输入尺寸的高度和宽度。然后我们将使用一个身份映射,类似于Resnets,配合这些跳跃连接。因此我们要做的是进行身份映射,以确保它具有相同的通道数量。
所以记住,我们不改变,因此我们使用相同的卷积,所以高度和宽度不会改变。但通道可能会改变。因此我们需要进行身份映射,我们将设置层来D。我们只是指定通道为1。然后我们将做卷积核大小为3。添加保持相同。然后对于调用,如果这一点有些。
现在这感觉不是很清楚,不用担心,我会再解释一遍。但我们将使用冷静的方法,我们将使用一个输入张量,并将训练默认设置为false。然后我们将做x等于self。CNNnn1,我们将把输入张量传递通过第一个CNNn块。接着,我们将训练等于训练。我们将对x的CNN 2进行处理。
然后再次指定训练。然后我们将其通过最后一个,好的。对于这个,我们将做x,但我们也会添加这个身份映射。我们将做input.tensot,然后我们将指定训练等于训练。因此我们在这里所做的是使用这些跳跃连接。
但对于这个,它已经通过CNNnn2并将原始的通道数量更改为通过这个列表传入的通道数量。因此,这个整数通道的index1,所以这就是我们要做的,将其通过CNN块运行,然后匹配通道数量,以便我们实际可以进行这个加法。
我们首先将输入张量通过身份映射,然后将其添加到x。好的,所以在编辑这个时,我实际上发现这里有个错误。因此,对于身份映射,我们使用卷积核大小为3,这不应该是这样,然后我们实际上在做一个comp层,但我们只是想做一个身份映射。
改变输出的通道数量。所以在这里你需要做的就是将这个卷积核大小改为1,这样唯一的作用就是进行身份映射并改变通道的数量。然后在最后。
我们先进行X的池化,然后返回结果。因此返回self的X池化。好的。到目前为止,我们已经进行了,去掉那个。我们不会再使用它。因此到目前为止,我们已经完成了CNNM块。我们完成了这个res块。接下来让我们做最后的模型,对吗?所以我们要做的是class resnet。
我们称之为共振,现在对于父方法,我们将使用ks做模型。好的,这适用于层。我们将使用层,层的意思是我们不会把它作为最终模型,因此当我们从ks模型继承时,它具有层的功能,但也有一些额外的功能。例如,我们有内置的训练评估,以便可以在模型中使用我们熟悉的do fit
和model evaluate
。
所以这些在从ks做模型继承时是可用的,但如果你只做层,则不可用。此外,你还有其他属性,可以例如检查模型中的所有层、模型摘要,并且你也可以做序列化,然后保存你的模型,虽然我们将在另一个视频中讨论这个。
只需知道CAs模型具有层所没有的额外功能。你应该在最终模型上使用CAs模型,希望这能让你明白。那么我们要做的就是在这里定义它,并在这里指定类别的数量,比如说10。
然后我们首先,看看我们将调用Resnet的super。然后,self。然后,初始化。接着self.block1将是res块。我们看看。这是你可以尝试的内容,比如说32、32、64。然后block 2,设为res块128、128到56。然后,block 3,Res块128、256、512。
我们只是为这个res块中的每个CNN块指定通道,因此你可以看到我们在扩展这个块,可能会变得难以理解,但如果你一步一步来,首先我们创建CNN块,仅使用combat re,因为我们想为不同的通道数量重用它。然后我们构建这个res块,它多次使用这些块,并与这个身份映射一起使用一个池化层,最后我们在resnet样式的模型中使用这个块,最后我们将执行self.dot pool,将执行layers.global average pooling 2D,你可以阅读有关此内容的资料,但本质上这会进行平均。
拉动高度和宽度。然后我们将做一个,例如,你可以替换一个平坦层。所以不使用这个,你可以做layers.flatten,如果你对此更为舒适。因此,我们以相同的功能使用它,我们希望将其平坦化或缩小高度和宽度,然后通过最后的分类层发送它。
所以现在我们要做的是执行self.dot classifier layers dense
和类的数量。现在剩下的就是调用,所以我们要进行输入张量(input tensor)。我们将设置训练,默认为false
。然后,我们要执行输入张量的第一个块(block one)。我们将指定训练。
根据我的理解,这里指定训练将在模型拟合(model fit)或模型评估(model evaluate)时完成,我们将在未来的视频中展示如何进行自定义训练循环等等。但是我认为如果我们在这里指定训练,这将在模型拟合内部完成,这会根据例如这里的训练将参数设置为true
,在评估时则设置为false
。
然后,我们要进行输入x
的第二个块(block 2),再次指定训练。接着我们要进行输入x
的第三个块(block 3),同样,指定训练。最后,我们将执行self.dot pool of x
,然后将x
返回,实际上就是返回self.dot classifier of x
。此时进行模型摘要(model summary)会有所帮助。在模型拟合(fit)之后。
让我们打印模型摘要(model dot summary)。就在那里。我们让它运行一个周期(epoch)。首先,好的,是的,我们还需要指定我们的模型。所以我们要做model equals res.Ne
。然后我们可以设置类为10
,希望现在可以运行。好的,所以我们可以看到经过一个周期后,我们在训练集上的准确率为97%
。
然后在这里我们可以看到模型的层次结构。我们有一个残差块(res block),再是平均池化(average pooling),然后有点烦人的是我们有多个输出形状,这通常发生在你进行子类化时。
但我找到了一种变通方法。我不确定这是否是最佳方法,但现在你可以使用这个方法,所以我们可以执行模型self
。我们要做的是指定输入形状的x
。然后让我们做28, 28, 28, 1
。接着返回ks.dot model inputs equals x
,然后输出为self.dot call of x
。
这将覆盖模型的调用(call),然后我们可以像这样执行模型调用(model model call),接着做.summary
,通过这种方式我们实际上将获得输出形状。所以我就让这个运行,然后我们看看结果是什么样的。
好的,现在我们可以看到输出形状实际上是包含的,我们对批次数没有任何限制。经过第一次重构块后,输入图像的形状是28281,通道数为64,接下来是14乘14,所以它包括了一个最大池化,然后我们再次进行了最大池化,再进行了一个最大池化,然后通过平均池化处理。如你所见,在这种情况下我们有512个通道,宽度和高度为3乘3,我们基本上是将所有的3乘3512通道平均成一个单一的512,然后我们通过一个密集层进行处理,总参数量为300万,我想这比我们之前做的要大得多,但相对其他模型来说,这仍然算是比较小的。因此,希望你能看到,如果你构建了这个模型,那将是巨大的。
我们甚至无法从模型摘要中看到所有层,对吧?我们只看到这些块,但这些块,每个块都有多个CNN块,所有这些残差块都是多个。如果你绘制这个模型,会发现它非常庞大。如果你使用的是顺序API,我认为你甚至无法使用顺序API,但它会是。
构建这个模型会更加麻烦。因此,希望这能够说明为什么进行子类化是非常好的,你也有很多灵活性,可以几乎按照自己的想法构建模型,并且你可以在调用过程中打印一切,这非常直观。
我真的觉得子类化是构建模型的一个很好的方法,在下一个视频中,我们还将展示如何使用子类化来创建自定义层。例如,假设我们现在使用这个密集层,实际上你该如何自己构建一个密集层等等。所以这就是我们下个视频要做的,我想只是为了好玩。
我们可以再运行一段时间,看看我们实际上能从到目前为止构建的最大模型中获得什么样的准确度。所以让我们开始运行,这会花费一些时间,但对你来说会很快。所以我会让它运行,直到完成。
好的,经过大约20个周期,我们在训练集上得到了99.84%的准确率,在测试集上得到了99.14%的准确率。我认为如果你再训练一段时间,可以将其提升到99。当我之前训练时,我在测试集上实际上得到了99.4%的准确率,但然后我又训练了几个周期。我认为你还可以添加正则化,模型会改善。不过,我认为这个视频确实展示了子类化的强大功能,希望你在观看完这个视频后也觉得子类化很棒。非常感谢你观看这个视频,希望在下一个视频中见到你。
“当前最好的 TensorFlow 教程!”,看完就能自己动手做项目啦!<实战教程系列> - P9:L9- 自定义图层 - ShowMeAI - BV1em4y1U7ib
大家好,希望你们过得非常精彩。在这个视频中,我想向你展示如何创建自定义层。😊!
到目前为止,我们已经看到了如何使用子类化构建非常灵活的模型,现在我们想更进一步,自己创建层。因此,我会向你解释我所指的内容,但首先为了说明我们面前的代码,我们只是引入了在几乎每个视频中看到的内容,然后我们有这两行代码以避免任何GPU错误,最后我们只是在加载Ms数据,这样可以节省一些时间,所以我们将从创建自己的自定义模型开始,像我们在上一个视频中做的一样,这会非常简单,我们将创建类my model,继承自Kast模型,首先找到init方法,我们会使用self,然后可以指定Ms的类数为10,接着我们将调用super mymod self的init。
然后我们将进行self dense1,这里我们只需创建两个密集层。好的。我们将使用layers do dense,设定为64个节点,然后self dense2是layers dense的nu classes,我们将调用self,然后是x。
输入或称为输入张量。然后我们将执行self do den one的输入张量。接着在其上运行Tf.nn.relu。这就是我们在上一个视频中看到的内容,因此我快速讲解,然后我们想返回self do then2的x。好的。现在让我们快速构建一个模型,编译模型并进行拟合。
我们将执行model equals my model。我们将执行model do compile。损失等于ks,损失,bars。分类交叉熵。从逻辑上讲等于true。😔,然后让我们进行模型拟合。你之前见过这些,所以我会快速写出。好的,现在我们有一个使用子类化的自定义模型,然后我们定义了编译、拟合和评估,所以让我们确保这确实有效,如果我们运行这个,我们会看到它实际上在训练,这应该相对较快,因为我们只有是的,我们有一个非常非常小的网络,像64个节点,然后10个输出节点,让我们实际讨论一下我想在这个视频中展示的内容。
现在我们想自己创建这些层。目前我们使用的是Ks中的层,里面包含密集层,然后使用Tf.n.relu。这是可以的,你可以用它构建非常灵活的模型,在大多数情况下这都很好。但有时为了理解,你想自己构建这些层,这样可以更深入地理解内部机制。所以我将向你展示如何做到这一点。让我们做一个类,命名为dense,并继承自layers layer。
我们将创建我们的初始化函数,所以我们将做init,然后是self和unit。接着我们将指定输入维度。然后我们要做的就是运行super方法,所以super dense self that init。然后我们将self.W设置为self.add weight。
实际上有多种方法来做到这一点。这是更简单的方法,你也可以用T点变量自己初始化,但我将以这种简单的方法展示给你。首先,我们需要设置一个名称,我们就叫它W。实际上,这一点非常重要,你会在下一个视频中看到如何保存和加载模型。我发现如果不指定名称,就无法保存模型,所以这非常重要。接下来,我们要指定一个输入维度的形状,然后设置单位。输入维度就是我们一开始的值,784,即28乘以28,然后单位就是我们要映射到的值,所以在使用layers164时,单位是64。
初始化器我们将使用随机正态分布,你可以查看其他初始化方法。然后我们将指定trainable等于true。所以trainable等于true。这适用于像batch norm这样的层,其中某些参数实际上不是可训练的。但在这个密集层中,我们的所有参数都将是可训练的,然后我们将进行self。
B是self.add weight。我们将其命名为B,形状就是单位。因此,我们进行矩阵乘法时需要W,这就是它必须具有输入维度的原因。然后它将是单位节点,所以我们为每个节点添加一个。这就是我们在这里所用的单位。然后我们可以进行初始化,我们将其初始化为零。
这也是一个可训练参数。最后,我们只需实现call方法。对于一些输入,我们将返回T点矩阵乘以输入。然后self到W,最后我们需要添加B。现在,我们可以在这里替换,所以我们可以做self ta dense 1是dense,然后设置64和784。
然后我们来做一个自密集层,输入维度是10,然后是64。现在把这个输出放在那里,看看是否有效。好的,我们似乎得到了与上一个几乎相等的结果,最重要的是它确实可以运行。首先,你可以注意到,在这些例子中,我们不需要指定输入维度,我们称之为懒惰层,这样你根本不需要说明输入维度,它会自动计算出来。所以我们现在想做的是移除这一部分,使其无论输入维度如何都能工作。我们要做到这一点的方法是创建一个构建方法。现在我们有了初始化,我们将在这里移除输入维度。
然后我们将创建一个构建方法。我们将定义构建,传入self和输入形状。接着,我们将在这里创建Ws,因此我们将把这段代码粘贴到构建方法中。
现在非常棒的是,使用输入形状而不是输入维度,我们可以处理最后一个维度。在这种情况下,我们在第一维有训练样本,然后由于我们在这里的重塑,我们有784。
所以我们在这里做-1,然后我们将使用单位,虽然在初始化方法中我们将self.units设置为units。接着,我们需要将这里的单位替换为self.units,W和B都需要如此。
所以现在令人惊讶的是,如果我们运行这个,我们就不需要指定输入维度,这样希望可以工作。我们可以运行这些类。现在让我们试试,看看会得到什么。它似乎有效,我们看到这两个功能几乎是相同的。你可能会说,我们仍在使用TfN和dot Reello,实际上自己创建这个也不错,这就是我们的下一步。你可以通过两种方式做到这一点,可以创建一个函数或像我们现在这样创建一个类。我认为最常见的方法是定义一个函数,但让我们创建一个类,你可以尝试制作一个函数。
它几乎是一样的。但我们将做一个类Mireello,然后定义初始化,只需传入self。我们需要调用super的Mireello,self和初始化。然后在我们的实际调用中,我们只需返回Tf.math.maximum(x, 0)。
这只是返回 x 和 0 中的最大值,这正是相对的,对吧?所以在这一点上,你可能会说,嗯,我们到底如何创建这个 Tf math maximum 函数。你可能觉得这是一种作弊的方式,我想说这甚至更底层,这是你可以尝试的,你可以阅读文档和源代码,了解他们是如何实现这个函数的等等,但总会有机会让你深入探索细节。因此,我会在这里划定界限,我们可以在这些张量上使用这些数学运算,当我们有这个 myrelu 时,我们可以做 self。
tre 是我的 Relu,所以我们必须实例化这个类,虽然如果你使用一个函数,这就不是这种情况。那么我们要做的是替换这个 Tf,然后做 relu,然后在此基础上做 selftrelu。所以我们可以先运行这个。因此,你现在已经看到如何通过 Kaa 子类化自己构建这些模型,以及如何实际构建这些层,比如稠密层和 re 函数。这些都是相当简单的,但你可以想象构建更复杂的层。我也建议你尝试一下。好的,这就是本视频的全部内容,非常感谢你的观看,希望在下一个视频见到你。
140分钟入门 PyTorch,官方教程手把手教你训练第一个深度学习模型!<官方教程系列> - P1:L1- PyTorch 简介 - ShowMeAI - BV19L4y1t7tu
你好,我的名字是Brad Heinz。我是Facebook Pytorrch团队的合作工程师。在这个视频中,我将向你介绍Pytorrch,它的特性、关键概念和相关工具及库。这个概述假设你是第一次接触Pytorrch进行机器学习。
在这个视频中,我们将涵盖Pytorrch和相关项目的概述。张量,它们是Pytorch的核心数据抽象。自动微分,它尝试快速计算模式,使模型快速迭代成为可能。我们将讨论如何使用Pytorch模块构建模型。
我们将讨论如何高效加载数据以训练模型。我们将演示一个基本的训练循环。最后,我们将讨论使用Torchscript进行部署。
在我们开始之前,你需要安装Pytorrch和torchvisions,以便能够跟随演示和练习。如果你还没有安装最新版本的Pytorrch,请访问Pytorrch.org。首页有一个安装向导。这里有两个重要事项需要注意。首先,Mac上不提供CUDA驱动程序。因此。
在Mac上不会提供GPU加速。其次,如果你在配备一个或多个Nvidia CUDA兼容GPU的Linux或Windows机器上工作,请确保你安装的CUDA工具包版本与机器上的CUDA驱动程序匹配。
那么Pytorch是什么呢?
Pytorch.org告诉我们,Pytorch是一个开源机器学习框架,能够加速从研究原型到生产部署的路径。让我们详细了解一下。首先,Pytorch是机器学习的软件。它包含构建和部署机器学习应用程序的完整工具包,包括深度学习的基本元素,如神经网络层类型。
激活函数和基于梯度的优化器。它在Nvidia GPU上具有硬件加速,并且有与计算机视觉、文本、自然语言和音频应用相关的库。Torchssion,Pytorch计算机视觉应用的库。
还包括预训练模型和打包数据集,你可以用来训练自己的模型。Pytorch旨在快速迭代你的机器学习模型和应用程序。你可以在常规的Python中工作。构建计算图时无需学习新的特定领域语言,Pytorch的自动微分引擎,模型的反向传播通过单个函数调用正确完成。
无论计算在代码中走哪条路径,都提供了无与伦比的模型设计灵活性。Pytorch 拥有适用于企业规模的工具,如 Torchcr,它可以从 Pytorrch 代码创建可序列化和可优化的模型,还有 Torchserv。
Pytorrch 的模型服务解决方案以及多种量化模型以提高性能的选项。最后,Pytorrch 是一个免费开源软件,免费使用,欢迎社区的贡献。
它的开源特性也促进了丰富的社区项目生态系统,支持从随机过程到基于图的神经网络的用例。
Pytorrch 社区庞大且不断壮大,来自全球的贡献者超过 1200 名,研究论文引用年增长率超过 50%。
Petorrch 在顶级公司中得到了应用,并为像 Alan N LP 这样的项目提供了基础。它是一个开源深度学习研究库,专注于自然语言处理,Fast AI 简化了使用现代最佳实践进行快速和准确的神经网络训练。Classy Vision 是一个用于图像和视频分类的端到端框架。
一个开源可扩展库,帮助你理解和解释模型的行为。现在你已经了解了 Pytorrch,让我们深入探讨一下。张量将是你在 Pytorrch 中所做的一切的核心。你的模型、输入、输出和学习权重都以张量的形式存在。
现在,如果张量不是你常用的数学词汇,只需知道在这个上下文中,我们谈论的是多维数组,但带有许多额外的特性。Pietorrch 张量附带超过 300 种可对其执行的数学和逻辑操作。尽管你是通过 Python API 访问张量,但计算实际上是在为 CPU 和 GPU 优化的编译 C++ 代码中进行的。
让我们看看 Pytorrch 中一些典型的张量操作。
我们需要做的第一件事是通过 import torch
调用来导入 Pytorrch。然后我们将继续在这里创建我们的第一个张量。我将创建一个具有五行三列的二维张量,并用零填充它。我将查询这些零的数据类型。
在这里,你可以看到我得到了请求的 15 个零的矩阵,数据类型为 32 位浮点数。默认情况下,Pytorrch 创建的所有张量都是 32 位浮点数。如果你想要整数,你可以随时覆盖默认设置。在下一个单元中,我创建了一个充满 1 的张量。我请求它们为 16 位整数,并注意到在我没有被问及时打印出来。
Pytorrch告诉我这些是16 B整数,因为它不是默认的,可能与我预期的不符。通常会随机初始化学习权重,常常使用特定的随机数生成器种子,以便在后续运行中重现结果。我们将演示如何用特定数字对Pytorch随机镜像生成器进行加种。
生成一个随机张量。生成第二个随机张量,预期它与第一个不同,通过使用相同输入重新设置随机数生成器。最后,创建另一个随机张量,预期它与第一个匹配,因为它是在对随机生成器加种后创建的第一个张量。果然,这些结果是我们得到的。第一个张量和第三个张量确实匹配。
而第二个则不行。Pytorch张量的算术操作是直观的。相似形状的张量可以相加、相乘等等,而标量与张量之间的操作将分布到张量的所有单元上。所以让我们看几个例子。首先,我将创建一个满是1的张量。
然后我要创建一个满是1的张量,但我将其乘以标量2。结果是所有的1都会变成2。这个乘法在张量的每个元素上分布。然后我会将这两个张量相加。我能这样做是因为它们形状相同。操作在它们之间按元素进行。
我们现在得到了一个满是3的张量。当我查询该张量的形状时,它与加法操作中的两个输入张量形状相同。最后,我创建两个不同形状的随机张量并尝试将它们相加。因为没有干净的方式在两个不同形状的张量之间进行按元素的算术操作,所以我得到了一个运行时错误。
这是Pytorch张量上可用的数学操作的小样本。我将创建一个随机张量并调整它,使其值在-1和1之间。我可以取它的绝对值,看到所有值变成正数。我可以取它的反函数,因为值在-1和1之间,得到一个角度。
我可以执行线性代数操作,比如求行列式或进行奇异值分解。此外,还有统计和汇总操作,比如均值、标准差、最小值和最大值等等。关于Pytorch张量的强大功能还有很多要了解的。
包括如何为GPU的并行计算设置它们。我们将在另一个视频中深入讨论。
作为对自动求导的介绍,Pytorcht的自动微分引擎。我们来考虑一次单一训练传递的基本机制。在这个例子中,我们将使用一个简单的递归神经网络(RNN)。我们开始时有四个张量,X,输入H,RNN的隐藏状态,这赋予了它记忆,以及两组学习权重。
每个输入和隐藏状态都有一个。接下来,我们将权重乘以各自的张量。在M中,代表自然乘法。之后,我们将两个矩阵乘法的输出相加。并将结果通过激活函数,这里是双曲正切。最后。
我们计算这个输出的损失。损失是正确输出与我们模型的实际预测之间的差异。因此,我们已经取了一个训练输入,通过模型运行,得到了输出并确定了损失。这是训练循环中的一个环节,我们必须计算该损失对模型每个参数的导数,并利用梯度调整学习权重,以减少损失的方式来调整这些权重。
即使是这样一个小模型,也有一堆参数和大量的导数需要计算。但好消息是,你可以用一行代码完成。每个由此计算生成的张量都知道它是如何产生的。例如,I到H携带元数据,表明它来自W X和X的矩阵乘法。
而且它会继续向下延续到图的其余部分。这种历史跟踪使得反向方法能够快速计算模型在学习中所需的梯度。这种历史跟踪是使模型灵活和快速迭代的因素之一。
即使在具有决策分支和循环的复杂模型中,计算历史也会跟踪特定输入在模型中所走的路径,并正确计算反向导数。在后续视频中,我们将向你展示如何使用autograd进行更多技巧,比如使用autograd分析器、计算二阶导数,以及如何在不需要时关闭autograd。
到目前为止,我们谈到了张量、自动微分以及它们如何与Pytorcht模型相互作用。但这个模型在代码中是什么样子的呢?让我们构建并运行一个简单的模型以获取感觉。首先,我们将导入PyTorch。我们还将导入torch.nn,它包含我们将组合成模型的神经网络层。
还有模型本身的父类。我们将导入torch.nn.functional,以便提供激活函数和最大池化函数,这些函数将用于连接层。因此,这里我们有一个Linenette 5的示意图。它是最早的卷积神经网络之一,也是深度学习爆炸的推动者之一。
它是为了读取手写数字的小图像而构建的。该数据集旨在正确分类图像中所表示的数字。下面是其工作原理的简要版本。层C1是卷积层,这意味着它扫描输入图像以识别在训练期间学习到的特征。
它输出了在该图像中看到的每个学习到的特征的位置图。这个激活图在层S2中进行了下采样。层C3是另一个卷积层,这次扫描C1的激活图以寻找特征组合。它还输出一个激活图,描述这些特征组合的空间位置。
该输出在层S4中进行了下采样。最后,位于5F6的全连接层和输出是一个分类器,它接受最终的激活图并将其分类为表示10个数字的10个箱子之一。那么我们如何在代码中表达这个简单的神经网络呢?看看这段代码。
你应该能看到与上面的图表有一些结构上的相似之处。这展示了一个典型的PyTorch模型的结构。它继承自Torch和N.dot模块,模块可以嵌套。实际上,这里的2D卷积层和线性层也是Torta和N.dot模块的子类。
每个模型都会有一个初始化方法,在其中构建将组成其计算图的层,并加载可能需要的任何数据工件。例如,一个NLP模型可能会加载一个词汇表。模型将具有一个前向函数。这是实际计算发生的地方,输入通过网络层在各种函数中传递以生成输出。
一个预测。除此之外,你可以像构建其他Python类一样构建你的模型类,添加任何你需要支持模型计算的属性和方法。所以让我们实例化这个,并通过它运行一个输入。这里发生了几个重要的事情。我们正在创建一个限制的实例。
我们正在打印对象,现在是Tortra的一个子类并在一个模块中。将报告它创建的层及其形状和参数。这可以为你提供一个模型的方便概述,以便你了解其处理的要点。下面,我们创建了一个表示32×32图像和一个颜色通道的虚拟输入。通常。
你需要加载一个图像切片并将其转换为这种形状的张量。你可能注意到我们的张量有一个额外的维度。这是批量维度。PyTorch模型假设它们在处理数据批量。例如,一批16个图像切片将具有形状16×1×32×32。
由于我们只使用一张图像,我们创建了一个形状为1×1×32×32的批量。我们通过调用它作为一个函数来请求模型进行推断,net input。这个调用的输出表示模型对输入表示特定数字的信心。因为该模型实例尚未经过训练。
我们不应该期望在输出中看到任何信号。查看输出的形状,我们可以看到它还有一个批次维度,大小应该始终与输入批次维度相匹配。如果我们传入一个16个实例的输入批次,输出的形状将是16×10。你已经了解了如何构建模型,以及如何提供一批输入并检查输出。
不过,模型并没有做太多,因为它尚未经过训练。我们需要提供大量数据,以便训练我们的模型。我们需要一种方法来批量提供数据。这就是Pytorch数据集和数据加载类发挥作用的地方。让我们看看它们的实际应用。
所以这里我在线声明Matplotlib,因为我们将在笔记本中渲染一些图像。我正在导入Pytorch,同时也导入torchvision和torchvision变换。这些将为我们提供所需的数据集和一些需要应用于图像的变换,以便让它们适合我们的Pytorch模型。因此,我们需要做的第一件事是将传入的图像转换为Pytorch张量。
在这里,我们为输入指定了两个变换。Transs to Tensor将由Pillow库加载的图像转换为Pytorch张量。transformers.dot normalize会调整张量的值,使其平均值为0,标准差为0.5。大多数激活函数在0点附近的辐射最强。
因此,中心化我们的数据可以加速学习。还有许多其他可用的变换,包括裁剪、中心化、旋转、反射,以及你可能对图像进行的其他大多数操作。接下来,我们将创建一个Car 10数据集的实例。
这是一组32×32的彩色图像瓷砖,代表10类物体,包括6种动物和4种车辆。当你准备好以上所有内容时,可能需要一两分钟的时间来下载这个数据集,所以请注意这一点。这是使用Pytorch创建数据集的一个示例。
可下载的数据集,如上面的Siffer 10,是Torch和Us数据集的子类。Pytorch中的数据集类包括可在torchvision中下载的数据集,以及Torch文本和torch音频,还有一些实用的数据集类,例如Torchvision datasets中的图像文件夹,它将读取一个标记图像的文件夹。你也可以创建自己的数据集子类。
当我们实例化我们的数据集时,需要告诉它一些信息,包括我们希望数据存放的文件系统路径,是否将此数据集用于训练,因为大多数数据集会在训练和测试子集之间进行拆分。是否希望下载数据集(如果我们还没有下载的话)以及我们希望对图像应用的变换。
一旦你准备好数据集,就可以将其交给数据加载器。现在,数据集子类封装了对数据的访问,并专门针对其所服务的数据类型。数据加载器对数据一无所知,但根据你在上面的示例中指定的参数,将数据集提供的输入张量组织成批次。我们请求数据加载器从训练集中给我们提供四张图像的批次,随机化它们的顺序。
当设置为shuffle为真时,我们告诉它启动两个工作线程从磁盘加载数据。可视化数据加载器提供的批次是一种良好的实践。运行这些单元应该会显示出四张图像的条带,并且你应该能看到每张图像的正确标签。那么,这里是我们的四张图像,实际上看起来像是一只猫和一只在两辆卡车里的鹿。
我们已经深入了解了张量和自动求导,并看到了PyTorch模型是如何构建的,以及如何高效地为它们提供数据。是时候把所有的部分结合起来,看看一个模型是如何训练的。所以,我们回到了笔记本,你会看到这里的导入。
除了Torchdot Opum,所有这些在视频早些时候应该看起来都很熟悉。我们首先需要的是训练和测试数据集。如果你还没有运行下面的单元,请确保数据集已下载。如果你还没这样做,可能需要花一分钟的时间。
我们将检查数据加载器的输出。再次,我们应该看到四张图像的条带,这看起来是正确的。抱歉,数据加载器很好。这是我们将训练的模型。现在,这个模型看起来很熟悉,因为它是Lyette的一个变体。
我们在本视频早些时候讨论过这一点,但它被调整为处理三种颜色的图像。我们需要的最终组成部分是损失函数和优化器。损失函数,如本视频早些时候讨论的,是衡量模型预测与理想输出之间差距的指标。交叉熵损失是像我们这样的分类模型的典型损失函数。
优化器是推动学习的关键。在这里,我们创建了一个实现随机梯度下降的优化器,这是最简单的优化算法之一。除了算法的参数,如学习率和动量外,我们还传入了net的参数,这是模型中所有学习权重的集合,优化器会调整这些权重。
最后,所有这些都汇集到训练循环中。继续运行这个单元,因为它会花几分钟来执行。从第一行你可以看到,我们只进行了两次训练历程,即对训练数据集的两次完整遍历。每次遍历都有一个内循环,用于迭代训练数据。
处理批次的变换图像及其正确标签。在第9行中处理梯度是一个非常重要的步骤。当你运行一个批次时,梯度会在该批次中累积。如果我们不为每个批次重置梯度,它们将继续累积并提供不正确的值,从而导致学习停止。在第12行中。
我们向模型请求其对该批次的实际预测。在接下来的行中,行13,我们计算损失。输出与标签之间的差异。在行14中,我们进行反向传播,计算将引导学习的梯度。在行15中,优化器执行一次学习步骤。它利用反向调用中的梯度来推动学习权重朝着减少损失的方向调整。
所以循环的其余部分只是对史诗编号和已完成的训练实例数量进行一些简单报告。总体损失在训练史诗上是多少。因此请注意,损失是单调下降的,这表明我们的模型在训练数据集上的表现不断提高。
作为最后一步,我们应该检查模型是否真的在进行一般学习,而不是简单地记忆数据集。这称为过拟合,通常表明你的数据集太小,示例不足,或模型过大,超出了规范。
对数据进行建模。你正在处理它。所以我们的训练完成了。嗯。无论如何,我们检测过拟合并防止它的方法是测试模型在未训练过的数据上。这就是我们拥有测试数据集的原因。所以我将运行测试数据,我们将得到一个准确度度量。55% 好吧,这并不算先进。
但这比我们期望的随机输出的10%要好得多。
这表明模型确实发生了一些一般学习。现在,当你花费时间构建和训练一个非平凡模型时,通常是因为你希望将其用于某个目的。你需要将其连接到一个系统,以便输入数据并处理模型的预测。如果你热衷于优化性能,可能希望在不依赖Python解释器的情况下做到这一点。
好消息是PyTorch为你提供了torch script。😊,Torchscript是Python的一个静态高性能子集。当你将模型转换为torchscript时,模型的动态和Pythonic特性会被完全保留。控制流在转换为torchscript时得到保留。
而且你仍然可以使用方便的Python数据结构,如列表和字典。查看右侧的代码,你会看到用Python定义的py torch模型。在此之下,创建模型的实例,然后我们将调用torch dot dot script my module。只需一行代码,就可以将你的Python模型转换为torchscript。
该序列化版本保存在最后一行,其中包含有关您模型计算图及其学习权重的所有信息。模型的torch grip渲染显示在右侧。Torch脚本旨在被PyTorch即时编译器或Jit使用。
Jit寻求运行时优化,如操作重排序和层融合,以最大化您模型在CPU或GPU硬件上的性能。
那么,您如何加载和执行torch脚本模型呢?您可以通过torch shott Jet dot load加载序列化包,然后像其他模型一样调用它。更重要的是,您可以在Python中这样做,也可以将其加载到Pytorrch C++运行时中,以消除对解释语言的依赖。
在后续视频中,我们将更详细地讨论Torch脚本、部署的最佳实践,并涵盖Torch Ser P Torch的模型服务解决方案。
所以这就是我们对Pyetorrch的快速概述。我们在这里使用的模型和数据集相对简单。但Pytorrch在大型企业中用于强大的实际应用场景,例如在人类语言之间进行翻译、描述视频场景的内容或在视频中生成逼真的人声。接下来将深入探讨这里讨论的所有主题,涵盖更复杂的用例,就像您在现实世界中看到的那样。
😊,感谢您的时间和关注。希望在Pytorrch Fors见到您。
140分钟入门 PyTorch,官方教程手把手教你训练第一个深度学习模型!<官方教程系列> - P2:L2- PyTorch 张量简介 - ShowMeAI - BV19L4y1t7tu
欢迎。在这个视频中,我们将深入探讨 PyTorch 张量。在 PyTorch 深度学习模型中,所有的数据输入、输出和学习权重仅以张量的形式表达,这是一种可以包含浮点数、整数或布尔数据的多维数组。特别是在这个视频中。
我们将讨论创建 PyTorch 张量的一些方法。如何在数学和逻辑操作中单独或相互使用张量。复制张量的方法。如何移动到 GPU 进行硬件加速?
操作张量形状和 PyTorch 的 Nuy bridge。如果你还没有这样做,我建议去 PyTorch 示例库下载与这个视频配套的交互式笔记本。
好吧,在这里的第一个单元中,我们将导入 PyTorch。我们还将导入 Python 的 math 模块以使用一些常量。我们将要讨论的第一件事是创建张量。所以这里有创建张量的最简单方法,torch.empty 调用。
Torch 模块有多个工厂方法,可以让你以有或没有初始值以及你需要的任何数据类型创建张量。这是分配张量的最基本方式,torch.empty 这里将创建一个三行四列的张量。
我们可以看到,对象本身是类型 torch.tensor。当你运行这个单元时,你可能会看到输出中出现随机的值,这是因为 torch.empty 仅分配内存,而不写入任何值。因此,在你分配这个张量时,内存中存在的内容就是你在这里看到的。关于张量及其维度和术语的一点简要说明。
有时当我们有一维张量时,我们会称之为向量,因为它只是一个有序的维度元组。二维张量通常被称为矩阵,而任何更大的张量我们都称为张量。现在,更常见的是,你会希望用一些值来初始化你的张量。
常见情况是全零、全一或随机值。Torch 模块为所有这些情况提供了工厂方法。所以在这里如果我们运行这个单元,你会得到你在方法名称中可能期望的结果,一个充满零的二行三列张量,一个充满一的二行三列张量。
然后是充满 0 到 1 之间随机值的张量。现在说到随机张量。你可能已经注意到在实例化那个张量之前调用了 torch.manual_seed。这是怎么回事呢?现在,用随机值初始化张量,例如你的模型学习权重是很常见的,但通常你会希望你的结果是可重复的。
尤其是如果你在研究环境中工作。因此Ptorrch为你提供了一个工具来做到这一点。手动种子调用。每当你使用特定的整数种子调用手动种子时,你将重新初始化你的伪随机数生成器,并在再次调用时获得相同的结果。
所以在下面的单元格中作为一个例子。我们调用手动种子,我们调用Torchdot Rand。我们输出一些值,然后再次调用Torchdot Rand并输出一些值。接着当我们再次调用手动种子并进行这两个torchdot随机调用时。我们会发现两次的结果都是相同的。因此,这就是确保依赖随机数的相同计算能提供相同结果的方式,如果你需要这种可重复性。
因此,通常当你对两个或多个张量执行操作时。它们需要具有相同的形状。即在每个维度上具有相同数量的维度和相同数量的单元格,或者在每个维度上的相同范围。我迄今为止在torch模块上展示的所有工厂方法都有相应的方法。后面加上下划线。当你将张量作为参数传递给empty或zeros时。
使用这些其他方法,你将得到一个根据你的指定初始化的张量。但它的形状与作为参数传入的张量相同。因此在这里我们运行了单元格,我们可以看到我们的初始张量是2 by 2 by 3,尽管我们没有为O张量指定形状。它们也都会以你所期望的方式输出为2 by 2 by 3。
当我们想要找出张量的形状时,我们总是可以查询其形状属性。这将给我们返回一个维度及其范围的列表。现在我们将要讨论的创建张量的最后一种方法是直接从Ptorrch集合中指定其数据。因此在这里,如果你看看这些例子,我们有一个嵌套数组和一个元组,以及一个包含元组的元组在列表中。
当我们调用Torchdot张量并将这些集合作为参数时。我们会得到一个用我们指定的数据初始化的新张量。因此在这里你可以看到在所有三个案例中,我们得到了一个形状和包含预期数据的张量。因此torchdot张量创建了数据的副本。知道Python列表的底层内存表示与张量的底层内存表示是不同的是很重要的。
因此,在以这种方式创建新的张量并用数据初始化时,我们总是复制那些数据。现在我之前提到过,张量可以有浮点或整数布尔底层数据类型。指定数据类型的最简单方法是在创建时进行。因此在这个单元格中,我正在创建一个int16和一个float 64,你会看到当我打印出来时A是由16位整数表示的一组1。
你会看到没有任何一个后面有小数点,这表明我们处理的是整数而非浮点数。我们还可以看到,因为我们覆盖了默认数据类型,默认是 32 位浮点数。当我们打印张量时。
PyTorch 有用的报告告诉我们这是该张量的基础数据类型。类似地,当我们使用 64 位浮点数时。改变张量的数据类型或将其真正移动到所需数据类型的新张量的另一种方法是使用这两种方法。因此,这里我调用 B.do2,并表示我希望将此数据作为 32 位整数。仔细查看打印出来的 B 和 C 的值。
C 的值只是 B 的值被截断为整数。因此,这是一个浮点到整数的转换。你可能注意到的另一件事是,这里指定了张量的维度为一个元组。典型情况下,PyTorch 对张量的维度期望一个元组,但当维度是方法的第一个参数时。
这让我们有点侥幸,只需输入一系列整数。但为了让代码更易读,我将张量的形状分离为一个元组。你可以使用的数据类型有布尔值、五种事件类型和四种浮点数类型。首先让我们看看基本的算术运算,以及如何让张量与标量交互,现在如果我们运行这个单元。
看,看这里的第一行,我们将创建一个满是零的张量,并将整数 1 加到其中。这意味着将一个整数加到张量上有什么含义。好吧,在这里。我们将在张量的每个元素上执行此操作,因此该张量中的每个零都应该加上一个 1。如果我们查看输出。
这实际上是我们所看到的。类似地,对于乘法、除法、减法和指数运算。对于整数或浮点幂,我还要指出,因为张量和标量之间的二元运算会输出与最初相同形状的张量。
你可以直观地将这些算术运算链接在一起。你可以在我们创建三的那一行看到这一点。现在,用两个张量执行相同的算术运算行为是你所期望的那样。因此,我们取出我们的二。我们的小 2x2 张量充满了两个浮点数 2。
我们将使用指数运算符。现在我们将指定幂 1、2、3 和 4。因此,数学运算将在每个张量的对应元素之间逐元素执行,因为它们具有相同的形状。因此,如果我们运行这个单元,你可以看到实际上,二的幂在第一个张量中。
我们添加了两个全是1和4的张量,得到了5;如果我们将3和4相乘,就得到了12。这里一个关键点是,我们在这些张量二元操作的示例中展示的所有张量都是相同形状的。因此,当我们运行这个单元时,发现当我们尝试对两个不同形状的张量进行操作时,会出现运行时错误,尽管这两个张量的单元数量完全相同。
之间没有自然的映射方式。因此在一般情况下,你的张量必须具有相同的形状,但有一个重要且有用的例外,那就是我们所称的广播。这里有一个例子,我创建了一个随机张量,两个行四列,并且在这里你可以看到我与一个一行四列的张量相乘,实际上我们得到了我们预期的结果,所以在第一个打印语句中看到我们的随机输出,而在第二个打印语句中显示了所有结果翻倍。
那我们该怎么做呢?我们如何将两个不同形状的张量相乘并得到直观的结果?
广播是一种在具有特定相似形状的张量之间执行操作的方法。在这里的单元中,那个一行四列的张量与随机张量的每个两行四列逐元素相乘。
这是深度学习中的一个重要操作。一个常见的例子是使用输入批次。因此,你的PyTorch机器学习模型在一般情况下不会期望单一输入进行训练或推理,而是会期望一个输入批次。因此,在这里对批次中的每个实例分别应用操作,但返回一个相同形状的张量是你所期望的。在我们的随机张量中,有两行随机值,我们与一行2相乘,逐行操作,这类似于我们对张量每个部分分别执行操作的批处理操作。
广播有一些规则。第一个是不能有空张量,因此每个张量必须至少有一个维度,然后在你想对其执行操作的两个张量的维度和范围之间有一些规则。
因此,当我们从最后一个维度到第一个维度比较两个张量的维度大小时,必须要么每个维度相等,要么其中一个维度的大小为1,或者在一个张量中该维度不存在。以下是一些展示我刚刚描述的规则的例子。
看这些可能比推理更容易,因此我们从一个充满1的张量开始。它是一个三维张量,有四层,三行和两列。我们将其与一个随机的3行2列张量相乘。如果我们查看输出,我们可以看到我们将随机张量与原始的充满1的张量的四层逐一相乘。
所以我们说,操作在这些层上广播到第一个维度。同样,在接下来的这一行中,我们将A乘以另一个随机张量以得到C。这次我们在做一个3x1的张量,所以这会给我们带来什么?这遵循规则,因为在最后一个维度中,一个维度是1,第二个维度匹配,而在其中一个张量中,第一个维度是缺失的。
输出看起来像这样。如果我们把进入C的随机张量看作是一个三元素列向量,你可以在输出中看到,当我们将其乘以一组一时,每个三元素列在我们的输出张量中都是相同的,因此我们对张量中的每个三元素列进行了广播这个操作。同样,在最后一个例子中,将一个随机的二张量与一个充满一的张量相乘。
这与上次的情况类似,但现在每个三元素列上执行的操作变成了每个二元素行上执行的操作。现在在这个广播主题上有一个Pytorch文档的说明。
如果你对更多细节感兴趣,我强烈建议你阅读它。现在,我想给你一些会打破规则并且无法工作的操作的例子。所有这些行应该会给你一个运行时错误,因此在第一种情况下,尝试创建B。我们总是从最后到第一比较维度,B的最后维度是三或者有一个三的范围。
A的范围是2,这些不匹配,我们无法在这里广播乘法。就像我所看到的,最后两个维度是2和3而不是3和2,它们是不同的,这样就不行了。在最后一个例子中,我们尝试创建一个空张量并在其上广播一个操作,维度为。
这不行,我们不能用空张量来进行操作。现在,Pytorch张量有超过300种数学操作可以执行,这里是一些主要类别的例子。在第一部分,我们有一些你可能会用来操作数字的函数,如绝对值、向上取整、向下取整和一个设置张量最小值和最大值的钳制函数。
所有这些操作都会作用于张量的每一个元素,三角函数也是如此。因此,我在这里创建了一个充满角度的张量,我想得到这些角度的正弦,然后得到那个正弦的反函数。你可以从运行单元格中看到,我们得到了预期的结果。我们可以对布尔或整数张量进行按位逻辑操作,这里我有两个整数张量,并对它们执行按位异或操作。
我们可以看到,这正是你所期望的,如果你在做类似的按位与或C。例如,我们也可以进行张量的比较。因此,我们将得到一个张量,你可以指定一些数据,我们将是一个充满一的张量。我们会测试它们的相等性。我们可以看到,因为张量D的第一个值是1。
但是其余的都不同,我们可以看到那里有一个真值和三个假值,这正是我们所期待的。你还可以对单个张量执行多种归约操作。例如,在这里我们可以获取一个张量的最大值,无论这个张量有多大。这将返回一个单一值。我们的张量中有一个单一值。
如果你想从那个单元素输出张量中提取那个值,我们使用点项调用。如果你查看这些归约节点的输出,首先我们得到一个包含我们值的张量,然后在调用项之后,我们实际上提取了这个值。你还可以计算均值和标准差。
有便利的方法来执行算术运算,包括张量的所有元素。因此,在这里通过点积调用,我们正在计算张量中所有数字的乘积。我们还可以作为另一个例子,获取张量中的所有唯一元素。这些行为或多或少都是你所期待的。当然。
线性代数是深度学习中很多工作的核心。因此有很多向量、矩阵和线性代数操作。例如,我将创建两个对应于 X 和 Y 单位向量的向量,并将创建两个矩阵。其中一个是随机的,另一个将是三倍的单位矩阵。
我们可以用它们做一些事情。Torch 在两个向量之间计算叉积。所以如果我们按照顺序将 Y 单位向量与 X 单位向量进行叉乘,我们应该得到负的 Z 单位向量,这实际上就是我们得到的。我们可以对我们的两个矩阵进行矩阵乘法。所以我们有了随机矩阵。
然后当我们将其乘以三倍的单位矩阵时,我们应该期待得到一个大约是我们输入值三倍的矩阵,实际上我们确实看到了这一点。你还可以进行更复杂的高级操作,比如奇异值分解。因此,这只是与 Pytorch 张量相关的 300 多个数学和逻辑操作中的一小部分。
我建议你查看文档以了解完整的清单。现在,有时候如果你正在进行两个张量的计算,你会说它们是某种中间值。当你完成时,你可能不需要那些中间值。能够回收内存是一个不错的优化。如果你需要一个与将要丢弃的中间张量大小和数据类型相同的张量。作为这个例子的再次说明,我将创建一个充满角度的张量。我将从中获取正弦值。你可以看到当我们运行这个单元并检查输出时,我们得到了一个。
这些是我们的角度,我们有这些角度的正弦。如果我们回头看一下,我们可以看到a没有改变。因此,我们看到Torch的sign给我们返回了一个新张量,并保留了旧张量在原地。但是因为我们在这里作用于一个单一张量,如果我们不需要输入值,我们可以直接将输出放在那个张量本身中。
像sign这样的带下划线的方法意味着你正在就地修改张量。你放入的那个张量,它是一个参数。所以现在如果我们做完全相同的事情,B是一个包含与A相同角度的张量。我们进行同样的操作,对它进行正弦计算。我们可以看到那是我们最初的角度,还有该正弦操作的输出。
但这次B已经改变,我们告诉它我们想使用B的内存,并且它的数据类型和大小是兼容的。因此B在原地被修改。如果你想对二元算术运算执行此操作,有一些函数的行为与二元pitorch操作符类似。因此,我们将创建两个2x2矩阵,A和B。我们可以查看它们的值,然后。
我们称之为就地加法方法。你可以看到这里a已经改变。覆盖二元操作的方法。调用的张量将是被就地改变的那个。因此,同样地,当我们对B进行相同操作时,如果我们对B的随机内容进行平方,但使用mo下划线,我们将得到我们预期的结果。
请注意,这些就地算术函数是torch张量对象的方法,而不是像许多其他函数一样附加到torch模块。调用的张量,正如我所说,是那个在原地被改变的张量。还有另一种选择,可以将计算结果放入一个已经分配的现有张量中。到目前为止,我们看到的许多方法和函数,包括张量的创建方法。
都有一个out参数,可以让你指定一个张量来接收输出。如果out张量与输出具有相同的形状,并且数据类型匹配输出的数据类型,则可以在不分配新内存的情况下发生这种情况。因此,如果我们运行这个单元格。我们将创建张量A和B,它们是两个2x2的随机矩阵,然后是C。
这是一个充满零的2x2矩阵,我们将使用Python ID调用来获取该对象的ID。我们将打印出来,我们将对A和B进行矩阵乘法,并将C指定为那个可选的输出参数。然后,如果我们查看C的下一个打印结果,会发现它已不再是零。所以C与A和B的大小相同,数据类型都是32位浮点数的默认类型。
因此,当我们进行乘法时,指定C来接收输出,我们看到它确实如此。我们还将输出赋值为另一个标签D的返回值。如果我们查看,将会发现C和D实际上是同一个对象,这个断言没有触发。所以C和D是同一个对象,我们还可以通过一个断言看到C的ID没有改变。
我们处理的是内存中的同一个对象。因此,我只是想给你一个具体的例子,说明这一切是如何运作的,它也适用于创建调用。所以当我们调用Torchdot Rand时,带有一个可选的输出参数,只要形状和数据类型符合要求,我们就会得到一个同一对象中的张量。所以我们已经看到如何创建和操作张量。那么,关于复制它们呢?
张量就像Python中的任何对象,这意味着如果你将其赋值给一个变量,那么该变量只是对象的标签,而不是创建对象的副本。创建一个满是一的张量,我们将其赋值给A,假设B等于A。如果你注意到,当我们改变A的值并打印B时,B中的值也发生了变化。
所以这只是同一个对象的两个标签。如果你需要数据的单独副本会怎样?这可能发生在你构建一个具有多个计算路径的复杂模型时,因此你想要对输入进行单独的副本,以传递给模型的不同部分。在这种情况下,你会使用克隆方法,所以我们将在这里做类似的事情。
我们将创建一个满是一的二维矩阵。我们将说B现在在同一个Josea中。但现在我们要克隆A,而不是仅仅进行赋值。我们可以通过断言验证它们实际上在内存中是不同的对象。我们还可以通过Torrsch EQ调用验证它们的内容是相同的。当我们再次改变A时。
我们可以验证,当我们打印B时,它没有改变。因此,有一件重要的事情需要注意,使用克隆时,如果你的源张量启用了autograd,那么该张量的克隆也会启用。我们将在关于autograd的视频中更深入地讨论这个问题。
但是如果你想要详细信息的简化版本,这里就是。嗯。因此作为一个例子,假设你有一个复杂模型,在其前向方法中有多个计算路径,原始张量及其克隆或副本将贡献于模型的输出。为了使模型学习,你希望这两个张量都启用autograd。
如果你的源张量启用了autograd,通常情况下是的。如果它是一组学习权重,或者它源于涉及权重的计算。那么其他地方的变化,它会提前知道,你将得到你想要的结果。另一方面,也许你正在进行一个计算,既不需要跟踪原始张量也不需要跟踪其克隆。
在这种情况下,只要源张量关闭了autograd,你就可以继续。还有当然,还有第三种情况,假设你在模型的前向函数中执行一些计算,其中所有内容默认情况下都开启了梯度跟踪。
但是你想在中间提取一些值来生成指标。你希望这些与正在处理的数据分开。因此在这种情况下,你不希望源张量的克隆副本跟踪梯度。这会降低性能,并且在这个示例用例中实际上没有任何作用。所以为此。
你可以对源张量使用detach方法。因此,如果我们运行。我们将看到这是我们创建的两个随机值的二乘二张量。我们将设置requires grad等于true。因此,现在每个后续计算都会跟踪其历史。我们知道它的来源,并可以计算反向导数。这是通过clone实现的。
所以在这里我们从A克隆B,当我们打印B时,看到grad函数等于clone backwards。这告诉我们B正在跟踪其历史。现在,如果你查看创建C的那一行,我们说a.dot detached.dot clone。然后当我们打印C时,我们得到相同的数据,只是没有附加历史。如果我们打印A。
我们会看到那个detach调用实际上没有改变A。它基本上只是说,做所有事情就像autograd被关闭一样。Pytorch的一个核心优势是硬件加速。如果你有兼容的Nvidia GPU和已安装的驱动程序。
你可以显著加速训练和推理的性能。到目前为止,我们所做的一切都是在CPU上。默认情况下,当你创建一个张量时,它是在CPU和内存中实例化的。那么我们如何移动到更快的硬件呢?首先,我们应该检查是否有更快的硬件可用,我们通过Torch.kuudo来做到这一点。
可用。所以如果我运行这个单元,你会看到它会告诉我们这个设备上是否有GPU可用。一旦你确定一个或多个GPU可用,你需要将数据放在GPU可以看到的地方。你的CPU处理的是存储在机器RAM中的数据。
你的GPU还附带专用内存。无论你希望在哪个设备上执行计算,都必须将该操作所需的所有数据移动到目标设备可以访问的内存中。现在我们知道我们有一个或多个GPU可用,我们运行。
现在有多种方法可以将数据传输到目标设备,但最简单的方法是在创建时。你可以在这里看到,当我们有可用的KUa GPU时,我们将创建一个带有可选参数的张量,该参数指示设备等于kuda。当我们创建一个想要移动到GPU的张量时。
我们将在工厂方法中使用可选的设备参数,所有我为你展示的创建张量的工厂方法都会接受这个设备参数,这里我们放入字符串kuta,表示我们希望将这个张量移动到GPU可访问的内存中,当你打印张量时。
你会看到它报告张量位于GPU设备上。你也可以查询GPU的数量,如果有多个,你可以通过在Kuda字符串后添加冒号来按索引指定它们,例如Kuda:0,Kuda:1。eta将是你作为设备参数输入的字符串。作为一般工程实践。
通常不建议在代码中到处使用魔法常量字符串,因此更好的做法是在计算开始时选择你希望在哪个设备上进行计算,并获取该设备的句柄,然后在下一个单元中传递该句柄。
我们有一个例子,其中我的设备取决于是否有可用的GPU,可能是Torch.device("cuda")或Torch.device("cpu")。一旦我们获得了该设备的句柄,我们可以将其作为可选参数传递给创建张量,如最后几行所示。因此创建张量,如果你有一个现有的张量。
它在一个设备的内存中,而你想将其移动到另一个设备。你该如何操作?在这个单元中,我们将演示如何创建一个张量在CPU中,例如,如果你想将其移动到GPU,你可以输入字符串ka或k:0,k:1。或者你可以传递先前获取的设备的句柄。
你可以将其传递给two方法,如此,这就是允许你更改张量数据类型的same two方法。如果你想同时更改数据类型和设备,则必须指定参数的名称,比如dtype=Torch.float16,device=你的GPU。
这就是如何将所有张量、学习权重以及从CPU内存移动到GPU的过程。有时你会有一个张量,需要它以不同的形状存在。因此我们将查看几种常见情况以及Pytorch提供的工具来帮助你处理这些情况。你可能需要改变维度数量的一种情况是当你向模型传递单个输入实例时。
Pytorch模型期望批量输入,而不是单个实例。例如,如果我们有一个图像分类模型,输入为一幅三色图像,226x226像素。每个输入图像将表示为一个3x226x226的张量。你的模型期望的形状是n x 3 x 226 x 226。
其中n是批次中的图像数量,例如在训练时可能是8或16。但假设你在逐个进行推理,如何将其批量化为1?我们将使用unsqueeze方法来实现。我们从一个随机张量开始,代表我们的输入。
3 x 226 x 226 的图像表示,然后我们将调用 unsqueeze 的零,并获取该张量并检查其形状。我们会看到它变成了 1 x 3 x 226 x 226。我们在开头添加了一个维度。这就是 unsqueeze 中的 0,表示我们希望这个新维度是第一个维度,即索引 0 的维度。这就是 unsqueeze 的意思。我们在这里所说的 squeezing 是指什么。
我们利用了扩展为 1 的任何维度不会改变张量中的元素数量这一事实。因此,例如,在这里如果我们创建 C,一个 1 x 1 x 1 x 1 x 1 的张量。当我们打印它时,我们看到它只有一个元素,还有很多方括号。所以继续上面的示例,使用我们的图像分类器。
假设模型的输出是每个输入的 20 元素向量。你可以期待输出具有 n x 20 的形状,其中 n 是输入批次中的实例数量。因此,你放入的输入实例越多,你希望得到的预测也越多。这意味着对于一个单一的输入批次,我们将获得形状为 1 x 20 的输出。那么,如果你想对该输出进行非批处理计算呢?
对于这一点,我们只是期望得到一个 20 元素的向量,所以我们有 squeeze。那么这里发生了什么呢?我们再次创建了一个随机的 1 x 20 向量,作为我们的输出张量。我们可以检查它的形状并验证它是 1 x 20。然后我们可以对其调用 squeeze 的零。那就是说,我们希望将该扩展为 1 的维度压缩掉。
当我们调用时,我们查看 B 的形状,可以看到它只是一个 20 元素的张量。现在这只能在扩展为 1 的维度下完成。因此,在接下来的诗句中,使用变量 C 和 D,我们创建一个随机的 PyTorch 张量。然后我们尝试压缩它的第一个维度。
如果你检查 squeeze 的输出形状,你会发现它与开始时的形状相同。我们没有失去一个维度,因为在这种情况下没有办法做到这一点而不损坏数据。因此,squeezing 和 unsqueezing 只会在扩展为 1 的维度上有效。你可能在其他地方使用 unsqueeze 来帮助广播。如果你之前记得。
我们有一些代码来演示广播,我们将一个 4 x 3 x 2 的张量与一个 3 x 1 的张量相乘,结果是当维度对齐时,原始张量中的每个三元素列都应用了相同的操作进行乘法。
现在,如果我们没有 3 x 1,而是有一个我们想要进行广播求和操作的三元素列向量呢?
如果我们查看下一个单元,我们可以看到如果我们直接查看 A 和 B 的创建情况。广播在这里无法发生。尾部维度不匹配。那么我们该怎么办?我们使用 unsqueeze。在单元中创建一个扩展为 1 的额外维度。然后当我们将随机的三元素向量与较大的张量相乘时。
我们可以看到张量中的每个三元素列都有一个乘法操作在其上广播。因此,这可以是一种操纵维度的方式,以便让广播为你工作,而无需转置任一张量的维度。Squeeze和unsqueeze方法也有就地版本。就像我们早些时候看到的数学方法一样,如果我有一个输入实例。
如果我想创建一个批次为1,而不是调用unsqueeze,我可以调用带下划线的unsqueeze,并进行就地操作。现在,有时你会想更激进地改变张量的形状,同时保留张量中元素的数量及其内容。
这种情况发生在一个例子中,即图像分类器。此类模型的计算开始时通常涉及卷积层,而最后的分类部分则涉及全连接层或线性层。
现在,卷积层在处理图像时,通常会输出一个三维张量。你会有一些水平和垂直的范围,用于将特征的检测在图像上进行空间映射。然后,它还会有一个深度,这将是该卷积核学习到的特征数量。接下来的全连接层则只期望一维向量。
那么,我们如何在这两种情况下进行转换,其中输出向量变为输入向量,但需要改变形状,但保持相同数量的单元呢?好吧,我们能做到的就是使用reshape方法。因此,在这里我们将创建一个6乘20乘20的张量,作为我们卷积层输出的占位符。
我们将把它重塑为一个一维张量,包含6乘20乘20个元素,这些元素代表我们全连接层的输入。现在,当它可以时,reshape实际上会在原始张量上输出一个视图。因此,它不会创建一个具有新内存分配的新张量对象,而是创建一个新的张量对象,指向第一个张量底层的相同内存。这一点很重要,如果你使用reshape并且返回原始张量的视图。
请注意,源张量中的更改将在新张量中反映,除非你克隆它。在此介绍的范围之外,还有条件需要reshape返回带数据复制的张量,更多信息可以参考相关文档。我最后写的主题是张量简介。
数据在numpy张量和PyTorch张量之间的可移植性如何?现在,在上面的部分,我们简要提到PyTorch的广播语义与numpy相似。但这两个库之间的连接更深。如果你有现有的机器学习或科学代码,其中数据存储在NI和D数组中。
你可能希望将相同的数据表示为 Pytorrch 张量,以利用 PyTtorrch 的 GPU 加速或其高效的深度学习模型构建抽象。在 Numpy、Di Rays 和 Pytorrch 张量之间切换非常简单。所以在这里的第一个单元我将导入 Ny。然后我们将创建一个 Nuy 数组。
一个充满一的 2x3 矩阵。现在要将其表示为 Pi Torch 张量,我们用 Numpy 数组作为参数调用 Torch。我们得到一个张量并将其打印出来,我们会看到它的形状相同,包含相同的数据,甚至保留了 64 位浮点数据类型,这是 Numpy 的默认值。转换在另一方向上同样简单。
所以在这里我们将创建一个随机的 Pi Torch 张量。然后我们将在其上调用 Numpy,我们会得到一个 Numpy 和 D。现在重要的是要知道这些转换后的对象使用与其源对象相同的底层内存。这意味着对一个的更改会反映在另一个上。所以当我运行最后一个单元时,你会看到更改了 Numpy 数组中的一个元素的值。
我们在从中创建的 Pi Torch 张量中看到了这一点。同样,当我更改我们制作的 Pi Torch 张量中的一个值时,它会反映在我们从中创建的 Nuy 张量中。所以,如果你已有代码在操纵 NPI 中的数据,将其迁移到 P Torches 是轻而易举的。
这是我们对张量的第一次深入探讨。我们今天讨论的主题和 Pytororch.org 上的文档应该是你在后续视频中和独立工作中开始所需的一切。感谢你的收听。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律