ShowMeAI-人工智能工具笔记-七-

ShowMeAI 人工智能工具笔记(七)

Python 3全系列基础教程,全程代码演示&讲解!10小时视频42节,保证你能掌握Python!快来一起跟着视频敲代码~<快速入门系列> - P7:7)Python列表 - ShowMeAI - BV1yg411c7Nw

欢迎回来,大家。我是布赖恩。在这个视频中,我们将讨论列表。列表是一种复杂的数据类型,相比于我们之前讨论的内容,它非常复杂。到目前为止,我们讨论了布尔值、数字和字符串,但列表要复杂得多,正如我们即将看到的那样。那么首先,什么是列表呢?😊

好吧,它是有序的。

列表或数据集合,我的意思是什么?想象一下,我们添加一个项目。那个项目将位于位置0,这意味着你添加的第一项始终是0。当我们添加项目时,你猜对了。那个索引会递增。让我们在这里添加一个项目。所以01、2,这些项目可以相同,也可以不同,甚至可以是一些完全疯狂的东西。

无论我们想做什么,这就是Python的美妙之处。因此,列表不需要被称为“类型”。这意味着你不必使用相同的数据类型。这就是许多不同编程语言中很多列表的工作方式。你可以将字符串与数字和自定义数据类型混合。我们在深入之前的主要要点是,这是一个基于顺序的索引,这意味着它会按照你添加的顺序添加,第一项始终是0。从0开始,依次是1、2,等等。

好吧,让我们先创建一个列表。你会在我们的笔记中注意到这些方括号。这表明它是一个列表,记住这一点很重要,因为我们将讨论其他与列表非常相似的数据类型。

但它们是不同的,并且使用不同的风格。首先,让我们创建我们的列表。记住方括号,我将说x等于方括号。我们放在这些方括号内的任何东西都成为列表的一部分。例如,我将说布赖恩。然后我们通过分号添加另一个项目,然后随便放入我们想放的内容。

所以我们有两个字符串在里面。如果你来自另一种语言,这可能会让你很困惑。我将添加一个数字。没错,这不是一个类型列表。你可能习惯于像C++这样的东西,在那里你必须有一个特定的类型,它只能包含字符串或数字。Python完全不是这样的。

这使得它非常灵活,非常简单。所以让我们在这里写个笔记。我们可以混合数据类型。接下来我们要打印出来。我想说列表。我要打印我们的列表。它会复制和粘贴。让我们把它放在这里并获取长度。因此,你可以看到我们的列表就在这里,并且它在这些方括号内。

始终记住方括号是列表,我们可以有两个字符串和一个数字,我们可以添加任何我们想要的,并且其中有三个项目。如果你来自另一种语言,这可能会让你感到困惑,因为你会想,等一下,你不能有多种类型,但在Python中可以。这使得它非常方便。

动态创建自己的数据结构非常简单。让我们在这里特别注意索引和位置。这让很多人感到困惑。我们认为,嗯,人类,第一个项目总是1。可是计算机并不这样认为,第一个项目总是0,因为你是从零开始的。

所以当我们谈论列表时,这是基于零的。让我们继续,叫上我们的朋友打印,并说我们想要0。所以要抓取那个列表中的第一个项目。只需说方括号和索引。现在,请注意,我们并不是在创建一个列表。我们是在说,在那个列表中,获取那个索引。在这个例子中,是0或第一个项目。

我将把这一点用大写字母写出来,供新手参考,第一个项目是0。请记住。人类认为第一个项目是1,计算机认为第一个项目是0,因为你是从零开始的。现在,如果你看过前一个关于字符串的视频,我希望你看过。你应该理解切片是什么。但以防你跳过了。

切片很像切面包。你面前有一块新鲜烤制的面包。如果你只想要一片,而不是整个面包,或者一块派可能是更好的例子。所以我们将把这个打印出来,我们将进行切片。所以我将说,我想要X。然后我们要,你猜对了。现在,请注意,这些也是方括号。

我们在上一个视频中没有涵盖这一点。但是,当你看到方括号时,这意味着我们想要这个列表中的一部分,或者在这种情况下,是它的一部分。我只会在这里放一些引号。P是一些引用和评论,切片列表。所以这将意味着X,并且我们有一个起始位置和一个结束位置。

我们将从第一个位置转到第二个位置。现在,请记住,第一个不是第一个项目,而是位置零。记住,这在零基索引方面会非常混淆。为了说明这一点,从一到二的位置实际上是凯伦的。所以我们正在拿这个列表,并且我们说0,1。到2,所以它将停止。

如果我们省略这个第二个位置,我们将获得其余部分。我们将说我们想要那个整个切片。让我们演示一下这是否按预期工作。切片是一种非常方便获取子项目的方法。

你可能会想,列表很好,但现在我创建了列表,如何向其中添加项目呢?这是一个常见问题。所以我们将在这一小节中讨论如何添加项目,你可以选择追加或插入。它们的功能确实如同听起来那样,举个例子,X。pen。我们要说一根笔披萨。让我们继续进行 X dot append。

我这样做两次是有原因的,你稍后会明白。并添加啤酒,因为每个人都喜欢披萨和啤酒,对吧?现在我们想要插入。因此,aend 会将项目按顺序放在末尾。注意我们进行了两个追加。披萨和啤酒,所以它将添加披萨,然后添加啤酒,两个都会放在末尾。

现在插入。允许你说,我想把这个放在特定的位置。因此,因为我们在谈论一个特定的,我需要给它一个数字。在这种情况下是 1。你注意到它需要一个索引,一个整数,说明你要把这个放在哪里。所以我会简单地说 1。然后我们添加猫。继续跟着。

我们在这里做的是将披萨添加到这个列表的末尾,然后添加啤酒。接着我们要去到一的位置,而不是开头。开头是 0。记得哦。我们要去到一的位置。并添加猫。让我们在这里添加一些注释。这样,任何从 GitHub 下载此代码的人都能有注释并轻松跟随。

现在,让我们进行打印。我想查看这个列表的完整内容。让我们看看这是什么样子。好的,在这里。你可以看到我们的列表,我们有布莱恩,然后猫被插入到第一个位置。接着是我的名字凯伦的 46,然后是披萨和啤酒。

理解追加会按你追加的顺序进行是非常重要的。所以它把披萨放入了列表。然后把啤酒放在了列表的末尾。一旦你理解这一点,就会很简单,但这常常让很多新手困惑。记住这一点,当你想添加特定的索引时。

如果你想将其放在末尾,你需要执行插入,你要做 append。

好吧,现在我们添加了项目,接下来我们来谈谈如何移除项目。我们说的是删除。我们要删除 pop 和 delete。这两者的功能非常不同。乍一看,它们可能看起来非常相似,所以我会说 X。那就移除。可我不想移除猫。我不是特别喜欢移除猫,因为我正好爱猫。

但你知道我的意思,有时你就是得把猫弄出去。因此,remove 将做的是遍历并移除这里的第一个项目。Sra 我们的打印语句。把它放在这里,然后运行这个。好的,你可以看到布莱恩卡斯,凯伦。现在是布莱恩凯伦,我们移除了猫,所以只移除了那个第一个项目。现在,让我们谈谈。

现在。不要太兴奋,pop 不像可乐或百事可乐之类的。但我们想做的是删除一个项目,同时返回它。这意味着我们希望能够在这里处理它。所以我要说我等于。我们将做 X.dot.index,因为我们想在这里找到某些东西。我们想找到比萨。

如果在里面没有找到,这将引发错误,所以如果你只是找一些疯狂的东西。它不会返回负一,实际上并没有“fine”,记得我们在上个视频中谈到的“fine”吗,它返回了负一。这只会说,嘿,有个错误,它会让你的程序崩溃。听起来确实很糟糕,直到我们进入更高级的讨论,讨论如何绕过这个问题,以及它为什么会存在。

所以,现在要大跨步信任一下。我们知道比萨在里面,因为我们已经添加了它。我们要获取那个索引,因为没有人想坐在这里数数,弄清楚这个位置实际上在哪。我们要说食物。然后我们要 pop。现在,当你想到 pop 时,想象一下把一个冰凉的汽水或啤酒的顶部打开,或者任何你喜欢的饮料。

现在你手里有那个盖子了,当你把它打开的时候。这就是我学习 P 的方式。所以当你打开盖子时,你仍然有这个盖子,在这种情况下,它是索引中任意比萨的项目。听起来超级混乱,确实是,但一旦你看到它的实际操作,就会觉得很简单。所以我们要做的是,我将清空这个列表,以避免任何混淆。

我们要运行这个。砰,所以这里发生了什么。我们有我们的列表,看看里面有比萨。我们要 pop。意思是我们要把手里的那个东西的盖子打开,现在我们有了那个瓶盖。这个瓶盖是比萨,所以我们现在可以使用它,但一旦我们打开它。

它不再在列表中,看看它是如何被移除的。如果你想移除项目,这非常方便,但同时也可以使用该项目。听起来有点混淆,但请耐心一点。实际上,在更高级的编程中,这种情况会用得很多。好的,接下来,我们要谈谈删除。所以我想说我等于。说 X 索引。

让我们获取啤酒的索引。因为毕竟,没有人想坐在这里一个个数零、1、2、3。没有人想这样做,我们只想让计算机为我们找到它实际上在哪儿。所以一旦我们获得那个索引,我应该在这里做个特别说明。如果没有找到,这会引发错误。但一旦我们获得它,我们就想实际删除它。所以我们要说 D EL。X。

然后无论那个位置是什么。现在这将删除项目而不返回它。我会在这里复制并粘贴一些笔记。所以删除特定项目而不返回它。而 pop 将移除并返回项目。这是根本的区别。你会使用哪个,为什么呢?好吧,pop 是如果你想实际使用它的话。

删除就是如果你想让它消失。现在,当你删除它时,它就不复存在了,你不能再使用它。它甚至在内存中都不存在了。这就是它被称为删除的原因,因为你实际上是将其从内存中删除。如果你来自C或C++或其他任何语言进行内存管理,没错。

你实际上是将其从内存中删除。现在,底层发生的事情是Python将其标记为垃圾收集和其他一些新手不太理解的复杂操作。但如果你是更高级的用户,这就是Python在说。😊。将其从Python内部列表中删除。我们只是让垃圾收集稍后清除它。

保存并运行,这里发生的事情是,我们找到了beer的索引并将其删除。非常酷,非常容易理解,所以从移除项目的主要收获是,如果remove将删除第一个,pop将删除它,但让你操作,而delete将实际删除它并让它消失。让我们谈谈从另一个列表扩展或添加元素。

这可能有点困惑,但请耐心点。你会选择扩展而不是简单地添加一个列表,是因为在Python中,你实际上可以将列表添加到列表中。我们将在本视频的最后部分介绍,但这会变得超级复杂。所以让我们看看。我们将说我们要再创建一个列表。

让我们称之为猫。Tma,狗。那么,Bds。如果有人在想,怎么添加逗号,你并不会直接添加逗号,而是像这样添加为字符串。但我们只是要将猫、狗和鸟加入到我们叫做Y的列表中。现在我们正在使用的列表叫做X。

所以我们想把Y的内容放到X里面。我们将使用x dot extend。有时智能会帮我们,有时则不会。我们将使用Y列表来扩展。让我们打印一下。注意我们在打印X。你觉得这运行时会是什么样子?嗯。

如果你说它将包含两个列表的内容,你是完全正确的。现在。注意它所做的事情是它取了RX。并将Y的元素添加到其中。所以这些现在是X内部的真实项。

这个功能真的很酷!

让我们谈谈排序,当我说排序时,我们是指排序和反向排序。意味着做与字母顺序相反的事。所以我们来做。反向排序。现在,把它想象成升序、降序。现在我们的列表是混合的。那么我所说的混合是什么意思呢?所以如果我们只取这个。打印出来,运行它。

你可以看到我们得到了字符串、字符串、整数、字符串、字符串、字符串。我们将对这个整数遇到问题,我们需要把它移除。我会非常快地演示一下,所以我将说x.dot.sort。这是很多新手会被绊倒的地方,出现了“整数和字符串之间不支持”。

这正是这样,所以它在说它知道如何排序字符串,知道如何排序数字,但它不知道如何将字符串与数字排序。想想这个。假设你面前有一张桌子,我进来扔了一堆土豆和一堆苹果,我说,给我排序。好吧,你想如何排序?你想要土豆在苹果之前,还是想按颜色排序?

但它们都是不同的颜色。这就是我所说的,Python会感到非常困惑。它只会说,知道吗,我甚至不想尝试搞明白这个。我只会抛出一个错误,让你自己去解决。此时摆脱这个的最简单方法就是直接移除它。有些人会说X.dot.remove。

我们将去掉那个提示,然后进行排序。所以现在是按字母顺序,因为我们去掉了那个。它完全知道如何排序这些字符串:Bir,Bryan,Karen的,猫,狗。非常简单。相反的当然就是反转。我们只是为了节省时间来抓取这个。

这显而易见。就像是升序排序,降序排序。我几乎希望他们不叫它反转,而是叫做降序排序之类的,或者在排序内部有一个参数,我们稍后会讨论参数。虽然这可能有点混乱,但只要把排序想象成按字母排序,而反转则是相反的。

你注意到了吗?当我们排序时,我们必须移除那个整数,因为如果类型混合,排序会抛出某种错误。现在,如果你想这样做,但又不想真的修改原始列表,那我们现在要做的就是复制,有些人称之为浅复制。

基本上我们只是这里在做一个复制,所以我们将说y等于x.dot.copy。这正是你想的那样,实际上它创建了一个新列表并将元素复制到其中。我们将说,将元素复制到新列表中。现在我们可以简单地说why.dot.reverse。我们可以添加项目,移除项目,做我们想做的任何事情,所以我可以说,嗯,我得到了一个。

我们来处理苹果吧。我们可以做任何其他我们真正想做的事情,所以让我们抓取这个打印语句。x是原始的,New是R Y。让我们看看它们的样子。所以我们的原始保持不变,而我们的新列表现在有苹果,并且它已经反转了。这个方式真不错,如果你完成了wine,并且不想再要了。

你只需简单地删除它。

这就是我们接下来要讨论的内容。

好吧,所以删除。嗯。删除整个内容实际上就是我在这里要说的。你为什么想删除某样东西呢?在之前的小段落中,我们提到我们要创建 Y,而 Y 是 X 的一个副本。现在我们完成了 Y,就不再需要它了。我们可以做两件事。

我们可以让 Python 自动垃圾回收,意味着它会在不再需要时自行处理。或者我们可以明确地说删除整个列表。是的,这确实会删除整个内容。如果我尝试打印 why,会出错并提示名称 why 未定义。你还记得在之前的视频中,每当你看到未定义的情况。

这意味着它根本不存在了,意味着我们现在已经摧毁了 why,里面的所有内容也被摧毁了。所以对于你们这些计算机爱好者来说,所有的内存现在都被释放并消失了。我们可以用它做其他事情。当你开始谈论嵌入式系统等内存可能会比你的台式机或笔记本更有限时,这一点尤为重要。你要明白,删除某样东西,它就消失了。

我是说,消失得无影无踪,未定义意味着你必须从头开始重建整个数据结构。根本没有恢复它的方式。删除可能有点激烈,正如我们所见,名称 Y 未定义确实是个问题。我是说,如果你不想删除整个变量,而只想删除其中的一部分或清空整个内容呢?

这就是我们在这个小段落中要讨论的内容。我们在谈论清空。把你的列表想象成一张大桌子,上面有盘子、碗碟和各种东西。你不想把整张桌子扔掉。你只想把它清理掉。这正是 clear 所做的。所以它会清除列表中的所有元素。

但列表本身仍然存在。它只是会是空的。演示一下,类型被清空了。因此,在编程的世界里,大多数时候你并不想删除。你只想清空它。所以我们的列表存在,你可以通过这些括号看到,里面只是没有元素。我们实际上可以测试一下。

让我们获取 X 的长度。所以它存在,但里面没有项目。大多数时候,如果你感到困惑,可以这样想:删除就是把整个东西扔掉。你是把整个餐桌都扔掉,而清空只是把桌子上的碗碟清理掉。通常你想要清空,而不是删除,但删除存在是为了你需要释放内存时。

你想做点疯狂的事情。一个列表可以包含其他列表。如果你看这个,它看起来有点奇怪。但想象一下,你有一个开始括号和一个结束括号,接着是开始结束、开始结束,再到开始和结束。所以没错,一个列表可以包含其他列表。如果你来自另一种语言,想象这就像一个数组的数组。

这有点复杂,新手可能不太理解。但如果你感兴趣,这就是你该怎么做。所以我们要说x等于,并将x变成一个空列表,里面什么都没有。w等于,我们要创建另一个列表,内容是1,2,3。

让我们再创建一个列表,叫做Z。在这里,我要说。我的名字。你可以把你的名字放进去,或者猫、狗、鸟,随便你想放的东西。所以现在我们有三个不同的列表。我们想要做的是把Z和Y的内容放入X。有人说X停止,接下来让我们加入Y。现在。

我做的是把所有这些数字放在X里面。让我们打印一下。现在,我说合并,但这其实不是我们在做的事情。我们实际上是把所有这些合并成一个巨大的数据结构。你注意到我们有这些双括号吗?所以我们所说的就是这个项目。

这个独立元素是它自己独特的列表。所以我说列表。无穷大。好吧,现在我们想要做的是将Z的内容放入X,但我们想把它放在我们放进去的其他东西之前。说X插入。让我们把这个放在零索引处,把所有的Z放进去。

让我们继续运行这个。你现在看到我们的列表。实际上,它由两个较小的列表组成。新手可能会看到这里有五个项目,但其实并没有。让我们在这里测试一下。所以我们说,抓住这个,叫它我们的列表。让我们开始吧,Lyn。

我们要获取这里面的项目数量。这里面只有两个项目。非常简单,非常容易理解。现在假设我们想抓取第一个项目。我们要说零,然后去0。让我们抓住那个第二个项目。所以我们的第一个项目是这个列表,它是自己的小列表。第二个项目是这个列表。

如果你在想,是的,你可以在这里有点疯狂。我们现在所做的是深入这些列表。所以在我们的第一个列表中,就在这里,我们要抓取第一个项目,它是素数。在我们的第二个列表中,我们要抓取第二个项目,注意那是在位置一,即2。

这看起来超级混乱,但你可以这样想。想象每次看到这些括号时,你就像是一步步走向地下室。所以例如,我们可以把这个调换过来,抓住第一个项目,就是1。

我们可以再调整一下,说我们想要第二个项目。那就是三。如果你是新手,这似乎超级困惑,但相信我,一旦你深入更高级的内容,这将是一个巨大的时间节省,仅仅是简单地列出列表。当你开始处理像网络服务这样的事物时,你会发现数据基本上是一个列表的列表,你只需简单地导航。

好吧,这里有一点额外的材料。我知道我会被问到这个问题,所以我想我就加上。你如何改变一个项目?记住,这是基于位置的。所以比如说,让我们设定x等于一些数字,1,2,3,4,5。我们实际上想改变这个,当我说改变这个时。

我们不想改变整个列表,只想改变一个特定的项目。所以我将说X,然后无论项目编号是多少。假设我想改变位置2的项目。我们想把它改为“测试”这个词。记住,这是基于零的,这让很多新手感到困惑,所以我们有零,1,2。

所以我们要改变这个家伙。我们直接打印出来。让我们看看实际效果,来吧。01,2,我们的两个位置现在是测试4,5。这就是改变某样东西的非常简单的方法。很多人,尤其是我,会认为这理所当然,因为这太简单易用了。

如果你使用过其他语言,你可能在寻找像“更改元素”或“交换元素”这样的东西。实际上,这非常简单。你获取列表,取出位置,然后赋值给它。

Python 3全系列基础教程,全程代码演示&讲解!10小时视频42节,保证你能掌握Python!快来一起跟着视频敲代码~<快速入门系列> - P8:8)Python集合 - ShowMeAI - BV1yg411c7Nw

欢迎回来,大家好。我叫布莱恩。在这个视频中,我们要讨论集合。现在,集合与列表有些不同。我们在上一个视频中花了30多分钟深入探讨列表。如果你还没看那个视频,我强烈建议你回去看,因为我们真的深入讨论了列表。😊,集合。

不过,它稍有不同。这个区别意味着在底层有着深远的不同。我们来看看。集合包含无序、唯一和不可变的数据类型在一个哈希表中。让我们分解一下。这究竟意味着什么?无序,意味着我们无法控制顺序,就像在列表中。

你可以添加或插入,这意味着我们现在可以控制顺序。集合无法做到这一点。集合确定唯一的顺序,这意味着你不能有多个相同的项。如果你试图添加两个猫或两个狗,它就是不行的。不可变数据类型。这意味着什么?意味着一旦添加,我们无法更改它们。

我们只能删除或添加它们,不能更改单个项目,而且它是在哈希表中。哈希表在计算机理论中有点复杂。但当你听到哈希表这个术语时,想想超快的读取访问。集合确定顺序,以便它确切知道内存中的位置,使其速度非常快,所以如果你想要非常。

如果你需要快速查找,集合就是你需要的。

现在我们明白了什么是集合,让我们创建一个。首先,我们说S等于,然后我们想要这些小的花括号。记住,如果你使用方括号,那是列表,完全不同的数据类型。你需要花括号。在这里,我只会说一,但还有两个。

三,四,五。你可能会想,等一下。我以为它必须是唯一的。嗯。这是我非常喜欢Python的一点。它会自动为你剔除所有重复项,所以你不必担心。看到没。一,二,三,四,五。即使我们尝试在这里添加多个二。

它聪明到足以意识到它已经存在,并说,不,不能这样做。并且不会引发错误或其他问题。所以我们不必担心它会在这里崩溃。我们还可以将列表反转为集合。让我们展示如何做到这一点,梅赛。这里是我们的列表。

A的名字和年龄即将出现。现在我们要说S等于,并使用集合函数。它的作用是将任何类型的数据,例如我们之前讨论过的列表,进行转换。它会自动处理,我们甚至不需要思考。我会抓取这个。现在,请注意顺序。

我做了 Brian Karen 的 46,在列表中,它将完全按照我们放置的方式。然而,在集合中,它实际上是 46 Brian Karens。所以集合现在正在确定位置。这是关于集合你真的需要牢记的一件事:集合是无序的、唯一的,正如我们稍后将看到的,不可变数据类型。好的。

让我们看看如何向集合中添加项目。实际上,这非常非常简单。所以必须说 S.dot add。你几乎可以添加任何类型的元素。我只是想添加单词 hello。不过还有另一种方法,叫做 update。当我们查看这个时,它看起来有点挑战,写着 star S colon iderable。T none。

这都意味着什么?但当你看到这里的术语时。基本上,我们在谈论类似列表的东西。我不应该说列表,而是像列表那样的东西。某种你可以像列表、集合或元组那样遍历或导航的东西,而我们还没有讨论过。你只需要某种包含多个项目的数据容器,你可以对其进行迭代。

在这种情况下,我们将说。我们想在一个列表中做这件事。说 1,2,3。我将继续添加 hello。注意我有 Ho 两次。但我们正在处理一个只有唯一项目的集合。那么,在后台会发生什么?如果你猜测集合会自动去掉第二个 hello。

你绝对是对的。让我们看看它的实际效果。对。😊,1,2,3,46,Karen 的 hello Bryan,再次。只有无序和唯一的项目。现在我们已经添加了项目。让我们看看如何去掉项目。这同样简单,S discard。discard 正好会执行你想的那样。

它只是把它放进去,直接扔进垃圾箱。然而,discard 和 remove 之间有一个微妙的区别。小测验,有谁知道这里的区别是什么吗?嗯,一个会抛出错误,而另一个不会。因此,discard 不会抛出错误,而 remove 会。

将会抛出一个错误。我们所说的是什么?如果我们以当前的形式运行它,一切都会正常工作。让我们稍微修改一下这个并演示这个错误。因此,在我们的集合中,我们有 1,2,3,Karen 的 46,Brian 和 hello。让我们假设一个我们知道不在里面的数字,78。运行这个,结果是 O。

我们有一个关键字 78,这意味着它知道 78 不在里面。在接下来的视频中,我们将讨论如何解决这个问题。你将使用关键字 in 来确定它是否实际上在里面。但就我们初学者的角度而言,discard 不会抛出错误,而 remove 会。请对此保持警惕,随着你继续前进。我们在这里真的可以做的另一件事。

我们现在可以弹出。集合的弹出功能并不是很常用。我只想说,你可能会倾向于说,我想获取第一个项目、第二个项目或最后一个项目,但你不能这样做。它只会返回一个任意项目。你无法控制它给你哪个项目,这让人有点沮丧。

但如果你只是将集合用作容器,想要获取每个项目并将其移除,那么弹出其实很有用,但对于你来说这将是随机的,你对此将没有控制权。现在你已经弹出了它,你可以对B做任何你想做的事情,因为它仍然存在于内存中。然而,它不再在我们的集合中。我常被问到一个问题,尤其是初学者。

我有一个集合,我想修改它,但不幸的是你不能。不仅无法修改它,你也不能根据索引访问项目,因为集合没有这种概念。我们来演示一下。我将说S和0。然后我们要将其改为A。去运行一下,看看会发生什么,对象不支持项目赋值,哦。

这真让人感到非常沮丧。这实际上是设计使然。一旦你将其放入集合,它就不会改变,因为在底层,它是一个哈希表。它在进行数学计算,以确定需要存储的位置,以便进行快速查找。好的,这并不是什么大事,但我只想打印出一个项目。

我们先尝试打印出第一个项目,看看会发生什么。集合对象不支持索引。哦,我的天,这太让人沮丧了。你可能在想,这真傻。为什么要用这个?我们就用列表算了。不过,你可以这样做,但集合是为了特定的原因而设计的,那就是快速查找。

把集合想象成你电脑设置的集合,例如,所有的电脑设置,可能有成千上万的电脑设置。如果你把这些放在列表里,会很难真正导航。因此你会使用类似循环的东西,或使用一些我们尚未涵盖的关键字,这些将在未来的视频中讨论。但我们要谈的是一些简单粗暴的方式来修改集合,比如说。

我们来运行我们的代码,看看结果,我们有346个Karen和Brian。我们来试试3和S。我们先打印出来,看看这个在里面吗。是真的,因此我们知道3在S中。接下来,S去移除,我们想移除那个3。现在,我们要打开并添加。好吧。

基本上,我们在做的事情是,取这个集合,移除这个3并将其改为12。不幸的是,我们无法控制它在集合中放置的位置。让我们打印一下。可能会更多一点。好了,现在是12,46个Karen和Brian。老实说。

纯粹是运气好,它在同一位置,不要指望这个,因为集合是无序的。现在。我们可以在这里做一些疯狂的事情,这真的会让你头疼。所以让我们来。X 等于。我们将创建一个集合。假设 A,B,C,D。我实际上只是重新格式化这个,所以请期待我在输入时犯一些错误。我们将说 C,E,E,F,G。

所以我们有两个集合。现在我们想对这些进行一些数学计算,而这就是进行任何集合修改的标准方法。我们将进行所谓的并集。因此我要说 S 等于,我们想要 x,而不是并集。为什么呢?这将会……我看看我是否有一些屏幕外的笔记。

所有在任一集合中的元素。我将添加一个小的打印语句。因此我们的并集现在是。所有在任一集合中的元素。对集合进行快速修改,你不必去移除再添加、移除再添加并检查是否在其中。它会直接抓取整个集合。

让我们进行交集操作。交集有点不同。它将获取两个集合中的所有元素。但展示一下。两个集合中都有的是 D 和 C。嘿。相当简单,很容易理解。现在我们来点疯狂的。所以我们将抓取这个。我们想要差异。

你有没有听过有人对你说,我们来分一分差异吧。差异是所有在 x 中但不在 y 中的元素。在这种情况下是 B 和 A。还有一个我们将在这里讨论的元素。也许我能让我的鼠标工作。对称差异。现在,这将与你想的有所不同。

所以这就是其中一个集合中的所有元素。这究竟意味着什么呢?保存并运行。所有在其中一个集合中的元素,所以它将获取两个集合,基本上在内存中生成一个第三个集合,并说好的。确保我们返回的是至少存在于我们给定的集合中的唯一项目顺序。

而且这比这要复杂得多,但基本上就是后台发生的事情。你可以看到我们有 F,B,A,G。所以这里的主要结论在顶部。集合包含无序、唯一且不可变的数据类型,存储在极快的哈希表中。集合和列表之间的根本区别是什么呢?

这个集合的使用会稍微有点挑战性,你不能像操作列表那样轻松修改它,但它快得多,快得多。你真的不会理解它有多快,直到你进入更高级的编程。现在,我们正在学习基本数据类型,我们将深入探讨集合。

Python 3全系列基础教程,全程代码演示&讲解!10小时视频42节,保证你能掌握Python!快来一起跟着视频敲代码~<快速入门系列> - P9:9)Python元组:快速且只读 - ShowMeAI - BV1yg411c7Nw

欢迎回来,大家好。我是布莱恩。让我们继续探索 Python 3,谈谈元组这个有趣的名字,但这真的非常酷。元组是一个快速的列表,不能被修改。它是只读的。一旦你创建了它,你就不能对它进行任何更改。😊。这个东西存在的唯一目的是交换数据,通常用于类之间、对象之间。

在框架之间和设备之间。例如,假设有人制作了一个包,提供关于你的 CPU、内存和硬件的所有酷炫信息。他们不希望你能够修改这些内容。所以在表面上看起来可能有点普通和无聊,但正如我们即将看到的,你可以做一些非常酷的技巧。

我们要做的第一件事是创建一个元组。请创建一个名为 T 的变量,并给它赋值。注意它有这些小的圆括号。当你看到这些圆括号时,可以把它看作是一种防护,因为它是只读的。你无法更改它。我们只是给它一些信息。

我们不在乎放进去什么,因为我们只是测试一下,假设打印。你猜对了,它有这些圆括号,这就是标识它是元组的方式。这里的主要收获是不同风格的括号标识它将是什么,无论是元组、集合、列表还是字典,我们尚未覆盖字典。

