In dieser Geschichte werde ich Schritt für Schritt ein LSTM-basiertes Sprachmodell für einen bestimmten Korpus erstellen. Verwendete Bibliotheken für Vorverarbeitung, neuronale Modelle usw. sind spaCy und Keras. Das Hauptziel besteht hier darin, eine einfache Suchmaschine für Sätze des Korpus zu erstellen, die die verborgenen LSTM-Zustände als Darstellungen verwendet.
Bitte beachten Sie, dass dieses kleine Tutorial vom Leser mindestens solide Grundlagen in Python und maschinellem Lernen erfordert, da ich mich hier eher auf den Codierungsteil konzentriert habe. Es handelt sich um ein Code-basiertes Tutorial, das davon ausgeht, dass der Leser bereits an ähnlichen Projekten gearbeitet hat.
Der Datensatz wird der Brown Corpus sein. Der Brown Corpus ist ein großer Korpus, der aus einer Million Wörtern besteht. Laut NLTK-Dokumentation struggle es das erste englische elektronische Korpus, das eine Million Wörter umfasste, und es wurde 1961 an der Brown College erstellt. Natural Language Toolkit oder NLTKist eine in Python geschriebene Plattform, die Bibliotheken, Korpora und Ressourcen für die Verarbeitung natürlicher Sprache bereitstellt. Ich werde die NLTK-Bibliothek und ihren braunen Korpus importieren.
# importing libraries
import numpy as np
from keras.utils import pad_sequences
import tensorflow as tf
import keras.backend as Okay# downloading nltk brown corpus
import nltk
from nltk.corpus import brown
nltk.obtain('brown')
nltk.obtain('universal_tagset')
Vorbereiten des Datensatzes
Hier werde ich jedem Wort im Datensatz eindeutige IDs zuweisen, beginnend bei 1, halte 0 für leere Stellen frei. Anschließend wird eine Zahl für die maximale Eingabegröße des Modells definiert.
Darüber hinaus ist es notwendig, eine Funktion zum Konvertieren von Satz-ID-Vektoren zu erstellen, die vom Modell verwendet werden können: string_to_model_input (Satz): 1. Hier ist die Eingabe ein String-Satz („Dies ist ein Satz“).
2. Erstellen Sie Wort-ID-Vektoren aus dem Satz ([3, 5, 8, 6, 1]).
3. Die Ausgabe erfolgt als Tupel aus 2 Vektoren: X Und Y mit Länge bei maximaler Eingabegröße. X sind die IDs mit Ausnahme des letzten Tokens ([3, 5, 8, 6, 0, 0, 0]). Y sind die IDs mit Ausnahme des ersten Tokens ([5, 8, 6, 1, 0, 0, 0]). Verwenden Sie 0, um leere Stellen zu füllen, falls vorhanden.
Am Ende die Funktion string_to_model_input wird auf alle Sätze im Korpus ausgeführt, um das zu erstellen X Und Y Eingabe für Trainingsmodell.
# tokensFromList is a perform that's created to create a Spacy Doc file for
# getting tokens particularly from listsimport spacy; nlp = spacy.load('en_core_web_sm')
def tokensFromList(words_):
doc = spacy.tokens.doc.Doc(
nlp.vocab, phrases=words_)
for title, proc in nlp.pipeline:
doc = proc(doc)
# return print([t for t in doc])
return doc
# Vocabulary class. It has 2 helpful capabilities for including sentences and including phrases.
# It additionally turns phrases to index and vice versa. It has phrase depend, num. of phrases and
# despatched., lengths of despatched and and so on.
class Vocabulary:
UNKNOWN = 0
def __init__(self, title):
self.title = title
self.word2index = {"UNKNOWN": self.UNKNOWN}
self.word2count = {}
self.index2word = {self.UNKNOWN: "UNKNOWN"}
self.num_words = 1
self.num_sentences = 0
self.longest_sentence = 0
self.sentence_lengths = []
def add_word(self, phrase):
if phrase not in self.word2index:
# First entry of phrase into vocabulary
self.word2index[word] = self.num_words
self.word2count[word] = 1
self.index2word[self.num_words] = phrase
self.num_words += 1
else:
# Phrase exists; enhance phrase depend
self.word2count[word] += 1
def add_sentence(self, sentence):
sentence_len = 0
for phrase in sentence:
sentence_len += 1
self.add_word(phrase.decrease())
self.sentence_lengths.append(sentence_len+1)
if sentence_len > self.longest_sentence:
# That is the longest sentence
self.longest_sentence = sentence_len
# Depend the variety of sentences
self.num_sentences += 1
def to_word(self, index):
return self.index2word[index]
def to_index(self, phrase):
return self.word2index[word]
# creating vocabulary brownCorpus
voc = Vocabulary('brownCorpus')
print(voc)
# including sentences and phrases and different properties of them to vocabulary
for despatched in brown.sents():
voc.add_sentence(despatched)sentence_lengths = voc.sentence_lengths
mean_sentence_length = np.imply(sentence_lengths)
deviation_sentence_length = np.std(sentence_lengths)
Hier können wir die Zahlen unseres Vokabulars ausdrucken, additionally dessen Verteilung und Statistik. Das Ergebnis des Druckens der Particulars sieht wie folgt aus:
print("Variety of Sentences:", voc.num_sentences)
print("Variety of Phrases:", voc.num_words)
print('Imply Sentence Size: {}nSentence Size Normal Deviation: {}n'
'Max Sentence Size: {}'.format(mean_sentence_length, deviation_sentence_length, voc.longest_sentence))
Variety of Sentences: 57340
Variety of Phrases: 49816
Imply Sentence Size: 21.250994070456922
Sentence Size Normal Deviation: 13.107004875007762
Max Sentence Size: 180
print('Token 4 corresponds to token:', voc.to_word(4))
print('Token "this" corresponds to index:', voc.to_index('this'))
Token 4 corresponds to token: grand
Token "this" corresponds to index: 79
Wir können ein wenig erkunden und einige Beispiele sehen:
# EXAMPLE AND EXPLORATION
i = 0
for phrase in vary(voc.num_words):
print(voc.to_word(phrase))
i = i+1
if i == 35:
break
# EXAMPLE AND EXPLORATION
corpus = ['this is the first sentence .',
'this is the second .',
'there is no sentence in this corpus longer than this one .',
'the dog is named patrick .']
print(corpus)
['this is the first sentence .', 'this is the second .', 'there is no sentence in this corpus longer than this one .', 'the dog is named patrick .']
# EXAMPLE AND EXPLORATION
sent_tkns = []
sent_idxs = []
for phrase in corpus[0].cut up(' '):
sent_tkns.append(phrase)
sent_idxs.append(voc.to_index(phrase))
print(sent_tkns)
print(sent_idxs)
['this', 'is', 'the', 'first', 'sentence', '.']
[79, 137, 1, 485, 3882, 25]
Der nächste Schritt besteht darin, Schlüsselkonzepte zuzuordnen. Wörter sind die Länge des Korpus. max_lengths ist die Länge jedes Satzes nach dem Auffüllen. Es folgt ein Funktionscode, der Wortsätze in ID-Sätze umwandelt und diese auffüllt. Danach, X_train Und y_train wird zugewiesen. Dieser Teil des Codes für die Vorverarbeitung wird durch die Konvertierung in NP-Arrays (Numpy) abgeschlossen. Sehen Sie sich den folgenden Codeausschnitt an:
dictOfIds = voc.index2word
phrases = record(dictOfIds)[-1] + 1
max_length = 14
# A FUNCTION THAT CONVERTS SENTENCE OF WORDS INTO SENTENCE OF IDS AND PAD THEM
def string_to_model_input(sents, maximam_longitudinem):
X,y = [],[]
X_temp, y_temp = [], []for phrase in sents:
X_temp.append(voc.to_index(phrase))
y_temp.append(voc.to_index(phrase))
# print(X_temp)
if voc.to_index(phrase) == 25: # 25 = id of "."
del X_temp[-1]
X.append(X_temp)
X_temp = []
del y_temp[0]
y.append(y_temp)
y_temp = []
if voc.to_index != 25 and len(X_temp) > 1: # simply added in case the final despatched of corpus shouldn't be endded with "."
del X_temp[-1]
X.append(X_temp)
del y_temp[0]
y.append(y_temp)
X = pad_sequences(X, padding = 'publish', maxlen=maximam_longitudinem)
y = pad_sequences(y, padding='publish', maxlen=maximam_longitudinem)
return tuple(X), tuple(y)
# ASSIGNING X_train ANDA y_train
brown_words = [x.lower() for x in brown.words()]
X_train,y_train = string_to_model_input(brown_words, max_length)
print("Size of brown_words", len(brown_words))
# CONVERTING THEM TO NP ARRAYS
X_train_arr = np.array(X_train)
y_train_arr = np.array(y_train)print(len(X_train_arr))
print(len(y_train_arr))
Size of brown_words 1161192
len(X_train_arr): 49346
len(y_train_arr): 49346
In diesem Teil werden wir ein Sprachmodell erstellen. Hier erfolgt die Erstellung des Keras-Funktionsmodells, wie im folgenden Code zu sehen ist. Bitte beachten Sie, dass der folgende Code Zellzustandsvektorfunktionen enthält.
from keras.utils import plot_model
from keras.fashions import Mannequin
from keras.layers import Enter
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dense, Activation, Flatten, Dropout, LSTM, Activation, Embeddingdeep_inputs = Enter(form=(max_length,))
embedding = Embedding(phrases, 150, input_length=max_length)(deep_inputs) # line A
# flatten = Flatten()(embedding)
lstm1 = LSTM(512, return_sequences=True)(embedding)
lstm2, state_s, state_c = LSTM(512, return_sequences=True, return_state=True)(lstm1)
hidden = Dense(phrases, activation='softmax')(lstm2)
mannequin = Mannequin(inputs = deep_inputs, outputs=hidden)
# summarize layers
print(mannequin.abstract())
# plot graph
Beachten Sie, dass ich verschiedene maximale Längen der Eingabe ausprobiert habe, von 120 bis 25 (mittlere Satzlänge), jedoch waren 35–40 diejenigen mit der höchsten Genauigkeit. Als Optimierer habe ich RMSprop (Root Imply Squared Propagation) verwendet. Der Grund ist einfach, denn es gilt als gute Wahl für RNNs.
RMSprop berechnet den Gradienten der Verlustfunktion in Bezug auf die Parameter des Modells und aktualisiert die Parameter in der entgegengesetzten Richtung des Gradienten, um den Verlust zu minimieren. (Deepchecks-Glossar)
LEARNING_RATE = 0.01
EPOCHS = 10 optimizer = tf.compat.v1.prepare.RMSPropOptimizer(LEARNING_RATE) # it's mentioned to be good selection for RNNs
# loss_fn = tf.keras.losses.SparseCategoricalCrossentropy()
mannequin.compile(optimizer=optimizer,
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
historical past = mannequin.match(X_train_arr,
y_train_arr,
epochs=EPOCHS,
batch_size=128,
verbose=1).historical past
Anschließend muss das Modell ordnungsgemäß gespeichert und geladen werden. Speichern Sie daher das Modell für die zukünftige Verwendung und das Laden.
# Save the whole mannequin as a SavedModel.
!mkdir -p saved_model
mannequin.save('saved_model/my_model') import pickle
mannequin.save('keras_next_word_modelFun.h5')
pickle.dump(historical past, open("historyFun.p", "wb"))
# load mannequin
from keras.fashions import load_model
mannequin = load_model('/content material/drive/MyDrive/keras_next_word_modelFun.h5', compile=False)
Zellstatusfunktion abrufen
Eine Funktion zum Abrufen des LSTM-Zellenstatus: get_cell_state (word_id_vector)
Eingang: Ein Eingabevektor, der zum Aufrufen des Modells verwendet werden kann.
Ausgang: Der Zellzustandsvektor der LSTM-Schicht.
def get_cell_state(word_id_vector):
get_output = Okay.perform([model.layers[0].enter],[model.layers[3].output[2]])
return get_output([word_id_vector])
# get_cell_state created completely for Person Enter
def get_cell_state_forUser(sents):
idVec, predInd = string_to_model_input_forUser(sents) # predInd is initially designed for predicting subsequent phrases capabilities, so ignore it right here
idVec_arr = np.array(idVec, dtype='int32') # ids is a listing of ids of a consumer inputed sentence. Right here I'm changing to np arrayreturn get_cell_state([idVec_arr])
Hier werde ich versuchen, das nächste Wort für den braunen Korpus und die Benutzereingabe vorherzusagen.
preprocess_corpus_forUser
Und string_to_model_input_forUser
sind Funktionen zur notwendigen Vorverarbeitung von Benutzereingaben.
def preprocess_corpus_forUser(corpus):
corpus_tokens = []
sentence_lengths = []
doc = nlp(str(corpus)) # Parse every line within the corpus
for despatched in doc.sents: # Loop over all of the sentences within the line
for tok in despatched: # Loop over all of the phrases in a sentence
corpus_tokens.append(tok.textual content.decrease())
return corpus_tokens
def string_to_model_input_forUser(sents):
X = []
X_temp = []
indexOfLast = 0
user_corpus = preprocess_corpus_forUser(sents) for phrase in user_corpus:
if phrase in voc.word2index:
X_temp.append(voc.to_index(phrase))
else:
X_temp.append(voc.word2index["UNKNOWN"])
# print(X_temp)
if X_temp[-1] == 25: # 25 = id of "."
X.append(X_temp)
X_temp = []
if voc.to_index != 25 and len(X_temp) > 1: # simply added in case the final despatched of corpus shouldn't be endded with "."
X.append(X_temp)
if len(X[-1]) < 15:
indexOfLast = len(X[-1]) - 1
else:
indexOfLast = 13
X = pad_sequences(X, padding = 'publish', maxlen=max_length)
# Xarray = np.array(X)
return tuple(X), indexOfLast
Vorhersage des nächsten Wortes (Funktionsmodell)
Vorhersagefunktionen zum Finden des Wortes mit der höchsten Wahrscheinlichkeit
# E X A M P L E
st = "The mannequin was superior. It is going to be subsequent huge "
p, l = string_to_model_input_forUser(st)
pred = mannequin.predict(p[-1])
print(pred.form)
WARNING:tensorflow:Mannequin was constructed with form (None, 14) for enter KerasTensor(type_spec=TensorSpec(form=(None, 14), dtype=tf.float32, title='input_2'), title='input_2', description="created by layer 'input_2'"), nevertheless it was known as on an enter with incompatible form (None, 1).
(14, 1, 49816)
# Discovering the best probabilty and its index. Additionally the variety of possibilities assigned.
def high_prob(vector, idLast):
max = 0
a, b, c = -1, -1, -1
leng = 0
for ii in vector[idLast]:
b+=1
c = -1
for iii in ii:
c+=1
leng += 1
if max < iii:
max = iii
second, third = b, c
else: proceed
return max, idLast, second, third, lengprint(high_prob(pred, 4))
(0.011349797, 4, 0, 33, 49816)
v, i, ii, iii, size = high_prob(pred, 5) # perform to seek out the best likelihood, its index, and size of the prediction vector
# print(pred[1][i][ii][iii]) # so 1st, 2nd and 4th index of 3d pr record is 0.09 which is the best one
# len(pr[1][3]) # the type of the record is like that --> 5*30 + 4*30 = 270
print("variety of phrases within the vocabulary: ", voc.num_words) # variety of phrases within the vocabulary
print("size of the prediction vector: ", size) # size of the prediction vector
variety of phrases within the vocabulary: 49816
size of the prediction vector: 49816
Aufruf der Vorhersagefunktion
A calling
Funktion zur Benutzereingabe und Vorhersage des nächsten Wortes. Man kann unendlich vorhersagen.
# a perform created for straightforward calling of a pos-tagger and make it work until you need it to
def calling():
z = "y"
whereas z == "y":
z = enter()
zz, idLast = string_to_model_input_forUser(z)
if len(zz) > 1:
zzz = mannequin.predict(zz[-1])
else:
zzz = mannequin.predict(zz)
v, i, ii, iii, size = high_prob(zzz, idLast)
predicted_word = voc.to_word(iii)
# x = enter(print("Go away empty if you don't want to proceed."))
X = enter()
if x != "":
calling()
else:
break
# return print(z, predicted_word, i, ii, iii, zzz)
return print(z, predicted_word)
calling() # ex: In the present day it was introduced that subsequent yr might be virus free. It sounds
In the present day it was introduced that subsequent yr might be virus free. It sounds nice, and yesterday, all my goals appeared so far-off, then got here
Go away empty if you don't want to proceed.In the present day it was introduced that subsequent yr might be virus free. It sounds nice, and yesterday, all my goals appeared so far-off, then got here on
KOSINUS-ÄHNLICHKEIT VON SÄTZEN FINDEN
Hier werde ich eine Funktion erstellen: cosine_similarity (a,b)
Eingang: 2 Vektoren
Ausgang: die Kosinusähnlichkeit der Vektoren
Dann werde ich damit fortfahren, ein Eingabefeld zum Lesen von 2 Sätzen zu erstellen. Fügen Sie es in eine Schleife ein, der Ausgang ist die leere Zeichenfolge. Dann erstelle ich Eingabevektoren aus den Sätzen und führe das Sprachmodell aus, um den LSTM-Zellenstatus zu erhalten (Aufruf get_cell_state Funktion). Der nächste Schritt besteht darin, die Ausgabevektoren für die Kosinusähnlichkeit zu verwenden und die Sätze und Ergebnisse auszudrucken.
# Be aware that spatial.distance.cosine computes the space, and never the similarity. So, you will need to subtract the worth from 1 to get the similarity.
from scipy import spatial
def cosine_similarity(a,b):
return 1 - spatial.distance.cosine(a, b)
# get_cell_state_forUser
def sim_of_2sents():
go = True
whereas go:
print("Please enter 2 sentences: ")
sent1 = enter()
sent2 = enter()
sent2vec1 = get_cell_state_forUser(sent1)
sent2vec2 = get_cell_state_forUser(sent2)
cos_similarity = cosine_similarity(sent2vec1, sent2vec2)
# print("Sentence I <--->", sent1)
# print("Sentence II <--->", sent2)
print("Cosine Similarity: ", cos_similarity)
# user_choice = enter(print("Go away empty if you don't want to proceed."))
user_choice = enter()
if user_choice != "":
sim_of_2sents()
else: break
sim_of_2sents()
Please enter 2 sentences:
In the present day it was introduced that subsequent yr might be virus free.
I hope peace will encounter the Earth and the cursed ones might be deleted.
Sentence I --- In the present day it was introduced that subsequent yr might be virus free.
Sentence II --- I hope peace will encounter the Earth and the cursed ones might be deleted.
Cosine Similarity: 0.9304618239402771
Go away empty if you don't want to proceed.
Ich werde AnnoyIndex zum Indizieren der Vektoren verwenden und Zellzustandsvektoren aus allen Sätzen im Brown-Korpus erstellen. Dann wird ein Eingabefeld zum Lesen der Suchwortfolge erstellt, es in eine Schleife gesetzt, der Ausgang ist eine leere Zeichenfolge. Anschließend wird aus der Suchwortfolge ein Zellzustandsvektor erstellt. Abschließend werden die 5 nächsten Nachbarn aus dem Index ermittelt und ausgedruckt.
Zellzustandsvektoren
ERHALTEN DES ZELLSTATUSVEKTORS ALLER SÄTZE DES BRAUNEN KORPULS UND ERHALTEN DER 5 NÄCHSTEN NACHBARN
# getting cell state vectors from brown corpus
# conv --> converter
def conv(despatched):
tete = np.expand_dims(despatched, axis=0)
return (get_cell_state(tete))# GETTING CELL STATE VECTOR OF ALL SENTENCES OF BROWN CORPU
corpora = []
for i in X_train_arr:
corpora.append(conv(i))
# INDEXING SENTENCES WITH ANNOY INDEX
IT WILL FIND 6 NEAREST NEIGHBOUR AS THE FIRST NEAREST ONE IS ITSELF
from annoy import AnnoyIndex
f = 512
t = AnnoyIndex(f, 'angular') # Size of merchandise vector that might be listed
for i in vary(0,len(X_train_arr)):
v = corpora[i][0][0]
t.add_item(i, v)
t.construct(10) # 10 timber
t.save('check.ann')
# ...
u = AnnoyIndex(f, 'angular')
u.load('check.ann') # tremendous quick, will simply mmap the file
print(u.get_nns_by_item(6, 6)) # will discover the 6 nearest neighbors
[6, 22804, 29305, 13425, 29290, 7]
# MINI SEARCH ENGINE FUNCTION FOR FINDING NN
def searchEngine():
sentBox, simSent = [], []
go = True
whereas go:
print("Please enter a sentence: ")
sent1 = enter()
sent2vec1 = get_cell_state_forUser(sent1)
simSent = u.get_nns_by_vector(sent2vec1[0][0], 5)
for sentId in simSent:
sentBox.append(TreebankWordDetokenizer().detokenize([voc.to_word(x) for x in X_train_arr[sentId]]))
print(sentBox)
user_choice = enter()
if user_choice != "":
searchEngine()
else: break
searchEngine()
Please enter a sentence:
I hope peace will encounter the Earth and the cursed ones might be deleted.
['mullins?? it was evident that mullins was the man to go UNKNOWN', 'of course, there were books about which nothing good could be said UNKNOWN', "if the crummy bastard could write!! that's how it should be UNKNOWN", 'he believed in being seen near the front lines and he was there UNKNOWN', 'and yet wilson knew that this place must go or he must go UNKNOWN']
print("thanks God it is completed")
thanks God it is completed
Vielen Dank fürs Lesen oder dass Sie zumindest davon profitiert haben. In Zukunft werde ich 5 kleine Geschichten veröffentlichen, die diese ganze Geschichte umfassen, und versuchen, sie anfängerfreundlicher zu gestalten. Bitte denken Sie daran, die Quelle anzugeben, damit ich mehr Follower gewinnen kann 🙂