【scikit-learn】如何用Python和SciKit Learn 0.18实现神经网络

本教程的代码和数据来自于 Springboard 的博客教程。本文的作者为 Jose Portilla,他是网络教育平台 Udemy 一门数据科学类课程的讲师。

GitHub 链接:https://github.com/Rogerh91/Springboard-Blog-Tutorials/blob/master/Neural%20Networks%20/JMPortilla_SpringBoard_Blog_Neural_Network.ipynb

最受欢迎的 Python 机器学习库是 SciKit Learn。最新版本(0.18)支持神经网络模型。在本文中,我们将了解神经网络的工作方式以及如何使用 Python 编程语言和最新版本的 SciKit-Learn 来实现它们。了解这篇文章需要 Python 基础知识,而且它也有助于积累 SciKit Learn 的经验。

本文的代码及结果用 Jupyter Notebook 编写,In [*]: 代表输入的代码,Out[*]: 代表程序输出的结果。

神经网络

人工神经网络是一种模仿生物神经网络学习模式的机器学习框架:可以将它们粗略地近似为人类在学习中的思维活动。生物神经网络具有相互连接的神经元,神经元的树突结构接收输入,并基于这些输入产生输出信号,通过轴突传输到另一个神经元。我们将尝试通过人工神经网络(ANN,简称神经网络)来模拟这个过程。神经网络是深度学习的基础,它属于机器学习范畴,是当今最令人兴奋的技术进步之一。在利用 Python 创建神经网络之前,让我们先从最基本形式——单个感知器(perceptron)开始。下面是感知器的介绍。

感知器

一个感知器完整的结构包括一个或多个输入、偏置、激活函数和一个输出。感知器接收输入,并将它们与权重相乘,然后传递到激活函数以产生输出。有许多可能的激活函数可供选择,如 logistic 函数、三角函数、阶跃函数(step function)等。我们需要确保向感知器模型添加偏置(用来调整激活函数的位置),它是不受输入影响的常数型权重,能使预测模型的拟合效果达到最佳。下面的图表展示了感知器的结构:

【scikit-learn】如何用Python和SciKit Learn 0.18实现神经网络_第1张图片

一旦得到输出,我们可以将其与一个已知的标签进行比较,并相应地调整权重(开始时通常用随机数初始化权重值)。重复此过程,直到达到允许的最大迭代次数或可接受的错误率。

为了创建一个神经网络,我们可以从叠加多层感知器开始,创建一个神经网络的多层感知器模型。它包含了传入数据的输入层和产生结果的输出层。输入层和输出层之间的任何层都被称为隐藏层,因为它们不能直接「看到」数据的特征输入或输出。下图直观地反映了输入层、隐藏层和输出层的关系(来源:维基百科)。

【scikit-learn】如何用Python和SciKit Learn 0.18实现神经网络_第2张图片

由于神经网络的特点,神经网络在 GPU 上的表现往往比 CPU 好。可惜的是,SciKit-learn 框架不支持 GPU 加速优化。如果你想使用 GPU 和分布式模型,请参考其它框架,例如谷歌的开源框架 TensorFlow。

让我们继续用 Python 和 SciKit-learn 创建神经网络。

SciKit-Learn

