浅谈人工智能之基于VGG16与Kmeans进行图像分类
摘要
随着深度学习技术的快速发展,卷积神经网络(CNN)在图像识别领域取得了显著的成就。VGG16作为经典的CNN模型之一,因其结构简单、性能稳定而被广泛应用于各种图像分类任务中。本文将详细介绍如何使用VGG16模型进行图像分类,包括模型的结构、训练过程、优化技巧以及实际应用案例。
VGG16模型简介
VGG16是由牛津大学的Visual Geometry Group (VGG)提出的一种深度卷积神经网络模型。该模型在2014年的ImageNet竞赛中取得了优异的成绩。VGG16的主要特点包括:
● 深度:模型包含16个可训练的层(13个卷积层和3个全连接层)。
● 结构简单:所有卷积层均使用3x3的小卷积核,步长为1,填充为1,使得输出的特征图大小与输入相同。
● 池化层:每个卷积层组后接一个2x2的最大池化层,步长为2,用于降低特征图的尺寸。
实战应用
我们为了简化操作实验步骤,我们通过两张图片经过数据增强生成多张图片进行训练,并且利用另外两张图片作为测试数据进行验证。
训练图片数据如下:
测试图片数据如下:
开发搭建
我们的开发环境如下:
python:Python 3.8.10
依赖环境如下:
pip install keras
pip install pandas
pip install tensorflow
pip install sklearn
如果提示还需要安装其他赖,则在提示下进行安装。
数据增强
我们分别将训练图片的两张图片,分别生成100张和20张图片。
第一步:在root目录下新建文件夹vgg,并且在此文件夹下从创建另外一个文件夹。
mkdir vgg
cd vgg
mkdir enhance
因此我们整体的目录的绝对类路径是:/root/vgg/enhance
第二步:将训练图片中的其中一张图片放到enhance目录下,代码如下
import os
from keras.preprocessing.image import ImageDataGenerator
# 定义路径
path = '/root/vgg'
dst_path = '/root/enhance_data'
# 检查路径是否存在,如果不存在则创建
os.makedirs(dst_path, exist_ok=True)
# 定义数据增强参数
datagen = ImageDataGenerator(
rotation_range=10, # 旋转范围,角度值
width_shift_range=0.1, # 水平平移范围
height_shift_range=0.02, # 垂直平移范围
horizontal_flip=True, # 水平翻转
vertical_flip=True # 垂直翻转
)
# 生成数据
gen = datagen.flow_from_directory(
path,
target_size=(224, 224), # 图像大小
batch_size=2, # 批量大小
save_to_dir=dst_path, # 保存生成的图像路径
save_prefix='gen', # 保存图像的前缀
save_format='jpg' # 保存图像的格式
)
# 生成并保存图像
for i in range(100):
try:
gen.next()
except Exception as e:
print(f"Error generating image: {e}")
第三步:在root下新建另外一个文件夹train_data
第四步:将刚刚生成的图片剪切到train_data文件夹下,然后重复第二个步骤,把另外的20张生成的图片放到train_data中。
单张图片数据加载和特征提取
我们首先尝试对单个数据进行加载和特征提取。
第一步:加载图片
from keras.preprocessing.image import load_img, img_to_array
img_path = 'baby.png'
img = load_img(img_path,target_size=(224,224))
print(type(img))
第二步:可视化图片并且进行展示
from matplotlib import pyplot as p
figOne = p.figure()
p.imshow(img)
结果如下:
第三步:格式转换
img = img_to_array(img)
print(type(img))
print(img.shape)
打印的结果如下:
<class ‘numpy.ndarray’>
(1, 224, 224, 3)
第四步:数据的维度转化和预处理
from keras.applications.vgg16 import preprocess_input
import numpy as npy
img_to_do = npy.expand_dims(img,axis=0)
print(img_to_do.shape)
img_to_do = preprocess_input(img_to_do)
第五步:特征提取
from keras.applications.vgg16 import VGG16
m_vgg16 = VGG16(weights='imagenet',include_top=False)
featuresForImg = m_vgg16.predict(img_to_do)
print(featuresForImg.shape,featuresForImg)
第六步:特征展开
featuresForImg = featuresForImg.reshape(1,7*7*512)
print(featuresForImg.shape)
打印的结果如下:
(1, 25088)
多张图片数据加载和特征提取
当我们可以获取单张实现特征提取时,我们可以批量对图片进行操作
第一步:获取所有图片路径
import os
# 定义文件夹路径
folder = '/root/train_data'
# 获取文件夹中的所有文件名
files_name = os.listdir(folder)
# 用于存储图片路径的列表
img_path = []
# 遍历文件名,筛选出.jpg文件并构建完整路径
for file_name in files_name:
if os.path.splitext(file_name)[1].lower() == '.jpg':
img_path.append(os.path.join(folder, file_name))
# 打印图片路径
print(img_path)
第二步:根据单张特征提取的方法,我们写一个vgg16的特征提取的方法
def modelProcess(img_path, model):
try:
# 加载图像并调整大小
img = image.load_img(img_path, target_size=(224, 224))
# 将图像转换为数组
img_array = image.img_to_array(img)
# 增加一个维度以匹配模型输入要求
img_array = npy.expand_dims(img_array, axis=0)
# 预处理图像
img_array = preprocess_input(img_array)
# 使用模型进行预测
features = model.predict(img_array)
# 重塑特征向量
features = features.reshape(1, 7 * 7 * 512)
return features
except Exception as e:
print(f"Error processing image {img_path}: {e}")
return None
第三步:批量提取特征
features_train = npy.zeros([len(img_path),7*7*512])
for i in range(len(img_path)):
features_temp = modelProcess(img_path[i],model_vgg16)
features_train[i] = features_temp
print('preprocess:',img_path[i])
执行以后我们可以看到如下信息
第四步:打印样本梳理和特征数
print(features_train.shape)
#赋值
X = features_train
print(X.shape)
第五步:使用kemeans进行聚类分析训练
from sklearn.cluster import KMeans
vgg_kmeans = KMeans(n_clusters=2,max_iter=3000)
#训练
vgg_kmeans.fit(X)
第六步:结果预测和打印
y_predict_km = vgg_kmeans.predict(X)
print(y_predict_km)
结果显示如下:
第七步:统计结果分布
import pandas as pd
print(pd.value_counts(y_predict_km))
结果显示如下:
第八步:图形化展示
# 设置有婴儿头像的标签为0
baby_id = 0
# 创建图形
figTwo = plt.figure(figsize=(10, 40))
# 遍历图像并绘制
for i in range(30):
for j in range(4):
index = i * 4 + j
if index < len(img_path):
img = image.load_img(img_path[index], target_size=(224, 224))
plt.subplot(30, 4, index + 1)
plt.title('baby' if y_predict_km[index] == baby_id else 'swim')
plt.imshow(img)
plt.axis('off')
else:
break # 如果图像路径列表不足120张,提前退出循环
plt.tight_layout()
plt.show()
显示结果如下
测试数据集
训练的数据集预测以后,我们针对测试数据集进行预测,这里就不再累赘,直接上代码:
import os
# 定义文件夹路径
folder = '/root/test_data'
# 获取文件夹中的所有文件名
files_name = os.listdir(folder)
# 用于存储图片路径的列表
img_path = []
# 遍历文件名,筛选出.jpg文件并构建完整路径
for file_name in files_name:
if os.path.splitext(file_name)[1].lower() == '.jpg':
img_path.append(os.path.join(folder, file_name))
# 打印图片路径
print(img_path)
#批量提取图片特征
features_test = np.zeros([len(img_path),7*7*512])
for i in range(len(img_path)):
features_temp = modelProcess(img_path[i],model_vgg16)
features_test[i] = features_temp
print('preprocess:',img_path[i])
# 创建图形
figThree = plt.figure(figsize=(10, 40))
# 遍历图像并绘制
for i in range(2):
for j in range(1):
index = i * 4 + j
if index < len(img_path):
img = image.load_img(img_path[index], target_size=(224, 224))
plt.subplot(2, 1, index + 1)
plt.title('baby' if y_predict_km_test[index] == baby_id else 'swim')
plt.imshow(img)
plt.axis('off')
else:
break # 如果图像路径列表不足120张,提前退出循环
plt.tight_layout()
plt.show()
#X_test
X_test = features_test
print(X_test.shape)
#测试数据预测
y_predict_km_test = vgg_kmeans.predict(X_test)
print(y_predict_km_test)
结果如下: