精华内容
下载资源
问答
  • 2017-06-29 14:51:02

    代码地址:https://github.com/hjptriplebee/Chinese_poem_generator, 欢迎fork, star

    机器人命名MC胖虎,目前只是最简单粗暴的方法,使用tensorflow完成,有些像人工智障,符合胖虎的人物设定,看一些效果:


    LSTM的原理网上资料很多,不了解的可以看这里:http://www.jianshu.com/p/9dc9f41f0b29

    本文以讲解写诗机器人实现为主,不会讲太多理论和tensorflow使用方法,好下面开始。

    训练数据预处理

    采用3w首唐诗作为训练数据,在github上dataset文件夹下可以看到,唐诗格式为”题目:诗句“,如下所示:


    我们首先通过”:“将题目和内容分离,然后做数据清洗过滤一些不好的训练样本,包含特殊符号、字数太少或太多的都要去除,最后在诗的前后分别加上开始和结束符号,用来告诉LSTM这是开头和结尾,这里用方括号表示。

    poems = []
    file = open(filename, "r")
    for line in file:  #every line is a poem
        #print(line)
        title, poem = line.strip().split(":")  #get title and poem
        poem = poem.replace(' ','')
        if '_' in poem or '《' in poem or '[' in poem or '(' in poem or '(' in poem:
            continue
        if len(poem) < 10 or len(poem) > 128:  #filter poem
            continue
        poem = '[' + poem + ']' #add start and end signs
        poems.append(poem)
    
    然后统计每个字出现的次数,并删除出现次数较少的生僻字

    #counting words
    allWords = {}
    for poem in poems:
        for word in poem:
            if word not in allWords:
                allWords[word] = 1
            else:
                allWords[word] += 1
    # erase words which are not common
    erase = []
    for key in allWords:
        if allWords[key] < 2:
            erase.append(key)
    for key in erase:
        del allWords[key]
    根据字出现的次数排序,建立字到ID的映射。为什么需要排序呢?排序后的ID从一定程度上表示了字的出现频率,两者之间有一定关系,比不排序直接映射更容易使模型学出规律。

    添加空格字符,因为诗的长度不一致,需要用空格填补,所以留出空格的ID。最后将诗转成字向量的形式。

    wordPairs = sorted(allWords.items(), key = lambda x: -x[1])
    words, a= zip(*wordPairs)
    words += (" ", )
    wordToID = dict(zip(words, range(len(words)))) #word to ID
    wordTOIDFun = lambda A: wordToID.get(A, len(words))
    poemsVector = [([wordTOIDFun(word) for word in poem]) for poem in poems] # poem to vector
    接下来构建训练batch,每一个batch中所有的诗都要补空格直到长度达到最长诗的长度。因为补的都是空格,所以模型可以学出这样一个规律:空格后面都是接着空格。X和Y分别表示输入和输出,输出为输入的错位,即模型看到字得到的输出应该为下一个字。

    这里注意一定要用np.copy,坑死我了!

    #padding length to batchMaxLength
    batchNum = (len(poemsVector) - 1) // batchSize
    X = []
    Y = []
    #create batch
    for i in range(batchNum):
        batch = poemsVector[i * batchSize: (i + 1) * batchSize]
        maxLength = max([len(vector) for vector in batch])
        temp = np.full((batchSize, maxLength), wordTOIDFun(" "), np.int32)
        for j in range(batchSize):
            temp[j, :len(batch[j])] = batch[j]
        X.append(temp)
        temp2 = np.copy(temp) #copy!!!!!!
        temp2[:, :-1] = temp[:, 1:]
        Y.append(temp2)

    搭建模型

    搭建一个LSTM模型,后接softmax,输出为每一个字出现的概率。这里对着LSTM模板抄一份,改改参数就好了。

    with tf.variable_scope("embedding"): #embedding
        embedding = tf.get_variable("embedding", [wordNum, hidden_units], dtype = tf.float32)
        inputbatch = tf.nn.embedding_lookup(embedding, gtX)
    
    basicCell = tf.contrib.rnn.BasicLSTMCell(hidden_units, state_is_tuple = True)
    stackCell = tf.contrib.rnn.MultiRNNCell([basicCell] * layers)
    initState = stackCell.zero_state(np.shape(gtX)[0], tf.float32)
    outputs, finalState = tf.nn.dynamic_rnn(stackCell, inputbatch, initial_state = initState)
    outputs = tf.reshape(outputs, [-1, hidden_units])
    
    with tf.variable_scope("softmax"):
        w = tf.get_variable("w", [hidden_units, wordNum])
        b = tf.get_variable("b", [wordNum])
        logits = tf.matmul(outputs, w) + b
    
    probs = tf.nn.softmax(logits)

    模型训练

    先定义输入输出,构建模型,然后设置损失函数、学习率等参数。

    gtX = tf.placeholder(tf.int32, shape=[batchSize, None])  # input
    gtY = tf.placeholder(tf.int32, shape=[batchSize, None])  # output
    logits, probs, a, b, c = buildModel(wordNum, gtX)
    targets = tf.reshape(gtY, [-1])
    #loss
    loss = tf.contrib.legacy_seq2seq.sequence_loss_by_example([logits], [targets],
                                                              [tf.ones_like(targets, dtype=tf.float32)], wordNum)
    cost = tf.reduce_mean(loss)
    tvars = tf.trainable_variables()
    grads, a = tf.clip_by_global_norm(tf.gradients(cost, tvars), 5)
    learningRate = learningRateBase
    optimizer = tf.train.AdamOptimizer(learningRate)
    trainOP = optimizer.apply_gradients(zip(grads, tvars))
    globalStep = 0
    然后开始训练,训练时先寻找能否找到检查点,找到则还原,否则重新训练。然后按照batch一步步读入数据训练,学习率逐渐递减,每隔几个step就保存一下模型。

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        saver = tf.train.Saver()
        if reload:
            checkPoint = tf.train.get_checkpoint_state(checkpointsPath)
            # if have checkPoint, restore checkPoint
            if checkPoint and checkPoint.model_checkpoint_path:
                saver.restore(sess, checkPoint.model_checkpoint_path)
                print("restored %s" % checkPoint.model_checkpoint_path)
            else:
                print("no checkpoint found!")
    
        for epoch in range(epochNum):
            if globalStep % learningRateDecreaseStep == 0: #learning rate decrease by epoch
                learningRate = learningRateBase * (0.95 ** epoch)
            epochSteps = len(X) # equal to batch
            for step, (x, y) in enumerate(zip(X, Y)):
                #print(x)
                #print(y)
                globalStep = epoch * epochSteps + step
                a, loss = sess.run([trainOP, cost], feed_dict = {gtX:x, gtY:y})
                print("epoch: %d steps:%d/%d loss:%3f" % (epoch,step,epochSteps,loss))
                if globalStep%1000==0:
                    print("save model")
                    saver.save(sess,checkpointsPath + "/poem",global_step=epoch)

    自动写诗

    在自动写诗之前,我们需要定义一个输出概率对应到单词的功能函数,为了避免每次生成的诗都一样,需要引入一定的随机性。不选择输出概率最高的字,而是将概率映射到一个区间上,在区间上随机采样,输出概率大的字对应的区间大,被采样的概率也大,但胖虎也有小概率会选择其他字。因为每一个字都有这样的随机性,所以每次作出的诗都完全不一样。

    def probsToWord(weights, words):
        """probs to word"""
        t = np.cumsum(weights) #prefix sum
        s = np.sum(weights)
        coff = np.random.rand(1)
        index = int(np.searchsorted(t, coff * s)) # large margin has high possibility to be sampled
        return words[index]
    然后开始写诗,首先仍然是构建模型,定义相关参数,加载checkpoint。

    gtX = tf.placeholder(tf.int32, shape=[1, None])  # input
    logits, probs, stackCell, initState, finalState = buildModel(wordNum, gtX)
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        saver = tf.train.Saver()
        checkPoint = tf.train.get_checkpoint_state(checkpointsPath)
        # if have checkPoint, restore checkPoint
        if checkPoint and checkPoint.model_checkpoint_path:
            saver.restore(sess, checkPoint.model_checkpoint_path)
            print("restored %s" % checkPoint.model_checkpoint_path)
        else:
            print("no checkpoint found!")
            exit(0)
    生成generateNum这么多首诗,每首诗以左中括号开始,以右中括号或空格结束,每次生成的prob用probsToWord方法转成字。

    poems = []
    for i in range(generateNum):
        state = sess.run(stackCell.zero_state(1, tf.float32))
        x = np.array([[wordToID['[']]]) # init start sign
        probs1, state = sess.run([probs, finalState], feed_dict={gtX: x, initState: state})
        word = probsToWord(probs1, words)
        poem = ''
        while word != ']' and word != ' ':
            poem += word
            if word == '。':
                poem += '\n'
            x = np.array([[wordToID[word]]])
            #print(word)
            probs2, state = sess.run([probs, finalState], feed_dict={gtX: x, initState: state})
            word = probsToWord(probs2, words)
        print(poem)
        poems.append(poem)
    还可以写藏头诗,前面的搭建模型,加载checkpoint等内容一样,作诗部分,每遇到标点符号,人为控制下一个输入的字为指定的字就可以了。需要注意,在标点符号后,因为没有选择模型输出的字,所以需要将state往前滚动一下,直接跳过这个字的生成。

    flag = 1
    endSign = {-1: ",", 1: "。"}
    poem = ''
    state = sess.run(stackCell.zero_state(1, tf.float32))
    x = np.array([[wordToID['[']]])
    probs1, state = sess.run([probs, finalState], feed_dict={gtX: x, initState: state})
    for c in characters:
        word = c
        flag = -flag
        while word != ']' and word != ',' and word != '。' and word != ' ':
            poem += word
            x = np.array([[wordToID[word]]])
            probs2, state = sess.run([probs, finalState], feed_dict={gtX: x, initState: state})
            word = probsToWord(probs2, words)
    
        poem += endSign[flag]
        # keep the context, state must be updated
        if endSign[flag] == '。':
            probs2, state = sess.run([probs, finalState],
                                     feed_dict={gtX: np.array([[wordToID["。"]]]), initState: state})
            poem += '\n'
        else:
            probs2, state = sess.run([probs, finalState],
                                     feed_dict={gtX: np.array([[wordToID[","]]]), initState: state})
    
    print(characters)
    print(poem)
    大约在GPU上训练20epoch效果就不错了!

    代码地址:https://github.com/hjptriplebee/Chinese_poem_generator, 欢迎fork, star

    估计后续还会出看图写诗机器人-MC胖虎2.0

    说了这么多胖虎该生气了!


    更多相关内容
  • 使用tensorflow深度学习,训练机器古诗词。唐诗生成
  • 原标题:如何利用深度学习写诗歌(使用Python进行文本生成)报 名翻译:李雪冬编辑:李雪冬前 言从短篇小说到写5万字的小说,机器不断涌现出前所未有的词汇。在web上有大量的例子可供开发人员使用机器学习来编写文本,...

    原标题:如何利用深度学习写诗歌(使用Python进行文本生成)

    报 名

    翻译:李雪冬

    编辑:李雪冬

    前 言

    从短篇小说到写5万字的小说,机器不断涌现出前所未有的词汇。在web上有大量的例子可供开发人员使用机器学习来编写文本,呈现的效果有荒谬的也有令人叹为观止的。

    由于自然语言处理(NLP)领域的重大进步,机器能够自己理解上下文和编造故事。

    7c57fb8c7de68494e9c3ba4583130f72.png

    文本生成的例子包括,机器编写了流行小说的整个章节,比如《权力的游戏》和《哈利波特》,取得了不同程度的成功。在本文中,我们将使用python和文本生成的概念来构建一个机器学习模型,可以用莎士比亚的风格来写十四行诗。让我们来看看它!

    本文的主要内容

    1.什么是文本生成?

    2.文本生成的不同步骤。

    3.入口的依赖

    4.加载数据

    5.创建字符/单词映射

    6.数据预处理

    7.模型创建

    8.生成文本

    9.尝试不同的模型

    10.更多的训练模型

    (1)一个更深层次的模型

    (2).一个更广泛的模型

    (3)一个超大的模型

    1

    什么是文本生成

    现在,有大量的数据可以按顺序分类。它们以音频、视频、文本、时间序列、传感器数据等形式存在。针对这样特殊类别的数据,如果两个事件都发生在特定的时间内,A先于B和B先于A是完全不同的两个场景。然而,在传统的机器学习问题中,一个特定的数据点是否被记录在另一个数据点之前是不重要的。这种考虑使我们的序列预测问题有了新的解决方法。

    文本是由一个挨着一个的字符组成的,实际中是很难处理的。这是因为在处理文本时,可以训练一个模型来使用之前发生的序列来做出非常准确的预测,但是之前的一个错误的预测有可能使整个句子变得毫无意义。这就是让文本生成器变得棘手的原因!

    为了更好地理解代码,请浏览这两篇文章。LSTM背后的理论(链接:https://www.analyticsvidhya.com/blog/2017/12/fundamentals-of-deep-learning-introduction-to-lstm/)

    2

    文本生成的步骤

    文本生成通常包括以下步骤:

    导入依赖

    加载数据

    创建映射

    数据预处理

    模型构建

    生成文本

    让我们详细地看一下每一个。

    3

    导入依赖

    importnumpy as np

    importpandas as pd

    from keras.models importSequential

    from keras.layers importDense

    from keras.layers importDropout

    from keras.layers importLSTM

    from keras.utils importnp_utils

    4

    加载数据

    text=(open( "/Users/pranjal/Desktop/text_generator/sonnets.txt").read())

    text=text.lower()

    这里,我们正在加载所有莎士比亚十四行诗的集合,这些十四行诗可以从这里(链接:http://www.gutenberg.org/cache/epub/1041/pg1041.txt)下载。我清理了这个文件以删除开始和结束的学分,并且可以从我的git存储库下载。文本文件被打开并保存在text中。然后将该内容转换为小写,以减少可能单词的数量(稍后将对此进行详细介绍)。

    5

    创建映射

    映射是在文本中为字符/单词分配任意数字的步骤。这样,所有的惟一字符/单词都映射到一个数字。这一点很重要,因为机器比文本更能理解数字,这使得训练过程更加容易。

    characters = sorted( list( set(text)))

    n_to_char = {n: charforn, charin enumerate(characters)}

    char_to_n = { char:n forn, charin enumerate(characters)}

    我已经创建了一个字典,其中给文本中每个独特的字符分配一个数字。所有独特的字符首先存储在字符中,然后被枚举。

    这里还必须注意,我使用了字符级别的映射,而不是单词映射。然而,与基于字符的模型相比,基于单词的模型与其他模型相比具有更高的准确性。这是因为基于字符需要一个更大的网络来学习长期依赖关系,因为它不仅要记住单词的顺序,而且还要学会预测一个语法正确的单词。但是,在基于单词的模型中,后者已经被处理好了。

    6

    数据预处理

    在构建LSTM模型时,这是最棘手的部分。将手头的数据转换成可供模型训练的格式是一项困难的任务。我会把这个过程分解成小的部分,让你更容易理解。

    X = []

    Y = []

    length = len(text)

    seq_length = 100

    fori in range( 0, length-seq_length, 1):

    sequence = text[i:i + seq_length]

    label =text[i + seq_length]

    X.append([char_to_n[ char] forcharin sequence])

    Y.append(char_to_n[label])

    这里,X是我们的训练序列,Y是我们的目标数组。seq_length是我们在预测某个特定字符之前要考虑的字符序列的长度。for循环用于遍历文本的整个长度,并创建这样的序列(存储在X中)和它们的真实值(存储在Y中),为了更好地弄清楚“真实值”的概念。让我们以一个例子来理解这一点:

    对于4的序列长度和文本“hello india”,我们将有X和Y表示如下:

    e08e86a2bce4d6f5a5f48f52611ba786.png

    现在,LSTMs接受输入的形式是(number_of_sequence, length_of_sequence, number_of_features),这不是数组的当前格式。另外,我们需要将数组Y转换成一个one-hot编码格式。

    X_modified = np.reshape(X, (len(X), seq_length, 1))

    X_modified = X_modified / float(len(characters))

    Y_modified = np_utils.to_categorical(Y)

    我们首先将数组X重构为所需的维度。然后,我们将X_modified的值进行缩放,这样我们的神经网络就可以更快地训练,并且更少的机会被困在局部最小值中。此外,我们的Y_modified是一个热编码,以删除在映射字符过程中可能引入的任何顺序关系。也就是说,与“z”相比,“a”可能会被分配一个较低的数字,但这并不表示两者之间有任何关系。

    最后的数组将是:

    d541e83fe113f9fba4269382cf1709ae.png

    7

    建立模型

    model = Sequential()

    model.add(LSTM( 400, input_shape=(X_modified.shape[ 1], X_modified.shape[ 2]), return_sequences=True))

    model.add(Dropout( 0.2))

    model.add(LSTM( 400))

    model.add(Dropout( 0.2))

    model.add(Dense(Y_modified.shape[ 1], activation= 'softmax'))

    model.compile(loss= 'categorical_crossentropy', optimizer= 'adam')

    我们正在构建一个具有两个LSTM层的序列模型,每个层有400个单元。第一层需要用输入形状输入。为了使下一个LSTM层能够处理相同的序列,我们输入return_sequence参数为真。 此外,设置参数为0.2的dropout层,以检查是否过拟合。最后一层输出one-hot编码的矢量,它提供字符输出。

    8

    文本生成

    string_mapped = X[ 99]

    fori in range(seq_length):

    x = np.reshape(string_mapped,( 1,len(string_mapped), 1))

    x = x / float(len(characters))

    pred_index = np.argmax(model.predict(x, verbose= 0))

    seq = [n_to_char[value] forvalue in string_mapped]

    string_mapped.append(pred_index)

    string_mapped = string_mapped[ 1:len(string_mapped)]

    我们从X数组中的随机一行开始,这是一个100个字符的数组。在此之后,我们的目标是预测x后面的另外100个字符,输入将如同前面一样被重新塑造和缩放,预测下一个具有最大概率的字符。seq用于存储到现在为止预测行为用到的字符串的解码格式。接下来,新字符串被更新,这样第一个字符被删除,新的预测字符被包含进来。您可以在这里 找到整个代码。这里提供了训练文件,注释和训练的模型权重供您参考。

    9

    尝试不同模型

    基线模型:

    当训练为1个周期,批大小为100时,给出如下输出:

    's the riper should by time decease,

    his tender heir might bear his memory:

    but thou, contracted toet she the the the the the the the the

    thi the the the the the the the the the the the the the the the the the

    thi the the the the the the the the the the the the the the the the the

    thi the the the the the the the the the the the the the the the the the

    thi the the the the the the the the the the the the the the the the the

    thi the the the the the the the the th'

    这个输出没有多大意义。它只是重复同样的预测,就好像它被困在一个循环中一样。这是因为与我们训练的微型模型相比,语言预测模型太复杂了。

    让我们试着训练同样的模型,但是将时间周期变长。

    加强训练时间的模型:

    这次我们训练我们的模型为100个周期,批大小设置为50。我们至少得到了一个非重复的字符序列,其中包含了相当数量的合理单词。此外,该模型还学会了生成一个类似14行诗的结构。

    'The riper should by time decease,

    his tender heir might bear his memory:

    but thou, contracted to thine own besire,

    that in the breath ther doomownd wron to ray,

    dorh part nit backn oy steresc douh dxcel;

    for that i have beauty lekeng norirness,

    for all the foowing of a former sight,

    which in the remame douh a foure to his,

    that in the very bumees of toue mart detenese;

    how ap i am nnw love, he past doth fiamee.

    to diserace but in the orsths of are orider,

    waie agliemt would have me '

    但是,这个模型还不够好,不能产生高质量的内容。所以现在我们要做的是当一个深度学习模型没有产生好的结果时,每个人都会做的事情。建立一个更深层次的架构!

    一个更深的模型:

    一位机器学习的大牛曾经说过:如果模型做得不好,那就增加层数!我将用我的模型做同样的事情。让我们再添加一个LSTM层,里面有400个单元,然后是一个参数为0.2的dropout层,看看我们得到了什么。

    "The riper should by time decease,

    his tender heir might bear his memory:

    but thou, contracted to the world's false sporoe,

    with eyes so dond touls be thy domfornds,

    which for memorion of the seasons new;

    mike own self-love to shou art constant

    how can i then be oy love doth give,

    the rose looks fair, but fairer bomments age.

    now with the seas that i have seen dychl

    that mot to teed of you, if h ho bontent,

    and all the ress of the heartai thee;

    the world will was iis bound and farty "

    结果开始变得有趣。语法实现了自我增强,保持了十四行诗的结构和标点的完整。然而,这仍然需要很大的改进。让我们尝试探索一个更广泛的网络,一个拥有更多单元的网络。

    一个更广的模型:

    在两个LSTM层中,我将单元的数量增加到700个。这个调整产生了以下的诗歌:

    "The riper should by time decease,

    his tender heir might bear his memory:

    but thou, contracted to thine own bright eyes,

    feed'st thy sigh aare so beuider poise,

    oor maty dis surre that gairs mot me love thee;

    when i braye the would and lays in the eesire.

    than thmu disgrmed stand with my bootr still nsentente;

    tell ia to thou art thou wilt woon'thy sook,

    and touain then tor, give thy soue semping.

    whose whod the better of your befaiss nu sante,

    though i, suoll oas, and i lose bouh twa"

    这个做法并没有令我满意,因为这些词已经失去了意义。但是,有趣的是,这个模型开始尝试建立一些韵脚。模型毕竟是在开始尝试更深层次理解诗歌!但是,对于训练出既有意义又优美的诗歌的目标,我们不能妥协,对吗?

    让我们把它放在一个超大的模型中。

    一个超大的模型:

    我将层数增加到3层,每层有700个单元,并训练了100个周期。产生的结果是一篇宏伟的诗篇。请看:

    "The riper should by time decease,

    his tender heir might bear his memory:

    but thou, contracted to thine own bright eyes,

    feed'st thy light's flame with self-substantial fuel,

    my beept is she breat oe bath dasehr ill:

    tirse do i pine and turfeit day by day,

    or gluttoning on all, or all away.

    Lxxvi

    why is my verse so barren of new pride,

    so far from variation or quick change?

    why with the time do i not glance aside

    to new-found methods, and to compounds strange?

    why write i stil"

    这篇诗歌不仅用词准确,而且也学会了押韵。我们本可以有一件更宏伟的艺术品,但是作为入门LSTM的一个开始,这就够了。这已经是比大多数人更好地表达了

    本文转载自公众号:机器学习算法全栈工程师 (已获授权)

    本文翻译自pranjal seivastava的一篇文章

    (链接:https://www.analyticsvidhya.com/blog/2018/03/text-generation-using-python-nlp/)原作者保留版权

    -END-

    8370db0ccd6d81c6ae66b59c6ed2bbc8.png

    图文来自网络、如涉及版权问题,请联系我们以便处理。文章内容纯属作者个人观点,不代表本网观点。返回搜狐,查看更多

    责任编辑:

    展开全文
  • 本文致力于解决和完成自然语言处理中的难题之一——机器自动写诗,采用循环神经网络(RNN)的变体长短时记忆网络(Long Short Term Memory networks, LSTM),通过合理的设计网络结构和算法实现了自动写诗和藏头诗的...
  • 在web上有大量的例子可供开发人员使用机器学习来编写文本,呈现的效果有荒谬的也有令人叹为观止的。  由于自然语言处理(NLP)领域的重大进步,机器能够自己理解上下文和编造故事。 文本生成的例子包括,机器编写了...

               翻译:李雪冬             

    前  言


    从短篇小说到写5万字的小说,机器不断涌现出前所未有的词汇。在web上有大量的例子可供开发人员使用机器学习来编写文本,呈现的效果有荒谬的也有令人叹为观止的。 
    由于自然语言处理(NLP)领域的重大进步,机器能够自己理解上下文和编造故事。

    文本生成的例子包括,机器编写了流行小说的整个章节,比如《权力的游戏》和《哈利波特》,取得了不同程度的成功。在本文中,我们将使用python和文本生成的概念来构建一个机器学习模型,可以用莎士比亚的风格来写十四行诗。让我们来看看它!

    本文的主要内容

    1.什么是文本生成? 
    2.文本生成的不同步骤。 
    3.入口的依赖 
    4.加载数据 
    5.创建字符/单词映射 
    6.数据预处理 
    7.模型创建 
    8.生成文本 
    9.尝试不同的模型 
    10.更多的训练模型 
    (1)一个更深层次的模型 
    (2).一个更广泛的模型 
    (3)一个超大的模型

    1

    什么是文本生成


    现在,有大量的数据可以按顺序分类。它们以音频、视频、文本、时间序列、传感器数据等形式存在。针对这样特殊类别的数据,如果两个事件都发生在特定的时间内,A先于B和B先于A是完全不同的两个场景。然而,在传统的机器学习问题中,一个特定的数据点是否被记录在另一个数据点之前是不重要的。这种考虑使我们的序列预测问题有了新的解决方法。

    文本是由一个挨着一个的字符组成的,实际中是很难处理的。这是因为在处理文本时,可以训练一个模型来使用之前发生的序列来做出非常准确的预测,但是之前的一个错误的预测有可能使整个句子变得毫无意义。这就是让文本生成器变得棘手的原因! 
    为了更好地理解代码,请浏览这两篇文章。LSTM背后的理论(链接:https://www.analyticsvidhya.com/blog/2017/12/fundamentals-of-deep-learning-introduction-to-lstm/)

    2

    文本生成的步骤


    文本生成通常包括以下步骤:

    1. 导入依赖

    2. 加载数据

    3. 创建映射

    4. 数据预处理

    5. 模型构建

    6. 生成文本

    让我们详细地看一下每一个。

    3

    导入依赖


    import numpy as np
    import pandas as pd
    from keras.models import Sequential
    from keras.layers import Dense
    from keras.layers import Dropout
    from keras.layers import LSTM
    from keras.utils import np_utils
    4

    加载数据

    text=(open("/Users/pranjal/Desktop/text_generator/sonnets.txt").read())
    text=text.lower()

    这里,我们正在加载所有莎士比亚十四行诗的集合,这些十四行诗可以从这里(链接:http://www.gutenberg.org/cache/epub/1041/pg1041.txt)下载。我清理了这个文件以删除开始和结束的学分,并且可以从我的git存储库下载。 文本文件被打开并保存在text中。然后将该内容转换为小写,以减少可能单词的数量(稍后将对此进行详细介绍)。

    5

    创建映射


    映射是在文本中为字符/单词分配任意数字的步骤。这样,所有的惟一字符/单词都映射到一个数字。这一点很重要,因为机器比文本更能理解数字,这使得训练过程更加容易。

    characters = sorted(list(set(text)))
    n_to_char = {n:char for n, char in enumerate(characters)}
    char_to_n = {char:n for n, char in enumerate(characters)}
    

    我已经创建了一个字典,其中给文本中每个独特的字符分配一个数字。所有独特的字符首先存储在字符中,然后被枚举。

    这里还必须注意,我使用了字符级别的映射,而不是单词映射。然而,与基于字符的模型相比,基于单词的模型与其他模型相比具有更高的准确性。这是因为基于字符需要一个更大的网络来学习长期依赖关系,因为它不仅要记住单词的顺序,而且还要学会预测一个语法正确的单词。但是,在基于单词的模型中,后者已经被处理好了。


    6

    数据预处理


    在构建LSTM模型时,这是最棘手的部分。将手头的数据转换成可供模型训练的格式是一项困难的任务。 我会把这个过程分解成小的部分,让你更容易理解。

    X = []
    Y = []
    length = len(text)
    seq_length = 100
    for i in range(0, length-seq_length, 1):
    sequence = text[i:i + seq_length]
    label =text[i + seq_length]
    X.append([char_to_n[char] for char in sequence])
    Y.append(char_to_n[label])
    

    这里,X是我们的训练序列,Y是我们的目标数组。seq_length是我们在预测某个特定字符之前要考虑的字符序列的长度。for循环用于遍历文本的整个长度,并创建这样的序列(存储在X中)和它们的真实值(存储在Y中),为了更好地弄清楚“真实值”的概念。让我们以一个例子来理解这一点: 

    对于4的序列长度和文本“hello india”,我们将有X和Y表示如下: 

    现在,LSTMs接受输入的形式是(number_of_sequence, length_of_sequence, number_of_features),这不是数组的当前格式。另外,我们需要将数组Y转换成一个one-hot编码格式。

    X_modified = np.reshape(X, (len(X), seq_length, 1))
    X_modified = X_modified / float(len(characters))
    Y_modified = np_utils.to_categorical(Y)


    我们首先将数组X重构为所需的维度。然后,我们将X_modified的值进行缩放,这样我们的神经网络就可以更快地训练,并且更少的机会被困在局部最小值中。此外,我们的Y_modified是一个热编码,以删除在映射字符过程中可能引入的任何顺序关系。也就是说,与“z”相比,“a”可能会被分配一个较低的数字,但这并不表示两者之间有任何关系。 
    最后的数组将是: 


    7

    建立模型


    model = Sequential()
    model.add(LSTM(400, input_shape=(X_modified.shape[1],            X_modified.shape[2]), return_sequences=True))
    model.add(Dropout(0.2))
    model.add(LSTM(400))
    model.add(Dropout(0.2))
    model.add(Dense(Y_modified.shape[1], activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adam')
    我们正在构建一个具有两个LSTM层的序列模型,每个层有400个单元。第一层需要用输入形状输入。为了使下一个LSTM层能够处理相同的序列,我们输入return_sequence参数为真。 此外,设置参数为0.2的dropout层,以检查是否过拟合。最后一层输出one-hot编码的矢量,它提供字符输出。 8

    文本生成


    string_mapped = X[99]
    for i in range(seq_length):
    x = np.reshape(string_mapped,(1,len(string_mapped), 1))
    x = x / float(len(characters))
    pred_index = np.argmax(model.predict(x, verbose=0))
    seq = [n_to_char[value] for value in string_mapped]
    string_mapped.append(pred_index)
    string_mapped = string_mapped[1:len(string_mapped)]


    我们从X数组中的随机一行开始,这是一个100个字符的数组。在此之后,我们的目标是预测x后面的另外100个字符,输入将如同前面一样被重新塑造和缩放,预测下一个具有最大概率的字符。seq用于存储到现在为止预测行为用到的字符串的解码格式。接下来,新字符串被更新,这样第一个字符被删除,新的预测字符被包含进来。您可以在这里 找到整个代码。这里提供了训练文件,注释和训练的模型权重供您参考。 9

    尝试不同模型

    基线模型:

    当训练为1个周期,批大小为100时,给出如下输出:

    's the riper should by time decease,
    his tender heir might bear his memory:
    but thou, contracted toet she the the the the the the the the
    thi the the the the the the the the the the the the the the the the the
    thi the the the the the the the the the the the the the the the the the
    thi the the the the the the the the the the the the the the the the the
    thi the the the the the the the the the the the the the the the the the
    thi the the the the the the the the th'

    这个输出没有多大意义。它只是重复同样的预测,就好像它被困在一个循环中一样。这是因为与我们训练的微型模型相比,语言预测模型太复杂了。 
    让我们试着训练同样的模型,但是将时间周期变长。

    加强训练时间的模型:

    这次我们训练我们的模型为100个周期,批大小设置为50。我们至少得到了一个非重复的字符序列,其中包含了相当数量的合理单词。此外,该模型还学会了生成一个类似14行诗的结构。

    'The riper should by time decease,
    his tender heir might bear his memory:
    but thou, contracted to thine own besire,
    that in the breath ther doomownd wron to ray,
    dorh part nit backn oy steresc douh dxcel;
    for that i have beauty lekeng norirness,
    for all the foowing of a former sight,
    which in the remame douh a foure to his,
    that in the very bumees of toue mart detenese;
    how ap i am nnw love, he past doth fiamee.
    to diserace but in the orsths of are orider,
    waie agliemt would have me '


    但是,这个模型还不够好,不能产生高质量的内容。所以现在我们要做的是当一个深度学习模型没有产生好的结果时,每个人都会做的事情。建立一个更深层次的架构!

    一个更深的模型:

    一位机器学习的大牛曾经说过:如果模型做得不好,那就增加层数!我将用我的模型做同样的事情。让我们再添加一个LSTM层,里面有400个单元,然后是一个参数为0.2的dropout层,看看我们得到了什么。

    "The riper should by time decease,
    his tender heir might bear his memory:
    but thou, contracted to the world's false sporoe,
    with eyes so dond touls be thy domfornds,
    which for memorion of the seasons new;
    mike own self-love to shou art constant
    how can i then be oy love doth give,
    the rose looks fair, but fairer bomments age.
    now with the seas that i have seen dychl
    that mot to teed of you, if h ho bontent,
    and all the ress of the heartai thee;
    the world will was iis bound and farty "

    结果开始变得有趣。语法实现了自我增强,保持了十四行诗的结构和标点的完整。然而,这仍然需要很大的改进。让我们尝试探索一个更广泛的网络,一个拥有更多单元的网络。

    一个更广的模型:

    在两个LSTM层中,我将单元的数量增加到700个。这个调整产生了以下的诗歌:

    "The riper should by time decease,
    his tender heir might bear his memory:
    but thou, contracted to thine own bright eyes,
    feed'st thy sigh aare so beuider poise,
    oor maty dis surre that gairs mot me love thee;
    when i braye the would and lays in the eesire.
    than thmu disgrmed stand with my bootr still nsentente;
    tell ia to thou art thou wilt woon'thy sook,
    and touain then tor, give thy soue semping.
    whose whod the better of your befaiss nu sante,
    though i, suoll oas, and i lose bouh twa"

    这个做法并没有令我满意,因为这些词已经失去了意义。但是,有趣的是,这个模型开始尝试建立一些韵脚。模型毕竟是在开始尝试更深层次理解诗歌!但是,对于训练出既有意义又优美的诗歌的目标,我们不能妥协,对吗? 
    让我们把它放在一个超大的模型中。

    一个超大的模型:

    我将层数增加到3层,每层有700个单元,并训练了100个周期。产生的结果是一篇宏伟的诗篇。请看:

    "The riper should by time decease,
    his tender heir might bear his memory:
    but thou, contracted to thine own bright eyes,
    feed'st thy light's flame with self-substantial fuel,
    my beept is she breat oe bath dasehr ill:
    tirse do i pine and turfeit day by day,
    or gluttoning on all, or all away.
    Lxxvi
    why is my verse so barren of new pride,
    so far from variation or quick change?
    why with the time do i not glance aside
    to new-found methods, and to compounds strange?
    why write i stil"

    这篇诗歌不仅用词准确,而且也学会了押韵。我们本可以有一件更宏伟的艺术品,但是作为入门LSTM的一个开始,这就够了。这已经是比大多数人更好地表达了!

    参考资料

    欢迎交流与转载,公众号:机器学习算法全栈工程师 

    本文翻译自pranjal seivastava的一篇文章 

    (链接:https://www.analyticsvidhya.com/blog/2018/03/text-generation-using-python-nlp/)原作者保留版权





    end






    机器学习算法全栈工程师


                                一个用心的公众号

    长按,识别,加关注

    进群,学习,得帮助

    你的关注,我们的热度,

    我们一定给你学习最大的帮助


    展开全文
  • 本文致力于解决和完成自然语言处理中的难题之一——机器自动写诗,采用循环神经网络(RNN)的变体长短时记忆网络(Long Short Term Memory networks, LSTM),通过合理的设计网络结构和算法实现了自动写诗和藏头诗的...
  • 用RNN做了一个自动写诗的程序,包含已经训练好的model,可以直接运行,训练数据也包含在里面
  • 深度学习(三)之LSTM写诗

    千次阅读 2022-04-05 12:45:03
    Python微信订餐小程序课程视频 ...机器学习业,圣贤不可求。临戎辞蜀计,忠信尽封疆。天子咨两相,建章应四方。自疑非俗态,谁复念鹪鹩。 生成藏头诗: 国步平生不愿君,古人今在古人风。 科公

    Python微信订餐小程序课程视频

    https://edu.csdn.net/course/detail/36074

    Python实战量化交易理财系统

    https://edu.csdn.net/course/detail/35475
    目录* 数据预处理

    1. 根据前文生成诗:

    机器学习业,圣贤不可求。临戎辞蜀计,忠信尽封疆。天子咨两相,建章应四方。自疑非俗态,谁复念鹪鹩。

    1. 生成藏头诗:

    步平生不愿君,古人今在古人风。

    公既得忘机者,白首空山道姓名。

    道不应无散处,未曾进退却还征。

    环境:

    • python:3.9.7
    • pytorch:1.11.0
    • numpy:1.21.2

    代码地址:https://github.com/xiaohuiduan/deeplearning-study/tree/main/写诗

    数据预处理

    数据集文件由3部分组成:ix2wordword2ixdata

    • ix2word:id到word的映射,如{23:‘姑’},一共有8293个word。
    • word2ix2:word到id的映射,如{‘姑’:23}
    • data:保存了诗的数据,一共有57580首诗,每条数据由125个word构成;如果诗的长度大于125则截断,如果诗的长度小于125,则使用""进行填充。

    每条数据的构成规则为:…\dots诗词

    在训练的时候,不考虑填充数据,因此,将数据中的填充数据去除,去除后,部分数据显示如下:

    构建数据集

    模型输入输出决定了数据集怎么构建,下图是模型的输入输出示意图。诗词生成实际上是一个语言模型,我们希望Model能够根据当前输入x0,x1,x2…xn−1x_0,x_1,x_2\dots x_{n-1}去预测下一个状态xnx_n。如图中所示例子,则是希望在训练的过程中,模型能够根据输入床前明月光生成床前明月光,

    因此根据“床前明月光,凝是地上霜。举头望明月,低头思故乡”,可以生成如下的X和Y(seq_len=6)。

    X:床前明月光,Y:床前明月光,

    X:,凝是地上霜,Y:凝是地上霜。

    X:。举头望明月,Y:举头望明月,

    X:,低头思故乡,Y:低头思故乡。

    代码示意图如下所示,seq_len代表每条训练数据的长度。

    seq_len = 48
    X = []
    Y = []
    
    poems_data = [j for i in poems for j in i] # 将所有诗的内容变成一个一维数组
    
    for i in range(0,len(poems_data) - seq_len -1,seq_len):
        X.append(poems_data[i:i+seq_len])
        Y.append(poems_data[i+1:i+seq_len+1])
    
    

    模型结构

    模型结构如下所示,模型一共由3部分构成,Embedding层,LSTM层和全连接层。输入数据首先输入Embedding层,进行word2vec,然后将Word2Vec后的数据输入到LSTM中,最后将LSTM的输出输入到全连接层中得到预测结果。

    模型构建代码如下,其中在本文中embedding_dim=200,hidden_dim=1024

    import torch
    import torch.nn.functional as F
    import torch.nn as nn
    class PoemNet(nn.Module):
        def \_\_init\_\_(self, vocab\_size, embedding\_dim, hidden\_dim):
            """
     vocab\_size:训练集合字典大小(8293)
     embedding\_dim:word2vec的维度
     hidden\_dim:LSTM的hidden\_dim
     """
            super(PoemNet, self).__init__()
            self.hidden_dim = hidden_dim
            self.embeddings = nn.Embedding(vocab_size, embedding_dim)
            self.lstm = nn.LSTM(embedding_dim, self.hidden_dim,batch_first=True)
    
            self.fc = nn.Sequential(
                nn.Linear(self.hidden_dim,2048),
                nn.ReLU(),
                nn.Dropout(0.25),
                
                nn.Linear(2048,4096),
                nn.Dropout(0.2),
                nn.ReLU(),
                nn.Linear(4096,vocab_size),
            )
    
        def forward(self, input,hidden=None):
            """
     input:输入的诗词
     hidden:在生成诗词的时候需要使用,在pytorch中,如果不指定初始状态h\_0和C\_0,则其
     默认为0.
     pytorch的LSTM的输出是(output,(h\_n,c\_n))。实际上,output就是h\_1,h\_2,……h\_n
     """
            embeds = self.embeddings(input)
            batch_size, seq_len = input.size()
            if hidden is None:
                output, hidden = self.lstm(embeds)
            else:
                # h\_0,c\_0 = hidden
                output, hidden = self.lstm(embeds,hidden)
        
            output = self.fc(output)
            output = output.reshape(batch_size * seq_len, -1)
            output = F.log_softmax(output,dim=1)
            return output,hidden
    
    

    优化器使用的是Adam优化器,lr=0.001,损失函数是CrossEntropyLoss。训练次数为100个epcoh。

    生成诗

    因为在模型构建的过程中,使用了dropout,所以在模型使用的时候,需要将model设置为eval模式。

    生成诗的逻辑图:

    根据上文生成诗

    根据上图的原理,写出的代码如下所示:

    def generate\_poem(my\_words,max\_len=128):
        '''
     根据前文my\_words生成一首诗。max\_len表示生成诗的最大长度。
     '''
    
        def \_\_generate\_next(idx,hidden=None):
            """
     根据input和hidden输出下一个预测
     """
            input = torch.Tensor([idx]).view(1,1).long().to(device)
            output,hidden = my_net(input,hidden)
            return output,hidden
    
        # 初始化hidden状态
        output,hidden = __generate_next(word2ix[""])
        my_words_len = len(my_words)
        result = []
        for word in my_words:
            result.append(word)
            # 积累hidden状态(h & c)
            output,hidden = __generate_next(word2ix[word],hidden)
        
        _,top_index = torch.max(output,1)
    
        word = idx2word[top_index[0].item()]
    
        result.append(word)
    
        for i in range(max_len-my_words_len):
            output,hidden = __generate_next(top_index[0].item(),hidden)
    
            _,top_index = torch.max(output,1)
            if top_index[0].item() == word2ix['']: # 如果诗词已经预测到结尾
                break
            word = idx2word[top_index[0].item()]
            result.append(word)
        return "".join(result)
    
    generate_poem("睡觉")
    
    

    睡觉寒炉火,晨钟坐中朝。炉烟沾煖露,池月静清砧。自有传心法,曾无住处传。不知尘世隔,一觉一壺秋。皎洁垂银液,浮航入绿醪。谁知旧邻里,相对似相亲。

    生成藏头诗

    生成藏头诗的方法与根据上文生成诗的方法大同小异。

    def acrostic\_poetry(my\_words):
        def \_\_generate\_next(idx,hidden=None):
            """
     根据input和hidden输出下一个预测词
     """
            input = torch.Tensor([idx]).view(1,1).long().to(device)
            output,hidden = my_net(input,hidden)
            return output,hidden
    
        def \_\_generate(word,hidden):
            """
     根据word生成一句诗(以“。”结尾的话) 如根据床生成“床前明月光,凝是地上霜。”
     """
            generate_word = word2ix[word]
            sentence = []
            sentence.append(word)
            while generate_word != word2ix["。"]: 
                output,hidden = __generate_next(generate_word,hidden)
                _,top_index = torch.max(output,1)
                generate_word = top_index[0].item()
                sentence.append(idx2word[generate_word])
            # 根据"。"生成下一个隐状态。
            _,hidden = __generate_next(generate_word,hidden)
            return sentence,hidden
    
        _,hidden = __generate_next(word2ix[""])
        result = []
        for word in my_words:
            sentence,hidden = __generate(word,hidden)
            result.append("".join(sentence))
        print("\n".join(result))
    
    acrostic_poetry("滚去读书")
    
    

    滚发初生光,三乘如太白。 去去冥冥没,冥茫寄天海。 读书三十年,手把棼琴策。 书罢华省郎,忧人惜凋病。

    参考

    展开全文
  • 本自动写诗代码解决的问题是随意给出首句,如给定“湖光秋月两相和”,输出模型续写的诗句,要求输出的诗句尽可能地满足汉语语法和表达习惯。
  • 2017年围棋界发生了一件比较重要事,Master(Alphago)以60连胜横扫天下,击败各路世界冠军,人工智能以气势如虹的姿态出现在我们人类的面前。围棋曾经一度被称为“人类智慧的堡垒”,如今,这座堡垒也随之成为过去...
  • tensorflow深度学习,使用encoder-decoder模型,进行诗词训练
  • AI作深度学习应用演示平台

    千次阅读 2020-05-25 21:48:43
    挺有意思的一个AI作网站,之前也用过几个作网站,但是感觉这个作出来的更有内味。 对于已经有人生成过的词句,结果返回的很快,对于生词,可能需要多等一会。 刚开始测试的时候还挺快,现在生成的...AI作深度
  • python:为你写诗

    2020-11-26 02:29:09
    实验背景周末,早晨下了点小雨,淅淅沥沥,来到阳台坐了一会,看着雨有点发呆,真惬意,真想雨一直这么下着。...实验器材●python● LSTM● tensorflow● 唐诗实验内容数据获取深度学习技术能发挥其作用,最重...
  • LSTM 是深度学习中的一种常见的循环神经模型。本课程教会学员使用TensorFlow搭建LSTM模型完成写诗实战训练!
  • 可以将目标网站的唐诗数据以“标题:诗句”的形式存储到本地文件,其中每首占据一行。以供网络训练使用。 毕业论文毕业论文毕业论文毕业论文毕业论文毕业论文毕业论文毕业论文毕业论文毕业论文毕业论文毕业...
  • 由于个人原因,核心代码忘记上传,已经在这上传了完整版https://download.csdn.net/download/HowardEmily/15876211?spm=1001.2014.3001.5503 抱歉!
  • 在pytorch下,以数万首唐诗为素材,训练双层LSTM神经网络,使其能够以唐诗的方式写诗。 代码结构分为四部分,分别为 1.model.py,定义了双层LSTM模型 2.data.py,定义了从网上得到的唐诗数据的处理方法 3.utlis.py ...
  • 利用深度学习种的NLP技术自动学习全唐诗,最后能够书写固定格式的唐诗
  • 人工智能写诗训练过程中输出的诗句
  • 理解 循环神经网络(Recurrent Neural Network, RNN)是一类以序列(sequence)数据为输入,在序列的演进方向进行递归(recursion)且所有节点(循环单元)按链式连接的递归神经网络(recursive neural network)。...
  • 第1章递归神经网络原理(RNN)34分钟4节 1-1课程简介[免费观看]01:21 1-2递归神经网络(RNN)08:39 1-3RNN网络细节11:54 1-4LSTM网络架构12:36 第2章RNN手写字体识别32分钟3节 2-1处理Mnist数据集11:50 ...
  • 一、亮出效果 世界上美好的事物很多,当我们想要表达时,总是感觉文化底蕴不够...这篇教程就是让人工智能学习大量的诗句,找到作的规律,然后你给他几个关键字,他给你一首。 看效果: 输入的关键词 输出的诗句
  • 自动写诗ppt汇报.pptx

    2020-06-21 00:19:30
    自动写诗是自然语言处理的一个入门实验,这个实验通过各种诗歌的数据集,对其中的数据进行预处理后采用各种网络模型进行学习和训练最终得到一个良好的loss和acuary之后,把模型保存下来,并输入一句话运行输出完整的...
  • 本章重点讲解自然语言处理中的两个基本概念:词向量(Word Vector)和循环神经网络(Recurrent Neural Network,RNN),并尝试自己动手,用RNN实现自动写诗
  • tensorflow2.0 实现自动写诗

    千次阅读 2020-06-20 22:38:25
    使用tensorflow经典的深度学习框架,使用python对其进行提取数据集的数据,并训练模型后,将本次构建的模型能实现应用。(注本次实验,由于自己的tensorflow程序出现了数据爆炸将电脑多次卡死的现象,这里参考了...
  • 目录注意事项一、数据介绍二、opt对象三、data.py四、☆model.py五、utils.py封装可视化操作,略六、main.py了解`...注意:本文代码来源《深度学习框架PyTorch:入门与实践》,点击书名跳转到对应GitHub。 作为从Te
  • 很早之前,我曾经过一个古体生成器(详情可以戳TensorFlow练手项目二:基于循环神经网络(RNN)的古诗生成器),那个时候用的还是Python 2.7和TensorFlow 1.4。 随着框架的迭代,API 的变更,老项目已经很难无障碍...
  • TensorFlow LSTM 写诗代码与数据
  • 在本次公开课中, 讲者将介绍清华自然语言处理与社会人文计算实验室的自动作系统,“九歌”,及其相关的技术方法和论文。分享嘉宾:矣晓沅,清华大学计算机系在读硕士, 导师为孙茂松教授。主要从事自然语言处理、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,337
精华内容 2,134
关键字:

深度学习写诗

友情链接: C#_2010_Example.zip