现在我们有了一个元组,让我们看看如何访问这个元组中的元素。这非常简单。我们之前做过这个。让我们说,打印 F,并通过索引来访问。给出我们的索引位置。记住这是一个零基索引,所以零实际上是第一个位置,然后是 1、2,以此类推。

运行的结果正如你所预期的那样。让我们来做一个切片,因为切片非常简单有趣。我们将获取这个,并说,我想从两个开始,一直到元组的末尾。效果如预期。清空这个,让我们来看一下布尔操作。我们现在要做的是在元组中查找一些特定的内容,我想说的是 T 中是否有 3。

这样做的目的是告诉 Python,嘿,在这个元组中取这个值。它可以是列表、集合或字典。我们尚未覆盖字典。它将搜索并查看它是否确实在里面。让我们返回一个可以说是“是”或“否”的结果。在这种情况下,是的,因为 3 就在那里。

这非常容易使用,而且速度极快。

好吧,额外内容,让我们谈谈赋值。当我说赋值时,你真正指的是什么,我的意思是,元组有点无聊。你创建它们,可以访问元素,除此之外,你就完成了。好吧,你可以做一些很酷的事情,不仅仅是与元组,还是与列表和集合。

但是元组使得理解变得非常简单。所以我们要创建一个元组,放一些变量。这些不是值,而是变量。记住这些是变量,某些东西会改变 X,逗号 Y,逗号 Z。现在我要再创建一个元组,给它值,1,2,3。我们在这里做什么呢?

我们在说的是将这些变量和这些值配对,Python 在后台会弄清楚哪个需要是哪个。然后打印 X。让我们打印 Y。接下来打印 Z。看看这个效果,1,2,3。很美妙。现在让我们谈谈 range 函数,这是一件很多人不太谈论的事情。你只是看到它,并期望它能神奇地工作,让我们来获取这个。好了。

所以我们有了 X Y Z,我们要在这里删除这个,并且我们希望 Python 完成所有这些工作,我们不想坐在这里整天输入值。所以我会说 range。让我们给它一个,看看会发生什么。你可能期待会出现一个错误。

你得到了一个错误。没有足够的值来解包,期望三个,得到了一个。好吧。让我们在那里测试一下,假设我们要 6。我们给它比需要的更多的值。当然,又是一个错误,解包的值太多,期望 3。所以它在告诉你,我需要 3。它从哪里得到 3 呢?就从这里。实际上,Python 正在创建一个变量的元组。

我们可以使用 range 函数将这些变量赋值。现在,range 本身并没有返回一个元组。我们可以通过简单地获取这个来测试一下。然后打印出来。我们实际上将打印 range 3。注意我们得到了 0,1,2。所以这就是我们的范围,但我们打印 range 3,它显示为 range 0 到 3。

所以我们真正要扩展的是 range 本身在告诉 Python,进行循环,这个我们将在未来的视频中讨论。但是你有一个开始和一个结束。我们还没有真正给它一个起始名称。我们只是说,嘿,生成三个值。它将从 0 开始,执行三次。如果我们不想从零开始呢?

我们想从 1 开始。好吧,我们给它一个起始值。现在我们必须给它一个在这里的前进位置。为什么是 4?因为我们需要一个起始位置加上我们需要解包的数量,也就是 4。1 加 3 等于 4。现在它完全按你想的方式工作了。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全 pipeline!<实战教程系列> - P1:L1- 安装 - ShowMeAI - BV12m4y1S7ix

大家好,欢迎来到你们的新教程系列。在这个系列中,我们将学习如何使用 Pytorch。Pytorch 是最流行的机器学习和深度学习框架之一。与之一起工作并开发酷炫的应用程序真的很有趣。所以我希望你们观看这个系列,并学习到关于这个框架所需的基础知识。

在这个第一视频中,我会展示如何安装 Pytorch。让我们开始吧。😊,为此,我们访问官方网站 Pytorch dot org。然后点击“开始”。接着选择最新的 Pytorch 构建。目前这是版本 1.3。

然后选择你的操作系统。在我的例子中,是 Mac。接着选择你想用来安装 Pytorch 的包管理器。所以我强烈推荐使用 Anaconda。如果你还没有安装 Anaconda,并且不知道如何使用它,请观看我关于 Anaconda 的其他教程。

我会把链接放在下面的描述中。然后选择最新的 Python 版本。所以这里我选择 Python 3.7。不幸的是,在 Mac 上,你目前只能安装 CPU 版本。但如果你在 Linux 或 Windows 上并希望获得 GP 支持,那么你还需要先安装 Kuda 工具包。

Kuda 工具包是用于创建高性能 GP 加速应用程序的开发环境。为此,你的机器上需要有一个 Nvidia GP。如果你有的话,可以访问网站,developer dot Nvidia dot com slash kuda minus downloads。

然后我们需要小心,因为目前 Pytorch 支持的最新 Kuda 版本是 Kuda 10.1。所以我们需要获取这个版本。目前最新版本是 10.2。因此我们需要去旧版发布页面。

然后选择最新的 Kuda 工具包 10.1。

然后选择你的操作系统。例如,Windows,Windows 10。接着下载安装程序并按照说明操作。这也会检查你的系统是否适合 Ka 工具包。

如果成功,那么我们可以返回 Py chart 网站并复制这个命令。在我的例子中,现在在 Mac 上,我需要这个命令。让我们复制这个。

现在让我们打开一个终端。首先,我们想使用 Conda 创建一个虚拟环境,在其中安装我们所有的包和安装 Pytorch。所以让我们创建一个环境。假设使用命令 Conda create minus n,然后给它一个名称。我把这个叫做 Pytorch。😊,简单地称为 Pytorch,然后还指定 Python 版本。

假设Python等于3。7,然后按回车。这将创建你的Python 3。7虚拟环境。再按一次回车以继续。这将花费一些时间。现在完成了。所以现在我们可以用Conda激活这个环境,输入pytorch。现在我们处于这个环境中,这一点在开头可以看到。

我们在括号中有pytorch。这是环境的名称。😊,现在,让我们从网站复制我们的命令。这将安装pytorch及所有必要的包。这也将花费几秒钟。现在,再次按回车以继续。现在完成了。我们已经安装了Pytorch,可以通过在这个环境中启动Python来验证。

所以假设输入Python并按回车。现在我们有Python在运行。现在我们可以导入torch模块。如果安装不正确,你将会遇到“找不到模块”的错误。但在这种情况下,它是正确的。现在我们可以,例如,创建一个torch张量。假设x等于torch.dot.R,大小为3。

现在我们想打印我们的张量。这也可以正常工作。我们还可以检查kuda是否可用。因此我们可以说torch.dot.kuda.is_available。在我的情况下,它显示为false。但如果你安装了kuda工具包以及支持GP的Pytorch包,那么这里应该显示为true。所以,是的。现在我们已经在pytorch上安装了,可以开始使用它。

所以我希望你喜欢这个教程,下次见,拜拜。😊。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P10:L10- 数据集转换 - ShowMeAI - BV12m4y1S7ix

嗨,大家好,欢迎回到你们的新Pytorach教程。这次我们想谈谈我们数据的变换。在上一个教程中,我们使用了内置的数据和数据加载器类,如果我们使用像这里看到的内置数据,那么我们会看到可以将变换参数传递给这个数据集,然后应用一些变换。所以在这个例子中,我们建立了一个Ms数据集,然后我们应用了2tenzo变换。

这些将把图像或Nmpy数组转换为Tzos,Pytorch已经为我们实现了很多变换。所以请查看官方文档,你可以在这个链接找到。

在这里你可以看到所有可用的变换。例如,有可以应用于图像的变换。例如,中心裁剪或灰度或抚摸。然后还有可以应用于Tenzos的变换,比如线性变换或标准化。

然后还有转换变换,例如,Tu枕头图像和Tutenzoa变换。

然后还有一些通用变换,我们可以使用Lambdas,或者我们可以编写自己的自定义类。

然后我们还可以组合多个变换,所以我们可以使用transform.dot compose,然后传入一个列表,这将依次应用多个变换。是的,在上一个教程中,我们实现了一个自定义葡萄酒数据集。现在,让我们扩展这个类以支持我们的变换,并编写我们自己的变换类。让我们开始。

在这里,我复制了上一个教程中的代码,我们有自己的自定义葡萄酒数据集。它将加载数据。然后我们实现了get item和长度方法,这将允许索引和长度函数。所以让我们扩展这个数据集。现在这也应该支持变换参数。所以我们把这个放在我们的in it中,并说。

变换,哦,抱歉。变换等于。这是可选的。所以默认情况下,这是没有的。然后在里面,我们存储这个。所以我们说self.dot transform等于transform。

现在我们还需要对我们的get item函数做一些更改。所以在这里我们想要应用一个变换,如果它可用。那么我们假设,sample等于这个。然后我们说如果self.dot transform。所以如果这不是none。那么我们应用这个。所以我们说sample等于self.dot transform我们的sample。然后我们简单地返回我们的sample。

所以让我们回到正题。

样本。这就是我们数据集所需的所有更改。现在让我们继续,创建一些自定义变换类,例如。我们可以编写自己的to Tenor类。因此,在上一个教程中,我们已经在此步骤将其转换为Tensor,但我们不需要这样做,所以我们可以将其保留为nuy数组,然后实现一个to Tenor类。它将被传递到我们的数据集中,然后在后面使用。

将其转换为tenzo。

所以类twotenzor。我们需要实现的唯一内容是双下划线调用方法。它将接收self和一个样本。

所以现在这是一个可调用对象。我们在这里所做的是,首先解包我们的样本。所以我们说输入和标签或目标。

等于样本。然后我们说,返回。Torch从Numpai,和这里的输入。然后也torch从nuy目标。

所以这里我们也返回。我们仍然想返回一个元组,像我们这里做的那样。

这就是我们所需的所有内容,用于我们的2tenar变换。现在我们可以将其传入这里。所以现在我们可以说我们的葡萄酒数据集得到了变换。变换。等于。到Tenz。

这是一个函数。现在,让我们看看这个。所以让我们获取第一个项目。所以我们说第一个数据等于数据集的索引0。然后让我们解包我们的数据, 所以。第一个数据。所以我们说特征和标签等于第一个数据。现在让我们打印特征的类型以及标签的类型。所以现在如果我们运行这个。

然后我们应该看到这个现在是类torch Tenor。如果我们不把它传入这里。所以如果你说这个是none。没有变换,那么我们看到它仍然是一个nuy和D数组。这就是我们如何编写自己的Tenor,自己的变换,然后将其应用于我们的数据集。

现在让我们写另一个自定义变换。例如,称之为mule变换。所以一个乘法。我们在这里实现init方法。所以这里有self,并且这里有一个factor参数。所以在这里我们存储self.dot factor等于factor。然后再次。我们必须实现双下划线调用函数或调用方法。

这个函数接收self和这个样本。

这里再次,让我们解包我们的样本。所以假设输入和目标等于样本。然后我们只需将因子应用到我们的特征上。所以假设,输入。时间乘以我们的自点因子。现在让我们返回我们的输入,修改后的输入和目标仍然是一个元组。

所以这是乘法变换。现在。让我们应用这个。所以让我们应用一个。

并假设在这种情况下是复合变换,看看我们如何使用它。

所以。假设组合等于。这里我们需要torch vision dot transforms,dot compose。我们在这里放入一个变换列表。所以首先,我们想要有totenor。然后我们想要有mal变换。

并且。假设这需要一个因子。所以假设乘以2。现在让我们创建一个新的数据集等于葡萄酒数据集。它的变换等于我们的复合变换。

组成,现在再次,让我们来处理这个。所以获取,或者我们就从这里复制这个。

并运行这个来查看是否有效。

所以现在我们有一个Tenzoa。让我们也看看这个。所以让我们打印。

特征。这里也打印特征。

查看乘法是否已应用。所以现在我们应该看到每个值都被加倍。

现在让我们使用另一个因子。所以让我们乘以4并运行这个。现在我们应该看到每个值都应乘以4。

是的,这就是我们如何为数据集使用变换的方法,非常有用。

是的,大多数时候你会看到转换变换为Tensor。但在我们处理图像时,你可能会看到一些。

所以,是的,请查看文档网站。我希望你喜欢这个教程。请订阅频道,下次见,拜!

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P11:L11- Softmax 和交叉熵 - ShowMeAI - BV12m4y1S7ix

大家好,欢迎回到新的PyTorch教程。这次我们将讨论softmax函数和交叉熵损失。这些是神经网络中最常用的函数之一,因此你应该知道它们是如何工作的。现在,我将教你这些函数背后的数学原理,以及如何在numpy和PyTorch中使用它们。

最后,我会向你展示一个典型的分类神经网络是如何运作的。让我们开始吧。😊这是softmax的公式。它将指数函数应用于每个元素,并通过所有这些指数的和进行归一化。因此,它基本上将输出压缩到0和1之间,得到概率。

让我们看一个例子。😊假设我们有一个线性层,它有三个输出值。这些值称为分数或锁定值。它们是原始值。然后我们应用softmax并得到概率。每个值被压缩到0和1之间,最高的值得到最高的概率。

如果我们将这三个概率相加,就得到1。这就是我们的预测。然后我们可以选择概率最高的类。所以,这就是softmax的工作原理。现在让我们看看代码。我已经在numpy中实现了它。我们可以在一行内计算。

我们有指数,然后我们除以总和。

所有这些指数。现在,让我们运行这个。这与我幻灯片中的值相同。在这里,我们也看到最高的值具有最高的概率。我在幻灯片中对它们进行了四舍五入,所以稍微不同,但基本上是正确的。当然,我们也可以在PyTorch中计算它。

我们创建一个张量。假设x等于torch.tensor,它得到与这个相同的值。然后我们可以说outputs等于torch.softmax(x)。我们还必须指定维度,所以我们说dim等于0。这是在第一个轴上计算。现在让我们打印这些输出。

在这里我们看到结果几乎相同。

所以,这有效。现在继续。很多时候,softmax函数与所谓的交叉熵损失结合使用。这测量我们的分类模型的性能,其输出是0到1之间的概率,可以用于多类问题。

当预测概率与实际标签偏离时,损失增加。因此,我们的预测越好,损失越低。这里有两个例子。这是一个好的预测,交叉熵损失较低。而这是一个差的预测,交叉熵损失较高。

我们还必须知道的是,在这种情况下,我们的 y 必须是热的,独热编码。假设我们有三个可能的类别,类别 0、1 和 2。在这种情况下,正确的标签是类别 0。所以这里我们必须放一个 1,所有其他类别我们必须放 0。这就是我们如何进行独热编码。

对于预测的 y,我们必须有概率。例如,我们之前在这里应用了软最大值。现在再次,让我们看看代码。我们如何在 nuy 中做到这一点。我们可以在这里计算。因此我们有实际标签的总和乘以。

预测标签的锁定。然后我们必须在开头放一个 -1。我们也可以对其进行归一化,但我们在这里不这样做,所以我们可以将其除以样本数量。然后我们创建我们的 y。正如我所说,这必须是独热编码。因此这里我们有其他示例。如果是类别 1,则必须像这样,例如。然后在下面。

我们提出了两个预测。这些现在是概率。第一个预测是好的,因为在这里,类别 0 拥有最高的概率。第二个预测是差的。在这里,类别 0 的概率非常低,而类别 2 的概率很高。然后我计算熵。

交叉熵和预测两个。所以让我们运行这个。在这里我们看到第一个预测有一个低损失,而第二个预测有一个高损失。现在再次,让我们看看如何在 Pytorch 中做到这一点。为此,我们首先创建损失。所以我们说损失等于 N,N 来自神经网络火炬和 N。模块,N,N dot 交叉熵损失。

现在我们必须知道的事情是,让我们再次查看幻灯片。在这里我们必须小心。因为交叉熵已经应用了锁定的软标记,然后是负对数似然损失。所以我们不应该或不能自己实现软标记层。这是我们必须知道的第一件事。第二件事是这里我们的 y 不能是独热编码。

所以我们应该只在这里放正确的类别标签。此外,为什么预测有原始分数。所以这里没有软标记。

所以要小心这一点。现在让我们看看实际情况。假设我们创建实际标签。这是一个 torch dot tenzor。这里我们只放正确的类别标签。假设在这个案例中,它是类别 0。不再是独热编码。然后我们有一个好的预测。Y 预测好等于。😊。

Torch dot tenzor。在这里我们必须注意大小。所以这个大小是样本数量乘以类别数量。假设在我们的案例中,我们有一个样本和 3 个可能的类别。所以这是一个数组的数组。在这里我们放入 2。01。0 和 0。1。请记住,这些是原始值。所以我们没有应用软最大值。然后这里。

最高的。或者对。类0具有最高的值。这是一个好的预测。现在让我们做一个不好的预测。所以不佳的预测。在这里,第一个值是较低的值,假设是,第二个值很高。我们也稍微改变一下这个。现在我们这样计算损失。

现在我们称这里创建的损失函数。然后我们输入预测的y和实际的y,第二个也是如此。让我们计算第二个损失,预测的y不佳和y。现在让我们打印它们。我们打印L1。Dot item。它只有一个值,所以我们可以调用item函数和L2 dot item。

让我们运行这个。是的,我们看到好的预测有较低的交叉熵损失。所以这是有效的。现在要获得实际预测,我们可以这样做。假设下划线,因为我们不需要这个。然后预测。Dicctions等于torch.dot max。然后在这里我们输入预测。即好的预测y。

然后沿着第一个维度。同样的不佳预测。所以我们称之为预测1和预测2。嗯。让我们打印我们的预测。所以预测1和打印预测2。在这里我们看到我们选择了最高的概率。因此在这种情况下,我们选择这个,在第二种情况下。

我们选择这个。所以这里是类别编号1。这就是我们获取预测的方式。还有一点非常好的是,Pyto中的损失允许多个样本。所以让我们在这里增加我们的样本。假设我们有三个样本。所以三个可能的类别。然后我们的张量必须有三个类别标签,我们的实际y。因此,例如,2,0和1。然后,我们的。

预测必须是样本数量乘以类别数量的大小。所以现在这是3乘3的大小。让我们这样做。所以在这里我们必须放入另一个带有三个值的列表。所以,嗯。像这样,像这样。假设这是一个好的预测。所以第一个类,第一个正确标签是类别编号2。

所以这个必须是最高值,这个必须是低值。假设是001。在这里,第一个类必须有高值。像这样。然后中间的值必须有最高的原始值。例如,像这样。然后,我们对不佳的预测做同样的事情。假设这里我们有一个更高的值。

还要稍微改变一下这个。然后我们可以再次计算多个样本的交叉熵。现在让我们运行这个。然后我们再次看到,我们的第一个预测是好的,并且有低损失。第二个就不太好了。是的,我们从第一个得到了正确的预测。

预测张量。所以这里我们也有2,0,1,和实际的y一样。所以,是的。这就是我们如何在Pytorch中使用交叉熵损失的方式!

现在,让我们回到幻灯片。所以现在我想展示一个典型的神经网络是怎样的。在多分类问题中,这是一个典型的神经网络。我们想要找出我们的图像显示的是哪种动物。因此我们有一个输入层,然后一些隐藏层,也许在中间有一些激活函数。

在最后,我们有一个每个类别的输出为一的线性层。所以这里我们有两个输出。在最后,我们应用softmax并获得概率。所以现在,如我所说,在PyTorch中,我们必须小心,因为我们在这里使用交叉熵损失。

所以我们在神经网络中必须不使用softmax层。因此我们必须不自己实现这个。让我们看看这个代码的样子。在多分类中。

分类,我们的网络,例如。看起来是这样的。所以我们定义我们的层。我们有一个线性层,它接收输入大小和一个隐藏大小。然后我们在中间有激活函数。最后一层接收隐藏大小,输出大小是类别的数量。对于每个可能的类别,我们都有一个输出。

在前向方法中。我们只应用我们的层,而在最后没有softmax。然后我们创建我们的模型,然后我们使用交叉熵,它适用于softmax。所以要小心这里。

这个例子也适用于更多类别。如果我们的图像也可以是鸟或老鼠或其他,那么这是正确的布局。但如果我们只是有一个二元分类问题,具有两个可能的输出。那么我们可以这样更改我们的层。所以,现在我们重新表述我们的问法。我们只是说。

这是一份文档吗?是或不是。然后在最后,我们有一个只有一个输出的线性层。我们不使用softmax函数,而是使用sigmoid函数。然后得到一个概率。如果这个概率高于0.5,我们就说是。这里在PyTorch中,我们使用BCELoss或二元交叉熵损失。

所以在这里我们必须在最后实现sigmoid函数。让我们看看在二元分类情况下的神经网络。所以在这里首先。我们设置我们的层和激活函数。最后一层的输出大小为1。在这种情况下总是固定的。然后在前向传播中,现在在应用我们的层后。

我们还必须实现sigmoid函数。所以,是的,然后在这里作为标准,我们使用二元交叉熵损失。所以在这两个不同的方面要非常小心。

不同可能的神经网络。

是的,这基本上就是我想要展示的内容。所以最后的结构也是我在逻辑回归教程中使用的,如果你还没看过,可以去看看。目前,我想展示的就是这些。希望你喜欢,并且理解了所有内容。如果你有任何问题,请在下面的评论中留言。如果你喜欢这个教程的话。

那么请订阅频道,下次再见,拜拜。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P12:L12- 激活函数 - ShowMeAI - BV12m4y1S7ix

嗨,大家好。欢迎来到新的PyTorch教程。这次,我想谈谈激活函数。激活函数是神经网络中极其重要的特性。让我们看看什么是激活函数,为什么使用它们,有哪些不同类型的函数,以及如何将它们纳入我们的PyTorch模型。

激活函数对层输出应用线性变换,并基本决定一个神经元是否应被激活。😊 那么,我们为什么使用它们呢?仅仅进行线性变换为什么不够好?通常,我们会在网络中有一个线性层,该层应用线性变换。在这里,它用某些权重乘以输入,并可能加上偏置,然后输出结果。

假设我们之间没有激活函数。那么,我们的整个网络从输入到输出实际上只是一个线性回归模型。而这个线性模型并不适合更复杂的任务。

结论是,通过在中间加入非线性变换,我们的网络可以更好地学习并执行更复杂的任务。因此,在每一层之后,我们通常希望应用这些激活函数。这里,首先是我们正常的线性层,然后应用这个激活函数。这样,我们的网络能够更好地学习。现在,让我们讨论最流行的激活函数。

我想展示的函数是二进制阶跃函数、sigmoid函数、双曲正切函数、ReLU函数、Leaky ReLU和softmax函数。首先,从简单的阶跃函数开始。当我们的输入大于一个阈值时,它将输出1。这里的阈值是0,否则输出0,这实际上在实践中并不常用。

但这应该演示一个神经元是否应该被激活的例子。而且,一个更流行的选择是sigmoid函数。如果你看过我关于逻辑回归的教程,你应该已经知道这个。它的公式是1除以1加上e的负x次方,这将输出一个介于0和1之间的概率。

这通常用于二分类问题的最后一层。那么,我们有双曲正切函数,也称为tanh。它基本上是一个缩放的sigmoid函数,并且稍微有点偏移。因此,它的输出值在-1和1之间。

实际上,这在隐藏层中是一个不错的选择。你应该了解tanh函数。接下来是ReLU函数,这是大多数网络中最流行的选择。ReLU函数对负值输出0,对正值则直接输出输入值。

这实际上是一个对大于0的值的线性函数,而对负值则为0。因此,它看起来与线性变换没有太大不同,但实际上它是非线性的,实际上是网络中最流行的选择,通常是激活函数的一个非常好的选择。

一条经验法则是,如果你不知道应该使用哪个函数,那么只需在隐藏层中使用ReLU。是的,这就是ReLU,非常受欢迎的选择。然后我们还有泄漏ReLU函数。这是ReLU的稍微修改和改进版本。因此,对于大于0的x,它仍然只输出输入。

但是这会对负数的输入乘以一个非常小的值。因此,我在这里为负数写了a乘以x,而这个a通常是非常小的。例如,0.0001。这是ReLU的改进版本,试图解决所谓的消失梯度问题。因为使用正常的ReLU时,我们这里的值为0。这也意味着在反向传播中,梯度也是0。

当梯度为0时,这意味着这些权重将永远不会被更新。因此,这些神经元不会学习任何东西。我们也称这些神经元为“死亡”。这就是为什么有时你想使用泄漏ReLU函数的原因。所以每当你注意到在训练过程中权重不会更新时。

然后尝试使用泄漏ReLU代替正常的ReLU。最后,我想向你展示Softmax函数。你也应该已经知道这一点,因为我有一个关于Softmax函数的完整教程。因此,这基本上会将输入压缩为0到1之间的输出,以便我们得到一个概率作为输出。这通常是多类分类问题最后一层的一个不错选择。

是的,这就是我想展示的不同激活函数。现在让我们跳到代码,看看如何在PyTorch中使用它们。因此,我们有两个选择。

第一个是将我们的函数创建为NN模块。在我们的网络的初始化函数中,首先定义我们想要的所有层。例如,这里,我们首先有一个线性层。然后,我们想要一个ReLU激活函数,所以我们在这里创建我们的ReLU模块。我们可以从torch的NN模块中获取。

这包含了我刚才展示的所有不同函数。接下来我们有这里的下一层,例如,下一层线性层。然后是下一个激活函数。在这里,我们在最后有一个Sigmoid函数。在前向传播中,我们简单地依次调用所有这些函数。因此,首先。

我们有线性,第一层线性,得到一个输出。然后我们使用这个输出并将其放入我们的relo中。接着,我们再次使用这个输出,将其放入下一个线性层,依此类推。这是我们可以使用它的第一种方式,而第二种方式是直接使用这些函数。

在init函数中,我们只定义我们的线性层。所以线性1和线性2,然后在前向传递中,我们应用这个线性层,然后也在这里调用torch dot relu函数,接着是torch dot sigmoid函数。所以这只是来自torch API的不同使用方式。没错,这两种方式将实现相同的效果。只是你喜欢你的代码方式而已。没错。

所有我刚刚给你展示的函数,你可以从N N模块中获得。所以这里我们有N relu,但我们也可以,比如说,拥有N dot sigmoid,还有N dot soft marks,以及N dot ton H。嗯。还有,N和dot leaky relu。所以所有这些函数在这里都是可用的。

它们在torch API中也可以这样使用。所以在这里我们有torch dot relo,还有torch dot sigmoid。我们也有torch dot soft max和torch dot1n H。但有时这些函数在torch API中不可用,但它们在torch do n n dot functional中是可以找到的。

所以在这里我导入了torch和n functional作为F。然后我可以在这里调用,比如说,F dot Relu。这和torch dot relu是一样的。但这里,比如说,torch的F dot leaky relu只在这个API中可用。所以,没错。这就是我们如何使用激活函数和pytorch。而且这实际上非常简单。

我希望你能理解所有内容,现在对激活函数感到舒适。如果你喜欢这个,请订阅频道,我们下次见!

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P13:L13- 前馈神经网络 - ShowMeAI - BV12m4y1S7ix

嗨,大家好。欢迎来到新的 Pytorch 教程。今天,我们将实现第一个多层神经网络,该网络可以基于著名的无尽数据集进行数字分类。在这个教程中,我们将上一期教程的所有内容结合在一起。因此,我们使用数据加载器来加载我们的数据。我们对数据应用变换。

然后我们将实现一个输入层、隐藏层和输出层的神经网络,并且我们还将应用激活函数。接着我们设置损失和优化器,并实现可以使用批量训练的训练循环。最后,我们评估我们的模型并计算准确率。此外,我们还将确保我们的整个代码也可以在支持 GPU 的情况下运行。

那么让我们开始。首先,我们导入我们需要的东西。所以我们导入 torch。然后我们导入 torch 和 N 作为 N。接着我们导入 torch。😊,Vision 用于数据集。我们导入 torch vision.transforms 作为 transforms。我们还导入 Matpllip.pipl SPLT 来稍后显示一些数据。然后首先。

我们进行设备配置,因此设备配置。而对于这个,我们通过说设备等于 torch.dot.device 来创建一个设备,并且它的名称是 Kuda。如果我们有 GPU 支持。所以如果 torch.kuda 是可用的。如果不可用,那么我们只称我们的设备为 CPU。然后稍后,我们需要将我们的张量推送到设备上。

这将保证如果支持的话,它将运行在 GPU 上。那么,是的,让我们定义一些超参数。在这里我们定义输入大小,这就是 784。这是因为稍后我们看到我们的图像大小为 28x28。然后我们将把这个数组展平为一维张量,28 乘 28 是 784。

所以这就是为什么我们的输入大小必须是 784。然后我们定义一个隐藏层大小。在这里我会说这是 100。你也可以尝试其他不同的大小。还有类别的数量,这必须是 10,因为我们有 10 个不同的类别。我们有数字 0 到 9。然后我们定义训练的轮数。

在这里我会简单设置为 2,这样训练不会花太长时间。但你可以将其设置为更高的值。然后我们在这里定义批量大小,假设为 100。我们也在这里定义学习率,设为学习率等于 0.001。现在让我们导入著名的 Amnes 数据。你可以通过说训练数据集等于从 Pytorch 库中获取它。

在这里,我们使用 torchvision.data.datasets.Amist。

这将需要指定根目录,根目录。

等于,这里应该在同一个文件夹中。所以 .,然后它应该创建一个名为 data 的文件夹。

然后我们说 train 等于 true。这是我们的训练数据集。

然后我们说立即应用一个变换。所以我们说变换等于 transforms.dot to tenzo。我们在这里将其转换为一个tenzzo。

然后我们还说 download 等于 true。所以如果它尚不可用,则应该下载。

然后我们复制这个,对我们的测试数据集做同样的事情。在这里我们必须说 train 等于 false。而且我们也不需要再下载它。现在让我们继续,通过说 train loader 等于来创建数据加载器。在这里我们从 torch.dot u.dot data.dot data loader 获取这个。

