(matlab) MLP с relu и softmax не работает с мини-пакетом SGD и дает аналогичные прогнозы в наборе данных MNIST.

Я реализовал многослойный персептрон с 1 скрытым слоем в наборе данных MNIST. Функция активации в скрытом слое — дырявая (0,01) ReLu, а выходной слой имеет функцию активации softmax. Метод обучения — мини-пакетный SGD. Структура сети 784*30*10. Проблема в том, что я обнаружил, что прогнозы, сделанные сетью для каждой входной выборки, очень похожи. Это означает, что модель всегда хотела бы думать, что изображение представляет собой какое-то определенное число. Спасибо @Lemm Ras за указание на проблему несоответствия данных метки в предыдущей функции data_shuffle, которая теперь исправлена. Но после некоторого пакетного обучения я обнаружил, что прогнозы все еще похожи: введите описание изображения здесь Это сбивает с толку.

Другая проблема заключается в том, что значение обновления слишком мало по сравнению с исходным весом, в коде MLP я добавляю переменные «cc» и «dd», чтобы записать соотношение между их weight_update и весом,

cc=W_OUTPUT_Update./W_OUTPUT;
dd=W_MLP_Update./W_MLP;

Во время отладки величина cc равна 10^-4 (0,0001), а dd также равна 10^-4. Это может быть причиной того, что точность кажется незначительной.

После нескольких дней отладки. Я понятия не имею, почему это происходит и как это решить, это заставило меня застрять на одну неделю. Может кто-то мне помочь, пожалуйста? На скриншоте значение A2 после функции softmax.

[dimension, images, labels, labels_matrix, train_amount, test_labels_matrix, test_images, test_labels, test_amount] = load_mnist_data(); %initialize str
    images=images(:,1:10000); % for debugging, get part of whole data set
    labels=labels(1:10000,1);
    labels_matrix=labels_matrix(:,1:10000);
    test_images=test_images(:,1:500);
    test_labels=test_labels(1:500,1);
    train_amount=10000;
    test_amount=500;
    % initialize the structure
    [ W_MAD, W_MLP, W_OUTPUT] = initialize_structure(dimension, train_amount, test_amount);



epoch=100;
correct_rate=zeros(1,epoch); %record testing accuracy
corr=zeros(1,epoch);    %record training accuracy
lr=0.2;
lamda=0;
batch_size=50;


for i=1:epoch
    sprintf('MLP in iteration %d over %d', i, epoch)
    %shuffle data
    [labels_shuffled labels_matrix_shuffled images_shuffled]=shuffle_data(labels, labels_matrix,images);
     [ cor, W_MLP, W_OUTPUT ] = train_mlp_relu(lr, leaky, lamda, momentum_gamma, batch_size,W_MLP, W_OUTPUT, W_MAD, power, images_shuffled, train_amount, labels_shuffled, labels_matrix_shuffled);

    corr(i)=cor/train_amount;
    % test 
    correct_rate(i) = structure_test(  W_MAD, W_MLP, W_OUTPUT, test_images, test_labels, test_amount );
end

% plot results
plot(1:epoch,correct_rate);

Вот функция обучения MLP, пожалуйста, игнорируйте параметр регуляризации L2 лямбда, который в настоящее время установлен как 0.

%MLP with batch size batch_size
    cor=0;
    %leaky=(1/batch_size);
    leaky=0.001;
    for i=1:train_amount/batch_size
        batch_images=images(:,batch_size*(i-1)+1:batch_size*i);
        batch_labels=labels_matrix(:,batch_size*(i-1)+1:batch_size*i);
        %from MAD to MLP

        V1=W_MLP'*batch_images;
        V1(1,:)=1; %set bias unit as 1
        V1_dirivative=ones(size(V1));
        V1_dirivative(find(V1<0))=leaky;
        A1=relu(V1,leaky); % A stands for activation
        V2=W_OUTPUT'* A1;
        A2=softmax(V2);
        %write these scope control codes into functions.
        %train error
        [val idx]=max(A2);
        idx=idx-1; %because  index(idx) for matrix vaires from 1 to 10 while label varies from 0 to 9.


        res=labels(batch_size*(i-1)+1:batch_size*i)-idx';
        cor=cor+sum(res(:)==0);
        %softmax loss, due to relu applied nodes that has
        %contribution to activate neurons has gradient 1; while <0 nodes
        %has no contribution
        delta_softmax=-(1/batch_size)*(batch_labels-A2);
        delta_output=W_OUTPUT*delta_softmax.*V1_dirivative;
        %update
        W_OUTPUT_Update=lr*(1/batch_size)*A1*delta_softmax'+lamda*W_OUTPUT;

        cc=W_OUTPUT_Update./W_OUTPUT;


        W_MLP_Update=lr*(1/batch_size)*batch_images*delta_output'+lamda*W_MLP;       

        dd=W_MLP_Update./W_MLP;

        k=mean(A2,2);
        W_OUTPUT=W_OUTPUT-W_OUTPUT_Update;
        W_MLP=W_MLP-W_MLP_Update;
    end
