Last active
September 25, 2017 06:47
-
-
Save yamaguchiyuto/25334f067098786d3edfb84f08491f0a to your computer and use it in GitHub Desktop.
Probabilistic matrix factorization using Edward
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import tensorflow as tf\n", | |
"import edward as ed\n", | |
"import numpy as np\n", | |
"\n", | |
"from edward.models import Normal\n", | |
"\n", | |
"ed.set_seed(42)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def build_dataset(U, V, n_samples):\n", | |
" N = U.shape[0]\n", | |
" M = V.shape[0]\n", | |
" K = U.shape[1]\n", | |
" X = []\n", | |
" sampled = set()\n", | |
" \n", | |
" for _ in range(n_samples):\n", | |
" i = np.random.randint(N)\n", | |
" j = np.random.randint(N)\n", | |
" while (i, j) in sampled:\n", | |
" i = np.random.randint(N)\n", | |
" j = np.random.randint(N)\n", | |
" sampled.add((i, j))\n", | |
" X.append([i, j])\n", | |
" \n", | |
" X = np.array(X)\n", | |
" y = np.random.normal(loc = np.sum(U[X[:, 0]] * V[X[:, 1]], axis=1), scale = 1.0)\n", | |
" \n", | |
" return X, y\n", | |
"\n", | |
"def train_test_split(X, y, test_ratio):\n", | |
" n_samples = X.shape[0]\n", | |
" test_indices = np.random.binomial(1, test_ratio, size = n_samples)\n", | |
" return X[test_indices==0], y[test_indices==0], X[test_indices==1], y[test_indices==1]\n", | |
" \n", | |
"N = 30\n", | |
"M = 40\n", | |
"K = 5 # number of latent dimensions\n", | |
"n_samples = 300\n", | |
"U_true = np.random.normal(loc = 0.0, scale = 1.0, size = (N, K))\n", | |
"V_true = np.random.normal(loc = 0.0, scale = 1.0, size = (M, K))\n", | |
"X_data, y_data = build_dataset(U_true, V_true, n_samples)\n", | |
"\n", | |
"test_ratio = 0.1\n", | |
"X_train, y_train, X_test, y_test = train_test_split(X_data, y_data, test_ratio)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# Building the model\n", | |
"\n", | |
"X_ph = tf.placeholder(tf.int32, [None, 2])\n", | |
"\n", | |
"U = Normal(loc = tf.zeros([N, K]), scale = tf.ones([N, K]))\n", | |
"V = Normal(loc = tf.zeros([M, K]), scale = tf.ones([M, K]))\n", | |
"y = Normal(loc = tf.reduce_sum(tf.gather(U, X_ph[:, 0]) * tf.gather(V, X_ph[:, 1]), axis=1), scale = tf.ones_like(tf.reduce_sum(tf.gather(U, X_ph[:, 0]) * tf.gather(V, X_ph[:, 1]), axis=1)))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# Building the variational model\n", | |
"\n", | |
"qU = Normal(loc = tf.Variable(tf.random_normal([N, K])), scale = tf.nn.softplus(tf.Variable(tf.random_normal([N, K]))))\n", | |
"qV = Normal(loc = tf.Variable(tf.random_normal([M, K])), scale = tf.nn.softplus(tf.Variable(tf.random_normal([M, K]))))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"1000/1000 [100%] ██████████████████████████████ Elapsed: 3s | Loss: 710.425\n" | |
] | |
} | |
], | |
"source": [ | |
"# Inference\n", | |
"\n", | |
"inference = ed.KLqp({U: qU, V: qV}, data = {X_ph: X_train, y: y_train})\n", | |
"inference.run(n_iter = 1000)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Mean squared error of posterior: 3.83919\n", | |
"Mean squared error of prior: 6.11875\n" | |
] | |
} | |
], | |
"source": [ | |
"# Evaluation\n", | |
"\n", | |
"y_prior = y\n", | |
"y_post = Normal(loc = tf.reduce_sum(tf.gather(qU, X_ph[:, 0]) * tf.gather(qV, X_ph[:, 1]), axis=1), scale = tf.ones_like(tf.reduce_sum(tf.gather(qU, X_ph[:, 0]) * tf.gather(qV, X_ph[:, 1]), axis=1)))\n", | |
"\n", | |
"print(\"Mean squared error of posterior: \", ed.evaluate(\"mean_squared_error\", data = {X_ph: X_test, y_post: y_test}))\n", | |
"print(\"Mean squared error of prior: \", ed.evaluate(\"mean_squared_error\", data = {X_ph: X_test, y_prior: y_test}))" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.6.1" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment