2013-10-14 5 views
2

이렇게 할 수 있습니다. 나는 왜 그것이 작동하는지 모른다. 내가 http://yann.lecun.com/exdb/mnist/에서 다운로드 MNIST 데이터베이스 및 해당 페이지의 하단에있는 지침을 사용하여, 나는 (아직 미완성 같이) 쉬운 부분이었다 F #을 사용하여 MNIST 데이터 세트 읽기 #

// TRAINING SET IMAGE FILE (train-images-idx3-ubyte): 
// [offset] [type]   [value]   [description] 
// 0000  32 bit integer 0x00000803(2051) magic number 
// 0004  32 bit integer 60000   number of images 
// 0008  32 bit integer 28    number of rows 
// 0012  32 bit integer 28    number of columns 
// 0016  unsigned byte ??    pixel 
// 0017  unsigned byte ??    pixel 
// ........ 
// xxxx  unsigned byte ??    pixel 

// TEST SET IMAGE FILE (t10k-images-idx3-ubyte): 
// [offset] [type]   [value]   [description] 
// 0000  32 bit integer 0x00000803(2051) magic number 
// 0004  32 bit integer 10000   number of images 
// 0008  32 bit integer 28    number of rows 
// 0012  32 bit integer 28    number of columns 
// 0016  unsigned byte ??    pixel 
// 0017  unsigned byte ??    pixel 
// ........ 
// xxxx  unsigned byte ??    pixel 
let loadMnistImage file = 
    use stream = File.Open(file, FileMode.Open) 
    use reader = new BinaryReader(stream) 
    let magicNumber = readInt(reader) 
    let nImages = readInt(reader) 
    let nRows = readInt(reader) 
    let nColumns = readInt(reader) 
    (magicNumber, nImages, nRows, nColumns);; 

방법

을 썼다. 어려운 부분은 readInt 함수의 형식입니다. 나는 단지 BitConverter.ToInt()을 사용할 수 없다. 나는이 페이지에서 대답을 발견했다 : https://code.google.com/p/aguaviva-libs/source/browse/c%23/NeuronalNetwork/sets/HandWriting.cs?spec=svn9ffdf444c6317be049572cea59170602c8f28bea&r=9ffdf444c6317be049572cea59170602c8f28bea. F 번호에있어서

int Read(BinaryReader b, int i) 
{ 
    int res = 0; 

    while (i-- > 0) 
    { 
     res <<= 8; 
     res |= b.ReadByte() 
    } 
    return res; 
} 

번역

let readInt (b : BinaryReader) = 
    [1..4] |> List.fold (fun res item -> (res <<< 8) ||| (int)(b.ReadByte())) 0 

(i = 4 가정) 준다. 이 작품 : F # 대화 형, 최초의 코드에서 주석의 값과 일치 라인

loadMnistImage @"Data\t10k-images.idx3-ubyte" 
loadMnistImage @"Data\train-images.idx3-ubyte" 

각각 (2051, 10000, 28, 28)(2051, 60000, 28, 28)의 결과를 제공합니다.

내가 이해가 가지 않는 이유는 그것이 작동하는 이유입니다. bitwise 또는 연산자에 대한 모든 비트 이동 및 접기는 무엇입니까? 왜 대신 BitConverter.ToInt()을 사용할 수 없습니까?

+2

사용한 방법은 코드를 실행중인 시스템의 엔디 언과는 별도입니다. Bitconverter를 사용하면 엔디안에 따라 결과가 달라집니다. –

+0

감사합니다. 아직이 작업을 수행 할 수있는 기본 제공 방법이 없습니까? –

+0

나는 내장 된 방법이 존재하지 않는다고 생각합니다. –

답변

2

답변 작성으로

로 내 댓글을 게시, 방법은 코드가 실행되는 시스템의 엔디안에 관계없이 작동합니다.

표준 라이브러리 메서드는 모두 코드를 실행하는 컴퓨터의 엔디안에 따라 결과를 반환합니다. 이렇게하면 예상 한 것과 다른 결과가 발생할 수 있습니다 (상대 바이트 순서가 반대로 됨).

3

표준 라이브러리 방법 IPAddress.NetworkToHostOrder(Int32)은 네트워크 순서에서 int을 변환 할 때 실행 플랫폼의 엔디안을 고려합니다. 표준 규칙에 의한 후자는 빅 엔디안입니다. MNIST 파일이 규칙을 따라 표준 라이브러리 방법의 다음 쌍 당신의 readInt로서 기능 엔디안에 얽매이지 대체 할 것입니다 빅 엔디안으로 :

let readInt (reader: System.IO.BinaryReader) = 
    reader.ReadInt32() |> System.Net.IPAddress.NetworkToHostOrder 

등가하지만, 더 자세한 BitConverter을 포함하는 변형 될

let readInt (reader: System.IO.BinaryReader) = 
    (reader.ReadBytes(4),0) 
    |> System.BitCoverter.ToInt32 
    |> System.Net.IPAddress.NetworkToHostOrder 
+0

감사합니다 Gene - 그건 매우 흥미 롭습니다. –