2009-08-17 4 views
5

Я работаю над созданием двухслойной нейронной сети с обратным распространением. Предполагается, что NN получит свои данные из вектора 20001x17, который содержит следующую информацию в каждой строке:Matlab - Обучение нейронной сети

- Первые 16 ячеек содержат целые числа от 0 до 15, которые действуют как переменные, которые помогают нам определить, какая из 26 букв алфавита, который мы хотим выразить при просмотре этих переменных. Например, последовательность из 16 значений, как указано ниже, предназначена для обозначения буквы A: [2 8 4 5 2 7 5 3 1 6 0 8 2 7 2 7].

-17-я ячейка содержит число от 1 до 26, представляющее букву нужного нам алфавита. 1 обозначает A, 2 обозначает B и т. Д.

Выходной уровень NN состоит из 26 выходов. Каждый раз, когда NN подает вход, подобный описанному выше, он должен выводить вектор 1x26, содержащий нули во всех, кроме одной ячейки, которая соответствует букве, которую должны были представлять входные значения. например, выход [1 0 0 ... 0] будет буквой A, тогда как [0 0 0 ... 1] будет буквой Z.

Некоторые вещи, которые важны, прежде чем я представляю код: I необходимо использовать функцию traingdm и номер скрытого слоя фиксируется (на данный момент) на 21.

Попытки создать вышеуказанную концепцию я написал следующий код MatLab:

%%%%%%%% 
%Start of code% 
%%%%%%%% 

% 
%Initialize the input and target vectors 
% 
p = zeros(16,20001); 
t = zeros(26,20001); 

% 
%Fill the input and training vectors from the dataset provided 
% 
for i=2:20001 
    for k=1:16 
     p(k,i-1) = data(i,k); 
    end 
    t(data(i,17),i-1) = 1; 
end 

net = newff(minmax(p),[21 26],{'logsig' 'logsig'},'traingdm'); 

y1 = sim(net,p); 

net.trainParam.epochs = 200; 
net.trainParam.show = 1; 
net.trainParam.goal = 0.1; 
net.trainParam.lr = 0.8; 
net.trainParam.mc = 0.2; 
net.divideFcn = 'dividerand'; 
net.divideParam.trainRatio = 0.7; 
net.divideParam.testRatio = 0.2; 
net.divideParam.valRatio = 0.1; 

%[pn,ps] = mapminmax(p); 
%[tn,ts] = mapminmax(t); 

net = init(net); 
[net,tr] = train(net,p,t); 

y2 = sim(net,pn); 

%%%%%%%% 
%End of code% 
%%%%%%%% 

Теперь к моей проблеме: я хочу, чтобы мои выходы были такими, как описано, а именно каждый столбец вектора y2, например, должен представлять собой букву. Мой код этого не делает. Вместо этого он дал результаты, которые сильно варьируются от 0 до 1, значения от 0,1 до 0,9.

Мой вопрос: есть ли какие-то преобразования, которые мне нужно делать, чтобы я не был? Смысл, мне нужно преобразовать данные ввода и/или вывода в форму, с помощью которой я действительно могу увидеть, правильно ли учится NN?

Любой вход будет оценен.

ответ

2

Это нормально. Ваш выходной уровень использует функцию передачи лог-сигмоида, и это всегда даст вам промежуточный выход между 0 и 1.

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

Это будет означать, что для каждого столбца в y2 вы ищете индекс строки, которая содержит наибольшее значение в этой строке. Вы можете вычислить это следующим образом:

[dummy, I]=max(y2); 

I тогда вектор, содержащий индексы наибольшего значения в каждой строке.

+0

Мартин, спасибо за ответ. Используя max (y2), я теперь могу получить некоторую информацию о том, сколько раз сеть была права на идентификацию букв. Тем не менее, что я сделал, прежде чем подавать сеть, данные, которые у меня были, уменьшили ее, так что 0 <= p (x) <= 1. Увидев, что минимальное значение p равно 0, а максимум равен 15, я сделал новый вектор ввода scaledp = p/15. –

+0

Вы не должны использовать max в качестве функции активности, потому что ваша функция ошибки должна быть определена над активностью, а не активацией, а max недифференцируема, что означает, что вы не можете использовать back-prop. Вам нужно softmax, см. Мой ответ ниже. –

1

Вы можете думать о y2 как распределение выходной вероятности для каждого входа является одним из 26 букв алфавита, например, если один столбец y2 говорит:

.2 
.5 
.15 
.15 

то его 50% вероятность что этот символ B (если мы предполагаем только 4 возможных выхода).



== Замечание ==

Выходной слой NN состоит из 26 выходов. Каждый раз, когда NN подается вход как описанный выше он должен выводить 1x26 вектор , содержащий нули во всех, кроме одной ячейку, соответствующую букве , что входные значения предназначались для представления. например, на выходе [1 0 0 ... 0] будет буква А, в то время как [0 0 0 ... 1] будет буква З.

Предпочтительно, чтобы избежать использования целевых значений от 0,1 для кодирования вывода сети.
Причина, по которой исключить целевые значения 0 и 1, заключается в том, что 'logsig' Передача сигмоида не может производить эти выходные значения при заданных весах. Если вы попытаетесь обучить сеть, чтобы она соответствовала целевым значениям ровно 0 и 1, спуск градиента заставит весы расти без ограничений.
Итак, вместо значений 0 и 1 попробуйте использовать, например, значения 0,04 и 0,9, так что [0,9,0,04, ..., 0,04] ​​является целевым выходным вектором для буквы A.


Ссылка:
Thomas M. Mitchell, Machine Learning, McGraw-Hill Высшее образование, 1997, p114-115

+0

Я не думаю, что это правильно. Каждый элемент выходного вектора будет иметь значение, изменяющееся от 0,00 до 1,00, но сумма любого столбца (или любого элемента в этом столбце, если на то пошло) никогда не будет фактически представлять процент. –

+0

Вы всегда можете нормализовать его самостоятельно: y2Normalized = y2 ./ repmat (sum (y2), 26, 1) – Amro

+0

В качестве альтернативы вы можете использовать разницу между самым высоким значением в y2 и вторым самым высоким значением в качестве меры доверия прогнозирование. – Amro

1
  1. Использование hardlin fcn в выходном слое.
    1. Используйте trainlm или trainrp для обучения сети.
    2. Чтобы узнать вашу сеть, используйте цикл for и условие, сравнивающее результат и цель. Когда это будет наилучшим образом использовать, перерыв для выхода из цикла обучения.
    3. Используйте другой способ вместо mapminmax для набора данных предварительной обработки.
0

Я не знаю, если это является фактический ответ или нет: но здесь есть некоторые замечания.

  • Я не понимаю вашу схему кодирования. Как обозначается «А» как набор чисел? Похоже, вы попадаете в довольно распространенную ловушку использования произвольных чисел для кодирования категориальных значений. Не делайте этого: например, если «a» равно 1, «b» равно 2, а «c» равно 3, тогда ваша кодировка неявно заявила, что «a» больше напоминает «b», чем «c» (поскольку сеть имеет вещественные значения, имеющие значение порядковых свойств). Способ сделать это должным образом состоит в том, чтобы каждая буква представляла собой 26 двоично-значных входов, где только один активен, представляя букву.
  • Ваши выходы правильные, активация на выходном уровне не будет никогда не будет 0 или 1, а действительными числами. Вы можете взять max как свою активность, но это проблематично, потому что это не дифференцируемо, поэтому вы не можете использовать back-prop. Что вы должны сделать, это пара выходов с softmax function, так что их сумма является одной.Затем вы можете обрабатывать выходы как условные вероятности с учетом ввода, если вы этого желаете. В то время как сеть не явно вероятностна, с правильной активностью и активацией функции будут идентичны по структуре логарифмически линейной модели (возможно со скрытыми переменными, соответствующими скрытому слою), , и люди делают это все время ,

См. David Mackay's textbook для приятного введения в нейронные сети, которые позволят понять вероятностную связь. Взгляните на this paper from Geoff Hinton's group, в котором описывается задача прогнозирования следующего символа, заданного контекстом, для получения подробных сведений о правильных представлениях и функциях активации/активности (хотя остерегайтесь их метода нетривиальным и использует повторяющуюся сеть с другим методом обучения).

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