根据我们的评论,MATLAB 一次读取 4 个整数的方式是little-endian
格式,而 MNIST 数据库文件的文件格式是big-endian
. 因此,当我们读入文件的前四个字节时,这些字节0x00, 0x00, 0x08, 0x03
与我们预期的一样。但是,MATLAB 会将其读取为0x03, 0x08, 0x00, 0x00
. 将其转换为整数时,我们实际上会得到50855936
不是我们想要的。
解决这个问题的一个技巧是,当我们需要一次读取几个字节时,我们需要确保我们指定了uint8
数据类型。这会将每个字节存储到数组中的单独元素中。然后,我们可以通过将每个字节移位指定的数量,然后对结果求和来计算我们需要的必要数字。我们需要对数据文件中的前几个字节执行此操作。
或者,我们可以使用swapbytes
您在评论中所述的方法,这将给我们完全相同的东西。您可以只读取 1 个uint32
类型的字节,然后交换字节的顺序以使字节符合big-endian
格式。您需要记住,即使您将数据读取为uint32
,该数字也将存储在 MATLAB 中,double
因此您需要在进入swapbytes
.
一旦我们得到实际的图像数据,我们可以一次读取numRows x numCols
字节,然后重塑数组,使其成为图像。我们可以将每个图像存储到一个元胞数组中。事不宜迟,代码如下。
clear all;
close all;
%//Open file
fid = fopen('t10k-images-idx3-ubyte', 'r');
%//Read in magic number
%//A = fread(fid, 4, 'uint8');
%//magicNumber = sum(bitshift(A', [24 16 8 0]));
%//OR
A = fread(fid, 1, 'uint32');
magicNumber = swapbytes(uint32(A));
%//Read in total number of images
%//A = fread(fid, 4, 'uint8');
%//totalImages = sum(bitshift(A', [24 16 8 0]));
%//OR
A = fread(fid, 1, 'uint32');
totalImages = swapbytes(uint32(A));
%//Read in number of rows
%//A = fread(fid, 4, 'uint8');
%//numRows = sum(bitshift(A', [24 16 8 0]));
%//OR
A = fread(fid, 1, 'uint32');
numRows = swapbytes(uint32(A));
%//Read in number of columns
%//A = fread(fid, 4, 'uint8');
%//numCols = sum(bitshift(A', [24 16 8 0]));
%// OR
A = fread(fid, 1, 'uint32');
numCols = swapbytes(uint32(A));
%//For each image, store into an individual cell
imageCellArray = cell(1, totalImages);
for k = 1 : totalImages
%//Read in numRows*numCols pixels at a time
A = fread(fid, numRows*numCols, 'uint8');
%//Reshape so that it becomes a matrix
%//We are actually reading this in column major format
%//so we need to transpose this at the end
imageCellArray{k} = reshape(uint8(A), numCols, numRows)';
end
%//Close the file
fclose(fid);
如果检查行数和列数(存储为numRows
, numCols
)、幻数(存储为magicNumber
)和图像总数(存储为totalImages
),这应该分别等于2051, 28, 28
和10000
。在这段代码之后, 的kth
元素imageCellArray
会将kth
数字存储在 MNIST 数据库中。如果你这样做imshow(imageCellArray{k});
,在到k
之间的任何整数,你应该能够看到一个数字。1
10000
另外,最后一点:由于矩阵数据的读取将在 中double
,我们需要将其转换uint8
为数据库中的图像属于该类型。
祝你好运!