OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-learn / scm / parse / pseudo-csets.scm

178 lines · scm ref:
;
; pseudo-csets.scm
;
; Representing words as vectors of (pseudo-)connector-sets.
;
; Copyright (c) 2017 Linas Vepstas
;
; ---------------------------------------------------------------------
; OVERVIEW
; --------
; This file provide the "matrix-object" API that allows words to be
; treated as vectors of connector-sets (vectors of disjuncts; vectors
; of Sections).  The vector representation is important, because vectors
; are the core input to a number of important machine-learning
; algorithms.  Most immediately and directly, one can take the cosine
; product between vectors (see `word-cosine.scm` for examples).
;
; This just provides the vector API, and nothing more. Other objects,
; as a part of the `(opencog matrix)` suite, do various things with the
; vector (such as compute cosines, perform other similarity measures,
; filter out unwanted/bad components, etc.)
;
; Here and below, "connector set" and "connector sequence" mean the same
; thing. The word "disjunct" alternately refers to either a connector
; sequence, or a "Section", the difference being that a Section
; indicates what word the connector sequence is attached to.
;
; A vector can be decomposed into a sum over "basis elements", as
; follows:
;
;     v = a_1 e_1 + a_2 e_2 + ... + a_n e_n
;
; where each a_k is a (real) number, and the e_k are the "basis
; elements".  Here, each distinct e_k corresponds to each distinct
; ConnectorSeq atom.  Each number a_k corresponds to the observational
; frequency, stored as a Value on the Section atom.  There is one
; such vector for each word, and thus, the set of all words can be
; treated as a matrix: each column of the matrix is a word-vector.
; Alternately, one can think of this as a collection of pairs, of
; the form (word, cset), and a count/frequency for each pair. The
; left side of the pair are WordNodes; the right side are ConnectorSeq's
; and the pair itself is a Section (which is why the counts are stored
; on the Section).  That is, each pair is of the form:
;
;    (Section
;       (WordNode "foobar")
;       (ConnectorSeq ... )
;
; An example connector-set, for the word "playing", illustrating
; that it can connect to the word "level" on the left, and "field"
; on the right, is shown below. (Please note that this is for
; illustrating the atomese structure, and not for illustrating actual
; English grammar; its a bad grammatical example, although the MST
; parser does find things like this.)
;
;    (Section
;       (WordNode "playing")
;       (ConnectorSeq
;          (Connector
;             (WordNode "level")
;             (ConnectorDir "-"))
;          (Connector
;             (WordNode "field")
;             (ConnectorDir "+"))))
;
; In dictionary short-hand, this would be written as
;
;     playing:  level- & field+;
;
; The `ConnectorSeq` part of this structure is referred to as the
; pseudo-disjunct, in that it resembles a normal link-grammar
; disjunct, but has words appearing where connectors should be.
;
; Any given word may have dozens or hundreds or thousands of these
; sections. The totality of these sections, for a given, fixed word
; form a vector.  The connector seq (the disjunct) is a basis element,
; and the raw observational count on the `Section` is the magnitude
; of the vector in that basis direction.
;
; Note that these vectors are sparse: if a particular disjunct is
; missing, then the associated count is zero.  Note that the dimension
; of the vector-space is extremely high, possibly in the
; tens-of-millions, while a "typical" English word might have a few
; thousand non-zero sections.
;
; Note: At this time, there can only ever be one such object in the
; entire AtomSpace. There is nothing in here to distinguish one
; collection of sections from another. I suppose that this should be
; fixed, but so far, there has not been any need for this.
;
; ---------------------------------------------------------------------
;
(use-modules (srfi srfi-1))
(use-modules (opencog))
(use-modules (opencog persist))
(use-modules (opencog matrix))

(define-public (make-pseudo-cset-api)
"
  make-pseudo-cset-api -- Create a word-disjunct matrix.

  The matrix consists of (word,disjunct) pairs (a 'disjunct' and a
  'cset' or 'connector set' are all different names for the same thing).
  The words appear as rows of the matrix; the disjuncts as columns.

  For a detailed description, see the `pseudo-csets.scm` file.
"
	(define any-left (AnyNode "cset-word"))
	(define any-right (AnyNode "cset-disjunct"))

	(define (get-left-type) (Type 'WordNode))
	(define (get-right-type) (Type 'ConnectorSeq))
	(define (get-pair-type) (Type 'Section))

	; Get the pair, if it exists.
	(define (get-pair L-ATOM R-ATOM)
		(cog-link 'Section L-ATOM R-ATOM))

	(define (make-pair L-ATOM R-ATOM)
		(Section L-ATOM R-ATOM))

	(define (get-left-element PAIR) (gar PAIR))
	(define (get-right-element PAIR) (gdr PAIR))

	(define (get-left-wildcard DJ)
		(ListLink any-left DJ))

	(define (get-right-wildcard WORD)
		(ListLink WORD any-right))

	(define (get-wild-wild)
		(ListLink any-left any-right))

	; Fetch (from the database) all pseudo-csets
	(define (fetch-pseudo-csets)
		(define start-time (current-time))

		; Marginals are located on a ListLink on any-left, any-right
		(fetch-incoming-by-type any-left 'ListLink)
		(fetch-incoming-by-type any-right 'ListLink)

		; Loading Sections is a bit too much, as that will also
		; pick up WordClassNodes. But I guess that is OK for now.
		(load-atoms-of-type 'Section)
		(format #t "Elapsed time to load csets: ~A secs\n"
			(- (current-time) start-time)))

	(define (describe)
		(display (procedure-property make-pseudo-cset-api 'documentation)))

	; Methods on the object
	(lambda (message . args)
		(apply (case message
			((name) (lambda () "Word-Disjunct Pairs (Connector Sets)"))
			((id)             (lambda () "cset"))
			((left-type)      get-left-type)
			((right-type)     get-right-type)
			((pair-type)      get-pair-type)
			((get-pair)       get-pair)
			((make-pair)      make-pair)
			((left-element)   get-left-element)
			((right-element)  get-right-element)
			((left-wildcard)  get-left-wildcard)
			((right-wildcard) get-right-wildcard)
			((wild-wild)      get-wild-wild)
			((fetch-pairs)    fetch-pseudo-csets)
			((provides)       (lambda (symb) #f))
			((filters?)       (lambda () #f))
			((help)           describe)
			((describe)       describe)
			((obj)            (lambda () "make-pseudo-cset-api"))
			((base)           (lambda () #f))
			(else (error "Bad method call on pseudo-cset:" message)))
		args))
)

; ---------------------------------------------------------------------