八 过拟合与欠拟合实例

文章目录

  • 过拟合实例
  • Dropout抑制过拟合
    • 理论知识
    • 代码实现
  • 使用正则化抑制过拟合
  • 网络参数选择的总原则

过拟合实例

import keras
from keras import layers
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
data = pd.read_csv('./Desktop/Keras/Data/credit-a.csv', header=None)#该数据没有columns即头部,为避免将第一行当作头部标签所以加上header=None
  • 未加header=None
data.head()

八 过拟合与欠拟合实例_第1张图片

  • 加header=None
    八 过拟合与欠拟合实例_第2张图片
    0—14是特征,最后一列是预测目标
data.iloc[:, -1].unique()##查看目标种类,是二元分类

在这里插入图片描述
取出x,y

x = data.iloc[:, :-1].values #取出前15列 
##取出数值为ndarray形式,之前为DataFrame形式,Keras都可以接受
x

八 过拟合与欠拟合实例_第3张图片

##y = data.iloc[: , -1].values.reshape(-1, 1)
y = data.iloc[: , -1].replace(-1, 0).values.reshape(-1, 1)
##取出value,并将653个数据reshape为每个数据维度为1.reshape(-1,1)中-1是自动计算的意思,第二个1是维度为1
y

因为sigmoid输出是在(0,1)之间,因此我们需要将y中数据-1替换为0,所以用了replace(-1,0)

y.shape, x.shape

在这里插入图片描述
y中有653个长度为1的数据,x中有653个长度为15的数据

model = keras.Sequential()
model.add(layers.Dense(128, input_dim=15, activation='relu'))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.summary()

八 过拟合与欠拟合实例_第4张图片
隐藏层3层,有35201个参数训练

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['acc']
)
history = model.fit(x, y, epochs=1000)

八 过拟合与欠拟合实例_第5张图片
八 过拟合与欠拟合实例_第6张图片
可以看出在训练集上正确率很高

history.history.keys()##看一下history字典属性

在这里插入图片描述
绘制loss和acc曲线

plt.plot(history.epoch, history.history.get('loss'), c='r')##迭代次数,loss,红色
plt.plot(history.epoch, history.history.get('acc'), c='b')

八 过拟合与欠拟合实例_第7张图片
网络评价标准,对于未知数据的预测准确性,把已知数据分割,一部分数据训练,一部分数据预测
对数据进行分割

x_train = x[:int(len(x)*0.75)] ##切片分割 总长度*0.75 取数据前面的%75作为训练数据
x_test = x[int(len(x)*0.75):]
y_train = y[:int(len(x)*0.75)]
y_test = y[int(len(x)*0.75):]

看一下各数据有多大

x_train.shape, x_test.shape, y_train.shape, y_test.shape

在这里插入图片描述
划分率489行作为训练数据,164行作为测试数据
建立模型

model = keras.Sequential()
model.add(layers.Dense(128, input_dim=15, activation='relu'))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

编译模型

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['acc']
)

训练模型
history会把训练过程中随着epochs变化的loss和acc记录下来

history = model.fit(x_train, y_train, epochs=1000, validation_data=(x_test, y_test))

训练时候 validation_data=(x_test, y_test)可以把测试数据填进去,在训练过程中每个epoch之后把测试数据测试一下,看一下测试数据得分结果
八 过拟合与欠拟合实例_第8张图片
八 过拟合与欠拟合实例_第9张图片
画出测试,训练图的acc图

plt.plot(history.epoch, history.history.get('val_acc'), c='r', label='val_acc')
plt.plot(history.epoch, history.history.get('acc'), c='b', label='acc')
plt.legend()##添加图例

八 过拟合与欠拟合实例_第10张图片
测试数据某一刻震荡,训练数据不断提高,从图像中两条线的分离点产生过拟合

评价训练集效果

model.evaluate(x_train, y_train) #评价函数,可返回损失函数和准确率

在这里插入图片描述
可以得到在该模型上损失函数为0.09981269526341877,正确率0.9938650306748467

评价测试集结果

model.evaluate(x_test, y_test)

在这里插入图片描述
可以得到在该模型上损失函数为2.2119179903132067 ,正确率0.774390243902439
过拟合:在训练数据正确率非常高, 在测试数据上比较低

Dropout抑制过拟合

理论知识

随机丢弃一些隐藏单元,从而增强另一部分隐藏单元的学习
为什么Drupout可以解决过拟合
八 过拟合与欠拟合实例_第11张图片
八 过拟合与欠拟合实例_第12张图片
八 过拟合与欠拟合实例_第13张图片

代码实现

