1.MNIST數據集介紹
MNIST數據集是機器學習領域非常經典的一個數據集。MNIST數據集來自美國國家標準與技術研所,National Institute of Standard and Technology(NIST)。訓練集(training set)由來自250個不同人手寫的數字構成,其中50%是高中學生,50%來自人口普查局的工作人員。測試集(test set)也是同樣比例的手寫數字數據。它有60000個訓練樣本集和10000個測試樣本集,可以被用來訓練和測試關於手寫數字識別的模型。
地址:http://yann.lecun.com/exdb/mnist/
MNIST數據集中所有的圖片都是28*28像素的灰度手寫數字圖片,每張圖片都是一個數字。
2.mnist手寫體的未處理原始格式
它包含四個部分:
- train-images-idx3-ubyte.gz:訓練集圖像(9912422字節)
訓練集圖像,共60000張圖像
- train-labels-idx1-ubyte.gz:訓練集標籤(28881 字節)
訓練標籤集
- t10k-images-idx3-ubyte.gz:測試集圖像(1648877字節)
測試集圖像,共10000張圖像
- t10k-labels-idx1-ubyte.gz:測試集標籤(4542字節)
測試標籤集
下載完成後解壓如圖:
注:但是這些個文件怎麼用呢,參照網站上的說明,他們都是二進制文件,格式分別如下:
idx3代表數據是三維數據,ubyte代表數據儲存格式爲二進制格式。
2.mnist數據集的理解
MNIST 數據集中含有數字0-9的訓練數據集和數字0-9測試數據集兩種圖片,每張圖片都是灰度圖,位深度爲8。
首先該數據是以二進制存儲的,我們讀取的時候要以’rb’方式讀取,其次,真正的數據只有[value]這一項,其他的[type]等只是來描述的,並不真正在數據文件裏面,這樣寫只是在向我們解釋文件的結構。
3.利用MATLAB將MNIST數據集轉換爲.bmp圖片和txt文檔
train_image代碼如下:
clear all;
clc;
%讀取訓練圖片數據文件
[FileName,PathName] = uigetfile('*.*','選擇訓練圖片數據文件train-images.idx3-ubyte');
TrainFile = fullfile(PathName,FileName);
fid = fopen(TrainFile,'r');
a = fread(fid,16,'uint8');
MagicNum = ((a(1)*256+a(2))*256+a(3))*256+a(4);
ImageNum = ((a(5)*256+a(6))*256+a(7))*256+a(8);
ImageRow = ((a(9)*256+a(10))*256+a(11))*256+a(12);
ImageCol = ((a(13)*256+a(14))*256+a(15))*256+a(16);
if ((MagicNum~=2051)||(ImageNum~=60000))
error('不是 MNIST train-images.idx3-ubyte 文件!');
fclose(fid);
return;
end
savedirectory = uigetdir('','選擇保存訓練圖片路徑:');
h_w = waitbar(0,'請稍候,處理中>>');
for i=1:ImageNum
b = fread(fid,ImageRow*ImageCol,'uint8');
c = reshape(b,[ImageRow ImageCol]);
d = c';
e = 255-d;
e = uint8(e);
savepath = fullfile(savedirectory,['TrainImage_' num2str(i,'%05d') '.bmp']);
imwrite(e,savepath,'bmp');
waitbar(i/ImageNum);
end
fclose(fid);
close(h_w);
disp(['保存完畢']);
重點解釋一下:
a = fread(fid,16,'uint8');
MagicNum = ((a(1)*256+a(2))*256+a(3))*256+a(4);
ImageNum = ((a(5)*256+a(6))*256+a(7))*256+a(8);
ImageRow = ((a(9)*256+a(10))*256+a(11))*256+a(12);
ImageCol = ((a(13)*256+a(14))*256+a(15))*256+a(16);
這裏,由於matlab只能讀取8位無符號數,而MNIST中存儲的是32位無符號數,因此調用fread讀取後出來的是16個8位無符號數,×256表示將4個8位無符號數轉成1個32位無符號數。
√
如有需要,可以下載:https://download.csdn.net/download/didi_ya/12267896
4.拓展:利用python將MNIST數據集轉換爲.bmp圖片和txt文檔
train_image代碼如下:
# -*- coding: utf-8 -*-
import struct
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
#二進制的形式讀入
filename='E:/My Graduation project/mnist/train-images.idx3-ubyte'
binfile=open(filename,'rb')
buf=binfile.read()
index=0
magic,numImages,numRows,numColumns=struct.unpack_from('>IIII',buf,index)
index+=struct.calcsize('>IIII')
#將每張圖片按照格式存儲到對應位置
for image in range(0,numImages):
im=struct.unpack_from('>784B',buf,index)
index+=struct.calcsize('>784B')
#這裏注意 Image對象的dtype是uint8,需要轉換
im=np.array(im,dtype='uint8')
im=im.reshape(28,28)
im=Image.fromarray(im)
im.save('E:/My Graduation project/mnist/trainIMG/train_%s.bmp'%image,'bmp')#保存
有的時候需要用python處理二進制數據,比如存取文件等。這時候,可以使用python的struct模塊來完成。也可以用 struct來處理c語言中的結構體。
struct模塊中最重要的三個函數是pack(), unpack(), calcsize():
struct.pack(fmt,v1,v2,…):將v1,v2等參數的值進行一層包裝,包裝的方法由fmt指定。被包裝的參數必須嚴格符合fmt。最後返回一個包裝後的字符串。
struct.unpack(fmt,string):解包。返回一個由解包數據(string)得到的一個元組(tuple), 即使僅有一個數據也會被解包成元組。其中len(string) 必須等於 calcsize(fmt),這裏面涉及到了一個calcsize函數。
calcsize(fmt) :計算給定的格式(fmt)佔用多少字節的內存
如有需要,可以下載:https://download.csdn.net/download/didi_ya/12268945
5.將MNIST數據集轉化爲.mat格式文件
%% I.清空環境變量
close all;
clear all;
clc;
% 訓練與測試文件名
TrainImagesName='train-images.idx3-ubyte';
TrainLabelsName='train-labels.idx1-ubyte';
TestImagesName='t10k-images.idx3-ubyte';
TestLabelsName='t10k-labels.idx1-ubyte';
%讀取訓練圖片數據文件
PathName = 'E:\My Graduation project\mnist';
TrainImagesFile = fullfile(PathName, TrainImagesName);
TrainLabelsFile = fullfile(PathName, TrainLabelsName);
TestImagesFile = fullfile(PathName, TestImagesName);
TestLabelsFile = fullfile(PathName, TestLabelsName);
%% II.處理訓練圖片
fid = fopen(TrainImagesFile,'r');
a = fread(fid,16,'uint8');
%MagicNum = ((a(1)*256+a(2))*256+a(3))*256+a(4);
ImageNum = ((a(5)*256+a(6))*256+a(7))*256+a(8);
ImageRow = ((a(9)*256+a(10))*256+a(11))*256+a(12);
ImageCol = ((a(13)*256+a(14))*256+a(15))*256+a(16);
trainImages=zeros(ImageRow,ImageCol,ImageNum,'uint8');
for i=1:ImageNum
b = fread(fid,ImageRow*ImageCol,'uint8');
c = reshape(b,[ImageRow ImageCol]);
trainImages(:,:,i)=uint8(c');
disp(['正在處理訓練圖片,處理進度 (' , num2str(i) , '/' , num2str(ImageNum) ,')']);
end
fclose(fid);
%% III.處理測試圖片
fid = fopen(TestImagesFile,'r');
a = fread(fid,16,'uint8');
%MagicNum = ((a(1)*256+a(2))*256+a(3))*256+a(4);
ImageNum = ((a(5)*256+a(6))*256+a(7))*256+a(8);
ImageRow = ((a(9)*256+a(10))*256+a(11))*256+a(12);
ImageCol = ((a(13)*256+a(14))*256+a(15))*256+a(16);
testImages=zeros(ImageRow,ImageCol,ImageNum,'uint8');
for i=1:ImageNum
b = fread(fid,ImageRow*ImageCol,'uint8');
c = reshape(b,[ImageRow ImageCol]);
testImages(:,:,i)=uint8(c');
disp(['正在處理測試圖片,處理進度 (' , num2str(i) , '/' , num2str(ImageNum) ,')']);
end
fclose(fid);
%% IV.處理訓練標籤
fid = fopen(TrainLabelsFile,'r');
a = fread(fid,8,'uint8');
%MagicNum = ((a(1)*256+a(2))*256+a(3))*256+a(4);
ImageNum = ((a(5)*256+a(6))*256+a(7))*256+a(8);
%trainLabels=zeros(ImageNum,1);
b = fread(fid,ImageNum,'uint8');
trainLabels=uint8(b);
disp('訓練標籤處理完成');
fclose(fid);
%% V.處理測試標籤
fid = fopen(TestLabelsFile,'r');
a = fread(fid,8,'uint8');
%MagicNum = ((a(1)*256+a(2))*256+a(3))*256+a(4);
ImageNum = ((a(5)*256+a(6))*256+a(7))*256+a(8);
%testLabels=zeros(ImageNum,1);
b = fread(fid,ImageNum,'uint8');
testLabels=uint8(b);
disp('測試標籤處理完成' );
fclose(fid);
% 保存提取的數據
save('mnist.mat','trainImages','trainLabels','testImages','testLabels')
通過證明,發現兩種方法基本正確,無任何問題。
完成√