哈佛-CS50-计算机科学导论笔记-四-

哈佛 CS50 计算机科学导论笔记(四)

哈佛CS50-AI | Python人工智能入门(2020·完整版) - P15:L4- 模型学习 2 (回归,损失函数,过拟合,正则化,强化学习,sklearn) - ShowMeAI - BV1AQ4y1y7wy

并不是降雨的真实与否,而有时我们要预测的是一个实数值,对此我们有一个相关问题,不是分类,而是称为回归,回归是监督学习问题,我们尝试学习一个将输入映射到输出的函数。

但不同的是,输出不再是离散类别,如降雨或不降雨,而在回归问题中,输出值通常是连续值,一些我们希望预测的实数,这种情况时常发生,你可能想象公司会采取这种方法。

例如,试图弄清楚广告的有效性。广告支出如何转化为公司产品的销售。例如,他们可能想尝试预测一个函数,该函数将广告支出的金额作为输入。

在这里我们只使用一个输入,但你可以扩大到多个输入,如果你拥有多种不同类型的数据,目标是学习一个函数,给定这笔广告支出,我们将获得这个销售额。

你可能会根据过去每个月的数据来判断,这里是我们花在广告上的金额,这里是销售额,我们想预测某种假设函数,再次给定广告支出的金额,可以预测在这种情况下某个实数,预计的销售额。

这个公司本月或这个季度或其他时间单位要做的事情。我们选择的衡量方式,因此再次解决这个类型问题的方法。我们可以尝试使用线性回归的方法,在x轴上绘制这些数据,广告支出如前所述。

在y轴上是销售额,我们可能只是想画一条线,尽可能准确地估计广告与销售之间的关系,在这种情况下,与之前不同的是,我们不是尝试将数据点分为离散类别。

我们只是试图找出一条线,近似广告与销售之间的关系,这样如果我们想要弄清楚特定广告预算的预计销售额,你只需在这条线中查找,确定对于这个广告支出,我们会有这个销售额。

而是试图以这种方式进行估计,如果你可以试图画出一条线,再次弄清楚如何使用各种技术修改权重,以使这条线尽可能贴合。因此,所有这些方法都是为了尝试解决机器学习风格的问题。

问题变成了我们如何评估这些方法,如何评估我们可能提出的各种不同假设,因为这些算法会给我们某种假设,一个将输入映射到输出的函数,我们想知道这个函数的效果如何。

可以将评估这些假设并尝试得到更好假设的过程看作是一个优化问题,在优化问题中,我们以前提到过,我们要么试图通过寻找全局最大值来最大化某个目标函数,要么试图最小化某些成本。

通过尝试找到某个全局最小值,在评估这些假设的情况下,我们可以说这个成本函数是我们试图最小化的东西,我们可能试图最小化我们所称之为损失函数的东西,而损失函数是一个。

为我们估计我们的函数表现不佳的程度,更正式地说,这就像是效用损失,每当我们预测错误时,都会增加我们的损失函数的输出,而你可以提出任何你想要的损失函数,只要是某种数学方式。

对于每一个数据点,考虑到实际输出以及我们预测的输出,我们可以计算某种数值损失,但有几个流行的损失函数值得讨论,以便你之前见过它们。

当涉及到离散类别时,比如下雨或不下雨,假币或真币,我们接近于0,1损失函数,其工作方式是对每一个数据点,我们的损失函数以实际输出为输入,比如它是否真的在下雨。

考虑到预测,我们是否预测了在这个数据点下是下雨还是不下雨,如果实际值等于预测值,那么0,1损失函数就会说损失为0,因为我们能够正确预测,没有效用损失。

如果实际值与我们预测的值不相同,那么在这种情况下我们的损失为1,我们失去了一些效用,因为我们预测的函数输出并不是实际的值,那么在这种情况下的目标就是提出一个最小化损失的假设。

总的经验损失是我们损失的总量,如果将所有这些数据点的实际输出和我们的假设预测相加,就可以得到。在这种情况下,例如,如果我们回到将天分类为下雨或不下雨,我们得出了这个决策边界。

我们如何评估这个决策边界,它比在这里画线或在那里画线好多少呢?我们可以获取每个输入数据点,每个输入数据点都有一个标签,表明是否下雨,我们可以将其与预测进行比较。

我们预测它会下雨或不下雨,并为其分配一个数值。例如,这些点都是雨天,我们预测它们会下雨,因为它们位于线的下方,因此它们的损失为零,没有损失。

对于这些点来说,确实如此,例如在这里没有下雨,而我们预测也不会下雨,然而我们确实有损失,例如这里和那里这两个点,我们预测不会下雨,但实际上是一个蓝点,它在下雨,或者在这里。

预测它会下雨,但实际上是一个红点,它没有下雨,因此我们错误分类了这些我们试图训练的数据点,因此这里有一些损失,例如这里一个,那里一个,总损失为四,例如在这种情况下。

我们如何估计或说这条线比另一条线更好,或者在更远处的对齐,因为这条线可能最小化损失,所以如果你只是通过我们的空间画一条直线,无法比这四个损失点做得更好。

1 损失函数检查我们是否做对了,如果做对了,损失为零,没有损失;如果做错了,那么我们的损失函数对该数据点的值为1,我们将所有数据点的损失相加,得到某种经验损失,表示我们损失了多少。

在所有这些原始数据点中,我们的算法可以访问到其他形式的损失,当我们处理更多实值案例时,尤其有效,例如广告预算与销售额之间的映射,因为在这种情况下,你不仅关心。

你可能并不在乎数字完全准确,而是关心你离实际值有多近。如果实际销售额是$2,800,而你预测的是$2,900,或许这还不错;这比你预测$1,000的销售额要好得多。

例如,我们希望我们的损失函数能够考虑到这一点,不仅考虑实际值与预期值是否完全相同,还要考虑它们之间的差距,因此对于这个,我们采用我们所称的L1。

l1损失不仅仅看实际值和预测值是否相等,而是取实际值减去预测值的绝对值,换句话说,我们只是在问实际值和预测值之间的距离有多远,并将所有数据点的损失加起来。

这样我们就能得出最终的答案。那么,对于我们的数据集,这可能是什么样子呢?如果我们回到这个表示,其中x轴是广告支出,y轴是销售额,我们的线是我们对于给定广告支出量的预测。

我们的l1损失就是在销售轴上,预测值与每个数据点之间的垂直距离。这样我们就可以准确地计算出预测值与每个数据点之间的距离,并因此得出这个特定假设的总体损失。

通过将所有这些不同的数据点的个别损失加起来,我们的目标是尽量最小化这些损失,试图找到一条线,使得通过判断我们预测的销售额与实际销售额的差距来最小化效用损失。

结果表明还有其他损失函数,其中一种非常流行的是l2损失。l2损失不仅仅使用绝对值来衡量实际值与预测值之间的距离,而是使用实际值减去预测值的平方,即实际值和预测值之间的差距。

它有效地平方了该值,严厉惩罚任何更差的预测。想象一下,如果你有两个数据点,你预测的值与它们的实际值相差很远,而不是一个数据点与其实际值相差不远。

l2损失函数会更严厉地惩罚与实际值相差较远的预测,因为它会平方实际值和预测值之间的差异,根据具体情况,你可能想选择某个损失函数,这取决于你最关心的最小化目标。

如果你真的想在更多异常值的情况下最小化误差,你可能想考虑类似的情况,但如果你有很多异常值,并且并不一定关心对它们建模,那么l1损失函数可能更可取,但在这里有一些权衡,你需要根据具体情况做出决定。

针对特定数据集,你确实面临的风险是任何这些损失函数都可能导致一个叫做过拟合的问题,过拟合是机器学习中的一个重大问题,每当模型过于复杂以至于无法泛化到新数据时就会发生。

该边界与数据集的拟合不太紧密,因此可能无法很好地进行推广。我们希望我们的模型能够准确预测数据及输入输出对。我们想这么做的原因是希望我们的模型能够很好地推广到我们未见过的数据。

我想利用过去一年是否下雨的数据来进行训练,并利用这些数据进行未来的推断,以判断将来是否会下雨。或者如果我有大量关于假币和真币的样本数据的话。

我希望训练一台计算机,使其在未来能够推广到我可能看到的其他钞票上。而过拟合的问题在于,如果你过于紧密地绑定于训练数据集,你最终可能无法很好地进行推广。那么这又是什么意思呢?

看起来我们可以想象一个下雨天和非下雨天的例子。从这里,蓝点表示下雨天,而红点表示非下雨天。我们决定感到相当舒适,可以画一条这样的线作为下雨天和非下雨天之间的决策边界。

对于非下雨天,我们可以相当自信地说,位于这一侧的点更可能是下雨天,而位于另一侧的点则更可能是非下雨天。但在这种情况下,经验损失并不是零,因为我们没有完美地对所有情况进行分类,这其中有一个异常值。

尽管那天并没有下雨,但我们的模型仍然预测会下雨。但这并不一定意味着我们的模型很差,只是意味着模型并不是100%准确。如果你真的想找到一个能最小化损失的假设,你可以提出一个不同的决策边界。

这可能是一条线,但它看起来会像这样。这条决策边界确实将所有红点与所有蓝点分开,因为红点位于这条决策边界的一侧,而蓝点则位于决策边界的另一侧,但我们可能会这样认为。

尽管基于我们训练这个机器学习模型所拥有的所有可用训练数据,它的预测似乎更准确,但它的预测效果却不如人意。我们可能会说,它可能无法很好地推广。如果还有其他数据点,比如在这里或那里,我们可能仍然想考虑这些点为下雨天,因为我们认为这可能只是一个异常值。

因此,如果你关心的唯一事情是最小化你拥有的数据上的损失,你就会面临过拟合的风险。这种情况可能发生在分类问题中,也可能发生在回归问题中。

我们预测了我们认为广告与销售之间有一个相当不错的关系,试图预测给定广告量的销售情况,但我可以得出一条更好地预测训练数据的线,它可能看起来像这样。

只是,你知道,连接所有不同的数据点,现在根本没有损失。现在我已完美预测了在任何广告下的销售情况,并且对于我所有可用的数据,它会是准确的,但它可能不太会很好泛化。我已经对训练数据过拟合了我的模型。

我可用的数据,因此一般来说,我们希望避免过拟合,我们希望有策略确保我们没有将模型过拟合到特定数据集。有几种方法可以尝试做到这一点,其中一种方法是检查我们在优化中所优化的内容。

问题是我们只是说,存在某种成本,我想要最小化该成本,到目前为止我们已定义了该成本函数,即假设的成本等于该假设的经验损失,即实际数据点的输出与我预测的输出之间的距离。

要基于该特定假设,如果你所做的只是最小化成本,也就是说在这种情况下最小化损失,那么结果可能是你可能会过拟合,为了最小化成本,你会尝试找到一种方法来完美匹配所有输入数据,这可能会发生。

由于在特定输入数据上过拟合,因此为了解决这个问题,你可以在成本函数中添加一些内容,什么算作成本,不仅仅是损失,还有假设复杂性的某种衡量标准。假设的复杂性是我们在考虑整体成本时需要考虑的内容。

需要定义你知道我们的线看起来多复杂,这是一种奥卡姆剃刀风格的方法,我们希望优先考虑更简单的决策边界,比如一条直线,举个例子,某些更简单的曲线,而不是某些更复杂的东西。

训练数据可能更好,但我们通常会说它可能不够泛化。一个更简单的解决方案可能是更好的解决方案,更有可能在其他输入上良好泛化,所以我们衡量损失是什么,但我们也衡量复杂性,现在这一切都被考虑进来了。

是的,某些东西可能在更好地预测训练数据时具有更少的损失,但如果它复杂得多,它仍然可能不是我们拥有的最佳选项,我们需要在损失和复杂性之间找到一些平衡,因此你会发现。

通常将其表示为,将复杂性乘以某个我们必须选择的参数。在这种情况下的参数 lambda,我们说如果 lambda 的值更大,我们确实想要对更复杂的假设施加更多惩罚。相反,如果 lambda 较小,我们将对更复杂的假设施加较少惩罚。

这有点取决于机器学习程序员决定他们希望在哪里设置 lambda 的值,以便决定我想对一个可能更好地拟合数据的更复杂假设施加多少惩罚。再一次,这些问题没有一个正确的答案,这取决于数据集。

根据你可用的数据和你要解决的问题,这些参数的选择可能会有所不同,你可能需要稍微实验一下,以找出最终合适的选择。这一过程不仅考虑损失,还考虑某种复杂性的衡量。

复杂性被称为正则化,正则化是对更复杂的假设施加惩罚的过程,以偏向于更简单的假设,后者更可能很好地进行泛化,更有可能应用于处理其他输入点的其他情况,而不是我们已知的。

通常没有见过,所以我们常常会在我们试图最小化的内容中添加一些正则化项,以避免过拟合的问题。确保不发生过拟合的另一种方法是进行一些实验,以查看我们是否能够对我们的模型进行泛化。

我们创建的模型在其他数据集上的表现,因此,当你进行机器学习实验时,通常你有一些数据,并且你想尝试创建一个函数,根据某些输入预测输出时,你不一定希望在。

你可用的所有数据可以使用一种称为留出交叉验证的方法。在留出交叉验证中,我们将数据分为训练集和测试集。训练集是我们将用于训练机器的数据集。

学习模型,而测试集是我们将用于测试我们机器学习模型实际表现的数据集。因此,学习发生在训练集上,我们确定参数应该是什么,找出正确的模型,然后我们看看。

现在我们已经训练了模型,看看它在预测事物方面的表现如何,并且在测试集中,某些数据集是我们之前没有见过的。希望是,我们能够很好地预测测试集,如果我们能够基于训练数据进行泛化。

如果我们对训练数据过拟合而无法很好地泛化,当我们查看测试集时,通常情况是我们在测试集上无法有效预测,因此这是验证模型泛化能力的一种交叉验证方法。

确保我们所做的工作能够推广到其他数据集上,还有其他统计技术可以使用。其中一个缺点是,如果你仅仅将数据以50/50分割,使用50%的数据进行训练,而使用另一半进行测试。

50% 或者你也可以选择其他百分比,因为有相当多的数据我现在没有用来训练,可能因此能够得到一个更好的模型。例如,一种方法被称为k折交叉验证。在k折交叉验证中,与其将数据仅分为两组并运行其中一个...

实验中我们将数据分为K个不同的集合,可能我将数据分为10个不同的集合,然后运行十个不同的实验。如果我将数据分成十个不同的数据集合,那么我每次在十个实验中将保留其中一个数据集合。

说让我训练我的模型和这9个集合,然后测试它对第10个的预测效果如何,再选择另一组9个集合进行训练,然后在我保留的那个集合上测试,每次我都在所有数据上训练模型——我保留的那一组,然后测试效果如何。

我们的模型在我保留的测试集上的表现如何,最终得到的是十个不同的结果,十个不同的答案,显示我们的模型的准确性,通常你可以取这十个结果的平均值来估算我们认为模型整体表现如何。

关键思想是将训练数据与测试数据分开。因为你希望在与训练模型的数据不同的数据上测试你的模型,以避免过拟合。你希望能够泛化,而测试你是否能够做到这一点的方法是...

泛化的一个方法是查看一些你之前未见过的数据,看看我们实际能够达到的效果。如果我们想在像Python这样的编程语言中实现任何这些技术,有很多方法可以做到。我们可以自己从头开始编写,但...

有一些库允许我们利用现有算法的实现,以便在很多不同的情况下使用相同类型的算法。因此,有一个非常流行的库叫做scikit-learn,它让我们在Python中能够非常快速地获得。

设置许多不同的机器学习模型,这个库已经为最近邻分类感知机学习以及许多其他我们尚未讨论的推理和监督学习类型编写了算法,但使用它我们可以开始尝试。

了解这些方法是如何工作的,以及它们的准确性表现如何,所以我们来看一种尝试解决这类问题的方法。好的,我首先会打开bank_notes.csv,这是由加州大学尔湾分校提供的一整套数据,关于各种银行票据的信息。

不同的银行票据,因此人们拍摄了各种不同的银行票据,并测量了这些银行票据的不同属性,特别是有一些人将每一张银行票据分类为伪钞或非伪钞。所以你正在查看的就是这些。

这里每一行代表一张银行票据,这个数据被格式化为CSV电子表格,我们只是用逗号分隔这些不同的字段。我们为每一个数据点有四个不同的输入值,都是一些对银行票据所做测量的信息。

这些测量值并不是那么重要,重要的是我们确实能够访问这些数据,更重要的是,我们可以为每个数据点访问一个标签,其中0表示这不是一张伪钞,意味着它是一张真实钞票,而标记为1的数据点则表示它是一张伪钞。

至少根据给这组特定数据贴标签的人类研究者的说法,我们有一整套数据,代表着大量不同的数据点,每个数据点都有这些不同的测量,且每个数据点都有一个输出值0或1,0表示它。

这是一个真实的钞票1,意味着它是一张伪钞,我们希望做的是使用监督学习,开始预测或建模某种函数,该函数可以将这四个值作为输入并预测输出是什么。我们希望我们的学习算法能够找到某种模式。

基于这些测量能够预测的东西,比如说你只需拍一张钞票的照片,就可以预测那张钞票是否真实,或者是否为伪钞。那么我们该如何做到这一点呢?首先我要打开bank_notes_0.py,看看我们该如何实现这一点。我首先导入许多东西。

使用scikit-learn,但重要的是我将把我的模型设为感知机模型,这是我们之前讨论过的模型之一。我们将尝试找出一些权重设置,以便将数据划分为两个不同的组,然后我会继续读取数据。

对于我的银行票据CSV文件,我基本上会将每一行分开为前四个值,这一行的证据,然后是标签。如果这一行的最后一列是零,标签为真品,否则为假冒品。

我实际上是从CSV文件中读取数据,将其划分为许多行,每一行都有一些证据,这四个输入值将作为我的假设函数的输入,然后是标签,输出是否是真品或假冒品,这是我试图预测的内容。

所以下一步是我想将我的数据集划分为训练集和测试集,一些数据用于训练我的机器学习模型,一些数据用于测试该模型,看看它的表现如何。所以我会先确定。

数据的长度有多少数据点,我将取一半。这个数字叫做保留集,这是我将为测试阶段保留的数据项数量。我会随机打乱数据,使其顺序随机,然后我会说我的测试集将是。

所有数据都到保留集为止,我将取出许多数据项,这将是我的测试集,而我的训练数据将是其他所有信息,我将用来训练我的模型,然后我会说我需要将我的训练数据划分为两个不同的集合。

我的X值,X在这里代表输入,因此我要训练的X值基本上是每一行的证据,这四个值构成一个四维向量,这是所有输入,然后我需要Y。

我想从每个输入点的标签中学习的输出值是什么?对于训练数据中的每一行也是一样,但这次我会取这一行并获取它的标签,看它是真品还是假冒品,所以我最终得到了。

使用一组所有输入数据的向量列表和一组按相同顺序排列的标签列表,然后训练我的模型,这里使用的是Sep Tron模型,我只是调用model.fit,传入训练数据。

这些训练数据的标签是什么,scikit-learn将处理模型拟合,整个算法将为我完成,然后当它完成后,我可以测试模型的表现,所以我可以说让我获取所有输入向量,用于我想要测试的内容,每一行在我的测试数据集中。

继续获取证据和y值,那些是每一行的实际值,以及测试数据集中,实际标签是什么,但接下来我要生成一些预测,我将使用这个模型,尝试预测基于测试,输出是什么,我的目标是现在比较原因。

测试与预测,我想看看我的预测基于模型,实际上与Y值的反映如何,输出是什么,这些实际上是标记的,因为我现在有这个标签数据,我可以评估算法的效果,所以现在我可以计算我们做得多好,我要。

这个zip函数基本上让我同时查看两个不同的列表,因此对于每个实际值和每个预测值,如果实际值与我预测的相同,我将递增计数器,否则我将递增我的错误计数。

计数器加一,所以到最后可以打印出结果。这是我正确预测的数量。

我犯了多少错误,这里是我的总体准确率,例如,所以我可以继续进行。我可以运行Python banknote 0,dot pi,它将对一半的数据集进行训练,然后对另一半的数据集进行测试,这里是我在这个案例中,感知器模型的结果,它能正确分类679张票据。

作为正确的,眼睛是正品或伪造,并错误分类七张,整体准确率接近99%。因此,在这个特定数据集上,使用这个感知器模型,我们能够很好地预测。

预期输出是什么,我们可以尝试不同的模型,scikit-learn使得这非常简单。

替换一个模型为另一个模型,因此,不是感知器模型,我可以使用支持向量机,使用SVC,也就是支持向量类。利用支持向量机将事物分类为两个不同的组,现在看看,表现如何,这次我们。

能够正确预测682个,并且,错误预测准确率为99.4%。我们甚至可以尝试K邻居分类器作为模型。这需要一个参数,邻居的数量,你想查看多少邻居。我们就看一个,最近邻居。

使用这个来进行预测,继续运行这个,看来基于K邻居的设置,仅查看一个邻居,我们能够正确分类685个数据点,错误分类一个,也许我们试试三个邻居,而不是仅使用一个邻居做更多的K。

最近邻居方法,我查看三个最近邻居,看看。

在这个案例中,它似乎准确地将所有预测的百分之百描述为真实的纸币或伪造的纸币,我们可以多次进行这些实验,因为我每次都在随机重组测试组中的一半数据。

在训练过程中,我们实际上是在稍微不同的数据集上进行训练,因此你可能想运行多个实验,看看它们的表现如何,但简而言之,它们的表现都很好,尽管其中一些的表现略好于其他,但这并不总是适用。

但是你现在可以开始测试,通过快速组装这些机器学习模型,使用scikit-learn在一些训练集上进行训练,然后在一些测试集上进行测试,分成训练组和测试组,测试如此频繁。

scikit-learn内置了尝试实现的功能,我刚才都是手动完成的,但如果我们看一下纸币案例,就可以利用一些。

scikit-learn中还有其他功能,可以简化我们的逻辑,内置了一个函数,称为train test split,它会自动将数据分成训练组和测试组,我只需指定测试组的比例,比如0.5。

然后我可以在训练数据上拟合模型,对测试数据进行预测,然后进行统计,scikit-learn有一些很好的方法来统计我们的数据与预测的匹配次数,以及测试数据未匹配的次数。

因此,你可以非常快速地编写程序,只需不多的代码行,可能只需40行代码就能完成所有预测,然后根据结果查看我们的表现,这些类型的库使我们能够在不真正了解这些算法的实现细节的情况下,以非常实用的方式使用这些算法来解决这些问题。

那么这就是监督学习的任务,给定一整套数据一些输入-输出对,我们希望学习一个函数,将这些输入映射到这些输出,但结果是。

还有其他形式的学习,另一个流行的机器学习类型,尤其是现在被称为强化学习,强化学习的思想不是一开始就给定一整套输入-输出对,强化学习全在于从经验中学习。

强化学习我们的代理无论是,像一个试图在世界中进行动作的物理机器人,还是某个在某处运行的虚拟程序代理。我们的代理将会获得一系列奖励或惩罚,形式是数值,但你可以把它们视为奖励或。

惩罚,基于此它学习未来该采取什么动作。我们的代理,我们的AI将被放置在某种环境中,它将进行一些动作,基于它所做的动作,它学习一些东西。当它做得好时,它会获得奖励,而当它做得不好的时候,它会受到惩罚。

学习如何做或者在未来不该做什么,基于这些个体经验。这通常的样子是,它往往会从某个代理开始,某个AI,可能再次是一个物理机器人。如果你想象的是一个四处移动的物理机器人,但它也可以仅仅是一个。

我们的代理位于他们的环境中,环境就是他们将进行动作的地方,也是给予他们各种动作奖励或惩罚的地方。例如,环境将开始将我们的代理放置在一个状态中。

代理在游戏中的某个状态,可能是代理正在玩的游戏状态,代理正在探索的世界可能是某个在网格中表示的,状态中的位置,并且在该状态中,代理需要选择采取一个动作。代理可能有多个。

可以选择的动作,但它们,选择一个动作,所以它们可能在某个特定状态下采取一个动作,作为结果,代理通常会得到两个响应,我们将其建模为,代理在采取一个动作后会找到一个新的状态。

其他状态,它们也会获得某种数值奖励,正面,负面通常意味着它们做了某些不好的事情,收到了某种惩罚。这就是代理所拥有的所有信息,它被告知自己处于哪个状态,它做出某种行动,基于此它最终会处于。

另一个状态,然后它最终获得某种特定的奖励,基于这些信息,它需要学习未来该采取什么动作。因此,你可以想象将其推广到很多不同的情况。这通常就是你训练的方式,如果你见过那些机器人,它们是。

现在能够像人类一样走动,这将非常困难,要准确编程机器人让它像人类那样走动。你可以通过强化学习来训练它,每次它做得好时给予它某种数值奖励。

采取积极的措施,每次它做错事,比如摔倒时就惩罚它。然后让AI根据这个奖励的序列进行学习,基于尝试采取各种不同的行动,你就可以开始让代理进行学习。

哈佛CS50-AI | Python人工智能入门(2020·完整版) - P16:L4- 模型学习 3 (马尔可夫决策过程,Q学习,无监督,聚类) - ShowMeAI - BV1AQ4y1y7wy

学习未来该做什么和不该做什么,因此为了开始正式化这一点,我们首先需要正式化我们所说的状态和行动的概念,像往常一样,我们将这种世界形式化为一个被称为马尔可夫决策过程的东西,与。

你可能记得之前的马尔可夫链,但马尔可夫决策过程是一个我们可以用来为代理在其环境中做决策的模型,这是一个允许我们表示代理可以处于的各种不同状态的模型。

他们可以采取的行动以及采取一种行动与采取另一种行动的奖励是什么,那么这实际上是什么样子呢?如果你还记得马尔可夫链,从之前的马尔可夫链看起来有点像这样,我们有一大堆这些个体状态,每个状态立即过渡到。

另一个基于某些概率的状态,分布我们在之前天气的上下文中看到过。如果天气是晴朗的,我们说在某种概率下,第二天也只有在某种其他概率下才会是雨天。例如,我们也可以想象不再下雨,我们只有这些状态,其中一个状态。

根据某些概率分布会导致另一个状态,但在这个原始模型中,没有代理可以控制这个过程,完全是基于概率的,在某种概率下我们移动到这个下一个状态,但也许它会是某种其他状态。

概率现在我们将拥有的是代理在这个状态下选择一组行动的能力,可能与仅有一条前进路径不同,他们有三种不同的行动选择,每种选择都通向不同的路径。即便这也有些过于简化,因为在每个状态下,

在这些状态中,你可以想象更多的分支点,那里有更多的决策可以被采取,因此我们扩展了马尔可夫链,表示从一个状态你现在有可用的行动选择,而每个这些行动可能与其自身的概率分布相关联,去。

各种不同的状态,然后我们还会添加另一个扩展,每当你从一个状态采取行动进入另一个状态时,我们可以将奖励与这个结果相关联,表明R是正值,意味着某种正奖励,或者R是负值,意味着有某种形式的。

惩罚,这就是我们将考虑的马尔可夫决策过程。马尔可夫决策过程有一些初始状态的集合,我们可以处于这些状态中,我们有一些行动的集合,给定一个状态,我可以说在那个状态下有哪些可用的行动。

然后我们有一些转移模型。转移模型之前提到,给定我当前的状态,我到达下一个状态或另一个状态的概率是什么?转移模型现在有效地有两个条件:我们在说,给定我处于这个状态,并且我采取这个行动,我到达下一个状态的概率是什么。

也许我们生活在一个非常确定的神秘世界中,在这个马尔可夫决策过程中,给定一个状态和一个行动,我们可以确定会到达哪个下一个状态,但也许世界中存在一些随机性,当你采取行动并意识到受到惩罚和经历时。

当你处于一个状态并采取行动时,你可能不会总是回到完全相同的状态,可能还涉及一些概率。马尔可夫决策过程可以处理这两种可能情况,最后我们有一个通常称为R的奖励函数,它在这种情况下说明了什么。

在这个状态中,采取这个行动然后到达s'这个下一个状态的奖励,因此我在这个原始状态中,采取这个行动,我到达这个下一个状态,这个过程的奖励是什么?你可以在每次采取行动时将这些奖励加起来,得到总奖励。

代理可能从与特定环境的交互中获得的奖励,可以使用这个马尔可夫决策过程进行建模。那么这在实践中可能是什么样子呢?好吧,让我们在这里创建一个小模拟世界,我有这个试图导航的代理,这个代理是这个黄色点。

这里像一个在世界中试图穿越这个网格的机器人,最终它试图找到通往目标的路,如果它到达绿色目标,它就会得到某种奖励,但我们也可能会有一些红色方块,那是会受到惩罚的地方。

在某个我们不想要的地方,如果我们的代理到达了方块,它将会受到某种惩罚,但代理最初并不知道所有这些细节,它不知道这些状态与惩罚相关。但是也许它知道这个状态与奖励相关。

这并不意味着它必须与环境进行交互,以尝试弄清楚该做什么和不该做什么,因此,代理可能首先会在没有额外信息的情况下采取行动。如果它不知道惩罚是什么,也不知道奖励在哪里,它可能只是尝试采取某种行动。

那么它可能会学到,当你在将来处于这个状态时,不要采取这个向右移动的行动,这是一个错误的行动。在将来,如果你再次回到这个状态,就不要采取去奖励的行动。

当你处于这个特定状态时,因为那会导致惩罚。这可能是直觉,至少可以这么说,因此你可以尝试进行其他行动,你向上移动,好吧,那没有导致任何立即的奖励,也许可以尝试其他事情。然后也许再尝试其他事情,好的,现在你发现你得到了。

另一种惩罚,因此你从那次经历中学到了一些东西,所以下次你进行这个完整的过程时,你知道如果你最终处于这个状态,你不应该采取这种行动,因为处于这个状态并采取那个行动最终会导致某种惩罚,负面的结果。

换句话说,这个过程会重复,你可以想象让我们的代理探索世界,随着时间的推移学习哪些状态往往对应于糟糕的行动,并随着时间的推移学习哪些状态对应于糟糕的行动,直到最终如果它随机尝试足够多的事情,它可能最终会发现。

当你处于这个状态时,如果你采取向上的行动,可能会发现你实际上从中得到了奖励,而从中可以学到的是,如果你在这个状态下,你应该采取向上的行动,因为那会导致奖励,随着时间的推移,你还可以学到如果你在这个状态下。

应该采取左侧的行动,因为那会导致这个状态,这也让你最终得到奖励,因此你随着时间的推移开始学习,不仅哪些行动在特定状态下是好的,还学习哪些行动是不好的,这样一来,一旦你知道一系列好的行动会引导你走向某种结果。

我们的代理可以遵循这些指令,遵循它所学到的经验,我们没有告诉代理目标是什么,也没有告诉代理惩罚在哪里,但代理可以开始从这个经验中学习,并开始更好地执行这些任务。

未来,所以现在让我们尝试形式化这个想法,形式化这个我们想要能够在这个状态下学习的想法,采取这种行动是好事还是坏事。强化学习有很多不同的模型,今天我们只看其中一个模型,而我们要看的那个。

我们要看的方法称为 Q 学习,Q 学习的核心在于学习一个函数 Q,这个函数以状态 s 和行动 a 为输入,其中 s 是状态,a 是你在该状态下采取的行动,而这个 Q 函数将做的就是估算出奖励的值。

我在这个状态下采取这种行动能得到什么奖励,起初我们不知道这个 Q 函数应该是什么,但随着时间的推移,基于经验,基于尝试和观察结果,我想尝试学习任意特定状态 Si 和我可能采取的任意特定行动的 Q 值。

那么方法是什么呢?最初的方法是,我们将对所有状态s和所有动作a的Q的si设定为零。在我开始任何事情之前,或者在我拥有任何经验之前,我不知道在任何给定状态下采取任何行动的价值,所以我将假设所有价值都是零。

但是当我与世界互动时,当我经历奖励或惩罚,或者我去一个既没有奖励也没有惩罚的状态时,我希望以某种方式更新我对Q的si的估计。我希望不断更新我对Q的si的估计。

基于我所获得的经验、奖励和惩罚,使我在未来对什么动作是好的、什么状态会更好有了了解。当我们采取一个动作并获得某种奖励时,我想估计Q的si的新值,而这个估计是基于几个不同的因素。

我根据从这个动作中获得的奖励以及进入下一个状态时的奖励来进行估计,但假设情况并没有结束,假设我可能还会采取未来的其他动作,我还需要考虑预期的未来奖励。

与环境互动,有时你会采取行动并获得奖励。但随后你可以继续采取更多行动,并获得比这些更多的奖励。这两者都与当前我从这一步获得的奖励相关,也与我未来可能想采取的步骤相关。

可能会有这样的情况,我会想采取一个不立即导致奖励的步骤,因为我知道在未来这将导致更多的奖励。因此,代理体验的当前奖励和未来奖励之间需要找到一个平衡。

Q的si的值基于当前的奖励和预期的未来奖励。然后我们需要更新这个q函数,以考虑这个新的估计。现在在我们经过这个过程时,我们已经有了一个我们认为的价值的估计,现在我们有了一个新的估计。

我们需要将这两种估计结合起来,我们将查看更正式的方法来实际开始这样做。为了向你展示这个公式的样子,这里是我们将采用的q-learning方法。我们将再次从Q的SN开始,a在所有状态下都等于0。

然后每次我们在状态s下采取一个动作a并观察到奖励R时,我们将更新我们的价值估计,Q的Si。这个想法是,我们将弄清楚新的价值估计减去我们现有的价值估计。

在这个状态下采取这个动作的期望也许是我们当前认为的价值是 10,但我们现在将估计我们认为的价值,也许新的价值估计是像 20 这样的东西,因此我们的新价值估计比我们。

