跳转至

神经网络与深度学习

——用于回归和分类的神经网络+图像

(一)服装分类

import tensorflow as tf
from tensorflow import keras

from keras.preprocessing.image import load_img
path = './clothing-dataset-small/train/t-shirt'
name = 'fb3f29fb-ae30-41a5-84cd-c1e3ccad0307.jpg'
fullname = path + '/' + name
load_img(fullname, target_size=(299,299))

(二)卷积神经网络

—— Xception

1 使用预训练模型

from keras.applications.xception import Xception # 实际模型
from keras.applications.xception import preprocess_input # 准备模型要使用的图像的函数
from keras.applications.xception import decode_predictions # 解码模型的预测的函数
model = Xception(
    weights = 'imagenet', # 使用来自ImaageNet的预训练模型
    input_shape = (299, 299, 3), # 高度、宽度、通道数
)
img = load_img(fullname, target_size=(299,299))
x = np.array(img) # Image对象->转换为Numpy数组
X = np.array([x]) # ⭐
X = preprocess_input(X) # 在模型应用到图像之前,要用preprocess_input准备

⭐:要得到一批图像,这个数组需要四个维度:图像数、宽度、高度、通道数。

2 获得预测

pred = model.predict(X)
pred.shape
# Xception模型预测图像是否属于1000个类中的一个,因此预测数组中的每个元素都是属于这些类中的一个的概率
decode_predictions(pred)

(三)模型的内部结构

Xception模型包含71层,其中最重要的层如下展开

1 卷积层

一组过滤器,把过滤器的内容与过滤器下面的图像进行比较,记录相似程度,得到特征图,数字越大越匹配。实际上,多个滤波器得到多个特征图。 把一个卷积层的输出作为下一层的输入。下一层的过滤器把前一层的形状组合成更复杂的结构。 最后得到图像的向量表示:一个一维数组,每个位置对应高级的视觉特征。(致密层运用这些高级特征得出最终决策)

2 致密层

多个逻辑回归模型放在一起,组成一个输出层。 一个只有一层的网络:这一层把输入转换为输出——致密层:把输出如的每个元素与输出的所有元素连接起来,即“全连接”

(四)训练模型

训练卷积神经网络需要大量时间和数据,捷径——迁移学习,使用预训练模型适用于问题的方法。

1 迁移学习

训练的困难通常来自于卷积层。为了更好的提取优秀的向量表示,过滤器需要学习良好的向量表示,这样训练卷积层会相对容易。 因此可以,保留ImageNet上预训练神经网络的卷积层,舍弃其致密层而训练新层。

2 加载数据

本来:将这个数据集加载到内存并用它获取X——特征矩阵。但是,我们可能没有足够的内存来保存所有图像,别的解决方案如下。 小批量地从磁盘加载图像。

from tensorflow.keras.preprocessing.image import ImageDataGenerator

image_size = (150, 150)
batch_size = 32
# 验证集同理
train_gen = ImageDataGenerator(
    preprocessing_function=preprocess_input # 对每个图像使用preprocess_input函数
)
train_ds = train_gen.flow_from_directory(
    'clothing-dataset-small/train', # 从训练集目录加载所有图像
    target_size=image_size, # 使用上文设置的image_size
    batch_size=batch_size, # 使用上文设置的batch_size
)

3 创建模型

base_model = Xception( # 迁移学习
    weights='imagenet', # 加载预训练模型
    include_top=False, # 去掉最后的全连接层,只保留卷积层——top指的是网络的最后一层(见图)
    input_shape = (150,150,3)
)
base_model.trainable = False # 冻结基本模型

# 构建服装分类模型
inputs = keras.Input(shape=(150,150,3)) # 指定期望的数组输入和大小:输入图像为150*150+3通道
base = base_model(inputs, training=False) # 创建基本模型:使用base_model提取高级特征
vector = keras.layers.GlobalAveragePooling2D()(base) # 池化层:把base_model的输出作为输入,提取向量表示——全局平均池化层
outputs = keras.layers.Dense(10)(vector) # 致密层:添加一个大小为10的致密层,每个元素代表一类
model = keras.Model(inputs, outputs)

4 训练模型

learning_rate = 0.01
optimizer = keras.optimizers.Adam(learning_rate) # 优化器
loss = keras.losses.CategoricalCrossentropy(from_logits=True) # 交叉熵损失函数

# 或者:outputsa = keras.layers.Dense(10, activation='softmax')(vector) loss=keras.losses.CategoricalCrossentropy()

model.compile(
    optimizer = optimizer,
    loss = loss,
    metrics=['accuracy']
)

model.fit(train_ds, epochs=10, validation_data=val_ds) # 对整个训练数据集的一次迭代成为一个迭代器(epcho)

5 调整学习率

6 保存模型和设置检查点

# model.save_weights('xcsption_v1_model.h5', save_format = 'h5')

checkpoint = keras.callbacks.ModelCheckpoint(
    "xception_v1_{epoch:02d}_{val_accuracy:.3f}.keras", # 指定保存模型的文件名模板
    save_best_only = True, # 只有当模型优于之前迭代时才保存模型
    monitor = 'val_accuracy', # 监控指标
)
model = make_model(learning_rate=0.001)
model.fit(
    train_ds,
    epochs=10,
    validation_data=val_ds,
    callbacks=[checkpoint]
)

7 添加更多的层

inputs = keras.Input(shape=(150,150,3))
base = base_model(inputs, training=False)
vector = keras.layers.GlobalAveragePooling2D()(base)

inner = keras.layers.Dense(100, activation='relu')(vector)
# 来个常见的激活函数啦Rectified Linear Unit
outputs = keras.layers.Dense(10)(inner)
model = keras.Model(inputs, outputs)

8 正则化和dropout

添加新层后,过拟合的可能性显著增加,为了避免这种情况,需要在模型中添加正则化。 dropout:训练时冻结致密层的一部分,每次迭代期中,冻结的部分是随机选择,从而解决过拟合 drop = keras.layers.Dropout(0.2)(inner) # inner是连接的上一层

9 数据增强

从现有图像中生成更多模型:翻转图像、旋转图像、缩放图像、错切图像、移动图像……(数据增强也是种正则化策略)

train_gen = ImageDataGenerator(
    rotation_range=30, # 随机旋转-30°-30°
    width_shift_range=30.0, # 水平移动
    height_shift_range=30.0, # 垂直移动
    sheaeer_range=10.0, # 错切变换
    zoom_range=0.2, # 缩放
    horizontal_flip=True, # 水平翻转
    vertical_flip=False, # 不垂直翻转
    preprocessing_function=preprocess_input # 对每个图像使用preprocess_input函数
)

10 训练更大的模型

改大图像大小就ok

(五)训练模型

model.evaluate(tst_ds) 略……