Skip to main content

myFM

Python pypi GitHub license Build Read the Docs codecov

myFM is an implementation of Bayesian Factorization Machines based on Gibbs sampling, which I believe is a wheel worth reinventing.

Currently this supports most options for libFM MCMC engine, such as

There are also functionalities not present in libFM:

  • The gibbs sampler for Ordered probit regression [5] implementing Metropolis-within-Gibbs scheme of [6].
  • Variational inference for regression and binary classification.

Tutorial and reference doc is provided at https://myfm.readthedocs.io/en/latest/.

Installation

The package is pip-installable.

pip install myfm

There are binaries for major operating systems.

If you are working with less popular OS/architecture, pip will attempt to build myFM from the source (you need a decent C++ compiler!). In that case, in addition to installing python dependencies (numpy, scipy, pandas, ...), the above command will automatically download eigen (ver 3.4.0) to its build directory and use it during the build.

Examples

A Toy example

This example is taken from pyfm with some modification.

import myfm
from sklearn.feature_extraction import DictVectorizer
import numpy as np
train = [
	{"user": "1", "item": "5", "age": 19},
	{"user": "2", "item": "43", "age": 33},
	{"user": "3", "item": "20", "age": 55},
	{"user": "4", "item": "10", "age": 20},
]
v = DictVectorizer()
X = v.fit_transform(train)
print(X.toarray())
# print
# [[ 19.   0.   0.   0.   1.   1.   0.   0.   0.]
#  [ 33.   0.   0.   1.   0.   0.   1.   0.   0.]
#  [ 55.   0.   1.   0.   0.   0.   0.   1.   0.]
#  [ 20.   1.   0.   0.   0.   0.   0.   0.   1.]]
y = np.asarray([0, 1, 1, 0])
fm = myfm.MyFMClassifier(rank=4)
fm.fit(X,y)
fm.predict(v.transform({"user": "1", "item": "10", "age": 24}))

A Movielens-100k Example

This example will require pandas and scikit-learn. movielens100k_loader is present in examples/movielens100k_loader.py.

You will be able to obtain a result comparable to SOTA algorithms like GC-MC. See examples/ml-100k.ipynb for the detailed version.

import numpy as np
from sklearn.preprocessing import OneHotEncoder
from sklearn import metrics

import myfm
from myfm.utils.benchmark_data import MovieLens100kDataManager

data_manager = MovieLens100kDataManager()
df_train, df_test = data_manager.load_rating_predefined_split(
    fold=3
)  # Note the dependence on the fold

def test_myfm(df_train, df_test, rank=8, grouping=None, n_iter=100, samples=95):
    explanation_columns = ["user_id", "movie_id"]
    ohe = OneHotEncoder(handle_unknown="ignore")
    X_train = ohe.fit_transform(df_train[explanation_columns])
    X_test = ohe.transform(df_test[explanation_columns])
    y_train = df_train.rating.values
    y_test = df_test.rating.values
    fm = myfm.MyFMRegressor(rank=rank, random_seed=114514)

    if grouping:
        # specify how columns of X_train are grouped
        group_shapes = [len(category) for category in ohe.categories_]
        assert sum(group_shapes) == X_train.shape[1]
    else:
        group_shapes = None

    fm.fit(
        X_train,
        y_train,
        group_shapes=group_shapes,
        n_iter=n_iter,
        n_kept_samples=samples,
    )
    prediction = fm.predict(X_test)
    rmse = ((y_test - prediction) ** 2).mean() ** 0.5
    mae = np.abs(y_test - prediction).mean()
    print("rmse={rmse}, mae={mae}".format(rmse=rmse, mae=mae))
    return fm


# basic regression
test_myfm(df_train, df_test, rank=8)
# rmse=0.90321, mae=0.71164

# with grouping
fm = test_myfm(df_train, df_test, rank=8, grouping=True)
# rmse=0.89594, mae=0.70481

Examples for Relational Data format

Below is a toy movielens-like example that utilizes relational data format proposed in [3].

This example, however, is too simplistic to exhibit the computational advantage of this data format. For an example with drastically reduced computational complexity, see examples/ml-100k-extended.ipynb;

import pandas as pd
import numpy as np
from myfm import MyFMRegressor, RelationBlock
from sklearn.preprocessing import OneHotEncoder

users = pd.DataFrame([
    {'user_id': 1, 'age': '20s', 'married': False},
    {'user_id': 2, 'age': '30s', 'married': False},
    {'user_id': 3, 'age': '40s', 'married': True}
]).set_index('user_id')

movies = pd.DataFrame([
    {'movie_id': 1, 'comedy': True, 'action': False },
    {'movie_id': 2, 'comedy': False, 'action': True },
    {'movie_id': 3, 'comedy': True, 'action': True}
]).set_index('movie_id')

ratings = pd.DataFrame([
    {'user_id': 1, 'movie_id': 1, 'rating': 2},
    {'user_id': 1, 'movie_id': 2, 'rating': 5},
    {'user_id': 2, 'movie_id': 2, 'rating': 4},
    {'user_id': 2, 'movie_id': 3, 'rating': 3},
    {'user_id': 3, 'movie_id': 3, 'rating': 3},
])

user_ids, user_indices = np.unique(ratings.user_id, return_inverse=True)
movie_ids, movie_indices = np.unique(ratings.movie_id, return_inverse=True)

user_ohe = OneHotEncoder(handle_unknown='ignore').fit(users.reset_index()) # include user id as feature
movie_ohe = OneHotEncoder(handle_unknown='ignore').fit(movies.reset_index())

X_user = user_ohe.transform(
    users.reindex(user_ids).reset_index()
)
X_movie = movie_ohe.transform(
    movies.reindex(movie_ids).reset_index()
)

block_user = RelationBlock(user_indices, X_user)
block_movie = RelationBlock(movie_indices, X_movie)

fm = MyFMRegressor(rank=2).fit(None, ratings.rating.values, X_rel=[block_user, block_movie])

prediction_df = pd.DataFrame([
    dict(user_id=user_id,movie_id=movie_id,
         user_index=user_index, movie_index=movie_index)
    for user_index, user_id in enumerate(user_ids)
    for movie_index, movie_id in enumerate(movie_ids)
])
predicted_rating = fm.predict(None, [
    RelationBlock(prediction_df.user_index, X_user),
    RelationBlock(prediction_df.movie_index, X_movie)
])

prediction_df['prediction']  = predicted_rating

print(
    prediction_df.merge(ratings.rename(columns={'rating':'ground_truth'}), how='left')
)

References

  1. Rendle, Steffen. "Factorization machines." 2010 IEEE International Conference on Data Mining. IEEE, 2010.
  2. Rendle, Steffen. "Factorization machines with libfm." ACM Transactions on Intelligent Systems and Technology (TIST) 3.3 (2012): 57.
  3. Rendle, Steffen. "Scaling factorization machines to relational data." Proceedings of the VLDB Endowment. Vol. 6. No. 5. VLDB Endowment, 2013.
  4. Bayer, Immanuel. "fastfm: A library for factorization machines." arXiv preprint arXiv:1505.00641 (2015).
  5. Albert, James H., and Siddhartha Chib. "Bayesian analysis of binary and polychotomous response data." Journal of the American statistical Association 88.422 (1993): 669-679.
  6. Albert, James H., and Siddhartha Chib. "Sequential ordinal modeling with applications to survival data." Biometrics 57.3 (2001): 829-836.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

myfm-0.5.0-cp312-abi3-win_amd64.whl (413.0 kB view details)

Uploaded CPython 3.12+Windows x86-64

myfm-0.5.0-cp312-abi3-musllinux_1_2_x86_64.whl (691.3 kB view details)

Uploaded CPython 3.12+musllinux: musl 1.2+ x86-64

myfm-0.5.0-cp312-abi3-musllinux_1_2_aarch64.whl (662.4 kB view details)

Uploaded CPython 3.12+musllinux: musl 1.2+ ARM64

myfm-0.5.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (233.3 kB view details)

Uploaded CPython 3.12+manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

myfm-0.5.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl (221.7 kB view details)

Uploaded CPython 3.12+manylinux: glibc 2.26+ ARM64manylinux: glibc 2.28+ ARM64

myfm-0.5.0-cp312-abi3-macosx_11_0_arm64.whl (205.6 kB view details)

Uploaded CPython 3.12+macOS 11.0+ ARM64

myfm-0.5.0-cp312-abi3-macosx_10_14_x86_64.whl (224.0 kB view details)

Uploaded CPython 3.12+macOS 10.14+ x86-64

File details

Details for the file myfm-0.5.0-cp312-abi3-win_amd64.whl.

File metadata

  • Download URL: myfm-0.5.0-cp312-abi3-win_amd64.whl
  • Upload date:
  • Size: 413.0 kB
  • Tags: CPython 3.12+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for myfm-0.5.0-cp312-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 d15a321f58ed396cf4ca81278bece3b286581c2f6ba7236a4e10e7ed96d2977d
