主要内容

傲慢与偏见和MATLAB

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

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

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

负荷训练数据

读取HTML代码《傲慢与偏见》古腾堡计划电子书,简·奥斯汀著然后使用webread而且htmlTree

url =“https://www.gutenberg.org/files/1342/1342-h/1342-h.htm”;代码= webread(url);tree = htmlTree(code);

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

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

从段落中提取文本数据extractHTMLText.然后去掉空字符串。

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

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

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

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

图wordcloud (textData);标题(《傲慢与偏见》

将文本数据转换为序列

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

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

newlineCharacter = compose(“\ x00B6”);whitespaceCharacter = compose(“\ x00B7”);textData = replace(textData,[换行符”“]、[newlineCharacter whitespaceCharacter]);

遍历文本数据并创建表示每个观察结果的字符的字符索引序列和用于响应的字符分类序列。为了表示每个观察的结束,包括特殊字符“␃”(文本的结束,“\ x2403”).

endOfTextCharacter =合成(“\ x2403”);numDocuments = numel(textData);i = 1:numDocuments characters = textData{i};X = double(字符);创建带有文本结尾字符的分类响应向量。charactersmoved = [cellstr(characters(2:end)')' endOfTextCharacter];Y = categorical(characters移位);XTrain{i} = X;YTrain{i} = Y;结束

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

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

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

numObservations = numel(XTrain);i=1:numObservations sequence = XTrain{i};sequenceLengths(i) = size(sequence,2);结束

按序列长度对数据进行排序。

[~,idx] = sort(sequenceLengths);XTrain = XTrain(idx);YTrain = YTrain(idx);

创建并训练LSTM网络

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

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

inputSize = size(XTrain{1},1);numClasses = number (categories([YTrain{:}]));numCharacters = max([textData{:}]);图层= [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网络生成剩余的字符,使用生成的文本的当前序列预测下一个序列。继续一个接一个地生成字符,直到网络预测到“文本结束”字符。

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

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

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

X = double(char(firstCharacter));

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

词汇= string(net.Layers(end).ClassNames);

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

maxLength = 500;strlength(generatedText) < maxLength预测下一个角色得分。[net,characterScores] = predictAndUpdateState(net,X,“ExecutionEnvironment”“cpu”);取样下一个字符。newCharacter = datasample(词汇量,1,“重量”, characterScores);在文本结尾停止预测。如果newCharacter == endOfTextCharacter打破结束将字符添加到生成的文本中。generatedText = generatedText + newCharacter;获取字符的数字索引。X = double(char(newCharacter));结束

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

generatedText = replace(generatedText,[newlineCharacter whitespaceCharacter],[换行符”“])
“我希望达西先生,像我这样的人,能诚心诚意地重新安顿下来。我们要去卢卡斯家。他们之所以跟韦翰爵士结了婚,是因为这两个人既然认识了他,现在就有一个人来办这件事,而且我读到的时候,他们的条件也很合适。丽萃也没有,她想到了那香味;对于一看的次数,我从来没有走到有利的情况下;有强迫自己。他们敦实活泼地相信她是在请客,因为,我很出色。”

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

net = resetState(net);

另请参阅

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

相关的话题

Baidu
map