然后必须设置数据集,方法是说数据集等于。这里进行训练。

数据集,一个训练数据集。然后我们必须指定批量大小。所以这等于批量大小。

然后我们还要说,或者可以说 shuffle 等于 true。这对训练非常好。然后我们再复制这个,并对我们的测试加载器做同样的事情。所以测试加载器等于获取测试数据集。我们可以说 shuffle 等于 false,因为对于评估来说这无关紧要。现在我们通过说 examples 等于来看一下这一批数据。

然后我们将其转换为内部对象,即训练加载器的迭代器。然后我们可以调用下一个方法,并通过说这等于 examples.dot next 将其解包为样本和标签。现在我们打印这些的大小。所以让我们打印 samples.dot shape。

还有,打印,打印标签的形状。

现在让我们保存并运行这个。所以我们调用 Python feet forward.dot p,看看到目前为止是否有效。是的,这里我们有样本的大小。所以这是 100 乘 1 乘 28 乘 28。这是因为我们的批量大小为 100。因此我们在批次中有 100 个样本。然后的 1 是因为我们只有一个通道。因此我们这里没有任何彩色通道。

所以只有一个通道。这是我们的实际图像数组。所以是28乘28,正如我一开始所说的。我们的标签只有一个大小为100的张量。所以对于每个类别标签,我们在这里有一个值。是的,这就是我们的一些示例数据。现在我们也在这里绘制一下,看看效果如何。所以对于 I 在范围 6 中,这里我们使用 matplotlip,因此我调用 PLT.dot subplot,设置两行三列,索引为 I 加 1,然后我可以说 PLT.show。

我想展示实际数据,所以样本为 I,然后为 0,因为我们想访问第一个通道,然后我还会给它一个颜色映射。因此 cmap 等于 gray。

然后我说P,LT.show。让我们保存这个,并再次运行它。

现在我们来看看数据。这些是一些手写数字的示例。现在我们想对这些数字进行分类。因此,我们想建立一个具有一个隐藏层的全连接神经网络。让我们开始吧!

所以让我们再次注释掉这一点。现在让我们创建一个神经网络类。这必须从一个模块中派生。现在我们必须定义初始化和前向方法。因此,初始化方法将包含self。然后它必须有输入大小、隐藏大小和输出大小。

所以输出大小是类别的数量。首先,我们想调用super的初始化。因此super of neural net和self的初始化。self.dot.init。然后我们创建我们的层。因此,首先我们想通过说self.dot.L1等于Nn.dot.linear来拥有一个线性层。这将把输入大小作为输入,输出大小是隐藏大小。

然后在第一层之后,我们想应用激活函数。这里我简单地使用著名的relu激活函数。因此self.dot.relu等于N N.dot.relu。

然后在最后,我们有另一个线性层。因此self.dot.L2等于。

N,N 点线性。现在我们必须小心。因此,输入大小是隐藏大小,输出大小是类别的数量。

现在让我们定义前向方法。这将包含self和一个样本X。现在我们应用所有这些层。因此,我们说输出等于。现在我们使用第一层L1,它获取样本X,然后下一个输出是self.dot.relu,使用激活函数。最后的输出等于self.dot.L2输出。

这将应用第二个线性函数,现在我们必须再次小心,因为在最后,我们不想要激活函数。因此我们不会像通常在多类分类问题中那样应用softmax,因为稍后我们将看到我们将使用交叉熵损失,而这将会应用。

为我们应用软最大值。因此这里没有软最大值。我们简单地返回输出。这是我们的整个模型。然后我们可以通过说模型等于神经网络来创建它。这将获取输入大小,然后是隐藏大小和类别数量。所以,没错。现在我们有了模型。现在让我们创建损失和优化器。

所以在这里我们说criterion等于N N.dot.cross_entropy_loss。这将为我们应用softmax。因此我们不想在这里使用这个。所以对此要非常小心。现在让我们通过说tor.optimizer等于torch.optim来创建我们的优化器。嗯。现在,让我们在这里使用Adam优化器。并且这必须获取参数。

在这里,我们可以使用模型的点参数。并且它还需要获取学习率。学习率等于学习率。

现在我们有了损失和优化器。现在我们可以进行训练循环。因此,现在是训练循环。为此,让我们首先定义总步骤数。因此,总步骤数等于。这是训练加载器的长度。所以现在我们可以进行典型的循环。我们说四个周期在范围内。

Noum epochs。

因此,这将循环遍历周期。现在我们循环遍历所有批次。因此,在这里我们说for I。然后再次,我们解包这个。因此,我们说images,images和labels。然后我们遍历enumerate我们的训练加载器。因此,enumerate函数将给我们实际的索引,然后是数据,而这里的数据是图像和标签的元组,现在我们必须首先重塑我们的图像。因为如果我们看看形状,我们看到这是100乘1乘28乘28。

正如我在开始时所示。现在我们设置我们的输入大小为784。因此,我们的图像张量需要的大小是100乘784,这是第二个维度。

所以首先是批次数。因此,让我们重塑我们的张量。我们可以通过说images等于images.dot.reshape来做到这一点。在这里,我们将-1放在第一个维度。因此,Tsor可以为我们自动找到这个。在这里作为第二个维度,我们希望有28乘28。然后我们也调用设备。

如果可用,我们将把这个推送到GPU。我们还必须将标签推送到设备。因此,labels等于labels.to.device。现在让我们进行前向传播。因此,首先,我们进行前向传播。然后是反向传播。所以前向传播,我们简单地说outputs等于model。

这将获取图像。然后我们通过说loss等于来计算损失。然后在这里我们调用我们的标准。这样将获取预测输出和实际标签。这是前向传播。然后在反向传播中,首先我们要做的是调用optr.dot0 gra以清空梯度属性中的值。

然后我们可以通过说“丢失的点向后”来进行下一步。这将进行反向传播。现在我们可以调用optr dot step。这样将执行更新步骤并为我们更新参数。现在,让我们打印一些信息。打印损失。假设,如果我加1。Moulular 100等于0。那么每100步,我们想打印一些信息。让我们打印当前的纪元。

通过说这是epoch epoch plus one。然后我们想打印所有的纪元。即纪元数量。然后让我们也通过说step打印当前步骤。这是I plus1。然后通过说n total steps打印总步骤数量。我们还想通过说loss equals loss dot item打印损失。

另外,让我们说我们只想打印四位小数。因此,是的。现在我们完成了训练。这是整个训练循环。现在让我们进行测试和评估。为此,我们不想计算所有步骤的梯度。

我们希望将其包装在with torch dot no gra语句中。首先,我们说正确预测的数量等于0,样本数量等于0。在开始时。然后我们遍历所有测试样本中的批次。我们说“对于图像和标签”,在这里我们可以简单地说在test loader中。然后我们需要重新调整形状。

就像我们在这里做的那样。图像和标签,我们想调整形状并将其推送到设备上。然后让我们调用。通过说outputs equals models来计算预测。这是我们现在训练的模型,这将获取测试图像。然后让我们通过说下划线和predictions equals torch dot max来获取实际预测。

输出和沿着维度,沿着维度1。因此,torch up max函数将返回值和索引。我们对实际索引感兴趣。所以这就是类别标签。因此我们不需要第一个实际值。这些就是我们的预测。现在。

假设样本数量加1。在这里我们说labels dot shape 0。这将给我们样本的数量和当前批次。所以应该是100。然后我们说正确的数量。那么正确预测的数量等于。在这里我们可以说predictions equals equals the actual labels,然后dot sumdot item

对于每个正确的预测,我们将加1。然后,当然,我们必须说plus equals the number of correct。然后当我们完成循环时。通过说a equals 100 times the number of correct来计算总准确率。预测除以样本数量。这是以百分比表示的准确率。

现在让我们打印这个。所以打印。嗯。我们想打印准确率等于。然后我们简单地说a。这样我们就完成了。现在让我们保存这个,清空它,然后运行,希望一切正常。所以现在我们的训练开始了,我们应该看到损失在每一步都应该增加。有时它也会再次增加。但最后,它应该越来越低。现在。

这应该完成,并且测试非常快。所以现在我们看到准确率是94.9。所以它成功了。我们的第一个前馈模型完成了。希望你能理解这一切,并且享受这个过程。如果你喜欢,请订阅频道,我们下次见,拜。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P14:L14- 卷积神经网络 (CNN) - ShowMeAI - BV12m4y1S7ix

大家好,欢迎来到新的 PyTorch 教程。今天,我们实现一个卷积神经网络,并基于 CIFAR-10 数据集进行图像分类。CIFAR-10 是一个非常流行的图像数据集,包含 10 种不同的类别,比如飞机、汽车、鸟类、猫以及其他类别。这个数据集在 PyTorch 中直接可用。

因此,我们将创建一个卷积神经网络,可以对这些图像进行分类。现在让我们简要谈谈卷积神经网络。我不会过多细节,因为本教程应该专注于 PyTorch 的实现,但如果你想更详细地了解,我会在描述中提供进一步的链接。😊

卷积神经网络或称为 confnets 与普通神经网络类似。它们由具有可学习权重和偏差的神经元组成。主要的区别在于卷积网络主要处理图像数据,并应用所谓的卷积滤波器。因此,典型的 conf 架构看起来是这样的。我们有我们的图像。

然后我们有不同的卷积层和可选的激活函数,接着是所谓的池化层。这些层用于自动学习一些图像特征。最后,我们有一个或多个全连接层用于实际分类任务。所以,这就是 CNN 的典型架构。而这些卷积滤波器,现在。

它们通过将滤波器内核应用于我们的图像来工作。因此我们把滤波器放在图像的第一个位置。这就是滤波器。这是输入图像。因此我们将其放在第一个位置,然后通过相乘并求和所有值来计算输出值。

然后我们将值写入输出图像。因此这里是红色位置。接着我们将滤波器滑动到下一个位置,即绿色位置。如果你能看到这里。然后我们做同样的事情和相同的滤波操作。接着我们在整个图像上滑动我们的滤波器,直到完成。

这就是卷积滤波器的工作原理。现在通过这个变换,我们的结果图像可能会有较小的尺寸,因为我们的滤波器在这里的角落不适用,除非我们使用一种叫做填充的技术。但在本讲座中我们不会涵盖这个内容。因此,获取正确的尺寸是一个重要的步骤,我们稍后会在实践中看到。

现在让我们也简要谈谈池化层。因此池化层,或更具体地说,在这种情况下,最大池化用于通过对子区域应用最大滤波器来下采样图像。这里我们有一个 2x2 的滤波器。然后我们查看原始图像中的 2x2 子区域,并将该区域的最大值写入输出图像。

最大池化用于通过减小图像的大小来降低计算成本。这减少了模型需要学习的参数数量,并通过提供输入的抽象形式帮助避免过拟合。所以这些都是我们必须了解的概念。

如果你想了解更多,请查看提供的链接。现在理论部分就到此为止,我们来看看代码。在这里,我已经写好了大部分需要的内容,所以我们导入所需的东西,确保我们有 GPU 支持,然后定义超参数。如果你不知道我是如何构建我的 Pytorch 文件的,请查看之前的教程,因为那里我已经解释了所有这些步骤。

首先,我们加载数据集,正如我所说,Spher 10 数据集已经在 Pytorach 中可用,所以我们可以使用它来自 Pytorch 的数据模块。然后,我们定义我们的 Pytorch 数据集和数据加载器,这样我们可以自动进行批量优化和批量训练。接着我在这里定义了类,并进行了硬编码。

然后我们需要实现卷积网络。和往常一样,我们通常创建我们的模型、损失和优化器。在这种情况下,由于这是一个多类别分类问题,我们使用交叉熵损失,然后作为优化器使用随机梯度下降。

需要优化模型参数,它获取定义的学习率,然后我们有典型的训练循环,进行批量优化,我们循环遍历 epoch 数,并循环遍历训练加载器,以获取所有不同的批次。

然后我们再次需要将图像和标签推送到设备上以获得 GPU 支持。接着我们进行典型的前向传播并创建损失。然后进行反向传播,我们必须记得先调用 zero_grad 来清空梯度。然后我们调用 backward 函数并优化一步,最后打印一些信息。

完成后,我们评估模型。和往常一样,我们将其包裹在一个 with torch.no_grad 的语句中,因为这里不需要反向传播和梯度计算。然后我们计算准确率,所以我们计算整个网络的准确率,并为每个单独的类别计算准确率。

是的,这就是脚本。你也可以在我的 GitHub 上找到这个内容,所以请去那里查看。现在唯一缺少的就是实现卷积网络。为此,我们定义一个类 confnet,它必须继承自 nn.Module。和往常一样,我们需要定义或实现 init 函数和前向传播的 forward 函数。

现在让我们在这里写一些代码。

因此,我们再次查看架构。在这里,首先,我们有一个卷积层,然后是一个ReLU激活函数。接着应用最大池化。然后我们有第二个卷积层,带有ReLU函数和最大池化。接下来我们有三个不同的全连接层。在最后。

我们有softms和交叉熵。因此softm已经包含在这里的交叉熵损失中。所以我们不需要关注这个。那么,让我们设置或创建所有这些层。假设self.dot con1等于,通过说n和dot conf获取第一个卷积层。

现在我们需要指定大小。输入通道大小现在是3,因为我们的图像有三个颜色通道。这就是为什么输入通道大小是3。然后假设输出通道大小是6,卷积核大小是5,即5乘5。现在让我们定义一个池化层,self pool等于N N.dot max pool 2 D,卷积核大小为2,步幅为2。

这正是我们看到的图像中那样。我们的卷积核大小是2乘2。每次操作后,我们将像素向右移动两个单位。这就是为什么步幅是2。

然后让我们定义第二个卷积层。self con2等于。现在输入通道大小必须等于最后的输出通道大小。因此这里我们说6。作为输出,假设是16,卷积核大小仍然是5。现在我们有了卷积层。接下来让我们通过说self.dot F1等于和N N.dot linear来设置全连接层。

现在作为输入大小。我先为你写这个。这是16乘5乘5。作为输出大小,我会简单地说100。所以你可以尝试不同的值。我会解释为什么这是16乘5乘5。然后让我们设置下一个全连接层,这里有120个输入特征。

假设有84个输出特征。然后我们使用最终的全连接层。我们有F1、F2和F3。这是输入大小为84,输出大小必须为10,因为我们有10个不同的类别。因此你可以改变这里的120和84,但这必须固定,10也必须固定。

现在让我们看看为什么这个数字必须是这个数字。这里我有一个小脚本,它做的正是相同的事情。哦,让我改变epoch的数量。哦,是的,这是4。所以在开始时,我有相同的内容。我加载数据集,嗯。

打印或绘制一些图像。这里我有相同的层。我有第一个卷积层和池化层,还有第二个卷积层。首先,让我们运行这个并绘制图像。我们可以说Python,CNN test dot pi。然后,我已经下载好了。所以它会打印。是的,虽然非常模糊,但我想你可以看到这个。

这是一匹马,也许是一只鸟,还有另一匹马。是的,我其实不认识这个。让我们再运行一下,看看是否能看到更好的图片。所以,是的,仍然非常模糊。我认为这是一只鹿、一辆车、一艘船。所以,好的。让我们看看尺寸的样子。首先,我们只打印形状的图像。所以这是4乘3乘32乘32。

这是因为我们的批处理大小是4。然后我们有三种不同的颜色通道。我们的图像尺寸为32乘32。现在让我们应用第一个卷积层。我们说x等于cont1,这将获取图像。现在让我们打印这个操作后的下一个大小。抱歉,我不想要。

再也不需要了。现在我们有下一个大小,所以这是4乘6乘28乘28,因此是6。现在我们有六个输出通道,如此处指定,图像大小是28乘28,因为正如我所说,生成的图像可能会更小,因为我们的滤波器无法适应角落,计算输出大小的公式是输入宽度减去滤波器大小加上2倍的填充。

在这种情况下我们没有填充,然后除以步幅再加1。所以在这个例子中,我们的输入大小是5乘5,滤波器大小是3乘3,填充是0,步幅是1。因此输出大小是5减去3加1。所以是2,然后除以。

1仍然是2,然后加上1。这就是为什么我们的输出图像是3乘3。现在我们必须在我们的情况下应用相同的公式。所以我们有32减去滤波器大小,减去5。因此是27。加0,仍然是27,除以1,仍然是27,然后加1。所以这就是为什么是28。

所以这里我们有28乘28。接下来我们应用下一层。下一个操作是池化层。我们保存这个并运行它。现在我们的尺寸是4乘6乘14乘14。这是因为,如示例所示,我们的池化层的核大小为2乘2,步幅为2,将图像减少了2倍。

所以是的,现在让我们应用第二个卷积层。让我们打印这个操作后的大小。首先清除这个。然后运行这个。接着,我们需要应用我刚才展示的公式来减小尺寸。因此这里PyTorch可以为我们计算出来。尺寸是4乘16,这就是下一个通道的输出大小。

我们指定的大小是16,结果图像是10乘10。然后我们应用另一个池化操作,这将再次将大小减少一半。因此,这就是我们现在看到的,在两个卷积层和池化层之后的最终大小是4乘16乘5乘5。所以。如果我们再看看。那么在此之后。

这些卷积层。现在,当我们将它们放入分类层时,我们想要展平大小,因此我们希望将我们的3D张量展平为1D张量。

现在,如果我们看看现在的大小,第一层线性层的输入大小正是我们这里的16乘5乘5。这一点非常重要,以确保这里的大小正确。但现在我们知道为什么这必须是16乘5乘5。现在我们有了正确的大小。

现在我们已经定义了所有层,现在必须在前向传播中应用它们。所以我们说x等于。现在让我们应用第一个卷积层,获取x。然后在此之后,我们应用一个激活函数。我们可以通过调用F来做到这一点。所以我导入了Torch和功能SF。然后我可以调用F.dot.relu,并将其作为参数传入。

然后在激活函数之后。顺便说一下,激活函数不会改变大小。所以现在我们应用第一个池化层,所以self.dot pool并包裹在这里。这是第一个卷积和池化层。然后我们对第二个卷积层做同样的事情。现在我们必须将其传递给第一个全连接层。为此,我们必须将其展平。因此我们可以通过说x等于x.dot.view来做到这一点。第一个大小,我们可以简单地说1。这样Pytorch就可以自动为我们定义正确的大小。这是批次的数量。

我们这里批次中的样本数量。所以在这种情况下是四个。然后这里我们必须说16乘5乘5。现在我们有我们的张量。现在让我们通过说x等于self.dot F1来调用第一个全连接层。这将获取X。然后我们再次应用激活函数,我们简单地使用relu。

我还有一个关于激活函数的完整教程。如果你还没看过,请查看。现在在此之后,我们应用第二个。所以x等于这个,第二个全连接层带有激活函数。最后,我们简单地有x等于self.dot最后一个全连接层F C 3和X。

最后没有激活函数,也没有这里的softmax激活函数,因为这已经包含在我们设置的损失中。所以我们可以简单地返回X。这就是整个卷积网络模型。现在你应该知道我们如何设置这个。嗯,然后我们在这里创建模型,然后继续进行。

这是我已经向你展示过的训练循环。所以现在让我们保存这个,运行它。清除这个,输入Python,C和N点P,希望这能启动训练。所以。哦,对了,我忘了一件事,当然,要调用super的初始化。所以永远不要忘记调用super。这需要获取con和self,然后。点下划线初始化。

所以让我们再清除一次,再试一次。现在,这应该会启动训练。我在我的MacBook上没有GPU支持,所以这可能需要几分钟。所以我想我会跳过这个,等训练完成后继续。所以我们一会儿见。好,现在我们回来了。我们的训练已经完成,如果我们看看。

我们可以看到损失值缓慢下降,然后我们有了最终评估。因此,总网络的准确率为46.6%,每个类别的准确率在这里列出。所以效果不是很好。这是因为我们这里只指定了训练的轮数。因此,你可能想尝试更多的轮数,不过是这样的。

现在你应该知道如何实现卷积神经网络。我希望你喜欢这个教程。如果你喜欢这个,请点赞并订阅频道,我们下次再见。😊!

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P15:L15- 迁移学习 - ShowMeAI - BV12m4y1S7ix

嗨,大家好。欢迎来到你的新 PyTorch 教程。在这个教程中,我们将讨论迁移学习以及如何在 PyTorch 中应用它。迁移学习是一种机器学习方法,其中为第一个任务开发的模型被重新用于第二个任务的起始点。例如,我们可以训练一个模型来分类鸟类和猫,然后使用同样的模型。

仅在最后一层稍作修改,然后使用新模型来分类蜜蜂和狗。这是深度学习中一种流行的方法,能够快速生成新模型。这非常重要,因为训练一个全新的模型可能会非常耗时,可能需要几天甚至几周的时间。因此,如果你使用一个预训练的模型。

然后我们通常只交换最后一层,而无需重新训练整个模型。然而,迁移学习能够取得相当不错的性能结果,这就是它如今如此受欢迎的原因。😊所以让我们看看这里的这张图片。我们有一个典型的 CNN 架构,我在上一个教程中已经向你展示过。

比如说,这个模型已经在大量数据上进行了训练,并且我们有优化的权重,现在我们只想保留最后一层的全连接层。所以就是这一层,然后修改它,并在我们的新数据上训练最后一层。这样我们就有了一个在最后一层经过训练和调整的新模型。是的,这就是迁移学习的概念。现在让我们在 PyTorch 中看看一个具体的例子。

在这个例子中,我们想使用预训练的 Resnet 18 CNN。这是一个在超过一百万张来自 Inet 数据库的图像上训练的网络。这个网络有 18 层深,可以将图像分类为 1000 个对象类别。而在我们的例子中,我们只有两个类别,所以我们只想检测蜜蜂和蚂蚁。😊

是的,让我们开始吧。在这一节中,我还想给你展示两个其他的新东西。首先是数据集的图像文件夹,我们如何使用它,以及如何使用调度程序来改变学习率。然后,当然,迁移学习是如何被使用的。我已经导入了我们需要的内容。

现在我们设置数据。上次我们使用了 Torch 视觉数据集中的内置数据集,而现在这里我们使用数据集的图像文件夹,因为我们把数据保存在一个文件夹中,并且这个文件夹需要具有这样的结构。我们在这里有一个文件夹,然后有一个训练文件夹和一个验证文件夹。所以是 train 和 Val。在每个文件夹中,我们都有每个类别的文件夹。这里我们有蚂蚁和蜜蜂。

在验证文件夹中,我们有蚂蚁和蜜蜂。现在在每个文件夹中,我们有这里的图像。所以,例如,这里我们有一些蚂蚁。还有,让我们看看一些蜜蜂。所以这里我们有一只蜜蜂。是的,所以你必须这样组织你的文件夹。然后你可以调用数据集.dot image folder并给出路径。

我们还在这里提供了一些变换。然后,我们通过调用image sets,image data sets.dot classes来获取类名。是的,然后在这里我定义了训练模型,在循环中进行了训练和评估。我在这里不会详细说明,你应该已经从上次的教程中知道典型的训练和评估循环是怎样的,你也可以在GitHub上查看完整代码。

所以我将在描述中提供链接。请自行查看。现在让我们使用迁移学习。首先,我们想导入预训练模型。让我们设置这个模型,这样我们就可以通过说model来做到这一点。所以model等于。这在Torch visionion.dot models模块中可用。

所以我已经导入了torch vision模型。然后我可以调用models.dot Resnet 16或抱歉,Resnet 18。在这里,我可以说pretrained等于true。这已经是针对imagenet数据训练的优化权重。现在我们想做的是交换最后的全连接层。首先。

让我们获取最后一层的输入特征数量。所以我们可以说nu features等于model。我们可以通过调用dot F fully connected来获取这个。然后是输入特征。这是我们需要的最后一层的输入特征数量。然后让我们创建一个新层并将其分配给最后一层。所以我们可以说model.Dot F C等于。

现在我们给它一个新的全连接层N N.dot linear。这获取我们拥有的输入特征的数量。然后作为新的输出特征,我们有两个输出,因为现在有两个类。现在我们将模型发送到设备。如果我们有GP支持。

所以我们在开始时创建了我们的设备,和往常一样。这是Kuda或简单的CPU。现在我们有了新模型,我们可以再次像往常一样定义我们的损失和优化器。所以我们说criterion等于N,N.dot cross entropis。然后我们可以说optr等于。这来自优化模块,Opim.dot S GD,随机梯度下降。

需要优化模型参数。我们必须指定学习率等于。让我们说0001。现在,作为一件新事物,让我们使用scheduleula。这将更新学习率。所以。为此,我们可以通过说它叫做step L R scheduleular来创建这个。并且L R scheduletula在torch优化模块中也可用。

所以我们已经导入了这一点。然后我们可以说学习率调度器执行学习率的步骤。然后在这里我们必须提供优化器。所以我们说优化器。然后我们说步长,步长等于7。然后我们说伽玛,假设为0.1。这意味着每7个轮次,我们的学习率乘以这个值。因此每7个轮次。

我们的学习率现在只有10,仅更新到10%。所以,这就是我们使用调度器的方式。通常我们想在我们的循环中,在每个轮次中进行。假设对于范围内的轮次为100。在这里我们通常使用训练,同时我们还要执行优化器的步骤。

优化器执行步骤。然后我们想要评估它,评估它。接着我们还必须调用调度器的步骤。这样我们就使用了调度器。请自己查看整个循环。因此,现在我们设置调度器,让我们调用训练函数。

所以我们说模型等于,然后训练模型。这是我创建的函数。然后我必须传递模型、标准、优化器、调度器以及训练轮数。假设训练轮数为20。那么,这就是我们如何使用迁移学习。在这种情况下。

我们使用一种叫做微调的技术。因为在这里,我们再次训练整个模型,但只是稍微调整。因此我们根据新数据微调所有权重,并使用新的最后一层。这是一个选项。第二个选项是,我复制粘贴相同的内容。让我们看看从哪里开始。

作为第二个选项,我们可以在一开始冻结所有层,仅训练最后一层。为此,我们在获得模型后必须遍历所有参数。所以我们说对于模型的参数,设置其要求梯度属性为假,所以我们可以说参数。

需要梯度。然后说,抱歉,需要梯度,要求梯度等于假。现在我们有了,这将在一开始冻结所有层。现在我们设置新的最后一层。我们在这里创建一个新层,默认情况下,这个层的要求梯度等于真。然后再次设置损失、优化器和调度器。

然后我们再次执行训练函数。所以,是的,这样甚至更快。让我们运行这个,然后查看两个评估结果。我还会打印出所花费的时间。所以,好的,让我们保存这个,并通过说Python transfer.py来运行。这可能最初会。

它将下载所有图像,这可能需要几秒钟,因为我在我的MacBook上没有GPU支持。所以我会跳过这一点,稍后再见。好的,我回来了。这在我的电脑上花了超级长的时间,所以我在这个例子中将训练轮数重置为2。让我们看看结果。在仅仅两个训练轮次之后。

这是第一次训练,我们对整个模型进行了微调。这个过程花了三分半钟,目前最佳准确率是92%。这是第二次训练,我们仅训练了最后一层,大约只花了一分半钟。

是的,准确率已经超过80%。当然,这还不如我们训练整个模型时的效果,但对于仅仅两个周期来说,已经相当不错了。现在我们假设将周期数设得更高。所以,这就是迁移学习如此强大的原因,因为我们有一个预训练的模型。

然后我们只需稍微调整一下,完成一个全新的任务,也能取得相当不错的结果。所以,现在我希望你理解了如何在Pythtorch中应用迁移学习。如果你喜欢这个教程,请订阅频道,我们下次再见。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P16:L16- 如何使用 TensorBoard - ShowMeAI - BV12m4y1S7ix

嗨,大家好,欢迎来到新的 PyTorch 教程。在这个视频中,我们将学习如何使用 TensorBoard 来可视化和分析我们的模型和训练管道。TensorBoard 是一个可视化工具包,用于实验我们的模型。它实际上是由 TensorFlow 的团队开发的,但同样可以与 PyTorch 一起使用。

在官方网站上,我们可以做几件事情。我们可以看到一些可以在 TensorBoard 中执行的操作。例如,我们可以跟踪和可视化指标,比如损失和准确率。我们可以可视化我们的模型图,查看直方图。

我们可以将嵌入投影到较低维空间,并可以显示图像、文本和音频数据,还可以分析我们的程序等等。😊所以现在我想向你展示我们如何在代码中使用这个。我将使用第 13 个教程中的代码。

好的,这里是代码。这是来自第 13 个教程的确切代码。如果你还没看过这个,我建议你先观看这个。因此,我现在将简要再次解释代码。在这个教程中,我们使用了 MNIST 数据集。因此,我们在这里进行了数字分类。现在我们正在加载 MNIST 数据集。

然后我们绘制了一些图像。接着我们创建了一个简单的前馈神经网络。这是一个具有一个隐藏层的全连接神经网络。我们看到,首先有一个线性层,然后是一个 ReLU 激活函数,再然后是另一个线性层。这就是我们的整个前向传播。

然后我们设置我们的训练管道。所以我们有我们的损失和优化器。接着我们进行训练。和往常一样,我们进行前向传播、反向传播,然后更新权重。最后,我们评估我们的模型并绘制准确率。因此,现在让我们使用 TensorBoard 对这段代码进行分析,以进一步分析我们的模型。

首先,我们要做的第一件事是安装 TensorBoard。为此,我们可以使用 pip install tensorboard。这将安装我们所需的所有内容。在我的情况下,我已经安装好了,所以这个过程很快。而且我们不需要安装整个 TensorFlow 库,在这里仅安装 TensorBoard 就足够了。现在我们可以通过输入 tensorboard 来启动 TensorBoard。

接着我们需要指定保存日志文件的路径,我们通过给定参数 --logdir= 来实现。默认情况下,这个路径在 runs 目录中。让我们按回车键。然后它将在本地主机 6006 启动 TensorBoard。

然后我们会收到一个警告,提示找不到 TensorFlow,并且将以减少功能集的方式运行。但这没关系。现在我们打开 TensorBoard。

