Exporter un réseau neuronal formé avec MATLAB dans d'autres langages de programmation

j'ai formé un réseau neuronal en utilisant la boîte à outils du réseau neuronal MATLAB, et en particulier en utilisant la commande nprtool, qui fournit une interface graphique simple pour utiliser les fonctionnalités de la boîte à outils, et pour exporter un net objet contenant les informations sur le NN généré.

De cette façon, j'ai créé un réseau de neurones, que je peux utiliser comme classificateur, et un diagramme représentant, il est le suivant:

Diagram representing the Neural Network

Il y a 200 entrées, 20 neurones dans la première couche cachée, et 2 neurones dans la dernière couche qui fournissent une bidimensionnelle de sortie.

Ce que je veux faire est d'utiliser le réseau dans un autre langage de programmation (C#, Java, ...).

pour résoudre ce problème, j'essaie d'utiliser le code suivant dans MATLAB:

y1 = tansig(net.IW{1} * input + net.b{1});
Results = tansig(net.LW{2} * y1 + net.b{2});

en Supposant que input est un tableau monodimensionnel de 200 éléments, le code précédent fonctionnerait si net.IW{1} est une matrice 20x200 (20 neurones, 200 Poids).

le le problème est que j'ai remarqué que size(net.IW{1}) renvoie des valeurs inattendues:

>> size(net.IW{1})

    ans =

    20   199

j'ai le même problème avec un réseau avec 10000 entrées. Dans ce cas, le résultat n'était pas 20x10000, mais quelque chose comme 20x9384 (Je ne me souviens pas de la valeur exacte).

Donc la question est: comment puis-je obtenir le poids de chaque neurone? Et après cela, quelqu'un peut-il m'expliquer comment je peux les utiliser pour produire la même production de MATLAB?

15
demandé sur Vito Gentile 2013-03-20 18:18:19

5 réponses

j'ai résolu les problèmes décrits ci-dessus, et je pense qu'il est utile de partager ce que j'ai appris.

locaux

tout d'Abord, nous avons besoin de quelques définitions. Considérons l'image suivante, tirée de [1]:

A scheme of Neural Network

Dans la figure ci-dessus, IW représente poids initiaux: ils représentent l' poids des neurones sur la couche 1, dont chacune est connecté avec chaque entrée, l'image suivante montre [1]:

All neurons are connected with all inputs

Tous les autres poids sont appelés poids des couches ( LW dans la première figure), qui sont également connectés à chaque sortie de la couche précédente. Dans le cas de notre étude, nous utilisons un réseau à deux couches seulement, de sorte que nous n'utiliserons qu'un seul réseau LW pour résoudre nos problèmes.

la Solution du problème

Après le au-dessus de l'introduction, Nous pouvons procéder en divisant la question en deux étapes:

  • forcer le nombre de poids initiaux à correspondre à la longueur du tableau d'entrées
  • Utiliser le poids à mettre en œuvre et utiliser le réseau de neurones juste formés dans d'autres langages de programmation

A - forcez le nombre de poids initiaux à correspondre à la longueur du tableau d'entrée

nprtool, nous pouvons former notre réseau, et à la fin de la processus, nous pouvons également exporter en l'espace de quelques informations sur l'ensemble du processus de formation. En particulier, nous avons besoin de l'exportation:

  • un objet réseau MATLAB qui représente le réseau neuronal créé
  • le tableau d'entrée utilisé pour former le réseau
  • le tableau cible utilisé pour former le réseau

aussi, nous avons besoin de générer un fichier M qui contient le code utilisé par MATLAB pour créer le réseau neuronal, parce que nous avons besoin de modifiez - le et modifiez certaines options de formation.

L'image suivante montre comment effectuer ces opérations:

The nprtool GUI to export data and generate the M-code

Le M-code généré sera similaire à la suivante:

function net = create_pr_net(inputs,targets)
%CREATE_PR_NET Creates and trains a pattern recognition neural network.
%
%  NET = CREATE_PR_NET(INPUTS,TARGETS) takes these arguments:
%    INPUTS - RxQ matrix of Q R-element input samples
%    TARGETS - SxQ matrix of Q S-element associated target samples, where
%      each column contains a single 1, with all other elements set to 0.
%  and returns these results:
%    NET - The trained neural network
%
%  For example, to solve the Iris dataset problem with this function:
%
%    load iris_dataset
%    net = create_pr_net(irisInputs,irisTargets);
%    irisOutputs = sim(net,irisInputs);
%
%  To reproduce the results you obtained in NPRTOOL:
%
%    net = create_pr_net(trainingSetInput,trainingSetOutput);