本教程使用了最新版本的 SciKit-Learn(> 0.18),它可以通过 pip 或 conda 来轻松安装,也可以参考官方安装文档(http://scikit-learn.org/stable/install.html)获取完整的详细信息。

Anaconda 和 iPython Notebook

Anaconda 的 iPython Notebook(Jupyter Notebook)软件可以轻松地帮助你安装 SciKit-Learn 以及所需的所有工具。下面的链接中有如何安装这些软件的教程(https://www.safaribooksonline.com/blog/2013/12/12/start-ipython-notebook/),以便你快速在 Python 中构建神经网络。

数据

本文的分析主题为葡萄酒。葡萄酒伪劣品是一件非常现实的事情,让我们来看看 Python 的神经网络是否可以帮助解决这个问题。我们将使用 UCI 机器学习库中的葡萄酒数据集。它具有不同葡萄酒的各种化学特征,均在意大利同一地区生长,但数据标签分类为三种不同的品种。我们将尝试建立一个可以根据其化学特征对葡萄酒品种进行分类的神经网络模型。

数据集链接:https://archive.ics.uci.edu/ml/datasets/Wine

第一步,先导入数据

importpandasaspd

wine = pd.read_csv('wine_data.csv', names = ["Cultivator", "Alchol", "Malic_Acid", "Ash", "Alcalinity_of_Ash", "Magnesium", "Total_phenols", "Falvanoids", "Nonflavanoid_phenols", "Proanthocyanins", "Color_intensity", "Hue", "OD280", "Proline"])

查看数据结构:

In [9]:

wine.head()

Out[9] 为了符合本文的格式,我们截取了部分列(实际数据有更多列):

【scikit-learn】如何用Python和SciKit Learn 0.18实现神经网络_第3张图片

In [12]:

wine.describe().transpose()

Out[12]为了符合本文的格式,从输出中去掉了标准偏差(std)和计数列:

【scikit-learn】如何用Python和SciKit Learn 0.18实现神经网络_第4张图片

In [13]:

# 178 data points with 13 features and 1 label columnwine.shape

Out[13]:

(178, 14)

将数据的标签设置为 y:

In [14]:

X=wine.drop('Cultivator',axis=1)

y=wine['Cultivator']

准备训练集和测试集

下面将数据分成训练集和测试集,这可以通过使用 SciKit-Learn 的 model_selection 中的 train_test_split 函数轻松完成:

In [15]:

fromsklearn.model_selectionimporttrain_test_split

In [16]:

X_train,X_test,y_train,y_test=train_test_split(X,y)

数据预处理

如果数据没有经过标准化,则神经网络可能在达到允许的最大迭代次数时仍未收敛。多层感知器对特征尺度(scale)敏感,因此强烈建议归一化数据。请注意,测试集采用相同的尺度变换才有意义。有很多不同的数据标准化方法,我们将使用内置的 StandardScaler 进行标准化。

In [17]:

fromsklearn.preprocessingimportStandardScaler

In [18]:

scaler=StandardScaler()

In [19]:

# Fit only to the training data

scaler.fit(X_train)

Out[19]:

StandardScaler(copy=True, with_mean=True, with_std=True)

In [20]:

# Now apply the transformations to the data:

X_train=scaler.transform(X_train)

X_test=scaler.transform(X_test)

训练模型

现在我们来训练模型。SciKit-learn 使用 estimator(估计量)对象。我们将从 SciKit-Learn 的 neural_network 库导入我们的估计量(多层感知器分类器模型/MLP)。

In [21]:

fromsklearn.neural_networkimportMLPClassifier

接下来我们创建一个模型的实例,可以自定义很多参数,我们将只定义 hidden_layer_sizes 参数。此参数传入的是一个元组,表示计划在每个层的神经元数量,其中元组中的第 n 个元素表示 MLP 模型第 n 层中的神经元数量。有很多参数可供选择,但是为了简单起见,我们将选择具有相同数量神经元的 3 层神经网络,每层的神经元数量与数据的特征数相同(13),并将最大迭代次数设置为 500 次。

In [24]:

mlp=MLPClassifier(hidden_layer_sizes=(13,13,13),max_iter=500)

现在我们已经建立好模型,可以用训练集来拟合我们的模型,记住这些数据已被预处理和标准化:

In [25]:

mlp.fit(X_train,y_train)

Out[25]:

MLPClassifier(activation='relu', alpha=0.0001, batch_size='auto', beta_1=0.9, beta_2=0.999, early_stopping=False, epsilon=1e-08, hidden_layer_sizes=(13, 13, 13), learning_rate='constant', learning_rate_init=0.001, max_iter=500, momentum=0.9, nesterovs_momentum=True, power_t=0.5, random_state=None, shuffle=True, solver='adam', tol=0.0001, validation_fraction=0.1, verbose=False, warm_start=False)

输出结果中给出了模型的其它参数的默认值。我鼓励你尝试这些参数的不同取值,看看它们对 Python 神经网络有什么影响。

In [26]:

predictions=mlp.predict(X_test)

现在我们可以用 SciKit-Learn 自带的评价指标,如分类报告(classification report)和混淆矩阵(confusion matrix)来评估模型的性能:

In [27]:

fromsklearn.metricsimportclassification_report,confusion_matrix

In [28]:

print(confusion_matrix(y_test,predictions))[[17 0 0] [ 0 14 1] [ 0 0 13]]

In [29]:

print(classification_report(y_test,predictions))precision recall f1-score support 1 1.00 1.00 1.00 17 2 1.00 0.93 0.97 15 3 0.93 1.00 0.96 13avg / total 0.98 0.98 0.98 45

结果不错!看来测试集中我们只错误分类了 1 瓶葡萄酒!考虑到我们的 Python 神经网络的代码行很少,这个效果是非常好的。然而,多层感知器模型的缺点在于解释模型本身。例如,模型的权重和偏差与数据特征的关系以及哪些特征最重要将不容易解释。

如果想查看 MLP 训练模型得到的权重和偏差,使用 public 属性 coefs_ 和 intercepts_。

coefs_ 是权重矩阵的列表,其中索引 i 处的权重矩阵表示层 i 和层 i+1 之间的权重。

intercepts_ 是偏差向量的列表,其中索引 i 处的向量表示添加到层 i+1 的偏差值。

In [30]:

len(mlp.coefs_)

Out[30]:

4

In [31]:

len(mlp.coefs_[0])

Out[31]:

13

In [32]:

len(mlp.intercepts_[0])

Out[32]:

13

你可能感兴趣的:(Python)