Repository: CalculatedContent/WeightWatcher (language: python)

Issue:
Pandas issues
There are 2 pandas issues that should be fixed:

Pandas keeps track of row indices in a hidden column. This column is referred to when using `.loc[ind]` to access specific rows. When rows are created individually and then concatenated as is done in weightwatcher, they all have this index set to 0. To reset this index, the following line should be added,
```
details.reset_index(drop=True)
```
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reset_index.html


Secondly, tests are currently outputting a FutureWarning:
WeightWatcher/weightwatcher/weightwatcher.py:2232: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.

This is the line that causes the warning:
```
data = pd.DataFrame.from_records(ww_layer.get_row() , index=[0])
details = pd.concat([details,data])
```
(Note that in this case, the index is being explicitly set to [0], so one possible fix for the first issue would be to set it to something here.)

One proposed solution is mentioned here. Note that this seems to be a recent phenomenon that will only be visible in the latest version of pandas. There are a few questions / bug reports about this, but this stack overflow post is the only one with an answer that I've seen.
https://stackoverflow.com/questions/73800841/add-series-as-a-new-row-into-dataframe-triggers-futurewarning


Discussion / hints:
This appears to be a duplicate of #137 .
Actually on closer inspection, it appears that though #137 touches on the exact same 3 lines of code, it is a separate issue altogether.

Fix patch:
diff --git a/BuildWeightWatcher.ipynb b/BuildWeightWatcher.ipynb
index bd284fc..922635a 100644
--- a/BuildWeightWatcher.ipynb
+++ b/BuildWeightWatcher.ipynb
@@ -364,7 +364,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 19,
    "metadata": {
     "tags": []
    },
@@ -373,7 +373,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "2023-02-07 22:13:27.313232: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
+      "2023-02-09 11:20:15.985344: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
       "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
       "\n",
       "-------------------------------------\n",
@@ -386,8 +386,6 @@
       "torch version 1.13.1.post200\n",
       "max esd before 60.278518503997944\n",
       "max esd after 60.278518503997944\n",
-      "/darda/WeightWatcher/tests/test.py:1053: DeprecationWarning: Please use assertEqual instead.\n",
-      "  self.assertEquals(np.max(esd_before),np.max(esd_after))\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_N_ge_M\n",
@@ -415,24 +413,6 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "Index(['layer_id', 'name', 'D', 'Lambda', 'M', 'N', 'Q', 'alpha',\n",
       "       'alpha_weighted', 'best_fit', 'entropy', 'fit_entropy', 'has_esd',\n",
       "       'lambda_max', 'layer_type', 'log_alpha_norm', 'log_norm',\n",
@@ -441,7 +421,7 @@
       "       'spectral_norm', 'stable_rank', 'sv_max', 'warning', 'weak_rank_loss',\n",
       "       'xmax', 'xmin'],\n",
       "      dtype='object')\n",
-      "F\n",
+      ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_analyze_columns_with_model\n",
       "\n",
@@ -450,24 +430,6 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "Index(['layer_id', 'name', 'D', 'Lambda', 'M', 'N', 'Q', 'alpha',\n",
       "       'alpha_weighted', 'best_fit', 'entropy', 'fit_entropy', 'has_esd',\n",
       "       'lambda_max', 'layer_type', 'log_alpha_norm', 'log_norm',\n",
@@ -536,22 +498,6 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "F\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_density_fit\n",
@@ -575,8 +521,8 @@
       "       'spectral_norm', 'stable_rank', 'sv_max', 'warning', 'weak_rank_loss',\n",
       "       'xmax', 'xmin'],\n",
       "      dtype='object')\n",
-      "num spikes 0    782.0\n",
-      "Name: num_spikes, dtype: float64\n",
+      "num spikes 0    782\n",
+      "Name: num_spikes, dtype: int64\n",
       "sigma mp 0    0.689477\n",
       "Name: sigma_mp, dtype: float64\n",
       "softrank 0    0.021673\n",
@@ -590,18 +536,18 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "  layer_id    name       M  ...      longname  num_evals   rf\n",
-      "0        2  Conv2d     3.0  ...    features.0       27.0  9.0\n",
-      "0        5  Conv2d    64.0  ...    features.3      576.0  9.0\n",
-      "0        8  Conv2d   128.0  ...    features.6     1152.0  9.0\n",
-      "0       10  Conv2d   256.0  ...    features.8     2304.0  9.0\n",
-      "0       13  Conv2d   256.0  ...   features.11     2304.0  9.0\n",
-      "0       15  Conv2d   512.0  ...   features.13     4608.0  9.0\n",
-      "0       18  Conv2d   512.0  ...   features.16     4608.0  9.0\n",
-      "0       20  Conv2d   512.0  ...   features.18     4608.0  9.0\n",
-      "0       25  Linear  4096.0  ...  classifier.0     4096.0  1.0\n",
-      "0       28  Linear  4096.0  ...  classifier.3     4096.0  1.0\n",
-      "0       31  Linear  1000.0  ...  classifier.6     1000.0  1.0\n",
+      "    layer_id    name     M  ...      longname  num_evals rf\n",
+      "0          2  Conv2d     3  ...    features.0         27  9\n",
+      "1          5  Conv2d    64  ...    features.3        576  9\n",
+      "2          8  Conv2d   128  ...    features.6       1152  9\n",
+      "3         10  Conv2d   256  ...    features.8       2304  9\n",
+      "4         13  Conv2d   256  ...   features.11       2304  9\n",
+      "5         15  Conv2d   512  ...   features.13       4608  9\n",
+      "6         18  Conv2d   512  ...   features.16       4608  9\n",
+      "7         20  Conv2d   512  ...   features.18       4608  9\n",
+      "8         25  Linear  4096  ...  classifier.0       4096  1\n",
+      "9         28  Linear  4096  ...  classifier.3       4096  1\n",
+      "10        31  Linear  1000  ...  classifier.6       1000  1\n",
       "\n",
       "[11 rows x 9 columns]\n",
       ".\n",
@@ -622,7 +568,7 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "64.0 3.0 9.0 27.0\n",
+      "64 3 9 27\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_filter_conv2D_layer_types\n",
@@ -632,15 +578,15 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "  layer_id    name      M  ...     longname  num_evals   rf\n",
-      "0        2  Conv2d    3.0  ...   features.0       27.0  9.0\n",
-      "0        5  Conv2d   64.0  ...   features.3      576.0  9.0\n",
-      "0        8  Conv2d  128.0  ...   features.6     1152.0  9.0\n",
-      "0       10  Conv2d  256.0  ...   features.8     2304.0  9.0\n",
-      "0       13  Conv2d  256.0  ...  features.11     2304.0  9.0\n",
-      "0       15  Conv2d  512.0  ...  features.13     4608.0  9.0\n",
-      "0       18  Conv2d  512.0  ...  features.16     4608.0  9.0\n",
-      "0       20  Conv2d  512.0  ...  features.18     4608.0  9.0\n",
+      "   layer_id    name    M    N  ...         layer_type     longname num_evals  rf\n",
+      "0         2  Conv2d    3   64  ...  LAYER_TYPE.CONV2D   features.0        27   9\n",
+      "1         5  Conv2d   64  128  ...  LAYER_TYPE.CONV2D   features.3       576   9\n",
+      "2         8  Conv2d  128  256  ...  LAYER_TYPE.CONV2D   features.6      1152   9\n",
+      "3        10  Conv2d  256  256  ...  LAYER_TYPE.CONV2D   features.8      2304   9\n",
+      "4        13  Conv2d  256  512  ...  LAYER_TYPE.CONV2D  features.11      2304   9\n",
+      "5        15  Conv2d  512  512  ...  LAYER_TYPE.CONV2D  features.13      4608   9\n",
+      "6        18  Conv2d  512  512  ...  LAYER_TYPE.CONV2D  features.16      4608   9\n",
+      "7        20  Conv2d  512  512  ...  LAYER_TYPE.CONV2D  features.18      4608   9\n",
       "\n",
       "[8 rows x 9 columns]\n",
       ".\n",
@@ -653,10 +599,10 @@
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
       "test_filter_dense_layer_types\n",
-      "  layer_id    name       M  ...      longname  num_evals   rf\n",
-      "0       25  Linear  4096.0  ...  classifier.0     4096.0  1.0\n",
-      "0       28  Linear  4096.0  ...  classifier.3     4096.0  1.0\n",
-      "0       31  Linear  1000.0  ...  classifier.6     1000.0  1.0\n",
+      "   layer_id    name     M      N  ...        layer_type      longname num_evals  rf\n",
+      "0        25  Linear  4096  25088  ...  LAYER_TYPE.DENSE  classifier.0      4096   1\n",
+      "1        28  Linear  4096   4096  ...  LAYER_TYPE.DENSE  classifier.3      4096   1\n",
+      "2        31  Linear  1000   4096  ...  LAYER_TYPE.DENSE  classifier.6      1000   1\n",
       "\n",
       "[3 rows x 9 columns]\n",
       ".\n",
@@ -668,24 +614,24 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "  layer_id    name       M  ...      longname  num_evals   rf\n",
-      "0        2  Conv2d     3.0  ...    features.0       27.0  9.0\n",
-      "0        5  Conv2d    64.0  ...    features.3      576.0  9.0\n",
-      "0        8  Conv2d   128.0  ...    features.6     1152.0  9.0\n",
-      "0       10  Conv2d   256.0  ...    features.8     2304.0  9.0\n",
-      "0       13  Conv2d   256.0  ...   features.11     2304.0  9.0\n",
-      "0       15  Conv2d   512.0  ...   features.13     4608.0  9.0\n",
-      "0       18  Conv2d   512.0  ...   features.16     4608.0  9.0\n",
-      "0       20  Conv2d   512.0  ...   features.18     4608.0  9.0\n",
-      "0       25  Linear  4096.0  ...  classifier.0     4096.0  1.0\n",
-      "0       28  Linear  4096.0  ...  classifier.3     4096.0  1.0\n",
-      "0       31  Linear  1000.0  ...  classifier.6     1000.0  1.0\n",
+      "    layer_id    name     M  ...      longname  num_evals rf\n",
+      "0          2  Conv2d     3  ...    features.0         27  9\n",
+      "1          5  Conv2d    64  ...    features.3        576  9\n",
+      "2          8  Conv2d   128  ...    features.6       1152  9\n",
+      "3         10  Conv2d   256  ...    features.8       2304  9\n",
+      "4         13  Conv2d   256  ...   features.11       2304  9\n",
+      "5         15  Conv2d   512  ...   features.13       4608  9\n",
+      "6         18  Conv2d   512  ...   features.16       4608  9\n",
+      "7         20  Conv2d   512  ...   features.18       4608  9\n",
+      "8         25  Linear  4096  ...  classifier.0       4096  1\n",
+      "9         28  Linear  4096  ...  classifier.3       4096  1\n",
+      "10        31  Linear  1000  ...  classifier.6       1000  1\n",
       "\n",
       "[11 rows x 9 columns]\n",
-      "  layer_id    name       M  ...      longname  num_evals   rf\n",
-      "0       25  Linear  4096.0  ...  classifier.0     4096.0  1.0\n",
-      "0       28  Linear  4096.0  ...  classifier.3     4096.0  1.0\n",
-      "0       31  Linear  1000.0  ...  classifier.6     1000.0  1.0\n",
+      "   layer_id    name     M      N  ...        layer_type      longname num_evals  rf\n",
+      "0        25  Linear  4096  25088  ...  LAYER_TYPE.DENSE  classifier.0      4096   1\n",
+      "1        28  Linear  4096   4096  ...  LAYER_TYPE.DENSE  classifier.3      4096   1\n",
+      "2        31  Linear  1000   4096  ...  LAYER_TYPE.DENSE  classifier.6      1000   1\n",
       "\n",
       "[3 rows x 9 columns]\n",
       ".\n",
@@ -698,9 +644,7 @@
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
       "Calculating best minimal value for power law fit\n",
-      "/darda/WeightWatcher/tests/test.py:1294: DeprecationWarning: Please use assertAlmostEqual instead.\n",
-      "  self.assertAlmostEquals(expected, actual, None, '', 0.01)\n",
-      ".\n",
+      ".min progress: 99%\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_fix_fingers_clip_xmax\n",
       "\n",
@@ -724,7 +668,7 @@
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
       "ACTUAL 7.116214252109355\n",
-      "F\n",
+      ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_getESD\n",
       "\n",
@@ -790,7 +734,7 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "2.6665577199150805 lognormal\n",
+      "2.6573088863046284 lognormal\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_intra_power_law_fit2\n",
@@ -819,10 +763,10 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "  layer_id    name       M  ...      longname  num_evals   rf\n",
-      "0        2  Conv2d     3.0  ...    features.0       27.0  9.0\n",
-      "0        5  Conv2d    64.0  ...    features.3      576.0  9.0\n",
-      "0       31  Linear  1000.0  ...  classifier.6     1000.0  1.0\n",
+      "   layer_id    name     M     N  ...         layer_type      longname num_evals  rf\n",
+      "0         2  Conv2d     3    64  ...  LAYER_TYPE.CONV2D    features.0        27   9\n",
+      "1         5  Conv2d    64   128  ...  LAYER_TYPE.CONV2D    features.3       576   9\n",
+      "2        31  Linear  1000  4096  ...   LAYER_TYPE.DENSE  classifier.6      1000   1\n",
       "\n",
       "[3 rows x 9 columns]\n",
       ".\n",
@@ -834,17 +778,17 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "  layer_id    name       M  ...      longname  num_evals   rf\n",
-      "0        5  Conv2d    64.0  ...    features.3      576.0  9.0\n",
-      "0        8  Conv2d   128.0  ...    features.6     1152.0  9.0\n",
-      "0       10  Conv2d   256.0  ...    features.8     2304.0  9.0\n",
-      "0       13  Conv2d   256.0  ...   features.11     2304.0  9.0\n",
-      "0       15  Conv2d   512.0  ...   features.13     4608.0  9.0\n",
-      "0       18  Conv2d   512.0  ...   features.16     4608.0  9.0\n",
-      "0       20  Conv2d   512.0  ...   features.18     4608.0  9.0\n",
-      "0       25  Linear  4096.0  ...  classifier.0     4096.0  1.0\n",
-      "0       28  Linear  4096.0  ...  classifier.3     4096.0  1.0\n",
-      "0       31  Linear  1000.0  ...  classifier.6     1000.0  1.0\n",
+      "   layer_id    name     M  ...      longname  num_evals rf\n",
+      "0         5  Conv2d    64  ...    features.3        576  9\n",
+      "1         8  Conv2d   128  ...    features.6       1152  9\n",
+      "2        10  Conv2d   256  ...    features.8       2304  9\n",
+      "3        13  Conv2d   256  ...   features.11       2304  9\n",
+      "4        15  Conv2d   512  ...   features.13       4608  9\n",
+      "5        18  Conv2d   512  ...   features.16       4608  9\n",
+      "6        20  Conv2d   512  ...   features.18       4608  9\n",
+      "7        25  Linear  4096  ...  classifier.0       4096  1\n",
+      "8        28  Linear  4096  ...  classifier.3       4096  1\n",
+      "9        31  Linear  1000  ...  classifier.6       1000  1\n",
       "\n",
       "[10 rows x 9 columns]\n",
       ".\n",
@@ -873,46 +817,28 @@
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: divide by zero encountered in divide\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: divide by zero encountered in divide\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: divide by zero encountered in divide\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_negative_filter_layer_ids\n",
@@ -922,29 +848,29 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "  layer_id    name       M  ...      longname  num_evals   rf\n",
-      "0        2  Conv2d     3.0  ...    features.0       27.0  9.0\n",
-      "0        5  Conv2d    64.0  ...    features.3      576.0  9.0\n",
-      "0        8  Conv2d   128.0  ...    features.6     1152.0  9.0\n",
-      "0       10  Conv2d   256.0  ...    features.8     2304.0  9.0\n",
-      "0       13  Conv2d   256.0  ...   features.11     2304.0  9.0\n",
-      "0       15  Conv2d   512.0  ...   features.13     4608.0  9.0\n",
-      "0       18  Conv2d   512.0  ...   features.16     4608.0  9.0\n",
-      "0       20  Conv2d   512.0  ...   features.18     4608.0  9.0\n",
-      "0       25  Linear  4096.0  ...  classifier.0     4096.0  1.0\n",
-      "0       28  Linear  4096.0  ...  classifier.3     4096.0  1.0\n",
-      "0       31  Linear  1000.0  ...  classifier.6     1000.0  1.0\n",
+      "    layer_id    name     M  ...      longname  num_evals rf\n",
+      "0          2  Conv2d     3  ...    features.0         27  9\n",
+      "1          5  Conv2d    64  ...    features.3        576  9\n",
+      "2          8  Conv2d   128  ...    features.6       1152  9\n",
+      "3         10  Conv2d   256  ...    features.8       2304  9\n",
+      "4         13  Conv2d   256  ...   features.11       2304  9\n",
+      "5         15  Conv2d   512  ...   features.13       4608  9\n",
+      "6         18  Conv2d   512  ...   features.16       4608  9\n",
+      "7         20  Conv2d   512  ...   features.18       4608  9\n",
+      "8         25  Linear  4096  ...  classifier.0       4096  1\n",
+      "9         28  Linear  4096  ...  classifier.3       4096  1\n",
+      "10        31  Linear  1000  ...  classifier.6       1000  1\n",
       "\n",
       "[11 rows x 9 columns]\n",
-      "  layer_id    name      M  ...     longname  num_evals   rf\n",
-      "0        2  Conv2d    3.0  ...   features.0       27.0  9.0\n",
-      "0        5  Conv2d   64.0  ...   features.3      576.0  9.0\n",
-      "0        8  Conv2d  128.0  ...   features.6     1152.0  9.0\n",
-      "0       10  Conv2d  256.0  ...   features.8     2304.0  9.0\n",
-      "0       13  Conv2d  256.0  ...  features.11     2304.0  9.0\n",
-      "0       15  Conv2d  512.0  ...  features.13     4608.0  9.0\n",
-      "0       18  Conv2d  512.0  ...  features.16     4608.0  9.0\n",
-      "0       20  Conv2d  512.0  ...  features.18     4608.0  9.0\n",
+      "   layer_id    name    M    N  ...         layer_type     longname num_evals  rf\n",
+      "0         2  Conv2d    3   64  ...  LAYER_TYPE.CONV2D   features.0        27   9\n",
+      "1         5  Conv2d   64  128  ...  LAYER_TYPE.CONV2D   features.3       576   9\n",
+      "2         8  Conv2d  128  256  ...  LAYER_TYPE.CONV2D   features.6      1152   9\n",
+      "3        10  Conv2d  256  256  ...  LAYER_TYPE.CONV2D   features.8      2304   9\n",
+      "4        13  Conv2d  256  512  ...  LAYER_TYPE.CONV2D  features.11      2304   9\n",
+      "5        15  Conv2d  512  512  ...  LAYER_TYPE.CONV2D  features.13      4608   9\n",
+      "6        18  Conv2d  512  512  ...  LAYER_TYPE.CONV2D  features.16      4608   9\n",
+      "7        20  Conv2d  512  512  ...  LAYER_TYPE.CONV2D  features.18      4608   9\n",
       "\n",
       "[8 rows x 9 columns]\n",
       ".\n",
