;;; Example of using libsvm to classify letters, using UCI's letter-recognition example ;;; Written by Peter Lane, 2010. ;; Note: use of srfi-42 only ok in interpreted version - cannot compile (require-extension srfi-1) (require-extension srfi-42) (require-extension format) (require-extension libsvm) (require-extension input-parse) (svm-no-print-function) ; do training quietly ;; helper functions ;; -- create a model (define (make-rbf-model problem cost gamma) (svm-train problem (make-svm-parameter C: cost gamma: gamma kernel-type: RBF svm-type: NU-SVC degree: 1 coef0: 0 eps: 0.001 nu: 0.5))) ;; -- return the number of errors (define (test-model model problem) (sum-ec (: i (problem-num-instances problem)) (if (= (problem-get-label problem i) (svm-predict model (problem-get-instance problem i))) 0 1))) ;; load letter-recognition data ;; -- given a list of strings from CSV input ;; convert into a list of numbers with features scaled 0 -> 1.0 ;; labels being char value - 'A' (define (make-instance str-list) (cons (- (char->integer (string-ref (car str-list) 0)) (char->integer #\A)) (map (lambda (str) (/ (string->number str) 15)) (cdr str-list)))) (define (read-data filename) (with-input-from-file filename (lambda () (let loop ((line (read-text-line)) (results '())) (if (eof-object? line) (reverse results) (loop (read-text-line) (cons (make-instance (string-tokenize line (char-set-complement (string->char-set ",")))) results))))))) (define *data* (read-data "letter-recognition.data")) (define *training-set* (make-problem (take *data* 2000))) (define *cross-set* (make-problem (take (drop *data* 9000) 1000))) (define *test-set* (make-problem (drop *data* 10000))) (let ((best-model '()) (lowest-error (problem-num-instances *cross-set*))) (for-each (lambda (cost) (for-each (lambda (gamma) (let* ((model (make-rbf-model *training-set* cost gamma)) (result (test-model model *cross-set*))) (if (< result lowest-error) (begin (unless (null? best-model) (svm-destroy-model best-model)) (set! best-model model) (set! lowest-error result)) (svm-destroy-model model)) (format #t "Testing: C = ~f G = ~f -> ~d~&" cost gamma result))) (map (lambda (p) (expt 2 p)) '(-15 -12 -8 -5 -3 -1 1 3 5 7 9)))) (map (lambda (p) (expt 2 p)) '(-5 -3 -1 0 1 3 5 8 10 13 15))) (format #t "Error rate is: ~f~&" (test-model best-model *test-set*)))