训练记忆力的简单高效方法,C#语言LSTM长短期记忆网络实战

极简大道 极简大道 2022-10-15 精品记忆课 阅读: 177
摘要: #程序员#

#程序员##IT##人工智能#

神经网络技术在机器学习中成为主流,也逐渐发展出来高级版本,LSTM长短期记忆网络就是一种高级版本。神经网络中网络细胞运算处理运算因子,LSTM加入了因子类型,扩展了细胞运算架构,能够有效地提升学习率,识别出好结果。
锐英源软件在kaldi中应用了LSTM,执行了LSTM训练用的一些脚本,对LSTM结合Python经验丰富,本文结合C#语言应用LSTM技术,描述了一个算法实现细节,信息来源于国外网站,锐英源软件进行了翻译和注解,部分信息著作权归属国外专家。
-------------------------翻译开始---------------------
在这篇文章中,我将展示如何在 C# 中实现 CNTK 106 教程。本教程讲座是用 Python 编写的,没有 C# 中的相关示例。出于这个原因,我决定将这个非常好的教程翻译成 C#。该教程可以在
CNTK 106: Part A – Time series prediction with LSTM (Basics)中找到,并使用正弦波函数来预测时间序列数据。对于这个问题,使用了 Long Short Term Memory,LSTM,Recurrent Neural Network。

目标

本教程的目标是预测连续函数(正弦波)的模拟数据。根据函数的先前值,其中是在时间观察到的幅度信号,对 的值的预测将预测相应的未来时间点。
本教程的精彩之处在于使用了非常适合此类问题的 LSTM 循环神经网络。你可能知道,LSTM 是一种特殊的循环神经网络,它能够在训练过程中从经验中学习。更多关于这个奇妙版本的循环神经网络的信息可以在这里找到。
博文分为几个小节:

  1. 模拟数据部分

  2. LSTM 网络

  3. 模型训练和评估

由于模拟数据集很大,原始教程有两种运行模式,由变量isFast控制。在快速模式的情况下,变量设置为True,本教程将使用此模式。稍后,读者可能会False为了看到更好的训练模型而将值更改为,但训练时间会更长。此博客文章的演示向用户公开了批量大小和迭代次数的变量,因此用户可以根据需要定义这些数字。

数据生成

为了生成模拟的正弦波数据,我们将实现几个辅助方法。让 和 分别是正弦波的过去值和未来(期望的预测值)的有序集合。两种方法的实现:

生成波数据集()

采用generateWaveDataset周期函数、一组独立值(对应于这种情况下的时间)并通过提供时间步长和时移来生成波函数。该方法与generate_data()原始教程中的 python 方法有关。


static Dictionary<string, (float[][] train, float[][] valid, float[][] test)>
loadWaveDataset(Func<double, double> fun, float[] x0, int timeSteps, int timeShift)
{
///
/fill data
float[] xsin = new float[x0.Length];
//all data
for (int l = 0; l < x0.Length; l++)
xsin[l] = (float)fun(x0[l]);

//split data on training and testing part
var a = new float[xsin.Length - timeShift];
var b = new float[xsin.Length - timeShift];

for (int l = 0; l < xsin.Length; l++)
{
//
if (l < xsin.Length - timeShift) a[l] = xsin[l];
// if (l >= timeShift)
b[l - timeShift] = xsin[l];
}

//make arrays of data
var a1 = new List<float[]>();
var b1 = new List<float[]>();
for (int i = 0; i < a.Length - timeSteps + 1; i++)
{
//features
var row = new float[timeSteps];
for (int j = 0; j < timeSteps; j++)
row[j] = a[i + j];
//create features row
a1.Add(row);
//label row
b1.Add(new float[] { b[i + timeSteps - 1] });
}

//split data into train, validation and test data set
var xxx = splitData(a1.ToArray(), 0.1f, 0.1f);
var yyy = splitData(b1.ToArray(), 0.1f, 0.1f);

var retVal = new Dictionary<string, (float[][] train, float[][] valid, float[][] test)>();
retVal.Add("features", xxx);
retVal.Add("label", yyy);
return retVal;
}

注:注意代码里的()元组形式,这和python类似了。另外var动态变量类型也和python类似了。
生成数据后,要创建三个数据集: train、validate 和test,test是上述方法生成的数据拆分而来。下面的splitData方法将原dataset分成三个datasets:


static (float[][] train, float[][] valid, float[][] test) splitData(float[][] data,
float valSize = 0.1f, float testSize = 0.1f)
{
//calculate
var posTest = (int)(data.Length * (1 - testSize));
var posVal = (int)(posTest * (1 - valSize));

return (data.Skip(0).Take(posVal).ToArray(),
data.Skip(posVal).Take(posTest - posVal).ToArray(), data.Skip(posTest).ToArray());
}

为了可视化数据,创建了 Windows 窗体项目。此外,使用 ZedGraph .NET 类库来可视化数据。下图显示了生成的数据。

网络建模

如博客文章开头所述,我们将创建 LSTM 循环神经网络,每个输入有 1 个 LSTM 单元。我们有 N 个输入,每个输入都是连续函数中的一个值。LSTM 的 N 个输出是产生单个输出的密集层的输入。在 LSTM 和密集层之间,我们插入了一个 dropout 层,该层随机丢弃来自 LSTM 的 20% 的值,以防止模型过度拟合训练数据集。我们想在训练期间使用 dropout 层,但是在使用模型进行预测时,我们不想丢弃值。
LSTM 的实现可以用一种方法进行总结,但真正的实现可以在本文随附的演示示例中查看。
以下方法实现了上图所示的 LSTM 网络。该方法的参数已经定义。


public static Function CreateModel(Variable input, int outDim, int LSTMDim,
int cellDim, DeviceDescriptor device, string outputName)
{

Func<Variable, Function> pastValueRecurrenceHook = (x) => CNTKLib.PastValue(x);

//creating LSTM cell for each input variable
Function LSTMFunction = LSTMPComponentWithSelfStabilization<float>(
input,
new int[] { LSTMDim },
new int[] { cellDim },
pastValueRecurrenceHook,
pastValueRecurrenceHook,
device).Item1;

//after the LSTM sequence is created return the last cell in order to
//continue generating the network
Function lastCell = CNTKLib.SequenceLast(LSTMFunction);

//implement drop out for 10%
var dropOut = CNTKLib.Dropout(lastCell,0.2, 1);

//create last dense layer before output
var outputLayer = FullyConnectedLinearLayer(dropOut, outDim, device, outputName);

return outputLayer;
}

注:Func<Variable, Function> pastValueRecurrenceHook = (x) => CNTKLib.PastValue(x);Func委托,结果是Function函数,x是参数,实际函数代码是CNTKLib.PastValue(x)。

训练网络

为了训练模型,nextBatch()实施了产生以提供训练功能的批次方法。请注意,由于 CNTK 支持可变序列长度,我们必须将批次作为序列列表提供。这是生成小批量数据的便利功能,通常称为小批量。


private static IEnumerable<(float[] X, float[] Y)> nextBatch(float[][] X, float[][] Y, int mMSize)
{

float[] asBatch(float[][] data, int start, int count)
{
var lst = new List<float>();
for (int i = start; i < start + count; i++) { if (i >= data.Length)
break;

lst.AddRange(data[i]);
}
return lst.ToArray();
}

for (int i = 0; i <= X.Length - 1; i += mMSize)
{ var size = X.Length - i; if (size > 0 && size > mMSize)
size = mMSize;

var x = asBatch(X, i, size);
var y = asBatch(Y, i, size);

yield return (x, y);
}
}

注意:由于本教程是作为 WinForms C# 项目实现的,它可以可视化训练和测试数据集,并且可以在训练过程中显示最佳找到的模型,所以还有很多其他实现的方法,这里没有提到,但是可以可以在此博客文章所附的演示源代码中找到。

关键见解

使用 LSTM 时,用户应注意以下几点:
由于 LSTM 必须使用未知维度的轴,因此应该以不同的方式定义变量,就像我们在之前的博客文章中看到的那样。因此,输入和输出变量使用以下代码清单进行初始化:


// build the model
var feature = Variable.InputVariable(new int[] { inDim },
DataType.Float, featuresName, null, false
/*isSparse*/);
var label = Variable.InputVariable(new int[] { ouDim },
DataType.Float, labelsName, new List<CNTK.Axis>() { CNTK.Axis.DefaultBatchAxis() }, false);

如原始教程中所述:“指定动态轴使递归引擎能够以预期的顺序处理时间序列数据。请花点时间了解如何在 CNTK 中同时使用静态和动态轴,如此处所述“,动态轴是 LSTM 中的关键点。
现在继续执行定义学习率、动量、学习者和训练者。


var lstmModel = LSTMHelper.CreateModel(feature, ouDim, hiDim, cellDim, device, "timeSeriesOutput");

Function trainingLoss = CNTKLib.SquaredError(lstmModel, label, "squarederrorLoss");
Function prediction = CNTKLib.SquaredError(lstmModel, label, "squarederrorEval");

// prepare for training
TrainingParameterScheduleDouble learningRatePerSample =
new TrainingParameterScheduleDouble(0.0005, 1);
TrainingParameterScheduleDouble momentumTimeConstant = CNTKLib.MomentumAsTimeConstantSchedule(256);

IList<Learner> parameterLearners = new List<Learner>() {
Learner.MomentumSGDLearner(lstmModel.Parameters(),
learningRatePerSample, momentumTimeConstant,
/*unitGainMomentum = */true) };

//create trainer
var trainer = Trainer.CreateTrainer(lstmModel, trainingLoss, prediction, parameterLearners);

现在代码已经准备好了,这 10 个 epoch 应该会返回可接受的结果:


