小牛的学习笔记---声纳数据分析

假如想象 提交于 2020-03-17 00:29:24

本讲内容:

  • 如何加载和准备数据
  • 如何创建一个基线神经网络
  • 如何使用scikit-learn和k-fold交叉验证评估Keras模型
  • 数据准备如何提升你的模型性能
  • 如何调整网络拓扑结构可以提高模型的性能试验

1.数据集描述

声纳数据集区分岩石和金属,输出变量是一个字符串“M”和“R”我岩石,它将需要转化为整数 1 和 0 。

2.导包

import numpy
import pandas
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.model_selection import cross_val_score#交叉验证的分数结果
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import StratifiedKFold#用于交叉验证
#from sklearn.preprocessing import StandardScaler#标准化
#from sklearn.pipeline import Pipeline

3.读数据

seed = 7
numpy.random.seed(seed)#总得到相同的随机数序列

dataframe = pandas.read_csv("sonar.csv", header=None) # 加载数据集,用的数据框,header=None:第一行的数据列名去掉
dataset = dataframe.values
#将列向量分割成60输入变量(X)和1个输出变量(Y)
X = dataset[:, 0:60].astype(float) # 分割为60个输入变量,属性个数为60,转化为浮点类型
Y = dataset[:, 60] # 1个输出变量,输出变量是字符串类型,后面要把r,m转化成0,1

我们可以使用从scikit-learn LabelEncoder类。这个类通过 fit() 函数获取整个数据集模型所需的编码,然后使用transform()函数应用编码来创建一个新的输出变量。

#不是数值类型要进行转换,类别标签数值化,使类别标签转化为数字标签
encoder = LabelEncoder()
encoder.fit(Y)
encoded_Y = encoder.transform(Y)#Y进行编码,转化为新的输出变量,为0,1

4.准备好使用Keras创建我们的神经网络模型

# 基准模型
def create_baseline():
    #create model创建模型
    model = Sequential()#定义基准模型
    model.add(Dense(60, input_dim=60, kernel_initializer='normal', activation='relu'))#60个全连接隐含层
    model.add(Dense(30, kernel_initializer='normal', activation='sigmoid'))
    model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))
    # Compile model编译模型
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])#loss='binary_crossentropy'对数损失函数;optimizer='adam'优化函数,做梯度下降
    return model

5.评估模型

交叉验证
K-fold交叉评估模型验证
10交叉:把数据分成10份,每次取出9份做训练,留一份做测试,轮流取,直到每一份都有且仅有做过一次测试,这样一共轮流10次

# evaluate model with standardized dataset
#start_time = time.time()
estimator = KerasClassifier(build_fn=create_baseline, nb_epoch=100, batch_size=5, verbose=0)#build_fn创建基线模型,nb_epoch=100指迭代100次;
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)#n_splits=10 10份;shuffle=True,随机打乱分random_state=seed;定义交叉验证怎么分
results = cross_val_score(estimator, X, encoded_Y, cv=kfold) 
print("Baseline: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))#结果的精确度和平均标准差打印出来,10个结果的平均数是一轮下来交叉验证的最终结果
#end_time = time.time()
#print"用时: ", end_time - start_time

batch_size调参:首先,如果训练集较小,直接使用batch梯度下降法(batch size 等于样本集大小)。如果样本数目较大,一般的mini-batch大小为64到512。考虑到电脑内存设置和使用的方式,如果mini-batch大小是2的 n 次方,代码会运行地快一些。当内存不够的时候要选取小的batch值。

输出结果:相当低。。。。。。结果未知
在这里插入图片描述

5.带有数据准备地重新运行基准模型

使用scikit-learn 的 StandardScaler 类来标准化声纳数据集。
标准化:让数据标准化同一个尺度,使每个属性的平均值为0,方差为1。
在训练集而不是整个数据集上对数据进行标准化, 通过运行交叉验证和训练过的标准化数据去准备“未知”的训练数据。这让标准化在交叉验证中成为模型准备的一步, 也防止了算法在评估期间获得了数据准备过程对测试集的记忆。
利用 scikit-learn 的 Pipeline 类来实现这个过程。Pipeline 是一个包装器, 在交叉验证过程的执行一个或多个模型。在这里,我们可以定义一个Pipeline 带有一个tandardScaler, 后面紧跟着就是我们的神经网络模型。

from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline#pipeline为包装器
numpy.random.seed(seed)
estimators = []
estimators.append(('standardize', StandardScaler()))#标准化的方式,最后一个函数,把数据放到平均值标准差为1,0
estimators.append(('mlp', KerasClassifier(build_fn=create_baseline, nb_epoch=100, batch_size=5, verbose=0)))#mlp为多层感知机,后面是训练方式
pipeline = Pipeline(estimators)#把上述两行程序都装进去,标准化的过程和训练方式全部装进去
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=seed)#5交叉验证
results = cross_val_score(pipeline, X, encoded_Y, cv=kfold)#采用交叉验证的方式去运行
print("Standardized: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
#end_time = time.time()
#print"用时: ", end_time - start_time

结果显示:
在这里插入图片描述

优化模型:

注释掉隐藏层30个神经元的部分得出的结果明显提升

def create_baseline():
    #create model
    model = Sequential()
    model.add(Dense(60, input_dim=60, kernel_initializer='normal', activation='relu'))
    #model.add(Dense(30, kernel_initializer='normal', activation='sigmoid'))
    model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))
    # Compile model
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

结果显示:
在这里插入图片描述
注:一般评估一个更大型的网络:对模型做调整,额外再隐藏层加一个较小的隐藏层,性能应该有很好的提升,但是这里去掉了隐藏层性能却得到很好的提升,因为交叉验证划分数据集是随机的。
这里原本:60 input->[60->30]->1 output变为60 input->[60]->1 output 居然性能提升了。。。。!!!

评估一个更小型的网络:
限制第一层的特征数量,将基准模型的60个输入变量减少到30,迫使神经网络从输入数据中提取最重要的结构,结果稍微提升

def create_baseline():
    #create model
    model = Sequential()
    model.add(Dense(30, input_dim=60, kernel_initializer='normal', activation='relu'))
    model.add(Dense(1, kernel_initializer='normal', activation='sigmoid'))
    # Compile model
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

结果显示:
在这里插入图片描述
所以神经网络的结构会影响性能 ,但目前为止没有好的方法告诉你,怎么改网络结构性能会提升,只有唯一的办法:多试
改代码,调参数。
原创中文链接:利用人工神经网络框架Keras解决二分类问题 —— Jinkey 翻译

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!