当前的值估计恰好在这里,我们需要决定我们想要调整我们当前的期望,这个动作在这个特定状态下的价值是什么,这个差异是我们增加或减少多少我们对预期价值的看法。

依赖于这个参数 alpha,也叫学习率,alpha 实际上表示我们对新信息的重视程度与我们对旧信息的重视程度之间的关系。alpha 值为 1 意味着我们真的重视新信息,但如果我们有一个新的估计,那么旧的估计就无关紧要。

我们只考虑我们的新估计,因为我们总是只想这样做。不能考虑我们的新信息,所以这工作的方式是。如果你想象 alpha 为 1,那么我们就取 Q 的旧值,然后加上 1 乘以新值减去旧值,这样就只剩下。

所以当 alpha 为 1 时,我们只考虑我们的新估计是什么,但随着时间的推移,随着我们经历很多经历,我们已经有一些现有信息,我们可能已经尝试过这个动作九次,而现在我们只是在第十次尝试,而且我们不想。

考虑这个帐篷体验,我还想考虑我之前九次体验的事实,这对我来说是有意义的,而这些数据我不一定想丢失。因此,alpha 控制这个决策,控制新信息的重要性,零则意味着忽略所有新信息。

信息只是保持这个 Q 值不变,这意味着完全用新信息替换旧信息,而在这两者之间保持某种平衡。我们可以更正式地将这个方程表达为,旧值估计是我们对。

在特定状态下采取这个动作的价值,这就是 Q 的意思。所以我们在这里有一次,我们要增加一些东西,我们将添加 alpha 乘以新价值估计减去旧价值估计,但旧价值估计我们只需通过调用这个 Q 函数来查找。

基于我们刚刚采取的这个经验的新价值估计是什么,在这个特定状态下采取这个动作的价值的新估计将由两个部分组成。它将由我在这个状态下采取这个动作获得的奖励组成,然后它将。

我可以从这一点开始期望未来的奖励是什么。因此,这将是我现在获得的总奖励,加上未来我将获得的奖励,我怎么估计将来会获得什么呢?这有点像对这个Q函数的另一次调用。

我将从所有可能的下一步行动中选取最大值,看看在所有这些可能的行动中,哪一个会有最高的奖励。因此这看起来有点复杂,这将是我们进行这种更新的概念。

然后我有一些旧的估计,估计采取这一行动在该状态下的价值。我将根据我经历的新信息更新它。我预测我将获得的未来奖励是什么,并且利用这一点更新我对采取此行动的奖励的估计。

在这个特定状态下,您可能还会对这个算法进行其他补充,有时候可能并不是所有的未来奖励都与当前奖励同等重要,也许你想要一个代理,重视现在的奖励而不是稍后的奖励。因此,有时您甚至可以在这里添加另一个项。

一个参数是折现未来的奖励,认为未来的奖励没有当前奖励那么有价值。在当前时间步获得奖励比等待一年后再获得奖励要好,但这要由程序员决定这个参数应该是什么。

这个公式的总体思路是说,每当我们经历一些新的奖励时,我们会考虑这一点,更新我们对这一行动有多好的估计。然后在未来,我们可以基于该算法做出决策,一旦我们对每个状态和每个行动都有了较好的估计。

如果我们知道采取这一行动的价值,那么我们可以做一些事情,比如实施一个贪婪决策政策。如果我处于某个状态,想知道在这个状态下应该采取什么行动,那么我会考虑所有可能的行动,看看Q(s, a)的价值是什么。

在该状态下采取这一行动,我将只选择在评估那个表达式后具有最高值的行动。所以我选择了具有最高值的行动,这告诉我在我处于的任何给定状态下,我应该采取什么行动,我可以贪婪地说在我所有的行动中。

这个行动给我带来最高的期望值,因此我会选择这个行动作为我采取的行动。但这种方法有一个缺点,缺点出现在这样的情况下:我们知道存在某种解决方案可以带我到达奖励。

但这不一定是最佳方式或最快方式,如果代理允许多探索一点,可能会发现通过某条其他路线获得奖励的速度更快,而不是通过这条特定的路径,这是更快到达最终目标的方式,或许我们想要。

代理也能找出这一点,但如果代理总是采取它知道的最佳动作,当它到达这个特定方格时,它并不知道这是一个好动作,因为它从未真正尝试过,但它知道向下走最终会引导它。

这个奖励,因此将来可能学到的就是它应该总是选择这条路线,而不会探索并走这条路线。因此在强化学习中,探索与利用之间存在这种紧张关系,而利用通常指的是使用AI所掌握的知识。

AI已经知道这是一个导致奖励的动作,因此我们会使用该动作,探索就是关于探索其他可能我们之前没有充分探索的动作,因为这些动作中的一个,即使我对此一无所知,也可能导致更好的结果。

更快地获得奖励或未来获得更多奖励,因此一个仅仅利用信息而不进行探索的代理可能能够获得奖励,但它可能无法最大化其未来,因为它不知道还有其他可能性,这些可能性只能通过利用探索来了解。

那么我们如何尝试解决这个问题呢?一个可能的解决方案称为epsilon贪婪算法,我们设定epsilon为我们希望多频繁随机选择一次,有时我们会随机选择一次,以便说“让我们尝试探索,看看会发生什么”,然后。

算法的逻辑将是以概率1减去Epsilon选择估计的最佳动作,在贪婪情况下,我们总是选择最佳动作,但在epsilon贪婪中,我们大多数时间会选择最佳动作,或者有时会以概率Epsilon选择最佳动作。

所以我们将选择一个随机动作,因此每次面临采取行动的能力时,有时我们会选择最佳动作,有时我们只会选择一个随机动作,因此这种类型的算法在强化学习背景下可能非常强大,而不仅仅是。

选择现在可能的最佳动作,但有时,尤其是在早期,允许自己进行随机移动,让你探索各种不同的可能状态和动作,随着时间的推移,你可能会逐渐减少Epsilon的值,更频繁地选择最佳动作。

你更有信心已经探索了所有可能性,所以我们可以将其付诸实践,强化学习的一个非常常见的应用是在游戏中,如果你想教一个代理如何玩一个游戏,你只需让代理玩这个游戏很多次,然后奖励信号会在游戏结束时发生。

当游戏结束时,如果我们的 AI 赢得了游戏,它会获得像 1 这样的奖励,例如,如果它输了游戏,它会得到负 1 的奖励,基于此,它开始学习哪些行动是好的,哪些行动是坏的,你不必告诉 AI 什么是好,什么是坏。

不好的结果,但是 AI 会根据这个奖励来判断,赢得游戏是某种信号,输掉游戏也是某种信号,基于所有这些信息,它开始弄清楚应该做出什么决策。一个你可能玩过的非常简单的游戏是 NIM,在 NIM 游戏中。

你有一堆物体和许多不同的堆,这里我将每个堆表示为一个独立的行,所以你在第一堆有一个物体,在第二堆有三个物体,在第三堆有五个物体,在第四堆有七个物体,NIM 游戏是一个双人游戏,玩家轮流进行。

从堆中移除物体的规则是,在任何给定的回合,你可以从这些堆中的任意一个移除任意数量的物体,任意一行你必须至少移除一个物体,但你可以从其中一个堆中移除任意数量的物体,而谁移走最后一个物体。

所以玩家一可能会从这个堆中移除四个物体,玩家二可能会从这个堆中移除四个物体,现在我们还有四堆,分别是三、一个和三,玩家一可能会从第二堆中移除全部物体,玩家二如果策略得当,可能会移除全部,或者只移除部分。

从第三堆中移除两个,现在我们还有三堆,每堆剩下一个物体,玩家一可能从一堆中移除一个物体,玩家二从另一堆中移除一个物体,现在玩家一剩下的选择是从最后一堆中选择这个物体,玩家一在此时输掉了游戏,所以这是一个相当简单的游戏。

物体的堆,每次轮到你选择从一个堆中移除多少个物体,移除最后一个物体的人会输掉,这是一种你可以相对容易地编码成 AI 的游戏,因为状态实际上只是四个数字。每个状态就是四个堆中每个堆的物体数量。

行动是指我将从每一个个别堆中移除多少个物体,而奖励则发生在最后,如果你是那个必须移除最后一个物体的玩家,那么你会受到某种惩罚,但如果你不是,另一个玩家必须移除最后一个物体,那么你就会获得奖励。

一种奖励,因此我们实际上可以展示这一点。我已经实现了一个AI来玩NIM游戏。好吧,所以我们要做的是创建一个AI,通过训练该AI进行一些场次的游戏,让AI与自己对战,想法是AI将会。

在与自己对战的游戏中学习,从每一次经历中学习,了解未来该怎么做,然后我作为人类将与AI对战。所以最开始我们说训练零次。

这意味着我们不会让AI与自己进行任何练习游戏,以便从它的经验中学习,我们只会看看它表现得多好。看起来有四堆,我可以选择从其中任何一堆中移走多少物品。所以,也许我会从三堆中移走五个物品。

例如,我选择从零堆中拿走一个物品,所以我现在留下这些堆。在这里,我可能会选择从二堆中移除所有五个物品。AI选择从一堆中移走两个,现在我剩下的有一堆只有一个物品。

一堆有两个物品的堆,所以从三堆中我将移走两个物品,现在我让AI没有选择,只能拿走最后一个。

直到游戏结束,我才能赢,但这是因为AI实际上是在随机玩,它没有任何先前的经验来进行这些判断。现在让我让AI自己训练,大约进行一万场游戏,我会让AI玩一万场游戏。

在每次NIMH对战中,无论是赢还是输,它都会从中学习。

从这个经验中学习,未来该怎么做,未来不该做什么。接下来我将再次运行这个程序,现在你看到AI正在进行大量的训练游戏,大约一万场与自己对战的训练游戏。现在它将让我做这些决定,所以现在我准备好玩。

在与AI对战时,也许我会从三堆中移走一个物品,AI则从三堆中移走所有物品,因此我剩下三堆。然后我会继续从二堆中移走三个物品,而AI从零堆中移走一个物品,留下两堆,每堆各有两个物品。我会从中移走一个物品。

我想是从一堆中,AI从二堆中拿走两个,留下我没有选择,只能从一堆中移走一个物品。因此,看起来在玩了一万场NIMH游戏之后,AI已经学会了一些关于哪些状态和哪些动作是好的,并开始学习一些预测模式。

行为在任何给定状态下会是什么好的,什么行为会是坏的。因此,强化学习可以是一种非常强大的技术,用于实现这些类型的游戏代理,这些代理能够通过学习经验玩得很好,无论是对抗其他人还是。

通过与自己对弈并从那些经验中学习,现在NIM是一个相对简单的游戏,适合用于强化学习,因为状态太少,只有状态数等于这些不同堆中对象的数量。你可能想象。

如果你想到像棋类游戏这样的游戏,或者有很多状态和许多你可以想象的动作,那将会更难。对于每个状态和每个动作学习其值并不容易。因此,通常在这种情况下,我们无法。

不一定要准确学习每个状态和每个动作的值。但我们可以近似,就像我们在极小化中看到的那样,我们可以使用深度限制的方法在某个时间点停止计算。我们可以做一种称为函数近似的类似类型的近似,在强化学习上下文中,而不是。

学习每个状态和每个动作的Q值,我们只是有一些函数来估计在这个特定状态下采取这个动作的值,这可能基于该状态的各种不同特征。代理所处的环境,你可能必须。

选择这些特征究竟是什么,但你可以开始学习一些模式,这些模式超越一个特定的状态和一个特定的动作。你可以开始学习某些特征是否倾向于是好的事情或坏的事情。强化学习允许你,使用非常,类似的机制来超越。

某个特定状态并说如果这个,其他状态看起来有点像这样。那么,可能在一个状态下有效的,类似类型的行为也会在另一个状态下。随着你开始处理存在于的强化学习,这种方法可能会非常有帮助。

较大且越来越大的状态空间,其中探索所有可能存在的状态并不可行。因此,强化学习的两个主要类别是,有监督学习,即你有标记的输入和输出对,以及强化学习,即一个代理。

从奖励或惩罚中学习,它接收的机器学习的第三个主要类别,我们将简要触及,称为无监督学习。无监督学习发生在我们有数据而没有任何额外反馈,没有标签的情况下,在有监督学习的情况下则是。

我们的数据有标签,我们对数据进行标记,标记是否为下雨天。或者不是下雨天,使用这些标签,我们能够推断出模式,钞票。并且利用这些标签,我们能够,推导出推论和模式,以判断钞票的样子,与非钞票在无监督学习中的区别。

我没有访问任何这些标签的权限,但我们仍然希望学习一些模式。在无监督学习中,你可能想要执行的任务之一就是聚类,聚类只是一个任务,如果给定一组对象,将其组织成不同的簇。

一组相似的对象,有很多聚类的应用,它出现在基因研究中,你可能有许多不同的基因,而你想将它们聚类为相似的基因。如果你尝试分析整个种群或跨物种,它。

在图像中,如果你想将,图像的所有像素进行聚类,并且在图像的不同部分,会出现很多市场研究。如果你想将消费者,分成不同的组,以便知道哪些,组应该以某些类型的产品广告为目标。

在其他许多上下文中,聚类也非常适用。一种聚类技术是,称为K均值聚类的算法。K均值聚类将会,做的是将我们的所有数据点划分为K个不同的簇,并通过重复来实现。

将点分配给的过程。

然后在这些簇的中心移动,我们将通过中心来定义一个簇,簇的中间,然后根据哪个中心离该点最近,将点分配给该簇,我现在给你一个示例,例如我有一大堆。

无标签数据只是各种在某种图形空间中的数据点。我想将它们分组为不同的簇,但我最初不知道如何做到这一点,假设我想给这个组分配三个簇,你必须选择你想要的簇的数量。

K均值聚类可以尝试多次,查看这些值的表现,但我将先随机选择一些位置,来放置这些簇的中心,可能我有一个,蓝色簇,一个红色簇和一个绿色簇,我将从这三个位置开始,作为这些簇的中心。

K均值聚类告诉我们做的是,一旦我有了簇的中心,就要根据哪个簇的中心离每个点最近,来将每个点分配给一个簇,因此我们最终得到类似这样的结果,所有这些点都更靠近,蓝色簇的中心,而不是其他。

聚类中心,这里所有的点距离绿色聚类中心比任何其他聚类中心都更近,然后这两个点加上这边的这些点都是离红色聚类中心最近的。因此,这里是将所有这些点分配到三个不同聚类的一种可能方式。

这并不是很好,因为在这个红色聚类中,这些点似乎有点分散,而在这个绿色聚类中,这些点也有点分散,这可能不是我理想的聚类方式来处理这些不同的数据点,但k均值聚类是一个迭代过程,完成这一步之后。

还有下一步,那就是在我将所有点分配到离它最近的聚类中心后,我们将重新确定聚类,意味着将这些菱形的聚类中心移动到该聚类中所有点的中间或平均值。

所以我们将这个蓝点和蓝色中心移动到分配给蓝色聚类的所有点的中心,稍微向右移动,在这种情况下,我们对红色做同样的事情,将聚类中心移动到这些点的中间,按数量加权。

这里有更多的点,所以红色中心会向那边移动一点,同样,绿色中心在这边的点也更多,因此绿色中心会稍微向这个方向移动,因此我们重新确定所有聚类的中心。

然后我们重复这个过程,现在重新分配所有点到它们最近的聚类中心,现在因为我们已经移动了聚类中心,这些聚类分配可能会改变,原本这个点是离红色聚类中心最近的,但现在。

它实际上离蓝色聚类中心更近,这个点也是如此,而这三个最初离绿色聚类中心更近的点,现在则离红色聚类中心更近,因此我们可以重新分配这些数据点属于哪个聚类。

再次重复这个过程,将每个聚类的均值从聚类的中心移动到所有其他点的均值,并再次重复这个过程,继续将每个点分配到离它们最近的聚类,因此一旦我们达到一个点。

将所有点分配到离它们最近的聚类,并且没有变化,我们达到了某种平衡状态,在这种情况下没有点改变其归属,因此我们可以宣布这个算法现在结束,我们现在有了每个点的分配。

将数据分为三个不同的集群,看起来我们在识别哪些点彼此更相似而不是与其他组的点相似方面做得相当不错。因此我们有了下方的绿色集群、这里的蓝色集群,以及那边的红色集群,我们在没有。

我们并没有任何标签来告诉我们这些不同的集群是什么,而是以无监督的方式使用算法,来确定哪些点属于哪些类别,再次强调,这种聚类技术有很多应用,且还有更多。

在机器学习的不同领域中,D'AndreaForesman所提到的监督与非监督算法是许多基础性大局观念的组成部分,这些理念支撑着我们要解决的许多问题。

使用多种不同的方法尝试从数据中学习模式,无论是寻找相似的邻近数据点,还是试图最小化某种损失函数,或其他许多技术,这些都使我们开始尝试解决这些问题。

然后我们看看一些现代机器学习的基础原则,这种能力是从数据中学习,以便计算机可以执行任务,即使没有明确的指令来做到这一点,下次我们将继续这个主题。

关于机器学习的对话,探索我们可以使用的其他技术。

哈佛CS50-AI | Python人工智能入门(2020·完整版) - P17:L5- 神经网络 1 (神经网络,激活函数,梯度下降,多层网络) - ShowMeAI - BV1AQ4y1y7wy

[音乐] 好的,欢迎大家回到《Python人工智能导论》。上次我们看到了机器学习,这是一组计算机可以用来处理数据并学习数据内模式的技术,学习如何执行任务,即使我们程序员并没有。

给计算机明确的指令,说明如何执行这个任务,今天我们转向机器学习中最流行的技术和工具之一——神经网络,神经网络早在1940年代就受到研究人员的启发,他们思考人类是如何学习的。

学习人类神经科学的大脑,并尝试看看我们是否可以将这些相同的思想应用于计算机,模拟计算机学习以人类学习为基础。那么,大脑是如何结构的呢?简单来说,大脑由许多神经元组成,这些神经元相互连接。

这些神经元以某种方式相互交流,特别是如果你考虑生物神经网络的结构,科学家们观察到了一些关键特性。其中之一是这些神经元彼此连接,并接收来自其他神经元的电信号。

一个神经元可以将电信号传播给另一个神经元,另一个要点是神经元处理这些输入信号,然后可以被激活,神经元在某个时刻被激活,随后可以向其他神经元传播进一步的信号。

问题随之而来,我们能否将这种人类如何用大脑和神经元学习的生物学理念应用于机器,设计出一个人工神经网络(ANN),这将是一个受到这些生物神经网络启发的学习数学模型。

网络以及人工神经网络将允许我们做的事情是,它们首先能够模拟某种数学函数。每次你查看神经网络时,我们今天稍后会看到,它们实际上只是将某些输入映射到特定输出的数学函数。

基于网络的结构输出,取决于我们在神经元内部放置的特定单元的位置。

网络将决定网络如何功能,特别是人工神经网络将让我们学习网络参数应该是什么,我们稍后将深入探讨,但实际上我们想要模拟的是网络结构。

使我们能够容易地得到一些代码,以便网络能够确定如何建模给定特定输入数据的正确数学函数,因此为了创建我们的人工神经网络,不使用生物神经元,我们将使用我们要使用的。

在神经网络内部称为单位的单元,我们可以把它表示为图中的一个节点,这里用一个蓝色圆圈来表示。像这样,这些人工单元,这些人工神经元可以彼此连接,因此这里,例如,我们有两个单元。

通过这个边连接在这个。

有效地表示图形,所以我们现在要做的是将这个想法视为某种从输入到输出的映射,因此我们有一个单元,它连接到另一个单元,我们可以把这边看作输入,那边看作输出,我们试图做的是弄清楚如何解决。

一个问题是如何建模某种数学函数,这可能以我们之前看到的形式出现。

时间上,输入有变量x1和x2,给定这些输入,我们想要执行某种任务,比如预测是否会下雨,理想情况下,我们希望有某种方式,基于这些输入x1和x2,它们代表与之相关的某种变量。

天气,我们希望能够预测,在这种情况下是布尔分类,它会下雨还是不会下雨,我们上次通过一种数学函数来完成这一点,我们为我们的假设函数定义了某个函数H,它以x1和x2作为输入,这两个输入我们。

关注处理,以确定我们是否认为会下雨,或者我们认为不会下雨,问题变成了这个假设函数如何做出这个判断,我们上次决定使用这些的线性组合。

输入变量,以确定输出应该是什么,因此我们的假设函数等于像这样的东西,权重0加权重1乘以x1,加权重2乘以x2,因此这里发生的事情是x1和x2。这些是输入变量,输入到这个假设函数中。

这些输入变量正在被某些权重相乘,这些权重只是一些数字,因此x1被乘以权重1,x2被乘以权重2,而我们有这个,等等,零并没有被输入变量相乘。它只是用来移动函数的值。

向下看,你可以把它视为一个权重,它只是与某个虚拟值相乘,比如数字1,它乘以1,因此没有被乘以任何东西,或者有时在文献中,人们称这个变量权重0为偏差,因此你可以将这些变量视为。

略有不同的是,我们有权重乘以输入,然后单独将某些偏差加到结果中,你会听到在谈论神经网络和机器学习时使用这两种术语,因此实际上我们在这里做的就是为了定义一个。

对于假设函数,我们只需要决定和计算这些权重应该是什么,以确定将哪些值乘以我们的输入,从而得到某种结果,当然在这一切的最后,我们需要进行某种分类,比如下雨或不下雨,为此我们使用某种方法。

这定义了一种阈值,我们看到例如阶跃函数的定义是,如果将权重与输入相乘的结果至少为零,则定义为 1,否则为零,你可以将这条中间的线看作是一条虚线。

它在达到一个点之前保持在零,然后函数在达到某个阈值后跳跃到 1,因此在到达某个阈值之前为零,然后在达到特定阈值后为 1。

因此,这是一种我们可以定义激活函数的方法,激活函数决定何时其输出变为活跃,变为 z1 而不是零,但我们也看到,如果我们不想要纯粹的二元分类,不希望只是 0 或 1,而是想要。

为了允许一些介于真实、编号值之间的值,我们可以使用不同的函数,有很多选择,但我们关注的是逻辑 sigmoid 函数,它呈现一种 S 形曲线,我们可以将其表示为一个概率,也许在这之间的某个地方。

比如雨的概率为 0.5,也许稍后雨的概率是 0.8,因此与其仅有 0 或 1 的二元分类,我们可以允许介于这之间的数值,结果显示有许多不同类型的激活函数,激活函数仅仅是输出某种函数。

将权重相乘,加上偏差,然后确定实际输出,另一个流行的函数是整流线性单元,也称为 relu,运作方式是它取其输入与 0 的最大值,因此如果它是正值,它保持。

依然保持不变,但如果它为 0 或负值,则将其平滑到零,还有其他激活函数可供选择,但简而言之,每个激活函数可以看作是应用于所有计算结果的函数,我们取某个函数 G。

并将其应用于所有计算的结果,这就是我们上次看到的定义某些假设函数的方法,该函数接收输入,计算这些输入的某种线性组合,然后通过某种激活函数得到输出,这实际上。

事实证明,这是最简单的神经网络模型,我们将用这样的结构来图形化表示这个数学概念,作为一个有两个输入的神经网络,我们可以把这看作是 x1 和 x2,然后有一个输出,你可以认为。

例如,判断我们是否认为会下雨,在这个特定实例中。那么这个模型到底是如何工作的呢?这两个输入代表我们的输入变量 x1 和 x2,注意这些输入通过这些边连接到这个输出。

将通过他们的权重来定义这些边,每条边都有一个权重,权重 1 和权重 - ,然后这个输出单元将根据这些输入和权重计算输出,这个输出单元将所有输入相乘。

他们的权重中添加这个偏置项,你可以把它看作是一个额外的 w0 项,然后我们通过激活函数传递它。因此,这只是一个图形化表示上次我们看到的同样想法的数学形式,我们将称之为一个非常简单的神经网络。

我们希望这个神经网络能够学习如何计算我们想要的某个函数,而神经网络将学习 w0、w1 和 w2 的值应该是什么。激活函数应该是什么,以获得我们想要的结果。

我们可以看看这个示例,实际上是一个非常简单的函数,我们可能会计算,如果我们回顾一下在命题逻辑中,我们看到的最简单的函数之一就是类似于或函数的,它接受两个输入 X 和 y 并输出一个。

当任一输入或两个输入都是 1 时,这被称为真;而当两个输入都是 0 时,输出为 0,即假。因此,这就是或函数,而这是或函数的真值表,只要任一输入为 1,函数的输出就是 1,唯一的情况是输出。

当两个输入都是 0 时,输出为 0。那么问题是,我们如何能够训练一个神经网络以学习这个特定的函数?那些权重会是什么样子呢?我们可以这样做,这是我们的神经网络,我提议为了计算或函数。

我们将为每个权重使用值 1,并将使用负 1 作为偏置,然后我们将使用这个阶跃函数作为我们的激活函数。那么这如何运作呢?如果我想计算 0 或 0,显然结果是 0,因为假或假为假,那么我们该怎么做呢?

我们的输出单元将计算这个输入乘以权重,0 乘以 1 是 0,同样,这里 0 乘以 1 也是 0,我们还会加上偏置负 1,所以我们得到的结果是负 1,如果我们将其绘制在激活函数上,负 1 在这里,处于阈值之前。

这意味着要么是 0,要么是 1,只有在阈值之后,因为负 1 在阈值之前,这个单元提供的输出将是 0,这就是我们期望的,0 或 0 应该为 0。如果我们改为 1 或 0,这个数字是 1,那么在这种情况下,为了计算超出阈值的值,输出将是 1。

输出将是我们再次需要做加权和,1 乘以 1 是 1,0 乘以 1 是 0,到目前为止的总和是 1,加上负 1,那么输出为 0,如果我们将 0 在阶跃函数上绘制,0 就在这里,正好在阈值上,输出将在这里为 1。

因为输出为 0 或 1,这就是我们所期望的结果,再举一个例子,如果我有 1 或 1,结果会是什么呢?嗯,1 乘以 1 等于 1,1 乘以 1 也是 1,加起来是 2,我再加上偏置项,得到的数是 1,1 在这个图表上的位置非常远。

输出总是 0 或 1,取决于我们是否超过了阈值,因此这个神经网络建模了或函数,虽然是一个非常简单的函数,但仍能正确建模,如果我给它输入。

将告诉我 x1 或 x2 的值是什么,你可以想象尝试对其他函数做同样的事情,例如与函数,它接受两个输入并计算是否 x 和 y 都为真,所以如果 X 为 1 且 Y 为 1,则 X 和 Y 的输出为 1,但在所有其他情况下,输出为 0。

我们如何在神经网络中建模这一点呢?事实证明,我们可以以相同的方式进行,除了将偏置从负 1 改为负 2。那么结果看起来会是什么呢?如果我有 1 和 1,应该为 1,因为真和真等于真。

取 1 乘以 1 是 1,1 乘以 1 是 1,到目前为止总和为 2,现在我加上偏置负 2,得到的值是 0,而 0 在激活函数上绘制时正好超过那个阈值,因此输出为 1。但如果我添加其他输入,例如 1 和 0,权重会是什么?

这些和是1加0,它将是1减2,结果为负1,而负1未通过阈值,因此输出将是0。因此,这些是我们可以使用具有两个输入和一个输出的神经网络来建模的一些非常简单的函数,我们的目标是。

为了确定这些权重应该是什么,以便确定输出应该是什么,你可以想象将其推广到计算更复杂的函数,比如给定湿度和压力,我们想计算下雨的概率。

例如,我们可能想做一个俄罗斯风格的问题,给定一些广告量和当前的月份,也许我们想预测该月份的预期销售额,因此你可以想象这些输入和输出也是不同的,结果表明。

在某些问题中,我们不仅会有两个输入,而这些神经网络的好处在于,我们可以将多个单元组合在一起,使我们的网络更复杂,仅通过向这个特定的神经网络添加更多单元。因此,我们正在查看的网络有两个输入和一个输出。

但我们同样可以轻松地说,继续添加三个输入,或有更多输入,我们可以任意决定有多少个输入到我们的问题中,所有这些都将计算我们关心的某种输出,如何进行数学运算。

输出方式与两个输入的情况非常相似,我们有两个权重,通过这些边表示,并将权重与数字相乘,添加这个偏差项,在其他情况下我们也会做同样的事情,如果我有三个输入,你可以想象将每个输入相乘。

对这三个输入的每个权重进行运算,如果我有五个输入,我们会在这里做同样的事情,我说从1到5求和,将每个输入变量乘以其对应的权重,然后将偏差添加到结果中,这就是一个情况。

例如,这个内部网络有五个输入,但我们可以在这个神经网络中有任意多个节点,每次我们只需将所有输入变量乘以它们的权重求和,然后在最后添加偏差项。

这使我们能够表示具有更多输入的问题,只需通过增大神经网络的规模。接下来我们可能会问一个关于如何训练这些神经网络的问题,在“与”函数和“或”函数的情况下,它们都简单得多。

我可以告诉你一些函数,比如这里的权重应该是什么,而你自己。权重应该如何设置,以便计算你想要的输出,但一般来说,像预测销售或预测是否会下雨这样的函数,都是更棘手的函数。

我们希望计算机有某种机制来计算权重应该如何设置,以便我们的神经网络能够准确建模我们关心的函数。结果证明,进行这项工作的策略受到了微积分领域的启发。

这是一种称为梯度下降的技术。

梯度下降是一种用于最小化损失的算法,尤其是在训练神经网络时。

回想一下,损失是指我们的假设函数有多糟糕。我们可以定义某些损失函数,之前我们看到了一些损失函数的例子,它们给我们一个数字,表示任何特定假设模型数据的效果如何,有多少例子被错误分类,它们的表现如何。

与我们可能定义的其他假设函数相比,它更差或稍微好一点,这个损失函数只是一个数学函数。当你在微积分中有一个数学函数时,你可以计算一些被称为梯度的东西,你可以把它想象成斜率。

在任何特定点,损失函数的方向在移动,告诉我们应该如何调整这些权重,以最小化损失量。一般来说,我们不会深入讨论微积分,但梯度下降的高层次思想看起来是这样的。

如果我们想要训练一个神经网络,我们将先随机选择权重,为神经网络中的所有权重随机选取,然后我们将使用我们可以访问的输入数据来训练网络,以便找出什么。

权重实际应该是什么,因此我们将一遍又一遍地重复这个过程。第一步是根据所有数据点计算梯度,我们将查看所有数据并找出当前权重设置下的梯度。

这意味着我们应该朝哪个方向移动权重,以最小化总的损失,使我们的解决方案更好。一旦我们计算出梯度,确定应该朝哪个方向移动损失函数,我们就可以根据梯度更新权重,采取一个小的步骤。

向这些权重的方向迈出一步,以试图使我们的解决方案稍微更好,而我们迈出的步伐大小会有所不同。你可以在训练特定神经网络时选择这个步伐,但简而言之,这个想法是基于所有数据点进行确定。

这些数据点中权重应该朝哪个方向移动,然后在那个方向上小步移动权重。如果你不断重复这个过程,逐渐调整权重,最终你应该能得到一个相当好的解决方案。

至少这是我们希望发生的事情,现在如果你看看这个算法,任何时候分析一个算法都要问一个好问题:进行计算时最昂贵的部分是什么?什么需要大量工作来搞清楚,什么将会很昂贵。

特别是在梯度下降的情况下,真正昂贵的部分是所有数据点的部分。在这里,需要使用所有的数据点来确定在所有权重的特定设置下梯度的值,因为在大数据集中这种情况的概率很高。

在机器学习问题中,当你试图解决一个有大量数据的大问题时,你有很多数据点。在计算和确定基于所有这些数据点的梯度时将是昂贵的,而且你需要多次进行这个过程。

一遍又一遍地查看所有数据点,反复进行小步伐,试图找出那些权重的最佳设置是什么。事实证明,我们理想情况下希望能够更快地训练我们的神经网络,以便更快地收敛到某种解决方案。

这将是一个良好的解决方案,因此在这种情况下,有比标准梯度下降更好的选择,后者一次性查看所有数据点。我们可以采用像随机梯度下降这样的方法,它将随机选择一个数据点来计算梯度。

基于所有数据点的计算,因此这里的想法是我们有一些权重设置,我们选择一个数据点,并基于那个数据点确定应该如何调整所有权重,并在那个小方向上移动权重,然后再选择另一个数据点并这样做。

再次重复这个过程,可能多次查看每个数据点,但每次只使用一个数据点来计算梯度,以确定我们应该朝哪个方向移动。现在,仅使用一个数据点而不是所有数据点,可能会使我们得出的结论不够准确。

这是对梯度的估计,但从好的一面来看,基于一个数据点计算梯度将会更快,而不是基于所有数据点进行计算,并且一次又一次地进行所有计算工作。

在查看所有数据点与仅查看一个数据点之间存在权衡,结果表明,一个也相当流行的中间选择是称为小批量梯度下降的技术,其中的理念是与查看所有数据相比,仅查看一个数据点。

我们将数据集分成小批量的数据点组。你可以决定每个批次的大小,但简而言之,你只是会在任何给定时间查看少量的数据点,希望能够更准确地估计梯度,同时也不需要所有的计算。

计算每一个数据点所需的计算量是巨大的。因此,梯度下降是一种我们可以用来训练神经网络的技术,以便确定所有权重的设置,如果我们想要某种方式来获得准确的概念。

这个函数应该如何工作,以及如何建模将输入转换为特定输出的方式。目前我们查看的网络结构都类似,我们有一些输入,可能是两个、三个、五个或更多,然后我们有一个输出。

但在机器学习问题中,我们通常不仅关心一个输出,而是可能关心一个与多个不同值相关的输出。因此,正如我们可以取一个神经网络并添加单元一样。

输入层,我们同样可以在输出层添加输入或输出。除了一个输出外,你可以想象我们有两个输出,或者我们可能有四个输出,例如,在每种情况下,随着输入或输出的增加,如果我们希望保持这个网络的完全连接。

