AIGC
叫“生成式人工智能”。想必“人工智能”咱们都很熟悉了,因而我想跟大伙儿聊聊这个“生成式”。
一、藏头诗展示
AIGC
中的GC
不是指“国粹”,是Generated Content
的缩写,表明生成内容。看下面这段文本:
掘井须到头 金刀剪紫绒 社日放歌还 区区趁适来
掘井须到南 金钿坠芳草 社会前年别 区区趁试期
掘井须到三 金钏色已歇 社客加笾食 区区趁试肠
掘井似翻罗 金钗已十年 社日穿痕月 区区趁试侣
怎么样?是不是有种《诗经》中“回旋往复,一唱三叹”的神韵。
其实,这每一行都是藏头诗。你仔细看看,榜首个字连起来便是:社区
。
上面的内容,是我用AI
生成的。
下面的内容,我将从原理到操作,讲一下怎么不调API
,自己动手写这么个同款AIGC
。
二、文本序列化
咱们先来做一个小游戏。往往小游戏里蕴含着大道理。
看这么一组数据:
序列1 | 序列2 | 序列3 | 序列4 | 序列5 | 序列6 |
---|---|---|---|---|---|
1 | 2 | 4 | 8 | 16 | ? |
请问,序列6
的值是多少?
答案是32
!解题思路:后一个数的值是前一个数的2倍。
我还能够搞更多的数据组,让你去探究。比如:
- 后一个数是前面所稀有之和。
- 后一个数是前面2个数的3倍减去22。
即使实在是找不到规则了。比如便是一串毫无规则的乱码。请问它的后边该是什么?将这串乱码再重复循环,也算是规则。
好了。到这儿我想给咱们引进一个概念叫做序列
。
文字范畴它有一个特点,那便是具有序列(sequence)特征。
我每天都访问社区,从这儿我能获取许多关于___的知识。
空白处该填什么呢?填“备孕”肯定不合适。你能够填“前端”、“人工智能”、“互联网技能”。
哎!你为什么会这么想?因为“社区”是一个IT
开发者社区。这句话前边的条件,会影响后边的判断,这便是序列的特点。
那位吃冰糕的先生说了,数字序列的规则我能看出来,可是文字的规则怎么看呢?
其实,咱们能够把文字转为数字。
序列1 | 序列2 | 序列3 | 序列4 | 序列5 | |
---|---|---|---|---|---|
文字 | 春 | 眠 | 不 | 觉 | 晓 |
数字 | 0 | 1 | 2 | 3 | 4 |
这样转换后,春晓
可用04
表明,它俩是等价的。
已然咱们能够分辨出高雅的诗句与一般的俗语,这说明它是有特征和规则的。
因而,咱们能够研究这些序列化后的文本,找找它们前后之间的联系和规则。
那么问题来了,有没有一个好的方案去处理这个问题呢?
三、循环神经网络
小弟我上一篇讲了CNN
卷积神经网络,它主要处理图画范畴的问题。可是,到了文字范畴,CNN
就怂了。因为它全靠凑数,没有时刻序列这条线。
为了处理具有顺序特征的数据,就呈现了循环神经网络
(Recurrent Neural Network)也便是RNN
。RNN的重点在R(Recurrent 循环)上。它能够将上一个时刻过程的状况,作为当前时刻过程的输入,从而捕捉到序列中的时刻依赖联系,并使用先前的状况来影响当前状况的更新。
我的话让你感觉很笼统,你也很想抽我。我发一张图给咱们缓解一下。
RNN
的结构图一般是这样的:
这张图解说了RNN
是怎么循环的。X
是输入,A
是神经单元,h
是输出。输入、输出都带着时刻t
。这个小单元,他就左手倒右手,转着圈玩儿。凡是经他手的数据,它都会记下一些特征,然后共享这些数据。因而,它就有了回忆。
今日咱们来到我的直播间……呸,来到我的专栏,我给咱们来点更生动的。
我的读者多是初学者。因而,咱们暂时以为
RNN
、LSTM
、GRU
都一样(就像包子、馅饼都是面食)。我不去讲它们的演变史(我厌烦技能课变为历史课)。
为了便于咱们理解,我特意画了下面这组动态图。
在某个序列t
时,将数据X
输入。这个输入数据的格式,后边会重点讲。在这儿,咱们要了解数据是依次导入的,也便是一条数据转一个单元。
再看下图,这儿演示了单元内部细节。Xt
是和ht-1
一同进入的。如果Xt
这个时刻代表“春眠不觉晓”的“眠”,那么ht-1
里肯定也包含了“春”的回忆信息。
下面是它的输出示意图。输入X
结合了ht-1
,又输出了新的ht
供后边使用。
RNN便是这样运作的。循环、递归、回忆传递是它的主题。
好了。道理就讲到这儿,再多说,你就要关页面了。下面开干,写代码!
四、实践项目:AI藏头诗
-
项目名称:使用
RNN
完成文本生成,写藏头诗。 -
运行环境:
Python 3.9
、TensorFlow 2.6
。 -
代码来源:
ChatGPT
。
已然本文讲AIGC
,那么咱们就要体现出它的妙用。我向ChatGPT咨询怎么完成我的主意,它给出了答案。
作为一个专业演员……人员。我负责地告知你,它的回答,过程明确、完全无误,在数据集完备的情况下,能够直接运行。
这说明了什么?
- 榜首,人工智能的初级使用并不悠远,也并非被置之不理无法企及。
- 第二,简单的需求真的是马路边上的东西,可是不为人所知,因为没有人去传播。
下面,我就拿老Chat的代码,依照我的思路,逐个解说并完成。
4.1 搭建神经网络
刚刚学了RNN,那么咱们就来组成一套循环神经网络。tensorflow
能够经过Sequential
来构建网络模型。
import tensorflow as tf
vocab_size = len(vocab)# 词汇表巨细
embedding_dim = 256 # 嵌入维度
rnn_units = 1024 # RNN单元数量
batch_size = 32 # 批次巨细
# 构建一个模型
model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, embedding_dim,
batch_input_shape=[batch_size, None]),
tf.keras.layers.GRU(rnn_units,
return_sequences=True,
stateful=True,
recurrent_initializer='glorot_uniform'),
tf.keras.layers.Dense(vocab_size)
])
上面这段代码是整个比如的核心部件。其上游代码为它供给弹药,下游的代码则分析它的产出。
4.1.1 网络结构图解
这个结构很简单,Sequential
中就三个层:Embedding
作为数据输入、GRU
作为神经单元处理、Dense
作为结果输出。
下图拿生成诗句举例,对每层做剖析。
中心是咱们熟悉的RNN
层,尽管它叫GRU
,但它归于RNN
宗族。代码中参数rnn_units
是神经单元的数量,这个咱们能够自己调。
咱们上面说那么热闹,其实只说了一个根本单元的工作。到真正干活时,是需求一堆单元来处理一条数据的(上图X
要衔接多个RNN
单元)。其他的参数你记住就能够了。
4.1.2 词汇表和嵌入层
下面说说词汇表和嵌入表。不管输入还是输出,咱们都要用到它。正是经过它们才将文本转为数字的。
你想让RNN自动生成,条件是它得有料。词汇库便是这个料。
假设咱们拿一堆诗句来练习模型,现在诗句也现已变为了数字。接着,咱们要做两件工作:
- 榜首:将数据传入模型,让它找规则(联想1、2、4、8那个游戏,规则是2倍联系)。
- 第二:给定一个开始值(藏头诗也是给一个字),让模型猜测后边的数字(32后边是64,64后边是128)。
为了完成上述内容。咱们界说了词汇表,用于文本转数字(眠->1)。
咱们又界说了嵌入表,让它对一个字进行多维度的描绘。0、1、2作为字的代号还能够。春眠是01
,春晓是04
。但关于文本生成来说,它的颗粒度太糙了。凭这,想要找出文学中深层次的内涵规则,根本不可能。还是得将这个字拆成粉末,转为几百维度的向量靠谱。
每个字的向量具体是多少,你肯定不知道。咱们正是想让神经网络自己去找(反向传播算法)。所以,咱们只下界说就行。因而,咱们看到代码中呈现了embedding_dim = 256
,这是一个有256个维度的嵌入向量。
4.1.3 Dense层的巨细
我看看还有啥值得说的。哦!Dense(vocab_size)
表明输出层的巨细是词汇表的巨细。意思便是说,它推测出来的下一个字,是词汇表中的某一个字。
读到这儿,你再回头看看上面的图,根本上就茅塞顿开了。
好了,大脑现已完成了,下面就让咱们去写无脑的代码吧。
4.2 处理练习数据集
已然想要生成藏头诗,那么首要得有一些诗句作为引子。
我自己攒了一些五言古诗+五言对联的语句。有多好不敢说,反正文绉绉的,大约15万条。
4.2.1 读入文件内容
首要读入这个文件,并生成词汇表。
# 读取文件
with open('poetry.txt', 'r', encoding='utf-8') as file:
text = file.read()
# 去除重复字符并排序
vocab = sorted(set(text))
# 创立字符到索引的映射字典
char2idx = {char: idx for idx, char in enumerate(vocab)}
poetry.txt
便是存放五言语句的文件。这个文件连同源码,我会上传到Github
,链接会附在文末。
建议咱们使用
jupyter
工具,能够逐渐履行,检查履行情况。
上面的代码,text
读取了文本内容,vocab
是文中一切呈现过的字,做了去重和排序处理。这便是咱们的词汇库。有了它,文字就能够变为数字了。
text = "春眠不觉晓 处处闻啼鸟 夜来风雨声 花落知多少 ……"
vocab = [' ', '一', '丁', '七', '万', '丈', '三', ……]
4.2.2 整理并序列化数据集
下一步,咱们开端组织练习用的数据集。
# 将文本切分为5字一组的数组
sentences = text.split(" ")
x_sequences = []
y_sequences = []
# 组织出练习集(输入+输出)
for sentence in sentences:
x = [char2idx[char] for char in sentence[:-1]]
y = [char2idx[char] for char in sentence[1:]]
x_sequences.append(x)
y_sequences.append(y)
# 转为tensor数据
datasets = tf.data.Dataset.from_tensor_slices((x_sequences, y_sequences))
# 将数据批次化
datasets = datasets.batch(batch_size, drop_remainder=True)
上面多是常规操作,我着重讲一下输入和输出的制作。
咱们希望模型能达到较高的认知水平。举个比如,咱们起一个头叫“春”,模型会生成下一个字是“眠”。以此类推,练习集的输入和输出总是会前后错开一个字。
这便是为什么输入sentence[:-1]
不要最后一个字,输出取sentence[1:]
不要榜首个字。咱们希望模型依照这样的思路去探究规则。
4.3 练习模型,保存权重
练习的代码其实很简单:
# 界说损失函数
def loss(labels, logits):
return tf.keras.losses.sparse_categorical_crossentropy(labels, logits, from_logits=True)
model.compile(optimizer='adam', loss=loss)
# 练习回调,模型保存途径
callback=tf.keras.callbacks.ModelCheckpoint(filepath="tf2/checkpoint", save_weights_only=True)
# 进行练习
model.fit(datasets, epochs=100, callbacks=[callback])
只要对模型做简单的装备,然后调用model.fit
就能够练习了。
-
model
是咱们一开端经过Sequential
创立的。 -
datasets
是上一步组的数据集。 -
epochs=100
是练习轮次。1个epochs表明把所稀有据跑一遍。 - 练习的最终模型将会保存为
tf2/checkpoint
。
这15万数据,关于一般电脑来说,压力很大。我设置的100epochs
才跑了40,就花费了3个多小时。模型的效果,便是文章开头的那样。
其实,咱们在学习的时分,能够适当地减少数据量或者epochs
来进步验证效率。
练习过程会有如下打印:
Epoch 1/100
4600/4600 [====================] - loss: 5.8752
Epoch 2/100
4600/4600 [====================] - loss: 5.4711
每个Epoch
结束,都会有权重保存下来。
4.4 验证模型,生成藏头诗
正常情况下,练习完了。你只要给模型起个头,后边它就会喋喋不休地输出。
# 给定1个字,变成5个字的办法
def generate_text(model, start_string):
num_generate = 4 # 生成的字符数
# 开始字序列化变为数字
input_eval = [char2idx[s] for s in start_string]
input_eval = tf.expand_dims(input_eval, 0)
text_generated = [] # 存放生成的字符
model.reset_states() # 清空本轮回忆
# 循环4次,每次生成一个字
for i in range(num_generate):
predictions = model(input_eval)
predictions = tf.squeeze(predictions, 0)
# 猜测最可信答案的序号
predicted_id = tf.random.categorical(predictions, num_samples=1)[-1, 0].numpy()
# 把猜测到的字作为输入,持续往下传递
input_eval = tf.expand_dims([predicted_id], 0)
# 依据编号找到字符,存起来
text_generated.append(idx2char[predicted_id])
return (start_string + ''.join(text_generated))
代码注释比较全面了。
-
start_string
是开始字符。便是藏头诗的榜首个字。 -
model
依然是咱们建立的那个RNN序列模型。如果要加载练习好权重,能够调用model.load_weights("tf2/checkpoint")
。
咱们实验一下效果:
generate_text(model, "请")
请以端溪润
generate_text(model, "嫁")
嫁来贤妻喜
generate_text(model, "给")
给园支遁隐
generate_text(model, "我")
我欲掣曳箭
咋说呢?咱们不是专业的诗人。可是,单看这个词汇与风格,唬人应该不成问题。
五、结语
说正经的,这用的是古诗数据,它会生成古诗。如果供给别的呢?
我希望本文能给诸位起一个头,让它四处散播,然后在各个行业与范畴,生根发芽。
整体项目源码地址(含数据集):github.com/hlwgy/jueji… 。
本文为稀土技能社区首发签约文章,30天内制止转载,30天后未获授权制止转载,侵权必究!