我们这里还是使用鸢尾花分类的神经网络模型来进行讲解
1.数据集
共有数据150组,每组包括花萼长、花萼宽、花瓣长、花瓣宽4个输入特征。同时给出了,这一组特征对应的鸢尾花类别。类别包括Setosa Iris(狗尾草鸢尾),Versicolour Iris(杂色鸢尾),Virginica Iris(弗吉尼亚鸢尾)三类,分别用数字0,1,2表示。 下面是训练集的特征数据, 可以看到数据是一个150*4的数组,表示有150组数据, 每组数据有4个特征值. 其实神经网络输入的不管是声音还是图片, 最终都会转化成离散的数据, 也就是一组一组的特征值数字. 比如图片会被转化成RGB值的矩阵数组. 下面是训练集的标签数据, 它的顺序和特征数据的数组一一对应
2.模型
模型有4个输入, 对应4个特征值x1, x2, x3, x4, 3个输出y1, y2, y3,分别对应属于3个分类的概率, 所以模型的公式可以写成如下形式
y1 = w11*x1+w12*x2+w13*x3+w14*x4+b1
y2 = w21*x1+w22*x2+w23*x3+w24*x4+b2
y3 = w31*x1+w32*x2+w33*x3+w34*x4+b3
其中w是权重(weight), b 是偏差(bias).
接下来我们需要通过数据来寻找特定的模型参数值,使模型在数据上的误差尽可能小。这个过程叫作模型训练(model training)。这里我们也就是要求得比较好的w和b,使得预测分类的准确率尽可能的高.
3.损失函数
在模型训练中,我们需要衡量预测值与真实值之间的误差。通常我们会选取一个非负数作为误差,且数值越小表示误差越小。一个常用的选择是平方函数。它在评估索引为 i 的样本误差的表达式为 说白了就是衡量预测值与真实值差距大小的计算公式, 模型根据这个误差不断迭代更新参数, 使得模型的预测误差越来越小.
4.优化函数和学习率
如何不断的调整参数来使loss越来越小的方法,最终令预测尽可能接近真实值,这些方法统称为优化函数, 举例如下
在上式中, |B| 代表每个小批量中的样本个数(批量大小,batch size), η 称作学习率(learning rate)并取正数。需要强调的是,这里的批量大小和学习率的值是人为设定的,并不是通过模型训练学出的,因此叫作超参数(hyperparameter)。我们通常所说的“调参”指的正是调节超参数,例如通过反复试错来找到超参数合适的值。在少数情况下,超参数也可以通过模型训练学出。
学习率 η用来控制w和b迭代更新变化的快慢, 也就是变化增量的大小. 学习率太小, 会导致模型训练速度太慢, 太大可能会导致训练效果不佳, 难以找到最优解.
5.训练模型
cwru_train.py
import os
import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras import Model
from sklearn import datasets
import numpy as np
import matplotlib.pyplot as plt
x_train = datasets.load_iris().data
y_train = datasets.load_iris().target
np.random.seed(116)
np.random.shuffle(x_train)
np.random.seed(116)
np.random.shuffle(y_train)
tf.random.set_seed(116)
class IrisModel(Model):
def __init__(self):
super(IrisModel, self).__init__()
self.d1 = Dense(3, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())
def call(self, x):
y = self.d1(x)
return y
model = IrisModel()
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
checkpoint_save_path = "./checkpoint/cnn_flower.ckpt"
if os.path.exists(checkpoint_save_path + '.index'):
print('-------------load the model-----------------')
model.load_weights(checkpoint_save_path)
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
save_weights_only=True,
save_best_only=True)
history = model.fit(x_train, y_train, batch_size=32, epochs=500, validation_split=0.2, validation_freq=20, callbacks=[cp_callback])
model.summary()
train_acc = history.history['sparse_categorical_accuracy']
val_acc = history.history['val_sparse_categorical_accuracy']
train_loss = history.history['loss']
val_loss = history.history['val_loss']
plt.subplot(1, 2, 1)
plt.plot(train_loss, label='train_loss')
plt.plot(val_loss, label='val_loss')
plt.xlabel('epochs')
plt.ylabel('loss')
plt.legend()
plt.title('Training and Validation loss')
plt.subplot(1, 2, 2)
plt.plot(train_acc, label='train_acc')
plt.plot(val_acc, label='val_acc')
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.legend()
plt.title('Training and Validation accuracy')
plt.show()
下面进行一些函数的介绍
1.model.compile
model.compile()方法用于在配置训练方法时,告知训练时用的优化器、损失函数和准确率评测标准.
model.compile( optimizer = 优化器,
loss = 损失函数,
metrics = ["准确率”] )
其中:
1. optimizer可以是字符串形式给出的优化器名字,也可以是函数形式,使用函数形式可以设置学习率、动量和超参数
例如:
“sgd” 或者 tf.optimizers.SGD( lr = 学习率,
decay = 学习率衰减率,
momentum = 动量参数)
“adagrad" 或者 tf.keras.optimizers.Adagrad(lr = 学习率,decay = 学习率衰减率)
”adadelta" 或者 tf.keras.optimizers.Adadelta(lr = 学习率,decay = 学习率衰减率)
“adam" 或者 tf.keras.optimizers.Adam(lr = 学习率,decay = 学习率衰减率)
2. loss可以是字符串形式给出的损失函数的名字,也可以是函数形式
例如:
"mse" 或者 tf.keras.losses.MeanSquaredError()
"sparse_categorical_crossentropy" 或者tf.keras.losses.SparseCatagoricalCrossentropy(from_logits = False)
损失函数经常需要使用softmax函数来将输出转化为概率分布的形式,
在这里from_logits代表是否将输出转为概率分布的形式,为False时表示
转换为概率分布,为True时表示不转换,直接输出
3. Metrics标注网络评价指标
例如:
"accuracy" : y_ 和 y 都是数值,如y_ = [1] y = [1] #y_为真实值,y为预测值
"sparse_accuracy" : y_和y都是以独热码和概率分布表示,如y_ = [0, 1, 0], y = [0.100, 0.600, 0.300]
"sparse_categorical_accuracy" : y_是以数值形式给出,y是以独热码给出,如y_ = [1], y = [0.100, 0.600, 0.300]
2.model.fit
将训练数据在模型中训练一定迭代次数,返回一个历史训练数据,即loss和测量指标
def fit(self,
x=None,
y=None,
batch_size=None,
epochs=1,
verbose=1,
callbacks=None,
validation_split=0.,
validation_data=None,
shuffle=True,
class_weight=None,
sample_weight=None,
initial_epoch=0,
steps_per_epoch=None,
validation_steps=None,
validation_freq=1,
max_queue_size=10,
workers=1,
use_multiprocessing=False,
**kwargs):
参数 | 作用 |
---|
x | 输入数据。如果模型只有一个输入,那么x的类型是numpy array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy array | y | 标签,numpy array | batch_size | 整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。 | epochs | 整数,训练终止时的epoch值,训练将在达到该epoch值时停止,当没有设置initial_epoch时,它就是训练的总轮数,否则训练的总轮数为epochs - inital_epoch | verbose | 日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录 | callbacks | list,其中的元素是keras.callbacks.Callback的对象。这个list中的回调函数将会在训练过程中的适当时机被调用,参考回调函数 | validation_split | 0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之前,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀。 | validation_data | 形式为(X,y)的tuple,是指定的验证集。此参数将覆盖validation_spilt。 | shuffle | 布尔值或字符串,一般为布尔值,表示是否在训练过程中随机打乱输入样本的顺序。若为字符串“batch”,则是用来处理HDF5数据的特殊情况,它将在batch内部将数据打乱。 | class_weight | 字典,将不同的类别映射为不同的权值,该参数用来在训练过程中调整损失函数(只能用于训练) | sample_weight | 权值的numpy array,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权,或者在面对时序数据时,传递一个的形式为(samples,sequence_length)的矩阵来为每个时间步上的样本赋不同的权。这种情况下请确定在编译模型时添加了sample_weight_mode=’temporal’。 | initial_epoch | 从该参数指定的epoch开始训练,在继续之前的训练时有用。 | steps_per_epoch | 一个epoch包含的步数(每一步是一个batch的数据送入),当使用如TensorFlow数据Tensor之类的输入张量进行训练时,默认的None代表自动分割,即数据集样本数/batch样本数。 | | | validation_steps | 在验证集上的step总数,仅当steps_per_epoch被指定时有用 | validation_freq | 指使用验证集实施验证的频率。当等于1时代表每个epoch结束都验证一次 | max_queue_size | 整数。仅用于生成器或 keras.utils.Sequence 输入。生成器队列的最大大小。如果未指定,“最大队列大小”将默认为10 | workers | 整数。仅用于生成器或“keras.utils.Sequence”输入。使用基于进程的线程时,要加速的最大进程数。如果未指明,则将默认为1。如果为0,将在main上执行生成器线程。 | use_multiprocessing | 布尔型。仅用于生成器或“keras.utils.Sequence”输入。如果为“真”,则使用基于进程的线程。如果未指定,将默认为False。注意,因为这个实现依赖于多重处理,所以您不应该将不可选择的参数传递给生成器,因为它们不容易传递给子进程。 | **kwargs | 用于向后兼容 |
3.history
history = model.fit, 返回一个History对象, 该对象包含两个属性,分别为epoch和history,epoch为训练轮数。
History所包含的内容是由compile参数的metrics确定的, history对象的history内容(history.history)是字典类型,键的内容受metrics的设置影响,值的长度与epochs值一致。
metrics | history.history |
---|
metrics=[‘accuracy’]时 | history字典类型,包含val_loss,loss,val_acc, acc四个key值 | metrics=[‘sparse_categorical_accuracy’]时 | history字典类型,包含sparse_categorical_accuracy, val_sparse_categorical_accuracy, loss, val_loss四个key值 |
6.进行预测
模型训练后会生成模型文件, 我们就可以使用这个模型进行预测了 cnn_flower_predict.py
import os
import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras import Model
from sklearn import datasets
import numpy as np
x_train = datasets.load_iris().data
y_train = datasets.load_iris().target
np.random.seed(116)
np.random.shuffle(x_train)
np.random.seed(116)
np.random.shuffle(y_train)
tf.random.set_seed(116)
class IrisModel(Model):
def __init__(self):
super(IrisModel, self).__init__()
self.d1 = Dense(3, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())
def call(self, x):
y = self.d1(x)
return y
model = IrisModel()
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
checkpoint_save_path = "./checkpoint/cnn_flower.ckpt"
if os.path.exists(checkpoint_save_path + '.index'):
print('-------------load the model-----------------')
model.load_weights(checkpoint_save_path)
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
save_weights_only=True,
save_best_only=True)
y_pre = model.predict(x_train[0:10])
print("------------预测样本数据----------")
print(x_train[0:10])
print("------------预测结果概率----------")
print(y_pre)
print("------------预测结果分类----------")
print(np.argmax(y_pre, axis=1))
下面进行一些函数的介绍
1.ModelCheckpoint
我们训练完模型之后,一般会需要保存模型或者只保存权重文件。可以利用keras中的回调函数ModelCheckpoint进行保存。
keras.callbacks.ModelCheckpoint(
filepath,
monitor='val_loss',
verbose=0,
save_best_only=True,
save_weights_only=False,
mode='auto',
period=1
)
参数 | 作用 |
---|
filepath | 模型保存在本地的路径 | monitor | 需要监视的值,val_accuracy、val_loss或者accuracy | verbose | 信息展示模式 | save_best_only | 当设置为True时,表示当模型这次epoch的训练评判结果(monitor的监测值)比上一次保存训练时的结果有提升时才进行保存。 | save_weights_only | 若设置为True,占用内存小(只保存模型权重),但下次想调用的话,需要搭建和训练时一样的网络。若设置为False,占用内存大(包括了模型结构和配置信息),下次调用可以直接载入,不需要再次搭建神经网络结构。 | mode | ‘auto’,‘min’,‘max’之一,在save_best_only=True时决定性能最佳模型的评判准则,例如,当监测值为val_acc时,模式应为max,当检测值为val_loss时,模式应为min。在auto模式下,评价准则由被监测值的名字自动推断。 | period | 填写 int 值,如果填写 period=3,指模型每训练3个epoch,进行保存一次。 |
2.model.predict
输入数据, 用于预测的函数, 输出预测值
predict(
x,
batch_size=None,
verbose=0,
steps=None,
callbacks=None,
max_queue_size=10,
workers=1,
use_multiprocessing=False
)
参数 | 作用 |
---|
x | 输入样本,格式可以是Numpy数组(或类似array的数组)或数组列表(如果模型具有多个输入). TensorFlow张量或张量列表(如果模型具有多个输入), tf.data数据集, 生成器或keras.utils.Sequence实例 | batch_size | 每个梯度更新的样本数。如果未指定,batch_size将默认为32 | verbose | 信息展示模式,0或1 | steps | 宣布预测回合完成之前的步骤总数(样本批次)。忽略默认值None | callbacks | 预测期间应用的回调函数列表 | max_queue_size | 仅用于generator或keras.utils.Sequence输入。生成器队列的最大大小。如果未指定,max_queue_size将默认为10 | workers | 仅用于generator或keras.utils.Sequence输入。使用基于进程的线程时,要启动的最大进程数。如果未指定,worker将默认为1。如果为0,将在主线程上执行生成器 | use_multiprocessing | 仅用于generator或keras.utils.Sequence输入。如果为True,则使用基于进程的线程。如果未指定,则use_multiprocessing将默认为False。 |
3.model.evaluate
输入数据和标签, 输出损失和精确度. 使用这个函数我们可以得到已生成模型的损失率和准确度 .
loss, accuracy = model.evaluate(x_train, y_train)
print('loss=', loss)
print('accuracy=', accuracy)
|