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
Directorio de artículos
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 y1. 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