2016-09-19 2 views
2

Я пытаюсь выполнить код, приведенный в ссылкеКак загрузить в MNIST цифры и данные метки в MATLAB?

https://github.com/bd622/DiscretHashing

Discrete Hashing является методом снижения размерности, который используется на приближенном ближайший поиске соседа. Я хочу загрузить в реализацию в базе данных MNIST, которая доступна в http://yann.lecun.com/exdb/mnist/. Я извлек файлы из их сжатого формата gz.

ПРОБЛЕМА 1:

Используя решение для чтения базы данных MNIST представлены в Reading MNIST Image Database binary file in MATLAB

Я получаю следующее сообщение об ошибке:

Error using fread 
Invalid file identifier. Use fopen to generate a valid file identifier. 

Error in Reading (line 7) 
A = fread(fid, 1, 'uint32'); 

Вот код:

clear all; 
close all; 

%//Open file 
fid = fopen('t10k-images-idx3-ubyte', 'r'); 

A = fread(fid, 1, 'uint32'); 
magicNumber = 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); 

UPDATE: Задача 1 решена и пересмотренный код

clear all; 
close all; 

%//Open file 
fid = fopen('t10k-images.idx3-ubyte', 'r'); 

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 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); 

ПРОБЛЕМА 2:

Я не могу понять, как применить 4 файлов MNIST в коде. Код содержит переменные

traindata = double(traindata); 
testdata = double(testdata); 

Как подготовить базу данных MNIST, чтобы я мог применить к реализации?

UPDATE: Я реализовал решение, но я получаю эту ошибку

Error using fread 
Invalid file identifier. Use fopen to generate a valid file identifier. 

Error in mnist_parse (line 11) 
A = fread(fid1, 1, 'uint32'); 

Эти файлы

demo.m% это главный файл, который вызывает функцию для чтения в данных MNIST

clear all 
clc 
[Trainimages, Trainlabels] = mnist_parse('C:\Users\Desktop\MNIST\train-images-idx3-ubyte', 'C:\Users\Desktop\MNIST\train-labels-idx1-ubyte'); 

[Testimages, Testlabels] = mnist_parse('t10k-images-idx3-ubyte', 't10k-labels-idx1-ubyte'); 

k=5; 
digit = images(:,:,k); 
lbl = label(k); 

function [images, labels] = mnist_parse(path_to_digits, path_to_labels) 

% Open files 
fid1 = fopen(path_to_digits, 'r'); 

% The labels file 
fid2 = fopen(path_to_labels, 'r'); 

% Read in magic numbers for both files 
A = fread(fid1, 1, 'uint32'); 
magicNumber1 = swapbytes(uint32(A)); % Should be 2051 
fprintf('Magic Number - Images: %d\n', magicNumber1); 

A = fread(fid2, 1, 'uint32'); 
magicNumber2 = swapbytes(uint32(A)); % Should be 2049 
fprintf('Magic Number - Labels: %d\n', magicNumber2); 

% Read in total number of images 
% Ensure that this number matches with the labels file 
A = fread(fid1, 1, 'uint32'); 
totalImages = swapbytes(uint32(A)); 
A = fread(fid2, 1, 'uint32'); 
if totalImages ~= swapbytes(uint32(A)) 
    error('Total number of images read from images and labels files are not the same'); 
end 
fprintf('Total number of images: %d\n', totalImages); 

% Read in number of rows 
A = fread(fid1, 1, 'uint32'); 
numRows = swapbytes(uint32(A)); 

% Read in number of columns 
A = fread(fid1, 1, 'uint32'); 
numCols = swapbytes(uint32(A)); 

fprintf('Dimensions of each digit: %d x %d\n', numRows, numCols); 

