Tfidf Class
The Tfidf class encodes sequences using the Term Frequency-Inverse Document Frequency technique. See the About section for more details.
Class Signature
Tfidf
class Tfidf(corpus, kmer, vocabulary=None, smooth_idf=True, original_idf=False, n_jobs=1, reader_fn=None, format=None)
Constructor Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
corpus |
iterable containing str or str |
Required | Sequences to encode, can also be a path to a file. |
kmer |
int |
Required | Size of the kmers used to build the vocabulary and compute the TF-IDF. |
vocabulary |
dict[str,int] |
None |
Dictionary mapping each kmers to consider for encoding to a unique integer value. |
smooth_idf |
bool |
True |
If True computes the IDF, adding 1 to the numerator and denominator IDF(t) = log(\frac{1+N}{1+df(t)})+1. Otherwise IDF(t) = log(\frac{N}{df(t)})+1. This option matches the scikit-learn implementation. |
original_idf |
bool |
False |
If True ignores 'smooth_idf' option and computes the IDF using the textbook definition IDF(t) = log(\frac{N}{df(t)}). |
n_jobs |
int |
1 |
number of threads used to encode the sequences in parallel. 0 to use all CPUs available. |
reader_fn |
Callable |
None |
Function to use to read sequences if corpusis a path to a file. |
format |
str |
None |
Format of the file when using SeqIO.read from Biopython. Either fasta or fastq. |
WrongTfidfConfig: Ifcorpusis astr(a file path) but noreader_fnis provided.
Vocabulary Indices Must Be Contiguous
If you provide a vocabulary, its integer values must form a contiguous range starting at 0 — i.e. 0, 1, 2, ..., len(vocabulary) - 1, with no gaps. A vocabulary like {"aaa": 0, "aac": 2} (skipping 1) is invalid.
Attributes
Use these attributes to check the live state of your Tfidf instance.
| Attribute | Type | Description |
|---|---|---|
corpus |
iterable containing str or str |
The sequences (or file path) currently associated with the instance. |
kmer_size |
int |
Size of the kmers used to build the vocabulary and compute the TF-IDF. |
vocabulary |
dict[str,int] or None |
Mapping of each kmer to its column index. None until it is provided in the constructor, via set_vocabulary(), or learned by fit() / fit_transform(). |
idf |
numpy.ndarray or None |
Inverse document frequency value for each term in vocabulary. None until fit() or fit_transform() has been called. |
is_idf_uptodate |
bool |
True once idf has been computed for the current vocabulary and corpus. Reset to False by set_vocabulary() and add_to_corpus(). |
smooth_idf |
bool |
True |
original_idf |
bool |
False |
n_jobs |
int |
Number of threads used to encode sequences in parallel. 0 uses all available CPUs. |
reader_fn |
Callable or None |
Function used to read sequences when corpus is a file path. |
format |
str or None |
Format passed to reader_fn when reading corpus from a file (e.g. fasta or fastq). |
Methods
.set_vocabulary()
Replaces the current vocabulary used to encode sequences.
vocabulary(dict[str,int]): Dictionary mapping each kmer to consider for encoding to a unique integer value.
None
Refit Required
Calling set_vocabulary() sets is_idf_uptodate to False. You must call fit() (or fit_transform()) again before transform() will produce valid results.
.set_threads()
Updates the number of threads used to encode sequences in parallel.
n_jobs(int): Number of threads to use.0uses all CPUs available.
None
.add_to_corpus()
Appends new sequences to the existing corpus in place.
new_corpus(iterable containing str): Sequences to add to the current corpus. Cannot itself be astr.
None
TypeError: Ifnew_corpusis astr. Pass a single sequence aslist[str]instead.UnextendableCorpus: If the instance'scorpusis not an extendable collection of sequences (i.e. not alist,set, ortuple, and without its own.extend()method) — most commonly whencorpusis a file path.
Refit Required
Calling add_to_corpus() sets is_idf_uptodate to False. You must call fit() (or fit_transform()) again before transform() will produce valid results for the updated corpus.
.fit()
Learns the vocabulary from corpus (if one was not already set) and computes the inverse document frequency (idf) values needed to encode sequences with transform().
- None
None
Existing Vocabulary
If vocabulary is already set (either via the constructor or set_vocabulary()), fit() skips vocabulary learning and only computes idf values against that vocabulary.
.transform()
Encodes sequences into a TF-IDF weighted sparse matrix using the fitted vocabulary and idf values.
sequences(iterable containing strorstr, optional): Sequences to encode, can also be a path to a file. Defaults to the instance'scorpuswhen not provided.l2_norm(bool, optional): L2 Row normalization is applied to the resulting matrix.
scipy.sparse.csr_matrix: The TF-IDF encoded matrix, with one row per sequence and one column per vocabulary term.
NotFittedError: Iffit()(orfit_transform()) has not been called since the last vocabulary or corpus change.
.fit_transform()
Fits the vocabulary (if not already set) and idf values on corpus, then returns the TF-IDF encoded matrix in a single call.
l2_norm(bool, optional): L2 Row normalization is applied to the resulting matrix.
scipy.sparse.csr_matrix: The TF-IDF encoded matrix forcorpus, with one row per sequence and one column per vocabulary term.
Exceptions
WrongTfidfConfig
Raised by the constructor when corpus is a str (a file path) but no reader_fn is provided to read it.
NotFittedError
Raised by .transform() when called before the instance has been fitted (i.e. before fit() or fit_transform() has been run against the current vocabulary and corpus).
UnextendableCorpus
Raised by .add_to_corpus() when the instance's corpus cannot be extended in place — i.e. it is not a list, set, tuple, or another object exposing its own .extend() method. This most commonly happens when corpus was set to a file path.
NoReader
Raised if a string is passed as genomic sequence but no reader function is specified. A string is assumed to represent a path to a file containing sequences. To encode a single sequence, the sequence should be wrapped in a list.
Examples
Basic Usage
import dna_parser as dps
sequences= ["agttcttctc","accttgtgt","acctgtcgc"]
tfidf= dps.Tfidf(sequences, 3)
matrix= tfidf.fit_transform()
print(matrix)
#Output:
#<Compressed Sparse Row sparse matrix of dtype 'float64'
# with 9 stored elements and shape (3, 7)>
# Coords Values
# (0, 0) 0.408248290463863
# (0, 1) 0.816496580927726
# (0, 2) 0.408248290463863
# (1, 3) 0.32718457421366
# (1, 4) 0.8865102981879298
# (1, 5) 0.32718457421366
# (2, 3) 0.32718457421366
# (2, 5) 0.32718457421366
# (2, 6) 0.8865102981879298
Fitting with a Predefined Vocabulary
import dna_parser as dps
sequences= ["agttcttctc","accttgtgt","acctgtcgc"]
vocabulary= {"acc":0, "agt":1,"tct":2, "ttg":3}
tfidf= dps.Tfidf(sequences, 3, vocabulary)
matrix= tfidf.fit_transform()
print(matrix)
#Output:
#<Compressed Sparse Row sparse matrix of dtype 'float64'
# with 5 stored elements and shape (3, 4)>
# Coords Values
# (0, 1) 0.4472135954999579
# (0, 2) 0.8944271909999159
# (1, 0) 0.3462415530579614
# (1, 3) 0.9381453975456102
# (2, 0) 1.0
Encoding Sequences from a File
import dna_parser as dps
from Bio import SeqIO
reader_fn= SeqIO.parse
form="fasta"
tfidf= dps.Tfidf("path/to/file.fasta", 3, reader_fn= reader_fn, format=form)
tfidf.fit_transform()
#Output:
#<Compressed Sparse Row sparse matrix of dtype 'float64'
# with 16 stored elements and shape (3, 16)>
reader_fn= dps.SequenceReader
tfidf= dps.Tfidf("path/to/file.fasta", 3, reader_fn= reader_fn)
tfidf.fit_transform()
#Output:
#<Compressed Sparse Row sparse matrix of dtype 'float64'
# with 16 stored elements and shape (3, 16)>
Updating the Corpus and Re-fitting
import dna_parser as dps
sequences= ["agttcttctc","accttgtgt","acctgtcgc"]
tfidf= dps.Tfidf(sequences, 3)
matrix= tfidf.fit_transform()
tfidf.add_to_corpus(["agtcgcgataaaa", "agatagagactgatagat"])
matrix= tfidf.fit_transform()
print(matrix)
#<Compressed Sparse Row sparse matrix of dtype 'float64'
# with 11 stored elements and shape (5, 7)>
# Coords Values
# (0, 0) 0.24673728071874365
# (0, 1) 0.8667736564079552
# (0, 2) 0.4333868282039776
# (1, 3) 0.4434518002301797
# (1, 4) 0.7789101371437052
# (1, 5) 0.4434518002301797
# (2, 3) 0.5773502691896257
# (2, 5) 0.5773502691896257
# (2, 6) 0.5773502691896257
# (3, 0) 0.7071067811865475
# (3, 6) 0.7071067811865475