/// <summary>Compute the overlap between the vectors in a binary matrix</summary> /// <returns>a sparse matrix with the overlaps</returns> /// <param name='entity_data'>the binary matrix</param> public static Tuple<IMatrix<float>, IList<float>> ComputeWeighted(IBooleanMatrix entity_data) { var transpose = (IBooleanMatrix) entity_data.Transpose(); var other_entity_weights = new float[transpose.NumberOfRows]; for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { int freq = transpose.GetEntriesByRow(row_id).Count; other_entity_weights[row_id] = 1f / (float) Math.Log(3 + freq, 2); // TODO make configurable } IMatrix<float> weighted_overlap = new SymmetricMatrix<float>(entity_data.NumberOfRows); IList<float> entity_weights = new float[entity_data.NumberOfRows]; // go over all (other) entities for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { var row = transpose.GetEntriesByRow(row_id); for (int i = 0; i < row.Count; i++) { int x = row[i]; entity_weights[x] += other_entity_weights[row_id]; for (int j = i + 1; j < row.Count; j++) { int y = row[j]; weighted_overlap[x, y] += other_entity_weights[row_id] * other_entity_weights[row_id]; } } } return Tuple.Create(weighted_overlap, entity_weights); }
/// <summary>Compute the overlap between the vectors in a binary matrix</summary> /// <returns>a sparse matrix with the overlaps</returns> /// <param name='entity_data'>the binary matrix</param> public static Tuple <IMatrix <float>, IList <float> > ComputeWeighted(IBooleanMatrix entity_data) { var transpose = (IBooleanMatrix)entity_data.Transpose(); var other_entity_weights = new float[transpose.NumberOfRows]; for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { int freq = transpose.GetEntriesByRow(row_id).Count; other_entity_weights[row_id] = 1f / (float)Math.Log(3 + freq, 2); // TODO make configurable } IMatrix <float> weighted_overlap = new SymmetricMatrix <float>(entity_data.NumberOfRows); IList <float> entity_weights = new float[entity_data.NumberOfRows]; // go over all (other) entities for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { var row = transpose.GetEntriesByRow(row_id); for (int i = 0; i < row.Count; i++) { int x = row[i]; entity_weights[x] += other_entity_weights[row_id]; for (int j = i + 1; j < row.Count; j++) { int y = row[j]; weighted_overlap[x, y] += other_entity_weights[row_id] * other_entity_weights[row_id]; } } } return(Tuple.Create(weighted_overlap, entity_weights)); }
/// public override void ComputeCorrelations(IBooleanMatrix entity_data) { var transpose = entity_data.Transpose(); var overlap = new SparseMatrix <int>(entity_data.NumberOfRows, entity_data.NumberOfRows); // go over all (other) entities for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { var row = ((IBooleanMatrix)transpose).GetEntriesByRow(row_id); for (int i = 0; i < row.Count; i++) { int x = row[i]; for (int j = i + 1; j < row.Count; j++) { int y = row[j]; if (x < y) { overlap[x, y]++; } else { overlap[y, x]++; } } } } // the diagonal of the correlation matrix for (int i = 0; i < num_entities; i++) { this[i, i] = 1; } // compute cosine foreach (var index_pair in overlap.NonEmptyEntryIDs) { int x = index_pair.First; int y = index_pair.Second; this[x, y] = (float)(overlap[x, y] / Math.Sqrt(entity_data.NumEntriesByRow(x) * entity_data.NumEntriesByRow(y))); } }
/// <summary>Compute the overlap between the vectors in a binary matrix</summary> /// <returns>a sparse matrix with the overlaps</returns> /// <param name='entity_data'>the binary matrix</param> public static IMatrix<uint> ComputeUInt(IBooleanMatrix entity_data) { var transpose = entity_data.Transpose() as IBooleanMatrix; var overlap = new SymmetricSparseMatrix<uint>(entity_data.NumberOfRows); // go over all (other) entities for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { var row = transpose.GetEntriesByRow(row_id); for (int i = 0; i < row.Count; i++) { int x = row[i]; for (int j = i + 1; j < row.Count; j++) overlap[x, row[j]]++; } } return overlap; }
/// <summary>Computes the overlap between the vectors in a binary matrix</summary> /// <returns>a sparse matrix with the overlaps</returns> /// <param name='entity_data'>the binary matrix</param> public static IMatrix <ushort> ComputeUShort(IBooleanMatrix entity_data) { var transpose = entity_data.Transpose() as IBooleanMatrix; var overlap = new SymmetricSparseMatrix <ushort>(entity_data.NumberOfRows); // go over all (other) entities for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { var row = transpose.GetEntriesByRow(row_id); for (int i = 0; i < row.Count; i++) { int x = row[i]; for (int j = i + 1; j < row.Count; j++) { overlap[x, row[j]]++; } } } return(overlap); }
/// public override void ComputeCorrelations(IBooleanMatrix entity_data) { var transpose = (IBooleanMatrix) entity_data.Transpose(); var other_entity_weights = new float[transpose.NumberOfRows]; for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { int freq = transpose.GetEntriesByRow(row_id).Count; other_entity_weights[row_id] = 1f / (float) Math.Log(3 + freq, 2); // TODO make configurable } var weighted_overlap = new SymmetricMatrix<float>(entity_data.NumberOfRows); var entity_weights = new float[entity_data.NumberOfRows]; // go over all (other) entities for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { var row = transpose.GetEntriesByRow(row_id); for (int i = 0; i < row.Count; i++) { int x = row[i]; entity_weights[x] += other_entity_weights[row_id]; for (int j = i + 1; j < row.Count; j++) { int y = row[j]; weighted_overlap[x, y] += other_entity_weights[row_id] * other_entity_weights[row_id]; } } } // the diagonal of the correlation matrix for (int i = 0; i < num_entities; i++) this[i, i] = 1; // compute cosine for (int x = 0; x < num_entities; x++) for (int y = 0; y < x; y++) this[x, y] = (float) (weighted_overlap[x, y] / Math.Sqrt(entity_weights[x] * entity_weights[y] )); }
private void IterateBatch(IList <int> rating_indices, bool update_user, bool update_item) { SetupLoss(); SparseBooleanMatrix user_reverse_connections = (SparseBooleanMatrix)user_connections.Transpose(); // I. compute gradients var user_factors_gradient = new Matrix <float>(user_factors.dim1, user_factors.dim2); var item_factors_gradient = new Matrix <float>(item_factors.dim1, item_factors.dim2); var user_bias_gradient = new float[user_factors.dim1]; var item_bias_gradient = new float[item_factors.dim1]; // I.1 prediction error foreach (int index in rating_indices) { int user_id = ratings.Users[index]; int item_id = ratings.Items[index]; // prediction float score = global_bias + user_bias[user_id] + item_bias[item_id]; score += DataType.MatrixExtensions.RowScalarProduct(user_factors, user_id, item_factors, item_id); double sig_score = 1 / (1 + Math.Exp(-score)); float prediction = (float)(MinRating + sig_score * rating_range_size); float error = prediction - ratings[index]; float gradient_common = compute_gradient_common(sig_score, error); user_bias_gradient[user_id] += gradient_common; item_bias_gradient[item_id] += gradient_common; for (int f = 0; f < NumFactors; f++) { float u_f = user_factors[user_id, f]; float i_f = item_factors[item_id, f]; user_factors_gradient.Inc(user_id, f, gradient_common * i_f); item_factors_gradient.Inc(item_id, f, gradient_common * u_f); } } // I.2 L2 regularization // biases for (int u = 0; u < user_bias_gradient.Length; u++) { user_bias_gradient[u] += user_bias[u] * RegU * BiasReg; } for (int i = 0; i < item_bias_gradient.Length; i++) { item_bias_gradient[i] += item_bias[i] * RegI * BiasReg; } // latent factors for (int u = 0; u < user_factors_gradient.dim1; u++) { for (int f = 0; f < user_factors_gradient.dim2; f++) { user_factors_gradient.Inc(u, f, user_factors[u, f] * RegU); } } for (int i = 0; i < item_factors_gradient.dim1; i++) { for (int f = 0; f < item_factors_gradient.dim2; f++) { item_factors_gradient.Inc(i, f, item_factors[i, f] * RegI); } } // I.3 social network regularization -- see eq. (13) in the paper if (SocialRegularization != 0) { for (int u = 0; u < user_factors_gradient.dim1; u++) { var sum_connections = new float[NumFactors]; float bias_sum_connections = 0; int num_connections = user_connections[u].Count; foreach (int v in user_connections[u]) { bias_sum_connections += user_bias[v]; for (int f = 0; f < sum_connections.Length; f++) { sum_connections[f] += user_factors[v, f]; } } if (num_connections != 0) { user_bias_gradient[u] += social_regularization * (user_bias[u] - bias_sum_connections / num_connections); for (int f = 0; f < user_factors_gradient.dim2; f++) { user_factors_gradient.Inc(u, f, social_regularization * (user_factors[u, f] - sum_connections[f] / num_connections)); } } foreach (int v in user_reverse_connections[u]) { float trust_v = (float)1 / user_connections[v].Count; float neg_trust_times_reg = -social_regularization * trust_v; float bias_diff = 0; var factor_diffs = new float[NumFactors]; foreach (int w in user_connections[v]) { bias_diff -= user_bias[w]; for (int f = 0; f < factor_diffs.Length; f++) { factor_diffs[f] -= user_factors[w, f]; } } bias_diff *= trust_v; // normalize bias_diff += user_bias[v]; user_bias_gradient[u] += neg_trust_times_reg * bias_diff; for (int f = 0; f < factor_diffs.Length; f++) { factor_diffs[f] *= trust_v; // normalize factor_diffs[f] += user_factors[v, f]; user_factors_gradient.Inc(u, f, neg_trust_times_reg * factor_diffs[f]); } } } } // II. apply gradient descent step if (update_user) { for (int user_id = 0; user_id < user_factors_gradient.dim1; user_id++) { user_bias[user_id] -= user_bias_gradient[user_id] * LearnRate * BiasLearnRate; } user_factors_gradient.Multiply(-LearnRate); user_factors.Inc(user_factors_gradient); } if (update_item) { for (int item_id = 0; item_id < item_factors_gradient.dim1; item_id++) { item_bias[item_id] -= item_bias_gradient[item_id] * LearnRate * BiasLearnRate; } item_factors_gradient.Multiply(-LearnRate); item_factors.Inc(item_factors_gradient); } }
void ComputeCorrelationsUShortOverlap(IBooleanMatrix entity_data) { var transpose = entity_data.Transpose() as IBooleanMatrix; var overlap = new SymmetricMatrix<ushort>(entity_data.NumberOfRows); // go over all (other) entities for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { var row = transpose.GetEntriesByRow(row_id); for (int i = 0; i < row.Count; i++) { int x = row[i]; for (int j = i + 1; j < row.Count; j++) overlap[x, row[j]]++; } } // the diagonal of the correlation matrix for (int i = 0; i < num_entities; i++) this[i, i] = 1; // compute cosine for (int x = 0; x < num_entities; x++) for (int y = 0; y < x; y++) { long size_product = entity_data.NumEntriesByRow(x) * entity_data.NumEntriesByRow(y); if (size_product > 0) this[x, y] = (float) (overlap[x, y] / Math.Sqrt(size_product)); } }
/// public override void ComputeCorrelations(IBooleanMatrix entity_data) { var transpose = entity_data.Transpose(); var overlap = new SparseMatrix<int>(entity_data.NumberOfRows, entity_data.NumberOfRows); // go over all (other) entities for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { var row = ((IBooleanMatrix) transpose).GetEntriesByRow(row_id); for (int i = 0; i < row.Count; i++) { int x = row[i]; for (int j = i + 1; j < row.Count; j++) { int y = row[j]; if (x < y) overlap[x, y]++; else overlap[y, x]++; } } } // the diagonal of the correlation matrix for (int i = 0; i < num_entities; i++) this[i, i] = 1; // compute cosine foreach (var index_pair in overlap.NonEmptyEntryIDs) { int x = index_pair.First; int y = index_pair.Second; this[x, y] = (float) (overlap[x, y] / Math.Sqrt(entity_data.NumEntriesByRow(x) * entity_data.NumEntriesByRow(y) )); } }
/// public override void ComputeCorrelations(IBooleanMatrix entity_data) { var transpose = entity_data.Transpose() as IBooleanMatrix; var overlap = new SymmetricMatrix<int>(entity_data.NumberOfRows); // go over all (other) entities for (int row_id = 0; row_id < transpose.NumberOfRows; row_id++) { var row = transpose.GetEntriesByRow(row_id); for (int i = 0; i < row.Count; i++) { int x = row[i]; for (int j = i + 1; j < row.Count; j++) { int y = row[j]; overlap[x, y]++; } } } // the diagonal of the correlation matrix for (int i = 0; i < num_entities; i++) this[i, i] = 1; // compute Jaccard index for (int x = 0; x < num_entities; x++) for (int y = 0; y < x; y++) this[x, y] = (float) (overlap[x, y] / (entity_data.NumEntriesByRow(x) + entity_data.NumEntriesByRow(y) - overlap[x, y])); }