深度学习在图像分类领域的应用日益广泛。图像分类技术的核心在于根据图像中的特征或属性对图像进行标记。算法通过识别这些特征来区分不同的图像,并为它们分配标签。卷积神经网络(CNN)是构建深度学习图像分类模型的主要组成部分,它们通常用于图像识别、图像分类、目标检测等任务。
Python因其在图像分类问题中的广泛应用而广为人知。TensorFlow和Keras是构建Python图像分类器的两个流行包,但这两个库也可以在R环境中使用。本文将逐步介绍如何在R中使用Keras构建深度学习图像分类模型。
将构建一个能够对服装图像进行分类的图像分类器,如裙子、衬衫和夹克等。数据来源为Fashion MNIST数据集,包含70,000张灰度图像,每张图像都是28x28像素的灰度图,分为10个不同的类别,每个图像都有一个与之对应的标签。总共有十个标签,分别是:T恤/上衣、裤子、套头衫、连衣裙、外套、凉鞋、衬衫、运动鞋、包和踝靴。
首先,需要导入所有必需的库。
library(keras)library(tidyverse)
然后,可以直接从Keras导入Fashion MNIST数据集。此外,将使用60,000张图像来训练模型,并使用10,000张图像来评估模型的学习效果。
fashion_mnist <- dataset_fashion_mnist()c(train_images, train_labels) %<-% fashion_mnist$trainc(test_images, test_labels) %<-% fashion_mnist$test
现在有四个数组:train_images和train_labels数组包含训练集,即模型用于训练的数据。模型将在测试集上进行验证,包括test_images和test_labels数组。每张图像是一个28x28的数组,像素值范围从0到255。标签是整数数组,范围从0到9,这些与服装类别相对应。之后,将为每个图像分配一个单一的标签。由于数据集中不包含类别名称,将使用以下命令将它们保存在一个向量中,并在稍后绘制图像时使用。
class_names = c('T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot')
在训练模型之前,让查看数据集的格式。使用以下命令,将打印train_images和train_labels的维度,即60,000张图像,每张图像为28x28像素。
dim(train_images)dim(train_labels)
类似地,使用以下命令打印test_images和test_labels的维度,即10,000张图像,每张图像大小为28x28像素。
dim(test_images)dim(test_labels)
然后,可以使用以下命令查看数据集中的样本图像。
options(repr.plot.width=7, repr.plot.height=7)sample_image <- as.data.frame(train_images[7, , ])colnames(sample_image) <- seq_len(ncol(sample_image))sample_image$y <- seq_len(nrow(sample_image))sample_image <- gather(sample_image, "x", "value", -y)sample_image$x <- as.integer(sample_image$x)ggplot(sample_image, aes(x = x, y = y, fill = value)) + geom_tile() + scale_fill_gradient(low = "white", high = "black", na.value = NA) + scale_y_reverse() + theme_minimal() + theme(panel.grid = element_blank()) + theme(aspect.ratio = 1) + xlab("") + ylab("")
在训练模型之前,数据必须进行预处理。为了降低像素值,必须对数据进行归一化。目前,所有图像像素的值范围从0到255,希望值在0和1之间。因此,将通过255.0将所有像素值除以train和test数据集。
train_images <- train_images / 255test_images <- test_images / 255
为确保数据格式正确,将查看训练集中的前30张图像。还将显示每个图像下方的类别名称。
options(repr.plot.width=10, repr.plot.height=10)par(mfcol=c(10,10))par(mar=c(0, 0, 1.5, 0), xaxs='i', yaxs='i')for (i in 1:30) { img <- train_images[i, , ] img <- t(apply(img, 2, rev)) image(1:28, 1:28, img, col = gray((0:255)/255), xaxt = 'n', yaxt = 'n', main = paste(class_names[train_labels[i] + 1]))}
要构建神经网络,需要配置模型的层,如下所示:
model <- keras_model_sequential()model %>% layer_conv_2d(filters = 32, kernel_size = c(3,3), activation = 'relu', input_shape = c(28, 28, 1)) %>% layer_max_pooling_2d(pool_size = c(2,2)) %>% layer_flatten() %>% layer_dense(units = 128, activation = 'relu') %>% layer_dropout(rate = 0.5) %>% layer_dense(units = 10, activation = 'softmax')
在模型准备好训练之前,还需要一些额外的设置。这些设置在模型的编译步骤中添加:
model %>% compile( loss = 'sparse_categorical_crossentropy', optimizer = 'adam', metrics = c('accuracy'))
使用'summary'函数可以看到模型层的所有参数和形状。
summary(model)
要开始训练,将调用fit方法,它将使用训练和测试数据以及以下输入来拟合模型:
history % fit(x_train, train_labels, epochs = 20,verbose=2)
Epochs:整个数据集通过神经网络前后传递的次数。Verbose:输出的视图选择。例如,verbose = 0不打印任何内容,verbose = 1打印进度条和每个epoch的一行,verbose = 2每个epoch打印一行。
运行20个Epochs后,得到了97.36%的训练准确率。
score % evaluate(x_train, train_labels)cat('Train loss:', score$loss, "")cat('Train accuracy:', score$acc, "")
可以使用以下命令绘制准确率-损失图以及Epochs:
plot(history)
现在将看看模型在测试数据集上的表现:
score % evaluate(x_test, test_labels)cat('Test loss:', score$loss, "")cat('Test accuracy:', score$acc, "")
在测试数据集上得到了91.6%的准确率。可以利用训练好的模型对一些测试图像进行预测。
predictions % predict(x_test)
从模型中得到了预测,即测试集中每个图像的标签。让看看第一个预测:
predictions[1, ]
一个预测是一组十个数字。这些数字表示模型对图像代表每种服装的“信心”。
class_pred % predict_classes(x_test)class_pred[1:20]
options(repr.plot.width=7, repr.plot.height=7)par(mfcol=c(5,5))par(mar=c(0, 0, 1.5, 0), xaxs='i', yaxs='i')for (i in 1:25) { img <- test_images[i, , ] img <- t(apply(img, 2, rev)) predicted_label <- which.max(predictions[i, ]) - 1 true_label <- test_labels[i] if (predicted_label == true_label) { color <- 'blue' } else { color <- 'red' } image(1:28, 1:28, img, col = gray((0:255)/255), xaxt = 'n', yaxt = 'n', main = paste0(class_names[predicted_label + 1], "(",class_names[true_label + 1], ")"),col.main = color)}