| … | … | @@ -0,0 +1,96 @@ |
| 1 | ; mi-verify.scm — data-level MI tie: opencog matrix `pair-fmi` vs our cpu_mi. |
| 2 | ; Tiny hand-computable word-pair dataset -> batch-all-pair-mi -> read pair-fmi, |
| 3 | ; compare to log2(count*N/(Nx*·N*y)) which our GPU kernel is verified == to. |
| 4 | |
| 5 | (use-modules (srfi srfi-1)) |
| 6 | (use-modules (opencog) (opencog matrix)) |
| 7 | |
| 8 | ; --- make-basic-api (verbatim from matrix/tests/matrix/basic-api.scm) --- |
| 9 | (define (make-basic-api) |
| 10 | (define (get-left-type) 'ConceptNode) |
| 11 | (define (get-right-type) 'ConceptNode) |
| 12 | (define (get-pair-type) 'EvaluationLink) |
| 13 | (define (get-pair L-ATOM R-ATOM) |
| 14 | (define maybe-list (cog-link 'ListLink L-ATOM R-ATOM)) |
| 15 | (if (not maybe-list) '() |
| 16 | (cog-link 'EvaluationLink (Predicate "foo") maybe-list))) |
| 17 | (define (get-count PAIR) |
| 18 | (cog-value-ref (cog-value PAIR (Predicate "counter")) 2)) |
| 19 | (define (get-pair-count L-ATOM R-ATOM) |
| 20 | (define stats-atom (get-pair L-ATOM R-ATOM)) |
| 21 | (if (not stats-atom) 0 (get-count stats-atom))) |
| 22 | (define (make-pair L-ATOM R-ATOM) |
| 23 | (EvaluationLink (Predicate "foo") (List L-ATOM R-ATOM))) |
| 24 | (define (get-left-element PAIR) (gadr PAIR)) |
| 25 | (define (get-right-element PAIR) (gddr PAIR)) |
| 26 | (define (get-left-wildcard ITEM) |
| 27 | (EvaluationLink (Predicate "foo") (ListLink (AnyNode "left-wild") ITEM))) |
| 28 | (define (get-right-wildcard ITEM) |
| 29 | (EvaluationLink (Predicate "foo") (ListLink ITEM (AnyNode "right-wild")))) |
| 30 | (define (get-wild-wild) |
| 31 | (EvaluationLink (Predicate "foo") (ListLink (AnyNode "left-wild") (AnyNode "right-wild")))) |
| 32 | (define (fetch-all-pairs) '()) |
| 33 | (lambda (message . args) |
| 34 | (apply (case message |
| 35 | ((name) (lambda () "MI verify demo")) |
| 36 | ((id) (lambda () "mi-verify")) |
| 37 | ((left-type) get-left-type) |
| 38 | ((right-type) get-right-type) |
| 39 | ((pair-type) get-pair-type) |
| 40 | ((pair-count) get-pair-count) |
| 41 | ((get-pair) get-pair) |
| 42 | ((get-count) get-count) |
| 43 | ((make-pair) make-pair) |
| 44 | ((left-element) get-left-element) |
| 45 | ((right-element) get-right-element) |
| 46 | ((left-wildcard) get-left-wildcard) |
| 47 | ((right-wildcard) get-right-wildcard) |
| 48 | ((wild-wild) get-wild-wild) |
| 49 | ((fetch-pairs) fetch-all-pairs) |
| 50 | ((provides) (lambda (symb) #f)) |
| 51 | ((filters?) (lambda () #f)) |
| 52 | (else (error "Bad method call on low-level API"))) |
| 53 | args))) |
| 54 | |
| 55 | (define bapi (make-basic-api)) |
| 56 | (define sapi (add-pair-stars bapi)) |
| 57 | (define fapi (add-pair-freq-api sapi)) |
| 58 | |
| 59 | ; --- tiny dataset: (left right count) --- |
| 60 | (define data '(("the" "cat" 2.0) ("the" "dog" 1.0) ("a" "cat" 1.0))) |
| 61 | |
| 62 | ; set a count on a pair the way the basic-api reads it (FloatValue index 2) |
| 63 | (define (observe L R cnt) |
| 64 | (define p (bapi 'make-pair (Concept L) (Concept R))) |
| 65 | (cog-set-value! p (Predicate "counter") (FloatValue 0 0 cnt)) |
| 66 | p) |
| 67 | (for-each (lambda (row) (apply observe row)) data) |
| 68 | |
| 69 | ; --- opencog computes marginals, freqs, entropies, MI (in-RAM, no store) --- |
| 70 | (batch-all-pair-mi bapi #f) |
| 71 | |
| 72 | ; --- our reference marginals from the raw counts (hand/independent) --- |
| 73 | (define (log2 x) (/ (log x) (log 2))) |
| 74 | (define N (fold + 0 (map caddr data))) |
| 75 | (define (Nx* L) (fold + 0 (map caddr (filter (lambda (r) (string=? (car r) L)) data)))) |
| 76 | (define (N*y R) (fold + 0 (map caddr (filter (lambda (r) (string=? (cadr r) R)) data)))) |
| 77 | (define (cpu-fmi L R cnt) (log2 (/ (* cnt N) (* (Nx* L) (N*y R))))) |
| 78 | |
| 79 | ; --- compare opencog pair-fmi vs cpu-fmi for each pair --- |
| 80 | (define tol 1e-6) |
| 81 | (define all-ok #t) |
| 82 | (display "pair count Nx* N*y opencog-fmi cpu-fmi diff\n") |
| 83 | (for-each |
| 84 | (lambda (row) |
| 85 | (define L (car row)) (define R (cadr row)) (define cnt (caddr row)) |
| 86 | (define p (bapi 'get-pair (Concept L) (Concept R))) |
| 87 | (define oc (fapi 'pair-fmi p)) |
| 88 | (define cpu (cpu-fmi L R cnt)) |
| 89 | (define d (abs (- oc cpu))) |
| 90 | (if (> d tol) (set! all-ok #f)) |
| 91 | (format #t "~a-~a\t ~a ~a ~a ~9,6f ~9,6f ~9,2e\n" |
| 92 | L R cnt (Nx* L) (N*y R) oc cpu d)) |
| 93 | data) |
| 94 | (newline) |
| 95 | (display (if all-ok "MI DATA-VERIFY PASS: opencog pair-fmi == cpu_mi (== our GPU kernel)\n" |
| 96 | "MI DATA-VERIFY FAIL\n")) |