mnist 文件是如何通过以下代码读取的。
how does mnist file is read through following code.
我对阅读 MNIST 数据集有疑问。我了解了 MNIST 数据集的构建方式。但是,我不知道它是如何读取以下代码的。你们中的一些人可能认为 couts 的结果是显而易见的(我写了 values 作为注释)。但对我来说这没有意义,因为它使用相同的函数四次,输入相同,但每次都得到不同的输出。这怎么可能?如果我的问题有任何歧义,请告诉我。
谢谢。
代码开始:
typedef unsigned char BYTE;
int main()
{
...
FILE *fp = fopen("MNIST/train-images.idx3-ubyte", "rb");
// delcare function;
int magicNumber = readFlippedInteger(fp);
int numImages = readFlippedInteger(fp);
int numRows = readFlippedInteger(fp);
int numCols = readFlippedInteger(fp);
cout << magicNumber << endl; // 2051
cout << numImages << endl; // 60000
cout << numRows << endl; // 28
cout << numCols << endl; // 28
...
}
int readFlippedInteger(FILE *fp)
{
int ret = 0;
BYTE *temp;
temp = (BYTE*)(&ret);
fread(&temp[3], sizeof(BYTE), 1, fp);
fread(&temp[2], sizeof(BYTE), 1, fp);
fread(&temp[1], sizeof(BYTE), 1, fp);
fread(&temp[0], sizeof(BYTE), 1, fp);
return ret;
}
除非绝对必要,否则请不要混用 C 和 C++。潜在的混淆是通过文件为您调用 fread
"moves" 文件指针。正如@RetiredNinja 指出的那样,您一次将文件指针前进 4 个字节。这就是 "knows" 如何读取下一个值,即使您没有明确告诉它。您可以阅读所有关于文件指针的内容 here.
使用稍微更惯用的 C++ 的实现可能是
#include <fstream>
#include <iostream>
#include <algorithm>
int readFlippedInteger(std::istream &in) {
char temp[sizeof(int)];
in.read(temp, sizeof(int));
std::reverse(temp, temp+sizeof(int));
return *reinterpret_cast<int*>(temp);
}
int main() {
std::ifstream fin("MNIST/train-images.idx3-ubyte", std::ios::binary);
if (!fin) {
std::cerr << "Could not open file\n";
return -1;
}
// delcare function;
int magicNumber = readFlippedInteger(fin);
int numImages = readFlippedInteger(fin);
int numRows = readFlippedInteger(fin);
int numCols = readFlippedInteger(fin);
std::cout << magicNumber << std::endl // 2051
<< numImages << std::endl // 60000
<< numRows << std::endl // 28
<< numCols << std::endl; // 28
}
使用用户定义的流操纵器的实现留作 reader 的练习。
我对阅读 MNIST 数据集有疑问。我了解了 MNIST 数据集的构建方式。但是,我不知道它是如何读取以下代码的。你们中的一些人可能认为 couts 的结果是显而易见的(我写了 values 作为注释)。但对我来说这没有意义,因为它使用相同的函数四次,输入相同,但每次都得到不同的输出。这怎么可能?如果我的问题有任何歧义,请告诉我。
谢谢。
代码开始:
typedef unsigned char BYTE;
int main()
{
...
FILE *fp = fopen("MNIST/train-images.idx3-ubyte", "rb");
// delcare function;
int magicNumber = readFlippedInteger(fp);
int numImages = readFlippedInteger(fp);
int numRows = readFlippedInteger(fp);
int numCols = readFlippedInteger(fp);
cout << magicNumber << endl; // 2051
cout << numImages << endl; // 60000
cout << numRows << endl; // 28
cout << numCols << endl; // 28
...
}
int readFlippedInteger(FILE *fp)
{
int ret = 0;
BYTE *temp;
temp = (BYTE*)(&ret);
fread(&temp[3], sizeof(BYTE), 1, fp);
fread(&temp[2], sizeof(BYTE), 1, fp);
fread(&temp[1], sizeof(BYTE), 1, fp);
fread(&temp[0], sizeof(BYTE), 1, fp);
return ret;
}
除非绝对必要,否则请不要混用 C 和 C++。潜在的混淆是通过文件为您调用 fread
"moves" 文件指针。正如@RetiredNinja 指出的那样,您一次将文件指针前进 4 个字节。这就是 "knows" 如何读取下一个值,即使您没有明确告诉它。您可以阅读所有关于文件指针的内容 here.
使用稍微更惯用的 C++ 的实现可能是
#include <fstream>
#include <iostream>
#include <algorithm>
int readFlippedInteger(std::istream &in) {
char temp[sizeof(int)];
in.read(temp, sizeof(int));
std::reverse(temp, temp+sizeof(int));
return *reinterpret_cast<int*>(temp);
}
int main() {
std::ifstream fin("MNIST/train-images.idx3-ubyte", std::ios::binary);
if (!fin) {
std::cerr << "Could not open file\n";
return -1;
}
// delcare function;
int magicNumber = readFlippedInteger(fin);
int numImages = readFlippedInteger(fin);
int numRows = readFlippedInteger(fin);
int numCols = readFlippedInteger(fin);
std::cout << magicNumber << std::endl // 2051
<< numImages << std::endl // 60000
<< numRows << std::endl // 28
<< numCols << std::endl; // 28
}
使用用户定义的流操纵器的实现留作 reader 的练习。