<jupyter_start><jupyter_text>Table of Contents- [Step D.1](Step-D.1)- [Step D.2](Step-D.2)- [Step D.3](Step-D.3)- [Step D.4](Step-D.4)- [Step D.5](Step-D.5)- [Step D.6](Step-D.6)<jupyter_code># disclaimer: may not work as is in Windows OS
# download the “small” 5-core dataset for the category "Digital Music"
# dataset source: https://nijianmo.github.io/amazon/index.html

!wget --backups=1 http://deepyeti.ucsd.edu/jianmo/amazon/categoryFilesSmall/Digital_Music_5.json.gz -P data/<jupyter_output>--2022-03-07 20:02:14--  http://deepyeti.ucsd.edu/jianmo/amazon/categoryFilesSmall/Digital_Music_5.json.gz
Resolving deepyeti.ucsd.edu (deepyeti.ucsd.edu)... 172.16.17.32
Connecting to deepyeti.ucsd.edu (deepyeti.ucsd.edu)|172.16.17.32|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 19408584 (19M) [application/octet-stream]
Saving to: ‘data/Digital_Music_5.json.gz’

Digital_Music_5.jso 100%[===================>]  18.51M  68.0KB/s    in 5m 54s  

2022-03-07 20:08:08 (53.6 KB/s) - ‘data/Digital_Music_5.json.gz’ saved [19408584/19408584]<jupyter_text>Step D.1<jupyter_code>def inspect_df(df: pd.DataFrame, n: int = 5) -> pd.DataFrame:
    """Helper method to easily inspect DataFrames."""

    print(f"shape: {df.shape}")

    return df.head(n)
def parse(filepath: str) -> Iterator[dict]:
    file_obj = gzip.open(filepath, "rb")
    for line in file_obj:
        yield json.loads(line)
def file_to_dataframe(filepath: str) -> pd.DataFrame:
    i = 0
    df = {}
    for d in parse(filepath):
        df[i] = {
            "user": d["reviewerID"],
            "item": d["asin"],
            "rating": d["overall"],
        }  # keep only the essential data
        i += 1
    return pd.DataFrame.from_dict(df, orient="index")
review_data = file_to_dataframe("data/Digital_Music_5.json.gz")

inspect_df(review_data)
review_data["user"] = review_data.groupby("user").ngroup()
review_data["item"] = review_data.groupby("item").ngroup()
n_users = len(review_data["user"].unique())

user_vector = np.asarray(review_data["user"].astype(np.int32))
n_items = len(review_data["item"].unique())

item_vector = np.asarray(review_data["item"].astype(np.int32))
n_users
n_items
latent_factors = 80
X = np.array([user_vector, item_vector]).T
y = review_data["rating"].values
X.shape
y.shape
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=True)<jupyter_output><empty_output><jupyter_text>Step D.2<jupyter_code>def clean_up(model_):
    tf.keras.backend.clear_session()
    del model_
    gc.collect()
def dmf_neural_network(
    n_users: int,
    n_item: int,
    n_latent_factors: int,
) -> tf.keras.Model:
    """An MLP-based Deep Matrix Factorization neural network."""
    users_input = tf.keras.layers.Input(shape=[1], dtype="int32", name="users_input")
    u = tf.keras.layers.Embedding(
        input_dim=n_users + 1, output_dim=n_latent_factors, name="users_embedding"
    )(users_input)
    u = tf.keras.layers.Flatten()(u)

    items_input = tf.keras.layers.Input(shape=[1], dtype="int32", name="items_input")
    i = tf.keras.layers.Embedding(
        input_dim=n_items + 1, output_dim=n_latent_factors, name="items_embedding"
    )(items_input)
    i = tf.keras.layers.Flatten()(i)

    x = tf.keras.layers.Concatenate(name="concatenated_vector")([i, u])

    for n in [1, 2, 4]:

        x = tf.keras.layers.Dense(
            units=200 / n,
            activation="elu",
            kernel_initializer="glorot_normal",
        )(x)
        x = tf.keras.layers.Dropout(0.2)(x)

    x = tf.keras.layers.Dense(
        units=12, activation="elu", kernel_initializer="glorot_normal"
    )(x)

    output = tf.keras.layers.Dense(units=1)(x)

    return tf.keras.Model(inputs=[users_input, items_input], outputs=output)<jupyter_output><empty_output><jupyter_text>Step D.3<jupyter_code>model = dmf_neural_network(
    n_users=n_users,
    n_item=n_items,
    n_latent_factors=latent_factors,
)

model.compile(
    loss="mean_squared_error",
    optimizer=tf.keras.optimizers.Adam(),
    metrics=[tf.keras.metrics.RootMeanSquaredError()],
)

