Skip to content

Proposing a consistent interface for thresholding matrices #38

Closed

Description

@sdmccabe

A number of the reconstruction methods involving creating some matrix and then thresholding it in some way. For some of the techniques we've been looking at (correlation matrix based), the thresholding is basically a researcher degree of freedom. We've implemented thresholding in specific ways for each method, trying to attain some level of generality, but with only two implementations this has already led to different function signatures.

class CorrelationMatrixReconstructor(BaseReconstructor):
    def fit(self, TS, cutoffs=[(-1, 1)]):
class RegularizedCorrelationMatrixReconstructor(BaseReconstructor):
    def fit(self, TS, num_eigs=10, quantile=0.9):

In place of this, it might be more straightforward (and more flexible) to define (in a utilities subfolder, say) a set of thresholding functions, then pass these functions as arguments to the various fit methods.

For example, we might have threshold_on_quantile and threshold_in_range functions, then rewrite the above function signatures to look like:

class CorrelationMatrixReconstructor(BaseReconstructor):
    def fit(self, TS, threshold=threshold_on_quantile):
class RegularizedCorrelationMatrixReconstructor(BaseReconstructor):
    def fit(self, TS, num_eigs=10, threshold=threshold_in_range):

The threshold functions would have to have default values; if they needed to be changed one could create custom threshold functions using lambdas.

bespoke_thresholder = lambda mat: threshold_in_range(mat, range=custom_range)
class RegularizedCorrelationMatrixReconstructor(BaseReconstructor):
    def fit(self, TS, num_eigs=10, threshold=bespoke_thresholder):

Activity

  1. sdmccabe commented on Jan 18, 2019

    @sdmccabe
    CollaboratorAuthor

    (this might be related to the parameterization question raised in #36)

  2. leotrs commented on Jan 18, 2019

    @leotrs
    Collaborator

    I like the idea of unifying things like this. However, I don't think passing a function is the most elegant way of doing this. The user would need to do something like

    from netrd.utilities import threshold_in_range
    ...
    obj.fit(TS, threshold=threshold_in_range)
    

    which amounts to two lines changed, OR

    obj.fit(TS, threshold=netrd.utilities.threshold_in_range)
    

    which amounts to ugly/long lines. I propose we use strings instead:

    obj.fit(TS, threshold=`range`)
    

    In the case we need to send some parameters to the thresholding function, we can expose those too:

    ...
    obj.fit(TS, threshold=`range`, threshold_params={'param1': ...})
    
  3. sdmccabe commented on Jan 18, 2019

    @sdmccabe
    CollaboratorAuthor

    I'm going to make a utilities/ subdirectory with the thresholding functions. Do we still want one file per method, or is an omnibus utilities/threshold.py better?

  4. leotrs commented on Jan 18, 2019

    @leotrs
    Collaborator

    Put all in the same place please.

  5. assigned and unassigned on Feb 13, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions