Сводка
Я создаю классификатор для электронных писем со спамом и ветчиной, используя Octave и корпус Ling-Spam;Мой метод классификации - логистическая регрессия.
Более высокие скорости обучения приводят к тому, что для стоимости рассчитываются значения NaN, но это не нарушает / не снижает эффективность самого классификатора.
Мои попытки
Примечание: мой набор данных уже нормализован с использованием средней нормализации. Когда я пытался выбрать скорость обучения, я начинал с 0,1 и 400 итераций.Это привело к следующему графику:
1 - График 1
Когда линии полностью исчезают после нескольких итераций, это происходит из-за значения NaN, являющегосяпроизводства;Я думал, что это приведет к неправильным значениям параметров и, следовательно, к плохой точности, но при проверке точности я обнаружил, что на тестовом наборе это 95% (это означает, что градиентный спуск, по-видимому, все еще функционирует).Я проверил различные значения скорости обучения и итераций, чтобы увидеть, как изменились графики:
2 - График 2
Строки больше не исчезали, то есть нетЗначения NaN, НО точность составила 87%, что существенно ниже.
Я провел еще два теста с большим количеством итераций и немного более высокой скоростью обучения, и в обоих из них оба графика уменьшились с итерациями, как и ожидалось,но точность была ~ 86-88%.Там тоже нет NaN.
Я понял, что мой набор данных искажен, только с 481 спамом и 2412 хамом.Поэтому я рассчитал FScore для каждой из этих различных комбинаций, надеясь найти более поздние из них с более высоким FScore, и точность была из-за перекоса.Это было не так - я суммировал свои результаты в таблице:
3 - Таблица
Таким образом, нет переобучения и перекос делаетне кажется проблемой;Я не знаю, что делать сейчас!
Единственное, о чем я могу думать, это то, что мои расчеты на точность и FScore неверны, или что моя первоначальная отладка строки «исчезновение» была неправильной.
РЕДАКТИРОВАТЬ: Этот вопрос имеет решающее значение для почему значения NaN встречаются для этих выбранных скоростей обучения .Поэтому временное исправление, которое я имел в отношении снижения скорости обучения, на самом деле не отвечало на мой вопрос - я всегда думал, что более высокие скорости обучения просто расходятся, а не сходятся, не , приводя к значениям NaN.
Мой код
Мой код main.m (бар, получающий набор данных из файлов):
numRecords = length(labels);
trainingSize = ceil(numRecords*0.6);
CVSize = trainingSize + ceil(numRecords*0.2);
featureData = normalise(data);
featureData = [ones(numRecords, 1), featureData];
numFeatures = size(featureData, 2);
featuresTrain = featureData(1:(trainingSize-1),:);
featuresCV = featureData(trainingSize:(CVSize-1),:);
featuresTest = featureData(CVSize:numRecords,:);
labelsTrain = labels(1:(trainingSize-1),:);
labelsCV = labels(trainingSize:(CVSize-1),:);
labelsTest = labels(CVSize:numRecords,:);
paramStart = zeros(numFeatures, 1);
learningRate = 0.0001;
iterations = 400;
[params] = gradDescent(featuresTrain, labelsTrain, learningRate, iterations, paramStart, featuresCV, labelsCV);
threshold = 0.5;
[accuracy, precision, recall] = predict(featuresTest, labelsTest, params, threshold);
fScore = (2*precision*recall)/(precision+recall);
Мой код gradDescent.m:
function [optimParams] = gradDescent(features, labels, learningRate, iterations, paramStart, featuresCV, labelsCV)
x_axis = [];
J_axis = [];
J_CV = [];
params = paramStart;
for i=1:iterations,
[cost, grad] = costFunction(features, labels, params);
[cost_CV] = costFunction(featuresCV, labelsCV, params);
params = params - (learningRate.*grad);
x_axis = [x_axis;i];
J_axis = [J_axis;cost];
J_CV = [J_CV;cost_CV];
endfor
graphics_toolkit("gnuplot")
plot(x_axis, J_axis, 'r', x_axis, J_CV, 'b');
legend("Training", "Cross-Validation");
xlabel("Iterations");
ylabel("Cost");
title("Cost as a function of iterations");
optimParams = params;
endfunction
Моя функция цены.код m:
function [cost, grad] = costFunction(features, labels, params)
numRecords = length(labels);
hypothesis = sigmoid(features*params);
cost = (-1/numRecords)*sum((labels).*log(hypothesis)+(1-labels).*log(1-hypothesis));
grad = (1/numRecords)*(features'*(hypothesis-labels));
endfunction
код моего прогноза.m:
function [accuracy, precision, recall] = predict(features, labels, params, threshold)
numRecords=length(labels);
predictions = sigmoid(features*params)>threshold;
correct = predictions == labels;
truePositives = sum(predictions == labels == 1);
falsePositives = sum((predictions == 1) != labels);
falseNegatives = sum((predictions == 0) != labels);
precision = truePositives/(truePositives+falsePositives);
recall = truePositives/(truePositives+falseNegatives);
accuracy = 100*(sum(correct)/numRecords);
endfunction