使用Keras逐步用Python开发你的第一个神经网络
Keras是一个功能强大且易于使用的免费开源Python库,用于开发和评估深度学习模型。
它包装了高效的数值计算库Theano和TensorFlow,并允许你在几行代码中定义和训练神经网络模型。
在本教程中,你将了解如何使用Keras在Python中创建第一个深度学习神经网络模型。
我们开始吧。
Keras教程概述
不需要太多的代码,但是我们将慢慢地介绍它,这样你就可以知道如何在将来创建你自己的模型。
你将在本教程中介绍的步骤如下:
- 加载数据。
- 定义Keras模型。
- 编译Keras模型。
- 拟合Keras模型。
- 评估Keras模型。
- 把它们都汇总在一起。
- 做出预测。
本Keras教程有几个要求:
- 你已经安装并配置了Python2或3。
- 你已安装并配置了SciPy(包括NumPy)。
- 你已经安装并配置了Keras和后端(Theano或TensorFlow)。
如果你需要有关环境的帮助,请参阅教程:
创建一个名为keras_first_network.py
的新文件,然后将代码键入或复制粘贴到文件中。
加载数据
第一步是定义我们打算在本教程中使用的函数和类。
我们将使用NumPy库来加载数据集,并使用Keras库中的两个类来定义我们的模型。
下面列出了所需的导入。
# first neural network with keras tutorial from numpy import loadtxt from keras.models import Sequential from keras.layers import Dense ...
我们现在可以加载数据集了。
在本Keras教程中,我们将使用皮马印第安人糖尿病发病数据集。这是来自UCI机器学习存储库的标准机器学习数据集。它描述了皮马印第安人的患者病历数据,以及他们是否在五年内发病糖尿病。
因此,这是一个二元分类问题(糖尿病的发病率为1或不是0)。描述每个病人的所有输入变量都是数值型的。这使得直接与期望数值输入和输出值的神经网络一起使用变得很容易,这对于我们在Keras的第一个神经网络来说是非常理想的。
我们可以从以下位置获得数据集:
下载数据集并将其放置在本地工作目录中,该目录与你的python文件位置相同。
使用文件名保存它:
pima-indians-diabetes.csv
查看文件内部,你应该会看到如下数据行:
6,148,72,35,0,33.6,0.627,50,1 1,85,66,29,0,26.6,0.351,31,0 8,183,64,0,0,23.3,0.672,32,1 1,89,66,23,94,28.1,0.167,21,0 0,137,40,35,168,43.1,2.288,33,1 ...
现在,我们可以使用NumPy函数loadtxt()将文件加载为数字矩阵。
有8个输入变量和1个输出变量(最后一列)。我们将学习将输入变量(X)行映射到输出变量(Y)的模型,我们通常将其概括为y=f(X)。
这些变量可以总结如下:
输入变量(X):
- 怀孕次数。
- 口服葡萄糖耐量试验中2小时的血糖浓度。
- 舒张压(毫米汞柱)。
- 三头肌皮褶厚度(毫米)。
- 2小时血清胰岛素(µU/ml)。
- 体重指数(体重(公斤/身高)^2)。
- 糖尿病家系功能。
- 年龄(岁)。
输出变量(Y):
- 类变量(0或1)。
一旦将CSV文件加载到内存中,我们就可以将数据列拆分为输入变量和输出变量。
数据将存储在二维数组中,其中第一维是行,第二维是列,例如[行、列]。
我们可以通过使用标准的NumPy切片运算符或“:”选择列的子集,将数组拆分为两个数组。我们可以通过切片0:8选择从索引0到索引7的前8列。然后,我们可以通过索引8选择输出列(第9个变量)。
... # load the dataset dataset = loadtxt('pima-indians-diabetes.csv', delimiter=',') # split into input (X) and output (y) variables X = dataset[:,0:8] y = dataset[:,8] ...
我们现在已经准备好定义我们的神经网络模型。
注意,数据集有9列,范围0:8将选择从0到7的列,在索引8之前停止。如果你不熟悉这一点,那么你可以在本文中了解有关数组切片和范围的更多信息:
定义Keras模型
Keras中的模型定义为一系列层。
我们创建顺序模型,一次添加一个层,直到我们对我们的网络架构感到满意。
正确的第一件事是确保输入层具有正确数量的输入要素。这可以在使用input_dim
参数创建第一个层并将其设置为8个输入变量时指定。
我们怎么知道层数和层数的类型呢?
这是一个很难回答的问题。我们可以使用启发式方法,并且通常通过反复试验的过程找到最佳的网络结构(如何配置神经网络中的层数和节点数)。通常,你需要一个足够大的网络来捕获问题的结构。
在本示例中,我们将使用具有三层的全连接网络结构。
使用密集类定义完全连接的层。我们可以指定层中神经元或节点的数量作为第一个参数,并使用激活参数指定激活函数。
我们将在前两层使用称为ReLU的校正线性单元激活函数,在输出层使用Sigmoid函数。
过去的情况是,Sigmoid和Tanh激活函数对于所有层都是优选的。如今,使用ReLU
激活功能可以获得更好的性能。我们在输出层使用Sigmoid
,以确保我们的网络输出介于0和1之间,并且易于映射到1类的概率,或捕捉到默认阈值为0.5的任一类的硬分类。
我们可以通过添加每一层将它们拼凑在一起:
- 模型需要具有8个变量的数据行(input_dim=8参数)。
- 第一隐藏层具有12个节点,并使用relu激活功能。
- 第二隐层具有8个节点,并使用relu激活功能。
- 输出层有一个节点,使用sigmoid激活功能。
... # define the keras model model = Sequential() model.add(Dense(12, input_dim=8, activation='relu')) model.add(Dense(8, activation='relu')) model.add(Dense(1, activation='sigmoid')) ...
请注意,这里最令人困惑的是,模型的输入形状被定义为第一个隐藏层上的参数。这意味着添加第一个致密层的代码行正在做两件事,定义输入或可见层和第一个隐藏层。
编译Keras模型
既然定义了模型,我们就可以编译它了。
编译该模型时使用了有效的数字库(所谓的后端),比如Theano或TensorFlow。后端会自动选择最佳方式来表示网络,以训练和预测在你的硬件(如CPU或GPU,甚至是分布式)上运行的网络。
在编译时,我们必须指定训练网络时所需的一些附加属性。记住,训练网络意味着找到将输入映射到数据集中的输出的最佳权重集。
我们必须指定用于评估一组权重的损失函数,优化器用于搜索网络的不同权重,以及我们希望在训练期间收集和报告的任何可选指标。
在这种情况下,我们将使用交叉熵作为损失变元。这种损失是针对二进制分类问题的,在Keras中定义为“binary_crossentropy”。你可以在此处了解有关根据你的问题选择损失函数的更多信息:
我们将优化器定义为高效的随机梯度下降算法“adam”。这是一个流行的渐变下降版本,因为它会自动调整自身,并在解决各种问题时提供良好的结果。要了解adam版本的随机梯度下降的更多信息,请参阅文章:
最后,由于这是一个分类问题,我们将收集并报告通过metrics参数定义的分类精度。
... # compile the keras model model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) ...
拟合Keras模型
我们已经定义了我们的模型,并对其进行了编译,以便进行有效的计算。
现在是对一些数据执行模型的时候了。
通过调用模型上的fit()函数,我们可以在加载的数据上训练或拟合模型。
训练在epoch上进行,每个历元被分成几个batche。
Epoch:一次遍历训练数据集中的所有行。
Batche:在更新权重之前,模型在一个epoch内考虑的一个或多个样本。
基于所选择的batche大小,一个epoch由一个或多个batche组成,并且该模型适用于多个epoch。有关epoch和batche之间的区别的更多信息,请参见帖子:
训练过程将通过称为Epochs的数据集运行固定次数的迭代,我们必须使用Epochs参数指定该数据集。我们还必须设置在每个Epoch内更新模型权重之前考虑的数据集行数,称为Batche大小,并使用batch_size
参数设置。
对于这个问题,我们将运行少量的epoch(150),并使用相对较小的batche大小(10)。
这些配置可以通过试验和错误实验来选择。我们希望对模型进行足够的训练,以便它了解输入数据行到输出分类的良好(或足够好)映射。模型总是会有一些错误,但是对于给定的模型配置,错误的量会在某个时间点之后趋于稳定。这称为模型收敛。
... # fit the keras model on the dataset model.fit(X, y, epochs=150, batch_size=10) ...
这是在你的CPU或GPU上进行工作的地方。
这个例子不需要GPU,但如果你对如何在云中廉价地在GPU硬件上运行大型模型感兴趣,请参阅这篇文章:
评估Keras模型
我们已经在整个数据集上训练了我们的神经网络,并且我们可以在相同的数据集上评估网络的性能。
这只会让我们知道我们对数据集的建模有多好(例如,训练精度),但不知道算法在新数据上可能执行得有多好。我们这样做是为了简单起见,但理想情况下,你可以将数据分成训练和测试数据集,以便对模型进行训练和评估。
你可以使用模型上的evaluate()函数评估训练数据集上的模型,并向其传递用于训练模型的相同输入和输出。
这将为每个输入和输出对生成预测,并收集分数,包括平均损失和你已配置的任何指标(如准确性)。
函数的作用是:返回一个包含两个值的列表。第一个是数据集上模型的损失,第二个是数据集上模型的准确性。我们只对报告准确性感兴趣,所以我们将忽略损失价值。
... # evaluate the keras model _, accuracy = model.evaluate(X, y) print('Accuracy: %.2f' % (accuracy*100))
把它们都汇总在一起
你刚才看到了如何在Keras中轻松创建第一个神经网络模型。
让我们将所有这些整合到一个完整的代码示例中。
# first neural network with keras tutorial from numpy import loadtxt from keras.models import Sequential from keras.layers import Dense # load the dataset dataset = loadtxt('pima-indians-diabetes.csv', delimiter=',') # split into input (X) and output (y) variables X = dataset[:,0:8] y = dataset[:,8] # define the keras model model = Sequential() model.add(Dense(12, input_dim=8, activation='relu')) model.add(Dense(8, activation='relu')) model.add(Dense(1, activation='sigmoid')) # compile the keras model model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # fit the keras model on the dataset model.fit(X, y, epochs=150, batch_size=10) # evaluate the keras model _, accuracy = model.evaluate(X, y) print('Accuracy: %.2f' % (accuracy*100))
你可以将所有代码复制到Python文件中,并将其另存为“keras_first_network.py”,保存在与数据文件“pia-indians-diabetes.csv”相同的目录中。然后,你可以从命令行(命令提示符)将Python文件作为脚本运行,如下所示:
python keras_first_network.py
运行此示例时,你应该会看到150个epoch中的每个epoch都会显示一条消息,打印损失和精度,然后是对训练数据集的训练模型的最终评估。
在CPU上运行的工作站上执行大约需要10秒。
理想情况下,我们希望损失为零,准确率为1.0(例如100%)。除了最微不足道的机器学习问题外,这对于任何问题都是不可能的。相反,我们的模型中总是会有一些错误。目标是为给定的数据集选择能够实现最低损失和最高精度的模型配置和训练配置。
... 768/768 [==============================] - 0s 63us/step - loss: 0.4817 - acc: 0.7708 Epoch 147/150 768/768 [==============================] - 0s 63us/step - loss: 0.4764 - acc: 0.7747 Epoch 148/150 768/768 [==============================] - 0s 63us/step - loss: 0.4737 - acc: 0.7682 Epoch 149/150 768/768 [==============================] - 0s 64us/step - loss: 0.4730 - acc: 0.7747 Epoch 150/150 768/768 [==============================] - 0s 63us/step - loss: 0.4754 - acc: 0.7799 768/768 [==============================] - 0s 38us/step Accuracy: 76.56
注意,如果你尝试在IPython或Jupyter笔记本中运行此示例,可能会出现错误。
原因是训练期间的输出进度条。通过在对fit()和evaluate()函数的调用中设置verbose=0,可以轻松地关闭这些设置,例如:
... # fit the keras model on the dataset without progress bars model.fit(X, y, epochs=150, batch_size=10, verbose=0) # evaluate the keras model _, accuracy = model.evaluate(X, y, verbose=0) ...
请注意,你的模型的精确度会有所不同。
你得了几分?
在下面的评论中发布你的结果。
神经网络是一种随机算法,这意味着相同数据上的相同算法可以在每次代码运行时以不同的技能训练不同的模型。这是一个功能,不是错误。你可以在帖子中了解更多关于这一点的信息:
模型性能的差异意味着要获得模型执行情况的合理近似值,你可能需要对其进行多次拟合并计算精度分数的平均值。有关这种评估神经网络的方法的更多信息,请参见帖子:
例如,以下是重新运行该示例5次所得的准确度分数:
Accuracy: 75.00 Accuracy: 77.73 Accuracy: 77.60 Accuracy: 78.12 Accuracy: 76.17
我们可以看到,所有的准确率得分都在77%左右,平均为76.924%。
做出预测
我被问到的第一个问题是:
在我训练了我的模型之后,我如何使用它来对新数据进行预测呢?
问得好。
我们可以调整上面的示例,并使用它来生成对训练数据集的预测,假装它是我们以前没有见过的新数据集。
做出预测就像在模型上调用predict()函数一样简单。我们在输出层使用sigmoid激活函数,因此预测将是介于0和1之间的概率。我们可以通过四舍五入很容易地将它们转换为此分类任务的简明的二进制预测。
例如:
... # make probability predictions with the model predictions = model.predict(X) # round predictions rounded = [round(x[0]) for x in predictions]
或者,我们也可以在模型上调用predict_classes()函数来直接预测清晰的类,例如:
... # make class predictions with the model predictions = model.predict_classes(X)
下面的完整示例对数据集中的每个示例进行预测,然后打印数据集中前5个示例的输入数据、预测类和预期类。
# first neural network with keras make predictions from numpy import loadtxt from keras.models import Sequential from keras.layers import Dense # load the dataset dataset = loadtxt('pima-indians-diabetes.csv', delimiter=',') # split into input (X) and output (y) variables X = dataset[:,0:8] y = dataset[:,8] # define the keras model model = Sequential() model.add(Dense(12, input_dim=8, activation='relu')) model.add(Dense(8, activation='relu')) model.add(Dense(1, activation='sigmoid')) # compile the keras model model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # fit the keras model on the dataset model.fit(X, y, epochs=150, batch_size=10, verbose=0) # make class predictions with the model predictions = model.predict_classes(X) # summarize the first 5 cases for i in range(5): print('%s => %d (expected %d)' % (X[i].tolist(), predictions[i], y[i]))
运行该示例不会像以前一样显示进度条,因为我们已将详细参数设置为0。
模型拟合后,对数据集中的所有示例进行预测,并打印前5个示例的输入行和预测的类值,并将其与预期类值进行比较。
我们可以看到,大多数行都被正确预测。事实上,根据我们在上一节中对模型性能的估计,我们预计大约76.9%的行将被正确预测。
[6.0, 148.0, 72.0, 35.0, 0.0, 33.6, 0.627, 50.0] => 0 (expected 1) [1.0, 85.0, 66.0, 29.0, 0.0, 26.6, 0.351, 31.0] => 0 (expected 0) [8.0, 183.0, 64.0, 0.0, 0.0, 23.3, 0.672, 32.0] => 1 (expected 1) [1.0, 89.0, 66.0, 23.0, 94.0, 28.1, 0.167, 21.0] => 0 (expected 0) [0.0, 137.0, 40.0, 35.0, 168.0, 43.1, 2.288, 33.0] => 1 (expected 1)
如果你想了解更多关于如何使用Keras模型进行预测的信息,请参阅帖子:
Keras教程摘要
在这篇文章中,你了解了如何使用功能强大的Keras Python库进行深度学习来创建你的第一个神经网络模型。
具体地说,你学习了使用Keras创建神经网络或深度学习模型的六个关键步骤,逐步包括:
- 如何加载数据。
- 如何在Keras中定义神经网络。
- 如何使用高效的数值后端编译Keras模型。
- 如何对模型进行数据训练。
- 如何根据数据评估模型。
- 如何用模型进行预测。
你对凯拉斯或本教程有什么问题吗?
在评论中问你的问题,我会尽我所能回答的。
Keras教程扩展模块
做得很好,你已经成功地使用Python中的Keras深度学习库开发了你的第一个神经网络。
本节提供了本教程的一些扩展,你可能希望了解这些扩展。
- 调整模型。更改模型的配置或训练过程,看看是否可以提高模型的性能,例如,达到76%以上的准确率。
- 保存模型。更新教程以将模型保存到文件,然后稍后加载它并使用它进行预测(请参阅本教程)。
- 总结模型。更新教程以总结模型并创建模型图层的打印(请参见本教程)。
- 单独的训练和测试数据集。将加载的数据集拆分成训练和测试集(基于行拆分),并使用一个集训练模型,使用另一个集估计模型在新数据上的性能。
- 绘制学习曲线。函数的作用是:返回一个历史记录对象,总结每个epoch结束时的损失和精度。创建此数据的线状图,称为学习曲线(请参阅本教程)。
- 了解新数据集。更新教程以使用不同的表格数据集,可能来自UCI机器学习存储库。
- 使用函数式API。更新教程以使用Keras Functional API定义模型(请参见本教程)。