model.summary()
tf.keras.utils.plot_model(
    model, to_file="static/DMF_model.png", show_shapes=True, show_layer_names=True
)
callback = tf.keras.callbacks.EarlyStopping(
    monitor="val_loss", patience=40, restore_best_weights=True
)
history = model.fit(
    [X_train[:, 0], X_train[:, 1]],
    y_train,
    epochs=100,
    validation_split=0.1,
    batch_size=256,
    callbacks=[callback],
)
plt.style.use("dark_background")
plt.rcParams["figure.figsize"] = [10, 8]
plt.plot(history.history["loss"], label="train")
plt.plot(history.history["val_loss"], label="validation")
plt.title("model loss")
plt.ylabel("loss")
plt.xlabel("epoch")
plt.legend(["train", "validation"], loc="upper right")
plt.show()
evaluation = model.evaluate(x=[X_test[:, 0], X_test[:, 1]], y=y_test, verbose=1)
mse, rmse = evaluation

print("test MSE  = " + str(mse))
print("test RMSE = " + str(rmse))
clean_up(model)<jupyter_output><empty_output><jupyter_text>Step D.4<jupyter_code>def dmf_cnn_neural_network(
    n_users: int,
    n_item: int,
    n_latent_factors: int,
) -> tf.keras.Model:
    """A CNN-based Deep Matrix Factorization neural network."""
    users_input = tf.keras.layers.Input(shape=[1], dtype="int32", name="users_input")
    u = tf.keras.layers.Embedding(
        input_dim=n_users + 1, output_dim=n_latent_factors, name="users_embedding"
    )(users_input)
    u = tf.keras.layers.Flatten()(u)

    items_input = tf.keras.layers.Input(shape=[1], dtype="int32", name="items_input")
    i = tf.keras.layers.Embedding(
        input_dim=n_items + 1, output_dim=n_latent_factors, name="items_embedding"
    )(items_input)
    i = tf.keras.layers.Flatten()(i)

    x = tf.keras.layers.Concatenate(name="concatenated_vector")([i, u])

    x = tf.keras.layers.Reshape(
        (2 * n_latent_factors, 1), input_shape=(n_latent_factors,)
    )(x)

    for i in range(3):
        x = tf.keras.layers.Conv1D(
            filters=4 * (2**i),
            kernel_size=3,
            padding="same",
            activation="tanh",
            name=f"convolution-{i + 1}",
        )(x)
        x = tf.keras.layers.MaxPool1D(
            pool_size=2,
            padding="same",
            name=f"max-pooling-{i + 1}",
        )(x)
        x = tf.keras.layers.Dropout(rate=0.2, name=f"dropout-{i + 1}")(x)

    x = tf.keras.layers.Flatten(name="Flatten")(
        x
    )  # flatten the convolved output in order to feed it into a dense layer

    x = tf.keras.layers.Dense(
        units=12, activation="elu", kernel_initializer="glorot_normal"
    )(x)

    output = tf.keras.layers.Dense(units=1)(x)

    return tf.keras.Model(inputs=[users_input, items_input], outputs=output)
model = dmf_cnn_neural_network(
    n_users=n_users,
    n_item=n_items,
    n_latent_factors=latent_factors,
)

model.compile(
    loss="mean_squared_error",
    optimizer=tf.keras.optimizers.Adam(),
    metrics=[tf.keras.metrics.RootMeanSquaredError()],
)

model.summary()
tf.keras.utils.plot_model(
    model, to_file="static/CNN_DMF_model.png", show_shapes=True, show_layer_names=True
)
history = model.fit(
    [X_train[:, 0], X_train[:, 1]],
    y_train,
    epochs=100,
    validation_split=0.1,
    batch_size=256,
    callbacks=[callback],
)
plt.style.use("dark_background")
plt.rcParams["figure.figsize"] = [10, 8]
plt.plot(history.history["loss"], label="train")
plt.plot(history.history["val_loss"], label="validation")
plt.title("CNN-based DMF model loss")
plt.ylabel("loss")
plt.xlabel("epoch")
plt.legend(["train", "validation"], loc="upper right")
plt.show()
evaluation = model.evaluate(x=[X_test[:, 0], X_test[:, 1]], y=y_test, verbose=1)
mse, rmse = evaluation

print("test MSE  = " + str(mse))
print("test RMSE = " + str(rmse))
clean_up(model)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.16505348955680083, 'fraction_numerical': 0.026235354049923585, 'mean_word_length': 3.9955470737913488, 'pattern_counts': {'":': 3, '<': 20, '<?xml version=': 0, '>': 26, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '456337', 'license': 'MIT', 'n_tokens_mistral': 3165, 'n_tokens_neox': 2964, 'n_words': 483, 'path': 'deep-learning-based-RS.ipynb', 'repo_name': 'ilias-ant/recommender-systems', 'size': '7854'}