【问题标题】:How to avoid using the pretrained/external model for image classification using keras in R如何避免在 R 中使用 keras 使用预训练/外部模型进行图像分类
【发布时间】:2018-01-26 08:28:56
【问题描述】:

我有以下代码。数据集可以下载herehere。该数据集包含分类为catdog 的图像。

这段代码的任务是训练猫狗图像数据。 因此,给定一张图片,它可以分辨出它是猫还是狗。 它的动机是page。下面是完整运行的代码:

library(keras)


# Organize dataset --------------------------------------------------------
options(warn = -1)

# Ths input
original_dataset_dir <- "data/kaggle_cats_dogs/original/"


# Create new organized dataset directory ----------------------------------

base_dir <- "data/kaggle_cats_dogs_small/"
dir.create(base_dir)

train_dir <- file.path(base_dir, "train")
dir.create(train_dir)

validation_dir <- file.path(base_dir, "validation")
dir.create(validation_dir)

test_dir <- file.path(base_dir, "test")
dir.create(test_dir)

train_cats_dir <- file.path(train_dir, "cats")
dir.create(train_cats_dir)

train_dogs_dir <- file.path(train_dir, "dogs")
dir.create(train_dogs_dir)

validation_cats_dir <- file.path(validation_dir, "cats")
dir.create(validation_cats_dir)

validation_dogs_dir <- file.path(validation_dir, "dogs")
dir.create(validation_dogs_dir)

test_cats_dir <- file.path(test_dir, "cats")
dir.create(test_cats_dir)

test_dogs_dir <- file.path(test_dir, "dogs")
dir.create(test_dogs_dir)

# Copying files from original dataset to newly created directory
fnames <- paste0("cat.", 1:1000, ".jpg")
dum <- file.copy(file.path(original_dataset_dir, fnames), 
          file.path(train_cats_dir)) 


fnames <- paste0("cat.", 1001:1500, ".jpg")
dum <- file.copy(file.path(original_dataset_dir, fnames), 
          file.path(validation_cats_dir))

fnames <- paste0("cat.", 1501:2000, ".jpg")
dum <- file.copy(file.path(original_dataset_dir, fnames),
          file.path(test_cats_dir))

fnames <- paste0("dog.", 1:1000, ".jpg")
dum <- file.copy(file.path(original_dataset_dir, fnames),
          file.path(train_dogs_dir))

fnames <- paste0("dog.", 1001:1500, ".jpg")
dum <- file.copy(file.path(original_dataset_dir, fnames),
          file.path(validation_dogs_dir)) 

fnames <- paste0("dog.", 1501:2000, ".jpg")
dum <- file.copy(file.path(original_dataset_dir, fnames),
          file.path(test_dogs_dir))

options(warn = -1)

# Making model ------------------------------------------------------------


conv_base <- application_vgg16(
  weights = "imagenet",
  include_top = FALSE,
  input_shape = c(150, 150, 3)
)


model <- keras_model_sequential() %>% 
  conv_base %>%
  layer_flatten() %>% 
  layer_dense(units = 256, activation = "relu") %>% 
  layer_dense(units = 1, activation = "sigmoid")

summary(model)

length(model$trainable_weights)
freeze_weights(conv_base)
length(model$trainable_weights)



# Train model -------------------------------------------------------------

train_datagen = image_data_generator(
  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"
)

# Note that the validation data shouldn't be augmented!
test_datagen <- image_data_generator(rescale = 1/255)  

train_generator <- flow_images_from_directory(
  train_dir,                  # Target directory  
  train_datagen,              # Data generator
  target_size = c(150, 150),  # Resizes all images to 150 × 150
  batch_size = 20,
  class_mode = "binary"       # binary_crossentropy loss for binary labels
)

validation_generator <- flow_images_from_directory(
  validation_dir,
  test_datagen,
  target_size = c(150, 150),
  batch_size = 20,
  class_mode = "binary"
)


# Compile model -----------------------------------------------------------

model %>% compile(
  loss = "binary_crossentropy",
  optimizer = optimizer_rmsprop(lr = 2e-5),
  metrics = c("accuracy")
)


# Evaluate  ---------------------------------------------------------------

history <- model %>% fit_generator(
  train_generator,
  steps_per_epoch = 100,
  epochs = 30,
  validation_data = validation_generator,
  validation_steps = 50
)


# Plot --------------------------------------------------------------------
plot(history)

上面的例子需要下载一个外部模型 (convnet 训练的 ImageNet)数据集,具有 VGG16 架构,功能齐全。

conv_base <- application_vgg16(
  weights = "imagenet",
  include_top = FALSE,
  input_shape = c(150, 150, 3)
)


model <- keras_model_sequential() %>% 
  conv_base %>%
  layer_flatten() %>% 
  layer_dense(units = 256, activation = "relu") %>% 
  layer_dense(units = 1, activation = "sigmoid")

对于cat/dog 数据集,这是合理的。因为 VGG16 还包含 猫和狗。

实际上,我正在执行相同的任务,分类两种类型的生物细胞而不是两种动物。所以代码是合适的,除了,因为内容不同,我似乎不能使用 VGG16 作为模型。

没有conv_base怎么写代码(合理模型)? 如果我仍然必须使用外部模型,那么合理的替代方案是什么?

【问题讨论】:

  • 是什么让你觉得你不能使用 VGG16?
  • @MatiasValdenegro AFAIK ImageNet 来自通用图像。不是非常具体的生物学数据,例如细胞。
  • 不,没关系,无论如何,学习的功能应该是有用的,有出版物通过实验证明了这一点。您应该进行实验,并且只有在得到否定结果时才尝试其他模型或预训练。

标签: r deep-learning keras tidyverse


【解决方案1】:

嗯....一个合理的模型可能是一个非常广泛和开放的问题。

您应该首先关注@Matias Valdenegro 的评论,如果您的结果不好,那么您可以尝试这些解决方案。

VGG16解决方案

首先,最简单的,你可以使用 VGG16 模型而不冻结它的权重,只是不要调用freeze_weights()

这将使 VGG16 模型得到重新训练,以满足您的需求。但另一方面,你的训练需要的时间要长得多,因为要训练的重量要多得多。

在此选项中,您还可以选择不下载预训练的 VGG16 权重,方法是将 weights = "imagenet" 替换为 weights=None(或者我认为“无”的 R 版本是 NULL)。这将创建一个完全未经训练的 VGG16 模型。

创建自定义模型

现在,这真是一个充满可能性的世界。无论您是使用卷积层、密集层还是混合层,选择多少过滤器、单元等。

一个建议是:访问 VGG16 代码并查看其架构。这是一个很好的图像分类模型。您可以复制其代码,如果需要,可以进行一些更改,例如减少过滤器和/或层的数量(因为分类两种类型的单元格可能比只分类任何类型的图像更容易)。

你可以看到它有五个块 Conv2D+Conv2D+MaxPooling2D。您可以在模型中尝试 2 或 3 个块,看看它是否足以对您的细胞进行分类。

python中的代码是here,但是你大概可以理解在R中怎么做,你只需要看看使用了哪些层。其他型号可在applications folder.

【讨论】:

    【解决方案2】:

    如果你的两类细胞可以被人眼合理区分,带有预训练模型的 VGG-16 将对你有很大帮助,因为它学习的特征与人类用来区分物体的方式非常相似。唯一的不同是将特征空间映射到您的新对象集,例如,如果您将其应用于生物细胞,那么可能所有圆形细胞都属于一个类,而椭圆形细胞是另一类(如果我的示例没有生物学意义,请原谅),所以你只需要重新训练最后一个全连接层,或者,如果结果仍然不可接受,冻结顶层重新训练几个底层,就像你引用的博客显示的那样。您可以尝试使用其他预训练的权重网络,例如 inceptionv3 等。使用训练前权重有助于大大减少训练时间和您需要的标签数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-04
      • 2017-08-13
      • 2020-09-07
      • 2019-12-30
      相关资源
      最近更新 更多