% For each image, store into an individual slice 
images = zeros(numRows, numCols, totalImages, 'uint8'); 
for k = 1 : totalImages 
    % Read in numRows*numCols pixels at a time 
    A = fread(fid1, 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 
    images(:,:,k) = reshape(uint8(A), numCols, numRows).'; 
end 

% Read in the labels 
labels = fread(fid2, totalImages, 'uint8'); 

% Close the files 
fclose(fid1); 
fclose(fid2); 

end 
+1

Ошибка довольно понятная, вы использовали 'fopen' для недопустимого имени файла. Убедитесь, что 't10k-images-idx3-ubyte'' является * полным * именем файла и находится в вашем текущем пути MATLAB. В противном случае убедитесь, что это полный * полный путь к файлу, который вы хотите открыть. – excaza

+0

@excaza: решена первая проблема и ошибка из-за операции чтения файлов. В названии файла действительно была проблема. Но теперь я понятия не имею, как использовать базу данных, я не понимаю, как использовать эти 4 файла. Я считаю, что переменная traindata будет содержать файл train-images.idx3-ubyte. Тогда какой из них будет testdata, а затем, как я должен использовать файлы базы данных с двумя метками? Пожалуйста, помогите – SKM

+0

@rayryeng: Не могли бы вы сообщить мне, почему я получаю сообщение об ошибке из-за операции чтения файлов, когда я выполнил ваш ответ? Я включил новые обновления в вопрос. Спасибо за ваше время и силы. – SKM

ответ

3

Я автор оригинала метода № 1, о котором вы говорили. Процесс чтения в учебных данных и тестовых меток довольно прост. С точки зрения чтения в изображениях, код, который вы показали выше, отлично читает файлы и находится в формате массива ячеек. Тем не менее, вы отсутствуете в количестве файлов, строк и столбцов , а внутри файла находится. Обратите внимание, что формат MNIST для этого файла выглядит следующим образом. Левая колонка смещения в байтах вы ссылаетесь относительно начала:

[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 

Первые четыре байта магического числа: 2051, чтобы убедиться, что вы читаете в файле правильно. Следующие четыре байта обозначают общее количество изображений, затем следующие четыре байта являются строками, и, наконец, следующие четыре байта являются столбцами. Должно быть 60000 изображений размером 28 строк на 28 столбцов. После этого пиксели чередуются в основном формате строки, поэтому вам нужно перебирать серию из 28 x 28 пикселей и сохранять их.В этом случае я сохранил их в массиве ячеек, и каждый элемент в этом массиве ячеек будет иметь одну цифру. Тот же формат также используется для тестовых данных, но вместо этого есть 10000 изображений.

Что касается фактических меток, это примерно тот же формат, но есть некоторые незначительные отличия:

[offset] [type]   [value]   [description] 
0000  32 bit integer 0x00000801(2049) magic number (MSB first) 
0004  32 bit integer 60000   number of items 
0008  unsigned byte ??    label 
0009  unsigned byte ??    label 
........ 
xxxx  unsigned byte ??    label 

Первые четыре байта магическое число: 2049, то второй набор из четырех байт говорит вам, как существует много меток и, наконец, для каждой соответствующей цифры в наборе данных имеется ровно 1 байт. Тестируемые данные также имеют тот же формат, но есть 10000 меток. Таким образом, как только вы прочтете необходимые данные в наборе меток, вам понадобится только один вызов fread и убедитесь, что данные беззнаковое 8-разрядное целое число читается в остальных ярлыках.

Теперь причина, почему вы должны использовать swapbytes потому, что MATLAB будет читать данные в прямом порядке байт, а это означает, что младшие байты из набора байт считываются первым. Вы используете swapbytes, чтобы упорядочить этот заказ, когда закончите.

Как таковой, я изменил этот код для вас, так что это фактическая функция, которая принимает набор из двух строк: полный путь к файлу изображения цифр и полный путь к цифрам. Я также изменил код, чтобы изображения представляли собой трехмерную числовую матрицу, а не массив ячеек для более быстрой обработки. Обратите внимание, что когда вы начинаете считывать фактические данные изображения, каждый пиксель представляет собой неподписанное 8-битовое целое число, поэтому нет необходимости делать замену байтов. Это было необходимо только при чтении в нескольких байт в одном fread вызова:

function [images, labels] = mnist_parse(path_to_digits, path_to_labels) 

% Open files 
fid1 = fopen(path_to_digits, 'r'); 

% The labels file 
fid2 = fopen(path_to_labels, 'r'); 

% Read in magic numbers for both files 
A = fread(fid1, 1, 'uint32'); 
magicNumber1 = swapbytes(uint32(A)); % Should be 2051 
fprintf('Magic Number - Images: %d\n', magicNumber1); 

A = fread(fid2, 1, 'uint32'); 
magicNumber2 = swapbytes(uint32(A)); % Should be 2049 
fprintf('Magic Number - Labels: %d\n', magicNumber2); 

% Read in total number of images 
% Ensure that this number matches with the labels file 
A = fread(fid1, 1, 'uint32'); 
totalImages = swapbytes(uint32(A)); 
A = fread(fid2, 1, 'uint32'); 
if totalImages ~= swapbytes(uint32(A)) 
    error('Total number of images read from images and labels files are not the same'); 
end 
fprintf('Total number of images: %d\n', totalImages); 

% Read in number of rows 
A = fread(fid1, 1, 'uint32'); 
numRows = swapbytes(uint32(A)); 

% Read in number of columns 
A = fread(fid1, 1, 'uint32'); 
numCols = swapbytes(uint32(A)); 

fprintf('Dimensions of each digit: %d x %d\n', numRows, numCols); 

% For each image, store into an individual slice 
images = zeros(numRows, numCols, totalImages, 'uint8'); 
for k = 1 : totalImages 
    % Read in numRows*numCols pixels at a time 
    A = fread(fid1, 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 
    images(:,:,k) = reshape(uint8(A), numCols, numRows).'; 
end 

% Read in the labels 
labels = fread(fid2, totalImages, 'uint8'); 

% Close the files 
fclose(fid1); 
fclose(fid2); 

end 

Чтобы вызвать эту функцию, просто указать путь как к файлу изображения и файл меток. Предполагая, что вы работаете этот файл в том же каталоге, где находятся файлы, вы могли бы сделать одно из следующих действий для подготовки изображений:

[images, labels] = mnist_parse('train-images-idx3-ubyte', 'train-labels-idx1-ubyte'); 

Кроме того, вы должны сделать следующее для тестовых изображений:

[images, labels] = mnist_parse('t10k-images-idx3-ubyte', 't10k-labels-idx1-ubyte'); 

Чтобы получить доступ к k ю цифру, вы бы просто сделать:

digit = images(:,:,k); 

соответствующая метка для k го разряда будет:

lbl = label(k); 

Чтобы, наконец, получить эти данные в формат, который является приемлемым для этого кода, который я видел на Github, они предполагают, что строки соответствуют примерам обучения и столбцы соответствуют особенностям. Если вы хотите иметь этот формат, просто измените данные так, чтобы пиксели изображения были распределены по столбцам.

Таким образом, просто сделать это:

[trainingdata, traingnd] = mnist_parse('train-images-idx3-ubyte', 'train-labels-idx1-ubyte'); 
trainingdata = double(reshape(trainingdata, size(trainingdata,1)*size(trainingdata,2), []).'); 
traingnd = double(traingnd); 

[testdata, testgnd] = mnist_parse('t10k-images-idx3-ubyte', 't10k-labels-idx1-ubyte'); 
testdata = double(reshape(testdata, size(testdata,1)*size(testdata_data,2), []).'); 
testgnd = double(testgnd); 

выше использует одни и те же переменные, как в сценарии, так что вы должны быть в состоянии включить это и он должен работать. Вторая строка преобразует матрицу так, чтобы каждая цифра находилась в столбце, но нам нужно перенести это так, чтобы каждая цифра находилась в столбце. Нам также нужно указать double, так как это делает код Github. Та же логика применяется к тестовым данным.Также обратите внимание на то, что я явно наложил метки обучения и тестирования на double, чтобы обеспечить максимальную совместимость с любыми алгоритмами, которые вы решили использовать для этих данных.


Счастливый взлом цифр!

+0

Большое вам спасибо за подробное объяснение. Я не мог войти в свою учетную запись Stackoverflow из-за некоторого сбоя, поэтому я не мог проверить ваш ответ. Итак, я запустил ваш код шаг за шагом, но Matlab выдает ошибку: Ошибка при использовании fread Недопустимый идентификатор файла. Используйте fopen для генерации допустимого идентификатора файла. Ошибка в mnist_parse (строка 11) A = fread (fid1, 1, 'uint32'); Ошибка в демонстрации (строка 3) [Тренировки, Trainlabels] = mnist_parse ('C: \ Users \ Desktop \ MNIST \ train-images-idx3-ubyte', 'C: \ Users \ Desktop \ MNIST \ train-labels -idx – SKM

+0

Исходя из вашего наблюдения, что я пропустил чтение в количестве totalImages, строк и столбцов, я исправил эту часть. Я исправил это в своем Вопросе. Однако я не знаю, как уменьшить эту новую ошибку, которая появляется, когда я реализовал ваше решение. Я не использовал последний параграф кода, который должен применяться к программе в GitHub. Не могли бы вы сообщить мне, что я должен делать, чтобы ошибка исчезла? – SKM

+0

Это не работает, потому что ваш путь неверен Между пользователями и Desktop на вашем пути должно быть ваше имя пользователя. Такой каталог отсутствует. 'Fopen' работает, когда был предоставлен допустимый путь для файла, и вы этого не сделали. Убедитесь, что путь t o ваш файл абсолютно прав ... Или поместите скрипт в тот же каталог, что и данные MNIST, и используйте локальные пути. – rayryeng