Правильная практика и подход к отчетности по результатам обучения и обобщения - PullRequest
0 голосов
/ 25 января 2020

Я пытаюсь узнать правильную процедуру обучения нейронной сети для классификации. Есть много учебных пособий, но они никогда не объясняют, как отчитываться за производительность обобщения. Может кто-нибудь, пожалуйста, скажите мне, если следующий метод является правильным или нет. Я использую первые 100 примеров из набора данных fisheriris, который имеет метки 1,2 и называю их X и Y соответственно. Затем я делю X на trainData и Xtest с коэффициентом разделения 90/10. Используя trainData, я обучил модель NN. Теперь NN внутренне разбивает trainData на tr, val, тестовые подмножества. Моя путаница заключается в том, какой из них обычно используется для целей обобщения при сообщении о производительности модели для невидимых данных в конференциях / журналах? Набор данных можно найти по ссылке: https://www.mathworks.com/matlabcentral/fileexchange/71468-simple-neural-networks-with-k-fold-cross-validation-manner

rng('default')
load iris.mat;

X = [f(1:100,:) l(1:100)];

numExamples = size(X,1);
indx = randperm(numExamples);
X = X(indx,:);
Y = X(:,end);


split1 = cvpartition(Y,'Holdout',0.1,'Stratify',true); %90% trainval 10% test

istrainval = training(split1); % index for fitting
istest = test(split1);      % indices for quality assessment

trainData = X(istrainval,:);

Xtest = X(istest,:);
Ytest = Y(istest);


numExamplesXtrainval = size(trainData,1);

indxXtrainval = randperm(numExamplesXtrainval);
trainData = trainData(indxXtrainval,:);
Ytrain = trainData(:,end);

hiddenLayerSize = 10;

% data format = rows = number of dim, column = number of examples
net  = patternnet(hiddenLayerSize);
net  = init(net);
net.performFcn = 'crossentropy';
net.trainFcn = 'trainscg';
net.trainParam.epochs=50;

[net tr]= train(net,trainData', Ytrain');
Trained = sim(net, trainData');  %outputs predicted labels

train_predict = net(trainData');

performanceTrain = perform(net,Ytrain',train_predict)
lbl_train=grp2idx(Ytrain);
Yhat_train = (train_predict >= 0.5);
Lbl_Yhat_Train = grp2idx(Yhat_train);   
[cmMatrixTrain]=  confusionmat(lbl_train,Lbl_Yhat_Train )

accTrain=sum(lbl_train ==Lbl_Yhat_Train)/size(lbl_train,1);
disp(['Training Set:    Total Train Acccuracy by MLP = ',num2str(100*accTrain ), '%'])

[confTest] =  confusionmat(lbl_train(tr.testInd),Lbl_Yhat_Train(tr.testInd) )


%unknown test
test_predict = net(Xtest');

performanceTest = perform(net,Ytest',test_predict);
Yhat_test = (test_predict >= 0.5);
test_lbl=grp2idx(Ytest);
Lbl_Yhat_Test = grp2idx(Yhat_test);

[cmMatrix_Test]=  confusionmat(test_lbl,Lbl_Yhat_Test )

Это вывод.

Проблема 1: Кажется, что нет никакого предсказания для другого класса. Почему?

Проблема 2: Нужен ли мне отдельный набор данных, подобный тому, который я создал как Xtest для сообщения об ошибке обобщения, или это практика использования данных trainData(tr.testInd,:) в качестве набора тестов обобщения? Я создал ненужное подмножество?

performanceTrain =

   2.2204e-16


cmMatrixTrain =

    45     0
    45     0

Training Set:    Total Train Acccuracy by MLP = 50%

confTest =

     9     0
     5     0


cmMatrix_Test =

     5     0
     5     0

1 Ответ

0 голосов
/ 27 января 2020

Есть несколько проблем с кодом. Давайте разберемся с ними, прежде чем ответить на ваш вопрос. Во-первых, вы устанавливаете порог 0,5 для принятия решений (Yhat_train = (train_predict >= 0.5);), в то время как все точки вашего прогноза net выше 0,5. Это означает, что вы получаете только нули в своих путаницах. Вы можете построить график, чтобы выбрать лучший порог:

figure;
plot(train_predict(Ytrain == 1),'.b')
hold on
plot(train_predict(Ytrain == 2),'.r')
legend('label 1','label 2')

cvpartition дал мне ошибку. Он успешно работал как split1 = cvpartition(Y,'Holdout',0.1);. В любом случае, искусственные нейронные сети обычно управляют разделением в процессе обучения, поэтому вы вводите X и Y и некоторые параметры, как это сделать. Смотрите здесь, например: ссылка где вы установили

net.divideParam.trainRatio = .4;
net.divideParam.valRatio = .3;
net.divideParam.testRatio = .3;

Так как сообщить о результатах? Только для тестовых данных. Данные поезда пострадают от перегрузки и покажут ложные, слишком хорошие результаты. Если вы используете данные проверки (у вас нет), то вы не сможете показать результаты для них, потому что они также пострадают от перегрузки. Если вы позволите обучению выполнить проверку для вас, результаты вашего теста будут защищены от перегрузки.

...