第10章 项目:多类花朵分类

本章我们使用Keras为多类分类开发并验证一个神经网络。本章包括:

  • 将CSV导入Keras
  • 为Keras预处理数据
  • 使用scikit-learn验证Keras模型

我们开始吧。

10.1 鸢尾花分类数据集

本章我们使用经典的鸢尾花数据集。这个数据集已经被充分研究过,4个输入变量都是数字,量纲都是厘米。每个数据代表花朵的不同参数,输出是分类结果。数据的属性是(厘米):

  1. 萼片长度
  2. 萼片宽度
  3. 花瓣长度
  4. 花瓣宽度
  5. 类别

这个问题是多类分类的:有两种以上的类别需要预测,确切的说,3种。这种问题需要对神经网络做出特殊调整。数据有150条:前5行是:

  1. 5.1,3.5,1.4,0.2,Iris-setosa
  2. 4.9,3.0,1.4,0.2,Iris-setosa
  3. 4.7,3.2,1.3,0.2,Iris-setosa
  4. 4.6,3.1,1.5,0.2,Iris-setosa
  5. 5.0,3.6,1.4,0.2,Iris-setosa

鸢尾花数据集已经被充分研究,模型的准确率可以达到95%到97%,作为目标很不错。本书的data目录下附带了示例代码和数据,也可以从UCI机器学习网站下载,重命名为iris.csv。数据集的详情请在UCI机器学习网站查询。

10.2 导入库和函数

我们导入所需要的库和函数,包括深度学习包Keras、数据处理包pandas和模型测试包scikit-learn。

  1. import numpy
  2. import pandas
  3. from keras.models import Sequential
  4. from keras.layers import Dense
  5. from keras.wrappers.scikit_learn import KerasClassifier
  6. from keras.utils import np_utils
  7. from sklearn.cross_validation import cross_val_score
  8. from sklearn.cross_validation import KFold
  9. from sklearn.preprocessing import LabelEncoder
  10. from sklearn.pipeline import Pipeline

10.3 指定随机数种子

我们指定一个随机数种子,这样重复运行的结果会一致,以便复现随机梯度下降的结果:

  1. # fix random seed for reproducibility
  2. seed = 7
  3. numpy.random.seed(seed)

10.4 导入数据

数据可以直接导入。因为数据包含字符,用pandas更容易。然后可以将数据的属性(列)分成输入变量(X)和输出变量(Y):

  1. # load dataset
  2. dataframe = pandas.read_csv("iris.csv", header=None)
  3. dataset = dataframe.values
  4. X = dataset[:,0:4].astype(float)
  5. Y = dataset[:,4]

10.5 输出变量编码

数据的类型是字符串:在使用神经网络时应该将类别编码成矩阵,每行每列代表所属类别。可以使用独热编码,或者加入一列。这个数据中有3个类别:Iris-setosaIris-versicolorIris-virginica。如果数据是

  1. Iris-setosa
  2. Iris-versicolor
  3. Iris-virginica

用独热编码可以编码成这种矩阵:

  1. Iris-setosa, Iris-versicolor, Iris-virginica 1, 0, 0
  2. 0, 1, 0
  3. 0, 0, 1

scikit-learn的LabelEncoder可以将类别变成数字,然后用Keras的to_categorical()函数编码:

  1. # encode class values as integers
  2. encoder = LabelEncoder()
  3. encoder.fit(Y)
  4. encoded_Y = encoder.transform(Y)
  5. # convert integers to dummy variables (i.e. one hot encoded)
  6. dummy_y = np_utils.to_categorical(encoded_Y)

10.6 设计神经网络

Keras提供了KerasClassifier,可以将网络封装,在scikit-learn上用。KerasClassifier的初始化变量是模型名称,返回供训练的神经网络模型。

我们写一个函数,为鸢尾花分类问题创建一个神经网络:这个全连接网络只有1个带有4个神经元的隐层,和输入的变量数相同。为了效果,隐层使用整流函数作为激活函数。因为我们用了独热编码,网络的输出必须是3个变量,每个变量代表一种花,最大的变量代表预测种类。网络的结构是:

  1. 4个神经元 输入层 -> [4个神经元 隐层] -> 3个神经元 输出层

输出层的函数是S型函数,把可能性映射到概率的0到1。优化算法选择ADAM随机梯度下降,损失函数是对数函数,在Keras中叫categorical_crossentropy

  1. # define baseline model
  2. def baseline_model():
  3. # create model
  4. model = Sequential()
  5. model.add(Dense(4, input_dim=4, init='normal', activation='relu')) model.add(Dense(3, init='normal', activation='sigmoid'))
  6. # Compile model
  7. model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) return model

可以用这个模型创建KerasClassifier,也可以传入其他参数,这些参数会传递到fit()函数中。我们将训练次数nb_epoch设成150,批尺寸batch_size设成5,verbose设成0以关闭调试信息:

  1. estimator = KerasClassifier(build_fn=baseline_model, nb_epoch=200, batch_size=5, verbose=0)

10.7 用K折交叉检验测试模型

现在可以测试模型效果了。scikit-learn有很多种办法可以测试模型,其中最重要的就是K折检验。我们先设定模型的测试方法:K设为10(默认值很好),在分割前随机重排数据:

  1. kfold = KFold(n=len(X), n_folds=10, shuffle=True, random_state=seed)

这样我们就可以在数据集(Xdummy_y)上用10折交叉检验(kfold)测试性能了。模型需要10秒钟就可以跑完,每次检验输出结果:

  1. results = cross_val_score(estimator, X, dummy_y, cv=kfold)
  2. print("Accuracy: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))

输出结果的均值和标准差,这样可以验证模型的预测能力,效果拔群:

  1. Baseline: 95.33% (4.27%)

10.8 总结

本章关于使用Keras开发深度学习项目。总结一下:

  • 如何导入数据
  • 如何使用独热编码处理多类分类数据
  • 如何与scikit-learn一同使用Keras
  • 如何用Keras定义多类分类神经网络
  • 如何用scikit-learn通过K折交叉检验测试Keras的模型

10.8.1 下一章

本章完整描述了Keras项目的开发:下一章我们开发一个二分类网络,并调优。