{"action":"created","comment":{"url":"https://api.github.com/repos/dato-code/mxnet/pulls/comments/67978552","id":67978552,"diff_hunk":"@@ -0,0 +1,714 @@\n+import os as _os\n+import logging as _logging\n+import json as _json\n+from collections import namedtuple as _namedtuple\n+from .model import FeedForward as _FeedForward\n+from .model import extract_feature as _extract_feature\n+from . import ndarray as _ndarray\n+from . import io as _io\n+from . import symbol as _sym\n+from .utils.rcnn_utils import nms, bbox_transform_inv, clip_boxes\n+import numpy as _np\n+import requests\n+import collections\n+\n+_LOGGER = _logging.getLogger(__name__)\n+\n+class ModelTypeEnum(object):\n+    \"\"\"\n+    Enumeration of Pretrained Model Type\n+    \"\"\"\n+    IMAGE_CLASSIFIER= 'IMAGE_CLASSIFIER'\n+    IMAGE_DETECTOR = 'IMAGE_DETECTOR'\n+\n+ModelEntry = _namedtuple('ModelEntry', ['name', 'type', 'version'])\n+\n+\n+\"\"\"\n+Default location for model download\n+\"\"\"\n+DEFAULT_MODEL_LOCATION=_os.path.expanduser('~/.graphlab/mxnet_models')\n+\n+\n+def list_models(location=DEFAULT_MODEL_LOCATION):\n+    \"\"\"\n+    Return list of pretrained model names.\n+\n+    Parameters\n+    ----------\n+    location : str, optional\n+      The local directory where the model is saved to.\n+\n+    Examples\n+    --------\n+    >>> mx.pretrained_model.list_models()\n+    \"\"\"\n+    if not _os.path.exists(location):\n+        _os.makedirs(location)\n+\n+    models = [p for p in _os.listdir(location)]\n+    ret = []\n+    for name in models:\n+        model_path = _os.path.join(location, name)\n+        if not _os.path.isdir(model_path):\n+            continue\n+        metadata_path = _os.path.join(model_path, 'metadata.json')\n+        version = None\n+        try:\n+            f = open(metadata_path)\n+            metadata = _json.load(f)\n+            version = metadata['version']\n+            model_type = metadata['model_type']\n+            name = metadata['name']\n+            ret.append(ModelEntry(name, model_type, version))\n+        except Exception as e:\n+            _LOGGER.warn('Unable to open or parse model metadata %s.' % metadata_path)\n+    return ret\n+\n+def _download_file(url, target_file):\n+    r = requests.get(url, stream=True)\n+    with open(target_file, 'wb') as f:\n+        for chunk in r.iter_content(chunk_size=1024 * 1024):\n+            if chunk:\n+                f.write(chunk)\n+\n+def download_model(url, location=DEFAULT_MODEL_LOCATION, overwrite=False):\n+    \"\"\"\n+    Perform downloading the model to local filesystem.\n+\n+    Parameters\n+    ----------\n+    url : str,\n+      URL of the model. Get the list of available models from https://github.com/dato-code/mxnet.\n+    location : str, optional\n+      The local directory where the model is saved to.\n+    overwrite : bool, optional\n+      If true, remove existing models first.\n+\n+    Examples\n+    --------\n+    >>> mx.pretrained_model.download_model('https://.../InceptionV3.tar.gz')\n+    >>> model = mx.pretrained_model.load_model('InceptionV3')\n+    \"\"\"\n+    name = url.split('/')[-1]\n+    name = name.split('-')[0]\n+    target_dir = _os.path.join(location, name)\n+    target_exists = _os.path.exists(target_dir)\n+    if overwrite is False and target_exists:\n+        raise OSError(\"Target directory %s already exists. Please remove existing model or set overwrite to True\" % target_dir)\n+    # Peform download\n+    _LOGGER.info(\"Begin downloading %s\" % (url))\n+    import tempfile\n+    import hashlib\n+    import shutil\n+    import tarfile\n+    import sys\n+\n+    f = tempfile.NamedTemporaryFile(suffix='tar.gz')\n+    _download_file(url, f.name)\n+    _LOGGER.info(\"Filed downloaded to %s\" % (f.name))\n+\n+    # Extract\n+    if target_exists:\n+        _LOGGER.info(\"Remove existing model: %s\" % target_dir)\n+        shutil.rmtree(target_dir)\n+    _os.makedirs(target_dir)\n+    _LOGGER.info(\"Extracting model to %s\" % target_dir)\n+    tar = tarfile.open(f.name)\n+    tar.extractall(location)\n+    tar.close()\n+    _LOGGER.info(\"Model %s is downloaded to %s\" % (name, target_dir))\n+\n+\n+def load_model(name, ctx=None, location=DEFAULT_MODEL_LOCATION):\n+    \"\"\"\n+    Load a pretrained model by name.\n+\n+    Parameters\n+    ----------\n+    name : str\n+        Name of the pretrained model. Model must be downloaded first\n+    ctx : mx.context, optional\n+        Context of the model. Default None is equivalent to mx.cpu()\n+    location : str, optional\n+        The directory which contains downloaded models\n+\n+    Examples\n+    --------\n+    >>> model = mx.pretrained_model.load_model('InceptionV3', ctx=mx.gpu(0))\n+    \"\"\"\n+    if not any(name == m.name for m in list_models(location)):\n+        raise KeyError('Model %s does not exist. Models can be listed using list_models()' % name)\n+    target_dir = _os.path.join(location, name)\n+    return load_path(target_dir, ctx)\n+\n+\n+def load_path(target_dir, ctx=None):\n+    \"\"\"\n+    Load a pretrained model by path.\n+\n+    Parameters\n+    ----------\n+    path : str\n+        Path of the downloaded pretrained model.\n+    ctx : mx.context, optional\n+        Context of the model. Default None is equivalent to mx.cpu().\n+    location : str, optional\n+        The directory which contains downloaded pretrained models\n+\n+    Examples\n+    --------\n+    >>> model = mx.pretrained_model.load_path('~/.graphlab/mxnet_models/InceptionV3')\n+    \"\"\"\n+\n+    _LOGGER.debug('load from: %s' % (target_dir))\n+    target_dir = _os.path.expanduser(target_dir)\n+\n+    # Load the model metadata\n+    metadata_path = _os.path.join(target_dir, 'metadata.json')\n+    _LOGGER.debug('metadata_path: %s' % metadata_path)\n+    metadata = _json.load(open(metadata_path))\n+    _LOGGER.debug('metadata: %s' % str(metadata))\n+    if metadata['mean_nd'] is not None:\n+        mean_nd_path = _os.path.join(target_dir, metadata['mean_nd'])\n+        mean_nd = _ndarray.load(mean_nd_path)['mean_img'].asnumpy()\n+        # mean_nd is in c, h, w order. need to convert to h, w, c\n+        mean_nd = _np.swapaxes(mean_nd, 0, 2) # c, h, w -> w, h, c\n+        mean_nd = _np.swapaxes(mean_nd, 0, 1) # w, h, c -> h, w, c\n+        metadata['mean_nd'] = mean_nd\n+\n+    # Load Image Classifier\n+    if metadata['model_type'] == ModelTypeEnum.IMAGE_CLASSIFIER:\n+        param_file = [f for f in _os.listdir(target_dir) if f.endswith('.params')]\n+        if len(param_file) != 1:\n+            raise ValueError('Invalid model directory %s. Please remove the directory and redownload the model' % target_dir)\n+\n+        # Parse the file name to get prefix and epoch\n+        _LOGGER.debug('param_file: %s' % param_file[0])\n+        prefix = _os.path.splitext(param_file[0])[0]\n+        epoch = prefix.split('-')[-1]\n+        prefix = prefix[:-(len(epoch) + 1)]\n+        prefix = _os.path.join(target_dir, prefix)\n+        epoch = int(epoch)\n+        _LOGGER.debug('prefix: %s, epoch: %s' % (prefix, epoch))\n+\n+        # Load the feedforward model\n+        model = _FeedForward.load(prefix, epoch, ctx)\n+\n+        # Load the labels\n+        label_file = _os.path.join(target_dir, 'labels.json')\n+        _LOGGER.debug('label_file: %s' % label_file)\n+        labels = _json.load(open(label_file))\n+        return ImageClassifier(model, labels, metadata)\n+    elif metadata['model_type'] == ModelTypeEnum.IMAGE_DETECTOR:\n+        param_file = [f for f in _os.listdir(target_dir) if f.endswith('.params')]\n+        if len(param_file) != 1:\n+            raise ValueError('Invalid model directory %s. Please remove the directory and redownload the model' % target_dir)\n+        _LOGGER.debug('param_file: %s' % param_file[0])\n+        prefix = _os.path.splitext(param_file[0])[0]\n+        epoch = prefix.split('-')[-1]\n+        prefix = prefix[:-(len(epoch) + 1)]\n+        prefix = _os.path.join(target_dir, prefix)\n+        epoch = int(epoch)\n+        _LOGGER.debug('prefix: %s, epoch: %s' % (prefix, epoch))\n+\n+        # Load the feedforward model\n+        model = _FeedForward.load(prefix, epoch, ctx)\n+        label_file = _os.path.join(target_dir, 'labels.json')\n+        return ImageDetector(model, label_file, metadata)\n+    else:\n+        raise TypeError('Unexpected model type: %s', metadata['model_type'])\n+\n+\n+class ImageClassifier(object):\n+    \"\"\"\n+    Wrapper of pretrained image classifier model.\n+\n+    Use :py:func:`load_model` or :py:func:`load_path` to load the model. Do not\n+    construct directly.\n+\n+    Parameters\n+    ----------\n+    model :  FeedForward\n+        The underlying model\n+    labels : list\n+        Map from index to label\n+    metadata : dict\n+        Metadata of the model including name, version, input shape, etc.\n+    \"\"\"\n+    def __init__(self, model, labels, metadata):\n+        self._model = model\n+        self._labels = labels\n+        self._input_shape = metadata['input_shape']\n+        self.mean_nd = metadata['mean_nd']\n+        self.mean_rgb = metadata['mean_rgb']\n+        self.rescale = metadata['scale']\n+        self._name = metadata['name']\n+        self._version = metadata['version']\n+        if 'label_name' in metadata:\n+            self._label_name = metadata['label_name']\n+        else:\n+            self._label_name = 'softmax_label'\n+\n+    @property\n+    def model(self):\n+        return self._model\n+\n+    @property\n+    def labels(self):\n+        return self._labels\n+\n+    @property\n+    def input_shape(self):\n+        return self._input_shape\n+\n+    @property\n+    def name(self):\n+        return self._name\n+\n+    @property\n+    def version(self):\n+        return self._version\n+\n+    def __str__(self):\n+        return \"ImageClassifier: \" + self._name + \"(version %s)\" % self._version\n+\n+    def __repr__(self):\n+        return self.__str__()\n+\n+    def _make_dataiter(self, data, batch_size):\n+        try:\n+            import graphlab as _gl\n+        except ImportError:\n+            import sframe as _gl\n+        except ImportError:\n+            raise ImportError('Require GraphLab Create or SFrame')\n+\n+        if type(data) is not _gl.SFrame and type(data) is not _gl.SArray:\n+            raise TypeError('Input data must be SFrame or SArray')\n+        if type(data) is _gl.SArray and data.dtype() != _gl.Image:\n+            raise TypeError('Expect image typed SArray, actual type is %s' % str(data.dtype()))\n+        elif type(data) is _gl.SFrame:\n+            if data.column_types().count(_gl.Image) != 1:\n+#            if len(data.column_names()) != 1 or data.column_types()[0] != _gl.Image:\n+                raise TypeError('Input SFrame must contain a single Image typed column')\n+        if batch_size < len(data):\n+            batch_size = len(data)\n+\n+        if type(data) is _gl.SArray:\n+            data = _gl.SFrame({'image': data})\n+        image_col = data.column_names()[data.column_types().index(_gl.Image)]\n+        first_image = data[image_col][0]\n+        input_shape = (first_image.height, first_image.width, first_image.channels)\n+\n+        if input_shape != tuple(self.input_shape):\n+            _LOGGER.info('Detect image shape mismatches network input shape. Perform resize to shape %s' \\\n+                    % str(tuple(self.input_shape)))\n+            data_resize = _gl.SFrame()\n+            data_resize[image_col] = _gl.image_analysis.resize(data[image_col],\n+                                                               self.input_shape[0],\n+                                                               self.input_shape[1],\n+                                                               self.input_shape[2], decode=True)\n+            data = data_resize\n+\n+        dataiter = _io.SFrameImageIter(data, data_field=[image_col],\n+                                       batch_size=batch_size,\n+                                       mean_r=self.mean_rgb[0],\n+                                       mean_g=self.mean_rgb[1],\n+                                       mean_b=self.mean_rgb[2],\n+                                       mean_nd=self.mean_nd,\n+                                       data_name='data',\n+                                       label_name=self._label_name,\n+                                       scale=self.rescale)\n+        return dataiter\n+\n+    def extract_features(self, *args, **kwargs):\n+        \"\"\"\n+        Alias for :py:func:`~mxnet.pretrained_model.ImageClassifier.extract_feature` \n+        \"\"\"\n+        return self.extract_feature(*args, **kwargs)\n+\n+    def extract_feature(self, data, batch_size=50):\n+        \"\"\"\n+        Extracts features from the second to last layer in the network.\n+\n+        Parameters\n+        ----------\n+        data : SFrame or SArray[Image]\n+            SFrame with a single image typed column.\n+            Images must have the same size as the model's input shape.\n+       batch_size : int, optional\n+            batch size of the input to the internal model. Larger\n+            batch size makes the prediction faster but requires more memory.\n+\n+        Returns\n+        -------\n+        out : SFrame\n+            An SFrame of 2 columns: row_id, feature\n+\n+        Examples\n+        --------\n+        >>> m = mx.pretrained_model.load_model('mnist_lenet')\n+        >>> sf = SFrame('http://s3.amazonaws.com/dato-datasets/mnist/sframe/train')\n+        >>> m.extract_feature(sf['image'])\n+        \"\"\"\n+        try:\n+            import graphlab as _gl\n+        except ImportError:\n+            import sframe as _gl\n+        except ImportError:\n+            raise ImportError('Require GraphLab Create or SFrame')\n+\n+       # Make DataIter\n+        dataiter = self._make_dataiter(data, batch_size)\n+        features =  _extract_feature(self.model, dataiter)\n+\n+        ret = _gl.SFrame()\n+        ret['feature'] = features\n+        ret = ret.add_row_number(column_name='row_id')\n+        return ret\n+\n+    def predict_topk(self, data, k=5, batch_size=50):\n+        \"\"\"\n+        Predict the topk classes for given data\n+\n+        Parameters\n+        ----------\n+        data : SFrame or SArray[Image]\n+            SFrame with a single image typed column.\n+            Images must have the same size as the model's input shape.\n+        k : int, optional\n+            Number of classes returned for each input\n+        batch_size : int, optional\n+            batch size of the input to the internal model. Larger\n+            batch size makes the prediction faster but requires more memory.\n+\n+        Returns\n+        -------\n+        out : SFrame\n+            An SFrame of 5 columns: row_id, label_id, label, score, rank\n+\n+        Examples\n+        --------\n+        >>> m = mx.pretrained_model.load_model('mnist_lenet')\n+        >>> sf = SFrame('http://s3.amazonaws.com/dato-datasets/mnist/sframe/train')\n+        >>> m.predict_topk(sf['image'])\n+        \"\"\"\n+        try:\n+            import graphlab as _gl\n+        except ImportError:\n+            import sframe as _gl\n+        except ImportError:\n+            raise ImportError('Require GraphLab Create or SFrame')\n+\n+        # Check input\n+        if k > len(self.labels):\n+            k = len(self.labels)\n+\n+        # Make DataIter\n+        dataiter = self._make_dataiter(data, batch_size)\n+\n+        # Make prediction\n+        # pred[i][j] is the score of row i belongs to label j\n+        pred = self.model.predict(dataiter)\n+        # top_idx[i][k] is the label index of kth highest score of row i\n+        top_idx = pred.argsort()[:,-k:][:,::-1]\n+        # Take row wise index, to get topk score for each row\n+        top_scores = pred[_np.arange(pred.shape[0])[:,None], top_idx]\n+\n+        top_labels = [self.labels[i] for i in top_idx.flatten()]\n+        row_ids = _np.repeat(_np.arange(len(pred)), k)\n+        ranks = _np.tile(_np.arange(1, k+1), len(pred))\n+\n+        ret = _gl.SFrame()\n+        ret['row_id'] = row_ids\n+        ret['label_id'] = top_idx.flatten()\n+        ret['label'] = top_labels\n+        ret['score'] = top_scores.flatten()\n+        ret['rank'] = ranks\n+        return ret\n+\n+class ImageDetector(object):\n+    \"\"\"\n+    Wrapper of pretrained image detect model.\n+\n+    Use :py:func:`load_model` or :py:func:`load_path` to load the model. Do not\n+    construct directly.\n+\n+    Parameters\n+    ----------\n+    model: FeedForward\n+        The underlying model\n+    labels : list\n+        Map from index to label\n+    metadata: dict\n+        Metadata of the model including name, version, input shape, etc\n+    \"\"\"\n+    def __init__(self, model, labels, metadata):\n+        self._model = model\n+        self._labels = labels\n+        self._metadata = metadata\n+        self._num_classes = len(labels)\n+        # rcnn params\n+        for k, v in metadata.items():\n+            self.__setattr__(\"_\" + k, v)\n+\n+        # new executor\n+        self._ctx = model.ctx[0] # only support single device for now\n+        self._sym = model.symbol\n+        self._arg_params = {k : v.as_in_context(self._ctx) for k, v in model.arg_params.items()}\n+        self._aux_params = {k : v.as_in_context(self._ctx) for k, v in model.aux_params.items()}\n+        self._executor_with_feature = False\n+\n+    def _init_executor(self, sym):\n+        #self._arg_params[\"data\"] = _ndarray.zeros(self._input_shape, self._ctx)\n+        self._executor = sym.bind(self._ctx, self._arg_params, args_grad=None,\n+                                  grad_req=\"null\", aux_states=self._aux_params)\n+\n+    @property\n+    def model(self):\n+        return self._model\n+\n+    @property\n+    def labels(self):\n+        return self._labels\n+\n+    @property\n+    def name(self):\n+        return self._name\n+\n+    @property\n+    def version(self):\n+        return self._version\n+\n+    def __str__(self):\n+        return \"ImageDetector: \" + self._name + \"(version %s)\" % self._version\n+\n+    def _detect(self, gl_im):\n+        im_tensor, im_info = self._preprocess(gl_im)\n+        self._arg_params[\"im_info\"][:] = im_info\n+        self._arg_params[\"data\"] = _ndarray.array(im_tensor, ctx=self._ctx)\n+        #self._executor = self._executor.reshape(data=im_tensor.shape, im_info=(1, 3))\n+        self._init_executor(self._sym)\n+        self._executor.forward()\n+        blobs = dict(zip(self._sym.list_outputs(), [x.asnumpy() for x in self._executor.outputs]))\n+        scores = blobs[\"cls_prob_output\"]\n+        bbox_deltas = blobs[\"bbox_pred_output\"]\n+        rois = blobs[\"rois_output\"]\n+        boxes = rois[:, 1:5] / im_info[0][2]\n+        boxes = bbox_transform_inv(boxes, bbox_deltas)\n+        boxes = clip_boxes(boxes, (im_info[0][0] / im_info[0][2],\n+                                   im_info[0][1] / im_info[0][2],\n+                                   3))\n+        blobs[\"bbox_pred\"] = boxes\n+        del blobs[\"rois_output\"]\n+        del blobs[\"bbox_pred_output\"]\n+        return blobs\n+\n+\n+    def _preprocess(self, gl_im, target_size=600, max_size=1000):\n+        import PIL\n+        import numpy as np\n+        import StringIO as _StringIO\n+        # build PIL image from sframe\n+        im = gl_im._to_pil_image()\n+        im_shape = im.size\n+        im_size_min = np.min(im_shape[0:2])\n+        im_size_max = np.max(im_shape[0:2])\n+        im_scale = float(target_size) / float(im_size_min)\n+        # prevent bigger axis from being more than max_size:\n+        if np.round(im_scale * im_size_max) > max_size:\n+            im_scale = float(max_size) / float(im_size_max)\n+        im_hw = (int(im_shape[0] * im_scale), int(im_shape[1] * im_scale))\n+        im = im.resize(im_hw, PIL.Image.ANTIALIAS)\n+        # normalize\n+        im = np.asarray(im).astype(\"float32\").copy()\n+        im -= self._mean_rgb\n+        if \"scale\" in self._metadata:\n+            im *= self._scale\n+        im_tensor = im[np.newaxis, :]\n+        im_tensor = im_tensor.transpose((0, 3, 1, 2))\n+        im_info = np.array([[im_tensor.shape[2], im_tensor.shape[3], im_scale]], dtype=np.float32)\n+        return im_tensor, im_info\n+\n+\n+    def _postprocess(self, blobs, class_score_threshold=0.3, nms_threshold=0.3):\n+        out_blob = {}\n+        dets = []\n+        feature = []\n+        scores = blobs[\"cls_prob_output\"]\n+        boxes = blobs[\"bbox_pred\"]\n+        for j in range(1, self._num_classes):\n+            inds = _np.where(scores[:, j] > class_score_threshold)[0]\n+            cls_scores = scores[inds, j]\n+            cls_boxes = boxes[inds, j * 4 : (j + 1) * 4]\n+            cls_dets = _np.hstack((cls_boxes, cls_scores[:, _np.newaxis]))\\\n+                    .astype(_np.float32, copy=False)\n+            keep = nms(cls_dets, nms_threshold)\n+            cls_dets = cls_dets[keep, :]\n+            dets.append(list(cls_dets))\n+            if self._executor_with_feature:\n+                fea =  blobs[\"feature_output\"][keep, :]\n+                feature.append(list(fea))\n+        out_blob[\"dets\"] = dets\n+        if self._executor_with_feature:\n+            out_blob[\"feature\"] = feature\n+        return out_blob\n+\n+    def detect(self, data, filter_result=False, class_score_threshold=0.3, nms_threshold=0.3):\n+        \"\"\"\n+        Detect objects for the given data\n+\n+        Parameters\n+        ----------\n+        data : SArray[Image] or gl.Image\n+            SArray of images type or a single gl.Imgae\n+            Image can be in various of size\n+        filter_result: bool, optional\n+            Filter raw detection result\n+            If set to false, the returned result will box and score of 300 proposal for all objects\n+            If set to true, the returned result will be filtered by nms and classification scroe\n+        class_score_threshold: float, optional\n+            Threshold for filtering.\n+            If the classification score is below threshold, the result will be filtered out\n+        nms_threshold: float, optional\n+            Threshold for filtering by nms(non-maximum surprised)\n+            If the nms score is below threshold, the result will be filtered out\n+\n+        Returns\n+        -------\n+        out: dict or SFrame\n+            If input is gl.Image, out will be dict\n+            If input is SArray[Image], out will be SFrame\n+            If filter_result is False, keys will be [cls_prob_output, bbox_pred]\n+            If filter_result is True, keys will be [dets]\n+            dets format is detection result for each class.\n+            The dection result is in 5 columns: 4 for box and last column is classification score\n+        \"\"\"\n+\n+        try:\n+            import graphlab as _gl\n+        except ImportError:\n+            import sframe as _gl\n+        except ImportError:\n+            raise ImportError('Require GraphLab Create or SFrame')\n+        if type(data) == _gl.Image:\n+            blobs = self._detect(data)\n+            if filter_result:\n+                return self._postprocess(blobs, class_score_threshold, nms_threshold)\n+            else:\n+                return blobs\n+        elif type(data) == _gl.SArray:\n+            if filter_result:\n+                tmp = collections.defaultdict(list)\n+                for x in data:\n+                    ret = self._postprocess(self._detect(x), class_score_threshold, nms_threshold)\n+                    for key in ret.keys():\n+                        tmp[key].append(ret[key])\n+                return _gl.SFrame(tmp)\n+            else:\n+                tmp = collections.defaultdict(list)\n+                for x in data:\n+                    ret = self._detect(x)\n+                    for key in ret.keys():\n+                        tmp[key].append(ret[key])\n+                return _gl.SFrame(tmp)\n+        else:\n+            raise Exception(\"Unsupport input data type.\")\n+\n+    def extract_feature(self, data,\n+                        filter_result=False,\n+                        class_score_threshold=0.3,\n+                        nms_threshold=0.3,\n+                        feature_op=\"roi_pool5\"):\n+        \"\"\"\n+        Detect objects and extract feature of objects for the given data\n+\n+        Parameters\n+        ----------\n+        data : SArray[Image] or gl.Image\n+            SArray of images type of a single gl.Imgae\n+            Image can be in various of size\n+        filter_result: bool, optional\n+            Filter raw detection result\n+            If set to false, the returned result will box and score of 300 proposal for all objects\n+            If set to true, the returned result will be filtered by nms and classification scroe\n+        class_score_threshold: float, optional\n+            Threshold for filtering.\n+            If the classification score is below threshold, the result will be filtered out\n+        nms_threshold: float, optional\n+            Threshold for filtering by nms(non-maximum surprised)\n+            If the nms score is below threshold, the result will be filtered out\n+        feature_op: str, optional\n+            Name of operator which generates object feature\n+\n+\n+        Returns\n+        -------\n+        out: dict or SFrame\n+            If input is gl.Image, out will be dict\n+            If input is SArray[Image], out will be SFrame\n+            If filter_result is False, keys will be [cls_prob_output, bbox_pred, feature]\n+            If filter_result is True, keys will be [dets, feature]\n+            dets format is detection result for each class. feature is in same format of dets\n+            The dection result is in 5 columns: 4 for box and last column is classification score\n+            The feature is a vector\n+        \"\"\"","path":"python/mxnet/pretrained_model.py","position":656,"original_position":656,"commit_id":"b283dc236a83fe8c8b66aa8958285f88849e2f13","original_commit_id":"b283dc236a83fe8c8b66aa8958285f88849e2f13","user":{"login":"piotr-teterwak","id":8304178,"avatar_url":"https://avatars.githubusercontent.com/u/8304178?v=3","gravatar_id":"","url":"https://api.github.com/users/piotr-teterwak","html_url":"https://github.com/piotr-teterwak","followers_url":"https://api.github.com/users/piotr-teterwak/followers","following_url":"https://api.github.com/users/piotr-teterwak/following{/other_user}","gists_url":"https://api.github.com/users/piotr-teterwak/gists{/gist_id}","starred_url":"https://api.github.com/users/piotr-teterwak/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/piotr-teterwak/subscriptions","organizations_url":"https://api.github.com/users/piotr-teterwak/orgs","repos_url":"https://api.github.com/users/piotr-teterwak/repos","events_url":"https://api.github.com/users/piotr-teterwak/events{/privacy}","received_events_url":"https://api.github.com/users/piotr-teterwak/received_events","type":"User","site_admin":false},"body":"Example would be nice here. ","created_at":"2016-06-22T00:48:18Z","updated_at":"2016-06-22T00:48:18Z","html_url":"https://github.com/dato-code/mxnet/pull/34#discussion_r67978552","pull_request_url":"https://api.github.com/repos/dato-code/mxnet/pulls/34","_links":{"self":{"href":"https://api.github.com/repos/dato-code/mxnet/pulls/comments/67978552"},"html":{"href":"https://github.com/dato-code/mxnet/pull/34#discussion_r67978552"},"pull_request":{"href":"https://api.github.com/repos/dato-code/mxnet/pulls/34"}}},"pull_request":{"url":"https://api.github.com/repos/dato-code/mxnet/pulls/34","id":73622253,"html_url":"https://github.com/dato-code/mxnet/pull/34","diff_url":"https://github.com/dato-code/mxnet/pull/34.diff","patch_url":"https://github.com/dato-code/mxnet/pull/34.patch","issue_url":"https://api.github.com/repos/dato-code/mxnet/issues/34","number":34,"state":"open","locked":false,"title":"Add pretrained_model and bug fix for extract_feature","user":{"login":"haijieg","id":818855,"avatar_url":"https://avatars.githubusercontent.com/u/818855?v=3","gravatar_id":"","url":"https://api.github.com/users/haijieg","html_url":"https://github.com/haijieg","followers_url":"https://api.github.com/users/haijieg/followers","following_url":"https://api.github.com/users/haijieg/following{/other_user}","gists_url":"https://api.github.com/users/haijieg/gists{/gist_id}","starred_url":"https://api.github.com/users/haijieg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/haijieg/subscriptions","organizations_url":"https://api.github.com/users/haijieg/orgs","repos_url":"https://api.github.com/users/haijieg/repos","events_url":"https://api.github.com/users/haijieg/events{/privacy}","received_events_url":"https://api.github.com/users/haijieg/received_events","type":"User","site_admin":false},"body":"Add pretrained model module\r\nProvide Pretrained ImageClassifier with high level APIs like:\r\npredict_topk and extract_feature.\r\n\r\nProvide model management APIs:\r\n- list_models()\r\n- download()\r\n- load_model()\r\n\r\nUsage:\r\n```\r\nIn [2]: import mxnet as mx\r\n\r\nIn [3]: mx.pretrained_model.download_model('https://s3.amazonaws.com/dato-models/mxnet_models/release/image_classifier/FastNet-1.0.tar.gz', overwrite=True)\r\n\r\nIn [4]: mx.pretrained_model.list_models()\r\nOut[4]: [ModelEntry(name=u'FastNet', type=u'IMAGE_CLASSIFIER', version=u'1.0')]\r\n\r\nIn [5]: mx.pretrained_model.download_model('https://s3.amazonaws.com/dato-models/mxnet_models/release/image_classifier/InceptionBN-1.0.tar.gz', overwrite=True)\r\n\r\nIn [6]: mx.pretrained_model.list_models()\r\n[ModelEntry(name=u'InceptionBN', type=u'IMAGE_CLASSIFIER', version=u'1.0'),\r\n ModelEntry(name=u'FastNet', type=u'IMAGE_CLASSIFIER', version=u'1.0')]\r\n```\r\n\r\n```\r\nfastnet = mx.pretrained_model.load_model('FastNet')\r\nfastnet.extract_feature(...)\r\nfastnet.predict_topk(...)\r\n```","created_at":"2016-06-13T18:36:09Z","updated_at":"2016-06-22T00:48:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3fc01d675f2446aaad9861269abff84d03166764","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/dato-code/mxnet/pulls/34/commits","review_comments_url":"https://api.github.com/repos/dato-code/mxnet/pulls/34/comments","review_comment_url":"https://api.github.com/repos/dato-code/mxnet/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dato-code/mxnet/issues/34/comments","statuses_url":"https://api.github.com/repos/dato-code/mxnet/statuses/b283dc236a83fe8c8b66aa8958285f88849e2f13","head":{"label":"dato-code:pretrained","ref":"pretrained","sha":"b283dc236a83fe8c8b66aa8958285f88849e2f13","user":{"login":"dato-code","id":10378005,"avatar_url":"https://avatars.githubusercontent.com/u/10378005?v=3","gravatar_id":"","url":"https://api.github.com/users/dato-code","html_url":"https://github.com/dato-code","followers_url":"https://api.github.com/users/dato-code/followers","following_url":"https://api.github.com/users/dato-code/following{/other_user}","gists_url":"https://api.github.com/users/dato-code/gists{/gist_id}","starred_url":"https://api.github.com/users/dato-code/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dato-code/subscriptions","organizations_url":"https://api.github.com/users/dato-code/orgs","repos_url":"https://api.github.com/users/dato-code/repos","events_url":"https://api.github.com/users/dato-code/events{/privacy}","received_events_url":"https://api.github.com/users/dato-code/received_events","type":"Organization","site_admin":false},"repo":{"id":48771029,"name":"mxnet","full_name":"dato-code/mxnet","owner":{"login":"dato-code","id":10378005,"avatar_url":"https://avatars.githubusercontent.com/u/10378005?v=3","gravatar_id":"","url":"https://api.github.com/users/dato-code","html_url":"https://github.com/dato-code","followers_url":"https://api.github.com/users/dato-code/followers","following_url":"https://api.github.com/users/dato-code/following{/other_user}","gists_url":"https://api.github.com/users/dato-code/gists{/gist_id}","starred_url":"https://api.github.com/users/dato-code/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dato-code/subscriptions","organizations_url":"https://api.github.com/users/dato-code/orgs","repos_url":"https://api.github.com/users/dato-code/repos","events_url":"https://api.github.com/users/dato-code/events{/privacy}","received_events_url":"https://api.github.com/users/dato-code/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dato-code/mxnet","description":"Fork of https://github.com/dmlc/mxnet","fork":true,"url":"https://api.github.com/repos/dato-code/mxnet","forks_url":"https://api.github.com/repos/dato-code/mxnet/forks","keys_url":"https://api.github.com/repos/dato-code/mxnet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dato-code/mxnet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dato-code/mxnet/teams","hooks_url":"https://api.github.com/repos/dato-code/mxnet/hooks","issue_events_url":"https://api.github.com/repos/dato-code/mxnet/issues/events{/number}","events_url":"https://api.github.com/repos/dato-code/mxnet/events","assignees_url":"https://api.github.com/repos/dato-code/mxnet/assignees{/user}","branches_url":"https://api.github.com/repos/dato-code/mxnet/branches{/branch}","tags_url":"https://api.github.com/repos/dato-code/mxnet/tags","blobs_url":"https://api.github.com/repos/dato-code/mxnet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dato-code/mxnet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dato-code/mxnet/git/refs{/sha}","trees_url":"https://api.github.com/repos/dato-code/mxnet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dato-code/mxnet/statuses/{sha}","languages_url":"https://api.github.com/repos/dato-code/mxnet/languages","stargazers_url":"https://api.github.com/repos/dato-code/mxnet/stargazers","contributors_url":"https://api.github.com/repos/dato-code/mxnet/contributors","subscribers_url":"https://api.github.com/repos/dato-code/mxnet/subscribers","subscription_url":"https://api.github.com/repos/dato-code/mxnet/subscription","commits_url":"https://api.github.com/repos/dato-code/mxnet/commits{/sha}","git_commits_url":"https://api.github.com/repos/dato-code/mxnet/git/commits{/sha}","comments_url":"https://api.github.com/repos/dato-code/mxnet/comments{/number}","issue_comment_url":"https://api.github.com/repos/dato-code/mxnet/issues/comments{/number}","contents_url":"https://api.github.com/repos/dato-code/mxnet/contents/{+path}","compare_url":"https://api.github.com/repos/dato-code/mxnet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dato-code/mxnet/merges","archive_url":"https://api.github.com/repos/dato-code/mxnet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dato-code/mxnet/downloads","issues_url":"https://api.github.com/repos/dato-code/mxnet/issues{/number}","pulls_url":"https://api.github.com/repos/dato-code/mxnet/pulls{/number}","milestones_url":"https://api.github.com/repos/dato-code/mxnet/milestones{/number}","notifications_url":"https://api.github.com/repos/dato-code/mxnet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dato-code/mxnet/labels{/name}","releases_url":"https://api.github.com/repos/dato-code/mxnet/releases{/id}","deployments_url":"https://api.github.com/repos/dato-code/mxnet/deployments","created_at":"2015-12-29T23:09:57Z","updated_at":"2016-06-06T04:12:54Z","pushed_at":"2016-06-22T00:01:02Z","git_url":"git://github.com/dato-code/mxnet.git","ssh_url":"git@github.com:dato-code/mxnet.git","clone_url":"https://github.com/dato-code/mxnet.git","svn_url":"https://github.com/dato-code/mxnet","homepage":"","size":11590,"stargazers_count":4,"watchers_count":4,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":4,"default_branch":"master"}},"base":{"label":"dato-code:master","ref":"master","sha":"c4d64d9f9a92076e638ed680c6781662c933386d","user":{"login":"dato-code","id":10378005,"avatar_url":"https://avatars.githubusercontent.com/u/10378005?v=3","gravatar_id":"","url":"https://api.github.com/users/dato-code","html_url":"https://github.com/dato-code","followers_url":"https://api.github.com/users/dato-code/followers","following_url":"https://api.github.com/users/dato-code/following{/other_user}","gists_url":"https://api.github.com/users/dato-code/gists{/gist_id}","starred_url":"https://api.github.com/users/dato-code/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dato-code/subscriptions","organizations_url":"https://api.github.com/users/dato-code/orgs","repos_url":"https://api.github.com/users/dato-code/repos","events_url":"https://api.github.com/users/dato-code/events{/privacy}","received_events_url":"https://api.github.com/users/dato-code/received_events","type":"Organization","site_admin":false},"repo":{"id":48771029,"name":"mxnet","full_name":"dato-code/mxnet","owner":{"login":"dato-code","id":10378005,"avatar_url":"https://avatars.githubusercontent.com/u/10378005?v=3","gravatar_id":"","url":"https://api.github.com/users/dato-code","html_url":"https://github.com/dato-code","followers_url":"https://api.github.com/users/dato-code/followers","following_url":"https://api.github.com/users/dato-code/following{/other_user}","gists_url":"https://api.github.com/users/dato-code/gists{/gist_id}","starred_url":"https://api.github.com/users/dato-code/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dato-code/subscriptions","organizations_url":"https://api.github.com/users/dato-code/orgs","repos_url":"https://api.github.com/users/dato-code/repos","events_url":"https://api.github.com/users/dato-code/events{/privacy}","received_events_url":"https://api.github.com/users/dato-code/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dato-code/mxnet","description":"Fork of https://github.com/dmlc/mxnet","fork":true,"url":"https://api.github.com/repos/dato-code/mxnet","forks_url":"https://api.github.com/repos/dato-code/mxnet/forks","keys_url":"https://api.github.com/repos/dato-code/mxnet/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dato-code/mxnet/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dato-code/mxnet/teams","hooks_url":"https://api.github.com/repos/dato-code/mxnet/hooks","issue_events_url":"https://api.github.com/repos/dato-code/mxnet/issues/events{/number}","events_url":"https://api.github.com/repos/dato-code/mxnet/events","assignees_url":"https://api.github.com/repos/dato-code/mxnet/assignees{/user}","branches_url":"https://api.github.com/repos/dato-code/mxnet/branches{/branch}","tags_url":"https://api.github.com/repos/dato-code/mxnet/tags","blobs_url":"https://api.github.com/repos/dato-code/mxnet/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dato-code/mxnet/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dato-code/mxnet/git/refs{/sha}","trees_url":"https://api.github.com/repos/dato-code/mxnet/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dato-code/mxnet/statuses/{sha}","languages_url":"https://api.github.com/repos/dato-code/mxnet/languages","stargazers_url":"https://api.github.com/repos/dato-code/mxnet/stargazers","contributors_url":"https://api.github.com/repos/dato-code/mxnet/contributors","subscribers_url":"https://api.github.com/repos/dato-code/mxnet/subscribers","subscription_url":"https://api.github.com/repos/dato-code/mxnet/subscription","commits_url":"https://api.github.com/repos/dato-code/mxnet/commits{/sha}","git_commits_url":"https://api.github.com/repos/dato-code/mxnet/git/commits{/sha}","comments_url":"https://api.github.com/repos/dato-code/mxnet/comments{/number}","issue_comment_url":"https://api.github.com/repos/dato-code/mxnet/issues/comments{/number}","contents_url":"https://api.github.com/repos/dato-code/mxnet/contents/{+path}","compare_url":"https://api.github.com/repos/dato-code/mxnet/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dato-code/mxnet/merges","archive_url":"https://api.github.com/repos/dato-code/mxnet/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dato-code/mxnet/downloads","issues_url":"https://api.github.com/repos/dato-code/mxnet/issues{/number}","pulls_url":"https://api.github.com/repos/dato-code/mxnet/pulls{/number}","milestones_url":"https://api.github.com/repos/dato-code/mxnet/milestones{/number}","notifications_url":"https://api.github.com/repos/dato-code/mxnet/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dato-code/mxnet/labels{/name}","releases_url":"https://api.github.com/repos/dato-code/mxnet/releases{/id}","deployments_url":"https://api.github.com/repos/dato-code/mxnet/deployments","created_at":"2015-12-29T23:09:57Z","updated_at":"2016-06-06T04:12:54Z","pushed_at":"2016-06-22T00:01:02Z","git_url":"git://github.com/dato-code/mxnet.git","ssh_url":"git@github.com:dato-code/mxnet.git","clone_url":"https://github.com/dato-code/mxnet.git","svn_url":"https://github.com/dato-code/mxnet","homepage":"","size":11590,"stargazers_count":4,"watchers_count":4,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dato-code/mxnet/pulls/34"},"html":{"href":"https://github.com/dato-code/mxnet/pull/34"},"issue":{"href":"https://api.github.com/repos/dato-code/mxnet/issues/34"},"comments":{"href":"https://api.github.com/repos/dato-code/mxnet/issues/34/comments"},"review_comments":{"href":"https://api.github.com/repos/dato-code/mxnet/pulls/34/comments"},"review_comment":{"href":"https://api.github.com/repos/dato-code/mxnet/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dato-code/mxnet/pulls/34/commits"},"statuses":{"href":"https://api.github.com/repos/dato-code/mxnet/statuses/b283dc236a83fe8c8b66aa8958285f88849e2f13"}}}}
{"actor":{"display_login":"piotr-teterwak"}}