现在我们来到了张量部分。此刻,我们看到没有活动的破折号端口。这是因为我们还没有写入任何数据。那我们来做一下吧。

让我们再跳回代码。现在我们想做的第一件事是导入Tensor板。所以,对于这个,我们说从torch的us中导入Tensor板。我们导入的叫做summary rider。这里我有一个拼写错误。现在让我们创建一个写入器。假设写入器等于summary rider。然后给它一个目录。

它应该保存日志文件,默认目录是,我说过的,运行文件夹。但让我们在这里更具体一点。我们叫这个运行,然后M N。现在我们已经设置好写入器。接下来我们想做的第一件事是在这里。在代码中,我们绘制了一些图像。现在,取而代之的是绘图。

让我们将图像添加到我们的张量板。为此,我们只需要创建一个网格。然后调用图像方法的写入器。那我们来做一下吧。假设我们的图像网格等于。我们也从torch vision中获取这个。Dot make,创建网格。然后给它数据。这里我们有一批示例数据。

让我们把这个放在这里。然后调用写入器的图像方法。这里我们给图像网格,并且一开始我们还需要提供这个图像的标签。比如我们叫这个,M Nist图像。现在。嗯。我想在这里退出,所以我使用。我导入cis或系统。然后我在这里使用提前退出,因为我现在不想运行整个训练管道。

在这里我调用cis.exit。我想确保所有事件都在这里写入。所以这就是我也调用写入器.close的原因。这确保所有输出都在这里被刷新。现在让我们保存这个。然后去终端,运行这个。假设我们说Python,然后我们的文件是feet forward.P,按回车。

现在让我们再次进入Tensor板并重新加载它。然后我们看到这里有我们的图像。

这里是我们刚创建的网格。这是60。这是8乘8,因为我们指定我们的批量大小为64。

嗯,所以现在我们可以分析我们的数据。

让我们继续在我们的Tzor板上做更多事情。接下来我们想做的是添加一个图。用于分析我们的模型。如果我们向下滚动,我们看到这里创建了我们的神经网络。让我们对此进行注释,然后在这里创建我们的模型。

然后在这里是我们的损失和优化器。现在在这里,让我们添加我们的模型图。我们可以通过说rider.at_graph()来实现这一点。然后在这里我们传递模型。我们还可以给它一个输入,所以我们可以再次说,我们有我们的示例数据。这是一个批次。然后我们必须以与这里相同的方式重新调整。

所以,让我们重新调整我们的批量数据。然后,再次调用Rer.close()writer.exit()。然后系统退出。再一次,让我们运行我们的文件。

现在让我们再次去TensorBoard。让我们重新加载它。然后我们在这里看到上方也有图表选项卡。所以让我们去图表。在这里我们看到我们的模型。我们有输入,然后是神经网络。现在如果我们双击,就可以看到更多细节。这里我们看到我们的整个模型。

所以现在我们看到我们有第一个线性层。然后是ReLU激活函数。接着是第二个线性层。我们还可以看到每个线性层的权重和偏差。因此,是的,如果我们想,我们可以进一步检查。这确实有助于分析我们模型的结构。

所以,是的,现在我们有了我们的模型。现在让我们分析一些指标。我们在原始脚本中所做的是,在训练期间,我们每100步打印一次。我们打印当前的损失。现在,不只是打印这个。让我们把它添加到我们的TensorBoard中。因此,让我们添加训练损失和准确率。

对于这个,我们希望在这一批训练中得到平均损失。所以在开始循环之前,让我们在这里添加两个值。第一个是我们的运行损失。这一开始是0。然后我们还要说,运行的正确预测在一开始也是0。现在,每100步,我们……

抱歉,之前在每次迭代中。现在,我们将损失添加到运行损失中。所以我们说running_loss += loss.item()。我们还将正确预测的数量添加到运行的正确值中。因此,对于这个,我们想要得到预测。我们可以通过调用torch.max以与我们在下面所做的方式相同来做到这一点。所以,让我们在这里也这样做。我们得到预测值。

然后我们说running_correct +=。在这里我们说predicted == actual_labels,然后是求和。这是一个仅包含一个项目的张量。因此,我们可以调用.item()。现在,是的,我们在这里将其添加到运行损失中。现在每100步,我们想要计算平均值并将其添加到TensorBoard中。所以我们调用rider.at_scala()

现在我们必须添加标签。所以在这里,让我们给它标签为训练损失。现在实际损失是运行损失除以100,因为我们为100步进行了求和。然后我们还必须给它当前的全局步骤。通过说epoch和提取的总步骤数来表示这一点。

这就是训练加载器的长度。再加上I,而I是当前批次迭代。所以这是当前的全局步骤。这里我们添加训练损失。现在让我们再做一次,添加准确性。我们说准确性。然后这里我们要说,运行。正确。除以100。然后在那之后。

我们必须将运行损失和运行预测正确的值重新设为0。所以我们说运行损失等于0.0和运行损失。不,抱歉。运行正确再次等于0。然后,是的,现在我们必须保存这个。现在我们必须运行整个训练管道。让我们再次注释掉系统退出。现在,让我们运行我们的脚本。

我们仍然应该看到这里的打印输出。因此,对于每100步,我们看到损失是如何减少的。现在我们应该完成了。现在我们也看到我们网络的整体准确性。现在让我们再次回到我们的TensorBoard,点击重新加载。

然后我们在这里还有一个条目。这是学者条目。这里我们有我们的两个图表。所以,是的,我们看到它成功了。我们看到了准确性。

对于每个步骤。我们也看到训练损失在减少。是的,所以在这里默认情况下,TensorFlow和TensorBoard会平滑这条线,因此我们可以在这里修改平滑参数。但现在我们可以分析损失是如何减少的。例如,如果我们看到在某一点上,损失没有进一步减少,我们可以看到这一点。

我们必须改进一些东西。例如,我们可以尝试不同的学习率。当然,这通常是我们想要优化的第一件事。那么,让我们修改学习率。现在,让我们称这个文件夹为mist,简单地说是simply2。

然后再次,让我们清理这个并再次运行我们的脚本。并且!

然后这应该已经在文件运行期间更新了我们的音调板。所以现在我们看到第二个图表。而且在损失图表中我们也看到第二个图表。现在,让我们再次重新加载这个。现在,是的,应该完成了。举例来说,这里我们又看到一个不同学习率的图表。

这就是我们如何互动地优化和分析我们的模型。现在,最后一件事,我想向你展示的是我们如何添加精确度召回曲线。精确度召回曲线让你理解模型在不同阈值设置下的表现。在二分类问题中,这更有意义。

但是如果我们分别分析每个类别。那我们确实有一个二元分类问题。因此让我们在这里为每个类别添加精确率-召回曲线。如果你不知道精确率和召回率的含义,我在描述中有一个链接。请查看一下。

现在我们想要做的是。让我们看看官方文档。我也建议你查看这个链接。让我们搜索一下PR。然后我们看到这里有方法at precision at PR曲线。这将添加精确率-召回曲线。这需要首先攻击。

然后需要标签。在这里我们看到标签是实际数据。每个元素的二元标签。

然后需要进行预测,预测是元素被分类为真的概率,值应在0到1之间。因此,这一点非常重要。我们需要实际标签以及这里的预测。好的,现在我们来看看代码,并为每个类别绘制精确率-召回曲线。

在我们的评估中,我们希望创建一个存储标签的列表。所以我们设置labels等于一个空列表。同样也需要一个预测的列表。所以pres等于一个空列表。在批评估期间,我们所做的是。对于标签,我们可以说标签停止追加,实际标签是预测标签。

现在对于。😊。

对于预测,我们必须小心。因此在这里,我们需要的概率在0到1之间。现在我们从模型中获得输出。如果我们再次查看神经网络,我们会发现最后有一层线性层。这些是原始值。这里甚至有一个评论。所以没有激活和没有softmax在最后。

因为在这种情况下,这应用于我们的损失函数中的交叉熵损失。但现在,再次,在评估中,我们想要获取实际概率。如果你看过我关于激活函数的教程,你就知道在这里必须使用哪种激活函数来获得概率。

这就是softmax函数。所以它将我们的值压缩为0到1之间的概率。所以我们在这里明确调用softmax用于我们的输出。为此,让我们导入F。也就是功能性。我们这里设置。😊,让我们导入torch.dot N,N.dot.functional,SF。大写F。然后,在这里,我们希望计算每个输出的softmax。

所以我们使用列表推导来实现这个。我们将其命名为类别。🤢,嗯。预测等于。现在我们在这里使用列表推导并调用F点softmax。然后我们说输出。接着我们需要给出维度。所以我们设置维度等于沿维度0。然后我们希望对每个输出执行此操作。

然后我们将这个添加到我们的,我们称之为 prettz 的对象中。prets dot,一支笔。然后在这里是类别预测。当我们完成循环时,我们想要将其转换为 a1zo。在这里我们说 labels 等于。然后 torch dot cut 这些标签。现在这是一个列表。当我们想要在一个维度上连接列表中的所有元素时。

转换为一维张量。对于预测,我们希望有一个二维张量。对于每个类别,我们想要堆叠预测。然后我们想要连接它。所以我们说。Prats 等于。然后在这里我们说 torch dot cat。接着我们再次使用列表推导,说 torch dot stack。

在这里,我们堆叠每个批次,并在预测中说四个批次。所以你应该自己检查这些张量的形状。我认为有多少。我们有,我想是10000个样本。所以这是10000乘以1,这应该是10000乘以10。对于每个类别,我们在这里堆叠它。现在当我们完成时。

所以现在我们必须做的最后一件事是得到实际的 PR 曲线。对于这个,我们说 classes。所以在这种情况下,我们的类别标签只是范围10,因为我们有从0到9的数值。现在我们迭代这个。所以4 I 在 classes 中。然后我们说我们得到的 labels I 等于。这里的 labels 等于 I。然后预测的同样操作,预测 I 等于预测。

在这里我们想要获取所有样本。但仅针对类别 I。然后我们调用 writer dot at。这称为 PR 曲线。这个需要一个标签。对于标签,我们仅使用类别标签作为字符串。然后在这里我们有。首先是标签,然后是预测。所以预测 I,然后作为全局步骤,我们就用0。

然后我们调用 writer dot close。这样我们就完成了。现在保存这个并再次运行我们的脚本。完成后,我们应该能看到每个类别标签的精确召回曲线。所以,差不多完成了。还有一支笔。我这里有个拼写错误。我有两个不同的标签变量。我们就叫这个。嗯。

我们在这里就叫这个 labels 1。这样 labels1 和 labels 1 以及 labels1。现在,我们再运行一次。抱歉。我们先清理一下,再运行一次。现在,我们又得经过训练管道。哦,我没保存。

好的,现在我们完成了。让我们再重新加载一次 tensor board。现在我们这里有一个新的条目。这是 PR 曲线。现在我们应该看到每个类别标签的精确召回曲线。在这里我们有标签0、标签1等。然后我们可以检查不同阈值下的精确度和召回率。

所以在y轴上,我们有精确度,在x轴上,我们有召回率。然后,例如,对于不同的阈值,我们可以分析一下,看看有多少个真正阳性,有多少个假阳性,有多少个真正阴性和假阴性。因此,这对分析模型也非常有帮助。没错。

这就是我想展示给你的关于Tensor板的所有内容。我希望你喜欢这个教程。请考虑订阅频道,下一次再见,拜拜。😊。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P17:L17- 保存和加载模型 - ShowMeAI - BV12m4y1S7ix

嘿,大家,欢迎来到新的Pytorch教程。今天我想展示如何保存和加载我们的模型。我会展示你必须知道的不同方法和保存选项,以及在使用GPU时需要考虑的事项。那么,我们开始吧。

这三种不同的方法你必须记住。所以我们有torch.dot.safe,接着是torch.dot.load和model.dot.load.state_dit。😊这些都是我们必须记住的方法,我会详细展示所有这些方法。torch.dot.Sa这里可以使用tensor模型或任何字典作为保存参数。所以你应该知道我们可以用它保存任何字典。

我会展示如何在训练管道中后续使用这些。😊所以torch doa然后利用Python的pickle模块来序列化对象并保存它们。结果是序列化的,不可读。而现在保存我们的模型,我们有两种选择。第一种是懒惰的方法。我们只需在模型上调用torch.do.save。

我们还必须指定路径或文件名。然后,当我们想加载模型时,只需设置模型,方法是model等于torch.do.load,再加上文件名。接着,我们还想将模型设置为评估模式,所以可以说model.do.evil。这是懒惰的方法,这种方法的缺点是序列化数据与模型保存时使用的特定类和确切目录结构绑定在一起。

还有第二个选项,这是推荐的保存模型方式。😊

如果我们只想保存我们的模型、训练好的模型,并在之后进行推理,那么只需保存参数即可。你应该记得,我们可以用torcha保存任何字典。所以我们可以通过调用torch.dot.save,然后model.dot.state_di来保存参数。因此,这里持有参数和路径,然后在之后使用。

当我们想再次加载模型时,首先必须创建模型对象,然后调用model.dot.load.state_dit。在这里,我们调用torch.dot.load路径。注意,load.state_di不仅接受路径,还接受加载的字典年。

我们将模型设置为评估模式。这是你应该记住的首选方式。现在让我们跳到代码中,看看实践中的不同保存方式。

在这里我有一个小脚本,其中我定义了一个小模型类,在这里我创建了我们的模型,现在让我先给你展示懒惰的方法。所以首先我们定义我们的文件名,所以我们说文件等于,让我们称之为模型do p,所以它是个好习惯使用结尾.dot p,缩写为pytorch。然后我们通过说torch.save来保存整个模型,然后是模型和文件。所以让我们保存这个并运行脚本。所以我们说Python save load do pi,现在如果我们打开浏览器,我们可以忽略这个警告,然后我们看到我们有模型do p。

在Exper。

如果我们打开这个,我们会看到这是一部分序列化数据,因此这是不可读的。现在如果我们回到我们的代码。我们加载我们的模型,所以我们可以注释掉这个。我们也可以注释掉这个。

然后我们可以通过说,模型等于来加载我们的模型。等于torch.load,然后是文件。然后记住,我们想要设置为评估模式。所以我们说模型.dot evil。然后我们可以使用我们的模型。例如,我们可以检查参数。所以我们假设对于Para在模型的参数中。

然后,让我们打印我们的Para。并保存这个。然后让我们清除这个并再次运行我们的脚本。

让我把这个放大给你看。所以现在如果我们再次运行我们的脚本,那么我们可以看到我们加载了模型并可以使用参数。所以这是懒惰选项。现在,让我给你展示做这件事的首选方式。所以不是仅仅说torch.save model,而是我们想要做的是说torch.save

然后我们想要保存状态字典。所以这里我们再次有我们的模型。然后我们说torch.model.

torch.save model.state dict。然后,让我们运行这个。所以,让我清除这个。然后打开资源管理器,删除这个文件。

现在如果我们再次运行脚本,那么我们又有文件。但现在它只保存状态字典。现在如果我们想要再次加载模型,我们首先必须定义它。

所以让我们称这个为加载的模型。加载的模型。等于。然后我们还说模型和输入特征的数量是相同的。所以是6。然后我们调用加载的模型.dot load state dict。在里面。记住,我们必须调用torch.load,然后是文件名。然后再次。

我们将加载的模型设置为评估模式。

然后如果我们运行这个,所以让我们打印加载模型的参数。再上面,让我们也打印一下我们正常模型的参数

所以如果我们在这里不进行任何训练,那么我们的模型仍然会初始化为一些随机参数。所以让我们运行脚本,检查参数是否相同。

所以在这里,我们看到它成功了。它首先打印了正常模型的参数,然后是加载模型的参数。所以这些是相同的。所以我们看到有一个包含权重的张量,还有一个包含偏置的张量,这对我们的两个模型都是一样的。所以我们看到这也成功了。所以是的,再次。

这是推荐的做法,通过调用safe dot model state dict。然后当我们加载它时,我们调用一个load state dict方法。

是的,所以在这里我们只是保存状态字典。所以这保存了参数。让我展示一下这个状态字典的样子。所以当我们有我们的模型时,让我们打印model.state。😊!

然后,让我们保存这个。接下来清除这个并运行脚本。然后我们看到这里有我们的状态字典。因此这里我们有线性权重,包含权重的张量。接下来我们还有一个张量。所以这就是我们的状态字典。现在让我给你展示一个在训练期间保存整个检查点的常见方法,正如你所知道的。

我们可以在这里保存任何字典。假设我们在这里也有一个优化器。假设我们定义一个学习率。设为0.0001。我们还有一个优化器。假设这是torch.optim,让我们使用随机梯度下降。在这里我们想优化模型参数。

我们还需要给它学习率,设置为learning rate = learning rate,我们的优化器也有一个状态字典。因此我们也可以打印优化器的状态字典。现在,如果我们清除这个并运行这个。那么我们看到优化器的状态字典,其中可以看到,例如,学习率和动量。因此现在在训练过程中。

假设我们想在训练过程中某个时刻暂停并保存一个检查点。那么我们可以这样做,所以下面是!

我们创建我们的检查点,这必须是一个字典。所以我们来创建一个字典。首先,我们想保存的内容是,比如说,纪元。所以我们来定义这个纪元。键叫做epoch。假设我们正处于第90个纪元。然后我们想保存模型状态。所以我们必须给它一个键。假设是model state。

在这里我们使用模型的状态字典。然后我们还想保存优化器状态字典。键,假设为optim state。然后这里的值,我们必须调用optr state字典。所以这是我们的检查点。现在我们可以调用torch dot save。

然后保存整个检查点。所以假设torch checkpoint作为文件名。我们称这个为check.Point dot P, T H。

现在再次,让我给你看看资源管理器,运行脚本。

现在我们清除这个并运行它。然后我们看到这里有我们的检查点。现在,当我们加载这个时,我们想加载整个检查点,所以。

我们可以注释掉这个。同时,我们也不需要这个,所以。

假设我们的加载检查点。假设,loaded checkpoint等于torch dot load。然后文件名与这个相同。

现在你必须重新设置不同的模型和优化器,以便我们可以立即获得纪元,方法是说epoch等于load at checkpoint。这是一个字典,所以我们可以直接。

调用。或者访问纪元键。然后对于模型。记住。我们必须在这里再次创建我们的模型。所以假设模型等于。然后模型的输入特征数量等于6,优化器与这个相同。实际上我们不必使用相同的学习率。

让我把这个复制过来,粘贴在这里。例如。我们可以使用学习率0。然后稍后,我们可以看到我们将正确的学习率加载到优化器中。所以。

现在,假设模型加载状态。然后这里我们给它检查点。然后我们访问键。我们称之为model state。所以这将加载所有参数到我们的模型中。优化器也是如此。我们称优化器为load state dis。然后使用检查点。

在这里我们称它为optim state。所以现在我们有了加载的模型和优化器,以及当前的纪元。所以我们可以继续训练。

让我通过打印优化器的 state_dict 来验证这一切是否正确。所以如果你注意到,我们将学习率设置为 0,然后加载了正确的 state_dict。现在如果我们运行这个。最后,我们打印了优化器的 state_dict,然后看到我们有与初始优化器相同的学习率。因此这有效。

这就是我们如何保存和加载整个检查点。是的,这三种保存方法你必须知道。最后,我想告诉你在使用 GPU 进行训练时需要考虑的事项。如果你在 CPU 上进行训练和加载,那么你不需要做任何区别。

所以你可以像我在这里做的那样使用它,但如果你在 GPU 上保存模型,然后稍后想在 CPU 上加载,那么你必须这样做。假设在你训练的某个时刻,你设置了 CUDA 设备并将模型发送到设备,然后通过使用 state_dict 保存它。

然后你想要加载到 CPU。所以你有你的 CPU 设备,然后重新创建模型,再调用 load_state_dict 和加载路径。在这里你必须指定映射位置,并给它 CPU 设备。如果你想在 GPU 上保存并在 CPU 上加载,就这样做。

现在,如果你想在 GPU 上同时进行这两项操作。你将模型发送到 CUDA 设备并保存,然后你也想在 GPU 上加载它,你只需这样做。设置你的模型,加载 state_dict,然后将模型发送到 CUDA 设备。

现在作为第三个选项。假设你在 CPU 上保存了模型,所以你没有将模型发送到 CUDA 设备上。但后来在加载时,你想将其加载到 GPU 上,你必须这样做。首先,你指定你的 CUDA 设备,然后创建你的模型。

然后你调用模型的 load_state_dict,接着用路径调用 torch.load,并指定映射位置。你需要指定 CUDA,然后是冒号,再加上你想要的任何 GPU 设备编号。例如,CUDA:0。然后你还需要调用模型到设备,所以指定到 CUDA 设备。这会将模型和所有加载的参数张量发送到设备上。这样你就可以继续在 GPU 上进行训练或推理。

当然,你还必须将所有训练样本发送到用于前向传播的设备上。

所以,是的,当你使用GPU时,这些是你需要考虑的事项。

现在,你了解了保存和加载模型的各种方法。 是的,这就是目前为止的所有内容。 希望你喜欢这个教程。如果你喜欢,请考虑订阅频道,下次见,再见。😊。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P18:L18- 创建和部署深度学习应用程序 - 使用 Flask 和 Heroku 部署 PyTorch 模型 - ShowMeAI - BV12m4y1S7ix

嗨,大家好,欢迎来到新的Pytorch教程。今天,我将向你展示如何使用flask和Heroku部署我们的Pytorch模型。我们将创建一个简单的flask应用,带有一个返回结果的REST API。然后我们将部署到Heroku。作为示例,我们的Pytorch应用应该进行数字分类。

最后,我将向你展示如何绘制自己的数字,然后用我们的实时应用进行预测。让我们开始吧。首先,让我们创建一个新的目录。我们称之为Pytorch flask 2。😊,然后让我们进入这个目录。接下来,我们要创建一个新的虚拟环境。所以我们输入python 3Minus M,V N V,N。这将创建一个新的虚拟环境。

顺便说一下,这个命令在Windows上可能稍有不同。所以你可以查看官方fl网站上的安装指南。我会把链接放在描述中。在这里,你可以找到所有这些指令。

现在我们有了虚拟环境,接下来我们要通过输入. vthin slash activate来激活它。同样,这在Windows上会有所不同。现在我们安装所需的东西。所以我们输入pip install flask

然后我们为Pytorch安装包。所以我们输入pip install torchtorch vision。现在,这将花费几秒钟。好的,现在我们有了这个。接下来我创建另一个目录,命名为app。然后我打开我的编辑器。在这里,我使用的是Visual Studio Code。并。

让我为你放大一点。现在我们看到有两个目录。一个是我们的虚拟环境,另一个是新的空应用目录。现在,在应用目录中,让我们创建一个名为main dot pi的文件。在这里我们将编写我们的flask应用。所以我们输入from flask import flask。然后我们创建一个新的,顺便说一句,是的,我说,是的。

我想在这里使用虚拟环境。😊,嗯。现在我创建一个应用,输入app equals flaskdouble underscore name。这只是我们惯用的做法。然后我们只想创建一个函数。即一个API端点。我们称之为predict,稍后在这里进行预测。现在。

我们还需要通过输入app dot route和URL的路径来装饰它。所以在这里我们输入slash predict。我们要说允许的方法,允许的方法只有POST方法。因此我们创建一个列表并输入post。😊,现在。这是我们需要的API路由。我们要做四件事。

所以我们想要加载一张图像。我们想从我们的请求中获取图像。然后我们想将图像转换为张量。接着我们想做出预测,然后返回数据。因此结果将作为数据返回。为此,我们还需要从 flask 导入 request。同时我们也导入 Chasonify。因此现在。

让我们做一个简单的返回语句并返回一个虚拟的数据。因此这里我们放入一个字典。作为键,我们说 results,然后作为值,我们使用 1。因此现在我们有这个,然后在这里打开终端,进入应用程序目录。为了启动 flask,我们必须设置两个环境变量。

所以我说 export flask app 赋值为文件名 main.dot.pi,export flask 赋值为 development。这将在开发过程中给我们热重载。顺便说一下,在 Windows 上,这不是 export。因此在这里你必须说 set,然后这一部分。现在我们可以说 flask run。这将启动我们的 flask 应用程序,运行在 local host port 5000 上。

现在我们有一个运行中的应用程序以及这个端点。现在让我们来测试一下。我们创建一个新目录,并称之为 test,然后在这里创建一个文件 test.dot.pie。😊为了这个,我们使用 requests 模块。因此我们说 import requests。我想我也得安装这个。

让我们通过使用控制 C 暂时退出服务器,然后说 Pip install requests。所以现在我们有这个。现在让我们再次重启我们的 flask 应用程序。在这里我们想要向这个 URL 发送一个 POST 请求。因此我们说 requests.dot.post。然后是 URL 路径。因此我们说 H T T P colon slash slash。

然后我们可以说 local host port 5000。这和我们在这里看到的是一样的。然后我们还需要说 /predict,就像我们在这里指定的 /predict。然后,我们想要发送什么。因此现在我们不想发送任何东西。所以,让我们说打印 response.dots.text。这将打印我们在这里返回的实际数据。因此现在。

如果我去到另一个终端。让我们进入测试文件夹并运行 Python test pi。我在这里有个拼写错误,local host 5000。我们再试一次。让我清空一下。现在让我们运行 Python test。然后我们看到这是有效的。因此我们得到了我们在这里指定的字典。因此我们的应用程序已经在运行。

现在让我们执行这四个步骤。为此,我们在相同的应用程序目录中创建另一个文件。我们创建一个文件,并称之为 torch.u.P。在这里我们做我们的。😊从 torch 库中导入。因此我们说 import torch。我们导入 torch.N,N,S 和 N。嗯。然后我们还说 import torch.vision.dot transforms as transform forms。

然后我们说 from pill import image。因此我们需要这个来将我们的图像转换为张量。在我们继续之前,先看一下我们将要使用的代码。对此,我在我的 Pytorch 初学者课程的 Pytorch 仓库中有这个,我也会将这个链接放在描述中。因此我们将使用第 13 个教程。

我们的基本前馈神经网络用于进行图像分类。让我在第二个编辑器中打开这个。

在这里,这是你可以在GitHub上找到并下载的完全相同的代码。所以现在基本上。我们想运行这个文件,然后保存模型。所以我们在最后这里要做的是说torch.save。然后我们想保存模型.state_dict。然后是文件名。所以在这里我们说,让我们称这个为Mist_underscore_FFN.pth。

然后我们还想做一件事。现在对于我们的数据集,我只使用了一个变换。所以transform.to_tensor。现在让我们在这里使用另一个变换。所以我说transform等于transform.compose,因为我们使用的不止一个。在这里作为一个列表。首先我们执行to_tensor变换。然后我们还想对其进行归一化。所以我说transform。

点归一化。然后在这里,我放入均值和标准差。这要作为一个元组传入。所以均值是点1,3,07,然后是一个逗号,因为这应该是一个元组。然后作为标准差,让我们复制并粘贴这个。在这里我们使用点30,8,1。这些都是来自MNES数据集的全局均值和标准差。

所以这里给出了这个。所以只需在这里放入相同的数字。现在我们使用这个变换。因此你不必这样做,但我只是想演示稍后在推理中,我们想应用相同的两个变换。现在我们使用这个,然后我们想运行代码并在最后保存它。在这里我使用的是conda环境。和我在中使用的相同。

初学者课程教程中的教程。所以我说Conda激活。3conda激活PyTorch。然后让我们使用Python。这个文件是编号13的前馈神经网络,然后运行它。这会花几秒钟。好了,现在完成了。你可以看到在我们的训练过程中,损失减少了。最后。

我们有了这个准确性。所以效果很好。同时在同一个文件夹中出现了这个文件。所以我们想复制这个文件,然后粘贴到这里的目录中。现在我们可以关闭这个,然后开始在这里实现管道。我们要做三件事。我们想加载我们的模型。我们想要一个函数将图像转换为一个张量,并且使用我们刚刚看到的相同变换。

然后我们想要一个函数来预测。所以。

现在,让我们回到。

嗯,原始代码。从这里开始,我们复制一些东西。所以我们复制这一部分。我们想要相同的模型类。

所以让我们把它粘贴到这里,我们需要这些参数,并去掉两个设备调用。所以目前,或者在这个教程中,我们只使用 CPU。现在我们需要输入大小、隐藏大小和类别数量。我们也从这里获取这些信息。所以我们有。

这些超参数。所以让我们把它们复制到这里。

然后,我们创建我们的模型。

然后我们想要加载状态数据。顺便提一下,你可以在我的 GitHub 仓库找到我们如何保存和加载模型的方法。这是第 17 个教程,我们可以抓取这一部分。这是推荐的方式,顺便说一下,当我们只保存状态数据时。然后我们从类中创建我们的模型。

我们加载状态数据,并且必须将其设置为评估模式。这一点非常重要。

我们还需要路径。所以路径等于。然后这是文件名。所以它在同一目录下。所以我们写 amest underscore FFN dot PH。顺便说一下,如果你在 GPU 上训练过,你必须小心。所以,你也会发现如何从 GPU 加载到 CPU。

所以你必须指定映射位置,这就是我们的 CPU 设备。

现在我们有这个。现在我们有了我们的模型。接下来我们要做的是定义一个函数来转换图像,这将接收原始字节作为输入。然后我们想要创建一个转换,写成 transform 等于。然后我们抓取和我们这里相同的东西。

所以我们希望与训练时相同的转换步骤,但我们还希望或需要这里有一些更多的内容。目前,这也可以作为 RGb 图像输入,但我们只想要它作为灰度图像,就像在加载这个 MNIST 数据集时一样,且它是灰度格式,正好是这个大小。所以每个图像都有。

28 x 28 像素。所以我们也必须使用这些相同的值。我们应用了两个更多的转换。我们写 transforms dot。然后我们可以使用灰度。接着我们可以说输出通道的数量等于 1,因为我们只想要一个输出通道。我们还想要调整大小。所以我们写 transforms dot resize。

然后作为一个元组,大小为 28 x 28。所以现在我们有这个。让我把它格式化得更漂亮一些。

所以现在这是我们的转换。然后我们想应用它。所以,首先,我们想从图像字节创建一个图像,使用 pillow 图像。我们可以说 image.dot open。然后 I O.dot bys,I O。然后是我们的图像字节。为此,我们需要导入,抱歉。导入 I O。以处理输入输出流。然后我们想应用我们的转换,然后可以返回它。

所以我们说返回,转换,然后是我们的图像。我们还说 unque。Unsqueze 0。这将返回一个新的张量,并在此位置插入一个维度。因为在抽取时,我们在一个轴上有批次数量。现在我们只有一张图像。所以我们必须添加这个轴,并且在我们的批次中只保留一个样本。

所以现在我们有这个。现在缺少一个方法。我们需要写一个函数来进行预测。所以我们说定义 get.Prediction。它将获取一个图像张量作为输入。现在我们也可以看一下。

在这里。

原始代码。然后在这里我们进行评估。在这里我们使用相同的代码。所以让我们复制并粘贴这个。

在这里。所以我们调整我们的图像大小,使其符合这个形状。然后我们可以去掉这部分,因为我们不使用 GPU 支持。然后我们执行前向传递。通过调用 torch.dot max 获取预测,然后我们可以返回预测的类别或预测的索引。

现在这个文件中我们需要的全部内容。这是我们推断的所有代码。现在我们可以返回到我们的主文件,然后导入这个。所以我们说从 torch us 导入。我们称之为 transform image 和 get prediction。现在在我们的预测方法中。我们想实现这个管道。在这里我们要非常小心,因为我们不想在这里出错。

否则我们的服务器会崩溃。所以我们做一些错误检查。首先,我们检查我们的请求.method 是否等于 post。只有这样我们才会执行代码。然后我们获取文件。稍后我们将文件传递给这个 post 请求。然后通过 saying file equals request.file.get 获取这个文件。

然后我们稍后会使用 key 文件。所以首先,我们检查文件。如果 file.is not 或者我们说如果 file 为 none 或者 file.dot file name 等于一个空字符串。然后我们返回 chason file。在这里我们返回一个字典,我们把一个错误作为键。作为值,我们说没有文件。这是我们检查的第一件事。

然后我们也检查这是否是允许的扩展名。所以,例如。我们只支持 P 和 G 以及 Jpe 文件。所以我们说如果不是允许的文件。然后在这里我们传递 file.dot file name。然后我们也返回一个错误。所以我们说返回 Chasoniffi。然后我们说格式不支持。

我们创建一个小助手函数。 假设我们定义一个允许的文件。 这将获取一个文件名。 然后我们的文件名可以是,例如。某个名字,然后点P和G,我们的结尾。现在我们想定义一些允许的扩展名。 所以我们说允许的扩展名等于。 这是一个仅包含唯一值的集合。

所以我们支持P和G JpeEC以及带E的Jpeg。 所以。😊,现在,我们返回。文件名中的点。 所以我们的文件名应该是这个格式。现在我们想检查结尾。 所以我们想拆分我们的文件。 所以我们说文件名点R拆分。 从右侧开始。我们想在点处拆分,并且最多只进行一次拆分。然后我们取第二部分。

所以这一部分。 这是索引1。 然后我们转换为小写。 然后检查这是否在我们的允许扩展名中。 现在,如果我们的文件名看起来例如这样,这将返回true。 所以现在在下面,我们可以继续。 现在我们想加载图像字节。

然后进行转换和我们的预测以及这一部分。 目前,我将其包装在try except块中。 这不是很好错误处理。 但目前应该没问题。 如果我们在这一部分有异常。 我们说错误。 假设在预测期间出错。

然后我们说我们的图像字节等于文件点读取。 然后我们说我们的tenor等于变换图像并放入图像字节。 然后我们得到预测。 预测等于获取预测与我们的tenor。 然后我们想将结果作为一个。Chasten文件返回。 所以我们说,我们的数据等于一个带有预测键的字典。

你将使用预测预测点项,因为我们不能在这里放一个tenor。 但我们的tenor只有一个元素。 所以我们通过说预测点项来获取。 在Mnes数据集的情况下,例如,这个索引为0。 然后这相当于我们绘制的数字0。 基本上。

我们还想返回实际的类名。 但在这种情况下,这个类名是相同的。 这里我们只是为了演示。 我们返回与字符串相同的内容。 所以字符串预测点。项。 举个例子,如果我们使用Cypher 10数据集。 那么我们必须做一个映射。 比如,索引0是汽车或船或者其他。

这就是你想放入这里的内容。 现在我们有了数据。 现在我们只需再次将其作为cha对象返回。 然后我们应该完成。 我认为这就是我们需要的一切。 现在让我们看看。 我们的服务器应该自动重新加载,因为我们将环境设置为开发。 现在让我们去我们的测试文件。

在这里我们想将文件放入我们的POST请求。 所以我们说文件等于。 记住,这是一个带有关键字文件的字典。 现在我们需要一个文件。 为此,我们去谷歌。 然后搜索Mnist。

图像。

现在我们去看图像,举个例子。它在哪里?让我们抓取这张图片。点击另存为,然后我会将其保存为7到我的桌面。接着我会快速复制到这个文件夹中。

现在我们看到这个图像在文件夹中。我们现在想在这里打开它。所以我们说打开,然后是文件名7 dot P和G。我们希望以读取二进制模式打开它。所以,现在我们有了这个。然后,我们再次去我们的测试文件,如果一切正常,我们应该得到结果为7。

现在让我们运行P test at pi,交叉手指。当然,它不工作。如果我们去看看这个终端,出现了语法错误无效的语法。让我们回去看看。我想我漏掉了一个逗号,所以我们保存它。

现在,我们的服务器崩溃了。所以我们要再次运行上一次。这正是我们希望在这个方法中非常小心并进行一些错误处理的原因。所以现在我们再测试一次。清除一下。抱歉,这是错误的。因此,我想说Python test dot pi。

然后我们在预测时遇到了错误。所以它仍然无法工作。所以现在,让我们注释掉这个尝试块,看看我们遇到了什么错误。现在你可以看到这不是最佳的错误处理,因为我们不知道出了什么问题。所以我们的服务器又启动了。假设我们再运行一次Python test of pi。

然后名字转换未定义。所以我在这里又犯了一个拼写错误,trans.Forms。对此我很抱歉。现在,让我们保存它,并再次运行。Tensor没有属性on squeeze。所以又是一个拼写错误。Unsque。再次运行,Python tester pi images image。

取消。现在,Pythhen test a pie。现在它终于可以工作了。所以现在我们看到我们的flaskg正在运行,我们的pytorch模型在做正确的事情。所以我可以再次添加我们的try except块。让我们在这一部分再做一次except块。😊。

现在我们可以删除这个。现在让我们用自己的图像进行测试。我在这里使用画笔,然后我指定一个宽度和高度为100像素的新图像。例如,我们想要小心,背景是黑色的。所以我填充背景为黑色。现在我使用白色铅笔,举个例子,画一个三,并保存它。

As3 dot P和G。然后让我把它复制到这里的文件夹里。现在我们用这个。所以我们使用3 dot P和G。让我们回去,清除一下,再次运行。预测结果是3。所以,是的,这很不错。现在我们有了这个,剩下的唯一事情就是部署它。为此,我们还需要做几件事情。

首先,我们需要使用一个适合生产的实际网络服务器。因此,我们使用Q unicorn。所以我说Pip安装Q unicorn。在我们的基础文件夹中,我们创建一个新文件,叫做W S G I dot pi,并将其移动到基础文件夹。在这里,我们说从app.dot main导入app。现在我们想从这个创建一个Heroku应用程序。所以当然。

你需要一个Heroku帐户和安装heroku命令行界面。如果你还没有,那么请访问官方网站,Heroku dot com。在那里你会找到说明。我已经做过这个。所以现在我得登录。所以我说heroku lock in minus I在终端中执行。

然后我必须输入我的凭据和密码。现在它说我已经登录,所以我可以再次清理。现在我们想通过输入heroku create来创建一个新应用程序。然后命名。所以我们叫它flask pieytorrch tutorial。😊这将创建一个新的Heroku应用程序。

为了测试这个,我们可以再次进入基础目录。我们需要做一件事,我们需要以和这里相同的方式更新我们的路径名称。因此,现在app是我们的基础包。所以这个文件夹。在主文件中,我们必须说从app dot torch us。在里面,我们必须修改我们的路径。

现在这是app dot Amnes F F N dot P, T, H。抱歉,这里是app。斜杠这个。现在我们可以通过输入heroku local来测试它。这将启动。我们首先需要有配置文件。让我们创建一个新的Proug文件,抱歉,抱歉。我想把这个放在顶层目录中。所以我们叫它proc file。

这就是我们需要的Heroku。在这里我们需要指定。我们想要一个Web应用程序。我们希望使用Q unicorn和我们的新W S G I文件作为起点以及我们的应用程序。所以这是语法。现在,我们可以通过输入heroku local来再次测试它。现在这个是工作的。因此,这会在同一个端口上启动我们的G unicorn服务器。现在我们的flask应用程序正在运行。

但我们的Heroku应用程序在本地运行。而且服务器没有变化,所以我们可以再次通过输入Python test pi来测试它。所以这仍然可以与我们新的正确路径名称一起工作。现在我们可以停止这个。

现在,我还想创建一个Runtime dot T X, T。在里面,我们指定我们的Python版本。所以现在是Python 3.8.3。然后,我们还要。让我们清理一下。我们还需要我们的需求。因为我们使用Pip,所以我们可以说Pip freeze,然后大于号,然后require U require dot T X, T。这将把我们安装的所有需求写入这个T X T文件中。

但我们需要修改一下,因为现在我们正在使用普通的 torch 和 torch vision。这占用了很多空间。这对于 Heroku 来说太大了。所以我们必须在这里使用仅 CPU 版本。为此,我们可以去官方的 Pytorch 网站查看安装指南。

在这里,我们使用 Pip 作为我们的包管理器,我们不想要 kuta 支持。对于我,我实际上使用这个命令。但在 Heroku 上,我们有 Linux。所以我们需要这个命令。我们需要在我们的 torch 和 torch vision 后添加 + CPU。所以我们在这里说 + CPU,这里也说 + CPU,我们还需要这个命令。

我们可以在要求文件的顶部写下它。所以在这里。现在这将只在 Heroku 上安装 CPU 版本。为了将此目录推送到 Heroku,我们需要一个 git 仓库。所以我们说 git init。然后我想添加一个 git 忽略文件。所以我创建一个新文件,Git ignore。为此,我们开始吧。

或者我们可以谷歌一下,搜索 Python git ignore。我认为这会引导我们到 git up。然后我们可以复制所有这些内容。

并将其放入我们的 git 忽略文件。在顶部,我还添加了测试文件夹。所以我想忽略这个文件夹。所以让我快速检查一下我在仓库中是否拥有我想要的所有内容。列表看起来不错。所以现在我们有了这一切。现在我们想将其添加为 Heroku 的远程仓库。所以我们说 heroku git:remote -a。然后是我们的应用名称。

所以我认为我们叫它 flask - pi。

Torch minus 教程。这将把它添加为远程 dpo。现在我们添加所有文件。所以我们说 git add . 然后 git commit -m。假设我们说初始提交,然后现在我们可以推送。所以我们说 git push Heroku master。这将所有内容推送到 Heroku,然后开始构建和部署应用程序。

现在这需要几秒钟。好的,这成功了。现在它已部署到这个 URL。所以在这个路径下,我们现在有我们的实时运行的 F。现在让我们回到 test.py。与其使用本地主机,不如使用这个 URL,然后加上 /predict。😊

然后我们回到测试文件。再运行一次 Python 测试。现在我们得到了结果。所以,是的,这有效。所以现在我们再做一个测试。再次使用我的绘画程序。作为背景,我们使用黑色。现在我们画一个,比如 a8,像这样。然后将其保存。😊

8 dot P,N G。然后我们把它移到这个文件夹里。这里我们用这个。8 dot P和G。再一次,保存它,清理一下,然后再运行。我们看到预测是8。所以这在工作。我们已经将一个实时运行的应用部署到heroku上。嗯。我希望你喜欢这个教程。如果你喜欢的话。

请订阅这个频道,给我点赞,下次再见,拜。😊。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P19:L19- 使用循环神经网络进行名称分类 - ShowMeAI - BV12m4y1S7ix

嗨,大家好,欢迎来到你们新的 Pytorch 教程。今天,我们将讨论循环神经网络,简称 RnNs。我将简要解释 RnNs 背后的理论和不同的应用,然后我们将在 Pytorch 中从头开始实现一个 RnN 来进行名称分类。

这应该能让你很好地理解 RnNs 的内部工作原理。那么,让我们开始吧。RnNs 是一种神经网络,它允许将之前的输出作为输入,同时拥有隐藏状态。这里有一张以最简单的方式展示 RnNs 架构的图像。我们有一个输入,然后在内部进行一些操作,得到隐藏状态。

然后我们将这些隐藏状态放回到下一步。😊 所以我们可以利用之前的知识更新我们的新状态。最后,我们也会得到一个输出。因此,我们也可以展开这个图,获得更好的理解,基本上我们在这里处理的是一个序列。例如,如果我们有一个完整的句子,我们可能会将每一个单词作为一个输入。

所以我们有第一个输入和一些初始隐藏状态。然后我们进行操作,得到输出和新的隐藏状态,再将这个隐藏状态放入下一个输入中。接着,我们获取下一个输入,利用之前的隐藏状态,再次进行操作,得到新的输出和更新后的隐藏状态。

然后我们继续获取下一个输入,如此反复。这基本上就是 RnN 的架构。那么 RnN 为什么如此重要呢?对此有一篇由 And Carpathy 撰写的精彩文章。文章名为《循环神经网络的不合理有效性》,我强烈建议大家阅读一下,因此我会将链接放在描述中。

但核心要点是 RnN 非常令人兴奋,因为它们允许我们在向量序列上进行操作。与传统神经网络仅具有一对一关系不同,例如,当我们进行图像分类时。😊 那时我们的输入,也就是我们的图像,是固定长度的,输出也是固定长度的。而现在通过 RnN,我们可以处理序列。

还有很多不同类型的关系。所以基本上,我们可以在输入中有一个序列,在输出中也有一个序列,或者在输入和输出中都有。例如,我们可以有一个对多的关系,其中只有一个输入,例如,这在图像描述中使用,当我们有一张图像时,然后想要描述我们在图像中看到的内容,并得到多个输出。

然后我们也可以有多对一的关系。例如,在情感分类中就是这种情况,或者我们稍后在名称分类中所做的。因此我们将序列作为输入,然后应用我们的 RnN,接着使用最后的输出进行分类。

然后我们也可以有多对多的关系。这是在机器翻译中使用的,例如,我们有一个完整的句子,假设是英语作为输入。然后我们输出一个完整的法语句子。例如,我们也可以以同步方式建立多对多的关系。

在视频分类中,我们想对每一帧进行分类。这些就是 R 和 RNN 的可能应用。因此,它们主要用于自然语言处理和语音识别领域,但它们也可以用于图像分类。因此,这就是 RNN 的强大之处。现在我们简单看一下它的一些优缺点。

优势在于我们可以处理任意长度的输入。然后我们的模型大小不会随着输入大小的增加而增加。计算考虑了历史信息。因此,先前的数据。我们的权重在时间上是共享的。一些缺点是,计算可能会比普通神经网络慢。

从很久以前获取信息可能会很困难。而且我们也无法考虑任何对当前状态的未来输入。所以,基本上这就是 R 和 RNN 的理论。现在我们可以直接跳到代码部分。在我们的示例中,我们想进行姓名分类。因此我下载了数据。

我也会把链接放在描述中。基本上,我们有不同文件,文件名也不同。这些都是来自不同国家的姓氏,例如:阿拉伯、中文、荷兰文、英文等等。我认为这些来自18个不同国家。现在我们要做的是分类并检测这个名字来自哪个国家,我们将在这里把整个名字作为一个序列,然后使用每个单独的字母,将其作为一个输入放入我们的 RNN 中。

为此,我们需要一些函数的帮助。我已经在这里实现了它们,我将简要介绍这段代码。我们在这里首先要做的是使用一个辅助函数将我们的数据转换为 ASCII。例如,如果我们有这个带有特殊字符的名字,然后我们处理它。让我们运行这个文件。

然后我们看到它去除了特殊字符,剩下的只有 ASCII 字符。基本上,我们还打印了所有可能的字母。这是从 a 到 c 以及大写字母。我们还允许这些符号。😊然后我们有一个辅助函数来加载数据。这基本上加载了所有这些文件,然后加载了所有的名字。

它从文件名中获取国家名。这就是 load data 函数的功能。然后我们有一些函数将数据转换为张量。所以我们有字母到索引、字母到张量和行到张量的转换。我们在这里使用了一种叫做独热编码的技术。

所以我们需要一种显示数据的方式,以便用于训练。为此,我们使用独热编码。如果你看过我关于Pyr中聊天机器人的教程,你可能已经知道了这一点。一个独热向量用零填充,除了在当前字母的索引处有一个1。例如。

如果我们只有五个可能的字符:A、B、C、D和E。那么我们的A将是长度为5的向量,在A所在的位置上有一个1,B也是同样,长度为5的向量,第二个索引为1,其余为0。这就是独热编码。所以如果我们回到我们的文件中,我可以给你展示load data函数的样子。

这将返回一个字典,其中国家是键,相应的名称是值。例如,如果我们运行这个并查看键Italian,只取前五个条目,那么我们看到这里有五个不同的意大利名字。然后,正如我所说的,我们做独热编码。为此,我们可以使用letter to tenor函数。所以现在如果我们运行这个。

现在让我们保存这个并运行,然后打印tenzoch。我们看到它的大小。这是形状为1x57,因为我们有57个可能的字符。这是我在这里打印的。这些都是字母,然后我们在大写J的位置有一个cha。所以这就是我们的输入稍后会是什么样子,当然。

我们不仅为单个字符做这个,而是为整个名称做这个。为此,我们有line to tensor函数。现在如果我们在这里打印大小。这将是5x1x57的大小。1是因为我们的模型希望它呈现这种形状,而5是字符的数量,57是所有不同字符的数量。

好的,这些是我们需要的所有帮助函数。当然,我会把代码放在Github上。我还提供数据的链接,以便你可以下载这些文件。现在我们可以开始编写我们的R和N。所以为此,当然,我们导入我们需要的东西。我们导入torch。我们导入torch.nn作为NN

然后我还想导入mapplotlibplot,因为我想稍后给你展示一个图。接着我们导入我们的实用函数。我说从us中导入所有不同的字母,以及不同字母的数量。所以这是57。然后我们还说从u中导入这些帮助函数。所以加载数据。

然后将字母转换为张量,行转换为张量以及随机训练示例。这基本上是一个函数,将从这些名称中随机选择,并返回相应的国家。所以现在我们有了这个,我们可以开始实现我们的R和N。我们需要有一个类,称为R和N。这应该从N继承。

N.dot module作为我们所有的Pytor模型。顺便说一句,Pytch中已经有一个R和N模块可用,所以你可以直接使用这个。但这是我们在下一个教程中要做的。所以现在我们想从头开始实现这个,以更好地理解。所以让我们再看看我们的模型架构。这就是我们的R和N用于名称分类的样子。

所以我们有一个输入和一个隐藏状态,然后在内部处理。这就是我们在内部所做的。我们将它们结合起来,然后处理我们的组合张量,并应用两个不同的隐藏层。因此,我们的输入连接到输出,我们的输入连接到一个隐藏层。

这些只是两个普通的线性层,然后我们得到一个隐藏输出,然后我们将其用于下一个输入,我们还得到一个输出,由于我们正在进行分类,因此这是一个多类分类任务,我们应用softmax层然后得到输出。

所以现在这是我们想要实现的。因此,首先,当然。我们定义我们的初始化函数。这将获得self。然后它获取输入大小。它还获取隐藏大小,这将是我们可以指定的超参数。我们还获取输出大小。在我们的初始化函数中,首先。

我们想调用super R和N以及self。然后初始化。😊,抱歉。初始化。然后在这里我们想存储我们的隐藏大小。所以我们说self.dot hidden size等于hidden size。然后我们定义我们两个不同的线性层。所以我们称之为输入到隐藏I到H等于NN.dot linear,大小是输入大小加上隐藏大小,因为我们将它们结合起来。对于这个,输出大小仍然是隐藏大小。然后我们对输出做同样的事情。

所以我们说输入到输出。这也将是一个线性层。因此输入大小是相同的。在这里我们使用输出大小。然后我们还需要一个softmax层。因此我们说self.dot softmax等于NN.dot softmax。然后我们说该维度等于长维度1,因为我们的输入,例如。

只需测试形状为1 x 57。我们需要第二个维度。这是我们的初始化函数。然后我们,当然,还需要定义前向传播。因此我们定义前向函数。它接收self,然后获取一个输入张量。正如你现在应该知道的,这也会获取隐藏张量。因此,我们使用隐藏张量进行前向传播。

然后在这里我们处理这个。所以首先,让我们再看一下这个。我们将输入和隐藏张量结合起来。然后我们应用这些线性层和softmax。然后我们返回两个不同的张量。所以输出张量和新的隐藏张量。我们来做这个。我们称之为combined等于。对于这个,我们可以使用torch.dot cat。

然后作为一个元组,我们想要组合输入张量和隐藏张量。在这里再次沿着维度1。然后我们应用我们的线性层。所以我们说隐藏等于self dot I to H。然后在这里我们放入组合后的张量,然后我们说我们的输出等于self dot I to O,O与我们的组合张量。对于输出,我们也应用soft max。

我们说output等于self dot soft max与输出。最后,我们先返回输出,然后返回新的隐藏状态。这基本上是我们R和N实现所需的一切。我还要添加一个新的辅助函数,我称之为init hidden。

所以我需要一个初始的隐藏状态。这里我想做的很简单,就是返回一个空的张量。所以我说torch dot zeros。这个张量的形状是1乘以self dot hidden size。是的,现在我们可以开始应用它。接下来我们加载数据。假设我们的类别行和所有可能的类别等于加载数据。

这是一个以国家为键、名称为值的字典。这只是所有不同国家的列表。然后是类别的数量。

Gorries等于所有类别的长度。例如,我们可以打印类别的数量。我们先保存这个,看看一切是否正常。假设我们用Python运行R和N。现在这个是可行的,我们看到有8个不同的类别。这是因为我们有8个不同的文件。现在我们需要定义或设置我们的R和N。

所以我们说R和N等于,然后我们使用我们的R和N类,这获取输入大小,也就是可能的字母数量。然后它需要隐藏大小。所以N hidden。它需要输出大小,也就是类别的数量。现在我们的隐藏大小。因此,N hidden是一个超参数,我们可以定义。因此,在这里,我们尝试128。现在,作为一个示例。

让我们做一个单独的步骤。比如说,我们的输入张量等于。然后我们使用字母到张量的函数,比如说字母a,然后我们需要一个隐藏张量。所以隐藏张量等于R和N dot init hidden,然后我们处理这个。所以我们说output和下一个隐藏状态等于R和N与输入张量和初始隐藏张量。

现在,例如,我们可以打印输出的大小或形状。我们还打印下一个隐藏状态的形状或大小。让我们运行这个,看看是否正常。因此,我们看到我们的N R和N应用了前向传递,我们得到了一个新输出和这个形状,以及一个新的隐藏状态和这个形状。因此,这仍然是定义的隐藏大小的大小。这就是它对于单个字符的工作方式。

现在如果我们回去。因此基本上我们想把我们的名字当作一个序列,然后每个单独的字符是一个输入。因此我们对名字中的所有字符重复应用R和N。然后在最后。我们获取最后的输出,应用软标记,然后选择概率最高的一个。这就是我们想为一个名字做的。所以现在我们说我们有整个序列。

整个名称,这里我们说我们的输入张量等于,然后我们使用线性到张量,这里。比如说,我们用名字阿尔伯特。然后我们的隐藏张量是一样的。并且也是。这次调用是一样的。所以我们抓住这个并复制它。然后在这里我们使用切片。所以我们现在只使用第一个字母作为这个简单例子。

所以让我们尝试这个并运行它,看看是否有效。嗯,是的。所以这个有效。而且现在在这里。我们必须重复应用这些字符。因此,为此,让我们先写一些帮助函数。所以让我。再将打印语句注释掉。所以现在让我们定义一个函数。并称之为从输出转换类别到类别。

这样就得到了输出。正如我所说,我们在最后应用了软标记。所以这基本上是每个类别中每个字符的可能性。因此我们想要返回最大值的索引。所以我们可以得到这个。因此类别索引等于。然后我们可以使用torch.dot.arc。😊,Max,然后在这里我们放入输出。

然后我们可以调用点项目,因为这只有一个值。然后我们可以返回所有类别,这个。使用这个索引类别索引的列表。所以这是一个。举个例子,假设我们现在打印输出的类别,然后从这个名称听到我们的输出。然后如果我们运行它。然后我们得到,现在,这是爱尔兰的。而且,当然,这还没有训练过。

所以这在我看来不像是爱尔兰的名字。因此现在我们想要做的是训练我们的R和N,当然。因此这里,和往常一样,我们想要设置一个标准和一个优化器。所以我们说标准等于。这里我们使用N N.dot N L L损失。这是负对数似然损失。然后我们需要指定学习率。在这种情况下,我们必须小心。

我尝试point005。学习率在这里非常重要。所以你可能想在这方面玩得多一点。然后我们说我们的优化器等于torch.dot.optim.dot S G D,因此随机梯度。下降。然后我们想要优化R N N.dot参数。作为学习率。

我们使用定义的学习率。因此现在我们有我们的损失和标准,并且让我们定义另一个帮助函数并称之为训练。这将是一个训练步骤,并且这得到一个行张量。因此整个名称作为张量。它也得到类别。类别张量。所以这是实际的类标签或类标签的索引。现在在这里我们想要获得初始隐藏状态。

所以我们说隐藏等于R和N点初始化隐藏。然后,正如我所说。我们想重复这样做。所以我们需要一个四个循环。我们说4 I在范围内,然后是行张量的长度。所以我们说行张量点大小,然后索引0。所以这基本上是名称的长度。然后我们应用这个。所以我们说输出和隐藏等于R和N与当前索引或当前字符的行张量以及之前的隐藏状态。请注意,我们放入隐藏状态并将其也分配给相同的变量。

所以新的隐藏状态将是来自R和N的输出。然后我们对整个名称执行此操作,然后对于最后一个字符。我们得到最终输出,然后我们用它来计算损失。所以我们说损失等于在这里我们应用我们的标准与输出和类别音调。

然后像往常一样,我们进行优化器步骤。所以首先,我们说优化器0梯度。然后我们说损失点反向传播,然后我们说优化器点步骤。然后在每个训练步骤结束时。让我们返回输出。也让我们返回损失点项目,所以不是作为音调,而是作为浮点值。

现在我们有这个训练步骤的辅助函数。现在我们可以进行典型的训练循环。所以为此,让我们跟踪一些东西。让我们说当前损失一开始等于0。然后所有损失等于一个空列表。在这里我们想放入所有的损失。这样我们可以稍后绘制它们。

然后我们说我们的绘图步骤和打印步骤等于。我们说1000和5000。迭代次数等于,让我们说100000。然后我们说4 I在范围内和。Eers。现在我们想要做的是获取一个随机训练样本。所以我们有这个作为辅助函数。它返回类别。

然后它返回实际的行或名称。然后类别是音调,也作为音调的行。我们通过调用实用类中的随机训练示例函数来获取这一点。这需要类别行作为输入和所有类别。然后我们调用训练函数。所以我们说输出和损失等于训练,这会得到行音调。

然后它获取类别音调,我们将损失加到当前损失中。所以我们说当前损失加等于损失。然后我们想打印一些信息。所以我们说如果我加。一种模式。Ploot步骤。所以每千步。如果这等于0。所以在这里我们想计算当前的运行损失并将其附加到所有损失中。

我们说所有损失点附加。在这里我们说当前损失除以绘图步骤的数量。然后我们将当前损失重置为0。因为在这里我们为每次迭代累加它。然后每千步我们才附加它。所以我们必须将其除以数量。然后我们得到平均值。现在我们对打印步骤做同样的事情。

所以我们说如果我加一模。打印步骤等于等于0。那么我们想打印一些信息。所以首先,我们想要获取猜测。所以我们说猜测等于从输出中获取类别,当然我们放入输出中。然后我们检查这是否正确。所以我们说正确等于。然后我们说。正确。

并且这是正确的。如果猜测等于我们从随机训练示例中得到的实际类别。如果这不正确,那么我们打印错误。我们还想打印实际类别。所以我们在这里使用F字符串。然后我们打印实际类别。接着我们再次以F字符串的形式打印当前迭代步骤。然后我们还。

让我们打印我除以迭代次数乘以100。然后我们也打印当前损失。所以我们说损失。并且我们只打印四个小数值。我们还打印当前行。所以基本上,这是名称。然后我们打印猜测。我们还打印是否正确。现在我们完成了。所以这基本上就是我们需要的全部。

现在当我们完成时,让我们绘制我们的损失。所以让我们用matplotlib绘制一个图形。所以PLDT.figure和PLT.plot,这里我们想要绘制所有的损失,然后说plot show,现在我们可以开始我们的训练了。现在我们可以做的事情是,我们可以在这里保存我们的模型,然后稍后用于我们想要的任何事情。但在这个情况下,我只是想自己试试。所以我说while true。

然后我说我获得一个句子作为输入。嗯。让我们说。输入。然后我把这个放入一个函数中。或者我首先说如果句子等于等于退出,那么我中断。否则,我想预测这个句子。所以为此。让我们创建另一个小助手函数,称之为。预测。

这会获取原始文本的输入行。所以首先,我打印。让我们打印一个新行。然后我们也打印输入行。所以为此,当然,我们需要一个F字符串。现在。在我们的预测中,我们应该使用torch.no_grad。我们现在可以关闭梯度。然后我们想要做的是说我们的行张量等于从原始输入行获取行张量。

