Работа с NaN (отсутствующими) значениями для логистической регрессии - лучшие практики? - PullRequest
0 голосов
/ 02 октября 2018

Я работаю с набором данных о пациентах и ​​пытаюсь рассчитать показатель склонности на основе данных с использованием MATLAB.После удаления объектов со многими пропущенными значениями у меня все еще остаются несколько пропущенных (NaN) значений.

Я получаю ошибки из-за этих пропущенных значений, поскольку значения моей функции стоимости и вектора градиента становятся NaN, когдаЯ пытаюсь выполнить логистическую регрессию, используя следующий код Matlab (из курса машинного обучения Coursera Эндрю Нга):

[m, n] = size(X);
X = [ones(m, 1) X];    
initial_theta = ones(n+1, 1);
[cost, grad] = costFunction(initial_theta, X, y);
options = optimset('GradObj', 'on', 'MaxIter', 400);

[theta, cost] = ...
    fminunc(@(t)(costFunction(t, X, y)), initial_theta, options);

Примечание: сигмоид и функция стоимости - это рабочие функции, которые я создал для общей простоты использования.

Расчеты можно выполнить плавно, если я заменю все значения NaN на 1 или 0. Однако я не уверен, является ли это лучшим способом решения этой проблемы, и мне также было интересно, какое значение замены мне следует выбрать (в целом), чтобы получить наилучшие результаты для выполнения логистической регрессии с отсутствующими данными. Есть ли какие-либо преимущества / недостатки в использовании определенного числа (0 или 1 или что-то еще) для замены указанных пропущенных значений в моих данных?

Примечание: я также нормализовал все значения признаковбыть в диапазоне 0-1.

Любое понимание этого вопроса будет высоко оценено.Спасибо

Ответы [ 2 ]

0 голосов
/ 28 октября 2018

Как указывалось ранее, это общая проблема, с которой сталкиваются люди независимо от платформы программирования.Это называется «вменение отсутствующих данных».

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

К счастью, в MATLAB есть функция с именем knnimpute, которая оценивает отсутствующую точку данных по ближайшему соседу.

Из моего опыта я часто находил knnimpute полезным.Тем не менее, он может не сработать, когда слишком много пропущенных сайтов, как в ваших данных;соседи отсутствующего сайта также могут быть неполными, что ведет к неточной оценке.Ниже я нашел обходное решение для этого;он начинается с наименьшего числа неполных столбцов, (необязательно), для определения безопасного заранее определенного расстояния для соседей.Надеюсь, это поможет.

function data = dnnimpute(data,distCutoff,option,distMetric)
% data = dnnimpute(data,distCutoff,option,distMetric)
%
%   Distance-based nearest neighbor imputation that impose a distance
%     cutoff to determine nearest neighbors, i.e., avoids those samples 
%     that are more distant than the distCutoff argument.
%
%   Imputes missing data coded by "NaN" starting from the covarites 
%     (columns) with the least number of missing data. Then it continues by 
%     including more (complete) covariates in the calculation of pair-wise 
%     distances.
%
%   option, 
%       'median'      - Median of the nearest neighboring values
%       'weighted'    - Weighted average of the nearest neighboring values
%       'default'     - Unweighted average of the nearest neighboring values
%
%   distMetric,
%       'euclidean'   - Euclidean distance (default)
%       'seuclidean'  - Standardized Euclidean distance. Each coordinate
%                       difference between rows in X is scaled by dividing
%                       by the corresponding element of the standard
%                       deviation S=NANSTD(X). To specify another value for
%                       S, use D=pdist(X,'seuclidean',S).
%       'cityblock'   - City Block distance
%       'minkowski'   - Minkowski distance. The default exponent is 2. To
%                       specify a different exponent, use
%                       D = pdist(X,'minkowski',P), where the exponent P is
%                       a scalar positive value.
%       'chebychev'   - Chebychev distance (maximum coordinate difference)
%       'mahalanobis' - Mahalanobis distance, using the sample covariance
%                       of X as computed by NANCOV. To compute the distance
%                       with a different covariance, use
%                       D =  pdist(X,'mahalanobis',C), where the matrix C
%                       is symmetric and positive definite.
%       'cosine'      - One minus the cosine of the included angle
%                       between observations (treated as vectors)
%       'correlation' - One minus the sample linear correlation between
%                       observations (treated as sequences of values).
%       'spearman'    - One minus the sample Spearman's rank correlation
%                       between observations (treated as sequences of values).
%       'hamming'     - Hamming distance, percentage of coordinates
%                       that differ
%       'jaccard'     - One minus the Jaccard coefficient, the
%                       percentage of nonzero coordinates that differ
%       function      - A distance function specified using @, for
%                       example @DISTFUN.
%  
if nargin < 3
    option = 'mean';
end
if nargin < 4
    distMetric = 'euclidean';
end

nanVals = isnan(data);
nanValsPerCov = sum(nanVals,1);
noNansCov = nanValsPerCov == 0;
if isempty(find(noNansCov, 1))
    [~,leastNans] = min(nanValsPerCov);
    noNansCov(leastNans) = true;
    first = data(nanVals(:,noNansCov),:);
    nanRows = find(nanVals(:,noNansCov)==true); i = 1;
    for row = first'
        data(nanRows(i),noNansCov) = mean(row(~isnan(row)));
        i = i+1;
    end
end

nSamples = size(data,1);
if nargin < 2
    dataNoNans = data(:,noNansCov);
    distances = pdist(dataNoNans);
    distCutoff = min(distances);
end
[stdCovMissDat,idxCovMissDat] = sort(nanValsPerCov,'ascend');
imputeCols = idxCovMissDat(stdCovMissDat>0);
% Impute starting from the cols (covariates) with the least number of 
% missing data. 
for c = reshape(imputeCols,1,length(imputeCols))    
    imputeRows = 1:nSamples;
    imputeRows = imputeRows(nanVals(:,c));   
    for r = reshape(imputeRows,1,length(imputeRows))
        % Calculate distances
        distR = inf(nSamples,1);
        %
        noNansCov_r = find(isnan(data(r,:))==0);
        noNansCov_r = noNansCov_r(sum(isnan(data(nanVals(:,c)'==false,~isnan(data(r,:)))),1)==0);
        %
        for i = find(nanVals(:,c)'==false)
            distR(i) = pdist([data(r,noNansCov_r); data(i,noNansCov_r)],distMetric);            
        end
        tmp = min(distR(distR>0));        
        % Impute the missing data at sample r of covariate c
        switch option
            case 'weighted'
                data(r,c) = (1./distR(distR<=max(distCutoff,tmp)))' * data(distR<=max(distCutoff,tmp),c) / sum(1./distR(distR<=max(distCutoff,tmp)));
            case 'median'
                data(r,c) = median(data(distR<=max(distCutoff,tmp),c),1);
            case 'mean'
                data(r,c) = mean(data(distR<=max(distCutoff,tmp),c),1);
        end
        % The missing data in sample r is imputed. Update the sample 
        % indices of c which are imputed. 
        nanVals(r,c) = false;  
    end    
    fprintf('%u/%u of the covariates are imputed.\n',find(c==imputeCols),length(imputeCols));
end
0 голосов
/ 02 октября 2018

Чтобы справиться с отсутствующими данными, вы можете использовать один из следующих трех вариантов:

  • Если экземпляров с пропущенными значениями не так много, вы можете просто удалить экземпляры с пропущенными значениями.

  • Если у вас много функций и возможно потерять некоторую информацию, удалите всю функцию с пропущенными значениями.

  • Лучший метод - этозаполнить некоторое значение (среднее значение, медиана) вместо отсутствующего значения.Вы можете рассчитать среднее значение остальных обучающих примеров для этой функции и заполнить все пропущенные значения средним.Это хорошо работает, так как среднее значение остается в распределении ваших данных.

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

Если вы используете 0 или 1 для замены всех пропущенных значений, тогда данные могут быть искажены, поэтому лучше заменитьпропущенные значения в среднем по всем другим значениям.

...