Cats vs Dogs 识别图像

目录

一.实验介绍

1.1 课题方向

1.2 目标任务

1.3 数据集

1.4 图像展示

二.数据集划分处理

2.1 数据集目录

2.2 train数据集划分

2.3 数据处理

3. 使用卷积神经网络识别猫狗图像

3.1 vgg16

3.2 CNN

3.3 模型修改

4 在cpu上训练模型

4.1 训练的参数和方法

4.2 在cpu上完成训练20个Epoch

4.3 检验并保存模型

4.4 抽样检测模型

5. 运用one api提升模型性能

5.1 迁移学习 Transfer Learning with oneAPI AI Analytics Toolkit

5.2 Intel Extension for PyTorch 优化并保存优化后的模型

5.3加载模型,并以准确度为评估函数进行量化

5.4 使用量化后的模型进行推理

6.实验总结


一.实验介绍

1.1 课题方向

  在问题中,你将面一个典的机器学分类挑——猫狗大。你的任是建立一个分类模型,能够准确地区分像中是猫是狗

1.2 目标任务

  你的目标是通过训练一个机器学习模型,使其在给定一张图像时能够准确地预测图像中是猫还是狗。模型应该能够推广到未见过的图像,并在测试数据上表现良好。期待您将其部署到模的生产环境中——里推理时间和二分类准确度(F1分数)将作为评分的主要依据

1.3 数据集

数据集:

链接:百度网盘 请输入提取码

提取码:jc34

1.4 图像展示

1.cat

2.dog

二.数据集划分处理

2.1 数据集目录

初始数据集猫狗.zip解压获得train和猫狗大战_test文件夹,其中train中含cat类12500张,含dog类12500张,猫狗_test含有两个子目录,分别是cats和dogs,各自含有cat类500张和dog类500张。

2.2 train数据集划分

a.从训练集train中,按类别cat和dog,选取10000张图片,6000张用于训练,2000张用于验证,2000张用于测试,并创建train_dataset及其子目录

import os
import shutil

# 初始训练集train
original_dataset_dir = 'train'
# 创建目录结构

#创建train_dataset,其子目录train
base_dir = 'train_dataset/train'
os.makedirs(base_dir, exist_ok=True)

#创建train_dataset/train/train作为模型训练
train_dir = os.path.join(base_dir, 'train')
os.makedirs(train_dir, exist_ok=True)

#创建train_dataset/train/validation作为模型验证
validation_dir = os.path.join(base_dir, 'validation')
os.makedirs(validation_dir, exist_ok=True)

#创建train_dataset/train/validation作为模型测试
test_dir = os.path.join(base_dir, 'test')
os.makedirs(test_dir, exist_ok=True)

b.在子目录train,test和validation中,分别创建cats和dogs子目录

# 训练集文件
train_cats_dir = os.path.join(train_dir, 'cats')
os.makedirs(train_cats_dir, exist_ok=True)

train_dogs_dir = os.path.join(train_dir, 'dogs')
os.makedirs(train_dogs_dir, exist_ok=True)

# 验证集文件
validation_cats_dir = os.path.join(validation_dir, 'cats')
os.makedirs(validation_cats_dir, exist_ok=True)

validation_dogs_dir = os.path.join(validation_dir, 'dogs')
os.makedirs(validation_dogs_dir, exist_ok=True)

# 测试集文件
test_cats_dir = os.path.join(test_dir, 'cats')
os.makedirs(test_cats_dir, exist_ok=True)

test_dogs_dir = os.path.join(test_dir, 'dogs')
os.makedirs(test_dogs_dir, exist_ok=True)

c.像其中放入抽取的图片

