/train.py Secret
Last active
February 25, 2022 07:44
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# libraries | |
import random | |
from tensorflow.keras.optimizers import SGD | |
from keras.layers import Dense, Dropout | |
from keras.models import load_model | |
from keras.models import Sequential | |
import numpy as np | |
import pickle | |
import json | |
import nltk | |
from nltk.stem import WordNetLemmatizer | |
lemmatizer = WordNetLemmatizer() | |
nltk.download('omw-1.4') | |
nltk.download("punkt") | |
nltk.download("wordnet") | |
# init file | |
words = [] | |
classes = [] | |
documents = [] | |
ignore_words = ["?", "!"] | |
data_file = open("intents.json").read() | |
intents = json.loads(data_file) | |
# words | |
for intent in intents["intents"]: | |
for pattern in intent["patterns"]: | |
# take each word and tokenize it | |
w = nltk.word_tokenize(pattern) | |
words.extend(w) | |
# adding documents | |
documents.append((w, intent["tag"])) | |
# adding classes to our class list | |
if intent["tag"] not in classes: | |
classes.append(intent["tag"]) | |
# lemmatizer | |
words = [lemmatizer.lemmatize(w.lower()) for w in words if w not in ignore_words] | |
words = sorted(list(set(words))) | |
classes = sorted(list(set(classes))) | |
print(len(documents), "documents") | |
print(len(classes), "classes", classes) | |
print(len(words), "unique lemmatized words", words) | |
pickle.dump(words, open("words.pkl", "wb")) | |
pickle.dump(classes, open("classes.pkl", "wb")) | |
# initializing training data | |
training = [] | |
output_empty = [0] * len(classes) | |
for doc in documents: | |
# initializing bag of words | |
bag = [] | |
# list of tokenized words for the pattern | |
pattern_words = doc[0] | |
# lemmatize each word - create base word, in attempt to represent related words | |
pattern_words = [lemmatizer.lemmatize(word.lower()) for word in pattern_words] | |
# create our bag of words array with 1, if word match found in current pattern | |
for w in words: | |
bag.append(1) if w in pattern_words else bag.append(0) | |
# output is a '0' for each tag and '1' for current tag (for each pattern) | |
output_row = list(output_empty) | |
output_row[classes.index(doc[1])] = 1 | |
training.append([bag, output_row]) | |
# shuffle our features and turn into np.array | |
random.shuffle(training) | |
training = np.array(training) | |
# create train and test lists. X - patterns, Y - intents | |
train_x = list(training[:, 0]) | |
train_y = list(training[:, 1]) | |
print("Training data created") | |
# actual training | |
model = Sequential() | |
model.add(Dense(128, input_shape=(len(train_x[0]),), activation="relu")) | |
model.add(Dropout(0.5)) | |
model.add(Dense(64, activation="relu")) | |
model.add(Dropout(0.5)) | |
model.add(Dense(len(train_y[0]), activation="softmax")) | |
model.summary() | |
# Compile model. Stochastic gradient descent with Nesterov accelerated gradient gives good results for this model | |
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) | |
model.compile(loss="categorical_crossentropy", optimizer=sgd, metrics=["accuracy"]) | |
#Optional snippet - I have commented it as I did not use it. | |
# from keras import callbacks | |
# earlystopping = callbacks.EarlyStopping(monitor ="loss", mode ="min", patience = 5, restore_best_weights = True) | |
# callbacks =[earlystopping] | |
# fitting and saving the model | |
hist = model.fit(np.array(train_x), np.array(train_y), epochs=200, batch_size=5, verbose=1) | |
model.save("chatbot_model.h5", hist) | |
print("model created") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment