NLP实战:300行代码实现基于GRU的自动对春联

1. 前言

我一直有个口号:

我有两个爱好,一个是传统文化,一个是高新技术。

没错,我一直探索用高新技术来激活传统文化,用传统文化来滋养高新技术。人工智能概念股

我写了一个基于TensorFlow中GRU网络来自动对春联的程序测试抑郁症

Inp测试抑郁症ut是人工输入的上联,Output是机器自动给出的下联。

Input: <start> 神 州 万 里 春 光 美 <end> [2, 61, 27, 26, 43, 4, 20, 78, 3]
Output:<start> 祖 国 两 制 好 事 兴 <end> [2, 138, 11, 120, 428, 73, 64, 46, 3]
Input:  <start> 爆 竹 迎 新 春 <end> [2, 167, 108, 23, 9, 4, 3]
Output: <start> 瑞 雪 兆 丰 年 <end> [2, 92, 90, 290, 30, 8, 3]
Input:  <start> 金 牛 送 寒 去 <end> [2, 63, 137, 183, 302, 101, 3]
Output: <start> 玉 鼠 喜 春 来 <end> [2, 126, 312, 17, 4, 26, 3]
Input:  <start> 锦 绣 花 似 锦 <end> [2, 68, 117, 8, 185, 68, 3]
Output: <start> 缤 纷 春 如 风 <end> [2, 1651, 744, 4, 140, 7, 3]
Input:  <start> 春 风 送 暖 山 河 好 <end> [2, 4, 5, 183, 60, 7, 71, 45, 3]
Output: <start> 瑞 雪 迎 春 世 纪 新 <end> [2, 92, 90, 27, 4, 36, 99, 5, 3]
Input:  <start> 百 花 争 艳 春 风 得 意 <end> [2, 48, 8, 164, 76, 4, 5, 197, 50, 3]
Output: <start> 万 马 奔 腾 喜 气 福 多 <end> [2, 6, 28, 167, 58, 17, 33, 15, 113, 3]

2. 数据的准备

人工tensorflow2.0教程智能的背后是大量数据的训练,关于数据来源,我还有一篇文章《没啥才人工智能的定义艺,30行代码写了个春联数据爬虫》,主要讲述如何从网络上爬取春联数据。

NLP实战:300行代码实现基于GRU的自动对春联

我们就有了春联数据,就可以开始进行训练了。

2.1 导入所需要的包

不管是哪种开发语言,首先是导入包,导入的每一个都是有用的。

# tensorflow主包
import tensorflow as tf
# 分词器,将文字变为数字
from tensorflow.keras.preprocessing.text import Tokenizer 
# 把序列填充,让数据长度相等,不足的补0
from tensorflow.keras.preprocessing.sequence import pad_sequences 
# 维度数组与矩阵运算的数学函数库
import numpy as np 
# 神经网络的序列
from tensorflow.python.keras.engine.sequential import Sequential
# 将训练集按照一定比例拆分为训练和测试数据
from sklearn.model_selection import train_test_split
# 神经网络的层
from tensorflow.keras import layers
# 神经网络的优化器
from tensorflow.keras.optimizers import Adam
# 系统文件一些操作
import os
# 时间
import time

2.2 读取要测试你的自卑程度训练的数据

首先要把我们准备的数据进行预处理。

你得从文件中读出文本吧,读完了还得分出测试你的自卑程度上下联单独存储吧,因为上联是输入,下联是输出,都要告诉机器的。机器呢,它又只认识数字,不认识文字。所以,你还得把它们转化成数字(这一步叫序列化)。

下面一段代码,做的事情是从.txt中读取文本,然后将文本拆分保存到上联、下联两个数组中。

# 给一段文本加上开始和结束标记,主要是告诉机器什么时候开始,什么时候结束
def preprocess_sentence(w):
    w = w.strip()
    w = '<start> ' + w + ' <end>'
    return w
# 加载一定条数的数据
def load_data(num = 10000):
    # 保存上联(input)和下联(target)的数组
    inp_lang = []
    targ_lang = []
    # 指定文件位置(同级目录data下的data.txt文件)
    file = open('F://all.txt','rb')
    line = file.readline()
    # 读取一行文本,如果此行存在
    while line: 
        # 读出内容:【春 来 眼 际 , 喜 上 眉 梢】拆分上下联
        wstr = str(line, encoding = "utf-8")
        wstrs = wstr.split(',')
        if len(wstrs) > 1:
            inp_lang.append(preprocess_sentence(wstrs[0]))
            targ_lang.append(preprocess_sentence(wstrs[1]))
        # 接着再读下一行
        line = file.readline()
        # 如果超过预设最大数量,则退出循环
        if len(inp_lang) > num:break 
    file.close()
    return inp_lang, targ_lang

特别说明一下,文本内容样式是:

春 来 眼 际 , 喜 上 眉 梢
春 光 普 照 , 福 气 长 临
春 和 景 明 , 物 阜 年 丰

每个字之间都有人工智能al女神古力娜扎一个空格,主要目的是中文gitlab分词。上下联之间使用gitee区分。

调用一下,打印出两个数组如下:

inp_lang, targ_lang = load_data()
print("inp_lang=>","\n ",inp_lang,"inp_lang=>","\n ", targ_lang)
'''
inp_lang => ['<start> 春 来 眼 际 <end>', '<start> 春 光 普 照 <end>'] 
targ_lang=> ['<start> 喜 上 眉 梢 <end>', '<start> 福 气 长 临 <end>']
'''

2.3 将文本进行序列化

我们获得了上面人工智能概念股文字版的标准结构。但是,机器不认识,需要将他们变成数字版的。

下面我们要做的基本上就是要将人工智能的定义“床前明月光”变为“65498人工智能技术应用”。

# 分词器,将文本转化为序列:上天言好事->65234
def tokenize(lang):
    # 创建分词器,默认以空格分词
    lang_tokenizer = Tokenizer(oov_token='<OOV>', filters='',split=' ')
    # 分词器设置处理训练的文本。  {'<end>': 2,'<start>': 1,'下': 54,'不': 5}
    lang_tokenizer.fit_on_texts(lang) 
    # 分词器序列化文本为数字。[[18, 19],[1, 18, 19,20]]
    tensor = lang_tokenizer.texts_to_sequences(lang)
    max_sequence_len = max([len(x) for x in tensor])
    # 预处理文本,补齐长度,统一格式 [[0, 0, 18, 19],[1, 18, 19, 20]]
    tensor = pad_sequences(tensor, maxlen=max_sequence_len)
    # 将序列化后的数字和包含段落信息的分词器返回
    return tensor, lang_tokenizer
input_tensor, inp_lang_tokenizer = tokenize(inp_lang)
target_tensor, targ_lang_tokenizer = tokenize(targ_lang)

返回值里面,第一tensor是文字转变的数字,第二个lang_tokenizer是吃透了这段文本的分词器,里面包含了这段文本的信息,比如总共多少个字,这些字都是什么,每个字的编号是多少,相当于一个“数据管家”。

里面涉及到了一些知识点:Tokenizer、texts_to_sequences、pad_sequenc机器学习es。我都给你准备好了,你不点一下吗?

到了这里,春联里的上联和TensorFlow下联的序列化数据,我们就都有了。

上联是:[[1,3,5,7,9]]。下联是:[[2,4,6,8,0]]。

2.4 做更适合框架的数据

看似到这一步就可以了,但是为了更好地融入机器学习框架的体系,还需要对数据进一步加工和处理。tensorflow是干什么的

# 包装成TF需要的格式,采用8:2切分训练集和验证集
input_tensor_train, input_tensor_val, target_tensor_train, target_tensor_val = train_test_split(input_tensor, target_tensor, test_size=0.2)
BUFFER_SIZE = len(input_tensor_train) # 训练集的大小
BATCH_SIZE = 64 # 批次大小,一次取多少条数据
# 一轮训练,需要几步取完所有数据
steps_per_epoch = len(input_tensor_train)//BATCH_SIZE  
# 将数据集顺序打乱
dataset = tf.data.Dataset.from_tensor_slices((input_tensor_train, target_tensor_train)).shuffle(BUFFER_SIZE)
# 生成训练批次,N批64条的数据drop_remainder=True最后一个批次不够的舍弃,去除余数。
dataset = dataset.batch(BATCH_SIZE, drop_remainder=True)

tr人工智能的定义ain_test_split会按照一定的比例,将数据切分为训练数据和验证数据。

即便如此,数据量可能还是巨大的,比如500万条。一次吃起来太费劲,所以就有了一个批次batch的概念,它表示每次取多少条数据BATCH_SIZE进行处理。所有数据,按照一批一批地取,tensorflow菜鸟教程全部扫个遍,我们称为一个周期epoch。每取一次数据进行处理,称为走了一步step

这些都是这个行业的黑话(shuyu)git教程

3. 模型的人工智能al女神古力娜扎构建

模型是个啥?这里是有关神经网络模型的序列和层、激活函数的介绍。

看看最好,不看也行,我再简单一说。

模型就好比工厂里流水线的机器,塞进去原料,吐出来成品。

就如同一个小孩,你教测试抑郁症的20道题给他认识苹果、桔子、人工智能技术应用香蕉、梨这些都是人工智能之父水果tensorflow菜鸟教程,他自己找特点总结规律,最终开悟了。后面,你给他一个猕猴桃和馒头,他能清楚地知道馒头和水果不测试用例是一类东西。具体他怎么判断的,是基于他大脑里那个固定的模型推演的,大脑的结构是固定的,但是思维方式的变化的。测试手机是否被监控

对于人工智能来说也类github永久回家地址似,我们要构建的模型就是大脑的结构。

要实现自动对对联的功能,我们也得构建一个模型,让数据按照这种结构去自己组织和思考,最终让它具git命令备思维。

3.1 GRU神经网络

我们听github永久回家地址说过很多种神经网络,他们各有特点,就像京东、天猫gitlab、拼多多的差别一样,我们也需要测试抑郁症的20道题从众多网络中选取一个来解决问题。

giti是什么牌子例子中,我们选择了GRU神经网络。

很遗憾,百度百科上都没有GRU的词giti是什么牌子条。我们想学点人工智能真的很难,找不到靠谱的资料。我想这也是为什么我这么菜,还有人来看我博客的原因。

GRU是RNN(Recugithub永久回家地址rrent NeTensorFlowural Network人工智能换脸鞠婧祎郑爽-循环神经网络)的一种。RNN上个世纪就出现了,但是有硬伤。后来,在1997年就出现了LSTM(Long-Short Term Memory-长短期记忆人工神经网人工智能电影络),但是它也有很多弊端。于是,在2014年,就出现了GRU(Gate Recurrent Unit-门循环单元)来救场。目前来看,用着还行。

说这github测试抑郁程度的问卷的目的,主要是想说明你要想了解GRU,其实得先了解RNN。它是处理一段序列的,不同于图像识别处理单张图片,它更像是处理一段视频tensorflow菜鸟教程。那人工智能专业是后话,现在可以先了解一下我讲的GRU。

下面是GRU的示意图。

NLP实战:300行代码实现基于GRU的自动对春联

能看懂最好,看不懂也不强求,它人工智能概念股可能影响你的研究,但是绝对不影响你的使用。

我还是忍不住想解释一下。

我们看到这个单元有两个输入:h0、x1,输出了下一个h1。这里面x1是测试用例序列里某一时段的输入,h0是上一个序tensorflow安装列传来的状态,经过一番运测试抑郁程度的问卷tensorflow版本,得出下一个状态h1。拿对联举例子,比如“春光普照”这一句。

序列 x1 h0 h1
1 前面没东西 后面的,你注意“春”
2 上面好像说到“春”了 上家是“春”,tensorflow菜鸟教程我这里是“光”
3 上面有提到“gitee春光” “光”无所谓,把“春”记好就行,我出“普”
4 “春”是一tensorflow和pytorch的区别个季节,“普”是全的意思 ……

它就是这么朴实无华,同一个结构,一遍遍地去循环,但是每Git次都得到了新的信息保存在h里遗传下去,于是就拥有tensorflow训练模型了记忆。

字——,机器是不认识的,即便是变成了数字,它也是理解不了语义的,他需要转为多维向量来解释这一切,这一步叫编码

为什么要编码,可以去了解下嵌入Embedding的概念。

编好码之后,对联数据就这样交给神经网络,训练上几次,它就学到里面的“道”、“规则”、“猫腻”。它就会特别注意,字与字之间是如何联系的,一句话之中,前言和后语是如何对应的。其实都是多维向量之间的参数计算人工智能

NLP实战:300行代码实现基于GRU的自动对春联

训练时,神经网络计算出了向量参数,也就是评委团tensorflow2.0教程。当我们想要让它预测的时候,可以将向量转化为字符,这tensorflow是干什么的个过程叫做解码

人工智能的定义以,训练和预测的流程就是:编码—观察计算总结—解码对照答案

3.2 编码器

首先我们将序列进行编码,也就是把输入进行升维。有了前面的介绍,相信下面这30行代码你可以轻松掌握了。

embedding_dim = 256 # 嵌入层的维度
units = 1024 # 神经元数量
# 输入集字库的数量,+1是因为有长度不够时,为了凑数的补0
vocab_inp_size = len(inp_lang_tokenizer.word_index)+1 
# 输出集字库的数量,+1是因为有0
vocab_tar_size = len(targ_lang_tokenizer.word_index)+1  
# 编码器,把数据转化为向量
class Encoder(tf.keras.Model):
  def __init__(self, vocab_size, embedding_dim, enc_units, batch_sz):
    super(Encoder, self).__init__()
    self.batch_sz = batch_sz # 每次批次大小
    self.enc_units = enc_units # 神经元数量
    # 嵌入层(字符数量,维度数)
    self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)
    # 门控循环单元 GRU
    self.gru = tf.keras.layers.GRU(self.enc_units, # 神经元数量
                                   return_sequences=True, # 返回序列
                                   return_state=True, # 返回状态
                                   recurrent_initializer='glorot_uniform') # 选择初始化器,固定值
  def call(self, x, hidden):
    x = self.embedding(x)
    output, state = self.gru(x, initial_state = hidden)
    return output, state
  def initialize_hidden_state(self):
    return tf.zeros((self.batch_sz, self.enc_units))
encoder = Encoder(vocab_inp_size, embedding_dim, units, BATCH_SIZE)

基本思路就是:每个字拆分出上百个维度,然后和上千个神经元进行运算,通过自己猜测的结果和标准输出进行比较,最终得出最适合的参数值。

3.3 注意力机器

如果只有编码和解码,流程就像下面这样,是可以满足需求的。

NLP实战:300行代码实现基于GRU的自动对春联

但是,这也有问题。当预测Y1时,Git评委是c,预人工智能测Y2时评委也是c,也就是说某时段的X对Ygitlab的影响是相同的。

但是,实际上一个序列中前后的内容是有关联的,比如这样一句话:我没有否定我不是不想你。如果只有一个固定评委,句子越长,携带的信息就会被稀释的越严重。

所以,除了全局状态之外,也需要关注局部的状态,测试抑郁症因此需要引入注意力机器。

NLP实战:300行代码实现基于GRU的自动对春联

引入注意力机制之后,“我没有否定我不是不想你”中的否定词语将被注意或者忽略。把“没有”、“否定”、“不是”、“不”去掉,这句话就变成了“我想你”。

其实,注意力机制就是一个权重配置。


# 注意力机器
class BahdanauAttention(tf.keras.layers.Layer):
    def __init__(self, units):
        super(BahdanauAttention, self).__init__()
        self.W1 = tf.keras.layers.Dense(units)
        self.W2 = tf.keras.layers.Dense(units)
        self.V = tf.keras.layers.Dense(1)
    def call(self, query, values):
        # 隐藏层的形状 == (批大小,隐藏层大小)
        # hidden_with_time_axis 的形状 == (批大小,1,隐藏层大小)
        # 这样做是为了执行加法以计算分数  
        hidden_with_time_axis = tf.expand_dims(query, 1)
        # 分数的形状 == (批大小,最大长度,1)
        # 我们在最后一个轴上得到 1, 因为我们把分数应用于 self.V
        # 在应用 self.V 之前,张量的形状是(批大小,最大长度,单位)
        score = self.V(tf.nn.tanh(self.W1(values) + self.W2(hidden_with_time_axis)))
        # 注意力权重 (attention_weights) 的形状 == (批大小,最大长度,1)
        attention_weights = tf.nn.softmax(score, axis=1)
        # 上下文向量 (context_vector) 求和之后的形状 == (批大小,隐藏层大小)
        context_vector = attention_weights * values
        context_vector = tf.reduce_sum(context_vector, axis=1)
        return context_vector, attention_weights

上面输出一个向Git量和它的权人工智能技术应用重。

3.4 解码器

下面是解码器的代码,它和编码相反。最终是降维,将多维向量再复原到语料库中。

# 解码器
class Decoder(tf.keras.Model):
    def __init__(self, vocab_size, embedding_dim, dec_units, batch_sz):
        super(Decoder, self).__init__()
        self.batch_sz = batch_sz
        self.dec_units = dec_units
        self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)
        self.gru = tf.keras.layers.GRU(self.dec_units,
                                    return_sequences=True,
                                    return_state=True,
                                    recurrent_initializer='glorot_uniform')
        self.fc = tf.keras.layers.Dense(vocab_size)
        # 用于注意力
        self.attention = BahdanauAttention(self.dec_units)
    def call(self, x, hidden, enc_output):
        # 编码器输出 (enc_output) 的形状 == (批大小,最大长度,隐藏层大小)
        context_vector, attention_weights = self.attention(hidden, enc_output)
        # x 在通过嵌入层后的形状 == (批大小,1,嵌入维度)
        x = self.embedding(x)
        # x 在拼接 (concatenation) 后的形状 == (批大小,1,嵌入维度 + 隐藏层大小)
        x = tf.concat([tf.expand_dims(context_vector, 1), x], axis=-1)
        # 将合并后的向量传送到 GRU
        output, state = self.gru(x)
        # 输出的形状 == (批大小 * 1,隐藏层大小)
        output = tf.reshape(output, (-1, output.shape[2]))
        # 输出的形状 == (批大小,vocab)
        x = self.fc(output)
        return x, state, attention_weights
decoder = Decoder(vocab_tar_size, embedding_dim, units, BATCH_SIZE)

这样,编码器,解码器Git,注意力机器,都有了,下面测试用例就可以进行数据训练了。

4. 训练数据

上面,格式化的训练数据准备好了。模型也准备好了,下面就该训练了。

训练就是把数据,按照模型预设的层次(网络结构),按照一定的幅度(损失函数)进行探索。

4.1 损失函数

下面是损失函数的设置,同时也设置了训练结果文件的保存位置。

optimizer = tf.keras.optimizers.Adam()
loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True, reduction='none')
# 保存训练数据的位置,此处设置了绝对路径
checkpoint_dir = 'F://juejin_chunlian/training_checkpoints'
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")
checkpoint = tf.train.Checkpoint(optimizer=optimizer,encoder=encoder,decoder=decoder)
def loss_function(real, pred):
  mask = tf.math.logical_not(tf.math.equal(real, 0))
  loss_ = loss_object(real, pred)
  mask = tf.cast(mask, dtype=loss_.dtype)
  loss_ *= mask
  return tf.reduce_mean(loss_)

4.2 训练一步

下面这个函数,就是执行一步训练的。

@tf.function
def train_step(inp, targ, enc_hidden):
    loss = 0
    with tf.GradientTape() as tape:
        enc_output, enc_hidden = encoder(inp, enc_hidden)
        dec_hidden = enc_hidden
        dec_input = tf.expand_dims([targ_lang_tokenizer.word_index['<start>']] * BATCH_SIZE, 1)
        # 强制 - 将目标词作为下一个输入
        for t in range(1, targ.shape[1]):
            # 将编码器输出 (enc_output) 传送至解码器
            predictions, dec_hidden, _ = decoder(dec_input, dec_hidden, enc_output)
            loss += loss_function(targ[:, t], predictions)
            # 使用强制
            dec_input = tf.expand_dims(targ[:, t], 1)
    batch_loss = (loss / int(targ.shape[1]))
    variables = encoder.trainable_variables + decoder.trainable_variables
    gradients = tape.gradient(loss, variables)
    optimizer.apply_gradients(zip(gradients, variables))
    return batch_loss

将上联输入giti是什么牌子序列、下联输出序列、编码隐藏层传入,它最终返回本次训练的损失情况。

损失越小,说明越好,和预期越接近。

4.3 多轮训练

上面是tensorflow菜鸟教程训练一步。

我们知道,所有数据扫个遍gitlab叫一个epochtensorflow版本对应一个epoch需要好多步才能完成。但是,我们还需要训练多个epoch

EPOCHS = 2000
for epoch in range(EPOCHS):
    start = time.time()
    enc_hidden = encoder.initialize_hidden_state()
    total_loss = 0
    for (batch, (inp, targ)) in enumerate(dataset.take(steps_per_epoch)):
        batch_loss = train_step(inp, targ, enc_hidden)
        total_loss += batch_loss
        if batch % 10 == 0:
            print('Epoch {} Batch {} Loss {:.4f}'.format(epoch + 1, batch,batch_loss.numpy()))
    # 每10个周期(epoch),保存(检查点)一次模型
    if (epoch + 1) % 10 == 0:
        print('save model')
        checkpoint.save(file_prefix = checkpoint_prefix)
    print('Epoch {} Loss {:.4f}'.format(epoch + 1,total_loss / steps_per_epoch))
    print('Time taken for 1 epoch {} sec\n'.format(time.time() - start))

就这样github中文官网网页训练吧。tensorflow和pytorch的区别

后面你就静静地看着日志打印,等着它训练完成。

这个过程很慢,具体看你的机器giti轮胎情况。

我机器并不好,训练一轮大约30分钟。开始没有耐心,急于验证效果,训练100轮就停止了,试了下它对出来的下联是什tensorflow菜鸟教程么样子的,结果连字数一致都没法保证,更别提意义相对,效果那叫一个差测试工程师

我减少春联条数到200条,增大训练轮数giti到1000次,效果也是很差,giti我一度认为是算法有问题。

后来,耐下心来,大数据量下的千轮级别的大出血训练了好几天,效人工智能技术应用果就好了不少。看来,机器学测试抑郁程度的问卷习的两个基础真的很重要:大数据量、多训练次数。而好的算法,是后面的事情。测试仪

5. 验证效果

最后Git是验证效果。

def max_length(tensor):
    return max(len(t) for t in tensor)
# 计算目标张量的最大长度 (max_length)。如果训练集确定,其实这个可以写个固定的。
max_length_targ, max_length_inp = max_length(target_tensor), max_length(input_tensor)
def evaluate(sentence):
    sentence = preprocess_sentence(sentence)
    inputs = [inp_lang_tokenizer.word_index[i] for i in sentence.split(' ')]
    print("inputs:",inputs)
    inputs = pad_sequences([inputs], maxlen=max_length_inp)
    inputs = tf.convert_to_tensor(inputs)
    result = ''
    hidden = [tf.zeros((1, units))]
    enc_out, enc_hidden = encoder(inputs, hidden)
    dec_hidden = enc_hidden
    dec_input = tf.expand_dims([targ_lang_tokenizer.word_index['<start>']], 0)
    outputs = []
    for t in range(max_length_targ):
        predictions, dec_hidden, attention_weights = decoder(dec_input,dec_hidden, enc_out)
        predicted_id = tf.argmax(predictions[0]).numpy()
        outputs.append(predicted_id)
        result += targ_lang_tokenizer.index_word[predicted_id] + ' '
        if targ_lang_tokenizer.index_word[predicted_id] == '<end>':
            print("outputs:",outputs)
            return result, sentence
        # 预测的 ID 被输送回模型
        dec_input = tf.expand_dims([predicted_id], 0)
    return result, sentence
# 恢复检查点目录 (checkpoint_dir) 中最新的检查点
checkpoint.restore(tf.train.latest_checkpoint(checkpoint_dir))
s = '百 花 争 艳 春 风 得 意'
result, sentence = evaluate(s)
print('Input: %s' % (sentence))
print('Predicted: {}'.format(result))

最后结果就是:

Input:  <start> 百 花 争 艳 春 风 得 意 <end> [2, 48, 8, 164, 76, 4, 5, 197, 50, 3]
Predicted: <start> 万 马 奔 腾 喜 气 福 多 <end> [2, 6, 28, 167, 58, 17, 33, 15, 113, 3]

6. 其他

带上注释才300行代码,去了注释估计也就200出头。但是,它却实现了一个完整的对春联的基本功能。

有一些知识点没有讲的太细,比如损失函数、优化器这些,我打算以后专项再讲测试工程师

其实,这个例子正统是tensorflow官网用于语言翻译的(原文链接),比如西班牙语翻译英语。

我此测试手机是否被监控处是尝试用于对春联,但是看效果也可以。

它也可以用于文言文翻译白话文,原理都是一样机器学习的,它支持输入输出的长度不一样。

github上传了dem人工智能专业o代码和8000条春联训练数据 hlwgy/co测试工程师uplets:自动对春联 (github.com)。

发表评论

提供最优质的资源集合

立即查看 了解详情