主要内容

傲慢与偏见和MATLAB

这个例子展示了如何训练一个深度学习LSTM网络来使用字符嵌入生成文本。

为了训练用于文本生成的深度学习网络,训练一个序列到序列的LSTM网络来预测字符序列中的下一个字符。为了训练网络预测下一个字符,指定响应为移动一个时间步长的输入序列。

要使用字符嵌入,请将每个训练观察值转换为整数序列,其中整数索引为字符词汇表。在网络中包括一个单词嵌入层,该层学习字符嵌入并将整数映射到向量。

负荷训练数据

读取HTML代码《傲慢与偏见古登堡计划》电子书,简·奥斯汀著并使用webreadhtmlTree

网址="https://www.gutenberg.org/files/1342/1342-h/1342-h.htm";code=webread(url);tree=htmlTree(code);

提取段落,找到p元素。指定忽略带有类的段落元素“toc”使用CSS选择器”:不(.toc)”

段落=findElement(树,“p: not (.toc)”);

从使用的段落中提取文本数据extractHTMLText.并删除空字符串。

textData = extractHTMLText(段落);textData (textData = ="") = [];

删除小于20个字符的字符串。

idx=strlength(textData)<20;textData(idx)=[];

在词云中可视化文本数据。

图wordcloud(文本数据);标题(《傲慢与偏见》

将文本数据转换为序列

将文本数据转换为预测值的字符索引序列和响应的分类序列。

Category函数将换行符和空白项视为未定义。若要为这些字符创建分类元素,请将它们替换为特殊字符““(皮尔克罗,“\x00B6”)和“·”(中间点,“\ x00B7”分别)。为防止歧义,必须选择文本中不出现的特殊字符。这些字符不会出现在训练数据中,因此可以用于此目的。

newlineCharacter =组成(“\x00B6”);whitespaceCharacter=compose(“\ x00B7”); textData=replace(textData,[newline" "],[newlineCharacter whitespaceCharacter]);

对文本数据进行循环,并创建一个字符索引序列,该序列表示每个观察到的字符,并为响应创建一个分类字符序列。要表示每个观察的结束,包括特殊字符“␃”(文本结束,“\ x2403”).

endOfTextCharacter =组成(“\ x2403”);numDocuments=numel(textData);i = 1:numDocuments字符= textData{i};X =双(字符);%创建带有文本结束字符的分类响应向量。charactersShifted=[cellstr(characters(2:end)'endOfTextCharacter];Y=分类(charactersShifted);XTrain{i}=X;YTrain{i}=Y;终止

在训练期间,默认情况下,软件将训练数据分成小批,并填充序列,使它们具有相同的长度。过多的填充会对网络性能产生负面影响。

为了防止训练过程添加过多的填充,可以按序列长度对训练数据进行排序,并选择一个小批量大小,以便小批量中的序列具有相似的长度。

获取每个观测的序列长度。

numObservations =元素个数(XTrain);i=1:numObservations序列=XTrain{i};SequenceLength(i)=大小(序列,2);终止

按序列长度对数据排序。

[~, idx] = (sequenceLengths)进行排序;XTrain = XTrain (idx);YTrain = YTrain (idx);

创建和培训LSTM网络

定义LSTM体系结构。指定一个序列,以400个隐藏单元对LSTM分类网络进行排序。将输入大小设置为训练数据的特征维度。对于字符索引序列,特征维度为1。指定维度为200的单词嵌入层,并指定单词数(对应于字符)为输入数据中的最高字符值。将完全连接层的输出大小设置为响应中的类别数。为帮助防止过度拟合,请在LSTM层之后包含一个退出层。

单词嵌入层学习字符的嵌入,并将每个字符映射到一个200维向量。

inputSize=size(XTrain{1},1);numClasses=numel(categories([YTrain{:}]);numCharacters=max([textData{:}]);layers=[sequenceInputLayer(inputSize)wordEmbeddingLayer(200,numCharacters)lstmLayer(400,“输出模式”“顺序”)dropoutLayer(0.2);fullyConnectedLayer(numClasses)softmaxLayer classificationLayer];

指定培训选项。指定训练的小批量大小为32,初始学习率为0.01。为了防止渐变发生爆炸,设置渐变阈值为1。为了确保数据保持排序,设置“洗牌”“永远”。若要监控培训进度,请设置“阴谋”选择“训练进步”.要抑制verbose输出,请设置“冗长”错误的

选项=培训选项(“亚当”...“MiniBatchSize”32岁的...“初始学习率”,0.01,...“梯度阈值”1....“洗牌”“永远”...“阴谋”“训练进步”...“冗长”,假);

培训网络。

net=列车网络(XTrain、YTrain、图层、选项);

生成新的文本

根据训练数据中文本的第一个字符,从概率分布中抽样一个字符,生成文本的第一个字符。使用训练好的LSTM网络生成剩余字符,利用生成文本的当前序列预测下一个序列。一个接一个地生成字符,直到网络预测到“文本结束”字符。

根据第一个字符在训练数据中的分布情况对第一个字符进行采样。

initialCharacters=extractBefore(textData,2);firstCharacter=datasample(initialCharacters,1);generatedText=firstCharacter;

将第一个字符转换为数字索引。

X =双(char (firstCharacter));

对于剩下的预测,根据网络的预测分数对下一个字符进行抽样。预测分数代表下一个字符的概率分布。从网络输出层的类名给出的字符词汇表中抽取字符样本。从网络的分类层获取词汇。

词汇=字符串(net.Layers(end).ClassNames);

使用predictAndUpdateState。对于每个预测,输入前一个字符的索引。当网络预测文本字符的结尾或生成的文本长度为500个字符时,停止预测。对于大型数据集合、长序列或大型网络,GPU上的预测通常比CPU上的预测计算得更快。否则,预测CPU上的操作通常计算速度更快。对于单时间步预测,请使用CPU。要使用CPU进行预测,请设置“ExecutionEnvironment”选择predictAndUpdateState“cpu”

最大长度=500;虽然strlength(生成的文本)预测下一个角色得分。[net,characterScores]=predictAndUpdateState(net,X,“ExecutionEnvironment”“cpu”);%对下一个字符进行采样。newCharacter = datasample(词汇,1,“重量”、性格分数);%在课文末尾停止预测。如果newCharacter = = endOfTextCharacter打破终止将字符添加到生成的文本中。generatedText=generatedText+新字符;%获取字符的数字索引。X=双精度(字符(新字符));终止

通过将特殊字符替换为它们相应的空格和换行符,重新构建生成的文本。

generatedText=replace(generatedText,[newlineCharacter空白字符],[newline" "])
生成的文本=”“我希望达西先生,在我这一类的人身上,能真心实意地谈一谈里兰特。我们要一起去卢卡斯家。他们像韦翰爵士那样跟他结婚,因为这两个od从那时起就认识了他,现在有可能做一件事,而且我读到的时候也有机会,丽萃也没有想到那气味,想了好几次,我从来没有利用过这个案子;我强迫过他自己。他们天真活泼地认为她在这种情况下是要处理的,因为我是个例外。”

要生成多段文本,请使用重置各代之间的网络状态重置状态

网= resetState(净);

另请参阅

|||(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)|(深度学习工具箱)||||

相关话题