From 836e6c390b27cf58c55d9b4aba8ff682e8f1d5e3 Mon Sep 17 00:00:00 2001 From: Danny Dunlavy Date: Mon, 3 Feb 2025 06:23:58 -0700 Subject: [PATCH 1/7] Checkpoint --- docs/source/tutorial/algorithm_cp_als.ipynb | 501 ++++++++++++++++---- 1 file changed, 408 insertions(+), 93 deletions(-) diff --git a/docs/source/tutorial/algorithm_cp_als.ipynb b/docs/source/tutorial/algorithm_cp_als.ipynb index a74c943..5f215f1 100644 --- a/docs/source/tutorial/algorithm_cp_als.ipynb +++ b/docs/source/tutorial/algorithm_cp_als.ipynb @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -41,14 +41,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ - "# Pick the shape and rank\n", + "# Pick the rank and shape\n", "R = 3\n", - "np.random.seed(0) # Set seed for reproducibility\n", - "X = ttb.tenrand(shape=(6, 8, 10))" + "tensor_shape = (6, 8, 10)\n", + "\n", + "# Set seed for reproducibility\n", + "np.random.seed(0)\n", + "\n", + "# Create a low-rank dense tensor from a Kruskal tensor\n", + "factor_matrices = [np.random.rand(s,R) for s in tensor_shape]\n", + "M_true = ttb.ktensor(factor_matrices)\n", + "X = M_true.to_tensor()" ] }, { @@ -65,24 +72,43 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 8.426960e-01 f-delta = 8.4e-01\n", + " Iter 1: f = 9.014378e-01 f-delta = 5.9e-02\n", + " Iter 2: f = 9.128262e-01 f-delta = 1.1e-02\n", + " Iter 3: f = 9.209368e-01 f-delta = 8.1e-03\n", + " Iter 4: f = 9.286166e-01 f-delta = 7.7e-03\n", + " Iter 5: f = 9.365676e-01 f-delta = 8.0e-03\n", + " Iter 6: f = 9.444309e-01 f-delta = 7.9e-03\n", + " Iter 7: f = 9.514539e-01 f-delta = 7.0e-03\n", + " Iter 8: f = 9.570292e-01 f-delta = 5.6e-03\n", + " Iter 9: f = 9.610205e-01 f-delta = 4.0e-03\n", + " Final f = 9.610205e-01\n" + ] + } + ], "source": [ "# Compute a solution with final ktensor stored in M1\n", - "np.random.seed(0) # Set seed for reproducibility\n", - "short_tutorial = 10 # Cut off solve early for demo\n", - "M1 = ttb.cp_als(X, R, maxiters=short_tutorial)" + "np.random.seed(1) # Set seed for reproducibility\n", + "few_iters = 10 # Cut off solve early for demo\n", + "M1, M1_init, M1_info = ttb.cp_als(X, R, maxiters=few_iters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Since we set only a single output, `M1` is actually a *tuple* containing:\n", - "1. `M1[0]`: the solution as a `ktensor`. \n", - "2. `M1[1]`: the initial guess as a `ktensor` that was generated at runtime since no initial guess was provided. \n", - "3. `M1[2]`: a dictionary containing runtime information with keys:\n", + "The `cp_als` method returns a the following objects:\n", + "1. `M1`: the solution as a `ktensor`. \n", + "2. `M1_init`: the initial guess as a `ktensor` that was generated at runtime since no initial guess was provided. \n", + "3. `M1_info`: a dictionary containing runtime information with keys:\n", " * `params`: parameters used by `cp_als`\n", " * `iters`: number of iterations performed\n", " * `normresidual`: the norm of the residual `X.norm()**2 + M.norm()**2 - 2*`\n", @@ -91,31 +117,61 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "M1_info:\n", + "\tparams: {'stoptol': 0.0001, 'maxiters': 10, 'dimorder': [0, 1, 2], 'printitn': 1, 'fixsigns': True}\n", + "\titers: 9\n", + "\tnormresidual: 0.37921276695158984\n", + "\tfit: 0.9610204980860142\n" + ] + } + ], "source": [ - "print(f\"M1[2]['params']: {M1[2]['params']}\")\n", - "print(f\"M1[2]['iters']: {M1[2]['iters']}\")\n", - "print(f\"M1[2]['normresidual']: {M1[2]['normresidual']}\")\n", - "print(f\"M1[2]['fit']: {M1[2]['fit']}\")" + "print(\"M1_info:\")\n", + "for k, v in M1_info.items(): print(f\"\\t{k}: {v}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Run again with a different initial guess, output the initial guess." + "## Run again with a different initial guess, output the initial guess" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.random.seed(1) # Set seed for reproducibility\n", - "M2bad, Minit, _ = ttb.cp_als(X, R, maxiters=short_tutorial)" + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 9.232027e-01 f-delta = 9.2e-01\n", + " Iter 1: f = 9.415585e-01 f-delta = 1.8e-02\n", + " Iter 2: f = 9.460143e-01 f-delta = 4.5e-03\n", + " Iter 3: f = 9.485320e-01 f-delta = 2.5e-03\n", + " Iter 4: f = 9.502871e-01 f-delta = 1.8e-03\n", + " Iter 5: f = 9.516351e-01 f-delta = 1.3e-03\n", + " Iter 6: f = 9.527532e-01 f-delta = 1.1e-03\n", + " Iter 7: f = 9.537623e-01 f-delta = 1.0e-03\n", + " Iter 8: f = 9.547515e-01 f-delta = 9.9e-04\n", + " Iter 9: f = 9.557875e-01 f-delta = 1.0e-03\n", + " Final f = 9.557875e-01\n" + ] + } + ], + "source": [ + "# Compute a solution with final ktensor stored in M2\n", + "np.random.seed(2) # Set seed for reproducibility\n", + "M2, M2_init, _ = ttb.cp_als(X, R, maxiters=few_iters) # Will not use third output, so leaving unassigned" ] }, { @@ -128,12 +184,110 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "less_short_tutorial = 10 * short_tutorial\n", - "M2 = ttb.cp_als(X, R, maxiters=less_short_tutorial, init=Minit)" + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 9.232027e-01 f-delta = 9.2e-01\n", + " Iter 1: f = 9.415585e-01 f-delta = 1.8e-02\n", + " Iter 2: f = 9.460143e-01 f-delta = 4.5e-03\n", + " Iter 3: f = 9.485320e-01 f-delta = 2.5e-03\n", + " Iter 4: f = 9.502871e-01 f-delta = 1.8e-03\n", + " Iter 5: f = 9.516351e-01 f-delta = 1.3e-03\n", + " Iter 6: f = 9.527532e-01 f-delta = 1.1e-03\n", + " Iter 7: f = 9.537623e-01 f-delta = 1.0e-03\n", + " Iter 8: f = 9.547515e-01 f-delta = 9.9e-04\n", + " Iter 9: f = 9.557875e-01 f-delta = 1.0e-03\n", + " Iter 10: f = 9.569224e-01 f-delta = 1.1e-03\n", + " Iter 11: f = 9.581995e-01 f-delta = 1.3e-03\n", + " Iter 12: f = 9.596531e-01 f-delta = 1.5e-03\n", + " Iter 13: f = 9.613014e-01 f-delta = 1.6e-03\n", + " Iter 14: f = 9.631317e-01 f-delta = 1.8e-03\n", + " Iter 15: f = 9.650854e-01 f-delta = 2.0e-03\n", + " Iter 16: f = 9.670592e-01 f-delta = 2.0e-03\n", + " Iter 17: f = 9.689361e-01 f-delta = 1.9e-03\n", + " Iter 18: f = 9.706308e-01 f-delta = 1.7e-03\n", + " Iter 19: f = 9.721134e-01 f-delta = 1.5e-03\n", + " Iter 20: f = 9.733984e-01 f-delta = 1.3e-03\n", + " Iter 21: f = 9.745196e-01 f-delta = 1.1e-03\n", + " Iter 22: f = 9.755127e-01 f-delta = 9.9e-04\n", + " Iter 23: f = 9.764073e-01 f-delta = 8.9e-04\n", + " Iter 24: f = 9.772262e-01 f-delta = 8.2e-04\n", + " Iter 25: f = 9.779860e-01 f-delta = 7.6e-04\n", + " Iter 26: f = 9.786985e-01 f-delta = 7.1e-04\n", + " Iter 27: f = 9.793724e-01 f-delta = 6.7e-04\n", + " Iter 28: f = 9.800139e-01 f-delta = 6.4e-04\n", + " Iter 29: f = 9.806278e-01 f-delta = 6.1e-04\n", + " Iter 30: f = 9.812174e-01 f-delta = 5.9e-04\n", + " Iter 31: f = 9.817854e-01 f-delta = 5.7e-04\n", + " Iter 32: f = 9.823337e-01 f-delta = 5.5e-04\n", + " Iter 33: f = 9.828638e-01 f-delta = 5.3e-04\n", + " Iter 34: f = 9.833771e-01 f-delta = 5.1e-04\n", + " Iter 35: f = 9.838744e-01 f-delta = 5.0e-04\n", + " Iter 36: f = 9.843567e-01 f-delta = 4.8e-04\n", + " Iter 37: f = 9.848247e-01 f-delta = 4.7e-04\n", + " Iter 38: f = 9.852789e-01 f-delta = 4.5e-04\n", + " Iter 39: f = 9.857198e-01 f-delta = 4.4e-04\n", + " Iter 40: f = 9.861479e-01 f-delta = 4.3e-04\n", + " Iter 41: f = 9.865637e-01 f-delta = 4.2e-04\n", + " Iter 42: f = 9.869675e-01 f-delta = 4.0e-04\n", + " Iter 43: f = 9.873597e-01 f-delta = 3.9e-04\n", + " Iter 44: f = 9.877407e-01 f-delta = 3.8e-04\n", + " Iter 45: f = 9.881107e-01 f-delta = 3.7e-04\n", + " Iter 46: f = 9.884700e-01 f-delta = 3.6e-04\n", + " Iter 47: f = 9.888190e-01 f-delta = 3.5e-04\n", + " Iter 48: f = 9.891579e-01 f-delta = 3.4e-04\n", + " Iter 49: f = 9.894870e-01 f-delta = 3.3e-04\n", + " Iter 50: f = 9.898065e-01 f-delta = 3.2e-04\n", + " Iter 51: f = 9.901168e-01 f-delta = 3.1e-04\n", + " Iter 52: f = 9.904180e-01 f-delta = 3.0e-04\n", + " Iter 53: f = 9.907104e-01 f-delta = 2.9e-04\n", + " Iter 54: f = 9.909942e-01 f-delta = 2.8e-04\n", + " Iter 55: f = 9.912696e-01 f-delta = 2.8e-04\n", + " Iter 56: f = 9.915369e-01 f-delta = 2.7e-04\n", + " Iter 57: f = 9.917963e-01 f-delta = 2.6e-04\n", + " Iter 58: f = 9.920480e-01 f-delta = 2.5e-04\n", + " Iter 59: f = 9.922922e-01 f-delta = 2.4e-04\n", + " Iter 60: f = 9.925290e-01 f-delta = 2.4e-04\n", + " Iter 61: f = 9.927588e-01 f-delta = 2.3e-04\n", + " Iter 62: f = 9.929816e-01 f-delta = 2.2e-04\n", + " Iter 63: f = 9.931977e-01 f-delta = 2.2e-04\n", + " Iter 64: f = 9.934073e-01 f-delta = 2.1e-04\n", + " Iter 65: f = 9.936105e-01 f-delta = 2.0e-04\n", + " Iter 66: f = 9.938075e-01 f-delta = 2.0e-04\n", + " Iter 67: f = 9.939984e-01 f-delta = 1.9e-04\n", + " Iter 68: f = 9.941835e-01 f-delta = 1.9e-04\n", + " Iter 69: f = 9.943629e-01 f-delta = 1.8e-04\n", + " Iter 70: f = 9.945368e-01 f-delta = 1.7e-04\n", + " Iter 71: f = 9.947053e-01 f-delta = 1.7e-04\n", + " Iter 72: f = 9.948686e-01 f-delta = 1.6e-04\n", + " Iter 73: f = 9.950268e-01 f-delta = 1.6e-04\n", + " Iter 74: f = 9.951801e-01 f-delta = 1.5e-04\n", + " Iter 75: f = 9.953287e-01 f-delta = 1.5e-04\n", + " Iter 76: f = 9.954725e-01 f-delta = 1.4e-04\n", + " Iter 77: f = 9.956119e-01 f-delta = 1.4e-04\n", + " Iter 78: f = 9.957469e-01 f-delta = 1.4e-04\n", + " Iter 79: f = 9.958777e-01 f-delta = 1.3e-04\n", + " Iter 80: f = 9.960044e-01 f-delta = 1.3e-04\n", + " Iter 81: f = 9.961270e-01 f-delta = 1.2e-04\n", + " Iter 82: f = 9.962458e-01 f-delta = 1.2e-04\n", + " Iter 83: f = 9.963609e-01 f-delta = 1.2e-04\n", + " Iter 84: f = 9.964723e-01 f-delta = 1.1e-04\n", + " Iter 85: f = 9.965802e-01 f-delta = 1.1e-04\n", + " Iter 86: f = 9.966847e-01 f-delta = 1.0e-04\n", + " Iter 87: f = 9.967859e-01 f-delta = 1.0e-04\n", + " Iter 88: f = 9.968838e-01 f-delta = 9.8e-05\n", + " Final f = 9.968838e-01\n" + ] + } + ], + "source": [ + "more_iters = 10 * few_iters\n", + "M2_better, _, _ = ttb.cp_als(X, R, maxiters=more_iters, init=M2_init)" ] }, { @@ -146,29 +300,38 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ - "M1_ktns = M1[0]\n", - "M2_ktns = M2[0]\n", - "score = M1_ktns.score(M2_ktns)" + "score_M2 = M2.score(M_true)\n", + "score_M2_better = M2_better.score(M_true)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Here, `score()` returned a tuple `score` with the score as the first element:" + "Here, `score()` returns a tuple with the score as the first element:" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Score of M2 and M_true: 0.5167723537387389\n", + "Score of M2_better and M_true: 0.9519267496183975\n" + ] + } + ], "source": [ - "score[0]" + "print(f\"Score of M2 and M_true: {score_M2[0]}\")\n", + "print(f\"Score of M2_better and M_true: {score_M2_better[0]}\")" ] }, { @@ -188,14 +351,33 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "M2alt = ttb.cp_als(X, R, maxiters=less_short_tutorial, init=Minit)\n", - "M2alt_ktns = M2alt[0]\n", - "score = M2_ktns.score(M2alt_ktns) # Score of 1 indicates the same solution\n", - "print(f\"Score: {score[0]}.\")" + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 9.232027e-01 f-delta = 9.2e-01\n", + " Iter 1: f = 9.415585e-01 f-delta = 1.8e-02\n", + " Iter 2: f = 9.460143e-01 f-delta = 4.5e-03\n", + " Iter 3: f = 9.485320e-01 f-delta = 2.5e-03\n", + " Iter 4: f = 9.502871e-01 f-delta = 1.8e-03\n", + " Iter 5: f = 9.516351e-01 f-delta = 1.3e-03\n", + " Iter 6: f = 9.527532e-01 f-delta = 1.1e-03\n", + " Iter 7: f = 9.537623e-01 f-delta = 1.0e-03\n", + " Iter 8: f = 9.547515e-01 f-delta = 9.9e-04\n", + " Iter 9: f = 9.557875e-01 f-delta = 1.0e-03\n", + " Final f = 9.557875e-01\n", + "Score: 1.0000000000000007\n" + ] + } + ], + "source": [ + "M2_rerun, _, _ = ttb.cp_als(X, R, maxiters=few_iters, init=M2_init)\n", + "score_M2_rerun = M2.score(M2_rerun) # Score of 1 indicates the same solution\n", + "print(f\"Score: {score_M2_rerun[0]}\")" ] }, { @@ -208,11 +390,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 8.805093e-01 f-delta = 8.8e-01\n", + " Iter 2: f = 9.379232e-01 f-delta = 1.5e-02\n", + " Iter 4: f = 9.445392e-01 f-delta = 3.0e-03\n", + " Iter 6: f = 9.492378e-01 f-delta = 2.2e-03\n", + " Iter 8: f = 9.532334e-01 f-delta = 2.0e-03\n", + " Final f = 9.552078e-01\n" + ] + } + ], "source": [ - "M2alt2 = ttb.cp_als(X, R, maxiters=less_short_tutorial, init=Minit, printitn=20)" + "M = ttb.cp_als(X, R, maxiters=few_iters, printitn=2)" ] }, { @@ -225,11 +421,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ - "M2alt2 = ttb.cp_als(X, R, printitn=0) # No output" + "M = ttb.cp_als(X, R, maxiters=few_iters, printitn=0) # No output" ] }, { @@ -237,71 +433,131 @@ "metadata": {}, "source": [ "## Use HOSVD initial guess\n", - "Use the `\"nvecs\"` option to use the leading mode-$n$ singular vectors as the initial guess." + "Use the `\"nvecs\"` option to use the leading mode-$n$ singular vectors as the initial guess. The initialization process will require more computation in general, but it may lead to better solutions." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Score of M2 and M_true: 0.5167723537387389\n", + "Score of M3 and M_true: 0.5406177000260891\n" + ] + } + ], "source": [ - "M3 = ttb.cp_als(X, R, init=\"nvecs\", printitn=20)\n", - "s = M2[0].score(M3[0])\n", - "print(f\"score(M2,M3) = {s[0]}\")" + "M3, _, _ = ttb.cp_als(X, R, maxiters=few_iters, init=\"nvecs\", printitn=0)\n", + "score_M3 = M3.score(M_true)\n", + "print(f\"Score of M2 and M_true: {score_M2[0]}\")\n", + "print(f\"Score of M3 and M_true: {score_M3[0]}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Change the order of the dimensions in CP" + "## Change the order of the dimensions in CP\n", + "Changing the order of the dimensions in which `cp_als` iterates over the input tensor can lead to a different solution." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Score of M3 and M_true: 0.5406177000260891\n", + "Score of M4 and M_true: 0.631431759054776\n" + ] + } + ], "source": [ - "M4, _, info = ttb.cp_als(X, 3, dimorder=[1, 2, 0], init=\"nvecs\", printitn=20)\n", - "s = M2[0].score(M4)\n", - "print(f\"score(M2,M4) = {s[0]}\")" + "M4, _, M4_info = ttb.cp_als(X, R, maxiters=few_iters, init=\"nvecs\", printitn=0, dimorder=[2, 1, 0])\n", + "score_M4 = M4.score(M_true)\n", + "print(f\"Score of M3 and M_true: {score_M3[0]}\")\n", + "print(f\"Score of M4 and M_true: {score_M4[0]}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In the last example, we also collected the third output argument `info` which has runtime information in it. The field `info[\"iters\"]` has the total number of iterations. The field `info[\"params\"]` has the information used to run the method. Unless the initialization method is `\"random\"`, passing the parameters back to the method will yield the exact same results." + "In the last example, we also collected the third output argument `M4_info` which has runtime information in it. The field `M4_info[\"iters\"]` has the total number of iterations. The field `M4_info[\"params\"]` has the information used to run the method. Unless the initialization method is `\"random\"`, passing the parameters back to the method will yield the exact same results." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "M4alt, _, info = ttb.cp_als(X, 3, **info[\"params\"])\n", - "s = M4alt.score(M4)\n", - "print(f\"score(M4alt,M4) = {s[0]}\")" + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Score of M4 and M4_rerun: 0.9999999999999986\n", + "M4_info:\n", + "\tparams: {'stoptol': 0.0001, 'maxiters': 10, 'dimorder': [2, 1, 0], 'printitn': 0, 'fixsigns': True}\n", + "\titers: 9\n", + "\tnormresidual: 0.45173622073800845\n", + "\tfit: 0.9535657698910707\n", + "M4_rerun_info:\n", + "\tparams: {'stoptol': 0.0001, 'maxiters': 10, 'dimorder': [2, 1, 0], 'printitn': 0, 'fixsigns': True}\n", + "\titers: 9\n", + "\tnormresidual: 0.4517362207380714\n", + "\tfit: 0.9535657698910641\n" + ] + } + ], + "source": [ + "M4_rerun, _, M4_rerun_info = ttb.cp_als(X, R, init=\"nvecs\", **M4_info[\"params\"])\n", + "score_M4_rerun = M4.score(M4_rerun)\n", + "print(f\"Score of M4 and M4_rerun: {score_M4_rerun[0]}\")\n", + "\n", + "print(\"M4_info:\")\n", + "for k, v in M4_info.items(): print(f\"\\t{k}: {v}\")\n", + "\n", + "print(\"M4_rerun_info:\")\n", + "for k, v in M4_rerun_info.items(): print(f\"\\t{k}: {v}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Change the tolerance\n", - "It's also possible to loosen or tighten the tolerance on the change in the fit. You may need to increase the number of iterations for it to converge." + "## Change the stopping tolerance\n", + "It's also possible to loosen or tighten the stopping tolerance on the change in the fit. Note that you may need to increase the number of iterations for it to converge." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 8.214438e-01 f-delta = 8.2e-01\n", + " Iter 100: f = 9.983903e-01 f-delta = 5.1e-05\n", + " Iter 200: f = 9.999079e-01 f-delta = 2.5e-06\n", + " Iter 300: f = 9.999932e-01 f-delta = 1.8e-07\n", + " Iter 400: f = 9.999995e-01 f-delta = 1.3e-08\n", + " Iter 449: f = 9.999999e-01 f-delta = 0.0e+00\n", + " Final f = 9.999999e-01\n" + ] + } + ], "source": [ - "M5 = ttb.cp_als(X, 3, init=\"nvecs\", stoptol=1e-12, printitn=100)" + "M5 = ttb.cp_als(X, R, init=\"nvecs\", maxiters=1000, stoptol=1e-12, printitn=100)" ] }, { @@ -314,21 +570,62 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "X = ttb.ktensor(\n", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "X2=\n", + "ktensor of shape (2, 2)\n", + "weights=[1. 1.]\n", + "factor_matrices[0] =\n", + "[[ 1. 1.]\n", + " [ -1. -10.]]\n", + "factor_matrices[1] =\n", + "[[ 1. 1.]\n", + " [ -2. -10.]]\n", + "\n", + "M_fixsigns=\n", + "ktensor of shape (2, 2)\n", + "weights=[101. 3.16227766]\n", + "factor_matrices[0] =\n", + "[[-0.09950372 -0.70710678]\n", + " [ 0.99503719 0.70710678]]\n", + "factor_matrices[1] =\n", + "[[-0.09950372 -0.4472136 ]\n", + " [ 0.99503719 0.89442719]]\n", + "\n", + "M_no_fixsigns=\n", + "ktensor of shape (2, 2)\n", + "weights=[101. 3.16227766]\n", + "factor_matrices[0] =\n", + "[[ 0.09950372 0.70710678]\n", + " [-0.99503719 -0.70710678]]\n", + "factor_matrices[1] =\n", + "[[ 0.09950372 0.4472136 ]\n", + " [-0.99503719 -0.89442719]]\n", + "\n" + ] + } + ], + "source": [ + "# Create rank-2 tensor \n", + "X2 = ttb.ktensor(\n", " factor_matrices=[\n", - " np.array([[1.0, 1.0], [1.0, -10.0]]),\n", - " np.array([[1.0, 1.0], [1.0, -10.0]]),\n", + " np.array([[1.0, 1.0], [-1.0, -10.0]]),\n", + " np.array([[1.0, 1.0], [-2.0, -10.0]]),\n", " ],\n", - " weights=np.array([1.0, 1.0]),\n", + " weights=np.array([1.0, 1.0])\n", ")\n", - "M1 = ttb.cp_als(X, 2, printitn=1, init=ttb.ktensor(X.factor_matrices))\n", - "print(M1[0]) # default behavior, fixsigns called\n", - "M2 = ttb.cp_als(X, 2, printitn=1, init=ttb.ktensor(X.factor_matrices), fixsigns=False)\n", - "print(M2[0]) # fixsigns not called" + "print(f\"X2=\\n{X2}\\n\")\n", + "\n", + "M_fixsigns, _, _ = ttb.cp_als(X2, 2, printitn=0, init=ttb.ktensor(X2.factor_matrices))\n", + "print(f\"M_fixsigns=\\n{M_fixsigns}\\n\") # default behavior, fixsigns called\n", + "\n", + "M_no_fixsigns, _, _ = ttb.cp_als(X2, 2, printitn=0, init=ttb.ktensor(X2.factor_matrices), fixsigns=False)\n", + "print(f\"M_no_fixsigns=\\n{M_no_fixsigns}\\n\") # fixsigns not called\n" ] }, { @@ -341,7 +638,25 @@ ] } ], - "metadata": {}, + "metadata": { + "kernelspec": { + "display_name": "base", + "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.9.13" + } + }, "nbformat": 4, "nbformat_minor": 2 } From 090f892f2f37fbac04343462d47d61c404e971ab Mon Sep 17 00:00:00 2001 From: Danny Dunlavy Date: Tue, 4 Feb 2025 22:32:50 -0700 Subject: [PATCH 2/7] Running nbstripout --- docs/source/tutorial/algorithm_cp_als.ipynb | 379 +++----------------- 1 file changed, 41 insertions(+), 338 deletions(-) diff --git a/docs/source/tutorial/algorithm_cp_als.ipynb b/docs/source/tutorial/algorithm_cp_als.ipynb index 5f215f1..9e8edd7 100644 --- a/docs/source/tutorial/algorithm_cp_als.ipynb +++ b/docs/source/tutorial/algorithm_cp_als.ipynb @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -41,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -72,28 +72,9 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 8.426960e-01 f-delta = 8.4e-01\n", - " Iter 1: f = 9.014378e-01 f-delta = 5.9e-02\n", - " Iter 2: f = 9.128262e-01 f-delta = 1.1e-02\n", - " Iter 3: f = 9.209368e-01 f-delta = 8.1e-03\n", - " Iter 4: f = 9.286166e-01 f-delta = 7.7e-03\n", - " Iter 5: f = 9.365676e-01 f-delta = 8.0e-03\n", - " Iter 6: f = 9.444309e-01 f-delta = 7.9e-03\n", - " Iter 7: f = 9.514539e-01 f-delta = 7.0e-03\n", - " Iter 8: f = 9.570292e-01 f-delta = 5.6e-03\n", - " Iter 9: f = 9.610205e-01 f-delta = 4.0e-03\n", - " Final f = 9.610205e-01\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# Compute a solution with final ktensor stored in M1\n", "np.random.seed(1) # Set seed for reproducibility\n", @@ -117,21 +98,9 @@ }, { "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "M1_info:\n", - "\tparams: {'stoptol': 0.0001, 'maxiters': 10, 'dimorder': [0, 1, 2], 'printitn': 1, 'fixsigns': True}\n", - "\titers: 9\n", - "\tnormresidual: 0.37921276695158984\n", - "\tfit: 0.9610204980860142\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "print(\"M1_info:\")\n", "for k, v in M1_info.items(): print(f\"\\t{k}: {v}\")" @@ -146,28 +115,9 @@ }, { "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 9.232027e-01 f-delta = 9.2e-01\n", - " Iter 1: f = 9.415585e-01 f-delta = 1.8e-02\n", - " Iter 2: f = 9.460143e-01 f-delta = 4.5e-03\n", - " Iter 3: f = 9.485320e-01 f-delta = 2.5e-03\n", - " Iter 4: f = 9.502871e-01 f-delta = 1.8e-03\n", - " Iter 5: f = 9.516351e-01 f-delta = 1.3e-03\n", - " Iter 6: f = 9.527532e-01 f-delta = 1.1e-03\n", - " Iter 7: f = 9.537623e-01 f-delta = 1.0e-03\n", - " Iter 8: f = 9.547515e-01 f-delta = 9.9e-04\n", - " Iter 9: f = 9.557875e-01 f-delta = 1.0e-03\n", - " Final f = 9.557875e-01\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# Compute a solution with final ktensor stored in M2\n", "np.random.seed(2) # Set seed for reproducibility\n", @@ -184,107 +134,9 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 9.232027e-01 f-delta = 9.2e-01\n", - " Iter 1: f = 9.415585e-01 f-delta = 1.8e-02\n", - " Iter 2: f = 9.460143e-01 f-delta = 4.5e-03\n", - " Iter 3: f = 9.485320e-01 f-delta = 2.5e-03\n", - " Iter 4: f = 9.502871e-01 f-delta = 1.8e-03\n", - " Iter 5: f = 9.516351e-01 f-delta = 1.3e-03\n", - " Iter 6: f = 9.527532e-01 f-delta = 1.1e-03\n", - " Iter 7: f = 9.537623e-01 f-delta = 1.0e-03\n", - " Iter 8: f = 9.547515e-01 f-delta = 9.9e-04\n", - " Iter 9: f = 9.557875e-01 f-delta = 1.0e-03\n", - " Iter 10: f = 9.569224e-01 f-delta = 1.1e-03\n", - " Iter 11: f = 9.581995e-01 f-delta = 1.3e-03\n", - " Iter 12: f = 9.596531e-01 f-delta = 1.5e-03\n", - " Iter 13: f = 9.613014e-01 f-delta = 1.6e-03\n", - " Iter 14: f = 9.631317e-01 f-delta = 1.8e-03\n", - " Iter 15: f = 9.650854e-01 f-delta = 2.0e-03\n", - " Iter 16: f = 9.670592e-01 f-delta = 2.0e-03\n", - " Iter 17: f = 9.689361e-01 f-delta = 1.9e-03\n", - " Iter 18: f = 9.706308e-01 f-delta = 1.7e-03\n", - " Iter 19: f = 9.721134e-01 f-delta = 1.5e-03\n", - " Iter 20: f = 9.733984e-01 f-delta = 1.3e-03\n", - " Iter 21: f = 9.745196e-01 f-delta = 1.1e-03\n", - " Iter 22: f = 9.755127e-01 f-delta = 9.9e-04\n", - " Iter 23: f = 9.764073e-01 f-delta = 8.9e-04\n", - " Iter 24: f = 9.772262e-01 f-delta = 8.2e-04\n", - " Iter 25: f = 9.779860e-01 f-delta = 7.6e-04\n", - " Iter 26: f = 9.786985e-01 f-delta = 7.1e-04\n", - " Iter 27: f = 9.793724e-01 f-delta = 6.7e-04\n", - " Iter 28: f = 9.800139e-01 f-delta = 6.4e-04\n", - " Iter 29: f = 9.806278e-01 f-delta = 6.1e-04\n", - " Iter 30: f = 9.812174e-01 f-delta = 5.9e-04\n", - " Iter 31: f = 9.817854e-01 f-delta = 5.7e-04\n", - " Iter 32: f = 9.823337e-01 f-delta = 5.5e-04\n", - " Iter 33: f = 9.828638e-01 f-delta = 5.3e-04\n", - " Iter 34: f = 9.833771e-01 f-delta = 5.1e-04\n", - " Iter 35: f = 9.838744e-01 f-delta = 5.0e-04\n", - " Iter 36: f = 9.843567e-01 f-delta = 4.8e-04\n", - " Iter 37: f = 9.848247e-01 f-delta = 4.7e-04\n", - " Iter 38: f = 9.852789e-01 f-delta = 4.5e-04\n", - " Iter 39: f = 9.857198e-01 f-delta = 4.4e-04\n", - " Iter 40: f = 9.861479e-01 f-delta = 4.3e-04\n", - " Iter 41: f = 9.865637e-01 f-delta = 4.2e-04\n", - " Iter 42: f = 9.869675e-01 f-delta = 4.0e-04\n", - " Iter 43: f = 9.873597e-01 f-delta = 3.9e-04\n", - " Iter 44: f = 9.877407e-01 f-delta = 3.8e-04\n", - " Iter 45: f = 9.881107e-01 f-delta = 3.7e-04\n", - " Iter 46: f = 9.884700e-01 f-delta = 3.6e-04\n", - " Iter 47: f = 9.888190e-01 f-delta = 3.5e-04\n", - " Iter 48: f = 9.891579e-01 f-delta = 3.4e-04\n", - " Iter 49: f = 9.894870e-01 f-delta = 3.3e-04\n", - " Iter 50: f = 9.898065e-01 f-delta = 3.2e-04\n", - " Iter 51: f = 9.901168e-01 f-delta = 3.1e-04\n", - " Iter 52: f = 9.904180e-01 f-delta = 3.0e-04\n", - " Iter 53: f = 9.907104e-01 f-delta = 2.9e-04\n", - " Iter 54: f = 9.909942e-01 f-delta = 2.8e-04\n", - " Iter 55: f = 9.912696e-01 f-delta = 2.8e-04\n", - " Iter 56: f = 9.915369e-01 f-delta = 2.7e-04\n", - " Iter 57: f = 9.917963e-01 f-delta = 2.6e-04\n", - " Iter 58: f = 9.920480e-01 f-delta = 2.5e-04\n", - " Iter 59: f = 9.922922e-01 f-delta = 2.4e-04\n", - " Iter 60: f = 9.925290e-01 f-delta = 2.4e-04\n", - " Iter 61: f = 9.927588e-01 f-delta = 2.3e-04\n", - " Iter 62: f = 9.929816e-01 f-delta = 2.2e-04\n", - " Iter 63: f = 9.931977e-01 f-delta = 2.2e-04\n", - " Iter 64: f = 9.934073e-01 f-delta = 2.1e-04\n", - " Iter 65: f = 9.936105e-01 f-delta = 2.0e-04\n", - " Iter 66: f = 9.938075e-01 f-delta = 2.0e-04\n", - " Iter 67: f = 9.939984e-01 f-delta = 1.9e-04\n", - " Iter 68: f = 9.941835e-01 f-delta = 1.9e-04\n", - " Iter 69: f = 9.943629e-01 f-delta = 1.8e-04\n", - " Iter 70: f = 9.945368e-01 f-delta = 1.7e-04\n", - " Iter 71: f = 9.947053e-01 f-delta = 1.7e-04\n", - " Iter 72: f = 9.948686e-01 f-delta = 1.6e-04\n", - " Iter 73: f = 9.950268e-01 f-delta = 1.6e-04\n", - " Iter 74: f = 9.951801e-01 f-delta = 1.5e-04\n", - " Iter 75: f = 9.953287e-01 f-delta = 1.5e-04\n", - " Iter 76: f = 9.954725e-01 f-delta = 1.4e-04\n", - " Iter 77: f = 9.956119e-01 f-delta = 1.4e-04\n", - " Iter 78: f = 9.957469e-01 f-delta = 1.4e-04\n", - " Iter 79: f = 9.958777e-01 f-delta = 1.3e-04\n", - " Iter 80: f = 9.960044e-01 f-delta = 1.3e-04\n", - " Iter 81: f = 9.961270e-01 f-delta = 1.2e-04\n", - " Iter 82: f = 9.962458e-01 f-delta = 1.2e-04\n", - " Iter 83: f = 9.963609e-01 f-delta = 1.2e-04\n", - " Iter 84: f = 9.964723e-01 f-delta = 1.1e-04\n", - " Iter 85: f = 9.965802e-01 f-delta = 1.1e-04\n", - " Iter 86: f = 9.966847e-01 f-delta = 1.0e-04\n", - " Iter 87: f = 9.967859e-01 f-delta = 1.0e-04\n", - " Iter 88: f = 9.968838e-01 f-delta = 9.8e-05\n", - " Final f = 9.968838e-01\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "more_iters = 10 * few_iters\n", "M2_better, _, _ = ttb.cp_als(X, R, maxiters=more_iters, init=M2_init)" @@ -300,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -317,18 +169,9 @@ }, { "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Score of M2 and M_true: 0.5167723537387389\n", - "Score of M2_better and M_true: 0.9519267496183975\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "print(f\"Score of M2 and M_true: {score_M2[0]}\")\n", "print(f\"Score of M2_better and M_true: {score_M2_better[0]}\")" @@ -351,29 +194,9 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 9.232027e-01 f-delta = 9.2e-01\n", - " Iter 1: f = 9.415585e-01 f-delta = 1.8e-02\n", - " Iter 2: f = 9.460143e-01 f-delta = 4.5e-03\n", - " Iter 3: f = 9.485320e-01 f-delta = 2.5e-03\n", - " Iter 4: f = 9.502871e-01 f-delta = 1.8e-03\n", - " Iter 5: f = 9.516351e-01 f-delta = 1.3e-03\n", - " Iter 6: f = 9.527532e-01 f-delta = 1.1e-03\n", - " Iter 7: f = 9.537623e-01 f-delta = 1.0e-03\n", - " Iter 8: f = 9.547515e-01 f-delta = 9.9e-04\n", - " Iter 9: f = 9.557875e-01 f-delta = 1.0e-03\n", - " Final f = 9.557875e-01\n", - "Score: 1.0000000000000007\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "M2_rerun, _, _ = ttb.cp_als(X, R, maxiters=few_iters, init=M2_init)\n", "score_M2_rerun = M2.score(M2_rerun) # Score of 1 indicates the same solution\n", @@ -390,23 +213,9 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 8.805093e-01 f-delta = 8.8e-01\n", - " Iter 2: f = 9.379232e-01 f-delta = 1.5e-02\n", - " Iter 4: f = 9.445392e-01 f-delta = 3.0e-03\n", - " Iter 6: f = 9.492378e-01 f-delta = 2.2e-03\n", - " Iter 8: f = 9.532334e-01 f-delta = 2.0e-03\n", - " Final f = 9.552078e-01\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "M = ttb.cp_als(X, R, maxiters=few_iters, printitn=2)" ] @@ -421,7 +230,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -438,18 +247,9 @@ }, { "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Score of M2 and M_true: 0.5167723537387389\n", - "Score of M3 and M_true: 0.5406177000260891\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "M3, _, _ = ttb.cp_als(X, R, maxiters=few_iters, init=\"nvecs\", printitn=0)\n", "score_M3 = M3.score(M_true)\n", @@ -467,18 +267,9 @@ }, { "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Score of M3 and M_true: 0.5406177000260891\n", - "Score of M4 and M_true: 0.631431759054776\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "M4, _, M4_info = ttb.cp_als(X, R, maxiters=few_iters, init=\"nvecs\", printitn=0, dimorder=[2, 1, 0])\n", "score_M4 = M4.score(M_true)\n", @@ -495,27 +286,9 @@ }, { "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Score of M4 and M4_rerun: 0.9999999999999986\n", - "M4_info:\n", - "\tparams: {'stoptol': 0.0001, 'maxiters': 10, 'dimorder': [2, 1, 0], 'printitn': 0, 'fixsigns': True}\n", - "\titers: 9\n", - "\tnormresidual: 0.45173622073800845\n", - "\tfit: 0.9535657698910707\n", - "M4_rerun_info:\n", - "\tparams: {'stoptol': 0.0001, 'maxiters': 10, 'dimorder': [2, 1, 0], 'printitn': 0, 'fixsigns': True}\n", - "\titers: 9\n", - "\tnormresidual: 0.4517362207380714\n", - "\tfit: 0.9535657698910641\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "M4_rerun, _, M4_rerun_info = ttb.cp_als(X, R, init=\"nvecs\", **M4_info[\"params\"])\n", "score_M4_rerun = M4.score(M4_rerun)\n", @@ -538,24 +311,9 @@ }, { "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 8.214438e-01 f-delta = 8.2e-01\n", - " Iter 100: f = 9.983903e-01 f-delta = 5.1e-05\n", - " Iter 200: f = 9.999079e-01 f-delta = 2.5e-06\n", - " Iter 300: f = 9.999932e-01 f-delta = 1.8e-07\n", - " Iter 400: f = 9.999995e-01 f-delta = 1.3e-08\n", - " Iter 449: f = 9.999999e-01 f-delta = 0.0e+00\n", - " Final f = 9.999999e-01\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "M5 = ttb.cp_als(X, R, init=\"nvecs\", maxiters=1000, stoptol=1e-12, printitn=100)" ] @@ -570,46 +328,9 @@ }, { "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "X2=\n", - "ktensor of shape (2, 2)\n", - "weights=[1. 1.]\n", - "factor_matrices[0] =\n", - "[[ 1. 1.]\n", - " [ -1. -10.]]\n", - "factor_matrices[1] =\n", - "[[ 1. 1.]\n", - " [ -2. -10.]]\n", - "\n", - "M_fixsigns=\n", - "ktensor of shape (2, 2)\n", - "weights=[101. 3.16227766]\n", - "factor_matrices[0] =\n", - "[[-0.09950372 -0.70710678]\n", - " [ 0.99503719 0.70710678]]\n", - "factor_matrices[1] =\n", - "[[-0.09950372 -0.4472136 ]\n", - " [ 0.99503719 0.89442719]]\n", - "\n", - "M_no_fixsigns=\n", - "ktensor of shape (2, 2)\n", - "weights=[101. 3.16227766]\n", - "factor_matrices[0] =\n", - "[[ 0.09950372 0.70710678]\n", - " [-0.99503719 -0.70710678]]\n", - "factor_matrices[1] =\n", - "[[ 0.09950372 0.4472136 ]\n", - " [-0.99503719 -0.89442719]]\n", - "\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# Create rank-2 tensor \n", "X2 = ttb.ktensor(\n", @@ -638,25 +359,7 @@ ] } ], - "metadata": { - "kernelspec": { - "display_name": "base", - "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.9.13" - } - }, + "metadata": {}, "nbformat": 4, "nbformat_minor": 2 } From cf1f99ebfab85c17bbd50082368ae337ffe32a35 Mon Sep 17 00:00:00 2001 From: Danny Dunlavy Date: Tue, 4 Feb 2025 22:59:02 -0700 Subject: [PATCH 3/7] Running ruff format --- docs/source/tutorial/algorithm_cp_als.ipynb | 39 ++++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/docs/source/tutorial/algorithm_cp_als.ipynb b/docs/source/tutorial/algorithm_cp_als.ipynb index 9e8edd7..ebfa21b 100644 --- a/docs/source/tutorial/algorithm_cp_als.ipynb +++ b/docs/source/tutorial/algorithm_cp_als.ipynb @@ -53,7 +53,7 @@ "np.random.seed(0)\n", "\n", "# Create a low-rank dense tensor from a Kruskal tensor\n", - "factor_matrices = [np.random.rand(s,R) for s in tensor_shape]\n", + "factor_matrices = [np.random.rand(s, R) for s in tensor_shape]\n", "M_true = ttb.ktensor(factor_matrices)\n", "X = M_true.to_tensor()" ] @@ -103,7 +103,8 @@ "outputs": [], "source": [ "print(\"M1_info:\")\n", - "for k, v in M1_info.items(): print(f\"\\t{k}: {v}\")" + "for k, v in M1_info.items():\n", + " print(f\"\\t{k}: {v}\")" ] }, { @@ -121,7 +122,9 @@ "source": [ "# Compute a solution with final ktensor stored in M2\n", "np.random.seed(2) # Set seed for reproducibility\n", - "M2, M2_init, _ = ttb.cp_als(X, R, maxiters=few_iters) # Will not use third output, so leaving unassigned" + "M2, M2_init, _ = ttb.cp_als(\n", + " X, R, maxiters=few_iters\n", + ") # Will not use third output, so leaving unassigned" ] }, { @@ -254,7 +257,7 @@ "M3, _, _ = ttb.cp_als(X, R, maxiters=few_iters, init=\"nvecs\", printitn=0)\n", "score_M3 = M3.score(M_true)\n", "print(f\"Score of M2 and M_true: {score_M2[0]}\")\n", - "print(f\"Score of M3 and M_true: {score_M3[0]}\")\n" + "print(f\"Score of M3 and M_true: {score_M3[0]}\")" ] }, { @@ -271,10 +274,12 @@ "metadata": {}, "outputs": [], "source": [ - "M4, _, M4_info = ttb.cp_als(X, R, maxiters=few_iters, init=\"nvecs\", printitn=0, dimorder=[2, 1, 0])\n", + "M4, _, M4_info = ttb.cp_als(\n", + " X, R, maxiters=few_iters, init=\"nvecs\", printitn=0, dimorder=[2, 1, 0]\n", + ")\n", "score_M4 = M4.score(M_true)\n", "print(f\"Score of M3 and M_true: {score_M3[0]}\")\n", - "print(f\"Score of M4 and M_true: {score_M4[0]}\")\n" + "print(f\"Score of M4 and M_true: {score_M4[0]}\")" ] }, { @@ -295,10 +300,12 @@ "print(f\"Score of M4 and M4_rerun: {score_M4_rerun[0]}\")\n", "\n", "print(\"M4_info:\")\n", - "for k, v in M4_info.items(): print(f\"\\t{k}: {v}\")\n", + "for k, v in M4_info.items():\n", + " print(f\"\\t{k}: {v}\")\n", "\n", "print(\"M4_rerun_info:\")\n", - "for k, v in M4_rerun_info.items(): print(f\"\\t{k}: {v}\")" + "for k, v in M4_rerun_info.items():\n", + " print(f\"\\t{k}: {v}\")" ] }, { @@ -332,21 +339,23 @@ "metadata": {}, "outputs": [], "source": [ - "# Create rank-2 tensor \n", + "# Create rank-2 tensor\n", "X2 = ttb.ktensor(\n", " factor_matrices=[\n", " np.array([[1.0, 1.0], [-1.0, -10.0]]),\n", " np.array([[1.0, 1.0], [-2.0, -10.0]]),\n", " ],\n", - " weights=np.array([1.0, 1.0])\n", + " weights=np.array([1.0, 1.0]),\n", ")\n", "print(f\"X2=\\n{X2}\\n\")\n", "\n", "M_fixsigns, _, _ = ttb.cp_als(X2, 2, printitn=0, init=ttb.ktensor(X2.factor_matrices))\n", "print(f\"M_fixsigns=\\n{M_fixsigns}\\n\") # default behavior, fixsigns called\n", "\n", - "M_no_fixsigns, _, _ = ttb.cp_als(X2, 2, printitn=0, init=ttb.ktensor(X2.factor_matrices), fixsigns=False)\n", - "print(f\"M_no_fixsigns=\\n{M_no_fixsigns}\\n\") # fixsigns not called\n" + "M_no_fixsigns, _, _ = ttb.cp_als(\n", + " X2, 2, printitn=0, init=ttb.ktensor(X2.factor_matrices), fixsigns=False\n", + ")\n", + "print(f\"M_no_fixsigns=\\n{M_no_fixsigns}\\n\") # fixsigns not called" ] }, { @@ -359,7 +368,11 @@ ] } ], - "metadata": {}, + "metadata": { + "language_info": { + "name": "python" + } + }, "nbformat": 4, "nbformat_minor": 2 } From 42adca7674a893fbce0e0514a588d2168f7da093 Mon Sep 17 00:00:00 2001 From: Danny Dunlavy Date: Tue, 4 Feb 2025 23:00:51 -0700 Subject: [PATCH 4/7] Run nbstripout --- docs/source/tutorial/algorithm_cp_als.ipynb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/source/tutorial/algorithm_cp_als.ipynb b/docs/source/tutorial/algorithm_cp_als.ipynb index ebfa21b..b5f0a10 100644 --- a/docs/source/tutorial/algorithm_cp_als.ipynb +++ b/docs/source/tutorial/algorithm_cp_als.ipynb @@ -368,11 +368,7 @@ ] } ], - "metadata": { - "language_info": { - "name": "python" - } - }, + "metadata": {}, "nbformat": 4, "nbformat_minor": 2 } From 7517213b4e06483487343340264a3f86a84c7730 Mon Sep 17 00:00:00 2001 From: Danny Dunlavy Date: Fri, 21 Mar 2025 09:11:41 -0600 Subject: [PATCH 5/7] Checkpoint --- docs/source/tutorial/algorithm_cp_als.ipynb | 327 +++++++++++++++----- 1 file changed, 242 insertions(+), 85 deletions(-) diff --git a/docs/source/tutorial/algorithm_cp_als.ipynb b/docs/source/tutorial/algorithm_cp_als.ipynb index b5f0a10..adc6095 100644 --- a/docs/source/tutorial/algorithm_cp_als.ipynb +++ b/docs/source/tutorial/algorithm_cp_als.ipynb @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": {}, "outputs": [], "source": [ @@ -36,25 +36,25 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Generate data" + "## Generate low-rank data tensor" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 71, "metadata": {}, "outputs": [], "source": [ - "# Pick the rank and shape\n", - "R = 3\n", - "tensor_shape = (6, 8, 10)\n", + "# Choose the rank and shape\n", + "R = 2\n", + "tensor_shape = (3, 4, 5)\n", "\n", - "# Set seed for reproducibility\n", + "# Set the random seed for reproducibility\n", "np.random.seed(0)\n", "\n", - "# Create a low-rank dense tensor from a Kruskal tensor\n", - "factor_matrices = [np.random.rand(s, R) for s in tensor_shape]\n", - "M_true = ttb.ktensor(factor_matrices)\n", + "# Create a low-rank dense tensor from a Kruskal tensor (i.e., ktensor)\n", + "factor_matrices = [np.random.randn(s, R) for s in tensor_shape]\n", + "M_true = ttb.ktensor(factor_matrices) # true solution\n", "X = M_true.to_tensor()" ] }, @@ -62,8 +62,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Basic call to the method, specifying the data tensor and its rank\n", - "This uses a *random* initial guess. At each iteration, it reports the *fit* `f` which is defined as \n", + "## Run `cp_als` using default parameters\n", + "The `cp_als` method has two required inputs: a data tensor (X) and the rank of the CP model (R) to compute.\n", + "\n", + "By default, `cp_als` uses a *random* initial guess. At each iteration, it reports the *fit* `f` which is defined for a data tensor `X` and CP model `M` as \n", "```\n", "f = 1 - ( X.norm()**2 + M.norm()**2 - 2* ) / X.norm()\n", "``` \n", @@ -72,24 +74,41 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 5.629369e-01 f-delta = 5.6e-01\n", + " Iter 1: f = 6.994515e-01 f-delta = 1.4e-01\n", + " Iter 2: f = 7.186123e-01 f-delta = 1.9e-02\n", + " Iter 3: f = 7.270663e-01 f-delta = 8.5e-03\n", + " Iter 4: f = 7.305063e-01 f-delta = 3.4e-03\n", + " Iter 5: f = 7.317567e-01 f-delta = 1.3e-03\n", + " Iter 6: f = 7.321614e-01 f-delta = 4.0e-04\n", + " Iter 7: f = 7.323097e-01 f-delta = 1.5e-04\n", + " Iter 8: f = 7.323887e-01 f-delta = 7.9e-05\n", + " Final f = 7.323887e-01\n" + ] + } + ], "source": [ "# Compute a solution with final ktensor stored in M1\n", - "np.random.seed(1) # Set seed for reproducibility\n", - "few_iters = 10 # Cut off solve early for demo\n", - "M1, M1_init, M1_info = ttb.cp_als(X, R, maxiters=few_iters)" + "np.random.seed(1) # Set the random seed for reproducibility\n", + "M1, M1_init, M1_info = ttb.cp_als(X, R)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The `cp_als` method returns a the following objects:\n", + "The `cp_als` method returns the following:\n", "1. `M1`: the solution as a `ktensor`. \n", - "2. `M1_init`: the initial guess as a `ktensor` that was generated at runtime since no initial guess was provided. \n", - "3. `M1_info`: a dictionary containing runtime information with keys:\n", + "2. `M1_init`: the initial guess as a `ktensor` that was used in computing the solution. \n", + "3. `M1_info`: a `dict` containing runtime information with keys:\n", " * `params`: parameters used by `cp_als`\n", " * `iters`: number of iterations performed\n", " * `normresidual`: the norm of the residual `X.norm()**2 + M.norm()**2 - 2*`\n", @@ -98,9 +117,21 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "M1_info:\n", + "\tparams: {'stoptol': 0.0001, 'maxiters': 1000, 'dimorder': [0, 1, 2], 'printitn': 1, 'fixsigns': True}\n", + "\titers: 8\n", + "\tnormresidual: 3.1416394034928916\n", + "\tfit: 0.7323887077713267\n" + ] + } + ], "source": [ "print(\"M1_info:\")\n", "for k, v in M1_info.items():\n", @@ -111,99 +142,216 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Run again with a different initial guess, output the initial guess" + "## Run `cp_als` using different initial guesses" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# Compute a solution with final ktensor stored in M2\n", + "Different random initial guesses can be generated and used by setting different random seeds (via `numpy`). You can also explicitly set the `init` parameter to `\"random\"` to make it clear that the default random initialization is being used, although this is not necessary as illustrated above." + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 7.483199e-01 f-delta = 7.5e-01\n", + " Iter 1: f = 8.417330e-01 f-delta = 9.3e-02\n", + " Iter 2: f = 8.622039e-01 f-delta = 2.0e-02\n", + " Iter 3: f = 8.851075e-01 f-delta = 2.3e-02\n", + " Iter 4: f = 9.126355e-01 f-delta = 2.8e-02\n", + " Iter 5: f = 9.418493e-01 f-delta = 2.9e-02\n", + " Iter 6: f = 9.666331e-01 f-delta = 2.5e-02\n", + " Iter 7: f = 9.830955e-01 f-delta = 1.6e-02\n", + " Iter 8: f = 9.920977e-01 f-delta = 9.0e-03\n", + " Iter 9: f = 9.964589e-01 f-delta = 4.4e-03\n", + " Iter 10: f = 9.984440e-01 f-delta = 2.0e-03\n", + " Iter 11: f = 9.993222e-01 f-delta = 8.8e-04\n", + " Iter 12: f = 9.997058e-01 f-delta = 3.8e-04\n", + " Iter 13: f = 9.998725e-01 f-delta = 1.7e-04\n", + " Iter 14: f = 9.999448e-01 f-delta = 7.2e-05\n", + " Final f = 9.999448e-01\n" + ] + } + ], + "source": [ "np.random.seed(2) # Set seed for reproducibility\n", - "M2, M2_init, _ = ttb.cp_als(\n", - " X, R, maxiters=few_iters\n", - ") # Will not use third output, so leaving unassigned" + "M2, M2_init, _ = ttb.cp_als(X, R, init=\"random\") # leaving third output unassigned" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Increase the maximum number of iterations\n", - "Note that the previous run kicked out at only 10 iterations, before reaching the specified convegence tolerance. Let's increase the maximum number of iterations and try again, using the same initial guess." + "A specific `ktensor` can also be used as an initial guess. As an example, using the same initial guess (and all other parameters) as the previous run of `cp_als` gives the exact same solution." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "more_iters = 10 * few_iters\n", - "M2_better, _, _ = ttb.cp_als(X, R, maxiters=more_iters, init=M2_init)" + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 7.483199e-01 f-delta = 7.5e-01\n", + " Iter 1: f = 8.417330e-01 f-delta = 9.3e-02\n", + " Iter 2: f = 8.622039e-01 f-delta = 2.0e-02\n", + " Iter 3: f = 8.851075e-01 f-delta = 2.3e-02\n", + " Iter 4: f = 9.126355e-01 f-delta = 2.8e-02\n", + " Iter 5: f = 9.418493e-01 f-delta = 2.9e-02\n", + " Iter 6: f = 9.666331e-01 f-delta = 2.5e-02\n", + " Iter 7: f = 9.830955e-01 f-delta = 1.6e-02\n", + " Iter 8: f = 9.920977e-01 f-delta = 9.0e-03\n", + " Iter 9: f = 9.964589e-01 f-delta = 4.4e-03\n", + " Iter 10: f = 9.984440e-01 f-delta = 2.0e-03\n", + " Iter 11: f = 9.993222e-01 f-delta = 8.8e-04\n", + " Iter 12: f = 9.997058e-01 f-delta = 3.8e-04\n", + " Iter 13: f = 9.998725e-01 f-delta = 1.7e-04\n", + " Iter 14: f = 9.999448e-01 f-delta = 7.2e-05\n", + " Final f = 9.999448e-01\n" + ] + } + ], + "source": [ + "M2_rerun, _, _ = ttb.cp_als(X, R, init=M2_init)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Compare the two solutions\n", - "Use the `ktensor` `score()` member function to compare the two solutions. A score of 1 indicates a perfect match." + "The `\"nvecs\"` initialization option computes the initial guess using the eigenvectors of the outer product of the matricized data tensor. This initialization process will require more computation than the default random initialization, but it can often lead to better solutions in fewer iterations." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "score_M2 = M2.score(M_true)\n", - "score_M2_better = M2_better.score(M_true)" + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 9.399785e-01 f-delta = 9.4e-01\n", + " Iter 1: f = 9.735771e-01 f-delta = 3.4e-02\n", + " Iter 2: f = 9.889950e-01 f-delta = 1.5e-02\n", + " Iter 3: f = 9.955336e-01 f-delta = 6.5e-03\n", + " Iter 4: f = 9.981764e-01 f-delta = 2.6e-03\n", + " Iter 5: f = 9.992526e-01 f-delta = 1.1e-03\n", + " Iter 6: f = 9.996931e-01 f-delta = 4.4e-04\n", + " Iter 7: f = 9.998738e-01 f-delta = 1.8e-04\n", + " Iter 8: f = 9.999480e-01 f-delta = 7.4e-05\n", + " Final f = 9.999480e-01\n" + ] + } + ], + "source": [ + "M2_nvecs, _, _ = ttb.cp_als(X, R, init=\"nvecs\")\n", + "#score_M3 = M3.score(M_true)\n", + "#print(f\"Score of M2 and M_true: {score_M2[0]}\")\n", + "#print(f\"Score of M3 and M_true: {score_M3[0]}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Here, `score()` returns a tuple with the score as the first element:" + "## Evaluate and compare the outputs of `cp_als`\n", + "Use the `ktensor.score()` method to compare outputs of `cp_als` to the true solution if known. In the examples above, the data tensor was generated from a `ktensor`, `M_true`, which can be used to evaluate solutions computed using `cp_als`. A score of 1 indicates a perfect match.\n", + "\n", + "\n", + "Note that the `ktensor.score()` method returns a tuple with the score as the first element and other information related to the score computation as the remaining elements. See the `ktensor` documentation for more information about the return values." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ + "execution_count": 91, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Score of M1 and M_true: 0.1601831981192085\n", + "Score of M2 and M_true: 0.9999905577227325\n", + "Score of M2_nvecs and M_true: 0.9999958760911375\n" + ] + } + ], + "source": [ + "score_M1 = M1.score(M_true) # not a good solution\n", + "score_M2 = M2.score(M_true) # a better solution\n", + "score_M2_nvecs = M2_nvecs.score(M_true) # an even better solution\n", + "\n", + "print(f\"Score of M1 and M_true: {score_M1[0]}\")\n", "print(f\"Score of M2 and M_true: {score_M2[0]}\")\n", - "print(f\"Score of M2_better and M_true: {score_M2_better[0]}\")" + "print(f\"Score of M2_nvecs and M_true: {score_M2_nvecs[0]}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "See the `ktensor` documentation for more information about the return values of `score()`." + "When two solutions match, as is the case with `M2` and `M2_rerun`, the score will be 1 (up to floating point error)." + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Score of M2 and M2_rerun: 1.0000000000000004\n" + ] + } + ], + "source": [ + "score_M2_rerun = M2.score(M2_rerun)\n", + "\n", + "print(f\"Score of M2 and M2_rerun: {score_M2_rerun[0]}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Rerun with same initial guess\n", - "Using the same initial guess (and all other parameters) gives the exact same solution." + "## Increase the maximum number of iterations\n", + "Note that the previous run kicked out at only 10 iterations, before reaching the specified convegence tolerance. Let's increase the maximum number of iterations and try again, using the same initial guess." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 90, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 1.000000e+00 f-delta = 1.0e+00\n", + " Iter 1: f = 1.000000e+00 f-delta = 0.0e+00\n", + " Final f = 1.000000e+00\n" + ] + } + ], "source": [ - "M2_rerun, _, _ = ttb.cp_als(X, R, maxiters=few_iters, init=M2_init)\n", - "score_M2_rerun = M2.score(M2_rerun) # Score of 1 indicates the same solution\n", - "print(f\"Score: {score_M2_rerun[0]}\")" + "more_iters = 10 * few_iters\n", + "M2_better, _, _ = ttb.cp_als(X, R, maxiters=more_iters, init=M_true)" ] }, { @@ -216,11 +364,28 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "M = ttb.cp_als(X, R, maxiters=few_iters, printitn=2)" + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP_ALS:\n", + " Iter 0: f = 5.302221e-01 f-delta = 5.3e-01\n", + " Iter 5: f = 7.375846e-01 f-delta = 5.5e-03\n", + " Iter 10: f = 7.438511e-01 f-delta = 1.1e-03\n", + " Iter 15: f = 7.542500e-01 f-delta = 3.1e-03\n", + " Iter 20: f = 8.015607e-01 f-delta = 1.8e-02\n", + " Iter 25: f = 9.874955e-01 f-delta = 1.8e-02\n", + " Iter 30: f = 9.998250e-01 f-delta = 2.3e-04\n", + " Iter 31: f = 9.999244e-01 f-delta = 9.9e-05\n", + " Final f = 9.999244e-01\n" + ] + } + ], + "source": [ + "M = ttb.cp_als(X, R, printitn=5)" ] }, { @@ -233,31 +398,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 60, "metadata": {}, "outputs": [], "source": [ - "M = ttb.cp_als(X, R, maxiters=few_iters, printitn=0) # No output" + "M = ttb.cp_als(X, R, printitn=0) # No output" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Use HOSVD initial guess\n", - "Use the `\"nvecs\"` option to use the leading mode-$n$ singular vectors as the initial guess. The initialization process will require more computation in general, but it may lead to better solutions." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "M3, _, _ = ttb.cp_als(X, R, maxiters=few_iters, init=\"nvecs\", printitn=0)\n", - "score_M3 = M3.score(M_true)\n", - "print(f\"Score of M2 and M_true: {score_M2[0]}\")\n", - "print(f\"Score of M3 and M_true: {score_M3[0]}\")" + "## Use initial guess based \n", + "Use the `\"nvecs\"` option to initialize `cp_als` with the leading mode-$n$ singular vectors of the input tensor. This initialization process will require more computation than the default `\"random` initialization in general, but it can lead to better solutions." ] }, { @@ -368,7 +521,11 @@ ] } ], - "metadata": {}, + "metadata": { + "language_info": { + "name": "python" + } + }, "nbformat": 4, "nbformat_minor": 2 } From c1745e6282f4b9650df4ec524a990ae0d1f9b41c Mon Sep 17 00:00:00 2001 From: Danny Dunlavy Date: Fri, 21 Mar 2025 11:20:23 -0600 Subject: [PATCH 6/7] Ruff formatting --- docs/source/tutorial/algorithm_cp_als.ipynb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/tutorial/algorithm_cp_als.ipynb b/docs/source/tutorial/algorithm_cp_als.ipynb index adc6095..fdf4c6b 100644 --- a/docs/source/tutorial/algorithm_cp_als.ipynb +++ b/docs/source/tutorial/algorithm_cp_als.ipynb @@ -54,7 +54,7 @@ "\n", "# Create a low-rank dense tensor from a Kruskal tensor (i.e., ktensor)\n", "factor_matrices = [np.random.randn(s, R) for s in tensor_shape]\n", - "M_true = ttb.ktensor(factor_matrices) # true solution\n", + "M_true = ttb.ktensor(factor_matrices) # true solution\n", "X = M_true.to_tensor()" ] }, @@ -258,9 +258,9 @@ ], "source": [ "M2_nvecs, _, _ = ttb.cp_als(X, R, init=\"nvecs\")\n", - "#score_M3 = M3.score(M_true)\n", - "#print(f\"Score of M2 and M_true: {score_M2[0]}\")\n", - "#print(f\"Score of M3 and M_true: {score_M3[0]}\")" + "# score_M3 = M3.score(M_true)\n", + "# print(f\"Score of M2 and M_true: {score_M2[0]}\")\n", + "# print(f\"Score of M3 and M_true: {score_M3[0]}\")" ] }, { @@ -296,7 +296,7 @@ "\n", "print(f\"Score of M1 and M_true: {score_M1[0]}\")\n", "print(f\"Score of M2 and M_true: {score_M2[0]}\")\n", - "print(f\"Score of M2_nvecs and M_true: {score_M2_nvecs[0]}\")\n" + "print(f\"Score of M2_nvecs and M_true: {score_M2_nvecs[0]}\")" ] }, { From 8dfda3f64c28769f4d6ad2e4fa7d805134c59566 Mon Sep 17 00:00:00 2001 From: Danny Dunlavy Date: Fri, 21 Mar 2025 11:22:28 -0600 Subject: [PATCH 7/7] Running nbstripout --- docs/source/tutorial/algorithm_cp_als.ipynb | 208 +++----------------- 1 file changed, 31 insertions(+), 177 deletions(-) diff --git a/docs/source/tutorial/algorithm_cp_als.ipynb b/docs/source/tutorial/algorithm_cp_als.ipynb index fdf4c6b..062f6f0 100644 --- a/docs/source/tutorial/algorithm_cp_als.ipynb +++ b/docs/source/tutorial/algorithm_cp_als.ipynb @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -41,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 71, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -74,27 +74,9 @@ }, { "cell_type": "code", - "execution_count": 72, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 5.629369e-01 f-delta = 5.6e-01\n", - " Iter 1: f = 6.994515e-01 f-delta = 1.4e-01\n", - " Iter 2: f = 7.186123e-01 f-delta = 1.9e-02\n", - " Iter 3: f = 7.270663e-01 f-delta = 8.5e-03\n", - " Iter 4: f = 7.305063e-01 f-delta = 3.4e-03\n", - " Iter 5: f = 7.317567e-01 f-delta = 1.3e-03\n", - " Iter 6: f = 7.321614e-01 f-delta = 4.0e-04\n", - " Iter 7: f = 7.323097e-01 f-delta = 1.5e-04\n", - " Iter 8: f = 7.323887e-01 f-delta = 7.9e-05\n", - " Final f = 7.323887e-01\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "# Compute a solution with final ktensor stored in M1\n", "np.random.seed(1) # Set the random seed for reproducibility\n", @@ -117,21 +99,9 @@ }, { "cell_type": "code", - "execution_count": 66, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "M1_info:\n", - "\tparams: {'stoptol': 0.0001, 'maxiters': 1000, 'dimorder': [0, 1, 2], 'printitn': 1, 'fixsigns': True}\n", - "\titers: 8\n", - "\tnormresidual: 3.1416394034928916\n", - "\tfit: 0.7323887077713267\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "print(\"M1_info:\")\n", "for k, v in M1_info.items():\n", @@ -154,33 +124,9 @@ }, { "cell_type": "code", - "execution_count": 79, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 7.483199e-01 f-delta = 7.5e-01\n", - " Iter 1: f = 8.417330e-01 f-delta = 9.3e-02\n", - " Iter 2: f = 8.622039e-01 f-delta = 2.0e-02\n", - " Iter 3: f = 8.851075e-01 f-delta = 2.3e-02\n", - " Iter 4: f = 9.126355e-01 f-delta = 2.8e-02\n", - " Iter 5: f = 9.418493e-01 f-delta = 2.9e-02\n", - " Iter 6: f = 9.666331e-01 f-delta = 2.5e-02\n", - " Iter 7: f = 9.830955e-01 f-delta = 1.6e-02\n", - " Iter 8: f = 9.920977e-01 f-delta = 9.0e-03\n", - " Iter 9: f = 9.964589e-01 f-delta = 4.4e-03\n", - " Iter 10: f = 9.984440e-01 f-delta = 2.0e-03\n", - " Iter 11: f = 9.993222e-01 f-delta = 8.8e-04\n", - " Iter 12: f = 9.997058e-01 f-delta = 3.8e-04\n", - " Iter 13: f = 9.998725e-01 f-delta = 1.7e-04\n", - " Iter 14: f = 9.999448e-01 f-delta = 7.2e-05\n", - " Final f = 9.999448e-01\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "np.random.seed(2) # Set seed for reproducibility\n", "M2, M2_init, _ = ttb.cp_als(X, R, init=\"random\") # leaving third output unassigned" @@ -195,33 +141,9 @@ }, { "cell_type": "code", - "execution_count": 80, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 7.483199e-01 f-delta = 7.5e-01\n", - " Iter 1: f = 8.417330e-01 f-delta = 9.3e-02\n", - " Iter 2: f = 8.622039e-01 f-delta = 2.0e-02\n", - " Iter 3: f = 8.851075e-01 f-delta = 2.3e-02\n", - " Iter 4: f = 9.126355e-01 f-delta = 2.8e-02\n", - " Iter 5: f = 9.418493e-01 f-delta = 2.9e-02\n", - " Iter 6: f = 9.666331e-01 f-delta = 2.5e-02\n", - " Iter 7: f = 9.830955e-01 f-delta = 1.6e-02\n", - " Iter 8: f = 9.920977e-01 f-delta = 9.0e-03\n", - " Iter 9: f = 9.964589e-01 f-delta = 4.4e-03\n", - " Iter 10: f = 9.984440e-01 f-delta = 2.0e-03\n", - " Iter 11: f = 9.993222e-01 f-delta = 8.8e-04\n", - " Iter 12: f = 9.997058e-01 f-delta = 3.8e-04\n", - " Iter 13: f = 9.998725e-01 f-delta = 1.7e-04\n", - " Iter 14: f = 9.999448e-01 f-delta = 7.2e-05\n", - " Final f = 9.999448e-01\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "M2_rerun, _, _ = ttb.cp_als(X, R, init=M2_init)" ] @@ -235,27 +157,9 @@ }, { "cell_type": "code", - "execution_count": 81, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 9.399785e-01 f-delta = 9.4e-01\n", - " Iter 1: f = 9.735771e-01 f-delta = 3.4e-02\n", - " Iter 2: f = 9.889950e-01 f-delta = 1.5e-02\n", - " Iter 3: f = 9.955336e-01 f-delta = 6.5e-03\n", - " Iter 4: f = 9.981764e-01 f-delta = 2.6e-03\n", - " Iter 5: f = 9.992526e-01 f-delta = 1.1e-03\n", - " Iter 6: f = 9.996931e-01 f-delta = 4.4e-04\n", - " Iter 7: f = 9.998738e-01 f-delta = 1.8e-04\n", - " Iter 8: f = 9.999480e-01 f-delta = 7.4e-05\n", - " Final f = 9.999480e-01\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "M2_nvecs, _, _ = ttb.cp_als(X, R, init=\"nvecs\")\n", "# score_M3 = M3.score(M_true)\n", @@ -276,19 +180,9 @@ }, { "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Score of M1 and M_true: 0.1601831981192085\n", - "Score of M2 and M_true: 0.9999905577227325\n", - "Score of M2_nvecs and M_true: 0.9999958760911375\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "score_M1 = M1.score(M_true) # not a good solution\n", "score_M2 = M2.score(M_true) # a better solution\n", @@ -308,17 +202,9 @@ }, { "cell_type": "code", - "execution_count": 89, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Score of M2 and M2_rerun: 1.0000000000000004\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "score_M2_rerun = M2.score(M2_rerun)\n", "\n", @@ -335,20 +221,9 @@ }, { "cell_type": "code", - "execution_count": 90, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 1.000000e+00 f-delta = 1.0e+00\n", - " Iter 1: f = 1.000000e+00 f-delta = 0.0e+00\n", - " Final f = 1.000000e+00\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "more_iters = 10 * few_iters\n", "M2_better, _, _ = ttb.cp_als(X, R, maxiters=more_iters, init=M_true)" @@ -364,26 +239,9 @@ }, { "cell_type": "code", - "execution_count": 59, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP_ALS:\n", - " Iter 0: f = 5.302221e-01 f-delta = 5.3e-01\n", - " Iter 5: f = 7.375846e-01 f-delta = 5.5e-03\n", - " Iter 10: f = 7.438511e-01 f-delta = 1.1e-03\n", - " Iter 15: f = 7.542500e-01 f-delta = 3.1e-03\n", - " Iter 20: f = 8.015607e-01 f-delta = 1.8e-02\n", - " Iter 25: f = 9.874955e-01 f-delta = 1.8e-02\n", - " Iter 30: f = 9.998250e-01 f-delta = 2.3e-04\n", - " Iter 31: f = 9.999244e-01 f-delta = 9.9e-05\n", - " Final f = 9.999244e-01\n" - ] - } - ], + "execution_count": null, + "metadata": {}, + "outputs": [], "source": [ "M = ttb.cp_als(X, R, printitn=5)" ] @@ -398,7 +256,7 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -521,11 +379,7 @@ ] } ], - "metadata": { - "language_info": { - "name": "python" - } - }, + "metadata": {}, "nbformat": 4, "nbformat_minor": 2 }