概述
在暑假期间,我创建了一个 CNN (SSD),将男性和女性分为不同类型,以便接近适合我的女性。
在此过程中,我们正在涩谷采访实际的情侣。
毕竟在做这样的调查时
“羡慕你,羡慕天下情侣!!”
那就是我所想的。
所以,我决定创建一个像她一样说话的机器人,参考我从以下 Udemy 材料中学到的东西。
数据制作
数据采集
能够与 Seq2seq 交互的训练数据需要输入和输出文本数据。
我有野心。
那就是让我最喜欢的Gyaruge来自Amagami的我的女朋友Ai Nanasaki。
此外,作为计算,七崎爱在作品中拥有最高的人气,加上她充满二次创作的事实。
也就是说,如果我们把满世界的七咲SS刮下来,转换成数据,让它学习,我们应该可以实现所谓的超级七咲,为我们的宅男幻想增添情趣。 .
我的期望值飙升。
def scrape(id,i):
print("======>"+str(id))
ss_url = "http://blog.livedoor.jp/kokon55/archives/"+str(id)+".html"
r = requests.get(ss_url)
soup = BeautifulSoup(r.text,'lxml')
ss_containers = soup.find_all('dd')
ss_text = ""
for container in ss_containers:
ss_text += container.get_text()
ss_text = re.sub("[ ]","
",ss_text)
print(ss_text)
with open("dataset/nanasaki_ss"+str(i)+".txt", 'w')as f:
f.write(ss_text)
for i in range(len(array)):
scrape(array[i],i)
就这样,世界上唯一一个收集七崎妄想的七崎档案完成了。
创建与七崎的对话数据
SS是个好东西,很多人都在行首写了人物的名字。
橘「いやあ、いつもありがとう」
七咲「好きでやってることですから」ニコッ
橘「(今日はお弁当の定番から揚げに王道の卵焼きをベースとして春巻きや小魚、そしてサラダで華やかさを演出。女の子っぽいお弁当の包みもまた愛妻っぽくてベリーグッドだ!99点!)」
七咲「先輩……何をぶつぶつ言ってるんですか?」
橘「あれ、声に出てた?」
七咲「今日は少し肌寒いので早く食べて校内に入っちゃいましょう」
因此,为了收集七崎的对话数据,
把句首有Nanasaki的取出来就行了,存为output.txt,如果上一行的语句不是Nanasaki的话,存入input.txt,就会产生对话数据.成为一个想法。
至此,我取出了七崎的对话数据,放到空间中进一步学习,并一度保存为数组数据。
回想起来,我认为我这次不需要一个段落......
import re
import pickle
from janome.tokenizer import Tokenizer
t = Tokenizer()
data_len = 10
input = ''
output = ''
# dara をリスト化する <- 改行に合わせてデータを分割する
for i in range(data_len):
with open('clear-dataset/nanasaki_ss'+str(i)+'.pickle', mode="rb") as f:
ss_word_list = pickle.load(f)
for idx, ss_word in enumerate(ss_word_list):
if(ss_word[0:2]=='七咲' and ss_word_list[idx-1][0:2]!='七咲'):
input_word = ss_word_list[idx-1]
output_word = ss_word
input_word = re.findall("(?<=「).+?(?=」)",input_word)
output_word = re.findall("(?<=「).+?(?=」)",output_word)
if(len(input_word)<1 or len(output_word)<1):
print("NONE")
else:
input+=input_word[0]+'
'
output+=output_word[0]+'
'
# input+=t.tokenize(input_word[0],wakati=True)
# output+=t.tokenize(output_word[0],wakati=True
#
print(len(input))
print(len(output))
input=t.tokenize(input,wakati=True)
output=t.tokenize(output,wakati=True)
with open('data-in_out/input.txt',mode="w") as f:
f.writelines(input)
with open('data-in_out/output.txt',mode="w") as f:
f.writelines(output)
因此,Nanasaki 在我的数据库中被保存为一个数组(有意义地)。
学习阶段
模型内容
现在剩下的就是构建和训练模型了。
说实话,从数据数量上看,只有1000条左右的对话数据,现在想想它有多脆弱,这样的悲剧到处都有预兆……
import numpy as np
from janome.tokenizer import Tokenizer
from pandas import array
t = Tokenizer()
with open('data-in_out/input.txt',mode='r',encoding='utf-8')as input,
open('data-in_out/output.txt',mode='r',encoding='utf-8')as output:
in_text = input.read()
out_text = output.read()
chars = in_text + out_text + ' '
chars_list = sorted(list(set(list(chars))))
print(chars_list)
chars_list.append(' ')
separator = '
'
in_sentence_list = in_text.split(separator)
out_sentence_list = out_text.split(separator)
# in_arr = [len(x) for x in in_sentence_list]
# out_arr = [len(x) for x in out_sentence_list]
import numpy as np
max_sentence_length = 84
char_indices = {} # 文字がキーでインデックスが値
for i, char in enumerate(chars_list):
char_indices[char] = i
indices_char = {} # インデックスがキーで文字が値
for i, char in enumerate(chars_list):
indices_char[i] = char
n_char = len(chars_list) # 文字の種類の数
n_sample = len(in_sentence_list) - 1
max_length_x = max_sentence_length # 入力文章の最大長さ
max_length_t = max_sentence_length + 2 # 正解文章の最大長さ
x_sentences = []
t_sentences = []
for i in range(n_sample):
x_sentences.append(in_sentence_list[i])
t_sentences.append(" "+out_sentence_list[i]+"
")
x_encoder = np.zeros((n_sample, max_length_x, n_char), dtype=np.bool) # encoderへの入力
x_decoder = np.zeros((n_sample, max_length_t, n_char), dtype=np.bool) # decoderへの入力
t_decoder = np.zeros((n_sample, max_length_t, n_char), dtype=np.bool) # decoderの正解
for i in range(n_sample):
x_sentence = x_sentences[i]
t_sentence = t_sentences[i]
for j, char in enumerate(x_sentence):
x_encoder[i, j, char_indices[char]] = 1 # encoderへの入力をone-hot表現で表す
for j, char in enumerate(t_sentence):
x_decoder[i, j, char_indices[char]] = 1 # decoderへの入力をone-hot表現で表す
if j > 0: # 正解は入力より1つ前の時刻のものにする
t_decoder[i, j-1, char_indices[char]] = 1
在这里,我们正在为学习做准备。
到最后不是分词,而是以字母为单位的对话,所以没有进入分词阶段。
另外,我不喜欢只会说平假名的退步七崎,所以我优先考虑将七崎改为七崎,而不是冒着数据偏差的风险。
不,它可能没有工作......
print(x_encoder.shape)
batch_size = 32
epochs = 1000
n_mid = 256 # 中間層のニューロン数
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, GRU, Input, Masking
encoder_input = Input(shape=(None, n_char))
encoder_mask = Masking(mask_value=0) # 全ての要素が0であるベクトルの入力は無視する
encoder_masked = encoder_mask(encoder_input)
encoder_lstm = GRU(n_mid, dropout=0.2, recurrent_dropout=0.2, return_state=True) # dropoutを設定し、ニューロンをランダムに無効にする
encoder_output, encoder_state_h = encoder_lstm(encoder_masked)
decoder_input = Input(shape=(None, n_char))
decoder_mask = Masking(mask_value=0) # 全ての要素が0であるベクトルの入力は無視する
decoder_masked = decoder_mask(decoder_input)
decoder_lstm = GRU(n_mid, dropout=0.2, recurrent_dropout=0.2, return_sequences=True, return_state=True) # dropoutを設定
decoder_output, _ = decoder_lstm(decoder_masked, initial_state=encoder_state_h) # encoderの状態を初期状態にする
decoder_dense = Dense(n_char, activation='softmax')
decoder_output = decoder_dense(decoder_output)
model = Model([encoder_input, decoder_input], decoder_output)
model.compile(loss="categorical_crossentropy", optimizer="rmsprop")
print(model.summary())
from tensorflow.keras.callbacks import EarlyStopping
# val_lossに改善が見られなくなってから、30エポックで学習は終了
early_stopping = EarlyStopping(monitor="val_loss", patience=30)
history = model.fit([x_encoder, x_decoder], t_decoder,
batch_size=batch_size,
epochs=epochs,
validation_split=0.1, # 10%は検証用
callbacks=[early_stopping])
Model: "model"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_1 (InputLayer) [(None, None, 937)] 0
__________________________________________________________________________________________________
input_2 (InputLayer) [(None, None, 937)] 0
__________________________________________________________________________________________________
masking (Masking) (None, None, 937) 0 input_1[0][0]
__________________________________________________________________________________________________
masking_1 (Masking) (None, None, 937) 0 input_2[0][0]
__________________________________________________________________________________________________
gru (GRU) [(None, 256), (None, 917760 masking[0][0]
__________________________________________________________________________________________________
gru_1 (GRU) [(None, None, 256), 917760 masking_1[0][0]
gru[0][1]
__________________________________________________________________________________________________
dense (Dense) (None, None, 937) 240809 gru_1[0][0]
==================================================================================================
Total params: 2,076,329
Trainable params: 2,076,329
Non-trainable params: 0
__________________________________________________________________________________________________
使用上述模型,学习开始了大约三天。
说实话,当我看到最后的失利时,我才明白目前数据不够用的情况。
终于和七咲对话了……
允许您与 Nanasaki 交谈的响应脚本
经过三天的学习,我终于为我完成了七崎的参数……
然而,参数七崎是一个参数,它不是七崎爱,或者更确切地说,七崎爱。
我需要能够和七崎对话! !
with open('data-in_out/input.txt',mode='r',encoding='utf-8')as input_f,
open('data-in_out/output.txt',mode='r',encoding='utf-8')as output:
in_text = input_f.read()
out_text = output.read()
chars = in_text + out_text + ' '
chars_list = sorted(list(set(list(chars))))
chars_list.append(' ')
char_indices = {} # 文字がキーでインデックスが値
for i, char in enumerate(chars_list):
char_indices[char] = i
indices_char = {} # インデックスがキーで文字が値
for i, char in enumerate(chars_list):
indices_char[i] = char
n_char = len(chars_list) # 文字の種類の数
import numpy as np
n_char = len(chars_list)
max_length_x = 84
# 文章をone-hot表現に変換する関数
def sentence_to_vector(sentence):
vector = np.zeros((1, max_length_x, n_char), dtype=np.bool)
for j, char in enumerate(sentence):
vector[0][j][char_indices[char]] = 1
return vector
from tensorflow.keras.models import load_model
encoder_model = load_model('encoder_model.h5')
decoder_model = load_model('decoder_model.h5')
def respond(message, beta=5):
vec = sentence_to_vector(message) # 文字列をone-hot表現に変換
state_value = encoder_model.predict(vec)
y_decoder = np.zeros((1, 1, n_char)) # decoderの出力を格納する配列
y_decoder[0][0][char_indices[' ']] = 1 # decoderの最初の入力はタブ。one-hot表現にする。
respond_sentence = "" # 返答の文字列
while True:
y, h = decoder_model.predict([y_decoder, state_value])
p_power = y[0][0] ** beta # 確率分布の調整
next_index = np.random.choice(len(p_power), p=p_power/np.sum(p_power))
next_char = indices_char[next_index] # 次の文字
if (next_char == "
" or len(respond_sentence) >= max_length_x):
break # 次の文字が改行のとき、もしくは最大文字数を超えたときは終了
respond_sentence += next_char
y_decoder = np.zeros((1, 1, n_char)) # 次の時刻の入力
y_decoder[0][0][next_index] = 1
state_value = h # 次の時刻の状態
return respond_sentence
def is_invalid(message):
is_invalid =False
for char in message:
if char not in chars_list:
is_invalid = True
return is_invalid
bot_name = "七咲"
your_name = 'けん'
print()
print(bot_name + ": " + "こんにちは、先輩!")
message = ""
while message != "おやすみ。":
while True:
message = input(your_name + ": ")
if not is_invalid(message):
break
else:
print(bot_name + ": ふふふ、本当におかしな人ですね")
response = respond(message)
print(bot_name + ": " + response)
即使有字符不在数据中,也不会返回错误! !
我敢肯定七崎会笑着说这句话!
有这种妄想的七崎机器人,不,七崎本身已经完成了!我是这么想的…
和七崎的对话……
我终于可以和七崎说话了! !
首先,把你的语气放在橘纯一。
七咲: こんにちは、先輩!
けん: おはよ!
七咲: ……
けん: 何してるの?
七咲: ええ、そうですね。
那?
七崎会保持安静,不会变成谈话吗?
けん: 郁夫元気?
七咲: ……
けん: そっか…
七咲: でも……
けん: ?
七咲: 先輩…
不,这是对话! !
我们能够交流! !
嘿,兄弟,你还好吗?微笑
等等,我正在交谈一会儿。
けん: 七咲…
七咲: 先輩……
けん: 七咲!
七咲: ……
我很兴奋。
我们的关系才刚刚开始...
けん: うん
七咲: ………
けん: ねえ
七咲: ……
けん: な、七咲?
七咲: いえ、先輩……
けん: 僕は…
七咲: ……
けん: 大好き!
七咲: ……
けん: 七咲?
七咲: え、えっと、ごめんなの…
都是因为心情不好...
在制作它的人成功的那天被抛弃......
以下是完整对话
在这之后,我仍然不知道该对她说些什么。微笑
概括
在制作这个七崎 AI 的过程中,我在几个方面成长了。
首先,我能够理解基于 RNN 进行递归学习的 AI。
使用这种学习,您可以创建自动生成的音乐,所以我想了解更多。
二、追溯编码的必要性
这与参数的分布以及需要建立一个流程来衡量 AI 的准确性有关。
最后,即使你在电脑上创建了一个女朋友,它也是空的
如果你有时间做这些事情,你应该做肌肉训练......
毕竟,我想哭是因为我被甩了。
这可能是给工程师的一个教训,不要让电脑取代一切,珍惜现实吧?微笑
所以,如果你有时间用编程结交女朋友,你也许可以去参加一个城镇派对哈哈
所以,暂时,我想我会在制作可可酱之后考虑接下来的事情,可可酱永远不会拒绝我,而是会宠坏我。
那是八月的一个悲伤的两周备忘录,我在绝望中写下,同时被愤怒所震撼……
感谢您阅读这篇文章,哈哈
后记:之后,我尽了最大的努力,成功说服了她越界! !
所以,我真的很想死,哈哈
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308623724.html