使用LSTM生成序列、自动问答使用?分割即可!

8 篇文章 0 订阅
8 篇文章 0 订阅
#使用LSTM生成序列。回头可以测试唐诗生成。
#蚂蚁金服的自动客服问答就是这样做的。而且效果不好简直是人工智障!
#根据不同的softmax温度值,对概率分布进行重新加权。
import numpy as np
def reweight_distribution(original_distribution,temperature=0.5):
    distribution = np.log(original_distribution) / temperature
    #log(原始分布)/softmax温度。 log是幂的逆运算。
    #原始分布式概率值组成的一维numpy数组,这些概率值之和是1.
    distribution = np.exp(distribution)
    return distribution / np.sum(distribution)
#返回原始分布重新加权后的结果。distribution的求和可能不再是1了。
#因此需要将它除以求和,以得到重新的分布。
#温度值更高就更不可预测。表现的更有创造性。
##############################################################
#就算AI能实现的功能有限,但有科技封装概念的加持,产品的品牌
#效应、让人认可的效果也更好。
#下载尼采的作品。
import keras
import numpy as np
path = keras.utils.get_file('nietzsche.txt',
    origin='https://s3.amazonaws.com/text-datasets/nietzsche.txt')
#
#text = open(path).read().lower()#英文读不懂换成还珠格格,文本文件大小差不多,但是内容
#应该比英文少,因为汉字字符bytes长,但是维度会很高。
#原来的尼采文集有:586kb,60万字,20万句话,58个唯一字符。中文肯定字符要多很多。
#还珠格格信息:603kb,Cropus length: 320503
#Number of sequences: 106815
#Unique charachters: 2992
#直接卡死了。
#坏蛋是怎样练成的有3.85MB.
#改用流浪地球部分,才68kbCropus length: 24363
#Number of sequences: 8101
#Unique charachters: 1581
#text = open('./data/还珠格格.txt').read().lower()
text = open('./data/流浪地球部分.txt',encoding='utf-8').read().lower()
print('Cropus length:',len(text))
#Cropus 全文
##################################################################
#提取长度为maxlen 的序列(这些序列之间存在部分重叠),对它们进行
#one-hot 编码。
#准备一个数组y,其中包含对应的目标,即在每一个所提
#取的序列之后出现的字符(已进行one-hot 编码)。用来训练和预测。
maxlen = 60#提取60个字符组成序列
step = 3#每3个字符采样一个新序列(类似卷积窗口).1-10的单词采样后为:123456、456789两句话。
sentences = []#保存所提取的序列.sentences句子。
next_char = []#保存目标(即训练和预测的下一个字符)
for i  in range(0,len(text) - maxlen,step):
    sentences.append(text[i:i + maxlen])#加入一句话。
    next_char.append(text[i + maxlen])#加入这句话下一个字符。
print('Number of sequences:',len(sentences))

chars = sorted(list(set(text)))#语料中唯一字符组成的集合,然后转为list然后排序。
print('Unique charachters:',len(chars))
char_indices = dict((char,chars.index(char)) for char in chars)#构建string,int字典。
####################################################################
print('Vectorization...')#向量化
x = np.zeros((len(sentences),#samples样品句子
            maxlen,#每个句子多少句话
            len(chars)#可能的维度
            )                
             ,dtype=np.bool)#独热编码
y=np.zeros(
            (len(sentences),#多少个目标
             len(chars)#多少个可能
            )
           ,dtype=np.bool)#独热编码
for i,sentence in enumerate(sentences):#每句话
    for t,char in enumerate(sentence):#每句话中的t索引和char字符
        x[i,t,char_indices[char]]=1#训练张量中句子、字符、单词设置对应的索引。
    y[i,char_indices[next_char[i]]]=1#目标张量中的句子、对应的下个单词设置对应索引。
###############################################################
print('构建网络模型')
from keras import layers
model=keras.models.Sequential()
model.add(layers.LSTM(128,input_shape=(maxlen,len(chars))))
#输出参数格式,输入形状。
model.add(layers.Dense(len(chars),activation='softmax'))
#输出参数len(chars);得到一个chars的可能的概率一维张量。
#结果是独热编码过的,所以要用categorical_crossentropy
#作为损失函数。
optimizer=keras.optimizers.RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy',optimizer=optimizer)
#训练模型,并从中采样#############################################
#对模型得到的原始概率分布进行重新加权,并从中提取一个字符索引作为下一个字符。
def sample(preds,temperature=1.0):#preds预测的句子张量,概率分布;temperature是softmax温度值
    preds=np.asarray(preds).astype('float64')
    preds=np.log(preds)/temperature
    exp_preds=np.exp(preds)
    preds=exp_preds/np.sum(exp_preds)#重新加权
    probas=np.random.multinomial(1,preds,1)#随机采样
    return np.argmax(probas)
import random
import sys
for epoch in range(1,60):#模型训练60轮
    print('\nEpoch:',epoch)
    model.fit(x,y,batch_size=128,epochs=1)#训练一次
    start_index=random.randint(0,len(text)-maxlen-1)
    #随机初始化一个序列,范围是0-(len(text)-maxlen-1)比如:一共100个字符,那么start_index就是39,这是
    #下一个字符的索引。
    generated_text=text[start_index:start_index+maxlen]
    #生成的内容是下一个字符到下一句话
    print('Generating with seed:\n'+generated_text)
    #print('--生成通过:'+generated_text)
    for temperature in [0.2,0.5,1.0,1.2]:#使用不同的softmax温度值采样
        print('')
        print('temperature',temperature,':')
        #sys.stdout.write(generated_text)#输出到控制台但是没有换行。

        #for i in range(400):#从种子文本开始,生成400个字符
        for i in range(40):#从种子文本开始,生成40个字符,太多
            sampled=np.zeros((1,maxlen,len(chars)))#对生成字符one-hot编码
            for t,char in enumerate(generated_text):
                sampled[0,t,char_indices[char]]=1.

            preds=model.predict(sampled,verbose=0)[0]#对下一个字符采样
            next_index=sample(preds,temperature)
            next_char=chars[next_index]
            generated_text+=next_char
            generated_text=generated_text[1:]
            sys.stdout.write(next_char)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值