end

Вот функция softmax:

function [ val ] = softmax( val )
    val=exp(val);
    val=val./repmat(sum(val),10,1);
end

labels_matrix — это целевая выходная матрица для A2, созданная как:

   labels_matrix=full(sparse(labels+1,1:train_amount,1));
   test_labels_matrix=full(sparse(test_labels+1,1:test_amount,1));  

И Релу:

function [ val ] = relu( val,leaky )
    val(find(val<0))=leaky*val(find(val<0));
end

Перетасовка данных

    %this version is wrong, due to it only shuffles label and data without doing the same shuffling on the 'labels_matrix' which is used to calculate MLP's delta in output layer. It destroyed the link between data and label.

%    function [ label, data ] = shuffle_data( label, data )
%        [row column]=size(data);
%        array=randperm(column);
%        data=data(:,array);
%        label=label(array);
%        %if shuffle respect to row then use the code below
%        %data=data(randperm(row),:);
%    end

function [ label, label_matrix, data ] = shuffle_data( label, label_matrix, data  )
    [row column]=size(data);
    array=randperm(column);
    data=data(:,array);
    label=label(array);
    label_matrix=label_matrix(:, array);
    %if shuffle respect to row then use the code below
    %data=data(randperm(row),:);
end

Загрузка данных:

function [ dimension, images, labels, labels_matrix, train_amount, test_labels_matrix, test_images, test_labels, test_amount] = load_mnist_data()
    %%load training and testing data, labels
        data_location='C:\Users\yz39g15\Documents\MATLAB\common\mnist test\for the report/modify/train-images.idx3-ubyte';
        label_location='C:\Users\yz39g15\Documents\MATLAB\common\mnist test\for the report/modify/train-labels.idx1-ubyte';
        test_data_location='C:\Users\yz39g15\Documents\MATLAB\common\mnist test\for the report/modify/t10k-images.idx3-ubyte';
        test_label_location='C:\Users\yz39g15\Documents\MATLAB\common\mnist test\for the report/modify/t10k-labels.idx1-ubyte';
        images = loadMNISTImages(data_location);
        labels = loadMNISTLabels(label_location);
        test_images=loadMNISTImages(test_data_location);
        test_labels=loadMNISTLabels(test_label_location);
    %%data centralization
        [dimension train_amount]=size(images);
        [dimension test_amount]=size(test_images);


    %%complete normalization
    %%transform labels from index to matrix in order to apply square loss function in output layer
        labels_matrix=full(sparse(labels+1,1:train_amount,1));
        test_labels_matrix=full(sparse(test_labels+1,1:test_amount,1));        
end

person Ludwig Zhou    schedule 12.08.2016    source источник
comment
Насчет соотношения, пробовали ли вы увеличить скорость обучения?   -  person Lemm Ras    schedule 12.08.2016
comment
Да, я пробовал разную величину от 0,01,0,1 до 1 и 10, нашел, что кривая для 0,01 относительно лучше. Я пишу функцию для ручного вычисления градиента. С помощью этой функции я просто сравниваю градиент, заданный формулой в коде. Получается, для градиента в W_OUTPUT они совсем разные, то бишь разная величина. В настоящее время я не уверен, что написал это правильно, я вернусь как можно скорее и обновлю код после того, как подтвержу его правильность.   -  person Ludwig Zhou    schedule 12.08.2016
comment
@LemmRas, я нашел это сегодня днем, проблема в функции shuffle_data, после того, как я прокомментировал этот код, он работает. Я добавил регуляризацию L2 и настроил другие параметры и получил ошибку обучения 97%, ошибку тестирования 96. Завтра придумаю, как заставить работать перетасовку.   -  person Ludwig Zhou    schedule 15.08.2016
comment
Я думаю, вы могли бы попытаться не перетасовывать строки или столбцы, а добавить третье измерение и перетасовать его. В противном случае изображения не сохраняются.   -  person Lemm Ras    schedule 16.08.2016
comment
@LemmRas Я обнаружил ошибку: функция перемешивания работает только с меткой и данными, но не с «labels_matrix», которая используется для вычисления значения дельты в выходном слое MLP, поэтому перемешивание на самом деле не работает и не нарушает связь между меткой и данные, ура дружище!   -  person Ludwig Zhou    schedule 19.08.2016


Ответы (1)


Когда вы перемешиваете изображения, метка данных ассоциации теряется. Поскольку эта ассоциация должна сохраниться, вам нужно обеспечить одинаковое перетасовку как для данных, так и для меток.

Для этого вы можете, например, создать внешний список с перетасованными индексами: shuffled=randperm(N), где N — количество изображений, а затем передать методу train либо созданный список, либо элементы images и label, адресованные перетасованным списком.

person Lemm Ras    schedule 12.08.2016