`tensorflowjs_converter` приводит к тому, что модель в браузере не обнаруживает никаких объектов

#tensorflow #tensorflow.js #tensorflowjs-converter

#tensorflow #tensorflow.js #tensorflowjs-конвертер

Вопрос:

Я создаю модель обнаружения объектов для tensorflow.js из «ssd_mobilenet_v2_fpnlite_640x640_coco17_tpu-8». Я обучил модель и преобразовал ее с tensorflowjs_converter помощью инструмента cli. Когда я запускаю модель в jupyter, я получаю этот вывод:

вывод jupyter

Но когда я загружаю модель в tensorflow.js , он не находит никаких ограничивающих рамок. Он выдает что-то в тензоре ограничивающей рамки, который выглядит следующим образом:

вывод модели tfjs

В основном случайно. Ни у одного из этих полей нет класса, связанного с ними. Изначально я думал, что модель tfjs была менее точной, поскольку похоже, что конвертер проходит через некоторые оптимизации. Но после повышения точности в записной книжке python точность tfjs не увеличилась.

Не похоже, что есть способ отключить tensorflowjs_converter оптимизацию. Это правда?

Есть ли что-нибудь еще, что я могу попытаться запустить мою модель в tfjs?

Вот мой pipeline_file.config :

 # SSD with Mobilenet v2 FPN-lite (go/fpn-lite) feature extractor, shared box
# predictor and focal loss (a mobile version of Retinanet).
# Retinanet: see Lin et al, https://arxiv.org/abs/1708.02002
# Trained on COCO, initialized from Imagenet classification checkpoint
# Train on TPU-8
#
# Achieves 28.2 mAP on COCO17 Val

model {
  ssd {
    inplace_batchnorm_update: true
    freeze_batchnorm: false
    num_classes: 6
    box_coder {
      faster_rcnn_box_coder {
        y_scale: 10.0
        x_scale: 10.0
        height_scale: 5.0
        width_scale: 5.0
      }
    }
    matcher {
      argmax_matcher {
        matched_threshold: 0.5
        unmatched_threshold: 0.5
        ignore_thresholds: false
        negatives_lower_than_unmatched: true
        force_match_for_each_row: true
        use_matmul_gather: true
      }
    }
    similarity_calculator {
      iou_similarity {
      }
    }
    encode_background_as_zeros: true
    anchor_generator {
      multiscale_anchor_generator {
        min_level: 3
        max_level: 7
        anchor_scale: 4.0
        aspect_ratios: [1.0, 2.0, 0.5]
        scales_per_octave: 2
      }
    }
    image_resizer {
      fixed_shape_resizer {
        height: 640
        width: 640
      }
    }
    box_predictor {
      weight_shared_convolutional_box_predictor {
        depth: 128
        class_prediction_bias_init: -4.6
        conv_hyperparams {
          activation: RELU_6,
          regularizer {
            l2_regularizer {
              weight: 0.00004
            }
          }
          initializer {
            random_normal_initializer {
              stddev: 0.01
              mean: 0.0
            }
          }
          batch_norm {
            scale: true,
            decay: 0.997,
            epsilon: 0.001,
          }
        }
        num_layers_before_predictor: 4
        share_prediction_tower: true
        use_depthwise: true
        kernel_size: 3
      }
    }
    feature_extractor {
      type: 'ssd_mobilenet_v2_fpn_keras'
      use_depthwise: true
      fpn {
        min_level: 3
        max_level: 7
        additional_layer_depth: 128
      }
      min_depth: 16
      depth_multiplier: 1.0
      conv_hyperparams {
        activation: RELU_6,
        regularizer {
          l2_regularizer {
            weight: 0.00004
          }
        }
        initializer {
          random_normal_initializer {
            stddev: 0.01
            mean: 0.0
          }
        }
        batch_norm {
          scale: true,
          decay: 0.997,
          epsilon: 0.001,
        }
      }
      override_base_feature_extractor_hyperparams: true
    }
    loss {
      classification_loss {
        weighted_sigmoid_focal {
          alpha: 0.25
          gamma: 2.0
        }
      }
      localization_loss {
        weighted_smooth_l1 {
        }
      }
      classification_weight: 1.0
      localization_weight: 1.0
    }
    normalize_loss_by_num_matches: true
    normalize_loc_loss_by_codesize: true
    post_processing {
      batch_non_max_suppression {
        score_threshold: 1e-8
        iou_threshold: 0.6
        max_detections_per_class: 100
        max_total_detections: 100
      }
      score_converter: SIGMOID
    }
  }
}