model = keras.Sequential()
model.add(layers.Dense(128, input_dim=15, activation='relu'))
model.add(layers.Dropout(0.5))##直接添加Droopout层,随机删除一半的神经元
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dropout(0.5))##直接添加Droopout层,随机删除一半的神经元
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dropout(0.5))##直接添加Droopout层,随机删除一半的神经元
model.add(layers.Dense(1, activation='sigmoid'))
model.summary() ##看一下当前网络构成

八 过拟合与欠拟合实例_第14张图片
编译模型

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['acc']
)
history = model.fit(x_train, y_train, epochs=1000, validation_data=(x_test, y_test))

评价模型
.

model.evaluate(x_train, y_train)##评价训练模型

在这里插入图片描述

model.evaluate(x_test, y_test) ##评价测试模型

在这里插入图片描述
可以看出加入Dropout层后训练准确率下降很多,测试准确率略微上升

绘出加入Dropout层后模型训练,测试过程acc变化图

plt.plot(history.epoch, history.history.get('val_acc'), c='r', label='val_acc')
plt.plot(history.epoch, history.history.get('acc'), c='b', label='acc')
plt.legend()

八 过拟合与欠拟合实例_第15张图片
从图片可以看出,测试和训练时acc值差别不大,添加Dropout层后测试数据得分会增加,有效抑制过拟合

使用正则化抑制过拟合

训练过程中抑制参数增长范围,不能使参数范围变化太大,在loss上添加一个权重规模的参数,使得网络在训练过程中参数范围不会无限扩大

L1正则:
loss = sabs(w1 + w2 + …) + mse
L2正则:
loss = s(w1
2 + w2**2 + …) + mse

添加前一项使得在训练过程中同时减小loss的同时,惩罚参数,使得参数不可以无限扩大,从而抑制过拟合,一般情况下使用L2正则

from keras import regularizers ##引入regularizers 方法
model = keras.Sequential()
model.add(layers.Dense(128, kernel_regularizer=regularizers.l2(0.001), input_dim=15, activation='relu'))
model.add(layers.Dense(128, kernel_regularizer=regularizers.l2(0.001), activation='relu'))
model.add(layers.Dense(128, kernel_regularizer=regularizers.l2(0.001), activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

kernel_regularizer=regularizers.l2(0.001)意思是使用L2正则,0.001是一个参数,代表惩罚力度,比如
loss = s(w1*2 + w2**2 + …) + mse 中的s=0.001,如果测试效果不好,则要继续改变这个参数大小

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['acc']
)
history = model.fit(x_train, y_train, epochs=1000, validation_data=(x_test, y_test))

八 过拟合与欠拟合实例_第16张图片
八 过拟合与欠拟合实例_第17张图片

model.evaluate(x_train, y_train)

在这里插入图片描述

model.evaluate(x_test, y_test)

在这里插入图片描述
这个测试效果甚至更差,需要改变正则化中参数继续测试,这里只谈方法,不再继续实验

网络参数选择的总原则

总的原则是: 保证神经网络容量足够拟合数据
神经网络容量:我们可以将网络的可训练参数当作神经网络容量,可训练神经网络参数越多,网络容量越大,神经网络拟合能力越强。神经网络隐藏单元越多,层数越多,拟合能力越强,容量越大
比如:
第一层4个,第二层也是4个神经元的网络

model = keras.Sequential()
model.add(layers.Dense(4, input_dim=15, activation='relu'))
model.add(layers.Dense(4,  activation='relu'))
model.add(layers.Dense(1, activation='sigmoid')

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['acc']`在这里插入代码片`
          
)
history = model.fit(x_train, y_train, epochs=1000, validation_data=(x_test, y_test))
model.evaluate(x_train, y_train)

在这里插入图片描述

model.evaluate(x_test, y_test)

在这里插入图片描述
可以看出这个网络中测试数据上得分甚至比之前很大的一个网络好

对于一个较小的数据我们使用一个较小的网络拟合更不容易引起过拟合。

网络容量太小,会引起欠拟合,拟合能力不够

比如:
第一层4个,第二层是1个神经元的网络,第二层可训练参数非常小

model = keras.Sequential()
model.add(layers.Dense(4, input_dim=15, activation='relu'))
model.add(layers.Dense(1,  activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['acc']
)
history = model.fit(x_train, y_train, epochs=1000, validation_data=(x_test, y_test))

八 过拟合与欠拟合实例_第18张图片
可以看出训练1000次,训练集正确率也才%57.46

网络参数选择的总原则

  1. 增大网络容量,直到过拟合
  2. 采取措施抑制过拟合
  3. 继续增大网络容量,直到过拟合

你可能感兴趣的:(Keras,深度学习)