这两个层我们只需要添加更多的权重,现在每个输入节点都有四个权重与四个输出相关联,并且对这些不同的输入节点都是如此,因此随着节点的增加,我们添加更多的权重,以确保每个输入都能以某种方式。

与每个输出相连接,以便每个输出值可以根据输入的值进行计算。我提到过,为什么我们想要多个不同的输出值的情况,比如天气预测。例如,我们可能不仅仅是在预测雨或不雨,或者只是预测一个特定的值。

无论是下雨还是不下雨,可能会有多种不同的天气类别,我们希望将天气分类为单一的输出变量,我们可以进行二元分类,例如下雨或不下雨(1或0),但这并不能让我们做到更多。

对于多个输出变量,我可能能够使用每一个来预测一些略有不同的内容,可能我想将天气分类为四个不同的类别,比如说,它会是下雨、晴天、多云还是下雪,现在我有4个可以用来预测的输出变量。

这些输入可能代表下雨的概率,与晴天、多云或下雪相对,那么这个神经网络是如何工作的呢?我们有一些输入变量,这些变量代表我们收集到的天气数据。

这些不同的权重,我们还有更多的乘法运算要做,但这些都是相当快速的数学运算,然后我们得到的结果是在通过某种激活函数后,在输出中得到的某种数字,你可以想象这个数字。

可以将其解释为概率,就像一个类别的概率与另一个类别的概率相比,所以在这里,我们根据输入认为下雨的概率是10%,晴天的概率是60%,多云的概率是20%,下雪的概率是10%,如果给定这个输出。

这些表示概率分布,那么你可以选择值最高的那个,在这种情况下是晴天,并且说我们最可能认为这些输入的分类意味着输出应该是下雪的,或者应该是晴天,这就是我们要的结果。

期望天气在这个特定的实例中是怎样的,这使我们能够进行这种多类别分类,而不仅仅是二元分类(1或0),我们可以有任意多的类别,并且我们的神经网络可以输出这些概率。

哪些类别比其他类别更可能,并利用这种推断来决定我们应该做什么,这就是监督机器学习的想法。我可以给神经网络提供大量数据以及与某些标签对应的输入数据。

我们知道这一天是下雨的,那一天是晴天,利用所有这些数据,算法可以使用梯度下降来计算所有权重,以创建某种模型,希望能够让我们预测我们认为天气会怎样,但神经网络还有很多其他。

同样的应用,你可以想象将这种思想应用于强化学习的例子,记住在强化学习中我们想要做的是训练某种代理来学习根据其当前所处的状态采取什么行动。

根据世界的当前状态,我们希望代理从可用的可采取的行动中选择一个,你可能会通过让每个输入变量代表一些关于状态的信息来进行建模,关于我们代理当前所处状态的一些数据,然后。

输出例如可以是我们代理可以采取的各种不同动作,动作一、二、三和四,你可能想象这个网络的工作方式是,根据这些特定的输入,我们继续计算每个输出的值,而这些输出可能。

模型评估哪个动作优于其他动作,我们可以仅仅根据查看这些输出来选择应该采取的行动,因此这些神经网络具有广泛的适用性,它们所做的实际上就是建模某种数学函数,所以任何我们能框定为一个。

数学函数类似于将输入分类为各种不同类别,或者基于某些输入状态来确定我们应该采取的行动,这些都是我们可以通过利用神经网络结构进行建模的数学函数,特别是。

利用这种技术,梯度下降,我们可以用来确定权重应该是什么,以便进行这种计算,那么你将如何训练一个有多个输出的神经网络,而不仅仅是一个呢?对于单个输出,我们可以。

查看该值的输出应该是什么,然后更新与其对应的所有权重,当我们在这个特定情况下有多个输出时,我们可以将其真正视为四个独立的神经网络,实际上我们这里只有一个网络,有这三个。

输入与这三个权重对应,这些权重对应于这个单一输出值,同样的事情也适用于这个输出值,这个输出值实际上定义了另一个神经网络,该网络具有这三个相同的输入,但对应于这个输出的权重集不同。

这个输出也有自己的权重集,第四个输出也是如此,因此如果你想训练一个有四个输出的神经网络,而不是仅仅一个,在这种情况下输入直接连接到输出,你可以真的把它看作是为独立的神经。

我们知道这些四个输出应基于我们的输入数据,并利用这些数据,我们可以开始确定这些个别权重应是什么,也许在最后还有一个额外步骤,以确保我们将这些值转化为概率分布。

这样我们可以解释哪个类别比另一个更好或更可能,因此这似乎在处理输入并试图预测输出时表现得相当不错,我们将很快看到一些实际例子,但这。

仅仅是取某些输入的线性组合,并将其传递到某种激活函数中。结果发现,当我们在二元分类的情况下进行此操作时,试图预测某个点是否属于某个类别。

是某个类别或另一个类别,我们只能预测线性可分的事物,因为我们正在取输入的线性组合并用它来定义某个决策边界或阈值,因此我们得到的情况是,如果我们有这组数据,我们可以预测像一条线那样。

它线性分隔红点与蓝点,但一个进行二元分类的单元,即感知器,无法处理这种情况,我们曾见过这种情况,其中没有一条直线可以直接穿过数据。

将红点与蓝点分开,这是一个更复杂的决策边界,决策边界必须捕捉圆圈内部的事物,而实际上并没有一条线能让我们处理这个问题。因此,这就是感知器的局限性,这些单元仅根据输入做出二元决策,单个感知器只能学习线性可分的决策边界,它所能做的只是定义一条线。

当然,它可以根据我们距离该决策边界的远近给出概率,但它只能真正基于线性决策做出判断。

边界,因此这似乎不太可能推广到涉及真实世界数据的情况,因为真实世界数据通常不是线性可分的,往往不能仅仅通过一条线将数据划分成多个组。那么重要的是要考虑这种方法的局限性。

这个问题的解决方案是提出了多层神经网络的概念,到目前为止,我们看到的所有神经网络都有一组输入和一组输出,而输入与这些输出连接,但在多层神经网络中,这将是一个。

人工神经网络,仍然有一个输入层,还有一个输出层,但中间还有一个或多个隐藏层,其他层的人工神经元或单元也将计算它们自己的值。因此,神经网络看起来并不是像这样有三个输入和一个。

输出时,你可能会想象在中间,注入一个隐藏层,像这样,这是一个有四个节点的隐藏层。你可以选择进入隐藏层的节点或单元的数量,你也可以有多个。隐藏层,因此现在每个输入并不是直接连接到。

输出的,每个输入都连接到这个隐藏层,然后隐藏层中的所有节点,都连接到一个输出。这只是我们可以迈向计算更复杂函数的又一步,这些隐藏单元将计算它的输出值。

也被称为其激活值,基于所有输入的线性组合。一旦我们对所有这些节点有了值,而不是这仅仅是输出,我们再次做同样的事情,根据将这些单元的值与它们的权重相乘来计算这个节点的输出。

因此,实际上它的工作方式是我们从输入开始,这些输入乘以权重。计算隐藏节点的值,这些值再次乘以权重,以确定最终输出将是什么,像这样分层的优点是它让我们能够建模更复杂的。

函数,但不是仅仅有一个单一的决策边界,一条线。将红点与蓝点分开,每个隐藏节点都可以。学习一个不同的决策边界,我们可以将这些决策边界结合起来。来确定最终的输出将会是什么,随着我们开始。

想象更复杂的情况,你可以想象这些节点学习某种有用的属性或,学习所有输入的某种有用特征,而我们以某种方式学习如何将这些特征结合在一起,以获得我们实际上想要的输出,现在自然会问。

你开始查看这个问题,现在是要问,如何训练一个内部有隐藏层的神经网络。这最初是一个有点棘手的问题,因为我们给定的输入数据是,我们得到了所有输入的值,以及输出的值。

例如,输入数据并没有告诉我们这些节点的值应该是什么,因此我们不知道这些节点实际上离目标有多远,因为我们仅仅得到了输入和输出的数据。这就是为什么这被称为隐藏层。

提供给我们的数据,并没有告诉我们所有这些中间节点的值应该是什么。

哈佛CS50-AI | Python人工智能入门(2020·完整版) - P18:L5- 神经网络 2 (反向传播,过拟合,tensorflow,计算机视觉) - ShowMeAI - BV1AQ4y1y7wy

实际上,人们提出的策略是,如果你知道输出节点上的错误或损失是什么,那么基于这些权重,如果其中一个权重比另一个高,你可以计算出这个节点的错误在多大程度上是由于这个。

隐藏节点的部分,或者隐藏层的这一部分,或者隐藏层的这一部分,基于这些权重的值,实际上是在说,根据输出的错误,我可以反向传播错误,并弄清楚每个隐藏层节点的错误估计是什么。

这里还有一些微积分,我们不会详细讨论。这个算法的思想被称为反向传播,它是一个用于训练神经网络的算法,具有多个不同的隐藏层。对于这个算法的伪代码,如果我们想要运行。

使用带有反向传播的梯度下降,我们将从随机选择的权重开始,正如我们之前所做的,现在我们将继续重复训练过程。一次又一次,但每次我们要做的是现在我们将会。首先计算输出层的错误,我们知道输出是什么。

应该是什么,我们知道我们计算了什么,因此我们可以弄清楚有什么错误。然后我们会对每一层进行重复,从输出层开始,向回移动到隐藏层,然后是之前的隐藏层。如果有多个隐藏层,将一直向回到最初的。

隐藏层假设它们是多个,我们将会把错误向回传播。每一层,无论输出的错误是什么,弄清楚在那之前一层的错误应该是什么,基于这些权重的值。然后我们可以更新这些权重,所以,从图形上来看,你可能会想。

关于这一点,我们首先从输出开始,我们知道输出应该是什么,我们知道计算出的输出是什么,基于此我们可以。弄清楚我们需要如何更新这些权重,将错误反向传播到这些节点,并利用它,我们可以弄清楚我们应该如何更新。

这些权重,你可能想象一下,如果有多个层,我们可以。重复这个过程一次又一次,以开始弄清楚所有这些。权重在这个反向传播算法中应该如何更新,这确实是关键。算法使得神经网络成为可能,它使得我们能够进行。

这些多层结构,能够训练这些结构,具体取决于这些权重的值,以弄清楚我们应该如何更新这些权重,从而创建一个能够最小化总损失的函数,找出一些好的设置。

权重将输入转换为我们期望的输出,正如我们所说,这不仅适用于单个隐藏层,您可以想象多个隐藏层,在每个隐藏层中定义所需的节点数量,每个节点都可以连接到下一个层的节点。

定义越来越复杂的网络,能够建模越来越复杂类型的函数,因此这种类型的网络可以称为深度神经网络,属于深度学习算法的大家族,如果您听说过这个术语,所有深度学习关注的就是。

它利用多个层来预测并建模输入中的高级特征,以确定输出应该是什么,因此深度神经网络就是一个具有多个隐藏层的神经网络,从输入开始计算。

对于这一层的值,然后是这一层,然后是这一层,最终得到输出,这使我们能够建模越来越复杂的函数,每一层可以计算一些略有不同的内容,我们可以结合这些信息来确定输出应该是什么。

当然,在任何机器学习的情况下,随着我们开始使模型变得越来越复杂,以建模越来越复杂的函数,我们面临的风险是过拟合,上次我们在过拟合的上下文中讨论了这一点。

我们在训练模型时,试图学习某种决策边界,过拟合发生在我们对训练数据拟合得过于紧密,因此我们对其他情况的泛化效果较差,而我们在一个复杂的神经网络中面临的风险是。

不同的节点可能会因为输入数据而导致过拟合,我们可能过于依赖某些节点,仅仅基于输入数据进行计算,这不允许我们很好地泛化到输出,并且有很多策略可以应对过拟合。

在神经网络的背景下,最流行的技术被称为 dropout,dropout 的作用是在训练神经网络时,暂时移除某些单元,随机选择这些人工神经元,从而达到目的。

防止对某些单元的过度依赖,过拟合通常发生在我们开始过于依赖神经网络内部的某些单元,以告诉我们如何解读输入数据。dropout 的作用是随机移除一些单元,以减少。

我们可能过度依赖某些单元,以使我们的神经网络更加健壮,以便能够处理情况,即使我们完全丢弃特定神经元。所以,这样的工作方式是我们有一个这样的网络,当我们训练它时,当我们更新权重时。

第一次我们将随机选择一些百分比的节点从网络中丢弃,就好像那些节点的权重根本不存在一样,然后以这种方式进行训练,接下来当我们更新权重时,我们将选择另一组节点并继续训练。

随机选择并训练与其他被丢弃的节点一起,目标是,在训练过程中,如果通过随机丢弃网络内部的节点进行训练,希望最终得到一个更健壮的网络,不会过于依赖。

任何特定节点,但更普遍地说是学习如何近似一个函数,所以这就是我们可以使用的一些技术,以实现一个神经网络,从而理解将这个输入通过这些不同的层进行处理的思路。

生成某种输出,现在我们想做的是将这些想法付诸于代码,为此,有许多不同的机器学习库和神经网络库可以使用,这些库允许我们访问某些人的反向传播实现和所有这些隐藏层。

最受欢迎的由谷歌开发的库被称为tensorflow,这是一个我们可以用来快速创建神经网络并对其进行建模和在一些样本数据上运行的库,以查看结果。

输出将是什么,在我们实际上开始编写代码之前,我们将先查看张量流的游乐场,这将为我们提供一个机会,让我们玩一玩神经网络和不同层次的概念,以便更好地理解我们可以利用什么。

神经网络,所以我们继续进入张量流的游乐场,你可以通过访问之前的URL来进入,我们现在要做的是尝试学习。

对于这个特定输出的决策边界,我想学习如何分离这些。

从蓝点到橙点,我想要学习一种神经网络内部的权重设置,这将能够将它们彼此分离。我们可以访问的输入数据特征是x值和y值,即两个轴上的两个值,现在我将进行的操作是。

我可以设置特定的参数,比如我想使用什么激活函数,然后我会按下播放,看看会发生什么。发生的事情是,你会看到仅通过使用这两个输入特征,x值和y值,没有隐藏层,只是根据这些输入预测x和y坐标的输出。

我们的神经网络很快学会了,为了将这两个点分开,我们应该使用这条线。这条线作为决策边界,将这一组点与另一组点分开,并且做得很好。你可以在这里看到损失是多少。

训练损失为零,意味着我们能够完美地建模,将这两个点从我们的训练数据中分离开来。所以这是一个相对简单的案例,尝试应用神经网络,因为数据非常干净,线性可分性很好,我们可以画一条线来分开。

现在让我们考虑一个更复杂的案例,先将模拟暂停,我们来看一下这个数据集,这个数据集稍微复杂一点。在这个数据集中,我们仍然有蓝色和橙色的点,我们希望将它们分开。

但是没有一条线能够将蓝色与橙色分开,因为蓝色位于这两个象限,而橙色位于这里和这里。这是一个更复杂的函数需要学习,所以让我们看看如果我们尝试一下这些点会发生什么。

我会按下播放,你会注意到我们似乎无法得出很清晰的结论,无法非常清楚地看到我们应该如何将橙色点与蓝色点分开,你没有看到一个非常。

这样看起来,我们的网络没有足够的复杂性来建模如此复杂的情况。我们需要一个更好的中心网络模型,我会通过添加一个隐藏层来实现这一点,现在我有一个包含两个神经元的隐藏层。

我有两个输入,然后传递给隐藏层中的两个神经元,再到我们的输出。现在我会按下播放,你会注意到我们能够做得稍微更好,我们能够说这些点绝对是蓝色的,这些点绝对是橙色的,但我们仍然在努力。

我们可以看到每个隐藏神经元到底在做什么。每个隐藏神经元都在学习自己的决策边界,我们可以看到这个边界。第一个神经元正在学习这条线,这似乎将一些y值分开。

这个隐藏神经元正在学习另一条线,似乎正在将右下角的橙点与其他点分开,这就是我们能够确定底部区域这两个区域的原因,但我们仍然无法。

好吧,使用两个神经元和一个隐藏层,我们能够完美地对所有点进行分类,所以让我们继续添加另一个神经元,现在我们的隐藏层中有三个神经元,看看我们现在能够学习到什么,好吧,现在我们似乎通过学习三个不同的决策边界做得更好,每个神经元都有各自的决策边界。

在我们的隐藏层中,我们能够更好地找出如何将这些蓝点与橙点分开,你可以看到每个隐藏神经元正在学习什么,每个神经元都在学习一个略微不同的决策边界,然后我们将这些决策边界组合在一起,以确定什么。

整体输出应该是,我的意思是我们可以再试一次,添加一个第四个神经元,并尝试学习,现在我们似乎能更好地尝试将蓝点与橙点分开,但我们只有通过添加一个隐藏层来实现这一点。

正在学习一些其他的边界,并结合这些边界来确定输出,线条的大小和厚度表示这些权重的高低,以及每个输入对进行这种计算的重要性,我们也许可以再做一次模拟。

继续尝试在一个看起来像这样的数据集上,去掉这里的隐藏层,现在我们尝试将蓝点与橙点分开,所有蓝点都有效地位于一个圆内,所以我们无法学习一条直线,注意我按下播放。

现在使用三个不同的决策边界,每个神经元都学习到了,而我们真的无法绘制任何分类,因为没有一条线可以干净地将蓝点与橙点分开,所以让我们尝试通过引入一个隐藏层来解决这个问题,我按下播放。

做得稍微好一些,因为我们有效地学习了两个不同的决策边界,我们在这里学习了这条线,并在右侧学习了这条线,现在我们只是说,好吧,如果它在中间,我们就称之为蓝点,如果在外面,我们就称之为橙点,所以不是很好,但肯定能分开蓝点与其他点。

比之前好,我们学习了一个决策边界和另一个,基于这些我们可以弄清楚输出应该是什么,但现在我们继续添加第三个神经元,看看会发生什么,我现在去训练它。

我们能够处理这些隐藏的神经元。

更准确地对蓝点和橙点之间的区别建模,我们能够通过这三个决策边界的组合来推测,想象一下输出应该是什么,以及如何进行这种分类,因此这里的目标是。

只是为了让我们对这些隐藏层中的更多神经元有个概念,这让我们能学习到数据中的更多结构,找出相关和重要的决策边界,然后通过反向传播算法,我们能够确定这些权重的值。

以训练这个网络能够将一个类别的点与另一个类别的点区分开来,这正是我们在训练神经网络时最终要尝试做的事情,所以让我们实际上来看一个例子,你会记得。

上次我们讨论的内容涉及到包含关于伪钞与真钞信息的钞票文件。我有四种不同面值的钞票,并且对每种钞票进行了分类,判断其是被认为是真钞还是伪钞

我想做的是根据输入信息推导出一个函数,该函数能够基于输入信息计算它属于哪个类别。我在钞票顶部写的神经网络就是为了学习这一点,它会根据所有输入来判断。

我们应该将钞票分类为真钞伪钞,第一步与上次看到的相同,我实际上只是将数据读入并将其转换为适当的格式。这是编写Python代码的地方。

操作statum,调整数据格式以便机器学习库如scikit-learn或tensorflow能理解,因此我将其分为训练集和测试集,现在我正在使用的网络是TF,代表tensor flow。上面我提到导入tensor flow为tftf。

我们常用的一个缩写,我们不需要每次都写出tensorflow。我在使用TF. Charis。Charis是一个API,一组函数,用于在tensorflow中操作神经网络,结果表明还有其他机器。

学习库也使用Charis API,但我在这里说,好的,给我一个顺序模型,即一个层层相叠的神经网络,接下来我要在我的神经网络中添加我想要的层。

继续添加一个密集层,当我们说密集层时,我们指的是该层中的每个节点都将与前一层中的每个节点相连,所以我们有一个密集连接的层,这一层将有八个单位在里面,因此它将是一个。

在我们的神经网络中,有一个隐藏层,里面有八个不同的单位,八个人工神经元,每个神经元可能学习不同的东西,我只是随意选择了八个,你可以选择不同数量的隐藏层节点,如果我们之前看到的。

根据隐藏层中单位的数量,更多的单位意味着你可以学习更复杂的函数,因此你可能可以更准确地建模训练数据,但这也带来了成本,更多的单位意味着你需要弄清楚如何更新更多的权重,所以可能会更复杂。

进行这样的计算是昂贵的,如果你有太多的单位,可能会导致对数据的过拟合,如果你学习只是过度拟合训练数据,那也不好,所以这之间存在一个平衡,通常会有一个测试过程,在某些数据上进行训练,并可能验证你做得有多好。

在一组单独的数据上,通常称为验证集,以查看哪种参数设置,应该有多少层,每层应该有多少单位,哪一个在验证集上表现最好,因此你可以进行一些测试来弄清楚这些超参数。

应该等于接下来我指定输入形状,这意味着我的输入是什么样的,我的输入有四个值,因此输入形状就是四,因为我们有四个输入,然后我指定激活函数是什么,激活函数,我们可以选择,有很多种。

不同的激活函数,在这里我使用的是relu,可能你之前听说过。然后我将添加一个输出层,因此我现在有了我的隐藏层,再添加一层,这一层将只有一个单位,因为我想预测的只是像假钞或真实钞票这样的东西,所以我只需要一个。

单位和激活函数,我将使用的激活函数是sigmoid激活函数,它是那个S形曲线,它给了我们一个概率,表示这是一张假钞的概率,与真实钞票相比,因此这就是我的神经网络的结构。

这是一个顺序神经网络,包含一个有八个单位的隐藏层和一个仅有一个单位的输出层,我可以选择有多少个单位,可以选择激活函数,然后我要编译这个模型,tensorflow让你选择如何。

我希望优化权重,有多种不同的算法可以做到这一点,想要使用什么样的损失函数也有很多选项,接下来我希望如何评估我的模型,我关心准确性,我关心我能分类多少个点。

正确与不正确的分类,即伪钞与真钞。我希望它能告诉我我的模型表现得有多准确。现在我已经定义了模型,我调用model.dot fit来训练模型,使用所有训练数据以及所有训练标签。

我为每一部分训练数据设置标签,并且我说运行20个周期,意味着对每一个训练点进行20次有效的遍历,并且不断尝试更新权重。如果我多做一些,我可以训练更长时间,或许会得到一个更好的结果。

更准确的结果,但在我将其应用于所有数据后,我将继续进行测试。我会使用内置于TensorFlow的模型评估来评估我的模型,它会告诉我在测试数据上的表现如何。所以,最终这只是会给我一些数字,告诉我我们的表现如何。

在这种情况下我将进入银行票据,继续运行银行票据的顶级PI。接下来会发生的是,它将读取所有训练数据,并生成一个神经网络,包含我所有的输入和8个隐藏层的单位。

有一层,然后是一个输出单元,现在它正在进行训练,每次训练20次。你可以看到我的数据,第一次的时候并不是很准确,胜过随机的情况,大约有79%的时间能够准确区分一张钞票与另一张,但随着训练的进行。

注意到他的准确率不断提高,直到在经过多次训练后,我的准确率在训练数据上超过了99%。在这里,我在一堆测试数据上测试,结果显示我在这种情况下的准确率也是99.8%,所以仅凭这些。

我能够生成一个神经网络,可以根据这个检测伪钞与真实钞票的能力。!

输入数据在至少99.8%的时间内能够准确分类,基于这组特定的测试数据,我可能还想用更多的数据进行测试,以增强信心,但这确实是使用像TensorFlow这样的机器学习库的价值,还有其他可用于Python的库

还有其他语言,但我所需要做的就是定义网络的结构,并定义要输入到网络中的数据,然后 TensorFlow 会运行反向传播算法,以学习这些权重应该是什么,从而训练这个神经网络。

尽可能准确地确定输出值应该是什么,因此,这就是我们查看神经网络可以做什么的方式,利用一层一层的序列,你可以开始想象将这些应用于更一般的问题。

计算和人工智能中的一个问题,尤其是计算机视觉的问题。计算机视觉涉及对图像进行分析和理解的计算方法。你可能有一些图片,希望计算机能够理解如何处理这些图像。

并找出如何从中产生某种有用的结果。你已经在社交媒体的上下文中见过这一点,社交媒体网站能够查看包含大量人脸的照片,并能够识别出每张照片中的人,并为他们贴上标签。

随着我们开始讨论自动驾驶汽车,这变得越来越相关。这些汽车现在配备了摄像头,我们希望计算机能够有某种算法,查看图像并判断例如交通灯的颜色、周围的汽车以及它们的方向。计算机视觉在这里就是关键。

所有这些都是关于获取图像并确定我们可以对图像进行何种计算,这在手写识别的上下文中也是相关的。这是你所看到的 EM NIST 数据集的一个例子,它是一个仅包含手写数字的大型数据集。

我们可以使用数字,理想情况下试图预测给定某人的手写或他们绘制的数字照片时,能否预测它是 0、1、2、3、4、5、6、7、8 或 9。例如,这种手写识别是我们可能想要使用计算机视觉的另一项任务。

计算机视觉任务和工具可能是我们关心的任务。那么,我们如何使用神经网络来解决这样的问题呢?神经网络依赖某种输入,该输入只是数值数据,我们有一堆单元。

它们每一个都表示某种数字,因此在手写识别或图像的上下文中,你可以想象图像实际上只是一个像素网格,每个点都有某种颜色。

在手写识别中,你可以想象,如果你以某种特定的方式填充这些点,你可以生成像2或8这样的数字,具体取决于哪些点被填充,哪些点没有。我们可以用数字来表示每个像素值。

例如,像素0可能表示完全黑色,具体取决于你如何表示颜色。通常,颜色值被表示在0到255的范围内,这样你就可以使用8位表示特定值,比如图像中白色的多少。因此,0可能表示全黑,255可能表示全白。

在这之间的某个值可能表示某种灰色的阴影。你可以想象,不仅仅有一个滑块来决定图像中白色的多少,如果你有一张彩色图像,你可以想象有三个不同的数值:红色、绿色和蓝色。

红色值控制图像中红色的多少,我们有一个值控制像素中绿色的多少,还有一个值控制像素中蓝色的多少。根据你设置红、绿、蓝这些值的方式,你可以获得不同的颜色。

像素实际上可以用三个数值来表示:红色值、绿色值和蓝色值。如果你把一堆这样的像素组合在一起,放在一个像素网格中,你就有了一大堆数值,可以用来进行操作。

对于某种预测任务,你可能会想象使用之前讨论过的相同技术,设计一个有很多输入的神经网络,对于每个像素来说,我们可能在彩色图像的情况下有一个或三个不同的输入。

比如说,把这些输入传递给一个深度神经网络,这个深度神经网络可能会处理图像中的所有像素,比如一个人画的数字,输出可能是十个神经元,它将其分类为0、1、2或3,或者以某种方式告诉我们这个数字是什么。

这种方法有几个缺点,第一个缺点是输入数组的大小。如果我们有一个大图像,就会有很多不同的通道,我们要查看很多输入,因此需要计算很多权重。

问题在于,通过将所有内容压缩成这种像素结构,我们失去了许多关于图像结构的信息,这些信息是相关的。但实际上,当一个人查看图像时,他们是在观察图像的特定特征。

观察曲线或形状,看看你能在图像的不同区域识别出什么,可能将这些东西组合在一起,以便更好地了解整体图像的含义。通过将其转换为每个像素的像素值,你可以。

可能能够学习到这种结构,但这可能会很具挑战性。为了做到这一点,利用图像本身的特性可能会很有帮助,事实上,它以特定方式结构化,以便改善我们基于该图像的学习方式——所以为了。

为了弄清楚如何训练我们的神经网络更好地处理图像,我们将引入几个想法和算法,这些算法可以应用于让我们从图像中提取一些有用的信息。我们将介绍的第一个概念是图像的。

图像卷积的演变是关于过滤图像,提取图像中有用或相关特征的。我们这样做的方法是通过应用一个特定的滤镜,基本上是将每个像素的值与所有邻近像素的值相加。

根据某种卷积核矩阵对其进行处理,稍后我们将看到,这将允许我们以各种不同的方式对这些像素进行加权。因此,图像卷积的目标是从图像中提取一些有趣或有用的特征,以便能够根据其。

邻近像素可能预测某种有价值的信息,比如取一个像素并查看其邻近像素,你可能能够预测图像内部是否存在某种曲线,或者它是否在形成特定线条或形状的轮廓,例如。

如果你试图使用所有这些不同的特性,结合它们来对整个图像做出有意义的陈述,这可能会很有用。那么,图像卷积是如何工作的呢?我们从一个卷积核矩阵开始,卷积核矩阵看起来像这样,基本理念是给定。

中间像素将是一个像素,我们将通过这些值对每个邻近像素进行乘法运算,以便通过将所有数字加在一起得到某种结果。因此,如果我取这个卷积核,你可以将其视为我将应用于图像的滤镜。假设我。

以这个图像为例,这是一个四乘四的图像,可以将其视为仅包含单个像素值的黑白图像,例如在0到255之间。所以我们有一大堆单独的像素值,我想做的是应用这个卷积核这个滤镜。

讲述这个图像,我将这样做,卷积核是 3x3。你可以想象一个 5x5 的卷积核或更大的卷积核,我会先将其应用于图像的第一个 3x3 部分,我将做的是将这些像素值与其对应的值相乘。

在过滤矩阵中,将所有结果加在一起。因此,在这里举个例子,我会说 10 乘以 0 加 20 乘以负 1 加 30 乘以 0,以此类推。完成所有这些计算后,最后如果我将这些值相加,对于这组特定的九个像素,我得到。

例如,值为 10,然后我会将这个三乘三的网格有效地滑动,滑动卷积核一单位以查看下一个三乘三的部分。在这里,我只是在滑动一个像素,但你可以想象不同的步长,或者可能一次跳过多个像素。

如果你真的想要,你可以在这里有不同的选择,但我只是在滑动,查看下一个 3x3 部分,我会做同样的数学,20 乘以 0 加 30 乘以负 1 加 40 乘以 0 加 20 乘以负 1,以此类推,加上 30 乘以 5,然后我。

最后得到的是数字二十,然后你可以想象把这个值移到这里。做同样的事情,计算比如数字四十,然后再做一次。现在我们得到的就是我们所称的特征图,我们将这个卷积核应用于这些不同区域,我们。

得到的是像图像的过滤版本的一些表示。因此,为了给出一个更具体的例子,说明为什么这种事情可能有用,我们以这个卷积核矩阵为例,这是一个非常著名的例子,它在中间加了八,然后所有相邻的像素得到负值。

一的值。让我们想象一下,我们想把这个应用于图像的一个三乘三部分,图像看起来像这样,所有的值都是相同的,都是 xx。比如在这种情况下,如果你做 20 乘以 8,然后减去 20,减去 20,再减去每个八个邻居的 20。

那样的结果就是你得到的表达式为零。你乘以 20 和 8,但然后你减去了 20 乘以 8,根据那个特定的卷积核,所有这些结果就是零。因此,关键在于,当很多像素的值相同时,我们最终得到。

如果我们加上类似这个 20s 的东西,得到的值接近零。第一行是 50s,第二行和第三行也是 50s。当你这样做时,因为同样的数学,二十乘以负一,二十乘以负一,以此类推,那么我会得到一个更高的值。

在这种特定情况下大约是90,因此这里更一般的想法是,通过应用这个内核,负值、八在中间,然后是负值。当这个中间值与邻近值(比如50大于这些20)差异很大时,你最终会得到一个更高的值。

如果这个数字大于零,假如这个数字高于其邻居,你最终会得到一个更大的输出,但如果这个邻居的值与所有邻居相同,那么你会得到一个较低的输出,比如零。结果是,这种过滤器可以用于某些东西。

检测图像中的边缘,或者我想检测图像中不同对象之间的边界,我可能会使用这样的过滤器,它能够判断这个像素的值是否与邻近像素的值不同,如果它大于邻近像素的值。

像素周围的情况,所以我们可以在图像过滤方面使用它。我会给你展示一个例子,我这里有一个在filter.dot PI文件中使用Python的图像库或PIL进行图像过滤的代码。我打开一张图像,然后我所要做的就是应用一个。

对于那张图像的内核,它将是一个三乘三的内核,和之前看到的那种内核相同。这是内核的列表表示,和我刚刚给你展示的矩阵相同,它是负一、负一、负一,第二行是负一、八、负一。

第三行全是负值和。

然后最后我要展示过滤后的图像,所以如果我进入卷积目录,打开一张像Bridge.png这样的图像,这就是输入图像的样子,只是一张桥在河上的图像,现在我将继续运行。

在桥上的这个过滤器程序,我得到的就是这张图像,只需通过将原始图像应用该过滤器到每个三乘三的网格。我提取了图像中分隔不同部分的所有边界和边缘。

图像的特定部分,你可以想象如果一个机器学习算法试图学习图像是什么样的,这样的过滤器可能非常有用,因为也许这个机器学习算法不在乎图像的所有细节,它只关心某些有用的特征。

它关心的特征,特定形状能够帮助它基于图像确定,这将是一个桥,例如,因此这种图像卷积的想法可以让我们将过滤器应用于图像,从而提取出有用的结果。

例如,它的边缘,你可能会想象许多其他可以应用于图像的滤镜,它们能够提取特定的值,一个滤镜可能会有单独的卷积核,针对红色值、绿色值和蓝色值,最后将这些值相加,这样你就可以得到。

特定滤镜在寻找图像的某部分是否有红色,其他部分是否有绿色,你可以开始组合这些相关和有用的滤镜,能够进行这些计算。因此,这就是图像卷积的概念,将某种滤镜应用于图像。

能够从图像中提取一些有用特征,但这些图像仍然相当大,图像中涉及很多像素。实际上,如果你有一个非常大的图像,这会带来几个问题,一个是输入到神经网络中的数据量很大,另一个是。

这也意味着我们确实需要关注每个特定像素的内容。而实际上,我们通常并不在意,比如当你查看图像时,你并不关心某个东西是否在一个特定像素中,而是在它旁边的像素中,它们距离很近,你实际上只是在乎。

关注某个区域是否存在特定特征,也许你并不关心具体是哪一个像素。所以这是一种我们可以使用的技术,称为池化,池化意味着减少。

通过从输入中的区域进行采样来减小输入的大小,因此我们将把一张大图像变成一张小图像,使用池化,特别是最流行的池化类型之一被称为最大池化。最大池化的作用是通过选择某个区域的最大值来进行池化。

例如,假设我有这个4x4的图像,但我想减少它的维度,想将其变为一张较小的图像,以便我有更少的输入可以使用,那么我可以应用2x2的最大池化,想法是,我首先查看这个。

在一个2x2区域中,如果我们查看该区域的最大值,那就是数字50,所以我们将使用数字50,然后我们将查看这个2x2区域,最大值是110,所以这将是我的值,同样,这里的最大值看起来是20,我们就放。

在最后的区域,最大值是40,所以我们将使用这个值,而现在我有的是同一原始图像的一个较小表示,这个表示是通过从这些区域中选择最大值获得的。因此,这里的优势在于现在我只需。

处理一个二乘二的输入,而不是四乘四的输入,你可以想象。进一步缩小图像的大小,但除此之外,我现在能够。使我的分析独立于是否,某个特定的值在这个像素或。这个像素中,我不在乎50是在这里还是在那里,只要它存在。

通常在这个区域,我仍然可以获取到那个值,这使得我们的。算法变得更加健壮,因此这就是池化,减少图像的。大小,通过从特定位置进行采样,稍微减少一点。

哈佛CS50-AI | Python人工智能入门(2020·完整版) - P19:L5- 神经网络 3 (卷积神经网络,循环神经网络) - ShowMeAI - BV1AQ4y1y7wy

图像内部的区域,现在我们可以将所有这些概念结合在一起。将图像池化、卷积和神经网络结合成另一种神经网络,称为卷积神经网络或CNN,这是一个使用卷积步骤的神经网络,通常是在上下文中。

例如,分析一张图像的方式是,卷积神经网络的工作原理是从某种输入图像开始,某个像素网格。

但不是立即放置我们之前看到的,我们将首先应用一个卷积步骤,其中卷积步骤涉及。

将一些不同的图像滤波器应用于我们的原始图像,以获取我们称之为特征图的结果,即将某个滤波器应用于图像的结果,我们可以做一次,但通常会做多次,得到一堆不同的特征图,每个特征图可能提取。

从图像中提取一些不同的相关特征,图像的一些不同重要特征,我们可能会关心这些特征,以计算结果应该是什么,和我们训练神经网络时一样,我们可以训练神经网络,学习特定之间的权重。

在神经网络内部,我们还可以训练神经网络以学习这些滤波器应该是什么,滤波器的值应该是什么,以便从原始图像中提取出最有用、最相关的信息,仅通过找出这些滤波器值的设置。

这个核的结果是最小化损失函数,最小化我们的假设在识别特定图像分类时表现的多差。例如,我们首先应用这个卷积步骤,得到一堆不同的特征图,但这些特征图相当大。

这里有很多像素值,因此接下来的逻辑步骤是池化步骤,我们通过使用最大池化等方法减少这些图像的大小,从特定区域提取最大值,还有其他存在的池化方法。

根据情况,你可以使用像平均池化这样的东西,取一个区域的平均值,而不是取最大值,这也有其用处,但实际上,池化会将这些特征图的维度降低,最终我们得到了。

更小的网格,像素更少,这样我们处理起来就更容易了,意味着我们要担心的输入会更少,也意味着我们对特定值潜在的移动会更有韧性、更强健,即使只是一个像素的变化,而最终我们并不真的。

关注原始图像中可能出现的一像素差异。在我们完成池化步骤后,我们现在拥有一堆值。然后我们可以将这些值展平,并放入一个更传统的神经网络中,因此我们继续展平它,然后得到一个传统的。

神经网络对每一个这些值有一个输入,这些值来自每个结果特征图,经过卷积和池化步骤后,这就是卷积网络的一般结构。我们从图像开始,应用卷积,应用池化,展平结果。

然后将其放入一个更传统的神经网络,该网络本身可能有隐藏层。你可以拥有深度卷积网络,在这个展平层和最终输出之间有隐藏层,以便能够计算这些值的各种不同特征,但这可以帮助我们能够使用。

使用卷积和池化利用我们对图像结构的知识,以便获得更好的结果,从而能更快地训练我们的网络,以更好地捕捉图像的特定部分。并且没有理由一定只能使用这些步骤一次,实际上在实践中你会。

多次在多个不同的步骤中使用卷积和池化,看看你可能想做什么。

首先从图像开始,应用卷积以获得一堆映射。然后应用池化,再次应用卷积,因为这些映射仍然相当大。你可以应用卷积来尝试提取相关特征,然后将这些结果应用池化。

减少它们的维度,然后将其输入到一个神经网络中。这个网络可能有更少的输入,因此我这里有两个不同的卷积和池化步骤。我先进行一次卷积和池化,然后再进行第二次卷积和池化,每次都从中提取有用的特征。

每次在前一层使用池化来减少你最终查看的内容的维度,现在这种模型的目标是,在每个步骤中,你可以开始学习原始图像的不同类型特征,在第一步中你学习非常低级的特征。

只学习并寻找特征,比如边缘、曲线和形状,因为基于像素及其邻近值,你可以弄清楚哪些是边缘,哪些是曲线,哪些是可能存在的各种不同形状。但是一旦你有一个映射,表示在哪里。

边缘、曲线和形状可以想象为,你可以想象再次应用相同的过程来开始寻找更高层次的特征,寻找物体,可能寻找人的眼睛和面部识别,例如,也许寻找更复杂的形状,比如特定数字上的曲线。

在手写识别的场景中识别一个数字,然后在拥有这些表示更高层次特征的结果后,你可以将它们传入一个神经网络,这实际上是一个深度神经网络。

二分类或多类别分类,进行各种不同的任务,卷积神经网络在这类模型中可以非常强大且受欢迎,尤其在分析时。

我们之前见过,但这些卷积神经网络在特别情况下非常有用,因为它们模拟了人类看图像的方式,而不是人类同时查看每一个像素并试图将其结合起来。

卷积真正做的就是查看图像的不同区域,并提取相关信息和特征,就像人类的视觉感受器一样,查看他们所见的特定部分并将其组合起来。

为了找出从这些不同输入中可以提取的意义,你可以想象将其应用于手写识别的情境,现在我们就来看看一个例子,我会再次打开handwriting.py,我们在这里首先导入。

TensorFlow中内置了一些数据集,你可以立即访问,其中一个最著名的机器学习数据集是EM NIST数据集,这是一个包含大量人们手写数字样本的数据集。

我之前给你展示了这个数据集的幻灯片,我们可以立即访问这个内置数据集,这样如果我想在大量手写数字上进行训练,我可以使用提供给我的数据集,当然,如果我有自己的数据集。

对于一组手写图像,我可以应用同样的思路,首先需要将这些图像转换为像素数组,因为这就是它们的格式,它们将有效地格式化为单个像素的数组,现在需要进行一些重塑。

需要将数据转换为可以输入到卷积神经网络中的格式,这包括将所有值除以255,如果你记得,这些颜色值通常在0到255之间,所以我可以将它们除以255,把它们转换为0到1的范围。

这可能会更容易训练,然后对数据进行各种其他修改,以使其变得更加可用,但这里有一个有趣且重要的部分,就是我创建卷积神经网络(CNN),在这里我说继续使用一个顺序模型。

在我能够使用模型添加之前,我需要说,添加一层再添加一层。另一种定义它的方法是,通过将我想要的所有层作为输入传递给这个顺序的神经网络。在我的模型中,第一层是一个卷积层,我将首先应用。

对我的图像进行卷积,我将使用13个不同的滤波器,因此我的模型将学习32种不同的滤波器,我希望在输入图像上学习,每个滤波器将是一个3x3的核,我们之前看到过这些3x3的核,我们可以对3x3网格中的每个值进行乘法运算。

通过一个值相乘并将所有结果加在一起,所以这里我将学习32种不同的3x3滤波器,我可以再次指定我的激活函数,并指定我的输入形状,我的输入形状在钞票的情况下是。只有4,我有4个输入,我的输入形状将在这里是28,28,1。

因为对于这些手写数字,NS数据集组织了它们的数据,每个图像是28x28像素的网格,所以我们将有一个28x28的像素网格,并且每个图像只有一个通道值。这些手写数字只有黑色和白色,所以它只是一个单一的颜色。

表示有多少黑色或多少白色,你可以想象在彩色图像中,如果你进行这种操作,你可能会有三个不同的通道,红色、绿色和蓝色通道,例如,但在仅进行手写识别,识别数字的情况下,我们只会使用一个。

像是有阴影还是没有阴影的值,它可能会有变化,但它只是一个单一的颜色值,这就是我们神经网络的第一层,一个卷积层,它将接受输入并学习许多不同的滤波器,我们可以应用这些滤波器来提取有意义的特征。

下一步将是一个最大池化层,这也直接构建在TensorFlow中,这将是一个层,使用2x2的池化大小,意味着我们将查看图像内部的2x2区域,并提取最大值,我们已经看到这可以如何有帮助。

一旦我们完成了这一步,就会减少输入的大小,我们将把所有的单元压平,变成一个单层,然后我们可以将其传递给其余的神经网络,现在这是其余的神经网络,在这里我说让我们给我的神经网络添加一个隐藏层。

一百二十八个单元,所以有一整堆隐藏单元在隐藏层里面。为了防止过拟合,我可以添加一个 dropout。比如说,你知道,在训练时随机丢弃这隐藏层中的一半节点,以确保我们不对任何特定节点过于依赖。

我们开始真正地泛化,并阻止自己过拟合。所以,TensorFlow 允许我们通过添加一行代码将 dropout 加入我们的模型,这样在训练时,它会执行这个 dropout 步骤,以帮助确保我们不会对这特定数据过拟合。

最后我添加一个输出层,输出层将有十个单元,分别对应我想将数字分类到的每个类别,从零到九,共十个不同类别,激活函数将使用 softmax 激活函数。

softmax 激活函数的作用是将输出转换为概率分布,所以最终它会告诉我,比如说我们估计这个是二与三或四的概率是多少,因此它将其转化为那个概率。

接下来我将编译我的模型,并在所有训练数据上进行拟合,然后我可以评估神经网络的表现。如果我在 Python 程序中提供了命令行参数,比如某个文件名。

我将模型保存到文件中,这在训练步骤完成后非常有用,这可能需要一些时间,涉及到通过数据进行反向传播和梯度下降,来调整权重分布。

对于这个特定模型,你最终会计算这些权重的值,计算这些过滤器的值,你希望记住这些信息,以便稍后使用。因此,TensorFlow 允许我们将模型保存到文件中,这样如果我们想使用已经学习的模型。

我们可以使用已经学到的权重进行一些新的预测,因此这里的做法是,在完成所有计算后,将模型保存到文件中,以便稍后使用。例如,如果我进入数字识别。

我将运行手写数字识别,这次不保存,只是运行并看看会发生什么。我们需要遍历模型,以训练 MS 数据集提供的所有手写数字样本,成千上万的样本。

手写数字以相同的格式,我们可以用来进行训练。因此,现在你看到的是这个训练过程,与银行票据的案例不同,数据点要少得多,数据非常简单。这里的数据更复杂,因此这个训练过程需要时间。

这是另一个案例,当训练神经网络时,这就是为什么计算能力如此重要,你经常看到人们想要使用复杂的GPU,以便更有效地进行这种神经网络训练。这也说明了为什么更多的数据可以。

拥有更多的样本数据点会更加有帮助,你的训练会做得更好。所以这里我们正在处理60,000个不同的手写数字样本,我说我们要遍历十次,所以我们将训练这个数据集十次。

我们每次运行这个数据集时,都在改进我们的权重。我们可以看到右侧显示了每次运行模型时的准确率,第一次看起来我们在这个训练集上约有92%的数字正确率,我们将其提升到96%或97%。

每次运行这个模型时,我们希望准确率能够提高,随着我们继续使用梯度下降的方法,尽量运行算法以最小化损失,从而更准确地预测输出应该是什么。

这个过程不仅在学习权重,还在学习特征,使用核矩阵在执行卷积步骤时,因为这是一个卷积神经网络,我首先执行卷积,然后进行更传统的神经网络操作。

这个网络结构将学习所有这些个体步骤,因此这里我们看到TensorFlow为我提供了一些非常好的输出,告诉我每次训练运行剩余的秒数,让我看到我们的表现如何,所以我们继续观察。

这个网络的表现看起来,我们已经遍历了数据集七次,现在正在进行第八次,此时准确率相当高,我们看到准确率从92%提升到97%,现在看起来是98%,此时似乎事情开始趋于平稳。

可能存在一个限制,关于我们能最终达到的准确率,而不冒过拟合的风险,当然,足够的节点可能会使你仅仅记住输入并导致过拟合,但我们希望避免这样,dropout将帮助我们,但现在我们看到快要完成了。

在我们的训练步骤中,我们达到了五万五千,好的,我们完成了训练。现在它将继续为我们在一万个样本上进行测试,似乎在测试集中我们的准确率是九十八点八百分之,所以在这个测试上,我们表现得相当不错。

测试集以查看我们能够多准确地预测这些手写数字。因此,我们可以测试一下,我写了一个程序叫做 recognition.dot pi,使用 PI game,如果你传入一个经过训练的模型,而我使用这些输入数据预训练了一个示例模型。

我们可以看看是否能够训练这个卷积神经网络,以预测手写。例如,我可以尝试像画一个手写数字一样,我将绘制数字二。比如说,这是我的数字二,再次看起来有点凌乱。

尝试想象如何用仅仅是 if 语句和 x' 来编写程序,以进行这样的计算,这会很棘手。但是在这里我会进行分类,似乎它能够正确地分类我画的数字是二,我将重置它并再试一次。

再次画一个八的样子。

例如,这里是一个八的分类,它预测我画的数字是八,关键在于这开始展示了神经网络的强大,它以某种方式观察这些不同像素的各种特征,找出这些特征。

相关特征并找出如何组合它们以获得分类,这将是一个困难的任务,因为需要向计算机提供明确的指令,如何处理大量的 if 语句以处理所有这些像素值,找出手写数字。

每个人画的八都会有所不同,如果我再次画八,它看起来会有所不同,而理想情况下,我们希望训练网络足够稳健,以便它开始自行学习这些模式。我所说的就是,这里是网络的结构。

这是用于训练网络的数据,而网络学习算法只是试图找出什么是最优的权重集合,什么是最优的过滤器,以便能够准确地将数字分类到一个类别或另一个类别,这将展示出强大的能力。

这些卷积神经网络的种类以及我们如何利用卷积神经网络开始解决与计算机视觉相关的问题,例如能够分析图像,这就是你可以想象的分析类型。

这种情况在自动驾驶汽车中发生,它们能够判断应用什么过滤器来理解计算机正在查看的图像,或者相同的想法也可以应用于社交媒体中的面部识别,以确定如何在图像中识别面孔。

想象一个神经网络,它不是将输入分类为十个不同的数字,而是能够判断这个人是A还是B,试图仅仅基于卷积将这些人区分开。因此,现在我们将看的是另一种类型的神经网络。

对于某些类型的任务,可能相当受欢迎,但这样做会尝试进行泛化,并更抽象地思考我们的神经网络。这里我们有一个样本深度神经网络,输入层有一整堆不同的隐藏层,执行某些类型的操作。

进行计算,然后是输出层,生成我们关心的某种输出,但我们可以想象将其表示得更简单一点,这里是我们神经网络的更抽象表示,输入可能像是一个向量。

一堆不同的值作为输入传递到网络中,以执行某种计算或运算,该网络产生某种输出。这个输出可能是一个单一值,也可能是一整堆不同的值,但这就是神经网络的一般结构。

我们看到有某种输入被输入到网络中,并且使用该输入计算输出应该是什么,这种口头网络模型我们可能称之为前馈神经网络。前馈神经网络的连接仅在一个方向上,它们从一个层移动到下一个层。

从一层传递到下一层,再到之后的层,使得输入通过不同的隐藏层,最终产生某种输出。因此,前馈神经网络在解决这些我们之前看到的分类问题时非常有帮助,我们有一整堆的案例。

我们想学习什么权重设置将有效地计算输出,但前馈神经网络有一些限制,我们稍后会看到,特别是输入需要像固定形状一样,比如输入层中的神经元数量是固定的。

输出有固定形状,比如输出层中的固定神经元数量,这也有其自身的限制,而一个可能的解决方案,我们稍后会看到可以解决的这类问题的示例,而不是仅仅是一个前馈神经网络。

在网络中,连接仅在一个方向上,从左到右有效。我们还可以想象一个递归神经网络,其中递归神经网络生成的输出会反馈到自身,作为未来运行该网络的输入,而在传统神经网络中则不是这样。

我们有输入传入网络,最终得出输出。决定输出的唯一因素是基于原始输入和我们在网络内部进行的计算。这与递归神经网络形成对比,在递归神经网络中。

你可以想象网络的输出会反馈到自身,再作为输入供下次计算使用。在网络内部,这使得网络能够维持某种状态,存储一些可以在未来使用的信息。

网络的运行以往只是找到一些权重,我们将输入传递给网络,生成输出,但网络并没有根据这些输入保存任何信息,以便在未来的迭代或运行中记住。递归神经网络让我们能够做到这一点。

它让网络存储信息,这些信息将在下次我们尝试执行某种操作时作为输入再次传入网络。这在处理数据序列时特别有用,所以我们实际上会看到,微软开发了一种被称为caption bot的AI。

caption bot的功能是我可以理解任何照片的内容。我会尽量描述得和任何人一样好,我会分析你的照片,但我不会存储或分享它。因此,微软的caption bot似乎声称它可以处理一张图片,并弄清楚图片中的内容。

只给我们一个描述的标题,所以我们来试试,比如这是哈佛广场的一张图片,前面有一些人在建筑前走。我会拿这个图像的URL,然后把它粘贴到caption bot中,按下GO,caption bot就是这样。

分析图像后,它表示我认为这是在建筑前走动的一群人,这似乎令人惊叹,AI能够查看这个图像并弄清楚图像中的内容,重要的是要认识到这不再只是一个分类任务。

使用卷积神经网络对图像进行分类,其工作是接收图像,然后判断它是0、1还是2,或者是这个人的脸还是那个人的脸。这里似乎发生的事情是,输入是一个图像,我们知道如何让网络接收图像输入,但。

输出是文本,就像是“在建筑物前走动的人群”的句子,这似乎对我们更传统的前馈神经网络构成挑战,因为在传统神经网络中,我们只有固定大小的输入和固定大小的。

输出中输入到神经网络的神经元数量是一定的,而输出的数量也是固定的,接下来在两者之间进行一些计算,但输入的大小和输入值的数量,以及输出值的数量始终是。

将会固定在神经网络的结构基础上,这让我们很难想象神经网络如何处理这样的图像,并说这是一个在建筑物前走动的人群,因为输出是文本,像是一系列单词,现在这可能对我们的。

神经网络的输出是一个单词,一个单词可以表示为一组值的向量,我们可以想象,下一次我们将更多地探讨与语言及语言处理相关的人工智能,但一系列单词要挑战得多,因为这取决于。

图像,你可以想象输出可能有不同数量的单词,我们可以有不同长度的序列,并且我们仍然希望能够生成适当的输出,因此这里的策略是使用递归神经网络,一种能够将自己的输出反馈回自己的神经网络。

下一次的输入,这使我们能够实现输入到输出的所谓一对多关系,而在传统的简单神经网络中,我们可能会认为这些是“一对一”的神经网络,你输入一组值,就得到一组值作为。

输出,但在这种情况下,我们希望将一个值作为输入(图像),并希望获得多个值的序列作为输出,每个值像是这个特定算法生成的一个单词,因此我们可能会想象。

从提供图像作为输入开始,神经网络将生成输出,但输出不会是整个单词序列,因为我们不能仅用固定数量的神经元来表示整个单词序列,而输出只会是。

我们将训练网络输出标题的第一个单词,你可以想象,微软通过运行大量训练样本来训练这一点,将大量图片与相应的标题进行匹配。

AI开始从中学习,但现在,由于网络生成的输出可以反馈回自己,你可以想象网络的输出被反馈回同一个网络,这里看起来像是一个独立的网络,但实际上是同一个网络,只是获取了不同的输入。

网络的输出会反馈回自己,但它会生成另一个输出,而那个输出就像是标题中的第二个单词,这个递归神经网络将会生成可以反馈回自己的其他输出,从而生成另一个输出。

单词被反馈回自己以生成另一个单词,因此递归神经网络允许我们表示这种一对多的结构,你提供一个图像作为输入,神经网络可以将数据传递到网络的下一次运行中,然后一次又一次地,这样你可以多次运行网络。

每次生成不同的输出,仍然基于原始输入,而这正是递归神经网络在处理输入或输出序列时特别有用的地方,我的输出是一个单词序列,由于我无法很容易地,表示整个序列的输出。

单词的输出将是逐个输出,而不是一次性输出,通过允许我的网络传递关于照片的,信息到下一阶段的运行,从而可以多次运行相同的网络。

这个输入每次首先从图像获取,然后作为关于特定标题需要额外提供的信息从网络本身获取,所以这是递归神经网络内部的一种一对多关系,但它转变。

还有其他模型我们可以使用,其他方式可以尝试使用递归神经网络来表示可能以其他形式存储的数据,我们看到我们如何使用神经网络分析图像,尤其是在卷积神经网络的背景下处理图像。

确定图像的各种不同属性,并能够基于此得出某种结论,但你可能想象像YouTube这样的东西,他们需要能够基于视频进行大量学习,他们需要查看视频,以检测是否存在版权侵犯或他们需要。

通过查看视频来识别视频中的特定项目,例如,视频你可能想象将其作为输入放入神经网络要困难得多,因为与图像相比,你可以将每个像素视为不同的值,而视频或序列则。

图像序列,每个序列可能长度不同,因此将整个视频表示为一个单一的值向量可能会很具挑战性,你可以传入神经网络,这里两个递归神经网络可能是解决这类问题的宝贵方案。

在这个问题中,我们不是仅仅将单一输入传入神经网络,而是可以一次传入一个帧的输入,想象一下,首先获取视频的第一帧,传入网络,然后可能不让网络输出任何结果,而是让它接收。

另一个输入,这次将其传入网络,但网络会获取我们上次提供输入的信息,然后我们传入第三个输入,再传入第四个输入,每次网络获得的是最近的输入,比如视频的每一帧,但它也获得信息。

网络处理来自所有先前迭代的信息,因此在第四帧时,你会获得第四帧的输入,加上网络从前三帧计算得到的信息,利用所有这些数据,结合递归神经网络可以开始学习如何提取。

从数据序列中提取模式,你可能会想象如果你想把视频分类为多个不同的类型,比如教育视频或音乐视频,或者其他类型的视频,这是一项分类任务,你希望将每一帧视频作为输入。

想要输出一些像它是什么,或者它属于哪个类别的东西,你可以想象这种多对一学习的事情,任何时候你的输入都是一个序列,在视频的上下文中也可能是这样的,如果有人输入了一条消息。

你希望能够对该消息进行分类,比如如果你想对电影评论进行分类,是正面评论还是负面评论,输入是一系列单词,输出是正面或负面的分类,对于递归神经网络可能是。

对于分析单词序列非常有帮助,而且在处理语言时它们相当受欢迎,甚至可以用于口语语言,口语语言是你知道的音频波形,可以分段成不同的块,而每一个块都可以作为输入传入。

递归神经网络能够对某个人的声音进行分类,例如,如果你想进行声音识别,判断这是一个人还是另一个人,这里还有许多情况下,你可能想要这种多对一的结构来进行递归神经网络的运用。

想象一下我们可以用这些类型的网络做些什么,类似于谷歌的那种!

Google Translate正在做的就是将某种语言写的文本转换成另一种语言的文本。例如,现在这个输入是一个数据序列,是一个单词序列,输出也是一个单词序列。

在序列中,这里我们实际上想要实现一种多对多的关系,我们的输入是一个序列,输出也是一个序列。仅仅将输入中的每个词翻译为输出中的一个词是不够的,因为不同的语言排列词语的顺序是不同的。

可能一种语言用两个词表示某个意思,而另一种语言只用一个词,因此我们确实需要某种方式来编码这个信息输入,并使用该编码生成最终的输出。这是自动化领域的一个重大进展。

翻译技术的关键在于使用神经网络,而不是旧的传统方法,这大大提高了准确性。你可以想象,使用一个具有多个输入和多个输出的循环神经网络来进行此操作,我们开始时。

所有输入都被传入网络,另一个输入(如另一个词)也进入网络,我们重复这个过程,比如对输入中的每个词进行一次翻译,只有在所有这些完成后,网络才开始生成输出,比如第一个词。

翻译后的句子和翻译句子的下一个词之间存在联系,每次网络通过允许某种状态在网络的不同运行之间传递信息,从而将信息汇总关于所有输入,然后传递一个。

通过对输出的不同部分的信息进行处理,以生成下一个输出。这类循环神经网络有多种不同类型,其中最受欢迎的一种被称为长短期记忆神经网络(LSTM),但一般来说,这些类型的网络可以非常有效。

当我们处理序列时,无论是图像序列还是特别是单词序列,这种能力都是强大的。

自然语言是我们可以用来进行各种不同计算的神经网络类型之一,这些都是极其多功能的工具,可以应用于多个不同领域,我们只看了一些最流行的。

神经网络的类型包括传统的前馈神经网络、卷积神经网络和循环神经网络,但还有其他类型,比如对抗网络,其中网络之间相互竞争,尝试生成新的数据类型以及其他网络。

可以根据它们的结构和适应性解决其他任务。这些是机器学习中非常强大的工具,能够基于一组输入数据非常轻松地学习,因此能够计算输入到输出的某些函数,无论是输入到。

一种分类方法,比如分析图像并得到一个数字,或者机器翻译,其中输入是某种语言,输出是另一种语言。这些工具在机器学习中有很多应用。下次我们将特别探讨机器学习和人工智能。

在自然语言的背景下,我们今天对此谈了一些,但看我们的人工智能如何开始理解自然语言,并能够分析和执行与人类语言相关的有用任务,这被证明是一个具有挑战性且有趣的任务。

哈佛CS50-AI | Python人工智能入门(2020·完整版) - P2:L0- 搜索算法 1 (搜索问题,深度优先搜索) - ShowMeAI - BV1AQ4y1y7wy

[音乐]。

好的,欢迎大家来到人工智能与Python的介绍课程,我的名字是布赖恩,在这节课中,我们将探索一些人工智能基础的思想、技术和算法。人工智能涵盖了多种类型。

每当你看到计算机做出某种看似智能或理性的事情,比如在照片中识别某人的脸,或能够比人类更好地玩游戏,或能够理解我们与手机对话时的语言,这些都是技术的表现。

回应我们,这些都是人工智能或人工智能的例子,在这节课中,我们将探讨使得这些人工智能成为可能的一些思想,因此我们将开始我们的讨论,搜索问题,即我们有一个人工智能,我们希望它能够搜索解决某种问题的方案,无论那是什么。

问题可能是无论它试图从A点到哪里获取行驶方向。

点B或尝试弄清楚如何在给定的井字游戏中进行游戏。

例如,弄清楚它应该做什么移动,然后我们将看一看。

知识理想情况下,我们希望我们的人工智能能够知道信息,能够表示该信息,更重要的是,能够从这些信息中得出推论,能够利用它所知道的信息并得出额外的结论,因此我们将讨论如何对人工智能进行编程。

为了做到这一点,我们将探讨不确定性的话题,讨论当计算机对某个事实不确定时会发生什么,也许它只对某个概率有把握,因此我们将讨论一些概率背后的思想,以及计算机如何开始处理不确定事件。

为了在这一意义上更加智能。之后我们将把注意力转向优化问题,当计算机试图优化某个目标时,尤其是在可能有多种方式解决问题的情况下。

我们在寻找一种更好的方法,或者说潜在的最佳方法。

如果一切都是可能的,那么我们将看看机器学习,或更一般的学习,以及当我们可以访问数据时,计算机如何能够通过从数据中学习和从经验中学习,被编程得非常智能,能够越来越好地执行任务。

基于更大的数据访问,因此,例如您的电子邮件,您的电子邮件收件箱以某种方式知道哪些电子邮件是好的,哪些电子邮件是垃圾邮件,这些都是计算机能够从过去的经验和数据中学习的示例,我们也将看看计算机如何能够。

从人类智能中汲取灵感,观察人脑的结构,以及神经网络如何成为计算机的类似物,如何利用某种类型的计算机程序结构,我们可以编写能够执行非常非常任务的神经网络。

有效地,最后我们将关注语言,不是编程语言,而是我们每天使用的人类语言,并观察计算机理解自然语言时所面临的挑战,以及自然语言的一些。

现代人工智能中发生的处理实际上可以。

但是今天我们将以搜索开始我们的对话,这个问题是试图弄清楚在某种环境中计算机处于什么情况,所谓的代理,希望该代理能够以某种方式寻找解决方案。

现在,这些问题可以有多种不同的格式。一个例子可能是经典的15拼图,您可能见过,它带有滑动的瓦片,您试图滑动。

瓦片的排列顺序,以确保所有数字都按顺序排列,这就是一个您可能称之为搜索问题的示例,15拼图从一个最初混乱的状态开始,我们需要某种方法找到移动的方式,以便将拼图恢复到已解决的状态,但还有类似的。

这些问题可以用其他方式表述,试图找到穿越迷宫的道路,例如,是搜索问题的另一个示例,您从一个地方开始,目标是您想要到达的地方,您需要找出正确的行动顺序,使您从初始状态到达。

目标,尽管这有点抽象,每当我们在这门课中讨论迷宫解决时,您可以将其转换为更现实的东西,比如驾驶方向,如果您曾想知道谷歌地图如何能够找出您从A点到B点的最佳路径。

取决于交通的时间,例如,它通常是某种搜索算法,您有一个人工智能,试图从初始位置到达某种目标,通过采取一系列动作,因此今天我们的对话将从思考这些类型的搜索问题开始,就像这样。

为了使AI能够找到好的解决方案,做到这一点。

我们需要引入一些术语,其中一些我已经使用过,但我们需要考虑的第一个术语是代理,代理只是一个感知其环境的实体,它能够以某种方式感知周围的事物并对环境采取行动。

在驾车导航的情况下,代理可能是汽车的一种表示,它试图弄清楚采取什么行动才能到达目的地;在15拼图中,移动瓷砖的代理可能是试图解决这个难题的AI或人。

找出要移动哪些瓷砖,以便达到解决方案,接下来我们引入状态的概念,状态只是代理在其环境中的某种配置。比如在15拼图中,任何状态可能是这三种之一,状态仅仅是瓷砖的某种配置。

这些状态各不相同,并且每个状态都需要稍微不同的解决方案,每个状态所需的动作序列也会不同,以便从初始状态到达目标。

代理开始的位置是其中一个状态,我们将从这里开始,这将是我们搜索算法的起点,可以这么说,我们将从此开始。

初始状态之后,我们开始对其进行推理,思考对初始状态可能应用哪些动作,以便弄清楚如何从起始位置到达我们的目标,并且我们如何从初始位置走向目标。

最终,通过采取动作,我们可以做出在任何给定状态下的选择,在AI中,我们总是会尝试更精确地形式化这些思想,以便能够更数学化地编程。因此,这将是一个反复出现的主题。

更精确地定义动作作为一个函数,我们将有效地定义一个称为动作的函数,它接受一个输入s,其中s将在我们的环境中存在某种状态,actions of s将接受状态输入并返回所有可以执行的动作集合作为输出。

在某些状态下,某些动作是有效的,而在其他状态下则不是,我们很快会看到这方面的例子。在这种情况下,

以15拼图为例,通常会有四种可能的动作可以执行。大多数情况下,我们可以将一个方块滑到右边、滑到左边、向上滑动或向下滑动。例如,这些将是可用的动作,因此我们的AI或程序需要某种。

状态的编码通常是这样的。

将以某种数值格式呈现,并且对这些动作进行某种编码,但它也需要对这些事物之间的关系进行编码。状态与动作之间是如何相互关联的,为此我们将向我们的AI引入一个转换模型,这将描述什么。

我们在执行某个可用动作后的状态,以及在其他状态中。我们可以更准确地定义这个转换模型,再稍微正式一些,再次定义为一个函数。这个函数将是一个名为result的函数,这次接受两个输入,输入数字一是某个状态s。

输入数字二是某个动作,结果函数的输出将给我们在状态s中执行动作a后得到的状态。那么让我们看看一个例子,更精确地了解这实际上意味着什么。这是一个15拼图的状态示例,以下是一个例子。

当一个动作将一个方块滑到右边时,如果我们将这些作为输入传递给结果函数,结果函数将这个棋盘状态作为第一个输入,并将一个动作作为第二个输入,当然在这里我以视觉方式描述事物,以便你可以清楚地看到状态是什么。

在计算机中,动作ISM可能代表这些动作之一。只是一些表示动作的数字,或者如果你熟悉枚举(enums),它可以让你枚举多个可能性,可能会是像这样的状态,这个状态可能只会被表示为一个数组或二维数组。

存在的数字,但在这里我们要以视觉方式展示它,这样你就能看到。

但是当我们将这个状态和这个动作传递给结果函数时,输出是一个新的状态,我们在将一个方块滑到右边后得到的状态。如果我们有一个不同的动作和不同的状态,并将其传递给结果函数,我们将。

得到一个完全不同的答案,所以结果函数需要处理如何获取一个状态并采取一个动作来得到结果。这将是我们的转换模型,描述状态与动作之间是如何相互关联的。如果我们考虑这个转换。

