示例加权的神经网络培训
示例加权的神经网络培训
示例加权是神经网络训练的常见变体,其中训练数据中的不同示例具有不同的重要性. 简而言之,这是通过将每个示例的损失乘以与本示例相关的权重(根据 NetTrain 执行的优化过程的更高或更低重要性)来实现的.
- 正确分类某些示例可能比分类其他示例更重要. 想象一下用于欺诈检测的二元分类器:假阳性可能是良性的,但假阴性是灾难性的. 在培训期间解决这个问题的一个方法是在正面例子上比在负面例子上放置更大的示例权重.
回归示例的权重
f = Function[# ^ 2];
Plot[f[x], {x, -4, 4}]xs = Range[-4, 4, .2];
ys = f[xs];
trainingData = Thread[xs -> ys];ListPlot[Association@trainingData, Filling -> Axis]我们训练一个没有示例加权的简单线性回归模型,作为我们可以比较示例加权训练的基线. 请注意,我们使用MeanSquaredLossLayer 作为损失函数;这实际上已经是默认的了,但是稍后我们必须明确地构建一个训练网络,所以我们现在突出显示损失函数的选择.
linear = LinearLayer[{}, "Input" -> {}]使用 NetTrain 培训模型:
results = NetTrain[linear, trainingData, All, LossFunction -> MeanSquaredLossLayer[], MaxTrainingRounds -> 5000]
unweightedNet = results["TrainedNet"]Plot[{f[x], unweightedNet[x]}, {x, -4, 4}, PlotLegends -> {"function", "baseline net"}]接下来,我们执行加权训练. 我们会创建两个数据集,分别强调原点左右的范例. 我们构建一个培训网络,将先前使用的均方损失与训练权重相乘. 这种乘法会使 NetTrain 优先为具有更高权重的示例进行优化.
Create weighted datasets using the Exp function to bias either the left or the right side of the input space:
weightedDataL = <|"Input" -> xs, "Target" -> ys, "Weight" -> Exp[-xs]|>;
weightedDataR = <|"Input" -> xs, "Target" -> ys, "Weight" -> Exp[xs]|>;weightedDataL[[All, ;; ;; 10]]weightedDataR[[All, ;; ;; 10]]ListPlot[{weightedDataL["Weight"], weightedDataR["Weight"]}, Filling -> Axis, DataRange -> {-4, 4}, PlotRange -> All, PlotLegends -> {"left-weighted", "right-weighted"}]weightedTrainingNet = NetGraph[<|"net" -> linear, "loss" -> MeanSquaredLossLayer[], "times" -> ThreadingLayer[Times]|>, {"net" -> "loss", {NetPort["Weight"], "loss"} -> "times" -> NetPort["WeightedLoss"]}]{leftNet, rightNet} = Table[
result = NetTrain[weightedTrainingNet, dataset, LossFunction -> "WeightedLoss", MaxTrainingRounds -> 5000];
NetExtract[result, "net"],
{dataset, {weightedDataL, weightedDataR}}]Plot[{f[x], unweightedNet[x], leftNet[x], rightNet[x]}, {x, -4, 4}, PlotLegends -> {"function", "unweighted net", "left-weighted net", "right-weighted net"}, PlotRange -> {All, {-5, All}}]分类的示例加权
makeCluster[mean_] := RandomVariate[NormalDistribution[mean, 1], 5000];
cluster1 = makeCluster[-1];
cluster2 = makeCluster[1];histogram = Histogram[{cluster1, cluster2}, 100, "PDF"]创建适于 NetTrain 的培训数据:
targets = Join[Table[1, 5000], Table[2, 5000]];
trainingData = <|"Input" -> Join[cluster1, cluster2], "Output" -> targets|>;我们训练一个没有示例加权的简单逻辑回归模型,作为我们可以比较示例加权训练的基线. 请注意,我们使用 CrossEntropyLossLayer 作为损失函数; 这实际上已经是默认了,但稍后我们必须明确构建一个培训网,所以我们现在突出显示它.
logistic = NetChain[{2, SoftmaxLayer[]}, "Output" -> NetDecoder["Class"]]results = NetTrain[logistic, trainingData, All, LossFunction -> CrossEntropyLossLayer["Index"], MaxTrainingRounds -> 10]
unweightedNet = results["TrainedNet"]unweightedNet[-1, "Probabilities"]unweightedNet[1, "Probabilities"]Plot[unweightedNet[x, {"Probabilities", 1}], {x, -5, 5}]接下来,我们执行加权训练. 这就要求训练数据强调属于第一个聚类的例子,并构建一个训练网络,将先前使用的交叉熵损失与训练权重相乘. 乘法会使 NetTrain 优先为具有更高权重的示例进行优化,在这种情况下,示例来自第一个聚类.
weightedTrainingData = <|"Input" -> Join[cluster1, cluster2], "Target" -> targets, "Weight" -> Map[If[#1 == 1, 5.0, 1.0]&, targets]|>;weightedTrainingData[[All, ;; ;; 1000]]weightedTrainingNet = NetGraph[<|"net" -> logistic, "loss" -> CrossEntropyLossLayer["Index"], "times" -> ThreadingLayer[Times]|>, {"net" -> "loss", {NetPort["Weight"], "loss"} -> "times" -> NetPort["WeightedLoss"]}]results = NetTrain[weightedTrainingNet, weightedTrainingData, All, LossFunction -> "WeightedLoss", MaxTrainingRounds -> 10]
weightedNet = NetExtract[results["TrainedNet"], "net"]重新附加 "Class" 解码器,它在回归网络嵌入培训网络时丢失:
weightedNet = NetReplacePart[weightedNet, "Output" -> NetDecoder["Class"]]weightedNet[-1, "Probabilities"]weightedNet[1, "Probabilities"]Show[
Plot[{unweightedNet[x, {"Probabilities", 1}], weightedNet[x, {"Probabilities", 1}]}, {x, -5, 5}, PlotLegends -> {"unweighted net", "weighted net"}, Epilog -> {Opacity[0.05], Blue}], histogram]使用 NetMeasurements 计算召回和混淆矩阵图:
NetMeasurements[unweightedNet, trainingData, {"Recall", "ConfusionMatrixPlot"}]NetMeasurements[weightedNet, trainingData, {"Recall", "ConfusionMatrixPlot"}]