MD5 cd5e6c8c3d233ef5ead7c30af3249602
BLAKE2b-256 068123f1d2de0260d6da59c9ea796e8e24d013273e4b7a63efd92e75eba12755

See more details on using hashes here.

Provenance

The following attestation bundles were made for myfm-0.5.0-cp312-abi3-win_amd64.whl:

Publisher: wheels.yml on tohtsky/myFM

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file myfm-0.5.0-cp312-abi3-musllinux_1_2_x86_64.whl.

File metadata

  • Download URL: myfm-0.5.0-cp312-abi3-musllinux_1_2_x86_64.whl
  • Upload date:
  • Size: 691.3 kB
  • Tags: CPython 3.12+, musllinux: musl 1.2+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for myfm-0.5.0-cp312-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 9baef3a52cd99fd48587c50eee26ba887f21c08bc8e41bdec55fe68df8dd9045
MD5 cfe4b4f22814695846a82eb43473220c
BLAKE2b-256 31c9f7bee079c0cc96a8ce879819bcdc4a4843dc0f7cb780a3df1fab4b327d5e

See more details on using hashes here.

Provenance

The following attestation bundles were made for myfm-0.5.0-cp312-abi3-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on tohtsky/myFM

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file myfm-0.5.0-cp312-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for myfm-0.5.0-cp312-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 4ca3f4d176dc9921206ede77a58a3013238c9fcbe4e84158b620a94e73010089
MD5 4a234e46addd42a7ff1b26e310d5a093
BLAKE2b-256 0259cd2eb349b1f37187cfc2df9d58725cf455276dfc7abe638b8eeeeba60498

See more details on using hashes here.

Provenance

The following attestation bundles were made for myfm-0.5.0-cp312-abi3-musllinux_1_2_aarch64.whl:

Publisher: wheels.yml on tohtsky/myFM

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file myfm-0.5.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for myfm-0.5.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 907a1d8b604cbdbf62a5a850334a98402e5bb922b333a5dfa8401808e7f90dd4
MD5 6ad9308770426afe9b1f38cafde66de8
BLAKE2b-256 99638a1a87f263a611e51f15d6b79c183c2f632a64db62aab8db1c97730358cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for myfm-0.5.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on tohtsky/myFM

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file myfm-0.5.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for myfm-0.5.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 f3f1a181e426474ea1d15250a1d178c5de013a304fa81909a097ae1abebb33d1
MD5 9ffbdcc32793aeb1f285831bf9656517
BLAKE2b-256 11828b7c1871fbb6a4951d2001cf974127a82e7735f175819ca27d9a3ed89541

See more details on using hashes here.

Provenance

The following attestation bundles were made for myfm-0.5.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl:

Publisher: wheels.yml on tohtsky/myFM

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file myfm-0.5.0-cp312-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: myfm-0.5.0-cp312-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 205.6 kB
  • Tags: CPython 3.12+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for myfm-0.5.0-cp312-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 19758bf7d6a47df94648817e78fe3ba418aad686ab8e256b450a064a5d077191
MD5 c5b0802d04003fff70620322db48f9fe
BLAKE2b-256 d784612170b1d738ff1382f9bcf0edbc03113a1b5f8e63210f1b020f3a832b33

See more details on using hashes here.

Provenance

The following attestation bundles were made for myfm-0.5.0-cp312-abi3-macosx_11_0_arm64.whl:

Publisher: wheels.yml on tohtsky/myFM

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file myfm-0.5.0-cp312-abi3-macosx_10_14_x86_64.whl.

File metadata

File hashes

Hashes for myfm-0.5.0-cp312-abi3-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 9dfba39562d7401e5e2d1f97230825c6afefb1af334e67880b98ad17f9f2eebd
MD5 04f8695e6db2844399ca7a13ad26a2e5
BLAKE2b-256 e6304a6a8ccc84bd69313061eb967a9d2d5b81b6e237621a6d4d79e84d3a4348

See more details on using hashes here.

Provenance

The following attestation bundles were made for myfm-0.5.0-cp312-abi3-macosx_10_14_x86_64.whl:

Publisher: wheels.yml on tohtsky/myFM

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.5.0 This release

7 files

0.4.0

28 files

0.3.6

20 files

0.3.5

16 files

0.3.4

16 files

0.3.3.0

16 files

0.3.2.0

17 files

0.3.1.0

17 files

0.3.0.1

1 file

0.3.0.0

1 file

0.2.1.2

1 file

0.2.1.1

1 file

0.2.1

1 file

0.2.0

1 file

0.1.1

1 file

0.0.0

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page