【问题标题】:Why do I get a small values with InceptionV3 ? how to set a threshold to detect the present classes in the image?为什么我使用 InceptionV3 得到一个小值?如何设置阈值来检测图像中的当前类?
【发布时间】:2018-01-02 12:24:02
【问题描述】:

在针对多类多标签分类问题将 InceptionV3 微调到我自己的数据集后,我正在使用 InceptionV3 我做了最重要的更改,例如将 softmax 更改为 sigmoid,并且我正在使用这个损失函数

model.compile(loss='binary_crossentropy',optimizer=keras.optimizers.Adam(),metrics=['accuracy'])

但是当我预测使用生成的模型时,我会得到一个像这样的小值 [ 2.74303748e-04 7.97736086e-03 2.44359515e-04 7.09630767e-05 5.43296163e-04 4.08404367e-03 3.28547925e-01 1.05091414e-04 1.80469989e-03 2.85170972e-03 1.44978316e-04 7.78235449e-03 1.72435939e-02 1.55413849e-02 3.82270187e-01 1.06311939e-03 2.70067930e-01 6.08937175e-04 7.47230020e-04 1.07850268e-04] 源代码是这样的:(它可以是我的验证集吗?)

import keras
import os
import sys
import glob
import argparse
import matplotlib.pyplot as plt


from keras import __version__
from keras.applications.inception_v3 import InceptionV3, 
preprocess_input
from keras.models import Model
from keras.layers import Dense, GlobalAveragePooling2D
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import SGD


IM_WIDTH, IM_HEIGHT = 299, 299 #fixed size for InceptionV3
NB_EPOCHS = 3
BAT_SIZE = 32
FC_SIZE = 1024
NB_IV3_LAYERS_TO_FREEZE = 172


def get_nb_files(directory):
   """Get number of files by searching directory recursively"""
  if not os.path.exists(directory):
    return 0
  cnt = 0
  for r, dirs, files in os.walk(directory):
    for dr in dirs:
      cnt += len(glob.glob(os.path.join(r, dr + "/*")))
  return cnt


def setup_to_transfer_learn(model, base_model):
  """Freeze all layers and compile the model"""
  for layer in base_model.layers:
    layer.trainable = False
  #model.compile(optimizer='rmsprop', loss='categorical_crossentropy', 
#metrics=['accuracy'])
  model.compile(loss='binary_crossentropy',
  optimizer=keras.optimizers.Adam(),metrics=['accuracy'])

def add_new_last_layer(base_model, nb_classes):
  """Add last layer to the convnet
  Args:
    base_model: keras model excluding top
    nb_classes: # of classes
  Returns:
        new keras model with last layer
  """
  x = base_model.output
  x = GlobalAveragePooling2D()(x)
  x = Dense(FC_SIZE, activation='relu')(x) #new FC layer, random init
  predictions = Dense(nb_classes, activation='sigmoid')(x) 

  model = Model(input=base_model.input, output=predictions)
  return model


def setup_to_finetune(model):
  """Freeze the bottom NB_IV3_LAYERS and retrain the remaining top 
     layers.
  note: NB_IV3_LAYERS corresponds to the top 2 inception blocks in the 
  inceptionv3 arch
  Args:
    model: keras model
  """
  for layer in model.layers[:NB_IV3_LAYERS_TO_FREEZE]:
     layer.trainable = False
  for layer in model.layers[NB_IV3_LAYERS_TO_FREEZE:]:
     layer.trainable = True

model.compile(loss='binary_crossentropy',
optimizer=keras.optimizers.Adam(),metrics=['accuracy']) 

