X x X 行列を含むバイナリ ファイルがあります。ファイル自体は、単精度浮動小数点 (リトルエンディアン) のシーケンスです。私がやりたいのは、それを解析して、適切な clojure マトリックス データ型に詰め込むことです。
この質問のおかげで、グロスでバイナリファイルを解析できることがわかりました。私は今、次のようなコードを持っています:
(ns foo.core
(:require gloss.core)
(:require gloss.io)
(:use [clojure.java.io])
(:use [clojure.math.numeric-tower]))
(gloss.core/defcodec mycodec
(gloss.core/repeated :float32 :prefix :none))
(def buffer (byte-array (* 1200 1200)))
(.read (input-stream "/path/to/binaryfile") buffer)
(gloss.io/decode mycodec buffer)
これには実行に時間がかかりますが、最終的には膨大な数のリストが出力されます。残念ながら、数字はすべて間違っています。さらに調査したところ、数字はビッグエンディアンとして読み取られました。
これらのバイナリ ファイルをリトルエンディアンとして読み取る何らかの方法があると仮定して、結果を行列に詰め込みたいと思います。この質問は、Parallel Colt 表現で Incanter を使用することに落ち着いたようですが、その質問は '09 年のものであり、私は clojure 1.4 と lein 2 に固執することを望んでいます。 jblas または mahout を使用します。最近、clojure に「最適な」マトリックス ライブラリはありますか?
編集: バイナリ ファイルの読み取りは非常に近いです。この便利なnio wrapperのおかげで、メモリ マップされたバイト バッファーを短いワンライナーとして取得し、並べ替えることもできます。
(ns foo.core
(:require [clojure.java.io :as io])
(:require [nio.core :as nio])
(:import [java.nio ByteOrder]))
(def buffer (nio/mmap "/path/to/binaryfile"))
(class buffer) ;; java.nio.DirectByteBuffer
(.order buffer java.nio.ByteOrder/LITTLE_ENDIAN)
;; #<DirectByteBuffer java.nio.DirectByteBuffer[pos=0 lim=5760000 cap=5760000]>
ただし、中間 (def) ステップを実行せずに並べ替えを行うと、次のように失敗します。
(.order (nio/mmap f) java.nio.ByteOrder/LITTLE_ENDIAN)
;; clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException: Unable to resolve classname: MappedByteBuffer, compiling:(/Users/peter/Developer/foo/src/foo/core.clj:12)
;; at clojure.lang.Compiler.analyzeSeq (Compiler.java:6462)
;; clojure.lang.Compiler.analyze (Compiler.java:6262)
;; etc...
グローバル変数を定義せずに関数内で並べ替えられたバイトバッファを作成できるようにしたいのですが、今のところそれは好きではないようです。
また、順序を変更した後は、反復可能ではないように見えるため、DirectByteBuffer をどうするか完全にはわかりません。おそらく、このバッファ オブジェクトを (JBLAS マトリックスに) 読み込む残りの手順として、2 つ目の質問を作成します。
EDIT 2:元の質問があまりにも多くのものを組み合わせていると思うので、以下の回答を承認済みとしてマークしています。この残りの部分を理解したら、この ByteBuffer で始まり、JBLAS マトリックス (正しいデータ構造のように見える) に読み込まれる完全なコードでこの質問を更新しようとします。
誰かが興味を持っている場合に備えて、次のように適切に順序付けられたバイトバッファを返す関数を作成できました。
;; This works!
(defn readf [^String file]
(.order
(.map
(.getChannel
(java.io.RandomAccessFile. file "r"))
java.nio.channels.FileChannel$MapMode/READ_ONLY 0 (* 1200 1200))
java.nio.ByteOrder/LITTLE_ENDIAN))
私が見つけたnioラッパーは、これをかなり単純化/きれいにしているように見えますが、正しく使用していないか、何か問題があるように見えます. nio ラッパーを使用して調査結果を要約するには、次のようにします。
;; this works
(def buffer (nio/mmap "/bin/file"))
(def buffer (.order buffer java.nio.ByteOrder/LITTLE_ENDIAN))
(def buffer (.asFloatBuffer buffer))
;; this fails
(def buffer
(.asFloatBuffer
(.order
(nio/mmap "/bin/file")
java.nio.ByteOrder/LITTLE_ENDIAN)))
悲しいことに、これは別の日の clojure の謎、またはおそらく別の StackOverflow の質問です。