本文概述
深度学习
到目前为止, 你可能已经知道机器学习, 这是计算机科学的一个分支, 研究可以学习的算法的设计。今天, 你将专注于深度学习, 它是机器学习的一个子领域, 它是一组受大脑结构和功能启发的算法。这些算法通常称为人工神经网络(ANN)。深度学习是数据科学领域最热门的领域之一, 许多案例研究在机器人技术, 图像识别和人工智能(AI)方面均取得了惊人的成果。
Keras是用于开发和评估深度学习模型的功能最强大且易于使用的Python库之一。它包装了高效的数值计算库Theano和TensorFlow。这样做的好处主要是可以轻松有趣地开始使用神经网络。
今天的Keras初学者教程将向你介绍Python深度学习的基础知识:
- 你将首先了解什么是人工神经网络。
- 然后, 本教程将逐步向你展示如何使用Python及其库来理解, 探索和可视化数据,
- 如何预处理数据:你将学习如何在训练和测试集中拆分数据, 以及如何标准化数据,
- 如何为分类任务建立多层感知器,
- 如何将数据编译并适合这些模型,
- 如何使用模型预测目标值, 以及
- 如何验证你建立的模型。
- 最后, 你还将看到如何为回归任务建立模型, 并且将学习如何微调已建立的模型。
你想参加有关Keras和Python深度学习的课程吗?考虑参加srcmini的Python深度学习课程!
另外, 请不要错过我们的Keras备忘单, 它通过代码示例向你展示了在Python中构建神经网络所需要完成的六个步骤!
人工神经网络介绍
在深入了解Keras以及如何使用它来开始使用Python进行深度学习之前, 你可能应该对神经网络有所了解。正如你在上一节中简要阅读的那样, 神经网络发现了它们的灵感和生物学特性, 其中”神经网络”一词也可以用于神经元。这样, 人脑就是这种神经网络的一个例子, 它由许多神经元组成。
而且, 众所周知, 大脑能够执行相当复杂的计算, 这就是人工神经网络的灵感来源。整个网络是一个强大的建模工具。
感知器
最简单的神经网络是”感知器”, 它以最简单的形式包含单个神经元。就像具有树突和轴突的生物神经元一样, 单个人工神经元是一个简单的树状结构, 具有输入节点和一个连接到每个输入节点的单个输出节点。这是两者的视觉对比:
从图片中可以看到, 人造神经元有六个组成部分。从左到右, 这些是:
- 输入节点。碰巧的是, 每个输入节点都与一个数值相关联, 该数值可以是任何实数。请记住, 实数构成数字的全部范围:它们可以是正数或负数, 整数或十进制数。
- 连接。类似地, 每个离开输入节点的连接都具有与之关联的权重, 并且它也可以是任何实数。
- 接下来, 将所有输入节点的值和连接权重放在一起:它们用作加权总和的输入:\(y = f(\ sum_ {i = 1} ^ {D} w_i * x_i)\ ), 或者换句话说, \(y = f(w_1 * x_1 + w_2 * x_2 + … w_D * x_D)\)。
- 该结果将成为传递或激活功能的输入。在最简单但琐碎的情况下, 此传递函数将是一个标识函数\(f(x)= x \)或\(y = x \)。在这种情况下, \(x \)是输入节点和连接的加权和。但是, 就像生物神经元仅在超过特定阈值时才会触发, 人工神经元也只会在输入总和超过阈值(例如0)时才会触发。这是你无法找到的身份功能!一个人可以想到的最直观的方法是设计一个如下的系统:
\(f(x)= 0 \)如果\(x <0 \)
如果\ {x = 0 \)则\ {f(x)= 0.5 \)
\(f(x)= 1 \)如果\(x> 0 \) - 当然, 你已经可以想象输出不会是一条平滑的线:它将是一个不连续的函数。由于这可能会在数学处理中引起问题, 因此经常使用连续变体(S型函数)。你可能已经知道的S形函数的一个例子是逻辑函数。使用此功能可以使结果更加平滑!
- 结果, 你有了输出节点, 该输出节点与输入节点的加权和的函数(例如Sigmoid函数)相关联。注意, S形函数是一种数学函数, 可以产生” S”形曲线。稍后你将详细了解。
- 最后, 感知器可能是一个附加参数, 称为bias, 你可以将其视为与永久设置为1的附加输入节点关联的权重。bias值很关键, 因为它允许你将激活函数移至向左或向右, 这可以确定你的学习是否成功。
请注意, 此模型的逻辑结果是感知器仅适用于数字数据。这意味着你应将任何名义数据转换为数字格式。
既然你知道感知器可以使用阈值, 那么将它们用于分类目的的步骤就不是那么遥远:感知器可以同意, 高于某个阈值的任何输出都表明一个实例属于一个类, 而低于阈值的输出则表明该实例属于一个类。阈值可能会导致输入成为其他类的成员。因此, 输出等于阈值的直线就是两个类别之间的边界。
多层感知器
感知器网络是多层感知器, 这就是本教程将在Keras的帮助下在Python中实现的内容!多层感知器也称为”前馈神经网络”。正如你现在所猜测的那样, 这些网络比感知器要复杂得多, 因为它们由分层组织的多个神经元组成。层数通常限制为两到三层, 但理论上没有限制!
这些层的行为非常类似于你在上面已经阅读过的生物神经元:一层的输出用作下一层的输入。
在各层之间, 你可以区分输入层, 隐藏层和输出层。多层感知器通常是完全连接的。这意味着从特定层中的每个感知器到下一层中的每个感知器都有连接。即使连接不是必需条件, 通常也是如此。
请注意, 虽然感知器只能表示类之间的线性间隔, 但多层感知器克服了该限制, 还可以表示更复杂的决策边界。
预测酒的类型:红色还是白色?
在本教程中, 你将使用在UCI机器学习存储库中的葡萄酒质量数据集中找到的葡萄酒质量数据集。理想情况下, 你可以对较大的数据集进行深度学习, 但是出于本教程的目的, 你将使用较小的数据集。这主要是因为目标是使你开始使用该库并熟悉神经网络的工作原理。
你可能已经知道此数据集, 因为它是开始学习如何解决机器学习问题的最受欢迎的数据集之一。在这种情况下, 它将为你提供使用Keras进行Python深度学习的入门。
现在开始吧!
了解数据
但是, 在开始加载数据之前, 最好检查一下你对葡萄酒的了解程度(当然与数据集有关)。你们大多数人都会知道, 一般来说, 有两种非常流行的葡萄酒:红色和白色。
(我敢肯定还有很多其他人, 但是为了简单起见, 由于我对葡萄酒的了解有限, 我会一直坚持下去。很抱歉让我对你们真正的鉴赏家失望:))
知道这一点已经是一回事了, 但是如果你想分析这些数据, 则只需要了解一点。
首先, 检出数据描述文件夹以查看其中包含哪些变量。这通常是了解数据的第一步。转到此页面查看说明或继续阅读以更好地了解你的数据。
数据包含两个与葡萄牙” Vinho Verde”葡萄酒的红色和白色变体有关的数据集。如描述中所述, 你只会找到此数据集中包含的物理化学和感官变量。数据描述文件列出了数据中包含的12个变量, 但是对于像我一样也不是化学专家的人, 以下是每个变量的简短说明:
- 固定的酸度:酸是葡萄酒的主要特性, 对葡萄酒的味道有很大的贡献。通常, 总酸度分为两类:挥发性酸和非挥发性或固定酸。在葡萄酒中可以找到的固定酸包括:酒石酸, 苹果酸, 柠檬酸和琥珀酸。该变量以数据集中的g(\(酒石酸\))/ \(dm ^ 3 \)表示。
- 挥发性酸度:挥发性酸度基本上是葡萄酒变成醋的过程。在美国, 挥发性酸度的法定限值是红色食用葡萄酒为1.2克/升, 白色食用葡萄酒为1.1克/升。在这些数据集中, 挥发性酸度以g(\(乙酸\))/ \(dm ^ 3 \)表示。
- 柠檬酸是葡萄酒中的固定酸之一。在两个数据集中以g / \(dm ^ 3 \)表示。
- 残余糖通常是指发酵停止或停止后剩余的糖。在红色和白色数据中以g / \(dm ^ 3 \)表示。
- 氯化物可能是导致葡萄酒咸味的重要因素。在这里, 你会看到它以g(\(氯化钠\))/ \(dm ^ 3 \)表示。
- 游离二氧化硫:添加到葡萄酒中并损失到葡萄酒中的二氧化硫部分被认为是结合的, 而活性成分则被认为是游离的。酿酒师将始终设法获得最大比例的游离硫。该变量在数据中以mg / \(dm ^ 3 \)表示。
- 二氧化硫总量是结合的和游离的二氧化硫(SO2)之和。在这里, 以mg / \(dm ^ 3 \)表示。葡萄酒中的硫含量有法律限制:在欧盟, 红葡萄酒只能含有160mg / L, 而白葡萄酒和玫瑰葡萄酒只能含有210mg / L。甜酒的含量不得超过400mg / L。对于美国, 法定限值为350mg / L, 对于澳大利亚, 法定限值为250mg / L。
- 密度通常用作衡量糖向酒精转化的量度。在这里, 以g / \(cm ^ 3 \)表示。
- pH值或氢势是用于确定葡萄酒的酸度或碱性的数字标度。如你所知, pH小于7的溶液是酸性的, 而pH大于7的溶液是碱性的。 pH值为7, 纯净水为中性。大多数葡萄酒的pH值在2.9至3.9之间, 因此呈酸性。
- 硫酸盐对葡萄酒的作用就像面筋对食物的作用一样。你可能已经从它们可能引起的头痛中了解了亚硫酸盐。它们是全世界酿酒的常规组成部分, 被认为是必要的。在这种情况下, 它们以g(\(硫酸钾\))/ \(dm ^ 3 \)表示。
- 酒精:葡萄酒是一种酒精饮料, 众所周知, 酒精的百分比因葡萄酒而异。将此变量包含在数据集中(以体积百分比表示)并不奇怪。
- 质量:葡萄酒专家将葡萄酒的质量分为0(非常差)和10(非常好)之间。最终数字是这些葡萄酒专家进行的至少三项评估的中位数。
当然, 所有这些都是你可能需要了解的一些非常基础的信息才能上手。如果你是一位真正的葡萄酒鉴赏家, 那么你可能知道所有这些以及更多!
现在, 该获取你的数据了!
载入数据
使用Python数据操作库Pandas可以很容易地做到这一点。你遵循导入约定, 并以其别名pd导入软件包。
接下来, 你使用read_csv()函数读取存储数据的CSV文件。此外, 使用sep参数来指定分隔符(在这种情况下为分号而不是常规逗号)。
在下面的srcmini Light块中尝试一下:
太棒了!那是小菜一碟, 不是吗?
到目前为止, 你可能已经完成了一百万次了, 但这始终是入门的重要步骤。现在你已完全准备好开始探索, 处理和建模数据!
数据探索
有了手头的数据, 你就可以轻松了解有关这些葡萄酒的更多信息!你可能要做的第一件事就是开始快速浏览两个DataFrame:
现在是时候检查你的导入是否成功:再次检查数据是否包含UCI机器学习存储库的数据描述文件向你承诺的所有变量。除了变量数量之外, 还要检查导入的质量:数据类型正确吗?所有的行都通过了吗?清理数据时是否应考虑任何空值?
你可能还想用不只是info()签出数据:
简要回顾所有这些熊猫函数:你看到head(), tail()和sample()很棒, 因为它们为你提供了一种快速检查数据的方法, 而没有任何麻烦。
接下来, describe()提供一些有关数据的摘要统计信息, 可以帮助你评估数据质量。你会看到某些变量的最小值和最大值有很多差异。这是你稍后要处理的事情, 但是目前, 必须意识到这一点。
最后, 借助于isull()再次检查了红色是否为空值。在你阅读了info()的结果后仍然不确定时, 此函数总是可以派上用场的。
提示:还要检查葡萄酒数据是否包含空值。你可以使用右上方的srcmini Light块的IPython shell来完成此操作。
现在, 你已经检查了数据以查看导入是否成功并且正确无误, 是时候进行更深入的研究了。
可视化数据
一种方法是查看某些数据集变量的分布并绘制散点图以查看可能的相关性。当然, 如果你将这些数据用于自己的项目, 则可以将其带到更高的层次。
醇
乍一看, 你会发现有趣的一个变量是酒精。检查葡萄酒数据集时, 这可能是引起你注意的第一件事。你可以使用任何数据可视化库来可视化分布, 但是在这种情况下, 本教程将使用matplotlib快速绘制分布:
如下图所示, 你发现红葡萄酒和白葡萄酒之间的酒精含量基本相同:酒精含量约为9%。当然, 也有大量酒精含量为10%或11%的观察结果。
请注意, 如果你使用numpy包中的histogram()函数来计算白色和红色数据的直方图, 则可以再次进行检查, 如下所示:
如果你对matplotlib教程感兴趣, 请务必查看srcmini的Matplotlib入门教程和Viewing 3D Volumetric Data教程, 该教程向你展示如何利用Matplotlib的事件处理程序API。
硫酸盐
其次, 令我感兴趣的一件事是硫酸盐与葡萄酒质量之间的关系。正如你在上文中所读到的, 硫酸盐会导致人们头痛, 我想知道这是否会影响葡萄酒的质量。更重要的是, 我经常听到女性特别不想喝葡萄酒, 因为它会引起头痛。也许这会影响红酒的评级?
让我们来看看。
从下图中可以看出, 与白葡萄酒相比, 红葡萄酒似乎含有更多的硫酸盐, 而白葡萄酒在1 g / \(dm ^ 3 \)以上具有较少的硫酸盐。对于白葡萄酒, 似乎只有几个例外, 即略高于1 g / \(dm ^ 3 \), 而对于红葡萄酒肯定更多。这也许可以解释一般的说法, 即红酒会引起头痛, 但是质量呢?
你可以清楚地看到, 硫酸盐含量较低的白葡萄酒得分为9, 但对于其余葡萄酒, 此时很难正确解释数据。
当然, 你需要考虑到观察值的差异也可能影响图形以及你如何解释它们。
酸度
除硫酸盐外, 酸度是获得优质葡萄酒所必需的主要和重要的葡萄酒特性之一。优质葡萄酒通常会平衡酸度, 单宁, 酒精和甜度。进一步的研究告诉我, 从0.2到0.4 g / L的量, 挥发性酸度不会影响葡萄酒的质量。但是, 较高的含量时, 挥发性酸会给葡萄酒带来强烈的醋味触感。极高的挥发性酸度表明葡萄酒有严重缺陷。
让我们将数据进行测试, 并绘制一个散点图, 绘制出酒精与挥发性酸度的关系图。数据点应根据其等级或质量标签上色:
请注意, 此图像中的颜色是在NumPy随机模块的帮助下随机选择的。你始终可以通过将列表传递给redcolors或whitecolors变量来更改此设置。但是, 请确保它们相同(1除外, 因为白葡萄酒数据比红葡萄酒数据具有一个唯一的质量值), 否则你的图例将不匹配!
在此处查看完整图表:
在上图中, 你看到的是上面阅读的水平对于白葡萄酒尤其如此:多数带有标签8的葡萄酒的挥发性酸度为0.5或以下, 但是是否对品质有影响很难说, 因为所有数据点都非常密集地排向图的一侧。
这只是快速的数据探索。如果你有兴趣在自己的项目中详细介绍此步骤, 请考虑srcmini的数据探索帖子, 例如Python Exploratory Data Analysis和Python Data Profiling教程, 它们将指导你了解EDA的基础知识。
总结探索性数据分析
可能需要消化很多内容, 因此, 回顾一下你在EDA期间所看到的内容, 对于本教程的后续课程可能很重要, 永远为时不晚:
- 数据集的某些变量的值相差很大。你可以并且将在本教程的下一部分中对此进行处理。
- 你有一个理想的方案:数据集中没有空值。
- 数据集中包含的大多数葡萄酒的酒精含量约为9%。
- 红葡萄酒似乎比白葡萄酒含有更多的硫酸盐, 而白葡萄酒的硫酸盐含量高于1 g / \(dm ^ 3 \)。
- 你看到大多数葡萄酒的挥发性酸度为0.5以下。目前, 这与葡萄酒的质量没有直接关系。
到目前为止, 你已经分别查看了白葡萄酒和红葡萄酒数据。当你仔细观察某些变量时, 两者似乎有所不同, 在其他情况下, 两者似乎非常相似。你是否认为有一种方法可以根据变量将条目分类为白葡萄酒或红葡萄酒?
只有一种方法可以找到:对数据进行预处理和建模, 以便可以看到会发生什么!
预处理数据
现在, 你已经探索了数据, 现在该根据所获得的见解采取行动了!让我们对数据进行预处理, 以便你可以开始构建自己的神经网络!
在这种情况下, 你可以将ignore_index设置为True, 因为在将数据追加到红色时不想保留白色的索引标签:你希望标签从红色的地方继续, 而不是从将两个数据集结合在一起。
间奏:相关矩阵
现在你已经拥有了完整的数据集, 同时也可以快速进行数据探索是个好主意;通过分别查看两个数据集, 你已经了解了一些知识, 现在是时候收集一些更扎实的见解了。
由于很难解释图形, 因此绘制相关矩阵也是个好主意。这将使你更快地了解哪些变量相关:
如你所料, 有一些相关的变量, 例如密度和残留糖分。此外, 挥发性酸度和类型与你分别查看两个数据集时最初所猜测的关系更紧密, 并且可以预料到游离二氧化硫和总二氧化硫将相互关联。
很有意思!
训练和测试集
数据不平衡通常是指分类问题的问题, 其中类别没有被平等地表示。大多数分类数据集在每个类别中的实例数并不完全相等, 但是很小的差异通常并不重要。因此, 你需要确保训练模型中存在所有两类葡萄酒。此外, 所有两种葡萄酒的实例数量必须或多或少相等, 以便你在预测中不偏爱一种或另一种。
在这种情况下, 似乎存在不平衡, 但是你现在就可以解决这个问题。之后, 你可以评估模型, 如果模型表现不佳, 则可以采用欠采样或过采样来掩盖观测值的差异。
现在, 从sklearn.model_selection导入train_test_split并将数据和目标标签分配给变量X和y。你会看到, 你需要展平目标标签的数组, 以便完全准备使用X和y变量作为train_test_split()函数的输入。开始工作, 从下面的srcmini Light块开始!
你已经很好地构建了第一个神经网络, 但是仍然需要注意一件事!在查看白色和红色数据集的摘要时, 你是否还知道发现了什么?
确实, 其中一些价值观相距甚远。在这里进行一些标准化可能是有意义的。
标准化数据
标准化是处理距离如此遥远的这些价值观的一种方式。 scikit-learn包为你提供了一种使数据标准化的好方法:从sklearn.preprocessing导入StandardScaler模块, 你就可以扩展训练和测试数据了!
# Import `StandardScaler` from `sklearn.preprocessing`
from sklearn.preprocessing import StandardScaler
# Define the scaler
scaler = StandardScaler().fit(X_train)
# Scale the train set
X_train = scaler.transform(X_train)
# Scale the test set
X_test = scaler.transform(X_test)
现在, 你已经对数据进行了预处理, 接下来可以进行实际工作:建立自己的神经网络来对葡萄酒进行分类。
模型数据
在开始建模之前, 请先回到原始问题:可以通过查看其化学特性(例如挥发性酸度或硫酸盐)来预测葡萄酒是红色还是白色?
由于只有白色和红色两个类, 因此将进行二进制分类。可以想象, “二进制”表示0或1, 是或否。由于神经网络只能处理数字数据, 因此你已经将红色编码为1, 将白色编码为0。
多层感知器是在此类问题上表现良好的一种网络。正如你在本教程开始时所读的那样, 这种类型的神经网络通常是完全连接的。这意味着你正在寻求构建相当简单的全连接层堆栈以解决此问题。至于你将要使用的激活功能, 最好使用此处最常用的激活功能之一, 以便熟悉Keras和神经网络, 即relu激活功能。
现在, 你如何开始构建多层感知器?快速入门是使用Keras顺序模型:它是线性的图层堆栈。通过将图层实例列表传递给构造函数, 可以很容易地创建模型, 你可以通过运行model = Sequential()进行设置。
接下来, 最好回顾一下本教程开头可能已经了解的多层感知器的结构:你有一个输入层, 一些隐藏层和一个输出层。因此, 在制作模型时, 重要的是要考虑到第一层需要使输入形状清晰。该模型需要知道预期的输入形状, 这就是为什么你总是在层的文档以及这些层的实际示例中找到input_shape, input_dim, input_length或batch_size参数的原因。
在这种情况下, 你将必须使用密集层, 这是一个完全连接的层。密集层实现以下操作:输出=激活(点(输入, 内核)+偏置)。请注意, 如果没有激活功能, 则”密集”层将仅包含两个线性运算:点积和加法运算。
在第一层中, 激活参数采用值relu。接下来, 你还将看到input_shape已定义。这是你刚刚看到的操作的输入:模型采用形状为(12, )或(*, 12)的输入数组。最后, 你看到第一层具有12作为Dense()的units参数的第一个值, 这是输出空间的维数, 实际上是12个隐藏的单位。这意味着模型将输出形状为(*, 12)的数组:这是输出空间的维数。如果你现在还没有完全了解, 请不要担心, 稍后你将详细了解它!
单位实际上代表上述公式的内核或权重矩阵, 该权重矩阵由层创建的, 赋予所有输入节点的所有权重组成。请注意, 由于没有包含use_bias参数并将其设置为TRUE, 因此在下面的示例中没有包含任何偏差。
中间层还使用relu激活功能。该层的输出将是形状(*, 8)的数组。
你将使用大小为1的密集层结束网络。最后一层还将使用S型激活函数, 因此你的输出实际上是概率;这意味着这将导致得分在0到1之间, 表明样品具有目标” 1″的可能性或葡萄酒变红的可能性。
总而言之, 你会看到需要做出两个关键的体系结构决策才能建立模型:要使用的层数以及为每个层选择的”隐藏单元”数。
在这种情况下, 你为模型的第一层选择了12个隐藏的单位:如上所示, 这是输出空间的维数。换句话说, 你要设置允许网络在学习表示形式时拥有的自由度。如果你允许更多的隐藏单元, 则你的网络将能够学习更多复杂的表示形式, 但操作起来也很昂贵, 可能会过度拟合。
请记住, 当模型过于复杂时, 就会发生过度拟合:它将描述随机误差或噪声, 而不是需要描述的基本关系。换句话说, 训练数据建模得太好了!
请注意, 当你没有足够的训练数据时, 你应该使用隐藏层很少的小型网络(通常只有一个网络, 如上例所示)。
如果要获取有关刚刚创建的模型的一些信息, 则可以使用属性output_shape或summary()函数等。下面列出了一些最基本的方法。
尝试运行它们, 以查看你获得了什么样的结果, 以及它们告诉你有关刚刚创建的模型的信息:
编译并拟合
接下来, 是时候编译模型并使模型适合数据了:再次使用compile()和fit()来完成此操作。
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=20, batch_size=1, verbose=1)
在编译时, 你需要使用adam优化器和binary_crossentropy损失函数来配置模型。此外, 你还可以通过将[‘accuracy’]传递到metrics参数来监视训练期间的准确性。
如果要编译模型, 则优化器和损失是两个参数。使用的一些最受欢迎的优化算法是随机梯度下降(SGD), ADAM和RMSprop。根据你选择的算法, 你需要调整某些参数, 例如学习率或动量。损失函数的选择取决于你手头的任务:例如, 对于回归问题, 通常将使用均方误差(MSE)。如本例所示, 你使用了binary_crossentropy来解决确定葡萄酒是红色还是白色的二进制分类问题。最后, 通过多类别分类, 你将利用categorical_crossentropy。
之后, 你可以在X_train和y_train中的所有样本上以1个样本的批次训练模型20个纪元或迭代。你还可以指定详细参数。通过将其设置为1, 表示你要查看进度条日志记录。
换句话说, 你必须针对训练数据集的指定时期或曝光次数训练模型。一个时期是整个训练集的一次通过, 然后是验证集的测试。你在上面的代码中指定的批量大小定义了将通过网络传播的样本数量。另外, 这样做还可以优化效率, 因为可以确保不会同时将太多的输入模式加载到内存中。
预测值
让我们使用你的模型!你可以使用它来预测测试集的标签。只需使用predict()并将测试集传递给它即可预测数据的标签。在这种情况下, 结果存储在y_pred中:
y_pred = model.predict(X_test)
在评估模型之前, 你已经可以通过检查y_pred和y_test的比较方式来快速了解准确性:
y_pred[:5]
array([[0], [1], [0], [0], [0]], dtype=int32)
y_test[:5]
array([0, 1, 0, 0, 0])
你会看到这些值似乎加起来了, 但是如果没有一些固定数字, 这一切是什么?
评估模型
现在, 你已经建立了模型, 并使用它来对模型尚未看到的数据进行预测, 是时候评估其性能了。你可以直观地将预测结果与实际测试标签(y_test)进行比较, 也可以使用所有类型的指标来确定实际性能。在这种情况下, 你将使用评估()来执行此操作。传递测试数据和测试标签, 并根据需要将详细参数设为1。这样做时, 你会看到更多日志。
score = model.evaluate(X_test, y_test, verbose=1)
print(score)
[0.025217213829228164, 0.99487179487179489]
分数是包含损失和准确性的组合的列表。在这种情况下, 你会看到两者看起来都很棒, 但是在这种情况下, 请记住你的数据有些不平衡:白葡萄酒的数量多于红葡萄酒的数量。准确性可能只是反映你数据的类别分布, 因为它只能预测白色, 因为这些观察值很多!
在开始重新排列数据并以其他方式将它们组合在一起之前, 尝试不同的评估指标总是一个好主意。为此, 你可以依靠scikit-learn(将其作为sklearn导入, 就像在制作训练和测试集之前一样)。
在这种情况下, 你将测试一些基本的分类评估技术, 例如:
- 混淆矩阵, 这是将预测分解为表格的表格, 该表格显示正确的预测和做出的错误预测的类型。理想情况下, 你只会在对角线上看到数字, 这意味着你所有的预测都是正确的!
- 精度是分类器准确性的度量。精度越高, 分类器越准确。
- 召回率是衡量分类器完整性的指标。召回率越高, 分类器覆盖的案例越多。
- F1分数或F分数是准确性和召回率的加权平均值。
- 卡伯(Kappa)或科恩(Cohen)的卡伯(kappa)是通过数据中类的不平衡归一化的分类精度。
# Import the modules from `sklearn.metrics`
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score, cohen_kappa_score
# Confusion matrix
confusion_matrix(y_test, y_pred)
array([[1585, 3], [ 8, 549]])
# Precision
precision_score(y_test, y_pred)
0.994565217391
# Recall
recall_score(y_test, y_pred)
0.98563734290843807
# F1 score
f1_score(y_test, y_pred)
0.99008115419296661
# Cohen's kappa
cohen_kappa_score(y_test, y_pred)
0.98662321692498967
所有这些分数都很好!尽管你有很多白葡萄酒类型的行, 但你已经做出了非常准确的模型。
做得好!
更多实验
你已经成功建立了第一个模型, 但是你可以使用这个模型进一步发展。为什么不尝试以下事情, 看看它们的作用是什么?就像你在上面阅读的一样, 你需要做出的两个关键体系结构决策涉及层和隐藏节点。这些是很好的起点:
- 你使用了1个隐藏层。尝试使用2或3个隐藏层;
- 使用具有更多隐藏单元或更少隐藏单元的图层;
- 将质量列作为目标标签, 并将其余数据(包括编码类型列!)作为数据。你现在遇到了多类分类问题!
但是, 为什么还不尝试更改激活功能呢?代替使用reh, 尝试使用tanh激活功能, 看看结果如何!
预测葡萄酒质量
你的分类模型在首次运行时表现完美!
但是, 除了多层感知器之外, 你还可以做更多的事情, 不仅可以提高层次并尝试更复杂的结构。为什么不尝试建立神经网络来预测葡萄酒的品质呢?
在这种情况下, 本教程假定质量是一个连续变量:那么该任务不是二进制分类任务, 而是序数回归任务。这是一种用于预测序数变量的回归:质量值存在于任意范围内, 其中不同质量值之间的相对顺序很重要。在这个量表中, 从”非常差”到”非常好”的质量量表0-10是这样的例子。
请注意, 你也可以将此类问题视为分类问题, 并将质量标签视为固定类标签。
无论如何, 这种情况的设置将意味着你的目标标签将成为本教程第二部分的红色和白色DataFrames中的quality列。这将需要一些额外的预处理。
预处理数据
由于质量变量成为你的目标类别, 因此你现在需要将质量标签与其余数据集隔离。你将wines.quality放入另一个变量y中, 并将wines数据放入其中, 但quality列除外则放入变量x中。
接下来, 你已经准备好将数据分为训练和测试集, 但是在这种情况下, 即使你可以, 也不会采用这种方法。在本教程的第二部分中, 你将使用k倍验证, 这需要将数据分成K个分区。通常, 将K设置为4或5。接下来, 你实例化相同的模型并在一个分区上训练每个模型, 同时还评估剩余的分区。然后, 模型的验证分数是所获得的K验证分数的平均值。
稍后你将看到如何执行此操作。现在, 像以前一样, 在将数据拟合到模型之前, 使用StandardScaler确保数据在正确的位置。
请记住, 你还需要再次执行缩放, 因为红色, 白色(因此也包括葡萄酒)数据的某些值存在很大差异。
在下面的srcmini Light块中尝试一下。已为你加载了所有必需的库!
现在你又回到了刚才的位置。你可以再次开始对神经网络建模!
模型神经网络架构
现在, 你已经再次对数据进行了预处理, 现在是再次构建神经网络模型(多层感知器)的时候了。即使你将其用于回归任务, 其架构看起来也几乎相同, 只有两个密集层。
不要忘记第一层是你的输入层。你将需要将输入数据的形状传递给它。在这种情况下, 你会看到将要使用input_dim将输入数据的尺寸传递到Dense层。
再次注意, 你定义的第一层是输入层。该层需要知道数据的输入维。你输入的输入尺寸(在这种情况下为12)(不要忘记, 你还在计算在教程的第一部分中生成的Type列!)。你再次使用relu激活功能, 但是再次没有偏见。隐藏的单位数是64。
你的网络以单个单元Dense(1)结尾, 并且不包含激活。这是标量回归的典型设置, 你要在其中预测单个连续值。
编译模型, 拟合数据
有了模型, 你就可以再次对其进行编译并将其拟合为数据。可是等等。你不需要以前阅读过的K折验证分区吗?那就对了。
import numpy as np
from sklearn.model_selection import StratifiedKFold
seed = 7
np.random.seed(seed)
kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=seed)
for train, test in kfold.split(X, Y):
model = Sequential()
model.add(Dense(64, input_dim=12, activation='relu'))
model.add(Dense(1))
model.compile(optimizer='rmsprop', loss='mse', metrics=['mae'])
model.fit(X[train], Y[train], epochs=10, verbose=1)
使用compile()函数编译模型, 然后使用fit()将模型拟合到数据。要编译模型, 请再次确保至少定义了优化器和损失参数。在这种情况下, 你可以使用rsmprop(最流行的优化算法之一)并将mse用作损失函数, 这对于诸如你的回归问题非常典型。
你定义的其他指标参数实际上是一个用于判断模型性能的函数。对于回归问题, 通常以平均绝对误差(MAE)作为度量标准。你将在下一部分中详细了解此内容。
将火车数据和标签传递给fit(), 确定要运行拟合的历时, 批次大小, 如果需要, 可以将verbose参数设置为1以获取更多日志, 因为这可能会花费一些时间。
评估模型
像以前一样, 你还应该评估模型。除了在上面的其余代码中添加y_pred = model.predict(X [test])之外, 使用sklearn中的一些评估指标也是一个好主意, 就像你在本教程的第一部分中所做的一样。
为此, 你可以利用均方误差(MSE)和平均绝对误差(MAE)。前者也称为”均方差”(MSD), 用于测量误差或偏差的平方的平均值。换句话说, 它量化了估计量和估计量之间的差异。这样, 你将对估计器的质量有更多了解:它总是非负的, 并且接近零的值更好。
后者的评估指标MAE代表平均绝对误差:它量化了预测与最终结果的接近程度。
将这些行添加到先前的代码块中, 并注意缩进:
mse_value, mae_value = model.evaluate(X[test], Y[test], verbose=0)
print(mse_value)
0.522478731072
print(mae_value)
0.561965950103
请注意, 除了MSE和MAE分数外, 你还可以使用R2分数或回归分数函数。在这里, 你应该获得1.0的最高分。但是, 分数也可以为负!
from sklearn.metrics import r2_score
r2_score(Y[test], y_pred)
0.3125092543
乍一看, 这些数字非常可怕, 对吧?不过, 这样做的好处是, 你现在可以尝试优化代码, 以使结果变得更好一点。
这就是下一节和最后一节的全部内容!
模型微调
微调模型可能是你将要做的事情, 因为并非所有问题都像在本教程第一部分中看到的那样简单。如上所读, 你可能已经要调整两个关键的决定:要使用多少个图层以及为每个图层选择多少个”隐藏单位”。
从一开始, 这确实是一个漫长的旅程。
添加图层
如果在模型中添加另一层会发生什么?如果看起来像这样怎么办?
model = Sequential()
model.add(Dense(64, input_dim=12, activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(1))
隐藏的单位
还可以尝试向模型的架构中添加更多隐藏单元的效果, 并研究对评估的效果, 如下所示:
model = Sequential()
model.add(Dense(128, input_dim=12, activation='relu'))
model.add(Dense(1))
再次提醒你, 通常来说, 由于你没有大量数据, 因此过度拟合的情况可能并将会越来越严重。因此, 你应该使用小型网络。
更多实验:优化参数
除了添加层并使用隐藏单元之外, 你还可以尝试调整提供给compile()函数的优化算法的(某些)参数。到目前为止, 你始终将诸如rmsprop之类的字符串传递给优化程序参数。
但这并不总是需要像这样!
例如, 尝试从keras.models导入RMSprop并调整学习率lr。你也可以更改为RMSprop()的其他参数设置的默认值, 但是不建议这样做。你可以在此处获取更多信息。
from keras.optimizers import RMSprop
rmsprop = RMSprop(lr=0.0001)
model.compile(optimizer=rmsprop, loss='mse', metrics=['mae'])
另外, 请尝试尝试使用其他优化算法, 例如随机梯度下降(SGD)。你注意到效果了吗?
from keras.optimizers import SGD, RMSprop
sgd=SGD(lr=0.1)
model.compile(optimizer=sgd, loss='mse', metrics=['mae'])
走得更远!
本教程只是你使用Python和Keras进行深度学习的起点。还有很多内容要讲, 为什么不参加srcmini的Python深度学习课程呢?同时, 请确保还查看Keras文档(如果你尚未这样做的话)。你将找到有关所有函数, 参数, 更多层等的更多示例和信息。当你学习如何在Python中使用神经网络时, 它无疑是必不可少的资源!如果你反而想读一本解释深度学习基础知识(使用Keras)以及其在实践中的用法的书, 则你绝对应该阅读FrançoisChollet的《 Python深度学习》一书。
评论前必须登录!
注册