神经网络与深度学习¶
——用于回归和分类的神经网络+图像
(一)服装分类¶
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)
略……