2013-03-20 4 views
10

Я обучил нейронную сеть с помощью набора инструментов Neural Network MATLAB и, в частности, с помощью команды nprtool, которая предоставляет простой графический интерфейс для использования возможностей панели инструментов и для экспорта net объект, содержащий информацию о генерируемом NN.Экспорт нейронной сети, обученной с помощью MATLAB в других языках программирования.

Таким образом, я создал рабочую нейронную сеть, что я могу использовать в качестве классификатора, а также схема, отображающая его заключается в следующем:

Diagram representing the Neural Network

Есть 200 входов, 20 нейронов в первом скрытый слой и 2 нейрона в последнем слое, которые обеспечивают двумерный выход.

Что я хочу сделать, это использовать сеть на другом языке программирования (C#, Java, ...).

Для того, чтобы решить эту проблему, я пытаюсь использовать следующий код в MATLAB:

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

Предполагая, что input является monodimensional массив из 200 элементов, предыдущий код будет работать, если net.IW{1} является 20x200 матрица (20 нейронов, 200 весов).

Проблема заключается в том, что я заметил, что size(net.IW{1}) возвращает неожиданные значения:

>> size(net.IW{1}) 

    ans = 

    20 199 

У меня такая же проблема с сетью с 10000 входом. В этом случае результат не был 20x10000, но что-то вроде 20x9384 (я не помню точное значение).

Итак, вопрос: как я могу получить вес каждого нейрона? И после этого, может кто-нибудь объяснить мне, как я могу использовать их для получения того же выхода MATLAB?

+0

Некоторые весовые коэффициенты могут быть установлены в 0 и поэтому вырезаны из матрицы. Надеюсь, если я прав, есть место где-то, чтобы избежать такого поведения. – CTZStef

+0

Я не вижу никаких настроек для изменения таких параметров ... Можете ли вы помочь мне найти их? –

ответ

13

Я решил проблемы, описанные выше, и я думаю, что полезно поделиться тем, что я узнал.

Помещения

Прежде всего, нам нужно несколько определений. Давайте рассмотрим следующий образ, взятый из [1]:

A scheme of Neural Network

На приведенном выше рисунке, IW означает начальных весов: они представляют веса нейронов на уровне 1, каждый из которых соединен с каждым входом, как показывает следующее изображение [1]:

All neurons are connected with all inputs

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

Решение задачи

После выше введения, мы можем продолжить путем деления вопроса в два этапа:

  • заставляя их число начальных весов в соответствии с длиной входного массива
  • Используйте весы для внедрения и использования нейронной сети, прошедшей обучение только на других языках программирования.

A - Принудительно число начальных весов в соответствии с длиной входного массива

Используя nprtool, мы можем обучить нашу сеть, и в конце процесса, мы можем также экспортировать в рабочем пространстве некоторой информации о весь процесс обучения. В частности, нам нужно экспортировать:

  • объект MATLAB сеть, которая представляет собой нейронную сеть, созданная
  • массив ввода, используемый для обучения сети
  • целевой массив используется для обучения сети

Кроме того, нам нужно сгенерировать M-файл, содержащий код, используемый MATLAB для создания нейронной сети, потому что нам нужно изменить его и изменить некоторые варианты обучения.

На следующем рисунке показано, как выполнить эти операции:

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

M-код, сгенерированный будет похож на следующий:

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) 

Перед начать процесс обучения, мы необходимо, чтобы удалил все функции предварительной обработки и постпроцессинга, которые MATLAB выполняет на входах и выходах. Это можно сделать, добавив следующие строки непосредственно перед % Train and Apply Network линий:

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

После этих изменений в функции create_pr_net(), просто мы можем использовать его для создания нашей конечной нейронной сети:

net = create_pr_net(input, target); 

где input и target - это значения, которые мы экспортировали через nprtool.

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

B - Внедрение и использование нейронной сети только обученного на других языках программирования

С учетом этих изменений, мы можем определить функцию так:

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

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

