4

「myfile.dat」という名前に変更された MNIST 画像データベースのバイナリ ファイルがあります。これは、4 つの符号なし 32 ビット整数のセットと、それに続く符号なし 8 ビット整数のチェーンで構成されます。このファイルを読み取り、その内容を配列として保存したいと考えています。これが私のコードです:

file_id = fopen('myfile.dat', 'rb');
data = fread(file_id, 'int');
size(data)
class(data)

出力は次のとおりです。

ans =

    2502           1


ans =

double

(2502, 1) のサイズは予想どおりです。doubleしかし、データがであると指定したのに、なぜデータが であると教えてくれるのintでしょうか?

最初のいくつかの数値がどうあるべきかはわかっていますが、出力データは期待どおりではありません。も試しましたがint32、同じ問題が発生しますuintuint32

4

1 に答える 1

3

私たちのコメントによると、MATLAB が一度に 4 つの整数を読み取る方法は inlittle-endian形式であり、MNIST データベース ファイルのファイル形式は ですbig-endian。そのため、ファイルの最初の 4 バイトを読み取ると、バイトは0x00, 0x00, 0x08, 0x03期待どおりになります。ただし、MATLAB はこれを として読み取ります0x03, 0x08, 0x00, 0x00。これを整数に変換すると、実際には50855936必要でないものが得られます。

これを解決するためのハックは、一度に数バイトを読み取る必要がある場合uint8です。データ型を確実に指定する必要があります。これにより、各バイトが配列内の個別の要素に格納されます。次に、各バイトを指定された量だけビットシフトし、結果を合計することで、必要な数を計算できます。これは、データ ファイルの最初の数バイトに対して行う必要があります。

swapbytesまたは、コメントで述べた方法を使用することもできます。これにより、まったく同じことが得られます。タイプの1バイトを読み取るだけで、バイトがフォーマットuint32されるようにバイトの順序を入れ替えることができます。big-endianとしてデータを読み込む場合でもuint32、数値は MATLAB as に格納されるdoubleため、 に入る前に数値をキャストする必要があることに注意してくださいswapbytes

実際の画像データを取得したら、一度にnumRows x numColsバイト単位で読み取り、配列を変形して画像にすることができます。各画像を cell 配列に格納できます。これ以上苦労することなく、これがコードです。

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と等しくなるはずです。このコードの後に​​、 の要素が数字を MNIST データベースに格納します。を実行すると、はから までの任意の整数で、数字が表示されるはずです。2051, 28, 2810000kthimageCellArraykthimshow(imageCellArray{k});k110000

また、最後に 1 つ注意してください。行列データの読み込みは で行われるdoubleため、これをキャストしuint8て、画像がデータベースからのそのタイプのものになるようにする必要があります。

幸運を!

于 2014-06-09T21:00:02.700 に答える