web-dev-qa-db-fra.com

Utilisation de R pour la régression logistique multi-classes

Format court:

Comment implémenter des algorithmes de classification par régression logistique multi-classes via la descente de gradient en R? optim() peut-il être utilisé lorsqu'il y a plus de deux étiquettes?

Le code MatLab est:

function [J, grad] = cost(theta, X, y, lambda)
    m = length(y);
    J = 0;
    grad = zeros(size(theta));
    h_theta = sigmoid(X * theta);
    J = (-1/m)*sum(y.*log(h_theta) + (1-y).*log(1-h_theta)) +...
    (lambda/(2*m))*sum(theta(2:length(theta)).^2);
    trans = X';
    grad(1) = (1/m)*(trans(1,:))*(h_theta - y);
    grad(2:size(theta, 1)) = 1/m * (trans(2:size(trans,1),:)*(h_theta - y) +...
    lambda * theta(2:size(theta,1),:));
    grad = grad(:);
end

et...

function [all_theta] = oneVsAll(X, y, num_labels, lambda)
    m = size(X, 1);
    n = size(X, 2);
    all_theta = zeros(num_labels, n + 1);
    initial_theta = zeros(n+1, 1);
    X = [ones(m, 1) X];
    options = optimset('GradObj', 'on', 'MaxIter', 50);
       for c = 1:num_labels,
     [theta] = ...
         fmincg (@(t)(cost(t, X, (y == c), lambda)), ...
                 initial_theta, options);
     all_theta(c,:) = theta';
end

Format long:

Bien qu'il ne soit probablement pas nécessaire de suivre la question, l'ensemble de données peut être téléchargé ici et une fois téléchargé et placé dans le répertoire R, chargé comme suit: 

library(R.matlab)
data <- readMat('data.mat')
str(data)
List of 2
 $ X: num [1:5000, 1:400] 0 0 0 0 0 0 0 0 0 0 ...
 $ y: num [1:5000, 1] 10 10 10 10 10 10 10 10 10 10 ...

Donc X est une matrice avec 5,000 examples , chacun contenant 400 features , qui se trouve être 400 pixels d’une image 20 x 20 d’un chiffre manuscrit de 1 à 10, comme par exemple ce 9: 

enter image description here

L'application d'un algorithme de régression logistique pour prédire le nombre manuscrit sur la base d'une "vision par ordinateur" des valeurs dans ces 400 pixels présente le défi supplémentaire de ne pas être une décision binaire. Il est peu probable que l'optimisation des coefficients soit efficace avec une boucle de descente ad hoc comme dans cette exemple de R-bloggers .

Il existe également un exemple bien élaboré dans R-bloggers , basé sur deux variables explicatives (caractéristiques) et un résultat dichotomique. L'exemple utilise la fonction optim()R, qui semble être le chemin à parcourir } _.

Même si j'ai lu la documentation, j'ai du mal à mettre en place cet exemple plus complexe, où nous devons choisir parmi 10 résultats possibles:

    library(R.matlab)
    data <- readMat('data.mat')

    X = data$X                 # These are the values for the pixels in all 5000 examples.
    y = data$y                 # These are the actual correct labels for each example.
    y = replace(y, y == 10, 0) # Replacing 10 with 0 for simplicity.

    # Defining the sigmoid function for logistic regression.
       sigmoid = function(z){
            1 / (1 + exp(-z))
       }

    X = cbind(rep(1, nrow(X)), X) # Adding an intercept or bias term (column of 1's).

    # Defining the regularized cost function parametrized by the coefficients.

       cost = function(theta){ 
           hypothesis = sigmoid(X%*%theta)
           # In "J" below we will need to have 10 columns of y:
           y = as.matrix(model.matrix(lm(y ~ as.factor(y))))
           m = nrow(y)
           lambda = 0.1
           # The regularized cost function is:
           J = (1/m) * sum(-y * log(hypothesis)  - (1 - y) * log(1 - hypothesis)) +
    (lambda/(2 * m)) * sum(theta[2:nrow(theta), 1]^2)
           J
        }

    no.pixels_plus1 = ncol(X)     # These are the columns of X plus the intercept.
    no.digits = length(unique(y)) # These are the number of labels (10).
    # coef matrix rows = no. of labels; cols = no. pixels plus intercept:
    theta_matrix = t(matrix(rep(0, no.digits*no.pixels_plus1), nrow = no.digits))
    cost(theta_matrix) # The initial cost:
    # [1] 0.6931472
    theta_optim = optim(par = theta_matrix, fn = cost) # This is the PROBLEM step!

Evidemment, cela semble incomplet et me donne le message d'erreur: 

 Error in X %*% theta : non-conformable arguments 

Notez que X%*%theta_matrix est exécuté sans aucun problème. Le problème doit donc être lié au fait que j'ai 10 classificateurs (0 à 9) et que je suis obligé de créer une matrice avec 10 vecteurs de colonne y pour rendre les opérations possibles avec la fonction cost. Il est possible que la solution passe par le code factice y avec une ligne telle que: y = as.matrix(model.matrix(lm(y ~ as.factor(y)))) comme dans le code qui ne fonctionne pas ci-dessus, mais je ne sais pas encore que cela résume l'idée "un contre tous" - OK, probablement pas, et probablement c'est le problème. 

Sinon, cela semble fonctionner sur le publication de R-bloggers avec un classificateur binaire et extrêmement parallèle au code identique.

Alors, quelle est la bonne syntaxe pour ce problème? 

Notez que j'ai essayé de calculer un chiffre par rapport à tous les autres }, mais je ne pense pas que cela ait du sens en termes de complexité.

14
Toni

La theta à laquelle vous alimentez optim doit être un vecteur. Vous pouvez le transformer en matrice dans la fonction de coût. 

Voir la question précédente ici: Comment optimiser l'utilisation de la multiplication de matrice dans la fonction à maximiser dans R

1
Philippe Marchand