模型,想得更一般一些,跨越整个问题,我们可以形成一个我们称之为状态空间的集合。

我们可以从初始状态通过任何序列获得的所有状态。

通过采取零个、一个、两个或更多的动作来实现的动作。因此,我们可以绘制一个类似这样的图表,其中每个状态通过一个游戏板表示,并且有箭头连接每个状态到所有其他状态。我们可以从那个状态到达的状态空间远比你在这里看到的要大得多。

这只是状态空间可能实际样子的一个示例,通常在许多搜索问题中,无论是这个特定的15拼图、驾驶方向还是其他东西,状态空间大致上都会像这样。我们有单独的状态和从一个状态到另一个状态的箭头,以及一个转移模型,定义了在我们采取特定动作后会发生什么。

将它们连接起来,通常为了简化,我们会将整个表示简化为图形,一系列连接节点的节点和边。但你可以将这种更抽象的表示视为完全相同的概念,每一个小圆圈或节点将代表。

这是我们问题中的一个状态,这里的箭头表示我们在任何特定状态下可以采取的动作,将我们从一个特定状态转移到另一个状态。例如,现在我们有了表示这些状态的节点的概念,以及可以使我们达到特定目标的动作。

所以,我们需要弄清楚的下一步是,如何知道人工智能何时完成解决问题。人工智能需要某种方式来知道它到达了目标,找到了目标。

接下来我们需要在人工智能中编码的是一个目标测试。某种方式来确定给定状态是否为目标状态。以驾驶方向为例,如果你处于与用户输入的预期目标状态相对应的状态,可能就相当简单。

在15拼图中,可能需要检查数字,以确保它们都是按升序排列的。但AG是某种方式来编码是否处于任何状态的目标,某些问题可能只有一个目标,比如迷宫,其中有一个初始位置和一个结束位置,那就是目标。

在复杂的问题中,你可能会想象有多个可能的目标,并且有多种方法来解决一个问题。我们可能不在乎计算机找到哪个目标,只要它能找到即可。

然而,有时计算机并不仅仅关心找到一个目标,而是要找到一个好的目标,或者说是一个成本较低的目标。因此,我们将用来定义这些搜索问题的最后一个术语是“路径成本”,你可以想象。

在驾驶方向的情况下,如果我说我想要从A点到B点的路线,而谷歌地图给我的路线是一个冗长的、有很多不必要绕路的路线,这会非常烦人,这样花费的时间比我到达目的地所需的时间要长。

因为在制定搜索问题时,我们通常会给每一个。

路径有某种数值成本,告诉我们采取这个特定选项的代价,然后告诉我们的人工智能,我们不仅要找到从初始状态到目标的解决方案,我们确实希望找到一个能最小化路径成本的解决方案。

如果我们想要的结果是用更少的时间或最小化某些其他数值,我们可以通过图形表示这一点,如果我们再次查看这个图,想象这些箭头,每个我们可以从一个状态到另一个状态的动作都有一个与之相关的数字,这个数字是路径成本。

这个特定动作的情况是,任何特定动作的成本可能比其他某些动作的成本更高,例如。尽管这只会在某些问题中发生,在其他问题中,我们可以简化图示,假设任何特定动作的成本。

这在15拼图之类的情况下可能是相同的,例如,移动向右或移动向左并没有太大区别,唯一重要的是从A点到B点所需的总步数,每一步的成本是相等的。

我们可以假设它的成本是某种常量,比如1,这就形成了我们可能考虑的搜索问题的基础,搜索问题有某种初始状态,我们开始的地方,有一些我们可以采取的动作或多种动作。

过渡模型是定义从一个状态到另一个状态时采取某一动作后会发生什么,我们最终会处于什么状态。此外,我们需要一个目标测试,以了解我们是否已达到目标,然后我们需要一个路径成本函数,告诉我们通过任何特定路径的成本。

一些动作序列的路径有多昂贵,这条路径的成本在金钱、时间或其他资源方面是多少。

我们试图最小化用户的工作,而最终的目标是找到一个解决方案,这里解决方案只是一些动作序列,将我们从初始状态带到目标状态,理想情况下,我们希望找到的不仅仅是任何解决方案,而是最优解决方案,即成本最低的解决方案。

在所有可能的解决方案中,路径成本有时可能会存在多个最佳解决方案,但最佳解决方案仅意味着没有更好的方法来找到该解决方案。

现在我们已经定义了问题,现在需要开始弄清楚我们将如何解决这种搜索问题。为此,你可能会想象我们的计算机需要表示与此相关的一整堆数据。

对于特定问题,我们需要表示关于我们在问题中位置的数据,我们可能需要同时考虑多种不同的选项。通常,当我们试图将与某个状态相关的大量数据打包在一起时,我们将使用我们将称之为的数据结构。

节点是一个数据结构,它将跟踪各种不同的值,特别是在这个情况下。

在搜索问题的情况下,它将特别跟踪这四个值,每个节点将跟踪一个状态,即我们当前所在的状态,每个节点还将跟踪一个父节点,父节点是我们到达当前状态之前的状态,或者是我们用来到达这个状态的节点。

当前状态,这一点很重要,因为最终一旦我们到达目标节点,一旦我们到达终点,我们想知道我们为了到达该目标所采用的动作序列,而我们知道这一点的方法是查看这些父节点,以跟踪是什么引导我们到达目标,以及是什么引导。

引导我们到该状态,以及让我们到达之前状态的路径,以此类推,回溯到开始,这样我们就知道从开始到结束所需的整个动作序列。节点还将跟踪我们采取了什么动作,以便从。

当前状态的父节点,同时节点还将跟踪路径成本,换句话说,它将跟踪一个数字,该数字表示从初始状态到我们当前所在状态所花费的时间,随着我们开始讨论这个问题的相关性,我们将看到这一点。

我们可以在这些搜索问题上进行的一些优化。更一般地说,这就是我们将要使用的数据结构,以解决问题。现在让我们谈谈方法,我们可能如何开始解决这个问题,正如你所想象的那样。

我们将从一个特定状态开始,只是从那里进行探索,直觉上,从给定的状态出发,我们有多个选择可供我们采取,我们将探索这些选项,一旦我们探索了这些选项,就会发现会有更多的选项。

可用的节点,我们将考虑所有可用选项,将其存储在一个名为前沿的单一数据结构中。前沿将代表我们可以探索的所有事情,这些事情我们尚未探索或访问。

在我们的方法中,我们将通过一个仅包含一个状态的前沿开始搜索算法,前沿将包含初始状态,因为在开始时,这就是我们知道的唯一状态,也是唯一存在的状态,然后我们的搜索算法实际上是。

我们将遵循一个循环,不断重复某个过程。首先,如果前沿是空的,那么就没有解决方案,我们可以报告没有办法到达目标,这当然是可能的,某些类型的问题可能是AI尝试解决的。

需要探索并意识到没有办法解决该问题,这对人类了解也是有用的信息,因此如果前沿为空,这意味着没有剩下的探索,我们尚未找到解决方案,因此没有解决方案,没有剩下的可探索内容,否则我们。

我们将从前沿中移除一个节点,现在在开始时,前沿仅包含一个代表初始状态的节点,但随着时间推移,前沿可能会增长,可能包含多个状态,因此在这里我们只会从该前沿中移除一个节点。

如果该节点恰好是目标,那么我们找到了一个解决方案,因此我们从前沿中移除一个节点,并问自己这是目标吗,我们通过应用之前谈到的目标测试来实现,问我们是否到达了目的地,或者问15拼图的所有数字是否按顺序排列。

目标是找到解决方案,太好了,我们完成了。否则,我们需要做的是扩展节点,这在人工智能中是一个专业术语,扩展节点意味着查看该节点的所有邻居,换句话说,考虑所有可能的行动。

我可以从这个节点所代表的状态采取的所有行动,以及我可以从那里到达哪些节点。我们将获取所有这些节点,即从当前节点可以到达的下一个节点,并将其添加到前沿,然后重复这一过程。总体来说,这个想法是。

从一个包含初始状态的前沿开始,不断从前沿中移除一个节点,查看我们可以到达的下一个节点,并将这些节点添加到前沿,重复这个过程,直到我们从前沿中移除一个节点并且它包含目标。

意味着我们已经解决了问题,或者我们遇到了一种情况,边界为空,此时我们就没有解决方案,所以让我们实际上尝试将伪代码付诸实践,看看一个示例搜索问题。因此,在这里我有一个示例图,a 通过。

这个动作 B 连接到节点 C,D 连接到 E,而 E 连接到 F,我希望我的 AI 找到从 A 到 E 的路径,我们想要从这个初始状态到达这个目标状态,那么我们将如何做到这一点呢?我们将从包含初始状态的边界开始。

代表我们的边界,所以我们的边界最初只包含 a 这个初始状态,我们将开始,现在我们将重复这个过程,如果边界为空,没有解决方案,那不是问题,因为边界不为空,所以我们将从边界中移除一个节点,作为下一个考虑的节点。

边界中只有一个节点,所以我们将其从边界中移除,但现在 a 是初始节点,这就是我们当前考虑的节点。我们按照下一步进行,问自己这个节点是否是目标,不,它不是,a 不是目标,而 e 是目标,所以我们不返回解决方案,因此我们转到最后一步。

展开节点并将结果节点添加到边界,这意味着什么呢?好吧,这意味着取这个状态 a 并考虑我们下一个可以到达的地方,a 后我们能到达的地方只有 B,因此这就是我们展开 a 时得到的结果,我们找到 B,并将 B 添加到边界,现在 B 在边界中。

我们再次重复这个过程,我们说,好吧,边界不为空,所以让我们从边界中移除 B,B 现在是我们正在考虑的节点。我们问自己,B 是目标吗?不,不是,所以我们继续展开 B 并将其结果节点添加到边界。展开 B 会发生什么,换句话说。

我们可以从 B 到达哪些节点呢?我们可以到达 C 和 D,因此我们将继续从边界添加 C 和 D,现在边界中有两个节点 C 和 D。我们再次重复这个过程,从边界中移除一个节点,暂时我会任意选择 C,稍后我们会看到选择哪个节点。

你从边界移除的节点实际上是算法中一个相当重要的部分,但现在我会任意移除它,因为说它不是目标,因此我们将下一个节点添加到边界,然后假设我从边界移除你,现在我检查一下,当前我正在查看的状态 e 是否是目标状态。

这是因为我正在尝试找到从 A 到 E 的路径,因此我将返回目标,现在这将是我能够返回的解决方案,我找到了从 A 到 E 的路径。因此,这是这个搜索算法的总体思路,遵循这些步骤,不断从边界中移除节点。

前沿,直到我们能够找到一个解决方案,所以下一个你可能合理问的问题是,这里可能出什么问题,采用这种方法的潜在问题是什么。

一个可能出现的问题的例子是,想象一下这个与之前相同的图表,唯一的变化是现在而不是。

从A到B有一条箭头,我们也有从B到A的箭头,意味着我们可以双向移动,这在类似于15个可能的情况下是正确的,当我将一个拼图块向右滑动时,我可以然后向左滑动一个拼图块回到原来的位置,我可以在A和B之间来回移动。

这就是这些双箭头所象征的,从一个状态我可以到达另一个状态,然后我可以再回去,这在许多搜索问题中都是正确的,如果我尝试。

现在我们将应用相同的方法,我们都将以之前的方式开始,我会。

从前沿中移除A,然后我会考虑从A可以到达哪里,A之后我唯一可以到达的地方是B,因此B进入前沿,然后我会说,好吧,让我们看看B,这是前沿中剩下的唯一一项,我可以从B到达哪里,之前只是C和D,但现在。

由于那个反向箭头,我可以到达A、C或D,因此A、C和D这三者都进入前沿,我可以从B到达的地方,现在我从前沿移除一个,可能我运气不好,选择了A,现在我再次看着A,考虑我可以从A到哪里。

从A到B我可以到达,现在我们开始看到问题,但如果我不小心,我从A到B然后。

回到A,然后再次到B,我可能会陷入这个无限循环中,永远无法取得进展,因为我一直在两个我已经见过的状态之间来回移动。那么这个问题的解决方案是什么?我们需要某种方法来处理这个问题,我们可以处理这个问题的方式是。

通过某种方式跟踪我们已经探索过的内容,逻辑是,如果我们已经探索过该状态,就没有理由再回去,一旦我们探索了一个状态,就不要再回去,不要再将其添加到前沿。

不需要这样,所以这将是我们修订的方法,一个更好的解决此类搜索问题的方法,虽然看起来非常相似,只是进行了几处修改,我们将从一个包含初始状态的前沿开始,与之前相同,但现在我们将使用另一种数据结构。

这将只是我们已经探索过的一组节点,那么我们最初探索过的状态是什么呢?它是空的,我们有一个空的已探索集合。现在我们重复,如果边界为空,则没有解决方案,和之前一样,我们从边界中移除一个节点,检查它是否是目标状态,返回。

解决方案到目前为止没有任何不同,但现在我们要做的是将节点添加到已探索状态中,因此如果它恰好在边界中并且不是目标,我们将其添加到已探索集合中,这样我们就知道我们已经探索过它,不需要再返回。

然后最后一步是扩展节点,并将结果节点添加到边界,但在我们之前总是将结果节点添加到边界时,这次我们会聪明一点,仅当节点不在边界中时才添加它们。

它们还不在已探索集合中,所以我们会检查边界和已探索集合,确保节点不在这两者中,只要不在,我们就可以将其添加到边界,否则就不添加。因此,这种修订后的方法是最终能帮助我们。

确保我们不在两个节点之间来回移动,现在我这里有一点我到目前为止略过了,那就是在移除节点之前的这一步。我之前随意选择了一个节点进行移除,但事实证明,我们如何决定构建我们的结构实际上是相当重要的。

边界是一个数据结构,我们需要选择我们将以什么顺序移除元素,而添加和移除元素的最简单数据结构之一是栈,栈是一种数据结构。

这是一种后进先出的数据类型,这意味着我最后添加到边界的东西将是我从边界中移除的第一个东西。因此,在这种情况下,最后进入栈或边界的东西是!

这将是我探索的节点,所以让我们看看如果我将这种基于栈的方法应用到这样的一个问题上,即从A到E寻找路径,会发生什么。我们将从A开始,并说好,让我们先看A,然后注意到这次我们添加了A。

已探索集合A是我们现在已经探索过的东西,我们有这个数据结构在跟踪。然后我们说从A可以到达B,好的,从B我们可以做什么呢?从B我们可以探索B,并到达C和D,因此我们添加了C和D。所以现在当我们探索一个节点时,我们将边界视为一个。

栈是后进先出,D是最后被探索的节点,接下来我们说,好吧,我们能从D到达哪里?我们可以到达F,没问题,我们会探索它,把F放入前沿,现在因为前沿是一个栈,F是最近进入栈的元素,所以F是我们接下来要探索的节点。

现在我们说,好吧,我们能从F到达哪里?我们什么地方也去不了,所以前沿没有新元素被添加。那么现在最近添加到前沿的元素是什么?现在是C,前沿中唯一剩下的元素,我们将从C进行探索,从中可以看到,从C我们可以到达E,所以E被放入。

在前沿中,我们说,好吧,E看起来是个选项,E现在是解决方案,我们已经解决了问题。因此,当我们把前沿视为一个栈,一个后进先出的数据结构时,得到的结果是从A到B再到D再到F,然后我们稍微退回,去探索C。

E,重要的是要对这个算法的工作方式有一个直观的理解。我们在这个搜索树中走得非常深,直到底部,遇到了死胡同,然后我们有效地退回,探索另一条之前未尝试的路径,这种方式在搜索中深入很重要。

搜索树的理念是这样的,算法在我们使用栈时能够工作。我们称这种算法的版本为深度优先搜索。深度优先搜索是一种搜索算法,我们始终探索前沿中最深的节点。

我们在搜索树中不断深入,如果遇到一个...

哈佛CS50-AI | Python人工智能入门(2020·完整版) - P20:L6- 自然语言处理 1 (语言,语法与语义,nltk,n-grams) - ShowMeAI - BV1AQ4y1y7wy

[音乐]。

好的,欢迎大家回来,进入我们关于人工智能与Python的最终主题,今天的主题是语言。在课程中,我们已经看到与AI交互的多种方式,但大部分是我们构建的方式。

以AI能够理解的方式解决问题,学习用AI的语言来表达,尝试将一个问题转化为搜索问题,或将其转化为约束满足问题,这是我们今天的目标。

想出算法和理念,允许我们的AI与我们达成某种共识,能够理解、解释并获取人类语言中的某种含义。

口语中的语言类型,如英语或其他我们自然使用的语言,这对AI来说是一个非常具有挑战性的任务,确实涵盖了多种类型。

所有任务都在自然语言处理的广泛范畴下,提出算法使我们的AI能够处理和理解自然语言。这些任务在我们希望AI执行的任务类型和我们可能使用的算法类型上各不相同。

一些常见任务包括自动摘要,你给AI一个长文档,希望AI能够总结出来,形成同一思想的简短表达,但仍然使用某种自然语言,如英语。

在给定大量信息的文档或互联网内容时,我们希望我们的AI能够提取一些有意义的语义信息,能够阅读并进行语言识别,任务是识别某一页面所用的语言。

确定文档所写的语言类型,这种情况在你使用网页浏览器时可能会出现,比如当你打开一个其他语言的页面时,浏览器可能会询问你,哦,我认为它是这种语言,你要我帮你翻译成英语吗。

识别过程是RAI需要能够完成的任务,这与机器翻译相关,即将一种语言的文本翻译成另一种语言,这方面在过去几年里有很多研究和发展,依然在持续进行。

在人工智能领域,改善如何将一种语言的文本转换为另一种语言是一个重要话题。此外,我们还有命名实体识别的主题,给定一段文本,你能识别出命名实体吗?这些实体通常是公司名称或。

人名或地点名,例如,它们常常是特定文档中的相关或重要部分。语音识别作为一个相关任务,不是处理书面文本,而是处理口语文本,能够处理音频并确定所说的实际单词。

如果你想想像Siri或Alexa这样的智能家居设备,这些设备现在能够在我们说话时倾听,弄清楚我们说了什么,并从中提取某种意义。我们讨论过如何将一些东西构想成。

隐马尔可夫模型能够得出这些结论和文本。

分类通常是一个广泛的类别,每当我们想将某种文本放入某种类别时,我们就会看到这些分类问题,以及如何利用统计机器学习方法来解决它们。

在自然语言中,我们可能需要做一些调整,我们将很快看到,像词义消歧这样的概念,与数字语言不同,AI在所有事物的表示上是非常精确的,而单词在意义上则有些模糊。

意义和单词可以有多重不同的含义,自然语言本质上是模糊的,今天我们将探讨一些这些模糊之处,但如果你希望AI理解自然语言,一个具有挑战性的任务是能够消歧或区分。

如果我说“我去银行”,你需要弄清楚我指的是存取款的银行,还是河岸。不同的词可以有不同的含义,我们可能想要基于上下文来弄清楚这些。

一个词出现的范围,包括句子、段落或论文,可能有助于我们了解如何在不同的含义之间进行消歧。

为了解决这些问题而设计的算法,今天我们将仅仅触及表面,看看一些基本概念,这些概念在自然语言处理和试图提出AI算法时会发现许多。

我们能够用我们每天说的语言做一些有意义的事情。因此,当我们考虑语言时,通常可以从几个不同的部分进行思考。第一部分涉及语言的句法,这更多的是与语言的结构有关。

这个结构是如何工作的。

如果你考虑自然语言,句法就是这样一种东西。如果你是某种语言的母语者,它会很自然地浮现出来,你不需要过多思考。如果我给你一个来自阿瑟·柯南·道尔的福尔摩斯的句子,比如在这之前的句子。

九点钟,福尔摩斯快步走进房间。我想我们都可以同意这是一个结构良好的语法句子。从句法上讲,它在这个特定句子的结构方面是有意义的,句法不仅适用于自然语言,也适用于编程语言。

如果你见过自己编写程序中的语法错误,那很可能是因为你写了一种不符合句法规则的程序。它的结构并不是一个有效的程序。以同样的方式,我们也可以看待英语。

在任何自然语言中句子或句子可以进行相同类型的判断。我可以说这个句子在句法上是结构良好的,当所有组成这些词的部分按照这个顺序组合时,它构造了一个语法正确的句子,或者说大多数人会同意这是一个语法正确的句子。

但也有语法上不良构造的句子,比如“九点钟福尔摩斯”。

快步走进房间。我想我们都会同意这不是一个结构良好的句子,从句法上讲它没有意义。这正是如果我们希望我们的 AI 生成自然语言,例如像聊天机器人那样与我们交流时,所需要解决的问题。

例如,我们的 AI 将需要能够识别这种区别。它需要能够知道哪些句子是语法正确的,哪些句子不是,我们可能会提出规则或方法来统计学习这些概念,我们将讨论一些这些方法。

句法也可能是模棱两可的,有些句子是这样的。

结构良好与结构不良之间存在某种方式,你可以对一个句子进行不同结构的多种构造。

比如,我在山上用望远镜看到了那个人。这是一个语法结构良好的句子,从句法上讲是有意义的。

但是这个句子的结构是什么?是“在山上的男人有望远镜”,还是“我看到山上的男人,我正在使用望远镜来观察山上的男人”?这里有一些有趣的模棱两可的地方,可能有两种不同的理解。

结构,这也是我们将在处理自然语言时,思考如何与AI打交道时会回到的一个概念,因为自然语言本质上是模棱两可的。因此,语法是语言的结构,理解单词的顺序和位置如何影响我们的理解。

提出了不同的语言结构,但除了语言有结构之外,语言还有意义,现在我们进入了。

语义是指一个单词、一组单词、一个句子或整篇文章实际上意味着什么,所以像“在九点钟前,福尔摩斯精神抖擞地走进了房间”这样的句子,与“福尔摩斯精神抖擞地走进了房间”是不同的句子。

在九点钟前的房间,然而它们实际上有相同的意义。它们是不同的句子,因此当AI读取它们时会将其识别为不同,但我们人类可以看这两个句子并说,是的,它们基本上是相同的意思,也许在这个情况下谁穿着。

因为我改变了单词的顺序,原本“九点钟”在句子的开头,现在“九点钟”在句子的末尾。你可能会想,我可以想出一个完全不同的句子,比如“在九点钟前几分钟,福尔摩斯快速走进了房间”。

房间,这也有一个非常相似的意思,但我使用不同的词来表达这个想法,理想情况下,AI应该能够识别这两个句子,这些不同的词组合相似的意思,并能够理解这个想法。

语法上正确的句子也可能根本没有任何意义,一个著名的例子来自于。

语言学家诺姆·乔姆斯基的这句话是“无色的绿色思想疯狂地睡觉”,从语法上看,这个句子完全没问题,“无色”和“绿色”是修饰名词“思想”的形容词,“睡觉”是一个动词,某种程度上作为副词。

旧词的句子,但事实证明这个句子在某种程度上是没有意义的,如果你试图给这个句子赋予意义,那它意味着什么并不容易确定。语义本身也可能是模棱两可的,因为不同的结构可以有不同类型的。

不同单词可以具有不同类型的含义,所以相同结构的句子可能最终意味着不同类型的东西。我最喜欢的例子来自洛杉矶时报,标题曾经出现在《洛杉矶时报》上。

标题说“大卡车运送水果,在210号高速公路上发生碰撞,造成堵塞”,所以根据你如何看待这个句子,以及如何解释它,它可能有多种不同的含义,因此在自然语言处理领域,有两个挑战:能够理解句法。

语言和语言的语义,今天我们将一起探讨这两个概念,我们将首先谈论句法,了解语言是如何构造的,我们可以通过制定一些规则来告诉我们的计算机,告诉我们的人工智能什么类型的。

有效句子是什么,哪些类型的东西不是有效句子,最终我们希望利用这些信息,让我们的人工智能得出有意义的结论,能够对语言进行操作。因此,我们将通过引入形式语法的概念来开始。

形式语法的全部内容是,形式语法是一种生成语言中句子的规则系统,我想知道有效的英语句子是什么,不是从它们的含义上,而是从它们的结构上来看。英语的句法结构中,哪些结构是有效且正确的。

英语的句子结构是什么,并不有效,它将以非常类似的方式应用于其他自然语言,因为语言遵循某些类型的结构,我们直观地知道这些结构的含义,但尝试正式定义这些结构的含义将是有帮助的。

结构的定义有许多不同类型的形式语法,这些语法被称为乔姆斯基语法层次结构,如果你曾经使用过正则表达式,可能会见过其中一些,它们属于正则语言的类别。

正则语言对应于一种特定类型的语言,但在这个层次上还有一种被称为上下文无关语法的语法,今天我们将主要关注它,上下文无关语法是通过所谓的重写规则生成语言中的句子的一种方法。

替换一个符号与其他符号的规则,我们稍后将看看这是什么意思,假设一个简单的英语句子,比如“她看到了城市”。

这是一个有效的语法上良好的英语句子,但我们希望AI能够以某种方式查看这个句子,并弄清楚句子的结构,因为为了回答一个问题,如果想象AI处于问答模式,想问AI一个。

问题是她看到了什么,那么AI希望能够查看这个句子并识别她所看到的是城市,能够弄清楚这一点,这需要一些理解,即这个句子的结构实际上是什么样子的。

我们将要称之为终结符的城市,语言中有这些单词,每个单词都是一个符号,这最终是我们关心生成的内容。

关于生成这些单词,但每个单词我们也会关联一个我们称之为的。

非终结符号最初看起来像词类,如果你回忆一下英语语法,“she”是一个名词,“saw”是V动词,“the”是D,D代表限定词,这些词如“the”、“a”和“an”。

例子是city,city也是一个名词,所以n在这里,所以每个。

这些NV和D是我们可能称之为非终结符号,它们实际上不是语言中的单词,“she saw the city”才是语言中的单词,但我们使用这些非终结符号来生成终结符号,终结符号如“she saw the city”这些实际的单词。

在像英语这样的语言中,为了将这些非终结符号翻译成终结符号,我们有称为重写规则的东西,这些规则看起来像这样,左边有一个n的箭头,箭头表示如果我有一个N的非终结符号,我就可以将其转换。

进入这些不同的可能性中。

这些是用垂直线分隔开的,因此一个名词可以翻译成单词she,名词也可以翻译成单词city、car或Harry等许多其他东西,这些都是名词的例子,另一方面,限定词D可以翻译成the、a或an,动词v4可以翻译成任何的。

这些动词P作为介词可以翻译成任何这些介词,比如to、on、over等,而形容词DJ则无法翻译成任何可能的形容词,因此这些在我们的上下文无关文法中就是规则。

英语语言或任何其他语言的结构是什么,我们给它这些类型的规则,表明一个名词可以是这些。可能性中的任何一个,一个动词可以是那些可能性中的任何一个,但事实证明,我们可以开始构建其他规则,那里不仅仅是一个非终结符。

转换为一个终结符号,我们总是会在箭头的左侧有一个非终结符,在箭头的右侧我们可以有其他东西,我们甚至可以有其他非终结符号。那么我想说的是什么呢?我们有名词的概念,比如“她”“城市”。

例如“车哈利”,但还有名词短语,像可以作为名词的短语,不只是单个,词,而是多个词对吧。“城市”是两个词,结合在一起,作为我们可能称之为名词短语,它是多个词,但它们,结合在一起作为名词,或者如果你。

想想更复杂的表达,像“大城市”三个词作为一个单一的名词运作,或“街上的车”多个词,现在,但那整个词组作为,像一个名词,替代名词短语。所以为此我们将引入,一个新的非终结符号的概念。

称为NP,代表名词短语,这个重写规则表明,名词短语可以是名词,因此,像“她”这样的东西是名词,因此它也可以是名词短语,但名词短语也可以是一个。

限定词D后面跟着一个名词,因此在这个非常简单的语法中,我们有两种方式可以形成名词短语。当然英语。

语言比这更复杂,但名词短语是我,著名的,或它是一个限定词,后面跟着一个名词。所以对于第一个,例子,一个名词短语仅仅是一个。

名词使我们能够生成,像“她”这样的名词短语,因为名词短语仅仅是一个名词,而一个名词,可以是“她”这个词。例如。与此同时,如果我们想查看其中一个,蜜蜂的例子,其中一个名词短语。

变成一个限定词和名词,那么我们就得到这样的结构,现在我们开始看到,语言的结构从这些规则中出现,形成一个语法树,我们称这种树状,结构为我们的自然语言的语法。在这里,我们有一个名词短语,而这个名词短语由。

一个限定词和一个名词组成,其中,限定词是“the”这个词,根据。那个规则,名词是“城市”这个词。那么,这里就是一个名词短语,由多个词组成,位于结构内部,并利用这种用一个符号,重写它的方法,使用其他,可能是终结符号的符号。

类似于“和”城市,但也可能是,像D这样的非终结符号代表限定词,或n代表名词,那么我们可以。

开始构建越来越复杂的结构,除了名词短语外。我们也可以考虑动词短语。

动词短语可能是什么样子呢,动词短语可能只是一个句子中的单个动词,比如我走了,走是动词,在这个句子中充当动词短语,但也有更复杂的动词短语,不仅仅是一个单词,而是多个单词。

句子像她看到了城市,例如看到了城市实际上是这样的。整个动词短语占据了类似于她在做什么的内容,例如。我们的动词短语可能有一个规则。

像这样的动词短语要么只是一个简单的动词,要么是一个动词后面跟着一个名词短语,我们之前看到过。

名词短语可以是一个名词,或者是一个限定词后跟一个名词,因此动词短语可能是简单的,比如动词短语只是一个动词,那个动词可能是“走”这个词,但它也可以是更复杂的东西,例如,现在我们开始看到更大的。

语法树,阅读这个语法树的方法是,动词短语是一个动词和一个短语,其中那个动词可以是像“诗篇”这样的东西,而这是我们之前见过的名词短语,“城市”是一个名词短语。

由限定词“the”和名词“city”组成,所有这些结合在一起构成这个更大的动词短语。然后再给一个规则的示例,我们可以。

也有这样的规则,句子s由名词短语和动词短语组成。句子的基本结构是。

这是一个名词短语后面跟着一个动词短语,这是一个形式语法。

表达你可能在学习英语语法时学到的概念的方式,当你阅读到一个子句时,句子就像一个主语和动词。主语在行动,某件事发生在特定的名词短语上。因此,利用这个结构,我们可以构造一个看起来像这样的句子。

这是一个句子由名词短语和动词短语组成,名词短语可以只是一个名词,比如单词“她”,动词短语可以是一个动词和一个名词短语,这是我们之前见过的,动词是“看”,名词短语是“城市”。现在看看我们在这里做了什么。

完成的方法是定义一组规则,有一些算法可以运行,处理这些单词。因此,Eyk算法是一个示例,如果你想了解它,你可以从一组终端符号开始,比如她看到了城市,然后使用这些规则,你能够弄清楚如何。

你可以从一个句子“她看到了城市”开始,然后通过这些重写规则,句子由名词短语和动词短语构成,动词短语可以是一个动词和一个名词短语,依此类推,你可以想象取这个结构,并找出如何。

生成一个解析树,一个语法树,为那组终结符和那组单词。如果你试图为一个不合语法的句子这样做,比如“看到了城市她好”,那就行不通,因为没有办法使用这些规则来生成那个句子。

这不在那个语言中,因此这种模型在规则足够表达所有自然语言中你想表达的想法时,可以非常有帮助。当然,使用我们这里的简单规则,有许多句子是我们无法生成的。

有些句子我们可能认为是语法和句法上良好的,但我们无法用这些规则构造。在这种情况下,我们可能需要更复杂的规则来处理这些情况,因此这种方法在你需要时是强大的。

处理一个有限的规则和单词集,这些是你真正关心的。我们可以通过使用一个名为NLTK的Python库来与之交互,今天我们会看到几次。

它有多种不同的功能和类,我们可以利用它,都是为了处理自然语言。其中一个算法是解析上下文无关文法,能够取一些单词并根据某个上下文无关文法来分析。

那么你如何构建这个语法树呢?让我们来看看NLTK。现在通过研究如何构建一些上下文无关文法,来实现这一点。在CFG零CFG中,我有一个示例上下文无关文法,包含我们之前见过的规则。

它会转向名词短语后跟动词短语,名词短语可以是一个限定词和一个名词,或名词动词短语,动词短语可以是一个动词或动词和名词短语,这些的顺序并不重要,限定词可以是“那个”或“一个”,名词可以是“她”、“城市”或“车”,动词可以是某个词。

“看”或者“走”这个词,现在使用我在顶部导入的NLTK,我将解析这个语法并将其保存在一个名为parser的变量中。接下来,我的程序将要求用户输入,像是输入一个句子,然后用split将其按空格分开。

所以我最终获得了每个单独的词,我们将把它们保存在一个叫做句子ISM的列表中,然后我们将尝试解析这个句子,对于我们解析的每个句子,我们将以漂亮的格式输出到屏幕上,以便在我的终端中显示,同时我们还会绘制它。

结果显示NLTK有一些图形能力,因此我们可以真正可视化这个树的样子,并且句子可能被解析的方式有多种,这就是为什么我们将其放入这个。

循环,我们稍后也会看到这有多么有用。所以好吧,现在我会进入CFG目录,我们将运行CFG 0,然后它会提示我输入一个句子,让我输入一个非常简单的句子,比如“她走了”,按回车,我得到的是在左侧你可以。

看一下基于文本的语法树表示,右侧这里让我放大一些,我们看到同一语法树的视觉表示,这就是我的计算机如何解析句子“她走了”的,句子由名词短语和动词短语组成。

每个短语只是一个单独的名词或动词“她”,然后是“走了”,结构与我们之前见过的相同,但这现在是我们的计算机能够理解句子的结构,以便能够获得某种结构。

理解句子的部分是如何相互关联的。让我再给它另一个句子,我可以尝试“她看到了城市”这样。

