这个例子展示了如何训练深度学习LSTM网络来使用字符嵌入生成文本。
为了训练用于文本生成的深度学习网络,训练一个序列到序列的LSTM网络来预测字符序列中的下一个字符。为了训练网络预测下一个字符,将响应指定为移动一个时间步长的输入序列。
要使用字符嵌入式,将每个培训观察转换为一系列整数,其中整数索引到字符的词汇表中。在网络中包含一个单词嵌入层,它学会嵌入角色并将整数映射到向量。
从中读取HTML代码简·奥斯汀的古腾堡项目《傲慢与偏见》电子书并使用网络阅读
和htmlTree
.
url =“https://www.gutenberg.org/files/1342/1342-h/1342-h.htm”;代码= webread (url);树= htmlTree(代码);
通过查找P
元素。指定用class忽略段落元素“目录”
使用CSS选择器“:不是(.toc)”
.
段落= findelement(树,'p:不是(.toc)');
使用从段落中提取文本数据提取HtmlText
。并删除空字符串。
textData=extractHTMLText(段落);textData(textData=="") = [];
删除少于20个字符的字符串。
idx = strlength(textData) < 20;textData (idx) = [];
将文本数据可视化到word cloud中。
图wordcloud (textData);标题(“傲慢与偏见”)
将文本数据转换为预测器的字符索引序列和响应的分类序列。
分类函数将换行符和空白条目视为未定义的。要为这些字符创建分类元素,请用特殊字符替换它们“¶
”(pilcrow,“\ x00b6”
)和“·”(中间点,“\x00B7”
)分别。为避免歧义,必须选择文本中未出现的特殊字符。这些字符不会出现在训练数据中,因此可用于此目的。
newlineCharacter=compose(“\ x00b6”);WhitespaceCharacter = Compose(“\x00B7”);textData =取代(textData,[换行符”“]、[newlineCharacter whitespaceCharacter]);
循环文本数据,创建一系列字符索引,表示每次观察的字符,并为响应创建一系列分类字符。要表示每次观察的结束,请包含特殊字符“␃" (案文结束,“\x2403”
).
endOfTextCharacter=compose(“\x2403”);numdocuments = numel(textdata);对于i=1:numDocuments characters=textData{i};X=双精度(字符);%创建带有文本结尾字符的分类响应向量。字符次= [CellStr(字符(2:结束)')'EndoftextCharacter];y =分类(Charactersshifted);xtrain {i} = x;ytrain {i} = y;结束
在训练过程中,默认情况下,软件会将训练数据拆分为小批量,并填充序列,使它们具有相同的长度。过多的填充会对网络性能产生负面影响。
为了防止训练过程添加太多的填充,可以按序列长度对训练数据进行排序,并选择一个迷你批大小,以便迷你批中的序列具有相似的长度。
获取每个观察的序列长度。
numObservations=numel(XTrain);对于i = 1:numobservations sequence = xtrain {i};Sequencelengths(i)=大小(序列,2);结束
按序列长度对数据进行排序。
[~,idx]=sort(sequencelength);XTrain=XTrain(idx);YTrain=YTrain(idx);
定义LSTM体系结构。指定一个包含400个隐藏单元的序列到序列LSTM分类网络。设置输入大小为训练数据的特征维数。对于字符索引序列,特征维数为1。指定一个维度为200的单词嵌入层,并指定单词的数量(对应于字符)作为输入数据中的最高字符值。将完全连接层的输出大小设置为响应中的类别数量。为了防止过拟合,在LSTM层之后加入一个dropout层。
单词嵌入层学习字符的嵌入,并将每个字符映射到200维向量。
inputSize =大小(XTrain {1}, 1);numClasses =元素个数(类别([YTrain {:})));(textData numCharacters = max ({}):);layer = [sequenceInputLayer(inputSize) wordEmbeddingLayer(200,numCharacters) lstmLayer(400,“OutputMode”,“序列”) dropoutLayer (0.2);fullyConnectedLayer (numClasses) softmaxLayer classificationLayer];
指定训练选项。指定以最小批量大小32和初始学习率0.01进行训练。若要防止渐变爆炸,请将渐变阈值设置为1。若要确保数据保持排序,请设置“洗牌”
到“从来没有”
.要监控培训进度,请设置“情节”
选择“培训进度”
。若要抑制详细输出,请设置“详细”
到假
.
选择= trainingOptions (“亚当”,...“MiniBatchSize”,32,...“InitialLearnRate”, 0.01,...“GradientThreshold”, 1...“洗牌”,“从来没有”,...“情节”,“培训进度”,...“详细”,错误的);
培训网络。
net = trainnetwork(xtrain,ytrain,图层,选项);
根据训练数据中文本的第一个字符,通过从概率分布中采样一个字符来生成文本的第一个字符。通过使用经过训练的LSTM网络生成剩余字符,以使用生成的文本的当前序列预测下一个序列。继续逐个生成字符il网络预测“文本结束”字符。
根据训练数据中第一个字符的分布对第一个字符进行采样。
InitialCharacters = ExtractBefore(TextData,2);firstcharacter = dataSample(initialcharacters,1);生成ext = first特征;
将第一个字符转换为数字索引。
X=双精度(字符(第一个字符));
对于其余预测,根据网络的预测分数对下一个字符进行采样。预测分数表示下一个字符的概率分布。从网络输出层的类名给出的字符词汇表中抽取字符样本。从网络的分类层获取词汇表。
词汇=字符串(net.Layers(结束).ClassNames);
一个字一个字地使用预测预测和更新房地产
.对于每个预测,输入前一个字符的索引。停止预测网络何时预测到文本字符的结束,或者生成的文本何时有500个字符长。对于大量数据、长序列或大型网络,GPU上的预测通常比CPU上的预测更快。否则,对CPU的预测通常计算得更快。对于单时间步长预测,使用CPU。要使用CPU进行预测,请设置“执行环境”
选择预测和更新房地产
到“cpu”
.
最大长度= 500;而strlength (generatedText) <最大长度%预测下一个角色的得分。[净,characterScores] = predictAndUpdateState(净,X,“执行环境”,“cpu”);%样本下一个字符。newCharacter=datasample(词汇表,1,“重量”, characterScores);停止预测文本的结尾。如果newCharacter==endOfTextCharacter打破结束%将字符添加到生成的文本中。generatedText = generatedText + newCharacter;%获取角色的数字索引。x = double(char(newcharacter));结束
通过将特殊字符替换为相应的空白字符和新行字符来重建生成的文本。
生成的文本= replace(生成的文本,[newlineCharacter whitespaceCharacter],[换行符”“])
“我希望达西先生跟我一样,诚心诚意地选择了亲戚关系。我们本来是要去找卢卡斯家的。她们是象韦翰爵士那样嫁给他的,因为这两个人认识他,就有可能做现在的事,而且机会就像她们和我读到的那样;丽萃也没有,因为她在思念着香气;看了几次,我从来没有走到有利的情况下;强迫自己。她们可怜又活泼地相信,她是要请客的,因为我太过份了。”
若要生成多段文本,请使用重置静止
.
净=重置状态(净);
lstmLayer
|序列输入层
|培训选项
|trainNetwork
|doc2sequence
(文本分析工具箱)|提取HtmlText
(文本分析工具箱)|Fedelement.
(文本分析工具箱)|htmlTree
(文本分析工具箱)|令人畏缩的鳕文
(文本分析工具箱)|wordcloud
(文本分析工具箱)|wordEmbeddingLayer
(文本分析工具箱)