Basado en TextRank+Seq2Seq+Pyqt5 artículo resumen título palabra clave sistema de generación auxiliar (incluido todo el código fuente del proyecto Python) + conjunto de datos de entrenamiento

inserte la descripción de la imagen aquí


prefacio

Basado en artículos académicos, Wikipedia y otros conjuntos de datos, este proyecto optimiza y mejora el modelo mediante la aplicación de algoritmos TextRank y Seq2Seq, y se compromete a construir un sistema de generación auxiliar integrado para resúmenes de artículos, títulos y palabras clave. Para brindar una experiencia fácil de usar, diseñamos una interfaz visual y empaquetamos todo el programa como un archivo ejecutable, que se puede ejecutar directamente en la PC.

En primer lugar, utilizamos conjuntos de datos enriquecidos, como documentos académicos y Wikipedia, como muestras de capacitación. Al entrenar y optimizar el algoritmo TextRank, podemos extraer oraciones clave y palabras clave en el artículo para formar un resumen refinado.

En segundo lugar, utilizamos el algoritmo Seq2Seq para mejorar el modelo y mejorar aún más la calidad de la generación de contenido relacionado con artículos. El modelo Seq2Seq es un modelo de secuencia a secuencia basado en una red neuronal recurrente (RNN), que puede convertir una secuencia de entrada en una secuencia de salida. Al usar el algoritmo Seq2Seq, podemos generar títulos generalizados y atractivos basados ​​en el contenido del artículo.

Al mismo tiempo, también proporcionamos a los usuarios una interfaz visual para usar fácilmente este sistema integrado de generación auxiliar. Los usuarios pueden ingresar el contenido del artículo y el sistema generará automáticamente resúmenes, títulos y palabras clave del artículo, y mostrará los resultados de manera intuitiva en la interfaz.

Para comodidad de los usuarios, empaquetamos todo el proyecto como un archivo ejecutable para que pueda ejecutarse directamente en la PC. De esta forma, los usuarios pueden abrir directamente el programa y utilizar las funciones proporcionadas por el sistema sin configuraciones y ajustes complicados.

A través de la implementación de este proyecto, los usuarios pueden generar rápidamente resúmenes de artículos, títulos y palabras clave precisos, concisos y atractivos, mejorando en gran medida la eficiencia del trabajo y la calidad de la creación. Al mismo tiempo, el diseño de la interfaz visual y los archivos ejecutables hace que el uso del sistema sea más conveniente e intuitivo, satisfaciendo las necesidades de los usuarios en cuanto a facilidad de uso.

diseño general

Esta parte incluye el diagrama de estructura general del sistema y el diagrama de flujo del sistema.

Diagrama de estructura general del sistema

La estructura general del sistema se muestra en la figura.

inserte la descripción de la imagen aquí

Diagrama de flujo del sistema

El flujo del sistema se muestra en la figura.

inserte la descripción de la imagen aquí

entorno operativo

Esta parte incluye el entorno de Python, el entorno de TextRank, el entorno de TensorFlow, PyQt5 y el entorno de tiempo de ejecución de Qt Designer.

Entorno de Python

Versión: Pitón 3.5.

Entorno TextRank

Descargue los archivos numpy-1.9.3.tar.gz, networkx-2.4.tar.gzy de la imagen del almacén de Tsinghua y, después de descomprimirlos localmente, use la línea de comando cmd para ingresar a la consola, cambie al directorio correspondiente y ejecute el siguiente comando para completar la instalación.math-0.5.tar.gz

python setup.py install 

Entorno TensorFlow

En la terminal, use el comando pip para instalar, use el comando pip para instalar tensorflow, tarfile, matplotlib, paquetes dependientes de jieba y realice la preparación de modelos relacionados con la plataforma TensorFlow.

pip3 install <package name>

Entorno operativo PyQt5 y Qt Designer

Use el comando pip para instalar el kit de herramientas PyQt5 correspondiente al lenguaje Python y configure las herramientas PyUIC5 y PyQt5 en el entorno para un rápido desarrollo y conversión de interfaces gráficas. Agregue las herramientas anteriores a ExternalTools del editor PyCharm.

Abra Qt Designer desde Tools-External Tools del editor PyCharm, como se muestra en la figura a continuación, lo que indica que Qt Designer se instaló correctamente.

inserte la descripción de la imagen aquí

Mapa de herramientas de Qt Designer

implementación del módulo

Este proyecto incluye 6 módulos: preprocesamiento de datos, resumen de extracción, construcción y compilación de modelos, entrenamiento y almacenamiento de modelos, desarrollo de interfaz gráfica y empaquetado de aplicaciones. La introducción de la función y el código relacionado de cada módulo se dan a continuación.

1. Preprocesamiento de datos

La dirección de descarga de preprocesamiento de datos es http://www.sogou.com/labs/resource/cs.php , y los datos sin procesar sin procesar se muestran en la siguiente figura.

inserte la descripción de la imagen aquí

Por su forma de codificación, debido a que el archivo es demasiado grande, es imposible obtener la codificación al abrir el archivo.Se puede usar GBK18030 para codificarlo. El proceso es el siguiente.

1) Extracción y división de datos

Use expresiones regulares para extraer el contenido de los datos, divida el conjunto de entrenamiento y el conjunto de verificación según la proporción, elimine los datos cuya longitud del contenido del texto no cumpla con los requisitos, almacene el título y el contenido divididos y use software para cambiar la codificación formato del archivo generado a utf -8. El código correspondiente es el siguiente:

a) Coincidencia de expresiones regulares:

for_title='<contenttitle>(.*)</contenttitle>'#筛选标题,去除标签
for_content='<content>(.*)</content>'#筛选内容,去除标签
p1=re.compile(for_title)
p2=re.compile(for_content)

