# Copyright 2018 The Cornac Authors. All Rights Reserved.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
"""Generic class of Modality to extend from
def __init__(self, **kwargs):
"""Decorator to fallback to `batch_feature` in FeatureModality
def wrapper(self, *args, **kwargs):
if self.features is not None:
ids = args if len(args) > 0 else kwargs['batch_ids']
return FeatureModality.batch_feature(self, batch_ids=ids)
return func(self, *args, **kwargs)
"""Modality that contains features in general
features: numpy.ndarray or scipy.sparse.csr_matrix, default = None
Numpy 2d-array that the row indices are aligned with user/item in `ids`.
ids: List, default = None
List of user/item ids that the indices are aligned with `corpus`.
If None, the indices of provided `features` will be used as `ids`.
copy: bool, default = False
Whether or not to make a copy of the input features array and leave it unchanged during manipulation.
If `False`, rows of the input feature array will be swapped if needed when building the modality.
def __init__(self, features=None, ids=None, copy=False, normalized=False, **kwargs):
self.features = features
self._ids = ids
self._normalized = normalized
if copy and features is not None:
self.features = np.copy(features)
"""Return the whole feature matrix
def features(self, input_features):
if input_features is not None:
assert len(input_features.shape) == 2
self.__features = input_features
"""Return the dimensionality of the feature vectors
def _swap_feature(self, id_map):
for old_idx, raw_id in enumerate(self._ids.copy()):
new_idx = id_map.get(raw_id, None)
if new_idx is None:
assert new_idx < self.features.shape
self.features[[new_idx, old_idx]] = self.features[[old_idx, new_idx]]
self._ids[old_idx], self._ids[new_idx] = self._ids[new_idx], self._ids[old_idx]
[docs] def build(self, id_map=None):
"""Build the feature matrix.
Features will be swapped if the id_map is provided
if self.features is None:
if (self._ids is not None) and (id_map is not None):
self.features = self.features - np.min(self.features)
self.features = self.features / (np.max(self.features) + 1e-10)
[docs] def batch_feature(self, batch_ids):
"""Return a matrix (batch of feature vectors) corresponding to provided batch_ids
assert self.features is not None