Preprocesamiento de datos SQuAD (3)

Preprocesamiento de datos SQuAD (3)

Sugerencia: aquí puede agregar el catálogo de todos los artículos de la serie, y el catálogo debe ser agregado manualmente por usted mismo.
Por ejemplo: el primer capítulo Introducción al aprendizaje automático de Python para el uso de pandas



Prefacio

1. Aquí, guarde los datos del modelo en el archivo pickle para la próxima llamada. 2. Cree la clase de cargador de datos y devuelva los datos necesarios durante el entrenamiento del modelo. 3. Obtenga el diccionario de guantes, cree la matriz de peso del guante y el vocabulario del conjunto de datos y

1. Transferir datos

El módulo pickle de Python puede almacenar objetos en el disco en forma de archivos.
pickle.dump (obj, archivo [, protocolo]): realiza la serialización
pickle.load (archivo): realiza la deserialización

Transferir datos a archivos pickle

Asegúrese de que podamos acceder directamente al archivo de marco de datos preprocesado la próxima vez

import pickle
# 保存训练集和验证集df数据
train_df.to_pickle('qanettrain.pkl')
valid_df.to_pickle('qanetvalid.pkl')

with open('qanetw2id.pickle','wb') as handle:
    pickle.dump(word2idx, handle)

with open('qanetc2id.pickle','wb') as handle:
    pickle.dump(char2idx, handle)

Leer datos del archivo pickle

Esto solo requiere un procesamiento previo una vez, ya que algunas funciones de procesamiento previo pueden tardar varios minutos, por lo que el decapado puede ahorrar mucho tiempo de limpieza de datos.

import pickle
# 读取字word2idx和char2idx文件
with open('qanetw2id.pickle', 'rb') as handle:
    word2idx = pickle.load(handle)
with open('qanetc2id.pickle','rb') as handle:
    char2idx = pickle.load(handle)

train_df = pd.read_pickle('qanettrain.pkl')
valid_df = pd.read_pickle('qanetvalid.pkl')

idx2word = {
    
    v:k for k,v in word2idx.items()}
idx2char = {
    
    v:k for k,v in word2idx.items()}

word_vocab = list(word2idx)
char_vocab = list(char2idx)

Dos, crea un cargador de datos

Esta clase es responsable del procesamiento por lotes, la creación de vectores de caracteres y la devolución de todo lo necesario durante el entrenamiento:
padded_context: el contexto que llena cada lote
padded_question: preguntas completadas en cada lote
char_ctx & ques_ctx: identificadores de nivel de carácter para contexto y pregunta
etiqueta: índice inicial y final wrt context_ids posición inicial y final context_ids
context_text, answer_text: utilizado durante la validación para calcular métricas
ids: question_ids para evaluación

código del cargador de datos