b) Filtrado de datos para el proceso de escritura:

for i in range(4,len(data.values)+1,6):#针对位置选择相应的数据
    n=p2.findall(str(data.values[i]))
    text=n[0]
    word=text
    result=''
    for w in word:
        result=result+str(w.word)+' ' 
#对意外的情况进行替换
    result=result.replace(u'\ u3000','').replace(u'\ ue40c','')
#检查数据长度是否复合需求,太长或者太短,都要舍弃 
    if len(result)>=1024 or len(result)==0: 
        id.append(i)
        continue      
    if i<for_train:
        f_content_train.write(result+'\n')
    else:
        f_content_test.write(result+'\n')
    print((i/6)/len(range(3,len(data.values)+1,6)))

2) Sustitución y segmentación de palabras

Realice el reemplazo de etiquetas en el texto obtenido para completar la operación de segmentación de palabras. El código correspondiente es el siguiente:

def token(self, sentence):
    words = self.segmentor.segment(sentence)  #分词
    words = list(words)
    postags = self.postagger.postag(words)    #词性标注
        postags = list(postags)
        netags = self.recognizer.recognize(words, postags)#命名实体识别
        netags = list(netags)
        result = []
        for i, j in zip(words, netags):
            if j in ['S-Nh', 'S-Ni', 'S-Ns']:
             result.append(j)
               continue
        result.append(i)
    return result

Después de usar el código anterior, obtenga 4 archivos: 2 conjuntos de entrenamiento y 2 conjuntos de prueba, la misma línea del archivo correspondiente es título y contenido respectivamente. Las etiquetas se reemplazan para todos los textos para completar la segmentación de palabras.

3) Lectura de datos

Lea los datos de acuerdo con el archivo obtenido, el código relevante es el siguiente:

data_set = [[] for _ in buckets]  
with tf.gfile.GFile(source_path, mode="r") as source_file:  
  	with tf.gfile.GFile(target_path, mode="r") as target_file:
   	 source, target = source_file.readline(), target_file.readline()  
   	 counter = 0  #源文件和目标文件
   	 while source and target and (not max_size or counter < max_size):  
      counter += 1  
      if counter % 10000 == 0:  
        print("reading data line%d"% counter)#输出信息
        sys.stdout.flush()  
      source_ids = [int(x) for x in source.split()]  
      target_ids = [int(x) for x in target.split()]  
      target_ids.append(data_utils.EOS_ID)  #添加标识
      for bucket_id, (source_size, target_size) in enumerate(buckets):  
        if len(source_ids)<source_size and len(target_ids)<target_size: 
          data_set[bucket_id].append([source_ids, target_ids])  
          break  
      source, target = source_file.readline(), target_file.readline()  
return data_set  

El código leerá automáticamente la información y almacenará los datos leídos en el cubo. El modelo de aprendizaje profundo se genera aprendiendo el contenido y el título. El preprocesamiento de datos se realiza al preparar los datos, que se pueden leer usando el módulo de códecs de Python. .

2. Extraer resumen

La mayoría de los artículos tienen decenas de miles de palabras y el uso directo del modelo para entrenar y probar los datos consumirá recursos informáticos. Por lo tanto, la importancia de los datos se extrae mediante la clasificación de texto y el algoritmo es el siguiente.

1) Ordenar algoritmo iterativo

Primero, obtenga una lista binaria, la oración es una sublista y los elementos son palabras; segundo, determine el enlace al juzgar si dos palabras aparecen en la misma ventana de tiempo al mismo tiempo. Después de agregar todas las palabras a los enlaces del gráfico, use el algoritmo de PageRank para iterar y obtener un valor PR de palabra estable; finalmente, obtenga la lista de palabras importantes.

def sort_words(vertex_source, edge_source, window=2, pagerank_config={
    
    'alpha': 0.85, }):#对单词的关键程度进行排序
"""
vertex_source:二维列表,子列表代表句子,其元素是单词,用来构造PageRank中的节点
edge_source:二维列表,子列表代表句子,其元素为单词,根据单词位置关系构造PageRank中的边窗口,一个句子中相邻的window个单词,两两之间认为有边
pagerank_config:PageRank的设置
"""
     sorted_words = []
     word_index = {
    
    }
     index_word = {
    
    }
     _vertex_source = vertex_source
     _edge_source = edge_source
     words_number = 0
     for word_list in _vertex_source:#对每个句子进行处理,提取包含单词的列表
         for word in word_list:
             if not word in word_index:
#更新word_index 假如字典中没有单词,将这个单词与索引添加到字典中
             word_index[word] = words_number
               index_word[words_number] = word #对word进行反向映射
                words_number += 1
    graph = np.zeros((words_number, words_number))
#构建word_number*word_number的矩阵,实现图计算
    for word_list in _edge_source:
        for w1, w2 in combine(word_list, window):
            if w1 in word_index and w2 in word_index:
                index1 = word_index[w1]
                index2 = word_index[w2]
                graph[index1][index2] = 1.0
                graph[index2][index1] = 1.0
#根据窗口判断其连接
    nx_graph = nx.from_numpy_matrix(graph)
#构成邻接矩阵
    scores = nx.pagerank(nx_graph, **pagerank_config)  
#使用PageRank算法进行迭代
    sorted_scores = sorted(scores.items(), key=lambda item: item[1], reverse=True)
    for index, score in sorted_scores:
        item = AttrDict(word=index_word[index], weight=score)
        sorted_words.append(item)
    return sorted_words

2) Algoritmo de similitud de oraciones

Cuando se usa el algoritmo TextRank para generar una oración, el nodo predeterminado que se usa es la oración, y el peso de la conexión entre los dos nodos usa la similitud de la oración. El código correspondiente es el siguiente:

def get_similarity(word_list1, word_list2):#计算两个句子的相似程度
    	"""默认用于计算两个句子相似度的函数
    	word_list1, word_list2分别代表两个句子,都是由单词组成的列表
    	"""
    		words = list(set(word_list1 + word_list2))
    		vector1 = [float(word_list1.count(word)) for word in words]
    		#统计某个单词在句子中的频率
    	vector2 = [float(word_list2.count(word)) for word in words]
    	vector3 = [vector1[x] * vector2[x] for x in range(len(vector1))]
    		vector4 = [1 for num in vector3 if num > 0.]
    		co_occur_num = sum(vector4)#分子
    	if abs(co_occur_num) <= 1e-12:
        		return 0.
         denominator = math.log(float(len(word_list1))) + math.log(float(len(word_list2)))  #分母
   		 if abs(denominator) < 1e-12:
       	 return 0.
    	return co_occur_num / denominator #返回句子的相似度

3. Construcción y compilación de modelos

Después de completar la producción del conjunto de datos, construya el modelo, defina la entrada del modelo y determine la función de pérdida.

1) Construcción de modelos

Según el modelo proporcionado por TensorFlow, los parámetros se pasan mediante clases:

class LargeConfig(object): #定义网络结构
    		learning_rate = 1.0  #学习率
    		init_scale = 0.04
    		learning_rate_decay_factor = 0.99 #学习率下降
    		max_gradient_norm = 5.0
    		num_samples = 4096 #采样的Softmax
    		batch_size = 64
    		size = 256 #每层节点数
    		num_layers = 4 #层数
vocab_size = 50000
#模型构建
def seq2seq_f(encoder_inputs, decoder_inputs, do_decode):
      return tf.contrib.legacy_seq2seq.embedding_attention_seq2seq(
         encoder_inputs,#输入的句子
         decoder_inputs,#输出的句子
         cell,#使用的cell、LSTM或者GRU
         num_encoder_symbols=source_vocab_size,#源字典的大小
         num_decoder_symbols=target_vocab_size,#转换后字典的大小
         embedding_size=size,#embedding的大小
         output_projection=output_projection,#看字典大小
         feed_previous=do_decode,#进行训练还是测试
         dtype=tf.float32)

2) Definir la entrada del modelo

En el modelo, bucketse aceptan los caracteres de entrada, por lo que se debe construir un marcador de posición para cada elemento del depósito.

#输入
    self.encoder_inputs = []
    self.decoder_inputs = []
    self.target_weights = []
    for i in xrange(buckets[-1][0]):  
      self.encoder_inputs.append(tf.placeholder(tf.int32, shape=[None],
                                                name="encoder{0}".format(i)))
#为列表对象中的每个元素表示一个占位符,名称分别为encoder0、encoder1...
    for i in xrange(buckets[-1][1] + 1):
      self.decoder_inputs.append(tf.placeholder(tf.int32, shape=[None],
                                                name="decoder{0}".format(i)))
      self.target_weights.append(tf.placeholder(tf.float32, shape=[None],
                                                name="weight{0}".format(i)))
#target_weights 是一个与 decoder_outputs 大小一样的矩阵
#该矩阵将目标序列长度以外的其他位置填充为标量值0
#目标是将解码器输入移位1
    targets = [self.decoder_inputs[i + 1]
               for i in xrange(len(self.decoder_inputs) - 1)]
#将 decoder input向右平移一个单位

3) Determinar la función de pérdida

En la función de pérdida, la función TensorFlowen uso sampled_softmax_loss().

def sampled_loss(labels, inputs):#使用候选采样损失函数
  labels = tf.reshape(labels, [-1, 1])
#需要使用32位浮点数计算sampled_softmax_loss,以避免数值不稳定性
  local_b = tf.cast(b, tf.float32)
  local_inputs = tf.cast(inputs, tf.float32)
  return tf.cast(
      tf.nn.sampled_softmax_loss(  #损失函数
          weights=local_w_t,
          biases=local_b,
          labels=labels,
          inputs=local_inputs,
          num_sampled=num_samples,
          num_classes=self.target_vocab_size),tf.float32)

4. Entrenamiento y almacenamiento de modelos

Después de configurar la estructura del modelo, defina la función de entrenamiento del modelo para importar y llamar al modelo.

1) Definir la función de entrenamiento del modelo

Definir funciones de entrenamiento del modelo y operaciones relacionadas.

def train():
  	#准备标题数据
  	print("Preparing Headline data in %s" % FLAGS.data_dir)
	src_train,,dest_train,src_dev,dest_dev,_,_=data_utils.prepare_headline_data(FLAGS.data_dir, FLAGS.vocab_size)
#将获得的数据进行处理,包括:构建词典、根据词典单词ID的转换,返回路径
config = tf.ConfigProto(device_count={
    
    "CPU": 4}, 
                  inter_op_parallelism_threads=1, 
                  intra_op_parallelism_threads=2) 
  	with tf.Session(config = config) as sess:
    	print("Creating %d layers of %d units."%(FLAGS.num_layers, FLAGS.size))
    	model = create_model(sess, False)
   #创建模型
    	print ("Reading development and training data (limit: %d)."
           % FLAGS.max_train_data_size)
  	dev_set = read_data(src_dev, dest_dev)
    	train_set = read_data(src_train, dest_train, FLAGS.max_train_data_size)
    train_bucket_sizes = [len(train_set[b]) for b in xrange(len(buckets))]
	    train_total_size = float(sum(train_bucket_sizes))
    	trainbuckets_scale=[sum(train_bucket_sizes[:i + 1]) / train_total_size
                           for i in xrange(len(train_bucket_sizes))]
    	#进行循环训练
    	step_time, loss = 0.0, 0.0
   	current_step = 0
    	previous_losses = []
    	while True:
      		random_number_01 = np.random.random_sample()
      		bucket_id = min([i for i in xrange(len(trainbuckets_scale))
                       if trainbuckets_scale[i] > random_number_01])
              #随机选择一个bucket进行训练
      		start_time = time.time()
      		encoder_inputs,decoder_inputs,target_weights=model.get_batch(
          	train_set, bucket_id)
    _,step_loss,_=model.step(sess, encoder_inputs, decoder_inputs,
                                   target_weights, bucket_id, False)
      		step_time+=(time.time()-start_time)/FLAGS.steps_per_checkp oint 
      		loss += step_loss / FLAGS.steps_per_checkpoint
      		current_step += 1
      		if current_step % FLAGS.steps_per_checkpoint == 0:
        			perplexity=math.exp(float(loss))
if	loss<300	
else                                                                         
float("inf")
        			print ("global step %d learning rate %.4f step-time %.2f perplexity ""%.2f" % (model.global_step.eval(), 
model.learning_rate.eval(),
                         step_time, perplexity))   #输出参数
        		if len(previous_losses)>2 and loss > max(previous_losses[-3:]):
          			sess.run(model.learning_rate_decay_op)
        		previous_losses.append(loss)
checkpoint_path=os.path.join(FLAGS.train_dir, "headline_large.ckpt") 
       				model.saver.save(sess,checkpoint_path,
global_step=model.global_step) #检查点输出路径
        		step_time, loss = 0.0, 0.0
        		for bucket_id in xrange(len(buckets)):
          			if len(dev_set[bucket_id]) == 0:
            			print("  eval: empty bucket %d" % (bucket_id))
            			continue
          			encoder_inputs,decoder_inputs,target_weights= 
model.get_batch(dev_set, bucket_id)  #编解码及目标加权
          			_,eval_loss,_=model.step(sess,encoder_inputs, 
decoder_inputs, target_weights, bucket_id, True)
          			eval_ppx = math.exp(float(eval_loss))#计算损失 
if eval_loss < 300 
else float("inf")
print("eval:bucket%dperplexity%.2f"%(bucket_id, eval_ppx))#输出困惑度
        		sys.stdout.flush()

2) Modelo de importación y llamada

Coloque el modelo generado /ckptdentro de la carpeta y cargue el modelo durante la ejecución. Después de que el programa obtiene la sentencia, realiza el siguiente procesamiento:

while sentence:
      sen=tf.compat.as_bytes(sentence)
      sen=sen.decode('utf-8')
      token_ids = data_utils.sentence_to_token_ids(sen, vocab, 
normalize_digits=False)
      print (token_ids) # 打印ID
      #选择合适的bucket
      bucket_id = min([b for b in xrange(len(buckets)) if buckets[b][0] > len(token_ids)])
      print ("current bucket id" + str(bucket_id))
      encoder_inputs, decoder_inputs, target_weights = model.get_batch(
          {
    
    bucket_id: [(token_ids, [])]}, bucket_id)
            #获得模型的输出
      _, _, output_logits_batch = model.step(sess, encoder_inputs, 
decoder_inputs, target_weights,
 		  bucket_id, True)
      #贪婪解码器 
      output_logits = []
      for item in output_logits_batch:
        output_logits.append(item[0])
      print (output_logits)
      print (len(output_logits))
      print (output_logits[0])
      outputs = [int(np.argmax(logit)) for logit in output_logits]
      print(output_logits)
      #剔除程序对文本进行的标记
      if data_utils.EOS_ID in outputs:
        outputs = outputs[:outputs.index(data_utils.EOS_ID)]
      print(" ".join([tf.compat.as_str(rev_vocab[output]) for output in outputs]))

5. Desarrollo de interfaz gráfica

Para mejorar la usabilidad, el entorno de operación orientado al código se transforma en una operación orientada a la interfaz, y la interfaz gráfica del proyecto se completa a través de los entornos QtDesigner y PyQt5 proporcionados por Python.

1) Diseño de interfaz

Abra el Qt Designer configurado desde las herramientas externas de PyCharm, cree la ventana principal y use WidgetBox para diseñar los componentes, como se muestra en la siguiente figura.

inserte la descripción de la imagen aquí

La estética de los componentes nativos no es suficiente y los estilos de cada componente deben personalizarse. Seleccione para modificar la hoja de estilo del componente correspondiente en la ventana de monitoreo y complete el embellecimiento de cada componente e interfaz agregando CSS (hojas de estilo en cascada, hojas de estilo en cascada). La imagen de embellecimiento que se muestra en la siguiente figura muestra el código CSS del botón "Ingresar al programa". Aquí, el estilo básico, el estilo de clic y el estilo de desplazamiento del mouse se configuran respectivamente para acercar la lógica del botón al escenario de uso real y mejorar la experiencia del usuario

inserte la descripción de la imagen aquí

Obtenga una vista previa de la hoja de estilo modificada de la ventana principal y cada componente, como se muestra en la figura a continuación.

inserte la descripción de la imagen aquí

Imagen de vista previa del diseño de la página de inicio (el estilo del botón es un puntero flotante)

2) Conversión de código

Guarde el diseño de la interfaz anterior como un archivo .ui y use la herramienta PyUIC5 configurada para procesarlo y obtener el código .py convertido.

Ajustar los componentes del código que no se pueden renderizar ejecutando el programa, por ejemplo, modificar el icono introducido especificando la asociación a través del archivo .qrc para hacer referencia a una dirección relativa. El código correspondiente es el siguiente:

from PyQt5 import QtCore, QtGui, QtWidgets  #引入所需的库
from PyQt5 import QtCore, QtGui, QtWidgets, Qt  
from PyQt5.QtWidgets import *  
import PreEdit  
  class Ui_MainWindow_home(QtWidgets.QMainWindow):  #界面类定义
    def __init__(self):  
        super(Ui_MainWindow_home,self).__init__()  
        self.setupUi(self)  
        self.retranslateUi(self)  
      def setupUi(self, MainWindow_home):  #设置界面
        MainWindow_home.setObjectName("MainWindow_home")  
        MainWindow_home.resize(900, 650)  
        MainWindow_home.setMinimumSize(QtCore.QSize(900, 650))  
        MainWindow_home.setMaximumSize(QtCore.QSize(900, 650))  
        MainWindow_home.setBaseSize(QtCore.QSize(900, 650))  
        font = QtGui.QFont()  
        font.setFamily("黑体")  
        font.setPointSize(12)  
        MainWindow_home.setFont(font)  #设置字体
        MainWindow_home.setStyleSheet("QMainWindow#MainWindow_home{\n"  
            "background:#FFFEF8\n}")  
        self.centralwidget = QtWidgets.QWidget(MainWindow_home)  
        self.centralwidget.setStyleSheet("")  #设置表单风格
        self.centralwidget.setObjectName("centralwidget")  
       self.pushButton_openfile=QtWidgets.QPushButton(self.centralwidget)
       self.pushButton_openfile.setGeometry(QtCore.QRect(320,328,258,51))
        font = QtGui.QFont()  
        font.setFamily("等线")  
        font.setPointSize(11)  
        font.setBold(True)  
        font.setWeight(75)  
        self.pushButton_openfile.setFont(font)  #单击按钮,自动浏览文件设置
        self.pushButton_openfile.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))  
        self.pushButton_openfile.setStyleSheet("QPushButton#pushButton_openfile{  \n"  
            "border: 1px solid #9a8878;  \n"  
            "background-color:#ffffff;\n"  
            "border-style: solid;  \n"  
            "border-radius:0px;  \n"  
            "width: 40px; \n"  
            "height:20px;  \n"  
            "padding:0 0px;  \n"  
            "margin:0 0px;  \n"  
            "}  \n"  
            "\n"  
            "QPushButton#pushButton_openfile:pressed{\n"  
            "background-color:#FBF7F6;\n"  
            "border:0.5px solid #DDCFC2;\n"  
            "}\n"  
            "\n"  
            "QPushButton#pushButton_openfile:hover{\n"  
            "border:0.5px solid #DDCFC2;\n"
            "}")  
        icon = QtGui.QIcon()  #图标设置
        icon.addPixmap(QtGui.QPixmap(r".\icon\enter2.png"), 
QtGui.QIcon.Normal, QtGui.QIcon.Off)  
        icon.addPixmap(QtGui.QPixmap(r".\icon\enter2.png"), 
QtGui.QIcon.Normal, QtGui.QIcon.On)  
        self.pushButton_openfile.setIcon(icon)  
        self.pushButton_openfile.setCheckable(False)  
        self.pushButton_openfile.setObjectName("pushButton_openfile")  
        self.label_maintitle_shadow=QtWidgets.QLabel(self.centralwidget)
        self.label_maintitle_shadow.setGeometry(QtCore.QRect(331,188,241, 61))
        font = QtGui.QFont()  #图形界面的字体设置
        font.setFamily("微软雅黑")  
        font.setPointSize(36)  
        font.setBold(True)  
        font.setWeight(75)  
        self.label_maintitle_shadow.setFont(font)  
        self.label_maintitle_shadow.setStyleSheet("QLabel#label_maintitle_shadow{\n"  
            " color:#847c74\n"  
            "}")  #设置表单的风格
        self.label_maintitle_shadow.setAlignment(QtCore.Qt.AlignCenter)
        self.label_maintitle_shadow.setObjectName("label_shadow")
        self.label_format = QtWidgets.QLabel(self.centralwidget)  
        self.label_format.setGeometry(QtCore.QRect(325, 395, 251, 20))  
        font = QtGui.QFont()  
        font.setFamily("黑体")  
        font.setPointSize(10)  
        self.label_format.setFont(font)  #设置表单的格式字体
        self.label_format.setStyleSheet("QLabel#label_format{\n"  
            "color:#3A332A\n"  
            "}")  
        self.label_format.setObjectName("label_format")  
        self.label_maintitle = QtWidgets.QLabel(self.centralwidget)  
        self.label_maintitle.setGeometry(QtCore.QRect(331, 189, 241, 61))
        font = QtGui.QFont()  
        font.setFamily("微软雅黑")  
        font.setPointSize(35)  
        font.setBold(True)  
        font.setWeight(75)  
        self.label_maintitle.setFont(font)  
        self.label_maintitle.setStyleSheet("QLabel#label_maintitle{\n"  
            "color:#3A332A\n"  
            "}")  #主题标签的风格设置
        self.label_maintitle.setAlignment(QtCore.Qt.AlignCenter)  
        self.label_maintitle.setObjectName("label_maintitle")  
        self.label_author = QtWidgets.QLabel(self.centralwidget)  
        self.label_author.setGeometry(QtCore.QRect(328, 600, 251, 20))  
        font = QtGui.QFont()  
        font.setFamily("等线")  
        font.setPointSize(8)  
        self.label_author.setFont(font)  
        self.label_author.setStyleSheet("QLabel#label_author{\n"  
            "color:#97846c\n"  #设置表单风格
            "}")  
        self.label_author.setAlignment(QtCore.Qt.AlignCenter)  
        self.label_author.setObjectName("label_author")  
        MainWindow_home.setCentralWidget(self.centralwidget)  
        self.menubar = QtWidgets.QMenuBar(MainWindow_home)  
        self.menubar.setGeometry(QtCore.QRect(0, 0, 900, 23))  
        self.menubar.setObjectName("menubar")  
        MainWindow_home.setMenuBar(self.menubar)  #主窗口设置菜单栏
        self.statusbar = QtWidgets.QStatusBar(MainWindow_home)  
        self.statusbar.setObjectName("statusbar")  
        MainWindow_home.setStatusBar(self.statusbar)  #主窗口设置状态栏
          self.retranslateUi(MainWindow_home)  
        QtCore.QMetaObject.connectSlotsByName(MainWindow_home)  
      def retranslateUi(self, MainWindow_home):  
        _translate = QtCore.QCoreApplication.translate  
        MainWindow_home.setWindowTitle(_translate("MainWindow_home",
"MainWindow"))#主窗口设置窗口标题
        self.pushButton_openfile.setText(_translate("MainWindow_home",
"进入程序"))  
        self.label_maintitle_shadow.setText(_translate("MainWindow_home",
"论文助手"))  
        self.label_format.setText(_translate("MainWindow_home",
"支持扩展名: .pdf  .doc  .docx  .txt"))  
        self.label_maintitle.setText(_translate("MainWindow_home",
"论文助手"))  
        self.label_author.setText(_translate("MainWindow_home",
"Designed by Hu Tong & Li Shuolin"))  
      def openfile(self):  
        openfile_name=QFileDialog.getOpenFileName(self,'选择文件',
'','files(*.doc,*.docx,*.pdf,*.txt)')  

