使用 Python 和 Keras 逐步开发你的第一个神经网络(转)

使用 Python 和 Keras 逐步开发你的第一个神经网络(转)

原文:Develop Your First Neural Network in Python With Keras Step-By-Step

译者:飞龙

协议:CC BY-NC-SA 4.0

Keras 是一个功能强大且易于使用的 Python 库,用于开发和评估深度学习模型。

它包含高效的数值计算库 Theano 和 TensorFlow,允许你使用几行代码定义和训练神经网络模型。

在这篇文章中,你将了解如何使用 Keras 和 Python 中创建你的第一个神经网络模型。

让我们开始吧。

概览

我们不需要很多代码,但我们会慢慢跨过它,以便你将来知道如何创建自己的模型。

本教程中介绍的步骤如下:

  • 加载数据
  • 定义模型
  • 编译模型
  • 拟合模型
  • 评估模型
  • 把它放在一起

本教程有一些要求:

你已安装并配置了Python 2 或 3。 你已安装并配置了 SciPy(包括 NumPy)。 你安装并配置了 Keras 和后端(Theano 或 TensorFlow)。

如果你需要环境方面的帮助,请参阅教程:

创建一个名为keras_first_network.py的新文件,然后在前进过程中,将代码键入或复制并粘贴到文件中。

1. 加载数据

每当我们处理使用随机过程(例如随机数)的机器学习算法时,最好设置随机数种子。

这样你就可以反复运行相同的代码并获得相同的结果。如果你需要演示结果,使用相同的随机源比较算法,或调试代码的一部分,这非常有用。

你可以使用你喜欢的任何种子初始化随机数生成器,例如:

from keras.models import Sequential
from keras.layers import Dense
import numpy
# fix random seed for reproducibility
numpy.random.seed(7)

现在我们可以加载我们的数据。

在本教程中,我们将使用皮马印第安人糖尿病数据集。 这是来自 UCI 机器学习库的标准机器学习数据集。 它描述了皮马印第安人的患者病历数据,以及他们是否在五年内患有糖尿病。

因此,它是二元分类问题(糖尿病发作为 1 或没有为 0)。 描述每个患者的所有输入变量都是数字的。 这使得它可以直接用于接受数字输入和输出值的神经网络,是我们在 Keras 的第一个神经网络的理想选择。

下载数据集并将其放在本地工作目录中,与 python 文件相同。 使用文件名保存:

pima-indians-diabetes.csv

你现在可以使用 NumPy 函数loadtxt()直接加载文件。 有八个输入变量和一个输出变量(最后一列)。 加载后,我们可以将数据集拆分为输入变量(X)和输出类变量(Y)。

# load pima indians dataset
dataset = numpy.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 之前停止。如果这对你来说是新的,那么你可以在此博文中了解数组切片和范围的更多信息:

2. 定义模型

Keras 中的模型被定义为层的序列。

我们创建一个Sequential(顺序)模型并一次添加一个层,直到我们对网络拓扑感到满意为止。

要做的第一件事是,确保输入层具有正确数量的输入。这可以使用input_dim参数创建第一个层并为 8 个输入变量将其设置为 8 来指定。

我们如何知道层数及其类型?

这是一个非常难的问题。我们可以使用启发式方法,通常通过试错的过程找到最好的网络结构。通常,如果有任何帮助,你需要一个足够大的网络来捕获问题的结构。

在此示例中,我们将使用三层的全连接的网络结构。

全连接层使用Dense类定义。我们可以在第一个参数中指定层中神经元的数量,在第二个参数中将初始化方法指定为init,并使用activation参数指定激活函数。

在这种情况下,我们将网络权重初始化为小随机数,它们从均匀分布('uniform')生成,在这种情况下介于 0 和 0.05 之间,因为这是 Keras 中的默认均匀权重初始化。对于从高斯分布产生的小随机数,另一种传统的备选项是'normal'

我们将在前两层使用整流器('relu')激活函数,在输出层使用sigmoid函数。过去,所有层都优先选择sigmoidtanh激活函数。目前,使用整流器激活函数可以获得更好的性能。我们在输出层使用sigmoid来确保我们的网络输出介于 0 和 1 之间,并且很容易映射到类为 1 的概率,或者使用默认阈值 0.5 划分到任一类的硬分类。

我们可以通过添加每一层将它们拼凑在一起。第一层有 12 个神经元,需要 8 个输入变量。第二个隐藏层有 8 个神经元,最后,输出层有 1 个神经元来预测类别(糖尿病的发病与否)。

# create model
model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

3. 编译模型

既然定义了模型,我们就可以编译它。

编译模型使用背后的高效数字库(所谓的后端),如 Theano 或 TensorFlow。后端自动选择最佳方式来为表示网络用于训练,并使预测能够在你的硬件上运行,例如 CPU 或 GPU 甚至分布式。

编译时,我们必须指定训练网络时所需的一些其他属性。记住训练网络意味着找到最好的权重集来预测这个问题。

我们必须指定用于评估一组权重的损失函数,用于搜索网络的不同权重的优化器,以及我们希望在训练期间收集和报告的任何可选指标。

在这种情况下,我们将使用对数损失,对于二元分类问题,在 Keras 中将其定义为binary_crossentropy。我们还将使用高效的梯度下降算法adam,因为它是一个有效的默认值。在《Adam:随机优化方法》一文中了解 Adam 优化算法的更多信息。

最后,因为它是一个分类问题,我们将收集并报告分类准确率作为指标。