class SquadDataset:
    '''
    - Creates batches dynamically by padding to the length of largest example
      in a given batch.
      通过填充到给定批处理中最大示例的长度来动态创建批处理。
    - Calulates character vectors for contexts and question.
      为context和question创建字符向量
    - Returns tensors for training.
      返回训练用的tensors
    '''
    def __init__(self, data, batch_size):
        '''
        data: dataframe
        batch_size: int
        '''
        self.batch_size = batch_size
        data = [data[i:i+self.batch_size] for i in range(0, len(data), self.batch_size)]
        self.data = data
        # 此时self.data中的数据是[batch1,batch2,...] 每个batch中包含batch_size条数据
        
        
    def __len__(self):
        # 如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。
        # 要让 len() 函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。
        # 只要正确实现了__len__()方法,就可以用len()函数返回长度
        return len(self.data)
    
    def make_char_vector(self, max_sent_len, sentence, max_word_len=16):
        # 单词长度小于16的,对每个句子中 每个单词 的每个字符创建长度为16的 tensor
        char_vec = torch.zeros(max_sent_len, max_word_len).type(torch.LongTensor)
        # 创建max_sent_len * max_word_len 的张量矩阵,类型LongTensor
        for i, word in enumerate(nlp(sentence, disable=['parser','tagger','ner'])):
            for j, ch in enumerate(word.text):
                if j == max_word_len:
                    break
                char_vec[i][j] = char2idx.get(ch, 0)    # 有返回idx,无返回0
        # 这个句子第i个单词,第j个字符的tensor,padding部分为全0
        return char_vec     
    
    def get_span(self, text):
        # len(w.text)是单词的长度 .idx是按照字符进行分割返回的是字符的位置

        text = nlp(text, disable=['parser','tagger','ner'])
        span = [(w.idx, w.idx+len(w.text)) for w in text]
        
        # [(,),,...(,)] 单词的开始和结束位置
        return span


    def __iter__(self):
        '''
        创建迭代器
        yields解释: https://blog.csdn.net/mieleizhi0522/article/details/82142856/
        Creates batches of data and yields them.
        
        Each yield comprises of:
        :padded_context: padded tensor of contexts for each batch 
         每个batch 填充过的context
        :padded_question: padded tensor of questions for each batch 
         每个batch 填充过的question
        :char_ctx & ques_ctx: character-level ids for context and question 字符水平的ids
        :label: start and end index wrt context_ids  开始和结束的位置 context_ids
        :context_text,answer_text: used while validation to calculate metrics
        :ids: question_ids for evaluation
        '''
        
        for batch in self.data:
            # 遍历每个batch
            spans = []    
            ctx_text = []    # 记录每个context
            answer_text = []
            
             
            for ctx in batch.context:
                # 遍历每个batch中的context字段,将每条context加载到列表ctx_text
                ctx_text.append(ctx)
                spans.append(self.get_span(ctx))
            
            for ans in batch.answer:
                answer_text.append(ans)
                
            max_context_len = max([len(ctx) for ctx in batch.context_ids])
            # context_ids, 返回这个批次中最长的一句话的长度
            padded_context = torch.LongTensor(len(batch), max_context_len).fill_(1)    # 1填充
            
            for i, ctx in enumerate(batch.context_ids):
                padded_context[i, :len(ctx)] = torch.LongTensor(ctx)
            # 将数据类型转化为longtensor()
            
            max_word_ctx = 16
          
            char_ctx = torch.zeros(len(batch), max_context_len, max_word_ctx).type(torch.LongTensor)
            for i, context in enumerate(batch.context):
                char_ctx[i] = self.make_char_vector(max_context_len, context)
            # 批次*句长*单词 最后一维每个位置代表一个字符,创建矩阵
            
            max_question_len = max([len(ques) for ques in batch.question_ids])
            padded_question = torch.LongTensor(len(batch), max_question_len).fill_(1)
            
            for i, ques in enumerate(batch.question_ids):
                padded_question[i, :len(ques)] = torch.LongTensor(ques)
                
            max_word_ques = 16
            
            char_ques = torch.zeros(len(batch), max_question_len, max_word_ques).type(torch.LongTensor)
            for i, question in enumerate(batch.question):
                char_ques[i] = self.make_char_vector(max_question_len, question)
            # 与context进行相同处理
              
            label = torch.LongTensor(list(batch.label_idx))
            ids = list(batch.id)
            
            yield (padded_context, padded_question, char_ctx, char_ques, label, ctx_text, answer_text, ids)
 

Ver la forma de varios tensores

# create dataloaders

train_dataset = SquadDataset(train_df,16)
valid_dataset = SquadDataset(valid_df,16)

# 查看loader返回的各种张量的性状
a = next(iter(train_dataset))
for i in range(len(a)):
    try:
        print(a[i].shape)
    except AttributeError:
        print(len(a[i]))
-------------------------------------------------------------------
out:
torch.Size([16, 253])
torch.Size([16, 16])
torch.Size([16, 253, 16])
torch.Size([16, 16, 16])
torch.Size([16, 2])
16
16
16

Tres, guante de carga y matriz de peso

Parse archivo de vector de palabra guante

def get_glove_dict():
    '''
    Parses the glove word vectors text file and returns a dictionary with the words as
    keys and their respective pretrained word vectors as values.
    解析glove词向量文件,并返回一个字典,单词做键,预训练的词向量作为值
    '''
    glove_dict = {
    
    }
    with open("./glove.840B.300d/glove.840B.300d.txt", "r", encoding="utf-8") as f:
        for line in f:
            values = line.split(' ')
            word = values[0]
            vector = np.asarray(values[1:], dtype="float32")
            glove_dict[word] = vector

    f.close()
    
    return glove_dict

Crea una matriz de peso

def create_weights_matrix(glove_dict):
    '''
    Creates a weight matrix of the words that are common in the GloVe vocab and
    the dataset's vocab. Initializes OOV words with a zero vector.
    创建GloVe和数据集的词汇表中常见单词的权重矩阵,用零向量初始化OOV单词
    '''
    weights_matrix = np.zeros((len(word_vocab), 300))
    words_found = 0
    for i, word in enumerate(word_vocab):
        try:
            weights_matrix[i] = glove_dict[word]
            words_found += 1
        except:
            pass

    return weights_matrix, words_found

weights_matrix, words_found = create_weights_matrix(glove_dict)
print("Words found in the GloVe vocab: " ,words_found)
----------------------------------------------------------------------------
out:
Words found in the GloVe vocab:  91194
# save the weight matrix for future loading.
# This matrix is the nn.Embedding's weight matrix.
# 保存权重矩阵 这个权重矩阵是nn.Embedding的权重矩阵
np.save('qanetglove_vt.npy', weights_matrix)

para resumir

Después de procesar y cargar todos los datos por la mañana, comience a organizar el modelo QANet

Supongo que te gusta

Origin blog.csdn.net/qq_42388742/article/details/112177743
Recomendado
Clasificación