现在我们想要做与训练步骤中相同的事情。所以我们有初始隐藏状态,然后反复应用我们的R和N。让我们这样做。让我复制这个并放在这里。所以我们有初始隐藏状态。然后我们说4我在行数十或大小0中。然后我们通过应用R和N来获取新的输出和新的隐藏状态。

然后在最后,我们想要获取猜测。所以我们说猜测等于。然后我们说从输出中获取类别。我们使用上一步的最后输出。然后我们简单地在这里打印猜测。在这个例子中。我没有计算准确性或其他任何东西。我只是打印猜测,看看它是否正确。

所以是的,让我们保存这个。然后让我们运行这个,希望一切正常。这可能需要几秒钟或几分钟。这是我给你展示的第一个例子?

现在我们看到有步骤。这应该是5000,实际上。这应该是训练的5%。然后我们有损失,还有名字,我们看到猜测是错误的,因为这实际上是Po。

好的,现在完成了,它正在绘制损失图。你会看到损失值迅速下降。然后它有些波动,但仍在下降。我认为这是一个相当不错的结果。那么我们来看一些。

训练期间的随机猜测。所以我们看到在开始时,几乎每个猜测都是错误的。然后它开始学习一些东西。现在它开始进行正确的预测。但当然,它仍然不是完美的。所以仍然有错误的修正。但在最后,我们得到了这个损失。这相当不错。现在我们可以自己尝试。现在。

例如,我们可以尝试一些来自那些文件的名字。比如说,让我们从一些德国名字开始。让我们试试acker。我们看到它说是德国的。再试试Oler,这也是正确的。再来试一些意大利名字。我觉得这些很容易识别。让我们试试Abba Dhi,它说是意大利的。

这是正确的。再试一些俄语名字,比如说a ba off。它说是俄语。好极了。再试一些更困难的,例如中文。让我们试试Bao,它说是正确的Bao。再试试bai。仍然是中文。所以看起来它在这个例子中运行得相当不错。当然,它仍然不是完美的。但现在。

所有的猜测都是正确的。所以现在你可以看到我们如何训练R和N进行名字分类。希望你喜欢这个教程,现在知道如何在Pytorch中实现R和N。如果你喜欢这个教程,请考虑订阅频道并给我一个点赞,下次再见,拜。😊

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P2:L2- 张量基础 - ShowMeAI - BV12m4y1S7ix

嗨,大家好。欢迎来到你的新 PyTorch 教程。在这个视频中,我们将学习如何使用 Tenzoas。所以我们将学习如何创建 Tenzoos 和一些基本操作。我们还将学习如何从 Numpy 数组转换到 PyTorch Tzoos 及其反向。因此,让我们开始。😊在 PyTorch 中,一切都是基于 Tenzo 操作的,从 Nai,你可能知道数组和向量。

现在在 PyTorch 中,一切都是一个 tenzoor。因此,tenzor 可以有不同的维度。它可以是 1D,2D,甚至 3D 或更多维度。所以让我们创建一个空的 Tenzoa。首先,我们当然要导入 torch。

然后我们说 x 等于 torch dot empty。然后。我们需要给它一个大小。因此,例如。如果我们只说一,这就像一个标量值。那么我们来打印我们的 tenzo。

所以这将打印一个空的张量。值尚未初始化。现在我们可以改变大小。例如,如果我们在这里说 3,那么这就像一个包含三个元素的 1D 向量。因此现在如果你运行这个。我们看到我们的 tenzon 中有三个项目。现在我们也可以制作一个 2D。例如。

假设大小是 2 乘 3。这就像一个 2D 矩阵。那么我们现在运行这个。

当然,我们甚至可以放入更多维度。所以现在它会是 3D。例如,现在它会是 40,但我现在不再打印它,因为看到四个维度很难。但这就是我们如何创建一个空的 Tenzo。我们还可以。例如,通过说 torch dot ran 然后给它大小来创建一个随机值的 tenzo。

所以我们说两乘两。

让我们再次打印我们的 tenzor。

我们也可以像在 Numpy 中一样,我们可以说 torch dot 0s。所以这会填充所有。

我们可以说 torch dot once。所以这将把一次放入所有项目中。然后我们还可以给它一个特定的数据类型。首先,我们可以通过说 x dot D type 来查看数据类型。

所以如果我们运行这个,我们会看到默认情况下,它是 float 32。但我们也可以给它 D type 参数。在这里我们可以说,例如,torch dot,现在它都是整数,或者我们可以说 torch dot。

Doub。现在是双倍。或者我们也可以说,例如,float 16 chest。嗯。一。现在。如果你想看看大小,我们可以通过说x点size来实现。这是一个函数。所以我们必须使用括号。

所以这将打印它的大小。我们还可以从数据构建一个tenor。例如,从Python列表中。所以,例如,这里我们可以说x等于torch点tenor。然后这里我们放一个包含一些元素的列表。比如说2。50。1,然后打印我们的tenor。

这也是我们可以创建tenor的方式。现在让我们谈谈可以进行的一些基本操作。所以让我们创建两个大小为2x2的随机值的Tzoos。x和y等于torch点rand2x2。所以让我们打印X。让我们打印Y。

而且。

是的,现在我们可以通过说set等于x加y来进行简单的加法。例如。现在让我们打印我们的C。这将进行逐元素加法。它将把每个条目相加。

我们也可以使用。

set等于torch点at,然后x和Y。这将做同样的事情。嗯。现在。我们还可以进行就地加法。所以,例如,如果我们说。

W点,然后add下划线。

X,然后打印Y。这将修改我们的y,并将x的所有元素加到y上。顺便说一下,在pi中,每个有尾随下划线的函数都会进行就地操作。所以这将修改应用于的变量。

所以,是的。那么,除了加法,我们当然也可以使用减法,所以我们可以说C等于x减y。或者这与C等于torch点s相同。

X和y。现在,如果你打印C,那么我们可以看到逐元素减法。然后我们还可以对每个元素进行乘法。所以这将是torch点mule。

再一次,我们可以通过说y点mu下划线x来实现就地修改我们的y。

然后我们还可以进行逐元素的运算。所以这将是torch dot di。

是的,这些是我们可以用张量执行的一些基本操作。然后我们也可以像你习惯于Numpy数组那样进行切片操作。所以假设我们有一个指定大小的张量。

假设是5乘3。让我们先打印这个。

现在,打印x。现在,比如说,我们可以简单地,或者我们可以获取所有行,但只要一列。所以我们使用切片。因此,我们在这里使用a。对于所有行,但仅仅是列0,所以下面是。

让我们打印整个张量,仅此而已。所以在这里我们看到只有第一列,但所有的行。

或者我们可以简单地说,比如说,使用行号一,但所有列。所以,这将打印。第二行,和所有列。然后我们还可以只获取一个元素。所以位置在1,1的元素。这将是这个值。顺便说一下,现在它打印的是张量。如果我们有一个仅包含一个元素的张量。

我们还可以调用dot item方法。

这将获得实际值,但要小心。只有在张量中仅有一个元素时,你才能使用此方法。所以这将获得实际值。是的,现在让我们讨论重塑张量。所以假设我们有一个大小为4乘4的张量,并打印我们的张量。

嗯。如果我们想重塑它,我们可以通过调用view方法来做到这一点。所以我们说y等于x dot view,然后给它一个大小。假设我们现在只想要一个维度。那么让我们打印Y。

现在它只是一个一维向量。

当然,元素的数量必须仍然相同。所以在这里我们有4乘4。所以总共也是16个值,比如说,如果我们不想将维度或值放在一个维度中,我们可以简单地说-1,然后指定另一个维度,Py会自动确定正确的大小。

所以现在它必须是2乘8。

Tzoa。所以我们也可以再次打印大小以查看其尺寸。

所以这是2乘8的大小。它已经正确确定了大小。如果我们在这里放一个-1。

所以是的,这就是我们如何调整张量的大小。现在让我们谈谈从Nmpy转换为torch张量及其反向转换。这非常简单。首先,让我们再次导入Ny或者导入Ny作为N P。我想我得。

哦,不,它已经安装在这里了。所以我们先创建一个Tzo。A等于torch点。我们用大小为5创建一个Tnza。所以我们打印我们的Tzo。

现在,如果我们想要一个numpy数组,我们可以简单地说B等于A点nuumpy,然后打印。

B。所以现在我们有一个nuy数组。如果我们打印be的类型。嗯。然后我们会看到。这将打印出我们有一个nuy和DNA。

所以是的,这就是我们如何从张量创建一个numpy数组。但是现在我们必须小心。因为如果张量在CPU上而不是GP。然后这两个对象将共享同一内存位置。这意味着如果我们改变一个。我们也会改变另一个。例如,如果我们打印或者通过说A点at underscore就地修改B或A。

记住,所有的underscore函数都会就地修改我们的变量。所以如果我们给每个元素加1,首先,我们来看看我们的张量。现在我们也来看看我们的B numpy数组。然后我们看到它也。

在这里给每个元素加一,因为它们都指向同一个内存位置。所以要小心。

嗯,如果你确实想反过来做。所以如果你有一个。

在开始时的Numpy数组。所以我们假设A等于nuy大小为5,然后打印A。

现在你想从一个numpy数组创建一个torch张量。你可以说B等于torch,然后from underscore nuumpy,然后放入numpy数组。所以现在我们有一个张量。

这将,嗯,默认情况下,将数据类型设置为float 64。当然,如果你想要不同的数据类型,你也可以在这里指定数据类型。

现在再次提醒,如果我们修改其中一个,要小心。所以如果我们通过递增每个元素来修改 nuy 数组,例如。

现在,打印我们的 nuy 数组。所以我们看到它的每个值都递增了。如果我们打印 B。

然后我们看到我们的张量也被修改了。所以在这里再次要小心。

是的,但这只有在你的张量位于 GPU 上时才会发生,而这一点我们还没有讨论,因为你也可以在 GPU 上执行操作,但只有在可用的情况下。所以如果你也安装了 Kuda 工具包。

你可以通过说来检查这一点。

如果 tor dot coa dot 是可用的。所以在我这里,Mac 上,它将。

这将返回假。但例如,如果你在 Windows 上,并且有 Kuda 可用,那么你可以通过说 device 等于 torch.Dot.Devicise,然后说 Kuda 来指定你的 Kuda 设备。如果你想在 GPU 上创建一个张量,你可以通过说 x 等于。

Torch dot once。然后,例如,给它大小,然后说 device 等于 device。所以这将创建一个张量并将其放在 GPU 上。或者你可以先创建它。因此,只需说。

Y 等于 torch dot1 的大小为 5。然后你通过说 y 等于 Y dot2,将其移动到你的设备到你的 GPU,然后设备,所以这会将其移动到设备上。如果你执行一个操作,例如 C 等于 x 加 Y,那么这将在 GPU 上执行,可能会快得多。

嗯。是的,但现在你必须小心,因为如果你调用 C dot Nmpy,那么这将返回一个错误,因为 Ny 只能处理 CPU 张量。因此,你无法将 GPU 张量转换回 Numpy。

所以再次,我们必须将其移回 CPU,因此我们可以通过说 C 等于 C 点。

2,然后作为一个字符串 CPU。所以现在它又会在 CPU 上。所以是的。这就是我想展示的所有基本操作,还有一件事,很多时候在创建张量时。

例如,torch dot。大小为5。然后很多时候你会看到参数 requires Grabs equals true。所以默认情况下,这是 false。

现在,如果我们打印这个。

那么我们在这个张量中也会看到它会打印出需要 Gr equals true。所以在代码中,你经常会看到这个,它会告诉 PyTorch 在你的优化步骤中需要计算这个张量的梯度。

所以每当这意味着你在模型中有一个想要优化的变量时,你就需要梯度。因此你需要指定 requires Gr equals true。不过我们将在下一个教程中更详细地讨论这个。所以希望你喜欢这个教程。如果你喜欢,请订阅频道,下次见,拜。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P20:L20- RNN & LSTM & GRU - 循环神经网络 - ShowMeAI - BV12m4y1S7ix

嗨,欢迎来到你的新Pytorch教程。今天,我将向你展示如何使用内置的RnN模块实现一个递归神经网络。在上一个教程中,我们从头开始实现了RnN。我强烈建议先观看这个教程,以了解RnN的内部结构。😊

今天,我们专注于使用Pytorch自己的模块进行实现,所以我们不必自己实现所有内容。我将向你展示如何使用RnN模块。最后,我还会向你展示如何轻松切换我们的RnN模型,并使用特殊类型的Rn,如LSTM和GRU。所以让我们开始吧。我们将以我的简单神经网络教程作为起点。

这是我Pytorch初学者课程的第13个教程。你可以在下面的描述中找到视频和代码的链接。正如我所说,这是第13个教程。我已经将这段代码抓取并复制到我的编辑器中。在这个例子中,我们在Mnes数据集上进行数字分类。

我必须说,图像分类并不是RnN的典型例子。但我想在这里演示的是我们必须如何处理输入。😊

将其视为一个序列,然后设置正确的形状,这也表明RnN确实可以用于在这个分类任务中获得高准确度。所以下次我们了解到,RnN的特殊之处在于我们在这里处理向量的序列。

所以我们将输入视为一个序列。RnN有不同类型。在这个例子中,我们使用了这种多对一的架构。这里我们有一个序列作为输入,最后只有一个输出。这个就是我们的类标签。所以让我们跳到代码。

首先我们必须改变的是超参数。所以Ms数据集由28乘28像素的图像组成。上次我们将其压缩为一维。我们的输入大小为28乘28或784。这次,如我所说,我们将图像视为一个序列。

所以现在我们做的是将一个图像维度视为一个序列,另一个图像维度视为输入或特征大小。你可以将其视为我们一次查看一行。让我们注释掉这个,然后创建一个新的。假设我们的输入大小等于。现在,如我所说,我们一次查看一行。这是28。然后我们也创建序列长度。

这也是28。然后我们将隐藏层大小更改为128。所以你可以在这里尝试不同的大小。我们再添加一个超参数,这是层数。这里我设置为2。默认情况下为1。这意味着我们在此情况下叠加两个RnN。

第二个R和N将第一个R和N的输出作为输入。这可以进一步改善我们的模型。现在我们想要实现R和N类。所以我们将名称改为R和N。在这个超类方法中也是如此。然后我们下面的模型现在也是R和N。

现在让我们删除所有这些,开始一个新的、干净的实现。所以现在我们的R和N仍然有输入大小、隐藏大小和类别数作为参数。它还获取新的参数层数。我们将其放在这里。因此,假设层数在这里。那么,当然。

我们在创建模型时也必须将其传递给模型。这是我们的超参数。😊。然后我们在这里首先想做的是简单地存储层数和隐藏大小。所以我们说self nu layers等于nu layers。还有,self.dot hidden size等于hidden size。然后我们创建R和N模型,并使用内置的Pytorch R和N模块。

所以你可以在官方文档中找到这个。所以这是Pytorch为我们提供的R和N类。我们将使用这个。因此,我们创建一个R和N并说self R和N等于。现在这在NN模块中。所以NN.dot R和N。

R和N需要输入大小。它需要隐藏大小,并且需要按此顺序的层数。然后我们还使用一个叫做batch first的参数,并将其设置为true。这意味着我们必须将batch作为第一维。因此,我们的输入需要具有形状。Batch size,Batch size,然后是序列长度。

然后是输入或特征大小。所以这是我们输入所需的形状。

再次,你可以在文档中找到这个。所以如果你将batch first设置为true,那么在这里你需要这个形状。

所以现在我们想要做的是在将图像传递给我们的模型之前。所以下次我们将其调整为这个大小。因此,最初我们的batch或图像的大小是batch size,然后是1,然后是28,然后再28。因此,这次我们只想要batch size,然后是28乘28。所以在这里我们将其调整为这个大小,然后是28。

第一个是我们的序列长度,第二个是我们的输入大小。所以这两个都是28。在我们的训练循环中也是如此,然后在我们的评估循环中,我们也做同样的事情。因此,在这里我们还需要将其调整为这个大小。现在我们的输入形状正确了。现在我们还需要一层。因此,正如我所说。

我们正在使用这种多对一的架构。所以最终我们有一个分类任务。这意味着我们使用一个线性层,然后是 softmax 和交叉熵。因此让我们再创建一个线性层。我们可以说 self dot Fc,表示全连接层等于 nn dot linear。在这里我们要小心。对于输入大小。

我们使用隐藏大小,输出大小是类别的数量。我稍后会再次解释,但基本上正如我们在这张图像中看到的,或者在这张图中,我们只使用最后一个时间步的隐藏状态来进行分类。因此,我们只需要最后一个隐藏大小作为线性层的输入大小。这基本上就是整个初始化函数。现在,当然。

我们还需要实现前向传播。因此我们的 R 和 N。如果我们查看文档。

然后它需要两个输入,第一个是输入,第二个是初始隐藏状态。所以我们需要以正确的形状来处理这个。因此,让我们创建一个 tensor,内容为 just0。所以我们说 H0 等于。然后我们说 torch dot0s。在这里,第一个是层数,第二个是批大小。

所以我们通过说 x dot size0 得到这个。下一个维度是隐藏大小。因此我们说 self dot hidden size。然后我们还想将其推送到设备上。如果你在使用一个。

所以现在这是我们的初始隐藏状态,现在我们可以调用我们的 R 和 N 模型。所以我们说 out,然后加下划线,因为我们不需要这个。然后我们说 self dot R 和 N。这会得到 x 和 H0。所以再次查看文档。它返回两个输出,第一个 tensor 包含来自所有时间步的输出特征或隐藏状态。

而另一个只是步骤 N 的隐藏状态。因此在这种情况下我们不需要这个。所以现在我们有了输出,输出的大小是。这是批次。

批大小,然后我们有序列长度,然后是隐藏大小。这是我们输出的新形状。现在我们想做的是仅解码最后一个时间步的隐藏状态。因此我们这里再次写出数字。这是 n,和 28,而我们的隐藏大小是 128。现在我们只想要最后一个时间步。

所以我们希望我们的输出在 n 和 128。因此我们通过说 out equals out 得到这个。然后我们在这里使用切片,获取批次中的所有样本,且仅取最后一个时间步。我们可以说 -1。然后再次使用冒号获取隐藏大小中的所有特征。现在我们得到了这个大小的输出。

这就是我们需要隐藏大小作为线性层输入大小的原因。所以现在我们可以调用它。现在我们可以说out等于self.fully_connected与我们的out。然后我们返回out。这就是我们为R和N所需的整个实现。所以,我们训练和评估循环中的其他一切保持不变。再次。

我们需要注意的是将输入视为一个序列。当我们使用内置的R和N时,我们需要使用正确的形状。然后我们还需要将初始隐藏状态设置为正确的形状。在将其传递给全连接层之前,我们必须重新调整它的形状。所以我们来试试看。

那么我们可以说Python main.pi。😊,好的,现在训练完成,正如你所看到的,我们得到了93%的准确率。因此我们的R和N有效,你可以看到它可以应用于这个分类任务。

现在最后,我还想向你展示两个R和N模块。所以两种特殊类型。第一个是GRU或门控递归单元。第二个是LSTM或长短期记忆。两者也是非常流行的R和N。我现在不会解释它们的理论。

我将向你展示我们如何轻松地使用这些实现。所以我们首先使用RU。我们可以简单地说nn.GRU。然后再称之为self.GRU,下面也称为self.GRU。其他一切保持不变。所以它接受相同的输入参数。

它还需要这个隐藏状态。然后输出具有相同的形状。现在让我们使用GRU并测试一下。

好的,正如你所看到的,GRU也能正常工作。这里的准确率甚至更高。最后一件事,让我们也试试LSTM。正如你可能知道的,对于LSTM,我们需要一个初始单元状态。所以让我们使用LSTM。首先调用cell.LSTM。然后在这里使用nn.LSTM。输入参数仍然是相同的。

然后这里我们需要一个初始的单元状态。所以我们称之为C0。这具有相同的形状。接下来我们调用自我LSTM。这需要隐藏状态和单元状态作为一个元组在这里。😊。

所以现在这就是我们应用LSTM所需的一切。让我们清理一下,再运行一次。好的,这一次工作得很好。你可以看到准确率是97%。所以,是的,现在你知道如何在Pyar中实现R和N,使用内置的R和N模块。你也知道如何使用GRU和LSTM。嗯,是的。

希望你喜欢这个教程。如果你喜欢它,请考虑订阅频道并点击点赞,下次见,拜拜。😊。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P21:L21- 调整学习率以获得更好的结果 - ShowMeAI - BV12m4y1S7ix

嘿,大家,欢迎来到另一个Pytorch教程。今天,我将向你展示一个简单但强大的技术,你可以在你的Pytorch代码中使用,以改善训练过程中的优化。因此,我们想在这里使用所谓的学习率调度。这意味着我们在训练循环中调整学习率。

无论是基于训练轮数还是基于验证测量。所以让我们开始介绍,然后我将向你展示如何做到这一点。😊!

🎼,如你所知,学习率是训练过程中最重要的参数之一,你应该在训练中进行调整。强烈建议在训练期间稍微调整学习率以获得更好的结果。Pytorch在其API中提供了几种方法来实现这一点。其实在你的代码中实现起来并不难。

让我向你展示一件事,我想提到的是,通过调整学习率,大多数时候我们想要降低学习率,而不是增加。但当然,这总是取决于你的具体问题。Pytorch在优化或optim模块中提供了一些所谓的学习率调度器。让我们浏览一下API文档,并展示一些例子。

所以我们现在在optim模块的API文档中。在这一部分中,如何调整学习率解释了我们如何做到这一点。当然,我会在描述中放上链接。它告诉我们torch Optim Lr调度提供了几种基于训练轮数调整学习率的方法,或者我们也有基于某些验证测量来调整学习率的方法。

我们还有这个重要的句子。学习率调度应该在优化器更新后应用。所以我们的代码应该看起来像这样。我们创建一个调度器。然后我们有我们的训练循环,在这里我们有训练轮数,然后我们进行训练步骤。这可能是像loss.backward。然后我们可能会有一个验证步骤。

然后我们调用Shaular的step方法。所以就是这么简单。但当然,我们必须创建一个调度器。为此,我们有不同的选项。让我们浏览一下文档,然后我会向你展示我们有哪些不同的方法。第一个是所谓的lambda Lr。它将每个参数组的学习率设置为初始学习率乘以给定的函数。

所以我们可能会有不同的参数组,但现在我们不需要关心这个。你应该知道,你可以在这里使用多个函数。所以我们想要做的是创建一个lambda函数。这基本上是一个单行函数。这可以依赖于训练轮数。在这个例子中,我们将轮数除以30。

然后我们用optr创建我们的lambda Lr,然后这个我们创建的lambda函数。那么我们来看看代码,让我给你展示一个实际的例子。所以你要做的是导入torch optim Lr scheduler作为Lr scheduler。😊

然后我们有一个学习率。因此在这种情况下,起初是0.1。接着我们有一个模型。在这种情况下,是一个简单的线性模型。然后你还需要一个优化器。接着我们创建这个lambda函数。这是一个单行函数,依赖于epoch。因此我们将epoch除以10,然后用初始学习率乘以这个值。

所以在第一个epoch我们有1除以10乘以我们的学习率,在第二个epoch,我们有2除以10乘以我们的初始学习率,依此类推,然后我们像这样创建我们的调度器。因此我们给它优化器和lambda函数。在这个例子中,我们的学习率实际上在增加。但在所有接下来的例子中,它将会减少。

所以在这里我们有我们的典型训练循环。首先,我想打印优化器状态字典,以展示它的样子。然后在这里我们可能,例如,进行lost.dot.backward,然后调用优化器步骤,然后我们可能有一些验证步骤,接着调用这个调度步骤。然后在这里我想打印实际的学习率,我们可以。

通过调用优化器状态字典来访问它。然后在这里我们访问关键参数组,并且这里我们只使用一个。所以我们用索引0来访问这个,并且使用关键学习率。所以这将给我们实际的学习率。我们通过说Python lambda L R来运行这段代码。然后在这里我们看到优化器状态字典的初始学习率是0.1。

然后在这里,第一个epoch。我们有1除以10乘以0.1。所以我们有这个。第二个epoch,我们有这个,依此类推。所以我希望这能清楚它是如何工作的。那么我们来看下一个例子。

所以下一个例子是所谓的乘法Lr。这基本上是相同的。但在这里我们将每个参数组的学习率乘以指定函数中给定的因子。因此,我们再次创建一个可能依赖于epoch的lambda函数。因此在这里我们只返回一个值。所以它实际上不会随着epoch数量的变化而改变。

但现在这是乘法的。因此每个epoch这将乘以上一个epoch。让我们再次查看代码,看看这看起来如何。因此这里我们有与之前相同的代码。但是现在我们使用乘法L R,简单地用这个0.95的因子。然后每次它将乘以上一个学习率。所以让我们打印出来。

这个,让我们清除这个并运行Python multi Lr dot pi。然后我们看到初始学习率为0.1。接着我们将其乘以0.95,这将给我们0.095。然后下一个,我们再次乘以0.95,这将给我们这个学习率,然后是这个,以此类推。

所以再次这里的主要区别是,我们将其乘以学习率,而使用lambda Lr时,我们只是使用初始学习率,然后将其乘以这个函数。如果我们继续前进,我们有步骤Lr,这可能是最简单理解的。因此,这里说它每个步长epoch将每个参数组的学习率衰减gamma。

它可能看起来像这样。因此,我们有我们的步骤Lr与优化器,然后是一个步长,再加上这个gamma。正如我所说,通常我们希望减少它。因此,我们将其设置为小于1的值。在这里,我们可以看到,在前30个epoch中,我们的初始学习率为0.05,然后我们将其乘以0.1。所以在接下来的30个步骤中,我们得到0.005,然后再次乘以我们的gamma。

所以我们有接下来30个步骤的学习率等等。所以,是的。这是最简单之一,但实际上非常强大。我自己非常常用这个。然后我们有这个多步骤Lr,它在达到里程碑的epoch数量后,通过gamma衰减每个参数组的学习率。因此,基本上在这里,我们可以给它里程碑,而不是步骤。

然后它将做同样的事情。因此,在第30个epoch时,它将应用我们的gamma,然后在第80个epoch时,它将应用我们的gamma,以此类推。这给了我们更多的变化,如果我们不想一直使用相同的步长。然后我们在这里有这个指数学习率(exponential Lr),它每个epoch通过gamma衰减学习率。因此,这本质上与步骤Lr相同。

如果我们在这里使用步长为1。那么我们在每个epoch简单地应用这个,而不必担心这些步骤。所以,是的,这就是这个。然后我们还有这个余弦调节学习率(cosine tuning Lr),我现在不会过多讲解,但你当然可以自己查看。好吧,但让我们再看一下这个。

这个被称为在平稳期减少学习率(reduce L R on plateau)。在这里,这并不依赖于epoch,而是依赖于一些测量或指标。因此,当指标停止改善时,它会减少学习率。在这里,我们希望降低学习率,而Py告诉我们,当学习停滞时,模型通常受益于将学习率降低2到10倍。

这个调度器读取一个度量数量。如果在患者的 epochs 数量上没有看到改进,学习率就会降低。所以我们需要的是一个优化器、一个模式、一个因子和一个患者。😊,模式可以是最小值或最大值。在最小模式下,当监测的数量停止减少时,学习率会降低;在最大模式下,当数量停止增加时,学习率也会降低。

然后我们需要这个因子。学习率降低的因子,默认是 0.1。我们还需要患者。我们需要等多久才算没有改进。即在没有改进的情况下经过的 epochs 数量,只有在第三个 epoch 后学习率才会降低。例如,如果患者等于 2,那么我们将忽略前两个没有改进的 epochs,只有在第三个 epoch 后才会降低学习率。

如果损失仍然没有改善,我们的代码可能看起来像这样。我们有我们的优化器。我们有这个 reduce L R on pla。与我们的优化器一起,在这种情况下,它只是使用默认的因子和患者。接着我们有我们的训练循环,在这里进行训练步骤。我们计算损失。验证后,我们使用这个验证损失计算 chatular dot step。

所以如果在我们想等待的 epochs 数量内没有改善,我们就会降低学习率。这确实可以帮助我们的模型停止停滞并进一步改善优化。所以是的,我们还有这个循环学习率,还有一个我想应该是这个 onecycl Lr。我在这里不会详细讲解,但你可以自己查看。不过,是的。

这就是我现在想给你展示的内容。所以再次强调,你可以查看这个 API 文档,然后了解不同的优化器。所以是的,这就是我目前想给你展示的一切,这真的可以在训练过程中帮助你的模型,并且实现起来并不困难。所以选择一个调度器,尝试不同的选项吧。

然后调用调度器,这就是 dot step。是的,接下来你就可以开始了。希望你喜欢这个教程,如果你喜欢的话,请订阅频道。希望下次再见,拜拜!

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P22:L22- PyTorch Lightning:专门为机器学习研究者开发的PyTorch轻量包装器 - ShowMeAI - BV12m4y1S7ix

嘿,大家,欢迎来到你们的新Pytor教程。今天,我们将讨论Pytor Lightning。Pytorch Lightning是一个轻量级的Pytor包装器。它旨在减少样板代码,以便实现算法和改进模型。因此,调整和优化可以更快。你不需要记住Pytor框架的所有细节,因为Lightning会处理这些。😊,另一个很棒的特点是它会打印警告,并给你有用的机器学习提示或建议。

如果你犯错误。我们稍后会看到这一切。通常,当涉及到抽象很多内容的包装框架时,我持怀疑态度。但这次,我真的可以推荐它。我仍然建议你首先学习基础知识。如果你还没有学习过,可以在YouTube上查看我的免费Pytorch课程。

链接在描述中。但如果你已经熟悉Pytorch,那么你可以查看Pytorch Lightning,看看你是否喜欢它。因此今天,我将把我的Pytor课程中的一段代码转换为Pytorch Lightning。这样你就能感受到这个框架的工作原理以及如何使用它。好的,让我们开始吧。