@@ -1030,14 +956,10 @@
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: divide by zero encountered in divide\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
@@ -1046,26 +968,18 @@
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: divide by zero encountered in divide\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
@@ -1074,14 +988,10 @@
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: divide by zero encountered in divide\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
@@ -1090,8 +1000,6 @@
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_rescale_eigenvalues\n",
@@ -1101,8 +1009,6 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "/darda/WeightWatcher/tests/test.py:1241: DeprecationWarning: Please use assertAlmostEqual instead.\n",
-      "  self.assertAlmostEquals(actual, expected)\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_reset_params\n",
@@ -1130,7 +1036,7 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "/darda/WeightWatcher/tests/test.py:1083: RuntimeWarning: invalid value encountered in sqrt\n",
+      "/darda/WeightWatcher/tests/test.py:1040: RuntimeWarning: invalid value encountered in sqrt\n",
       "  print(\"test runtime warning: sqrt(-1)=\", np.sqrt(-1.0))\n",
       "test runtime warning: sqrt(-1)= nan\n",
       ".\n",
@@ -1151,18 +1057,18 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "  layer_id    name       M  ...      longname  num_evals   rf\n",
-      "0        2  Conv2d     3.0  ...    features.0       27.0  9.0\n",
-      "0        5  Conv2d    64.0  ...    features.3      576.0  9.0\n",
-      "0        8  Conv2d   128.0  ...    features.6     1152.0  9.0\n",
-      "0       10  Conv2d   256.0  ...    features.8     2304.0  9.0\n",
-      "0       13  Conv2d   256.0  ...   features.11     2304.0  9.0\n",
-      "0       15  Conv2d   512.0  ...   features.13     4608.0  9.0\n",
-      "0       18  Conv2d   512.0  ...   features.16     4608.0  9.0\n",
-      "0       20  Conv2d   512.0  ...   features.18     4608.0  9.0\n",
-      "0       25  Linear  4096.0  ...  classifier.0     4096.0  1.0\n",
-      "0       28  Linear  4096.0  ...  classifier.3     4096.0  1.0\n",
-      "0       31  Linear  1000.0  ...  classifier.6     1000.0  1.0\n",
+      "    layer_id    name     M  ...      longname  num_evals rf\n",
+      "0          2  Conv2d     3  ...    features.0         27  9\n",
+      "1          5  Conv2d    64  ...    features.3        576  9\n",
+      "2          8  Conv2d   128  ...    features.6       1152  9\n",
+      "3         10  Conv2d   256  ...    features.8       2304  9\n",
+      "4         13  Conv2d   256  ...   features.11       2304  9\n",
+      "5         15  Conv2d   512  ...   features.13       4608  9\n",
+      "6         18  Conv2d   512  ...   features.16       4608  9\n",
+      "7         20  Conv2d   512  ...   features.18       4608  9\n",
+      "8         25  Linear  4096  ...  classifier.0       4096  1\n",
+      "9         28  Linear  4096  ...  classifier.3       4096  1\n",
+      "10        31  Linear  1000  ...  classifier.6       1000  1\n",
       "\n",
       "[11 rows x 9 columns] 11\n",
       "1 3\n",
@@ -1287,21 +1193,6 @@
       "torch version 1.13.1.post200\n",
       ".\n",
       "-------------------------------------\n",
-      "In Test_VGG11: test_truncated_power_law_fit\n",
-      "\n",
-      "\n",
-      "python      version 3.9.12 | packaged by conda-forge | (main, Mar 24 2022, 23:22:55) \n",
-      "[GCC 10.3.0]\n",
-      "numpy       version 1.23.5\n",
-      "torch version 1.13.1.post200\n",
-      "\n",
-      "\n",
-      "python      version 3.9.12 | packaged by conda-forge | (main, Mar 24 2022, 23:22:55) \n",
-      "[GCC 10.3.0]\n",
-      "numpy       version 1.23.5\n",
-      "torch version 1.13.1.post200\n",
-      "F\n",
-      "-------------------------------------\n",
       "In Test_VGG11: test_ww_maxdist\n",
       "\n",
       "\n",
@@ -1311,8 +1202,8 @@
       "torch version 1.13.1.post200\n",
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:148: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (np.pi * sigma * sigma)) * np.sqrt(4 - x ** 2)\n",
-      "  layer_id    name         D  ...  ww_softrank      xmax      xmin\n",
-      "0       28  Linear  0.031031  ...     0.336356  60.29372  0.340533\n",
+      "   layer_id    name         D  ...  ww_softrank      xmax      xmin\n",
+      "0        28  Linear  0.031031  ...     0.336002  60.29372  0.340533\n",
       "\n",
       "[1 rows x 44 columns]\n",
       ".\n",
@@ -1333,7 +1224,7 @@
       "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
       "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
       "   ww_softrank  mp_softrank  lambda_max  rand_bulk_max  max_rand_eval\n",
-      "0     0.058112     0.024624   58.785088       3.442841        3.40814\n",
+      "0     0.057705     0.024624   58.785088       3.440293       3.403632\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_ww_stacked_layer_details\n",
@@ -1383,24 +1274,6 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_raw_distances\n",
@@ -1410,24 +1283,6 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11: test_raw_distances_w_one_layer\n",
@@ -1446,45 +1301,9 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:1570: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  distances = pd.concat([distances, data_df])\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11_noModel: test_analyze_columns_no_model\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
       "Index(['layer_id', 'name', 'D', 'Lambda', 'M', 'N', 'Q', 'alpha',\n",
       "       'alpha_weighted', 'best_fit', 'entropy', 'fit_entropy', 'has_esd',\n",
       "       'lambda_max', 'layer_type', 'log_alpha_norm', 'log_norm',\n",
