def _init_signature_matrix(self): """ Description A function which computes and returns the signature matrix which is a DynamicArray. """ signatures = self._calculate_signatures(self.matrix) return DynamicArray(signatures, lambda: DynamicArray())
def test_col(self): matrix = [ DynamicArray([1, None, None]), DynamicArray([None, None, None]), DynamicArray([None, None, 1]) ] da = DynamicArray(matrix, default_value=lambda: DynamicArray()) self.assertEqual(da.col(0), [1, None, None]) da.set_col(0, [1, 1, 1]) self.assertEqual(da.col(0), [1, 1, 1])
def test_matrix(self): matrix = [ DynamicArray([1, None, None]), DynamicArray([None, None, None]), DynamicArray([None, None, 1]) ] da = DynamicArray(matrix, default_value=lambda: DynamicArray()) self.assertEqual(da._size, len(matrix)) self.assertEqual(da._data, matrix) self.assertEqual(type(da._data[0]), DynamicArray)
def _init_neighborhood(self): """ Description A function which computes and returns the neighborhood model which is a DynamicArray object. """ neighbors = DynamicArray( default_value=lambda: DynamicArray(default_value=lambda: list())) for cluster in self.clusters: cluster_neighborhood = self._init_neighborhood_cluster(cluster) neighbors.append(cluster_neighborhood) return neighbors
def _init_v(self): """ Description A function which returns a computed V matrix. Arguments :param v: V matrix. :type v: DynamicArray """ return DynamicArray([ DynamicArray([uniform(0, 1) for _ in range(len(self.items))], default_value=lambda: uniform(0, 1)) for _ in range(self.latent_factors) ], default_value=lambda: DynamicArray( default_value=lambda: uniform(0, 1)))
def __init__(self, matrix): """ Description CollaborativeFiltering's constructor. Arguments :param matrix: The ratings matrix. :type matrix: list. """ self.items = set( {item_id for row in matrix for item_id in range(len(row))}) self.users = set({user_id for user_id in range(len(matrix))}) self.matrix = DynamicArray(default_value=lambda: DynamicArray()) for row in matrix: self.matrix.append(DynamicArray(row))
def test_new_values(self): matrix = [ DynamicArray([1, None, None]), DynamicArray([None, None, None]), DynamicArray([None, None, 1]) ] da = DynamicArray(matrix, default_value=lambda: DynamicArray()) self.assertEqual(da._size, len(matrix)) da[4][4] = 1 self.assertEqual(len(da), 5) self.assertEqual(len(da[4]), 5) self.assertEqual(da[4][4], 1) da.append(DynamicArray([None, None, 1, None])) self.assertEqual(len(da[5]), 4)
def _init_avg_ratings(self): """ Description A function which computes and returns users' average ratings. """ avg_r = DynamicArray(default_value=lambda: 0) for index, user in enumerate(self.matrix): avg_r[index] = avg(user) return avg_r
def _init_l1(self): """ Description The function which computes and returns a DynamicArray which contains items' l1 norms. """ l1_norms = DynamicArray([0 for _ in self.items], default_value=lambda: 0) for items in self.inv_index.values(): for item in items: l1_norms[item] += 1 return l1_norms
class CollaborativeFiltering(ABC): """ Description The CollaborativeFiltering abstract class. Intended for generalizing collaborative filtering algorithms. """ def __init__(self, matrix): """ Description CollaborativeFiltering's constructor. Arguments :param matrix: The ratings matrix. :type matrix: list. """ self.items = set( {item_id for row in matrix for item_id in range(len(row))}) self.users = set({user_id for user_id in range(len(matrix))}) self.matrix = DynamicArray(default_value=lambda: DynamicArray()) for row in matrix: self.matrix.append(DynamicArray(row)) def _init_model(self, model, callback): """ Description A function which returns a collaborative filtering model, initializing it if empty. Arguments :param model: The collaborative filtering model. E.g list of\ average ratings. Has to have __len__ implemented. :type model: Any. :param callback: The function which returns a computed model. :type callback: function. """ if len(model) == 0: return callback() else: return model
def _init_neighborhood(self, candidate_set): """ Description A function which computes and returns a neighborhood for a candidate set, which is a DynamicArray object. Arguments :param candidate_set: A set of elements to candidate neighbors for :type candidate_set: set """ neighbors = DynamicArray( [self._neighborhood(ide) for ide in candidate_set], default_value=lambda: list()) return neighbors
def _init_neighborhood_cluster(self, candidate_set): """ Description A function which computes and returns the neighborhood for a cluster which is a DynamicArray object. Argument :param candidate_set: The cluster. :type candidate_set: DynamicArray """ neighbors = DynamicArray( [self._neighborhood(ide, candidate_set) for ide in candidate_set], default_value=lambda: list()) return neighbors
def _calculate_signatures(self, matrix): """ Description A function which calculates signatures for a matrix. Arguments :param matrix: A ratings matrix. :type matrix: DynamicArray """ signatures = [] for i in range(self.n_permutations): permutated_matrix = DynamicArray(self._permutation(matrix)) sign = self._generate_signature(permutated_matrix) signatures.append(sign) return signatures
def _generate_signature(self, perm_matrix): """ Description A function which generates and returns a signature for a permutated matrix. Returns a DynamicArray. Arguments :param perm_matrix: A permutated matrix. :type perm_matrix: DynamicArray """ signature = [] for elem in self._elements(): vector = self.get_vector(perm_matrix, elem) identifier = self._min_hash(vector) signature.append(identifier) return DynamicArray(signature)
def _update_factors(self, user_id, item_id, error): """ Description A function which updates the latent factors in the U and V factorized matrices. Arguments :param user_id: The latent vector to update on matrix U. :type user_id: int :param item_id: The latent vector to update on matrix V. :type item_id: int :param error: The error associated with the update. :type error: int """ u_factors = array(self.u[user_id]) v_factors = array(self.v.col(item_id)) updated_u = u_factors + self.learning_rate * ( error * v_factors - self.reg_factor * u_factors) updated_v = v_factors + self.learning_rate * ( error * u_factors - self.reg_factor * v_factors) self.u[user_id] = DynamicArray( list(updated_u), default_value=uniform(0, 1)) self.v.set_col(item_id, updated_v)
def _init_preprocessed_matrix(self): """ Description A function which computes and returns a preprocessed matrix as a DynamicArray. """ prep = DynamicArray(default_value=lambda: DynamicArray()) for user_id, ratings in enumerate(self.matrix): row = [ rating - 0.5 * (self.user_avg[user_id] + self.item_avg[item_id]) if rating is not None else None for item_id, rating in enumerate(ratings) ] prep.append(DynamicArray(row)) return prep
def test_empty(self): da = DynamicArray() self.assertEqual(da._size, 0) self.assertEqual(da._data, [])
class TestDynamicArray(TestCase): def setUp(self): self.dyn_arr = DynamicArray() self.dyn_arr.append(1) self.dyn_arr.append(2) self.dyn_arr.append(3) def test_append(self): """Appends items onto list""" self.assertEqual(self.dyn_arr.store[0], 1) self.assertEqual(self.dyn_arr.store[1], 2) self.assertEqual(self.dyn_arr.store[2], 3) def test_appendleft(self): """Appends item to beginning of list""" self.dyn_arr.appendleft(0) self.assertEqual(self.dyn_arr.store[0], 0) def test_pop(self): """Pop last item off list""" self.dyn_arr.pop() self.assertEqual(self.dyn_arr.last, 2) self.assertEqual(self.dyn_arr.pop(), 2) def test_popleft(self): """Pops first item in list""" self.dyn_arr.popleft() self.assertEqual(self.dyn_arr.store[0], 2) self.assertEqual(self.dyn_arr.popleft(), 2) def test_over_indexing_error(self): """Raises IndexError when trying to pop an empty list""" self.dyn_arr.pop() self.dyn_arr.pop() self.dyn_arr.pop() with self.assertRaises(IndexError): self.dyn_arr.pop() self.dyn_arr.popleft() def test_mix_of_append_pop(self): """Tests append and pop together""" self.dyn_arr.popleft() self.dyn_arr.append(10) self.dyn_arr.appendleft(15) self.assertEqual(self.dyn_arr.store[0], 15) self.assertEqual(self.dyn_arr.store[1], 2) self.assertEqual(self.dyn_arr.store[-1], 10) def test_resize(self): """Ensures list resizes when it hits capacity""" self.assertEqual(self.dyn_arr.capacity, 3) self.dyn_arr.append(4) self.assertEqual(self.dyn_arr.capacity, 6) def test_delete_at(self): """Deletes an item at a given index""" self.dyn_arr.delete_at(1) self.assertEqual(self.dyn_arr.store[0], 1) self.assertEqual(self.dyn_arr.store[1], 3) self.assertEqual(self.dyn_arr.store[2], None) def test_delete_at_error(self): """Raises an exception when trying to delete at an invalid index""" with self.assertRaises(IndexError): self.dyn_arr.delete_at(3) self.dyn_arr.delete_at(-2)
def setUp(self): self.dyn_arr = DynamicArray() self.dyn_arr.append(1) self.dyn_arr.append(2) self.dyn_arr.append(3)