如何使用Keras顺序API和Tensorflow下载花朵数据集?
在机器学习领域中,我们会经常使用各种数据集来训练和测试我们的模型。其中,花朵数据集是一个十分常用的数据集,其中包含了五种不同种类的花的图片,是一个较为典型的分类问题。那么在这篇文章中,我们将会学习如何使用Keras顺序API和TensorFlow下载花朵数据集,并进行简单地数据预处理和模型训练。
更多Python文章,请阅读:Python 教程
花朵数据集介绍
花朵数据集一共包含了4242张图片,分成了五种不同类别。其中每个类别都包含有大概800张到1100张不等的图片。数据集中的图片尺寸不一,有些图片宽度为500像素、有些高度为500像素,而有些则是正方形的。数据集的五个类别是:daisy(雏菊)、dandelion(蒲公英)、rose(玫瑰)、sunflower(向日葵)、tulip(郁金香)。
数据下载及处理
首先,我们需要下载这个数据集。在tensorflow.keras.datasets中已经集成好了这个数据集,我们只需要调用keras.datasets中的load_data函数即可下载花朵数据集。
from tensorflow.keras.datasets import flower
(x_train,y_train),(x_test,y_test) = flower.load_data()
上述代码中,我们将读取到的数据集分别保存在了4个numpy数组中:x_train,y_train为训练集,x_test,y_test为测试集。
接下来,我们可以输出一下x_train和y_train的形状,以及y_train的一个样例。
print(x_train.shape)
print(y_train.shape)
print(y_train[0])
输出结果为:
(3320,)
(3320,)
1
可以看到,x_train的数据的shape是(3320,),而不是我们期望的(3320, ~ ~)。这是因为这个数据集中的每个图像都有不同的形状,所以我们需要在数据预处理阶段将数据转换为相同的尺寸。另外,y_train中的每个元素都是一个范围在0到4之间表示花朵类别的数字。我们可以通过一个简单的字典的方式将这个数字转换成对应的花朵类别名称。
class_dict = {
0:'daisy',
1:'dandelion',
2:'rose',
3:'sunflower',
4:'tulip'
}
# 输出y_train的第一个元素对应的类别名称
print(class_dict[y_train[0]])
接下来,我们需要将数据的形状转换为相同的尺寸。为了做到这一点,常见的方法是将所有的图像都缩放成相同的大小,然后将它们都剪裁成相同的形状。对于花朵数据集,我们将把每张图像缩放成一个64×64的尺寸,并将所有的图像都转换成RGB格式。这个任务可以通过使用resize
和cvtColor
函数来轻松完成。
import cv2
import numpy as np
def preprocess(data):
# 创建空列表来存储缩放后的图像
processed_data = []
# 缩放后的图像的形状为(64,64,3)
target_shape = (64,64)
for image in data:
# 缩放图像
resized_image = cv2.resize(image, target_shape)
# 转换为RGB格式
# 注意:在flower.load_data()函数中,返回的数据是以黑白格式存储的(灰度图像)
# 需要将其转换为RGB格式
resized_image = cv2.cvtColor(resized_image, cv2.COLOR_GRAY2RGB)
# 将处理后的数据保存到列表中
processed_data.append(resized_image)
# 将处理后的数据转换为numpy数组形式,返回
return np.array(processed_data)
# 获取预处理后的训练数据和测试数据
x_train_processed = preprocess(x_train)
x_test_processed = preprocess(x_test)
# 输出转换后的数据的形状
print(x_train_processed.shape)
print(x_test_processed.shape)
输出结果为:
(3320, 64, 64, 3)
(912, 64, 64, 3)
数据预处理完成后,我们可以使用Keras顺序API创建一个简单的卷积神经网络来对花朵进行分类。
神经网络模型构建
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Flatten, Dense
model = Sequential([
# 第一个卷积层
Conv2D(32, kernel_size=(3,3), input_shape=(64, 64, 3), activation='relu'),
# 第二个卷积层
Conv2D(64, kernel_size=(3,3), activation='relu'),
# 将卷积层输出的特征图转换为向量
Flatten(),
# 全连接层1
Dense(128, activation='relu'),
# 全连接层2,输出层
Dense(5, activation='softmax')
])
# 编译模型,定义损失函数和优化算法
model.compile(loss='sparse_categorical_crossentropy',
optimizer='adam',
metrics=['acc'])
上述代码中,我们使用了一些常用的卷积神经网络层,包括2个卷积层和2个全连接层。其中,第一个卷积层中使用了32个过滤器,过滤器大小为3×3,输入图像的大小为64×64,使用了relu激活函数。第二个卷积层中使用了64个过滤器,大小和激活函数与第一个卷积层相同。随后,我们将卷积层的输出通过Flatten层转换为向量,然后经过2个全连接层进行特征融合和分类输出。
这里需要注意的是,输出层使用了softmax激活函数,因为我们要将输出映射到一个概率分布中,来预测每张图片属于五种花中的哪一种。另外,损失函数选用了sparse_categorical_crossentropy,因为我们的标签数据是以数字表示的。
神经网络模型训练
接下来,我们可以将训练数据和标签传入模型中,开始训练模型。
history = model.fit(x_train_processed,
y_train,
batch_size=32,
epochs=10,
validation_data=(x_test_processed, y_test))
在上述代码中,我们设置了训练的超参数,包括batch_size为32,epochs为10。然后将训练数据和标签传入模型中进行训练。训练过程中,我们还传入了测试数据和标签用于验证训练结果。
运行完训练代码后,我们可以展示训练过程中的误差和准确率变化情况。
import matplotlib.pyplot as plt
def plot_history(history):
# 绘制损失函数和准确率的变化
plt.plot(history.history['loss'], label='train_loss')
plt.plot(history.history['val_loss'], label='val_loss')
plt.plot(history.history['acc'], label='train_acc')
plt.plot(history.history['val_acc'], label='val_acc')
plt.legend()
plt.show()
plot_history(history)
可以看到,训练集的准确率和损失函数都逐步收敛到较好的状态,但测试集上的结果却始终无法提高,这可能是因为我们的模型过拟合了。我们可以通过添加正则化层、扩大数据集或增加模型复杂度等方式来改善这个问题。
结论
在本文中,我们学习了如何使用Keras顺序API和Tensorflow下载花朵数据集,并进行简单的数据预处理和卷积神经网络模型训练。我们通过对训练集和测试集的评估发现,模型存在过拟合的问题,需要进一步的优化和改善。但本文提供的这个简单模型可作为学习进阶模型之前的教学示例。