(原文参考https://cloud.tencent.com/developer/news/291298。Keras库自TensorFlow 2.0 起已集成在 TensorFlow库中,安装了TensorFlow库则不用再单独安装Keras库)

教程概述

使用Keras创建神经网络模型不需要你写太多代码,创建神经网络模型的步骤如下:

1)加载数据

2)定义模型

3)编译模型

4)训练模型

5)评估模型

6)做出预测

创建一个.py新文件,然后一步一步把代码复制、粘贴到文件中。

1)加载数据

当使用随机过程(例如随机数)的机器学习算法时,最好设置随机数种子(seed),这样可以反复运行相同的代码并获得相同的结果,例如:

from keras.models import Sequential

from keras.layers import Dense

import numpy

# fix random seed for reproducibility

numpy.random.seed(7)

#训练神经网络过程中到处都有随机行为,随机种子的作用就是 “锁住” 这些随机行为,让每次运行的结果完全一致。如果需要完全复现结果(生成同样的随机数),要同时固定「Python+NumPy+TensorFlow」三层种子,且固定3层随机种子要在导入keras之前,因为Keras 在导入时可能会初始化一些底层组件,提前固定种子能确保这些组件的随机行为也被锁住。

现在可以加载我们的数据了,在本教程中,我们将使用皮马印第安人糖尿病数据集(下载地址https://gitee.com/biabianm/pima-indians-diabetes)。这是来自UCI机器学习库的标准机器学习数据集。这是一个皮马印第安人的患者病历数据集,显示近五年内糖尿病患者是否发作。因此,这是一个二元分类问题(糖尿病发作为1或未发作为0)。数据集共有768个样本(患者),每个样本(患者)有8个特征值。数据集如下图所示,前8列为8个特征值,最后一列为标签值。

下载数据集并将其放在与python文件相同目录下(pima-indians-diabetes.csv为数据集文件),现在可以使用NumPy的loadtxt()函数直接加载数据集。数据集中一行有9个数值,前8个是特征值(输入数据的原始特征),最后一个是标签值(已知的正确答案输出或者期望返回的输出)。加载后,我们可以将数据集拆分为输入变量X(即前8个特征值)和输出变量Y(即最后一个标签值),代码如下:

#load pima indians dataset

dataset = numpy.loadtxt("pima-indians-diabetes.csv",delimiter="," ,skiprows=1)   # delimiter=','因csv文件就是以逗号分隔的,skiprows=1跳过第一行

#split into input (X) and output (Y) variables

X = dataset[:,0:8]  # numpy数组的多维切片,所有行的0:8列(不含索引8的列),即前8列

Y = dataset[:,8]        # numpy数组的多维切片,所有行的第9列

数据已经加载完成,现在准备定义我们的神经网络模型。注意,数据集有9列。

2)定义/搭建神经网络模型

我们使用Keras中的Sequential模型即序列模型,首先我们创建一个Sequential模型,然后使用add()函数一次添加一个层,一直添加到我们满意的层数为止,在本教程中共3层。

我们将创建具有3层的全连接网络结构。全连接层(当前层的每一个神经元都与前一层的所有神经元相连)使用Dense()来定义。在第一层中,我们可以指定层中神经元的数量作为第一个参数,输入维度作为第二个参数,激活函数作为第三个参数;在第二层中,指定层中神经元的数量作为第一个参数,激活函数作为第二个参数;第三层和第二层相似,指定层中神经元的数量作为第一个参数,激活函数作为第二个参数。

我们在前两层使用"relu"激活函数,在输出层使用"sigmoid"激活函数。顺便提一下,以前创建神经网络时优先选择"sigmoid"和"tanh"激活函数。现在都是使用"relu"激活函数,因为相比之下它的表现比"sigmoid"和"tanh"更优秀。我们在输出层使用"sigmoid"来确保我们的网络输出介于0和1之间。

创建神经网络的代码如下所示,第一层有12个神经元,需要8个输入变量。第二个隐藏层有8个神经元,最后,输出层有1个神经元来预测类别(糖尿病的发病与否)。

#create model

model=Sequential()       #实例化keras库中的models模块中的Sequential类序贯模型

model.add(Dense(12,input_dim=8, kernel_initializer='uniform', activation='relu'))    #第一层:12个神经元,输入维度8(对应X的8个特征),relu激活。调用keras库中layers模块中的Dense类生成对象,再添加到模型中即传给model.add()。kernel_initializer(“权重初始化器”)是 Keras 中层的核心参数,作用是:在模型训练开始前,为层的权重(kernel)设置初始值。

model.add(Dense(8,activation='relu'))

model.add(Dense(1,activation='sigmoid'))

神经网络模型已经搭建起来了,是不是很有成就感,是不是很简单!!!

3)编译模型(配置训练规则)

神经网络模型搭建起来之后,下一步我们就该编译它了。编译操作很简单,只需要一个.compile()函数就搞定了,要记住训练网络的目的是要找到最好的权重集和偏置,使模型具有最佳的预测功能。

第一步我们需要指定一个用于评估一组权重的损失函数,第二步需要指定一个用于寻找最好权重集和偏置的优化器。在本教程中我们使用“binary_crossentropy”作为损失函数,使用“adam”作为优化器,最后我们使用”accuracy”准确率作为评估的指标。编译模型.compile()时的参数决定指标顺序:Keras 会把「loss」和「metrics 里的指标」合并成一个指标列表,顺序是:[loss, accuracy],可在编译后验证:print(model.metrics_names)  # 输出:['loss', 'accuracy']。编译代码如下:

#Compile model

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])

4)训练模型(让模型学习数据)

上一步完成了神经网络模型的编译,接下来就该用数据集对模型进行训练了。

我们通过调用keras的.fit()函数对模型进行训练,训练代码如下所示:X、Y分别是数据集的特征值和标签值,epochs表示训练多少轮,batch_size表示一次训练多少个样本,对于初学者来说epochs和batch_size这两个名词不容易理解,其实很简单,举个例子,有一条小河,河上有一座破桥,破桥每次只允许10个人同时过桥,现在有1000个人要过桥,注意,关键时刻到了,1000个人全部过去就是1个epoch,1000个人全部从对岸过来又是一个epoch,1000个人过了几次桥就是几个epoch,再说batch_size,每次只允许10个人同时过桥,那么batch_size就等于10,已经够清楚了吧。

在训练完后,我的model变量就改变了,model.fit() 会直接修改 model 内部的核心参数(权重 / 偏置),从随机初始值变成训练后学到的最优值,因此后面可以用它预测。

# Fit the model

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

5)评估模型(这部分去掉也可运行,但建议保留以评估模型)

我们已经在整个数据集上训练了神经网络,我们也将在同一数据集上做测试来评估网络的性能。注意本教程中没有划分训练集和测试集,是用整个数据集做训练,然后再用整个数据集做测试,我们这样做是为了简化,理想情况下,应该将数据集分为训练集和测试集,以便对模型进行训练和评估。使用keras的evaluate()函数在数据集上评估模型,操作很简单,代码如下所示:将特征值数据X和标签值数据Y传递给evaluate()函数,函数将评估结果返回给scores,包括平均损失和配置的其他指标,例如准确率指标。

#evaluate the model 

scores=model.evaluate(X,Y)        #理论上,评估应使用新数据而非训练模型的数据,推荐和测试数据相同!返回值是一个列表,包含 损失值loss 和 准确率accuracy 2个参数

print('指标名列表:', model.metrics_names)

print("loss值:", scores[0]) 

print("accuracy值:", scores[1])

print('\n%s:%.2f%%'%(model.metrics_names[1], scores[1]*100))      #输出评估结果scores

运行以上所有代码,应该可以看到150个epoch中每个epoch的消息,打印每个epoch的损失值和准确率,然后在数据集上对模型进行最终评估。

注意:如果你尝试在IPython或Jupyter笔记本中运行上述代码可能会出错。出错的原因是训练期间的输出进度条问题。可以通过在对model.fit()函数调用时设置verbose= 0来轻松解决。