#分别向集合中放入初始训练集的图片
# 训练集 - 猫和狗
fnames = ['cat.{}.jpg'.format(i) for i in range(3000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(train_cats_dir, fname)
    shutil.copyfile(src, dst)

fnames = ['dog.{}.jpg'.format(i) for i in range(3000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(train_dogs_dir, fname)
    shutil.copyfile(src, dst)
    
# 验证集 - 猫和狗
fnames = ['cat.{}.jpg'.format(i) for i in range(3000, 4000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(validation_cats_dir, fname)
    shutil.copyfile(src, dst)
    
fnames = ['dog.{}.jpg'.format(i) for i in range(3000, 4000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(validation_dogs_dir, fname)
    shutil.copyfile(src, dst)
    
# 测试集 - 猫和狗
fnames = ['cat.{}.jpg'.format(i) for i in range(4000, 5000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(test_cats_dir, fname)
    shutil.copyfile(src, dst)

fnames = ['dog.{}.jpg'.format(i) for i in range(4000, 5000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(test_dogs_dir, fname)
    shutil.copyfile(src, dst)

d.检验图片放入是否数量正确

#数据划分的结果检验
import os
from IPython.display import display, HTML
def count_images_in_directory(directory):
    count = sum([len(files) for _, _, files in os.walk(directory)])
    return count

# 打印初始train图片数量
target_directory = 'train'
total_images = count_images_in_directory(target_directory)
display(HTML(f"<p>目录 '{target_directory}' 中的总图片数量为: <strong>{total_images}</strong></p>"))

# 打印初始test图片数量
target_directory = 'test'
total_images = count_images_in_directory(target_directory)
display(HTML(f"<p>目录 '{target_directory}' 中的总图片数量为: <strong>{total_images}</strong></p>"))

# 打印/train_dataset/train/train/cats图片数量
target_directory = './train_dataset/train/train/cats'
total_images = count_images_in_directory(target_directory)
display(HTML(f"<p>目录 '{target_directory}' 中的总图片数量为: <strong>{total_images}</strong></p>"))

# 打印/train_dataset/train/train/dogs图片数量
target_directory = './train_dataset/train/train/dogs'
total_images = count_images_in_directory(target_directory)
display(HTML(f"<p>目录 '{target_directory}' 中的总图片数量为: <strong>{total_images}</strong></p>"))

# 打印/train_dataset/train/validation/cats图片数量
target_directory = './train_dataset/train/validation/cats'
total_images = count_images_in_directory(target_directory)
display(HTML(f"<p>目录 '{target_directory}' 中的总图片数量为: <strong>{total_images}</strong></p>"))

# 打印/train_dataset/train/validation/dogs图片数量
target_directory = './train_dataset/train/validation/dogs'
total_images = count_images_in_directory(target_directory)
display(HTML(f"<p>目录 '{target_directory}' 中的总图片数量为: <strong>{total_images}</strong></p>"))

# 打印/train_dataset/train/test/cats图片数量
target_directory = './train_dataset/train/test/cats'
total_images = count_images_in_directory(target_directory)
display(HTML(f"<p>目录 '{target_directory}' 中的总图片数量为: <strong>{total_images}</strong></p>"))

# 打印/train_dataset/train/test/dogs图片数量
target_directory = './train_dataset/train/test/dogs'
total_images = count_images_in_directory(target_directory)
display(HTML(f"<p>目录 '{target_directory}' 中的总图片数量为: <strong>{total_images}</strong></p>"))

2.3 数据处理

#导包和样本目录
from keras import models, layers
from tensorflow.keras.applications import VGG16
from tensorflow import optimizers
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt

#训练样本的目录
train_dir='./train_dataset/train/train'
#验证样本的目录
validation_dir='./train_dataset/train/validation'
#测试样本目录
test_dir='./train_dataset/train/test'
#训练集生成器,数据加强
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')
 
train_generator=train_datagen.flow_from_directory(
    directory=train_dir,
    target_size=(150,150),
    class_mode='binary',
    batch_size=20
)
#cats和dogs的分类标签
print(train_generator.class_indices)
print(test_generator.class_indices)
print(validation_generator.class_indices)

3. 使用卷积神经网络识别猫狗图像

3.1 vgg16

  VGG16是由Karen Simonyan和Andrew Zisserman于2014年在论文“VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE SCALE IMAGE RECOGNITION”中提出的一种处理多分类、大范围图像识别问题的卷积神经网络架构, 本项目将分类层的最后一层修改为(1x1x2)即可将分类结果从1000类 修改为二分类。

3.2 CNN

    卷积神经网络(Convolutional Neural Network,CNN)是一种专门用于处理具有网格结构数据(如图像和视频)的深度学习模型。CNN 在计算机视觉任务中取得了巨大成功,因为它能够有效地捕获图像中的空间结构信息。

3.3 模型修改

   对传统的VGG-16网络进行了调整,将其输出大小改为2,并优化了网络结构,适应本项目需求

vgg16_model = models.vgg16(pretrained=True)
 
# 解冻最后几层
for param in vgg16_model.features.parameters():
    param.requires_grad = False
 
# 修改分类层
num_features = vgg16_model.classifier[6].in_features
vgg16_model.classifier[6] = nn.Sequential(
    nn.Linear(num_features, 512),
    nn.ReLU(),
    nn.Dropout(0.5),
    nn.Linear(512, 2)
)

4 在cpu上训练模型

4.1 训练的参数和方法

   在jupyter上默认使用cpu进行模型训练,完成vgg16实例化,冻结卷积层,构建基于vgg16的网络结构,使用adam优化函数,使用代价函数,并在过程中记录准确率

#VGG 16实例化---使用imagenet数据集训练,全连接层
conv_base = VGG16(weights='imagenet',
                  include_top=False,  #是否指定模型最后是否包含密集连接分类器
                  input_shape=(150, 150, 3))
#冻结卷积基----保证其权重在训练过程中不变
conv_base.trainable = False

#构建网络模型----基于VGG16建立模型
model = models.Sequential()
model.add(conv_base)
model.add(layers.Flatten(input_shape=conv_base.output_shape[1:]))  #图片输出四维,1代表数量
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1, activation='sigmoid'))  #二分类
#定义优化器、代价函数、训练过程中计算准确率
model.compile(optimizer=optimizers.Adam(learning_rate=0.001),
              loss='binary_crossentropy',
              metrics=['acc'])
model.summary()

4.2 在cpu上完成训练20个Epoch

history=model.fit_generator(
    train_generator,
    steps_per_epoch=100,
    epochs=20,
    validation_data=validation_generator,
    validation_steps=50
)

4.3 检验并保存模型

#保存模型
model.save('model/model4_2_VGG 16_cats_vs_dogs_1.pth')
#评估测试集的准确率[los,Accuracy]
test_eval=model.evaluate(test_generator)
print("测试集准确率:",test_eval)
train_eval=model.evaluate(train_generator)
print("训练集准确率:",train_eval)
val_eval=model.evaluate(validation_generator)
print("验证集准确率:",val_eval)

推理时间和f1的值

from keras.models import load_model
from keras.preprocessing.image import ImageDataGenerator
import numpy as np
import time
from sklearn.metrics import f1_score

# 加载模型
model = load_model('model/model4_2_VGG 16_cats_vs_dogs_1.h5')
model.summary()

test_datagen = ImageDataGenerator(rescale=1./255)
test_generator = test_datagen.flow_from_directory(
    directory="猫狗大战_test",
    target_size=(150,150),
    shuffle=False,
    class_mode='binary',
    batch_size=20
)

# 预测
start_time = time.time()

result = model.predict(test_generator)

end_time = time.time()

# 转换为整数
result = [(int((result[i][0] + 0.5) / 1.0)) for i in range(len(result))]

# 计算 F1 值
f1 = f1_score(test_label, result)

print("推理时间: {} 秒".format(end_time - start_time))
print("F1 值: ", f1)

4.4 抽样检测模型

冲测试目录的cats和dogs各抽取两张,调用保存好的vgg16模型进行测试

#随机抽样测试模型
import os
import random
from keras.models import load_model
from keras.preprocessing import image
import numpy as np
from PIL import Image
from IPython.display import display
# 加载模型
model = load_model('model/model4_2_VGG 16_cats_vs_dogs_1.h5')
model.summary()

# 定义图像预处理函数
def preprocess_image(img_path, target_size=(150, 150)):
    img = image.load_img(img_path, target_size=target_size)
    img_array = image.img_to_array(img)
    img_array = np.expand_dims(img_array, axis=0)
    img_array /= 255.0  # 归一化
    return img_array

# 获取 'cats' 文件夹中的所有图像文件
test_images_path = "train_dataset/test2/cats"
all_test_images = [os.path.join(test_images_path, img) for img in os.listdir(test_images_path)]

# 从 'cats' 文件夹中随机选择 2 张图片
selected_test_images = random.sample(all_test_images, 2)

# 预测并输出结果
for img_path in selected_test_images:
    # 预处理图像
    img_array = preprocess_image(img_path)
    
    # 预测
    prediction = model.predict(img_array)
    prediction = int((prediction[0][0] + 0.5) / 1.0)  # 转为整数
    
    # 打印预测结果
    print(f"图像路径: {img_path}, 预测结果: {'猫' if prediction == 0 else '狗'}")
    img = Image.open(img_path)
    display(img)

# 获取 'dogs' 文件夹中的所有图像文件
test_images_path = "train_dataset/test2/dogs"
all_test_images = [os.path.join(test_images_path, img) for img in os.listdir(test_images_path)]

# 从 'cats' 文件夹中随机选择 2 张图片
selected_test_images = random.sample(all_test_images, 2)

# 预测并输出结果
for img_path in selected_test_images:
    # 预处理图像
    img_array = preprocess_image(img_path)
    
    # 预测
    prediction = model.predict(img_array)
    prediction = int((prediction[0][0] + 0.5) / 1.0)  # 转为整数
    
    # 打印预测结果
    print(f"图像路径: {img_path}, 预测结果: {'猫' if prediction == 0 else '狗'}")
    img = Image.open(img_path)
    display(img)
    

测试结果均正确

5. 运用one api提升模型性能

5.1 迁移学习 Transfer Learning with oneAPI AI Analytics Toolkit

class CustomVGG16(nn.Module):
    def __init__(self):
        super(CustomVGG16, self).__init__()
        self.vgg16_model = models.vgg16(pretrained=True)
        for param in self.vgg16_model.features.parameters():
            param.requires_grad = False
        num_features = self.vgg16_model.classifier[6].in_features
        self.vgg16_model.classifier[6] = nn.Sequential(
            nn.Linear(num_features, 512),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(512, 2)
        )
 
    def forward(self, x):
        return self.vgg16_model(x)
 
# 创建 CustomVGG16 模型实例
vgg16_model = CustomVGG16()
 
 
 
# 创建 CustomVGG16 模型实例
 
 
 
# 加载权重
vgg16_model.vgg16_model.load_state_dict(torch.load('vgg16.pth', map_location=torch.device('cpu')))
 
 

5.2 Intel Extension for PyTorch 优化并保存优化后的模型

​

# 将模型移动到CPU
device = torch.device('cpu')
vgg16_model.to(device)
 
# 重新构建优化器
optimizer = optim.Adam(vgg16_model.parameters(), lr=0.001, weight_decay=1e-4)
 
# 使用Intel Extension for PyTorch进行优化
vgg16_model, optimizer = ipex.optimize(model=vgg16_model, optimizer=optimizer, dtype=torch.float32)

优化后,在次执行cpu上调用保存的模型,得到了推理时间变短的结果如下

保存模型

# 保存模型参数
torch.save(vgg16_model.state_dict(), 'vgg16_optimized.pth')
 
# 加载模型参数
loaded_model = CustomVGG16()
loaded_model.load_state_dict(torch.load('vgg16_optimized.pth'))

5.3加载模型,并以准确度为评估函数进行量化

from neural_compressor.config import PostTrainingQuantConfig, AccuracyCriterion
from neural_compressor import quantization
import os
 
# 加载模型
model = CustomVGG16()
model.load_state_dict(torch.load('vgg16_optimized.pth'))
model.to('cpu')  # 将模型移动到 CPU
model.eval()
 
# 定义评估函数
def eval_func(model):
    with torch.no_grad():
        y_true = []
        y_pred = []
 
        for inputs, labels in train_loader:
            inputs = inputs.to('cpu')
            labels = labels.to('cpu')
            preds_probs = model(inputs)
            preds_class = torch.argmax(preds_probs, dim=-1)
            y_true.extend(labels.numpy())
            y_pred.extend(preds_class.numpy())
 
        return accuracy_score(y_true, y_pred)
 
# 配置量化参数
conf = PostTrainingQuantConfig(backend='ipex',  # 使用 Intel PyTorch Extension
                               accuracy_criterion=AccuracyCriterion(higher_is_better=True, 
                                                                   criterion='relative',  
                                                                   tolerable_loss=0.01))
 
# 执行量化
q_model = quantization.fit(model,
                           conf,
                           calib_dataloader=train_loader,
                           eval_func=eval_func)
 
# 保存量化模型
quantized_model_path = './quantized_models'
if not os.path.exists(quantized_model_path):
    os.makedirs(quantized_model_path)
 
q_model.save(quantized_model_path)

量化结果

量化后保存

5.4 使用量化后的模型进行推理

import torch
import json
 
from neural_compressor import quantization
 
# 指定量化模型的路径
quantized_model_path = './quantized_models'
 
# 加载 Qt 模型和 JSON 配置
vgg16_model_path = f'{quantized_model_path}/best_model.pt'
json_config_path = f'{quantized_model_path}/best_configure.json'
 
# 加载 Qt 模型
vgg16_model = torch.jit.load(vgg16_model_path, map_location='cpu')
 
# 加载 JSON 配置
with open(json_config_path, 'r') as json_file:
    json_config = json.load(json_file)
 
# 打印 JSON 配置(可选)
print(json_config)

明显在推理速度上得到了提升

6.实验总结

  完成基础的模型训练后,再使用oneAPI优化组件,推理的速度有明显提升,如果在使用量化工具,推理的时间还能可以进一步下降,并且在整个过程中F1分数的值一直能稳定在0.89以上,这是一个非常好的现象。证明了oneAPI优秀的模型压缩能力,在保证模型精确度,F1值的基础上还能够缩小模型的规模。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值