Matlab - 神经网络训练
Posted
技术标签:
【中文标题】Matlab - 神经网络训练【英文标题】:Matlab - Neural network training 【发布时间】:2010-11-20 10:24:06 【问题描述】:我正在创建一个带有反向传播的 2 层神经网络。 NN 应该从 20001x17 向量中获取数据,该向量在每一行中包含以下信息:
-前 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。
在我展示代码之前,一些重要的事情:我需要使用 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。
我的问题是:我需要做一些我不需要做的转换吗?意思是,我是否必须将我的输入和/或输出数据转换为我可以实际查看我的神经网络是否正确学习的形式?
我们将不胜感激。
【问题讨论】:
【参考方案1】:这是正常的。您的输出层使用的是对数 sigmoid 传递函数,它总是会给您一些介于 0 和 1 之间的中间输出。
您通常会寻找具有最大值的输出 - 换句话说,最可能的字符。
这意味着,对于y2
中的每一列,您都在寻找包含该行中最大值的行的索引。您可以按如下方式计算:
[dummy, I]=max(y2);
I
是一个向量,包含每行中最大值的索引。
【讨论】:
马丁,感谢您的回复。使用 max(y2) 我现在至少可以获得一些关于网络正确识别字母的次数的信息。然而,在向网络提供我所拥有的数据之前,我所做的是将其缩小,以使 0 你不应该使用 max 作为活动函数,因为你的错误函数应该定义在活动而不是激活上,并且 max 是不可微分的,这意味着你不能使用 back-prop .你需要softmax,请看下面我的回答。【参考方案2】:您可以将 y2 视为每个输入为 26 个字母字符之一的输出概率分布,例如,如果 y2 的一列表示:
.2
.5
.15
.15
那么这个字符是 B 的概率为 50%(如果我们假设只有 4 个可能的输出)。
==备注==
NN 的输出层由 26 个输出。每次喂食NN 类似于上述的输入 它应该输出一个 1x26 向量 除了一个之外的所有内容都包含零 对应字母的单元格 输入值是为了 代表。例如输出 [1 0 0 ... 0] 将是字母 A,而 [0 0 0 ... 1] 将是字母 Z。
最好避免使用目标值 0,1 来编码网络的输出。 避免目标值 0 和 1 的原因是 'logsig' sigmoid 传递函数在给定有限权重的情况下无法产生这些输出值。如果您尝试训练网络以恰好适合 0 和 1 的目标值,梯度下降将迫使权重无限制地增长。 因此,不要使用 0 和 1 值,而是尝试使用 0.04 和 0.9 的值,这样 [0.9,0.04,...,0.04] 就是字母 A 的目标输出向量。 p>
参考: Thomas M. Mitchell,机器学习,McGraw-Hill 高等教育,1997,p114-115
【讨论】:
我不认为这是正确的。输出向量的每个元素都有一个在 0.00 和 1.00 之间变化的值,但任何列(或该列中的任何元素)的总和实际上永远不会代表百分比。 你总是可以自己规范化它:y2Normalized = y2 ./ repmat(sum(y2), 26, 1) 或者,您可以使用 y2 中的最高值与次高值之间的差值作为预测置信度的度量。 除非您使用概率神经网络,否则它绝对不是概率分布。它甚至不是一个置信度值,具体取决于您使用的算法以及您如何训练它。【参考方案3】:-
在输出层使用
hardlin fcn
。
-
使用
trainlm
或trainrp
训练网络。
要了解您的网络,请使用 for 循环和比较输出和目标的条件。最佳使用时,break 退出学习循环。
使用其他方式而不是mapminmax
来预处理数据集。
【讨论】:
【参考方案4】:我不知道这是否构成实际答案:但这里有一些评论。
我不明白你的编码方案。 'A' 如何表示为那组数字?看起来您陷入了一个相当常见的陷阱,即使用任意数字对分类值进行编码。不要这样做:例如,如果 'a' 是 1,'b' 是 2,'c' 是 3,那么你的编码已经隐含地表明 'a' 更像 'b' 而不是 'c'(因为网络具有实值输入,序数属性很重要)。正确执行此操作的方法是将每个字母表示为 26 个二进制值输入,其中只有一个处于活动状态,代表字母。 你的输出是正确的,输出层的激活不会 永远不是 0 或 1,而是实数。你可以把最大值作为 您的活动功能,但这是有问题的,因为它不是 可微分,所以你不能使用反向道具。你应该做的是 将输出与softmax function 耦合,这样它们的总和 是一个。然后,您可以将输出视为条件概率 给定输入,如果你愿意的话。虽然网络不 显式概率,具有正确的活动和激活 函数在结构上与对数线性模型相同 (可能带有对应于隐藏层的潜在变量), 人们一直都在这样做。请参阅David Mackay's textbook 了解神经网络的精彩介绍,这将阐明概率连接。看一下this paper from Geoff Hinton's group,它描述了在给定上下文的情况下预测下一个字符的任务,以获取有关正确表示和激活/活动功能的详细信息(尽管要注意他们的方法并不简单,并且使用具有不同训练方法的循环网络) .
【讨论】:
以上是关于Matlab - 神经网络训练的主要内容,如果未能解决你的问题,请参考以下文章