Ich war an der automatischen Erzeugung von Sätzen mit KI interessiert, also habe ich versucht, Sätze mit Keras zu erzeugen. Was ich tat, war, die Tweets der Idolgruppe zu bekommen, sie lernen zu lassen und Sätze zu bilden.
Ich habe auf diesen Artikel verwiesen.
Versuchen Sie, mit Keras LSTM schnell Sätze zu generieren
Der Code ist im Grunde der gleiche, aber ich werde eine Notiz von Teilen hinterlassen, die allein in diesem Artikel etwas schwer zu verstehen waren.
Erstens ist die Erfassung von Trainingsdaten.
import json
import config
from requests_oauthlib import OAuth1Session
from time import sleep
import re
import emoji
from mongo_dao import MongoDAO
# Diesmal nicht verwendet
# Piktogramme entfernen
def remove_emoji(src_str):
return ''.join(c for c in src_str if c not in emoji.UNICODE_EMOJI)
# API-Schlüsseleinstellung (definiert in einer anderen Datei config.py)
CK = config.CONSUMER_KEY
CS = config.CONSUMER_SECRET
AT = config.ACCESS_TOKEN
ATS = config.ACCESS_TOKEN_SECRET
# Authentifizierungsprozess
twitter = OAuth1Session(CK, CS, AT, ATS)
# Endpunkt der Zeitleistenerfassung
url = "https://api.twitter.com/1.1/statuses/user_timeline.json"
# Erwerbskonto
necopla_menber = ['@yukino__NECOPLA', '@yurinaNECOPLA', '@riku_NECOPLA', '@miiNECOPLA', '@kaori_NECOPLA', '@sakuraNECOPLA', '@miriNECOPLA', '@renaNECOPLA']
# Parameterdefinition
params = {'q': '-filter:retweets',
'max_id': 0, #ID, um zu beginnen
'count': 200}
arg1:DB Name
arg2:Collection Name
mongo = MongoDAO("db", "necopla_tweets")
mongo.delete_many({})
regex_twitter_account = '@[0-9a-zA-Z_]+'
for menber in necopla_menber:
print(menber)
del params ['max_id'] # ID löschen, um die Erfassung zu starten
# Holen Sie sich die letzten 200 Tweets / Holen Sie sich Tweets, die älter als die in params ['max_id'] festgelegte ID sind, ab dem zweiten Mal
for j in range(100):
params['screen_name'] = menber
res = twitter.get(url, params=params)
if res.status_code == 200:
#API verbleibende Anzahl
limit = res.headers['x-rate-limit-remaining']
print("API remain: " + limit)
if limit == 1:
sleep(60*15)
n = 0
tweets = json.loads(res.text)
# Verlassen Sie die Schleife, wenn Sie keine Tweets von dem Konto erhalten, das Sie verarbeiten
if len(tweets) == 0:
break
# Per Tweet verarbeiten
for tweet in tweets:
# Registrieren Sie die gesamten Tweet-Daten
if not "RT @" in tweet['text'][0:4]:
mongo.insert_one({'tweet':re.sub(regex_twitter_account, '',tweet['text'].split('http')[0]).strip()})
if len(tweets) >= 1:
params['max_id'] = tweets[-1]['id']-1
Für die Trainingsdaten in diesem Artikel haben wir Tweets von der Gruppe "// Necopla //" erhalten. Die folgenden Elemente wurden aus den erfassten Tweets gelöscht. ・ Bildlink ・ Konto zum Zeitpunkt der Antwort
Die so zu trainierenden Daten werden in mongoDB abgelegt.
{"_id": ObjectId ("5e511a2ffac622266fb5801d"), "tweet": "Ich bin zum Karaoke gegangen, um Sololieder zu üben, aber ich habe mir normal die Kehle gebrochen"}
{"_id": ObjectId ("5e511a2ffac622266fb5801e"), "tweet": "Ich kann immer noch gehen"}
Die Quelle der MongoDB-Operation ist hier
Es ist fast das gleiche wie die Quelle, auf die ich mich bezog.
from __future__ import print_function
from keras.callbacks import LambdaCallback
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.layers import LSTM
from keras.optimizers import RMSprop
from keras.utils.data_utils import get_file
importiere matplotlib.pyplot als plt # add
import numpy as np
import random
import sys
import io
from mongo_dao import MongoDAO
mongo = MongoDAO("db", "necopla_tweets")
results = mongo.find()
text = ''
for result in results:
text += result['tweet']
chars = sorted(list(set(text)))
print('total chars:', len(chars))
char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))
cut the text in semi-redundant sequences of maxlen characters
maxlen = 3
step = 1
sentences = []
next_chars = []
for i in range(0, len(text) - maxlen, step):
sentences.append(text[i: i + maxlen])
next_chars.append(text[i + maxlen])
print('nb sequences:', len(sentences))
print('Vectorization...')
x = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool)
y = np.zeros((len(sentences), len(chars)), dtype=np.bool)
for i, sentence in enumerate(sentences):
for t, char in enumerate(sentence):
x[i, t, char_indices[char]] = 1
y[i, char_indices[next_chars[i]]] = 1
build the model: a single LSTM
print('Build model...')
model = Sequential()
model.add(LSTM(128, input_shape=(maxlen, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))
optimizer = RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
def sample(preds, temperature=1.0):
# helper function to sample an index from a probability array
preds = np.asarray(preds).astype('float64')
preds = np.log(preds) / temperature
exp_preds = np.exp(preds)
preds = exp_preds / np.sum(exp_preds)
probas = np.random.multinomial(1, preds, 1)
return np.argmax(probas)
# Am Ende der Epoche ausführen
def on_epoch_end(epoch, logs):
# Function invoked at end of each epoch. Prints generated text.
print()
print('----- Generating text after Epoch: %d' % epoch)
# start_index = random.randint(0, len(text) - maxlen - 1)
# start_index = 0 # Satzgenerierung aus "Alter Mann war alt" jedes Mal
für Diversity in [0.2]: # Diversity = nur 0.2
print('----- diversity:', diversity)
generated = ''
# sentence = text[start_index: start_index + maxlen]
Satz = 'Morgen'
generated += sentence
print('----- Generating with seed: "' + sentence + '"')
sys.stdout.write(generated)
for i in range(120):
x_pred = np.zeros((1, maxlen, len(chars)))
for t, char in enumerate(sentence):
x_pred[0, t, char_indices[char]] = 1.
preds = model.predict(x_pred, verbose=0)[0]
next_index = sample(preds, diversity)
next_char = indices_char[next_index]
generated += next_char
sentence = sentence[1:] + next_char
sys.stdout.write(next_char)
sys.stdout.flush()
print()
# Am Ende des Lernens ausführen
def on_train_end(logs):
print('----- saving model...')
model.save_weights("necopla_model" + 'w.hdf5')
model.save("necopla_model.hdf5")
print_callback = LambdaCallback(on_epoch_end=on_epoch_end,
on_train_end=on_train_end)
history = model.fit(x, y,
batch_size=128,
epochs=5,
callbacks=[print_callback])
Plot Training loss & Validation Loss
loss = history.history["loss"]
epochs = range(1, len(loss) + 1)
plt.plot(epochs, loss, "bo", label = "Training loss" )
plt.title("Training loss")
plt.legend()
plt.savefig("loss.png ")
plt.close()
Die Änderungen sind wie folgt.
Der erste Punkt ist, dass ich den Schmerz sah, dass die Trainingsdaten, die über einen ganzen Tag verschoben wurden, nicht gespeichert wurden, also habe ich einen Speicherprozess hinzugefügt. Der zweite Punkt war das Lernen mit 8 Zeichen, und als ich aus den Lerndaten einen Satz vorhersagte, der mit einem 3-stelligen Wort wie "Morgen" begann, funktionierte dies nicht gut. Seit ich Tweets gemacht habe, habe ich gelernt, mit kurzen Worten zu beginnen.
Der Lernprozess sieht so aus.
Epoch 1/5
663305/663305 [==============================] - 401s 605us/step - loss: 3.5554
----- Generating text after Epoch: 0
----- diversity: 0.2
----- Mit Samen erzeugen: "Morgen"
Morgen! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !!
Ich freue mich darauf, mit Dir zu arbeiten! !! !!
"Nekopura // Nekopura
# Nekopura
# Nekopura // Nekopura // Nekopura // Nekopura // Nekopura
# Nekopura
# Nekopura // Ich bevorzuge Nekopura
Epoch 2/5
663305/663305 [==============================] - 459s 693us/step - loss: 3.2893
----- Generating text after Epoch: 1
----- diversity: 0.2
----- Mit Samen erzeugen: "Morgen"
Morgen hier! !!
# Es ist eine Live-Aufführung von Nekopura!
# Es gibt eine Live-Aufführung von Nekopla! !!
# Vielen Dank für Nekopura! !! !!
# Vielen Dank für alle Informationen über Nekopura! !!
# Ich würde mich freuen, wenn es ein Katzenplastik gäbe ...
# Katze
Epoch 3/5
663305/663305 [==============================] - 492s 742us/step - loss: 3.2109
----- Generating text after Epoch: 2
----- diversity: 0.2
----- Mit Samen erzeugen: "Morgen"
Morgen hier! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Epoch 4/5
663305/663305 [==============================] - 501s 755us/step - loss: 3.1692
----- Generating text after Epoch: 3
----- diversity: 0.2
----- Mit Samen erzeugen: "Morgen"
Morgen hier! !!
# Nekopura
# Nekopura
# Ich bin froh, dass du zu den Katzenplastikleuten gekommen bist! !!
# Nekopura
# Nekopura
# Über Nekopura Mehr Mehr Mehr Mehr Mehr Mehr Mehr Mehr Mehr Mehr Mehr Mehr Mehr
Epoch 5/5
663305/663305 [==============================] - 490s 739us/step - loss: 3.1407
----- Generating text after Epoch: 4
----- diversity: 0.2
----- Mit Samen erzeugen: "Morgen"
Komm morgen zu mir! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Weiterbildung mit den gespeicherten Trainingsdaten Laden Sie einfach die Trainingsdaten, die nach dem Erstellen des Modells gespeichert wurden.
Der Code lautet hier
print('Build model...')
model = Sequential()
model.add(LSTM(128, input_shape=(maxlen, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))
optimizer = RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
model.load_weights("necopla_modelw.hdf5")
Als ich diesen Prozess durchführte, dachte ich über die Bedeutung jedes Codes nach. (langsam··.) Der Prozess von "on_epoch_end" wird am Ende der Lernepoche aufgerufen, aber hier werden zum Zeitpunkt des Epochenendes Sätze unter Verwendung der Lerndaten zu diesem Zeitpunkt erstellt. Daher können Sie beim Erstellen eines Tweets diesen Prozess grundsätzlich nachahmen.
Der Code lautet hier
def evaluate_tweet():
für Diversity in [0.2]: # Diversity = nur 0.2
print('----- diversity:', diversity)
generated = ''
Satz = 'Morgen'
generated += sentence
print('----- Generating with seed: "' + sentence + '"')
sameCharCount = 0
for i in range(120):
x_pred = np.zeros((1, maxlen, len(chars)))
for t, char in enumerate(sentence):
x_pred[0, t, char_indices[char]] = 1.
preds = model.predict(x_pred, verbose=0)[0]
next_index = sample(preds, diversity)
next_char = indices_char[next_index]
if next_char == generated[-1]:
sameCharCount += 1
if sameCharCount >= 3:
continue
elif sameCharCount != 0:
sameCharCount = 0
generated += next_char
sentence = sentence[1:] + next_char
return generated
for i in range(10):
tweet = evaluate_tweet()
print ('----------------' + str (i + 1) + 'th time ----------------')
print(tweet)
Wenn beim Erstellen eines Tweet-Satzes dasselbe Zeichen für 3 oder mehr Zeichen fortgesetzt wird, werden die Zeichen nicht verbunden. Tweets werden mit Sätzen erstellt, die mit den Worten "Tomorrow is" beginnen.
Das Ausgabeergebnis sieht folgendermaßen aus.
---------------- Erstes Mal ----------------
Morgen hier! !! !!
---------------- Zweites Mal ----------------
Morgen hier! !! !!
---------------- Drittes Mal ----------------
Ich frage mich, ob wir uns morgen treffen können! !! !!
---------------- 4. ----------------
Morgen hier! !! !!
---------------- 5. Mal ----------------
Morgen hier! !! !!
---------------- 6. Mal ----------------
Morgen hier! !! !!
---------------- 7. Mal ----------------
Morgen hier! !! !!
---------------- 8. Mal ----------------
Morgen hier! !! !!
---------------- 9. Mal ----------------
Morgen hier! !! !!
---------------- 10. Mal ----------------
Morgen hier! !! !!
Irgendwie konnte ich so etwas schaffen.
Ich habe das gleiche mit Chainer gemacht, aber mit Keras ist es definitiv immer einfacher. Das Ausgabeergebnis ist ein kurzer Satz, da die Anzahl der Lernvorgänge gering ist. Daher werde ich versuchen, das Ergebnis zu sehen, während ich zusätzliches Lernen durchführe.
Ich denke, dass die Lernmethode anders sein wird, wenn es sich um eine Methode des Lernens durch Teilen handelt, also werde ich das auch versuchen.
Recommended Posts