神经网络由输入层(input layer),隐藏层(hidden layers),输出层(output layer)三部分组成,如下图。
输入层(input layer)是由训练集的样本特征向量传入。
每层由神经元(neuron)或单元(unit)组成。
经过连接节点的权重(weight)传入下一层,上一层的输出是下一层的输入,一层中的加权求和,然后根据非线性方程转化为下一层的输入。
即一个神经元,可以把它分成左半球和右半球两部分。左半球为上一层加权求和的结果,为此神经元的输入。右半球为加权求和结果即左半球值通过非线性方程转化后的值,为此神经元的输出。
这个非线性方程就是激活函数,通过激活函数就可以把线性的值转成非线性的值。
常用的激活函数有三种,Sigmoid,Tanh和ReLU。其中sklearn中神经网络默认选择的是ReLU。
下图为这三种激活函数的结果,可以看出:Sigmoid和Tanh都是曲线,Sigmoid是把x归一化到0到1范围,Tanh归一化到-1到1范围。ReLU是折线,若x<0则输出0,否则y=x。
MLP为多层感知器,我们首先来看只有一个隐含层的MLP,如下图。
和上面介绍过的一样,h0的输入值就是x0*w00+x1*w10+x2*w20+x3*w30,输出值就是用激活函数,即tanh(x0*w00+x1*w10+x2*w20+x3*w30)。
最后y的值就是前一层即隐含层的权重和。
多层MLP也就是有多个隐含层
初始化模型
ann_model = MLPClassifier(hidden_layer_sizes=[unit,], activation=’logistic’, solver=’lbfgs’, random_state=0)
训练模型
ann_model.fit(X_train, y_train)
参数:
①ANN建模
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.linear_model import LogisticRegression
# 加载数据集
fruits_df = pd.read_table('fruit_data_with_colors.txt')
X = fruits_df[['width', 'height']]
y = fruits_df['fruit_label'].copy()
# 将不是apple的标签设为0
y[y != 1] = 0
# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=1/4, random_state=0)
②单层ANN(MLP)
from sklearn.neural_network import MLPClassifier
from ml_visualization import plot_class_regions_for_classifier
# 神经元个数
units = [1, 10, 100]
for unit in units:
# 激活函数:relu, logistic, tanh
# 优化算法:lbfgs, sgd, adam。adam适用于较大的数据集,lbfgs适用于较小的数据集。
#初始化模型
ann_model = MLPClassifier(hidden_layer_sizes=[unit], activation='logistic', solver='lbfgs', random_state=0)
#训练模型
ann_model.fit(X_train, y_train)
print('神经元个数={},准确率:{:.3f}'.format(unit, ann_model.score(X_test, y_test)))
#用自己写的函数画出下图
plot_class_regions_for_classifier(ann_model, X_test.values, y_test.values, title='Unit={}'.format(unit))
结果:
上面的代码结果只有下图的第一行,第二行是把激活函数换成relu得到的结果,可以看到每层的节点个数越多,模型越复杂,越复杂就会导致过拟合现象。因此就要使用正则化防止过拟合,下面将介绍ANN如何防止过拟合。
③ 多层ANN
多层ann也就是把hidden_layer_sizes=[10, 10],这个参数的列表中多放几个数,放几个数就有几层
ann_model = MLPClassifier(hidden_layer_sizes=[10, 10], activation='relu', solver='lbfgs', random_state=0)
ann_model.fit(X_train, y_train)
print('准确率:{:.3f}'.format(ann_model.score(X_test, y_test)))
plot_class_regions_for_classifier(ann_model, X_test.values, y_test.values)
结果:
使用正则化防止ANN过拟合
sklearn中 alpha为正则化强度
我们通过下面的例子来看正则化对模型复杂度的影响
# alpha
aplhas = [0.001, 0.01, 0.1, 1.0]
for alpha in aplhas:
ann_model = MLPClassifier(hidden_layer_sizes=[100, 100], activation='tanh', solver='lbfgs', random_state=0,
alpha=alpha)
ann_model.fit(X_train, y_train)
print('alpha={},准确率:{:.3f}'.format(alpha, ann_model.score(X_test, y_test)))
plot_class_regions_for_classifier(ann_model, X_test.values, y_test.values, title='Alpha={}'.format(alpha))
从结果可以看到alpha值越大,模型越复杂,即正则化的程度越低