首先,Pytorch Lightning是开源的。你可以在Github上找到它。他们还有一个网站,提供良好的文档,帮助你入门。我会放上。😊!

描述中的链接也是如此。而现在,这里有一些关于Pytorch Lightning的细节,你不再需要担心的。因此,你不再需要担心何时将模型设置为训练或评估模式,你也不必担心使用设备进行GPU支持,然后将模型和所有张量推送到设备上。你可以轻松关闭GPU或甚至不使用GPU支持,使用Lightning可以轻松扩展。此外,你也不再需要关心零梯度或调用反向传播和优化步骤,你也不需要担心使用torch.no_grad或detach,作为额外奖励,你还有张量或支持集成。

它还会打印提示或提示,我们稍后会看到。让我们跳到代码。这次示例中,我们将从我的Pytorch教程中提取一段代码。你可以在Github上找到它,然后在这种情况下,我们取教程编号13。这是一个简单的前馈神经网络,应用于MNIST数据集进行数字分类。

现在,让我们抓取一些代码,并用Pytorch Lightning编写新代码。首先,我来删除这个,现在我们从一个新的Python脚本开始。顺便说一下,当你想安装Pytorch Lightning时,有两个常见的选择。第一个是使用Pip。所以你只需说Pip install Pytorch Lightning。或者如果你在Conda中使用。

然后你可以抓取这个命令。

我已经在我的终端中完成了这个操作。所以Pytorch lightning已经在这里导入了。现在让我们回到代码中,复制粘贴一些内容。我们希望有所有相同的导入语句。

作为补充,我们现在还导入了Pytorch lightning。所以我们说导入带下划线的Pytorch lightning。

现在我们想将我们的模型、神经网络转换为一个lightning模型。所以我们抓取这段代码,然后把它复制粘贴到这里。现在我们不再从N和dot模块派生,而是从P dot lightning模块派生。这将给我们原始模型的相同功能,但还会提供一些更多的功能,我们稍后将看到。

现在in it函数仍然是相同的,forward函数也仍然是相同的。所以我们需要所有的超参数。让我们抓取这些超参数并粘贴到这里。😊。

现在我们需要实现一些更多的函数。所以让我们快速访问一下官方网站。在这里,你会看到一步一步的指南,顺便提一下,你还有一个很好的比较,Pytorch代码与Pytorch lightning的区别,以及它抽象了什么。因此,如你所见,我们还需要定义一个训练步骤。

一个配置优化器函数和一个训练数据加载器。所以让我们把这些全部复制到这里。

现在,对于最简单的配置优化器,你只需放入你创建的优化器。所以在我们原始脚本中,我们在这里设置了优化器。这是原子优化器。然后返回它。所以我们可以在一行中返回这个。这将是我们的优化器。

我们的原子优化器与超参数中的学习率。

然后我们想要实现训练步骤。

对于训练步骤,我们正在做的正是我们在训练循环中所做的。现在我们不再需要担心关于解包图像和标签的循环,以及优化器如何进行反向传播和步骤。

所以我们简单地抓取这一部分。

并粘贴到这里。如你所见,在训练步骤函数中,我们获得一个批次和一个批次索引。因此我们将批次解包为x和y。让我复制代码。因此。这就是我们的图像和标签。然后我们需要重新调整图像的形状。并且我们不再需要将其推送到设备。因此我们移除所有这些内容。

然后我们进行前向传递。在这里我们实际上可以使用self,因为我们在模型类内部。

然后我们应用标准。 在我们原来的代码中,我们将标准设置为N和dot交叉熵。但如果使用功能模块,我们也可以用它。因此,我们说。

导入torch的N,N,dot funk。Channel S F。然后在这里,我们说我们的损失等于。现在我们可以调用F dot交叉熵与我们的输出和标签。这些都是我们所需的。而现在,我们只想返回一个包含这个损失的字典。因此PyTorch Lightning需要这个字典,以便在训练过程中显示损失。

这就是我们训练步骤中所需的一切。然后我们还必须实现训练数据加载器函数。我们想在这里做的就是回到开始时设置训练数据集和训练数据加载器。

所以我们复制这个并粘贴到这个函数里。因此首先是我们的训练数据集。这就是这个。然后是训练数据加载器。这一个。

然后我们想要返回训练数据加载器或训练加载器。现在这就是我们开始训练所需的一切。接下来我们要做的是,如果__name__等于__main__,那么我们需要设置一个Lightning训练器。因此,我们导入一个训练器。我们说从Pytorch Lightning导入训练器。

然后我们想设置一个训练器。因此在这里我们说我们的训练器等于我们的Lightning训练器。现在,我可以给你展示一个在开发过程中非常有用的技巧。因此你说fast_dev_run等于True。这将通过训练和验证运行一个批次。如果我们有验证步骤。通过这个。

你可以测试你的模型是否有效。因此现在我们还必须设置我们的模型。我们说模型等于。让我们称其为lit模型,以清楚地表明这是一个Lightning模型。因此lit。😊。uralNe。这里我们说让神经网络具有超参数。因此它需要输入大小。它需要隐藏大小,并且需要类别数。

我们在这里都有超参数。然后我们必须将其适配到我们的训练器。所以我们说trainer.dot fit我们的模型。现在我们可以直接运行它并看看这是否有效。所以现在,让我们去控制台。现在让我们运行这个文件。所以我们说Python lightning.dot pi。这里我们得到一个错误。所以,当然,我重命名了lital net。所以我也必须说明。

将神经网络命名为这里。现在再次运行它。现在我们看到它开始了。我们看到没有GPU支持。我们还得到了不同层和参数的概述。然后因为我是第一次运行,所以它正在下载数据集。然后这里是训练。所以它成功了。因为我们设置fast defffron等于true,所以只处理了一批。

所以让我们清除它并再测试一次。所以现在它不应该再下载了。这快得多了。现在这里,例如,我们得到一个警告,所以它说。数据加载器训练数据加载器没有很多工作进程,这可能是一个瓶颈。考虑增加nu workers参数的值。试试4。

所以这实际上是第一个可以帮助我们加速代码的提示。在我们的训练加载器中,我们可以给它的参数设置为nu workers等于4。现在我们清除这个并再次运行,现在我们的警告消失了。这里我们看到了概览。我们现在只使用了一个epoch,这里有损失值。

所以现在如果你想进行完整的训练,我们也可以给我们的训练器参数max epoch等于定义的epoch数量。所以这是超参数之一。现在让我们再次将其设置为false。这应该进行完整的训练。现在,让我们看看这是否有效。

现在这应该需要。Max epos,抱歉。现在这应该稍微长一点。是的,我们看到。所以我们得到了一个不错的进度条,我们看到训练正常运行,损失值应该慢慢减少。所以这有效。😊,所以现在让我暂时停止这个。接下来我们想要做的是进行评估或测试。

所以类似于训练步骤和训练数据加载器。我们现在也想添加一个验证步骤和验证数据加载器。所以让我复制这个。并在这里粘贴。它必须被称为验证步骤。实际上我们在这里做同样的事情。所以在测试训练步骤中也是如此。

所以我们重新调整了图像,然后进行前向传播并计算损失。这次我们使用关键损失或验证损失。现在我们再次将fast defron设置为true。让我再运行一次。所以现在如果我们运行它,我们应该得到一个错误。是的,这里我们得到了异常,你已定义验证步骤。

但尚未传入验证数据加载器。所以现在我们知道该怎么做。我们还必须使用验证数据加载器。所以让我复制并粘贴这个。并且这必须被称为well data loaddown。如果你不确定,可以去官方文档。

文档,然后滚动到验证循环。在那里。你会看到。

你需要的三个函数,所以。现在,首先,我们有我们的。验证数据集。因此在这里我们想说,或者我们想抓取。

下一个或测试数据集。在这种情况下,我称之为测试数据集。但实际上。你需要将数据划分为训练数据集、验证数据集和测试数据集。验证数据集用于在调整超参数时对模型性能进行无偏评估。而测试数据集则是在最后提供对模型从未见过的数据的无偏评估。

在这个示例中,我们假设只有两个数据集的划分。现在。我们只使用前两个步骤进行训练和验证。所以让我复制这个并粘贴到这里。然后让我们将其重命名为验证数据集。接着我们获取验证数据加载器。

并将其重命名为验证加载器,然后返回v加载器。现在让我们再运行一次。假设Python lightning dot pi。我们得到了一个错误。因此数据集等于好的数据集。 当然。让我们清除这个并再次运行,然后它应该通过训练和验证进行一次传递。我们看到它成功了。现在我们再次得到了相同的警告。

在这里我们使用nu workers等于4。因此让我们清除并再次尝试。因此,你会看到,当我们犯错误时,它已经开始给我们提示。现在我们看到它成功了。现在它也建议定义一个验证周期和方法来累积统计数据。所以让我们去文档中获取这个函数,看看它的样子。

我们复制并粘贴这个。因此这是在每个验证周期后执行的函数。在这里我们想计算平均损失。实际上,在我们的示例中。我们想做的正是这个。所以我们想调用。通过说这是torch stack来计算平均损失。然后因为我们。

被称为关键验证损失。我们可以在这里访问它,然后计算所有损失的均值,现在,暂时先不担心这个。然后我们将平均损失作为字典返回。这样我们就完成了。所以现在,如果我们清除它。那么,我们应该得到一个。1次通过,现在没有更多的警告。现在我们有了我们所需的一切来处理我们的代码。

所以这就是我们在PyTorch Lightning中所需的全部。现在,让我给你展示一个提示。我们可以获得的内容。例如,在我们的验证加载器中。如果我们不小心将shuffle设置为true并尝试运行它。我们应该得到一个警告或提示。所以是的,这里我们看到了用户警告。

你的数据加载器有shuffle equals true。在验证和测试数据加载时,最佳做法是将其关闭。所以你看,我们实际上可以用这个框架改进我们的代码。现在,让我们把它和我们的原始代码进行比较。如果我们在Github上查看这段代码。

然后我们不再需要这个设备功能。我们也不再需要手动遍历所有的轮次和所有的批次。我们不再需要关心这两个设备调用。我们也不再需要关心优化器和反向传播,并且我们可以省略整个验证循环,因为我们可以通过这个验证步骤来计算,现在,例如,如果你还想要一个训练步骤,我们可以以同样的方式轻松编辑,就像我们用这个函数和这个函数一样,现在。

例如,如果你想使用GPU,我们可以通过给我们的训练器传递参数GPus equals,例如one来轻松实现,当你想扩大规模并且有更多GPU可用时,你也可以使用。

2,或者我们说4,或者你甚至可以使用T支持。所以从CPU切换到GPU,然后扩展规模真的很简单。你还可以拥有一个分布式后端。所以DP,例如。你也可以轻松切换到16位精度。你可以锁定GPU内存。因此,你现在可以非常轻松地测试很多功能,这个框架非常适合。

你只需使用所有不同的训练器参数。比如说,还有一个很有用的功能你可以尝试,就是auto L RFind equals true。这将运行一个算法来寻找最佳学习率。所以你可以尝试这个。你也可以设置,例如,deterministic equals true。这样可以使你的结果可重现。

或者你可以通过简单地传入参数Claient gripve equals和一个介于0到1之间的值来轻松应用梯度裁剪,我想,这样的话,你仍然需要查看官方文档。

在那里你可以找到所有不同的功能和用例。现在让我给你展示完整的训练和验证。所以让我们去掉这个。现在让我们将参数fast defffron重新设置为false。所以再次强调,我没有设置很多的轮次,所以只有两个,因为在没有GPU的情况下,这里会花费很长时间。

但我们还是运行一下。

所以我们再次看到这里第一轮的进展,以及我们的损失是如何降低的。当这一切完成时,我们应该在验证循环中看到一个更快的进度条。现在小心。现在我们看到验证循环。现在我们的第二个训练轮开始了。所以,没错,这在工作。现在第二次验证,也完成了。

我们可以查看并检查最终的损失。因此这有效。现在最后一件事,让我给你展示集成的天线板支持。正如你所看到的,已经有一个名为 lightning lock 的文件夹,所以它已经自动保存了一些检查点。😊,所以现在。

如果我们想检查天线板中的不同损失,那么我们需要做的是。例如,如果你想检查训练。那么在我们的训练步骤中,我们创建另一个字典。我们称之为天线板锁,等于。再一次,这是一个字典,这里我们把训练损失作为键,值是相同的损失。

然后我们还将天线板损失附加到我们的字典中。我们必须给它钥匙锁,然后是锁。这是我们的天线板锁。现在在我们的验证周期结束时也是如此。所以在这里我们创建天线板锁。我们称之为平均验证损失。这是平均的,平均损失。

然后在这里,我们使用了钥匙锁和天线板锁。现在我们再运行一次以保存所有内容。因此,我们需要等到这个完成。现在我们的训练和验证都完成了。所以现在应该保存所有这些到锁目录。

现在我们可以通过输入 tensor board minus minus lock 来启动天线板。D 等于,然后是 lightning locks。顺便说一下,我也有一个完整的教程,讲述如何使用 Tensor board。我会在描述中放上链接。使用 lightning,你不必手动安装,因为它包含在 lightning 的要求中。

所以这现在应该自动工作。现在如果我们点击运行,抱歉,这里没有下划线。inus minus loar 等于 lightning locks。现在它可以工作。现在我们的天线板在这里运行。如果我们打开这个。

然后我们应该检查周期。然后我们有平均验证损失。由于我们只使用了两个周期,我们在这里看不到太大的差异,所以只有一行。但对于训练损失,这是我们在每个训练步骤后查看的。因此这里我们看到一个很好的图表,显示我们的训练损失是如何减少的。所以,是的,你看到了。

我们有自动的天线板集成,使用这个工具非常简单。因此,是的,这些是我想展示的大部分功能。如果你喜欢这个框架,请在评论中告诉我。如果你也认为它可以简化你的开发过程。如果你喜欢这个视频。

请点击喜欢按钮,并考虑订阅频道。这对我帮助很大,下次再见!

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P3:L3- 使用 Autograd 计算梯度 - ShowMeAI - BV12m4y1S7ix

嗨,大家好。欢迎来到新的 pytorrch 教程。今天,我们将学习 pytorrch 中的 autograd 包,以及我们如何用它计算梯度。梯度对于我们的模型优化至关重要。因此,这是一个我们应该理解的重要概念。幸运的是,Pytorch 提供了 autograd 包,它可以为我们执行所有计算。

我们只需要知道如何使用它。因此,让我们开始看看如何在 pytorrch 中计算梯度。首先,我们导入 torch。当然。😊 然后让我们创建一个张量 x 等于 torch dot R n,大小为 3。现在让我们打印我们的 x。这是一个包含三个值的张量。三个随机值。现在。假设我们稍后想计算某个函数相对于 x 的梯度。

那么我们要做的就是指定参数 requires Gr 等于 true。默认情况下,这是 false。现在如果我们再次运行这个,我们会看到 Pyto 也跟踪它需要梯度。现在,每当我们对这个张量进行操作时,Pytoch 会为我们创建一个所谓的计算图。因此,现在假设我们进行操作 x 加 2,并将其存储在输出中。

所以我们说 y 等于 x 加 2。这将创建计算图。

这看起来像这样。对于每个节点,我们有一个遍历操作。我们有一个带输入和输出的节点。所以这里的操作是加法。因此,输入是 x 和 2,输出是 y。现在通过这个图和称为反向传播的技术,我们可以计算梯度。我将在下一个视频中详细解释反向传播的概念。

但现在,只需知道我们如何使用它就可以了。因此,首先我们进行前向传递。在这里,我们应用这个操作。在前向传递中,我们计算输出 y。由于我们指定它需要梯度,Pytoch 会自动为我们创建并存储一个函数。

这个函数随后用于反向传播以获取梯度。因此,y 拥有一个属性 Gr underscore F N。这将指向一个梯度函数。在这种情况下,称为 at add backward。通过这个函数,我们可以在所谓的反向传递中计算梯度。

所以这将计算 y 对 x 的梯度。在这种情况下。如果我们打印 y。

然后我们将看到这个 grat Fn 属性。这里,这是一个反向函数。因为在这里,我们的操作是加法。然后,我们再进行反向传播。因此,这就是为什么称之为反向。让我们用我们的张量做一些更多的操作。假设我们有 C 等于 y 乘以 y 乘以 2。

所以这个张量也有这个 gra 函数属性。因此这里 Grt Fn 等于 mile backward,因为这里我们的操作是乘法。例如,我们可以说 C 等于 C.mean。这样我们就可以应用均值操作。然后我们的梯度函数就是 mean backward。现在,当我们想要计算梯度时,我们必须做的唯一事情就是调用 C.backward。

因此,这将计算 C 关于 x 的梯度。所以 x 具有一个梯度,一个 dot Gr 属性,其中存储了梯度。我们可以打印它。现在如果你运行这个。那么我们看到在这个张量中有梯度。因此,这就是我们必须做的所有事情。现在让我们看看当我们不指定这个参数时会发生什么。所以首先。

如果我们打印我们的张量。然后我们看到它们没有这个 gra 函数属性。如果我们尝试调用反向函数,那么这将产生一个错误。因此,它显示张量不需要 gr 并且没有 gr 函数。所以记住,我们必须指定这个参数,然后它将正常工作。

我们还应该知道的一件事是,在后台这基本上做了什么。这将创建一个标量向量雅可比乘积以获得梯度。所以它将看起来像这样。我不会深入数学细节。但我们应该知道,我们有雅可比矩阵与偏导数。

然后我们将其与梯度向量相乘。然后我们将得到我们感兴趣的最终梯度。这也称为链式法则。我将在下一个视频中更详细地解释这一点。但我们应该知道,实际上我们必须将其与一个向量相乘。因此在这种情况下,由于我们的 C 是一个标量值,我们不需要传递参数。

在这里对于我们的反向函数。

所以我们的 C 这里只有一个标量值。这是可以的。但假设我们没有应用均值操作。那么现在我们的 C 中有多个值。所以它的大小也是 1x3。现在,当我们尝试像这样调用反向函数时。这将产生一个错误。因此,Gr 只能为标量输出隐式创建。在这种情况下,我们必须。

给它梯度参数。所以我们必须创建一个相同大小的向量。所以,假设 V 等于 torch.dot(1)。在这里我们放置,例如,011.0 和 0.0,0,1。并且我们将数据类型设置为 torch.float32。然后我们必须将这个向量传递给我们的反向函数。现在它将再次正常工作。所以现在,如果我们运行这个。那么这是可以的。

我们应该知道,在后台,这是一个向量雅可比乘积。很多时候,最后一个操作是某个操作,将创建一个标量值。因此,可以在没有参数的情况下像这样调用。但如果这不是标量,我们必须提供向量。还有一些其他事情我们应该知道,如何防止Pyth跟踪历史并计算这个grad_fn属性。

例如,有时在我们的训练循环中,当我们想更新权重时,这个操作不应该是梯度计算的一部分。在接下来的教程中,我会给出一个具体的示例,说明我们如何应用这个autograd包。然后可能会变得更清晰。但现在是这样。

我们应该知道如何防止跟踪梯度,并且我们有三个选项。第一个是调用requires_grad下划线函数,并将其设置为false。第二个选项是调用x dot detach。因此这将创建一个不需要梯度的新张量。

第二个选项是将其包装在一个宽度语句中。因此使用torch,dot,不需要梯度。然后我们可以进行操作。是的,让我们尝试每一个。这是第一步。我们可以说x dot需要梯度,带下划线,并将其设置为false。因此,每当一个函数在Pytorch中有一个尾随的下划线时。

这意味着它将在原地修改我们的变量。因此,现在,如果我们打印x。然后我们会看到它不再具有这个requires_grad属性。所以现在这是false。这是第一个选项,第二个选项是调用x.detach。因此我们说y等于x.detach。这将创建一个具有相同值的新向量或新张量。

但它不需要梯度。因此在这里我们看到我们的y具有相同的值,但不需要梯度。最后一个选项是将其包装在一个torch的with语句中,使用torch.no_grad。然后我们可以进行一些操作,例如y等于x加2。现在,如果我们打印我们的y,我们会看到它在这里没有梯度函数属性。因此,是的。

如果我们不使用这个并且像这样运行它。那么我们的y就会有梯度函数。因此,这三种方法可以阻止Pytorch创建梯度函数并跟踪我们计算图中的历史。而现在还有一个非常重要的事情,我们也应该知道的是,每当我们调用backward函数时,梯度将被累积到dot_grad属性中。

这样值就会被求和。在这里我们必须非常小心。因此让我们创建一些虚拟的训练示例,其中我们有一些权重。这是一个全为1的张量,大小为4,并且需要梯度。因此requires_grad等于true。现在假设我们有一个训练循环,我们说对于每个epoch在范围内。

我们先进行一次迭代。这里我们假设模型输出等于权重乘以3的总和。这只是一个虚拟操作,用来模拟一些模型输出。然后我们想计算梯度。所以我们调用模型输出的.backward()。现在我们有了梯度,可以调用weights.Gr并打印出来。

这里的梯度是3,所以张量填充了三的值。如果我们进行第二次迭代,那么第二次的backward调用将再次累加值并写入Gr属性。现在我们的grs中有六。再进行第三次迭代后,它将变为九。

所有值都已被求和。现在我们的权重或梯度显然不正确。在进行下一次迭代和优化步骤之前,我们必须清空梯度。因此,我们必须调用weights.Gr.0_。现在如果我们运行这个,梯度将再次正确。这是我们在训练步骤中必须了解的一个非常重要的事项。

接下来我们将使用Pytorch内置的优化器。假设我们有一个来自torch优化包的优化器。torch的optim模块提供了随机梯度下降(SGD),它的参数包括我们的权重和一些学习率,现在有了这个优化器。

我们可以调用或进行一个优化步骤,然后在进行下一次迭代之前,必须调用优化器的do0_gra函数,它会执行完全相同的操作。所以,是的。我们将在后面的教程中讨论优化器。但现在,你应该记住的是,每当我们想计算梯度时。

我们必须指定require_gr参数并设置为true。然后我们可以简单地调用backward函数来计算梯度。在进行下一个操作或优化步骤的下一次迭代之前,我们必须清空我们的梯度。因此,我们必须再次调用the0函数。我们还应该知道如何防止某些操作在计算图中被跟踪。

这就是我想向你展示的有关autograd包的内容。希望你喜欢。请订阅频道,下次再见,拜。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P4:L4- 反向传播 - 理论与实例 - ShowMeAI - BV12m4y1S7ix

大家好,欢迎来到新的 PyTorch 教程。在这个视频中,我将解释著名的反向传播算法,以及我们如何用它计算梯度。😊我将解释这项技术的必要概念,然后带你通过一个具体的示例和一些数字。最后。

然后我们将看到在 PyTorch 中应用反向传播是多么简单。所以让我们开始。首先,我们必须了解的概念是链式法则。假设我们有两个操作或两个函数。首先,我们有输入 X,然后我们应用一个函数 A,得到输出 Y。

然后我们将这个输出作为我们第二个函数的输入。第二个函数 B。然后我们得到最终输出 C。现在我们想要最小化我们的 C。因此,我们想知道 C 关于我们最开始的 x 的导数。我们可以使用所谓的链式法则来做到这一点。

我们首先计算 C 关于 y 的导数,并将其与 y 关于 X 的导数相乘。然后我们得到我们想要的最终导数。所以首先,在这里,我们计算这个位置的导数。这个输出相对于这个输入的导数。然后在这里,这个输出相对于这个输入的导数。

然后我们将它们相乘,得到我们感兴趣的最终梯度。这就是链式法则。接下来要了解的概念是所谓的计算图。对于我们在 PyTorch 中进行的每一个操作,PyTorch 会为我们创建一个图。在每个节点上,我们应用一个操作或一个函数,并获得输出。

在这个例子中,我们使用乘法操作。我们将 x 和 y 相乘,然后得到 C。在这些节点上,我们可以计算所谓的局部梯度,稍后可以在链式法则中使用它们来得到最终梯度。在这里,局部梯度,我们可以计算两个梯度,C 关于 x 的梯度。

这很简单,因为我们知道这个函数。所以这是 x 和 y 关于 x 的导数的梯度,即 y。在底部,我们计算 x 和 y 关于 y 的导数,结果是 x。局部梯度很简单,因为我们知道这个函数。我们为什么要它们呢?

因为通常我们的图有更多操作。在最后,我们计算一个我们想要最小化的损失函数。因此,我们必须计算这个损失关于我们最开始的参数 X 的梯度。现在,假设在这个位置,我们已经知道损失关于 C 的导数。

然后我们可以得到我们想要的最终梯度。通过链式法则。损失相对于X的梯度是损失相对于C的梯度乘以我们的局部梯度。因此,C相对于x的导数。是的,这就是我们得到最终梯度的方式。现在,整个概念由三个步骤组成。

首先,我们进行前向传播,应用所有的函数并计算损失。然后在每个节点,我们计算局部梯度。接着我们进行所谓的反向传播,在这里我们使用链式法则计算损失相对于我们的权重或参数的梯度。这就是我们将要做的三个步骤。现在我们看一个具体的例子。

所以我们在这里想要使用线性回归。如果你不知道这如何工作,那么我强烈推荐我的《从零开始的机器学习》教程,关于线性回归。我会在描述中放上链接。因此,基本上,我们用一些权重和输入的线性组合来建模我们的输出。

所以我们的y hat或预测的y是w乘以x。然后我们制定一些损失函数。在这种情况下,这就是平方误差。实际上,它应该是均方误差,但为了简单起见,我们只使用平方误差。否则,我们还需要进行另一个操作来获取均值。因此,损失是预测的y与实际y的差值,然后我们对其进行平方。

现在我们想要最小化我们的损失。我们想知道损失相对于我们权重的导数。我们如何得到这个呢?所以我们应用我们的三个步骤。首先,我们进行前向传播,输入x和W。然后在这里我们输入y,并在这里应用我们的函数。然后我们得到损失。

然后我们在每个节点计算局部梯度。在这里,损失相对于我们的S的梯度。然后这里,S相对于我们的y hat的梯度。在这个节点上,Y hat相对于我们的W的梯度。接着我们进行反向传播,从最后开始。

在这里我们有第一个,我们有损失相对于我们的S的导数。然后我们使用它们,我们还使用链式法则来获取损失相对于Y hat的导数。然后再次,我们使用这个和链式法则来获得损失相对于我们的W的最终梯度。所以让我们用一些具体的数字来做这个。假设我们有x和y。

而y在开始时是2。所以这些是我们的训练样本。我们初始化我们的权重。假设,例如,我们说我们的w在开始时是1。然后我们进行前向传播。在第一个节点,我们将x和W相乘。所以我们得到Y hat等于1。然后在下一个节点,我们进行减法。所以y hat y是1-2等于-1。在最后,我们对我们的S进行平方。

我们有 S 的平方,因此我们的损失是 1。现在我们计算局部梯度。在最后一个节点,我们有损失对 S 的梯度。这很简单,因为我们知道函数。这是 S 的平方的梯度,也就是 2 S。在下一个节点,我们有 S 对 Y hat 的梯度。

这是函数 Y hat 减去 y 对 Y hat 的梯度,值为 1。在最后一个节点,我们有 Y hat 对 W 的导数。这是 W 乘以 x 对 w 的导数,结果是 x。同时,注意我们不需要了解这个图线中的导数。

因此,我们不需要知道 S 对 Y 的导数。而且在这里,我们也不需要这个,因为我们的 x 和 y 是固定的。因此,我们只关注想要在这里更新的参数。然后我们进行反向传播。首先,我们使用我们的局部梯度。

我们想要计算损失对 Y hat 的导数。在这里,我们使用链式法则,结合我们刚刚计算的两个局部梯度,也就是 2 S 乘以 1,而 S 是 -1,这个我们在上面计算过。结果是 -2。现在我们使用这个导数和这个局部梯度来得到最终的梯度。

损失对我们的 W 的梯度,就是损失对 Y hat 的梯度乘以 Y hat 对 W 的梯度。结果是 -2 乘以 x,而 x 是 1。因此,最终的梯度是 -2。这就是我们想知道的最终梯度。这就是反向传播的全部工作原理。让我们跳到代码部分,验证 PyTorch 是否能得到这些确切的数字。

让我们记住 x 是 1,y 是 2,而 w 是 1。那么我们的第一个梯度应该是 -2。

让我们看看如何在 PyTorch 中使用这个。首先,我们当然要导入 torch。然后我们创建我们的向量或张量。因此,我们说 x 等于 torch.dot.tenor。这是 1。然后我们的 y 等于 torch.dot.tenor,值为 2。接着我们的初始权重是一个张量,值为 1。因此,1.0 使其成为浮点数。然后用我们的权重。

我们对梯度感兴趣。因此我们需要指定 require Sc 等于 true。然后我们进行前向传播,计算损失。因此我们简单地说,Y hat 等于 W 乘以 x,这就是我们的函数。然后我们说损失等于 Y hats 减去实际的 y。然后我们将其平方。所以我们说,这个平方。现在,让我们打印我们的损失,看看结果。

这是开始的内容。现在我们想要进行反向传播。因此,让我们进行反向传播。pi touch 将自动为我们计算局部梯度,同时也自动计算反向传播。因此,我们唯一需要调用的就是 loss backward。这就是整个梯度计算。现在我们的 w 有了这个 dot Gr 属性。

我们可以打印这个。现在这是第一个梯度。在第一次前向和后向传播之后。记住,开始时应该是-2。在这里我们看到有一个张量为-2。所以这个是有效的。接下来的步骤是。例如,现在我们更新我们的权重,然后进行下一次前向和后向传播,并进行几次迭代。

是的,这就是反向传播的工作原理,以及在Pytorch中使用它是多么简单。希望你喜欢这个教程。请订阅频道,下次见,拜!😊。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P5:L5- 带有 Autograd 和反向传播的梯度下降 - ShowMeAI - BV12m4y1S7ix