3) Interacción de la interfaz

Después de completar el diseño, establezca la relación de interacción entre las interfaces. Pruebe dos métodos aquí: uno es definir la función de salto; el otro es vincular la función de ranura del botón para completar el salto.

a) Defina la función de salto
Defina la función de salto y las operaciones relacionadas.

#Jumpmain2pre.py  
from PyQt5 import QtCore, QtGui, QtWidgets  
from home import Ui_MainWindow_home        #跳转按钮所在界面  
from PreEdit import Ui_Form                #跳转到的界面  
  class Ui_PreEdit(Ui_Form):   				#定义跳转函数的名字  
    def __init__(self):  
        super(Ui_PreEdit,self).__init__()  #跳转函数类名  
        self.setupUi(self)  
  #主界面  
class Mainshow(Ui_MainWindow_home):         
  def __init__(self):  
        super(Mainshow,self).__init__()     
        self.setupUi(self)  
  #定义按钮功能  
  def loginEvent(self):  
        self.hide()  
        self.dia = Ui_PreEdit()              #跳转到的界面类名
        self.dia.show()  
  def homeshow():                            #调用这个函数来执行  
    import sys  
    app=QtWidgets.QApplication(sys.argv)  
    first=Mainshow()  
    first.show()  
    first.pushButton_openfile.clicked.connect(first.loginEvent) 
#绑定跳转功能的按钮  
    sys.exit(app.exec_()) 

b) Función de ranura para vincular botones
Configure un evento de clic para el botón que necesita completar la función de salto y use la función de ranura para vincular el evento. Aquí hay un ejemplo de vinculación de la función showwaiting():

self.pushButton_create.clicked.connect(self.showwaiting)  

Defina por separado el evento que se vinculará al botón como una función:

def showwaiting(self):  
    import sys  
    self.MainWindow = QtWidgets.QMainWindow()  
    self.newshow = Ui_MainWindow_sumcreating()  #图形界面创建
    self.newshow.setupUi(self.MainWindow)        #界面设置
    self.hide()  
    self.MainWindow.show()  
    print('生成中…')  

c) Ejemplo: leer archivos locales en GUI

Defina la acción de abrir, la acción de guardar y el contenido de guardado como tres funciones, que son convenientes para llamar a través de la ranura cuando se hace clic en el botón. Los códigos relevantes son los siguientes:

def open_event(self):  #打开文件事件
     _translate = QtCore.QCoreApplication.translate  
     directory1 = QFileDialog.getOpenFileName(None, "选择文件", "C:/","Wo
rd文档 (*.docx;*.doc);;文本文件(*.txt);;pdf(*.pdf);;")  
     print(directory1)  #输出路径
     path = directory1[0]  
     self.open_path_text.setText(_translate("Form", path))  
     if path is not None:  
         with open(file=path, mode='r+', encoding='utf-8') as file:  
             self.text_value.setPlainText(file.read())  
 def save_event(self):  #保存事件
     global save_path  
     _translate = QtCore.QCoreApplication.translate  
     fileName2, ok2 = QFileDialog.getSaveFileName(None, "文件保存", "C:/",
"Text Files (*.txt)")  
     print(fileName2)  #打印保存文件的全部路径(包括文件名和后缀名)  
     save_path = fileName2  
     self.save_path_text.setText(_translate("Form", save_path))  
  def save_text(self):  #保存文本
     global save_path  
     if save_path is not None:  
         with open(file=save_path, mode='a+', encoding='utf-8') as file:
             file.write(self.text_value.toPlainText())  
         print('已保存!')  

Vincule la acción de clic a los botones abrir y guardar, y llame a la función correspondiente definida anteriormente a través de la ranura. Al mismo tiempo, utilice el mismo método para asociar las rutas obtenidas en las funciones open_event() y save_event() con los dos cuadros de visualización de rutas definidos.Los códigos relevantes son los siguientes:

def retranslateUi(self, Form):  
    _translate = QtCore.QCoreApplication.translate  
    Form.setWindowTitle(_translate("Form", "Form"))  
    self.label_preview.setText(_translate("MainWindow_preview","预览"))  
    self.open_path_text.setPlaceholderText(_translate("Form","打开"))  
    self.open_path_but.setText(_translate("Form", "浏览"))  
    self.save_path_but.setText(_translate("Form", "浏览"))  
    self.save_path_text.setPlaceholderText(_translate("Form","保存"))  
    self.save_but.setText(_translate("Form", "保存"))  
    self.open_path_but.clicked.connect(self.open_event)  
    self.save_path_but.clicked.connect(self.save_event)  
    self.save_but.clicked.connect(self.save_text)  
    self.pushButton_create.clicked.connect(self.showwaiting)  
    self.pushButton_create.setText(_translate("Main_preview","生成"))  

El diagrama de efectos de la operación del programa se muestra en las siguientes dos figuras respectivamente.

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

4) Programa de acoplamiento

