Spaces:
Running
Running
| # 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("/home/quangjimmy/chatbotmini/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")) | |
| # training initializer | |
| # 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]) | |
| #updated | |
| # Separate bag-of-words representations and output labels | |
| train_x = [item[0] for item in training] | |
| train_y = [item[1] for item in training] | |
| # Convert to NumPy arrays | |
| train_x = np.array(train_x) | |
| train_y = np.array(train_y) | |
| print("Training data created") | |
| # actual training | |
| # Create model - 3 layers. First layer 128 neurons, second layer 64 neurons and 3rd output layer contains number of neurons | |
| # equal to number of intents to predict output intent with softmax | |
| 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"]) | |
| #Updated (Removed decayIt seems like you're using a deprecated argument, decay, in the instantiation of the SGD optimizer from Keras. The decay argument has been deprecated in newer versions of Keras. To address this issue, | |
| # you can switch to using the newer format for specifying learning rate schedules in the optimizer.) | |
| sgd = SGD(learning_rate=0.01, momentum=0.9, nesterov=True) | |
| model.compile(loss="categorical_crossentropy", optimizer=sgd, metrics=["accuracy"]) | |
| # for choosing an optimal number of training epochs to avoid underfitting or overfitting use an early stopping callback to keras | |
| # based on either accuracy or loos monitoring. If the loss is being monitored, training comes to halt when there is an | |
| # increment observed in loss values. Or, If accuracy is being monitored, training comes to halt when there is decrement observed in accuracy values. | |
| # 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") | |