train_config: {
  fine_tune_checkpoint_version: V2
  fine_tune_checkpoint: "/content/drive/MyDrive/nespresso_detection/models/research/deploy/ssd_mobilenet_v2_fpnlite_640x640_coco17_tpu-8/checkpoint/ckpt-0"
  fine_tune_checkpoint_type: "detection"
  batch_size: 16
  sync_replicas: true
  startup_delay_steps: 0
  replicas_to_aggregate: 8
  num_steps: 8000
  data_augmentation_options {
    random_horizontal_flip {
    }
  }
  data_augmentation_options {
    random_crop_image {
      min_object_covered: 0.0
      min_aspect_ratio: 0.75
      max_aspect_ratio: 3.0
      min_area: 0.75
      max_area: 1.0
      overlap_thresh: 0.0
    }
  }
  optimizer {
    momentum_optimizer: {
      learning_rate: {
        cosine_decay_learning_rate {
          learning_rate_base: .08
          total_steps: 50000
          warmup_learning_rate: .026666
          warmup_steps: 1000
        }
      }
      momentum_optimizer_value: 0.9
    }
    use_moving_average: false
  }
  max_number_of_boxes: 100
  unpad_groundtruth_tensors: false
}

train_input_reader: {
  label_map_path: "/content/drive/MyDrive/nespresso_detection/train/VertuoPlus_label_map.pbtxt"
  tf_record_input_reader {
    input_path: "/content/drive/MyDrive/nespresso_detection/train/VertuoPlus.tfrecord"
  }
}

eval_config: {
  metrics_set: "coco_detection_metrics"
  use_moving_averages: false
}

eval_input_reader: {
  label_map_path: "/content/drive/MyDrive/nespresso_detection/train/VertuoPlus_label_map.pbtxt"
  shuffle: false
  num_epochs: 1
  tf_record_input_reader {
    input_path: "/content/drive/MyDrive/nespresso_detection/valid/VertuoPlus.tfrecord"
  }
}

 