示例我们刚才处理的词,然后我们最终得到这个语法树,它是一个包含名词短语和动词短语的句子,名词短语相对简单,就是“她”,但动词短语则更复杂,它并没有“看到”。

比如城市,让我们再做一个。

使用这个语法,让我们做一些像“她看到了一辆车”的句子,这看起来会很相似,我们得到的是“她”,但我们的动词短语现在不同,它是“看到了一辆车”,因为在我们的语言中有多个可能的限定词和名词。我没有给这个语法太多词汇,但如果有的话。

我给它提供了更大的词汇量,它就能理解越来越多的内容。

不同类型的句子,给你增加一些复杂度的感觉,我们可以在这里添加更多的复杂性,我们的语法越复杂,规则越多,我们将能够生成更多不同类型的句子。所以让我们看一下CFG一个例子,我添加了一个完整的。

我添加了一些其他不同类型的规则,比如形容词短语,我们可以在名词短语中有多个形容词,因此名词短语可以像形容词短语后面跟着名词短语,如果我想说像“大城市”,那是一个形容词短语,后面跟着。

可以是一个名词短语,或者我们也可以有一个名词和一个介词短语,例如“街上的车”,其中“在街上”是一个介词短语,我们可能想将这两个想法结合在一起,因为“街上的车”仍然可以作为一种名词短语,因此无需理解。

如果详细讲解所有这些规则,它就开始涉及到英语的本质。

语法,但现在我们有了一种更复杂的方式来理解这些类型的句子,因此如果我运行Python CFG 1,我可以尝试输入一些像“她看到了宽街”的句子,例如一个更。

复杂的句子,如果我们让它变大,你可以看到这个句子是什么样的。我会把它缩小一点,所以现在我们有了这样一个句子:她看到了宽街,宽街是一个完整的名词短语。

“看到了宽街”是一个完整的动词短语,而“她看到了宽街”最终形成整个句子。让我们再看一个例子,介绍这种模糊性的概念,所以我可以运行Python CFG 1,让我输入一个像“她看到了带望远镜的狗”的句子,所以这是我们的句子。

这里是一个可能的语法树,表示这个想法:她看到了名词短语“狗”,然后是带有望远镜的介词短语,句子的解释是她看到的是一只狗,而她是如何看到的,她是用望远镜看到的,因此这是一个。

解释她是如何使用单目望远镜的,使用那些望远镜她看到了狗,但另一个。

解析该句子的一个可能方式是这里的树。

你可以说她看到了一只带望远镜的狗,其中“带望远镜的狗”形成了一个完整的名词短语,使用相同的词,顺序也相同。

但不同的语法结构,现在我们有一个带着望远镜的狗。所有这些名词短语意味着她看到了什么,她看到的是一只狗,而那只狗恰好有望远镜,因此解析这个句子的不同方式,即便给定相同的可能顺序。

单词和NLTK的算法在这个特定的算法中具有能力,能够找到所有这些,以理解不同的解析句子的方式,并能够提取出一些有用的含义。因此,这就是对的简要概述。

我们可以通过使用这些上下文无关的语法规则来获取语言的结构,以描述语言的结构。但我们可能还关心的是理解这些单词序列在实际中是如何相互关联的。

单词本身的语法使我们之前看到的,能够生成一个句子,比如“我吃了一个香蕉”,其中“我”是名词短语,而“吃了一个香蕉”是动词短语,但它也允许生成像“我吃了一辆蓝色的车”这样的句子,这在语法上也是符合规则的。

这可能是一个人不太可能说的句子,我们可能希望我们的AI能够封装某些单词序列比其他序列更可能或更不可能的概念。因此,为了处理这一点,我们将引入Engram的概念。

更普遍地说,Engram指的是我们文本中的某些n个项目的序列,这些项目可能采取不同的形式。我们可以有字符Engrams,它只是n个字符的连续序列,例如,三个连续的字符或四个连续的字符。

有单词Engrams,它们是连续的。

从特定文本样本中提取的n个连续单词序列,这证明非常有用,你可以选择n来决定我们的序列会有多少。当n为1时,我们只是在查看一个单词或一个字符,这就是我们可能称之为单元组(unigram)的东西,仅一个项目。

这通常被称为二元组,所以一个Engram当n等于二时,查看两个连续的单词。如果有三个项目,你可能想象称之为三元组,所以是三个连续的字符或三个恰好在一个连续序列中的单词。如果我们取一个句子。

例如,这里有一句来自《福尔摩斯探案集》的句子:“我多久说过你,当你排除了不可能的事情,剩下的无论多么不可能的都必须是真相。”如果我们查看三个单词的序列,可以提取出哪些三元组。

第一个三元组将是这三个单词的序列出现的频率,然后我们可以查看下一个三元组,通常是“我”,下一个三元组是“我说”,接着是“我说了”,这都是三元组,显示在文本中的三个连续单词序列。

提取这些图表和三元组或更一般的n-gram,结果证明是非常有帮助的,因为当我们分析大量文本时,一次性分析整个文本并不特别有意义,而是我们希望对文本进行分段。

将其拆分成我们可以开始进行一些分析的片段,尽管我们的AI可能从未见过这整个句子,但它可能见过“对你来说”这个三元组,因为“对你来说”是可能在Rai之前见过的其他文档中出现的,因此它知道一些。

关于那个特定的三个单词的序列,或者像我提到的另一个三个单词的序列,这在英语中是相当常见的,因此我们希望能够提取这些类型的n-gram,我们该如何做到这一点?

我们如何提取三个单词的序列?我们需要将输入以某种方式拆分为所有单独的单词,这个过程通常被称为标记化。

将某个序列拆分成独特的片段,我们称这些片段为标记,最常见的是指单词标记化。我有一些文本序列,我想将其拆分为该文本中出现的所有单词,但这也可能出现在诸如句子标记化的上下文中。

我有一长串文本,我想将其拆分为句子。例如,单词标记化如何运作?

将我们的字符序列拆分成单词的任务,我们已经看到了这个想法。在单词标记化中,刚才我对输入序列调用了Python的拆分方法,或者说拆分方法根据空格的出现将那个单词序列分开。如果我有一句话。

像“无论剩下什么,尽管不太可能”。

“必定是真理”,我该如何标记化这个?简单的方法是说,每当你看到一个空格,就去拆分它。我们将拆分这个。

仅通过查找特定字符串和空格,我们得到的结果是一句话,诸如“无论剩下什么,尽管不太可能,必定是真理”。但你会注意到,如果我们仅仅根据空格的位置来拆分,我们会保留标点符号,比如有一个逗号。

在“剩下的”之后有一个逗号,在“不太可能”之后有一个句号,在“真理”之后有一个句号。当我们考虑将内容标记化为单独的单词时,这会带来一些挑战,因为如果你将单词彼此进行比较,这个带句号的“真理”如果仅进行字符串比较。

这将与没有句号的“truth”一词有所不同,因此这个标点有时会给我们带来问题,所以我们可能希望以某种方式处理它,要么将标点视为一个完全独立的标记,要么也许完全从我们的序列中移除该标点。

还有,这可能是我们想要做的事情,但在其他情况下,它变得有些不清晰,点钟,福尔摩斯先生迅速走进房间,嗯,这个在9点钟后的撇号,好的,在9点钟的O后面,这是否是我们应该去掉的?我们应该基于这个来分开吗?

好吧,哦,时钟那里也有一些有趣的问题,如果你开始考虑像连字符单词这样的东西,那就更棘手了,像这样,我们有一堆连字符的词,然后你需要做出判断,这是一个分开的地方吗。

将内容拆分为独立单词,还是要把frock-coat、well-cut和pearl-grey视为独立的词,所以这些往往会带来我们需要处理的挑战,这也是我们在尝试执行这种分析时需要做出的决定,类似的挑战。

在句子标记化的世界中会出现,当涉及到这段句子的序列时,想象一下这个句子序列,例如,如果你看看这个特定的句子序列,你可能会想象你可以相当容易地提取句子,这里是一个句子,这里是第二个句子,所以我们有两个。

这个特定段落中的不同句子,其区分特征似乎是句号,句号将一个句子与另一个句子分开,也许还有其他类型的标点符号,比如感叹号或问号,但这就是这些类型。

我们知道的标点符号通常出现在句子的末尾,但如果你看看像这样的句子,那就更棘手了,不仅仅是与福尔摩斯对话,而是与霍尔姆斯先生对话,现在,我们在霍尔姆斯先生后面有一个句号,所以如果你只是基于。

句号你可能会想象这将是一个句子,然后霍尔姆斯会是一个句子,接着我们会有第三个句子,事情确实变得有些棘手,当你开始想象这些情况时,以及对话会使这变得更加复杂,如果你有这些。

里面的行分开,比如说他所说的,这个特定的词序列,以及这个特定的词序列。它们提出了有趣的挑战,涉及到我们如何将句子分开成独立的句子。

这些都是我们的算法在实际中需要决定的内容,通常我们可以使用一些启发式方法,我们知道某些句点的出现,例如Mr.之后的句点,作为其他例子,我们知道这不是新句子的开始,因此我们可以对其进行编码。

将规则融入我们的AI,以使其能够以我们想要的方式进行标记化,因此一旦我们具备了标记特定段落的能力,就可以将段落拆分成单个单词,从而开始提取实际的ngrams,我们可以真正看看这些内容。

通过进入一个Python程序来提取这些ngrams,我们可以使用NLTK,自然语言工具包来帮助我们,因此我们将进入ngrams,查看Engram spy,我们将使用一些文本语料库。

一些文档的序列,使用所有这些文档,并提取最流行的ngrams,因此为了实现这一点,我们将加载从一个我们指定的目录的数据,这个命令行参数还将接受一个数字n。

关于我们应该在多少序列单词中查看,那么我们就会计算所有的NLTK点ngrams,因此我们将查看整个语料库中的所有ngrams,并将其保存在变量ngrams中,然后我们将查看这些内容。

最常见的那些,并打印出来,因此为了做到这一点,我不仅在使用NLTK,还在使用内置于Python中的Counter,我可以计算这些不同ngrams出现的次数。

因此我们将进入ngrams,我会说一些类似于python ngrams的内容,我们先来看unigram。

在一个语料库中,单个词的序列,而我准备的语料库是I。

我有所有这些故事,来自福尔摩斯的故事,每一个都是福尔摩斯故事中的一部分,所以我在这个语料库中有很多文本,我将作为命令行参数提供这个语料库。

它将把所有福尔摩斯的故事加载到内存中,或者至少加载我在这个语料库中提供的那些内容,它将查找最流行的unigram,这些流行的单词序列,似乎最流行的就是那个词,使用了9700次。

接下来我用了五千次,使用了大约五千次你可能预期的单词。那么现在,让我们检查一下买grams,例如福尔摩斯的二元组,现在再次出现的两个单词序列。

这些是出现频率较高的bye,Gramps类型,通常出现在福尔摩斯故事的语料库中,这在其他语料库中也可能是真的,但我们只有在实际测试后才能确认。为了保险起见,我们再试一次。

尝试寻找三元组,这些三元组可能会出现,现在我们看到它们像是出现了其中之一,我认为在这些中!

是由三个单词组成的序列,现在它们在多个地方出现。

哈佛CS50-AI | Python人工智能入门(2020·完整版) - P21:L6- 自然语言处理 2 (马尔可夫,词袋,朴素贝叶斯,信息检索,tf-idf) - ShowMeAI - BV1AQ4y1y7wy

偶尔会多次出现。

这个特定的语料库,那么这里的潜在使用案例是什么?现在我们有一些数据,我们有关于特定单词序列出现的频率,按特定顺序排列,并利用这些数据,我们可以开始做一些预测。我们可能会说,如果你看到这些单词,它是。

有合理的机会,后面跟着的单词应该是单词“a”,如果我看到单词“one of”,可以合理地想象下一个单词可能是单词“the”,例如,因为我们有关于三元组序列的数据,以及它们出现的频率。现在基于两个单词,你可能会。

能够预测第三个单词是什么,而我们可以用来实现这一点的模型是我们之前见过的模型,它是马尔可夫模型。再次回想,马尔可夫模型实际上只指某种事件序列。

发生在一个时间步之后,每个单位都有某种能力来预测下一个单位会是什么,或者可能是过去两个单位预测下一个单位会是什么,或者过去三个单位预测下一个单位会是什么。我们可以使用马尔可夫模型并将其应用于语言。

一种非常幼稚且简单的方法来尝试生成自然语言,让我们的AI能够像英语文本一样说话,它的工作方式是,我们将说一些内容,比如在给定这两个单词的情况下,得到一些概率分布,这个概率分布是什么。

根据所有的数据,第三个单词可能是什么,如果你看到它,可能的第三个单词有哪些,它们出现的频率如何。利用这些信息,我们可以尝试构建我们期望的第三个单词是什么。如果你不断这样做,效果就是我们的马尔可夫模型可以。

有效地开始生成文本并。

能够生成不在原始语料库中的文本,但听起来有点像原始语料库,使用相同的规则。那么我们也来看看一个例子。我们现在在这里,我还有另一个语料库,这是我手上的语料库。

威廉·莎士比亚的所有作品,所以我有一整堆故事。来自莎士比亚,所有的故事都在这个大的文本文件中。因此,我想做的是看看,所有的语言图式,也许看看莎士比亚文本中的所有三元组,然后弄清楚给定两个单词的情况下。

我能预测第三个单词,可能是什么,然后继续。重复这个过程,我有两个单词,预测第三个单词,然后从第二和第三个单词预测,第四个单词,从第三和。第四个单词预测第五个单词,最终生成随机句子。

听起来像莎士比亚的句子,使用莎士比亚所使用的相似单词模式,但实际上从未在莎士比亚中出现过。为了做到这一点,我将展示 generator.py,这将从特定文件读取数据。我使用的一个,Python库叫做 Markova Phi。

将为我完成这个过程,所以这里有一些库,可以。训练一堆文本,并基于该文本生成马尔可夫模型。我将继续并且。

生成五个随机生成的句子,所以我们接下来将深入探讨。马尔可夫,我将对莎士比亚的文本运行生成器,我们看到的是它。会加载这些数据,然后这是,我们得到的五个。不同的句子,这些是,句子在任何地方都没有出现过。

莎士比亚的戏剧,但设计成,听起来像莎士比亚,旨在仅仅取两个单词,并且,预测给定这两个单词莎士比亚可能会选择的第三个单词,跟随他,你知道这些句子可能没有,任何意义,不是说人工智能。

尝试表达任何潜在的,含义,这只是试图。理解基于单词的顺序,接下来可能会出现什么。作为下一个单词,例如,这些是,它能够生成的句子类型。如果你多次运行这个,你会。

最终会得到不同的结果,我,可能再次运行这个,然后得到一个。完全不同的一组五个不同,句子也应该是。

听起来有点像,莎士比亚的句子声音一样。因此,这就是我们如何使用马尔可夫模型,简单地尝试生成语言,语言目前并没有太多意义。你不想在这个当前形式下使用,系统来做。

像机器翻译这样的事情,因为它无法,封装任何意义,但我们。现在开始看到我们的人工智能,逐渐变得更好,尝试。说我们的语言或以某种方式处理自然语言,具有一定的意义。因此我们现在将看一下几项,其他任务,我们可能希望我们的人工智能。

能够执行的任务之一是,文本分类,这实际上就是。

一种分类问题,我们已经,讨论过分类问题。这些问题是,我们希望将某个对象分类。到多个不同类别。

这种文本的表现方式是,无论何时你有一些文本样本,并且想把它归入某个类别,比如说,给定一封邮件,它是否属于收件箱,还是属于垃圾邮件?这两个类别中它属于哪个,你是通过查看文本来实现的。

能够对这些文本进行某种分析,以得出结论,比如说根据出现在邮件中的词汇,我认为这可能属于收件箱,或者我认为它可能属于垃圾邮件,你可能会想象为多种不同类型的。

这种分类问题,你可能想象另一个常见的例子是情感分析,我想分析给定的文本样本,是否有正面情感,还是有负面情感,这可能出现在例如。

例如,网站上的产品评论,或是你有的反馈!

一堆由网站用户提供的数据样本,你想能够快速分析这些评论是正面的还是负面的,人们在说什么,以便了解他们在说什么,以便将文本分类为其中之一。

这两种不同的类别,所以怎么。

我们可以如何处理这个问题呢?让我们看看一些示例产品评论,这里有一些可能出现的产品评论:“我孙子非常喜欢这个,有趣的产品”,几天后坏了,这是我很久以来玩过的最好的游戏,“有点廉价和脆弱,不值得买”。

你可能在亚马逊或易贝或其他某些人们销售产品的网站上看到的不同产品评论,我们人类可以相对容易地将其分类为正面情感或负面情感。我们可能会说第一条和第三条是正面的。

正面情感的信息,第二和第四条可能是负面情感的信息,但我们如何尝试评估这些评论呢?你知道它们是正面还是负面,这最终取决于这些特定评论中的词汇。

在这些特定句子中,现在我们将忽略结构,以及词汇之间的关系,我们只关注词汇本身,所以这里可能有一些关键词,例如喜欢有趣最好,这些词可能在更多的正面评论中出现。

而像破碎廉价脆弱这样的词,可能更容易出现在负面评论中,而非正面评论。因此,一种处理这种文本分析的方法是,暂时忽略这些句子的结构,也就是说我们不。

我们关心的是单词之间的关系,我们不会尝试解析这些句子以构建它们的语法结构,就像我们刚才看到的那样,但我们可能只依赖于实际使用的单词,依赖于积极评价更有可能的事实。

拥有“最好”、“喜爱”和“有趣”等单词,负面评论更可能包含我们在这种模型中突出显示的负面词汇,这种思考语言的方法通常被称为词袋模型,我们将对其进行建模。

文本样本,不关心它的。

结构,但仅仅关注样本中出现的无序单词集合,我们关心的只是文本中的单词,而不关心这些单词的顺序,也不关心单词的结构,我们不在意什么名词与什么形容词搭配。

事物之间如何相互关联,我们只关心单词,结果证明这种方法在进行分类时,比如积极情感或消极情感,效果相当不错,你可以想象用我们讨论过的多种方式来实现。

分类样式的问题,但在自然语言中,最流行的方法之一是朴素贝叶斯方法,这是分析某事物是否是积极情感或消极情感的一种方法,或者只是试图将一些文本进行分类。

可能的类别,它不仅适用于文本,也适用于其他类型的概念,但在分析文本和自然语言的领域中相当流行,朴素贝叶斯方法基于贝叶斯规则,你可能还记得我们讨论概率时提到的贝叶斯。

规则看起来是这样的,给定某事件A的事件B的概率可以用这个表达式来表示,给定A的B的概率等于给定B的A的概率乘以B的概率除以A的概率,我们看到这只是因为。

条件独立性的定义,以及两个事件一起发生的意义,这就是我们的贝叶斯规则的公式,结果证明它非常有用,我们能够通过翻转这些事件的顺序在这个概率计算中预测一个事件。

这种方法将非常有帮助,我们稍后会看到原因。它能够进行情感分析,因为我想说,消息是积极的概率是多少,或消息是消极的概率是多少,我会简化这个。

使用表情符号只是为了简单,比如积极的概率、消极的概率,这就是我想计算的,但我想在给定一些信息的情况下计算,比如这里是一个文本样本,我的孙子喜欢它,我想知道的不仅仅是什么。

任何消息是积极的概率是什么,但在给定我的孙子喜欢它作为样本文本的情况下,消息是积极的概率是什么?那么,在给定这个信息,即样本中包含单词“我的孙子喜欢它”的情况下,这个是积极消息的概率又是多少呢?

根据词袋模型,我们将真正忽略单词的顺序,而不是将其视为有某种结构的单个句子,而是将其视为一堆不同的单词,我们将要说的是,这个是积极的概率是多少。

给定单词“我的”在消息中的情况下,给定单词“孙子”在消息中的情况下,给定单词“喜欢”在消息中的情况下,以及给定单词在消息中的情况下,词袋模型在这里我们将整个样本视为一堆不同的单词。

这就是我想计算的概率,给定这些单词,这个是积极消息的概率是多少,现在我们可以应用贝叶斯定理,这实际上是某个事件给定某个事件的概率,这正是我想要的。

根据贝叶斯定理,这整个表达式等于……好吧,是我交换了它们的顺序,是所有这些单词在它是积极消息的情况下的概率,乘以它是积极消息的概率,除以所有单词的概率。

所以这只是贝叶斯定理的一个应用,我们已经看到我想要将给定单词的积极概率表示为与积极消息的单词概率相关,结果是你可能会记得我们讨论过的。

关于概率,这个分母无论我们看积极还是消极消息都是相同的,这些单词的概率并没有变化,因为我们下面没有积极或消极的东西,所以我们可以说,rather than just say that this expression up。

这里等于下面这个表达式,它实际上只是与分子成比例,我们可以暂时忽略分母,使用分母会得到一个确切的概率,但实际上我们要做的就是弄清楚概率与什么成比例。

最后,我们必须归一化概率分布,确保概率分布最终的总和为一。所以现在我已经能够形成这个概率,这是我关心的,与这两件事相乘成比例,即单词的概率。

给定正面消息,乘以正面消息的概率,但再次如果你回想我们的概率规则,我们实际上可以将其计算为所有这些事情发生的联合概率,即正面消息的概率乘以这些概率。

给定正面消息的词,实际上就是这些事情的联合概率。这与它是正面消息的概率,以及 my 在句子或消息中,grandson 在样本中,love 在样本中,以及 it 在样本中是一样的。所以,利用这个规则来定义。

联合概率我能够说,这整个表达式现在是与这序列成比例的,这些词的联合概率以及其中的正面内容。所以,现在有趣的问题就是如何计算这个联合概率,我如何弄清楚概率。

给定某个任意消息,它是正面的,并且其中包含单词 my,单词 grandson,单词 loved 和单词 it。你会记得,我们可以通过将所有这些条件概率相乘来计算联合概率。

我想知道 A、B 和 C 的概率,我可以将其计算为 A 的概率乘以给定 A 的 B 的概率乘以给定 A 和 B 的 C 的概率。我可以将这些条件概率相乘,以获得我关心的总体联合概率。

我可以在这里做同样的事情,我可以说,让我们将正面的概率与单词 my 在消息中出现的概率相乘,前提是它是正面的,乘以给定单词 my 在那里且它是正面的情况下,grandson 出现在消息中的概率。

乘以给定这三样东西的 loved 的概率,乘以给定这四样东西的 it 的概率,而这将是一个相当复杂的计算,我们可能没有好的方法去知道答案,比如,孙子出现的概率是多少。

在消息中,前提是它是正面的,且单词 my 在消息中。这并不是我们会有一个容易回答的事情,这就是朴素贝叶斯的朴素之处。我们将简化这个概念,而不是精确计算这个概率分布。

我们假设这些词在已知是积极信息的情况下彼此独立。如果这是一个积极的信息,那么“grandson”在消息中出现的概率并不会因为我知道“loved”不是消息而改变。

在实际情况中,这可能并不一定成立,现实世界中这些词可能并不独立,但我们假设它们独立,以简化我们的模型。事实证明,这种简化仍然让我们获得相当不错的结果,所以我们要做的假设是。

所有这些词出现的概率仅仅取决于消息是积极还是消极。我仍然可以说,“loved”在积极信息中出现的可能性高于在消极信息中出现的可能性,这可能是对的,但我们也会说这不会改变“loved”出现的可能性。

如果我知道“my”这个词出现在消息中,那么它出现的可能性不会因为这是一个积极的信息而变得更可能或不太可能。这些是我们要做的假设,所以虽然上面的表达式与下面的表达式成正比,我们将简单地说它与这个表达式的概率成正比。

积极的信息,然后对于样本中出现的每个单词,我将乘以在已知这是积极的情况下,给定的不是消息的概率,乘以在已知这是积极的情况下,“grandson”出现在消息中的概率,然后依此类推,对其他出现的单词进行同样的处理。

这些数据会包含在样本中,结果是这些数字我们可以计算。我们之所以做这些数学运算,是为了能够计算我们关心的概率分布,基于这些我们实际上可以计算的项。

基于我们可用的一些数据,这就是如今许多自然语言处理的内容,它涉及分析数据。如果我给你一堆标记为积极或消极的评论数据,那么你就可以开始计算这些特定的项。

我可以仅通过查看我的数据来计算一条消息是积极的概率,看看有多少个正样本,然后将其除以总样本数,这就是我认为一条消息是积极的概率,以及“loved”这个词出现在消息中的概率。

这肯定是积极的,我可以根据我的数据来计算。让我看看样本中有多少个包含“love”这个词的正样本,并将其除以我的正样本总数,这将给我一个关于“love”在评论中出现的概率的近似值。

鉴于我们知道评论是正面的,因此这使我们能够计算这些概率。那么我们不妨进行这项计算,计算“我孙子喜欢它”这句话,是正面还是负面的评论。我们如何能够得出这些概率呢?再次上面的数据是。

我们要计算的表达式,以及在这种情况下可用的数据。解读这些数据的方式是,在所有消息中,49%的消息是正面的,51%的消息是负面的,或许在线评论往往会稍微偏向负面。

他们是正面的,至少基于这个特定的数据样本。这就是我所拥有的,然后我有各种不同词的分布,假设这是一个正面消息,那么有多少正面消息包含“我”这个词呢?你知道,大约是30%,而对于负面消息。

消息中有多少条包含“我”的词,大约是20%。所以似乎“我”这个词在正面消息中出现得更频繁,至少在这个分析中稍微多一些。以“孙子”为例,可能在1%的所有正面消息中出现,而在2%的所有负面消息中出现。

“孙子”这个词出现在32%的所有正面消息中,8%的所有负面消息中,例如,“它”这个词在30%的正面消息中出现,而在40%的负面消息中再次出现,这里是一些任意的数据,仅供参考,但现在我们有了可以开始计算的数据。

那么这个表达式,我该如何计算呢?将所有这些值相乘。这实际上是正面概率乘以我所给定的正面概率,再乘以孙子在正面消息中的概率,依此类推,针对其他每个单词,如果你这样做的话。

将所有这些值相乘,你会得到这个0.00014112,单独看这个数字并没有什么特别的意义,但如果你将这个表达式与我知道它是正面的概率相乘,再乘以给定的所有词的概率。

消息是正面的,并且将其与负面情感消息进行比较。我想知道它是负面消息的概率,乘以给定的所有这些词的概率,得出这是一个负面消息的概率。那么我该如何做到这一点呢?为了做到这一点,你只需将负面概率与所有这些条件概率相乘。

如果我将这五个值相乘,那么我得到的值是负面0.00006528,再次强调,这个数值在孤立状态下并没有特别的意义,真正有意义的是处理这两个值。

作为一种概率分布,并且,通过归一化它们,使得这两个值的总和为1,这就是概率分布应有的方式。我们通过将这两个值相加,然后将每个值除以它们的总和来实现归一化——以便能够做到这一点。

当归一化这个概率分布时,你最终得到的结果大概是这样的:正面0.6837,负面0.3163。这似乎让我们能够得出结论,我们对这个消息的正面概率大约有68%的信心。

“我孙子喜欢这个”,为什么我们有68%的信心呢?似乎我们比不更有信心,因为“喜欢”这个词在32%的正面消息中出现,但在8%的负面消息中仅出现,因此这是一个相当强的指标。而对于其他词来说,确实像是这个词出现。

在负面消息中更常出现,无法抵消那种爱在积极消息中远远更常出现,因此这种类型的分析就是我们如何应用朴素贝叶斯,我们刚刚进行了这个计算,最终不仅得到了正面或负面的分类。

但我获得了一种信心,比如我认为它是正面的概率是什么。我可以说,我认为它是正面的概率是这样,因此朴素贝叶斯在尝试实现这一点时可以非常强大,只需使用这个词袋模型。

通过查看样本中出现的单词,我能够得出这些结论。现在一个潜在的缺点是,如果你开始严格按照这个规则应用,你会很快注意到的事情是,数据中如果包含零的话会发生什么,假设例如这个情况。

相同的句子“我孙子喜欢这个”,但我们假设这里的值不是0.01,而是在我们的数据集中,从未发生过在正面消息中出现“孙子”这个词,这确实是可能的,如果我有一个相对较小的。

数据集可能并不一定所有消息都会包含“孙子”这个词,也许在我的数据集中没有任何正面消息包含“孙子”这个词,但如果有2%的负面消息仍然包含“孙子”这个词,那我们就会遇到一个问题。

有趣的挑战在于,当我将所有正数相乘并将所有负数相乘以计算这两种概率时,最终得到的是一个值为零的正值。我得到的是纯零,因为当我将所有的。

当我将某个数乘以零时,无论其他数字是什么,结果都会是零,负数也是如此,因此这似乎是一个问题,因为“孙子”从未出现在任何正面消息中。

在我们的符号内部,我们似乎得出的结论是,信息是正面的概率为零,因此它必须是负面的,因为我们看到“孙子”这个词的唯一情况是在负面消息中。

正面消息更可能包含“爱”这个词,因为我们乘以零,这意味着其他概率完全无关紧要,因此这是我们需要面对的挑战,这意味着我们可能不会每个值在我们的分布中,以便稍微平滑数据。

如果我们纯粹使用这种方法,就能够获得正确的结果,正因为如此,有很多方法可以确保我们不会将某个东西乘以零,将某个东西乘以一个小数字是可以的,因为它可以被其他更大的数字抵消。

但将数字乘以零似乎意味着故事结束了,你将一个数字乘以零,输出将是零,无论其他任何数字有多大,因此,在朴素贝叶斯中,一个相对常见的方法是这种加法平滑的想法,给其他概率加上一个值α。

一种这样的方式称为拉普拉斯平滑。

这基本上意味着对我们分布中的每个值加一,所以如果我有100个样本,且其中0个包含“孙子”这个词,我可能会说,不如假设我看到了一个额外的样本,其中出现了“孙子”这个词。

“孙子”没有出现,所以我会说,现在我有102个样本中有1个样本包含“孙子”这个词,我基本上创造了两个之前不存在的样本,但通过这样做,我已经能够稍微平滑分布,以确保我从未乘以数字。

通过假设每个类别中都有一个额外的值,我实际上没有的,这让我们得出了一个结果,那就是不必担心将数字乘以零,因此这是我们可以使用的方法,以便在处理的情况下应用朴素贝叶斯。

现在让我们看看如何在实践中应用它,事实证明,MLT不仅具有提取n-gram和将内容标记为单词的能力,还能够在某些样本中应用朴素贝叶斯。

例如文本,所以让我们继续进行,我在 sentiment 中准备了一个语料库,包含我生成的评论,但你可以想象使用真实评论,或者我只有几条正面评论,比如“太棒了”,“非常有趣”,“会推荐给我孙子,他喜欢这些”。

各种消息,我有一堆负面评论,真的不值得,便宜得让人失望,没有按预期工作。每一行都是一堆正面评论和负面评论,我现在想做的是以某种方式分析它们,所以这里是 sentiment.dot.pi。

我们要做的第一件事是提取所有正面和负面的句子,创建一个使用过的所有单词的集合,然后我们将继续训练 NLTK 的朴素贝叶斯分类器,使用所有这些训练数据,而训练数据的有效性。

如果我将所有正面的消息标记为正面,将所有负面的消息标记为负面,然后。我会继续将这个分类器应用于它,我会说我希望将所有的训练数据分类为正面或负面。

然后我会从用户那里获取一些输入,他们可以输入一串单词,然后我想将该序列分类为正面或负面,然后我将打印出每个分类的概率,并且这里有一些辅助函数来组织这些内容。

以ltk所期望的方式呈现,但关键思想是我正在将正面消息标记,将负面消息标记,然后放入分类器中,现在尝试进行分类。

分类一些新文本,所以让我们继续尝试,我将进入情感分析,并运行 Python sentiment,将包含所有正面和负面消息的语料库作为输入,因为根据语料库的不同,这将影响概率。

我们分类的有效性完全依赖于我们的数据有多好,以及我们拥有多少数据,以及这些数据标记得有多好。所以我现在可以尝试一下,像是尝试这样的评论:“太棒了”,就像我可能会留下的评论,似乎有 96% 的机会。

估计这是一个正面消息,4% 的机会是负面的,可能是因为“葡萄”这个词出现在正面消息中,但不出现在负面消息中,这可能是我们的 AI 能够利用的一个方面,实际上它会寻找的是。

区分性的词汇,如果这些词的概率在正面和负面词汇之间相似,那么朴素贝叶斯分类器就不会使用这些值,因为它们在两边是相同的,因此不会在算法中具有某种重要性。

对于正面和负面的值进行相乘,最终得到的结果差不多。最终,影响朴素贝叶斯分类器的区别在于,当你为一个类别乘以一个远大于另一个类别的值时,当一个词如"好"在某一种类型中出现的可能性远高于其他类型时。

一种消息与另一种消息之间的差别,这是朴素贝叶斯分类器的一个好处,尽管我没有告诉它,"好"比"坏"更重要,但朴素贝叶斯可以根据数据来判断,它可以发现这两者出现的频率大致相同,但。

"好"是一个区分器,可以在这两种消息类型之间有所不同,因此我可以再试一次,输入一个句子,比如"非常有趣",例如,这个句子就有点不那么确定,62%的概率是正面,37%的概率是负面,可能是因为不够明确。

在状态内部的区分器或区分因素,我再尝试一次,比如说"价格过高",现在95%到96%肯定这是一个负面情绪,可能是因为"价格过高"这个词之前在负面情绪表达中出现过,因此你知道这是什么。

这很可能是一个负面句子,因此现在朴素贝叶斯给了我们能力来分类文本,给定足够的训练数据和示例,我们可以训练我们的AI来分析自然语言中的人类词汇,找出哪些词更可能出现在正面而非。