// train the model
for (int i = 1; i <= iteration; i++)
{
//get the next minibatch amount of data
foreach (var miniBatchData in nextBatch(featureSet.train, labelSet.train, batchSize))
{
var xValues = Value.CreateBatch<float>(new NDShape(1, inDim), miniBatchData.X, device);
var yValues = Value.CreateBatch<float>(new NDShape(1, ouDim), miniBatchData.Y, device);

//Combine variables and data in to Dictionary for the training
var batchData = new Dictionary<Variable, Value>();
batchData.Add(feature, xValues);
batchData.Add(label, yValues);

//train minibatch data
trainer.TrainMinibatch(batchData, device);
}

if (this.InvokeRequired)
{
// Execute the same method, but this time on the GUI thread
this.Invoke(
new Action(() =>
{
//output training process
progressReport(trainer, lstmModel.Clone(), i, device);
}
));
}
else
{
//output training process
progressReport(trainer, lstmModel.Clone(), i, device);
}
}

模型评估

模型评估在训练过程中实施。通过这种方式,我们可以看到学习过程以及模型是如何变得越来越好的。
对于每个小批量,progress都会调用该方法来更新训练和测试数据集的图表。


void progressReport(Trainer trainer, Function model, int iteration, DeviceDescriptor device)
{
textBox3.Text = iteration.ToString();
textBox4.Text = trainer.PreviousMinibatchLossAverage().ToString();
progressBar1.Value = iteration;

reportOnGraphs(trainer, model, iteration, device);
}

private void reportOnGraphs(Trainer trainer, Function model, int i, DeviceDescriptor device)
{
currentModelEvaluation(trainer, model, i, device);
currentModelTest(trainer, model, i, device);
}

其他相关

脑力训练app排行榜,编记忆口诀的软件,这个软件帮你记忆任何想记住的东西,Anki,记忆神器

作者: 极简大道 时间:2024-02-27 阅读: 444
Anki,中文取日语谐音叫暗记。...

精英特快速阅读记忆训练软件,脑力训练app排行榜,6款学霸手机必备APP,家有学生党逆袭必备

作者: 极简大道 时间:2024-02-27 阅读: 147
新的一年大家都要努力吖!今天给大家带来的是学生党可以提升自我的神器软件。无论是初高中生,还是大学生上班族都用得到。破茧成蝶终有时,蓄力提升靠自己,喜欢的宝可以去试试哦。...
免费幼儿记忆力训练app,单词记忆APP开发有什么特点

免费幼儿记忆力训练app,单词记忆APP开发有什么特点

作者: 极简大道 时间:2022-10-15 阅读: 168
  中国经济的持续发展在一定程度上影响着人们的生活。经济的发展让中国和其他国家走得越来越近,外国面孔在中国也很常见。所以,学习外语对当代年轻人来说很重要,想要学好英语,背单词是必然的。...

专注力训练300题,又暴露年龄啦!盘点留在记忆深处的软件

作者: 极简大道 时间:2022-10-15 阅读: 177
1盘点留在记忆深处的软件(一)回顶部【PConline资讯】又到一年年尾时,这一年又有多少人和事离你而去?事实上在与我们每天相伴的软件领域,同样上演着一出出诞生与离开的好戏。之前很多经典软件早已不再新鲜,有些还在惨淡经营,而更多的则完全消声觅迹。反正正应了那句话,里面的人想出去,外面的人想进来!这里就像围城一样,吸引着一波又一波的软件开发者前赴后继。今天小编就给大家盘点一下,那些留在我们记忆深处的软件们!...

记忆宫殿训练软件,能秒杀众多背单词软件的记忆神器Anki,真有那么厉害吗?

作者: 极简大道 时间:2022-10-15 阅读: 180
  俗话说,活到老学到老,人这一生从出生开始就在学习,学习走路、跑步,到老了也在学习社会上的各种经验等等。  而且,对于现代的年轻人来说,很多人都会因为上班后,才发现原来学历是一件真的很重要的事情,于是他们利用下班后的休息时间,开始考成人本科,考研等等。这件事情在活到老学到老以及学无止境这些词汇上也是表现的很明显。  而且不论你是在自己考专科、考本科还是考研,学习英语这件事情,一直都会跟随着我们。而如果你学习的是与外语相关的专业的话,那么不知道你有没有听说过Anki这个软件呢?不管你有没有听说过,反正小编已经是听过很多次了。那么它到底是个什么软件呢?...

成年逻辑思维训练软件,艾宾浩斯记忆法工具推荐(APP+表格)!

作者: 极简大道 时间:2022-10-15 阅读: 188
在现在这个智能的时代,手机功能无比的强大,只要有合适的APP。由于本篇是推荐工具,而不是讲记忆方法,所以如果不知道艾宾浩斯记忆法的话可以自己查一下:)直接正题:在APP STORE 里面搜索:艾宾浩斯,仅出现一下三个符合条件的记忆软件:...

年度爆文