Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
935 changes: 836 additions & 99 deletions examples/demo_pipeline_with_movielens.ipynb

Large diffs are not rendered by default.

706 changes: 353 additions & 353 deletions examples/demo_stream_with_amazon_music.ipynb

Large diffs are not rendered by default.

414 changes: 217 additions & 197 deletions examples/demo_stream_with_movielens.ipynb

Large diffs are not rendered by default.

20 changes: 7 additions & 13 deletions src/streamsight/algorithms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
Random
RecentPopularity
DecayPopularity
MostPop
MostPopular

Item Similarity Algorithms
----------------------------
Expand Down Expand Up @@ -69,17 +69,11 @@
TARSItemKNNDing
"""

from streamsight.algorithms.base import Algorithm
from streamsight.algorithms.decay_popularity import DecayPopularity
from streamsight.algorithms.itemknn import ItemKNN
from streamsight.algorithms.itemknn_incremental import ItemKNNIncremental
from streamsight.algorithms.itemknn_incremental_movielens import ItemKNNIncrementalMovieLens100K
from streamsight.algorithms.itemknn_rolling import ItemKNNRolling
from streamsight.algorithms.itemknn_static import ItemKNNStatic
from streamsight.algorithms.most_pop import MostPop
from streamsight.algorithms.random import Random
from streamsight.algorithms.recent_popularity import RecentPopularity
from streamsight.algorithms.time_aware_item_knn import (
from .base import Algorithm
from .baseline import MostPopular, Random, RecentPopularity
from .baseline.decay_popularity import DecayPopularity
from .itemknn import ItemKNN, ItemKNNIncremental, ItemKNNIncrementalMovieLens100K, ItemKNNRolling, ItemKNNStatic
from .time_aware_item_knn import (
TARSItemKNN,
TARSItemKNNDing,
TARSItemKNNLiu,
Expand All @@ -95,7 +89,7 @@
"ItemKNNIncrementalMovieLens100K",
"ItemKNNRolling",
"ItemKNNStatic",
"MostPop",
"MostPopular",
"Random",
"RecentPopularity",
"TARSItemKNN",
Expand Down
3 changes: 1 addition & 2 deletions src/streamsight/algorithms/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
from sklearn.utils.validation import check_is_fitted

from streamsight.matrix import InteractionMatrix, ItemUserBasedEnum, PredictionMatrix, to_csr_matrix
from streamsight.utils.util import add_columns_to_csr_matrix, add_rows_to_csr_matrix
from ..models import BaseModel, ParamMixin
from ..utils import add_columns_to_csr_matrix, add_rows_to_csr_matrix


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -331,7 +331,6 @@ class TopKAlgorithm(Algorithm):
def __init__(self, K: int = 10) -> None:
super().__init__()
self.K = K
self.similarity_matrix_: csr_matrix


class TopKItemSimilarityMatrixAlgorithm(TopKAlgorithm):
Expand Down
10 changes: 10 additions & 0 deletions src/streamsight/algorithms/baseline/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from .most_popular import MostPopular
from .random import Random
from .recent_popularity import RecentPopularity


__all__ = [
"MostPopular",
"Random",
"RecentPopularity",
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import numpy as np
from scipy.sparse import csr_matrix, lil_matrix

from streamsight.matrix import InteractionMatrix
from .base import Algorithm
from ...matrix import InteractionMatrix
from ..base import Algorithm


class DecayPopularity(Algorithm):
Expand Down
72 changes: 72 additions & 0 deletions src/streamsight/algorithms/baseline/most_popular.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import logging
from typing import Self

import numpy as np
from scipy.sparse import csr_matrix, hstack, vstack

from ...matrix import PredictionMatrix
from ..base import PopularityPaddingMixin, TopKAlgorithm


logger = logging.getLogger(__name__)


class MostPopular(TopKAlgorithm, PopularityPaddingMixin):
"""A popularity-based algorithm that considers all historical data."""

IS_BASE: bool = False
X_: csr_matrix | None = None # Store all historical training data

def _append_training_data(self, X: csr_matrix) -> None:
"""Append a new interaction matrix to the historical data.

Args:
X (csr_matrix): Interaction matrix to append
"""
if self.X_ is None:
raise ValueError("No existing training data to append to.")
X_prev: csr_matrix = self.X_.copy()
new_num_rows = max(X_prev.shape[0], X.shape[0])
new_num_cols = max(X_prev.shape[1], X.shape[1])
# Pad the previous matrix
if X_prev.shape[0] < new_num_rows: # Pad rows
row_padding = csr_matrix((new_num_rows - X_prev.shape[0], X_prev.shape[1]))
X_prev = vstack([X_prev, row_padding])
if X_prev.shape[1] < new_num_cols: # Pad columns
col_padding = csr_matrix((X_prev.shape[0], new_num_cols - X_prev.shape[1]))
X_prev = hstack([X_prev, col_padding])

# Pad the current matrix
if X.shape[0] < new_num_rows: # Pad rows
row_padding = csr_matrix((new_num_rows - X.shape[0], X.shape[1]))
X = vstack([X, row_padding])
if X.shape[1] < new_num_cols: # Pad columns
col_padding = csr_matrix((X.shape[0], new_num_cols - X.shape[1]))
X = hstack([X, col_padding])

# Merge data
self.X_ = X_prev + X

def _fit(self, X: csr_matrix) -> Self:
if self.X_ is not None:
self._append_training_data(X)
else:
self.X_ = X.copy()

if not isinstance(self.X_, csr_matrix):
raise ValueError("Training data is not initialized properly.")

if self.X_.shape[1] < self.K:
logger.warning("K is larger than the number of items.", UserWarning)

self.sorted_scores_ = self.get_popularity_scores(self.X_)
return self

def _predict(self, X: PredictionMatrix) -> csr_matrix:
intended_shape = (X.get_prediction_data().num_interactions, X.user_item_shape[1])

# Vectorized: repeat the sorted scores for each prediction row
data = np.tile(self.sorted_scores_, (intended_shape[0], 1))
X_pred = csr_matrix(data)

return X_pred
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import pandas as pd
from scipy.sparse import csr_matrix

from ..matrix import PredictionMatrix
from .base import TopKAlgorithm
from .utils import get_top_K_values
from ...matrix import PredictionMatrix
from ..base import TopKAlgorithm
from ..utils import get_top_K_values


class Random(TopKAlgorithm):
Expand Down
34 changes: 34 additions & 0 deletions src/streamsight/algorithms/baseline/recent_popularity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

import logging
from typing import Self

import numpy as np
from scipy.sparse import csr_matrix

from ...matrix import PredictionMatrix
from ..base import PopularityPaddingMixin, TopKAlgorithm


logger = logging.getLogger(__name__)


class RecentPopularity(TopKAlgorithm, PopularityPaddingMixin):
"""A popularity-based algorithm which only considers popularity of the latest train data."""

IS_BASE: bool = False

def _fit(self, X: csr_matrix) -> Self:
self.sorted_scores_ = self.get_popularity_scores(X)
return self

def _predict(self, X: PredictionMatrix) -> csr_matrix:
"""
Predict the K most popular item for each user using only data from the latest window.
"""
intended_shape = (X.get_prediction_data().num_interactions, X.user_item_shape[1])

# Vectorized: repeat the sorted scores for each prediction row
data = np.tile(self.sorted_scores_, (intended_shape[0], 1))
X_pred = csr_matrix(data)

return X_pred
14 changes: 14 additions & 0 deletions src/streamsight/algorithms/itemknn/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from .itemknn import ItemKNN
from .itemknn_incremental import ItemKNNIncremental
from .itemknn_incremental_movielens import ItemKNNIncrementalMovieLens100K
from .itemknn_rolling import ItemKNNRolling
from .itemknn_static import ItemKNNStatic


__all__ = [
"ItemKNN",
"ItemKNNIncremental",
"ItemKNNIncrementalMovieLens100K",
"ItemKNNRolling",
"ItemKNNStatic",
]
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from sklearn.metrics.pairwise import cosine_similarity

from streamsight.matrix import ItemUserBasedEnum, PredictionMatrix
from .base import PopularityPaddingMixin, TopKItemSimilarityMatrixAlgorithm
from .utils import get_top_K_values
from ..base import PopularityPaddingMixin, TopKItemSimilarityMatrixAlgorithm
from ..utils import get_top_K_values


logger = logging.getLogger(__name__)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from scipy.sparse import csr_matrix, hstack, vstack

from .base import PopularityPaddingMixin, TopKItemSimilarityMatrixAlgorithm
from ..base import PopularityPaddingMixin, TopKItemSimilarityMatrixAlgorithm
from .itemknn import ItemKNN


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import numpy as np
import pandas as pd
from scipy.sparse import csr_matrix, hstack, vstack
from scipy.sparse import csr_matrix
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.preprocessing import OneHotEncoder

from streamsight.matrix import InteractionMatrix
from streamsight.utils.util import add_rows_to_csr_matrix
from ...matrix import InteractionMatrix
from ...utils import add_rows_to_csr_matrix
from .itemknn_incremental import ItemKNNIncremental


Expand Down
109 changes: 0 additions & 109 deletions src/streamsight/algorithms/most_pop.py

This file was deleted.

Loading