负面情绪消息中,并据此进行分类,你可以想象在任何时候想要将文本分组为类别时做同样的事情。如果我想将一封电子邮件分类为邮件、好邮件或垃圾邮件,你可以应用类似的想法,尝试查看。

针对具有区分性的词汇,这些词使得一封邮件更有可能被判定为垃圾邮件或不是垃圾邮件,并且仅仅训练一个朴素贝叶斯分类器,以便能够判断这种分布是什么,并能够判断如何将一封邮件分类为好邮件或垃圾邮件。当然,它不会给我们一个。

它给出的不是确定的答案,而是一个概率分布,比如63%为正面,37%为负面,这可能是我们垃圾邮件过滤器和电子邮件有时出错的原因,有时会认为一封好的邮件实际上是垃圾邮件,反之亦然。因为最终,它能做的只是计算概率。

自然语言的分布是模糊的,我们通常可以在概率的世界中处理,试图得到一个合理的答案,即使我们不能确保这确实是我们所期望的数字,因此,我们可以看看如何开始处理这个问题。

处理一些文本,并能够分析这些文本,将其归类为某些类别,但最终除了能够分析文本和分类之外,我们还希望能够,获取文本的信息,从文本中提炼出某种意义,这开始让我们深入思考。

在信息世界中,能够尝试以文本形式获取数据并从中检索信息,因此,一类问题被称为信息检索(IR),即在响应查询时寻找相关文档的任务。这就像你在某处输入查询。

像谷歌这样的搜索引擎,或者你在某个系统中输入某些内容,这将会在图书馆目录中查找,例如,这将会寻找对查询的响应,我想寻找关于美国宪法的文档,或者其他类似的东西。

与匹配该查询的文档相联系,你可以想象我真正想要做的是,为了有效解决这个任务,我需要能够处理文档,找出这些文档的内容。我想知道这些特定文档到底在讲什么。

是关于那些文档的主题之一,这样我就能更有效地从这些特定文档中检索信息,这涉及到一组通常被称为主题建模的任务。

我希望探索一组文档的主题,这正是人类可以做到的,人类可以阅读文档并告诉你,好的,这个文档是关于什么的,并给出几个主题,比如文档中重要的人物和重要的对象。

文档可以告诉你那类事情,但我们希望人工智能也能做到这一点,比如给定某个文档,你能告诉我这个文档中的重要词汇是什么吗?哪些词汇使得股票单位显得特别,如果我根据这些文档进行查找。

例如关键词,因此一种本能和直观的想法是。

可能比较合理的是,我们就用术语频率,术语频率被定义为特定术语在文档中出现的次数,如果我有一份包含一百个单词的文档。

你知道某个特定的词出现了十次,它的词频就是十,没错,它出现得相当频繁,也许这将是一个重要的词。有时你还会看到这个框架,就像是总词数的一个比例,十个词中有100个,可能它的词频是0.1。

意味着所有词中有10%是我关心的这个特定词,最终这并不会相对改变它们在任何特定文档中的重要性,但它们的理念是寻找出现频率较高的词,因为这些词更可能是。

霍顿词在一个语料库中的分布。

文档,所以让我们试试看,比如我想找出福尔摩斯的故事是关于什么的,我有一堆福尔摩斯的故事,我想大致了解它们是关于什么的,重要角色是谁,重要的是什么物品。

这个故事的重要部分是什么,仅仅从词的角度来看,我希望AI能够自己弄清楚这点,它将通过查看词频来实现,找出出现得最频繁的词。因此我们将继续,我将进入tf-idf目录。

你会很快明白为什么叫这个名字,但让我们先打开TF 0。pi,它将计算文档语料库中前10个词频,或者也许是前5个词频,文档是来自福尔摩斯的故事,我们将加载所有数据。

进入你的语料库,我们将弄清楚,所有出现在该语料库中的词是什么,我们基本上只需汇总所有的词频,计算每个词在文档中出现的频率,然后打印出前。

因此,有一些数据结构可以查看,如果你愿意,吉姆,确切的代码并不是那么重要,重要的是我们正在做的事情,我们将这些文档提取出来,首先进行排序,我们说像是取出所有出现的词并按。

每个词出现的频率,让我们为每个文档保存出现在这些文档中的前5个词。因此,一些辅助函数你可以查看。

如果你感兴趣可以查看,但这里的关键思想是我们要做的就是在福尔摩斯的故事上运行T 0,我希望从这个过程中弄清楚福尔摩斯中重要的词是什么,例如,我们将运行这个,看看结果。

数据正在加载,这就是我们为这个特定故事得到的结果。重要的词是“the”、“and”、“an”、“i”、“ii”,这些词在这个故事中出现得最频繁,得出的词是“the”、“and”、“an”、“i”、“a”、“of”。

我们关注的是哪些词在这些不同文档中出现得最频繁,但我们自然获得的只是英语中出现频率很高的词,比如“the”、“of”和“and”,因此它们在这些文档中也很常见。

对于不同的文档来说,这对我们分析重要词汇并没有特别大的帮助,因为这些词只是英语语法结构的一部分。事实证明,我们可以将词汇分为几类,而这些词正好符合。

这些词被称为功能词,它们本身几乎没有意义,但用于在句子中语法性地连接不同部分。这些词包括“am”、“buy”、“do”、“when”等等。

像“which”、“with”和“yet”这样的词单独来看,它们的意思难以界定,它们的意义来自于它们如何连接句子的不同部分,而这些功能词也是如此。

在英语等语言中,我们可以称之为一个封闭的词类,实际上只是一些固定的功能词列表,它们很少变化。这些词是常用来连接语言中其他语法结构的,与我们所称之的内容词形成对比。

这对我们并没有特别大的帮助,我们所使用的术语可能被称为内容词,这些词独立承载意义,例如。

算法类别的计算机词汇实际上有某种意义,而这些通常是我们关心的词。

关于这些词,我们想弄清楚在文档中哪些是重要的词汇。我们可能更关心内容词,而不是功能词,因此一种策略是忽略所有的功能词。在TF one dot pi中,我已经完成了这个。

完全相同的事情,除了我将从一个名为functions words dot text的文件中加载一大堆词,这些词是按字母顺序排列的功能词。这些只是一些用于连接英语中其他词的功能词。

有人编制了这个特定的列表,这些词是我想要忽略的。如果这些词中的任何一个出现,我们就把它当作顶级术语来忽略,因为如果我想分析文档中的重要术语,这些词可能并不重要。

在TF-IDF中,我们实际上做的是,如果这个词在我的功能词集中,我会跳过它,忽略任何功能词,继续下一个词,并计算那些词的频率。因此,我将假装。

功能词不在这里,现在我能更好地理解每个不同福尔摩斯故事中哪些词是重要的。现在让我们在福尔摩斯语料库上运行TF-IDF,看看我们能得到什么,让我们看看每个故事中最重要的词是什么。

故事ISM,好吧,似乎每个故事中最重要的词是“福尔摩斯”。我想这是我们所期望的,因为它们都是福尔摩斯的故事,而“福尔摩斯”不是一个功能词,它不是“the”或“a”或“an”,所以没有被忽略,但“福尔摩斯”这些词可能不是我所指的。

我想知道哪些词是重要的,尽管“福尔摩斯”出现得最频繁,但这并没有给我提供很多关于不同福尔摩斯故事实际内容的信息,原因是“福尔摩斯”出现在所有故事中,因此它没有意义。

如果我说这个故事是关于福尔摩斯的,我想知道在文档中出现的单词,与其他文档中出现的频率较低的单词是什么。因此,我真正想知道的是,哪些词在这篇文档中出现,而在其他文档中出现的频率较低。

在这个概念下,我们引入逆文档频率的概念。逆文档频率是衡量一个单词在整个语料库中出现的普遍性或稀有性的指标,数学上通常是这样计算的:总数的对数。

文档的数量除以包含该词的文档数量。如果像“福尔摩斯”这样的词出现在所有文档中,那么总文档数量就是文档总数,而包含“福尔摩斯”的文档数量也是一样。因此,当你将这两个数相除时,你会得到1。

1的对数就是0,因此,如果福尔摩斯出现在所有文档中,它的逆文档频率就是0。你可以把逆文档频率看作是一个度量,说明在这篇特定文档中,单词出现的稀有程度。如果一个单词没有出现在任何文档中。

如果很多文档都出现,这个数字会高得多,这将导致我们得到一个称为TF-IDF的模型,这是一种通过将这两个概念结合在一起来对文档中的重要词进行排名的方法。将词频(TF)相乘。

逆文档频率(IDF),这里的想法是,一个词的重要性取决于两个因素,它取决于在文档中出现的频率,使用启发式方法:如果一个词出现得越频繁,它可能就越重要,我们将其乘以逆文档频率IDF。

因为如果一个词比较稀有,但出现在文档中,它可能比在大多数或所有文档中出现的词更重要,因为它可能在不同文档中话题的不同重要性较低。

让我们在福尔摩斯语料库上应用这个算法,这就是tf-idf,现在我正在计算每个文档中每个单词的TF分数(词频),乘以该词的逆文档频率,而不仅仅是看单个值,而是进行乘法运算。

将这两个值结合起来,以计算总体值,现在如果我在福尔摩斯语料库上运行tf-idf,这将帮助我们更好地近似每个故事中的重要内容,似乎正在提取角色的名字。

在故事中重要的角色,会在这个故事中出现,而不会在其他故事中出现,并且优先考虑那些出现频率更高的角色,这可能是一个更好的分析,关于话题的类型。

不管重要性如何,我还有另一个语料库,其中包含所有的语料。

如果我对美国历史上的《联邦党人文集》运行tf-idf,我们可以开始看到各个《联邦党人文集》中重要的单词是什么,而在第61篇中,似乎是关于这一组内容。

对于弹劾,你可以通过观察在多个文档中出现的关键词,提取出重要的术语和单词,它们在某些文档中出现得足够频繁,而在其他文档中则不出现,这可以成为帮助工具。

理解这种主题建模,弄清楚特定文档的主题,这使我们开始进入语义的世界,即在讨论语言时事物的实际含义,我们不会仅仅考虑词袋。

当我们只是处理一段文本时,我们处理的是一大堆单词。

哈佛CS50-AI | Python人工智能入门(2020·完整版) - P22:L6- 自然语言处理 3 (信息抽取,词网,word2vec) - ShowMeAI - BV1AQ4y1y7wy

现在我们不关心顺序,当我们进入语义世界时。我们确实开始关心这些词的实际含义!

这些词如何相互关联,特别是我们如何从文本中提取信息。信息抽取就是从我们的文档中提取知识,弄清楚给定一大堆文本,我们能否自动化AI的过程。

查看这些文件,提取出什么。

这些文件中有用或相关的知识是,因此让我们看一个例子。我将给你两个来自新闻文章的样本,上面是《哈佛商业评论》的新闻文章样本,关于Facebook,下面是《商业内幕》的文章示例。

关于亚马逊的2018年信息。

这里有一些信息,我们可能希望AI能够提取。关于这些公司的知识,我们可能想要提取,特别是我想提取的数据,比如我想知道公司的成立时间,但我想知道Facebook是在。

在2004年成立,1994年成立的重要信息,我对此非常关心。我该如何从文本中提取这些信息?我如何理解这段文字并弄清楚所有内容?好吧,Facebook是在2004年成立的,我可以寻找模板或。

这种模式出现在多个不同文档中,给我对这种知识的含义有一些理解。我们会注意到这两段之间的一个共同模式,就是这种表达:“Facebook是在2004年成立的,”然后下面是“亚马逊是在。”

成立于1994年,而这两个模板最终为我们提供了一种提取信息的机制,即当公司在年份成立时,逗号。这个!

能告诉我们某个公司成立时间的信息,因为如果我们让AI在网上搜索,让它查看一大堆论文或文章,并找到这种模式:“在blank成立于blank,”,那么我们的AI可以合理地得出结论。

这将是某个公司的名称,而这将是该公司成立的年份。例如,可能不是完美的,但至少这是一个好的启发式方法。所以你可以想象,如果你想训练一个AI来查找信息,你可以给AI这样的模板,不仅提供。

现在的想法是,人工智能可以开始寻找模板,比如“当公司____成立于____”,但也可以给它类似“书籍____是由____编写的”的模板,例如,给它一些模板,让它在网络上搜索,查找与之匹配的文档。

好的,这里是公司和年份,但这当然需要我们编写这些模板,需要我们弄清楚这些信息的结构可能是什么样子的,而不同的网站显然会以不同的方式处理这种类型。

这种方法无法提取所有的信息,因为如果词语的顺序稍微不同,它就无法匹配特定的模板,但我们可以做的一件事是。!

我们可以将数据提供给人工智能,而不是给人工智能模板。我们可以告诉人工智能,比如说Facebook成立于2004年,亚马逊成立于1994年,然后让人工智能处理这两条信息,然后在网络上自由搜索。

在2004年,Facebook和1994年的亚马逊可以一起出现,它可以自行发现这些模板,它可以发现“当____成立于____”这种措辞往往将Facebook与2004年关联,将亚马逊与1994年关联,因此也许它会将其他公司与此类关系联系起来。

这最终成为一种自动化模板生成的方式,结果相当强大。我们现在就来看看我在模板目录中有一个名为公司(company)的CSV文件,这就是我将要提供给我的人工智能的所有数据。

这是亚马逊1994年和Facebook 2004年,而我将告诉我的人工智能去搜索文档语料库中的其他数据,这些对,比如其他的关系。我并没有告诉人工智能这是一家公司及其成立的日期,我只是提供亚马逊1994年和Facebook 2004年。

让人工智能做其余的工作,人工智能将会查看我的语料库,这是我的文档语料库,它将找到像在《商业内幕》中的句子,比如“亚马逊成立于2004年”,这种措辞将会类似于。

如果找到匹配,它就能够识别出这样的信息,比如《哈佛商业评论》的一个故事,其中有句子“Facebook成立于2004年”,它将会在其他许多文档中寻找类似的模式,以提取这种信息。!

如果我继续运行,我会进入模板。我会说Python搜索PI,我将要。查找公司目录中像CSV那样的数据,里面包含了我提前策划的一大堆新闻文章。这里是我得到的关于谷歌的内容。

1998年苹果 976 微软 1975等等,沃尔玛1962年,例如这些。都是与我们之前能够找到的相同模板相匹配的数据。它是如何找到这些的呢?很可能是因为如果我们查看像是,福布斯文章的例子,它有一个。

像“沃尔玛成立于1962年”的短语,它能够。识别这些类型的模式并,从中提取信息。现在,当然,我已经提前策划了所有这些故事,以确保。能够匹配的数据,而实际上并不总是。

当你看到与成立年份相关的公司时,必须以这个确切的格式出现。但如果你给人工智能足够的数据,比如互联网上的所有文本数据,并且让人工智能爬行互联网。寻找信息,它可以非常可靠或以某种概率尝试。

并提取信息,你,这些类型的模板能够。生成有趣的知识感知,而它学习的知识越多,。它能够构建的新模板就越多,寻找在其他地方出现的构造。让我们来看另一个例子。

然后我会向你展示总统的CSV,其中我有两位总统和他们的就职日期:乔治·华盛顿1789年,巴拉克·奥巴马2009年,例如,我。还将给我们的人工智能一个语料库,里面只包含一份文件。即美国总统名单的维基百科文章。

例如,仅仅是关于的信息。

总统,我想从这个网页上的原始HTML文档提取关于总统的信息,因此。 我可以说搜索总统的CSV。总统,我得到的是一大堆关于总统的数据,和他们可能的就职年份,通过寻找与巴拉克·奥巴马2009年匹配的模式。

例如,寻找这些类型的模式,给我们一些线索,了解这个故事。大致是关于什么的,这里是另一个。

例如,如果我打开奥运会内部,这里是奥运会主页的抓取版本,其中有关于。各种不同奥运会的信息,也许我。

想要从这个特定页面提取奥运会地点和年份。好吧,我可以用完全相同的算法来做到这一点,我只是说。好吧,这里有两个奥运会以及它们的地点。

它们的位置信息,比如2012年伦敦,比如让我运行这个Python搜索,查看奥运会的CSV,查看所有奥运数据集,现在我得到一些信息返回,虽然这些信息并不完全完美。

有几个例子显然不太正确,因为我的模板可能太笼统,比如可能在寻找某个广泛类别的事物,而某些奇怪的事情恰好捕捉到了这个特定模板,因此你可以想象添加规则来尝试使。

这个过程更加智能,确保左侧的东西只是一个年份,例如,进行其他各种分析,但纯粹只是基于某些数据,我们能够提取一些有趣的信息。使用某些算法,所有搜索实际上就是在进行数据的提取。

数据语料库,找到与之匹配的模板,这里我正在过滤,只查看恰好匹配的前两个模板,然后使用这些模板从我能够访问的数据中提取结果,能够寻找我关心的所有信息,而这最终将会。

帮我打印出这些结果,以找出匹配项。因此,信息提取是另一个强大的工具,旨在提取信息,但当然它仅在非常有限的上下文中有效。它只在我能够找到完全相似的模板时有效。

这样做是为了得出某种结果。

匹配能够将其连接到某对数据的,这家公司成立于这一年。我想做的是开始考虑词语的语义,并设想一些定义所有词语的方式,能够将字典中的所有词关联起来。

彼此之间,因为这最终是必要的,如果我们希望我们的人工智能能够沟通,我们需要某种表示来表达词语的含义,而一个著名的数据集叫做词网(WordNet)。词网是人类策划的,研究人员共同策划了一个。

一大堆词语及其定义。

它们的各种不同含义,因为一个词可能有多个不同的意思,以及这些词之间的关系。

彼此相关,因此我们的意思是,我可以向你展示一个词网的例子,词网内置于NLTK中,使用NLTK你可以下载并访问词网,所以让我进入词网,并运行词网,提取一个词的信息,比如“城市”这个词,去查看它的印象。

返回的信息是,我关于城市的信息,结果发现,城市有三种不同的感知,根据WordNet有三种不同的含义,这其实就像一本字典,每种感知都有其对应的含义,定义由人提供。

例如,一个单词所属的类别,一个城市是一种市政类型,城市是一种行政区,这让我能够将单词与其他单词关联起来。因此,WordNet的一个优势是能够将一个单词与我们可能感兴趣的其他相关单词连接起来。

例如,如果我再做一个例子,试试“房子”这个词。我输入“房子”,看看我能得到什么,好的,房子是一种建筑,房子在某种程度上与家庭单位相关。因此,你可能想象出这些不同的关联方式。

这是一个建筑和居住地,研究人员已经整理了这些不同单词之间的关系,以说明。

比如说,房子是一种建筑,房子是一种居住地。但这种方法虽然在能够将单词关联起来时非常有帮助,但随着语言的变化以及各种变化的思考,它并不特别适用。

单词之间可能存在的不同关系。这一单词表示的挑战最终变得困难,但我们所做的就是定义一个单词,就像一句话那样,解释这个单词的意思。但我们真正希望以某种方式表示一个单词的意义。

我们希望我们的人工智能能够以某种方式,随时利用这些信息做有用的事情。我们希望我们的人工智能能够看懂文本,并真正理解这些文本的含义,将文本和单词与相似的单词关联起来,并理解单词之间的关系,我们希望有某种方式让计算机能够表示。

我们在整个课程中多次看到的信息是,当我们希望我们的人工智能表示某些东西时,使用数字来表示可能是有帮助的。我们看到,我们可以将游戏中的效用(如胜利、失败或平局)表示为数字1。

负数、一、二、零,我们已经看到了其他方式,可以将数据转换为特征向量,其中我们有一堆数字表示某些特定的数据。如果我们想将单词输入到神经网络中,例如能够给定一些描述房子的内容。

将这个句子翻译成另一个句子,或者能够用神经网络对单个词进行有趣的分类,我们需要某种词的表示,仅仅是通过向量的方式来表示两个词。我们该如何做到呢?我们如何将词转换成向量?

我们可以用来表示这些词含义的一种方法是,如果我有四个词,我想编码“他写了一本书”。我可以说,让“他”是这个向量1 0 0 0,写是0 1 0 0,而“书”则是0 0 0 1。实际上,我所拥有的就是这样的表示。

这被称为独热表示独热编码,它是一种含义表示,其中的含义。

这是一个只在一个位置有1,其他位置全是0的向量。1的位置告诉我这个词的含义,在第一个位置的1意味着“他”,在第二个位置的1意味着“写”,字典中的每个词都会被分配一个这样的表示。

只需在向量中分配一个位置,那个位置对这个词为1,其他词为0。现在我有了不同词的表示,这就是所谓的独热表示。那么,这种方法有什么缺点呢?为什么这并不一定是一个好的方法呢?

我只创建了足够的向量来表示字典中的四个词。如果你想象一个包含50,000个词的字典,我可能想表示的这些向量会变得异常庞大,这些是50,000维的向量,用来表示50,000个词的词汇。

后面的“写”有一大堆零,这不是一个特别易于处理的方式,如果我必须处理长度为50,000的向量。另一个问题是,我希望这些向量在某种程度上能够表示它们之间的含义。

如果我有句子“他写了一本书”和“他创作了一部小说”,我可以从中提取有用的信息。这里“写”和“创作”将是两个完全不同的向量,而“书”和“小说”在我的向量空间中也会是两个完全不同的向量,它们之间没有任何关系。

这两个词只是位于不同的位置,而我真正希望的是“写”和“创作”有相似的向量表示,“书”和“小说”的向量表示也应该相似,因为它们是含义相关的词。

理想情况下,我希望当我将它们放入向量形式并用向量来表示含义时,这些向量彼此之间也应相似。因此,与其使用这种独热表示,即通过给一个词一个在某个位置为1的向量来表示其含义,

在特定位置,我们将要做的事情是一个有点奇怪的事情,第一次看到时会觉得陌生,这就是我们要称之为的分布式表示,我们将用一大堆不同的值来表示一个词的意义,而不仅仅是一个值和其余的零。

一大堆数值,比如他写了一本书,可能是一个大的向量,也许有50维,也许有100维,但肯定不会是数万维,每个值都是一个数字。写了一本书的想法是用这些。

向量表示,我希望“写作”和“作者”这两个词的向量表示非常接近,它们之间的距离不会太远,书和小说的向量表示也是如此。因此,这将是许多统计机器学习的目标。

自然语言处理的方法就是使用这些词的向量表示,但我们究竟该如何定义一个词呢?它就像是一串串数字,那么谈论一个词的意义到底是什么意思呢?对此,著名的。

回答这个问题的引用来自20世纪50年代的英国语言学家J.R. Firth,他说:“你将通过……了解一个词。”

你可以通过与之相伴的词来了解一个词的意义,我们的意思是,定义一个词的方式就是根据那些出现在它周围的词来确定这个词的意义,如果我有这样一个句子。

他吃什么的空白处需要填的词。

你可能想象,在英语中,填补空白的词可能是像早餐、午餐或晚餐这样的词,这些就是填入那个空白的词。因此,如果我们想定义午餐或晚餐的意义,可以通过它们周围出现的词来定义。

如果一个词在特定上下文中出现,而另一个词恰好在非常相似的上下文中出现,那么这两个词就有关系。

它们可能彼此相关,可能具有相似的意义,这就是。

一个被称为“词向量”的算法的基础思想是生成词向量的模型,你给“词向量”一个文档语料库,也就是一大堆文本,而“词向量”将为每个词生成向量,有多种方法可以做到这一点,一种常见的方法是。

通过被称为Skip-gram架构的方法,该架构基本上使用神经网络预测上下文单词,给定一个目标单词,因此,给定一个单词,如“午餐”,使用神经网络尝试预测给定单词“午餐”周围将出现哪些单词,这就是我们可能表示的方式。

对于这样一个大型神经网络,我们为每个单词设置一个输入单元,每个单词在这个神经网络中都有一个节点,目标是使用这个节点网络来预测给定目标单词的上下文单词,比如“午餐”,我能否预测其他单词出现的概率。

比如说在上下文中相隔一个单词或两个单词的情况,如果你给AI这个神经网络大量的单词数据,以及单词在上下文中出现的情况,你可以训练一个神经网络来进行这个计算,能够预测给定的目标单词。

我能否预测那些上下文单词最终应该是什么,并且将使用我们所讨论的相同方法,从上下文单词反向传播误差通过这个神经网络,得到的结果是如果我们只使用一个单层的隐藏节点。

每个单词,我得到的,比如说从这个单词,我得到五条边,每条边都有一个权重对应于这五个隐藏节点,换句话说,我得到了五个数字,然后有效地表示这个特定的目标单词,以及我在这里选择的隐藏节点数量。

在这里的中间层,我可以选择可能有50个隐藏节点或100个隐藏节点,然后对于每个目标单词,我将有50个不同的值或100个不同的值,这些值我们可以有效地视为该单词的新向量表示。

这里的基本思想是,如果两个单词相似,它们在相似的上下文中出现。换句话说,使用这些相同的目标单词,我想预测相似的上下文,那么这些向量中的值我选择的这些向量,这些边的权重的数值可能。

因为对于出现在相似上下文中的两个不同单词,我希望计算出的这些值最终非常相似,因此,最终你可以高层次地想象,这个单词的Tyvek训练方法将会做什么。

给定一堆单词,最初我们随机初始化这些权重,选择随机权重,随着训练神经网络,我们会调整这些权重,调整每个单词的向量表示,使得在某种上下文窗口中,逐渐出现的单词。

相似的上下文彼此靠近,而在不同上下文中出现的单词则相距较远。

我希望能得到像breakfastlunchdinner这样的词的向量表示,它们彼此相似,而像bookmemoirnovel这样的词也是彼此相似的。因此,使用这个算法,我们能够处理一组数据并进行训练。

我们训练这台计算机,训练这个神经网络,以便找出哪些向量、哪些数字序列将代表这些单词。这是一个有点奇怪的概念,想象一个单词仅用一堆数字表示,但我们马上就会看到它的强大之处。

这真的很有趣,所以我们继续进入vectors,我将打开vectors.py,现在我打开的是words.txt,这是一个预训练模型,我已经运行过Word2Vec,它已经为每个可能的单词给了我一堆向量,我只想取50个。

我们将它们保存到一个名为words的字典中,然后我还定义了一些函数,比如distanceclosest words,这些函数将告诉我某个特定单词的最接近单词,以及closest word函数,它只会给我一个最接近的单词。

例如,现在让我尝试做这件事,让我打开Python解释器并说点什么。像是从vectors中导入star,也就是从vectors中导入所有内容,现在让我们看看一些单词的含义,比如city这个词。

city这个词,这些数字究竟代表什么并不重要,但这就是我的计算机如何表示city这个词的含义。然后是像house这样的不同单词,这里是house的向量表示,仅仅是一堆数字。

这在某种程度上编码了house这个词的含义。那我如何获取这个想法呢?一种衡量其优劣的方法是查看不同单词之间的距离。在向量上下文中,定义距离的方式有很多种,常见的方式是使用。

被称为余弦距离,它与测量向量之间的角度有关。简而言之,它只是测量这两个向量之间的距离。所以如果我取一个词,比如book,它与自己之间的距离有多远?bookbook的距离是多少?

这就是零,book这个词与它自己之间的距离为零。但我们来看看book这个词与像breakfast这样的词有多远。我们可以说,一个是很远的,零是很近的。好吧,bookbreakfast的距离大约是0.64,似乎相距很远,但现在让我们尝试。

计算单词之间的距离,比如“书”和“小说”这两个词,例如这两个词彼此更接近,点三四,单词“书”的向量表示比“早餐”的向量表示更接近单词“小说”的向量表示。

我可以做同样的事情,比如比较“早餐”和“午餐”,例如这两个词更加接近,它们之间有更加相似的关系。所以现在看起来我们有一些表示单词的方式,使用向量来表示一个单词,使我们能够。

能够说出像是相似的单词,最终在它们之间会有一个小距离,而这证明了在代表单词的意义时,可以用它们与其他单词的关系来表示,这是非常强大的,我也可以给你展示,我有一个函数。

叫做“最近单词”,基本上只需获取一堆单词并获取与其最接近的单词,所以让我获取最接近的单词,比如“书”,例如,也许我获取大约十个最近的单词,我们将自己限制为十个,而单词“书”显然与它自己最接近。

还与像“书”和“论文”、“回忆录”、“论文”、“中篇小说”、“选集”等密切相关。为什么这些单词我能够让计算机接近呢?因为基于这个算法训练的语料库,向量就像玫瑰一样,基于在类似上下文中出现的单词。

单词“书”在类似的上下文中出现,类似的其他单词也类似于“回忆录”和“论文”,例如,如果我做一些事情,比如获取与“城市”最接近的单词,你最终会得到“城市”、“镇”、“乡镇”、“村庄”,这些单词恰好出现在与“城市”相似的上下文中。

现在有趣的是,因为这些是向量,我们可以对它们进行数学运算。我们可以计算不同单词之间的关系,所以我可以。

比如说,好吧,如果我有“男人”和“国王”,这两个是不同的向量,而这是一个著名的。

例子来自单词“Tyvek”,你知道,我可以将这两个向量相减,这里这条线,这里的距离又是另一个。

表示像“国王 - 男人”的向量,现在从一个单词中减去另一个单词,这在向量的世界里通常是没有意义的,不过你可以取某个向量,某个数字序列来进行减法。

其他数字序列并获得新的向量,得到新的数字序列,而这个新的数字序列实际上将告诉我,从“男人”到“国王”需要做什么,这两个单词之间的关系是什么,而这就是某种向量。

描述了如何从“男人”到“国王”,然后我们可以再取。

这个值并将其添加到另一个向量中,你可能会想象,“女人”这个词例如,是在这个空间的某个地方存在的另一个向量,如果我采取这个相同的思路“国王 - 男人”,然后添加“女人”,我们会发现什么。

这里有一个有趣的问题,我们可以很容易地回答,因为我拥有所有这些事物的向量表示。我可以说,让我们回去看看“男人”这个词的表示。这里是“男人”的向量表示,让我们看看它的表示。

“国王”这个词的表示,这里是“国王”的表示,我可以将这些从“国王”减去“男人”,进入这个数组,很多值,所以“国王 - 男人”现在在某种数值向量格式中表示了“国王”和“男人”之间的关系。那么,如果我添加“女人”到这个值,比如说,是什么将我们从。

“男人”到“国王”,继续应用同样的向量到“女人”的向量表示,这给了我们这个向量,现在出于好奇,让我们取这个表达,找出与这个表达最接近的单词,惊人的是我们得到的是。

我们得到的“女王”这个词,似乎在你测量“男人”和“国王”之间的不同距离时,这个数字表示了“男人”与“国王”的关系。

将“国王”和“男人”的相同概念添加到单词的向量表示中。“女人”得到的结果是,我们得到了接近于单词“女王”的向量表示,因为这种距离以某种方式编码了这两个单词之间的关系,当你通过这个算法运行时。

它并不是被编程来做这个,但如果你试着找出如何根据上下文词来预测单词,你会得到能够基于所提供信息生成类似SAT类比的向量,这里有更多的例子,我们可以说,好吧,让我们找出。

巴黎和法国之间的距离是什么,所以巴黎和法国是单词,各自都有向量表示,那么这是巴黎和法国之间的距离的向量表示,像是从法国到巴黎的距离。让我继续将“英国”的向量表示添加到这里。

因此,这是巴黎 - 法国加上英格兰的向量表示,朋友和巴黎之间的距离作为向量,添加英格兰向量,让我们找到最接近的词,结果是伦敦。你进行这种关系。

法国和巴黎,继续添加英格兰向量,最接近的向量是伦敦的向量,我们可以进行更多的例子。我可以说,让我们取“教师”的向量表示,并减去“学校”的向量表示,那么。

我们所剩下的是,从“学校”到“教师”的关系,并将该向量应用于“医院”这个词,看看最接近的词是什么,结果发现最接近的词是“护士”。让我们再试几个例子,比如“拉面”的最接近词,减去与日本的最接近词。

日本和拉面之间的关系,添加“美国”这个词,猜测一下结果是什么,结果是你得到了“卷饼”作为关系,如果你进行减法和加法,这就是答案!

结果会引出非常有趣的类比,这些类比存在于这两个词之间。如果你将所有这些词映射到一个向量空间,你可以得到一些相当有趣的结果,这种表示词的想法。

将词作为向量来处理是极其有用和强大的,尤其是当我们想进行与自然语言相关的统计工作时,可以不仅仅将词表示为其字符,而是将其表示为数字,这些数字能够传达某种意义。

单词本身与其他单词之间的关系以某种方式关联起来,这些工具使我们能够在自然语言这个领域中工作,处理语言的句法和语义很棘手,但我们确实。

这只是一些基本思想的开始,这些思想支撑着许多自然语言处理的能力,比如从文本中提取信息,从中获取某种意义,生成句子,可能通过了解语法,或者仅仅通过观察。

基于其他先前出现的单词,计算哪些单词可能会出现的概率,最后能够将词转化为某种分布式表示,将词表示为数字,并利用这些数字传达某种信息。

对这些词汇的意义也是如此,因此这是在人工智能这个更广泛主题下的另一个话题。回顾一下我们所经历的,我们开始我们的讨论时谈论的是搜索世界,尝试解决问题。

类似于井字棋,通过寻找解决方案,探索我们各种不同的可能性,并查看我们可以应用哪些算法,以有效地尝试搜索空间。我们研究了一些简单的算法,然后研究了我们可以对这些算法进行的优化。

最终,这些都服务于让我们的AI了解世界的尝试,这也是我们今天讨论的很多内容,试图从文本信息中提取知识,具备从中提取信息的能力。

根据这些信息得出结论,如果我知道这两个。

也许我可以得出第三个结论,那就是与不确定性相关的词汇。如果我们对某事没有确切的了解,我们能否预测某事,并找出某事的概率?今天我们再次看到这一点,试图预测一条推文或。

无论消息是积极情绪还是消极情绪,试图得出这样的结论。然后我们研究了优化,寻找局部的。

