赵走x博客
网站访问量:151933
首页
书籍
软件
工具
古诗词
搜索
登录
深入浅出Python机器学习:31、自动特征选择
深入浅出Python机器学习:30、数据“升维”
深入浅出Python机器学习:29、数据表达
深入浅出Python机器学习:28、聚类算法
深入浅出Python机器学习:27、特征提取
深入浅出Python机器学习:26、数据降维
深入浅出Python机器学习:25、数据预处理
深入浅出Python机器学习:24、神经网络实例一一手写识别
深入浅出Python机器学习:23、神经网络的原理及使用
深入浅出Python机器学习:22、神经网络的前世今生
深入浅出Python机器学习:21、SVM 实例一一波士顿房价回归分析
深入浅出Python机器学习:20、SVM 的核函数与参数选择
深入浅出Python机器学习:19、支持向量机SVM 基本概念
深入浅出Python机器学习:18、随机森林实例一一要不要和中目亲对象进一步发展
深入浅出Python机器学习:17、随机森林
深入浅出Python机器学习:16、决策树
深入浅出Python机器学习:15、朴素贝叶斯实战一一判断肿瘤是良性还是恶性
深入浅出Python机器学习:14、朴素贝叶斯算法的不同方法
深入浅出Python机器学习:13、朴素贝叶斯基本概念
深入浅出Python机器学习:12、使用L1 正则化的线性模型一一套索回归
深入浅出Python机器学习:11、使用L2 正则化的线性模型一一岭回归
深入浅出Python机器学习:10、最基本的线性模型一一线性回归
深入浅出Python机器学习:9、线性模型的墓本概念
深入浅出Python机器学习:8、K 最近邻算法项目实战一一酒的分类
深入浅出Python机器学习:7、K最近邻算法用于回归分析
深入浅出Python机器学习:6、K最近邻算法处理多元分类任务
深入浅出Python机器学习:5、k最近邻算法在分类任务中的应用
深入浅出Python机器学习:4、K 最近邻算法的原理
深入浅出Python机器学习:3、一些必需库的安装及功能简介
深入浅出Python机器学习:2、基于python i吾言的环境配置
深入浅出Python机器学习:1、概述
人脸数据集加载faces = fetch_lfw_people()报错
31、直方图
74、插件开发:Android端API实现
Python3之socket编程--3:基于UDP的套接字
15、使用 jQuery 处理 Ajax 请求
深入浅出Python机器学习:23、神经网络的原理及使用
资源编号:75920
人工智能
深入浅出Python机器学习
热度:94
借“深度学习”之名重新回到大家视线范围的神经网络包含了诸多算法,而在本章中,我们重点向大家介绍的是“多层感知器”,即MLP 算法,以此作为读者朋友们进入深度学习的起点, MLP 也被称为前馈神经网络,或者被泛称为神经网络。
借“深度学习”之名重新回到大家视线范围的神经网络包含了诸多算法,而在本章中,我们重点向大家介绍的是“多层感知器”,即MLP 算法,以此作为读者朋友们进入深度学习的起点, MLP 也被称为前馈神经网络,或者被泛称为神经网络。 # 1、神经网络的原理 不知道读者朋友们是否还记得我们在第4 章中介绍的线性模型的一般公式: $$ \hat{y} $$=w[0]$$\cdot$$x[0]+w[1]$$\cdot$$x[1]+$$\cdots$$+w[p]$$\cdot$$x[p]+b 其中$$\hat{y}$$表示对y 的估计值, x[0] 到x[p] 是样本特征值, w 表示每个特征值的权重, y-hat可以看成是所有特征值的加权求和,我们可以用图8 - 5 表示这个过程。  图8 -5 线性回归的图像表示 在图8- 5 中,输入的特征和预测的结果用节点进行表示,系数w 用来连接这些节点。而在MLP 模型中,算法在过程里添加了隐藏层( Hidden Layers ),然后在隐藏层重复进行上述加权求和计算,最后再把隐藏层所计算的结果用来生成最终结果,如图8-6 所示。  图8-6 带l 个隐藏层的MLP 模型 这样一来,模型要学习的特征系数,或者说权重,就会多很多了。大家可以看到在每一个输入的特征和隐藏单元( hidden unit )之间,都有一个系数,这一步也是为了生成这些隐藏单元。而每个隐藏单元到最终结果之间,也都有一个系数。而计算一系列的加权求和和计算单一的加权求和。 # 2、 神经网络中的非线性矫正 从数学的角度来说,如果每一个隐藏层只是进行加权求和,得到的结果和普通的线性模型不会有什么不同。所以为了让模型能够比普通线性模型更强大一些,我们还需要进行一点处理。 这种处理方法是: 在生成隐藏层之后,我们要对结果进行非线性矫正( rectifying nonlinearity ),简称为relu (rectified linear unit)或者是进行双曲正切处理( tangens hyperbolicus ),简称为tanh。通过这两种方式处理后的结果用来计算最终结果y。这样讲实在过于抽象,我们还是用图像来进行直观展示,在Jupyter Notebook 中输入代码如下: ``` # 导入numpy import numpy as np # 导入画图工具 import matplotlib.pyplot as plt # 生成一个等差数列 line = np.linspace(-5, 5, 200) # 画出非线性矫正的图形表示 plt.plot(line,np.tanh(line),label='tanh') plt.plot(line,np.maximum(line,0),label='relu') # 设置图注位置 plt.legend(loc='best') # 设置横纵轴标题 plt.xlabel('x') plt.ylabel('relu(x) and tanh(x)') # 显示图形 plt.show() ``` 运行结果:  图8-7 对特征进行ta由和relu 处理 {结果分析]从图中可以看出, tanh 函数把特征x 的值压缩进- 1 到I 的区间内,- 1代表的是x 中较小的数值,而1代表x 中较大的数值。relu 函数则索性把小于0 的x 值全部去掉,用0 来代替。这两种非线性处理的方法,都是为了将样本特征进行简化,从而使神经网络可以对复杂的非线性数据集进行学习。 那么这样一来,我们刚才所看到的公式: $$ \hat{y} $$=w[0]$$\cdot$$x[0]+w[1]$$\cdot$$x[1]+$$\cdots$$+w[p]$$\cdot$$x[p]+b 经过tanh 处理后,就会变成下面的样子: h[0]=tanh(w[0]$$\cdot$$x[0]+w[1]$$\cdot$$x[1]+$$\cdots$$++w[p]$$\cdot$$x[p]+b) h[1]=tanh(w[0]$$\cdot$$x[0]+w[1]$$\cdot$$x[1]+$$\cdots$$++w[p]$$\cdot$$x[p]+b) h[2]=tanh(w[0]$$\cdot$$x[0]+w[1]$$\cdot$$x[1]+$$\cdots$$++w[p]$$\cdot$$x[p]+b) ... $$ \hat{y} $$=v[0]$$\cdot$$h[0]+v[1]$$\cdot$$h[1]+$$\cdots$$++v[n]$$\cdot$$h[n] 在权重系数w 之外,我们又多了一个权重系数v,用来通过隐藏层h 来计算y-hat 的结果。在模型中, w 和v 都是通过对数据的学习所得出的。而用户所要设置的参数,就是隐藏层中节点的数量。一般来讲,对于小规模数据集或者简单数据集,节点数量设置为10 就己经足够了,但是对于大规模数据集或者复杂数据集来说,有两种方式可供选择: * 一是增加隐藏层中的节点数量,比如增加到1 万个; * 二是添加更多的隐藏层,如图8 - 8所示的样子。  图8 -8 对模型添加1新的隐藏层 在大型神经网络当中,往往有很多这样的隐藏层,这也是“深度学习”中“深度”二字的来源。 # 3、神经网络的参数设置 下面我们就以MLP 算法中的MLP 分类器为例,研究一下MLP 分类器模型的使用方法。这次我们还是使用熟悉的酒的数据集。在Jupyter Notebook 中输入代码如下: ``` # 导入MLP神经网络 from sklearn.neural_network import MLPClassifier # 导入红酒数据集 from sklearn.datasets import load_wine # 导人数据集拆分工具 from sklearn .model_selection import train_test_split wine= load_wine() X =wine.data[ :, : 2] y = wine.target # 下面我们拆分数据集 X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0) # 接下来定义分类器 mlp=MLPClassifier(solver='lbfgs') mlp.fit(X_train,y_train) print(mlp) ``` 运行结果: ``` 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=(100,), learning_rate='constant', learning_rate_init=0.001, max_iter=200, momentum=0.9, nesterovs_momentum=True, power_t=0.5, random_state=None, shuffle=True, solver='lbfgs', tol=0.0001, validation_fraction=0.1, verbose=False, warm_start=False) ``` [结果分析] 和我们之前使用的算法一样, MLP 分类器也把它自己的参数给我们返了回来。其中solver = ' lbfgs ’是我们在代码中指定的,而其他的参数都是算法默认的。 下面我们重点看一下各个参数的含义: * activation 是8. 2 .2 节中提到的将隐藏单元进行非线性化的方法, 一共有4 种:“ identity ”“logistic ” “ tanh "以及“ relu ”, 而在默认情况下,参数值是“ relu ” 。其中“ identity " 对样本特征不做处理, 返回值是f(x) =x;而“ logistic "返回的结果会是f (x)= 1/[ I1+ exp(-x) ] , 这种方法和tanh 类似, 但是经过处理后的特征值会在0 和1 之间。其余两个参数值, tanh 和relu 我们已经介绍过, 在这里就不重复了。 * alpha 值和线性模型的alpha 值是一样的, 是一个L2 惩罚项, 用来控制正则化的程度, 默认的数值是0.0001 。 * 这里着重介绍一下hidden_layer_sizes 参数, 默认情况下, hidden_layer_sizes 的值是[ 100 ,] 这意味着模型中只有一个隐藏层,而隐藏层中的节点数是100 。如果我们给hidden _ layer_ sizes 定义为[ 10 , 10] ,那就意味着模型中有两个隐藏层, 每层有10 个节点。 现在用图像展示一下MLP 分类的情况,输入代码如下: ``` # 导入MLP神经网络 from sklearn.neural_network import MLPClassifier # 导入红酒数据集 from sklearn.datasets import load_wine # 导人数据集拆分工具 from sklearn.model_selection import train_test_split wine = load_wine() X = wine.data[:, : 2] y = wine.target # 下面我们拆分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) # 接下来定义分类器 mlp = MLPClassifier(solver='lbfgs') mlp.fit(X_train, y_train) # 导入画图工具 import matplotlib.pyplot as plt import numpy as np from matplotlib.colors import ListedColormap # 使用不同色块表示不同分类 cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF']) cmap_bold = ListedColormap(['#FFOOOO', '#OOFFOO', '#OOFFOO']) x_min, x_max = X_train[:, 0].min() - 1, X_train[:, 0].max() + 1 y_min, y_max = X_train[:, 1].min() - 1, X_train[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, .02), np.arange(y_min, y_max, .02)) Z = mlp.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure() plt.pcolormesh(xx, yy, Z, cmap=cmap_light) # 将数据特征用散点图表示出来 plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', s=60) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) # 设定图题 plt.title("MLPClassifier : solver=lbfgs") # 显示图形 plt.show() ``` 运行代码,会得到结果如图8 - 10 所示。  图8 -10 隐藏层节点数为100 时的MLP 分类器 下面我们试试把隐藏层的节点数变少,如减少至10 个,看会发生什么。在JupyterNotebook 中输入代码如下: ``` # 导入MLP神经网络 from sklearn.neural_network import MLPClassifier # 导入红酒数据集 from sklearn.datasets import load_wine # 导人数据集拆分工具 from sklearn.model_selection import train_test_split wine = load_wine() X = wine.data[:, : 2] y = wine.target # 下面我们拆分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) # 接下来定义分类器 # 设定隐藏层中的节点数为10 mlp = MLPClassifier(solver='lbfgs',hidden_layer_sizes=[10]) mlp.fit(X_train, y_train) # 导入画图工具 import matplotlib.pyplot as plt import numpy as np from matplotlib.colors import ListedColormap # 使用不同色块表示不同分类 cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF']) cmap_bold = ListedColormap(['#FFOOOO', '#OOFFOO', '#OOFFOO']) x_min, x_max = X_train[:, 0].min() - 1, X_train[:, 0].max() + 1 y_min, y_max = X_train[:, 1].min() - 1, X_train[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, .02), np.arange(y_min, y_max, .02)) Z = mlp.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure() plt.pcolormesh(xx, yy, Z, cmap=cmap_light) # 将数据特征用散点图表示出来 plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', s=60) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) # 设定图题 plt.title("MLPClassifier : hidden_layer_sizes=10") # 显示图形 plt.show() ``` 运行结果:  图8-11 隐藏层节点数为10 时的MLP 分类器 [结果分析] 如果将图8 -11 和图8 -10 进行对比,你就会发现分类器生成的决定边界看起来很不一样了。节点数为10 的时候,决定边界丢失了很多细节。我们可以这样理解,在每一个隐藏层当中,节点数就代表了决定边界中最大的直线数,这个数值越大,则决定边界看起来越平滑。当然,除了增加单个隐藏层中的节点数之外,还有两种方法可以 让决定边界更细腻: 一个是增加隐藏层的数量;另一个是把activation 参数改为tanh ,下面我们逐一展示一下。 现在我们试着给MLP 分类器增加隐藏层数量,如增加到2 层。在Jupyter Notebook中输入代码如下: ``` # 导入MLP神经网络 from sklearn.neural_network import MLPClassifier # 导入红酒数据集 from sklearn.datasets import load_wine # 导人数据集拆分工具 from sklearn.model_selection import train_test_split wine = load_wine() X = wine.data[:, : 2] y = wine.target # 下面我们拆分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) # 接下来定义分类器 # 设定隐藏层中的节点数为10 mlp = MLPClassifier(solver='lbfgs',hidden_layer_sizes=[10,10]) mlp.fit(X_train, y_train) # 导入画图工具 import matplotlib.pyplot as plt import numpy as np from matplotlib.colors import ListedColormap # 使用不同色块表示不同分类 cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF']) cmap_bold = ListedColormap(['#FFOOOO', '#OOFFOO', '#OOFFOO']) x_min, x_max = X_train[:, 0].min() - 1, X_train[:, 0].max() + 1 y_min, y_max = X_train[:, 1].min() - 1, X_train[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, .02), np.arange(y_min, y_max, .02)) Z = mlp.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure() plt.pcolormesh(xx, yy, Z, cmap=cmap_light) # 将数据特征用散点图表示出来 plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', s=60) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) # 设定图题 plt.title("MLPClassifier :hidden_layer_sizes=[10,10]") # 显示图形 plt.show() ``` 运行结果:  图8 -12 两个隐藏层,每层IO 个节点的MLP 分类器 {结果分析]和图8-11 对比,能够看到隐藏层的增加带来的结果就是决定边界看起来更加细腻,下面我们再使用activation=' tanh ’ 实验一下。 输入代码如下: ``` # 导入MLP神经网络 from sklearn.neural_network import MLPClassifier # 导入红酒数据集 from sklearn.datasets import load_wine # 导人数据集拆分工具 from sklearn.model_selection import train_test_split wine = load_wine() X = wine.data[:, : 2] y = wine.target # 下面我们拆分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) # 接下来定义分类器 # 设定隐藏层中的节点数为10 mlp = MLPClassifier(solver='lbfgs',hidden_layer_sizes=[10,10],activation='tanh') mlp.fit(X_train, y_train) # 导入画图工具 import matplotlib.pyplot as plt import numpy as np from matplotlib.colors import ListedColormap # 使用不同色块表示不同分类 cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF']) cmap_bold = ListedColormap(['#FFOOOO', '#OOFFOO', '#OOFFOO']) x_min, x_max = X_train[:, 0].min() - 1, X_train[:, 0].max() + 1 y_min, y_max = X_train[:, 1].min() - 1, X_train[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, .02), np.arange(y_min, y_max, .02)) Z = mlp.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure() plt.pcolormesh(xx, yy, Z, cmap=cmap_light) # 将数据特征用散点图表示出来 plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', s=60) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) # 设定图题 plt.title("MLPClassifier :hidden_layer_sizes=[10,10],activation='tanh'") # 显示图形 plt.show() ``` 运行结果:  图8-13 两个节点为10 的隐藏层, activat ion 为tanh 的MLP 分类器 [结果分析] 从医I 8-13 中可以看出,将activation 参数修改为tanh 之后,分类器的决定边界完全变成了平滑的曲线。这就是我们对样本特征进行双曲线正切化后的结果。 当然除了上述方法之外,我们还可以通过调节a lpha 值来进行模型复杂度控制, 默认的alpha 值是0 .0001 ,现在试着把alpha 值增加,如增加到1 ,看会发生什么样的变化。 输入代码如下: ``` # 导入MLP神经网络 from sklearn.neural_network import MLPClassifier # 导入红酒数据集 from sklearn.datasets import load_wine # 导人数据集拆分工具 from sklearn.model_selection import train_test_split wine = load_wine() X = wine.data[:, : 2] y = wine.target # 下面我们拆分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) # 接下来定义分类器 # 设定隐藏层中的节点数为10 mlp = MLPClassifier(solver='lbfgs',hidden_layer_sizes=[10,10], activation='tanh',alpha=1) mlp.fit(X_train, y_train) # 导入画图工具 import matplotlib.pyplot as plt import numpy as np from matplotlib.colors import ListedColormap # 使用不同色块表示不同分类 cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF']) cmap_bold = ListedColormap(['#FFOOOO', '#OOFFOO', '#OOFFOO']) x_min, x_max = X_train[:, 0].min() - 1, X_train[:, 0].max() + 1 y_min, y_max = X_train[:, 1].min() - 1, X_train[:, 1].max() + 1 xx, yy = np.meshgrid(np.arange(x_min, x_max, .02), np.arange(y_min, y_max, .02)) Z = mlp.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure() plt.pcolormesh(xx, yy, Z, cmap=cmap_light) # 将数据特征用散点图表示出来 plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k', s=60) plt.xlim(xx.min(), xx.max()) plt.ylim(yy.min(), yy.max()) # 设定图题 plt.title("MLPClassifier :hidden_layer_sizes=[10,10],activation='tanh',alpha=1") # 显示图形 plt.show() ``` 运行结果:  图8- 14 将alpha 值增加到l 之后的决定边界 [结果分析]从图8-14 中可以看出,增加alpha 参数的数值,会加大模型正则化的程度, 也就会让模型更加简单。到目前为止, 我们有4 种方法可以调节模型的复杂程度了,第一种是调整神经网络每一个隐藏层上的节点数, 第2 种是调节神经网络隐藏层的层数,第3 种是调节activation 的方式,而第4 种,便是通过调整alpha 值来改变模型正则化的程度。 > 由于神经网络算法中,样本特征的权重是在模型开始学习之前,就已经随机生成了。而随机生成的权重会导致模型的形态也完全不一样。所以如果我们不指定random_state的话,即使模型所有的参数都是相同的,生成的决定边界也不一样。所以如果重新运行我们前面的代码,也会得到不同的结果。不过不用担心,只要模型的复杂度不变,其预测结果的准确率不会受什么影晌。