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
data.head()
data.iloc[:, -1].unique()##查看目标种类,是二元分类
x = data.iloc[:, :-1].values #取出前15列
##取出数值为ndarray形式,之前为DataFrame形式,Keras都可以接受
x
##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()
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['acc']
)
history = model.fit(x, y, epochs=1000)
history.history.keys()##看一下history字典属性
plt.plot(history.epoch, history.history.get('loss'), c='r')##迭代次数,loss,红色
plt.plot(history.epoch, history.history.get('acc'), c='b')
网络评价标准,对于未知数据的预测准确性,把已知数据分割,一部分数据训练,一部分数据预测
对数据进行分割
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
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之后把测试数据测试一下,看一下测试数据得分结果
画出测试,训练图的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()##添加图例
测试数据某一刻震荡,训练数据不断提高,从图像中两条线的分离点产生过拟合
评价训练集效果
model.evaluate(x_train, y_train) #评价函数,可返回损失函数和准确率
可以得到在该模型上损失函数为0.09981269526341877,正确率0.9938650306748467
评价测试集结果
model.evaluate(x_test, y_test)
可以得到在该模型上损失函数为2.2119179903132067 ,正确率0.774390243902439
过拟合:在训练数据正确率非常高, 在测试数据上比较低
随机丢弃一些隐藏单元,从而增强另一部分隐藏单元的学习
为什么Drupout可以解决过拟合
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() ##看一下当前网络构成
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()
从图片可以看出,测试和训练时acc值差别不大,添加Dropout层后测试数据得分会增加,有效抑制过拟合
训练过程中抑制参数增长范围,不能使参数范围变化太大,在loss上添加一个权重规模的参数,使得网络在训练过程中参数范围不会无限扩大
L1正则:
loss = sabs(w1 + w2 + …) + mse
L2正则:
loss = s(w12 + 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))
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))
网络参数选择的总原则