4. 拟合模型

我们已经定义了我们的模型并为高效计算而将其编译。

现在是时候在一些数据上执行模型了。

我们可以通过调用模型上的fit()函数来训练或拟合我们加载的数据模型。

训练过程将对名为epochs的数据集进行固定次数的迭代,我们必须使用nepochs参数指定。 我们还可以设置实例数,它在执行网络中的权重更新之前求值,称为批量大小并使用batch_size参数进行设置。

对于这个问题,我们将进行少量迭代(150)并使用相对较小的批量大小 10。再次,这些可以通过试错进行选择。

# Fit the model
model.fit(X, Y, epochs=150, batch_size=10)

这在你的 CPU 或 GPU 上工作。

此示例不需要 GPU,但如果你想知道如何在云中廉价地在 GPU 硬件上运行大型模型,请参阅此博文:

5. 评估模型

我们已经在整个数据集上训练了神经网络,我们可以在同一数据集上评估网络的性能。

这只会让我们了解我们对数据集建模的好坏(例如训练准确率),但不知道算法在新数据上的表现如何。 我们这样做是为了简化,但理想情况下,你应该将数据分为训练和测试数据集,以便对模型进行训练和评估。

你可以使用模型上的evaluate()函数在训练数据集上评估模型,并将其传递给用于训练模型的相同输入和输出。

这将为每个输入和输出对生成预测并收集分数,包括平均损失和你已配置的任何指标,例如准确度。

# evaluate the model
scores = model.evaluate(X, Y)
print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))

6. 把它放在一起

你刚刚看到如何在 Keras 中轻松创建第一个神经网络模型。

让我们将它们组合成一个完整的代码示例。

# Create your first MLP in Keras
from keras.models import Sequential
from keras.layers import Dense
import numpy
# fix random seed for reproducibility
numpy.random.seed(7)
# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# create 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 model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(X, Y, epochs=150, batch_size=10)
# evaluate the model
scores = model.evaluate(X, Y)
print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))

运行此示例,你应该看到 150 个时期中每个时期的消息,每个时期的损失和准确率,然后是训练数据集上的训练模型的最终评估。

在我的工作站上执行大约需要 10 秒钟,它在后端为 Theano 的 CPU 上运行。

...
Epoch 145/150
768/768 [==============================] - 0s - loss: 0.5105 - acc: 0.7396
Epoch 146/150
768/768 [==============================] - 0s - loss: 0.4900 - acc: 0.7591
Epoch 147/150
768/768 [==============================] - 0s - loss: 0.4939 - acc: 0.7565
Epoch 148/150
768/768 [==============================] - 0s - loss: 0.4766 - acc: 0.7773
Epoch 149/150
768/768 [==============================] - 0s - loss: 0.4883 - acc: 0.7591
Epoch 150/150
768/768 [==============================] - 0s - loss: 0.4827 - acc: 0.7656
 32/768 [>.............................] - ETA: 0s
acc: 78.26%

注意:如果你尝试在 IPython 或 Jupyter笔记本中运行此示例,则可能会出错。 原因是训练期间的输出进度条。 你可以通过在对model.fit()的调用中设置verbose=0来轻松关闭它们。

请注意,你的模型的技能可能会有所不同。

神经网络是一种随机算法,意味着相同数据上的相同算法可以训练具有不同技能的不同模型。 这是一个特征,而不是一个 bug。 你可以在博文中了解更多相关信息:

我们确实尝试固定随机种子,来确保你和我获得相同的模型,因此得到相同的结果,但这并不总是适用于所有系统。 我在这里写了更多使用 Keras 模型重现结果的问题

7. 附加分:做出预测

我被问到的第一个问题是:

在训练我的模型后,如何使用它来预测新数据?

好问题。

我们可以调整上面的示例并使用它来生成训练数据集的预测,假装它是我们以前从未见过的新数据集。

进行预测就像调用model.predict()一样简单。 我们在输出层使用sigmoid激活函数,因此预测将在 0 和 1 之间的范围内。我们可以通过舍入它们轻松地将它们转换为这个分类任务的清晰二元预测。

下面列出了完整示例,为训练数据中的每条记录做出预测。

# Create first network with Keras
from keras.models import Sequential
from keras.layers import Dense
import numpy
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]
# create model
model = Sequential()
model.add(Dense(12, input_dim=8, init='uniform', activation='relu'))
model.add(Dense(8, init='uniform', activation='relu'))
model.add(Dense(1, init='uniform', activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
# Fit the model
model.fit(X, Y, epochs=150, batch_size=10,  verbose=2)
# calculate predictions
predictions = model.predict(X)
# round predictions
rounded = [round(x[0]) for x in predictions]
print(rounded)

现在运行此修改示例将打印每个输入的预测。 如果需要,我们可以直接在我们的应用中使用这些预测。

[1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]

如果你对使用经过训练的模型进行预测有更多疑问,请参阅此博文:

总结

在这篇文章中,你发现了如何使用功能强大的 Keras Python 库,为深度学习创建你的第一个神经网络模型。

具体来说,你学习了使用 Keras 创建神经网络或深度学习模型的五个关键步骤,包括:

  • 如何加载数据。
  • 如何在 Keras 中定义神经网络。
  • 如何使用高效的数值后端编译 Keras 模型。
  • 如何训练数据模型。
  • 如何评估数据模型。
posted @ 2019-05-20 16:08  大汤姆  阅读(1407)  评论(0编辑  收藏  举报