1.导入MNIST的数据
在开始时我们需要导入MNIST的数据,MNIST的数据可以从github上进行下载Fashion-MNIST数据集,MNIST有四个数据集,分别如下:
train-images-idx3-ubyte.gz: training set images (9912422 bytes)
train-labels-idx1-ubyte.gz: training set labels (28881 bytes)
t10k-images-idx3-ubyte.gz: test set images (1648877 bytes)
t10k-labels-idx1-ubyte.gz: test set labels (4542 bytes)
前两个数据集是训练集,分别是训练集的图片和标签,后两个数据集是测试集,分别是测试集的图片和标签。一共有60000张训练集以及10000张测试集。共10种标签,以0~9数字形式给出,对应的描述如下:
在第一个数据集中,数据是以2进制给出,其中前128位不包含图片信息,它是关于数据集的一些说明。在图片数据集中(包括数据集和训练集),前面有4个信息,都是由32位二进制数表示,第一个信息是magic number图片位2049,第二个信息是样本数,第三个是行数,第四个是列数。描述如下:
其中训练集样本为60000个,测试集样本为10000个。
标签数据集,包含两个头文件信息:
第一个是magic number,第二个是样本个数。下面是matlab导入图片和标签的函数。
function images1=loadImage()
filename="train-images-idx3-ubyte";%将下载的数据解解压后去掉后缀名得到。
fid=fopen(filename,"rb");%打开训练集的图片数据集
A=fread(fid);%读取训练集中的数据,读取后,数据按照每个字节(8位二进制)转化成了十进制数。
images1=A(17:length(A));%从17位开始是图片信息
num=A(5:8);%第二个头文件,样本个数
row=A(9:12);%第三个头文件,行数
col=A(13:16);%第四个头文件,列数
%下面的操作是将32位二进制数转化为十进制
num=dec2hex(num);
row=dec2hex(row);
col=dec2hex(col);
num1=[];
row1=[];
col1=[];
for i=1:4
num1=[num1 num(i,:)];
row1=[row1,row(i,:)];
col1=[col1 col(i,:)];
end
num1=hex2dec(num1);
col1=hex2dec(col1);
row1=hex2dec(row1);
%将图片数据转化为矩阵形式。
images1=reshape(images1,row1,col1,num1);
images1=permute(images1,[2,1,3]);
fclose(fid);
end
为了验证转化的是否正确可以利用imwrite函数将矩阵转化为图片看看是否是数字如取第十个矩阵
a=images1(:,:,50);
imwrite(uint8(a),‘test.tif’)%输出文件名为test.tif。
%imwrite(mat2gray(a), ‘test.tif’);
Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N
上述得到的数据是 28 × 28 × 60000 28\times28\times60000 28×28×60000,需要转化为 60000 × ( 28 ∗ 28 ) 60000\times(28*28) 60000×(28∗28)的形式,以便带入模型中学习,并且需要将数据进行归一化处理
function [x,x_test,y,y_test]=getData()
%数据文件同函数在同一目录下
train_imgs="train-images-idx3-ubyte"; %训练集
train_labels="train-labels-idx1-ubyte"; %训练集标签
test_imgs="t10k-images-idx3-ubyte"; %测试集
test_labels="t10k-labels-idx1-ubyte"; %测试集标签
x=loadImage(train_imgs);
x_test=loadImage(test_imgs);
y=loadLabel(train_labels);
y_test=loadLabel(test_labels);
x=reshape(x,28*28,60000);
x=x/255.0; %归一化处理
x=x.'; %转置
x_test=reshape(x_test,28*28,10000);
x_test=x_test/255.0;
x_test=x_test.';
end
导入标签:
function labels1=loadLabel()
filename="train-labels-idx1-ubyte";
fid=fopen(filename,"rb");
A=fread(fid);
labels1=A(9:length(A));
fclose(fid);
end
2.softmax分类
2.1 softmax回归模型
o 1 = x 1 w 11 + x 2 w 21 + x 3 w 31 + x 4 w 41 + b 1 , o 2 = x 1 w 12 + x 2 w 22 + x 3 w 32 + x 4 w 42 + b 2 , o 3 = x 1 w 13 + x 2 w 23 + x 3 w 33 + x 4 w 43 + b 3 . o_1 = x_1 w_{11} + x_2 w_{21} + x_3 w_{31} + x_4 w_{41} + b_1,\\ o_2 = x_1 w_{12} + x_2 w_{22} + x_3 w_{32} + x_4 w_{42} + b_2,\\ o_3 = x_1 w_{13} + x_2 w_{23} + x_3 w_{33} + x_4 w_{43} + b_3. o1=x1w11+x2w21+x3w31+x4w41+b1,o2=x1w12+x2w22+x3w32+x4w42+b2,o3=x1w13+x2w23+x3w33+x4w43+b3.
转化为矩阵形式:
O = X W T + b O=XW^T+b O=XWT+b
假设一共有 n n n个样本,每个样本有 q q q 个特征, K K K个标签则:
X ∈ R n × q X\in{R^{n\times{q}}} X∈Rn×q 为输入样本
W ∈ R K × q W\in{R^{K\times{q}}} W∈RK×q 权重
d ∈ R 1 × K d\in{R^{1\times{K}}} d∈R1×K 偏置
O ∈ R n × k O\in{R^{n\times k}} O∈Rn×k
2.2 softmax损失函数
softmax使用交叉熵来计算损失函数
H ( y ( i ) , y ^ ( i ) ) = − ∑ j = 1 q y j ( i ) log y ^ j ( i ) H\left(\boldsymbol y^{(i)}, \boldsymbol {\hat y}^{(i)}\right ) = -\sum_{j=1}^q y_j^{(i)} \log \hat y_j^{(i)} H(y(i),y^(i))=−j=1∑qyj(i)logy^j(i)
ℓ ( Θ ) = 1 n ∑ i = 1 n H ( y ( i ) , y ^ ( i ) ) \ell(\boldsymbol{\Theta}) = \frac{1}{n} \sum_{i=1}^n H\left(\boldsymbol y^{(i)}, \boldsymbol {\hat y}^{(i)}\right ) ℓ(Θ)=n1i=1∑nH(y(i),y^(i))
其中 n n n 表示样本总数, i i i表示第 i i i 个样本, j j j 表示第 j j j 个输出。
y j ( i ) y_j^{(i)} yj(i) 表示第 i i i个样本的真实标签。只有样本 $i 标签为 j j j时, y j ( i ) = 1 y_j^{(i)}=1 yj(i)=1 ,其他标签位为0;
y ^ j ( i ) = e O i j ∑ k = 1 K e O i k = e ( X i W ( j , : ) T + b j ) ∑ k = 1 K e ( X i W ( k , : ) T + b k ) \hat y_j^{(i)}=\frac{e^{O_{ij}}}{\sum_{k=1}^{K}{e^{O_{ik}}}}=\frac{e^{(X_iW_{(j,:)}^{T}+b_j)}}{\sum_{k=1}^{K}{e^{(X_iW_{(k,:)}^{T}+b_k)}}} y^j(i)=∑k=1KeOikeOij=∑k=1Ke(XiW(k,:)T+bk)e(XiW(j,:)T+bj)
损失函数可以表示为:
ℓ ( Θ ) = − ( 1 / n ) ∑ i = 1 n ∑ j = 1 K y j ( i ) ln y ^ j ( i )