【Iris】【Keras】神经网络分类器和【scikit-learn】逻辑回归分类器的构建

原文链接:https://github.com/fastforwardlabs/keras-hello-world/blob/master/kerashelloworld.ipynb

原文标题:“Hello world” in Keras

本文全部代码基于python2,使用编辑器为ipython notebook,入门级。

高级神经网络库的出现,使开发人员能够快速构建神经网络模型,而不必担心浮点运算、张量代数和GPU编程的数值细节。

Keras是一种高级神经网络库,它基于Theano或TensorFlow的后端(backends)工作,提供了一种类似于scikit-learn的API。

我将提供一个快速上手教程,详细比对Keras和scikit-learn,并教会你如何使用Keras。

一、Scikit-learn

Scikit-learn是Python开发人员使用的最为流行的、功能完备的机器学习库。Scikit-learn的API围绕Estimator对象构建,表现出简单、连贯、一致的特性。这套API是针对机器学习工作流程的一个很好的描述,许多工程师都习惯于此,也在很多工具包中得到广泛使用。

我们从导入所需的库开始工作:scikit-learn、Keras和一些绘图功能。

%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

from sklearn.cross_validation import train_test_split
from sklearn.linear_model import LogisticRegressionCV

from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.utils import np_utils

1、Iris data

著名的鸢尾花(Iris)数据集(由Ronald Fisher于1936年发表)是一种展示机器学习框架API的好方法。从某种程度上说,Iris数据集是机器学习界的”Hello world“。

数据很简单,可以使用非常简单的分类器获得高精度。因此,使用神经网络解决这个问题有点小题大做。但是这不错啊!我们的目的是探索从数据到可用分类器所需的代码,而不是模型设计和选择的细节。

Iris数据集内置于许多机器学习库中。我更喜欢它在seaborn中的副本,因为这一副本是个有标签的数据框(dataframe),可以很容易的做数据可视化。既然我们使用seaborn库,不妨加载该数据集并观察一下前5个样本。

iris = sns.load_dataset("iris")
iris.head()

对于每个样本(本例中是花),存在五个数据。其中前四项是花的尺寸(厘米)的标准测量,第五项是鸢尾花的种类。数据集中有三种鸢尾花:setosa、verscicolor和virginica。我们的工作是建立一个分类器,给定两个花瓣和两个萼片的测量,可以预测鸢尾花的种类。

 

2、调整并切分数据用于训练和测试

首先,我们需要从iris数据框中提取原始数据。我们将花瓣和萼片数据保存到数组X中,将种类标记保存到响应的数组Y中。

X = iris.values[:, :4]
y = iris.values[:, 4]

按照有监督机器学习的标准,我们使用一部分数据训练模型,并使用剩余的数据衡量模型的性能。这是很容易做到的,已经内置成为scikit-learn的train_test_split()函数。

train_X, test_X, train_y, test_y = train_test_split(X, y, train_size=0.5, random_state=0)

3、训练一个scikit-learn分类器

我们将要训练一个logistic回归分类器。训练分类器、使用内置的超参数交叉验证,是scikit-learn中的一条工作线。

像所有其他scikit-learn的Estimator对象一样,LogisticRegressionCV分类器有一个.fit()方法,可以处理模型训练细节,搜索到最适于训练集的模型参数。这个方法就是我们所要做的全部:

lr = LogisticRegressionCV()
lr.fit(train_X, train_y)

4、基于正确率评估模型性能

现在我们可以测量训练得到的分类器在测试集上的性能优劣(如正确率:accuracy)。

print("Accuracy = {:.2f}".format(lr.score(test_X, test_y)))
正确率大概等于0.83.


二、Keras

 

说明:本教程中的Keras选择Theano作为后端。

Keras默认使用TensorFlow作为后端来进行张量操作,也可以按需切换到Theano。

如果你至少运行过一次Keras,你将在下面的目录下找到Keras的配置文件:

~/.keras/keras.json

如果该目录下没有该文件,你可以手动创建一个,文件的默认配置如下:

{
“image_dim_ordering”:”tf”,
“epsilon”:1e-07,
“floatx”:”float32”,
“backend”:”tensorflow”
}

将backend字段的值改写为你需要使用的后端:theano或tensorflow,即可完成后端的切换。注意image_dim_ordering字段需要与之对应:th或tf,该选项指定了Keras将要使用的维度顺序,可通过keras.backend.image_dim_ordering()来获取当前的维度顺序。对2D数据来说,tf假定维度顺序为(rows,cols,channels)而th假定维度顺序为(channels, rows, cols)。对3D数据而言,tf假定(conv_dim1, conv_dim2, conv_dim3, channels),th则是(channels, conv_dim1, conv_dim2, conv_dim3)。

 

1、现在做一些与Keras非常相似的事情

正如我们刚刚看到的,scikit-learn构建分类器非常简单:一行代码用于实例化分类器;一行代码用于训练分类器;一行代码用于衡量分类器性能。

在Keras上构建分类器只是稍微复杂一点。数据的预处理有一点变化,另外,我们必须做一些工作来定义网络,然后将其实例化为分类器,除此之外,Keras的使用与scikit-learn非常相似。

