pytorch文本序列化的方法
·
在介绍word embedding的时候,我们说过,不会直接把文本转化为向量,而是先转化为数字,再把数字转化为向量,那么这个过程如何实现?
这里我们可以考虑把文本中的每个词语和其对应的数字,使用字典保存,同时实现方法把句子通过字典映射为包含数字的列表。
实现文本序列化之前,考虑一下几点:
1.如何使用字典把词语和数字进行对应
2.不同的词语出现的次数不尽相同,是否需要对高频或者低频词语进行过滤,以及总的词语数量是否需要进行限制
3.得到词典之后,如何把句子转化为数字序列,如何把数字序列转化为句子
4.不同句子长度不同,每个batch的句子如何构造成相同的长度(可以对句子进行填充,填充特殊字符)
5.对于新出现的词语在词典中没有出现怎么办(可以使用特殊字符代替)
思路分析:
1.对所有的句子进行分词
2.词语存入字典,根据次数对词语进行过滤,并统计次数
3.实现文本转数字序列的方法
4.实现数字序列转文本的方法
解决办法:
不同的词语出现的次数不尽相同,是否需要对高频或者低频词语进行过滤,以及总的词语数量是否需要进行限制
def build_vocab(self, min=5, max=None, max_features=None):
"""
生成词典
:param min:最小出现的次数
:param max: 最大的次数
:param max_features: 一共保留多少个词语
:return:
"""
# 删除count中词频小于min的词语
if min is not None:
self.count = {word: value for word, value in self.count if value > min}
# 删除大于max的值
if max is not None:
self.count = {word: value for word, value in self.count if value < max}
# 限制保留的词语数
if max_features is not None:
temp = sorted(self.count.items(), key=lambda x: x[-1], reverse=True)[:max_features]
self.count = dict(temp)
for word in self.count:
self.dict[word] = len(self.dict)
# 得到一个翻转的dict字典
self.inverse_dict = dict(zip(self.dict.values(), self.dict.keys())) # 分别把值和键取出来 zip
把句子构造成相同长度的句子 (填充和裁剪)
def transform(self, sentence, max_len=None):
"""
把句子转化成序列
:param sentence:【word1, word2】
:return:
"""
if max_len is not None:
if max_len > len(sentence):
sentence = sentence + [self.PAD_TAG] * (max_len-len(sentence))# 填充
if max_len < len(sentence):
sentence = sentence[:max_len] # 裁剪
return [self.dict.get(word, self.UNK) for word in sentence]
完整代码
import numpy as np
class Word2Sequence():
UNK_TAG = "UNK" # 特殊字符用UNK表示
PAD_TAG = "PAD" # 填充字符
UNK = 0
PAD = 1
def __init__(self):
self.dict = {
self.UNK_TAG : self.UNK, # 建立一个保存所有词的词典
self.PAD_TAG : self.PAD}
self.fited = False
def to_index(self, word):
"""word - index"""
assert self.fited == True, "必须先进行fit操作"
return self.dict.get(word, self.UNK)
def to_word(self, index):
"""index - word"""
assert self.fited,
if index in self.inversed_dict:
return self.inversed_dict[index]
return self.UNK_TAG
def __len__(self):
return self(self.dict)
def fit(self,sentence,min_count=1,max_count=None,max_features=None): # 【min_count:最小词频; max_count: 最大词频; max_features: 最大词语数(词典容量大小)】
"""
:param sentence:[word1,word2,word3]
:param min_count: 最小出现的次数
:param max_count: 最大出现的次数
:param max_feature: 总词语的最大数量
:return:
"""
count = {}
for sentence in sentences:
for a in sentence:
if a not in count:
count[a] = 0
count[a] += 1
if min_count is not None: # 根据条件统计词频
count = {k:v for k, v in count.items() if v >= min_count}
if max_count is not None:
count = {k:v for k, v in count.items() if v<= max_count}
# 限制最大的数量
if isinstance(max_feature, int):
count = sorted(list(count.items()), key=lambda x: x[1])
if max_feature is not None and len(count) > max_feature:
count = count[-int(max_feature):]
for w, _in count:
self.dict[w] = len(self.dict)
else:
for w in sorted(count.keys())
self.dict[w] = len(self.dict)
self.fited = True
# 准备一个index-word的字典
self.inversed_dict = dict(zip(self.dict.values(), self.dict.keys()))
def transform(self, sentence, max_len=None):
"""
实现把句子转化成数组(向量)
"""
assert self.fited, "必须先进行fit操作"
if max_len is not None:
r = [self.PAD]*max_len
else:
r = [self.PAD]*len(sentence)
if max_len is not None and len(sentence)>max_len:
sentence = sentence[:max_len]
for index, word in enumerate(sentence):
r[index] = self.to_index(word)
return np.array(r, dtype=np.int64)
def inverse_transform(self, indices):
"""
把数组转化成文字
"""
sentence = []
for i in indices:
word = self.to_word(i)
sentence.append(word)
return sentence
if __name__ == "__main__"
w2s = Word2Sequence()
w2s.fit([
["你", "好", "么"], ["你", "好", "哦"]])
print(w2s.dict)
print(w2s.fited)
print(w2s.transform(["你", "好", "嘛"]))
保存 word_sequence
from word_sequence import Word2Sequence
import os
import pickle
from dataset import tokenize
from tqdm import tqdm
# def a():
# a = __name__
if __name__ == '__main__':
a = __name__
ws = Word2Sequence()
path = "./data/train"
temp_data_path = [os.path.join(path, "pos"), os.path.join(path, "neg")]
for data_path in temp_data_path:
file_paths = [os.path.join(data_path, file_name) for file_name in os.listdir(data_path)]
for file_path in tqdm(file_paths):
sentence = tokenize(open(file_path).read())
ws.fit(sentence)
ws.build_vocab(min_count=10, max_features=10000)
pickle.dump(ws, open("./model/ws.pkl", "wb")) # 把ws保存在本地
print(len(ws))
注意if __name__=='__main__'的用法!!!
更多推荐



所有评论(0)