web-dev-qa-db-fra.com

GNU Méthode d'octave pour opérer sur chaque élément d'une matrice. Exemple "arrayfun (...)" d'octave

Dans GNU Octave version 3.4.3, j'ai du mal à appliquer une fonction personnalisée pour opérer sur chaque élément/élément d'une matrice.

J'ai une matrice (2,3) qui ressemble à:

mymatrix = [1,2,3;4,5,6];

mymatrix

   1   2   3
   4   5   6

Je veux utiliser chaque élément de la matrice comme entrée, et exécuter une fonction personnalisée par rapport à lui, et faire en sorte que la sortie de la fonction remplace le contenu de mymatrix élément par élément.

38
Eric Leschinski

De manière plus simple, comme l'a souligné Nasser, le code d'octave suivant:

f=@(x) x+5;
A = [1, 0, -1; 3, 4, 5];
result = f(A)
result

s'applique (x + 5) à chaque élément transmis, il affiche:

result =
    6    5    4
    8    9   10
2
Eric Leschinski

arrayfun fonctionne bien pour cela:

arrayfun(@(x) 1/(1+e^(-x)), [0, 1; 2, 3])

Production:

ans =

   0.50000   0.73106
   0.88080   0.95257

Cela exécute essentiellement la fonction 1/(1+e^(-x)) sur chaque élément de la matrice/vecteur.

67
Nikita G.

Vous pouvez également utiliser les opérateurs élément par élément comme suit (notez le préfixe du point):

  • . +
  • .-
  • ./
  • e. ^

Par exemple

mymatrix = 1 ./ (1 .+ e.^(-mymatrix));
21
frhack

Mettez ce code dans le nom de fichier appelé "myfun.m"

function [ out ] = myfun(num)
  out = num + 5;
end

Mettez ce code dans le nom de fichier appelé "main.m"

arrayfun(@myfun, [1, 0, -1; 3, 4, 5] )

Production:

ans =
   6   5   4
   8   9   10

Remarquez comment la procédure (ajouter 5) a été appliquée à chaque élément de la matrice.

PROTIP: Pourquoi ce code sur une matrice suffisamment grande ne maximisera pas votre processeur quad-core.

Ci-dessous, une analyse des capacités de arrayfun du point de vue de la vectorisation vers le bas de bas niveau C. Vers une optimisation multicœur et multithread sur le métal nu:

Ce code arrayfun est "vectorisé", et GNU Octave empaquette ce code pour être remis au code C pré-optimisé plutôt que d'avoir GNU Octave gère sa propre itération glaciaire. Les opérations effectuées de manière vectorisée comme celle ci-dessus sont entre 2 et 5 ordres de grandeur plus rapides que si vous mettez cela dans une boucle for. Le code vectorisé comme celui-ci est généralement suffisant pour les tâches typiques, mais si extraire chaque régime de puissance du processeur hyperthread QUAD-CHIP 32-Core de votre Alienware est essentiel à la mission, continuez à lire.

Ne faites pas l'erreur de dire que ce code est "multi-thread" ou "multi-core" car ce n'est pas le cas. Le code C est toujours en train de traiter ce code de manière itérative de type file d'attente premier entré, premier sorti. Le 4ème ajout doit attendre le 3ème, et le 3ème doit attendre le 2ème. Votre CPU tourne les pouces pendant cette itération. Si vous voulez que votre CPU à seize cœurs sous votre bureau maximise son utilisation du processeur à 100% pendant que cette opération est en cours d'exécution, alors il n'y a pas d'échappatoire: vous devez arrêter et redéfinir ce problème dans un environnement multi-thread et multi-core façon. Multi-thread et multi-core est au-delà de la portée de cette réponse, le moyen le plus simple est de définir votre code d'octave pour générer 8 parallèles distincts job1.m à travers job8.m fichiers qui s'exécutent tous en même temps, ont tous à traiter 1/8 de la tâche à accomplir, à la fin attendez que tout se termine puis rejoignez la réponse. GNU La vectorisation d'octave ici n'équivaut PAS au multithread sur le métal.

7
Eric Leschinski