{ "cells": [ { "cell_type": "markdown", "id": "224cb90e-08c1-4b41-b3ae-3eb1379caa29", "metadata": {}, "source": [ "# Background\n", "\n", "Partial least squares correlation (PLSC) is a multivariate statistical technique that uses [compact singular value decomposition (SVD)](https://en.wikipedia.org/wiki/Singular_value_decomposition#Compact_SVD) to identify associations between a set of multivariate observations and a design matrix. The details of this technique in the context of neuroimaging can be found in [Krishnan et al. (2011)](https://doi.org/10.1016/j.neuroimage.2010.07.034).\n", "\n", "The vocabulary of PLSC can be challenging, since different terms sometimes appear in different sources for the same underlying mathematical objects. Thus, to discuss the terminology used in `pyplsc`, we will also review the mathematics of PLSC." ] }, { "cell_type": "markdown", "id": "2d44349b-510d-4f15-bf47-ba0db5d049d0", "metadata": {}, "source": [ "## Mathematical overview and example" ] }, { "cell_type": "markdown", "id": "c4a9c074-6c0a-4c80-b101-bfb17dddc780", "metadata": {}, "source": [ "### Data and design matrices\n", "\n", "The two basic ingredients to PLSC are (1) a data matrix $X$ with one row per observation and one column per observed variable, and (2) a design matrix $Y$ with one row per observation whose columns contain covariates or encode experimental conditions. In the simplest case, which we will consider here for expository purposes, $Y$ contains only covariates. To make this concrete, we will create and inspect a simulated $X$ and $Y$:" ] }, { "cell_type": "code", "execution_count": 1, "id": "31c6ebad-df97-485c-86ca-4c0b4e9fbcc8", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "np.random.seed(123)\n", "\n", "n_obs = 4\n", "n_var = 5\n", "n_cov = 3\n", "true_latent_var = 5*np.random.normal(size=(n_obs, 1)) # Data covary\n", "X = true_latent_var + np.random.normal(size=(n_obs, n_var))\n", "Y = true_latent_var + np.random.normal(size=(n_obs, n_cov))" ] }, { "cell_type": "markdown", "id": "28c5b183-3b2c-442f-94ae-1a0e1432b6ce", "metadata": {}, "source": [ "Here, $X$ and $Y$ have the same number of rows:" ] }, { "cell_type": "code", "execution_count": 2, "id": "db480280-8eab-4255-b41c-e41945351f3e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[-6.00675327, -3.77671648, -7.85483226, -5.85706565, -4.16221676],\n", " [ 4.11998683, 4.30784108, 4.89201826, 6.47811686, 4.34782524],\n", " [ 0.97091053, 0.98054121, 3.62082257, 3.60167858, 2.41894639],\n", " [-7.14528717, -6.79410499, -6.04074154, -8.46730744, -6.35564452]])" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X" ] }, { "cell_type": "code", "execution_count": 3, "id": "a220b63d-41ed-4af6-8bd5-e8e073e4c7af", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[-6.68203368, -6.06590452, -4.52104782],\n", " [ 3.55804653, 4.84665851, 4.12497234],\n", " [ 1.15927312, -1.38369662, -0.35664061],\n", " [-8.2313508 , -6.60401114, -7.70510925]])" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Y" ] }, { "cell_type": "markdown", "id": "ecfa4698-0300-4048-b151-57c7e4f3e104", "metadata": {}, "source": [ "### Correlation and SVD\n", "\n", "Next, the correlations between the columns of $X$ and $Y$ are computed and stored in a new matrix $R$, to which compact SVD is applied:\n", "\n", "$$R = USV^T$$\n", "\n", "where $U$ and $V$ are orthonormal matrices of \"left singular vectors\" and \"right singular vectors\", respectively, and $S$ is a diagonal matrix of singular values.\n", "\n", "`pyplsc` computes and decomposing $R$ internally when the `.fit()` method of a model of class `PLSC` is called:" ] }, { "cell_type": "code", "execution_count": 4, "id": "391a5f4b-3ed7-44c6-89be-0790099a44c0", "metadata": {}, "outputs": [], "source": [ "from pyplsc import PLSC\n", "\n", "mod = PLSC()\n", "mod.fit(data=X, covariates=Y)" ] }, { "cell_type": "markdown", "id": "9fdb9994-88a9-4261-8950-fb35e3db4580", "metadata": {}, "source": [ "### Saliences\n", "\n", "The singular vectors $U$ and $V$ are also called \"saliences\"; thus we might refer to $U$ as the \"left saliences\" ad $V$ as the \"right saliences\". For clarity, in the context of neuroimaging, the terms \"brain saliences\" for $V$ and \"design saliences\" for $U$ can be used [('Krishnan et al., 2011)](https://doi.org/10.1016/j.neuroimage.2010.07.034), which saves us having to remember an arbitrary left--right mapping. `pyplsc` refers to $U$ as the \"design saliences\" but uses the non-neuroimaging-specific term \"data saliences\" for $V$. After calling `.fit()`, these are accessible by the properties `design_sals_` and `data_sals_` (with the trailing underscores because these properties are added by fitting the model, following the scikit-learn convention):" ] }, { "cell_type": "code", "execution_count": 5, "id": "b54065b5-d9e9-4d4b-9ce2-cb8af570eecb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[-0.59266317, 0.68357283, 0.426003 ],\n", " [-0.56264137, 0.02710892, -0.82625649],\n", " [-0.57635497, -0.7293787 , 0.3685399 ]])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mod.design_sals_" ] }, { "cell_type": "code", "execution_count": 6, "id": "24cedfb5-cc2a-4018-b581-c9c6856adfda", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[-0.45449331, -0.08584571, -0.63766531],\n", " [-0.45392915, -0.5901328 , -0.20111844],\n", " [-0.42744766, 0.8003629 , -0.16236509],\n", " [-0.45031061, -0.02013286, 0.38956821],\n", " [-0.44932506, -0.0582038 , 0.61221606]])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mod.data_sals_" ] }, { "cell_type": "markdown", "id": "e4e9c49e-1ab0-4d52-a995-fdba0f5a8623", "metadata": {}, "source": [ "### Latent variables\n", "\n", "PLSC can be interpreted as identifying pairs of latent variables with maximal covariance. If $U_{:,i}$ and $V_{:,i}$ are the $i$th columns of the design and data saliences, respectively, the values of the $i$th pair of these latent variables are estimated as $L_{Y,i} = YU_{:,i}$ and $L_{X,i} = XV_{:,i}$. In neuroimaging, $L_{Y,i}$ are called the \"brain scores\" and $L_{X,i}$ the \"design scores\", respectively, analogous to the principal component scores that can be computed in PCA. `pyplsc` also refers to $L_{Y,i}$ as the \"design scores\" but the documentation uses the non-neuroimaging specific term \"data scores\" for $L_{X,i}$.\n", "\n", "Note that significance testing (via `.permute()`) is performed on the level of pairs of latent variables. Thus, in these tutorials, we might say \"the first pair of latent variables is significant\". Note also that computing $L_{Y,i}$ is only as simple as $YU_{:,i}$ when the observations are not stratified by experimental condition.\n", "\n", "After fitting, the design scores are accessible via the `design_scores_` property, while the data scores can be computed via the `transform` method (which can also be applied to a new data array with the same number of columns as $X$):" ] }, { "cell_type": "code", "execution_count": 8, "id": "c9b46f7e-0ac5-49f8-bde0-d53f011a44ff", "metadata": {}, "outputs": [], "source": [ "design_scores = mod.design_scores_\n", "data_scores = mod.transform()" ] }, { "cell_type": "markdown", "id": "2ea5626e-e7dc-4962-88f6-4589bb9932b2", "metadata": {}, "source": [ "There are 2 pairs of latent variables, thus two columns in each matrix of scores:" ] }, { "cell_type": "code", "execution_count": 9, "id": "73de909b-ce6b-4cf6-a357-a471d8bafc2e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 9.9788525 , -1.4345408 , 0.49924011],\n", " [-7.21310205, -0.44509536, -0.96862769],\n", " [ 0.29701807, 1.01506316, 1.50570584],\n", " [13.03498637, -0.18581278, -0.88961322]])" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "design_scores" ] }, { "cell_type": "code", "execution_count": 10, "id": "0de30208-c845-483e-b732-0ac484c521e0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 12.30960766, -3.18212168, 1.03531354],\n", " [-10.78979444, 0.63602538, 0.89762489],\n", " [ -5.14284803, 2.02267003, 1.47980124],\n", " [ 15.58229709, 0.3284249 , -0.28609435]])" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data_scores" ] }, { "cell_type": "markdown", "id": "80a8fb2e-4191-48db-8b6e-30a5d6c772eb", "metadata": {}, "source": [ "We can see that the first pair of latent variables are indeed correlated with one another:" ] }, { "cell_type": "code", "execution_count": 11, "id": "fcb45612-c5ab-4edc-953a-be353a7c370c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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sgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkpVEULn33nvD7rvvHjp27BgGDRoUZs+eXegqAQAJKHhQefLJJ8NVV10VxowZE+bMmRMGDhwYhg0bFpYvX17oqgEArT2oTJw4MVx00UXh/PPPD/379w/3339/2G677cJDDz1U6KoBAK05qKxbty688sorYejQof+/Qm3a5OszZ86s8zVr164NlZWVtRYAoGUqaFD55JNPwvr160P37t1rbY/ry5Ytq/M148aNC2VlZdVLr169mqm2AECrG/rZWqNHjw4VFRXVy+LFiwtdJQCgibQLBdSlS5fQtm3b8NFHH9XaHtfLy8vrfE2HDh3yBQBo+Qrao9K+fftwwAEHhKlTp1Zv27BhQ74+ePDgQlYNAGjtPSpRnJo8YsSIcOCBB4aDDz443HXXXWH16tX5LCAAoHUreFA544wzwscffxxuuumm/AbafffdN0yePHmTG2wBgNanJMuyLBSxOD05zv6JN9aWlpYWujoAQCNev4tu1g8A0HoIKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIVkGDyu677x5KSkpqLePHjy9klQCAhLQrdAVuvvnmcNFFF1Wvd+rUqaD1gdSt35CF2Qs/C8tXrgndOnUMB/fuHNq2KSl0tQBaZlCJwaS8vLzQ1YCiMPmNpWHss2+FpRVrqrf1KOsYxgzvH47eu0dB6wbQIu9RiUM9O++8c9hvv/3C7bffHr788ssGy69duzZUVlbWWqC1hJRRj82pFVKiZRVr8u1xP0BLU9Aelcsvvzzsv//+oXPnzmHGjBlh9OjRYenSpWHixIn1vmbcuHFh7NixzVpPSGG4J/akZHXsi9viwE/c/93+5YaBgBalJMuyuj77vrLrr78+3HbbbQ2Wefvtt8Nee+21yfaHHnooXHLJJWHVqlWhQ4cO9faoxKVK7FHp1atXqKioCKWlpY1wBJCemQs+DWf9z0ubLfebi/5PGNx352apE8B/I16/y8rKNnv9bvQelauvvjqMHDmywTJ9+vSpc/ugQYPyoZ/33nsv9OvXr84yMcDUF2KgpYo3zjZmOYBi0ehBpWvXrvnyVcydOze0adMmdOvWrbGrBUUtzu5pzHIAxaJg96jMnDkzzJo1KwwZMiSf+RPXr7zyynDOOeeEnXbaqVDVgiTFKchxdk+8cbausdp4j0p52f+bqgzQkhRs1k8cvnniiSfC4YcfHgYMGBBuueWWPKg88MADhaoSJCs+JyVOQY42fmJK1Xrc73kqQEvT6DfTpnozDrQEnqMCtBQFu5kWaDrxoW5xCrIn0wKthaACRSYO75iCDLQWBX8yLQBAfQQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVAKD1BZVbbrklHHLIIWG77bYLO+64Y51lFi1aFI477ri8TLdu3cI111wTvvzyy6aqEgBQZNo11Tdet25dOO2008LgwYPDgw8+uMn+9evX5yGlvLw8zJgxIyxdujScd955YZtttgm33nprU1ULACgiJVmWZU35D0yaNClcccUVYcWKFbW2//Wvfw3HH398WLJkSejevXu+7f777w/XXXdd+Pjjj0P79u236PtXVlaGsrKyUFFREUpLS5vkGACAxrWl1++C3aMyc+bMsM8++1SHlGjYsGF5xd988816X7d27dq8TM0FAGiZChZUli1bViukRFXrcV99xo0blyewqqVXr15NXlcAoAiCyvXXXx9KSkoaXN55552mq20IYfTo0Xk3UdWyePHiJv33AIAiuZn26quvDiNHjmywTJ8+fbboe8WbaGfPnl1r20cffVS9rz4dOnTIFwCg5duqoNK1a9d8aQxxNlCcwrx8+fJ8anL03HPP5TfU9O/fv1H+DQCguDXZ9OT4jJTPPvss/xqnIs+dOzffvscee4QddtghHHXUUXkgOffcc8OECRPy+1JuuOGGcNlll+kxAQCadnpyHCJ65JFHNtn+wgsvhCOOOCL///fffz+MGjUqTJs2LWy//fZhxIgRYfz48aFduy3PT001PXn9hizMXvhZWL5yTejWqWM4uHfn0LZNSaN9fwBozSq38Prd5M9RaWpNEVQmv7E0jH32rbC0Yk31th5lHcOY4f3D0Xv3aJR/AwBas8rUn6OSqhhSRj02p1ZIiZZVrMm3x/0AQPMQVDYa7ok9KXV1MVVti/tjOQCg6QkqNcR7UjbuSakpxpO4P5YDAJqeoFJDvHG2McsBAP8dQaWGOLunMcsBAP8dQaWGOAU5zu6pbxJy3B73x3IAQNMTVGqIz0mJU5CjjcNK1Xrc73kqANA8BJWNxOek3HfO/qG8rPbwTlyP2z1HBQBawCP0i1kMI9/tX+7JtABQYIJKPeLwzuC+OzdvawAAtRj6AQCSJagAAMkSVACAZAkqAECyBBUAIFmCCgCQLEEFAEiWoAIAJEtQAQCSVfRPps2yLP9aWVlZ6KoAAFuo6rpddR1vsUFl5cqV+ddevXoVuioAwFe4jpeVldW7vyTbXJRJ3IYNG8KSJUtCp06dQklJyVdKdDHkLF68OJSWloaWpiUfX0s+tsjxFS9tV9y0X/OI8SOGlJ49e4Y2bdq03B6VeHC77LLLf/194oWuJV7sWsPxteRjixxf8dJ2xU37Nb2GelKquJkWAEiWoAIAJKvVB5UOHTqEMWPG5F9bopZ8fC352CLHV7y0XXHTfmkp+ptpAYCWq9X3qAAA6RJUAIBkCSoAQLIEFQAgWa0uqEybNi1/gm1dyz//+c96X3fEEUdsUv7SSy8NKdp99903qev48eMbfM2aNWvCZZddFnbeeeewww47hFNPPTV89NFHISXvvfdeuPDCC0Pv3r3DtttuG/r27ZvP+lm3bl2Dr0u57e699968vTp27BgGDRoUZs+e3WD5p556Kuy11155+X322Sf85S9/CSkaN25cOOigg/InRnfr1i2cdNJJ4d13323wNZMmTdqkneJxpuhnP/vZJnWN7dIS2q6uz4+4xM+HYmy3F198MQwfPjx/+mms2zPPPFNrf5xPctNNN4UePXrknytDhw4N8+bNa/T3biGO74svvgjXXXddfr5tv/32eZnzzjsvf5p7Y5/fTanVBZVDDjkkLF26tNby/e9/P7/4HXjggQ2+9qKLLqr1ugkTJoRU3XzzzbXq+qMf/ajB8ldeeWV49tln8w/T6dOn5yfyKaecElLyzjvv5H8y4Ze//GV48803w5133hnuv//+8NOf/nSzr02x7Z588slw1VVX5WFrzpw5YeDAgWHYsGFh+fLldZafMWNGOOuss/Kw9uqrr+YX/7i88cYbITXxHIoXtpdeeik899xz+QfmUUcdFVavXr3ZJ4HWbKf3338/pGrAgAG16vr3v/+93rLF1HbxF7aaxxXbLzrttNOKst3iORffWzFY1CV+Ftx99935Z8msWbPyC3p8H8Zf3hrrvVuo4/v888/z+t14443519///vf5LwwnnHBCo57fTS5r5datW5d17do1u/nmmxssd/jhh2c//vGPs2Kw2267ZXfeeecWl1+xYkW2zTbbZE899VT1trfffjtOW89mzpyZpWzChAlZ7969i7LtDj744Oyyyy6rXl+/fn3Ws2fPbNy4cXWWP/3007Pjjjuu1rZBgwZll1xySZa65cuX5+fT9OnT6y3z8MMPZ2VlZVkxGDNmTDZw4MAtLl/MbRffO3379s02bNhQ9O0Wz8Gnn366ej0eU3l5eXb77bfX+jzs0KFD9pvf/KbR3ruFOr66zJ49Oy/3/vvvZ411fje1VtejsrE//vGP4dNPPw3nn3/+Zss+/vjjoUuXLmHvvfcOo0ePztNqquJQTxzG2W+//cLtt98evvzyy3rLvvLKK/lvvLHLs0rs5tt1113DzJkzQ8oqKipC586di67t4nBV/LnX/JnHv1sV1+v7mcftNctH8be41Nuoqp2izbXVqlWrwm677Zb/sckTTzwx7zlLVRweiF3pffr0CWeffXZYtGhRvWWLte3iefrYY4+FCy64oME/+lpM7VbTwoULw7Jly2q1TfzbM3Eop762+Srv3dTeiyUlJWHHHXdstPO7qRX9HyX8bz344IP5B8bm/rDh9773vfyNGBvutddey8f9Yhda7EpLzeWXXx7233///KIQu5zjhTl23U2cOLHO8vGN2r59+01O3O7du+f7UjV//vxwzz33hDvuuKPo2u6TTz4J69evz3/GNcX1OMRVl9gWdZVPuY2iOFx3xRVXhG9961t5UKxPv379wkMPPRS++c1v5h+msV3jUG286DXGHx5tTPFCFu/NiHWO762xY8eGww47LB/KiffltJS2i/c7rFixIowcObJFtNvGqn7+W9M2X+W9m4o1a9bkn39xGLKhP+S6ted3k8taiOuuuy7vzmpoicMZNS1evDhr06ZN9rvf/W6r/72pU6fm33P+/PlZqsdX5cEHH8zatWuXrVmzps79jz/+eNa+fftNth900EHZtddem6V4bB988EHeHX3hhRcm33Z1+fDDD/M6zJgxo9b2a665Ju9Wrkscnvv1r39da9u9996bdevWLUvZpZdemg9Hxvfb1g7Lxja+4YYbstT9+9//zkpLS7Nf/epXLartjjrqqOz4449vMe228dDIP/7xj3zbkiVLapU77bTT8uG6xnrvpjD0s27dumz48OHZfvvtl1VUVDTq+d3UWkyPytVXX91g6o9iF1ZNDz/8cD48siU3FtWVOKt+q4+zT1I8vpp1jUM/cdZMTMgbKy8vz7sz429ONXtV4qyfuC+1Y4s3+g4ZMiT/re2BBx5Ivu3qEoeh2rZtu8nMqoZ+5nH71pRPwQ9/+MPwpz/9KZ+ZsLW/XW+zzTb50GVsp9TF982ee+5Zb12Lse3iDbFTpkzZ6p7HYmq3qp9/bIs466dKXN93330b7b1baF988UU4/fTT8zZ9/vnnG+xN+Srnd1NrMUGla9eu+bKlYviMQSVO1YpvrK01d+7c/GvNkzul49u4rnEMNU4TrcsBBxyQ/wymTp2aT0uO4tBIHJMcPHhwSOnYPvzwwzykxDrH9ovHlXrb1SUOtcVjiD/zOPujaogkrseLe11iW8T9cRilSpyR0RxttLXi+yvONHv66afzRwLEWXVbK3avv/766+HYY48NqYv3aCxYsCCce+65Rd92VeL7K35mHHfccS223eJ5GcNFbJuqYFJZWZnP/hk1alSjvXdTCCnz5s0LL7zwQv7LeWOf300ua6WmTJlS73BJHFbo169fNmvWrHw9DhHEWUEvv/xytnDhwuwPf/hD1qdPn+zb3/52lprYHRln/MydOzdbsGBB9thjj+Wzms4777x6j6+qe37XXXfNnn/++fw4Bw8enC8pifXeY489siOPPDL//6VLl1Yvxdh2TzzxRD67YNKkSdlbb72VXXzxxdmOO+6YLVu2LN9/7rnnZtdff32tbuo4hHfHHXfk5228Mz8OKbz++utZakaNGpXPBJk2bVqtdvr888+ry2x8fGPHjs3+9re/5eftK6+8kp155plZx44dszfffDNLzdVXX50fWzynYrsMHTo069KlSz67qdjbrmoWS/w8iMOyGyu2dlu5cmX26quv5kv8zJ84cWL+/1WzXsaPH5+/7+Jnw2uvvZadeOKJ+UzC//znP9Xf4zvf+U52zz33bPF7N5XjW7duXXbCCSdku+yyS35NqPleXLt2bb3Ht7nzu7m12qBy1llnZYccckid+2LjxAZ/4YUX8vVFixblF7bOnTvnJ2e8WMbxyK0d52sO8YMiTnuMF4n4YfGNb3wju/XWW2vdn7Lx8UXxTfmDH/wg22mnnbLtttsuO/nkk2sFgBTEaZD13cNSrG0XPxziBSHeIxTHt1966aVa06pHjBhRq/xvf/vbbM8998zLDxgwIPvzn/+cpai+doptWN/xXXHFFdU/i+7du2fHHntsNmfOnCxFZ5xxRtajR4+8rl/72tfy9Zr3PBVz20UxeMT2evfddzfZV2ztFj8L6joXq44hTlG+8cYb87rHz4j4i9DGxx3vsYrhckvfu6kc38L//Tysa6n5+b/x8W3u/G5uJfE/henLAQBoWKt/jgoAkC5BBQBIlqACACRLUAEAkiWoAADJElQAgGQJKgBAsgQVACBZggoAkCxBBQBIlqACACRLUAEAQqr+L8Dutt1qm0AmAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from matplotlib import pyplot as plt\n", "\n", "plt.scatter(design_scores[:, 0], data_scores[:, 0])" ] }, { "cell_type": "markdown", "id": "4d610bb0-9b83-43cd-96c9-0a607eecca54", "metadata": {}, "source": [ "## PLSC and BDA\n", "\n", "We can use a similar approach to the one described above to analyze condition-wise differences rather than correlations with covariates. In this case, $R$ is a matrix of stacked condition-wise averages (\"barycentres\") rather than a correlation matrix. Within `pyplsc`, this approach is referred to as \"barycentric discriminant analysis\" (BDA; [Abdi and Williams, 2018](https://doi.org/10.1007/978-1-4614-7163-9_110192-2)); it is described in detail elsewhere in the documentation.\n", "\n", "Unfortunately, here the terminology becomes even more confusing. At times, \"PLSC\" is used in a broad sense to refer to a _family_ of techniques including the method that decomposes a correlation matrix _and_ the method that decomposes stacked barycentres ([Krishnan et al., 2011](https://doi.org/10.1016/j.neuroimage.2010.07.034)). In this case, the former method is referred to as \"behaviour PLSC\" or \"seed PLSC\" depending on whether the covariates in $Y$ are behavioural or neural variables, whereas the latter method is referred to as \"mean-centred task PLSC\". At other times, however, \"PLSC\" is used in a narrow sense to refer only to the method that decomposes a correlation matrix ([Abdi & Williams, 2012](doi.org/10.1007/978-1-62703-059-5_23)). To make matters yet more confusing, the main [Matlab software](https://github.com/McIntosh-Lab/PLS) used for PLSC in neuroimaging is simply called \"PLS\" ([McIntosh & Lobaugh, 2004](https://doi.org/10.1016/j.neuroimage.2004.07.020)), which obscures differences between partial least squares correlation, partial least squares regression, and partial least squares path modeling ([Krishnan et al., 2011](https://doi.org/10.1016/j.neuroimage.2010.07.034)).\n", "\n", "Thus, there doesn't seem to be any single set of terms that simultaneously avoids being unfamiliar (in the way that \"BDA\" is not widely used), imprecise (in the way that \"PLSC\" has both a broad and a narrow sense), and potentially misleading (in the way that \"behaviour PLSC\" and \"seed PLSC\" are mathematically identical). The balance struck in `pyplsc` is as follows: for discoverability, the library is described as implementing broad-sense PLSC, which includes the technique of applying SVD to correlation matrices and the technique of applying SVD to stacked barycentres. Within `pyplsc`, the former technique is implemented in the `PLSC` class (whose name uses the narrow sense of \"PLSC\") and the latter technique is implemented in the `BDA` class (whose name is unambiguous)." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.13.2" } }, "nbformat": 4, "nbformat_minor": 5 }