class_docstr: Conducts NMF and holds the models and components 
class_docstr_tok: ["Conducts","NMF","and","holds","the","models","and","components"]
docstr: Receives a neuron activations tensor from OutputSeq and decomposes it using NMF into the number
  of components specified by `n_components`. For example, a model like `distilgpt2` has 18,000+
  neurons. Using NMF to reduce them to 32 components can reveal interesting underlying firing
  patterns.
  
  Args:
      activations: Activations tensor. Dimensions: (batch, layer, neuron, position)
      n_input_tokens: Number of input tokens.
      token_ids: List of tokens ids.
      _path: Disk path to find javascript that create interactive explorables
      n_components: Number of components/factors to reduce the neuron factors to.
      tokens: The text of each token.
      collect_activations_layer_nums: The list of layer ids whose activtions were collected. If
      None, then all layers were collected.
      
docstr_tok: ["Receives","a","neuron","activations","tensor","from","OutputSeq","and","decomposes","it","using","NMF","into","the","number","of","components","specified","by","`","n_components","`",".","For","example",",","a","model","like","`","distilgpt2","`","has","18,000+","neurons",".","Using","NMF","to","reduce","them","to","32","components","can","reveal","interesting","underlying","firing","patterns",".","Args",":","activations",":","Activations","tensor",".","Dimensions",":","(","batch",",","layer",",","neuron",",","position",")","n_input_tokens",":","Number","of","input","tokens",".","token_ids",":","List","of","tokens","ids",".","_path",":","Disk","path","to","find","javascript","that","create","interactive","explorables","n_components",":","Number","of","components\/factors","to","reduce","the","neuron","factors","to",".","tokens",":","The","text","of","each","token",".","collect_activations_layer_nums",":","The","list","of","layer","ids","whose","activtions","were","collected",".","If","None",",","then","all","layers","were","collected","."]
code: def __init__(
      self,
      activations: Dict[str, np.ndarray],
      n_input_tokens: int = 0,
      token_ids: torch.Tensor = torch.Tensor(0),
      _path: str = "",
      n_components: int = 10,
      from_layer: Optional[int] = None,
      to_layer: Optional[int] = None,
      tokens: Optional[List[str]] = None,
      collect_activations_layer_nums: Optional[List[int]] = None,
      config=None,
      **kwargs,
  ):
      """
      Receives a neuron activations tensor from OutputSeq and decomposes it using NMF into the number
      of components specified by `n_components`. For example, a model like `distilgpt2` has 18,000+
      neurons. Using NMF to reduce them to 32 components can reveal interesting underlying firing
      patterns.
  
      Args:
          activations: Activations tensor. Dimensions: (batch, layer, neuron, position)
          n_input_tokens: Number of input tokens.
          token_ids: List of tokens ids.
          _path: Disk path to find javascript that create interactive explorables
          n_components: Number of components/factors to reduce the neuron factors to.
          tokens: The text of each token.
          collect_activations_layer_nums: The list of layer ids whose activtions were collected. If
          None, then all layers were collected.
      """
  
      if activations == []:
          raise ValueError(
              f"No activation data found. Make sure 'activations=True' was passed to "
              f"ecco.from_pretrained()."
          )
  
      self._path = _path
      self.token_ids = token_ids
      self.n_input_tokens = n_input_tokens
      self.config = config
  
      # Joining Encoder and Decoder (if exists) together
      activations = np.concatenate(list(activations.values()), axis=-1)
  
      merged_act = self.reshape_activations(
          activations,
          from_layer,
          to_layer,
          collect_activations_layer_nums,
      )
      # 'merged_act' is now ( neuron (and layer), position (and batch) )
  
      activations = merged_act
  
      self.tokens = tokens
      # Run NMF. 'activations' is neuron activations shaped (neurons (and layers), positions (and batches))
      n_output_tokens = activations.shape[-1]
      n_layers = activations.shape[0]
      n_components = min([n_components, n_output_tokens])
      components = np.zeros((n_layers, n_components, n_output_tokens))
      models = []
  
      # Get rid of negative activation values
      # (There are some, because GPT2 uses GELU, which allow small negative values)
      self.activations = np.maximum(activations, 0).T
  
      self.model = decomposition.NMF(
          n_components=n_components,
          init="random",
          random_state=0,
          max_iter=500,
      )
      self.components = self.model.fit_transform(self.activations).T
  
imports: import os
  import json
  import ecco
  from IPython import display
  from ecco import util, lm_plots
  import random
  import matplotlib.pyplot
  import numpy
  import torch
  from torch.nn import functional
  from sklearn import decomposition
  from typing import Dict, Optional, List, Tuple, Union
  from ecco.util import strip_tokenizer_prefix, is_partial_token
label_desc: Use image node_id 1 to create a new NMF object  with example: obj = NMF(activations, n_input_tokens, token_ids, _path, n_components, from_layer, to_layer, tokens, collect_activations_layer_nums, config)