参考资料:
《B站:黑马程序员3天带你玩转Python深度学习TensorFlow框架》
《B站:卷起来!2022年B站最全最清晰的Tensorflow教程!全86讲!》
《Keras 中文文档》
《TensorFlow中文官网》
《简单粗暴 TensorFlow 2》
《TensorFlow—Keras常用API》
《机器学习实战:基于Scikit-Learn、Keras和TenserFlow 原书第2版》
tf.keras.datasets
是提供 tf.keras.datasets 空间的公开 API,说直白点就是,相关机器学习的数据集,可以直接使用该 API 获取并使用数据mnist = tf.keras.datasets.mnist
;(train_data, train_label), (test_data, test_label) = mnist.load_data()
tensorflow.keras.preprocessing.image
模块;from tensorflow.keras.preprocessing.image import ImageDataGenerator(rescale, rotation_range, height_shift_range, width_shift_range, shear_range, zoom_rang, channel_shift_range, horizontal_flip, fill_mode)
:构造图片生成器,返回一个生成器 datagen;
datagen.flow_from_directory(in_path, batch_size=1, shuffle=False, save_to_dir, save_prefix='', target_size=(224, 224))
:保存变换后的图片数据,是一个二维数组格式 gen_data;
gen_data.next()
:处理下一张图片;# 数据变换处理器 - 从数据角度解决过拟合问题
train_datagen = ImageDataGenerator(
rescale=1. / 255, # 归一化
rotation_range=40, # 旋转角度
width_shift_range=0.2, # 横平移变换
height_shift_range=0.2, # 平纵移变换
shear_range=0.2, # 剪切范围
zoom_range=0.2, # 缩放
horizontal_flip=True, # 翻转
fill_mode="nearest",
)
# 测试集不能数据变换
valid_datagen = ImageDataGenerator(rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(
train_dir, # 文件夹路径
target_size=(64, 64), # 指定resize成的大小,需要与模型的输入大小一致
batch_size=20, # 每次迭代20个数据
seed=7, # 随机种子
# 如果one-hot就是categorical,二分类用binary就可以
class_mode='binary',
) # 数据格式
validation_generator = valid_datagen.flow_from_directory(
validation_dir,
target_size=(width, height),
batch_size=valid_batch_size,
seed=7,
class_mode='binary',
)
tf.data.Dataset.from_tensor_slices(input_data)
:将 ndarray 格式转成 tensor 格式。返回 tensors;tensors.repeat(x)
:复制 x 次数据。返回 tensors;tensors.batch(x)
:每 x 个张量数据构成 1 个 x 维张量数据,数据量变成 total / x。返回 tensors;tensors.shuffle(buffer_size=10)
:。指定一个缓冲区 buffer_size,打乱顺序。返回 tensors;机器学习的步骤是:获取数据、数据处理、特征工程(转换器)、训练模型(估计器)、评估模型、应用;
在深度学习里,同样遵循机器学习基本步骤,只不过我们一般把获取数据、数据处理与特征工程放在一起。将训练模型分为下面 模型构建、模型训练 两个步骤;
流程:
tf.keras.datasets
获得数据集并预处理;tf.keras.Model
和 tf.keras.layers
构建模型;tf.keras.losses
计算损失函数,并使用 tf.keras.optimizer
优化模型;(常用 Adam 优化器)tf.keras.metrics
计算评估指标;模型构建 的思路:(为了得出损失)
模型训练 的流程:(目的是由损失更新 W 和 b)
详情请见本篇第一大点《1. 基本数据处理》;
- keras 中文文档
tf.keras.model
- 两种类型的模型:
Sequential()
:序列模型。是一种“从头一路走到尾”的模型。参数为 keras 支持的层及参数。返回 model 模型;Model()
:通用函数式模型。通用模型可以设计非常复杂、任意拓扑结构的神经网络,例如有向无环网络、共享层网络等。相比于序列模型只能依次线性逐层添加,通用模型能够比较灵活地构造网络结构,设定各层级的关系。返回 model 模型;tf.keras.layers
- keras 常用层及参数:Dense()
:全连接层。参数如下;
relu
。二分类用 sigmoid
。多分类用 softmax
;Dropout(rate)
:对上一层的神经元随机选取一定比例的失活,不更新,但是权重仍然保留,防止过拟合;
Flatten()
:用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡;Conv1D()
:一维卷积层。主要应用于以时间序列数据或文本数据。参数同二维;Conv2D()
:二维卷积层。通常应用于图像数据。参数如下;
Conv3D()
:三维卷积层。三维卷积对三维的输入进行滑动窗卷积。参数同二维;MaxPooling1D()
:时域信号进行最大值池化;MaxPooling2D()
:空域信号进行最大值池化号;
MaxPooling3D()
:时空域信号进行最大值池化;model = keras.models.Sequential([
# 如果训练慢,可以把数据设置的更小一些
keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu', padding='same', input_shape=[width, height, channel]), # 卷积:生成64个特征图,卷积核 3*3,激活函数(概念化),填充,输入 64*64*3
keras.layers.MaxPooling2D(pool_size=2), # 池化 - 最大池化:变成原来 1/2
keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu', padding='same'), # 卷积:生成32个特征图,卷积核 3*3,激活函数(概念化),
keras.layers.MaxPooling2D(pool_size=2), # 池化
keras.layers.Conv2D(filters=64, kernel_size=3, activation='relu', padding='same'), # 卷积
keras.layers.MaxPooling2D(pool_size=2), # 池化
keras.layers.Conv2D(filters=64, kernel_size=3, activation='relu', padding='same'), # 卷积
keras.layers.MaxPooling2D(pool_size=2), # 池化
keras.layers.Conv2D(filters=128, kernel_size=3, activation='relu', padding='same'), # 卷积
keras.layers.MaxPooling2D(pool_size=2), # 池化
keras.layers.Conv2D(filters=128, kernel_size=3, activation='relu', padding='same'), # 卷积
keras.layers.MaxPooling2D(pool_size=2), # 池化
# 为全连接层准备
keras.layers.Flatten(), # 拉长数据,相当于将 立体三维特征图 变成 一维向量
keras.layers.Dense(256, activation='relu'), # 得到 512个隐形特征,容易出现过拟合
keras.layers.Dropout(0.5), # (解决过拟合)感受野,每次忽略一半神经元 0.5 rate to drop
# 猫狗分类二分类sigmoid就够了
keras.layers.Dense(1, activation='sigmoid'), # 相当于逻辑回归,映射到 0-1。多分类用activation='softmax'
])
思路步骤:
tf.keras.optimizers
- 使用优化器:
SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)
:随机梯度下降优化器;
Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
:Adam 优化器。常用于图像;
使用损失函数
使用指标
API:model.compile(optimizer, loss, metrics)
model.fit(x, y, batch_size=32, epochs=10, verbose=1, callbacks=None,validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0)
:与 fit_generator 类似,区别在于:fit 把所有数据读进内存;fit_generator 相当于生成器,动态生产所需 batch 数据。返回一个 History 的对象,其 History.history 属性记录了损失函数和其他指标的数值随 epoch 变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况;
model.fit_generator(train_data, steps_per_epoch=100, epochs=20, validation_data=, validation_steps=50, verbose=2)
:;
model.predict(x_test)
:传入训练集,返回预测值,一般用来与真实值对比;model.evaluate(x_test, y_test)
:返回测试集评估结果,类型为数组,可以通过数组下标访问;model.summary()
:打印展示模型结构;history = model.fit()
;# 4.2 画图展示
acc = history.history['acc'] # 训练数据准确率
val_acc = history.history['val_acc'] # 验证数据准确率
loss = history.history['loss'] # 训练集 loss
val_loss = history.history['val_loss'] # 验证集 loss
epochs = range(len(acc))
plt.plot(epochs, acc, 'bo', label='Training accuracy') # 训练集精确率数据,点图例
plt.plot(epochs, val_acc, 'b', label='Validation accuracy') # 测试集精确率数据,线图例
plt.title('Training and validation accuracy') # 精确率图表标题
plt.figure()
plt.show() # 展示图表
plt.plot(epochs, loss, 'bo', label='Training Loss') # 训练集损失值数据,点图例
plt.plot(epochs, val_loss, 'b', label='Validation Loss') # 测试集损失值数据,线图例
plt.title('Training and validation loss') # 损失值图表标题
plt.legend() # 添加图例
plt.show() # 展示图表
tf.keras.Model
类实现:
class MyModel(tf.keras.Model):
def __init__(self):
super().__init__() # Python 2 下使用 super(MyModel, self).__init__()
# 此处添加初始化代码(包含 call 方法中会用到的层),例如
# layer1 = tf.keras.layers.BuiltInLayer(...)
# layer2 = MyCustomLayer(...)
def call(self, input):
# 此处添加模型调用的代码(处理输入并返回输出),例如
# x = layer1(input)
# output = layer2(x)
return output
# 还可以添加自定义的方法
属性参数 | 中文含义 | 二分类 | 多分类 |
---|---|---|---|
train_datagen.flow_from_directory(class_mode=‘binary’, …) | 图像生成器类型 | binary | categorical |
keras.layers.Dense(activation=‘sigmoid’, …) | 全连接层 | sigmoid | softmax |
model.compile(loss=‘binary_crossentropy’, …) | 损失函数 | binary_crossentropy | categorical_crossentropy(labels 是 one-hot 编码) 或 sparse_categorical_crossentropy(labels 是数字编码) |
if __name__ == "__main__":
# 1. 数据准备
# 1.1 数据所在文件夹
base_dir = '../resources/p02_deep_learning_tensorFlow/dog_and_cat/'
train_dir = os.path.join(base_dir, 'train/')
validation_dir = os.path.join(base_dir, 'validation/')
# # 训练集
# train_cats_dir = os.path.join(train_dir, 'cats')
# train_dogs_dir = os.path.join(train_dir, 'dogs')
#
# # 验证集
# validation_cats_dir = os.path.join(validation_dir, 'cats')
# validation_dogs_dir = os.path.join(validation_dir, 'dogs')
# 2 数据预处理
# 数据变换处理器 - 从数据角度解决过拟合问题
train_datagen = ImageDataGenerator(
rescale=1. / 255, # 归一化
rotation_range=40, # 旋转角度
width_shift_range=0.2, # 横平移变换
height_shift_range=0.2, # 平纵移变换
shear_range=0.2, # 剪切范围
zoom_range=0.2, # 缩放
horizontal_flip=True, # 翻转
fill_mode="nearest",
)
# 测试集不能数据变换
valid_datagen = ImageDataGenerator(rescale=1. / 255)
# 图像处理数据, GPU 可以 224*224*3
width = 64
height = 64
channel = 3
batch_size = 20 # 训练集每次迭代20个数据
valid_batch_size = 20 # 测试集每次迭代20个数据
# 2.1 从文件夹读取数据,并且每次读 20 个
train_generator = train_datagen.flow_from_directory(
train_dir, # 文件夹路径
target_size=(width, height), # 指定resize成的大小,需要与模型的输入大小一致
batch_size=batch_size, # 每次迭代20个数据
seed=7, # 随机种子
# 如果one-hot就是categorical,二分类用binary就可以
class_mode='binary',
) # 数据格式
# 查看数据:train_generator.next()
validation_generator = valid_datagen.flow_from_directory(
validation_dir,
target_size=(width, height),
batch_size=valid_batch_size,
seed=7,
class_mode='binary',
)
# 3. 特征工程
# 估计器:基于 Keras 构建网络模型
# 3.1 前向传播:按顺序构造网络模型
model = keras.models.Sequential([
# 如果训练慢,可以把数据设置的更小一些
keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu', padding='same', input_shape=[width, height, channel]), # 卷积:生成64个特征图,卷积核 3*3,激活函数(概念化),填充,输入 64*64*3
keras.layers.MaxPooling2D(pool_size=2), # 池化 - 最大池化:变成原来 1/2
keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu', padding='same'), # 卷积:生成32个特征图,卷积核 3*3,激活函数(概念化),
keras.layers.MaxPooling2D(pool_size=2), # 池化
keras.layers.Conv2D(filters=64, kernel_size=3, activation='relu', padding='same'), # 卷积
keras.layers.MaxPooling2D(pool_size=2), # 池化
keras.layers.Conv2D(filters=64, kernel_size=3, activation='relu', padding='same'), # 卷积
keras.layers.MaxPooling2D(pool_size=2), # 池化
keras.layers.Conv2D(filters=128, kernel_size=3, activation='relu', padding='same'), # 卷积
keras.layers.MaxPooling2D(pool_size=2), # 池化
keras.layers.Conv2D(filters=128, kernel_size=3, activation='relu', padding='same'), # 卷积
keras.layers.MaxPooling2D(pool_size=2), # 池化
# 为全连接层准备
keras.layers.Flatten(), # 拉长数据,相当于将 立体三维特征图 变成 一维向量
keras.layers.Dense(256, activation='relu'), # 得到 512个隐形特征,容易出现过拟合
keras.layers.Dropout(0.5), # (解决过拟合)感受野,每次忽略一半神经元 0.5 rate to drop
# 猫狗分类二分类sigmoid就够了
keras.layers.Dense(1, activation='sigmoid'), # 相当于逻辑回归,映射到 0-1。多分类用activation='softmax'
])
# model.summary() # 展示逻辑结构
# 3.2 反向传播:配置训练器
model.compile(loss='binary_crossentropy',
optimizer=Adam(lr=1e-4),
metrics=['acc']) # 由于是二分类,使用准确率作为评估标准
# 3.3 训练模型
# fit 把所有数据读进内存;fit_generator 相当于生成器,动态生产所需 batch 数据
history = model.fit(
train_generator, # 训练数据生成器
steps_per_epoch=100, # 每次迭代生成100个数据,至少需要跑 100次才能遍历完2000个数据。2000 images = batch_size * steps
epochs=60, # 迭代20次(每个 batch 是 20 个数据)
validation_data=validation_generator, # 目标数据生成器
validation_steps=50, # 1000 images = batch_size * steps
verbose=2)
# 4. 模型评估
# 4.1 评估器评估
# 4.2 画图展示
acc = history.history['acc'] # 训练数据准确率
val_acc = history.history['val_acc'] # 验证数据准确率
loss = history.history['loss'] # 训练集 loss
val_loss = history.history['val_loss'] # 验证集 loss
epochs = range(len(acc))
plt.plot(epochs, acc, 'bo', label='Training accuracy') # 训练集精确率数据,点图例
plt.plot(epochs, val_acc, 'b', label='Validation accuracy') # 测试集精确率数据,线图例
plt.title('Training and validation accuracy') # 精确率图表标题
plt.figure()
plt.show() # 展示图表
plt.plot(epochs, loss, 'bo', label='Training Loss') # 训练集损失值数据,点图例
plt.plot(epochs, val_loss, 'b', label='Validation Loss') # 测试集损失值数据,线图例
plt.title('Training and validation loss') # 损失值图表标题
plt.legend() # 添加图例
plt.show() # 展示图表