개인적으로 텐서플로우를 이용해보고 싶었지만 이런저런 이유로
MATLAB의 예제부터 진행을 해보도록 한다.
 MNIST Example 
% Data load
digitDatasetPath = fullfile(matlabroot,'toolbox','nnet','nndemos', ...
    'nndatasets','DigitDataset');
% Create imageData object
imds = imageDatastore(digitDatasetPath, ...
    'IncludeSubfolders',true,'LabelSource','foldernames');
일단 실험에 쓸 데이터가 필요하다. 저 fullfile이라는 함수는 해당인자들을 순차적으로 타고 들어가는 폴더 경로를 반환한다.
fullfile이 반환하는 경로에 가보니 'digitTest'와 'digitTrain'이라는 excel파일과 폴더'0,1, ... 9' 가 존재했다.
imageDatastore은 이미지들을 저장할 객체를 생성해주는데 굉장히 많은 일을 한번에 해주는 함수다.
digitDatasetPath 하위폴더의 image들을 저장하는데 폴더이름과 같은 이름의 label을 달아준다. 폴더 이름이 '0,1, ..., 9'이기 때문에 
각 이미지에 0 부터 9 까지의 label이 달린다.
figure;
perm = randperm(10000,20);
for i = 1:20
    subplot(4,5,i);
    imshow(imds.Files{perm(i)});
end
그 이후에 sample로 몇개의 이미지들을 가시화하는데 사실 큰 의미는 없는듯하다.
figure창을 4x5로 분할하고 분할된 영역에 random한 20개의 파일을 띄운다.
labelCount = countEachLabel(imds)
img = readimage(imds,1);
size(img)
그리고 이미지저장소 객체에서 각 label에 해당하는 이미지가 몇개인지 센다. 해당 예제에는 각 1000개씩 존재한다.
그 후로 첫번째 이미지를 저장하고 사이즈(28x28)를 출력하는데 이것도 별 의미 없는 것 같다.
numTrainFiles = 750;
[imdsTrain,imdsValidation] = splitEachLabel(imds,numTrainFiles,'randomize');
그 후 전체 데이터들 중 train 데이터와 validation 데이터를 분리한나.
750개의 기존 imds에서 다시 두개의 이미지저장소 객체를 만드는데, train 저장소엔 각 레이블마다 750개의 이미지를 저장하고
validation 저장소에 나머지 데이터를 저장한다. 
기존에 주어진 코드는 75 : 25 로 Train : Validation 셋을 나누는데 보통 train이 더 적지 않나??
3:7로 줄였더니 정확도가 내려간다. 
layers = [
    imageInputLayer([28 28 1])
    
    convolution2dLayer(3,8,'Padding','same')
    batchNormalizationLayer
    reluLayer
    
    maxPooling2dLayer(2,'Stride',2)
    
    convolution2dLayer(3,16,'Padding','same')
    batchNormalizationLayer
    reluLayer
    
    maxPooling2dLayer(2,'Stride',2)
    
    convolution2dLayer(3,32,'Padding','same')
    batchNormalizationLayer
    reluLayer
    
    fullyConnectedLayer(10)
    softmaxLayer
    classificationLayer];
그리고 드디어 네트워크의 구조를 만들어주는데 대체 문법이 이상한건지 콤마도 없고..
그래도 한개씩 보자.
inputlayer : 28x28 이미지이고 1채널이다. gray scale이란 뜻이겠지. 
convolution2dLater : filter size : 3x3, filter num : 8, padding을 이용해 output size를 input과 같게 만듬 
batchNormalizationLayer :모르겠다. 나중에 보자. 
ReLU Layer : activation function으로 RELU를 쓴다. 
maxPooling2dLayer : down-sampling을 위해 max pooling을 이용한다. size는 2x2
fullyConnectedLayer : output 10 짜리 fully connected layer.
options = trainingOptions('sgdm', ...
    'InitialLearnRate',0.01, ...
    'MaxEpochs',4, ...
    'Shuffle','every-epoch', ...
    'ValidationData',imdsValidation, ...
    'ValidationFrequency',30, ...
    'Verbose',false, ...
    'Plots','training-progress');
다음으로는 학습을 어떻게 진행할지 옵션을 준다. 
net = trainNetwork(imdsTrain,layers,options);
YPred = classify(net,imdsValidation);
YValidation = imdsValidation.Labels;
accuracy = sum(YPred == YValidation)/numel(YValidation) 
마침내 학습을 하고 학습된 모델을 이용해 classification을 진행한다.
만약 최적화를 한다고 치면 trainNetwork, classify를 직접 까보거나 대체하기 위한 함수를 만들 것이다.
정확도를 올리기 위해서는 네트워크의 구조를 변경해야 할 것이다.
예제를 한번 봤는데 실제로 의미있는 부분은 함수로 전부 가려져있다.
좀더 봐야할 듯 하다.