Para completar la combinación del modelo y la interfaz gráfica, es necesario reservar una interfaz de acoplamiento correspondiente en el código. En este proyecto, hay cuatro partes clave de conexión entre la interfaz y el cuerpo principal del modelo: llamar al modelo, finalizar el procesamiento del modelo, mostrar el resultado y guardar la salida.

a) llamar al modelo

Para completar la función de llamar al modelo para su procesamiento después de hacer clic en el botón generar, escriba la interfaz de llamada en la última función showWaiting() de PreEdit.py y llame al modelo cuando aparezca la página de generación de resumen. El código correspondiente es el siguiente:

def showwaiting(self):  
    import sys  
    self.MainWindow = QtWidgets.QMainWindow()  
    self.newshow = Ui_MainWindow_sumcreating()  #创建
    self.newshow.setupUi(self.MainWindow)        #设置
    self.hide()  
#待对接程序,读取前面保存的文件(文件的路径在save_event函数里)
#调用模型进行输出并保存  
    self.MainWindow.show()  
    print('生成中…')  

b) Fin del procesamiento del modelo

Una vez que finaliza el procesamiento del modelo, es necesario continuar ejecutando la página de visualización de resultados, por lo que se agrega un juicio a la función principal de PaperMain.py. Después de que se procesa el modelo de juicio, se llama a la función resultShow() para continuar con ejecutar la visualización de resultados posterior. El código correspondiente es el siguiente:

def main():  
    homeshow()    
    #待对接程序在PreEdit.py最后的showwaiting()函数里调用模型  
    #待对接程序判断处理完成后继续运行结果展示页  
resultshow()  

c) Visualización de resultados

Después de procesar el modelo, el resumen, el título y las palabras clave deben mostrarse en la página de visualización de resultados. La página de visualización de resultados corresponde al result.pyarchivo. Antes del acoplamiento, los resultados que se muestran en la interfaz son cadenas fijas; al acoplar, solo es necesario guardar los resultados de la operación del modelo como cadenas y reemplazar el contenido previamente fijado. El código correspondiente es el siguiente:

#待对接程序模型运行的结果存几个字符串后替换下面的文字即可
#替换摘要
self.plainTextEdit_summary.setPlainText(_translate("MainWindow_result", "生成的摘要"))   
#替换标题1  
self.lineEdit_title1.setText(_translate("MainWindow_result","标题1"))
#替换标题2  
self.lineEdit_title2.setText(_translate("MainWindow_result","标题2"))
#替换标题3    
self.lineEdit_title3.setText(_translate("MainWindow_result","标题3"))  
#替换关键词
self.lineEdit_keywords.setText(_translate("MainWindow_result","关键词"))

d) Guardar
la salida Cuando se hace clic en el botón "Guardar", la salida del modelo se guarda directamente localmente. Esta función se completa result. pycon save_text()la función del medio f.write()Antes del acoplamiento, la salida de f.write() es una cadena fija, y puede ser reemplazada por el contenido generado por el modelo al acoplar. El código correspondiente es el siguiente:

def save_text(self):  
    global save_path  
    if save_path is not None:  
        with open(file=save_path, mode='a+', encoding='utf-8') as file: 
        #对接file.write这里直接把程序里的字符串加起来写入保存的结果即可
            file.write("hello,Tibbarr")  
        print('已保存!')  

6. Empaquetado de aplicaciones

Para mejorar la comodidad de uso y reducir el umbral de uso del usuario, este proyecto requiere un embalaje integrado. Teniendo en cuenta que la redacción de la tesis se realiza principalmente en el lado de la PC, se utiliza PyInstaller para empaquetar el proyecto como .exeuna aplicación.

1) Instalar PyInstaller

Descárguelo de Tsinghua Warehouse Mirror.Después PyInstaller-3.6.tar.gzde descomprimirlo localmente, use cmd para ingresar a la consola, cambie al directorio correspondiente después de la descompresión y ejecute el comando para completar la instalación. :

python setup.py install

2) Empaquete el programa como un archivo .exe

Abra la ventana de comandos, cambie el directorio a papermain.pyla ruta e ingrese el comando

pyinstaller -F -w papermain.py

Los detalles se muestran en la siguiente figura.

inserte la descripción de la imagen aquí

Use el comando PyInstaller para empaquetar correctamente, como se muestra en la figura a continuación.

inserte la descripción de la imagen aquí

3) Ver el archivo .exe

Una vez que el programa se empaqueta correctamente, se genera una carpeta dist en el directorio de archivos papermain.py, que contiene el archivo .exe generado, que se puede ejecutar haciendo doble clic y se completa el empaquetado del programa.

