DeepLearning
ISLisp

MNISTデータをISLispの配列として取り込む

はじめに

ISLispによりDeep Larningの勉強をしています。うまく学習できるのかを確認するためにMNISTデータを利用することとしています。ISLispの配列としてランダムに取り込むコードを書きました。

使い方

(create-training-data) 訓練データ6万個からランダムに100個を選び image-arrayとlabel-arrayに書き込みます。

(create-test-data) テストデータ1万個からランダムに100個を選び label-arrayとlabel-arrayに書き込みみます。

画像データの各要素は0~1の間に正規化しています。

image-arrayは100*784です。784要素の画像データを100個分取り込みます。
label-arrayは教師データです。100*10です。10は数の0~9に対応しています。ラベルの数のインデックスの位置に1.0を書き込みます。

準備

下記のページよりMNISTのデータをダウンロードします。これらはgzファイルとなっていますので解凍します。WindowsでしたらLhaplusで解凍することができます。解凍したファイルをカレントディレクトリに置きます。
http://yann.lecun.com/exdb/mnist/

動作確認

自作のEasy-ISLispで動作確認しています。ISLispの標準関数しか使用していませんので、他の処理系でも動作するものと思います。

データ構造

下記の投稿を参考にしました。
https://qiita.com/mine820/items/e9c08439465a5580a9cb

コード

ラベルファイル、画像ファイルのヘッダ部分を読み飛ばし、順次読み取りつつ、乱数で生成した自然数番目のものだけを配列に読み込んでいます。

(defglobal image-array (create-array (list 100 784)))
(defglobal label-array (create-array (list 100 10)))

(defun create-training-data ()
  (let ((image (open-input-file "train-images.idx3-ubyte" 8))
        (label (open-input-file "train-labels.idx1-ubyte" 8))
        (randls (gen-random-list 60000 100)))
    (init-label-array)
    (skip-images-header image)
    (skip-labels-header label)
    (for ((i 0 (+ i 1))
          (j 0))
         ((>= j 100))
         (cond ((member i randls)
                (write-label (read-byte label) j)
                (read-one-image image j)
                (setq j (+ j 1)))))
    (close image)
    (close label)))

(defun create-test-data ()
  (let ((image (open-input-file "t10k-images.idx3-ubyte" 8))
        (label (open-input-file "t10k-labels.idx1-ubyte" 8))
        (randls (gen-random-list 10000 100)))
    (init-label-array)
    (skip-images-header image)
    (skip-labels-header label)
    (for ((i 0 (+ i 1))
          (j 0))
         ((>= j 100))
         (cond ((member i randls)
                (write-label (read-byte label) j) 
                (read-one-image image j))))
    (close image)
    (close label)))


(defun read-one-image (file n)
  (for ((i 0 (+ i 1)))
       ((>= i 784) image-array)
       (set-aref (quotient (read-byte file) 255) image-array n i)))

(defun write-label (n j)
  (set-aref 1.0 label-array j n))

(defun skip-images-header (file)
  (for ((i 0 (+ i 1)))
       ((> i 15))
       (read-byte file)))

(defun skip-labels-header (file)
  (for ((i 0 (+ i 1)))
       ((> i 7))
       (read-byte file)))

(defun init-label-array ()
  (for ((i 0 (+ i 1)))
       ((>= i 100))
       (for ((j 0 (+ j 1)))
            ((>= j 10))
            (set-aref 0 label-array i j))))

(defun qsort (fn ls)
  (if (null ls)
      ls
      (qsort2 fn (car ls) (cdr ls) nil nil)))

(defun qsort2 (fn p ls left right)
  (if (null ls)
      (append (qsort fn left)(cons p (qsort fn right)))
      (if (apply fn (car ls)(list p))
          (qsort2 fn p
                  (cdr ls)(cons (car ls) left) right)
          (qsort2 fn p
                  (cdr ls) left (cons (car ls) right)))))

(defun gen-random-list (m n)
  (qsort #'< (gen-random-list1 m n)))

(defun gen-random-list1 (m n)    
  (if (= n 0)
      nil
      (cons (random m) (gen-random-list1 m (- n 1)))))