utils_feature.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. from collections import OrderedDict
  2. import numpy as np
  3. from .utils_dict import get_dict_first_item as _get_dict_first_item
  4. def convert_feature_dict_to_array(feature_dict):
  5. key_list = []
  6. one_feature = _get_dict_first_item(feature_dict)[1]
  7. feature_array = np.empty((len(feature_dict), len(one_feature)), one_feature.dtype)
  8. for k, (key, value) in enumerate(feature_dict.items()):
  9. key_list.append(key)
  10. feature_array[k] = value
  11. return key_list, feature_array
  12. def convert_feature_array_to_dict(key_list, feature_array):
  13. assert len(feature_array) == len(key_list)
  14. feature_dict = OrderedDict()
  15. for k, key in enumerate(key_list):
  16. feature_dict[key] = feature_array[k]
  17. return feature_dict
  18. def get_feature_array(feature_dict, keys):
  19. one_feature = _get_dict_first_item(feature_dict)[1]
  20. feature_array = np.empty((len(keys), len(one_feature)), one_feature.dtype)
  21. for i, key in enumerate(keys):
  22. feature_array[i, :] = feature_dict[key]
  23. return feature_array
  24. def pairwise_distances(x, y, squared=True):
  25. """Compute pairwise (squared) Euclidean distances.
  26. References:
  27. [2016 CVPR] Deep Metric Learning via Lifted Structured Feature Embedding
  28. `euclidean_distances` from sklearn
  29. """
  30. assert isinstance(x, np.ndarray) and x.ndim == 2
  31. assert isinstance(y, np.ndarray) and y.ndim == 2
  32. assert x.shape[1] == y.shape[1]
  33. x_square = np.expand_dims(np.einsum('ij,ij->i', x, x), axis=1)
  34. if x is y:
  35. y_square = x_square.T
  36. else:
  37. y_square = np.expand_dims(np.einsum('ij,ij->i', y, y), axis=0)
  38. distances = np.dot(x, y.T)
  39. # use inplace operation to accelerate
  40. distances *= -2
  41. distances += x_square
  42. distances += y_square
  43. # result maybe less than 0 due to floating point rounding errors.
  44. np.maximum(distances, 0, distances)
  45. if x is y:
  46. # Ensure that distances between vectors and themselves are set to 0.0.
  47. # This may not be the case due to floating point rounding errors.
  48. distances.flat[::distances.shape[0] + 1] = 0.0
  49. if not squared:
  50. np.sqrt(distances, distances)
  51. return distances