Prueba del sistema

Esta sección cubre la perplejidad del entrenamiento, el desempeño de las pruebas y la aplicación del modelo.

1. Perplejidad de entrenamiento

En el modelo Seq2Seq, se utiliza la perplejidad para evaluar el efecto final, y cuanto menor sea el valor, mejor será el efecto del modelo de lenguaje. Este proyecto utiliza una gran red para la formación, con un total de 48.000 pasos.Después de un período de formación, la pérdida ya no disminuirá. Comience a entrenar y construir la red, como se muestra en la figura a continuación.

inserte la descripción de la imagen aquí

Durante el proceso de entrenamiento, el valor de la perplejidad del modelo muestra una tendencia a la baja, es decir, la ambigüedad del lenguaje disminuye gradualmente a medida que avanza el entrenamiento, y el efecto del modelo mejora gradualmente. Cuando el modelo alcanza los 30 000 pasos, su tendencia descendente se ha vuelto plana y la perplejidad básicamente ya no disminuye; cuando llega a los 47 000 pasos, el valor de perplejidad del modelo fluctúa en un rango pequeño y, finalmente, el punto más bajo de su perplejidad cae a 232.62, como se muestra a continuación.

inserte la descripción de la imagen aquí

2. Efecto de prueba

Cargue el modelo entrenado e ingrese el texto relevante para la prueba. Use Seq2Seqla salida para la sección de encabezado, como se muestra en la imagen a continuación.

inserte la descripción de la imagen aquí

A partir de los resultados de salida, se puede ver que todavía falta la capacidad de generación de títulos del modelo, y solo puede lograr mejores títulos para contenido simple. Cuando se trata de textos difíciles, se necesita mejorar la precisión.

En la parte de extracción de resumen y extracción de palabras clave, TextRankel algoritmo se usa para entrenar el modelo, y el modelo entrenado se usa para generar el texto dado.Después de muchas pruebas, se obtienen buenos resultados, como se muestra en la figura a continuación.

inserte la descripción de la imagen aquí

3. Modelo de aplicación

Dado que el programa ha sido empaquetado como un archivo ejecutable, descargue .exeel archivo a la computadora y haga doble clic para ejecutarlo.La interfaz inicial de la aplicación se muestra en la siguiente figura.

inserte la descripción de la imagen aquí

La página de inicio es el nombre del proyecto, el botón "Ingresar al programa" y la descripción de los formatos de archivo admitidos. Haga clic en el botón "Ingresar al programa" para ingresar a la página de lectura del archivo.

En la página de lectura de archivos, haga clic en el navegador correspondiente a la dirección abierta y guarde la dirección y el documento a procesar, y configure la ruta de guardado y el nombre del archivo del resultado de la modificación, como se muestra en la figura a continuación.

inserte la descripción de la imagen aquí

Después de leer el archivo, las páginas de vista previa y edición se muestran en la Figura 1 a continuación. Obtenga una vista previa y modifique el contenido de lectura aquí, haga clic en el botón "Guardar" para guardar temporalmente el documento modificado, haga clic en el botón "Generar", el modelo comienza a procesar el contenido del texto e ingresa a la página de espera, como se muestra en la Figura- 2 a continuación.

inserte la descripción de la imagen aquí

Figura 1 Página de vista previa y edición

inserte la descripción de la imagen aquí

Figura 2 Procesamiento de páginas en espera

Después de procesar el modelo, cierre la ventana actual y el programa saltará automáticamente a la página de visualización de resultados. La página muestra tres esquemas de títulos diferentes, resúmenes en papel y palabras clave de arriba a abajo. Los usuarios pueden copiar directamente en la interfaz o seleccionar una ruta en la parte inferior de la página y guardar todos los resultados en la máquina local, como se muestra en la figura de abajo.

inserte la descripción de la imagen aquí

Después de seleccionar la ruta de guardado y hacer clic en el botón "Guardar", el programa guardará todos los resultados en la ruta especificada y saltará a la página de descarga exitosa, como se muestra en la figura a continuación.

inserte la descripción de la imagen aquí

Una vez que se completa el procesamiento, el usuario cierra directamente el programa o hace clic en el botón "Volver a Inicio" para volver a la página de inicio y procesar otros archivos. Pruebe el programa en el lado de la PC, el contenido del archivo de entrada, el mapa de contenido de salida y el archivo de resultados de salida se muestran en la Figura 3 a la Figura 5 a continuación.

inserte la descripción de la imagen aquí

Figura 3 Mapa de contenido del archivo de entrada

inserte la descripción de la imagen aquí

Figura 4 mapa de contenido de salida

inserte la descripción de la imagen aquí

Figura 5 Diagrama del archivo de resultados de salida

Descarga del código fuente del proyecto

Consulte la página de descarga de recursos de mi blog para obtener más información.


Descarga de otra información

Si desea continuar aprendiendo sobre rutas de aprendizaje y sistemas de conocimiento relacionados con la inteligencia artificial, bienvenido a leer mi otro blog " Pesado | Ruta de aprendizaje de conocimiento básico de aprendizaje de inteligencia artificial completa, todos los materiales se pueden descargar directamente desde el disco de la red sin pagar atención a las rutinas "
Este blog se refiere a la conocida plataforma de código abierto de Github, la plataforma de tecnología de IA y expertos en campos relacionados: Datawhale, ApacheCN, AI Youdao y Dr. Huang Haiguang, etc. Hay alrededor de 100G de materiales relacionados, y espero ayuda a todos tus amigos.

Supongo que te gusta

Origin blog.csdn.net/qq_31136513/article/details/131635775
Recomendado
Clasificación