sciBASIC# knot logo sciBASIC# ↖

07 Tutorial — Text features

Turn five short documents into a TF-IDF space, then measure how far apart their vocabularies sit.

Module Data.NLP · TFIDF Corpus 5 documents Matrix 5 × 5 square distance Output PNG · 300 dpi · Plasma

TF-IDF is the smallest useful model of "what a document is about". This demo registers five short documents in the sciBASIC# TFIDF index, pulls each one back out as a weighted term vector, and fills a 5 × 5 matrix of pairwise squared distances — printed to the console and rendered as a Plasma-colored heatmap where dark cells mean "same vocabulary" and bright cells mean "different worlds".

02 Pipeline

From five sentences to a distance matrix

Step 1

Index

Every document is whitespace-tokenized (StringSplit("\s+")) and registered in the TFIDF index via tfIdf.Add(++i, tokens), building the inverted document–term table.

Step 2

Vectorize

tfIdf.TfidfVectorizer(id) maps every document to its sparse TF-IDF weights: term frequency scaled by inverse document frequency.

Step 3

Measure

All 25 pairs are compared with v.SquareDistance; the row loops echo the matrix to the console while filling a 5 × 5 array.

Step 4

Visualize

A HeatmapPlot (800 × 600, PlotTheme.Light) renders the matrix with the Plasma colormap and saves it at 300 dpi.

03 The corpus

Five documents, twenty-five pairs

The exact texts registered by tfIdf.Add — five short notes on knowledge building and creative environments:

DocumentText
doc_1knowledge building needs innovative environments are better at helping their inhabitants explore the adjacent possible
doc_2As a basis for evaluating explanations, creative knowledge building weight of evidence is a poor substitute for the first two criteria listed above.
doc_3A public idea database makes every passing idea visible to everyone else in the organization and do creative work.
doc_4questioning and various disturbances initiate cycles of innovation and creative organization knowledge.
doc_5We need some way to ensure knowledge to spread among environments that any notes that are dropped are dropped.

01 The Script

Full demo source

The complete script exactly as executed by the sciBASIC# script engine (vbs.exe) — nothing elided.

tfidf.vb · 111 linesDownload tfidf.vb
#include "Microsoft.VisualBasic.Data.NLP.dll"
#include "Microsoft.VisualBasic.Data.Framework.dll"
#include "Microsoft.VisualBasic.Drawing.dll"
#include "Microsoft.VisualBasic.Data.DataPlot.dll"

Imports System.IO
Imports Microsoft.VisualBasic.ComponentModel.Collection
Imports Microsoft.VisualBasic.Data.NLP
Imports Microsoft.VisualBasic.Language
Imports Microsoft.VisualBasic.Math.Correlations
imports microsoft.visualbasic.data.plots
imports microsoft.visualbasic.drawing
imports Microsoft.VisualBasic.Data.Framework

' ============================================================================
'  TF-IDF document distance tutorial
'
'  Build a TF-IDF vectorizer over a handful of short documents, compute the
'  pairwise squared Euclidean distance between the document vectors, and render
'  the resulting distance matrix as a heatmap.
'
'  Run:
'      vbs.exe tutorials\VBS\tf-idf\tfidf.vb
'
'  Flow:
'      1) collect the raw documents
'      2) feed every document into the TF-IDF index (id + token stream)
'      3) compute the N x N pairwise squared distance matrix
'      4) render the distance matrix as a heatmap and save it to PNG
' ============================================================================

' ---------------------------------------------------------------------------
'  1) A small in-memory corpus; each element is one document.
'     The documents deliberately share the vocabulary of
'     "knowledge / creative / environments", so the TF-IDF distances between
'     them stay meaningful.
' ---------------------------------------------------------------------------
Dim docs = New String() {
    "knowledge building needs innovative environments are better at helping their inhabitants explore the adjacent possible",
    "As a basis for evaluating explanations, creative knowledge building weight of evidence is a poor substitute for the first two criteria listed above.",
    "A public idea database makes every passing idea visible to everyone else in the organization and do creative work.",
    "questioning and various disturbances initiate cycles of innovation and creative organization knowledge.",
    "We need some way to ensure knowledge to spread among environments that any notes that are dropped are dropped."
}

' ---------------------------------------------------------------------------
'  2) Build the TF-IDF index.
'
'     * ``Add`` takes a numeric document id together with the token sequence of
'       that document
'     * ``StringSplit`` applies the regular expression "\s+" so that each
'       sentence is split into words on any whitespace run
'     * document ids start at 2 because ``++i`` is evaluated before the call
' ---------------------------------------------------------------------------
Dim tfIdf As New TFIDF
Dim i As i32 = 1

For Each seq As String In docs
    Call tfIdf.Add(++i, seq.StringSplit("\s+"))
Next

' ---------------------------------------------------------------------------
'  3) Pairwise document distance matrix.
'
'     * ``N`` is the number of documents
'     * ``RectangularArray.Matrix`` allocates an N x N jagged matrix
'     * ``TfidfVectorizer(id)`` returns the TF-IDF vector of a document
'     * ``SquareDistance`` compares two vectors
'     The matrix is symmetric with a zero diagonal, since the distance of a
'     document to itself is 0.
' ---------------------------------------------------------------------------
Dim N As Integer = docs.Length
Dim dist As Double()() = RectangularArray.Matrix(Of Double)(N, N)

For id As Integer = 1 To tfIdf.N
    Dim v = tfIdf.TfidfVectorizer(id.ToString)
    Dim rd As Double() = New Double(N - 1) {}

    Console.Write(id.ToString() & vbTab)

    For j As Integer = 1 To tfIdf.N
        Dim d = v.SquareDistance(tfIdf.TfidfVectorizer(j.ToString))

        rd(j - 1) = d
        Call Console.Write(d.ToString("F4").PadLeft(8, "0"c) & vbTab)
    Next

    dist(id - 1) = rd.ToArray

    Call Console.WriteLine()
Next

' ---------------------------------------------------------------------------
'  4) Render the distance matrix as a heatmap.
'
'     Row and column labels are generated as doc_1 .. doc_N by ``fieldName``;
'     the Plasma colour map highlights that the diagonal distance is 0 while
'     unrelated documents are far apart.
' ---------------------------------------------------------------------------
call SkiaDriver.Register()

Using plt As New HeatmapPlot(800, 600, PlotTheme.Light())
    plt.Title = "TF-IDF Document Distance Heatmap"
    plt.Matrix = dist.ToMatrix()
    plt.RowLabels = fieldName("doc", dist.length, sep := "_").toarray()
    plt.ColLabels = fieldName("doc", dist.length, sep := "_").ToArray()
    plt.ColorMap = HeatmapPlot.ColorMapType.Plasma
    plt.ShowValues = False
    plt.Plot()
    plt.SavePng(here("tfidf-heatmap.png"), 300)
End Using

03 Results

The document-distance heatmap

Plasma heatmap of pairwise TF-IDF square distances between five documents
Fig. 1 — Pairwise squared TF-IDF distances over the five-document corpus. The diagonal reads dark (zero distance to itself), and the brightest cell — doc_2 ↔ doc_5 — marks the pair of documents whose weighted vocabularies diverge the most.
SquareDistance is used on purpose: the demo shows the raw squared metric, so cell values grow quadratically with vocabulary mismatch — and the Plasma color scale runs from the zero diagonal up to the bright-yellow doc_2 ↔ doc_5 pair.