摄影作品展示网站flash全站源码长沙app开发公司排名

news/2025/9/22 16:00:51/文章来源:
摄影作品展示网站flash全站源码,长沙app开发公司排名,wordpress禁止更新代码,扬州商城网站制作目录 引言 1 导入数据集 2 清洗数据集 3 确定允许的最大序列长度 4 选择合理的文本和摘要 5 对文本进行标记 6 删除空文本和摘要 7 构建模型 7.1 编码器 7.2 解码器 8 训练模型 9 测试模型 10 注意 11 整体代码 引言 文本摘要是指在捕捉其本质的同时缩短长文本的…目录 引言 1 导入数据集 2 清洗数据集 3 确定允许的最大序列长度 4 选择合理的文本和摘要 5 对文本进行标记 6 删除空文本和摘要 7 构建模型 7.1 编码器 7.2 解码器 8 训练模型 9 测试模型 10 注意 11 整体代码 引言 文本摘要是指在捕捉其本质的同时缩短长文本的技术。这对于捕获大段文本的底线很有用从而减少了所需的阅读时间。本文利用使用编码器-解码器序 Seq2Seq 模型构建的深度学习模型来构建文本摘要器而不是依赖手动摘要。参考原文 在此模型中编码器接受实际文本和摘要训练模型以创建编码表示并将其发送到解码器解码器将编码表示解码为可靠的摘要。随着训练的进行训练后的模型可用于对新文本进行推理从中生成可靠的摘要。 1 导入数据集 在这里我们将使用新闻摘要数据集。它由两个 CSV 文件组成一个包含有关作者、标题、源 URL、短文章和完整文章的信息另一个仅包含标题和文本。在当前应用程序中您将从两个 CSV 文件中提取标题和文本以训练模型。 使用 pandas 的方法将新闻摘要数据集导入工作区 read_csv() import pandas as pd # 导入 pandas 库并将其重命名为 pd惯例summary pd.read_csv(./data/news_summary.csv, encodingiso-8859-1) # 从 CSV 文件中读取数据到 DataFrame指定编码为 iso-8859-1 raw pd.read_csv(./data/news_summary_more.csv, encodingiso-8859-1) # 从另一个 CSV 文件中读取数据到 DataFrame指定编码为 iso-8859-1summary 数据形式 raw 数据形式 将两个 CSV 文件中的数据合并为一个  pre1 raw.iloc[:, 0:2].copy() # 复制 raw DataFrame 的前两列数据到 pre1 DataFrame pre2 summary.iloc[:, 0:6].copy() # 复制 summary DataFrame 的前六列数据到 pre2 DataFrame# 创建一个新列 text其中包含了多个列的文本值用于构建可靠的模型 pre2[text] pre2[author].str.cat(pre2[date].str.cat(pre2[read_more].str.cat(pre2[text].str.cat(pre2[ctext], sep ), sep ), sep ), sep ) pre1 数据形式 pre2 数据形式 将两个 CSV 文件中的数据合并为一个  pre pd.DataFrame() # 创建一个空的 DataFrame pre# 将 pre1 和 pre2 中的 text 列合并到 pre DataFrame 中并忽略索引重新编号 pre[text] pd.concat([pre1[text], pre2[text]], ignore_indexTrue)# 将 pre1 和 pre2 中的 headlines 列合并到 pre DataFrame 中并忽略索引重新编号 pre[summary] pd.concat([pre1[headlines], pre2[headlines]], ignore_indexTrue) pre 数据形式第一列 text 是 raw 中 headlines 一列第二列 summary 是 raw 中 headlines 列 注意为了增加数据点的摄入量来训练模型使用一个CSV文件构造了一个新的“文本”列。 2 清洗数据集 获取的数据包含非字母字符在训练模型之前删除这些字符。 import re # 导入 re 模块用于正则表达式操作# 去除非字母字符数据清洗 def text_strip(column):for row in column:row re.sub((\\t), , str(row)).lower() # 将制表符替换为空格并转换为小写row re.sub((\\r), , str(row)).lower() # 将回车符替换为空格并转换为小写row re.sub((\\n), , str(row)).lower() # 将换行符替换为空格并转换为小写# 如果连续出现两次以上的下划线替换为空格row re.sub((__), , str(row)).lower()# 如果连续出现两次以上的减号替换为空格row re.sub((--), , str(row)).lower()# 如果连续出现两次以上的波浪线替换为空格row re.sub((~~), , str(row)).lower()# 如果连续出现两次以上的加号替换为空格row re.sub((\\), , str(row)).lower()# 如果连续出现两次以上的句点替换为空格row re.sub((\.\.), , str(row)).lower()# 移除字符 - ()|©ø,;?~*!row re.sub(r[()|©ø\[\]\\,;?~*!], , str(row)).lower()# 移除字符串 mailto:row re.sub((mailto:), , str(row)).lower()# 移除文本中的 \x9* 字符row re.sub(r(\\x9\d), , str(row)).lower()# 将 INC 后面跟着数字的部分替换为 INC_NUMrow re.sub(([iI][nN][cC]\d), INC_NUM, str(row)).lower()# 将 CM# 或者 CHG# 后面跟着数字的部分替换为 CM_NUMrow re.sub(([cC][mM]\d)|([cC][hH][gG]\d), CM_NUM, str(row)).lower()# 移除单词末尾的标点符号row re.sub((\.\s), , str(row)).lower()row re.sub((\-\s), , str(row)).lower()row re.sub((\:\s), , str(row)).lower()# 将任何 URL 替换为域名部分try:url re.search(r((https*:\/*)([^\/\s]))(.[^\s]), str(row))repl_url url.group(3)row re.sub(r((https*:\/*)([^\/\s]))(.[^\s]), repl_url, str(row))except:pass# 移除多余的空格row re.sub((\s), , str(row)).lower()# 移除两个空格之间的单个字符row re.sub((\s.\s), , str(row)).lower()yield row 在文本和摘要上调用 text_strip() 函数。 # 对 text 列进行文本处理 processed_text text_strip(pre[text]) # 对 summary 列进行文本处理 processed_summary text_strip(pre[summary]) processed_text 数据形式 processed_summary 数据形式 使用 spacy 提供的方法批量加载数据确保所有文本和摘要都具有数据类型。 import spacy # 导入 spacy 库 from time import time # 从 time 模块中导入 time 函数nlp spacy.blank(en) # 创建一个空的英语语言模型对象# 以批处理方式处理文本并按顺序生成 Doc 对象 text [str(doc) for doc in nlp.pipe(processed_text, batch_size5000)]# 对摘要文本进行处理在每个摘要前加上 _START_在每个摘要后加上 _END_ summary [_START_ str(doc) _END_ for doc in nlp.pipe(processed_summary, batch_size5000)] _START_ 和 _END_ 分别表示摘要的开始和结束用于检测和删除空摘要。 text[0] 和 summary[0] 数据形式 3 确定允许的最大序列长度 接下来将 text 和 summary 列表存储在 pandas 对象中。 pre[cleaned_text] pd.Series(text) pre[cleaned_summary] pd.Series(summary) 绘制图表以确定与文本和摘要的长度相关的频率范围即确定最大数量的文本和摘要所属的单词长度范围。 import matplotlib.pyplot as plt # 导入 matplotlib.pyplot 模块并将其重命名为 plttext_count [] # 创建一个空列表 text_count用于存储文本长度统计结果 summary_count [] # 创建一个空列表 summary_count用于存储摘要长度统计结果for sent in pre[cleaned_text]: # 遍历 pre DataFrame 中 cleaned_text 列中的每个文本text_count.append(len(sent.split())) # 将每个文本按空格分割后的单词数量添加到 text_count 列表中for sent in pre[cleaned_summary]: # 遍历 pre DataFrame 中 cleaned_summary 列中的每个摘要summary_count.append(len(sent.split())) # 将每个摘要按空格分割后的单词数量添加到 summary_count 列表中graph_df pd.DataFrame() # 创建一个空的 DataFrame graph_df用于存储文本和摘要长度统计结果graph_df[text] text_count # 将文本长度统计结果存储在 graph_df 中的 text 列中 graph_df[summary] summary_count # 将摘要长度统计结果存储在 graph_df 中的 summary 列中graph_df.hist(bins5) # 绘制图表将文本长度和摘要长度的频率分布绘制成直方图设置分箱数量为5 plt.show() # 显示绘制的直方图运行结果如下  从上图中可以确定摘要的范围大致指定为 [0-15]。  但我们无法从上图中清楚地解读最大单词数所属的范围只能用找一个随机范围查看落入该范围单词的百分比。 cnt 0 # 初始化计数器 cnt用于统计单词数量不超过 100 的文本数量for i in pre[cleaned_text]: # 遍历 pre DataFrame 中 cleaned_text 列中的每个文本if len(i.split()) 100: # 如果当前文本按空格分割后的单词数量不超过 100cnt cnt 1 # 则计数器 cnt 自增 1print(cnt / len(pre[cleaned_text])) # 打印计数器 cnt 除以 cleaned_text 列的总数即平均每个文本中单词数量不超过 100 的比例运行结果如下  现在初始化文本和摘要的最大允许长度。 max_text_len 100 # 设置文本最大长度为 100max_summary_len 15 # 设置摘要最大长度为 154 选择合理的文本和摘要 选择低于第 3 部分中定义的最大长度的文本和摘要。  import numpy as np # 导入 numpy 库并重命名为 npcleaned_text np.array(pre[cleaned_text]) # 将 cleaned_text 列转换为 numpy 数组 cleaned_summary np.array(pre[cleaned_summary]) # 将 cleaned_summary 列转换为 numpy 数组short_text [] # 创建一个空列表 short_text用于存储长度符合要求的文本 short_summary [] # 创建一个空列表 short_summary用于存储长度符合要求的摘要for i in range(len(cleaned_text)): # 遍历 numpy 数组的索引范围if len(cleaned_summary[i].split()) max_summary_len and len(cleaned_text[i].split()) max_text_len:# 如果当前摘要和文本的单词数量均不超过指定的最大长度short_text.append(cleaned_text[i]) # 将当前文本添加到 short_text 列表中short_summary.append(cleaned_summary[i]) # 将当前摘要添加到 short_summary 列表中post_pre pd.DataFrame({text: short_text,summary: short_summary}) # 创建一个新的 DataFrame post_pre包含符合要求的文本和摘要post_pre.head(2) # 显示 post_pre DataFrame 中前两行数据运行结果如下 现在添加序列的开始sostok和序列的结束eostok分别表示摘要的开始和结束。这对于在推理阶段触发摘要的开始很有用。 post_pre[summary] post_pre[summary].apply(lambda x: sostok x \ eostok) # 对 summary 列中的每个摘要应用 lambda 函数在摘要前加上 sostok 在摘要后加上 eostokpost_pre.head(2) # 显示经过处理后的 post_pre DataFrame 中前两行数据运行结果如下 5 对文本进行标记 首先将数据分成训练数据块和测试数据块。 from sklearn.model_selection import train_test_split # 导入 train_test_split 函数x_tr, x_val, y_tr, y_val train_test_split( # 使用 train_test_split 函数划分数据集并将结果赋值给四个变量np.array(post_pre[text]), # 将 text 列转换为 numpy 数组作为训练集特征 x_trnp.array(post_pre[summary]), # 将 summary 列转换为 numpy 数组作为训练集标签 y_trtest_size0.1, # 测试集占总数据的比例为 0.1random_state0, # 随机数种子为 0保证每次划分结果相同shuffleTrue, # 对数据进行随机洗牌 ) 准备文本数据并对其进行标记。 from keras.preprocessing.text import Tokenizer # 导入 Tokenizer 类 from keras.preprocessing.sequence import pad_sequences # 导入 pad_sequences 函数x_tokenizer Tokenizer() # 创建 Tokenizer 对象 x_tokenizer x_tokenizer.fit_on_texts(list(x_tr)) # 在训练集上拟合 Tokenizer将文本转换为序列并构建词汇表 查找文本中罕见单词例如出现次数少于 5 次的出现百分比。  thresh 5 # 阈值设为 5用于筛选稀有词cnt 0 # 初始化计数器 cnt用于统计稀有词的数量 tot_cnt 0 # 初始化总计数器 tot_cnt用于统计词汇表中词的总数for key, value in x_tokenizer.word_counts.items(): # 遍历 Tokenizer 对象中词频统计字典的键值对tot_cnt tot_cnt 1 # 总计数器自增 1统计词汇表中词的总数if value thresh: # 如果词频小于设定的阈值cnt cnt 1 # 计数器 cnt 自增 1统计稀有词的数量print(% of rare words in vocabulary: , (cnt / tot_cnt) * 100) # 打印稀有词在词汇表中的比例 通过考虑总单词数减去罕见出现的单词数来再次对文本进行标记。将文本转换为数字并将它们全部填充到相同的长度。 x_tokenizer Tokenizer(num_wordstot_cnt - cnt) # 根据稀有词的数量重新实例化 Tokenizer 对象num_words 参数设置为词汇表中词的总数减去稀有词的数量 x_tokenizer.fit_on_texts(list(x_tr)) # 在重新实例化的 Tokenizer 对象上拟合训练集文本x_tr_seq x_tokenizer.texts_to_sequences(x_tr) # 将训练集文本转换为序列 x_val_seq x_tokenizer.texts_to_sequences(x_val) # 将验证集文本转换为序列x_tr pad_sequences(x_tr_seq, maxlenmax_text_len, paddingpost) # 对训练集序列进行填充使其长度为 max_text_len x_val pad_sequences(x_val_seq, maxlenmax_text_len, paddingpost) # 对验证集序列进行填充使其长度为 max_text_lenx_voc x_tokenizer.num_words 1 # 计算 Tokenizer 对象中词汇表的大小加 1 是为了考虑未知词汇print(Size of vocabulary in X {}.format(x_voc)) # 打印 Tokenizer 对象中词汇表的大小运行结果如下 对摘要也执行相同的操作。 y_tokenizer Tokenizer() # 创建 Tokenizer 对象 y_tokenizer y_tokenizer.fit_on_texts(list(y_tr)) # 在训练集标签上拟合 Tokenizer 对象thresh 5 # 阈值设为 5用于筛选稀有词cnt 0 # 初始化计数器 cnt用于统计稀有词的数量 tot_cnt 0 # 初始化总计数器 tot_cnt用于统计词汇表中词的总数for key, value in y_tokenizer.word_counts.items(): # 遍历 Tokenizer 对象中词频统计字典的键值对tot_cnt tot_cnt 1 # 总计数器自增 1统计词汇表中词的总数if value thresh: # 如果词频小于设定的阈值cnt cnt 1 # 计数器 cnt 自增 1统计稀有词的数量print(% of rare words in vocabulary:, (cnt / tot_cnt) * 100) # 打印稀有词在词汇表中的比例y_tokenizer Tokenizer(num_wordstot_cnt - cnt) # 根据稀有词的数量重新实例化 Tokenizer 对象num_words 参数设置为词汇表中词的总数减去稀有词的数量 y_tokenizer.fit_on_texts(list(y_tr)) # 在重新实例化的 Tokenizer 对象上拟合训练集标签y_tr_seq y_tokenizer.texts_to_sequences(y_tr) # 将训练集标签转换为序列 y_val_seq y_tokenizer.texts_to_sequences(y_val) # 将验证集标签转换为序列y_tr pad_sequences(y_tr_seq, maxlenmax_summary_len, paddingpost) # 对训练集标签序列进行填充使其长度为 max_summary_len y_val pad_sequences(y_val_seq, maxlenmax_summary_len, paddingpost) # 对验证集标签序列进行填充使其长度为 max_summary_leny_voc y_tokenizer.num_words 1 # 计算 Tokenizer 对象中词汇表的大小加 1 是为了考虑未知词汇print(Size of vocabulary in Y {}.format(y_voc)) # 打印 Tokenizer 对象中词汇表的大小 运行结果如下 6 删除空文本和摘要 从数据中删除所有空摘要仅具有 START 和 END 标记及其关联文本。 # 从数据中删除所有空摘要仅具有 START 和 END 标记及其关联文本。 ind [] # 创建一个空列表 ind用于存储需要删除的索引for i in range(len(y_tr)): # 遍历训练集标签中的每个序列cnt 0 # 初始化计数器 cnt用于统计非零元素的数量for j in y_tr[i]: # 遍历序列中的每个元素if j ! 0: # 如果元素不为零cnt cnt 1 # 计数器 cnt 自增 1if cnt 2: # 如果序列中非零元素的数量为 2即仅具有 START 和 END 标记ind.append(i) # 将该序列的索引添加到 ind 列表中y_tr np.delete(y_tr, ind, axis0) # 使用 np.delete 函数删除训练集标签中指定索引的序列 x_tr np.delete(x_tr, ind, axis0) # 使用 np.delete 函数删除训练集文本中指定索引的文本 对验证数据也重复相同的操作。 # 对验证数据也重复相同的操作。 ind [] # 创建一个空列表 ind用于存储需要删除的索引 for i in range(len(y_val)): # 遍历验证集标签中的每个序列cnt 0 # 初始化计数器 cnt用于统计非零元素的数量for j in y_val[i]: # 遍历序列中的每个元素if j ! 0: # 如果元素不为零cnt cnt 1 # 计数器 cnt 自增 1if cnt 2: # 如果序列中非零元素的数量为 2即仅具有 START 和 END 标记ind.append(i) # 将该序列的索引添加到 ind 列表中y_val np.delete(y_val, ind, axis0) # 使用 np.delete 函数删除验证集标签中指定索引的序列 x_val np.delete(x_val, ind, axis0) # 使用 np.delete 函数删除验证集文本中指定索引的文本 继续在第 2 部分构建模型、训练模型并进行推理。 7 构建模型 首先导入所有必需的库文件。 from keras.preprocessing.text import Tokenizer # 导入 Tokenizer 类用于文本预处理 from keras.preprocessing.sequence import pad_sequences # 导入 pad_sequences 函数用于填充序列 from keras.layers import Input, LSTM, Embedding, Dense, Concatenate, TimeDistributed # 导入模型层类包括输入层、LSTM层、嵌入层、全连接层和时间分布层等 from keras.models import Model # 导入 Model 类用于构建模型 from keras.callbacks import EarlyStopping # 导入 EarlyStopping 类用于早停法回调 接下来定义编码器和解码器网络。 7.1 编码器 编码器接受的输入长度等于在第 3 部分中估计的最大文本长度。然后将其赋予维度为文本收录中抓取的单词总数 × 嵌入层中的节点数的嵌入层。接下来是 3 个 LSTM 网络其中每层返回 LSTM 输出以及在先前时间步骤中观察到的隐藏状态和单元状态。 latent_dim 300 # 定义编码器和解码器 LSTM 层的隐藏状态维度 embedding_dim 200 # 定义嵌入层的维度# Encoder编码器部分 encoder_inputs Input(shape(max_text_len, )) # 定义编码器输入形状为 (最大文本长度,)# Embedding layer嵌入层 enc_emb Embedding(x_voc, embedding_dim, trainableTrue)(encoder_inputs) # 创建可训练的嵌入层并应用于编码器输入# Encoder LSTM 1编码器 LSTM 1 encoder_lstm1 LSTM(latent_dim, return_sequencesTrue, return_stateTrue, dropout0.4, recurrent_dropout0.4) # 创建第一个编码器 LSTM 层 (encoder_output1, state_h1, state_c1) encoder_lstm1(enc_emb) # 应用编码器 LSTM 1 层于嵌入层输出# Encoder LSTM 2编码器 LSTM 2 encoder_lstm2 LSTM(latent_dim, return_sequencesTrue, return_stateTrue, dropout0.4, recurrent_dropout0.4) # 创建第二个编码器 LSTM 层 (encoder_output2, state_h2, state_c2) encoder_lstm2(encoder_output1) # 应用编码器 LSTM 2 层于第一个编码器 LSTM 输出# Encoder LSTM 3编码器 LSTM 3 encoder_lstm3 LSTM(latent_dim, return_sequencesTrue, return_stateTrue, dropout0.4, recurrent_dropout0.4) # 创建第三个编码器 LSTM 层 (encoder_outputs, state_h, state_c) encoder_lstm3(encoder_output2) # 应用编码器 LSTM 3 层于第二个编码器 LSTM 输出 7.2 解码器 在解码器中定义了一个嵌入层后面是一个 LSTM 网络。 LSTM 网络的初始状态是从编码器获取的最后一个隐藏状态和单元状态。 LSTM 的输出被提供给包裹在 TimeDistributed 层中的 Dense 层并附加了 softmax 激活函数。 # 设置解码器部分使用编码器状态作为初始状态 decoder_inputs Input(shape(None, )) # 定义解码器输入形状为 (None,)# Embedding layer嵌入层 dec_emb_layer Embedding(y_voc, embedding_dim, trainableTrue) # 创建可训练的嵌入层 dec_emb dec_emb_layer(decoder_inputs) # 应用嵌入层于解码器输入# Decoder LSTM解码器 LSTM decoder_lstm LSTM(latent_dim, return_sequencesTrue, return_stateTrue, dropout0.4, recurrent_dropout0.2) # 创建解码器 LSTM 层 (decoder_outputs, decoder_fwd_state, decoder_back_state) \decoder_lstm(dec_emb, initial_state[state_h, state_c]) # 应用解码器 LSTM 层于嵌入层输出并传入初始状态# Dense layer全连接层 decoder_dense TimeDistributed(Dense(y_voc, activationsoftmax)) # 创建时间分布的全连接层使用 softmax 激活函数 decoder_outputs decoder_dense(decoder_outputs) # 应用全连接层于解码器 LSTM 输出# 定义模型 model Model([encoder_inputs, decoder_inputs], decoder_outputs) # 创建模型输入为编码器和解码器输入输出为解码器输出print(model.summary()) # 打印模型摘要信息 运行结果如下 __________________________________________________________________________________________________Layer (type) Output Shape Param # Connected to input_1 (InputLayer) [(None, 100)] 0 [] embedding (Embedding) (None, 100, 200) 5927600 [input_1[0][0]] lstm (LSTM) [(None, 100, 300), 601200 [embedding[0][0]] (None, 300), (None, 300)] input_2 (InputLayer) [(None, None)] 0 [] lstm_1 (LSTM) [(None, 100, 300), 721200 [lstm[0][0]] (None, 300), (None, 300)] embedding_1 (Embedding) (None, None, 200) 2576600 [input_2[0][0]] lstm_2 (LSTM) [(None, 100, 300), 721200 [lstm_1[0][0]] (None, 300), (None, 300)] lstm_3 (LSTM) [(None, None, 300), 601200 [embedding_1[0][0], (None, 300), lstm_2[0][1], (None, 300)] lstm_2[0][2]] time_distributed (TimeDist (None, None, 12883) 3877783 [lstm_3[0][0]] ributed) Total params: 15026783 (57.32 MB) Trainable params: 15026783 (57.32 MB) Non-trainable params: 0 (0.00 Byte) __________________________________________________________________________________________________ 总而言之该模型接受编码器文本和解码器摘要作为输入并输出摘要。预测是通过根据摘要的前一个单词预测摘要中即将出现的单词来进行的。 8 训练模型 在训练阶段解码器接受给予模型的输入摘要并学习必须跟随某个给定单词的每个单词。 编译模型并定义 EarlyStopping 一旦验证损失指标停止减少就停止训练模型。 model.compile(optimizerrmsprop, losssparse_categorical_crossentropy) # 编译模型使用 rmsprop 优化器和稀疏分类交叉熵损失函数es EarlyStopping(monitorval_loss, modemin, verbose1, patience2) # 创建 EarlyStopping 回调函数监控验证集损失模式为最小化显示详细信息忍耐次数为2次 接下来使用该 model.fit() 方法来拟合训练数据可以将批量大小定义为 128。发送文本和摘要不包括摘要中的最后一个单词作为输入以及包含每个单词从第二个单词作为输出这解释了将智能注入模型以在给定前一个单词的情况下预测单词。此外为了在训练阶段启用验证还需要发送验证数据。 history model.fit( # 拟合模型[x_tr, y_tr[:, :-1]], # 训练数据为编码器输入和解码器输入截断最后一个词y_tr.reshape(y_tr.shape[0], y_tr.shape[1], 1)[:, 1:], # 训练标签为解码器输出截断第一个词epochs50, # 迭代次数为50轮callbacks[es], # 使用 EarlyStopping 回调函数batch_size128, # 批大小为128validation_data([x_val, y_val[:, :-1]], # 验证数据为编码器输入和解码器输入截断最后一个词y_val.reshape(y_val.shape[0], y_val.shape[1], 1)[:, 1:]), # 验证标签为解码器输出截断第一个词 ) 接下来绘制在训练阶段观察到的训练和验证损失指标。 from matplotlib import pyplot # 导入 pyplot 模块# 绘制训练集损失和验证集损失的曲线 pyplot.plot(history.history[loss], labeltrain) # 绘制训练集损失曲线设置标签为 train pyplot.plot(history.history[val_loss], labeltest) # 绘制验证集损失曲线设置标签为 test pyplot.legend() # 添加图例 pyplot.show() # 显示图像9 测试模型 在测试阶段使用推理模型生成预测。 现在我们已经训练了模型为了从给定的文本片段生成摘要首先将索引反向映射到单词。此外将单词映射到摘要分词器中的索引该索引用于检测序列的开头和结尾。 reverse_target_word_index y_tokenizer.index_word # 创建反转的目标词索引用于将索引转换为单词 reverse_source_word_index x_tokenizer.index_word # 创建反转的源词索引用于将索引转换为单词 target_word_index y_tokenizer.word_index # 获取目标词的索引 现在定义编码器和解码器推理模型以开始进行预测。使用 keras.Model() 对象创建推理模型。 编码器推理模型接受文本并返回从三个 LSTM 以及隐藏状态和单元状态生成的输出。解码器推理模型接受序列标识符 (sostok) 的开头并预测即将出现的单词最终预测整个摘要。 定义推理模型的架构。 # 推断模型# 编码输入序列以获取特征向量 encoder_model Model(inputsencoder_inputs, outputs[encoder_outputs, state_h, state_c]) # 创建编码器模型# 解码器设置# 下面的张量将保存上一个时间步长的状态 decoder_state_input_h Input(shape(latent_dim, )) # 创建解码器隐藏状态输入张量 decoder_state_input_c Input(shape(latent_dim, )) # 创建解码器细胞状态输入张量 decoder_hidden_state_input Input(shape(max_text_len, latent_dim)) # 创建解码器隐藏状态输入张量# 获取解码器序列的嵌入 dec_emb2 dec_emb_layer(decoder_inputs) # 应用嵌入层于解码器输入# 为了预测序列中的下一个词将初始状态设置为上一个时间步长的状态 (decoder_outputs2, state_h2, state_c2) decoder_lstm(dec_emb2, initial_state[decoder_state_input_h, decoder_state_input_c]) # 应用解码器 LSTM 层# 一个密集的 softmax 层生成目标词汇上的概率分布 decoder_outputs2 decoder_dense(decoder_outputs2) # 应用全连接层于解码器 LSTM 输出# 最终解码器模型 decoder_model Model([decoder_inputs] [decoder_hidden_state_input, decoder_state_input_h, decoder_state_input_c], [decoder_outputs2] [state_h2, state_c2]) # 创建解码器模型 现在定义一个函数 decode_sequence()它接受输入文本并输出预测摘要。从开始 sostok 并继续生成单词直到 sostok 遇到或达到摘要的最大长度。通过选择具有最大概率的单词来预测给定单词中即将出现的单词并相应地更新解码器的内部状态。 def decode_sequence(input_seq):# 将输入编码为状态向量(e_out, e_h, e_c) encoder_model.predict(input_seq)# 生成长度为 1 的空目标序列target_seq np.zeros((1, 1))# 使用起始词填充目标序列的第一个单词target_seq[0, 0] target_word_index[sostok]stop_condition False # 停止条件为 Falsedecoded_sentence # 初始化解码后的句子while not stop_condition: # 当停止条件为 False 时执行循环(output_tokens, h, c) decoder_model.predict([target_seq] [e_out, e_h, e_c]) # 使用解码器模型预测输出# 采样一个 tokensampled_token_index np.argmax(output_tokens[0, -1, :]) # 获取最可能的 token 索引sampled_token reverse_target_word_index[sampled_token_index] # 获取对应的单词if sampled_token ! eostok: # 如果采样的 token 不是结束标记decoded_sentence sampled_token # 添加到解码后的句子中# 退出条件达到最大长度或者找到停止词if sampled_token eostok or len(decoded_sentence.split()) max_summary_len - 1:stop_condition True # 设置停止条件为 True# 更新目标序列长度为 1target_seq np.zeros((1, 1)) # 重置目标序列target_seq[0, 0] sampled_token_index # 更新为预测的 token 索引# 更新内部状态(e_h, e_c) (h, c) # 更新编码器状态return decoded_sentence # 返回解码后的句子定义两个函数 seq2summary() 和 seq2text() 分别将摘要和文本的数字表示形式转换为字符串表示形式。 # 将序列转换为摘要 def seq2summary(input_seq): # 定义将序列转换为摘要的函数newString # 初始化新字符串for i in input_seq: # 遍历输入序列if i ! 0 and i ! target_word_index[sostok] and i ! target_word_index[eostok]: # 如果索引不是零、sostok 或 eostoknewString newString reverse_target_word_index[i] # 添加单词到新字符串return newString # 返回新字符串# 将序列转换为文本 def seq2text(input_seq): # 定义将序列转换为文本的函数newString # 初始化新字符串for i in input_seq: # 遍历输入序列if i ! 0: # 如果索引不是零newString newString reverse_source_word_index[i] # 添加单词到新字符串return newString # 返回新字符串 最后通过发送文本来生成预测。  # 打印预测结果 for i in range(0, 19): # 遍历前19个序列print(Review:, seq2text(x_tr[i])) # 打印文本序列print(Original summary:, seq2summary(y_tr[i])) # 打印原始摘要print(Predicted summary:, decode_sequence(x_tr[i].reshape(1, max_text_len))) # 打印预测摘要print(\n) # 打印空行 10 注意 原文中导入的 tensorflow 库改为下述代码 第 5 部分 第 7 部分  11 整体代码  import pandas as pd # 导入 pandas 库并将其重命名为 pd惯例 import matplotlib # 导入 matplotlib 库 matplotlib.use(TkAgg) # 使用 TkAgg 后端来绘制 matplotlib 图形summary pd.read_csv(./data/news_summary.csv, encodingiso-8859-1) # 从 CSV 文件中读取数据到 DataFrame指定编码为 iso-8859-1 raw pd.read_csv(./data/news_summary_more.csv, encodingiso-8859-1) # 从另一个 CSV 文件中读取数据到 DataFrame指定编码为 iso-8859-1pre1 raw.iloc[:, 0:2].copy() # 复制 raw DataFrame 的前两列数据到 pre1 DataFrame pre2 summary.iloc[:, 0:6].copy() # 复制 summary DataFrame 的前六列数据到 pre2 DataFrame# 创建一个新列 text其中包含了多个列的文本值用于构建可靠的模型 pre2[text] pre2[author].str.cat(pre2[date].str.cat(pre2[read_more].str.cat(pre2[text].str.cat(pre2[ctext], sep ), sep ), sep ), sep )pre pd.DataFrame() # 创建一个空的 DataFrame pre# 将 pre1 和 pre2 中的 text 列合并到 pre DataFrame 中并忽略索引重新编号 pre[text] pd.concat([pre1[text], pre2[text]], ignore_indexTrue)# 将 pre1 和 pre2 中的 headlines 列合并到 pre DataFrame 中并忽略索引重新编号 pre[summary] pd.concat([pre1[headlines], pre2[headlines]], ignore_indexTrue)import re # 导入 re 模块用于正则表达式操作# 去除非字母字符数据清洗 def text_strip(column):for row in column:row re.sub((\\t), , str(row)).lower() # 将制表符替换为空格并转换为小写row re.sub((\\r), , str(row)).lower() # 将回车符替换为空格并转换为小写row re.sub((\\n), , str(row)).lower() # 将换行符替换为空格并转换为小写# 如果连续出现两次以上的下划线替换为空格row re.sub((__), , str(row)).lower()# 如果连续出现两次以上的减号替换为空格row re.sub((--), , str(row)).lower()# 如果连续出现两次以上的波浪线替换为空格row re.sub((~~), , str(row)).lower()# 如果连续出现两次以上的加号替换为空格row re.sub((\\), , str(row)).lower()# 如果连续出现两次以上的句点替换为空格row re.sub((\.\.), , str(row)).lower()# 移除字符 - ()|©ø,;?~*!row re.sub(r[()|©ø\[\]\\,;?~*!], , str(row)).lower()# 移除字符串 mailto:row re.sub((mailto:), , str(row)).lower()# 移除文本中的 \x9* 字符row re.sub(r(\\x9\d), , str(row)).lower()# 将 INC 后面跟着数字的部分替换为 INC_NUMrow re.sub(([iI][nN][cC]\d), INC_NUM, str(row)).lower()# 将 CM# 或者 CHG# 后面跟着数字的部分替换为 CM_NUMrow re.sub(([cC][mM]\d)|([cC][hH][gG]\d), CM_NUM, str(row)).lower()# 移除单词末尾的标点符号row re.sub((\.\s), , str(row)).lower()row re.sub((\-\s), , str(row)).lower()row re.sub((\:\s), , str(row)).lower()# 将任何 URL 替换为域名部分try:url re.search(r((https*:\/*)([^\/\s]))(.[^\s]), str(row))repl_url url.group(3)row re.sub(r((https*:\/*)([^\/\s]))(.[^\s]), repl_url, str(row))except:pass# 移除多余的空格row re.sub((\s), , str(row)).lower()# 移除两个空格之间的单个字符row re.sub((\s.\s), , str(row)).lower()yield row# 对 text 列进行文本处理 processed_text text_strip(pre[text]) # 对 summary 列进行文本处理 processed_summary text_strip(pre[summary])import spacy # 导入 spacy 库 from time import time # 从 time 模块中导入 time 函数nlp spacy.blank(en) # 创建一个空的英语语言模型对象# 以批处理方式处理文本并按顺序生成 Doc 对象 text [str(doc) for doc in nlp.pipe(processed_text, batch_size5000)]# 对摘要文本进行处理在每个摘要前加上 _START_在每个摘要后加上 _END_ summary [_START_ str(doc) _END_ for doc in nlp.pipe(processed_summary, batch_size5000)]print(text[0]: , text[0]) print(summary[0]: , summary[0])# 确定最大允许序列长度 # 接下来将 text 和 summary 列表存储在 pandas 对象中。 pre[cleaned_text] pd.Series(text) pre[cleaned_summary] pd.Series(summary)# 绘制图表以确定与文本和摘要的长度相关的频率范围即确定最大数量的文本和摘要所属的单词长度范围。import matplotlib.pyplot as plt # 导入 matplotlib.pyplot 模块并将其重命名为 plttext_count [] # 创建一个空列表 text_count用于存储文本长度统计结果 summary_count [] # 创建一个空列表 summary_count用于存储摘要长度统计结果for sent in pre[cleaned_text]: # 遍历 pre DataFrame 中 cleaned_text 列中的每个文本text_count.append(len(sent.split())) # 将每个文本按空格分割后的单词数量添加到 text_count 列表中for sent in pre[cleaned_summary]: # 遍历 pre DataFrame 中 cleaned_summary 列中的每个摘要summary_count.append(len(sent.split())) # 将每个摘要按空格分割后的单词数量添加到 summary_count 列表中graph_df pd.DataFrame() # 创建一个空的 DataFrame graph_df用于存储文本和摘要长度统计结果graph_df[text] text_count # 将文本长度统计结果存储在 graph_df 中的 text 列中 graph_df[summary] summary_count # 将摘要长度统计结果存储在 graph_df 中的 summary 列中graph_df.hist(bins5) # 绘制图表将文本长度和摘要长度的频率分布绘制成直方图设置分箱数量为5 # plt.show() # 显示绘制的直方图# 从上图中可以确定摘要的范围大致指定为 [0-15] # 但我们无法从上图中清楚地解读最大单词数所属的范围只能用找一个随机范围查看落入该范围单词的百分比。 cnt 0 # 初始化计数器 cnt用于统计单词数量不超过 100 的文本数量for i in pre[cleaned_text]: # 遍历 pre DataFrame 中 cleaned_text 列中的每个文本if len(i.split()) 100: # 如果当前文本按空格分割后的单词数量不超过 100cnt cnt 1 # 则计数器 cnt 自增 1print(cnt / len(pre[cleaned_text])) # 打印计数器 cnt 除以 cleaned_text 列的总数即平均每个文本中单词数量不超过 100 的比例max_text_len 100 # 设置文本最大长度为 100max_summary_len 15 # 设置摘要最大长度为 15import numpy as np # 导入 numpy 库并重命名为 npcleaned_text np.array(pre[cleaned_text]) # 将 cleaned_text 列转换为 numpy 数组 cleaned_summary np.array(pre[cleaned_summary]) # 将 cleaned_summary 列转换为 numpy 数组short_text [] # 创建一个空列表 short_text用于存储长度符合要求的文本 short_summary [] # 创建一个空列表 short_summary用于存储长度符合要求的摘要for i in range(len(cleaned_text)): # 遍历 numpy 数组的索引范围if len(cleaned_summary[i].split()) max_summary_len and len(cleaned_text[i].split()) max_text_len:# 如果当前摘要和文本的单词数量均不超过指定的最大长度short_text.append(cleaned_text[i]) # 将当前文本添加到 short_text 列表中short_summary.append(cleaned_summary[i]) # 将当前摘要添加到 short_summary 列表中post_pre pd.DataFrame({text: short_text, summary: short_summary}) # 创建一个新的 DataFrame post_pre包含符合要求的文本和摘要print(post_pre.head(2)) # 显示 post_pre DataFrame 中前两行数据# 现在添加序列的开始sostok和序列的结束eostok分别表示摘要的开始和结束。这对于在推理阶段触发摘要的开始很有用。 # 对 summary 列中的每个摘要应用 lambda 函数在摘要前加上 sostok 在摘要后加上 eostok post_pre[summary] post_pre[summary].apply(lambda x: sostok x eostok)print(post_pre.head(2)) # 显示经过处理后的 post_pre DataFrame 中前两行数据# 首先将数据分成训练数据块和测试数据块。 from sklearn.model_selection import train_test_split # 导入 train_test_split 函数x_tr, x_val, y_tr, y_val train_test_split( # 使用 train_test_split 函数划分数据集并将结果赋值给四个变量np.array(post_pre[text]), # 将 text 列转换为 numpy 数组作为训练集特征 x_trnp.array(post_pre[summary]), # 将 summary 列转换为 numpy 数组作为训练集标签 y_trtest_size0.1, # 测试集占总数据的比例为 0.1random_state0, # 随机数种子为 0保证每次划分结果相同shuffleTrue, # 对数据进行随机洗牌 )# 准备文本数据并对其进行标记。 from keras.preprocessing.text import Tokenizer # 导入 Tokenizer 类 from keras.preprocessing.sequence import pad_sequences # 导入 pad_sequences 函数x_tokenizer Tokenizer() # 创建 Tokenizer 对象 x_tokenizer x_tokenizer.fit_on_texts(list(x_tr)) # 在训练集上拟合 Tokenizer将文本转换为序列并构建词汇表# 查找文本中罕见单词例如出现次数少于 5 次的出现百分比。 thresh 5 # 阈值设为 5用于筛选稀有词cnt 0 # 初始化计数器 cnt用于统计稀有词的数量 tot_cnt 0 # 初始化总计数器 tot_cnt用于统计词汇表中词的总数for key, value in x_tokenizer.word_counts.items(): # 遍历 Tokenizer 对象中词频统计字典的键值对tot_cnt tot_cnt 1 # 总计数器自增 1统计词汇表中词的总数if value thresh: # 如果词频小于设定的阈值cnt cnt 1 # 计数器 cnt 自增 1统计稀有词的数量print(% of rare words in vocabulary: , (cnt / tot_cnt) * 100) # 打印稀有词在词汇表中的比例# 通过考虑总单词数减去罕见出现的单词数来再次对文本进行标记。将文本转换为数字并将它们全部填充到相同的长度。 x_tokenizer Tokenizer(num_wordstot_cnt - cnt) # 根据稀有词的数量重新实例化 Tokenizer 对象num_words 参数设置为词汇表中词的总数减去稀有词的数量 x_tokenizer.fit_on_texts(list(x_tr)) # 在重新实例化的 Tokenizer 对象上拟合训练集文本x_tr_seq x_tokenizer.texts_to_sequences(x_tr) # 将训练集文本转换为序列 x_val_seq x_tokenizer.texts_to_sequences(x_val) # 将验证集文本转换为序列x_tr pad_sequences(x_tr_seq, maxlenmax_text_len, paddingpost) # 对训练集序列进行填充使其长度为 max_text_len x_val pad_sequences(x_val_seq, maxlenmax_text_len, paddingpost) # 对验证集序列进行填充使其长度为 max_text_lenx_voc x_tokenizer.num_words 1 # 计算 Tokenizer 对象中词汇表的大小加 1 是为了考虑未知词汇print(Size of vocabulary in X {}.format(x_voc)) # 打印 Tokenizer 对象中词汇表的大小y_tokenizer Tokenizer() # 创建 Tokenizer 对象 y_tokenizer y_tokenizer.fit_on_texts(list(y_tr)) # 在训练集标签上拟合 Tokenizer 对象thresh 5 # 阈值设为 5用于筛选稀有词cnt 0 # 初始化计数器 cnt用于统计稀有词的数量 tot_cnt 0 # 初始化总计数器 tot_cnt用于统计词汇表中词的总数for key, value in y_tokenizer.word_counts.items(): # 遍历 Tokenizer 对象中词频统计字典的键值对tot_cnt tot_cnt 1 # 总计数器自增 1统计词汇表中词的总数if value thresh: # 如果词频小于设定的阈值cnt cnt 1 # 计数器 cnt 自增 1统计稀有词的数量print(% of rare words in vocabulary:, (cnt / tot_cnt) * 100) # 打印稀有词在词汇表中的比例y_tokenizer Tokenizer(num_wordstot_cnt - cnt) # 根据稀有词的数量重新实例化 Tokenizer 对象num_words 参数设置为词汇表中词的总数减去稀有词的数量 y_tokenizer.fit_on_texts(list(y_tr)) # 在重新实例化的 Tokenizer 对象上拟合训练集标签y_tr_seq y_tokenizer.texts_to_sequences(y_tr) # 将训练集标签转换为序列 y_val_seq y_tokenizer.texts_to_sequences(y_val) # 将验证集标签转换为序列y_tr pad_sequences(y_tr_seq, maxlenmax_summary_len, paddingpost) # 对训练集标签序列进行填充使其长度为 max_summary_len y_val pad_sequences(y_val_seq, maxlenmax_summary_len, paddingpost) # 对验证集标签序列进行填充使其长度为 max_summary_leny_voc y_tokenizer.num_words 1 # 计算 Tokenizer 对象中词汇表的大小加 1 是为了考虑未知词汇print(Size of vocabulary in Y {}.format(y_voc)) # 打印 Tokenizer 对象中词汇表的大小# 从数据中删除所有空摘要仅具有 START 和 END 标记及其关联文本。 ind [] # 创建一个空列表 ind用于存储需要删除的索引for i in range(len(y_tr)): # 遍历训练集标签中的每个序列cnt 0 # 初始化计数器 cnt用于统计非零元素的数量for j in y_tr[i]: # 遍历序列中的每个元素if j ! 0: # 如果元素不为零cnt cnt 1 # 计数器 cnt 自增 1if cnt 2: # 如果序列中非零元素的数量为 2即仅具有 START 和 END 标记ind.append(i) # 将该序列的索引添加到 ind 列表中y_tr np.delete(y_tr, ind, axis0) # 使用 np.delete 函数删除训练集标签中指定索引的序列 x_tr np.delete(x_tr, ind, axis0) # 使用 np.delete 函数删除训练集文本中指定索引的文本# 对验证数据也重复相同的操作。 ind [] # 创建一个空列表 ind用于存储需要删除的索引 for i in range(len(y_val)): # 遍历验证集标签中的每个序列cnt 0 # 初始化计数器 cnt用于统计非零元素的数量for j in y_val[i]: # 遍历序列中的每个元素if j ! 0: # 如果元素不为零cnt cnt 1 # 计数器 cnt 自增 1if cnt 2: # 如果序列中非零元素的数量为 2即仅具有 START 和 END 标记ind.append(i) # 将该序列的索引添加到 ind 列表中y_val np.delete(y_val, ind, axis0) # 使用 np.delete 函数删除验证集标签中指定索引的序列 x_val np.delete(x_val, ind, axis0) # 使用 np.delete 函数删除验证集文本中指定索引的文本from keras.layers import Input, LSTM, Embedding, Dense, TimeDistributed # 导入模型层类包括输入层、LSTM层、嵌入层、全连接层和时间分布层等 from keras.models import Model # 导入 Model 类用于构建模型 from keras.callbacks import EarlyStopping # 导入 EarlyStopping 类用于早停法回调latent_dim 300 # 定义编码器和解码器 LSTM 层的隐藏状态维度 embedding_dim 200 # 定义嵌入层的维度# Encoder编码器部分 encoder_inputs Input(shape(max_text_len, )) # 定义编码器输入形状为 (最大文本长度,)# Embedding layer嵌入层 enc_emb Embedding(x_voc, embedding_dim, trainableTrue)(encoder_inputs) # 创建可训练的嵌入层并应用于编码器输入# Encoder LSTM 1编码器 LSTM 1 encoder_lstm1 LSTM(latent_dim, return_sequencesTrue, return_stateTrue, dropout0.4, recurrent_dropout0.4) # 创建第一个编码器 LSTM 层 (encoder_output1, state_h1, state_c1) encoder_lstm1(enc_emb) # 应用编码器 LSTM 1 层于嵌入层输出# Encoder LSTM 2编码器 LSTM 2 encoder_lstm2 LSTM(latent_dim, return_sequencesTrue, return_stateTrue, dropout0.4, recurrent_dropout0.4) # 创建第二个编码器 LSTM 层 (encoder_output2, state_h2, state_c2) encoder_lstm2(encoder_output1) # 应用编码器 LSTM 2 层于第一个编码器 LSTM 输出# Encoder LSTM 3编码器 LSTM 3 encoder_lstm3 LSTM(latent_dim, return_sequencesTrue, return_stateTrue, dropout0.4, recurrent_dropout0.4) # 创建第三个编码器 LSTM 层 (encoder_outputs, state_h, state_c) encoder_lstm3(encoder_output2) # 应用编码器 LSTM 3 层于第二个编码器 LSTM 输出# 设置解码器部分使用编码器状态作为初始状态 decoder_inputs Input(shape(None, )) # 定义解码器输入形状为 (None,)# Embedding layer嵌入层 dec_emb_layer Embedding(y_voc, embedding_dim, trainableTrue) # 创建可训练的嵌入层 dec_emb dec_emb_layer(decoder_inputs) # 应用嵌入层于解码器输入# Decoder LSTM解码器 LSTM decoder_lstm LSTM(latent_dim, return_sequencesTrue, return_stateTrue, dropout0.4, recurrent_dropout0.2) # 创建解码器 LSTM 层 (decoder_outputs, decoder_fwd_state, decoder_back_state) \decoder_lstm(dec_emb, initial_state[state_h, state_c]) # 应用解码器 LSTM 层于嵌入层输出并传入初始状态# Dense layer全连接层 decoder_dense TimeDistributed(Dense(y_voc, activationsoftmax)) # 创建时间分布的全连接层使用 softmax 激活函数 decoder_outputs decoder_dense(decoder_outputs) # 应用全连接层于解码器 LSTM 输出# 定义模型 model Model([encoder_inputs, decoder_inputs], decoder_outputs) # 创建模型输入为编码器和解码器输入输出为解码器输出print(model.summary()) # 打印模型摘要信息# 训练模型 model.compile(optimizerrmsprop, losssparse_categorical_crossentropy) # 编译模型使用 rmsprop 优化器和稀疏分类交叉熵损失函数es EarlyStopping(monitorval_loss, modemin, verbose1, patience2) # 创建 EarlyStopping 回调函数监控验证集损失模式为最小化显示详细信息忍耐次数为2次history model.fit( # 拟合模型[x_tr, y_tr[:, :-1]], # 训练数据为编码器输入和解码器输入截断最后一个词y_tr.reshape(y_tr.shape[0], y_tr.shape[1], 1)[:, 1:], # 训练标签为解码器输出截断第一个词epochs50, # 迭代次数为50轮callbacks[es], # 使用 EarlyStopping 回调函数batch_size128, # 批大小为128validation_data([x_val, y_val[:, :-1]], # 验证数据为编码器输入和解码器输入截断最后一个词y_val.reshape(y_val.shape[0], y_val.shape[1], 1)[:, 1:]), # 验证标签为解码器输出截断第一个词 )# 接下来绘制在训练阶段观察到的训练和验证损失指标。 from matplotlib import pyplot # 导入 pyplot 模块# 绘制训练集损失和验证集损失的曲线 pyplot.plot(history.history[loss], labeltrain) # 绘制训练集损失曲线设置标签为 train pyplot.plot(history.history[val_loss], labeltest) # 绘制验证集损失曲线设置标签为 test pyplot.legend() # 添加图例 pyplot.show() # 显示图像reverse_target_word_index y_tokenizer.index_word # 创建反转的目标词索引用于将索引转换为单词 reverse_source_word_index x_tokenizer.index_word # 创建反转的源词索引用于将索引转换为单词 target_word_index y_tokenizer.word_index # 获取目标词的索引# 推断模型# 编码输入序列以获取特征向量 encoder_model Model(inputsencoder_inputs, outputs[encoder_outputs, state_h, state_c]) # 创建编码器模型# 解码器设置# 下面的张量将保存上一个时间步长的状态 decoder_state_input_h Input(shape(latent_dim, )) # 创建解码器隐藏状态输入张量 decoder_state_input_c Input(shape(latent_dim, )) # 创建解码器细胞状态输入张量 decoder_hidden_state_input Input(shape(max_text_len, latent_dim)) # 创建解码器隐藏状态输入张量# 获取解码器序列的嵌入 dec_emb2 dec_emb_layer(decoder_inputs) # 应用嵌入层于解码器输入# 为了预测序列中的下一个词将初始状态设置为上一个时间步长的状态 (decoder_outputs2, state_h2, state_c2) decoder_lstm(dec_emb2, initial_state[decoder_state_input_h, decoder_state_input_c]) # 应用解码器 LSTM 层# 一个密集的 softmax 层生成目标词汇上的概率分布 decoder_outputs2 decoder_dense(decoder_outputs2) # 应用全连接层于解码器 LSTM 输出# 最终解码器模型 decoder_model Model([decoder_inputs] [decoder_hidden_state_input, decoder_state_input_h, decoder_state_input_c], [decoder_outputs2] [state_h2, state_c2]) # 创建解码器模型def decode_sequence(input_seq):# 将输入编码为状态向量(e_out, e_h, e_c) encoder_model.predict(input_seq)# 生成长度为 1 的空目标序列target_seq np.zeros((1, 1))# 使用起始词填充目标序列的第一个单词target_seq[0, 0] target_word_index[sostok]stop_condition False # 停止条件为 Falsedecoded_sentence # 初始化解码后的句子while not stop_condition: # 当停止条件为 False 时执行循环(output_tokens, h, c) decoder_model.predict([target_seq] [e_out, e_h, e_c]) # 使用解码器模型预测输出# 采样一个 tokensampled_token_index np.argmax(output_tokens[0, -1, :]) # 获取最可能的 token 索引sampled_token reverse_target_word_index[sampled_token_index] # 获取对应的单词if sampled_token ! eostok: # 如果采样的 token 不是结束标记decoded_sentence sampled_token # 添加到解码后的句子中# 退出条件达到最大长度或者找到停止词if sampled_token eostok or len(decoded_sentence.split()) max_summary_len - 1:stop_condition True # 设置停止条件为 True# 更新目标序列长度为 1target_seq np.zeros((1, 1)) # 重置目标序列target_seq[0, 0] sampled_token_index # 更新为预测的 token 索引# 更新内部状态(e_h, e_c) (h, c) # 更新编码器状态return decoded_sentence # 返回解码后的句子# 将序列转换为摘要 def seq2summary(input_seq): # 定义将序列转换为摘要的函数newString # 初始化新字符串for i in input_seq: # 遍历输入序列if i ! 0 and i ! target_word_index[sostok] and i ! target_word_index[eostok]: # 如果索引不是零、sostok 或 eostoknewString newString reverse_target_word_index[i] # 添加单词到新字符串return newString # 返回新字符串# 将序列转换为文本 def seq2text(input_seq): # 定义将序列转换为文本的函数newString # 初始化新字符串for i in input_seq: # 遍历输入序列if i ! 0: # 如果索引不是零newString newString reverse_source_word_index[i] # 添加单词到新字符串return newString # 返回新字符串# 打印预测结果 for i in range(0, 19): # 遍历前19个序列print(Review:, seq2text(x_tr[i])) # 打印文本序列print(Original summary:, seq2summary(y_tr[i])) # 打印原始摘要print(Predicted summary:, decode_sequence(x_tr[i].reshape(1, max_text_len))) # 打印预测摘要print(\n) # 打印空行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/909566.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中文乱码速查表

从小红书贴过来的,自己保存看。侵删。为了自己能看到乱码快快解决。

使用PySide6/PyQt6实现全国省市区的级联选择组件

使用PySide6/PyQt6实现全国省市区的级联选择组件在基于BS或者H5实现全国省市区的级联选择组件,相对比较容易,一般都要有现成的封装,如对于移动端H5或者小程序的Vant4界面库,他们直接安装使用内置的数据即可进行调用…

WPF TextBlock effect DropShadrowEffect,BlurEffect

<Window x:Class="WpfApp32.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d=&quo…

重庆建设集团网站企业建设流程

目录 一、动态顺序表结构定义 二、动态顺序表初始化 三、动态顺序表打印 四、动态顺序表尾插 五、封装扩容函数 六、动态顺序表头插 七、动态顺序表的尾删 八、动态顺序表的头删 九、动态顺序表任意位置插入 十、动态顺序表任意位置删除 十一、动态顺序表销毁 十二、…

求网站建设贵阳电商网站建设

一:论语 这个有意思,我们可以从中得出的是&#xff0c;一个人过错 其实是潜意思决定的 行为见品质 但知错更改也是nice的 二:题目 三:上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* Tr…

服务周到的微网站建设wordpress地理定位

精简jdk包帖子“ 紧凑数字格式出现在JDK 12中 ”演示了对JDK 12中 NumberFormat的支持&#xff0c;以支持紧凑数字格式 。 该帖子中显示的示例仅使用NumberFormat的实例&#xff0c;这些实例是通过调用NumberFormat的新重载getCompactNumberInstance(-)方法返回的&#xff0c;因…

做网站广告公司国外销售网站怎样建设

1.使用 typeof bar “object” 判断 bar 是不是一个对象有神马潜在的弊端&#xff1f;如何避免这种弊端&#xff1f;使用 typeof 的弊端是显而易见的(这种弊端同使用 instanceof)&#xff1a;let obj {};let arr [];console.log(typeof obj object); //trueconsole.log(typ…

开发购物平台网站费用网站关键词被改

目录 一、规则 二、方法 1、seed 2、identifier 1&#xff09;选取一个身份号 2&#xff09;选取一定比例的身份号作为测试集 3&#xff09;身份号的选取&#xff1a; 3、利用scikit-learn&#xff1a; 1) 随机生成&#xff1a; 2&#xff09;注&#xff1a;分类 3&a…

控制面板网站宁波网站建设服务

背景&#xff1a; 微软和谷歌母公司Alphabet最新公布的季度财报均显示&#xff0c;由于企业客户在人工智能服务上的投入增加&#xff0c;其云计算业务实现了显著的收入增长。尽管Meta在将人工智能技术转化为收益方面稍显滞后&#xff0c;但它表示&#xff0c;其相关努力对提高…

中山做网站专业的公司如何做网站竞品分析

2020年全国研究生数学建模大赛开始啦&#xff01;各学院&#xff1a; 为在大学生中倡导学习统计、应用统计的良好氛围&#xff0c;适应大数据时代的高校统计和数据科学人才的培养要求&#xff0c;提高研究生的数据挖掘、数据分析、运用计算机处理数据的能力&#xff0c;加强创新…

建设网站的企业费用东莞网络公司哪家好

背景在使用富士施乐的一体机中(其他厂商的一体机 也类似)&#xff0c;很多人的网络环境是动态IP的&#xff0c;即打印的IP地址是不固定的&#xff0c;随着每次开机或关机会变化&#xff0c;从而经常有人反应打印机不能打印或者扫描了。。总体思路1. 检查当前的IP设置2. 把相应的…

程序员做的简单的网站企业做网站和宣传册的作用

在视频制作过程中&#xff0c;为视频添加引人注目的封面是吸引观众的关键。而当我们需要批量处理多个视频时&#xff0c;如何快速、准确地置入封面就显得尤为重要。本文将为您揭示这一高效技巧&#xff0c;让您在一分钟内学会批量置入视频封面&#xff0c;提升视频的吸引力与观…

.NET驾驭Word之力:结构化文档元素操作

在前几篇文章中,我们学习了Word对象模型的基础知识、文本操作与格式设置等内容。掌握了这些基础知识后,我们现在可以进一步深入到文档的结构化元素操作,包括段落与节的管理、表格的创建与操作以及图片的插入等。本文…

行稳、致远 | 技术驱动下的思考感悟

行稳: 做好当下,结果第一 读书和加入京东以来的这十几年,我感触最深的一个点就是要做好当下。我个人是一个思维比较跳脱,想法算是比较多的人。总是喜欢瞎折腾,喜欢想东想西。有时候有点 “这山望见那山高” 的意思…

在控制台执行这段代码可以列出所有::selection规则

// 在控制台执行这段代码可以列出所有::selection规则 Array.from(document.styleSheets).forEach(sheet => { try { Array.from(sheet.cssRules).forEach(rule => { if(rule.selectorText && rule.sele…

JDK从8升级到21的问题集

一、背景与挑战 1.升级动因 ◦Oracle长期支持策略 ◦现代特性需求:协程、模式匹配、ZGC等 ◦安全性与性能的需求 ◦AI新技术引入的版本要求 2.项目情况 ◦100+项目并行升级的协同作战 ◦多技术栈并存 ◦持续集成体系的…

网站建设公司调查报告wordpress多国语言版本

首先&#xff0c;Kafka无法保证消息的全局有序性&#xff0c;这是因为Kafka的设计中允许多个生产者并行地向同一个主题写入消息。而且&#xff0c;一个主题可能会被划分为多个分区&#xff0c;每个分区都可以在独立的生产者和消费者之间进行并行处理。因此&#xff0c;生产者将…

wordpress游客变用户品牌网站和优化网站

各位小伙伴们大家好&#xff0c;欢迎来到这个小扎扎的ElasticSearch专栏&#xff0c;本篇博客由B战尚硅谷的ElasticSearch视频总结而来&#xff0c;鉴于 看到就是学到、学到就是赚到 精神&#xff0c;这波依然是血赚 ┗|&#xff40;O′|┛ &#x1f306; 内容速览 1 es数据格…

网站色彩搭配方案泰安市高新区建设局网站

前言 当谈到异步编程时&#xff0c;C#中的async/await是一个强大且方便的工具。它使得编写并发和异步操作变得更加简单和可读&#xff0c;同时提供良好的可维护性。本文将详细解释async/await的使用&#xff0c;以及如何在C#中有效地利用它来实现异步操作。 目录 前言1. async…

先做网站装修还是先买虚拟主机wordpress china 中文

任务7:采集这5页中胜点列的数据,找出胜点最高的召唤师,将召唤师姓名填入答案中 此题采集的是胜点列表的数据如下 通过控制台审查元素查看,可以看到是乱码,记得几年前的快手,小红书,抖音也采用了此类反爬措施,html页面显示的是乱码,浏览器能正常显示数据,大概率就是…