6)利用模型做出预测

训练模型的最终目的是对输入数据做出预测,到目前为止,我们的第一神经网络已经训练完成了,可以对输入数据进行预测了。调用keras的predict()函数对输入数据进行预测,将特征值X传递给model.predict()函数,由于我们在输出层使用sigmoid激活函数,因此预测值将是0和1之间的小数。我们期望的输出值是0(糖尿病未发作)或者1(糖尿病发作),我们可以调用round()函数,通过四舍五入方法轻松地将0到1之间的小数数值转化为只有0或1的预测值。

# calculate predictions 利用模型来预测

pred=model.predict(X)       #理论上,测试的数据应与训练的数据不同!输入的X是n行*8列,输出层是1个神经元,则.predict(X)的输出是n行*1列的二维数组,例如[[0.05], [0.98], [0.49]]。

# round predictions

result=[round(i[0]) for i in pred]    #列表推导式,把二维数组中的小数取出并四舍五入。round() 函数对数字四舍五入。

print(result)

7)下面为全部完整代码(评估模型的部分去掉也可以运行,但建议保留以评估模型)

# 导入依赖库

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=',',skiprows=1)   

# split into input (X) and output (Y) variables

X=dataset[:,0:8]       #numpy数组的多维切片,所有行的0:8列(不含索引8的列),即前8列

Y=dataset[:,8]         #numpy数组的多维切片,所有行的第9列

# create model 定义/搭建神经网络模型

model = Sequential()     #实例化keras库中的models模块中的Sequential类序贯模型

model.add(Dense(12,input_dim=8,kernel_initializer='uniform',activation='relu'))    #第一层:12个神经元,输入维度8(对应X的8个特征),relu激活

model.add(Dense(8,activation='relu'))                 # 第二层:8个神经元,relu激活

model.add(Dense(1,activation='sigmoid'))            # 输出层:1个神经元,sigmoid激活(二分类专用)

# Compile model 编译模型(配置训练规则)

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])   

 #训练过程中会输出accuracy:准确率,越大越好;loss:损失值(越小越好,代表预测结果越接近真实值)。

# Fit the model 训练模型(让模型学习数据)

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

#evaluate the model 模型评估

scores=model.evaluate(X,Y)        #理论上,评估应使用新数据而非训练模型的数据,推荐和测试数据相同!返回值是一个列表,包含 损失值loss 和 准确率accuracy 2个参数

print('指标名列表:', model.metrics_names)

print("loss值:", scores[0]) 

print("accuracy值:", scores[1]) 

print('\n%s:%.2f%%'%(model.metrics_names[1], scores[1]*100))      #输出评估结果scores

# calculate predictions 利用模型来预测

pred=model.predict(X)       #理论上,测试的数据应与训练的数据不同!输入的X是n行*8列,输出层是1个神经元,则.predict(X)的输出是n行*1列的二维数组,例如[[0.05], [0.98], [0.49]]。

# round predictions

result=[round(i[0]) for i in pred]    #列表推导式,把二维数组中的小数取出并四舍五入。round() 函数对数字四舍五入

print(result)

输出:

Epoch 146/150

77/77 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.8076 - loss: 0.4191 

Epoch 147/150

77/77 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.7733 - loss: 0.4437 

Epoch 148/150

77/77 ━━━━━━━━━━━━━━━━━━━━ 0s 1ms/step - accuracy: 0.7655 - loss: 0.4678 

Epoch 149/150

77/77 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step - accuracy: 0.8271 - loss: 0.4089 

Epoch 150/150

77/77 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step - accuracy: 0.7617 - loss: 0.4900 

24/24 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step - accuracy: 0.7483 - loss: 0.4850  

指标名列表: ['loss', 'compile_metrics']

loss值: 0.43940469622612

accuracy值: 0.7825520634651184

compile_metrics:78.26%

24/24 ━━━━━━━━━━━━━━━━━━━━ 0s 2ms/step 

[1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1,…]

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