def train(args):
  """Use transfer learning and fine-tuning to train a network on a new 
  dataset"""
  nb_train_samples = get_nb_files(args.train_dir)
  nb_classes = len(glob.glob(args.train_dir + "/*"))
  nb_val_samples = get_nb_files(args.val_dir)
  nb_epoch = int(args.nb_epoch)
  batch_size = int(args.batch_size)

  # data prep
  train_datagen =  ImageDataGenerator(
   preprocessing_function=preprocess_input,
   rotation_range=30,
   width_shift_range=0.2,
   height_shift_range=0.2,
   shear_range=0.2,
   zoom_range=0.2,
   horizontal_flip=True
  )
  test_datagen = ImageDataGenerator(
      preprocessing_function=preprocess_input,
      rotation_range=30,
      width_shift_range=0.2,
      height_shift_range=0.2,
      shear_range=0.2,
      zoom_range=0.2,
      horizontal_flip=True
  )

  train_generator = train_datagen.flow_from_directory(
    args.train_dir,
    target_size=(IM_WIDTH, IM_HEIGHT),
    batch_size=batch_size,
  )

  validation_generator = test_datagen.flow_from_directory(
    args.val_dir,
    target_size=(IM_WIDTH, IM_HEIGHT),
    batch_size=batch_size,
  )

  # setup model
  base_model = InceptionV3(weights='imagenet', include_top=False) 
  #include_top=False excludes final FC layer
  model = add_new_last_layer(base_model, nb_classes)

  # transfer learning
  setup_to_transfer_learn(model, base_model)

  history_tl = model.fit_generator(
    train_generator,
    nb_epoch=nb_epoch,
    samples_per_epoch=nb_train_samples,
    validation_data=validation_generator,
    nb_val_samples=nb_val_samples,
    class_weight='auto')

  # fine-tuning
  setup_to_finetune(model)

  history_ft = model.fit_generator(
    train_generator,
    samples_per_epoch=nb_train_samples,
    nb_epoch=nb_epoch,
    validation_data=validation_generator,
    nb_val_samples=nb_val_samples,
    class_weight='auto')

  model.save(args.output_model_file)

  if args.plot:
    plot_training(history_ft)


def plot_training(history):
  acc = history.history['acc']
  val_acc = history.history['val_acc']
  loss = history.history['loss']
  val_loss = history.history['val_loss']
  epochs = range(len(acc))

  plt.plot(epochs, acc, 'r.')
  plt.plot(epochs, val_acc, 'r')
  plt.title('Training and validation accuracy')

  plt.figure()
  plt.plot(epochs, loss, 'r.')
  plt.plot(epochs, val_loss, 'r-')
  plt.title('Training and validation loss')
  plt.show()


if __name__=="__main__":
  a = argparse.ArgumentParser()
  a.add_argument("--train_dir")
  a.add_argument("--val_dir")
  a.add_argument("--nb_epoch", default=NB_EPOCHS)
  a.add_argument("--batch_size", default=BAT_SIZE)
  a.add_argument("--output_model_file", default="inceptionv3-ft.model")
  a.add_argument("--plot", action="store_true")

  args = a.parse_args()
  if args.train_dir is None or args.val_dir is None:
    a.print_help()
    sys.exit(1)

  if (not os.path.exists(args.train_dir)) or (not 
   os.path.exists(args.val_dir)):
   print("directories do not exist")
   sys.exit(1)

  train(args)

【问题讨论】:

  • 问题是什么?获得较小的值根本不是问题,因为输出是概率。
  • Matias Valdenegro:我的问题是指我在网上红的它们应该在 0 和 1 之间,是的,但它们并不像我期望的那样小,例如 [0.6 , 0.7 0.4 。 ...] 所以我可以将阈值设置为 0.5
  • 你只是被科学记数法弄糊涂了,看看我将你的概率格式化为 2 个有效数字时得到的数字:['0.00', '0.01', '0.00', '0.00', '0.00'、'0.00'、'0.33'、'0.00'、'0.00'、'0.00'、'0.00'、'0.01'、'0.02'、'0.02'、'0.38'、'0.00'、'0.27 ', '0.00', '0.00', '0.00']
  • Mathias Valdenegro 我知道你的意思,但有些值应该是 >0.5(当前类),有些值应该是 0.5 否?
  • 为此,您需要正确训练神经网络,为训练集和验证集获取低损失值。只有在那之后,您才应该查看输出,看看它们是否有意义。

标签: machine-learning neural-network computer-vision deep-learning conv-neural-network


【解决方案1】:

你回答你自己的问题。这就是原因。

我做了最重要的改变,比如 softmax 到 sigmoid

Sigmoid function 将输入映射到范围 [0, 1]。因此,网络的输出值只是这个函数的输出,而不是类概率。节点的最大值将为您提供具有最大输出的神经元,从而为您提供当前类。

当你说

但有些值应该是 >0.5(当前类),而其他一些值应该是

在 cmets 中,您指的是当前班级 >0.5 的概率。你需要的类概率是softmax function

因此,将最后一个 sigmoid 层替换为 softmax 层会得到你认为应该观察的结果。

【讨论】:

    猜你喜欢
    • 2021-03-26
    • 1970-01-01
    • 2011-07-09
    • 2013-11-29
    • 1970-01-01
    • 2020-05-27
    • 2020-02-23
    • 2019-03-13
    • 1970-01-01
    相关资源
    最近更新 更多