@@ -1506,7 +1325,7 @@
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11_noModel: test_intra_power_law_fit_no_model\n",
-      "2.6671415251237764 lognormal\n",
+      "2.660544613721005 lognormal\n",
       ".\n",
       "-------------------------------------\n",
       "In Test_VGG11_noModel: test_permute_W_no_model\n",
@@ -1531,7 +1350,7 @@
       "Test that the distance method works correctly for CKA method,  ww2x False | True\n",
       "----------------------------------------------------------------------\n",
       "Traceback (most recent call last):\n",
-      "  File \"/darda/WeightWatcher/tests/test.py\", line 283, in test_CKA_distances_TODO\n",
+      "  File \"/darda/WeightWatcher/tests/test.py\", line 259, in test_CKA_distances_TODO\n",
       "    avg_dist, distances = self.watcher.distances(m1, m2, method=CKA)\n",
       "  File \"/darda/WeightWatcher/weightwatcher/weightwatcher.py\", line 1505, in distances\n",
       "    raise Exception(msg)\n",
@@ -1543,7 +1362,7 @@
       "Test that the distance method works correctly for EUCLIDEAN method,  ww2x=False | True\n",
       "----------------------------------------------------------------------\n",
       "Traceback (most recent call last):\n",
-      "  File \"/darda/WeightWatcher/tests/test.py\", line 299, in test_EUCLIDEAN_distances_TODO\n",
+      "  File \"/darda/WeightWatcher/tests/test.py\", line 275, in test_EUCLIDEAN_distances_TODO\n",
       "    avg_dist, distances = self.watcher.distances(m1, m2, method=EUCLIDEAN)\n",
       "  File \"/darda/WeightWatcher/weightwatcher/weightwatcher.py\", line 1505, in distances\n",
       "    raise Exception(msg)\n",
@@ -1551,52 +1370,18 @@
       " euclidean\n",
       "\n",
       "======================================================================\n",
-      "FAIL: test_analyze_columns (tests.test.Test_VGG11)\n",
-      "Test that new results are returns a valid pandas dataframe\n",
-      "----------------------------------------------------------------------\n",
-      "Traceback (most recent call last):\n",
-      "  File \"/darda/WeightWatcher/tests/test.py\", line 410, in test_analyze_columns\n",
-      "    self.assertTrue(key in details.columns, \"{} in details. Columns are {}\".format(key, details.columns))\n",
-      "AssertionError: False is not true :  fit_entropy in details. Columns are Index(['layer_id', 'name', 'D', 'Lambda', 'M', 'N', 'Q', 'alpha',\n",
-      "       'alpha_weighted', 'best_fit', 'entropy', 'fit_entropy', 'has_esd',\n",
-      "       'lambda_max', 'layer_type', 'log_alpha_norm', 'log_norm',\n",
-      "       'log_spectral_norm', 'longname', 'matrix_rank', 'norm', 'num_evals',\n",
-      "       'num_fingers', 'num_pl_spikes', 'rank_loss', 'rf', 'sigma',\n",
-      "       'spectral_norm', 'stable_rank', 'sv_max', 'warning', 'weak_rank_loss',\n",
-      "       'xmax', 'xmin'],\n",
-      "      dtype='object')\n",
-      "\n",
-      "======================================================================\n",
       "FAIL: test_compute_alphas (tests.test.Test_VGG11)\n",
       "Test that alphas are computed and values are within thresholds\n",
       "----------------------------------------------------------------------\n",
       "Traceback (most recent call last):\n",
-      "  File \"/darda/WeightWatcher/tests/test.py\", line 659, in test_compute_alphas\n",
+      "  File \"/darda/WeightWatcher/tests/test.py\", line 614, in test_compute_alphas\n",
       "    self.assertAlmostEqual(a[0],20.2149, places=4)\n",
       "AssertionError: 20.215107 != 20.2149 within 4 places (0.00020696411132803405 difference)\n",
       "\n",
-      "======================================================================\n",
-      "FAIL: test_fix_fingers_xmin_peak (tests.test.Test_VGG11)\n",
-      "Test fix fingers xmin_peak\n",
-      "----------------------------------------------------------------------\n",
-      "Traceback (most recent call last):\n",
-      "  File \"/darda/WeightWatcher/tests/test.py\", line 886, in test_fix_fingers_xmin_peak\n",
-      "    self.assertAlmostEqual(actual,expected, places=4)\n",
-      "AssertionError: 7.116214252109355 != 7.116304 within 4 places (8.974789064541966e-05 difference)\n",
-      "\n",
-      "======================================================================\n",
-      "FAIL: test_truncated_power_law_fit (tests.test.Test_VGG11)\n",
-      "Test TPL fits\n",
-      "----------------------------------------------------------------------\n",
-      "Traceback (most recent call last):\n",
-      "  File \"/darda/WeightWatcher/tests/test.py\", line 856, in test_truncated_power_law_fit\n",
-      "    self.assertAlmostEqual(actual_alpha,expected_alpha, places=2)\n",
-      "AssertionError: 2.097491293770757 != 2.1075 within 2 places (0.010008706229243103 difference)\n",
-      "\n",
       "----------------------------------------------------------------------\n",
-      "Ran 75 tests in 5055.161s\n",
+      "Ran 74 tests in 1926.020s\n",
       "\n",
-      "FAILED (failures=4, errors=2)\n"
+      "FAILED (failures=1, errors=2)\n"
      ]
     }
    ],
@@ -1606,7 +1391,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 20,
    "metadata": {
     "tags": []
    },
@@ -1615,7 +1400,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "2023-02-07 22:02:58.149474: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
+      "2023-02-09 12:15:00.862518: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
       "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
       "\n",
       "\n",
@@ -1631,7 +1416,7 @@
       "torch version 1.13.1.post200\n",
       ".\n",
       "----------------------------------------------------------------------\n",
-      "Ran 2 tests in 0.909s\n",
+      "Ran 2 tests in 0.940s\n",
       "\n",
       "OK\n"
      ]
@@ -1643,7 +1428,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 21,
    "metadata": {
     "tags": []
    },
@@ -1652,7 +1437,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "2023-02-07 22:03:03.729246: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
+      "2023-02-09 12:15:06.302648: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
       "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
       "\n",
       "-------------------------------------\n",
@@ -1671,7 +1456,7 @@
       "In Test_ResNet: test_vector_entropy\n",
       ".\n",
       "----------------------------------------------------------------------\n",
-      "Ran 5 tests in 0.954s\n",
+      "Ran 5 tests in 0.965s\n",
       "\n",
       "OK\n"
      ]
@@ -1683,7 +1468,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 22,
    "metadata": {
     "colab": {
      "background_save": true
@@ -1696,7 +1481,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "2023-02-07 22:03:21.493730: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
+      "2023-02-09 12:15:11.792513: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
       "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
       "\n",
       "-------------------------------------\n",
@@ -1715,8 +1500,6 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "v=  [0 1 2 3 4]\n",
-      "/darda/WeightWatcher/tests/test.py:1551: DeprecationWarning: Please use assertEqual instead.\n",
-      "  self.assertEquals(1, num+1)\n",
       "v=  [0 1 2 3 4]\n",
       "v=  [0 1 2 3 4]\n",
       "v=  [0 1 2 3 4]\n",
@@ -1730,7 +1513,7 @@
       "python      version 3.9.12 | packaged by conda-forge | (main, Mar 24 2022, 23:22:55) \n",
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2007: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.\n",
+      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2011: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.\n",
       "  df.loc[iv] = None\n",
       "   length   entropy  ...  participation_ratio  discete_entropy\n",
       "0     5.0  0.025796  ...             1.262728         1.609438\n",
@@ -1738,7 +1521,7 @@
       "[1 rows x 6 columns]\n",
       ".\n",
       "----------------------------------------------------------------------\n",
-      "Ran 3 tests in 0.015s\n",
+      "Ran 3 tests in 0.661s\n",
       "\n",
       "OK\n"
      ]
@@ -1750,7 +1533,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": 23,
    "metadata": {
     "tags": []
    },
@@ -1759,7 +1542,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "2023-02-07 23:41:23.067913: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
+      "2023-02-09 12:15:17.240115: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
       "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
       "\n",
       "-------------------------------------\n",
@@ -1770,19 +1553,11 @@
       "[GCC 10.3.0]\n",
       "numpy       version 1.23.5\n",
       "torch version 1.13.1.post200\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "PyTorch (fast): 64.83086133003235s\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "/darda/WeightWatcher/weightwatcher/weightwatcher.py:2288: FutureWarning: In a future version, object-dtype columns with all-bool values will not be included in reductions with bool_only=True. Explicitly cast to bool dtype instead.\n",
-      "  details = pd.concat([details,data])\n",
-      "SciPy (accurate): 92.52676177024841s\n",
+      "PyTorch (fast): 64.84156966209412s\n",
+      "SciPy (accurate): 93.38426685333252s\n",
       ".\n",
       "----------------------------------------------------------------------\n",
-      "Ran 1 test in 159.117s\n",
+      "Ran 1 test in 160.054s\n",
       "\n",
       "OK\n"
      ]
@@ -1792,6 +1567,84 @@
     "!python -m unittest -k TestPyTorchSVD"
    ]
   },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "2023-02-09 12:18:02.205981: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  SSE4.1 SSE4.2 AVX AVX2 FMA\n",
