Spaces:
Configuration error
Configuration error
import numpy as np | |
import random | |
import json | |
import torch | |
import torch.nn as nn | |
from torch.utils.data import Dataset, DataLoader | |
from nltk_utils import bag_of_words, tokenize, stem | |
from model import NeuralNet | |
# Make sure you run this file as many times as it takes to get a low value for loss ~0.0004, so that gibberish words will not be misinterpreted | |
with open(r'C:\Users\vilsons\Documents\chatbot-deployment-main\flask chatbot\intents.json', 'r', encoding='utf-8') as f: | |
intents = json.load(f) | |
all_words = [] | |
tags = [] | |
xy = [] | |
# loop through each sentence in our intents patterns | |
for intent in intents['intents']: | |
tag = intent['tag'] | |
# add to tag list | |
tags.append(tag) | |
for pattern in intent['patterns']: | |
# tokenize each word in the sentence | |
w = tokenize(pattern) | |
# add to our words list | |
all_words.extend(w) | |
# add to xy pair | |
xy.append((w, tag)) | |
# stem and lower each word | |
ignore_words = ['?', '.', '!'] | |
all_words = [stem(w) for w in all_words if w not in ignore_words] | |
# remove duplicates and sort | |
all_words = sorted(set(all_words)) | |
tags = sorted(set(tags)) | |
print(len(xy), "patterns") | |
print(len(tags), "tags:", tags) | |
print(len(all_words), "unique stemmed words:", all_words) | |
# create training data | |
X_train = [] | |
y_train = [] | |
for (pattern_sentence, tag) in xy: | |
# X: bag of words for each pattern_sentence | |
bag = bag_of_words(pattern_sentence, all_words) | |
X_train.append(bag) | |
# y: PyTorch CrossEntropyLoss needs only class labels, not one-hot | |
label = tags.index(tag) | |
y_train.append(label) | |
X_train = np.array(X_train) | |
y_train = np.array(y_train) | |
# Hyper-parameters | |
num_epochs = 1000 | |
batch_size = 8 | |
learning_rate = 0.001 | |
input_size = len(X_train[0]) | |
hidden_size = 8 | |
output_size = len(tags) | |
print(input_size, output_size) | |
class ChatDataset(Dataset): | |
def __init__(self): | |
self.n_samples = len(X_train) | |
self.x_data = X_train | |
self.y_data = y_train | |
# support indexing such that dataset[i] can be used to get i-th sample | |
def __getitem__(self, index): | |
return self.x_data[index], self.y_data[index] | |
# we can call len(dataset) to return the size | |
def __len__(self): | |
return self.n_samples | |
dataset = ChatDataset() | |
train_loader = DataLoader(dataset=dataset,batch_size=batch_size,shuffle=True,num_workers=0) | |
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') | |
model = NeuralNet(input_size, hidden_size, output_size).to(device) | |
# Loss and optimizer | |
criterion = nn.CrossEntropyLoss() | |
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) | |
# Train the model | |
for epoch in range(num_epochs): | |
for (words, labels) in train_loader: | |
words = words.to(device) | |
labels = labels.to(dtype=torch.long).to(device) | |
# Forward pass | |
outputs = model(words) | |
# if y would be one-hot, we must apply | |
# labels = torch.max(labels, 1)[1] | |
loss = criterion(outputs, labels) | |
# Backward and optimize | |
optimizer.zero_grad() | |
loss.backward() | |
optimizer.step() | |
if (epoch+1) % 100 == 0: | |
print (f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}') | |
print(f'final loss: {loss.item():.4f}') | |
data = { | |
"model_state": model.state_dict(), | |
"input_size": input_size, | |
"hidden_size": hidden_size, | |
"output_size": output_size, | |
"all_words": all_words, | |
"tags": tags | |
} | |
FILE = "data.pth" | |
torch.save(data, FILE) | |
print(f'training complete. file saved to {FILE}') | |