% Create Network
numHiddenNeurons = 20;  % Adjust as desired
net = newpr(inputs,targets,numHiddenNeurons);
net.divideParam.trainRatio = 75/100;  % Adjust as desired
net.divideParam.valRatio = 15/100;  % Adjust as desired
net.divideParam.testRatio = 10/100;  % Adjust as desired

% Train and Apply Network
[net,tr] = train(net,inputs,targets);
outputs = sim(net,inputs);

% Plot
plotperf(tr)
plotconfusion(targets,outputs)

avant de commencer le processus de formation, nous devons supprimer toutes les fonctions de prétraitement et de posttraitement que MATLAB exécute sur les entrées et sorties. Ceci peut être fait en ajoutant les lignes suivantes juste avant le % Train and Apply Network lignes:

net.inputs{1}.processFcns = {};
net.outputs{2}.processFcns = {};

après ces modifications à la create_pr_net() fonction, simplement nous pouvons l'utiliser pour créer notre réseau neuronal final:

net = create_pr_net(input, target);

input et target sont les valeurs que nous avons exportées par nprtool.

De cette façon, nous sommes sûrs que le nombre de poids est égale à la longueur du tableau d'entrée. En outre, ce processus est utile pour simplifier le portage vers d'autres langages de programmation.

B-mettre en oeuvre et utiliser le réseau neuronal formé dans d'autres langages de programmation

Avec ces changements, nous pouvons définir une fonction comme ceci:

function [ Results ] = classify( net, input )
    y1 = tansig(net.IW{1} * input + net.b{1});

    Results = tansig(net.LW{2} * y1 + net.b{2});
end

dans ce code, nous utilisons les tableaux IW et LW mentionnés ci-dessus, mais aussi les biais b, utilisé dans le schéma du réseau par le nprtool. Dans ce contexte, nous ne nous soucions pas de la rôle de préjugés; simplement, nous avons besoin de les utiliser car nprtool t-il.

Maintenant, nous pouvons utiliser le classify() la fonction définie ci-dessus, ou le sim() fonctionner également, en obtenant les mêmes résultats, comme indiqué dans l'exemple suivant:

>> sim(net, input(:, 1))

ans =

    0.9759
   -0.1867
   -0.1891

>> classify(net, input(:, 1))

ans =

   0.9759   
  -0.1867
  -0.1891

bien Évidemment, le classify() la fonction peut être interprétée comme un pseudocode, puis implémentée dans tous les langages de programmation dans lesquels il est possible de définir le MATLAB tansig() la fonction [2] et les opérations de base entre les tableaux.

Références

[1] Howard Demuth, Mark Beale, Martin Hagan: Boîte À Outils Des Réseaux Neuronaux 6-Guide De L'Utilisateur, MATLAB

[2] Mathworks,tansig - tangente Hyperbolique la fonction de transfert sigmoïde, MATLAB Documentation center

notes supplémentaires

jetez un coup d'oeil à la robott réponse et la réponse de Sangeun Chi pour plus de détails.

14
répondu Vito Gentile 2017-05-23 12:25:20

grâce aux réponses de VitoShadow et robott, je peux exporter les valeurs des réseaux neuronaux Matlab vers d'autres applications.

je les apprécie vraiment, mais j'ai trouvé quelques petites erreurs dans leurs codes et je veux les corriger.

1) dans les codes VitoShadow,

Results = tansig(net.LW{2} * y1 + net.b{2});
-> Results = net.LW{2} * y1 + net.b{2};

2) dans les codes de prétraitement robott, Il serait plus facile d'extraire xmax et xmin de la variable nette que de les calculer.

xmax = net.inputs{1}.processSettings{1}.xmax
xmin = net.inputs{1}.processSettings{1}.xmin

3) dans le robott postprocessing codes,

xmax = net.outputs{2}.processSettings{1}.xmax
xmin = net.outputs{2}.processSettings{1}.xmin

Results = (ymax-ymin)*(Results-xmin)/(xmax-xmin) + ymin;
-> Results = (Results-ymin)*(xmax-xmin)/(ymax-ymin) + xmin;

Vous pouvez vérifier manuellement et confirmer les valeurs comme suit:

p2 = mapminmax('apply', net(:, 1), net.inputs{1}.processSettings{1})

-> prétraitées de données

y1 = purelin ( net.LW{2} * tansig(net.iw{1}* p2 + net.b{1}) + net.b{2})

-> données traitées par le réseau neuronal

y2 = mapminmax( 'reverse' , y1, net.outputs{2}.processSettings{1})

-> données post-traitées

Référence: http://www.mathworks.com/matlabcentral/answers/14517-processing-of-i-p-data

3
répondu Sangeun Chi 2014-04-28 05:07:08

Si vous voulez utiliser le prétraitement et le post-traitement ' mapminmax' fonctions, vous devez faire attention parce que 'mapminmax' dans Matlab se normalise par ligne et non par colonne!

C'est ce que vous devez ajouter à la fonction supérieure "classifier", pour garder un pré/post-traitement cohérent:

[m n] = size(input);
ymax = 1;
ymin = -1;
for i=1:m
   xmax = max(input(i,:));
   xmin = min(input(i,:));
   for j=1:n
     input(i,j) = (ymax-ymin)*(input(i,j)-xmin)/(xmax-xmin) + ymin;
   end
end
ymax = 1;
ymin = 0;
xmax = 1;
xmin = -1;
Results = (ymax-ymin)*(Results-xmin)/(xmax-xmin) + ymin;

c'est du code Matlab, mais il peut être facilement lu en pseudo-code. Espérons que ce sera utile!

3
répondu Gabrer 2018-03-07 23:59:01

j'ai essayé d'implémenter simplement un NN à 2 couches en C++ en utilisant OpenCV et j'ai ensuite exporté les poids vers Android qui fonctionnait très bien. J'ai écrit un petit script qui génère un fichier d'en-tête avec les poids appris et ceci est utilisé dans le code suivant snipped.

// Map Minimum and Maximum Input Processing Function
Mat mapminmax_apply(Mat x, Mat settings_gain, Mat settings_xoffset, double settings_ymin){

    Mat y;

    subtract(x, settings_xoffset, y);
    multiply(y, settings_gain, y);
    add(y, settings_ymin, y);

    return y;


    /* MATLAB CODE
     y = x - settings_xoffset;
     y = y .* settings_gain;
     y = y + settings_ymin;
     */
}




// Sigmoid Symmetric Transfer Function
Mat transig_apply(Mat n){
    Mat tempexp;
    exp(-2*n, tempexp);
    Mat transig_apply_result = 2 /(1 + tempexp) - 1;
    return transig_apply_result;
}


// Map Minimum and Maximum Output Reverse-Processing Function
Mat mapminmax_reverse(Mat y, Mat settings_gain, Mat settings_xoffset, double settings_ymin){

    Mat x;

    subtract(y, settings_ymin, x);
    divide(x, settings_gain, x);
    add(x, settings_xoffset, x);

    return x;


/* MATLAB CODE
function x = mapminmax_reverse(y,settings_gain,settings_xoffset,settings_ymin)
x = y - settings_ymin;
x = x ./ settings_gain;
x = x + settings_xoffset;
end
*/

}


Mat getNNParameter (Mat x1)
{

    // convert double array to MAT

    // input 1
    Mat x1_step1_xoffsetM = Mat(1, 48, CV_64FC1, x1_step1_xoffset).t();
    Mat x1_step1_gainM = Mat(1, 48, CV_64FC1, x1_step1_gain).t();
    double x1_step1_ymin = -1;

    // Layer 1
    Mat b1M = Mat(1, 25, CV_64FC1, b1).t();
    Mat IW1_1M = Mat(48, 25, CV_64FC1, IW1_1).t();

    // Layer 2
    Mat b2M = Mat(1, 48, CV_64FC1, b2).t();
    Mat LW2_1M = Mat(25, 48, CV_64FC1, LW2_1).t();

    // input 1
    Mat y1_step1_gainM = Mat(1, 48, CV_64FC1, y1_step1_gain).t();
    Mat y1_step1_xoffsetM = Mat(1, 48, CV_64FC1, y1_step1_xoffset).t();
    double y1_step1_ymin = -1;



    // ===== SIMULATION ========


    // Input 1
    Mat xp1 = mapminmax_apply(x1, x1_step1_gainM, x1_step1_xoffsetM, x1_step1_ymin);

    Mat  temp = b1M + IW1_1M*xp1;

    // Layer 1
    Mat a1M = transig_apply(temp);

    // Layer 2
    Mat a2M = b2M + LW2_1M*a1M;

    // Output 1
    Mat y1M = mapminmax_reverse(a2M, y1_step1_gainM, y1_step1_xoffsetM, y1_step1_ymin);

    return y1M;
}