嗨,大家好。欢迎来到新的Pytorch教程。在这个教程中,我向你展示如何使用pytorch autograd包自动梯度计算来优化我们的模型的具体例子。因此,我们从零开始实现线性回归算法,在每一步中都手动进行。因此,我们实现计算模型预测和损失函数的方程。

然后我们进行梯度的数值计算并实现公式。接着我们实现梯度下降算法来优化我们的参数。当这一切正常时,我们看到如何将手动计算的梯度替换为Pytorch的自动反向传播算法。😊所以这是第二步。在第三步中,我们在第三步。

我们通过使用Pytorch中的损失和优化类来替换手动计算的损失和参数更新。在最后一步中,我们通过实现一个pytorch模型替换了手动计算的模型预测。因此,当我们理解这些步骤时,Pytorch可以为我们做大部分工作。当然,我们仍然需要设计我们的模型,并且要知道应该使用哪个损失和优化器。

但我们不必再担心底层算法。因此,这个视频将涵盖步骤1和2。在下一个视频中,我们将看到步骤3和4。那么让我们开始。我假设你已经知道线性回归和梯度下降是如何工作的。如果不知道,请观看我关于这个算法的从零开始的机器学习教程。

因为现在我不会详细解释所有步骤。

但我把链接放在描述中了。因此我们现在从头开始做所有事情。我们只使用nuy。然后我们导入nuy的S和P,然后我们使用线性回归。我们使用一个仅仅进行一些权重与输入的线性组合的函数。这里我们不关心偏差。在我们的例子中,假设F等于2倍的x。

所以我们的权重必须是2。然后我们做一些训练样本。假设x等于numpy.dot.array。然后我们放一些测试或训练样本。假设是1、2、3和4。这将是numpy的。或者,让我们给它一个数据类型,比如说这是Nmpy.dot.float32。然后,我们也想要一个y。因为我们的公式是,这就是2x。

我们必须将每个值乘以2。因此是2、4、6和8。现在我们初始化我们的权重。我们简单地说w在开始时等于0。现在我们必须计算我们的模型预测。同时我们也要计算损失。然后我们要计算梯度。现在我们手动执行每一个步骤。那么我们定义一个函数,我们称之为forward。

这是一个遵循pytorch约定的前向传播,将获取x。然后我们的模型输出仅仅是w乘以x。这是前向传播。现在,损失。这里我们定义损失函数,它依赖于y和预测的y。所以,这是模型输出。现在在这种情况下。

这是或损失等于线性回归情况下的均方误差。我们可以通过说,这是。嗯。假设y预测减去y。然后平方。然后我们进行平均操作。所以这是损失。现在我们手动计算损失相对于我们参数的梯度。

让我们来看看均方误差。公式是1除以n,因为这是平均值。然后我们有我们的w乘以x,我们的预测减去实际值的平方。现在如果你想要导数。那么这个导数,让我们称之为j或目标函数关于w等于1除以n,然后我们有两个乘以x。

然后乘以W乘以x减去y。所以这是数值计算的。计算出的导数。请自行仔细检查数学。现在我们实现这个。我们说定义梯度,它依赖于x和y以及预测的y。现在我们可以一行完成。我们返回numpy.dot。我们需要两个乘以x的点积。

然后这里我们有预测的y减去y。

说这是这里的公式。当然,我们还需要平均值。假设这是点平均。我们可以简单地在Ny中这样做。现在,这些是我们需要的东西。现在,让我们在训练之前打印我们的预测。所以我们打印。我们使用F字符串。所以训练之前的预测。假设我们想预测值5。

应该是10。在这里,我们可以在F字符串中做到。在这个表达式中我们可以调用这个forward方法,传入5。假设我们只想要三位小数。现在,让我们开始训练。我们定义一些参数。我们需要学习率,假设是0.01。

然后我们需要一个迭代次数。我们说its等于10。现在让我们进行训练循环。所以我们说对于epoch在范围内和iter。然后首先,我们进行预测,即前向传播。这是前向传播。我们可以简单地用我们的函数来完成这个。所以我们说y预测或y pre等于forward。

然后我们输入我们的大写x。现在我们想要损失。所以我们的损失L等于实际y的损失。和我们的预测y。现在,我们需要获取。梯度,即关于W的梯度。所以D W等于我们刚刚实现的梯度函数,依赖于x和y以及预测的y。

现在我们必须更新我们的权重。是的,所以梯度下降算法中的更新公式就是我们朝着梯度的负方向前进。所以是负x。在这里,步长或所谓的学习率乘以我们的梯度。

所以这是更新公式。然后我们假设我们还想在这里打印一些信息。所以我们说如果epoch取模,假设这里为1,因为我们想在每一步打印。如果这是0。我们想打印,比如说。我们想打印epoch。在这里我们打印epoch加1。然后我们想得到权重,即。权重。W,保留三位小数。

然后我们还想要有损失。损失等于。损失。在这里我们说,点。8。就这样。然后在最后。我们想在训练后打印预测。所以,现在。让我们预测。预测并打印预测。在训练后。是的,那么。现在。让我们运行这个,看看会发生什么。一切应该都能正常工作。现在,是的。

在我们的训练之前,预测为0。然后对于每一步。记住我们的公式应该是2倍的x。所以我们的w一开始应该是2。我们看到每个训练步骤都在增加我们的权重,并且减少我们的损失。因此,每一步都会变得更好。训练后,我们的模型预测为9.999。

所以快到了。我们举个例子,现在我们想要更多的迭代。假设我们只进行了10次迭代,这并不多。现在,如果我们运行这个,并且每隔一步打印一次。然后我们看到,最后我们的损失是0,预测是正确的。现在,这是我们手动实现的部分。

现在让我们替换梯度计算。所以我们选择所有这些并将其复制到一个单独的文件中。现在我们不再使用numpy了。所以现在我们只需导入torch,并使用torch来完成所有工作。当然,我们现在想要去掉的是这个梯度,即手动计算的梯度。因此我们简单地删除它。我们不再需要这个。现在我们也没有nuy数组了。

所以现在这是一个Torch dot Tzar。我们的数据类型现在是torch dot float 32,y也是如此。它现在是一个Torch dot Tensor,并且数据类型来自torch模块。但其他一切在这里都是一样的。因此,语法相同。现在我们的W也必须是一个张量。所以我们说这是一开始为0.0的torch dot tensor。它也会有一个数据类型。

说是torch dot float 32。由于我们对损失关于这个参数的梯度感兴趣,我们需要指定这需要梯度计算。所以requires grad = true。

现在,前向函数和损失函数仍然相同,因为我们可以在 pytorrch 中使用相同的语法。 现在,在我们的训练循环中,前向传播仍然相同。 损失是相同的。 现在梯度等于反向传播。 所以记住,在反向传播中,我们首先进行前向传播。 这就是我们使用这种语法的原因。 然后再进行梯度计算。

我们使用反向传播。 所以这里我们简单地调用 L dot。Backward。这样就会计算我们损失对 W 的梯度。 所以 Pyto 为我们完成所有计算。 现在我们更新我们的权重。 但在这里我们要小心。 我在关于 auto gridd 包的教程中解释过这一点。

因为我们不希望这个操作成为我们梯度追踪图的一部分。 所以这不应成为计算图的一部分。 我们需要用 torch dot。no gr 语句将其包装。 还有一件我们也应该知道的事情。 我也已经谈到过,我们必须再次清空或置零梯度。

因为每当我们调用 backward 时,它会写入我们的 Grads,并将其累积在 W dot Gr 属性中。 所以在下一次迭代之前,我们要确保我们的梯度再次为 0。 所以我们可以说 w times gra times 0 underscore。 这样将就地修改它。 现在,我们完成了。

现在让我们运行这个,看看它是否有效。 W 还未定义。 哦,是的,当然。 现在是 W dot gra。 让我们再试一次。 现在它工作正常。 现在我们也看到它会增加我们的 W,并且会减少我们的损失。 这里我们说我们有 20 次迭代。 但这并不完全正确。

这是因为反向传播并不像数值梯度计算那样精确。 所以让我们在这里尝试更多的迭代。 假设我们想要 100 次迭代,并在每 10 步时打印我们的更新。 所以让我们再试一次。 现在我们看到训练完成后,我们有了正确的预测。 所以,没错,这就是本视频的内容。 在下一个视频中。

我们将在这里继续,将手动计算的损失和权重更新替换为 Pytorch 的损失和优化器类。 如果你喜欢这个视频,请订阅频道,下次见,再见!

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P6:L6- 训练管道:模型、损失和优化器 - ShowMeAI - BV12m4y1S7ix

大家好。欢迎回到新的 PyTorch 教程。在上一个教程中,我们从头实现了逻辑回归,然后学习了如何使用 Pyt 来计算梯度,现在,我们将继续之前的内容。现在我们要用 PyTorch 中的损失和优化器类替代手动计算的损失和参数更新。😊然后我们还通过实现一个 PyTorch 模型替换了手动计算的模型预测。

然后 PyTorch 可以为我们完成整个管道。所以这个视频涵盖了步骤 3 和 4。请先观看之前的教程以了解步骤 1 和 2。那么现在让我们开始吧!

首先,我想谈谈 PyTorch 中的一般训练管道。通常,我们有三个步骤。第一步是设计我们的模型。我们设计输入和输出的数量,即输入大小和输出大小。然后,我们还设计了前向传播及所有不同的操作或不同的层。

然后作为第二步,我们设计或构建损失和优化器,最后一步是进行训练循环。这是训练循环。我们从前向传播开始。这里我们计算,或者让我们写下来。计算预测。然后我们进行反向传播,获取梯度。

PyTorch 可以为我们做一切。我们只需定义或设计我们的模型。然后在获得梯度后,我们可以更新权重。现在我们更新权重,然后迭代几次直到完成。这就是整个管道。现在让我们继续,替换损失和优化。

我们导入神经网络模块,因此我们导入 torch dot N N S 和 N,以便可以使用其中的一些函数。现在我们不再想手动定义损失,所以可以简单地删除这一部分。在我们训练之前,我们仍需要定义我们的损失。因此我们可以说损失等于。这里可以使用 PyTorch 提供的损失。所以我们可以说 N N dot M E loss。

这正是我们之前实现的。所以这是均方误差。这是一个可调用的函数。然后我们还想从 p chargech 获取一个优化器。所以我们说 optr 等于 torch dot optim 来自优化模块,然后在这里我们使用 S GD,代表随机梯度下降,需要一些参数。

一些需要优化的参数,并且它将需要作为列表。因此我们把 W 放在这里。然后它还需要 Lr,即学习率,具体是。

我们之前定义的学习率。

然后在我们的训练循环中。损失计算现在仍然是一样的,因为这是一个可调用的函数,它获取实际的 y 和预测的 y。然后我们不再需要手动更新我们的权重,因此我们可以简单地说 optr.dot.step。

这将进行一次优化步骤。然后我们在优化步骤之后仍然需要清空我们的梯度。因此我们可以说 optimizer.dot0.gra。现在我们完成了步骤 3。让我们运行这个看看是否有效。嗯,所以,是的,仍然有效。我们的预测在训练后是不错的。让我们继续进行步骤 4,并用 pytorch 模型替换我们手动实现的前向方法。

所以,对于这个,我们也不再需要我们的权重,因为我们的模型已经知道了参数。所以在这里我们说 model 等于 N N.dot.linear。通常我们需要自己设计这个。但由于这对于线性回归来说非常简单。这只有一层,这在 pytorch 中已经提供了。所以这是 N N.dot.linear。

这需要我们特征的输入大小和输出大小。为此,我们需要做一些修改。因此,现在我们的 X 和 y 需要有不同的形状。因此这必须是一个二维数组,现在行数是样本的数量。每行对应特征数量。因此这个有一个新形状。抱歉。

新形状看起来像这样。y 的形状也是一样的,所以是 2、4、6 和 8。所以现在让我们获取形状。所以是 y。我现在得小心。所以我们可以说样本数量和特征数量等于 x.dot.shape。现在让我们打印这个。所以打印样本数量和特征数量。现在让我们运行这个。

这会导致一个错误。但我想我们可以做到这一点。所以形状现在是 4×1。我们有四个样本,每个样本一个特征。现在我们定义我们的模型。这需要一个输入和一个输出大小。输入大小等于特征的数量,输出大小仍然是一样的。所以这也是特征的数量。

所以这是一个输入大小和一个输出大小。现在我们需要把这个给我们的模型。所以我们在这里说输入大小。

输出大小。

然后再一次,当我们想要获取预测时。我们可以简单地说我们可以调用模型。但现在这不能是一个浮点值。因此这必须是一个张量。让我们创建一个测试张量。假设 X.Test 等于 torch.dot.Tensor,它只获取一个样本,值为 5。然后它的数据类型为 torch.dot.float32。然后在这里我们传递测试样本。

由于这个只有一个值,我们可以调用点项目来获取实际的浮点值。所以现在让我们把这段复制粘贴到这里。嗯。现在我们还需要修改我们的优化器。因此现在我们没有权重。所以这个列表中包含参数,我们可以简单地说 model.dot。

Terrameter,并调用这个函数。现在在这里,对于预测,我们也简单地调用模型。

现在我们完成了。所以现在我们正在使用pieytor模型来获得这个。此外在这里,如果我们想再次打印它们,我们必须解包它们。所以我们说W和一个可选的偏置等于模型参数。这将解包它们。如果我们想打印实际的,这将是一个列表的列表。

所以让我们用这个获取第一个或实际的第一个权重,我们也可以调用这个项目,因为我们不想看到张量。现在我觉得我们完成了。所以让我们运行这个,看看它是否有效。是的,最终输出并不完美。这可能是因为初始化现在是随机的。此外,这个优化技术可能有点不同。所以你可能想要尝试一下。

尝试一下学习率和迭代次数。但基本上,它有效。随着每一步,它变得越来越好。是的,所以这就是我们如何构建整个训练管道。还有一件事。在这种情况下,我们不必自己提出模型。所以在这里我们只有一层。

这已经在Pytorch中提供了。但假设我们需要一个自定义模型。让我们写一个自定义的线性回归模型。然后我们必须从N,N.dot.module派生。这将得到一个初始化的方法。它有self,并获取输入维度和输出维度。

然后在这里我们调用super,超类。所以线性回归的super和self。然后点。

在这里,这就是我们如何调用超类。我们会定义我们的层。所以在这种情况下,我们说我们的self.dot线性层等于Nn.dot.linear。这将获取输入维度和输出维度,然后我们将它们存储在这里。然后我们还必须在我们的模型类中实现前向传递,所以self和x。

在这里我们可以简单地返回self.dot.linear的x。

这就是整个内容。现在我们可以说我们的模型等同于线性回归,输入大小和输出大小。现在这将做同样的事情。所以现在这只是一个虚拟示例,因为这是一个简单的包装器,它将完全相同。但基本上,这就是我们设计pieyto模型的方式。所以现在让我们注释掉这个,使用这个类来看看它是否有效。

是的,所以它仍然有效。现在就这些。现在,Pyto可以为我们完成大部分工作。当然,我们仍然需要设计我们的模型,并且需要知道我们想要使用哪个损失和优化器,但我们不必再担心底层算法了。所以,你可以在Giub上找到所有代码。如果你喜欢这个。

请订阅频道,下一次见,拜拜。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P7:L7- 线性回归 - ShowMeAI - BV12m4y1S7ix

嗨,大家好。欢迎回到新的Pytarch教程。这一次,我们实现线性回归。所以我们已经在前几个教程中逐步实现了这个。这应该是一个重复的过程,让我们可以应用所有学到的概念,并迅速再次实现我们的算法。😊如我之前所示,我们典型的pyytorch管道由这三个步骤组成。首先。

我们设计我们的模型。所以我们定义输入和输出大小,然后进行前向传播。接着我们创建我们的损失和优化器函数。然后我们执行实际的训练循环,包括前向传播、后向传播和权重更新。让我们来做这个。首先,我们导入一些需要的内容。所以我们导入torch。

然后我们导入torch点和N S和N。也就是神经网络模块。然后我们导入nuy S和P以进行一些数据转换。然后从S K learn中导入数据集。我们想生成一个回归数据集。然后我们稍后也想绘制这个。所以我说导入matplot clip的pie plot作为P LT。

然后我们进行我们的三个步骤。所以我们设计模型,第一步。然后第二步,我们定义损失和优化器。最后第三步,我们的训练循环。让我们来做这个。首先,我们做一个步骤0,准备我们的数据。所以准备数据。让我们生成一个回归数据集。我们可以通过说让我们称这个为x nuy和y nuy来实现。

然后我们可以使用数据集点make regression。获取,假设100个样本。所以n samples等于100。在这个例子中只需要一个特征。所以n features等于1。然后我们添加一些噪声。我们还要设置一个随机状态。假设这个是1。

然后我们想把这个转换为一个torch张量。所以我们说x等于。然后我们可以使用函数torch从numy中提取。然后我们说x点。X下划线nuy。但我们想在此之前将其转换为一个float 32数据类型。所以现在这是一个双精度数据类型。如果我们在这里使用双精度。

然后我们稍后会遇到一些错误。所以我们只需通过说S类型,然后说nuy点float 32来转换,并且对我们的y做同样的事情。所以我们说y等于从我们的nuy数组转换的torch张量。现在我们还要重塑我们的y。因为现在它只有一行,我们想把它变成列向量。我们希望将每个值放在一行中,整个形状只有一列。

让我们说y等于y点view。在这里我们放入新的大小,所以y点shape0。所以值的数量。然后只需要一列。

所以这个方法是一个内置的PyTorch方法,将重新调整我们的tensor。然后通过说x.shape来获取样本数量和特征数量。这样我们就可以在稍后使用。现在让我们进行三步操作。现在我们有了数据。现在我们定义模型。在线性回归的情况下,这只是一个层。我们的。

因此,我们可以使用内置的线性模型。我们说model = NN.Linear

这是线性层,它需要我们特征的输入大小和输出大小。所以假设输入大小等于。这是我们拥有的特征数量。在我们的示例中,这仅为1。输出大小等于1。所以我们只想为每个样本生成一个值。

现在我们的模型得到了输入和输出的大小,输入大小和输出大小。

这就是我们设置模型所需做的全部。现在让我们继续处理损失和优化器。所以我们称之为criterion

在这里,我们可以使用Pytorch内置的损失函数。在线性回归的情况下,这就是均方误差。所以我们可以说这是NN.MSELoss。这样就会计算均方误差。这是一个可调用的函数。然后我们还设置优化器。所以我们说,optimizer = ...

假设我们使用torch.optim.SGD。这就是随机梯度下降。我们的优化器需要优化的参数。所以这里我们可以简单地说这是model.parameters。然后它需要一个学习率。我们在这里定义为一个变量。假设学习率等于0.01

然后lr = learning rate

这是第二步。现在让我们进行训练循环。首先,定义一下迭代的次数。假设我们想进行100次训练迭代。然后,

range(epochs)中进行循环。现在在训练循环中执行我们的步骤,前向传播,反向传播和权重更新。

所以首先我们做前向传播以及这里的损失。然后是反向传播。然后是更新。前向传播和这里的损失,我们可以说,为什么预测它。

等于,然后我们调用我们的模型。作为数据,它获取x。这就是前向传播。然后我们通过说loss = ...来计算损失。

这是我们的criterion

这需要实际标签和预测值。那么为什么要预测呢?

在反向传播中计算梯度时,我们只需说 lost dot backward。这将进行反向传播并为我们计算梯度。然后我们在这里的更新,只需说 optimizer dot step。这将更新权重。在下一次迭代之前,我们必须小心,因此我们必须现在清空梯度。

因为每当我们调用 backward 函数时,这将把梯度累加到 dot Gr 属性中。所以现在我们想再次清空这个。我们简单地说 optimizer dot 0 gra。所以你永远不要忘记这个。

然后我们完成了训练循环。让我们打印一些信息。假设如果 Epoch plus 1 modular1s 等于 0。每第 10 步,我们想打印一些信息。所以让我们打印 epoch。这里我们说 epoch plus one。让我们也打印损失,损失等于。我们可以说 loss dot item。然后让我们格式化这个。

所以让我们只绘制或打印小数值。🤢,现在我们完成了。现在我们也来绘制这个。我们来说,获取所有的预测值,称为 predicted。现在我们调用我们的最终模型,model X。带着所有的数据。现在我们想把它转换回 nu pipe,但在此之前。

我们想要分离我们的 tenzo,以防止此操作被跟踪在我们的图形和计算图中。因为现在,这个 tenzo。这里我有个错别字预测了。所以这个 tenzo 需要梯度参数设置为 true。但现在我们希望它变为 false。这样将生成一个新的 tenzo,其中我们的梯度计算属性为 false。

这是我们的新 tenzo。然后我们调用 numpy 函数。现在我们将其转换为 numpy,并绘制这个。所以我们先绘制所有的数据。所以,x nuy 和 y nuy。我们希望将其绘制为红点。然后我们希望绘制我们的生成或近似函数。所以说 P,L T dot plot。

在 X 轴上是 X nuy,Y 轴上是我们的预测标签。让我们用蓝色绘制这个。然后我们说 P L T dot show。现在让我们运行这个,希望一切都是正确的。

现在这个图出现了。我们看到这条线很好地近似了我们的数据,我们看到这个是有效的。

是的,现在我们完成了。希望你喜欢这个。如果你喜欢,请订阅频道,下次见,再见。😊。

PyTorch 极简实战教程!全程代码讲解,在实践中掌握深度学习&搭建全pipeline!<实战教程系列> - P8:L8- 逻辑回归 - ShowMeAI - BV12m4y1S7ix

大家好,欢迎回到新的Pytorch教程。这次,我们实现逻辑回归。如果你看过之前的教程,那现在应该非常简单。再次,我们实现我们的典型Pytorch管道,包含这三个步骤。所以首先,我们建立我们的模型。我们定义输入和输出大小以及前向传播。

然后我们创建损失和优化器函数。然后我们进行实际的训练循环,包括前向传播、反向传播和权重更新。😊这里的代码应该与上一个教程中实现线性回归的代码非常相似。我们只需要对模型和损失函数进行稍微调整。

所以我们在模型中增加一层,并选择一个不同的损失函数来自Pytorch内置函数。首先,让我们导入一些我们需要的东西。我们导入torch,当然,还有torch点nn作为n。所以神经网络模块。然后我们导入Numpy来进行一些数据转换。然后从Sklearn。

我们导入数据集来加载一个二分类数据集。然后从Sklearn点预处理。我们想导入标准缩放器,因为我们想对特征进行缩放。然后从Sklearn点模型选择,我们导入训练测试拆分,因为我们希望对训练和测试数据进行分离。现在让我们进行我们的三个步骤。所以首先,我们想建立模型。

然后我们想建立损失和优化器。然后在第三步中,我们进行实际的训练循环。作为第0步。我们想准备数据。让我们这样做。让我们从Sklearn加载乳腺癌数据集,所以我们可以说B等于数据集点加载乳腺癌。这是一个二分类问题,我们可以根据输入特征预测癌症。

所以假设X和Y等于B点数据和B点目标。然后我们想说,哦,首先,让我们通过说这是来获取样本数量和特征数量。X点形状。

所以让我们先打印这个,打印样本数量和特征数量,看看我们的数据集长什么样。

我们看到我们有569个样本和30个不同的特征。这里有很多特征。现在让我们继续。当我们说X训练和X测试,以及X测试和Y训练和Y测试等于这里时,我们可以使用训练测试拆分函数,将X和Y放入其中。

我们想进行测试。大小。

为了达到20%。所以这是02。

让我们还给这个一个随机状态,等于,假设是1,2,3,4。

应该有一个小S。现在让我们转换。或者,首先。现在我们想要缩放我们的特征。Sc它们。在这里,我们设置一个标准的标量S C等于标准标量。这将使我们的特征具有零均值和单位方差。这在处理逻辑回归时总是推荐的。

现在我们对数据进行缩放,所以我们说x train等于sc dot fit transform。然后作为输入我们放入x train。接着我们希望对测试数据做同样的事情。所以我们说x test等于SC dot,这里我们只进行转换。嗯。我们在这里放入X test。现在。我们缩放了我们的数据。现在我们想把它转换为torch tenzoos。所以假设x train。

等于torch dot。这里我们可以使用nuy的函数。然后我们放入x train并将其转换为flow 32数据类型。所以我们说x train dot S。类型。Numpy dot float 32。因为现在,这的类型是double。然后我们会在以后的某些错误中遇到问题。所以我们将其转换为tenor。

现在让我们对所有其他数组执行此操作。所以假设x。

Test。等于。这。还有我们的Y train。还有,我们的y test tenzon。W test。现在,准备数据的最后一步是重塑我们的y。Tenzo。所以Y train等于Y train dot V。这是Pytorarch的内置函数,将根据给定的大小重塑我们的Tzo。所以它获取大小。Y train。

那个形状,0。

只有一个。所以现在,我们的y只有一行,我们希望把它变成列向量。所以我们希望将每个值放在一行中,只有一列。所以这将完全做到这一点。也适用于我们的y test。所以Y test等于这个y test。

现在,我们正在。

我认为我们已经完成了数据准备。所以现在让我们建立我们的模型。在这里,我们的模型是权重和偏差的线性组合。在逻辑回归的情况下,我们在最后应用一个sigmoid函数。所以让我们这样做。为此,我们想编写自己的类。所以我们称之为模型。

或者我们也可以称之为逻辑回归。Chatic。回归。这必须从N和dot模块派生。然后这将得到一个init。它有self。然后它获取输入的数量。特征。这里,首先,我们调用super init。所以我们说super。

逻辑回归和self dot init。

然后我们定义我们的层。所以我们只有一层self dot linear等于。这里我们可以使用内置的layer N N dot linear。这将获取输入大小。所以输入特征。而输出大小只有一个。所以我们只想在最后得到一个值,一个类别标签。

然后我们还必须在这里实现前向传播,其中包含self和数据。我们的前向传播首先是应用线性层,然后是sigmoid函数。所以这里我们说为什么预测它。等于torch.sitete。

所以这也是我们可以使用的构建和功能。这里我们应用线性层。将线性层与我们的数据X相结合,然后返回我们的y预测。

所以这是我们的模型。现在让我们创建这个。所以model等于大小的logistic regression。在这里我们输入我们拥有的特征数量。所以现在我们的层大小为30乘1。

而且。不好意思,30个输入特征和一个输出特征。

现在我们有了我们的模型。现在我们可以继续进行损失和优化器。因此,对于损失,损失函数现在与线性回归情况下不同。这里我们说criterion等于N.N.B.E loss。所以这里是二元交叉熵损失。我们的优化器是一样的。所以这可以是。嗯。这是torch.optim.SGD,用于随机梯度下降。

这获取一些我们想要优化的参数。所以这里我们只说model.dot parameters。同时也需要一个学习率。我们说。

学习率等于0.01。然后这里我们说LR等于学习率。这是步骤2,现在是步骤3。我们定义一些训练周期,等于,比如说100次迭代。现在我们进行训练循环。所以现在我们进行四个周期。在范围内的训练周期中。然后首先,我们进行前向传播和损失计算。

然后我们进行反向传播,然后进行更新。所以我们说y预测等于这里我们调用我们的模型,作为theta,它获取x训练。然后我们说loss等于criterion,这将获取y预测和实际y训练。所以训练样本或训练标签。

现在我们进行反向传播并计算梯度,再次。我们只需调用loss.dot.backward,Pytorch会为我们完成所有的计算。现在我们更新权重。所以这里我们只需说optimizer.dot.step。再一次,Pytorch会为我们完成所有的更新计算。

然后我们不,或者说,我们绝不能忘记再次清空我们的梯度,所以。想要设置梯度为 0。因为这里的反向函数将始终将所有梯度相加到 dot_grad 属性中。所以在下一次迭代之前,我们需要再次清空它们。我们只需说 optimizer.zero_grad()。然后,让我们也打印一些信息,如果 epoch + 1 % 10 == 0

因此每十个步骤,我们想打印一些信息。让我们在这里使用一个格式化字符串。假设是 epoch。在这里我们可以使用 epoch + 1。然后我们还想查看损失。因此损失等于 loss.item()。让我们格式化为只打印四个小数位。好吧,现在我们完成了。这是我们的逻辑回归实现。

现在让我们评估我们的模型。因此,评估不应该是我们想要跟踪历史的计算图的一部分。我们想要使用 torch.no_grad()

然后在这里进行评估。所以我想得到准确率。让我们从测试样本中获取所有预测类别。假设这是模型,并且在这里我们放入 X_test

然后让我们将其转换为类别标签。所以 0 或 1。所以记住,这里的 sigmoid 函数将返回一个介于 0 和 1 之间的值。

而且,如果这个值大于 0.5,我们说这是类别 1。否则就是类别 0。所以假设 y_predicted_classes = y_predicted.round()。这里我们可以再次使用构建函数。这将正好做到这一点。如果我们不使用这个语句,那么这将是计算图的一部分。

它将为我们跟踪梯度计算。因此我们不想这样。我们不需要这样,因为我们已经完成了。这就是我们在这里使用 with 语句的原因。现在让我们通过 act = y_predicted_classes 计算准确率。在这里我们可以调用 equal 函数,等于 y_test,然后对其求和。因此我们想对其求和。

对于每个正确的预测,我们会加一。然后我们将其除以测试样本的数量。所以为什么使用 test.shape[0]。这将返回测试样本的数量,然后让我们打印我们的准确率。

准确率等于。嗯,ac:.4f,也只显示小数位。现在让我们运行这个,希望一切都是正确的。

而且,标准缩放器没有属性 transform。因此我这里有一个拼写错误。

转换。现在,让我们再运行一次。转换。再试一次。现在完成了,我们的准确率是089。所以还可以,挺好的,但不是完美的。你可能想要调整一下,比如迭代次数。我们在哪里设置的呢?

例如,周期数或学习率。或者也许在这里尝试不同的优化器。基本上,这就是我们如何实现逻辑回归。我希望你喜欢。如果喜欢,请订阅频道,我们下次见,再见。

posted @ 2024-10-15 03:47  绝不原创的飞龙  阅读(49)  评论(0)    收藏  举报