成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

使用 LSTM 智能作詩送新年祝福

lauren_liuling / 2809人閱讀

摘要:經(jīng)過第一步的處理已經(jīng)把古詩詞詞語轉(zhuǎn)換為可以機(jī)器學(xué)習(xí)建模的數(shù)字形式,因為我們采用算法進(jìn)行古詩詞生成,所以還需要構(gòu)建輸入到輸出的映射處理。

LSTM 介紹

序列化數(shù)據(jù)即每個樣本和它之前的樣本存在關(guān)聯(lián),前一數(shù)據(jù)和后一個數(shù)據(jù)有順序關(guān)系。深度學(xué)習(xí)中有一個重要的分支是專門用來處理這樣的數(shù)據(jù)的——循環(huán)神經(jīng)網(wǎng)絡(luò)。循環(huán)神經(jīng)網(wǎng)絡(luò)廣泛應(yīng)用在自然語言處理領(lǐng)域(NLP),今天我們帶你從一個實際的例子出發(fā),介紹循環(huán)神經(jīng)網(wǎng)絡(luò)一個重要的改進(jìn)算法模型-LSTM。本文章不對LSTM的原理進(jìn)行深入,想詳細(xì)了解LSTM可以參考這篇 [譯] 理解 LSTM 網(wǎng)絡(luò)。本文重點從古詩詞自動生成的實例出發(fā),一步一步帶你從數(shù)據(jù)處理到模型搭建,再到訓(xùn)練出古詩詞生成模型,最后實現(xiàn)從古詩詞自動生成新春祝福詩詞。

數(shù)據(jù)處理

我們使用76748首古詩詞作為數(shù)據(jù)集,數(shù)據(jù)集下載鏈接,原始的古詩詞的存儲形式如下:

我們可以看到原始的古詩詞是文本符號的形式,無法直接進(jìn)行機(jī)器學(xué)習(xí),所以我們第一步需要把文本信息轉(zhuǎn)換為數(shù)據(jù)形式,這種轉(zhuǎn)換方式就叫詞嵌入(word embedding),我們采用一種常用的詞嵌套(word embedding)算法-Word2vec對古詩詞進(jìn)行編碼。關(guān)于Word2Vec這里不詳細(xì)講解,感興趣可以參考 [NLP] 秒懂詞向量Word2vec的本質(zhì)。在詞嵌套過程中,為了避免最終的分類數(shù)過于龐大,可以選擇去掉出現(xiàn)頻率較小的字,比如可以去掉只出現(xiàn)過一次的字。Word2vec算法經(jīng)過訓(xùn)練后會產(chǎn)生一個模型文件,我們就可以利用這個模型文件對古詩詞文本進(jìn)行詞嵌套編碼。

經(jīng)過第一步的處理已經(jīng)把古詩詞詞語轉(zhuǎn)換為可以機(jī)器學(xué)習(xí)建模的數(shù)字形式,因為我們采用LSTM算法進(jìn)行古詩詞生成,所以還需要構(gòu)建輸入到輸出的映射處理。例如:
“[長河落日圓]”作為train_data,而相應(yīng)的train_label就是“長河落日圓]]”,也就是
“[”->“長”,“長”->“河”,“河”->“落”,“落”->“日”,“日”->“圓”,“圓”->“]”,“]”->“]”,這樣子先后順序一一對相。這也是循環(huán)神經(jīng)網(wǎng)絡(luò)的一個重要的特征。
這里的“[”和“]”是開始符和結(jié)束符,用于生成古詩的開始與結(jié)束標(biāo)記。

總結(jié)一下數(shù)據(jù)處理的步驟:

讀取原始的古詩詞文本,統(tǒng)計出所有不同的字,使用 Word2Vec 算法進(jìn)行對應(yīng)編碼;

對于每首詩,將每個字、標(biāo)點都轉(zhuǎn)換為字典中對應(yīng)的編號,構(gòu)成神經(jīng)網(wǎng)絡(luò)的輸入數(shù)據(jù) train_data;

將輸入數(shù)據(jù)左移動構(gòu)成輸出標(biāo)簽 train_label;

經(jīng)過數(shù)據(jù)處理后我們得到以下數(shù)據(jù)文件:

poems_edge_split.txt:原始古詩詞文件,按行排列,每行為一首詩詞;

vectors_poem.bin:利用 Word2Vec訓(xùn)練好的詞向量模型,以開頭,按詞頻排列,去除低頻詞;

poem_ids.txt:按輸入輸出關(guān)系映射處理之后的語料庫文件;

rhyme_words.txt: 押韻詞存儲,用于押韻詩的生成;

在提供的源碼中已經(jīng)提供了以上四個數(shù)據(jù)文件放在data文件夾下,數(shù)據(jù)處理代碼見 data_loader.py 文件,源碼鏈接

模型構(gòu)建及訓(xùn)練

這里我們使用2層的LSTM框架,每層有128個隱藏層節(jié)點,我們使用tensorflow.nn模塊庫來定義網(wǎng)絡(luò)結(jié)構(gòu)層,其中RNNcell是tensorflow中實現(xiàn)RNN的基本單元,是一個抽象類,在實際應(yīng)用中多用RNNcell的實現(xiàn)子類BasicRNNCell或者BasicLSTMCell,BasicGRUCell;如果需要構(gòu)建多層的RNN,在TensorFlow中,可以使用tf.nn.rnn_cell.MultiRNNCell函數(shù)對RNNCell進(jìn)行堆疊。模型網(wǎng)絡(luò)的第一層要對輸入數(shù)據(jù)進(jìn)行 embedding,可以理解為數(shù)據(jù)的維度變換,經(jīng)過兩層LSTM后,接著softMax得到一個在全字典上的輸出概率。
模型網(wǎng)絡(luò)結(jié)構(gòu)如下:

定義網(wǎng)絡(luò)的類的程序代碼如下:

class CharRNNLM(object):
    def __init__(self, is_training, batch_size, vocab_size, w2v_model,
                 hidden_size, max_grad_norm, embedding_size, num_layers,
                 learning_rate, cell_type, dropout=0.0, input_dropout=0.0, infer=False):
        self.batch_size = batch_size
        self.hidden_size = hidden_size
        self.vocab_size = vocab_size
        self.max_grad_norm = max_grad_norm
        self.num_layers = num_layers
        self.embedding_size = embedding_size
        self.cell_type = cell_type
        self.dropout = dropout
        self.input_dropout = input_dropout
        self.w2v_model = w2v_model

        if embedding_size <= 0:
            self.input_size = vocab_size
            self.input_dropout = 0.0
        else:
            self.input_size = embedding_size

        # 輸入和輸入定義
        self.input_data = tf.placeholder(tf.int64, [self.batch_size, self.num_unrollings], name="inputs")
        self.targets = tf.placeholder(tf.int64, [self.batch_size, self.num_unrollings], name="targets")

        # 根據(jù)定義選擇不同的循環(huán)神經(jīng)網(wǎng)絡(luò)內(nèi)核單元
        if self.cell_type == "rnn":
            cell_fn = tf.nn.rnn_cell.BasicRNNCell
        elif self.cell_type == "lstm":
            cell_fn = tf.nn.rnn_cell.LSTMCell
        elif self.cell_type == "gru":
            cell_fn = tf.nn.rnn_cell.GRUCell

        params = dict()
        if self.cell_type == "lstm":
            params["forget_bias"] = 1.0
        cell = cell_fn(self.hidden_size, **params)

        cells = [cell]
        for i in range(self.num_layers-1):
            higher_layer_cell = cell_fn(self.hidden_size, **params)
            cells.append(higher_layer_cell)

        # 訓(xùn)練時是否進(jìn)行 Dropout
        if is_training and self.dropout > 0:
            cells = [tf.nn.rnn_cell.DropoutWrapper(cell, output_keep_prob=1.0-self.dropout) for cell in cells]

        # 對lstm層進(jìn)行堆疊
        multi_cell = tf.nn.rnn_cell.MultiRNNCell(cells)

        # 定義網(wǎng)絡(luò)模型初始狀態(tài)
        with tf.name_scope("initial_state"):
            self.zero_state = multi_cell.zero_state(self.batch_size, tf.float32)
            if self.cell_type == "rnn" or self.cell_type == "gru":
                self.initial_state = tuple(
                        [tf.placeholder(tf.float32,
                            [self.batch_size, multi_cell.state_size[idx]],
                            "initial_state_"+str(idx+1)) for idx in range(self.num_layers)])
            elif self.cell_type == "lstm":
                self.initial_state = tuple(
                        [tf.nn.rnn_cell.LSTMStateTuple(
                            tf.placeholder(tf.float32, [self.batch_size, multi_cell.state_size[idx][0]],
                                          "initial_lstm_state_"+str(idx+1)),
                            tf.placeholder(tf.float32, [self.batch_size, multi_cell.state_size[idx][1]],
                                           "initial_lstm_state_"+str(idx+1)))
                            for idx in range(self.num_layers)])

        # 定義 embedding 層
        with tf.name_scope("embedding_layer"):
            if embedding_size > 0:
                # self.embedding = tf.get_variable("embedding", [self.vocab_size, self.embedding_size])
                self.embedding = tf.get_variable("word_embeddings",
                    initializer=self.w2v_model.vectors.astype(np.float32))
            else:
                self.embedding = tf.constant(np.eye(self.vocab_size), dtype=tf.float32)

            inputs = tf.nn.embedding_lookup(self.embedding, self.input_data)
            if is_training and self.input_dropout > 0:
                inputs = tf.nn.dropout(inputs, 1-self.input_dropout)

        # 創(chuàng)建每個切分通道網(wǎng)絡(luò)層
        with tf.name_scope("slice_inputs"):
            sliced_inputs = [tf.squeeze(input_, [1]) for input_ in tf.split(
                axis = 1, num_or_size_splits = self.num_unrollings, value = inputs)]

        outputs, final_state = tf.nn.static_rnn(
                cell = multi_cell,
                inputs = sliced_inputs,
                initial_state=self.initial_state)
        self.final_state = final_state

        # 數(shù)據(jù)變換層,把經(jīng)過循環(huán)神經(jīng)網(wǎng)絡(luò)的數(shù)據(jù)拉伸降維
        with tf.name_scope("flatten_outputs"):
            flat_outputs = tf.reshape(tf.concat(axis = 1, values = outputs), [-1, hidden_size])

        with tf.name_scope("flatten_targets"):
            flat_targets = tf.reshape(tf.concat(axis = 1, values = self.targets), [-1])

        # 定義 softmax 輸出層
        with tf.variable_scope("softmax") as sm_vs:
            softmax_w = tf.get_variable("softmax_w", [hidden_size, vocab_size])
            softmax_b = tf.get_variable("softmax_b", [vocab_size])
            self.logits = tf.matmul(flat_outputs, softmax_w) + softmax_b
            self.probs = tf.nn.softmax(self.logits)

        # 定義 loss 損失函數(shù)
        with tf.name_scope("loss"):
            loss = tf.nn.sparse_softmax_cross_entropy_with_logits(
                    logits = self.logits, labels = flat_targets)
            self.mean_loss = tf.reduce_mean(loss)

        # tensorBoard 損失函數(shù)可視化
        with tf.name_scope("loss_montor"):
            count = tf.Variable(1.0, name="count")
            sum_mean_loss = tf.Variable(1.0, name="sum_mean_loss")

            self.reset_loss_monitor = tf.group(sum_mean_loss.assign(0.0),
                                               count.assign(0.0), name="reset_loss_monitor")
            self.update_loss_monitor = tf.group(sum_mean_loss.assign(sum_mean_loss+self.mean_loss),
                                                count.assign(count+1), name="update_loss_monitor")

            with tf.control_dependencies([self.update_loss_monitor]):
                self.average_loss = sum_mean_loss / count
                self.ppl = tf.exp(self.average_loss)

            average_loss_summary = tf.summary.scalar(
                    name = "average loss", tensor = self.average_loss)
            ppl_summary = tf.summary.scalar(
                    name = "perplexity", tensor = self.ppl)

        self.summaries = tf.summary.merge(
                inputs = [average_loss_summary, ppl_summary], name="loss_monitor")

        self.global_step = tf.get_variable("global_step", [], initializer=tf.constant_initializer(0.0))
        self.learning_rate = tf.placeholder(tf.float32, [], name="learning_rate")

        if is_training:
            tvars = tf.trainable_variables()
            grads, _ = tf.clip_by_global_norm(tf.gradients(self.mean_loss, tvars), self.max_grad_norm)
            optimizer = tf.train.AdamOptimizer(self.learning_rate)
            self.train_op = optimizer.apply_gradients(zip(grads, tvars), global_step=self.global_step)

訓(xùn)練時可以定義batch_size的值,是否進(jìn)行dropout,為了結(jié)果的多樣性,訓(xùn)練時在softmax輸出層每次可以選擇topK概率的字符作為輸出。訓(xùn)練完成后可以使用tensorboard 對網(wǎng)絡(luò)結(jié)構(gòu)和訓(xùn)練過程可視化展示。這里推薦大家一個在線人工智能建模平臺momodel.cn,帶有完整的Python和機(jī)器學(xué)習(xí)框架運行環(huán)境,并且有免費的GPU可以使用,大家可以訓(xùn)練的時候可以在這個平臺上試一下。訓(xùn)練部分的代碼和訓(xùn)練好的模型見鏈接。

詩詞生成

調(diào)用前面訓(xùn)練好的模型我們就可以實現(xiàn)一個古詩詞的應(yīng)用了,我這里利用 Mo平臺 實現(xiàn)了藏頭詩和藏子詩自動生成的功能,運行的效果如下:

新年快到了,趕緊利用算法作詩,給親朋好友送去“最聰明”的祝福吧!
PC端查看完整代碼

參考文章:
https://www.jianshu.com/p/9dc...
https://zhuanlan.zhihu.com/p/...
https://github.com/norybaby/poet

————————————————————————————————————Mo (網(wǎng)址:http://momodel.cn)是一個支持 Python 的人工智能建模平臺,能幫助你快速開發(fā)訓(xùn)練并部署 AI 應(yīng)用。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/20011.html

相關(guān)文章

  • Nervos 雙周報第 2 期 :祝福滿滿,期許滿滿新一年?。ㄗ詈笥胁实芭叮?/b>

    摘要:針對區(qū)塊鏈技術(shù)推出的中文播客第三期更新啦,與宣布正式建立合作關(guān)系,共同推進(jìn)解決方案的發(fā)展,團(tuán)隊去了成都做封閉開發(fā)更多動態(tài),都在這里社區(qū)動態(tài)終于更新啦本期是三位大佬一起暢聊攻擊,畫風(fēng)幽默,內(nèi)容全面。 Jan,29,2019showImg(https://segmentfault.com/img/bVbnWvk?w=1080&h=460); 親愛的 Nervos 粉絲們: 中國的農(nóng)歷新年馬...

    tomorrowwu 評論0 收藏0
  • 慶祝新年?畫一顆圣誕樹?還是...

    摘要:關(guān)于節(jié)日圣誕節(jié),元旦,看大家情侶在朋友圈里發(fā)各種慶祝的或者祝福的話語,甚是感動,然后悄悄拉黑了。預(yù)覽效果本地下打開很卡,火狐正常圣誕樹早先的時候是圣誕節(jié)的時候,看到各種用字符組成圣誕樹的形式,于是自己就去試了下,還是比較簡單的。 關(guān)于節(jié)日 圣誕節(jié),元旦,看大家(情侶)在朋友圈里發(fā)各種慶祝的或者祝福的話語,甚是感動,然后悄悄拉黑了。作為單身狗,我們也有自己慶祝節(jié)日的方式,今天我們就來實現(xiàn)...

    cloud 評論0 收藏0
  • 慶祝新年?畫一顆圣誕樹?還是...

    摘要:關(guān)于節(jié)日圣誕節(jié),元旦,看大家情侶在朋友圈里發(fā)各種慶祝的或者祝福的話語,甚是感動,然后悄悄拉黑了。預(yù)覽效果本地下打開很卡,火狐正常圣誕樹早先的時候是圣誕節(jié)的時候,看到各種用字符組成圣誕樹的形式,于是自己就去試了下,還是比較簡單的。 關(guān)于節(jié)日 圣誕節(jié),元旦,看大家(情侶)在朋友圈里發(fā)各種慶祝的或者祝福的話語,甚是感動,然后悄悄拉黑了。作為單身狗,我們也有自己慶祝節(jié)日的方式,今天我們就來實現(xiàn)...

    k00baa 評論0 收藏0
  • 慶祝新年?畫一顆圣誕樹?還是...

    摘要:關(guān)于節(jié)日圣誕節(jié),元旦,看大家情侶在朋友圈里發(fā)各種慶祝的或者祝福的話語,甚是感動,然后悄悄拉黑了。預(yù)覽效果本地下打開很卡,火狐正常圣誕樹早先的時候是圣誕節(jié)的時候,看到各種用字符組成圣誕樹的形式,于是自己就去試了下,還是比較簡單的。 關(guān)于節(jié)日 圣誕節(jié),元旦,看大家(情侶)在朋友圈里發(fā)各種慶祝的或者祝福的話語,甚是感動,然后悄悄拉黑了。作為單身狗,我們也有自己慶祝節(jié)日的方式,今天我們就來實現(xiàn)...

    zhoutk 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<