nn_matching.py
Go to the documentation of this file.
1 # vim: expandtab:ts=4:sw=4
2 import numpy as np
3 
4 
5 def _pdist(a, b):
6  """Compute pair-wise squared distance between points in `a` and `b`.
7 
8  Parameters
9  ----------
10  a : array_like
11  An NxM matrix of N samples of dimensionality M.
12  b : array_like
13  An LxM matrix of L samples of dimensionality M.
14 
15  Returns
16  -------
17  ndarray
18  Returns a matrix of size len(a), len(b) such that eleement (i, j)
19  contains the squared distance between `a[i]` and `b[j]`.
20 
21  """
22  a, b = np.asarray(a), np.asarray(b)
23  if len(a) == 0 or len(b) == 0:
24  return np.zeros((len(a), len(b)))
25  a2, b2 = np.square(a).sum(axis=1), np.square(b).sum(axis=1)
26  r2 = -2. * np.dot(a, b.T) + a2[:, None] + b2[None, :]
27  r2 = np.clip(r2, 0., float(np.inf))
28  return r2
29 
30 
31 def _cosine_distance(a, b, data_is_normalized=False):
32  """Compute pair-wise cosine distance between points in `a` and `b`.
33 
34  Parameters
35  ----------
36  a : array_like
37  An NxM matrix of N samples of dimensionality M.
38  b : array_like
39  An LxM matrix of L samples of dimensionality M.
40  data_is_normalized : Optional[bool]
41  If True, assumes rows in a and b are unit length vectors.
42  Otherwise, a and b are explicitly normalized to lenght 1.
43 
44  Returns
45  -------
46  ndarray
47  Returns a matrix of size len(a), len(b) such that eleement (i, j)
48  contains the squared distance between `a[i]` and `b[j]`.
49 
50  """
51  if not data_is_normalized:
52  a = np.asarray(a) / np.linalg.norm(a, axis=1, keepdims=True)
53  b = np.asarray(b) / np.linalg.norm(b, axis=1, keepdims=True)
54  return 1. - np.dot(a, b.T)
55 
56 
58  """ Helper function for nearest neighbor distance metric (Euclidean).
59 
60  Parameters
61  ----------
62  x : ndarray
63  A matrix of N row-vectors (sample points).
64  y : ndarray
65  A matrix of M row-vectors (query points).
66 
67  Returns
68  -------
69  ndarray
70  A vector of length M that contains for each entry in `y` the
71  smallest Euclidean distance to a sample in `x`.
72 
73  """
74  distances = _pdist(x, y)
75  return np.maximum(0.0, distances.min(axis=0))
76 
77 
79  """ Helper function for nearest neighbor distance metric (cosine).
80 
81  Parameters
82  ----------
83  x : ndarray
84  A matrix of N row-vectors (sample points).
85  y : ndarray
86  A matrix of M row-vectors (query points).
87 
88  Returns
89  -------
90  ndarray
91  A vector of length M that contains for each entry in `y` the
92  smallest cosine distance to a sample in `x`.
93 
94  """
95  distances = _cosine_distance(x, y)
96  return distances.min(axis=0)
97 
98 
100  """
101  A nearest neighbor distance metric that, for each target, returns
102  the closest distance to any sample that has been observed so far.
103 
104  Parameters
105  ----------
106  metric : str
107  Either "euclidean" or "cosine".
108  matching_threshold: float
109  The matching threshold. Samples with larger distance are considered an
110  invalid match.
111  budget : Optional[int]
112  If not None, fix samples per class to at most this number. Removes
113  the oldest samples when the budget is reached.
114 
115  Attributes
116  ----------
117  samples : Dict[int -> List[ndarray]]
118  A dictionary that maps from target identities to the list of samples
119  that have been observed so far.
120 
121  """
122 
123  def __init__(self, metric, matching_threshold, budget=None):
124 
125 
126  if metric == "euclidean":
127  self._metric = _nn_euclidean_distance
128  elif metric == "cosine":
129  self._metric = _nn_cosine_distance
130  else:
131  raise ValueError(
132  "Invalid metric; must be either 'euclidean' or 'cosine'")
133  self.matching_threshold = matching_threshold
134  self.budget = budget
135  self.samples = {}
136 
137  def partial_fit(self, features, targets, active_targets):
138  """Update the distance metric with new data.
139 
140  Parameters
141  ----------
142  features : ndarray
143  An NxM matrix of N features of dimensionality M.
144  targets : ndarray
145  An integer array of associated target identities.
146  active_targets : List[int]
147  A list of targets that are currently present in the scene.
148 
149  """
150  for feature, target in zip(features, targets):
151  self.samples.setdefault(target, []).append(feature)
152  if self.budget is not None:
153  self.samples[target] = self.samples[target][-self.budget:]
154  self.samples = {k: self.samples[k] for k in active_targets}
155 
156  def distance(self, features, targets):
157  """Compute distance between features and targets.
158 
159  Parameters
160  ----------
161  features : ndarray
162  An NxM matrix of N features of dimensionality M.
163  targets : List[int]
164  A list of targets to match the given `features` against.
165 
166  Returns
167  -------
168  ndarray
169  Returns a cost matrix of shape len(targets), len(features), where
170  element (i, j) contains the closest squared distance between
171  `targets[i]` and `features[j]`.
172 
173  """
174  cost_matrix = np.zeros((len(targets), len(features)))
175  for i, target in enumerate(targets):
176  cost_matrix[i, :] = self._metric(self.samples[target], features)
177  return cost_matrix
def _nn_euclidean_distance(x, y)
Definition: nn_matching.py:57
def partial_fit(self, features, targets, active_targets)
Definition: nn_matching.py:137
def __init__(self, metric, matching_threshold, budget=None)
Definition: nn_matching.py:123
def _cosine_distance(a, b, data_is_normalized=False)
Definition: nn_matching.py:31
def _nn_cosine_distance(x, y)
Definition: nn_matching.py:78


jsk_perception
Author(s): Manabu Saito, Ryohei Ueda
autogenerated on Mon May 3 2021 03:03:27