{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Using numpy backend.\n", "Using tensorflow backend.\n" ] } ], "source": [ "import tensorly as tl\n", "tl.set_backend('tensorflow')\n", "import numpy as np\n", "import tensorflow as tf\n", "tfe = tf.contrib.eager\n", "\n", "from tensorly.tucker_tensor import tucker_to_tensor\n", "from tensorly.random import check_random_state\n", "from tensorly.metrics import RMSE" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "num_epochs = 1000\n", "penalty = 0.0001\n", "lr = 0.01\n", "\n", "shape = [5, 5, 5]\n", "rank = [5, 5, 5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make the results reproducible by fixing the random seed" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "random_state = 1234\n", "rng = check_random_state(random_state)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create the tensor we want to decompose:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "tensor = tfe.Variable(tl.tensor(rng.random_sample(shape)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Initialise a random Tucker decomposition of that tensor (that is, the core tensor and the factors of the decomposition)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "core = tfe.Variable(tl.tensor(rng.random_sample(rank)))\n", "factors = [tfe.Variable(tl.tensor(rng.random_sample((tensor.shape[i], rank[i])))) for i in range(len(tensor.get_shape()._dims))]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's define our optimiser" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "optimizer = tf.train.GradientDescentOptimizer(learning_rate=lr)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we just iterate through the training loop and backpropagate...\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 000: Loss: 118.707\n", "Epoch 100: Loss: 2.810\n", "Epoch 200: Loss: 2.653\n", "Epoch 300: Loss: 2.484\n", "Epoch 400: Loss: 2.326\n", "Epoch 500: Loss: 2.194\n", "Epoch 600: Loss: 2.057\n", "Epoch 700: Loss: 1.868\n", "Epoch 800: Loss: 1.633\n", "Epoch 900: Loss: 1.445\n" ] } ], "source": [ "for epoch in range(num_epochs):\n", " \n", " with tfe.GradientTape() as tape:\n", " rec = tl.tucker_to_tensor(core, factors)\n", " loss_value = tf.norm(rec - tensor, ord=2)\n", " for f in factors: \n", " loss_value = loss_value + penalty*tf.norm(f, 2)\n", "\n", " grads = tape.gradient(loss_value, [core] + factors)\n", " optimizer.apply_gradients(zip(grads, [core] + factors),\n", " global_step=tf.train.get_or_create_global_step())\n", "\n", " rec_error = tl.norm(rec - tensor, 2)\n", " if epoch % 100 == 0:\n", " print(\"Epoch {:03d}: Loss: {:.3f}\".format(epoch, rec_error))" ] } ], "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.4" } }, "nbformat": 4, "nbformat_minor": 2 }