猫狗分类的数据集,各一千张。
一.第一版
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import pathlib
from keras.layers import Input, Activation, BatchNormalization, Flatten
from keras.layers import Dense, Conv2D, MaxPooling2D, Dropout
from keras.models import Model
gpus = tf.config.list_physical_devices("GPU")
if gpus:
tf.config.experimental.set_memory_growth(gpus[0], True) # 设置GPU显存用量按需使用
tf.config.set_visible_devices([gpus[0]], "GPU")
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 设置随机种子尽可能使结果可以重现
np.random.seed(1)
# 设置随机种子尽可能使结果可以重现
tf.random.set_seed(1)
# 数据集路径
data_dir = r"F:\Projects"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*')))
print("图片总数为:", image_count)
batch_size = 8
img_height = 224
img_width = 224
# 训练集
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
# 测试集
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
# 检查数据
class_names = train_ds.class_names
print(class_names)
for image_batch, labels_batch in train_ds:
print(image_batch.shape) # (8, 224, 224, 3)
print(labels_batch.shape) # (8,)
break
# 配置数据集
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
# 搭建网络模型
def AlexNet(num_classes, input_shape):
# 输入层
input_tensor = Input(shape=input_shape)
# 第一层
x = Conv2D(96, (11, 11), strides=4, padding='valid', activation='relu', name='conv-1')(input_tensor)
x = MaxPooling2D((3, 3), strides=2, padding='valid', name='MaxPool-1')(x)
# 第二层
x = Conv2D(256, (5, 5), strides=1, padding='same', activation='relu', name='conv-2')(x)
x = MaxPooling2D((3, 3), strides=2, padding='valid', name='Maxpool-2')(x)
# 第三层
x = Conv2D(384, (3, 3), strides=1, padding='same', activation='relu', name='conv-3')(x)
# 第四层
x = Conv2D(384, (3, 3), strides=1, padding='same', activation='relu', name='conv-4')(x)
# 第五层
x = Conv2D(256, (3, 3), strides=1, padding='same', activation='relu', name='conv-5')(x)
x = MaxPooling2D((3, 3), strides=2, padding='valid', name='Maxpool-3')(x)
# 第六七八层:全连接层
x = Flatten()(x)
x = Dense(4096, activation='relu', name='fc1')(x)
x = Dense(4096, activation='relu', name='fc2')(x)
output_tensor = Dense(num_classes, activation='softmax', name='predictions')(x)
model = Model(input_tensor, output_tensor)
return model
model = AlexNet(1000, (img_width, img_height, 3))
model.summary()
# 编译
opt = tf.keras.optimizers.Adam(learning_rate=1e-7)
model.compile(optimizer="adam",
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
epochs = 10 # 训练轮数
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
# 模型评估可视化
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(epochs)
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
# 保存模型
model.save('model/alexnet_model2.h5')
print('模型保存成功!')
可以训练,但是没什么用:
可以看到几乎没什么收敛。
第二版
这次主要添加了上面两行,其他没修改。
但是效果跟之前差不多,所以应该是网络结构的书写出了问题。
第三版
这次在第二版的基础上把激活函数的写法给修改了:
即在每个卷积层后面添加Activation。但是发现效果跟之前差不多,不收敛。
第三版的网络部分代码,其他没有修改:
# 搭建网络模型
def AlexNet(num_classes, input_shape):
# 输入层
input_tensor = Input(shape=input_shape)
# 第一层
x = Conv2D(96, (11, 11), strides=4, padding='valid', name='conv-1')(input_tensor)
x = Activation('relu')(x)
x = MaxPooling2D((3, 3), strides=2, padding='valid', name='MaxPool-1')(x)
# 第二层
x = Conv2D(256, (5, 5), strides=1, padding='same', activation='relu', name='conv-2')(x)
x = Activation('relu')(x)
x = MaxPooling2D((3, 3), strides=2, padding='valid', name='Maxpool-2')(x)
# 第三层
x = Conv2D(384, (3, 3), strides=1, padding='same', activation='relu', name='conv-3')(x)
x = Activation('relu')(x)
# 第四层
x = Conv2D(384, (3, 3), strides=1, padding='same', activation='relu', name='conv-4')(x)
x = Activation('relu')(x)
# 第五层
x = Conv2D(256, (3, 3), strides=1, padding='same', activation='relu', name='conv-5')(x)
x = Activation('relu')(x)
x = MaxPooling2D((3, 3), strides=2, padding='valid', name='Maxpool-3')(x)
# 第六七八层:全连接层
x = Flatten()(x)
x = Dense(4096, activation='relu', name='fc1')(x)
x = Dropout(0.5)(x) # 加入0.5的Dropout
x = Dense(4096, activation='relu', name='fc2')(x)
x = Dropout(0.5)(x)
output_tensor = Dense(num_classes, activation='softmax', name='predictions')(x)
model = Model(input_tensor, output_tensor)
return model
第四版
这次在前面两个卷积层后面添加了BN操作,可是还是一样的效果。
最后
最后换了一个数据集,换成鸟类分类的数据集,写法如下,准确率提高了,说明基本能用。
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import pathlib
from keras.layers import Input, Activation, BatchNormalization, Flatten
from keras.layers import Dense, Conv2D, MaxPooling2D, Dropout
from keras.models import Model
gpus = tf.config.list_physical_devices("GPU")
if gpus:
tf.config.experimental.set_memory_growth(gpus[0], True) # 设置GPU显存用量按需使用
tf.config.set_visible_devices([gpus[0]], "GPU")
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 设置随机种子尽可能使结果可以重现
np.random.seed(1)
# 设置随机种子尽可能使结果可以重现
tf.random.set_seed(1)
# 数据集路径
data_dir = r"F:\Dataset_DL\bird_photos"
data_dir = pathlib.Path(data_dir)
image_count = len(list(data_dir.glob('*/*')))
print("图片总数为:", image_count)
batch_size = 8
img_height = 227
img_width = 227
# 训练集
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
# 测试集
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
# 检查数据
class_names = train_ds.class_names
print(class_names)
for image_batch, labels_batch in train_ds:
print(image_batch.shape) # (8, 224, 224, 3)
print(labels_batch.shape) # (8,)
break
# 配置数据集
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
seed = 7
np.random.seed(seed)
# 搭建网络模型
# 搭建网络模型
def AlexNet(num_classes, input_shape):
# 输入层
input_tensor = Input(shape=input_shape)
# 第一层
x = Conv2D(96, (11, 11), strides=4, padding='valid',name='conv-1')(input_tensor)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = MaxPooling2D((3, 3), strides=2, padding='valid', name='MaxPool-1')(x)
# 第二层
x = Conv2D(256, (5, 5), strides=1, padding='same', name='conv-2')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = MaxPooling2D((3, 3), strides=2, padding='valid', name='Maxpool-2')(x)
# 第三层
x = Conv2D(384, (3, 3), strides=1, padding='same', name='conv-3')(x)
x = Activation('relu')(x)
# 第四层
x = Conv2D(384, (3, 3), strides=1, padding='same', name='conv-4')(x)
x = Activation('relu')(x)
# 第五层
x = Conv2D(256, (3, 3), strides=1, padding='same', name='conv-5')(x)
x = Activation('relu')(x)
x = MaxPooling2D((3, 3), strides=2, padding='valid', name='Maxpool-3')(x)
# 第六七八层:全连接层
x = Flatten()(x)
x = Dense(4096, activation='relu', name='fc1')(x)
x = Dropout(0.5)(x) # 加入0.5的Dropout
x = Dense(4096, activation='relu', name='fc2')(x)
x = Dropout(0.5)(x)
output_tensor = Dense(num_classes, activation='softmax', name='predictions')(x)
model = Model(input_tensor, output_tensor)
return model
model = AlexNet(1000, (img_width, img_height, 3))
model.summary()
# 编译
opt = tf.keras.optimizers.Adam(learning_rate=1e-7)
model.compile(optimizer="adam",
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
epochs = 10 # 训练轮数
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
# 模型评估可视化
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(epochs)
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
# 保存模型
model.save('model/alexnet_model2.h5')
print('模型保存成功!')