在数据预处理方面,scikit-learn分类器接收字符型标签,如”setosa“。但是,Keras需要将标签做独热编码(One-Hot-Encoded)。有很多方法可以实现独热编码。如果你是一个Pandas用户,那么可以使用pandas.get_dummies(),基于scikit-learn实现独热编码。此处我们使用一个Keras实用程序和一些numpy。

def one_hot_encode_object_array(arr):
    '''One hot encode a numpy array of objects (e.g. strings)'''
    uniques, ids = np.unique(arr, return_inverse=True)
    return np_utils.to_categorical(ids, len(uniques))

train_y_ohe = one_hot_encode_object_array(train_y)
test_y_ohe = one_hot_encode_object_array(test_y)

2、构建神经网络模型

除了这种在特定情况下需要的数据预处理之外,与scikit-learn最大的区别在于,使用Keras工作,你必须先指定模型的结构,然后才能实例化和使用它。

在scikit-learn中,模型是现成的。Keras是一个神经网络库,因此,即使你的数据特征或数据类别的数目存在限制,你可以定义模型结构所有的其他方面:网络层数、层的大小、层间连接性质等。(如果这些参数没有意义,Keras是一种很伟大的实验方法)

这样的自由度带来一个缺点,实例化一个最小的分类器也会涉及到比scikit-learn更多的工作需求。

在本例中,我们将构建一个极简的网络。数据本身为我们做了两个决定,我们有4个特征和3个类别,因此输入层必有4个单元,输出层必有3个单元。我们只需要定义隐藏层。本例中,我们只定义一个隐藏层,该层包含16个单元。从GPU的角度考虑,16是一个完整的数!在使用神经网络的过程中,你会发现许多2的指数值被使用。

我们将以最常见的方式定义我们的模型:作为层的顺序堆栈。另一种方式是作为一个计算图,但我们在这里坚持Sequential()。

model = Sequential()

接下来的两行定义了输入层的大小(input_shape=(4,))、隐藏层的大小和激活函数的种类。

model.add(Dense(16, input_shape=(4,)))
model.add(Activation('sigmoid'))

下一行定义了输出层的大小和激活函数的种类。

model.add(Dense(3))
model.add(Activation('softmax'))

最后,我们指定优化策略和损失函数进行优化。我们还指定了模型工作是的计算准确度。

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

3、使用神经网络分类器

现在我们定义了模型结构并编译了它,这样我们得到一个对象,其API几乎与scikit-learn中的分类器完全一致。特别的,该对象有.fit()和.predict()方法。现在让我们训练该模型。

神经网络的训练通常涉及到”mini-batching“的概念,指的是神经网络一次只读取训练集的一个子集,训练模型调整权重,随后再读取训练集的下一个子集。神经网络完整的读取整个训练集一次,称之为一个”epoch“。Mini-batch/epoch策略的调整,是神经网络训练中的一个难点。但在本例中,我们设定mini-batch=1,则该策略变成经典的随机梯度下降策略。神经网络每次从训练集读取一个花的样本,并立即调整网络权重。

下一行代码中的参数verbose=0也可以移除。注意,如果你希望实验mini-batch/epoch策略,你需要重新运行前面的代码段,重新编译模型(model.compile)并初始化模型权重。


model.fit(train_X, train_y_ohe, nb_epoch=100, batch_size=1, verbose=0)

对于一些基本的方法函数,编译好的Keras模型和scikit-learn分类器之间唯一的语法API差异是,Keras中与scikit-learn.score()方法等效的方法是.evaluate()。

Evaluate()返回损失函数和我们在编译模型是要求的任何其他度量。在本例中,我们要求的是正确率(accuracy),可以与我们从scikit-learn的LogisticRegressionCV分类器的.score()方法中获得的正确率进行比较。

loss, accuracy = model.evaluate(test_X, test_y_ohe, verbose=0)
print("Accuracy = {:.2f}".format(accuracy))
正确率大概等于0.97.


可以看到,神经网络模型的测试精度优于简单逻辑回归分类器。

但是也隐藏了神经网络的危险之一:过度拟合。如果有一些过度拟合,可以通过添加dropout(这也是内置于Keras)来处理。

 

4、下一步应该做什么?

此处我们构建了一个非常简单的前馈神经网络。想要进行更多的实验,可以加载手写数字的MNIST数据库,看看是否能够击败标准的scikit-learn分类器。与Iris数据集不同,这种情况下神经网络的功率和相对复杂性是合理的。参考链接:

https://github.com/wxs/keras-mnist-tutorial/blob/master/MNIST%20in%20Keras.ipynb

Keras还有别的层允许你建立模型:

卷积层,其给出计算机垂直问题的最先进的结果;

循环层,其特别好地适合于语言建模和其他序列数据。

实际上,神经网络的一个关键力量(以及纯粹的预测能力)是它们的可组合型。使用像Keras这样的高级库,创建一个非常不同的网络只需要几秒钟的工作。模型可以像乐高构建一样。

Have fun!

参考文献1https://zhuanlan.zhihu.com/p/23748037

参考文献2https://github.com/fchollet/keras-resources

参考文献3https://github.com/fastforwardlabs/keras-hello-world/blob/master/kerashelloworld.ipynb

参考文献4http://keras-cn.readthedocs.io/en/latest/


猜你喜欢

转载自blog.csdn.net/lixiaowang_327/article/details/54094235
今日推荐