1
$\begingroup$

I am running a regression with a sparse rank-deficient matrix where many columns are correlated with others. At the moment, I remove all columns with a correlation over 0.8. The matrix has 12k columns and 35k observations, and I drop about 2k columns.

For example, my text may mention cities and I have three highly correlated n-grams: "New York", "York City", and "New York City". At the moment, I am dropping all three of them and I lose one dimension in the rank of the matrix. I am looking for a package that keeps makes the matrix invertible and keeps its rank as high as possible; and whose transformation on that matrix can be applied to a single row, because I want to predict the values when a single new observation arrives.

I found the PyPi package collinearity. Converting the sparse matrix to a dense matrix is fast, but the collinearity package on it is prohibitively slow (several hours). This is probably because, from reading the description, it adds features one at a time and recomputes all correlations.

This thread links to a paper with a QR-Column Pivoting algorithm to select the most linearly independent columns. Since Singular Value Decompositions and matrix operations are optimized for sparse matrices, does a package exist that already does this conversion of a rank-deficient sparse matrix to a full-rank, invertible matrix?

$\endgroup$
6
  • 2
    $\begingroup$ Removing pairwise correlated columns is not the same as finding a full-rank matrix, because three or more columns can have low correlation but together be collinear. (Consider the dummy variable trap.) Which goal are you trying to achieve, retaining columns with low correlation or dropping columns until your matrix is a full-rank matrix? Or something else? $\endgroup$
    – Sycorax
    Commented May 19, 2023 at 18:53
  • 2
    $\begingroup$ Let me be more clear. Removing features with high correlation is, at best, only a coincidental solution to producing a full-rank matrix. At worst, it arbitrarily removes features without regard to anything you might want to learn from the model, with the kicker that it also hasn’t solved the problem of producing a full-rank matrix! In other words, this is an XY Problem. Rank-revealing factorizations like SVD or QR are examples of the tools for finding a full-rank matrix. $\endgroup$
    – Sycorax
    Commented May 21, 2023 at 16:43
  • 1
    $\begingroup$ @Sycorax Fair point. I've edited the question to remove mention of dropping columns, and I believe addresses the XY problem. What I want is to invert the matrix keeping the highest possible number of dimensions. $\endgroup$
    – emonigma
    Commented May 22, 2023 at 7:07
  • 1
    $\begingroup$ I think it still sounds like an XY problem. If your goal is to perform a regression with a rank deficient matrix you are better off using a regularised regression algorithm such as ridge regression (L2) or lasso (L1) coefficient regularisation. L2 is what I would naturally do for correlated - eg if NY city and NYC are 100% correlated then you will have 1/2 weight on each. $\endgroup$
    – seanv507
    Commented May 22, 2023 at 17:42
  • 1
    $\begingroup$ @seanv507 Yes, it was an XY problem, and running a regularised regression solved it. I added it as a comment to the accepted answer. Thanks! $\endgroup$
    – emonigma
    Commented May 25, 2023 at 8:19

2 Answers 2

6
$\begingroup$

A fast implementation suits your needs. SVD is the "gold-standard" of rank-revealing matrix factorizations (Golub & van Loan, Matrix Computations).

The first place to start is to try scipy.sparse.linalg.svds. If it's not fast enough for your needs, then you'll need to explore other packages & SVD algorithms.

Some alternative SVD algorithms are mentioned here What fast algorithms exist for computing truncated SVD? but you might have to do some digging to turn up a python implementation that suits your needs. I've read that implicitly restarted lanczos bidiagonalization methods can compute SVD for much, much larger matrices than the one you have, such as the Netflix prize dataset, but I haven't found a widely used python implementation.

Alternatively, you could simply use your rank-deficient matrix as-is and estimate a penalized regression instead. Options include , and .

$\endgroup$
1
  • 2
    $\begingroup$ Yes, a penalized regression solves my problem and I can use the rank-deficient matrix as is. The LASSO takes about 5 times as long to run compared to when I remove all columns with large pairwise correlations, but it's a good tradeoff between my development time with the machine's running time. $\endgroup$
    – emonigma
    Commented May 25, 2023 at 8:18
-3
$\begingroup$

Do you only want to remove highly correlated variables? If so, the following solution uses less than 6GB of RAM, assuming everything is float32, and runs in a few seconds. I used torch because it often seems to parallelize work better than numpy does.

The basic idea is to calculate a correlation matrix, make it upper triangular, and remove any column whose (absolute) max correlation is greater than the threshold.

import torch

COR_LIMIT = 0.8

data = torch.rand(35000, 12000)
cor = torch.corrcoef(data.T)
cor = torch.triu(cor, 1)
keep_mask = torch.abs(cor.max(dim=0).values) < COR_LIMIT
data = data[:, keep_mask]
$\endgroup$
6
  • 1
    $\begingroup$ That sounds like an extremely poor statistical procedure! Moreover, it won't necessarily solve the problem: how do you maintain the rank of the matrix? (It's possible your procedure would remove every column!) Wouldn't the OP be better off with a recommendation to do something that worked better? $\endgroup$
    – whuber
    Commented May 19, 2023 at 19:16
  • $\begingroup$ @whuber It removes correlated variables, which is exactly what I said it does. If N features are correlated with each other, it'll remove N - 1 of them. $\endgroup$
    – tkunk
    Commented May 20, 2023 at 15:22
  • 2
    $\begingroup$ As I wrote, that's a really poor procedure and it doesn't meet the requirements of the question. $\endgroup$
    – whuber
    Commented May 20, 2023 at 15:27
  • 1
    $\begingroup$ Thank you. In fact, this is the procedure I'm already using, and I am looking for a better one that keeps some of those variables. I updated the question with an explanation. $\endgroup$
    – emonigma
    Commented May 20, 2023 at 18:55
  • 3
    $\begingroup$ I am not judging your code, which I did not run, but reacting to your description, to wit: "Remove any column whose (absolute) max correlation is greater than the threshold." That implies you will drop all columns when all correlations exceed the threshold. If that's not what you are proposing, then please edit your post to clarify what you do suggest the OP do. However, as a general principle in regression, dropping columns based solely on pairwise correlations is a notably bad idea, so the details don't really matter. $\endgroup$
    – whuber
    Commented May 20, 2023 at 22:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.