exemple d'un biais dans l'en-tête pourrait être ceci:

static double b2[1][48] = {
        {-0.19879, 0.78254, -0.87674, -0.5827, -0.017464, 0.13143, -0.74361, 0.4645, 0.25262, 0.54249, -0.22292, -0.35605, -0.42747, 0.044744, -0.14827, -0.27354, 0.77793, -0.4511, 0.059346, 0.29589, -0.65137, -0.51788, 0.38366, -0.030243, -0.57632, 0.76785, -0.36374, 0.19446, 0.10383, -0.57989, -0.82931, 0.15301, -0.89212, -0.17296, -0.16356, 0.18946, -1.0032, 0.48846, -0.78148, 0.66608, 0.14946, 0.1972, -0.93501, 0.42523, -0.37773, -0.068266, -0.27003, 0.1196}};

maintenant, que Google a publié Tensorflow, cela est devenu obsolète.

0
répondu beniroquai 2016-12-06 07:28:08

D'où la solution devient (après correction de toutes les parties)

ici je donne une solution dans Matlab, mais si vous avez la fonction tanh (), vous pouvez facilement la convertir en n'importe quel langage de programmation. C'est juste pour montrer les champs de l'objet du réseau et les opérations dont vous avez besoin.

  • supposons que vous avez un ann (network object) que vous voulez exporter
  • supposons que le nom de l'ann formée est trained_ann

Voici la script pour exporter et tester. Testing script compare le résultat original du réseau avec le résultat my_ann_evaluation ()

% Export IT
exported_ann_structure = my_ann_exporter(trained_ann);

% Run and Compare 
% Works only for single INPUT vector
% Please extend it to MATRIX version by yourself
input = [12 3 5 100];
res1 = trained_ann(input')';
res2 = my_ann_evaluation(exported_ann_structure, input')';

où vous avez besoin de deux fonctions

Première my_ann_exporter:

function [ my_ann_structure ] = my_ann_exporter(trained_netw)
% Just for extracting as Structure object
my_ann_structure.input_ymax = trained_netw.inputs{1}.processSettings{1}.ymax;
my_ann_structure.input_ymin = trained_netw.inputs{1}.processSettings{1}.ymin;
my_ann_structure.input_xmax = trained_netw.inputs{1}.processSettings{1}.xmax;
my_ann_structure.input_xmin = trained_netw.inputs{1}.processSettings{1}.xmin;

my_ann_structure.IW = trained_netw.IW{1};
my_ann_structure.b1 = trained_netw.b{1};
my_ann_structure.LW = trained_netw.LW{2};
my_ann_structure.b2 = trained_netw.b{2};

my_ann_structure.output_ymax = trained_netw.outputs{2}.processSettings{1}.ymax;
my_ann_structure.output_ymin = trained_netw.outputs{2}.processSettings{1}.ymin;
my_ann_structure.output_xmax = trained_netw.outputs{2}.processSettings{1}.xmax;
my_ann_structure.output_xmin = trained_netw.outputs{2}.processSettings{1}.xmin;
end

Deuxième my_ann_evaluation:

function [ res ] = my_ann_evaluation(my_ann_structure, input)
% Works with only single INPUT vector
% Matrix version can be implemented

ymax = my_ann_structure.input_ymax;
ymin = my_ann_structure.input_ymin;
xmax = my_ann_structure.input_xmax;
xmin = my_ann_structure.input_xmin;
input_preprocessed = (ymax-ymin) * (input-xmin) ./ (xmax-xmin) + ymin;

% Pass it through the ANN matrix multiplication
y1 = tanh(my_ann_structure.IW * input_preprocessed + my_ann_structure.b1);

y2 = my_ann_structure.LW * y1 + my_ann_structure.b2;

ymax = my_ann_structure.output_ymax;
ymin = my_ann_structure.output_ymin;
xmax = my_ann_structure.output_xmax;
xmin = my_ann_structure.output_xmin;
res = (y2-ymin) .* (xmax-xmin) /(ymax-ymin) + xmin;
end
0
répondu fermat4214 2017-03-11 03:57:57