Вот model.json файл, который создает конвертер:

 {
    "format": "graph-model",
    "generatedBy": "2.4.0",
    "convertedBy": "TensorFlow.js Converter v2.8.3",
    "signature": {
        "inputs": {
            "input_tensor:0": {
                "name": "input_tensor:0",
                "dtype": "DT_UINT8",
                "tensorShape": {
                    "dim": [
                        {
                            "size": "1"
                        },
                        {
                            "size": "-1"
                        },
                        {
                            "size": "-1"
                        },
                        {
                            "size": "3"
                        }
                    ]
                }
            }
        },
        "outputs": {
            "Identity_1:0": {
                "name": "Identity_1:0",
                "dtype": "DT_FLOAT",
                "tensorShape": {
                    "dim": [
                        {
                            "size": "1"
                        },
                        {
                            "size": "100"
                        },
                        {
                            "size": "4"
                        }
                    ]
                }
            },
            "Identity_3:0": {
                "name": "Identity_3:0",
                "dtype": "DT_FLOAT",
                "tensorShape": {
                    "dim": [
                        {
                            "size": "1"
                        },
                        {
                            "size": "100"
                        },
                        {
                            "size": "7"
                        }
                    ]
                }
            },
            "Identity_5:0": {
                "name": "Identity_5:0",
                "dtype": "DT_FLOAT",
                "tensorShape": {
                    "dim": [
                        {
                            "size": "1"
                        }
                    ]
                }
            },
            "Identity:0": {
                "name": "Identity:0",
                "dtype": "DT_FLOAT",
                "tensorShape": {
                    "dim": [
                        {
                            "size": "1"
                        },
                        {
                            "size": "100"
                        }
                    ]
                }
            },
            "Identity_7:0": {
                "name": "Identity_7:0",
                "dtype": "DT_FLOAT",
                "tensorShape": {
                    "dim": [
                        {
                            "size": "1"
                        },
                        {
                            "size": "51150"
                        },
                        {
                            "size": "7"
                        }
                    ]
                }
            },
            "Identity_2:0": {
                "name": "Identity_2:0",
                "dtype": "DT_FLOAT",
                "tensorShape": {
                    "dim": [
                        {
                            "size": "1"
                        },
                        {
                            "size": "100"
                        }
                    ]
                }
            },
            "Identity_4:0": {
                "name": "Identity_4:0",
                "dtype": "DT_FLOAT",
                "tensorShape": {
                    "dim": [
                        {
                            "size": "1"
                        },
                        {
                            "size": "100"
                        }
                    ]
                }
            },
            "Identity_6:0": {
                "name": "Identity_6:0",
                "dtype": "DT_FLOAT",
                "tensorShape": {
                    "dim": [
                        {
                            "size": "1"
                        },
                        {
                            "size": "51150"
                        },
                        {
                            "size": "4"
                        }
                    ]
                }
            }
        }
    },
    "modelTopology": {
        "node": [
            {
                "name": "StatefulPartitionedCall/Postprocessor/BatchMultiClassNonMaxSuppression/PadOrClipBoxList/zeros_7",
                "op": "Const",
                "attr": {
                    "dtype": {
                        "type": "DT_INT32"
                    },
                    "value": {
                        "tensor": {
                            "dtype": "DT_INT32",
                            "tensorShape": {
                                "dim": [
                                    {
                                        "size": "1"
                                    }
                                ]
                            }
                        }
                    }
                }
            },
... to many nodes to list here ...
            {
                    "name": "ConstantFolding/StatefulPartitionedCall/Postprocessor/BatchMultiClassNonMaxSuppression/stack_7_const_axis",
                    "shape": [],
                    "dtype": "int32"
                }
            ]
        }
    ]
}
 

И мой скрипт конвертера (чего бы это ни стоило):

 !tensorflowjs_converter 
    --input_format=tf_saved_model 
    --output_format=tfjs_graph_model 
    --signature_name=serving_default 
    --saved_model_tags=serve 
    ./saved_model 
    ./tfjs
 

Комментарии:

1. Вы выполняете предварительную обработку изображений так же, как и при обучении модели?

2. Я использую сценарий обнаружения объектов model_main_tf2.py , подробно описанный здесь: github.com/tensorflow/models/blob/master/research /… Я покопался в коде и не вижу никакой предварительной обработки. При этом нужно просмотреть много слоев кода, и я мог что-то пропустить. Есть ли простой способ узнать, выполняется ли какая-либо предварительная обработка?

Ответ №1:

Оказывается, произошло несколько вещей.

  1. серверная часть WASM возвращала разные числа и может быть неправильной. Я не смог полностью проанализировать вывод из серверной части WASM.
  2. В серверных системах CPU или webgl выходные тензоры не помечены, поэтому для интерпретации данных требуется некоторое предположение. Модель всегда будет выводить 100 ограничивающих прямоугольников. У одного тензора будет оценка точности, у одного будет классификация для этого объекта (целочисленные значения), у одного будут координаты (значения с плавающей запятой, проценты от верхнего левого угла), и у одного будут исходные данные классификации (значения с плавающей запятой, рейтинг точности для каждого класса, в моем случае, вформа (1,100,7)) .

Первым шагом было понять, что означают выходные тензоры, а затем отфильтровать объекты с низким показателем (<.8). Затем мне пришлось сопоставить классы с заданными им целочисленными значениями, которые, возможно, изменились с момента маркировки. Тогда данные имели смысл.

Я надеюсь, что это даст другим людям хороший путь, если вы заблудитесь в данных, как я.

Комментарии:

1. Не могли бы вы поделиться тем, как вы смогли понять выходные тензоры и как вы обработали выходные данные? Спасибо!

2. Вам просто нужно будет соединить их с данными, которые вы вводите в свою модель. Каждая модель будет настроена по-разному. Начните с фильтрации объектов с низкой точностью. Если нет объектов с высокой точностью, убедитесь, что вы правильно передаете изображение в свою модель.