赞
踩
在NLP-统计语言模型中已经简要介绍过语言模型的相关知识,该文中已阐述语言模型的应用场景和一些传统的实现方式,本文接着演示n-gram的另一种实现方式-神经网络,那这样的实现方式就是神经语言模型吗?
按本渣的理解,答案是否定的,神经语言模型是一个类指,其本质是在统计语言模型上的一种延伸和扩展,我可以只考虑上文n个词,也可以考虑下文n个词,也可以基于上下文考虑,具体的情况需要根据需求而定。
为了和NLP-统计语言模型形成呼应,本文依旧使用文本生成作为案例,依旧照抄语料库(量少更能直观理解过程)。
另外强调一点,本文还是以理解为主,并没有将数据进行训练、验证和测试等拆分!
corpus = '''
这一生原本一个人,你坚持厮守成我们,却小小声牵着手在默认。
感动的眼神说愿意,走进我的人生。
进了门开了灯一家人,盼来生依然是一家人。
确认过眼神,我遇上对的人。
我挥剑转身,而鲜血如红唇。
前朝记忆渡红尘,伤人的不是刀刃,是你转世而来的魂。
青石板上的月光照进这山城,我一路的跟你轮回声,我对你用情极深。
谁在用琵琶弹奏一曲东风破,枫叶将故事染色,结局我看透。
篱笆外的古道我牵着你走过,荒烟漫草的年头,就连分手都很沉默。
'''
本文假设第n个词的出现只与前面n-1个词相关,而与其它任何词都不相关,因此在构建训练数据时,将语料进行截取,如
这一生原本一个人,你坚持厮守成我们,却小小声牵着手在默认
以n为4进行切分的话即为
这一生->原
一生原->本
生原本->一
...以此类推
根据上述的切分方法,将数据进行切分并转为one-hot序列
def __init__(self,window,corpus): self.window = window self.corpus = corpus self.char2id = None self.id2char = None self.char_length = 0 def load_data(self): X = [] Y = [] # 将语料按照\n切分为句子 corpus = self.corpus.strip().split('\n') # 获取所有的字符作为字典 chrs = set(self.corpus.replace('\n','')) chrs.add('UNK') self.char_length = len(chrs) self.char2id = {c: i for i, c in enumerate(chrs)} self.id2char = {i: c for c, i in self.char2id.items()} for line in corpus: x = [[self.char2id[char] for char in line[i: i + self.window]] for i in range(len(line) - self.window)] y = [[self.char2id[line[i + self.window]]] for i in range(len(line) - self.window)] X.extend(x) Y.extend(y) # 转为one-hot X = to_categorical(X) Y = to_categorical(Y) return X,Y
本文使用两层的LSTM进行模型搭建
def build_model(self):
model = Sequential()
model.add(Bidirectional(LSTM(100,return_sequences=True)))
model.add(Bidirectional(LSTM(200)))
model.add(Dense(self.char_length, activation='softmax'))
model.compile('adam', 'categorical_crossentropy')
self.model = model
def train_model(self,X,Y,epochs):
self.model.fit(X, Y, epochs=epochs, verbose=1)
self.model.save('model.model')
def predict(self,sentence):
input_sentence = [self.char2id.get(char,self.char2id['UNK']) for char in sentence]
input_sentence = pad_sequences([input_sentence],maxlen=self.window)
input_sentence = to_categorical(input_sentence,num_classes=self.char_length)
predict = self.model.predict(input_sentence)
# 本文为了方便 直接取使用最大概率的值,并非绝对,采样的方式有很多种,自行选择
return self.id2char[np.argmax(predict)]
# 以5切分 window = 5 text_generate = TextGenerate(window,corpus) X,Y = text_generate.load_data() text_generate.build_model() text_generate.train_model(X,Y,500) # text_generate.load_model() input_sentence = '确认过眼神' result = input_sentence #在构建语料的过程中,设置了每次只预测一个词,为了生成完成的一句话,需要进行循环预测 while not result.endswith('。'): predict = text_generate.predict(input_sentence) result += predict input_sentence += predict input_sentence = input_sentence[len(input_sentence)-(window if len(input_sentence)>window else len(input_sentence)):] print(result)
以‘确认过眼神’作为提示语句,测试结果如下:
'''
确认过眼神,
确认过眼神,我
确认过眼神,我遇
确认过眼神,我遇上
确认过眼神,我遇上对
确认过眼神,我遇上对的
确认过眼神,我遇上对的人
确认过眼神,我遇上对的人。
'''
从结果中发现,该模型已经完全记住了训练语料的连接关系,但也因为采样的时候贪婪地采样最大概率词作为预测结果,所以当提示语句在语料库中完全出现过时,预测结果的多样性就受到了抑制。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。