一、项目简介
1、问题概述
问题描述:在这个问题中,你将面临一个经典的机器学习分类挑战——猫狗大战。你的任务是建立一个分类模型,能够准确地区分图像中是猫还是狗。
预期解决方案:
你的目标是通过训练一个机器学习模型,使其在给定一张图像时能够准确地预测图像中是猫还是狗。模型应该能够推广到未见过的图像,并在测试数据上表现良好。我们期待您将其部署到模拟的生产环境中——这里推理时间和二分类准确度(F1分数)将作为评分的主要依据。
2、数据描述以及来源
本实验一共有两个数据集合,都在data目录下,整个数据集分为训练集和测试集,分别是test_dir与train_dir,其内容都是一些大小不等的jpg照片格式。其中train_dir有 25000 张图片,其格式为cat.xxxx.jpg与dog.xxxx.jpg,xxxx表示的是数据标号。猫狗各 12500 张。 而测试集tets_dir有张图片,其格式与train_dir的数据格式一样
数据集:
链接:百度网盘 请输入提取码
提取码:jc34
3、部分原始数据展示
4、运行平台
由于需要用到oneApI组件,因此本实验是在intel的devCloud平台下运行的,采用的框架是TensorFlow。
二、InceptionResNetV2结构设计
1、InceptionResNetV2的加载
CFG = dict(
seed = 77,
batch_size = 20,
img_size = (299,299),
epochs = 5,
patience = 5
)
base_model = InceptionResNetV2(weights='imagenet',
include_top=False,
input_shape=(CFG['img_size'][0],
CFG['img_size'][1], 3))
2、Flatten层
x = base_model.output
x = Flatten()(x)
3、定义优化器
optimizer = Adam()
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
4、保存模型
# 保存模型
save_checkpoint = keras.callbacks.ModelCheckpoint(filepath='model.h5',
monitor='val_f1_score',
save_best_only=True, verbose=1,
mode='max',
save_weights_only=False)
early_stopping = keras.callbacks.EarlyStopping(monitor='val_loss',
patience=CFG['patience'],
verbose=True)
# 定义计算 F1 分数的回调
class F1ScoreCallback(keras.callbacks.Callback):
def __init__(self, validation_generator):
self.validation_generator = validation_generator
def on_epoch_end(self, epoch, logs=None):
predictions = self.model.predict(self.validation_generator)
predictions_binary = np.round(predictions)
true_labels = self.validation_generator.classes
f1 = f1_score(true_labels, predictions_binary)
print(f'Validation F1 Score: {f1}')
5、模型训练
# 训练模型
history = model.fit(
train_generator,
steps_per_epoch=nb_train_samples // CFG['batch_size'],
epochs=CFG['epochs'],
callbacks=[save_checkpoint,early_stopping],
validation_data=validation_generator,
verbose=True,
validation_steps=nb_validation_samples // CFG['batch_size'])
三、其余实现代码
1、导包准备
import numpy as np
import random
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.metrics import confusion_matrix
import seaborn as sns
sns.set(style='darkgrid', font_scale=1.5)
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications.inception_resnet_v2 import InceptionResNetV2, preprocess_input
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
2、数据准备
import shutil
def move_images_by_prefix(source_folder, destination_folder_cat, destination_folder_dog, prefix_cat="cat", prefix_dog="dog"):
# 创建目标文件夹
os.makedirs(destination_folder_cat, exist_ok=True)
os.makedirs(destination_folder_dog, exist_ok=True)
# 遍历源文件夹中的文件
for filename in os.listdir(source_folder):
if filename.startswith(prefix_cat):
# 如果文件名以 'cat' 开头,移动到 cats 文件夹
shutil.move(os.path.join(source_folder, filename), os.path.join(destination_folder_cat, filename))
elif filename.startswith(prefix_dog):
# 如果文件名以 'dog' 开头,移动到 dogs 文件夹
shutil.move(os.path.join(source_folder, filename), os.path.join(destination_folder_dog, filename))
# 目标文件夹路径
train = './train'
test = './test'
move_images_by_prefix(train, './data/train_dir/cats','./data/train_dir/dogs')
move_images_by_prefix(test, './data/test_dir/cats', './data/test_dir/dogs')
train_dir = './data/train_dir'
test_dir = './data/test_dir'
3、生成器加入数据增强防止过拟合
train_data_generator = ImageDataGenerator(
validation_split=0.2,
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',
preprocessing_function=preprocess_input)
# 获取指定目录下的所有文件和子目录,但过滤掉隐藏目录
contents = [item for item in os.listdir(train_dir) if not item.startswith('.')]
val_data_generator = ImageDataGenerator(preprocessing_function=preprocess_input, validation_split=0.20)
test_data_generator = ImageDataGenerator(preprocessing_function=preprocess_input)
# 将生成器连接到文件夹中的数据
# 将生成器连接到文件夹中的数据
train_generator = train_data_generator.flow_from_directory(train_dir,
target_size=CFG['img_size'],
shuffle=True, seed=CFG['seed'],
class_mode='categorical',
batch_size=CFG['batch_size'],
subset="training",
classes=contents)
validation_generator = val_data_generator.flow_from_directory(train_dir,
target_size=CFG['img_size'],
shuffle=False, seed=CFG['seed'],
class_mode='categorical',
batch_size=CFG['batch_size'],
subset="validation",
classes=contents)
test_generator = test_data_generator.flow_from_directory(test_dir,
target_size=CFG['img_size'],
shuffle=False, seed=CFG['seed'],
class_mode='categorical',
batch_size=CFG['batch_size'],
classes=contents)
4、推理验证
import os
import random
from PIL import Image
import numpy as np
from tensorflow.keras.models import load_model
import matplotlib.pyplot as plt
# 加载模型
loaded_model = load_model('model.h5') # 替换'model.h5'为你的模型文件名
# 图像文件夹路径
image_folder_path = './data/test_dir/dogs' # 替换为你的图像文件夹路径
# 获取图像文件列表
image_files = [f for f in os.listdir(image_folder_path) if os.path.isfile(os.path.join(image_folder_path, f))]
# 从列表中随机选择一张图像
random_image_path = os.path.join(image_folder_path, random.choice(image_files))
# 加载和预处理图像
img = Image.open(random_image_path)
img = img.resize((299, 299))
img_array = np.array(img) / 255.0
img_array = np.expand_dims(img_array, axis=0)
# 进行预测
predictions = loaded_model.predict(img_array)
# 获取预测结果
predicted_class = np.argmax(predictions)
predicted_probability = predictions[0][predicted_class]
# 获取类别标签
class_labels = ['dog', 'cat'] # 替换为你的类别标签
predicted_label = class_labels[predicted_class]
# 显示图像和预测结果
plt.imshow(img)
plt.title(f'Predicted Class: {predicted_label}\nProbability: {predicted_probability:.2%}')
plt.show()
print(f'Randomly Selected Image: {random_image_path}')
5、F1分数以及准确率展示
score = model.evaluate(test_generator, verbose=False)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
from sklearn.metrics import f1_score
test_prediction = model.predict(test_generator)
test_prediction_labels = np.argmax(test_prediction , axis = 1)
test_true_labels = test_generator.classes
f1 = f1_score(test_true_labels , test_prediction_labels , average = 'weighted')
print('test f1 Score:',f1)
在大小为5000的的测试集中,能够达到0.996的准确率,以及衡量二分类的分数也有0.996,可以看出这个模型十分不错。
四、oneAPI加速架构设计
1、oneAPI介绍
oneAPI 是由英特尔(Intel)推出的一个开发工具集合,旨在简化和统一在不同硬件架构上进行高性能计算的开发。oneAPI 提供了一套开放、灵活、跨平台的工具,使开发者能够利用 CPU、GPU、FPGA 和其他硬件加速器,以及异构系统中的各种硬件资源。
主要特点和组件:
-
统一编程模型: oneAPI 提供了一个统一的编程模型,让开发者能够在不同硬件上使用相似的代码进行高性能计算。这有助于简化代码的维护和移植。
-
DPC++ 编程语言: oneAPI 引入了 DPC++ 编程语言,这是一种基于 C++ 的扩展,支持异构计算和硬件加速器。
-
适用于不同硬件: oneAPI 不仅适用于英特尔的 CPU 和 GPU,还支持 FPGAs(可编程逻辑门阵列)等硬件。这使得开发者能够在多种加速器上部署其代码。
-
工具和库: oneAPI 提供了一系列工具和库,包括调试器、性能分析器、数学库等,帮助开发者更轻松地构建和优化高性能应用。
-
开源: oneAPI 的组件是基于开源标准和开放规范构建的,这有助于促进跨行业的合作和创新。
-
支持异构计算: oneAPI 的设计目标之一是支持异构计算,使开发者能够更好地利用不同类型的处理单元,提高应用程序的性能。
2、代码展示
使用extension for tensorflow进行优化
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 防止显示不必要的警告信息
# 设置TensorFlow为使用oneAPI加速
os.environ['TF_ENABLE_ONEAPI'] = '1'
# 加载已训练好的模型
model = tf.keras.models.load_model('./model.h5')
# 设置批量推理
batch_size = 20
# 使用oneAPI加速推理
with tf.device('/CPU:0'):
predictions = model.predict(test_generator, batch_size=batch_size)
# 将预测结果转换为类别标签
# 保存模型
model.save('./model_intel.h5')
predicted_classes =test_generator.classes
# 计算并输出 F1 分数
true_labels = test_generator.classes
f1 = f1_score(true_labels, predicted_classes)
print("F1 score:", f1)
import os
import random
from PIL import Image
import numpy as np
from tensorflow.keras.models import load_model
import matplotlib.pyplot as plt
# 加载模型
loaded_model = load_model('model_intel.h5') # 替换'model.h5'为你的模型文件名
# 图像文件夹路径
image_folder_path = './data/test_dir/dogs' # 替换为你的图像文件夹路径
# 获取图像文件列表
image_files = [f for f in os.listdir(image_folder_path) if os.path.isfile(os.path.join(image_folder_path, f))]
# 从列表中随机选择一张图像
random_image_path = os.path.join(image_folder_path, random.choice(image_files))
# 加载和预处理图像
img = Image.open(random_image_path)
img = img.resize((299, 299))
img_array = np.array(img) / 255.0
img_array = np.expand_dims(img_array, axis=0)
# 进行预测
predictions = loaded_model.predict(img_array)
# 获取预测结果
predicted_class = np.argmax(predictions)
predicted_probability = predictions[0][predicted_class]
# 获取类别标签
class_labels = ['dog', 'cat'] # 替换为你的类别标签
predicted_label = class_labels[predicted_class]
# 显示图像和预测结果
plt.imshow(img)
plt.title(f'Predicted Class: {predicted_label}\nProbability: {predicted_probability:.2%}')
plt.show()
print(f'Randomly Selected Image: {random_image_path}')
五、运行效果展示
使用oneAPI优化组件后,计算F1分数与推理的时间虽然与没有优化之前差不多,但是F1的分数达到了1。
六、总结
本实验参考代码:基于tensorflow深度学习的猫狗分类识别