我能做到;我只是不知道为什么会这样。使用我从 http://yann.lecun.com/exdb/mnist/ 下载的 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 .
翻译方法
int Read(BinaryReader b, int i)
{
int res = 0;
while (i-- > 0)
{
res <<= 8;
res |= b.ReadByte()
}
return res;
}
进入 F# 给出
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)
的结果,与评论中的值一致第一个代码片段。
我不明白为什么会这样。按位或运算符上的所有这些移位和折叠是什么?为什么我不能只使用 BitConverter.ToInt()
来代替?
最佳答案
标准库方法IPAddress.NetworkToHostOrder(Int32)从网络顺序转换 int
时考虑执行平台的字节顺序。后者按照标准惯例是大端。由于 MNIST 文件遵循约定并且是 big-endian,因此以下一对标准库方法将作为 readInt
函数的 endian-agnostic 替代品:
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
关于io - 使用 F# 读取 MNIST 数据集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19370314/