+      "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
+      "\n",
+      "-------------------------------------\n",
+      "In TestPandas: test_column_names_analyze\n",
+      "\n",
+      "\n",
+      "python      version 3.9.12 | packaged by conda-forge | (main, Mar 24 2022, 23:22:55) \n",
+      "[GCC 10.3.0]\n",
+      "numpy       version 1.23.5\n",
+      "torch version 1.13.1.post200\n",
+      ".\n",
+      "-------------------------------------\n",
+      "In TestPandas: test_column_names_analyze_intra\n",
+      "\n",
+      "\n",
+      "python      version 3.9.12 | packaged by conda-forge | (main, Mar 24 2022, 23:22:55) \n",
+      "[GCC 10.3.0]\n",
+      "numpy       version 1.23.5\n",
+      "torch version 1.13.1.post200\n",
+      ".\n",
+      "-------------------------------------\n",
+      "In TestPandas: test_column_names_analyze_mp_fit\n",
+      "\n",
+      "\n",
+      "python      version 3.9.12 | packaged by conda-forge | (main, Mar 24 2022, 23:22:55) \n",
+      "[GCC 10.3.0]\n",
+      "numpy       version 1.23.5\n",
+      "torch version 1.13.1.post200\n",
+      "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: divide by zero encountered in divide\n",
+      "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
+      "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
+      "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
+      ".\n",
+      "-------------------------------------\n",
+      "In TestPandas: test_column_names_analyze_randomize\n",
+      "\n",
+      "\n",
+      "python      version 3.9.12 | packaged by conda-forge | (main, Mar 24 2022, 23:22:55) \n",
+      "[GCC 10.3.0]\n",
+      "numpy       version 1.23.5\n",
+      "torch version 1.13.1.post200\n",
+      "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: divide by zero encountered in divide\n",
+      "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
+      "/darda/WeightWatcher/weightwatcher/RMT_Util.py:139: RuntimeWarning: invalid value encountered in sqrt\n",
+      "  return x, (1 / (2 * np.pi * sigma * sigma * x * y)) * np.sqrt((b - x) * (x - a))\n",
+      ".\n",
+      "-------------------------------------\n",
+      "In TestPandas: test_column_names_describe_basic\n",
+      "\n",
+      "\n",
+      "python      version 3.9.12 | packaged by conda-forge | (main, Mar 24 2022, 23:22:55) \n",
+      "[GCC 10.3.0]\n",
+      "numpy       version 1.23.5\n",
+      "torch version 1.13.1.post200\n",
+      ".\n",
+      "----------------------------------------------------------------------\n",
+      "Ran 5 tests in 12.437s\n",
+      "\n",
+      "OK\n"
+     ]
+    }
+   ],
+   "source": [
+    "!python -m unittest -k TestPandas"
+   ]
+  },
   {
    "cell_type": "markdown",
    "metadata": {
diff --git a/weightwatcher/weightwatcher.py b/weightwatcher/weightwatcher.py
index 7535fc3..7a4133a 100644
--- a/weightwatcher/weightwatcher.py
+++ b/weightwatcher/weightwatcher.py
@@ -1513,7 +1513,7 @@ def distances(self, model_1, model_2,
         if not same:
             raise Exception("Sorry, models are from different frameworks")
         
-        distances = pd.DataFrame(columns=['layer_id', 'name', 'delta_Wb', 'method', 'combine_Wb', 'M', 'N', 'b_shape'])
+        distances = pd.DataFrame()
         data = {}
         ilayer = 0
         try:      
@@ -1567,7 +1567,7 @@ def distances(self, model_1, model_2,
                     logger.fatal(f"unknown distance method {method}")
 
                 data_df = pd.DataFrame.from_records(data, index=[ilayer])
-                distances = pd.concat([distances, data_df])
+                distances = pd.concat([distances, data_df], ignore_index=True)
                 ilayer += 1
 
         except:
@@ -1575,7 +1575,11 @@ def distances(self, model_1, model_2,
             logger.error("Sorry, problem comparing models")
             logger.error(msg)
             raise Exception("Sorry, problem comparing models: "+msg)
-        
+
+        # Reorder the columns so that layer_id and name come first.
+        lead_cols = ['layer_id', 'name', 'delta_Wb', 'method', 'combine_Wb', 'M', 'N', 'b_shape']
+        distances = distances[lead_cols + [c for c in distances.columns if not c in lead_cols]]
+
         distances.set_index('layer_id', inplace=True)
         avg_dWb = np.mean(distances['delta_Wb'].to_numpy())
         return avg_dWb, distances
@@ -2238,8 +2242,8 @@ def analyze(self, model=None, layers=[],
         
         layer_iterator = self.make_layer_iterator(model=self.model, layers=layers, params=params)     
         
-        details = pd.DataFrame(columns=['layer_id', 'name'])
-        
+        details = pd.DataFrame(columns=[])
+
         for ww_layer in layer_iterator:
             if not ww_layer.skipped and ww_layer.has_weights:
                 logger.debug("LAYER: {} {}  : {}".format(ww_layer.layer_id, ww_layer.the_type, type(ww_layer.layer)))
@@ -2285,7 +2289,11 @@ def analyze(self, model=None, layers=[],
                 # issue 137
                 # details = details.append(ww_layer.get_row(), ignore_index=True)
                 data = pd.DataFrame.from_records(ww_layer.get_row() , index=[0])
-                details = pd.concat([details,data])
+                details = pd.concat([details,data], ignore_index=True)
+
+        # Reorder the columns so that layer_id and name come first.
+        lead_cols = ["layer_id", "name"]
+        details = details[lead_cols + [c for c in details.columns if not c in lead_cols]]
 
         self.details = details
         return details
@@ -2375,7 +2383,7 @@ def describe(self, model=None, layers=[], min_evals=0, max_evals=None,
         params = self.normalize_params(params)
 
         layer_iterator = self.make_layer_iterator(model=self.model, layers=layers, params=params)            
-        details = pd.DataFrame(columns=['layer_id', 'name'])
+        details = pd.DataFrame(columns=[])
            
         num_all_evals = 0
         for ww_layer in layer_iterator:
@@ -2395,8 +2403,11 @@ def describe(self, model=None, layers=[], min_evals=0, max_evals=None,
                 # issue 137
                 #details = details.append(ww_layer.get_row(), ignore_index=True)
                 data = pd.DataFrame.from_records(ww_layer.get_row() , index=[0])
-                details = pd.concat([details,data])
+                details = pd.concat([details,data], ignore_index=True)
 
+        # Reorder the columns so that layer_id and name come first.
+        lead_cols = ["layer_id", "name"]
+        details = details[lead_cols + [c for c in details.columns if not c in lead_cols]]
         return details
 
     def valid_params(self, params):


Test patch:
diff --git a/tests/test.py b/tests/test.py
index b03f7f6..f6c3e87 100644
--- a/tests/test.py
+++ b/tests/test.py
@@ -287,12 +287,6 @@ def test_EUCLIDEAN_distances_TODO(self):
 #  https://kapeli.com/cheat_sheets/Python_unittest_Assertions.docset/Contents/Resources/Documents/index
 
 class Test_VGG11(Test_Base):
-
-	@classmethod
-	def setUpClass(cls):
-		"""I run only once for this class
-		"""
-	
 	def setUp(self):
 		"""I run before every test in this class
 		"""
@@ -1265,11 +1259,6 @@ def test_same_models(self):
 
 
 class Test_Keras(Test_Base):
-	@classmethod
-	def setUpClass(cls):
-		"""I run only once for this class
-		"""
-		
 	def setUp(self):
 		"""I run before every test in this class
 		"""
@@ -1329,17 +1318,12 @@ def test_N_ge_M(self):
 
 
 class Test_ResNet(Test_Base):
-	@classmethod
-	def setUpClass(cls):
-		"""I run only once for this class
-		"""
-		
 	def setUp(self):
 		"""I run before every test in this class
 		"""
 		self.model = models.resnet18()#weights='ResNet18_Weights.IMAGENET1K_V1')
 		self.watcher = ww.WeightWatcher(model=self.model, log_level=logging.WARNING)
-		
+
 		
 	def test_N_ge_M(self):
 		"""Test that the Keras on VGG11 M,N set properly on Conv2D layers
@@ -1360,11 +1344,6 @@ def test_num_evals(self):
 	
 
 class Test_RMT_Util(Test_Base):
-	@classmethod
-	def setUpClass(cls):
-		"""I run only once for this class
-		"""
-		
 	def setUp(self):
 		"""I run before every test in this class
 		"""
@@ -1426,11 +1405,6 @@ def test_line_entropy(self):
 
 
 class Test_Vector_Metrics(Test_Base):
-	@classmethod
-	def setUpClass(cls):
-		"""I run only once for this class
-		"""
-		
 	def setUp(self):
 		"""I run before every test in this class
 		"""
@@ -1494,11 +1468,6 @@ class Test_Distances(Test_Base):
 	"""If we ever implement the idea of combining the biases into,  W+b_>W', then this class will 
 		contain the unit tests for this.  
 	"""
-	@classmethod
-	def setUpClass(cls):
-		"""I run only once for this class
-		"""
-		
 	def setUp(self):
 		"""I run before every test in this class
 		"""
@@ -1590,16 +1559,11 @@ class TestPyTorchSVD(Test_Base):
 	Tests for discrepancies between the scipy and torch implementations of SVD.
 	"""
 
-	@classmethod
-	def setUpClass(cls):
-		"""I run only once for this class
-		"""
-
 	def setUp(self):
 		"""I run before every test in this class
 		"""
 		print("\n-------------------------------------\nIn TestPyTorchSVD:", self._testMethodName)
-		
+
 
 	def test_torch_svd(self):
 		if RMT_Util._svd_full_fast is RMT_Util._svd_full_accurate:
@@ -1624,6 +1588,81 @@ def test_torch_svd(self):
 			self.assertLess(np.max(np.abs(details_fast.alpha - details_accurate.alpha)), 0.02)
 
 
-	
+class TestPandas(Test_Base):
+	def setUp(self):
+		"""I run before every test in this class
+		"""
+		print("\n-------------------------------------\nIn TestPandas:", self._testMethodName)
+		self.model = models.resnet18()
+		self.watcher = ww.WeightWatcher(model=self.model, log_level=logging.WARNING)
+
+	def test_column_names_describe_basic(self):
+		expected_columns = ['layer_id', 'name', 'M', 'N', 'Q', 'layer_type', 'longname',
+							'num_evals', 'rf']
+
+		details = self.watcher.describe(layers=[67])
+		self.assertTrue(isinstance(details, pd.DataFrame), "details is a pandas DataFrame")
+		self.assertEqual(len(expected_columns), len(details.columns))
+		self.assertEqual(expected_columns, list(details.columns))
+
+	def test_column_names_analyze(self):
+		expected_columns = ['layer_id', 'name', 'D', 'Lambda', 'M', 'N', 'Q', 'alpha',
+							'alpha_weighted', 'best_fit', 'entropy', 'fit_entropy', 'has_esd',
+							'lambda_max', 'layer_type', 'log_alpha_norm', 'log_norm',
+							'log_spectral_norm', 'longname', 'matrix_rank', 'norm', 'num_evals',
+							'num_fingers', 'num_pl_spikes', 'rank_loss', 'rf', 'sigma',
+							'spectral_norm', 'stable_rank', 'sv_max', 'warning', 'weak_rank_loss',
+							'xmax', 'xmin']
+
+		details = self.watcher.analyze(layers=[67])
+		self.assertTrue(isinstance(details, pd.DataFrame), "details is a pandas DataFrame")
+		self.assertEqual(len(expected_columns), len(details.columns))
+		self.assertEqual(expected_columns, list(details.columns))
+
+	def test_column_names_analyze_randomize(self):
+		expected_columns = ['layer_id', 'name', 'D', 'Lambda', 'M', 'N', 'Q', 'alpha',
+ 					        'alpha_weighted', 'best_fit', 'entropy', 'fit_entropy', 'has_esd',
+					        'lambda_max', 'layer_type', 'log_alpha_norm', 'log_norm',
+					        'log_spectral_norm', 'longname', 'matrix_rank', 'max_rand_eval', 'norm',
+					        'num_evals', 'num_fingers', 'num_pl_spikes', 'rand_W_scale',
+					        'rand_bulk_max', 'rand_bulk_min', 'rand_distance', 'rand_mp_softrank',
+					        'rand_num_spikes', 'rand_sigma_mp', 'rank_loss', 'rf', 'sigma',
+					        'spectral_norm', 'stable_rank', 'sv_max', 'warning', 'weak_rank_loss',
+					        'ww_maxdist', 'ww_softrank', 'xmax', 'xmin']
+
+		details = self.watcher.analyze(layers=[67], randomize=True)
+		self.assertTrue(isinstance(details, pd.DataFrame), "details is a pandas DataFrame")
+		self.assertEqual(len(expected_columns), len(details.columns))
+		self.assertEqual(expected_columns, list(details.columns))
+
+	def test_column_names_analyze_intra(self):
+		expected_columns = ['layer_id', 'name', 'D', 'Lambda', 'M', 'N', 'Q', 'Xflag', 'alpha',
+					        'alpha_weighted', 'best_fit', 'entropy', 'fit_entropy', 'has_esd',
+					        'lambda_max', 'layer_type', 'log_alpha_norm', 'log_norm',
+					        'log_spectral_norm', 'longname', 'matrix_rank', 'norm', 'num_evals',
+					        'num_fingers', 'num_pl_spikes', 'rank_loss', 'rf', 'sigma',
+					        'spectral_norm', 'stable_rank', 'sv_max', 'warning', 'weak_rank_loss',
+					        'xmax', 'xmin']
+
+		details = self.watcher.analyze(layers=[64, 67], intra=True)
+		self.assertTrue(isinstance(details, pd.DataFrame), "details is a pandas DataFrame")
+		self.assertEqual(len(expected_columns), len(details.columns))
+		self.assertEqual(expected_columns, list(details.columns))
+
+	def test_column_names_analyze_mp_fit(self):
+		expected_columns = ['layer_id', 'name', 'D', 'Lambda', 'M', 'N', 'Q', 'W_scale', 'alpha',
+							'alpha_weighted', 'best_fit', 'bulk_max', 'bulk_min', 'entropy',
+							'fit_entropy', 'has_esd', 'lambda_max', 'layer_type', 'log_alpha_norm',
+							'log_norm', 'log_spectral_norm', 'longname', 'matrix_rank',
+							'mp_softrank', 'norm', 'num_evals', 'num_fingers', 'num_pl_spikes',
+							'num_spikes', 'rank_loss', 'rf', 'sigma', 'sigma_mp', 'spectral_norm',
+							'stable_rank', 'sv_max', 'warning', 'weak_rank_loss', 'xmax', 'xmin']
+
+		details = self.watcher.analyze(layers=[67], mp_fit=True)
+		self.assertTrue(isinstance(details, pd.DataFrame), "details is a pandas DataFrame")
+		self.assertEqual(len(expected_columns), len(details.columns))
+		self.assertEqual(expected_columns, list(details.columns))
+
+
 if __name__ == '__main__':
 	unittest.main()