全局或局部最大值或最小值,这一点一次又一次地出现。尤其是在最近的神经网络背景下,神经网络实际上是一种优化问题,我们试图最小化基于我们神经网络权重设置的总损失。

基于我们所选择的词汇向量表示,这最终帮助我们能够解决与学习相关的问题,具备从大量数据中提取模式的能力,而不是告诉AI该做什么,让AI从数据中学习。

让它自己去发现什么使收件箱消息与垃圾邮件不同,让它找出伪钞与真钞之间的区别,并能够进行这样的分析。我们使用的一个重要工具是神经网络,这些结构使我们能够关联事物。

通过训练这些神经网络将输入转化为输出,以学习某种函数,将我们从某个输入映射到某个输出,最终形成另一种人工智能语言模型,以便与我们的AI进行沟通。最后,今天我们探讨了一些AI可以使用的方法。

开始与我们沟通,探索人工智能如何开始理解语言的语法和语义,以便能够生成句子,预测关于书面或口头语言(如英语)所写文本的内容,并能够做到这一点。

这里有一个有趣的分析,同时在积极研究中还有更多的内容,这些研究正在人工智能的各个领域进行。我们实际上只见到了人工智能所能提供的开始,所以我希望你喜欢这次探索人工智能的世界。

非常感谢Python课程的教学人员和制作团队,让这门课成为可能,这是一段介绍。

哈佛CS50-AI | Python人工智能入门(2020·完整版) - P3:L0- 搜索算法 2 (广度优先搜索,贪心搜索,A*算法) - ShowMeAI - BV1AQ4y1y7wy

另外,深度优先搜索只是我们可以使用的多种搜索选项之一,事实证明还有另一种算法叫做广度优先搜索,它的行为与深度优先搜索非常相似,只是一个区别是它不会总是探索搜索树中最深的节点,像深度优先搜索那样。

广度优先搜索总是会探索边界中最浅的节点,这意味着什么呢?这意味着我们不会像深度优先搜索那样使用栈,后者最近添加到边界的项目是我们下一个要探索的,而在广度优先搜索中。

我们会使用队列,队列是一种先进先出的数据类型,我们添加到边界的第一个项目将是我们首先要探索的,而它们有效地形成一条线或队列,越早到达边界的项目,越早被探索。我说这对相同的情况意味着什么。

精确的问题是找到从A到E的路径。

我们将从之前的情况开始,然后继续探索A,问从A我们可以到哪里,从A我们可以到B,跟之前一样。从B我们可以到C和D,因此C和D被添加到边界,但这次我们用D的方式将C添加到边界,因此我们会探索。

首先探索C,然后从C出发,我们可以到达E。所以E被添加到边界,但因为D在E之前已经被探索,我们接下来会看D。因此我们会探索D,问从D出发我们能到哪里,我们可以到F,然后我们才说,好吧,现在我们可以到E了,那么这又有什么呢?

广度优先搜索或BFS是这样开始的,我们在这里看C和D,然后我们看E。实际上,我们是在从初始状态向外看一层,然后是两层,只有在那之后才是离初始状态三层的东西,这与深度优先搜索不同,后者只是。

我们深入搜索树,直到遇到死胡同,然后最终不得不回退,因此现在有两种不同的搜索算法,我们可以应用它们来尝试解决一个问题,让我们看看这些在实践中是如何运作的,比如迷宫求解。

这是一个迷宫的示例,这些空单元格代表我们的代理可以移动的地方,而这些深色的灰色单元格代表代理无法通过的墙,最终我们的代理,我们的AI将尝试找到一种方法,从位置A通过一些动作序列到达位置B。

这些动作是左右上下,深度优先搜索会在这里做什么?

在这种情况下,深度优先搜索将只沿着一条路径前进,如果它到达一个岔路口,有多个不同的选项,深度优先搜索在这种情况下将选择其中一条,它并没有真正的偏好,但它将继续跟随这条路径,直到遇到死胡同,当它到达死胡同时。

深度优先搜索有效地回到最后的决策点,尝试另一条路径,完全耗尽这整条路径,当它意识到目标不在这里时,它将注意力转向这条路径,它会尽可能深入,当它遇到死胡同时,它会退回,然后尝试这条另一条路径,继续深入。

可能沿着某条特定路径向下,当它意识到这是个死胡同时,它会退回去,最终找到通向目标的道路,也许你运气不错,也许你之前做了不同的选择,但最终这就是深度优先搜索的工作方式,它会一直跟随直到结束。

它会退回并寻找不同的解决方案,因此你可能合理地问,这个算法是否总是会工作,是否总是能够找到从初始状态到目标的路径,结果是只要我们的迷宫是有限的,只要方块数量是有限的。

如果我们可以在可以移动的空间中,那么是的,深度优先搜索将找到解决方案,因为最终它将探索一切,如果迷宫恰好是无限的,并且存在无限状态空间,在某些类型的问题中确实存在,那么情况会稍微不同,但只要我们的迷宫。

我们有有限的方块,我们将要找到一个解决方案,但下一个问题是,是否会是一个好的解决方案,是我们能找到的最优解,答案并不一定,让我们看一下这个迷宫的例子,我们又在试图找到从。

从A到B,你会注意到这里有多个可能的解决方案,我们可以沿这条路走,或者向上走以从A到B,现在如果我们运气好,深度优先搜索会选择这条路,顺利到达B,但并没有理由说明深度优先搜索会选择上走还是。

向右移动这是一种任意的决策点,因为两者都会被添加到边界,最终如果我们运气不好,深度优先搜索可能会选择先探索这条路径,因为此时它只是一个随机选择,它会不断探索。

最终找到目标的这条特定路径,其实是有更好的路径存在,存在一个更优的解决方案,使用更少的步骤假设!

我们根据需要采取的步骤数量来衡量解决方案的成本,因此深度优先搜索如果。

如果我们运气不好,可能最终找不到最佳解决方案,而更好的解决方案。

是可用的,所以如果这是深度优先搜索(DFS),那么。

广度优先搜索(BFS)如何比较,在这个特定的情况下它将如何工作,算法在视觉上将会有很大的不同,因为BFS首先查看较浅的节点,想法是BFS将首先查看离初始节点一步远的所有节点。

状态查看这里和这里,例如就像是这两个节点。紧挨着这个初始状态,那么它将探索离这个状态两步远的节点,查看这个状态和那个状态,例如,然后它将探索离这个状态三步远的节点,而深度优先搜索(DFS)。

只选择了一条路径并继续,另一方面,广度优先搜索则选择了探索所有可能的路径。几乎同时在它们之间反弹,深入探索每一条路径,但确保探索较浅的路径或较近的路径。

更接近初始状态,所以我们将继续遵循这个模式,查看远处的事物,查看五步远的事物,查看六步远的事物,直到最终到达目标,在这种情况下,确实我们必须探索一些最终。

没有带我们到任何地方,但我们找到的通往目标的路径是最优路径,这是我们到达目标的最短方式,因此。

在更大的迷宫中可能发生什么,嗯,让我们看看这样的情况,广度优先搜索将如何表现,广度优先搜索再次会继续跟随状态,直到它收到一个决策点,它可以向左或向右,而深度优先搜索则选择一个并继续。

一直跟随直到它遇到死胡同,另一方面,BFS将探索两个节点,它会查看这个节点,然后这个节点,并查看这个节点,然后那个节点,依此类推,当它在这里遇到一个决策点时,而不是选择左边一个或右边两个并探索那条路径,它将再次探索两个。

交替在它们之间,越来越深入,我们将在这里探索,然后也许在这里和这里,然后继续前进,慢慢探索这里,你可以在视觉上看到越来越远,一旦我们到达这个决策点,我们将向上和向下探索,直到最终我们到达,并且你会注意到是的。

广度优先搜索(BFS)确实找到了我们的路径,从A到B,遵循这个特定的路径,但它需要探索许多状态才能做到这一点,因此我们看到DFS和BFS之间有一些权衡,在DFS中,可能有些情况下与广度优先方法相比会节省内存。

在这种情况下,广度优先搜索必须探索很多状态,但这可能并不总是这样,所以现在,让我们实际上将注意力转向一些代码,看看我们可以实际编写的代码,以实现深度优先搜索或广度优先搜索。

解决迷宫的上下文,例如,所以我将前往我的终端,而我在迷宫管道内部拥有的是相同的迷宫求解思想的实现,我定义了一个名为节点的类,在这种情况下,它跟踪状态、父状态,换句话说,状态之前的状态和。

在这种情况下,我们没有跟踪路径成本,因为我们可以在找到从初始状态到目标的路径后计算路径成本。此外,我定义了一个名为栈的类前沿,如果不熟悉类,类是我定义一种方式的方式。

在Python中生成对象,它指的是面向对象编程的理念,这里的想法是我想创建一个能够存储我所有前沿数据的对象,我希望在该对象上有可以用来操纵的函数,通常称为方法。

对象中的方法,所以如果你对语法不熟悉,这里发生的事情是我有一个函数,最初创建一个前沿,我将使用列表来表示,最初我的前沿用空列表表示,开始时前沿中没有任何东西,我有一个添加函数可以添加某物。

通过将其附加到列表的末尾,我有一个函数。该函数检查前沿是否包含特定状态,我有一个空的,如果前沿为空,那就意味着,前沿的长度为0,然后。我有一个从前沿中移除某物的函数,我不能从前沿中移除。

如果前沿为空,我不能从前沿中移除某物,所以我首先检查这一点。但是如果前沿不为空,请记住,我将前沿实现为一个栈,即后进先出数据结构,这意味着我最后添加到前沿的。

我应该从这个前沿中移除的项目,所以你会看到我已移除列表的最后一个项目,如果你用负一索引Python列表,这会得到列表中的最后一个项目,因为零是第一个项目,负一则可以循环到列表的最后一个项目。

我们给该节点,我们称其为节点,我们在第28行更新前沿,以说继续移除你刚刚从前沿中移除的节点,然后我们将节点作为结果返回,所以这个类实际上实现了前沿的理念,它给了我一种将某物添加到一个。

前沿和从前沿中移除某物的方法是栈,我还为好措施实现了同一事物的替代版本,称为队列前沿,括号中你会看到它继承自栈前沿,意味着它将执行栈所做的所有操作。

前沿是这样的,除了我们从前沿移除节点的方式会稍微不同,我们将从列表的开头移除,而不是从栈中通常从末尾移除。self.frontier[0]将为我获取前沿中的第一个节点。

被添加的那个将是我们在队列中的返回项。接下来,我有一个名为Mae ism的类定义。这将处理获取一个序列,类似迷宫的文本文件并找出如何解决它,因此它将以文本文件作为输入。

例如,结果看起来像这样,其中我们看到代表墙壁的哈希标记。我有字符A表示起始位置,字符B表示结束位置,你可以查看解析这个文本文件的代码。现在这部分不太有趣,更有趣的是。

这一部分是解决函数,这个函数将弄清楚如何从点A到点B。在这里,我们看到的实现与刚才看到的完全相同,我们将跟踪探索的状态数量,以便稍后报告这些数据。

从表示起始状态的节点开始,我以栈前沿开始。在这种情况下,考虑到我将前沿视为栈,你可能想象我在这里使用的算法是深度优先搜索,因为深度优先搜索或DFS使用栈作为其数据。

结构,最初这个前沿将仅包含起始状态。我们初始化一个探索集合,最初为空,我们还没有探索过任何东西,现在这是我们的循环,重复某事的概念。

我们看到的功能的实现,如果前沿确实为空,我们将抛出一个异常或Python错误,表示抱歉,这个问题没有解决方案。否则,我们将继续从前沿移除一个节点,通过调用frontier.remove()来更新状态。

我们探索的状态数量,因为现在我们探索了一个额外的状态。所以我们说self.numb_explored += 1,将1添加到我们探索的状态数量中。一旦我们从前沿移除一个节点,请记住,下一步是检查它是否是目标,进行目标测试,在迷宫的情况下。

检查目标是相对简单的。我会查看节点的状态是否等于目标。在我设置迷宫时,我设定了一个叫做目标的值,这是迷宫的一个属性,因此我可以检查节点是否实际是目标。

我逐步搞清楚为了达到这个目标我采取了什么行动。如何做到这一点呢?回想一下,每个节点存储它的父节点,即到达此节点所经过的节点,以及为此使用的动作。因此,我可以创建一个循环,持续查看。

查看每个节点的父节点,并记录所有父节点之间的动作,以便从父节点到当前节点。因此,这个循环将持续查找所有父节点,直到我们回到初始状态,其父节点node dot parent等于None。

在这个过程中,我将构建出我所遵循的所有动作的列表,以及所有属于这个解决方案的单元格的列表,但我会反转它们,因为我是在从目标返回到初始状态时构建动作序列。

从目标到初始状态,但我想反转它们以获得从初始状态到目标的动作序列,这最终将是解决方案。因此,所有这些发生在当前状态等于目标时,否则如果它不是目标。

我将这个状态添加到已探索集合中,表示我已经探索了这个状态,未来如果再遇到就不需要再回去,然后这段逻辑实现了将邻居添加到边界的想法。我会查看我的所有邻居,并实现一个叫做邻居的函数。

请查看每一个邻居,我会检查这个状态是否已经在边界内,或者是否已经在已探索集合中。如果不在这两个集合中,我将添加这个新子节点到边界中,因此这里有相当多的语法,但关键是。

这里的重点不是要理解所有内容。

语法的细微差别,所以请随意仔细查看这个文件,了解它的工作原理。但关键是看到这是同样伪代码的实现,正如我们在屏幕上描述的那样,当时我们查看了可能的步骤。

为了解决这种搜索问题,我们现在来看看实际操作。我将运行maze spy on maze one dot text作为示例,下面是迷宫最初的打印输出,之后是解决后的结果。

探索了11个状态才能做到这一点,我们找到了一条从A到B的路径,而在这个程序中我刚好生成了。

好的,所以我可以打开由这个程序生成的 maze dot PNG,它向你展示了。黑暗中的位置,较深的颜色是墙,红色是初始状态,绿色是目标,黄色是经过的路径,我们找到了一条从。

初始状态到目标,但现在让我们看看一个更复杂的迷宫。看看可能会发生什么,接下来我们看 maze to dot text,我们现在。这里有一个更大的迷宫,从A到B,但现在你会想象深度优先搜索可能不会那么幸运,可能不会在第一次就找到目标。

尝试一下,你可能需要沿着一条路径,然后回溯并探索其他东西。

这个,我们运行Python maze da pie of maze two,文本这次尝试另一个迷宫,现在深度优先搜索能够在这里找到解决方案,如所示。

星星是一种从A到B的方式,我们可以通过打开这个迷宫以视觉方式表示。这个迷宫看起来是这样的,黄色高亮的是从初始状态到目标找到的路径,但我们必须探索多少个状态才能找到这条路径呢?回想一下在。

我的程序一直在跟踪这个。

到目前为止,我们探索的状态数量,所以我可以回到终端,看看,好的,为了解决这个问题,我们必须探索399个状态。

不同的状态,事实上,如果我对程序做一个小的修改,并告诉程序在最后当我们输出这个图像时,我添加了一个参数。

称为 show explored,如果我将 show explored 设置为 true 并重新运行这个。

程序Python可能停止运行在 maze 2 上,然后我打开迷宫,结果是。

你会看到这里用红色高亮的是所有必须探索的状态,以便从初始状态到达目标,深度优先搜索(DFS)。没有立即找到目标,它选择首先探索这个方向,当它探索这个方向时,它必须遵循每一个。

所有可能的路径一直到最后,甚至这个长而曲折的路径。为了意识到,你知道,这是死胡同,程序需要在走这个方向后回溯,它一定是走了这个方向,幸运的是没有选择这条路径,但也不幸地。

这里探索了这个方向,探索了一堆不必要的状态,接着又探索了图的上半部分,实际上也没有必要这样做。因此,总的来说,深度优先搜索并没有表现得很理想,可能探索了更多的状态。

找到一个最优解决方案是通往目标的最佳路径,但为此需要探索的状态数量,以及我必须采取的步骤数量,都要高得多。所以让我们比较一下,如果宽度优先搜索(BFS)在这个完全相同的迷宫中会怎么做。

DFS和BFS的算法是相同的,唯一的区别是我们用什么数据结构来表示前沿。在DFS中,我使用的是后进先出(LIFO)的栈作为前沿,而在BFS中,我使用的是先进先出(FIFO)的队列,首先加入前沿的就是第一个被探索的。

删除这些后,我将返回终端,在同一个迷宫上重新运行这个程序,现在你会看到我们需要探索的状态数量只有77……。

相比之下,当我们使用深度优先搜索时,几乎有400个状态,而我们可以看到……。

这就是我们可以看到,如果我们打开maze.png,重新查看时,黄色高亮部分是宽度优先搜索找到的解决方案,巧合的是,它也是深度优先搜索找到的解决方案。它们都找到了最佳解决方案,但注意所有未探索的白色单元格。

为了到达金子,所需探索的状态大大减少,因为宽度优先搜索(BFS)操作得较为浅显,它在探索离初始状态较近的东西,而不去探索更远的东西。所以如果目标不太远,那么宽度优先搜索……。

搜索实际上可以非常有效地在一个迷宫中进行,就像这样。在这个例子中,BFS和DFS最终找到了相同的解决方案,但这并不总是如此。实际上,让我们再看一个例子,例如迷宫3。

在迷宫3中,你可以从A到B有多种方式,这是一个相对较小的迷宫,但让我们看看如果我使用……。

关闭显示已探索状态,这样我们只看到解决方案。如果我使用BFS来解决迷宫3……。

然后我们找到一个解决方案,如果我打开迷宫,这里就是我们找到的解决方案,它是最优的,只需四步就能从初始状态到达目标。但如果我们尝试……。

使用深度优先搜索或DFS,然而我会再次回到我的队列边界,队列边界意味着我们正在使用广度优先搜索。

我会把它改为栈边界,这意味着现在我们将使用深度优先搜索,我会重新运行Python,也许我会,现在你会看到我们。

找到了解决方案,但这并不是最优解决方案,这反而是我们的算法所找到的,也许深度优先搜索能找到解决方案,这有可能,但并不保证如果我们正好选择了这个状态,而不是那个状态,那么深度优先搜索就会这样。

搜索可能找到一条更长的路径,从初始状态到目标,所以我们在这里看到一些权衡,深度优先搜索可能找不到最优解决方案,因此到那个时候,看起来广度优先搜索是相当不错的,这是否是我们能做的最好的选择,它将找到最优解。

解决方案,我们不必担心可能会找到一条比实际存在的解决方案更长的路径的情况,目标距离初始状态很远,我们可能需要走很多步才能到达。

为了从初始状态到达目标,最后发生的事情是这个算法广度优先搜索基本上探索了整个图,必须通过整个迷宫才能找到从初始状态到目标状态的路径。

我们最终希望的是我们的算法更智能,那么在这种情况下,什么是使我们的算法更智能呢?让我们回顾一下广度优先搜索可能能够做出不同决策的地方,并考虑人类直觉。

这个过程就像人类在解决迷宫时可能做的那样,这与广度优先搜索最终选择的方式不同,广度优先搜索的第一个决策点正是在这里,它进行了五步,最后到达了一个分岔路口,可以选择左转或右转。

在这最初的几步中没有选择,每个状态只能采取一个动作,因此搜索算法做了唯一能做的事情,就是继续跟随那个状态直到下一个状态,但这一点是事情变得有些不同的时候。

有趣的是,深度优先搜索这个我们看到的第一种搜索算法选择了一条路径并穷尽那条路径,看看那条路上是否有目标,如果没有,那么就尝试另一条路。广度优先搜索,你知道的,让我们先探索那些浅层的、靠近我们的东西,先看看左右。

然后左转再右转,交替我们的选择,希望能找到附近的东西,但最终使人类陷入困境的原因是当面临这样的选择:往左还是往。

对于人类来说,视觉上可能会看到,我正试图到达B状态,B在那里,往右走似乎更接近目标,感觉上往右走应该比往左走更好,因为我正在朝目标迈进。

当然,为了达到这个目标,我在这里做了一些假设,我假设我们可以将这个网格表示为一个二维网格,我知道所有的坐标,我知道A在坐标(0, 0),B在其他坐标对上。

我可以计算出是的,往这个方向走更接近目标,这可能是某些类型搜索问题的合理假设,但在其他情况下可能不是。不过,现在我们假设我知道我当前的坐标对。

我希望在这种情况下有一个稍微更聪明的算法,它能够知道我应该朝目标前进。这可能是这样做的方式,因为在迷宫中,沿坐标方向移动。

目标通常,虽然并不总是,是一个好事,所以在这里我们区分两种不同类型的搜索算法:无信息搜索和有信息搜索。无信息搜索算法是像DFS和BFS这样的算法,这两种算法都是我们刚刚看到的搜索策略。

不使用任何特定于问题的知识来解决问题,DFS和BFS并不在意迷宫的结构或迷宫的任何情况。它们只是查看可用的动作,并从这些动作中选择,而不管当前位置。

无论是迷宫还是其他问题,解决方案或它试图解决问题的方法在根本上都是相同的。我们现在要看看的是对无信息搜索的改进,我们将看看有信息搜索。有信息搜索将是搜索策略。

利用特定于问题的知识来更好地找到解决方案,在迷宫这个问题中,特定知识是如果我在一个地理上更靠近目标的方格中,这比在一个地理上更远的方格中要好。

只能通过思考这个问题并推理出对我们的 AI 代理有帮助的知识来了解。不同类型的知情搜索中,首先我们将关注一种叫做贪婪的搜索算法。

最佳优先搜索贪婪最佳优先搜索,通常缩写为 G BFS,是一种搜索算法,它不会像深度优先搜索那样扩展最深的节点,也不会像广度优先搜索那样扩展最浅的节点,而是始终扩展它认为离目标最近的节点。

我们无法确定它是否是离目标最近的,因为如果我们知道什么是最接近目标的,那我们早就有解决方案了。如果我们了解什么接近目标,我们只需按照这些步骤从初始位置到达解决方案,但如果……

我们不知道解决方案的意思,也就是说,我们并不确切知道什么是最接近目标的。相反,我们可以使用一种估算方法,称为启发式,就是估计我们是否接近目标。

我们将使用一个常规称为 H(n) 的启发式函数,它接受状态输入并返回我们与目标的接近程度的估算。那么,在解决迷宫算法的情况下,这个启发式函数是什么样子的呢?

启发式函数需要回答一个问题:在这两个单元 C 和 D 之间,哪个更好?如果我试图找到到目标的路,我宁愿在什么地方。任何人类可能都能看出 D 看起来更好,即使迷宫很……

复杂的问题,如果你没有考虑到所有的墙,D 可能会更好。

为什么更好呢?因为如果你忽略墙壁,假装墙壁暂时不存在,放松一下问题,那么 D 就在坐标对的意义上更接近这个目标,走的步骤更少。

相比于 C 到达目标需要采取的步骤,即使你忽略墙壁,只要你知道 C 的 XY 坐标和目标的 XY 坐标,同样也知道 D 的 XY 坐标,你可以地理上计算 D,忽略墙壁,看起来 D 更好,这就是……

我们将使用的启发式函数是曼哈顿距离,这是一种特定类型的启发式,其中启发式是垂直和水平方向上的方格数量,然后从左到右,所以不允许对角线移动,只能向上、向右、向左或向下。

我需要多少步才能从这些单元格到达目标。事实证明,D更近,只需要六步就能到达目标,这里忽略墙壁,我们稍微放宽了问题,我们只关心数学运算。

要从每个X值中减去彼此,再从每个Y值中减去彼此。我们估计我们离目标有多远,D比C更接近目标,所以现在我们有了一种选择要从前沿移除哪个节点的方法,在我们算法的每个阶段,我们都会进行。

从前沿移除一个节点时,我们将探索具有此启发式函数最小值的节点,如果它到目标的曼哈顿距离最小。那么,这实际上会是什么样子呢?让我先给这个图标标上标签,把这个迷宫标记为。

这个启发式函数的值。

从任何这些单元格的曼哈顿距离值来看。例如,从这个单元格,我们距离目标是1,从这个单元格,我们距离目标是2,3,4,而这里是5,因为我们需要向右走一步,然后从这里向上走四步,曼哈顿距离。

距离是2,实际上我们将不得不走更长的路径,但我们还不知道,启发式。

是一种简单的方法来估算我们离目标有多远,也许我们的启发式过于乐观,它认为我们只需两步,而实际上考虑到墙壁时可能需要更多步骤。因此,重要的是启发式并不能保证。

步骤的估计是一种尝试去逼近,通常情况下,看起来离目标更近的方格具有更小的启发式函数值,而远离目标的方格则更大。因此,使用贪心最佳优先搜索,这可能是什么呢?

算法表现得很好,对于这前五步,我们没有太多选择,我们从初始状态A开始,表示我们必须探索这五个状态,但现在我们有了一个决策点,我们可以选择向左或向右。

随便选择,因为这只是取决于你把这两个节点放入前沿的顺序,而我们没有指定你将它们放入前沿的顺序,只是取出它们的顺序。我们可以看看13和11,发现这个方格离目标的距离是11,根据我们的启发式。

根据我们的估计,这个估计我们认为距离目标是13。所以在这两个选项之间,我宁愿选择11。我宁愿距离目标有11步,所以我会向右走,我们能够做出明智的决定,因为我们对这个有更多了解。

所以这个问题是,我们继续跟随10、9、8,在两个7之间,我们没有太多方法来了解,所以我们必须做一个任意的选择,也许我们选择错了,但没关系,因为我们仍然可以说,好吧,让我们试试这个7,我们说7、6,我们必须做出这个选择。

尽管这增加了启发式函数的值,但现在我们在6和8之间有另一个决策点,而在这两个值之间,我们还在考虑13,但这在6、8和13之间要高得多。好吧,6是最小的值,所以我们更愿意选择6。

做出明智的决定,选择向右走可能比向下走要好。因此我们转向这条路,走到5,现在我们发现一个决策点,我们实际上可能不想做出这个决策,但不幸的是,在这里没有太多的选择,我们看到4和6,4。

看起来更接近目标,它在上升,而目标在更高的地方。所以我们最终选择了那条路线,尽管最终导致我们走进了死胡同,但没关系,因为我们仍然可以说,好吧,现在让我们试试6,然后跟随这条路线,最终带我们到达目标。

贪婪最佳优先搜索可能会通过说,每当我们在多个节点之间做决策时,让我们探索h(n)值最小的节点来接近这个问题。这个启发式函数是估算我需要走多远,而正好是这样。

在这种情况下,我们在需要探索的状态数量上做得更好,比起BFS所需的数量。BFS探索了整个这个区域和那个区域,但我们通过利用这个启发式,即关于我们离目标有多近的知识,能够消除那些。

这个想法的估计看起来好多了,所以我们难道不总是更倾向于使用这样的算法而不是广度优先搜索这样的算法吗?也许需要考虑的一件事是,我们需要提出一个好的启发式。启发式的好坏将影响这个算法的表现。

提出一个好的启发式方法往往是具有挑战性的,但另一个需要考虑的问题是,像我们之前两种算法一样,问这个算法是否最优,它是否总是能找到从初始状态到目标的最短路径。为了解答这个问题,我们来看看。

暂时看看这个例子。我们尝试从A到B,并且我已标注每个单元格与目标的曼哈顿距离,也就是你需要从该格到目标旅行的平方数。

想一想,贪婪最佳优先搜索总是选择最小数字,是否能找到最优解?什么是最短的解决方案?这个算法会找到吗?重要的是要意识到,在这里我们估计离目标有12步,我们有两个选择。

在左侧,我们估计离目标有13步,或者我们可以向上走,估计离目标有11步。在这两者之间,贪婪最佳优先搜索会说11看起来比13更好,因此贪婪最佳优先搜索最终会找到这条通往目标的路径。

结果是这条路径并不最优,有一种方法可以用更少的步骤到达目标,而实际上就是这条路,尽管此时选择了两个中我们估计为最差的选项。

这就是我们所说的贪婪算法,它在此决策点上做出了最佳决定。看起来在这里比去13更好,但从大局来看,这不一定是最优的。它可能会找到一个解决方案,而实际上还有更好的解决方案。

我们希望有一种解决这个问题的方法,我们喜欢这种能够估计我们与目标之间距离的启发式,这帮助我们做出更好的决策,消除搜索整个状态空间的需要。

我们希望修改算法,以实现最优性,使其能够是最优的。那么实现这一点的方法是什么?直觉是什么?让我们看看这个初始问题,贪婪最佳优先搜索给我们找到了这个长路径,原因在于它并不理想。

这是因为启发式数字下降得很低,但后来又开始回升,回升到8、9、10、11,直到12。那么我们该如何改进这个算法呢?我们可能意识到,如果我们一直走下去。

通过这条路径,最终我们走到12,花费了很多步,谁知道那有多少步,只是为了到达这个12。作为替代,我们可以选择只需六步,就能更快到达12,所以看起来不太好,但确实需要的步骤少得多。

为了到达这个13我花了六步,而到达这个12则需要更多的步骤。虽然贪婪的最佳优先搜索说哦,12比13更好,所以选择12,但我们可能会更智能地说,如果我能更快到达一个看似需要稍长时间的地方,我宁愿选择后者。

我们将把这个总体思路编码成一个更正式的算法,称为A搜索。A搜索将通过不仅考虑启发式,还考虑到达目标的时间来解决这个问题。

这是我到达任何特定状态所需的步数,因此区分在于贪婪的最佳优先搜索。如果我现在在一个状态中,我唯一关心的是我与目标之间的估计距离,即启发式值,而A*搜索将考虑两条信息。

考虑到我估计自己离目标有多远,同时也考虑我为了到达这里还需走多远,因为这与我们将要使用的搜索算法相关,它通过扩展具有最低G(n)+h(n)值的节点来进行。H(n)就是我们刚才提到的那个启发式。

这将根据问题而有所不同,但G(n)将是到达节点的成本,也就是在这种情况下到达我当前位置所需的步数。那么这个搜索算法在实际中看起来是什么样的呢?让我们再看一下,我们有相同的迷宫,我已经标记好了它们。

使用它们的曼哈顿距离,这个值是H(n)值,即对每个方格距离目标的启发式估计,但现在当我们开始探索状态时,我们不仅关心这个启发式值,还关心G(n),我到达那里所需的步数。

你知道,需要将这两个数字相加。那么在这第一步中,假设我已经走了一步,现在我估计距离目标还有16步。因此这里的总值是17。然后我再走一步,我现在走了两步,估计自己距离目标还有15步。

总值仍然是17,现在我已经走了三步,估计距离目标还有14步,依此类推,四步时估计为13,五步时估计为12,现在这是一个决策点,我可能距离目标六步,启发式值为13,总共为19。

或者我可能距离目标还有六步,启发式值为11,总估计为17。因此在19和17之间,我宁愿选择17,也就是6加11。到目前为止与之前没有什么不同,我们仍然选择这个选项,因为它看起来更好,我继续选择。

这个选项看起来更好,但在这里事情变得有点不同。我可能距离目标有十五步,估计距离为六,所以15加6,总值为21。或者我可能距离目标有六步,因为这是五步。

这里距离目标有六步,总值为十三,作为我的估计,所以六加十三是十九。在这里,我们会评估G(n)加H(n)为十九,六加十三,而这里是15加六或21,因此直觉上是19小于21,但最终的想法是我。

在减少步数的情况下,走到十三步比走到六步要好,因为这意味着我为了到达那里必须走更多的步数,可能有更好的路径。因此我们现在将探索这条路线,如果我们再走一步,这是七步加14是二十一。

在这两者之间,结果有点难以预测,我们可能会最终探索那个。不管怎样,随着这些数字在启发式中的增大,启发式值开始变小,你会发现实际上会继续沿着这条路径探索,你可以计算一下。

在每个决策点,A*搜索将基于我到达当前位置所需的步数之和,以及我估计离目标有多远来做出选择。因此我们必须探索一些状态,实际上找到的最佳解决方案是我们从中获取的最快方法。

从初始状态到目标,事实证明A*是一个在某些条件下的最佳搜索算法。这些条件是H(n),我的启发式需要是可接纳的。启发式可接纳意味着它永远不会高估真实成本H(n)。

总是需要在我离目标有多远上,要么精确到位,要么低估。所以我们之前看到的例子中,启发式值远小于实际成本,这是完全可以的,但启发式值绝不能高估,绝不能认为。

我离目标实际上更远,而与此同时,H(n)也需要一致性。那么在数学上,一致性意味着对于每个节点,我们称之为n+后继,即我之后的节点,我称之为n',在此步骤的成本为C。

n的启发式值需要小于或等于n'的启发式值加上成本,因此这有很多数学,但用言语来说,这最终意味着如果我现在在这个状态,离目标的启发式值不应该超过。

我接替者的启发式价值,接下来我可以去的地方,以及这将花费我多少。仅仅从一步迈向下一步,所以这只是确保我的启发式在我可能采取的所有步骤之间是一致的,只要这一点成立,那么A*搜索就是。

这将为我找到一个最优解决方案,这也是解决这些搜索问题的挑战所在。有时,A*搜索是一个已知算法,你可以相对容易地编写代码,但选择启发式可能是有趣的挑战,启发式越好。

启发式越好,我就能在更少的状态中解决问题。我需要确保启发式满足这些特定约束,所以总的来说,这些是一些可能有效的搜索算法,当然还有许多其他算法。

例如,A确实有使用大量内存的倾向。因此,存在替代方法,最终使用比此版本A更少的内存,还有其他搜索算法也针对其他情况进行了优化,但到目前为止我们只讨论了。

我一直在研究搜索算法,其中有一个代理,比如我正在尝试寻找一个问题的解决方案,我正在试图通过迷宫导航,我正在尝试解决15拼图,我正在尝试。

posted @ 2024-10-19 01:42  绝不原创的飞龙  阅读(59)  评论(0)    收藏  举报