В этом коде мы используем IW и LW, но также и ошибки b, используемые в сетевой схеме на nprtool. В этом контексте нас не волнует role of biases; просто, мы должны использовать их, потому что nprtool делает это.

Теперь мы можем использовать функцию classify() определено выше, или функцию sim() в равной степени, получая те же результаты, как показано в следующем примере:

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

ans = 

    0.9759 
    -0.1867 
    -0.1891 

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

ans = 

    0.9759 
    -0.1867 
    -0.1891 

Очевидно, что функция classify() может интерпретироваться как псевдокод, а затем реализуется на всех языках программирования, в которых возможно определить функцию MATLAB tansig() [2] и основные операции между массивами.

Ссылки

[1] Howard Demuth, Mark Beale, Martin Hagan: Neural Network Toolbox 6 - User Guide, MATLAB

[2] Mathworks, tansig - Hyperbolic tangent sigmoid transfer function, MATLAB Documentation center

Дополнительные примечания

Посмотрите на robott's answer и Sangeun Chi's answer для более подробной информации.

+1

Благодарим вас за этот ответ. Это мне очень помогло. Но мне нужны processFcns. Я использовал только '[input, PSi] = mapminmax (входы);' на мои входные данные и сохранил его в minmaxParams.mat 'save ('minmaxParams', 'PSi')'. И затем в моей функции классификации я добавил 'load minmaxParams.mat; input = mapminmax ('apply', input, PSi);' –

+0

Я объединил все комментарии, исправил некоторые опечатки и дал пример реализации, который отлично подходит для одного скрытый слой. Он включает в себя усовершенствования и корректировки Сангун Чи. – fermat4214

2

Это небольшое улучшение в ответе великого Vito Gentile.

Если вы хотите использовать предварительную обработку и постобработку «mapminmax» функции, вы должны обратить внимание, потому что «mapminmax» в Matlab нормализует построчно, а не по столбцам!

Это то, что вам нужно добавить к функции верхней «классификации», чтобы сохранить целостную пре/пост-обработки:

[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; 

Это код Matlab, но его можно легко прочитать как псевдокод. Надеюсь, это будет полезно!

3

Благодаря ответам VitoShadow и robott я могу экспортировать значения нейронной сети Matlab в другие приложения.

Я действительно ценю их, но я нашел некоторые тривиальные ошибки в своих кодах и хочу их исправить.

1) В кодах VitoShadow,

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

2) В кодах предварительной обработки robott, Было бы легче извлекать Xmax и Xmin из чистой переменной, чем их расчета.

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

3) В кодах robott постобработки,

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; 

Вы можете вручную проверить и подтвердить следующие значения:

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

-> предварительно обработанных данных

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

-> Neural Network pro cessed данные

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

-> постобработки данных

Ссылка: http://www.mathworks.com/matlabcentral/answers/14517-processing-of-i-p-data

0

Я пытался реализовать просто 2-слоя NN в C++ с использованием OpenCV, а затем экспортировали веса на Android, которые работали тихо хорошо , Я написал небольшой скрипт, который генерирует файл заголовка с узнанными весами, и это используется в следующем коде.

// 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; 
} 

пример для смещения в заголовке может быть такой:

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}}; 

Теперь, что Google опубликовал Tensorflow, это стало устаревшим.

0

Следовательно, решение становится (после исправления всех частей)

Здесь я даю решение в Matlab, но если у вас есть функция Тань(), вы можете легко преобразовать его в любом языке программирования. Это просто отображение полей из сетевого объекта и необходимых операций.

  • Предположим, у вас есть обученный апп (сетевой объект), который вы хотите экспортировать
  • Предположим, что имя обученной ИНС trained_ann

Вот скрипт для экспорта и тестирования. Тестирование сценария сравнивает первоначальный результат сети с 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')'; 

, где необходимы следующие две функции

Первый 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 

Второй 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

Эта функция экспорта предназначена для простого случая: только для ANN с 1input, 1output и 1hidden layer. Его можно легко расширить до более многоуровневых ANN – fermat4214

Смежные вопросы